From aa75c69411019e19f0507ad525e191cee8533374 Mon Sep 17 00:00:00 2001 From: Mathias Markl Date: Sun, 9 Jul 2017 19:26:34 +0200 Subject: [PATCH] MuK Preview (muk_web_preview) 10.0.1.0.0 --- muk_web_preview/LICENSE | 619 + muk_web_preview/README.md | 7 + muk_web_preview/__init__.py | 20 + muk_web_preview/__manifest__.py | 61 + muk_web_preview/i18n/de.po | 96 + muk_web_preview/static/description/banner.png | Bin 0 -> 111993 bytes muk_web_preview/static/description/demo.gif | Bin 0 -> 419599 bytes muk_web_preview/static/description/icon.png | Bin 0 -> 26362 bytes muk_web_preview/static/description/index.html | 26 + .../static/description/screenshot.png | Bin 0 -> 117250 bytes .../static/lib/ViewerJS/compatibility.js | 577 + .../static/lib/ViewerJS/fonts/futura_book.eot | Bin 0 -> 113086 bytes .../static/lib/ViewerJS/fonts/futura_book.ttf | Bin 0 -> 112892 bytes .../lib/ViewerJS/fonts/futura_book.woff | Bin 0 -> 66744 bytes .../static/lib/ViewerJS/images/kogmbh.png | Bin 0 -> 2835 bytes .../static/lib/ViewerJS/images/nlnet.png | Bin 0 -> 5400 bytes .../static/lib/ViewerJS/images/texture.png | Bin 0 -> 2459 bytes .../images/toolbarButton-download.png | Bin 0 -> 512 bytes .../images/toolbarButton-fullscreen.png | Bin 0 -> 491 bytes .../images/toolbarButton-menuArrows.png | Bin 0 -> 237 bytes .../images/toolbarButton-pageDown.png | Bin 0 -> 353 bytes .../ViewerJS/images/toolbarButton-pageUp.png | Bin 0 -> 344 bytes .../images/toolbarButton-presentation.png | Bin 0 -> 4366 bytes .../ViewerJS/images/toolbarButton-zoomIn.png | Bin 0 -> 228 bytes .../ViewerJS/images/toolbarButton-zoomOut.png | Bin 0 -> 143 bytes .../static/lib/ViewerJS/index.html | 155 + muk_web_preview/static/lib/ViewerJS/local.css | 22 + muk_web_preview/static/lib/ViewerJS/pdf.js | 8052 ++++ .../static/lib/ViewerJS/pdf.worker.js | 39353 ++++++++++++++++ .../static/lib/ViewerJS/pdfjsversion.js | 1 + .../static/lib/ViewerJS/text_layer_builder.js | 419 + .../static/lib/ViewerJS/ui_utils.js | 394 + muk_web_preview/static/lib/ViewerJS/webodf.js | 936 + .../static/src/js/preview_dialog.js | 102 + .../static/src/js/preview_generator.js | 92 + .../static/src/js/preview_handler.js | 39 + .../static/src/js/preview_widgets.js | 78 + .../static/src/less/preview_content.less | 57 + .../static/src/less/preview_dialog.less | 134 + .../static/src/less/preview_widgets.less | 34 + .../static/src/xml/preview_content.xml | 66 + .../static/src/xml/preview_dialog.xml | 39 + .../static/src/xml/preview_widgets.xml | 29 + muk_web_preview/template/assets.xml | 32 + 44 files changed, 51440 insertions(+) create mode 100644 muk_web_preview/LICENSE create mode 100644 muk_web_preview/README.md create mode 100644 muk_web_preview/__init__.py create mode 100644 muk_web_preview/__manifest__.py create mode 100644 muk_web_preview/i18n/de.po create mode 100644 muk_web_preview/static/description/banner.png create mode 100644 muk_web_preview/static/description/demo.gif create mode 100644 muk_web_preview/static/description/icon.png create mode 100644 muk_web_preview/static/description/index.html create mode 100644 muk_web_preview/static/description/screenshot.png create mode 100644 muk_web_preview/static/lib/ViewerJS/compatibility.js create mode 100644 muk_web_preview/static/lib/ViewerJS/fonts/futura_book.eot create mode 100644 muk_web_preview/static/lib/ViewerJS/fonts/futura_book.ttf create mode 100644 muk_web_preview/static/lib/ViewerJS/fonts/futura_book.woff create mode 100644 muk_web_preview/static/lib/ViewerJS/images/kogmbh.png create mode 100644 muk_web_preview/static/lib/ViewerJS/images/nlnet.png create mode 100644 muk_web_preview/static/lib/ViewerJS/images/texture.png create mode 100644 muk_web_preview/static/lib/ViewerJS/images/toolbarButton-download.png create mode 100644 muk_web_preview/static/lib/ViewerJS/images/toolbarButton-fullscreen.png create mode 100644 muk_web_preview/static/lib/ViewerJS/images/toolbarButton-menuArrows.png create mode 100644 muk_web_preview/static/lib/ViewerJS/images/toolbarButton-pageDown.png create mode 100644 muk_web_preview/static/lib/ViewerJS/images/toolbarButton-pageUp.png create mode 100644 muk_web_preview/static/lib/ViewerJS/images/toolbarButton-presentation.png create mode 100644 muk_web_preview/static/lib/ViewerJS/images/toolbarButton-zoomIn.png create mode 100644 muk_web_preview/static/lib/ViewerJS/images/toolbarButton-zoomOut.png create mode 100644 muk_web_preview/static/lib/ViewerJS/index.html create mode 100644 muk_web_preview/static/lib/ViewerJS/local.css create mode 100644 muk_web_preview/static/lib/ViewerJS/pdf.js create mode 100644 muk_web_preview/static/lib/ViewerJS/pdf.worker.js create mode 100644 muk_web_preview/static/lib/ViewerJS/pdfjsversion.js create mode 100644 muk_web_preview/static/lib/ViewerJS/text_layer_builder.js create mode 100644 muk_web_preview/static/lib/ViewerJS/ui_utils.js create mode 100644 muk_web_preview/static/lib/ViewerJS/webodf.js create mode 100644 muk_web_preview/static/src/js/preview_dialog.js create mode 100644 muk_web_preview/static/src/js/preview_generator.js create mode 100644 muk_web_preview/static/src/js/preview_handler.js create mode 100644 muk_web_preview/static/src/js/preview_widgets.js create mode 100644 muk_web_preview/static/src/less/preview_content.less create mode 100644 muk_web_preview/static/src/less/preview_dialog.less create mode 100644 muk_web_preview/static/src/less/preview_widgets.less create mode 100644 muk_web_preview/static/src/xml/preview_content.xml create mode 100644 muk_web_preview/static/src/xml/preview_dialog.xml create mode 100644 muk_web_preview/static/src/xml/preview_widgets.xml create mode 100644 muk_web_preview/template/assets.xml diff --git a/muk_web_preview/LICENSE b/muk_web_preview/LICENSE new file mode 100644 index 0000000..faf7bf4 --- /dev/null +++ b/muk_web_preview/LICENSE @@ -0,0 +1,619 @@ + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 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 Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are 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. + + 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. + + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + + 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 Affero 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. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + + 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 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 work with which it is combined will remain governed by version +3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU Affero 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 Affero 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 Affero 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 Affero 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 \ No newline at end of file diff --git a/muk_web_preview/README.md b/muk_web_preview/README.md new file mode 100644 index 0000000..bfe7387 --- /dev/null +++ b/muk_web_preview/README.md @@ -0,0 +1,7 @@ +# MuK Preview + +Adds a button to the FieldBinaryFile form widget to preview the file content directly in the browser. +Currently the following file extensions are supported: + +* Portable Document Format (.pdf) +* Open Document (.odt, .odp, .ods, .otp) \ No newline at end of file diff --git a/muk_web_preview/__init__.py b/muk_web_preview/__init__.py new file mode 100644 index 0000000..48ccf85 --- /dev/null +++ b/muk_web_preview/__init__.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- + +################################################################################### +# +# Copyright (C) 2017 MuK IT GmbH +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero 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 Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +################################################################################### diff --git a/muk_web_preview/__manifest__.py b/muk_web_preview/__manifest__.py new file mode 100644 index 0000000..bd868c0 --- /dev/null +++ b/muk_web_preview/__manifest__.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- + +################################################################################### +# +# Copyright (C) 2017 MuK IT GmbH +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero 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 Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +################################################################################### + +{ + "name": "MuK Preview", + "summary": """File Preview Dialog""", + "description": """ + Adds a button to the FieldBinaryFile form widget to + preview the file content directly in the browser. + Currently the following file extensions are supported: + - Portable Document Format (.pdf) + - Open Document (.odt, .odp, .ods, .otp) + """, + "version": "10.0.1.0.0", + "category": "Extra Tools", + "license": "AGPL-3", + "website": "http://www.mukit.at", + "author": "MuK IT", + "contributors": [ + "Mathias Markl ", + ], + "depends": [ + "base", + ], + "data": [ + "template/assets.xml", + ], + "demo": [ + ], + "qweb": [ + "static/src/xml/*.xml", + ], + "images": [ + 'static/description/banner.png' + ], + "external_dependencies": { + "python": [], + "bin": [], + }, + "application": False, + "installable": True, + +} \ No newline at end of file diff --git a/muk_web_preview/i18n/de.po b/muk_web_preview/i18n/de.po new file mode 100644 index 0000000..80e0d7a --- /dev/null +++ b/muk_web_preview/i18n/de.po @@ -0,0 +1,96 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * muk_web_preview +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-07-08 09:21+0000\n" +"PO-Revision-Date: 2017-07-08 11:29+0200\n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: \n" +"Language: de\n" +"X-Generator: Poedit 2.0.2\n" + +#. module: muk_web_preview +#. openerp-web +#: code:addons/muk_web_preview/static/src/js/preview_widgets.js:67 +#: code:addons/muk_web_preview/static/src/xml/preview_content.xml:62 +#, python-format +msgid "Download" +msgstr "Herunterladen" + +#. module: muk_web_preview +#. openerp-web +#: code:addons/muk_web_preview/static/src/xml/preview_content.xml:55 +#, python-format +msgid "Extension:" +msgstr "Dateiendung:" + +#. module: muk_web_preview +#. openerp-web +#: code:addons/muk_web_preview/static/src/xml/preview_content.xml:47 +#, python-format +msgid "Filename:" +msgstr "Dateiname:" + +#. module: muk_web_preview +#. openerp-web +#: code:addons/muk_web_preview/static/src/xml/preview_content.xml:36 +#, python-format +msgid "Odoo App Store" +msgstr "Odoo App Store" + +#. module: muk_web_preview +#. openerp-web +#: code:addons/muk_web_preview/static/src/xml/preview_dialog.xml:34 +#, python-format +msgid "Ok" +msgstr "Ok" + +#. module: muk_web_preview +#. openerp-web +#: code:addons/muk_web_preview/static/src/js/preview_dialog.js:38 +#, python-format +msgid "Preview" +msgstr "Vorschau" + +#. module: muk_web_preview +#. openerp-web +#: code:addons/muk_web_preview/static/src/xml/preview_content.xml:34 +#, python-format +msgid "This file type is currently not supported. By installing further extension via the" +msgstr "Die Dateiendung wird im Moment nicht unterstützt. Durch das installieren von Erweiterungen aus dem" + +#. module: muk_web_preview +#. openerp-web +#: code:addons/muk_web_preview/static/src/xml/preview_content.xml:51 +#, python-format +msgid "Type:" +msgstr "Dateityp:" + +#. module: muk_web_preview +#. openerp-web +#: code:addons/muk_web_preview/static/src/js/preview_generator.js:81 +#, python-format +msgid "Unknown" +msgstr "Unbekannt" + +#. module: muk_web_preview +#. openerp-web +#: code:addons/muk_web_preview/static/src/xml/preview_content.xml:30 +#, python-format +msgid "Unsupported File Extension" +msgstr "Unbekannte Dateiendung" + +#. module: muk_web_preview +#. openerp-web +#: code:addons/muk_web_preview/static/src/xml/preview_content.xml:36 +#, python-format +msgid "it is possible to improve the Preview." +msgstr "ist es möglich zusätzliche Dateitypen in der Vorschau anzuzeigen." diff --git a/muk_web_preview/static/description/banner.png b/muk_web_preview/static/description/banner.png new file mode 100644 index 0000000000000000000000000000000000000000..71a4ba75bd6203d89e4335443bc45c1ec4d31aa1 GIT binary patch literal 111993 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�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 literal 0 HcmV?d00001 diff --git a/muk_web_preview/static/description/demo.gif b/muk_web_preview/static/description/demo.gif new file mode 100644 index 0000000000000000000000000000000000000000..35e24643caf823a111cd945407cbb72923b7cc1f GIT binary patch literal 419599 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≻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 KmGKw>0RTG+?@6!# literal 0 HcmV?d00001 diff --git a/muk_web_preview/static/description/icon.png b/muk_web_preview/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..258d4a37f58190196c624024bd80863912b6b74a GIT binary patch literal 26362 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

}0MfY{0GbLC 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 +

+

Preview Dialog

+

Preview your files directly in Odoo.

+

MuK IT GmbH , www.mukit.at

+
+ +
+
+ + +
+
+
+

Overview

+

+ Adds a button to the FieldBinaryFile form widget to preview the file content directly in the browser. + Currently the following file extensions are supported: +

+

+ Portable Document Format (.pdf)
+ Open Document (.odt, .odp, .ods, .otp)
+

+
+
+
\ No newline at end of file diff --git a/muk_web_preview/static/description/screenshot.png b/muk_web_preview/static/description/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..551dc10a2ca96b90aed31ccdffa009a5ad10def3 GIT binary patch literal 117250 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°n?#TFUH6(`yW)$WB2<`C3uA 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 2, d2 = ((b1 & 3) << 4) | (b2 >> 4); + var d3 = i + 1 < n ? ((b2 & 0xF) << 2) | (b3 >> 6) : 64; + var d4 = i + 2 < n ? (b3 & 0x3F) : 64; + buffer += (digits.charAt(d1) + digits.charAt(d2) + + digits.charAt(d3) + digits.charAt(d4)); + } + return buffer; + }; +})(); + +// window.atob (base64 encode function)? +// Support: IE<10 +(function checkWindowAtobCompatibility() { + if ('atob' in window) { + return; + } + + // https://github.com/davidchambers/Base64.js + var digits = + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; + window.atob = function (input) { + input = input.replace(/=+$/, ''); + if (input.length % 4 === 1) { + throw new Error('bad atob input'); + } + for ( + // initialize result and counters + var bc = 0, bs, buffer, idx = 0, output = ''; + // get next character + buffer = input.charAt(idx++); + // character found in table? + // initialize bit storage and add its ascii value + ~buffer && (bs = bc % 4 ? bs * 64 + buffer : buffer, + // and if not first of each 4 characters, + // convert the first 8 bits to one ascii character + bc++ % 4) ? output += String.fromCharCode(255 & bs >> (-2 * bc & 6)) : 0 + ) { + // try to find character in table (0-63, not found => -1) + buffer = digits.indexOf(buffer); + } + return output; + }; +})(); + +// Function.prototype.bind? +// Support: Android<4.0, iOS<6.0 +(function checkFunctionPrototypeBindCompatibility() { + if (typeof Function.prototype.bind !== 'undefined') { + return; + } + + Function.prototype.bind = function functionPrototypeBind(obj) { + var fn = this, headArgs = Array.prototype.slice.call(arguments, 1); + var bound = function functionPrototypeBindBound() { + var args = headArgs.concat(Array.prototype.slice.call(arguments)); + return fn.apply(obj, args); + }; + return bound; + }; +})(); + +// HTMLElement dataset property +// Support: IE<11, Safari<5.1, Android<4.0 +(function checkDatasetProperty() { + var div = document.createElement('div'); + if ('dataset' in div) { + return; // dataset property exists + } + + Object.defineProperty(HTMLElement.prototype, 'dataset', { + get: function() { + if (this._dataset) { + return this._dataset; + } + + var dataset = {}; + for (var j = 0, jj = this.attributes.length; j < jj; j++) { + var attribute = this.attributes[j]; + if (attribute.name.substring(0, 5) !== 'data-') { + continue; + } + var key = attribute.name.substring(5).replace(/\-([a-z])/g, + function(all, ch) { + return ch.toUpperCase(); + }); + dataset[key] = attribute.value; + } + + Object.defineProperty(this, '_dataset', { + value: dataset, + writable: false, + enumerable: false + }); + return dataset; + }, + enumerable: true + }); +})(); + +// HTMLElement classList property +// Support: IE<10, Android<4.0, iOS<5.0 +(function checkClassListProperty() { + var div = document.createElement('div'); + if ('classList' in div) { + return; // classList property exists + } + + function changeList(element, itemName, add, remove) { + var s = element.className || ''; + var list = s.split(/\s+/g); + if (list[0] === '') { + list.shift(); + } + var index = list.indexOf(itemName); + if (index < 0 && add) { + list.push(itemName); + } + if (index >= 0 && remove) { + list.splice(index, 1); + } + element.className = list.join(' '); + return (index >= 0); + } + + var classListPrototype = { + add: function(name) { + changeList(this.element, name, true, false); + }, + contains: function(name) { + return changeList(this.element, name, false, false); + }, + remove: function(name) { + changeList(this.element, name, false, true); + }, + toggle: function(name) { + changeList(this.element, name, true, true); + } + }; + + Object.defineProperty(HTMLElement.prototype, 'classList', { + get: function() { + if (this._classList) { + return this._classList; + } + + var classList = Object.create(classListPrototype, { + element: { + value: this, + writable: false, + enumerable: true + } + }); + Object.defineProperty(this, '_classList', { + value: classList, + writable: false, + enumerable: false + }); + return classList; + }, + enumerable: true + }); +})(); + +// Check console compatibility +// In older IE versions the console object is not available +// unless console is open. +// Support: IE<10 +(function checkConsoleCompatibility() { + if (!('console' in window)) { + window.console = { + log: function() {}, + error: function() {}, + warn: function() {} + }; + } else if (!('bind' in console.log)) { + // native functions in IE9 might not have bind + console.log = (function(fn) { + return function(msg) { return fn(msg); }; + })(console.log); + console.error = (function(fn) { + return function(msg) { return fn(msg); }; + })(console.error); + console.warn = (function(fn) { + return function(msg) { return fn(msg); }; + })(console.warn); + } +})(); + +// Check onclick compatibility in Opera +// Support: Opera<15 +(function checkOnClickCompatibility() { + // workaround for reported Opera bug DSK-354448: + // onclick fires on disabled buttons with opaque content + function ignoreIfTargetDisabled(event) { + if (isDisabled(event.target)) { + event.stopPropagation(); + } + } + function isDisabled(node) { + return node.disabled || (node.parentNode && isDisabled(node.parentNode)); + } + if (navigator.userAgent.indexOf('Opera') !== -1) { + // use browser detection since we cannot feature-check this bug + document.addEventListener('click', ignoreIfTargetDisabled, true); + } +})(); + +// Checks if possible to use URL.createObjectURL() +// Support: IE +(function checkOnBlobSupport() { + // sometimes IE loosing the data created with createObjectURL(), see #3977 + if (navigator.userAgent.indexOf('Trident') >= 0) { + PDFJS.disableCreateObjectURL = true; + } +})(); + +// Checks if navigator.language is supported +(function checkNavigatorLanguage() { + if ('language' in navigator) { + return; + } + PDFJS.locale = navigator.userLanguage || 'en-US'; +})(); + +(function checkRangeRequests() { + // Safari has issues with cached range requests see: + // https://github.com/mozilla/pdf.js/issues/3260 + // Last tested with version 6.0.4. + // Support: Safari 6.0+ + var isSafari = Object.prototype.toString.call( + window.HTMLElement).indexOf('Constructor') > 0; + + // Older versions of Android (pre 3.0) has issues with range requests, see: + // https://github.com/mozilla/pdf.js/issues/3381. + // Make sure that we only match webkit-based Android browsers, + // since Firefox/Fennec works as expected. + // Support: Android<3.0 + var regex = /Android\s[0-2][^\d]/; + var isOldAndroid = regex.test(navigator.userAgent); + + // Range requests are broken in Chrome 39 and 40, https://crbug.com/442318 + var isChromeWithRangeBug = /Chrome\/(39|40)\./.test(navigator.userAgent); + + if (isSafari || isOldAndroid || isChromeWithRangeBug) { + PDFJS.disableRange = true; + PDFJS.disableStream = true; + } +})(); + +// Check if the browser supports manipulation of the history. +// Support: IE<10, Android<4.2 +(function checkHistoryManipulation() { + // Android 2.x has so buggy pushState support that it was removed in + // Android 3.0 and restored as late as in Android 4.2. + // Support: Android 2.x + if (!history.pushState || navigator.userAgent.indexOf('Android 2.') >= 0) { + PDFJS.disableHistory = true; + } +})(); + +// Support: IE<11, Chrome<21, Android<4.4, Safari<6 +(function checkSetPresenceInImageData() { + // IE < 11 will use window.CanvasPixelArray which lacks set function. + if (window.CanvasPixelArray) { + if (typeof window.CanvasPixelArray.prototype.set !== 'function') { + window.CanvasPixelArray.prototype.set = function(arr) { + for (var i = 0, ii = this.length; i < ii; i++) { + this[i] = arr[i]; + } + }; + } + } else { + // Old Chrome and Android use an inaccessible CanvasPixelArray prototype. + // Because we cannot feature detect it, we rely on user agent parsing. + var polyfill = false, versionMatch; + if (navigator.userAgent.indexOf('Chrom') >= 0) { + versionMatch = navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./); + // Chrome < 21 lacks the set function. + polyfill = versionMatch && parseInt(versionMatch[2]) < 21; + } else if (navigator.userAgent.indexOf('Android') >= 0) { + // Android < 4.4 lacks the set function. + // Android >= 4.4 will contain Chrome in the user agent, + // thus pass the Chrome check above and not reach this block. + polyfill = /Android\s[0-4][^\d]/g.test(navigator.userAgent); + } else if (navigator.userAgent.indexOf('Safari') >= 0) { + versionMatch = navigator.userAgent. + match(/Version\/([0-9]+)\.([0-9]+)\.([0-9]+) Safari\//); + // Safari < 6 lacks the set function. + polyfill = versionMatch && parseInt(versionMatch[1]) < 6; + } + + if (polyfill) { + var contextPrototype = window.CanvasRenderingContext2D.prototype; + contextPrototype._createImageData = contextPrototype.createImageData; + contextPrototype.createImageData = function(w, h) { + var imageData = this._createImageData(w, h); + imageData.data.set = function(arr) { + for (var i = 0, ii = this.length; i < ii; i++) { + this[i] = arr[i]; + } + }; + return imageData; + }; + } + } +})(); + +// Support: IE<10, Android<4.0, iOS +(function checkRequestAnimationFrame() { + function fakeRequestAnimationFrame(callback) { + window.setTimeout(callback, 20); + } + + var isIOS = /(iPad|iPhone|iPod)/g.test(navigator.userAgent); + if (isIOS) { + // requestAnimationFrame on iOS is broken, replacing with fake one. + window.requestAnimationFrame = fakeRequestAnimationFrame; + return; + } + if ('requestAnimationFrame' in window) { + return; + } + window.requestAnimationFrame = + window.mozRequestAnimationFrame || + window.webkitRequestAnimationFrame || + fakeRequestAnimationFrame; +})(); + +(function checkCanvasSizeLimitation() { + var isIOS = /(iPad|iPhone|iPod)/g.test(navigator.userAgent); + var isAndroid = /Android/g.test(navigator.userAgent); + if (isIOS || isAndroid) { + // 5MP + PDFJS.maxCanvasPixels = 5242880; + } +})(); + +// Disable fullscreen support for certain problematic configurations. +// Support: IE11+ (when embedded). +(function checkFullscreenSupport() { + var isEmbeddedIE = (navigator.userAgent.indexOf('Trident') >= 0 && + window.parent !== window); + if (isEmbeddedIE) { + PDFJS.disableFullscreen = true; + } +})(); diff --git a/muk_web_preview/static/lib/ViewerJS/fonts/futura_book.eot b/muk_web_preview/static/lib/ViewerJS/fonts/futura_book.eot new file mode 100644 index 0000000000000000000000000000000000000000..9103f6ee42a377f6a7539143e6371d29bdfc6854 GIT binary patch literal 113086 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

KFgdSVFw1%^<>_iqB-@Lb!3?7js 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 F{|BpmL2m#6 literal 0 HcmV?d00001 diff --git a/muk_web_preview/static/lib/ViewerJS/fonts/futura_book.ttf b/muk_web_preview/static/lib/ViewerJS/fonts/futura_book.ttf new file mode 100644 index 0000000000000000000000000000000000000000..2290fb7b6bf6ecc239d7c8521adcc722214d2dcd GIT binary patch literal 112892 zcmb@v34BylmOp;)yKkv|O|404Nu?^OY*pDQ637#hKu92pNaKRCyCP*00%0*aY9k6L zjiQZ6M@T{v0-b-aGx#yncdlnEz2$|p)i#&DnuAjMS)1z$&|MK4uVqEpthYAqVDG^@v4SZ|IwbHlO6c`D@{P&%KLREtbmGwsf% z#-@hli&utbEWT%Pbn)%08a{Z{)$JYv9}W!0V-Z(KG1v8sXW1n&I~{_+~Yn z(FD&1xGuf(-SAumkGror68mcod}{`ry9!3NTpr<_Fgp*7J|7-eUM+UcO5l#$VO&e$ z`%Nep?p*|TE`qaW!(AKTwN$=BZ2l9kkvl$`cGQV_Q4f0vO<{MT8T)qGwSXcQp2ZYp0^QC<$h{hA-p` z(GKzi+;u11$&Ge1NoY0s1B{~)EkW=lgkE7D5HBvdKo(16(ZZeFq6_4<+=bk2Tga^! z$ikiEmJ8%&`!(FnJIPH8c5*jeAUEzL3wDwpT_E#!k{i+%ayM)t^WbHkM6RDZmAhUd zbElH)Br-=Lv+K5Sv*D$mt*gC}tJ^~A9$;%{1-RN9Nv+7v3Xqza8@U>Z%-l$3NTgaK zRh6VtBGZ3Grb$Hn6{(QO)G0H#sT;|Z8KnFg68ROGB#}~ylt`plB1OLLK(enPS-~w_)&-K)&jvFWa=|Sm z_y8-O$jk_EnF~p#$YumcAoUt9u!Z>H#lMB5`?hfD7f5

w|gvwh-R~Y??Q~r7a|B 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 literal 0 HcmV?d00001 diff --git a/muk_web_preview/static/lib/ViewerJS/fonts/futura_book.woff b/muk_web_preview/static/lib/ViewerJS/fonts/futura_book.woff new file mode 100644 index 0000000000000000000000000000000000000000..1f340b4d0260cc9fa5ed74d7496e02f4beff0d8d GIT binary patch literal 66744 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 O5r8?-l2B*lk?>!&x?|k{ literal 0 HcmV?d00001 diff --git a/muk_web_preview/static/lib/ViewerJS/images/toolbarButton-download.png b/muk_web_preview/static/lib/ViewerJS/images/toolbarButton-download.png new file mode 100644 index 0000000000000000000000000000000000000000..8676d8e2c2c0bac77cfce486f6f18639a8caa987 GIT binary patch literal 512 zcmV+b0{{JqP)z}Is24wg34Vg0&(Nh)A4KqyCy|cYNsu~v@z2dmB9tj1uH`lp^J3U`8~E{N z-p=3On^hdg5sIR03L*9Y+kk-hD<6Ofzy>Vo6d1ck4*P?_;4T~v8^TAR$Zf0DN+pxY zdoYJGiL9nW@D^3_!$~5MNL4D8YtWAX>pTG(3u?~~8-RJKR61@po0nw&j-Zf}uM`Re z1IBnHvj;%lW(tv*fb&ZHFIX|iIJtqC9%tO0lVf5?1zr z%n1($UyPgb4t7C5rMH$zKiPV#uKO2UXNZ0M7GMAtm#g$qt>3!<0000gp@kF&{Rb5bN zGzijG&{UKVshtpNClNu)%Ekhbw2`1J>Z6HtgGN0xKEhh;{0EDsrSU_qGw%`SWF~jc zxpQak3{VFTy2*App+P}o)NW`Vy70=Y$@eYTjRgDq)}ID15R?~1J&mx+C#(qTX;VcI z7?3B$uiL;R>R}-rT@%F{Q^f$#FZUOjQcfPeZ$<}E18p$$rORXa`Z6Q;=m%OKw=v~i zDrMy^zYYg%xi!g`vmMKrqSFdWO=yItW9DoVJ*XuE>5afFEf*aJP=P8AjY%zNU{t}` z&6S2q!}*1UI~}}%g2r}h|1FKpX|M(R^hMUF<}P<`VJOHX(}C-46~4}~;<03|R$zne zd{Hvx6aP5;bXPIK`>N>asx-f>p5`o;?TlKMQ-6LJb45R#;%UHjic=P>Ck@ z+{d0AQcWVHUUFA4oxlhWu<(*~7(R)cs(MMk>=;Zw$5hvZ{W->}h6+FUwIhgP8WFVd hn-r{!B2=PuoIg4=n|)8MY<2(u002ovPDHLkV1hfJ)Vlxx literal 0 HcmV?d00001 diff --git a/muk_web_preview/static/lib/ViewerJS/images/toolbarButton-menuArrows.png b/muk_web_preview/static/lib/ViewerJS/images/toolbarButton-menuArrows.png new file mode 100644 index 0000000000000000000000000000000000000000..31b06b5af9e548b15e274677b8ecaac1c1d06e77 GIT binary patch literal 237 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 literal 0 HcmV?d00001 diff --git a/muk_web_preview/static/lib/ViewerJS/images/toolbarButton-zoomIn.png b/muk_web_preview/static/lib/ViewerJS/images/toolbarButton-zoomIn.png new file mode 100644 index 0000000000000000000000000000000000000000..670acd93f5324c0f32e37e13d43c31890bdd123a GIT binary patch literal 228 zcmVviSpk+Ka&^`vn5+K)IU-oAe*-xp*r + + + + + + + ViewerJS + + + + + + + +

+
+
+
+ + + +
+
+
+
+
+ + + + +
+
+
+
+ +
+ +
+ + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ✖ +
+
+
+
+ + diff --git a/muk_web_preview/static/lib/ViewerJS/local.css b/muk_web_preview/static/lib/ViewerJS/local.css new file mode 100644 index 0000000..9649509 --- /dev/null +++ b/muk_web_preview/static/lib/ViewerJS/local.css @@ -0,0 +1,22 @@ +@font-face { + font-family: 'futura_book'; + src: url('/fonts/futura_book.eot'); + src: url('/fonts/futura_book.eot?#iefix') format('embedded-opentype'), + url('/fonts/futura_book.woff') format('woff'), + url('/fonts/futura_book.ttf') format('truetype'), + font-weight: normal; + font-style: normal; +} + +#fullscreen { + display: none; +} + +#download { + display: none; +} + +#about { + display: none; +} + diff --git a/muk_web_preview/static/lib/ViewerJS/pdf.js b/muk_web_preview/static/lib/ViewerJS/pdf.js new file mode 100644 index 0000000..463d7d0 --- /dev/null +++ b/muk_web_preview/static/lib/ViewerJS/pdf.js @@ -0,0 +1,8052 @@ +/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ +/* Copyright 2012 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*jshint globalstrict: false */ +/* globals PDFJS */ + +// Initializing PDFJS global object (if still undefined) +if (typeof PDFJS === 'undefined') { + (typeof window !== 'undefined' ? window : this).PDFJS = {}; +} + +PDFJS.version = '1.1.114'; +PDFJS.build = '3fd44fd'; + +(function pdfjsWrapper() { + // Use strict in our context only - users might not want it + 'use strict'; + +/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ +/* Copyright 2012 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* globals Cmd, ColorSpace, Dict, MozBlobBuilder, Name, PDFJS, Ref, URL, + Promise */ + +'use strict'; + +var globalScope = (typeof window === 'undefined') ? this : window; + +var isWorker = (typeof window === 'undefined'); + +var FONT_IDENTITY_MATRIX = [0.001, 0, 0, 0.001, 0, 0]; + +var TextRenderingMode = { + FILL: 0, + STROKE: 1, + FILL_STROKE: 2, + INVISIBLE: 3, + FILL_ADD_TO_PATH: 4, + STROKE_ADD_TO_PATH: 5, + FILL_STROKE_ADD_TO_PATH: 6, + ADD_TO_PATH: 7, + FILL_STROKE_MASK: 3, + ADD_TO_PATH_FLAG: 4 +}; + +var ImageKind = { + GRAYSCALE_1BPP: 1, + RGB_24BPP: 2, + RGBA_32BPP: 3 +}; + +var AnnotationType = { + WIDGET: 1, + TEXT: 2, + LINK: 3 +}; + +var StreamType = { + UNKNOWN: 0, + FLATE: 1, + LZW: 2, + DCT: 3, + JPX: 4, + JBIG: 5, + A85: 6, + AHX: 7, + CCF: 8, + RL: 9 +}; + +var FontType = { + UNKNOWN: 0, + TYPE1: 1, + TYPE1C: 2, + CIDFONTTYPE0: 3, + CIDFONTTYPE0C: 4, + TRUETYPE: 5, + CIDFONTTYPE2: 6, + TYPE3: 7, + OPENTYPE: 8, + TYPE0: 9, + MMTYPE1: 10 +}; + +// The global PDFJS object exposes the API +// In production, it will be declared outside a global wrapper +// In development, it will be declared here +if (!globalScope.PDFJS) { + globalScope.PDFJS = {}; +} + +globalScope.PDFJS.pdfBug = false; + +PDFJS.VERBOSITY_LEVELS = { + errors: 0, + warnings: 1, + infos: 5 +}; + +// All the possible operations for an operator list. +var OPS = PDFJS.OPS = { + // Intentionally start from 1 so it is easy to spot bad operators that will be + // 0's. + dependency: 1, + setLineWidth: 2, + setLineCap: 3, + setLineJoin: 4, + setMiterLimit: 5, + setDash: 6, + setRenderingIntent: 7, + setFlatness: 8, + setGState: 9, + save: 10, + restore: 11, + transform: 12, + moveTo: 13, + lineTo: 14, + curveTo: 15, + curveTo2: 16, + curveTo3: 17, + closePath: 18, + rectangle: 19, + stroke: 20, + closeStroke: 21, + fill: 22, + eoFill: 23, + fillStroke: 24, + eoFillStroke: 25, + closeFillStroke: 26, + closeEOFillStroke: 27, + endPath: 28, + clip: 29, + eoClip: 30, + beginText: 31, + endText: 32, + setCharSpacing: 33, + setWordSpacing: 34, + setHScale: 35, + setLeading: 36, + setFont: 37, + setTextRenderingMode: 38, + setTextRise: 39, + moveText: 40, + setLeadingMoveText: 41, + setTextMatrix: 42, + nextLine: 43, + showText: 44, + showSpacedText: 45, + nextLineShowText: 46, + nextLineSetSpacingShowText: 47, + setCharWidth: 48, + setCharWidthAndBounds: 49, + setStrokeColorSpace: 50, + setFillColorSpace: 51, + setStrokeColor: 52, + setStrokeColorN: 53, + setFillColor: 54, + setFillColorN: 55, + setStrokeGray: 56, + setFillGray: 57, + setStrokeRGBColor: 58, + setFillRGBColor: 59, + setStrokeCMYKColor: 60, + setFillCMYKColor: 61, + shadingFill: 62, + beginInlineImage: 63, + beginImageData: 64, + endInlineImage: 65, + paintXObject: 66, + markPoint: 67, + markPointProps: 68, + beginMarkedContent: 69, + beginMarkedContentProps: 70, + endMarkedContent: 71, + beginCompat: 72, + endCompat: 73, + paintFormXObjectBegin: 74, + paintFormXObjectEnd: 75, + beginGroup: 76, + endGroup: 77, + beginAnnotations: 78, + endAnnotations: 79, + beginAnnotation: 80, + endAnnotation: 81, + paintJpegXObject: 82, + paintImageMaskXObject: 83, + paintImageMaskXObjectGroup: 84, + paintImageXObject: 85, + paintInlineImageXObject: 86, + paintInlineImageXObjectGroup: 87, + paintImageXObjectRepeat: 88, + paintImageMaskXObjectRepeat: 89, + paintSolidColorImageMask: 90, + constructPath: 91 +}; + +// A notice for devs. These are good for things that are helpful to devs, such +// as warning that Workers were disabled, which is important to devs but not +// end users. +function info(msg) { + if (PDFJS.verbosity >= PDFJS.VERBOSITY_LEVELS.infos) { + console.log('Info: ' + msg); + } +} + +// Non-fatal warnings. +function warn(msg) { + if (PDFJS.verbosity >= PDFJS.VERBOSITY_LEVELS.warnings) { + console.log('Warning: ' + msg); + } +} + +// Fatal errors that should trigger the fallback UI and halt execution by +// throwing an exception. +function error(msg) { + if (PDFJS.verbosity >= PDFJS.VERBOSITY_LEVELS.errors) { + console.log('Error: ' + msg); + console.log(backtrace()); + } + UnsupportedManager.notify(UNSUPPORTED_FEATURES.unknown); + throw new Error(msg); +} + +function backtrace() { + try { + throw new Error(); + } catch (e) { + return e.stack ? e.stack.split('\n').slice(2).join('\n') : ''; + } +} + +function assert(cond, msg) { + if (!cond) { + error(msg); + } +} + +var UNSUPPORTED_FEATURES = PDFJS.UNSUPPORTED_FEATURES = { + unknown: 'unknown', + forms: 'forms', + javaScript: 'javaScript', + smask: 'smask', + shadingPattern: 'shadingPattern', + font: 'font' +}; + +var UnsupportedManager = PDFJS.UnsupportedManager = + (function UnsupportedManagerClosure() { + var listeners = []; + return { + listen: function (cb) { + listeners.push(cb); + }, + notify: function (featureId) { + warn('Unsupported feature "' + featureId + '"'); + for (var i = 0, ii = listeners.length; i < ii; i++) { + listeners[i](featureId); + } + } + }; +})(); + +// Combines two URLs. The baseUrl shall be absolute URL. If the url is an +// absolute URL, it will be returned as is. +function combineUrl(baseUrl, url) { + if (!url) { + return baseUrl; + } + if (/^[a-z][a-z0-9+\-.]*:/i.test(url)) { + return url; + } + var i; + if (url.charAt(0) === '/') { + // absolute path + i = baseUrl.indexOf('://'); + if (url.charAt(1) === '/') { + ++i; + } else { + i = baseUrl.indexOf('/', i + 3); + } + return baseUrl.substring(0, i) + url; + } else { + // relative path + var pathLength = baseUrl.length; + i = baseUrl.lastIndexOf('#'); + pathLength = i >= 0 ? i : pathLength; + i = baseUrl.lastIndexOf('?', pathLength); + pathLength = i >= 0 ? i : pathLength; + var prefixLength = baseUrl.lastIndexOf('/', pathLength); + return baseUrl.substring(0, prefixLength + 1) + url; + } +} + +// Validates if URL is safe and allowed, e.g. to avoid XSS. +function isValidUrl(url, allowRelative) { + if (!url) { + return false; + } + // RFC 3986 (http://tools.ietf.org/html/rfc3986#section-3.1) + // scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) + var protocol = /^[a-z][a-z0-9+\-.]*(?=:)/i.exec(url); + if (!protocol) { + return allowRelative; + } + protocol = protocol[0].toLowerCase(); + switch (protocol) { + case 'http': + case 'https': + case 'ftp': + case 'mailto': + case 'tel': + return true; + default: + return false; + } +} +PDFJS.isValidUrl = isValidUrl; + +function shadow(obj, prop, value) { + Object.defineProperty(obj, prop, { value: value, + enumerable: true, + configurable: true, + writable: false }); + return value; +} +PDFJS.shadow = shadow; + +var PasswordResponses = PDFJS.PasswordResponses = { + NEED_PASSWORD: 1, + INCORRECT_PASSWORD: 2 +}; + +var PasswordException = (function PasswordExceptionClosure() { + function PasswordException(msg, code) { + this.name = 'PasswordException'; + this.message = msg; + this.code = code; + } + + PasswordException.prototype = new Error(); + PasswordException.constructor = PasswordException; + + return PasswordException; +})(); +PDFJS.PasswordException = PasswordException; + +var UnknownErrorException = (function UnknownErrorExceptionClosure() { + function UnknownErrorException(msg, details) { + this.name = 'UnknownErrorException'; + this.message = msg; + this.details = details; + } + + UnknownErrorException.prototype = new Error(); + UnknownErrorException.constructor = UnknownErrorException; + + return UnknownErrorException; +})(); +PDFJS.UnknownErrorException = UnknownErrorException; + +var InvalidPDFException = (function InvalidPDFExceptionClosure() { + function InvalidPDFException(msg) { + this.name = 'InvalidPDFException'; + this.message = msg; + } + + InvalidPDFException.prototype = new Error(); + InvalidPDFException.constructor = InvalidPDFException; + + return InvalidPDFException; +})(); +PDFJS.InvalidPDFException = InvalidPDFException; + +var MissingPDFException = (function MissingPDFExceptionClosure() { + function MissingPDFException(msg) { + this.name = 'MissingPDFException'; + this.message = msg; + } + + MissingPDFException.prototype = new Error(); + MissingPDFException.constructor = MissingPDFException; + + return MissingPDFException; +})(); +PDFJS.MissingPDFException = MissingPDFException; + +var UnexpectedResponseException = + (function UnexpectedResponseExceptionClosure() { + function UnexpectedResponseException(msg, status) { + this.name = 'UnexpectedResponseException'; + this.message = msg; + this.status = status; + } + + UnexpectedResponseException.prototype = new Error(); + UnexpectedResponseException.constructor = UnexpectedResponseException; + + return UnexpectedResponseException; +})(); +PDFJS.UnexpectedResponseException = UnexpectedResponseException; + +var NotImplementedException = (function NotImplementedExceptionClosure() { + function NotImplementedException(msg) { + this.message = msg; + } + + NotImplementedException.prototype = new Error(); + NotImplementedException.prototype.name = 'NotImplementedException'; + NotImplementedException.constructor = NotImplementedException; + + return NotImplementedException; +})(); + +var MissingDataException = (function MissingDataExceptionClosure() { + function MissingDataException(begin, end) { + this.begin = begin; + this.end = end; + this.message = 'Missing data [' + begin + ', ' + end + ')'; + } + + MissingDataException.prototype = new Error(); + MissingDataException.prototype.name = 'MissingDataException'; + MissingDataException.constructor = MissingDataException; + + return MissingDataException; +})(); + +var XRefParseException = (function XRefParseExceptionClosure() { + function XRefParseException(msg) { + this.message = msg; + } + + XRefParseException.prototype = new Error(); + XRefParseException.prototype.name = 'XRefParseException'; + XRefParseException.constructor = XRefParseException; + + return XRefParseException; +})(); + + +function bytesToString(bytes) { + assert(bytes !== null && typeof bytes === 'object' && + bytes.length !== undefined, 'Invalid argument for bytesToString'); + var length = bytes.length; + var MAX_ARGUMENT_COUNT = 8192; + if (length < MAX_ARGUMENT_COUNT) { + return String.fromCharCode.apply(null, bytes); + } + var strBuf = []; + for (var i = 0; i < length; i += MAX_ARGUMENT_COUNT) { + var chunkEnd = Math.min(i + MAX_ARGUMENT_COUNT, length); + var chunk = bytes.subarray(i, chunkEnd); + strBuf.push(String.fromCharCode.apply(null, chunk)); + } + return strBuf.join(''); +} + +function stringToBytes(str) { + assert(typeof str === 'string', 'Invalid argument for stringToBytes'); + var length = str.length; + var bytes = new Uint8Array(length); + for (var i = 0; i < length; ++i) { + bytes[i] = str.charCodeAt(i) & 0xFF; + } + return bytes; +} + +function string32(value) { + return String.fromCharCode((value >> 24) & 0xff, (value >> 16) & 0xff, + (value >> 8) & 0xff, value & 0xff); +} + +function log2(x) { + var n = 1, i = 0; + while (x > n) { + n <<= 1; + i++; + } + return i; +} + +function readInt8(data, start) { + return (data[start] << 24) >> 24; +} + +function readUint16(data, offset) { + return (data[offset] << 8) | data[offset + 1]; +} + +function readUint32(data, offset) { + return ((data[offset] << 24) | (data[offset + 1] << 16) | + (data[offset + 2] << 8) | data[offset + 3]) >>> 0; +} + +// Lazy test the endianness of the platform +// NOTE: This will be 'true' for simulated TypedArrays +function isLittleEndian() { + var buffer8 = new Uint8Array(2); + buffer8[0] = 1; + var buffer16 = new Uint16Array(buffer8.buffer); + return (buffer16[0] === 1); +} + +Object.defineProperty(PDFJS, 'isLittleEndian', { + configurable: true, + get: function PDFJS_isLittleEndian() { + return shadow(PDFJS, 'isLittleEndian', isLittleEndian()); + } +}); + +//#if !(FIREFOX || MOZCENTRAL || B2G || CHROME) +//// Lazy test if the userAgant support CanvasTypedArrays +function hasCanvasTypedArrays() { + var canvas = document.createElement('canvas'); + canvas.width = canvas.height = 1; + var ctx = canvas.getContext('2d'); + var imageData = ctx.createImageData(1, 1); + return (typeof imageData.data.buffer !== 'undefined'); +} + +Object.defineProperty(PDFJS, 'hasCanvasTypedArrays', { + configurable: true, + get: function PDFJS_hasCanvasTypedArrays() { + return shadow(PDFJS, 'hasCanvasTypedArrays', hasCanvasTypedArrays()); + } +}); + +var Uint32ArrayView = (function Uint32ArrayViewClosure() { + + function Uint32ArrayView(buffer, length) { + this.buffer = buffer; + this.byteLength = buffer.length; + this.length = length === undefined ? (this.byteLength >> 2) : length; + ensureUint32ArrayViewProps(this.length); + } + Uint32ArrayView.prototype = Object.create(null); + + var uint32ArrayViewSetters = 0; + function createUint32ArrayProp(index) { + return { + get: function () { + var buffer = this.buffer, offset = index << 2; + return (buffer[offset] | (buffer[offset + 1] << 8) | + (buffer[offset + 2] << 16) | (buffer[offset + 3] << 24)) >>> 0; + }, + set: function (value) { + var buffer = this.buffer, offset = index << 2; + buffer[offset] = value & 255; + buffer[offset + 1] = (value >> 8) & 255; + buffer[offset + 2] = (value >> 16) & 255; + buffer[offset + 3] = (value >>> 24) & 255; + } + }; + } + + function ensureUint32ArrayViewProps(length) { + while (uint32ArrayViewSetters < length) { + Object.defineProperty(Uint32ArrayView.prototype, + uint32ArrayViewSetters, + createUint32ArrayProp(uint32ArrayViewSetters)); + uint32ArrayViewSetters++; + } + } + + return Uint32ArrayView; +})(); +//#else +//PDFJS.hasCanvasTypedArrays = true; +//#endif + +var IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0]; + +var Util = PDFJS.Util = (function UtilClosure() { + function Util() {} + + var rgbBuf = ['rgb(', 0, ',', 0, ',', 0, ')']; + + // makeCssRgb() can be called thousands of times. Using |rgbBuf| avoids + // creating many intermediate strings. + Util.makeCssRgb = function Util_makeCssRgb(r, g, b) { + rgbBuf[1] = r; + rgbBuf[3] = g; + rgbBuf[5] = b; + return rgbBuf.join(''); + }; + + // Concatenates two transformation matrices together and returns the result. + Util.transform = function Util_transform(m1, m2) { + return [ + m1[0] * m2[0] + m1[2] * m2[1], + m1[1] * m2[0] + m1[3] * m2[1], + m1[0] * m2[2] + m1[2] * m2[3], + m1[1] * m2[2] + m1[3] * m2[3], + m1[0] * m2[4] + m1[2] * m2[5] + m1[4], + m1[1] * m2[4] + m1[3] * m2[5] + m1[5] + ]; + }; + + // For 2d affine transforms + Util.applyTransform = function Util_applyTransform(p, m) { + var xt = p[0] * m[0] + p[1] * m[2] + m[4]; + var yt = p[0] * m[1] + p[1] * m[3] + m[5]; + return [xt, yt]; + }; + + Util.applyInverseTransform = function Util_applyInverseTransform(p, m) { + var d = m[0] * m[3] - m[1] * m[2]; + var xt = (p[0] * m[3] - p[1] * m[2] + m[2] * m[5] - m[4] * m[3]) / d; + var yt = (-p[0] * m[1] + p[1] * m[0] + m[4] * m[1] - m[5] * m[0]) / d; + return [xt, yt]; + }; + + // Applies the transform to the rectangle and finds the minimum axially + // aligned bounding box. + Util.getAxialAlignedBoundingBox = + function Util_getAxialAlignedBoundingBox(r, m) { + + var p1 = Util.applyTransform(r, m); + var p2 = Util.applyTransform(r.slice(2, 4), m); + var p3 = Util.applyTransform([r[0], r[3]], m); + var p4 = Util.applyTransform([r[2], r[1]], m); + return [ + Math.min(p1[0], p2[0], p3[0], p4[0]), + Math.min(p1[1], p2[1], p3[1], p4[1]), + Math.max(p1[0], p2[0], p3[0], p4[0]), + Math.max(p1[1], p2[1], p3[1], p4[1]) + ]; + }; + + Util.inverseTransform = function Util_inverseTransform(m) { + var d = m[0] * m[3] - m[1] * m[2]; + return [m[3] / d, -m[1] / d, -m[2] / d, m[0] / d, + (m[2] * m[5] - m[4] * m[3]) / d, (m[4] * m[1] - m[5] * m[0]) / d]; + }; + + // Apply a generic 3d matrix M on a 3-vector v: + // | a b c | | X | + // | d e f | x | Y | + // | g h i | | Z | + // M is assumed to be serialized as [a,b,c,d,e,f,g,h,i], + // with v as [X,Y,Z] + Util.apply3dTransform = function Util_apply3dTransform(m, v) { + return [ + m[0] * v[0] + m[1] * v[1] + m[2] * v[2], + m[3] * v[0] + m[4] * v[1] + m[5] * v[2], + m[6] * v[0] + m[7] * v[1] + m[8] * v[2] + ]; + }; + + // This calculation uses Singular Value Decomposition. + // The SVD can be represented with formula A = USV. We are interested in the + // matrix S here because it represents the scale values. + Util.singularValueDecompose2dScale = + function Util_singularValueDecompose2dScale(m) { + + var transpose = [m[0], m[2], m[1], m[3]]; + + // Multiply matrix m with its transpose. + var a = m[0] * transpose[0] + m[1] * transpose[2]; + var b = m[0] * transpose[1] + m[1] * transpose[3]; + var c = m[2] * transpose[0] + m[3] * transpose[2]; + var d = m[2] * transpose[1] + m[3] * transpose[3]; + + // Solve the second degree polynomial to get roots. + var first = (a + d) / 2; + var second = Math.sqrt((a + d) * (a + d) - 4 * (a * d - c * b)) / 2; + var sx = first + second || 1; + var sy = first - second || 1; + + // Scale values are the square roots of the eigenvalues. + return [Math.sqrt(sx), Math.sqrt(sy)]; + }; + + // Normalize rectangle rect=[x1, y1, x2, y2] so that (x1,y1) < (x2,y2) + // For coordinate systems whose origin lies in the bottom-left, this + // means normalization to (BL,TR) ordering. For systems with origin in the + // top-left, this means (TL,BR) ordering. + Util.normalizeRect = function Util_normalizeRect(rect) { + var r = rect.slice(0); // clone rect + if (rect[0] > rect[2]) { + r[0] = rect[2]; + r[2] = rect[0]; + } + if (rect[1] > rect[3]) { + r[1] = rect[3]; + r[3] = rect[1]; + } + return r; + }; + + // Returns a rectangle [x1, y1, x2, y2] corresponding to the + // intersection of rect1 and rect2. If no intersection, returns 'false' + // The rectangle coordinates of rect1, rect2 should be [x1, y1, x2, y2] + Util.intersect = function Util_intersect(rect1, rect2) { + function compare(a, b) { + return a - b; + } + + // Order points along the axes + var orderedX = [rect1[0], rect1[2], rect2[0], rect2[2]].sort(compare), + orderedY = [rect1[1], rect1[3], rect2[1], rect2[3]].sort(compare), + result = []; + + rect1 = Util.normalizeRect(rect1); + rect2 = Util.normalizeRect(rect2); + + // X: first and second points belong to different rectangles? + if ((orderedX[0] === rect1[0] && orderedX[1] === rect2[0]) || + (orderedX[0] === rect2[0] && orderedX[1] === rect1[0])) { + // Intersection must be between second and third points + result[0] = orderedX[1]; + result[2] = orderedX[2]; + } else { + return false; + } + + // Y: first and second points belong to different rectangles? + if ((orderedY[0] === rect1[1] && orderedY[1] === rect2[1]) || + (orderedY[0] === rect2[1] && orderedY[1] === rect1[1])) { + // Intersection must be between second and third points + result[1] = orderedY[1]; + result[3] = orderedY[2]; + } else { + return false; + } + + return result; + }; + + Util.sign = function Util_sign(num) { + return num < 0 ? -1 : 1; + }; + + Util.appendToArray = function Util_appendToArray(arr1, arr2) { + Array.prototype.push.apply(arr1, arr2); + }; + + Util.prependToArray = function Util_prependToArray(arr1, arr2) { + Array.prototype.unshift.apply(arr1, arr2); + }; + + Util.extendObj = function extendObj(obj1, obj2) { + for (var key in obj2) { + obj1[key] = obj2[key]; + } + }; + + Util.getInheritableProperty = function Util_getInheritableProperty(dict, + name) { + while (dict && !dict.has(name)) { + dict = dict.get('Parent'); + } + if (!dict) { + return null; + } + return dict.get(name); + }; + + Util.inherit = function Util_inherit(sub, base, prototype) { + sub.prototype = Object.create(base.prototype); + sub.prototype.constructor = sub; + for (var prop in prototype) { + sub.prototype[prop] = prototype[prop]; + } + }; + + Util.loadScript = function Util_loadScript(src, callback) { + var script = document.createElement('script'); + var loaded = false; + script.setAttribute('src', src); + if (callback) { + script.onload = function() { + if (!loaded) { + callback(); + } + loaded = true; + }; + } + document.getElementsByTagName('head')[0].appendChild(script); + }; + + return Util; +})(); + +/** + * PDF page viewport created based on scale, rotation and offset. + * @class + * @alias PDFJS.PageViewport + */ +var PageViewport = PDFJS.PageViewport = (function PageViewportClosure() { + /** + * @constructor + * @private + * @param viewBox {Array} xMin, yMin, xMax and yMax coordinates. + * @param scale {number} scale of the viewport. + * @param rotation {number} rotations of the viewport in degrees. + * @param offsetX {number} offset X + * @param offsetY {number} offset Y + * @param dontFlip {boolean} if true, axis Y will not be flipped. + */ + function PageViewport(viewBox, scale, rotation, offsetX, offsetY, dontFlip) { + this.viewBox = viewBox; + this.scale = scale; + this.rotation = rotation; + this.offsetX = offsetX; + this.offsetY = offsetY; + + // creating transform to convert pdf coordinate system to the normal + // canvas like coordinates taking in account scale and rotation + var centerX = (viewBox[2] + viewBox[0]) / 2; + var centerY = (viewBox[3] + viewBox[1]) / 2; + var rotateA, rotateB, rotateC, rotateD; + rotation = rotation % 360; + rotation = rotation < 0 ? rotation + 360 : rotation; + switch (rotation) { + case 180: + rotateA = -1; rotateB = 0; rotateC = 0; rotateD = 1; + break; + case 90: + rotateA = 0; rotateB = 1; rotateC = 1; rotateD = 0; + break; + case 270: + rotateA = 0; rotateB = -1; rotateC = -1; rotateD = 0; + break; + //case 0: + default: + rotateA = 1; rotateB = 0; rotateC = 0; rotateD = -1; + break; + } + + if (dontFlip) { + rotateC = -rotateC; rotateD = -rotateD; + } + + var offsetCanvasX, offsetCanvasY; + var width, height; + if (rotateA === 0) { + offsetCanvasX = Math.abs(centerY - viewBox[1]) * scale + offsetX; + offsetCanvasY = Math.abs(centerX - viewBox[0]) * scale + offsetY; + width = Math.abs(viewBox[3] - viewBox[1]) * scale; + height = Math.abs(viewBox[2] - viewBox[0]) * scale; + } else { + offsetCanvasX = Math.abs(centerX - viewBox[0]) * scale + offsetX; + offsetCanvasY = Math.abs(centerY - viewBox[1]) * scale + offsetY; + width = Math.abs(viewBox[2] - viewBox[0]) * scale; + height = Math.abs(viewBox[3] - viewBox[1]) * scale; + } + // creating transform for the following operations: + // translate(-centerX, -centerY), rotate and flip vertically, + // scale, and translate(offsetCanvasX, offsetCanvasY) + this.transform = [ + rotateA * scale, + rotateB * scale, + rotateC * scale, + rotateD * scale, + offsetCanvasX - rotateA * scale * centerX - rotateC * scale * centerY, + offsetCanvasY - rotateB * scale * centerX - rotateD * scale * centerY + ]; + + this.width = width; + this.height = height; + this.fontScale = scale; + } + PageViewport.prototype = /** @lends PDFJS.PageViewport.prototype */ { + /** + * Clones viewport with additional properties. + * @param args {Object} (optional) If specified, may contain the 'scale' or + * 'rotation' properties to override the corresponding properties in + * the cloned viewport. + * @returns {PDFJS.PageViewport} Cloned viewport. + */ + clone: function PageViewPort_clone(args) { + args = args || {}; + var scale = 'scale' in args ? args.scale : this.scale; + var rotation = 'rotation' in args ? args.rotation : this.rotation; + return new PageViewport(this.viewBox.slice(), scale, rotation, + this.offsetX, this.offsetY, args.dontFlip); + }, + /** + * Converts PDF point to the viewport coordinates. For examples, useful for + * converting PDF location into canvas pixel coordinates. + * @param x {number} X coordinate. + * @param y {number} Y coordinate. + * @returns {Object} Object that contains 'x' and 'y' properties of the + * point in the viewport coordinate space. + * @see {@link convertToPdfPoint} + * @see {@link convertToViewportRectangle} + */ + convertToViewportPoint: function PageViewport_convertToViewportPoint(x, y) { + return Util.applyTransform([x, y], this.transform); + }, + /** + * Converts PDF rectangle to the viewport coordinates. + * @param rect {Array} xMin, yMin, xMax and yMax coordinates. + * @returns {Array} Contains corresponding coordinates of the rectangle + * in the viewport coordinate space. + * @see {@link convertToViewportPoint} + */ + convertToViewportRectangle: + function PageViewport_convertToViewportRectangle(rect) { + var tl = Util.applyTransform([rect[0], rect[1]], this.transform); + var br = Util.applyTransform([rect[2], rect[3]], this.transform); + return [tl[0], tl[1], br[0], br[1]]; + }, + /** + * Converts viewport coordinates to the PDF location. For examples, useful + * for converting canvas pixel location into PDF one. + * @param x {number} X coordinate. + * @param y {number} Y coordinate. + * @returns {Object} Object that contains 'x' and 'y' properties of the + * point in the PDF coordinate space. + * @see {@link convertToViewportPoint} + */ + convertToPdfPoint: function PageViewport_convertToPdfPoint(x, y) { + return Util.applyInverseTransform([x, y], this.transform); + } + }; + return PageViewport; +})(); + +var PDFStringTranslateTable = [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0x2D8, 0x2C7, 0x2C6, 0x2D9, 0x2DD, 0x2DB, 0x2DA, 0x2DC, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2022, 0x2020, 0x2021, 0x2026, 0x2014, + 0x2013, 0x192, 0x2044, 0x2039, 0x203A, 0x2212, 0x2030, 0x201E, 0x201C, + 0x201D, 0x2018, 0x2019, 0x201A, 0x2122, 0xFB01, 0xFB02, 0x141, 0x152, 0x160, + 0x178, 0x17D, 0x131, 0x142, 0x153, 0x161, 0x17E, 0, 0x20AC +]; + +function stringToPDFString(str) { + var i, n = str.length, strBuf = []; + if (str[0] === '\xFE' && str[1] === '\xFF') { + // UTF16BE BOM + for (i = 2; i < n; i += 2) { + strBuf.push(String.fromCharCode( + (str.charCodeAt(i) << 8) | str.charCodeAt(i + 1))); + } + } else { + for (i = 0; i < n; ++i) { + var code = PDFStringTranslateTable[str.charCodeAt(i)]; + strBuf.push(code ? String.fromCharCode(code) : str.charAt(i)); + } + } + return strBuf.join(''); +} + +function stringToUTF8String(str) { + return decodeURIComponent(escape(str)); +} + +function isEmptyObj(obj) { + for (var key in obj) { + return false; + } + return true; +} + +function isBool(v) { + return typeof v === 'boolean'; +} + +function isInt(v) { + return typeof v === 'number' && ((v | 0) === v); +} + +function isNum(v) { + return typeof v === 'number'; +} + +function isString(v) { + return typeof v === 'string'; +} + +function isName(v) { + return v instanceof Name; +} + +function isCmd(v, cmd) { + return v instanceof Cmd && (cmd === undefined || v.cmd === cmd); +} + +function isDict(v, type) { + if (!(v instanceof Dict)) { + return false; + } + if (!type) { + return true; + } + var dictType = v.get('Type'); + return isName(dictType) && dictType.name === type; +} + +function isArray(v) { + return v instanceof Array; +} + +function isStream(v) { + return typeof v === 'object' && v !== null && v.getBytes !== undefined; +} + +function isArrayBuffer(v) { + return typeof v === 'object' && v !== null && v.byteLength !== undefined; +} + +function isRef(v) { + return v instanceof Ref; +} + +/** + * Promise Capability object. + * + * @typedef {Object} PromiseCapability + * @property {Promise} promise - A promise object. + * @property {function} resolve - Fullfills the promise. + * @property {function} reject - Rejects the promise. + */ + +/** + * Creates a promise capability object. + * @alias PDFJS.createPromiseCapability + * + * @return {PromiseCapability} A capability object contains: + * - a Promise, resolve and reject methods. + */ +function createPromiseCapability() { + var capability = {}; + capability.promise = new Promise(function (resolve, reject) { + capability.resolve = resolve; + capability.reject = reject; + }); + return capability; +} + +PDFJS.createPromiseCapability = createPromiseCapability; + +/** + * Polyfill for Promises: + * The following promise implementation tries to generally implement the + * Promise/A+ spec. Some notable differences from other promise libaries are: + * - There currently isn't a seperate deferred and promise object. + * - Unhandled rejections eventually show an error if they aren't handled. + * + * Based off of the work in: + * https://bugzilla.mozilla.org/show_bug.cgi?id=810490 + */ +(function PromiseClosure() { + if (globalScope.Promise) { + // Promises existing in the DOM/Worker, checking presence of all/resolve + if (typeof globalScope.Promise.all !== 'function') { + globalScope.Promise.all = function (iterable) { + var count = 0, results = [], resolve, reject; + var promise = new globalScope.Promise(function (resolve_, reject_) { + resolve = resolve_; + reject = reject_; + }); + iterable.forEach(function (p, i) { + count++; + p.then(function (result) { + results[i] = result; + count--; + if (count === 0) { + resolve(results); + } + }, reject); + }); + if (count === 0) { + resolve(results); + } + return promise; + }; + } + if (typeof globalScope.Promise.resolve !== 'function') { + globalScope.Promise.resolve = function (value) { + return new globalScope.Promise(function (resolve) { resolve(value); }); + }; + } + if (typeof globalScope.Promise.reject !== 'function') { + globalScope.Promise.reject = function (reason) { + return new globalScope.Promise(function (resolve, reject) { + reject(reason); + }); + }; + } + if (typeof globalScope.Promise.prototype.catch !== 'function') { + globalScope.Promise.prototype.catch = function (onReject) { + return globalScope.Promise.prototype.then(undefined, onReject); + }; + } + return; + } +//#if !MOZCENTRAL + var STATUS_PENDING = 0; + var STATUS_RESOLVED = 1; + var STATUS_REJECTED = 2; + + // In an attempt to avoid silent exceptions, unhandled rejections are + // tracked and if they aren't handled in a certain amount of time an + // error is logged. + var REJECTION_TIMEOUT = 500; + + var HandlerManager = { + handlers: [], + running: false, + unhandledRejections: [], + pendingRejectionCheck: false, + + scheduleHandlers: function scheduleHandlers(promise) { + if (promise._status === STATUS_PENDING) { + return; + } + + this.handlers = this.handlers.concat(promise._handlers); + promise._handlers = []; + + if (this.running) { + return; + } + this.running = true; + + setTimeout(this.runHandlers.bind(this), 0); + }, + + runHandlers: function runHandlers() { + var RUN_TIMEOUT = 1; // ms + var timeoutAt = Date.now() + RUN_TIMEOUT; + while (this.handlers.length > 0) { + var handler = this.handlers.shift(); + + var nextStatus = handler.thisPromise._status; + var nextValue = handler.thisPromise._value; + + try { + if (nextStatus === STATUS_RESOLVED) { + if (typeof handler.onResolve === 'function') { + nextValue = handler.onResolve(nextValue); + } + } else if (typeof handler.onReject === 'function') { + nextValue = handler.onReject(nextValue); + nextStatus = STATUS_RESOLVED; + + if (handler.thisPromise._unhandledRejection) { + this.removeUnhandeledRejection(handler.thisPromise); + } + } + } catch (ex) { + nextStatus = STATUS_REJECTED; + nextValue = ex; + } + + handler.nextPromise._updateStatus(nextStatus, nextValue); + if (Date.now() >= timeoutAt) { + break; + } + } + + if (this.handlers.length > 0) { + setTimeout(this.runHandlers.bind(this), 0); + return; + } + + this.running = false; + }, + + addUnhandledRejection: function addUnhandledRejection(promise) { + this.unhandledRejections.push({ + promise: promise, + time: Date.now() + }); + this.scheduleRejectionCheck(); + }, + + removeUnhandeledRejection: function removeUnhandeledRejection(promise) { + promise._unhandledRejection = false; + for (var i = 0; i < this.unhandledRejections.length; i++) { + if (this.unhandledRejections[i].promise === promise) { + this.unhandledRejections.splice(i); + i--; + } + } + }, + + scheduleRejectionCheck: function scheduleRejectionCheck() { + if (this.pendingRejectionCheck) { + return; + } + this.pendingRejectionCheck = true; + setTimeout(function rejectionCheck() { + this.pendingRejectionCheck = false; + var now = Date.now(); + for (var i = 0; i < this.unhandledRejections.length; i++) { + if (now - this.unhandledRejections[i].time > REJECTION_TIMEOUT) { + var unhandled = this.unhandledRejections[i].promise._value; + var msg = 'Unhandled rejection: ' + unhandled; + if (unhandled.stack) { + msg += '\n' + unhandled.stack; + } + warn(msg); + this.unhandledRejections.splice(i); + i--; + } + } + if (this.unhandledRejections.length) { + this.scheduleRejectionCheck(); + } + }.bind(this), REJECTION_TIMEOUT); + } + }; + + function Promise(resolver) { + this._status = STATUS_PENDING; + this._handlers = []; + try { + resolver.call(this, this._resolve.bind(this), this._reject.bind(this)); + } catch (e) { + this._reject(e); + } + } + /** + * Builds a promise that is resolved when all the passed in promises are + * resolved. + * @param {array} array of data and/or promises to wait for. + * @return {Promise} New dependant promise. + */ + Promise.all = function Promise_all(promises) { + var resolveAll, rejectAll; + var deferred = new Promise(function (resolve, reject) { + resolveAll = resolve; + rejectAll = reject; + }); + var unresolved = promises.length; + var results = []; + if (unresolved === 0) { + resolveAll(results); + return deferred; + } + function reject(reason) { + if (deferred._status === STATUS_REJECTED) { + return; + } + results = []; + rejectAll(reason); + } + for (var i = 0, ii = promises.length; i < ii; ++i) { + var promise = promises[i]; + var resolve = (function(i) { + return function(value) { + if (deferred._status === STATUS_REJECTED) { + return; + } + results[i] = value; + unresolved--; + if (unresolved === 0) { + resolveAll(results); + } + }; + })(i); + if (Promise.isPromise(promise)) { + promise.then(resolve, reject); + } else { + resolve(promise); + } + } + return deferred; + }; + + /** + * Checks if the value is likely a promise (has a 'then' function). + * @return {boolean} true if value is thenable + */ + Promise.isPromise = function Promise_isPromise(value) { + return value && typeof value.then === 'function'; + }; + + /** + * Creates resolved promise + * @param value resolve value + * @returns {Promise} + */ + Promise.resolve = function Promise_resolve(value) { + return new Promise(function (resolve) { resolve(value); }); + }; + + /** + * Creates rejected promise + * @param reason rejection value + * @returns {Promise} + */ + Promise.reject = function Promise_reject(reason) { + return new Promise(function (resolve, reject) { reject(reason); }); + }; + + Promise.prototype = { + _status: null, + _value: null, + _handlers: null, + _unhandledRejection: null, + + _updateStatus: function Promise__updateStatus(status, value) { + if (this._status === STATUS_RESOLVED || + this._status === STATUS_REJECTED) { + return; + } + + if (status === STATUS_RESOLVED && + Promise.isPromise(value)) { + value.then(this._updateStatus.bind(this, STATUS_RESOLVED), + this._updateStatus.bind(this, STATUS_REJECTED)); + return; + } + + this._status = status; + this._value = value; + + if (status === STATUS_REJECTED && this._handlers.length === 0) { + this._unhandledRejection = true; + HandlerManager.addUnhandledRejection(this); + } + + HandlerManager.scheduleHandlers(this); + }, + + _resolve: function Promise_resolve(value) { + this._updateStatus(STATUS_RESOLVED, value); + }, + + _reject: function Promise_reject(reason) { + this._updateStatus(STATUS_REJECTED, reason); + }, + + then: function Promise_then(onResolve, onReject) { + var nextPromise = new Promise(function (resolve, reject) { + this.resolve = resolve; + this.reject = reject; + }); + this._handlers.push({ + thisPromise: this, + onResolve: onResolve, + onReject: onReject, + nextPromise: nextPromise + }); + HandlerManager.scheduleHandlers(this); + return nextPromise; + }, + + catch: function Promise_catch(onReject) { + return this.then(undefined, onReject); + } + }; + + globalScope.Promise = Promise; +//#else +//throw new Error('DOM Promise is not present'); +//#endif +})(); + +var StatTimer = (function StatTimerClosure() { + function rpad(str, pad, length) { + while (str.length < length) { + str += pad; + } + return str; + } + function StatTimer() { + this.started = {}; + this.times = []; + this.enabled = true; + } + StatTimer.prototype = { + time: function StatTimer_time(name) { + if (!this.enabled) { + return; + } + if (name in this.started) { + warn('Timer is already running for ' + name); + } + this.started[name] = Date.now(); + }, + timeEnd: function StatTimer_timeEnd(name) { + if (!this.enabled) { + return; + } + if (!(name in this.started)) { + warn('Timer has not been started for ' + name); + } + this.times.push({ + 'name': name, + 'start': this.started[name], + 'end': Date.now() + }); + // Remove timer from started so it can be called again. + delete this.started[name]; + }, + toString: function StatTimer_toString() { + var i, ii; + var times = this.times; + var out = ''; + // Find the longest name for padding purposes. + var longest = 0; + for (i = 0, ii = times.length; i < ii; ++i) { + var name = times[i]['name']; + if (name.length > longest) { + longest = name.length; + } + } + for (i = 0, ii = times.length; i < ii; ++i) { + var span = times[i]; + var duration = span.end - span.start; + out += rpad(span['name'], ' ', longest) + ' ' + duration + 'ms\n'; + } + return out; + } + }; + return StatTimer; +})(); + +PDFJS.createBlob = function createBlob(data, contentType) { + if (typeof Blob !== 'undefined') { + return new Blob([data], { type: contentType }); + } + // Blob builder is deprecated in FF14 and removed in FF18. + var bb = new MozBlobBuilder(); + bb.append(data); + return bb.getBlob(contentType); +}; + +PDFJS.createObjectURL = (function createObjectURLClosure() { + // Blob/createObjectURL is not available, falling back to data schema. + var digits = + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; + + return function createObjectURL(data, contentType) { + if (!PDFJS.disableCreateObjectURL && + typeof URL !== 'undefined' && URL.createObjectURL) { + var blob = PDFJS.createBlob(data, contentType); + return URL.createObjectURL(blob); + } + + var buffer = 'data:' + contentType + ';base64,'; + for (var i = 0, ii = data.length; i < ii; i += 3) { + var b1 = data[i] & 0xFF; + var b2 = data[i + 1] & 0xFF; + var b3 = data[i + 2] & 0xFF; + var d1 = b1 >> 2, d2 = ((b1 & 3) << 4) | (b2 >> 4); + var d3 = i + 1 < ii ? ((b2 & 0xF) << 2) | (b3 >> 6) : 64; + var d4 = i + 2 < ii ? (b3 & 0x3F) : 64; + buffer += digits[d1] + digits[d2] + digits[d3] + digits[d4]; + } + return buffer; + }; +})(); + +function MessageHandler(name, comObj) { + this.name = name; + this.comObj = comObj; + this.callbackIndex = 1; + this.postMessageTransfers = true; + var callbacksCapabilities = this.callbacksCapabilities = {}; + var ah = this.actionHandler = {}; + + ah['console_log'] = [function ahConsoleLog(data) { + console.log.apply(console, data); + }]; + ah['console_error'] = [function ahConsoleError(data) { + console.error.apply(console, data); + }]; + ah['_unsupported_feature'] = [function ah_unsupportedFeature(data) { + UnsupportedManager.notify(data); + }]; + + comObj.onmessage = function messageHandlerComObjOnMessage(event) { + var data = event.data; + if (data.isReply) { + var callbackId = data.callbackId; + if (data.callbackId in callbacksCapabilities) { + var callback = callbacksCapabilities[callbackId]; + delete callbacksCapabilities[callbackId]; + if ('error' in data) { + callback.reject(data.error); + } else { + callback.resolve(data.data); + } + } else { + error('Cannot resolve callback ' + callbackId); + } + } else if (data.action in ah) { + var action = ah[data.action]; + if (data.callbackId) { + Promise.resolve().then(function () { + return action[0].call(action[1], data.data); + }).then(function (result) { + comObj.postMessage({ + isReply: true, + callbackId: data.callbackId, + data: result + }); + }, function (reason) { + comObj.postMessage({ + isReply: true, + callbackId: data.callbackId, + error: reason + }); + }); + } else { + action[0].call(action[1], data.data); + } + } else { + error('Unknown action from worker: ' + data.action); + } + }; +} + +MessageHandler.prototype = { + on: function messageHandlerOn(actionName, handler, scope) { + var ah = this.actionHandler; + if (ah[actionName]) { + error('There is already an actionName called "' + actionName + '"'); + } + ah[actionName] = [handler, scope]; + }, + /** + * Sends a message to the comObj to invoke the action with the supplied data. + * @param {String} actionName Action to call. + * @param {JSON} data JSON data to send. + * @param {Array} [transfers] Optional list of transfers/ArrayBuffers + */ + send: function messageHandlerSend(actionName, data, transfers) { + var message = { + action: actionName, + data: data + }; + this.postMessage(message, transfers); + }, + /** + * Sends a message to the comObj to invoke the action with the supplied data. + * Expects that other side will callback with the response. + * @param {String} actionName Action to call. + * @param {JSON} data JSON data to send. + * @param {Array} [transfers] Optional list of transfers/ArrayBuffers. + * @returns {Promise} Promise to be resolved with response data. + */ + sendWithPromise: + function messageHandlerSendWithPromise(actionName, data, transfers) { + var callbackId = this.callbackIndex++; + var message = { + action: actionName, + data: data, + callbackId: callbackId + }; + var capability = createPromiseCapability(); + this.callbacksCapabilities[callbackId] = capability; + try { + this.postMessage(message, transfers); + } catch (e) { + capability.reject(e); + } + return capability.promise; + }, + /** + * Sends raw message to the comObj. + * @private + * @param message {Object} Raw message. + * @param transfers List of transfers/ArrayBuffers, or undefined. + */ + postMessage: function (message, transfers) { + if (transfers && this.postMessageTransfers) { + this.comObj.postMessage(message, transfers); + } else { + this.comObj.postMessage(message); + } + } +}; + +function loadJpegStream(id, imageUrl, objs) { + var img = new Image(); + img.onload = (function loadJpegStream_onloadClosure() { + objs.resolve(id, img); + }); + img.onerror = (function loadJpegStream_onerrorClosure() { + objs.resolve(id, null); + warn('Error during JPEG image loading'); + }); + img.src = imageUrl; +} + + +/** + * The maximum allowed image size in total pixels e.g. width * height. Images + * above this value will not be drawn. Use -1 for no limit. + * @var {number} + */ +PDFJS.maxImageSize = (PDFJS.maxImageSize === undefined ? + -1 : PDFJS.maxImageSize); + +/** + * The url of where the predefined Adobe CMaps are located. Include trailing + * slash. + * @var {string} + */ +PDFJS.cMapUrl = (PDFJS.cMapUrl === undefined ? null : PDFJS.cMapUrl); + +/** + * Specifies if CMaps are binary packed. + * @var {boolean} + */ +PDFJS.cMapPacked = PDFJS.cMapPacked === undefined ? false : PDFJS.cMapPacked; + +/** + * By default fonts are converted to OpenType fonts and loaded via font face + * rules. If disabled, the font will be rendered using a built in font renderer + * that constructs the glyphs with primitive path commands. + * @var {boolean} + */ +PDFJS.disableFontFace = (PDFJS.disableFontFace === undefined ? + false : PDFJS.disableFontFace); + +/** + * Path for image resources, mainly for annotation icons. Include trailing + * slash. + * @var {string} + */ +PDFJS.imageResourcesPath = (PDFJS.imageResourcesPath === undefined ? + '' : PDFJS.imageResourcesPath); + +/** + * Disable the web worker and run all code on the main thread. This will happen + * automatically if the browser doesn't support workers or sending typed arrays + * to workers. + * @var {boolean} + */ +PDFJS.disableWorker = (PDFJS.disableWorker === undefined ? + false : PDFJS.disableWorker); + +/** + * Path and filename of the worker file. Required when the worker is enabled in + * development mode. If unspecified in the production build, the worker will be + * loaded based on the location of the pdf.js file. + * @var {string} + */ +PDFJS.workerSrc = (PDFJS.workerSrc === undefined ? null : PDFJS.workerSrc); + +/** + * Disable range request loading of PDF files. When enabled and if the server + * supports partial content requests then the PDF will be fetched in chunks. + * Enabled (false) by default. + * @var {boolean} + */ +PDFJS.disableRange = (PDFJS.disableRange === undefined ? + false : PDFJS.disableRange); + +/** + * Disable streaming of PDF file data. By default PDF.js attempts to load PDF + * in chunks. This default behavior can be disabled. + * @var {boolean} + */ +PDFJS.disableStream = (PDFJS.disableStream === undefined ? + false : PDFJS.disableStream); + +/** + * Disable pre-fetching of PDF file data. When range requests are enabled PDF.js + * will automatically keep fetching more data even if it isn't needed to display + * the current page. This default behavior can be disabled. + * + * NOTE: It is also necessary to disable streaming, see above, + * in order for disabling of pre-fetching to work correctly. + * @var {boolean} + */ +PDFJS.disableAutoFetch = (PDFJS.disableAutoFetch === undefined ? + false : PDFJS.disableAutoFetch); + +/** + * Enables special hooks for debugging PDF.js. + * @var {boolean} + */ +PDFJS.pdfBug = (PDFJS.pdfBug === undefined ? false : PDFJS.pdfBug); + +/** + * Enables transfer usage in postMessage for ArrayBuffers. + * @var {boolean} + */ +PDFJS.postMessageTransfers = (PDFJS.postMessageTransfers === undefined ? + true : PDFJS.postMessageTransfers); + +/** + * Disables URL.createObjectURL usage. + * @var {boolean} + */ +PDFJS.disableCreateObjectURL = (PDFJS.disableCreateObjectURL === undefined ? + false : PDFJS.disableCreateObjectURL); + +/** + * Disables WebGL usage. + * @var {boolean} + */ +PDFJS.disableWebGL = (PDFJS.disableWebGL === undefined ? + true : PDFJS.disableWebGL); + +/** + * Disables fullscreen support, and by extension Presentation Mode, + * in browsers which support the fullscreen API. + * @var {boolean} + */ +PDFJS.disableFullscreen = (PDFJS.disableFullscreen === undefined ? + false : PDFJS.disableFullscreen); + +/** + * Enables CSS only zooming. + * @var {boolean} + */ +PDFJS.useOnlyCssZoom = (PDFJS.useOnlyCssZoom === undefined ? + false : PDFJS.useOnlyCssZoom); + +/** + * Controls the logging level. + * The constants from PDFJS.VERBOSITY_LEVELS should be used: + * - errors + * - warnings [default] + * - infos + * @var {number} + */ +PDFJS.verbosity = (PDFJS.verbosity === undefined ? + PDFJS.VERBOSITY_LEVELS.warnings : PDFJS.verbosity); + +/** + * The maximum supported canvas size in total pixels e.g. width * height. + * The default value is 4096 * 4096. Use -1 for no limit. + * @var {number} + */ +PDFJS.maxCanvasPixels = (PDFJS.maxCanvasPixels === undefined ? + 16777216 : PDFJS.maxCanvasPixels); + +/** + * Opens external links in a new window if enabled. The default behavior opens + * external links in the PDF.js window. + * @var {boolean} + */ +PDFJS.openExternalLinksInNewWindow = ( + PDFJS.openExternalLinksInNewWindow === undefined ? + false : PDFJS.openExternalLinksInNewWindow); + +/** + * Document initialization / loading parameters object. + * + * @typedef {Object} DocumentInitParameters + * @property {string} url - The URL of the PDF. + * @property {TypedArray|Array|string} data - Binary PDF data. Use typed arrays + * (Uint8Array) to improve the memory usage. If PDF data is BASE64-encoded, + * use atob() to convert it to a binary string first. + * @property {Object} httpHeaders - Basic authentication headers. + * @property {boolean} withCredentials - Indicates whether or not cross-site + * Access-Control requests should be made using credentials such as cookies + * or authorization headers. The default is false. + * @property {string} password - For decrypting password-protected PDFs. + * @property {TypedArray} initialData - A typed array with the first portion or + * all of the pdf data. Used by the extension since some data is already + * loaded before the switch to range requests. + * @property {number} length - The PDF file length. It's used for progress + * reports and range requests operations. + * @property {PDFDataRangeTransport} range + */ + +/** + * @typedef {Object} PDFDocumentStats + * @property {Array} streamTypes - Used stream types in the document (an item + * is set to true if specific stream ID was used in the document). + * @property {Array} fontTypes - Used font type in the document (an item is set + * to true if specific font ID was used in the document). + */ + +/** + * This is the main entry point for loading a PDF and interacting with it. + * NOTE: If a URL is used to fetch the PDF data a standard XMLHttpRequest(XHR) + * is used, which means it must follow the same origin rules that any XHR does + * e.g. No cross domain requests without CORS. + * + * @param {string|TypedArray|DocumentInitParameters|PDFDataRangeTransport} src + * Can be a url to where a PDF is located, a typed array (Uint8Array) + * already populated with data or parameter object. + * + * @param {PDFDataRangeTransport} pdfDataRangeTransport (deprecated) It is used + * if you want to manually serve range requests for data in the PDF. + * + * @param {function} passwordCallback (deprecated) It is used to request a + * password if wrong or no password was provided. The callback receives two + * parameters: function that needs to be called with new password and reason + * (see {PasswordResponses}). + * + * @param {function} progressCallback (deprecated) It is used to be able to + * monitor the loading progress of the PDF file (necessary to implement e.g. + * a loading bar). The callback receives an {Object} with the properties: + * {number} loaded and {number} total. + * + * @return {PDFDocumentLoadingTask} + */ +PDFJS.getDocument = function getDocument(src, + pdfDataRangeTransport, + passwordCallback, + progressCallback) { + var task = new PDFDocumentLoadingTask(); + + // Support of the obsolete arguments (for compatibility with API v1.0) + if (pdfDataRangeTransport) { + if (!(pdfDataRangeTransport instanceof PDFDataRangeTransport)) { + // Not a PDFDataRangeTransport instance, trying to add missing properties. + pdfDataRangeTransport = Object.create(pdfDataRangeTransport); + pdfDataRangeTransport.length = src.length; + pdfDataRangeTransport.initialData = src.initialData; + } + src = Object.create(src); + src.range = pdfDataRangeTransport; + } + task.onPassword = passwordCallback || null; + task.onProgress = progressCallback || null; + + var workerInitializedCapability, transport; + var source; + if (typeof src === 'string') { + source = { url: src }; + } else if (isArrayBuffer(src)) { + source = { data: src }; + } else if (src instanceof PDFDataRangeTransport) { + source = { range: src }; + } else { + if (typeof src !== 'object') { + error('Invalid parameter in getDocument, need either Uint8Array, ' + + 'string or a parameter object'); + } + if (!src.url && !src.data && !src.range) { + error('Invalid parameter object: need either .data, .range or .url'); + } + + source = src; + } + + var params = {}; + for (var key in source) { + if (key === 'url' && typeof window !== 'undefined') { + // The full path is required in the 'url' field. + params[key] = combineUrl(window.location.href, source[key]); + continue; + } else if (key === 'range') { + continue; + } else if (key === 'data' && !(source[key] instanceof Uint8Array)) { + // Converting string or array-like data to Uint8Array. + var pdfBytes = source[key]; + if (typeof pdfBytes === 'string') { + params[key] = stringToBytes(pdfBytes); + } else if (typeof pdfBytes === 'object' && pdfBytes !== null && + !isNaN(pdfBytes.length)) { + params[key] = new Uint8Array(pdfBytes); + } else { + error('Invalid PDF binary data: either typed array, string or ' + + 'array-like object is expected in the data property.'); + } + continue; + } + params[key] = source[key]; + } + + workerInitializedCapability = createPromiseCapability(); + transport = new WorkerTransport(workerInitializedCapability, source.range); + workerInitializedCapability.promise.then(function transportInitialized() { + transport.fetchDocument(task, params); + }); + + return task; +}; + +/** + * PDF document loading operation. + * @class + */ +var PDFDocumentLoadingTask = (function PDFDocumentLoadingTaskClosure() { + /** @constructs PDFDocumentLoadingTask */ + function PDFDocumentLoadingTask() { + this._capability = createPromiseCapability(); + + /** + * Callback to request a password if wrong or no password was provided. + * The callback receives two parameters: function that needs to be called + * with new password and reason (see {PasswordResponses}). + */ + this.onPassword = null; + + /** + * Callback to be able to monitor the loading progress of the PDF file + * (necessary to implement e.g. a loading bar). The callback receives + * an {Object} with the properties: {number} loaded and {number} total. + */ + this.onProgress = null; + } + + PDFDocumentLoadingTask.prototype = + /** @lends PDFDocumentLoadingTask.prototype */ { + /** + * @return {Promise} + */ + get promise() { + return this._capability.promise; + }, + + // TODO add cancel or abort method + + /** + * Registers callbacks to indicate the document loading completion. + * + * @param {function} onFulfilled The callback for the loading completion. + * @param {function} onRejected The callback for the loading failure. + * @return {Promise} A promise that is resolved after the onFulfilled or + * onRejected callback. + */ + then: function PDFDocumentLoadingTask_then(onFulfilled, onRejected) { + return this.promise.then.apply(this.promise, arguments); + } + }; + + return PDFDocumentLoadingTask; +})(); + +/** + * Abstract class to support range requests file loading. + * @class + */ +var PDFDataRangeTransport = (function pdfDataRangeTransportClosure() { + /** + * @constructs PDFDataRangeTransport + * @param {number} length + * @param {Uint8Array} initialData + */ + function PDFDataRangeTransport(length, initialData) { + this.length = length; + this.initialData = initialData; + + this._rangeListeners = []; + this._progressListeners = []; + this._progressiveReadListeners = []; + this._readyCapability = createPromiseCapability(); + } + PDFDataRangeTransport.prototype = + /** @lends PDFDataRangeTransport.prototype */ { + addRangeListener: + function PDFDataRangeTransport_addRangeListener(listener) { + this._rangeListeners.push(listener); + }, + + addProgressListener: + function PDFDataRangeTransport_addProgressListener(listener) { + this._progressListeners.push(listener); + }, + + addProgressiveReadListener: + function PDFDataRangeTransport_addProgressiveReadListener(listener) { + this._progressiveReadListeners.push(listener); + }, + + onDataRange: function PDFDataRangeTransport_onDataRange(begin, chunk) { + var listeners = this._rangeListeners; + for (var i = 0, n = listeners.length; i < n; ++i) { + listeners[i](begin, chunk); + } + }, + + onDataProgress: function PDFDataRangeTransport_onDataProgress(loaded) { + this._readyCapability.promise.then(function () { + var listeners = this._progressListeners; + for (var i = 0, n = listeners.length; i < n; ++i) { + listeners[i](loaded); + } + }.bind(this)); + }, + + onDataProgressiveRead: + function PDFDataRangeTransport_onDataProgress(chunk) { + this._readyCapability.promise.then(function () { + var listeners = this._progressiveReadListeners; + for (var i = 0, n = listeners.length; i < n; ++i) { + listeners[i](chunk); + } + }.bind(this)); + }, + + transportReady: function PDFDataRangeTransport_transportReady() { + this._readyCapability.resolve(); + }, + + requestDataRange: + function PDFDataRangeTransport_requestDataRange(begin, end) { + throw new Error('Abstract method PDFDataRangeTransport.requestDataRange'); + } + }; + return PDFDataRangeTransport; +})(); + +PDFJS.PDFDataRangeTransport = PDFDataRangeTransport; + +/** + * Proxy to a PDFDocument in the worker thread. Also, contains commonly used + * properties that can be read synchronously. + * @class + */ +var PDFDocumentProxy = (function PDFDocumentProxyClosure() { + function PDFDocumentProxy(pdfInfo, transport) { + this.pdfInfo = pdfInfo; + this.transport = transport; + } + PDFDocumentProxy.prototype = /** @lends PDFDocumentProxy.prototype */ { + /** + * @return {number} Total number of pages the PDF contains. + */ + get numPages() { + return this.pdfInfo.numPages; + }, + /** + * @return {string} A unique ID to identify a PDF. Not guaranteed to be + * unique. + */ + get fingerprint() { + return this.pdfInfo.fingerprint; + }, + /** + * @param {number} pageNumber The page number to get. The first page is 1. + * @return {Promise} A promise that is resolved with a {@link PDFPageProxy} + * object. + */ + getPage: function PDFDocumentProxy_getPage(pageNumber) { + return this.transport.getPage(pageNumber); + }, + /** + * @param {{num: number, gen: number}} ref The page reference. Must have + * the 'num' and 'gen' properties. + * @return {Promise} A promise that is resolved with the page index that is + * associated with the reference. + */ + getPageIndex: function PDFDocumentProxy_getPageIndex(ref) { + return this.transport.getPageIndex(ref); + }, + /** + * @return {Promise} A promise that is resolved with a lookup table for + * mapping named destinations to reference numbers. + * + * This can be slow for large documents: use getDestination instead + */ + getDestinations: function PDFDocumentProxy_getDestinations() { + return this.transport.getDestinations(); + }, + /** + * @param {string} id The named destination to get. + * @return {Promise} A promise that is resolved with all information + * of the given named destination. + */ + getDestination: function PDFDocumentProxy_getDestination(id) { + return this.transport.getDestination(id); + }, + /** + * @return {Promise} A promise that is resolved with a lookup table for + * mapping named attachments to their content. + */ + getAttachments: function PDFDocumentProxy_getAttachments() { + return this.transport.getAttachments(); + }, + /** + * @return {Promise} A promise that is resolved with an array of all the + * JavaScript strings in the name tree. + */ + getJavaScript: function PDFDocumentProxy_getJavaScript() { + return this.transport.getJavaScript(); + }, + /** + * @return {Promise} A promise that is resolved with an {Array} that is a + * tree outline (if it has one) of the PDF. The tree is in the format of: + * [ + * { + * title: string, + * bold: boolean, + * italic: boolean, + * color: rgb array, + * dest: dest obj, + * items: array of more items like this + * }, + * ... + * ]. + */ + getOutline: function PDFDocumentProxy_getOutline() { + return this.transport.getOutline(); + }, + /** + * @return {Promise} A promise that is resolved with an {Object} that has + * info and metadata properties. Info is an {Object} filled with anything + * available in the information dictionary and similarly metadata is a + * {Metadata} object with information from the metadata section of the PDF. + */ + getMetadata: function PDFDocumentProxy_getMetadata() { + return this.transport.getMetadata(); + }, + /** + * @return {Promise} A promise that is resolved with a TypedArray that has + * the raw data from the PDF. + */ + getData: function PDFDocumentProxy_getData() { + return this.transport.getData(); + }, + /** + * @return {Promise} A promise that is resolved when the document's data + * is loaded. It is resolved with an {Object} that contains the length + * property that indicates size of the PDF data in bytes. + */ + getDownloadInfo: function PDFDocumentProxy_getDownloadInfo() { + return this.transport.downloadInfoCapability.promise; + }, + /** + * @return {Promise} A promise this is resolved with current stats about + * document structures (see {@link PDFDocumentStats}). + */ + getStats: function PDFDocumentProxy_getStats() { + return this.transport.getStats(); + }, + /** + * Cleans up resources allocated by the document, e.g. created @font-face. + */ + cleanup: function PDFDocumentProxy_cleanup() { + this.transport.startCleanup(); + }, + /** + * Destroys current document instance and terminates worker. + */ + destroy: function PDFDocumentProxy_destroy() { + this.transport.destroy(); + } + }; + return PDFDocumentProxy; +})(); + +/** + * Page text content. + * + * @typedef {Object} TextContent + * @property {array} items - array of {@link TextItem} + * @property {Object} styles - {@link TextStyles} objects, indexed by font + * name. + */ + +/** + * Page text content part. + * + * @typedef {Object} TextItem + * @property {string} str - text content. + * @property {string} dir - text direction: 'ttb', 'ltr' or 'rtl'. + * @property {array} transform - transformation matrix. + * @property {number} width - width in device space. + * @property {number} height - height in device space. + * @property {string} fontName - font name used by pdf.js for converted font. + */ + +/** + * Text style. + * + * @typedef {Object} TextStyle + * @property {number} ascent - font ascent. + * @property {number} descent - font descent. + * @property {boolean} vertical - text is in vertical mode. + * @property {string} fontFamily - possible font family + */ + +/** + * Page render parameters. + * + * @typedef {Object} RenderParameters + * @property {Object} canvasContext - A 2D context of a DOM Canvas object. + * @property {PDFJS.PageViewport} viewport - Rendering viewport obtained by + * calling of PDFPage.getViewport method. + * @property {string} intent - Rendering intent, can be 'display' or 'print' + * (default value is 'display'). + * @property {Object} imageLayer - (optional) An object that has beginLayout, + * endLayout and appendImage functions. + * @property {function} continueCallback - (deprecated) A function that will be + * called each time the rendering is paused. To continue + * rendering call the function that is the first argument + * to the callback. + */ + +/** + * PDF page operator list. + * + * @typedef {Object} PDFOperatorList + * @property {Array} fnArray - Array containing the operator functions. + * @property {Array} argsArray - Array containing the arguments of the + * functions. + */ + +/** + * Proxy to a PDFPage in the worker thread. + * @class + */ +var PDFPageProxy = (function PDFPageProxyClosure() { + function PDFPageProxy(pageIndex, pageInfo, transport) { + this.pageIndex = pageIndex; + this.pageInfo = pageInfo; + this.transport = transport; + this.stats = new StatTimer(); + this.stats.enabled = !!globalScope.PDFJS.enableStats; + this.commonObjs = transport.commonObjs; + this.objs = new PDFObjects(); + this.cleanupAfterRender = false; + this.pendingDestroy = false; + this.intentStates = {}; + } + PDFPageProxy.prototype = /** @lends PDFPageProxy.prototype */ { + /** + * @return {number} Page number of the page. First page is 1. + */ + get pageNumber() { + return this.pageIndex + 1; + }, + /** + * @return {number} The number of degrees the page is rotated clockwise. + */ + get rotate() { + return this.pageInfo.rotate; + }, + /** + * @return {Object} The reference that points to this page. It has 'num' and + * 'gen' properties. + */ + get ref() { + return this.pageInfo.ref; + }, + /** + * @return {Array} An array of the visible portion of the PDF page in the + * user space units - [x1, y1, x2, y2]. + */ + get view() { + return this.pageInfo.view; + }, + /** + * @param {number} scale The desired scale of the viewport. + * @param {number} rotate Degrees to rotate the viewport. If omitted this + * defaults to the page rotation. + * @return {PDFJS.PageViewport} Contains 'width' and 'height' properties + * along with transforms required for rendering. + */ + getViewport: function PDFPageProxy_getViewport(scale, rotate) { + if (arguments.length < 2) { + rotate = this.rotate; + } + return new PDFJS.PageViewport(this.view, scale, rotate, 0, 0); + }, + /** + * @return {Promise} A promise that is resolved with an {Array} of the + * annotation objects. + */ + getAnnotations: function PDFPageProxy_getAnnotations() { + if (this.annotationsPromise) { + return this.annotationsPromise; + } + + var promise = this.transport.getAnnotations(this.pageIndex); + this.annotationsPromise = promise; + return promise; + }, + /** + * Begins the process of rendering a page to the desired context. + * @param {RenderParameters} params Page render parameters. + * @return {RenderTask} An object that contains the promise, which + * is resolved when the page finishes rendering. + */ + render: function PDFPageProxy_render(params) { + var stats = this.stats; + stats.time('Overall'); + + // If there was a pending destroy cancel it so no cleanup happens during + // this call to render. + this.pendingDestroy = false; + + var renderingIntent = (params.intent === 'print' ? 'print' : 'display'); + + if (!this.intentStates[renderingIntent]) { + this.intentStates[renderingIntent] = {}; + } + var intentState = this.intentStates[renderingIntent]; + + // If there's no displayReadyCapability yet, then the operatorList + // was never requested before. Make the request and create the promise. + if (!intentState.displayReadyCapability) { + intentState.receivingOperatorList = true; + intentState.displayReadyCapability = createPromiseCapability(); + intentState.operatorList = { + fnArray: [], + argsArray: [], + lastChunk: false + }; + + this.stats.time('Page Request'); + this.transport.messageHandler.send('RenderPageRequest', { + pageIndex: this.pageNumber - 1, + intent: renderingIntent + }); + } + + var internalRenderTask = new InternalRenderTask(complete, params, + this.objs, + this.commonObjs, + intentState.operatorList, + this.pageNumber); + if (!intentState.renderTasks) { + intentState.renderTasks = []; + } + intentState.renderTasks.push(internalRenderTask); + var renderTask = internalRenderTask.task; + + // Obsolete parameter support + if (params.continueCallback) { + renderTask.onContinue = params.continueCallback; + } + + var self = this; + intentState.displayReadyCapability.promise.then( + function pageDisplayReadyPromise(transparency) { + if (self.pendingDestroy) { + complete(); + return; + } + stats.time('Rendering'); + internalRenderTask.initalizeGraphics(transparency); + internalRenderTask.operatorListChanged(); + }, + function pageDisplayReadPromiseError(reason) { + complete(reason); + } + ); + + function complete(error) { + var i = intentState.renderTasks.indexOf(internalRenderTask); + if (i >= 0) { + intentState.renderTasks.splice(i, 1); + } + + if (self.cleanupAfterRender) { + self.pendingDestroy = true; + } + self._tryDestroy(); + + if (error) { + internalRenderTask.capability.reject(error); + } else { + internalRenderTask.capability.resolve(); + } + stats.timeEnd('Rendering'); + stats.timeEnd('Overall'); + } + + return renderTask; + }, + + /** + * @return {Promise} A promise resolved with an {@link PDFOperatorList} + * object that represents page's operator list. + */ + getOperatorList: function PDFPageProxy_getOperatorList() { + function operatorListChanged() { + if (intentState.operatorList.lastChunk) { + intentState.opListReadCapability.resolve(intentState.operatorList); + } + } + + var renderingIntent = 'oplist'; + if (!this.intentStates[renderingIntent]) { + this.intentStates[renderingIntent] = {}; + } + var intentState = this.intentStates[renderingIntent]; + + if (!intentState.opListReadCapability) { + var opListTask = {}; + opListTask.operatorListChanged = operatorListChanged; + intentState.receivingOperatorList = true; + intentState.opListReadCapability = createPromiseCapability(); + intentState.renderTasks = []; + intentState.renderTasks.push(opListTask); + intentState.operatorList = { + fnArray: [], + argsArray: [], + lastChunk: false + }; + + this.transport.messageHandler.send('RenderPageRequest', { + pageIndex: this.pageIndex, + intent: renderingIntent + }); + } + return intentState.opListReadCapability.promise; + }, + + /** + * @return {Promise} That is resolved a {@link TextContent} + * object that represent the page text content. + */ + getTextContent: function PDFPageProxy_getTextContent() { + return this.transport.messageHandler.sendWithPromise('GetTextContent', { + pageIndex: this.pageNumber - 1 + }); + }, + /** + * Destroys resources allocated by the page. + */ + destroy: function PDFPageProxy_destroy() { + this.pendingDestroy = true; + this._tryDestroy(); + }, + /** + * For internal use only. Attempts to clean up if rendering is in a state + * where that's possible. + * @ignore + */ + _tryDestroy: function PDFPageProxy__destroy() { + if (!this.pendingDestroy || + Object.keys(this.intentStates).some(function(intent) { + var intentState = this.intentStates[intent]; + return (intentState.renderTasks.length !== 0 || + intentState.receivingOperatorList); + }, this)) { + return; + } + + Object.keys(this.intentStates).forEach(function(intent) { + delete this.intentStates[intent]; + }, this); + this.objs.clear(); + this.annotationsPromise = null; + this.pendingDestroy = false; + }, + /** + * For internal use only. + * @ignore + */ + _startRenderPage: function PDFPageProxy_startRenderPage(transparency, + intent) { + var intentState = this.intentStates[intent]; + // TODO Refactor RenderPageRequest to separate rendering + // and operator list logic + if (intentState.displayReadyCapability) { + intentState.displayReadyCapability.resolve(transparency); + } + }, + /** + * For internal use only. + * @ignore + */ + _renderPageChunk: function PDFPageProxy_renderPageChunk(operatorListChunk, + intent) { + var intentState = this.intentStates[intent]; + var i, ii; + // Add the new chunk to the current operator list. + for (i = 0, ii = operatorListChunk.length; i < ii; i++) { + intentState.operatorList.fnArray.push(operatorListChunk.fnArray[i]); + intentState.operatorList.argsArray.push( + operatorListChunk.argsArray[i]); + } + intentState.operatorList.lastChunk = operatorListChunk.lastChunk; + + // Notify all the rendering tasks there are more operators to be consumed. + for (i = 0; i < intentState.renderTasks.length; i++) { + intentState.renderTasks[i].operatorListChanged(); + } + + if (operatorListChunk.lastChunk) { + intentState.receivingOperatorList = false; + this._tryDestroy(); + } + } + }; + return PDFPageProxy; +})(); + +/** + * For internal use only. + * @ignore + */ +var WorkerTransport = (function WorkerTransportClosure() { + function WorkerTransport(workerInitializedCapability, pdfDataRangeTransport) { + this.pdfDataRangeTransport = pdfDataRangeTransport; + this.workerInitializedCapability = workerInitializedCapability; + this.commonObjs = new PDFObjects(); + + this.loadingTask = null; + + this.pageCache = []; + this.pagePromises = []; + this.downloadInfoCapability = createPromiseCapability(); + + // If worker support isn't disabled explicit and the browser has worker + // support, create a new web worker and test if it/the browser fullfills + // all requirements to run parts of pdf.js in a web worker. + // Right now, the requirement is, that an Uint8Array is still an Uint8Array + // as it arrives on the worker. Chrome added this with version 15. +//#if !SINGLE_FILE + if (!globalScope.PDFJS.disableWorker && typeof Worker !== 'undefined') { + var workerSrc = PDFJS.workerSrc; + if (!workerSrc) { + error('No PDFJS.workerSrc specified'); + } + + try { + // Some versions of FF can't create a worker on localhost, see: + // https://bugzilla.mozilla.org/show_bug.cgi?id=683280 + var worker = new Worker(workerSrc); + var messageHandler = new MessageHandler('main', worker); + this.messageHandler = messageHandler; + + messageHandler.on('test', function transportTest(data) { + var supportTypedArray = data && data.supportTypedArray; + if (supportTypedArray) { + this.worker = worker; + if (!data.supportTransfers) { + PDFJS.postMessageTransfers = false; + } + this.setupMessageHandler(messageHandler); + workerInitializedCapability.resolve(); + } else { + this.setupFakeWorker(); + } + }.bind(this)); + + var testObj = new Uint8Array([PDFJS.postMessageTransfers ? 255 : 0]); + // Some versions of Opera throw a DATA_CLONE_ERR on serializing the + // typed array. Also, checking if we can use transfers. + try { + messageHandler.send('test', testObj, [testObj.buffer]); + } catch (ex) { + info('Cannot use postMessage transfers'); + testObj[0] = 0; + messageHandler.send('test', testObj); + } + return; + } catch (e) { + info('The worker has been disabled.'); + } + } +//#endif + // Either workers are disabled, not supported or have thrown an exception. + // Thus, we fallback to a faked worker. + this.setupFakeWorker(); + } + WorkerTransport.prototype = { + destroy: function WorkerTransport_destroy() { + this.pageCache = []; + this.pagePromises = []; + var self = this; + this.messageHandler.sendWithPromise('Terminate', null).then(function () { + FontLoader.clear(); + if (self.worker) { + self.worker.terminate(); + } + }); + }, + + setupFakeWorker: function WorkerTransport_setupFakeWorker() { + globalScope.PDFJS.disableWorker = true; + + if (!PDFJS.fakeWorkerFilesLoadedCapability) { + PDFJS.fakeWorkerFilesLoadedCapability = createPromiseCapability(); + // In the developer build load worker_loader which in turn loads all the + // other files and resolves the promise. In production only the + // pdf.worker.js file is needed. +//#if !PRODUCTION + Util.loadScript(PDFJS.workerSrc); +//#endif +//#if PRODUCTION && SINGLE_FILE +// PDFJS.fakeWorkerFilesLoadedCapability.resolve(); +//#endif +//#if PRODUCTION && !SINGLE_FILE +// Util.loadScript(PDFJS.workerSrc, function() { +// PDFJS.fakeWorkerFilesLoadedCapability.resolve(); +// }); +//#endif + } + PDFJS.fakeWorkerFilesLoadedCapability.promise.then(function () { + warn('Setting up fake worker.'); + // If we don't use a worker, just post/sendMessage to the main thread. + var fakeWorker = { + postMessage: function WorkerTransport_postMessage(obj) { + fakeWorker.onmessage({data: obj}); + }, + terminate: function WorkerTransport_terminate() {} + }; + + var messageHandler = new MessageHandler('main', fakeWorker); + this.setupMessageHandler(messageHandler); + + // If the main thread is our worker, setup the handling for the messages + // the main thread sends to it self. + PDFJS.WorkerMessageHandler.setup(messageHandler); + + this.workerInitializedCapability.resolve(); + }.bind(this)); + }, + + setupMessageHandler: + function WorkerTransport_setupMessageHandler(messageHandler) { + this.messageHandler = messageHandler; + + function updatePassword(password) { + messageHandler.send('UpdatePassword', password); + } + + var pdfDataRangeTransport = this.pdfDataRangeTransport; + if (pdfDataRangeTransport) { + pdfDataRangeTransport.addRangeListener(function(begin, chunk) { + messageHandler.send('OnDataRange', { + begin: begin, + chunk: chunk + }); + }); + + pdfDataRangeTransport.addProgressListener(function(loaded) { + messageHandler.send('OnDataProgress', { + loaded: loaded + }); + }); + + pdfDataRangeTransport.addProgressiveReadListener(function(chunk) { + messageHandler.send('OnDataRange', { + chunk: chunk + }); + }); + + messageHandler.on('RequestDataRange', + function transportDataRange(data) { + pdfDataRangeTransport.requestDataRange(data.begin, data.end); + }, this); + } + + messageHandler.on('GetDoc', function transportDoc(data) { + var pdfInfo = data.pdfInfo; + this.numPages = data.pdfInfo.numPages; + var pdfDocument = new PDFDocumentProxy(pdfInfo, this); + this.pdfDocument = pdfDocument; + this.loadingTask._capability.resolve(pdfDocument); + }, this); + + messageHandler.on('NeedPassword', + function transportNeedPassword(exception) { + var loadingTask = this.loadingTask; + if (loadingTask.onPassword) { + return loadingTask.onPassword(updatePassword, + PasswordResponses.NEED_PASSWORD); + } + loadingTask._capability.reject( + new PasswordException(exception.message, exception.code)); + }, this); + + messageHandler.on('IncorrectPassword', + function transportIncorrectPassword(exception) { + var loadingTask = this.loadingTask; + if (loadingTask.onPassword) { + return loadingTask.onPassword(updatePassword, + PasswordResponses.INCORRECT_PASSWORD); + } + loadingTask._capability.reject( + new PasswordException(exception.message, exception.code)); + }, this); + + messageHandler.on('InvalidPDF', function transportInvalidPDF(exception) { + this.loadingTask._capability.reject( + new InvalidPDFException(exception.message)); + }, this); + + messageHandler.on('MissingPDF', function transportMissingPDF(exception) { + this.loadingTask._capability.reject( + new MissingPDFException(exception.message)); + }, this); + + messageHandler.on('UnexpectedResponse', + function transportUnexpectedResponse(exception) { + this.loadingTask._capability.reject( + new UnexpectedResponseException(exception.message, exception.status)); + }, this); + + messageHandler.on('UnknownError', + function transportUnknownError(exception) { + this.loadingTask._capability.reject( + new UnknownErrorException(exception.message, exception.details)); + }, this); + + messageHandler.on('DataLoaded', function transportPage(data) { + this.downloadInfoCapability.resolve(data); + }, this); + + messageHandler.on('PDFManagerReady', function transportPage(data) { + if (this.pdfDataRangeTransport) { + this.pdfDataRangeTransport.transportReady(); + } + }, this); + + messageHandler.on('StartRenderPage', function transportRender(data) { + var page = this.pageCache[data.pageIndex]; + + page.stats.timeEnd('Page Request'); + page._startRenderPage(data.transparency, data.intent); + }, this); + + messageHandler.on('RenderPageChunk', function transportRender(data) { + var page = this.pageCache[data.pageIndex]; + + page._renderPageChunk(data.operatorList, data.intent); + }, this); + + messageHandler.on('commonobj', function transportObj(data) { + var id = data[0]; + var type = data[1]; + if (this.commonObjs.hasData(id)) { + return; + } + + switch (type) { + case 'Font': + var exportedData = data[2]; + + var font; + if ('error' in exportedData) { + var error = exportedData.error; + warn('Error during font loading: ' + error); + this.commonObjs.resolve(id, error); + break; + } else { + font = new FontFaceObject(exportedData); + } + + FontLoader.bind( + [font], + function fontReady(fontObjs) { + this.commonObjs.resolve(id, font); + }.bind(this) + ); + break; + case 'FontPath': + this.commonObjs.resolve(id, data[2]); + break; + default: + error('Got unknown common object type ' + type); + } + }, this); + + messageHandler.on('obj', function transportObj(data) { + var id = data[0]; + var pageIndex = data[1]; + var type = data[2]; + var pageProxy = this.pageCache[pageIndex]; + var imageData; + if (pageProxy.objs.hasData(id)) { + return; + } + + switch (type) { + case 'JpegStream': + imageData = data[3]; + loadJpegStream(id, imageData, pageProxy.objs); + break; + case 'Image': + imageData = data[3]; + pageProxy.objs.resolve(id, imageData); + + // heuristics that will allow not to store large data + var MAX_IMAGE_SIZE_TO_STORE = 8000000; + if (imageData && 'data' in imageData && + imageData.data.length > MAX_IMAGE_SIZE_TO_STORE) { + pageProxy.cleanupAfterRender = true; + } + break; + default: + error('Got unknown object type ' + type); + } + }, this); + + messageHandler.on('DocProgress', function transportDocProgress(data) { + var loadingTask = this.loadingTask; + if (loadingTask.onProgress) { + loadingTask.onProgress({ + loaded: data.loaded, + total: data.total + }); + } + }, this); + + messageHandler.on('PageError', function transportError(data) { + var page = this.pageCache[data.pageNum - 1]; + var intentState = page.intentStates[data.intent]; + if (intentState.displayReadyCapability) { + intentState.displayReadyCapability.reject(data.error); + } else { + error(data.error); + } + }, this); + + messageHandler.on('JpegDecode', function(data) { + var imageUrl = data[0]; + var components = data[1]; + if (components !== 3 && components !== 1) { + return Promise.reject( + new Error('Only 3 components or 1 component can be returned')); + } + + return new Promise(function (resolve, reject) { + var img = new Image(); + img.onload = function () { + var width = img.width; + var height = img.height; + var size = width * height; + var rgbaLength = size * 4; + var buf = new Uint8Array(size * components); + var tmpCanvas = createScratchCanvas(width, height); + var tmpCtx = tmpCanvas.getContext('2d'); + tmpCtx.drawImage(img, 0, 0); + var data = tmpCtx.getImageData(0, 0, width, height).data; + var i, j; + + if (components === 3) { + for (i = 0, j = 0; i < rgbaLength; i += 4, j += 3) { + buf[j] = data[i]; + buf[j + 1] = data[i + 1]; + buf[j + 2] = data[i + 2]; + } + } else if (components === 1) { + for (i = 0, j = 0; i < rgbaLength; i += 4, j++) { + buf[j] = data[i]; + } + } + resolve({ data: buf, width: width, height: height}); + }; + img.onerror = function () { + reject(new Error('JpegDecode failed to load image')); + }; + img.src = imageUrl; + }); + }); + }, + + fetchDocument: function WorkerTransport_fetchDocument(loadingTask, source) { + this.loadingTask = loadingTask; + + source.disableAutoFetch = PDFJS.disableAutoFetch; + source.disableStream = PDFJS.disableStream; + source.chunkedViewerLoading = !!this.pdfDataRangeTransport; + if (this.pdfDataRangeTransport) { + source.length = this.pdfDataRangeTransport.length; + source.initialData = this.pdfDataRangeTransport.initialData; + } + this.messageHandler.send('GetDocRequest', { + source: source, + disableRange: PDFJS.disableRange, + maxImageSize: PDFJS.maxImageSize, + cMapUrl: PDFJS.cMapUrl, + cMapPacked: PDFJS.cMapPacked, + disableFontFace: PDFJS.disableFontFace, + disableCreateObjectURL: PDFJS.disableCreateObjectURL, + verbosity: PDFJS.verbosity + }); + }, + + getData: function WorkerTransport_getData() { + return this.messageHandler.sendWithPromise('GetData', null); + }, + + getPage: function WorkerTransport_getPage(pageNumber, capability) { + if (pageNumber <= 0 || pageNumber > this.numPages || + (pageNumber|0) !== pageNumber) { + return Promise.reject(new Error('Invalid page request')); + } + + var pageIndex = pageNumber - 1; + if (pageIndex in this.pagePromises) { + return this.pagePromises[pageIndex]; + } + var promise = this.messageHandler.sendWithPromise('GetPage', { + pageIndex: pageIndex + }).then(function (pageInfo) { + var page = new PDFPageProxy(pageIndex, pageInfo, this); + this.pageCache[pageIndex] = page; + return page; + }.bind(this)); + this.pagePromises[pageIndex] = promise; + return promise; + }, + + getPageIndex: function WorkerTransport_getPageIndexByRef(ref) { + return this.messageHandler.sendWithPromise('GetPageIndex', { ref: ref }); + }, + + getAnnotations: function WorkerTransport_getAnnotations(pageIndex) { + return this.messageHandler.sendWithPromise('GetAnnotations', + { pageIndex: pageIndex }); + }, + + getDestinations: function WorkerTransport_getDestinations() { + return this.messageHandler.sendWithPromise('GetDestinations', null); + }, + + getDestination: function WorkerTransport_getDestination(id) { + return this.messageHandler.sendWithPromise('GetDestination', { id: id } ); + }, + + getAttachments: function WorkerTransport_getAttachments() { + return this.messageHandler.sendWithPromise('GetAttachments', null); + }, + + getJavaScript: function WorkerTransport_getJavaScript() { + return this.messageHandler.sendWithPromise('GetJavaScript', null); + }, + + getOutline: function WorkerTransport_getOutline() { + return this.messageHandler.sendWithPromise('GetOutline', null); + }, + + getMetadata: function WorkerTransport_getMetadata() { + return this.messageHandler.sendWithPromise('GetMetadata', null). + then(function transportMetadata(results) { + return { + info: results[0], + metadata: (results[1] ? new PDFJS.Metadata(results[1]) : null) + }; + }); + }, + + getStats: function WorkerTransport_getStats() { + return this.messageHandler.sendWithPromise('GetStats', null); + }, + + startCleanup: function WorkerTransport_startCleanup() { + this.messageHandler.sendWithPromise('Cleanup', null). + then(function endCleanup() { + for (var i = 0, ii = this.pageCache.length; i < ii; i++) { + var page = this.pageCache[i]; + if (page) { + page.destroy(); + } + } + this.commonObjs.clear(); + FontLoader.clear(); + }.bind(this)); + } + }; + return WorkerTransport; + +})(); + +/** + * A PDF document and page is built of many objects. E.g. there are objects + * for fonts, images, rendering code and such. These objects might get processed + * inside of a worker. The `PDFObjects` implements some basic functions to + * manage these objects. + * @ignore + */ +var PDFObjects = (function PDFObjectsClosure() { + function PDFObjects() { + this.objs = {}; + } + + PDFObjects.prototype = { + /** + * Internal function. + * Ensures there is an object defined for `objId`. + */ + ensureObj: function PDFObjects_ensureObj(objId) { + if (this.objs[objId]) { + return this.objs[objId]; + } + + var obj = { + capability: createPromiseCapability(), + data: null, + resolved: false + }; + this.objs[objId] = obj; + + return obj; + }, + + /** + * If called *without* callback, this returns the data of `objId` but the + * object needs to be resolved. If it isn't, this function throws. + * + * If called *with* a callback, the callback is called with the data of the + * object once the object is resolved. That means, if you call this + * function and the object is already resolved, the callback gets called + * right away. + */ + get: function PDFObjects_get(objId, callback) { + // If there is a callback, then the get can be async and the object is + // not required to be resolved right now + if (callback) { + this.ensureObj(objId).capability.promise.then(callback); + return null; + } + + // If there isn't a callback, the user expects to get the resolved data + // directly. + var obj = this.objs[objId]; + + // If there isn't an object yet or the object isn't resolved, then the + // data isn't ready yet! + if (!obj || !obj.resolved) { + error('Requesting object that isn\'t resolved yet ' + objId); + } + + return obj.data; + }, + + /** + * Resolves the object `objId` with optional `data`. + */ + resolve: function PDFObjects_resolve(objId, data) { + var obj = this.ensureObj(objId); + + obj.resolved = true; + obj.data = data; + obj.capability.resolve(data); + }, + + isResolved: function PDFObjects_isResolved(objId) { + var objs = this.objs; + + if (!objs[objId]) { + return false; + } else { + return objs[objId].resolved; + } + }, + + hasData: function PDFObjects_hasData(objId) { + return this.isResolved(objId); + }, + + /** + * Returns the data of `objId` if object exists, null otherwise. + */ + getData: function PDFObjects_getData(objId) { + var objs = this.objs; + if (!objs[objId] || !objs[objId].resolved) { + return null; + } else { + return objs[objId].data; + } + }, + + clear: function PDFObjects_clear() { + this.objs = {}; + } + }; + return PDFObjects; +})(); + +/** + * Allows controlling of the rendering tasks. + * @class + */ +var RenderTask = (function RenderTaskClosure() { + function RenderTask(internalRenderTask) { + this._internalRenderTask = internalRenderTask; + + /** + * Callback for incremental rendering -- a function that will be called + * each time the rendering is paused. To continue rendering call the + * function that is the first argument to the callback. + * @type {function} + */ + this.onContinue = null; + } + + RenderTask.prototype = /** @lends RenderTask.prototype */ { + /** + * Promise for rendering task completion. + * @return {Promise} + */ + get promise() { + return this._internalRenderTask.capability.promise; + }, + + /** + * Cancels the rendering task. If the task is currently rendering it will + * not be cancelled until graphics pauses with a timeout. The promise that + * this object extends will resolved when cancelled. + */ + cancel: function RenderTask_cancel() { + this._internalRenderTask.cancel(); + }, + + /** + * Registers callbacks to indicate the rendering task completion. + * + * @param {function} onFulfilled The callback for the rendering completion. + * @param {function} onRejected The callback for the rendering failure. + * @return {Promise} A promise that is resolved after the onFulfilled or + * onRejected callback. + */ + then: function RenderTask_then(onFulfilled, onRejected) { + return this.promise.then.apply(this.promise, arguments); + } + }; + + return RenderTask; +})(); + +/** + * For internal use only. + * @ignore + */ +var InternalRenderTask = (function InternalRenderTaskClosure() { + + function InternalRenderTask(callback, params, objs, commonObjs, operatorList, + pageNumber) { + this.callback = callback; + this.params = params; + this.objs = objs; + this.commonObjs = commonObjs; + this.operatorListIdx = null; + this.operatorList = operatorList; + this.pageNumber = pageNumber; + this.running = false; + this.graphicsReadyCallback = null; + this.graphicsReady = false; + this.cancelled = false; + this.capability = createPromiseCapability(); + this.task = new RenderTask(this); + // caching this-bound methods + this._continueBound = this._continue.bind(this); + this._scheduleNextBound = this._scheduleNext.bind(this); + this._nextBound = this._next.bind(this); + } + + InternalRenderTask.prototype = { + + initalizeGraphics: + function InternalRenderTask_initalizeGraphics(transparency) { + + if (this.cancelled) { + return; + } + if (PDFJS.pdfBug && 'StepperManager' in globalScope && + globalScope.StepperManager.enabled) { + this.stepper = globalScope.StepperManager.create(this.pageNumber - 1); + this.stepper.init(this.operatorList); + this.stepper.nextBreakPoint = this.stepper.getNextBreakPoint(); + } + + var params = this.params; + this.gfx = new CanvasGraphics(params.canvasContext, this.commonObjs, + this.objs, params.imageLayer); + + this.gfx.beginDrawing(params.viewport, transparency); + this.operatorListIdx = 0; + this.graphicsReady = true; + if (this.graphicsReadyCallback) { + this.graphicsReadyCallback(); + } + }, + + cancel: function InternalRenderTask_cancel() { + this.running = false; + this.cancelled = true; + this.callback('cancelled'); + }, + + operatorListChanged: function InternalRenderTask_operatorListChanged() { + if (!this.graphicsReady) { + if (!this.graphicsReadyCallback) { + this.graphicsReadyCallback = this._continueBound; + } + return; + } + + if (this.stepper) { + this.stepper.updateOperatorList(this.operatorList); + } + + if (this.running) { + return; + } + this._continue(); + }, + + _continue: function InternalRenderTask__continue() { + this.running = true; + if (this.cancelled) { + return; + } + if (this.task.onContinue) { + this.task.onContinue.call(this.task, this._scheduleNextBound); + } else { + this._scheduleNext(); + } + }, + + _scheduleNext: function InternalRenderTask__scheduleNext() { + window.requestAnimationFrame(this._nextBound); + }, + + _next: function InternalRenderTask__next() { + if (this.cancelled) { + return; + } + this.operatorListIdx = this.gfx.executeOperatorList(this.operatorList, + this.operatorListIdx, + this._continueBound, + this.stepper); + if (this.operatorListIdx === this.operatorList.argsArray.length) { + this.running = false; + if (this.operatorList.lastChunk) { + this.gfx.endDrawing(); + this.callback(); + } + } + } + + }; + + return InternalRenderTask; +})(); + + +var Metadata = PDFJS.Metadata = (function MetadataClosure() { + function fixMetadata(meta) { + return meta.replace(/>\\376\\377([^<]+)/g, function(all, codes) { + var bytes = codes.replace(/\\([0-3])([0-7])([0-7])/g, + function(code, d1, d2, d3) { + return String.fromCharCode(d1 * 64 + d2 * 8 + d3 * 1); + }); + var chars = ''; + for (var i = 0; i < bytes.length; i += 2) { + var code = bytes.charCodeAt(i) * 256 + bytes.charCodeAt(i + 1); + chars += code >= 32 && code < 127 && code !== 60 && code !== 62 && + code !== 38 && false ? String.fromCharCode(code) : + '&#x' + (0x10000 + code).toString(16).substring(1) + ';'; + } + return '>' + chars; + }); + } + + function Metadata(meta) { + if (typeof meta === 'string') { + // Ghostscript produces invalid metadata + meta = fixMetadata(meta); + + var parser = new DOMParser(); + meta = parser.parseFromString(meta, 'application/xml'); + } else if (!(meta instanceof Document)) { + error('Metadata: Invalid metadata object'); + } + + this.metaDocument = meta; + this.metadata = {}; + this.parse(); + } + + Metadata.prototype = { + parse: function Metadata_parse() { + var doc = this.metaDocument; + var rdf = doc.documentElement; + + if (rdf.nodeName.toLowerCase() !== 'rdf:rdf') { // Wrapped in + rdf = rdf.firstChild; + while (rdf && rdf.nodeName.toLowerCase() !== 'rdf:rdf') { + rdf = rdf.nextSibling; + } + } + + var nodeName = (rdf) ? rdf.nodeName.toLowerCase() : null; + if (!rdf || nodeName !== 'rdf:rdf' || !rdf.hasChildNodes()) { + return; + } + + var children = rdf.childNodes, desc, entry, name, i, ii, length, iLength; + for (i = 0, length = children.length; i < length; i++) { + desc = children[i]; + if (desc.nodeName.toLowerCase() !== 'rdf:description') { + continue; + } + + for (ii = 0, iLength = desc.childNodes.length; ii < iLength; ii++) { + if (desc.childNodes[ii].nodeName.toLowerCase() !== '#text') { + entry = desc.childNodes[ii]; + name = entry.nodeName.toLowerCase(); + this.metadata[name] = entry.textContent.trim(); + } + } + } + }, + + get: function Metadata_get(name) { + return this.metadata[name] || null; + }, + + has: function Metadata_has(name) { + return typeof this.metadata[name] !== 'undefined'; + } + }; + + return Metadata; +})(); + + +// contexts store most of the state we need natively. +// However, PDF needs a bit more state, which we store here. + +// Minimal font size that would be used during canvas fillText operations. +var MIN_FONT_SIZE = 16; +// Maximum font size that would be used during canvas fillText operations. +var MAX_FONT_SIZE = 100; +var MAX_GROUP_SIZE = 4096; + +// Heuristic value used when enforcing minimum line widths. +var MIN_WIDTH_FACTOR = 0.65; + +var COMPILE_TYPE3_GLYPHS = true; +var MAX_SIZE_TO_COMPILE = 1000; + +var FULL_CHUNK_HEIGHT = 16; + +function createScratchCanvas(width, height) { + var canvas = document.createElement('canvas'); + canvas.width = width; + canvas.height = height; + return canvas; +} + +function addContextCurrentTransform(ctx) { + // If the context doesn't expose a `mozCurrentTransform`, add a JS based one. + if (!ctx.mozCurrentTransform) { + ctx._originalSave = ctx.save; + ctx._originalRestore = ctx.restore; + ctx._originalRotate = ctx.rotate; + ctx._originalScale = ctx.scale; + ctx._originalTranslate = ctx.translate; + ctx._originalTransform = ctx.transform; + ctx._originalSetTransform = ctx.setTransform; + + ctx._transformMatrix = ctx._transformMatrix || [1, 0, 0, 1, 0, 0]; + ctx._transformStack = []; + + Object.defineProperty(ctx, 'mozCurrentTransform', { + get: function getCurrentTransform() { + return this._transformMatrix; + } + }); + + Object.defineProperty(ctx, 'mozCurrentTransformInverse', { + get: function getCurrentTransformInverse() { + // Calculation done using WolframAlpha: + // http://www.wolframalpha.com/input/? + // i=Inverse+{{a%2C+c%2C+e}%2C+{b%2C+d%2C+f}%2C+{0%2C+0%2C+1}} + + var m = this._transformMatrix; + var a = m[0], b = m[1], c = m[2], d = m[3], e = m[4], f = m[5]; + + var ad_bc = a * d - b * c; + var bc_ad = b * c - a * d; + + return [ + d / ad_bc, + b / bc_ad, + c / bc_ad, + a / ad_bc, + (d * e - c * f) / bc_ad, + (b * e - a * f) / ad_bc + ]; + } + }); + + ctx.save = function ctxSave() { + var old = this._transformMatrix; + this._transformStack.push(old); + this._transformMatrix = old.slice(0, 6); + + this._originalSave(); + }; + + ctx.restore = function ctxRestore() { + var prev = this._transformStack.pop(); + if (prev) { + this._transformMatrix = prev; + this._originalRestore(); + } + }; + + ctx.translate = function ctxTranslate(x, y) { + var m = this._transformMatrix; + m[4] = m[0] * x + m[2] * y + m[4]; + m[5] = m[1] * x + m[3] * y + m[5]; + + this._originalTranslate(x, y); + }; + + ctx.scale = function ctxScale(x, y) { + var m = this._transformMatrix; + m[0] = m[0] * x; + m[1] = m[1] * x; + m[2] = m[2] * y; + m[3] = m[3] * y; + + this._originalScale(x, y); + }; + + ctx.transform = function ctxTransform(a, b, c, d, e, f) { + var m = this._transformMatrix; + this._transformMatrix = [ + m[0] * a + m[2] * b, + m[1] * a + m[3] * b, + m[0] * c + m[2] * d, + m[1] * c + m[3] * d, + m[0] * e + m[2] * f + m[4], + m[1] * e + m[3] * f + m[5] + ]; + + ctx._originalTransform(a, b, c, d, e, f); + }; + + ctx.setTransform = function ctxSetTransform(a, b, c, d, e, f) { + this._transformMatrix = [a, b, c, d, e, f]; + + ctx._originalSetTransform(a, b, c, d, e, f); + }; + + ctx.rotate = function ctxRotate(angle) { + var cosValue = Math.cos(angle); + var sinValue = Math.sin(angle); + + var m = this._transformMatrix; + this._transformMatrix = [ + m[0] * cosValue + m[2] * sinValue, + m[1] * cosValue + m[3] * sinValue, + m[0] * (-sinValue) + m[2] * cosValue, + m[1] * (-sinValue) + m[3] * cosValue, + m[4], + m[5] + ]; + + this._originalRotate(angle); + }; + } +} + +var CachedCanvases = (function CachedCanvasesClosure() { + var cache = {}; + return { + getCanvas: function CachedCanvases_getCanvas(id, width, height, + trackTransform) { + var canvasEntry; + if (cache[id] !== undefined) { + canvasEntry = cache[id]; + canvasEntry.canvas.width = width; + canvasEntry.canvas.height = height; + // reset canvas transform for emulated mozCurrentTransform, if needed + canvasEntry.context.setTransform(1, 0, 0, 1, 0, 0); + } else { + var canvas = createScratchCanvas(width, height); + var ctx = canvas.getContext('2d'); + if (trackTransform) { + addContextCurrentTransform(ctx); + } + cache[id] = canvasEntry = {canvas: canvas, context: ctx}; + } + return canvasEntry; + }, + clear: function () { + for (var id in cache) { + var canvasEntry = cache[id]; + // Zeroing the width and height causes Firefox to release graphics + // resources immediately, which can greatly reduce memory consumption. + canvasEntry.canvas.width = 0; + canvasEntry.canvas.height = 0; + delete cache[id]; + } + } + }; +})(); + +function compileType3Glyph(imgData) { + var POINT_TO_PROCESS_LIMIT = 1000; + + var width = imgData.width, height = imgData.height; + var i, j, j0, width1 = width + 1; + var points = new Uint8Array(width1 * (height + 1)); + var POINT_TYPES = + new Uint8Array([0, 2, 4, 0, 1, 0, 5, 4, 8, 10, 0, 8, 0, 2, 1, 0]); + + // decodes bit-packed mask data + var lineSize = (width + 7) & ~7, data0 = imgData.data; + var data = new Uint8Array(lineSize * height), pos = 0, ii; + for (i = 0, ii = data0.length; i < ii; i++) { + var mask = 128, elem = data0[i]; + while (mask > 0) { + data[pos++] = (elem & mask) ? 0 : 255; + mask >>= 1; + } + } + + // finding iteresting points: every point is located between mask pixels, + // so there will be points of the (width + 1)x(height + 1) grid. Every point + // will have flags assigned based on neighboring mask pixels: + // 4 | 8 + // --P-- + // 2 | 1 + // We are interested only in points with the flags: + // - outside corners: 1, 2, 4, 8; + // - inside corners: 7, 11, 13, 14; + // - and, intersections: 5, 10. + var count = 0; + pos = 0; + if (data[pos] !== 0) { + points[0] = 1; + ++count; + } + for (j = 1; j < width; j++) { + if (data[pos] !== data[pos + 1]) { + points[j] = data[pos] ? 2 : 1; + ++count; + } + pos++; + } + if (data[pos] !== 0) { + points[j] = 2; + ++count; + } + for (i = 1; i < height; i++) { + pos = i * lineSize; + j0 = i * width1; + if (data[pos - lineSize] !== data[pos]) { + points[j0] = data[pos] ? 1 : 8; + ++count; + } + // 'sum' is the position of the current pixel configuration in the 'TYPES' + // array (in order 8-1-2-4, so we can use '>>2' to shift the column). + var sum = (data[pos] ? 4 : 0) + (data[pos - lineSize] ? 8 : 0); + for (j = 1; j < width; j++) { + sum = (sum >> 2) + (data[pos + 1] ? 4 : 0) + + (data[pos - lineSize + 1] ? 8 : 0); + if (POINT_TYPES[sum]) { + points[j0 + j] = POINT_TYPES[sum]; + ++count; + } + pos++; + } + if (data[pos - lineSize] !== data[pos]) { + points[j0 + j] = data[pos] ? 2 : 4; + ++count; + } + + if (count > POINT_TO_PROCESS_LIMIT) { + return null; + } + } + + pos = lineSize * (height - 1); + j0 = i * width1; + if (data[pos] !== 0) { + points[j0] = 8; + ++count; + } + for (j = 1; j < width; j++) { + if (data[pos] !== data[pos + 1]) { + points[j0 + j] = data[pos] ? 4 : 8; + ++count; + } + pos++; + } + if (data[pos] !== 0) { + points[j0 + j] = 4; + ++count; + } + if (count > POINT_TO_PROCESS_LIMIT) { + return null; + } + + // building outlines + var steps = new Int32Array([0, width1, -1, 0, -width1, 0, 0, 0, 1]); + var outlines = []; + for (i = 0; count && i <= height; i++) { + var p = i * width1; + var end = p + width; + while (p < end && !points[p]) { + p++; + } + if (p === end) { + continue; + } + var coords = [p % width1, i]; + + var type = points[p], p0 = p, pp; + do { + var step = steps[type]; + do { + p += step; + } while (!points[p]); + + pp = points[p]; + if (pp !== 5 && pp !== 10) { + // set new direction + type = pp; + // delete mark + points[p] = 0; + } else { // type is 5 or 10, ie, a crossing + // set new direction + type = pp & ((0x33 * type) >> 4); + // set new type for "future hit" + points[p] &= (type >> 2 | type << 2); + } + + coords.push(p % width1); + coords.push((p / width1) | 0); + --count; + } while (p0 !== p); + outlines.push(coords); + --i; + } + + var drawOutline = function(c) { + c.save(); + // the path shall be painted in [0..1]x[0..1] space + c.scale(1 / width, -1 / height); + c.translate(0, -height); + c.beginPath(); + for (var i = 0, ii = outlines.length; i < ii; i++) { + var o = outlines[i]; + c.moveTo(o[0], o[1]); + for (var j = 2, jj = o.length; j < jj; j += 2) { + c.lineTo(o[j], o[j+1]); + } + } + c.fill(); + c.beginPath(); + c.restore(); + }; + + return drawOutline; +} + +var CanvasExtraState = (function CanvasExtraStateClosure() { + function CanvasExtraState(old) { + // Are soft masks and alpha values shapes or opacities? + this.alphaIsShape = false; + this.fontSize = 0; + this.fontSizeScale = 1; + this.textMatrix = IDENTITY_MATRIX; + this.textMatrixScale = 1; + this.fontMatrix = FONT_IDENTITY_MATRIX; + this.leading = 0; + // Current point (in user coordinates) + this.x = 0; + this.y = 0; + // Start of text line (in text coordinates) + this.lineX = 0; + this.lineY = 0; + // Character and word spacing + this.charSpacing = 0; + this.wordSpacing = 0; + this.textHScale = 1; + this.textRenderingMode = TextRenderingMode.FILL; + this.textRise = 0; + // Default fore and background colors + this.fillColor = '#000000'; + this.strokeColor = '#000000'; + this.patternFill = false; + // Note: fill alpha applies to all non-stroking operations + this.fillAlpha = 1; + this.strokeAlpha = 1; + this.lineWidth = 1; + this.activeSMask = null; // nonclonable field (see the save method below) + + this.old = old; + } + + CanvasExtraState.prototype = { + clone: function CanvasExtraState_clone() { + return Object.create(this); + }, + setCurrentPoint: function CanvasExtraState_setCurrentPoint(x, y) { + this.x = x; + this.y = y; + } + }; + return CanvasExtraState; +})(); + +var CanvasGraphics = (function CanvasGraphicsClosure() { + // Defines the time the executeOperatorList is going to be executing + // before it stops and shedules a continue of execution. + var EXECUTION_TIME = 15; + // Defines the number of steps before checking the execution time + var EXECUTION_STEPS = 10; + + function CanvasGraphics(canvasCtx, commonObjs, objs, imageLayer) { + this.ctx = canvasCtx; + this.current = new CanvasExtraState(); + this.stateStack = []; + this.pendingClip = null; + this.pendingEOFill = false; + this.res = null; + this.xobjs = null; + this.commonObjs = commonObjs; + this.objs = objs; + this.imageLayer = imageLayer; + this.groupStack = []; + this.processingType3 = null; + // Patterns are painted relative to the initial page/form transform, see pdf + // spec 8.7.2 NOTE 1. + this.baseTransform = null; + this.baseTransformStack = []; + this.groupLevel = 0; + this.smaskStack = []; + this.smaskCounter = 0; + this.tempSMask = null; + if (canvasCtx) { + // NOTE: if mozCurrentTransform is polyfilled, then the current state of + // the transformation must already be set in canvasCtx._transformMatrix. + addContextCurrentTransform(canvasCtx); + } + this.cachedGetSinglePixelWidth = null; + } + + function putBinaryImageData(ctx, imgData) { + if (typeof ImageData !== 'undefined' && imgData instanceof ImageData) { + ctx.putImageData(imgData, 0, 0); + return; + } + + // Put the image data to the canvas in chunks, rather than putting the + // whole image at once. This saves JS memory, because the ImageData object + // is smaller. It also possibly saves C++ memory within the implementation + // of putImageData(). (E.g. in Firefox we make two short-lived copies of + // the data passed to putImageData()). |n| shouldn't be too small, however, + // because too many putImageData() calls will slow things down. + // + // Note: as written, if the last chunk is partial, the putImageData() call + // will (conceptually) put pixels past the bounds of the canvas. But + // that's ok; any such pixels are ignored. + + var height = imgData.height, width = imgData.width; + var partialChunkHeight = height % FULL_CHUNK_HEIGHT; + var fullChunks = (height - partialChunkHeight) / FULL_CHUNK_HEIGHT; + var totalChunks = partialChunkHeight === 0 ? fullChunks : fullChunks + 1; + + var chunkImgData = ctx.createImageData(width, FULL_CHUNK_HEIGHT); + var srcPos = 0, destPos; + var src = imgData.data; + var dest = chunkImgData.data; + var i, j, thisChunkHeight, elemsInThisChunk; + + // There are multiple forms in which the pixel data can be passed, and + // imgData.kind tells us which one this is. + if (imgData.kind === ImageKind.GRAYSCALE_1BPP) { + // Grayscale, 1 bit per pixel (i.e. black-and-white). + var srcLength = src.byteLength; + var dest32 = PDFJS.hasCanvasTypedArrays ? new Uint32Array(dest.buffer) : + new Uint32ArrayView(dest); + var dest32DataLength = dest32.length; + var fullSrcDiff = (width + 7) >> 3; + var white = 0xFFFFFFFF; + var black = (PDFJS.isLittleEndian || !PDFJS.hasCanvasTypedArrays) ? + 0xFF000000 : 0x000000FF; + for (i = 0; i < totalChunks; i++) { + thisChunkHeight = + (i < fullChunks) ? FULL_CHUNK_HEIGHT : partialChunkHeight; + destPos = 0; + for (j = 0; j < thisChunkHeight; j++) { + var srcDiff = srcLength - srcPos; + var k = 0; + var kEnd = (srcDiff > fullSrcDiff) ? width : srcDiff * 8 - 7; + var kEndUnrolled = kEnd & ~7; + var mask = 0; + var srcByte = 0; + for (; k < kEndUnrolled; k += 8) { + srcByte = src[srcPos++]; + dest32[destPos++] = (srcByte & 128) ? white : black; + dest32[destPos++] = (srcByte & 64) ? white : black; + dest32[destPos++] = (srcByte & 32) ? white : black; + dest32[destPos++] = (srcByte & 16) ? white : black; + dest32[destPos++] = (srcByte & 8) ? white : black; + dest32[destPos++] = (srcByte & 4) ? white : black; + dest32[destPos++] = (srcByte & 2) ? white : black; + dest32[destPos++] = (srcByte & 1) ? white : black; + } + for (; k < kEnd; k++) { + if (mask === 0) { + srcByte = src[srcPos++]; + mask = 128; + } + + dest32[destPos++] = (srcByte & mask) ? white : black; + mask >>= 1; + } + } + // We ran out of input. Make all remaining pixels transparent. + while (destPos < dest32DataLength) { + dest32[destPos++] = 0; + } + + ctx.putImageData(chunkImgData, 0, i * FULL_CHUNK_HEIGHT); + } + } else if (imgData.kind === ImageKind.RGBA_32BPP) { + // RGBA, 32-bits per pixel. + + j = 0; + elemsInThisChunk = width * FULL_CHUNK_HEIGHT * 4; + for (i = 0; i < fullChunks; i++) { + dest.set(src.subarray(srcPos, srcPos + elemsInThisChunk)); + srcPos += elemsInThisChunk; + + ctx.putImageData(chunkImgData, 0, j); + j += FULL_CHUNK_HEIGHT; + } + if (i < totalChunks) { + elemsInThisChunk = width * partialChunkHeight * 4; + dest.set(src.subarray(srcPos, srcPos + elemsInThisChunk)); + ctx.putImageData(chunkImgData, 0, j); + } + + } else if (imgData.kind === ImageKind.RGB_24BPP) { + // RGB, 24-bits per pixel. + thisChunkHeight = FULL_CHUNK_HEIGHT; + elemsInThisChunk = width * thisChunkHeight; + for (i = 0; i < totalChunks; i++) { + if (i >= fullChunks) { + thisChunkHeight = partialChunkHeight; + elemsInThisChunk = width * thisChunkHeight; + } + + destPos = 0; + for (j = elemsInThisChunk; j--;) { + dest[destPos++] = src[srcPos++]; + dest[destPos++] = src[srcPos++]; + dest[destPos++] = src[srcPos++]; + dest[destPos++] = 255; + } + ctx.putImageData(chunkImgData, 0, i * FULL_CHUNK_HEIGHT); + } + } else { + error('bad image kind: ' + imgData.kind); + } + } + + function putBinaryImageMask(ctx, imgData) { + var height = imgData.height, width = imgData.width; + var partialChunkHeight = height % FULL_CHUNK_HEIGHT; + var fullChunks = (height - partialChunkHeight) / FULL_CHUNK_HEIGHT; + var totalChunks = partialChunkHeight === 0 ? fullChunks : fullChunks + 1; + + var chunkImgData = ctx.createImageData(width, FULL_CHUNK_HEIGHT); + var srcPos = 0; + var src = imgData.data; + var dest = chunkImgData.data; + + for (var i = 0; i < totalChunks; i++) { + var thisChunkHeight = + (i < fullChunks) ? FULL_CHUNK_HEIGHT : partialChunkHeight; + + // Expand the mask so it can be used by the canvas. Any required + // inversion has already been handled. + var destPos = 3; // alpha component offset + for (var j = 0; j < thisChunkHeight; j++) { + var mask = 0; + for (var k = 0; k < width; k++) { + if (!mask) { + var elem = src[srcPos++]; + mask = 128; + } + dest[destPos] = (elem & mask) ? 0 : 255; + destPos += 4; + mask >>= 1; + } + } + ctx.putImageData(chunkImgData, 0, i * FULL_CHUNK_HEIGHT); + } + } + + function copyCtxState(sourceCtx, destCtx) { + var properties = ['strokeStyle', 'fillStyle', 'fillRule', 'globalAlpha', + 'lineWidth', 'lineCap', 'lineJoin', 'miterLimit', + 'globalCompositeOperation', 'font']; + for (var i = 0, ii = properties.length; i < ii; i++) { + var property = properties[i]; + if (sourceCtx[property] !== undefined) { + destCtx[property] = sourceCtx[property]; + } + } + if (sourceCtx.setLineDash !== undefined) { + destCtx.setLineDash(sourceCtx.getLineDash()); + destCtx.lineDashOffset = sourceCtx.lineDashOffset; + } else if (sourceCtx.mozDashOffset !== undefined) { + destCtx.mozDash = sourceCtx.mozDash; + destCtx.mozDashOffset = sourceCtx.mozDashOffset; + } + } + + function composeSMaskBackdrop(bytes, r0, g0, b0) { + var length = bytes.length; + for (var i = 3; i < length; i += 4) { + var alpha = bytes[i]; + if (alpha === 0) { + bytes[i - 3] = r0; + bytes[i - 2] = g0; + bytes[i - 1] = b0; + } else if (alpha < 255) { + var alpha_ = 255 - alpha; + bytes[i - 3] = (bytes[i - 3] * alpha + r0 * alpha_) >> 8; + bytes[i - 2] = (bytes[i - 2] * alpha + g0 * alpha_) >> 8; + bytes[i - 1] = (bytes[i - 1] * alpha + b0 * alpha_) >> 8; + } + } + } + + function composeSMaskAlpha(maskData, layerData) { + var length = maskData.length; + var scale = 1 / 255; + for (var i = 3; i < length; i += 4) { + var alpha = maskData[i]; + layerData[i] = (layerData[i] * alpha * scale) | 0; + } + } + + function composeSMaskLuminosity(maskData, layerData) { + var length = maskData.length; + for (var i = 3; i < length; i += 4) { + var y = (maskData[i - 3] * 77) + // * 0.3 / 255 * 0x10000 + (maskData[i - 2] * 152) + // * 0.59 .... + (maskData[i - 1] * 28); // * 0.11 .... + layerData[i] = (layerData[i] * y) >> 16; + } + } + + function genericComposeSMask(maskCtx, layerCtx, width, height, + subtype, backdrop) { + var hasBackdrop = !!backdrop; + var r0 = hasBackdrop ? backdrop[0] : 0; + var g0 = hasBackdrop ? backdrop[1] : 0; + var b0 = hasBackdrop ? backdrop[2] : 0; + + var composeFn; + if (subtype === 'Luminosity') { + composeFn = composeSMaskLuminosity; + } else { + composeFn = composeSMaskAlpha; + } + + // processing image in chunks to save memory + var PIXELS_TO_PROCESS = 1048576; + var chunkSize = Math.min(height, Math.ceil(PIXELS_TO_PROCESS / width)); + for (var row = 0; row < height; row += chunkSize) { + var chunkHeight = Math.min(chunkSize, height - row); + var maskData = maskCtx.getImageData(0, row, width, chunkHeight); + var layerData = layerCtx.getImageData(0, row, width, chunkHeight); + + if (hasBackdrop) { + composeSMaskBackdrop(maskData.data, r0, g0, b0); + } + composeFn(maskData.data, layerData.data); + + maskCtx.putImageData(layerData, 0, row); + } + } + + function composeSMask(ctx, smask, layerCtx) { + var mask = smask.canvas; + var maskCtx = smask.context; + + ctx.setTransform(smask.scaleX, 0, 0, smask.scaleY, + smask.offsetX, smask.offsetY); + + var backdrop = smask.backdrop || null; + if (WebGLUtils.isEnabled) { + var composed = WebGLUtils.composeSMask(layerCtx.canvas, mask, + {subtype: smask.subtype, backdrop: backdrop}); + ctx.setTransform(1, 0, 0, 1, 0, 0); + ctx.drawImage(composed, smask.offsetX, smask.offsetY); + return; + } + genericComposeSMask(maskCtx, layerCtx, mask.width, mask.height, + smask.subtype, backdrop); + ctx.drawImage(mask, 0, 0); + } + + var LINE_CAP_STYLES = ['butt', 'round', 'square']; + var LINE_JOIN_STYLES = ['miter', 'round', 'bevel']; + var NORMAL_CLIP = {}; + var EO_CLIP = {}; + + CanvasGraphics.prototype = { + + beginDrawing: function CanvasGraphics_beginDrawing(viewport, transparency) { + // For pdfs that use blend modes we have to clear the canvas else certain + // blend modes can look wrong since we'd be blending with a white + // backdrop. The problem with a transparent backdrop though is we then + // don't get sub pixel anti aliasing on text, so we fill with white if + // we can. + var width = this.ctx.canvas.width; + var height = this.ctx.canvas.height; + if (transparency) { + this.ctx.clearRect(0, 0, width, height); + } else { + this.ctx.mozOpaque = true; + this.ctx.save(); + this.ctx.fillStyle = 'rgb(255, 255, 255)'; + this.ctx.fillRect(0, 0, width, height); + this.ctx.restore(); + } + + var transform = viewport.transform; + + this.ctx.save(); + this.ctx.transform.apply(this.ctx, transform); + + this.baseTransform = this.ctx.mozCurrentTransform.slice(); + + if (this.imageLayer) { + this.imageLayer.beginLayout(); + } + }, + + executeOperatorList: function CanvasGraphics_executeOperatorList( + operatorList, + executionStartIdx, continueCallback, + stepper) { + var argsArray = operatorList.argsArray; + var fnArray = operatorList.fnArray; + var i = executionStartIdx || 0; + var argsArrayLen = argsArray.length; + + // Sometimes the OperatorList to execute is empty. + if (argsArrayLen === i) { + return i; + } + + var chunkOperations = (argsArrayLen - i > EXECUTION_STEPS && + typeof continueCallback === 'function'); + var endTime = chunkOperations ? Date.now() + EXECUTION_TIME : 0; + var steps = 0; + + var commonObjs = this.commonObjs; + var objs = this.objs; + var fnId; + + while (true) { + if (stepper !== undefined && i === stepper.nextBreakPoint) { + stepper.breakIt(i, continueCallback); + return i; + } + + fnId = fnArray[i]; + + if (fnId !== OPS.dependency) { + this[fnId].apply(this, argsArray[i]); + } else { + var deps = argsArray[i]; + for (var n = 0, nn = deps.length; n < nn; n++) { + var depObjId = deps[n]; + var common = depObjId[0] === 'g' && depObjId[1] === '_'; + var objsPool = common ? commonObjs : objs; + + // If the promise isn't resolved yet, add the continueCallback + // to the promise and bail out. + if (!objsPool.isResolved(depObjId)) { + objsPool.get(depObjId, continueCallback); + return i; + } + } + } + + i++; + + // If the entire operatorList was executed, stop as were done. + if (i === argsArrayLen) { + return i; + } + + // If the execution took longer then a certain amount of time and + // `continueCallback` is specified, interrupt the execution. + if (chunkOperations && ++steps > EXECUTION_STEPS) { + if (Date.now() > endTime) { + continueCallback(); + return i; + } + steps = 0; + } + + // If the operatorList isn't executed completely yet OR the execution + // time was short enough, do another execution round. + } + }, + + endDrawing: function CanvasGraphics_endDrawing() { + this.ctx.restore(); + CachedCanvases.clear(); + WebGLUtils.clear(); + + if (this.imageLayer) { + this.imageLayer.endLayout(); + } + }, + + // Graphics state + setLineWidth: function CanvasGraphics_setLineWidth(width) { + this.current.lineWidth = width; + this.ctx.lineWidth = width; + }, + setLineCap: function CanvasGraphics_setLineCap(style) { + this.ctx.lineCap = LINE_CAP_STYLES[style]; + }, + setLineJoin: function CanvasGraphics_setLineJoin(style) { + this.ctx.lineJoin = LINE_JOIN_STYLES[style]; + }, + setMiterLimit: function CanvasGraphics_setMiterLimit(limit) { + this.ctx.miterLimit = limit; + }, + setDash: function CanvasGraphics_setDash(dashArray, dashPhase) { + var ctx = this.ctx; + if (ctx.setLineDash !== undefined) { + ctx.setLineDash(dashArray); + ctx.lineDashOffset = dashPhase; + } else { + ctx.mozDash = dashArray; + ctx.mozDashOffset = dashPhase; + } + }, + setRenderingIntent: function CanvasGraphics_setRenderingIntent(intent) { + // Maybe if we one day fully support color spaces this will be important + // for now we can ignore. + // TODO set rendering intent? + }, + setFlatness: function CanvasGraphics_setFlatness(flatness) { + // There's no way to control this with canvas, but we can safely ignore. + // TODO set flatness? + }, + setGState: function CanvasGraphics_setGState(states) { + for (var i = 0, ii = states.length; i < ii; i++) { + var state = states[i]; + var key = state[0]; + var value = state[1]; + + switch (key) { + case 'LW': + this.setLineWidth(value); + break; + case 'LC': + this.setLineCap(value); + break; + case 'LJ': + this.setLineJoin(value); + break; + case 'ML': + this.setMiterLimit(value); + break; + case 'D': + this.setDash(value[0], value[1]); + break; + case 'RI': + this.setRenderingIntent(value); + break; + case 'FL': + this.setFlatness(value); + break; + case 'Font': + this.setFont(value[0], value[1]); + break; + case 'CA': + this.current.strokeAlpha = state[1]; + break; + case 'ca': + this.current.fillAlpha = state[1]; + this.ctx.globalAlpha = state[1]; + break; + case 'BM': + if (value && value.name && (value.name !== 'Normal')) { + var mode = value.name.replace(/([A-Z])/g, + function(c) { + return '-' + c.toLowerCase(); + } + ).substring(1); + this.ctx.globalCompositeOperation = mode; + if (this.ctx.globalCompositeOperation !== mode) { + warn('globalCompositeOperation "' + mode + + '" is not supported'); + } + } else { + this.ctx.globalCompositeOperation = 'source-over'; + } + break; + case 'SMask': + if (this.current.activeSMask) { + this.endSMaskGroup(); + } + this.current.activeSMask = value ? this.tempSMask : null; + if (this.current.activeSMask) { + this.beginSMaskGroup(); + } + this.tempSMask = null; + break; + } + } + }, + beginSMaskGroup: function CanvasGraphics_beginSMaskGroup() { + + var activeSMask = this.current.activeSMask; + var drawnWidth = activeSMask.canvas.width; + var drawnHeight = activeSMask.canvas.height; + var cacheId = 'smaskGroupAt' + this.groupLevel; + var scratchCanvas = CachedCanvases.getCanvas( + cacheId, drawnWidth, drawnHeight, true); + + var currentCtx = this.ctx; + var currentTransform = currentCtx.mozCurrentTransform; + this.ctx.save(); + + var groupCtx = scratchCanvas.context; + groupCtx.scale(1 / activeSMask.scaleX, 1 / activeSMask.scaleY); + groupCtx.translate(-activeSMask.offsetX, -activeSMask.offsetY); + groupCtx.transform.apply(groupCtx, currentTransform); + + copyCtxState(currentCtx, groupCtx); + this.ctx = groupCtx; + this.setGState([ + ['BM', 'Normal'], + ['ca', 1], + ['CA', 1] + ]); + this.groupStack.push(currentCtx); + this.groupLevel++; + }, + endSMaskGroup: function CanvasGraphics_endSMaskGroup() { + var groupCtx = this.ctx; + this.groupLevel--; + this.ctx = this.groupStack.pop(); + + composeSMask(this.ctx, this.current.activeSMask, groupCtx); + this.ctx.restore(); + }, + save: function CanvasGraphics_save() { + this.ctx.save(); + var old = this.current; + this.stateStack.push(old); + this.current = old.clone(); + this.current.activeSMask = null; + }, + restore: function CanvasGraphics_restore() { + if (this.stateStack.length !== 0) { + if (this.current.activeSMask !== null) { + this.endSMaskGroup(); + } + + this.current = this.stateStack.pop(); + this.ctx.restore(); + + this.cachedGetSinglePixelWidth = null; + } + }, + transform: function CanvasGraphics_transform(a, b, c, d, e, f) { + this.ctx.transform(a, b, c, d, e, f); + + this.cachedGetSinglePixelWidth = null; + }, + + // Path + constructPath: function CanvasGraphics_constructPath(ops, args) { + var ctx = this.ctx; + var current = this.current; + var x = current.x, y = current.y; + for (var i = 0, j = 0, ii = ops.length; i < ii; i++) { + switch (ops[i] | 0) { + case OPS.rectangle: + x = args[j++]; + y = args[j++]; + var width = args[j++]; + var height = args[j++]; + if (width === 0) { + width = this.getSinglePixelWidth(); + } + if (height === 0) { + height = this.getSinglePixelWidth(); + } + var xw = x + width; + var yh = y + height; + this.ctx.moveTo(x, y); + this.ctx.lineTo(xw, y); + this.ctx.lineTo(xw, yh); + this.ctx.lineTo(x, yh); + this.ctx.lineTo(x, y); + this.ctx.closePath(); + break; + case OPS.moveTo: + x = args[j++]; + y = args[j++]; + ctx.moveTo(x, y); + break; + case OPS.lineTo: + x = args[j++]; + y = args[j++]; + ctx.lineTo(x, y); + break; + case OPS.curveTo: + x = args[j + 4]; + y = args[j + 5]; + ctx.bezierCurveTo(args[j], args[j + 1], args[j + 2], args[j + 3], + x, y); + j += 6; + break; + case OPS.curveTo2: + ctx.bezierCurveTo(x, y, args[j], args[j + 1], + args[j + 2], args[j + 3]); + x = args[j + 2]; + y = args[j + 3]; + j += 4; + break; + case OPS.curveTo3: + x = args[j + 2]; + y = args[j + 3]; + ctx.bezierCurveTo(args[j], args[j + 1], x, y, x, y); + j += 4; + break; + case OPS.closePath: + ctx.closePath(); + break; + } + } + current.setCurrentPoint(x, y); + }, + closePath: function CanvasGraphics_closePath() { + this.ctx.closePath(); + }, + stroke: function CanvasGraphics_stroke(consumePath) { + consumePath = typeof consumePath !== 'undefined' ? consumePath : true; + var ctx = this.ctx; + var strokeColor = this.current.strokeColor; + // Prevent drawing too thin lines by enforcing a minimum line width. + ctx.lineWidth = Math.max(this.getSinglePixelWidth() * MIN_WIDTH_FACTOR, + this.current.lineWidth); + // For stroke we want to temporarily change the global alpha to the + // stroking alpha. + ctx.globalAlpha = this.current.strokeAlpha; + if (strokeColor && strokeColor.hasOwnProperty('type') && + strokeColor.type === 'Pattern') { + // for patterns, we transform to pattern space, calculate + // the pattern, call stroke, and restore to user space + ctx.save(); + ctx.strokeStyle = strokeColor.getPattern(ctx, this); + ctx.stroke(); + ctx.restore(); + } else { + ctx.stroke(); + } + if (consumePath) { + this.consumePath(); + } + // Restore the global alpha to the fill alpha + ctx.globalAlpha = this.current.fillAlpha; + }, + closeStroke: function CanvasGraphics_closeStroke() { + this.closePath(); + this.stroke(); + }, + fill: function CanvasGraphics_fill(consumePath) { + consumePath = typeof consumePath !== 'undefined' ? consumePath : true; + var ctx = this.ctx; + var fillColor = this.current.fillColor; + var isPatternFill = this.current.patternFill; + var needRestore = false; + + if (isPatternFill) { + ctx.save(); + ctx.fillStyle = fillColor.getPattern(ctx, this); + needRestore = true; + } + + if (this.pendingEOFill) { + if (ctx.mozFillRule !== undefined) { + ctx.mozFillRule = 'evenodd'; + ctx.fill(); + ctx.mozFillRule = 'nonzero'; + } else { + try { + ctx.fill('evenodd'); + } catch (ex) { + // shouldn't really happen, but browsers might think differently + ctx.fill(); + } + } + this.pendingEOFill = false; + } else { + ctx.fill(); + } + + if (needRestore) { + ctx.restore(); + } + if (consumePath) { + this.consumePath(); + } + }, + eoFill: function CanvasGraphics_eoFill() { + this.pendingEOFill = true; + this.fill(); + }, + fillStroke: function CanvasGraphics_fillStroke() { + this.fill(false); + this.stroke(false); + + this.consumePath(); + }, + eoFillStroke: function CanvasGraphics_eoFillStroke() { + this.pendingEOFill = true; + this.fillStroke(); + }, + closeFillStroke: function CanvasGraphics_closeFillStroke() { + this.closePath(); + this.fillStroke(); + }, + closeEOFillStroke: function CanvasGraphics_closeEOFillStroke() { + this.pendingEOFill = true; + this.closePath(); + this.fillStroke(); + }, + endPath: function CanvasGraphics_endPath() { + this.consumePath(); + }, + + // Clipping + clip: function CanvasGraphics_clip() { + this.pendingClip = NORMAL_CLIP; + }, + eoClip: function CanvasGraphics_eoClip() { + this.pendingClip = EO_CLIP; + }, + + // Text + beginText: function CanvasGraphics_beginText() { + this.current.textMatrix = IDENTITY_MATRIX; + this.current.textMatrixScale = 1; + this.current.x = this.current.lineX = 0; + this.current.y = this.current.lineY = 0; + }, + endText: function CanvasGraphics_endText() { + var paths = this.pendingTextPaths; + var ctx = this.ctx; + if (paths === undefined) { + ctx.beginPath(); + return; + } + + ctx.save(); + ctx.beginPath(); + for (var i = 0; i < paths.length; i++) { + var path = paths[i]; + ctx.setTransform.apply(ctx, path.transform); + ctx.translate(path.x, path.y); + path.addToPath(ctx, path.fontSize); + } + ctx.restore(); + ctx.clip(); + ctx.beginPath(); + delete this.pendingTextPaths; + }, + setCharSpacing: function CanvasGraphics_setCharSpacing(spacing) { + this.current.charSpacing = spacing; + }, + setWordSpacing: function CanvasGraphics_setWordSpacing(spacing) { + this.current.wordSpacing = spacing; + }, + setHScale: function CanvasGraphics_setHScale(scale) { + this.current.textHScale = scale / 100; + }, + setLeading: function CanvasGraphics_setLeading(leading) { + this.current.leading = -leading; + }, + setFont: function CanvasGraphics_setFont(fontRefName, size) { + var fontObj = this.commonObjs.get(fontRefName); + var current = this.current; + + if (!fontObj) { + error('Can\'t find font for ' + fontRefName); + } + + current.fontMatrix = (fontObj.fontMatrix ? + fontObj.fontMatrix : FONT_IDENTITY_MATRIX); + + // A valid matrix needs all main diagonal elements to be non-zero + // This also ensures we bypass FF bugzilla bug #719844. + if (current.fontMatrix[0] === 0 || + current.fontMatrix[3] === 0) { + warn('Invalid font matrix for font ' + fontRefName); + } + + // The spec for Tf (setFont) says that 'size' specifies the font 'scale', + // and in some docs this can be negative (inverted x-y axes). + if (size < 0) { + size = -size; + current.fontDirection = -1; + } else { + current.fontDirection = 1; + } + + this.current.font = fontObj; + this.current.fontSize = size; + + if (fontObj.isType3Font) { + return; // we don't need ctx.font for Type3 fonts + } + + var name = fontObj.loadedName || 'sans-serif'; + var bold = fontObj.black ? (fontObj.bold ? 'bolder' : 'bold') : + (fontObj.bold ? 'bold' : 'normal'); + + var italic = fontObj.italic ? 'italic' : 'normal'; + var typeface = '"' + name + '", ' + fontObj.fallbackName; + + // Some font backends cannot handle fonts below certain size. + // Keeping the font at minimal size and using the fontSizeScale to change + // the current transformation matrix before the fillText/strokeText. + // See https://bugzilla.mozilla.org/show_bug.cgi?id=726227 + var browserFontSize = size < MIN_FONT_SIZE ? MIN_FONT_SIZE : + size > MAX_FONT_SIZE ? MAX_FONT_SIZE : size; + this.current.fontSizeScale = size / browserFontSize; + + var rule = italic + ' ' + bold + ' ' + browserFontSize + 'px ' + typeface; + this.ctx.font = rule; + }, + setTextRenderingMode: function CanvasGraphics_setTextRenderingMode(mode) { + this.current.textRenderingMode = mode; + }, + setTextRise: function CanvasGraphics_setTextRise(rise) { + this.current.textRise = rise; + }, + moveText: function CanvasGraphics_moveText(x, y) { + this.current.x = this.current.lineX += x; + this.current.y = this.current.lineY += y; + }, + setLeadingMoveText: function CanvasGraphics_setLeadingMoveText(x, y) { + this.setLeading(-y); + this.moveText(x, y); + }, + setTextMatrix: function CanvasGraphics_setTextMatrix(a, b, c, d, e, f) { + this.current.textMatrix = [a, b, c, d, e, f]; + this.current.textMatrixScale = Math.sqrt(a * a + b * b); + + this.current.x = this.current.lineX = 0; + this.current.y = this.current.lineY = 0; + }, + nextLine: function CanvasGraphics_nextLine() { + this.moveText(0, this.current.leading); + }, + + paintChar: function CanvasGraphics_paintChar(character, x, y) { + var ctx = this.ctx; + var current = this.current; + var font = current.font; + var textRenderingMode = current.textRenderingMode; + var fontSize = current.fontSize / current.fontSizeScale; + var fillStrokeMode = textRenderingMode & + TextRenderingMode.FILL_STROKE_MASK; + var isAddToPathSet = !!(textRenderingMode & + TextRenderingMode.ADD_TO_PATH_FLAG); + + var addToPath; + if (font.disableFontFace || isAddToPathSet) { + addToPath = font.getPathGenerator(this.commonObjs, character); + } + + if (font.disableFontFace) { + ctx.save(); + ctx.translate(x, y); + ctx.beginPath(); + addToPath(ctx, fontSize); + if (fillStrokeMode === TextRenderingMode.FILL || + fillStrokeMode === TextRenderingMode.FILL_STROKE) { + ctx.fill(); + } + if (fillStrokeMode === TextRenderingMode.STROKE || + fillStrokeMode === TextRenderingMode.FILL_STROKE) { + ctx.stroke(); + } + ctx.restore(); + } else { + if (fillStrokeMode === TextRenderingMode.FILL || + fillStrokeMode === TextRenderingMode.FILL_STROKE) { + ctx.fillText(character, x, y); + } + if (fillStrokeMode === TextRenderingMode.STROKE || + fillStrokeMode === TextRenderingMode.FILL_STROKE) { + ctx.strokeText(character, x, y); + } + } + + if (isAddToPathSet) { + var paths = this.pendingTextPaths || (this.pendingTextPaths = []); + paths.push({ + transform: ctx.mozCurrentTransform, + x: x, + y: y, + fontSize: fontSize, + addToPath: addToPath + }); + } + }, + + get isFontSubpixelAAEnabled() { + // Checks if anti-aliasing is enabled when scaled text is painted. + // On Windows GDI scaled fonts looks bad. + var ctx = document.createElement('canvas').getContext('2d'); + ctx.scale(1.5, 1); + ctx.fillText('I', 0, 10); + var data = ctx.getImageData(0, 0, 10, 10).data; + var enabled = false; + for (var i = 3; i < data.length; i += 4) { + if (data[i] > 0 && data[i] < 255) { + enabled = true; + break; + } + } + return shadow(this, 'isFontSubpixelAAEnabled', enabled); + }, + + showText: function CanvasGraphics_showText(glyphs) { + var current = this.current; + var font = current.font; + if (font.isType3Font) { + return this.showType3Text(glyphs); + } + + var fontSize = current.fontSize; + if (fontSize === 0) { + return; + } + + var ctx = this.ctx; + var fontSizeScale = current.fontSizeScale; + var charSpacing = current.charSpacing; + var wordSpacing = current.wordSpacing; + var fontDirection = current.fontDirection; + var textHScale = current.textHScale * fontDirection; + var glyphsLength = glyphs.length; + var vertical = font.vertical; + var defaultVMetrics = font.defaultVMetrics; + var widthAdvanceScale = fontSize * current.fontMatrix[0]; + + var simpleFillText = + current.textRenderingMode === TextRenderingMode.FILL && + !font.disableFontFace; + + ctx.save(); + ctx.transform.apply(ctx, current.textMatrix); + ctx.translate(current.x, current.y + current.textRise); + + if (fontDirection > 0) { + ctx.scale(textHScale, -1); + } else { + ctx.scale(textHScale, 1); + } + + var lineWidth = current.lineWidth; + var scale = current.textMatrixScale; + if (scale === 0 || lineWidth === 0) { + var fillStrokeMode = current.textRenderingMode & + TextRenderingMode.FILL_STROKE_MASK; + if (fillStrokeMode === TextRenderingMode.STROKE || + fillStrokeMode === TextRenderingMode.FILL_STROKE) { + this.cachedGetSinglePixelWidth = null; + lineWidth = this.getSinglePixelWidth() * MIN_WIDTH_FACTOR; + } + } else { + lineWidth /= scale; + } + + if (fontSizeScale !== 1.0) { + ctx.scale(fontSizeScale, fontSizeScale); + lineWidth /= fontSizeScale; + } + + ctx.lineWidth = lineWidth; + + var x = 0, i; + for (i = 0; i < glyphsLength; ++i) { + var glyph = glyphs[i]; + if (glyph === null) { + // word break + x += fontDirection * wordSpacing; + continue; + } else if (isNum(glyph)) { + x += -glyph * fontSize * 0.001; + continue; + } + + var restoreNeeded = false; + var character = glyph.fontChar; + var accent = glyph.accent; + var scaledX, scaledY, scaledAccentX, scaledAccentY; + var width = glyph.width; + if (vertical) { + var vmetric, vx, vy; + vmetric = glyph.vmetric || defaultVMetrics; + vx = glyph.vmetric ? vmetric[1] : width * 0.5; + vx = -vx * widthAdvanceScale; + vy = vmetric[2] * widthAdvanceScale; + + width = vmetric ? -vmetric[0] : width; + scaledX = vx / fontSizeScale; + scaledY = (x + vy) / fontSizeScale; + } else { + scaledX = x / fontSizeScale; + scaledY = 0; + } + + if (font.remeasure && width > 0 && this.isFontSubpixelAAEnabled) { + // some standard fonts may not have the exact width, trying to + // rescale per character + var measuredWidth = ctx.measureText(character).width * 1000 / + fontSize * fontSizeScale; + var characterScaleX = width / measuredWidth; + restoreNeeded = true; + ctx.save(); + ctx.scale(characterScaleX, 1); + scaledX /= characterScaleX; + } + + if (simpleFillText && !accent) { + // common case + ctx.fillText(character, scaledX, scaledY); + } else { + this.paintChar(character, scaledX, scaledY); + if (accent) { + scaledAccentX = scaledX + accent.offset.x / fontSizeScale; + scaledAccentY = scaledY - accent.offset.y / fontSizeScale; + this.paintChar(accent.fontChar, scaledAccentX, scaledAccentY); + } + } + + var charWidth = width * widthAdvanceScale + charSpacing * fontDirection; + x += charWidth; + + if (restoreNeeded) { + ctx.restore(); + } + } + if (vertical) { + current.y -= x * textHScale; + } else { + current.x += x * textHScale; + } + ctx.restore(); + }, + + showType3Text: function CanvasGraphics_showType3Text(glyphs) { + // Type3 fonts - each glyph is a "mini-PDF" + var ctx = this.ctx; + var current = this.current; + var font = current.font; + var fontSize = current.fontSize; + var fontDirection = current.fontDirection; + var charSpacing = current.charSpacing; + var wordSpacing = current.wordSpacing; + var textHScale = current.textHScale * fontDirection; + var fontMatrix = current.fontMatrix || FONT_IDENTITY_MATRIX; + var glyphsLength = glyphs.length; + var isTextInvisible = + current.textRenderingMode === TextRenderingMode.INVISIBLE; + var i, glyph, width; + + if (isTextInvisible || fontSize === 0) { + return; + } + + ctx.save(); + ctx.transform.apply(ctx, current.textMatrix); + ctx.translate(current.x, current.y); + + ctx.scale(textHScale, fontDirection); + + for (i = 0; i < glyphsLength; ++i) { + glyph = glyphs[i]; + if (glyph === null) { + // word break + this.ctx.translate(wordSpacing, 0); + current.x += wordSpacing * textHScale; + continue; + } else if (isNum(glyph)) { + var spacingLength = -glyph * 0.001 * fontSize; + this.ctx.translate(spacingLength, 0); + current.x += spacingLength * textHScale; + continue; + } + + var operatorList = font.charProcOperatorList[glyph.operatorListId]; + if (!operatorList) { + warn('Type3 character \"' + glyph.operatorListId + + '\" is not available'); + continue; + } + this.processingType3 = glyph; + this.save(); + ctx.scale(fontSize, fontSize); + ctx.transform.apply(ctx, fontMatrix); + this.executeOperatorList(operatorList); + this.restore(); + + var transformed = Util.applyTransform([glyph.width, 0], fontMatrix); + width = transformed[0] * fontSize + charSpacing; + + ctx.translate(width, 0); + current.x += width * textHScale; + } + ctx.restore(); + this.processingType3 = null; + }, + + // Type3 fonts + setCharWidth: function CanvasGraphics_setCharWidth(xWidth, yWidth) { + // We can safely ignore this since the width should be the same + // as the width in the Widths array. + }, + setCharWidthAndBounds: function CanvasGraphics_setCharWidthAndBounds(xWidth, + yWidth, + llx, + lly, + urx, + ury) { + // TODO According to the spec we're also suppose to ignore any operators + // that set color or include images while processing this type3 font. + this.ctx.rect(llx, lly, urx - llx, ury - lly); + this.clip(); + this.endPath(); + }, + + // Color + getColorN_Pattern: function CanvasGraphics_getColorN_Pattern(IR) { + var pattern; + if (IR[0] === 'TilingPattern') { + var color = IR[1]; + pattern = new TilingPattern(IR, color, this.ctx, this.objs, + this.commonObjs, this.baseTransform); + } else { + pattern = getShadingPatternFromIR(IR); + } + return pattern; + }, + setStrokeColorN: function CanvasGraphics_setStrokeColorN(/*...*/) { + this.current.strokeColor = this.getColorN_Pattern(arguments); + }, + setFillColorN: function CanvasGraphics_setFillColorN(/*...*/) { + this.current.fillColor = this.getColorN_Pattern(arguments); + this.current.patternFill = true; + }, + setStrokeRGBColor: function CanvasGraphics_setStrokeRGBColor(r, g, b) { + var color = Util.makeCssRgb(r, g, b); + this.ctx.strokeStyle = color; + this.current.strokeColor = color; + }, + setFillRGBColor: function CanvasGraphics_setFillRGBColor(r, g, b) { + var color = Util.makeCssRgb(r, g, b); + this.ctx.fillStyle = color; + this.current.fillColor = color; + this.current.patternFill = false; + }, + + shadingFill: function CanvasGraphics_shadingFill(patternIR) { + var ctx = this.ctx; + + this.save(); + var pattern = getShadingPatternFromIR(patternIR); + ctx.fillStyle = pattern.getPattern(ctx, this, true); + + var inv = ctx.mozCurrentTransformInverse; + if (inv) { + var canvas = ctx.canvas; + var width = canvas.width; + var height = canvas.height; + + var bl = Util.applyTransform([0, 0], inv); + var br = Util.applyTransform([0, height], inv); + var ul = Util.applyTransform([width, 0], inv); + var ur = Util.applyTransform([width, height], inv); + + var x0 = Math.min(bl[0], br[0], ul[0], ur[0]); + var y0 = Math.min(bl[1], br[1], ul[1], ur[1]); + var x1 = Math.max(bl[0], br[0], ul[0], ur[0]); + var y1 = Math.max(bl[1], br[1], ul[1], ur[1]); + + this.ctx.fillRect(x0, y0, x1 - x0, y1 - y0); + } else { + // HACK to draw the gradient onto an infinite rectangle. + // PDF gradients are drawn across the entire image while + // Canvas only allows gradients to be drawn in a rectangle + // The following bug should allow us to remove this. + // https://bugzilla.mozilla.org/show_bug.cgi?id=664884 + + this.ctx.fillRect(-1e10, -1e10, 2e10, 2e10); + } + + this.restore(); + }, + + // Images + beginInlineImage: function CanvasGraphics_beginInlineImage() { + error('Should not call beginInlineImage'); + }, + beginImageData: function CanvasGraphics_beginImageData() { + error('Should not call beginImageData'); + }, + + paintFormXObjectBegin: function CanvasGraphics_paintFormXObjectBegin(matrix, + bbox) { + this.save(); + this.baseTransformStack.push(this.baseTransform); + + if (isArray(matrix) && 6 === matrix.length) { + this.transform.apply(this, matrix); + } + + this.baseTransform = this.ctx.mozCurrentTransform; + + if (isArray(bbox) && 4 === bbox.length) { + var width = bbox[2] - bbox[0]; + var height = bbox[3] - bbox[1]; + this.ctx.rect(bbox[0], bbox[1], width, height); + this.clip(); + this.endPath(); + } + }, + + paintFormXObjectEnd: function CanvasGraphics_paintFormXObjectEnd() { + this.restore(); + this.baseTransform = this.baseTransformStack.pop(); + }, + + beginGroup: function CanvasGraphics_beginGroup(group) { + this.save(); + var currentCtx = this.ctx; + // TODO non-isolated groups - according to Rik at adobe non-isolated + // group results aren't usually that different and they even have tools + // that ignore this setting. Notes from Rik on implmenting: + // - When you encounter an transparency group, create a new canvas with + // the dimensions of the bbox + // - copy the content from the previous canvas to the new canvas + // - draw as usual + // - remove the backdrop alpha: + // alphaNew = 1 - (1 - alpha)/(1 - alphaBackdrop) with 'alpha' the alpha + // value of your transparency group and 'alphaBackdrop' the alpha of the + // backdrop + // - remove background color: + // colorNew = color - alphaNew *colorBackdrop /(1 - alphaNew) + if (!group.isolated) { + info('TODO: Support non-isolated groups.'); + } + + // TODO knockout - supposedly possible with the clever use of compositing + // modes. + if (group.knockout) { + warn('Knockout groups not supported.'); + } + + var currentTransform = currentCtx.mozCurrentTransform; + if (group.matrix) { + currentCtx.transform.apply(currentCtx, group.matrix); + } + assert(group.bbox, 'Bounding box is required.'); + + // Based on the current transform figure out how big the bounding box + // will actually be. + var bounds = Util.getAxialAlignedBoundingBox( + group.bbox, + currentCtx.mozCurrentTransform); + // Clip the bounding box to the current canvas. + var canvasBounds = [0, + 0, + currentCtx.canvas.width, + currentCtx.canvas.height]; + bounds = Util.intersect(bounds, canvasBounds) || [0, 0, 0, 0]; + // Use ceil in case we're between sizes so we don't create canvas that is + // too small and make the canvas at least 1x1 pixels. + var offsetX = Math.floor(bounds[0]); + var offsetY = Math.floor(bounds[1]); + var drawnWidth = Math.max(Math.ceil(bounds[2]) - offsetX, 1); + var drawnHeight = Math.max(Math.ceil(bounds[3]) - offsetY, 1); + var scaleX = 1, scaleY = 1; + if (drawnWidth > MAX_GROUP_SIZE) { + scaleX = drawnWidth / MAX_GROUP_SIZE; + drawnWidth = MAX_GROUP_SIZE; + } + if (drawnHeight > MAX_GROUP_SIZE) { + scaleY = drawnHeight / MAX_GROUP_SIZE; + drawnHeight = MAX_GROUP_SIZE; + } + + var cacheId = 'groupAt' + this.groupLevel; + if (group.smask) { + // Using two cache entries is case if masks are used one after another. + cacheId += '_smask_' + ((this.smaskCounter++) % 2); + } + var scratchCanvas = CachedCanvases.getCanvas( + cacheId, drawnWidth, drawnHeight, true); + var groupCtx = scratchCanvas.context; + + // Since we created a new canvas that is just the size of the bounding box + // we have to translate the group ctx. + groupCtx.scale(1 / scaleX, 1 / scaleY); + groupCtx.translate(-offsetX, -offsetY); + groupCtx.transform.apply(groupCtx, currentTransform); + + if (group.smask) { + // Saving state and cached mask to be used in setGState. + this.smaskStack.push({ + canvas: scratchCanvas.canvas, + context: groupCtx, + offsetX: offsetX, + offsetY: offsetY, + scaleX: scaleX, + scaleY: scaleY, + subtype: group.smask.subtype, + backdrop: group.smask.backdrop + }); + } else { + // Setup the current ctx so when the group is popped we draw it at the + // right location. + currentCtx.setTransform(1, 0, 0, 1, 0, 0); + currentCtx.translate(offsetX, offsetY); + currentCtx.scale(scaleX, scaleY); + } + // The transparency group inherits all off the current graphics state + // except the blend mode, soft mask, and alpha constants. + copyCtxState(currentCtx, groupCtx); + this.ctx = groupCtx; + this.setGState([ + ['BM', 'Normal'], + ['ca', 1], + ['CA', 1] + ]); + this.groupStack.push(currentCtx); + this.groupLevel++; + }, + + endGroup: function CanvasGraphics_endGroup(group) { + this.groupLevel--; + var groupCtx = this.ctx; + this.ctx = this.groupStack.pop(); + // Turn off image smoothing to avoid sub pixel interpolation which can + // look kind of blurry for some pdfs. + if (this.ctx.imageSmoothingEnabled !== undefined) { + this.ctx.imageSmoothingEnabled = false; + } else { + this.ctx.mozImageSmoothingEnabled = false; + } + if (group.smask) { + this.tempSMask = this.smaskStack.pop(); + } else { + this.ctx.drawImage(groupCtx.canvas, 0, 0); + } + this.restore(); + }, + + beginAnnotations: function CanvasGraphics_beginAnnotations() { + this.save(); + this.current = new CanvasExtraState(); + }, + + endAnnotations: function CanvasGraphics_endAnnotations() { + this.restore(); + }, + + beginAnnotation: function CanvasGraphics_beginAnnotation(rect, transform, + matrix) { + this.save(); + + if (isArray(rect) && 4 === rect.length) { + var width = rect[2] - rect[0]; + var height = rect[3] - rect[1]; + this.ctx.rect(rect[0], rect[1], width, height); + this.clip(); + this.endPath(); + } + + this.transform.apply(this, transform); + this.transform.apply(this, matrix); + }, + + endAnnotation: function CanvasGraphics_endAnnotation() { + this.restore(); + }, + + paintJpegXObject: function CanvasGraphics_paintJpegXObject(objId, w, h) { + var domImage = this.objs.get(objId); + if (!domImage) { + warn('Dependent image isn\'t ready yet'); + return; + } + + this.save(); + + var ctx = this.ctx; + // scale the image to the unit square + ctx.scale(1 / w, -1 / h); + + ctx.drawImage(domImage, 0, 0, domImage.width, domImage.height, + 0, -h, w, h); + if (this.imageLayer) { + var currentTransform = ctx.mozCurrentTransformInverse; + var position = this.getCanvasPosition(0, 0); + this.imageLayer.appendImage({ + objId: objId, + left: position[0], + top: position[1], + width: w / currentTransform[0], + height: h / currentTransform[3] + }); + } + this.restore(); + }, + + paintImageMaskXObject: function CanvasGraphics_paintImageMaskXObject(img) { + var ctx = this.ctx; + var width = img.width, height = img.height; + var fillColor = this.current.fillColor; + var isPatternFill = this.current.patternFill; + + var glyph = this.processingType3; + + if (COMPILE_TYPE3_GLYPHS && glyph && glyph.compiled === undefined) { + if (width <= MAX_SIZE_TO_COMPILE && height <= MAX_SIZE_TO_COMPILE) { + glyph.compiled = + compileType3Glyph({data: img.data, width: width, height: height}); + } else { + glyph.compiled = null; + } + } + + if (glyph && glyph.compiled) { + glyph.compiled(ctx); + return; + } + + var maskCanvas = CachedCanvases.getCanvas('maskCanvas', width, height); + var maskCtx = maskCanvas.context; + maskCtx.save(); + + putBinaryImageMask(maskCtx, img); + + maskCtx.globalCompositeOperation = 'source-in'; + + maskCtx.fillStyle = isPatternFill ? + fillColor.getPattern(maskCtx, this) : fillColor; + maskCtx.fillRect(0, 0, width, height); + + maskCtx.restore(); + + this.paintInlineImageXObject(maskCanvas.canvas); + }, + + paintImageMaskXObjectRepeat: + function CanvasGraphics_paintImageMaskXObjectRepeat(imgData, scaleX, + scaleY, positions) { + var width = imgData.width; + var height = imgData.height; + var fillColor = this.current.fillColor; + var isPatternFill = this.current.patternFill; + + var maskCanvas = CachedCanvases.getCanvas('maskCanvas', width, height); + var maskCtx = maskCanvas.context; + maskCtx.save(); + + putBinaryImageMask(maskCtx, imgData); + + maskCtx.globalCompositeOperation = 'source-in'; + + maskCtx.fillStyle = isPatternFill ? + fillColor.getPattern(maskCtx, this) : fillColor; + maskCtx.fillRect(0, 0, width, height); + + maskCtx.restore(); + + var ctx = this.ctx; + for (var i = 0, ii = positions.length; i < ii; i += 2) { + ctx.save(); + ctx.transform(scaleX, 0, 0, scaleY, positions[i], positions[i + 1]); + ctx.scale(1, -1); + ctx.drawImage(maskCanvas.canvas, 0, 0, width, height, + 0, -1, 1, 1); + ctx.restore(); + } + }, + + paintImageMaskXObjectGroup: + function CanvasGraphics_paintImageMaskXObjectGroup(images) { + var ctx = this.ctx; + + var fillColor = this.current.fillColor; + var isPatternFill = this.current.patternFill; + for (var i = 0, ii = images.length; i < ii; i++) { + var image = images[i]; + var width = image.width, height = image.height; + + var maskCanvas = CachedCanvases.getCanvas('maskCanvas', width, height); + var maskCtx = maskCanvas.context; + maskCtx.save(); + + putBinaryImageMask(maskCtx, image); + + maskCtx.globalCompositeOperation = 'source-in'; + + maskCtx.fillStyle = isPatternFill ? + fillColor.getPattern(maskCtx, this) : fillColor; + maskCtx.fillRect(0, 0, width, height); + + maskCtx.restore(); + + ctx.save(); + ctx.transform.apply(ctx, image.transform); + ctx.scale(1, -1); + ctx.drawImage(maskCanvas.canvas, 0, 0, width, height, + 0, -1, 1, 1); + ctx.restore(); + } + }, + + paintImageXObject: function CanvasGraphics_paintImageXObject(objId) { + var imgData = this.objs.get(objId); + if (!imgData) { + warn('Dependent image isn\'t ready yet'); + return; + } + + this.paintInlineImageXObject(imgData); + }, + + paintImageXObjectRepeat: + function CanvasGraphics_paintImageXObjectRepeat(objId, scaleX, scaleY, + positions) { + var imgData = this.objs.get(objId); + if (!imgData) { + warn('Dependent image isn\'t ready yet'); + return; + } + + var width = imgData.width; + var height = imgData.height; + var map = []; + for (var i = 0, ii = positions.length; i < ii; i += 2) { + map.push({transform: [scaleX, 0, 0, scaleY, positions[i], + positions[i + 1]], x: 0, y: 0, w: width, h: height}); + } + this.paintInlineImageXObjectGroup(imgData, map); + }, + + paintInlineImageXObject: + function CanvasGraphics_paintInlineImageXObject(imgData) { + var width = imgData.width; + var height = imgData.height; + var ctx = this.ctx; + + this.save(); + // scale the image to the unit square + ctx.scale(1 / width, -1 / height); + + var currentTransform = ctx.mozCurrentTransformInverse; + var a = currentTransform[0], b = currentTransform[1]; + var widthScale = Math.max(Math.sqrt(a * a + b * b), 1); + var c = currentTransform[2], d = currentTransform[3]; + var heightScale = Math.max(Math.sqrt(c * c + d * d), 1); + + var imgToPaint, tmpCanvas; + // instanceof HTMLElement does not work in jsdom node.js module + if (imgData instanceof HTMLElement || !imgData.data) { + imgToPaint = imgData; + } else { + tmpCanvas = CachedCanvases.getCanvas('inlineImage', width, height); + var tmpCtx = tmpCanvas.context; + putBinaryImageData(tmpCtx, imgData); + imgToPaint = tmpCanvas.canvas; + } + + var paintWidth = width, paintHeight = height; + var tmpCanvasId = 'prescale1'; + // Vertial or horizontal scaling shall not be more than 2 to not loose the + // pixels during drawImage operation, painting on the temporary canvas(es) + // that are twice smaller in size + while ((widthScale > 2 && paintWidth > 1) || + (heightScale > 2 && paintHeight > 1)) { + var newWidth = paintWidth, newHeight = paintHeight; + if (widthScale > 2 && paintWidth > 1) { + newWidth = Math.ceil(paintWidth / 2); + widthScale /= paintWidth / newWidth; + } + if (heightScale > 2 && paintHeight > 1) { + newHeight = Math.ceil(paintHeight / 2); + heightScale /= paintHeight / newHeight; + } + tmpCanvas = CachedCanvases.getCanvas(tmpCanvasId, newWidth, newHeight); + tmpCtx = tmpCanvas.context; + tmpCtx.clearRect(0, 0, newWidth, newHeight); + tmpCtx.drawImage(imgToPaint, 0, 0, paintWidth, paintHeight, + 0, 0, newWidth, newHeight); + imgToPaint = tmpCanvas.canvas; + paintWidth = newWidth; + paintHeight = newHeight; + tmpCanvasId = tmpCanvasId === 'prescale1' ? 'prescale2' : 'prescale1'; + } + ctx.drawImage(imgToPaint, 0, 0, paintWidth, paintHeight, + 0, -height, width, height); + + if (this.imageLayer) { + var position = this.getCanvasPosition(0, -height); + this.imageLayer.appendImage({ + imgData: imgData, + left: position[0], + top: position[1], + width: width / currentTransform[0], + height: height / currentTransform[3] + }); + } + this.restore(); + }, + + paintInlineImageXObjectGroup: + function CanvasGraphics_paintInlineImageXObjectGroup(imgData, map) { + var ctx = this.ctx; + var w = imgData.width; + var h = imgData.height; + + var tmpCanvas = CachedCanvases.getCanvas('inlineImage', w, h); + var tmpCtx = tmpCanvas.context; + putBinaryImageData(tmpCtx, imgData); + + for (var i = 0, ii = map.length; i < ii; i++) { + var entry = map[i]; + ctx.save(); + ctx.transform.apply(ctx, entry.transform); + ctx.scale(1, -1); + ctx.drawImage(tmpCanvas.canvas, entry.x, entry.y, entry.w, entry.h, + 0, -1, 1, 1); + if (this.imageLayer) { + var position = this.getCanvasPosition(entry.x, entry.y); + this.imageLayer.appendImage({ + imgData: imgData, + left: position[0], + top: position[1], + width: w, + height: h + }); + } + ctx.restore(); + } + }, + + paintSolidColorImageMask: + function CanvasGraphics_paintSolidColorImageMask() { + this.ctx.fillRect(0, 0, 1, 1); + }, + + // Marked content + + markPoint: function CanvasGraphics_markPoint(tag) { + // TODO Marked content. + }, + markPointProps: function CanvasGraphics_markPointProps(tag, properties) { + // TODO Marked content. + }, + beginMarkedContent: function CanvasGraphics_beginMarkedContent(tag) { + // TODO Marked content. + }, + beginMarkedContentProps: function CanvasGraphics_beginMarkedContentProps( + tag, properties) { + // TODO Marked content. + }, + endMarkedContent: function CanvasGraphics_endMarkedContent() { + // TODO Marked content. + }, + + // Compatibility + + beginCompat: function CanvasGraphics_beginCompat() { + // TODO ignore undefined operators (should we do that anyway?) + }, + endCompat: function CanvasGraphics_endCompat() { + // TODO stop ignoring undefined operators + }, + + // Helper functions + + consumePath: function CanvasGraphics_consumePath() { + var ctx = this.ctx; + if (this.pendingClip) { + if (this.pendingClip === EO_CLIP) { + if (ctx.mozFillRule !== undefined) { + ctx.mozFillRule = 'evenodd'; + ctx.clip(); + ctx.mozFillRule = 'nonzero'; + } else { + try { + ctx.clip('evenodd'); + } catch (ex) { + // shouldn't really happen, but browsers might think differently + ctx.clip(); + } + } + } else { + ctx.clip(); + } + this.pendingClip = null; + } + ctx.beginPath(); + }, + getSinglePixelWidth: function CanvasGraphics_getSinglePixelWidth(scale) { + if (this.cachedGetSinglePixelWidth === null) { + var inverse = this.ctx.mozCurrentTransformInverse; + // max of the current horizontal and vertical scale + this.cachedGetSinglePixelWidth = Math.sqrt(Math.max( + (inverse[0] * inverse[0] + inverse[1] * inverse[1]), + (inverse[2] * inverse[2] + inverse[3] * inverse[3]))); + } + return this.cachedGetSinglePixelWidth; + }, + getCanvasPosition: function CanvasGraphics_getCanvasPosition(x, y) { + var transform = this.ctx.mozCurrentTransform; + return [ + transform[0] * x + transform[2] * y + transform[4], + transform[1] * x + transform[3] * y + transform[5] + ]; + } + }; + + for (var op in OPS) { + CanvasGraphics.prototype[OPS[op]] = CanvasGraphics.prototype[op]; + } + + return CanvasGraphics; +})(); + + +var WebGLUtils = (function WebGLUtilsClosure() { + function loadShader(gl, code, shaderType) { + var shader = gl.createShader(shaderType); + gl.shaderSource(shader, code); + gl.compileShader(shader); + var compiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS); + if (!compiled) { + var errorMsg = gl.getShaderInfoLog(shader); + throw new Error('Error during shader compilation: ' + errorMsg); + } + return shader; + } + function createVertexShader(gl, code) { + return loadShader(gl, code, gl.VERTEX_SHADER); + } + function createFragmentShader(gl, code) { + return loadShader(gl, code, gl.FRAGMENT_SHADER); + } + function createProgram(gl, shaders) { + var program = gl.createProgram(); + for (var i = 0, ii = shaders.length; i < ii; ++i) { + gl.attachShader(program, shaders[i]); + } + gl.linkProgram(program); + var linked = gl.getProgramParameter(program, gl.LINK_STATUS); + if (!linked) { + var errorMsg = gl.getProgramInfoLog(program); + throw new Error('Error during program linking: ' + errorMsg); + } + return program; + } + function createTexture(gl, image, textureId) { + gl.activeTexture(textureId); + var texture = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, texture); + + // Set the parameters so we can render any size image. + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + + // Upload the image into the texture. + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image); + return texture; + } + + var currentGL, currentCanvas; + function generateGL() { + if (currentGL) { + return; + } + currentCanvas = document.createElement('canvas'); + currentGL = currentCanvas.getContext('webgl', + { premultipliedalpha: false }); + } + + var smaskVertexShaderCode = '\ + attribute vec2 a_position; \ + attribute vec2 a_texCoord; \ + \ + uniform vec2 u_resolution; \ + \ + varying vec2 v_texCoord; \ + \ + void main() { \ + vec2 clipSpace = (a_position / u_resolution) * 2.0 - 1.0; \ + gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1); \ + \ + v_texCoord = a_texCoord; \ + } '; + + var smaskFragmentShaderCode = '\ + precision mediump float; \ + \ + uniform vec4 u_backdrop; \ + uniform int u_subtype; \ + uniform sampler2D u_image; \ + uniform sampler2D u_mask; \ + \ + varying vec2 v_texCoord; \ + \ + void main() { \ + vec4 imageColor = texture2D(u_image, v_texCoord); \ + vec4 maskColor = texture2D(u_mask, v_texCoord); \ + if (u_backdrop.a > 0.0) { \ + maskColor.rgb = maskColor.rgb * maskColor.a + \ + u_backdrop.rgb * (1.0 - maskColor.a); \ + } \ + float lum; \ + if (u_subtype == 0) { \ + lum = maskColor.a; \ + } else { \ + lum = maskColor.r * 0.3 + maskColor.g * 0.59 + \ + maskColor.b * 0.11; \ + } \ + imageColor.a *= lum; \ + imageColor.rgb *= imageColor.a; \ + gl_FragColor = imageColor; \ + } '; + + var smaskCache = null; + + function initSmaskGL() { + var canvas, gl; + + generateGL(); + canvas = currentCanvas; + currentCanvas = null; + gl = currentGL; + currentGL = null; + + // setup a GLSL program + var vertexShader = createVertexShader(gl, smaskVertexShaderCode); + var fragmentShader = createFragmentShader(gl, smaskFragmentShaderCode); + var program = createProgram(gl, [vertexShader, fragmentShader]); + gl.useProgram(program); + + var cache = {}; + cache.gl = gl; + cache.canvas = canvas; + cache.resolutionLocation = gl.getUniformLocation(program, 'u_resolution'); + cache.positionLocation = gl.getAttribLocation(program, 'a_position'); + cache.backdropLocation = gl.getUniformLocation(program, 'u_backdrop'); + cache.subtypeLocation = gl.getUniformLocation(program, 'u_subtype'); + + var texCoordLocation = gl.getAttribLocation(program, 'a_texCoord'); + var texLayerLocation = gl.getUniformLocation(program, 'u_image'); + var texMaskLocation = gl.getUniformLocation(program, 'u_mask'); + + // provide texture coordinates for the rectangle. + var texCoordBuffer = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, texCoordBuffer); + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ + 0.0, 0.0, + 1.0, 0.0, + 0.0, 1.0, + 0.0, 1.0, + 1.0, 0.0, + 1.0, 1.0]), gl.STATIC_DRAW); + gl.enableVertexAttribArray(texCoordLocation); + gl.vertexAttribPointer(texCoordLocation, 2, gl.FLOAT, false, 0, 0); + + gl.uniform1i(texLayerLocation, 0); + gl.uniform1i(texMaskLocation, 1); + + smaskCache = cache; + } + + function composeSMask(layer, mask, properties) { + var width = layer.width, height = layer.height; + + if (!smaskCache) { + initSmaskGL(); + } + var cache = smaskCache,canvas = cache.canvas, gl = cache.gl; + canvas.width = width; + canvas.height = height; + gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight); + gl.uniform2f(cache.resolutionLocation, width, height); + + if (properties.backdrop) { + gl.uniform4f(cache.resolutionLocation, properties.backdrop[0], + properties.backdrop[1], properties.backdrop[2], 1); + } else { + gl.uniform4f(cache.resolutionLocation, 0, 0, 0, 0); + } + gl.uniform1i(cache.subtypeLocation, + properties.subtype === 'Luminosity' ? 1 : 0); + + // Create a textures + var texture = createTexture(gl, layer, gl.TEXTURE0); + var maskTexture = createTexture(gl, mask, gl.TEXTURE1); + + + // Create a buffer and put a single clipspace rectangle in + // it (2 triangles) + var buffer = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, buffer); + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ + 0, 0, + width, 0, + 0, height, + 0, height, + width, 0, + width, height]), gl.STATIC_DRAW); + gl.enableVertexAttribArray(cache.positionLocation); + gl.vertexAttribPointer(cache.positionLocation, 2, gl.FLOAT, false, 0, 0); + + // draw + gl.clearColor(0, 0, 0, 0); + gl.enable(gl.BLEND); + gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); + gl.clear(gl.COLOR_BUFFER_BIT); + + gl.drawArrays(gl.TRIANGLES, 0, 6); + + gl.flush(); + + gl.deleteTexture(texture); + gl.deleteTexture(maskTexture); + gl.deleteBuffer(buffer); + + return canvas; + } + + var figuresVertexShaderCode = '\ + attribute vec2 a_position; \ + attribute vec3 a_color; \ + \ + uniform vec2 u_resolution; \ + uniform vec2 u_scale; \ + uniform vec2 u_offset; \ + \ + varying vec4 v_color; \ + \ + void main() { \ + vec2 position = (a_position + u_offset) * u_scale; \ + vec2 clipSpace = (position / u_resolution) * 2.0 - 1.0; \ + gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1); \ + \ + v_color = vec4(a_color / 255.0, 1.0); \ + } '; + + var figuresFragmentShaderCode = '\ + precision mediump float; \ + \ + varying vec4 v_color; \ + \ + void main() { \ + gl_FragColor = v_color; \ + } '; + + var figuresCache = null; + + function initFiguresGL() { + var canvas, gl; + + generateGL(); + canvas = currentCanvas; + currentCanvas = null; + gl = currentGL; + currentGL = null; + + // setup a GLSL program + var vertexShader = createVertexShader(gl, figuresVertexShaderCode); + var fragmentShader = createFragmentShader(gl, figuresFragmentShaderCode); + var program = createProgram(gl, [vertexShader, fragmentShader]); + gl.useProgram(program); + + var cache = {}; + cache.gl = gl; + cache.canvas = canvas; + cache.resolutionLocation = gl.getUniformLocation(program, 'u_resolution'); + cache.scaleLocation = gl.getUniformLocation(program, 'u_scale'); + cache.offsetLocation = gl.getUniformLocation(program, 'u_offset'); + cache.positionLocation = gl.getAttribLocation(program, 'a_position'); + cache.colorLocation = gl.getAttribLocation(program, 'a_color'); + + figuresCache = cache; + } + + function drawFigures(width, height, backgroundColor, figures, context) { + if (!figuresCache) { + initFiguresGL(); + } + var cache = figuresCache, canvas = cache.canvas, gl = cache.gl; + + canvas.width = width; + canvas.height = height; + gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight); + gl.uniform2f(cache.resolutionLocation, width, height); + + // count triangle points + var count = 0; + var i, ii, rows; + for (i = 0, ii = figures.length; i < ii; i++) { + switch (figures[i].type) { + case 'lattice': + rows = (figures[i].coords.length / figures[i].verticesPerRow) | 0; + count += (rows - 1) * (figures[i].verticesPerRow - 1) * 6; + break; + case 'triangles': + count += figures[i].coords.length; + break; + } + } + // transfer data + var coords = new Float32Array(count * 2); + var colors = new Uint8Array(count * 3); + var coordsMap = context.coords, colorsMap = context.colors; + var pIndex = 0, cIndex = 0; + for (i = 0, ii = figures.length; i < ii; i++) { + var figure = figures[i], ps = figure.coords, cs = figure.colors; + switch (figure.type) { + case 'lattice': + var cols = figure.verticesPerRow; + rows = (ps.length / cols) | 0; + for (var row = 1; row < rows; row++) { + var offset = row * cols + 1; + for (var col = 1; col < cols; col++, offset++) { + coords[pIndex] = coordsMap[ps[offset - cols - 1]]; + coords[pIndex + 1] = coordsMap[ps[offset - cols - 1] + 1]; + coords[pIndex + 2] = coordsMap[ps[offset - cols]]; + coords[pIndex + 3] = coordsMap[ps[offset - cols] + 1]; + coords[pIndex + 4] = coordsMap[ps[offset - 1]]; + coords[pIndex + 5] = coordsMap[ps[offset - 1] + 1]; + colors[cIndex] = colorsMap[cs[offset - cols - 1]]; + colors[cIndex + 1] = colorsMap[cs[offset - cols - 1] + 1]; + colors[cIndex + 2] = colorsMap[cs[offset - cols - 1] + 2]; + colors[cIndex + 3] = colorsMap[cs[offset - cols]]; + colors[cIndex + 4] = colorsMap[cs[offset - cols] + 1]; + colors[cIndex + 5] = colorsMap[cs[offset - cols] + 2]; + colors[cIndex + 6] = colorsMap[cs[offset - 1]]; + colors[cIndex + 7] = colorsMap[cs[offset - 1] + 1]; + colors[cIndex + 8] = colorsMap[cs[offset - 1] + 2]; + + coords[pIndex + 6] = coords[pIndex + 2]; + coords[pIndex + 7] = coords[pIndex + 3]; + coords[pIndex + 8] = coords[pIndex + 4]; + coords[pIndex + 9] = coords[pIndex + 5]; + coords[pIndex + 10] = coordsMap[ps[offset]]; + coords[pIndex + 11] = coordsMap[ps[offset] + 1]; + colors[cIndex + 9] = colors[cIndex + 3]; + colors[cIndex + 10] = colors[cIndex + 4]; + colors[cIndex + 11] = colors[cIndex + 5]; + colors[cIndex + 12] = colors[cIndex + 6]; + colors[cIndex + 13] = colors[cIndex + 7]; + colors[cIndex + 14] = colors[cIndex + 8]; + colors[cIndex + 15] = colorsMap[cs[offset]]; + colors[cIndex + 16] = colorsMap[cs[offset] + 1]; + colors[cIndex + 17] = colorsMap[cs[offset] + 2]; + pIndex += 12; + cIndex += 18; + } + } + break; + case 'triangles': + for (var j = 0, jj = ps.length; j < jj; j++) { + coords[pIndex] = coordsMap[ps[j]]; + coords[pIndex + 1] = coordsMap[ps[j] + 1]; + colors[cIndex] = colorsMap[cs[i]]; + colors[cIndex + 1] = colorsMap[cs[j] + 1]; + colors[cIndex + 2] = colorsMap[cs[j] + 2]; + pIndex += 2; + cIndex += 3; + } + break; + } + } + + // draw + if (backgroundColor) { + gl.clearColor(backgroundColor[0] / 255, backgroundColor[1] / 255, + backgroundColor[2] / 255, 1.0); + } else { + gl.clearColor(0, 0, 0, 0); + } + gl.clear(gl.COLOR_BUFFER_BIT); + + var coordsBuffer = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, coordsBuffer); + gl.bufferData(gl.ARRAY_BUFFER, coords, gl.STATIC_DRAW); + gl.enableVertexAttribArray(cache.positionLocation); + gl.vertexAttribPointer(cache.positionLocation, 2, gl.FLOAT, false, 0, 0); + + var colorsBuffer = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, colorsBuffer); + gl.bufferData(gl.ARRAY_BUFFER, colors, gl.STATIC_DRAW); + gl.enableVertexAttribArray(cache.colorLocation); + gl.vertexAttribPointer(cache.colorLocation, 3, gl.UNSIGNED_BYTE, false, + 0, 0); + + gl.uniform2f(cache.scaleLocation, context.scaleX, context.scaleY); + gl.uniform2f(cache.offsetLocation, context.offsetX, context.offsetY); + + gl.drawArrays(gl.TRIANGLES, 0, count); + + gl.flush(); + + gl.deleteBuffer(coordsBuffer); + gl.deleteBuffer(colorsBuffer); + + return canvas; + } + + function cleanup() { + if (smaskCache && smaskCache.canvas) { + smaskCache.canvas.width = 0; + smaskCache.canvas.height = 0; + } + if (figuresCache && figuresCache.canvas) { + figuresCache.canvas.width = 0; + figuresCache.canvas.height = 0; + } + smaskCache = null; + figuresCache = null; + } + + return { + get isEnabled() { + if (PDFJS.disableWebGL) { + return false; + } + var enabled = false; + try { + generateGL(); + enabled = !!currentGL; + } catch (e) { } + return shadow(this, 'isEnabled', enabled); + }, + composeSMask: composeSMask, + drawFigures: drawFigures, + clear: cleanup + }; +})(); + + +var ShadingIRs = {}; + +ShadingIRs.RadialAxial = { + fromIR: function RadialAxial_fromIR(raw) { + var type = raw[1]; + var colorStops = raw[2]; + var p0 = raw[3]; + var p1 = raw[4]; + var r0 = raw[5]; + var r1 = raw[6]; + return { + type: 'Pattern', + getPattern: function RadialAxial_getPattern(ctx) { + var grad; + if (type === 'axial') { + grad = ctx.createLinearGradient(p0[0], p0[1], p1[0], p1[1]); + } else if (type === 'radial') { + grad = ctx.createRadialGradient(p0[0], p0[1], r0, p1[0], p1[1], r1); + } + + for (var i = 0, ii = colorStops.length; i < ii; ++i) { + var c = colorStops[i]; + grad.addColorStop(c[0], c[1]); + } + return grad; + } + }; + } +}; + +var createMeshCanvas = (function createMeshCanvasClosure() { + function drawTriangle(data, context, p1, p2, p3, c1, c2, c3) { + // Very basic Gouraud-shaded triangle rasterization algorithm. + var coords = context.coords, colors = context.colors; + var bytes = data.data, rowSize = data.width * 4; + var tmp; + if (coords[p1 + 1] > coords[p2 + 1]) { + tmp = p1; p1 = p2; p2 = tmp; tmp = c1; c1 = c2; c2 = tmp; + } + if (coords[p2 + 1] > coords[p3 + 1]) { + tmp = p2; p2 = p3; p3 = tmp; tmp = c2; c2 = c3; c3 = tmp; + } + if (coords[p1 + 1] > coords[p2 + 1]) { + tmp = p1; p1 = p2; p2 = tmp; tmp = c1; c1 = c2; c2 = tmp; + } + var x1 = (coords[p1] + context.offsetX) * context.scaleX; + var y1 = (coords[p1 + 1] + context.offsetY) * context.scaleY; + var x2 = (coords[p2] + context.offsetX) * context.scaleX; + var y2 = (coords[p2 + 1] + context.offsetY) * context.scaleY; + var x3 = (coords[p3] + context.offsetX) * context.scaleX; + var y3 = (coords[p3 + 1] + context.offsetY) * context.scaleY; + if (y1 >= y3) { + return; + } + var c1r = colors[c1], c1g = colors[c1 + 1], c1b = colors[c1 + 2]; + var c2r = colors[c2], c2g = colors[c2 + 1], c2b = colors[c2 + 2]; + var c3r = colors[c3], c3g = colors[c3 + 1], c3b = colors[c3 + 2]; + + var minY = Math.round(y1), maxY = Math.round(y3); + var xa, car, cag, cab; + var xb, cbr, cbg, cbb; + var k; + for (var y = minY; y <= maxY; y++) { + if (y < y2) { + k = y < y1 ? 0 : y1 === y2 ? 1 : (y1 - y) / (y1 - y2); + xa = x1 - (x1 - x2) * k; + car = c1r - (c1r - c2r) * k; + cag = c1g - (c1g - c2g) * k; + cab = c1b - (c1b - c2b) * k; + } else { + k = y > y3 ? 1 : y2 === y3 ? 0 : (y2 - y) / (y2 - y3); + xa = x2 - (x2 - x3) * k; + car = c2r - (c2r - c3r) * k; + cag = c2g - (c2g - c3g) * k; + cab = c2b - (c2b - c3b) * k; + } + k = y < y1 ? 0 : y > y3 ? 1 : (y1 - y) / (y1 - y3); + xb = x1 - (x1 - x3) * k; + cbr = c1r - (c1r - c3r) * k; + cbg = c1g - (c1g - c3g) * k; + cbb = c1b - (c1b - c3b) * k; + var x1_ = Math.round(Math.min(xa, xb)); + var x2_ = Math.round(Math.max(xa, xb)); + var j = rowSize * y + x1_ * 4; + for (var x = x1_; x <= x2_; x++) { + k = (xa - x) / (xa - xb); + k = k < 0 ? 0 : k > 1 ? 1 : k; + bytes[j++] = (car - (car - cbr) * k) | 0; + bytes[j++] = (cag - (cag - cbg) * k) | 0; + bytes[j++] = (cab - (cab - cbb) * k) | 0; + bytes[j++] = 255; + } + } + } + + function drawFigure(data, figure, context) { + var ps = figure.coords; + var cs = figure.colors; + var i, ii; + switch (figure.type) { + case 'lattice': + var verticesPerRow = figure.verticesPerRow; + var rows = Math.floor(ps.length / verticesPerRow) - 1; + var cols = verticesPerRow - 1; + for (i = 0; i < rows; i++) { + var q = i * verticesPerRow; + for (var j = 0; j < cols; j++, q++) { + drawTriangle(data, context, + ps[q], ps[q + 1], ps[q + verticesPerRow], + cs[q], cs[q + 1], cs[q + verticesPerRow]); + drawTriangle(data, context, + ps[q + verticesPerRow + 1], ps[q + 1], ps[q + verticesPerRow], + cs[q + verticesPerRow + 1], cs[q + 1], cs[q + verticesPerRow]); + } + } + break; + case 'triangles': + for (i = 0, ii = ps.length; i < ii; i += 3) { + drawTriangle(data, context, + ps[i], ps[i + 1], ps[i + 2], + cs[i], cs[i + 1], cs[i + 2]); + } + break; + default: + error('illigal figure'); + break; + } + } + + function createMeshCanvas(bounds, combinesScale, coords, colors, figures, + backgroundColor) { + // we will increase scale on some weird factor to let antialiasing take + // care of "rough" edges + var EXPECTED_SCALE = 1.1; + // MAX_PATTERN_SIZE is used to avoid OOM situation. + var MAX_PATTERN_SIZE = 3000; // 10in @ 300dpi shall be enough + + var offsetX = Math.floor(bounds[0]); + var offsetY = Math.floor(bounds[1]); + var boundsWidth = Math.ceil(bounds[2]) - offsetX; + var boundsHeight = Math.ceil(bounds[3]) - offsetY; + + var width = Math.min(Math.ceil(Math.abs(boundsWidth * combinesScale[0] * + EXPECTED_SCALE)), MAX_PATTERN_SIZE); + var height = Math.min(Math.ceil(Math.abs(boundsHeight * combinesScale[1] * + EXPECTED_SCALE)), MAX_PATTERN_SIZE); + var scaleX = boundsWidth / width; + var scaleY = boundsHeight / height; + + var context = { + coords: coords, + colors: colors, + offsetX: -offsetX, + offsetY: -offsetY, + scaleX: 1 / scaleX, + scaleY: 1 / scaleY + }; + + var canvas, tmpCanvas, i, ii; + if (WebGLUtils.isEnabled) { + canvas = WebGLUtils.drawFigures(width, height, backgroundColor, + figures, context); + + // https://bugzilla.mozilla.org/show_bug.cgi?id=972126 + tmpCanvas = CachedCanvases.getCanvas('mesh', width, height, false); + tmpCanvas.context.drawImage(canvas, 0, 0); + canvas = tmpCanvas.canvas; + } else { + tmpCanvas = CachedCanvases.getCanvas('mesh', width, height, false); + var tmpCtx = tmpCanvas.context; + + var data = tmpCtx.createImageData(width, height); + if (backgroundColor) { + var bytes = data.data; + for (i = 0, ii = bytes.length; i < ii; i += 4) { + bytes[i] = backgroundColor[0]; + bytes[i + 1] = backgroundColor[1]; + bytes[i + 2] = backgroundColor[2]; + bytes[i + 3] = 255; + } + } + for (i = 0; i < figures.length; i++) { + drawFigure(data, figures[i], context); + } + tmpCtx.putImageData(data, 0, 0); + canvas = tmpCanvas.canvas; + } + + return {canvas: canvas, offsetX: offsetX, offsetY: offsetY, + scaleX: scaleX, scaleY: scaleY}; + } + return createMeshCanvas; +})(); + +ShadingIRs.Mesh = { + fromIR: function Mesh_fromIR(raw) { + //var type = raw[1]; + var coords = raw[2]; + var colors = raw[3]; + var figures = raw[4]; + var bounds = raw[5]; + var matrix = raw[6]; + //var bbox = raw[7]; + var background = raw[8]; + return { + type: 'Pattern', + getPattern: function Mesh_getPattern(ctx, owner, shadingFill) { + var scale; + if (shadingFill) { + scale = Util.singularValueDecompose2dScale(ctx.mozCurrentTransform); + } else { + // Obtain scale from matrix and current transformation matrix. + scale = Util.singularValueDecompose2dScale(owner.baseTransform); + if (matrix) { + var matrixScale = Util.singularValueDecompose2dScale(matrix); + scale = [scale[0] * matrixScale[0], + scale[1] * matrixScale[1]]; + } + } + + + // Rasterizing on the main thread since sending/queue large canvases + // might cause OOM. + var temporaryPatternCanvas = createMeshCanvas(bounds, scale, coords, + colors, figures, shadingFill ? null : background); + + if (!shadingFill) { + ctx.setTransform.apply(ctx, owner.baseTransform); + if (matrix) { + ctx.transform.apply(ctx, matrix); + } + } + + ctx.translate(temporaryPatternCanvas.offsetX, + temporaryPatternCanvas.offsetY); + ctx.scale(temporaryPatternCanvas.scaleX, + temporaryPatternCanvas.scaleY); + + return ctx.createPattern(temporaryPatternCanvas.canvas, 'no-repeat'); + } + }; + } +}; + +ShadingIRs.Dummy = { + fromIR: function Dummy_fromIR() { + return { + type: 'Pattern', + getPattern: function Dummy_fromIR_getPattern() { + return 'hotpink'; + } + }; + } +}; + +function getShadingPatternFromIR(raw) { + var shadingIR = ShadingIRs[raw[0]]; + if (!shadingIR) { + error('Unknown IR type: ' + raw[0]); + } + return shadingIR.fromIR(raw); +} + +var TilingPattern = (function TilingPatternClosure() { + var PaintType = { + COLORED: 1, + UNCOLORED: 2 + }; + + var MAX_PATTERN_SIZE = 3000; // 10in @ 300dpi shall be enough + + function TilingPattern(IR, color, ctx, objs, commonObjs, baseTransform) { + this.operatorList = IR[2]; + this.matrix = IR[3] || [1, 0, 0, 1, 0, 0]; + this.bbox = IR[4]; + this.xstep = IR[5]; + this.ystep = IR[6]; + this.paintType = IR[7]; + this.tilingType = IR[8]; + this.color = color; + this.objs = objs; + this.commonObjs = commonObjs; + this.baseTransform = baseTransform; + this.type = 'Pattern'; + this.ctx = ctx; + } + + TilingPattern.prototype = { + createPatternCanvas: function TilinPattern_createPatternCanvas(owner) { + var operatorList = this.operatorList; + var bbox = this.bbox; + var xstep = this.xstep; + var ystep = this.ystep; + var paintType = this.paintType; + var tilingType = this.tilingType; + var color = this.color; + var objs = this.objs; + var commonObjs = this.commonObjs; + + info('TilingType: ' + tilingType); + + var x0 = bbox[0], y0 = bbox[1], x1 = bbox[2], y1 = bbox[3]; + + var topLeft = [x0, y0]; + // we want the canvas to be as large as the step size + var botRight = [x0 + xstep, y0 + ystep]; + + var width = botRight[0] - topLeft[0]; + var height = botRight[1] - topLeft[1]; + + // Obtain scale from matrix and current transformation matrix. + var matrixScale = Util.singularValueDecompose2dScale(this.matrix); + var curMatrixScale = Util.singularValueDecompose2dScale( + this.baseTransform); + var combinedScale = [matrixScale[0] * curMatrixScale[0], + matrixScale[1] * curMatrixScale[1]]; + + // MAX_PATTERN_SIZE is used to avoid OOM situation. + // Use width and height values that are as close as possible to the end + // result when the pattern is used. Too low value makes the pattern look + // blurry. Too large value makes it look too crispy. + width = Math.min(Math.ceil(Math.abs(width * combinedScale[0])), + MAX_PATTERN_SIZE); + + height = Math.min(Math.ceil(Math.abs(height * combinedScale[1])), + MAX_PATTERN_SIZE); + + var tmpCanvas = CachedCanvases.getCanvas('pattern', width, height, true); + var tmpCtx = tmpCanvas.context; + var graphics = new CanvasGraphics(tmpCtx, commonObjs, objs); + graphics.groupLevel = owner.groupLevel; + + this.setFillAndStrokeStyleToContext(tmpCtx, paintType, color); + + this.setScale(width, height, xstep, ystep); + this.transformToScale(graphics); + + // transform coordinates to pattern space + var tmpTranslate = [1, 0, 0, 1, -topLeft[0], -topLeft[1]]; + graphics.transform.apply(graphics, tmpTranslate); + + this.clipBbox(graphics, bbox, x0, y0, x1, y1); + + graphics.executeOperatorList(operatorList); + return tmpCanvas.canvas; + }, + + setScale: function TilingPattern_setScale(width, height, xstep, ystep) { + this.scale = [width / xstep, height / ystep]; + }, + + transformToScale: function TilingPattern_transformToScale(graphics) { + var scale = this.scale; + var tmpScale = [scale[0], 0, 0, scale[1], 0, 0]; + graphics.transform.apply(graphics, tmpScale); + }, + + scaleToContext: function TilingPattern_scaleToContext() { + var scale = this.scale; + this.ctx.scale(1 / scale[0], 1 / scale[1]); + }, + + clipBbox: function clipBbox(graphics, bbox, x0, y0, x1, y1) { + if (bbox && isArray(bbox) && bbox.length === 4) { + var bboxWidth = x1 - x0; + var bboxHeight = y1 - y0; + graphics.ctx.rect(x0, y0, bboxWidth, bboxHeight); + graphics.clip(); + graphics.endPath(); + } + }, + + setFillAndStrokeStyleToContext: + function setFillAndStrokeStyleToContext(context, paintType, color) { + switch (paintType) { + case PaintType.COLORED: + var ctx = this.ctx; + context.fillStyle = ctx.fillStyle; + context.strokeStyle = ctx.strokeStyle; + break; + case PaintType.UNCOLORED: + var cssColor = Util.makeCssRgb(color[0], color[1], color[2]); + context.fillStyle = cssColor; + context.strokeStyle = cssColor; + break; + default: + error('Unsupported paint type: ' + paintType); + } + }, + + getPattern: function TilingPattern_getPattern(ctx, owner) { + var temporaryPatternCanvas = this.createPatternCanvas(owner); + + ctx = this.ctx; + ctx.setTransform.apply(ctx, this.baseTransform); + ctx.transform.apply(ctx, this.matrix); + this.scaleToContext(); + + return ctx.createPattern(temporaryPatternCanvas, 'repeat'); + } + }; + + return TilingPattern; +})(); + + +PDFJS.disableFontFace = false; + +var FontLoader = { + insertRule: function fontLoaderInsertRule(rule) { + var styleElement = document.getElementById('PDFJS_FONT_STYLE_TAG'); + if (!styleElement) { + styleElement = document.createElement('style'); + styleElement.id = 'PDFJS_FONT_STYLE_TAG'; + document.documentElement.getElementsByTagName('head')[0].appendChild( + styleElement); + } + + var styleSheet = styleElement.sheet; + styleSheet.insertRule(rule, styleSheet.cssRules.length); + }, + + clear: function fontLoaderClear() { + var styleElement = document.getElementById('PDFJS_FONT_STYLE_TAG'); + if (styleElement) { + styleElement.parentNode.removeChild(styleElement); + } +//#if !(MOZCENTRAL) + this.nativeFontFaces.forEach(function(nativeFontFace) { + document.fonts.delete(nativeFontFace); + }); + this.nativeFontFaces.length = 0; +//#endif + }, +//#if !(MOZCENTRAL) + get loadTestFont() { + // This is a CFF font with 1 glyph for '.' that fills its entire width and + // height. + return shadow(this, 'loadTestFont', atob( + 'T1RUTwALAIAAAwAwQ0ZGIDHtZg4AAAOYAAAAgUZGVE1lkzZwAAAEHAAAABxHREVGABQAFQ' + + 'AABDgAAAAeT1MvMlYNYwkAAAEgAAAAYGNtYXABDQLUAAACNAAAAUJoZWFk/xVFDQAAALwA' + + 'AAA2aGhlYQdkA+oAAAD0AAAAJGhtdHgD6AAAAAAEWAAAAAZtYXhwAAJQAAAAARgAAAAGbm' + + 'FtZVjmdH4AAAGAAAAAsXBvc3T/hgAzAAADeAAAACAAAQAAAAEAALZRFsRfDzz1AAsD6AAA' + + 'AADOBOTLAAAAAM4KHDwAAAAAA+gDIQAAAAgAAgAAAAAAAAABAAADIQAAAFoD6AAAAAAD6A' + + 'ABAAAAAAAAAAAAAAAAAAAAAQAAUAAAAgAAAAQD6AH0AAUAAAKKArwAAACMAooCvAAAAeAA' + + 'MQECAAACAAYJAAAAAAAAAAAAAQAAAAAAAAAAAAAAAFBmRWQAwAAuAC4DIP84AFoDIQAAAA' + + 'AAAQAAAAAAAAAAACAAIAABAAAADgCuAAEAAAAAAAAAAQAAAAEAAAAAAAEAAQAAAAEAAAAA' + + 'AAIAAQAAAAEAAAAAAAMAAQAAAAEAAAAAAAQAAQAAAAEAAAAAAAUAAQAAAAEAAAAAAAYAAQ' + + 'AAAAMAAQQJAAAAAgABAAMAAQQJAAEAAgABAAMAAQQJAAIAAgABAAMAAQQJAAMAAgABAAMA' + + 'AQQJAAQAAgABAAMAAQQJAAUAAgABAAMAAQQJAAYAAgABWABYAAAAAAAAAwAAAAMAAAAcAA' + + 'EAAAAAADwAAwABAAAAHAAEACAAAAAEAAQAAQAAAC7//wAAAC7////TAAEAAAAAAAABBgAA' + + 'AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAA' + + 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' + + 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' + + 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' + + 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAA' + + 'AAAAD/gwAyAAAAAQAAAAAAAAAAAAAAAAAAAAABAAQEAAEBAQJYAAEBASH4DwD4GwHEAvgc' + + 'A/gXBIwMAYuL+nz5tQXkD5j3CBLnEQACAQEBIVhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWF' + + 'hYWFhYWFhYAAABAQAADwACAQEEE/t3Dov6fAH6fAT+fPp8+nwHDosMCvm1Cvm1DAz6fBQA' + + 'AAAAAAABAAAAAMmJbzEAAAAAzgTjFQAAAADOBOQpAAEAAAAAAAAADAAUAAQAAAABAAAAAg' + + 'ABAAAAAAAAAAAD6AAAAAAAAA==' + )); + }, + + loadTestFontId: 0, + + loadingContext: { + requests: [], + nextRequestId: 0 + }, + + isSyncFontLoadingSupported: (function detectSyncFontLoadingSupport() { + if (isWorker) { + return false; + } + + // User agent string sniffing is bad, but there is no reliable way to tell + // if font is fully loaded and ready to be used with canvas. + var userAgent = window.navigator.userAgent; + var m = /Mozilla\/5.0.*?rv:(\d+).*? Gecko/.exec(userAgent); + if (m && m[1] >= 14) { + return true; + } + // TODO other browsers + if (userAgent === 'node') { + return true; + } + return false; + })(), + + nativeFontFaces: [], + + isFontLoadingAPISupported: (!isWorker && typeof document !== 'undefined' && + !!document.fonts), + + addNativeFontFace: function fontLoader_addNativeFontFace(nativeFontFace) { + this.nativeFontFaces.push(nativeFontFace); + document.fonts.add(nativeFontFace); + }, + + bind: function fontLoaderBind(fonts, callback) { + assert(!isWorker, 'bind() shall be called from main thread'); + + var rules = []; + var fontsToLoad = []; + var fontLoadPromises = []; + for (var i = 0, ii = fonts.length; i < ii; i++) { + var font = fonts[i]; + + // Add the font to the DOM only once or skip if the font + // is already loaded. + if (font.attached || font.loading === false) { + continue; + } + font.attached = true; + + if (this.isFontLoadingAPISupported) { + var nativeFontFace = font.createNativeFontFace(); + if (nativeFontFace) { + fontLoadPromises.push(nativeFontFace.loaded); + } + } else { + var rule = font.bindDOM(); + if (rule) { + rules.push(rule); + fontsToLoad.push(font); + } + } + } + + var request = FontLoader.queueLoadingCallback(callback); + if (this.isFontLoadingAPISupported) { + Promise.all(fontsToLoad).then(function() { + request.complete(); + }); + } else if (rules.length > 0 && !this.isSyncFontLoadingSupported) { + FontLoader.prepareFontLoadEvent(rules, fontsToLoad, request); + } else { + request.complete(); + } + }, + + queueLoadingCallback: function FontLoader_queueLoadingCallback(callback) { + function LoadLoader_completeRequest() { + assert(!request.end, 'completeRequest() cannot be called twice'); + request.end = Date.now(); + + // sending all completed requests in order how they were queued + while (context.requests.length > 0 && context.requests[0].end) { + var otherRequest = context.requests.shift(); + setTimeout(otherRequest.callback, 0); + } + } + + var context = FontLoader.loadingContext; + var requestId = 'pdfjs-font-loading-' + (context.nextRequestId++); + var request = { + id: requestId, + complete: LoadLoader_completeRequest, + callback: callback, + started: Date.now() + }; + context.requests.push(request); + return request; + }, + + prepareFontLoadEvent: function fontLoaderPrepareFontLoadEvent(rules, + fonts, + request) { + /** Hack begin */ + // There's currently no event when a font has finished downloading so the + // following code is a dirty hack to 'guess' when a font is + // ready. It's assumed fonts are loaded in order, so add a known test + // font after the desired fonts and then test for the loading of that + // test font. + + function int32(data, offset) { + return (data.charCodeAt(offset) << 24) | + (data.charCodeAt(offset + 1) << 16) | + (data.charCodeAt(offset + 2) << 8) | + (data.charCodeAt(offset + 3) & 0xff); + } + + function spliceString(s, offset, remove, insert) { + var chunk1 = s.substr(0, offset); + var chunk2 = s.substr(offset + remove); + return chunk1 + insert + chunk2; + } + + var i, ii; + + var canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + var ctx = canvas.getContext('2d'); + + var called = 0; + function isFontReady(name, callback) { + called++; + // With setTimeout clamping this gives the font ~100ms to load. + if(called > 30) { + warn('Load test font never loaded.'); + callback(); + return; + } + ctx.font = '30px ' + name; + ctx.fillText('.', 0, 20); + var imageData = ctx.getImageData(0, 0, 1, 1); + if (imageData.data[3] > 0) { + callback(); + return; + } + setTimeout(isFontReady.bind(null, name, callback)); + } + + var loadTestFontId = 'lt' + Date.now() + this.loadTestFontId++; + // Chromium seems to cache fonts based on a hash of the actual font data, + // so the font must be modified for each load test else it will appear to + // be loaded already. + // TODO: This could maybe be made faster by avoiding the btoa of the full + // font by splitting it in chunks before hand and padding the font id. + var data = this.loadTestFont; + var COMMENT_OFFSET = 976; // has to be on 4 byte boundary (for checksum) + data = spliceString(data, COMMENT_OFFSET, loadTestFontId.length, + loadTestFontId); + // CFF checksum is important for IE, adjusting it + var CFF_CHECKSUM_OFFSET = 16; + var XXXX_VALUE = 0x58585858; // the "comment" filled with 'X' + var checksum = int32(data, CFF_CHECKSUM_OFFSET); + for (i = 0, ii = loadTestFontId.length - 3; i < ii; i += 4) { + checksum = (checksum - XXXX_VALUE + int32(loadTestFontId, i)) | 0; + } + if (i < loadTestFontId.length) { // align to 4 bytes boundary + checksum = (checksum - XXXX_VALUE + + int32(loadTestFontId + 'XXX', i)) | 0; + } + data = spliceString(data, CFF_CHECKSUM_OFFSET, 4, string32(checksum)); + + var url = 'url(data:font/opentype;base64,' + btoa(data) + ');'; + var rule = '@font-face { font-family:"' + loadTestFontId + '";src:' + + url + '}'; + FontLoader.insertRule(rule); + + var names = []; + for (i = 0, ii = fonts.length; i < ii; i++) { + names.push(fonts[i].loadedName); + } + names.push(loadTestFontId); + + var div = document.createElement('div'); + div.setAttribute('style', + 'visibility: hidden;' + + 'width: 10px; height: 10px;' + + 'position: absolute; top: 0px; left: 0px;'); + for (i = 0, ii = names.length; i < ii; ++i) { + var span = document.createElement('span'); + span.textContent = 'Hi'; + span.style.fontFamily = names[i]; + div.appendChild(span); + } + document.body.appendChild(div); + + isFontReady(loadTestFontId, function() { + document.body.removeChild(div); + request.complete(); + }); + /** Hack end */ + } +//#else +//bind: function fontLoaderBind(fonts, callback) { +// assert(!isWorker, 'bind() shall be called from main thread'); +// +// for (var i = 0, ii = fonts.length; i < ii; i++) { +// var font = fonts[i]; +// if (font.attached) { +// continue; +// } +// +// font.attached = true; +// font.bindDOM() +// } +// +// setTimeout(callback); +//} +//#endif +}; + +var FontFaceObject = (function FontFaceObjectClosure() { + function FontFaceObject(name, file, properties) { + this.compiledGlyphs = {}; + if (arguments.length === 1) { + // importing translated data + var data = arguments[0]; + for (var i in data) { + this[i] = data[i]; + } + return; + } + } + FontFaceObject.prototype = { +//#if !(MOZCENTRAL) + createNativeFontFace: function FontFaceObject_createNativeFontFace() { + if (!this.data) { + return null; + } + + if (PDFJS.disableFontFace) { + this.disableFontFace = true; + return null; + } + + var nativeFontFace = new FontFace(this.loadedName, this.data, {}); + + FontLoader.addNativeFontFace(nativeFontFace); + + if (PDFJS.pdfBug && 'FontInspector' in globalScope && + globalScope['FontInspector'].enabled) { + globalScope['FontInspector'].fontAdded(this); + } + return nativeFontFace; + }, +//#endif + + bindDOM: function FontFaceObject_bindDOM() { + if (!this.data) { + return null; + } + + if (PDFJS.disableFontFace) { + this.disableFontFace = true; + return null; + } + + var data = bytesToString(new Uint8Array(this.data)); + var fontName = this.loadedName; + + // Add the font-face rule to the document + var url = ('url(data:' + this.mimetype + ';base64,' + + window.btoa(data) + ');'); + var rule = '@font-face { font-family:"' + fontName + '";src:' + url + '}'; + FontLoader.insertRule(rule); + + if (PDFJS.pdfBug && 'FontInspector' in globalScope && + globalScope['FontInspector'].enabled) { + globalScope['FontInspector'].fontAdded(this, url); + } + + return rule; + }, + + getPathGenerator: function FontLoader_getPathGenerator(objs, character) { + if (!(character in this.compiledGlyphs)) { + var js = objs.get(this.loadedName + '_path_' + character); + /*jshint -W054 */ + this.compiledGlyphs[character] = new Function('c', 'size', js); + } + return this.compiledGlyphs[character]; + } + }; + return FontFaceObject; +})(); + + +var ANNOT_MIN_SIZE = 10; // px + +var AnnotationUtils = (function AnnotationUtilsClosure() { + // TODO(mack): This dupes some of the logic in CanvasGraphics.setFont() + function setTextStyles(element, item, fontObj) { + + var style = element.style; + style.fontSize = item.fontSize + 'px'; + style.direction = item.fontDirection < 0 ? 'rtl': 'ltr'; + + if (!fontObj) { + return; + } + + style.fontWeight = fontObj.black ? + (fontObj.bold ? 'bolder' : 'bold') : + (fontObj.bold ? 'bold' : 'normal'); + style.fontStyle = fontObj.italic ? 'italic' : 'normal'; + + var fontName = fontObj.loadedName; + var fontFamily = fontName ? '"' + fontName + '", ' : ''; + // Use a reasonable default font if the font doesn't specify a fallback + var fallbackName = fontObj.fallbackName || 'Helvetica, sans-serif'; + style.fontFamily = fontFamily + fallbackName; + } + + function initContainer(item, drawBorder) { + var container = document.createElement('section'); + var cstyle = container.style; + var width = item.rect[2] - item.rect[0]; + var height = item.rect[3] - item.rect[1]; + + var bWidth = item.borderWidth || 0; + if (bWidth) { + width = width - 2 * bWidth; + height = height - 2 * bWidth; + cstyle.borderWidth = bWidth + 'px'; + var color = item.color; + if (drawBorder && color) { + cstyle.borderStyle = 'solid'; + cstyle.borderColor = Util.makeCssRgb(Math.round(color[0] * 255), + Math.round(color[1] * 255), + Math.round(color[2] * 255)); + } + } + cstyle.width = width + 'px'; + cstyle.height = height + 'px'; + return container; + } + + function getHtmlElementForTextWidgetAnnotation(item, commonObjs) { + var element = document.createElement('div'); + var width = item.rect[2] - item.rect[0]; + var height = item.rect[3] - item.rect[1]; + element.style.width = width + 'px'; + element.style.height = height + 'px'; + element.style.display = 'table'; + + var content = document.createElement('div'); + content.textContent = item.fieldValue; + var textAlignment = item.textAlignment; + content.style.textAlign = ['left', 'center', 'right'][textAlignment]; + content.style.verticalAlign = 'middle'; + content.style.display = 'table-cell'; + + var fontObj = item.fontRefName ? + commonObjs.getData(item.fontRefName) : null; + setTextStyles(content, item, fontObj); + + element.appendChild(content); + + return element; + } + + function getHtmlElementForTextAnnotation(item) { + var rect = item.rect; + + // sanity check because of OOo-generated PDFs + if ((rect[3] - rect[1]) < ANNOT_MIN_SIZE) { + rect[3] = rect[1] + ANNOT_MIN_SIZE; + } + if ((rect[2] - rect[0]) < ANNOT_MIN_SIZE) { + rect[2] = rect[0] + (rect[3] - rect[1]); // make it square + } + + var container = initContainer(item, false); + container.className = 'annotText'; + + var image = document.createElement('img'); + image.style.height = container.style.height; + image.style.width = container.style.width; + var iconName = item.name; + image.src = PDFJS.imageResourcesPath + 'annotation-' + + iconName.toLowerCase() + '.svg'; + image.alt = '[{{type}} Annotation]'; + image.dataset.l10nId = 'text_annotation_type'; + image.dataset.l10nArgs = JSON.stringify({type: iconName}); + + var contentWrapper = document.createElement('div'); + contentWrapper.className = 'annotTextContentWrapper'; + contentWrapper.style.left = Math.floor(rect[2] - rect[0] + 5) + 'px'; + contentWrapper.style.top = '-10px'; + + var content = document.createElement('div'); + content.className = 'annotTextContent'; + content.setAttribute('hidden', true); + + var i, ii; + if (item.hasBgColor) { + var color = item.color; + + // Enlighten the color (70%) + var BACKGROUND_ENLIGHT = 0.7; + var r = BACKGROUND_ENLIGHT * (1.0 - color[0]) + color[0]; + var g = BACKGROUND_ENLIGHT * (1.0 - color[1]) + color[1]; + var b = BACKGROUND_ENLIGHT * (1.0 - color[2]) + color[2]; + content.style.backgroundColor = Util.makeCssRgb((r * 255) | 0, + (g * 255) | 0, + (b * 255) | 0); + } + + var title = document.createElement('h1'); + var text = document.createElement('p'); + title.textContent = item.title; + + if (!item.content && !item.title) { + content.setAttribute('hidden', true); + } else { + var e = document.createElement('span'); + var lines = item.content.split(/(?:\r\n?|\n)/); + for (i = 0, ii = lines.length; i < ii; ++i) { + var line = lines[i]; + e.appendChild(document.createTextNode(line)); + if (i < (ii - 1)) { + e.appendChild(document.createElement('br')); + } + } + text.appendChild(e); + + var pinned = false; + + var showAnnotation = function showAnnotation(pin) { + if (pin) { + pinned = true; + } + if (content.hasAttribute('hidden')) { + container.style.zIndex += 1; + content.removeAttribute('hidden'); + } + }; + + var hideAnnotation = function hideAnnotation(unpin) { + if (unpin) { + pinned = false; + } + if (!content.hasAttribute('hidden') && !pinned) { + container.style.zIndex -= 1; + content.setAttribute('hidden', true); + } + }; + + var toggleAnnotation = function toggleAnnotation() { + if (pinned) { + hideAnnotation(true); + } else { + showAnnotation(true); + } + }; + + image.addEventListener('click', function image_clickHandler() { + toggleAnnotation(); + }, false); + image.addEventListener('mouseover', function image_mouseOverHandler() { + showAnnotation(); + }, false); + image.addEventListener('mouseout', function image_mouseOutHandler() { + hideAnnotation(); + }, false); + + content.addEventListener('click', function content_clickHandler() { + hideAnnotation(true); + }, false); + } + + content.appendChild(title); + content.appendChild(text); + contentWrapper.appendChild(content); + container.appendChild(image); + container.appendChild(contentWrapper); + + return container; + } + + function getHtmlElementForLinkAnnotation(item) { + var container = initContainer(item, true); + container.className = 'annotLink'; + + var link = document.createElement('a'); + link.href = link.title = item.url || ''; + if (item.url && PDFJS.openExternalLinksInNewWindow) { + link.target = '_blank'; + } + + container.appendChild(link); + + return container; + } + + function getHtmlElement(data, objs) { + switch (data.annotationType) { + case AnnotationType.WIDGET: + return getHtmlElementForTextWidgetAnnotation(data, objs); + case AnnotationType.TEXT: + return getHtmlElementForTextAnnotation(data); + case AnnotationType.LINK: + return getHtmlElementForLinkAnnotation(data); + default: + throw new Error('Unsupported annotationType: ' + data.annotationType); + } + } + + return { + getHtmlElement: getHtmlElement + }; +})(); +PDFJS.AnnotationUtils = AnnotationUtils; + + +//#if (GENERIC || SINGLE_FILE) +var SVG_DEFAULTS = { + fontStyle: 'normal', + fontWeight: 'normal', + fillColor: '#000000' +}; + +var convertImgDataToPng = (function convertImgDataToPngClosure() { + var PNG_HEADER = + new Uint8Array([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]); + + var CHUNK_WRAPPER_SIZE = 12; + + var crcTable = new Int32Array(256); + for (var i = 0; i < 256; i++) { + var c = i; + for (var h = 0; h < 8; h++) { + if (c & 1) { + c = 0xedB88320 ^ ((c >> 1) & 0x7fffffff); + } else { + c = (c >> 1) & 0x7fffffff; + } + } + crcTable[i] = c; + } + + function crc32(data, start, end) { + var crc = -1; + for (var i = start; i < end; i++) { + var a = (crc ^ data[i]) & 0xff; + var b = crcTable[a]; + crc = (crc >>> 8) ^ b; + } + return crc ^ -1; + } + + function writePngChunk(type, body, data, offset) { + var p = offset; + var len = body.length; + + data[p] = len >> 24 & 0xff; + data[p + 1] = len >> 16 & 0xff; + data[p + 2] = len >> 8 & 0xff; + data[p + 3] = len & 0xff; + p += 4; + + data[p] = type.charCodeAt(0) & 0xff; + data[p + 1] = type.charCodeAt(1) & 0xff; + data[p + 2] = type.charCodeAt(2) & 0xff; + data[p + 3] = type.charCodeAt(3) & 0xff; + p += 4; + + data.set(body, p); + p += body.length; + + var crc = crc32(data, offset + 4, p); + + data[p] = crc >> 24 & 0xff; + data[p + 1] = crc >> 16 & 0xff; + data[p + 2] = crc >> 8 & 0xff; + data[p + 3] = crc & 0xff; + } + + function adler32(data, start, end) { + var a = 1; + var b = 0; + for (var i = start; i < end; ++i) { + a = (a + (data[i] & 0xff)) % 65521; + b = (b + a) % 65521; + } + return (b << 16) | a; + } + + function encode(imgData, kind) { + var width = imgData.width; + var height = imgData.height; + var bitDepth, colorType, lineSize; + var bytes = imgData.data; + + switch (kind) { + case ImageKind.GRAYSCALE_1BPP: + colorType = 0; + bitDepth = 1; + lineSize = (width + 7) >> 3; + break; + case ImageKind.RGB_24BPP: + colorType = 2; + bitDepth = 8; + lineSize = width * 3; + break; + case ImageKind.RGBA_32BPP: + colorType = 6; + bitDepth = 8; + lineSize = width * 4; + break; + default: + throw new Error('invalid format'); + } + + // prefix every row with predictor 0 + var literals = new Uint8Array((1 + lineSize) * height); + var offsetLiterals = 0, offsetBytes = 0; + var y, i; + for (y = 0; y < height; ++y) { + literals[offsetLiterals++] = 0; // no prediction + literals.set(bytes.subarray(offsetBytes, offsetBytes + lineSize), + offsetLiterals); + offsetBytes += lineSize; + offsetLiterals += lineSize; + } + + if (kind === ImageKind.GRAYSCALE_1BPP) { + // inverting for B/W + offsetLiterals = 0; + for (y = 0; y < height; y++) { + offsetLiterals++; // skipping predictor + for (i = 0; i < lineSize; i++) { + literals[offsetLiterals++] ^= 0xFF; + } + } + } + + var ihdr = new Uint8Array([ + width >> 24 & 0xff, + width >> 16 & 0xff, + width >> 8 & 0xff, + width & 0xff, + height >> 24 & 0xff, + height >> 16 & 0xff, + height >> 8 & 0xff, + height & 0xff, + bitDepth, // bit depth + colorType, // color type + 0x00, // compression method + 0x00, // filter method + 0x00 // interlace method + ]); + + var len = literals.length; + var maxBlockLength = 0xFFFF; + + var deflateBlocks = Math.ceil(len / maxBlockLength); + var idat = new Uint8Array(2 + len + deflateBlocks * 5 + 4); + var pi = 0; + idat[pi++] = 0x78; // compression method and flags + idat[pi++] = 0x9c; // flags + + var pos = 0; + while (len > maxBlockLength) { + // writing non-final DEFLATE blocks type 0 and length of 65535 + idat[pi++] = 0x00; + idat[pi++] = 0xff; + idat[pi++] = 0xff; + idat[pi++] = 0x00; + idat[pi++] = 0x00; + idat.set(literals.subarray(pos, pos + maxBlockLength), pi); + pi += maxBlockLength; + pos += maxBlockLength; + len -= maxBlockLength; + } + + // writing non-final DEFLATE blocks type 0 + idat[pi++] = 0x01; + idat[pi++] = len & 0xff; + idat[pi++] = len >> 8 & 0xff; + idat[pi++] = (~len & 0xffff) & 0xff; + idat[pi++] = (~len & 0xffff) >> 8 & 0xff; + idat.set(literals.subarray(pos), pi); + pi += literals.length - pos; + + var adler = adler32(literals, 0, literals.length); // checksum + idat[pi++] = adler >> 24 & 0xff; + idat[pi++] = adler >> 16 & 0xff; + idat[pi++] = adler >> 8 & 0xff; + idat[pi++] = adler & 0xff; + + // PNG will consists: header, IHDR+data, IDAT+data, and IEND. + var pngLength = PNG_HEADER.length + (CHUNK_WRAPPER_SIZE * 3) + + ihdr.length + idat.length; + var data = new Uint8Array(pngLength); + var offset = 0; + data.set(PNG_HEADER, offset); + offset += PNG_HEADER.length; + writePngChunk('IHDR', ihdr, data, offset); + offset += CHUNK_WRAPPER_SIZE + ihdr.length; + writePngChunk('IDATA', idat, data, offset); + offset += CHUNK_WRAPPER_SIZE + idat.length; + writePngChunk('IEND', new Uint8Array(0), data, offset); + + return PDFJS.createObjectURL(data, 'image/png'); + } + + return function convertImgDataToPng(imgData) { + var kind = (imgData.kind === undefined ? + ImageKind.GRAYSCALE_1BPP : imgData.kind); + return encode(imgData, kind); + }; +})(); + +var SVGExtraState = (function SVGExtraStateClosure() { + function SVGExtraState() { + this.fontSizeScale = 1; + this.fontWeight = SVG_DEFAULTS.fontWeight; + this.fontSize = 0; + + this.textMatrix = IDENTITY_MATRIX; + this.fontMatrix = FONT_IDENTITY_MATRIX; + this.leading = 0; + + // Current point (in user coordinates) + this.x = 0; + this.y = 0; + + // Start of text line (in text coordinates) + this.lineX = 0; + this.lineY = 0; + + // Character and word spacing + this.charSpacing = 0; + this.wordSpacing = 0; + this.textHScale = 1; + this.textRise = 0; + + // Default foreground and background colors + this.fillColor = SVG_DEFAULTS.fillColor; + this.strokeColor = '#000000'; + + this.fillAlpha = 1; + this.strokeAlpha = 1; + this.lineWidth = 1; + this.lineJoin = ''; + this.lineCap = ''; + this.miterLimit = 0; + + this.dashArray = []; + this.dashPhase = 0; + + this.dependencies = []; + + // Clipping + this.clipId = ''; + this.pendingClip = false; + + this.maskId = ''; + } + + SVGExtraState.prototype = { + clone: function SVGExtraState_clone() { + return Object.create(this); + }, + setCurrentPoint: function SVGExtraState_setCurrentPoint(x, y) { + this.x = x; + this.y = y; + } + }; + return SVGExtraState; +})(); + +var SVGGraphics = (function SVGGraphicsClosure() { + function createScratchSVG(width, height) { + var NS = 'http://www.w3.org/2000/svg'; + var svg = document.createElementNS(NS, 'svg:svg'); + svg.setAttributeNS(null, 'version', '1.1'); + svg.setAttributeNS(null, 'width', width + 'px'); + svg.setAttributeNS(null, 'height', height + 'px'); + svg.setAttributeNS(null, 'viewBox', '0 0 ' + width + ' ' + height); + return svg; + } + + function opListToTree(opList) { + var opTree = []; + var tmp = []; + var opListLen = opList.length; + + for (var x = 0; x < opListLen; x++) { + if (opList[x].fn === 'save') { + opTree.push({'fnId': 92, 'fn': 'group', 'items': []}); + tmp.push(opTree); + opTree = opTree[opTree.length - 1].items; + continue; + } + + if(opList[x].fn === 'restore') { + opTree = tmp.pop(); + } else { + opTree.push(opList[x]); + } + } + return opTree; + } + + /** + * Formats float number. + * @param value {number} number to format. + * @returns {string} + */ + function pf(value) { + if (value === (value | 0)) { // integer number + return value.toString(); + } + var s = value.toFixed(10); + var i = s.length - 1; + if (s[i] !== '0') { + return s; + } + // removing trailing zeros + do { + i--; + } while (s[i] === '0'); + return s.substr(0, s[i] === '.' ? i : i + 1); + } + + /** + * Formats transform matrix. The standard rotation, scale and translate + * matrices are replaced by their shorter forms, and for identity matrix + * returns empty string to save the memory. + * @param m {Array} matrix to format. + * @returns {string} + */ + function pm(m) { + if (m[4] === 0 && m[5] === 0) { + if (m[1] === 0 && m[2] === 0) { + if (m[0] === 1 && m[3] === 1) { + return ''; + } + return 'scale(' + pf(m[0]) + ' ' + pf(m[3]) + ')'; + } + if (m[0] === m[3] && m[1] === -m[2]) { + var a = Math.acos(m[0]) * 180 / Math.PI; + return 'rotate(' + pf(a) + ')'; + } + } else { + if (m[0] === 1 && m[1] === 0 && m[2] === 0 && m[3] === 1) { + return 'translate(' + pf(m[4]) + ' ' + pf(m[5]) + ')'; + } + } + return 'matrix(' + pf(m[0]) + ' ' + pf(m[1]) + ' ' + pf(m[2]) + ' ' + + pf(m[3]) + ' ' + pf(m[4]) + ' ' + pf(m[5]) + ')'; + } + + function SVGGraphics(commonObjs, objs) { + this.current = new SVGExtraState(); + this.transformMatrix = IDENTITY_MATRIX; // Graphics state matrix + this.transformStack = []; + this.extraStack = []; + this.commonObjs = commonObjs; + this.objs = objs; + this.pendingEOFill = false; + + this.embedFonts = false; + this.embeddedFonts = {}; + this.cssStyle = null; + } + + var NS = 'http://www.w3.org/2000/svg'; + var XML_NS = 'http://www.w3.org/XML/1998/namespace'; + var XLINK_NS = 'http://www.w3.org/1999/xlink'; + var LINE_CAP_STYLES = ['butt', 'round', 'square']; + var LINE_JOIN_STYLES = ['miter', 'round', 'bevel']; + var clipCount = 0; + var maskCount = 0; + + SVGGraphics.prototype = { + save: function SVGGraphics_save() { + this.transformStack.push(this.transformMatrix); + var old = this.current; + this.extraStack.push(old); + this.current = old.clone(); + }, + + restore: function SVGGraphics_restore() { + this.transformMatrix = this.transformStack.pop(); + this.current = this.extraStack.pop(); + + this.tgrp = document.createElementNS(NS, 'svg:g'); + this.tgrp.setAttributeNS(null, 'transform', pm(this.transformMatrix)); + this.pgrp.appendChild(this.tgrp); + }, + + group: function SVGGraphics_group(items) { + this.save(); + this.executeOpTree(items); + this.restore(); + }, + + loadDependencies: function SVGGraphics_loadDependencies(operatorList) { + var fnArray = operatorList.fnArray; + var fnArrayLen = fnArray.length; + var argsArray = operatorList.argsArray; + + var self = this; + for (var i = 0; i < fnArrayLen; i++) { + if (OPS.dependency === fnArray[i]) { + var deps = argsArray[i]; + for (var n = 0, nn = deps.length; n < nn; n++) { + var obj = deps[n]; + var common = obj.substring(0, 2) === 'g_'; + var promise; + if (common) { + promise = new Promise(function(resolve) { + self.commonObjs.get(obj, resolve); + }); + } else { + promise = new Promise(function(resolve) { + self.objs.get(obj, resolve); + }); + } + this.current.dependencies.push(promise); + } + } + } + return Promise.all(this.current.dependencies); + }, + + transform: function SVGGraphics_transform(a, b, c, d, e, f) { + var transformMatrix = [a, b, c, d, e, f]; + this.transformMatrix = PDFJS.Util.transform(this.transformMatrix, + transformMatrix); + + this.tgrp = document.createElementNS(NS, 'svg:g'); + this.tgrp.setAttributeNS(null, 'transform', pm(this.transformMatrix)); + }, + + getSVG: function SVGGraphics_getSVG(operatorList, viewport) { + this.svg = createScratchSVG(viewport.width, viewport.height); + this.viewport = viewport; + + return this.loadDependencies(operatorList).then(function () { + this.transformMatrix = IDENTITY_MATRIX; + this.pgrp = document.createElementNS(NS, 'svg:g'); // Parent group + this.pgrp.setAttributeNS(null, 'transform', pm(viewport.transform)); + this.tgrp = document.createElementNS(NS, 'svg:g'); // Transform group + this.tgrp.setAttributeNS(null, 'transform', pm(this.transformMatrix)); + this.defs = document.createElementNS(NS, 'svg:defs'); + this.pgrp.appendChild(this.defs); + this.pgrp.appendChild(this.tgrp); + this.svg.appendChild(this.pgrp); + var opTree = this.convertOpList(operatorList); + this.executeOpTree(opTree); + return this.svg; + }.bind(this)); + }, + + convertOpList: function SVGGraphics_convertOpList(operatorList) { + var argsArray = operatorList.argsArray; + var fnArray = operatorList.fnArray; + var fnArrayLen = fnArray.length; + var REVOPS = []; + var opList = []; + + for (var op in OPS) { + REVOPS[OPS[op]] = op; + } + + for (var x = 0; x < fnArrayLen; x++) { + var fnId = fnArray[x]; + opList.push({'fnId' : fnId, 'fn': REVOPS[fnId], 'args': argsArray[x]}); + } + return opListToTree(opList); + }, + + executeOpTree: function SVGGraphics_executeOpTree(opTree) { + var opTreeLen = opTree.length; + for(var x = 0; x < opTreeLen; x++) { + var fn = opTree[x].fn; + var fnId = opTree[x].fnId; + var args = opTree[x].args; + + switch (fnId | 0) { + case OPS.beginText: + this.beginText(); + break; + case OPS.setLeading: + this.setLeading(args); + break; + case OPS.setLeadingMoveText: + this.setLeadingMoveText(args[0], args[1]); + break; + case OPS.setFont: + this.setFont(args); + break; + case OPS.showText: + this.showText(args[0]); + break; + case OPS.showSpacedText: + this.showText(args[0]); + break; + case OPS.endText: + this.endText(); + break; + case OPS.moveText: + this.moveText(args[0], args[1]); + break; + case OPS.setCharSpacing: + this.setCharSpacing(args[0]); + break; + case OPS.setWordSpacing: + this.setWordSpacing(args[0]); + break; + case OPS.setHScale: + this.setHScale(args[0]); + break; + case OPS.setTextMatrix: + this.setTextMatrix(args[0], args[1], args[2], + args[3], args[4], args[5]); + break; + case OPS.setLineWidth: + this.setLineWidth(args[0]); + break; + case OPS.setLineJoin: + this.setLineJoin(args[0]); + break; + case OPS.setLineCap: + this.setLineCap(args[0]); + break; + case OPS.setMiterLimit: + this.setMiterLimit(args[0]); + break; + case OPS.setFillRGBColor: + this.setFillRGBColor(args[0], args[1], args[2]); + break; + case OPS.setStrokeRGBColor: + this.setStrokeRGBColor(args[0], args[1], args[2]); + break; + case OPS.setDash: + this.setDash(args[0], args[1]); + break; + case OPS.setGState: + this.setGState(args[0]); + break; + case OPS.fill: + this.fill(); + break; + case OPS.eoFill: + this.eoFill(); + break; + case OPS.stroke: + this.stroke(); + break; + case OPS.fillStroke: + this.fillStroke(); + break; + case OPS.eoFillStroke: + this.eoFillStroke(); + break; + case OPS.clip: + this.clip('nonzero'); + break; + case OPS.eoClip: + this.clip('evenodd'); + break; + case OPS.paintSolidColorImageMask: + this.paintSolidColorImageMask(); + break; + case OPS.paintJpegXObject: + this.paintJpegXObject(args[0], args[1], args[2]); + break; + case OPS.paintImageXObject: + this.paintImageXObject(args[0]); + break; + case OPS.paintInlineImageXObject: + this.paintInlineImageXObject(args[0]); + break; + case OPS.paintImageMaskXObject: + this.paintImageMaskXObject(args[0]); + break; + case OPS.paintFormXObjectBegin: + this.paintFormXObjectBegin(args[0], args[1]); + break; + case OPS.paintFormXObjectEnd: + this.paintFormXObjectEnd(); + break; + case OPS.closePath: + this.closePath(); + break; + case OPS.closeStroke: + this.closeStroke(); + break; + case OPS.closeFillStroke: + this.closeFillStroke(); + break; + case OPS.nextLine: + this.nextLine(); + break; + case OPS.transform: + this.transform(args[0], args[1], args[2], args[3], + args[4], args[5]); + break; + case OPS.constructPath: + this.constructPath(args[0], args[1]); + break; + case OPS.endPath: + this.endPath(); + break; + case 92: + this.group(opTree[x].items); + break; + default: + warn('Unimplemented method '+ fn); + break; + } + } + }, + + setWordSpacing: function SVGGraphics_setWordSpacing(wordSpacing) { + this.current.wordSpacing = wordSpacing; + }, + + setCharSpacing: function SVGGraphics_setCharSpacing(charSpacing) { + this.current.charSpacing = charSpacing; + }, + + nextLine: function SVGGraphics_nextLine() { + this.moveText(0, this.current.leading); + }, + + setTextMatrix: function SVGGraphics_setTextMatrix(a, b, c, d, e, f) { + var current = this.current; + this.current.textMatrix = this.current.lineMatrix = [a, b, c, d, e, f]; + + this.current.x = this.current.lineX = 0; + this.current.y = this.current.lineY = 0; + + current.xcoords = []; + current.tspan = document.createElementNS(NS, 'svg:tspan'); + current.tspan.setAttributeNS(null, 'font-family', current.fontFamily); + current.tspan.setAttributeNS(null, 'font-size', + pf(current.fontSize) + 'px'); + current.tspan.setAttributeNS(null, 'y', pf(-current.y)); + + current.txtElement = document.createElementNS(NS, 'svg:text'); + current.txtElement.appendChild(current.tspan); + }, + + beginText: function SVGGraphics_beginText() { + this.current.x = this.current.lineX = 0; + this.current.y = this.current.lineY = 0; + this.current.textMatrix = IDENTITY_MATRIX; + this.current.lineMatrix = IDENTITY_MATRIX; + this.current.tspan = document.createElementNS(NS, 'svg:tspan'); + this.current.txtElement = document.createElementNS(NS, 'svg:text'); + this.current.txtgrp = document.createElementNS(NS, 'svg:g'); + this.current.xcoords = []; + }, + + moveText: function SVGGraphics_moveText(x, y) { + var current = this.current; + this.current.x = this.current.lineX += x; + this.current.y = this.current.lineY += y; + + current.xcoords = []; + current.tspan = document.createElementNS(NS, 'svg:tspan'); + current.tspan.setAttributeNS(null, 'font-family', current.fontFamily); + current.tspan.setAttributeNS(null, 'font-size', + pf(current.fontSize) + 'px'); + current.tspan.setAttributeNS(null, 'y', pf(-current.y)); + }, + + showText: function SVGGraphics_showText(glyphs) { + var current = this.current; + var font = current.font; + var fontSize = current.fontSize; + + if (fontSize === 0) { + return; + } + + var charSpacing = current.charSpacing; + var wordSpacing = current.wordSpacing; + var fontDirection = current.fontDirection; + var textHScale = current.textHScale * fontDirection; + var glyphsLength = glyphs.length; + var vertical = font.vertical; + var widthAdvanceScale = fontSize * current.fontMatrix[0]; + + var x = 0, i; + for (i = 0; i < glyphsLength; ++i) { + var glyph = glyphs[i]; + if (glyph === null) { + // word break + x += fontDirection * wordSpacing; + continue; + } else if (isNum(glyph)) { + x += -glyph * fontSize * 0.001; + continue; + } + current.xcoords.push(current.x + x * textHScale); + + var width = glyph.width; + var character = glyph.fontChar; + var charWidth = width * widthAdvanceScale + charSpacing * fontDirection; + x += charWidth; + + current.tspan.textContent += character; + } + if (vertical) { + current.y -= x * textHScale; + } else { + current.x += x * textHScale; + } + + current.tspan.setAttributeNS(null, 'x', + current.xcoords.map(pf).join(' ')); + current.tspan.setAttributeNS(null, 'y', pf(-current.y)); + current.tspan.setAttributeNS(null, 'font-family', current.fontFamily); + current.tspan.setAttributeNS(null, 'font-size', + pf(current.fontSize) + 'px'); + if (current.fontStyle !== SVG_DEFAULTS.fontStyle) { + current.tspan.setAttributeNS(null, 'font-style', current.fontStyle); + } + if (current.fontWeight !== SVG_DEFAULTS.fontWeight) { + current.tspan.setAttributeNS(null, 'font-weight', current.fontWeight); + } + if (current.fillColor !== SVG_DEFAULTS.fillColor) { + current.tspan.setAttributeNS(null, 'fill', current.fillColor); + } + + current.txtElement.setAttributeNS(null, 'transform', + pm(current.textMatrix) + + ' scale(1, -1)' ); + current.txtElement.setAttributeNS(XML_NS, 'xml:space', 'preserve'); + current.txtElement.appendChild(current.tspan); + current.txtgrp.appendChild(current.txtElement); + + this.tgrp.appendChild(current.txtElement); + + }, + + setLeadingMoveText: function SVGGraphics_setLeadingMoveText(x, y) { + this.setLeading(-y); + this.moveText(x, y); + }, + + addFontStyle: function SVGGraphics_addFontStyle(fontObj) { + if (!this.cssStyle) { + this.cssStyle = document.createElementNS(NS, 'svg:style'); + this.cssStyle.setAttributeNS(null, 'type', 'text/css'); + this.defs.appendChild(this.cssStyle); + } + + var url = PDFJS.createObjectURL(fontObj.data, fontObj.mimetype); + this.cssStyle.textContent += + '@font-face { font-family: "' + fontObj.loadedName + '";' + + ' src: url(' + url + '); }\n'; + }, + + setFont: function SVGGraphics_setFont(details) { + var current = this.current; + var fontObj = this.commonObjs.get(details[0]); + var size = details[1]; + this.current.font = fontObj; + + if (this.embedFonts && fontObj.data && + !this.embeddedFonts[fontObj.loadedName]) { + this.addFontStyle(fontObj); + this.embeddedFonts[fontObj.loadedName] = fontObj; + } + + current.fontMatrix = (fontObj.fontMatrix ? + fontObj.fontMatrix : FONT_IDENTITY_MATRIX); + + var bold = fontObj.black ? (fontObj.bold ? 'bolder' : 'bold') : + (fontObj.bold ? 'bold' : 'normal'); + var italic = fontObj.italic ? 'italic' : 'normal'; + + if (size < 0) { + size = -size; + current.fontDirection = -1; + } else { + current.fontDirection = 1; + } + current.fontSize = size; + current.fontFamily = fontObj.loadedName; + current.fontWeight = bold; + current.fontStyle = italic; + + current.tspan = document.createElementNS(NS, 'svg:tspan'); + current.tspan.setAttributeNS(null, 'y', pf(-current.y)); + current.xcoords = []; + }, + + endText: function SVGGraphics_endText() { + if (this.current.pendingClip) { + this.cgrp.appendChild(this.tgrp); + this.pgrp.appendChild(this.cgrp); + } else { + this.pgrp.appendChild(this.tgrp); + } + this.tgrp = document.createElementNS(NS, 'svg:g'); + this.tgrp.setAttributeNS(null, 'transform', pm(this.transformMatrix)); + }, + + // Path properties + setLineWidth: function SVGGraphics_setLineWidth(width) { + this.current.lineWidth = width; + }, + setLineCap: function SVGGraphics_setLineCap(style) { + this.current.lineCap = LINE_CAP_STYLES[style]; + }, + setLineJoin: function SVGGraphics_setLineJoin(style) { + this.current.lineJoin = LINE_JOIN_STYLES[style]; + }, + setMiterLimit: function SVGGraphics_setMiterLimit(limit) { + this.current.miterLimit = limit; + }, + setStrokeRGBColor: function SVGGraphics_setStrokeRGBColor(r, g, b) { + var color = Util.makeCssRgb(r, g, b); + this.current.strokeColor = color; + }, + setFillRGBColor: function SVGGraphics_setFillRGBColor(r, g, b) { + var color = Util.makeCssRgb(r, g, b); + this.current.fillColor = color; + this.current.tspan = document.createElementNS(NS, 'svg:tspan'); + this.current.xcoords = []; + }, + setDash: function SVGGraphics_setDash(dashArray, dashPhase) { + this.current.dashArray = dashArray; + this.current.dashPhase = dashPhase; + }, + + constructPath: function SVGGraphics_constructPath(ops, args) { + var current = this.current; + var x = current.x, y = current.y; + current.path = document.createElementNS(NS, 'svg:path'); + var d = []; + var opLength = ops.length; + + for (var i = 0, j = 0; i < opLength; i++) { + switch (ops[i] | 0) { + case OPS.rectangle: + x = args[j++]; + y = args[j++]; + var width = args[j++]; + var height = args[j++]; + var xw = x + width; + var yh = y + height; + d.push('M', pf(x), pf(y), 'L', pf(xw) , pf(y), 'L', pf(xw), pf(yh), + 'L', pf(x), pf(yh), 'Z'); + break; + case OPS.moveTo: + x = args[j++]; + y = args[j++]; + d.push('M', pf(x), pf(y)); + break; + case OPS.lineTo: + x = args[j++]; + y = args[j++]; + d.push('L', pf(x) , pf(y)); + break; + case OPS.curveTo: + x = args[j + 4]; + y = args[j + 5]; + d.push('C', pf(args[j]), pf(args[j + 1]), pf(args[j + 2]), + pf(args[j + 3]), pf(x), pf(y)); + j += 6; + break; + case OPS.curveTo2: + x = args[j + 2]; + y = args[j + 3]; + d.push('C', pf(x), pf(y), pf(args[j]), pf(args[j + 1]), + pf(args[j + 2]), pf(args[j + 3])); + j += 4; + break; + case OPS.curveTo3: + x = args[j + 2]; + y = args[j + 3]; + d.push('C', pf(args[j]), pf(args[j + 1]), pf(x), pf(y), + pf(x), pf(y)); + j += 4; + break; + case OPS.closePath: + d.push('Z'); + break; + } + } + current.path.setAttributeNS(null, 'd', d.join(' ')); + current.path.setAttributeNS(null, 'stroke-miterlimit', + pf(current.miterLimit)); + current.path.setAttributeNS(null, 'stroke-linecap', current.lineCap); + current.path.setAttributeNS(null, 'stroke-linejoin', current.lineJoin); + current.path.setAttributeNS(null, 'stroke-width', + pf(current.lineWidth) + 'px'); + current.path.setAttributeNS(null, 'stroke-dasharray', + current.dashArray.map(pf).join(' ')); + current.path.setAttributeNS(null, 'stroke-dashoffset', + pf(current.dashPhase) + 'px'); + current.path.setAttributeNS(null, 'fill', 'none'); + + this.tgrp.appendChild(current.path); + if (current.pendingClip) { + this.cgrp.appendChild(this.tgrp); + this.pgrp.appendChild(this.cgrp); + } else { + this.pgrp.appendChild(this.tgrp); + } + // Saving a reference in current.element so that it can be addressed + // in 'fill' and 'stroke' + current.element = current.path; + current.setCurrentPoint(x, y); + }, + + endPath: function SVGGraphics_endPath() { + var current = this.current; + if (current.pendingClip) { + this.cgrp.appendChild(this.tgrp); + this.pgrp.appendChild(this.cgrp); + } else { + this.pgrp.appendChild(this.tgrp); + } + this.tgrp = document.createElementNS(NS, 'svg:g'); + this.tgrp.setAttributeNS(null, 'transform', pm(this.transformMatrix)); + }, + + clip: function SVGGraphics_clip(type) { + var current = this.current; + // Add current path to clipping path + current.clipId = 'clippath' + clipCount; + clipCount++; + this.clippath = document.createElementNS(NS, 'svg:clipPath'); + this.clippath.setAttributeNS(null, 'id', current.clipId); + var clipElement = current.element.cloneNode(); + if (type === 'evenodd') { + clipElement.setAttributeNS(null, 'clip-rule', 'evenodd'); + } else { + clipElement.setAttributeNS(null, 'clip-rule', 'nonzero'); + } + this.clippath.setAttributeNS(null, 'transform', pm(this.transformMatrix)); + this.clippath.appendChild(clipElement); + this.defs.appendChild(this.clippath); + + // Create a new group with that attribute + current.pendingClip = true; + this.cgrp = document.createElementNS(NS, 'svg:g'); + this.cgrp.setAttributeNS(null, 'clip-path', + 'url(#' + current.clipId + ')'); + this.pgrp.appendChild(this.cgrp); + }, + + closePath: function SVGGraphics_closePath() { + var current = this.current; + var d = current.path.getAttributeNS(null, 'd'); + d += 'Z'; + current.path.setAttributeNS(null, 'd', d); + }, + + setLeading: function SVGGraphics_setLeading(leading) { + this.current.leading = -leading; + }, + + setTextRise: function SVGGraphics_setTextRise(textRise) { + this.current.textRise = textRise; + }, + + setHScale: function SVGGraphics_setHScale(scale) { + this.current.textHScale = scale / 100; + }, + + setGState: function SVGGraphics_setGState(states) { + for (var i = 0, ii = states.length; i < ii; i++) { + var state = states[i]; + var key = state[0]; + var value = state[1]; + + switch (key) { + case 'LW': + this.setLineWidth(value); + break; + case 'LC': + this.setLineCap(value); + break; + case 'LJ': + this.setLineJoin(value); + break; + case 'ML': + this.setMiterLimit(value); + break; + case 'D': + this.setDash(value[0], value[1]); + break; + case 'RI': + break; + case 'FL': + break; + case 'Font': + this.setFont(value); + break; + case 'CA': + break; + case 'ca': + break; + case 'BM': + break; + case 'SMask': + break; + } + } + }, + + fill: function SVGGraphics_fill() { + var current = this.current; + current.element.setAttributeNS(null, 'fill', current.fillColor); + }, + + stroke: function SVGGraphics_stroke() { + var current = this.current; + current.element.setAttributeNS(null, 'stroke', current.strokeColor); + current.element.setAttributeNS(null, 'fill', 'none'); + }, + + eoFill: function SVGGraphics_eoFill() { + var current = this.current; + current.element.setAttributeNS(null, 'fill', current.fillColor); + current.element.setAttributeNS(null, 'fill-rule', 'evenodd'); + }, + + fillStroke: function SVGGraphics_fillStroke() { + // Order is important since stroke wants fill to be none. + // First stroke, then if fill needed, it will be overwritten. + this.stroke(); + this.fill(); + }, + + eoFillStroke: function SVGGraphics_eoFillStroke() { + this.current.element.setAttributeNS(null, 'fill-rule', 'evenodd'); + this.fillStroke(); + }, + + closeStroke: function SVGGraphics_closeStroke() { + this.closePath(); + this.stroke(); + }, + + closeFillStroke: function SVGGraphics_closeFillStroke() { + this.closePath(); + this.fillStroke(); + }, + + paintSolidColorImageMask: + function SVGGraphics_paintSolidColorImageMask() { + var current = this.current; + var rect = document.createElementNS(NS, 'svg:rect'); + rect.setAttributeNS(null, 'x', '0'); + rect.setAttributeNS(null, 'y', '0'); + rect.setAttributeNS(null, 'width', '1px'); + rect.setAttributeNS(null, 'height', '1px'); + rect.setAttributeNS(null, 'fill', current.fillColor); + this.tgrp.appendChild(rect); + }, + + paintJpegXObject: function SVGGraphics_paintJpegXObject(objId, w, h) { + var current = this.current; + var imgObj = this.objs.get(objId); + var imgEl = document.createElementNS(NS, 'svg:image'); + imgEl.setAttributeNS(XLINK_NS, 'xlink:href', imgObj.src); + imgEl.setAttributeNS(null, 'width', imgObj.width + 'px'); + imgEl.setAttributeNS(null, 'height', imgObj.height + 'px'); + imgEl.setAttributeNS(null, 'x', '0'); + imgEl.setAttributeNS(null, 'y', pf(-h)); + imgEl.setAttributeNS(null, 'transform', + 'scale(' + pf(1 / w) + ' ' + pf(-1 / h) + ')'); + + this.tgrp.appendChild(imgEl); + if (current.pendingClip) { + this.cgrp.appendChild(this.tgrp); + this.pgrp.appendChild(this.cgrp); + } else { + this.pgrp.appendChild(this.tgrp); + } + }, + + paintImageXObject: function SVGGraphics_paintImageXObject(objId) { + var imgData = this.objs.get(objId); + if (!imgData) { + warn('Dependent image isn\'t ready yet'); + return; + } + this.paintInlineImageXObject(imgData); + }, + + paintInlineImageXObject: + function SVGGraphics_paintInlineImageXObject(imgData, mask) { + var current = this.current; + var width = imgData.width; + var height = imgData.height; + + var imgSrc = convertImgDataToPng(imgData); + var cliprect = document.createElementNS(NS, 'svg:rect'); + cliprect.setAttributeNS(null, 'x', '0'); + cliprect.setAttributeNS(null, 'y', '0'); + cliprect.setAttributeNS(null, 'width', pf(width)); + cliprect.setAttributeNS(null, 'height', pf(height)); + current.element = cliprect; + this.clip('nonzero'); + var imgEl = document.createElementNS(NS, 'svg:image'); + imgEl.setAttributeNS(XLINK_NS, 'xlink:href', imgSrc); + imgEl.setAttributeNS(null, 'x', '0'); + imgEl.setAttributeNS(null, 'y', pf(-height)); + imgEl.setAttributeNS(null, 'width', pf(width) + 'px'); + imgEl.setAttributeNS(null, 'height', pf(height) + 'px'); + imgEl.setAttributeNS(null, 'transform', + 'scale(' + pf(1 / width) + ' ' + + pf(-1 / height) + ')'); + if (mask) { + mask.appendChild(imgEl); + } else { + this.tgrp.appendChild(imgEl); + } + if (current.pendingClip) { + this.cgrp.appendChild(this.tgrp); + this.pgrp.appendChild(this.cgrp); + } else { + this.pgrp.appendChild(this.tgrp); + } + }, + + paintImageMaskXObject: + function SVGGraphics_paintImageMaskXObject(imgData) { + var current = this.current; + var width = imgData.width; + var height = imgData.height; + var fillColor = current.fillColor; + + current.maskId = 'mask' + maskCount++; + var mask = document.createElementNS(NS, 'svg:mask'); + mask.setAttributeNS(null, 'id', current.maskId); + + var rect = document.createElementNS(NS, 'svg:rect'); + rect.setAttributeNS(null, 'x', '0'); + rect.setAttributeNS(null, 'y', '0'); + rect.setAttributeNS(null, 'width', pf(width)); + rect.setAttributeNS(null, 'height', pf(height)); + rect.setAttributeNS(null, 'fill', fillColor); + rect.setAttributeNS(null, 'mask', 'url(#' + current.maskId +')'); + this.defs.appendChild(mask); + this.tgrp.appendChild(rect); + + this.paintInlineImageXObject(imgData, mask); + }, + + paintFormXObjectBegin: + function SVGGraphics_paintFormXObjectBegin(matrix, bbox) { + this.save(); + + if (isArray(matrix) && matrix.length === 6) { + this.transform(matrix[0], matrix[1], matrix[2], + matrix[3], matrix[4], matrix[5]); + } + + if (isArray(bbox) && bbox.length === 4) { + var width = bbox[2] - bbox[0]; + var height = bbox[3] - bbox[1]; + + var cliprect = document.createElementNS(NS, 'svg:rect'); + cliprect.setAttributeNS(null, 'x', bbox[0]); + cliprect.setAttributeNS(null, 'y', bbox[1]); + cliprect.setAttributeNS(null, 'width', pf(width)); + cliprect.setAttributeNS(null, 'height', pf(height)); + this.current.element = cliprect; + this.clip('nonzero'); + this.endPath(); + } + }, + + paintFormXObjectEnd: + function SVGGraphics_paintFormXObjectEnd() { + this.restore(); + } + }; + return SVGGraphics; +})(); + +PDFJS.SVGGraphics = SVGGraphics; +//#endif + + +}).call((typeof window === 'undefined') ? this : window); + +if (!PDFJS.workerSrc && typeof document !== 'undefined') { + // workerSrc is not set -- using last script url to define default location + PDFJS.workerSrc = (function () { + 'use strict'; + var scriptTagContainer = document.body || + document.getElementsByTagName('head')[0]; + var pdfjsSrc = scriptTagContainer.lastChild.src; + return pdfjsSrc && pdfjsSrc.replace(/\.js$/i, '.worker.js'); + })(); +} + diff --git a/muk_web_preview/static/lib/ViewerJS/pdf.worker.js b/muk_web_preview/static/lib/ViewerJS/pdf.worker.js new file mode 100644 index 0000000..c17192e --- /dev/null +++ b/muk_web_preview/static/lib/ViewerJS/pdf.worker.js @@ -0,0 +1,39353 @@ +/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ +/* Copyright 2012 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*jshint globalstrict: false */ +/* globals PDFJS */ + +// Initializing PDFJS global object (if still undefined) +if (typeof PDFJS === 'undefined') { + (typeof window !== 'undefined' ? window : this).PDFJS = {}; +} + +PDFJS.version = '1.1.114'; +PDFJS.build = '3fd44fd'; + +(function pdfjsWrapper() { + // Use strict in our context only - users might not want it + 'use strict'; + +/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ +/* Copyright 2012 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* globals Cmd, ColorSpace, Dict, MozBlobBuilder, Name, PDFJS, Ref, URL, + Promise */ + +'use strict'; + +var globalScope = (typeof window === 'undefined') ? this : window; + +var isWorker = (typeof window === 'undefined'); + +var FONT_IDENTITY_MATRIX = [0.001, 0, 0, 0.001, 0, 0]; + +var TextRenderingMode = { + FILL: 0, + STROKE: 1, + FILL_STROKE: 2, + INVISIBLE: 3, + FILL_ADD_TO_PATH: 4, + STROKE_ADD_TO_PATH: 5, + FILL_STROKE_ADD_TO_PATH: 6, + ADD_TO_PATH: 7, + FILL_STROKE_MASK: 3, + ADD_TO_PATH_FLAG: 4 +}; + +var ImageKind = { + GRAYSCALE_1BPP: 1, + RGB_24BPP: 2, + RGBA_32BPP: 3 +}; + +var AnnotationType = { + WIDGET: 1, + TEXT: 2, + LINK: 3 +}; + +var StreamType = { + UNKNOWN: 0, + FLATE: 1, + LZW: 2, + DCT: 3, + JPX: 4, + JBIG: 5, + A85: 6, + AHX: 7, + CCF: 8, + RL: 9 +}; + +var FontType = { + UNKNOWN: 0, + TYPE1: 1, + TYPE1C: 2, + CIDFONTTYPE0: 3, + CIDFONTTYPE0C: 4, + TRUETYPE: 5, + CIDFONTTYPE2: 6, + TYPE3: 7, + OPENTYPE: 8, + TYPE0: 9, + MMTYPE1: 10 +}; + +// The global PDFJS object exposes the API +// In production, it will be declared outside a global wrapper +// In development, it will be declared here +if (!globalScope.PDFJS) { + globalScope.PDFJS = {}; +} + +globalScope.PDFJS.pdfBug = false; + +PDFJS.VERBOSITY_LEVELS = { + errors: 0, + warnings: 1, + infos: 5 +}; + +// All the possible operations for an operator list. +var OPS = PDFJS.OPS = { + // Intentionally start from 1 so it is easy to spot bad operators that will be + // 0's. + dependency: 1, + setLineWidth: 2, + setLineCap: 3, + setLineJoin: 4, + setMiterLimit: 5, + setDash: 6, + setRenderingIntent: 7, + setFlatness: 8, + setGState: 9, + save: 10, + restore: 11, + transform: 12, + moveTo: 13, + lineTo: 14, + curveTo: 15, + curveTo2: 16, + curveTo3: 17, + closePath: 18, + rectangle: 19, + stroke: 20, + closeStroke: 21, + fill: 22, + eoFill: 23, + fillStroke: 24, + eoFillStroke: 25, + closeFillStroke: 26, + closeEOFillStroke: 27, + endPath: 28, + clip: 29, + eoClip: 30, + beginText: 31, + endText: 32, + setCharSpacing: 33, + setWordSpacing: 34, + setHScale: 35, + setLeading: 36, + setFont: 37, + setTextRenderingMode: 38, + setTextRise: 39, + moveText: 40, + setLeadingMoveText: 41, + setTextMatrix: 42, + nextLine: 43, + showText: 44, + showSpacedText: 45, + nextLineShowText: 46, + nextLineSetSpacingShowText: 47, + setCharWidth: 48, + setCharWidthAndBounds: 49, + setStrokeColorSpace: 50, + setFillColorSpace: 51, + setStrokeColor: 52, + setStrokeColorN: 53, + setFillColor: 54, + setFillColorN: 55, + setStrokeGray: 56, + setFillGray: 57, + setStrokeRGBColor: 58, + setFillRGBColor: 59, + setStrokeCMYKColor: 60, + setFillCMYKColor: 61, + shadingFill: 62, + beginInlineImage: 63, + beginImageData: 64, + endInlineImage: 65, + paintXObject: 66, + markPoint: 67, + markPointProps: 68, + beginMarkedContent: 69, + beginMarkedContentProps: 70, + endMarkedContent: 71, + beginCompat: 72, + endCompat: 73, + paintFormXObjectBegin: 74, + paintFormXObjectEnd: 75, + beginGroup: 76, + endGroup: 77, + beginAnnotations: 78, + endAnnotations: 79, + beginAnnotation: 80, + endAnnotation: 81, + paintJpegXObject: 82, + paintImageMaskXObject: 83, + paintImageMaskXObjectGroup: 84, + paintImageXObject: 85, + paintInlineImageXObject: 86, + paintInlineImageXObjectGroup: 87, + paintImageXObjectRepeat: 88, + paintImageMaskXObjectRepeat: 89, + paintSolidColorImageMask: 90, + constructPath: 91 +}; + +// A notice for devs. These are good for things that are helpful to devs, such +// as warning that Workers were disabled, which is important to devs but not +// end users. +function info(msg) { + if (PDFJS.verbosity >= PDFJS.VERBOSITY_LEVELS.infos) { + console.log('Info: ' + msg); + } +} + +// Non-fatal warnings. +function warn(msg) { + if (PDFJS.verbosity >= PDFJS.VERBOSITY_LEVELS.warnings) { + console.log('Warning: ' + msg); + } +} + +// Fatal errors that should trigger the fallback UI and halt execution by +// throwing an exception. +function error(msg) { + if (PDFJS.verbosity >= PDFJS.VERBOSITY_LEVELS.errors) { + console.log('Error: ' + msg); + console.log(backtrace()); + } + UnsupportedManager.notify(UNSUPPORTED_FEATURES.unknown); + throw new Error(msg); +} + +function backtrace() { + try { + throw new Error(); + } catch (e) { + return e.stack ? e.stack.split('\n').slice(2).join('\n') : ''; + } +} + +function assert(cond, msg) { + if (!cond) { + error(msg); + } +} + +var UNSUPPORTED_FEATURES = PDFJS.UNSUPPORTED_FEATURES = { + unknown: 'unknown', + forms: 'forms', + javaScript: 'javaScript', + smask: 'smask', + shadingPattern: 'shadingPattern', + font: 'font' +}; + +var UnsupportedManager = PDFJS.UnsupportedManager = + (function UnsupportedManagerClosure() { + var listeners = []; + return { + listen: function (cb) { + listeners.push(cb); + }, + notify: function (featureId) { + warn('Unsupported feature "' + featureId + '"'); + for (var i = 0, ii = listeners.length; i < ii; i++) { + listeners[i](featureId); + } + } + }; +})(); + +// Combines two URLs. The baseUrl shall be absolute URL. If the url is an +// absolute URL, it will be returned as is. +function combineUrl(baseUrl, url) { + if (!url) { + return baseUrl; + } + if (/^[a-z][a-z0-9+\-.]*:/i.test(url)) { + return url; + } + var i; + if (url.charAt(0) === '/') { + // absolute path + i = baseUrl.indexOf('://'); + if (url.charAt(1) === '/') { + ++i; + } else { + i = baseUrl.indexOf('/', i + 3); + } + return baseUrl.substring(0, i) + url; + } else { + // relative path + var pathLength = baseUrl.length; + i = baseUrl.lastIndexOf('#'); + pathLength = i >= 0 ? i : pathLength; + i = baseUrl.lastIndexOf('?', pathLength); + pathLength = i >= 0 ? i : pathLength; + var prefixLength = baseUrl.lastIndexOf('/', pathLength); + return baseUrl.substring(0, prefixLength + 1) + url; + } +} + +// Validates if URL is safe and allowed, e.g. to avoid XSS. +function isValidUrl(url, allowRelative) { + if (!url) { + return false; + } + // RFC 3986 (http://tools.ietf.org/html/rfc3986#section-3.1) + // scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) + var protocol = /^[a-z][a-z0-9+\-.]*(?=:)/i.exec(url); + if (!protocol) { + return allowRelative; + } + protocol = protocol[0].toLowerCase(); + switch (protocol) { + case 'http': + case 'https': + case 'ftp': + case 'mailto': + case 'tel': + return true; + default: + return false; + } +} +PDFJS.isValidUrl = isValidUrl; + +function shadow(obj, prop, value) { + Object.defineProperty(obj, prop, { value: value, + enumerable: true, + configurable: true, + writable: false }); + return value; +} +PDFJS.shadow = shadow; + +var PasswordResponses = PDFJS.PasswordResponses = { + NEED_PASSWORD: 1, + INCORRECT_PASSWORD: 2 +}; + +var PasswordException = (function PasswordExceptionClosure() { + function PasswordException(msg, code) { + this.name = 'PasswordException'; + this.message = msg; + this.code = code; + } + + PasswordException.prototype = new Error(); + PasswordException.constructor = PasswordException; + + return PasswordException; +})(); +PDFJS.PasswordException = PasswordException; + +var UnknownErrorException = (function UnknownErrorExceptionClosure() { + function UnknownErrorException(msg, details) { + this.name = 'UnknownErrorException'; + this.message = msg; + this.details = details; + } + + UnknownErrorException.prototype = new Error(); + UnknownErrorException.constructor = UnknownErrorException; + + return UnknownErrorException; +})(); +PDFJS.UnknownErrorException = UnknownErrorException; + +var InvalidPDFException = (function InvalidPDFExceptionClosure() { + function InvalidPDFException(msg) { + this.name = 'InvalidPDFException'; + this.message = msg; + } + + InvalidPDFException.prototype = new Error(); + InvalidPDFException.constructor = InvalidPDFException; + + return InvalidPDFException; +})(); +PDFJS.InvalidPDFException = InvalidPDFException; + +var MissingPDFException = (function MissingPDFExceptionClosure() { + function MissingPDFException(msg) { + this.name = 'MissingPDFException'; + this.message = msg; + } + + MissingPDFException.prototype = new Error(); + MissingPDFException.constructor = MissingPDFException; + + return MissingPDFException; +})(); +PDFJS.MissingPDFException = MissingPDFException; + +var UnexpectedResponseException = + (function UnexpectedResponseExceptionClosure() { + function UnexpectedResponseException(msg, status) { + this.name = 'UnexpectedResponseException'; + this.message = msg; + this.status = status; + } + + UnexpectedResponseException.prototype = new Error(); + UnexpectedResponseException.constructor = UnexpectedResponseException; + + return UnexpectedResponseException; +})(); +PDFJS.UnexpectedResponseException = UnexpectedResponseException; + +var NotImplementedException = (function NotImplementedExceptionClosure() { + function NotImplementedException(msg) { + this.message = msg; + } + + NotImplementedException.prototype = new Error(); + NotImplementedException.prototype.name = 'NotImplementedException'; + NotImplementedException.constructor = NotImplementedException; + + return NotImplementedException; +})(); + +var MissingDataException = (function MissingDataExceptionClosure() { + function MissingDataException(begin, end) { + this.begin = begin; + this.end = end; + this.message = 'Missing data [' + begin + ', ' + end + ')'; + } + + MissingDataException.prototype = new Error(); + MissingDataException.prototype.name = 'MissingDataException'; + MissingDataException.constructor = MissingDataException; + + return MissingDataException; +})(); + +var XRefParseException = (function XRefParseExceptionClosure() { + function XRefParseException(msg) { + this.message = msg; + } + + XRefParseException.prototype = new Error(); + XRefParseException.prototype.name = 'XRefParseException'; + XRefParseException.constructor = XRefParseException; + + return XRefParseException; +})(); + + +function bytesToString(bytes) { + assert(bytes !== null && typeof bytes === 'object' && + bytes.length !== undefined, 'Invalid argument for bytesToString'); + var length = bytes.length; + var MAX_ARGUMENT_COUNT = 8192; + if (length < MAX_ARGUMENT_COUNT) { + return String.fromCharCode.apply(null, bytes); + } + var strBuf = []; + for (var i = 0; i < length; i += MAX_ARGUMENT_COUNT) { + var chunkEnd = Math.min(i + MAX_ARGUMENT_COUNT, length); + var chunk = bytes.subarray(i, chunkEnd); + strBuf.push(String.fromCharCode.apply(null, chunk)); + } + return strBuf.join(''); +} + +function stringToBytes(str) { + assert(typeof str === 'string', 'Invalid argument for stringToBytes'); + var length = str.length; + var bytes = new Uint8Array(length); + for (var i = 0; i < length; ++i) { + bytes[i] = str.charCodeAt(i) & 0xFF; + } + return bytes; +} + +function string32(value) { + return String.fromCharCode((value >> 24) & 0xff, (value >> 16) & 0xff, + (value >> 8) & 0xff, value & 0xff); +} + +function log2(x) { + var n = 1, i = 0; + while (x > n) { + n <<= 1; + i++; + } + return i; +} + +function readInt8(data, start) { + return (data[start] << 24) >> 24; +} + +function readUint16(data, offset) { + return (data[offset] << 8) | data[offset + 1]; +} + +function readUint32(data, offset) { + return ((data[offset] << 24) | (data[offset + 1] << 16) | + (data[offset + 2] << 8) | data[offset + 3]) >>> 0; +} + +// Lazy test the endianness of the platform +// NOTE: This will be 'true' for simulated TypedArrays +function isLittleEndian() { + var buffer8 = new Uint8Array(2); + buffer8[0] = 1; + var buffer16 = new Uint16Array(buffer8.buffer); + return (buffer16[0] === 1); +} + +Object.defineProperty(PDFJS, 'isLittleEndian', { + configurable: true, + get: function PDFJS_isLittleEndian() { + return shadow(PDFJS, 'isLittleEndian', isLittleEndian()); + } +}); + +//#if !(FIREFOX || MOZCENTRAL || B2G || CHROME) +//// Lazy test if the userAgant support CanvasTypedArrays +function hasCanvasTypedArrays() { + var canvas = document.createElement('canvas'); + canvas.width = canvas.height = 1; + var ctx = canvas.getContext('2d'); + var imageData = ctx.createImageData(1, 1); + return (typeof imageData.data.buffer !== 'undefined'); +} + +Object.defineProperty(PDFJS, 'hasCanvasTypedArrays', { + configurable: true, + get: function PDFJS_hasCanvasTypedArrays() { + return shadow(PDFJS, 'hasCanvasTypedArrays', hasCanvasTypedArrays()); + } +}); + +var Uint32ArrayView = (function Uint32ArrayViewClosure() { + + function Uint32ArrayView(buffer, length) { + this.buffer = buffer; + this.byteLength = buffer.length; + this.length = length === undefined ? (this.byteLength >> 2) : length; + ensureUint32ArrayViewProps(this.length); + } + Uint32ArrayView.prototype = Object.create(null); + + var uint32ArrayViewSetters = 0; + function createUint32ArrayProp(index) { + return { + get: function () { + var buffer = this.buffer, offset = index << 2; + return (buffer[offset] | (buffer[offset + 1] << 8) | + (buffer[offset + 2] << 16) | (buffer[offset + 3] << 24)) >>> 0; + }, + set: function (value) { + var buffer = this.buffer, offset = index << 2; + buffer[offset] = value & 255; + buffer[offset + 1] = (value >> 8) & 255; + buffer[offset + 2] = (value >> 16) & 255; + buffer[offset + 3] = (value >>> 24) & 255; + } + }; + } + + function ensureUint32ArrayViewProps(length) { + while (uint32ArrayViewSetters < length) { + Object.defineProperty(Uint32ArrayView.prototype, + uint32ArrayViewSetters, + createUint32ArrayProp(uint32ArrayViewSetters)); + uint32ArrayViewSetters++; + } + } + + return Uint32ArrayView; +})(); +//#else +//PDFJS.hasCanvasTypedArrays = true; +//#endif + +var IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0]; + +var Util = PDFJS.Util = (function UtilClosure() { + function Util() {} + + var rgbBuf = ['rgb(', 0, ',', 0, ',', 0, ')']; + + // makeCssRgb() can be called thousands of times. Using |rgbBuf| avoids + // creating many intermediate strings. + Util.makeCssRgb = function Util_makeCssRgb(r, g, b) { + rgbBuf[1] = r; + rgbBuf[3] = g; + rgbBuf[5] = b; + return rgbBuf.join(''); + }; + + // Concatenates two transformation matrices together and returns the result. + Util.transform = function Util_transform(m1, m2) { + return [ + m1[0] * m2[0] + m1[2] * m2[1], + m1[1] * m2[0] + m1[3] * m2[1], + m1[0] * m2[2] + m1[2] * m2[3], + m1[1] * m2[2] + m1[3] * m2[3], + m1[0] * m2[4] + m1[2] * m2[5] + m1[4], + m1[1] * m2[4] + m1[3] * m2[5] + m1[5] + ]; + }; + + // For 2d affine transforms + Util.applyTransform = function Util_applyTransform(p, m) { + var xt = p[0] * m[0] + p[1] * m[2] + m[4]; + var yt = p[0] * m[1] + p[1] * m[3] + m[5]; + return [xt, yt]; + }; + + Util.applyInverseTransform = function Util_applyInverseTransform(p, m) { + var d = m[0] * m[3] - m[1] * m[2]; + var xt = (p[0] * m[3] - p[1] * m[2] + m[2] * m[5] - m[4] * m[3]) / d; + var yt = (-p[0] * m[1] + p[1] * m[0] + m[4] * m[1] - m[5] * m[0]) / d; + return [xt, yt]; + }; + + // Applies the transform to the rectangle and finds the minimum axially + // aligned bounding box. + Util.getAxialAlignedBoundingBox = + function Util_getAxialAlignedBoundingBox(r, m) { + + var p1 = Util.applyTransform(r, m); + var p2 = Util.applyTransform(r.slice(2, 4), m); + var p3 = Util.applyTransform([r[0], r[3]], m); + var p4 = Util.applyTransform([r[2], r[1]], m); + return [ + Math.min(p1[0], p2[0], p3[0], p4[0]), + Math.min(p1[1], p2[1], p3[1], p4[1]), + Math.max(p1[0], p2[0], p3[0], p4[0]), + Math.max(p1[1], p2[1], p3[1], p4[1]) + ]; + }; + + Util.inverseTransform = function Util_inverseTransform(m) { + var d = m[0] * m[3] - m[1] * m[2]; + return [m[3] / d, -m[1] / d, -m[2] / d, m[0] / d, + (m[2] * m[5] - m[4] * m[3]) / d, (m[4] * m[1] - m[5] * m[0]) / d]; + }; + + // Apply a generic 3d matrix M on a 3-vector v: + // | a b c | | X | + // | d e f | x | Y | + // | g h i | | Z | + // M is assumed to be serialized as [a,b,c,d,e,f,g,h,i], + // with v as [X,Y,Z] + Util.apply3dTransform = function Util_apply3dTransform(m, v) { + return [ + m[0] * v[0] + m[1] * v[1] + m[2] * v[2], + m[3] * v[0] + m[4] * v[1] + m[5] * v[2], + m[6] * v[0] + m[7] * v[1] + m[8] * v[2] + ]; + }; + + // This calculation uses Singular Value Decomposition. + // The SVD can be represented with formula A = USV. We are interested in the + // matrix S here because it represents the scale values. + Util.singularValueDecompose2dScale = + function Util_singularValueDecompose2dScale(m) { + + var transpose = [m[0], m[2], m[1], m[3]]; + + // Multiply matrix m with its transpose. + var a = m[0] * transpose[0] + m[1] * transpose[2]; + var b = m[0] * transpose[1] + m[1] * transpose[3]; + var c = m[2] * transpose[0] + m[3] * transpose[2]; + var d = m[2] * transpose[1] + m[3] * transpose[3]; + + // Solve the second degree polynomial to get roots. + var first = (a + d) / 2; + var second = Math.sqrt((a + d) * (a + d) - 4 * (a * d - c * b)) / 2; + var sx = first + second || 1; + var sy = first - second || 1; + + // Scale values are the square roots of the eigenvalues. + return [Math.sqrt(sx), Math.sqrt(sy)]; + }; + + // Normalize rectangle rect=[x1, y1, x2, y2] so that (x1,y1) < (x2,y2) + // For coordinate systems whose origin lies in the bottom-left, this + // means normalization to (BL,TR) ordering. For systems with origin in the + // top-left, this means (TL,BR) ordering. + Util.normalizeRect = function Util_normalizeRect(rect) { + var r = rect.slice(0); // clone rect + if (rect[0] > rect[2]) { + r[0] = rect[2]; + r[2] = rect[0]; + } + if (rect[1] > rect[3]) { + r[1] = rect[3]; + r[3] = rect[1]; + } + return r; + }; + + // Returns a rectangle [x1, y1, x2, y2] corresponding to the + // intersection of rect1 and rect2. If no intersection, returns 'false' + // The rectangle coordinates of rect1, rect2 should be [x1, y1, x2, y2] + Util.intersect = function Util_intersect(rect1, rect2) { + function compare(a, b) { + return a - b; + } + + // Order points along the axes + var orderedX = [rect1[0], rect1[2], rect2[0], rect2[2]].sort(compare), + orderedY = [rect1[1], rect1[3], rect2[1], rect2[3]].sort(compare), + result = []; + + rect1 = Util.normalizeRect(rect1); + rect2 = Util.normalizeRect(rect2); + + // X: first and second points belong to different rectangles? + if ((orderedX[0] === rect1[0] && orderedX[1] === rect2[0]) || + (orderedX[0] === rect2[0] && orderedX[1] === rect1[0])) { + // Intersection must be between second and third points + result[0] = orderedX[1]; + result[2] = orderedX[2]; + } else { + return false; + } + + // Y: first and second points belong to different rectangles? + if ((orderedY[0] === rect1[1] && orderedY[1] === rect2[1]) || + (orderedY[0] === rect2[1] && orderedY[1] === rect1[1])) { + // Intersection must be between second and third points + result[1] = orderedY[1]; + result[3] = orderedY[2]; + } else { + return false; + } + + return result; + }; + + Util.sign = function Util_sign(num) { + return num < 0 ? -1 : 1; + }; + + Util.appendToArray = function Util_appendToArray(arr1, arr2) { + Array.prototype.push.apply(arr1, arr2); + }; + + Util.prependToArray = function Util_prependToArray(arr1, arr2) { + Array.prototype.unshift.apply(arr1, arr2); + }; + + Util.extendObj = function extendObj(obj1, obj2) { + for (var key in obj2) { + obj1[key] = obj2[key]; + } + }; + + Util.getInheritableProperty = function Util_getInheritableProperty(dict, + name) { + while (dict && !dict.has(name)) { + dict = dict.get('Parent'); + } + if (!dict) { + return null; + } + return dict.get(name); + }; + + Util.inherit = function Util_inherit(sub, base, prototype) { + sub.prototype = Object.create(base.prototype); + sub.prototype.constructor = sub; + for (var prop in prototype) { + sub.prototype[prop] = prototype[prop]; + } + }; + + Util.loadScript = function Util_loadScript(src, callback) { + var script = document.createElement('script'); + var loaded = false; + script.setAttribute('src', src); + if (callback) { + script.onload = function() { + if (!loaded) { + callback(); + } + loaded = true; + }; + } + document.getElementsByTagName('head')[0].appendChild(script); + }; + + return Util; +})(); + +/** + * PDF page viewport created based on scale, rotation and offset. + * @class + * @alias PDFJS.PageViewport + */ +var PageViewport = PDFJS.PageViewport = (function PageViewportClosure() { + /** + * @constructor + * @private + * @param viewBox {Array} xMin, yMin, xMax and yMax coordinates. + * @param scale {number} scale of the viewport. + * @param rotation {number} rotations of the viewport in degrees. + * @param offsetX {number} offset X + * @param offsetY {number} offset Y + * @param dontFlip {boolean} if true, axis Y will not be flipped. + */ + function PageViewport(viewBox, scale, rotation, offsetX, offsetY, dontFlip) { + this.viewBox = viewBox; + this.scale = scale; + this.rotation = rotation; + this.offsetX = offsetX; + this.offsetY = offsetY; + + // creating transform to convert pdf coordinate system to the normal + // canvas like coordinates taking in account scale and rotation + var centerX = (viewBox[2] + viewBox[0]) / 2; + var centerY = (viewBox[3] + viewBox[1]) / 2; + var rotateA, rotateB, rotateC, rotateD; + rotation = rotation % 360; + rotation = rotation < 0 ? rotation + 360 : rotation; + switch (rotation) { + case 180: + rotateA = -1; rotateB = 0; rotateC = 0; rotateD = 1; + break; + case 90: + rotateA = 0; rotateB = 1; rotateC = 1; rotateD = 0; + break; + case 270: + rotateA = 0; rotateB = -1; rotateC = -1; rotateD = 0; + break; + //case 0: + default: + rotateA = 1; rotateB = 0; rotateC = 0; rotateD = -1; + break; + } + + if (dontFlip) { + rotateC = -rotateC; rotateD = -rotateD; + } + + var offsetCanvasX, offsetCanvasY; + var width, height; + if (rotateA === 0) { + offsetCanvasX = Math.abs(centerY - viewBox[1]) * scale + offsetX; + offsetCanvasY = Math.abs(centerX - viewBox[0]) * scale + offsetY; + width = Math.abs(viewBox[3] - viewBox[1]) * scale; + height = Math.abs(viewBox[2] - viewBox[0]) * scale; + } else { + offsetCanvasX = Math.abs(centerX - viewBox[0]) * scale + offsetX; + offsetCanvasY = Math.abs(centerY - viewBox[1]) * scale + offsetY; + width = Math.abs(viewBox[2] - viewBox[0]) * scale; + height = Math.abs(viewBox[3] - viewBox[1]) * scale; + } + // creating transform for the following operations: + // translate(-centerX, -centerY), rotate and flip vertically, + // scale, and translate(offsetCanvasX, offsetCanvasY) + this.transform = [ + rotateA * scale, + rotateB * scale, + rotateC * scale, + rotateD * scale, + offsetCanvasX - rotateA * scale * centerX - rotateC * scale * centerY, + offsetCanvasY - rotateB * scale * centerX - rotateD * scale * centerY + ]; + + this.width = width; + this.height = height; + this.fontScale = scale; + } + PageViewport.prototype = /** @lends PDFJS.PageViewport.prototype */ { + /** + * Clones viewport with additional properties. + * @param args {Object} (optional) If specified, may contain the 'scale' or + * 'rotation' properties to override the corresponding properties in + * the cloned viewport. + * @returns {PDFJS.PageViewport} Cloned viewport. + */ + clone: function PageViewPort_clone(args) { + args = args || {}; + var scale = 'scale' in args ? args.scale : this.scale; + var rotation = 'rotation' in args ? args.rotation : this.rotation; + return new PageViewport(this.viewBox.slice(), scale, rotation, + this.offsetX, this.offsetY, args.dontFlip); + }, + /** + * Converts PDF point to the viewport coordinates. For examples, useful for + * converting PDF location into canvas pixel coordinates. + * @param x {number} X coordinate. + * @param y {number} Y coordinate. + * @returns {Object} Object that contains 'x' and 'y' properties of the + * point in the viewport coordinate space. + * @see {@link convertToPdfPoint} + * @see {@link convertToViewportRectangle} + */ + convertToViewportPoint: function PageViewport_convertToViewportPoint(x, y) { + return Util.applyTransform([x, y], this.transform); + }, + /** + * Converts PDF rectangle to the viewport coordinates. + * @param rect {Array} xMin, yMin, xMax and yMax coordinates. + * @returns {Array} Contains corresponding coordinates of the rectangle + * in the viewport coordinate space. + * @see {@link convertToViewportPoint} + */ + convertToViewportRectangle: + function PageViewport_convertToViewportRectangle(rect) { + var tl = Util.applyTransform([rect[0], rect[1]], this.transform); + var br = Util.applyTransform([rect[2], rect[3]], this.transform); + return [tl[0], tl[1], br[0], br[1]]; + }, + /** + * Converts viewport coordinates to the PDF location. For examples, useful + * for converting canvas pixel location into PDF one. + * @param x {number} X coordinate. + * @param y {number} Y coordinate. + * @returns {Object} Object that contains 'x' and 'y' properties of the + * point in the PDF coordinate space. + * @see {@link convertToViewportPoint} + */ + convertToPdfPoint: function PageViewport_convertToPdfPoint(x, y) { + return Util.applyInverseTransform([x, y], this.transform); + } + }; + return PageViewport; +})(); + +var PDFStringTranslateTable = [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0x2D8, 0x2C7, 0x2C6, 0x2D9, 0x2DD, 0x2DB, 0x2DA, 0x2DC, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2022, 0x2020, 0x2021, 0x2026, 0x2014, + 0x2013, 0x192, 0x2044, 0x2039, 0x203A, 0x2212, 0x2030, 0x201E, 0x201C, + 0x201D, 0x2018, 0x2019, 0x201A, 0x2122, 0xFB01, 0xFB02, 0x141, 0x152, 0x160, + 0x178, 0x17D, 0x131, 0x142, 0x153, 0x161, 0x17E, 0, 0x20AC +]; + +function stringToPDFString(str) { + var i, n = str.length, strBuf = []; + if (str[0] === '\xFE' && str[1] === '\xFF') { + // UTF16BE BOM + for (i = 2; i < n; i += 2) { + strBuf.push(String.fromCharCode( + (str.charCodeAt(i) << 8) | str.charCodeAt(i + 1))); + } + } else { + for (i = 0; i < n; ++i) { + var code = PDFStringTranslateTable[str.charCodeAt(i)]; + strBuf.push(code ? String.fromCharCode(code) : str.charAt(i)); + } + } + return strBuf.join(''); +} + +function stringToUTF8String(str) { + return decodeURIComponent(escape(str)); +} + +function isEmptyObj(obj) { + for (var key in obj) { + return false; + } + return true; +} + +function isBool(v) { + return typeof v === 'boolean'; +} + +function isInt(v) { + return typeof v === 'number' && ((v | 0) === v); +} + +function isNum(v) { + return typeof v === 'number'; +} + +function isString(v) { + return typeof v === 'string'; +} + +function isName(v) { + return v instanceof Name; +} + +function isCmd(v, cmd) { + return v instanceof Cmd && (cmd === undefined || v.cmd === cmd); +} + +function isDict(v, type) { + if (!(v instanceof Dict)) { + return false; + } + if (!type) { + return true; + } + var dictType = v.get('Type'); + return isName(dictType) && dictType.name === type; +} + +function isArray(v) { + return v instanceof Array; +} + +function isStream(v) { + return typeof v === 'object' && v !== null && v.getBytes !== undefined; +} + +function isArrayBuffer(v) { + return typeof v === 'object' && v !== null && v.byteLength !== undefined; +} + +function isRef(v) { + return v instanceof Ref; +} + +/** + * Promise Capability object. + * + * @typedef {Object} PromiseCapability + * @property {Promise} promise - A promise object. + * @property {function} resolve - Fullfills the promise. + * @property {function} reject - Rejects the promise. + */ + +/** + * Creates a promise capability object. + * @alias PDFJS.createPromiseCapability + * + * @return {PromiseCapability} A capability object contains: + * - a Promise, resolve and reject methods. + */ +function createPromiseCapability() { + var capability = {}; + capability.promise = new Promise(function (resolve, reject) { + capability.resolve = resolve; + capability.reject = reject; + }); + return capability; +} + +PDFJS.createPromiseCapability = createPromiseCapability; + +/** + * Polyfill for Promises: + * The following promise implementation tries to generally implement the + * Promise/A+ spec. Some notable differences from other promise libaries are: + * - There currently isn't a seperate deferred and promise object. + * - Unhandled rejections eventually show an error if they aren't handled. + * + * Based off of the work in: + * https://bugzilla.mozilla.org/show_bug.cgi?id=810490 + */ +(function PromiseClosure() { + if (globalScope.Promise) { + // Promises existing in the DOM/Worker, checking presence of all/resolve + if (typeof globalScope.Promise.all !== 'function') { + globalScope.Promise.all = function (iterable) { + var count = 0, results = [], resolve, reject; + var promise = new globalScope.Promise(function (resolve_, reject_) { + resolve = resolve_; + reject = reject_; + }); + iterable.forEach(function (p, i) { + count++; + p.then(function (result) { + results[i] = result; + count--; + if (count === 0) { + resolve(results); + } + }, reject); + }); + if (count === 0) { + resolve(results); + } + return promise; + }; + } + if (typeof globalScope.Promise.resolve !== 'function') { + globalScope.Promise.resolve = function (value) { + return new globalScope.Promise(function (resolve) { resolve(value); }); + }; + } + if (typeof globalScope.Promise.reject !== 'function') { + globalScope.Promise.reject = function (reason) { + return new globalScope.Promise(function (resolve, reject) { + reject(reason); + }); + }; + } + if (typeof globalScope.Promise.prototype.catch !== 'function') { + globalScope.Promise.prototype.catch = function (onReject) { + return globalScope.Promise.prototype.then(undefined, onReject); + }; + } + return; + } +//#if !MOZCENTRAL + var STATUS_PENDING = 0; + var STATUS_RESOLVED = 1; + var STATUS_REJECTED = 2; + + // In an attempt to avoid silent exceptions, unhandled rejections are + // tracked and if they aren't handled in a certain amount of time an + // error is logged. + var REJECTION_TIMEOUT = 500; + + var HandlerManager = { + handlers: [], + running: false, + unhandledRejections: [], + pendingRejectionCheck: false, + + scheduleHandlers: function scheduleHandlers(promise) { + if (promise._status === STATUS_PENDING) { + return; + } + + this.handlers = this.handlers.concat(promise._handlers); + promise._handlers = []; + + if (this.running) { + return; + } + this.running = true; + + setTimeout(this.runHandlers.bind(this), 0); + }, + + runHandlers: function runHandlers() { + var RUN_TIMEOUT = 1; // ms + var timeoutAt = Date.now() + RUN_TIMEOUT; + while (this.handlers.length > 0) { + var handler = this.handlers.shift(); + + var nextStatus = handler.thisPromise._status; + var nextValue = handler.thisPromise._value; + + try { + if (nextStatus === STATUS_RESOLVED) { + if (typeof handler.onResolve === 'function') { + nextValue = handler.onResolve(nextValue); + } + } else if (typeof handler.onReject === 'function') { + nextValue = handler.onReject(nextValue); + nextStatus = STATUS_RESOLVED; + + if (handler.thisPromise._unhandledRejection) { + this.removeUnhandeledRejection(handler.thisPromise); + } + } + } catch (ex) { + nextStatus = STATUS_REJECTED; + nextValue = ex; + } + + handler.nextPromise._updateStatus(nextStatus, nextValue); + if (Date.now() >= timeoutAt) { + break; + } + } + + if (this.handlers.length > 0) { + setTimeout(this.runHandlers.bind(this), 0); + return; + } + + this.running = false; + }, + + addUnhandledRejection: function addUnhandledRejection(promise) { + this.unhandledRejections.push({ + promise: promise, + time: Date.now() + }); + this.scheduleRejectionCheck(); + }, + + removeUnhandeledRejection: function removeUnhandeledRejection(promise) { + promise._unhandledRejection = false; + for (var i = 0; i < this.unhandledRejections.length; i++) { + if (this.unhandledRejections[i].promise === promise) { + this.unhandledRejections.splice(i); + i--; + } + } + }, + + scheduleRejectionCheck: function scheduleRejectionCheck() { + if (this.pendingRejectionCheck) { + return; + } + this.pendingRejectionCheck = true; + setTimeout(function rejectionCheck() { + this.pendingRejectionCheck = false; + var now = Date.now(); + for (var i = 0; i < this.unhandledRejections.length; i++) { + if (now - this.unhandledRejections[i].time > REJECTION_TIMEOUT) { + var unhandled = this.unhandledRejections[i].promise._value; + var msg = 'Unhandled rejection: ' + unhandled; + if (unhandled.stack) { + msg += '\n' + unhandled.stack; + } + warn(msg); + this.unhandledRejections.splice(i); + i--; + } + } + if (this.unhandledRejections.length) { + this.scheduleRejectionCheck(); + } + }.bind(this), REJECTION_TIMEOUT); + } + }; + + function Promise(resolver) { + this._status = STATUS_PENDING; + this._handlers = []; + try { + resolver.call(this, this._resolve.bind(this), this._reject.bind(this)); + } catch (e) { + this._reject(e); + } + } + /** + * Builds a promise that is resolved when all the passed in promises are + * resolved. + * @param {array} array of data and/or promises to wait for. + * @return {Promise} New dependant promise. + */ + Promise.all = function Promise_all(promises) { + var resolveAll, rejectAll; + var deferred = new Promise(function (resolve, reject) { + resolveAll = resolve; + rejectAll = reject; + }); + var unresolved = promises.length; + var results = []; + if (unresolved === 0) { + resolveAll(results); + return deferred; + } + function reject(reason) { + if (deferred._status === STATUS_REJECTED) { + return; + } + results = []; + rejectAll(reason); + } + for (var i = 0, ii = promises.length; i < ii; ++i) { + var promise = promises[i]; + var resolve = (function(i) { + return function(value) { + if (deferred._status === STATUS_REJECTED) { + return; + } + results[i] = value; + unresolved--; + if (unresolved === 0) { + resolveAll(results); + } + }; + })(i); + if (Promise.isPromise(promise)) { + promise.then(resolve, reject); + } else { + resolve(promise); + } + } + return deferred; + }; + + /** + * Checks if the value is likely a promise (has a 'then' function). + * @return {boolean} true if value is thenable + */ + Promise.isPromise = function Promise_isPromise(value) { + return value && typeof value.then === 'function'; + }; + + /** + * Creates resolved promise + * @param value resolve value + * @returns {Promise} + */ + Promise.resolve = function Promise_resolve(value) { + return new Promise(function (resolve) { resolve(value); }); + }; + + /** + * Creates rejected promise + * @param reason rejection value + * @returns {Promise} + */ + Promise.reject = function Promise_reject(reason) { + return new Promise(function (resolve, reject) { reject(reason); }); + }; + + Promise.prototype = { + _status: null, + _value: null, + _handlers: null, + _unhandledRejection: null, + + _updateStatus: function Promise__updateStatus(status, value) { + if (this._status === STATUS_RESOLVED || + this._status === STATUS_REJECTED) { + return; + } + + if (status === STATUS_RESOLVED && + Promise.isPromise(value)) { + value.then(this._updateStatus.bind(this, STATUS_RESOLVED), + this._updateStatus.bind(this, STATUS_REJECTED)); + return; + } + + this._status = status; + this._value = value; + + if (status === STATUS_REJECTED && this._handlers.length === 0) { + this._unhandledRejection = true; + HandlerManager.addUnhandledRejection(this); + } + + HandlerManager.scheduleHandlers(this); + }, + + _resolve: function Promise_resolve(value) { + this._updateStatus(STATUS_RESOLVED, value); + }, + + _reject: function Promise_reject(reason) { + this._updateStatus(STATUS_REJECTED, reason); + }, + + then: function Promise_then(onResolve, onReject) { + var nextPromise = new Promise(function (resolve, reject) { + this.resolve = resolve; + this.reject = reject; + }); + this._handlers.push({ + thisPromise: this, + onResolve: onResolve, + onReject: onReject, + nextPromise: nextPromise + }); + HandlerManager.scheduleHandlers(this); + return nextPromise; + }, + + catch: function Promise_catch(onReject) { + return this.then(undefined, onReject); + } + }; + + globalScope.Promise = Promise; +//#else +//throw new Error('DOM Promise is not present'); +//#endif +})(); + +var StatTimer = (function StatTimerClosure() { + function rpad(str, pad, length) { + while (str.length < length) { + str += pad; + } + return str; + } + function StatTimer() { + this.started = {}; + this.times = []; + this.enabled = true; + } + StatTimer.prototype = { + time: function StatTimer_time(name) { + if (!this.enabled) { + return; + } + if (name in this.started) { + warn('Timer is already running for ' + name); + } + this.started[name] = Date.now(); + }, + timeEnd: function StatTimer_timeEnd(name) { + if (!this.enabled) { + return; + } + if (!(name in this.started)) { + warn('Timer has not been started for ' + name); + } + this.times.push({ + 'name': name, + 'start': this.started[name], + 'end': Date.now() + }); + // Remove timer from started so it can be called again. + delete this.started[name]; + }, + toString: function StatTimer_toString() { + var i, ii; + var times = this.times; + var out = ''; + // Find the longest name for padding purposes. + var longest = 0; + for (i = 0, ii = times.length; i < ii; ++i) { + var name = times[i]['name']; + if (name.length > longest) { + longest = name.length; + } + } + for (i = 0, ii = times.length; i < ii; ++i) { + var span = times[i]; + var duration = span.end - span.start; + out += rpad(span['name'], ' ', longest) + ' ' + duration + 'ms\n'; + } + return out; + } + }; + return StatTimer; +})(); + +PDFJS.createBlob = function createBlob(data, contentType) { + if (typeof Blob !== 'undefined') { + return new Blob([data], { type: contentType }); + } + // Blob builder is deprecated in FF14 and removed in FF18. + var bb = new MozBlobBuilder(); + bb.append(data); + return bb.getBlob(contentType); +}; + +PDFJS.createObjectURL = (function createObjectURLClosure() { + // Blob/createObjectURL is not available, falling back to data schema. + var digits = + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; + + return function createObjectURL(data, contentType) { + if (!PDFJS.disableCreateObjectURL && + typeof URL !== 'undefined' && URL.createObjectURL) { + var blob = PDFJS.createBlob(data, contentType); + return URL.createObjectURL(blob); + } + + var buffer = 'data:' + contentType + ';base64,'; + for (var i = 0, ii = data.length; i < ii; i += 3) { + var b1 = data[i] & 0xFF; + var b2 = data[i + 1] & 0xFF; + var b3 = data[i + 2] & 0xFF; + var d1 = b1 >> 2, d2 = ((b1 & 3) << 4) | (b2 >> 4); + var d3 = i + 1 < ii ? ((b2 & 0xF) << 2) | (b3 >> 6) : 64; + var d4 = i + 2 < ii ? (b3 & 0x3F) : 64; + buffer += digits[d1] + digits[d2] + digits[d3] + digits[d4]; + } + return buffer; + }; +})(); + +function MessageHandler(name, comObj) { + this.name = name; + this.comObj = comObj; + this.callbackIndex = 1; + this.postMessageTransfers = true; + var callbacksCapabilities = this.callbacksCapabilities = {}; + var ah = this.actionHandler = {}; + + ah['console_log'] = [function ahConsoleLog(data) { + console.log.apply(console, data); + }]; + ah['console_error'] = [function ahConsoleError(data) { + console.error.apply(console, data); + }]; + ah['_unsupported_feature'] = [function ah_unsupportedFeature(data) { + UnsupportedManager.notify(data); + }]; + + comObj.onmessage = function messageHandlerComObjOnMessage(event) { + var data = event.data; + if (data.isReply) { + var callbackId = data.callbackId; + if (data.callbackId in callbacksCapabilities) { + var callback = callbacksCapabilities[callbackId]; + delete callbacksCapabilities[callbackId]; + if ('error' in data) { + callback.reject(data.error); + } else { + callback.resolve(data.data); + } + } else { + error('Cannot resolve callback ' + callbackId); + } + } else if (data.action in ah) { + var action = ah[data.action]; + if (data.callbackId) { + Promise.resolve().then(function () { + return action[0].call(action[1], data.data); + }).then(function (result) { + comObj.postMessage({ + isReply: true, + callbackId: data.callbackId, + data: result + }); + }, function (reason) { + comObj.postMessage({ + isReply: true, + callbackId: data.callbackId, + error: reason + }); + }); + } else { + action[0].call(action[1], data.data); + } + } else { + error('Unknown action from worker: ' + data.action); + } + }; +} + +MessageHandler.prototype = { + on: function messageHandlerOn(actionName, handler, scope) { + var ah = this.actionHandler; + if (ah[actionName]) { + error('There is already an actionName called "' + actionName + '"'); + } + ah[actionName] = [handler, scope]; + }, + /** + * Sends a message to the comObj to invoke the action with the supplied data. + * @param {String} actionName Action to call. + * @param {JSON} data JSON data to send. + * @param {Array} [transfers] Optional list of transfers/ArrayBuffers + */ + send: function messageHandlerSend(actionName, data, transfers) { + var message = { + action: actionName, + data: data + }; + this.postMessage(message, transfers); + }, + /** + * Sends a message to the comObj to invoke the action with the supplied data. + * Expects that other side will callback with the response. + * @param {String} actionName Action to call. + * @param {JSON} data JSON data to send. + * @param {Array} [transfers] Optional list of transfers/ArrayBuffers. + * @returns {Promise} Promise to be resolved with response data. + */ + sendWithPromise: + function messageHandlerSendWithPromise(actionName, data, transfers) { + var callbackId = this.callbackIndex++; + var message = { + action: actionName, + data: data, + callbackId: callbackId + }; + var capability = createPromiseCapability(); + this.callbacksCapabilities[callbackId] = capability; + try { + this.postMessage(message, transfers); + } catch (e) { + capability.reject(e); + } + return capability.promise; + }, + /** + * Sends raw message to the comObj. + * @private + * @param message {Object} Raw message. + * @param transfers List of transfers/ArrayBuffers, or undefined. + */ + postMessage: function (message, transfers) { + if (transfers && this.postMessageTransfers) { + this.comObj.postMessage(message, transfers); + } else { + this.comObj.postMessage(message); + } + } +}; + +function loadJpegStream(id, imageUrl, objs) { + var img = new Image(); + img.onload = (function loadJpegStream_onloadClosure() { + objs.resolve(id, img); + }); + img.onerror = (function loadJpegStream_onerrorClosure() { + objs.resolve(id, null); + warn('Error during JPEG image loading'); + }); + img.src = imageUrl; +} + + + +//#if (FIREFOX || MOZCENTRAL) +// +//Components.utils.import('resource://gre/modules/Services.jsm'); +// +//var EXPORTED_SYMBOLS = ['NetworkManager']; +// +//var console = { +// log: function console_log(aMsg) { +// var msg = 'network.js: ' + (aMsg.join ? aMsg.join('') : aMsg); +// Services.console.logStringMessage(msg); +// // TODO(mack): dump() doesn't seem to work here... +// dump(msg + '\n'); +// } +//} +//#endif + +var NetworkManager = (function NetworkManagerClosure() { + + var OK_RESPONSE = 200; + var PARTIAL_CONTENT_RESPONSE = 206; + + function NetworkManager(url, args) { + this.url = url; + args = args || {}; + this.isHttp = /^https?:/i.test(url); + this.httpHeaders = (this.isHttp && args.httpHeaders) || {}; + this.withCredentials = args.withCredentials || false; + this.getXhr = args.getXhr || + function NetworkManager_getXhr() { +//#if B2G +// return new XMLHttpRequest({ mozSystem: true }); +//#else + return new XMLHttpRequest(); +//#endif + }; + + this.currXhrId = 0; + this.pendingRequests = {}; + this.loadedRequests = {}; + } + + function getArrayBuffer(xhr) { + var data = xhr.response; + if (typeof data !== 'string') { + return data; + } + var length = data.length; + var array = new Uint8Array(length); + for (var i = 0; i < length; i++) { + array[i] = data.charCodeAt(i) & 0xFF; + } + return array.buffer; + } + + NetworkManager.prototype = { + requestRange: function NetworkManager_requestRange(begin, end, listeners) { + var args = { + begin: begin, + end: end + }; + for (var prop in listeners) { + args[prop] = listeners[prop]; + } + return this.request(args); + }, + + requestFull: function NetworkManager_requestFull(listeners) { + return this.request(listeners); + }, + + request: function NetworkManager_request(args) { + var xhr = this.getXhr(); + var xhrId = this.currXhrId++; + var pendingRequest = this.pendingRequests[xhrId] = { + xhr: xhr + }; + + xhr.open('GET', this.url); + xhr.withCredentials = this.withCredentials; + for (var property in this.httpHeaders) { + var value = this.httpHeaders[property]; + if (typeof value === 'undefined') { + continue; + } + xhr.setRequestHeader(property, value); + } + if (this.isHttp && 'begin' in args && 'end' in args) { + var rangeStr = args.begin + '-' + (args.end - 1); + xhr.setRequestHeader('Range', 'bytes=' + rangeStr); + pendingRequest.expectedStatus = 206; + } else { + pendingRequest.expectedStatus = 200; + } + + if (args.onProgressiveData) { + // Some legacy browsers might throw an exception. + try { + xhr.responseType = 'moz-chunked-arraybuffer'; + } catch(e) {} + if (xhr.responseType === 'moz-chunked-arraybuffer') { + pendingRequest.onProgressiveData = args.onProgressiveData; + pendingRequest.mozChunked = true; + } else { + xhr.responseType = 'arraybuffer'; + } + } else { + xhr.responseType = 'arraybuffer'; + } + + if (args.onError) { + xhr.onerror = function(evt) { + args.onError(xhr.status); + }; + } + xhr.onreadystatechange = this.onStateChange.bind(this, xhrId); + xhr.onprogress = this.onProgress.bind(this, xhrId); + + pendingRequest.onHeadersReceived = args.onHeadersReceived; + pendingRequest.onDone = args.onDone; + pendingRequest.onError = args.onError; + pendingRequest.onProgress = args.onProgress; + + xhr.send(null); + + return xhrId; + }, + + onProgress: function NetworkManager_onProgress(xhrId, evt) { + var pendingRequest = this.pendingRequests[xhrId]; + if (!pendingRequest) { + // Maybe abortRequest was called... + return; + } + + if (pendingRequest.mozChunked) { + var chunk = getArrayBuffer(pendingRequest.xhr); + pendingRequest.onProgressiveData(chunk); + } + + var onProgress = pendingRequest.onProgress; + if (onProgress) { + onProgress(evt); + } + }, + + onStateChange: function NetworkManager_onStateChange(xhrId, evt) { + var pendingRequest = this.pendingRequests[xhrId]; + if (!pendingRequest) { + // Maybe abortRequest was called... + return; + } + + var xhr = pendingRequest.xhr; + if (xhr.readyState >= 2 && pendingRequest.onHeadersReceived) { + pendingRequest.onHeadersReceived(); + delete pendingRequest.onHeadersReceived; + } + + if (xhr.readyState !== 4) { + return; + } + + if (!(xhrId in this.pendingRequests)) { + // The XHR request might have been aborted in onHeadersReceived() + // callback, in which case we should abort request + return; + } + + delete this.pendingRequests[xhrId]; + + // success status == 0 can be on ftp, file and other protocols + if (xhr.status === 0 && this.isHttp) { + if (pendingRequest.onError) { + pendingRequest.onError(xhr.status); + } + return; + } + var xhrStatus = xhr.status || OK_RESPONSE; + + // From http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35.2: + // "A server MAY ignore the Range header". This means it's possible to + // get a 200 rather than a 206 response from a range request. + var ok_response_on_range_request = + xhrStatus === OK_RESPONSE && + pendingRequest.expectedStatus === PARTIAL_CONTENT_RESPONSE; + + if (!ok_response_on_range_request && + xhrStatus !== pendingRequest.expectedStatus) { + if (pendingRequest.onError) { + pendingRequest.onError(xhr.status); + } + return; + } + + this.loadedRequests[xhrId] = true; + + var chunk = getArrayBuffer(xhr); + if (xhrStatus === PARTIAL_CONTENT_RESPONSE) { + var rangeHeader = xhr.getResponseHeader('Content-Range'); + var matches = /bytes (\d+)-(\d+)\/(\d+)/.exec(rangeHeader); + var begin = parseInt(matches[1], 10); + pendingRequest.onDone({ + begin: begin, + chunk: chunk + }); + } else if (pendingRequest.onProgressiveData) { + pendingRequest.onDone(null); + } else { + pendingRequest.onDone({ + begin: 0, + chunk: chunk + }); + } + }, + + hasPendingRequests: function NetworkManager_hasPendingRequests() { + for (var xhrId in this.pendingRequests) { + return true; + } + return false; + }, + + getRequestXhr: function NetworkManager_getXhr(xhrId) { + return this.pendingRequests[xhrId].xhr; + }, + + isStreamingRequest: function NetworkManager_isStreamingRequest(xhrId) { + return !!(this.pendingRequests[xhrId].onProgressiveData); + }, + + isPendingRequest: function NetworkManager_isPendingRequest(xhrId) { + return xhrId in this.pendingRequests; + }, + + isLoadedRequest: function NetworkManager_isLoadedRequest(xhrId) { + return xhrId in this.loadedRequests; + }, + + abortAllRequests: function NetworkManager_abortAllRequests() { + for (var xhrId in this.pendingRequests) { + this.abortRequest(xhrId | 0); + } + }, + + abortRequest: function NetworkManager_abortRequest(xhrId) { + var xhr = this.pendingRequests[xhrId].xhr; + delete this.pendingRequests[xhrId]; + xhr.abort(); + } + }; + + return NetworkManager; +})(); + + +var ChunkedStream = (function ChunkedStreamClosure() { + function ChunkedStream(length, chunkSize, manager) { + this.bytes = new Uint8Array(length); + this.start = 0; + this.pos = 0; + this.end = length; + this.chunkSize = chunkSize; + this.loadedChunks = []; + this.numChunksLoaded = 0; + this.numChunks = Math.ceil(length / chunkSize); + this.manager = manager; + this.progressiveDataLength = 0; + this.lastSuccessfulEnsureByteChunk = -1; // a single-entry cache + } + + // required methods for a stream. if a particular stream does not + // implement these, an error should be thrown + ChunkedStream.prototype = { + + getMissingChunks: function ChunkedStream_getMissingChunks() { + var chunks = []; + for (var chunk = 0, n = this.numChunks; chunk < n; ++chunk) { + if (!this.loadedChunks[chunk]) { + chunks.push(chunk); + } + } + return chunks; + }, + + getBaseStreams: function ChunkedStream_getBaseStreams() { + return [this]; + }, + + allChunksLoaded: function ChunkedStream_allChunksLoaded() { + return this.numChunksLoaded === this.numChunks; + }, + + onReceiveData: function ChunkedStream_onReceiveData(begin, chunk) { + var end = begin + chunk.byteLength; + + assert(begin % this.chunkSize === 0, 'Bad begin offset: ' + begin); + // Using this.length is inaccurate here since this.start can be moved + // See ChunkedStream.moveStart() + var length = this.bytes.length; + assert(end % this.chunkSize === 0 || end === length, + 'Bad end offset: ' + end); + + this.bytes.set(new Uint8Array(chunk), begin); + var chunkSize = this.chunkSize; + var beginChunk = Math.floor(begin / chunkSize); + var endChunk = Math.floor((end - 1) / chunkSize) + 1; + var curChunk; + + for (curChunk = beginChunk; curChunk < endChunk; ++curChunk) { + if (!this.loadedChunks[curChunk]) { + this.loadedChunks[curChunk] = true; + ++this.numChunksLoaded; + } + } + }, + + onReceiveProgressiveData: + function ChunkedStream_onReceiveProgressiveData(data) { + var position = this.progressiveDataLength; + var beginChunk = Math.floor(position / this.chunkSize); + + this.bytes.set(new Uint8Array(data), position); + position += data.byteLength; + this.progressiveDataLength = position; + var endChunk = position >= this.end ? this.numChunks : + Math.floor(position / this.chunkSize); + var curChunk; + for (curChunk = beginChunk; curChunk < endChunk; ++curChunk) { + if (!this.loadedChunks[curChunk]) { + this.loadedChunks[curChunk] = true; + ++this.numChunksLoaded; + } + } + }, + + ensureByte: function ChunkedStream_ensureByte(pos) { + var chunk = Math.floor(pos / this.chunkSize); + if (chunk === this.lastSuccessfulEnsureByteChunk) { + return; + } + + if (!this.loadedChunks[chunk]) { + throw new MissingDataException(pos, pos + 1); + } + this.lastSuccessfulEnsureByteChunk = chunk; + }, + + ensureRange: function ChunkedStream_ensureRange(begin, end) { + if (begin >= end) { + return; + } + + if (end <= this.progressiveDataLength) { + return; + } + + var chunkSize = this.chunkSize; + var beginChunk = Math.floor(begin / chunkSize); + var endChunk = Math.floor((end - 1) / chunkSize) + 1; + for (var chunk = beginChunk; chunk < endChunk; ++chunk) { + if (!this.loadedChunks[chunk]) { + throw new MissingDataException(begin, end); + } + } + }, + + nextEmptyChunk: function ChunkedStream_nextEmptyChunk(beginChunk) { + var chunk, n; + for (chunk = beginChunk, n = this.numChunks; chunk < n; ++chunk) { + if (!this.loadedChunks[chunk]) { + return chunk; + } + } + // Wrap around to beginning + for (chunk = 0; chunk < beginChunk; ++chunk) { + if (!this.loadedChunks[chunk]) { + return chunk; + } + } + return null; + }, + + hasChunk: function ChunkedStream_hasChunk(chunk) { + return !!this.loadedChunks[chunk]; + }, + + get length() { + return this.end - this.start; + }, + + get isEmpty() { + return this.length === 0; + }, + + getByte: function ChunkedStream_getByte() { + var pos = this.pos; + if (pos >= this.end) { + return -1; + } + this.ensureByte(pos); + return this.bytes[this.pos++]; + }, + + getUint16: function ChunkedStream_getUint16() { + var b0 = this.getByte(); + var b1 = this.getByte(); + if (b0 === -1 || b1 === -1) { + return -1; + } + return (b0 << 8) + b1; + }, + + getInt32: function ChunkedStream_getInt32() { + var b0 = this.getByte(); + var b1 = this.getByte(); + var b2 = this.getByte(); + var b3 = this.getByte(); + return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3; + }, + + // returns subarray of original buffer + // should only be read + getBytes: function ChunkedStream_getBytes(length) { + var bytes = this.bytes; + var pos = this.pos; + var strEnd = this.end; + + if (!length) { + this.ensureRange(pos, strEnd); + return bytes.subarray(pos, strEnd); + } + + var end = pos + length; + if (end > strEnd) { + end = strEnd; + } + this.ensureRange(pos, end); + + this.pos = end; + return bytes.subarray(pos, end); + }, + + peekByte: function ChunkedStream_peekByte() { + var peekedByte = this.getByte(); + this.pos--; + return peekedByte; + }, + + peekBytes: function ChunkedStream_peekBytes(length) { + var bytes = this.getBytes(length); + this.pos -= bytes.length; + return bytes; + }, + + getByteRange: function ChunkedStream_getBytes(begin, end) { + this.ensureRange(begin, end); + return this.bytes.subarray(begin, end); + }, + + skip: function ChunkedStream_skip(n) { + if (!n) { + n = 1; + } + this.pos += n; + }, + + reset: function ChunkedStream_reset() { + this.pos = this.start; + }, + + moveStart: function ChunkedStream_moveStart() { + this.start = this.pos; + }, + + makeSubStream: function ChunkedStream_makeSubStream(start, length, dict) { + this.ensureRange(start, start + length); + + function ChunkedStreamSubstream() {} + ChunkedStreamSubstream.prototype = Object.create(this); + ChunkedStreamSubstream.prototype.getMissingChunks = function() { + var chunkSize = this.chunkSize; + var beginChunk = Math.floor(this.start / chunkSize); + var endChunk = Math.floor((this.end - 1) / chunkSize) + 1; + var missingChunks = []; + for (var chunk = beginChunk; chunk < endChunk; ++chunk) { + if (!this.loadedChunks[chunk]) { + missingChunks.push(chunk); + } + } + return missingChunks; + }; + var subStream = new ChunkedStreamSubstream(); + subStream.pos = subStream.start = start; + subStream.end = start + length || this.end; + subStream.dict = dict; + return subStream; + }, + + isStream: true + }; + + return ChunkedStream; +})(); + +var ChunkedStreamManager = (function ChunkedStreamManagerClosure() { + + function ChunkedStreamManager(length, chunkSize, url, args) { + this.stream = new ChunkedStream(length, chunkSize, this); + this.length = length; + this.chunkSize = chunkSize; + this.url = url; + this.disableAutoFetch = args.disableAutoFetch; + var msgHandler = this.msgHandler = args.msgHandler; + + if (args.chunkedViewerLoading) { + msgHandler.on('OnDataRange', this.onReceiveData.bind(this)); + msgHandler.on('OnDataProgress', this.onProgress.bind(this)); + this.sendRequest = function ChunkedStreamManager_sendRequest(begin, end) { + msgHandler.send('RequestDataRange', { begin: begin, end: end }); + }; + } else { + + var getXhr = function getXhr() { +//#if B2G +// return new XMLHttpRequest({ mozSystem: true }); +//#else + return new XMLHttpRequest(); +//#endif + }; + this.networkManager = new NetworkManager(this.url, { + getXhr: getXhr, + httpHeaders: args.httpHeaders, + withCredentials: args.withCredentials + }); + this.sendRequest = function ChunkedStreamManager_sendRequest(begin, end) { + this.networkManager.requestRange(begin, end, { + onDone: this.onReceiveData.bind(this), + onProgress: this.onProgress.bind(this) + }); + }; + } + + this.currRequestId = 0; + + this.chunksNeededByRequest = {}; + this.requestsByChunk = {}; + this.callbacksByRequest = {}; + this.progressiveDataLength = 0; + + this._loadedStreamCapability = createPromiseCapability(); + + if (args.initialData) { + this.onReceiveData({chunk: args.initialData}); + } + } + + ChunkedStreamManager.prototype = { + onLoadedStream: function ChunkedStreamManager_getLoadedStream() { + return this._loadedStreamCapability.promise; + }, + + // Get all the chunks that are not yet loaded and groups them into + // contiguous ranges to load in as few requests as possible + requestAllChunks: function ChunkedStreamManager_requestAllChunks() { + var missingChunks = this.stream.getMissingChunks(); + this.requestChunks(missingChunks); + return this._loadedStreamCapability.promise; + }, + + requestChunks: function ChunkedStreamManager_requestChunks(chunks, + callback) { + var requestId = this.currRequestId++; + + var chunksNeeded; + var i, ii; + this.chunksNeededByRequest[requestId] = chunksNeeded = {}; + for (i = 0, ii = chunks.length; i < ii; i++) { + if (!this.stream.hasChunk(chunks[i])) { + chunksNeeded[chunks[i]] = true; + } + } + + if (isEmptyObj(chunksNeeded)) { + if (callback) { + callback(); + } + return; + } + + this.callbacksByRequest[requestId] = callback; + + var chunksToRequest = []; + for (var chunk in chunksNeeded) { + chunk = chunk | 0; + if (!(chunk in this.requestsByChunk)) { + this.requestsByChunk[chunk] = []; + chunksToRequest.push(chunk); + } + this.requestsByChunk[chunk].push(requestId); + } + + if (!chunksToRequest.length) { + return; + } + + var groupedChunksToRequest = this.groupChunks(chunksToRequest); + + for (i = 0; i < groupedChunksToRequest.length; ++i) { + var groupedChunk = groupedChunksToRequest[i]; + var begin = groupedChunk.beginChunk * this.chunkSize; + var end = Math.min(groupedChunk.endChunk * this.chunkSize, this.length); + this.sendRequest(begin, end); + } + }, + + getStream: function ChunkedStreamManager_getStream() { + return this.stream; + }, + + // Loads any chunks in the requested range that are not yet loaded + requestRange: function ChunkedStreamManager_requestRange( + begin, end, callback) { + + end = Math.min(end, this.length); + + var beginChunk = this.getBeginChunk(begin); + var endChunk = this.getEndChunk(end); + + var chunks = []; + for (var chunk = beginChunk; chunk < endChunk; ++chunk) { + chunks.push(chunk); + } + + this.requestChunks(chunks, callback); + }, + + requestRanges: function ChunkedStreamManager_requestRanges(ranges, + callback) { + ranges = ranges || []; + var chunksToRequest = []; + + for (var i = 0; i < ranges.length; i++) { + var beginChunk = this.getBeginChunk(ranges[i].begin); + var endChunk = this.getEndChunk(ranges[i].end); + for (var chunk = beginChunk; chunk < endChunk; ++chunk) { + if (chunksToRequest.indexOf(chunk) < 0) { + chunksToRequest.push(chunk); + } + } + } + + chunksToRequest.sort(function(a, b) { return a - b; }); + this.requestChunks(chunksToRequest, callback); + }, + + // Groups a sorted array of chunks into as few continguous larger + // chunks as possible + groupChunks: function ChunkedStreamManager_groupChunks(chunks) { + var groupedChunks = []; + var beginChunk = -1; + var prevChunk = -1; + for (var i = 0; i < chunks.length; ++i) { + var chunk = chunks[i]; + + if (beginChunk < 0) { + beginChunk = chunk; + } + + if (prevChunk >= 0 && prevChunk + 1 !== chunk) { + groupedChunks.push({ beginChunk: beginChunk, + endChunk: prevChunk + 1 }); + beginChunk = chunk; + } + if (i + 1 === chunks.length) { + groupedChunks.push({ beginChunk: beginChunk, + endChunk: chunk + 1 }); + } + + prevChunk = chunk; + } + return groupedChunks; + }, + + onProgress: function ChunkedStreamManager_onProgress(args) { + var bytesLoaded = (this.stream.numChunksLoaded * this.chunkSize + + args.loaded); + this.msgHandler.send('DocProgress', { + loaded: bytesLoaded, + total: this.length + }); + }, + + onReceiveData: function ChunkedStreamManager_onReceiveData(args) { + var chunk = args.chunk; + var isProgressive = args.begin === undefined; + var begin = isProgressive ? this.progressiveDataLength : args.begin; + var end = begin + chunk.byteLength; + + var beginChunk = Math.floor(begin / this.chunkSize); + var endChunk = end < this.length ? Math.floor(end / this.chunkSize) : + Math.ceil(end / this.chunkSize); + + if (isProgressive) { + this.stream.onReceiveProgressiveData(chunk); + this.progressiveDataLength = end; + } else { + this.stream.onReceiveData(begin, chunk); + } + + if (this.stream.allChunksLoaded()) { + this._loadedStreamCapability.resolve(this.stream); + } + + var loadedRequests = []; + var i, requestId; + for (chunk = beginChunk; chunk < endChunk; ++chunk) { + // The server might return more chunks than requested + var requestIds = this.requestsByChunk[chunk] || []; + delete this.requestsByChunk[chunk]; + + for (i = 0; i < requestIds.length; ++i) { + requestId = requestIds[i]; + var chunksNeeded = this.chunksNeededByRequest[requestId]; + if (chunk in chunksNeeded) { + delete chunksNeeded[chunk]; + } + + if (!isEmptyObj(chunksNeeded)) { + continue; + } + + loadedRequests.push(requestId); + } + } + + // If there are no pending requests, automatically fetch the next + // unfetched chunk of the PDF + if (!this.disableAutoFetch && isEmptyObj(this.requestsByChunk)) { + var nextEmptyChunk; + if (this.stream.numChunksLoaded === 1) { + // This is a special optimization so that after fetching the first + // chunk, rather than fetching the second chunk, we fetch the last + // chunk. + var lastChunk = this.stream.numChunks - 1; + if (!this.stream.hasChunk(lastChunk)) { + nextEmptyChunk = lastChunk; + } + } else { + nextEmptyChunk = this.stream.nextEmptyChunk(endChunk); + } + if (isInt(nextEmptyChunk)) { + this.requestChunks([nextEmptyChunk]); + } + } + + for (i = 0; i < loadedRequests.length; ++i) { + requestId = loadedRequests[i]; + var callback = this.callbacksByRequest[requestId]; + delete this.callbacksByRequest[requestId]; + if (callback) { + callback(); + } + } + + this.msgHandler.send('DocProgress', { + loaded: this.stream.numChunksLoaded * this.chunkSize, + total: this.length + }); + }, + + onError: function ChunkedStreamManager_onError(err) { + this._loadedStreamCapability.reject(err); + }, + + getBeginChunk: function ChunkedStreamManager_getBeginChunk(begin) { + var chunk = Math.floor(begin / this.chunkSize); + return chunk; + }, + + getEndChunk: function ChunkedStreamManager_getEndChunk(end) { + if (end % this.chunkSize === 0) { + return end / this.chunkSize; + } + + // 0 -> 0 + // 1 -> 1 + // 99 -> 1 + // 100 -> 1 + // 101 -> 2 + var chunk = Math.floor((end - 1) / this.chunkSize) + 1; + return chunk; + } + }; + + return ChunkedStreamManager; +})(); + + +// The maximum number of bytes fetched per range request +var RANGE_CHUNK_SIZE = 65536; + +// TODO(mack): Make use of PDFJS.Util.inherit() when it becomes available +var BasePdfManager = (function BasePdfManagerClosure() { + function BasePdfManager() { + throw new Error('Cannot initialize BaseManagerManager'); + } + + BasePdfManager.prototype = { + onLoadedStream: function BasePdfManager_onLoadedStream() { + throw new NotImplementedException(); + }, + + ensureDoc: function BasePdfManager_ensureDoc(prop, args) { + return this.ensure(this.pdfDocument, prop, args); + }, + + ensureXRef: function BasePdfManager_ensureXRef(prop, args) { + return this.ensure(this.pdfDocument.xref, prop, args); + }, + + ensureCatalog: function BasePdfManager_ensureCatalog(prop, args) { + return this.ensure(this.pdfDocument.catalog, prop, args); + }, + + getPage: function BasePdfManager_pagePage(pageIndex) { + return this.pdfDocument.getPage(pageIndex); + }, + + cleanup: function BasePdfManager_cleanup() { + return this.pdfDocument.cleanup(); + }, + + ensure: function BasePdfManager_ensure(obj, prop, args) { + return new NotImplementedException(); + }, + + requestRange: function BasePdfManager_ensure(begin, end) { + return new NotImplementedException(); + }, + + requestLoadedStream: function BasePdfManager_requestLoadedStream() { + return new NotImplementedException(); + }, + + sendProgressiveData: function BasePdfManager_sendProgressiveData(chunk) { + return new NotImplementedException(); + }, + + updatePassword: function BasePdfManager_updatePassword(password) { + this.pdfDocument.xref.password = this.password = password; + if (this._passwordChangedCapability) { + this._passwordChangedCapability.resolve(); + } + }, + + passwordChanged: function BasePdfManager_passwordChanged() { + this._passwordChangedCapability = createPromiseCapability(); + return this._passwordChangedCapability.promise; + }, + + terminate: function BasePdfManager_terminate() { + return new NotImplementedException(); + } + }; + + return BasePdfManager; +})(); + +var LocalPdfManager = (function LocalPdfManagerClosure() { + function LocalPdfManager(data, password) { + var stream = new Stream(data); + this.pdfDocument = new PDFDocument(this, stream, password); + this._loadedStreamCapability = createPromiseCapability(); + this._loadedStreamCapability.resolve(stream); + } + + LocalPdfManager.prototype = Object.create(BasePdfManager.prototype); + LocalPdfManager.prototype.constructor = LocalPdfManager; + + LocalPdfManager.prototype.ensure = + function LocalPdfManager_ensure(obj, prop, args) { + return new Promise(function (resolve, reject) { + try { + var value = obj[prop]; + var result; + if (typeof value === 'function') { + result = value.apply(obj, args); + } else { + result = value; + } + resolve(result); + } catch (e) { + reject(e); + } + }); + }; + + LocalPdfManager.prototype.requestRange = + function LocalPdfManager_requestRange(begin, end) { + return Promise.resolve(); + }; + + LocalPdfManager.prototype.requestLoadedStream = + function LocalPdfManager_requestLoadedStream() { + }; + + LocalPdfManager.prototype.onLoadedStream = + function LocalPdfManager_getLoadedStream() { + return this._loadedStreamCapability.promise; + }; + + LocalPdfManager.prototype.terminate = + function LocalPdfManager_terminate() { + return; + }; + + return LocalPdfManager; +})(); + +var NetworkPdfManager = (function NetworkPdfManagerClosure() { + function NetworkPdfManager(args, msgHandler) { + + this.msgHandler = msgHandler; + + var params = { + msgHandler: msgHandler, + httpHeaders: args.httpHeaders, + withCredentials: args.withCredentials, + chunkedViewerLoading: args.chunkedViewerLoading, + disableAutoFetch: args.disableAutoFetch, + initialData: args.initialData + }; + this.streamManager = new ChunkedStreamManager(args.length, RANGE_CHUNK_SIZE, + args.url, params); + + this.pdfDocument = new PDFDocument(this, this.streamManager.getStream(), + args.password); + } + + NetworkPdfManager.prototype = Object.create(BasePdfManager.prototype); + NetworkPdfManager.prototype.constructor = NetworkPdfManager; + + NetworkPdfManager.prototype.ensure = + function NetworkPdfManager_ensure(obj, prop, args) { + var pdfManager = this; + + return new Promise(function (resolve, reject) { + function ensureHelper() { + try { + var result; + var value = obj[prop]; + if (typeof value === 'function') { + result = value.apply(obj, args); + } else { + result = value; + } + resolve(result); + } catch(e) { + if (!(e instanceof MissingDataException)) { + reject(e); + return; + } + pdfManager.streamManager.requestRange(e.begin, e.end, ensureHelper); + } + } + + ensureHelper(); + }); + }; + + NetworkPdfManager.prototype.requestRange = + function NetworkPdfManager_requestRange(begin, end) { + return new Promise(function (resolve) { + this.streamManager.requestRange(begin, end, function() { + resolve(); + }); + }.bind(this)); + }; + + NetworkPdfManager.prototype.requestLoadedStream = + function NetworkPdfManager_requestLoadedStream() { + this.streamManager.requestAllChunks(); + }; + + NetworkPdfManager.prototype.sendProgressiveData = + function NetworkPdfManager_sendProgressiveData(chunk) { + this.streamManager.onReceiveData({ chunk: chunk }); + }; + + NetworkPdfManager.prototype.onLoadedStream = + function NetworkPdfManager_getLoadedStream() { + return this.streamManager.onLoadedStream(); + }; + + NetworkPdfManager.prototype.terminate = + function NetworkPdfManager_terminate() { + this.streamManager.networkManager.abortAllRequests(); + }; + + return NetworkPdfManager; +})(); + + +var Page = (function PageClosure() { + + var LETTER_SIZE_MEDIABOX = [0, 0, 612, 792]; + + function Page(pdfManager, xref, pageIndex, pageDict, ref, fontCache) { + this.pdfManager = pdfManager; + this.pageIndex = pageIndex; + this.pageDict = pageDict; + this.xref = xref; + this.ref = ref; + this.fontCache = fontCache; + this.idCounters = { + obj: 0 + }; + this.resourcesPromise = null; + } + + Page.prototype = { + getPageProp: function Page_getPageProp(key) { + return this.pageDict.get(key); + }, + + getInheritedPageProp: function Page_inheritPageProp(key) { + var dict = this.pageDict; + var value = dict.get(key); + while (value === undefined) { + dict = dict.get('Parent'); + if (!dict) { + break; + } + value = dict.get(key); + } + return value; + }, + + get content() { + return this.getPageProp('Contents'); + }, + + get resources() { + var value = this.getInheritedPageProp('Resources'); + // For robustness: The spec states that a \Resources entry has to be + // present, but can be empty. Some document omit it still. In this case + // return an empty dictionary: + if (value === undefined) { + value = Dict.empty; + } + return shadow(this, 'resources', value); + }, + + get mediaBox() { + var obj = this.getInheritedPageProp('MediaBox'); + // Reset invalid media box to letter size. + if (!isArray(obj) || obj.length !== 4) { + obj = LETTER_SIZE_MEDIABOX; + } + return shadow(this, 'mediaBox', obj); + }, + + get view() { + var mediaBox = this.mediaBox; + var cropBox = this.getInheritedPageProp('CropBox'); + if (!isArray(cropBox) || cropBox.length !== 4) { + return shadow(this, 'view', mediaBox); + } + + // From the spec, 6th ed., p.963: + // "The crop, bleed, trim, and art boxes should not ordinarily + // extend beyond the boundaries of the media box. If they do, they are + // effectively reduced to their intersection with the media box." + cropBox = Util.intersect(cropBox, mediaBox); + if (!cropBox) { + return shadow(this, 'view', mediaBox); + } + return shadow(this, 'view', cropBox); + }, + + get annotationRefs() { + return shadow(this, 'annotationRefs', + this.getInheritedPageProp('Annots')); + }, + + get rotate() { + var rotate = this.getInheritedPageProp('Rotate') || 0; + // Normalize rotation so it's a multiple of 90 and between 0 and 270 + if (rotate % 90 !== 0) { + rotate = 0; + } else if (rotate >= 360) { + rotate = rotate % 360; + } else if (rotate < 0) { + // The spec doesn't cover negatives, assume its counterclockwise + // rotation. The following is the other implementation of modulo. + rotate = ((rotate % 360) + 360) % 360; + } + return shadow(this, 'rotate', rotate); + }, + + getContentStream: function Page_getContentStream() { + var content = this.content; + var stream; + if (isArray(content)) { + // fetching items + var xref = this.xref; + var i, n = content.length; + var streams = []; + for (i = 0; i < n; ++i) { + streams.push(xref.fetchIfRef(content[i])); + } + stream = new StreamsSequenceStream(streams); + } else if (isStream(content)) { + stream = content; + } else { + // replacing non-existent page content with empty one + stream = new NullStream(); + } + return stream; + }, + + loadResources: function Page_loadResources(keys) { + if (!this.resourcesPromise) { + // TODO: add async getInheritedPageProp and remove this. + this.resourcesPromise = this.pdfManager.ensure(this, 'resources'); + } + return this.resourcesPromise.then(function resourceSuccess() { + var objectLoader = new ObjectLoader(this.resources.map, + keys, + this.xref); + return objectLoader.load(); + }.bind(this)); + }, + + getOperatorList: function Page_getOperatorList(handler, intent) { + var self = this; + + var pdfManager = this.pdfManager; + var contentStreamPromise = pdfManager.ensure(this, 'getContentStream', + []); + var resourcesPromise = this.loadResources([ + 'ExtGState', + 'ColorSpace', + 'Pattern', + 'Shading', + 'XObject', + 'Font' + // ProcSet + // Properties + ]); + + var partialEvaluator = new PartialEvaluator(pdfManager, this.xref, + handler, this.pageIndex, + 'p' + this.pageIndex + '_', + this.idCounters, + this.fontCache); + + var dataPromises = Promise.all([contentStreamPromise, resourcesPromise]); + var pageListPromise = dataPromises.then(function(data) { + var contentStream = data[0]; + var opList = new OperatorList(intent, handler, self.pageIndex); + + handler.send('StartRenderPage', { + transparency: partialEvaluator.hasBlendModes(self.resources), + pageIndex: self.pageIndex, + intent: intent + }); + return partialEvaluator.getOperatorList(contentStream, self.resources, + opList).then(function () { + return opList; + }); + }); + + var annotationsPromise = pdfManager.ensure(this, 'annotations'); + return Promise.all([pageListPromise, annotationsPromise]).then( + function(datas) { + var pageOpList = datas[0]; + var annotations = datas[1]; + + if (annotations.length === 0) { + pageOpList.flush(true); + return pageOpList; + } + + var annotationsReadyPromise = Annotation.appendToOperatorList( + annotations, pageOpList, pdfManager, partialEvaluator, intent); + return annotationsReadyPromise.then(function () { + pageOpList.flush(true); + return pageOpList; + }); + }); + }, + + extractTextContent: function Page_extractTextContent() { + var handler = { + on: function nullHandlerOn() {}, + send: function nullHandlerSend() {} + }; + + var self = this; + + var pdfManager = this.pdfManager; + var contentStreamPromise = pdfManager.ensure(this, 'getContentStream', + []); + + var resourcesPromise = this.loadResources([ + 'ExtGState', + 'XObject', + 'Font' + ]); + + var dataPromises = Promise.all([contentStreamPromise, + resourcesPromise]); + return dataPromises.then(function(data) { + var contentStream = data[0]; + var partialEvaluator = new PartialEvaluator(pdfManager, self.xref, + handler, self.pageIndex, + 'p' + self.pageIndex + '_', + self.idCounters, + self.fontCache); + + return partialEvaluator.getTextContent(contentStream, + self.resources); + }); + }, + + getAnnotationsData: function Page_getAnnotationsData() { + var annotations = this.annotations; + var annotationsData = []; + for (var i = 0, n = annotations.length; i < n; ++i) { + annotationsData.push(annotations[i].getData()); + } + return annotationsData; + }, + + get annotations() { + var annotations = []; + var annotationRefs = (this.annotationRefs || []); + for (var i = 0, n = annotationRefs.length; i < n; ++i) { + var annotationRef = annotationRefs[i]; + var annotation = Annotation.fromRef(this.xref, annotationRef); + if (annotation) { + annotations.push(annotation); + } + } + return shadow(this, 'annotations', annotations); + } + }; + + return Page; +})(); + +/** + * The `PDFDocument` holds all the data of the PDF file. Compared to the + * `PDFDoc`, this one doesn't have any job management code. + * Right now there exists one PDFDocument on the main thread + one object + * for each worker. If there is no worker support enabled, there are two + * `PDFDocument` objects on the main thread created. + */ +var PDFDocument = (function PDFDocumentClosure() { + var FINGERPRINT_FIRST_BYTES = 1024; + var EMPTY_FINGERPRINT = '\x00\x00\x00\x00\x00\x00\x00' + + '\x00\x00\x00\x00\x00\x00\x00\x00\x00'; + + function PDFDocument(pdfManager, arg, password) { + if (isStream(arg)) { + init.call(this, pdfManager, arg, password); + } else if (isArrayBuffer(arg)) { + init.call(this, pdfManager, new Stream(arg), password); + } else { + error('PDFDocument: Unknown argument type'); + } + } + + function init(pdfManager, stream, password) { + assert(stream.length > 0, 'stream must have data'); + this.pdfManager = pdfManager; + this.stream = stream; + var xref = new XRef(this.stream, password, pdfManager); + this.xref = xref; + } + + function find(stream, needle, limit, backwards) { + var pos = stream.pos; + var end = stream.end; + var strBuf = []; + if (pos + limit > end) { + limit = end - pos; + } + for (var n = 0; n < limit; ++n) { + strBuf.push(String.fromCharCode(stream.getByte())); + } + var str = strBuf.join(''); + stream.pos = pos; + var index = backwards ? str.lastIndexOf(needle) : str.indexOf(needle); + if (index === -1) { + return false; /* not found */ + } + stream.pos += index; + return true; /* found */ + } + + var DocumentInfoValidators = { + get entries() { + // Lazily build this since all the validation functions below are not + // defined until after this file loads. + return shadow(this, 'entries', { + Title: isString, + Author: isString, + Subject: isString, + Keywords: isString, + Creator: isString, + Producer: isString, + CreationDate: isString, + ModDate: isString, + Trapped: isName + }); + } + }; + + PDFDocument.prototype = { + parse: function PDFDocument_parse(recoveryMode) { + this.setup(recoveryMode); + try { + // checking if AcroForm is present + this.acroForm = this.catalog.catDict.get('AcroForm'); + if (this.acroForm) { + this.xfa = this.acroForm.get('XFA'); + var fields = this.acroForm.get('Fields'); + if ((!fields || !isArray(fields) || fields.length === 0) && + !this.xfa) { + // no fields and no XFA -- not a form (?) + this.acroForm = null; + } + } + } catch (ex) { + info('Something wrong with AcroForm entry'); + this.acroForm = null; + } + }, + + get linearization() { + var linearization = null; + if (this.stream.length) { + try { + linearization = Linearization.create(this.stream); + } catch (err) { + if (err instanceof MissingDataException) { + throw err; + } + info(err); + } + } + // shadow the prototype getter with a data property + return shadow(this, 'linearization', linearization); + }, + get startXRef() { + var stream = this.stream; + var startXRef = 0; + var linearization = this.linearization; + if (linearization) { + // Find end of first obj. + stream.reset(); + if (find(stream, 'endobj', 1024)) { + startXRef = stream.pos + 6; + } + } else { + // Find startxref by jumping backward from the end of the file. + var step = 1024; + var found = false, pos = stream.end; + while (!found && pos > 0) { + pos -= step - 'startxref'.length; + if (pos < 0) { + pos = 0; + } + stream.pos = pos; + found = find(stream, 'startxref', step, true); + } + if (found) { + stream.skip(9); + var ch; + do { + ch = stream.getByte(); + } while (Lexer.isSpace(ch)); + var str = ''; + while (ch >= 0x20 && ch <= 0x39) { // < '9' + str += String.fromCharCode(ch); + ch = stream.getByte(); + } + startXRef = parseInt(str, 10); + if (isNaN(startXRef)) { + startXRef = 0; + } + } + } + // shadow the prototype getter with a data property + return shadow(this, 'startXRef', startXRef); + }, + get mainXRefEntriesOffset() { + var mainXRefEntriesOffset = 0; + var linearization = this.linearization; + if (linearization) { + mainXRefEntriesOffset = linearization.mainXRefEntriesOffset; + } + // shadow the prototype getter with a data property + return shadow(this, 'mainXRefEntriesOffset', mainXRefEntriesOffset); + }, + // Find the header, remove leading garbage and setup the stream + // starting from the header. + checkHeader: function PDFDocument_checkHeader() { + var stream = this.stream; + stream.reset(); + if (find(stream, '%PDF-', 1024)) { + // Found the header, trim off any garbage before it. + stream.moveStart(); + // Reading file format version + var MAX_VERSION_LENGTH = 12; + var version = '', ch; + while ((ch = stream.getByte()) > 0x20) { // SPACE + if (version.length >= MAX_VERSION_LENGTH) { + break; + } + version += String.fromCharCode(ch); + } + // removing "%PDF-"-prefix + this.pdfFormatVersion = version.substring(5); + return; + } + // May not be a PDF file, continue anyway. + }, + parseStartXRef: function PDFDocument_parseStartXRef() { + var startXRef = this.startXRef; + this.xref.setStartXRef(startXRef); + }, + setup: function PDFDocument_setup(recoveryMode) { + this.xref.parse(recoveryMode); + this.catalog = new Catalog(this.pdfManager, this.xref); + }, + get numPages() { + var linearization = this.linearization; + var num = linearization ? linearization.numPages : this.catalog.numPages; + // shadow the prototype getter + return shadow(this, 'numPages', num); + }, + get documentInfo() { + var docInfo = { + PDFFormatVersion: this.pdfFormatVersion, + IsAcroFormPresent: !!this.acroForm, + IsXFAPresent: !!this.xfa + }; + var infoDict; + try { + infoDict = this.xref.trailer.get('Info'); + } catch (err) { + info('The document information dictionary is invalid.'); + } + if (infoDict) { + var validEntries = DocumentInfoValidators.entries; + // Only fill the document info with valid entries from the spec. + for (var key in validEntries) { + if (infoDict.has(key)) { + var value = infoDict.get(key); + // Make sure the value conforms to the spec. + if (validEntries[key](value)) { + docInfo[key] = (typeof value !== 'string' ? + value : stringToPDFString(value)); + } else { + info('Bad value in document info for "' + key + '"'); + } + } + } + } + return shadow(this, 'documentInfo', docInfo); + }, + get fingerprint() { + var xref = this.xref, idArray, hash, fileID = ''; + + if (xref.trailer.has('ID')) { + idArray = xref.trailer.get('ID'); + } + if (idArray && isArray(idArray) && idArray[0] !== EMPTY_FINGERPRINT) { + hash = stringToBytes(idArray[0]); + } else { + if (this.stream.ensureRange) { + this.stream.ensureRange(0, + Math.min(FINGERPRINT_FIRST_BYTES, this.stream.end)); + } + hash = calculateMD5(this.stream.bytes.subarray(0, + FINGERPRINT_FIRST_BYTES), 0, FINGERPRINT_FIRST_BYTES); + } + + for (var i = 0, n = hash.length; i < n; i++) { + var hex = hash[i].toString(16); + fileID += hex.length === 1 ? '0' + hex : hex; + } + + return shadow(this, 'fingerprint', fileID); + }, + + getPage: function PDFDocument_getPage(pageIndex) { + return this.catalog.getPage(pageIndex); + }, + + cleanup: function PDFDocument_cleanup() { + return this.catalog.cleanup(); + } + }; + + return PDFDocument; +})(); + + +var Name = (function NameClosure() { + function Name(name) { + this.name = name; + } + + Name.prototype = {}; + + var nameCache = {}; + + Name.get = function Name_get(name) { + var nameValue = nameCache[name]; + return (nameValue ? nameValue : (nameCache[name] = new Name(name))); + }; + + return Name; +})(); + +var Cmd = (function CmdClosure() { + function Cmd(cmd) { + this.cmd = cmd; + } + + Cmd.prototype = {}; + + var cmdCache = {}; + + Cmd.get = function Cmd_get(cmd) { + var cmdValue = cmdCache[cmd]; + return (cmdValue ? cmdValue : (cmdCache[cmd] = new Cmd(cmd))); + }; + + return Cmd; +})(); + +var Dict = (function DictClosure() { + var nonSerializable = function nonSerializableClosure() { + return nonSerializable; // creating closure on some variable + }; + + var GETALL_DICTIONARY_TYPES_WHITELIST = { + 'Background': true, + 'ExtGState': true, + 'Halftone': true, + 'Layout': true, + 'Mask': true, + 'Pagination': true, + 'Printing': true + }; + + function isRecursionAllowedFor(dict) { + if (!isName(dict.Type)) { + return true; + } + var dictType = dict.Type.name; + return GETALL_DICTIONARY_TYPES_WHITELIST[dictType] === true; + } + + // xref is optional + function Dict(xref) { + // Map should only be used internally, use functions below to access. + this.map = Object.create(null); + this.xref = xref; + this.objId = null; + this.__nonSerializable__ = nonSerializable; // disable cloning of the Dict + } + + Dict.prototype = { + assignXref: function Dict_assignXref(newXref) { + this.xref = newXref; + }, + + // automatically dereferences Ref objects + get: function Dict_get(key1, key2, key3) { + var value; + var xref = this.xref; + if (typeof (value = this.map[key1]) !== 'undefined' || key1 in this.map || + typeof key2 === 'undefined') { + return xref ? xref.fetchIfRef(value) : value; + } + if (typeof (value = this.map[key2]) !== 'undefined' || key2 in this.map || + typeof key3 === 'undefined') { + return xref ? xref.fetchIfRef(value) : value; + } + value = this.map[key3] || null; + return xref ? xref.fetchIfRef(value) : value; + }, + + // Same as get(), but returns a promise and uses fetchIfRefAsync(). + getAsync: function Dict_getAsync(key1, key2, key3) { + var value; + var xref = this.xref; + if (typeof (value = this.map[key1]) !== 'undefined' || key1 in this.map || + typeof key2 === 'undefined') { + if (xref) { + return xref.fetchIfRefAsync(value); + } + return Promise.resolve(value); + } + if (typeof (value = this.map[key2]) !== 'undefined' || key2 in this.map || + typeof key3 === 'undefined') { + if (xref) { + return xref.fetchIfRefAsync(value); + } + return Promise.resolve(value); + } + value = this.map[key3] || null; + if (xref) { + return xref.fetchIfRefAsync(value); + } + return Promise.resolve(value); + }, + + // no dereferencing + getRaw: function Dict_getRaw(key) { + return this.map[key]; + }, + + // creates new map and dereferences all Refs + getAll: function Dict_getAll() { + var all = Object.create(null); + var queue = null; + var key, obj; + for (key in this.map) { + obj = this.get(key); + if (obj instanceof Dict) { + if (isRecursionAllowedFor(obj)) { + (queue || (queue = [])).push({target: all, key: key, obj: obj}); + } else { + all[key] = this.getRaw(key); + } + } else { + all[key] = obj; + } + } + if (!queue) { + return all; + } + + // trying to take cyclic references into the account + var processed = Object.create(null); + while (queue.length > 0) { + var item = queue.shift(); + var itemObj = item.obj; + var objId = itemObj.objId; + if (objId && objId in processed) { + item.target[item.key] = processed[objId]; + continue; + } + var dereferenced = Object.create(null); + for (key in itemObj.map) { + obj = itemObj.get(key); + if (obj instanceof Dict) { + if (isRecursionAllowedFor(obj)) { + queue.push({target: dereferenced, key: key, obj: obj}); + } else { + dereferenced[key] = itemObj.getRaw(key); + } + } else { + dereferenced[key] = obj; + } + } + if (objId) { + processed[objId] = dereferenced; + } + item.target[item.key] = dereferenced; + } + return all; + }, + + getKeys: function Dict_getKeys() { + return Object.keys(this.map); + }, + + set: function Dict_set(key, value) { + this.map[key] = value; + }, + + has: function Dict_has(key) { + return key in this.map; + }, + + forEach: function Dict_forEach(callback) { + for (var key in this.map) { + callback(key, this.get(key)); + } + } + }; + + Dict.empty = new Dict(null); + + return Dict; +})(); + +var Ref = (function RefClosure() { + function Ref(num, gen) { + this.num = num; + this.gen = gen; + } + + Ref.prototype = { + toString: function Ref_toString() { + // This function is hot, so we make the string as compact as possible. + // |this.gen| is almost always zero, so we treat that case specially. + var str = this.num + 'R'; + if (this.gen !== 0) { + str += this.gen; + } + return str; + } + }; + + return Ref; +})(); + +// The reference is identified by number and generation. +// This structure stores only one instance of the reference. +var RefSet = (function RefSetClosure() { + function RefSet() { + this.dict = {}; + } + + RefSet.prototype = { + has: function RefSet_has(ref) { + return ref.toString() in this.dict; + }, + + put: function RefSet_put(ref) { + this.dict[ref.toString()] = true; + }, + + remove: function RefSet_remove(ref) { + delete this.dict[ref.toString()]; + } + }; + + return RefSet; +})(); + +var RefSetCache = (function RefSetCacheClosure() { + function RefSetCache() { + this.dict = Object.create(null); + } + + RefSetCache.prototype = { + get: function RefSetCache_get(ref) { + return this.dict[ref.toString()]; + }, + + has: function RefSetCache_has(ref) { + return ref.toString() in this.dict; + }, + + put: function RefSetCache_put(ref, obj) { + this.dict[ref.toString()] = obj; + }, + + putAlias: function RefSetCache_putAlias(ref, aliasRef) { + this.dict[ref.toString()] = this.get(aliasRef); + }, + + forEach: function RefSetCache_forEach(fn, thisArg) { + for (var i in this.dict) { + fn.call(thisArg, this.dict[i]); + } + }, + + clear: function RefSetCache_clear() { + this.dict = Object.create(null); + } + }; + + return RefSetCache; +})(); + +var Catalog = (function CatalogClosure() { + function Catalog(pdfManager, xref) { + this.pdfManager = pdfManager; + this.xref = xref; + this.catDict = xref.getCatalogObj(); + this.fontCache = new RefSetCache(); + assert(isDict(this.catDict), + 'catalog object is not a dictionary'); + + this.pagePromises = []; + } + + Catalog.prototype = { + get metadata() { + var streamRef = this.catDict.getRaw('Metadata'); + if (!isRef(streamRef)) { + return shadow(this, 'metadata', null); + } + + var encryptMetadata = (!this.xref.encrypt ? false : + this.xref.encrypt.encryptMetadata); + + var stream = this.xref.fetch(streamRef, !encryptMetadata); + var metadata; + if (stream && isDict(stream.dict)) { + var type = stream.dict.get('Type'); + var subtype = stream.dict.get('Subtype'); + + if (isName(type) && isName(subtype) && + type.name === 'Metadata' && subtype.name === 'XML') { + // XXX: This should examine the charset the XML document defines, + // however since there are currently no real means to decode + // arbitrary charsets, let's just hope that the author of the PDF + // was reasonable enough to stick with the XML default charset, + // which is UTF-8. + try { + metadata = stringToUTF8String(bytesToString(stream.getBytes())); + } catch (e) { + info('Skipping invalid metadata.'); + } + } + } + + return shadow(this, 'metadata', metadata); + }, + get toplevelPagesDict() { + var pagesObj = this.catDict.get('Pages'); + assert(isDict(pagesObj), 'invalid top-level pages dictionary'); + // shadow the prototype getter + return shadow(this, 'toplevelPagesDict', pagesObj); + }, + get documentOutline() { + var obj = null; + try { + obj = this.readDocumentOutline(); + } catch (ex) { + if (ex instanceof MissingDataException) { + throw ex; + } + warn('Unable to read document outline'); + } + return shadow(this, 'documentOutline', obj); + }, + readDocumentOutline: function Catalog_readDocumentOutline() { + var xref = this.xref; + var obj = this.catDict.get('Outlines'); + var root = { items: [] }; + if (isDict(obj)) { + obj = obj.getRaw('First'); + var processed = new RefSet(); + if (isRef(obj)) { + var queue = [{obj: obj, parent: root}]; + // to avoid recursion keeping track of the items + // in the processed dictionary + processed.put(obj); + while (queue.length > 0) { + var i = queue.shift(); + var outlineDict = xref.fetchIfRef(i.obj); + if (outlineDict === null) { + continue; + } + if (!outlineDict.has('Title')) { + error('Invalid outline item'); + } + var dest = outlineDict.get('A'); + if (dest) { + dest = dest.get('D'); + } else if (outlineDict.has('Dest')) { + dest = outlineDict.getRaw('Dest'); + if (isName(dest)) { + dest = dest.name; + } + } + var title = outlineDict.get('Title'); + var outlineItem = { + dest: dest, + title: stringToPDFString(title), + color: outlineDict.get('C') || [0, 0, 0], + count: outlineDict.get('Count'), + bold: !!(outlineDict.get('F') & 2), + italic: !!(outlineDict.get('F') & 1), + items: [] + }; + i.parent.items.push(outlineItem); + obj = outlineDict.getRaw('First'); + if (isRef(obj) && !processed.has(obj)) { + queue.push({obj: obj, parent: outlineItem}); + processed.put(obj); + } + obj = outlineDict.getRaw('Next'); + if (isRef(obj) && !processed.has(obj)) { + queue.push({obj: obj, parent: i.parent}); + processed.put(obj); + } + } + } + } + return (root.items.length > 0 ? root.items : null); + }, + get numPages() { + var obj = this.toplevelPagesDict.get('Count'); + assert( + isInt(obj), + 'page count in top level pages object is not an integer' + ); + // shadow the prototype getter + return shadow(this, 'num', obj); + }, + get destinations() { + function fetchDestination(dest) { + return isDict(dest) ? dest.get('D') : dest; + } + + var xref = this.xref; + var dests = {}, nameTreeRef, nameDictionaryRef; + var obj = this.catDict.get('Names'); + if (obj && obj.has('Dests')) { + nameTreeRef = obj.getRaw('Dests'); + } else if (this.catDict.has('Dests')) { + nameDictionaryRef = this.catDict.get('Dests'); + } + + if (nameDictionaryRef) { + // reading simple destination dictionary + obj = nameDictionaryRef; + obj.forEach(function catalogForEach(key, value) { + if (!value) { + return; + } + dests[key] = fetchDestination(value); + }); + } + if (nameTreeRef) { + var nameTree = new NameTree(nameTreeRef, xref); + var names = nameTree.getAll(); + for (var name in names) { + if (!names.hasOwnProperty(name)) { + continue; + } + dests[name] = fetchDestination(names[name]); + } + } + return shadow(this, 'destinations', dests); + }, + getDestination: function Catalog_getDestination(destinationId) { + function fetchDestination(dest) { + return isDict(dest) ? dest.get('D') : dest; + } + + var xref = this.xref; + var dest, nameTreeRef, nameDictionaryRef; + var obj = this.catDict.get('Names'); + if (obj && obj.has('Dests')) { + nameTreeRef = obj.getRaw('Dests'); + } else if (this.catDict.has('Dests')) { + nameDictionaryRef = this.catDict.get('Dests'); + } + + if (nameDictionaryRef) { + // reading simple destination dictionary + obj = nameDictionaryRef; + obj.forEach(function catalogForEach(key, value) { + if (!value) { + return; + } + if (key === destinationId) { + dest = fetchDestination(value); + } + }); + } + if (nameTreeRef) { + var nameTree = new NameTree(nameTreeRef, xref); + dest = fetchDestination(nameTree.get(destinationId)); + } + return dest; + }, + get attachments() { + var xref = this.xref; + var attachments = null, nameTreeRef; + var obj = this.catDict.get('Names'); + if (obj) { + nameTreeRef = obj.getRaw('EmbeddedFiles'); + } + + if (nameTreeRef) { + var nameTree = new NameTree(nameTreeRef, xref); + var names = nameTree.getAll(); + for (var name in names) { + if (!names.hasOwnProperty(name)) { + continue; + } + var fs = new FileSpec(names[name], xref); + if (!attachments) { + attachments = {}; + } + attachments[stringToPDFString(name)] = fs.serializable; + } + } + return shadow(this, 'attachments', attachments); + }, + get javaScript() { + var xref = this.xref; + var obj = this.catDict.get('Names'); + + var javaScript = []; + if (obj && obj.has('JavaScript')) { + var nameTree = new NameTree(obj.getRaw('JavaScript'), xref); + var names = nameTree.getAll(); + for (var name in names) { + if (!names.hasOwnProperty(name)) { + continue; + } + // We don't really use the JavaScript right now. This code is + // defensive so we don't cause errors on document load. + var jsDict = names[name]; + if (!isDict(jsDict)) { + continue; + } + var type = jsDict.get('S'); + if (!isName(type) || type.name !== 'JavaScript') { + continue; + } + var js = jsDict.get('JS'); + if (!isString(js) && !isStream(js)) { + continue; + } + if (isStream(js)) { + js = bytesToString(js.getBytes()); + } + javaScript.push(stringToPDFString(js)); + } + } + + // Append OpenAction actions to javaScript array + var openactionDict = this.catDict.get('OpenAction'); + if (isDict(openactionDict)) { + var objType = openactionDict.get('Type'); + var actionType = openactionDict.get('S'); + var action = openactionDict.get('N'); + var isPrintAction = (isName(objType) && objType.name === 'Action' && + isName(actionType) && actionType.name === 'Named' && + isName(action) && action.name === 'Print'); + + if (isPrintAction) { + javaScript.push('print(true);'); + } + } + + return shadow(this, 'javaScript', javaScript); + }, + + cleanup: function Catalog_cleanup() { + var promises = []; + this.fontCache.forEach(function (promise) { + promises.push(promise); + }); + return Promise.all(promises).then(function (translatedFonts) { + for (var i = 0, ii = translatedFonts.length; i < ii; i++) { + var font = translatedFonts[i].dict; + delete font.translated; + } + this.fontCache.clear(); + }.bind(this)); + }, + + getPage: function Catalog_getPage(pageIndex) { + if (!(pageIndex in this.pagePromises)) { + this.pagePromises[pageIndex] = this.getPageDict(pageIndex).then( + function (a) { + var dict = a[0]; + var ref = a[1]; + return new Page(this.pdfManager, this.xref, pageIndex, dict, ref, + this.fontCache); + }.bind(this) + ); + } + return this.pagePromises[pageIndex]; + }, + + getPageDict: function Catalog_getPageDict(pageIndex) { + var capability = createPromiseCapability(); + var nodesToVisit = [this.catDict.getRaw('Pages')]; + var currentPageIndex = 0; + var xref = this.xref; + var checkAllKids = false; + + function next() { + while (nodesToVisit.length) { + var currentNode = nodesToVisit.pop(); + + if (isRef(currentNode)) { + xref.fetchAsync(currentNode).then(function (obj) { + if (isDict(obj, 'Page') || (isDict(obj) && !obj.has('Kids'))) { + if (pageIndex === currentPageIndex) { + capability.resolve([obj, currentNode]); + } else { + currentPageIndex++; + next(); + } + return; + } + nodesToVisit.push(obj); + next(); + }, capability.reject); + return; + } + + // Must be a child page dictionary. + assert( + isDict(currentNode), + 'page dictionary kid reference points to wrong type of object' + ); + var count = currentNode.get('Count'); + // If the current node doesn't have any children, avoid getting stuck + // in an empty node further down in the tree (see issue5644.pdf). + if (count === 0) { + checkAllKids = true; + } + // Skip nodes where the page can't be. + if (currentPageIndex + count <= pageIndex) { + currentPageIndex += count; + continue; + } + + var kids = currentNode.get('Kids'); + assert(isArray(kids), 'page dictionary kids object is not an array'); + if (!checkAllKids && count === kids.length) { + // Nodes that don't have the page have been skipped and this is the + // bottom of the tree which means the page requested must be a + // descendant of this pages node. Ideally we would just resolve the + // promise with the page ref here, but there is the case where more + // pages nodes could link to single a page (see issue 3666 pdf). To + // handle this push it back on the queue so if it is a pages node it + // will be descended into. + nodesToVisit = [kids[pageIndex - currentPageIndex]]; + currentPageIndex = pageIndex; + continue; + } else { + for (var last = kids.length - 1; last >= 0; last--) { + nodesToVisit.push(kids[last]); + } + } + } + capability.reject('Page index ' + pageIndex + ' not found.'); + } + next(); + return capability.promise; + }, + + getPageIndex: function Catalog_getPageIndex(ref) { + // The page tree nodes have the count of all the leaves below them. To get + // how many pages are before we just have to walk up the tree and keep + // adding the count of siblings to the left of the node. + var xref = this.xref; + function pagesBeforeRef(kidRef) { + var total = 0; + var parentRef; + return xref.fetchAsync(kidRef).then(function (node) { + if (!node) { + return null; + } + parentRef = node.getRaw('Parent'); + return node.getAsync('Parent'); + }).then(function (parent) { + if (!parent) { + return null; + } + return parent.getAsync('Kids'); + }).then(function (kids) { + if (!kids) { + return null; + } + var kidPromises = []; + var found = false; + for (var i = 0; i < kids.length; i++) { + var kid = kids[i]; + assert(isRef(kid), 'kids must be a ref'); + if (kid.num === kidRef.num) { + found = true; + break; + } + kidPromises.push(xref.fetchAsync(kid).then(function (kid) { + if (kid.has('Count')) { + var count = kid.get('Count'); + total += count; + } else { // page leaf node + total++; + } + })); + } + if (!found) { + error('kid ref not found in parents kids'); + } + return Promise.all(kidPromises).then(function () { + return [total, parentRef]; + }); + }); + } + + var total = 0; + function next(ref) { + return pagesBeforeRef(ref).then(function (args) { + if (!args) { + return total; + } + var count = args[0]; + var parentRef = args[1]; + total += count; + return next(parentRef); + }); + } + + return next(ref); + } + }; + + return Catalog; +})(); + +var XRef = (function XRefClosure() { + function XRef(stream, password) { + this.stream = stream; + this.entries = []; + this.xrefstms = {}; + // prepare the XRef cache + this.cache = []; + this.password = password; + this.stats = { + streamTypes: [], + fontTypes: [] + }; + } + + XRef.prototype = { + setStartXRef: function XRef_setStartXRef(startXRef) { + // Store the starting positions of xref tables as we process them + // so we can recover from missing data errors + this.startXRefQueue = [startXRef]; + }, + + parse: function XRef_parse(recoveryMode) { + var trailerDict; + if (!recoveryMode) { + trailerDict = this.readXRef(); + } else { + warn('Indexing all PDF objects'); + trailerDict = this.indexObjects(); + } + trailerDict.assignXref(this); + this.trailer = trailerDict; + var encrypt = trailerDict.get('Encrypt'); + if (encrypt) { + var ids = trailerDict.get('ID'); + var fileId = (ids && ids.length) ? ids[0] : ''; + this.encrypt = new CipherTransformFactory(encrypt, fileId, + this.password); + } + + // get the root dictionary (catalog) object + if (!(this.root = trailerDict.get('Root'))) { + error('Invalid root reference'); + } + }, + + processXRefTable: function XRef_processXRefTable(parser) { + if (!('tableState' in this)) { + // Stores state of the table as we process it so we can resume + // from middle of table in case of missing data error + this.tableState = { + entryNum: 0, + streamPos: parser.lexer.stream.pos, + parserBuf1: parser.buf1, + parserBuf2: parser.buf2 + }; + } + + var obj = this.readXRefTable(parser); + + // Sanity check + if (!isCmd(obj, 'trailer')) { + error('Invalid XRef table: could not find trailer dictionary'); + } + // Read trailer dictionary, e.g. + // trailer + // << /Size 22 + // /Root 20R + // /Info 10R + // /ID [ <81b14aafa313db63dbd6f981e49f94f4> ] + // >> + // The parser goes through the entire stream << ... >> and provides + // a getter interface for the key-value table + var dict = parser.getObj(); + + // The pdflib PDF generator can generate a nested trailer dictionary + if (!isDict(dict) && dict.dict) { + dict = dict.dict; + } + if (!isDict(dict)) { + error('Invalid XRef table: could not parse trailer dictionary'); + } + delete this.tableState; + + return dict; + }, + + readXRefTable: function XRef_readXRefTable(parser) { + // Example of cross-reference table: + // xref + // 0 1 <-- subsection header (first obj #, obj count) + // 0000000000 65535 f <-- actual object (offset, generation #, f/n) + // 23 2 <-- subsection header ... and so on ... + // 0000025518 00002 n + // 0000025635 00000 n + // trailer + // ... + + var stream = parser.lexer.stream; + var tableState = this.tableState; + stream.pos = tableState.streamPos; + parser.buf1 = tableState.parserBuf1; + parser.buf2 = tableState.parserBuf2; + + // Outer loop is over subsection headers + var obj; + + while (true) { + if (!('firstEntryNum' in tableState) || !('entryCount' in tableState)) { + if (isCmd(obj = parser.getObj(), 'trailer')) { + break; + } + tableState.firstEntryNum = obj; + tableState.entryCount = parser.getObj(); + } + + var first = tableState.firstEntryNum; + var count = tableState.entryCount; + if (!isInt(first) || !isInt(count)) { + error('Invalid XRef table: wrong types in subsection header'); + } + // Inner loop is over objects themselves + for (var i = tableState.entryNum; i < count; i++) { + tableState.streamPos = stream.pos; + tableState.entryNum = i; + tableState.parserBuf1 = parser.buf1; + tableState.parserBuf2 = parser.buf2; + + var entry = {}; + entry.offset = parser.getObj(); + entry.gen = parser.getObj(); + var type = parser.getObj(); + + if (isCmd(type, 'f')) { + entry.free = true; + } else if (isCmd(type, 'n')) { + entry.uncompressed = true; + } + + // Validate entry obj + if (!isInt(entry.offset) || !isInt(entry.gen) || + !(entry.free || entry.uncompressed)) { + error('Invalid entry in XRef subsection: ' + first + ', ' + count); + } + + if (!this.entries[i + first]) { + this.entries[i + first] = entry; + } + } + + tableState.entryNum = 0; + tableState.streamPos = stream.pos; + tableState.parserBuf1 = parser.buf1; + tableState.parserBuf2 = parser.buf2; + delete tableState.firstEntryNum; + delete tableState.entryCount; + } + + // Per issue 3248: hp scanners generate bad XRef + if (first === 1 && this.entries[1] && this.entries[1].free) { + // shifting the entries + this.entries.shift(); + } + + // Sanity check: as per spec, first object must be free + if (this.entries[0] && !this.entries[0].free) { + error('Invalid XRef table: unexpected first object'); + } + return obj; + }, + + processXRefStream: function XRef_processXRefStream(stream) { + if (!('streamState' in this)) { + // Stores state of the stream as we process it so we can resume + // from middle of stream in case of missing data error + var streamParameters = stream.dict; + var byteWidths = streamParameters.get('W'); + var range = streamParameters.get('Index'); + if (!range) { + range = [0, streamParameters.get('Size')]; + } + + this.streamState = { + entryRanges: range, + byteWidths: byteWidths, + entryNum: 0, + streamPos: stream.pos + }; + } + this.readXRefStream(stream); + delete this.streamState; + + return stream.dict; + }, + + readXRefStream: function XRef_readXRefStream(stream) { + var i, j; + var streamState = this.streamState; + stream.pos = streamState.streamPos; + + var byteWidths = streamState.byteWidths; + var typeFieldWidth = byteWidths[0]; + var offsetFieldWidth = byteWidths[1]; + var generationFieldWidth = byteWidths[2]; + + var entryRanges = streamState.entryRanges; + while (entryRanges.length > 0) { + var first = entryRanges[0]; + var n = entryRanges[1]; + + if (!isInt(first) || !isInt(n)) { + error('Invalid XRef range fields: ' + first + ', ' + n); + } + if (!isInt(typeFieldWidth) || !isInt(offsetFieldWidth) || + !isInt(generationFieldWidth)) { + error('Invalid XRef entry fields length: ' + first + ', ' + n); + } + for (i = streamState.entryNum; i < n; ++i) { + streamState.entryNum = i; + streamState.streamPos = stream.pos; + + var type = 0, offset = 0, generation = 0; + for (j = 0; j < typeFieldWidth; ++j) { + type = (type << 8) | stream.getByte(); + } + // if type field is absent, its default value is 1 + if (typeFieldWidth === 0) { + type = 1; + } + for (j = 0; j < offsetFieldWidth; ++j) { + offset = (offset << 8) | stream.getByte(); + } + for (j = 0; j < generationFieldWidth; ++j) { + generation = (generation << 8) | stream.getByte(); + } + var entry = {}; + entry.offset = offset; + entry.gen = generation; + switch (type) { + case 0: + entry.free = true; + break; + case 1: + entry.uncompressed = true; + break; + case 2: + break; + default: + error('Invalid XRef entry type: ' + type); + } + if (!this.entries[first + i]) { + this.entries[first + i] = entry; + } + } + + streamState.entryNum = 0; + streamState.streamPos = stream.pos; + entryRanges.splice(0, 2); + } + }, + + indexObjects: function XRef_indexObjects() { + // Simple scan through the PDF content to find objects, + // trailers and XRef streams. + function readToken(data, offset) { + var token = '', ch = data[offset]; + while (ch !== 13 && ch !== 10) { + if (++offset >= data.length) { + break; + } + token += String.fromCharCode(ch); + ch = data[offset]; + } + return token; + } + function skipUntil(data, offset, what) { + var length = what.length, dataLength = data.length; + var skipped = 0; + // finding byte sequence + while (offset < dataLength) { + var i = 0; + while (i < length && data[offset + i] === what[i]) { + ++i; + } + if (i >= length) { + break; // sequence found + } + offset++; + skipped++; + } + return skipped; + } + var trailerBytes = new Uint8Array([116, 114, 97, 105, 108, 101, 114]); + var startxrefBytes = new Uint8Array([115, 116, 97, 114, 116, 120, 114, + 101, 102]); + var endobjBytes = new Uint8Array([101, 110, 100, 111, 98, 106]); + var xrefBytes = new Uint8Array([47, 88, 82, 101, 102]); + + var stream = this.stream; + stream.pos = 0; + var buffer = stream.getBytes(); + var position = stream.start, length = buffer.length; + var trailers = [], xrefStms = []; + while (position < length) { + var ch = buffer[position]; + if (ch === 32 || ch === 9 || ch === 13 || ch === 10) { + ++position; + continue; + } + if (ch === 37) { // %-comment + do { + ++position; + if (position >= length) { + break; + } + ch = buffer[position]; + } while (ch !== 13 && ch !== 10); + continue; + } + var token = readToken(buffer, position); + var m; + if (token === 'xref') { + position += skipUntil(buffer, position, trailerBytes); + trailers.push(position); + position += skipUntil(buffer, position, startxrefBytes); + } else if ((m = /^(\d+)\s+(\d+)\s+obj\b/.exec(token))) { + this.entries[m[1]] = { + offset: position, + gen: m[2] | 0, + uncompressed: true + }; + + var contentLength = skipUntil(buffer, position, endobjBytes) + 7; + var content = buffer.subarray(position, position + contentLength); + + // checking XRef stream suspect + // (it shall have '/XRef' and next char is not a letter) + var xrefTagOffset = skipUntil(content, 0, xrefBytes); + if (xrefTagOffset < contentLength && + content[xrefTagOffset + 5] < 64) { + xrefStms.push(position); + this.xrefstms[position] = 1; // don't read it recursively + } + + position += contentLength; + } else { + position += token.length + 1; + } + } + // reading XRef streams + var i, ii; + for (i = 0, ii = xrefStms.length; i < ii; ++i) { + this.startXRefQueue.push(xrefStms[i]); + this.readXRef(/* recoveryMode */ true); + } + // finding main trailer + var dict; + for (i = 0, ii = trailers.length; i < ii; ++i) { + stream.pos = trailers[i]; + var parser = new Parser(new Lexer(stream), true, this); + var obj = parser.getObj(); + if (!isCmd(obj, 'trailer')) { + continue; + } + // read the trailer dictionary + if (!isDict(dict = parser.getObj())) { + continue; + } + // taking the first one with 'ID' + if (dict.has('ID')) { + return dict; + } + } + // no tailer with 'ID', taking last one (if exists) + if (dict) { + return dict; + } + // nothing helps + // calling error() would reject worker with an UnknownErrorException. + throw new InvalidPDFException('Invalid PDF structure'); + }, + + readXRef: function XRef_readXRef(recoveryMode) { + var stream = this.stream; + + try { + while (this.startXRefQueue.length) { + var startXRef = this.startXRefQueue[0]; + + stream.pos = startXRef + stream.start; + + var parser = new Parser(new Lexer(stream), true, this); + var obj = parser.getObj(); + var dict; + + // Get dictionary + if (isCmd(obj, 'xref')) { + // Parse end-of-file XRef + dict = this.processXRefTable(parser); + if (!this.topDict) { + this.topDict = dict; + } + + // Recursively get other XRefs 'XRefStm', if any + obj = dict.get('XRefStm'); + if (isInt(obj)) { + var pos = obj; + // ignore previously loaded xref streams + // (possible infinite recursion) + if (!(pos in this.xrefstms)) { + this.xrefstms[pos] = 1; + this.startXRefQueue.push(pos); + } + } + } else if (isInt(obj)) { + // Parse in-stream XRef + if (!isInt(parser.getObj()) || + !isCmd(parser.getObj(), 'obj') || + !isStream(obj = parser.getObj())) { + error('Invalid XRef stream'); + } + dict = this.processXRefStream(obj); + if (!this.topDict) { + this.topDict = dict; + } + if (!dict) { + error('Failed to read XRef stream'); + } + } else { + error('Invalid XRef stream header'); + } + + // Recursively get previous dictionary, if any + obj = dict.get('Prev'); + if (isInt(obj)) { + this.startXRefQueue.push(obj); + } else if (isRef(obj)) { + // The spec says Prev must not be a reference, i.e. "/Prev NNN" + // This is a fallback for non-compliant PDFs, i.e. "/Prev NNN 0 R" + this.startXRefQueue.push(obj.num); + } + + this.startXRefQueue.shift(); + } + + return this.topDict; + } catch (e) { + if (e instanceof MissingDataException) { + throw e; + } + info('(while reading XRef): ' + e); + } + + if (recoveryMode) { + return; + } + throw new XRefParseException(); + }, + + getEntry: function XRef_getEntry(i) { + var xrefEntry = this.entries[i]; + if (xrefEntry && !xrefEntry.free && xrefEntry.offset) { + return xrefEntry; + } + return null; + }, + + fetchIfRef: function XRef_fetchIfRef(obj) { + if (!isRef(obj)) { + return obj; + } + return this.fetch(obj); + }, + + fetch: function XRef_fetch(ref, suppressEncryption) { + assert(isRef(ref), 'ref object is not a reference'); + var num = ref.num; + if (num in this.cache) { + var cacheEntry = this.cache[num]; + return cacheEntry; + } + + var xrefEntry = this.getEntry(num); + + // the referenced entry can be free + if (xrefEntry === null) { + return (this.cache[num] = null); + } + + if (xrefEntry.uncompressed) { + xrefEntry = this.fetchUncompressed(ref, xrefEntry, suppressEncryption); + } else { + xrefEntry = this.fetchCompressed(xrefEntry, suppressEncryption); + } + if (isDict(xrefEntry)){ + xrefEntry.objId = ref.toString(); + } else if (isStream(xrefEntry)) { + xrefEntry.dict.objId = ref.toString(); + } + return xrefEntry; + }, + + fetchUncompressed: function XRef_fetchUncompressed(ref, xrefEntry, + suppressEncryption) { + var gen = ref.gen; + var num = ref.num; + if (xrefEntry.gen !== gen) { + error('inconsistent generation in XRef'); + } + var stream = this.stream.makeSubStream(xrefEntry.offset + + this.stream.start); + var parser = new Parser(new Lexer(stream), true, this); + var obj1 = parser.getObj(); + var obj2 = parser.getObj(); + var obj3 = parser.getObj(); + if (!isInt(obj1) || parseInt(obj1, 10) !== num || + !isInt(obj2) || parseInt(obj2, 10) !== gen || + !isCmd(obj3)) { + error('bad XRef entry'); + } + if (!isCmd(obj3, 'obj')) { + // some bad PDFs use "obj1234" and really mean 1234 + if (obj3.cmd.indexOf('obj') === 0) { + num = parseInt(obj3.cmd.substring(3), 10); + if (!isNaN(num)) { + return num; + } + } + error('bad XRef entry'); + } + if (this.encrypt && !suppressEncryption) { + xrefEntry = parser.getObj(this.encrypt.createCipherTransform(num, gen)); + } else { + xrefEntry = parser.getObj(); + } + if (!isStream(xrefEntry)) { + this.cache[num] = xrefEntry; + } + return xrefEntry; + }, + + fetchCompressed: function XRef_fetchCompressed(xrefEntry, + suppressEncryption) { + var tableOffset = xrefEntry.offset; + var stream = this.fetch(new Ref(tableOffset, 0)); + if (!isStream(stream)) { + error('bad ObjStm stream'); + } + var first = stream.dict.get('First'); + var n = stream.dict.get('N'); + if (!isInt(first) || !isInt(n)) { + error('invalid first and n parameters for ObjStm stream'); + } + var parser = new Parser(new Lexer(stream), false, this); + parser.allowStreams = true; + var i, entries = [], num, nums = []; + // read the object numbers to populate cache + for (i = 0; i < n; ++i) { + num = parser.getObj(); + if (!isInt(num)) { + error('invalid object number in the ObjStm stream: ' + num); + } + nums.push(num); + var offset = parser.getObj(); + if (!isInt(offset)) { + error('invalid object offset in the ObjStm stream: ' + offset); + } + } + // read stream objects for cache + for (i = 0; i < n; ++i) { + entries.push(parser.getObj()); + num = nums[i]; + var entry = this.entries[num]; + if (entry && entry.offset === tableOffset && entry.gen === i) { + this.cache[num] = entries[i]; + } + } + xrefEntry = entries[xrefEntry.gen]; + if (xrefEntry === undefined) { + error('bad XRef entry for compressed object'); + } + return xrefEntry; + }, + + fetchIfRefAsync: function XRef_fetchIfRefAsync(obj) { + if (!isRef(obj)) { + return Promise.resolve(obj); + } + return this.fetchAsync(obj); + }, + + fetchAsync: function XRef_fetchAsync(ref, suppressEncryption) { + var streamManager = this.stream.manager; + var xref = this; + return new Promise(function tryFetch(resolve, reject) { + try { + resolve(xref.fetch(ref, suppressEncryption)); + } catch (e) { + if (e instanceof MissingDataException) { + streamManager.requestRange(e.begin, e.end, function () { + tryFetch(resolve, reject); + }); + return; + } + reject(e); + } + }); + }, + + getCatalogObj: function XRef_getCatalogObj() { + return this.root; + } + }; + + return XRef; +})(); + +/** + * A NameTree is like a Dict but has some advantageous properties, see the + * spec (7.9.6) for more details. + * TODO: implement all the Dict functions and make this more efficent. + */ +var NameTree = (function NameTreeClosure() { + function NameTree(root, xref) { + this.root = root; + this.xref = xref; + } + + NameTree.prototype = { + getAll: function NameTree_getAll() { + var dict = {}; + if (!this.root) { + return dict; + } + var xref = this.xref; + // reading name tree + var processed = new RefSet(); + processed.put(this.root); + var queue = [this.root]; + while (queue.length > 0) { + var i, n; + var obj = xref.fetchIfRef(queue.shift()); + if (!isDict(obj)) { + continue; + } + if (obj.has('Kids')) { + var kids = obj.get('Kids'); + for (i = 0, n = kids.length; i < n; i++) { + var kid = kids[i]; + if (processed.has(kid)) { + error('invalid destinations'); + } + queue.push(kid); + processed.put(kid); + } + continue; + } + var names = obj.get('Names'); + if (names) { + for (i = 0, n = names.length; i < n; i += 2) { + dict[names[i]] = xref.fetchIfRef(names[i + 1]); + } + } + } + return dict; + }, + + get: function NameTree_get(destinationId) { + if (!this.root) { + return null; + } + + var xref = this.xref; + var kidsOrNames = xref.fetchIfRef(this.root); + var loopCount = 0; + var MAX_NAMES_LEVELS = 10; + var l, r, m; + + // Perform a binary search to quickly find the entry that + // contains the named destination we are looking for. + while (kidsOrNames.has('Kids')) { + loopCount++; + if (loopCount > MAX_NAMES_LEVELS) { + warn('Search depth limit for named destionations has been reached.'); + return null; + } + + var kids = kidsOrNames.get('Kids'); + if (!isArray(kids)) { + return null; + } + + l = 0; + r = kids.length - 1; + while (l <= r) { + m = (l + r) >> 1; + var kid = xref.fetchIfRef(kids[m]); + var limits = kid.get('Limits'); + + if (destinationId < limits[0]) { + r = m - 1; + } else if (destinationId > limits[1]) { + l = m + 1; + } else { + kidsOrNames = xref.fetchIfRef(kids[m]); + break; + } + } + if (l > r) { + return null; + } + } + + // If we get here, then we have found the right entry. Now + // go through the named destinations in the Named dictionary + // until we find the exact destination we're looking for. + var names = kidsOrNames.get('Names'); + if (isArray(names)) { + // Perform a binary search to reduce the lookup time. + l = 0; + r = names.length - 2; + while (l <= r) { + // Check only even indices (0, 2, 4, ...) because the + // odd indices contain the actual D array. + m = (l + r) & ~1; + if (destinationId < names[m]) { + r = m - 2; + } else if (destinationId > names[m]) { + l = m + 2; + } else { + return xref.fetchIfRef(names[m + 1]); + } + } + } + return null; + } + }; + return NameTree; +})(); + +/** + * "A PDF file can refer to the contents of another file by using a File + * Specification (PDF 1.1)", see the spec (7.11) for more details. + * NOTE: Only embedded files are supported (as part of the attachments support) + * TODO: support the 'URL' file system (with caching if !/V), portable + * collections attributes and related files (/RF) + */ +var FileSpec = (function FileSpecClosure() { + function FileSpec(root, xref) { + if (!root || !isDict(root)) { + return; + } + this.xref = xref; + this.root = root; + if (root.has('FS')) { + this.fs = root.get('FS'); + } + this.description = root.has('Desc') ? + stringToPDFString(root.get('Desc')) : + ''; + if (root.has('RF')) { + warn('Related file specifications are not supported'); + } + this.contentAvailable = true; + if (!root.has('EF')) { + this.contentAvailable = false; + warn('Non-embedded file specifications are not supported'); + } + } + + function pickPlatformItem(dict) { + // Look for the filename in this order: + // UF, F, Unix, Mac, DOS + if (dict.has('UF')) { + return dict.get('UF'); + } else if (dict.has('F')) { + return dict.get('F'); + } else if (dict.has('Unix')) { + return dict.get('Unix'); + } else if (dict.has('Mac')) { + return dict.get('Mac'); + } else if (dict.has('DOS')) { + return dict.get('DOS'); + } else { + return null; + } + } + + FileSpec.prototype = { + get filename() { + if (!this._filename && this.root) { + var filename = pickPlatformItem(this.root) || 'unnamed'; + this._filename = stringToPDFString(filename). + replace(/\\\\/g, '\\'). + replace(/\\\//g, '/'). + replace(/\\/g, '/'); + } + return this._filename; + }, + get content() { + if (!this.contentAvailable) { + return null; + } + if (!this.contentRef && this.root) { + this.contentRef = pickPlatformItem(this.root.get('EF')); + } + var content = null; + if (this.contentRef) { + var xref = this.xref; + var fileObj = xref.fetchIfRef(this.contentRef); + if (fileObj && isStream(fileObj)) { + content = fileObj.getBytes(); + } else { + warn('Embedded file specification points to non-existing/invalid ' + + 'content'); + } + } else { + warn('Embedded file specification does not have a content'); + } + return content; + }, + get serializable() { + return { + filename: this.filename, + content: this.content + }; + } + }; + return FileSpec; +})(); + +/** + * A helper for loading missing data in object graphs. It traverses the graph + * depth first and queues up any objects that have missing data. Once it has + * has traversed as many objects that are available it attempts to bundle the + * missing data requests and then resume from the nodes that weren't ready. + * + * NOTE: It provides protection from circular references by keeping track of + * of loaded references. However, you must be careful not to load any graphs + * that have references to the catalog or other pages since that will cause the + * entire PDF document object graph to be traversed. + */ +var ObjectLoader = (function() { + function mayHaveChildren(value) { + return isRef(value) || isDict(value) || isArray(value) || isStream(value); + } + + function addChildren(node, nodesToVisit) { + var value; + if (isDict(node) || isStream(node)) { + var map; + if (isDict(node)) { + map = node.map; + } else { + map = node.dict.map; + } + for (var key in map) { + value = map[key]; + if (mayHaveChildren(value)) { + nodesToVisit.push(value); + } + } + } else if (isArray(node)) { + for (var i = 0, ii = node.length; i < ii; i++) { + value = node[i]; + if (mayHaveChildren(value)) { + nodesToVisit.push(value); + } + } + } + } + + function ObjectLoader(obj, keys, xref) { + this.obj = obj; + this.keys = keys; + this.xref = xref; + this.refSet = null; + } + + ObjectLoader.prototype = { + load: function ObjectLoader_load() { + var keys = this.keys; + this.capability = createPromiseCapability(); + // Don't walk the graph if all the data is already loaded. + if (!(this.xref.stream instanceof ChunkedStream) || + this.xref.stream.getMissingChunks().length === 0) { + this.capability.resolve(); + return this.capability.promise; + } + + this.refSet = new RefSet(); + // Setup the initial nodes to visit. + var nodesToVisit = []; + for (var i = 0; i < keys.length; i++) { + nodesToVisit.push(this.obj[keys[i]]); + } + + this.walk(nodesToVisit); + return this.capability.promise; + }, + + walk: function ObjectLoader_walk(nodesToVisit) { + var nodesToRevisit = []; + var pendingRequests = []; + // DFS walk of the object graph. + while (nodesToVisit.length) { + var currentNode = nodesToVisit.pop(); + + // Only references or chunked streams can cause missing data exceptions. + if (isRef(currentNode)) { + // Skip nodes that have already been visited. + if (this.refSet.has(currentNode)) { + continue; + } + try { + var ref = currentNode; + this.refSet.put(ref); + currentNode = this.xref.fetch(currentNode); + } catch (e) { + if (!(e instanceof MissingDataException)) { + throw e; + } + nodesToRevisit.push(currentNode); + pendingRequests.push({ begin: e.begin, end: e.end }); + } + } + if (currentNode && currentNode.getBaseStreams) { + var baseStreams = currentNode.getBaseStreams(); + var foundMissingData = false; + for (var i = 0; i < baseStreams.length; i++) { + var stream = baseStreams[i]; + if (stream.getMissingChunks && stream.getMissingChunks().length) { + foundMissingData = true; + pendingRequests.push({ + begin: stream.start, + end: stream.end + }); + } + } + if (foundMissingData) { + nodesToRevisit.push(currentNode); + } + } + + addChildren(currentNode, nodesToVisit); + } + + if (pendingRequests.length) { + this.xref.stream.manager.requestRanges(pendingRequests, + function pendingRequestCallback() { + nodesToVisit = nodesToRevisit; + for (var i = 0; i < nodesToRevisit.length; i++) { + var node = nodesToRevisit[i]; + // Remove any reference nodes from the currrent refset so they + // aren't skipped when we revist them. + if (isRef(node)) { + this.refSet.remove(node); + } + } + this.walk(nodesToVisit); + }.bind(this)); + return; + } + // Everything is loaded. + this.refSet = null; + this.capability.resolve(); + } + }; + + return ObjectLoader; +})(); + + +var ISOAdobeCharset = [ + '.notdef', 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', + 'percent', 'ampersand', 'quoteright', 'parenleft', 'parenright', + 'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash', 'zero', + 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', + 'nine', 'colon', 'semicolon', 'less', 'equal', 'greater', 'question', + 'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', + 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', + 'bracketleft', 'backslash', 'bracketright', 'asciicircum', 'underscore', + 'quoteleft', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', + 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', + 'braceleft', 'bar', 'braceright', 'asciitilde', 'exclamdown', 'cent', + 'sterling', 'fraction', 'yen', 'florin', 'section', 'currency', + 'quotesingle', 'quotedblleft', 'guillemotleft', 'guilsinglleft', + 'guilsinglright', 'fi', 'fl', 'endash', 'dagger', 'daggerdbl', + 'periodcentered', 'paragraph', 'bullet', 'quotesinglbase', + 'quotedblbase', 'quotedblright', 'guillemotright', 'ellipsis', + 'perthousand', 'questiondown', 'grave', 'acute', 'circumflex', 'tilde', + 'macron', 'breve', 'dotaccent', 'dieresis', 'ring', 'cedilla', + 'hungarumlaut', 'ogonek', 'caron', 'emdash', 'AE', 'ordfeminine', + 'Lslash', 'Oslash', 'OE', 'ordmasculine', 'ae', 'dotlessi', 'lslash', + 'oslash', 'oe', 'germandbls', 'onesuperior', 'logicalnot', 'mu', + 'trademark', 'Eth', 'onehalf', 'plusminus', 'Thorn', 'onequarter', + 'divide', 'brokenbar', 'degree', 'thorn', 'threequarters', 'twosuperior', + 'registered', 'minus', 'eth', 'multiply', 'threesuperior', 'copyright', + 'Aacute', 'Acircumflex', 'Adieresis', 'Agrave', 'Aring', 'Atilde', + 'Ccedilla', 'Eacute', 'Ecircumflex', 'Edieresis', 'Egrave', 'Iacute', + 'Icircumflex', 'Idieresis', 'Igrave', 'Ntilde', 'Oacute', 'Ocircumflex', + 'Odieresis', 'Ograve', 'Otilde', 'Scaron', 'Uacute', 'Ucircumflex', + 'Udieresis', 'Ugrave', 'Yacute', 'Ydieresis', 'Zcaron', 'aacute', + 'acircumflex', 'adieresis', 'agrave', 'aring', 'atilde', 'ccedilla', + 'eacute', 'ecircumflex', 'edieresis', 'egrave', 'iacute', 'icircumflex', + 'idieresis', 'igrave', 'ntilde', 'oacute', 'ocircumflex', 'odieresis', + 'ograve', 'otilde', 'scaron', 'uacute', 'ucircumflex', 'udieresis', + 'ugrave', 'yacute', 'ydieresis', 'zcaron' +]; + +var ExpertCharset = [ + '.notdef', 'space', 'exclamsmall', 'Hungarumlautsmall', 'dollaroldstyle', + 'dollarsuperior', 'ampersandsmall', 'Acutesmall', 'parenleftsuperior', + 'parenrightsuperior', 'twodotenleader', 'onedotenleader', 'comma', + 'hyphen', 'period', 'fraction', 'zerooldstyle', 'oneoldstyle', + 'twooldstyle', 'threeoldstyle', 'fouroldstyle', 'fiveoldstyle', + 'sixoldstyle', 'sevenoldstyle', 'eightoldstyle', 'nineoldstyle', + 'colon', 'semicolon', 'commasuperior', 'threequartersemdash', + 'periodsuperior', 'questionsmall', 'asuperior', 'bsuperior', + 'centsuperior', 'dsuperior', 'esuperior', 'isuperior', 'lsuperior', + 'msuperior', 'nsuperior', 'osuperior', 'rsuperior', 'ssuperior', + 'tsuperior', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'parenleftinferior', + 'parenrightinferior', 'Circumflexsmall', 'hyphensuperior', 'Gravesmall', + 'Asmall', 'Bsmall', 'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall', + 'Hsmall', 'Ismall', 'Jsmall', 'Ksmall', 'Lsmall', 'Msmall', 'Nsmall', + 'Osmall', 'Psmall', 'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall', + 'Vsmall', 'Wsmall', 'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary', + 'onefitted', 'rupiah', 'Tildesmall', 'exclamdownsmall', 'centoldstyle', + 'Lslashsmall', 'Scaronsmall', 'Zcaronsmall', 'Dieresissmall', + 'Brevesmall', 'Caronsmall', 'Dotaccentsmall', 'Macronsmall', + 'figuredash', 'hypheninferior', 'Ogoneksmall', 'Ringsmall', + 'Cedillasmall', 'onequarter', 'onehalf', 'threequarters', + 'questiondownsmall', 'oneeighth', 'threeeighths', 'fiveeighths', + 'seveneighths', 'onethird', 'twothirds', 'zerosuperior', 'onesuperior', + 'twosuperior', 'threesuperior', 'foursuperior', 'fivesuperior', + 'sixsuperior', 'sevensuperior', 'eightsuperior', 'ninesuperior', + 'zeroinferior', 'oneinferior', 'twoinferior', 'threeinferior', + 'fourinferior', 'fiveinferior', 'sixinferior', 'seveninferior', + 'eightinferior', 'nineinferior', 'centinferior', 'dollarinferior', + 'periodinferior', 'commainferior', 'Agravesmall', 'Aacutesmall', + 'Acircumflexsmall', 'Atildesmall', 'Adieresissmall', 'Aringsmall', + 'AEsmall', 'Ccedillasmall', 'Egravesmall', 'Eacutesmall', + 'Ecircumflexsmall', 'Edieresissmall', 'Igravesmall', 'Iacutesmall', + 'Icircumflexsmall', 'Idieresissmall', 'Ethsmall', 'Ntildesmall', + 'Ogravesmall', 'Oacutesmall', 'Ocircumflexsmall', 'Otildesmall', + 'Odieresissmall', 'OEsmall', 'Oslashsmall', 'Ugravesmall', 'Uacutesmall', + 'Ucircumflexsmall', 'Udieresissmall', 'Yacutesmall', 'Thornsmall', + 'Ydieresissmall' +]; + +var ExpertSubsetCharset = [ + '.notdef', 'space', 'dollaroldstyle', 'dollarsuperior', + 'parenleftsuperior', 'parenrightsuperior', 'twodotenleader', + 'onedotenleader', 'comma', 'hyphen', 'period', 'fraction', + 'zerooldstyle', 'oneoldstyle', 'twooldstyle', 'threeoldstyle', + 'fouroldstyle', 'fiveoldstyle', 'sixoldstyle', 'sevenoldstyle', + 'eightoldstyle', 'nineoldstyle', 'colon', 'semicolon', 'commasuperior', + 'threequartersemdash', 'periodsuperior', 'asuperior', 'bsuperior', + 'centsuperior', 'dsuperior', 'esuperior', 'isuperior', 'lsuperior', + 'msuperior', 'nsuperior', 'osuperior', 'rsuperior', 'ssuperior', + 'tsuperior', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'parenleftinferior', + 'parenrightinferior', 'hyphensuperior', 'colonmonetary', 'onefitted', + 'rupiah', 'centoldstyle', 'figuredash', 'hypheninferior', 'onequarter', + 'onehalf', 'threequarters', 'oneeighth', 'threeeighths', 'fiveeighths', + 'seveneighths', 'onethird', 'twothirds', 'zerosuperior', 'onesuperior', + 'twosuperior', 'threesuperior', 'foursuperior', 'fivesuperior', + 'sixsuperior', 'sevensuperior', 'eightsuperior', 'ninesuperior', + 'zeroinferior', 'oneinferior', 'twoinferior', 'threeinferior', + 'fourinferior', 'fiveinferior', 'sixinferior', 'seveninferior', + 'eightinferior', 'nineinferior', 'centinferior', 'dollarinferior', + 'periodinferior', 'commainferior' +]; + + +var DEFAULT_ICON_SIZE = 22; // px +var SUPPORTED_TYPES = ['Link', 'Text', 'Widget']; + +var Annotation = (function AnnotationClosure() { + // 12.5.5: Algorithm: Appearance streams + function getTransformMatrix(rect, bbox, matrix) { + var bounds = Util.getAxialAlignedBoundingBox(bbox, matrix); + var minX = bounds[0]; + var minY = bounds[1]; + var maxX = bounds[2]; + var maxY = bounds[3]; + + if (minX === maxX || minY === maxY) { + // From real-life file, bbox was [0, 0, 0, 0]. In this case, + // just apply the transform for rect + return [1, 0, 0, 1, rect[0], rect[1]]; + } + + var xRatio = (rect[2] - rect[0]) / (maxX - minX); + var yRatio = (rect[3] - rect[1]) / (maxY - minY); + return [ + xRatio, + 0, + 0, + yRatio, + rect[0] - minX * xRatio, + rect[1] - minY * yRatio + ]; + } + + function getDefaultAppearance(dict) { + var appearanceState = dict.get('AP'); + if (!isDict(appearanceState)) { + return; + } + + var appearance; + var appearances = appearanceState.get('N'); + if (isDict(appearances)) { + var as = dict.get('AS'); + if (as && appearances.has(as.name)) { + appearance = appearances.get(as.name); + } + } else { + appearance = appearances; + } + return appearance; + } + + function Annotation(params) { + var dict = params.dict; + var data = this.data = {}; + + data.subtype = dict.get('Subtype').name; + var rect = dict.get('Rect') || [0, 0, 0, 0]; + data.rect = Util.normalizeRect(rect); + data.annotationFlags = dict.get('F'); + + var color = dict.get('C'); + if (!color) { + // The PDF spec does not mention how a missing color array is interpreted. + // Adobe Reader seems to default to black in this case. + data.color = [0, 0, 0]; + } else if (isArray(color)) { + switch (color.length) { + case 0: + // Empty array denotes transparent border. + data.color = null; + break; + case 1: + // TODO: implement DeviceGray + break; + case 3: + data.color = color; + break; + case 4: + // TODO: implement DeviceCMYK + break; + } + } + + // Some types of annotations have border style dict which has more + // info than the border array + if (dict.has('BS')) { + var borderStyle = dict.get('BS'); + data.borderWidth = borderStyle.has('W') ? borderStyle.get('W') : 1; + } else { + var borderArray = dict.get('Border') || [0, 0, 1]; + data.borderWidth = borderArray[2] || 0; + + // TODO: implement proper support for annotations with line dash patterns. + var dashArray = borderArray[3]; + if (data.borderWidth > 0 && dashArray) { + if (!isArray(dashArray)) { + // Ignore the border if dashArray is not actually an array, + // this is consistent with the behaviour in Adobe Reader. + data.borderWidth = 0; + } else { + var dashArrayLength = dashArray.length; + if (dashArrayLength > 0) { + // According to the PDF specification: the elements in a dashArray + // shall be numbers that are nonnegative and not all equal to zero. + var isInvalid = false; + var numPositive = 0; + for (var i = 0; i < dashArrayLength; i++) { + var validNumber = (+dashArray[i] >= 0); + if (!validNumber) { + isInvalid = true; + break; + } else if (dashArray[i] > 0) { + numPositive++; + } + } + if (isInvalid || numPositive === 0) { + data.borderWidth = 0; + } + } + } + } + } + + this.appearance = getDefaultAppearance(dict); + data.hasAppearance = !!this.appearance; + data.id = params.ref.num; + } + + Annotation.prototype = { + + getData: function Annotation_getData() { + return this.data; + }, + + isInvisible: function Annotation_isInvisible() { + var data = this.data; + if (data && SUPPORTED_TYPES.indexOf(data.subtype) !== -1) { + return false; + } else { + return !!(data && + data.annotationFlags && // Default: not invisible + data.annotationFlags & 0x1); // Invisible + } + }, + + isViewable: function Annotation_isViewable() { + var data = this.data; + return !!(!this.isInvisible() && + data && + (!data.annotationFlags || + !(data.annotationFlags & 0x22)) && // Hidden or NoView + data.rect); // rectangle is necessary + }, + + isPrintable: function Annotation_isPrintable() { + var data = this.data; + return !!(!this.isInvisible() && + data && + data.annotationFlags && // Default: not printable + data.annotationFlags & 0x4 && // Print + !(data.annotationFlags & 0x2) && // Hidden + data.rect); // rectangle is necessary + }, + + loadResources: function Annotation_loadResources(keys) { + return new Promise(function (resolve, reject) { + this.appearance.dict.getAsync('Resources').then(function (resources) { + if (!resources) { + resolve(); + return; + } + var objectLoader = new ObjectLoader(resources.map, + keys, + resources.xref); + objectLoader.load().then(function() { + resolve(resources); + }, reject); + }, reject); + }.bind(this)); + }, + + getOperatorList: function Annotation_getOperatorList(evaluator) { + + if (!this.appearance) { + return Promise.resolve(new OperatorList()); + } + + var data = this.data; + + var appearanceDict = this.appearance.dict; + var resourcesPromise = this.loadResources([ + 'ExtGState', + 'ColorSpace', + 'Pattern', + 'Shading', + 'XObject', + 'Font' + // ProcSet + // Properties + ]); + var bbox = appearanceDict.get('BBox') || [0, 0, 1, 1]; + var matrix = appearanceDict.get('Matrix') || [1, 0, 0, 1, 0 ,0]; + var transform = getTransformMatrix(data.rect, bbox, matrix); + var self = this; + + return resourcesPromise.then(function(resources) { + var opList = new OperatorList(); + opList.addOp(OPS.beginAnnotation, [data.rect, transform, matrix]); + return evaluator.getOperatorList(self.appearance, resources, opList). + then(function () { + opList.addOp(OPS.endAnnotation, []); + self.appearance.reset(); + return opList; + }); + }); + } + }; + + Annotation.getConstructor = + function Annotation_getConstructor(subtype, fieldType) { + + if (!subtype) { + return; + } + + // TODO(mack): Implement FreeText annotations + if (subtype === 'Link') { + return LinkAnnotation; + } else if (subtype === 'Text') { + return TextAnnotation; + } else if (subtype === 'Widget') { + if (!fieldType) { + return; + } + + if (fieldType === 'Tx') { + return TextWidgetAnnotation; + } else { + return WidgetAnnotation; + } + } else { + return Annotation; + } + }; + + Annotation.fromRef = function Annotation_fromRef(xref, ref) { + + var dict = xref.fetchIfRef(ref); + if (!isDict(dict)) { + return; + } + + var subtype = dict.get('Subtype'); + subtype = isName(subtype) ? subtype.name : ''; + if (!subtype) { + return; + } + + var fieldType = Util.getInheritableProperty(dict, 'FT'); + fieldType = isName(fieldType) ? fieldType.name : ''; + + var Constructor = Annotation.getConstructor(subtype, fieldType); + if (!Constructor) { + return; + } + + var params = { + dict: dict, + ref: ref, + }; + + var annotation = new Constructor(params); + + if (annotation.isViewable() || annotation.isPrintable()) { + return annotation; + } else { + if (SUPPORTED_TYPES.indexOf(subtype) === -1) { + warn('unimplemented annotation type: ' + subtype); + } + } + }; + + Annotation.appendToOperatorList = function Annotation_appendToOperatorList( + annotations, opList, pdfManager, partialEvaluator, intent) { + + function reject(e) { + annotationsReadyCapability.reject(e); + } + + var annotationsReadyCapability = createPromiseCapability(); + + var annotationPromises = []; + for (var i = 0, n = annotations.length; i < n; ++i) { + if (intent === 'display' && annotations[i].isViewable() || + intent === 'print' && annotations[i].isPrintable()) { + annotationPromises.push( + annotations[i].getOperatorList(partialEvaluator)); + } + } + Promise.all(annotationPromises).then(function(datas) { + opList.addOp(OPS.beginAnnotations, []); + for (var i = 0, n = datas.length; i < n; ++i) { + var annotOpList = datas[i]; + opList.addOpList(annotOpList); + } + opList.addOp(OPS.endAnnotations, []); + annotationsReadyCapability.resolve(); + }, reject); + + return annotationsReadyCapability.promise; + }; + + return Annotation; +})(); + +var WidgetAnnotation = (function WidgetAnnotationClosure() { + + function WidgetAnnotation(params) { + Annotation.call(this, params); + + var dict = params.dict; + var data = this.data; + + data.fieldValue = stringToPDFString( + Util.getInheritableProperty(dict, 'V') || ''); + data.alternativeText = stringToPDFString(dict.get('TU') || ''); + data.defaultAppearance = Util.getInheritableProperty(dict, 'DA') || ''; + var fieldType = Util.getInheritableProperty(dict, 'FT'); + data.fieldType = isName(fieldType) ? fieldType.name : ''; + data.fieldFlags = Util.getInheritableProperty(dict, 'Ff') || 0; + this.fieldResources = Util.getInheritableProperty(dict, 'DR') || Dict.empty; + + // Building the full field name by collecting the field and + // its ancestors 'T' data and joining them using '.'. + var fieldName = []; + var namedItem = dict; + var ref = params.ref; + while (namedItem) { + var parent = namedItem.get('Parent'); + var parentRef = namedItem.getRaw('Parent'); + var name = namedItem.get('T'); + if (name) { + fieldName.unshift(stringToPDFString(name)); + } else if (parent && ref) { + // The field name is absent, that means more than one field + // with the same name may exist. Replacing the empty name + // with the '`' plus index in the parent's 'Kids' array. + // This is not in the PDF spec but necessary to id the + // the input controls. + var kids = parent.get('Kids'); + var j, jj; + for (j = 0, jj = kids.length; j < jj; j++) { + var kidRef = kids[j]; + if (kidRef.num === ref.num && kidRef.gen === ref.gen) { + break; + } + } + fieldName.unshift('`' + j); + } + namedItem = parent; + ref = parentRef; + } + data.fullName = fieldName.join('.'); + } + + var parent = Annotation.prototype; + Util.inherit(WidgetAnnotation, Annotation, { + isViewable: function WidgetAnnotation_isViewable() { + if (this.data.fieldType === 'Sig') { + warn('unimplemented annotation type: Widget signature'); + return false; + } + + return parent.isViewable.call(this); + } + }); + + return WidgetAnnotation; +})(); + +var TextWidgetAnnotation = (function TextWidgetAnnotationClosure() { + function TextWidgetAnnotation(params) { + WidgetAnnotation.call(this, params); + + this.data.textAlignment = Util.getInheritableProperty(params.dict, 'Q'); + this.data.annotationType = AnnotationType.WIDGET; + this.data.hasHtml = !this.data.hasAppearance && !!this.data.fieldValue; + } + + Util.inherit(TextWidgetAnnotation, WidgetAnnotation, { + getOperatorList: function TextWidgetAnnotation_getOperatorList(evaluator) { + if (this.appearance) { + return Annotation.prototype.getOperatorList.call(this, evaluator); + } + + var opList = new OperatorList(); + var data = this.data; + + // Even if there is an appearance stream, ignore it. This is the + // behaviour used by Adobe Reader. + if (!data.defaultAppearance) { + return Promise.resolve(opList); + } + + var stream = new Stream(stringToBytes(data.defaultAppearance)); + return evaluator.getOperatorList(stream, this.fieldResources, opList). + then(function () { + return opList; + }); + } + }); + + return TextWidgetAnnotation; +})(); + +var InteractiveAnnotation = (function InteractiveAnnotationClosure() { + function InteractiveAnnotation(params) { + Annotation.call(this, params); + + this.data.hasHtml = true; + } + + Util.inherit(InteractiveAnnotation, Annotation, { }); + + return InteractiveAnnotation; +})(); + +var TextAnnotation = (function TextAnnotationClosure() { + function TextAnnotation(params) { + InteractiveAnnotation.call(this, params); + + var dict = params.dict; + var data = this.data; + + var content = dict.get('Contents'); + var title = dict.get('T'); + data.annotationType = AnnotationType.TEXT; + data.content = stringToPDFString(content || ''); + data.title = stringToPDFString(title || ''); + + if (data.hasAppearance) { + data.name = 'NoIcon'; + } else { + data.rect[1] = data.rect[3] - DEFAULT_ICON_SIZE; + data.rect[2] = data.rect[0] + DEFAULT_ICON_SIZE; + data.name = dict.has('Name') ? dict.get('Name').name : 'Note'; + } + + if (dict.has('C')) { + data.hasBgColor = true; + } + } + + Util.inherit(TextAnnotation, InteractiveAnnotation, { }); + + return TextAnnotation; +})(); + +var LinkAnnotation = (function LinkAnnotationClosure() { + function LinkAnnotation(params) { + InteractiveAnnotation.call(this, params); + + var dict = params.dict; + var data = this.data; + data.annotationType = AnnotationType.LINK; + + var action = dict.get('A'); + if (action && isDict(action)) { + var linkType = action.get('S').name; + if (linkType === 'URI') { + var url = action.get('URI'); + if (isName(url)) { + // Some bad PDFs do not put parentheses around relative URLs. + url = '/' + url.name; + } else if (url) { + url = addDefaultProtocolToUrl(url); + } + // TODO: pdf spec mentions urls can be relative to a Base + // entry in the dictionary. + if (!isValidUrl(url, false)) { + url = ''; + } + data.url = url; + } else if (linkType === 'GoTo') { + data.dest = action.get('D'); + } else if (linkType === 'GoToR') { + var urlDict = action.get('F'); + if (isDict(urlDict)) { + // We assume that the 'url' is a Filspec dictionary + // and fetch the url without checking any further + url = urlDict.get('F') || ''; + } + + // TODO: pdf reference says that GoToR + // can also have 'NewWindow' attribute + if (!isValidUrl(url, false)) { + url = ''; + } + data.url = url; + data.dest = action.get('D'); + } else if (linkType === 'Named') { + data.action = action.get('N').name; + } else { + warn('unrecognized link type: ' + linkType); + } + } else if (dict.has('Dest')) { + // simple destination link + var dest = dict.get('Dest'); + data.dest = isName(dest) ? dest.name : dest; + } + } + + // Lets URLs beginning with 'www.' default to using the 'http://' protocol. + function addDefaultProtocolToUrl(url) { + if (url && url.indexOf('www.') === 0) { + return ('http://' + url); + } + return url; + } + + Util.inherit(LinkAnnotation, InteractiveAnnotation, { }); + + return LinkAnnotation; +})(); + + +var PDFFunction = (function PDFFunctionClosure() { + var CONSTRUCT_SAMPLED = 0; + var CONSTRUCT_INTERPOLATED = 2; + var CONSTRUCT_STICHED = 3; + var CONSTRUCT_POSTSCRIPT = 4; + + return { + getSampleArray: function PDFFunction_getSampleArray(size, outputSize, bps, + str) { + var i, ii; + var length = 1; + for (i = 0, ii = size.length; i < ii; i++) { + length *= size[i]; + } + length *= outputSize; + + var array = new Array(length); + var codeSize = 0; + var codeBuf = 0; + // 32 is a valid bps so shifting won't work + var sampleMul = 1.0 / (Math.pow(2.0, bps) - 1); + + var strBytes = str.getBytes((length * bps + 7) / 8); + var strIdx = 0; + for (i = 0; i < length; i++) { + while (codeSize < bps) { + codeBuf <<= 8; + codeBuf |= strBytes[strIdx++]; + codeSize += 8; + } + codeSize -= bps; + array[i] = (codeBuf >> codeSize) * sampleMul; + codeBuf &= (1 << codeSize) - 1; + } + return array; + }, + + getIR: function PDFFunction_getIR(xref, fn) { + var dict = fn.dict; + if (!dict) { + dict = fn; + } + + var types = [this.constructSampled, + null, + this.constructInterpolated, + this.constructStiched, + this.constructPostScript]; + + var typeNum = dict.get('FunctionType'); + var typeFn = types[typeNum]; + if (!typeFn) { + error('Unknown type of function'); + } + + return typeFn.call(this, fn, dict, xref); + }, + + fromIR: function PDFFunction_fromIR(IR) { + var type = IR[0]; + switch (type) { + case CONSTRUCT_SAMPLED: + return this.constructSampledFromIR(IR); + case CONSTRUCT_INTERPOLATED: + return this.constructInterpolatedFromIR(IR); + case CONSTRUCT_STICHED: + return this.constructStichedFromIR(IR); + //case CONSTRUCT_POSTSCRIPT: + default: + return this.constructPostScriptFromIR(IR); + } + }, + + parse: function PDFFunction_parse(xref, fn) { + var IR = this.getIR(xref, fn); + return this.fromIR(IR); + }, + + parseArray: function PDFFunction_parseArray(xref, fnObj) { + if (!isArray(fnObj)) { + // not an array -- parsing as regular function + return this.parse(xref, fnObj); + } + + var fnArray = []; + for (var j = 0, jj = fnObj.length; j < jj; j++) { + var obj = xref.fetchIfRef(fnObj[j]); + fnArray.push(PDFFunction.parse(xref, obj)); + } + return function (src, srcOffset, dest, destOffset) { + for (var i = 0, ii = fnArray.length; i < ii; i++) { + fnArray[i](src, srcOffset, dest, destOffset + i); + } + }; + }, + + constructSampled: function PDFFunction_constructSampled(str, dict) { + function toMultiArray(arr) { + var inputLength = arr.length; + var out = []; + var index = 0; + for (var i = 0; i < inputLength; i += 2) { + out[index] = [arr[i], arr[i + 1]]; + ++index; + } + return out; + } + var domain = dict.get('Domain'); + var range = dict.get('Range'); + + if (!domain || !range) { + error('No domain or range'); + } + + var inputSize = domain.length / 2; + var outputSize = range.length / 2; + + domain = toMultiArray(domain); + range = toMultiArray(range); + + var size = dict.get('Size'); + var bps = dict.get('BitsPerSample'); + var order = dict.get('Order') || 1; + if (order !== 1) { + // No description how cubic spline interpolation works in PDF32000:2008 + // As in poppler, ignoring order, linear interpolation may work as good + info('No support for cubic spline interpolation: ' + order); + } + + var encode = dict.get('Encode'); + if (!encode) { + encode = []; + for (var i = 0; i < inputSize; ++i) { + encode.push(0); + encode.push(size[i] - 1); + } + } + encode = toMultiArray(encode); + + var decode = dict.get('Decode'); + if (!decode) { + decode = range; + } else { + decode = toMultiArray(decode); + } + + var samples = this.getSampleArray(size, outputSize, bps, str); + + return [ + CONSTRUCT_SAMPLED, inputSize, domain, encode, decode, samples, size, + outputSize, Math.pow(2, bps) - 1, range + ]; + }, + + constructSampledFromIR: function PDFFunction_constructSampledFromIR(IR) { + // See chapter 3, page 109 of the PDF reference + function interpolate(x, xmin, xmax, ymin, ymax) { + return ymin + ((x - xmin) * ((ymax - ymin) / (xmax - xmin))); + } + + return function constructSampledFromIRResult(src, srcOffset, + dest, destOffset) { + // See chapter 3, page 110 of the PDF reference. + var m = IR[1]; + var domain = IR[2]; + var encode = IR[3]; + var decode = IR[4]; + var samples = IR[5]; + var size = IR[6]; + var n = IR[7]; + //var mask = IR[8]; + var range = IR[9]; + + // Building the cube vertices: its part and sample index + // http://rjwagner49.com/Mathematics/Interpolation.pdf + var cubeVertices = 1 << m; + var cubeN = new Float64Array(cubeVertices); + var cubeVertex = new Uint32Array(cubeVertices); + var i, j; + for (j = 0; j < cubeVertices; j++) { + cubeN[j] = 1; + } + + var k = n, pos = 1; + // Map x_i to y_j for 0 <= i < m using the sampled function. + for (i = 0; i < m; ++i) { + // x_i' = min(max(x_i, Domain_2i), Domain_2i+1) + var domain_2i = domain[i][0]; + var domain_2i_1 = domain[i][1]; + var xi = Math.min(Math.max(src[srcOffset +i], domain_2i), + domain_2i_1); + + // e_i = Interpolate(x_i', Domain_2i, Domain_2i+1, + // Encode_2i, Encode_2i+1) + var e = interpolate(xi, domain_2i, domain_2i_1, + encode[i][0], encode[i][1]); + + // e_i' = min(max(e_i, 0), Size_i - 1) + var size_i = size[i]; + e = Math.min(Math.max(e, 0), size_i - 1); + + // Adjusting the cube: N and vertex sample index + var e0 = e < size_i - 1 ? Math.floor(e) : e - 1; // e1 = e0 + 1; + var n0 = e0 + 1 - e; // (e1 - e) / (e1 - e0); + var n1 = e - e0; // (e - e0) / (e1 - e0); + var offset0 = e0 * k; + var offset1 = offset0 + k; // e1 * k + for (j = 0; j < cubeVertices; j++) { + if (j & pos) { + cubeN[j] *= n1; + cubeVertex[j] += offset1; + } else { + cubeN[j] *= n0; + cubeVertex[j] += offset0; + } + } + + k *= size_i; + pos <<= 1; + } + + for (j = 0; j < n; ++j) { + // Sum all cube vertices' samples portions + var rj = 0; + for (i = 0; i < cubeVertices; i++) { + rj += samples[cubeVertex[i] + j] * cubeN[i]; + } + + // r_j' = Interpolate(r_j, 0, 2^BitsPerSample - 1, + // Decode_2j, Decode_2j+1) + rj = interpolate(rj, 0, 1, decode[j][0], decode[j][1]); + + // y_j = min(max(r_j, range_2j), range_2j+1) + dest[destOffset + j] = Math.min(Math.max(rj, range[j][0]), + range[j][1]); + } + }; + }, + + constructInterpolated: function PDFFunction_constructInterpolated(str, + dict) { + var c0 = dict.get('C0') || [0]; + var c1 = dict.get('C1') || [1]; + var n = dict.get('N'); + + if (!isArray(c0) || !isArray(c1)) { + error('Illegal dictionary for interpolated function'); + } + + var length = c0.length; + var diff = []; + for (var i = 0; i < length; ++i) { + diff.push(c1[i] - c0[i]); + } + + return [CONSTRUCT_INTERPOLATED, c0, diff, n]; + }, + + constructInterpolatedFromIR: + function PDFFunction_constructInterpolatedFromIR(IR) { + var c0 = IR[1]; + var diff = IR[2]; + var n = IR[3]; + + var length = diff.length; + + return function constructInterpolatedFromIRResult(src, srcOffset, + dest, destOffset) { + var x = n === 1 ? src[srcOffset] : Math.pow(src[srcOffset], n); + + for (var j = 0; j < length; ++j) { + dest[destOffset + j] = c0[j] + (x * diff[j]); + } + }; + }, + + constructStiched: function PDFFunction_constructStiched(fn, dict, xref) { + var domain = dict.get('Domain'); + + if (!domain) { + error('No domain'); + } + + var inputSize = domain.length / 2; + if (inputSize !== 1) { + error('Bad domain for stiched function'); + } + + var fnRefs = dict.get('Functions'); + var fns = []; + for (var i = 0, ii = fnRefs.length; i < ii; ++i) { + fns.push(PDFFunction.getIR(xref, xref.fetchIfRef(fnRefs[i]))); + } + + var bounds = dict.get('Bounds'); + var encode = dict.get('Encode'); + + return [CONSTRUCT_STICHED, domain, bounds, encode, fns]; + }, + + constructStichedFromIR: function PDFFunction_constructStichedFromIR(IR) { + var domain = IR[1]; + var bounds = IR[2]; + var encode = IR[3]; + var fnsIR = IR[4]; + var fns = []; + var tmpBuf = new Float32Array(1); + + for (var i = 0, ii = fnsIR.length; i < ii; i++) { + fns.push(PDFFunction.fromIR(fnsIR[i])); + } + + return function constructStichedFromIRResult(src, srcOffset, + dest, destOffset) { + var clip = function constructStichedFromIRClip(v, min, max) { + if (v > max) { + v = max; + } else if (v < min) { + v = min; + } + return v; + }; + + // clip to domain + var v = clip(src[srcOffset], domain[0], domain[1]); + // calulate which bound the value is in + for (var i = 0, ii = bounds.length; i < ii; ++i) { + if (v < bounds[i]) { + break; + } + } + + // encode value into domain of function + var dmin = domain[0]; + if (i > 0) { + dmin = bounds[i - 1]; + } + var dmax = domain[1]; + if (i < bounds.length) { + dmax = bounds[i]; + } + + var rmin = encode[2 * i]; + var rmax = encode[2 * i + 1]; + + tmpBuf[0] = rmin + (v - dmin) * (rmax - rmin) / (dmax - dmin); + + // call the appropriate function + fns[i](tmpBuf, 0, dest, destOffset); + }; + }, + + constructPostScript: function PDFFunction_constructPostScript(fn, dict, + xref) { + var domain = dict.get('Domain'); + var range = dict.get('Range'); + + if (!domain) { + error('No domain.'); + } + + if (!range) { + error('No range.'); + } + + var lexer = new PostScriptLexer(fn); + var parser = new PostScriptParser(lexer); + var code = parser.parse(); + + return [CONSTRUCT_POSTSCRIPT, domain, range, code]; + }, + + constructPostScriptFromIR: function PDFFunction_constructPostScriptFromIR( + IR) { + var domain = IR[1]; + var range = IR[2]; + var code = IR[3]; + + var compiled = (new PostScriptCompiler()).compile(code, domain, range); + if (compiled) { + // Compiled function consists of simple expressions such as addition, + // subtraction, Math.max, and also contains 'var' and 'return' + // statements. See the generation in the PostScriptCompiler below. + /*jshint -W054 */ + return new Function('src', 'srcOffset', 'dest', 'destOffset', compiled); + } + + info('Unable to compile PS function'); + + var numOutputs = range.length >> 1; + var numInputs = domain.length >> 1; + var evaluator = new PostScriptEvaluator(code); + // Cache the values for a big speed up, the cache size is limited though + // since the number of possible values can be huge from a PS function. + var cache = {}; + // The MAX_CACHE_SIZE is set to ~4x the maximum number of distinct values + // seen in our tests. + var MAX_CACHE_SIZE = 2048 * 4; + var cache_available = MAX_CACHE_SIZE; + var tmpBuf = new Float32Array(numInputs); + + return function constructPostScriptFromIRResult(src, srcOffset, + dest, destOffset) { + var i, value; + var key = ''; + var input = tmpBuf; + for (i = 0; i < numInputs; i++) { + value = src[srcOffset + i]; + input[i] = value; + key += value + '_'; + } + + var cachedValue = cache[key]; + if (cachedValue !== undefined) { + dest.set(cachedValue, destOffset); + return; + } + + var output = new Float32Array(numOutputs); + var stack = evaluator.execute(input); + var stackIndex = stack.length - numOutputs; + for (i = 0; i < numOutputs; i++) { + value = stack[stackIndex + i]; + var bound = range[i * 2]; + if (value < bound) { + value = bound; + } else { + bound = range[i * 2 +1]; + if (value > bound) { + value = bound; + } + } + output[i] = value; + } + if (cache_available > 0) { + cache_available--; + cache[key] = output; + } + dest.set(output, destOffset); + }; + } + }; +})(); + +function isPDFFunction(v) { + var fnDict; + if (typeof v !== 'object') { + return false; + } else if (isDict(v)) { + fnDict = v; + } else if (isStream(v)) { + fnDict = v.dict; + } else { + return false; + } + return fnDict.has('FunctionType'); +} + +var PostScriptStack = (function PostScriptStackClosure() { + var MAX_STACK_SIZE = 100; + function PostScriptStack(initialStack) { + this.stack = !initialStack ? [] : + Array.prototype.slice.call(initialStack, 0); + } + + PostScriptStack.prototype = { + push: function PostScriptStack_push(value) { + if (this.stack.length >= MAX_STACK_SIZE) { + error('PostScript function stack overflow.'); + } + this.stack.push(value); + }, + pop: function PostScriptStack_pop() { + if (this.stack.length <= 0) { + error('PostScript function stack underflow.'); + } + return this.stack.pop(); + }, + copy: function PostScriptStack_copy(n) { + if (this.stack.length + n >= MAX_STACK_SIZE) { + error('PostScript function stack overflow.'); + } + var stack = this.stack; + for (var i = stack.length - n, j = n - 1; j >= 0; j--, i++) { + stack.push(stack[i]); + } + }, + index: function PostScriptStack_index(n) { + this.push(this.stack[this.stack.length - n - 1]); + }, + // rotate the last n stack elements p times + roll: function PostScriptStack_roll(n, p) { + var stack = this.stack; + var l = stack.length - n; + var r = stack.length - 1, c = l + (p - Math.floor(p / n) * n), i, j, t; + for (i = l, j = r; i < j; i++, j--) { + t = stack[i]; stack[i] = stack[j]; stack[j] = t; + } + for (i = l, j = c - 1; i < j; i++, j--) { + t = stack[i]; stack[i] = stack[j]; stack[j] = t; + } + for (i = c, j = r; i < j; i++, j--) { + t = stack[i]; stack[i] = stack[j]; stack[j] = t; + } + } + }; + return PostScriptStack; +})(); +var PostScriptEvaluator = (function PostScriptEvaluatorClosure() { + function PostScriptEvaluator(operators) { + this.operators = operators; + } + PostScriptEvaluator.prototype = { + execute: function PostScriptEvaluator_execute(initialStack) { + var stack = new PostScriptStack(initialStack); + var counter = 0; + var operators = this.operators; + var length = operators.length; + var operator, a, b; + while (counter < length) { + operator = operators[counter++]; + if (typeof operator === 'number') { + // Operator is really an operand and should be pushed to the stack. + stack.push(operator); + continue; + } + switch (operator) { + // non standard ps operators + case 'jz': // jump if false + b = stack.pop(); + a = stack.pop(); + if (!a) { + counter = b; + } + break; + case 'j': // jump + a = stack.pop(); + counter = a; + break; + + // all ps operators in alphabetical order (excluding if/ifelse) + case 'abs': + a = stack.pop(); + stack.push(Math.abs(a)); + break; + case 'add': + b = stack.pop(); + a = stack.pop(); + stack.push(a + b); + break; + case 'and': + b = stack.pop(); + a = stack.pop(); + if (isBool(a) && isBool(b)) { + stack.push(a && b); + } else { + stack.push(a & b); + } + break; + case 'atan': + a = stack.pop(); + stack.push(Math.atan(a)); + break; + case 'bitshift': + b = stack.pop(); + a = stack.pop(); + if (a > 0) { + stack.push(a << b); + } else { + stack.push(a >> b); + } + break; + case 'ceiling': + a = stack.pop(); + stack.push(Math.ceil(a)); + break; + case 'copy': + a = stack.pop(); + stack.copy(a); + break; + case 'cos': + a = stack.pop(); + stack.push(Math.cos(a)); + break; + case 'cvi': + a = stack.pop() | 0; + stack.push(a); + break; + case 'cvr': + // noop + break; + case 'div': + b = stack.pop(); + a = stack.pop(); + stack.push(a / b); + break; + case 'dup': + stack.copy(1); + break; + case 'eq': + b = stack.pop(); + a = stack.pop(); + stack.push(a === b); + break; + case 'exch': + stack.roll(2, 1); + break; + case 'exp': + b = stack.pop(); + a = stack.pop(); + stack.push(Math.pow(a, b)); + break; + case 'false': + stack.push(false); + break; + case 'floor': + a = stack.pop(); + stack.push(Math.floor(a)); + break; + case 'ge': + b = stack.pop(); + a = stack.pop(); + stack.push(a >= b); + break; + case 'gt': + b = stack.pop(); + a = stack.pop(); + stack.push(a > b); + break; + case 'idiv': + b = stack.pop(); + a = stack.pop(); + stack.push((a / b) | 0); + break; + case 'index': + a = stack.pop(); + stack.index(a); + break; + case 'le': + b = stack.pop(); + a = stack.pop(); + stack.push(a <= b); + break; + case 'ln': + a = stack.pop(); + stack.push(Math.log(a)); + break; + case 'log': + a = stack.pop(); + stack.push(Math.log(a) / Math.LN10); + break; + case 'lt': + b = stack.pop(); + a = stack.pop(); + stack.push(a < b); + break; + case 'mod': + b = stack.pop(); + a = stack.pop(); + stack.push(a % b); + break; + case 'mul': + b = stack.pop(); + a = stack.pop(); + stack.push(a * b); + break; + case 'ne': + b = stack.pop(); + a = stack.pop(); + stack.push(a !== b); + break; + case 'neg': + a = stack.pop(); + stack.push(-a); + break; + case 'not': + a = stack.pop(); + if (isBool(a)) { + stack.push(!a); + } else { + stack.push(~a); + } + break; + case 'or': + b = stack.pop(); + a = stack.pop(); + if (isBool(a) && isBool(b)) { + stack.push(a || b); + } else { + stack.push(a | b); + } + break; + case 'pop': + stack.pop(); + break; + case 'roll': + b = stack.pop(); + a = stack.pop(); + stack.roll(a, b); + break; + case 'round': + a = stack.pop(); + stack.push(Math.round(a)); + break; + case 'sin': + a = stack.pop(); + stack.push(Math.sin(a)); + break; + case 'sqrt': + a = stack.pop(); + stack.push(Math.sqrt(a)); + break; + case 'sub': + b = stack.pop(); + a = stack.pop(); + stack.push(a - b); + break; + case 'true': + stack.push(true); + break; + case 'truncate': + a = stack.pop(); + a = a < 0 ? Math.ceil(a) : Math.floor(a); + stack.push(a); + break; + case 'xor': + b = stack.pop(); + a = stack.pop(); + if (isBool(a) && isBool(b)) { + stack.push(a !== b); + } else { + stack.push(a ^ b); + } + break; + default: + error('Unknown operator ' + operator); + break; + } + } + return stack.stack; + } + }; + return PostScriptEvaluator; +})(); + +// Most of the PDFs functions consist of simple operations such as: +// roll, exch, sub, cvr, pop, index, dup, mul, if, gt, add. +// +// We can compile most of such programs, and at the same moment, we can +// optimize some expressions using basic math properties. Keeping track of +// min/max values will allow us to avoid extra Math.min/Math.max calls. +var PostScriptCompiler = (function PostScriptCompilerClosure() { + function AstNode(type) { + this.type = type; + } + AstNode.prototype.visit = function (visitor) { + throw new Error('abstract method'); + }; + + function AstArgument(index, min, max) { + AstNode.call(this, 'args'); + this.index = index; + this.min = min; + this.max = max; + } + AstArgument.prototype = Object.create(AstNode.prototype); + AstArgument.prototype.visit = function (visitor) { + visitor.visitArgument(this); + }; + + function AstLiteral(number) { + AstNode.call(this, 'literal'); + this.number = number; + this.min = number; + this.max = number; + } + AstLiteral.prototype = Object.create(AstNode.prototype); + AstLiteral.prototype.visit = function (visitor) { + visitor.visitLiteral(this); + }; + + function AstBinaryOperation(op, arg1, arg2, min, max) { + AstNode.call(this, 'binary'); + this.op = op; + this.arg1 = arg1; + this.arg2 = arg2; + this.min = min; + this.max = max; + } + AstBinaryOperation.prototype = Object.create(AstNode.prototype); + AstBinaryOperation.prototype.visit = function (visitor) { + visitor.visitBinaryOperation(this); + }; + + function AstMin(arg, max) { + AstNode.call(this, 'max'); + this.arg = arg; + this.min = arg.min; + this.max = max; + } + AstMin.prototype = Object.create(AstNode.prototype); + AstMin.prototype.visit = function (visitor) { + visitor.visitMin(this); + }; + + function AstVariable(index, min, max) { + AstNode.call(this, 'var'); + this.index = index; + this.min = min; + this.max = max; + } + AstVariable.prototype = Object.create(AstNode.prototype); + AstVariable.prototype.visit = function (visitor) { + visitor.visitVariable(this); + }; + + function AstVariableDefinition(variable, arg) { + AstNode.call(this, 'definition'); + this.variable = variable; + this.arg = arg; + } + AstVariableDefinition.prototype = Object.create(AstNode.prototype); + AstVariableDefinition.prototype.visit = function (visitor) { + visitor.visitVariableDefinition(this); + }; + + function ExpressionBuilderVisitor() { + this.parts = []; + } + ExpressionBuilderVisitor.prototype = { + visitArgument: function (arg) { + this.parts.push('Math.max(', arg.min, ', Math.min(', + arg.max, ', src[srcOffset + ', arg.index, ']))'); + }, + visitVariable: function (variable) { + this.parts.push('v', variable.index); + }, + visitLiteral: function (literal) { + this.parts.push(literal.number); + }, + visitBinaryOperation: function (operation) { + this.parts.push('('); + operation.arg1.visit(this); + this.parts.push(' ', operation.op, ' '); + operation.arg2.visit(this); + this.parts.push(')'); + }, + visitVariableDefinition: function (definition) { + this.parts.push('var '); + definition.variable.visit(this); + this.parts.push(' = '); + definition.arg.visit(this); + this.parts.push(';'); + }, + visitMin: function (max) { + this.parts.push('Math.min('); + max.arg.visit(this); + this.parts.push(', ', max.max, ')'); + }, + toString: function () { + return this.parts.join(''); + } + }; + + function buildAddOperation(num1, num2) { + if (num2.type === 'literal' && num2.number === 0) { + // optimization: second operand is 0 + return num1; + } + if (num1.type === 'literal' && num1.number === 0) { + // optimization: first operand is 0 + return num2; + } + if (num2.type === 'literal' && num1.type === 'literal') { + // optimization: operands operand are literals + return new AstLiteral(num1.number + num2.number); + } + return new AstBinaryOperation('+', num1, num2, + num1.min + num2.min, num1.max + num2.max); + } + + function buildMulOperation(num1, num2) { + if (num2.type === 'literal') { + // optimization: second operands is a literal... + if (num2.number === 0) { + return new AstLiteral(0); // and it's 0 + } else if (num2.number === 1) { + return num1; // and it's 1 + } else if (num1.type === 'literal') { + // ... and first operands is a literal too + return new AstLiteral(num1.number * num2.number); + } + } + if (num1.type === 'literal') { + // optimization: first operands is a literal... + if (num1.number === 0) { + return new AstLiteral(0); // and it's 0 + } else if (num1.number === 1) { + return num2; // and it's 1 + } + } + var min = Math.min(num1.min * num2.min, num1.min * num2.max, + num1.max * num2.min, num1.max * num2.max); + var max = Math.max(num1.min * num2.min, num1.min * num2.max, + num1.max * num2.min, num1.max * num2.max); + return new AstBinaryOperation('*', num1, num2, min, max); + } + + function buildSubOperation(num1, num2) { + if (num2.type === 'literal') { + // optimization: second operands is a literal... + if (num2.number === 0) { + return num1; // ... and it's 0 + } else if (num1.type === 'literal') { + // ... and first operands is a literal too + return new AstLiteral(num1.number - num2.number); + } + } + if (num2.type === 'binary' && num2.op === '-' && + num1.type === 'literal' && num1.number === 1 && + num2.arg1.type === 'literal' && num2.arg1.number === 1) { + // optimization for case: 1 - (1 - x) + return num2.arg2; + } + return new AstBinaryOperation('-', num1, num2, + num1.min - num2.max, num1.max - num2.min); + } + + function buildMinOperation(num1, max) { + if (num1.min >= max) { + // optimization: num1 min value is not less than required max + return new AstLiteral(max); // just returning max + } else if (num1.max <= max) { + // optimization: num1 max value is not greater than required max + return num1; // just returning an argument + } + return new AstMin(num1, max); + } + + function PostScriptCompiler() {} + PostScriptCompiler.prototype = { + compile: function PostScriptCompiler_compile(code, domain, range) { + var stack = []; + var i, ii; + var instructions = []; + var inputSize = domain.length >> 1, outputSize = range.length >> 1; + var lastRegister = 0; + var n, j, min, max; + var num1, num2, ast1, ast2, tmpVar, item; + for (i = 0; i < inputSize; i++) { + stack.push(new AstArgument(i, domain[i * 2], domain[i * 2 + 1])); + } + + for (i = 0, ii = code.length; i < ii; i++) { + item = code[i]; + if (typeof item === 'number') { + stack.push(new AstLiteral(item)); + continue; + } + + switch (item) { + case 'add': + if (stack.length < 2) { + return null; + } + num2 = stack.pop(); + num1 = stack.pop(); + stack.push(buildAddOperation(num1, num2)); + break; + case 'cvr': + if (stack.length < 1) { + return null; + } + break; + case 'mul': + if (stack.length < 2) { + return null; + } + num2 = stack.pop(); + num1 = stack.pop(); + stack.push(buildMulOperation(num1, num2)); + break; + case 'sub': + if (stack.length < 2) { + return null; + } + num2 = stack.pop(); + num1 = stack.pop(); + stack.push(buildSubOperation(num1, num2)); + break; + case 'exch': + if (stack.length < 2) { + return null; + } + ast1 = stack.pop(); ast2 = stack.pop(); + stack.push(ast1, ast2); + break; + case 'pop': + if (stack.length < 1) { + return null; + } + stack.pop(); + break; + case 'index': + if (stack.length < 1) { + return null; + } + num1 = stack.pop(); + if (num1.type !== 'literal') { + return null; + } + n = num1.number; + if (n < 0 || (n|0) !== n || stack.length < n) { + return null; + } + ast1 = stack[stack.length - n - 1]; + if (ast1.type === 'literal' || ast1.type === 'var') { + stack.push(ast1); + break; + } + tmpVar = new AstVariable(lastRegister++, ast1.min, ast1.max); + stack[stack.length - n - 1] = tmpVar; + stack.push(tmpVar); + instructions.push(new AstVariableDefinition(tmpVar, ast1)); + break; + case 'dup': + if (stack.length < 1) { + return null; + } + if (typeof code[i + 1] === 'number' && code[i + 2] === 'gt' && + code[i + 3] === i + 7 && code[i + 4] === 'jz' && + code[i + 5] === 'pop' && code[i + 6] === code[i + 1]) { + // special case of the commands sequence for the min operation + num1 = stack.pop(); + stack.push(buildMinOperation(num1, code[i + 1])); + i += 6; + break; + } + ast1 = stack[stack.length - 1]; + if (ast1.type === 'literal' || ast1.type === 'var') { + // we don't have to save into intermediate variable a literal or + // variable. + stack.push(ast1); + break; + } + tmpVar = new AstVariable(lastRegister++, ast1.min, ast1.max); + stack[stack.length - 1] = tmpVar; + stack.push(tmpVar); + instructions.push(new AstVariableDefinition(tmpVar, ast1)); + break; + case 'roll': + if (stack.length < 2) { + return null; + } + num2 = stack.pop(); + num1 = stack.pop(); + if (num2.type !== 'literal' || num1.type !== 'literal') { + // both roll operands must be numbers + return null; + } + j = num2.number; + n = num1.number; + if (n <= 0 || (n|0) !== n || (j|0) !== j || stack.length < n) { + // ... and integers + return null; + } + j = ((j % n) + n) % n; + if (j === 0) { + break; // just skipping -- there are nothing to rotate + } + Array.prototype.push.apply(stack, + stack.splice(stack.length - n, n - j)); + break; + default: + return null; // unsupported operator + } + } + + if (stack.length !== outputSize) { + return null; + } + + var result = []; + instructions.forEach(function (instruction) { + var statementBuilder = new ExpressionBuilderVisitor(); + instruction.visit(statementBuilder); + result.push(statementBuilder.toString()); + }); + stack.forEach(function (expr, i) { + var statementBuilder = new ExpressionBuilderVisitor(); + expr.visit(statementBuilder); + var min = range[i * 2], max = range[i * 2 + 1]; + var out = [statementBuilder.toString()]; + if (min > expr.min) { + out.unshift('Math.max(', min, ', '); + out.push(')'); + } + if (max < expr.max) { + out.unshift('Math.min(', max, ', '); + out.push(')'); + } + out.unshift('dest[destOffset + ', i, '] = '); + out.push(';'); + result.push(out.join('')); + }); + return result.join('\n'); + } + }; + + return PostScriptCompiler; +})(); + + +var ColorSpace = (function ColorSpaceClosure() { + // Constructor should define this.numComps, this.defaultColor, this.name + function ColorSpace() { + error('should not call ColorSpace constructor'); + } + + ColorSpace.prototype = { + /** + * Converts the color value to the RGB color. The color components are + * located in the src array starting from the srcOffset. Returns the array + * of the rgb components, each value ranging from [0,255]. + */ + getRgb: function ColorSpace_getRgb(src, srcOffset) { + var rgb = new Uint8Array(3); + this.getRgbItem(src, srcOffset, rgb, 0); + return rgb; + }, + /** + * Converts the color value to the RGB color, similar to the getRgb method. + * The result placed into the dest array starting from the destOffset. + */ + getRgbItem: function ColorSpace_getRgbItem(src, srcOffset, + dest, destOffset) { + error('Should not call ColorSpace.getRgbItem'); + }, + /** + * Converts the specified number of the color values to the RGB colors. + * The colors are located in the src array starting from the srcOffset. + * The result is placed into the dest array starting from the destOffset. + * The src array items shall be in [0,2^bits) range, the dest array items + * will be in [0,255] range. alpha01 indicates how many alpha components + * there are in the dest array; it will be either 0 (RGB array) or 1 (RGBA + * array). + */ + getRgbBuffer: function ColorSpace_getRgbBuffer(src, srcOffset, count, + dest, destOffset, bits, + alpha01) { + error('Should not call ColorSpace.getRgbBuffer'); + }, + /** + * Determines the number of bytes required to store the result of the + * conversion done by the getRgbBuffer method. As in getRgbBuffer, + * |alpha01| is either 0 (RGB output) or 1 (RGBA output). + */ + getOutputLength: function ColorSpace_getOutputLength(inputLength, + alpha01) { + error('Should not call ColorSpace.getOutputLength'); + }, + /** + * Returns true if source data will be equal the result/output data. + */ + isPassthrough: function ColorSpace_isPassthrough(bits) { + return false; + }, + /** + * Fills in the RGB colors in the destination buffer. alpha01 indicates + * how many alpha components there are in the dest array; it will be either + * 0 (RGB array) or 1 (RGBA array). + */ + fillRgb: function ColorSpace_fillRgb(dest, originalWidth, + originalHeight, width, height, + actualHeight, bpc, comps, alpha01) { + var count = originalWidth * originalHeight; + var rgbBuf = null; + var numComponentColors = 1 << bpc; + var needsResizing = originalHeight !== height || originalWidth !== width; + var i, ii; + + if (this.isPassthrough(bpc)) { + rgbBuf = comps; + } else if (this.numComps === 1 && count > numComponentColors && + this.name !== 'DeviceGray' && this.name !== 'DeviceRGB') { + // Optimization: create a color map when there is just one component and + // we are converting more colors than the size of the color map. We + // don't build the map if the colorspace is gray or rgb since those + // methods are faster than building a map. This mainly offers big speed + // ups for indexed and alternate colorspaces. + // + // TODO it may be worth while to cache the color map. While running + // testing I never hit a cache so I will leave that out for now (perhaps + // we are reparsing colorspaces too much?). + var allColors = bpc <= 8 ? new Uint8Array(numComponentColors) : + new Uint16Array(numComponentColors); + var key; + for (i = 0; i < numComponentColors; i++) { + allColors[i] = i; + } + var colorMap = new Uint8Array(numComponentColors * 3); + this.getRgbBuffer(allColors, 0, numComponentColors, colorMap, 0, bpc, + /* alpha01 = */ 0); + + var destPos, rgbPos; + if (!needsResizing) { + // Fill in the RGB values directly into |dest|. + destPos = 0; + for (i = 0; i < count; ++i) { + key = comps[i] * 3; + dest[destPos++] = colorMap[key]; + dest[destPos++] = colorMap[key + 1]; + dest[destPos++] = colorMap[key + 2]; + destPos += alpha01; + } + } else { + rgbBuf = new Uint8Array(count * 3); + rgbPos = 0; + for (i = 0; i < count; ++i) { + key = comps[i] * 3; + rgbBuf[rgbPos++] = colorMap[key]; + rgbBuf[rgbPos++] = colorMap[key + 1]; + rgbBuf[rgbPos++] = colorMap[key + 2]; + } + } + } else { + if (!needsResizing) { + // Fill in the RGB values directly into |dest|. + this.getRgbBuffer(comps, 0, width * actualHeight, dest, 0, bpc, + alpha01); + } else { + rgbBuf = new Uint8Array(count * 3); + this.getRgbBuffer(comps, 0, count, rgbBuf, 0, bpc, + /* alpha01 = */ 0); + } + } + + if (rgbBuf) { + if (needsResizing) { + PDFImage.resize(rgbBuf, bpc, 3, originalWidth, originalHeight, width, + height, dest, alpha01); + } else { + rgbPos = 0; + destPos = 0; + for (i = 0, ii = width * actualHeight; i < ii; i++) { + dest[destPos++] = rgbBuf[rgbPos++]; + dest[destPos++] = rgbBuf[rgbPos++]; + dest[destPos++] = rgbBuf[rgbPos++]; + destPos += alpha01; + } + } + } + }, + /** + * True if the colorspace has components in the default range of [0, 1]. + * This should be true for all colorspaces except for lab color spaces + * which are [0,100], [-128, 127], [-128, 127]. + */ + usesZeroToOneRange: true + }; + + ColorSpace.parse = function ColorSpace_parse(cs, xref, res) { + var IR = ColorSpace.parseToIR(cs, xref, res); + if (IR instanceof AlternateCS) { + return IR; + } + return ColorSpace.fromIR(IR); + }; + + ColorSpace.fromIR = function ColorSpace_fromIR(IR) { + var name = isArray(IR) ? IR[0] : IR; + var whitePoint, blackPoint, gamma; + + switch (name) { + case 'DeviceGrayCS': + return this.singletons.gray; + case 'DeviceRgbCS': + return this.singletons.rgb; + case 'DeviceCmykCS': + return this.singletons.cmyk; + case 'CalGrayCS': + whitePoint = IR[1].WhitePoint; + blackPoint = IR[1].BlackPoint; + gamma = IR[1].Gamma; + return new CalGrayCS(whitePoint, blackPoint, gamma); + case 'CalRGBCS': + whitePoint = IR[1].WhitePoint; + blackPoint = IR[1].BlackPoint; + gamma = IR[1].Gamma; + var matrix = IR[1].Matrix; + return new CalRGBCS(whitePoint, blackPoint, gamma, matrix); + case 'PatternCS': + var basePatternCS = IR[1]; + if (basePatternCS) { + basePatternCS = ColorSpace.fromIR(basePatternCS); + } + return new PatternCS(basePatternCS); + case 'IndexedCS': + var baseIndexedCS = IR[1]; + var hiVal = IR[2]; + var lookup = IR[3]; + return new IndexedCS(ColorSpace.fromIR(baseIndexedCS), hiVal, lookup); + case 'AlternateCS': + var numComps = IR[1]; + var alt = IR[2]; + var tintFnIR = IR[3]; + + return new AlternateCS(numComps, ColorSpace.fromIR(alt), + PDFFunction.fromIR(tintFnIR)); + case 'LabCS': + whitePoint = IR[1].WhitePoint; + blackPoint = IR[1].BlackPoint; + var range = IR[1].Range; + return new LabCS(whitePoint, blackPoint, range); + default: + error('Unknown name ' + name); + } + return null; + }; + + ColorSpace.parseToIR = function ColorSpace_parseToIR(cs, xref, res) { + if (isName(cs)) { + var colorSpaces = res.get('ColorSpace'); + if (isDict(colorSpaces)) { + var refcs = colorSpaces.get(cs.name); + if (refcs) { + cs = refcs; + } + } + } + + cs = xref.fetchIfRef(cs); + var mode; + + if (isName(cs)) { + mode = cs.name; + this.mode = mode; + + switch (mode) { + case 'DeviceGray': + case 'G': + return 'DeviceGrayCS'; + case 'DeviceRGB': + case 'RGB': + return 'DeviceRgbCS'; + case 'DeviceCMYK': + case 'CMYK': + return 'DeviceCmykCS'; + case 'Pattern': + return ['PatternCS', null]; + default: + error('unrecognized colorspace ' + mode); + } + } else if (isArray(cs)) { + mode = cs[0].name; + this.mode = mode; + var numComps, params; + + switch (mode) { + case 'DeviceGray': + case 'G': + return 'DeviceGrayCS'; + case 'DeviceRGB': + case 'RGB': + return 'DeviceRgbCS'; + case 'DeviceCMYK': + case 'CMYK': + return 'DeviceCmykCS'; + case 'CalGray': + params = xref.fetchIfRef(cs[1]).getAll(); + return ['CalGrayCS', params]; + case 'CalRGB': + params = xref.fetchIfRef(cs[1]).getAll(); + return ['CalRGBCS', params]; + case 'ICCBased': + var stream = xref.fetchIfRef(cs[1]); + var dict = stream.dict; + numComps = dict.get('N'); + if (numComps === 1) { + return 'DeviceGrayCS'; + } else if (numComps === 3) { + return 'DeviceRgbCS'; + } else if (numComps === 4) { + return 'DeviceCmykCS'; + } + break; + case 'Pattern': + var basePatternCS = cs[1]; + if (basePatternCS) { + basePatternCS = ColorSpace.parseToIR(basePatternCS, xref, res); + } + return ['PatternCS', basePatternCS]; + case 'Indexed': + case 'I': + var baseIndexedCS = ColorSpace.parseToIR(cs[1], xref, res); + var hiVal = cs[2] + 1; + var lookup = xref.fetchIfRef(cs[3]); + if (isStream(lookup)) { + lookup = lookup.getBytes(); + } + return ['IndexedCS', baseIndexedCS, hiVal, lookup]; + case 'Separation': + case 'DeviceN': + var name = cs[1]; + numComps = 1; + if (isName(name)) { + numComps = 1; + } else if (isArray(name)) { + numComps = name.length; + } + var alt = ColorSpace.parseToIR(cs[2], xref, res); + var tintFnIR = PDFFunction.getIR(xref, xref.fetchIfRef(cs[3])); + return ['AlternateCS', numComps, alt, tintFnIR]; + case 'Lab': + params = cs[1].getAll(); + return ['LabCS', params]; + default: + error('unimplemented color space object "' + mode + '"'); + } + } else { + error('unrecognized color space object: "' + cs + '"'); + } + return null; + }; + /** + * Checks if a decode map matches the default decode map for a color space. + * This handles the general decode maps where there are two values per + * component. e.g. [0, 1, 0, 1, 0, 1] for a RGB color. + * This does not handle Lab, Indexed, or Pattern decode maps since they are + * slightly different. + * @param {Array} decode Decode map (usually from an image). + * @param {Number} n Number of components the color space has. + */ + ColorSpace.isDefaultDecode = function ColorSpace_isDefaultDecode(decode, n) { + if (!decode) { + return true; + } + + if (n * 2 !== decode.length) { + warn('The decode map is not the correct length'); + return true; + } + for (var i = 0, ii = decode.length; i < ii; i += 2) { + if (decode[i] !== 0 || decode[i + 1] !== 1) { + return false; + } + } + return true; + }; + + ColorSpace.singletons = { + get gray() { + return shadow(this, 'gray', new DeviceGrayCS()); + }, + get rgb() { + return shadow(this, 'rgb', new DeviceRgbCS()); + }, + get cmyk() { + return shadow(this, 'cmyk', new DeviceCmykCS()); + } + }; + + return ColorSpace; +})(); + +/** + * Alternate color space handles both Separation and DeviceN color spaces. A + * Separation color space is actually just a DeviceN with one color component. + * Both color spaces use a tinting function to convert colors to a base color + * space. + */ +var AlternateCS = (function AlternateCSClosure() { + function AlternateCS(numComps, base, tintFn) { + this.name = 'Alternate'; + this.numComps = numComps; + this.defaultColor = new Float32Array(numComps); + for (var i = 0; i < numComps; ++i) { + this.defaultColor[i] = 1; + } + this.base = base; + this.tintFn = tintFn; + this.tmpBuf = new Float32Array(base.numComps); + } + + AlternateCS.prototype = { + getRgb: ColorSpace.prototype.getRgb, + getRgbItem: function AlternateCS_getRgbItem(src, srcOffset, + dest, destOffset) { + var tmpBuf = this.tmpBuf; + this.tintFn(src, srcOffset, tmpBuf, 0); + this.base.getRgbItem(tmpBuf, 0, dest, destOffset); + }, + getRgbBuffer: function AlternateCS_getRgbBuffer(src, srcOffset, count, + dest, destOffset, bits, + alpha01) { + var tintFn = this.tintFn; + var base = this.base; + var scale = 1 / ((1 << bits) - 1); + var baseNumComps = base.numComps; + var usesZeroToOneRange = base.usesZeroToOneRange; + var isPassthrough = (base.isPassthrough(8) || !usesZeroToOneRange) && + alpha01 === 0; + var pos = isPassthrough ? destOffset : 0; + var baseBuf = isPassthrough ? dest : new Uint8Array(baseNumComps * count); + var numComps = this.numComps; + + var scaled = new Float32Array(numComps); + var tinted = new Float32Array(baseNumComps); + var i, j; + if (usesZeroToOneRange) { + for (i = 0; i < count; i++) { + for (j = 0; j < numComps; j++) { + scaled[j] = src[srcOffset++] * scale; + } + tintFn(scaled, 0, tinted, 0); + for (j = 0; j < baseNumComps; j++) { + baseBuf[pos++] = tinted[j] * 255; + } + } + } else { + for (i = 0; i < count; i++) { + for (j = 0; j < numComps; j++) { + scaled[j] = src[srcOffset++] * scale; + } + tintFn(scaled, 0, tinted, 0); + base.getRgbItem(tinted, 0, baseBuf, pos); + pos += baseNumComps; + } + } + if (!isPassthrough) { + base.getRgbBuffer(baseBuf, 0, count, dest, destOffset, 8, alpha01); + } + }, + getOutputLength: function AlternateCS_getOutputLength(inputLength, + alpha01) { + return this.base.getOutputLength(inputLength * + this.base.numComps / this.numComps, + alpha01); + }, + isPassthrough: ColorSpace.prototype.isPassthrough, + fillRgb: ColorSpace.prototype.fillRgb, + isDefaultDecode: function AlternateCS_isDefaultDecode(decodeMap) { + return ColorSpace.isDefaultDecode(decodeMap, this.numComps); + }, + usesZeroToOneRange: true + }; + + return AlternateCS; +})(); + +var PatternCS = (function PatternCSClosure() { + function PatternCS(baseCS) { + this.name = 'Pattern'; + this.base = baseCS; + } + PatternCS.prototype = {}; + + return PatternCS; +})(); + +var IndexedCS = (function IndexedCSClosure() { + function IndexedCS(base, highVal, lookup) { + this.name = 'Indexed'; + this.numComps = 1; + this.defaultColor = new Uint8Array([0]); + this.base = base; + this.highVal = highVal; + + var baseNumComps = base.numComps; + var length = baseNumComps * highVal; + var lookupArray; + + if (isStream(lookup)) { + lookupArray = new Uint8Array(length); + var bytes = lookup.getBytes(length); + lookupArray.set(bytes); + } else if (isString(lookup)) { + lookupArray = new Uint8Array(length); + for (var i = 0; i < length; ++i) { + lookupArray[i] = lookup.charCodeAt(i); + } + } else if (lookup instanceof Uint8Array || lookup instanceof Array) { + lookupArray = lookup; + } else { + error('Unrecognized lookup table: ' + lookup); + } + this.lookup = lookupArray; + } + + IndexedCS.prototype = { + getRgb: ColorSpace.prototype.getRgb, + getRgbItem: function IndexedCS_getRgbItem(src, srcOffset, + dest, destOffset) { + var numComps = this.base.numComps; + var start = src[srcOffset] * numComps; + this.base.getRgbItem(this.lookup, start, dest, destOffset); + }, + getRgbBuffer: function IndexedCS_getRgbBuffer(src, srcOffset, count, + dest, destOffset, bits, + alpha01) { + var base = this.base; + var numComps = base.numComps; + var outputDelta = base.getOutputLength(numComps, alpha01); + var lookup = this.lookup; + + for (var i = 0; i < count; ++i) { + var lookupPos = src[srcOffset++] * numComps; + base.getRgbBuffer(lookup, lookupPos, 1, dest, destOffset, 8, alpha01); + destOffset += outputDelta; + } + }, + getOutputLength: function IndexedCS_getOutputLength(inputLength, alpha01) { + return this.base.getOutputLength(inputLength * this.base.numComps, + alpha01); + }, + isPassthrough: ColorSpace.prototype.isPassthrough, + fillRgb: ColorSpace.prototype.fillRgb, + isDefaultDecode: function IndexedCS_isDefaultDecode(decodeMap) { + // indexed color maps shouldn't be changed + return true; + }, + usesZeroToOneRange: true + }; + return IndexedCS; +})(); + +var DeviceGrayCS = (function DeviceGrayCSClosure() { + function DeviceGrayCS() { + this.name = 'DeviceGray'; + this.numComps = 1; + this.defaultColor = new Float32Array([0]); + } + + DeviceGrayCS.prototype = { + getRgb: ColorSpace.prototype.getRgb, + getRgbItem: function DeviceGrayCS_getRgbItem(src, srcOffset, + dest, destOffset) { + var c = (src[srcOffset] * 255) | 0; + c = c < 0 ? 0 : c > 255 ? 255 : c; + dest[destOffset] = dest[destOffset + 1] = dest[destOffset + 2] = c; + }, + getRgbBuffer: function DeviceGrayCS_getRgbBuffer(src, srcOffset, count, + dest, destOffset, bits, + alpha01) { + var scale = 255 / ((1 << bits) - 1); + var j = srcOffset, q = destOffset; + for (var i = 0; i < count; ++i) { + var c = (scale * src[j++]) | 0; + dest[q++] = c; + dest[q++] = c; + dest[q++] = c; + q += alpha01; + } + }, + getOutputLength: function DeviceGrayCS_getOutputLength(inputLength, + alpha01) { + return inputLength * (3 + alpha01); + }, + isPassthrough: ColorSpace.prototype.isPassthrough, + fillRgb: ColorSpace.prototype.fillRgb, + isDefaultDecode: function DeviceGrayCS_isDefaultDecode(decodeMap) { + return ColorSpace.isDefaultDecode(decodeMap, this.numComps); + }, + usesZeroToOneRange: true + }; + return DeviceGrayCS; +})(); + +var DeviceRgbCS = (function DeviceRgbCSClosure() { + function DeviceRgbCS() { + this.name = 'DeviceRGB'; + this.numComps = 3; + this.defaultColor = new Float32Array([0, 0, 0]); + } + DeviceRgbCS.prototype = { + getRgb: ColorSpace.prototype.getRgb, + getRgbItem: function DeviceRgbCS_getRgbItem(src, srcOffset, + dest, destOffset) { + var r = (src[srcOffset] * 255) | 0; + var g = (src[srcOffset + 1] * 255) | 0; + var b = (src[srcOffset + 2] * 255) | 0; + dest[destOffset] = r < 0 ? 0 : r > 255 ? 255 : r; + dest[destOffset + 1] = g < 0 ? 0 : g > 255 ? 255 : g; + dest[destOffset + 2] = b < 0 ? 0 : b > 255 ? 255 : b; + }, + getRgbBuffer: function DeviceRgbCS_getRgbBuffer(src, srcOffset, count, + dest, destOffset, bits, + alpha01) { + if (bits === 8 && alpha01 === 0) { + dest.set(src.subarray(srcOffset, srcOffset + count * 3), destOffset); + return; + } + var scale = 255 / ((1 << bits) - 1); + var j = srcOffset, q = destOffset; + for (var i = 0; i < count; ++i) { + dest[q++] = (scale * src[j++]) | 0; + dest[q++] = (scale * src[j++]) | 0; + dest[q++] = (scale * src[j++]) | 0; + q += alpha01; + } + }, + getOutputLength: function DeviceRgbCS_getOutputLength(inputLength, + alpha01) { + return (inputLength * (3 + alpha01) / 3) | 0; + }, + isPassthrough: function DeviceRgbCS_isPassthrough(bits) { + return bits === 8; + }, + fillRgb: ColorSpace.prototype.fillRgb, + isDefaultDecode: function DeviceRgbCS_isDefaultDecode(decodeMap) { + return ColorSpace.isDefaultDecode(decodeMap, this.numComps); + }, + usesZeroToOneRange: true + }; + return DeviceRgbCS; +})(); + +var DeviceCmykCS = (function DeviceCmykCSClosure() { + // The coefficients below was found using numerical analysis: the method of + // steepest descent for the sum((f_i - color_value_i)^2) for r/g/b colors, + // where color_value is the tabular value from the table of sampled RGB colors + // from CMYK US Web Coated (SWOP) colorspace, and f_i is the corresponding + // CMYK color conversion using the estimation below: + // f(A, B,.. N) = Acc+Bcm+Ccy+Dck+c+Fmm+Gmy+Hmk+Im+Jyy+Kyk+Ly+Mkk+Nk+255 + function convertToRgb(src, srcOffset, srcScale, dest, destOffset) { + var c = src[srcOffset + 0] * srcScale; + var m = src[srcOffset + 1] * srcScale; + var y = src[srcOffset + 2] * srcScale; + var k = src[srcOffset + 3] * srcScale; + + var r = + (c * (-4.387332384609988 * c + 54.48615194189176 * m + + 18.82290502165302 * y + 212.25662451639585 * k + + -285.2331026137004) + + m * (1.7149763477362134 * m - 5.6096736904047315 * y + + -17.873870861415444 * k - 5.497006427196366) + + y * (-2.5217340131683033 * y - 21.248923337353073 * k + + 17.5119270841813) + + k * (-21.86122147463605 * k - 189.48180835922747) + 255) | 0; + var g = + (c * (8.841041422036149 * c + 60.118027045597366 * m + + 6.871425592049007 * y + 31.159100130055922 * k + + -79.2970844816548) + + m * (-15.310361306967817 * m + 17.575251261109482 * y + + 131.35250912493976 * k - 190.9453302588951) + + y * (4.444339102852739 * y + 9.8632861493405 * k - 24.86741582555878) + + k * (-20.737325471181034 * k - 187.80453709719578) + 255) | 0; + var b = + (c * (0.8842522430003296 * c + 8.078677503112928 * m + + 30.89978309703729 * y - 0.23883238689178934 * k + + -14.183576799673286) + + m * (10.49593273432072 * m + 63.02378494754052 * y + + 50.606957656360734 * k - 112.23884253719248) + + y * (0.03296041114873217 * y + 115.60384449646641 * k + + -193.58209356861505) + + k * (-22.33816807309886 * k - 180.12613974708367) + 255) | 0; + + dest[destOffset] = r > 255 ? 255 : r < 0 ? 0 : r; + dest[destOffset + 1] = g > 255 ? 255 : g < 0 ? 0 : g; + dest[destOffset + 2] = b > 255 ? 255 : b < 0 ? 0 : b; + } + + function DeviceCmykCS() { + this.name = 'DeviceCMYK'; + this.numComps = 4; + this.defaultColor = new Float32Array([0, 0, 0, 1]); + } + DeviceCmykCS.prototype = { + getRgb: ColorSpace.prototype.getRgb, + getRgbItem: function DeviceCmykCS_getRgbItem(src, srcOffset, + dest, destOffset) { + convertToRgb(src, srcOffset, 1, dest, destOffset); + }, + getRgbBuffer: function DeviceCmykCS_getRgbBuffer(src, srcOffset, count, + dest, destOffset, bits, + alpha01) { + var scale = 1 / ((1 << bits) - 1); + for (var i = 0; i < count; i++) { + convertToRgb(src, srcOffset, scale, dest, destOffset); + srcOffset += 4; + destOffset += 3 + alpha01; + } + }, + getOutputLength: function DeviceCmykCS_getOutputLength(inputLength, + alpha01) { + return (inputLength / 4 * (3 + alpha01)) | 0; + }, + isPassthrough: ColorSpace.prototype.isPassthrough, + fillRgb: ColorSpace.prototype.fillRgb, + isDefaultDecode: function DeviceCmykCS_isDefaultDecode(decodeMap) { + return ColorSpace.isDefaultDecode(decodeMap, this.numComps); + }, + usesZeroToOneRange: true + }; + + return DeviceCmykCS; +})(); + +// +// CalGrayCS: Based on "PDF Reference, Sixth Ed", p.245 +// +var CalGrayCS = (function CalGrayCSClosure() { + function CalGrayCS(whitePoint, blackPoint, gamma) { + this.name = 'CalGray'; + this.numComps = 1; + this.defaultColor = new Float32Array([0]); + + if (!whitePoint) { + error('WhitePoint missing - required for color space CalGray'); + } + blackPoint = blackPoint || [0, 0, 0]; + gamma = gamma || 1; + + // Translate arguments to spec variables. + this.XW = whitePoint[0]; + this.YW = whitePoint[1]; + this.ZW = whitePoint[2]; + + this.XB = blackPoint[0]; + this.YB = blackPoint[1]; + this.ZB = blackPoint[2]; + + this.G = gamma; + + // Validate variables as per spec. + if (this.XW < 0 || this.ZW < 0 || this.YW !== 1) { + error('Invalid WhitePoint components for ' + this.name + + ', no fallback available'); + } + + if (this.XB < 0 || this.YB < 0 || this.ZB < 0) { + info('Invalid BlackPoint for ' + this.name + ', falling back to default'); + this.XB = this.YB = this.ZB = 0; + } + + if (this.XB !== 0 || this.YB !== 0 || this.ZB !== 0) { + warn(this.name + ', BlackPoint: XB: ' + this.XB + ', YB: ' + this.YB + + ', ZB: ' + this.ZB + ', only default values are supported.'); + } + + if (this.G < 1) { + info('Invalid Gamma: ' + this.G + ' for ' + this.name + + ', falling back to default'); + this.G = 1; + } + } + + function convertToRgb(cs, src, srcOffset, dest, destOffset, scale) { + // A represents a gray component of a calibrated gray space. + // A <---> AG in the spec + var A = src[srcOffset] * scale; + var AG = Math.pow(A, cs.G); + + // Computes L as per spec. ( = cs.YW * AG ) + // Except if other than default BlackPoint values are used. + var L = cs.YW * AG; + // http://www.poynton.com/notes/colour_and_gamma/ColorFAQ.html, Ch 4. + // Convert values to rgb range [0, 255]. + var val = Math.max(295.8 * Math.pow(L, 0.333333333333333333) - 40.8, 0) | 0; + dest[destOffset] = val; + dest[destOffset + 1] = val; + dest[destOffset + 2] = val; + } + + CalGrayCS.prototype = { + getRgb: ColorSpace.prototype.getRgb, + getRgbItem: function CalGrayCS_getRgbItem(src, srcOffset, + dest, destOffset) { + convertToRgb(this, src, srcOffset, dest, destOffset, 1); + }, + getRgbBuffer: function CalGrayCS_getRgbBuffer(src, srcOffset, count, + dest, destOffset, bits, + alpha01) { + var scale = 1 / ((1 << bits) - 1); + + for (var i = 0; i < count; ++i) { + convertToRgb(this, src, srcOffset, dest, destOffset, scale); + srcOffset += 1; + destOffset += 3 + alpha01; + } + }, + getOutputLength: function CalGrayCS_getOutputLength(inputLength, alpha01) { + return inputLength * (3 + alpha01); + }, + isPassthrough: ColorSpace.prototype.isPassthrough, + fillRgb: ColorSpace.prototype.fillRgb, + isDefaultDecode: function CalGrayCS_isDefaultDecode(decodeMap) { + return ColorSpace.isDefaultDecode(decodeMap, this.numComps); + }, + usesZeroToOneRange: true + }; + return CalGrayCS; +})(); + +// +// CalRGBCS: Based on "PDF Reference, Sixth Ed", p.247 +// +var CalRGBCS = (function CalRGBCSClosure() { + + // See http://www.brucelindbloom.com/index.html?Eqn_ChromAdapt.html for these + // matrices. + var BRADFORD_SCALE_MATRIX = new Float32Array([ + 0.8951, 0.2664, -0.1614, + -0.7502, 1.7135, 0.0367, + 0.0389, -0.0685, 1.0296]); + + var BRADFORD_SCALE_INVERSE_MATRIX = new Float32Array([ + 0.9869929, -0.1470543, 0.1599627, + 0.4323053, 0.5183603, 0.0492912, + -0.0085287, 0.0400428, 0.9684867]); + + // See http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html. + var SRGB_D65_XYZ_TO_RGB_MATRIX = new Float32Array([ + 3.2404542, -1.5371385, -0.4985314, + -0.9692660, 1.8760108, 0.0415560, + 0.0556434, -0.2040259, 1.0572252]); + + var FLAT_WHITEPOINT_MATRIX = new Float32Array([1, 1, 1]); + + var tempNormalizeMatrix = new Float32Array(3); + var tempConvertMatrix1 = new Float32Array(3); + var tempConvertMatrix2 = new Float32Array(3); + + var DECODE_L_CONSTANT = Math.pow(((8 + 16) / 116), 3) / 8.0; + + function CalRGBCS(whitePoint, blackPoint, gamma, matrix) { + this.name = 'CalRGB'; + this.numComps = 3; + this.defaultColor = new Float32Array(3); + + if (!whitePoint) { + error('WhitePoint missing - required for color space CalRGB'); + } + blackPoint = blackPoint || new Float32Array(3); + gamma = gamma || new Float32Array([1, 1, 1]); + matrix = matrix || new Float32Array([1, 0, 0, 0, 1, 0, 0, 0, 1]); + + // Translate arguments to spec variables. + var XW = whitePoint[0]; + var YW = whitePoint[1]; + var ZW = whitePoint[2]; + this.whitePoint = whitePoint; + + var XB = blackPoint[0]; + var YB = blackPoint[1]; + var ZB = blackPoint[2]; + this.blackPoint = blackPoint; + + this.GR = gamma[0]; + this.GG = gamma[1]; + this.GB = gamma[2]; + + this.MXA = matrix[0]; + this.MYA = matrix[1]; + this.MZA = matrix[2]; + this.MXB = matrix[3]; + this.MYB = matrix[4]; + this.MZB = matrix[5]; + this.MXC = matrix[6]; + this.MYC = matrix[7]; + this.MZC = matrix[8]; + + // Validate variables as per spec. + if (XW < 0 || ZW < 0 || YW !== 1) { + error('Invalid WhitePoint components for ' + this.name + + ', no fallback available'); + } + + if (XB < 0 || YB < 0 || ZB < 0) { + info('Invalid BlackPoint for ' + this.name + ' [' + XB + ', ' + YB + + ', ' + ZB + '], falling back to default'); + this.blackPoint = new Float32Array(3); + } + + if (this.GR < 0 || this.GG < 0 || this.GB < 0) { + info('Invalid Gamma [' + this.GR + ', ' + this.GG + ', ' + this.GB + + '] for ' + this.name + ', falling back to default'); + this.GR = this.GG = this.GB = 1; + } + + if (this.MXA < 0 || this.MYA < 0 || this.MZA < 0 || + this.MXB < 0 || this.MYB < 0 || this.MZB < 0 || + this.MXC < 0 || this.MYC < 0 || this.MZC < 0) { + info('Invalid Matrix for ' + this.name + ' [' + + this.MXA + ', ' + this.MYA + ', ' + this.MZA + + this.MXB + ', ' + this.MYB + ', ' + this.MZB + + this.MXC + ', ' + this.MYC + ', ' + this.MZC + + '], falling back to default'); + this.MXA = this.MYB = this.MZC = 1; + this.MXB = this.MYA = this.MZA = this.MXC = this.MYC = this.MZB = 0; + } + } + + function matrixProduct(a, b, result) { + result[0] = a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; + result[1] = a[3] * b[0] + a[4] * b[1] + a[5] * b[2]; + result[2] = a[6] * b[0] + a[7] * b[1] + a[8] * b[2]; + } + + function convertToFlat(sourceWhitePoint, LMS, result) { + result[0] = LMS[0] * 1 / sourceWhitePoint[0]; + result[1] = LMS[1] * 1 / sourceWhitePoint[1]; + result[2] = LMS[2] * 1 / sourceWhitePoint[2]; + } + + function convertToD65(sourceWhitePoint, LMS, result) { + var D65X = 0.95047; + var D65Y = 1; + var D65Z = 1.08883; + + result[0] = LMS[0] * D65X / sourceWhitePoint[0]; + result[1] = LMS[1] * D65Y / sourceWhitePoint[1]; + result[2] = LMS[2] * D65Z / sourceWhitePoint[2]; + } + + function sRGBTransferFunction(color) { + // See http://en.wikipedia.org/wiki/SRGB. + if (color <= 0.0031308){ + return adjustToRange(0, 1, 12.92 * color); + } + + return adjustToRange(0, 1, (1 + 0.055) * Math.pow(color, 1 / 2.4) - 0.055); + } + + function adjustToRange(min, max, value) { + return Math.max(min, Math.min(max, value)); + } + + function decodeL(L) { + if (L < 0) { + return -decodeL(-L); + } + + if (L > 8.0) { + return Math.pow(((L + 16) / 116), 3); + } + + return L * DECODE_L_CONSTANT; + } + + function compensateBlackPoint(sourceBlackPoint, XYZ_Flat, result) { + + // In case the blackPoint is already the default blackPoint then there is + // no need to do compensation. + if (sourceBlackPoint[0] === 0 && + sourceBlackPoint[1] === 0 && + sourceBlackPoint[2] === 0) { + result[0] = XYZ_Flat[0]; + result[1] = XYZ_Flat[1]; + result[2] = XYZ_Flat[2]; + return; + } + + // For the blackPoint calculation details, please see + // http://www.adobe.com/content/dam/Adobe/en/devnet/photoshop/sdk/ + // AdobeBPC.pdf. + // The destination blackPoint is the default blackPoint [0, 0, 0]. + var zeroDecodeL = decodeL(0); + + var X_DST = zeroDecodeL; + var X_SRC = decodeL(sourceBlackPoint[0]); + + var Y_DST = zeroDecodeL; + var Y_SRC = decodeL(sourceBlackPoint[1]); + + var Z_DST = zeroDecodeL; + var Z_SRC = decodeL(sourceBlackPoint[2]); + + var X_Scale = (1 - X_DST) / (1 - X_SRC); + var X_Offset = 1 - X_Scale; + + var Y_Scale = (1 - Y_DST) / (1 - Y_SRC); + var Y_Offset = 1 - Y_Scale; + + var Z_Scale = (1 - Z_DST) / (1 - Z_SRC); + var Z_Offset = 1 - Z_Scale; + + result[0] = XYZ_Flat[0] * X_Scale + X_Offset; + result[1] = XYZ_Flat[1] * Y_Scale + Y_Offset; + result[2] = XYZ_Flat[2] * Z_Scale + Z_Offset; + } + + function normalizeWhitePointToFlat(sourceWhitePoint, XYZ_In, result) { + + // In case the whitePoint is already flat then there is no need to do + // normalization. + if (sourceWhitePoint[0] === 1 && sourceWhitePoint[2] === 1) { + result[0] = XYZ_In[0]; + result[1] = XYZ_In[1]; + result[2] = XYZ_In[2]; + return; + } + + var LMS = result; + matrixProduct(BRADFORD_SCALE_MATRIX, XYZ_In, LMS); + + var LMS_Flat = tempNormalizeMatrix; + convertToFlat(sourceWhitePoint, LMS, LMS_Flat); + + matrixProduct(BRADFORD_SCALE_INVERSE_MATRIX, LMS_Flat, result); + } + + function normalizeWhitePointToD65(sourceWhitePoint, XYZ_In, result) { + + var LMS = result; + matrixProduct(BRADFORD_SCALE_MATRIX, XYZ_In, LMS); + + var LMS_D65 = tempNormalizeMatrix; + convertToD65(sourceWhitePoint, LMS, LMS_D65); + + matrixProduct(BRADFORD_SCALE_INVERSE_MATRIX, LMS_D65, result); + } + + function convertToRgb(cs, src, srcOffset, dest, destOffset, scale) { + // A, B and C represent a red, green and blue components of a calibrated + // rgb space. + var A = adjustToRange(0, 1, src[srcOffset] * scale); + var B = adjustToRange(0, 1, src[srcOffset + 1] * scale); + var C = adjustToRange(0, 1, src[srcOffset + 2] * scale); + + // A <---> AGR in the spec + // B <---> BGG in the spec + // C <---> CGB in the spec + var AGR = Math.pow(A, cs.GR); + var BGG = Math.pow(B, cs.GG); + var CGB = Math.pow(C, cs.GB); + + // Computes intermediate variables L, M, N as per spec. + // To decode X, Y, Z values map L, M, N directly to them. + var X = cs.MXA * AGR + cs.MXB * BGG + cs.MXC * CGB; + var Y = cs.MYA * AGR + cs.MYB * BGG + cs.MYC * CGB; + var Z = cs.MZA * AGR + cs.MZB * BGG + cs.MZC * CGB; + + // The following calculations are based on this document: + // http://www.adobe.com/content/dam/Adobe/en/devnet/photoshop/sdk/ + // AdobeBPC.pdf. + var XYZ = tempConvertMatrix1; + XYZ[0] = X; + XYZ[1] = Y; + XYZ[2] = Z; + var XYZ_Flat = tempConvertMatrix2; + + normalizeWhitePointToFlat(cs.whitePoint, XYZ, XYZ_Flat); + + var XYZ_Black = tempConvertMatrix1; + compensateBlackPoint(cs.blackPoint, XYZ_Flat, XYZ_Black); + + var XYZ_D65 = tempConvertMatrix2; + normalizeWhitePointToD65(FLAT_WHITEPOINT_MATRIX, XYZ_Black, XYZ_D65); + + var SRGB = tempConvertMatrix1; + matrixProduct(SRGB_D65_XYZ_TO_RGB_MATRIX, XYZ_D65, SRGB); + + var sR = sRGBTransferFunction(SRGB[0]); + var sG = sRGBTransferFunction(SRGB[1]); + var sB = sRGBTransferFunction(SRGB[2]); + + // Convert the values to rgb range [0, 255]. + dest[destOffset] = Math.round(sR * 255); + dest[destOffset + 1] = Math.round(sG * 255); + dest[destOffset + 2] = Math.round(sB * 255); + } + + CalRGBCS.prototype = { + getRgb: function CalRGBCS_getRgb(src, srcOffset) { + var rgb = new Uint8Array(3); + this.getRgbItem(src, srcOffset, rgb, 0); + return rgb; + }, + getRgbItem: function CalRGBCS_getRgbItem(src, srcOffset, + dest, destOffset) { + convertToRgb(this, src, srcOffset, dest, destOffset, 1); + }, + getRgbBuffer: function CalRGBCS_getRgbBuffer(src, srcOffset, count, + dest, destOffset, bits, + alpha01) { + var scale = 1 / ((1 << bits) - 1); + + for (var i = 0; i < count; ++i) { + convertToRgb(this, src, srcOffset, dest, destOffset, scale); + srcOffset += 3; + destOffset += 3 + alpha01; + } + }, + getOutputLength: function CalRGBCS_getOutputLength(inputLength, alpha01) { + return (inputLength * (3 + alpha01) / 3) | 0; + }, + isPassthrough: ColorSpace.prototype.isPassthrough, + fillRgb: ColorSpace.prototype.fillRgb, + isDefaultDecode: function CalRGBCS_isDefaultDecode(decodeMap) { + return ColorSpace.isDefaultDecode(decodeMap, this.numComps); + }, + usesZeroToOneRange: true + }; + return CalRGBCS; +})(); + +// +// LabCS: Based on "PDF Reference, Sixth Ed", p.250 +// +var LabCS = (function LabCSClosure() { + function LabCS(whitePoint, blackPoint, range) { + this.name = 'Lab'; + this.numComps = 3; + this.defaultColor = new Float32Array([0, 0, 0]); + + if (!whitePoint) { + error('WhitePoint missing - required for color space Lab'); + } + blackPoint = blackPoint || [0, 0, 0]; + range = range || [-100, 100, -100, 100]; + + // Translate args to spec variables + this.XW = whitePoint[0]; + this.YW = whitePoint[1]; + this.ZW = whitePoint[2]; + this.amin = range[0]; + this.amax = range[1]; + this.bmin = range[2]; + this.bmax = range[3]; + + // These are here just for completeness - the spec doesn't offer any + // formulas that use BlackPoint in Lab + this.XB = blackPoint[0]; + this.YB = blackPoint[1]; + this.ZB = blackPoint[2]; + + // Validate vars as per spec + if (this.XW < 0 || this.ZW < 0 || this.YW !== 1) { + error('Invalid WhitePoint components, no fallback available'); + } + + if (this.XB < 0 || this.YB < 0 || this.ZB < 0) { + info('Invalid BlackPoint, falling back to default'); + this.XB = this.YB = this.ZB = 0; + } + + if (this.amin > this.amax || this.bmin > this.bmax) { + info('Invalid Range, falling back to defaults'); + this.amin = -100; + this.amax = 100; + this.bmin = -100; + this.bmax = 100; + } + } + + // Function g(x) from spec + function fn_g(x) { + if (x >= 6 / 29) { + return x * x * x; + } else { + return (108 / 841) * (x - 4 / 29); + } + } + + function decode(value, high1, low2, high2) { + return low2 + (value) * (high2 - low2) / (high1); + } + + // If decoding is needed maxVal should be 2^bits per component - 1. + function convertToRgb(cs, src, srcOffset, maxVal, dest, destOffset) { + // XXX: Lab input is in the range of [0, 100], [amin, amax], [bmin, bmax] + // not the usual [0, 1]. If a command like setFillColor is used the src + // values will already be within the correct range. However, if we are + // converting an image we have to map the values to the correct range given + // above. + // Ls,as,bs <---> L*,a*,b* in the spec + var Ls = src[srcOffset]; + var as = src[srcOffset + 1]; + var bs = src[srcOffset + 2]; + if (maxVal !== false) { + Ls = decode(Ls, maxVal, 0, 100); + as = decode(as, maxVal, cs.amin, cs.amax); + bs = decode(bs, maxVal, cs.bmin, cs.bmax); + } + + // Adjust limits of 'as' and 'bs' + as = as > cs.amax ? cs.amax : as < cs.amin ? cs.amin : as; + bs = bs > cs.bmax ? cs.bmax : bs < cs.bmin ? cs.bmin : bs; + + // Computes intermediate variables X,Y,Z as per spec + var M = (Ls + 16) / 116; + var L = M + (as / 500); + var N = M - (bs / 200); + + var X = cs.XW * fn_g(L); + var Y = cs.YW * fn_g(M); + var Z = cs.ZW * fn_g(N); + + var r, g, b; + // Using different conversions for D50 and D65 white points, + // per http://www.color.org/srgb.pdf + if (cs.ZW < 1) { + // Assuming D50 (X=0.9642, Y=1.00, Z=0.8249) + r = X * 3.1339 + Y * -1.6170 + Z * -0.4906; + g = X * -0.9785 + Y * 1.9160 + Z * 0.0333; + b = X * 0.0720 + Y * -0.2290 + Z * 1.4057; + } else { + // Assuming D65 (X=0.9505, Y=1.00, Z=1.0888) + r = X * 3.2406 + Y * -1.5372 + Z * -0.4986; + g = X * -0.9689 + Y * 1.8758 + Z * 0.0415; + b = X * 0.0557 + Y * -0.2040 + Z * 1.0570; + } + // clamp color values to [0,1] range then convert to [0,255] range. + dest[destOffset] = r <= 0 ? 0 : r >= 1 ? 255 : Math.sqrt(r) * 255 | 0; + dest[destOffset + 1] = g <= 0 ? 0 : g >= 1 ? 255 : Math.sqrt(g) * 255 | 0; + dest[destOffset + 2] = b <= 0 ? 0 : b >= 1 ? 255 : Math.sqrt(b) * 255 | 0; + } + + LabCS.prototype = { + getRgb: ColorSpace.prototype.getRgb, + getRgbItem: function LabCS_getRgbItem(src, srcOffset, dest, destOffset) { + convertToRgb(this, src, srcOffset, false, dest, destOffset); + }, + getRgbBuffer: function LabCS_getRgbBuffer(src, srcOffset, count, + dest, destOffset, bits, + alpha01) { + var maxVal = (1 << bits) - 1; + for (var i = 0; i < count; i++) { + convertToRgb(this, src, srcOffset, maxVal, dest, destOffset); + srcOffset += 3; + destOffset += 3 + alpha01; + } + }, + getOutputLength: function LabCS_getOutputLength(inputLength, alpha01) { + return (inputLength * (3 + alpha01) / 3) | 0; + }, + isPassthrough: ColorSpace.prototype.isPassthrough, + fillRgb: ColorSpace.prototype.fillRgb, + isDefaultDecode: function LabCS_isDefaultDecode(decodeMap) { + // XXX: Decoding is handled with the lab conversion because of the strange + // ranges that are used. + return true; + }, + usesZeroToOneRange: false + }; + return LabCS; +})(); + + +var ARCFourCipher = (function ARCFourCipherClosure() { + function ARCFourCipher(key) { + this.a = 0; + this.b = 0; + var s = new Uint8Array(256); + var i, j = 0, tmp, keyLength = key.length; + for (i = 0; i < 256; ++i) { + s[i] = i; + } + for (i = 0; i < 256; ++i) { + tmp = s[i]; + j = (j + tmp + key[i % keyLength]) & 0xFF; + s[i] = s[j]; + s[j] = tmp; + } + this.s = s; + } + + ARCFourCipher.prototype = { + encryptBlock: function ARCFourCipher_encryptBlock(data) { + var i, n = data.length, tmp, tmp2; + var a = this.a, b = this.b, s = this.s; + var output = new Uint8Array(n); + for (i = 0; i < n; ++i) { + a = (a + 1) & 0xFF; + tmp = s[a]; + b = (b + tmp) & 0xFF; + tmp2 = s[b]; + s[a] = tmp2; + s[b] = tmp; + output[i] = data[i] ^ s[(tmp + tmp2) & 0xFF]; + } + this.a = a; + this.b = b; + return output; + } + }; + ARCFourCipher.prototype.decryptBlock = ARCFourCipher.prototype.encryptBlock; + + return ARCFourCipher; +})(); + +var calculateMD5 = (function calculateMD5Closure() { + var r = new Uint8Array([ + 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, + 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, + 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, + 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21]); + + var k = new Int32Array([ + -680876936, -389564586, 606105819, -1044525330, -176418897, 1200080426, + -1473231341, -45705983, 1770035416, -1958414417, -42063, -1990404162, + 1804603682, -40341101, -1502002290, 1236535329, -165796510, -1069501632, + 643717713, -373897302, -701558691, 38016083, -660478335, -405537848, + 568446438, -1019803690, -187363961, 1163531501, -1444681467, -51403784, + 1735328473, -1926607734, -378558, -2022574463, 1839030562, -35309556, + -1530992060, 1272893353, -155497632, -1094730640, 681279174, -358537222, + -722521979, 76029189, -640364487, -421815835, 530742520, -995338651, + -198630844, 1126891415, -1416354905, -57434055, 1700485571, -1894986606, + -1051523, -2054922799, 1873313359, -30611744, -1560198380, 1309151649, + -145523070, -1120210379, 718787259, -343485551]); + + function hash(data, offset, length) { + var h0 = 1732584193, h1 = -271733879, h2 = -1732584194, h3 = 271733878; + // pre-processing + var paddedLength = (length + 72) & ~63; // data + 9 extra bytes + var padded = new Uint8Array(paddedLength); + var i, j, n; + for (i = 0; i < length; ++i) { + padded[i] = data[offset++]; + } + padded[i++] = 0x80; + n = paddedLength - 8; + while (i < n) { + padded[i++] = 0; + } + padded[i++] = (length << 3) & 0xFF; + padded[i++] = (length >> 5) & 0xFF; + padded[i++] = (length >> 13) & 0xFF; + padded[i++] = (length >> 21) & 0xFF; + padded[i++] = (length >>> 29) & 0xFF; + padded[i++] = 0; + padded[i++] = 0; + padded[i++] = 0; + var w = new Int32Array(16); + for (i = 0; i < paddedLength;) { + for (j = 0; j < 16; ++j, i += 4) { + w[j] = (padded[i] | (padded[i + 1] << 8) | + (padded[i + 2] << 16) | (padded[i + 3] << 24)); + } + var a = h0, b = h1, c = h2, d = h3, f, g; + for (j = 0; j < 64; ++j) { + if (j < 16) { + f = (b & c) | ((~b) & d); + g = j; + } else if (j < 32) { + f = (d & b) | ((~d) & c); + g = (5 * j + 1) & 15; + } else if (j < 48) { + f = b ^ c ^ d; + g = (3 * j + 5) & 15; + } else { + f = c ^ (b | (~d)); + g = (7 * j) & 15; + } + var tmp = d, rotateArg = (a + f + k[j] + w[g]) | 0, rotate = r[j]; + d = c; + c = b; + b = (b + ((rotateArg << rotate) | (rotateArg >>> (32 - rotate)))) | 0; + a = tmp; + } + h0 = (h0 + a) | 0; + h1 = (h1 + b) | 0; + h2 = (h2 + c) | 0; + h3 = (h3 + d) | 0; + } + return new Uint8Array([ + h0 & 0xFF, (h0 >> 8) & 0xFF, (h0 >> 16) & 0xFF, (h0 >>> 24) & 0xFF, + h1 & 0xFF, (h1 >> 8) & 0xFF, (h1 >> 16) & 0xFF, (h1 >>> 24) & 0xFF, + h2 & 0xFF, (h2 >> 8) & 0xFF, (h2 >> 16) & 0xFF, (h2 >>> 24) & 0xFF, + h3 & 0xFF, (h3 >> 8) & 0xFF, (h3 >> 16) & 0xFF, (h3 >>> 24) & 0xFF + ]); + } + + return hash; +})(); +var Word64 = (function Word64Closure() { + function Word64(highInteger, lowInteger) { + this.high = highInteger | 0; + this.low = lowInteger | 0; + } + Word64.prototype = { + and: function Word64_and(word) { + this.high &= word.high; + this.low &= word.low; + }, + xor: function Word64_xor(word) { + this.high ^= word.high; + this.low ^= word.low; + }, + + or: function Word64_or(word) { + this.high |= word.high; + this.low |= word.low; + }, + + shiftRight: function Word64_shiftRight(places) { + if (places >= 32) { + this.low = (this.high >>> (places - 32)) | 0; + this.high = 0; + } else { + this.low = (this.low >>> places) | (this.high << (32 - places)); + this.high = (this.high >>> places) | 0; + } + }, + + shiftLeft: function Word64_shiftLeft(places) { + if (places >= 32) { + this.high = this.low << (places - 32); + this.low = 0; + } else { + this.high = (this.high << places) | (this.low >>> (32 - places)); + this.low = this.low << places; + } + }, + + rotateRight: function Word64_rotateRight(places) { + var low, high; + if (places & 32) { + high = this.low; + low = this.high; + } else { + low = this.low; + high = this.high; + } + places &= 31; + this.low = (low >>> places) | (high << (32 - places)); + this.high = (high >>> places) | (low << (32 - places)); + }, + + not: function Word64_not() { + this.high = ~this.high; + this.low = ~this.low; + }, + + add: function Word64_add(word) { + var lowAdd = (this.low >>> 0) + (word.low >>> 0); + var highAdd = (this.high >>> 0) + (word.high >>> 0); + if (lowAdd > 0xFFFFFFFF) { + highAdd += 1; + } + this.low = lowAdd | 0; + this.high = highAdd | 0; + }, + + copyTo: function Word64_copyTo(bytes, offset) { + bytes[offset] = (this.high >>> 24) & 0xFF; + bytes[offset + 1] = (this.high >> 16) & 0xFF; + bytes[offset + 2] = (this.high >> 8) & 0xFF; + bytes[offset + 3] = this.high & 0xFF; + bytes[offset + 4] = (this.low >>> 24) & 0xFF; + bytes[offset + 5] = (this.low >> 16) & 0xFF; + bytes[offset + 6] = (this.low >> 8) & 0xFF; + bytes[offset + 7] = this.low & 0xFF; + }, + + assign: function Word64_assign(word) { + this.high = word.high; + this.low = word.low; + } + }; + return Word64; +})(); + +var calculateSHA256 = (function calculateSHA256Closure() { + function rotr(x, n) { + return (x >>> n) | (x << 32 - n); + } + + function ch(x, y, z) { + return (x & y) ^ (~x & z); + } + + function maj(x, y, z) { + return (x & y) ^ (x & z) ^ (y & z); + } + + function sigma(x) { + return rotr(x, 2) ^ rotr(x, 13) ^ rotr(x, 22); + } + + function sigmaPrime(x) { + return rotr(x, 6) ^ rotr(x, 11) ^ rotr(x, 25); + } + + function littleSigma(x) { + return rotr(x, 7) ^ rotr(x, 18) ^ x >>> 3; + } + + function littleSigmaPrime(x) { + return rotr(x, 17) ^ rotr(x, 19) ^ x >>> 10; + } + + var k = [0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2]; + + function hash(data, offset, length) { + // initial hash values + var h0 = 0x6a09e667, h1 = 0xbb67ae85, h2 = 0x3c6ef372, + h3 = 0xa54ff53a, h4 = 0x510e527f, h5 = 0x9b05688c, + h6 = 0x1f83d9ab, h7 = 0x5be0cd19; + // pre-processing + var paddedLength = Math.ceil((length + 9) / 64) * 64; + var padded = new Uint8Array(paddedLength); + var i, j, n; + for (i = 0; i < length; ++i) { + padded[i] = data[offset++]; + } + padded[i++] = 0x80; + n = paddedLength - 8; + while (i < n) { + padded[i++] = 0; + } + padded[i++] = 0; + padded[i++] = 0; + padded[i++] = 0; + padded[i++] = (length >>> 29) & 0xFF; + padded[i++] = (length >> 21) & 0xFF; + padded[i++] = (length >> 13) & 0xFF; + padded[i++] = (length >> 5) & 0xFF; + padded[i++] = (length << 3) & 0xFF; + var w = new Uint32Array(64); + // for each 512 bit block + for (i = 0; i < paddedLength;) { + for (j = 0; j < 16; ++j) { + w[j] = (padded[i] << 24 | (padded[i + 1] << 16) | + (padded[i + 2] << 8) | (padded[i + 3])); + i += 4; + } + + for (j = 16; j < 64; ++j) { + w[j] = littleSigmaPrime(w[j - 2]) + w[j - 7] + + littleSigma(w[j - 15]) + w[j - 16] | 0; + } + var a = h0, b = h1, c = h2, d = h3, e = h4, + f = h5, g = h6, h = h7, t1, t2; + for (j = 0; j < 64; ++j) { + t1 = h + sigmaPrime(e) + ch(e, f, g) + k[j] + w[j]; + t2 = sigma(a) + maj(a, b, c); + h = g; + g = f; + f = e; + e = (d + t1) | 0; + d = c; + c = b; + b = a; + a = (t1 + t2) | 0; + } + h0 = (h0 + a) | 0; + h1 = (h1 + b) | 0; + h2 = (h2 + c) | 0; + h3 = (h3 + d) | 0; + h4 = (h4 + e) | 0; + h5 = (h5 + f) | 0; + h6 = (h6 + g) | 0; + h7 = (h7 + h) | 0; + } + return new Uint8Array([ + (h0 >> 24) & 0xFF, (h0 >> 16) & 0xFF, (h0 >> 8) & 0xFF, (h0) & 0xFF, + (h1 >> 24) & 0xFF, (h1 >> 16) & 0xFF, (h1 >> 8) & 0xFF, (h1) & 0xFF, + (h2 >> 24) & 0xFF, (h2 >> 16) & 0xFF, (h2 >> 8) & 0xFF, (h2) & 0xFF, + (h3 >> 24) & 0xFF, (h3 >> 16) & 0xFF, (h3 >> 8) & 0xFF, (h3) & 0xFF, + (h4 >> 24) & 0xFF, (h4 >> 16) & 0xFF, (h4 >> 8) & 0xFF, (h4) & 0xFF, + (h5 >> 24) & 0xFF, (h5 >> 16) & 0xFF, (h5 >> 8) & 0xFF, (h5) & 0xFF, + (h6 >> 24) & 0xFF, (h6 >> 16) & 0xFF, (h6 >> 8) & 0xFF, (h6) & 0xFF, + (h7 >> 24) & 0xFF, (h7 >> 16) & 0xFF, (h7 >> 8) & 0xFF, (h7) & 0xFF + ]); + } + + return hash; +})(); + +var calculateSHA512 = (function calculateSHA512Closure() { + function ch(result, x, y, z, tmp) { + result.assign(x); + result.and(y); + tmp.assign(x); + tmp.not(); + tmp.and(z); + result.xor(tmp); + } + + function maj(result, x, y, z, tmp) { + result.assign(x); + result.and(y); + tmp.assign(x); + tmp.and(z); + result.xor(tmp); + tmp.assign(y); + tmp.and(z); + result.xor(tmp); + } + + function sigma(result, x, tmp) { + result.assign(x); + result.rotateRight(28); + tmp.assign(x); + tmp.rotateRight(34); + result.xor(tmp); + tmp.assign(x); + tmp.rotateRight(39); + result.xor(tmp); + } + + function sigmaPrime(result, x, tmp) { + result.assign(x); + result.rotateRight(14); + tmp.assign(x); + tmp.rotateRight(18); + result.xor(tmp); + tmp.assign(x); + tmp.rotateRight(41); + result.xor(tmp); + } + + function littleSigma(result, x, tmp) { + result.assign(x); + result.rotateRight(1); + tmp.assign(x); + tmp.rotateRight(8); + result.xor(tmp); + tmp.assign(x); + tmp.shiftRight(7); + result.xor(tmp); + } + + function littleSigmaPrime(result, x, tmp) { + result.assign(x); + result.rotateRight(19); + tmp.assign(x); + tmp.rotateRight(61); + result.xor(tmp); + tmp.assign(x); + tmp.shiftRight(6); + result.xor(tmp); + } + + var k = [ + new Word64(0x428a2f98, 0xd728ae22), new Word64(0x71374491, 0x23ef65cd), + new Word64(0xb5c0fbcf, 0xec4d3b2f), new Word64(0xe9b5dba5, 0x8189dbbc), + new Word64(0x3956c25b, 0xf348b538), new Word64(0x59f111f1, 0xb605d019), + new Word64(0x923f82a4, 0xaf194f9b), new Word64(0xab1c5ed5, 0xda6d8118), + new Word64(0xd807aa98, 0xa3030242), new Word64(0x12835b01, 0x45706fbe), + new Word64(0x243185be, 0x4ee4b28c), new Word64(0x550c7dc3, 0xd5ffb4e2), + new Word64(0x72be5d74, 0xf27b896f), new Word64(0x80deb1fe, 0x3b1696b1), + new Word64(0x9bdc06a7, 0x25c71235), new Word64(0xc19bf174, 0xcf692694), + new Word64(0xe49b69c1, 0x9ef14ad2), new Word64(0xefbe4786, 0x384f25e3), + new Word64(0x0fc19dc6, 0x8b8cd5b5), new Word64(0x240ca1cc, 0x77ac9c65), + new Word64(0x2de92c6f, 0x592b0275), new Word64(0x4a7484aa, 0x6ea6e483), + new Word64(0x5cb0a9dc, 0xbd41fbd4), new Word64(0x76f988da, 0x831153b5), + new Word64(0x983e5152, 0xee66dfab), new Word64(0xa831c66d, 0x2db43210), + new Word64(0xb00327c8, 0x98fb213f), new Word64(0xbf597fc7, 0xbeef0ee4), + new Word64(0xc6e00bf3, 0x3da88fc2), new Word64(0xd5a79147, 0x930aa725), + new Word64(0x06ca6351, 0xe003826f), new Word64(0x14292967, 0x0a0e6e70), + new Word64(0x27b70a85, 0x46d22ffc), new Word64(0x2e1b2138, 0x5c26c926), + new Word64(0x4d2c6dfc, 0x5ac42aed), new Word64(0x53380d13, 0x9d95b3df), + new Word64(0x650a7354, 0x8baf63de), new Word64(0x766a0abb, 0x3c77b2a8), + new Word64(0x81c2c92e, 0x47edaee6), new Word64(0x92722c85, 0x1482353b), + new Word64(0xa2bfe8a1, 0x4cf10364), new Word64(0xa81a664b, 0xbc423001), + new Word64(0xc24b8b70, 0xd0f89791), new Word64(0xc76c51a3, 0x0654be30), + new Word64(0xd192e819, 0xd6ef5218), new Word64(0xd6990624, 0x5565a910), + new Word64(0xf40e3585, 0x5771202a), new Word64(0x106aa070, 0x32bbd1b8), + new Word64(0x19a4c116, 0xb8d2d0c8), new Word64(0x1e376c08, 0x5141ab53), + new Word64(0x2748774c, 0xdf8eeb99), new Word64(0x34b0bcb5, 0xe19b48a8), + new Word64(0x391c0cb3, 0xc5c95a63), new Word64(0x4ed8aa4a, 0xe3418acb), + new Word64(0x5b9cca4f, 0x7763e373), new Word64(0x682e6ff3, 0xd6b2b8a3), + new Word64(0x748f82ee, 0x5defb2fc), new Word64(0x78a5636f, 0x43172f60), + new Word64(0x84c87814, 0xa1f0ab72), new Word64(0x8cc70208, 0x1a6439ec), + new Word64(0x90befffa, 0x23631e28), new Word64(0xa4506ceb, 0xde82bde9), + new Word64(0xbef9a3f7, 0xb2c67915), new Word64(0xc67178f2, 0xe372532b), + new Word64(0xca273ece, 0xea26619c), new Word64(0xd186b8c7, 0x21c0c207), + new Word64(0xeada7dd6, 0xcde0eb1e), new Word64(0xf57d4f7f, 0xee6ed178), + new Word64(0x06f067aa, 0x72176fba), new Word64(0x0a637dc5, 0xa2c898a6), + new Word64(0x113f9804, 0xbef90dae), new Word64(0x1b710b35, 0x131c471b), + new Word64(0x28db77f5, 0x23047d84), new Word64(0x32caab7b, 0x40c72493), + new Word64(0x3c9ebe0a, 0x15c9bebc), new Word64(0x431d67c4, 0x9c100d4c), + new Word64(0x4cc5d4be, 0xcb3e42b6), new Word64(0x597f299c, 0xfc657e2a), + new Word64(0x5fcb6fab, 0x3ad6faec), new Word64(0x6c44198c, 0x4a475817)]; + + function hash(data, offset, length, mode384) { + mode384 = !!mode384; + // initial hash values + var h0, h1, h2, h3, h4, h5, h6, h7; + if (!mode384) { + h0 = new Word64(0x6a09e667, 0xf3bcc908); + h1 = new Word64(0xbb67ae85, 0x84caa73b); + h2 = new Word64(0x3c6ef372, 0xfe94f82b); + h3 = new Word64(0xa54ff53a, 0x5f1d36f1); + h4 = new Word64(0x510e527f, 0xade682d1); + h5 = new Word64(0x9b05688c, 0x2b3e6c1f); + h6 = new Word64(0x1f83d9ab, 0xfb41bd6b); + h7 = new Word64(0x5be0cd19, 0x137e2179); + } + else { + // SHA384 is exactly the same + // except with different starting values and a trimmed result + h0 = new Word64(0xcbbb9d5d, 0xc1059ed8); + h1 = new Word64(0x629a292a, 0x367cd507); + h2 = new Word64(0x9159015a, 0x3070dd17); + h3 = new Word64(0x152fecd8, 0xf70e5939); + h4 = new Word64(0x67332667, 0xffc00b31); + h5 = new Word64(0x8eb44a87, 0x68581511); + h6 = new Word64(0xdb0c2e0d, 0x64f98fa7); + h7 = new Word64(0x47b5481d, 0xbefa4fa4); + } + + // pre-processing + var paddedLength = Math.ceil((length + 17) / 128) * 128; + var padded = new Uint8Array(paddedLength); + var i, j, n; + for (i = 0; i < length; ++i) { + padded[i] = data[offset++]; + } + padded[i++] = 0x80; + n = paddedLength - 16; + while (i < n) { + padded[i++] = 0; + } + padded[i++] = 0; + padded[i++] = 0; + padded[i++] = 0; + padded[i++] = 0; + padded[i++] = 0; + padded[i++] = 0; + padded[i++] = 0; + padded[i++] = 0; + padded[i++] = 0; + padded[i++] = 0; + padded[i++] = 0; + padded[i++] = (length >>> 29) & 0xFF; + padded[i++] = (length >> 21) & 0xFF; + padded[i++] = (length >> 13) & 0xFF; + padded[i++] = (length >> 5) & 0xFF; + padded[i++] = (length << 3) & 0xFF; + + var w = new Array(80); + for (i = 0; i < 80; i++) { + w[i] = new Word64(0, 0); + } + var a = new Word64(0, 0), b = new Word64(0, 0), c = new Word64(0, 0); + var d = new Word64(0, 0), e = new Word64(0, 0), f = new Word64(0, 0); + var g = new Word64(0, 0), h = new Word64(0, 0); + var t1 = new Word64(0, 0), t2 = new Word64(0, 0); + var tmp1 = new Word64(0, 0), tmp2 = new Word64(0, 0), tmp3; + + // for each 1024 bit block + for (i = 0; i < paddedLength;) { + for (j = 0; j < 16; ++j) { + w[j].high = (padded[i] << 24) | (padded[i + 1] << 16) | + (padded[i + 2] << 8) | (padded[i + 3]); + w[j].low = (padded[i + 4]) << 24 | (padded[i + 5]) << 16 | + (padded[i + 6]) << 8 | (padded[i + 7]); + i += 8; + } + for (j = 16; j < 80; ++j) { + tmp3 = w[j]; + littleSigmaPrime(tmp3, w[j - 2], tmp2); + tmp3.add(w[j - 7]); + littleSigma(tmp1, w[j - 15], tmp2); + tmp3.add(tmp1); + tmp3.add(w[j - 16]); + } + + a.assign(h0); b.assign(h1); c.assign(h2); d.assign(h3); + e.assign(h4); f.assign(h5); g.assign(h6); h.assign(h7); + for (j = 0; j < 80; ++j) { + t1.assign(h); + sigmaPrime(tmp1, e, tmp2); + t1.add(tmp1); + ch(tmp1, e, f, g, tmp2); + t1.add(tmp1); + t1.add(k[j]); + t1.add(w[j]); + + sigma(t2, a, tmp2); + maj(tmp1, a, b, c, tmp2); + t2.add(tmp1); + + tmp3 = h; + h = g; + g = f; + f = e; + d.add(t1); + e = d; + d = c; + c = b; + b = a; + tmp3.assign(t1); + tmp3.add(t2); + a = tmp3; + } + h0.add(a); + h1.add(b); + h2.add(c); + h3.add(d); + h4.add(e); + h5.add(f); + h6.add(g); + h7.add(h); + } + + var result; + if (!mode384) { + result = new Uint8Array(64); + h0.copyTo(result,0); + h1.copyTo(result,8); + h2.copyTo(result,16); + h3.copyTo(result,24); + h4.copyTo(result,32); + h5.copyTo(result,40); + h6.copyTo(result,48); + h7.copyTo(result,56); + } + else { + result = new Uint8Array(48); + h0.copyTo(result,0); + h1.copyTo(result,8); + h2.copyTo(result,16); + h3.copyTo(result,24); + h4.copyTo(result,32); + h5.copyTo(result,40); + } + return result; + } + + return hash; +})(); +var calculateSHA384 = (function calculateSHA384Closure() { + function hash(data, offset, length) { + return calculateSHA512(data, offset, length, true); + } + + return hash; +})(); +var NullCipher = (function NullCipherClosure() { + function NullCipher() { + } + + NullCipher.prototype = { + decryptBlock: function NullCipher_decryptBlock(data) { + return data; + } + }; + + return NullCipher; +})(); + +var AES128Cipher = (function AES128CipherClosure() { + var rcon = new Uint8Array([ + 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, + 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, + 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, + 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, + 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, + 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, + 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, + 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, + 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, + 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, + 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, + 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, + 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, + 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, + 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, + 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, + 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, + 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, + 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, + 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, + 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, + 0x74, 0xe8, 0xcb, 0x8d]); + + var s = new Uint8Array([ + 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, + 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, + 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, + 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, + 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, + 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, + 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, + 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, + 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, + 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, + 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec, + 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, + 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, + 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, + 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, + 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, + 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, + 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, + 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, + 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, + 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, + 0xb0, 0x54, 0xbb, 0x16]); + + var inv_s = new Uint8Array([ + 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, + 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, + 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, + 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, + 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, + 0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, + 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, + 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, + 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, + 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, + 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41, + 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, + 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, + 0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, + 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, + 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, + 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, + 0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, + 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d, + 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, + 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, + 0x55, 0x21, 0x0c, 0x7d]); + var mixCol = new Uint8Array(256); + for (var i = 0; i < 256; i++) { + if (i < 128) { + mixCol[i] = i << 1; + } else { + mixCol[i] = (i << 1) ^ 0x1b; + } + } + var mix = new Uint32Array([ + 0x00000000, 0x0e090d0b, 0x1c121a16, 0x121b171d, 0x3824342c, 0x362d3927, + 0x24362e3a, 0x2a3f2331, 0x70486858, 0x7e416553, 0x6c5a724e, 0x62537f45, + 0x486c5c74, 0x4665517f, 0x547e4662, 0x5a774b69, 0xe090d0b0, 0xee99ddbb, + 0xfc82caa6, 0xf28bc7ad, 0xd8b4e49c, 0xd6bde997, 0xc4a6fe8a, 0xcaaff381, + 0x90d8b8e8, 0x9ed1b5e3, 0x8ccaa2fe, 0x82c3aff5, 0xa8fc8cc4, 0xa6f581cf, + 0xb4ee96d2, 0xbae79bd9, 0xdb3bbb7b, 0xd532b670, 0xc729a16d, 0xc920ac66, + 0xe31f8f57, 0xed16825c, 0xff0d9541, 0xf104984a, 0xab73d323, 0xa57ade28, + 0xb761c935, 0xb968c43e, 0x9357e70f, 0x9d5eea04, 0x8f45fd19, 0x814cf012, + 0x3bab6bcb, 0x35a266c0, 0x27b971dd, 0x29b07cd6, 0x038f5fe7, 0x0d8652ec, + 0x1f9d45f1, 0x119448fa, 0x4be30393, 0x45ea0e98, 0x57f11985, 0x59f8148e, + 0x73c737bf, 0x7dce3ab4, 0x6fd52da9, 0x61dc20a2, 0xad766df6, 0xa37f60fd, + 0xb16477e0, 0xbf6d7aeb, 0x955259da, 0x9b5b54d1, 0x894043cc, 0x87494ec7, + 0xdd3e05ae, 0xd33708a5, 0xc12c1fb8, 0xcf2512b3, 0xe51a3182, 0xeb133c89, + 0xf9082b94, 0xf701269f, 0x4de6bd46, 0x43efb04d, 0x51f4a750, 0x5ffdaa5b, + 0x75c2896a, 0x7bcb8461, 0x69d0937c, 0x67d99e77, 0x3daed51e, 0x33a7d815, + 0x21bccf08, 0x2fb5c203, 0x058ae132, 0x0b83ec39, 0x1998fb24, 0x1791f62f, + 0x764dd68d, 0x7844db86, 0x6a5fcc9b, 0x6456c190, 0x4e69e2a1, 0x4060efaa, + 0x527bf8b7, 0x5c72f5bc, 0x0605bed5, 0x080cb3de, 0x1a17a4c3, 0x141ea9c8, + 0x3e218af9, 0x302887f2, 0x223390ef, 0x2c3a9de4, 0x96dd063d, 0x98d40b36, + 0x8acf1c2b, 0x84c61120, 0xaef93211, 0xa0f03f1a, 0xb2eb2807, 0xbce2250c, + 0xe6956e65, 0xe89c636e, 0xfa877473, 0xf48e7978, 0xdeb15a49, 0xd0b85742, + 0xc2a3405f, 0xccaa4d54, 0x41ecdaf7, 0x4fe5d7fc, 0x5dfec0e1, 0x53f7cdea, + 0x79c8eedb, 0x77c1e3d0, 0x65daf4cd, 0x6bd3f9c6, 0x31a4b2af, 0x3fadbfa4, + 0x2db6a8b9, 0x23bfa5b2, 0x09808683, 0x07898b88, 0x15929c95, 0x1b9b919e, + 0xa17c0a47, 0xaf75074c, 0xbd6e1051, 0xb3671d5a, 0x99583e6b, 0x97513360, + 0x854a247d, 0x8b432976, 0xd134621f, 0xdf3d6f14, 0xcd267809, 0xc32f7502, + 0xe9105633, 0xe7195b38, 0xf5024c25, 0xfb0b412e, 0x9ad7618c, 0x94de6c87, + 0x86c57b9a, 0x88cc7691, 0xa2f355a0, 0xacfa58ab, 0xbee14fb6, 0xb0e842bd, + 0xea9f09d4, 0xe49604df, 0xf68d13c2, 0xf8841ec9, 0xd2bb3df8, 0xdcb230f3, + 0xcea927ee, 0xc0a02ae5, 0x7a47b13c, 0x744ebc37, 0x6655ab2a, 0x685ca621, + 0x42638510, 0x4c6a881b, 0x5e719f06, 0x5078920d, 0x0a0fd964, 0x0406d46f, + 0x161dc372, 0x1814ce79, 0x322bed48, 0x3c22e043, 0x2e39f75e, 0x2030fa55, + 0xec9ab701, 0xe293ba0a, 0xf088ad17, 0xfe81a01c, 0xd4be832d, 0xdab78e26, + 0xc8ac993b, 0xc6a59430, 0x9cd2df59, 0x92dbd252, 0x80c0c54f, 0x8ec9c844, + 0xa4f6eb75, 0xaaffe67e, 0xb8e4f163, 0xb6edfc68, 0x0c0a67b1, 0x02036aba, + 0x10187da7, 0x1e1170ac, 0x342e539d, 0x3a275e96, 0x283c498b, 0x26354480, + 0x7c420fe9, 0x724b02e2, 0x605015ff, 0x6e5918f4, 0x44663bc5, 0x4a6f36ce, + 0x587421d3, 0x567d2cd8, 0x37a10c7a, 0x39a80171, 0x2bb3166c, 0x25ba1b67, + 0x0f853856, 0x018c355d, 0x13972240, 0x1d9e2f4b, 0x47e96422, 0x49e06929, + 0x5bfb7e34, 0x55f2733f, 0x7fcd500e, 0x71c45d05, 0x63df4a18, 0x6dd64713, + 0xd731dcca, 0xd938d1c1, 0xcb23c6dc, 0xc52acbd7, 0xef15e8e6, 0xe11ce5ed, + 0xf307f2f0, 0xfd0efffb, 0xa779b492, 0xa970b999, 0xbb6bae84, 0xb562a38f, + 0x9f5d80be, 0x91548db5, 0x834f9aa8, 0x8d4697a3]); + + function expandKey128(cipherKey) { + var b = 176, result = new Uint8Array(b); + result.set(cipherKey); + for (var j = 16, i = 1; j < b; ++i) { + // RotWord + var t1 = result[j - 3], t2 = result[j - 2], + t3 = result[j - 1], t4 = result[j - 4]; + // SubWord + t1 = s[t1]; + t2 = s[t2]; + t3 = s[t3]; + t4 = s[t4]; + // Rcon + t1 = t1 ^ rcon[i]; + for (var n = 0; n < 4; ++n) { + result[j] = (t1 ^= result[j - 16]); + j++; + result[j] = (t2 ^= result[j - 16]); + j++; + result[j] = (t3 ^= result[j - 16]); + j++; + result[j] = (t4 ^= result[j - 16]); + j++; + } + } + return result; + } + + function decrypt128(input, key) { + var state = new Uint8Array(16); + state.set(input); + var i, j, k; + var t, u, v; + // AddRoundKey + for (j = 0, k = 160; j < 16; ++j, ++k) { + state[j] ^= key[k]; + } + for (i = 9; i >= 1; --i) { + // InvShiftRows + t = state[13]; + state[13] = state[9]; + state[9] = state[5]; + state[5] = state[1]; + state[1] = t; + t = state[14]; + u = state[10]; + state[14] = state[6]; + state[10] = state[2]; + state[6] = t; + state[2] = u; + t = state[15]; + u = state[11]; + v = state[7]; + state[15] = state[3]; + state[11] = t; + state[7] = u; + state[3] = v; + // InvSubBytes + for (j = 0; j < 16; ++j) { + state[j] = inv_s[state[j]]; + } + // AddRoundKey + for (j = 0, k = i * 16; j < 16; ++j, ++k) { + state[j] ^= key[k]; + } + // InvMixColumns + for (j = 0; j < 16; j += 4) { + var s0 = mix[state[j]], s1 = mix[state[j + 1]], + s2 = mix[state[j + 2]], s3 = mix[state[j + 3]]; + t = (s0 ^ (s1 >>> 8) ^ (s1 << 24) ^ (s2 >>> 16) ^ (s2 << 16) ^ + (s3 >>> 24) ^ (s3 << 8)); + state[j] = (t >>> 24) & 0xFF; + state[j + 1] = (t >> 16) & 0xFF; + state[j + 2] = (t >> 8) & 0xFF; + state[j + 3] = t & 0xFF; + } + } + // InvShiftRows + t = state[13]; + state[13] = state[9]; + state[9] = state[5]; + state[5] = state[1]; + state[1] = t; + t = state[14]; + u = state[10]; + state[14] = state[6]; + state[10] = state[2]; + state[6] = t; + state[2] = u; + t = state[15]; + u = state[11]; + v = state[7]; + state[15] = state[3]; + state[11] = t; + state[7] = u; + state[3] = v; + for (j = 0; j < 16; ++j) { + // InvSubBytes + state[j] = inv_s[state[j]]; + // AddRoundKey + state[j] ^= key[j]; + } + return state; + } + + function encrypt128(input, key) { + var t, u, v, k; + var state = new Uint8Array(16); + state.set(input); + for (j = 0; j < 16; ++j) { + // AddRoundKey + state[j] ^= key[j]; + } + + for (i = 1; i < 10; i++) { + //SubBytes + for (j = 0; j < 16; ++j) { + state[j] = s[state[j]]; + } + //ShiftRows + v = state[1]; + state[1] = state[5]; + state[5] = state[9]; + state[9] = state[13]; + state[13] = v; + v = state[2]; + u = state[6]; + state[2] = state[10]; + state[6] = state[14]; + state[10] = v; + state[14] = u; + v = state[3]; + u = state[7]; + t = state[11]; + state[3] = state[15]; + state[7] = v; + state[11] = u; + state[15] = t; + //MixColumns + for (var j = 0; j < 16; j += 4) { + var s0 = state[j + 0], s1 = state[j + 1]; + var s2 = state[j + 2], s3 = state[j + 3]; + t = s0 ^ s1 ^ s2 ^ s3; + state[j + 0] ^= t ^ mixCol[s0 ^ s1]; + state[j + 1] ^= t ^ mixCol[s1 ^ s2]; + state[j + 2] ^= t ^ mixCol[s2 ^ s3]; + state[j + 3] ^= t ^ mixCol[s3 ^ s0]; + } + //AddRoundKey + for (j = 0, k = i * 16; j < 16; ++j, ++k) { + state[j] ^= key[k]; + } + } + + //SubBytes + for (j = 0; j < 16; ++j) { + state[j] = s[state[j]]; + } + //ShiftRows + v = state[1]; + state[1] = state[5]; + state[5] = state[9]; + state[9] = state[13]; + state[13] = v; + v = state[2]; + u = state[6]; + state[2] = state[10]; + state[6] = state[14]; + state[10] = v; + state[14] = u; + v = state[3]; + u = state[7]; + t = state[11]; + state[3] = state[15]; + state[7] = v; + state[11] = u; + state[15] = t; + //AddRoundKey + for (j = 0, k = 160; j < 16; ++j, ++k) { + state[j] ^= key[k]; + } + return state; + } + + function AES128Cipher(key) { + this.key = expandKey128(key); + this.buffer = new Uint8Array(16); + this.bufferPosition = 0; + } + + function decryptBlock2(data, finalize) { + var i, j, ii, sourceLength = data.length, + buffer = this.buffer, bufferLength = this.bufferPosition, + result = [], iv = this.iv; + for (i = 0; i < sourceLength; ++i) { + buffer[bufferLength] = data[i]; + ++bufferLength; + if (bufferLength < 16) { + continue; + } + // buffer is full, decrypting + var plain = decrypt128(buffer, this.key); + // xor-ing the IV vector to get plain text + for (j = 0; j < 16; ++j) { + plain[j] ^= iv[j]; + } + iv = buffer; + result.push(plain); + buffer = new Uint8Array(16); + bufferLength = 0; + } + // saving incomplete buffer + this.buffer = buffer; + this.bufferLength = bufferLength; + this.iv = iv; + if (result.length === 0) { + return new Uint8Array([]); + } + // combining plain text blocks into one + var outputLength = 16 * result.length; + if (finalize) { + // undo a padding that is described in RFC 2898 + var lastBlock = result[result.length - 1]; + var psLen = lastBlock[15]; + if (psLen <= 16) { + for (i = 15, ii = 16 - psLen; i >= ii; --i) { + if (lastBlock[i] !== psLen) { + // Invalid padding, assume that the block has no padding. + psLen = 0; + break; + } + } + outputLength -= psLen; + result[result.length - 1] = lastBlock.subarray(0, 16 - psLen); + } + } + var output = new Uint8Array(outputLength); + for (i = 0, j = 0, ii = result.length; i < ii; ++i, j += 16) { + output.set(result[i], j); + } + return output; + } + + AES128Cipher.prototype = { + decryptBlock: function AES128Cipher_decryptBlock(data, finalize) { + var i, sourceLength = data.length; + var buffer = this.buffer, bufferLength = this.bufferPosition; + // waiting for IV values -- they are at the start of the stream + for (i = 0; bufferLength < 16 && i < sourceLength; ++i, ++bufferLength) { + buffer[bufferLength] = data[i]; + } + if (bufferLength < 16) { + // need more data + this.bufferLength = bufferLength; + return new Uint8Array([]); + } + this.iv = buffer; + this.buffer = new Uint8Array(16); + this.bufferLength = 0; + // starting decryption + this.decryptBlock = decryptBlock2; + return this.decryptBlock(data.subarray(16), finalize); + }, + encrypt: function AES128Cipher_encrypt(data, iv) { + var i, j, ii, sourceLength = data.length, + buffer = this.buffer, bufferLength = this.bufferPosition, + result = []; + if (!iv) { + iv = new Uint8Array(16); + } + for (i = 0; i < sourceLength; ++i) { + buffer[bufferLength] = data[i]; + ++bufferLength; + if (bufferLength < 16) { + continue; + } + for (j = 0; j < 16; ++j) { + buffer[j] ^= iv[j]; + } + + // buffer is full, encrypting + var cipher = encrypt128(buffer, this.key); + iv = cipher; + result.push(cipher); + buffer = new Uint8Array(16); + bufferLength = 0; + } + // saving incomplete buffer + this.buffer = buffer; + this.bufferLength = bufferLength; + this.iv = iv; + if (result.length === 0) { + return new Uint8Array([]); + } + // combining plain text blocks into one + var outputLength = 16 * result.length; + var output = new Uint8Array(outputLength); + for (i = 0, j = 0, ii = result.length; i < ii; ++i, j += 16) { + output.set(result[i], j); + } + return output; + } + }; + + return AES128Cipher; +})(); + +var AES256Cipher = (function AES256CipherClosure() { + var rcon = new Uint8Array([ + 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, + 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, + 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, + 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, + 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, + 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, + 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, + 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, + 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, + 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, + 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, + 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, + 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, + 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, + 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, + 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, + 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, + 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, + 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, + 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, + 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, + 0x74, 0xe8, 0xcb, 0x8d]); + + var s = new Uint8Array([ + 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, + 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, + 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, + 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, + 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, + 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, + 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, + 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, + 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, + 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, + 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec, + 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, + 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, + 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, + 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, + 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, + 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, + 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, + 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, + 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, + 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, + 0xb0, 0x54, 0xbb, 0x16]); + + var inv_s = new Uint8Array([ + 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, + 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, + 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, + 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, + 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, + 0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, + 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, + 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, + 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, + 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, + 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41, + 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, + 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, + 0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, + 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, + 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, + 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, + 0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, + 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d, + 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, + 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, + 0x55, 0x21, 0x0c, 0x7d]); + + var mixCol = new Uint8Array(256); + for (var i = 0; i < 256; i++) { + if (i < 128) { + mixCol[i] = i << 1; + } else { + mixCol[i] = (i << 1) ^ 0x1b; + } + } + var mix = new Uint32Array([ + 0x00000000, 0x0e090d0b, 0x1c121a16, 0x121b171d, 0x3824342c, 0x362d3927, + 0x24362e3a, 0x2a3f2331, 0x70486858, 0x7e416553, 0x6c5a724e, 0x62537f45, + 0x486c5c74, 0x4665517f, 0x547e4662, 0x5a774b69, 0xe090d0b0, 0xee99ddbb, + 0xfc82caa6, 0xf28bc7ad, 0xd8b4e49c, 0xd6bde997, 0xc4a6fe8a, 0xcaaff381, + 0x90d8b8e8, 0x9ed1b5e3, 0x8ccaa2fe, 0x82c3aff5, 0xa8fc8cc4, 0xa6f581cf, + 0xb4ee96d2, 0xbae79bd9, 0xdb3bbb7b, 0xd532b670, 0xc729a16d, 0xc920ac66, + 0xe31f8f57, 0xed16825c, 0xff0d9541, 0xf104984a, 0xab73d323, 0xa57ade28, + 0xb761c935, 0xb968c43e, 0x9357e70f, 0x9d5eea04, 0x8f45fd19, 0x814cf012, + 0x3bab6bcb, 0x35a266c0, 0x27b971dd, 0x29b07cd6, 0x038f5fe7, 0x0d8652ec, + 0x1f9d45f1, 0x119448fa, 0x4be30393, 0x45ea0e98, 0x57f11985, 0x59f8148e, + 0x73c737bf, 0x7dce3ab4, 0x6fd52da9, 0x61dc20a2, 0xad766df6, 0xa37f60fd, + 0xb16477e0, 0xbf6d7aeb, 0x955259da, 0x9b5b54d1, 0x894043cc, 0x87494ec7, + 0xdd3e05ae, 0xd33708a5, 0xc12c1fb8, 0xcf2512b3, 0xe51a3182, 0xeb133c89, + 0xf9082b94, 0xf701269f, 0x4de6bd46, 0x43efb04d, 0x51f4a750, 0x5ffdaa5b, + 0x75c2896a, 0x7bcb8461, 0x69d0937c, 0x67d99e77, 0x3daed51e, 0x33a7d815, + 0x21bccf08, 0x2fb5c203, 0x058ae132, 0x0b83ec39, 0x1998fb24, 0x1791f62f, + 0x764dd68d, 0x7844db86, 0x6a5fcc9b, 0x6456c190, 0x4e69e2a1, 0x4060efaa, + 0x527bf8b7, 0x5c72f5bc, 0x0605bed5, 0x080cb3de, 0x1a17a4c3, 0x141ea9c8, + 0x3e218af9, 0x302887f2, 0x223390ef, 0x2c3a9de4, 0x96dd063d, 0x98d40b36, + 0x8acf1c2b, 0x84c61120, 0xaef93211, 0xa0f03f1a, 0xb2eb2807, 0xbce2250c, + 0xe6956e65, 0xe89c636e, 0xfa877473, 0xf48e7978, 0xdeb15a49, 0xd0b85742, + 0xc2a3405f, 0xccaa4d54, 0x41ecdaf7, 0x4fe5d7fc, 0x5dfec0e1, 0x53f7cdea, + 0x79c8eedb, 0x77c1e3d0, 0x65daf4cd, 0x6bd3f9c6, 0x31a4b2af, 0x3fadbfa4, + 0x2db6a8b9, 0x23bfa5b2, 0x09808683, 0x07898b88, 0x15929c95, 0x1b9b919e, + 0xa17c0a47, 0xaf75074c, 0xbd6e1051, 0xb3671d5a, 0x99583e6b, 0x97513360, + 0x854a247d, 0x8b432976, 0xd134621f, 0xdf3d6f14, 0xcd267809, 0xc32f7502, + 0xe9105633, 0xe7195b38, 0xf5024c25, 0xfb0b412e, 0x9ad7618c, 0x94de6c87, + 0x86c57b9a, 0x88cc7691, 0xa2f355a0, 0xacfa58ab, 0xbee14fb6, 0xb0e842bd, + 0xea9f09d4, 0xe49604df, 0xf68d13c2, 0xf8841ec9, 0xd2bb3df8, 0xdcb230f3, + 0xcea927ee, 0xc0a02ae5, 0x7a47b13c, 0x744ebc37, 0x6655ab2a, 0x685ca621, + 0x42638510, 0x4c6a881b, 0x5e719f06, 0x5078920d, 0x0a0fd964, 0x0406d46f, + 0x161dc372, 0x1814ce79, 0x322bed48, 0x3c22e043, 0x2e39f75e, 0x2030fa55, + 0xec9ab701, 0xe293ba0a, 0xf088ad17, 0xfe81a01c, 0xd4be832d, 0xdab78e26, + 0xc8ac993b, 0xc6a59430, 0x9cd2df59, 0x92dbd252, 0x80c0c54f, 0x8ec9c844, + 0xa4f6eb75, 0xaaffe67e, 0xb8e4f163, 0xb6edfc68, 0x0c0a67b1, 0x02036aba, + 0x10187da7, 0x1e1170ac, 0x342e539d, 0x3a275e96, 0x283c498b, 0x26354480, + 0x7c420fe9, 0x724b02e2, 0x605015ff, 0x6e5918f4, 0x44663bc5, 0x4a6f36ce, + 0x587421d3, 0x567d2cd8, 0x37a10c7a, 0x39a80171, 0x2bb3166c, 0x25ba1b67, + 0x0f853856, 0x018c355d, 0x13972240, 0x1d9e2f4b, 0x47e96422, 0x49e06929, + 0x5bfb7e34, 0x55f2733f, 0x7fcd500e, 0x71c45d05, 0x63df4a18, 0x6dd64713, + 0xd731dcca, 0xd938d1c1, 0xcb23c6dc, 0xc52acbd7, 0xef15e8e6, 0xe11ce5ed, + 0xf307f2f0, 0xfd0efffb, 0xa779b492, 0xa970b999, 0xbb6bae84, 0xb562a38f, + 0x9f5d80be, 0x91548db5, 0x834f9aa8, 0x8d4697a3]); + + function expandKey256(cipherKey) { + var b = 240, result = new Uint8Array(b); + var r = 1; + + result.set(cipherKey); + for (var j = 32, i = 1; j < b; ++i) { + if (j % 32 === 16) { + t1 = s[t1]; + t2 = s[t2]; + t3 = s[t3]; + t4 = s[t4]; + } else if (j % 32 === 0) { + // RotWord + var t1 = result[j - 3], t2 = result[j - 2], + t3 = result[j - 1], t4 = result[j - 4]; + // SubWord + t1 = s[t1]; + t2 = s[t2]; + t3 = s[t3]; + t4 = s[t4]; + // Rcon + t1 = t1 ^ r; + if ((r <<= 1) >= 256) { + r = (r ^ 0x1b) & 0xFF; + } + } + + for (var n = 0; n < 4; ++n) { + result[j] = (t1 ^= result[j - 32]); + j++; + result[j] = (t2 ^= result[j - 32]); + j++; + result[j] = (t3 ^= result[j - 32]); + j++; + result[j] = (t4 ^= result[j - 32]); + j++; + } + } + return result; + } + + function decrypt256(input, key) { + var state = new Uint8Array(16); + state.set(input); + var i, j, k; + var t, u, v; + // AddRoundKey + for (j = 0, k = 224; j < 16; ++j, ++k) { + state[j] ^= key[k]; + } + for (i = 13; i >= 1; --i) { + // InvShiftRows + t = state[13]; + state[13] = state[9]; + state[9] = state[5]; + state[5] = state[1]; + state[1] = t; + t = state[14]; + u = state[10]; + state[14] = state[6]; + state[10] = state[2]; + state[6] = t; + state[2] = u; + t = state[15]; + u = state[11]; + v = state[7]; + state[15] = state[3]; + state[11] = t; + state[7] = u; + state[3] = v; + // InvSubBytes + for (j = 0; j < 16; ++j) { + state[j] = inv_s[state[j]]; + } + // AddRoundKey + for (j = 0, k = i * 16; j < 16; ++j, ++k) { + state[j] ^= key[k]; + } + // InvMixColumns + for (j = 0; j < 16; j += 4) { + var s0 = mix[state[j]], s1 = mix[state[j + 1]], + s2 = mix[state[j + 2]], s3 = mix[state[j + 3]]; + t = (s0 ^ (s1 >>> 8) ^ (s1 << 24) ^ (s2 >>> 16) ^ (s2 << 16) ^ + (s3 >>> 24) ^ (s3 << 8)); + state[j] = (t >>> 24) & 0xFF; + state[j + 1] = (t >> 16) & 0xFF; + state[j + 2] = (t >> 8) & 0xFF; + state[j + 3] = t & 0xFF; + } + } + // InvShiftRows + t = state[13]; + state[13] = state[9]; + state[9] = state[5]; + state[5] = state[1]; + state[1] = t; + t = state[14]; + u = state[10]; + state[14] = state[6]; + state[10] = state[2]; + state[6] = t; + state[2] = u; + t = state[15]; + u = state[11]; + v = state[7]; + state[15] = state[3]; + state[11] = t; + state[7] = u; + state[3] = v; + for (j = 0; j < 16; ++j) { + // InvSubBytes + state[j] = inv_s[state[j]]; + // AddRoundKey + state[j] ^= key[j]; + } + return state; + } + + function encrypt256(input, key) { + var t, u, v, k; + var state = new Uint8Array(16); + state.set(input); + for (j = 0; j < 16; ++j) { + // AddRoundKey + state[j] ^= key[j]; + } + + for (i = 1; i < 14; i++) { + //SubBytes + for (j = 0; j < 16; ++j) { + state[j] = s[state[j]]; + } + //ShiftRows + v = state[1]; + state[1] = state[5]; + state[5] = state[9]; + state[9] = state[13]; + state[13] = v; + v = state[2]; + u = state[6]; + state[2] = state[10]; + state[6] = state[14]; + state[10] = v; + state[14] = u; + v = state[3]; + u = state[7]; + t = state[11]; + state[3] = state[15]; + state[7] = v; + state[11] = u; + state[15] = t; + //MixColumns + for (var j = 0; j < 16; j += 4) { + var s0 = state[j + 0], s1 = state[j + 1]; + var s2 = state[j + 2], s3 = state[j + 3]; + t = s0 ^ s1 ^ s2 ^ s3; + state[j + 0] ^= t ^ mixCol[s0 ^ s1]; + state[j + 1] ^= t ^ mixCol[s1 ^ s2]; + state[j + 2] ^= t ^ mixCol[s2 ^ s3]; + state[j + 3] ^= t ^ mixCol[s3 ^ s0]; + } + //AddRoundKey + for (j = 0, k = i * 16; j < 16; ++j, ++k) { + state[j] ^= key[k]; + } + } + + //SubBytes + for (j = 0; j < 16; ++j) { + state[j] = s[state[j]]; + } + //ShiftRows + v = state[1]; + state[1] = state[5]; + state[5] = state[9]; + state[9] = state[13]; + state[13] = v; + v = state[2]; + u = state[6]; + state[2] = state[10]; + state[6] = state[14]; + state[10] = v; + state[14] = u; + v = state[3]; + u = state[7]; + t = state[11]; + state[3] = state[15]; + state[7] = v; + state[11] = u; + state[15] = t; + //AddRoundKey + for (j = 0, k = 224; j < 16; ++j, ++k) { + state[j] ^= key[k]; + } + + return state; + + } + + function AES256Cipher(key) { + this.key = expandKey256(key); + this.buffer = new Uint8Array(16); + this.bufferPosition = 0; + } + + function decryptBlock2(data, finalize) { + var i, j, ii, sourceLength = data.length, + buffer = this.buffer, bufferLength = this.bufferPosition, + result = [], iv = this.iv; + + for (i = 0; i < sourceLength; ++i) { + buffer[bufferLength] = data[i]; + ++bufferLength; + if (bufferLength < 16) { + continue; + } + // buffer is full, decrypting + var plain = decrypt256(buffer, this.key); + // xor-ing the IV vector to get plain text + for (j = 0; j < 16; ++j) { + plain[j] ^= iv[j]; + } + iv = buffer; + result.push(plain); + buffer = new Uint8Array(16); + bufferLength = 0; + } + // saving incomplete buffer + this.buffer = buffer; + this.bufferLength = bufferLength; + this.iv = iv; + if (result.length === 0) { + return new Uint8Array([]); + } + // combining plain text blocks into one + var outputLength = 16 * result.length; + if (finalize) { + // undo a padding that is described in RFC 2898 + var lastBlock = result[result.length - 1]; + var psLen = lastBlock[15]; + if (psLen <= 16) { + for (i = 15, ii = 16 - psLen; i >= ii; --i) { + if (lastBlock[i] !== psLen) { + // Invalid padding, assume that the block has no padding. + psLen = 0; + break; + } + } + outputLength -= psLen; + result[result.length - 1] = lastBlock.subarray(0, 16 - psLen); + } + } + var output = new Uint8Array(outputLength); + for (i = 0, j = 0, ii = result.length; i < ii; ++i, j += 16) { + output.set(result[i], j); + } + return output; + + } + + AES256Cipher.prototype = { + decryptBlock: function AES256Cipher_decryptBlock(data, finalize, iv) { + var i, sourceLength = data.length; + var buffer = this.buffer, bufferLength = this.bufferPosition; + // if not supplied an IV wait for IV values + // they are at the start of the stream + if (iv) { + this.iv = iv; + } else { + for (i = 0; bufferLength < 16 && + i < sourceLength; ++i, ++bufferLength) { + buffer[bufferLength] = data[i]; + } + if (bufferLength < 16) { + //need more data + this.bufferLength = bufferLength; + return new Uint8Array([]); + } + this.iv = buffer; + data = data.subarray(16); + } + this.buffer = new Uint8Array(16); + this.bufferLength = 0; + // starting decryption + this.decryptBlock = decryptBlock2; + return this.decryptBlock(data, finalize); + }, + encrypt: function AES256Cipher_encrypt(data, iv) { + var i, j, ii, sourceLength = data.length, + buffer = this.buffer, bufferLength = this.bufferPosition, + result = []; + if (!iv) { + iv = new Uint8Array(16); + } + for (i = 0; i < sourceLength; ++i) { + buffer[bufferLength] = data[i]; + ++bufferLength; + if (bufferLength < 16) { + continue; + } + for (j = 0; j < 16; ++j) { + buffer[j] ^= iv[j]; + } + + // buffer is full, encrypting + var cipher = encrypt256(buffer, this.key); + this.iv = cipher; + result.push(cipher); + buffer = new Uint8Array(16); + bufferLength = 0; + } + // saving incomplete buffer + this.buffer = buffer; + this.bufferLength = bufferLength; + this.iv = iv; + if (result.length === 0) { + return new Uint8Array([]); + } + // combining plain text blocks into one + var outputLength = 16 * result.length; + var output = new Uint8Array(outputLength); + for (i = 0, j = 0, ii = result.length; i < ii; ++i, j += 16) { + output.set(result[i], j); + } + return output; + } + }; + + return AES256Cipher; +})(); + +var PDF17 = (function PDF17Closure() { + + function compareByteArrays(array1, array2) { + if (array1.length !== array2.length) { + return false; + } + for (var i = 0; i < array1.length; i++) { + if (array1[i] !== array2[i]) { + return false; + } + } + return true; + } + + function PDF17() { + } + + PDF17.prototype = { + checkOwnerPassword: function PDF17_checkOwnerPassword(password, + ownerValidationSalt, + userBytes, + ownerPassword) { + var hashData = new Uint8Array(password.length + 56); + hashData.set(password, 0); + hashData.set(ownerValidationSalt, password.length); + hashData.set(userBytes, password.length + ownerValidationSalt.length); + var result = calculateSHA256(hashData, 0, hashData.length); + return compareByteArrays(result, ownerPassword); + }, + checkUserPassword: function PDF17_checkUserPassword(password, + userValidationSalt, + userPassword) { + var hashData = new Uint8Array(password.length + 8); + hashData.set(password, 0); + hashData.set(userValidationSalt, password.length); + var result = calculateSHA256(hashData, 0, hashData.length); + return compareByteArrays(result, userPassword); + }, + getOwnerKey: function PDF17_getOwnerKey(password, ownerKeySalt, userBytes, + ownerEncryption) { + var hashData = new Uint8Array(password.length + 56); + hashData.set(password, 0); + hashData.set(ownerKeySalt, password.length); + hashData.set(userBytes, password.length + ownerKeySalt.length); + var key = calculateSHA256(hashData, 0, hashData.length); + var cipher = new AES256Cipher(key); + return cipher.decryptBlock(ownerEncryption, + false, + new Uint8Array(16)); + + }, + getUserKey: function PDF17_getUserKey(password, userKeySalt, + userEncryption) { + var hashData = new Uint8Array(password.length + 8); + hashData.set(password, 0); + hashData.set(userKeySalt, password.length); + //key is the decryption key for the UE string + var key = calculateSHA256(hashData, 0, hashData.length); + var cipher = new AES256Cipher(key); + return cipher.decryptBlock(userEncryption, + false, + new Uint8Array(16)); + } + }; + return PDF17; +})(); + +var PDF20 = (function PDF20Closure() { + + function concatArrays(array1, array2) { + var t = new Uint8Array(array1.length + array2.length); + t.set(array1, 0); + t.set(array2, array1.length); + return t; + } + + function calculatePDF20Hash(password, input, userBytes) { + //This refers to Algorithm 2.B as defined in ISO 32000-2 + var k = calculateSHA256(input, 0, input.length).subarray(0, 32); + var e = [0]; + var i = 0; + while (i < 64 || e[e.length - 1] > i - 32) { + var arrayLength = password.length + k.length + userBytes.length; + + var k1 = new Uint8Array(arrayLength * 64); + var array = concatArrays(password, k); + array = concatArrays(array, userBytes); + for (var j = 0, pos = 0; j < 64; j++, pos += arrayLength) { + k1.set(array, pos); + } + //AES128 CBC NO PADDING with + //first 16 bytes of k as the key and the second 16 as the iv. + var cipher = new AES128Cipher(k.subarray(0, 16)); + e = cipher.encrypt(k1, k.subarray(16, 32)); + //Now we have to take the first 16 bytes of an unsigned + //big endian integer... and compute the remainder + //modulo 3.... That is a fairly large number and + //JavaScript isn't going to handle that well... + //So we're using a trick that allows us to perform + //modulo math byte by byte + var remainder = 0; + for (var z = 0; z < 16; z++) { + remainder *= (256 % 3); + remainder %= 3; + remainder += ((e[z] >>> 0) % 3); + remainder %= 3; + } + if (remainder === 0) { + k = calculateSHA256(e, 0, e.length); + } + else if (remainder === 1) { + k = calculateSHA384(e, 0, e.length); + } + else if (remainder === 2) { + k = calculateSHA512(e, 0, e.length); + } + i++; + } + return k.subarray(0, 32); + } + + function PDF20() { + } + + function compareByteArrays(array1, array2) { + if (array1.length !== array2.length) { + return false; + } + for (var i = 0; i < array1.length; i++) { + if (array1[i] !== array2[i]) { + return false; + } + } + return true; + } + + PDF20.prototype = { + hash: function PDF20_hash(password, concatBytes, userBytes) { + return calculatePDF20Hash(password, concatBytes, userBytes); + }, + checkOwnerPassword: function PDF20_checkOwnerPassword(password, + ownerValidationSalt, + userBytes, + ownerPassword) { + var hashData = new Uint8Array(password.length + 56); + hashData.set(password, 0); + hashData.set(ownerValidationSalt, password.length); + hashData.set(userBytes, password.length + ownerValidationSalt.length); + var result = calculatePDF20Hash(password, hashData, userBytes); + return compareByteArrays(result, ownerPassword); + }, + checkUserPassword: function PDF20_checkUserPassword(password, + userValidationSalt, + userPassword) { + var hashData = new Uint8Array(password.length + 8); + hashData.set(password, 0); + hashData.set(userValidationSalt, password.length); + var result = calculatePDF20Hash(password, hashData, []); + return compareByteArrays(result, userPassword); + }, + getOwnerKey: function PDF20_getOwnerKey(password, ownerKeySalt, userBytes, + ownerEncryption) { + var hashData = new Uint8Array(password.length + 56); + hashData.set(password, 0); + hashData.set(ownerKeySalt, password.length); + hashData.set(userBytes, password.length + ownerKeySalt.length); + var key = calculatePDF20Hash(password, hashData, userBytes); + var cipher = new AES256Cipher(key); + return cipher.decryptBlock(ownerEncryption, + false, + new Uint8Array(16)); + + }, + getUserKey: function PDF20_getUserKey(password, userKeySalt, + userEncryption) { + var hashData = new Uint8Array(password.length + 8); + hashData.set(password, 0); + hashData.set(userKeySalt, password.length); + //key is the decryption key for the UE string + var key = calculatePDF20Hash(password, hashData, []); + var cipher = new AES256Cipher(key); + return cipher.decryptBlock(userEncryption, + false, + new Uint8Array(16)); + } + }; + return PDF20; +})(); + +var CipherTransform = (function CipherTransformClosure() { + function CipherTransform(stringCipherConstructor, streamCipherConstructor) { + this.stringCipherConstructor = stringCipherConstructor; + this.streamCipherConstructor = streamCipherConstructor; + } + + CipherTransform.prototype = { + createStream: function CipherTransform_createStream(stream, length) { + var cipher = new this.streamCipherConstructor(); + return new DecryptStream(stream, length, + function cipherTransformDecryptStream(data, finalize) { + return cipher.decryptBlock(data, finalize); + } + ); + }, + decryptString: function CipherTransform_decryptString(s) { + var cipher = new this.stringCipherConstructor(); + var data = stringToBytes(s); + data = cipher.decryptBlock(data, true); + return bytesToString(data); + } + }; + return CipherTransform; +})(); + +var CipherTransformFactory = (function CipherTransformFactoryClosure() { + var defaultPasswordBytes = new Uint8Array([ + 0x28, 0xBF, 0x4E, 0x5E, 0x4E, 0x75, 0x8A, 0x41, + 0x64, 0x00, 0x4E, 0x56, 0xFF, 0xFA, 0x01, 0x08, + 0x2E, 0x2E, 0x00, 0xB6, 0xD0, 0x68, 0x3E, 0x80, + 0x2F, 0x0C, 0xA9, 0xFE, 0x64, 0x53, 0x69, 0x7A]); + + function createEncryptionKey20(revision, password, ownerPassword, + ownerValidationSalt, ownerKeySalt, uBytes, + userPassword, userValidationSalt, userKeySalt, + ownerEncryption, userEncryption, perms) { + if (password) { + var passwordLength = Math.min(127, password.length); + password = password.subarray(0, passwordLength); + } else { + password = []; + } + var pdfAlgorithm; + if (revision === 6) { + pdfAlgorithm = new PDF20(); + } else { + pdfAlgorithm = new PDF17(); + } + + if (pdfAlgorithm) { + if (pdfAlgorithm.checkUserPassword(password, userValidationSalt, + userPassword)) { + return pdfAlgorithm.getUserKey(password, userKeySalt, userEncryption); + } else if (pdfAlgorithm.checkOwnerPassword(password, ownerValidationSalt, + uBytes, + ownerPassword)) { + return pdfAlgorithm.getOwnerKey(password, ownerKeySalt, uBytes, + ownerEncryption); + } + } + + return null; + } + + function prepareKeyData(fileId, password, ownerPassword, userPassword, + flags, revision, keyLength, encryptMetadata) { + var hashDataSize = 40 + ownerPassword.length + fileId.length; + var hashData = new Uint8Array(hashDataSize), i = 0, j, n; + if (password) { + n = Math.min(32, password.length); + for (; i < n; ++i) { + hashData[i] = password[i]; + } + } + j = 0; + while (i < 32) { + hashData[i++] = defaultPasswordBytes[j++]; + } + // as now the padded password in the hashData[0..i] + for (j = 0, n = ownerPassword.length; j < n; ++j) { + hashData[i++] = ownerPassword[j]; + } + hashData[i++] = flags & 0xFF; + hashData[i++] = (flags >> 8) & 0xFF; + hashData[i++] = (flags >> 16) & 0xFF; + hashData[i++] = (flags >>> 24) & 0xFF; + for (j = 0, n = fileId.length; j < n; ++j) { + hashData[i++] = fileId[j]; + } + if (revision >= 4 && !encryptMetadata) { + hashData[i++] = 0xFF; + hashData[i++] = 0xFF; + hashData[i++] = 0xFF; + hashData[i++] = 0xFF; + } + var hash = calculateMD5(hashData, 0, i); + var keyLengthInBytes = keyLength >> 3; + if (revision >= 3) { + for (j = 0; j < 50; ++j) { + hash = calculateMD5(hash, 0, keyLengthInBytes); + } + } + var encryptionKey = hash.subarray(0, keyLengthInBytes); + var cipher, checkData; + + if (revision >= 3) { + for (i = 0; i < 32; ++i) { + hashData[i] = defaultPasswordBytes[i]; + } + for (j = 0, n = fileId.length; j < n; ++j) { + hashData[i++] = fileId[j]; + } + cipher = new ARCFourCipher(encryptionKey); + checkData = cipher.encryptBlock(calculateMD5(hashData, 0, i)); + n = encryptionKey.length; + var derivedKey = new Uint8Array(n), k; + for (j = 1; j <= 19; ++j) { + for (k = 0; k < n; ++k) { + derivedKey[k] = encryptionKey[k] ^ j; + } + cipher = new ARCFourCipher(derivedKey); + checkData = cipher.encryptBlock(checkData); + } + for (j = 0, n = checkData.length; j < n; ++j) { + if (userPassword[j] !== checkData[j]) { + return null; + } + } + } else { + cipher = new ARCFourCipher(encryptionKey); + checkData = cipher.encryptBlock(defaultPasswordBytes); + for (j = 0, n = checkData.length; j < n; ++j) { + if (userPassword[j] !== checkData[j]) { + return null; + } + } + } + return encryptionKey; + } + + function decodeUserPassword(password, ownerPassword, revision, keyLength) { + var hashData = new Uint8Array(32), i = 0, j, n; + n = Math.min(32, password.length); + for (; i < n; ++i) { + hashData[i] = password[i]; + } + j = 0; + while (i < 32) { + hashData[i++] = defaultPasswordBytes[j++]; + } + var hash = calculateMD5(hashData, 0, i); + var keyLengthInBytes = keyLength >> 3; + if (revision >= 3) { + for (j = 0; j < 50; ++j) { + hash = calculateMD5(hash, 0, hash.length); + } + } + + var cipher, userPassword; + if (revision >= 3) { + userPassword = ownerPassword; + var derivedKey = new Uint8Array(keyLengthInBytes), k; + for (j = 19; j >= 0; j--) { + for (k = 0; k < keyLengthInBytes; ++k) { + derivedKey[k] = hash[k] ^ j; + } + cipher = new ARCFourCipher(derivedKey); + userPassword = cipher.encryptBlock(userPassword); + } + } else { + cipher = new ARCFourCipher(hash.subarray(0, keyLengthInBytes)); + userPassword = cipher.encryptBlock(ownerPassword); + } + return userPassword; + } + + var identityName = Name.get('Identity'); + + function CipherTransformFactory(dict, fileId, password) { + var filter = dict.get('Filter'); + if (!isName(filter) || filter.name !== 'Standard') { + error('unknown encryption method'); + } + this.dict = dict; + var algorithm = dict.get('V'); + if (!isInt(algorithm) || + (algorithm !== 1 && algorithm !== 2 && algorithm !== 4 && + algorithm !== 5)) { + error('unsupported encryption algorithm'); + } + this.algorithm = algorithm; + var keyLength = dict.get('Length') || 40; + if (!isInt(keyLength) || + keyLength < 40 || (keyLength % 8) !== 0) { + error('invalid key length'); + } + + // prepare keys + var ownerPassword = stringToBytes(dict.get('O')).subarray(0, 32); + var userPassword = stringToBytes(dict.get('U')).subarray(0, 32); + var flags = dict.get('P'); + var revision = dict.get('R'); + // meaningful when V is 4 or 5 + var encryptMetadata = ((algorithm === 4 || algorithm === 5) && + dict.get('EncryptMetadata') !== false); + this.encryptMetadata = encryptMetadata; + + var fileIdBytes = stringToBytes(fileId); + var passwordBytes; + if (password) { + passwordBytes = stringToBytes(password); + } + + var encryptionKey; + if (algorithm !== 5) { + encryptionKey = prepareKeyData(fileIdBytes, passwordBytes, + ownerPassword, userPassword, flags, + revision, keyLength, encryptMetadata); + } + else { + var ownerValidationSalt = stringToBytes(dict.get('O')).subarray(32, 40); + var ownerKeySalt = stringToBytes(dict.get('O')).subarray(40, 48); + var uBytes = stringToBytes(dict.get('U')).subarray(0, 48); + var userValidationSalt = stringToBytes(dict.get('U')).subarray(32, 40); + var userKeySalt = stringToBytes(dict.get('U')).subarray(40, 48); + var ownerEncryption = stringToBytes(dict.get('OE')); + var userEncryption = stringToBytes(dict.get('UE')); + var perms = stringToBytes(dict.get('Perms')); + encryptionKey = + createEncryptionKey20(revision, passwordBytes, + ownerPassword, ownerValidationSalt, + ownerKeySalt, uBytes, + userPassword, userValidationSalt, + userKeySalt, ownerEncryption, + userEncryption, perms); + } + if (!encryptionKey && !password) { + throw new PasswordException('No password given', + PasswordResponses.NEED_PASSWORD); + } else if (!encryptionKey && password) { + // Attempting use the password as an owner password + var decodedPassword = decodeUserPassword(passwordBytes, ownerPassword, + revision, keyLength); + encryptionKey = prepareKeyData(fileIdBytes, decodedPassword, + ownerPassword, userPassword, flags, + revision, keyLength, encryptMetadata); + } + + if (!encryptionKey) { + throw new PasswordException('Incorrect Password', + PasswordResponses.INCORRECT_PASSWORD); + } + + this.encryptionKey = encryptionKey; + + if (algorithm >= 4) { + this.cf = dict.get('CF'); + this.stmf = dict.get('StmF') || identityName; + this.strf = dict.get('StrF') || identityName; + this.eff = dict.get('EFF') || this.stmf; + } + } + + function buildObjectKey(num, gen, encryptionKey, isAes) { + var key = new Uint8Array(encryptionKey.length + 9), i, n; + for (i = 0, n = encryptionKey.length; i < n; ++i) { + key[i] = encryptionKey[i]; + } + key[i++] = num & 0xFF; + key[i++] = (num >> 8) & 0xFF; + key[i++] = (num >> 16) & 0xFF; + key[i++] = gen & 0xFF; + key[i++] = (gen >> 8) & 0xFF; + if (isAes) { + key[i++] = 0x73; + key[i++] = 0x41; + key[i++] = 0x6C; + key[i++] = 0x54; + } + var hash = calculateMD5(key, 0, i); + return hash.subarray(0, Math.min(encryptionKey.length + 5, 16)); + } + + function buildCipherConstructor(cf, name, num, gen, key) { + var cryptFilter = cf.get(name.name); + var cfm; + if (cryptFilter !== null && cryptFilter !== undefined) { + cfm = cryptFilter.get('CFM'); + } + if (!cfm || cfm.name === 'None') { + return function cipherTransformFactoryBuildCipherConstructorNone() { + return new NullCipher(); + }; + } + if ('V2' === cfm.name) { + return function cipherTransformFactoryBuildCipherConstructorV2() { + return new ARCFourCipher(buildObjectKey(num, gen, key, false)); + }; + } + if ('AESV2' === cfm.name) { + return function cipherTransformFactoryBuildCipherConstructorAESV2() { + return new AES128Cipher(buildObjectKey(num, gen, key, true)); + }; + } + if ('AESV3' === cfm.name) { + return function cipherTransformFactoryBuildCipherConstructorAESV3() { + return new AES256Cipher(key); + }; + } + error('Unknown crypto method'); + } + + CipherTransformFactory.prototype = { + createCipherTransform: + function CipherTransformFactory_createCipherTransform(num, gen) { + if (this.algorithm === 4 || this.algorithm === 5) { + return new CipherTransform( + buildCipherConstructor(this.cf, this.stmf, + num, gen, this.encryptionKey), + buildCipherConstructor(this.cf, this.strf, + num, gen, this.encryptionKey)); + } + // algorithms 1 and 2 + var key = buildObjectKey(num, gen, this.encryptionKey, false); + var cipherConstructor = function buildCipherCipherConstructor() { + return new ARCFourCipher(key); + }; + return new CipherTransform(cipherConstructor, cipherConstructor); + } + }; + + return CipherTransformFactory; +})(); + + +var PatternType = { + FUNCTION_BASED: 1, + AXIAL: 2, + RADIAL: 3, + FREE_FORM_MESH: 4, + LATTICE_FORM_MESH: 5, + COONS_PATCH_MESH: 6, + TENSOR_PATCH_MESH: 7 +}; + +var Pattern = (function PatternClosure() { + // Constructor should define this.getPattern + function Pattern() { + error('should not call Pattern constructor'); + } + + Pattern.prototype = { + // Input: current Canvas context + // Output: the appropriate fillStyle or strokeStyle + getPattern: function Pattern_getPattern(ctx) { + error('Should not call Pattern.getStyle: ' + ctx); + } + }; + + Pattern.parseShading = function Pattern_parseShading(shading, matrix, xref, + res) { + + var dict = isStream(shading) ? shading.dict : shading; + var type = dict.get('ShadingType'); + + try { + switch (type) { + case PatternType.AXIAL: + case PatternType.RADIAL: + // Both radial and axial shadings are handled by RadialAxial shading. + return new Shadings.RadialAxial(dict, matrix, xref, res); + case PatternType.FREE_FORM_MESH: + case PatternType.LATTICE_FORM_MESH: + case PatternType.COONS_PATCH_MESH: + case PatternType.TENSOR_PATCH_MESH: + return new Shadings.Mesh(shading, matrix, xref, res); + default: + throw new Error('Unknown PatternType: ' + type); + } + } catch (ex) { + if (ex instanceof MissingDataException) { + throw ex; + } + UnsupportedManager.notify(UNSUPPORTED_FEATURES.shadingPattern); + warn(ex); + return new Shadings.Dummy(); + } + }; + return Pattern; +})(); + +var Shadings = {}; + +// A small number to offset the first/last color stops so we can insert ones to +// support extend. Number.MIN_VALUE appears to be too small and breaks the +// extend. 1e-7 works in FF but chrome seems to use an even smaller sized number +// internally so we have to go bigger. +Shadings.SMALL_NUMBER = 1e-2; + +// Radial and axial shading have very similar implementations +// If needed, the implementations can be broken into two classes +Shadings.RadialAxial = (function RadialAxialClosure() { + function RadialAxial(dict, matrix, xref, res) { + this.matrix = matrix; + this.coordsArr = dict.get('Coords'); + this.shadingType = dict.get('ShadingType'); + this.type = 'Pattern'; + var cs = dict.get('ColorSpace', 'CS'); + cs = ColorSpace.parse(cs, xref, res); + this.cs = cs; + + var t0 = 0.0, t1 = 1.0; + if (dict.has('Domain')) { + var domainArr = dict.get('Domain'); + t0 = domainArr[0]; + t1 = domainArr[1]; + } + + var extendStart = false, extendEnd = false; + if (dict.has('Extend')) { + var extendArr = dict.get('Extend'); + extendStart = extendArr[0]; + extendEnd = extendArr[1]; + } + + if (this.shadingType === PatternType.RADIAL && + (!extendStart || !extendEnd)) { + // Radial gradient only currently works if either circle is fully within + // the other circle. + var x1 = this.coordsArr[0]; + var y1 = this.coordsArr[1]; + var r1 = this.coordsArr[2]; + var x2 = this.coordsArr[3]; + var y2 = this.coordsArr[4]; + var r2 = this.coordsArr[5]; + var distance = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)); + if (r1 <= r2 + distance && + r2 <= r1 + distance) { + warn('Unsupported radial gradient.'); + } + } + + this.extendStart = extendStart; + this.extendEnd = extendEnd; + + var fnObj = dict.get('Function'); + var fn = PDFFunction.parseArray(xref, fnObj); + + // 10 samples seems good enough for now, but probably won't work + // if there are sharp color changes. Ideally, we would implement + // the spec faithfully and add lossless optimizations. + var diff = t1 - t0; + var step = diff / 10; + + var colorStops = this.colorStops = []; + + // Protect against bad domains so we don't end up in an infinte loop below. + if (t0 >= t1 || step <= 0) { + // Acrobat doesn't seem to handle these cases so we'll ignore for + // now. + info('Bad shading domain.'); + return; + } + + var color = new Float32Array(cs.numComps), ratio = new Float32Array(1); + var rgbColor; + for (var i = t0; i <= t1; i += step) { + ratio[0] = i; + fn(ratio, 0, color, 0); + rgbColor = cs.getRgb(color, 0); + var cssColor = Util.makeCssRgb(rgbColor[0], rgbColor[1], rgbColor[2]); + colorStops.push([(i - t0) / diff, cssColor]); + } + + var background = 'transparent'; + if (dict.has('Background')) { + rgbColor = cs.getRgb(dict.get('Background'), 0); + background = Util.makeCssRgb(rgbColor[0], rgbColor[1], rgbColor[2]); + } + + if (!extendStart) { + // Insert a color stop at the front and offset the first real color stop + // so it doesn't conflict with the one we insert. + colorStops.unshift([0, background]); + colorStops[1][0] += Shadings.SMALL_NUMBER; + } + if (!extendEnd) { + // Same idea as above in extendStart but for the end. + colorStops[colorStops.length - 1][0] -= Shadings.SMALL_NUMBER; + colorStops.push([1, background]); + } + + this.colorStops = colorStops; + } + + RadialAxial.prototype = { + getIR: function RadialAxial_getIR() { + var coordsArr = this.coordsArr; + var shadingType = this.shadingType; + var type, p0, p1, r0, r1; + if (shadingType === PatternType.AXIAL) { + p0 = [coordsArr[0], coordsArr[1]]; + p1 = [coordsArr[2], coordsArr[3]]; + r0 = null; + r1 = null; + type = 'axial'; + } else if (shadingType === PatternType.RADIAL) { + p0 = [coordsArr[0], coordsArr[1]]; + p1 = [coordsArr[3], coordsArr[4]]; + r0 = coordsArr[2]; + r1 = coordsArr[5]; + type = 'radial'; + } else { + error('getPattern type unknown: ' + shadingType); + } + + var matrix = this.matrix; + if (matrix) { + p0 = Util.applyTransform(p0, matrix); + p1 = Util.applyTransform(p1, matrix); + } + + return ['RadialAxial', type, this.colorStops, p0, p1, r0, r1]; + } + }; + + return RadialAxial; +})(); + +// All mesh shading. For now, they will be presented as set of the triangles +// to be drawn on the canvas and rgb color for each vertex. +Shadings.Mesh = (function MeshClosure() { + function MeshStreamReader(stream, context) { + this.stream = stream; + this.context = context; + this.buffer = 0; + this.bufferLength = 0; + + var numComps = context.numComps; + this.tmpCompsBuf = new Float32Array(numComps); + var csNumComps = context.colorSpace; + this.tmpCsCompsBuf = context.colorFn ? new Float32Array(csNumComps) : + this.tmpCompsBuf; + } + MeshStreamReader.prototype = { + get hasData() { + if (this.stream.end) { + return this.stream.pos < this.stream.end; + } + if (this.bufferLength > 0) { + return true; + } + var nextByte = this.stream.getByte(); + if (nextByte < 0) { + return false; + } + this.buffer = nextByte; + this.bufferLength = 8; + return true; + }, + readBits: function MeshStreamReader_readBits(n) { + var buffer = this.buffer; + var bufferLength = this.bufferLength; + if (n === 32) { + if (bufferLength === 0) { + return ((this.stream.getByte() << 24) | + (this.stream.getByte() << 16) | (this.stream.getByte() << 8) | + this.stream.getByte()) >>> 0; + } + buffer = (buffer << 24) | (this.stream.getByte() << 16) | + (this.stream.getByte() << 8) | this.stream.getByte(); + var nextByte = this.stream.getByte(); + this.buffer = nextByte & ((1 << bufferLength) - 1); + return ((buffer << (8 - bufferLength)) | + ((nextByte & 0xFF) >> bufferLength)) >>> 0; + } + if (n === 8 && bufferLength === 0) { + return this.stream.getByte(); + } + while (bufferLength < n) { + buffer = (buffer << 8) | this.stream.getByte(); + bufferLength += 8; + } + bufferLength -= n; + this.bufferLength = bufferLength; + this.buffer = buffer & ((1 << bufferLength) - 1); + return buffer >> bufferLength; + }, + align: function MeshStreamReader_align() { + this.buffer = 0; + this.bufferLength = 0; + }, + readFlag: function MeshStreamReader_readFlag() { + return this.readBits(this.context.bitsPerFlag); + }, + readCoordinate: function MeshStreamReader_readCoordinate() { + var bitsPerCoordinate = this.context.bitsPerCoordinate; + var xi = this.readBits(bitsPerCoordinate); + var yi = this.readBits(bitsPerCoordinate); + var decode = this.context.decode; + var scale = bitsPerCoordinate < 32 ? 1 / ((1 << bitsPerCoordinate) - 1) : + 2.3283064365386963e-10; // 2 ^ -32 + return [ + xi * scale * (decode[1] - decode[0]) + decode[0], + yi * scale * (decode[3] - decode[2]) + decode[2] + ]; + }, + readComponents: function MeshStreamReader_readComponents() { + var numComps = this.context.numComps; + var bitsPerComponent = this.context.bitsPerComponent; + var scale = bitsPerComponent < 32 ? 1 / ((1 << bitsPerComponent) - 1) : + 2.3283064365386963e-10; // 2 ^ -32 + var decode = this.context.decode; + var components = this.tmpCompsBuf; + for (var i = 0, j = 4; i < numComps; i++, j += 2) { + var ci = this.readBits(bitsPerComponent); + components[i] = ci * scale * (decode[j + 1] - decode[j]) + decode[j]; + } + var color = this.tmpCsCompsBuf; + if (this.context.colorFn) { + this.context.colorFn(components, 0, color, 0); + } + return this.context.colorSpace.getRgb(color, 0); + } + }; + + function decodeType4Shading(mesh, reader) { + var coords = mesh.coords; + var colors = mesh.colors; + var operators = []; + var ps = []; // not maintaining cs since that will match ps + var verticesLeft = 0; // assuming we have all data to start a new triangle + while (reader.hasData) { + var f = reader.readFlag(); + var coord = reader.readCoordinate(); + var color = reader.readComponents(); + if (verticesLeft === 0) { // ignoring flags if we started a triangle + assert(0 <= f && f <= 2, 'Unknown type4 flag'); + switch (f) { + case 0: + verticesLeft = 3; + break; + case 1: + ps.push(ps[ps.length - 2], ps[ps.length - 1]); + verticesLeft = 1; + break; + case 2: + ps.push(ps[ps.length - 3], ps[ps.length - 1]); + verticesLeft = 1; + break; + } + operators.push(f); + } + ps.push(coords.length); + coords.push(coord); + colors.push(color); + verticesLeft--; + + reader.align(); + } + + var psPacked = new Int32Array(ps); + + mesh.figures.push({ + type: 'triangles', + coords: psPacked, + colors: psPacked + }); + } + + function decodeType5Shading(mesh, reader, verticesPerRow) { + var coords = mesh.coords; + var colors = mesh.colors; + var ps = []; // not maintaining cs since that will match ps + while (reader.hasData) { + var coord = reader.readCoordinate(); + var color = reader.readComponents(); + ps.push(coords.length); + coords.push(coord); + colors.push(color); + } + + var psPacked = new Int32Array(ps); + + mesh.figures.push({ + type: 'lattice', + coords: psPacked, + colors: psPacked, + verticesPerRow: verticesPerRow + }); + } + + var MIN_SPLIT_PATCH_CHUNKS_AMOUNT = 3; + var MAX_SPLIT_PATCH_CHUNKS_AMOUNT = 20; + + var TRIANGLE_DENSITY = 20; // count of triangles per entire mesh bounds + + var getB = (function getBClosure() { + function buildB(count) { + var lut = []; + for (var i = 0; i <= count; i++) { + var t = i / count, t_ = 1 - t; + lut.push(new Float32Array([t_ * t_ * t_, 3 * t * t_ * t_, + 3 * t * t * t_, t * t * t])); + } + return lut; + } + var cache = []; + return function getB(count) { + if (!cache[count]) { + cache[count] = buildB(count); + } + return cache[count]; + }; + })(); + + function buildFigureFromPatch(mesh, index) { + var figure = mesh.figures[index]; + assert(figure.type === 'patch', 'Unexpected patch mesh figure'); + + var coords = mesh.coords, colors = mesh.colors; + var pi = figure.coords; + var ci = figure.colors; + + var figureMinX = Math.min(coords[pi[0]][0], coords[pi[3]][0], + coords[pi[12]][0], coords[pi[15]][0]); + var figureMinY = Math.min(coords[pi[0]][1], coords[pi[3]][1], + coords[pi[12]][1], coords[pi[15]][1]); + var figureMaxX = Math.max(coords[pi[0]][0], coords[pi[3]][0], + coords[pi[12]][0], coords[pi[15]][0]); + var figureMaxY = Math.max(coords[pi[0]][1], coords[pi[3]][1], + coords[pi[12]][1], coords[pi[15]][1]); + var splitXBy = Math.ceil((figureMaxX - figureMinX) * TRIANGLE_DENSITY / + (mesh.bounds[2] - mesh.bounds[0])); + splitXBy = Math.max(MIN_SPLIT_PATCH_CHUNKS_AMOUNT, + Math.min(MAX_SPLIT_PATCH_CHUNKS_AMOUNT, splitXBy)); + var splitYBy = Math.ceil((figureMaxY - figureMinY) * TRIANGLE_DENSITY / + (mesh.bounds[3] - mesh.bounds[1])); + splitYBy = Math.max(MIN_SPLIT_PATCH_CHUNKS_AMOUNT, + Math.min(MAX_SPLIT_PATCH_CHUNKS_AMOUNT, splitYBy)); + + var verticesPerRow = splitXBy + 1; + var figureCoords = new Int32Array((splitYBy + 1) * verticesPerRow); + var figureColors = new Int32Array((splitYBy + 1) * verticesPerRow); + var k = 0; + var cl = new Uint8Array(3), cr = new Uint8Array(3); + var c0 = colors[ci[0]], c1 = colors[ci[1]], + c2 = colors[ci[2]], c3 = colors[ci[3]]; + var bRow = getB(splitYBy), bCol = getB(splitXBy); + for (var row = 0; row <= splitYBy; row++) { + cl[0] = ((c0[0] * (splitYBy - row) + c2[0] * row) / splitYBy) | 0; + cl[1] = ((c0[1] * (splitYBy - row) + c2[1] * row) / splitYBy) | 0; + cl[2] = ((c0[2] * (splitYBy - row) + c2[2] * row) / splitYBy) | 0; + + cr[0] = ((c1[0] * (splitYBy - row) + c3[0] * row) / splitYBy) | 0; + cr[1] = ((c1[1] * (splitYBy - row) + c3[1] * row) / splitYBy) | 0; + cr[2] = ((c1[2] * (splitYBy - row) + c3[2] * row) / splitYBy) | 0; + + for (var col = 0; col <= splitXBy; col++, k++) { + if ((row === 0 || row === splitYBy) && + (col === 0 || col === splitXBy)) { + continue; + } + var x = 0, y = 0; + var q = 0; + for (var i = 0; i <= 3; i++) { + for (var j = 0; j <= 3; j++, q++) { + var m = bRow[row][i] * bCol[col][j]; + x += coords[pi[q]][0] * m; + y += coords[pi[q]][1] * m; + } + } + figureCoords[k] = coords.length; + coords.push([x, y]); + figureColors[k] = colors.length; + var newColor = new Uint8Array(3); + newColor[0] = ((cl[0] * (splitXBy - col) + cr[0] * col) / splitXBy) | 0; + newColor[1] = ((cl[1] * (splitXBy - col) + cr[1] * col) / splitXBy) | 0; + newColor[2] = ((cl[2] * (splitXBy - col) + cr[2] * col) / splitXBy) | 0; + colors.push(newColor); + } + } + figureCoords[0] = pi[0]; + figureColors[0] = ci[0]; + figureCoords[splitXBy] = pi[3]; + figureColors[splitXBy] = ci[1]; + figureCoords[verticesPerRow * splitYBy] = pi[12]; + figureColors[verticesPerRow * splitYBy] = ci[2]; + figureCoords[verticesPerRow * splitYBy + splitXBy] = pi[15]; + figureColors[verticesPerRow * splitYBy + splitXBy] = ci[3]; + + mesh.figures[index] = { + type: 'lattice', + coords: figureCoords, + colors: figureColors, + verticesPerRow: verticesPerRow + }; + } + + function decodeType6Shading(mesh, reader) { + // A special case of Type 7. The p11, p12, p21, p22 automatically filled + var coords = mesh.coords; + var colors = mesh.colors; + var ps = new Int32Array(16); // p00, p10, ..., p30, p01, ..., p33 + var cs = new Int32Array(4); // c00, c30, c03, c33 + while (reader.hasData) { + var f = reader.readFlag(); + assert(0 <= f && f <= 3, 'Unknown type6 flag'); + var i, ii; + var pi = coords.length; + for (i = 0, ii = (f !== 0 ? 8 : 12); i < ii; i++) { + coords.push(reader.readCoordinate()); + } + var ci = colors.length; + for (i = 0, ii = (f !== 0 ? 2 : 4); i < ii; i++) { + colors.push(reader.readComponents()); + } + var tmp1, tmp2, tmp3, tmp4; + switch (f) { + case 0: + ps[12] = pi + 3; ps[13] = pi + 4; ps[14] = pi + 5; ps[15] = pi + 6; + ps[ 8] = pi + 2; /* values for 5, 6, 9, 10 are */ ps[11] = pi + 7; + ps[ 4] = pi + 1; /* calculated below */ ps[ 7] = pi + 8; + ps[ 0] = pi; ps[ 1] = pi + 11; ps[ 2] = pi + 10; ps[ 3] = pi + 9; + cs[2] = ci + 1; cs[3] = ci + 2; + cs[0] = ci; cs[1] = ci + 3; + break; + case 1: + tmp1 = ps[12]; tmp2 = ps[13]; tmp3 = ps[14]; tmp4 = ps[15]; + ps[12] = pi + 5; ps[13] = pi + 4; ps[14] = pi + 3; ps[15] = pi + 2; + ps[ 8] = pi + 6; /* values for 5, 6, 9, 10 are */ ps[11] = pi + 1; + ps[ 4] = pi + 7; /* calculated below */ ps[ 7] = pi; + ps[ 0] = tmp1; ps[ 1] = tmp2; ps[ 2] = tmp3; ps[ 3] = tmp4; + tmp1 = cs[2]; tmp2 = cs[3]; + cs[2] = ci + 1; cs[3] = ci; + cs[0] = tmp1; cs[1] = tmp2; + break; + case 2: + ps[12] = ps[15]; ps[13] = pi + 7; ps[14] = pi + 6; ps[15] = pi + 5; + ps[ 8] = ps[11]; /* values for 5, 6, 9, 10 are */ ps[11] = pi + 4; + ps[ 4] = ps[7]; /* calculated below */ ps[ 7] = pi + 3; + ps[ 0] = ps[3]; ps[ 1] = pi; ps[ 2] = pi + 1; ps[ 3] = pi + 2; + cs[2] = cs[3]; cs[3] = ci + 1; + cs[0] = cs[1]; cs[1] = ci; + break; + case 3: + ps[12] = ps[0]; ps[13] = ps[1]; ps[14] = ps[2]; ps[15] = ps[3]; + ps[ 8] = pi; /* values for 5, 6, 9, 10 are */ ps[11] = pi + 7; + ps[ 4] = pi + 1; /* calculated below */ ps[ 7] = pi + 6; + ps[ 0] = pi + 2; ps[ 1] = pi + 3; ps[ 2] = pi + 4; ps[ 3] = pi + 5; + cs[2] = cs[0]; cs[3] = cs[1]; + cs[0] = ci; cs[1] = ci + 1; + break; + } + // set p11, p12, p21, p22 + ps[5] = coords.length; + coords.push([ + (-4 * coords[ps[0]][0] - coords[ps[15]][0] + + 6 * (coords[ps[4]][0] + coords[ps[1]][0]) - + 2 * (coords[ps[12]][0] + coords[ps[3]][0]) + + 3 * (coords[ps[13]][0] + coords[ps[7]][0])) / 9, + (-4 * coords[ps[0]][1] - coords[ps[15]][1] + + 6 * (coords[ps[4]][1] + coords[ps[1]][1]) - + 2 * (coords[ps[12]][1] + coords[ps[3]][1]) + + 3 * (coords[ps[13]][1] + coords[ps[7]][1])) / 9 + ]); + ps[6] = coords.length; + coords.push([ + (-4 * coords[ps[3]][0] - coords[ps[12]][0] + + 6 * (coords[ps[2]][0] + coords[ps[7]][0]) - + 2 * (coords[ps[0]][0] + coords[ps[15]][0]) + + 3 * (coords[ps[4]][0] + coords[ps[14]][0])) / 9, + (-4 * coords[ps[3]][1] - coords[ps[12]][1] + + 6 * (coords[ps[2]][1] + coords[ps[7]][1]) - + 2 * (coords[ps[0]][1] + coords[ps[15]][1]) + + 3 * (coords[ps[4]][1] + coords[ps[14]][1])) / 9 + ]); + ps[9] = coords.length; + coords.push([ + (-4 * coords[ps[12]][0] - coords[ps[3]][0] + + 6 * (coords[ps[8]][0] + coords[ps[13]][0]) - + 2 * (coords[ps[0]][0] + coords[ps[15]][0]) + + 3 * (coords[ps[11]][0] + coords[ps[1]][0])) / 9, + (-4 * coords[ps[12]][1] - coords[ps[3]][1] + + 6 * (coords[ps[8]][1] + coords[ps[13]][1]) - + 2 * (coords[ps[0]][1] + coords[ps[15]][1]) + + 3 * (coords[ps[11]][1] + coords[ps[1]][1])) / 9 + ]); + ps[10] = coords.length; + coords.push([ + (-4 * coords[ps[15]][0] - coords[ps[0]][0] + + 6 * (coords[ps[11]][0] + coords[ps[14]][0]) - + 2 * (coords[ps[12]][0] + coords[ps[3]][0]) + + 3 * (coords[ps[2]][0] + coords[ps[8]][0])) / 9, + (-4 * coords[ps[15]][1] - coords[ps[0]][1] + + 6 * (coords[ps[11]][1] + coords[ps[14]][1]) - + 2 * (coords[ps[12]][1] + coords[ps[3]][1]) + + 3 * (coords[ps[2]][1] + coords[ps[8]][1])) / 9 + ]); + mesh.figures.push({ + type: 'patch', + coords: new Int32Array(ps), // making copies of ps and cs + colors: new Int32Array(cs) + }); + } + } + + function decodeType7Shading(mesh, reader) { + var coords = mesh.coords; + var colors = mesh.colors; + var ps = new Int32Array(16); // p00, p10, ..., p30, p01, ..., p33 + var cs = new Int32Array(4); // c00, c30, c03, c33 + while (reader.hasData) { + var f = reader.readFlag(); + assert(0 <= f && f <= 3, 'Unknown type7 flag'); + var i, ii; + var pi = coords.length; + for (i = 0, ii = (f !== 0 ? 12 : 16); i < ii; i++) { + coords.push(reader.readCoordinate()); + } + var ci = colors.length; + for (i = 0, ii = (f !== 0 ? 2 : 4); i < ii; i++) { + colors.push(reader.readComponents()); + } + var tmp1, tmp2, tmp3, tmp4; + switch (f) { + case 0: + ps[12] = pi + 3; ps[13] = pi + 4; ps[14] = pi + 5; ps[15] = pi + 6; + ps[ 8] = pi + 2; ps[ 9] = pi + 13; ps[10] = pi + 14; ps[11] = pi + 7; + ps[ 4] = pi + 1; ps[ 5] = pi + 12; ps[ 6] = pi + 15; ps[ 7] = pi + 8; + ps[ 0] = pi; ps[ 1] = pi + 11; ps[ 2] = pi + 10; ps[ 3] = pi + 9; + cs[2] = ci + 1; cs[3] = ci + 2; + cs[0] = ci; cs[1] = ci + 3; + break; + case 1: + tmp1 = ps[12]; tmp2 = ps[13]; tmp3 = ps[14]; tmp4 = ps[15]; + ps[12] = pi + 5; ps[13] = pi + 4; ps[14] = pi + 3; ps[15] = pi + 2; + ps[ 8] = pi + 6; ps[ 9] = pi + 11; ps[10] = pi + 10; ps[11] = pi + 1; + ps[ 4] = pi + 7; ps[ 5] = pi + 8; ps[ 6] = pi + 9; ps[ 7] = pi; + ps[ 0] = tmp1; ps[ 1] = tmp2; ps[ 2] = tmp3; ps[ 3] = tmp4; + tmp1 = cs[2]; tmp2 = cs[3]; + cs[2] = ci + 1; cs[3] = ci; + cs[0] = tmp1; cs[1] = tmp2; + break; + case 2: + ps[12] = ps[15]; ps[13] = pi + 7; ps[14] = pi + 6; ps[15] = pi + 5; + ps[ 8] = ps[11]; ps[ 9] = pi + 8; ps[10] = pi + 11; ps[11] = pi + 4; + ps[ 4] = ps[7]; ps[ 5] = pi + 9; ps[ 6] = pi + 10; ps[ 7] = pi + 3; + ps[ 0] = ps[3]; ps[ 1] = pi; ps[ 2] = pi + 1; ps[ 3] = pi + 2; + cs[2] = cs[3]; cs[3] = ci + 1; + cs[0] = cs[1]; cs[1] = ci; + break; + case 3: + ps[12] = ps[0]; ps[13] = ps[1]; ps[14] = ps[2]; ps[15] = ps[3]; + ps[ 8] = pi; ps[ 9] = pi + 9; ps[10] = pi + 8; ps[11] = pi + 7; + ps[ 4] = pi + 1; ps[ 5] = pi + 10; ps[ 6] = pi + 11; ps[ 7] = pi + 6; + ps[ 0] = pi + 2; ps[ 1] = pi + 3; ps[ 2] = pi + 4; ps[ 3] = pi + 5; + cs[2] = cs[0]; cs[3] = cs[1]; + cs[0] = ci; cs[1] = ci + 1; + break; + } + mesh.figures.push({ + type: 'patch', + coords: new Int32Array(ps), // making copies of ps and cs + colors: new Int32Array(cs) + }); + } + } + + function updateBounds(mesh) { + var minX = mesh.coords[0][0], minY = mesh.coords[0][1], + maxX = minX, maxY = minY; + for (var i = 1, ii = mesh.coords.length; i < ii; i++) { + var x = mesh.coords[i][0], y = mesh.coords[i][1]; + minX = minX > x ? x : minX; + minY = minY > y ? y : minY; + maxX = maxX < x ? x : maxX; + maxY = maxY < y ? y : maxY; + } + mesh.bounds = [minX, minY, maxX, maxY]; + } + + function packData(mesh) { + var i, ii, j, jj; + + var coords = mesh.coords; + var coordsPacked = new Float32Array(coords.length * 2); + for (i = 0, j = 0, ii = coords.length; i < ii; i++) { + var xy = coords[i]; + coordsPacked[j++] = xy[0]; + coordsPacked[j++] = xy[1]; + } + mesh.coords = coordsPacked; + + var colors = mesh.colors; + var colorsPacked = new Uint8Array(colors.length * 3); + for (i = 0, j = 0, ii = colors.length; i < ii; i++) { + var c = colors[i]; + colorsPacked[j++] = c[0]; + colorsPacked[j++] = c[1]; + colorsPacked[j++] = c[2]; + } + mesh.colors = colorsPacked; + + var figures = mesh.figures; + for (i = 0, ii = figures.length; i < ii; i++) { + var figure = figures[i], ps = figure.coords, cs = figure.colors; + for (j = 0, jj = ps.length; j < jj; j++) { + ps[j] *= 2; + cs[j] *= 3; + } + } + } + + function Mesh(stream, matrix, xref, res) { + assert(isStream(stream), 'Mesh data is not a stream'); + var dict = stream.dict; + this.matrix = matrix; + this.shadingType = dict.get('ShadingType'); + this.type = 'Pattern'; + this.bbox = dict.get('BBox'); + var cs = dict.get('ColorSpace', 'CS'); + cs = ColorSpace.parse(cs, xref, res); + this.cs = cs; + this.background = dict.has('Background') ? + cs.getRgb(dict.get('Background'), 0) : null; + + var fnObj = dict.get('Function'); + var fn = fnObj ? PDFFunction.parseArray(xref, fnObj) : null; + + this.coords = []; + this.colors = []; + this.figures = []; + + var decodeContext = { + bitsPerCoordinate: dict.get('BitsPerCoordinate'), + bitsPerComponent: dict.get('BitsPerComponent'), + bitsPerFlag: dict.get('BitsPerFlag'), + decode: dict.get('Decode'), + colorFn: fn, + colorSpace: cs, + numComps: fn ? 1 : cs.numComps + }; + var reader = new MeshStreamReader(stream, decodeContext); + + var patchMesh = false; + switch (this.shadingType) { + case PatternType.FREE_FORM_MESH: + decodeType4Shading(this, reader); + break; + case PatternType.LATTICE_FORM_MESH: + var verticesPerRow = dict.get('VerticesPerRow') | 0; + assert(verticesPerRow >= 2, 'Invalid VerticesPerRow'); + decodeType5Shading(this, reader, verticesPerRow); + break; + case PatternType.COONS_PATCH_MESH: + decodeType6Shading(this, reader); + patchMesh = true; + break; + case PatternType.TENSOR_PATCH_MESH: + decodeType7Shading(this, reader); + patchMesh = true; + break; + default: + error('Unsupported mesh type.'); + break; + } + + if (patchMesh) { + // dirty bounds calculation for determining, how dense shall be triangles + updateBounds(this); + for (var i = 0, ii = this.figures.length; i < ii; i++) { + buildFigureFromPatch(this, i); + } + } + // calculate bounds + updateBounds(this); + + packData(this); + } + + Mesh.prototype = { + getIR: function Mesh_getIR() { + return ['Mesh', this.shadingType, this.coords, this.colors, this.figures, + this.bounds, this.matrix, this.bbox, this.background]; + } + }; + + return Mesh; +})(); + +Shadings.Dummy = (function DummyClosure() { + function Dummy() { + this.type = 'Pattern'; + } + + Dummy.prototype = { + getIR: function Dummy_getIR() { + return ['Dummy']; + } + }; + return Dummy; +})(); + +function getTilingPatternIR(operatorList, dict, args) { + var matrix = dict.get('Matrix'); + var bbox = dict.get('BBox'); + var xstep = dict.get('XStep'); + var ystep = dict.get('YStep'); + var paintType = dict.get('PaintType'); + var tilingType = dict.get('TilingType'); + + return [ + 'TilingPattern', args, operatorList, matrix, bbox, xstep, ystep, + paintType, tilingType + ]; +} + + +var PartialEvaluator = (function PartialEvaluatorClosure() { + function PartialEvaluator(pdfManager, xref, handler, pageIndex, + uniquePrefix, idCounters, fontCache) { + this.pdfManager = pdfManager; + this.xref = xref; + this.handler = handler; + this.pageIndex = pageIndex; + this.uniquePrefix = uniquePrefix; + this.idCounters = idCounters; + this.fontCache = fontCache; + } + + // Trying to minimize Date.now() usage and check every 100 time + var TIME_SLOT_DURATION_MS = 20; + var CHECK_TIME_EVERY = 100; + function TimeSlotManager() { + this.reset(); + } + TimeSlotManager.prototype = { + check: function TimeSlotManager_check() { + if (++this.checked < CHECK_TIME_EVERY) { + return false; + } + this.checked = 0; + return this.endTime <= Date.now(); + }, + reset: function TimeSlotManager_reset() { + this.endTime = Date.now() + TIME_SLOT_DURATION_MS; + this.checked = 0; + } + }; + + var deferred = Promise.resolve(); + + var TILING_PATTERN = 1, SHADING_PATTERN = 2; + + PartialEvaluator.prototype = { + hasBlendModes: function PartialEvaluator_hasBlendModes(resources) { + if (!isDict(resources)) { + return false; + } + + var processed = Object.create(null); + if (resources.objId) { + processed[resources.objId] = true; + } + + var nodes = [resources]; + while (nodes.length) { + var key; + var node = nodes.shift(); + // First check the current resources for blend modes. + var graphicStates = node.get('ExtGState'); + if (isDict(graphicStates)) { + graphicStates = graphicStates.getAll(); + for (key in graphicStates) { + var graphicState = graphicStates[key]; + var bm = graphicState['BM']; + if (isName(bm) && bm.name !== 'Normal') { + return true; + } + } + } + // Descend into the XObjects to look for more resources and blend modes. + var xObjects = node.get('XObject'); + if (!isDict(xObjects)) { + continue; + } + xObjects = xObjects.getAll(); + for (key in xObjects) { + var xObject = xObjects[key]; + if (!isStream(xObject)) { + continue; + } + if (xObject.dict.objId) { + if (processed[xObject.dict.objId]) { + // stream has objId and is processed already + continue; + } + processed[xObject.dict.objId] = true; + } + var xResources = xObject.dict.get('Resources'); + // Checking objId to detect an infinite loop. + if (isDict(xResources) && + (!xResources.objId || !processed[xResources.objId])) { + nodes.push(xResources); + if (xResources.objId) { + processed[xResources.objId] = true; + } + } + } + } + return false; + }, + + buildFormXObject: function PartialEvaluator_buildFormXObject(resources, + xobj, smask, + operatorList, + initialState) { + var matrix = xobj.dict.get('Matrix'); + var bbox = xobj.dict.get('BBox'); + var group = xobj.dict.get('Group'); + if (group) { + var groupOptions = { + matrix: matrix, + bbox: bbox, + smask: smask, + isolated: false, + knockout: false + }; + + var groupSubtype = group.get('S'); + var colorSpace; + if (isName(groupSubtype) && groupSubtype.name === 'Transparency') { + groupOptions.isolated = (group.get('I') || false); + groupOptions.knockout = (group.get('K') || false); + colorSpace = (group.has('CS') ? + ColorSpace.parse(group.get('CS'), this.xref, resources) : null); + } + + if (smask && smask.backdrop) { + colorSpace = colorSpace || ColorSpace.singletons.rgb; + smask.backdrop = colorSpace.getRgb(smask.backdrop, 0); + } + + operatorList.addOp(OPS.beginGroup, [groupOptions]); + } + + operatorList.addOp(OPS.paintFormXObjectBegin, [matrix, bbox]); + + return this.getOperatorList(xobj, + (xobj.dict.get('Resources') || resources), operatorList, initialState). + then(function () { + operatorList.addOp(OPS.paintFormXObjectEnd, []); + + if (group) { + operatorList.addOp(OPS.endGroup, [groupOptions]); + } + }); + }, + + buildPaintImageXObject: + function PartialEvaluator_buildPaintImageXObject(resources, image, + inline, operatorList, + cacheKey, imageCache) { + var self = this; + var dict = image.dict; + var w = dict.get('Width', 'W'); + var h = dict.get('Height', 'H'); + + if (!(w && isNum(w)) || !(h && isNum(h))) { + warn('Image dimensions are missing, or not numbers.'); + return; + } + if (PDFJS.maxImageSize !== -1 && w * h > PDFJS.maxImageSize) { + warn('Image exceeded maximum allowed size and was removed.'); + return; + } + + var imageMask = (dict.get('ImageMask', 'IM') || false); + var imgData, args; + if (imageMask) { + // This depends on a tmpCanvas being filled with the + // current fillStyle, such that processing the pixel + // data can't be done here. Instead of creating a + // complete PDFImage, only read the information needed + // for later. + + var width = dict.get('Width', 'W'); + var height = dict.get('Height', 'H'); + var bitStrideLength = (width + 7) >> 3; + var imgArray = image.getBytes(bitStrideLength * height); + var decode = dict.get('Decode', 'D'); + var inverseDecode = (!!decode && decode[0] > 0); + + imgData = PDFImage.createMask(imgArray, width, height, + image instanceof DecodeStream, + inverseDecode); + imgData.cached = true; + args = [imgData]; + operatorList.addOp(OPS.paintImageMaskXObject, args); + if (cacheKey) { + imageCache[cacheKey] = { + fn: OPS.paintImageMaskXObject, + args: args + }; + } + return; + } + + var softMask = (dict.get('SMask', 'SM') || false); + var mask = (dict.get('Mask') || false); + + var SMALL_IMAGE_DIMENSIONS = 200; + // Inlining small images into the queue as RGB data + if (inline && !softMask && !mask && !(image instanceof JpegStream) && + (w + h) < SMALL_IMAGE_DIMENSIONS) { + var imageObj = new PDFImage(this.xref, resources, image, + inline, null, null); + // We force the use of RGBA_32BPP images here, because we can't handle + // any other kind. + imgData = imageObj.createImageData(/* forceRGBA = */ true); + operatorList.addOp(OPS.paintInlineImageXObject, [imgData]); + return; + } + + // If there is no imageMask, create the PDFImage and a lot + // of image processing can be done here. + var uniquePrefix = (this.uniquePrefix || ''); + var objId = 'img_' + uniquePrefix + (++this.idCounters.obj); + operatorList.addDependency(objId); + args = [objId, w, h]; + + if (!softMask && !mask && image instanceof JpegStream && + image.isNativelySupported(this.xref, resources)) { + // These JPEGs don't need any more processing so we can just send it. + operatorList.addOp(OPS.paintJpegXObject, args); + this.handler.send('obj', + [objId, this.pageIndex, 'JpegStream', image.getIR()]); + return; + } + + PDFImage.buildImage(self.handler, self.xref, resources, image, inline). + then(function(imageObj) { + var imgData = imageObj.createImageData(/* forceRGBA = */ false); + self.handler.send('obj', [objId, self.pageIndex, 'Image', imgData], + [imgData.data.buffer]); + }).then(undefined, function (reason) { + warn('Unable to decode image: ' + reason); + self.handler.send('obj', [objId, self.pageIndex, 'Image', null]); + }); + + operatorList.addOp(OPS.paintImageXObject, args); + if (cacheKey) { + imageCache[cacheKey] = { + fn: OPS.paintImageXObject, + args: args + }; + } + }, + + handleSMask: function PartialEvaluator_handleSmask(smask, resources, + operatorList, + stateManager) { + var smaskContent = smask.get('G'); + var smaskOptions = { + subtype: smask.get('S').name, + backdrop: smask.get('BC') + }; + return this.buildFormXObject(resources, smaskContent, smaskOptions, + operatorList, stateManager.state.clone()); + }, + + handleTilingType: + function PartialEvaluator_handleTilingType(fn, args, resources, + pattern, patternDict, + operatorList) { + // Create an IR of the pattern code. + var tilingOpList = new OperatorList(); + return this.getOperatorList(pattern, + (patternDict.get('Resources') || resources), tilingOpList). + then(function () { + // Add the dependencies to the parent operator list so they are + // resolved before sub operator list is executed synchronously. + operatorList.addDependencies(tilingOpList.dependencies); + operatorList.addOp(fn, getTilingPatternIR({ + fnArray: tilingOpList.fnArray, + argsArray: tilingOpList.argsArray + }, patternDict, args)); + }); + }, + + handleSetFont: + function PartialEvaluator_handleSetFont(resources, fontArgs, fontRef, + operatorList, state) { + // TODO(mack): Not needed? + var fontName; + if (fontArgs) { + fontArgs = fontArgs.slice(); + fontName = fontArgs[0].name; + } + + var self = this; + return this.loadFont(fontName, fontRef, this.xref, resources).then( + function (translated) { + if (!translated.font.isType3Font) { + return translated; + } + return translated.loadType3Data(self, resources, operatorList).then( + function () { + return translated; + }); + }).then(function (translated) { + state.font = translated.font; + translated.send(self.handler); + return translated.loadedName; + }); + }, + + handleText: function PartialEvaluator_handleText(chars, state) { + var font = state.font; + var glyphs = font.charsToGlyphs(chars); + var isAddToPathSet = !!(state.textRenderingMode & + TextRenderingMode.ADD_TO_PATH_FLAG); + if (font.data && (isAddToPathSet || PDFJS.disableFontFace)) { + var buildPath = function (fontChar) { + if (!font.renderer.hasBuiltPath(fontChar)) { + var path = font.renderer.getPathJs(fontChar); + this.handler.send('commonobj', [ + font.loadedName + '_path_' + fontChar, + 'FontPath', + path + ]); + } + }.bind(this); + + for (var i = 0, ii = glyphs.length; i < ii; i++) { + var glyph = glyphs[i]; + if (glyph === null) { + continue; + } + buildPath(glyph.fontChar); + + // If the glyph has an accent we need to build a path for its + // fontChar too, otherwise CanvasGraphics_paintChar will fail. + var accent = glyph.accent; + if (accent && accent.fontChar) { + buildPath(accent.fontChar); + } + } + } + + return glyphs; + }, + + setGState: function PartialEvaluator_setGState(resources, gState, + operatorList, xref, + stateManager) { + // This array holds the converted/processed state data. + var gStateObj = []; + var gStateMap = gState.map; + var self = this; + var promise = Promise.resolve(); + for (var key in gStateMap) { + var value = gStateMap[key]; + switch (key) { + case 'Type': + break; + case 'LW': + case 'LC': + case 'LJ': + case 'ML': + case 'D': + case 'RI': + case 'FL': + case 'CA': + case 'ca': + gStateObj.push([key, value]); + break; + case 'Font': + promise = promise.then(function () { + return self.handleSetFont(resources, null, value[0], + operatorList, stateManager.state). + then(function (loadedName) { + operatorList.addDependency(loadedName); + gStateObj.push([key, [loadedName, value[1]]]); + }); + }); + break; + case 'BM': + gStateObj.push([key, value]); + break; + case 'SMask': + if (isName(value) && value.name === 'None') { + gStateObj.push([key, false]); + break; + } + var dict = xref.fetchIfRef(value); + if (isDict(dict)) { + promise = promise.then(function () { + return self.handleSMask(dict, resources, operatorList, + stateManager); + }); + gStateObj.push([key, true]); + } else { + warn('Unsupported SMask type'); + } + + break; + // Only generate info log messages for the following since + // they are unlikely to have a big impact on the rendering. + case 'OP': + case 'op': + case 'OPM': + case 'BG': + case 'BG2': + case 'UCR': + case 'UCR2': + case 'TR': + case 'TR2': + case 'HT': + case 'SM': + case 'SA': + case 'AIS': + case 'TK': + // TODO implement these operators. + info('graphic state operator ' + key); + break; + default: + info('Unknown graphic state operator ' + key); + break; + } + } + return promise.then(function () { + if (gStateObj.length >= 0) { + operatorList.addOp(OPS.setGState, [gStateObj]); + } + }); + }, + + loadFont: function PartialEvaluator_loadFont(fontName, font, xref, + resources) { + + function errorFont() { + return Promise.resolve(new TranslatedFont('g_font_error', + new ErrorFont('Font ' + fontName + ' is not available'), font)); + } + var fontRef; + if (font) { // Loading by ref. + assert(isRef(font)); + fontRef = font; + } else { // Loading by name. + var fontRes = resources.get('Font'); + if (fontRes) { + fontRef = fontRes.getRaw(fontName); + } else { + warn('fontRes not available'); + return errorFont(); + } + } + if (!fontRef) { + warn('fontRef not available'); + return errorFont(); + } + + if (this.fontCache.has(fontRef)) { + return this.fontCache.get(fontRef); + } + + font = xref.fetchIfRef(fontRef); + if (!isDict(font)) { + return errorFont(); + } + + // We are holding font.translated references just for fontRef that are not + // dictionaries (Dict). See explanation below. + if (font.translated) { + return font.translated; + } + + var fontCapability = createPromiseCapability(); + + var preEvaluatedFont = this.preEvaluateFont(font, xref); + var descriptor = preEvaluatedFont.descriptor; + var fontID = fontRef.num + '_' + fontRef.gen; + if (isDict(descriptor)) { + if (!descriptor.fontAliases) { + descriptor.fontAliases = Object.create(null); + } + + var fontAliases = descriptor.fontAliases; + var hash = preEvaluatedFont.hash; + if (fontAliases[hash]) { + var aliasFontRef = fontAliases[hash].aliasRef; + if (aliasFontRef && this.fontCache.has(aliasFontRef)) { + this.fontCache.putAlias(fontRef, aliasFontRef); + return this.fontCache.get(fontRef); + } + } + + if (!fontAliases[hash]) { + fontAliases[hash] = { + fontID: Font.getFontID() + }; + } + + fontAliases[hash].aliasRef = fontRef; + fontID = fontAliases[hash].fontID; + } + + // Workaround for bad PDF generators that don't reference fonts + // properly, i.e. by not using an object identifier. + // Check if the fontRef is a Dict (as opposed to a standard object), + // in which case we don't cache the font and instead reference it by + // fontName in font.loadedName below. + var fontRefIsDict = isDict(fontRef); + if (!fontRefIsDict) { + this.fontCache.put(fontRef, fontCapability.promise); + } + + // Keep track of each font we translated so the caller can + // load them asynchronously before calling display on a page. + font.loadedName = 'g_font_' + (fontRefIsDict ? + fontName.replace(/\W/g, '') : fontID); + + font.translated = fontCapability.promise; + + // TODO move promises into translate font + var translatedPromise; + try { + translatedPromise = Promise.resolve( + this.translateFont(preEvaluatedFont, xref)); + } catch (e) { + translatedPromise = Promise.reject(e); + } + + translatedPromise.then(function (translatedFont) { + if (translatedFont.fontType !== undefined) { + var xrefFontStats = xref.stats.fontTypes; + xrefFontStats[translatedFont.fontType] = true; + } + + fontCapability.resolve(new TranslatedFont(font.loadedName, + translatedFont, font)); + }, function (reason) { + // TODO fontCapability.reject? + UnsupportedManager.notify(UNSUPPORTED_FEATURES.font); + + try { + // error, but it's still nice to have font type reported + var descriptor = preEvaluatedFont.descriptor; + var fontFile3 = descriptor && descriptor.get('FontFile3'); + var subtype = fontFile3 && fontFile3.get('Subtype'); + var fontType = getFontType(preEvaluatedFont.type, + subtype && subtype.name); + var xrefFontStats = xref.stats.fontTypes; + xrefFontStats[fontType] = true; + } catch (ex) { } + + fontCapability.resolve(new TranslatedFont(font.loadedName, + new ErrorFont(reason instanceof Error ? reason.message : reason), + font)); + }); + return fontCapability.promise; + }, + + buildPath: function PartialEvaluator_buildPath(operatorList, fn, args) { + var lastIndex = operatorList.length - 1; + if (!args) { + args = []; + } + if (lastIndex < 0 || + operatorList.fnArray[lastIndex] !== OPS.constructPath) { + operatorList.addOp(OPS.constructPath, [[fn], args]); + } else { + var opArgs = operatorList.argsArray[lastIndex]; + opArgs[0].push(fn); + Array.prototype.push.apply(opArgs[1], args); + } + }, + + handleColorN: function PartialEvaluator_handleColorN(operatorList, fn, args, + cs, patterns, resources, xref) { + // compile tiling patterns + var patternName = args[args.length - 1]; + // SCN/scn applies patterns along with normal colors + var pattern; + if (isName(patternName) && + (pattern = patterns.get(patternName.name))) { + var dict = (isStream(pattern) ? pattern.dict : pattern); + var typeNum = dict.get('PatternType'); + + if (typeNum === TILING_PATTERN) { + var color = cs.base ? cs.base.getRgb(args, 0) : null; + return this.handleTilingType(fn, color, resources, pattern, + dict, operatorList); + } else if (typeNum === SHADING_PATTERN) { + var shading = dict.get('Shading'); + var matrix = dict.get('Matrix'); + pattern = Pattern.parseShading(shading, matrix, xref, resources); + operatorList.addOp(fn, pattern.getIR()); + return Promise.resolve(); + } else { + return Promise.reject('Unknown PatternType: ' + typeNum); + } + } + // TODO shall we fail here? + operatorList.addOp(fn, args); + return Promise.resolve(); + }, + + getOperatorList: function PartialEvaluator_getOperatorList(stream, + resources, + operatorList, + initialState) { + + var self = this; + var xref = this.xref; + var imageCache = {}; + + assert(operatorList); + + resources = (resources || Dict.empty); + var xobjs = (resources.get('XObject') || Dict.empty); + var patterns = (resources.get('Pattern') || Dict.empty); + var stateManager = new StateManager(initialState || new EvalState()); + var preprocessor = new EvaluatorPreprocessor(stream, xref, stateManager); + var timeSlotManager = new TimeSlotManager(); + + return new Promise(function next(resolve, reject) { + timeSlotManager.reset(); + var stop, operation = {}, i, ii, cs; + while (!(stop = timeSlotManager.check())) { + // The arguments parsed by read() are used beyond this loop, so we + // cannot reuse the same array on each iteration. Therefore we pass + // in |null| as the initial value (see the comment on + // EvaluatorPreprocessor_read() for why). + operation.args = null; + if (!(preprocessor.read(operation))) { + break; + } + var args = operation.args; + var fn = operation.fn; + + switch (fn | 0) { + case OPS.paintXObject: + if (args[0].code) { + break; + } + // eagerly compile XForm objects + var name = args[0].name; + if (imageCache[name] !== undefined) { + operatorList.addOp(imageCache[name].fn, imageCache[name].args); + args = null; + continue; + } + + var xobj = xobjs.get(name); + if (xobj) { + assert(isStream(xobj), 'XObject should be a stream'); + + var type = xobj.dict.get('Subtype'); + assert(isName(type), + 'XObject should have a Name subtype'); + + if (type.name === 'Form') { + stateManager.save(); + return self.buildFormXObject(resources, xobj, null, + operatorList, + stateManager.state.clone()). + then(function () { + stateManager.restore(); + next(resolve, reject); + }, reject); + } else if (type.name === 'Image') { + self.buildPaintImageXObject(resources, xobj, false, + operatorList, name, imageCache); + args = null; + continue; + } else if (type.name === 'PS') { + // PostScript XObjects are unused when viewing documents. + // See section 4.7.1 of Adobe's PDF reference. + info('Ignored XObject subtype PS'); + continue; + } else { + error('Unhandled XObject subtype ' + type.name); + } + } + break; + case OPS.setFont: + var fontSize = args[1]; + // eagerly collect all fonts + return self.handleSetFont(resources, args, null, + operatorList, stateManager.state). + then(function (loadedName) { + operatorList.addDependency(loadedName); + operatorList.addOp(OPS.setFont, [loadedName, fontSize]); + next(resolve, reject); + }, reject); + case OPS.endInlineImage: + var cacheKey = args[0].cacheKey; + if (cacheKey) { + var cacheEntry = imageCache[cacheKey]; + if (cacheEntry !== undefined) { + operatorList.addOp(cacheEntry.fn, cacheEntry.args); + args = null; + continue; + } + } + self.buildPaintImageXObject(resources, args[0], true, + operatorList, cacheKey, imageCache); + args = null; + continue; + case OPS.showText: + args[0] = self.handleText(args[0], stateManager.state); + break; + case OPS.showSpacedText: + var arr = args[0]; + var combinedGlyphs = []; + var arrLength = arr.length; + for (i = 0; i < arrLength; ++i) { + var arrItem = arr[i]; + if (isString(arrItem)) { + Array.prototype.push.apply(combinedGlyphs, + self.handleText(arrItem, stateManager.state)); + } else if (isNum(arrItem)) { + combinedGlyphs.push(arrItem); + } + } + args[0] = combinedGlyphs; + fn = OPS.showText; + break; + case OPS.nextLineShowText: + operatorList.addOp(OPS.nextLine); + args[0] = self.handleText(args[0], stateManager.state); + fn = OPS.showText; + break; + case OPS.nextLineSetSpacingShowText: + operatorList.addOp(OPS.nextLine); + operatorList.addOp(OPS.setWordSpacing, [args.shift()]); + operatorList.addOp(OPS.setCharSpacing, [args.shift()]); + args[0] = self.handleText(args[0], stateManager.state); + fn = OPS.showText; + break; + case OPS.setTextRenderingMode: + stateManager.state.textRenderingMode = args[0]; + break; + + case OPS.setFillColorSpace: + stateManager.state.fillColorSpace = + ColorSpace.parse(args[0], xref, resources); + continue; + case OPS.setStrokeColorSpace: + stateManager.state.strokeColorSpace = + ColorSpace.parse(args[0], xref, resources); + continue; + case OPS.setFillColor: + cs = stateManager.state.fillColorSpace; + args = cs.getRgb(args, 0); + fn = OPS.setFillRGBColor; + break; + case OPS.setStrokeColor: + cs = stateManager.state.strokeColorSpace; + args = cs.getRgb(args, 0); + fn = OPS.setStrokeRGBColor; + break; + case OPS.setFillGray: + stateManager.state.fillColorSpace = ColorSpace.singletons.gray; + args = ColorSpace.singletons.gray.getRgb(args, 0); + fn = OPS.setFillRGBColor; + break; + case OPS.setStrokeGray: + stateManager.state.strokeColorSpace = ColorSpace.singletons.gray; + args = ColorSpace.singletons.gray.getRgb(args, 0); + fn = OPS.setStrokeRGBColor; + break; + case OPS.setFillCMYKColor: + stateManager.state.fillColorSpace = ColorSpace.singletons.cmyk; + args = ColorSpace.singletons.cmyk.getRgb(args, 0); + fn = OPS.setFillRGBColor; + break; + case OPS.setStrokeCMYKColor: + stateManager.state.strokeColorSpace = ColorSpace.singletons.cmyk; + args = ColorSpace.singletons.cmyk.getRgb(args, 0); + fn = OPS.setStrokeRGBColor; + break; + case OPS.setFillRGBColor: + stateManager.state.fillColorSpace = ColorSpace.singletons.rgb; + args = ColorSpace.singletons.rgb.getRgb(args, 0); + break; + case OPS.setStrokeRGBColor: + stateManager.state.strokeColorSpace = ColorSpace.singletons.rgb; + args = ColorSpace.singletons.rgb.getRgb(args, 0); + break; + case OPS.setFillColorN: + cs = stateManager.state.fillColorSpace; + if (cs.name === 'Pattern') { + return self.handleColorN(operatorList, OPS.setFillColorN, + args, cs, patterns, resources, xref).then(function() { + next(resolve, reject); + }, reject); + } + args = cs.getRgb(args, 0); + fn = OPS.setFillRGBColor; + break; + case OPS.setStrokeColorN: + cs = stateManager.state.strokeColorSpace; + if (cs.name === 'Pattern') { + return self.handleColorN(operatorList, OPS.setStrokeColorN, + args, cs, patterns, resources, xref).then(function() { + next(resolve, reject); + }, reject); + } + args = cs.getRgb(args, 0); + fn = OPS.setStrokeRGBColor; + break; + + case OPS.shadingFill: + var shadingRes = resources.get('Shading'); + if (!shadingRes) { + error('No shading resource found'); + } + + var shading = shadingRes.get(args[0].name); + if (!shading) { + error('No shading object found'); + } + + var shadingFill = Pattern.parseShading(shading, null, xref, + resources); + var patternIR = shadingFill.getIR(); + args = [patternIR]; + fn = OPS.shadingFill; + break; + case OPS.setGState: + var dictName = args[0]; + var extGState = resources.get('ExtGState'); + + if (!isDict(extGState) || !extGState.has(dictName.name)) { + break; + } + + var gState = extGState.get(dictName.name); + return self.setGState(resources, gState, operatorList, xref, + stateManager).then(function() { + next(resolve, reject); + }, reject); + case OPS.moveTo: + case OPS.lineTo: + case OPS.curveTo: + case OPS.curveTo2: + case OPS.curveTo3: + case OPS.closePath: + self.buildPath(operatorList, fn, args); + continue; + case OPS.rectangle: + self.buildPath(operatorList, fn, args); + continue; + } + operatorList.addOp(fn, args); + } + if (stop) { + deferred.then(function () { + next(resolve, reject); + }); + return; + } + // Some PDFs don't close all restores inside object/form. + // Closing those for them. + for (i = 0, ii = preprocessor.savedStatesDepth; i < ii; i++) { + operatorList.addOp(OPS.restore, []); + } + resolve(); + }); + }, + + getTextContent: function PartialEvaluator_getTextContent(stream, resources, + stateManager) { + + stateManager = (stateManager || new StateManager(new TextState())); + + var textContent = { + items: [], + styles: Object.create(null) + }; + var bidiTexts = textContent.items; + var SPACE_FACTOR = 0.3; + var MULTI_SPACE_FACTOR = 1.5; + + var self = this; + var xref = this.xref; + + resources = (xref.fetchIfRef(resources) || Dict.empty); + + // The xobj is parsed iff it's needed, e.g. if there is a `DO` cmd. + var xobjs = null; + var xobjsCache = {}; + + var preprocessor = new EvaluatorPreprocessor(stream, xref, stateManager); + + var textState; + + function newTextChunk() { + var font = textState.font; + if (!(font.loadedName in textContent.styles)) { + textContent.styles[font.loadedName] = { + fontFamily: font.fallbackName, + ascent: font.ascent, + descent: font.descent, + vertical: font.vertical + }; + } + return { + // |str| is initially an array which we push individual chars to, and + // then runBidi() overwrites it with the final string. + str: [], + dir: null, + width: 0, + height: 0, + transform: null, + fontName: font.loadedName + }; + } + + function runBidi(textChunk) { + var str = textChunk.str.join(''); + var bidiResult = PDFJS.bidi(str, -1, textState.font.vertical); + textChunk.str = bidiResult.str; + textChunk.dir = bidiResult.dir; + return textChunk; + } + + function handleSetFont(fontName, fontRef) { + return self.loadFont(fontName, fontRef, xref, resources). + then(function (translated) { + textState.font = translated.font; + textState.fontMatrix = translated.font.fontMatrix || + FONT_IDENTITY_MATRIX; + }); + } + + function buildTextGeometry(chars, textChunk) { + var font = textState.font; + textChunk = textChunk || newTextChunk(); + if (!textChunk.transform) { + // 9.4.4 Text Space Details + var tsm = [textState.fontSize * textState.textHScale, 0, + 0, textState.fontSize, + 0, textState.textRise]; + var trm = textChunk.transform = Util.transform(textState.ctm, + Util.transform(textState.textMatrix, tsm)); + if (!font.vertical) { + textChunk.height = Math.sqrt(trm[2] * trm[2] + trm[3] * trm[3]); + } else { + textChunk.width = Math.sqrt(trm[0] * trm[0] + trm[1] * trm[1]); + } + } + var width = 0; + var height = 0; + var glyphs = font.charsToGlyphs(chars); + var defaultVMetrics = font.defaultVMetrics; + for (var i = 0; i < glyphs.length; i++) { + var glyph = glyphs[i]; + if (!glyph) { // Previous glyph was a space. + width += textState.wordSpacing * textState.textHScale; + continue; + } + var vMetricX = null; + var vMetricY = null; + var glyphWidth = null; + if (font.vertical) { + if (glyph.vmetric) { + glyphWidth = glyph.vmetric[0]; + vMetricX = glyph.vmetric[1]; + vMetricY = glyph.vmetric[2]; + } else { + glyphWidth = glyph.width; + vMetricX = glyph.width * 0.5; + vMetricY = defaultVMetrics[2]; + } + } else { + glyphWidth = glyph.width; + } + + var glyphUnicode = glyph.unicode; + if (NormalizedUnicodes[glyphUnicode] !== undefined) { + glyphUnicode = NormalizedUnicodes[glyphUnicode]; + } + glyphUnicode = reverseIfRtl(glyphUnicode); + + // The following will calculate the x and y of the individual glyphs. + // if (font.vertical) { + // tsm[4] -= vMetricX * Math.abs(textState.fontSize) * + // textState.fontMatrix[0]; + // tsm[5] -= vMetricY * textState.fontSize * + // textState.fontMatrix[0]; + // } + // var trm = Util.transform(textState.textMatrix, tsm); + // var pt = Util.applyTransform([trm[4], trm[5]], textState.ctm); + // var x = pt[0]; + // var y = pt[1]; + + var tx = 0; + var ty = 0; + if (!font.vertical) { + var w0 = glyphWidth * textState.fontMatrix[0]; + tx = (w0 * textState.fontSize + textState.charSpacing) * + textState.textHScale; + width += tx; + } else { + var w1 = glyphWidth * textState.fontMatrix[0]; + ty = w1 * textState.fontSize + textState.charSpacing; + height += ty; + } + textState.translateTextMatrix(tx, ty); + + textChunk.str.push(glyphUnicode); + } + + var a = textState.textLineMatrix[0]; + var b = textState.textLineMatrix[1]; + var scaleLineX = Math.sqrt(a * a + b * b); + a = textState.ctm[0]; + b = textState.ctm[1]; + var scaleCtmX = Math.sqrt(a * a + b * b); + if (!font.vertical) { + textChunk.width += width * scaleCtmX * scaleLineX; + } else { + textChunk.height += Math.abs(height * scaleCtmX * scaleLineX); + } + return textChunk; + } + + var timeSlotManager = new TimeSlotManager(); + + return new Promise(function next(resolve, reject) { + timeSlotManager.reset(); + var stop, operation = {}, args = []; + while (!(stop = timeSlotManager.check())) { + // The arguments parsed by read() are not used beyond this loop, so + // we can reuse the same array on every iteration, thus avoiding + // unnecessary allocations. + args.length = 0; + operation.args = args; + if (!(preprocessor.read(operation))) { + break; + } + textState = stateManager.state; + var fn = operation.fn; + args = operation.args; + + switch (fn | 0) { + case OPS.setFont: + textState.fontSize = args[1]; + return handleSetFont(args[0].name).then(function() { + next(resolve, reject); + }, reject); + case OPS.setTextRise: + textState.textRise = args[0]; + break; + case OPS.setHScale: + textState.textHScale = args[0] / 100; + break; + case OPS.setLeading: + textState.leading = args[0]; + break; + case OPS.moveText: + textState.translateTextLineMatrix(args[0], args[1]); + textState.textMatrix = textState.textLineMatrix.slice(); + break; + case OPS.setLeadingMoveText: + textState.leading = -args[1]; + textState.translateTextLineMatrix(args[0], args[1]); + textState.textMatrix = textState.textLineMatrix.slice(); + break; + case OPS.nextLine: + textState.carriageReturn(); + break; + case OPS.setTextMatrix: + textState.setTextMatrix(args[0], args[1], args[2], args[3], + args[4], args[5]); + textState.setTextLineMatrix(args[0], args[1], args[2], args[3], + args[4], args[5]); + break; + case OPS.setCharSpacing: + textState.charSpacing = args[0]; + break; + case OPS.setWordSpacing: + textState.wordSpacing = args[0]; + break; + case OPS.beginText: + textState.textMatrix = IDENTITY_MATRIX.slice(); + textState.textLineMatrix = IDENTITY_MATRIX.slice(); + break; + case OPS.showSpacedText: + var items = args[0]; + var textChunk = newTextChunk(); + var offset; + for (var j = 0, jj = items.length; j < jj; j++) { + if (typeof items[j] === 'string') { + buildTextGeometry(items[j], textChunk); + } else { + var val = items[j] / 1000; + if (!textState.font.vertical) { + offset = -val * textState.fontSize * textState.textHScale * + textState.textMatrix[0]; + textState.translateTextMatrix(offset, 0); + textChunk.width += offset; + } else { + offset = -val * textState.fontSize * + textState.textMatrix[3]; + textState.translateTextMatrix(0, offset); + textChunk.height += offset; + } + if (items[j] < 0 && textState.font.spaceWidth > 0) { + var fakeSpaces = -items[j] / textState.font.spaceWidth; + if (fakeSpaces > MULTI_SPACE_FACTOR) { + fakeSpaces = Math.round(fakeSpaces); + while (fakeSpaces--) { + textChunk.str.push(' '); + } + } else if (fakeSpaces > SPACE_FACTOR) { + textChunk.str.push(' '); + } + } + } + } + bidiTexts.push(runBidi(textChunk)); + break; + case OPS.showText: + bidiTexts.push(runBidi(buildTextGeometry(args[0]))); + break; + case OPS.nextLineShowText: + textState.carriageReturn(); + bidiTexts.push(runBidi(buildTextGeometry(args[0]))); + break; + case OPS.nextLineSetSpacingShowText: + textState.wordSpacing = args[0]; + textState.charSpacing = args[1]; + textState.carriageReturn(); + bidiTexts.push(runBidi(buildTextGeometry(args[2]))); + break; + case OPS.paintXObject: + if (args[0].code) { + break; + } + + if (!xobjs) { + xobjs = (resources.get('XObject') || Dict.empty); + } + + var name = args[0].name; + if (xobjsCache.key === name) { + if (xobjsCache.texts) { + Util.appendToArray(bidiTexts, xobjsCache.texts.items); + Util.extendObj(textContent.styles, xobjsCache.texts.styles); + } + break; + } + + var xobj = xobjs.get(name); + if (!xobj) { + break; + } + assert(isStream(xobj), 'XObject should be a stream'); + + var type = xobj.dict.get('Subtype'); + assert(isName(type), + 'XObject should have a Name subtype'); + + if ('Form' !== type.name) { + xobjsCache.key = name; + xobjsCache.texts = null; + break; + } + + stateManager.save(); + var matrix = xobj.dict.get('Matrix'); + if (isArray(matrix) && matrix.length === 6) { + stateManager.transform(matrix); + } + + return self.getTextContent(xobj, + xobj.dict.get('Resources') || resources, stateManager). + then(function (formTextContent) { + Util.appendToArray(bidiTexts, formTextContent.items); + Util.extendObj(textContent.styles, formTextContent.styles); + stateManager.restore(); + + xobjsCache.key = name; + xobjsCache.texts = formTextContent; + + next(resolve, reject); + }, reject); + case OPS.setGState: + var dictName = args[0]; + var extGState = resources.get('ExtGState'); + + if (!isDict(extGState) || !extGState.has(dictName.name)) { + break; + } + + var gsStateMap = extGState.get(dictName.name); + var gsStateFont = null; + for (var key in gsStateMap) { + if (key === 'Font') { + assert(!gsStateFont); + gsStateFont = gsStateMap[key]; + } + } + if (gsStateFont) { + textState.fontSize = gsStateFont[1]; + return handleSetFont(gsStateFont[0]).then(function() { + next(resolve, reject); + }, reject); + } + break; + } // switch + } // while + if (stop) { + deferred.then(function () { + next(resolve, reject); + }); + return; + } + resolve(textContent); + }); + }, + + extractDataStructures: function + partialEvaluatorExtractDataStructures(dict, baseDict, + xref, properties) { + // 9.10.2 + var toUnicode = (dict.get('ToUnicode') || baseDict.get('ToUnicode')); + if (toUnicode) { + properties.toUnicode = this.readToUnicode(toUnicode); + } + if (properties.composite) { + // CIDSystemInfo helps to match CID to glyphs + var cidSystemInfo = dict.get('CIDSystemInfo'); + if (isDict(cidSystemInfo)) { + properties.cidSystemInfo = { + registry: cidSystemInfo.get('Registry'), + ordering: cidSystemInfo.get('Ordering'), + supplement: cidSystemInfo.get('Supplement') + }; + } + + var cidToGidMap = dict.get('CIDToGIDMap'); + if (isStream(cidToGidMap)) { + properties.cidToGidMap = this.readCidToGidMap(cidToGidMap); + } + } + + // Based on 9.6.6 of the spec the encoding can come from multiple places + // and depends on the font type. The base encoding and differences are + // read here, but the encoding that is actually used is chosen during + // glyph mapping in the font. + // TODO: Loading the built in encoding in the font would allow the + // differences to be merged in here not require us to hold on to it. + var differences = []; + var baseEncodingName = null; + var encoding; + if (dict.has('Encoding')) { + encoding = dict.get('Encoding'); + if (isDict(encoding)) { + baseEncodingName = encoding.get('BaseEncoding'); + baseEncodingName = (isName(baseEncodingName) ? + baseEncodingName.name : null); + // Load the differences between the base and original + if (encoding.has('Differences')) { + var diffEncoding = encoding.get('Differences'); + var index = 0; + for (var j = 0, jj = diffEncoding.length; j < jj; j++) { + var data = diffEncoding[j]; + if (isNum(data)) { + index = data; + } else { + differences[index++] = data.name; + } + } + } + } else if (isName(encoding)) { + baseEncodingName = encoding.name; + } else { + error('Encoding is not a Name nor a Dict'); + } + // According to table 114 if the encoding is a named encoding it must be + // one of these predefined encodings. + if ((baseEncodingName !== 'MacRomanEncoding' && + baseEncodingName !== 'MacExpertEncoding' && + baseEncodingName !== 'WinAnsiEncoding')) { + baseEncodingName = null; + } + } + + if (baseEncodingName) { + properties.defaultEncoding = Encodings[baseEncodingName].slice(); + } else { + encoding = (properties.type === 'TrueType' ? + Encodings.WinAnsiEncoding : Encodings.StandardEncoding); + // The Symbolic attribute can be misused for regular fonts + // Heuristic: we have to check if the font is a standard one also + if (!!(properties.flags & FontFlags.Symbolic)) { + encoding = Encodings.MacRomanEncoding; + if (!properties.file) { + if (/Symbol/i.test(properties.name)) { + encoding = Encodings.SymbolSetEncoding; + } else if (/Dingbats/i.test(properties.name)) { + encoding = Encodings.ZapfDingbatsEncoding; + } + } + } + properties.defaultEncoding = encoding; + } + + properties.differences = differences; + properties.baseEncodingName = baseEncodingName; + properties.dict = dict; + }, + + readToUnicode: function PartialEvaluator_readToUnicode(toUnicode) { + var cmap, cmapObj = toUnicode; + if (isName(cmapObj)) { + cmap = CMapFactory.create(cmapObj, + { url: PDFJS.cMapUrl, packed: PDFJS.cMapPacked }, null); + if (cmap instanceof IdentityCMap) { + return new IdentityToUnicodeMap(0, 0xFFFF); + } + return new ToUnicodeMap(cmap.getMap()); + } else if (isStream(cmapObj)) { + cmap = CMapFactory.create(cmapObj, + { url: PDFJS.cMapUrl, packed: PDFJS.cMapPacked }, null); + if (cmap instanceof IdentityCMap) { + return new IdentityToUnicodeMap(0, 0xFFFF); + } + cmap = cmap.getMap(); + // Convert UTF-16BE + // NOTE: cmap can be a sparse array, so use forEach instead of for(;;) + // to iterate over all keys. + cmap.forEach(function(token, i) { + var str = []; + for (var k = 0; k < token.length; k += 2) { + var w1 = (token.charCodeAt(k) << 8) | token.charCodeAt(k + 1); + if ((w1 & 0xF800) !== 0xD800) { // w1 < 0xD800 || w1 > 0xDFFF + str.push(w1); + continue; + } + k += 2; + var w2 = (token.charCodeAt(k) << 8) | token.charCodeAt(k + 1); + str.push(((w1 & 0x3ff) << 10) + (w2 & 0x3ff) + 0x10000); + } + cmap[i] = String.fromCharCode.apply(String, str); + }); + return new ToUnicodeMap(cmap); + } + return null; + }, + + readCidToGidMap: function PartialEvaluator_readCidToGidMap(cidToGidStream) { + // Extract the encoding from the CIDToGIDMap + var glyphsData = cidToGidStream.getBytes(); + + // Set encoding 0 to later verify the font has an encoding + var result = []; + for (var j = 0, jj = glyphsData.length; j < jj; j++) { + var glyphID = (glyphsData[j++] << 8) | glyphsData[j]; + if (glyphID === 0) { + continue; + } + var code = j >> 1; + result[code] = glyphID; + } + return result; + }, + + extractWidths: function PartialEvaluator_extractWidths(dict, xref, + descriptor, + properties) { + var glyphsWidths = []; + var defaultWidth = 0; + var glyphsVMetrics = []; + var defaultVMetrics; + var i, ii, j, jj, start, code, widths; + if (properties.composite) { + defaultWidth = dict.get('DW') || 1000; + + widths = dict.get('W'); + if (widths) { + for (i = 0, ii = widths.length; i < ii; i++) { + start = widths[i++]; + code = xref.fetchIfRef(widths[i]); + if (isArray(code)) { + for (j = 0, jj = code.length; j < jj; j++) { + glyphsWidths[start++] = code[j]; + } + } else { + var width = widths[++i]; + for (j = start; j <= code; j++) { + glyphsWidths[j] = width; + } + } + } + } + + if (properties.vertical) { + var vmetrics = (dict.get('DW2') || [880, -1000]); + defaultVMetrics = [vmetrics[1], defaultWidth * 0.5, vmetrics[0]]; + vmetrics = dict.get('W2'); + if (vmetrics) { + for (i = 0, ii = vmetrics.length; i < ii; i++) { + start = vmetrics[i++]; + code = xref.fetchIfRef(vmetrics[i]); + if (isArray(code)) { + for (j = 0, jj = code.length; j < jj; j++) { + glyphsVMetrics[start++] = [code[j++], code[j++], code[j]]; + } + } else { + var vmetric = [vmetrics[++i], vmetrics[++i], vmetrics[++i]]; + for (j = start; j <= code; j++) { + glyphsVMetrics[j] = vmetric; + } + } + } + } + } + } else { + var firstChar = properties.firstChar; + widths = dict.get('Widths'); + if (widths) { + j = firstChar; + for (i = 0, ii = widths.length; i < ii; i++) { + glyphsWidths[j++] = widths[i]; + } + defaultWidth = (parseFloat(descriptor.get('MissingWidth')) || 0); + } else { + // Trying get the BaseFont metrics (see comment above). + var baseFontName = dict.get('BaseFont'); + if (isName(baseFontName)) { + var metrics = this.getBaseFontMetrics(baseFontName.name); + + glyphsWidths = this.buildCharCodeToWidth(metrics.widths, + properties); + defaultWidth = metrics.defaultWidth; + } + } + } + + // Heuristic: detection of monospace font by checking all non-zero widths + var isMonospace = true; + var firstWidth = defaultWidth; + for (var glyph in glyphsWidths) { + var glyphWidth = glyphsWidths[glyph]; + if (!glyphWidth) { + continue; + } + if (!firstWidth) { + firstWidth = glyphWidth; + continue; + } + if (firstWidth !== glyphWidth) { + isMonospace = false; + break; + } + } + if (isMonospace) { + properties.flags |= FontFlags.FixedPitch; + } + + properties.defaultWidth = defaultWidth; + properties.widths = glyphsWidths; + properties.defaultVMetrics = defaultVMetrics; + properties.vmetrics = glyphsVMetrics; + }, + + isSerifFont: function PartialEvaluator_isSerifFont(baseFontName) { + // Simulating descriptor flags attribute + var fontNameWoStyle = baseFontName.split('-')[0]; + return (fontNameWoStyle in serifFonts) || + (fontNameWoStyle.search(/serif/gi) !== -1); + }, + + getBaseFontMetrics: function PartialEvaluator_getBaseFontMetrics(name) { + var defaultWidth = 0; + var widths = []; + var monospace = false; + var lookupName = (stdFontMap[name] || name); + + if (!(lookupName in Metrics)) { + // Use default fonts for looking up font metrics if the passed + // font is not a base font + if (this.isSerifFont(name)) { + lookupName = 'Times-Roman'; + } else { + lookupName = 'Helvetica'; + } + } + var glyphWidths = Metrics[lookupName]; + + if (isNum(glyphWidths)) { + defaultWidth = glyphWidths; + monospace = true; + } else { + widths = glyphWidths; + } + + return { + defaultWidth: defaultWidth, + monospace: monospace, + widths: widths + }; + }, + + buildCharCodeToWidth: + function PartialEvaluator_bulildCharCodeToWidth(widthsByGlyphName, + properties) { + var widths = Object.create(null); + var differences = properties.differences; + var encoding = properties.defaultEncoding; + for (var charCode = 0; charCode < 256; charCode++) { + if (charCode in differences && + widthsByGlyphName[differences[charCode]]) { + widths[charCode] = widthsByGlyphName[differences[charCode]]; + continue; + } + if (charCode in encoding && widthsByGlyphName[encoding[charCode]]) { + widths[charCode] = widthsByGlyphName[encoding[charCode]]; + continue; + } + } + return widths; + }, + + preEvaluateFont: function PartialEvaluator_preEvaluateFont(dict, xref) { + var baseDict = dict; + var type = dict.get('Subtype'); + assert(isName(type), 'invalid font Subtype'); + + var composite = false; + var uint8array; + if (type.name === 'Type0') { + // If font is a composite + // - get the descendant font + // - set the type according to the descendant font + // - get the FontDescriptor from the descendant font + var df = dict.get('DescendantFonts'); + if (!df) { + error('Descendant fonts are not specified'); + } + dict = (isArray(df) ? xref.fetchIfRef(df[0]) : df); + + type = dict.get('Subtype'); + assert(isName(type), 'invalid font Subtype'); + composite = true; + } + + var descriptor = dict.get('FontDescriptor'); + if (descriptor) { + var hash = new MurmurHash3_64(); + var encoding = baseDict.getRaw('Encoding'); + if (isName(encoding)) { + hash.update(encoding.name); + } else if (isRef(encoding)) { + hash.update(encoding.num + '_' + encoding.gen); + } else if (isDict(encoding)) { + var keys = encoding.getKeys(); + for (var i = 0, ii = keys.length; i < ii; i++) { + var entry = encoding.getRaw(keys[i]); + if (isName(entry)) { + hash.update(entry.name); + } else if (isRef(entry)) { + hash.update(entry.num + '_' + entry.gen); + } else if (isArray(entry)) { // 'Differences' entry. + // Ideally we should check the contents of the array, but to avoid + // parsing it here and then again in |extractDataStructures|, + // we only use the array length for now (fixes bug1157493.pdf). + hash.update(entry.length.toString()); + } + } + } + + var toUnicode = dict.get('ToUnicode') || baseDict.get('ToUnicode'); + if (isStream(toUnicode)) { + var stream = toUnicode.str || toUnicode; + uint8array = stream.buffer ? + new Uint8Array(stream.buffer.buffer, 0, stream.bufferLength) : + new Uint8Array(stream.bytes.buffer, + stream.start, stream.end - stream.start); + hash.update(uint8array); + + } else if (isName(toUnicode)) { + hash.update(toUnicode.name); + } + + var widths = dict.get('Widths') || baseDict.get('Widths'); + if (widths) { + uint8array = new Uint8Array(new Uint32Array(widths).buffer); + hash.update(uint8array); + } + } + + return { + descriptor: descriptor, + dict: dict, + baseDict: baseDict, + composite: composite, + type: type.name, + hash: hash ? hash.hexdigest() : '' + }; + }, + + translateFont: function PartialEvaluator_translateFont(preEvaluatedFont, + xref) { + var baseDict = preEvaluatedFont.baseDict; + var dict = preEvaluatedFont.dict; + var composite = preEvaluatedFont.composite; + var descriptor = preEvaluatedFont.descriptor; + var type = preEvaluatedFont.type; + var maxCharIndex = (composite ? 0xFFFF : 0xFF); + var properties; + + if (!descriptor) { + if (type === 'Type3') { + // FontDescriptor is only required for Type3 fonts when the document + // is a tagged pdf. Create a barbebones one to get by. + descriptor = new Dict(null); + descriptor.set('FontName', Name.get(type)); + } else { + // Before PDF 1.5 if the font was one of the base 14 fonts, having a + // FontDescriptor was not required. + // This case is here for compatibility. + var baseFontName = dict.get('BaseFont'); + if (!isName(baseFontName)) { + error('Base font is not specified'); + } + + // Using base font name as a font name. + baseFontName = baseFontName.name.replace(/[,_]/g, '-'); + var metrics = this.getBaseFontMetrics(baseFontName); + + // Simulating descriptor flags attribute + var fontNameWoStyle = baseFontName.split('-')[0]; + var flags = + (this.isSerifFont(fontNameWoStyle) ? FontFlags.Serif : 0) | + (metrics.monospace ? FontFlags.FixedPitch : 0) | + (symbolsFonts[fontNameWoStyle] ? FontFlags.Symbolic : + FontFlags.Nonsymbolic); + + properties = { + type: type, + name: baseFontName, + widths: metrics.widths, + defaultWidth: metrics.defaultWidth, + flags: flags, + firstChar: 0, + lastChar: maxCharIndex + }; + this.extractDataStructures(dict, dict, xref, properties); + properties.widths = this.buildCharCodeToWidth(metrics.widths, + properties); + return new Font(baseFontName, null, properties); + } + } + + // According to the spec if 'FontDescriptor' is declared, 'FirstChar', + // 'LastChar' and 'Widths' should exist too, but some PDF encoders seem + // to ignore this rule when a variant of a standart font is used. + // TODO Fill the width array depending on which of the base font this is + // a variant. + var firstChar = (dict.get('FirstChar') || 0); + var lastChar = (dict.get('LastChar') || maxCharIndex); + + var fontName = descriptor.get('FontName'); + var baseFont = dict.get('BaseFont'); + // Some bad PDFs have a string as the font name. + if (isString(fontName)) { + fontName = Name.get(fontName); + } + if (isString(baseFont)) { + baseFont = Name.get(baseFont); + } + + if (type !== 'Type3') { + var fontNameStr = fontName && fontName.name; + var baseFontStr = baseFont && baseFont.name; + if (fontNameStr !== baseFontStr) { + info('The FontDescriptor\'s FontName is "' + fontNameStr + + '" but should be the same as the Font\'s BaseFont "' + + baseFontStr + '"'); + // Workaround for cases where e.g. fontNameStr = 'Arial' and + // baseFontStr = 'Arial,Bold' (needed when no font file is embedded). + if (fontNameStr && baseFontStr && + baseFontStr.indexOf(fontNameStr) === 0) { + fontName = baseFont; + } + } + } + fontName = (fontName || baseFont); + + assert(isName(fontName), 'invalid font name'); + + var fontFile = descriptor.get('FontFile', 'FontFile2', 'FontFile3'); + if (fontFile) { + if (fontFile.dict) { + var subtype = fontFile.dict.get('Subtype'); + if (subtype) { + subtype = subtype.name; + } + var length1 = fontFile.dict.get('Length1'); + var length2 = fontFile.dict.get('Length2'); + } + } + + properties = { + type: type, + name: fontName.name, + subtype: subtype, + file: fontFile, + length1: length1, + length2: length2, + loadedName: baseDict.loadedName, + composite: composite, + wideChars: composite, + fixedPitch: false, + fontMatrix: (dict.get('FontMatrix') || FONT_IDENTITY_MATRIX), + firstChar: firstChar || 0, + lastChar: (lastChar || maxCharIndex), + bbox: descriptor.get('FontBBox'), + ascent: descriptor.get('Ascent'), + descent: descriptor.get('Descent'), + xHeight: descriptor.get('XHeight'), + capHeight: descriptor.get('CapHeight'), + flags: descriptor.get('Flags'), + italicAngle: descriptor.get('ItalicAngle'), + coded: false + }; + + if (composite) { + var cidEncoding = baseDict.get('Encoding'); + if (isName(cidEncoding)) { + properties.cidEncoding = cidEncoding.name; + } + properties.cMap = CMapFactory.create(cidEncoding, + { url: PDFJS.cMapUrl, packed: PDFJS.cMapPacked }, null); + properties.vertical = properties.cMap.vertical; + } + this.extractDataStructures(dict, baseDict, xref, properties); + this.extractWidths(dict, xref, descriptor, properties); + + if (type === 'Type3') { + properties.isType3Font = true; + } + + return new Font(fontName.name, fontFile, properties); + } + }; + + return PartialEvaluator; +})(); + +var TranslatedFont = (function TranslatedFontClosure() { + function TranslatedFont(loadedName, font, dict) { + this.loadedName = loadedName; + this.font = font; + this.dict = dict; + this.type3Loaded = null; + this.sent = false; + } + TranslatedFont.prototype = { + send: function (handler) { + if (this.sent) { + return; + } + var fontData = this.font.exportData(); + handler.send('commonobj', [ + this.loadedName, + 'Font', + fontData + ]); + this.sent = true; + }, + loadType3Data: function (evaluator, resources, parentOperatorList) { + assert(this.font.isType3Font); + + if (this.type3Loaded) { + return this.type3Loaded; + } + + var translatedFont = this.font; + var loadCharProcsPromise = Promise.resolve(); + var charProcs = this.dict.get('CharProcs').getAll(); + var fontResources = this.dict.get('Resources') || resources; + var charProcKeys = Object.keys(charProcs); + var charProcOperatorList = {}; + for (var i = 0, n = charProcKeys.length; i < n; ++i) { + loadCharProcsPromise = loadCharProcsPromise.then(function (key) { + var glyphStream = charProcs[key]; + var operatorList = new OperatorList(); + return evaluator.getOperatorList(glyphStream, fontResources, + operatorList).then(function () { + charProcOperatorList[key] = operatorList.getIR(); + + // Add the dependencies to the parent operator list so they are + // resolved before sub operator list is executed synchronously. + parentOperatorList.addDependencies(operatorList.dependencies); + }, function (reason) { + warn('Type3 font resource \"' + key + '\" is not available'); + var operatorList = new OperatorList(); + charProcOperatorList[key] = operatorList.getIR(); + }); + }.bind(this, charProcKeys[i])); + } + this.type3Loaded = loadCharProcsPromise.then(function () { + translatedFont.charProcOperatorList = charProcOperatorList; + }); + return this.type3Loaded; + } + }; + return TranslatedFont; +})(); + +var OperatorList = (function OperatorListClosure() { + var CHUNK_SIZE = 1000; + var CHUNK_SIZE_ABOUT = CHUNK_SIZE - 5; // close to chunk size + + function getTransfers(queue) { + var transfers = []; + var fnArray = queue.fnArray, argsArray = queue.argsArray; + for (var i = 0, ii = queue.length; i < ii; i++) { + switch (fnArray[i]) { + case OPS.paintInlineImageXObject: + case OPS.paintInlineImageXObjectGroup: + case OPS.paintImageMaskXObject: + var arg = argsArray[i][0]; // first param in imgData + if (!arg.cached) { + transfers.push(arg.data.buffer); + } + break; + } + } + return transfers; + } + + function OperatorList(intent, messageHandler, pageIndex) { + this.messageHandler = messageHandler; + this.fnArray = []; + this.argsArray = []; + this.dependencies = {}; + this.pageIndex = pageIndex; + this.intent = intent; + } + + OperatorList.prototype = { + get length() { + return this.argsArray.length; + }, + + addOp: function(fn, args) { + this.fnArray.push(fn); + this.argsArray.push(args); + if (this.messageHandler) { + if (this.fnArray.length >= CHUNK_SIZE) { + this.flush(); + } else if (this.fnArray.length >= CHUNK_SIZE_ABOUT && + (fn === OPS.restore || fn === OPS.endText)) { + // heuristic to flush on boundary of restore or endText + this.flush(); + } + } + }, + + addDependency: function(dependency) { + if (dependency in this.dependencies) { + return; + } + this.dependencies[dependency] = true; + this.addOp(OPS.dependency, [dependency]); + }, + + addDependencies: function(dependencies) { + for (var key in dependencies) { + this.addDependency(key); + } + }, + + addOpList: function(opList) { + Util.extendObj(this.dependencies, opList.dependencies); + for (var i = 0, ii = opList.length; i < ii; i++) { + this.addOp(opList.fnArray[i], opList.argsArray[i]); + } + }, + + getIR: function() { + return { + fnArray: this.fnArray, + argsArray: this.argsArray, + length: this.length + }; + }, + + flush: function(lastChunk) { + if (this.intent !== 'oplist') { + new QueueOptimizer().optimize(this); + } + var transfers = getTransfers(this); + this.messageHandler.send('RenderPageChunk', { + operatorList: { + fnArray: this.fnArray, + argsArray: this.argsArray, + lastChunk: lastChunk, + length: this.length + }, + pageIndex: this.pageIndex, + intent: this.intent + }, transfers); + this.dependencies = {}; + this.fnArray.length = 0; + this.argsArray.length = 0; + } + }; + + return OperatorList; +})(); + +var StateManager = (function StateManagerClosure() { + function StateManager(initialState) { + this.state = initialState; + this.stateStack = []; + } + StateManager.prototype = { + save: function () { + var old = this.state; + this.stateStack.push(this.state); + this.state = old.clone(); + }, + restore: function () { + var prev = this.stateStack.pop(); + if (prev) { + this.state = prev; + } + }, + transform: function (args) { + this.state.ctm = Util.transform(this.state.ctm, args); + } + }; + return StateManager; +})(); + +var TextState = (function TextStateClosure() { + function TextState() { + this.ctm = new Float32Array(IDENTITY_MATRIX); + this.fontSize = 0; + this.font = null; + this.fontMatrix = FONT_IDENTITY_MATRIX; + this.textMatrix = IDENTITY_MATRIX.slice(); + this.textLineMatrix = IDENTITY_MATRIX.slice(); + this.charSpacing = 0; + this.wordSpacing = 0; + this.leading = 0; + this.textHScale = 1; + this.textRise = 0; + } + + TextState.prototype = { + setTextMatrix: function TextState_setTextMatrix(a, b, c, d, e, f) { + var m = this.textMatrix; + m[0] = a; m[1] = b; m[2] = c; m[3] = d; m[4] = e; m[5] = f; + }, + setTextLineMatrix: function TextState_setTextMatrix(a, b, c, d, e, f) { + var m = this.textLineMatrix; + m[0] = a; m[1] = b; m[2] = c; m[3] = d; m[4] = e; m[5] = f; + }, + translateTextMatrix: function TextState_translateTextMatrix(x, y) { + var m = this.textMatrix; + m[4] = m[0] * x + m[2] * y + m[4]; + m[5] = m[1] * x + m[3] * y + m[5]; + }, + translateTextLineMatrix: function TextState_translateTextMatrix(x, y) { + var m = this.textLineMatrix; + m[4] = m[0] * x + m[2] * y + m[4]; + m[5] = m[1] * x + m[3] * y + m[5]; + }, + calcRenderMatrix: function TextState_calcRendeMatrix(ctm) { + // 9.4.4 Text Space Details + var tsm = [this.fontSize * this.textHScale, 0, + 0, this.fontSize, + 0, this.textRise]; + return Util.transform(ctm, Util.transform(this.textMatrix, tsm)); + }, + carriageReturn: function TextState_carriageReturn() { + this.translateTextLineMatrix(0, -this.leading); + this.textMatrix = this.textLineMatrix.slice(); + }, + clone: function TextState_clone() { + var clone = Object.create(this); + clone.textMatrix = this.textMatrix.slice(); + clone.textLineMatrix = this.textLineMatrix.slice(); + clone.fontMatrix = this.fontMatrix.slice(); + return clone; + } + }; + return TextState; +})(); + +var EvalState = (function EvalStateClosure() { + function EvalState() { + this.ctm = new Float32Array(IDENTITY_MATRIX); + this.font = null; + this.textRenderingMode = TextRenderingMode.FILL; + this.fillColorSpace = ColorSpace.singletons.gray; + this.strokeColorSpace = ColorSpace.singletons.gray; + } + EvalState.prototype = { + clone: function CanvasExtraState_clone() { + return Object.create(this); + }, + }; + return EvalState; +})(); + +var EvaluatorPreprocessor = (function EvaluatorPreprocessorClosure() { + // Specifies properties for each command + // + // If variableArgs === true: [0, `numArgs`] expected + // If variableArgs === false: exactly `numArgs` expected + var OP_MAP = { + // Graphic state + w: { id: OPS.setLineWidth, numArgs: 1, variableArgs: false }, + J: { id: OPS.setLineCap, numArgs: 1, variableArgs: false }, + j: { id: OPS.setLineJoin, numArgs: 1, variableArgs: false }, + M: { id: OPS.setMiterLimit, numArgs: 1, variableArgs: false }, + d: { id: OPS.setDash, numArgs: 2, variableArgs: false }, + ri: { id: OPS.setRenderingIntent, numArgs: 1, variableArgs: false }, + i: { id: OPS.setFlatness, numArgs: 1, variableArgs: false }, + gs: { id: OPS.setGState, numArgs: 1, variableArgs: false }, + q: { id: OPS.save, numArgs: 0, variableArgs: false }, + Q: { id: OPS.restore, numArgs: 0, variableArgs: false }, + cm: { id: OPS.transform, numArgs: 6, variableArgs: false }, + + // Path + m: { id: OPS.moveTo, numArgs: 2, variableArgs: false }, + l: { id: OPS.lineTo, numArgs: 2, variableArgs: false }, + c: { id: OPS.curveTo, numArgs: 6, variableArgs: false }, + v: { id: OPS.curveTo2, numArgs: 4, variableArgs: false }, + y: { id: OPS.curveTo3, numArgs: 4, variableArgs: false }, + h: { id: OPS.closePath, numArgs: 0, variableArgs: false }, + re: { id: OPS.rectangle, numArgs: 4, variableArgs: false }, + S: { id: OPS.stroke, numArgs: 0, variableArgs: false }, + s: { id: OPS.closeStroke, numArgs: 0, variableArgs: false }, + f: { id: OPS.fill, numArgs: 0, variableArgs: false }, + F: { id: OPS.fill, numArgs: 0, variableArgs: false }, + 'f*': { id: OPS.eoFill, numArgs: 0, variableArgs: false }, + B: { id: OPS.fillStroke, numArgs: 0, variableArgs: false }, + 'B*': { id: OPS.eoFillStroke, numArgs: 0, variableArgs: false }, + b: { id: OPS.closeFillStroke, numArgs: 0, variableArgs: false }, + 'b*': { id: OPS.closeEOFillStroke, numArgs: 0, variableArgs: false }, + n: { id: OPS.endPath, numArgs: 0, variableArgs: false }, + + // Clipping + W: { id: OPS.clip, numArgs: 0, variableArgs: false }, + 'W*': { id: OPS.eoClip, numArgs: 0, variableArgs: false }, + + // Text + BT: { id: OPS.beginText, numArgs: 0, variableArgs: false }, + ET: { id: OPS.endText, numArgs: 0, variableArgs: false }, + Tc: { id: OPS.setCharSpacing, numArgs: 1, variableArgs: false }, + Tw: { id: OPS.setWordSpacing, numArgs: 1, variableArgs: false }, + Tz: { id: OPS.setHScale, numArgs: 1, variableArgs: false }, + TL: { id: OPS.setLeading, numArgs: 1, variableArgs: false }, + Tf: { id: OPS.setFont, numArgs: 2, variableArgs: false }, + Tr: { id: OPS.setTextRenderingMode, numArgs: 1, variableArgs: false }, + Ts: { id: OPS.setTextRise, numArgs: 1, variableArgs: false }, + Td: { id: OPS.moveText, numArgs: 2, variableArgs: false }, + TD: { id: OPS.setLeadingMoveText, numArgs: 2, variableArgs: false }, + Tm: { id: OPS.setTextMatrix, numArgs: 6, variableArgs: false }, + 'T*': { id: OPS.nextLine, numArgs: 0, variableArgs: false }, + Tj: { id: OPS.showText, numArgs: 1, variableArgs: false }, + TJ: { id: OPS.showSpacedText, numArgs: 1, variableArgs: false }, + '\'': { id: OPS.nextLineShowText, numArgs: 1, variableArgs: false }, + '"': { id: OPS.nextLineSetSpacingShowText, numArgs: 3, + variableArgs: false }, + + // Type3 fonts + d0: { id: OPS.setCharWidth, numArgs: 2, variableArgs: false }, + d1: { id: OPS.setCharWidthAndBounds, numArgs: 6, variableArgs: false }, + + // Color + CS: { id: OPS.setStrokeColorSpace, numArgs: 1, variableArgs: false }, + cs: { id: OPS.setFillColorSpace, numArgs: 1, variableArgs: false }, + SC: { id: OPS.setStrokeColor, numArgs: 4, variableArgs: true }, + SCN: { id: OPS.setStrokeColorN, numArgs: 33, variableArgs: true }, + sc: { id: OPS.setFillColor, numArgs: 4, variableArgs: true }, + scn: { id: OPS.setFillColorN, numArgs: 33, variableArgs: true }, + G: { id: OPS.setStrokeGray, numArgs: 1, variableArgs: false }, + g: { id: OPS.setFillGray, numArgs: 1, variableArgs: false }, + RG: { id: OPS.setStrokeRGBColor, numArgs: 3, variableArgs: false }, + rg: { id: OPS.setFillRGBColor, numArgs: 3, variableArgs: false }, + K: { id: OPS.setStrokeCMYKColor, numArgs: 4, variableArgs: false }, + k: { id: OPS.setFillCMYKColor, numArgs: 4, variableArgs: false }, + + // Shading + sh: { id: OPS.shadingFill, numArgs: 1, variableArgs: false }, + + // Images + BI: { id: OPS.beginInlineImage, numArgs: 0, variableArgs: false }, + ID: { id: OPS.beginImageData, numArgs: 0, variableArgs: false }, + EI: { id: OPS.endInlineImage, numArgs: 1, variableArgs: false }, + + // XObjects + Do: { id: OPS.paintXObject, numArgs: 1, variableArgs: false }, + MP: { id: OPS.markPoint, numArgs: 1, variableArgs: false }, + DP: { id: OPS.markPointProps, numArgs: 2, variableArgs: false }, + BMC: { id: OPS.beginMarkedContent, numArgs: 1, variableArgs: false }, + BDC: { id: OPS.beginMarkedContentProps, numArgs: 2, + variableArgs: false }, + EMC: { id: OPS.endMarkedContent, numArgs: 0, variableArgs: false }, + + // Compatibility + BX: { id: OPS.beginCompat, numArgs: 0, variableArgs: false }, + EX: { id: OPS.endCompat, numArgs: 0, variableArgs: false }, + + // (reserved partial commands for the lexer) + BM: null, + BD: null, + 'true': null, + fa: null, + fal: null, + fals: null, + 'false': null, + nu: null, + nul: null, + 'null': null + }; + + function EvaluatorPreprocessor(stream, xref, stateManager) { + // TODO(mduan): pass array of knownCommands rather than OP_MAP + // dictionary + this.parser = new Parser(new Lexer(stream, OP_MAP), false, xref); + this.stateManager = stateManager; + this.nonProcessedArgs = []; + } + + EvaluatorPreprocessor.prototype = { + get savedStatesDepth() { + return this.stateManager.stateStack.length; + }, + + // |operation| is an object with two fields: + // + // - |fn| is an out param. + // + // - |args| is an inout param. On entry, it should have one of two values. + // + // - An empty array. This indicates that the caller is providing the + // array in which the args will be stored in. The caller should use + // this value if it can reuse a single array for each call to read(). + // + // - |null|. This indicates that the caller needs this function to create + // the array in which any args are stored in. If there are zero args, + // this function will leave |operation.args| as |null| (thus avoiding + // allocations that would occur if we used an empty array to represent + // zero arguments). Otherwise, it will replace |null| with a new array + // containing the arguments. The caller should use this value if it + // cannot reuse an array for each call to read(). + // + // These two modes are present because this function is very hot and so + // avoiding allocations where possible is worthwhile. + // + read: function EvaluatorPreprocessor_read(operation) { + var args = operation.args; + while (true) { + var obj = this.parser.getObj(); + if (isCmd(obj)) { + var cmd = obj.cmd; + // Check that the command is valid + var opSpec = OP_MAP[cmd]; + if (!opSpec) { + warn('Unknown command "' + cmd + '"'); + continue; + } + + var fn = opSpec.id; + var numArgs = opSpec.numArgs; + var argsLength = args !== null ? args.length : 0; + + if (!opSpec.variableArgs) { + // Postscript commands can be nested, e.g. /F2 /GS2 gs 5.711 Tf + if (argsLength !== numArgs) { + var nonProcessedArgs = this.nonProcessedArgs; + while (argsLength > numArgs) { + nonProcessedArgs.push(args.shift()); + argsLength--; + } + while (argsLength < numArgs && nonProcessedArgs.length !== 0) { + if (!args) { + args = []; + } + args.unshift(nonProcessedArgs.pop()); + argsLength++; + } + } + + if (argsLength < numArgs) { + // If we receive too few args, it's not possible to possible + // to execute the command, so skip the command + info('Command ' + fn + ': because expected ' + + numArgs + ' args, but received ' + argsLength + + ' args; skipping'); + args = null; + continue; + } + } else if (argsLength > numArgs) { + info('Command ' + fn + ': expected [0,' + numArgs + + '] args, but received ' + argsLength + ' args'); + } + + // TODO figure out how to type-check vararg functions + this.preprocessCommand(fn, args); + + operation.fn = fn; + operation.args = args; + return true; + } else { + if (isEOF(obj)) { + return false; // no more commands + } + // argument + if (obj !== null) { + if (!args) { + args = []; + } + args.push((obj instanceof Dict ? obj.getAll() : obj)); + assert(args.length <= 33, 'Too many arguments'); + } + } + } + }, + + preprocessCommand: + function EvaluatorPreprocessor_preprocessCommand(fn, args) { + switch (fn | 0) { + case OPS.save: + this.stateManager.save(); + break; + case OPS.restore: + this.stateManager.restore(); + break; + case OPS.transform: + this.stateManager.transform(args); + break; + } + } + }; + return EvaluatorPreprocessor; +})(); + +var QueueOptimizer = (function QueueOptimizerClosure() { + function addState(parentState, pattern, fn) { + var state = parentState; + for (var i = 0, ii = pattern.length - 1; i < ii; i++) { + var item = pattern[i]; + state = (state[item] || (state[item] = [])); + } + state[pattern[pattern.length - 1]] = fn; + } + + function handlePaintSolidColorImageMask(iFirstSave, count, fnArray, + argsArray) { + // Handles special case of mainly LaTeX documents which use image masks to + // draw lines with the current fill style. + // 'count' groups of (save, transform, paintImageMaskXObject, restore)+ + // have been found at iFirstSave. + var iFirstPIMXO = iFirstSave + 2; + for (var i = 0; i < count; i++) { + var arg = argsArray[iFirstPIMXO + 4 * i]; + var imageMask = arg.length === 1 && arg[0]; + if (imageMask && imageMask.width === 1 && imageMask.height === 1 && + (!imageMask.data.length || + (imageMask.data.length === 1 && imageMask.data[0] === 0))) { + fnArray[iFirstPIMXO + 4 * i] = OPS.paintSolidColorImageMask; + continue; + } + break; + } + return count - i; + } + + var InitialState = []; + + // This replaces (save, transform, paintInlineImageXObject, restore)+ + // sequences with one |paintInlineImageXObjectGroup| operation. + addState(InitialState, + [OPS.save, OPS.transform, OPS.paintInlineImageXObject, OPS.restore], + function foundInlineImageGroup(context) { + var MIN_IMAGES_IN_INLINE_IMAGES_BLOCK = 10; + var MAX_IMAGES_IN_INLINE_IMAGES_BLOCK = 200; + var MAX_WIDTH = 1000; + var IMAGE_PADDING = 1; + + var fnArray = context.fnArray, argsArray = context.argsArray; + var curr = context.iCurr; + var iFirstSave = curr - 3; + var iFirstTransform = curr - 2; + var iFirstPIIXO = curr - 1; + + // Look for the quartets. + var i = iFirstSave + 4; + var ii = fnArray.length; + while (i + 3 < ii) { + if (fnArray[i] !== OPS.save || + fnArray[i + 1] !== OPS.transform || + fnArray[i + 2] !== OPS.paintInlineImageXObject || + fnArray[i + 3] !== OPS.restore) { + break; // ops don't match + } + i += 4; + } + + // At this point, i is the index of the first op past the last valid + // quartet. + var count = Math.min((i - iFirstSave) / 4, + MAX_IMAGES_IN_INLINE_IMAGES_BLOCK); + if (count < MIN_IMAGES_IN_INLINE_IMAGES_BLOCK) { + return i; + } + + // assuming that heights of those image is too small (~1 pixel) + // packing as much as possible by lines + var maxX = 0; + var map = [], maxLineHeight = 0; + var currentX = IMAGE_PADDING, currentY = IMAGE_PADDING; + var q; + for (q = 0; q < count; q++) { + var transform = argsArray[iFirstTransform + (q << 2)]; + var img = argsArray[iFirstPIIXO + (q << 2)][0]; + if (currentX + img.width > MAX_WIDTH) { + // starting new line + maxX = Math.max(maxX, currentX); + currentY += maxLineHeight + 2 * IMAGE_PADDING; + currentX = 0; + maxLineHeight = 0; + } + map.push({ + transform: transform, + x: currentX, y: currentY, + w: img.width, h: img.height + }); + currentX += img.width + 2 * IMAGE_PADDING; + maxLineHeight = Math.max(maxLineHeight, img.height); + } + var imgWidth = Math.max(maxX, currentX) + IMAGE_PADDING; + var imgHeight = currentY + maxLineHeight + IMAGE_PADDING; + var imgData = new Uint8Array(imgWidth * imgHeight * 4); + var imgRowSize = imgWidth << 2; + for (q = 0; q < count; q++) { + var data = argsArray[iFirstPIIXO + (q << 2)][0].data; + // Copy image by lines and extends pixels into padding. + var rowSize = map[q].w << 2; + var dataOffset = 0; + var offset = (map[q].x + map[q].y * imgWidth) << 2; + imgData.set(data.subarray(0, rowSize), offset - imgRowSize); + for (var k = 0, kk = map[q].h; k < kk; k++) { + imgData.set(data.subarray(dataOffset, dataOffset + rowSize), offset); + dataOffset += rowSize; + offset += imgRowSize; + } + imgData.set(data.subarray(dataOffset - rowSize, dataOffset), offset); + while (offset >= 0) { + data[offset - 4] = data[offset]; + data[offset - 3] = data[offset + 1]; + data[offset - 2] = data[offset + 2]; + data[offset - 1] = data[offset + 3]; + data[offset + rowSize] = data[offset + rowSize - 4]; + data[offset + rowSize + 1] = data[offset + rowSize - 3]; + data[offset + rowSize + 2] = data[offset + rowSize - 2]; + data[offset + rowSize + 3] = data[offset + rowSize - 1]; + offset -= imgRowSize; + } + } + + // Replace queue items. + fnArray.splice(iFirstSave, count * 4, OPS.paintInlineImageXObjectGroup); + argsArray.splice(iFirstSave, count * 4, + [{ width: imgWidth, height: imgHeight, kind: ImageKind.RGBA_32BPP, + data: imgData }, map]); + + return iFirstSave + 1; + }); + + // This replaces (save, transform, paintImageMaskXObject, restore)+ + // sequences with one |paintImageMaskXObjectGroup| or one + // |paintImageMaskXObjectRepeat| operation. + addState(InitialState, + [OPS.save, OPS.transform, OPS.paintImageMaskXObject, OPS.restore], + function foundImageMaskGroup(context) { + var MIN_IMAGES_IN_MASKS_BLOCK = 10; + var MAX_IMAGES_IN_MASKS_BLOCK = 100; + var MAX_SAME_IMAGES_IN_MASKS_BLOCK = 1000; + + var fnArray = context.fnArray, argsArray = context.argsArray; + var curr = context.iCurr; + var iFirstSave = curr - 3; + var iFirstTransform = curr - 2; + var iFirstPIMXO = curr - 1; + + // Look for the quartets. + var i = iFirstSave + 4; + var ii = fnArray.length; + while (i + 3 < ii) { + if (fnArray[i] !== OPS.save || + fnArray[i + 1] !== OPS.transform || + fnArray[i + 2] !== OPS.paintImageMaskXObject || + fnArray[i + 3] !== OPS.restore) { + break; // ops don't match + } + i += 4; + } + + // At this point, i is the index of the first op past the last valid + // quartet. + var count = (i - iFirstSave) / 4; + count = handlePaintSolidColorImageMask(iFirstSave, count, fnArray, + argsArray); + if (count < MIN_IMAGES_IN_MASKS_BLOCK) { + return i; + } + + var q; + var isSameImage = false; + var iTransform, transformArgs; + var firstPIMXOArg0 = argsArray[iFirstPIMXO][0]; + if (argsArray[iFirstTransform][1] === 0 && + argsArray[iFirstTransform][2] === 0) { + isSameImage = true; + var firstTransformArg0 = argsArray[iFirstTransform][0]; + var firstTransformArg3 = argsArray[iFirstTransform][3]; + iTransform = iFirstTransform + 4; + var iPIMXO = iFirstPIMXO + 4; + for (q = 1; q < count; q++, iTransform += 4, iPIMXO += 4) { + transformArgs = argsArray[iTransform]; + if (argsArray[iPIMXO][0] !== firstPIMXOArg0 || + transformArgs[0] !== firstTransformArg0 || + transformArgs[1] !== 0 || + transformArgs[2] !== 0 || + transformArgs[3] !== firstTransformArg3) { + if (q < MIN_IMAGES_IN_MASKS_BLOCK) { + isSameImage = false; + } else { + count = q; + } + break; // different image or transform + } + } + } + + if (isSameImage) { + count = Math.min(count, MAX_SAME_IMAGES_IN_MASKS_BLOCK); + var positions = new Float32Array(count * 2); + iTransform = iFirstTransform; + for (q = 0; q < count; q++, iTransform += 4) { + transformArgs = argsArray[iTransform]; + positions[(q << 1)] = transformArgs[4]; + positions[(q << 1) + 1] = transformArgs[5]; + } + + // Replace queue items. + fnArray.splice(iFirstSave, count * 4, OPS.paintImageMaskXObjectRepeat); + argsArray.splice(iFirstSave, count * 4, + [firstPIMXOArg0, firstTransformArg0, firstTransformArg3, positions]); + } else { + count = Math.min(count, MAX_IMAGES_IN_MASKS_BLOCK); + var images = []; + for (q = 0; q < count; q++) { + transformArgs = argsArray[iFirstTransform + (q << 2)]; + var maskParams = argsArray[iFirstPIMXO + (q << 2)][0]; + images.push({ data: maskParams.data, width: maskParams.width, + height: maskParams.height, + transform: transformArgs }); + } + + // Replace queue items. + fnArray.splice(iFirstSave, count * 4, OPS.paintImageMaskXObjectGroup); + argsArray.splice(iFirstSave, count * 4, [images]); + } + + return iFirstSave + 1; + }); + + // This replaces (save, transform, paintImageXObject, restore)+ sequences + // with one paintImageXObjectRepeat operation, if the |transform| and + // |paintImageXObjectRepeat| ops are appropriate. + addState(InitialState, + [OPS.save, OPS.transform, OPS.paintImageXObject, OPS.restore], + function (context) { + var MIN_IMAGES_IN_BLOCK = 3; + var MAX_IMAGES_IN_BLOCK = 1000; + + var fnArray = context.fnArray, argsArray = context.argsArray; + var curr = context.iCurr; + var iFirstSave = curr - 3; + var iFirstTransform = curr - 2; + var iFirstPIXO = curr - 1; + var iFirstRestore = curr; + + if (argsArray[iFirstTransform][1] !== 0 || + argsArray[iFirstTransform][2] !== 0) { + return iFirstRestore + 1; // transform has the wrong form + } + + // Look for the quartets. + var firstPIXOArg0 = argsArray[iFirstPIXO][0]; + var firstTransformArg0 = argsArray[iFirstTransform][0]; + var firstTransformArg3 = argsArray[iFirstTransform][3]; + var i = iFirstSave + 4; + var ii = fnArray.length; + while (i + 3 < ii) { + if (fnArray[i] !== OPS.save || + fnArray[i + 1] !== OPS.transform || + fnArray[i + 2] !== OPS.paintImageXObject || + fnArray[i + 3] !== OPS.restore) { + break; // ops don't match + } + if (argsArray[i + 1][0] !== firstTransformArg0 || + argsArray[i + 1][1] !== 0 || + argsArray[i + 1][2] !== 0 || + argsArray[i + 1][3] !== firstTransformArg3) { + break; // transforms don't match + } + if (argsArray[i + 2][0] !== firstPIXOArg0) { + break; // images don't match + } + i += 4; + } + + // At this point, i is the index of the first op past the last valid + // quartet. + var count = Math.min((i - iFirstSave) / 4, MAX_IMAGES_IN_BLOCK); + if (count < MIN_IMAGES_IN_BLOCK) { + return i; + } + + // Extract the (x,y) positions from all of the matching transforms. + var positions = new Float32Array(count * 2); + var iTransform = iFirstTransform; + for (var q = 0; q < count; q++, iTransform += 4) { + var transformArgs = argsArray[iTransform]; + positions[(q << 1)] = transformArgs[4]; + positions[(q << 1) + 1] = transformArgs[5]; + } + + // Replace queue items. + var args = [firstPIXOArg0, firstTransformArg0, firstTransformArg3, + positions]; + fnArray.splice(iFirstSave, count * 4, OPS.paintImageXObjectRepeat); + argsArray.splice(iFirstSave, count * 4, args); + + return iFirstSave + 1; + }); + + // This replaces (beginText, setFont, setTextMatrix, showText, endText)+ + // sequences with (beginText, setFont, (setTextMatrix, showText)+, endText)+ + // sequences, if the font for each one is the same. + addState(InitialState, + [OPS.beginText, OPS.setFont, OPS.setTextMatrix, OPS.showText, OPS.endText], + function (context) { + var MIN_CHARS_IN_BLOCK = 3; + var MAX_CHARS_IN_BLOCK = 1000; + + var fnArray = context.fnArray, argsArray = context.argsArray; + var curr = context.iCurr; + var iFirstBeginText = curr - 4; + var iFirstSetFont = curr - 3; + var iFirstSetTextMatrix = curr - 2; + var iFirstShowText = curr - 1; + var iFirstEndText = curr; + + // Look for the quintets. + var firstSetFontArg0 = argsArray[iFirstSetFont][0]; + var firstSetFontArg1 = argsArray[iFirstSetFont][1]; + var i = iFirstBeginText + 5; + var ii = fnArray.length; + while (i + 4 < ii) { + if (fnArray[i] !== OPS.beginText || + fnArray[i + 1] !== OPS.setFont || + fnArray[i + 2] !== OPS.setTextMatrix || + fnArray[i + 3] !== OPS.showText || + fnArray[i + 4] !== OPS.endText) { + break; // ops don't match + } + if (argsArray[i + 1][0] !== firstSetFontArg0 || + argsArray[i + 1][1] !== firstSetFontArg1) { + break; // fonts don't match + } + i += 5; + } + + // At this point, i is the index of the first op past the last valid + // quintet. + var count = Math.min(((i - iFirstBeginText) / 5), MAX_CHARS_IN_BLOCK); + if (count < MIN_CHARS_IN_BLOCK) { + return i; + } + + // If the preceding quintet is (, setFont, setTextMatrix, + // showText, endText), include that as well. (E.g. might be + // |dependency|.) + var iFirst = iFirstBeginText; + if (iFirstBeginText >= 4 && + fnArray[iFirstBeginText - 4] === fnArray[iFirstSetFont] && + fnArray[iFirstBeginText - 3] === fnArray[iFirstSetTextMatrix] && + fnArray[iFirstBeginText - 2] === fnArray[iFirstShowText] && + fnArray[iFirstBeginText - 1] === fnArray[iFirstEndText] && + argsArray[iFirstBeginText - 4][0] === firstSetFontArg0 && + argsArray[iFirstBeginText - 4][1] === firstSetFontArg1) { + count++; + iFirst -= 5; + } + + // Remove (endText, beginText, setFont) trios. + var iEndText = iFirst + 4; + for (var q = 1; q < count; q++) { + fnArray.splice(iEndText, 3); + argsArray.splice(iEndText, 3); + iEndText += 2; + } + + return iEndText + 1; + }); + + function QueueOptimizer() {} + + QueueOptimizer.prototype = { + optimize: function QueueOptimizer_optimize(queue) { + var fnArray = queue.fnArray, argsArray = queue.argsArray; + var context = { + iCurr: 0, + fnArray: fnArray, + argsArray: argsArray + }; + var state; + var i = 0, ii = fnArray.length; + while (i < ii) { + state = (state || InitialState)[fnArray[i]]; + if (typeof state === 'function') { // we found some handler + context.iCurr = i; + // state() returns the index of the first non-matching op (if we + // didn't match) or the first op past the modified ops (if we did + // match and replace). + i = state(context); + state = undefined; // reset the state machine + ii = context.fnArray.length; + } else { + i++; + } + } + } + }; + return QueueOptimizer; +})(); + + +var BUILT_IN_CMAPS = [ +// << Start unicode maps. +'Adobe-GB1-UCS2', +'Adobe-CNS1-UCS2', +'Adobe-Japan1-UCS2', +'Adobe-Korea1-UCS2', +// >> End unicode maps. +'78-EUC-H', +'78-EUC-V', +'78-H', +'78-RKSJ-H', +'78-RKSJ-V', +'78-V', +'78ms-RKSJ-H', +'78ms-RKSJ-V', +'83pv-RKSJ-H', +'90ms-RKSJ-H', +'90ms-RKSJ-V', +'90msp-RKSJ-H', +'90msp-RKSJ-V', +'90pv-RKSJ-H', +'90pv-RKSJ-V', +'Add-H', +'Add-RKSJ-H', +'Add-RKSJ-V', +'Add-V', +'Adobe-CNS1-0', +'Adobe-CNS1-1', +'Adobe-CNS1-2', +'Adobe-CNS1-3', +'Adobe-CNS1-4', +'Adobe-CNS1-5', +'Adobe-CNS1-6', +'Adobe-GB1-0', +'Adobe-GB1-1', +'Adobe-GB1-2', +'Adobe-GB1-3', +'Adobe-GB1-4', +'Adobe-GB1-5', +'Adobe-Japan1-0', +'Adobe-Japan1-1', +'Adobe-Japan1-2', +'Adobe-Japan1-3', +'Adobe-Japan1-4', +'Adobe-Japan1-5', +'Adobe-Japan1-6', +'Adobe-Korea1-0', +'Adobe-Korea1-1', +'Adobe-Korea1-2', +'B5-H', +'B5-V', +'B5pc-H', +'B5pc-V', +'CNS-EUC-H', +'CNS-EUC-V', +'CNS1-H', +'CNS1-V', +'CNS2-H', +'CNS2-V', +'ETHK-B5-H', +'ETHK-B5-V', +'ETen-B5-H', +'ETen-B5-V', +'ETenms-B5-H', +'ETenms-B5-V', +'EUC-H', +'EUC-V', +'Ext-H', +'Ext-RKSJ-H', +'Ext-RKSJ-V', +'Ext-V', +'GB-EUC-H', +'GB-EUC-V', +'GB-H', +'GB-V', +'GBK-EUC-H', +'GBK-EUC-V', +'GBK2K-H', +'GBK2K-V', +'GBKp-EUC-H', +'GBKp-EUC-V', +'GBT-EUC-H', +'GBT-EUC-V', +'GBT-H', +'GBT-V', +'GBTpc-EUC-H', +'GBTpc-EUC-V', +'GBpc-EUC-H', +'GBpc-EUC-V', +'H', +'HKdla-B5-H', +'HKdla-B5-V', +'HKdlb-B5-H', +'HKdlb-B5-V', +'HKgccs-B5-H', +'HKgccs-B5-V', +'HKm314-B5-H', +'HKm314-B5-V', +'HKm471-B5-H', +'HKm471-B5-V', +'HKscs-B5-H', +'HKscs-B5-V', +'Hankaku', +'Hiragana', +'KSC-EUC-H', +'KSC-EUC-V', +'KSC-H', +'KSC-Johab-H', +'KSC-Johab-V', +'KSC-V', +'KSCms-UHC-H', +'KSCms-UHC-HW-H', +'KSCms-UHC-HW-V', +'KSCms-UHC-V', +'KSCpc-EUC-H', +'KSCpc-EUC-V', +'Katakana', +'NWP-H', +'NWP-V', +'RKSJ-H', +'RKSJ-V', +'Roman', +'UniCNS-UCS2-H', +'UniCNS-UCS2-V', +'UniCNS-UTF16-H', +'UniCNS-UTF16-V', +'UniCNS-UTF32-H', +'UniCNS-UTF32-V', +'UniCNS-UTF8-H', +'UniCNS-UTF8-V', +'UniGB-UCS2-H', +'UniGB-UCS2-V', +'UniGB-UTF16-H', +'UniGB-UTF16-V', +'UniGB-UTF32-H', +'UniGB-UTF32-V', +'UniGB-UTF8-H', +'UniGB-UTF8-V', +'UniJIS-UCS2-H', +'UniJIS-UCS2-HW-H', +'UniJIS-UCS2-HW-V', +'UniJIS-UCS2-V', +'UniJIS-UTF16-H', +'UniJIS-UTF16-V', +'UniJIS-UTF32-H', +'UniJIS-UTF32-V', +'UniJIS-UTF8-H', +'UniJIS-UTF8-V', +'UniJIS2004-UTF16-H', +'UniJIS2004-UTF16-V', +'UniJIS2004-UTF32-H', +'UniJIS2004-UTF32-V', +'UniJIS2004-UTF8-H', +'UniJIS2004-UTF8-V', +'UniJISPro-UCS2-HW-V', +'UniJISPro-UCS2-V', +'UniJISPro-UTF8-V', +'UniJISX0213-UTF32-H', +'UniJISX0213-UTF32-V', +'UniJISX02132004-UTF32-H', +'UniJISX02132004-UTF32-V', +'UniKS-UCS2-H', +'UniKS-UCS2-V', +'UniKS-UTF16-H', +'UniKS-UTF16-V', +'UniKS-UTF32-H', +'UniKS-UTF32-V', +'UniKS-UTF8-H', +'UniKS-UTF8-V', +'V', +'WP-Symbol']; + +// CMap, not to be confused with TrueType's cmap. +var CMap = (function CMapClosure() { + function CMap(builtInCMap) { + // Codespace ranges are stored as follows: + // [[1BytePairs], [2BytePairs], [3BytePairs], [4BytePairs]] + // where nBytePairs are ranges e.g. [low1, high1, low2, high2, ...] + this.codespaceRanges = [[], [], [], []]; + this.numCodespaceRanges = 0; + // Map entries have one of two forms. + // - cid chars are 16-bit unsigned integers, stored as integers. + // - bf chars are variable-length byte sequences, stored as strings, with + // one byte per character. + this._map = []; + this.name = ''; + this.vertical = false; + this.useCMap = null; + this.builtInCMap = builtInCMap; + } + CMap.prototype = { + addCodespaceRange: function(n, low, high) { + this.codespaceRanges[n - 1].push(low, high); + this.numCodespaceRanges++; + }, + + mapCidRange: function(low, high, dstLow) { + while (low <= high) { + this._map[low++] = dstLow++; + } + }, + + mapBfRange: function(low, high, dstLow) { + var lastByte = dstLow.length - 1; + while (low <= high) { + this._map[low++] = dstLow; + // Only the last byte has to be incremented. + dstLow = dstLow.substr(0, lastByte) + + String.fromCharCode(dstLow.charCodeAt(lastByte) + 1); + } + }, + + mapBfRangeToArray: function(low, high, array) { + var i = 0, ii = array.length; + while (low <= high && i < ii) { + this._map[low] = array[i++]; + ++low; + } + }, + + // This is used for both bf and cid chars. + mapOne: function(src, dst) { + this._map[src] = dst; + }, + + lookup: function(code) { + return this._map[code]; + }, + + contains: function(code) { + return this._map[code] !== undefined; + }, + + forEach: function(callback) { + // Most maps have fewer than 65536 entries, and for those we use normal + // array iteration. But really sparse tables are possible -- e.g. with + // indices in the *billions*. For such tables we use for..in, which isn't + // ideal because it stringifies the indices for all present elements, but + // it does avoid iterating over every undefined entry. + var map = this._map; + var length = map.length; + var i; + if (length <= 0x10000) { + for (i = 0; i < length; i++) { + if (map[i] !== undefined) { + callback(i, map[i]); + } + } + } else { + for (i in this._map) { + callback(i, map[i]); + } + } + }, + + charCodeOf: function(value) { + return this._map.indexOf(value); + }, + + getMap: function() { + return this._map; + }, + + readCharCode: function(str, offset, out) { + var c = 0; + var codespaceRanges = this.codespaceRanges; + var codespaceRangesLen = this.codespaceRanges.length; + // 9.7.6.2 CMap Mapping + // The code length is at most 4. + for (var n = 0; n < codespaceRangesLen; n++) { + c = ((c << 8) | str.charCodeAt(offset + n)) >>> 0; + // Check each codespace range to see if it falls within. + var codespaceRange = codespaceRanges[n]; + for (var k = 0, kk = codespaceRange.length; k < kk;) { + var low = codespaceRange[k++]; + var high = codespaceRange[k++]; + if (c >= low && c <= high) { + out.charcode = c; + out.length = n + 1; + return; + } + } + } + out.charcode = 0; + out.length = 1; + }, + + get isIdentityCMap() { + if (!(this.name === 'Identity-H' || this.name === 'Identity-V')) { + return false; + } + if (this._map.length !== 0x10000) { + return false; + } + for (var i = 0; i < 0x10000; i++) { + if (this._map[i] !== i) { + return false; + } + } + return true; + } + }; + return CMap; +})(); + +// A special case of CMap, where the _map array implicitly has a length of +// 65536 and each element is equal to its index. +var IdentityCMap = (function IdentityCMapClosure() { + function IdentityCMap(vertical, n) { + CMap.call(this); + this.vertical = vertical; + this.addCodespaceRange(n, 0, 0xffff); + } + Util.inherit(IdentityCMap, CMap, {}); + + IdentityCMap.prototype = { + addCodespaceRange: CMap.prototype.addCodespaceRange, + + mapCidRange: function(low, high, dstLow) { + error('should not call mapCidRange'); + }, + + mapBfRange: function(low, high, dstLow) { + error('should not call mapBfRange'); + }, + + mapBfRangeToArray: function(low, high, array) { + error('should not call mapBfRangeToArray'); + }, + + mapOne: function(src, dst) { + error('should not call mapCidOne'); + }, + + lookup: function(code) { + return (isInt(code) && code <= 0xffff) ? code : undefined; + }, + + contains: function(code) { + return isInt(code) && code <= 0xffff; + }, + + forEach: function(callback) { + for (var i = 0; i <= 0xffff; i++) { + callback(i, i); + } + }, + + charCodeOf: function(value) { + return (isInt(value) && value <= 0xffff) ? value : -1; + }, + + getMap: function() { + // Sometimes identity maps must be instantiated, but it's rare. + var map = new Array(0x10000); + for (var i = 0; i <= 0xffff; i++) { + map[i] = i; + } + return map; + }, + + readCharCode: CMap.prototype.readCharCode, + + get isIdentityCMap() { + error('should not access .isIdentityCMap'); + } + }; + + return IdentityCMap; +})(); + +var BinaryCMapReader = (function BinaryCMapReaderClosure() { + function fetchBinaryData(url) { + var nonBinaryRequest = PDFJS.disableWorker; + var request = new XMLHttpRequest(); + request.open('GET', url, false); + if (!nonBinaryRequest) { + try { + request.responseType = 'arraybuffer'; + nonBinaryRequest = request.responseType !== 'arraybuffer'; + } catch (e) { + nonBinaryRequest = true; + } + } + if (nonBinaryRequest && request.overrideMimeType) { + request.overrideMimeType('text/plain; charset=x-user-defined'); + } + request.send(null); + if (nonBinaryRequest ? !request.responseText : !request.response) { + error('Unable to get binary cMap at: ' + url); + } + if (nonBinaryRequest) { + var data = Array.prototype.map.call(request.responseText, function (ch) { + return ch.charCodeAt(0) & 255; + }); + return new Uint8Array(data); + } + return new Uint8Array(request.response); + } + + function hexToInt(a, size) { + var n = 0; + for (var i = 0; i <= size; i++) { + n = (n << 8) | a[i]; + } + return n >>> 0; + } + + function hexToStr(a, size) { + // This code is hot. Special-case some common values to avoid creating an + // object with subarray(). + if (size === 1) { + return String.fromCharCode(a[0], a[1]); + } + if (size === 3) { + return String.fromCharCode(a[0], a[1], a[2], a[3]); + } + return String.fromCharCode.apply(null, a.subarray(0, size + 1)); + } + + function addHex(a, b, size) { + var c = 0; + for (var i = size; i >= 0; i--) { + c += a[i] + b[i]; + a[i] = c & 255; + c >>= 8; + } + } + + function incHex(a, size) { + var c = 1; + for (var i = size; i >= 0 && c > 0; i--) { + c += a[i]; + a[i] = c & 255; + c >>= 8; + } + } + + var MAX_NUM_SIZE = 16; + var MAX_ENCODED_NUM_SIZE = 19; // ceil(MAX_NUM_SIZE * 7 / 8) + + function BinaryCMapStream(data) { + this.buffer = data; + this.pos = 0; + this.end = data.length; + this.tmpBuf = new Uint8Array(MAX_ENCODED_NUM_SIZE); + } + + BinaryCMapStream.prototype = { + readByte: function () { + if (this.pos >= this.end) { + return -1; + } + return this.buffer[this.pos++]; + }, + readNumber: function () { + var n = 0; + var last; + do { + var b = this.readByte(); + if (b < 0) { + error('unexpected EOF in bcmap'); + } + last = !(b & 0x80); + n = (n << 7) | (b & 0x7F); + } while (!last); + return n; + }, + readSigned: function () { + var n = this.readNumber(); + return (n & 1) ? ~(n >>> 1) : n >>> 1; + }, + readHex: function (num, size) { + num.set(this.buffer.subarray(this.pos, + this.pos + size + 1)); + this.pos += size + 1; + }, + readHexNumber: function (num, size) { + var last; + var stack = this.tmpBuf, sp = 0; + do { + var b = this.readByte(); + if (b < 0) { + error('unexpected EOF in bcmap'); + } + last = !(b & 0x80); + stack[sp++] = b & 0x7F; + } while (!last); + var i = size, buffer = 0, bufferSize = 0; + while (i >= 0) { + while (bufferSize < 8 && stack.length > 0) { + buffer = (stack[--sp] << bufferSize) | buffer; + bufferSize += 7; + } + num[i] = buffer & 255; + i--; + buffer >>= 8; + bufferSize -= 8; + } + }, + readHexSigned: function (num, size) { + this.readHexNumber(num, size); + var sign = num[size] & 1 ? 255 : 0; + var c = 0; + for (var i = 0; i <= size; i++) { + c = ((c & 1) << 8) | num[i]; + num[i] = (c >> 1) ^ sign; + } + }, + readString: function () { + var len = this.readNumber(); + var s = ''; + for (var i = 0; i < len; i++) { + s += String.fromCharCode(this.readNumber()); + } + return s; + } + }; + + function processBinaryCMap(url, cMap, extend) { + var data = fetchBinaryData(url); + var stream = new BinaryCMapStream(data); + + var header = stream.readByte(); + cMap.vertical = !!(header & 1); + + var useCMap = null; + var start = new Uint8Array(MAX_NUM_SIZE); + var end = new Uint8Array(MAX_NUM_SIZE); + var char = new Uint8Array(MAX_NUM_SIZE); + var charCode = new Uint8Array(MAX_NUM_SIZE); + var tmp = new Uint8Array(MAX_NUM_SIZE); + var code; + + var b; + while ((b = stream.readByte()) >= 0) { + var type = b >> 5; + if (type === 7) { // metadata, e.g. comment or usecmap + switch (b & 0x1F) { + case 0: + stream.readString(); // skipping comment + break; + case 1: + useCMap = stream.readString(); + break; + } + continue; + } + var sequence = !!(b & 0x10); + var dataSize = b & 15; + + assert(dataSize + 1 <= MAX_NUM_SIZE); + + var ucs2DataSize = 1; + var subitemsCount = stream.readNumber(); + var i; + switch (type) { + case 0: // codespacerange + stream.readHex(start, dataSize); + stream.readHexNumber(end, dataSize); + addHex(end, start, dataSize); + cMap.addCodespaceRange(dataSize + 1, hexToInt(start, dataSize), + hexToInt(end, dataSize)); + for (i = 1; i < subitemsCount; i++) { + incHex(end, dataSize); + stream.readHexNumber(start, dataSize); + addHex(start, end, dataSize); + stream.readHexNumber(end, dataSize); + addHex(end, start, dataSize); + cMap.addCodespaceRange(dataSize + 1, hexToInt(start, dataSize), + hexToInt(end, dataSize)); + } + break; + case 1: // notdefrange + stream.readHex(start, dataSize); + stream.readHexNumber(end, dataSize); + addHex(end, start, dataSize); + code = stream.readNumber(); + // undefined range, skipping + for (i = 1; i < subitemsCount; i++) { + incHex(end, dataSize); + stream.readHexNumber(start, dataSize); + addHex(start, end, dataSize); + stream.readHexNumber(end, dataSize); + addHex(end, start, dataSize); + code = stream.readNumber(); + // nop + } + break; + case 2: // cidchar + stream.readHex(char, dataSize); + code = stream.readNumber(); + cMap.mapOne(hexToInt(char, dataSize), code); + for (i = 1; i < subitemsCount; i++) { + incHex(char, dataSize); + if (!sequence) { + stream.readHexNumber(tmp, dataSize); + addHex(char, tmp, dataSize); + } + code = stream.readSigned() + (code + 1); + cMap.mapOne(hexToInt(char, dataSize), code); + } + break; + case 3: // cidrange + stream.readHex(start, dataSize); + stream.readHexNumber(end, dataSize); + addHex(end, start, dataSize); + code = stream.readNumber(); + cMap.mapCidRange(hexToInt(start, dataSize), hexToInt(end, dataSize), + code); + for (i = 1; i < subitemsCount; i++) { + incHex(end, dataSize); + if (!sequence) { + stream.readHexNumber(start, dataSize); + addHex(start, end, dataSize); + } else { + start.set(end); + } + stream.readHexNumber(end, dataSize); + addHex(end, start, dataSize); + code = stream.readNumber(); + cMap.mapCidRange(hexToInt(start, dataSize), hexToInt(end, dataSize), + code); + } + break; + case 4: // bfchar + stream.readHex(char, ucs2DataSize); + stream.readHex(charCode, dataSize); + cMap.mapOne(hexToInt(char, ucs2DataSize), + hexToStr(charCode, dataSize)); + for (i = 1; i < subitemsCount; i++) { + incHex(char, ucs2DataSize); + if (!sequence) { + stream.readHexNumber(tmp, ucs2DataSize); + addHex(char, tmp, ucs2DataSize); + } + incHex(charCode, dataSize); + stream.readHexSigned(tmp, dataSize); + addHex(charCode, tmp, dataSize); + cMap.mapOne(hexToInt(char, ucs2DataSize), + hexToStr(charCode, dataSize)); + } + break; + case 5: // bfrange + stream.readHex(start, ucs2DataSize); + stream.readHexNumber(end, ucs2DataSize); + addHex(end, start, ucs2DataSize); + stream.readHex(charCode, dataSize); + cMap.mapBfRange(hexToInt(start, ucs2DataSize), + hexToInt(end, ucs2DataSize), + hexToStr(charCode, dataSize)); + for (i = 1; i < subitemsCount; i++) { + incHex(end, ucs2DataSize); + if (!sequence) { + stream.readHexNumber(start, ucs2DataSize); + addHex(start, end, ucs2DataSize); + } else { + start.set(end); + } + stream.readHexNumber(end, ucs2DataSize); + addHex(end, start, ucs2DataSize); + stream.readHex(charCode, dataSize); + cMap.mapBfRange(hexToInt(start, ucs2DataSize), + hexToInt(end, ucs2DataSize), + hexToStr(charCode, dataSize)); + } + break; + default: + error('Unknown type: ' + type); + break; + } + } + + if (useCMap) { + extend(useCMap); + } + return cMap; + } + + function BinaryCMapReader() {} + + BinaryCMapReader.prototype = { + read: processBinaryCMap + }; + + return BinaryCMapReader; +})(); + +var CMapFactory = (function CMapFactoryClosure() { + function strToInt(str) { + var a = 0; + for (var i = 0; i < str.length; i++) { + a = (a << 8) | str.charCodeAt(i); + } + return a >>> 0; + } + + function expectString(obj) { + if (!isString(obj)) { + error('Malformed CMap: expected string.'); + } + } + + function expectInt(obj) { + if (!isInt(obj)) { + error('Malformed CMap: expected int.'); + } + } + + function parseBfChar(cMap, lexer) { + while (true) { + var obj = lexer.getObj(); + if (isEOF(obj)) { + break; + } + if (isCmd(obj, 'endbfchar')) { + return; + } + expectString(obj); + var src = strToInt(obj); + obj = lexer.getObj(); + // TODO are /dstName used? + expectString(obj); + var dst = obj; + cMap.mapOne(src, dst); + } + } + + function parseBfRange(cMap, lexer) { + while (true) { + var obj = lexer.getObj(); + if (isEOF(obj)) { + break; + } + if (isCmd(obj, 'endbfrange')) { + return; + } + expectString(obj); + var low = strToInt(obj); + obj = lexer.getObj(); + expectString(obj); + var high = strToInt(obj); + obj = lexer.getObj(); + if (isInt(obj) || isString(obj)) { + var dstLow = isInt(obj) ? String.fromCharCode(obj) : obj; + cMap.mapBfRange(low, high, dstLow); + } else if (isCmd(obj, '[')) { + obj = lexer.getObj(); + var array = []; + while (!isCmd(obj, ']') && !isEOF(obj)) { + array.push(obj); + obj = lexer.getObj(); + } + cMap.mapBfRangeToArray(low, high, array); + } else { + break; + } + } + error('Invalid bf range.'); + } + + function parseCidChar(cMap, lexer) { + while (true) { + var obj = lexer.getObj(); + if (isEOF(obj)) { + break; + } + if (isCmd(obj, 'endcidchar')) { + return; + } + expectString(obj); + var src = strToInt(obj); + obj = lexer.getObj(); + expectInt(obj); + var dst = obj; + cMap.mapOne(src, dst); + } + } + + function parseCidRange(cMap, lexer) { + while (true) { + var obj = lexer.getObj(); + if (isEOF(obj)) { + break; + } + if (isCmd(obj, 'endcidrange')) { + return; + } + expectString(obj); + var low = strToInt(obj); + obj = lexer.getObj(); + expectString(obj); + var high = strToInt(obj); + obj = lexer.getObj(); + expectInt(obj); + var dstLow = obj; + cMap.mapCidRange(low, high, dstLow); + } + } + + function parseCodespaceRange(cMap, lexer) { + while (true) { + var obj = lexer.getObj(); + if (isEOF(obj)) { + break; + } + if (isCmd(obj, 'endcodespacerange')) { + return; + } + if (!isString(obj)) { + break; + } + var low = strToInt(obj); + obj = lexer.getObj(); + if (!isString(obj)) { + break; + } + var high = strToInt(obj); + cMap.addCodespaceRange(obj.length, low, high); + } + error('Invalid codespace range.'); + } + + function parseWMode(cMap, lexer) { + var obj = lexer.getObj(); + if (isInt(obj)) { + cMap.vertical = !!obj; + } + } + + function parseCMapName(cMap, lexer) { + var obj = lexer.getObj(); + if (isName(obj) && isString(obj.name)) { + cMap.name = obj.name; + } + } + + function parseCMap(cMap, lexer, builtInCMapParams, useCMap) { + var previous; + var embededUseCMap; + objLoop: while (true) { + var obj = lexer.getObj(); + if (isEOF(obj)) { + break; + } else if (isName(obj)) { + if (obj.name === 'WMode') { + parseWMode(cMap, lexer); + } else if (obj.name === 'CMapName') { + parseCMapName(cMap, lexer); + } + previous = obj; + } else if (isCmd(obj)) { + switch (obj.cmd) { + case 'endcmap': + break objLoop; + case 'usecmap': + if (isName(previous)) { + embededUseCMap = previous.name; + } + break; + case 'begincodespacerange': + parseCodespaceRange(cMap, lexer); + break; + case 'beginbfchar': + parseBfChar(cMap, lexer); + break; + case 'begincidchar': + parseCidChar(cMap, lexer); + break; + case 'beginbfrange': + parseBfRange(cMap, lexer); + break; + case 'begincidrange': + parseCidRange(cMap, lexer); + break; + } + } + } + + if (!useCMap && embededUseCMap) { + // Load the usecmap definition from the file only if there wasn't one + // specified. + useCMap = embededUseCMap; + } + if (useCMap) { + extendCMap(cMap, builtInCMapParams, useCMap); + } + } + + function extendCMap(cMap, builtInCMapParams, useCMap) { + cMap.useCMap = createBuiltInCMap(useCMap, builtInCMapParams); + // If there aren't any code space ranges defined clone all the parent ones + // into this cMap. + if (cMap.numCodespaceRanges === 0) { + var useCodespaceRanges = cMap.useCMap.codespaceRanges; + for (var i = 0; i < useCodespaceRanges.length; i++) { + cMap.codespaceRanges[i] = useCodespaceRanges[i].slice(); + } + cMap.numCodespaceRanges = cMap.useCMap.numCodespaceRanges; + } + // Merge the map into the current one, making sure not to override + // any previously defined entries. + cMap.useCMap.forEach(function(key, value) { + if (!cMap.contains(key)) { + cMap.mapOne(key, cMap.useCMap.lookup(key)); + } + }); + } + + function parseBinaryCMap(name, builtInCMapParams) { + var url = builtInCMapParams.url + name + '.bcmap'; + var cMap = new CMap(true); + new BinaryCMapReader().read(url, cMap, function (useCMap) { + extendCMap(cMap, builtInCMapParams, useCMap); + }); + return cMap; + } + + function createBuiltInCMap(name, builtInCMapParams) { + if (name === 'Identity-H') { + return new IdentityCMap(false, 2); + } else if (name === 'Identity-V') { + return new IdentityCMap(true, 2); + } + if (BUILT_IN_CMAPS.indexOf(name) === -1) { + error('Unknown cMap name: ' + name); + } + assert(builtInCMapParams, 'built-in cMap parameters are not provided'); + + if (builtInCMapParams.packed) { + return parseBinaryCMap(name, builtInCMapParams); + } + + var request = new XMLHttpRequest(); + var url = builtInCMapParams.url + name; + request.open('GET', url, false); + request.send(null); + if (!request.responseText) { + error('Unable to get cMap at: ' + url); + } + var cMap = new CMap(true); + var lexer = new Lexer(new StringStream(request.responseText)); + parseCMap(cMap, lexer, builtInCMapParams, null); + return cMap; + } + + return { + create: function (encoding, builtInCMapParams, useCMap) { + if (isName(encoding)) { + return createBuiltInCMap(encoding.name, builtInCMapParams); + } else if (isStream(encoding)) { + var cMap = new CMap(); + var lexer = new Lexer(encoding); + try { + parseCMap(cMap, lexer, builtInCMapParams, useCMap); + } catch (e) { + warn('Invalid CMap data. ' + e); + } + if (cMap.isIdentityCMap) { + return createBuiltInCMap(cMap.name, builtInCMapParams); + } + return cMap; + } + error('Encoding required.'); + } + }; +})(); + + +// Unicode Private Use Area +var PRIVATE_USE_OFFSET_START = 0xE000; +var PRIVATE_USE_OFFSET_END = 0xF8FF; +var SKIP_PRIVATE_USE_RANGE_F000_TO_F01F = false; + +// PDF Glyph Space Units are one Thousandth of a TextSpace Unit +// except for Type 3 fonts +var PDF_GLYPH_SPACE_UNITS = 1000; + +// Hinting is currently disabled due to unknown problems on windows +// in tracemonkey and various other pdfs with type1 fonts. +var HINTING_ENABLED = false; + +// Accented charactars are not displayed properly on windows, using this flag +// to control analysis of seac charstrings. +var SEAC_ANALYSIS_ENABLED = false; + +var FontFlags = { + FixedPitch: 1, + Serif: 2, + Symbolic: 4, + Script: 8, + Nonsymbolic: 32, + Italic: 64, + AllCap: 65536, + SmallCap: 131072, + ForceBold: 262144 +}; + +var Encodings = { + ExpertEncoding: ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 'space', 'exclamsmall', 'Hungarumlautsmall', '', 'dollaroldstyle', + 'dollarsuperior', 'ampersandsmall', 'Acutesmall', 'parenleftsuperior', + 'parenrightsuperior', 'twodotenleader', 'onedotenleader', 'comma', + 'hyphen', 'period', 'fraction', 'zerooldstyle', 'oneoldstyle', + 'twooldstyle', 'threeoldstyle', 'fouroldstyle', 'fiveoldstyle', + 'sixoldstyle', 'sevenoldstyle', 'eightoldstyle', 'nineoldstyle', 'colon', + 'semicolon', 'commasuperior', 'threequartersemdash', 'periodsuperior', + 'questionsmall', '', 'asuperior', 'bsuperior', 'centsuperior', 'dsuperior', + 'esuperior', '', '', 'isuperior', '', '', 'lsuperior', 'msuperior', + 'nsuperior', 'osuperior', '', '', 'rsuperior', 'ssuperior', 'tsuperior', + '', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'parenleftinferior', '', + 'parenrightinferior', 'Circumflexsmall', 'hyphensuperior', 'Gravesmall', + 'Asmall', 'Bsmall', 'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall', + 'Hsmall', 'Ismall', 'Jsmall', 'Ksmall', 'Lsmall', 'Msmall', 'Nsmall', + 'Osmall', 'Psmall', 'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall', + 'Vsmall', 'Wsmall', 'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary', + 'onefitted', 'rupiah', 'Tildesmall', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', 'exclamdownsmall', 'centoldstyle', 'Lslashsmall', + '', '', 'Scaronsmall', 'Zcaronsmall', 'Dieresissmall', 'Brevesmall', + 'Caronsmall', '', 'Dotaccentsmall', '', '', 'Macronsmall', '', '', + 'figuredash', 'hypheninferior', '', '', 'Ogoneksmall', 'Ringsmall', + 'Cedillasmall', '', '', '', 'onequarter', 'onehalf', 'threequarters', + 'questiondownsmall', 'oneeighth', 'threeeighths', 'fiveeighths', + 'seveneighths', 'onethird', 'twothirds', '', '', 'zerosuperior', + 'onesuperior', 'twosuperior', 'threesuperior', 'foursuperior', + 'fivesuperior', 'sixsuperior', 'sevensuperior', 'eightsuperior', + 'ninesuperior', 'zeroinferior', 'oneinferior', 'twoinferior', + 'threeinferior', 'fourinferior', 'fiveinferior', 'sixinferior', + 'seveninferior', 'eightinferior', 'nineinferior', 'centinferior', + 'dollarinferior', 'periodinferior', 'commainferior', 'Agravesmall', + 'Aacutesmall', 'Acircumflexsmall', 'Atildesmall', 'Adieresissmall', + 'Aringsmall', 'AEsmall', 'Ccedillasmall', 'Egravesmall', 'Eacutesmall', + 'Ecircumflexsmall', 'Edieresissmall', 'Igravesmall', 'Iacutesmall', + 'Icircumflexsmall', 'Idieresissmall', 'Ethsmall', 'Ntildesmall', + 'Ogravesmall', 'Oacutesmall', 'Ocircumflexsmall', 'Otildesmall', + 'Odieresissmall', 'OEsmall', 'Oslashsmall', 'Ugravesmall', 'Uacutesmall', + 'Ucircumflexsmall', 'Udieresissmall', 'Yacutesmall', 'Thornsmall', + 'Ydieresissmall'], + MacExpertEncoding: ['', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 'space', 'exclamsmall', 'Hungarumlautsmall', 'centoldstyle', + 'dollaroldstyle', 'dollarsuperior', 'ampersandsmall', 'Acutesmall', + 'parenleftsuperior', 'parenrightsuperior', 'twodotenleader', + 'onedotenleader', 'comma', 'hyphen', 'period', 'fraction', 'zerooldstyle', + 'oneoldstyle', 'twooldstyle', 'threeoldstyle', 'fouroldstyle', + 'fiveoldstyle', 'sixoldstyle', 'sevenoldstyle', 'eightoldstyle', + 'nineoldstyle', 'colon', 'semicolon', '', 'threequartersemdash', '', + 'questionsmall', '', '', '', '', 'Ethsmall', '', '', 'onequarter', + 'onehalf', 'threequarters', 'oneeighth', 'threeeighths', 'fiveeighths', + 'seveneighths', 'onethird', 'twothirds', '', '', '', '', '', '', 'ff', + 'fi', 'fl', 'ffi', 'ffl', 'parenleftinferior', '', 'parenrightinferior', + 'Circumflexsmall', 'hypheninferior', 'Gravesmall', 'Asmall', 'Bsmall', + 'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall', 'Hsmall', 'Ismall', + 'Jsmall', 'Ksmall', 'Lsmall', 'Msmall', 'Nsmall', 'Osmall', 'Psmall', + 'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall', 'Vsmall', 'Wsmall', + 'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary', 'onefitted', 'rupiah', + 'Tildesmall', '', '', 'asuperior', 'centsuperior', '', '', '', '', + 'Aacutesmall', 'Agravesmall', 'Acircumflexsmall', 'Adieresissmall', + 'Atildesmall', 'Aringsmall', 'Ccedillasmall', 'Eacutesmall', 'Egravesmall', + 'Ecircumflexsmall', 'Edieresissmall', 'Iacutesmall', 'Igravesmall', + 'Icircumflexsmall', 'Idieresissmall', 'Ntildesmall', 'Oacutesmall', + 'Ogravesmall', 'Ocircumflexsmall', 'Odieresissmall', 'Otildesmall', + 'Uacutesmall', 'Ugravesmall', 'Ucircumflexsmall', 'Udieresissmall', '', + 'eightsuperior', 'fourinferior', 'threeinferior', 'sixinferior', + 'eightinferior', 'seveninferior', 'Scaronsmall', '', 'centinferior', + 'twoinferior', '', 'Dieresissmall', '', 'Caronsmall', 'osuperior', + 'fiveinferior', '', 'commainferior', 'periodinferior', 'Yacutesmall', '', + 'dollarinferior', '', 'Thornsmall', '', 'nineinferior', 'zeroinferior', + 'Zcaronsmall', 'AEsmall', 'Oslashsmall', 'questiondownsmall', + 'oneinferior', 'Lslashsmall', '', '', '', '', '', '', 'Cedillasmall', '', + '', '', '', '', 'OEsmall', 'figuredash', 'hyphensuperior', '', '', '', '', + 'exclamdownsmall', '', 'Ydieresissmall', '', 'onesuperior', 'twosuperior', + 'threesuperior', 'foursuperior', 'fivesuperior', 'sixsuperior', + 'sevensuperior', 'ninesuperior', 'zerosuperior', '', 'esuperior', + 'rsuperior', 'tsuperior', '', '', 'isuperior', 'ssuperior', 'dsuperior', + '', '', '', '', '', 'lsuperior', 'Ogoneksmall', 'Brevesmall', + 'Macronsmall', 'bsuperior', 'nsuperior', 'msuperior', 'commasuperior', + 'periodsuperior', 'Dotaccentsmall', 'Ringsmall'], + MacRomanEncoding: ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent', + 'ampersand', 'quotesingle', 'parenleft', 'parenright', 'asterisk', 'plus', + 'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two', 'three', + 'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', + 'less', 'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F', + 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', + 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright', + 'asciicircum', 'underscore', 'grave', 'a', 'b', 'c', 'd', 'e', 'f', 'g', + 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', + 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde', '', + 'Adieresis', 'Aring', 'Ccedilla', 'Eacute', 'Ntilde', 'Odieresis', + 'Udieresis', 'aacute', 'agrave', 'acircumflex', 'adieresis', 'atilde', + 'aring', 'ccedilla', 'eacute', 'egrave', 'ecircumflex', 'edieresis', + 'iacute', 'igrave', 'icircumflex', 'idieresis', 'ntilde', 'oacute', + 'ograve', 'ocircumflex', 'odieresis', 'otilde', 'uacute', 'ugrave', + 'ucircumflex', 'udieresis', 'dagger', 'degree', 'cent', 'sterling', + 'section', 'bullet', 'paragraph', 'germandbls', 'registered', 'copyright', + 'trademark', 'acute', 'dieresis', 'notequal', 'AE', 'Oslash', 'infinity', + 'plusminus', 'lessequal', 'greaterequal', 'yen', 'mu', 'partialdiff', + 'summation', 'product', 'pi', 'integral', 'ordfeminine', 'ordmasculine', + 'Omega', 'ae', 'oslash', 'questiondown', 'exclamdown', 'logicalnot', + 'radical', 'florin', 'approxequal', 'Delta', 'guillemotleft', + 'guillemotright', 'ellipsis', 'space', 'Agrave', 'Atilde', 'Otilde', 'OE', + 'oe', 'endash', 'emdash', 'quotedblleft', 'quotedblright', 'quoteleft', + 'quoteright', 'divide', 'lozenge', 'ydieresis', 'Ydieresis', 'fraction', + 'currency', 'guilsinglleft', 'guilsinglright', 'fi', 'fl', 'daggerdbl', + 'periodcentered', 'quotesinglbase', 'quotedblbase', 'perthousand', + 'Acircumflex', 'Ecircumflex', 'Aacute', 'Edieresis', 'Egrave', 'Iacute', + 'Icircumflex', 'Idieresis', 'Igrave', 'Oacute', 'Ocircumflex', 'apple', + 'Ograve', 'Uacute', 'Ucircumflex', 'Ugrave', 'dotlessi', 'circumflex', + 'tilde', 'macron', 'breve', 'dotaccent', 'ring', 'cedilla', 'hungarumlaut', + 'ogonek', 'caron'], + StandardEncoding: ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent', + 'ampersand', 'quoteright', 'parenleft', 'parenright', 'asterisk', 'plus', + 'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two', 'three', + 'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', + 'less', 'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F', + 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', + 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright', + 'asciicircum', 'underscore', 'quoteleft', 'a', 'b', 'c', 'd', 'e', 'f', + 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', + 'v', 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'exclamdown', + 'cent', 'sterling', 'fraction', 'yen', 'florin', 'section', 'currency', + 'quotesingle', 'quotedblleft', 'guillemotleft', 'guilsinglleft', + 'guilsinglright', 'fi', 'fl', '', 'endash', 'dagger', 'daggerdbl', + 'periodcentered', '', 'paragraph', 'bullet', 'quotesinglbase', + 'quotedblbase', 'quotedblright', 'guillemotright', 'ellipsis', + 'perthousand', '', 'questiondown', '', 'grave', 'acute', 'circumflex', + 'tilde', 'macron', 'breve', 'dotaccent', 'dieresis', '', 'ring', 'cedilla', + '', 'hungarumlaut', 'ogonek', 'caron', 'emdash', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', 'AE', '', 'ordfeminine', '', '', + '', '', 'Lslash', 'Oslash', 'OE', 'ordmasculine', '', '', '', '', '', 'ae', + '', '', '', 'dotlessi', '', '', 'lslash', 'oslash', 'oe', 'germandbls'], + WinAnsiEncoding: ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent', + 'ampersand', 'quotesingle', 'parenleft', 'parenright', 'asterisk', 'plus', + 'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two', 'three', + 'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', + 'less', 'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F', + 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', + 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright', + 'asciicircum', 'underscore', 'grave', 'a', 'b', 'c', 'd', 'e', 'f', 'g', + 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', + 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde', + 'bullet', 'Euro', 'bullet', 'quotesinglbase', 'florin', 'quotedblbase', + 'ellipsis', 'dagger', 'daggerdbl', 'circumflex', 'perthousand', 'Scaron', + 'guilsinglleft', 'OE', 'bullet', 'Zcaron', 'bullet', 'bullet', 'quoteleft', + 'quoteright', 'quotedblleft', 'quotedblright', 'bullet', 'endash', + 'emdash', 'tilde', 'trademark', 'scaron', 'guilsinglright', 'oe', 'bullet', + 'zcaron', 'Ydieresis', 'space', 'exclamdown', 'cent', 'sterling', + 'currency', 'yen', 'brokenbar', 'section', 'dieresis', 'copyright', + 'ordfeminine', 'guillemotleft', 'logicalnot', 'hyphen', 'registered', + 'macron', 'degree', 'plusminus', 'twosuperior', 'threesuperior', 'acute', + 'mu', 'paragraph', 'periodcentered', 'cedilla', 'onesuperior', + 'ordmasculine', 'guillemotright', 'onequarter', 'onehalf', 'threequarters', + 'questiondown', 'Agrave', 'Aacute', 'Acircumflex', 'Atilde', 'Adieresis', + 'Aring', 'AE', 'Ccedilla', 'Egrave', 'Eacute', 'Ecircumflex', 'Edieresis', + 'Igrave', 'Iacute', 'Icircumflex', 'Idieresis', 'Eth', 'Ntilde', 'Ograve', + 'Oacute', 'Ocircumflex', 'Otilde', 'Odieresis', 'multiply', 'Oslash', + 'Ugrave', 'Uacute', 'Ucircumflex', 'Udieresis', 'Yacute', 'Thorn', + 'germandbls', 'agrave', 'aacute', 'acircumflex', 'atilde', 'adieresis', + 'aring', 'ae', 'ccedilla', 'egrave', 'eacute', 'ecircumflex', 'edieresis', + 'igrave', 'iacute', 'icircumflex', 'idieresis', 'eth', 'ntilde', 'ograve', + 'oacute', 'ocircumflex', 'otilde', 'odieresis', 'divide', 'oslash', + 'ugrave', 'uacute', 'ucircumflex', 'udieresis', 'yacute', 'thorn', + 'ydieresis'], + SymbolSetEncoding: ['', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 'space', 'exclam', 'universal', 'numbersign', 'existential', 'percent', + 'ampersand', 'suchthat', 'parenleft', 'parenright', 'asteriskmath', 'plus', + 'comma', 'minus', 'period', 'slash', 'zero', 'one', 'two', 'three', 'four', + 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', 'less', + 'equal', 'greater', 'question', 'congruent', 'Alpha', 'Beta', 'Chi', + 'Delta', 'Epsilon', 'Phi', 'Gamma', 'Eta', 'Iota', 'theta1', 'Kappa', + 'Lambda', 'Mu', 'Nu', 'Omicron', 'Pi', 'Theta', 'Rho', 'Sigma', 'Tau', + 'Upsilon', 'sigma1', 'Omega', 'Xi', 'Psi', 'Zeta', 'bracketleft', + 'therefore', 'bracketright', 'perpendicular', 'underscore', 'radicalex', + 'alpha', 'beta', 'chi', 'delta', 'epsilon', 'phi', 'gamma', 'eta', 'iota', + 'phi1', 'kappa', 'lambda', 'mu', 'nu', 'omicron', 'pi', 'theta', 'rho', + 'sigma', 'tau', 'upsilon', 'omega1', 'omega', 'xi', 'psi', 'zeta', + 'braceleft', 'bar', 'braceright', 'similar', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', 'Euro', 'Upsilon1', 'minute', 'lessequal', + 'fraction', 'infinity', 'florin', 'club', 'diamond', 'heart', 'spade', + 'arrowboth', 'arrowleft', 'arrowup', 'arrowright', 'arrowdown', 'degree', + 'plusminus', 'second', 'greaterequal', 'multiply', 'proportional', + 'partialdiff', 'bullet', 'divide', 'notequal', 'equivalence', + 'approxequal', 'ellipsis', 'arrowvertex', 'arrowhorizex', 'carriagereturn', + 'aleph', 'Ifraktur', 'Rfraktur', 'weierstrass', 'circlemultiply', + 'circleplus', 'emptyset', 'intersection', 'union', 'propersuperset', + 'reflexsuperset', 'notsubset', 'propersubset', 'reflexsubset', 'element', + 'notelement', 'angle', 'gradient', 'registerserif', 'copyrightserif', + 'trademarkserif', 'product', 'radical', 'dotmath', 'logicalnot', + 'logicaland', 'logicalor', 'arrowdblboth', 'arrowdblleft', 'arrowdblup', + 'arrowdblright', 'arrowdbldown', 'lozenge', 'angleleft', 'registersans', + 'copyrightsans', 'trademarksans', 'summation', 'parenlefttp', + 'parenleftex', 'parenleftbt', 'bracketlefttp', 'bracketleftex', + 'bracketleftbt', 'bracelefttp', 'braceleftmid', 'braceleftbt', 'braceex', + '', 'angleright', 'integral', 'integraltp', 'integralex', 'integralbt', + 'parenrighttp', 'parenrightex', 'parenrightbt', 'bracketrighttp', + 'bracketrightex', 'bracketrightbt', 'bracerighttp', 'bracerightmid', + 'bracerightbt'], + ZapfDingbatsEncoding: ['', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 'space', 'a1', 'a2', 'a202', 'a3', 'a4', 'a5', 'a119', 'a118', 'a117', + 'a11', 'a12', 'a13', 'a14', 'a15', 'a16', 'a105', 'a17', 'a18', 'a19', + 'a20', 'a21', 'a22', 'a23', 'a24', 'a25', 'a26', 'a27', 'a28', 'a6', 'a7', + 'a8', 'a9', 'a10', 'a29', 'a30', 'a31', 'a32', 'a33', 'a34', 'a35', 'a36', + 'a37', 'a38', 'a39', 'a40', 'a41', 'a42', 'a43', 'a44', 'a45', 'a46', + 'a47', 'a48', 'a49', 'a50', 'a51', 'a52', 'a53', 'a54', 'a55', 'a56', + 'a57', 'a58', 'a59', 'a60', 'a61', 'a62', 'a63', 'a64', 'a65', 'a66', + 'a67', 'a68', 'a69', 'a70', 'a71', 'a72', 'a73', 'a74', 'a203', 'a75', + 'a204', 'a76', 'a77', 'a78', 'a79', 'a81', 'a82', 'a83', 'a84', 'a97', + 'a98', 'a99', 'a100', '', 'a89', 'a90', 'a93', 'a94', 'a91', 'a92', 'a205', + 'a85', 'a206', 'a86', 'a87', 'a88', 'a95', 'a96', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', 'a101', 'a102', 'a103', + 'a104', 'a106', 'a107', 'a108', 'a112', 'a111', 'a110', 'a109', 'a120', + 'a121', 'a122', 'a123', 'a124', 'a125', 'a126', 'a127', 'a128', 'a129', + 'a130', 'a131', 'a132', 'a133', 'a134', 'a135', 'a136', 'a137', 'a138', + 'a139', 'a140', 'a141', 'a142', 'a143', 'a144', 'a145', 'a146', 'a147', + 'a148', 'a149', 'a150', 'a151', 'a152', 'a153', 'a154', 'a155', 'a156', + 'a157', 'a158', 'a159', 'a160', 'a161', 'a163', 'a164', 'a196', 'a165', + 'a192', 'a166', 'a167', 'a168', 'a169', 'a170', 'a171', 'a172', 'a173', + 'a162', 'a174', 'a175', 'a176', 'a177', 'a178', 'a179', 'a193', 'a180', + 'a199', 'a181', 'a200', 'a182', '', 'a201', 'a183', 'a184', 'a197', 'a185', + 'a194', 'a198', 'a186', 'a195', 'a187', 'a188', 'a189', 'a190', 'a191'] +}; + +/** + * Hold a map of decoded fonts and of the standard fourteen Type1 + * fonts and their acronyms. + */ +var stdFontMap = { + 'ArialNarrow': 'Helvetica', + 'ArialNarrow-Bold': 'Helvetica-Bold', + 'ArialNarrow-BoldItalic': 'Helvetica-BoldOblique', + 'ArialNarrow-Italic': 'Helvetica-Oblique', + 'ArialBlack': 'Helvetica', + 'ArialBlack-Bold': 'Helvetica-Bold', + 'ArialBlack-BoldItalic': 'Helvetica-BoldOblique', + 'ArialBlack-Italic': 'Helvetica-Oblique', + 'Arial': 'Helvetica', + 'Arial-Bold': 'Helvetica-Bold', + 'Arial-BoldItalic': 'Helvetica-BoldOblique', + 'Arial-Italic': 'Helvetica-Oblique', + 'Arial-BoldItalicMT': 'Helvetica-BoldOblique', + 'Arial-BoldMT': 'Helvetica-Bold', + 'Arial-ItalicMT': 'Helvetica-Oblique', + 'ArialMT': 'Helvetica', + 'Courier-Bold': 'Courier-Bold', + 'Courier-BoldItalic': 'Courier-BoldOblique', + 'Courier-Italic': 'Courier-Oblique', + 'CourierNew': 'Courier', + 'CourierNew-Bold': 'Courier-Bold', + 'CourierNew-BoldItalic': 'Courier-BoldOblique', + 'CourierNew-Italic': 'Courier-Oblique', + 'CourierNewPS-BoldItalicMT': 'Courier-BoldOblique', + 'CourierNewPS-BoldMT': 'Courier-Bold', + 'CourierNewPS-ItalicMT': 'Courier-Oblique', + 'CourierNewPSMT': 'Courier', + 'Helvetica': 'Helvetica', + 'Helvetica-Bold': 'Helvetica-Bold', + 'Helvetica-BoldItalic': 'Helvetica-BoldOblique', + 'Helvetica-BoldOblique': 'Helvetica-BoldOblique', + 'Helvetica-Italic': 'Helvetica-Oblique', + 'Helvetica-Oblique':'Helvetica-Oblique', + 'Symbol-Bold': 'Symbol', + 'Symbol-BoldItalic': 'Symbol', + 'Symbol-Italic': 'Symbol', + 'TimesNewRoman': 'Times-Roman', + 'TimesNewRoman-Bold': 'Times-Bold', + 'TimesNewRoman-BoldItalic': 'Times-BoldItalic', + 'TimesNewRoman-Italic': 'Times-Italic', + 'TimesNewRomanPS': 'Times-Roman', + 'TimesNewRomanPS-Bold': 'Times-Bold', + 'TimesNewRomanPS-BoldItalic': 'Times-BoldItalic', + 'TimesNewRomanPS-BoldItalicMT': 'Times-BoldItalic', + 'TimesNewRomanPS-BoldMT': 'Times-Bold', + 'TimesNewRomanPS-Italic': 'Times-Italic', + 'TimesNewRomanPS-ItalicMT': 'Times-Italic', + 'TimesNewRomanPSMT': 'Times-Roman', + 'TimesNewRomanPSMT-Bold': 'Times-Bold', + 'TimesNewRomanPSMT-BoldItalic': 'Times-BoldItalic', + 'TimesNewRomanPSMT-Italic': 'Times-Italic' +}; + +/** + * Holds the map of the non-standard fonts that might be included as a standard + * fonts without glyph data. + */ +var nonStdFontMap = { + 'CenturyGothic': 'Helvetica', + 'CenturyGothic-Bold': 'Helvetica-Bold', + 'CenturyGothic-BoldItalic': 'Helvetica-BoldOblique', + 'CenturyGothic-Italic': 'Helvetica-Oblique', + 'ComicSansMS': 'Comic Sans MS', + 'ComicSansMS-Bold': 'Comic Sans MS-Bold', + 'ComicSansMS-BoldItalic': 'Comic Sans MS-BoldItalic', + 'ComicSansMS-Italic': 'Comic Sans MS-Italic', + 'LucidaConsole': 'Courier', + 'LucidaConsole-Bold': 'Courier-Bold', + 'LucidaConsole-BoldItalic': 'Courier-BoldOblique', + 'LucidaConsole-Italic': 'Courier-Oblique', + 'MS-Gothic': 'MS Gothic', + 'MS-Gothic-Bold': 'MS Gothic-Bold', + 'MS-Gothic-BoldItalic': 'MS Gothic-BoldItalic', + 'MS-Gothic-Italic': 'MS Gothic-Italic', + 'MS-Mincho': 'MS Mincho', + 'MS-Mincho-Bold': 'MS Mincho-Bold', + 'MS-Mincho-BoldItalic': 'MS Mincho-BoldItalic', + 'MS-Mincho-Italic': 'MS Mincho-Italic', + 'MS-PGothic': 'MS PGothic', + 'MS-PGothic-Bold': 'MS PGothic-Bold', + 'MS-PGothic-BoldItalic': 'MS PGothic-BoldItalic', + 'MS-PGothic-Italic': 'MS PGothic-Italic', + 'MS-PMincho': 'MS PMincho', + 'MS-PMincho-Bold': 'MS PMincho-Bold', + 'MS-PMincho-BoldItalic': 'MS PMincho-BoldItalic', + 'MS-PMincho-Italic': 'MS PMincho-Italic', + 'Wingdings': 'ZapfDingbats' +}; + +var serifFonts = { + 'Adobe Jenson': true, 'Adobe Text': true, 'Albertus': true, + 'Aldus': true, 'Alexandria': true, 'Algerian': true, + 'American Typewriter': true, 'Antiqua': true, 'Apex': true, + 'Arno': true, 'Aster': true, 'Aurora': true, + 'Baskerville': true, 'Bell': true, 'Bembo': true, + 'Bembo Schoolbook': true, 'Benguiat': true, 'Berkeley Old Style': true, + 'Bernhard Modern': true, 'Berthold City': true, 'Bodoni': true, + 'Bauer Bodoni': true, 'Book Antiqua': true, 'Bookman': true, + 'Bordeaux Roman': true, 'Californian FB': true, 'Calisto': true, + 'Calvert': true, 'Capitals': true, 'Cambria': true, + 'Cartier': true, 'Caslon': true, 'Catull': true, + 'Centaur': true, 'Century Old Style': true, 'Century Schoolbook': true, + 'Chaparral': true, 'Charis SIL': true, 'Cheltenham': true, + 'Cholla Slab': true, 'Clarendon': true, 'Clearface': true, + 'Cochin': true, 'Colonna': true, 'Computer Modern': true, + 'Concrete Roman': true, 'Constantia': true, 'Cooper Black': true, + 'Corona': true, 'Ecotype': true, 'Egyptienne': true, + 'Elephant': true, 'Excelsior': true, 'Fairfield': true, + 'FF Scala': true, 'Folkard': true, 'Footlight': true, + 'FreeSerif': true, 'Friz Quadrata': true, 'Garamond': true, + 'Gentium': true, 'Georgia': true, 'Gloucester': true, + 'Goudy Old Style': true, 'Goudy Schoolbook': true, 'Goudy Pro Font': true, + 'Granjon': true, 'Guardian Egyptian': true, 'Heather': true, + 'Hercules': true, 'High Tower Text': true, 'Hiroshige': true, + 'Hoefler Text': true, 'Humana Serif': true, 'Imprint': true, + 'Ionic No. 5': true, 'Janson': true, 'Joanna': true, + 'Korinna': true, 'Lexicon': true, 'Liberation Serif': true, + 'Linux Libertine': true, 'Literaturnaya': true, 'Lucida': true, + 'Lucida Bright': true, 'Melior': true, 'Memphis': true, + 'Miller': true, 'Minion': true, 'Modern': true, + 'Mona Lisa': true, 'Mrs Eaves': true, 'MS Serif': true, + 'Museo Slab': true, 'New York': true, 'Nimbus Roman': true, + 'NPS Rawlinson Roadway': true, 'Palatino': true, 'Perpetua': true, + 'Plantin': true, 'Plantin Schoolbook': true, 'Playbill': true, + 'Poor Richard': true, 'Rawlinson Roadway': true, 'Renault': true, + 'Requiem': true, 'Rockwell': true, 'Roman': true, + 'Rotis Serif': true, 'Sabon': true, 'Scala': true, + 'Seagull': true, 'Sistina': true, 'Souvenir': true, + 'STIX': true, 'Stone Informal': true, 'Stone Serif': true, + 'Sylfaen': true, 'Times': true, 'Trajan': true, + 'Trinité': true, 'Trump Mediaeval': true, 'Utopia': true, + 'Vale Type': true, 'Bitstream Vera': true, 'Vera Serif': true, + 'Versailles': true, 'Wanted': true, 'Weiss': true, + 'Wide Latin': true, 'Windsor': true, 'XITS': true +}; + +var symbolsFonts = { + 'Dingbats': true, 'Symbol': true, 'ZapfDingbats': true +}; + +// Glyph map for well-known standard fonts. Sometimes Ghostscript uses CID fonts +// but does not embed the CID to GID mapping. The mapping is incomplete for all +// glyphs, but common for some set of the standard fonts. +var GlyphMapForStandardFonts = { + '2': 10, '3': 32, '4': 33, '5': 34, '6': 35, '7': 36, '8': 37, '9': 38, + '10': 39, '11': 40, '12': 41, '13': 42, '14': 43, '15': 44, '16': 45, + '17': 46, '18': 47, '19': 48, '20': 49, '21': 50, '22': 51, '23': 52, + '24': 53, '25': 54, '26': 55, '27': 56, '28': 57, '29': 58, '30': 894, + '31': 60, '32': 61, '33': 62, '34': 63, '35': 64, '36': 65, '37': 66, + '38': 67, '39': 68, '40': 69, '41': 70, '42': 71, '43': 72, '44': 73, + '45': 74, '46': 75, '47': 76, '48': 77, '49': 78, '50': 79, '51': 80, + '52': 81, '53': 82, '54': 83, '55': 84, '56': 85, '57': 86, '58': 87, + '59': 88, '60': 89, '61': 90, '62': 91, '63': 92, '64': 93, '65': 94, + '66': 95, '67': 96, '68': 97, '69': 98, '70': 99, '71': 100, '72': 101, + '73': 102, '74': 103, '75': 104, '76': 105, '77': 106, '78': 107, '79': 108, + '80': 109, '81': 110, '82': 111, '83': 112, '84': 113, '85': 114, '86': 115, + '87': 116, '88': 117, '89': 118, '90': 119, '91': 120, '92': 121, '93': 122, + '94': 123, '95': 124, '96': 125, '97': 126, '98': 196, '99': 197, '100': 199, + '101': 201, '102': 209, '103': 214, '104': 220, '105': 225, '106': 224, + '107': 226, '108': 228, '109': 227, '110': 229, '111': 231, '112': 233, + '113': 232, '114': 234, '115': 235, '116': 237, '117': 236, '118': 238, + '119': 239, '120': 241, '121': 243, '122': 242, '123': 244, '124': 246, + '125': 245, '126': 250, '127': 249, '128': 251, '129': 252, '130': 8224, + '131': 176, '132': 162, '133': 163, '134': 167, '135': 8226, '136': 182, + '137': 223, '138': 174, '139': 169, '140': 8482, '141': 180, '142': 168, + '143': 8800, '144': 198, '145': 216, '146': 8734, '147': 177, '148': 8804, + '149': 8805, '150': 165, '151': 181, '152': 8706, '153': 8721, '154': 8719, + '156': 8747, '157': 170, '158': 186, '159': 8486, '160': 230, '161': 248, + '162': 191, '163': 161, '164': 172, '165': 8730, '166': 402, '167': 8776, + '168': 8710, '169': 171, '170': 187, '171': 8230, '210': 218, '223': 711, + '224': 321, '225': 322, '227': 353, '229': 382, '234': 253, '252': 263, + '253': 268, '254': 269, '258': 258, '260': 260, '261': 261, '265': 280, + '266': 281, '268': 283, '269': 313, '275': 323, '276': 324, '278': 328, + '284': 345, '285': 346, '286': 347, '292': 367, '295': 377, '296': 378, + '298': 380, '305': 963, + '306': 964, '307': 966, '308': 8215, '309': 8252, '310': 8319, '311': 8359, + '312': 8592, '313': 8593, '337': 9552, '493': 1039, '494': 1040, '705': 1524, + '706': 8362, '710': 64288, '711': 64298, '759': 1617, '761': 1776, + '763': 1778, '775': 1652, '777': 1764, '778': 1780, '779': 1781, '780': 1782, + '782': 771, '783': 64726, '786': 8363, '788': 8532, '790': 768, '791': 769, + '792': 768, '795': 803, '797': 64336, '798': 64337, '799': 64342, + '800': 64343, '801': 64344, '802': 64345, '803': 64362, '804': 64363, + '805': 64364, '2424': 7821, '2425': 7822, '2426': 7823, '2427': 7824, + '2428': 7825, '2429': 7826, '2430': 7827, '2433': 7682, '2678': 8045, + '2679': 8046, '2830': 1552, '2838': 686, '2840': 751, '2842': 753, + '2843': 754, '2844': 755, '2846': 757, '2856': 767, '2857': 848, '2858': 849, + '2862': 853, '2863': 854, '2864': 855, '2865': 861, '2866': 862, '2906': 7460, + '2908': 7462, '2909': 7463, '2910': 7464, '2912': 7466, '2913': 7467, + '2914': 7468, '2916': 7470, '2917': 7471, '2918': 7472, '2920': 7474, + '2921': 7475, '2922': 7476, '2924': 7478, '2925': 7479, '2926': 7480, + '2928': 7482, '2929': 7483, '2930': 7484, '2932': 7486, '2933': 7487, + '2934': 7488, '2936': 7490, '2937': 7491, '2938': 7492, '2940': 7494, + '2941': 7495, '2942': 7496, '2944': 7498, '2946': 7500, '2948': 7502, + '2950': 7504, '2951': 7505, '2952': 7506, '2954': 7508, '2955': 7509, + '2956': 7510, '2958': 7512, '2959': 7513, '2960': 7514, '2962': 7516, + '2963': 7517, '2964': 7518, '2966': 7520, '2967': 7521, '2968': 7522, + '2970': 7524, '2971': 7525, '2972': 7526, '2974': 7528, '2975': 7529, + '2976': 7530, '2978': 1537, '2979': 1538, '2980': 1539, '2982': 1549, + '2983': 1551, '2984': 1552, '2986': 1554, '2987': 1555, '2988': 1556, + '2990': 1623, '2991': 1624, '2995': 1775, '2999': 1791, '3002': 64290, + '3003': 64291, '3004': 64292, '3006': 64294, '3007': 64295, '3008': 64296, + '3011': 1900, '3014': 8223, '3015': 8244, '3017': 7532, '3018': 7533, + '3019': 7534, '3075': 7590, '3076': 7591, '3079': 7594, '3080': 7595, + '3083': 7598, '3084': 7599, '3087': 7602, '3088': 7603, '3091': 7606, + '3092': 7607, '3095': 7610, '3096': 7611, '3099': 7614, '3100': 7615, + '3103': 7618, '3104': 7619, '3107': 8337, '3108': 8338, '3116': 1884, + '3119': 1885, '3120': 1885, '3123': 1886, '3124': 1886, '3127': 1887, + '3128': 1887, '3131': 1888, '3132': 1888, '3135': 1889, '3136': 1889, + '3139': 1890, '3140': 1890, '3143': 1891, '3144': 1891, '3147': 1892, + '3148': 1892, '3153': 580, '3154': 581, '3157': 584, '3158': 585, '3161': 588, + '3162': 589, '3165': 891, '3166': 892, '3169': 1274, '3170': 1275, + '3173': 1278, '3174': 1279, '3181': 7622, '3182': 7623, '3282': 11799, + '3316': 578, '3379': 42785, '3393': 1159, '3416': 8377 +}; + +// Some characters, e.g. copyrightserif, are mapped to the private use area and +// might not be displayed using standard fonts. Mapping/hacking well-known chars +// to the similar equivalents in the normal characters range. +var SpecialPUASymbols = { + '63721': 0x00A9, // copyrightsans (0xF8E9) => copyright + '63193': 0x00A9, // copyrightserif (0xF6D9) => copyright + '63720': 0x00AE, // registersans (0xF8E8) => registered + '63194': 0x00AE, // registerserif (0xF6DA) => registered + '63722': 0x2122, // trademarksans (0xF8EA) => trademark + '63195': 0x2122, // trademarkserif (0xF6DB) => trademark + '63729': 0x23A7, // bracelefttp (0xF8F1) + '63730': 0x23A8, // braceleftmid (0xF8F2) + '63731': 0x23A9, // braceleftbt (0xF8F3) + '63740': 0x23AB, // bracerighttp (0xF8FC) + '63741': 0x23AC, // bracerightmid (0xF8FD) + '63742': 0x23AD, // bracerightbt (0xF8FE) + '63726': 0x23A1, // bracketlefttp (0xF8EE) + '63727': 0x23A2, // bracketleftex (0xF8EF) + '63728': 0x23A3, // bracketleftbt (0xF8F0) + '63737': 0x23A4, // bracketrighttp (0xF8F9) + '63738': 0x23A5, // bracketrightex (0xF8FA) + '63739': 0x23A6, // bracketrightbt (0xF8FB) + '63723': 0x239B, // parenlefttp (0xF8EB) + '63724': 0x239C, // parenleftex (0xF8EC) + '63725': 0x239D, // parenleftbt (0xF8ED) + '63734': 0x239E, // parenrighttp (0xF8F6) + '63735': 0x239F, // parenrightex (0xF8F7) + '63736': 0x23A0, // parenrightbt (0xF8F8) +}; +function mapSpecialUnicodeValues(code) { + if (code >= 0xFFF0 && code <= 0xFFFF) { // Specials unicode block. + return 0; + } else if (code >= 0xF600 && code <= 0xF8FF) { + return (SpecialPUASymbols[code] || code); + } + return code; +} + +var UnicodeRanges = [ + { 'begin': 0x0000, 'end': 0x007F }, // Basic Latin + { 'begin': 0x0080, 'end': 0x00FF }, // Latin-1 Supplement + { 'begin': 0x0100, 'end': 0x017F }, // Latin Extended-A + { 'begin': 0x0180, 'end': 0x024F }, // Latin Extended-B + { 'begin': 0x0250, 'end': 0x02AF }, // IPA Extensions + { 'begin': 0x02B0, 'end': 0x02FF }, // Spacing Modifier Letters + { 'begin': 0x0300, 'end': 0x036F }, // Combining Diacritical Marks + { 'begin': 0x0370, 'end': 0x03FF }, // Greek and Coptic + { 'begin': 0x2C80, 'end': 0x2CFF }, // Coptic + { 'begin': 0x0400, 'end': 0x04FF }, // Cyrillic + { 'begin': 0x0530, 'end': 0x058F }, // Armenian + { 'begin': 0x0590, 'end': 0x05FF }, // Hebrew + { 'begin': 0xA500, 'end': 0xA63F }, // Vai + { 'begin': 0x0600, 'end': 0x06FF }, // Arabic + { 'begin': 0x07C0, 'end': 0x07FF }, // NKo + { 'begin': 0x0900, 'end': 0x097F }, // Devanagari + { 'begin': 0x0980, 'end': 0x09FF }, // Bengali + { 'begin': 0x0A00, 'end': 0x0A7F }, // Gurmukhi + { 'begin': 0x0A80, 'end': 0x0AFF }, // Gujarati + { 'begin': 0x0B00, 'end': 0x0B7F }, // Oriya + { 'begin': 0x0B80, 'end': 0x0BFF }, // Tamil + { 'begin': 0x0C00, 'end': 0x0C7F }, // Telugu + { 'begin': 0x0C80, 'end': 0x0CFF }, // Kannada + { 'begin': 0x0D00, 'end': 0x0D7F }, // Malayalam + { 'begin': 0x0E00, 'end': 0x0E7F }, // Thai + { 'begin': 0x0E80, 'end': 0x0EFF }, // Lao + { 'begin': 0x10A0, 'end': 0x10FF }, // Georgian + { 'begin': 0x1B00, 'end': 0x1B7F }, // Balinese + { 'begin': 0x1100, 'end': 0x11FF }, // Hangul Jamo + { 'begin': 0x1E00, 'end': 0x1EFF }, // Latin Extended Additional + { 'begin': 0x1F00, 'end': 0x1FFF }, // Greek Extended + { 'begin': 0x2000, 'end': 0x206F }, // General Punctuation + { 'begin': 0x2070, 'end': 0x209F }, // Superscripts And Subscripts + { 'begin': 0x20A0, 'end': 0x20CF }, // Currency Symbol + { 'begin': 0x20D0, 'end': 0x20FF }, // Combining Diacritical Marks For Symbols + { 'begin': 0x2100, 'end': 0x214F }, // Letterlike Symbols + { 'begin': 0x2150, 'end': 0x218F }, // Number Forms + { 'begin': 0x2190, 'end': 0x21FF }, // Arrows + { 'begin': 0x2200, 'end': 0x22FF }, // Mathematical Operators + { 'begin': 0x2300, 'end': 0x23FF }, // Miscellaneous Technical + { 'begin': 0x2400, 'end': 0x243F }, // Control Pictures + { 'begin': 0x2440, 'end': 0x245F }, // Optical Character Recognition + { 'begin': 0x2460, 'end': 0x24FF }, // Enclosed Alphanumerics + { 'begin': 0x2500, 'end': 0x257F }, // Box Drawing + { 'begin': 0x2580, 'end': 0x259F }, // Block Elements + { 'begin': 0x25A0, 'end': 0x25FF }, // Geometric Shapes + { 'begin': 0x2600, 'end': 0x26FF }, // Miscellaneous Symbols + { 'begin': 0x2700, 'end': 0x27BF }, // Dingbats + { 'begin': 0x3000, 'end': 0x303F }, // CJK Symbols And Punctuation + { 'begin': 0x3040, 'end': 0x309F }, // Hiragana + { 'begin': 0x30A0, 'end': 0x30FF }, // Katakana + { 'begin': 0x3100, 'end': 0x312F }, // Bopomofo + { 'begin': 0x3130, 'end': 0x318F }, // Hangul Compatibility Jamo + { 'begin': 0xA840, 'end': 0xA87F }, // Phags-pa + { 'begin': 0x3200, 'end': 0x32FF }, // Enclosed CJK Letters And Months + { 'begin': 0x3300, 'end': 0x33FF }, // CJK Compatibility + { 'begin': 0xAC00, 'end': 0xD7AF }, // Hangul Syllables + { 'begin': 0xD800, 'end': 0xDFFF }, // Non-Plane 0 * + { 'begin': 0x10900, 'end': 0x1091F }, // Phoenicia + { 'begin': 0x4E00, 'end': 0x9FFF }, // CJK Unified Ideographs + { 'begin': 0xE000, 'end': 0xF8FF }, // Private Use Area (plane 0) + { 'begin': 0x31C0, 'end': 0x31EF }, // CJK Strokes + { 'begin': 0xFB00, 'end': 0xFB4F }, // Alphabetic Presentation Forms + { 'begin': 0xFB50, 'end': 0xFDFF }, // Arabic Presentation Forms-A + { 'begin': 0xFE20, 'end': 0xFE2F }, // Combining Half Marks + { 'begin': 0xFE10, 'end': 0xFE1F }, // Vertical Forms + { 'begin': 0xFE50, 'end': 0xFE6F }, // Small Form Variants + { 'begin': 0xFE70, 'end': 0xFEFF }, // Arabic Presentation Forms-B + { 'begin': 0xFF00, 'end': 0xFFEF }, // Halfwidth And Fullwidth Forms + { 'begin': 0xFFF0, 'end': 0xFFFF }, // Specials + { 'begin': 0x0F00, 'end': 0x0FFF }, // Tibetan + { 'begin': 0x0700, 'end': 0x074F }, // Syriac + { 'begin': 0x0780, 'end': 0x07BF }, // Thaana + { 'begin': 0x0D80, 'end': 0x0DFF }, // Sinhala + { 'begin': 0x1000, 'end': 0x109F }, // Myanmar + { 'begin': 0x1200, 'end': 0x137F }, // Ethiopic + { 'begin': 0x13A0, 'end': 0x13FF }, // Cherokee + { 'begin': 0x1400, 'end': 0x167F }, // Unified Canadian Aboriginal Syllabics + { 'begin': 0x1680, 'end': 0x169F }, // Ogham + { 'begin': 0x16A0, 'end': 0x16FF }, // Runic + { 'begin': 0x1780, 'end': 0x17FF }, // Khmer + { 'begin': 0x1800, 'end': 0x18AF }, // Mongolian + { 'begin': 0x2800, 'end': 0x28FF }, // Braille Patterns + { 'begin': 0xA000, 'end': 0xA48F }, // Yi Syllables + { 'begin': 0x1700, 'end': 0x171F }, // Tagalog + { 'begin': 0x10300, 'end': 0x1032F }, // Old Italic + { 'begin': 0x10330, 'end': 0x1034F }, // Gothic + { 'begin': 0x10400, 'end': 0x1044F }, // Deseret + { 'begin': 0x1D000, 'end': 0x1D0FF }, // Byzantine Musical Symbols + { 'begin': 0x1D400, 'end': 0x1D7FF }, // Mathematical Alphanumeric Symbols + { 'begin': 0xFF000, 'end': 0xFFFFD }, // Private Use (plane 15) + { 'begin': 0xFE00, 'end': 0xFE0F }, // Variation Selectors + { 'begin': 0xE0000, 'end': 0xE007F }, // Tags + { 'begin': 0x1900, 'end': 0x194F }, // Limbu + { 'begin': 0x1950, 'end': 0x197F }, // Tai Le + { 'begin': 0x1980, 'end': 0x19DF }, // New Tai Lue + { 'begin': 0x1A00, 'end': 0x1A1F }, // Buginese + { 'begin': 0x2C00, 'end': 0x2C5F }, // Glagolitic + { 'begin': 0x2D30, 'end': 0x2D7F }, // Tifinagh + { 'begin': 0x4DC0, 'end': 0x4DFF }, // Yijing Hexagram Symbols + { 'begin': 0xA800, 'end': 0xA82F }, // Syloti Nagri + { 'begin': 0x10000, 'end': 0x1007F }, // Linear B Syllabary + { 'begin': 0x10140, 'end': 0x1018F }, // Ancient Greek Numbers + { 'begin': 0x10380, 'end': 0x1039F }, // Ugaritic + { 'begin': 0x103A0, 'end': 0x103DF }, // Old Persian + { 'begin': 0x10450, 'end': 0x1047F }, // Shavian + { 'begin': 0x10480, 'end': 0x104AF }, // Osmanya + { 'begin': 0x10800, 'end': 0x1083F }, // Cypriot Syllabary + { 'begin': 0x10A00, 'end': 0x10A5F }, // Kharoshthi + { 'begin': 0x1D300, 'end': 0x1D35F }, // Tai Xuan Jing Symbols + { 'begin': 0x12000, 'end': 0x123FF }, // Cuneiform + { 'begin': 0x1D360, 'end': 0x1D37F }, // Counting Rod Numerals + { 'begin': 0x1B80, 'end': 0x1BBF }, // Sundanese + { 'begin': 0x1C00, 'end': 0x1C4F }, // Lepcha + { 'begin': 0x1C50, 'end': 0x1C7F }, // Ol Chiki + { 'begin': 0xA880, 'end': 0xA8DF }, // Saurashtra + { 'begin': 0xA900, 'end': 0xA92F }, // Kayah Li + { 'begin': 0xA930, 'end': 0xA95F }, // Rejang + { 'begin': 0xAA00, 'end': 0xAA5F }, // Cham + { 'begin': 0x10190, 'end': 0x101CF }, // Ancient Symbols + { 'begin': 0x101D0, 'end': 0x101FF }, // Phaistos Disc + { 'begin': 0x102A0, 'end': 0x102DF }, // Carian + { 'begin': 0x1F030, 'end': 0x1F09F } // Domino Tiles +]; + +var MacStandardGlyphOrdering = [ + '.notdef', '.null', 'nonmarkingreturn', 'space', 'exclam', 'quotedbl', + 'numbersign', 'dollar', 'percent', 'ampersand', 'quotesingle', 'parenleft', + 'parenright', 'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash', + 'zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', + 'nine', 'colon', 'semicolon', 'less', 'equal', 'greater', 'question', 'at', + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', + 'backslash', 'bracketright', 'asciicircum', 'underscore', 'grave', 'a', 'b', + 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', + 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', + 'asciitilde', 'Adieresis', 'Aring', 'Ccedilla', 'Eacute', 'Ntilde', + 'Odieresis', 'Udieresis', 'aacute', 'agrave', 'acircumflex', 'adieresis', + 'atilde', 'aring', 'ccedilla', 'eacute', 'egrave', 'ecircumflex', 'edieresis', + 'iacute', 'igrave', 'icircumflex', 'idieresis', 'ntilde', 'oacute', 'ograve', + 'ocircumflex', 'odieresis', 'otilde', 'uacute', 'ugrave', 'ucircumflex', + 'udieresis', 'dagger', 'degree', 'cent', 'sterling', 'section', 'bullet', + 'paragraph', 'germandbls', 'registered', 'copyright', 'trademark', 'acute', + 'dieresis', 'notequal', 'AE', 'Oslash', 'infinity', 'plusminus', 'lessequal', + 'greaterequal', 'yen', 'mu', 'partialdiff', 'summation', 'product', 'pi', + 'integral', 'ordfeminine', 'ordmasculine', 'Omega', 'ae', 'oslash', + 'questiondown', 'exclamdown', 'logicalnot', 'radical', 'florin', + 'approxequal', 'Delta', 'guillemotleft', 'guillemotright', 'ellipsis', + 'nonbreakingspace', 'Agrave', 'Atilde', 'Otilde', 'OE', 'oe', 'endash', + 'emdash', 'quotedblleft', 'quotedblright', 'quoteleft', 'quoteright', + 'divide', 'lozenge', 'ydieresis', 'Ydieresis', 'fraction', 'currency', + 'guilsinglleft', 'guilsinglright', 'fi', 'fl', 'daggerdbl', 'periodcentered', + 'quotesinglbase', 'quotedblbase', 'perthousand', 'Acircumflex', + 'Ecircumflex', 'Aacute', 'Edieresis', 'Egrave', 'Iacute', 'Icircumflex', + 'Idieresis', 'Igrave', 'Oacute', 'Ocircumflex', 'apple', 'Ograve', 'Uacute', + 'Ucircumflex', 'Ugrave', 'dotlessi', 'circumflex', 'tilde', 'macron', + 'breve', 'dotaccent', 'ring', 'cedilla', 'hungarumlaut', 'ogonek', 'caron', + 'Lslash', 'lslash', 'Scaron', 'scaron', 'Zcaron', 'zcaron', 'brokenbar', + 'Eth', 'eth', 'Yacute', 'yacute', 'Thorn', 'thorn', 'minus', 'multiply', + 'onesuperior', 'twosuperior', 'threesuperior', 'onehalf', 'onequarter', + 'threequarters', 'franc', 'Gbreve', 'gbreve', 'Idotaccent', 'Scedilla', + 'scedilla', 'Cacute', 'cacute', 'Ccaron', 'ccaron', 'dcroat']; + +function getUnicodeRangeFor(value) { + for (var i = 0, ii = UnicodeRanges.length; i < ii; i++) { + var range = UnicodeRanges[i]; + if (value >= range.begin && value < range.end) { + return i; + } + } + return -1; +} + +function isRTLRangeFor(value) { + var range = UnicodeRanges[13]; + if (value >= range.begin && value < range.end) { + return true; + } + range = UnicodeRanges[11]; + if (value >= range.begin && value < range.end) { + return true; + } + return false; +} + +// The normalization table is obtained by filtering the Unicode characters +// database with entries. +var NormalizedUnicodes = { + '\u00A8': '\u0020\u0308', + '\u00AF': '\u0020\u0304', + '\u00B4': '\u0020\u0301', + '\u00B5': '\u03BC', + '\u00B8': '\u0020\u0327', + '\u0132': '\u0049\u004A', + '\u0133': '\u0069\u006A', + '\u013F': '\u004C\u00B7', + '\u0140': '\u006C\u00B7', + '\u0149': '\u02BC\u006E', + '\u017F': '\u0073', + '\u01C4': '\u0044\u017D', + '\u01C5': '\u0044\u017E', + '\u01C6': '\u0064\u017E', + '\u01C7': '\u004C\u004A', + '\u01C8': '\u004C\u006A', + '\u01C9': '\u006C\u006A', + '\u01CA': '\u004E\u004A', + '\u01CB': '\u004E\u006A', + '\u01CC': '\u006E\u006A', + '\u01F1': '\u0044\u005A', + '\u01F2': '\u0044\u007A', + '\u01F3': '\u0064\u007A', + '\u02D8': '\u0020\u0306', + '\u02D9': '\u0020\u0307', + '\u02DA': '\u0020\u030A', + '\u02DB': '\u0020\u0328', + '\u02DC': '\u0020\u0303', + '\u02DD': '\u0020\u030B', + '\u037A': '\u0020\u0345', + '\u0384': '\u0020\u0301', + '\u03D0': '\u03B2', + '\u03D1': '\u03B8', + '\u03D2': '\u03A5', + '\u03D5': '\u03C6', + '\u03D6': '\u03C0', + '\u03F0': '\u03BA', + '\u03F1': '\u03C1', + '\u03F2': '\u03C2', + '\u03F4': '\u0398', + '\u03F5': '\u03B5', + '\u03F9': '\u03A3', + '\u0587': '\u0565\u0582', + '\u0675': '\u0627\u0674', + '\u0676': '\u0648\u0674', + '\u0677': '\u06C7\u0674', + '\u0678': '\u064A\u0674', + '\u0E33': '\u0E4D\u0E32', + '\u0EB3': '\u0ECD\u0EB2', + '\u0EDC': '\u0EAB\u0E99', + '\u0EDD': '\u0EAB\u0EA1', + '\u0F77': '\u0FB2\u0F81', + '\u0F79': '\u0FB3\u0F81', + '\u1E9A': '\u0061\u02BE', + '\u1FBD': '\u0020\u0313', + '\u1FBF': '\u0020\u0313', + '\u1FC0': '\u0020\u0342', + '\u1FFE': '\u0020\u0314', + '\u2002': '\u0020', + '\u2003': '\u0020', + '\u2004': '\u0020', + '\u2005': '\u0020', + '\u2006': '\u0020', + '\u2008': '\u0020', + '\u2009': '\u0020', + '\u200A': '\u0020', + '\u2017': '\u0020\u0333', + '\u2024': '\u002E', + '\u2025': '\u002E\u002E', + '\u2026': '\u002E\u002E\u002E', + '\u2033': '\u2032\u2032', + '\u2034': '\u2032\u2032\u2032', + '\u2036': '\u2035\u2035', + '\u2037': '\u2035\u2035\u2035', + '\u203C': '\u0021\u0021', + '\u203E': '\u0020\u0305', + '\u2047': '\u003F\u003F', + '\u2048': '\u003F\u0021', + '\u2049': '\u0021\u003F', + '\u2057': '\u2032\u2032\u2032\u2032', + '\u205F': '\u0020', + '\u20A8': '\u0052\u0073', + '\u2100': '\u0061\u002F\u0063', + '\u2101': '\u0061\u002F\u0073', + '\u2103': '\u00B0\u0043', + '\u2105': '\u0063\u002F\u006F', + '\u2106': '\u0063\u002F\u0075', + '\u2107': '\u0190', + '\u2109': '\u00B0\u0046', + '\u2116': '\u004E\u006F', + '\u2121': '\u0054\u0045\u004C', + '\u2135': '\u05D0', + '\u2136': '\u05D1', + '\u2137': '\u05D2', + '\u2138': '\u05D3', + '\u213B': '\u0046\u0041\u0058', + '\u2160': '\u0049', + '\u2161': '\u0049\u0049', + '\u2162': '\u0049\u0049\u0049', + '\u2163': '\u0049\u0056', + '\u2164': '\u0056', + '\u2165': '\u0056\u0049', + '\u2166': '\u0056\u0049\u0049', + '\u2167': '\u0056\u0049\u0049\u0049', + '\u2168': '\u0049\u0058', + '\u2169': '\u0058', + '\u216A': '\u0058\u0049', + '\u216B': '\u0058\u0049\u0049', + '\u216C': '\u004C', + '\u216D': '\u0043', + '\u216E': '\u0044', + '\u216F': '\u004D', + '\u2170': '\u0069', + '\u2171': '\u0069\u0069', + '\u2172': '\u0069\u0069\u0069', + '\u2173': '\u0069\u0076', + '\u2174': '\u0076', + '\u2175': '\u0076\u0069', + '\u2176': '\u0076\u0069\u0069', + '\u2177': '\u0076\u0069\u0069\u0069', + '\u2178': '\u0069\u0078', + '\u2179': '\u0078', + '\u217A': '\u0078\u0069', + '\u217B': '\u0078\u0069\u0069', + '\u217C': '\u006C', + '\u217D': '\u0063', + '\u217E': '\u0064', + '\u217F': '\u006D', + '\u222C': '\u222B\u222B', + '\u222D': '\u222B\u222B\u222B', + '\u222F': '\u222E\u222E', + '\u2230': '\u222E\u222E\u222E', + '\u2474': '\u0028\u0031\u0029', + '\u2475': '\u0028\u0032\u0029', + '\u2476': '\u0028\u0033\u0029', + '\u2477': '\u0028\u0034\u0029', + '\u2478': '\u0028\u0035\u0029', + '\u2479': '\u0028\u0036\u0029', + '\u247A': '\u0028\u0037\u0029', + '\u247B': '\u0028\u0038\u0029', + '\u247C': '\u0028\u0039\u0029', + '\u247D': '\u0028\u0031\u0030\u0029', + '\u247E': '\u0028\u0031\u0031\u0029', + '\u247F': '\u0028\u0031\u0032\u0029', + '\u2480': '\u0028\u0031\u0033\u0029', + '\u2481': '\u0028\u0031\u0034\u0029', + '\u2482': '\u0028\u0031\u0035\u0029', + '\u2483': '\u0028\u0031\u0036\u0029', + '\u2484': '\u0028\u0031\u0037\u0029', + '\u2485': '\u0028\u0031\u0038\u0029', + '\u2486': '\u0028\u0031\u0039\u0029', + '\u2487': '\u0028\u0032\u0030\u0029', + '\u2488': '\u0031\u002E', + '\u2489': '\u0032\u002E', + '\u248A': '\u0033\u002E', + '\u248B': '\u0034\u002E', + '\u248C': '\u0035\u002E', + '\u248D': '\u0036\u002E', + '\u248E': '\u0037\u002E', + '\u248F': '\u0038\u002E', + '\u2490': '\u0039\u002E', + '\u2491': '\u0031\u0030\u002E', + '\u2492': '\u0031\u0031\u002E', + '\u2493': '\u0031\u0032\u002E', + '\u2494': '\u0031\u0033\u002E', + '\u2495': '\u0031\u0034\u002E', + '\u2496': '\u0031\u0035\u002E', + '\u2497': '\u0031\u0036\u002E', + '\u2498': '\u0031\u0037\u002E', + '\u2499': '\u0031\u0038\u002E', + '\u249A': '\u0031\u0039\u002E', + '\u249B': '\u0032\u0030\u002E', + '\u249C': '\u0028\u0061\u0029', + '\u249D': '\u0028\u0062\u0029', + '\u249E': '\u0028\u0063\u0029', + '\u249F': '\u0028\u0064\u0029', + '\u24A0': '\u0028\u0065\u0029', + '\u24A1': '\u0028\u0066\u0029', + '\u24A2': '\u0028\u0067\u0029', + '\u24A3': '\u0028\u0068\u0029', + '\u24A4': '\u0028\u0069\u0029', + '\u24A5': '\u0028\u006A\u0029', + '\u24A6': '\u0028\u006B\u0029', + '\u24A7': '\u0028\u006C\u0029', + '\u24A8': '\u0028\u006D\u0029', + '\u24A9': '\u0028\u006E\u0029', + '\u24AA': '\u0028\u006F\u0029', + '\u24AB': '\u0028\u0070\u0029', + '\u24AC': '\u0028\u0071\u0029', + '\u24AD': '\u0028\u0072\u0029', + '\u24AE': '\u0028\u0073\u0029', + '\u24AF': '\u0028\u0074\u0029', + '\u24B0': '\u0028\u0075\u0029', + '\u24B1': '\u0028\u0076\u0029', + '\u24B2': '\u0028\u0077\u0029', + '\u24B3': '\u0028\u0078\u0029', + '\u24B4': '\u0028\u0079\u0029', + '\u24B5': '\u0028\u007A\u0029', + '\u2A0C': '\u222B\u222B\u222B\u222B', + '\u2A74': '\u003A\u003A\u003D', + '\u2A75': '\u003D\u003D', + '\u2A76': '\u003D\u003D\u003D', + '\u2E9F': '\u6BCD', + '\u2EF3': '\u9F9F', + '\u2F00': '\u4E00', + '\u2F01': '\u4E28', + '\u2F02': '\u4E36', + '\u2F03': '\u4E3F', + '\u2F04': '\u4E59', + '\u2F05': '\u4E85', + '\u2F06': '\u4E8C', + '\u2F07': '\u4EA0', + '\u2F08': '\u4EBA', + '\u2F09': '\u513F', + '\u2F0A': '\u5165', + '\u2F0B': '\u516B', + '\u2F0C': '\u5182', + '\u2F0D': '\u5196', + '\u2F0E': '\u51AB', + '\u2F0F': '\u51E0', + '\u2F10': '\u51F5', + '\u2F11': '\u5200', + '\u2F12': '\u529B', + '\u2F13': '\u52F9', + '\u2F14': '\u5315', + '\u2F15': '\u531A', + '\u2F16': '\u5338', + '\u2F17': '\u5341', + '\u2F18': '\u535C', + '\u2F19': '\u5369', + '\u2F1A': '\u5382', + '\u2F1B': '\u53B6', + '\u2F1C': '\u53C8', + '\u2F1D': '\u53E3', + '\u2F1E': '\u56D7', + '\u2F1F': '\u571F', + '\u2F20': '\u58EB', + '\u2F21': '\u5902', + '\u2F22': '\u590A', + '\u2F23': '\u5915', + '\u2F24': '\u5927', + '\u2F25': '\u5973', + '\u2F26': '\u5B50', + '\u2F27': '\u5B80', + '\u2F28': '\u5BF8', + '\u2F29': '\u5C0F', + '\u2F2A': '\u5C22', + '\u2F2B': '\u5C38', + '\u2F2C': '\u5C6E', + '\u2F2D': '\u5C71', + '\u2F2E': '\u5DDB', + '\u2F2F': '\u5DE5', + '\u2F30': '\u5DF1', + '\u2F31': '\u5DFE', + '\u2F32': '\u5E72', + '\u2F33': '\u5E7A', + '\u2F34': '\u5E7F', + '\u2F35': '\u5EF4', + '\u2F36': '\u5EFE', + '\u2F37': '\u5F0B', + '\u2F38': '\u5F13', + '\u2F39': '\u5F50', + '\u2F3A': '\u5F61', + '\u2F3B': '\u5F73', + '\u2F3C': '\u5FC3', + '\u2F3D': '\u6208', + '\u2F3E': '\u6236', + '\u2F3F': '\u624B', + '\u2F40': '\u652F', + '\u2F41': '\u6534', + '\u2F42': '\u6587', + '\u2F43': '\u6597', + '\u2F44': '\u65A4', + '\u2F45': '\u65B9', + '\u2F46': '\u65E0', + '\u2F47': '\u65E5', + '\u2F48': '\u66F0', + '\u2F49': '\u6708', + '\u2F4A': '\u6728', + '\u2F4B': '\u6B20', + '\u2F4C': '\u6B62', + '\u2F4D': '\u6B79', + '\u2F4E': '\u6BB3', + '\u2F4F': '\u6BCB', + '\u2F50': '\u6BD4', + '\u2F51': '\u6BDB', + '\u2F52': '\u6C0F', + '\u2F53': '\u6C14', + '\u2F54': '\u6C34', + '\u2F55': '\u706B', + '\u2F56': '\u722A', + '\u2F57': '\u7236', + '\u2F58': '\u723B', + '\u2F59': '\u723F', + '\u2F5A': '\u7247', + '\u2F5B': '\u7259', + '\u2F5C': '\u725B', + '\u2F5D': '\u72AC', + '\u2F5E': '\u7384', + '\u2F5F': '\u7389', + '\u2F60': '\u74DC', + '\u2F61': '\u74E6', + '\u2F62': '\u7518', + '\u2F63': '\u751F', + '\u2F64': '\u7528', + '\u2F65': '\u7530', + '\u2F66': '\u758B', + '\u2F67': '\u7592', + '\u2F68': '\u7676', + '\u2F69': '\u767D', + '\u2F6A': '\u76AE', + '\u2F6B': '\u76BF', + '\u2F6C': '\u76EE', + '\u2F6D': '\u77DB', + '\u2F6E': '\u77E2', + '\u2F6F': '\u77F3', + '\u2F70': '\u793A', + '\u2F71': '\u79B8', + '\u2F72': '\u79BE', + '\u2F73': '\u7A74', + '\u2F74': '\u7ACB', + '\u2F75': '\u7AF9', + '\u2F76': '\u7C73', + '\u2F77': '\u7CF8', + '\u2F78': '\u7F36', + '\u2F79': '\u7F51', + '\u2F7A': '\u7F8A', + '\u2F7B': '\u7FBD', + '\u2F7C': '\u8001', + '\u2F7D': '\u800C', + '\u2F7E': '\u8012', + '\u2F7F': '\u8033', + '\u2F80': '\u807F', + '\u2F81': '\u8089', + '\u2F82': '\u81E3', + '\u2F83': '\u81EA', + '\u2F84': '\u81F3', + '\u2F85': '\u81FC', + '\u2F86': '\u820C', + '\u2F87': '\u821B', + '\u2F88': '\u821F', + '\u2F89': '\u826E', + '\u2F8A': '\u8272', + '\u2F8B': '\u8278', + '\u2F8C': '\u864D', + '\u2F8D': '\u866B', + '\u2F8E': '\u8840', + '\u2F8F': '\u884C', + '\u2F90': '\u8863', + '\u2F91': '\u897E', + '\u2F92': '\u898B', + '\u2F93': '\u89D2', + '\u2F94': '\u8A00', + '\u2F95': '\u8C37', + '\u2F96': '\u8C46', + '\u2F97': '\u8C55', + '\u2F98': '\u8C78', + '\u2F99': '\u8C9D', + '\u2F9A': '\u8D64', + '\u2F9B': '\u8D70', + '\u2F9C': '\u8DB3', + '\u2F9D': '\u8EAB', + '\u2F9E': '\u8ECA', + '\u2F9F': '\u8F9B', + '\u2FA0': '\u8FB0', + '\u2FA1': '\u8FB5', + '\u2FA2': '\u9091', + '\u2FA3': '\u9149', + '\u2FA4': '\u91C6', + '\u2FA5': '\u91CC', + '\u2FA6': '\u91D1', + '\u2FA7': '\u9577', + '\u2FA8': '\u9580', + '\u2FA9': '\u961C', + '\u2FAA': '\u96B6', + '\u2FAB': '\u96B9', + '\u2FAC': '\u96E8', + '\u2FAD': '\u9751', + '\u2FAE': '\u975E', + '\u2FAF': '\u9762', + '\u2FB0': '\u9769', + '\u2FB1': '\u97CB', + '\u2FB2': '\u97ED', + '\u2FB3': '\u97F3', + '\u2FB4': '\u9801', + '\u2FB5': '\u98A8', + '\u2FB6': '\u98DB', + '\u2FB7': '\u98DF', + '\u2FB8': '\u9996', + '\u2FB9': '\u9999', + '\u2FBA': '\u99AC', + '\u2FBB': '\u9AA8', + '\u2FBC': '\u9AD8', + '\u2FBD': '\u9ADF', + '\u2FBE': '\u9B25', + '\u2FBF': '\u9B2F', + '\u2FC0': '\u9B32', + '\u2FC1': '\u9B3C', + '\u2FC2': '\u9B5A', + '\u2FC3': '\u9CE5', + '\u2FC4': '\u9E75', + '\u2FC5': '\u9E7F', + '\u2FC6': '\u9EA5', + '\u2FC7': '\u9EBB', + '\u2FC8': '\u9EC3', + '\u2FC9': '\u9ECD', + '\u2FCA': '\u9ED1', + '\u2FCB': '\u9EF9', + '\u2FCC': '\u9EFD', + '\u2FCD': '\u9F0E', + '\u2FCE': '\u9F13', + '\u2FCF': '\u9F20', + '\u2FD0': '\u9F3B', + '\u2FD1': '\u9F4A', + '\u2FD2': '\u9F52', + '\u2FD3': '\u9F8D', + '\u2FD4': '\u9F9C', + '\u2FD5': '\u9FA0', + '\u3036': '\u3012', + '\u3038': '\u5341', + '\u3039': '\u5344', + '\u303A': '\u5345', + '\u309B': '\u0020\u3099', + '\u309C': '\u0020\u309A', + '\u3131': '\u1100', + '\u3132': '\u1101', + '\u3133': '\u11AA', + '\u3134': '\u1102', + '\u3135': '\u11AC', + '\u3136': '\u11AD', + '\u3137': '\u1103', + '\u3138': '\u1104', + '\u3139': '\u1105', + '\u313A': '\u11B0', + '\u313B': '\u11B1', + '\u313C': '\u11B2', + '\u313D': '\u11B3', + '\u313E': '\u11B4', + '\u313F': '\u11B5', + '\u3140': '\u111A', + '\u3141': '\u1106', + '\u3142': '\u1107', + '\u3143': '\u1108', + '\u3144': '\u1121', + '\u3145': '\u1109', + '\u3146': '\u110A', + '\u3147': '\u110B', + '\u3148': '\u110C', + '\u3149': '\u110D', + '\u314A': '\u110E', + '\u314B': '\u110F', + '\u314C': '\u1110', + '\u314D': '\u1111', + '\u314E': '\u1112', + '\u314F': '\u1161', + '\u3150': '\u1162', + '\u3151': '\u1163', + '\u3152': '\u1164', + '\u3153': '\u1165', + '\u3154': '\u1166', + '\u3155': '\u1167', + '\u3156': '\u1168', + '\u3157': '\u1169', + '\u3158': '\u116A', + '\u3159': '\u116B', + '\u315A': '\u116C', + '\u315B': '\u116D', + '\u315C': '\u116E', + '\u315D': '\u116F', + '\u315E': '\u1170', + '\u315F': '\u1171', + '\u3160': '\u1172', + '\u3161': '\u1173', + '\u3162': '\u1174', + '\u3163': '\u1175', + '\u3164': '\u1160', + '\u3165': '\u1114', + '\u3166': '\u1115', + '\u3167': '\u11C7', + '\u3168': '\u11C8', + '\u3169': '\u11CC', + '\u316A': '\u11CE', + '\u316B': '\u11D3', + '\u316C': '\u11D7', + '\u316D': '\u11D9', + '\u316E': '\u111C', + '\u316F': '\u11DD', + '\u3170': '\u11DF', + '\u3171': '\u111D', + '\u3172': '\u111E', + '\u3173': '\u1120', + '\u3174': '\u1122', + '\u3175': '\u1123', + '\u3176': '\u1127', + '\u3177': '\u1129', + '\u3178': '\u112B', + '\u3179': '\u112C', + '\u317A': '\u112D', + '\u317B': '\u112E', + '\u317C': '\u112F', + '\u317D': '\u1132', + '\u317E': '\u1136', + '\u317F': '\u1140', + '\u3180': '\u1147', + '\u3181': '\u114C', + '\u3182': '\u11F1', + '\u3183': '\u11F2', + '\u3184': '\u1157', + '\u3185': '\u1158', + '\u3186': '\u1159', + '\u3187': '\u1184', + '\u3188': '\u1185', + '\u3189': '\u1188', + '\u318A': '\u1191', + '\u318B': '\u1192', + '\u318C': '\u1194', + '\u318D': '\u119E', + '\u318E': '\u11A1', + '\u3200': '\u0028\u1100\u0029', + '\u3201': '\u0028\u1102\u0029', + '\u3202': '\u0028\u1103\u0029', + '\u3203': '\u0028\u1105\u0029', + '\u3204': '\u0028\u1106\u0029', + '\u3205': '\u0028\u1107\u0029', + '\u3206': '\u0028\u1109\u0029', + '\u3207': '\u0028\u110B\u0029', + '\u3208': '\u0028\u110C\u0029', + '\u3209': '\u0028\u110E\u0029', + '\u320A': '\u0028\u110F\u0029', + '\u320B': '\u0028\u1110\u0029', + '\u320C': '\u0028\u1111\u0029', + '\u320D': '\u0028\u1112\u0029', + '\u320E': '\u0028\u1100\u1161\u0029', + '\u320F': '\u0028\u1102\u1161\u0029', + '\u3210': '\u0028\u1103\u1161\u0029', + '\u3211': '\u0028\u1105\u1161\u0029', + '\u3212': '\u0028\u1106\u1161\u0029', + '\u3213': '\u0028\u1107\u1161\u0029', + '\u3214': '\u0028\u1109\u1161\u0029', + '\u3215': '\u0028\u110B\u1161\u0029', + '\u3216': '\u0028\u110C\u1161\u0029', + '\u3217': '\u0028\u110E\u1161\u0029', + '\u3218': '\u0028\u110F\u1161\u0029', + '\u3219': '\u0028\u1110\u1161\u0029', + '\u321A': '\u0028\u1111\u1161\u0029', + '\u321B': '\u0028\u1112\u1161\u0029', + '\u321C': '\u0028\u110C\u116E\u0029', + '\u321D': '\u0028\u110B\u1169\u110C\u1165\u11AB\u0029', + '\u321E': '\u0028\u110B\u1169\u1112\u116E\u0029', + '\u3220': '\u0028\u4E00\u0029', + '\u3221': '\u0028\u4E8C\u0029', + '\u3222': '\u0028\u4E09\u0029', + '\u3223': '\u0028\u56DB\u0029', + '\u3224': '\u0028\u4E94\u0029', + '\u3225': '\u0028\u516D\u0029', + '\u3226': '\u0028\u4E03\u0029', + '\u3227': '\u0028\u516B\u0029', + '\u3228': '\u0028\u4E5D\u0029', + '\u3229': '\u0028\u5341\u0029', + '\u322A': '\u0028\u6708\u0029', + '\u322B': '\u0028\u706B\u0029', + '\u322C': '\u0028\u6C34\u0029', + '\u322D': '\u0028\u6728\u0029', + '\u322E': '\u0028\u91D1\u0029', + '\u322F': '\u0028\u571F\u0029', + '\u3230': '\u0028\u65E5\u0029', + '\u3231': '\u0028\u682A\u0029', + '\u3232': '\u0028\u6709\u0029', + '\u3233': '\u0028\u793E\u0029', + '\u3234': '\u0028\u540D\u0029', + '\u3235': '\u0028\u7279\u0029', + '\u3236': '\u0028\u8CA1\u0029', + '\u3237': '\u0028\u795D\u0029', + '\u3238': '\u0028\u52B4\u0029', + '\u3239': '\u0028\u4EE3\u0029', + '\u323A': '\u0028\u547C\u0029', + '\u323B': '\u0028\u5B66\u0029', + '\u323C': '\u0028\u76E3\u0029', + '\u323D': '\u0028\u4F01\u0029', + '\u323E': '\u0028\u8CC7\u0029', + '\u323F': '\u0028\u5354\u0029', + '\u3240': '\u0028\u796D\u0029', + '\u3241': '\u0028\u4F11\u0029', + '\u3242': '\u0028\u81EA\u0029', + '\u3243': '\u0028\u81F3\u0029', + '\u32C0': '\u0031\u6708', + '\u32C1': '\u0032\u6708', + '\u32C2': '\u0033\u6708', + '\u32C3': '\u0034\u6708', + '\u32C4': '\u0035\u6708', + '\u32C5': '\u0036\u6708', + '\u32C6': '\u0037\u6708', + '\u32C7': '\u0038\u6708', + '\u32C8': '\u0039\u6708', + '\u32C9': '\u0031\u0030\u6708', + '\u32CA': '\u0031\u0031\u6708', + '\u32CB': '\u0031\u0032\u6708', + '\u3358': '\u0030\u70B9', + '\u3359': '\u0031\u70B9', + '\u335A': '\u0032\u70B9', + '\u335B': '\u0033\u70B9', + '\u335C': '\u0034\u70B9', + '\u335D': '\u0035\u70B9', + '\u335E': '\u0036\u70B9', + '\u335F': '\u0037\u70B9', + '\u3360': '\u0038\u70B9', + '\u3361': '\u0039\u70B9', + '\u3362': '\u0031\u0030\u70B9', + '\u3363': '\u0031\u0031\u70B9', + '\u3364': '\u0031\u0032\u70B9', + '\u3365': '\u0031\u0033\u70B9', + '\u3366': '\u0031\u0034\u70B9', + '\u3367': '\u0031\u0035\u70B9', + '\u3368': '\u0031\u0036\u70B9', + '\u3369': '\u0031\u0037\u70B9', + '\u336A': '\u0031\u0038\u70B9', + '\u336B': '\u0031\u0039\u70B9', + '\u336C': '\u0032\u0030\u70B9', + '\u336D': '\u0032\u0031\u70B9', + '\u336E': '\u0032\u0032\u70B9', + '\u336F': '\u0032\u0033\u70B9', + '\u3370': '\u0032\u0034\u70B9', + '\u33E0': '\u0031\u65E5', + '\u33E1': '\u0032\u65E5', + '\u33E2': '\u0033\u65E5', + '\u33E3': '\u0034\u65E5', + '\u33E4': '\u0035\u65E5', + '\u33E5': '\u0036\u65E5', + '\u33E6': '\u0037\u65E5', + '\u33E7': '\u0038\u65E5', + '\u33E8': '\u0039\u65E5', + '\u33E9': '\u0031\u0030\u65E5', + '\u33EA': '\u0031\u0031\u65E5', + '\u33EB': '\u0031\u0032\u65E5', + '\u33EC': '\u0031\u0033\u65E5', + '\u33ED': '\u0031\u0034\u65E5', + '\u33EE': '\u0031\u0035\u65E5', + '\u33EF': '\u0031\u0036\u65E5', + '\u33F0': '\u0031\u0037\u65E5', + '\u33F1': '\u0031\u0038\u65E5', + '\u33F2': '\u0031\u0039\u65E5', + '\u33F3': '\u0032\u0030\u65E5', + '\u33F4': '\u0032\u0031\u65E5', + '\u33F5': '\u0032\u0032\u65E5', + '\u33F6': '\u0032\u0033\u65E5', + '\u33F7': '\u0032\u0034\u65E5', + '\u33F8': '\u0032\u0035\u65E5', + '\u33F9': '\u0032\u0036\u65E5', + '\u33FA': '\u0032\u0037\u65E5', + '\u33FB': '\u0032\u0038\u65E5', + '\u33FC': '\u0032\u0039\u65E5', + '\u33FD': '\u0033\u0030\u65E5', + '\u33FE': '\u0033\u0031\u65E5', + '\uFB00': '\u0066\u0066', + '\uFB01': '\u0066\u0069', + '\uFB02': '\u0066\u006C', + '\uFB03': '\u0066\u0066\u0069', + '\uFB04': '\u0066\u0066\u006C', + '\uFB05': '\u017F\u0074', + '\uFB06': '\u0073\u0074', + '\uFB13': '\u0574\u0576', + '\uFB14': '\u0574\u0565', + '\uFB15': '\u0574\u056B', + '\uFB16': '\u057E\u0576', + '\uFB17': '\u0574\u056D', + '\uFB4F': '\u05D0\u05DC', + '\uFB50': '\u0671', + '\uFB51': '\u0671', + '\uFB52': '\u067B', + '\uFB53': '\u067B', + '\uFB54': '\u067B', + '\uFB55': '\u067B', + '\uFB56': '\u067E', + '\uFB57': '\u067E', + '\uFB58': '\u067E', + '\uFB59': '\u067E', + '\uFB5A': '\u0680', + '\uFB5B': '\u0680', + '\uFB5C': '\u0680', + '\uFB5D': '\u0680', + '\uFB5E': '\u067A', + '\uFB5F': '\u067A', + '\uFB60': '\u067A', + '\uFB61': '\u067A', + '\uFB62': '\u067F', + '\uFB63': '\u067F', + '\uFB64': '\u067F', + '\uFB65': '\u067F', + '\uFB66': '\u0679', + '\uFB67': '\u0679', + '\uFB68': '\u0679', + '\uFB69': '\u0679', + '\uFB6A': '\u06A4', + '\uFB6B': '\u06A4', + '\uFB6C': '\u06A4', + '\uFB6D': '\u06A4', + '\uFB6E': '\u06A6', + '\uFB6F': '\u06A6', + '\uFB70': '\u06A6', + '\uFB71': '\u06A6', + '\uFB72': '\u0684', + '\uFB73': '\u0684', + '\uFB74': '\u0684', + '\uFB75': '\u0684', + '\uFB76': '\u0683', + '\uFB77': '\u0683', + '\uFB78': '\u0683', + '\uFB79': '\u0683', + '\uFB7A': '\u0686', + '\uFB7B': '\u0686', + '\uFB7C': '\u0686', + '\uFB7D': '\u0686', + '\uFB7E': '\u0687', + '\uFB7F': '\u0687', + '\uFB80': '\u0687', + '\uFB81': '\u0687', + '\uFB82': '\u068D', + '\uFB83': '\u068D', + '\uFB84': '\u068C', + '\uFB85': '\u068C', + '\uFB86': '\u068E', + '\uFB87': '\u068E', + '\uFB88': '\u0688', + '\uFB89': '\u0688', + '\uFB8A': '\u0698', + '\uFB8B': '\u0698', + '\uFB8C': '\u0691', + '\uFB8D': '\u0691', + '\uFB8E': '\u06A9', + '\uFB8F': '\u06A9', + '\uFB90': '\u06A9', + '\uFB91': '\u06A9', + '\uFB92': '\u06AF', + '\uFB93': '\u06AF', + '\uFB94': '\u06AF', + '\uFB95': '\u06AF', + '\uFB96': '\u06B3', + '\uFB97': '\u06B3', + '\uFB98': '\u06B3', + '\uFB99': '\u06B3', + '\uFB9A': '\u06B1', + '\uFB9B': '\u06B1', + '\uFB9C': '\u06B1', + '\uFB9D': '\u06B1', + '\uFB9E': '\u06BA', + '\uFB9F': '\u06BA', + '\uFBA0': '\u06BB', + '\uFBA1': '\u06BB', + '\uFBA2': '\u06BB', + '\uFBA3': '\u06BB', + '\uFBA4': '\u06C0', + '\uFBA5': '\u06C0', + '\uFBA6': '\u06C1', + '\uFBA7': '\u06C1', + '\uFBA8': '\u06C1', + '\uFBA9': '\u06C1', + '\uFBAA': '\u06BE', + '\uFBAB': '\u06BE', + '\uFBAC': '\u06BE', + '\uFBAD': '\u06BE', + '\uFBAE': '\u06D2', + '\uFBAF': '\u06D2', + '\uFBB0': '\u06D3', + '\uFBB1': '\u06D3', + '\uFBD3': '\u06AD', + '\uFBD4': '\u06AD', + '\uFBD5': '\u06AD', + '\uFBD6': '\u06AD', + '\uFBD7': '\u06C7', + '\uFBD8': '\u06C7', + '\uFBD9': '\u06C6', + '\uFBDA': '\u06C6', + '\uFBDB': '\u06C8', + '\uFBDC': '\u06C8', + '\uFBDD': '\u0677', + '\uFBDE': '\u06CB', + '\uFBDF': '\u06CB', + '\uFBE0': '\u06C5', + '\uFBE1': '\u06C5', + '\uFBE2': '\u06C9', + '\uFBE3': '\u06C9', + '\uFBE4': '\u06D0', + '\uFBE5': '\u06D0', + '\uFBE6': '\u06D0', + '\uFBE7': '\u06D0', + '\uFBE8': '\u0649', + '\uFBE9': '\u0649', + '\uFBEA': '\u0626\u0627', + '\uFBEB': '\u0626\u0627', + '\uFBEC': '\u0626\u06D5', + '\uFBED': '\u0626\u06D5', + '\uFBEE': '\u0626\u0648', + '\uFBEF': '\u0626\u0648', + '\uFBF0': '\u0626\u06C7', + '\uFBF1': '\u0626\u06C7', + '\uFBF2': '\u0626\u06C6', + '\uFBF3': '\u0626\u06C6', + '\uFBF4': '\u0626\u06C8', + '\uFBF5': '\u0626\u06C8', + '\uFBF6': '\u0626\u06D0', + '\uFBF7': '\u0626\u06D0', + '\uFBF8': '\u0626\u06D0', + '\uFBF9': '\u0626\u0649', + '\uFBFA': '\u0626\u0649', + '\uFBFB': '\u0626\u0649', + '\uFBFC': '\u06CC', + '\uFBFD': '\u06CC', + '\uFBFE': '\u06CC', + '\uFBFF': '\u06CC', + '\uFC00': '\u0626\u062C', + '\uFC01': '\u0626\u062D', + '\uFC02': '\u0626\u0645', + '\uFC03': '\u0626\u0649', + '\uFC04': '\u0626\u064A', + '\uFC05': '\u0628\u062C', + '\uFC06': '\u0628\u062D', + '\uFC07': '\u0628\u062E', + '\uFC08': '\u0628\u0645', + '\uFC09': '\u0628\u0649', + '\uFC0A': '\u0628\u064A', + '\uFC0B': '\u062A\u062C', + '\uFC0C': '\u062A\u062D', + '\uFC0D': '\u062A\u062E', + '\uFC0E': '\u062A\u0645', + '\uFC0F': '\u062A\u0649', + '\uFC10': '\u062A\u064A', + '\uFC11': '\u062B\u062C', + '\uFC12': '\u062B\u0645', + '\uFC13': '\u062B\u0649', + '\uFC14': '\u062B\u064A', + '\uFC15': '\u062C\u062D', + '\uFC16': '\u062C\u0645', + '\uFC17': '\u062D\u062C', + '\uFC18': '\u062D\u0645', + '\uFC19': '\u062E\u062C', + '\uFC1A': '\u062E\u062D', + '\uFC1B': '\u062E\u0645', + '\uFC1C': '\u0633\u062C', + '\uFC1D': '\u0633\u062D', + '\uFC1E': '\u0633\u062E', + '\uFC1F': '\u0633\u0645', + '\uFC20': '\u0635\u062D', + '\uFC21': '\u0635\u0645', + '\uFC22': '\u0636\u062C', + '\uFC23': '\u0636\u062D', + '\uFC24': '\u0636\u062E', + '\uFC25': '\u0636\u0645', + '\uFC26': '\u0637\u062D', + '\uFC27': '\u0637\u0645', + '\uFC28': '\u0638\u0645', + '\uFC29': '\u0639\u062C', + '\uFC2A': '\u0639\u0645', + '\uFC2B': '\u063A\u062C', + '\uFC2C': '\u063A\u0645', + '\uFC2D': '\u0641\u062C', + '\uFC2E': '\u0641\u062D', + '\uFC2F': '\u0641\u062E', + '\uFC30': '\u0641\u0645', + '\uFC31': '\u0641\u0649', + '\uFC32': '\u0641\u064A', + '\uFC33': '\u0642\u062D', + '\uFC34': '\u0642\u0645', + '\uFC35': '\u0642\u0649', + '\uFC36': '\u0642\u064A', + '\uFC37': '\u0643\u0627', + '\uFC38': '\u0643\u062C', + '\uFC39': '\u0643\u062D', + '\uFC3A': '\u0643\u062E', + '\uFC3B': '\u0643\u0644', + '\uFC3C': '\u0643\u0645', + '\uFC3D': '\u0643\u0649', + '\uFC3E': '\u0643\u064A', + '\uFC3F': '\u0644\u062C', + '\uFC40': '\u0644\u062D', + '\uFC41': '\u0644\u062E', + '\uFC42': '\u0644\u0645', + '\uFC43': '\u0644\u0649', + '\uFC44': '\u0644\u064A', + '\uFC45': '\u0645\u062C', + '\uFC46': '\u0645\u062D', + '\uFC47': '\u0645\u062E', + '\uFC48': '\u0645\u0645', + '\uFC49': '\u0645\u0649', + '\uFC4A': '\u0645\u064A', + '\uFC4B': '\u0646\u062C', + '\uFC4C': '\u0646\u062D', + '\uFC4D': '\u0646\u062E', + '\uFC4E': '\u0646\u0645', + '\uFC4F': '\u0646\u0649', + '\uFC50': '\u0646\u064A', + '\uFC51': '\u0647\u062C', + '\uFC52': '\u0647\u0645', + '\uFC53': '\u0647\u0649', + '\uFC54': '\u0647\u064A', + '\uFC55': '\u064A\u062C', + '\uFC56': '\u064A\u062D', + '\uFC57': '\u064A\u062E', + '\uFC58': '\u064A\u0645', + '\uFC59': '\u064A\u0649', + '\uFC5A': '\u064A\u064A', + '\uFC5B': '\u0630\u0670', + '\uFC5C': '\u0631\u0670', + '\uFC5D': '\u0649\u0670', + '\uFC5E': '\u0020\u064C\u0651', + '\uFC5F': '\u0020\u064D\u0651', + '\uFC60': '\u0020\u064E\u0651', + '\uFC61': '\u0020\u064F\u0651', + '\uFC62': '\u0020\u0650\u0651', + '\uFC63': '\u0020\u0651\u0670', + '\uFC64': '\u0626\u0631', + '\uFC65': '\u0626\u0632', + '\uFC66': '\u0626\u0645', + '\uFC67': '\u0626\u0646', + '\uFC68': '\u0626\u0649', + '\uFC69': '\u0626\u064A', + '\uFC6A': '\u0628\u0631', + '\uFC6B': '\u0628\u0632', + '\uFC6C': '\u0628\u0645', + '\uFC6D': '\u0628\u0646', + '\uFC6E': '\u0628\u0649', + '\uFC6F': '\u0628\u064A', + '\uFC70': '\u062A\u0631', + '\uFC71': '\u062A\u0632', + '\uFC72': '\u062A\u0645', + '\uFC73': '\u062A\u0646', + '\uFC74': '\u062A\u0649', + '\uFC75': '\u062A\u064A', + '\uFC76': '\u062B\u0631', + '\uFC77': '\u062B\u0632', + '\uFC78': '\u062B\u0645', + '\uFC79': '\u062B\u0646', + '\uFC7A': '\u062B\u0649', + '\uFC7B': '\u062B\u064A', + '\uFC7C': '\u0641\u0649', + '\uFC7D': '\u0641\u064A', + '\uFC7E': '\u0642\u0649', + '\uFC7F': '\u0642\u064A', + '\uFC80': '\u0643\u0627', + '\uFC81': '\u0643\u0644', + '\uFC82': '\u0643\u0645', + '\uFC83': '\u0643\u0649', + '\uFC84': '\u0643\u064A', + '\uFC85': '\u0644\u0645', + '\uFC86': '\u0644\u0649', + '\uFC87': '\u0644\u064A', + '\uFC88': '\u0645\u0627', + '\uFC89': '\u0645\u0645', + '\uFC8A': '\u0646\u0631', + '\uFC8B': '\u0646\u0632', + '\uFC8C': '\u0646\u0645', + '\uFC8D': '\u0646\u0646', + '\uFC8E': '\u0646\u0649', + '\uFC8F': '\u0646\u064A', + '\uFC90': '\u0649\u0670', + '\uFC91': '\u064A\u0631', + '\uFC92': '\u064A\u0632', + '\uFC93': '\u064A\u0645', + '\uFC94': '\u064A\u0646', + '\uFC95': '\u064A\u0649', + '\uFC96': '\u064A\u064A', + '\uFC97': '\u0626\u062C', + '\uFC98': '\u0626\u062D', + '\uFC99': '\u0626\u062E', + '\uFC9A': '\u0626\u0645', + '\uFC9B': '\u0626\u0647', + '\uFC9C': '\u0628\u062C', + '\uFC9D': '\u0628\u062D', + '\uFC9E': '\u0628\u062E', + '\uFC9F': '\u0628\u0645', + '\uFCA0': '\u0628\u0647', + '\uFCA1': '\u062A\u062C', + '\uFCA2': '\u062A\u062D', + '\uFCA3': '\u062A\u062E', + '\uFCA4': '\u062A\u0645', + '\uFCA5': '\u062A\u0647', + '\uFCA6': '\u062B\u0645', + '\uFCA7': '\u062C\u062D', + '\uFCA8': '\u062C\u0645', + '\uFCA9': '\u062D\u062C', + '\uFCAA': '\u062D\u0645', + '\uFCAB': '\u062E\u062C', + '\uFCAC': '\u062E\u0645', + '\uFCAD': '\u0633\u062C', + '\uFCAE': '\u0633\u062D', + '\uFCAF': '\u0633\u062E', + '\uFCB0': '\u0633\u0645', + '\uFCB1': '\u0635\u062D', + '\uFCB2': '\u0635\u062E', + '\uFCB3': '\u0635\u0645', + '\uFCB4': '\u0636\u062C', + '\uFCB5': '\u0636\u062D', + '\uFCB6': '\u0636\u062E', + '\uFCB7': '\u0636\u0645', + '\uFCB8': '\u0637\u062D', + '\uFCB9': '\u0638\u0645', + '\uFCBA': '\u0639\u062C', + '\uFCBB': '\u0639\u0645', + '\uFCBC': '\u063A\u062C', + '\uFCBD': '\u063A\u0645', + '\uFCBE': '\u0641\u062C', + '\uFCBF': '\u0641\u062D', + '\uFCC0': '\u0641\u062E', + '\uFCC1': '\u0641\u0645', + '\uFCC2': '\u0642\u062D', + '\uFCC3': '\u0642\u0645', + '\uFCC4': '\u0643\u062C', + '\uFCC5': '\u0643\u062D', + '\uFCC6': '\u0643\u062E', + '\uFCC7': '\u0643\u0644', + '\uFCC8': '\u0643\u0645', + '\uFCC9': '\u0644\u062C', + '\uFCCA': '\u0644\u062D', + '\uFCCB': '\u0644\u062E', + '\uFCCC': '\u0644\u0645', + '\uFCCD': '\u0644\u0647', + '\uFCCE': '\u0645\u062C', + '\uFCCF': '\u0645\u062D', + '\uFCD0': '\u0645\u062E', + '\uFCD1': '\u0645\u0645', + '\uFCD2': '\u0646\u062C', + '\uFCD3': '\u0646\u062D', + '\uFCD4': '\u0646\u062E', + '\uFCD5': '\u0646\u0645', + '\uFCD6': '\u0646\u0647', + '\uFCD7': '\u0647\u062C', + '\uFCD8': '\u0647\u0645', + '\uFCD9': '\u0647\u0670', + '\uFCDA': '\u064A\u062C', + '\uFCDB': '\u064A\u062D', + '\uFCDC': '\u064A\u062E', + '\uFCDD': '\u064A\u0645', + '\uFCDE': '\u064A\u0647', + '\uFCDF': '\u0626\u0645', + '\uFCE0': '\u0626\u0647', + '\uFCE1': '\u0628\u0645', + '\uFCE2': '\u0628\u0647', + '\uFCE3': '\u062A\u0645', + '\uFCE4': '\u062A\u0647', + '\uFCE5': '\u062B\u0645', + '\uFCE6': '\u062B\u0647', + '\uFCE7': '\u0633\u0645', + '\uFCE8': '\u0633\u0647', + '\uFCE9': '\u0634\u0645', + '\uFCEA': '\u0634\u0647', + '\uFCEB': '\u0643\u0644', + '\uFCEC': '\u0643\u0645', + '\uFCED': '\u0644\u0645', + '\uFCEE': '\u0646\u0645', + '\uFCEF': '\u0646\u0647', + '\uFCF0': '\u064A\u0645', + '\uFCF1': '\u064A\u0647', + '\uFCF2': '\u0640\u064E\u0651', + '\uFCF3': '\u0640\u064F\u0651', + '\uFCF4': '\u0640\u0650\u0651', + '\uFCF5': '\u0637\u0649', + '\uFCF6': '\u0637\u064A', + '\uFCF7': '\u0639\u0649', + '\uFCF8': '\u0639\u064A', + '\uFCF9': '\u063A\u0649', + '\uFCFA': '\u063A\u064A', + '\uFCFB': '\u0633\u0649', + '\uFCFC': '\u0633\u064A', + '\uFCFD': '\u0634\u0649', + '\uFCFE': '\u0634\u064A', + '\uFCFF': '\u062D\u0649', + '\uFD00': '\u062D\u064A', + '\uFD01': '\u062C\u0649', + '\uFD02': '\u062C\u064A', + '\uFD03': '\u062E\u0649', + '\uFD04': '\u062E\u064A', + '\uFD05': '\u0635\u0649', + '\uFD06': '\u0635\u064A', + '\uFD07': '\u0636\u0649', + '\uFD08': '\u0636\u064A', + '\uFD09': '\u0634\u062C', + '\uFD0A': '\u0634\u062D', + '\uFD0B': '\u0634\u062E', + '\uFD0C': '\u0634\u0645', + '\uFD0D': '\u0634\u0631', + '\uFD0E': '\u0633\u0631', + '\uFD0F': '\u0635\u0631', + '\uFD10': '\u0636\u0631', + '\uFD11': '\u0637\u0649', + '\uFD12': '\u0637\u064A', + '\uFD13': '\u0639\u0649', + '\uFD14': '\u0639\u064A', + '\uFD15': '\u063A\u0649', + '\uFD16': '\u063A\u064A', + '\uFD17': '\u0633\u0649', + '\uFD18': '\u0633\u064A', + '\uFD19': '\u0634\u0649', + '\uFD1A': '\u0634\u064A', + '\uFD1B': '\u062D\u0649', + '\uFD1C': '\u062D\u064A', + '\uFD1D': '\u062C\u0649', + '\uFD1E': '\u062C\u064A', + '\uFD1F': '\u062E\u0649', + '\uFD20': '\u062E\u064A', + '\uFD21': '\u0635\u0649', + '\uFD22': '\u0635\u064A', + '\uFD23': '\u0636\u0649', + '\uFD24': '\u0636\u064A', + '\uFD25': '\u0634\u062C', + '\uFD26': '\u0634\u062D', + '\uFD27': '\u0634\u062E', + '\uFD28': '\u0634\u0645', + '\uFD29': '\u0634\u0631', + '\uFD2A': '\u0633\u0631', + '\uFD2B': '\u0635\u0631', + '\uFD2C': '\u0636\u0631', + '\uFD2D': '\u0634\u062C', + '\uFD2E': '\u0634\u062D', + '\uFD2F': '\u0634\u062E', + '\uFD30': '\u0634\u0645', + '\uFD31': '\u0633\u0647', + '\uFD32': '\u0634\u0647', + '\uFD33': '\u0637\u0645', + '\uFD34': '\u0633\u062C', + '\uFD35': '\u0633\u062D', + '\uFD36': '\u0633\u062E', + '\uFD37': '\u0634\u062C', + '\uFD38': '\u0634\u062D', + '\uFD39': '\u0634\u062E', + '\uFD3A': '\u0637\u0645', + '\uFD3B': '\u0638\u0645', + '\uFD3C': '\u0627\u064B', + '\uFD3D': '\u0627\u064B', + '\uFD50': '\u062A\u062C\u0645', + '\uFD51': '\u062A\u062D\u062C', + '\uFD52': '\u062A\u062D\u062C', + '\uFD53': '\u062A\u062D\u0645', + '\uFD54': '\u062A\u062E\u0645', + '\uFD55': '\u062A\u0645\u062C', + '\uFD56': '\u062A\u0645\u062D', + '\uFD57': '\u062A\u0645\u062E', + '\uFD58': '\u062C\u0645\u062D', + '\uFD59': '\u062C\u0645\u062D', + '\uFD5A': '\u062D\u0645\u064A', + '\uFD5B': '\u062D\u0645\u0649', + '\uFD5C': '\u0633\u062D\u062C', + '\uFD5D': '\u0633\u062C\u062D', + '\uFD5E': '\u0633\u062C\u0649', + '\uFD5F': '\u0633\u0645\u062D', + '\uFD60': '\u0633\u0645\u062D', + '\uFD61': '\u0633\u0645\u062C', + '\uFD62': '\u0633\u0645\u0645', + '\uFD63': '\u0633\u0645\u0645', + '\uFD64': '\u0635\u062D\u062D', + '\uFD65': '\u0635\u062D\u062D', + '\uFD66': '\u0635\u0645\u0645', + '\uFD67': '\u0634\u062D\u0645', + '\uFD68': '\u0634\u062D\u0645', + '\uFD69': '\u0634\u062C\u064A', + '\uFD6A': '\u0634\u0645\u062E', + '\uFD6B': '\u0634\u0645\u062E', + '\uFD6C': '\u0634\u0645\u0645', + '\uFD6D': '\u0634\u0645\u0645', + '\uFD6E': '\u0636\u062D\u0649', + '\uFD6F': '\u0636\u062E\u0645', + '\uFD70': '\u0636\u062E\u0645', + '\uFD71': '\u0637\u0645\u062D', + '\uFD72': '\u0637\u0645\u062D', + '\uFD73': '\u0637\u0645\u0645', + '\uFD74': '\u0637\u0645\u064A', + '\uFD75': '\u0639\u062C\u0645', + '\uFD76': '\u0639\u0645\u0645', + '\uFD77': '\u0639\u0645\u0645', + '\uFD78': '\u0639\u0645\u0649', + '\uFD79': '\u063A\u0645\u0645', + '\uFD7A': '\u063A\u0645\u064A', + '\uFD7B': '\u063A\u0645\u0649', + '\uFD7C': '\u0641\u062E\u0645', + '\uFD7D': '\u0641\u062E\u0645', + '\uFD7E': '\u0642\u0645\u062D', + '\uFD7F': '\u0642\u0645\u0645', + '\uFD80': '\u0644\u062D\u0645', + '\uFD81': '\u0644\u062D\u064A', + '\uFD82': '\u0644\u062D\u0649', + '\uFD83': '\u0644\u062C\u062C', + '\uFD84': '\u0644\u062C\u062C', + '\uFD85': '\u0644\u062E\u0645', + '\uFD86': '\u0644\u062E\u0645', + '\uFD87': '\u0644\u0645\u062D', + '\uFD88': '\u0644\u0645\u062D', + '\uFD89': '\u0645\u062D\u062C', + '\uFD8A': '\u0645\u062D\u0645', + '\uFD8B': '\u0645\u062D\u064A', + '\uFD8C': '\u0645\u062C\u062D', + '\uFD8D': '\u0645\u062C\u0645', + '\uFD8E': '\u0645\u062E\u062C', + '\uFD8F': '\u0645\u062E\u0645', + '\uFD92': '\u0645\u062C\u062E', + '\uFD93': '\u0647\u0645\u062C', + '\uFD94': '\u0647\u0645\u0645', + '\uFD95': '\u0646\u062D\u0645', + '\uFD96': '\u0646\u062D\u0649', + '\uFD97': '\u0646\u062C\u0645', + '\uFD98': '\u0646\u062C\u0645', + '\uFD99': '\u0646\u062C\u0649', + '\uFD9A': '\u0646\u0645\u064A', + '\uFD9B': '\u0646\u0645\u0649', + '\uFD9C': '\u064A\u0645\u0645', + '\uFD9D': '\u064A\u0645\u0645', + '\uFD9E': '\u0628\u062E\u064A', + '\uFD9F': '\u062A\u062C\u064A', + '\uFDA0': '\u062A\u062C\u0649', + '\uFDA1': '\u062A\u062E\u064A', + '\uFDA2': '\u062A\u062E\u0649', + '\uFDA3': '\u062A\u0645\u064A', + '\uFDA4': '\u062A\u0645\u0649', + '\uFDA5': '\u062C\u0645\u064A', + '\uFDA6': '\u062C\u062D\u0649', + '\uFDA7': '\u062C\u0645\u0649', + '\uFDA8': '\u0633\u062E\u0649', + '\uFDA9': '\u0635\u062D\u064A', + '\uFDAA': '\u0634\u062D\u064A', + '\uFDAB': '\u0636\u062D\u064A', + '\uFDAC': '\u0644\u062C\u064A', + '\uFDAD': '\u0644\u0645\u064A', + '\uFDAE': '\u064A\u062D\u064A', + '\uFDAF': '\u064A\u062C\u064A', + '\uFDB0': '\u064A\u0645\u064A', + '\uFDB1': '\u0645\u0645\u064A', + '\uFDB2': '\u0642\u0645\u064A', + '\uFDB3': '\u0646\u062D\u064A', + '\uFDB4': '\u0642\u0645\u062D', + '\uFDB5': '\u0644\u062D\u0645', + '\uFDB6': '\u0639\u0645\u064A', + '\uFDB7': '\u0643\u0645\u064A', + '\uFDB8': '\u0646\u062C\u062D', + '\uFDB9': '\u0645\u062E\u064A', + '\uFDBA': '\u0644\u062C\u0645', + '\uFDBB': '\u0643\u0645\u0645', + '\uFDBC': '\u0644\u062C\u0645', + '\uFDBD': '\u0646\u062C\u062D', + '\uFDBE': '\u062C\u062D\u064A', + '\uFDBF': '\u062D\u062C\u064A', + '\uFDC0': '\u0645\u062C\u064A', + '\uFDC1': '\u0641\u0645\u064A', + '\uFDC2': '\u0628\u062D\u064A', + '\uFDC3': '\u0643\u0645\u0645', + '\uFDC4': '\u0639\u062C\u0645', + '\uFDC5': '\u0635\u0645\u0645', + '\uFDC6': '\u0633\u062E\u064A', + '\uFDC7': '\u0646\u062C\u064A', + '\uFE49': '\u203E', + '\uFE4A': '\u203E', + '\uFE4B': '\u203E', + '\uFE4C': '\u203E', + '\uFE4D': '\u005F', + '\uFE4E': '\u005F', + '\uFE4F': '\u005F', + '\uFE80': '\u0621', + '\uFE81': '\u0622', + '\uFE82': '\u0622', + '\uFE83': '\u0623', + '\uFE84': '\u0623', + '\uFE85': '\u0624', + '\uFE86': '\u0624', + '\uFE87': '\u0625', + '\uFE88': '\u0625', + '\uFE89': '\u0626', + '\uFE8A': '\u0626', + '\uFE8B': '\u0626', + '\uFE8C': '\u0626', + '\uFE8D': '\u0627', + '\uFE8E': '\u0627', + '\uFE8F': '\u0628', + '\uFE90': '\u0628', + '\uFE91': '\u0628', + '\uFE92': '\u0628', + '\uFE93': '\u0629', + '\uFE94': '\u0629', + '\uFE95': '\u062A', + '\uFE96': '\u062A', + '\uFE97': '\u062A', + '\uFE98': '\u062A', + '\uFE99': '\u062B', + '\uFE9A': '\u062B', + '\uFE9B': '\u062B', + '\uFE9C': '\u062B', + '\uFE9D': '\u062C', + '\uFE9E': '\u062C', + '\uFE9F': '\u062C', + '\uFEA0': '\u062C', + '\uFEA1': '\u062D', + '\uFEA2': '\u062D', + '\uFEA3': '\u062D', + '\uFEA4': '\u062D', + '\uFEA5': '\u062E', + '\uFEA6': '\u062E', + '\uFEA7': '\u062E', + '\uFEA8': '\u062E', + '\uFEA9': '\u062F', + '\uFEAA': '\u062F', + '\uFEAB': '\u0630', + '\uFEAC': '\u0630', + '\uFEAD': '\u0631', + '\uFEAE': '\u0631', + '\uFEAF': '\u0632', + '\uFEB0': '\u0632', + '\uFEB1': '\u0633', + '\uFEB2': '\u0633', + '\uFEB3': '\u0633', + '\uFEB4': '\u0633', + '\uFEB5': '\u0634', + '\uFEB6': '\u0634', + '\uFEB7': '\u0634', + '\uFEB8': '\u0634', + '\uFEB9': '\u0635', + '\uFEBA': '\u0635', + '\uFEBB': '\u0635', + '\uFEBC': '\u0635', + '\uFEBD': '\u0636', + '\uFEBE': '\u0636', + '\uFEBF': '\u0636', + '\uFEC0': '\u0636', + '\uFEC1': '\u0637', + '\uFEC2': '\u0637', + '\uFEC3': '\u0637', + '\uFEC4': '\u0637', + '\uFEC5': '\u0638', + '\uFEC6': '\u0638', + '\uFEC7': '\u0638', + '\uFEC8': '\u0638', + '\uFEC9': '\u0639', + '\uFECA': '\u0639', + '\uFECB': '\u0639', + '\uFECC': '\u0639', + '\uFECD': '\u063A', + '\uFECE': '\u063A', + '\uFECF': '\u063A', + '\uFED0': '\u063A', + '\uFED1': '\u0641', + '\uFED2': '\u0641', + '\uFED3': '\u0641', + '\uFED4': '\u0641', + '\uFED5': '\u0642', + '\uFED6': '\u0642', + '\uFED7': '\u0642', + '\uFED8': '\u0642', + '\uFED9': '\u0643', + '\uFEDA': '\u0643', + '\uFEDB': '\u0643', + '\uFEDC': '\u0643', + '\uFEDD': '\u0644', + '\uFEDE': '\u0644', + '\uFEDF': '\u0644', + '\uFEE0': '\u0644', + '\uFEE1': '\u0645', + '\uFEE2': '\u0645', + '\uFEE3': '\u0645', + '\uFEE4': '\u0645', + '\uFEE5': '\u0646', + '\uFEE6': '\u0646', + '\uFEE7': '\u0646', + '\uFEE8': '\u0646', + '\uFEE9': '\u0647', + '\uFEEA': '\u0647', + '\uFEEB': '\u0647', + '\uFEEC': '\u0647', + '\uFEED': '\u0648', + '\uFEEE': '\u0648', + '\uFEEF': '\u0649', + '\uFEF0': '\u0649', + '\uFEF1': '\u064A', + '\uFEF2': '\u064A', + '\uFEF3': '\u064A', + '\uFEF4': '\u064A', + '\uFEF5': '\u0644\u0622', + '\uFEF6': '\u0644\u0622', + '\uFEF7': '\u0644\u0623', + '\uFEF8': '\u0644\u0623', + '\uFEF9': '\u0644\u0625', + '\uFEFA': '\u0644\u0625', + '\uFEFB': '\u0644\u0627', + '\uFEFC': '\u0644\u0627' +}; + +function reverseIfRtl(chars) { + var charsLength = chars.length; + //reverse an arabic ligature + if (charsLength <= 1 || !isRTLRangeFor(chars.charCodeAt(0))) { + return chars; + } + var s = ''; + for (var ii = charsLength - 1; ii >= 0; ii--) { + s += chars[ii]; + } + return s; +} + +function adjustWidths(properties) { + if (properties.fontMatrix[0] === FONT_IDENTITY_MATRIX[0]) { + return; + } + // adjusting width to fontMatrix scale + var scale = 0.001 / properties.fontMatrix[0]; + var glyphsWidths = properties.widths; + for (var glyph in glyphsWidths) { + glyphsWidths[glyph] *= scale; + } + properties.defaultWidth *= scale; +} + +function getFontType(type, subtype) { + switch (type) { + case 'Type1': + return subtype === 'Type1C' ? FontType.TYPE1C : FontType.TYPE1; + case 'CIDFontType0': + return subtype === 'CIDFontType0C' ? FontType.CIDFONTTYPE0C : + FontType.CIDFONTTYPE0; + case 'OpenType': + return FontType.OPENTYPE; + case 'TrueType': + return FontType.TRUETYPE; + case 'CIDFontType2': + return FontType.CIDFONTTYPE2; + case 'MMType1': + return FontType.MMTYPE1; + case 'Type0': + return FontType.TYPE0; + default: + return FontType.UNKNOWN; + } +} + +var Glyph = (function GlyphClosure() { + function Glyph(fontChar, unicode, accent, width, vmetric, operatorListId) { + this.fontChar = fontChar; + this.unicode = unicode; + this.accent = accent; + this.width = width; + this.vmetric = vmetric; + this.operatorListId = operatorListId; + } + + Glyph.prototype.matchesForCache = + function(fontChar, unicode, accent, width, vmetric, operatorListId) { + return this.fontChar === fontChar && + this.unicode === unicode && + this.accent === accent && + this.width === width && + this.vmetric === vmetric && + this.operatorListId === operatorListId; + }; + + return Glyph; +})(); + +var ToUnicodeMap = (function ToUnicodeMapClosure() { + function ToUnicodeMap(cmap) { + // The elements of this._map can be integers or strings, depending on how + // |cmap| was created. + this._map = cmap; + } + + ToUnicodeMap.prototype = { + get length() { + return this._map.length; + }, + + forEach: function(callback) { + for (var charCode in this._map) { + callback(charCode, this._map[charCode].charCodeAt(0)); + } + }, + + has: function(i) { + return this._map[i] !== undefined; + }, + + get: function(i) { + return this._map[i]; + }, + + charCodeOf: function(v) { + return this._map.indexOf(v); + } + }; + + return ToUnicodeMap; +})(); + +var IdentityToUnicodeMap = (function IdentityToUnicodeMapClosure() { + function IdentityToUnicodeMap(firstChar, lastChar) { + this.firstChar = firstChar; + this.lastChar = lastChar; + } + + IdentityToUnicodeMap.prototype = { + get length() { + return (this.lastChar + 1) - this.firstChar; + }, + + forEach: function (callback) { + for (var i = this.firstChar, ii = this.lastChar; i <= ii; i++) { + callback(i, i); + } + }, + + has: function (i) { + return this.firstChar <= i && i <= this.lastChar; + }, + + get: function (i) { + if (this.firstChar <= i && i <= this.lastChar) { + return String.fromCharCode(i); + } + return undefined; + }, + + charCodeOf: function (v) { + error('should not call .charCodeOf'); + } + }; + + return IdentityToUnicodeMap; +})(); + +var OpenTypeFileBuilder = (function OpenTypeFileBuilderClosure() { + function writeInt16(dest, offset, num) { + dest[offset] = (num >> 8) & 0xFF; + dest[offset + 1] = num & 0xFF; + } + + function writeInt32(dest, offset, num) { + dest[offset] = (num >> 24) & 0xFF; + dest[offset + 1] = (num >> 16) & 0xFF; + dest[offset + 2] = (num >> 8) & 0xFF; + dest[offset + 3] = num & 0xFF; + } + + function writeData(dest, offset, data) { + var i, ii; + if (data instanceof Uint8Array) { + dest.set(data, offset); + } else if (typeof data === 'string') { + for (i = 0, ii = data.length; i < ii; i++) { + dest[offset++] = data.charCodeAt(i) & 0xFF; + } + } else { + // treating everything else as array + for (i = 0, ii = data.length; i < ii; i++) { + dest[offset++] = data[i] & 0xFF; + } + } + } + + function OpenTypeFileBuilder(sfnt) { + this.sfnt = sfnt; + this.tables = Object.create(null); + } + + OpenTypeFileBuilder.getSearchParams = + function OpenTypeFileBuilder_getSearchParams(entriesCount, entrySize) { + var maxPower2 = 1, log2 = 0; + while ((maxPower2 ^ entriesCount) > maxPower2) { + maxPower2 <<= 1; + log2++; + } + var searchRange = maxPower2 * entrySize; + return { + range: searchRange, + entry: log2, + rangeShift: entrySize * entriesCount - searchRange + }; + }; + + var OTF_HEADER_SIZE = 12; + var OTF_TABLE_ENTRY_SIZE = 16; + + OpenTypeFileBuilder.prototype = { + toArray: function OpenTypeFileBuilder_toArray() { + var sfnt = this.sfnt; + + // Tables needs to be written by ascendant alphabetic order + var tables = this.tables; + var tablesNames = Object.keys(tables); + tablesNames.sort(); + var numTables = tablesNames.length; + + var i, j, jj, table, tableName; + // layout the tables data + var offset = OTF_HEADER_SIZE + numTables * OTF_TABLE_ENTRY_SIZE; + var tableOffsets = [offset]; + for (i = 0; i < numTables; i++) { + table = tables[tablesNames[i]]; + var paddedLength = ((table.length + 3) & ~3) >>> 0; + offset += paddedLength; + tableOffsets.push(offset); + } + + var file = new Uint8Array(offset); + // write the table data first (mostly for checksum) + for (i = 0; i < numTables; i++) { + table = tables[tablesNames[i]]; + writeData(file, tableOffsets[i], table); + } + + // sfnt version (4 bytes) + if (sfnt === 'true') { + // Windows hates the Mac TrueType sfnt version number + sfnt = string32(0x00010000); + } + file[0] = sfnt.charCodeAt(0) & 0xFF; + file[1] = sfnt.charCodeAt(1) & 0xFF; + file[2] = sfnt.charCodeAt(2) & 0xFF; + file[3] = sfnt.charCodeAt(3) & 0xFF; + + // numTables (2 bytes) + writeInt16(file, 4, numTables); + + var searchParams = OpenTypeFileBuilder.getSearchParams(numTables, 16); + + // searchRange (2 bytes) + writeInt16(file, 6, searchParams.range); + // entrySelector (2 bytes) + writeInt16(file, 8, searchParams.entry); + // rangeShift (2 bytes) + writeInt16(file, 10, searchParams.rangeShift); + + offset = OTF_HEADER_SIZE; + // writing table entries + for (i = 0; i < numTables; i++) { + tableName = tablesNames[i]; + file[offset] = tableName.charCodeAt(0) & 0xFF; + file[offset + 1] = tableName.charCodeAt(1) & 0xFF; + file[offset + 2] = tableName.charCodeAt(2) & 0xFF; + file[offset + 3] = tableName.charCodeAt(3) & 0xFF; + + // checksum + var checksum = 0; + for (j = tableOffsets[i], jj = tableOffsets[i + 1]; j < jj; j += 4) { + var quad = (file[j] << 24) + (file[j + 1] << 16) + + (file[j + 2] << 8) + file[j + 3]; + checksum = (checksum + quad) | 0; + } + writeInt32(file, offset + 4, checksum); + + // offset + writeInt32(file, offset + 8, tableOffsets[i]); + // length + writeInt32(file, offset + 12, tables[tableName].length); + + offset += OTF_TABLE_ENTRY_SIZE; + } + return file; + }, + + addTable: function OpenTypeFileBuilder_addTable(tag, data) { + if (tag in this.tables) { + throw new Error('Table ' + tag + ' already exists'); + } + this.tables[tag] = data; + } + }; + + return OpenTypeFileBuilder; +})(); + +/** + * 'Font' is the class the outside world should use, it encapsulate all the font + * decoding logics whatever type it is (assuming the font type is supported). + * + * For example to read a Type1 font and to attach it to the document: + * var type1Font = new Font("MyFontName", binaryFile, propertiesObject); + * type1Font.bind(); + */ +var Font = (function FontClosure() { + function Font(name, file, properties) { + var charCode, glyphName, fontChar; + + this.name = name; + this.loadedName = properties.loadedName; + this.isType3Font = properties.isType3Font; + this.sizes = []; + + this.glyphCache = {}; + + var names = name.split('+'); + names = names.length > 1 ? names[1] : names[0]; + names = names.split(/[-,_]/g)[0]; + this.isSerifFont = !!(properties.flags & FontFlags.Serif); + this.isSymbolicFont = !!(properties.flags & FontFlags.Symbolic); + this.isMonospace = !!(properties.flags & FontFlags.FixedPitch); + + var type = properties.type; + var subtype = properties.subtype; + this.type = type; + + this.fallbackName = (this.isMonospace ? 'monospace' : + (this.isSerifFont ? 'serif' : 'sans-serif')); + + this.differences = properties.differences; + this.widths = properties.widths; + this.defaultWidth = properties.defaultWidth; + this.composite = properties.composite; + this.wideChars = properties.wideChars; + this.cMap = properties.cMap; + this.ascent = properties.ascent / PDF_GLYPH_SPACE_UNITS; + this.descent = properties.descent / PDF_GLYPH_SPACE_UNITS; + this.fontMatrix = properties.fontMatrix; + + this.toUnicode = properties.toUnicode = this.buildToUnicode(properties); + + this.toFontChar = []; + + if (properties.type === 'Type3') { + for (charCode = 0; charCode < 256; charCode++) { + this.toFontChar[charCode] = (this.differences[charCode] || + properties.defaultEncoding[charCode]); + } + this.fontType = FontType.TYPE3; + return; + } + + this.cidEncoding = properties.cidEncoding; + this.vertical = properties.vertical; + if (this.vertical) { + this.vmetrics = properties.vmetrics; + this.defaultVMetrics = properties.defaultVMetrics; + } + + if (!file || file.isEmpty) { + if (file) { + // Some bad PDF generators will include empty font files, + // attempting to recover by assuming that no file exists. + warn('Font file is empty in "' + name + '" (' + this.loadedName + ')'); + } + + this.missingFile = true; + // The file data is not specified. Trying to fix the font name + // to be used with the canvas.font. + var fontName = name.replace(/[,_]/g, '-'); + var isStandardFont = !!stdFontMap[fontName] || + !!(nonStdFontMap[fontName] && stdFontMap[nonStdFontMap[fontName]]); + fontName = stdFontMap[fontName] || nonStdFontMap[fontName] || fontName; + + this.bold = (fontName.search(/bold/gi) !== -1); + this.italic = ((fontName.search(/oblique/gi) !== -1) || + (fontName.search(/italic/gi) !== -1)); + + // Use 'name' instead of 'fontName' here because the original + // name ArialBlack for example will be replaced by Helvetica. + this.black = (name.search(/Black/g) !== -1); + + // if at least one width is present, remeasure all chars when exists + this.remeasure = Object.keys(this.widths).length > 0; + if (isStandardFont && type === 'CIDFontType2' && + properties.cidEncoding.indexOf('Identity-') === 0) { + // Standard fonts might be embedded as CID font without glyph mapping. + // Building one based on GlyphMapForStandardFonts. + var map = []; + for (var code in GlyphMapForStandardFonts) { + map[+code] = GlyphMapForStandardFonts[code]; + } + var isIdentityUnicode = this.toUnicode instanceof IdentityToUnicodeMap; + if (!isIdentityUnicode) { + this.toUnicode.forEach(function(charCode, unicodeCharCode) { + map[+charCode] = unicodeCharCode; + }); + } + this.toFontChar = map; + this.toUnicode = new ToUnicodeMap(map); + } else if (/Symbol/i.test(fontName)) { + var symbols = Encodings.SymbolSetEncoding; + for (charCode in symbols) { + fontChar = GlyphsUnicode[symbols[charCode]]; + if (!fontChar) { + continue; + } + this.toFontChar[charCode] = fontChar; + } + for (charCode in properties.differences) { + fontChar = GlyphsUnicode[properties.differences[charCode]]; + if (!fontChar) { + continue; + } + this.toFontChar[charCode] = fontChar; + } + } else if (/Dingbats/i.test(fontName)) { + if (/Wingdings/i.test(name)) { + warn('Wingdings font without embedded font file, ' + + 'falling back to the ZapfDingbats encoding.'); + } + var dingbats = Encodings.ZapfDingbatsEncoding; + for (charCode in dingbats) { + fontChar = DingbatsGlyphsUnicode[dingbats[charCode]]; + if (!fontChar) { + continue; + } + this.toFontChar[charCode] = fontChar; + } + for (charCode in properties.differences) { + fontChar = DingbatsGlyphsUnicode[properties.differences[charCode]]; + if (!fontChar) { + continue; + } + this.toFontChar[charCode] = fontChar; + } + } else if (isStandardFont) { + this.toFontChar = []; + for (charCode in properties.defaultEncoding) { + glyphName = (properties.differences[charCode] || + properties.defaultEncoding[charCode]); + this.toFontChar[charCode] = GlyphsUnicode[glyphName]; + } + } else { + var unicodeCharCode, notCidFont = (type.indexOf('CIDFontType') === -1); + this.toUnicode.forEach(function(charCode, unicodeCharCode) { + if (notCidFont) { + glyphName = (properties.differences[charCode] || + properties.defaultEncoding[charCode]); + unicodeCharCode = (GlyphsUnicode[glyphName] || unicodeCharCode); + } + this.toFontChar[charCode] = unicodeCharCode; + }.bind(this)); + } + this.loadedName = fontName.split('-')[0]; + this.loading = false; + this.fontType = getFontType(type, subtype); + return; + } + + // Some fonts might use wrong font types for Type1C or CIDFontType0C + if (subtype === 'Type1C' && (type !== 'Type1' && type !== 'MMType1')) { + // Some TrueType fonts by mistake claim Type1C + if (isTrueTypeFile(file)) { + subtype = 'TrueType'; + } else { + type = 'Type1'; + } + } + if (subtype === 'CIDFontType0C' && type !== 'CIDFontType0') { + type = 'CIDFontType0'; + } + if (subtype === 'OpenType') { + type = 'OpenType'; + } + // Some CIDFontType0C fonts by mistake claim CIDFontType0. + if (type === 'CIDFontType0') { + subtype = isType1File(file) ? 'CIDFontType0' : 'CIDFontType0C'; + } + + var data; + switch (type) { + case 'MMType1': + info('MMType1 font (' + name + '), falling back to Type1.'); + /* falls through */ + case 'Type1': + case 'CIDFontType0': + this.mimetype = 'font/opentype'; + + var cff = (subtype === 'Type1C' || subtype === 'CIDFontType0C') ? + new CFFFont(file, properties) : new Type1Font(name, file, properties); + + adjustWidths(properties); + + // Wrap the CFF data inside an OTF font file + data = this.convert(name, cff, properties); + break; + + case 'OpenType': + case 'TrueType': + case 'CIDFontType2': + this.mimetype = 'font/opentype'; + + // Repair the TrueType file. It is can be damaged in the point of + // view of the sanitizer + data = this.checkAndRepair(name, file, properties); + if (this.isOpenType) { + type = 'OpenType'; + } + break; + + default: + error('Font ' + type + ' is not supported'); + break; + } + + this.data = data; + this.fontType = getFontType(type, subtype); + + // Transfer some properties again that could change during font conversion + this.fontMatrix = properties.fontMatrix; + this.widths = properties.widths; + this.defaultWidth = properties.defaultWidth; + this.encoding = properties.baseEncoding; + this.seacMap = properties.seacMap; + + this.loading = true; + } + + Font.getFontID = (function () { + var ID = 1; + return function Font_getFontID() { + return String(ID++); + }; + })(); + + function int16(b0, b1) { + return (b0 << 8) + b1; + } + + function int32(b0, b1, b2, b3) { + return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3; + } + + function string16(value) { + return String.fromCharCode((value >> 8) & 0xff, value & 0xff); + } + + function safeString16(value) { + // clamp value to the 16-bit int range + value = (value > 0x7FFF ? 0x7FFF : (value < -0x8000 ? -0x8000 : value)); + return String.fromCharCode((value >> 8) & 0xff, value & 0xff); + } + + function isTrueTypeFile(file) { + var header = file.peekBytes(4); + return readUint32(header, 0) === 0x00010000; + } + + function isType1File(file) { + var header = file.peekBytes(2); + // All Type1 font programs must begin with the comment '%!' (0x25 + 0x21). + if (header[0] === 0x25 && header[1] === 0x21) { + return true; + } + // ... obviously some fonts violate that part of the specification, + // please refer to the comment in |Type1Font| below. + if (header[0] === 0x80 && header[1] === 0x01) { // pfb file header. + return true; + } + return false; + } + + /** + * Helper function for |adjustMapping|. + * @return {boolean} + */ + function isProblematicUnicodeLocation(code) { + if (code <= 0x1F) { // Control chars + return true; + } + if (code >= 0x80 && code <= 0x9F) { // Control chars + return true; + } + if ((code >= 0x2000 && code <= 0x200F) || // General punctuation chars + (code >= 0x2028 && code <= 0x202F) || + (code >= 0x2060 && code <= 0x206F)) { + return true; + } + if (code >= 0xFFF0 && code <= 0xFFFF) { // Specials Unicode block + return true; + } + switch (code) { + case 0x7F: // Control char + case 0xA0: // Non breaking space + case 0xAD: // Soft hyphen + case 0x0E33: // Thai character SARA AM + case 0x2011: // Non breaking hyphen + case 0x205F: // Medium mathematical space + case 0x25CC: // Dotted circle (combining mark) + return true; + } + return false; + } + + /** + * Rebuilds the char code to glyph ID map by trying to replace the char codes + * with their unicode value. It also moves char codes that are in known + * problematic locations. + * @return {Object} Two properties: + * 'toFontChar' - maps original char codes(the value that will be read + * from commands such as show text) to the char codes that will be used in the + * font that we build + * 'charCodeToGlyphId' - maps the new font char codes to glyph ids + */ + function adjustMapping(charCodeToGlyphId, properties) { + var toUnicode = properties.toUnicode; + var isSymbolic = !!(properties.flags & FontFlags.Symbolic); + var isIdentityUnicode = + properties.toUnicode instanceof IdentityToUnicodeMap; + var newMap = Object.create(null); + var toFontChar = []; + var usedFontCharCodes = []; + var nextAvailableFontCharCode = PRIVATE_USE_OFFSET_START; + for (var originalCharCode in charCodeToGlyphId) { + originalCharCode |= 0; + var glyphId = charCodeToGlyphId[originalCharCode]; + var fontCharCode = originalCharCode; + // First try to map the value to a unicode position if a non identity map + // was created. + if (!isIdentityUnicode && toUnicode.has(originalCharCode)) { + var unicode = toUnicode.get(fontCharCode); + // TODO: Try to map ligatures to the correct spot. + if (unicode.length === 1) { + fontCharCode = unicode.charCodeAt(0); + } + } + // Try to move control characters, special characters and already mapped + // characters to the private use area since they will not be drawn by + // canvas if left in their current position. Also, move characters if the + // font was symbolic and there is only an identity unicode map since the + // characters probably aren't in the correct position (fixes an issue + // with firefox and thuluthfont). + if ((usedFontCharCodes[fontCharCode] !== undefined || + isProblematicUnicodeLocation(fontCharCode) || + (isSymbolic && isIdentityUnicode)) && + nextAvailableFontCharCode <= PRIVATE_USE_OFFSET_END) { // Room left. + // Loop to try and find a free spot in the private use area. + do { + fontCharCode = nextAvailableFontCharCode++; + + if (SKIP_PRIVATE_USE_RANGE_F000_TO_F01F && fontCharCode === 0xF000) { + fontCharCode = 0xF020; + nextAvailableFontCharCode = fontCharCode + 1; + } + + } while (usedFontCharCodes[fontCharCode] !== undefined && + nextAvailableFontCharCode <= PRIVATE_USE_OFFSET_END); + } + + newMap[fontCharCode] = glyphId; + toFontChar[originalCharCode] = fontCharCode; + usedFontCharCodes[fontCharCode] = true; + } + return { + toFontChar: toFontChar, + charCodeToGlyphId: newMap, + nextAvailableFontCharCode: nextAvailableFontCharCode + }; + } + + function getRanges(glyphs) { + // Array.sort() sorts by characters, not numerically, so convert to an + // array of characters. + var codes = []; + for (var charCode in glyphs) { + codes.push({ fontCharCode: charCode | 0, glyphId: glyphs[charCode] }); + } + codes.sort(function fontGetRangesSort(a, b) { + return a.fontCharCode - b.fontCharCode; + }); + + // Split the sorted codes into ranges. + var ranges = []; + var length = codes.length; + for (var n = 0; n < length; ) { + var start = codes[n].fontCharCode; + var codeIndices = [codes[n].glyphId]; + ++n; + var end = start; + while (n < length && end + 1 === codes[n].fontCharCode) { + codeIndices.push(codes[n].glyphId); + ++end; + ++n; + if (end === 0xFFFF) { + break; + } + } + ranges.push([start, end, codeIndices]); + } + + return ranges; + } + + function createCmapTable(glyphs) { + var ranges = getRanges(glyphs); + var numTables = ranges[ranges.length - 1][1] > 0xFFFF ? 2 : 1; + var cmap = '\x00\x00' + // version + string16(numTables) + // numTables + '\x00\x03' + // platformID + '\x00\x01' + // encodingID + string32(4 + numTables * 8); // start of the table record + + var i, ii, j, jj; + for (i = ranges.length - 1; i >= 0; --i) { + if (ranges[i][0] <= 0xFFFF) { break; } + } + var bmpLength = i + 1; + + if (ranges[i][0] < 0xFFFF && ranges[i][1] === 0xFFFF) { + ranges[i][1] = 0xFFFE; + } + var trailingRangesCount = ranges[i][1] < 0xFFFF ? 1 : 0; + var segCount = bmpLength + trailingRangesCount; + var searchParams = OpenTypeFileBuilder.getSearchParams(segCount, 2); + + // Fill up the 4 parallel arrays describing the segments. + var startCount = ''; + var endCount = ''; + var idDeltas = ''; + var idRangeOffsets = ''; + var glyphsIds = ''; + var bias = 0; + + var range, start, end, codes; + for (i = 0, ii = bmpLength; i < ii; i++) { + range = ranges[i]; + start = range[0]; + end = range[1]; + startCount += string16(start); + endCount += string16(end); + codes = range[2]; + var contiguous = true; + for (j = 1, jj = codes.length; j < jj; ++j) { + if (codes[j] !== codes[j - 1] + 1) { + contiguous = false; + break; + } + } + if (!contiguous) { + var offset = (segCount - i) * 2 + bias * 2; + bias += (end - start + 1); + + idDeltas += string16(0); + idRangeOffsets += string16(offset); + + for (j = 0, jj = codes.length; j < jj; ++j) { + glyphsIds += string16(codes[j]); + } + } else { + var startCode = codes[0]; + + idDeltas += string16((startCode - start) & 0xFFFF); + idRangeOffsets += string16(0); + } + } + + if (trailingRangesCount > 0) { + endCount += '\xFF\xFF'; + startCount += '\xFF\xFF'; + idDeltas += '\x00\x01'; + idRangeOffsets += '\x00\x00'; + } + + var format314 = '\x00\x00' + // language + string16(2 * segCount) + + string16(searchParams.range) + + string16(searchParams.entry) + + string16(searchParams.rangeShift) + + endCount + '\x00\x00' + startCount + + idDeltas + idRangeOffsets + glyphsIds; + + var format31012 = ''; + var header31012 = ''; + if (numTables > 1) { + cmap += '\x00\x03' + // platformID + '\x00\x0A' + // encodingID + string32(4 + numTables * 8 + + 4 + format314.length); // start of the table record + format31012 = ''; + for (i = 0, ii = ranges.length; i < ii; i++) { + range = ranges[i]; + start = range[0]; + codes = range[2]; + var code = codes[0]; + for (j = 1, jj = codes.length; j < jj; ++j) { + if (codes[j] !== codes[j - 1] + 1) { + end = range[0] + j - 1; + format31012 += string32(start) + // startCharCode + string32(end) + // endCharCode + string32(code); // startGlyphID + start = end + 1; + code = codes[j]; + } + } + format31012 += string32(start) + // startCharCode + string32(range[1]) + // endCharCode + string32(code); // startGlyphID + } + header31012 = '\x00\x0C' + // format + '\x00\x00' + // reserved + string32(format31012.length + 16) + // length + '\x00\x00\x00\x00' + // language + string32(format31012.length / 12); // nGroups + } + + return cmap + '\x00\x04' + // format + string16(format314.length + 4) + // length + format314 + header31012 + format31012; + } + + function validateOS2Table(os2) { + var stream = new Stream(os2.data); + var version = stream.getUint16(); + // TODO verify all OS/2 tables fields, but currently we validate only those + // that give us issues + stream.getBytes(60); // skipping type, misc sizes, panose, unicode ranges + var selection = stream.getUint16(); + if (version < 4 && (selection & 0x0300)) { + return false; + } + var firstChar = stream.getUint16(); + var lastChar = stream.getUint16(); + if (firstChar > lastChar) { + return false; + } + stream.getBytes(6); // skipping sTypoAscender/Descender/LineGap + var usWinAscent = stream.getUint16(); + if (usWinAscent === 0) { // makes font unreadable by windows + return false; + } + + // OS/2 appears to be valid, resetting some fields + os2.data[8] = os2.data[9] = 0; // IE rejects fonts if fsType != 0 + return true; + } + + function createOS2Table(properties, charstrings, override) { + override = override || { + unitsPerEm: 0, + yMax: 0, + yMin: 0, + ascent: 0, + descent: 0 + }; + + var ulUnicodeRange1 = 0; + var ulUnicodeRange2 = 0; + var ulUnicodeRange3 = 0; + var ulUnicodeRange4 = 0; + + var firstCharIndex = null; + var lastCharIndex = 0; + + if (charstrings) { + for (var code in charstrings) { + code |= 0; + if (firstCharIndex > code || !firstCharIndex) { + firstCharIndex = code; + } + if (lastCharIndex < code) { + lastCharIndex = code; + } + + var position = getUnicodeRangeFor(code); + if (position < 32) { + ulUnicodeRange1 |= 1 << position; + } else if (position < 64) { + ulUnicodeRange2 |= 1 << position - 32; + } else if (position < 96) { + ulUnicodeRange3 |= 1 << position - 64; + } else if (position < 123) { + ulUnicodeRange4 |= 1 << position - 96; + } else { + error('Unicode ranges Bits > 123 are reserved for internal usage'); + } + } + } else { + // TODO + firstCharIndex = 0; + lastCharIndex = 255; + } + + var bbox = properties.bbox || [0, 0, 0, 0]; + var unitsPerEm = (override.unitsPerEm || + 1 / (properties.fontMatrix || FONT_IDENTITY_MATRIX)[0]); + + // if the font units differ to the PDF glyph space units + // then scale up the values + var scale = (properties.ascentScaled ? 1.0 : + unitsPerEm / PDF_GLYPH_SPACE_UNITS); + + var typoAscent = (override.ascent || + Math.round(scale * (properties.ascent || bbox[3]))); + var typoDescent = (override.descent || + Math.round(scale * (properties.descent || bbox[1]))); + if (typoDescent > 0 && properties.descent > 0 && bbox[1] < 0) { + typoDescent = -typoDescent; // fixing incorrect descent + } + var winAscent = override.yMax || typoAscent; + var winDescent = -override.yMin || -typoDescent; + + return '\x00\x03' + // version + '\x02\x24' + // xAvgCharWidth + '\x01\xF4' + // usWeightClass + '\x00\x05' + // usWidthClass + '\x00\x00' + // fstype (0 to let the font loads via font-face on IE) + '\x02\x8A' + // ySubscriptXSize + '\x02\xBB' + // ySubscriptYSize + '\x00\x00' + // ySubscriptXOffset + '\x00\x8C' + // ySubscriptYOffset + '\x02\x8A' + // ySuperScriptXSize + '\x02\xBB' + // ySuperScriptYSize + '\x00\x00' + // ySuperScriptXOffset + '\x01\xDF' + // ySuperScriptYOffset + '\x00\x31' + // yStrikeOutSize + '\x01\x02' + // yStrikeOutPosition + '\x00\x00' + // sFamilyClass + '\x00\x00\x06' + + String.fromCharCode(properties.fixedPitch ? 0x09 : 0x00) + + '\x00\x00\x00\x00\x00\x00' + // Panose + string32(ulUnicodeRange1) + // ulUnicodeRange1 (Bits 0-31) + string32(ulUnicodeRange2) + // ulUnicodeRange2 (Bits 32-63) + string32(ulUnicodeRange3) + // ulUnicodeRange3 (Bits 64-95) + string32(ulUnicodeRange4) + // ulUnicodeRange4 (Bits 96-127) + '\x2A\x32\x31\x2A' + // achVendID + string16(properties.italicAngle ? 1 : 0) + // fsSelection + string16(firstCharIndex || + properties.firstChar) + // usFirstCharIndex + string16(lastCharIndex || properties.lastChar) + // usLastCharIndex + string16(typoAscent) + // sTypoAscender + string16(typoDescent) + // sTypoDescender + '\x00\x64' + // sTypoLineGap (7%-10% of the unitsPerEM value) + string16(winAscent) + // usWinAscent + string16(winDescent) + // usWinDescent + '\x00\x00\x00\x00' + // ulCodePageRange1 (Bits 0-31) + '\x00\x00\x00\x00' + // ulCodePageRange2 (Bits 32-63) + string16(properties.xHeight) + // sxHeight + string16(properties.capHeight) + // sCapHeight + string16(0) + // usDefaultChar + string16(firstCharIndex || properties.firstChar) + // usBreakChar + '\x00\x03'; // usMaxContext + } + + function createPostTable(properties) { + var angle = Math.floor(properties.italicAngle * (Math.pow(2, 16))); + return ('\x00\x03\x00\x00' + // Version number + string32(angle) + // italicAngle + '\x00\x00' + // underlinePosition + '\x00\x00' + // underlineThickness + string32(properties.fixedPitch) + // isFixedPitch + '\x00\x00\x00\x00' + // minMemType42 + '\x00\x00\x00\x00' + // maxMemType42 + '\x00\x00\x00\x00' + // minMemType1 + '\x00\x00\x00\x00'); // maxMemType1 + } + + function createNameTable(name, proto) { + if (!proto) { + proto = [[], []]; // no strings and unicode strings + } + + var strings = [ + proto[0][0] || 'Original licence', // 0.Copyright + proto[0][1] || name, // 1.Font family + proto[0][2] || 'Unknown', // 2.Font subfamily (font weight) + proto[0][3] || 'uniqueID', // 3.Unique ID + proto[0][4] || name, // 4.Full font name + proto[0][5] || 'Version 0.11', // 5.Version + proto[0][6] || '', // 6.Postscript name + proto[0][7] || 'Unknown', // 7.Trademark + proto[0][8] || 'Unknown', // 8.Manufacturer + proto[0][9] || 'Unknown' // 9.Designer + ]; + + // Mac want 1-byte per character strings while Windows want + // 2-bytes per character, so duplicate the names table + var stringsUnicode = []; + var i, ii, j, jj, str; + for (i = 0, ii = strings.length; i < ii; i++) { + str = proto[1][i] || strings[i]; + + var strBufUnicode = []; + for (j = 0, jj = str.length; j < jj; j++) { + strBufUnicode.push(string16(str.charCodeAt(j))); + } + stringsUnicode.push(strBufUnicode.join('')); + } + + var names = [strings, stringsUnicode]; + var platforms = ['\x00\x01', '\x00\x03']; + var encodings = ['\x00\x00', '\x00\x01']; + var languages = ['\x00\x00', '\x04\x09']; + + var namesRecordCount = strings.length * platforms.length; + var nameTable = + '\x00\x00' + // format + string16(namesRecordCount) + // Number of names Record + string16(namesRecordCount * 12 + 6); // Storage + + // Build the name records field + var strOffset = 0; + for (i = 0, ii = platforms.length; i < ii; i++) { + var strs = names[i]; + for (j = 0, jj = strs.length; j < jj; j++) { + str = strs[j]; + var nameRecord = + platforms[i] + // platform ID + encodings[i] + // encoding ID + languages[i] + // language ID + string16(j) + // name ID + string16(str.length) + + string16(strOffset); + nameTable += nameRecord; + strOffset += str.length; + } + } + + nameTable += strings.join('') + stringsUnicode.join(''); + return nameTable; + } + + Font.prototype = { + name: null, + font: null, + mimetype: null, + encoding: null, + get renderer() { + var renderer = FontRendererFactory.create(this); + return shadow(this, 'renderer', renderer); + }, + + exportData: function Font_exportData() { + var data = {}; + for (var i in this) { + if (this.hasOwnProperty(i)) { + data[i] = this[i]; + } + } + return data; + }, + + checkAndRepair: function Font_checkAndRepair(name, font, properties) { + function readTableEntry(file) { + var tag = bytesToString(file.getBytes(4)); + + var checksum = file.getInt32(); + var offset = file.getInt32() >>> 0; + var length = file.getInt32() >>> 0; + + // Read the table associated data + var previousPosition = file.pos; + file.pos = file.start ? file.start : 0; + file.skip(offset); + var data = file.getBytes(length); + file.pos = previousPosition; + + if (tag === 'head') { + // clearing checksum adjustment + data[8] = data[9] = data[10] = data[11] = 0; + data[17] |= 0x20; //Set font optimized for cleartype flag + } + + return { + tag: tag, + checksum: checksum, + length: length, + offset: offset, + data: data + }; + } + + function readOpenTypeHeader(ttf) { + return { + version: bytesToString(ttf.getBytes(4)), + numTables: ttf.getUint16(), + searchRange: ttf.getUint16(), + entrySelector: ttf.getUint16(), + rangeShift: ttf.getUint16() + }; + } + + /** + * Read the appropriate subtable from the cmap according to 9.6.6.4 from + * PDF spec + */ + function readCmapTable(cmap, font, isSymbolicFont) { + var segment; + var start = (font.start ? font.start : 0) + cmap.offset; + font.pos = start; + + var version = font.getUint16(); + var numTables = font.getUint16(); + + var potentialTable; + var canBreak = false; + // There's an order of preference in terms of which cmap subtable to + // use: + // - non-symbolic fonts the preference is a 3,1 table then a 1,0 table + // - symbolic fonts the preference is a 3,0 table then a 1,0 table + // The following takes advantage of the fact that the tables are sorted + // to work. + for (var i = 0; i < numTables; i++) { + var platformId = font.getUint16(); + var encodingId = font.getUint16(); + var offset = font.getInt32() >>> 0; + var useTable = false; + + if (platformId === 0 && encodingId === 0) { + useTable = true; + // Continue the loop since there still may be a higher priority + // table. + } else if (platformId === 1 && encodingId === 0) { + useTable = true; + // Continue the loop since there still may be a higher priority + // table. + } else if (platformId === 3 && encodingId === 1 && + (!isSymbolicFont || !potentialTable)) { + useTable = true; + if (!isSymbolicFont) { + canBreak = true; + } + } else if (isSymbolicFont && platformId === 3 && encodingId === 0) { + useTable = true; + canBreak = true; + } + + if (useTable) { + potentialTable = { + platformId: platformId, + encodingId: encodingId, + offset: offset + }; + } + if (canBreak) { + break; + } + } + + if (!potentialTable) { + warn('Could not find a preferred cmap table.'); + return { + platformId: -1, + encodingId: -1, + mappings: [], + hasShortCmap: false + }; + } + + font.pos = start + potentialTable.offset; + var format = font.getUint16(); + var length = font.getUint16(); + var language = font.getUint16(); + + var hasShortCmap = false; + var mappings = []; + var j, glyphId; + + // TODO(mack): refactor this cmap subtable reading logic out + if (format === 0) { + for (j = 0; j < 256; j++) { + var index = font.getByte(); + if (!index) { + continue; + } + mappings.push({ + charCode: j, + glyphId: index + }); + } + hasShortCmap = true; + } else if (format === 4) { + // re-creating the table in format 4 since the encoding + // might be changed + var segCount = (font.getUint16() >> 1); + font.getBytes(6); // skipping range fields + var segIndex, segments = []; + for (segIndex = 0; segIndex < segCount; segIndex++) { + segments.push({ end: font.getUint16() }); + } + font.getUint16(); + for (segIndex = 0; segIndex < segCount; segIndex++) { + segments[segIndex].start = font.getUint16(); + } + + for (segIndex = 0; segIndex < segCount; segIndex++) { + segments[segIndex].delta = font.getUint16(); + } + + var offsetsCount = 0; + for (segIndex = 0; segIndex < segCount; segIndex++) { + segment = segments[segIndex]; + var rangeOffset = font.getUint16(); + if (!rangeOffset) { + segment.offsetIndex = -1; + continue; + } + + var offsetIndex = (rangeOffset >> 1) - (segCount - segIndex); + segment.offsetIndex = offsetIndex; + offsetsCount = Math.max(offsetsCount, offsetIndex + + segment.end - segment.start + 1); + } + + var offsets = []; + for (j = 0; j < offsetsCount; j++) { + offsets.push(font.getUint16()); + } + + for (segIndex = 0; segIndex < segCount; segIndex++) { + segment = segments[segIndex]; + start = segment.start; + var end = segment.end; + var delta = segment.delta; + offsetIndex = segment.offsetIndex; + + for (j = start; j <= end; j++) { + if (j === 0xFFFF) { + continue; + } + + glyphId = (offsetIndex < 0 ? + j : offsets[offsetIndex + j - start]); + glyphId = (glyphId + delta) & 0xFFFF; + if (glyphId === 0) { + continue; + } + mappings.push({ + charCode: j, + glyphId: glyphId + }); + } + } + } else if (format === 6) { + // Format 6 is a 2-bytes dense mapping, which means the font data + // lives glue together even if they are pretty far in the unicode + // table. (This looks weird, so I can have missed something), this + // works on Linux but seems to fails on Mac so let's rewrite the + // cmap table to a 3-1-4 style + var firstCode = font.getUint16(); + var entryCount = font.getUint16(); + + for (j = 0; j < entryCount; j++) { + glyphId = font.getUint16(); + var charCode = firstCode + j; + + mappings.push({ + charCode: charCode, + glyphId: glyphId + }); + } + } else { + error('cmap table has unsupported format: ' + format); + } + + // removing duplicate entries + mappings.sort(function (a, b) { + return a.charCode - b.charCode; + }); + for (i = 1; i < mappings.length; i++) { + if (mappings[i - 1].charCode === mappings[i].charCode) { + mappings.splice(i, 1); + i--; + } + } + + return { + platformId: potentialTable.platformId, + encodingId: potentialTable.encodingId, + mappings: mappings, + hasShortCmap: hasShortCmap + }; + } + + function sanitizeMetrics(font, header, metrics, numGlyphs) { + if (!header) { + if (metrics) { + metrics.data = null; + } + return; + } + + font.pos = (font.start ? font.start : 0) + header.offset; + font.pos += header.length - 2; + var numOfMetrics = font.getUint16(); + + if (numOfMetrics > numGlyphs) { + info('The numOfMetrics (' + numOfMetrics + ') should not be ' + + 'greater than the numGlyphs (' + numGlyphs + ')'); + // Reduce numOfMetrics if it is greater than numGlyphs + numOfMetrics = numGlyphs; + header.data[34] = (numOfMetrics & 0xff00) >> 8; + header.data[35] = numOfMetrics & 0x00ff; + } + + var numOfSidebearings = numGlyphs - numOfMetrics; + var numMissing = numOfSidebearings - + ((metrics.length - numOfMetrics * 4) >> 1); + + if (numMissing > 0) { + // For each missing glyph, we set both the width and lsb to 0 (zero). + // Since we need to add two properties for each glyph, this explains + // the use of |numMissing * 2| when initializing the typed array. + var entries = new Uint8Array(metrics.length + numMissing * 2); + entries.set(metrics.data); + metrics.data = entries; + } + } + + function sanitizeGlyph(source, sourceStart, sourceEnd, dest, destStart, + hintsValid) { + if (sourceEnd - sourceStart <= 12) { + // glyph with data less than 12 is invalid one + return 0; + } + var glyf = source.subarray(sourceStart, sourceEnd); + var contoursCount = (glyf[0] << 8) | glyf[1]; + if (contoursCount & 0x8000) { + // complex glyph, writing as is + dest.set(glyf, destStart); + return glyf.length; + } + + var i, j = 10, flagsCount = 0; + for (i = 0; i < contoursCount; i++) { + var endPoint = (glyf[j] << 8) | glyf[j + 1]; + flagsCount = endPoint + 1; + j += 2; + } + // skipping instructions + var instructionsStart = j; + var instructionsLength = (glyf[j] << 8) | glyf[j + 1]; + j += 2 + instructionsLength; + var instructionsEnd = j; + // validating flags + var coordinatesLength = 0; + for (i = 0; i < flagsCount; i++) { + var flag = glyf[j++]; + if (flag & 0xC0) { + // reserved flags must be zero, cleaning up + glyf[j - 1] = flag & 0x3F; + } + var xyLength = ((flag & 2) ? 1 : (flag & 16) ? 0 : 2) + + ((flag & 4) ? 1 : (flag & 32) ? 0 : 2); + coordinatesLength += xyLength; + if (flag & 8) { + var repeat = glyf[j++]; + i += repeat; + coordinatesLength += repeat * xyLength; + } + } + // glyph without coordinates will be rejected + if (coordinatesLength === 0) { + return 0; + } + var glyphDataLength = j + coordinatesLength; + if (glyphDataLength > glyf.length) { + // not enough data for coordinates + return 0; + } + if (!hintsValid && instructionsLength > 0) { + dest.set(glyf.subarray(0, instructionsStart), destStart); + dest.set([0, 0], destStart + instructionsStart); + dest.set(glyf.subarray(instructionsEnd, glyphDataLength), + destStart + instructionsStart + 2); + glyphDataLength -= instructionsLength; + if (glyf.length - glyphDataLength > 3) { + glyphDataLength = (glyphDataLength + 3) & ~3; + } + return glyphDataLength; + } + if (glyf.length - glyphDataLength > 3) { + // truncating and aligning to 4 bytes the long glyph data + glyphDataLength = (glyphDataLength + 3) & ~3; + dest.set(glyf.subarray(0, glyphDataLength), destStart); + return glyphDataLength; + } + // glyph data is fine + dest.set(glyf, destStart); + return glyf.length; + } + + function sanitizeHead(head, numGlyphs, locaLength) { + var data = head.data; + + // Validate version: + // Should always be 0x00010000 + var version = int32(data[0], data[1], data[2], data[3]); + if (version >> 16 !== 1) { + info('Attempting to fix invalid version in head table: ' + version); + data[0] = 0; + data[1] = 1; + data[2] = 0; + data[3] = 0; + } + + var indexToLocFormat = int16(data[50], data[51]); + if (indexToLocFormat < 0 || indexToLocFormat > 1) { + info('Attempting to fix invalid indexToLocFormat in head table: ' + + indexToLocFormat); + + // The value of indexToLocFormat should be 0 if the loca table + // consists of short offsets, and should be 1 if the loca table + // consists of long offsets. + // + // The number of entries in the loca table should be numGlyphs + 1. + // + // Using this information, we can work backwards to deduce if the + // size of each offset in the loca table, and thus figure out the + // appropriate value for indexToLocFormat. + + var numGlyphsPlusOne = numGlyphs + 1; + if (locaLength === numGlyphsPlusOne << 1) { + // 0x0000 indicates the loca table consists of short offsets + data[50] = 0; + data[51] = 0; + } else if (locaLength === numGlyphsPlusOne << 2) { + // 0x0001 indicates the loca table consists of long offsets + data[50] = 0; + data[51] = 1; + } else { + warn('Could not fix indexToLocFormat: ' + indexToLocFormat); + } + } + } + + function sanitizeGlyphLocations(loca, glyf, numGlyphs, + isGlyphLocationsLong, hintsValid, + dupFirstEntry) { + var itemSize, itemDecode, itemEncode; + if (isGlyphLocationsLong) { + itemSize = 4; + itemDecode = function fontItemDecodeLong(data, offset) { + return (data[offset] << 24) | (data[offset + 1] << 16) | + (data[offset + 2] << 8) | data[offset + 3]; + }; + itemEncode = function fontItemEncodeLong(data, offset, value) { + data[offset] = (value >>> 24) & 0xFF; + data[offset + 1] = (value >> 16) & 0xFF; + data[offset + 2] = (value >> 8) & 0xFF; + data[offset + 3] = value & 0xFF; + }; + } else { + itemSize = 2; + itemDecode = function fontItemDecode(data, offset) { + return (data[offset] << 9) | (data[offset + 1] << 1); + }; + itemEncode = function fontItemEncode(data, offset, value) { + data[offset] = (value >> 9) & 0xFF; + data[offset + 1] = (value >> 1) & 0xFF; + }; + } + var locaData = loca.data; + var locaDataSize = itemSize * (1 + numGlyphs); + // is loca.data too short or long? + if (locaData.length !== locaDataSize) { + locaData = new Uint8Array(locaDataSize); + locaData.set(loca.data.subarray(0, locaDataSize)); + loca.data = locaData; + } + // removing the invalid glyphs + var oldGlyfData = glyf.data; + var oldGlyfDataLength = oldGlyfData.length; + var newGlyfData = new Uint8Array(oldGlyfDataLength); + var startOffset = itemDecode(locaData, 0); + var writeOffset = 0; + var missingGlyphData = {}; + itemEncode(locaData, 0, writeOffset); + var i, j; + for (i = 0, j = itemSize; i < numGlyphs; i++, j += itemSize) { + var endOffset = itemDecode(locaData, j); + if (endOffset > oldGlyfDataLength && + ((oldGlyfDataLength + 3) & ~3) === endOffset) { + // Aspose breaks fonts by aligning the glyphs to the qword, but not + // the glyf table size, which makes last glyph out of range. + endOffset = oldGlyfDataLength; + } + if (endOffset > oldGlyfDataLength) { + // glyph end offset points outside glyf data, rejecting the glyph + itemEncode(locaData, j, writeOffset); + startOffset = endOffset; + continue; + } + + if (startOffset === endOffset) { + missingGlyphData[i] = true; + } + + var newLength = sanitizeGlyph(oldGlyfData, startOffset, endOffset, + newGlyfData, writeOffset, hintsValid); + writeOffset += newLength; + itemEncode(locaData, j, writeOffset); + startOffset = endOffset; + } + + if (writeOffset === 0) { + // glyf table cannot be empty -- redoing the glyf and loca tables + // to have single glyph with one point + var simpleGlyph = new Uint8Array( + [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 0]); + for (i = 0, j = itemSize; i < numGlyphs; i++, j += itemSize) { + itemEncode(locaData, j, simpleGlyph.length); + } + glyf.data = simpleGlyph; + return missingGlyphData; + } + + if (dupFirstEntry) { + var firstEntryLength = itemDecode(locaData, itemSize); + if (newGlyfData.length > firstEntryLength + writeOffset) { + glyf.data = newGlyfData.subarray(0, firstEntryLength + writeOffset); + } else { + glyf.data = new Uint8Array(firstEntryLength + writeOffset); + glyf.data.set(newGlyfData.subarray(0, writeOffset)); + } + glyf.data.set(newGlyfData.subarray(0, firstEntryLength), writeOffset); + itemEncode(loca.data, locaData.length - itemSize, + writeOffset + firstEntryLength); + } else { + glyf.data = newGlyfData.subarray(0, writeOffset); + } + return missingGlyphData; + } + + function readPostScriptTable(post, properties, maxpNumGlyphs) { + var start = (font.start ? font.start : 0) + post.offset; + font.pos = start; + + var length = post.length, end = start + length; + var version = font.getInt32(); + // skip rest to the tables + font.getBytes(28); + + var glyphNames; + var valid = true; + var i; + + switch (version) { + case 0x00010000: + glyphNames = MacStandardGlyphOrdering; + break; + case 0x00020000: + var numGlyphs = font.getUint16(); + if (numGlyphs !== maxpNumGlyphs) { + valid = false; + break; + } + var glyphNameIndexes = []; + for (i = 0; i < numGlyphs; ++i) { + var index = font.getUint16(); + if (index >= 32768) { + valid = false; + break; + } + glyphNameIndexes.push(index); + } + if (!valid) { + break; + } + var customNames = []; + var strBuf = []; + while (font.pos < end) { + var stringLength = font.getByte(); + strBuf.length = stringLength; + for (i = 0; i < stringLength; ++i) { + strBuf[i] = String.fromCharCode(font.getByte()); + } + customNames.push(strBuf.join('')); + } + glyphNames = []; + for (i = 0; i < numGlyphs; ++i) { + var j = glyphNameIndexes[i]; + if (j < 258) { + glyphNames.push(MacStandardGlyphOrdering[j]); + continue; + } + glyphNames.push(customNames[j - 258]); + } + break; + case 0x00030000: + break; + default: + warn('Unknown/unsupported post table version ' + version); + valid = false; + break; + } + properties.glyphNames = glyphNames; + return valid; + } + + function readNameTable(nameTable) { + var start = (font.start ? font.start : 0) + nameTable.offset; + font.pos = start; + + var names = [[], []]; + var length = nameTable.length, end = start + length; + var format = font.getUint16(); + var FORMAT_0_HEADER_LENGTH = 6; + if (format !== 0 || length < FORMAT_0_HEADER_LENGTH) { + // unsupported name table format or table "too" small + return names; + } + var numRecords = font.getUint16(); + var stringsStart = font.getUint16(); + var records = []; + var NAME_RECORD_LENGTH = 12; + var i, ii; + + for (i = 0; i < numRecords && + font.pos + NAME_RECORD_LENGTH <= end; i++) { + var r = { + platform: font.getUint16(), + encoding: font.getUint16(), + language: font.getUint16(), + name: font.getUint16(), + length: font.getUint16(), + offset: font.getUint16() + }; + // using only Macintosh and Windows platform/encoding names + if ((r.platform === 1 && r.encoding === 0 && r.language === 0) || + (r.platform === 3 && r.encoding === 1 && r.language === 0x409)) { + records.push(r); + } + } + for (i = 0, ii = records.length; i < ii; i++) { + var record = records[i]; + var pos = start + stringsStart + record.offset; + if (pos + record.length > end) { + continue; // outside of name table, ignoring + } + font.pos = pos; + var nameIndex = record.name; + if (record.encoding) { + // unicode + var str = ''; + for (var j = 0, jj = record.length; j < jj; j += 2) { + str += String.fromCharCode(font.getUint16()); + } + names[1][nameIndex] = str; + } else { + names[0][nameIndex] = bytesToString(font.getBytes(record.length)); + } + } + return names; + } + + var TTOpsStackDeltas = [ + 0, 0, 0, 0, 0, 0, 0, 0, -2, -2, -2, -2, 0, 0, -2, -5, + -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, -1, 0, -1, -1, -1, -1, + 1, -1, -999, 0, 1, 0, -1, -2, 0, -1, -2, -1, -1, 0, -1, -1, + 0, 0, -999, -999, -1, -1, -1, -1, -2, -999, -2, -2, -999, 0, -2, -2, + 0, 0, -2, 0, -2, 0, 0, 0, -2, -1, -1, 1, 1, 0, 0, -1, + -1, -1, -1, -1, -1, -1, 0, 0, -1, 0, -1, -1, 0, -999, -1, -1, + -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -2, -999, -999, -999, -999, -999, -1, -1, -2, -2, 0, 0, 0, 0, -1, -1, + -999, -2, -2, 0, 0, -1, -2, -2, 0, 0, 0, -1, -1, -1, -2]; + // 0xC0-DF == -1 and 0xE0-FF == -2 + + function sanitizeTTProgram(table, ttContext) { + var data = table.data; + var i = 0, j, n, b, funcId, pc, lastEndf = 0, lastDeff = 0; + var stack = []; + var callstack = []; + var functionsCalled = []; + var tooComplexToFollowFunctions = + ttContext.tooComplexToFollowFunctions; + var inFDEF = false, ifLevel = 0, inELSE = 0; + for (var ii = data.length; i < ii;) { + var op = data[i++]; + // The TrueType instruction set docs can be found at + // https://developer.apple.com/fonts/TTRefMan/RM05/Chap5.html + if (op === 0x40) { // NPUSHB - pushes n bytes + n = data[i++]; + if (inFDEF || inELSE) { + i += n; + } else { + for (j = 0; j < n; j++) { + stack.push(data[i++]); + } + } + } else if (op === 0x41) { // NPUSHW - pushes n words + n = data[i++]; + if (inFDEF || inELSE) { + i += n * 2; + } else { + for (j = 0; j < n; j++) { + b = data[i++]; + stack.push((b << 8) | data[i++]); + } + } + } else if ((op & 0xF8) === 0xB0) { // PUSHB - pushes bytes + n = op - 0xB0 + 1; + if (inFDEF || inELSE) { + i += n; + } else { + for (j = 0; j < n; j++) { + stack.push(data[i++]); + } + } + } else if ((op & 0xF8) === 0xB8) { // PUSHW - pushes words + n = op - 0xB8 + 1; + if (inFDEF || inELSE) { + i += n * 2; + } else { + for (j = 0; j < n; j++) { + b = data[i++]; + stack.push((b << 8) | data[i++]); + } + } + } else if (op === 0x2B && !tooComplexToFollowFunctions) { // CALL + if (!inFDEF && !inELSE) { + // collecting inforamtion about which functions are used + funcId = stack[stack.length - 1]; + ttContext.functionsUsed[funcId] = true; + if (funcId in ttContext.functionsStackDeltas) { + stack.length += ttContext.functionsStackDeltas[funcId]; + } else if (funcId in ttContext.functionsDefined && + functionsCalled.indexOf(funcId) < 0) { + callstack.push({data: data, i: i, stackTop: stack.length - 1}); + functionsCalled.push(funcId); + pc = ttContext.functionsDefined[funcId]; + if (!pc) { + warn('TT: CALL non-existent function'); + ttContext.hintsValid = false; + return; + } + data = pc.data; + i = pc.i; + } + } + } else if (op === 0x2C && !tooComplexToFollowFunctions) { // FDEF + if (inFDEF || inELSE) { + warn('TT: nested FDEFs not allowed'); + tooComplexToFollowFunctions = true; + } + inFDEF = true; + // collecting inforamtion about which functions are defined + lastDeff = i; + funcId = stack.pop(); + ttContext.functionsDefined[funcId] = {data: data, i: i}; + } else if (op === 0x2D) { // ENDF - end of function + if (inFDEF) { + inFDEF = false; + lastEndf = i; + } else { + pc = callstack.pop(); + if (!pc) { + warn('TT: ENDF bad stack'); + ttContext.hintsValid = false; + return; + } + funcId = functionsCalled.pop(); + data = pc.data; + i = pc.i; + ttContext.functionsStackDeltas[funcId] = + stack.length - pc.stackTop; + } + } else if (op === 0x89) { // IDEF - instruction definition + if (inFDEF || inELSE) { + warn('TT: nested IDEFs not allowed'); + tooComplexToFollowFunctions = true; + } + inFDEF = true; + // recording it as a function to track ENDF + lastDeff = i; + } else if (op === 0x58) { // IF + ++ifLevel; + } else if (op === 0x1B) { // ELSE + inELSE = ifLevel; + } else if (op === 0x59) { // EIF + if (inELSE === ifLevel) { + inELSE = 0; + } + --ifLevel; + } else if (op === 0x1C) { // JMPR + if (!inFDEF && !inELSE) { + var offset = stack[stack.length - 1]; + // only jumping forward to prevent infinite loop + if (offset > 0) { + i += offset - 1; + } + } + } + // Adjusting stack not extactly, but just enough to get function id + if (!inFDEF && !inELSE) { + var stackDelta = op <= 0x8E ? TTOpsStackDeltas[op] : + op >= 0xC0 && op <= 0xDF ? -1 : op >= 0xE0 ? -2 : 0; + if (op >= 0x71 && op <= 0x75) { + n = stack.pop(); + if (n === n) { + stackDelta = -n * 2; + } + } + while (stackDelta < 0 && stack.length > 0) { + stack.pop(); + stackDelta++; + } + while (stackDelta > 0) { + stack.push(NaN); // pushing any number into stack + stackDelta--; + } + } + } + ttContext.tooComplexToFollowFunctions = tooComplexToFollowFunctions; + var content = [data]; + if (i > data.length) { + content.push(new Uint8Array(i - data.length)); + } + if (lastDeff > lastEndf) { + warn('TT: complementing a missing function tail'); + // new function definition started, but not finished + // complete function by [CLEAR, ENDF] + content.push(new Uint8Array([0x22, 0x2D])); + } + foldTTTable(table, content); + } + + function checkInvalidFunctions(ttContext, maxFunctionDefs) { + if (ttContext.tooComplexToFollowFunctions) { + return; + } + if (ttContext.functionsDefined.length > maxFunctionDefs) { + warn('TT: more functions defined than expected'); + ttContext.hintsValid = false; + return; + } + for (var j = 0, jj = ttContext.functionsUsed.length; j < jj; j++) { + if (j > maxFunctionDefs) { + warn('TT: invalid function id: ' + j); + ttContext.hintsValid = false; + return; + } + if (ttContext.functionsUsed[j] && !ttContext.functionsDefined[j]) { + warn('TT: undefined function: ' + j); + ttContext.hintsValid = false; + return; + } + } + } + + function foldTTTable(table, content) { + if (content.length > 1) { + // concatenating the content items + var newLength = 0; + var j, jj; + for (j = 0, jj = content.length; j < jj; j++) { + newLength += content[j].length; + } + newLength = (newLength + 3) & ~3; + var result = new Uint8Array(newLength); + var pos = 0; + for (j = 0, jj = content.length; j < jj; j++) { + result.set(content[j], pos); + pos += content[j].length; + } + table.data = result; + table.length = newLength; + } + } + + function sanitizeTTPrograms(fpgm, prep, cvt) { + var ttContext = { + functionsDefined: [], + functionsUsed: [], + functionsStackDeltas: [], + tooComplexToFollowFunctions: false, + hintsValid: true + }; + if (fpgm) { + sanitizeTTProgram(fpgm, ttContext); + } + if (prep) { + sanitizeTTProgram(prep, ttContext); + } + if (fpgm) { + checkInvalidFunctions(ttContext, maxFunctionDefs); + } + if (cvt && (cvt.length & 1)) { + var cvtData = new Uint8Array(cvt.length + 1); + cvtData.set(cvt.data); + cvt.data = cvtData; + } + return ttContext.hintsValid; + } + + // The following steps modify the original font data, making copy + font = new Stream(new Uint8Array(font.getBytes())); + + var VALID_TABLES = ['OS/2', 'cmap', 'head', 'hhea', 'hmtx', 'maxp', + 'name', 'post', 'loca', 'glyf', 'fpgm', 'prep', 'cvt ', 'CFF ']; + + var header = readOpenTypeHeader(font); + var numTables = header.numTables; + var cff, cffFile; + + var tables = { 'OS/2': null, cmap: null, head: null, hhea: null, + hmtx: null, maxp: null, name: null, post: null }; + var table; + for (var i = 0; i < numTables; i++) { + table = readTableEntry(font); + if (VALID_TABLES.indexOf(table.tag) < 0) { + continue; // skipping table if it's not a required or optional table + } + if (table.length === 0) { + continue; // skipping empty tables + } + tables[table.tag] = table; + } + + var isTrueType = !tables['CFF ']; + if (!isTrueType) { + // OpenType font + if (header.version === 'OTTO' || + !tables.head || !tables.hhea || !tables.maxp || !tables.post) { + // no major tables: throwing everything at CFFFont + cffFile = new Stream(tables['CFF '].data); + cff = new CFFFont(cffFile, properties); + + return this.convert(name, cff, properties); + } + + delete tables.glyf; + delete tables.loca; + delete tables.fpgm; + delete tables.prep; + delete tables['cvt ']; + this.isOpenType = true; + } else { + if (!tables.glyf || !tables.loca) { + error('Required "glyf" or "loca" tables are not found'); + } + this.isOpenType = false; + } + + if (!tables.maxp) { + error('Required "maxp" table is not found'); + } + + font.pos = (font.start || 0) + tables.maxp.offset; + var version = font.getInt32(); + var numGlyphs = font.getUint16(); + var maxFunctionDefs = 0; + if (version >= 0x00010000 && tables.maxp.length >= 22) { + // maxZones can be invalid + font.pos += 8; + var maxZones = font.getUint16(); + if (maxZones > 2) { // reset to 2 if font has invalid maxZones + tables.maxp.data[14] = 0; + tables.maxp.data[15] = 2; + } + font.pos += 4; + maxFunctionDefs = font.getUint16(); + } + + var dupFirstEntry = false; + if (properties.type === 'CIDFontType2' && properties.toUnicode && + properties.toUnicode.get(0) > '\u0000') { + // oracle's defect (see 3427), duplicating first entry + dupFirstEntry = true; + numGlyphs++; + tables.maxp.data[4] = numGlyphs >> 8; + tables.maxp.data[5] = numGlyphs & 255; + } + + var hintsValid = sanitizeTTPrograms(tables.fpgm, tables.prep, + tables['cvt '], maxFunctionDefs); + if (!hintsValid) { + delete tables.fpgm; + delete tables.prep; + delete tables['cvt ']; + } + + // Ensure the hmtx table contains the advance width and + // sidebearings information for numGlyphs in the maxp table + sanitizeMetrics(font, tables.hhea, tables.hmtx, numGlyphs); + + if (!tables.head) { + error('Required "head" table is not found'); + } + + sanitizeHead(tables.head, numGlyphs, isTrueType ? tables.loca.length : 0); + + var missingGlyphs = {}; + if (isTrueType) { + var isGlyphLocationsLong = int16(tables.head.data[50], + tables.head.data[51]); + missingGlyphs = sanitizeGlyphLocations(tables.loca, tables.glyf, + numGlyphs, isGlyphLocationsLong, + hintsValid, dupFirstEntry); + } + + if (!tables.hhea) { + error('Required "hhea" table is not found'); + } + + // Sanitizer reduces the glyph advanceWidth to the maxAdvanceWidth + // Sometimes it's 0. That needs to be fixed + if (tables.hhea.data[10] === 0 && tables.hhea.data[11] === 0) { + tables.hhea.data[10] = 0xFF; + tables.hhea.data[11] = 0xFF; + } + + // The 'post' table has glyphs names. + if (tables.post) { + var valid = readPostScriptTable(tables.post, properties, numGlyphs); + if (!valid) { + tables.post = null; + } + } + + var charCodeToGlyphId = [], charCode, toUnicode = properties.toUnicode; + + function hasGlyph(glyphId, charCode) { + if (!missingGlyphs[glyphId]) { + return true; + } + if (charCode >= 0 && toUnicode.has(charCode)) { + return true; + } + return false; + } + + if (properties.type === 'CIDFontType2') { + var cidToGidMap = properties.cidToGidMap || []; + var isCidToGidMapEmpty = cidToGidMap.length === 0; + + properties.cMap.forEach(function(charCode, cid) { + assert(cid <= 0xffff, 'Max size of CID is 65,535'); + var glyphId = -1; + if (isCidToGidMapEmpty) { + glyphId = charCode; + } else if (cidToGidMap[cid] !== undefined) { + glyphId = cidToGidMap[cid]; + } + + if (glyphId >= 0 && glyphId < numGlyphs && + hasGlyph(glyphId, charCode)) { + charCodeToGlyphId[charCode] = glyphId; + } + }); + if (dupFirstEntry) { + charCodeToGlyphId[0] = numGlyphs - 1; + } + } else { + // Most of the following logic in this code branch is based on the + // 9.6.6.4 of the PDF spec. + var cmapTable = readCmapTable(tables.cmap, font, this.isSymbolicFont); + var cmapPlatformId = cmapTable.platformId; + var cmapEncodingId = cmapTable.encodingId; + var cmapMappings = cmapTable.mappings; + var cmapMappingsLength = cmapMappings.length; + var hasEncoding = properties.differences.length || + !!properties.baseEncodingName; + + // The spec seems to imply that if the font is symbolic the encoding + // should be ignored, this doesn't appear to work for 'preistabelle.pdf' + // where the the font is symbolic and it has an encoding. + if (hasEncoding && + (cmapPlatformId === 3 && cmapEncodingId === 1 || + cmapPlatformId === 1 && cmapEncodingId === 0) || + (cmapPlatformId === -1 && cmapEncodingId === -1 && // Temporary hack + !!Encodings[properties.baseEncodingName])) { // Temporary hack + // When no preferred cmap table was found and |baseEncodingName| is + // one of the predefined encodings, we seem to obtain a better + // |charCodeToGlyphId| map from the code below (fixes bug 1057544). + // TODO: Note that this is a hack which should be removed as soon as + // we have proper support for more exotic cmap tables. + + var baseEncoding = []; + if (properties.baseEncodingName === 'MacRomanEncoding' || + properties.baseEncodingName === 'WinAnsiEncoding') { + baseEncoding = Encodings[properties.baseEncodingName]; + } + for (charCode = 0; charCode < 256; charCode++) { + var glyphName; + if (this.differences && charCode in this.differences) { + glyphName = this.differences[charCode]; + } else if (charCode in baseEncoding && + baseEncoding[charCode] !== '') { + glyphName = baseEncoding[charCode]; + } else { + glyphName = Encodings.StandardEncoding[charCode]; + } + if (!glyphName) { + continue; + } + var unicodeOrCharCode; + if (cmapPlatformId === 3 && cmapEncodingId === 1) { + unicodeOrCharCode = GlyphsUnicode[glyphName]; + } else if (cmapPlatformId === 1 && cmapEncodingId === 0) { + // TODO: the encoding needs to be updated with mac os table. + unicodeOrCharCode = Encodings.MacRomanEncoding.indexOf(glyphName); + } + + var found = false; + for (i = 0; i < cmapMappingsLength; ++i) { + if (cmapMappings[i].charCode === unicodeOrCharCode && + hasGlyph(cmapMappings[i].glyphId, unicodeOrCharCode)) { + charCodeToGlyphId[charCode] = cmapMappings[i].glyphId; + found = true; + break; + } + } + if (!found && properties.glyphNames) { + // Try to map using the post table. There are currently no known + // pdfs that this fixes. + var glyphId = properties.glyphNames.indexOf(glyphName); + if (glyphId > 0 && hasGlyph(glyphId, -1)) { + charCodeToGlyphId[charCode] = glyphId; + } + } + } + } else if (cmapPlatformId === 0 && cmapEncodingId === 0) { + // Default Unicode semantics, use the charcodes as is. + for (i = 0; i < cmapMappingsLength; ++i) { + charCodeToGlyphId[cmapMappings[i].charCode] = + cmapMappings[i].glyphId; + } + } else { + // For (3, 0) cmap tables: + // The charcode key being stored in charCodeToGlyphId is the lower + // byte of the two-byte charcodes of the cmap table since according to + // the spec: 'each byte from the string shall be prepended with the + // high byte of the range [of charcodes in the cmap table], to form + // a two-byte character, which shall be used to select the + // associated glyph description from the subtable'. + // + // For (1, 0) cmap tables: + // 'single bytes from the string shall be used to look up the + // associated glyph descriptions from the subtable'. This means + // charcodes in the cmap will be single bytes, so no-op since + // glyph.charCode & 0xFF === glyph.charCode + for (i = 0; i < cmapMappingsLength; ++i) { + charCode = cmapMappings[i].charCode & 0xFF; + charCodeToGlyphId[charCode] = cmapMappings[i].glyphId; + } + } + } + + if (charCodeToGlyphId.length === 0) { + // defines at least one glyph + charCodeToGlyphId[0] = 0; + } + + // Converting glyphs and ids into font's cmap table + var newMapping = adjustMapping(charCodeToGlyphId, properties); + this.toFontChar = newMapping.toFontChar; + tables.cmap = { + tag: 'cmap', + data: createCmapTable(newMapping.charCodeToGlyphId) + }; + + if (!tables['OS/2'] || !validateOS2Table(tables['OS/2'])) { + // extract some more font properties from the OpenType head and + // hhea tables; yMin and descent value are always negative + var override = { + unitsPerEm: int16(tables.head.data[18], tables.head.data[19]), + yMax: int16(tables.head.data[42], tables.head.data[43]), + yMin: int16(tables.head.data[38], tables.head.data[39]) - 0x10000, + ascent: int16(tables.hhea.data[4], tables.hhea.data[5]), + descent: int16(tables.hhea.data[6], tables.hhea.data[7]) - 0x10000 + }; + + tables['OS/2'] = { + tag: 'OS/2', + data: createOS2Table(properties, newMapping.charCodeToGlyphId, + override) + }; + } + + // Rewrite the 'post' table if needed + if (!tables.post) { + tables.post = { + tag: 'post', + data: createPostTable(properties) + }; + } + + if (!isTrueType) { + try { + // Trying to repair CFF file + cffFile = new Stream(tables['CFF '].data); + var parser = new CFFParser(cffFile, properties); + cff = parser.parse(); + var compiler = new CFFCompiler(cff); + tables['CFF '].data = compiler.compile(); + } catch (e) { + warn('Failed to compile font ' + properties.loadedName); + } + } + + // Re-creating 'name' table + if (!tables.name) { + tables.name = { + tag: 'name', + data: createNameTable(this.name) + }; + } else { + // ... using existing 'name' table as prototype + var namePrototype = readNameTable(tables.name); + tables.name.data = createNameTable(name, namePrototype); + } + + var builder = new OpenTypeFileBuilder(header.version); + for (var tableTag in tables) { + builder.addTable(tableTag, tables[tableTag].data); + } + return builder.toArray(); + }, + + convert: function Font_convert(fontName, font, properties) { + // TODO: Check the charstring widths to determine this. + properties.fixedPitch = false; + + var mapping = font.getGlyphMapping(properties); + var newMapping = adjustMapping(mapping, properties); + this.toFontChar = newMapping.toFontChar; + var numGlyphs = font.numGlyphs; + + function getCharCodes(charCodeToGlyphId, glyphId) { + var charCodes = null; + for (var charCode in charCodeToGlyphId) { + if (glyphId === charCodeToGlyphId[charCode]) { + if (!charCodes) { + charCodes = []; + } + charCodes.push(charCode | 0); + } + } + return charCodes; + } + + function createCharCode(charCodeToGlyphId, glyphId) { + for (var charCode in charCodeToGlyphId) { + if (glyphId === charCodeToGlyphId[charCode]) { + return charCode | 0; + } + } + newMapping.charCodeToGlyphId[newMapping.nextAvailableFontCharCode] = + glyphId; + return newMapping.nextAvailableFontCharCode++; + } + + var seacs = font.seacs; + if (SEAC_ANALYSIS_ENABLED && seacs && seacs.length) { + var matrix = properties.fontMatrix || FONT_IDENTITY_MATRIX; + var charset = font.getCharset(); + var seacMap = Object.create(null); + for (var glyphId in seacs) { + glyphId |= 0; + var seac = seacs[glyphId]; + var baseGlyphName = Encodings.StandardEncoding[seac[2]]; + var accentGlyphName = Encodings.StandardEncoding[seac[3]]; + var baseGlyphId = charset.indexOf(baseGlyphName); + var accentGlyphId = charset.indexOf(accentGlyphName); + if (baseGlyphId < 0 || accentGlyphId < 0) { + continue; + } + var accentOffset = { + x: seac[0] * matrix[0] + seac[1] * matrix[2] + matrix[4], + y: seac[0] * matrix[1] + seac[1] * matrix[3] + matrix[5] + }; + + var charCodes = getCharCodes(mapping, glyphId); + if (!charCodes) { + // There's no point in mapping it if the char code was never mapped + // to begin with. + continue; + } + for (var i = 0, ii = charCodes.length; i < ii; i++) { + var charCode = charCodes[i]; + // Find a fontCharCode that maps to the base and accent glyphs. + // If one doesn't exists, create it. + var charCodeToGlyphId = newMapping.charCodeToGlyphId; + var baseFontCharCode = createCharCode(charCodeToGlyphId, + baseGlyphId); + var accentFontCharCode = createCharCode(charCodeToGlyphId, + accentGlyphId); + seacMap[charCode] = { + baseFontCharCode: baseFontCharCode, + accentFontCharCode: accentFontCharCode, + accentOffset: accentOffset + }; + } + } + properties.seacMap = seacMap; + } + + var unitsPerEm = 1 / (properties.fontMatrix || FONT_IDENTITY_MATRIX)[0]; + + var builder = new OpenTypeFileBuilder('\x4F\x54\x54\x4F'); + // PostScript Font Program + builder.addTable('CFF ', font.data); + // OS/2 and Windows Specific metrics + builder.addTable('OS/2', createOS2Table(properties, + newMapping.charCodeToGlyphId)); + // Character to glyphs mapping + builder.addTable('cmap', createCmapTable(newMapping.charCodeToGlyphId)); + // Font header + builder.addTable('head', + '\x00\x01\x00\x00' + // Version number + '\x00\x00\x10\x00' + // fontRevision + '\x00\x00\x00\x00' + // checksumAdjustement + '\x5F\x0F\x3C\xF5' + // magicNumber + '\x00\x00' + // Flags + safeString16(unitsPerEm) + // unitsPerEM + '\x00\x00\x00\x00\x9e\x0b\x7e\x27' + // creation date + '\x00\x00\x00\x00\x9e\x0b\x7e\x27' + // modifification date + '\x00\x00' + // xMin + safeString16(properties.descent) + // yMin + '\x0F\xFF' + // xMax + safeString16(properties.ascent) + // yMax + string16(properties.italicAngle ? 2 : 0) + // macStyle + '\x00\x11' + // lowestRecPPEM + '\x00\x00' + // fontDirectionHint + '\x00\x00' + // indexToLocFormat + '\x00\x00'); // glyphDataFormat + + // Horizontal header + builder.addTable('hhea', + '\x00\x01\x00\x00' + // Version number + safeString16(properties.ascent) + // Typographic Ascent + safeString16(properties.descent) + // Typographic Descent + '\x00\x00' + // Line Gap + '\xFF\xFF' + // advanceWidthMax + '\x00\x00' + // minLeftSidebearing + '\x00\x00' + // minRightSidebearing + '\x00\x00' + // xMaxExtent + safeString16(properties.capHeight) + // caretSlopeRise + safeString16(Math.tan(properties.italicAngle) * + properties.xHeight) + // caretSlopeRun + '\x00\x00' + // caretOffset + '\x00\x00' + // -reserved- + '\x00\x00' + // -reserved- + '\x00\x00' + // -reserved- + '\x00\x00' + // -reserved- + '\x00\x00' + // metricDataFormat + string16(numGlyphs)); // Number of HMetrics + + // Horizontal metrics + builder.addTable('hmtx', (function fontFieldsHmtx() { + var charstrings = font.charstrings; + var cffWidths = font.cff ? font.cff.widths : null; + var hmtx = '\x00\x00\x00\x00'; // Fake .notdef + for (var i = 1, ii = numGlyphs; i < ii; i++) { + var width = 0; + if (charstrings) { + var charstring = charstrings[i - 1]; + width = 'width' in charstring ? charstring.width : 0; + } else if (cffWidths) { + width = Math.ceil(cffWidths[i] || 0); + } + hmtx += string16(width) + string16(0); + } + return hmtx; + })()); + + // Maximum profile + builder.addTable('maxp', + '\x00\x00\x50\x00' + // Version number + string16(numGlyphs)); // Num of glyphs + + // Naming tables + builder.addTable('name', createNameTable(fontName)); + + // PostScript informations + builder.addTable('post', createPostTable(properties)); + + return builder.toArray(); + }, + + /** + * Builds a char code to unicode map based on section 9.10 of the spec. + * @param {Object} properties Font properties object. + * @return {Object} A ToUnicodeMap object. + */ + buildToUnicode: function Font_buildToUnicode(properties) { + // Section 9.10.2 Mapping Character Codes to Unicode Values + if (properties.toUnicode && properties.toUnicode.length !== 0) { + return properties.toUnicode; + } + // According to the spec if the font is a simple font we should only map + // to unicode if the base encoding is MacRoman, MacExpert, or WinAnsi or + // the differences array only contains adobe standard or symbol set names, + // in pratice it seems better to always try to create a toUnicode + // map based of the default encoding. + var toUnicode, charcode; + if (!properties.composite /* is simple font */) { + toUnicode = []; + var encoding = properties.defaultEncoding.slice(); + var baseEncodingName = properties.baseEncodingName; + // Merge in the differences array. + var differences = properties.differences; + for (charcode in differences) { + encoding[charcode] = differences[charcode]; + } + for (charcode in encoding) { + // a) Map the character code to a character name. + var glyphName = encoding[charcode]; + // b) Look up the character name in the Adobe Glyph List (see the + // Bibliography) to obtain the corresponding Unicode value. + if (glyphName === '') { + continue; + } else if (GlyphsUnicode[glyphName] === undefined) { + // (undocumented) c) Few heuristics to recognize unknown glyphs + // NOTE: Adobe Reader does not do this step, but OSX Preview does + var code = 0; + switch (glyphName[0]) { + case 'G': // Gxx glyph + if (glyphName.length === 3) { + code = parseInt(glyphName.substr(1), 16); + } + break; + case 'g': // g00xx glyph + if (glyphName.length === 5) { + code = parseInt(glyphName.substr(1), 16); + } + break; + case 'C': // Cddd glyph + case 'c': // cddd glyph + if (glyphName.length >= 3) { + code = +glyphName.substr(1); + } + break; + } + if (code) { + // If |baseEncodingName| is one the predefined encodings, + // and |code| equals |charcode|, using the glyph defined in the + // baseEncoding seems to yield a better |toUnicode| mapping + // (fixes issue 5070). + if (baseEncodingName && code === +charcode) { + var baseEncoding = Encodings[baseEncodingName]; + if (baseEncoding && (glyphName = baseEncoding[charcode])) { + toUnicode[charcode] = + String.fromCharCode(GlyphsUnicode[glyphName]); + continue; + } + } + toUnicode[charcode] = String.fromCharCode(code); + } + continue; + } + toUnicode[charcode] = String.fromCharCode(GlyphsUnicode[glyphName]); + } + return new ToUnicodeMap(toUnicode); + } + // If the font is a composite font that uses one of the predefined CMaps + // listed in Table 118 (except Identity–H and Identity–V) or whose + // descendant CIDFont uses the Adobe-GB1, Adobe-CNS1, Adobe-Japan1, or + // Adobe-Korea1 character collection: + if (properties.composite && ( + (properties.cMap.builtInCMap && + !(properties.cMap instanceof IdentityCMap)) || + (properties.cidSystemInfo.registry === 'Adobe' && + (properties.cidSystemInfo.ordering === 'GB1' || + properties.cidSystemInfo.ordering === 'CNS1' || + properties.cidSystemInfo.ordering === 'Japan1' || + properties.cidSystemInfo.ordering === 'Korea1')))) { + // Then: + // a) Map the character code to a character identifier (CID) according + // to the font’s CMap. + // b) Obtain the registry and ordering of the character collection used + // by the font’s CMap (for example, Adobe and Japan1) from its + // CIDSystemInfo dictionary. + var registry = properties.cidSystemInfo.registry; + var ordering = properties.cidSystemInfo.ordering; + // c) Construct a second CMap name by concatenating the registry and + // ordering obtained in step (b) in the format registry–ordering–UCS2 + // (for example, Adobe–Japan1–UCS2). + var ucs2CMapName = new Name(registry + '-' + ordering + '-UCS2'); + // d) Obtain the CMap with the name constructed in step (c) (available + // from the ASN Web site; see the Bibliography). + var ucs2CMap = CMapFactory.create(ucs2CMapName, + { url: PDFJS.cMapUrl, packed: PDFJS.cMapPacked }, null); + var cMap = properties.cMap; + toUnicode = []; + cMap.forEach(function(charcode, cid) { + assert(cid <= 0xffff, 'Max size of CID is 65,535'); + // e) Map the CID obtained in step (a) according to the CMap obtained + // in step (d), producing a Unicode value. + var ucs2 = ucs2CMap.lookup(cid); + if (ucs2) { + toUnicode[charcode] = + String.fromCharCode((ucs2.charCodeAt(0) << 8) + + ucs2.charCodeAt(1)); + } + }); + return new ToUnicodeMap(toUnicode); + } + + // The viewer's choice, just use an identity map. + return new IdentityToUnicodeMap(properties.firstChar, + properties.lastChar); + }, + + get spaceWidth() { + if ('_shadowWidth' in this) { + return this._shadowWidth; + } + + // trying to estimate space character width + var possibleSpaceReplacements = ['space', 'minus', 'one', 'i']; + var width; + for (var i = 0, ii = possibleSpaceReplacements.length; i < ii; i++) { + var glyphName = possibleSpaceReplacements[i]; + // if possible, getting width by glyph name + if (glyphName in this.widths) { + width = this.widths[glyphName]; + break; + } + var glyphUnicode = GlyphsUnicode[glyphName]; + // finding the charcode via unicodeToCID map + var charcode = 0; + if (this.composite) { + if (this.cMap.contains(glyphUnicode)) { + charcode = this.cMap.lookup(glyphUnicode); + } + } + // ... via toUnicode map + if (!charcode && 'toUnicode' in this) { + charcode = this.toUnicode.charCodeOf(glyphUnicode); + } + // setting it to unicode if negative or undefined + if (charcode <= 0) { + charcode = glyphUnicode; + } + // trying to get width via charcode + width = this.widths[charcode]; + if (width) { + break; // the non-zero width found + } + } + width = width || this.defaultWidth; + // Do not shadow the property here. See discussion: + // https://github.com/mozilla/pdf.js/pull/2127#discussion_r1662280 + this._shadowWidth = width; + return width; + }, + + charToGlyph: function Font_charToGlyph(charcode) { + var fontCharCode, width, operatorListId; + + var widthCode = charcode; + if (this.cMap && this.cMap.contains(charcode)) { + widthCode = this.cMap.lookup(charcode); + } + width = this.widths[widthCode]; + width = isNum(width) ? width : this.defaultWidth; + var vmetric = this.vmetrics && this.vmetrics[widthCode]; + + var unicode = this.toUnicode.get(charcode) || charcode; + if (typeof unicode === 'number') { + unicode = String.fromCharCode(unicode); + } + + // First try the toFontChar map, if it's not there then try falling + // back to the char code. + fontCharCode = this.toFontChar[charcode] || charcode; + if (this.missingFile) { + fontCharCode = mapSpecialUnicodeValues(fontCharCode); + } + + if (this.isType3Font) { + // Font char code in this case is actually a glyph name. + operatorListId = fontCharCode; + } + + var accent = null; + if (this.seacMap && this.seacMap[charcode]) { + var seac = this.seacMap[charcode]; + fontCharCode = seac.baseFontCharCode; + accent = { + fontChar: String.fromCharCode(seac.accentFontCharCode), + offset: seac.accentOffset + }; + } + + var fontChar = String.fromCharCode(fontCharCode); + + var glyph = this.glyphCache[charcode]; + if (!glyph || + !glyph.matchesForCache(fontChar, unicode, accent, width, vmetric, + operatorListId)) { + glyph = new Glyph(fontChar, unicode, accent, width, vmetric, + operatorListId); + this.glyphCache[charcode] = glyph; + } + return glyph; + }, + + charsToGlyphs: function Font_charsToGlyphs(chars) { + var charsCache = this.charsCache; + var glyphs, glyph, charcode; + + // if we translated this string before, just grab it from the cache + if (charsCache) { + glyphs = charsCache[chars]; + if (glyphs) { + return glyphs; + } + } + + // lazily create the translation cache + if (!charsCache) { + charsCache = this.charsCache = Object.create(null); + } + + glyphs = []; + var charsCacheKey = chars; + var i = 0, ii; + + if (this.cMap) { + // composite fonts have multi-byte strings convert the string from + // single-byte to multi-byte + var c = {}; + while (i < chars.length) { + this.cMap.readCharCode(chars, i, c); + charcode = c.charcode; + var length = c.length; + i += length; + glyph = this.charToGlyph(charcode); + glyphs.push(glyph); + // placing null after each word break charcode (ASCII SPACE) + // Ignore occurences of 0x20 in multiple-byte codes. + if (length === 1 && chars.charCodeAt(i - 1) === 0x20) { + glyphs.push(null); + } + } + } else { + for (i = 0, ii = chars.length; i < ii; ++i) { + charcode = chars.charCodeAt(i); + glyph = this.charToGlyph(charcode); + glyphs.push(glyph); + if (charcode === 0x20) { + glyphs.push(null); + } + } + } + + // Enter the translated string into the cache + return (charsCache[charsCacheKey] = glyphs); + } + }; + + return Font; +})(); + +var ErrorFont = (function ErrorFontClosure() { + function ErrorFont(error) { + this.error = error; + this.loadedName = 'g_font_error'; + this.loading = false; + } + + ErrorFont.prototype = { + charsToGlyphs: function ErrorFont_charsToGlyphs() { + return []; + }, + exportData: function ErrorFont_exportData() { + return {error: this.error}; + } + }; + + return ErrorFont; +})(); + +/** + * Shared logic for building a char code to glyph id mapping for Type1 and + * simple CFF fonts. See section 9.6.6.2 of the spec. + * @param {Object} properties Font properties object. + * @param {Object} builtInEncoding The encoding contained within the actual font + * data. + * @param {Array} Array of glyph names where the index is the glyph ID. + * @returns {Object} A char code to glyph ID map. + */ +function type1FontGlyphMapping(properties, builtInEncoding, glyphNames) { + var charCodeToGlyphId = Object.create(null); + var glyphId, charCode, baseEncoding; + + if (properties.baseEncodingName) { + // If a valid base encoding name was used, the mapping is initialized with + // that. + baseEncoding = Encodings[properties.baseEncodingName]; + for (charCode = 0; charCode < baseEncoding.length; charCode++) { + glyphId = glyphNames.indexOf(baseEncoding[charCode]); + if (glyphId >= 0) { + charCodeToGlyphId[charCode] = glyphId; + } else { + charCodeToGlyphId[charCode] = 0; // notdef + } + } + } else if (!!(properties.flags & FontFlags.Symbolic)) { + // For a symbolic font the encoding should be the fonts built-in + // encoding. + for (charCode in builtInEncoding) { + charCodeToGlyphId[charCode] = builtInEncoding[charCode]; + } + } else { + // For non-symbolic fonts that don't have a base encoding the standard + // encoding should be used. + baseEncoding = Encodings.StandardEncoding; + for (charCode = 0; charCode < baseEncoding.length; charCode++) { + glyphId = glyphNames.indexOf(baseEncoding[charCode]); + if (glyphId >= 0) { + charCodeToGlyphId[charCode] = glyphId; + } else { + charCodeToGlyphId[charCode] = 0; // notdef + } + } + } + + // Lastly, merge in the differences. + var differences = properties.differences; + if (differences) { + for (charCode in differences) { + var glyphName = differences[charCode]; + glyphId = glyphNames.indexOf(glyphName); + if (glyphId >= 0) { + charCodeToGlyphId[charCode] = glyphId; + } else { + charCodeToGlyphId[charCode] = 0; // notdef + } + } + } + return charCodeToGlyphId; +} + +/* + * CharStrings are encoded following the the CharString Encoding sequence + * describe in Chapter 6 of the "Adobe Type1 Font Format" specification. + * The value in a byte indicates a command, a number, or subsequent bytes + * that are to be interpreted in a special way. + * + * CharString Number Encoding: + * A CharString byte containing the values from 32 through 255 inclusive + * indicate an integer. These values are decoded in four ranges. + * + * 1. A CharString byte containing a value, v, between 32 and 246 inclusive, + * indicate the integer v - 139. Thus, the integer values from -107 through + * 107 inclusive may be encoded in single byte. + * + * 2. A CharString byte containing a value, v, between 247 and 250 inclusive, + * indicates an integer involving the next byte, w, according to the formula: + * [(v - 247) x 256] + w + 108 + * + * 3. A CharString byte containing a value, v, between 251 and 254 inclusive, + * indicates an integer involving the next byte, w, according to the formula: + * -[(v - 251) * 256] - w - 108 + * + * 4. A CharString containing the value 255 indicates that the next 4 bytes + * are a two complement signed integer. The first of these bytes contains the + * highest order bits, the second byte contains the next higher order bits + * and the fourth byte contain the lowest order bits. + * + * + * CharString Command Encoding: + * CharStrings commands are encoded in 1 or 2 bytes. + * + * Single byte commands are encoded in 1 byte that contains a value between + * 0 and 31 inclusive. + * If a command byte contains the value 12, then the value in the next byte + * indicates a command. This "escape" mechanism allows many extra commands + * to be encoded and this encoding technique helps to minimize the length of + * the charStrings. + */ +var Type1CharString = (function Type1CharStringClosure() { + var COMMAND_MAP = { + 'hstem': [1], + 'vstem': [3], + 'vmoveto': [4], + 'rlineto': [5], + 'hlineto': [6], + 'vlineto': [7], + 'rrcurveto': [8], + 'callsubr': [10], + 'flex': [12, 35], + 'drop' : [12, 18], + 'endchar': [14], + 'rmoveto': [21], + 'hmoveto': [22], + 'vhcurveto': [30], + 'hvcurveto': [31] + }; + + function Type1CharString() { + this.width = 0; + this.lsb = 0; + this.flexing = false; + this.output = []; + this.stack = []; + } + + Type1CharString.prototype = { + convert: function Type1CharString_convert(encoded, subrs) { + var count = encoded.length; + var error = false; + var wx, sbx, subrNumber; + for (var i = 0; i < count; i++) { + var value = encoded[i]; + if (value < 32) { + if (value === 12) { + value = (value << 8) + encoded[++i]; + } + switch (value) { + case 1: // hstem + if (!HINTING_ENABLED) { + this.stack = []; + break; + } + error = this.executeCommand(2, COMMAND_MAP.hstem); + break; + case 3: // vstem + if (!HINTING_ENABLED) { + this.stack = []; + break; + } + error = this.executeCommand(2, COMMAND_MAP.vstem); + break; + case 4: // vmoveto + if (this.flexing) { + if (this.stack.length < 1) { + error = true; + break; + } + // Add the dx for flex and but also swap the values so they are + // the right order. + var dy = this.stack.pop(); + this.stack.push(0, dy); + break; + } + error = this.executeCommand(1, COMMAND_MAP.vmoveto); + break; + case 5: // rlineto + error = this.executeCommand(2, COMMAND_MAP.rlineto); + break; + case 6: // hlineto + error = this.executeCommand(1, COMMAND_MAP.hlineto); + break; + case 7: // vlineto + error = this.executeCommand(1, COMMAND_MAP.vlineto); + break; + case 8: // rrcurveto + error = this.executeCommand(6, COMMAND_MAP.rrcurveto); + break; + case 9: // closepath + // closepath is a Type1 command that does not take argument and is + // useless in Type2 and it can simply be ignored. + this.stack = []; + break; + case 10: // callsubr + if (this.stack.length < 1) { + error = true; + break; + } + subrNumber = this.stack.pop(); + error = this.convert(subrs[subrNumber], subrs); + break; + case 11: // return + return error; + case 13: // hsbw + if (this.stack.length < 2) { + error = true; + break; + } + // To convert to type2 we have to move the width value to the + // first part of the charstring and then use hmoveto with lsb. + wx = this.stack.pop(); + sbx = this.stack.pop(); + this.lsb = sbx; + this.width = wx; + this.stack.push(wx, sbx); + error = this.executeCommand(2, COMMAND_MAP.hmoveto); + break; + case 14: // endchar + this.output.push(COMMAND_MAP.endchar[0]); + break; + case 21: // rmoveto + if (this.flexing) { + break; + } + error = this.executeCommand(2, COMMAND_MAP.rmoveto); + break; + case 22: // hmoveto + if (this.flexing) { + // Add the dy for flex. + this.stack.push(0); + break; + } + error = this.executeCommand(1, COMMAND_MAP.hmoveto); + break; + case 30: // vhcurveto + error = this.executeCommand(4, COMMAND_MAP.vhcurveto); + break; + case 31: // hvcurveto + error = this.executeCommand(4, COMMAND_MAP.hvcurveto); + break; + case (12 << 8) + 0: // dotsection + // dotsection is a Type1 command to specify some hinting feature + // for dots that do not take a parameter and it can safely be + // ignored for Type2. + this.stack = []; + break; + case (12 << 8) + 1: // vstem3 + if (!HINTING_ENABLED) { + this.stack = []; + break; + } + // [vh]stem3 are Type1 only and Type2 supports [vh]stem with + // multiple parameters, so instead of returning [vh]stem3 take a + // shortcut and return [vhstem] instead. + error = this.executeCommand(2, COMMAND_MAP.vstem); + break; + case (12 << 8) + 2: // hstem3 + if (!HINTING_ENABLED) { + this.stack = []; + break; + } + // See vstem3. + error = this.executeCommand(2, COMMAND_MAP.hstem); + break; + case (12 << 8) + 6: // seac + // seac is like type 2's special endchar but it doesn't use the + // first argument asb, so remove it. + if (SEAC_ANALYSIS_ENABLED) { + this.seac = this.stack.splice(-4, 4); + error = this.executeCommand(0, COMMAND_MAP.endchar); + } else { + error = this.executeCommand(4, COMMAND_MAP.endchar); + } + break; + case (12 << 8) + 7: // sbw + if (this.stack.length < 4) { + error = true; + break; + } + // To convert to type2 we have to move the width value to the + // first part of the charstring and then use rmoveto with + // (dx, dy). The height argument will not be used for vmtx and + // vhea tables reconstruction -- ignoring it. + var wy = this.stack.pop(); + wx = this.stack.pop(); + var sby = this.stack.pop(); + sbx = this.stack.pop(); + this.lsb = sbx; + this.width = wx; + this.stack.push(wx, sbx, sby); + error = this.executeCommand(3, COMMAND_MAP.rmoveto); + break; + case (12 << 8) + 12: // div + if (this.stack.length < 2) { + error = true; + break; + } + var num2 = this.stack.pop(); + var num1 = this.stack.pop(); + this.stack.push(num1 / num2); + break; + case (12 << 8) + 16: // callothersubr + if (this.stack.length < 2) { + error = true; + break; + } + subrNumber = this.stack.pop(); + var numArgs = this.stack.pop(); + if (subrNumber === 0 && numArgs === 3) { + var flexArgs = this.stack.splice(this.stack.length - 17, 17); + this.stack.push( + flexArgs[2] + flexArgs[0], // bcp1x + rpx + flexArgs[3] + flexArgs[1], // bcp1y + rpy + flexArgs[4], // bcp2x + flexArgs[5], // bcp2y + flexArgs[6], // p2x + flexArgs[7], // p2y + flexArgs[8], // bcp3x + flexArgs[9], // bcp3y + flexArgs[10], // bcp4x + flexArgs[11], // bcp4y + flexArgs[12], // p3x + flexArgs[13], // p3y + flexArgs[14] // flexDepth + // 15 = finalx unused by flex + // 16 = finaly unused by flex + ); + error = this.executeCommand(13, COMMAND_MAP.flex, true); + this.flexing = false; + this.stack.push(flexArgs[15], flexArgs[16]); + } else if (subrNumber === 1 && numArgs === 0) { + this.flexing = true; + } + break; + case (12 << 8) + 17: // pop + // Ignore this since it is only used with othersubr. + break; + case (12 << 8) + 33: // setcurrentpoint + // Ignore for now. + this.stack = []; + break; + default: + warn('Unknown type 1 charstring command of "' + value + '"'); + break; + } + if (error) { + break; + } + continue; + } else if (value <= 246) { + value = value - 139; + } else if (value <= 250) { + value = ((value - 247) * 256) + encoded[++i] + 108; + } else if (value <= 254) { + value = -((value - 251) * 256) - encoded[++i] - 108; + } else { + value = (encoded[++i] & 0xff) << 24 | (encoded[++i] & 0xff) << 16 | + (encoded[++i] & 0xff) << 8 | (encoded[++i] & 0xff) << 0; + } + this.stack.push(value); + } + return error; + }, + + executeCommand: function(howManyArgs, command, keepStack) { + var stackLength = this.stack.length; + if (howManyArgs > stackLength) { + return true; + } + var start = stackLength - howManyArgs; + for (var i = start; i < stackLength; i++) { + var value = this.stack[i]; + if (value === (value | 0)) { // int + this.output.push(28, (value >> 8) & 0xff, value & 0xff); + } else { // fixed point + value = (65536 * value) | 0; + this.output.push(255, + (value >> 24) & 0xFF, + (value >> 16) & 0xFF, + (value >> 8) & 0xFF, + value & 0xFF); + } + } + this.output.push.apply(this.output, command); + if (keepStack) { + this.stack.splice(start, howManyArgs); + } else { + this.stack.length = 0; + } + return false; + } + }; + + return Type1CharString; +})(); + +/* + * Type1Parser encapsulate the needed code for parsing a Type1 font + * program. Some of its logic depends on the Type2 charstrings + * structure. + * Note: this doesn't really parse the font since that would require evaluation + * of PostScript, but it is possible in most cases to extract what we need + * without a full parse. + */ +var Type1Parser = (function Type1ParserClosure() { + /* + * Decrypt a Sequence of Ciphertext Bytes to Produce the Original Sequence + * of Plaintext Bytes. The function took a key as a parameter which can be + * for decrypting the eexec block of for decoding charStrings. + */ + var EEXEC_ENCRYPT_KEY = 55665; + var CHAR_STRS_ENCRYPT_KEY = 4330; + + function isHexDigit(code) { + return code >= 48 && code <= 57 || // '0'-'9' + code >= 65 && code <= 70 || // 'A'-'F' + code >= 97 && code <= 102; // 'a'-'f' + } + + function decrypt(data, key, discardNumber) { + var r = key | 0, c1 = 52845, c2 = 22719; + var count = data.length; + var decrypted = new Uint8Array(count); + for (var i = 0; i < count; i++) { + var value = data[i]; + decrypted[i] = value ^ (r >> 8); + r = ((value + r) * c1 + c2) & ((1 << 16) - 1); + } + return Array.prototype.slice.call(decrypted, discardNumber); + } + + function decryptAscii(data, key, discardNumber) { + var r = key | 0, c1 = 52845, c2 = 22719; + var count = data.length, maybeLength = count >>> 1; + var decrypted = new Uint8Array(maybeLength); + var i, j; + for (i = 0, j = 0; i < count; i++) { + var digit1 = data[i]; + if (!isHexDigit(digit1)) { + continue; + } + i++; + var digit2; + while (i < count && !isHexDigit(digit2 = data[i])) { + i++; + } + if (i < count) { + var value = parseInt(String.fromCharCode(digit1, digit2), 16); + decrypted[j++] = value ^ (r >> 8); + r = ((value + r) * c1 + c2) & ((1 << 16) - 1); + } + } + return Array.prototype.slice.call(decrypted, discardNumber, j); + } + + function isSpecial(c) { + return c === 0x2F || // '/' + c === 0x5B || c === 0x5D || // '[', ']' + c === 0x7B || c === 0x7D || // '{', '}' + c === 0x28 || c === 0x29; // '(', ')' + } + + function Type1Parser(stream, encrypted) { + if (encrypted) { + var data = stream.getBytes(); + var isBinary = !(isHexDigit(data[0]) && isHexDigit(data[1]) && + isHexDigit(data[2]) && isHexDigit(data[3])); + stream = new Stream(isBinary ? decrypt(data, EEXEC_ENCRYPT_KEY, 4) : + decryptAscii(data, EEXEC_ENCRYPT_KEY, 4)); + } + this.stream = stream; + this.nextChar(); + } + + Type1Parser.prototype = { + readNumberArray: function Type1Parser_readNumberArray() { + this.getToken(); // read '[' or '{' (arrays can start with either) + var array = []; + while (true) { + var token = this.getToken(); + if (token === null || token === ']' || token === '}') { + break; + } + array.push(parseFloat(token || 0)); + } + return array; + }, + + readNumber: function Type1Parser_readNumber() { + var token = this.getToken(); + return parseFloat(token || 0); + }, + + readInt: function Type1Parser_readInt() { + // Use '| 0' to prevent setting a double into length such as the double + // does not flow into the loop variable. + var token = this.getToken(); + return parseInt(token || 0, 10) | 0; + }, + + readBoolean: function Type1Parser_readBoolean() { + var token = this.getToken(); + + // Use 1 and 0 since that's what type2 charstrings use. + return token === 'true' ? 1 : 0; + }, + + nextChar : function Type1_nextChar() { + return (this.currentChar = this.stream.getByte()); + }, + + getToken: function Type1Parser_getToken() { + // Eat whitespace and comments. + var comment = false; + var ch = this.currentChar; + while (true) { + if (ch === -1) { + return null; + } + + if (comment) { + if (ch === 0x0A || ch === 0x0D) { + comment = false; + } + } else if (ch === 0x25) { // '%' + comment = true; + } else if (!Lexer.isSpace(ch)) { + break; + } + ch = this.nextChar(); + } + if (isSpecial(ch)) { + this.nextChar(); + return String.fromCharCode(ch); + } + var token = ''; + do { + token += String.fromCharCode(ch); + ch = this.nextChar(); + } while (ch >= 0 && !Lexer.isSpace(ch) && !isSpecial(ch)); + return token; + }, + + /* + * Returns an object containing a Subrs array and a CharStrings + * array extracted from and eexec encrypted block of data + */ + extractFontProgram: function Type1Parser_extractFontProgram() { + var stream = this.stream; + + var subrs = [], charstrings = []; + var program = { + subrs: [], + charstrings: [], + properties: { + 'privateData': { + 'lenIV': 4 + } + } + }; + var token, length, data, lenIV, encoded; + while ((token = this.getToken()) !== null) { + if (token !== '/') { + continue; + } + token = this.getToken(); + switch (token) { + case 'CharStrings': + // The number immediately following CharStrings must be greater or + // equal to the number of CharStrings. + this.getToken(); + this.getToken(); // read in 'dict' + this.getToken(); // read in 'dup' + this.getToken(); // read in 'begin' + while(true) { + token = this.getToken(); + if (token === null || token === 'end') { + break; + } + + if (token !== '/') { + continue; + } + var glyph = this.getToken(); + length = this.readInt(); + this.getToken(); // read in 'RD' or '-|' + data = stream.makeSubStream(stream.pos, length); + lenIV = program.properties.privateData['lenIV']; + encoded = decrypt(data.getBytes(), CHAR_STRS_ENCRYPT_KEY, lenIV); + // Skip past the required space and binary data. + stream.skip(length); + this.nextChar(); + token = this.getToken(); // read in 'ND' or '|-' + if (token === 'noaccess') { + this.getToken(); // read in 'def' + } + charstrings.push({ + glyph: glyph, + encoded: encoded + }); + } + break; + case 'Subrs': + var num = this.readInt(); + this.getToken(); // read in 'array' + while ((token = this.getToken()) === 'dup') { + var index = this.readInt(); + length = this.readInt(); + this.getToken(); // read in 'RD' or '-|' + data = stream.makeSubStream(stream.pos, length); + lenIV = program.properties.privateData['lenIV']; + encoded = decrypt(data.getBytes(), CHAR_STRS_ENCRYPT_KEY, lenIV); + // Skip past the required space and binary data. + stream.skip(length); + this.nextChar(); + token = this.getToken(); // read in 'NP' or '|' + if (token === 'noaccess') { + this.getToken(); // read in 'put' + } + subrs[index] = encoded; + } + break; + case 'BlueValues': + case 'OtherBlues': + case 'FamilyBlues': + case 'FamilyOtherBlues': + var blueArray = this.readNumberArray(); + // *Blue* values may contain invalid data: disables reading of + // those values when hinting is disabled. + if (blueArray.length > 0 && (blueArray.length % 2) === 0 && + HINTING_ENABLED) { + program.properties.privateData[token] = blueArray; + } + break; + case 'StemSnapH': + case 'StemSnapV': + program.properties.privateData[token] = this.readNumberArray(); + break; + case 'StdHW': + case 'StdVW': + program.properties.privateData[token] = + this.readNumberArray()[0]; + break; + case 'BlueShift': + case 'lenIV': + case 'BlueFuzz': + case 'BlueScale': + case 'LanguageGroup': + case 'ExpansionFactor': + program.properties.privateData[token] = this.readNumber(); + break; + case 'ForceBold': + program.properties.privateData[token] = this.readBoolean(); + break; + } + } + + for (var i = 0; i < charstrings.length; i++) { + glyph = charstrings[i].glyph; + encoded = charstrings[i].encoded; + var charString = new Type1CharString(); + var error = charString.convert(encoded, subrs); + var output = charString.output; + if (error) { + // It seems when FreeType encounters an error while evaluating a glyph + // that it completely ignores the glyph so we'll mimic that behaviour + // here and put an endchar to make the validator happy. + output = [14]; + } + program.charstrings.push({ + glyphName: glyph, + charstring: output, + width: charString.width, + lsb: charString.lsb, + seac: charString.seac + }); + } + + return program; + }, + + extractFontHeader: function Type1Parser_extractFontHeader(properties) { + var token; + while ((token = this.getToken()) !== null) { + if (token !== '/') { + continue; + } + token = this.getToken(); + switch (token) { + case 'FontMatrix': + var matrix = this.readNumberArray(); + properties.fontMatrix = matrix; + break; + case 'Encoding': + var encodingArg = this.getToken(); + var encoding; + if (!/^\d+$/.test(encodingArg)) { + // encoding name is specified + encoding = Encodings[encodingArg]; + } else { + encoding = []; + var size = parseInt(encodingArg, 10) | 0; + this.getToken(); // read in 'array' + + for (var j = 0; j < size; j++) { + token = this.getToken(); + // skipping till first dup or def (e.g. ignoring for statement) + while (token !== 'dup' && token !== 'def') { + token = this.getToken(); + if (token === null) { + return; // invalid header + } + } + if (token === 'def') { + break; // read all array data + } + var index = this.readInt(); + this.getToken(); // read in '/' + var glyph = this.getToken(); + encoding[index] = glyph; + this.getToken(); // read the in 'put' + } + } + properties.builtInEncoding = encoding; + break; + case 'FontBBox': + var fontBBox = this.readNumberArray(); + // adjusting ascent/descent + properties.ascent = fontBBox[3]; + properties.descent = fontBBox[1]; + properties.ascentScaled = true; + break; + } + } + } + }; + + return Type1Parser; +})(); + +/** + * The CFF class takes a Type1 file and wrap it into a + * 'Compact Font Format' which itself embed Type2 charstrings. + */ +var CFFStandardStrings = [ + '.notdef', 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent', + 'ampersand', 'quoteright', 'parenleft', 'parenright', 'asterisk', 'plus', + 'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two', 'three', 'four', + 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', 'less', + 'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', + 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', + 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright', 'asciicircum', + 'underscore', 'quoteleft', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', + 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', + 'z', 'braceleft', 'bar', 'braceright', 'asciitilde', 'exclamdown', 'cent', + 'sterling', 'fraction', 'yen', 'florin', 'section', 'currency', + 'quotesingle', 'quotedblleft', 'guillemotleft', 'guilsinglleft', + 'guilsinglright', 'fi', 'fl', 'endash', 'dagger', 'daggerdbl', + 'periodcentered', 'paragraph', 'bullet', 'quotesinglbase', 'quotedblbase', + 'quotedblright', 'guillemotright', 'ellipsis', 'perthousand', 'questiondown', + 'grave', 'acute', 'circumflex', 'tilde', 'macron', 'breve', 'dotaccent', + 'dieresis', 'ring', 'cedilla', 'hungarumlaut', 'ogonek', 'caron', 'emdash', + 'AE', 'ordfeminine', 'Lslash', 'Oslash', 'OE', 'ordmasculine', 'ae', + 'dotlessi', 'lslash', 'oslash', 'oe', 'germandbls', 'onesuperior', + 'logicalnot', 'mu', 'trademark', 'Eth', 'onehalf', 'plusminus', 'Thorn', + 'onequarter', 'divide', 'brokenbar', 'degree', 'thorn', 'threequarters', + 'twosuperior', 'registered', 'minus', 'eth', 'multiply', 'threesuperior', + 'copyright', 'Aacute', 'Acircumflex', 'Adieresis', 'Agrave', 'Aring', + 'Atilde', 'Ccedilla', 'Eacute', 'Ecircumflex', 'Edieresis', 'Egrave', + 'Iacute', 'Icircumflex', 'Idieresis', 'Igrave', 'Ntilde', 'Oacute', + 'Ocircumflex', 'Odieresis', 'Ograve', 'Otilde', 'Scaron', 'Uacute', + 'Ucircumflex', 'Udieresis', 'Ugrave', 'Yacute', 'Ydieresis', 'Zcaron', + 'aacute', 'acircumflex', 'adieresis', 'agrave', 'aring', 'atilde', + 'ccedilla', 'eacute', 'ecircumflex', 'edieresis', 'egrave', 'iacute', + 'icircumflex', 'idieresis', 'igrave', 'ntilde', 'oacute', 'ocircumflex', + 'odieresis', 'ograve', 'otilde', 'scaron', 'uacute', 'ucircumflex', + 'udieresis', 'ugrave', 'yacute', 'ydieresis', 'zcaron', 'exclamsmall', + 'Hungarumlautsmall', 'dollaroldstyle', 'dollarsuperior', 'ampersandsmall', + 'Acutesmall', 'parenleftsuperior', 'parenrightsuperior', 'twodotenleader', + 'onedotenleader', 'zerooldstyle', 'oneoldstyle', 'twooldstyle', + 'threeoldstyle', 'fouroldstyle', 'fiveoldstyle', 'sixoldstyle', + 'sevenoldstyle', 'eightoldstyle', 'nineoldstyle', 'commasuperior', + 'threequartersemdash', 'periodsuperior', 'questionsmall', 'asuperior', + 'bsuperior', 'centsuperior', 'dsuperior', 'esuperior', 'isuperior', + 'lsuperior', 'msuperior', 'nsuperior', 'osuperior', 'rsuperior', 'ssuperior', + 'tsuperior', 'ff', 'ffi', 'ffl', 'parenleftinferior', 'parenrightinferior', + 'Circumflexsmall', 'hyphensuperior', 'Gravesmall', 'Asmall', 'Bsmall', + 'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall', 'Hsmall', 'Ismall', + 'Jsmall', 'Ksmall', 'Lsmall', 'Msmall', 'Nsmall', 'Osmall', 'Psmall', + 'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall', 'Vsmall', 'Wsmall', + 'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary', 'onefitted', 'rupiah', + 'Tildesmall', 'exclamdownsmall', 'centoldstyle', 'Lslashsmall', + 'Scaronsmall', 'Zcaronsmall', 'Dieresissmall', 'Brevesmall', 'Caronsmall', + 'Dotaccentsmall', 'Macronsmall', 'figuredash', 'hypheninferior', + 'Ogoneksmall', 'Ringsmall', 'Cedillasmall', 'questiondownsmall', 'oneeighth', + 'threeeighths', 'fiveeighths', 'seveneighths', 'onethird', 'twothirds', + 'zerosuperior', 'foursuperior', 'fivesuperior', 'sixsuperior', + 'sevensuperior', 'eightsuperior', 'ninesuperior', 'zeroinferior', + 'oneinferior', 'twoinferior', 'threeinferior', 'fourinferior', + 'fiveinferior', 'sixinferior', 'seveninferior', 'eightinferior', + 'nineinferior', 'centinferior', 'dollarinferior', 'periodinferior', + 'commainferior', 'Agravesmall', 'Aacutesmall', 'Acircumflexsmall', + 'Atildesmall', 'Adieresissmall', 'Aringsmall', 'AEsmall', 'Ccedillasmall', + 'Egravesmall', 'Eacutesmall', 'Ecircumflexsmall', 'Edieresissmall', + 'Igravesmall', 'Iacutesmall', 'Icircumflexsmall', 'Idieresissmall', + 'Ethsmall', 'Ntildesmall', 'Ogravesmall', 'Oacutesmall', 'Ocircumflexsmall', + 'Otildesmall', 'Odieresissmall', 'OEsmall', 'Oslashsmall', 'Ugravesmall', + 'Uacutesmall', 'Ucircumflexsmall', 'Udieresissmall', 'Yacutesmall', + 'Thornsmall', 'Ydieresissmall', '001.000', '001.001', '001.002', '001.003', + 'Black', 'Bold', 'Book', 'Light', 'Medium', 'Regular', 'Roman', 'Semibold' +]; + +// Type1Font is also a CIDFontType0. +var Type1Font = function Type1Font(name, file, properties) { + // Some bad generators embed pfb file as is, we have to strip 6-byte headers. + // Also, length1 and length2 might be off by 6 bytes as well. + // http://www.math.ubc.ca/~cass/piscript/type1.pdf + var PFB_HEADER_SIZE = 6; + var headerBlockLength = properties.length1; + var eexecBlockLength = properties.length2; + var pfbHeader = file.peekBytes(PFB_HEADER_SIZE); + var pfbHeaderPresent = pfbHeader[0] === 0x80 && pfbHeader[1] === 0x01; + if (pfbHeaderPresent) { + file.skip(PFB_HEADER_SIZE); + headerBlockLength = (pfbHeader[5] << 24) | (pfbHeader[4] << 16) | + (pfbHeader[3] << 8) | pfbHeader[2]; + } + + // Get the data block containing glyphs and subrs informations + var headerBlock = new Stream(file.getBytes(headerBlockLength)); + var headerBlockParser = new Type1Parser(headerBlock); + headerBlockParser.extractFontHeader(properties); + + if (pfbHeaderPresent) { + pfbHeader = file.getBytes(PFB_HEADER_SIZE); + eexecBlockLength = (pfbHeader[5] << 24) | (pfbHeader[4] << 16) | + (pfbHeader[3] << 8) | pfbHeader[2]; + } + + // Decrypt the data blocks and retrieve it's content + var eexecBlock = new Stream(file.getBytes(eexecBlockLength)); + var eexecBlockParser = new Type1Parser(eexecBlock, true); + var data = eexecBlockParser.extractFontProgram(); + for (var info in data.properties) { + properties[info] = data.properties[info]; + } + + var charstrings = data.charstrings; + var type2Charstrings = this.getType2Charstrings(charstrings); + var subrs = this.getType2Subrs(data.subrs); + + this.charstrings = charstrings; + this.data = this.wrap(name, type2Charstrings, this.charstrings, + subrs, properties); + this.seacs = this.getSeacs(data.charstrings); +}; + +Type1Font.prototype = { + get numGlyphs() { + return this.charstrings.length + 1; + }, + + getCharset: function Type1Font_getCharset() { + var charset = ['.notdef']; + var charstrings = this.charstrings; + for (var glyphId = 0; glyphId < charstrings.length; glyphId++) { + charset.push(charstrings[glyphId].glyphName); + } + return charset; + }, + + getGlyphMapping: function Type1Font_getGlyphMapping(properties) { + var charstrings = this.charstrings; + var glyphNames = ['.notdef'], glyphId; + for (glyphId = 0; glyphId < charstrings.length; glyphId++) { + glyphNames.push(charstrings[glyphId].glyphName); + } + var encoding = properties.builtInEncoding; + if (encoding) { + var builtInEncoding = {}; + for (var charCode in encoding) { + glyphId = glyphNames.indexOf(encoding[charCode]); + if (glyphId >= 0) { + builtInEncoding[charCode] = glyphId; + } + } + } + + return type1FontGlyphMapping(properties, builtInEncoding, glyphNames); + }, + + getSeacs: function Type1Font_getSeacs(charstrings) { + var i, ii; + var seacMap = []; + for (i = 0, ii = charstrings.length; i < ii; i++) { + var charstring = charstrings[i]; + if (charstring.seac) { + // Offset by 1 for .notdef + seacMap[i + 1] = charstring.seac; + } + } + return seacMap; + }, + + getType2Charstrings: function Type1Font_getType2Charstrings( + type1Charstrings) { + var type2Charstrings = []; + for (var i = 0, ii = type1Charstrings.length; i < ii; i++) { + type2Charstrings.push(type1Charstrings[i].charstring); + } + return type2Charstrings; + }, + + getType2Subrs: function Type1Font_getType2Subrs(type1Subrs) { + var bias = 0; + var count = type1Subrs.length; + if (count < 1133) { + bias = 107; + } else if (count < 33769) { + bias = 1131; + } else { + bias = 32768; + } + + // Add a bunch of empty subrs to deal with the Type2 bias + var type2Subrs = []; + var i; + for (i = 0; i < bias; i++) { + type2Subrs.push([0x0B]); + } + + for (i = 0; i < count; i++) { + type2Subrs.push(type1Subrs[i]); + } + + return type2Subrs; + }, + + wrap: function Type1Font_wrap(name, glyphs, charstrings, subrs, properties) { + var cff = new CFF(); + cff.header = new CFFHeader(1, 0, 4, 4); + + cff.names = [name]; + + var topDict = new CFFTopDict(); + // CFF strings IDs 0...390 are predefined names, so refering + // to entries in our own String INDEX starts at SID 391. + topDict.setByName('version', 391); + topDict.setByName('Notice', 392); + topDict.setByName('FullName', 393); + topDict.setByName('FamilyName', 394); + topDict.setByName('Weight', 395); + topDict.setByName('Encoding', null); // placeholder + topDict.setByName('FontMatrix', properties.fontMatrix); + topDict.setByName('FontBBox', properties.bbox); + topDict.setByName('charset', null); // placeholder + topDict.setByName('CharStrings', null); // placeholder + topDict.setByName('Private', null); // placeholder + cff.topDict = topDict; + + var strings = new CFFStrings(); + strings.add('Version 0.11'); // Version + strings.add('See original notice'); // Notice + strings.add(name); // FullName + strings.add(name); // FamilyName + strings.add('Medium'); // Weight + cff.strings = strings; + + cff.globalSubrIndex = new CFFIndex(); + + var count = glyphs.length; + var charsetArray = [0]; + var i, ii; + for (i = 0; i < count; i++) { + var index = CFFStandardStrings.indexOf(charstrings[i].glyphName); + // TODO: Insert the string and correctly map it. Previously it was + // thought mapping names that aren't in the standard strings to .notdef + // was fine, however in issue818 when mapping them all to .notdef the + // adieresis glyph no longer worked. + if (index === -1) { + index = 0; + } + charsetArray.push((index >> 8) & 0xff, index & 0xff); + } + cff.charset = new CFFCharset(false, 0, [], charsetArray); + + var charStringsIndex = new CFFIndex(); + charStringsIndex.add([0x8B, 0x0E]); // .notdef + for (i = 0; i < count; i++) { + charStringsIndex.add(glyphs[i]); + } + cff.charStrings = charStringsIndex; + + var privateDict = new CFFPrivateDict(); + privateDict.setByName('Subrs', null); // placeholder + var fields = [ + 'BlueValues', + 'OtherBlues', + 'FamilyBlues', + 'FamilyOtherBlues', + 'StemSnapH', + 'StemSnapV', + 'BlueShift', + 'BlueFuzz', + 'BlueScale', + 'LanguageGroup', + 'ExpansionFactor', + 'ForceBold', + 'StdHW', + 'StdVW' + ]; + for (i = 0, ii = fields.length; i < ii; i++) { + var field = fields[i]; + if (!properties.privateData.hasOwnProperty(field)) { + continue; + } + var value = properties.privateData[field]; + if (isArray(value)) { + // All of the private dictionary array data in CFF must be stored as + // "delta-encoded" numbers. + for (var j = value.length - 1; j > 0; j--) { + value[j] -= value[j - 1]; // ... difference from previous value + } + } + privateDict.setByName(field, value); + } + cff.topDict.privateDict = privateDict; + + var subrIndex = new CFFIndex(); + for (i = 0, ii = subrs.length; i < ii; i++) { + subrIndex.add(subrs[i]); + } + privateDict.subrsIndex = subrIndex; + + var compiler = new CFFCompiler(cff); + return compiler.compile(); + } +}; + +var CFFFont = (function CFFFontClosure() { + function CFFFont(file, properties) { + this.properties = properties; + + var parser = new CFFParser(file, properties); + this.cff = parser.parse(); + var compiler = new CFFCompiler(this.cff); + this.seacs = this.cff.seacs; + try { + this.data = compiler.compile(); + } catch (e) { + warn('Failed to compile font ' + properties.loadedName); + // There may have just been an issue with the compiler, set the data + // anyway and hope the font loaded. + this.data = file; + } + } + + CFFFont.prototype = { + get numGlyphs() { + return this.cff.charStrings.count; + }, + getCharset: function CFFFont_getCharset() { + return this.cff.charset.charset; + }, + getGlyphMapping: function CFFFont_getGlyphMapping() { + var cff = this.cff; + var properties = this.properties; + var charsets = cff.charset.charset; + var charCodeToGlyphId; + var glyphId; + + if (properties.composite) { + charCodeToGlyphId = Object.create(null); + if (cff.isCIDFont) { + // If the font is actually a CID font then we should use the charset + // to map CIDs to GIDs. + for (glyphId = 0; glyphId < charsets.length; glyphId++) { + var cid = charsets[glyphId]; + var charCode = properties.cMap.charCodeOf(cid); + charCodeToGlyphId[charCode] = glyphId; + } + } else { + // If it is NOT actually a CID font then CIDs should be mapped + // directly to GIDs. + for (glyphId = 0; glyphId < cff.charStrings.count; glyphId++) { + charCodeToGlyphId[glyphId] = glyphId; + } + } + return charCodeToGlyphId; + } + + var encoding = cff.encoding ? cff.encoding.encoding : null; + charCodeToGlyphId = type1FontGlyphMapping(properties, encoding, charsets); + return charCodeToGlyphId; + } + }; + + return CFFFont; +})(); + +var CFFParser = (function CFFParserClosure() { + var CharstringValidationData = [ + null, + { id: 'hstem', min: 2, stackClearing: true, stem: true }, + null, + { id: 'vstem', min: 2, stackClearing: true, stem: true }, + { id: 'vmoveto', min: 1, stackClearing: true }, + { id: 'rlineto', min: 2, resetStack: true }, + { id: 'hlineto', min: 1, resetStack: true }, + { id: 'vlineto', min: 1, resetStack: true }, + { id: 'rrcurveto', min: 6, resetStack: true }, + null, + { id: 'callsubr', min: 1, undefStack: true }, + { id: 'return', min: 0, undefStack: true }, + null, // 12 + null, + { id: 'endchar', min: 0, stackClearing: true }, + null, + null, + null, + { id: 'hstemhm', min: 2, stackClearing: true, stem: true }, + { id: 'hintmask', min: 0, stackClearing: true }, + { id: 'cntrmask', min: 0, stackClearing: true }, + { id: 'rmoveto', min: 2, stackClearing: true }, + { id: 'hmoveto', min: 1, stackClearing: true }, + { id: 'vstemhm', min: 2, stackClearing: true, stem: true }, + { id: 'rcurveline', min: 8, resetStack: true }, + { id: 'rlinecurve', min: 8, resetStack: true }, + { id: 'vvcurveto', min: 4, resetStack: true }, + { id: 'hhcurveto', min: 4, resetStack: true }, + null, // shortint + { id: 'callgsubr', min: 1, undefStack: true }, + { id: 'vhcurveto', min: 4, resetStack: true }, + { id: 'hvcurveto', min: 4, resetStack: true } + ]; + var CharstringValidationData12 = [ + null, + null, + null, + { id: 'and', min: 2, stackDelta: -1 }, + { id: 'or', min: 2, stackDelta: -1 }, + { id: 'not', min: 1, stackDelta: 0 }, + null, + null, + null, + { id: 'abs', min: 1, stackDelta: 0 }, + { id: 'add', min: 2, stackDelta: -1, + stackFn: function stack_div(stack, index) { + stack[index - 2] = stack[index - 2] + stack[index - 1]; + } + }, + { id: 'sub', min: 2, stackDelta: -1, + stackFn: function stack_div(stack, index) { + stack[index - 2] = stack[index - 2] - stack[index - 1]; + } + }, + { id: 'div', min: 2, stackDelta: -1, + stackFn: function stack_div(stack, index) { + stack[index - 2] = stack[index - 2] / stack[index - 1]; + } + }, + null, + { id: 'neg', min: 1, stackDelta: 0, + stackFn: function stack_div(stack, index) { + stack[index - 1] = -stack[index - 1]; + } + }, + { id: 'eq', min: 2, stackDelta: -1 }, + null, + null, + { id: 'drop', min: 1, stackDelta: -1 }, + null, + { id: 'put', min: 2, stackDelta: -2 }, + { id: 'get', min: 1, stackDelta: 0 }, + { id: 'ifelse', min: 4, stackDelta: -3 }, + { id: 'random', min: 0, stackDelta: 1 }, + { id: 'mul', min: 2, stackDelta: -1, + stackFn: function stack_div(stack, index) { + stack[index - 2] = stack[index - 2] * stack[index - 1]; + } + }, + null, + { id: 'sqrt', min: 1, stackDelta: 0 }, + { id: 'dup', min: 1, stackDelta: 1 }, + { id: 'exch', min: 2, stackDelta: 0 }, + { id: 'index', min: 2, stackDelta: 0 }, + { id: 'roll', min: 3, stackDelta: -2 }, + null, + null, + null, + { id: 'hflex', min: 7, resetStack: true }, + { id: 'flex', min: 13, resetStack: true }, + { id: 'hflex1', min: 9, resetStack: true }, + { id: 'flex1', min: 11, resetStack: true } + ]; + + function CFFParser(file, properties) { + this.bytes = file.getBytes(); + this.properties = properties; + } + CFFParser.prototype = { + parse: function CFFParser_parse() { + var properties = this.properties; + var cff = new CFF(); + this.cff = cff; + + // The first five sections must be in order, all the others are reached + // via offsets contained in one of the below. + var header = this.parseHeader(); + var nameIndex = this.parseIndex(header.endPos); + var topDictIndex = this.parseIndex(nameIndex.endPos); + var stringIndex = this.parseIndex(topDictIndex.endPos); + var globalSubrIndex = this.parseIndex(stringIndex.endPos); + + var topDictParsed = this.parseDict(topDictIndex.obj.get(0)); + var topDict = this.createDict(CFFTopDict, topDictParsed, cff.strings); + + cff.header = header.obj; + cff.names = this.parseNameIndex(nameIndex.obj); + cff.strings = this.parseStringIndex(stringIndex.obj); + cff.topDict = topDict; + cff.globalSubrIndex = globalSubrIndex.obj; + + this.parsePrivateDict(cff.topDict); + + cff.isCIDFont = topDict.hasName('ROS'); + + var charStringOffset = topDict.getByName('CharStrings'); + var charStringsAndSeacs = this.parseCharStrings(charStringOffset); + cff.charStrings = charStringsAndSeacs.charStrings; + cff.seacs = charStringsAndSeacs.seacs; + cff.widths = charStringsAndSeacs.widths; + + var fontMatrix = topDict.getByName('FontMatrix'); + if (fontMatrix) { + properties.fontMatrix = fontMatrix; + } + + var fontBBox = topDict.getByName('FontBBox'); + if (fontBBox) { + // adjusting ascent/descent + properties.ascent = fontBBox[3]; + properties.descent = fontBBox[1]; + properties.ascentScaled = true; + } + + var charset, encoding; + if (cff.isCIDFont) { + var fdArrayIndex = this.parseIndex(topDict.getByName('FDArray')).obj; + for (var i = 0, ii = fdArrayIndex.count; i < ii; ++i) { + var dictRaw = fdArrayIndex.get(i); + var fontDict = this.createDict(CFFTopDict, this.parseDict(dictRaw), + cff.strings); + this.parsePrivateDict(fontDict); + cff.fdArray.push(fontDict); + } + // cid fonts don't have an encoding + encoding = null; + charset = this.parseCharsets(topDict.getByName('charset'), + cff.charStrings.count, cff.strings, true); + cff.fdSelect = this.parseFDSelect(topDict.getByName('FDSelect'), + cff.charStrings.count); + } else { + charset = this.parseCharsets(topDict.getByName('charset'), + cff.charStrings.count, cff.strings, false); + encoding = this.parseEncoding(topDict.getByName('Encoding'), + properties, + cff.strings, charset.charset); + } + cff.charset = charset; + cff.encoding = encoding; + + return cff; + }, + parseHeader: function CFFParser_parseHeader() { + var bytes = this.bytes; + var bytesLength = bytes.length; + var offset = 0; + + // Prevent an infinite loop, by checking that the offset is within the + // bounds of the bytes array. Necessary in empty, or invalid, font files. + while (offset < bytesLength && bytes[offset] !== 1) { + ++offset; + } + if (offset >= bytesLength) { + error('Invalid CFF header'); + } else if (offset !== 0) { + info('cff data is shifted'); + bytes = bytes.subarray(offset); + this.bytes = bytes; + } + var major = bytes[0]; + var minor = bytes[1]; + var hdrSize = bytes[2]; + var offSize = bytes[3]; + var header = new CFFHeader(major, minor, hdrSize, offSize); + return { obj: header, endPos: hdrSize }; + }, + parseDict: function CFFParser_parseDict(dict) { + var pos = 0; + + function parseOperand() { + var value = dict[pos++]; + if (value === 30) { + return parseFloatOperand(pos); + } else if (value === 28) { + value = dict[pos++]; + value = ((value << 24) | (dict[pos++] << 16)) >> 16; + return value; + } else if (value === 29) { + value = dict[pos++]; + value = (value << 8) | dict[pos++]; + value = (value << 8) | dict[pos++]; + value = (value << 8) | dict[pos++]; + return value; + } else if (value >= 32 && value <= 246) { + return value - 139; + } else if (value >= 247 && value <= 250) { + return ((value - 247) * 256) + dict[pos++] + 108; + } else if (value >= 251 && value <= 254) { + return -((value - 251) * 256) - dict[pos++] - 108; + } else { + error('255 is not a valid DICT command'); + } + return -1; + } + + function parseFloatOperand() { + var str = ''; + var eof = 15; + var lookup = ['0', '1', '2', '3', '4', '5', '6', '7', '8', + '9', '.', 'E', 'E-', null, '-']; + var length = dict.length; + while (pos < length) { + var b = dict[pos++]; + var b1 = b >> 4; + var b2 = b & 15; + + if (b1 === eof) { + break; + } + str += lookup[b1]; + + if (b2 === eof) { + break; + } + str += lookup[b2]; + } + return parseFloat(str); + } + + var operands = []; + var entries = []; + + pos = 0; + var end = dict.length; + while (pos < end) { + var b = dict[pos]; + if (b <= 21) { + if (b === 12) { + b = (b << 8) | dict[++pos]; + } + entries.push([b, operands]); + operands = []; + ++pos; + } else { + operands.push(parseOperand()); + } + } + return entries; + }, + parseIndex: function CFFParser_parseIndex(pos) { + var cffIndex = new CFFIndex(); + var bytes = this.bytes; + var count = (bytes[pos++] << 8) | bytes[pos++]; + var offsets = []; + var end = pos; + var i, ii; + + if (count !== 0) { + var offsetSize = bytes[pos++]; + // add 1 for offset to determine size of last object + var startPos = pos + ((count + 1) * offsetSize) - 1; + + for (i = 0, ii = count + 1; i < ii; ++i) { + var offset = 0; + for (var j = 0; j < offsetSize; ++j) { + offset <<= 8; + offset += bytes[pos++]; + } + offsets.push(startPos + offset); + } + end = offsets[count]; + } + for (i = 0, ii = offsets.length - 1; i < ii; ++i) { + var offsetStart = offsets[i]; + var offsetEnd = offsets[i + 1]; + cffIndex.add(bytes.subarray(offsetStart, offsetEnd)); + } + return {obj: cffIndex, endPos: end}; + }, + parseNameIndex: function CFFParser_parseNameIndex(index) { + var names = []; + for (var i = 0, ii = index.count; i < ii; ++i) { + var name = index.get(i); + // OTS doesn't allow names to be over 127 characters. + var length = Math.min(name.length, 127); + var data = []; + // OTS also only permits certain characters in the name. + for (var j = 0; j < length; ++j) { + var c = name[j]; + if (j === 0 && c === 0) { + data[j] = c; + continue; + } + if ((c < 33 || c > 126) || c === 91 /* [ */ || c === 93 /* ] */ || + c === 40 /* ( */ || c === 41 /* ) */ || c === 123 /* { */ || + c === 125 /* } */ || c === 60 /* < */ || c === 62 /* > */ || + c === 47 /* / */ || c === 37 /* % */ || c === 35 /* # */) { + data[j] = 95; + continue; + } + data[j] = c; + } + names.push(bytesToString(data)); + } + return names; + }, + parseStringIndex: function CFFParser_parseStringIndex(index) { + var strings = new CFFStrings(); + for (var i = 0, ii = index.count; i < ii; ++i) { + var data = index.get(i); + strings.add(bytesToString(data)); + } + return strings; + }, + createDict: function CFFParser_createDict(Type, dict, strings) { + var cffDict = new Type(strings); + for (var i = 0, ii = dict.length; i < ii; ++i) { + var pair = dict[i]; + var key = pair[0]; + var value = pair[1]; + cffDict.setByKey(key, value); + } + return cffDict; + }, + parseCharStrings: function CFFParser_parseCharStrings(charStringOffset) { + var charStrings = this.parseIndex(charStringOffset).obj; + var seacs = []; + var widths = []; + var count = charStrings.count; + for (var i = 0; i < count; i++) { + var charstring = charStrings.get(i); + + var stackSize = 0; + var stack = []; + var undefStack = true; + var hints = 0; + var valid = true; + var data = charstring; + var length = data.length; + var firstStackClearing = true; + for (var j = 0; j < length;) { + var value = data[j++]; + var validationCommand = null; + if (value === 12) { + var q = data[j++]; + if (q === 0) { + // The CFF specification state that the 'dotsection' command + // (12, 0) is deprecated and treated as a no-op, but all Type2 + // charstrings processors should support them. Unfortunately + // the font sanitizer don't. As a workaround the sequence (12, 0) + // is replaced by a useless (0, hmoveto). + data[j - 2] = 139; + data[j - 1] = 22; + stackSize = 0; + } else { + validationCommand = CharstringValidationData12[q]; + } + } else if (value === 28) { // number (16 bit) + stack[stackSize] = ((data[j] << 24) | (data[j + 1] << 16)) >> 16; + j += 2; + stackSize++; + } else if (value === 14) { + if (stackSize >= 4) { + stackSize -= 4; + if (SEAC_ANALYSIS_ENABLED) { + seacs[i] = stack.slice(stackSize, stackSize + 4); + valid = false; + } + } + validationCommand = CharstringValidationData[value]; + } else if (value >= 32 && value <= 246) { // number + stack[stackSize] = value - 139; + stackSize++; + } else if (value >= 247 && value <= 254) { // number (+1 bytes) + stack[stackSize] = (value < 251 ? + ((value - 247) << 8) + data[j] + 108 : + -((value - 251) << 8) - data[j] - 108); + j++; + stackSize++; + } else if (value === 255) { // number (32 bit) + stack[stackSize] = ((data[j] << 24) | (data[j + 1] << 16) | + (data[j + 2] << 8) | data[j + 3]) / 65536; + j += 4; + stackSize++; + } else if (value === 19 || value === 20) { + hints += stackSize >> 1; + j += (hints + 7) >> 3; // skipping right amount of hints flag data + stackSize %= 2; + validationCommand = CharstringValidationData[value]; + } else { + validationCommand = CharstringValidationData[value]; + } + if (validationCommand) { + if (validationCommand.stem) { + hints += stackSize >> 1; + } + if ('min' in validationCommand) { + if (!undefStack && stackSize < validationCommand.min) { + warn('Not enough parameters for ' + validationCommand.id + + '; actual: ' + stackSize + + ', expected: ' + validationCommand.min); + valid = false; + break; + } + } + if (firstStackClearing && validationCommand.stackClearing) { + firstStackClearing = false; + // the optional character width can be found before the first + // stack-clearing command arguments + stackSize -= validationCommand.min; + if (stackSize >= 2 && validationCommand.stem) { + // there are even amount of arguments for stem commands + stackSize %= 2; + } else if (stackSize > 1) { + warn('Found too many parameters for stack-clearing command'); + } + if (stackSize > 0 && stack[stackSize - 1] >= 0) { + widths[i] = stack[stackSize - 1]; + } + } + if ('stackDelta' in validationCommand) { + if ('stackFn' in validationCommand) { + validationCommand.stackFn(stack, stackSize); + } + stackSize += validationCommand.stackDelta; + } else if (validationCommand.stackClearing) { + stackSize = 0; + } else if (validationCommand.resetStack) { + stackSize = 0; + undefStack = false; + } else if (validationCommand.undefStack) { + stackSize = 0; + undefStack = true; + firstStackClearing = false; + } + } + } + if (!valid) { + // resetting invalid charstring to single 'endchar' + charStrings.set(i, new Uint8Array([14])); + } + } + return { charStrings: charStrings, seacs: seacs, widths: widths }; + }, + emptyPrivateDictionary: + function CFFParser_emptyPrivateDictionary(parentDict) { + var privateDict = this.createDict(CFFPrivateDict, [], + parentDict.strings); + parentDict.setByKey(18, [0, 0]); + parentDict.privateDict = privateDict; + }, + parsePrivateDict: function CFFParser_parsePrivateDict(parentDict) { + // no private dict, do nothing + if (!parentDict.hasName('Private')) { + this.emptyPrivateDictionary(parentDict); + return; + } + var privateOffset = parentDict.getByName('Private'); + // make sure the params are formatted correctly + if (!isArray(privateOffset) || privateOffset.length !== 2) { + parentDict.removeByName('Private'); + return; + } + var size = privateOffset[0]; + var offset = privateOffset[1]; + // remove empty dicts or ones that refer to invalid location + if (size === 0 || offset >= this.bytes.length) { + this.emptyPrivateDictionary(parentDict); + return; + } + + var privateDictEnd = offset + size; + var dictData = this.bytes.subarray(offset, privateDictEnd); + var dict = this.parseDict(dictData); + var privateDict = this.createDict(CFFPrivateDict, dict, + parentDict.strings); + parentDict.privateDict = privateDict; + + // Parse the Subrs index also since it's relative to the private dict. + if (!privateDict.getByName('Subrs')) { + return; + } + var subrsOffset = privateDict.getByName('Subrs'); + var relativeOffset = offset + subrsOffset; + // Validate the offset. + if (subrsOffset === 0 || relativeOffset >= this.bytes.length) { + this.emptyPrivateDictionary(parentDict); + return; + } + var subrsIndex = this.parseIndex(relativeOffset); + privateDict.subrsIndex = subrsIndex.obj; + }, + parseCharsets: function CFFParser_parseCharsets(pos, length, strings, cid) { + if (pos === 0) { + return new CFFCharset(true, CFFCharsetPredefinedTypes.ISO_ADOBE, + ISOAdobeCharset); + } else if (pos === 1) { + return new CFFCharset(true, CFFCharsetPredefinedTypes.EXPERT, + ExpertCharset); + } else if (pos === 2) { + return new CFFCharset(true, CFFCharsetPredefinedTypes.EXPERT_SUBSET, + ExpertSubsetCharset); + } + + var bytes = this.bytes; + var start = pos; + var format = bytes[pos++]; + var charset = ['.notdef']; + var id, count, i; + + // subtract 1 for the .notdef glyph + length -= 1; + + switch (format) { + case 0: + for (i = 0; i < length; i++) { + id = (bytes[pos++] << 8) | bytes[pos++]; + charset.push(cid ? id : strings.get(id)); + } + break; + case 1: + while (charset.length <= length) { + id = (bytes[pos++] << 8) | bytes[pos++]; + count = bytes[pos++]; + for (i = 0; i <= count; i++) { + charset.push(cid ? id++ : strings.get(id++)); + } + } + break; + case 2: + while (charset.length <= length) { + id = (bytes[pos++] << 8) | bytes[pos++]; + count = (bytes[pos++] << 8) | bytes[pos++]; + for (i = 0; i <= count; i++) { + charset.push(cid ? id++ : strings.get(id++)); + } + } + break; + default: + error('Unknown charset format'); + } + // Raw won't be needed if we actually compile the charset. + var end = pos; + var raw = bytes.subarray(start, end); + + return new CFFCharset(false, format, charset, raw); + }, + parseEncoding: function CFFParser_parseEncoding(pos, + properties, + strings, + charset) { + var encoding = {}; + var bytes = this.bytes; + var predefined = false; + var hasSupplement = false; + var format, i, ii; + var raw = null; + + function readSupplement() { + var supplementsCount = bytes[pos++]; + for (i = 0; i < supplementsCount; i++) { + var code = bytes[pos++]; + var sid = (bytes[pos++] << 8) + (bytes[pos++] & 0xff); + encoding[code] = charset.indexOf(strings.get(sid)); + } + } + + if (pos === 0 || pos === 1) { + predefined = true; + format = pos; + var baseEncoding = pos ? Encodings.ExpertEncoding : + Encodings.StandardEncoding; + for (i = 0, ii = charset.length; i < ii; i++) { + var index = baseEncoding.indexOf(charset[i]); + if (index !== -1) { + encoding[index] = i; + } + } + } else { + var dataStart = pos; + format = bytes[pos++]; + switch (format & 0x7f) { + case 0: + var glyphsCount = bytes[pos++]; + for (i = 1; i <= glyphsCount; i++) { + encoding[bytes[pos++]] = i; + } + break; + + case 1: + var rangesCount = bytes[pos++]; + var gid = 1; + for (i = 0; i < rangesCount; i++) { + var start = bytes[pos++]; + var left = bytes[pos++]; + for (var j = start; j <= start + left; j++) { + encoding[j] = gid++; + } + } + break; + + default: + error('Unknow encoding format: ' + format + ' in CFF'); + break; + } + var dataEnd = pos; + if (format & 0x80) { + // The font sanitizer does not support CFF encoding with a + // supplement, since the encoding is not really used to map + // between gid to glyph, let's overwrite what is declared in + // the top dictionary to let the sanitizer think the font use + // StandardEncoding, that's a lie but that's ok. + bytes[dataStart] &= 0x7f; + readSupplement(); + hasSupplement = true; + } + raw = bytes.subarray(dataStart, dataEnd); + } + format = format & 0x7f; + return new CFFEncoding(predefined, format, encoding, raw); + }, + parseFDSelect: function CFFParser_parseFDSelect(pos, length) { + var start = pos; + var bytes = this.bytes; + var format = bytes[pos++]; + var fdSelect = []; + var i; + + switch (format) { + case 0: + for (i = 0; i < length; ++i) { + var id = bytes[pos++]; + fdSelect.push(id); + } + break; + case 3: + var rangesCount = (bytes[pos++] << 8) | bytes[pos++]; + for (i = 0; i < rangesCount; ++i) { + var first = (bytes[pos++] << 8) | bytes[pos++]; + var fdIndex = bytes[pos++]; + var next = (bytes[pos] << 8) | bytes[pos + 1]; + for (var j = first; j < next; ++j) { + fdSelect.push(fdIndex); + } + } + // Advance past the sentinel(next). + pos += 2; + break; + default: + error('Unknown fdselect format ' + format); + break; + } + var end = pos; + return new CFFFDSelect(fdSelect, bytes.subarray(start, end)); + } + }; + return CFFParser; +})(); + +// Compact Font Format +var CFF = (function CFFClosure() { + function CFF() { + this.header = null; + this.names = []; + this.topDict = null; + this.strings = new CFFStrings(); + this.globalSubrIndex = null; + + // The following could really be per font, but since we only have one font + // store them here. + this.encoding = null; + this.charset = null; + this.charStrings = null; + this.fdArray = []; + this.fdSelect = null; + + this.isCIDFont = false; + } + return CFF; +})(); + +var CFFHeader = (function CFFHeaderClosure() { + function CFFHeader(major, minor, hdrSize, offSize) { + this.major = major; + this.minor = minor; + this.hdrSize = hdrSize; + this.offSize = offSize; + } + return CFFHeader; +})(); + +var CFFStrings = (function CFFStringsClosure() { + function CFFStrings() { + this.strings = []; + } + CFFStrings.prototype = { + get: function CFFStrings_get(index) { + if (index >= 0 && index <= 390) { + return CFFStandardStrings[index]; + } + if (index - 391 <= this.strings.length) { + return this.strings[index - 391]; + } + return CFFStandardStrings[0]; + }, + add: function CFFStrings_add(value) { + this.strings.push(value); + }, + get count() { + return this.strings.length; + } + }; + return CFFStrings; +})(); + +var CFFIndex = (function CFFIndexClosure() { + function CFFIndex() { + this.objects = []; + this.length = 0; + } + CFFIndex.prototype = { + add: function CFFIndex_add(data) { + this.length += data.length; + this.objects.push(data); + }, + set: function CFFIndex_set(index, data) { + this.length += data.length - this.objects[index].length; + this.objects[index] = data; + }, + get: function CFFIndex_get(index) { + return this.objects[index]; + }, + get count() { + return this.objects.length; + } + }; + return CFFIndex; +})(); + +var CFFDict = (function CFFDictClosure() { + function CFFDict(tables, strings) { + this.keyToNameMap = tables.keyToNameMap; + this.nameToKeyMap = tables.nameToKeyMap; + this.defaults = tables.defaults; + this.types = tables.types; + this.opcodes = tables.opcodes; + this.order = tables.order; + this.strings = strings; + this.values = {}; + } + CFFDict.prototype = { + // value should always be an array + setByKey: function CFFDict_setByKey(key, value) { + if (!(key in this.keyToNameMap)) { + return false; + } + // ignore empty values + if (value.length === 0) { + return true; + } + var type = this.types[key]; + // remove the array wrapping these types of values + if (type === 'num' || type === 'sid' || type === 'offset') { + value = value[0]; + } + this.values[key] = value; + return true; + }, + setByName: function CFFDict_setByName(name, value) { + if (!(name in this.nameToKeyMap)) { + error('Invalid dictionary name "' + name + '"'); + } + this.values[this.nameToKeyMap[name]] = value; + }, + hasName: function CFFDict_hasName(name) { + return this.nameToKeyMap[name] in this.values; + }, + getByName: function CFFDict_getByName(name) { + if (!(name in this.nameToKeyMap)) { + error('Invalid dictionary name "' + name + '"'); + } + var key = this.nameToKeyMap[name]; + if (!(key in this.values)) { + return this.defaults[key]; + } + return this.values[key]; + }, + removeByName: function CFFDict_removeByName(name) { + delete this.values[this.nameToKeyMap[name]]; + } + }; + CFFDict.createTables = function CFFDict_createTables(layout) { + var tables = { + keyToNameMap: {}, + nameToKeyMap: {}, + defaults: {}, + types: {}, + opcodes: {}, + order: [] + }; + for (var i = 0, ii = layout.length; i < ii; ++i) { + var entry = layout[i]; + var key = isArray(entry[0]) ? (entry[0][0] << 8) + entry[0][1] : entry[0]; + tables.keyToNameMap[key] = entry[1]; + tables.nameToKeyMap[entry[1]] = key; + tables.types[key] = entry[2]; + tables.defaults[key] = entry[3]; + tables.opcodes[key] = isArray(entry[0]) ? entry[0] : [entry[0]]; + tables.order.push(key); + } + return tables; + }; + return CFFDict; +})(); + +var CFFTopDict = (function CFFTopDictClosure() { + var layout = [ + [[12, 30], 'ROS', ['sid', 'sid', 'num'], null], + [[12, 20], 'SyntheticBase', 'num', null], + [0, 'version', 'sid', null], + [1, 'Notice', 'sid', null], + [[12, 0], 'Copyright', 'sid', null], + [2, 'FullName', 'sid', null], + [3, 'FamilyName', 'sid', null], + [4, 'Weight', 'sid', null], + [[12, 1], 'isFixedPitch', 'num', 0], + [[12, 2], 'ItalicAngle', 'num', 0], + [[12, 3], 'UnderlinePosition', 'num', -100], + [[12, 4], 'UnderlineThickness', 'num', 50], + [[12, 5], 'PaintType', 'num', 0], + [[12, 6], 'CharstringType', 'num', 2], + [[12, 7], 'FontMatrix', ['num', 'num', 'num', 'num', 'num', 'num'], + [0.001, 0, 0, 0.001, 0, 0]], + [13, 'UniqueID', 'num', null], + [5, 'FontBBox', ['num', 'num', 'num', 'num'], [0, 0, 0, 0]], + [[12, 8], 'StrokeWidth', 'num', 0], + [14, 'XUID', 'array', null], + [15, 'charset', 'offset', 0], + [16, 'Encoding', 'offset', 0], + [17, 'CharStrings', 'offset', 0], + [18, 'Private', ['offset', 'offset'], null], + [[12, 21], 'PostScript', 'sid', null], + [[12, 22], 'BaseFontName', 'sid', null], + [[12, 23], 'BaseFontBlend', 'delta', null], + [[12, 31], 'CIDFontVersion', 'num', 0], + [[12, 32], 'CIDFontRevision', 'num', 0], + [[12, 33], 'CIDFontType', 'num', 0], + [[12, 34], 'CIDCount', 'num', 8720], + [[12, 35], 'UIDBase', 'num', null], + // XXX: CID Fonts on DirectWrite 6.1 only seem to work if FDSelect comes + // before FDArray. + [[12, 37], 'FDSelect', 'offset', null], + [[12, 36], 'FDArray', 'offset', null], + [[12, 38], 'FontName', 'sid', null] + ]; + var tables = null; + function CFFTopDict(strings) { + if (tables === null) { + tables = CFFDict.createTables(layout); + } + CFFDict.call(this, tables, strings); + this.privateDict = null; + } + CFFTopDict.prototype = Object.create(CFFDict.prototype); + return CFFTopDict; +})(); + +var CFFPrivateDict = (function CFFPrivateDictClosure() { + var layout = [ + [6, 'BlueValues', 'delta', null], + [7, 'OtherBlues', 'delta', null], + [8, 'FamilyBlues', 'delta', null], + [9, 'FamilyOtherBlues', 'delta', null], + [[12, 9], 'BlueScale', 'num', 0.039625], + [[12, 10], 'BlueShift', 'num', 7], + [[12, 11], 'BlueFuzz', 'num', 1], + [10, 'StdHW', 'num', null], + [11, 'StdVW', 'num', null], + [[12, 12], 'StemSnapH', 'delta', null], + [[12, 13], 'StemSnapV', 'delta', null], + [[12, 14], 'ForceBold', 'num', 0], + [[12, 17], 'LanguageGroup', 'num', 0], + [[12, 18], 'ExpansionFactor', 'num', 0.06], + [[12, 19], 'initialRandomSeed', 'num', 0], + [20, 'defaultWidthX', 'num', 0], + [21, 'nominalWidthX', 'num', 0], + [19, 'Subrs', 'offset', null] + ]; + var tables = null; + function CFFPrivateDict(strings) { + if (tables === null) { + tables = CFFDict.createTables(layout); + } + CFFDict.call(this, tables, strings); + this.subrsIndex = null; + } + CFFPrivateDict.prototype = Object.create(CFFDict.prototype); + return CFFPrivateDict; +})(); + +var CFFCharsetPredefinedTypes = { + ISO_ADOBE: 0, + EXPERT: 1, + EXPERT_SUBSET: 2 +}; +var CFFCharset = (function CFFCharsetClosure() { + function CFFCharset(predefined, format, charset, raw) { + this.predefined = predefined; + this.format = format; + this.charset = charset; + this.raw = raw; + } + return CFFCharset; +})(); + +var CFFEncoding = (function CFFEncodingClosure() { + function CFFEncoding(predefined, format, encoding, raw) { + this.predefined = predefined; + this.format = format; + this.encoding = encoding; + this.raw = raw; + } + return CFFEncoding; +})(); + +var CFFFDSelect = (function CFFFDSelectClosure() { + function CFFFDSelect(fdSelect, raw) { + this.fdSelect = fdSelect; + this.raw = raw; + } + return CFFFDSelect; +})(); + +// Helper class to keep track of where an offset is within the data and helps +// filling in that offset once it's known. +var CFFOffsetTracker = (function CFFOffsetTrackerClosure() { + function CFFOffsetTracker() { + this.offsets = {}; + } + CFFOffsetTracker.prototype = { + isTracking: function CFFOffsetTracker_isTracking(key) { + return key in this.offsets; + }, + track: function CFFOffsetTracker_track(key, location) { + if (key in this.offsets) { + error('Already tracking location of ' + key); + } + this.offsets[key] = location; + }, + offset: function CFFOffsetTracker_offset(value) { + for (var key in this.offsets) { + this.offsets[key] += value; + } + }, + setEntryLocation: function CFFOffsetTracker_setEntryLocation(key, + values, + output) { + if (!(key in this.offsets)) { + error('Not tracking location of ' + key); + } + var data = output.data; + var dataOffset = this.offsets[key]; + var size = 5; + for (var i = 0, ii = values.length; i < ii; ++i) { + var offset0 = i * size + dataOffset; + var offset1 = offset0 + 1; + var offset2 = offset0 + 2; + var offset3 = offset0 + 3; + var offset4 = offset0 + 4; + // It's easy to screw up offsets so perform this sanity check. + if (data[offset0] !== 0x1d || data[offset1] !== 0 || + data[offset2] !== 0 || data[offset3] !== 0 || data[offset4] !== 0) { + error('writing to an offset that is not empty'); + } + var value = values[i]; + data[offset0] = 0x1d; + data[offset1] = (value >> 24) & 0xFF; + data[offset2] = (value >> 16) & 0xFF; + data[offset3] = (value >> 8) & 0xFF; + data[offset4] = value & 0xFF; + } + } + }; + return CFFOffsetTracker; +})(); + +// Takes a CFF and converts it to the binary representation. +var CFFCompiler = (function CFFCompilerClosure() { + function CFFCompiler(cff) { + this.cff = cff; + } + CFFCompiler.prototype = { + compile: function CFFCompiler_compile() { + var cff = this.cff; + var output = { + data: [], + length: 0, + add: function CFFCompiler_add(data) { + this.data = this.data.concat(data); + this.length = this.data.length; + } + }; + + // Compile the five entries that must be in order. + var header = this.compileHeader(cff.header); + output.add(header); + + var nameIndex = this.compileNameIndex(cff.names); + output.add(nameIndex); + + if (cff.isCIDFont) { + // The spec is unclear on how font matrices should relate to each other + // when there is one in the main top dict and the sub top dicts. + // Windows handles this differently than linux and osx so we have to + // normalize to work on all. + // Rules based off of some mailing list discussions: + // - If main font has a matrix and subfont doesn't, use the main matrix. + // - If no main font matrix and there is a subfont matrix, use the + // subfont matrix. + // - If both have matrices, concat together. + // - If neither have matrices, use default. + // To make this work on all platforms we move the top matrix into each + // sub top dict and concat if necessary. + if (cff.topDict.hasName('FontMatrix')) { + var base = cff.topDict.getByName('FontMatrix'); + cff.topDict.removeByName('FontMatrix'); + for (var i = 0, ii = cff.fdArray.length; i < ii; i++) { + var subDict = cff.fdArray[i]; + var matrix = base.slice(0); + if (subDict.hasName('FontMatrix')) { + matrix = Util.transform(matrix, subDict.getByName('FontMatrix')); + } + subDict.setByName('FontMatrix', matrix); + } + } + } + + var compiled = this.compileTopDicts([cff.topDict], + output.length, + cff.isCIDFont); + output.add(compiled.output); + var topDictTracker = compiled.trackers[0]; + + var stringIndex = this.compileStringIndex(cff.strings.strings); + output.add(stringIndex); + + var globalSubrIndex = this.compileIndex(cff.globalSubrIndex); + output.add(globalSubrIndex); + + // Now start on the other entries that have no specfic order. + if (cff.encoding && cff.topDict.hasName('Encoding')) { + if (cff.encoding.predefined) { + topDictTracker.setEntryLocation('Encoding', [cff.encoding.format], + output); + } else { + var encoding = this.compileEncoding(cff.encoding); + topDictTracker.setEntryLocation('Encoding', [output.length], output); + output.add(encoding); + } + } + + if (cff.charset && cff.topDict.hasName('charset')) { + if (cff.charset.predefined) { + topDictTracker.setEntryLocation('charset', [cff.charset.format], + output); + } else { + var charset = this.compileCharset(cff.charset); + topDictTracker.setEntryLocation('charset', [output.length], output); + output.add(charset); + } + } + + var charStrings = this.compileCharStrings(cff.charStrings); + topDictTracker.setEntryLocation('CharStrings', [output.length], output); + output.add(charStrings); + + if (cff.isCIDFont) { + // For some reason FDSelect must be in front of FDArray on windows. OSX + // and linux don't seem to care. + topDictTracker.setEntryLocation('FDSelect', [output.length], output); + var fdSelect = this.compileFDSelect(cff.fdSelect.raw); + output.add(fdSelect); + // It is unclear if the sub font dictionary can have CID related + // dictionary keys, but the sanitizer doesn't like them so remove them. + compiled = this.compileTopDicts(cff.fdArray, output.length, true); + topDictTracker.setEntryLocation('FDArray', [output.length], output); + output.add(compiled.output); + var fontDictTrackers = compiled.trackers; + + this.compilePrivateDicts(cff.fdArray, fontDictTrackers, output); + } + + this.compilePrivateDicts([cff.topDict], [topDictTracker], output); + + // If the font data ends with INDEX whose object data is zero-length, + // the sanitizer will bail out. Add a dummy byte to avoid that. + output.add([0]); + + return output.data; + }, + encodeNumber: function CFFCompiler_encodeNumber(value) { + if (parseFloat(value) === parseInt(value, 10) && !isNaN(value)) { // isInt + return this.encodeInteger(value); + } else { + return this.encodeFloat(value); + } + }, + encodeFloat: function CFFCompiler_encodeFloat(num) { + var value = num.toString(); + + // rounding inaccurate doubles + var m = /\.(\d*?)(?:9{5,20}|0{5,20})\d{0,2}(?:e(.+)|$)/.exec(value); + if (m) { + var epsilon = parseFloat('1e' + ((m[2] ? +m[2] : 0) + m[1].length)); + value = (Math.round(num * epsilon) / epsilon).toString(); + } + + var nibbles = ''; + var i, ii; + for (i = 0, ii = value.length; i < ii; ++i) { + var a = value[i]; + if (a === 'e') { + nibbles += value[++i] === '-' ? 'c' : 'b'; + } else if (a === '.') { + nibbles += 'a'; + } else if (a === '-') { + nibbles += 'e'; + } else { + nibbles += a; + } + } + nibbles += (nibbles.length & 1) ? 'f' : 'ff'; + var out = [30]; + for (i = 0, ii = nibbles.length; i < ii; i += 2) { + out.push(parseInt(nibbles.substr(i, 2), 16)); + } + return out; + }, + encodeInteger: function CFFCompiler_encodeInteger(value) { + var code; + if (value >= -107 && value <= 107) { + code = [value + 139]; + } else if (value >= 108 && value <= 1131) { + value = [value - 108]; + code = [(value >> 8) + 247, value & 0xFF]; + } else if (value >= -1131 && value <= -108) { + value = -value - 108; + code = [(value >> 8) + 251, value & 0xFF]; + } else if (value >= -32768 && value <= 32767) { + code = [0x1c, (value >> 8) & 0xFF, value & 0xFF]; + } else { + code = [0x1d, + (value >> 24) & 0xFF, + (value >> 16) & 0xFF, + (value >> 8) & 0xFF, + value & 0xFF]; + } + return code; + }, + compileHeader: function CFFCompiler_compileHeader(header) { + return [ + header.major, + header.minor, + header.hdrSize, + header.offSize + ]; + }, + compileNameIndex: function CFFCompiler_compileNameIndex(names) { + var nameIndex = new CFFIndex(); + for (var i = 0, ii = names.length; i < ii; ++i) { + nameIndex.add(stringToBytes(names[i])); + } + return this.compileIndex(nameIndex); + }, + compileTopDicts: function CFFCompiler_compileTopDicts(dicts, + length, + removeCidKeys) { + var fontDictTrackers = []; + var fdArrayIndex = new CFFIndex(); + for (var i = 0, ii = dicts.length; i < ii; ++i) { + var fontDict = dicts[i]; + if (removeCidKeys) { + fontDict.removeByName('CIDFontVersion'); + fontDict.removeByName('CIDFontRevision'); + fontDict.removeByName('CIDFontType'); + fontDict.removeByName('CIDCount'); + fontDict.removeByName('UIDBase'); + } + var fontDictTracker = new CFFOffsetTracker(); + var fontDictData = this.compileDict(fontDict, fontDictTracker); + fontDictTrackers.push(fontDictTracker); + fdArrayIndex.add(fontDictData); + fontDictTracker.offset(length); + } + fdArrayIndex = this.compileIndex(fdArrayIndex, fontDictTrackers); + return { + trackers: fontDictTrackers, + output: fdArrayIndex + }; + }, + compilePrivateDicts: function CFFCompiler_compilePrivateDicts(dicts, + trackers, + output) { + for (var i = 0, ii = dicts.length; i < ii; ++i) { + var fontDict = dicts[i]; + assert(fontDict.privateDict && fontDict.hasName('Private'), + 'There must be an private dictionary.'); + var privateDict = fontDict.privateDict; + var privateDictTracker = new CFFOffsetTracker(); + var privateDictData = this.compileDict(privateDict, privateDictTracker); + + var outputLength = output.length; + privateDictTracker.offset(outputLength); + if (!privateDictData.length) { + // The private dictionary was empty, set the output length to zero to + // ensure the offset length isn't out of bounds in the eyes of the + // sanitizer. + outputLength = 0; + } + + trackers[i].setEntryLocation('Private', + [privateDictData.length, outputLength], + output); + output.add(privateDictData); + + if (privateDict.subrsIndex && privateDict.hasName('Subrs')) { + var subrs = this.compileIndex(privateDict.subrsIndex); + privateDictTracker.setEntryLocation('Subrs', [privateDictData.length], + output); + output.add(subrs); + } + } + }, + compileDict: function CFFCompiler_compileDict(dict, offsetTracker) { + var out = []; + // The dictionary keys must be in a certain order. + var order = dict.order; + for (var i = 0; i < order.length; ++i) { + var key = order[i]; + if (!(key in dict.values)) { + continue; + } + var values = dict.values[key]; + var types = dict.types[key]; + if (!isArray(types)) { + types = [types]; + } + if (!isArray(values)) { + values = [values]; + } + + // Remove any empty dict values. + if (values.length === 0) { + continue; + } + + for (var j = 0, jj = types.length; j < jj; ++j) { + var type = types[j]; + var value = values[j]; + switch (type) { + case 'num': + case 'sid': + out = out.concat(this.encodeNumber(value)); + break; + case 'offset': + // For offsets we just insert a 32bit integer so we don't have to + // deal with figuring out the length of the offset when it gets + // replaced later on by the compiler. + var name = dict.keyToNameMap[key]; + // Some offsets have the offset and the length, so just record the + // position of the first one. + if (!offsetTracker.isTracking(name)) { + offsetTracker.track(name, out.length); + } + out = out.concat([0x1d, 0, 0, 0, 0]); + break; + case 'array': + case 'delta': + out = out.concat(this.encodeNumber(value)); + for (var k = 1, kk = values.length; k < kk; ++k) { + out = out.concat(this.encodeNumber(values[k])); + } + break; + default: + error('Unknown data type of ' + type); + break; + } + } + out = out.concat(dict.opcodes[key]); + } + return out; + }, + compileStringIndex: function CFFCompiler_compileStringIndex(strings) { + var stringIndex = new CFFIndex(); + for (var i = 0, ii = strings.length; i < ii; ++i) { + stringIndex.add(stringToBytes(strings[i])); + } + return this.compileIndex(stringIndex); + }, + compileGlobalSubrIndex: function CFFCompiler_compileGlobalSubrIndex() { + var globalSubrIndex = this.cff.globalSubrIndex; + this.out.writeByteArray(this.compileIndex(globalSubrIndex)); + }, + compileCharStrings: function CFFCompiler_compileCharStrings(charStrings) { + return this.compileIndex(charStrings); + }, + compileCharset: function CFFCompiler_compileCharset(charset) { + return this.compileTypedArray(charset.raw); + }, + compileEncoding: function CFFCompiler_compileEncoding(encoding) { + return this.compileTypedArray(encoding.raw); + }, + compileFDSelect: function CFFCompiler_compileFDSelect(fdSelect) { + return this.compileTypedArray(fdSelect); + }, + compileTypedArray: function CFFCompiler_compileTypedArray(data) { + var out = []; + for (var i = 0, ii = data.length; i < ii; ++i) { + out[i] = data[i]; + } + return out; + }, + compileIndex: function CFFCompiler_compileIndex(index, trackers) { + trackers = trackers || []; + var objects = index.objects; + // First 2 bytes contains the number of objects contained into this index + var count = objects.length; + + // If there is no object, just create an index. This technically + // should just be [0, 0] but OTS has an issue with that. + if (count === 0) { + return [0, 0, 0]; + } + + var data = [(count >> 8) & 0xFF, count & 0xff]; + + var lastOffset = 1, i; + for (i = 0; i < count; ++i) { + lastOffset += objects[i].length; + } + + var offsetSize; + if (lastOffset < 0x100) { + offsetSize = 1; + } else if (lastOffset < 0x10000) { + offsetSize = 2; + } else if (lastOffset < 0x1000000) { + offsetSize = 3; + } else { + offsetSize = 4; + } + + // Next byte contains the offset size use to reference object in the file + data.push(offsetSize); + + // Add another offset after this one because we need a new offset + var relativeOffset = 1; + for (i = 0; i < count + 1; i++) { + if (offsetSize === 1) { + data.push(relativeOffset & 0xFF); + } else if (offsetSize === 2) { + data.push((relativeOffset >> 8) & 0xFF, + relativeOffset & 0xFF); + } else if (offsetSize === 3) { + data.push((relativeOffset >> 16) & 0xFF, + (relativeOffset >> 8) & 0xFF, + relativeOffset & 0xFF); + } else { + data.push((relativeOffset >>> 24) & 0xFF, + (relativeOffset >> 16) & 0xFF, + (relativeOffset >> 8) & 0xFF, + relativeOffset & 0xFF); + } + + if (objects[i]) { + relativeOffset += objects[i].length; + } + } + + for (i = 0; i < count; i++) { + // Notify the tracker where the object will be offset in the data. + if (trackers[i]) { + trackers[i].offset(data.length); + } + for (var j = 0, jj = objects[i].length; j < jj; j++) { + data.push(objects[i][j]); + } + } + return data; + } + }; + return CFFCompiler; +})(); + +// Workaround for seac on Windows. +(function checkSeacSupport() { + if (/Windows/.test(navigator.userAgent)) { + SEAC_ANALYSIS_ENABLED = true; + } +})(); + +// Workaround for Private Use Area characters in Chrome on Windows +// http://code.google.com/p/chromium/issues/detail?id=122465 +// https://github.com/mozilla/pdf.js/issues/1689 +(function checkChromeWindows() { + if (/Windows.*Chrome/.test(navigator.userAgent)) { + SKIP_PRIVATE_USE_RANGE_F000_TO_F01F = true; + } +})(); + + +var FontRendererFactory = (function FontRendererFactoryClosure() { + function getLong(data, offset) { + return (data[offset] << 24) | (data[offset + 1] << 16) | + (data[offset + 2] << 8) | data[offset + 3]; + } + + function getUshort(data, offset) { + return (data[offset] << 8) | data[offset + 1]; + } + + function parseCmap(data, start, end) { + var offset = (getUshort(data, start + 2) === 1 ? + getLong(data, start + 8) : getLong(data, start + 16)); + var format = getUshort(data, start + offset); + var length, ranges, p, i; + if (format === 4) { + length = getUshort(data, start + offset + 2); + var segCount = getUshort(data, start + offset + 6) >> 1; + p = start + offset + 14; + ranges = []; + for (i = 0; i < segCount; i++, p += 2) { + ranges[i] = {end: getUshort(data, p)}; + } + p += 2; + for (i = 0; i < segCount; i++, p += 2) { + ranges[i].start = getUshort(data, p); + } + for (i = 0; i < segCount; i++, p += 2) { + ranges[i].idDelta = getUshort(data, p); + } + for (i = 0; i < segCount; i++, p += 2) { + var idOffset = getUshort(data, p); + if (idOffset === 0) { + continue; + } + ranges[i].ids = []; + for (var j = 0, jj = ranges[i].end - ranges[i].start + 1; j < jj; j++) { + ranges[i].ids[j] = getUshort(data, p + idOffset); + idOffset += 2; + } + } + return ranges; + } else if (format === 12) { + length = getLong(data, start + offset + 4); + var groups = getLong(data, start + offset + 12); + p = start + offset + 16; + ranges = []; + for (i = 0; i < groups; i++) { + ranges.push({ + start: getLong(data, p), + end: getLong(data, p + 4), + idDelta: getLong(data, p + 8) - getLong(data, p) + }); + p += 12; + } + return ranges; + } + error('not supported cmap: ' + format); + } + + function parseCff(data, start, end) { + var properties = {}; + var parser = new CFFParser(new Stream(data, start, end - start), + properties); + var cff = parser.parse(); + return { + glyphs: cff.charStrings.objects, + subrs: (cff.topDict.privateDict && cff.topDict.privateDict.subrsIndex && + cff.topDict.privateDict.subrsIndex.objects), + gsubrs: cff.globalSubrIndex && cff.globalSubrIndex.objects + }; + } + + function parseGlyfTable(glyf, loca, isGlyphLocationsLong) { + var itemSize, itemDecode; + if (isGlyphLocationsLong) { + itemSize = 4; + itemDecode = function fontItemDecodeLong(data, offset) { + return (data[offset] << 24) | (data[offset + 1] << 16) | + (data[offset + 2] << 8) | data[offset + 3]; + }; + } else { + itemSize = 2; + itemDecode = function fontItemDecode(data, offset) { + return (data[offset] << 9) | (data[offset + 1] << 1); + }; + } + var glyphs = []; + var startOffset = itemDecode(loca, 0); + for (var j = itemSize; j < loca.length; j += itemSize) { + var endOffset = itemDecode(loca, j); + glyphs.push(glyf.subarray(startOffset, endOffset)); + startOffset = endOffset; + } + return glyphs; + } + + function lookupCmap(ranges, unicode) { + var code = unicode.charCodeAt(0); + var l = 0, r = ranges.length - 1; + while (l < r) { + var c = (l + r + 1) >> 1; + if (code < ranges[c].start) { + r = c - 1; + } else { + l = c; + } + } + if (ranges[l].start <= code && code <= ranges[l].end) { + return (ranges[l].idDelta + (ranges[l].ids ? + ranges[l].ids[code - ranges[l].start] : code)) & 0xFFFF; + } + return 0; + } + + function compileGlyf(code, js, font) { + function moveTo(x, y) { + js.push('c.moveTo(' + x + ',' + y + ');'); + } + function lineTo(x, y) { + js.push('c.lineTo(' + x + ',' + y + ');'); + } + function quadraticCurveTo(xa, ya, x, y) { + js.push('c.quadraticCurveTo(' + xa + ',' + ya + ',' + + x + ',' + y + ');'); + } + + var i = 0; + var numberOfContours = ((code[i] << 24) | (code[i + 1] << 16)) >> 16; + var flags; + var x = 0, y = 0; + i += 10; + if (numberOfContours < 0) { + // composite glyph + do { + flags = (code[i] << 8) | code[i + 1]; + var glyphIndex = (code[i + 2] << 8) | code[i + 3]; + i += 4; + var arg1, arg2; + if ((flags & 0x01)) { + arg1 = ((code[i] << 24) | (code[i + 1] << 16)) >> 16; + arg2 = ((code[i + 2] << 24) | (code[i + 3] << 16)) >> 16; + i += 4; + } else { + arg1 = code[i++]; arg2 = code[i++]; + } + if ((flags & 0x02)) { + x = arg1; + y = arg2; + } else { + x = 0; y = 0; // TODO "they are points" ? + } + var scaleX = 1, scaleY = 1, scale01 = 0, scale10 = 0; + if ((flags & 0x08)) { + scaleX = + scaleY = ((code[i] << 24) | (code[i + 1] << 16)) / 1073741824; + i += 2; + } else if ((flags & 0x40)) { + scaleX = ((code[i] << 24) | (code[i + 1] << 16)) / 1073741824; + scaleY = ((code[i + 2] << 24) | (code[i + 3] << 16)) / 1073741824; + i += 4; + } else if ((flags & 0x80)) { + scaleX = ((code[i] << 24) | (code[i + 1] << 16)) / 1073741824; + scale01 = ((code[i + 2] << 24) | (code[i + 3] << 16)) / 1073741824; + scale10 = ((code[i + 4] << 24) | (code[i + 5] << 16)) / 1073741824; + scaleY = ((code[i + 6] << 24) | (code[i + 7] << 16)) / 1073741824; + i += 8; + } + var subglyph = font.glyphs[glyphIndex]; + if (subglyph) { + js.push('c.save();'); + js.push('c.transform(' + scaleX + ',' + scale01 + ',' + + scale10 + ',' + scaleY + ',' + x + ',' + y + ');'); + compileGlyf(subglyph, js, font); + js.push('c.restore();'); + } + } while ((flags & 0x20)); + } else { + // simple glyph + var endPtsOfContours = []; + var j, jj; + for (j = 0; j < numberOfContours; j++) { + endPtsOfContours.push((code[i] << 8) | code[i + 1]); + i += 2; + } + var instructionLength = (code[i] << 8) | code[i + 1]; + i += 2 + instructionLength; // skipping the instructions + var numberOfPoints = endPtsOfContours[endPtsOfContours.length - 1] + 1; + var points = []; + while (points.length < numberOfPoints) { + flags = code[i++]; + var repeat = 1; + if ((flags & 0x08)) { + repeat += code[i++]; + } + while (repeat-- > 0) { + points.push({flags: flags}); + } + } + for (j = 0; j < numberOfPoints; j++) { + switch (points[j].flags & 0x12) { + case 0x00: + x += ((code[i] << 24) | (code[i + 1] << 16)) >> 16; + i += 2; + break; + case 0x02: + x -= code[i++]; + break; + case 0x12: + x += code[i++]; + break; + } + points[j].x = x; + } + for (j = 0; j < numberOfPoints; j++) { + switch (points[j].flags & 0x24) { + case 0x00: + y += ((code[i] << 24) | (code[i + 1] << 16)) >> 16; + i += 2; + break; + case 0x04: + y -= code[i++]; + break; + case 0x24: + y += code[i++]; + break; + } + points[j].y = y; + } + + var startPoint = 0; + for (i = 0; i < numberOfContours; i++) { + var endPoint = endPtsOfContours[i]; + // contours might have implicit points, which is located in the middle + // between two neighboring off-curve points + var contour = points.slice(startPoint, endPoint + 1); + if ((contour[0].flags & 1)) { + contour.push(contour[0]); // using start point at the contour end + } else if ((contour[contour.length - 1].flags & 1)) { + // first is off-curve point, trying to use one from the end + contour.unshift(contour[contour.length - 1]); + } else { + // start and end are off-curve points, creating implicit one + var p = { + flags: 1, + x: (contour[0].x + contour[contour.length - 1].x) / 2, + y: (contour[0].y + contour[contour.length - 1].y) / 2 + }; + contour.unshift(p); + contour.push(p); + } + moveTo(contour[0].x, contour[0].y); + for (j = 1, jj = contour.length; j < jj; j++) { + if ((contour[j].flags & 1)) { + lineTo(contour[j].x, contour[j].y); + } else if ((contour[j + 1].flags & 1)){ + quadraticCurveTo(contour[j].x, contour[j].y, + contour[j + 1].x, contour[j + 1].y); + j++; + } else { + quadraticCurveTo(contour[j].x, contour[j].y, + (contour[j].x + contour[j + 1].x) / 2, + (contour[j].y + contour[j + 1].y) / 2); + } + } + startPoint = endPoint + 1; + } + } + } + + function compileCharString(code, js, font) { + var stack = []; + var x = 0, y = 0; + var stems = 0; + + function moveTo(x, y) { + js.push('c.moveTo(' + x + ',' + y + ');'); + } + function lineTo(x, y) { + js.push('c.lineTo(' + x + ',' + y + ');'); + } + function bezierCurveTo(x1, y1, x2, y2, x, y) { + js.push('c.bezierCurveTo(' + x1 + ',' + y1 + ',' + x2 + ',' + y2 + ',' + + x + ',' + y + ');'); + } + + function parse(code) { + var i = 0; + while (i < code.length) { + var stackClean = false; + var v = code[i++]; + var xa, xb, ya, yb, y1, y2, y3, n, subrCode; + switch (v) { + case 1: // hstem + stems += stack.length >> 1; + stackClean = true; + break; + case 3: // vstem + stems += stack.length >> 1; + stackClean = true; + break; + case 4: // vmoveto + y += stack.pop(); + moveTo(x, y); + stackClean = true; + break; + case 5: // rlineto + while (stack.length > 0) { + x += stack.shift(); + y += stack.shift(); + lineTo(x, y); + } + break; + case 6: // hlineto + while (stack.length > 0) { + x += stack.shift(); + lineTo(x, y); + if (stack.length === 0) { + break; + } + y += stack.shift(); + lineTo(x, y); + } + break; + case 7: // vlineto + while (stack.length > 0) { + y += stack.shift(); + lineTo(x, y); + if (stack.length === 0) { + break; + } + x += stack.shift(); + lineTo(x, y); + } + break; + case 8: // rrcurveto + while (stack.length > 0) { + xa = x + stack.shift(); ya = y + stack.shift(); + xb = xa + stack.shift(); yb = ya + stack.shift(); + x = xb + stack.shift(); y = yb + stack.shift(); + bezierCurveTo(xa, ya, xb, yb, x, y); + } + break; + case 10: // callsubr + n = stack.pop() + font.subrsBias; + subrCode = font.subrs[n]; + if (subrCode) { + parse(subrCode); + } + break; + case 11: // return + return; + case 12: + v = code[i++]; + switch (v) { + case 34: // flex + xa = x + stack.shift(); + xb = xa + stack.shift(); y1 = y + stack.shift(); + x = xb + stack.shift(); + bezierCurveTo(xa, y, xb, y1, x, y1); + xa = x + stack.shift(); + xb = xa + stack.shift(); + x = xb + stack.shift(); + bezierCurveTo(xa, y1, xb, y, x, y); + break; + case 35: // flex + xa = x + stack.shift(); ya = y + stack.shift(); + xb = xa + stack.shift(); yb = ya + stack.shift(); + x = xb + stack.shift(); y = yb + stack.shift(); + bezierCurveTo(xa, ya, xb, yb, x, y); + xa = x + stack.shift(); ya = y + stack.shift(); + xb = xa + stack.shift(); yb = ya + stack.shift(); + x = xb + stack.shift(); y = yb + stack.shift(); + bezierCurveTo(xa, ya, xb, yb, x, y); + stack.pop(); // fd + break; + case 36: // hflex1 + xa = x + stack.shift(); y1 = y + stack.shift(); + xb = xa + stack.shift(); y2 = y1 + stack.shift(); + x = xb + stack.shift(); + bezierCurveTo(xa, y1, xb, y2, x, y2); + xa = x + stack.shift(); + xb = xa + stack.shift(); y3 = y2 + stack.shift(); + x = xb + stack.shift(); + bezierCurveTo(xa, y2, xb, y3, x, y); + break; + case 37: // flex1 + var x0 = x, y0 = y; + xa = x + stack.shift(); ya = y + stack.shift(); + xb = xa + stack.shift(); yb = ya + stack.shift(); + x = xb + stack.shift(); y = yb + stack.shift(); + bezierCurveTo(xa, ya, xb, yb, x, y); + xa = x + stack.shift(); ya = y + stack.shift(); + xb = xa + stack.shift(); yb = ya + stack.shift(); + x = xb; y = yb; + if (Math.abs(x - x0) > Math.abs(y - y0)) { + x += stack.shift(); + } else { + y += stack.shift(); + } + bezierCurveTo(xa, ya, xb, yb, x, y); + break; + default: + error('unknown operator: 12 ' + v); + } + break; + case 14: // endchar + if (stack.length >= 4) { + var achar = stack.pop(); + var bchar = stack.pop(); + y = stack.pop(); + x = stack.pop(); + js.push('c.save();'); + js.push('c.translate('+ x + ',' + y + ');'); + var gid = lookupCmap(font.cmap, String.fromCharCode( + font.glyphNameMap[Encodings.StandardEncoding[achar]])); + compileCharString(font.glyphs[gid], js, font); + js.push('c.restore();'); + + gid = lookupCmap(font.cmap, String.fromCharCode( + font.glyphNameMap[Encodings.StandardEncoding[bchar]])); + compileCharString(font.glyphs[gid], js, font); + } + return; + case 18: // hstemhm + stems += stack.length >> 1; + stackClean = true; + break; + case 19: // hintmask + stems += stack.length >> 1; + i += (stems + 7) >> 3; + stackClean = true; + break; + case 20: // cntrmask + stems += stack.length >> 1; + i += (stems + 7) >> 3; + stackClean = true; + break; + case 21: // rmoveto + y += stack.pop(); + x += stack.pop(); + moveTo(x, y); + stackClean = true; + break; + case 22: // hmoveto + x += stack.pop(); + moveTo(x, y); + stackClean = true; + break; + case 23: // vstemhm + stems += stack.length >> 1; + stackClean = true; + break; + case 24: // rcurveline + while (stack.length > 2) { + xa = x + stack.shift(); ya = y + stack.shift(); + xb = xa + stack.shift(); yb = ya + stack.shift(); + x = xb + stack.shift(); y = yb + stack.shift(); + bezierCurveTo(xa, ya, xb, yb, x, y); + } + x += stack.shift(); + y += stack.shift(); + lineTo(x, y); + break; + case 25: // rlinecurve + while (stack.length > 6) { + x += stack.shift(); + y += stack.shift(); + lineTo(x, y); + } + xa = x + stack.shift(); ya = y + stack.shift(); + xb = xa + stack.shift(); yb = ya + stack.shift(); + x = xb + stack.shift(); y = yb + stack.shift(); + bezierCurveTo(xa, ya, xb, yb, x, y); + break; + case 26: // vvcurveto + if (stack.length % 2) { + x += stack.shift(); + } + while (stack.length > 0) { + xa = x; ya = y + stack.shift(); + xb = xa + stack.shift(); yb = ya + stack.shift(); + x = xb; y = yb + stack.shift(); + bezierCurveTo(xa, ya, xb, yb, x, y); + } + break; + case 27: // hhcurveto + if (stack.length % 2) { + y += stack.shift(); + } + while (stack.length > 0) { + xa = x + stack.shift(); ya = y; + xb = xa + stack.shift(); yb = ya + stack.shift(); + x = xb + stack.shift(); y = yb; + bezierCurveTo(xa, ya, xb, yb, x, y); + } + break; + case 28: + stack.push(((code[i] << 24) | (code[i + 1] << 16)) >> 16); + i += 2; + break; + case 29: // callgsubr + n = stack.pop() + font.gsubrsBias; + subrCode = font.gsubrs[n]; + if (subrCode) { + parse(subrCode); + } + break; + case 30: // vhcurveto + while (stack.length > 0) { + xa = x; ya = y + stack.shift(); + xb = xa + stack.shift(); yb = ya + stack.shift(); + x = xb + stack.shift(); + y = yb + (stack.length === 1 ? stack.shift() : 0); + bezierCurveTo(xa, ya, xb, yb, x, y); + if (stack.length === 0) { + break; + } + + xa = x + stack.shift(); ya = y; + xb = xa + stack.shift(); yb = ya + stack.shift(); + y = yb + stack.shift(); + x = xb + (stack.length === 1 ? stack.shift() : 0); + bezierCurveTo(xa, ya, xb, yb, x, y); + } + break; + case 31: // hvcurveto + while (stack.length > 0) { + xa = x + stack.shift(); ya = y; + xb = xa + stack.shift(); yb = ya + stack.shift(); + y = yb + stack.shift(); + x = xb + (stack.length === 1 ? stack.shift() : 0); + bezierCurveTo(xa, ya, xb, yb, x, y); + if (stack.length === 0) { + break; + } + + xa = x; ya = y + stack.shift(); + xb = xa + stack.shift(); yb = ya + stack.shift(); + x = xb + stack.shift(); + y = yb + (stack.length === 1 ? stack.shift() : 0); + bezierCurveTo(xa, ya, xb, yb, x, y); + } + break; + default: + if (v < 32) { + error('unknown operator: ' + v); + } + if (v < 247) { + stack.push(v - 139); + } else if (v < 251) { + stack.push((v - 247) * 256 + code[i++] + 108); + } else if (v < 255) { + stack.push(-(v - 251) * 256 - code[i++] - 108); + } else { + stack.push(((code[i] << 24) | (code[i + 1] << 16) | + (code[i + 2] << 8) | code[i + 3]) / 65536); + i += 4; + } + break; + } + if (stackClean) { + stack.length = 0; + } + } + } + parse(code); + } + + var noop = ''; + + function CompiledFont(fontMatrix) { + this.compiledGlyphs = {}; + this.fontMatrix = fontMatrix; + } + CompiledFont.prototype = { + getPathJs: function (unicode) { + var gid = lookupCmap(this.cmap, unicode); + var fn = this.compiledGlyphs[gid]; + if (!fn) { + this.compiledGlyphs[gid] = fn = this.compileGlyph(this.glyphs[gid]); + } + return fn; + }, + + compileGlyph: function (code) { + if (!code || code.length === 0 || code[0] === 14) { + return noop; + } + + var js = []; + js.push('c.save();'); + js.push('c.transform(' + this.fontMatrix.join(',') + ');'); + js.push('c.scale(size, -size);'); + + this.compileGlyphImpl(code, js); + + js.push('c.restore();'); + + return js.join('\n'); + }, + + compileGlyphImpl: function () { + error('Children classes should implement this.'); + }, + + hasBuiltPath: function (unicode) { + var gid = lookupCmap(this.cmap, unicode); + return gid in this.compiledGlyphs; + } + }; + + function TrueTypeCompiled(glyphs, cmap, fontMatrix) { + fontMatrix = fontMatrix || [0.000488, 0, 0, 0.000488, 0, 0]; + CompiledFont.call(this, fontMatrix); + + this.glyphs = glyphs; + this.cmap = cmap; + + this.compiledGlyphs = []; + } + + Util.inherit(TrueTypeCompiled, CompiledFont, { + compileGlyphImpl: function (code, js) { + compileGlyf(code, js, this); + } + }); + + function Type2Compiled(cffInfo, cmap, fontMatrix, glyphNameMap) { + fontMatrix = fontMatrix || [0.001, 0, 0, 0.001, 0, 0]; + CompiledFont.call(this, fontMatrix); + this.glyphs = cffInfo.glyphs; + this.gsubrs = cffInfo.gsubrs || []; + this.subrs = cffInfo.subrs || []; + this.cmap = cmap; + this.glyphNameMap = glyphNameMap || GlyphsUnicode; + + this.compiledGlyphs = []; + this.gsubrsBias = (this.gsubrs.length < 1240 ? + 107 : (this.gsubrs.length < 33900 ? 1131 : 32768)); + this.subrsBias = (this.subrs.length < 1240 ? + 107 : (this.subrs.length < 33900 ? 1131 : 32768)); + } + + Util.inherit(Type2Compiled, CompiledFont, { + compileGlyphImpl: function (code, js) { + compileCharString(code, js, this); + } + }); + + + return { + create: function FontRendererFactory_create(font) { + var data = new Uint8Array(font.data); + var cmap, glyf, loca, cff, indexToLocFormat, unitsPerEm; + var numTables = getUshort(data, 4); + for (var i = 0, p = 12; i < numTables; i++, p += 16) { + var tag = bytesToString(data.subarray(p, p + 4)); + var offset = getLong(data, p + 8); + var length = getLong(data, p + 12); + switch (tag) { + case 'cmap': + cmap = parseCmap(data, offset, offset + length); + break; + case 'glyf': + glyf = data.subarray(offset, offset + length); + break; + case 'loca': + loca = data.subarray(offset, offset + length); + break; + case 'head': + unitsPerEm = getUshort(data, offset + 18); + indexToLocFormat = getUshort(data, offset + 50); + break; + case 'CFF ': + cff = parseCff(data, offset, offset + length); + break; + } + } + + if (glyf) { + var fontMatrix = (!unitsPerEm ? font.fontMatrix : + [1 / unitsPerEm, 0, 0, 1 / unitsPerEm, 0, 0]); + return new TrueTypeCompiled( + parseGlyfTable(glyf, loca, indexToLocFormat), cmap, fontMatrix); + } else { + return new Type2Compiled(cff, cmap, font.fontMatrix, font.glyphNameMap); + } + } + }; +})(); + + +var GlyphsUnicode = { + A: 0x0041, + AE: 0x00C6, + AEacute: 0x01FC, + AEmacron: 0x01E2, + AEsmall: 0xF7E6, + Aacute: 0x00C1, + Aacutesmall: 0xF7E1, + Abreve: 0x0102, + Abreveacute: 0x1EAE, + Abrevecyrillic: 0x04D0, + Abrevedotbelow: 0x1EB6, + Abrevegrave: 0x1EB0, + Abrevehookabove: 0x1EB2, + Abrevetilde: 0x1EB4, + Acaron: 0x01CD, + Acircle: 0x24B6, + Acircumflex: 0x00C2, + Acircumflexacute: 0x1EA4, + Acircumflexdotbelow: 0x1EAC, + Acircumflexgrave: 0x1EA6, + Acircumflexhookabove: 0x1EA8, + Acircumflexsmall: 0xF7E2, + Acircumflextilde: 0x1EAA, + Acute: 0xF6C9, + Acutesmall: 0xF7B4, + Acyrillic: 0x0410, + Adblgrave: 0x0200, + Adieresis: 0x00C4, + Adieresiscyrillic: 0x04D2, + Adieresismacron: 0x01DE, + Adieresissmall: 0xF7E4, + Adotbelow: 0x1EA0, + Adotmacron: 0x01E0, + Agrave: 0x00C0, + Agravesmall: 0xF7E0, + Ahookabove: 0x1EA2, + Aiecyrillic: 0x04D4, + Ainvertedbreve: 0x0202, + Alpha: 0x0391, + Alphatonos: 0x0386, + Amacron: 0x0100, + Amonospace: 0xFF21, + Aogonek: 0x0104, + Aring: 0x00C5, + Aringacute: 0x01FA, + Aringbelow: 0x1E00, + Aringsmall: 0xF7E5, + Asmall: 0xF761, + Atilde: 0x00C3, + Atildesmall: 0xF7E3, + Aybarmenian: 0x0531, + B: 0x0042, + Bcircle: 0x24B7, + Bdotaccent: 0x1E02, + Bdotbelow: 0x1E04, + Becyrillic: 0x0411, + Benarmenian: 0x0532, + Beta: 0x0392, + Bhook: 0x0181, + Blinebelow: 0x1E06, + Bmonospace: 0xFF22, + Brevesmall: 0xF6F4, + Bsmall: 0xF762, + Btopbar: 0x0182, + C: 0x0043, + Caarmenian: 0x053E, + Cacute: 0x0106, + Caron: 0xF6CA, + Caronsmall: 0xF6F5, + Ccaron: 0x010C, + Ccedilla: 0x00C7, + Ccedillaacute: 0x1E08, + Ccedillasmall: 0xF7E7, + Ccircle: 0x24B8, + Ccircumflex: 0x0108, + Cdot: 0x010A, + Cdotaccent: 0x010A, + Cedillasmall: 0xF7B8, + Chaarmenian: 0x0549, + Cheabkhasiancyrillic: 0x04BC, + Checyrillic: 0x0427, + Chedescenderabkhasiancyrillic: 0x04BE, + Chedescendercyrillic: 0x04B6, + Chedieresiscyrillic: 0x04F4, + Cheharmenian: 0x0543, + Chekhakassiancyrillic: 0x04CB, + Cheverticalstrokecyrillic: 0x04B8, + Chi: 0x03A7, + Chook: 0x0187, + Circumflexsmall: 0xF6F6, + Cmonospace: 0xFF23, + Coarmenian: 0x0551, + Csmall: 0xF763, + D: 0x0044, + DZ: 0x01F1, + DZcaron: 0x01C4, + Daarmenian: 0x0534, + Dafrican: 0x0189, + Dcaron: 0x010E, + Dcedilla: 0x1E10, + Dcircle: 0x24B9, + Dcircumflexbelow: 0x1E12, + Dcroat: 0x0110, + Ddotaccent: 0x1E0A, + Ddotbelow: 0x1E0C, + Decyrillic: 0x0414, + Deicoptic: 0x03EE, + Delta: 0x2206, + Deltagreek: 0x0394, + Dhook: 0x018A, + Dieresis: 0xF6CB, + DieresisAcute: 0xF6CC, + DieresisGrave: 0xF6CD, + Dieresissmall: 0xF7A8, + Digammagreek: 0x03DC, + Djecyrillic: 0x0402, + Dlinebelow: 0x1E0E, + Dmonospace: 0xFF24, + Dotaccentsmall: 0xF6F7, + Dslash: 0x0110, + Dsmall: 0xF764, + Dtopbar: 0x018B, + Dz: 0x01F2, + Dzcaron: 0x01C5, + Dzeabkhasiancyrillic: 0x04E0, + Dzecyrillic: 0x0405, + Dzhecyrillic: 0x040F, + E: 0x0045, + Eacute: 0x00C9, + Eacutesmall: 0xF7E9, + Ebreve: 0x0114, + Ecaron: 0x011A, + Ecedillabreve: 0x1E1C, + Echarmenian: 0x0535, + Ecircle: 0x24BA, + Ecircumflex: 0x00CA, + Ecircumflexacute: 0x1EBE, + Ecircumflexbelow: 0x1E18, + Ecircumflexdotbelow: 0x1EC6, + Ecircumflexgrave: 0x1EC0, + Ecircumflexhookabove: 0x1EC2, + Ecircumflexsmall: 0xF7EA, + Ecircumflextilde: 0x1EC4, + Ecyrillic: 0x0404, + Edblgrave: 0x0204, + Edieresis: 0x00CB, + Edieresissmall: 0xF7EB, + Edot: 0x0116, + Edotaccent: 0x0116, + Edotbelow: 0x1EB8, + Efcyrillic: 0x0424, + Egrave: 0x00C8, + Egravesmall: 0xF7E8, + Eharmenian: 0x0537, + Ehookabove: 0x1EBA, + Eightroman: 0x2167, + Einvertedbreve: 0x0206, + Eiotifiedcyrillic: 0x0464, + Elcyrillic: 0x041B, + Elevenroman: 0x216A, + Emacron: 0x0112, + Emacronacute: 0x1E16, + Emacrongrave: 0x1E14, + Emcyrillic: 0x041C, + Emonospace: 0xFF25, + Encyrillic: 0x041D, + Endescendercyrillic: 0x04A2, + Eng: 0x014A, + Enghecyrillic: 0x04A4, + Enhookcyrillic: 0x04C7, + Eogonek: 0x0118, + Eopen: 0x0190, + Epsilon: 0x0395, + Epsilontonos: 0x0388, + Ercyrillic: 0x0420, + Ereversed: 0x018E, + Ereversedcyrillic: 0x042D, + Escyrillic: 0x0421, + Esdescendercyrillic: 0x04AA, + Esh: 0x01A9, + Esmall: 0xF765, + Eta: 0x0397, + Etarmenian: 0x0538, + Etatonos: 0x0389, + Eth: 0x00D0, + Ethsmall: 0xF7F0, + Etilde: 0x1EBC, + Etildebelow: 0x1E1A, + Euro: 0x20AC, + Ezh: 0x01B7, + Ezhcaron: 0x01EE, + Ezhreversed: 0x01B8, + F: 0x0046, + Fcircle: 0x24BB, + Fdotaccent: 0x1E1E, + Feharmenian: 0x0556, + Feicoptic: 0x03E4, + Fhook: 0x0191, + Fitacyrillic: 0x0472, + Fiveroman: 0x2164, + Fmonospace: 0xFF26, + Fourroman: 0x2163, + Fsmall: 0xF766, + G: 0x0047, + GBsquare: 0x3387, + Gacute: 0x01F4, + Gamma: 0x0393, + Gammaafrican: 0x0194, + Gangiacoptic: 0x03EA, + Gbreve: 0x011E, + Gcaron: 0x01E6, + Gcedilla: 0x0122, + Gcircle: 0x24BC, + Gcircumflex: 0x011C, + Gcommaaccent: 0x0122, + Gdot: 0x0120, + Gdotaccent: 0x0120, + Gecyrillic: 0x0413, + Ghadarmenian: 0x0542, + Ghemiddlehookcyrillic: 0x0494, + Ghestrokecyrillic: 0x0492, + Gheupturncyrillic: 0x0490, + Ghook: 0x0193, + Gimarmenian: 0x0533, + Gjecyrillic: 0x0403, + Gmacron: 0x1E20, + Gmonospace: 0xFF27, + Grave: 0xF6CE, + Gravesmall: 0xF760, + Gsmall: 0xF767, + Gsmallhook: 0x029B, + Gstroke: 0x01E4, + H: 0x0048, + H18533: 0x25CF, + H18543: 0x25AA, + H18551: 0x25AB, + H22073: 0x25A1, + HPsquare: 0x33CB, + Haabkhasiancyrillic: 0x04A8, + Hadescendercyrillic: 0x04B2, + Hardsigncyrillic: 0x042A, + Hbar: 0x0126, + Hbrevebelow: 0x1E2A, + Hcedilla: 0x1E28, + Hcircle: 0x24BD, + Hcircumflex: 0x0124, + Hdieresis: 0x1E26, + Hdotaccent: 0x1E22, + Hdotbelow: 0x1E24, + Hmonospace: 0xFF28, + Hoarmenian: 0x0540, + Horicoptic: 0x03E8, + Hsmall: 0xF768, + Hungarumlaut: 0xF6CF, + Hungarumlautsmall: 0xF6F8, + Hzsquare: 0x3390, + I: 0x0049, + IAcyrillic: 0x042F, + IJ: 0x0132, + IUcyrillic: 0x042E, + Iacute: 0x00CD, + Iacutesmall: 0xF7ED, + Ibreve: 0x012C, + Icaron: 0x01CF, + Icircle: 0x24BE, + Icircumflex: 0x00CE, + Icircumflexsmall: 0xF7EE, + Icyrillic: 0x0406, + Idblgrave: 0x0208, + Idieresis: 0x00CF, + Idieresisacute: 0x1E2E, + Idieresiscyrillic: 0x04E4, + Idieresissmall: 0xF7EF, + Idot: 0x0130, + Idotaccent: 0x0130, + Idotbelow: 0x1ECA, + Iebrevecyrillic: 0x04D6, + Iecyrillic: 0x0415, + Ifraktur: 0x2111, + Igrave: 0x00CC, + Igravesmall: 0xF7EC, + Ihookabove: 0x1EC8, + Iicyrillic: 0x0418, + Iinvertedbreve: 0x020A, + Iishortcyrillic: 0x0419, + Imacron: 0x012A, + Imacroncyrillic: 0x04E2, + Imonospace: 0xFF29, + Iniarmenian: 0x053B, + Iocyrillic: 0x0401, + Iogonek: 0x012E, + Iota: 0x0399, + Iotaafrican: 0x0196, + Iotadieresis: 0x03AA, + Iotatonos: 0x038A, + Ismall: 0xF769, + Istroke: 0x0197, + Itilde: 0x0128, + Itildebelow: 0x1E2C, + Izhitsacyrillic: 0x0474, + Izhitsadblgravecyrillic: 0x0476, + J: 0x004A, + Jaarmenian: 0x0541, + Jcircle: 0x24BF, + Jcircumflex: 0x0134, + Jecyrillic: 0x0408, + Jheharmenian: 0x054B, + Jmonospace: 0xFF2A, + Jsmall: 0xF76A, + K: 0x004B, + KBsquare: 0x3385, + KKsquare: 0x33CD, + Kabashkircyrillic: 0x04A0, + Kacute: 0x1E30, + Kacyrillic: 0x041A, + Kadescendercyrillic: 0x049A, + Kahookcyrillic: 0x04C3, + Kappa: 0x039A, + Kastrokecyrillic: 0x049E, + Kaverticalstrokecyrillic: 0x049C, + Kcaron: 0x01E8, + Kcedilla: 0x0136, + Kcircle: 0x24C0, + Kcommaaccent: 0x0136, + Kdotbelow: 0x1E32, + Keharmenian: 0x0554, + Kenarmenian: 0x053F, + Khacyrillic: 0x0425, + Kheicoptic: 0x03E6, + Khook: 0x0198, + Kjecyrillic: 0x040C, + Klinebelow: 0x1E34, + Kmonospace: 0xFF2B, + Koppacyrillic: 0x0480, + Koppagreek: 0x03DE, + Ksicyrillic: 0x046E, + Ksmall: 0xF76B, + L: 0x004C, + LJ: 0x01C7, + LL: 0xF6BF, + Lacute: 0x0139, + Lambda: 0x039B, + Lcaron: 0x013D, + Lcedilla: 0x013B, + Lcircle: 0x24C1, + Lcircumflexbelow: 0x1E3C, + Lcommaaccent: 0x013B, + Ldot: 0x013F, + Ldotaccent: 0x013F, + Ldotbelow: 0x1E36, + Ldotbelowmacron: 0x1E38, + Liwnarmenian: 0x053C, + Lj: 0x01C8, + Ljecyrillic: 0x0409, + Llinebelow: 0x1E3A, + Lmonospace: 0xFF2C, + Lslash: 0x0141, + Lslashsmall: 0xF6F9, + Lsmall: 0xF76C, + M: 0x004D, + MBsquare: 0x3386, + Macron: 0xF6D0, + Macronsmall: 0xF7AF, + Macute: 0x1E3E, + Mcircle: 0x24C2, + Mdotaccent: 0x1E40, + Mdotbelow: 0x1E42, + Menarmenian: 0x0544, + Mmonospace: 0xFF2D, + Msmall: 0xF76D, + Mturned: 0x019C, + Mu: 0x039C, + N: 0x004E, + NJ: 0x01CA, + Nacute: 0x0143, + Ncaron: 0x0147, + Ncedilla: 0x0145, + Ncircle: 0x24C3, + Ncircumflexbelow: 0x1E4A, + Ncommaaccent: 0x0145, + Ndotaccent: 0x1E44, + Ndotbelow: 0x1E46, + Nhookleft: 0x019D, + Nineroman: 0x2168, + Nj: 0x01CB, + Njecyrillic: 0x040A, + Nlinebelow: 0x1E48, + Nmonospace: 0xFF2E, + Nowarmenian: 0x0546, + Nsmall: 0xF76E, + Ntilde: 0x00D1, + Ntildesmall: 0xF7F1, + Nu: 0x039D, + O: 0x004F, + OE: 0x0152, + OEsmall: 0xF6FA, + Oacute: 0x00D3, + Oacutesmall: 0xF7F3, + Obarredcyrillic: 0x04E8, + Obarreddieresiscyrillic: 0x04EA, + Obreve: 0x014E, + Ocaron: 0x01D1, + Ocenteredtilde: 0x019F, + Ocircle: 0x24C4, + Ocircumflex: 0x00D4, + Ocircumflexacute: 0x1ED0, + Ocircumflexdotbelow: 0x1ED8, + Ocircumflexgrave: 0x1ED2, + Ocircumflexhookabove: 0x1ED4, + Ocircumflexsmall: 0xF7F4, + Ocircumflextilde: 0x1ED6, + Ocyrillic: 0x041E, + Odblacute: 0x0150, + Odblgrave: 0x020C, + Odieresis: 0x00D6, + Odieresiscyrillic: 0x04E6, + Odieresissmall: 0xF7F6, + Odotbelow: 0x1ECC, + Ogoneksmall: 0xF6FB, + Ograve: 0x00D2, + Ogravesmall: 0xF7F2, + Oharmenian: 0x0555, + Ohm: 0x2126, + Ohookabove: 0x1ECE, + Ohorn: 0x01A0, + Ohornacute: 0x1EDA, + Ohorndotbelow: 0x1EE2, + Ohorngrave: 0x1EDC, + Ohornhookabove: 0x1EDE, + Ohorntilde: 0x1EE0, + Ohungarumlaut: 0x0150, + Oi: 0x01A2, + Oinvertedbreve: 0x020E, + Omacron: 0x014C, + Omacronacute: 0x1E52, + Omacrongrave: 0x1E50, + Omega: 0x2126, + Omegacyrillic: 0x0460, + Omegagreek: 0x03A9, + Omegaroundcyrillic: 0x047A, + Omegatitlocyrillic: 0x047C, + Omegatonos: 0x038F, + Omicron: 0x039F, + Omicrontonos: 0x038C, + Omonospace: 0xFF2F, + Oneroman: 0x2160, + Oogonek: 0x01EA, + Oogonekmacron: 0x01EC, + Oopen: 0x0186, + Oslash: 0x00D8, + Oslashacute: 0x01FE, + Oslashsmall: 0xF7F8, + Osmall: 0xF76F, + Ostrokeacute: 0x01FE, + Otcyrillic: 0x047E, + Otilde: 0x00D5, + Otildeacute: 0x1E4C, + Otildedieresis: 0x1E4E, + Otildesmall: 0xF7F5, + P: 0x0050, + Pacute: 0x1E54, + Pcircle: 0x24C5, + Pdotaccent: 0x1E56, + Pecyrillic: 0x041F, + Peharmenian: 0x054A, + Pemiddlehookcyrillic: 0x04A6, + Phi: 0x03A6, + Phook: 0x01A4, + Pi: 0x03A0, + Piwrarmenian: 0x0553, + Pmonospace: 0xFF30, + Psi: 0x03A8, + Psicyrillic: 0x0470, + Psmall: 0xF770, + Q: 0x0051, + Qcircle: 0x24C6, + Qmonospace: 0xFF31, + Qsmall: 0xF771, + R: 0x0052, + Raarmenian: 0x054C, + Racute: 0x0154, + Rcaron: 0x0158, + Rcedilla: 0x0156, + Rcircle: 0x24C7, + Rcommaaccent: 0x0156, + Rdblgrave: 0x0210, + Rdotaccent: 0x1E58, + Rdotbelow: 0x1E5A, + Rdotbelowmacron: 0x1E5C, + Reharmenian: 0x0550, + Rfraktur: 0x211C, + Rho: 0x03A1, + Ringsmall: 0xF6FC, + Rinvertedbreve: 0x0212, + Rlinebelow: 0x1E5E, + Rmonospace: 0xFF32, + Rsmall: 0xF772, + Rsmallinverted: 0x0281, + Rsmallinvertedsuperior: 0x02B6, + S: 0x0053, + SF010000: 0x250C, + SF020000: 0x2514, + SF030000: 0x2510, + SF040000: 0x2518, + SF050000: 0x253C, + SF060000: 0x252C, + SF070000: 0x2534, + SF080000: 0x251C, + SF090000: 0x2524, + SF100000: 0x2500, + SF110000: 0x2502, + SF190000: 0x2561, + SF200000: 0x2562, + SF210000: 0x2556, + SF220000: 0x2555, + SF230000: 0x2563, + SF240000: 0x2551, + SF250000: 0x2557, + SF260000: 0x255D, + SF270000: 0x255C, + SF280000: 0x255B, + SF360000: 0x255E, + SF370000: 0x255F, + SF380000: 0x255A, + SF390000: 0x2554, + SF400000: 0x2569, + SF410000: 0x2566, + SF420000: 0x2560, + SF430000: 0x2550, + SF440000: 0x256C, + SF450000: 0x2567, + SF460000: 0x2568, + SF470000: 0x2564, + SF480000: 0x2565, + SF490000: 0x2559, + SF500000: 0x2558, + SF510000: 0x2552, + SF520000: 0x2553, + SF530000: 0x256B, + SF540000: 0x256A, + Sacute: 0x015A, + Sacutedotaccent: 0x1E64, + Sampigreek: 0x03E0, + Scaron: 0x0160, + Scarondotaccent: 0x1E66, + Scaronsmall: 0xF6FD, + Scedilla: 0x015E, + Schwa: 0x018F, + Schwacyrillic: 0x04D8, + Schwadieresiscyrillic: 0x04DA, + Scircle: 0x24C8, + Scircumflex: 0x015C, + Scommaaccent: 0x0218, + Sdotaccent: 0x1E60, + Sdotbelow: 0x1E62, + Sdotbelowdotaccent: 0x1E68, + Seharmenian: 0x054D, + Sevenroman: 0x2166, + Shaarmenian: 0x0547, + Shacyrillic: 0x0428, + Shchacyrillic: 0x0429, + Sheicoptic: 0x03E2, + Shhacyrillic: 0x04BA, + Shimacoptic: 0x03EC, + Sigma: 0x03A3, + Sixroman: 0x2165, + Smonospace: 0xFF33, + Softsigncyrillic: 0x042C, + Ssmall: 0xF773, + Stigmagreek: 0x03DA, + T: 0x0054, + Tau: 0x03A4, + Tbar: 0x0166, + Tcaron: 0x0164, + Tcedilla: 0x0162, + Tcircle: 0x24C9, + Tcircumflexbelow: 0x1E70, + Tcommaaccent: 0x0162, + Tdotaccent: 0x1E6A, + Tdotbelow: 0x1E6C, + Tecyrillic: 0x0422, + Tedescendercyrillic: 0x04AC, + Tenroman: 0x2169, + Tetsecyrillic: 0x04B4, + Theta: 0x0398, + Thook: 0x01AC, + Thorn: 0x00DE, + Thornsmall: 0xF7FE, + Threeroman: 0x2162, + Tildesmall: 0xF6FE, + Tiwnarmenian: 0x054F, + Tlinebelow: 0x1E6E, + Tmonospace: 0xFF34, + Toarmenian: 0x0539, + Tonefive: 0x01BC, + Tonesix: 0x0184, + Tonetwo: 0x01A7, + Tretroflexhook: 0x01AE, + Tsecyrillic: 0x0426, + Tshecyrillic: 0x040B, + Tsmall: 0xF774, + Twelveroman: 0x216B, + Tworoman: 0x2161, + U: 0x0055, + Uacute: 0x00DA, + Uacutesmall: 0xF7FA, + Ubreve: 0x016C, + Ucaron: 0x01D3, + Ucircle: 0x24CA, + Ucircumflex: 0x00DB, + Ucircumflexbelow: 0x1E76, + Ucircumflexsmall: 0xF7FB, + Ucyrillic: 0x0423, + Udblacute: 0x0170, + Udblgrave: 0x0214, + Udieresis: 0x00DC, + Udieresisacute: 0x01D7, + Udieresisbelow: 0x1E72, + Udieresiscaron: 0x01D9, + Udieresiscyrillic: 0x04F0, + Udieresisgrave: 0x01DB, + Udieresismacron: 0x01D5, + Udieresissmall: 0xF7FC, + Udotbelow: 0x1EE4, + Ugrave: 0x00D9, + Ugravesmall: 0xF7F9, + Uhookabove: 0x1EE6, + Uhorn: 0x01AF, + Uhornacute: 0x1EE8, + Uhorndotbelow: 0x1EF0, + Uhorngrave: 0x1EEA, + Uhornhookabove: 0x1EEC, + Uhorntilde: 0x1EEE, + Uhungarumlaut: 0x0170, + Uhungarumlautcyrillic: 0x04F2, + Uinvertedbreve: 0x0216, + Ukcyrillic: 0x0478, + Umacron: 0x016A, + Umacroncyrillic: 0x04EE, + Umacrondieresis: 0x1E7A, + Umonospace: 0xFF35, + Uogonek: 0x0172, + Upsilon: 0x03A5, + Upsilon1: 0x03D2, + Upsilonacutehooksymbolgreek: 0x03D3, + Upsilonafrican: 0x01B1, + Upsilondieresis: 0x03AB, + Upsilondieresishooksymbolgreek: 0x03D4, + Upsilonhooksymbol: 0x03D2, + Upsilontonos: 0x038E, + Uring: 0x016E, + Ushortcyrillic: 0x040E, + Usmall: 0xF775, + Ustraightcyrillic: 0x04AE, + Ustraightstrokecyrillic: 0x04B0, + Utilde: 0x0168, + Utildeacute: 0x1E78, + Utildebelow: 0x1E74, + V: 0x0056, + Vcircle: 0x24CB, + Vdotbelow: 0x1E7E, + Vecyrillic: 0x0412, + Vewarmenian: 0x054E, + Vhook: 0x01B2, + Vmonospace: 0xFF36, + Voarmenian: 0x0548, + Vsmall: 0xF776, + Vtilde: 0x1E7C, + W: 0x0057, + Wacute: 0x1E82, + Wcircle: 0x24CC, + Wcircumflex: 0x0174, + Wdieresis: 0x1E84, + Wdotaccent: 0x1E86, + Wdotbelow: 0x1E88, + Wgrave: 0x1E80, + Wmonospace: 0xFF37, + Wsmall: 0xF777, + X: 0x0058, + Xcircle: 0x24CD, + Xdieresis: 0x1E8C, + Xdotaccent: 0x1E8A, + Xeharmenian: 0x053D, + Xi: 0x039E, + Xmonospace: 0xFF38, + Xsmall: 0xF778, + Y: 0x0059, + Yacute: 0x00DD, + Yacutesmall: 0xF7FD, + Yatcyrillic: 0x0462, + Ycircle: 0x24CE, + Ycircumflex: 0x0176, + Ydieresis: 0x0178, + Ydieresissmall: 0xF7FF, + Ydotaccent: 0x1E8E, + Ydotbelow: 0x1EF4, + Yericyrillic: 0x042B, + Yerudieresiscyrillic: 0x04F8, + Ygrave: 0x1EF2, + Yhook: 0x01B3, + Yhookabove: 0x1EF6, + Yiarmenian: 0x0545, + Yicyrillic: 0x0407, + Yiwnarmenian: 0x0552, + Ymonospace: 0xFF39, + Ysmall: 0xF779, + Ytilde: 0x1EF8, + Yusbigcyrillic: 0x046A, + Yusbigiotifiedcyrillic: 0x046C, + Yuslittlecyrillic: 0x0466, + Yuslittleiotifiedcyrillic: 0x0468, + Z: 0x005A, + Zaarmenian: 0x0536, + Zacute: 0x0179, + Zcaron: 0x017D, + Zcaronsmall: 0xF6FF, + Zcircle: 0x24CF, + Zcircumflex: 0x1E90, + Zdot: 0x017B, + Zdotaccent: 0x017B, + Zdotbelow: 0x1E92, + Zecyrillic: 0x0417, + Zedescendercyrillic: 0x0498, + Zedieresiscyrillic: 0x04DE, + Zeta: 0x0396, + Zhearmenian: 0x053A, + Zhebrevecyrillic: 0x04C1, + Zhecyrillic: 0x0416, + Zhedescendercyrillic: 0x0496, + Zhedieresiscyrillic: 0x04DC, + Zlinebelow: 0x1E94, + Zmonospace: 0xFF3A, + Zsmall: 0xF77A, + Zstroke: 0x01B5, + a: 0x0061, + aabengali: 0x0986, + aacute: 0x00E1, + aadeva: 0x0906, + aagujarati: 0x0A86, + aagurmukhi: 0x0A06, + aamatragurmukhi: 0x0A3E, + aarusquare: 0x3303, + aavowelsignbengali: 0x09BE, + aavowelsigndeva: 0x093E, + aavowelsigngujarati: 0x0ABE, + abbreviationmarkarmenian: 0x055F, + abbreviationsigndeva: 0x0970, + abengali: 0x0985, + abopomofo: 0x311A, + abreve: 0x0103, + abreveacute: 0x1EAF, + abrevecyrillic: 0x04D1, + abrevedotbelow: 0x1EB7, + abrevegrave: 0x1EB1, + abrevehookabove: 0x1EB3, + abrevetilde: 0x1EB5, + acaron: 0x01CE, + acircle: 0x24D0, + acircumflex: 0x00E2, + acircumflexacute: 0x1EA5, + acircumflexdotbelow: 0x1EAD, + acircumflexgrave: 0x1EA7, + acircumflexhookabove: 0x1EA9, + acircumflextilde: 0x1EAB, + acute: 0x00B4, + acutebelowcmb: 0x0317, + acutecmb: 0x0301, + acutecomb: 0x0301, + acutedeva: 0x0954, + acutelowmod: 0x02CF, + acutetonecmb: 0x0341, + acyrillic: 0x0430, + adblgrave: 0x0201, + addakgurmukhi: 0x0A71, + adeva: 0x0905, + adieresis: 0x00E4, + adieresiscyrillic: 0x04D3, + adieresismacron: 0x01DF, + adotbelow: 0x1EA1, + adotmacron: 0x01E1, + ae: 0x00E6, + aeacute: 0x01FD, + aekorean: 0x3150, + aemacron: 0x01E3, + afii00208: 0x2015, + afii08941: 0x20A4, + afii10017: 0x0410, + afii10018: 0x0411, + afii10019: 0x0412, + afii10020: 0x0413, + afii10021: 0x0414, + afii10022: 0x0415, + afii10023: 0x0401, + afii10024: 0x0416, + afii10025: 0x0417, + afii10026: 0x0418, + afii10027: 0x0419, + afii10028: 0x041A, + afii10029: 0x041B, + afii10030: 0x041C, + afii10031: 0x041D, + afii10032: 0x041E, + afii10033: 0x041F, + afii10034: 0x0420, + afii10035: 0x0421, + afii10036: 0x0422, + afii10037: 0x0423, + afii10038: 0x0424, + afii10039: 0x0425, + afii10040: 0x0426, + afii10041: 0x0427, + afii10042: 0x0428, + afii10043: 0x0429, + afii10044: 0x042A, + afii10045: 0x042B, + afii10046: 0x042C, + afii10047: 0x042D, + afii10048: 0x042E, + afii10049: 0x042F, + afii10050: 0x0490, + afii10051: 0x0402, + afii10052: 0x0403, + afii10053: 0x0404, + afii10054: 0x0405, + afii10055: 0x0406, + afii10056: 0x0407, + afii10057: 0x0408, + afii10058: 0x0409, + afii10059: 0x040A, + afii10060: 0x040B, + afii10061: 0x040C, + afii10062: 0x040E, + afii10063: 0xF6C4, + afii10064: 0xF6C5, + afii10065: 0x0430, + afii10066: 0x0431, + afii10067: 0x0432, + afii10068: 0x0433, + afii10069: 0x0434, + afii10070: 0x0435, + afii10071: 0x0451, + afii10072: 0x0436, + afii10073: 0x0437, + afii10074: 0x0438, + afii10075: 0x0439, + afii10076: 0x043A, + afii10077: 0x043B, + afii10078: 0x043C, + afii10079: 0x043D, + afii10080: 0x043E, + afii10081: 0x043F, + afii10082: 0x0440, + afii10083: 0x0441, + afii10084: 0x0442, + afii10085: 0x0443, + afii10086: 0x0444, + afii10087: 0x0445, + afii10088: 0x0446, + afii10089: 0x0447, + afii10090: 0x0448, + afii10091: 0x0449, + afii10092: 0x044A, + afii10093: 0x044B, + afii10094: 0x044C, + afii10095: 0x044D, + afii10096: 0x044E, + afii10097: 0x044F, + afii10098: 0x0491, + afii10099: 0x0452, + afii10100: 0x0453, + afii10101: 0x0454, + afii10102: 0x0455, + afii10103: 0x0456, + afii10104: 0x0457, + afii10105: 0x0458, + afii10106: 0x0459, + afii10107: 0x045A, + afii10108: 0x045B, + afii10109: 0x045C, + afii10110: 0x045E, + afii10145: 0x040F, + afii10146: 0x0462, + afii10147: 0x0472, + afii10148: 0x0474, + afii10192: 0xF6C6, + afii10193: 0x045F, + afii10194: 0x0463, + afii10195: 0x0473, + afii10196: 0x0475, + afii10831: 0xF6C7, + afii10832: 0xF6C8, + afii10846: 0x04D9, + afii299: 0x200E, + afii300: 0x200F, + afii301: 0x200D, + afii57381: 0x066A, + afii57388: 0x060C, + afii57392: 0x0660, + afii57393: 0x0661, + afii57394: 0x0662, + afii57395: 0x0663, + afii57396: 0x0664, + afii57397: 0x0665, + afii57398: 0x0666, + afii57399: 0x0667, + afii57400: 0x0668, + afii57401: 0x0669, + afii57403: 0x061B, + afii57407: 0x061F, + afii57409: 0x0621, + afii57410: 0x0622, + afii57411: 0x0623, + afii57412: 0x0624, + afii57413: 0x0625, + afii57414: 0x0626, + afii57415: 0x0627, + afii57416: 0x0628, + afii57417: 0x0629, + afii57418: 0x062A, + afii57419: 0x062B, + afii57420: 0x062C, + afii57421: 0x062D, + afii57422: 0x062E, + afii57423: 0x062F, + afii57424: 0x0630, + afii57425: 0x0631, + afii57426: 0x0632, + afii57427: 0x0633, + afii57428: 0x0634, + afii57429: 0x0635, + afii57430: 0x0636, + afii57431: 0x0637, + afii57432: 0x0638, + afii57433: 0x0639, + afii57434: 0x063A, + afii57440: 0x0640, + afii57441: 0x0641, + afii57442: 0x0642, + afii57443: 0x0643, + afii57444: 0x0644, + afii57445: 0x0645, + afii57446: 0x0646, + afii57448: 0x0648, + afii57449: 0x0649, + afii57450: 0x064A, + afii57451: 0x064B, + afii57452: 0x064C, + afii57453: 0x064D, + afii57454: 0x064E, + afii57455: 0x064F, + afii57456: 0x0650, + afii57457: 0x0651, + afii57458: 0x0652, + afii57470: 0x0647, + afii57505: 0x06A4, + afii57506: 0x067E, + afii57507: 0x0686, + afii57508: 0x0698, + afii57509: 0x06AF, + afii57511: 0x0679, + afii57512: 0x0688, + afii57513: 0x0691, + afii57514: 0x06BA, + afii57519: 0x06D2, + afii57534: 0x06D5, + afii57636: 0x20AA, + afii57645: 0x05BE, + afii57658: 0x05C3, + afii57664: 0x05D0, + afii57665: 0x05D1, + afii57666: 0x05D2, + afii57667: 0x05D3, + afii57668: 0x05D4, + afii57669: 0x05D5, + afii57670: 0x05D6, + afii57671: 0x05D7, + afii57672: 0x05D8, + afii57673: 0x05D9, + afii57674: 0x05DA, + afii57675: 0x05DB, + afii57676: 0x05DC, + afii57677: 0x05DD, + afii57678: 0x05DE, + afii57679: 0x05DF, + afii57680: 0x05E0, + afii57681: 0x05E1, + afii57682: 0x05E2, + afii57683: 0x05E3, + afii57684: 0x05E4, + afii57685: 0x05E5, + afii57686: 0x05E6, + afii57687: 0x05E7, + afii57688: 0x05E8, + afii57689: 0x05E9, + afii57690: 0x05EA, + afii57694: 0xFB2A, + afii57695: 0xFB2B, + afii57700: 0xFB4B, + afii57705: 0xFB1F, + afii57716: 0x05F0, + afii57717: 0x05F1, + afii57718: 0x05F2, + afii57723: 0xFB35, + afii57793: 0x05B4, + afii57794: 0x05B5, + afii57795: 0x05B6, + afii57796: 0x05BB, + afii57797: 0x05B8, + afii57798: 0x05B7, + afii57799: 0x05B0, + afii57800: 0x05B2, + afii57801: 0x05B1, + afii57802: 0x05B3, + afii57803: 0x05C2, + afii57804: 0x05C1, + afii57806: 0x05B9, + afii57807: 0x05BC, + afii57839: 0x05BD, + afii57841: 0x05BF, + afii57842: 0x05C0, + afii57929: 0x02BC, + afii61248: 0x2105, + afii61289: 0x2113, + afii61352: 0x2116, + afii61573: 0x202C, + afii61574: 0x202D, + afii61575: 0x202E, + afii61664: 0x200C, + afii63167: 0x066D, + afii64937: 0x02BD, + agrave: 0x00E0, + agujarati: 0x0A85, + agurmukhi: 0x0A05, + ahiragana: 0x3042, + ahookabove: 0x1EA3, + aibengali: 0x0990, + aibopomofo: 0x311E, + aideva: 0x0910, + aiecyrillic: 0x04D5, + aigujarati: 0x0A90, + aigurmukhi: 0x0A10, + aimatragurmukhi: 0x0A48, + ainarabic: 0x0639, + ainfinalarabic: 0xFECA, + aininitialarabic: 0xFECB, + ainmedialarabic: 0xFECC, + ainvertedbreve: 0x0203, + aivowelsignbengali: 0x09C8, + aivowelsigndeva: 0x0948, + aivowelsigngujarati: 0x0AC8, + akatakana: 0x30A2, + akatakanahalfwidth: 0xFF71, + akorean: 0x314F, + alef: 0x05D0, + alefarabic: 0x0627, + alefdageshhebrew: 0xFB30, + aleffinalarabic: 0xFE8E, + alefhamzaabovearabic: 0x0623, + alefhamzaabovefinalarabic: 0xFE84, + alefhamzabelowarabic: 0x0625, + alefhamzabelowfinalarabic: 0xFE88, + alefhebrew: 0x05D0, + aleflamedhebrew: 0xFB4F, + alefmaddaabovearabic: 0x0622, + alefmaddaabovefinalarabic: 0xFE82, + alefmaksuraarabic: 0x0649, + alefmaksurafinalarabic: 0xFEF0, + alefmaksurainitialarabic: 0xFEF3, + alefmaksuramedialarabic: 0xFEF4, + alefpatahhebrew: 0xFB2E, + alefqamatshebrew: 0xFB2F, + aleph: 0x2135, + allequal: 0x224C, + alpha: 0x03B1, + alphatonos: 0x03AC, + amacron: 0x0101, + amonospace: 0xFF41, + ampersand: 0x0026, + ampersandmonospace: 0xFF06, + ampersandsmall: 0xF726, + amsquare: 0x33C2, + anbopomofo: 0x3122, + angbopomofo: 0x3124, + angbracketleft: 0x3008, // This glyph is missing from Adobe's original list. + angbracketright: 0x3009, // This glyph is missing from Adobe's original list. + angkhankhuthai: 0x0E5A, + angle: 0x2220, + anglebracketleft: 0x3008, + anglebracketleftvertical: 0xFE3F, + anglebracketright: 0x3009, + anglebracketrightvertical: 0xFE40, + angleleft: 0x2329, + angleright: 0x232A, + angstrom: 0x212B, + anoteleia: 0x0387, + anudattadeva: 0x0952, + anusvarabengali: 0x0982, + anusvaradeva: 0x0902, + anusvaragujarati: 0x0A82, + aogonek: 0x0105, + apaatosquare: 0x3300, + aparen: 0x249C, + apostrophearmenian: 0x055A, + apostrophemod: 0x02BC, + apple: 0xF8FF, + approaches: 0x2250, + approxequal: 0x2248, + approxequalorimage: 0x2252, + approximatelyequal: 0x2245, + araeaekorean: 0x318E, + araeakorean: 0x318D, + arc: 0x2312, + arighthalfring: 0x1E9A, + aring: 0x00E5, + aringacute: 0x01FB, + aringbelow: 0x1E01, + arrowboth: 0x2194, + arrowdashdown: 0x21E3, + arrowdashleft: 0x21E0, + arrowdashright: 0x21E2, + arrowdashup: 0x21E1, + arrowdblboth: 0x21D4, + arrowdbldown: 0x21D3, + arrowdblleft: 0x21D0, + arrowdblright: 0x21D2, + arrowdblup: 0x21D1, + arrowdown: 0x2193, + arrowdownleft: 0x2199, + arrowdownright: 0x2198, + arrowdownwhite: 0x21E9, + arrowheaddownmod: 0x02C5, + arrowheadleftmod: 0x02C2, + arrowheadrightmod: 0x02C3, + arrowheadupmod: 0x02C4, + arrowhorizex: 0xF8E7, + arrowleft: 0x2190, + arrowleftdbl: 0x21D0, + arrowleftdblstroke: 0x21CD, + arrowleftoverright: 0x21C6, + arrowleftwhite: 0x21E6, + arrowright: 0x2192, + arrowrightdblstroke: 0x21CF, + arrowrightheavy: 0x279E, + arrowrightoverleft: 0x21C4, + arrowrightwhite: 0x21E8, + arrowtableft: 0x21E4, + arrowtabright: 0x21E5, + arrowup: 0x2191, + arrowupdn: 0x2195, + arrowupdnbse: 0x21A8, + arrowupdownbase: 0x21A8, + arrowupleft: 0x2196, + arrowupleftofdown: 0x21C5, + arrowupright: 0x2197, + arrowupwhite: 0x21E7, + arrowvertex: 0xF8E6, + asciicircum: 0x005E, + asciicircummonospace: 0xFF3E, + asciitilde: 0x007E, + asciitildemonospace: 0xFF5E, + ascript: 0x0251, + ascriptturned: 0x0252, + asmallhiragana: 0x3041, + asmallkatakana: 0x30A1, + asmallkatakanahalfwidth: 0xFF67, + asterisk: 0x002A, + asteriskaltonearabic: 0x066D, + asteriskarabic: 0x066D, + asteriskmath: 0x2217, + asteriskmonospace: 0xFF0A, + asterisksmall: 0xFE61, + asterism: 0x2042, + asuperior: 0xF6E9, + asymptoticallyequal: 0x2243, + at: 0x0040, + atilde: 0x00E3, + atmonospace: 0xFF20, + atsmall: 0xFE6B, + aturned: 0x0250, + aubengali: 0x0994, + aubopomofo: 0x3120, + audeva: 0x0914, + augujarati: 0x0A94, + augurmukhi: 0x0A14, + aulengthmarkbengali: 0x09D7, + aumatragurmukhi: 0x0A4C, + auvowelsignbengali: 0x09CC, + auvowelsigndeva: 0x094C, + auvowelsigngujarati: 0x0ACC, + avagrahadeva: 0x093D, + aybarmenian: 0x0561, + ayin: 0x05E2, + ayinaltonehebrew: 0xFB20, + ayinhebrew: 0x05E2, + b: 0x0062, + babengali: 0x09AC, + backslash: 0x005C, + backslashmonospace: 0xFF3C, + badeva: 0x092C, + bagujarati: 0x0AAC, + bagurmukhi: 0x0A2C, + bahiragana: 0x3070, + bahtthai: 0x0E3F, + bakatakana: 0x30D0, + bar: 0x007C, + barmonospace: 0xFF5C, + bbopomofo: 0x3105, + bcircle: 0x24D1, + bdotaccent: 0x1E03, + bdotbelow: 0x1E05, + beamedsixteenthnotes: 0x266C, + because: 0x2235, + becyrillic: 0x0431, + beharabic: 0x0628, + behfinalarabic: 0xFE90, + behinitialarabic: 0xFE91, + behiragana: 0x3079, + behmedialarabic: 0xFE92, + behmeeminitialarabic: 0xFC9F, + behmeemisolatedarabic: 0xFC08, + behnoonfinalarabic: 0xFC6D, + bekatakana: 0x30D9, + benarmenian: 0x0562, + bet: 0x05D1, + beta: 0x03B2, + betasymbolgreek: 0x03D0, + betdagesh: 0xFB31, + betdageshhebrew: 0xFB31, + bethebrew: 0x05D1, + betrafehebrew: 0xFB4C, + bhabengali: 0x09AD, + bhadeva: 0x092D, + bhagujarati: 0x0AAD, + bhagurmukhi: 0x0A2D, + bhook: 0x0253, + bihiragana: 0x3073, + bikatakana: 0x30D3, + bilabialclick: 0x0298, + bindigurmukhi: 0x0A02, + birusquare: 0x3331, + blackcircle: 0x25CF, + blackdiamond: 0x25C6, + blackdownpointingtriangle: 0x25BC, + blackleftpointingpointer: 0x25C4, + blackleftpointingtriangle: 0x25C0, + blacklenticularbracketleft: 0x3010, + blacklenticularbracketleftvertical: 0xFE3B, + blacklenticularbracketright: 0x3011, + blacklenticularbracketrightvertical: 0xFE3C, + blacklowerlefttriangle: 0x25E3, + blacklowerrighttriangle: 0x25E2, + blackrectangle: 0x25AC, + blackrightpointingpointer: 0x25BA, + blackrightpointingtriangle: 0x25B6, + blacksmallsquare: 0x25AA, + blacksmilingface: 0x263B, + blacksquare: 0x25A0, + blackstar: 0x2605, + blackupperlefttriangle: 0x25E4, + blackupperrighttriangle: 0x25E5, + blackuppointingsmalltriangle: 0x25B4, + blackuppointingtriangle: 0x25B2, + blank: 0x2423, + blinebelow: 0x1E07, + block: 0x2588, + bmonospace: 0xFF42, + bobaimaithai: 0x0E1A, + bohiragana: 0x307C, + bokatakana: 0x30DC, + bparen: 0x249D, + bqsquare: 0x33C3, + braceex: 0xF8F4, + braceleft: 0x007B, + braceleftbt: 0xF8F3, + braceleftmid: 0xF8F2, + braceleftmonospace: 0xFF5B, + braceleftsmall: 0xFE5B, + bracelefttp: 0xF8F1, + braceleftvertical: 0xFE37, + braceright: 0x007D, + bracerightbt: 0xF8FE, + bracerightmid: 0xF8FD, + bracerightmonospace: 0xFF5D, + bracerightsmall: 0xFE5C, + bracerighttp: 0xF8FC, + bracerightvertical: 0xFE38, + bracketleft: 0x005B, + bracketleftbt: 0xF8F0, + bracketleftex: 0xF8EF, + bracketleftmonospace: 0xFF3B, + bracketlefttp: 0xF8EE, + bracketright: 0x005D, + bracketrightbt: 0xF8FB, + bracketrightex: 0xF8FA, + bracketrightmonospace: 0xFF3D, + bracketrighttp: 0xF8F9, + breve: 0x02D8, + brevebelowcmb: 0x032E, + brevecmb: 0x0306, + breveinvertedbelowcmb: 0x032F, + breveinvertedcmb: 0x0311, + breveinverteddoublecmb: 0x0361, + bridgebelowcmb: 0x032A, + bridgeinvertedbelowcmb: 0x033A, + brokenbar: 0x00A6, + bstroke: 0x0180, + bsuperior: 0xF6EA, + btopbar: 0x0183, + buhiragana: 0x3076, + bukatakana: 0x30D6, + bullet: 0x2022, + bulletinverse: 0x25D8, + bulletoperator: 0x2219, + bullseye: 0x25CE, + c: 0x0063, + caarmenian: 0x056E, + cabengali: 0x099A, + cacute: 0x0107, + cadeva: 0x091A, + cagujarati: 0x0A9A, + cagurmukhi: 0x0A1A, + calsquare: 0x3388, + candrabindubengali: 0x0981, + candrabinducmb: 0x0310, + candrabindudeva: 0x0901, + candrabindugujarati: 0x0A81, + capslock: 0x21EA, + careof: 0x2105, + caron: 0x02C7, + caronbelowcmb: 0x032C, + caroncmb: 0x030C, + carriagereturn: 0x21B5, + cbopomofo: 0x3118, + ccaron: 0x010D, + ccedilla: 0x00E7, + ccedillaacute: 0x1E09, + ccircle: 0x24D2, + ccircumflex: 0x0109, + ccurl: 0x0255, + cdot: 0x010B, + cdotaccent: 0x010B, + cdsquare: 0x33C5, + cedilla: 0x00B8, + cedillacmb: 0x0327, + cent: 0x00A2, + centigrade: 0x2103, + centinferior: 0xF6DF, + centmonospace: 0xFFE0, + centoldstyle: 0xF7A2, + centsuperior: 0xF6E0, + chaarmenian: 0x0579, + chabengali: 0x099B, + chadeva: 0x091B, + chagujarati: 0x0A9B, + chagurmukhi: 0x0A1B, + chbopomofo: 0x3114, + cheabkhasiancyrillic: 0x04BD, + checkmark: 0x2713, + checyrillic: 0x0447, + chedescenderabkhasiancyrillic: 0x04BF, + chedescendercyrillic: 0x04B7, + chedieresiscyrillic: 0x04F5, + cheharmenian: 0x0573, + chekhakassiancyrillic: 0x04CC, + cheverticalstrokecyrillic: 0x04B9, + chi: 0x03C7, + chieuchacirclekorean: 0x3277, + chieuchaparenkorean: 0x3217, + chieuchcirclekorean: 0x3269, + chieuchkorean: 0x314A, + chieuchparenkorean: 0x3209, + chochangthai: 0x0E0A, + chochanthai: 0x0E08, + chochingthai: 0x0E09, + chochoethai: 0x0E0C, + chook: 0x0188, + cieucacirclekorean: 0x3276, + cieucaparenkorean: 0x3216, + cieuccirclekorean: 0x3268, + cieuckorean: 0x3148, + cieucparenkorean: 0x3208, + cieucuparenkorean: 0x321C, + circle: 0x25CB, + circlecopyrt: 0x00A9, // This glyph is missing from Adobe's original list. + circlemultiply: 0x2297, + circleot: 0x2299, + circleplus: 0x2295, + circlepostalmark: 0x3036, + circlewithlefthalfblack: 0x25D0, + circlewithrighthalfblack: 0x25D1, + circumflex: 0x02C6, + circumflexbelowcmb: 0x032D, + circumflexcmb: 0x0302, + clear: 0x2327, + clickalveolar: 0x01C2, + clickdental: 0x01C0, + clicklateral: 0x01C1, + clickretroflex: 0x01C3, + club: 0x2663, + clubsuitblack: 0x2663, + clubsuitwhite: 0x2667, + cmcubedsquare: 0x33A4, + cmonospace: 0xFF43, + cmsquaredsquare: 0x33A0, + coarmenian: 0x0581, + colon: 0x003A, + colonmonetary: 0x20A1, + colonmonospace: 0xFF1A, + colonsign: 0x20A1, + colonsmall: 0xFE55, + colontriangularhalfmod: 0x02D1, + colontriangularmod: 0x02D0, + comma: 0x002C, + commaabovecmb: 0x0313, + commaaboverightcmb: 0x0315, + commaaccent: 0xF6C3, + commaarabic: 0x060C, + commaarmenian: 0x055D, + commainferior: 0xF6E1, + commamonospace: 0xFF0C, + commareversedabovecmb: 0x0314, + commareversedmod: 0x02BD, + commasmall: 0xFE50, + commasuperior: 0xF6E2, + commaturnedabovecmb: 0x0312, + commaturnedmod: 0x02BB, + compass: 0x263C, + congruent: 0x2245, + contourintegral: 0x222E, + control: 0x2303, + controlACK: 0x0006, + controlBEL: 0x0007, + controlBS: 0x0008, + controlCAN: 0x0018, + controlCR: 0x000D, + controlDC1: 0x0011, + controlDC2: 0x0012, + controlDC3: 0x0013, + controlDC4: 0x0014, + controlDEL: 0x007F, + controlDLE: 0x0010, + controlEM: 0x0019, + controlENQ: 0x0005, + controlEOT: 0x0004, + controlESC: 0x001B, + controlETB: 0x0017, + controlETX: 0x0003, + controlFF: 0x000C, + controlFS: 0x001C, + controlGS: 0x001D, + controlHT: 0x0009, + controlLF: 0x000A, + controlNAK: 0x0015, + controlRS: 0x001E, + controlSI: 0x000F, + controlSO: 0x000E, + controlSOT: 0x0002, + controlSTX: 0x0001, + controlSUB: 0x001A, + controlSYN: 0x0016, + controlUS: 0x001F, + controlVT: 0x000B, + copyright: 0x00A9, + copyrightsans: 0xF8E9, + copyrightserif: 0xF6D9, + cornerbracketleft: 0x300C, + cornerbracketlefthalfwidth: 0xFF62, + cornerbracketleftvertical: 0xFE41, + cornerbracketright: 0x300D, + cornerbracketrighthalfwidth: 0xFF63, + cornerbracketrightvertical: 0xFE42, + corporationsquare: 0x337F, + cosquare: 0x33C7, + coverkgsquare: 0x33C6, + cparen: 0x249E, + cruzeiro: 0x20A2, + cstretched: 0x0297, + curlyand: 0x22CF, + curlyor: 0x22CE, + currency: 0x00A4, + cyrBreve: 0xF6D1, + cyrFlex: 0xF6D2, + cyrbreve: 0xF6D4, + cyrflex: 0xF6D5, + d: 0x0064, + daarmenian: 0x0564, + dabengali: 0x09A6, + dadarabic: 0x0636, + dadeva: 0x0926, + dadfinalarabic: 0xFEBE, + dadinitialarabic: 0xFEBF, + dadmedialarabic: 0xFEC0, + dagesh: 0x05BC, + dageshhebrew: 0x05BC, + dagger: 0x2020, + daggerdbl: 0x2021, + dagujarati: 0x0AA6, + dagurmukhi: 0x0A26, + dahiragana: 0x3060, + dakatakana: 0x30C0, + dalarabic: 0x062F, + dalet: 0x05D3, + daletdagesh: 0xFB33, + daletdageshhebrew: 0xFB33, + dalethebrew: 0x05D3, + dalfinalarabic: 0xFEAA, + dammaarabic: 0x064F, + dammalowarabic: 0x064F, + dammatanaltonearabic: 0x064C, + dammatanarabic: 0x064C, + danda: 0x0964, + dargahebrew: 0x05A7, + dargalefthebrew: 0x05A7, + dasiapneumatacyrilliccmb: 0x0485, + dblGrave: 0xF6D3, + dblanglebracketleft: 0x300A, + dblanglebracketleftvertical: 0xFE3D, + dblanglebracketright: 0x300B, + dblanglebracketrightvertical: 0xFE3E, + dblarchinvertedbelowcmb: 0x032B, + dblarrowleft: 0x21D4, + dblarrowright: 0x21D2, + dbldanda: 0x0965, + dblgrave: 0xF6D6, + dblgravecmb: 0x030F, + dblintegral: 0x222C, + dbllowline: 0x2017, + dbllowlinecmb: 0x0333, + dbloverlinecmb: 0x033F, + dblprimemod: 0x02BA, + dblverticalbar: 0x2016, + dblverticallineabovecmb: 0x030E, + dbopomofo: 0x3109, + dbsquare: 0x33C8, + dcaron: 0x010F, + dcedilla: 0x1E11, + dcircle: 0x24D3, + dcircumflexbelow: 0x1E13, + dcroat: 0x0111, + ddabengali: 0x09A1, + ddadeva: 0x0921, + ddagujarati: 0x0AA1, + ddagurmukhi: 0x0A21, + ddalarabic: 0x0688, + ddalfinalarabic: 0xFB89, + dddhadeva: 0x095C, + ddhabengali: 0x09A2, + ddhadeva: 0x0922, + ddhagujarati: 0x0AA2, + ddhagurmukhi: 0x0A22, + ddotaccent: 0x1E0B, + ddotbelow: 0x1E0D, + decimalseparatorarabic: 0x066B, + decimalseparatorpersian: 0x066B, + decyrillic: 0x0434, + degree: 0x00B0, + dehihebrew: 0x05AD, + dehiragana: 0x3067, + deicoptic: 0x03EF, + dekatakana: 0x30C7, + deleteleft: 0x232B, + deleteright: 0x2326, + delta: 0x03B4, + deltaturned: 0x018D, + denominatorminusonenumeratorbengali: 0x09F8, + dezh: 0x02A4, + dhabengali: 0x09A7, + dhadeva: 0x0927, + dhagujarati: 0x0AA7, + dhagurmukhi: 0x0A27, + dhook: 0x0257, + dialytikatonos: 0x0385, + dialytikatonoscmb: 0x0344, + diamond: 0x2666, + diamondsuitwhite: 0x2662, + dieresis: 0x00A8, + dieresisacute: 0xF6D7, + dieresisbelowcmb: 0x0324, + dieresiscmb: 0x0308, + dieresisgrave: 0xF6D8, + dieresistonos: 0x0385, + dihiragana: 0x3062, + dikatakana: 0x30C2, + dittomark: 0x3003, + divide: 0x00F7, + divides: 0x2223, + divisionslash: 0x2215, + djecyrillic: 0x0452, + dkshade: 0x2593, + dlinebelow: 0x1E0F, + dlsquare: 0x3397, + dmacron: 0x0111, + dmonospace: 0xFF44, + dnblock: 0x2584, + dochadathai: 0x0E0E, + dodekthai: 0x0E14, + dohiragana: 0x3069, + dokatakana: 0x30C9, + dollar: 0x0024, + dollarinferior: 0xF6E3, + dollarmonospace: 0xFF04, + dollaroldstyle: 0xF724, + dollarsmall: 0xFE69, + dollarsuperior: 0xF6E4, + dong: 0x20AB, + dorusquare: 0x3326, + dotaccent: 0x02D9, + dotaccentcmb: 0x0307, + dotbelowcmb: 0x0323, + dotbelowcomb: 0x0323, + dotkatakana: 0x30FB, + dotlessi: 0x0131, + dotlessj: 0xF6BE, + dotlessjstrokehook: 0x0284, + dotmath: 0x22C5, + dottedcircle: 0x25CC, + doubleyodpatah: 0xFB1F, + doubleyodpatahhebrew: 0xFB1F, + downtackbelowcmb: 0x031E, + downtackmod: 0x02D5, + dparen: 0x249F, + dsuperior: 0xF6EB, + dtail: 0x0256, + dtopbar: 0x018C, + duhiragana: 0x3065, + dukatakana: 0x30C5, + dz: 0x01F3, + dzaltone: 0x02A3, + dzcaron: 0x01C6, + dzcurl: 0x02A5, + dzeabkhasiancyrillic: 0x04E1, + dzecyrillic: 0x0455, + dzhecyrillic: 0x045F, + e: 0x0065, + eacute: 0x00E9, + earth: 0x2641, + ebengali: 0x098F, + ebopomofo: 0x311C, + ebreve: 0x0115, + ecandradeva: 0x090D, + ecandragujarati: 0x0A8D, + ecandravowelsigndeva: 0x0945, + ecandravowelsigngujarati: 0x0AC5, + ecaron: 0x011B, + ecedillabreve: 0x1E1D, + echarmenian: 0x0565, + echyiwnarmenian: 0x0587, + ecircle: 0x24D4, + ecircumflex: 0x00EA, + ecircumflexacute: 0x1EBF, + ecircumflexbelow: 0x1E19, + ecircumflexdotbelow: 0x1EC7, + ecircumflexgrave: 0x1EC1, + ecircumflexhookabove: 0x1EC3, + ecircumflextilde: 0x1EC5, + ecyrillic: 0x0454, + edblgrave: 0x0205, + edeva: 0x090F, + edieresis: 0x00EB, + edot: 0x0117, + edotaccent: 0x0117, + edotbelow: 0x1EB9, + eegurmukhi: 0x0A0F, + eematragurmukhi: 0x0A47, + efcyrillic: 0x0444, + egrave: 0x00E8, + egujarati: 0x0A8F, + eharmenian: 0x0567, + ehbopomofo: 0x311D, + ehiragana: 0x3048, + ehookabove: 0x1EBB, + eibopomofo: 0x311F, + eight: 0x0038, + eightarabic: 0x0668, + eightbengali: 0x09EE, + eightcircle: 0x2467, + eightcircleinversesansserif: 0x2791, + eightdeva: 0x096E, + eighteencircle: 0x2471, + eighteenparen: 0x2485, + eighteenperiod: 0x2499, + eightgujarati: 0x0AEE, + eightgurmukhi: 0x0A6E, + eighthackarabic: 0x0668, + eighthangzhou: 0x3028, + eighthnotebeamed: 0x266B, + eightideographicparen: 0x3227, + eightinferior: 0x2088, + eightmonospace: 0xFF18, + eightoldstyle: 0xF738, + eightparen: 0x247B, + eightperiod: 0x248F, + eightpersian: 0x06F8, + eightroman: 0x2177, + eightsuperior: 0x2078, + eightthai: 0x0E58, + einvertedbreve: 0x0207, + eiotifiedcyrillic: 0x0465, + ekatakana: 0x30A8, + ekatakanahalfwidth: 0xFF74, + ekonkargurmukhi: 0x0A74, + ekorean: 0x3154, + elcyrillic: 0x043B, + element: 0x2208, + elevencircle: 0x246A, + elevenparen: 0x247E, + elevenperiod: 0x2492, + elevenroman: 0x217A, + ellipsis: 0x2026, + ellipsisvertical: 0x22EE, + emacron: 0x0113, + emacronacute: 0x1E17, + emacrongrave: 0x1E15, + emcyrillic: 0x043C, + emdash: 0x2014, + emdashvertical: 0xFE31, + emonospace: 0xFF45, + emphasismarkarmenian: 0x055B, + emptyset: 0x2205, + enbopomofo: 0x3123, + encyrillic: 0x043D, + endash: 0x2013, + endashvertical: 0xFE32, + endescendercyrillic: 0x04A3, + eng: 0x014B, + engbopomofo: 0x3125, + enghecyrillic: 0x04A5, + enhookcyrillic: 0x04C8, + enspace: 0x2002, + eogonek: 0x0119, + eokorean: 0x3153, + eopen: 0x025B, + eopenclosed: 0x029A, + eopenreversed: 0x025C, + eopenreversedclosed: 0x025E, + eopenreversedhook: 0x025D, + eparen: 0x24A0, + epsilon: 0x03B5, + epsilontonos: 0x03AD, + equal: 0x003D, + equalmonospace: 0xFF1D, + equalsmall: 0xFE66, + equalsuperior: 0x207C, + equivalence: 0x2261, + erbopomofo: 0x3126, + ercyrillic: 0x0440, + ereversed: 0x0258, + ereversedcyrillic: 0x044D, + escyrillic: 0x0441, + esdescendercyrillic: 0x04AB, + esh: 0x0283, + eshcurl: 0x0286, + eshortdeva: 0x090E, + eshortvowelsigndeva: 0x0946, + eshreversedloop: 0x01AA, + eshsquatreversed: 0x0285, + esmallhiragana: 0x3047, + esmallkatakana: 0x30A7, + esmallkatakanahalfwidth: 0xFF6A, + estimated: 0x212E, + esuperior: 0xF6EC, + eta: 0x03B7, + etarmenian: 0x0568, + etatonos: 0x03AE, + eth: 0x00F0, + etilde: 0x1EBD, + etildebelow: 0x1E1B, + etnahtafoukhhebrew: 0x0591, + etnahtafoukhlefthebrew: 0x0591, + etnahtahebrew: 0x0591, + etnahtalefthebrew: 0x0591, + eturned: 0x01DD, + eukorean: 0x3161, + euro: 0x20AC, + evowelsignbengali: 0x09C7, + evowelsigndeva: 0x0947, + evowelsigngujarati: 0x0AC7, + exclam: 0x0021, + exclamarmenian: 0x055C, + exclamdbl: 0x203C, + exclamdown: 0x00A1, + exclamdownsmall: 0xF7A1, + exclammonospace: 0xFF01, + exclamsmall: 0xF721, + existential: 0x2203, + ezh: 0x0292, + ezhcaron: 0x01EF, + ezhcurl: 0x0293, + ezhreversed: 0x01B9, + ezhtail: 0x01BA, + f: 0x0066, + fadeva: 0x095E, + fagurmukhi: 0x0A5E, + fahrenheit: 0x2109, + fathaarabic: 0x064E, + fathalowarabic: 0x064E, + fathatanarabic: 0x064B, + fbopomofo: 0x3108, + fcircle: 0x24D5, + fdotaccent: 0x1E1F, + feharabic: 0x0641, + feharmenian: 0x0586, + fehfinalarabic: 0xFED2, + fehinitialarabic: 0xFED3, + fehmedialarabic: 0xFED4, + feicoptic: 0x03E5, + female: 0x2640, + ff: 0xFB00, + ffi: 0xFB03, + ffl: 0xFB04, + fi: 0xFB01, + fifteencircle: 0x246E, + fifteenparen: 0x2482, + fifteenperiod: 0x2496, + figuredash: 0x2012, + filledbox: 0x25A0, + filledrect: 0x25AC, + finalkaf: 0x05DA, + finalkafdagesh: 0xFB3A, + finalkafdageshhebrew: 0xFB3A, + finalkafhebrew: 0x05DA, + finalmem: 0x05DD, + finalmemhebrew: 0x05DD, + finalnun: 0x05DF, + finalnunhebrew: 0x05DF, + finalpe: 0x05E3, + finalpehebrew: 0x05E3, + finaltsadi: 0x05E5, + finaltsadihebrew: 0x05E5, + firsttonechinese: 0x02C9, + fisheye: 0x25C9, + fitacyrillic: 0x0473, + five: 0x0035, + fivearabic: 0x0665, + fivebengali: 0x09EB, + fivecircle: 0x2464, + fivecircleinversesansserif: 0x278E, + fivedeva: 0x096B, + fiveeighths: 0x215D, + fivegujarati: 0x0AEB, + fivegurmukhi: 0x0A6B, + fivehackarabic: 0x0665, + fivehangzhou: 0x3025, + fiveideographicparen: 0x3224, + fiveinferior: 0x2085, + fivemonospace: 0xFF15, + fiveoldstyle: 0xF735, + fiveparen: 0x2478, + fiveperiod: 0x248C, + fivepersian: 0x06F5, + fiveroman: 0x2174, + fivesuperior: 0x2075, + fivethai: 0x0E55, + fl: 0xFB02, + florin: 0x0192, + fmonospace: 0xFF46, + fmsquare: 0x3399, + fofanthai: 0x0E1F, + fofathai: 0x0E1D, + fongmanthai: 0x0E4F, + forall: 0x2200, + four: 0x0034, + fourarabic: 0x0664, + fourbengali: 0x09EA, + fourcircle: 0x2463, + fourcircleinversesansserif: 0x278D, + fourdeva: 0x096A, + fourgujarati: 0x0AEA, + fourgurmukhi: 0x0A6A, + fourhackarabic: 0x0664, + fourhangzhou: 0x3024, + fourideographicparen: 0x3223, + fourinferior: 0x2084, + fourmonospace: 0xFF14, + fournumeratorbengali: 0x09F7, + fouroldstyle: 0xF734, + fourparen: 0x2477, + fourperiod: 0x248B, + fourpersian: 0x06F4, + fourroman: 0x2173, + foursuperior: 0x2074, + fourteencircle: 0x246D, + fourteenparen: 0x2481, + fourteenperiod: 0x2495, + fourthai: 0x0E54, + fourthtonechinese: 0x02CB, + fparen: 0x24A1, + fraction: 0x2044, + franc: 0x20A3, + g: 0x0067, + gabengali: 0x0997, + gacute: 0x01F5, + gadeva: 0x0917, + gafarabic: 0x06AF, + gaffinalarabic: 0xFB93, + gafinitialarabic: 0xFB94, + gafmedialarabic: 0xFB95, + gagujarati: 0x0A97, + gagurmukhi: 0x0A17, + gahiragana: 0x304C, + gakatakana: 0x30AC, + gamma: 0x03B3, + gammalatinsmall: 0x0263, + gammasuperior: 0x02E0, + gangiacoptic: 0x03EB, + gbopomofo: 0x310D, + gbreve: 0x011F, + gcaron: 0x01E7, + gcedilla: 0x0123, + gcircle: 0x24D6, + gcircumflex: 0x011D, + gcommaaccent: 0x0123, + gdot: 0x0121, + gdotaccent: 0x0121, + gecyrillic: 0x0433, + gehiragana: 0x3052, + gekatakana: 0x30B2, + geometricallyequal: 0x2251, + gereshaccenthebrew: 0x059C, + gereshhebrew: 0x05F3, + gereshmuqdamhebrew: 0x059D, + germandbls: 0x00DF, + gershayimaccenthebrew: 0x059E, + gershayimhebrew: 0x05F4, + getamark: 0x3013, + ghabengali: 0x0998, + ghadarmenian: 0x0572, + ghadeva: 0x0918, + ghagujarati: 0x0A98, + ghagurmukhi: 0x0A18, + ghainarabic: 0x063A, + ghainfinalarabic: 0xFECE, + ghaininitialarabic: 0xFECF, + ghainmedialarabic: 0xFED0, + ghemiddlehookcyrillic: 0x0495, + ghestrokecyrillic: 0x0493, + gheupturncyrillic: 0x0491, + ghhadeva: 0x095A, + ghhagurmukhi: 0x0A5A, + ghook: 0x0260, + ghzsquare: 0x3393, + gihiragana: 0x304E, + gikatakana: 0x30AE, + gimarmenian: 0x0563, + gimel: 0x05D2, + gimeldagesh: 0xFB32, + gimeldageshhebrew: 0xFB32, + gimelhebrew: 0x05D2, + gjecyrillic: 0x0453, + glottalinvertedstroke: 0x01BE, + glottalstop: 0x0294, + glottalstopinverted: 0x0296, + glottalstopmod: 0x02C0, + glottalstopreversed: 0x0295, + glottalstopreversedmod: 0x02C1, + glottalstopreversedsuperior: 0x02E4, + glottalstopstroke: 0x02A1, + glottalstopstrokereversed: 0x02A2, + gmacron: 0x1E21, + gmonospace: 0xFF47, + gohiragana: 0x3054, + gokatakana: 0x30B4, + gparen: 0x24A2, + gpasquare: 0x33AC, + gradient: 0x2207, + grave: 0x0060, + gravebelowcmb: 0x0316, + gravecmb: 0x0300, + gravecomb: 0x0300, + gravedeva: 0x0953, + gravelowmod: 0x02CE, + gravemonospace: 0xFF40, + gravetonecmb: 0x0340, + greater: 0x003E, + greaterequal: 0x2265, + greaterequalorless: 0x22DB, + greatermonospace: 0xFF1E, + greaterorequivalent: 0x2273, + greaterorless: 0x2277, + greateroverequal: 0x2267, + greatersmall: 0xFE65, + gscript: 0x0261, + gstroke: 0x01E5, + guhiragana: 0x3050, + guillemotleft: 0x00AB, + guillemotright: 0x00BB, + guilsinglleft: 0x2039, + guilsinglright: 0x203A, + gukatakana: 0x30B0, + guramusquare: 0x3318, + gysquare: 0x33C9, + h: 0x0068, + haabkhasiancyrillic: 0x04A9, + haaltonearabic: 0x06C1, + habengali: 0x09B9, + hadescendercyrillic: 0x04B3, + hadeva: 0x0939, + hagujarati: 0x0AB9, + hagurmukhi: 0x0A39, + haharabic: 0x062D, + hahfinalarabic: 0xFEA2, + hahinitialarabic: 0xFEA3, + hahiragana: 0x306F, + hahmedialarabic: 0xFEA4, + haitusquare: 0x332A, + hakatakana: 0x30CF, + hakatakanahalfwidth: 0xFF8A, + halantgurmukhi: 0x0A4D, + hamzaarabic: 0x0621, + hamzalowarabic: 0x0621, + hangulfiller: 0x3164, + hardsigncyrillic: 0x044A, + harpoonleftbarbup: 0x21BC, + harpoonrightbarbup: 0x21C0, + hasquare: 0x33CA, + hatafpatah: 0x05B2, + hatafpatah16: 0x05B2, + hatafpatah23: 0x05B2, + hatafpatah2f: 0x05B2, + hatafpatahhebrew: 0x05B2, + hatafpatahnarrowhebrew: 0x05B2, + hatafpatahquarterhebrew: 0x05B2, + hatafpatahwidehebrew: 0x05B2, + hatafqamats: 0x05B3, + hatafqamats1b: 0x05B3, + hatafqamats28: 0x05B3, + hatafqamats34: 0x05B3, + hatafqamatshebrew: 0x05B3, + hatafqamatsnarrowhebrew: 0x05B3, + hatafqamatsquarterhebrew: 0x05B3, + hatafqamatswidehebrew: 0x05B3, + hatafsegol: 0x05B1, + hatafsegol17: 0x05B1, + hatafsegol24: 0x05B1, + hatafsegol30: 0x05B1, + hatafsegolhebrew: 0x05B1, + hatafsegolnarrowhebrew: 0x05B1, + hatafsegolquarterhebrew: 0x05B1, + hatafsegolwidehebrew: 0x05B1, + hbar: 0x0127, + hbopomofo: 0x310F, + hbrevebelow: 0x1E2B, + hcedilla: 0x1E29, + hcircle: 0x24D7, + hcircumflex: 0x0125, + hdieresis: 0x1E27, + hdotaccent: 0x1E23, + hdotbelow: 0x1E25, + he: 0x05D4, + heart: 0x2665, + heartsuitblack: 0x2665, + heartsuitwhite: 0x2661, + hedagesh: 0xFB34, + hedageshhebrew: 0xFB34, + hehaltonearabic: 0x06C1, + heharabic: 0x0647, + hehebrew: 0x05D4, + hehfinalaltonearabic: 0xFBA7, + hehfinalalttwoarabic: 0xFEEA, + hehfinalarabic: 0xFEEA, + hehhamzaabovefinalarabic: 0xFBA5, + hehhamzaaboveisolatedarabic: 0xFBA4, + hehinitialaltonearabic: 0xFBA8, + hehinitialarabic: 0xFEEB, + hehiragana: 0x3078, + hehmedialaltonearabic: 0xFBA9, + hehmedialarabic: 0xFEEC, + heiseierasquare: 0x337B, + hekatakana: 0x30D8, + hekatakanahalfwidth: 0xFF8D, + hekutaarusquare: 0x3336, + henghook: 0x0267, + herutusquare: 0x3339, + het: 0x05D7, + hethebrew: 0x05D7, + hhook: 0x0266, + hhooksuperior: 0x02B1, + hieuhacirclekorean: 0x327B, + hieuhaparenkorean: 0x321B, + hieuhcirclekorean: 0x326D, + hieuhkorean: 0x314E, + hieuhparenkorean: 0x320D, + hihiragana: 0x3072, + hikatakana: 0x30D2, + hikatakanahalfwidth: 0xFF8B, + hiriq: 0x05B4, + hiriq14: 0x05B4, + hiriq21: 0x05B4, + hiriq2d: 0x05B4, + hiriqhebrew: 0x05B4, + hiriqnarrowhebrew: 0x05B4, + hiriqquarterhebrew: 0x05B4, + hiriqwidehebrew: 0x05B4, + hlinebelow: 0x1E96, + hmonospace: 0xFF48, + hoarmenian: 0x0570, + hohipthai: 0x0E2B, + hohiragana: 0x307B, + hokatakana: 0x30DB, + hokatakanahalfwidth: 0xFF8E, + holam: 0x05B9, + holam19: 0x05B9, + holam26: 0x05B9, + holam32: 0x05B9, + holamhebrew: 0x05B9, + holamnarrowhebrew: 0x05B9, + holamquarterhebrew: 0x05B9, + holamwidehebrew: 0x05B9, + honokhukthai: 0x0E2E, + hookabovecomb: 0x0309, + hookcmb: 0x0309, + hookpalatalizedbelowcmb: 0x0321, + hookretroflexbelowcmb: 0x0322, + hoonsquare: 0x3342, + horicoptic: 0x03E9, + horizontalbar: 0x2015, + horncmb: 0x031B, + hotsprings: 0x2668, + house: 0x2302, + hparen: 0x24A3, + hsuperior: 0x02B0, + hturned: 0x0265, + huhiragana: 0x3075, + huiitosquare: 0x3333, + hukatakana: 0x30D5, + hukatakanahalfwidth: 0xFF8C, + hungarumlaut: 0x02DD, + hungarumlautcmb: 0x030B, + hv: 0x0195, + hyphen: 0x002D, + hypheninferior: 0xF6E5, + hyphenmonospace: 0xFF0D, + hyphensmall: 0xFE63, + hyphensuperior: 0xF6E6, + hyphentwo: 0x2010, + i: 0x0069, + iacute: 0x00ED, + iacyrillic: 0x044F, + ibengali: 0x0987, + ibopomofo: 0x3127, + ibreve: 0x012D, + icaron: 0x01D0, + icircle: 0x24D8, + icircumflex: 0x00EE, + icyrillic: 0x0456, + idblgrave: 0x0209, + ideographearthcircle: 0x328F, + ideographfirecircle: 0x328B, + ideographicallianceparen: 0x323F, + ideographiccallparen: 0x323A, + ideographiccentrecircle: 0x32A5, + ideographicclose: 0x3006, + ideographiccomma: 0x3001, + ideographiccommaleft: 0xFF64, + ideographiccongratulationparen: 0x3237, + ideographiccorrectcircle: 0x32A3, + ideographicearthparen: 0x322F, + ideographicenterpriseparen: 0x323D, + ideographicexcellentcircle: 0x329D, + ideographicfestivalparen: 0x3240, + ideographicfinancialcircle: 0x3296, + ideographicfinancialparen: 0x3236, + ideographicfireparen: 0x322B, + ideographichaveparen: 0x3232, + ideographichighcircle: 0x32A4, + ideographiciterationmark: 0x3005, + ideographiclaborcircle: 0x3298, + ideographiclaborparen: 0x3238, + ideographicleftcircle: 0x32A7, + ideographiclowcircle: 0x32A6, + ideographicmedicinecircle: 0x32A9, + ideographicmetalparen: 0x322E, + ideographicmoonparen: 0x322A, + ideographicnameparen: 0x3234, + ideographicperiod: 0x3002, + ideographicprintcircle: 0x329E, + ideographicreachparen: 0x3243, + ideographicrepresentparen: 0x3239, + ideographicresourceparen: 0x323E, + ideographicrightcircle: 0x32A8, + ideographicsecretcircle: 0x3299, + ideographicselfparen: 0x3242, + ideographicsocietyparen: 0x3233, + ideographicspace: 0x3000, + ideographicspecialparen: 0x3235, + ideographicstockparen: 0x3231, + ideographicstudyparen: 0x323B, + ideographicsunparen: 0x3230, + ideographicsuperviseparen: 0x323C, + ideographicwaterparen: 0x322C, + ideographicwoodparen: 0x322D, + ideographiczero: 0x3007, + ideographmetalcircle: 0x328E, + ideographmooncircle: 0x328A, + ideographnamecircle: 0x3294, + ideographsuncircle: 0x3290, + ideographwatercircle: 0x328C, + ideographwoodcircle: 0x328D, + ideva: 0x0907, + idieresis: 0x00EF, + idieresisacute: 0x1E2F, + idieresiscyrillic: 0x04E5, + idotbelow: 0x1ECB, + iebrevecyrillic: 0x04D7, + iecyrillic: 0x0435, + ieungacirclekorean: 0x3275, + ieungaparenkorean: 0x3215, + ieungcirclekorean: 0x3267, + ieungkorean: 0x3147, + ieungparenkorean: 0x3207, + igrave: 0x00EC, + igujarati: 0x0A87, + igurmukhi: 0x0A07, + ihiragana: 0x3044, + ihookabove: 0x1EC9, + iibengali: 0x0988, + iicyrillic: 0x0438, + iideva: 0x0908, + iigujarati: 0x0A88, + iigurmukhi: 0x0A08, + iimatragurmukhi: 0x0A40, + iinvertedbreve: 0x020B, + iishortcyrillic: 0x0439, + iivowelsignbengali: 0x09C0, + iivowelsigndeva: 0x0940, + iivowelsigngujarati: 0x0AC0, + ij: 0x0133, + ikatakana: 0x30A4, + ikatakanahalfwidth: 0xFF72, + ikorean: 0x3163, + ilde: 0x02DC, + iluyhebrew: 0x05AC, + imacron: 0x012B, + imacroncyrillic: 0x04E3, + imageorapproximatelyequal: 0x2253, + imatragurmukhi: 0x0A3F, + imonospace: 0xFF49, + increment: 0x2206, + infinity: 0x221E, + iniarmenian: 0x056B, + integral: 0x222B, + integralbottom: 0x2321, + integralbt: 0x2321, + integralex: 0xF8F5, + integraltop: 0x2320, + integraltp: 0x2320, + intersection: 0x2229, + intisquare: 0x3305, + invbullet: 0x25D8, + invcircle: 0x25D9, + invsmileface: 0x263B, + iocyrillic: 0x0451, + iogonek: 0x012F, + iota: 0x03B9, + iotadieresis: 0x03CA, + iotadieresistonos: 0x0390, + iotalatin: 0x0269, + iotatonos: 0x03AF, + iparen: 0x24A4, + irigurmukhi: 0x0A72, + ismallhiragana: 0x3043, + ismallkatakana: 0x30A3, + ismallkatakanahalfwidth: 0xFF68, + issharbengali: 0x09FA, + istroke: 0x0268, + isuperior: 0xF6ED, + iterationhiragana: 0x309D, + iterationkatakana: 0x30FD, + itilde: 0x0129, + itildebelow: 0x1E2D, + iubopomofo: 0x3129, + iucyrillic: 0x044E, + ivowelsignbengali: 0x09BF, + ivowelsigndeva: 0x093F, + ivowelsigngujarati: 0x0ABF, + izhitsacyrillic: 0x0475, + izhitsadblgravecyrillic: 0x0477, + j: 0x006A, + jaarmenian: 0x0571, + jabengali: 0x099C, + jadeva: 0x091C, + jagujarati: 0x0A9C, + jagurmukhi: 0x0A1C, + jbopomofo: 0x3110, + jcaron: 0x01F0, + jcircle: 0x24D9, + jcircumflex: 0x0135, + jcrossedtail: 0x029D, + jdotlessstroke: 0x025F, + jecyrillic: 0x0458, + jeemarabic: 0x062C, + jeemfinalarabic: 0xFE9E, + jeeminitialarabic: 0xFE9F, + jeemmedialarabic: 0xFEA0, + jeharabic: 0x0698, + jehfinalarabic: 0xFB8B, + jhabengali: 0x099D, + jhadeva: 0x091D, + jhagujarati: 0x0A9D, + jhagurmukhi: 0x0A1D, + jheharmenian: 0x057B, + jis: 0x3004, + jmonospace: 0xFF4A, + jparen: 0x24A5, + jsuperior: 0x02B2, + k: 0x006B, + kabashkircyrillic: 0x04A1, + kabengali: 0x0995, + kacute: 0x1E31, + kacyrillic: 0x043A, + kadescendercyrillic: 0x049B, + kadeva: 0x0915, + kaf: 0x05DB, + kafarabic: 0x0643, + kafdagesh: 0xFB3B, + kafdageshhebrew: 0xFB3B, + kaffinalarabic: 0xFEDA, + kafhebrew: 0x05DB, + kafinitialarabic: 0xFEDB, + kafmedialarabic: 0xFEDC, + kafrafehebrew: 0xFB4D, + kagujarati: 0x0A95, + kagurmukhi: 0x0A15, + kahiragana: 0x304B, + kahookcyrillic: 0x04C4, + kakatakana: 0x30AB, + kakatakanahalfwidth: 0xFF76, + kappa: 0x03BA, + kappasymbolgreek: 0x03F0, + kapyeounmieumkorean: 0x3171, + kapyeounphieuphkorean: 0x3184, + kapyeounpieupkorean: 0x3178, + kapyeounssangpieupkorean: 0x3179, + karoriisquare: 0x330D, + kashidaautoarabic: 0x0640, + kashidaautonosidebearingarabic: 0x0640, + kasmallkatakana: 0x30F5, + kasquare: 0x3384, + kasraarabic: 0x0650, + kasratanarabic: 0x064D, + kastrokecyrillic: 0x049F, + katahiraprolongmarkhalfwidth: 0xFF70, + kaverticalstrokecyrillic: 0x049D, + kbopomofo: 0x310E, + kcalsquare: 0x3389, + kcaron: 0x01E9, + kcedilla: 0x0137, + kcircle: 0x24DA, + kcommaaccent: 0x0137, + kdotbelow: 0x1E33, + keharmenian: 0x0584, + kehiragana: 0x3051, + kekatakana: 0x30B1, + kekatakanahalfwidth: 0xFF79, + kenarmenian: 0x056F, + kesmallkatakana: 0x30F6, + kgreenlandic: 0x0138, + khabengali: 0x0996, + khacyrillic: 0x0445, + khadeva: 0x0916, + khagujarati: 0x0A96, + khagurmukhi: 0x0A16, + khaharabic: 0x062E, + khahfinalarabic: 0xFEA6, + khahinitialarabic: 0xFEA7, + khahmedialarabic: 0xFEA8, + kheicoptic: 0x03E7, + khhadeva: 0x0959, + khhagurmukhi: 0x0A59, + khieukhacirclekorean: 0x3278, + khieukhaparenkorean: 0x3218, + khieukhcirclekorean: 0x326A, + khieukhkorean: 0x314B, + khieukhparenkorean: 0x320A, + khokhaithai: 0x0E02, + khokhonthai: 0x0E05, + khokhuatthai: 0x0E03, + khokhwaithai: 0x0E04, + khomutthai: 0x0E5B, + khook: 0x0199, + khorakhangthai: 0x0E06, + khzsquare: 0x3391, + kihiragana: 0x304D, + kikatakana: 0x30AD, + kikatakanahalfwidth: 0xFF77, + kiroguramusquare: 0x3315, + kiromeetorusquare: 0x3316, + kirosquare: 0x3314, + kiyeokacirclekorean: 0x326E, + kiyeokaparenkorean: 0x320E, + kiyeokcirclekorean: 0x3260, + kiyeokkorean: 0x3131, + kiyeokparenkorean: 0x3200, + kiyeoksioskorean: 0x3133, + kjecyrillic: 0x045C, + klinebelow: 0x1E35, + klsquare: 0x3398, + kmcubedsquare: 0x33A6, + kmonospace: 0xFF4B, + kmsquaredsquare: 0x33A2, + kohiragana: 0x3053, + kohmsquare: 0x33C0, + kokaithai: 0x0E01, + kokatakana: 0x30B3, + kokatakanahalfwidth: 0xFF7A, + kooposquare: 0x331E, + koppacyrillic: 0x0481, + koreanstandardsymbol: 0x327F, + koroniscmb: 0x0343, + kparen: 0x24A6, + kpasquare: 0x33AA, + ksicyrillic: 0x046F, + ktsquare: 0x33CF, + kturned: 0x029E, + kuhiragana: 0x304F, + kukatakana: 0x30AF, + kukatakanahalfwidth: 0xFF78, + kvsquare: 0x33B8, + kwsquare: 0x33BE, + l: 0x006C, + labengali: 0x09B2, + lacute: 0x013A, + ladeva: 0x0932, + lagujarati: 0x0AB2, + lagurmukhi: 0x0A32, + lakkhangyaothai: 0x0E45, + lamaleffinalarabic: 0xFEFC, + lamalefhamzaabovefinalarabic: 0xFEF8, + lamalefhamzaaboveisolatedarabic: 0xFEF7, + lamalefhamzabelowfinalarabic: 0xFEFA, + lamalefhamzabelowisolatedarabic: 0xFEF9, + lamalefisolatedarabic: 0xFEFB, + lamalefmaddaabovefinalarabic: 0xFEF6, + lamalefmaddaaboveisolatedarabic: 0xFEF5, + lamarabic: 0x0644, + lambda: 0x03BB, + lambdastroke: 0x019B, + lamed: 0x05DC, + lameddagesh: 0xFB3C, + lameddageshhebrew: 0xFB3C, + lamedhebrew: 0x05DC, + lamfinalarabic: 0xFEDE, + lamhahinitialarabic: 0xFCCA, + laminitialarabic: 0xFEDF, + lamjeeminitialarabic: 0xFCC9, + lamkhahinitialarabic: 0xFCCB, + lamlamhehisolatedarabic: 0xFDF2, + lammedialarabic: 0xFEE0, + lammeemhahinitialarabic: 0xFD88, + lammeeminitialarabic: 0xFCCC, + largecircle: 0x25EF, + lbar: 0x019A, + lbelt: 0x026C, + lbopomofo: 0x310C, + lcaron: 0x013E, + lcedilla: 0x013C, + lcircle: 0x24DB, + lcircumflexbelow: 0x1E3D, + lcommaaccent: 0x013C, + ldot: 0x0140, + ldotaccent: 0x0140, + ldotbelow: 0x1E37, + ldotbelowmacron: 0x1E39, + leftangleabovecmb: 0x031A, + lefttackbelowcmb: 0x0318, + less: 0x003C, + lessequal: 0x2264, + lessequalorgreater: 0x22DA, + lessmonospace: 0xFF1C, + lessorequivalent: 0x2272, + lessorgreater: 0x2276, + lessoverequal: 0x2266, + lesssmall: 0xFE64, + lezh: 0x026E, + lfblock: 0x258C, + lhookretroflex: 0x026D, + lira: 0x20A4, + liwnarmenian: 0x056C, + lj: 0x01C9, + ljecyrillic: 0x0459, + ll: 0xF6C0, + lladeva: 0x0933, + llagujarati: 0x0AB3, + llinebelow: 0x1E3B, + llladeva: 0x0934, + llvocalicbengali: 0x09E1, + llvocalicdeva: 0x0961, + llvocalicvowelsignbengali: 0x09E3, + llvocalicvowelsigndeva: 0x0963, + lmiddletilde: 0x026B, + lmonospace: 0xFF4C, + lmsquare: 0x33D0, + lochulathai: 0x0E2C, + logicaland: 0x2227, + logicalnot: 0x00AC, + logicalnotreversed: 0x2310, + logicalor: 0x2228, + lolingthai: 0x0E25, + longs: 0x017F, + lowlinecenterline: 0xFE4E, + lowlinecmb: 0x0332, + lowlinedashed: 0xFE4D, + lozenge: 0x25CA, + lparen: 0x24A7, + lslash: 0x0142, + lsquare: 0x2113, + lsuperior: 0xF6EE, + ltshade: 0x2591, + luthai: 0x0E26, + lvocalicbengali: 0x098C, + lvocalicdeva: 0x090C, + lvocalicvowelsignbengali: 0x09E2, + lvocalicvowelsigndeva: 0x0962, + lxsquare: 0x33D3, + m: 0x006D, + mabengali: 0x09AE, + macron: 0x00AF, + macronbelowcmb: 0x0331, + macroncmb: 0x0304, + macronlowmod: 0x02CD, + macronmonospace: 0xFFE3, + macute: 0x1E3F, + madeva: 0x092E, + magujarati: 0x0AAE, + magurmukhi: 0x0A2E, + mahapakhhebrew: 0x05A4, + mahapakhlefthebrew: 0x05A4, + mahiragana: 0x307E, + maichattawalowleftthai: 0xF895, + maichattawalowrightthai: 0xF894, + maichattawathai: 0x0E4B, + maichattawaupperleftthai: 0xF893, + maieklowleftthai: 0xF88C, + maieklowrightthai: 0xF88B, + maiekthai: 0x0E48, + maiekupperleftthai: 0xF88A, + maihanakatleftthai: 0xF884, + maihanakatthai: 0x0E31, + maitaikhuleftthai: 0xF889, + maitaikhuthai: 0x0E47, + maitholowleftthai: 0xF88F, + maitholowrightthai: 0xF88E, + maithothai: 0x0E49, + maithoupperleftthai: 0xF88D, + maitrilowleftthai: 0xF892, + maitrilowrightthai: 0xF891, + maitrithai: 0x0E4A, + maitriupperleftthai: 0xF890, + maiyamokthai: 0x0E46, + makatakana: 0x30DE, + makatakanahalfwidth: 0xFF8F, + male: 0x2642, + mansyonsquare: 0x3347, + maqafhebrew: 0x05BE, + mars: 0x2642, + masoracirclehebrew: 0x05AF, + masquare: 0x3383, + mbopomofo: 0x3107, + mbsquare: 0x33D4, + mcircle: 0x24DC, + mcubedsquare: 0x33A5, + mdotaccent: 0x1E41, + mdotbelow: 0x1E43, + meemarabic: 0x0645, + meemfinalarabic: 0xFEE2, + meeminitialarabic: 0xFEE3, + meemmedialarabic: 0xFEE4, + meemmeeminitialarabic: 0xFCD1, + meemmeemisolatedarabic: 0xFC48, + meetorusquare: 0x334D, + mehiragana: 0x3081, + meizierasquare: 0x337E, + mekatakana: 0x30E1, + mekatakanahalfwidth: 0xFF92, + mem: 0x05DE, + memdagesh: 0xFB3E, + memdageshhebrew: 0xFB3E, + memhebrew: 0x05DE, + menarmenian: 0x0574, + merkhahebrew: 0x05A5, + merkhakefulahebrew: 0x05A6, + merkhakefulalefthebrew: 0x05A6, + merkhalefthebrew: 0x05A5, + mhook: 0x0271, + mhzsquare: 0x3392, + middledotkatakanahalfwidth: 0xFF65, + middot: 0x00B7, + mieumacirclekorean: 0x3272, + mieumaparenkorean: 0x3212, + mieumcirclekorean: 0x3264, + mieumkorean: 0x3141, + mieumpansioskorean: 0x3170, + mieumparenkorean: 0x3204, + mieumpieupkorean: 0x316E, + mieumsioskorean: 0x316F, + mihiragana: 0x307F, + mikatakana: 0x30DF, + mikatakanahalfwidth: 0xFF90, + minus: 0x2212, + minusbelowcmb: 0x0320, + minuscircle: 0x2296, + minusmod: 0x02D7, + minusplus: 0x2213, + minute: 0x2032, + miribaarusquare: 0x334A, + mirisquare: 0x3349, + mlonglegturned: 0x0270, + mlsquare: 0x3396, + mmcubedsquare: 0x33A3, + mmonospace: 0xFF4D, + mmsquaredsquare: 0x339F, + mohiragana: 0x3082, + mohmsquare: 0x33C1, + mokatakana: 0x30E2, + mokatakanahalfwidth: 0xFF93, + molsquare: 0x33D6, + momathai: 0x0E21, + moverssquare: 0x33A7, + moverssquaredsquare: 0x33A8, + mparen: 0x24A8, + mpasquare: 0x33AB, + mssquare: 0x33B3, + msuperior: 0xF6EF, + mturned: 0x026F, + mu: 0x00B5, + mu1: 0x00B5, + muasquare: 0x3382, + muchgreater: 0x226B, + muchless: 0x226A, + mufsquare: 0x338C, + mugreek: 0x03BC, + mugsquare: 0x338D, + muhiragana: 0x3080, + mukatakana: 0x30E0, + mukatakanahalfwidth: 0xFF91, + mulsquare: 0x3395, + multiply: 0x00D7, + mumsquare: 0x339B, + munahhebrew: 0x05A3, + munahlefthebrew: 0x05A3, + musicalnote: 0x266A, + musicalnotedbl: 0x266B, + musicflatsign: 0x266D, + musicsharpsign: 0x266F, + mussquare: 0x33B2, + muvsquare: 0x33B6, + muwsquare: 0x33BC, + mvmegasquare: 0x33B9, + mvsquare: 0x33B7, + mwmegasquare: 0x33BF, + mwsquare: 0x33BD, + n: 0x006E, + nabengali: 0x09A8, + nabla: 0x2207, + nacute: 0x0144, + nadeva: 0x0928, + nagujarati: 0x0AA8, + nagurmukhi: 0x0A28, + nahiragana: 0x306A, + nakatakana: 0x30CA, + nakatakanahalfwidth: 0xFF85, + napostrophe: 0x0149, + nasquare: 0x3381, + nbopomofo: 0x310B, + nbspace: 0x00A0, + ncaron: 0x0148, + ncedilla: 0x0146, + ncircle: 0x24DD, + ncircumflexbelow: 0x1E4B, + ncommaaccent: 0x0146, + ndotaccent: 0x1E45, + ndotbelow: 0x1E47, + nehiragana: 0x306D, + nekatakana: 0x30CD, + nekatakanahalfwidth: 0xFF88, + newsheqelsign: 0x20AA, + nfsquare: 0x338B, + ngabengali: 0x0999, + ngadeva: 0x0919, + ngagujarati: 0x0A99, + ngagurmukhi: 0x0A19, + ngonguthai: 0x0E07, + nhiragana: 0x3093, + nhookleft: 0x0272, + nhookretroflex: 0x0273, + nieunacirclekorean: 0x326F, + nieunaparenkorean: 0x320F, + nieuncieuckorean: 0x3135, + nieuncirclekorean: 0x3261, + nieunhieuhkorean: 0x3136, + nieunkorean: 0x3134, + nieunpansioskorean: 0x3168, + nieunparenkorean: 0x3201, + nieunsioskorean: 0x3167, + nieuntikeutkorean: 0x3166, + nihiragana: 0x306B, + nikatakana: 0x30CB, + nikatakanahalfwidth: 0xFF86, + nikhahitleftthai: 0xF899, + nikhahitthai: 0x0E4D, + nine: 0x0039, + ninearabic: 0x0669, + ninebengali: 0x09EF, + ninecircle: 0x2468, + ninecircleinversesansserif: 0x2792, + ninedeva: 0x096F, + ninegujarati: 0x0AEF, + ninegurmukhi: 0x0A6F, + ninehackarabic: 0x0669, + ninehangzhou: 0x3029, + nineideographicparen: 0x3228, + nineinferior: 0x2089, + ninemonospace: 0xFF19, + nineoldstyle: 0xF739, + nineparen: 0x247C, + nineperiod: 0x2490, + ninepersian: 0x06F9, + nineroman: 0x2178, + ninesuperior: 0x2079, + nineteencircle: 0x2472, + nineteenparen: 0x2486, + nineteenperiod: 0x249A, + ninethai: 0x0E59, + nj: 0x01CC, + njecyrillic: 0x045A, + nkatakana: 0x30F3, + nkatakanahalfwidth: 0xFF9D, + nlegrightlong: 0x019E, + nlinebelow: 0x1E49, + nmonospace: 0xFF4E, + nmsquare: 0x339A, + nnabengali: 0x09A3, + nnadeva: 0x0923, + nnagujarati: 0x0AA3, + nnagurmukhi: 0x0A23, + nnnadeva: 0x0929, + nohiragana: 0x306E, + nokatakana: 0x30CE, + nokatakanahalfwidth: 0xFF89, + nonbreakingspace: 0x00A0, + nonenthai: 0x0E13, + nonuthai: 0x0E19, + noonarabic: 0x0646, + noonfinalarabic: 0xFEE6, + noonghunnaarabic: 0x06BA, + noonghunnafinalarabic: 0xFB9F, + nooninitialarabic: 0xFEE7, + noonjeeminitialarabic: 0xFCD2, + noonjeemisolatedarabic: 0xFC4B, + noonmedialarabic: 0xFEE8, + noonmeeminitialarabic: 0xFCD5, + noonmeemisolatedarabic: 0xFC4E, + noonnoonfinalarabic: 0xFC8D, + notcontains: 0x220C, + notelement: 0x2209, + notelementof: 0x2209, + notequal: 0x2260, + notgreater: 0x226F, + notgreaternorequal: 0x2271, + notgreaternorless: 0x2279, + notidentical: 0x2262, + notless: 0x226E, + notlessnorequal: 0x2270, + notparallel: 0x2226, + notprecedes: 0x2280, + notsubset: 0x2284, + notsucceeds: 0x2281, + notsuperset: 0x2285, + nowarmenian: 0x0576, + nparen: 0x24A9, + nssquare: 0x33B1, + nsuperior: 0x207F, + ntilde: 0x00F1, + nu: 0x03BD, + nuhiragana: 0x306C, + nukatakana: 0x30CC, + nukatakanahalfwidth: 0xFF87, + nuktabengali: 0x09BC, + nuktadeva: 0x093C, + nuktagujarati: 0x0ABC, + nuktagurmukhi: 0x0A3C, + numbersign: 0x0023, + numbersignmonospace: 0xFF03, + numbersignsmall: 0xFE5F, + numeralsigngreek: 0x0374, + numeralsignlowergreek: 0x0375, + numero: 0x2116, + nun: 0x05E0, + nundagesh: 0xFB40, + nundageshhebrew: 0xFB40, + nunhebrew: 0x05E0, + nvsquare: 0x33B5, + nwsquare: 0x33BB, + nyabengali: 0x099E, + nyadeva: 0x091E, + nyagujarati: 0x0A9E, + nyagurmukhi: 0x0A1E, + o: 0x006F, + oacute: 0x00F3, + oangthai: 0x0E2D, + obarred: 0x0275, + obarredcyrillic: 0x04E9, + obarreddieresiscyrillic: 0x04EB, + obengali: 0x0993, + obopomofo: 0x311B, + obreve: 0x014F, + ocandradeva: 0x0911, + ocandragujarati: 0x0A91, + ocandravowelsigndeva: 0x0949, + ocandravowelsigngujarati: 0x0AC9, + ocaron: 0x01D2, + ocircle: 0x24DE, + ocircumflex: 0x00F4, + ocircumflexacute: 0x1ED1, + ocircumflexdotbelow: 0x1ED9, + ocircumflexgrave: 0x1ED3, + ocircumflexhookabove: 0x1ED5, + ocircumflextilde: 0x1ED7, + ocyrillic: 0x043E, + odblacute: 0x0151, + odblgrave: 0x020D, + odeva: 0x0913, + odieresis: 0x00F6, + odieresiscyrillic: 0x04E7, + odotbelow: 0x1ECD, + oe: 0x0153, + oekorean: 0x315A, + ogonek: 0x02DB, + ogonekcmb: 0x0328, + ograve: 0x00F2, + ogujarati: 0x0A93, + oharmenian: 0x0585, + ohiragana: 0x304A, + ohookabove: 0x1ECF, + ohorn: 0x01A1, + ohornacute: 0x1EDB, + ohorndotbelow: 0x1EE3, + ohorngrave: 0x1EDD, + ohornhookabove: 0x1EDF, + ohorntilde: 0x1EE1, + ohungarumlaut: 0x0151, + oi: 0x01A3, + oinvertedbreve: 0x020F, + okatakana: 0x30AA, + okatakanahalfwidth: 0xFF75, + okorean: 0x3157, + olehebrew: 0x05AB, + omacron: 0x014D, + omacronacute: 0x1E53, + omacrongrave: 0x1E51, + omdeva: 0x0950, + omega: 0x03C9, + omega1: 0x03D6, + omegacyrillic: 0x0461, + omegalatinclosed: 0x0277, + omegaroundcyrillic: 0x047B, + omegatitlocyrillic: 0x047D, + omegatonos: 0x03CE, + omgujarati: 0x0AD0, + omicron: 0x03BF, + omicrontonos: 0x03CC, + omonospace: 0xFF4F, + one: 0x0031, + onearabic: 0x0661, + onebengali: 0x09E7, + onecircle: 0x2460, + onecircleinversesansserif: 0x278A, + onedeva: 0x0967, + onedotenleader: 0x2024, + oneeighth: 0x215B, + onefitted: 0xF6DC, + onegujarati: 0x0AE7, + onegurmukhi: 0x0A67, + onehackarabic: 0x0661, + onehalf: 0x00BD, + onehangzhou: 0x3021, + oneideographicparen: 0x3220, + oneinferior: 0x2081, + onemonospace: 0xFF11, + onenumeratorbengali: 0x09F4, + oneoldstyle: 0xF731, + oneparen: 0x2474, + oneperiod: 0x2488, + onepersian: 0x06F1, + onequarter: 0x00BC, + oneroman: 0x2170, + onesuperior: 0x00B9, + onethai: 0x0E51, + onethird: 0x2153, + oogonek: 0x01EB, + oogonekmacron: 0x01ED, + oogurmukhi: 0x0A13, + oomatragurmukhi: 0x0A4B, + oopen: 0x0254, + oparen: 0x24AA, + openbullet: 0x25E6, + option: 0x2325, + ordfeminine: 0x00AA, + ordmasculine: 0x00BA, + orthogonal: 0x221F, + oshortdeva: 0x0912, + oshortvowelsigndeva: 0x094A, + oslash: 0x00F8, + oslashacute: 0x01FF, + osmallhiragana: 0x3049, + osmallkatakana: 0x30A9, + osmallkatakanahalfwidth: 0xFF6B, + ostrokeacute: 0x01FF, + osuperior: 0xF6F0, + otcyrillic: 0x047F, + otilde: 0x00F5, + otildeacute: 0x1E4D, + otildedieresis: 0x1E4F, + oubopomofo: 0x3121, + overline: 0x203E, + overlinecenterline: 0xFE4A, + overlinecmb: 0x0305, + overlinedashed: 0xFE49, + overlinedblwavy: 0xFE4C, + overlinewavy: 0xFE4B, + overscore: 0x00AF, + ovowelsignbengali: 0x09CB, + ovowelsigndeva: 0x094B, + ovowelsigngujarati: 0x0ACB, + p: 0x0070, + paampssquare: 0x3380, + paasentosquare: 0x332B, + pabengali: 0x09AA, + pacute: 0x1E55, + padeva: 0x092A, + pagedown: 0x21DF, + pageup: 0x21DE, + pagujarati: 0x0AAA, + pagurmukhi: 0x0A2A, + pahiragana: 0x3071, + paiyannoithai: 0x0E2F, + pakatakana: 0x30D1, + palatalizationcyrilliccmb: 0x0484, + palochkacyrillic: 0x04C0, + pansioskorean: 0x317F, + paragraph: 0x00B6, + parallel: 0x2225, + parenleft: 0x0028, + parenleftaltonearabic: 0xFD3E, + parenleftbt: 0xF8ED, + parenleftex: 0xF8EC, + parenleftinferior: 0x208D, + parenleftmonospace: 0xFF08, + parenleftsmall: 0xFE59, + parenleftsuperior: 0x207D, + parenlefttp: 0xF8EB, + parenleftvertical: 0xFE35, + parenright: 0x0029, + parenrightaltonearabic: 0xFD3F, + parenrightbt: 0xF8F8, + parenrightex: 0xF8F7, + parenrightinferior: 0x208E, + parenrightmonospace: 0xFF09, + parenrightsmall: 0xFE5A, + parenrightsuperior: 0x207E, + parenrighttp: 0xF8F6, + parenrightvertical: 0xFE36, + partialdiff: 0x2202, + paseqhebrew: 0x05C0, + pashtahebrew: 0x0599, + pasquare: 0x33A9, + patah: 0x05B7, + patah11: 0x05B7, + patah1d: 0x05B7, + patah2a: 0x05B7, + patahhebrew: 0x05B7, + patahnarrowhebrew: 0x05B7, + patahquarterhebrew: 0x05B7, + patahwidehebrew: 0x05B7, + pazerhebrew: 0x05A1, + pbopomofo: 0x3106, + pcircle: 0x24DF, + pdotaccent: 0x1E57, + pe: 0x05E4, + pecyrillic: 0x043F, + pedagesh: 0xFB44, + pedageshhebrew: 0xFB44, + peezisquare: 0x333B, + pefinaldageshhebrew: 0xFB43, + peharabic: 0x067E, + peharmenian: 0x057A, + pehebrew: 0x05E4, + pehfinalarabic: 0xFB57, + pehinitialarabic: 0xFB58, + pehiragana: 0x307A, + pehmedialarabic: 0xFB59, + pekatakana: 0x30DA, + pemiddlehookcyrillic: 0x04A7, + perafehebrew: 0xFB4E, + percent: 0x0025, + percentarabic: 0x066A, + percentmonospace: 0xFF05, + percentsmall: 0xFE6A, + period: 0x002E, + periodarmenian: 0x0589, + periodcentered: 0x00B7, + periodhalfwidth: 0xFF61, + periodinferior: 0xF6E7, + periodmonospace: 0xFF0E, + periodsmall: 0xFE52, + periodsuperior: 0xF6E8, + perispomenigreekcmb: 0x0342, + perpendicular: 0x22A5, + perthousand: 0x2030, + peseta: 0x20A7, + pfsquare: 0x338A, + phabengali: 0x09AB, + phadeva: 0x092B, + phagujarati: 0x0AAB, + phagurmukhi: 0x0A2B, + phi: 0x03C6, + phi1: 0x03D5, + phieuphacirclekorean: 0x327A, + phieuphaparenkorean: 0x321A, + phieuphcirclekorean: 0x326C, + phieuphkorean: 0x314D, + phieuphparenkorean: 0x320C, + philatin: 0x0278, + phinthuthai: 0x0E3A, + phisymbolgreek: 0x03D5, + phook: 0x01A5, + phophanthai: 0x0E1E, + phophungthai: 0x0E1C, + phosamphaothai: 0x0E20, + pi: 0x03C0, + pieupacirclekorean: 0x3273, + pieupaparenkorean: 0x3213, + pieupcieuckorean: 0x3176, + pieupcirclekorean: 0x3265, + pieupkiyeokkorean: 0x3172, + pieupkorean: 0x3142, + pieupparenkorean: 0x3205, + pieupsioskiyeokkorean: 0x3174, + pieupsioskorean: 0x3144, + pieupsiostikeutkorean: 0x3175, + pieupthieuthkorean: 0x3177, + pieuptikeutkorean: 0x3173, + pihiragana: 0x3074, + pikatakana: 0x30D4, + pisymbolgreek: 0x03D6, + piwrarmenian: 0x0583, + plus: 0x002B, + plusbelowcmb: 0x031F, + pluscircle: 0x2295, + plusminus: 0x00B1, + plusmod: 0x02D6, + plusmonospace: 0xFF0B, + plussmall: 0xFE62, + plussuperior: 0x207A, + pmonospace: 0xFF50, + pmsquare: 0x33D8, + pohiragana: 0x307D, + pointingindexdownwhite: 0x261F, + pointingindexleftwhite: 0x261C, + pointingindexrightwhite: 0x261E, + pointingindexupwhite: 0x261D, + pokatakana: 0x30DD, + poplathai: 0x0E1B, + postalmark: 0x3012, + postalmarkface: 0x3020, + pparen: 0x24AB, + precedes: 0x227A, + prescription: 0x211E, + primemod: 0x02B9, + primereversed: 0x2035, + product: 0x220F, + projective: 0x2305, + prolongedkana: 0x30FC, + propellor: 0x2318, + propersubset: 0x2282, + propersuperset: 0x2283, + proportion: 0x2237, + proportional: 0x221D, + psi: 0x03C8, + psicyrillic: 0x0471, + psilipneumatacyrilliccmb: 0x0486, + pssquare: 0x33B0, + puhiragana: 0x3077, + pukatakana: 0x30D7, + pvsquare: 0x33B4, + pwsquare: 0x33BA, + q: 0x0071, + qadeva: 0x0958, + qadmahebrew: 0x05A8, + qafarabic: 0x0642, + qaffinalarabic: 0xFED6, + qafinitialarabic: 0xFED7, + qafmedialarabic: 0xFED8, + qamats: 0x05B8, + qamats10: 0x05B8, + qamats1a: 0x05B8, + qamats1c: 0x05B8, + qamats27: 0x05B8, + qamats29: 0x05B8, + qamats33: 0x05B8, + qamatsde: 0x05B8, + qamatshebrew: 0x05B8, + qamatsnarrowhebrew: 0x05B8, + qamatsqatanhebrew: 0x05B8, + qamatsqatannarrowhebrew: 0x05B8, + qamatsqatanquarterhebrew: 0x05B8, + qamatsqatanwidehebrew: 0x05B8, + qamatsquarterhebrew: 0x05B8, + qamatswidehebrew: 0x05B8, + qarneyparahebrew: 0x059F, + qbopomofo: 0x3111, + qcircle: 0x24E0, + qhook: 0x02A0, + qmonospace: 0xFF51, + qof: 0x05E7, + qofdagesh: 0xFB47, + qofdageshhebrew: 0xFB47, + qofhebrew: 0x05E7, + qparen: 0x24AC, + quarternote: 0x2669, + qubuts: 0x05BB, + qubuts18: 0x05BB, + qubuts25: 0x05BB, + qubuts31: 0x05BB, + qubutshebrew: 0x05BB, + qubutsnarrowhebrew: 0x05BB, + qubutsquarterhebrew: 0x05BB, + qubutswidehebrew: 0x05BB, + question: 0x003F, + questionarabic: 0x061F, + questionarmenian: 0x055E, + questiondown: 0x00BF, + questiondownsmall: 0xF7BF, + questiongreek: 0x037E, + questionmonospace: 0xFF1F, + questionsmall: 0xF73F, + quotedbl: 0x0022, + quotedblbase: 0x201E, + quotedblleft: 0x201C, + quotedblmonospace: 0xFF02, + quotedblprime: 0x301E, + quotedblprimereversed: 0x301D, + quotedblright: 0x201D, + quoteleft: 0x2018, + quoteleftreversed: 0x201B, + quotereversed: 0x201B, + quoteright: 0x2019, + quoterightn: 0x0149, + quotesinglbase: 0x201A, + quotesingle: 0x0027, + quotesinglemonospace: 0xFF07, + r: 0x0072, + raarmenian: 0x057C, + rabengali: 0x09B0, + racute: 0x0155, + radeva: 0x0930, + radical: 0x221A, + radicalex: 0xF8E5, + radoverssquare: 0x33AE, + radoverssquaredsquare: 0x33AF, + radsquare: 0x33AD, + rafe: 0x05BF, + rafehebrew: 0x05BF, + ragujarati: 0x0AB0, + ragurmukhi: 0x0A30, + rahiragana: 0x3089, + rakatakana: 0x30E9, + rakatakanahalfwidth: 0xFF97, + ralowerdiagonalbengali: 0x09F1, + ramiddlediagonalbengali: 0x09F0, + ramshorn: 0x0264, + ratio: 0x2236, + rbopomofo: 0x3116, + rcaron: 0x0159, + rcedilla: 0x0157, + rcircle: 0x24E1, + rcommaaccent: 0x0157, + rdblgrave: 0x0211, + rdotaccent: 0x1E59, + rdotbelow: 0x1E5B, + rdotbelowmacron: 0x1E5D, + referencemark: 0x203B, + reflexsubset: 0x2286, + reflexsuperset: 0x2287, + registered: 0x00AE, + registersans: 0xF8E8, + registerserif: 0xF6DA, + reharabic: 0x0631, + reharmenian: 0x0580, + rehfinalarabic: 0xFEAE, + rehiragana: 0x308C, + rekatakana: 0x30EC, + rekatakanahalfwidth: 0xFF9A, + resh: 0x05E8, + reshdageshhebrew: 0xFB48, + reshhebrew: 0x05E8, + reversedtilde: 0x223D, + reviahebrew: 0x0597, + reviamugrashhebrew: 0x0597, + revlogicalnot: 0x2310, + rfishhook: 0x027E, + rfishhookreversed: 0x027F, + rhabengali: 0x09DD, + rhadeva: 0x095D, + rho: 0x03C1, + rhook: 0x027D, + rhookturned: 0x027B, + rhookturnedsuperior: 0x02B5, + rhosymbolgreek: 0x03F1, + rhotichookmod: 0x02DE, + rieulacirclekorean: 0x3271, + rieulaparenkorean: 0x3211, + rieulcirclekorean: 0x3263, + rieulhieuhkorean: 0x3140, + rieulkiyeokkorean: 0x313A, + rieulkiyeoksioskorean: 0x3169, + rieulkorean: 0x3139, + rieulmieumkorean: 0x313B, + rieulpansioskorean: 0x316C, + rieulparenkorean: 0x3203, + rieulphieuphkorean: 0x313F, + rieulpieupkorean: 0x313C, + rieulpieupsioskorean: 0x316B, + rieulsioskorean: 0x313D, + rieulthieuthkorean: 0x313E, + rieultikeutkorean: 0x316A, + rieulyeorinhieuhkorean: 0x316D, + rightangle: 0x221F, + righttackbelowcmb: 0x0319, + righttriangle: 0x22BF, + rihiragana: 0x308A, + rikatakana: 0x30EA, + rikatakanahalfwidth: 0xFF98, + ring: 0x02DA, + ringbelowcmb: 0x0325, + ringcmb: 0x030A, + ringhalfleft: 0x02BF, + ringhalfleftarmenian: 0x0559, + ringhalfleftbelowcmb: 0x031C, + ringhalfleftcentered: 0x02D3, + ringhalfright: 0x02BE, + ringhalfrightbelowcmb: 0x0339, + ringhalfrightcentered: 0x02D2, + rinvertedbreve: 0x0213, + rittorusquare: 0x3351, + rlinebelow: 0x1E5F, + rlongleg: 0x027C, + rlonglegturned: 0x027A, + rmonospace: 0xFF52, + rohiragana: 0x308D, + rokatakana: 0x30ED, + rokatakanahalfwidth: 0xFF9B, + roruathai: 0x0E23, + rparen: 0x24AD, + rrabengali: 0x09DC, + rradeva: 0x0931, + rragurmukhi: 0x0A5C, + rreharabic: 0x0691, + rrehfinalarabic: 0xFB8D, + rrvocalicbengali: 0x09E0, + rrvocalicdeva: 0x0960, + rrvocalicgujarati: 0x0AE0, + rrvocalicvowelsignbengali: 0x09C4, + rrvocalicvowelsigndeva: 0x0944, + rrvocalicvowelsigngujarati: 0x0AC4, + rsuperior: 0xF6F1, + rtblock: 0x2590, + rturned: 0x0279, + rturnedsuperior: 0x02B4, + ruhiragana: 0x308B, + rukatakana: 0x30EB, + rukatakanahalfwidth: 0xFF99, + rupeemarkbengali: 0x09F2, + rupeesignbengali: 0x09F3, + rupiah: 0xF6DD, + ruthai: 0x0E24, + rvocalicbengali: 0x098B, + rvocalicdeva: 0x090B, + rvocalicgujarati: 0x0A8B, + rvocalicvowelsignbengali: 0x09C3, + rvocalicvowelsigndeva: 0x0943, + rvocalicvowelsigngujarati: 0x0AC3, + s: 0x0073, + sabengali: 0x09B8, + sacute: 0x015B, + sacutedotaccent: 0x1E65, + sadarabic: 0x0635, + sadeva: 0x0938, + sadfinalarabic: 0xFEBA, + sadinitialarabic: 0xFEBB, + sadmedialarabic: 0xFEBC, + sagujarati: 0x0AB8, + sagurmukhi: 0x0A38, + sahiragana: 0x3055, + sakatakana: 0x30B5, + sakatakanahalfwidth: 0xFF7B, + sallallahoualayhewasallamarabic: 0xFDFA, + samekh: 0x05E1, + samekhdagesh: 0xFB41, + samekhdageshhebrew: 0xFB41, + samekhhebrew: 0x05E1, + saraaathai: 0x0E32, + saraaethai: 0x0E41, + saraaimaimalaithai: 0x0E44, + saraaimaimuanthai: 0x0E43, + saraamthai: 0x0E33, + saraathai: 0x0E30, + saraethai: 0x0E40, + saraiileftthai: 0xF886, + saraiithai: 0x0E35, + saraileftthai: 0xF885, + saraithai: 0x0E34, + saraothai: 0x0E42, + saraueeleftthai: 0xF888, + saraueethai: 0x0E37, + saraueleftthai: 0xF887, + sarauethai: 0x0E36, + sarauthai: 0x0E38, + sarauuthai: 0x0E39, + sbopomofo: 0x3119, + scaron: 0x0161, + scarondotaccent: 0x1E67, + scedilla: 0x015F, + schwa: 0x0259, + schwacyrillic: 0x04D9, + schwadieresiscyrillic: 0x04DB, + schwahook: 0x025A, + scircle: 0x24E2, + scircumflex: 0x015D, + scommaaccent: 0x0219, + sdotaccent: 0x1E61, + sdotbelow: 0x1E63, + sdotbelowdotaccent: 0x1E69, + seagullbelowcmb: 0x033C, + second: 0x2033, + secondtonechinese: 0x02CA, + section: 0x00A7, + seenarabic: 0x0633, + seenfinalarabic: 0xFEB2, + seeninitialarabic: 0xFEB3, + seenmedialarabic: 0xFEB4, + segol: 0x05B6, + segol13: 0x05B6, + segol1f: 0x05B6, + segol2c: 0x05B6, + segolhebrew: 0x05B6, + segolnarrowhebrew: 0x05B6, + segolquarterhebrew: 0x05B6, + segoltahebrew: 0x0592, + segolwidehebrew: 0x05B6, + seharmenian: 0x057D, + sehiragana: 0x305B, + sekatakana: 0x30BB, + sekatakanahalfwidth: 0xFF7E, + semicolon: 0x003B, + semicolonarabic: 0x061B, + semicolonmonospace: 0xFF1B, + semicolonsmall: 0xFE54, + semivoicedmarkkana: 0x309C, + semivoicedmarkkanahalfwidth: 0xFF9F, + sentisquare: 0x3322, + sentosquare: 0x3323, + seven: 0x0037, + sevenarabic: 0x0667, + sevenbengali: 0x09ED, + sevencircle: 0x2466, + sevencircleinversesansserif: 0x2790, + sevendeva: 0x096D, + seveneighths: 0x215E, + sevengujarati: 0x0AED, + sevengurmukhi: 0x0A6D, + sevenhackarabic: 0x0667, + sevenhangzhou: 0x3027, + sevenideographicparen: 0x3226, + seveninferior: 0x2087, + sevenmonospace: 0xFF17, + sevenoldstyle: 0xF737, + sevenparen: 0x247A, + sevenperiod: 0x248E, + sevenpersian: 0x06F7, + sevenroman: 0x2176, + sevensuperior: 0x2077, + seventeencircle: 0x2470, + seventeenparen: 0x2484, + seventeenperiod: 0x2498, + seventhai: 0x0E57, + sfthyphen: 0x00AD, + shaarmenian: 0x0577, + shabengali: 0x09B6, + shacyrillic: 0x0448, + shaddaarabic: 0x0651, + shaddadammaarabic: 0xFC61, + shaddadammatanarabic: 0xFC5E, + shaddafathaarabic: 0xFC60, + shaddakasraarabic: 0xFC62, + shaddakasratanarabic: 0xFC5F, + shade: 0x2592, + shadedark: 0x2593, + shadelight: 0x2591, + shademedium: 0x2592, + shadeva: 0x0936, + shagujarati: 0x0AB6, + shagurmukhi: 0x0A36, + shalshelethebrew: 0x0593, + shbopomofo: 0x3115, + shchacyrillic: 0x0449, + sheenarabic: 0x0634, + sheenfinalarabic: 0xFEB6, + sheeninitialarabic: 0xFEB7, + sheenmedialarabic: 0xFEB8, + sheicoptic: 0x03E3, + sheqel: 0x20AA, + sheqelhebrew: 0x20AA, + sheva: 0x05B0, + sheva115: 0x05B0, + sheva15: 0x05B0, + sheva22: 0x05B0, + sheva2e: 0x05B0, + shevahebrew: 0x05B0, + shevanarrowhebrew: 0x05B0, + shevaquarterhebrew: 0x05B0, + shevawidehebrew: 0x05B0, + shhacyrillic: 0x04BB, + shimacoptic: 0x03ED, + shin: 0x05E9, + shindagesh: 0xFB49, + shindageshhebrew: 0xFB49, + shindageshshindot: 0xFB2C, + shindageshshindothebrew: 0xFB2C, + shindageshsindot: 0xFB2D, + shindageshsindothebrew: 0xFB2D, + shindothebrew: 0x05C1, + shinhebrew: 0x05E9, + shinshindot: 0xFB2A, + shinshindothebrew: 0xFB2A, + shinsindot: 0xFB2B, + shinsindothebrew: 0xFB2B, + shook: 0x0282, + sigma: 0x03C3, + sigma1: 0x03C2, + sigmafinal: 0x03C2, + sigmalunatesymbolgreek: 0x03F2, + sihiragana: 0x3057, + sikatakana: 0x30B7, + sikatakanahalfwidth: 0xFF7C, + siluqhebrew: 0x05BD, + siluqlefthebrew: 0x05BD, + similar: 0x223C, + sindothebrew: 0x05C2, + siosacirclekorean: 0x3274, + siosaparenkorean: 0x3214, + sioscieuckorean: 0x317E, + sioscirclekorean: 0x3266, + sioskiyeokkorean: 0x317A, + sioskorean: 0x3145, + siosnieunkorean: 0x317B, + siosparenkorean: 0x3206, + siospieupkorean: 0x317D, + siostikeutkorean: 0x317C, + six: 0x0036, + sixarabic: 0x0666, + sixbengali: 0x09EC, + sixcircle: 0x2465, + sixcircleinversesansserif: 0x278F, + sixdeva: 0x096C, + sixgujarati: 0x0AEC, + sixgurmukhi: 0x0A6C, + sixhackarabic: 0x0666, + sixhangzhou: 0x3026, + sixideographicparen: 0x3225, + sixinferior: 0x2086, + sixmonospace: 0xFF16, + sixoldstyle: 0xF736, + sixparen: 0x2479, + sixperiod: 0x248D, + sixpersian: 0x06F6, + sixroman: 0x2175, + sixsuperior: 0x2076, + sixteencircle: 0x246F, + sixteencurrencydenominatorbengali: 0x09F9, + sixteenparen: 0x2483, + sixteenperiod: 0x2497, + sixthai: 0x0E56, + slash: 0x002F, + slashmonospace: 0xFF0F, + slong: 0x017F, + slongdotaccent: 0x1E9B, + smileface: 0x263A, + smonospace: 0xFF53, + sofpasuqhebrew: 0x05C3, + softhyphen: 0x00AD, + softsigncyrillic: 0x044C, + sohiragana: 0x305D, + sokatakana: 0x30BD, + sokatakanahalfwidth: 0xFF7F, + soliduslongoverlaycmb: 0x0338, + solidusshortoverlaycmb: 0x0337, + sorusithai: 0x0E29, + sosalathai: 0x0E28, + sosothai: 0x0E0B, + sosuathai: 0x0E2A, + space: 0x0020, + spacehackarabic: 0x0020, + spade: 0x2660, + spadesuitblack: 0x2660, + spadesuitwhite: 0x2664, + sparen: 0x24AE, + squarebelowcmb: 0x033B, + squarecc: 0x33C4, + squarecm: 0x339D, + squarediagonalcrosshatchfill: 0x25A9, + squarehorizontalfill: 0x25A4, + squarekg: 0x338F, + squarekm: 0x339E, + squarekmcapital: 0x33CE, + squareln: 0x33D1, + squarelog: 0x33D2, + squaremg: 0x338E, + squaremil: 0x33D5, + squaremm: 0x339C, + squaremsquared: 0x33A1, + squareorthogonalcrosshatchfill: 0x25A6, + squareupperlefttolowerrightfill: 0x25A7, + squareupperrighttolowerleftfill: 0x25A8, + squareverticalfill: 0x25A5, + squarewhitewithsmallblack: 0x25A3, + srsquare: 0x33DB, + ssabengali: 0x09B7, + ssadeva: 0x0937, + ssagujarati: 0x0AB7, + ssangcieuckorean: 0x3149, + ssanghieuhkorean: 0x3185, + ssangieungkorean: 0x3180, + ssangkiyeokkorean: 0x3132, + ssangnieunkorean: 0x3165, + ssangpieupkorean: 0x3143, + ssangsioskorean: 0x3146, + ssangtikeutkorean: 0x3138, + ssuperior: 0xF6F2, + sterling: 0x00A3, + sterlingmonospace: 0xFFE1, + strokelongoverlaycmb: 0x0336, + strokeshortoverlaycmb: 0x0335, + subset: 0x2282, + subsetnotequal: 0x228A, + subsetorequal: 0x2286, + succeeds: 0x227B, + suchthat: 0x220B, + suhiragana: 0x3059, + sukatakana: 0x30B9, + sukatakanahalfwidth: 0xFF7D, + sukunarabic: 0x0652, + summation: 0x2211, + sun: 0x263C, + superset: 0x2283, + supersetnotequal: 0x228B, + supersetorequal: 0x2287, + svsquare: 0x33DC, + syouwaerasquare: 0x337C, + t: 0x0074, + tabengali: 0x09A4, + tackdown: 0x22A4, + tackleft: 0x22A3, + tadeva: 0x0924, + tagujarati: 0x0AA4, + tagurmukhi: 0x0A24, + taharabic: 0x0637, + tahfinalarabic: 0xFEC2, + tahinitialarabic: 0xFEC3, + tahiragana: 0x305F, + tahmedialarabic: 0xFEC4, + taisyouerasquare: 0x337D, + takatakana: 0x30BF, + takatakanahalfwidth: 0xFF80, + tatweelarabic: 0x0640, + tau: 0x03C4, + tav: 0x05EA, + tavdages: 0xFB4A, + tavdagesh: 0xFB4A, + tavdageshhebrew: 0xFB4A, + tavhebrew: 0x05EA, + tbar: 0x0167, + tbopomofo: 0x310A, + tcaron: 0x0165, + tccurl: 0x02A8, + tcedilla: 0x0163, + tcheharabic: 0x0686, + tchehfinalarabic: 0xFB7B, + tchehinitialarabic: 0xFB7C, + tchehmedialarabic: 0xFB7D, + tcircle: 0x24E3, + tcircumflexbelow: 0x1E71, + tcommaaccent: 0x0163, + tdieresis: 0x1E97, + tdotaccent: 0x1E6B, + tdotbelow: 0x1E6D, + tecyrillic: 0x0442, + tedescendercyrillic: 0x04AD, + teharabic: 0x062A, + tehfinalarabic: 0xFE96, + tehhahinitialarabic: 0xFCA2, + tehhahisolatedarabic: 0xFC0C, + tehinitialarabic: 0xFE97, + tehiragana: 0x3066, + tehjeeminitialarabic: 0xFCA1, + tehjeemisolatedarabic: 0xFC0B, + tehmarbutaarabic: 0x0629, + tehmarbutafinalarabic: 0xFE94, + tehmedialarabic: 0xFE98, + tehmeeminitialarabic: 0xFCA4, + tehmeemisolatedarabic: 0xFC0E, + tehnoonfinalarabic: 0xFC73, + tekatakana: 0x30C6, + tekatakanahalfwidth: 0xFF83, + telephone: 0x2121, + telephoneblack: 0x260E, + telishagedolahebrew: 0x05A0, + telishaqetanahebrew: 0x05A9, + tencircle: 0x2469, + tenideographicparen: 0x3229, + tenparen: 0x247D, + tenperiod: 0x2491, + tenroman: 0x2179, + tesh: 0x02A7, + tet: 0x05D8, + tetdagesh: 0xFB38, + tetdageshhebrew: 0xFB38, + tethebrew: 0x05D8, + tetsecyrillic: 0x04B5, + tevirhebrew: 0x059B, + tevirlefthebrew: 0x059B, + thabengali: 0x09A5, + thadeva: 0x0925, + thagujarati: 0x0AA5, + thagurmukhi: 0x0A25, + thalarabic: 0x0630, + thalfinalarabic: 0xFEAC, + thanthakhatlowleftthai: 0xF898, + thanthakhatlowrightthai: 0xF897, + thanthakhatthai: 0x0E4C, + thanthakhatupperleftthai: 0xF896, + theharabic: 0x062B, + thehfinalarabic: 0xFE9A, + thehinitialarabic: 0xFE9B, + thehmedialarabic: 0xFE9C, + thereexists: 0x2203, + therefore: 0x2234, + theta: 0x03B8, + theta1: 0x03D1, + thetasymbolgreek: 0x03D1, + thieuthacirclekorean: 0x3279, + thieuthaparenkorean: 0x3219, + thieuthcirclekorean: 0x326B, + thieuthkorean: 0x314C, + thieuthparenkorean: 0x320B, + thirteencircle: 0x246C, + thirteenparen: 0x2480, + thirteenperiod: 0x2494, + thonangmonthothai: 0x0E11, + thook: 0x01AD, + thophuthaothai: 0x0E12, + thorn: 0x00FE, + thothahanthai: 0x0E17, + thothanthai: 0x0E10, + thothongthai: 0x0E18, + thothungthai: 0x0E16, + thousandcyrillic: 0x0482, + thousandsseparatorarabic: 0x066C, + thousandsseparatorpersian: 0x066C, + three: 0x0033, + threearabic: 0x0663, + threebengali: 0x09E9, + threecircle: 0x2462, + threecircleinversesansserif: 0x278C, + threedeva: 0x0969, + threeeighths: 0x215C, + threegujarati: 0x0AE9, + threegurmukhi: 0x0A69, + threehackarabic: 0x0663, + threehangzhou: 0x3023, + threeideographicparen: 0x3222, + threeinferior: 0x2083, + threemonospace: 0xFF13, + threenumeratorbengali: 0x09F6, + threeoldstyle: 0xF733, + threeparen: 0x2476, + threeperiod: 0x248A, + threepersian: 0x06F3, + threequarters: 0x00BE, + threequartersemdash: 0xF6DE, + threeroman: 0x2172, + threesuperior: 0x00B3, + threethai: 0x0E53, + thzsquare: 0x3394, + tihiragana: 0x3061, + tikatakana: 0x30C1, + tikatakanahalfwidth: 0xFF81, + tikeutacirclekorean: 0x3270, + tikeutaparenkorean: 0x3210, + tikeutcirclekorean: 0x3262, + tikeutkorean: 0x3137, + tikeutparenkorean: 0x3202, + tilde: 0x02DC, + tildebelowcmb: 0x0330, + tildecmb: 0x0303, + tildecomb: 0x0303, + tildedoublecmb: 0x0360, + tildeoperator: 0x223C, + tildeoverlaycmb: 0x0334, + tildeverticalcmb: 0x033E, + timescircle: 0x2297, + tipehahebrew: 0x0596, + tipehalefthebrew: 0x0596, + tippigurmukhi: 0x0A70, + titlocyrilliccmb: 0x0483, + tiwnarmenian: 0x057F, + tlinebelow: 0x1E6F, + tmonospace: 0xFF54, + toarmenian: 0x0569, + tohiragana: 0x3068, + tokatakana: 0x30C8, + tokatakanahalfwidth: 0xFF84, + tonebarextrahighmod: 0x02E5, + tonebarextralowmod: 0x02E9, + tonebarhighmod: 0x02E6, + tonebarlowmod: 0x02E8, + tonebarmidmod: 0x02E7, + tonefive: 0x01BD, + tonesix: 0x0185, + tonetwo: 0x01A8, + tonos: 0x0384, + tonsquare: 0x3327, + topatakthai: 0x0E0F, + tortoiseshellbracketleft: 0x3014, + tortoiseshellbracketleftsmall: 0xFE5D, + tortoiseshellbracketleftvertical: 0xFE39, + tortoiseshellbracketright: 0x3015, + tortoiseshellbracketrightsmall: 0xFE5E, + tortoiseshellbracketrightvertical: 0xFE3A, + totaothai: 0x0E15, + tpalatalhook: 0x01AB, + tparen: 0x24AF, + trademark: 0x2122, + trademarksans: 0xF8EA, + trademarkserif: 0xF6DB, + tretroflexhook: 0x0288, + triagdn: 0x25BC, + triaglf: 0x25C4, + triagrt: 0x25BA, + triagup: 0x25B2, + ts: 0x02A6, + tsadi: 0x05E6, + tsadidagesh: 0xFB46, + tsadidageshhebrew: 0xFB46, + tsadihebrew: 0x05E6, + tsecyrillic: 0x0446, + tsere: 0x05B5, + tsere12: 0x05B5, + tsere1e: 0x05B5, + tsere2b: 0x05B5, + tserehebrew: 0x05B5, + tserenarrowhebrew: 0x05B5, + tserequarterhebrew: 0x05B5, + tserewidehebrew: 0x05B5, + tshecyrillic: 0x045B, + tsuperior: 0xF6F3, + ttabengali: 0x099F, + ttadeva: 0x091F, + ttagujarati: 0x0A9F, + ttagurmukhi: 0x0A1F, + tteharabic: 0x0679, + ttehfinalarabic: 0xFB67, + ttehinitialarabic: 0xFB68, + ttehmedialarabic: 0xFB69, + tthabengali: 0x09A0, + tthadeva: 0x0920, + tthagujarati: 0x0AA0, + tthagurmukhi: 0x0A20, + tturned: 0x0287, + tuhiragana: 0x3064, + tukatakana: 0x30C4, + tukatakanahalfwidth: 0xFF82, + tusmallhiragana: 0x3063, + tusmallkatakana: 0x30C3, + tusmallkatakanahalfwidth: 0xFF6F, + twelvecircle: 0x246B, + twelveparen: 0x247F, + twelveperiod: 0x2493, + twelveroman: 0x217B, + twentycircle: 0x2473, + twentyhangzhou: 0x5344, + twentyparen: 0x2487, + twentyperiod: 0x249B, + two: 0x0032, + twoarabic: 0x0662, + twobengali: 0x09E8, + twocircle: 0x2461, + twocircleinversesansserif: 0x278B, + twodeva: 0x0968, + twodotenleader: 0x2025, + twodotleader: 0x2025, + twodotleadervertical: 0xFE30, + twogujarati: 0x0AE8, + twogurmukhi: 0x0A68, + twohackarabic: 0x0662, + twohangzhou: 0x3022, + twoideographicparen: 0x3221, + twoinferior: 0x2082, + twomonospace: 0xFF12, + twonumeratorbengali: 0x09F5, + twooldstyle: 0xF732, + twoparen: 0x2475, + twoperiod: 0x2489, + twopersian: 0x06F2, + tworoman: 0x2171, + twostroke: 0x01BB, + twosuperior: 0x00B2, + twothai: 0x0E52, + twothirds: 0x2154, + u: 0x0075, + uacute: 0x00FA, + ubar: 0x0289, + ubengali: 0x0989, + ubopomofo: 0x3128, + ubreve: 0x016D, + ucaron: 0x01D4, + ucircle: 0x24E4, + ucircumflex: 0x00FB, + ucircumflexbelow: 0x1E77, + ucyrillic: 0x0443, + udattadeva: 0x0951, + udblacute: 0x0171, + udblgrave: 0x0215, + udeva: 0x0909, + udieresis: 0x00FC, + udieresisacute: 0x01D8, + udieresisbelow: 0x1E73, + udieresiscaron: 0x01DA, + udieresiscyrillic: 0x04F1, + udieresisgrave: 0x01DC, + udieresismacron: 0x01D6, + udotbelow: 0x1EE5, + ugrave: 0x00F9, + ugujarati: 0x0A89, + ugurmukhi: 0x0A09, + uhiragana: 0x3046, + uhookabove: 0x1EE7, + uhorn: 0x01B0, + uhornacute: 0x1EE9, + uhorndotbelow: 0x1EF1, + uhorngrave: 0x1EEB, + uhornhookabove: 0x1EED, + uhorntilde: 0x1EEF, + uhungarumlaut: 0x0171, + uhungarumlautcyrillic: 0x04F3, + uinvertedbreve: 0x0217, + ukatakana: 0x30A6, + ukatakanahalfwidth: 0xFF73, + ukcyrillic: 0x0479, + ukorean: 0x315C, + umacron: 0x016B, + umacroncyrillic: 0x04EF, + umacrondieresis: 0x1E7B, + umatragurmukhi: 0x0A41, + umonospace: 0xFF55, + underscore: 0x005F, + underscoredbl: 0x2017, + underscoremonospace: 0xFF3F, + underscorevertical: 0xFE33, + underscorewavy: 0xFE4F, + union: 0x222A, + universal: 0x2200, + uogonek: 0x0173, + uparen: 0x24B0, + upblock: 0x2580, + upperdothebrew: 0x05C4, + upsilon: 0x03C5, + upsilondieresis: 0x03CB, + upsilondieresistonos: 0x03B0, + upsilonlatin: 0x028A, + upsilontonos: 0x03CD, + uptackbelowcmb: 0x031D, + uptackmod: 0x02D4, + uragurmukhi: 0x0A73, + uring: 0x016F, + ushortcyrillic: 0x045E, + usmallhiragana: 0x3045, + usmallkatakana: 0x30A5, + usmallkatakanahalfwidth: 0xFF69, + ustraightcyrillic: 0x04AF, + ustraightstrokecyrillic: 0x04B1, + utilde: 0x0169, + utildeacute: 0x1E79, + utildebelow: 0x1E75, + uubengali: 0x098A, + uudeva: 0x090A, + uugujarati: 0x0A8A, + uugurmukhi: 0x0A0A, + uumatragurmukhi: 0x0A42, + uuvowelsignbengali: 0x09C2, + uuvowelsigndeva: 0x0942, + uuvowelsigngujarati: 0x0AC2, + uvowelsignbengali: 0x09C1, + uvowelsigndeva: 0x0941, + uvowelsigngujarati: 0x0AC1, + v: 0x0076, + vadeva: 0x0935, + vagujarati: 0x0AB5, + vagurmukhi: 0x0A35, + vakatakana: 0x30F7, + vav: 0x05D5, + vavdagesh: 0xFB35, + vavdagesh65: 0xFB35, + vavdageshhebrew: 0xFB35, + vavhebrew: 0x05D5, + vavholam: 0xFB4B, + vavholamhebrew: 0xFB4B, + vavvavhebrew: 0x05F0, + vavyodhebrew: 0x05F1, + vcircle: 0x24E5, + vdotbelow: 0x1E7F, + vecyrillic: 0x0432, + veharabic: 0x06A4, + vehfinalarabic: 0xFB6B, + vehinitialarabic: 0xFB6C, + vehmedialarabic: 0xFB6D, + vekatakana: 0x30F9, + venus: 0x2640, + verticalbar: 0x007C, + verticallineabovecmb: 0x030D, + verticallinebelowcmb: 0x0329, + verticallinelowmod: 0x02CC, + verticallinemod: 0x02C8, + vewarmenian: 0x057E, + vhook: 0x028B, + vikatakana: 0x30F8, + viramabengali: 0x09CD, + viramadeva: 0x094D, + viramagujarati: 0x0ACD, + visargabengali: 0x0983, + visargadeva: 0x0903, + visargagujarati: 0x0A83, + vmonospace: 0xFF56, + voarmenian: 0x0578, + voicediterationhiragana: 0x309E, + voicediterationkatakana: 0x30FE, + voicedmarkkana: 0x309B, + voicedmarkkanahalfwidth: 0xFF9E, + vokatakana: 0x30FA, + vparen: 0x24B1, + vtilde: 0x1E7D, + vturned: 0x028C, + vuhiragana: 0x3094, + vukatakana: 0x30F4, + w: 0x0077, + wacute: 0x1E83, + waekorean: 0x3159, + wahiragana: 0x308F, + wakatakana: 0x30EF, + wakatakanahalfwidth: 0xFF9C, + wakorean: 0x3158, + wasmallhiragana: 0x308E, + wasmallkatakana: 0x30EE, + wattosquare: 0x3357, + wavedash: 0x301C, + wavyunderscorevertical: 0xFE34, + wawarabic: 0x0648, + wawfinalarabic: 0xFEEE, + wawhamzaabovearabic: 0x0624, + wawhamzaabovefinalarabic: 0xFE86, + wbsquare: 0x33DD, + wcircle: 0x24E6, + wcircumflex: 0x0175, + wdieresis: 0x1E85, + wdotaccent: 0x1E87, + wdotbelow: 0x1E89, + wehiragana: 0x3091, + weierstrass: 0x2118, + wekatakana: 0x30F1, + wekorean: 0x315E, + weokorean: 0x315D, + wgrave: 0x1E81, + whitebullet: 0x25E6, + whitecircle: 0x25CB, + whitecircleinverse: 0x25D9, + whitecornerbracketleft: 0x300E, + whitecornerbracketleftvertical: 0xFE43, + whitecornerbracketright: 0x300F, + whitecornerbracketrightvertical: 0xFE44, + whitediamond: 0x25C7, + whitediamondcontainingblacksmalldiamond: 0x25C8, + whitedownpointingsmalltriangle: 0x25BF, + whitedownpointingtriangle: 0x25BD, + whiteleftpointingsmalltriangle: 0x25C3, + whiteleftpointingtriangle: 0x25C1, + whitelenticularbracketleft: 0x3016, + whitelenticularbracketright: 0x3017, + whiterightpointingsmalltriangle: 0x25B9, + whiterightpointingtriangle: 0x25B7, + whitesmallsquare: 0x25AB, + whitesmilingface: 0x263A, + whitesquare: 0x25A1, + whitestar: 0x2606, + whitetelephone: 0x260F, + whitetortoiseshellbracketleft: 0x3018, + whitetortoiseshellbracketright: 0x3019, + whiteuppointingsmalltriangle: 0x25B5, + whiteuppointingtriangle: 0x25B3, + wihiragana: 0x3090, + wikatakana: 0x30F0, + wikorean: 0x315F, + wmonospace: 0xFF57, + wohiragana: 0x3092, + wokatakana: 0x30F2, + wokatakanahalfwidth: 0xFF66, + won: 0x20A9, + wonmonospace: 0xFFE6, + wowaenthai: 0x0E27, + wparen: 0x24B2, + wring: 0x1E98, + wsuperior: 0x02B7, + wturned: 0x028D, + wynn: 0x01BF, + x: 0x0078, + xabovecmb: 0x033D, + xbopomofo: 0x3112, + xcircle: 0x24E7, + xdieresis: 0x1E8D, + xdotaccent: 0x1E8B, + xeharmenian: 0x056D, + xi: 0x03BE, + xmonospace: 0xFF58, + xparen: 0x24B3, + xsuperior: 0x02E3, + y: 0x0079, + yaadosquare: 0x334E, + yabengali: 0x09AF, + yacute: 0x00FD, + yadeva: 0x092F, + yaekorean: 0x3152, + yagujarati: 0x0AAF, + yagurmukhi: 0x0A2F, + yahiragana: 0x3084, + yakatakana: 0x30E4, + yakatakanahalfwidth: 0xFF94, + yakorean: 0x3151, + yamakkanthai: 0x0E4E, + yasmallhiragana: 0x3083, + yasmallkatakana: 0x30E3, + yasmallkatakanahalfwidth: 0xFF6C, + yatcyrillic: 0x0463, + ycircle: 0x24E8, + ycircumflex: 0x0177, + ydieresis: 0x00FF, + ydotaccent: 0x1E8F, + ydotbelow: 0x1EF5, + yeharabic: 0x064A, + yehbarreearabic: 0x06D2, + yehbarreefinalarabic: 0xFBAF, + yehfinalarabic: 0xFEF2, + yehhamzaabovearabic: 0x0626, + yehhamzaabovefinalarabic: 0xFE8A, + yehhamzaaboveinitialarabic: 0xFE8B, + yehhamzaabovemedialarabic: 0xFE8C, + yehinitialarabic: 0xFEF3, + yehmedialarabic: 0xFEF4, + yehmeeminitialarabic: 0xFCDD, + yehmeemisolatedarabic: 0xFC58, + yehnoonfinalarabic: 0xFC94, + yehthreedotsbelowarabic: 0x06D1, + yekorean: 0x3156, + yen: 0x00A5, + yenmonospace: 0xFFE5, + yeokorean: 0x3155, + yeorinhieuhkorean: 0x3186, + yerahbenyomohebrew: 0x05AA, + yerahbenyomolefthebrew: 0x05AA, + yericyrillic: 0x044B, + yerudieresiscyrillic: 0x04F9, + yesieungkorean: 0x3181, + yesieungpansioskorean: 0x3183, + yesieungsioskorean: 0x3182, + yetivhebrew: 0x059A, + ygrave: 0x1EF3, + yhook: 0x01B4, + yhookabove: 0x1EF7, + yiarmenian: 0x0575, + yicyrillic: 0x0457, + yikorean: 0x3162, + yinyang: 0x262F, + yiwnarmenian: 0x0582, + ymonospace: 0xFF59, + yod: 0x05D9, + yoddagesh: 0xFB39, + yoddageshhebrew: 0xFB39, + yodhebrew: 0x05D9, + yodyodhebrew: 0x05F2, + yodyodpatahhebrew: 0xFB1F, + yohiragana: 0x3088, + yoikorean: 0x3189, + yokatakana: 0x30E8, + yokatakanahalfwidth: 0xFF96, + yokorean: 0x315B, + yosmallhiragana: 0x3087, + yosmallkatakana: 0x30E7, + yosmallkatakanahalfwidth: 0xFF6E, + yotgreek: 0x03F3, + yoyaekorean: 0x3188, + yoyakorean: 0x3187, + yoyakthai: 0x0E22, + yoyingthai: 0x0E0D, + yparen: 0x24B4, + ypogegrammeni: 0x037A, + ypogegrammenigreekcmb: 0x0345, + yr: 0x01A6, + yring: 0x1E99, + ysuperior: 0x02B8, + ytilde: 0x1EF9, + yturned: 0x028E, + yuhiragana: 0x3086, + yuikorean: 0x318C, + yukatakana: 0x30E6, + yukatakanahalfwidth: 0xFF95, + yukorean: 0x3160, + yusbigcyrillic: 0x046B, + yusbigiotifiedcyrillic: 0x046D, + yuslittlecyrillic: 0x0467, + yuslittleiotifiedcyrillic: 0x0469, + yusmallhiragana: 0x3085, + yusmallkatakana: 0x30E5, + yusmallkatakanahalfwidth: 0xFF6D, + yuyekorean: 0x318B, + yuyeokorean: 0x318A, + yyabengali: 0x09DF, + yyadeva: 0x095F, + z: 0x007A, + zaarmenian: 0x0566, + zacute: 0x017A, + zadeva: 0x095B, + zagurmukhi: 0x0A5B, + zaharabic: 0x0638, + zahfinalarabic: 0xFEC6, + zahinitialarabic: 0xFEC7, + zahiragana: 0x3056, + zahmedialarabic: 0xFEC8, + zainarabic: 0x0632, + zainfinalarabic: 0xFEB0, + zakatakana: 0x30B6, + zaqefgadolhebrew: 0x0595, + zaqefqatanhebrew: 0x0594, + zarqahebrew: 0x0598, + zayin: 0x05D6, + zayindagesh: 0xFB36, + zayindageshhebrew: 0xFB36, + zayinhebrew: 0x05D6, + zbopomofo: 0x3117, + zcaron: 0x017E, + zcircle: 0x24E9, + zcircumflex: 0x1E91, + zcurl: 0x0291, + zdot: 0x017C, + zdotaccent: 0x017C, + zdotbelow: 0x1E93, + zecyrillic: 0x0437, + zedescendercyrillic: 0x0499, + zedieresiscyrillic: 0x04DF, + zehiragana: 0x305C, + zekatakana: 0x30BC, + zero: 0x0030, + zeroarabic: 0x0660, + zerobengali: 0x09E6, + zerodeva: 0x0966, + zerogujarati: 0x0AE6, + zerogurmukhi: 0x0A66, + zerohackarabic: 0x0660, + zeroinferior: 0x2080, + zeromonospace: 0xFF10, + zerooldstyle: 0xF730, + zeropersian: 0x06F0, + zerosuperior: 0x2070, + zerothai: 0x0E50, + zerowidthjoiner: 0xFEFF, + zerowidthnonjoiner: 0x200C, + zerowidthspace: 0x200B, + zeta: 0x03B6, + zhbopomofo: 0x3113, + zhearmenian: 0x056A, + zhebrevecyrillic: 0x04C2, + zhecyrillic: 0x0436, + zhedescendercyrillic: 0x0497, + zhedieresiscyrillic: 0x04DD, + zihiragana: 0x3058, + zikatakana: 0x30B8, + zinorhebrew: 0x05AE, + zlinebelow: 0x1E95, + zmonospace: 0xFF5A, + zohiragana: 0x305E, + zokatakana: 0x30BE, + zparen: 0x24B5, + zretroflexhook: 0x0290, + zstroke: 0x01B6, + zuhiragana: 0x305A, + zukatakana: 0x30BA, + '.notdef': 0x0000 +}; + +var DingbatsGlyphsUnicode = { + space: 0x0020, + a1: 0x2701, + a2: 0x2702, + a202: 0x2703, + a3: 0x2704, + a4: 0x260E, + a5: 0x2706, + a119: 0x2707, + a118: 0x2708, + a117: 0x2709, + a11: 0x261B, + a12: 0x261E, + a13: 0x270C, + a14: 0x270D, + a15: 0x270E, + a16: 0x270F, + a105: 0x2710, + a17: 0x2711, + a18: 0x2712, + a19: 0x2713, + a20: 0x2714, + a21: 0x2715, + a22: 0x2716, + a23: 0x2717, + a24: 0x2718, + a25: 0x2719, + a26: 0x271A, + a27: 0x271B, + a28: 0x271C, + a6: 0x271D, + a7: 0x271E, + a8: 0x271F, + a9: 0x2720, + a10: 0x2721, + a29: 0x2722, + a30: 0x2723, + a31: 0x2724, + a32: 0x2725, + a33: 0x2726, + a34: 0x2727, + a35: 0x2605, + a36: 0x2729, + a37: 0x272A, + a38: 0x272B, + a39: 0x272C, + a40: 0x272D, + a41: 0x272E, + a42: 0x272F, + a43: 0x2730, + a44: 0x2731, + a45: 0x2732, + a46: 0x2733, + a47: 0x2734, + a48: 0x2735, + a49: 0x2736, + a50: 0x2737, + a51: 0x2738, + a52: 0x2739, + a53: 0x273A, + a54: 0x273B, + a55: 0x273C, + a56: 0x273D, + a57: 0x273E, + a58: 0x273F, + a59: 0x2740, + a60: 0x2741, + a61: 0x2742, + a62: 0x2743, + a63: 0x2744, + a64: 0x2745, + a65: 0x2746, + a66: 0x2747, + a67: 0x2748, + a68: 0x2749, + a69: 0x274A, + a70: 0x274B, + a71: 0x25CF, + a72: 0x274D, + a73: 0x25A0, + a74: 0x274F, + a203: 0x2750, + a75: 0x2751, + a204: 0x2752, + a76: 0x25B2, + a77: 0x25BC, + a78: 0x25C6, + a79: 0x2756, + a81: 0x25D7, + a82: 0x2758, + a83: 0x2759, + a84: 0x275A, + a97: 0x275B, + a98: 0x275C, + a99: 0x275D, + a100: 0x275E, + a101: 0x2761, + a102: 0x2762, + a103: 0x2763, + a104: 0x2764, + a106: 0x2765, + a107: 0x2766, + a108: 0x2767, + a112: 0x2663, + a111: 0x2666, + a110: 0x2665, + a109: 0x2660, + a120: 0x2460, + a121: 0x2461, + a122: 0x2462, + a123: 0x2463, + a124: 0x2464, + a125: 0x2465, + a126: 0x2466, + a127: 0x2467, + a128: 0x2468, + a129: 0x2469, + a130: 0x2776, + a131: 0x2777, + a132: 0x2778, + a133: 0x2779, + a134: 0x277A, + a135: 0x277B, + a136: 0x277C, + a137: 0x277D, + a138: 0x277E, + a139: 0x277F, + a140: 0x2780, + a141: 0x2781, + a142: 0x2782, + a143: 0x2783, + a144: 0x2784, + a145: 0x2785, + a146: 0x2786, + a147: 0x2787, + a148: 0x2788, + a149: 0x2789, + a150: 0x278A, + a151: 0x278B, + a152: 0x278C, + a153: 0x278D, + a154: 0x278E, + a155: 0x278F, + a156: 0x2790, + a157: 0x2791, + a158: 0x2792, + a159: 0x2793, + a160: 0x2794, + a161: 0x2192, + a163: 0x2194, + a164: 0x2195, + a196: 0x2798, + a165: 0x2799, + a192: 0x279A, + a166: 0x279B, + a167: 0x279C, + a168: 0x279D, + a169: 0x279E, + a170: 0x279F, + a171: 0x27A0, + a172: 0x27A1, + a173: 0x27A2, + a162: 0x27A3, + a174: 0x27A4, + a175: 0x27A5, + a176: 0x27A6, + a177: 0x27A7, + a178: 0x27A8, + a179: 0x27A9, + a193: 0x27AA, + a180: 0x27AB, + a199: 0x27AC, + a181: 0x27AD, + a200: 0x27AE, + a182: 0x27AF, + a201: 0x27B1, + a183: 0x27B2, + a184: 0x27B3, + a197: 0x27B4, + a185: 0x27B5, + a194: 0x27B6, + a198: 0x27B7, + a186: 0x27B8, + a195: 0x27B9, + a187: 0x27BA, + a188: 0x27BB, + a189: 0x27BC, + a190: 0x27BD, + a191: 0x27BE, + a89: 0x2768, // 0xF8D7 + a90: 0x2769, // 0xF8D8 + a93: 0x276A, // 0xF8D9 + a94: 0x276B, // 0xF8DA + a91: 0x276C, // 0xF8DB + a92: 0x276D, // 0xF8DC + a205: 0x276E, // 0xF8DD + a85: 0x276F, // 0xF8DE + a206: 0x2770, // 0xF8DF + a86: 0x2771, // 0xF8E0 + a87: 0x2772, // 0xF8E1 + a88: 0x2773, // 0xF8E2 + a95: 0x2774, // 0xF8E3 + a96: 0x2775, // 0xF8E4 + '.notdef': 0x0000 +}; + + +var PDFImage = (function PDFImageClosure() { + /** + * Decode the image in the main thread if it supported. Resovles the promise + * when the image data is ready. + */ + function handleImageData(handler, xref, res, image) { + if (image instanceof JpegStream && image.isNativelyDecodable(xref, res)) { + // For natively supported jpegs send them to the main thread for decoding. + var dict = image.dict; + var colorSpace = dict.get('ColorSpace', 'CS'); + colorSpace = ColorSpace.parse(colorSpace, xref, res); + var numComps = colorSpace.numComps; + var decodePromise = handler.sendWithPromise('JpegDecode', + [image.getIR(), numComps]); + return decodePromise.then(function (message) { + var data = message.data; + return new Stream(data, 0, data.length, image.dict); + }); + } else { + return Promise.resolve(image); + } + } + + /** + * Decode and clamp a value. The formula is different from the spec because we + * don't decode to float range [0,1], we decode it in the [0,max] range. + */ + function decodeAndClamp(value, addend, coefficient, max) { + value = addend + value * coefficient; + // Clamp the value to the range + return (value < 0 ? 0 : (value > max ? max : value)); + } + + function PDFImage(xref, res, image, inline, smask, mask, isMask) { + this.image = image; + var dict = image.dict; + if (dict.has('Filter')) { + var filter = dict.get('Filter').name; + if (filter === 'JPXDecode') { + var jpxImage = new JpxImage(); + jpxImage.parseImageProperties(image.stream); + image.stream.reset(); + image.bitsPerComponent = jpxImage.bitsPerComponent; + image.numComps = jpxImage.componentsCount; + } else if (filter === 'JBIG2Decode') { + image.bitsPerComponent = 1; + image.numComps = 1; + } + } + // TODO cache rendered images? + + this.width = dict.get('Width', 'W'); + this.height = dict.get('Height', 'H'); + + if (this.width < 1 || this.height < 1) { + error('Invalid image width: ' + this.width + ' or height: ' + + this.height); + } + + this.interpolate = dict.get('Interpolate', 'I') || false; + this.imageMask = dict.get('ImageMask', 'IM') || false; + this.matte = dict.get('Matte') || false; + + var bitsPerComponent = image.bitsPerComponent; + if (!bitsPerComponent) { + bitsPerComponent = dict.get('BitsPerComponent', 'BPC'); + if (!bitsPerComponent) { + if (this.imageMask) { + bitsPerComponent = 1; + } else { + error('Bits per component missing in image: ' + this.imageMask); + } + } + } + this.bpc = bitsPerComponent; + + if (!this.imageMask) { + var colorSpace = dict.get('ColorSpace', 'CS'); + if (!colorSpace) { + info('JPX images (which do not require color spaces)'); + switch (image.numComps) { + case 1: + colorSpace = Name.get('DeviceGray'); + break; + case 3: + colorSpace = Name.get('DeviceRGB'); + break; + case 4: + colorSpace = Name.get('DeviceCMYK'); + break; + default: + error('JPX images with ' + this.numComps + + ' color components not supported.'); + } + } + this.colorSpace = ColorSpace.parse(colorSpace, xref, res); + this.numComps = this.colorSpace.numComps; + } + + this.decode = dict.get('Decode', 'D'); + this.needsDecode = false; + if (this.decode && + ((this.colorSpace && !this.colorSpace.isDefaultDecode(this.decode)) || + (isMask && !ColorSpace.isDefaultDecode(this.decode, 1)))) { + this.needsDecode = true; + // Do some preprocessing to avoid more math. + var max = (1 << bitsPerComponent) - 1; + this.decodeCoefficients = []; + this.decodeAddends = []; + for (var i = 0, j = 0; i < this.decode.length; i += 2, ++j) { + var dmin = this.decode[i]; + var dmax = this.decode[i + 1]; + this.decodeCoefficients[j] = dmax - dmin; + this.decodeAddends[j] = max * dmin; + } + } + + if (smask) { + this.smask = new PDFImage(xref, res, smask, false); + } else if (mask) { + if (isStream(mask)) { + this.mask = new PDFImage(xref, res, mask, false, null, null, true); + } else { + // Color key mask (just an array). + this.mask = mask; + } + } + } + /** + * Handles processing of image data and returns the Promise that is resolved + * with a PDFImage when the image is ready to be used. + */ + PDFImage.buildImage = function PDFImage_buildImage(handler, xref, + res, image, inline) { + var imagePromise = handleImageData(handler, xref, res, image); + var smaskPromise; + var maskPromise; + + var smask = image.dict.get('SMask'); + var mask = image.dict.get('Mask'); + + if (smask) { + smaskPromise = handleImageData(handler, xref, res, smask); + maskPromise = Promise.resolve(null); + } else { + smaskPromise = Promise.resolve(null); + if (mask) { + if (isStream(mask)) { + maskPromise = handleImageData(handler, xref, res, mask); + } else if (isArray(mask)) { + maskPromise = Promise.resolve(mask); + } else { + warn('Unsupported mask format.'); + maskPromise = Promise.resolve(null); + } + } else { + maskPromise = Promise.resolve(null); + } + } + return Promise.all([imagePromise, smaskPromise, maskPromise]).then( + function(results) { + var imageData = results[0]; + var smaskData = results[1]; + var maskData = results[2]; + return new PDFImage(xref, res, imageData, inline, smaskData, maskData); + }); + }; + + /** + * Resize an image using the nearest neighbor algorithm. Currently only + * supports one and three component images. + * @param {TypedArray} pixels The original image with one component. + * @param {Number} bpc Number of bits per component. + * @param {Number} components Number of color components, 1 or 3 is supported. + * @param {Number} w1 Original width. + * @param {Number} h1 Original height. + * @param {Number} w2 New width. + * @param {Number} h2 New height. + * @param {TypedArray} dest (Optional) The destination buffer. + * @param {Number} alpha01 (Optional) Size reserved for the alpha channel. + * @return {TypedArray} Resized image data. + */ + PDFImage.resize = function PDFImage_resize(pixels, bpc, components, + w1, h1, w2, h2, dest, alpha01) { + + if (components !== 1 && components !== 3) { + error('Unsupported component count for resizing.'); + } + + var length = w2 * h2 * components; + var temp = dest ? dest : (bpc <= 8 ? new Uint8Array(length) : + (bpc <= 16 ? new Uint16Array(length) : new Uint32Array(length))); + var xRatio = w1 / w2; + var yRatio = h1 / h2; + var i, j, py, newIndex = 0, oldIndex; + var xScaled = new Uint16Array(w2); + var w1Scanline = w1 * components; + if (alpha01 !== 1) { + alpha01 = 0; + } + + for (j = 0; j < w2; j++) { + xScaled[j] = Math.floor(j * xRatio) * components; + } + + if (components === 1) { + for (i = 0; i < h2; i++) { + py = Math.floor(i * yRatio) * w1Scanline; + for (j = 0; j < w2; j++) { + oldIndex = py + xScaled[j]; + temp[newIndex++] = pixels[oldIndex]; + } + } + } else if (components === 3) { + for (i = 0; i < h2; i++) { + py = Math.floor(i * yRatio) * w1Scanline; + for (j = 0; j < w2; j++) { + oldIndex = py + xScaled[j]; + temp[newIndex++] = pixels[oldIndex++]; + temp[newIndex++] = pixels[oldIndex++]; + temp[newIndex++] = pixels[oldIndex++]; + newIndex += alpha01; + } + } + } + return temp; + }; + + PDFImage.createMask = + function PDFImage_createMask(imgArray, width, height, + imageIsFromDecodeStream, inverseDecode) { + + // |imgArray| might not contain full data for every pixel of the mask, so + // we need to distinguish between |computedLength| and |actualLength|. + // In particular, if inverseDecode is true, then the array we return must + // have a length of |computedLength|. + + var computedLength = ((width + 7) >> 3) * height; + var actualLength = imgArray.byteLength; + var haveFullData = computedLength === actualLength; + var data, i; + + if (imageIsFromDecodeStream && (!inverseDecode || haveFullData)) { + // imgArray came from a DecodeStream and its data is in an appropriate + // form, so we can just transfer it. + data = imgArray; + } else if (!inverseDecode) { + data = new Uint8Array(actualLength); + data.set(imgArray); + } else { + data = new Uint8Array(computedLength); + data.set(imgArray); + for (i = actualLength; i < computedLength; i++) { + data[i] = 0xff; + } + } + + // If necessary, invert the original mask data (but not any extra we might + // have added above). It's safe to modify the array -- whether it's the + // original or a copy, we're about to transfer it anyway, so nothing else + // in this thread can be relying on its contents. + if (inverseDecode) { + for (i = 0; i < actualLength; i++) { + data[i] = ~data[i]; + } + } + + return {data: data, width: width, height: height}; + }; + + PDFImage.prototype = { + get drawWidth() { + return Math.max(this.width, + this.smask && this.smask.width || 0, + this.mask && this.mask.width || 0); + }, + + get drawHeight() { + return Math.max(this.height, + this.smask && this.smask.height || 0, + this.mask && this.mask.height || 0); + }, + + decodeBuffer: function PDFImage_decodeBuffer(buffer) { + var bpc = this.bpc; + var numComps = this.numComps; + + var decodeAddends = this.decodeAddends; + var decodeCoefficients = this.decodeCoefficients; + var max = (1 << bpc) - 1; + var i, ii; + + if (bpc === 1) { + // If the buffer needed decode that means it just needs to be inverted. + for (i = 0, ii = buffer.length; i < ii; i++) { + buffer[i] = +!(buffer[i]); + } + return; + } + var index = 0; + for (i = 0, ii = this.width * this.height; i < ii; i++) { + for (var j = 0; j < numComps; j++) { + buffer[index] = decodeAndClamp(buffer[index], decodeAddends[j], + decodeCoefficients[j], max); + index++; + } + } + }, + + getComponents: function PDFImage_getComponents(buffer) { + var bpc = this.bpc; + + // This image doesn't require any extra work. + if (bpc === 8) { + return buffer; + } + + var width = this.width; + var height = this.height; + var numComps = this.numComps; + + var length = width * height * numComps; + var bufferPos = 0; + var output = (bpc <= 8 ? new Uint8Array(length) : + (bpc <= 16 ? new Uint16Array(length) : new Uint32Array(length))); + var rowComps = width * numComps; + + var max = (1 << bpc) - 1; + var i = 0, ii, buf; + + if (bpc === 1) { + // Optimization for reading 1 bpc images. + var mask, loop1End, loop2End; + for (var j = 0; j < height; j++) { + loop1End = i + (rowComps & ~7); + loop2End = i + rowComps; + + // unroll loop for all full bytes + while (i < loop1End) { + buf = buffer[bufferPos++]; + output[i] = (buf >> 7) & 1; + output[i + 1] = (buf >> 6) & 1; + output[i + 2] = (buf >> 5) & 1; + output[i + 3] = (buf >> 4) & 1; + output[i + 4] = (buf >> 3) & 1; + output[i + 5] = (buf >> 2) & 1; + output[i + 6] = (buf >> 1) & 1; + output[i + 7] = buf & 1; + i += 8; + } + + // handle remaing bits + if (i < loop2End) { + buf = buffer[bufferPos++]; + mask = 128; + while (i < loop2End) { + output[i++] = +!!(buf & mask); + mask >>= 1; + } + } + } + } else { + // The general case that handles all other bpc values. + var bits = 0; + buf = 0; + for (i = 0, ii = length; i < ii; ++i) { + if (i % rowComps === 0) { + buf = 0; + bits = 0; + } + + while (bits < bpc) { + buf = (buf << 8) | buffer[bufferPos++]; + bits += 8; + } + + var remainingBits = bits - bpc; + var value = buf >> remainingBits; + output[i] = (value < 0 ? 0 : (value > max ? max : value)); + buf = buf & ((1 << remainingBits) - 1); + bits = remainingBits; + } + } + return output; + }, + + fillOpacity: function PDFImage_fillOpacity(rgbaBuf, width, height, + actualHeight, image) { + var smask = this.smask; + var mask = this.mask; + var alphaBuf, sw, sh, i, ii, j; + + if (smask) { + sw = smask.width; + sh = smask.height; + alphaBuf = new Uint8Array(sw * sh); + smask.fillGrayBuffer(alphaBuf); + if (sw !== width || sh !== height) { + alphaBuf = PDFImage.resize(alphaBuf, smask.bpc, 1, sw, sh, width, + height); + } + } else if (mask) { + if (mask instanceof PDFImage) { + sw = mask.width; + sh = mask.height; + alphaBuf = new Uint8Array(sw * sh); + mask.numComps = 1; + mask.fillGrayBuffer(alphaBuf); + + // Need to invert values in rgbaBuf + for (i = 0, ii = sw * sh; i < ii; ++i) { + alphaBuf[i] = 255 - alphaBuf[i]; + } + + if (sw !== width || sh !== height) { + alphaBuf = PDFImage.resize(alphaBuf, mask.bpc, 1, sw, sh, width, + height); + } + } else if (isArray(mask)) { + // Color key mask: if any of the compontents are outside the range + // then they should be painted. + alphaBuf = new Uint8Array(width * height); + var numComps = this.numComps; + for (i = 0, ii = width * height; i < ii; ++i) { + var opacity = 0; + var imageOffset = i * numComps; + for (j = 0; j < numComps; ++j) { + var color = image[imageOffset + j]; + var maskOffset = j * 2; + if (color < mask[maskOffset] || color > mask[maskOffset + 1]) { + opacity = 255; + break; + } + } + alphaBuf[i] = opacity; + } + } else { + error('Unknown mask format.'); + } + } + + if (alphaBuf) { + for (i = 0, j = 3, ii = width * actualHeight; i < ii; ++i, j += 4) { + rgbaBuf[j] = alphaBuf[i]; + } + } else { + // No mask. + for (i = 0, j = 3, ii = width * actualHeight; i < ii; ++i, j += 4) { + rgbaBuf[j] = 255; + } + } + }, + + undoPreblend: function PDFImage_undoPreblend(buffer, width, height) { + var matte = this.smask && this.smask.matte; + if (!matte) { + return; + } + var matteRgb = this.colorSpace.getRgb(matte, 0); + var matteR = matteRgb[0]; + var matteG = matteRgb[1]; + var matteB = matteRgb[2]; + var length = width * height * 4; + var r, g, b; + for (var i = 0; i < length; i += 4) { + var alpha = buffer[i + 3]; + if (alpha === 0) { + // according formula we have to get Infinity in all components + // making it white (typical paper color) should be okay + buffer[i] = 255; + buffer[i + 1] = 255; + buffer[i + 2] = 255; + continue; + } + var k = 255 / alpha; + r = (buffer[i] - matteR) * k + matteR; + g = (buffer[i + 1] - matteG) * k + matteG; + b = (buffer[i + 2] - matteB) * k + matteB; + buffer[i] = r <= 0 ? 0 : r >= 255 ? 255 : r | 0; + buffer[i + 1] = g <= 0 ? 0 : g >= 255 ? 255 : g | 0; + buffer[i + 2] = b <= 0 ? 0 : b >= 255 ? 255 : b | 0; + } + }, + + createImageData: function PDFImage_createImageData(forceRGBA) { + var drawWidth = this.drawWidth; + var drawHeight = this.drawHeight; + var imgData = { // other fields are filled in below + width: drawWidth, + height: drawHeight + }; + + var numComps = this.numComps; + var originalWidth = this.width; + var originalHeight = this.height; + var bpc = this.bpc; + + // Rows start at byte boundary. + var rowBytes = (originalWidth * numComps * bpc + 7) >> 3; + var imgArray; + + if (!forceRGBA) { + // If it is a 1-bit-per-pixel grayscale (i.e. black-and-white) image + // without any complications, we pass a same-sized copy to the main + // thread rather than expanding by 32x to RGBA form. This saves *lots* + // of memory for many scanned documents. It's also much faster. + // + // Similarly, if it is a 24-bit-per pixel RGB image without any + // complications, we avoid expanding by 1.333x to RGBA form. + var kind; + if (this.colorSpace.name === 'DeviceGray' && bpc === 1) { + kind = ImageKind.GRAYSCALE_1BPP; + } else if (this.colorSpace.name === 'DeviceRGB' && bpc === 8 && + !this.needsDecode) { + kind = ImageKind.RGB_24BPP; + } + if (kind && !this.smask && !this.mask && + drawWidth === originalWidth && drawHeight === originalHeight) { + imgData.kind = kind; + + imgArray = this.getImageBytes(originalHeight * rowBytes); + // If imgArray came from a DecodeStream, we're safe to transfer it + // (and thus neuter it) because it will constitute the entire + // DecodeStream's data. But if it came from a Stream, we need to + // copy it because it'll only be a portion of the Stream's data, and + // the rest will be read later on. + if (this.image instanceof DecodeStream) { + imgData.data = imgArray; + } else { + var newArray = new Uint8Array(imgArray.length); + newArray.set(imgArray); + imgData.data = newArray; + } + if (this.needsDecode) { + // Invert the buffer (which must be grayscale if we reached here). + assert(kind === ImageKind.GRAYSCALE_1BPP); + var buffer = imgData.data; + for (var i = 0, ii = buffer.length; i < ii; i++) { + buffer[i] ^= 0xff; + } + } + return imgData; + } + if (this.image instanceof JpegStream && !this.smask && !this.mask) { + imgData.kind = ImageKind.RGB_24BPP; + imgData.data = this.getImageBytes(originalHeight * rowBytes, + drawWidth, drawHeight, true); + return imgData; + } + } + + imgArray = this.getImageBytes(originalHeight * rowBytes); + // imgArray can be incomplete (e.g. after CCITT fax encoding). + var actualHeight = 0 | (imgArray.length / rowBytes * + drawHeight / originalHeight); + + var comps = this.getComponents(imgArray); + + // If opacity data is present, use RGBA_32BPP form. Otherwise, use the + // more compact RGB_24BPP form if allowable. + var alpha01, maybeUndoPreblend; + if (!forceRGBA && !this.smask && !this.mask) { + imgData.kind = ImageKind.RGB_24BPP; + imgData.data = new Uint8Array(drawWidth * drawHeight * 3); + alpha01 = 0; + maybeUndoPreblend = false; + } else { + imgData.kind = ImageKind.RGBA_32BPP; + imgData.data = new Uint8Array(drawWidth * drawHeight * 4); + alpha01 = 1; + maybeUndoPreblend = true; + + // Color key masking (opacity) must be performed before decoding. + this.fillOpacity(imgData.data, drawWidth, drawHeight, actualHeight, + comps); + } + + if (this.needsDecode) { + this.decodeBuffer(comps); + } + this.colorSpace.fillRgb(imgData.data, originalWidth, originalHeight, + drawWidth, drawHeight, actualHeight, bpc, comps, + alpha01); + if (maybeUndoPreblend) { + this.undoPreblend(imgData.data, drawWidth, actualHeight); + } + + return imgData; + }, + + fillGrayBuffer: function PDFImage_fillGrayBuffer(buffer) { + var numComps = this.numComps; + if (numComps !== 1) { + error('Reading gray scale from a color image: ' + numComps); + } + + var width = this.width; + var height = this.height; + var bpc = this.bpc; + + // rows start at byte boundary + var rowBytes = (width * numComps * bpc + 7) >> 3; + var imgArray = this.getImageBytes(height * rowBytes); + + var comps = this.getComponents(imgArray); + var i, length; + + if (bpc === 1) { + // inline decoding (= inversion) for 1 bpc images + length = width * height; + if (this.needsDecode) { + // invert and scale to {0, 255} + for (i = 0; i < length; ++i) { + buffer[i] = (comps[i] - 1) & 255; + } + } else { + // scale to {0, 255} + for (i = 0; i < length; ++i) { + buffer[i] = (-comps[i]) & 255; + } + } + return; + } + + if (this.needsDecode) { + this.decodeBuffer(comps); + } + length = width * height; + // we aren't using a colorspace so we need to scale the value + var scale = 255 / ((1 << bpc) - 1); + for (i = 0; i < length; ++i) { + buffer[i] = (scale * comps[i]) | 0; + } + }, + + getImageBytes: function PDFImage_getImageBytes(length, + drawWidth, drawHeight, + forceRGB) { + this.image.reset(); + this.image.drawWidth = drawWidth || this.width; + this.image.drawHeight = drawHeight || this.height; + this.image.forceRGB = !!forceRGB; + return this.image.getBytes(length); + } + }; + return PDFImage; +})(); + + +// The Metrics object contains glyph widths (in glyph space units). +// As per PDF spec, for most fonts (Type 3 being an exception) a glyph +// space unit corresponds to 1/1000th of text space unit. +var Metrics = { + 'Courier': 600, + 'Courier-Bold': 600, + 'Courier-BoldOblique': 600, + 'Courier-Oblique': 600, + 'Helvetica' : { + 'space': 278, + 'exclam': 278, + 'quotedbl': 355, + 'numbersign': 556, + 'dollar': 556, + 'percent': 889, + 'ampersand': 667, + 'quoteright': 222, + 'parenleft': 333, + 'parenright': 333, + 'asterisk': 389, + 'plus': 584, + 'comma': 278, + 'hyphen': 333, + 'period': 278, + 'slash': 278, + 'zero': 556, + 'one': 556, + 'two': 556, + 'three': 556, + 'four': 556, + 'five': 556, + 'six': 556, + 'seven': 556, + 'eight': 556, + 'nine': 556, + 'colon': 278, + 'semicolon': 278, + 'less': 584, + 'equal': 584, + 'greater': 584, + 'question': 556, + 'at': 1015, + 'A': 667, + 'B': 667, + 'C': 722, + 'D': 722, + 'E': 667, + 'F': 611, + 'G': 778, + 'H': 722, + 'I': 278, + 'J': 500, + 'K': 667, + 'L': 556, + 'M': 833, + 'N': 722, + 'O': 778, + 'P': 667, + 'Q': 778, + 'R': 722, + 'S': 667, + 'T': 611, + 'U': 722, + 'V': 667, + 'W': 944, + 'X': 667, + 'Y': 667, + 'Z': 611, + 'bracketleft': 278, + 'backslash': 278, + 'bracketright': 278, + 'asciicircum': 469, + 'underscore': 556, + 'quoteleft': 222, + 'a': 556, + 'b': 556, + 'c': 500, + 'd': 556, + 'e': 556, + 'f': 278, + 'g': 556, + 'h': 556, + 'i': 222, + 'j': 222, + 'k': 500, + 'l': 222, + 'm': 833, + 'n': 556, + 'o': 556, + 'p': 556, + 'q': 556, + 'r': 333, + 's': 500, + 't': 278, + 'u': 556, + 'v': 500, + 'w': 722, + 'x': 500, + 'y': 500, + 'z': 500, + 'braceleft': 334, + 'bar': 260, + 'braceright': 334, + 'asciitilde': 584, + 'exclamdown': 333, + 'cent': 556, + 'sterling': 556, + 'fraction': 167, + 'yen': 556, + 'florin': 556, + 'section': 556, + 'currency': 556, + 'quotesingle': 191, + 'quotedblleft': 333, + 'guillemotleft': 556, + 'guilsinglleft': 333, + 'guilsinglright': 333, + 'fi': 500, + 'fl': 500, + 'endash': 556, + 'dagger': 556, + 'daggerdbl': 556, + 'periodcentered': 278, + 'paragraph': 537, + 'bullet': 350, + 'quotesinglbase': 222, + 'quotedblbase': 333, + 'quotedblright': 333, + 'guillemotright': 556, + 'ellipsis': 1000, + 'perthousand': 1000, + 'questiondown': 611, + 'grave': 333, + 'acute': 333, + 'circumflex': 333, + 'tilde': 333, + 'macron': 333, + 'breve': 333, + 'dotaccent': 333, + 'dieresis': 333, + 'ring': 333, + 'cedilla': 333, + 'hungarumlaut': 333, + 'ogonek': 333, + 'caron': 333, + 'emdash': 1000, + 'AE': 1000, + 'ordfeminine': 370, + 'Lslash': 556, + 'Oslash': 778, + 'OE': 1000, + 'ordmasculine': 365, + 'ae': 889, + 'dotlessi': 278, + 'lslash': 222, + 'oslash': 611, + 'oe': 944, + 'germandbls': 611, + 'Idieresis': 278, + 'eacute': 556, + 'abreve': 556, + 'uhungarumlaut': 556, + 'ecaron': 556, + 'Ydieresis': 667, + 'divide': 584, + 'Yacute': 667, + 'Acircumflex': 667, + 'aacute': 556, + 'Ucircumflex': 722, + 'yacute': 500, + 'scommaaccent': 500, + 'ecircumflex': 556, + 'Uring': 722, + 'Udieresis': 722, + 'aogonek': 556, + 'Uacute': 722, + 'uogonek': 556, + 'Edieresis': 667, + 'Dcroat': 722, + 'commaaccent': 250, + 'copyright': 737, + 'Emacron': 667, + 'ccaron': 500, + 'aring': 556, + 'Ncommaaccent': 722, + 'lacute': 222, + 'agrave': 556, + 'Tcommaaccent': 611, + 'Cacute': 722, + 'atilde': 556, + 'Edotaccent': 667, + 'scaron': 500, + 'scedilla': 500, + 'iacute': 278, + 'lozenge': 471, + 'Rcaron': 722, + 'Gcommaaccent': 778, + 'ucircumflex': 556, + 'acircumflex': 556, + 'Amacron': 667, + 'rcaron': 333, + 'ccedilla': 500, + 'Zdotaccent': 611, + 'Thorn': 667, + 'Omacron': 778, + 'Racute': 722, + 'Sacute': 667, + 'dcaron': 643, + 'Umacron': 722, + 'uring': 556, + 'threesuperior': 333, + 'Ograve': 778, + 'Agrave': 667, + 'Abreve': 667, + 'multiply': 584, + 'uacute': 556, + 'Tcaron': 611, + 'partialdiff': 476, + 'ydieresis': 500, + 'Nacute': 722, + 'icircumflex': 278, + 'Ecircumflex': 667, + 'adieresis': 556, + 'edieresis': 556, + 'cacute': 500, + 'nacute': 556, + 'umacron': 556, + 'Ncaron': 722, + 'Iacute': 278, + 'plusminus': 584, + 'brokenbar': 260, + 'registered': 737, + 'Gbreve': 778, + 'Idotaccent': 278, + 'summation': 600, + 'Egrave': 667, + 'racute': 333, + 'omacron': 556, + 'Zacute': 611, + 'Zcaron': 611, + 'greaterequal': 549, + 'Eth': 722, + 'Ccedilla': 722, + 'lcommaaccent': 222, + 'tcaron': 317, + 'eogonek': 556, + 'Uogonek': 722, + 'Aacute': 667, + 'Adieresis': 667, + 'egrave': 556, + 'zacute': 500, + 'iogonek': 222, + 'Oacute': 778, + 'oacute': 556, + 'amacron': 556, + 'sacute': 500, + 'idieresis': 278, + 'Ocircumflex': 778, + 'Ugrave': 722, + 'Delta': 612, + 'thorn': 556, + 'twosuperior': 333, + 'Odieresis': 778, + 'mu': 556, + 'igrave': 278, + 'ohungarumlaut': 556, + 'Eogonek': 667, + 'dcroat': 556, + 'threequarters': 834, + 'Scedilla': 667, + 'lcaron': 299, + 'Kcommaaccent': 667, + 'Lacute': 556, + 'trademark': 1000, + 'edotaccent': 556, + 'Igrave': 278, + 'Imacron': 278, + 'Lcaron': 556, + 'onehalf': 834, + 'lessequal': 549, + 'ocircumflex': 556, + 'ntilde': 556, + 'Uhungarumlaut': 722, + 'Eacute': 667, + 'emacron': 556, + 'gbreve': 556, + 'onequarter': 834, + 'Scaron': 667, + 'Scommaaccent': 667, + 'Ohungarumlaut': 778, + 'degree': 400, + 'ograve': 556, + 'Ccaron': 722, + 'ugrave': 556, + 'radical': 453, + 'Dcaron': 722, + 'rcommaaccent': 333, + 'Ntilde': 722, + 'otilde': 556, + 'Rcommaaccent': 722, + 'Lcommaaccent': 556, + 'Atilde': 667, + 'Aogonek': 667, + 'Aring': 667, + 'Otilde': 778, + 'zdotaccent': 500, + 'Ecaron': 667, + 'Iogonek': 278, + 'kcommaaccent': 500, + 'minus': 584, + 'Icircumflex': 278, + 'ncaron': 556, + 'tcommaaccent': 278, + 'logicalnot': 584, + 'odieresis': 556, + 'udieresis': 556, + 'notequal': 549, + 'gcommaaccent': 556, + 'eth': 556, + 'zcaron': 500, + 'ncommaaccent': 556, + 'onesuperior': 333, + 'imacron': 278, + 'Euro': 556 + }, + 'Helvetica-Bold': { + 'space': 278, + 'exclam': 333, + 'quotedbl': 474, + 'numbersign': 556, + 'dollar': 556, + 'percent': 889, + 'ampersand': 722, + 'quoteright': 278, + 'parenleft': 333, + 'parenright': 333, + 'asterisk': 389, + 'plus': 584, + 'comma': 278, + 'hyphen': 333, + 'period': 278, + 'slash': 278, + 'zero': 556, + 'one': 556, + 'two': 556, + 'three': 556, + 'four': 556, + 'five': 556, + 'six': 556, + 'seven': 556, + 'eight': 556, + 'nine': 556, + 'colon': 333, + 'semicolon': 333, + 'less': 584, + 'equal': 584, + 'greater': 584, + 'question': 611, + 'at': 975, + 'A': 722, + 'B': 722, + 'C': 722, + 'D': 722, + 'E': 667, + 'F': 611, + 'G': 778, + 'H': 722, + 'I': 278, + 'J': 556, + 'K': 722, + 'L': 611, + 'M': 833, + 'N': 722, + 'O': 778, + 'P': 667, + 'Q': 778, + 'R': 722, + 'S': 667, + 'T': 611, + 'U': 722, + 'V': 667, + 'W': 944, + 'X': 667, + 'Y': 667, + 'Z': 611, + 'bracketleft': 333, + 'backslash': 278, + 'bracketright': 333, + 'asciicircum': 584, + 'underscore': 556, + 'quoteleft': 278, + 'a': 556, + 'b': 611, + 'c': 556, + 'd': 611, + 'e': 556, + 'f': 333, + 'g': 611, + 'h': 611, + 'i': 278, + 'j': 278, + 'k': 556, + 'l': 278, + 'm': 889, + 'n': 611, + 'o': 611, + 'p': 611, + 'q': 611, + 'r': 389, + 's': 556, + 't': 333, + 'u': 611, + 'v': 556, + 'w': 778, + 'x': 556, + 'y': 556, + 'z': 500, + 'braceleft': 389, + 'bar': 280, + 'braceright': 389, + 'asciitilde': 584, + 'exclamdown': 333, + 'cent': 556, + 'sterling': 556, + 'fraction': 167, + 'yen': 556, + 'florin': 556, + 'section': 556, + 'currency': 556, + 'quotesingle': 238, + 'quotedblleft': 500, + 'guillemotleft': 556, + 'guilsinglleft': 333, + 'guilsinglright': 333, + 'fi': 611, + 'fl': 611, + 'endash': 556, + 'dagger': 556, + 'daggerdbl': 556, + 'periodcentered': 278, + 'paragraph': 556, + 'bullet': 350, + 'quotesinglbase': 278, + 'quotedblbase': 500, + 'quotedblright': 500, + 'guillemotright': 556, + 'ellipsis': 1000, + 'perthousand': 1000, + 'questiondown': 611, + 'grave': 333, + 'acute': 333, + 'circumflex': 333, + 'tilde': 333, + 'macron': 333, + 'breve': 333, + 'dotaccent': 333, + 'dieresis': 333, + 'ring': 333, + 'cedilla': 333, + 'hungarumlaut': 333, + 'ogonek': 333, + 'caron': 333, + 'emdash': 1000, + 'AE': 1000, + 'ordfeminine': 370, + 'Lslash': 611, + 'Oslash': 778, + 'OE': 1000, + 'ordmasculine': 365, + 'ae': 889, + 'dotlessi': 278, + 'lslash': 278, + 'oslash': 611, + 'oe': 944, + 'germandbls': 611, + 'Idieresis': 278, + 'eacute': 556, + 'abreve': 556, + 'uhungarumlaut': 611, + 'ecaron': 556, + 'Ydieresis': 667, + 'divide': 584, + 'Yacute': 667, + 'Acircumflex': 722, + 'aacute': 556, + 'Ucircumflex': 722, + 'yacute': 556, + 'scommaaccent': 556, + 'ecircumflex': 556, + 'Uring': 722, + 'Udieresis': 722, + 'aogonek': 556, + 'Uacute': 722, + 'uogonek': 611, + 'Edieresis': 667, + 'Dcroat': 722, + 'commaaccent': 250, + 'copyright': 737, + 'Emacron': 667, + 'ccaron': 556, + 'aring': 556, + 'Ncommaaccent': 722, + 'lacute': 278, + 'agrave': 556, + 'Tcommaaccent': 611, + 'Cacute': 722, + 'atilde': 556, + 'Edotaccent': 667, + 'scaron': 556, + 'scedilla': 556, + 'iacute': 278, + 'lozenge': 494, + 'Rcaron': 722, + 'Gcommaaccent': 778, + 'ucircumflex': 611, + 'acircumflex': 556, + 'Amacron': 722, + 'rcaron': 389, + 'ccedilla': 556, + 'Zdotaccent': 611, + 'Thorn': 667, + 'Omacron': 778, + 'Racute': 722, + 'Sacute': 667, + 'dcaron': 743, + 'Umacron': 722, + 'uring': 611, + 'threesuperior': 333, + 'Ograve': 778, + 'Agrave': 722, + 'Abreve': 722, + 'multiply': 584, + 'uacute': 611, + 'Tcaron': 611, + 'partialdiff': 494, + 'ydieresis': 556, + 'Nacute': 722, + 'icircumflex': 278, + 'Ecircumflex': 667, + 'adieresis': 556, + 'edieresis': 556, + 'cacute': 556, + 'nacute': 611, + 'umacron': 611, + 'Ncaron': 722, + 'Iacute': 278, + 'plusminus': 584, + 'brokenbar': 280, + 'registered': 737, + 'Gbreve': 778, + 'Idotaccent': 278, + 'summation': 600, + 'Egrave': 667, + 'racute': 389, + 'omacron': 611, + 'Zacute': 611, + 'Zcaron': 611, + 'greaterequal': 549, + 'Eth': 722, + 'Ccedilla': 722, + 'lcommaaccent': 278, + 'tcaron': 389, + 'eogonek': 556, + 'Uogonek': 722, + 'Aacute': 722, + 'Adieresis': 722, + 'egrave': 556, + 'zacute': 500, + 'iogonek': 278, + 'Oacute': 778, + 'oacute': 611, + 'amacron': 556, + 'sacute': 556, + 'idieresis': 278, + 'Ocircumflex': 778, + 'Ugrave': 722, + 'Delta': 612, + 'thorn': 611, + 'twosuperior': 333, + 'Odieresis': 778, + 'mu': 611, + 'igrave': 278, + 'ohungarumlaut': 611, + 'Eogonek': 667, + 'dcroat': 611, + 'threequarters': 834, + 'Scedilla': 667, + 'lcaron': 400, + 'Kcommaaccent': 722, + 'Lacute': 611, + 'trademark': 1000, + 'edotaccent': 556, + 'Igrave': 278, + 'Imacron': 278, + 'Lcaron': 611, + 'onehalf': 834, + 'lessequal': 549, + 'ocircumflex': 611, + 'ntilde': 611, + 'Uhungarumlaut': 722, + 'Eacute': 667, + 'emacron': 556, + 'gbreve': 611, + 'onequarter': 834, + 'Scaron': 667, + 'Scommaaccent': 667, + 'Ohungarumlaut': 778, + 'degree': 400, + 'ograve': 611, + 'Ccaron': 722, + 'ugrave': 611, + 'radical': 549, + 'Dcaron': 722, + 'rcommaaccent': 389, + 'Ntilde': 722, + 'otilde': 611, + 'Rcommaaccent': 722, + 'Lcommaaccent': 611, + 'Atilde': 722, + 'Aogonek': 722, + 'Aring': 722, + 'Otilde': 778, + 'zdotaccent': 500, + 'Ecaron': 667, + 'Iogonek': 278, + 'kcommaaccent': 556, + 'minus': 584, + 'Icircumflex': 278, + 'ncaron': 611, + 'tcommaaccent': 333, + 'logicalnot': 584, + 'odieresis': 611, + 'udieresis': 611, + 'notequal': 549, + 'gcommaaccent': 611, + 'eth': 611, + 'zcaron': 500, + 'ncommaaccent': 611, + 'onesuperior': 333, + 'imacron': 278, + 'Euro': 556 + }, + 'Helvetica-BoldOblique': { + 'space': 278, + 'exclam': 333, + 'quotedbl': 474, + 'numbersign': 556, + 'dollar': 556, + 'percent': 889, + 'ampersand': 722, + 'quoteright': 278, + 'parenleft': 333, + 'parenright': 333, + 'asterisk': 389, + 'plus': 584, + 'comma': 278, + 'hyphen': 333, + 'period': 278, + 'slash': 278, + 'zero': 556, + 'one': 556, + 'two': 556, + 'three': 556, + 'four': 556, + 'five': 556, + 'six': 556, + 'seven': 556, + 'eight': 556, + 'nine': 556, + 'colon': 333, + 'semicolon': 333, + 'less': 584, + 'equal': 584, + 'greater': 584, + 'question': 611, + 'at': 975, + 'A': 722, + 'B': 722, + 'C': 722, + 'D': 722, + 'E': 667, + 'F': 611, + 'G': 778, + 'H': 722, + 'I': 278, + 'J': 556, + 'K': 722, + 'L': 611, + 'M': 833, + 'N': 722, + 'O': 778, + 'P': 667, + 'Q': 778, + 'R': 722, + 'S': 667, + 'T': 611, + 'U': 722, + 'V': 667, + 'W': 944, + 'X': 667, + 'Y': 667, + 'Z': 611, + 'bracketleft': 333, + 'backslash': 278, + 'bracketright': 333, + 'asciicircum': 584, + 'underscore': 556, + 'quoteleft': 278, + 'a': 556, + 'b': 611, + 'c': 556, + 'd': 611, + 'e': 556, + 'f': 333, + 'g': 611, + 'h': 611, + 'i': 278, + 'j': 278, + 'k': 556, + 'l': 278, + 'm': 889, + 'n': 611, + 'o': 611, + 'p': 611, + 'q': 611, + 'r': 389, + 's': 556, + 't': 333, + 'u': 611, + 'v': 556, + 'w': 778, + 'x': 556, + 'y': 556, + 'z': 500, + 'braceleft': 389, + 'bar': 280, + 'braceright': 389, + 'asciitilde': 584, + 'exclamdown': 333, + 'cent': 556, + 'sterling': 556, + 'fraction': 167, + 'yen': 556, + 'florin': 556, + 'section': 556, + 'currency': 556, + 'quotesingle': 238, + 'quotedblleft': 500, + 'guillemotleft': 556, + 'guilsinglleft': 333, + 'guilsinglright': 333, + 'fi': 611, + 'fl': 611, + 'endash': 556, + 'dagger': 556, + 'daggerdbl': 556, + 'periodcentered': 278, + 'paragraph': 556, + 'bullet': 350, + 'quotesinglbase': 278, + 'quotedblbase': 500, + 'quotedblright': 500, + 'guillemotright': 556, + 'ellipsis': 1000, + 'perthousand': 1000, + 'questiondown': 611, + 'grave': 333, + 'acute': 333, + 'circumflex': 333, + 'tilde': 333, + 'macron': 333, + 'breve': 333, + 'dotaccent': 333, + 'dieresis': 333, + 'ring': 333, + 'cedilla': 333, + 'hungarumlaut': 333, + 'ogonek': 333, + 'caron': 333, + 'emdash': 1000, + 'AE': 1000, + 'ordfeminine': 370, + 'Lslash': 611, + 'Oslash': 778, + 'OE': 1000, + 'ordmasculine': 365, + 'ae': 889, + 'dotlessi': 278, + 'lslash': 278, + 'oslash': 611, + 'oe': 944, + 'germandbls': 611, + 'Idieresis': 278, + 'eacute': 556, + 'abreve': 556, + 'uhungarumlaut': 611, + 'ecaron': 556, + 'Ydieresis': 667, + 'divide': 584, + 'Yacute': 667, + 'Acircumflex': 722, + 'aacute': 556, + 'Ucircumflex': 722, + 'yacute': 556, + 'scommaaccent': 556, + 'ecircumflex': 556, + 'Uring': 722, + 'Udieresis': 722, + 'aogonek': 556, + 'Uacute': 722, + 'uogonek': 611, + 'Edieresis': 667, + 'Dcroat': 722, + 'commaaccent': 250, + 'copyright': 737, + 'Emacron': 667, + 'ccaron': 556, + 'aring': 556, + 'Ncommaaccent': 722, + 'lacute': 278, + 'agrave': 556, + 'Tcommaaccent': 611, + 'Cacute': 722, + 'atilde': 556, + 'Edotaccent': 667, + 'scaron': 556, + 'scedilla': 556, + 'iacute': 278, + 'lozenge': 494, + 'Rcaron': 722, + 'Gcommaaccent': 778, + 'ucircumflex': 611, + 'acircumflex': 556, + 'Amacron': 722, + 'rcaron': 389, + 'ccedilla': 556, + 'Zdotaccent': 611, + 'Thorn': 667, + 'Omacron': 778, + 'Racute': 722, + 'Sacute': 667, + 'dcaron': 743, + 'Umacron': 722, + 'uring': 611, + 'threesuperior': 333, + 'Ograve': 778, + 'Agrave': 722, + 'Abreve': 722, + 'multiply': 584, + 'uacute': 611, + 'Tcaron': 611, + 'partialdiff': 494, + 'ydieresis': 556, + 'Nacute': 722, + 'icircumflex': 278, + 'Ecircumflex': 667, + 'adieresis': 556, + 'edieresis': 556, + 'cacute': 556, + 'nacute': 611, + 'umacron': 611, + 'Ncaron': 722, + 'Iacute': 278, + 'plusminus': 584, + 'brokenbar': 280, + 'registered': 737, + 'Gbreve': 778, + 'Idotaccent': 278, + 'summation': 600, + 'Egrave': 667, + 'racute': 389, + 'omacron': 611, + 'Zacute': 611, + 'Zcaron': 611, + 'greaterequal': 549, + 'Eth': 722, + 'Ccedilla': 722, + 'lcommaaccent': 278, + 'tcaron': 389, + 'eogonek': 556, + 'Uogonek': 722, + 'Aacute': 722, + 'Adieresis': 722, + 'egrave': 556, + 'zacute': 500, + 'iogonek': 278, + 'Oacute': 778, + 'oacute': 611, + 'amacron': 556, + 'sacute': 556, + 'idieresis': 278, + 'Ocircumflex': 778, + 'Ugrave': 722, + 'Delta': 612, + 'thorn': 611, + 'twosuperior': 333, + 'Odieresis': 778, + 'mu': 611, + 'igrave': 278, + 'ohungarumlaut': 611, + 'Eogonek': 667, + 'dcroat': 611, + 'threequarters': 834, + 'Scedilla': 667, + 'lcaron': 400, + 'Kcommaaccent': 722, + 'Lacute': 611, + 'trademark': 1000, + 'edotaccent': 556, + 'Igrave': 278, + 'Imacron': 278, + 'Lcaron': 611, + 'onehalf': 834, + 'lessequal': 549, + 'ocircumflex': 611, + 'ntilde': 611, + 'Uhungarumlaut': 722, + 'Eacute': 667, + 'emacron': 556, + 'gbreve': 611, + 'onequarter': 834, + 'Scaron': 667, + 'Scommaaccent': 667, + 'Ohungarumlaut': 778, + 'degree': 400, + 'ograve': 611, + 'Ccaron': 722, + 'ugrave': 611, + 'radical': 549, + 'Dcaron': 722, + 'rcommaaccent': 389, + 'Ntilde': 722, + 'otilde': 611, + 'Rcommaaccent': 722, + 'Lcommaaccent': 611, + 'Atilde': 722, + 'Aogonek': 722, + 'Aring': 722, + 'Otilde': 778, + 'zdotaccent': 500, + 'Ecaron': 667, + 'Iogonek': 278, + 'kcommaaccent': 556, + 'minus': 584, + 'Icircumflex': 278, + 'ncaron': 611, + 'tcommaaccent': 333, + 'logicalnot': 584, + 'odieresis': 611, + 'udieresis': 611, + 'notequal': 549, + 'gcommaaccent': 611, + 'eth': 611, + 'zcaron': 500, + 'ncommaaccent': 611, + 'onesuperior': 333, + 'imacron': 278, + 'Euro': 556 + }, + 'Helvetica-Oblique' : { + 'space': 278, + 'exclam': 278, + 'quotedbl': 355, + 'numbersign': 556, + 'dollar': 556, + 'percent': 889, + 'ampersand': 667, + 'quoteright': 222, + 'parenleft': 333, + 'parenright': 333, + 'asterisk': 389, + 'plus': 584, + 'comma': 278, + 'hyphen': 333, + 'period': 278, + 'slash': 278, + 'zero': 556, + 'one': 556, + 'two': 556, + 'three': 556, + 'four': 556, + 'five': 556, + 'six': 556, + 'seven': 556, + 'eight': 556, + 'nine': 556, + 'colon': 278, + 'semicolon': 278, + 'less': 584, + 'equal': 584, + 'greater': 584, + 'question': 556, + 'at': 1015, + 'A': 667, + 'B': 667, + 'C': 722, + 'D': 722, + 'E': 667, + 'F': 611, + 'G': 778, + 'H': 722, + 'I': 278, + 'J': 500, + 'K': 667, + 'L': 556, + 'M': 833, + 'N': 722, + 'O': 778, + 'P': 667, + 'Q': 778, + 'R': 722, + 'S': 667, + 'T': 611, + 'U': 722, + 'V': 667, + 'W': 944, + 'X': 667, + 'Y': 667, + 'Z': 611, + 'bracketleft': 278, + 'backslash': 278, + 'bracketright': 278, + 'asciicircum': 469, + 'underscore': 556, + 'quoteleft': 222, + 'a': 556, + 'b': 556, + 'c': 500, + 'd': 556, + 'e': 556, + 'f': 278, + 'g': 556, + 'h': 556, + 'i': 222, + 'j': 222, + 'k': 500, + 'l': 222, + 'm': 833, + 'n': 556, + 'o': 556, + 'p': 556, + 'q': 556, + 'r': 333, + 's': 500, + 't': 278, + 'u': 556, + 'v': 500, + 'w': 722, + 'x': 500, + 'y': 500, + 'z': 500, + 'braceleft': 334, + 'bar': 260, + 'braceright': 334, + 'asciitilde': 584, + 'exclamdown': 333, + 'cent': 556, + 'sterling': 556, + 'fraction': 167, + 'yen': 556, + 'florin': 556, + 'section': 556, + 'currency': 556, + 'quotesingle': 191, + 'quotedblleft': 333, + 'guillemotleft': 556, + 'guilsinglleft': 333, + 'guilsinglright': 333, + 'fi': 500, + 'fl': 500, + 'endash': 556, + 'dagger': 556, + 'daggerdbl': 556, + 'periodcentered': 278, + 'paragraph': 537, + 'bullet': 350, + 'quotesinglbase': 222, + 'quotedblbase': 333, + 'quotedblright': 333, + 'guillemotright': 556, + 'ellipsis': 1000, + 'perthousand': 1000, + 'questiondown': 611, + 'grave': 333, + 'acute': 333, + 'circumflex': 333, + 'tilde': 333, + 'macron': 333, + 'breve': 333, + 'dotaccent': 333, + 'dieresis': 333, + 'ring': 333, + 'cedilla': 333, + 'hungarumlaut': 333, + 'ogonek': 333, + 'caron': 333, + 'emdash': 1000, + 'AE': 1000, + 'ordfeminine': 370, + 'Lslash': 556, + 'Oslash': 778, + 'OE': 1000, + 'ordmasculine': 365, + 'ae': 889, + 'dotlessi': 278, + 'lslash': 222, + 'oslash': 611, + 'oe': 944, + 'germandbls': 611, + 'Idieresis': 278, + 'eacute': 556, + 'abreve': 556, + 'uhungarumlaut': 556, + 'ecaron': 556, + 'Ydieresis': 667, + 'divide': 584, + 'Yacute': 667, + 'Acircumflex': 667, + 'aacute': 556, + 'Ucircumflex': 722, + 'yacute': 500, + 'scommaaccent': 500, + 'ecircumflex': 556, + 'Uring': 722, + 'Udieresis': 722, + 'aogonek': 556, + 'Uacute': 722, + 'uogonek': 556, + 'Edieresis': 667, + 'Dcroat': 722, + 'commaaccent': 250, + 'copyright': 737, + 'Emacron': 667, + 'ccaron': 500, + 'aring': 556, + 'Ncommaaccent': 722, + 'lacute': 222, + 'agrave': 556, + 'Tcommaaccent': 611, + 'Cacute': 722, + 'atilde': 556, + 'Edotaccent': 667, + 'scaron': 500, + 'scedilla': 500, + 'iacute': 278, + 'lozenge': 471, + 'Rcaron': 722, + 'Gcommaaccent': 778, + 'ucircumflex': 556, + 'acircumflex': 556, + 'Amacron': 667, + 'rcaron': 333, + 'ccedilla': 500, + 'Zdotaccent': 611, + 'Thorn': 667, + 'Omacron': 778, + 'Racute': 722, + 'Sacute': 667, + 'dcaron': 643, + 'Umacron': 722, + 'uring': 556, + 'threesuperior': 333, + 'Ograve': 778, + 'Agrave': 667, + 'Abreve': 667, + 'multiply': 584, + 'uacute': 556, + 'Tcaron': 611, + 'partialdiff': 476, + 'ydieresis': 500, + 'Nacute': 722, + 'icircumflex': 278, + 'Ecircumflex': 667, + 'adieresis': 556, + 'edieresis': 556, + 'cacute': 500, + 'nacute': 556, + 'umacron': 556, + 'Ncaron': 722, + 'Iacute': 278, + 'plusminus': 584, + 'brokenbar': 260, + 'registered': 737, + 'Gbreve': 778, + 'Idotaccent': 278, + 'summation': 600, + 'Egrave': 667, + 'racute': 333, + 'omacron': 556, + 'Zacute': 611, + 'Zcaron': 611, + 'greaterequal': 549, + 'Eth': 722, + 'Ccedilla': 722, + 'lcommaaccent': 222, + 'tcaron': 317, + 'eogonek': 556, + 'Uogonek': 722, + 'Aacute': 667, + 'Adieresis': 667, + 'egrave': 556, + 'zacute': 500, + 'iogonek': 222, + 'Oacute': 778, + 'oacute': 556, + 'amacron': 556, + 'sacute': 500, + 'idieresis': 278, + 'Ocircumflex': 778, + 'Ugrave': 722, + 'Delta': 612, + 'thorn': 556, + 'twosuperior': 333, + 'Odieresis': 778, + 'mu': 556, + 'igrave': 278, + 'ohungarumlaut': 556, + 'Eogonek': 667, + 'dcroat': 556, + 'threequarters': 834, + 'Scedilla': 667, + 'lcaron': 299, + 'Kcommaaccent': 667, + 'Lacute': 556, + 'trademark': 1000, + 'edotaccent': 556, + 'Igrave': 278, + 'Imacron': 278, + 'Lcaron': 556, + 'onehalf': 834, + 'lessequal': 549, + 'ocircumflex': 556, + 'ntilde': 556, + 'Uhungarumlaut': 722, + 'Eacute': 667, + 'emacron': 556, + 'gbreve': 556, + 'onequarter': 834, + 'Scaron': 667, + 'Scommaaccent': 667, + 'Ohungarumlaut': 778, + 'degree': 400, + 'ograve': 556, + 'Ccaron': 722, + 'ugrave': 556, + 'radical': 453, + 'Dcaron': 722, + 'rcommaaccent': 333, + 'Ntilde': 722, + 'otilde': 556, + 'Rcommaaccent': 722, + 'Lcommaaccent': 556, + 'Atilde': 667, + 'Aogonek': 667, + 'Aring': 667, + 'Otilde': 778, + 'zdotaccent': 500, + 'Ecaron': 667, + 'Iogonek': 278, + 'kcommaaccent': 500, + 'minus': 584, + 'Icircumflex': 278, + 'ncaron': 556, + 'tcommaaccent': 278, + 'logicalnot': 584, + 'odieresis': 556, + 'udieresis': 556, + 'notequal': 549, + 'gcommaaccent': 556, + 'eth': 556, + 'zcaron': 500, + 'ncommaaccent': 556, + 'onesuperior': 333, + 'imacron': 278, + 'Euro': 556 + }, + 'Symbol': { + 'space': 250, + 'exclam': 333, + 'universal': 713, + 'numbersign': 500, + 'existential': 549, + 'percent': 833, + 'ampersand': 778, + 'suchthat': 439, + 'parenleft': 333, + 'parenright': 333, + 'asteriskmath': 500, + 'plus': 549, + 'comma': 250, + 'minus': 549, + 'period': 250, + 'slash': 278, + 'zero': 500, + 'one': 500, + 'two': 500, + 'three': 500, + 'four': 500, + 'five': 500, + 'six': 500, + 'seven': 500, + 'eight': 500, + 'nine': 500, + 'colon': 278, + 'semicolon': 278, + 'less': 549, + 'equal': 549, + 'greater': 549, + 'question': 444, + 'congruent': 549, + 'Alpha': 722, + 'Beta': 667, + 'Chi': 722, + 'Delta': 612, + 'Epsilon': 611, + 'Phi': 763, + 'Gamma': 603, + 'Eta': 722, + 'Iota': 333, + 'theta1': 631, + 'Kappa': 722, + 'Lambda': 686, + 'Mu': 889, + 'Nu': 722, + 'Omicron': 722, + 'Pi': 768, + 'Theta': 741, + 'Rho': 556, + 'Sigma': 592, + 'Tau': 611, + 'Upsilon': 690, + 'sigma1': 439, + 'Omega': 768, + 'Xi': 645, + 'Psi': 795, + 'Zeta': 611, + 'bracketleft': 333, + 'therefore': 863, + 'bracketright': 333, + 'perpendicular': 658, + 'underscore': 500, + 'radicalex': 500, + 'alpha': 631, + 'beta': 549, + 'chi': 549, + 'delta': 494, + 'epsilon': 439, + 'phi': 521, + 'gamma': 411, + 'eta': 603, + 'iota': 329, + 'phi1': 603, + 'kappa': 549, + 'lambda': 549, + 'mu': 576, + 'nu': 521, + 'omicron': 549, + 'pi': 549, + 'theta': 521, + 'rho': 549, + 'sigma': 603, + 'tau': 439, + 'upsilon': 576, + 'omega1': 713, + 'omega': 686, + 'xi': 493, + 'psi': 686, + 'zeta': 494, + 'braceleft': 480, + 'bar': 200, + 'braceright': 480, + 'similar': 549, + 'Euro': 750, + 'Upsilon1': 620, + 'minute': 247, + 'lessequal': 549, + 'fraction': 167, + 'infinity': 713, + 'florin': 500, + 'club': 753, + 'diamond': 753, + 'heart': 753, + 'spade': 753, + 'arrowboth': 1042, + 'arrowleft': 987, + 'arrowup': 603, + 'arrowright': 987, + 'arrowdown': 603, + 'degree': 400, + 'plusminus': 549, + 'second': 411, + 'greaterequal': 549, + 'multiply': 549, + 'proportional': 713, + 'partialdiff': 494, + 'bullet': 460, + 'divide': 549, + 'notequal': 549, + 'equivalence': 549, + 'approxequal': 549, + 'ellipsis': 1000, + 'arrowvertex': 603, + 'arrowhorizex': 1000, + 'carriagereturn': 658, + 'aleph': 823, + 'Ifraktur': 686, + 'Rfraktur': 795, + 'weierstrass': 987, + 'circlemultiply': 768, + 'circleplus': 768, + 'emptyset': 823, + 'intersection': 768, + 'union': 768, + 'propersuperset': 713, + 'reflexsuperset': 713, + 'notsubset': 713, + 'propersubset': 713, + 'reflexsubset': 713, + 'element': 713, + 'notelement': 713, + 'angle': 768, + 'gradient': 713, + 'registerserif': 790, + 'copyrightserif': 790, + 'trademarkserif': 890, + 'product': 823, + 'radical': 549, + 'dotmath': 250, + 'logicalnot': 713, + 'logicaland': 603, + 'logicalor': 603, + 'arrowdblboth': 1042, + 'arrowdblleft': 987, + 'arrowdblup': 603, + 'arrowdblright': 987, + 'arrowdbldown': 603, + 'lozenge': 494, + 'angleleft': 329, + 'registersans': 790, + 'copyrightsans': 790, + 'trademarksans': 786, + 'summation': 713, + 'parenlefttp': 384, + 'parenleftex': 384, + 'parenleftbt': 384, + 'bracketlefttp': 384, + 'bracketleftex': 384, + 'bracketleftbt': 384, + 'bracelefttp': 494, + 'braceleftmid': 494, + 'braceleftbt': 494, + 'braceex': 494, + 'angleright': 329, + 'integral': 274, + 'integraltp': 686, + 'integralex': 686, + 'integralbt': 686, + 'parenrighttp': 384, + 'parenrightex': 384, + 'parenrightbt': 384, + 'bracketrighttp': 384, + 'bracketrightex': 384, + 'bracketrightbt': 384, + 'bracerighttp': 494, + 'bracerightmid': 494, + 'bracerightbt': 494, + 'apple': 790 + }, + 'Times-Roman': { + 'space': 250, + 'exclam': 333, + 'quotedbl': 408, + 'numbersign': 500, + 'dollar': 500, + 'percent': 833, + 'ampersand': 778, + 'quoteright': 333, + 'parenleft': 333, + 'parenright': 333, + 'asterisk': 500, + 'plus': 564, + 'comma': 250, + 'hyphen': 333, + 'period': 250, + 'slash': 278, + 'zero': 500, + 'one': 500, + 'two': 500, + 'three': 500, + 'four': 500, + 'five': 500, + 'six': 500, + 'seven': 500, + 'eight': 500, + 'nine': 500, + 'colon': 278, + 'semicolon': 278, + 'less': 564, + 'equal': 564, + 'greater': 564, + 'question': 444, + 'at': 921, + 'A': 722, + 'B': 667, + 'C': 667, + 'D': 722, + 'E': 611, + 'F': 556, + 'G': 722, + 'H': 722, + 'I': 333, + 'J': 389, + 'K': 722, + 'L': 611, + 'M': 889, + 'N': 722, + 'O': 722, + 'P': 556, + 'Q': 722, + 'R': 667, + 'S': 556, + 'T': 611, + 'U': 722, + 'V': 722, + 'W': 944, + 'X': 722, + 'Y': 722, + 'Z': 611, + 'bracketleft': 333, + 'backslash': 278, + 'bracketright': 333, + 'asciicircum': 469, + 'underscore': 500, + 'quoteleft': 333, + 'a': 444, + 'b': 500, + 'c': 444, + 'd': 500, + 'e': 444, + 'f': 333, + 'g': 500, + 'h': 500, + 'i': 278, + 'j': 278, + 'k': 500, + 'l': 278, + 'm': 778, + 'n': 500, + 'o': 500, + 'p': 500, + 'q': 500, + 'r': 333, + 's': 389, + 't': 278, + 'u': 500, + 'v': 500, + 'w': 722, + 'x': 500, + 'y': 500, + 'z': 444, + 'braceleft': 480, + 'bar': 200, + 'braceright': 480, + 'asciitilde': 541, + 'exclamdown': 333, + 'cent': 500, + 'sterling': 500, + 'fraction': 167, + 'yen': 500, + 'florin': 500, + 'section': 500, + 'currency': 500, + 'quotesingle': 180, + 'quotedblleft': 444, + 'guillemotleft': 500, + 'guilsinglleft': 333, + 'guilsinglright': 333, + 'fi': 556, + 'fl': 556, + 'endash': 500, + 'dagger': 500, + 'daggerdbl': 500, + 'periodcentered': 250, + 'paragraph': 453, + 'bullet': 350, + 'quotesinglbase': 333, + 'quotedblbase': 444, + 'quotedblright': 444, + 'guillemotright': 500, + 'ellipsis': 1000, + 'perthousand': 1000, + 'questiondown': 444, + 'grave': 333, + 'acute': 333, + 'circumflex': 333, + 'tilde': 333, + 'macron': 333, + 'breve': 333, + 'dotaccent': 333, + 'dieresis': 333, + 'ring': 333, + 'cedilla': 333, + 'hungarumlaut': 333, + 'ogonek': 333, + 'caron': 333, + 'emdash': 1000, + 'AE': 889, + 'ordfeminine': 276, + 'Lslash': 611, + 'Oslash': 722, + 'OE': 889, + 'ordmasculine': 310, + 'ae': 667, + 'dotlessi': 278, + 'lslash': 278, + 'oslash': 500, + 'oe': 722, + 'germandbls': 500, + 'Idieresis': 333, + 'eacute': 444, + 'abreve': 444, + 'uhungarumlaut': 500, + 'ecaron': 444, + 'Ydieresis': 722, + 'divide': 564, + 'Yacute': 722, + 'Acircumflex': 722, + 'aacute': 444, + 'Ucircumflex': 722, + 'yacute': 500, + 'scommaaccent': 389, + 'ecircumflex': 444, + 'Uring': 722, + 'Udieresis': 722, + 'aogonek': 444, + 'Uacute': 722, + 'uogonek': 500, + 'Edieresis': 611, + 'Dcroat': 722, + 'commaaccent': 250, + 'copyright': 760, + 'Emacron': 611, + 'ccaron': 444, + 'aring': 444, + 'Ncommaaccent': 722, + 'lacute': 278, + 'agrave': 444, + 'Tcommaaccent': 611, + 'Cacute': 667, + 'atilde': 444, + 'Edotaccent': 611, + 'scaron': 389, + 'scedilla': 389, + 'iacute': 278, + 'lozenge': 471, + 'Rcaron': 667, + 'Gcommaaccent': 722, + 'ucircumflex': 500, + 'acircumflex': 444, + 'Amacron': 722, + 'rcaron': 333, + 'ccedilla': 444, + 'Zdotaccent': 611, + 'Thorn': 556, + 'Omacron': 722, + 'Racute': 667, + 'Sacute': 556, + 'dcaron': 588, + 'Umacron': 722, + 'uring': 500, + 'threesuperior': 300, + 'Ograve': 722, + 'Agrave': 722, + 'Abreve': 722, + 'multiply': 564, + 'uacute': 500, + 'Tcaron': 611, + 'partialdiff': 476, + 'ydieresis': 500, + 'Nacute': 722, + 'icircumflex': 278, + 'Ecircumflex': 611, + 'adieresis': 444, + 'edieresis': 444, + 'cacute': 444, + 'nacute': 500, + 'umacron': 500, + 'Ncaron': 722, + 'Iacute': 333, + 'plusminus': 564, + 'brokenbar': 200, + 'registered': 760, + 'Gbreve': 722, + 'Idotaccent': 333, + 'summation': 600, + 'Egrave': 611, + 'racute': 333, + 'omacron': 500, + 'Zacute': 611, + 'Zcaron': 611, + 'greaterequal': 549, + 'Eth': 722, + 'Ccedilla': 667, + 'lcommaaccent': 278, + 'tcaron': 326, + 'eogonek': 444, + 'Uogonek': 722, + 'Aacute': 722, + 'Adieresis': 722, + 'egrave': 444, + 'zacute': 444, + 'iogonek': 278, + 'Oacute': 722, + 'oacute': 500, + 'amacron': 444, + 'sacute': 389, + 'idieresis': 278, + 'Ocircumflex': 722, + 'Ugrave': 722, + 'Delta': 612, + 'thorn': 500, + 'twosuperior': 300, + 'Odieresis': 722, + 'mu': 500, + 'igrave': 278, + 'ohungarumlaut': 500, + 'Eogonek': 611, + 'dcroat': 500, + 'threequarters': 750, + 'Scedilla': 556, + 'lcaron': 344, + 'Kcommaaccent': 722, + 'Lacute': 611, + 'trademark': 980, + 'edotaccent': 444, + 'Igrave': 333, + 'Imacron': 333, + 'Lcaron': 611, + 'onehalf': 750, + 'lessequal': 549, + 'ocircumflex': 500, + 'ntilde': 500, + 'Uhungarumlaut': 722, + 'Eacute': 611, + 'emacron': 444, + 'gbreve': 500, + 'onequarter': 750, + 'Scaron': 556, + 'Scommaaccent': 556, + 'Ohungarumlaut': 722, + 'degree': 400, + 'ograve': 500, + 'Ccaron': 667, + 'ugrave': 500, + 'radical': 453, + 'Dcaron': 722, + 'rcommaaccent': 333, + 'Ntilde': 722, + 'otilde': 500, + 'Rcommaaccent': 667, + 'Lcommaaccent': 611, + 'Atilde': 722, + 'Aogonek': 722, + 'Aring': 722, + 'Otilde': 722, + 'zdotaccent': 444, + 'Ecaron': 611, + 'Iogonek': 333, + 'kcommaaccent': 500, + 'minus': 564, + 'Icircumflex': 333, + 'ncaron': 500, + 'tcommaaccent': 278, + 'logicalnot': 564, + 'odieresis': 500, + 'udieresis': 500, + 'notequal': 549, + 'gcommaaccent': 500, + 'eth': 500, + 'zcaron': 444, + 'ncommaaccent': 500, + 'onesuperior': 300, + 'imacron': 278, + 'Euro': 500 + }, + 'Times-Bold': { + 'space': 250, + 'exclam': 333, + 'quotedbl': 555, + 'numbersign': 500, + 'dollar': 500, + 'percent': 1000, + 'ampersand': 833, + 'quoteright': 333, + 'parenleft': 333, + 'parenright': 333, + 'asterisk': 500, + 'plus': 570, + 'comma': 250, + 'hyphen': 333, + 'period': 250, + 'slash': 278, + 'zero': 500, + 'one': 500, + 'two': 500, + 'three': 500, + 'four': 500, + 'five': 500, + 'six': 500, + 'seven': 500, + 'eight': 500, + 'nine': 500, + 'colon': 333, + 'semicolon': 333, + 'less': 570, + 'equal': 570, + 'greater': 570, + 'question': 500, + 'at': 930, + 'A': 722, + 'B': 667, + 'C': 722, + 'D': 722, + 'E': 667, + 'F': 611, + 'G': 778, + 'H': 778, + 'I': 389, + 'J': 500, + 'K': 778, + 'L': 667, + 'M': 944, + 'N': 722, + 'O': 778, + 'P': 611, + 'Q': 778, + 'R': 722, + 'S': 556, + 'T': 667, + 'U': 722, + 'V': 722, + 'W': 1000, + 'X': 722, + 'Y': 722, + 'Z': 667, + 'bracketleft': 333, + 'backslash': 278, + 'bracketright': 333, + 'asciicircum': 581, + 'underscore': 500, + 'quoteleft': 333, + 'a': 500, + 'b': 556, + 'c': 444, + 'd': 556, + 'e': 444, + 'f': 333, + 'g': 500, + 'h': 556, + 'i': 278, + 'j': 333, + 'k': 556, + 'l': 278, + 'm': 833, + 'n': 556, + 'o': 500, + 'p': 556, + 'q': 556, + 'r': 444, + 's': 389, + 't': 333, + 'u': 556, + 'v': 500, + 'w': 722, + 'x': 500, + 'y': 500, + 'z': 444, + 'braceleft': 394, + 'bar': 220, + 'braceright': 394, + 'asciitilde': 520, + 'exclamdown': 333, + 'cent': 500, + 'sterling': 500, + 'fraction': 167, + 'yen': 500, + 'florin': 500, + 'section': 500, + 'currency': 500, + 'quotesingle': 278, + 'quotedblleft': 500, + 'guillemotleft': 500, + 'guilsinglleft': 333, + 'guilsinglright': 333, + 'fi': 556, + 'fl': 556, + 'endash': 500, + 'dagger': 500, + 'daggerdbl': 500, + 'periodcentered': 250, + 'paragraph': 540, + 'bullet': 350, + 'quotesinglbase': 333, + 'quotedblbase': 500, + 'quotedblright': 500, + 'guillemotright': 500, + 'ellipsis': 1000, + 'perthousand': 1000, + 'questiondown': 500, + 'grave': 333, + 'acute': 333, + 'circumflex': 333, + 'tilde': 333, + 'macron': 333, + 'breve': 333, + 'dotaccent': 333, + 'dieresis': 333, + 'ring': 333, + 'cedilla': 333, + 'hungarumlaut': 333, + 'ogonek': 333, + 'caron': 333, + 'emdash': 1000, + 'AE': 1000, + 'ordfeminine': 300, + 'Lslash': 667, + 'Oslash': 778, + 'OE': 1000, + 'ordmasculine': 330, + 'ae': 722, + 'dotlessi': 278, + 'lslash': 278, + 'oslash': 500, + 'oe': 722, + 'germandbls': 556, + 'Idieresis': 389, + 'eacute': 444, + 'abreve': 500, + 'uhungarumlaut': 556, + 'ecaron': 444, + 'Ydieresis': 722, + 'divide': 570, + 'Yacute': 722, + 'Acircumflex': 722, + 'aacute': 500, + 'Ucircumflex': 722, + 'yacute': 500, + 'scommaaccent': 389, + 'ecircumflex': 444, + 'Uring': 722, + 'Udieresis': 722, + 'aogonek': 500, + 'Uacute': 722, + 'uogonek': 556, + 'Edieresis': 667, + 'Dcroat': 722, + 'commaaccent': 250, + 'copyright': 747, + 'Emacron': 667, + 'ccaron': 444, + 'aring': 500, + 'Ncommaaccent': 722, + 'lacute': 278, + 'agrave': 500, + 'Tcommaaccent': 667, + 'Cacute': 722, + 'atilde': 500, + 'Edotaccent': 667, + 'scaron': 389, + 'scedilla': 389, + 'iacute': 278, + 'lozenge': 494, + 'Rcaron': 722, + 'Gcommaaccent': 778, + 'ucircumflex': 556, + 'acircumflex': 500, + 'Amacron': 722, + 'rcaron': 444, + 'ccedilla': 444, + 'Zdotaccent': 667, + 'Thorn': 611, + 'Omacron': 778, + 'Racute': 722, + 'Sacute': 556, + 'dcaron': 672, + 'Umacron': 722, + 'uring': 556, + 'threesuperior': 300, + 'Ograve': 778, + 'Agrave': 722, + 'Abreve': 722, + 'multiply': 570, + 'uacute': 556, + 'Tcaron': 667, + 'partialdiff': 494, + 'ydieresis': 500, + 'Nacute': 722, + 'icircumflex': 278, + 'Ecircumflex': 667, + 'adieresis': 500, + 'edieresis': 444, + 'cacute': 444, + 'nacute': 556, + 'umacron': 556, + 'Ncaron': 722, + 'Iacute': 389, + 'plusminus': 570, + 'brokenbar': 220, + 'registered': 747, + 'Gbreve': 778, + 'Idotaccent': 389, + 'summation': 600, + 'Egrave': 667, + 'racute': 444, + 'omacron': 500, + 'Zacute': 667, + 'Zcaron': 667, + 'greaterequal': 549, + 'Eth': 722, + 'Ccedilla': 722, + 'lcommaaccent': 278, + 'tcaron': 416, + 'eogonek': 444, + 'Uogonek': 722, + 'Aacute': 722, + 'Adieresis': 722, + 'egrave': 444, + 'zacute': 444, + 'iogonek': 278, + 'Oacute': 778, + 'oacute': 500, + 'amacron': 500, + 'sacute': 389, + 'idieresis': 278, + 'Ocircumflex': 778, + 'Ugrave': 722, + 'Delta': 612, + 'thorn': 556, + 'twosuperior': 300, + 'Odieresis': 778, + 'mu': 556, + 'igrave': 278, + 'ohungarumlaut': 500, + 'Eogonek': 667, + 'dcroat': 556, + 'threequarters': 750, + 'Scedilla': 556, + 'lcaron': 394, + 'Kcommaaccent': 778, + 'Lacute': 667, + 'trademark': 1000, + 'edotaccent': 444, + 'Igrave': 389, + 'Imacron': 389, + 'Lcaron': 667, + 'onehalf': 750, + 'lessequal': 549, + 'ocircumflex': 500, + 'ntilde': 556, + 'Uhungarumlaut': 722, + 'Eacute': 667, + 'emacron': 444, + 'gbreve': 500, + 'onequarter': 750, + 'Scaron': 556, + 'Scommaaccent': 556, + 'Ohungarumlaut': 778, + 'degree': 400, + 'ograve': 500, + 'Ccaron': 722, + 'ugrave': 556, + 'radical': 549, + 'Dcaron': 722, + 'rcommaaccent': 444, + 'Ntilde': 722, + 'otilde': 500, + 'Rcommaaccent': 722, + 'Lcommaaccent': 667, + 'Atilde': 722, + 'Aogonek': 722, + 'Aring': 722, + 'Otilde': 778, + 'zdotaccent': 444, + 'Ecaron': 667, + 'Iogonek': 389, + 'kcommaaccent': 556, + 'minus': 570, + 'Icircumflex': 389, + 'ncaron': 556, + 'tcommaaccent': 333, + 'logicalnot': 570, + 'odieresis': 500, + 'udieresis': 556, + 'notequal': 549, + 'gcommaaccent': 500, + 'eth': 500, + 'zcaron': 444, + 'ncommaaccent': 556, + 'onesuperior': 300, + 'imacron': 278, + 'Euro': 500 + }, + 'Times-BoldItalic': { + 'space': 250, + 'exclam': 389, + 'quotedbl': 555, + 'numbersign': 500, + 'dollar': 500, + 'percent': 833, + 'ampersand': 778, + 'quoteright': 333, + 'parenleft': 333, + 'parenright': 333, + 'asterisk': 500, + 'plus': 570, + 'comma': 250, + 'hyphen': 333, + 'period': 250, + 'slash': 278, + 'zero': 500, + 'one': 500, + 'two': 500, + 'three': 500, + 'four': 500, + 'five': 500, + 'six': 500, + 'seven': 500, + 'eight': 500, + 'nine': 500, + 'colon': 333, + 'semicolon': 333, + 'less': 570, + 'equal': 570, + 'greater': 570, + 'question': 500, + 'at': 832, + 'A': 667, + 'B': 667, + 'C': 667, + 'D': 722, + 'E': 667, + 'F': 667, + 'G': 722, + 'H': 778, + 'I': 389, + 'J': 500, + 'K': 667, + 'L': 611, + 'M': 889, + 'N': 722, + 'O': 722, + 'P': 611, + 'Q': 722, + 'R': 667, + 'S': 556, + 'T': 611, + 'U': 722, + 'V': 667, + 'W': 889, + 'X': 667, + 'Y': 611, + 'Z': 611, + 'bracketleft': 333, + 'backslash': 278, + 'bracketright': 333, + 'asciicircum': 570, + 'underscore': 500, + 'quoteleft': 333, + 'a': 500, + 'b': 500, + 'c': 444, + 'd': 500, + 'e': 444, + 'f': 333, + 'g': 500, + 'h': 556, + 'i': 278, + 'j': 278, + 'k': 500, + 'l': 278, + 'm': 778, + 'n': 556, + 'o': 500, + 'p': 500, + 'q': 500, + 'r': 389, + 's': 389, + 't': 278, + 'u': 556, + 'v': 444, + 'w': 667, + 'x': 500, + 'y': 444, + 'z': 389, + 'braceleft': 348, + 'bar': 220, + 'braceright': 348, + 'asciitilde': 570, + 'exclamdown': 389, + 'cent': 500, + 'sterling': 500, + 'fraction': 167, + 'yen': 500, + 'florin': 500, + 'section': 500, + 'currency': 500, + 'quotesingle': 278, + 'quotedblleft': 500, + 'guillemotleft': 500, + 'guilsinglleft': 333, + 'guilsinglright': 333, + 'fi': 556, + 'fl': 556, + 'endash': 500, + 'dagger': 500, + 'daggerdbl': 500, + 'periodcentered': 250, + 'paragraph': 500, + 'bullet': 350, + 'quotesinglbase': 333, + 'quotedblbase': 500, + 'quotedblright': 500, + 'guillemotright': 500, + 'ellipsis': 1000, + 'perthousand': 1000, + 'questiondown': 500, + 'grave': 333, + 'acute': 333, + 'circumflex': 333, + 'tilde': 333, + 'macron': 333, + 'breve': 333, + 'dotaccent': 333, + 'dieresis': 333, + 'ring': 333, + 'cedilla': 333, + 'hungarumlaut': 333, + 'ogonek': 333, + 'caron': 333, + 'emdash': 1000, + 'AE': 944, + 'ordfeminine': 266, + 'Lslash': 611, + 'Oslash': 722, + 'OE': 944, + 'ordmasculine': 300, + 'ae': 722, + 'dotlessi': 278, + 'lslash': 278, + 'oslash': 500, + 'oe': 722, + 'germandbls': 500, + 'Idieresis': 389, + 'eacute': 444, + 'abreve': 500, + 'uhungarumlaut': 556, + 'ecaron': 444, + 'Ydieresis': 611, + 'divide': 570, + 'Yacute': 611, + 'Acircumflex': 667, + 'aacute': 500, + 'Ucircumflex': 722, + 'yacute': 444, + 'scommaaccent': 389, + 'ecircumflex': 444, + 'Uring': 722, + 'Udieresis': 722, + 'aogonek': 500, + 'Uacute': 722, + 'uogonek': 556, + 'Edieresis': 667, + 'Dcroat': 722, + 'commaaccent': 250, + 'copyright': 747, + 'Emacron': 667, + 'ccaron': 444, + 'aring': 500, + 'Ncommaaccent': 722, + 'lacute': 278, + 'agrave': 500, + 'Tcommaaccent': 611, + 'Cacute': 667, + 'atilde': 500, + 'Edotaccent': 667, + 'scaron': 389, + 'scedilla': 389, + 'iacute': 278, + 'lozenge': 494, + 'Rcaron': 667, + 'Gcommaaccent': 722, + 'ucircumflex': 556, + 'acircumflex': 500, + 'Amacron': 667, + 'rcaron': 389, + 'ccedilla': 444, + 'Zdotaccent': 611, + 'Thorn': 611, + 'Omacron': 722, + 'Racute': 667, + 'Sacute': 556, + 'dcaron': 608, + 'Umacron': 722, + 'uring': 556, + 'threesuperior': 300, + 'Ograve': 722, + 'Agrave': 667, + 'Abreve': 667, + 'multiply': 570, + 'uacute': 556, + 'Tcaron': 611, + 'partialdiff': 494, + 'ydieresis': 444, + 'Nacute': 722, + 'icircumflex': 278, + 'Ecircumflex': 667, + 'adieresis': 500, + 'edieresis': 444, + 'cacute': 444, + 'nacute': 556, + 'umacron': 556, + 'Ncaron': 722, + 'Iacute': 389, + 'plusminus': 570, + 'brokenbar': 220, + 'registered': 747, + 'Gbreve': 722, + 'Idotaccent': 389, + 'summation': 600, + 'Egrave': 667, + 'racute': 389, + 'omacron': 500, + 'Zacute': 611, + 'Zcaron': 611, + 'greaterequal': 549, + 'Eth': 722, + 'Ccedilla': 667, + 'lcommaaccent': 278, + 'tcaron': 366, + 'eogonek': 444, + 'Uogonek': 722, + 'Aacute': 667, + 'Adieresis': 667, + 'egrave': 444, + 'zacute': 389, + 'iogonek': 278, + 'Oacute': 722, + 'oacute': 500, + 'amacron': 500, + 'sacute': 389, + 'idieresis': 278, + 'Ocircumflex': 722, + 'Ugrave': 722, + 'Delta': 612, + 'thorn': 500, + 'twosuperior': 300, + 'Odieresis': 722, + 'mu': 576, + 'igrave': 278, + 'ohungarumlaut': 500, + 'Eogonek': 667, + 'dcroat': 500, + 'threequarters': 750, + 'Scedilla': 556, + 'lcaron': 382, + 'Kcommaaccent': 667, + 'Lacute': 611, + 'trademark': 1000, + 'edotaccent': 444, + 'Igrave': 389, + 'Imacron': 389, + 'Lcaron': 611, + 'onehalf': 750, + 'lessequal': 549, + 'ocircumflex': 500, + 'ntilde': 556, + 'Uhungarumlaut': 722, + 'Eacute': 667, + 'emacron': 444, + 'gbreve': 500, + 'onequarter': 750, + 'Scaron': 556, + 'Scommaaccent': 556, + 'Ohungarumlaut': 722, + 'degree': 400, + 'ograve': 500, + 'Ccaron': 667, + 'ugrave': 556, + 'radical': 549, + 'Dcaron': 722, + 'rcommaaccent': 389, + 'Ntilde': 722, + 'otilde': 500, + 'Rcommaaccent': 667, + 'Lcommaaccent': 611, + 'Atilde': 667, + 'Aogonek': 667, + 'Aring': 667, + 'Otilde': 722, + 'zdotaccent': 389, + 'Ecaron': 667, + 'Iogonek': 389, + 'kcommaaccent': 500, + 'minus': 606, + 'Icircumflex': 389, + 'ncaron': 556, + 'tcommaaccent': 278, + 'logicalnot': 606, + 'odieresis': 500, + 'udieresis': 556, + 'notequal': 549, + 'gcommaaccent': 500, + 'eth': 500, + 'zcaron': 389, + 'ncommaaccent': 556, + 'onesuperior': 300, + 'imacron': 278, + 'Euro': 500 + }, + 'Times-Italic': { + 'space': 250, + 'exclam': 333, + 'quotedbl': 420, + 'numbersign': 500, + 'dollar': 500, + 'percent': 833, + 'ampersand': 778, + 'quoteright': 333, + 'parenleft': 333, + 'parenright': 333, + 'asterisk': 500, + 'plus': 675, + 'comma': 250, + 'hyphen': 333, + 'period': 250, + 'slash': 278, + 'zero': 500, + 'one': 500, + 'two': 500, + 'three': 500, + 'four': 500, + 'five': 500, + 'six': 500, + 'seven': 500, + 'eight': 500, + 'nine': 500, + 'colon': 333, + 'semicolon': 333, + 'less': 675, + 'equal': 675, + 'greater': 675, + 'question': 500, + 'at': 920, + 'A': 611, + 'B': 611, + 'C': 667, + 'D': 722, + 'E': 611, + 'F': 611, + 'G': 722, + 'H': 722, + 'I': 333, + 'J': 444, + 'K': 667, + 'L': 556, + 'M': 833, + 'N': 667, + 'O': 722, + 'P': 611, + 'Q': 722, + 'R': 611, + 'S': 500, + 'T': 556, + 'U': 722, + 'V': 611, + 'W': 833, + 'X': 611, + 'Y': 556, + 'Z': 556, + 'bracketleft': 389, + 'backslash': 278, + 'bracketright': 389, + 'asciicircum': 422, + 'underscore': 500, + 'quoteleft': 333, + 'a': 500, + 'b': 500, + 'c': 444, + 'd': 500, + 'e': 444, + 'f': 278, + 'g': 500, + 'h': 500, + 'i': 278, + 'j': 278, + 'k': 444, + 'l': 278, + 'm': 722, + 'n': 500, + 'o': 500, + 'p': 500, + 'q': 500, + 'r': 389, + 's': 389, + 't': 278, + 'u': 500, + 'v': 444, + 'w': 667, + 'x': 444, + 'y': 444, + 'z': 389, + 'braceleft': 400, + 'bar': 275, + 'braceright': 400, + 'asciitilde': 541, + 'exclamdown': 389, + 'cent': 500, + 'sterling': 500, + 'fraction': 167, + 'yen': 500, + 'florin': 500, + 'section': 500, + 'currency': 500, + 'quotesingle': 214, + 'quotedblleft': 556, + 'guillemotleft': 500, + 'guilsinglleft': 333, + 'guilsinglright': 333, + 'fi': 500, + 'fl': 500, + 'endash': 500, + 'dagger': 500, + 'daggerdbl': 500, + 'periodcentered': 250, + 'paragraph': 523, + 'bullet': 350, + 'quotesinglbase': 333, + 'quotedblbase': 556, + 'quotedblright': 556, + 'guillemotright': 500, + 'ellipsis': 889, + 'perthousand': 1000, + 'questiondown': 500, + 'grave': 333, + 'acute': 333, + 'circumflex': 333, + 'tilde': 333, + 'macron': 333, + 'breve': 333, + 'dotaccent': 333, + 'dieresis': 333, + 'ring': 333, + 'cedilla': 333, + 'hungarumlaut': 333, + 'ogonek': 333, + 'caron': 333, + 'emdash': 889, + 'AE': 889, + 'ordfeminine': 276, + 'Lslash': 556, + 'Oslash': 722, + 'OE': 944, + 'ordmasculine': 310, + 'ae': 667, + 'dotlessi': 278, + 'lslash': 278, + 'oslash': 500, + 'oe': 667, + 'germandbls': 500, + 'Idieresis': 333, + 'eacute': 444, + 'abreve': 500, + 'uhungarumlaut': 500, + 'ecaron': 444, + 'Ydieresis': 556, + 'divide': 675, + 'Yacute': 556, + 'Acircumflex': 611, + 'aacute': 500, + 'Ucircumflex': 722, + 'yacute': 444, + 'scommaaccent': 389, + 'ecircumflex': 444, + 'Uring': 722, + 'Udieresis': 722, + 'aogonek': 500, + 'Uacute': 722, + 'uogonek': 500, + 'Edieresis': 611, + 'Dcroat': 722, + 'commaaccent': 250, + 'copyright': 760, + 'Emacron': 611, + 'ccaron': 444, + 'aring': 500, + 'Ncommaaccent': 667, + 'lacute': 278, + 'agrave': 500, + 'Tcommaaccent': 556, + 'Cacute': 667, + 'atilde': 500, + 'Edotaccent': 611, + 'scaron': 389, + 'scedilla': 389, + 'iacute': 278, + 'lozenge': 471, + 'Rcaron': 611, + 'Gcommaaccent': 722, + 'ucircumflex': 500, + 'acircumflex': 500, + 'Amacron': 611, + 'rcaron': 389, + 'ccedilla': 444, + 'Zdotaccent': 556, + 'Thorn': 611, + 'Omacron': 722, + 'Racute': 611, + 'Sacute': 500, + 'dcaron': 544, + 'Umacron': 722, + 'uring': 500, + 'threesuperior': 300, + 'Ograve': 722, + 'Agrave': 611, + 'Abreve': 611, + 'multiply': 675, + 'uacute': 500, + 'Tcaron': 556, + 'partialdiff': 476, + 'ydieresis': 444, + 'Nacute': 667, + 'icircumflex': 278, + 'Ecircumflex': 611, + 'adieresis': 500, + 'edieresis': 444, + 'cacute': 444, + 'nacute': 500, + 'umacron': 500, + 'Ncaron': 667, + 'Iacute': 333, + 'plusminus': 675, + 'brokenbar': 275, + 'registered': 760, + 'Gbreve': 722, + 'Idotaccent': 333, + 'summation': 600, + 'Egrave': 611, + 'racute': 389, + 'omacron': 500, + 'Zacute': 556, + 'Zcaron': 556, + 'greaterequal': 549, + 'Eth': 722, + 'Ccedilla': 667, + 'lcommaaccent': 278, + 'tcaron': 300, + 'eogonek': 444, + 'Uogonek': 722, + 'Aacute': 611, + 'Adieresis': 611, + 'egrave': 444, + 'zacute': 389, + 'iogonek': 278, + 'Oacute': 722, + 'oacute': 500, + 'amacron': 500, + 'sacute': 389, + 'idieresis': 278, + 'Ocircumflex': 722, + 'Ugrave': 722, + 'Delta': 612, + 'thorn': 500, + 'twosuperior': 300, + 'Odieresis': 722, + 'mu': 500, + 'igrave': 278, + 'ohungarumlaut': 500, + 'Eogonek': 611, + 'dcroat': 500, + 'threequarters': 750, + 'Scedilla': 500, + 'lcaron': 300, + 'Kcommaaccent': 667, + 'Lacute': 556, + 'trademark': 980, + 'edotaccent': 444, + 'Igrave': 333, + 'Imacron': 333, + 'Lcaron': 611, + 'onehalf': 750, + 'lessequal': 549, + 'ocircumflex': 500, + 'ntilde': 500, + 'Uhungarumlaut': 722, + 'Eacute': 611, + 'emacron': 444, + 'gbreve': 500, + 'onequarter': 750, + 'Scaron': 500, + 'Scommaaccent': 500, + 'Ohungarumlaut': 722, + 'degree': 400, + 'ograve': 500, + 'Ccaron': 667, + 'ugrave': 500, + 'radical': 453, + 'Dcaron': 722, + 'rcommaaccent': 389, + 'Ntilde': 667, + 'otilde': 500, + 'Rcommaaccent': 611, + 'Lcommaaccent': 556, + 'Atilde': 611, + 'Aogonek': 611, + 'Aring': 611, + 'Otilde': 722, + 'zdotaccent': 389, + 'Ecaron': 611, + 'Iogonek': 333, + 'kcommaaccent': 444, + 'minus': 675, + 'Icircumflex': 333, + 'ncaron': 500, + 'tcommaaccent': 278, + 'logicalnot': 675, + 'odieresis': 500, + 'udieresis': 500, + 'notequal': 549, + 'gcommaaccent': 500, + 'eth': 500, + 'zcaron': 389, + 'ncommaaccent': 500, + 'onesuperior': 300, + 'imacron': 278, + 'Euro': 500 + }, + 'ZapfDingbats': { + 'space': 278, + 'a1': 974, + 'a2': 961, + 'a202': 974, + 'a3': 980, + 'a4': 719, + 'a5': 789, + 'a119': 790, + 'a118': 791, + 'a117': 690, + 'a11': 960, + 'a12': 939, + 'a13': 549, + 'a14': 855, + 'a15': 911, + 'a16': 933, + 'a105': 911, + 'a17': 945, + 'a18': 974, + 'a19': 755, + 'a20': 846, + 'a21': 762, + 'a22': 761, + 'a23': 571, + 'a24': 677, + 'a25': 763, + 'a26': 760, + 'a27': 759, + 'a28': 754, + 'a6': 494, + 'a7': 552, + 'a8': 537, + 'a9': 577, + 'a10': 692, + 'a29': 786, + 'a30': 788, + 'a31': 788, + 'a32': 790, + 'a33': 793, + 'a34': 794, + 'a35': 816, + 'a36': 823, + 'a37': 789, + 'a38': 841, + 'a39': 823, + 'a40': 833, + 'a41': 816, + 'a42': 831, + 'a43': 923, + 'a44': 744, + 'a45': 723, + 'a46': 749, + 'a47': 790, + 'a48': 792, + 'a49': 695, + 'a50': 776, + 'a51': 768, + 'a52': 792, + 'a53': 759, + 'a54': 707, + 'a55': 708, + 'a56': 682, + 'a57': 701, + 'a58': 826, + 'a59': 815, + 'a60': 789, + 'a61': 789, + 'a62': 707, + 'a63': 687, + 'a64': 696, + 'a65': 689, + 'a66': 786, + 'a67': 787, + 'a68': 713, + 'a69': 791, + 'a70': 785, + 'a71': 791, + 'a72': 873, + 'a73': 761, + 'a74': 762, + 'a203': 762, + 'a75': 759, + 'a204': 759, + 'a76': 892, + 'a77': 892, + 'a78': 788, + 'a79': 784, + 'a81': 438, + 'a82': 138, + 'a83': 277, + 'a84': 415, + 'a97': 392, + 'a98': 392, + 'a99': 668, + 'a100': 668, + 'a89': 390, + 'a90': 390, + 'a93': 317, + 'a94': 317, + 'a91': 276, + 'a92': 276, + 'a205': 509, + 'a85': 509, + 'a206': 410, + 'a86': 410, + 'a87': 234, + 'a88': 234, + 'a95': 334, + 'a96': 334, + 'a101': 732, + 'a102': 544, + 'a103': 544, + 'a104': 910, + 'a106': 667, + 'a107': 760, + 'a108': 760, + 'a112': 776, + 'a111': 595, + 'a110': 694, + 'a109': 626, + 'a120': 788, + 'a121': 788, + 'a122': 788, + 'a123': 788, + 'a124': 788, + 'a125': 788, + 'a126': 788, + 'a127': 788, + 'a128': 788, + 'a129': 788, + 'a130': 788, + 'a131': 788, + 'a132': 788, + 'a133': 788, + 'a134': 788, + 'a135': 788, + 'a136': 788, + 'a137': 788, + 'a138': 788, + 'a139': 788, + 'a140': 788, + 'a141': 788, + 'a142': 788, + 'a143': 788, + 'a144': 788, + 'a145': 788, + 'a146': 788, + 'a147': 788, + 'a148': 788, + 'a149': 788, + 'a150': 788, + 'a151': 788, + 'a152': 788, + 'a153': 788, + 'a154': 788, + 'a155': 788, + 'a156': 788, + 'a157': 788, + 'a158': 788, + 'a159': 788, + 'a160': 894, + 'a161': 838, + 'a163': 1016, + 'a164': 458, + 'a196': 748, + 'a165': 924, + 'a192': 748, + 'a166': 918, + 'a167': 927, + 'a168': 928, + 'a169': 928, + 'a170': 834, + 'a171': 873, + 'a172': 828, + 'a173': 924, + 'a162': 924, + 'a174': 917, + 'a175': 930, + 'a176': 931, + 'a177': 463, + 'a178': 883, + 'a179': 836, + 'a193': 836, + 'a180': 867, + 'a199': 867, + 'a181': 696, + 'a200': 696, + 'a182': 874, + 'a201': 874, + 'a183': 760, + 'a184': 946, + 'a197': 771, + 'a185': 865, + 'a194': 771, + 'a198': 888, + 'a186': 967, + 'a195': 888, + 'a187': 831, + 'a188': 873, + 'a189': 927, + 'a190': 970, + 'a191': 918 + } +}; + + +var EOF = {}; + +function isEOF(v) { + return (v === EOF); +} + +var MAX_LENGTH_TO_CACHE = 1000; + +var Parser = (function ParserClosure() { + function Parser(lexer, allowStreams, xref) { + this.lexer = lexer; + this.allowStreams = allowStreams; + this.xref = xref; + this.imageCache = {}; + this.refill(); + } + + Parser.prototype = { + refill: function Parser_refill() { + this.buf1 = this.lexer.getObj(); + this.buf2 = this.lexer.getObj(); + }, + shift: function Parser_shift() { + if (isCmd(this.buf2, 'ID')) { + this.buf1 = this.buf2; + this.buf2 = null; + } else { + this.buf1 = this.buf2; + this.buf2 = this.lexer.getObj(); + } + }, + getObj: function Parser_getObj(cipherTransform) { + var buf1 = this.buf1; + this.shift(); + + if (buf1 instanceof Cmd) { + switch (buf1.cmd) { + case 'BI': // inline image + return this.makeInlineImage(cipherTransform); + case '[': // array + var array = []; + while (!isCmd(this.buf1, ']') && !isEOF(this.buf1)) { + array.push(this.getObj(cipherTransform)); + } + if (isEOF(this.buf1)) { + error('End of file inside array'); + } + this.shift(); + return array; + case '<<': // dictionary or stream + var dict = new Dict(this.xref); + while (!isCmd(this.buf1, '>>') && !isEOF(this.buf1)) { + if (!isName(this.buf1)) { + info('Malformed dictionary: key must be a name object'); + this.shift(); + continue; + } + + var key = this.buf1.name; + this.shift(); + if (isEOF(this.buf1)) { + break; + } + dict.set(key, this.getObj(cipherTransform)); + } + if (isEOF(this.buf1)) { + error('End of file inside dictionary'); + } + + // Stream objects are not allowed inside content streams or + // object streams. + if (isCmd(this.buf2, 'stream')) { + return (this.allowStreams ? + this.makeStream(dict, cipherTransform) : dict); + } + this.shift(); + return dict; + default: // simple object + return buf1; + } + } + + if (isInt(buf1)) { // indirect reference or integer + var num = buf1; + if (isInt(this.buf1) && isCmd(this.buf2, 'R')) { + var ref = new Ref(num, this.buf1); + this.shift(); + this.shift(); + return ref; + } + return num; + } + + if (isString(buf1)) { // string + var str = buf1; + if (cipherTransform) { + str = cipherTransform.decryptString(str); + } + return str; + } + + // simple object + return buf1; + }, + /** + * Find the end of the stream by searching for the /EI\s/. + * @returns {number} The inline stream length. + */ + findDefaultInlineStreamEnd: + function Parser_findDefaultInlineStreamEnd(stream) { + var E = 0x45, I = 0x49, SPACE = 0x20, LF = 0xA, CR = 0xD; + var startPos = stream.pos, state = 0, ch, i, n, followingBytes; + while ((ch = stream.getByte()) !== -1) { + if (state === 0) { + state = (ch === E) ? 1 : 0; + } else if (state === 1) { + state = (ch === I) ? 2 : 0; + } else { + assert(state === 2); + if (ch === SPACE || ch === LF || ch === CR) { + // Let's check the next five bytes are ASCII... just be sure. + n = 5; + followingBytes = stream.peekBytes(n); + for (i = 0; i < n; i++) { + ch = followingBytes[i]; + if (ch !== LF && ch !== CR && (ch < SPACE || ch > 0x7F)) { + // Not a LF, CR, SPACE or any visible ASCII character, i.e. + // it's binary stuff. Resetting the state. + state = 0; + break; + } + } + if (state === 2) { + break; // Finished! + } + } else { + state = 0; + } + } + } + return ((stream.pos - 4) - startPos); + }, + /** + * Find the EOI (end-of-image) marker 0xFFD9 of the stream. + * @returns {number} The inline stream length. + */ + findDCTDecodeInlineStreamEnd: + function Parser_findDCTDecodeInlineStreamEnd(stream) { + var startPos = stream.pos, foundEOI = false, b, markerLength, length; + while ((b = stream.getByte()) !== -1) { + if (b !== 0xFF) { // Not a valid marker. + continue; + } + switch (stream.getByte()) { + case 0x00: // Byte stuffing. + // 0xFF00 appears to be a very common byte sequence in JPEG images. + break; + + case 0xFF: // Fill byte. + // Avoid skipping a valid marker, resetting the stream position. + stream.skip(-1); + break; + + case 0xD9: // EOI + foundEOI = true; + break; + + case 0xC0: // SOF0 + case 0xC1: // SOF1 + case 0xC2: // SOF2 + case 0xC3: // SOF3 + + case 0xC5: // SOF5 + case 0xC6: // SOF6 + case 0xC7: // SOF7 + + case 0xC9: // SOF9 + case 0xCA: // SOF10 + case 0xCB: // SOF11 + + case 0xCD: // SOF13 + case 0xCE: // SOF14 + case 0xCF: // SOF15 + + case 0xC4: // DHT + case 0xCC: // DAC + + case 0xDA: // SOS + case 0xDB: // DQT + case 0xDC: // DNL + case 0xDD: // DRI + case 0xDE: // DHP + case 0xDF: // EXP + + case 0xE0: // APP0 + case 0xE1: // APP1 + case 0xE2: // APP2 + case 0xE3: // APP3 + case 0xE4: // APP4 + case 0xE5: // APP5 + case 0xE6: // APP6 + case 0xE7: // APP7 + case 0xE8: // APP8 + case 0xE9: // APP9 + case 0xEA: // APP10 + case 0xEB: // APP11 + case 0xEC: // APP12 + case 0xED: // APP13 + case 0xEE: // APP14 + case 0xEF: // APP15 + + case 0xFE: // COM + // The marker should be followed by the length of the segment. + markerLength = stream.getUint16(); + if (markerLength > 2) { + // |markerLength| contains the byte length of the marker segment, + // including its own length (2 bytes) and excluding the marker. + stream.skip(markerLength - 2); // Jump to the next marker. + } else { + // The marker length is invalid, resetting the stream position. + stream.skip(-2); + } + break; + } + if (foundEOI) { + break; + } + } + length = stream.pos - startPos; + if (b === -1) { + warn('Inline DCTDecode image stream: ' + + 'EOI marker not found, searching for /EI/ instead.'); + stream.skip(-length); // Reset the stream position. + return this.findDefaultInlineStreamEnd(stream); + } + this.inlineStreamSkipEI(stream); + return length; + }, + /** + * Find the EOD (end-of-data) marker '~>' (i.e. TILDE + GT) of the stream. + * @returns {number} The inline stream length. + */ + findASCII85DecodeInlineStreamEnd: + function Parser_findASCII85DecodeInlineStreamEnd(stream) { + var TILDE = 0x7E, GT = 0x3E; + var startPos = stream.pos, ch, length; + while ((ch = stream.getByte()) !== -1) { + if (ch === TILDE && stream.peekByte() === GT) { + stream.skip(); + break; + } + } + length = stream.pos - startPos; + if (ch === -1) { + warn('Inline ASCII85Decode image stream: ' + + 'EOD marker not found, searching for /EI/ instead.'); + stream.skip(-length); // Reset the stream position. + return this.findDefaultInlineStreamEnd(stream); + } + this.inlineStreamSkipEI(stream); + return length; + }, + /** + * Find the EOD (end-of-data) marker '>' (i.e. GT) of the stream. + * @returns {number} The inline stream length. + */ + findASCIIHexDecodeInlineStreamEnd: + function Parser_findASCIIHexDecodeInlineStreamEnd(stream) { + var GT = 0x3E; + var startPos = stream.pos, ch, length; + while ((ch = stream.getByte()) !== -1) { + if (ch === GT) { + break; + } + } + length = stream.pos - startPos; + if (ch === -1) { + warn('Inline ASCIIHexDecode image stream: ' + + 'EOD marker not found, searching for /EI/ instead.'); + stream.skip(-length); // Reset the stream position. + return this.findDefaultInlineStreamEnd(stream); + } + this.inlineStreamSkipEI(stream); + return length; + }, + /** + * Skip over the /EI/ for streams where we search for an EOD marker. + */ + inlineStreamSkipEI: function Parser_inlineStreamSkipEI(stream) { + var E = 0x45, I = 0x49; + var state = 0, ch; + while ((ch = stream.getByte()) !== -1) { + if (state === 0) { + state = (ch === E) ? 1 : 0; + } else if (state === 1) { + state = (ch === I) ? 2 : 0; + } else if (state === 2) { + break; + } + } + }, + makeInlineImage: function Parser_makeInlineImage(cipherTransform) { + var lexer = this.lexer; + var stream = lexer.stream; + + // Parse dictionary. + var dict = new Dict(null); + while (!isCmd(this.buf1, 'ID') && !isEOF(this.buf1)) { + if (!isName(this.buf1)) { + error('Dictionary key must be a name object'); + } + var key = this.buf1.name; + this.shift(); + if (isEOF(this.buf1)) { + break; + } + dict.set(key, this.getObj(cipherTransform)); + } + + // Extract the name of the first (i.e. the current) image filter. + var filter = this.fetchIfRef(dict.get('Filter', 'F')), filterName; + if (isName(filter)) { + filterName = filter.name; + } else if (isArray(filter) && isName(filter[0])) { + filterName = filter[0].name; + } + + // Parse image stream. + var startPos = stream.pos, length, i, ii; + if (filterName === 'DCTDecode' || filterName === 'DCT') { + length = this.findDCTDecodeInlineStreamEnd(stream); + } else if (filterName === 'ASCII85Decide' || filterName === 'A85') { + length = this.findASCII85DecodeInlineStreamEnd(stream); + } else if (filterName === 'ASCIIHexDecode' || filterName === 'AHx') { + length = this.findASCIIHexDecodeInlineStreamEnd(stream); + } else { + length = this.findDefaultInlineStreamEnd(stream); + } + var imageStream = stream.makeSubStream(startPos, length, dict); + + // Cache all images below the MAX_LENGTH_TO_CACHE threshold by their + // adler32 checksum. + var adler32; + if (length < MAX_LENGTH_TO_CACHE) { + var imageBytes = imageStream.getBytes(); + imageStream.reset(); + + var a = 1; + var b = 0; + for (i = 0, ii = imageBytes.length; i < ii; ++i) { + // No modulo required in the loop if imageBytes.length < 5552. + a += imageBytes[i] & 0xff; + b += a; + } + adler32 = ((b % 65521) << 16) | (a % 65521); + + if (this.imageCache.adler32 === adler32) { + this.buf2 = Cmd.get('EI'); + this.shift(); + + this.imageCache[adler32].reset(); + return this.imageCache[adler32]; + } + } + + if (cipherTransform) { + imageStream = cipherTransform.createStream(imageStream, length); + } + + imageStream = this.filter(imageStream, dict, length); + imageStream.dict = dict; + if (adler32 !== undefined) { + imageStream.cacheKey = 'inline_' + length + '_' + adler32; + this.imageCache[adler32] = imageStream; + } + + this.buf2 = Cmd.get('EI'); + this.shift(); + + return imageStream; + }, + fetchIfRef: function Parser_fetchIfRef(obj) { + // not relying on the xref.fetchIfRef -- xref might not be set + return (isRef(obj) ? this.xref.fetch(obj) : obj); + }, + makeStream: function Parser_makeStream(dict, cipherTransform) { + var lexer = this.lexer; + var stream = lexer.stream; + + // get stream start position + lexer.skipToNextLine(); + var pos = stream.pos - 1; + + // get length + var length = this.fetchIfRef(dict.get('Length')); + if (!isInt(length)) { + info('Bad ' + length + ' attribute in stream'); + length = 0; + } + + // skip over the stream data + stream.pos = pos + length; + lexer.nextChar(); + + this.shift(); // '>>' + this.shift(); // 'stream' + if (!isCmd(this.buf1, 'endstream')) { + // bad stream length, scanning for endstream + stream.pos = pos; + var SCAN_BLOCK_SIZE = 2048; + var ENDSTREAM_SIGNATURE_LENGTH = 9; + var ENDSTREAM_SIGNATURE = [0x65, 0x6E, 0x64, 0x73, 0x74, 0x72, 0x65, + 0x61, 0x6D]; + var skipped = 0, found = false, i, j; + while (stream.pos < stream.end) { + var scanBytes = stream.peekBytes(SCAN_BLOCK_SIZE); + var scanLength = scanBytes.length - ENDSTREAM_SIGNATURE_LENGTH; + if (scanLength <= 0) { + break; + } + found = false; + for (i = 0, j = 0; i < scanLength; i++) { + var b = scanBytes[i]; + if (b !== ENDSTREAM_SIGNATURE[j]) { + i -= j; + j = 0; + } else { + j++; + if (j >= ENDSTREAM_SIGNATURE_LENGTH) { + i++; + found = true; + break; + } + } + } + if (found) { + skipped += i - ENDSTREAM_SIGNATURE_LENGTH; + stream.pos += i - ENDSTREAM_SIGNATURE_LENGTH; + break; + } + skipped += scanLength; + stream.pos += scanLength; + } + if (!found) { + error('Missing endstream'); + } + length = skipped; + + lexer.nextChar(); + this.shift(); + this.shift(); + } + this.shift(); // 'endstream' + + stream = stream.makeSubStream(pos, length, dict); + if (cipherTransform) { + stream = cipherTransform.createStream(stream, length); + } + stream = this.filter(stream, dict, length); + stream.dict = dict; + return stream; + }, + filter: function Parser_filter(stream, dict, length) { + var filter = this.fetchIfRef(dict.get('Filter', 'F')); + var params = this.fetchIfRef(dict.get('DecodeParms', 'DP')); + if (isName(filter)) { + return this.makeFilter(stream, filter.name, length, params); + } + + var maybeLength = length; + if (isArray(filter)) { + var filterArray = filter; + var paramsArray = params; + for (var i = 0, ii = filterArray.length; i < ii; ++i) { + filter = filterArray[i]; + if (!isName(filter)) { + error('Bad filter name: ' + filter); + } + + params = null; + if (isArray(paramsArray) && (i in paramsArray)) { + params = paramsArray[i]; + } + stream = this.makeFilter(stream, filter.name, maybeLength, params); + // after the first stream the length variable is invalid + maybeLength = null; + } + } + return stream; + }, + makeFilter: function Parser_makeFilter(stream, name, maybeLength, params) { + if (stream.dict.get('Length') === 0) { + return new NullStream(stream); + } + try { + if (params) { + params = this.fetchIfRef(params); + } + var xrefStreamStats = this.xref.stats.streamTypes; + if (name === 'FlateDecode' || name === 'Fl') { + xrefStreamStats[StreamType.FLATE] = true; + if (params) { + return new PredictorStream(new FlateStream(stream, maybeLength), + maybeLength, params); + } + return new FlateStream(stream, maybeLength); + } + if (name === 'LZWDecode' || name === 'LZW') { + xrefStreamStats[StreamType.LZW] = true; + var earlyChange = 1; + if (params) { + if (params.has('EarlyChange')) { + earlyChange = params.get('EarlyChange'); + } + return new PredictorStream( + new LZWStream(stream, maybeLength, earlyChange), + maybeLength, params); + } + return new LZWStream(stream, maybeLength, earlyChange); + } + if (name === 'DCTDecode' || name === 'DCT') { + xrefStreamStats[StreamType.DCT] = true; + return new JpegStream(stream, maybeLength, stream.dict, this.xref); + } + if (name === 'JPXDecode' || name === 'JPX') { + xrefStreamStats[StreamType.JPX] = true; + return new JpxStream(stream, maybeLength, stream.dict); + } + if (name === 'ASCII85Decode' || name === 'A85') { + xrefStreamStats[StreamType.A85] = true; + return new Ascii85Stream(stream, maybeLength); + } + if (name === 'ASCIIHexDecode' || name === 'AHx') { + xrefStreamStats[StreamType.AHX] = true; + return new AsciiHexStream(stream, maybeLength); + } + if (name === 'CCITTFaxDecode' || name === 'CCF') { + xrefStreamStats[StreamType.CCF] = true; + return new CCITTFaxStream(stream, maybeLength, params); + } + if (name === 'RunLengthDecode' || name === 'RL') { + xrefStreamStats[StreamType.RL] = true; + return new RunLengthStream(stream, maybeLength); + } + if (name === 'JBIG2Decode') { + xrefStreamStats[StreamType.JBIG] = true; + return new Jbig2Stream(stream, maybeLength, stream.dict); + } + warn('filter "' + name + '" not supported yet'); + return stream; + } catch (ex) { + if (ex instanceof MissingDataException) { + throw ex; + } + warn('Invalid stream: \"' + ex + '\"'); + return new NullStream(stream); + } + } + }; + + return Parser; +})(); + +var Lexer = (function LexerClosure() { + function Lexer(stream, knownCommands) { + this.stream = stream; + this.nextChar(); + + // While lexing, we build up many strings one char at a time. Using += for + // this can result in lots of garbage strings. It's better to build an + // array of single-char strings and then join() them together at the end. + // And reusing a single array (i.e. |this.strBuf|) over and over for this + // purpose uses less memory than using a new array for each string. + this.strBuf = []; + + // The PDFs might have "glued" commands with other commands, operands or + // literals, e.g. "q1". The knownCommands is a dictionary of the valid + // commands and their prefixes. The prefixes are built the following way: + // if there a command that is a prefix of the other valid command or + // literal (e.g. 'f' and 'false') the following prefixes must be included, + // 'fa', 'fal', 'fals'. The prefixes are not needed, if the command has no + // other commands or literals as a prefix. The knowCommands is optional. + this.knownCommands = knownCommands; + } + + Lexer.isSpace = function Lexer_isSpace(ch) { + // Space is one of the following characters: SPACE, TAB, CR or LF. + return (ch === 0x20 || ch === 0x09 || ch === 0x0D || ch === 0x0A); + }; + + // A '1' in this array means the character is white space. A '1' or + // '2' means the character ends a name or command. + var specialChars = [ + 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, // 0x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x + 1, 0, 0, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 0, 0, 2, // 2x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, // 3x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, // 5x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, // 7x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // ax + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // bx + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // cx + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // dx + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // ex + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // fx + ]; + + function toHexDigit(ch) { + if (ch >= 0x30 && ch <= 0x39) { // '0'-'9' + return ch & 0x0F; + } + if ((ch >= 0x41 && ch <= 0x46) || (ch >= 0x61 && ch <= 0x66)) { + // 'A'-'F', 'a'-'f' + return (ch & 0x0F) + 9; + } + return -1; + } + + Lexer.prototype = { + nextChar: function Lexer_nextChar() { + return (this.currentChar = this.stream.getByte()); + }, + peekChar: function Lexer_peekChar() { + return this.stream.peekByte(); + }, + getNumber: function Lexer_getNumber() { + var ch = this.currentChar; + var eNotation = false; + var divideBy = 0; // different from 0 if it's a floating point value + var sign = 1; + + if (ch === 0x2D) { // '-' + sign = -1; + ch = this.nextChar(); + } else if (ch === 0x2B) { // '+' + ch = this.nextChar(); + } + if (ch === 0x2E) { // '.' + divideBy = 10; + ch = this.nextChar(); + } + if (ch < 0x30 || ch > 0x39) { // '0' - '9' + error('Invalid number: ' + String.fromCharCode(ch)); + return 0; + } + + var baseValue = ch - 0x30; // '0' + var powerValue = 0; + var powerValueSign = 1; + + while ((ch = this.nextChar()) >= 0) { + if (0x30 <= ch && ch <= 0x39) { // '0' - '9' + var currentDigit = ch - 0x30; // '0' + if (eNotation) { // We are after an 'e' or 'E' + powerValue = powerValue * 10 + currentDigit; + } else { + if (divideBy !== 0) { // We are after a point + divideBy *= 10; + } + baseValue = baseValue * 10 + currentDigit; + } + } else if (ch === 0x2E) { // '.' + if (divideBy === 0) { + divideBy = 1; + } else { + // A number can have only one '.' + break; + } + } else if (ch === 0x2D) { // '-' + // ignore minus signs in the middle of numbers to match + // Adobe's behavior + warn('Badly formated number'); + } else if (ch === 0x45 || ch === 0x65) { // 'E', 'e' + // 'E' can be either a scientific notation or the beginning of a new + // operator + ch = this.peekChar(); + if (ch === 0x2B || ch === 0x2D) { // '+', '-' + powerValueSign = (ch === 0x2D) ? -1 : 1; + this.nextChar(); // Consume the sign character + } else if (ch < 0x30 || ch > 0x39) { // '0' - '9' + // The 'E' must be the beginning of a new operator + break; + } + eNotation = true; + } else { + // the last character doesn't belong to us + break; + } + } + + if (divideBy !== 0) { + baseValue /= divideBy; + } + if (eNotation) { + baseValue *= Math.pow(10, powerValueSign * powerValue); + } + return sign * baseValue; + }, + getString: function Lexer_getString() { + var numParen = 1; + var done = false; + var strBuf = this.strBuf; + strBuf.length = 0; + + var ch = this.nextChar(); + while (true) { + var charBuffered = false; + switch (ch | 0) { + case -1: + warn('Unterminated string'); + done = true; + break; + case 0x28: // '(' + ++numParen; + strBuf.push('('); + break; + case 0x29: // ')' + if (--numParen === 0) { + this.nextChar(); // consume strings ')' + done = true; + } else { + strBuf.push(')'); + } + break; + case 0x5C: // '\\' + ch = this.nextChar(); + switch (ch) { + case -1: + warn('Unterminated string'); + done = true; + break; + case 0x6E: // 'n' + strBuf.push('\n'); + break; + case 0x72: // 'r' + strBuf.push('\r'); + break; + case 0x74: // 't' + strBuf.push('\t'); + break; + case 0x62: // 'b' + strBuf.push('\b'); + break; + case 0x66: // 'f' + strBuf.push('\f'); + break; + case 0x5C: // '\' + case 0x28: // '(' + case 0x29: // ')' + strBuf.push(String.fromCharCode(ch)); + break; + case 0x30: case 0x31: case 0x32: case 0x33: // '0'-'3' + case 0x34: case 0x35: case 0x36: case 0x37: // '4'-'7' + var x = ch & 0x0F; + ch = this.nextChar(); + charBuffered = true; + if (ch >= 0x30 && ch <= 0x37) { // '0'-'7' + x = (x << 3) + (ch & 0x0F); + ch = this.nextChar(); + if (ch >= 0x30 && ch <= 0x37) { // '0'-'7' + charBuffered = false; + x = (x << 3) + (ch & 0x0F); + } + } + strBuf.push(String.fromCharCode(x)); + break; + case 0x0D: // CR + if (this.peekChar() === 0x0A) { // LF + this.nextChar(); + } + break; + case 0x0A: // LF + break; + default: + strBuf.push(String.fromCharCode(ch)); + break; + } + break; + default: + strBuf.push(String.fromCharCode(ch)); + break; + } + if (done) { + break; + } + if (!charBuffered) { + ch = this.nextChar(); + } + } + return strBuf.join(''); + }, + getName: function Lexer_getName() { + var ch; + var strBuf = this.strBuf; + strBuf.length = 0; + while ((ch = this.nextChar()) >= 0 && !specialChars[ch]) { + if (ch === 0x23) { // '#' + ch = this.nextChar(); + var x = toHexDigit(ch); + if (x !== -1) { + var x2 = toHexDigit(this.nextChar()); + if (x2 === -1) { + error('Illegal digit in hex char in name: ' + x2); + } + strBuf.push(String.fromCharCode((x << 4) | x2)); + } else { + strBuf.push('#', String.fromCharCode(ch)); + } + } else { + strBuf.push(String.fromCharCode(ch)); + } + } + if (strBuf.length > 128) { + error('Warning: name token is longer than allowed by the spec: ' + + strBuf.length); + } + return Name.get(strBuf.join('')); + }, + getHexString: function Lexer_getHexString() { + var strBuf = this.strBuf; + strBuf.length = 0; + var ch = this.currentChar; + var isFirstHex = true; + var firstDigit; + var secondDigit; + while (true) { + if (ch < 0) { + warn('Unterminated hex string'); + break; + } else if (ch === 0x3E) { // '>' + this.nextChar(); + break; + } else if (specialChars[ch] === 1) { + ch = this.nextChar(); + continue; + } else { + if (isFirstHex) { + firstDigit = toHexDigit(ch); + if (firstDigit === -1) { + warn('Ignoring invalid character "' + ch + '" in hex string'); + ch = this.nextChar(); + continue; + } + } else { + secondDigit = toHexDigit(ch); + if (secondDigit === -1) { + warn('Ignoring invalid character "' + ch + '" in hex string'); + ch = this.nextChar(); + continue; + } + strBuf.push(String.fromCharCode((firstDigit << 4) | secondDigit)); + } + isFirstHex = !isFirstHex; + ch = this.nextChar(); + } + } + return strBuf.join(''); + }, + getObj: function Lexer_getObj() { + // skip whitespace and comments + var comment = false; + var ch = this.currentChar; + while (true) { + if (ch < 0) { + return EOF; + } + if (comment) { + if (ch === 0x0A || ch === 0x0D) { // LF, CR + comment = false; + } + } else if (ch === 0x25) { // '%' + comment = true; + } else if (specialChars[ch] !== 1) { + break; + } + ch = this.nextChar(); + } + + // start reading token + switch (ch | 0) { + case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: // '0'-'4' + case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: // '5'-'9' + case 0x2B: case 0x2D: case 0x2E: // '+', '-', '.' + return this.getNumber(); + case 0x28: // '(' + return this.getString(); + case 0x2F: // '/' + return this.getName(); + // array punctuation + case 0x5B: // '[' + this.nextChar(); + return Cmd.get('['); + case 0x5D: // ']' + this.nextChar(); + return Cmd.get(']'); + // hex string or dict punctuation + case 0x3C: // '<' + ch = this.nextChar(); + if (ch === 0x3C) { + // dict punctuation + this.nextChar(); + return Cmd.get('<<'); + } + return this.getHexString(); + // dict punctuation + case 0x3E: // '>' + ch = this.nextChar(); + if (ch === 0x3E) { + this.nextChar(); + return Cmd.get('>>'); + } + return Cmd.get('>'); + case 0x7B: // '{' + this.nextChar(); + return Cmd.get('{'); + case 0x7D: // '}' + this.nextChar(); + return Cmd.get('}'); + case 0x29: // ')' + error('Illegal character: ' + ch); + break; + } + + // command + var str = String.fromCharCode(ch); + var knownCommands = this.knownCommands; + var knownCommandFound = knownCommands && knownCommands[str] !== undefined; + while ((ch = this.nextChar()) >= 0 && !specialChars[ch]) { + // stop if known command is found and next character does not make + // the str a command + var possibleCommand = str + String.fromCharCode(ch); + if (knownCommandFound && knownCommands[possibleCommand] === undefined) { + break; + } + if (str.length === 128) { + error('Command token too long: ' + str.length); + } + str = possibleCommand; + knownCommandFound = knownCommands && knownCommands[str] !== undefined; + } + if (str === 'true') { + return true; + } + if (str === 'false') { + return false; + } + if (str === 'null') { + return null; + } + return Cmd.get(str); + }, + skipToNextLine: function Lexer_skipToNextLine() { + var ch = this.currentChar; + while (ch >= 0) { + if (ch === 0x0D) { // CR + ch = this.nextChar(); + if (ch === 0x0A) { // LF + this.nextChar(); + } + break; + } else if (ch === 0x0A) { // LF + this.nextChar(); + break; + } + ch = this.nextChar(); + } + } + }; + + return Lexer; +})(); + +var Linearization = { + create: function LinearizationCreate(stream) { + function getInt(name, allowZeroValue) { + var obj = linDict.get(name); + if (isInt(obj) && (allowZeroValue ? obj >= 0 : obj > 0)) { + return obj; + } + throw new Error('The "' + name + '" parameter in the linearization ' + + 'dictionary is invalid.'); + } + function getHints() { + var hints = linDict.get('H'), hintsLength, item; + if (isArray(hints) && + ((hintsLength = hints.length) === 2 || hintsLength === 4)) { + for (var index = 0; index < hintsLength; index++) { + if (!(isInt(item = hints[index]) && item > 0)) { + throw new Error('Hint (' + index + + ') in the linearization dictionary is invalid.'); + } + } + return hints; + } + throw new Error('Hint array in the linearization dictionary is invalid.'); + } + var parser = new Parser(new Lexer(stream), false, null); + var obj1 = parser.getObj(); + var obj2 = parser.getObj(); + var obj3 = parser.getObj(); + var linDict = parser.getObj(); + var obj, length; + if (!(isInt(obj1) && isInt(obj2) && isCmd(obj3, 'obj') && isDict(linDict) && + isNum(obj = linDict.get('Linearized')) && obj > 0)) { + return null; // No valid linearization dictionary found. + } else if ((length = getInt('L')) !== stream.length) { + throw new Error('The "L" parameter in the linearization dictionary ' + + 'does not equal the stream length.'); + } + return { + length: length, + hints: getHints(), + objectNumberFirst: getInt('O'), + endFirst: getInt('E'), + numPages: getInt('N'), + mainXRefEntriesOffset: getInt('T'), + pageFirst: (linDict.has('P') ? getInt('P', true) : 0) + }; + } +}; + + +var PostScriptParser = (function PostScriptParserClosure() { + function PostScriptParser(lexer) { + this.lexer = lexer; + this.operators = []; + this.token = null; + this.prev = null; + } + PostScriptParser.prototype = { + nextToken: function PostScriptParser_nextToken() { + this.prev = this.token; + this.token = this.lexer.getToken(); + }, + accept: function PostScriptParser_accept(type) { + if (this.token.type === type) { + this.nextToken(); + return true; + } + return false; + }, + expect: function PostScriptParser_expect(type) { + if (this.accept(type)) { + return true; + } + error('Unexpected symbol: found ' + this.token.type + ' expected ' + + type + '.'); + }, + parse: function PostScriptParser_parse() { + this.nextToken(); + this.expect(PostScriptTokenTypes.LBRACE); + this.parseBlock(); + this.expect(PostScriptTokenTypes.RBRACE); + return this.operators; + }, + parseBlock: function PostScriptParser_parseBlock() { + while (true) { + if (this.accept(PostScriptTokenTypes.NUMBER)) { + this.operators.push(this.prev.value); + } else if (this.accept(PostScriptTokenTypes.OPERATOR)) { + this.operators.push(this.prev.value); + } else if (this.accept(PostScriptTokenTypes.LBRACE)) { + this.parseCondition(); + } else { + return; + } + } + }, + parseCondition: function PostScriptParser_parseCondition() { + // Add two place holders that will be updated later + var conditionLocation = this.operators.length; + this.operators.push(null, null); + + this.parseBlock(); + this.expect(PostScriptTokenTypes.RBRACE); + if (this.accept(PostScriptTokenTypes.IF)) { + // The true block is right after the 'if' so it just falls through on + // true else it jumps and skips the true block. + this.operators[conditionLocation] = this.operators.length; + this.operators[conditionLocation + 1] = 'jz'; + } else if (this.accept(PostScriptTokenTypes.LBRACE)) { + var jumpLocation = this.operators.length; + this.operators.push(null, null); + var endOfTrue = this.operators.length; + this.parseBlock(); + this.expect(PostScriptTokenTypes.RBRACE); + this.expect(PostScriptTokenTypes.IFELSE); + // The jump is added at the end of the true block to skip the false + // block. + this.operators[jumpLocation] = this.operators.length; + this.operators[jumpLocation + 1] = 'j'; + + this.operators[conditionLocation] = endOfTrue; + this.operators[conditionLocation + 1] = 'jz'; + } else { + error('PS Function: error parsing conditional.'); + } + } + }; + return PostScriptParser; +})(); + +var PostScriptTokenTypes = { + LBRACE: 0, + RBRACE: 1, + NUMBER: 2, + OPERATOR: 3, + IF: 4, + IFELSE: 5 +}; + +var PostScriptToken = (function PostScriptTokenClosure() { + function PostScriptToken(type, value) { + this.type = type; + this.value = value; + } + + var opCache = {}; + + PostScriptToken.getOperator = function PostScriptToken_getOperator(op) { + var opValue = opCache[op]; + if (opValue) { + return opValue; + } + return opCache[op] = new PostScriptToken(PostScriptTokenTypes.OPERATOR, op); + }; + + PostScriptToken.LBRACE = new PostScriptToken(PostScriptTokenTypes.LBRACE, + '{'); + PostScriptToken.RBRACE = new PostScriptToken(PostScriptTokenTypes.RBRACE, + '}'); + PostScriptToken.IF = new PostScriptToken(PostScriptTokenTypes.IF, 'IF'); + PostScriptToken.IFELSE = new PostScriptToken(PostScriptTokenTypes.IFELSE, + 'IFELSE'); + return PostScriptToken; +})(); + +var PostScriptLexer = (function PostScriptLexerClosure() { + function PostScriptLexer(stream) { + this.stream = stream; + this.nextChar(); + + this.strBuf = []; + } + PostScriptLexer.prototype = { + nextChar: function PostScriptLexer_nextChar() { + return (this.currentChar = this.stream.getByte()); + }, + getToken: function PostScriptLexer_getToken() { + var comment = false; + var ch = this.currentChar; + + // skip comments + while (true) { + if (ch < 0) { + return EOF; + } + + if (comment) { + if (ch === 0x0A || ch === 0x0D) { + comment = false; + } + } else if (ch === 0x25) { // '%' + comment = true; + } else if (!Lexer.isSpace(ch)) { + break; + } + ch = this.nextChar(); + } + switch (ch | 0) { + case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: // '0'-'4' + case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: // '5'-'9' + case 0x2B: case 0x2D: case 0x2E: // '+', '-', '.' + return new PostScriptToken(PostScriptTokenTypes.NUMBER, + this.getNumber()); + case 0x7B: // '{' + this.nextChar(); + return PostScriptToken.LBRACE; + case 0x7D: // '}' + this.nextChar(); + return PostScriptToken.RBRACE; + } + // operator + var strBuf = this.strBuf; + strBuf.length = 0; + strBuf[0] = String.fromCharCode(ch); + + while ((ch = this.nextChar()) >= 0 && // and 'A'-'Z', 'a'-'z' + ((ch >= 0x41 && ch <= 0x5A) || (ch >= 0x61 && ch <= 0x7A))) { + strBuf.push(String.fromCharCode(ch)); + } + var str = strBuf.join(''); + switch (str.toLowerCase()) { + case 'if': + return PostScriptToken.IF; + case 'ifelse': + return PostScriptToken.IFELSE; + default: + return PostScriptToken.getOperator(str); + } + }, + getNumber: function PostScriptLexer_getNumber() { + var ch = this.currentChar; + var strBuf = this.strBuf; + strBuf.length = 0; + strBuf[0] = String.fromCharCode(ch); + + while ((ch = this.nextChar()) >= 0) { + if ((ch >= 0x30 && ch <= 0x39) || // '0'-'9' + ch === 0x2D || ch === 0x2E) { // '-', '.' + strBuf.push(String.fromCharCode(ch)); + } else { + break; + } + } + var value = parseFloat(strBuf.join('')); + if (isNaN(value)) { + error('Invalid floating point number: ' + value); + } + return value; + } + }; + return PostScriptLexer; +})(); + + +var Stream = (function StreamClosure() { + function Stream(arrayBuffer, start, length, dict) { + this.bytes = (arrayBuffer instanceof Uint8Array ? + arrayBuffer : new Uint8Array(arrayBuffer)); + this.start = start || 0; + this.pos = this.start; + this.end = (start + length) || this.bytes.length; + this.dict = dict; + } + + // required methods for a stream. if a particular stream does not + // implement these, an error should be thrown + Stream.prototype = { + get length() { + return this.end - this.start; + }, + get isEmpty() { + return this.length === 0; + }, + getByte: function Stream_getByte() { + if (this.pos >= this.end) { + return -1; + } + return this.bytes[this.pos++]; + }, + getUint16: function Stream_getUint16() { + var b0 = this.getByte(); + var b1 = this.getByte(); + if (b0 === -1 || b1 === -1) { + return -1; + } + return (b0 << 8) + b1; + }, + getInt32: function Stream_getInt32() { + var b0 = this.getByte(); + var b1 = this.getByte(); + var b2 = this.getByte(); + var b3 = this.getByte(); + return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3; + }, + // returns subarray of original buffer + // should only be read + getBytes: function Stream_getBytes(length) { + var bytes = this.bytes; + var pos = this.pos; + var strEnd = this.end; + + if (!length) { + return bytes.subarray(pos, strEnd); + } + var end = pos + length; + if (end > strEnd) { + end = strEnd; + } + this.pos = end; + return bytes.subarray(pos, end); + }, + peekByte: function Stream_peekByte() { + var peekedByte = this.getByte(); + this.pos--; + return peekedByte; + }, + peekBytes: function Stream_peekBytes(length) { + var bytes = this.getBytes(length); + this.pos -= bytes.length; + return bytes; + }, + skip: function Stream_skip(n) { + if (!n) { + n = 1; + } + this.pos += n; + }, + reset: function Stream_reset() { + this.pos = this.start; + }, + moveStart: function Stream_moveStart() { + this.start = this.pos; + }, + makeSubStream: function Stream_makeSubStream(start, length, dict) { + return new Stream(this.bytes.buffer, start, length, dict); + }, + isStream: true + }; + + return Stream; +})(); + +var StringStream = (function StringStreamClosure() { + function StringStream(str) { + var length = str.length; + var bytes = new Uint8Array(length); + for (var n = 0; n < length; ++n) { + bytes[n] = str.charCodeAt(n); + } + Stream.call(this, bytes); + } + + StringStream.prototype = Stream.prototype; + + return StringStream; +})(); + +// super class for the decoding streams +var DecodeStream = (function DecodeStreamClosure() { + // Lots of DecodeStreams are created whose buffers are never used. For these + // we share a single empty buffer. This is (a) space-efficient and (b) avoids + // having special cases that would be required if we used |null| for an empty + // buffer. + var emptyBuffer = new Uint8Array(0); + + function DecodeStream(maybeMinBufferLength) { + this.pos = 0; + this.bufferLength = 0; + this.eof = false; + this.buffer = emptyBuffer; + this.minBufferLength = 512; + if (maybeMinBufferLength) { + // Compute the first power of two that is as big as maybeMinBufferLength. + while (this.minBufferLength < maybeMinBufferLength) { + this.minBufferLength *= 2; + } + } + } + + DecodeStream.prototype = { + get isEmpty() { + while (!this.eof && this.bufferLength === 0) { + this.readBlock(); + } + return this.bufferLength === 0; + }, + ensureBuffer: function DecodeStream_ensureBuffer(requested) { + var buffer = this.buffer; + if (requested <= buffer.byteLength) { + return buffer; + } + var size = this.minBufferLength; + while (size < requested) { + size *= 2; + } + var buffer2 = new Uint8Array(size); + buffer2.set(buffer); + return (this.buffer = buffer2); + }, + getByte: function DecodeStream_getByte() { + var pos = this.pos; + while (this.bufferLength <= pos) { + if (this.eof) { + return -1; + } + this.readBlock(); + } + return this.buffer[this.pos++]; + }, + getUint16: function DecodeStream_getUint16() { + var b0 = this.getByte(); + var b1 = this.getByte(); + if (b0 === -1 || b1 === -1) { + return -1; + } + return (b0 << 8) + b1; + }, + getInt32: function DecodeStream_getInt32() { + var b0 = this.getByte(); + var b1 = this.getByte(); + var b2 = this.getByte(); + var b3 = this.getByte(); + return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3; + }, + getBytes: function DecodeStream_getBytes(length) { + var end, pos = this.pos; + + if (length) { + this.ensureBuffer(pos + length); + end = pos + length; + + while (!this.eof && this.bufferLength < end) { + this.readBlock(); + } + var bufEnd = this.bufferLength; + if (end > bufEnd) { + end = bufEnd; + } + } else { + while (!this.eof) { + this.readBlock(); + } + end = this.bufferLength; + } + + this.pos = end; + return this.buffer.subarray(pos, end); + }, + peekByte: function DecodeStream_peekByte() { + var peekedByte = this.getByte(); + this.pos--; + return peekedByte; + }, + peekBytes: function DecodeStream_peekBytes(length) { + var bytes = this.getBytes(length); + this.pos -= bytes.length; + return bytes; + }, + makeSubStream: function DecodeStream_makeSubStream(start, length, dict) { + var end = start + length; + while (this.bufferLength <= end && !this.eof) { + this.readBlock(); + } + return new Stream(this.buffer, start, length, dict); + }, + skip: function DecodeStream_skip(n) { + if (!n) { + n = 1; + } + this.pos += n; + }, + reset: function DecodeStream_reset() { + this.pos = 0; + }, + getBaseStreams: function DecodeStream_getBaseStreams() { + if (this.str && this.str.getBaseStreams) { + return this.str.getBaseStreams(); + } + return []; + } + }; + + return DecodeStream; +})(); + +var StreamsSequenceStream = (function StreamsSequenceStreamClosure() { + function StreamsSequenceStream(streams) { + this.streams = streams; + DecodeStream.call(this, /* maybeLength = */ null); + } + + StreamsSequenceStream.prototype = Object.create(DecodeStream.prototype); + + StreamsSequenceStream.prototype.readBlock = + function streamSequenceStreamReadBlock() { + + var streams = this.streams; + if (streams.length === 0) { + this.eof = true; + return; + } + var stream = streams.shift(); + var chunk = stream.getBytes(); + var bufferLength = this.bufferLength; + var newLength = bufferLength + chunk.length; + var buffer = this.ensureBuffer(newLength); + buffer.set(chunk, bufferLength); + this.bufferLength = newLength; + }; + + StreamsSequenceStream.prototype.getBaseStreams = + function StreamsSequenceStream_getBaseStreams() { + + var baseStreams = []; + for (var i = 0, ii = this.streams.length; i < ii; i++) { + var stream = this.streams[i]; + if (stream.getBaseStreams) { + Util.appendToArray(baseStreams, stream.getBaseStreams()); + } + } + return baseStreams; + }; + + return StreamsSequenceStream; +})(); + +var FlateStream = (function FlateStreamClosure() { + var codeLenCodeMap = new Int32Array([ + 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 + ]); + + var lengthDecode = new Int32Array([ + 0x00003, 0x00004, 0x00005, 0x00006, 0x00007, 0x00008, 0x00009, 0x0000a, + 0x1000b, 0x1000d, 0x1000f, 0x10011, 0x20013, 0x20017, 0x2001b, 0x2001f, + 0x30023, 0x3002b, 0x30033, 0x3003b, 0x40043, 0x40053, 0x40063, 0x40073, + 0x50083, 0x500a3, 0x500c3, 0x500e3, 0x00102, 0x00102, 0x00102 + ]); + + var distDecode = new Int32Array([ + 0x00001, 0x00002, 0x00003, 0x00004, 0x10005, 0x10007, 0x20009, 0x2000d, + 0x30011, 0x30019, 0x40021, 0x40031, 0x50041, 0x50061, 0x60081, 0x600c1, + 0x70101, 0x70181, 0x80201, 0x80301, 0x90401, 0x90601, 0xa0801, 0xa0c01, + 0xb1001, 0xb1801, 0xc2001, 0xc3001, 0xd4001, 0xd6001 + ]); + + var fixedLitCodeTab = [new Int32Array([ + 0x70100, 0x80050, 0x80010, 0x80118, 0x70110, 0x80070, 0x80030, 0x900c0, + 0x70108, 0x80060, 0x80020, 0x900a0, 0x80000, 0x80080, 0x80040, 0x900e0, + 0x70104, 0x80058, 0x80018, 0x90090, 0x70114, 0x80078, 0x80038, 0x900d0, + 0x7010c, 0x80068, 0x80028, 0x900b0, 0x80008, 0x80088, 0x80048, 0x900f0, + 0x70102, 0x80054, 0x80014, 0x8011c, 0x70112, 0x80074, 0x80034, 0x900c8, + 0x7010a, 0x80064, 0x80024, 0x900a8, 0x80004, 0x80084, 0x80044, 0x900e8, + 0x70106, 0x8005c, 0x8001c, 0x90098, 0x70116, 0x8007c, 0x8003c, 0x900d8, + 0x7010e, 0x8006c, 0x8002c, 0x900b8, 0x8000c, 0x8008c, 0x8004c, 0x900f8, + 0x70101, 0x80052, 0x80012, 0x8011a, 0x70111, 0x80072, 0x80032, 0x900c4, + 0x70109, 0x80062, 0x80022, 0x900a4, 0x80002, 0x80082, 0x80042, 0x900e4, + 0x70105, 0x8005a, 0x8001a, 0x90094, 0x70115, 0x8007a, 0x8003a, 0x900d4, + 0x7010d, 0x8006a, 0x8002a, 0x900b4, 0x8000a, 0x8008a, 0x8004a, 0x900f4, + 0x70103, 0x80056, 0x80016, 0x8011e, 0x70113, 0x80076, 0x80036, 0x900cc, + 0x7010b, 0x80066, 0x80026, 0x900ac, 0x80006, 0x80086, 0x80046, 0x900ec, + 0x70107, 0x8005e, 0x8001e, 0x9009c, 0x70117, 0x8007e, 0x8003e, 0x900dc, + 0x7010f, 0x8006e, 0x8002e, 0x900bc, 0x8000e, 0x8008e, 0x8004e, 0x900fc, + 0x70100, 0x80051, 0x80011, 0x80119, 0x70110, 0x80071, 0x80031, 0x900c2, + 0x70108, 0x80061, 0x80021, 0x900a2, 0x80001, 0x80081, 0x80041, 0x900e2, + 0x70104, 0x80059, 0x80019, 0x90092, 0x70114, 0x80079, 0x80039, 0x900d2, + 0x7010c, 0x80069, 0x80029, 0x900b2, 0x80009, 0x80089, 0x80049, 0x900f2, + 0x70102, 0x80055, 0x80015, 0x8011d, 0x70112, 0x80075, 0x80035, 0x900ca, + 0x7010a, 0x80065, 0x80025, 0x900aa, 0x80005, 0x80085, 0x80045, 0x900ea, + 0x70106, 0x8005d, 0x8001d, 0x9009a, 0x70116, 0x8007d, 0x8003d, 0x900da, + 0x7010e, 0x8006d, 0x8002d, 0x900ba, 0x8000d, 0x8008d, 0x8004d, 0x900fa, + 0x70101, 0x80053, 0x80013, 0x8011b, 0x70111, 0x80073, 0x80033, 0x900c6, + 0x70109, 0x80063, 0x80023, 0x900a6, 0x80003, 0x80083, 0x80043, 0x900e6, + 0x70105, 0x8005b, 0x8001b, 0x90096, 0x70115, 0x8007b, 0x8003b, 0x900d6, + 0x7010d, 0x8006b, 0x8002b, 0x900b6, 0x8000b, 0x8008b, 0x8004b, 0x900f6, + 0x70103, 0x80057, 0x80017, 0x8011f, 0x70113, 0x80077, 0x80037, 0x900ce, + 0x7010b, 0x80067, 0x80027, 0x900ae, 0x80007, 0x80087, 0x80047, 0x900ee, + 0x70107, 0x8005f, 0x8001f, 0x9009e, 0x70117, 0x8007f, 0x8003f, 0x900de, + 0x7010f, 0x8006f, 0x8002f, 0x900be, 0x8000f, 0x8008f, 0x8004f, 0x900fe, + 0x70100, 0x80050, 0x80010, 0x80118, 0x70110, 0x80070, 0x80030, 0x900c1, + 0x70108, 0x80060, 0x80020, 0x900a1, 0x80000, 0x80080, 0x80040, 0x900e1, + 0x70104, 0x80058, 0x80018, 0x90091, 0x70114, 0x80078, 0x80038, 0x900d1, + 0x7010c, 0x80068, 0x80028, 0x900b1, 0x80008, 0x80088, 0x80048, 0x900f1, + 0x70102, 0x80054, 0x80014, 0x8011c, 0x70112, 0x80074, 0x80034, 0x900c9, + 0x7010a, 0x80064, 0x80024, 0x900a9, 0x80004, 0x80084, 0x80044, 0x900e9, + 0x70106, 0x8005c, 0x8001c, 0x90099, 0x70116, 0x8007c, 0x8003c, 0x900d9, + 0x7010e, 0x8006c, 0x8002c, 0x900b9, 0x8000c, 0x8008c, 0x8004c, 0x900f9, + 0x70101, 0x80052, 0x80012, 0x8011a, 0x70111, 0x80072, 0x80032, 0x900c5, + 0x70109, 0x80062, 0x80022, 0x900a5, 0x80002, 0x80082, 0x80042, 0x900e5, + 0x70105, 0x8005a, 0x8001a, 0x90095, 0x70115, 0x8007a, 0x8003a, 0x900d5, + 0x7010d, 0x8006a, 0x8002a, 0x900b5, 0x8000a, 0x8008a, 0x8004a, 0x900f5, + 0x70103, 0x80056, 0x80016, 0x8011e, 0x70113, 0x80076, 0x80036, 0x900cd, + 0x7010b, 0x80066, 0x80026, 0x900ad, 0x80006, 0x80086, 0x80046, 0x900ed, + 0x70107, 0x8005e, 0x8001e, 0x9009d, 0x70117, 0x8007e, 0x8003e, 0x900dd, + 0x7010f, 0x8006e, 0x8002e, 0x900bd, 0x8000e, 0x8008e, 0x8004e, 0x900fd, + 0x70100, 0x80051, 0x80011, 0x80119, 0x70110, 0x80071, 0x80031, 0x900c3, + 0x70108, 0x80061, 0x80021, 0x900a3, 0x80001, 0x80081, 0x80041, 0x900e3, + 0x70104, 0x80059, 0x80019, 0x90093, 0x70114, 0x80079, 0x80039, 0x900d3, + 0x7010c, 0x80069, 0x80029, 0x900b3, 0x80009, 0x80089, 0x80049, 0x900f3, + 0x70102, 0x80055, 0x80015, 0x8011d, 0x70112, 0x80075, 0x80035, 0x900cb, + 0x7010a, 0x80065, 0x80025, 0x900ab, 0x80005, 0x80085, 0x80045, 0x900eb, + 0x70106, 0x8005d, 0x8001d, 0x9009b, 0x70116, 0x8007d, 0x8003d, 0x900db, + 0x7010e, 0x8006d, 0x8002d, 0x900bb, 0x8000d, 0x8008d, 0x8004d, 0x900fb, + 0x70101, 0x80053, 0x80013, 0x8011b, 0x70111, 0x80073, 0x80033, 0x900c7, + 0x70109, 0x80063, 0x80023, 0x900a7, 0x80003, 0x80083, 0x80043, 0x900e7, + 0x70105, 0x8005b, 0x8001b, 0x90097, 0x70115, 0x8007b, 0x8003b, 0x900d7, + 0x7010d, 0x8006b, 0x8002b, 0x900b7, 0x8000b, 0x8008b, 0x8004b, 0x900f7, + 0x70103, 0x80057, 0x80017, 0x8011f, 0x70113, 0x80077, 0x80037, 0x900cf, + 0x7010b, 0x80067, 0x80027, 0x900af, 0x80007, 0x80087, 0x80047, 0x900ef, + 0x70107, 0x8005f, 0x8001f, 0x9009f, 0x70117, 0x8007f, 0x8003f, 0x900df, + 0x7010f, 0x8006f, 0x8002f, 0x900bf, 0x8000f, 0x8008f, 0x8004f, 0x900ff + ]), 9]; + + var fixedDistCodeTab = [new Int32Array([ + 0x50000, 0x50010, 0x50008, 0x50018, 0x50004, 0x50014, 0x5000c, 0x5001c, + 0x50002, 0x50012, 0x5000a, 0x5001a, 0x50006, 0x50016, 0x5000e, 0x00000, + 0x50001, 0x50011, 0x50009, 0x50019, 0x50005, 0x50015, 0x5000d, 0x5001d, + 0x50003, 0x50013, 0x5000b, 0x5001b, 0x50007, 0x50017, 0x5000f, 0x00000 + ]), 5]; + + function FlateStream(str, maybeLength) { + this.str = str; + this.dict = str.dict; + + var cmf = str.getByte(); + var flg = str.getByte(); + if (cmf === -1 || flg === -1) { + error('Invalid header in flate stream: ' + cmf + ', ' + flg); + } + if ((cmf & 0x0f) !== 0x08) { + error('Unknown compression method in flate stream: ' + cmf + ', ' + flg); + } + if ((((cmf << 8) + flg) % 31) !== 0) { + error('Bad FCHECK in flate stream: ' + cmf + ', ' + flg); + } + if (flg & 0x20) { + error('FDICT bit set in flate stream: ' + cmf + ', ' + flg); + } + + this.codeSize = 0; + this.codeBuf = 0; + + DecodeStream.call(this, maybeLength); + } + + FlateStream.prototype = Object.create(DecodeStream.prototype); + + FlateStream.prototype.getBits = function FlateStream_getBits(bits) { + var str = this.str; + var codeSize = this.codeSize; + var codeBuf = this.codeBuf; + + var b; + while (codeSize < bits) { + if ((b = str.getByte()) === -1) { + error('Bad encoding in flate stream'); + } + codeBuf |= b << codeSize; + codeSize += 8; + } + b = codeBuf & ((1 << bits) - 1); + this.codeBuf = codeBuf >> bits; + this.codeSize = codeSize -= bits; + + return b; + }; + + FlateStream.prototype.getCode = function FlateStream_getCode(table) { + var str = this.str; + var codes = table[0]; + var maxLen = table[1]; + var codeSize = this.codeSize; + var codeBuf = this.codeBuf; + + var b; + while (codeSize < maxLen) { + if ((b = str.getByte()) === -1) { + // premature end of stream. code might however still be valid. + // codeSize < codeLen check below guards against incomplete codeVal. + break; + } + codeBuf |= (b << codeSize); + codeSize += 8; + } + var code = codes[codeBuf & ((1 << maxLen) - 1)]; + var codeLen = code >> 16; + var codeVal = code & 0xffff; + if (codeLen < 1 || codeSize < codeLen) { + error('Bad encoding in flate stream'); + } + this.codeBuf = (codeBuf >> codeLen); + this.codeSize = (codeSize - codeLen); + return codeVal; + }; + + FlateStream.prototype.generateHuffmanTable = + function flateStreamGenerateHuffmanTable(lengths) { + var n = lengths.length; + + // find max code length + var maxLen = 0; + var i; + for (i = 0; i < n; ++i) { + if (lengths[i] > maxLen) { + maxLen = lengths[i]; + } + } + + // build the table + var size = 1 << maxLen; + var codes = new Int32Array(size); + for (var len = 1, code = 0, skip = 2; + len <= maxLen; + ++len, code <<= 1, skip <<= 1) { + for (var val = 0; val < n; ++val) { + if (lengths[val] === len) { + // bit-reverse the code + var code2 = 0; + var t = code; + for (i = 0; i < len; ++i) { + code2 = (code2 << 1) | (t & 1); + t >>= 1; + } + + // fill the table entries + for (i = code2; i < size; i += skip) { + codes[i] = (len << 16) | val; + } + ++code; + } + } + } + + return [codes, maxLen]; + }; + + FlateStream.prototype.readBlock = function FlateStream_readBlock() { + var buffer, len; + var str = this.str; + // read block header + var hdr = this.getBits(3); + if (hdr & 1) { + this.eof = true; + } + hdr >>= 1; + + if (hdr === 0) { // uncompressed block + var b; + + if ((b = str.getByte()) === -1) { + error('Bad block header in flate stream'); + } + var blockLen = b; + if ((b = str.getByte()) === -1) { + error('Bad block header in flate stream'); + } + blockLen |= (b << 8); + if ((b = str.getByte()) === -1) { + error('Bad block header in flate stream'); + } + var check = b; + if ((b = str.getByte()) === -1) { + error('Bad block header in flate stream'); + } + check |= (b << 8); + if (check !== (~blockLen & 0xffff) && + (blockLen !== 0 || check !== 0)) { + // Ignoring error for bad "empty" block (see issue 1277) + error('Bad uncompressed block length in flate stream'); + } + + this.codeBuf = 0; + this.codeSize = 0; + + var bufferLength = this.bufferLength; + buffer = this.ensureBuffer(bufferLength + blockLen); + var end = bufferLength + blockLen; + this.bufferLength = end; + if (blockLen === 0) { + if (str.peekByte() === -1) { + this.eof = true; + } + } else { + for (var n = bufferLength; n < end; ++n) { + if ((b = str.getByte()) === -1) { + this.eof = true; + break; + } + buffer[n] = b; + } + } + return; + } + + var litCodeTable; + var distCodeTable; + if (hdr === 1) { // compressed block, fixed codes + litCodeTable = fixedLitCodeTab; + distCodeTable = fixedDistCodeTab; + } else if (hdr === 2) { // compressed block, dynamic codes + var numLitCodes = this.getBits(5) + 257; + var numDistCodes = this.getBits(5) + 1; + var numCodeLenCodes = this.getBits(4) + 4; + + // build the code lengths code table + var codeLenCodeLengths = new Uint8Array(codeLenCodeMap.length); + + var i; + for (i = 0; i < numCodeLenCodes; ++i) { + codeLenCodeLengths[codeLenCodeMap[i]] = this.getBits(3); + } + var codeLenCodeTab = this.generateHuffmanTable(codeLenCodeLengths); + + // build the literal and distance code tables + len = 0; + i = 0; + var codes = numLitCodes + numDistCodes; + var codeLengths = new Uint8Array(codes); + var bitsLength, bitsOffset, what; + while (i < codes) { + var code = this.getCode(codeLenCodeTab); + if (code === 16) { + bitsLength = 2; bitsOffset = 3; what = len; + } else if (code === 17) { + bitsLength = 3; bitsOffset = 3; what = (len = 0); + } else if (code === 18) { + bitsLength = 7; bitsOffset = 11; what = (len = 0); + } else { + codeLengths[i++] = len = code; + continue; + } + + var repeatLength = this.getBits(bitsLength) + bitsOffset; + while (repeatLength-- > 0) { + codeLengths[i++] = what; + } + } + + litCodeTable = + this.generateHuffmanTable(codeLengths.subarray(0, numLitCodes)); + distCodeTable = + this.generateHuffmanTable(codeLengths.subarray(numLitCodes, codes)); + } else { + error('Unknown block type in flate stream'); + } + + buffer = this.buffer; + var limit = buffer ? buffer.length : 0; + var pos = this.bufferLength; + while (true) { + var code1 = this.getCode(litCodeTable); + if (code1 < 256) { + if (pos + 1 >= limit) { + buffer = this.ensureBuffer(pos + 1); + limit = buffer.length; + } + buffer[pos++] = code1; + continue; + } + if (code1 === 256) { + this.bufferLength = pos; + return; + } + code1 -= 257; + code1 = lengthDecode[code1]; + var code2 = code1 >> 16; + if (code2 > 0) { + code2 = this.getBits(code2); + } + len = (code1 & 0xffff) + code2; + code1 = this.getCode(distCodeTable); + code1 = distDecode[code1]; + code2 = code1 >> 16; + if (code2 > 0) { + code2 = this.getBits(code2); + } + var dist = (code1 & 0xffff) + code2; + if (pos + len >= limit) { + buffer = this.ensureBuffer(pos + len); + limit = buffer.length; + } + for (var k = 0; k < len; ++k, ++pos) { + buffer[pos] = buffer[pos - dist]; + } + } + }; + + return FlateStream; +})(); + +var PredictorStream = (function PredictorStreamClosure() { + function PredictorStream(str, maybeLength, params) { + var predictor = this.predictor = params.get('Predictor') || 1; + + if (predictor <= 1) { + return str; // no prediction + } + if (predictor !== 2 && (predictor < 10 || predictor > 15)) { + error('Unsupported predictor: ' + predictor); + } + + if (predictor === 2) { + this.readBlock = this.readBlockTiff; + } else { + this.readBlock = this.readBlockPng; + } + + this.str = str; + this.dict = str.dict; + + var colors = this.colors = params.get('Colors') || 1; + var bits = this.bits = params.get('BitsPerComponent') || 8; + var columns = this.columns = params.get('Columns') || 1; + + this.pixBytes = (colors * bits + 7) >> 3; + this.rowBytes = (columns * colors * bits + 7) >> 3; + + DecodeStream.call(this, maybeLength); + return this; + } + + PredictorStream.prototype = Object.create(DecodeStream.prototype); + + PredictorStream.prototype.readBlockTiff = + function predictorStreamReadBlockTiff() { + var rowBytes = this.rowBytes; + + var bufferLength = this.bufferLength; + var buffer = this.ensureBuffer(bufferLength + rowBytes); + + var bits = this.bits; + var colors = this.colors; + + var rawBytes = this.str.getBytes(rowBytes); + this.eof = !rawBytes.length; + if (this.eof) { + return; + } + + var inbuf = 0, outbuf = 0; + var inbits = 0, outbits = 0; + var pos = bufferLength; + var i; + + if (bits === 1) { + for (i = 0; i < rowBytes; ++i) { + var c = rawBytes[i]; + inbuf = (inbuf << 8) | c; + // bitwise addition is exclusive or + // first shift inbuf and then add + buffer[pos++] = (c ^ (inbuf >> colors)) & 0xFF; + // truncate inbuf (assumes colors < 16) + inbuf &= 0xFFFF; + } + } else if (bits === 8) { + for (i = 0; i < colors; ++i) { + buffer[pos++] = rawBytes[i]; + } + for (; i < rowBytes; ++i) { + buffer[pos] = buffer[pos - colors] + rawBytes[i]; + pos++; + } + } else { + var compArray = new Uint8Array(colors + 1); + var bitMask = (1 << bits) - 1; + var j = 0, k = bufferLength; + var columns = this.columns; + for (i = 0; i < columns; ++i) { + for (var kk = 0; kk < colors; ++kk) { + if (inbits < bits) { + inbuf = (inbuf << 8) | (rawBytes[j++] & 0xFF); + inbits += 8; + } + compArray[kk] = (compArray[kk] + + (inbuf >> (inbits - bits))) & bitMask; + inbits -= bits; + outbuf = (outbuf << bits) | compArray[kk]; + outbits += bits; + if (outbits >= 8) { + buffer[k++] = (outbuf >> (outbits - 8)) & 0xFF; + outbits -= 8; + } + } + } + if (outbits > 0) { + buffer[k++] = (outbuf << (8 - outbits)) + + (inbuf & ((1 << (8 - outbits)) - 1)); + } + } + this.bufferLength += rowBytes; + }; + + PredictorStream.prototype.readBlockPng = + function predictorStreamReadBlockPng() { + + var rowBytes = this.rowBytes; + var pixBytes = this.pixBytes; + + var predictor = this.str.getByte(); + var rawBytes = this.str.getBytes(rowBytes); + this.eof = !rawBytes.length; + if (this.eof) { + return; + } + + var bufferLength = this.bufferLength; + var buffer = this.ensureBuffer(bufferLength + rowBytes); + + var prevRow = buffer.subarray(bufferLength - rowBytes, bufferLength); + if (prevRow.length === 0) { + prevRow = new Uint8Array(rowBytes); + } + + var i, j = bufferLength, up, c; + switch (predictor) { + case 0: + for (i = 0; i < rowBytes; ++i) { + buffer[j++] = rawBytes[i]; + } + break; + case 1: + for (i = 0; i < pixBytes; ++i) { + buffer[j++] = rawBytes[i]; + } + for (; i < rowBytes; ++i) { + buffer[j] = (buffer[j - pixBytes] + rawBytes[i]) & 0xFF; + j++; + } + break; + case 2: + for (i = 0; i < rowBytes; ++i) { + buffer[j++] = (prevRow[i] + rawBytes[i]) & 0xFF; + } + break; + case 3: + for (i = 0; i < pixBytes; ++i) { + buffer[j++] = (prevRow[i] >> 1) + rawBytes[i]; + } + for (; i < rowBytes; ++i) { + buffer[j] = (((prevRow[i] + buffer[j - pixBytes]) >> 1) + + rawBytes[i]) & 0xFF; + j++; + } + break; + case 4: + // we need to save the up left pixels values. the simplest way + // is to create a new buffer + for (i = 0; i < pixBytes; ++i) { + up = prevRow[i]; + c = rawBytes[i]; + buffer[j++] = up + c; + } + for (; i < rowBytes; ++i) { + up = prevRow[i]; + var upLeft = prevRow[i - pixBytes]; + var left = buffer[j - pixBytes]; + var p = left + up - upLeft; + + var pa = p - left; + if (pa < 0) { + pa = -pa; + } + var pb = p - up; + if (pb < 0) { + pb = -pb; + } + var pc = p - upLeft; + if (pc < 0) { + pc = -pc; + } + + c = rawBytes[i]; + if (pa <= pb && pa <= pc) { + buffer[j++] = left + c; + } else if (pb <= pc) { + buffer[j++] = up + c; + } else { + buffer[j++] = upLeft + c; + } + } + break; + default: + error('Unsupported predictor: ' + predictor); + } + this.bufferLength += rowBytes; + }; + + return PredictorStream; +})(); + +/** + * Depending on the type of JPEG a JpegStream is handled in different ways. For + * JPEG's that are supported natively such as DeviceGray and DeviceRGB the image + * data is stored and then loaded by the browser. For unsupported JPEG's we use + * a library to decode these images and the stream behaves like all the other + * DecodeStreams. + */ +var JpegStream = (function JpegStreamClosure() { + function JpegStream(stream, maybeLength, dict, xref) { + // Some images may contain 'junk' before the SOI (start-of-image) marker. + // Note: this seems to mainly affect inline images. + var ch; + while ((ch = stream.getByte()) !== -1) { + if (ch === 0xFF) { // Find the first byte of the SOI marker (0xFFD8). + stream.skip(-1); // Reset the stream position to the SOI. + break; + } + } + this.stream = stream; + this.maybeLength = maybeLength; + this.dict = dict; + + DecodeStream.call(this, maybeLength); + } + + JpegStream.prototype = Object.create(DecodeStream.prototype); + + Object.defineProperty(JpegStream.prototype, 'bytes', { + get: function JpegStream_bytes() { + // If this.maybeLength is null, we'll get the entire stream. + return shadow(this, 'bytes', this.stream.getBytes(this.maybeLength)); + }, + configurable: true + }); + + JpegStream.prototype.ensureBuffer = function JpegStream_ensureBuffer(req) { + if (this.bufferLength) { + return; + } + try { + var jpegImage = new JpegImage(); + + // checking if values needs to be transformed before conversion + if (this.forceRGB && this.dict && isArray(this.dict.get('Decode'))) { + var decodeArr = this.dict.get('Decode'); + var bitsPerComponent = this.dict.get('BitsPerComponent') || 8; + var decodeArrLength = decodeArr.length; + var transform = new Int32Array(decodeArrLength); + var transformNeeded = false; + var maxValue = (1 << bitsPerComponent) - 1; + for (var i = 0; i < decodeArrLength; i += 2) { + transform[i] = ((decodeArr[i + 1] - decodeArr[i]) * 256) | 0; + transform[i + 1] = (decodeArr[i] * maxValue) | 0; + if (transform[i] !== 256 || transform[i + 1] !== 0) { + transformNeeded = true; + } + } + if (transformNeeded) { + jpegImage.decodeTransform = transform; + } + } + + jpegImage.parse(this.bytes); + var data = jpegImage.getData(this.drawWidth, this.drawHeight, + this.forceRGB); + this.buffer = data; + this.bufferLength = data.length; + this.eof = true; + } catch (e) { + error('JPEG error: ' + e); + } + }; + + JpegStream.prototype.getBytes = function JpegStream_getBytes(length) { + this.ensureBuffer(); + return this.buffer; + }; + + JpegStream.prototype.getIR = function JpegStream_getIR() { + return PDFJS.createObjectURL(this.bytes, 'image/jpeg'); + }; + /** + * Checks if the image can be decoded and displayed by the browser without any + * further processing such as color space conversions. + */ + JpegStream.prototype.isNativelySupported = + function JpegStream_isNativelySupported(xref, res) { + var cs = ColorSpace.parse(this.dict.get('ColorSpace', 'CS'), xref, res); + return cs.name === 'DeviceGray' || cs.name === 'DeviceRGB'; + }; + /** + * Checks if the image can be decoded by the browser. + */ + JpegStream.prototype.isNativelyDecodable = + function JpegStream_isNativelyDecodable(xref, res) { + var cs = ColorSpace.parse(this.dict.get('ColorSpace', 'CS'), xref, res); + var numComps = cs.numComps; + return numComps === 1 || numComps === 3; + }; + + return JpegStream; +})(); + +/** + * For JPEG 2000's we use a library to decode these images and + * the stream behaves like all the other DecodeStreams. + */ +var JpxStream = (function JpxStreamClosure() { + function JpxStream(stream, maybeLength, dict) { + this.stream = stream; + this.maybeLength = maybeLength; + this.dict = dict; + + DecodeStream.call(this, maybeLength); + } + + JpxStream.prototype = Object.create(DecodeStream.prototype); + + Object.defineProperty(JpxStream.prototype, 'bytes', { + get: function JpxStream_bytes() { + // If this.maybeLength is null, we'll get the entire stream. + return shadow(this, 'bytes', this.stream.getBytes(this.maybeLength)); + }, + configurable: true + }); + + JpxStream.prototype.ensureBuffer = function JpxStream_ensureBuffer(req) { + if (this.bufferLength) { + return; + } + + var jpxImage = new JpxImage(); + jpxImage.parse(this.bytes); + + var width = jpxImage.width; + var height = jpxImage.height; + var componentsCount = jpxImage.componentsCount; + var tileCount = jpxImage.tiles.length; + if (tileCount === 1) { + this.buffer = jpxImage.tiles[0].items; + } else { + var data = new Uint8Array(width * height * componentsCount); + + for (var k = 0; k < tileCount; k++) { + var tileComponents = jpxImage.tiles[k]; + var tileWidth = tileComponents.width; + var tileHeight = tileComponents.height; + var tileLeft = tileComponents.left; + var tileTop = tileComponents.top; + + var src = tileComponents.items; + var srcPosition = 0; + var dataPosition = (width * tileTop + tileLeft) * componentsCount; + var imgRowSize = width * componentsCount; + var tileRowSize = tileWidth * componentsCount; + + for (var j = 0; j < tileHeight; j++) { + var rowBytes = src.subarray(srcPosition, srcPosition + tileRowSize); + data.set(rowBytes, dataPosition); + srcPosition += tileRowSize; + dataPosition += imgRowSize; + } + } + this.buffer = data; + } + this.bufferLength = this.buffer.length; + this.eof = true; + }; + + return JpxStream; +})(); + +/** + * For JBIG2's we use a library to decode these images and + * the stream behaves like all the other DecodeStreams. + */ +var Jbig2Stream = (function Jbig2StreamClosure() { + function Jbig2Stream(stream, maybeLength, dict) { + this.stream = stream; + this.maybeLength = maybeLength; + this.dict = dict; + + DecodeStream.call(this, maybeLength); + } + + Jbig2Stream.prototype = Object.create(DecodeStream.prototype); + + Object.defineProperty(Jbig2Stream.prototype, 'bytes', { + get: function Jbig2Stream_bytes() { + // If this.maybeLength is null, we'll get the entire stream. + return shadow(this, 'bytes', this.stream.getBytes(this.maybeLength)); + }, + configurable: true + }); + + Jbig2Stream.prototype.ensureBuffer = function Jbig2Stream_ensureBuffer(req) { + if (this.bufferLength) { + return; + } + + var jbig2Image = new Jbig2Image(); + + var chunks = [], xref = this.dict.xref; + var decodeParams = xref.fetchIfRef(this.dict.get('DecodeParms')); + + // According to the PDF specification, DecodeParms can be either + // a dictionary, or an array whose elements are dictionaries. + if (isArray(decodeParams)) { + if (decodeParams.length > 1) { + warn('JBIG2 - \'DecodeParms\' array with multiple elements ' + + 'not supported.'); + } + decodeParams = xref.fetchIfRef(decodeParams[0]); + } + if (decodeParams && decodeParams.has('JBIG2Globals')) { + var globalsStream = decodeParams.get('JBIG2Globals'); + var globals = globalsStream.getBytes(); + chunks.push({data: globals, start: 0, end: globals.length}); + } + chunks.push({data: this.bytes, start: 0, end: this.bytes.length}); + var data = jbig2Image.parseChunks(chunks); + var dataLength = data.length; + + // JBIG2 had black as 1 and white as 0, inverting the colors + for (var i = 0; i < dataLength; i++) { + data[i] ^= 0xFF; + } + + this.buffer = data; + this.bufferLength = dataLength; + this.eof = true; + }; + + return Jbig2Stream; +})(); + +var DecryptStream = (function DecryptStreamClosure() { + function DecryptStream(str, maybeLength, decrypt) { + this.str = str; + this.dict = str.dict; + this.decrypt = decrypt; + this.nextChunk = null; + this.initialized = false; + + DecodeStream.call(this, maybeLength); + } + + var chunkSize = 512; + + DecryptStream.prototype = Object.create(DecodeStream.prototype); + + DecryptStream.prototype.readBlock = function DecryptStream_readBlock() { + var chunk; + if (this.initialized) { + chunk = this.nextChunk; + } else { + chunk = this.str.getBytes(chunkSize); + this.initialized = true; + } + if (!chunk || chunk.length === 0) { + this.eof = true; + return; + } + this.nextChunk = this.str.getBytes(chunkSize); + var hasMoreData = this.nextChunk && this.nextChunk.length > 0; + + var decrypt = this.decrypt; + chunk = decrypt(chunk, !hasMoreData); + + var bufferLength = this.bufferLength; + var i, n = chunk.length; + var buffer = this.ensureBuffer(bufferLength + n); + for (i = 0; i < n; i++) { + buffer[bufferLength++] = chunk[i]; + } + this.bufferLength = bufferLength; + }; + + return DecryptStream; +})(); + +var Ascii85Stream = (function Ascii85StreamClosure() { + function Ascii85Stream(str, maybeLength) { + this.str = str; + this.dict = str.dict; + this.input = new Uint8Array(5); + + // Most streams increase in size when decoded, but Ascii85 streams + // typically shrink by ~20%. + if (maybeLength) { + maybeLength = 0.8 * maybeLength; + } + DecodeStream.call(this, maybeLength); + } + + Ascii85Stream.prototype = Object.create(DecodeStream.prototype); + + Ascii85Stream.prototype.readBlock = function Ascii85Stream_readBlock() { + var TILDA_CHAR = 0x7E; // '~' + var Z_LOWER_CHAR = 0x7A; // 'z' + var EOF = -1; + + var str = this.str; + + var c = str.getByte(); + while (Lexer.isSpace(c)) { + c = str.getByte(); + } + + if (c === EOF || c === TILDA_CHAR) { + this.eof = true; + return; + } + + var bufferLength = this.bufferLength, buffer; + var i; + + // special code for z + if (c === Z_LOWER_CHAR) { + buffer = this.ensureBuffer(bufferLength + 4); + for (i = 0; i < 4; ++i) { + buffer[bufferLength + i] = 0; + } + this.bufferLength += 4; + } else { + var input = this.input; + input[0] = c; + for (i = 1; i < 5; ++i) { + c = str.getByte(); + while (Lexer.isSpace(c)) { + c = str.getByte(); + } + + input[i] = c; + + if (c === EOF || c === TILDA_CHAR) { + break; + } + } + buffer = this.ensureBuffer(bufferLength + i - 1); + this.bufferLength += i - 1; + + // partial ending; + if (i < 5) { + for (; i < 5; ++i) { + input[i] = 0x21 + 84; + } + this.eof = true; + } + var t = 0; + for (i = 0; i < 5; ++i) { + t = t * 85 + (input[i] - 0x21); + } + + for (i = 3; i >= 0; --i) { + buffer[bufferLength + i] = t & 0xFF; + t >>= 8; + } + } + }; + + return Ascii85Stream; +})(); + +var AsciiHexStream = (function AsciiHexStreamClosure() { + function AsciiHexStream(str, maybeLength) { + this.str = str; + this.dict = str.dict; + + this.firstDigit = -1; + + // Most streams increase in size when decoded, but AsciiHex streams shrink + // by 50%. + if (maybeLength) { + maybeLength = 0.5 * maybeLength; + } + DecodeStream.call(this, maybeLength); + } + + AsciiHexStream.prototype = Object.create(DecodeStream.prototype); + + AsciiHexStream.prototype.readBlock = function AsciiHexStream_readBlock() { + var UPSTREAM_BLOCK_SIZE = 8000; + var bytes = this.str.getBytes(UPSTREAM_BLOCK_SIZE); + if (!bytes.length) { + this.eof = true; + return; + } + + var maxDecodeLength = (bytes.length + 1) >> 1; + var buffer = this.ensureBuffer(this.bufferLength + maxDecodeLength); + var bufferLength = this.bufferLength; + + var firstDigit = this.firstDigit; + for (var i = 0, ii = bytes.length; i < ii; i++) { + var ch = bytes[i], digit; + if (ch >= 0x30 && ch <= 0x39) { // '0'-'9' + digit = ch & 0x0F; + } else if ((ch >= 0x41 && ch <= 0x46) || (ch >= 0x61 && ch <= 0x66)) { + // 'A'-'Z', 'a'-'z' + digit = (ch & 0x0F) + 9; + } else if (ch === 0x3E) { // '>' + this.eof = true; + break; + } else { // probably whitespace + continue; // ignoring + } + if (firstDigit < 0) { + firstDigit = digit; + } else { + buffer[bufferLength++] = (firstDigit << 4) | digit; + firstDigit = -1; + } + } + if (firstDigit >= 0 && this.eof) { + // incomplete byte + buffer[bufferLength++] = (firstDigit << 4); + firstDigit = -1; + } + this.firstDigit = firstDigit; + this.bufferLength = bufferLength; + }; + + return AsciiHexStream; +})(); + +var RunLengthStream = (function RunLengthStreamClosure() { + function RunLengthStream(str, maybeLength) { + this.str = str; + this.dict = str.dict; + + DecodeStream.call(this, maybeLength); + } + + RunLengthStream.prototype = Object.create(DecodeStream.prototype); + + RunLengthStream.prototype.readBlock = function RunLengthStream_readBlock() { + // The repeatHeader has following format. The first byte defines type of run + // and amount of bytes to repeat/copy: n = 0 through 127 - copy next n bytes + // (in addition to the second byte from the header), n = 129 through 255 - + // duplicate the second byte from the header (257 - n) times, n = 128 - end. + var repeatHeader = this.str.getBytes(2); + if (!repeatHeader || repeatHeader.length < 2 || repeatHeader[0] === 128) { + this.eof = true; + return; + } + + var buffer; + var bufferLength = this.bufferLength; + var n = repeatHeader[0]; + if (n < 128) { + // copy n bytes + buffer = this.ensureBuffer(bufferLength + n + 1); + buffer[bufferLength++] = repeatHeader[1]; + if (n > 0) { + var source = this.str.getBytes(n); + buffer.set(source, bufferLength); + bufferLength += n; + } + } else { + n = 257 - n; + var b = repeatHeader[1]; + buffer = this.ensureBuffer(bufferLength + n + 1); + for (var i = 0; i < n; i++) { + buffer[bufferLength++] = b; + } + } + this.bufferLength = bufferLength; + }; + + return RunLengthStream; +})(); + +var CCITTFaxStream = (function CCITTFaxStreamClosure() { + + var ccittEOL = -2; + var twoDimPass = 0; + var twoDimHoriz = 1; + var twoDimVert0 = 2; + var twoDimVertR1 = 3; + var twoDimVertL1 = 4; + var twoDimVertR2 = 5; + var twoDimVertL2 = 6; + var twoDimVertR3 = 7; + var twoDimVertL3 = 8; + + var twoDimTable = [ + [-1, -1], [-1, -1], // 000000x + [7, twoDimVertL3], // 0000010 + [7, twoDimVertR3], // 0000011 + [6, twoDimVertL2], [6, twoDimVertL2], // 000010x + [6, twoDimVertR2], [6, twoDimVertR2], // 000011x + [4, twoDimPass], [4, twoDimPass], // 0001xxx + [4, twoDimPass], [4, twoDimPass], + [4, twoDimPass], [4, twoDimPass], + [4, twoDimPass], [4, twoDimPass], + [3, twoDimHoriz], [3, twoDimHoriz], // 001xxxx + [3, twoDimHoriz], [3, twoDimHoriz], + [3, twoDimHoriz], [3, twoDimHoriz], + [3, twoDimHoriz], [3, twoDimHoriz], + [3, twoDimHoriz], [3, twoDimHoriz], + [3, twoDimHoriz], [3, twoDimHoriz], + [3, twoDimHoriz], [3, twoDimHoriz], + [3, twoDimHoriz], [3, twoDimHoriz], + [3, twoDimVertL1], [3, twoDimVertL1], // 010xxxx + [3, twoDimVertL1], [3, twoDimVertL1], + [3, twoDimVertL1], [3, twoDimVertL1], + [3, twoDimVertL1], [3, twoDimVertL1], + [3, twoDimVertL1], [3, twoDimVertL1], + [3, twoDimVertL1], [3, twoDimVertL1], + [3, twoDimVertL1], [3, twoDimVertL1], + [3, twoDimVertL1], [3, twoDimVertL1], + [3, twoDimVertR1], [3, twoDimVertR1], // 011xxxx + [3, twoDimVertR1], [3, twoDimVertR1], + [3, twoDimVertR1], [3, twoDimVertR1], + [3, twoDimVertR1], [3, twoDimVertR1], + [3, twoDimVertR1], [3, twoDimVertR1], + [3, twoDimVertR1], [3, twoDimVertR1], + [3, twoDimVertR1], [3, twoDimVertR1], + [3, twoDimVertR1], [3, twoDimVertR1], + [1, twoDimVert0], [1, twoDimVert0], // 1xxxxxx + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0] + ]; + + var whiteTable1 = [ + [-1, -1], // 00000 + [12, ccittEOL], // 00001 + [-1, -1], [-1, -1], // 0001x + [-1, -1], [-1, -1], [-1, -1], [-1, -1], // 001xx + [-1, -1], [-1, -1], [-1, -1], [-1, -1], // 010xx + [-1, -1], [-1, -1], [-1, -1], [-1, -1], // 011xx + [11, 1792], [11, 1792], // 1000x + [12, 1984], // 10010 + [12, 2048], // 10011 + [12, 2112], // 10100 + [12, 2176], // 10101 + [12, 2240], // 10110 + [12, 2304], // 10111 + [11, 1856], [11, 1856], // 1100x + [11, 1920], [11, 1920], // 1101x + [12, 2368], // 11100 + [12, 2432], // 11101 + [12, 2496], // 11110 + [12, 2560] // 11111 + ]; + + var whiteTable2 = [ + [-1, -1], [-1, -1], [-1, -1], [-1, -1], // 0000000xx + [8, 29], [8, 29], // 00000010x + [8, 30], [8, 30], // 00000011x + [8, 45], [8, 45], // 00000100x + [8, 46], [8, 46], // 00000101x + [7, 22], [7, 22], [7, 22], [7, 22], // 0000011xx + [7, 23], [7, 23], [7, 23], [7, 23], // 0000100xx + [8, 47], [8, 47], // 00001010x + [8, 48], [8, 48], // 00001011x + [6, 13], [6, 13], [6, 13], [6, 13], // 000011xxx + [6, 13], [6, 13], [6, 13], [6, 13], + [7, 20], [7, 20], [7, 20], [7, 20], // 0001000xx + [8, 33], [8, 33], // 00010010x + [8, 34], [8, 34], // 00010011x + [8, 35], [8, 35], // 00010100x + [8, 36], [8, 36], // 00010101x + [8, 37], [8, 37], // 00010110x + [8, 38], [8, 38], // 00010111x + [7, 19], [7, 19], [7, 19], [7, 19], // 0001100xx + [8, 31], [8, 31], // 00011010x + [8, 32], [8, 32], // 00011011x + [6, 1], [6, 1], [6, 1], [6, 1], // 000111xxx + [6, 1], [6, 1], [6, 1], [6, 1], + [6, 12], [6, 12], [6, 12], [6, 12], // 001000xxx + [6, 12], [6, 12], [6, 12], [6, 12], + [8, 53], [8, 53], // 00100100x + [8, 54], [8, 54], // 00100101x + [7, 26], [7, 26], [7, 26], [7, 26], // 0010011xx + [8, 39], [8, 39], // 00101000x + [8, 40], [8, 40], // 00101001x + [8, 41], [8, 41], // 00101010x + [8, 42], [8, 42], // 00101011x + [8, 43], [8, 43], // 00101100x + [8, 44], [8, 44], // 00101101x + [7, 21], [7, 21], [7, 21], [7, 21], // 0010111xx + [7, 28], [7, 28], [7, 28], [7, 28], // 0011000xx + [8, 61], [8, 61], // 00110010x + [8, 62], [8, 62], // 00110011x + [8, 63], [8, 63], // 00110100x + [8, 0], [8, 0], // 00110101x + [8, 320], [8, 320], // 00110110x + [8, 384], [8, 384], // 00110111x + [5, 10], [5, 10], [5, 10], [5, 10], // 00111xxxx + [5, 10], [5, 10], [5, 10], [5, 10], + [5, 10], [5, 10], [5, 10], [5, 10], + [5, 10], [5, 10], [5, 10], [5, 10], + [5, 11], [5, 11], [5, 11], [5, 11], // 01000xxxx + [5, 11], [5, 11], [5, 11], [5, 11], + [5, 11], [5, 11], [5, 11], [5, 11], + [5, 11], [5, 11], [5, 11], [5, 11], + [7, 27], [7, 27], [7, 27], [7, 27], // 0100100xx + [8, 59], [8, 59], // 01001010x + [8, 60], [8, 60], // 01001011x + [9, 1472], // 010011000 + [9, 1536], // 010011001 + [9, 1600], // 010011010 + [9, 1728], // 010011011 + [7, 18], [7, 18], [7, 18], [7, 18], // 0100111xx + [7, 24], [7, 24], [7, 24], [7, 24], // 0101000xx + [8, 49], [8, 49], // 01010010x + [8, 50], [8, 50], // 01010011x + [8, 51], [8, 51], // 01010100x + [8, 52], [8, 52], // 01010101x + [7, 25], [7, 25], [7, 25], [7, 25], // 0101011xx + [8, 55], [8, 55], // 01011000x + [8, 56], [8, 56], // 01011001x + [8, 57], [8, 57], // 01011010x + [8, 58], [8, 58], // 01011011x + [6, 192], [6, 192], [6, 192], [6, 192], // 010111xxx + [6, 192], [6, 192], [6, 192], [6, 192], + [6, 1664], [6, 1664], [6, 1664], [6, 1664], // 011000xxx + [6, 1664], [6, 1664], [6, 1664], [6, 1664], + [8, 448], [8, 448], // 01100100x + [8, 512], [8, 512], // 01100101x + [9, 704], // 011001100 + [9, 768], // 011001101 + [8, 640], [8, 640], // 01100111x + [8, 576], [8, 576], // 01101000x + [9, 832], // 011010010 + [9, 896], // 011010011 + [9, 960], // 011010100 + [9, 1024], // 011010101 + [9, 1088], // 011010110 + [9, 1152], // 011010111 + [9, 1216], // 011011000 + [9, 1280], // 011011001 + [9, 1344], // 011011010 + [9, 1408], // 011011011 + [7, 256], [7, 256], [7, 256], [7, 256], // 0110111xx + [4, 2], [4, 2], [4, 2], [4, 2], // 0111xxxxx + [4, 2], [4, 2], [4, 2], [4, 2], + [4, 2], [4, 2], [4, 2], [4, 2], + [4, 2], [4, 2], [4, 2], [4, 2], + [4, 2], [4, 2], [4, 2], [4, 2], + [4, 2], [4, 2], [4, 2], [4, 2], + [4, 2], [4, 2], [4, 2], [4, 2], + [4, 2], [4, 2], [4, 2], [4, 2], + [4, 3], [4, 3], [4, 3], [4, 3], // 1000xxxxx + [4, 3], [4, 3], [4, 3], [4, 3], + [4, 3], [4, 3], [4, 3], [4, 3], + [4, 3], [4, 3], [4, 3], [4, 3], + [4, 3], [4, 3], [4, 3], [4, 3], + [4, 3], [4, 3], [4, 3], [4, 3], + [4, 3], [4, 3], [4, 3], [4, 3], + [4, 3], [4, 3], [4, 3], [4, 3], + [5, 128], [5, 128], [5, 128], [5, 128], // 10010xxxx + [5, 128], [5, 128], [5, 128], [5, 128], + [5, 128], [5, 128], [5, 128], [5, 128], + [5, 128], [5, 128], [5, 128], [5, 128], + [5, 8], [5, 8], [5, 8], [5, 8], // 10011xxxx + [5, 8], [5, 8], [5, 8], [5, 8], + [5, 8], [5, 8], [5, 8], [5, 8], + [5, 8], [5, 8], [5, 8], [5, 8], + [5, 9], [5, 9], [5, 9], [5, 9], // 10100xxxx + [5, 9], [5, 9], [5, 9], [5, 9], + [5, 9], [5, 9], [5, 9], [5, 9], + [5, 9], [5, 9], [5, 9], [5, 9], + [6, 16], [6, 16], [6, 16], [6, 16], // 101010xxx + [6, 16], [6, 16], [6, 16], [6, 16], + [6, 17], [6, 17], [6, 17], [6, 17], // 101011xxx + [6, 17], [6, 17], [6, 17], [6, 17], + [4, 4], [4, 4], [4, 4], [4, 4], // 1011xxxxx + [4, 4], [4, 4], [4, 4], [4, 4], + [4, 4], [4, 4], [4, 4], [4, 4], + [4, 4], [4, 4], [4, 4], [4, 4], + [4, 4], [4, 4], [4, 4], [4, 4], + [4, 4], [4, 4], [4, 4], [4, 4], + [4, 4], [4, 4], [4, 4], [4, 4], + [4, 4], [4, 4], [4, 4], [4, 4], + [4, 5], [4, 5], [4, 5], [4, 5], // 1100xxxxx + [4, 5], [4, 5], [4, 5], [4, 5], + [4, 5], [4, 5], [4, 5], [4, 5], + [4, 5], [4, 5], [4, 5], [4, 5], + [4, 5], [4, 5], [4, 5], [4, 5], + [4, 5], [4, 5], [4, 5], [4, 5], + [4, 5], [4, 5], [4, 5], [4, 5], + [4, 5], [4, 5], [4, 5], [4, 5], + [6, 14], [6, 14], [6, 14], [6, 14], // 110100xxx + [6, 14], [6, 14], [6, 14], [6, 14], + [6, 15], [6, 15], [6, 15], [6, 15], // 110101xxx + [6, 15], [6, 15], [6, 15], [6, 15], + [5, 64], [5, 64], [5, 64], [5, 64], // 11011xxxx + [5, 64], [5, 64], [5, 64], [5, 64], + [5, 64], [5, 64], [5, 64], [5, 64], + [5, 64], [5, 64], [5, 64], [5, 64], + [4, 6], [4, 6], [4, 6], [4, 6], // 1110xxxxx + [4, 6], [4, 6], [4, 6], [4, 6], + [4, 6], [4, 6], [4, 6], [4, 6], + [4, 6], [4, 6], [4, 6], [4, 6], + [4, 6], [4, 6], [4, 6], [4, 6], + [4, 6], [4, 6], [4, 6], [4, 6], + [4, 6], [4, 6], [4, 6], [4, 6], + [4, 6], [4, 6], [4, 6], [4, 6], + [4, 7], [4, 7], [4, 7], [4, 7], // 1111xxxxx + [4, 7], [4, 7], [4, 7], [4, 7], + [4, 7], [4, 7], [4, 7], [4, 7], + [4, 7], [4, 7], [4, 7], [4, 7], + [4, 7], [4, 7], [4, 7], [4, 7], + [4, 7], [4, 7], [4, 7], [4, 7], + [4, 7], [4, 7], [4, 7], [4, 7], + [4, 7], [4, 7], [4, 7], [4, 7] + ]; + + var blackTable1 = [ + [-1, -1], [-1, -1], // 000000000000x + [12, ccittEOL], [12, ccittEOL], // 000000000001x + [-1, -1], [-1, -1], [-1, -1], [-1, -1], // 00000000001xx + [-1, -1], [-1, -1], [-1, -1], [-1, -1], // 00000000010xx + [-1, -1], [-1, -1], [-1, -1], [-1, -1], // 00000000011xx + [-1, -1], [-1, -1], [-1, -1], [-1, -1], // 00000000100xx + [-1, -1], [-1, -1], [-1, -1], [-1, -1], // 00000000101xx + [-1, -1], [-1, -1], [-1, -1], [-1, -1], // 00000000110xx + [-1, -1], [-1, -1], [-1, -1], [-1, -1], // 00000000111xx + [11, 1792], [11, 1792], [11, 1792], [11, 1792], // 00000001000xx + [12, 1984], [12, 1984], // 000000010010x + [12, 2048], [12, 2048], // 000000010011x + [12, 2112], [12, 2112], // 000000010100x + [12, 2176], [12, 2176], // 000000010101x + [12, 2240], [12, 2240], // 000000010110x + [12, 2304], [12, 2304], // 000000010111x + [11, 1856], [11, 1856], [11, 1856], [11, 1856], // 00000001100xx + [11, 1920], [11, 1920], [11, 1920], [11, 1920], // 00000001101xx + [12, 2368], [12, 2368], // 000000011100x + [12, 2432], [12, 2432], // 000000011101x + [12, 2496], [12, 2496], // 000000011110x + [12, 2560], [12, 2560], // 000000011111x + [10, 18], [10, 18], [10, 18], [10, 18], // 0000001000xxx + [10, 18], [10, 18], [10, 18], [10, 18], + [12, 52], [12, 52], // 000000100100x + [13, 640], // 0000001001010 + [13, 704], // 0000001001011 + [13, 768], // 0000001001100 + [13, 832], // 0000001001101 + [12, 55], [12, 55], // 000000100111x + [12, 56], [12, 56], // 000000101000x + [13, 1280], // 0000001010010 + [13, 1344], // 0000001010011 + [13, 1408], // 0000001010100 + [13, 1472], // 0000001010101 + [12, 59], [12, 59], // 000000101011x + [12, 60], [12, 60], // 000000101100x + [13, 1536], // 0000001011010 + [13, 1600], // 0000001011011 + [11, 24], [11, 24], [11, 24], [11, 24], // 00000010111xx + [11, 25], [11, 25], [11, 25], [11, 25], // 00000011000xx + [13, 1664], // 0000001100100 + [13, 1728], // 0000001100101 + [12, 320], [12, 320], // 000000110011x + [12, 384], [12, 384], // 000000110100x + [12, 448], [12, 448], // 000000110101x + [13, 512], // 0000001101100 + [13, 576], // 0000001101101 + [12, 53], [12, 53], // 000000110111x + [12, 54], [12, 54], // 000000111000x + [13, 896], // 0000001110010 + [13, 960], // 0000001110011 + [13, 1024], // 0000001110100 + [13, 1088], // 0000001110101 + [13, 1152], // 0000001110110 + [13, 1216], // 0000001110111 + [10, 64], [10, 64], [10, 64], [10, 64], // 0000001111xxx + [10, 64], [10, 64], [10, 64], [10, 64] + ]; + + var blackTable2 = [ + [8, 13], [8, 13], [8, 13], [8, 13], // 00000100xxxx + [8, 13], [8, 13], [8, 13], [8, 13], + [8, 13], [8, 13], [8, 13], [8, 13], + [8, 13], [8, 13], [8, 13], [8, 13], + [11, 23], [11, 23], // 00000101000x + [12, 50], // 000001010010 + [12, 51], // 000001010011 + [12, 44], // 000001010100 + [12, 45], // 000001010101 + [12, 46], // 000001010110 + [12, 47], // 000001010111 + [12, 57], // 000001011000 + [12, 58], // 000001011001 + [12, 61], // 000001011010 + [12, 256], // 000001011011 + [10, 16], [10, 16], [10, 16], [10, 16], // 0000010111xx + [10, 17], [10, 17], [10, 17], [10, 17], // 0000011000xx + [12, 48], // 000001100100 + [12, 49], // 000001100101 + [12, 62], // 000001100110 + [12, 63], // 000001100111 + [12, 30], // 000001101000 + [12, 31], // 000001101001 + [12, 32], // 000001101010 + [12, 33], // 000001101011 + [12, 40], // 000001101100 + [12, 41], // 000001101101 + [11, 22], [11, 22], // 00000110111x + [8, 14], [8, 14], [8, 14], [8, 14], // 00000111xxxx + [8, 14], [8, 14], [8, 14], [8, 14], + [8, 14], [8, 14], [8, 14], [8, 14], + [8, 14], [8, 14], [8, 14], [8, 14], + [7, 10], [7, 10], [7, 10], [7, 10], // 0000100xxxxx + [7, 10], [7, 10], [7, 10], [7, 10], + [7, 10], [7, 10], [7, 10], [7, 10], + [7, 10], [7, 10], [7, 10], [7, 10], + [7, 10], [7, 10], [7, 10], [7, 10], + [7, 10], [7, 10], [7, 10], [7, 10], + [7, 10], [7, 10], [7, 10], [7, 10], + [7, 10], [7, 10], [7, 10], [7, 10], + [7, 11], [7, 11], [7, 11], [7, 11], // 0000101xxxxx + [7, 11], [7, 11], [7, 11], [7, 11], + [7, 11], [7, 11], [7, 11], [7, 11], + [7, 11], [7, 11], [7, 11], [7, 11], + [7, 11], [7, 11], [7, 11], [7, 11], + [7, 11], [7, 11], [7, 11], [7, 11], + [7, 11], [7, 11], [7, 11], [7, 11], + [7, 11], [7, 11], [7, 11], [7, 11], + [9, 15], [9, 15], [9, 15], [9, 15], // 000011000xxx + [9, 15], [9, 15], [9, 15], [9, 15], + [12, 128], // 000011001000 + [12, 192], // 000011001001 + [12, 26], // 000011001010 + [12, 27], // 000011001011 + [12, 28], // 000011001100 + [12, 29], // 000011001101 + [11, 19], [11, 19], // 00001100111x + [11, 20], [11, 20], // 00001101000x + [12, 34], // 000011010010 + [12, 35], // 000011010011 + [12, 36], // 000011010100 + [12, 37], // 000011010101 + [12, 38], // 000011010110 + [12, 39], // 000011010111 + [11, 21], [11, 21], // 00001101100x + [12, 42], // 000011011010 + [12, 43], // 000011011011 + [10, 0], [10, 0], [10, 0], [10, 0], // 0000110111xx + [7, 12], [7, 12], [7, 12], [7, 12], // 0000111xxxxx + [7, 12], [7, 12], [7, 12], [7, 12], + [7, 12], [7, 12], [7, 12], [7, 12], + [7, 12], [7, 12], [7, 12], [7, 12], + [7, 12], [7, 12], [7, 12], [7, 12], + [7, 12], [7, 12], [7, 12], [7, 12], + [7, 12], [7, 12], [7, 12], [7, 12], + [7, 12], [7, 12], [7, 12], [7, 12] + ]; + + var blackTable3 = [ + [-1, -1], [-1, -1], [-1, -1], [-1, -1], // 0000xx + [6, 9], // 000100 + [6, 8], // 000101 + [5, 7], [5, 7], // 00011x + [4, 6], [4, 6], [4, 6], [4, 6], // 0010xx + [4, 5], [4, 5], [4, 5], [4, 5], // 0011xx + [3, 1], [3, 1], [3, 1], [3, 1], // 010xxx + [3, 1], [3, 1], [3, 1], [3, 1], + [3, 4], [3, 4], [3, 4], [3, 4], // 011xxx + [3, 4], [3, 4], [3, 4], [3, 4], + [2, 3], [2, 3], [2, 3], [2, 3], // 10xxxx + [2, 3], [2, 3], [2, 3], [2, 3], + [2, 3], [2, 3], [2, 3], [2, 3], + [2, 3], [2, 3], [2, 3], [2, 3], + [2, 2], [2, 2], [2, 2], [2, 2], // 11xxxx + [2, 2], [2, 2], [2, 2], [2, 2], + [2, 2], [2, 2], [2, 2], [2, 2], + [2, 2], [2, 2], [2, 2], [2, 2] + ]; + + function CCITTFaxStream(str, maybeLength, params) { + this.str = str; + this.dict = str.dict; + + params = params || Dict.empty; + + this.encoding = params.get('K') || 0; + this.eoline = params.get('EndOfLine') || false; + this.byteAlign = params.get('EncodedByteAlign') || false; + this.columns = params.get('Columns') || 1728; + this.rows = params.get('Rows') || 0; + var eoblock = params.get('EndOfBlock'); + if (eoblock === null || eoblock === undefined) { + eoblock = true; + } + this.eoblock = eoblock; + this.black = params.get('BlackIs1') || false; + + this.codingLine = new Uint32Array(this.columns + 1); + this.refLine = new Uint32Array(this.columns + 2); + + this.codingLine[0] = this.columns; + this.codingPos = 0; + + this.row = 0; + this.nextLine2D = this.encoding < 0; + this.inputBits = 0; + this.inputBuf = 0; + this.outputBits = 0; + + var code1; + while ((code1 = this.lookBits(12)) === 0) { + this.eatBits(1); + } + if (code1 === 1) { + this.eatBits(12); + } + if (this.encoding > 0) { + this.nextLine2D = !this.lookBits(1); + this.eatBits(1); + } + + DecodeStream.call(this, maybeLength); + } + + CCITTFaxStream.prototype = Object.create(DecodeStream.prototype); + + CCITTFaxStream.prototype.readBlock = function CCITTFaxStream_readBlock() { + while (!this.eof) { + var c = this.lookChar(); + this.ensureBuffer(this.bufferLength + 1); + this.buffer[this.bufferLength++] = c; + } + }; + + CCITTFaxStream.prototype.addPixels = + function ccittFaxStreamAddPixels(a1, blackPixels) { + var codingLine = this.codingLine; + var codingPos = this.codingPos; + + if (a1 > codingLine[codingPos]) { + if (a1 > this.columns) { + info('row is wrong length'); + this.err = true; + a1 = this.columns; + } + if ((codingPos & 1) ^ blackPixels) { + ++codingPos; + } + + codingLine[codingPos] = a1; + } + this.codingPos = codingPos; + }; + + CCITTFaxStream.prototype.addPixelsNeg = + function ccittFaxStreamAddPixelsNeg(a1, blackPixels) { + var codingLine = this.codingLine; + var codingPos = this.codingPos; + + if (a1 > codingLine[codingPos]) { + if (a1 > this.columns) { + info('row is wrong length'); + this.err = true; + a1 = this.columns; + } + if ((codingPos & 1) ^ blackPixels) { + ++codingPos; + } + + codingLine[codingPos] = a1; + } else if (a1 < codingLine[codingPos]) { + if (a1 < 0) { + info('invalid code'); + this.err = true; + a1 = 0; + } + while (codingPos > 0 && a1 < codingLine[codingPos - 1]) { + --codingPos; + } + codingLine[codingPos] = a1; + } + + this.codingPos = codingPos; + }; + + CCITTFaxStream.prototype.lookChar = function CCITTFaxStream_lookChar() { + var refLine = this.refLine; + var codingLine = this.codingLine; + var columns = this.columns; + + var refPos, blackPixels, bits, i; + + if (this.outputBits === 0) { + if (this.eof) { + return null; + } + this.err = false; + + var code1, code2, code3; + if (this.nextLine2D) { + for (i = 0; codingLine[i] < columns; ++i) { + refLine[i] = codingLine[i]; + } + refLine[i++] = columns; + refLine[i] = columns; + codingLine[0] = 0; + this.codingPos = 0; + refPos = 0; + blackPixels = 0; + + while (codingLine[this.codingPos] < columns) { + code1 = this.getTwoDimCode(); + switch (code1) { + case twoDimPass: + this.addPixels(refLine[refPos + 1], blackPixels); + if (refLine[refPos + 1] < columns) { + refPos += 2; + } + break; + case twoDimHoriz: + code1 = code2 = 0; + if (blackPixels) { + do { + code1 += (code3 = this.getBlackCode()); + } while (code3 >= 64); + do { + code2 += (code3 = this.getWhiteCode()); + } while (code3 >= 64); + } else { + do { + code1 += (code3 = this.getWhiteCode()); + } while (code3 >= 64); + do { + code2 += (code3 = this.getBlackCode()); + } while (code3 >= 64); + } + this.addPixels(codingLine[this.codingPos] + + code1, blackPixels); + if (codingLine[this.codingPos] < columns) { + this.addPixels(codingLine[this.codingPos] + code2, + blackPixels ^ 1); + } + while (refLine[refPos] <= codingLine[this.codingPos] && + refLine[refPos] < columns) { + refPos += 2; + } + break; + case twoDimVertR3: + this.addPixels(refLine[refPos] + 3, blackPixels); + blackPixels ^= 1; + if (codingLine[this.codingPos] < columns) { + ++refPos; + while (refLine[refPos] <= codingLine[this.codingPos] && + refLine[refPos] < columns) { + refPos += 2; + } + } + break; + case twoDimVertR2: + this.addPixels(refLine[refPos] + 2, blackPixels); + blackPixels ^= 1; + if (codingLine[this.codingPos] < columns) { + ++refPos; + while (refLine[refPos] <= codingLine[this.codingPos] && + refLine[refPos] < columns) { + refPos += 2; + } + } + break; + case twoDimVertR1: + this.addPixels(refLine[refPos] + 1, blackPixels); + blackPixels ^= 1; + if (codingLine[this.codingPos] < columns) { + ++refPos; + while (refLine[refPos] <= codingLine[this.codingPos] && + refLine[refPos] < columns) { + refPos += 2; + } + } + break; + case twoDimVert0: + this.addPixels(refLine[refPos], blackPixels); + blackPixels ^= 1; + if (codingLine[this.codingPos] < columns) { + ++refPos; + while (refLine[refPos] <= codingLine[this.codingPos] && + refLine[refPos] < columns) { + refPos += 2; + } + } + break; + case twoDimVertL3: + this.addPixelsNeg(refLine[refPos] - 3, blackPixels); + blackPixels ^= 1; + if (codingLine[this.codingPos] < columns) { + if (refPos > 0) { + --refPos; + } else { + ++refPos; + } + while (refLine[refPos] <= codingLine[this.codingPos] && + refLine[refPos] < columns) { + refPos += 2; + } + } + break; + case twoDimVertL2: + this.addPixelsNeg(refLine[refPos] - 2, blackPixels); + blackPixels ^= 1; + if (codingLine[this.codingPos] < columns) { + if (refPos > 0) { + --refPos; + } else { + ++refPos; + } + while (refLine[refPos] <= codingLine[this.codingPos] && + refLine[refPos] < columns) { + refPos += 2; + } + } + break; + case twoDimVertL1: + this.addPixelsNeg(refLine[refPos] - 1, blackPixels); + blackPixels ^= 1; + if (codingLine[this.codingPos] < columns) { + if (refPos > 0) { + --refPos; + } else { + ++refPos; + } + while (refLine[refPos] <= codingLine[this.codingPos] && + refLine[refPos] < columns) { + refPos += 2; + } + } + break; + case EOF: + this.addPixels(columns, 0); + this.eof = true; + break; + default: + info('bad 2d code'); + this.addPixels(columns, 0); + this.err = true; + } + } + } else { + codingLine[0] = 0; + this.codingPos = 0; + blackPixels = 0; + while (codingLine[this.codingPos] < columns) { + code1 = 0; + if (blackPixels) { + do { + code1 += (code3 = this.getBlackCode()); + } while (code3 >= 64); + } else { + do { + code1 += (code3 = this.getWhiteCode()); + } while (code3 >= 64); + } + this.addPixels(codingLine[this.codingPos] + code1, blackPixels); + blackPixels ^= 1; + } + } + + var gotEOL = false; + + if (this.byteAlign) { + this.inputBits &= ~7; + } + + if (!this.eoblock && this.row === this.rows - 1) { + this.eof = true; + } else { + code1 = this.lookBits(12); + if (this.eoline) { + while (code1 !== EOF && code1 !== 1) { + this.eatBits(1); + code1 = this.lookBits(12); + } + } else { + while (code1 === 0) { + this.eatBits(1); + code1 = this.lookBits(12); + } + } + if (code1 === 1) { + this.eatBits(12); + gotEOL = true; + } else if (code1 === EOF) { + this.eof = true; + } + } + + if (!this.eof && this.encoding > 0) { + this.nextLine2D = !this.lookBits(1); + this.eatBits(1); + } + + if (this.eoblock && gotEOL && this.byteAlign) { + code1 = this.lookBits(12); + if (code1 === 1) { + this.eatBits(12); + if (this.encoding > 0) { + this.lookBits(1); + this.eatBits(1); + } + if (this.encoding >= 0) { + for (i = 0; i < 4; ++i) { + code1 = this.lookBits(12); + if (code1 !== 1) { + info('bad rtc code: ' + code1); + } + this.eatBits(12); + if (this.encoding > 0) { + this.lookBits(1); + this.eatBits(1); + } + } + } + this.eof = true; + } + } else if (this.err && this.eoline) { + while (true) { + code1 = this.lookBits(13); + if (code1 === EOF) { + this.eof = true; + return null; + } + if ((code1 >> 1) === 1) { + break; + } + this.eatBits(1); + } + this.eatBits(12); + if (this.encoding > 0) { + this.eatBits(1); + this.nextLine2D = !(code1 & 1); + } + } + + if (codingLine[0] > 0) { + this.outputBits = codingLine[this.codingPos = 0]; + } else { + this.outputBits = codingLine[this.codingPos = 1]; + } + this.row++; + } + + var c; + if (this.outputBits >= 8) { + c = (this.codingPos & 1) ? 0 : 0xFF; + this.outputBits -= 8; + if (this.outputBits === 0 && codingLine[this.codingPos] < columns) { + this.codingPos++; + this.outputBits = (codingLine[this.codingPos] - + codingLine[this.codingPos - 1]); + } + } else { + bits = 8; + c = 0; + do { + if (this.outputBits > bits) { + c <<= bits; + if (!(this.codingPos & 1)) { + c |= 0xFF >> (8 - bits); + } + this.outputBits -= bits; + bits = 0; + } else { + c <<= this.outputBits; + if (!(this.codingPos & 1)) { + c |= 0xFF >> (8 - this.outputBits); + } + bits -= this.outputBits; + this.outputBits = 0; + if (codingLine[this.codingPos] < columns) { + this.codingPos++; + this.outputBits = (codingLine[this.codingPos] - + codingLine[this.codingPos - 1]); + } else if (bits > 0) { + c <<= bits; + bits = 0; + } + } + } while (bits); + } + if (this.black) { + c ^= 0xFF; + } + return c; + }; + + // This functions returns the code found from the table. + // The start and end parameters set the boundaries for searching the table. + // The limit parameter is optional. Function returns an array with three + // values. The first array element indicates whether a valid code is being + // returned. The second array element is the actual code. The third array + // element indicates whether EOF was reached. + CCITTFaxStream.prototype.findTableCode = + function ccittFaxStreamFindTableCode(start, end, table, limit) { + + var limitValue = limit || 0; + for (var i = start; i <= end; ++i) { + var code = this.lookBits(i); + if (code === EOF) { + return [true, 1, false]; + } + if (i < end) { + code <<= end - i; + } + if (!limitValue || code >= limitValue) { + var p = table[code - limitValue]; + if (p[0] === i) { + this.eatBits(i); + return [true, p[1], true]; + } + } + } + return [false, 0, false]; + }; + + CCITTFaxStream.prototype.getTwoDimCode = + function ccittFaxStreamGetTwoDimCode() { + + var code = 0; + var p; + if (this.eoblock) { + code = this.lookBits(7); + p = twoDimTable[code]; + if (p && p[0] > 0) { + this.eatBits(p[0]); + return p[1]; + } + } else { + var result = this.findTableCode(1, 7, twoDimTable); + if (result[0] && result[2]) { + return result[1]; + } + } + info('Bad two dim code'); + return EOF; + }; + + CCITTFaxStream.prototype.getWhiteCode = + function ccittFaxStreamGetWhiteCode() { + + var code = 0; + var p; + if (this.eoblock) { + code = this.lookBits(12); + if (code === EOF) { + return 1; + } + + if ((code >> 5) === 0) { + p = whiteTable1[code]; + } else { + p = whiteTable2[code >> 3]; + } + + if (p[0] > 0) { + this.eatBits(p[0]); + return p[1]; + } + } else { + var result = this.findTableCode(1, 9, whiteTable2); + if (result[0]) { + return result[1]; + } + + result = this.findTableCode(11, 12, whiteTable1); + if (result[0]) { + return result[1]; + } + } + info('bad white code'); + this.eatBits(1); + return 1; + }; + + CCITTFaxStream.prototype.getBlackCode = + function ccittFaxStreamGetBlackCode() { + + var code, p; + if (this.eoblock) { + code = this.lookBits(13); + if (code === EOF) { + return 1; + } + if ((code >> 7) === 0) { + p = blackTable1[code]; + } else if ((code >> 9) === 0 && (code >> 7) !== 0) { + p = blackTable2[(code >> 1) - 64]; + } else { + p = blackTable3[code >> 7]; + } + + if (p[0] > 0) { + this.eatBits(p[0]); + return p[1]; + } + } else { + var result = this.findTableCode(2, 6, blackTable3); + if (result[0]) { + return result[1]; + } + + result = this.findTableCode(7, 12, blackTable2, 64); + if (result[0]) { + return result[1]; + } + + result = this.findTableCode(10, 13, blackTable1); + if (result[0]) { + return result[1]; + } + } + info('bad black code'); + this.eatBits(1); + return 1; + }; + + CCITTFaxStream.prototype.lookBits = function CCITTFaxStream_lookBits(n) { + var c; + while (this.inputBits < n) { + if ((c = this.str.getByte()) === -1) { + if (this.inputBits === 0) { + return EOF; + } + return ((this.inputBuf << (n - this.inputBits)) & + (0xFFFF >> (16 - n))); + } + this.inputBuf = (this.inputBuf << 8) + c; + this.inputBits += 8; + } + return (this.inputBuf >> (this.inputBits - n)) & (0xFFFF >> (16 - n)); + }; + + CCITTFaxStream.prototype.eatBits = function CCITTFaxStream_eatBits(n) { + if ((this.inputBits -= n) < 0) { + this.inputBits = 0; + } + }; + + return CCITTFaxStream; +})(); + +var LZWStream = (function LZWStreamClosure() { + function LZWStream(str, maybeLength, earlyChange) { + this.str = str; + this.dict = str.dict; + this.cachedData = 0; + this.bitsCached = 0; + + var maxLzwDictionarySize = 4096; + var lzwState = { + earlyChange: earlyChange, + codeLength: 9, + nextCode: 258, + dictionaryValues: new Uint8Array(maxLzwDictionarySize), + dictionaryLengths: new Uint16Array(maxLzwDictionarySize), + dictionaryPrevCodes: new Uint16Array(maxLzwDictionarySize), + currentSequence: new Uint8Array(maxLzwDictionarySize), + currentSequenceLength: 0 + }; + for (var i = 0; i < 256; ++i) { + lzwState.dictionaryValues[i] = i; + lzwState.dictionaryLengths[i] = 1; + } + this.lzwState = lzwState; + + DecodeStream.call(this, maybeLength); + } + + LZWStream.prototype = Object.create(DecodeStream.prototype); + + LZWStream.prototype.readBits = function LZWStream_readBits(n) { + var bitsCached = this.bitsCached; + var cachedData = this.cachedData; + while (bitsCached < n) { + var c = this.str.getByte(); + if (c === -1) { + this.eof = true; + return null; + } + cachedData = (cachedData << 8) | c; + bitsCached += 8; + } + this.bitsCached = (bitsCached -= n); + this.cachedData = cachedData; + this.lastCode = null; + return (cachedData >>> bitsCached) & ((1 << n) - 1); + }; + + LZWStream.prototype.readBlock = function LZWStream_readBlock() { + var blockSize = 512; + var estimatedDecodedSize = blockSize * 2, decodedSizeDelta = blockSize; + var i, j, q; + + var lzwState = this.lzwState; + if (!lzwState) { + return; // eof was found + } + + var earlyChange = lzwState.earlyChange; + var nextCode = lzwState.nextCode; + var dictionaryValues = lzwState.dictionaryValues; + var dictionaryLengths = lzwState.dictionaryLengths; + var dictionaryPrevCodes = lzwState.dictionaryPrevCodes; + var codeLength = lzwState.codeLength; + var prevCode = lzwState.prevCode; + var currentSequence = lzwState.currentSequence; + var currentSequenceLength = lzwState.currentSequenceLength; + + var decodedLength = 0; + var currentBufferLength = this.bufferLength; + var buffer = this.ensureBuffer(this.bufferLength + estimatedDecodedSize); + + for (i = 0; i < blockSize; i++) { + var code = this.readBits(codeLength); + var hasPrev = currentSequenceLength > 0; + if (code < 256) { + currentSequence[0] = code; + currentSequenceLength = 1; + } else if (code >= 258) { + if (code < nextCode) { + currentSequenceLength = dictionaryLengths[code]; + for (j = currentSequenceLength - 1, q = code; j >= 0; j--) { + currentSequence[j] = dictionaryValues[q]; + q = dictionaryPrevCodes[q]; + } + } else { + currentSequence[currentSequenceLength++] = currentSequence[0]; + } + } else if (code === 256) { + codeLength = 9; + nextCode = 258; + currentSequenceLength = 0; + continue; + } else { + this.eof = true; + delete this.lzwState; + break; + } + + if (hasPrev) { + dictionaryPrevCodes[nextCode] = prevCode; + dictionaryLengths[nextCode] = dictionaryLengths[prevCode] + 1; + dictionaryValues[nextCode] = currentSequence[0]; + nextCode++; + codeLength = (nextCode + earlyChange) & (nextCode + earlyChange - 1) ? + codeLength : Math.min(Math.log(nextCode + earlyChange) / + 0.6931471805599453 + 1, 12) | 0; + } + prevCode = code; + + decodedLength += currentSequenceLength; + if (estimatedDecodedSize < decodedLength) { + do { + estimatedDecodedSize += decodedSizeDelta; + } while (estimatedDecodedSize < decodedLength); + buffer = this.ensureBuffer(this.bufferLength + estimatedDecodedSize); + } + for (j = 0; j < currentSequenceLength; j++) { + buffer[currentBufferLength++] = currentSequence[j]; + } + } + lzwState.nextCode = nextCode; + lzwState.codeLength = codeLength; + lzwState.prevCode = prevCode; + lzwState.currentSequenceLength = currentSequenceLength; + + this.bufferLength = currentBufferLength; + }; + + return LZWStream; +})(); + +var NullStream = (function NullStreamClosure() { + function NullStream() { + Stream.call(this, new Uint8Array(0)); + } + + NullStream.prototype = Stream.prototype; + + return NullStream; +})(); + + +var WorkerMessageHandler = PDFJS.WorkerMessageHandler = { + setup: function wphSetup(handler) { + var pdfManager; + + function loadDocument(recoveryMode) { + var loadDocumentCapability = createPromiseCapability(); + + var parseSuccess = function parseSuccess() { + var numPagesPromise = pdfManager.ensureDoc('numPages'); + var fingerprintPromise = pdfManager.ensureDoc('fingerprint'); + var encryptedPromise = pdfManager.ensureXRef('encrypt'); + Promise.all([numPagesPromise, fingerprintPromise, + encryptedPromise]).then(function onDocReady(results) { + var doc = { + numPages: results[0], + fingerprint: results[1], + encrypted: !!results[2], + }; + loadDocumentCapability.resolve(doc); + }, + parseFailure); + }; + + var parseFailure = function parseFailure(e) { + loadDocumentCapability.reject(e); + }; + + pdfManager.ensureDoc('checkHeader', []).then(function() { + pdfManager.ensureDoc('parseStartXRef', []).then(function() { + pdfManager.ensureDoc('parse', [recoveryMode]).then( + parseSuccess, parseFailure); + }, parseFailure); + }, parseFailure); + + return loadDocumentCapability.promise; + } + + function getPdfManager(data) { + var pdfManagerCapability = createPromiseCapability(); + + var source = data.source; + var disableRange = data.disableRange; + if (source.data) { + try { + pdfManager = new LocalPdfManager(source.data, source.password); + pdfManagerCapability.resolve(); + } catch (ex) { + pdfManagerCapability.reject(ex); + } + return pdfManagerCapability.promise; + } else if (source.chunkedViewerLoading) { + try { + pdfManager = new NetworkPdfManager(source, handler); + pdfManagerCapability.resolve(); + } catch (ex) { + pdfManagerCapability.reject(ex); + } + return pdfManagerCapability.promise; + } + + var networkManager = new NetworkManager(source.url, { + httpHeaders: source.httpHeaders, + withCredentials: source.withCredentials + }); + var cachedChunks = []; + var fullRequestXhrId = networkManager.requestFull({ + onHeadersReceived: function onHeadersReceived() { + if (disableRange) { + return; + } + + var fullRequestXhr = networkManager.getRequestXhr(fullRequestXhrId); + if (fullRequestXhr.getResponseHeader('Accept-Ranges') !== 'bytes') { + return; + } + + var contentEncoding = + fullRequestXhr.getResponseHeader('Content-Encoding') || 'identity'; + if (contentEncoding !== 'identity') { + return; + } + + var length = fullRequestXhr.getResponseHeader('Content-Length'); + length = parseInt(length, 10); + if (!isInt(length)) { + return; + } + source.length = length; + if (length <= 2 * RANGE_CHUNK_SIZE) { + // The file size is smaller than the size of two chunks, so it does + // not make any sense to abort the request and retry with a range + // request. + return; + } + + if (networkManager.isStreamingRequest(fullRequestXhrId)) { + // We can continue fetching when progressive loading is enabled, + // and we don't need the autoFetch feature. + source.disableAutoFetch = true; + } else { + // NOTE: by cancelling the full request, and then issuing range + // requests, there will be an issue for sites where you can only + // request the pdf once. However, if this is the case, then the + // server should not be returning that it can support range + // requests. + networkManager.abortRequest(fullRequestXhrId); + } + + try { + pdfManager = new NetworkPdfManager(source, handler); + pdfManagerCapability.resolve(pdfManager); + } catch (ex) { + pdfManagerCapability.reject(ex); + } + }, + + onProgressiveData: source.disableStream ? null : + function onProgressiveData(chunk) { + if (!pdfManager) { + cachedChunks.push(chunk); + return; + } + pdfManager.sendProgressiveData(chunk); + }, + + onDone: function onDone(args) { + if (pdfManager) { + return; // already processed + } + + var pdfFile; + if (args === null) { + // TODO add some streaming manager, e.g. for unknown length files. + // The data was returned in the onProgressiveData, combining... + var pdfFileLength = 0, pos = 0; + cachedChunks.forEach(function (chunk) { + pdfFileLength += chunk.byteLength; + }); + if (source.length && pdfFileLength !== source.length) { + warn('reported HTTP length is different from actual'); + } + var pdfFileArray = new Uint8Array(pdfFileLength); + cachedChunks.forEach(function (chunk) { + pdfFileArray.set(new Uint8Array(chunk), pos); + pos += chunk.byteLength; + }); + pdfFile = pdfFileArray.buffer; + } else { + pdfFile = args.chunk; + } + + // the data is array, instantiating directly from it + try { + pdfManager = new LocalPdfManager(pdfFile, source.password); + pdfManagerCapability.resolve(); + } catch (ex) { + pdfManagerCapability.reject(ex); + } + }, + + onError: function onError(status) { + var exception; + if (status === 404) { + exception = new MissingPDFException('Missing PDF "' + + source.url + '".'); + handler.send('MissingPDF', exception); + } else { + exception = new UnexpectedResponseException( + 'Unexpected server response (' + status + + ') while retrieving PDF "' + source.url + '".', status); + handler.send('UnexpectedResponse', exception); + } + }, + + onProgress: function onProgress(evt) { + handler.send('DocProgress', { + loaded: evt.loaded, + total: evt.lengthComputable ? evt.total : source.length + }); + } + }); + + return pdfManagerCapability.promise; + } + + handler.on('test', function wphSetupTest(data) { + // check if Uint8Array can be sent to worker + if (!(data instanceof Uint8Array)) { + handler.send('test', false); + return; + } + // making sure postMessage transfers are working + var supportTransfers = data[0] === 255; + handler.postMessageTransfers = supportTransfers; + // check if the response property is supported by xhr + var xhr = new XMLHttpRequest(); + var responseExists = 'response' in xhr; + // check if the property is actually implemented + try { + var dummy = xhr.responseType; + } catch (e) { + responseExists = false; + } + if (!responseExists) { + handler.send('test', false); + return; + } + handler.send('test', { + supportTypedArray: true, + supportTransfers: supportTransfers + }); + }); + + handler.on('GetDocRequest', function wphSetupDoc(data) { + + var onSuccess = function(doc) { + handler.send('GetDoc', { pdfInfo: doc }); + }; + + var onFailure = function(e) { + if (e instanceof PasswordException) { + if (e.code === PasswordResponses.NEED_PASSWORD) { + handler.send('NeedPassword', e); + } else if (e.code === PasswordResponses.INCORRECT_PASSWORD) { + handler.send('IncorrectPassword', e); + } + } else if (e instanceof InvalidPDFException) { + handler.send('InvalidPDF', e); + } else if (e instanceof MissingPDFException) { + handler.send('MissingPDF', e); + } else if (e instanceof UnexpectedResponseException) { + handler.send('UnexpectedResponse', e); + } else { + handler.send('UnknownError', + new UnknownErrorException(e.message, e.toString())); + } + }; + + PDFJS.maxImageSize = data.maxImageSize === undefined ? + -1 : data.maxImageSize; + PDFJS.disableFontFace = data.disableFontFace; + PDFJS.disableCreateObjectURL = data.disableCreateObjectURL; + PDFJS.verbosity = data.verbosity; + PDFJS.cMapUrl = data.cMapUrl === undefined ? + null : data.cMapUrl; + PDFJS.cMapPacked = data.cMapPacked === true; + + getPdfManager(data).then(function () { + handler.send('PDFManagerReady', null); + pdfManager.onLoadedStream().then(function(stream) { + handler.send('DataLoaded', { length: stream.bytes.byteLength }); + }); + }).then(function pdfManagerReady() { + loadDocument(false).then(onSuccess, function loadFailure(ex) { + // Try again with recoveryMode == true + if (!(ex instanceof XRefParseException)) { + if (ex instanceof PasswordException) { + // after password exception prepare to receive a new password + // to repeat loading + pdfManager.passwordChanged().then(pdfManagerReady); + } + + onFailure(ex); + return; + } + + pdfManager.requestLoadedStream(); + pdfManager.onLoadedStream().then(function() { + loadDocument(true).then(onSuccess, onFailure); + }); + }, onFailure); + }, onFailure); + }); + + handler.on('GetPage', function wphSetupGetPage(data) { + return pdfManager.getPage(data.pageIndex).then(function(page) { + var rotatePromise = pdfManager.ensure(page, 'rotate'); + var refPromise = pdfManager.ensure(page, 'ref'); + var viewPromise = pdfManager.ensure(page, 'view'); + + return Promise.all([rotatePromise, refPromise, viewPromise]).then( + function(results) { + return { + rotate: results[0], + ref: results[1], + view: results[2] + }; + }); + }); + }); + + handler.on('GetPageIndex', function wphSetupGetPageIndex(data) { + var ref = new Ref(data.ref.num, data.ref.gen); + var catalog = pdfManager.pdfDocument.catalog; + return catalog.getPageIndex(ref); + }); + + handler.on('GetDestinations', + function wphSetupGetDestinations(data) { + return pdfManager.ensureCatalog('destinations'); + } + ); + + handler.on('GetDestination', + function wphSetupGetDestination(data) { + return pdfManager.ensureCatalog('getDestination', [ data.id ]); + } + ); + + handler.on('GetAttachments', + function wphSetupGetAttachments(data) { + return pdfManager.ensureCatalog('attachments'); + } + ); + + handler.on('GetJavaScript', + function wphSetupGetJavaScript(data) { + return pdfManager.ensureCatalog('javaScript'); + } + ); + + handler.on('GetOutline', + function wphSetupGetOutline(data) { + return pdfManager.ensureCatalog('documentOutline'); + } + ); + + handler.on('GetMetadata', + function wphSetupGetMetadata(data) { + return Promise.all([pdfManager.ensureDoc('documentInfo'), + pdfManager.ensureCatalog('metadata')]); + } + ); + + handler.on('GetData', function wphSetupGetData(data) { + pdfManager.requestLoadedStream(); + return pdfManager.onLoadedStream().then(function(stream) { + return stream.bytes; + }); + }); + + handler.on('GetStats', + function wphSetupGetStats(data) { + return pdfManager.pdfDocument.xref.stats; + } + ); + + handler.on('UpdatePassword', function wphSetupUpdatePassword(data) { + pdfManager.updatePassword(data); + }); + + handler.on('GetAnnotations', function wphSetupGetAnnotations(data) { + return pdfManager.getPage(data.pageIndex).then(function(page) { + return pdfManager.ensure(page, 'getAnnotationsData', []); + }); + }); + + handler.on('RenderPageRequest', function wphSetupRenderPage(data) { + pdfManager.getPage(data.pageIndex).then(function(page) { + + var pageNum = data.pageIndex + 1; + var start = Date.now(); + // Pre compile the pdf page and fetch the fonts/images. + page.getOperatorList(handler, data.intent).then(function(operatorList) { + + info('page=' + pageNum + ' - getOperatorList: time=' + + (Date.now() - start) + 'ms, len=' + operatorList.fnArray.length); + + }, function(e) { + + var minimumStackMessage = + 'worker.js: while trying to getPage() and getOperatorList()'; + + var wrappedException; + + // Turn the error into an obj that can be serialized + if (typeof e === 'string') { + wrappedException = { + message: e, + stack: minimumStackMessage + }; + } else if (typeof e === 'object') { + wrappedException = { + message: e.message || e.toString(), + stack: e.stack || minimumStackMessage + }; + } else { + wrappedException = { + message: 'Unknown exception type: ' + (typeof e), + stack: minimumStackMessage + }; + } + + handler.send('PageError', { + pageNum: pageNum, + error: wrappedException, + intent: data.intent + }); + }); + }); + }, this); + + handler.on('GetTextContent', function wphExtractText(data) { + return pdfManager.getPage(data.pageIndex).then(function(page) { + var pageNum = data.pageIndex + 1; + var start = Date.now(); + return page.extractTextContent().then(function(textContent) { + info('text indexing: page=' + pageNum + ' - time=' + + (Date.now() - start) + 'ms'); + return textContent; + }); + }); + }); + + handler.on('Cleanup', function wphCleanup(data) { + return pdfManager.cleanup(); + }); + + handler.on('Terminate', function wphTerminate(data) { + pdfManager.terminate(); + }); + } +}; + +var consoleTimer = {}; + +var workerConsole = { + log: function log() { + var args = Array.prototype.slice.call(arguments); + globalScope.postMessage({ + action: 'console_log', + data: args + }); + }, + + error: function error() { + var args = Array.prototype.slice.call(arguments); + globalScope.postMessage({ + action: 'console_error', + data: args + }); + throw 'pdf.js execution error'; + }, + + time: function time(name) { + consoleTimer[name] = Date.now(); + }, + + timeEnd: function timeEnd(name) { + var time = consoleTimer[name]; + if (!time) { + error('Unknown timer name ' + name); + } + this.log('Timer:', name, Date.now() - time); + } +}; + + +// Worker thread? +if (typeof window === 'undefined') { + if (!('console' in globalScope)) { + globalScope.console = workerConsole; + } + + // Listen for unsupported features so we can pass them on to the main thread. + PDFJS.UnsupportedManager.listen(function (msg) { + globalScope.postMessage({ + action: '_unsupported_feature', + data: msg + }); + }); + + var handler = new MessageHandler('worker_processor', this); + WorkerMessageHandler.setup(handler); +} + + +/* This class implements the QM Coder decoding as defined in + * JPEG 2000 Part I Final Committee Draft Version 1.0 + * Annex C.3 Arithmetic decoding procedure + * available at http://www.jpeg.org/public/fcd15444-1.pdf + * + * The arithmetic decoder is used in conjunction with context models to decode + * JPEG2000 and JBIG2 streams. + */ +var ArithmeticDecoder = (function ArithmeticDecoderClosure() { + // Table C-2 + var QeTable = [ + {qe: 0x5601, nmps: 1, nlps: 1, switchFlag: 1}, + {qe: 0x3401, nmps: 2, nlps: 6, switchFlag: 0}, + {qe: 0x1801, nmps: 3, nlps: 9, switchFlag: 0}, + {qe: 0x0AC1, nmps: 4, nlps: 12, switchFlag: 0}, + {qe: 0x0521, nmps: 5, nlps: 29, switchFlag: 0}, + {qe: 0x0221, nmps: 38, nlps: 33, switchFlag: 0}, + {qe: 0x5601, nmps: 7, nlps: 6, switchFlag: 1}, + {qe: 0x5401, nmps: 8, nlps: 14, switchFlag: 0}, + {qe: 0x4801, nmps: 9, nlps: 14, switchFlag: 0}, + {qe: 0x3801, nmps: 10, nlps: 14, switchFlag: 0}, + {qe: 0x3001, nmps: 11, nlps: 17, switchFlag: 0}, + {qe: 0x2401, nmps: 12, nlps: 18, switchFlag: 0}, + {qe: 0x1C01, nmps: 13, nlps: 20, switchFlag: 0}, + {qe: 0x1601, nmps: 29, nlps: 21, switchFlag: 0}, + {qe: 0x5601, nmps: 15, nlps: 14, switchFlag: 1}, + {qe: 0x5401, nmps: 16, nlps: 14, switchFlag: 0}, + {qe: 0x5101, nmps: 17, nlps: 15, switchFlag: 0}, + {qe: 0x4801, nmps: 18, nlps: 16, switchFlag: 0}, + {qe: 0x3801, nmps: 19, nlps: 17, switchFlag: 0}, + {qe: 0x3401, nmps: 20, nlps: 18, switchFlag: 0}, + {qe: 0x3001, nmps: 21, nlps: 19, switchFlag: 0}, + {qe: 0x2801, nmps: 22, nlps: 19, switchFlag: 0}, + {qe: 0x2401, nmps: 23, nlps: 20, switchFlag: 0}, + {qe: 0x2201, nmps: 24, nlps: 21, switchFlag: 0}, + {qe: 0x1C01, nmps: 25, nlps: 22, switchFlag: 0}, + {qe: 0x1801, nmps: 26, nlps: 23, switchFlag: 0}, + {qe: 0x1601, nmps: 27, nlps: 24, switchFlag: 0}, + {qe: 0x1401, nmps: 28, nlps: 25, switchFlag: 0}, + {qe: 0x1201, nmps: 29, nlps: 26, switchFlag: 0}, + {qe: 0x1101, nmps: 30, nlps: 27, switchFlag: 0}, + {qe: 0x0AC1, nmps: 31, nlps: 28, switchFlag: 0}, + {qe: 0x09C1, nmps: 32, nlps: 29, switchFlag: 0}, + {qe: 0x08A1, nmps: 33, nlps: 30, switchFlag: 0}, + {qe: 0x0521, nmps: 34, nlps: 31, switchFlag: 0}, + {qe: 0x0441, nmps: 35, nlps: 32, switchFlag: 0}, + {qe: 0x02A1, nmps: 36, nlps: 33, switchFlag: 0}, + {qe: 0x0221, nmps: 37, nlps: 34, switchFlag: 0}, + {qe: 0x0141, nmps: 38, nlps: 35, switchFlag: 0}, + {qe: 0x0111, nmps: 39, nlps: 36, switchFlag: 0}, + {qe: 0x0085, nmps: 40, nlps: 37, switchFlag: 0}, + {qe: 0x0049, nmps: 41, nlps: 38, switchFlag: 0}, + {qe: 0x0025, nmps: 42, nlps: 39, switchFlag: 0}, + {qe: 0x0015, nmps: 43, nlps: 40, switchFlag: 0}, + {qe: 0x0009, nmps: 44, nlps: 41, switchFlag: 0}, + {qe: 0x0005, nmps: 45, nlps: 42, switchFlag: 0}, + {qe: 0x0001, nmps: 45, nlps: 43, switchFlag: 0}, + {qe: 0x5601, nmps: 46, nlps: 46, switchFlag: 0} + ]; + + // C.3.5 Initialisation of the decoder (INITDEC) + function ArithmeticDecoder(data, start, end) { + this.data = data; + this.bp = start; + this.dataEnd = end; + + this.chigh = data[start]; + this.clow = 0; + + this.byteIn(); + + this.chigh = ((this.chigh << 7) & 0xFFFF) | ((this.clow >> 9) & 0x7F); + this.clow = (this.clow << 7) & 0xFFFF; + this.ct -= 7; + this.a = 0x8000; + } + + ArithmeticDecoder.prototype = { + // C.3.4 Compressed data input (BYTEIN) + byteIn: function ArithmeticDecoder_byteIn() { + var data = this.data; + var bp = this.bp; + if (data[bp] === 0xFF) { + var b1 = data[bp + 1]; + if (b1 > 0x8F) { + this.clow += 0xFF00; + this.ct = 8; + } else { + bp++; + this.clow += (data[bp] << 9); + this.ct = 7; + this.bp = bp; + } + } else { + bp++; + this.clow += bp < this.dataEnd ? (data[bp] << 8) : 0xFF00; + this.ct = 8; + this.bp = bp; + } + if (this.clow > 0xFFFF) { + this.chigh += (this.clow >> 16); + this.clow &= 0xFFFF; + } + }, + // C.3.2 Decoding a decision (DECODE) + readBit: function ArithmeticDecoder_readBit(contexts, pos) { + // contexts are packed into 1 byte: + // highest 7 bits carry cx.index, lowest bit carries cx.mps + var cx_index = contexts[pos] >> 1, cx_mps = contexts[pos] & 1; + var qeTableIcx = QeTable[cx_index]; + var qeIcx = qeTableIcx.qe; + var d; + var a = this.a - qeIcx; + + if (this.chigh < qeIcx) { + // exchangeLps + if (a < qeIcx) { + a = qeIcx; + d = cx_mps; + cx_index = qeTableIcx.nmps; + } else { + a = qeIcx; + d = 1 ^ cx_mps; + if (qeTableIcx.switchFlag === 1) { + cx_mps = d; + } + cx_index = qeTableIcx.nlps; + } + } else { + this.chigh -= qeIcx; + if ((a & 0x8000) !== 0) { + this.a = a; + return cx_mps; + } + // exchangeMps + if (a < qeIcx) { + d = 1 ^ cx_mps; + if (qeTableIcx.switchFlag === 1) { + cx_mps = d; + } + cx_index = qeTableIcx.nlps; + } else { + d = cx_mps; + cx_index = qeTableIcx.nmps; + } + } + // C.3.3 renormD; + do { + if (this.ct === 0) { + this.byteIn(); + } + + a <<= 1; + this.chigh = ((this.chigh << 1) & 0xFFFF) | ((this.clow >> 15) & 1); + this.clow = (this.clow << 1) & 0xFFFF; + this.ct--; + } while ((a & 0x8000) === 0); + this.a = a; + + contexts[pos] = cx_index << 1 | cx_mps; + return d; + } + }; + + return ArithmeticDecoder; +})(); + + +var JpegImage = (function jpegImage() { + var dctZigZag = new Uint8Array([ + 0, + 1, 8, + 16, 9, 2, + 3, 10, 17, 24, + 32, 25, 18, 11, 4, + 5, 12, 19, 26, 33, 40, + 48, 41, 34, 27, 20, 13, 6, + 7, 14, 21, 28, 35, 42, 49, 56, + 57, 50, 43, 36, 29, 22, 15, + 23, 30, 37, 44, 51, 58, + 59, 52, 45, 38, 31, + 39, 46, 53, 60, + 61, 54, 47, + 55, 62, + 63 + ]); + + var dctCos1 = 4017; // cos(pi/16) + var dctSin1 = 799; // sin(pi/16) + var dctCos3 = 3406; // cos(3*pi/16) + var dctSin3 = 2276; // sin(3*pi/16) + var dctCos6 = 1567; // cos(6*pi/16) + var dctSin6 = 3784; // sin(6*pi/16) + var dctSqrt2 = 5793; // sqrt(2) + var dctSqrt1d2 = 2896; // sqrt(2) / 2 + + function constructor() { + } + + function buildHuffmanTable(codeLengths, values) { + var k = 0, code = [], i, j, length = 16; + while (length > 0 && !codeLengths[length - 1]) { + length--; + } + code.push({children: [], index: 0}); + var p = code[0], q; + for (i = 0; i < length; i++) { + for (j = 0; j < codeLengths[i]; j++) { + p = code.pop(); + p.children[p.index] = values[k]; + while (p.index > 0) { + p = code.pop(); + } + p.index++; + code.push(p); + while (code.length <= i) { + code.push(q = {children: [], index: 0}); + p.children[p.index] = q.children; + p = q; + } + k++; + } + if (i + 1 < length) { + // p here points to last code + code.push(q = {children: [], index: 0}); + p.children[p.index] = q.children; + p = q; + } + } + return code[0].children; + } + + function getBlockBufferOffset(component, row, col) { + return 64 * ((component.blocksPerLine + 1) * row + col); + } + + function decodeScan(data, offset, frame, components, resetInterval, + spectralStart, spectralEnd, successivePrev, successive) { + var precision = frame.precision; + var samplesPerLine = frame.samplesPerLine; + var scanLines = frame.scanLines; + var mcusPerLine = frame.mcusPerLine; + var progressive = frame.progressive; + var maxH = frame.maxH, maxV = frame.maxV; + + var startOffset = offset, bitsData = 0, bitsCount = 0; + + function readBit() { + if (bitsCount > 0) { + bitsCount--; + return (bitsData >> bitsCount) & 1; + } + bitsData = data[offset++]; + if (bitsData === 0xFF) { + var nextByte = data[offset++]; + if (nextByte) { + throw 'unexpected marker: ' + + ((bitsData << 8) | nextByte).toString(16); + } + // unstuff 0 + } + bitsCount = 7; + return bitsData >>> 7; + } + + function decodeHuffman(tree) { + var node = tree; + while (true) { + node = node[readBit()]; + if (typeof node === 'number') { + return node; + } + if (typeof node !== 'object') { + throw 'invalid huffman sequence'; + } + } + } + + function receive(length) { + var n = 0; + while (length > 0) { + n = (n << 1) | readBit(); + length--; + } + return n; + } + + function receiveAndExtend(length) { + if (length === 1) { + return readBit() === 1 ? 1 : -1; + } + var n = receive(length); + if (n >= 1 << (length - 1)) { + return n; + } + return n + (-1 << length) + 1; + } + + function decodeBaseline(component, offset) { + var t = decodeHuffman(component.huffmanTableDC); + var diff = t === 0 ? 0 : receiveAndExtend(t); + component.blockData[offset] = (component.pred += diff); + var k = 1; + while (k < 64) { + var rs = decodeHuffman(component.huffmanTableAC); + var s = rs & 15, r = rs >> 4; + if (s === 0) { + if (r < 15) { + break; + } + k += 16; + continue; + } + k += r; + var z = dctZigZag[k]; + component.blockData[offset + z] = receiveAndExtend(s); + k++; + } + } + + function decodeDCFirst(component, offset) { + var t = decodeHuffman(component.huffmanTableDC); + var diff = t === 0 ? 0 : (receiveAndExtend(t) << successive); + component.blockData[offset] = (component.pred += diff); + } + + function decodeDCSuccessive(component, offset) { + component.blockData[offset] |= readBit() << successive; + } + + var eobrun = 0; + function decodeACFirst(component, offset) { + if (eobrun > 0) { + eobrun--; + return; + } + var k = spectralStart, e = spectralEnd; + while (k <= e) { + var rs = decodeHuffman(component.huffmanTableAC); + var s = rs & 15, r = rs >> 4; + if (s === 0) { + if (r < 15) { + eobrun = receive(r) + (1 << r) - 1; + break; + } + k += 16; + continue; + } + k += r; + var z = dctZigZag[k]; + component.blockData[offset + z] = + receiveAndExtend(s) * (1 << successive); + k++; + } + } + + var successiveACState = 0, successiveACNextValue; + function decodeACSuccessive(component, offset) { + var k = spectralStart; + var e = spectralEnd; + var r = 0; + var s; + var rs; + while (k <= e) { + var z = dctZigZag[k]; + switch (successiveACState) { + case 0: // initial state + rs = decodeHuffman(component.huffmanTableAC); + s = rs & 15; + r = rs >> 4; + if (s === 0) { + if (r < 15) { + eobrun = receive(r) + (1 << r); + successiveACState = 4; + } else { + r = 16; + successiveACState = 1; + } + } else { + if (s !== 1) { + throw 'invalid ACn encoding'; + } + successiveACNextValue = receiveAndExtend(s); + successiveACState = r ? 2 : 3; + } + continue; + case 1: // skipping r zero items + case 2: + if (component.blockData[offset + z]) { + component.blockData[offset + z] += (readBit() << successive); + } else { + r--; + if (r === 0) { + successiveACState = successiveACState === 2 ? 3 : 0; + } + } + break; + case 3: // set value for a zero item + if (component.blockData[offset + z]) { + component.blockData[offset + z] += (readBit() << successive); + } else { + component.blockData[offset + z] = + successiveACNextValue << successive; + successiveACState = 0; + } + break; + case 4: // eob + if (component.blockData[offset + z]) { + component.blockData[offset + z] += (readBit() << successive); + } + break; + } + k++; + } + if (successiveACState === 4) { + eobrun--; + if (eobrun === 0) { + successiveACState = 0; + } + } + } + + function decodeMcu(component, decode, mcu, row, col) { + var mcuRow = (mcu / mcusPerLine) | 0; + var mcuCol = mcu % mcusPerLine; + var blockRow = mcuRow * component.v + row; + var blockCol = mcuCol * component.h + col; + var offset = getBlockBufferOffset(component, blockRow, blockCol); + decode(component, offset); + } + + function decodeBlock(component, decode, mcu) { + var blockRow = (mcu / component.blocksPerLine) | 0; + var blockCol = mcu % component.blocksPerLine; + var offset = getBlockBufferOffset(component, blockRow, blockCol); + decode(component, offset); + } + + var componentsLength = components.length; + var component, i, j, k, n; + var decodeFn; + if (progressive) { + if (spectralStart === 0) { + decodeFn = successivePrev === 0 ? decodeDCFirst : decodeDCSuccessive; + } else { + decodeFn = successivePrev === 0 ? decodeACFirst : decodeACSuccessive; + } + } else { + decodeFn = decodeBaseline; + } + + var mcu = 0, marker; + var mcuExpected; + if (componentsLength === 1) { + mcuExpected = components[0].blocksPerLine * components[0].blocksPerColumn; + } else { + mcuExpected = mcusPerLine * frame.mcusPerColumn; + } + if (!resetInterval) { + resetInterval = mcuExpected; + } + + var h, v; + while (mcu < mcuExpected) { + // reset interval stuff + for (i = 0; i < componentsLength; i++) { + components[i].pred = 0; + } + eobrun = 0; + + if (componentsLength === 1) { + component = components[0]; + for (n = 0; n < resetInterval; n++) { + decodeBlock(component, decodeFn, mcu); + mcu++; + } + } else { + for (n = 0; n < resetInterval; n++) { + for (i = 0; i < componentsLength; i++) { + component = components[i]; + h = component.h; + v = component.v; + for (j = 0; j < v; j++) { + for (k = 0; k < h; k++) { + decodeMcu(component, decodeFn, mcu, j, k); + } + } + } + mcu++; + } + } + + // find marker + bitsCount = 0; + marker = (data[offset] << 8) | data[offset + 1]; + if (marker <= 0xFF00) { + throw 'marker was not found'; + } + + if (marker >= 0xFFD0 && marker <= 0xFFD7) { // RSTx + offset += 2; + } else { + break; + } + } + + return offset - startOffset; + } + + // A port of poppler's IDCT method which in turn is taken from: + // Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz, + // 'Practical Fast 1-D DCT Algorithms with 11 Multiplications', + // IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989, + // 988-991. + function quantizeAndInverse(component, blockBufferOffset, p) { + var qt = component.quantizationTable, blockData = component.blockData; + var v0, v1, v2, v3, v4, v5, v6, v7; + var p0, p1, p2, p3, p4, p5, p6, p7; + var t; + + // inverse DCT on rows + for (var row = 0; row < 64; row += 8) { + // gather block data + p0 = blockData[blockBufferOffset + row]; + p1 = blockData[blockBufferOffset + row + 1]; + p2 = blockData[blockBufferOffset + row + 2]; + p3 = blockData[blockBufferOffset + row + 3]; + p4 = blockData[blockBufferOffset + row + 4]; + p5 = blockData[blockBufferOffset + row + 5]; + p6 = blockData[blockBufferOffset + row + 6]; + p7 = blockData[blockBufferOffset + row + 7]; + + // dequant p0 + p0 *= qt[row]; + + // check for all-zero AC coefficients + if ((p1 | p2 | p3 | p4 | p5 | p6 | p7) === 0) { + t = (dctSqrt2 * p0 + 512) >> 10; + p[row] = t; + p[row + 1] = t; + p[row + 2] = t; + p[row + 3] = t; + p[row + 4] = t; + p[row + 5] = t; + p[row + 6] = t; + p[row + 7] = t; + continue; + } + // dequant p1 ... p7 + p1 *= qt[row + 1]; + p2 *= qt[row + 2]; + p3 *= qt[row + 3]; + p4 *= qt[row + 4]; + p5 *= qt[row + 5]; + p6 *= qt[row + 6]; + p7 *= qt[row + 7]; + + // stage 4 + v0 = (dctSqrt2 * p0 + 128) >> 8; + v1 = (dctSqrt2 * p4 + 128) >> 8; + v2 = p2; + v3 = p6; + v4 = (dctSqrt1d2 * (p1 - p7) + 128) >> 8; + v7 = (dctSqrt1d2 * (p1 + p7) + 128) >> 8; + v5 = p3 << 4; + v6 = p5 << 4; + + // stage 3 + v0 = (v0 + v1 + 1) >> 1; + v1 = v0 - v1; + t = (v2 * dctSin6 + v3 * dctCos6 + 128) >> 8; + v2 = (v2 * dctCos6 - v3 * dctSin6 + 128) >> 8; + v3 = t; + v4 = (v4 + v6 + 1) >> 1; + v6 = v4 - v6; + v7 = (v7 + v5 + 1) >> 1; + v5 = v7 - v5; + + // stage 2 + v0 = (v0 + v3 + 1) >> 1; + v3 = v0 - v3; + v1 = (v1 + v2 + 1) >> 1; + v2 = v1 - v2; + t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12; + v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12; + v7 = t; + t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12; + v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12; + v6 = t; + + // stage 1 + p[row] = v0 + v7; + p[row + 7] = v0 - v7; + p[row + 1] = v1 + v6; + p[row + 6] = v1 - v6; + p[row + 2] = v2 + v5; + p[row + 5] = v2 - v5; + p[row + 3] = v3 + v4; + p[row + 4] = v3 - v4; + } + + // inverse DCT on columns + for (var col = 0; col < 8; ++col) { + p0 = p[col]; + p1 = p[col + 8]; + p2 = p[col + 16]; + p3 = p[col + 24]; + p4 = p[col + 32]; + p5 = p[col + 40]; + p6 = p[col + 48]; + p7 = p[col + 56]; + + // check for all-zero AC coefficients + if ((p1 | p2 | p3 | p4 | p5 | p6 | p7) === 0) { + t = (dctSqrt2 * p0 + 8192) >> 14; + // convert to 8 bit + t = (t < -2040) ? 0 : (t >= 2024) ? 255 : (t + 2056) >> 4; + blockData[blockBufferOffset + col] = t; + blockData[blockBufferOffset + col + 8] = t; + blockData[blockBufferOffset + col + 16] = t; + blockData[blockBufferOffset + col + 24] = t; + blockData[blockBufferOffset + col + 32] = t; + blockData[blockBufferOffset + col + 40] = t; + blockData[blockBufferOffset + col + 48] = t; + blockData[blockBufferOffset + col + 56] = t; + continue; + } + + // stage 4 + v0 = (dctSqrt2 * p0 + 2048) >> 12; + v1 = (dctSqrt2 * p4 + 2048) >> 12; + v2 = p2; + v3 = p6; + v4 = (dctSqrt1d2 * (p1 - p7) + 2048) >> 12; + v7 = (dctSqrt1d2 * (p1 + p7) + 2048) >> 12; + v5 = p3; + v6 = p5; + + // stage 3 + // Shift v0 by 128.5 << 5 here, so we don't need to shift p0...p7 when + // converting to UInt8 range later. + v0 = ((v0 + v1 + 1) >> 1) + 4112; + v1 = v0 - v1; + t = (v2 * dctSin6 + v3 * dctCos6 + 2048) >> 12; + v2 = (v2 * dctCos6 - v3 * dctSin6 + 2048) >> 12; + v3 = t; + v4 = (v4 + v6 + 1) >> 1; + v6 = v4 - v6; + v7 = (v7 + v5 + 1) >> 1; + v5 = v7 - v5; + + // stage 2 + v0 = (v0 + v3 + 1) >> 1; + v3 = v0 - v3; + v1 = (v1 + v2 + 1) >> 1; + v2 = v1 - v2; + t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12; + v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12; + v7 = t; + t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12; + v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12; + v6 = t; + + // stage 1 + p0 = v0 + v7; + p7 = v0 - v7; + p1 = v1 + v6; + p6 = v1 - v6; + p2 = v2 + v5; + p5 = v2 - v5; + p3 = v3 + v4; + p4 = v3 - v4; + + // convert to 8-bit integers + p0 = (p0 < 16) ? 0 : (p0 >= 4080) ? 255 : p0 >> 4; + p1 = (p1 < 16) ? 0 : (p1 >= 4080) ? 255 : p1 >> 4; + p2 = (p2 < 16) ? 0 : (p2 >= 4080) ? 255 : p2 >> 4; + p3 = (p3 < 16) ? 0 : (p3 >= 4080) ? 255 : p3 >> 4; + p4 = (p4 < 16) ? 0 : (p4 >= 4080) ? 255 : p4 >> 4; + p5 = (p5 < 16) ? 0 : (p5 >= 4080) ? 255 : p5 >> 4; + p6 = (p6 < 16) ? 0 : (p6 >= 4080) ? 255 : p6 >> 4; + p7 = (p7 < 16) ? 0 : (p7 >= 4080) ? 255 : p7 >> 4; + + // store block data + blockData[blockBufferOffset + col] = p0; + blockData[blockBufferOffset + col + 8] = p1; + blockData[blockBufferOffset + col + 16] = p2; + blockData[blockBufferOffset + col + 24] = p3; + blockData[blockBufferOffset + col + 32] = p4; + blockData[blockBufferOffset + col + 40] = p5; + blockData[blockBufferOffset + col + 48] = p6; + blockData[blockBufferOffset + col + 56] = p7; + } + } + + function buildComponentData(frame, component) { + var blocksPerLine = component.blocksPerLine; + var blocksPerColumn = component.blocksPerColumn; + var computationBuffer = new Int16Array(64); + + for (var blockRow = 0; blockRow < blocksPerColumn; blockRow++) { + for (var blockCol = 0; blockCol < blocksPerLine; blockCol++) { + var offset = getBlockBufferOffset(component, blockRow, blockCol); + quantizeAndInverse(component, offset, computationBuffer); + } + } + return component.blockData; + } + + function clamp0to255(a) { + return a <= 0 ? 0 : a >= 255 ? 255 : a; + } + + constructor.prototype = { + parse: function parse(data) { + + function readUint16() { + var value = (data[offset] << 8) | data[offset + 1]; + offset += 2; + return value; + } + + function readDataBlock() { + var length = readUint16(); + var array = data.subarray(offset, offset + length - 2); + offset += array.length; + return array; + } + + function prepareComponents(frame) { + var mcusPerLine = Math.ceil(frame.samplesPerLine / 8 / frame.maxH); + var mcusPerColumn = Math.ceil(frame.scanLines / 8 / frame.maxV); + for (var i = 0; i < frame.components.length; i++) { + component = frame.components[i]; + var blocksPerLine = Math.ceil(Math.ceil(frame.samplesPerLine / 8) * + component.h / frame.maxH); + var blocksPerColumn = Math.ceil(Math.ceil(frame.scanLines / 8) * + component.v / frame.maxV); + var blocksPerLineForMcu = mcusPerLine * component.h; + var blocksPerColumnForMcu = mcusPerColumn * component.v; + + var blocksBufferSize = 64 * blocksPerColumnForMcu * + (blocksPerLineForMcu + 1); + component.blockData = new Int16Array(blocksBufferSize); + component.blocksPerLine = blocksPerLine; + component.blocksPerColumn = blocksPerColumn; + } + frame.mcusPerLine = mcusPerLine; + frame.mcusPerColumn = mcusPerColumn; + } + + var offset = 0, length = data.length; + var jfif = null; + var adobe = null; + var pixels = null; + var frame, resetInterval; + var quantizationTables = []; + var huffmanTablesAC = [], huffmanTablesDC = []; + var fileMarker = readUint16(); + if (fileMarker !== 0xFFD8) { // SOI (Start of Image) + throw 'SOI not found'; + } + + fileMarker = readUint16(); + while (fileMarker !== 0xFFD9) { // EOI (End of image) + var i, j, l; + switch(fileMarker) { + case 0xFFE0: // APP0 (Application Specific) + case 0xFFE1: // APP1 + case 0xFFE2: // APP2 + case 0xFFE3: // APP3 + case 0xFFE4: // APP4 + case 0xFFE5: // APP5 + case 0xFFE6: // APP6 + case 0xFFE7: // APP7 + case 0xFFE8: // APP8 + case 0xFFE9: // APP9 + case 0xFFEA: // APP10 + case 0xFFEB: // APP11 + case 0xFFEC: // APP12 + case 0xFFED: // APP13 + case 0xFFEE: // APP14 + case 0xFFEF: // APP15 + case 0xFFFE: // COM (Comment) + var appData = readDataBlock(); + + if (fileMarker === 0xFFE0) { + if (appData[0] === 0x4A && appData[1] === 0x46 && + appData[2] === 0x49 && appData[3] === 0x46 && + appData[4] === 0) { // 'JFIF\x00' + jfif = { + version: { major: appData[5], minor: appData[6] }, + densityUnits: appData[7], + xDensity: (appData[8] << 8) | appData[9], + yDensity: (appData[10] << 8) | appData[11], + thumbWidth: appData[12], + thumbHeight: appData[13], + thumbData: appData.subarray(14, 14 + + 3 * appData[12] * appData[13]) + }; + } + } + // TODO APP1 - Exif + if (fileMarker === 0xFFEE) { + if (appData[0] === 0x41 && appData[1] === 0x64 && + appData[2] === 0x6F && appData[3] === 0x62 && + appData[4] === 0x65) { // 'Adobe' + adobe = { + version: (appData[5] << 8) | appData[6], + flags0: (appData[7] << 8) | appData[8], + flags1: (appData[9] << 8) | appData[10], + transformCode: appData[11] + }; + } + } + break; + + case 0xFFDB: // DQT (Define Quantization Tables) + var quantizationTablesLength = readUint16(); + var quantizationTablesEnd = quantizationTablesLength + offset - 2; + var z; + while (offset < quantizationTablesEnd) { + var quantizationTableSpec = data[offset++]; + var tableData = new Uint16Array(64); + if ((quantizationTableSpec >> 4) === 0) { // 8 bit values + for (j = 0; j < 64; j++) { + z = dctZigZag[j]; + tableData[z] = data[offset++]; + } + } else if ((quantizationTableSpec >> 4) === 1) { //16 bit + for (j = 0; j < 64; j++) { + z = dctZigZag[j]; + tableData[z] = readUint16(); + } + } else { + throw 'DQT: invalid table spec'; + } + quantizationTables[quantizationTableSpec & 15] = tableData; + } + break; + + case 0xFFC0: // SOF0 (Start of Frame, Baseline DCT) + case 0xFFC1: // SOF1 (Start of Frame, Extended DCT) + case 0xFFC2: // SOF2 (Start of Frame, Progressive DCT) + if (frame) { + throw 'Only single frame JPEGs supported'; + } + readUint16(); // skip data length + frame = {}; + frame.extended = (fileMarker === 0xFFC1); + frame.progressive = (fileMarker === 0xFFC2); + frame.precision = data[offset++]; + frame.scanLines = readUint16(); + frame.samplesPerLine = readUint16(); + frame.components = []; + frame.componentIds = {}; + var componentsCount = data[offset++], componentId; + var maxH = 0, maxV = 0; + for (i = 0; i < componentsCount; i++) { + componentId = data[offset]; + var h = data[offset + 1] >> 4; + var v = data[offset + 1] & 15; + if (maxH < h) { + maxH = h; + } + if (maxV < v) { + maxV = v; + } + var qId = data[offset + 2]; + l = frame.components.push({ + h: h, + v: v, + quantizationTable: quantizationTables[qId] + }); + frame.componentIds[componentId] = l - 1; + offset += 3; + } + frame.maxH = maxH; + frame.maxV = maxV; + prepareComponents(frame); + break; + + case 0xFFC4: // DHT (Define Huffman Tables) + var huffmanLength = readUint16(); + for (i = 2; i < huffmanLength;) { + var huffmanTableSpec = data[offset++]; + var codeLengths = new Uint8Array(16); + var codeLengthSum = 0; + for (j = 0; j < 16; j++, offset++) { + codeLengthSum += (codeLengths[j] = data[offset]); + } + var huffmanValues = new Uint8Array(codeLengthSum); + for (j = 0; j < codeLengthSum; j++, offset++) { + huffmanValues[j] = data[offset]; + } + i += 17 + codeLengthSum; + + ((huffmanTableSpec >> 4) === 0 ? + huffmanTablesDC : huffmanTablesAC)[huffmanTableSpec & 15] = + buildHuffmanTable(codeLengths, huffmanValues); + } + break; + + case 0xFFDD: // DRI (Define Restart Interval) + readUint16(); // skip data length + resetInterval = readUint16(); + break; + + case 0xFFDA: // SOS (Start of Scan) + var scanLength = readUint16(); + var selectorsCount = data[offset++]; + var components = [], component; + for (i = 0; i < selectorsCount; i++) { + var componentIndex = frame.componentIds[data[offset++]]; + component = frame.components[componentIndex]; + var tableSpec = data[offset++]; + component.huffmanTableDC = huffmanTablesDC[tableSpec >> 4]; + component.huffmanTableAC = huffmanTablesAC[tableSpec & 15]; + components.push(component); + } + var spectralStart = data[offset++]; + var spectralEnd = data[offset++]; + var successiveApproximation = data[offset++]; + var processed = decodeScan(data, offset, + frame, components, resetInterval, + spectralStart, spectralEnd, + successiveApproximation >> 4, successiveApproximation & 15); + offset += processed; + break; + + case 0xFFFF: // Fill bytes + if (data[offset] !== 0xFF) { // Avoid skipping a valid marker. + offset--; + } + break; + + default: + if (data[offset - 3] === 0xFF && + data[offset - 2] >= 0xC0 && data[offset - 2] <= 0xFE) { + // could be incorrect encoding -- last 0xFF byte of the previous + // block was eaten by the encoder + offset -= 3; + break; + } + throw 'unknown JPEG marker ' + fileMarker.toString(16); + } + fileMarker = readUint16(); + } + + this.width = frame.samplesPerLine; + this.height = frame.scanLines; + this.jfif = jfif; + this.adobe = adobe; + this.components = []; + for (i = 0; i < frame.components.length; i++) { + component = frame.components[i]; + this.components.push({ + output: buildComponentData(frame, component), + scaleX: component.h / frame.maxH, + scaleY: component.v / frame.maxV, + blocksPerLine: component.blocksPerLine, + blocksPerColumn: component.blocksPerColumn + }); + } + this.numComponents = this.components.length; + }, + + _getLinearizedBlockData: function getLinearizedBlockData(width, height) { + var scaleX = this.width / width, scaleY = this.height / height; + + var component, componentScaleX, componentScaleY, blocksPerScanline; + var x, y, i, j, k; + var index; + var offset = 0; + var output; + var numComponents = this.components.length; + var dataLength = width * height * numComponents; + var data = new Uint8Array(dataLength); + var xScaleBlockOffset = new Uint32Array(width); + var mask3LSB = 0xfffffff8; // used to clear the 3 LSBs + + for (i = 0; i < numComponents; i++) { + component = this.components[i]; + componentScaleX = component.scaleX * scaleX; + componentScaleY = component.scaleY * scaleY; + offset = i; + output = component.output; + blocksPerScanline = (component.blocksPerLine + 1) << 3; + // precalculate the xScaleBlockOffset + for (x = 0; x < width; x++) { + j = 0 | (x * componentScaleX); + xScaleBlockOffset[x] = ((j & mask3LSB) << 3) | (j & 7); + } + // linearize the blocks of the component + for (y = 0; y < height; y++) { + j = 0 | (y * componentScaleY); + index = blocksPerScanline * (j & mask3LSB) | ((j & 7) << 3); + for (x = 0; x < width; x++) { + data[offset] = output[index + xScaleBlockOffset[x]]; + offset += numComponents; + } + } + } + + // decodeTransform contains pairs of multiplier (-256..256) and additive + var transform = this.decodeTransform; + if (transform) { + for (i = 0; i < dataLength;) { + for (j = 0, k = 0; j < numComponents; j++, i++, k += 2) { + data[i] = ((data[i] * transform[k]) >> 8) + transform[k + 1]; + } + } + } + return data; + }, + + _isColorConversionNeeded: function isColorConversionNeeded() { + if (this.adobe && this.adobe.transformCode) { + // The adobe transform marker overrides any previous setting + return true; + } else if (this.numComponents === 3) { + return true; + } else { + return false; + } + }, + + _convertYccToRgb: function convertYccToRgb(data) { + var Y, Cb, Cr; + for (var i = 0, length = data.length; i < length; i += 3) { + Y = data[i ]; + Cb = data[i + 1]; + Cr = data[i + 2]; + data[i ] = clamp0to255(Y - 179.456 + 1.402 * Cr); + data[i + 1] = clamp0to255(Y + 135.459 - 0.344 * Cb - 0.714 * Cr); + data[i + 2] = clamp0to255(Y - 226.816 + 1.772 * Cb); + } + return data; + }, + + _convertYcckToRgb: function convertYcckToRgb(data) { + var Y, Cb, Cr, k; + var offset = 0; + for (var i = 0, length = data.length; i < length; i += 4) { + Y = data[i]; + Cb = data[i + 1]; + Cr = data[i + 2]; + k = data[i + 3]; + + var r = -122.67195406894 + + Cb * (-6.60635669420364e-5 * Cb + 0.000437130475926232 * Cr - + 5.4080610064599e-5 * Y + 0.00048449797120281 * k - + 0.154362151871126) + + Cr * (-0.000957964378445773 * Cr + 0.000817076911346625 * Y - + 0.00477271405408747 * k + 1.53380253221734) + + Y * (0.000961250184130688 * Y - 0.00266257332283933 * k + + 0.48357088451265) + + k * (-0.000336197177618394 * k + 0.484791561490776); + + var g = 107.268039397724 + + Cb * (2.19927104525741e-5 * Cb - 0.000640992018297945 * Cr + + 0.000659397001245577 * Y + 0.000426105652938837 * k - + 0.176491792462875) + + Cr * (-0.000778269941513683 * Cr + 0.00130872261408275 * Y + + 0.000770482631801132 * k - 0.151051492775562) + + Y * (0.00126935368114843 * Y - 0.00265090189010898 * k + + 0.25802910206845) + + k * (-0.000318913117588328 * k - 0.213742400323665); + + var b = -20.810012546947 + + Cb * (-0.000570115196973677 * Cb - 2.63409051004589e-5 * Cr + + 0.0020741088115012 * Y - 0.00288260236853442 * k + + 0.814272968359295) + + Cr * (-1.53496057440975e-5 * Cr - 0.000132689043961446 * Y + + 0.000560833691242812 * k - 0.195152027534049) + + Y * (0.00174418132927582 * Y - 0.00255243321439347 * k + + 0.116935020465145) + + k * (-0.000343531996510555 * k + 0.24165260232407); + + data[offset++] = clamp0to255(r); + data[offset++] = clamp0to255(g); + data[offset++] = clamp0to255(b); + } + return data; + }, + + _convertYcckToCmyk: function convertYcckToCmyk(data) { + var Y, Cb, Cr; + for (var i = 0, length = data.length; i < length; i += 4) { + Y = data[i]; + Cb = data[i + 1]; + Cr = data[i + 2]; + data[i ] = clamp0to255(434.456 - Y - 1.402 * Cr); + data[i + 1] = clamp0to255(119.541 - Y + 0.344 * Cb + 0.714 * Cr); + data[i + 2] = clamp0to255(481.816 - Y - 1.772 * Cb); + // K in data[i + 3] is unchanged + } + return data; + }, + + _convertCmykToRgb: function convertCmykToRgb(data) { + var c, m, y, k; + var offset = 0; + var min = -255 * 255 * 255; + var scale = 1 / 255 / 255; + for (var i = 0, length = data.length; i < length; i += 4) { + c = data[i]; + m = data[i + 1]; + y = data[i + 2]; + k = data[i + 3]; + + var r = + c * (-4.387332384609988 * c + 54.48615194189176 * m + + 18.82290502165302 * y + 212.25662451639585 * k - + 72734.4411664936) + + m * (1.7149763477362134 * m - 5.6096736904047315 * y - + 17.873870861415444 * k - 1401.7366389350734) + + y * (-2.5217340131683033 * y - 21.248923337353073 * k + + 4465.541406466231) - + k * (21.86122147463605 * k + 48317.86113160301); + var g = + c * (8.841041422036149 * c + 60.118027045597366 * m + + 6.871425592049007 * y + 31.159100130055922 * k - + 20220.756542821975) + + m * (-15.310361306967817 * m + 17.575251261109482 * y + + 131.35250912493976 * k - 48691.05921601825) + + y * (4.444339102852739 * y + 9.8632861493405 * k - + 6341.191035517494) - + k * (20.737325471181034 * k + 47890.15695978492); + var b = + c * (0.8842522430003296 * c + 8.078677503112928 * m + + 30.89978309703729 * y - 0.23883238689178934 * k - + 3616.812083916688) + + m * (10.49593273432072 * m + 63.02378494754052 * y + + 50.606957656360734 * k - 28620.90484698408) + + y * (0.03296041114873217 * y + 115.60384449646641 * k - + 49363.43385999684) - + k * (22.33816807309886 * k + 45932.16563550634); + + data[offset++] = r >= 0 ? 255 : r <= min ? 0 : 255 + r * scale | 0; + data[offset++] = g >= 0 ? 255 : g <= min ? 0 : 255 + g * scale | 0; + data[offset++] = b >= 0 ? 255 : b <= min ? 0 : 255 + b * scale | 0; + } + return data; + }, + + getData: function getData(width, height, forceRGBoutput) { + if (this.numComponents > 4) { + throw 'Unsupported color mode'; + } + // type of data: Uint8Array(width * height * numComponents) + var data = this._getLinearizedBlockData(width, height); + + if (this.numComponents === 3) { + return this._convertYccToRgb(data); + } else if (this.numComponents === 4) { + if (this._isColorConversionNeeded()) { + if (forceRGBoutput) { + return this._convertYcckToRgb(data); + } else { + return this._convertYcckToCmyk(data); + } + } else if (forceRGBoutput) { + return this._convertCmykToRgb(data); + } + } + return data; + } + }; + + return constructor; +})(); + + +var JpxImage = (function JpxImageClosure() { + // Table E.1 + var SubbandsGainLog2 = { + 'LL': 0, + 'LH': 1, + 'HL': 1, + 'HH': 2 + }; + function JpxImage() { + this.failOnCorruptedImage = false; + } + JpxImage.prototype = { + parse: function JpxImage_parse(data) { + + var head = readUint16(data, 0); + // No box header, immediate start of codestream (SOC) + if (head === 0xFF4F) { + this.parseCodestream(data, 0, data.length); + return; + } + + var position = 0, length = data.length; + while (position < length) { + var headerSize = 8; + var lbox = readUint32(data, position); + var tbox = readUint32(data, position + 4); + position += headerSize; + if (lbox === 1) { + // XLBox: read UInt64 according to spec. + // JavaScript's int precision of 53 bit should be sufficient here. + lbox = readUint32(data, position) * 4294967296 + + readUint32(data, position + 4); + position += 8; + headerSize += 8; + } + if (lbox === 0) { + lbox = length - position + headerSize; + } + if (lbox < headerSize) { + throw new Error('JPX Error: Invalid box field size'); + } + var dataLength = lbox - headerSize; + var jumpDataLength = true; + switch (tbox) { + case 0x6A703268: // 'jp2h' + jumpDataLength = false; // parsing child boxes + break; + case 0x636F6C72: // 'colr' + // Colorspaces are not used, the CS from the PDF is used. + var method = data[position]; + var precedence = data[position + 1]; + var approximation = data[position + 2]; + if (method === 1) { + // enumerated colorspace + var colorspace = readUint32(data, position + 3); + switch (colorspace) { + case 16: // this indicates a sRGB colorspace + case 17: // this indicates a grayscale colorspace + case 18: // this indicates a YUV colorspace + break; + default: + warn('Unknown colorspace ' + colorspace); + break; + } + } else if (method === 2) { + info('ICC profile not supported'); + } + break; + case 0x6A703263: // 'jp2c' + this.parseCodestream(data, position, position + dataLength); + break; + case 0x6A502020: // 'jP\024\024' + if (0x0d0a870a !== readUint32(data, position)) { + warn('Invalid JP2 signature'); + } + break; + // The following header types are valid but currently not used: + case 0x6A501A1A: // 'jP\032\032' + case 0x66747970: // 'ftyp' + case 0x72726571: // 'rreq' + case 0x72657320: // 'res ' + case 0x69686472: // 'ihdr' + break; + default: + var headerType = String.fromCharCode((tbox >> 24) & 0xFF, + (tbox >> 16) & 0xFF, + (tbox >> 8) & 0xFF, + tbox & 0xFF); + warn('Unsupported header type ' + tbox + ' (' + headerType + ')'); + break; + } + if (jumpDataLength) { + position += dataLength; + } + } + }, + parseImageProperties: function JpxImage_parseImageProperties(stream) { + var newByte = stream.getByte(); + while (newByte >= 0) { + var oldByte = newByte; + newByte = stream.getByte(); + var code = (oldByte << 8) | newByte; + // Image and tile size (SIZ) + if (code === 0xFF51) { + stream.skip(4); + var Xsiz = stream.getInt32() >>> 0; // Byte 4 + var Ysiz = stream.getInt32() >>> 0; // Byte 8 + var XOsiz = stream.getInt32() >>> 0; // Byte 12 + var YOsiz = stream.getInt32() >>> 0; // Byte 16 + stream.skip(16); + var Csiz = stream.getUint16(); // Byte 36 + this.width = Xsiz - XOsiz; + this.height = Ysiz - YOsiz; + this.componentsCount = Csiz; + // Results are always returned as Uint8Arrays + this.bitsPerComponent = 8; + return; + } + } + throw new Error('JPX Error: No size marker found in JPX stream'); + }, + parseCodestream: function JpxImage_parseCodestream(data, start, end) { + var context = {}; + try { + var doNotRecover = false; + var position = start; + while (position + 1 < end) { + var code = readUint16(data, position); + position += 2; + + var length = 0, j, sqcd, spqcds, spqcdSize, scalarExpounded, tile; + switch (code) { + case 0xFF4F: // Start of codestream (SOC) + context.mainHeader = true; + break; + case 0xFFD9: // End of codestream (EOC) + break; + case 0xFF51: // Image and tile size (SIZ) + length = readUint16(data, position); + var siz = {}; + siz.Xsiz = readUint32(data, position + 4); + siz.Ysiz = readUint32(data, position + 8); + siz.XOsiz = readUint32(data, position + 12); + siz.YOsiz = readUint32(data, position + 16); + siz.XTsiz = readUint32(data, position + 20); + siz.YTsiz = readUint32(data, position + 24); + siz.XTOsiz = readUint32(data, position + 28); + siz.YTOsiz = readUint32(data, position + 32); + var componentsCount = readUint16(data, position + 36); + siz.Csiz = componentsCount; + var components = []; + j = position + 38; + for (var i = 0; i < componentsCount; i++) { + var component = { + precision: (data[j] & 0x7F) + 1, + isSigned: !!(data[j] & 0x80), + XRsiz: data[j + 1], + YRsiz: data[j + 1] + }; + calculateComponentDimensions(component, siz); + components.push(component); + } + context.SIZ = siz; + context.components = components; + calculateTileGrids(context, components); + context.QCC = []; + context.COC = []; + break; + case 0xFF5C: // Quantization default (QCD) + length = readUint16(data, position); + var qcd = {}; + j = position + 2; + sqcd = data[j++]; + switch (sqcd & 0x1F) { + case 0: + spqcdSize = 8; + scalarExpounded = true; + break; + case 1: + spqcdSize = 16; + scalarExpounded = false; + break; + case 2: + spqcdSize = 16; + scalarExpounded = true; + break; + default: + throw new Error('JPX Error: Invalid SQcd value ' + sqcd); + } + qcd.noQuantization = (spqcdSize === 8); + qcd.scalarExpounded = scalarExpounded; + qcd.guardBits = sqcd >> 5; + spqcds = []; + while (j < length + position) { + var spqcd = {}; + if (spqcdSize === 8) { + spqcd.epsilon = data[j++] >> 3; + spqcd.mu = 0; + } else { + spqcd.epsilon = data[j] >> 3; + spqcd.mu = ((data[j] & 0x7) << 8) | data[j + 1]; + j += 2; + } + spqcds.push(spqcd); + } + qcd.SPqcds = spqcds; + if (context.mainHeader) { + context.QCD = qcd; + } else { + context.currentTile.QCD = qcd; + context.currentTile.QCC = []; + } + break; + case 0xFF5D: // Quantization component (QCC) + length = readUint16(data, position); + var qcc = {}; + j = position + 2; + var cqcc; + if (context.SIZ.Csiz < 257) { + cqcc = data[j++]; + } else { + cqcc = readUint16(data, j); + j += 2; + } + sqcd = data[j++]; + switch (sqcd & 0x1F) { + case 0: + spqcdSize = 8; + scalarExpounded = true; + break; + case 1: + spqcdSize = 16; + scalarExpounded = false; + break; + case 2: + spqcdSize = 16; + scalarExpounded = true; + break; + default: + throw new Error('JPX Error: Invalid SQcd value ' + sqcd); + } + qcc.noQuantization = (spqcdSize === 8); + qcc.scalarExpounded = scalarExpounded; + qcc.guardBits = sqcd >> 5; + spqcds = []; + while (j < (length + position)) { + spqcd = {}; + if (spqcdSize === 8) { + spqcd.epsilon = data[j++] >> 3; + spqcd.mu = 0; + } else { + spqcd.epsilon = data[j] >> 3; + spqcd.mu = ((data[j] & 0x7) << 8) | data[j + 1]; + j += 2; + } + spqcds.push(spqcd); + } + qcc.SPqcds = spqcds; + if (context.mainHeader) { + context.QCC[cqcc] = qcc; + } else { + context.currentTile.QCC[cqcc] = qcc; + } + break; + case 0xFF52: // Coding style default (COD) + length = readUint16(data, position); + var cod = {}; + j = position + 2; + var scod = data[j++]; + cod.entropyCoderWithCustomPrecincts = !!(scod & 1); + cod.sopMarkerUsed = !!(scod & 2); + cod.ephMarkerUsed = !!(scod & 4); + cod.progressionOrder = data[j++]; + cod.layersCount = readUint16(data, j); + j += 2; + cod.multipleComponentTransform = data[j++]; + + cod.decompositionLevelsCount = data[j++]; + cod.xcb = (data[j++] & 0xF) + 2; + cod.ycb = (data[j++] & 0xF) + 2; + var blockStyle = data[j++]; + cod.selectiveArithmeticCodingBypass = !!(blockStyle & 1); + cod.resetContextProbabilities = !!(blockStyle & 2); + cod.terminationOnEachCodingPass = !!(blockStyle & 4); + cod.verticalyStripe = !!(blockStyle & 8); + cod.predictableTermination = !!(blockStyle & 16); + cod.segmentationSymbolUsed = !!(blockStyle & 32); + cod.reversibleTransformation = data[j++]; + if (cod.entropyCoderWithCustomPrecincts) { + var precinctsSizes = []; + while (j < length + position) { + var precinctsSize = data[j++]; + precinctsSizes.push({ + PPx: precinctsSize & 0xF, + PPy: precinctsSize >> 4 + }); + } + cod.precinctsSizes = precinctsSizes; + } + var unsupported = []; + if (cod.selectiveArithmeticCodingBypass) { + unsupported.push('selectiveArithmeticCodingBypass'); + } + if (cod.resetContextProbabilities) { + unsupported.push('resetContextProbabilities'); + } + if (cod.terminationOnEachCodingPass) { + unsupported.push('terminationOnEachCodingPass'); + } + if (cod.verticalyStripe) { + unsupported.push('verticalyStripe'); + } + if (cod.predictableTermination) { + unsupported.push('predictableTermination'); + } + if (unsupported.length > 0) { + doNotRecover = true; + throw new Error('JPX Error: Unsupported COD options (' + + unsupported.join(', ') + ')'); + } + if (context.mainHeader) { + context.COD = cod; + } else { + context.currentTile.COD = cod; + context.currentTile.COC = []; + } + break; + case 0xFF90: // Start of tile-part (SOT) + length = readUint16(data, position); + tile = {}; + tile.index = readUint16(data, position + 2); + tile.length = readUint32(data, position + 4); + tile.dataEnd = tile.length + position - 2; + tile.partIndex = data[position + 8]; + tile.partsCount = data[position + 9]; + + context.mainHeader = false; + if (tile.partIndex === 0) { + // reset component specific settings + tile.COD = context.COD; + tile.COC = context.COC.slice(0); // clone of the global COC + tile.QCD = context.QCD; + tile.QCC = context.QCC.slice(0); // clone of the global COC + } + context.currentTile = tile; + break; + case 0xFF93: // Start of data (SOD) + tile = context.currentTile; + if (tile.partIndex === 0) { + initializeTile(context, tile.index); + buildPackets(context); + } + + // moving to the end of the data + length = tile.dataEnd - position; + parseTilePackets(context, data, position, length); + break; + case 0xFF55: // Tile-part lengths, main header (TLM) + case 0xFF57: // Packet length, main header (PLM) + case 0xFF58: // Packet length, tile-part header (PLT) + case 0xFF64: // Comment (COM) + length = readUint16(data, position); + // skipping content + break; + case 0xFF53: // Coding style component (COC) + throw new Error('JPX Error: Codestream code 0xFF53 (COC) is ' + + 'not implemented'); + default: + throw new Error('JPX Error: Unknown codestream code: ' + + code.toString(16)); + } + position += length; + } + } catch (e) { + if (doNotRecover || this.failOnCorruptedImage) { + throw e; + } else { + warn('Trying to recover from ' + e.message); + } + } + this.tiles = transformComponents(context); + this.width = context.SIZ.Xsiz - context.SIZ.XOsiz; + this.height = context.SIZ.Ysiz - context.SIZ.YOsiz; + this.componentsCount = context.SIZ.Csiz; + } + }; + function calculateComponentDimensions(component, siz) { + // Section B.2 Component mapping + component.x0 = Math.ceil(siz.XOsiz / component.XRsiz); + component.x1 = Math.ceil(siz.Xsiz / component.XRsiz); + component.y0 = Math.ceil(siz.YOsiz / component.YRsiz); + component.y1 = Math.ceil(siz.Ysiz / component.YRsiz); + component.width = component.x1 - component.x0; + component.height = component.y1 - component.y0; + } + function calculateTileGrids(context, components) { + var siz = context.SIZ; + // Section B.3 Division into tile and tile-components + var tile, tiles = []; + var numXtiles = Math.ceil((siz.Xsiz - siz.XTOsiz) / siz.XTsiz); + var numYtiles = Math.ceil((siz.Ysiz - siz.YTOsiz) / siz.YTsiz); + for (var q = 0; q < numYtiles; q++) { + for (var p = 0; p < numXtiles; p++) { + tile = {}; + tile.tx0 = Math.max(siz.XTOsiz + p * siz.XTsiz, siz.XOsiz); + tile.ty0 = Math.max(siz.YTOsiz + q * siz.YTsiz, siz.YOsiz); + tile.tx1 = Math.min(siz.XTOsiz + (p + 1) * siz.XTsiz, siz.Xsiz); + tile.ty1 = Math.min(siz.YTOsiz + (q + 1) * siz.YTsiz, siz.Ysiz); + tile.width = tile.tx1 - tile.tx0; + tile.height = tile.ty1 - tile.ty0; + tile.components = []; + tiles.push(tile); + } + } + context.tiles = tiles; + + var componentsCount = siz.Csiz; + for (var i = 0, ii = componentsCount; i < ii; i++) { + var component = components[i]; + for (var j = 0, jj = tiles.length; j < jj; j++) { + var tileComponent = {}; + tile = tiles[j]; + tileComponent.tcx0 = Math.ceil(tile.tx0 / component.XRsiz); + tileComponent.tcy0 = Math.ceil(tile.ty0 / component.YRsiz); + tileComponent.tcx1 = Math.ceil(tile.tx1 / component.XRsiz); + tileComponent.tcy1 = Math.ceil(tile.ty1 / component.YRsiz); + tileComponent.width = tileComponent.tcx1 - tileComponent.tcx0; + tileComponent.height = tileComponent.tcy1 - tileComponent.tcy0; + tile.components[i] = tileComponent; + } + } + } + function getBlocksDimensions(context, component, r) { + var codOrCoc = component.codingStyleParameters; + var result = {}; + if (!codOrCoc.entropyCoderWithCustomPrecincts) { + result.PPx = 15; + result.PPy = 15; + } else { + result.PPx = codOrCoc.precinctsSizes[r].PPx; + result.PPy = codOrCoc.precinctsSizes[r].PPy; + } + // calculate codeblock size as described in section B.7 + result.xcb_ = (r > 0 ? Math.min(codOrCoc.xcb, result.PPx - 1) : + Math.min(codOrCoc.xcb, result.PPx)); + result.ycb_ = (r > 0 ? Math.min(codOrCoc.ycb, result.PPy - 1) : + Math.min(codOrCoc.ycb, result.PPy)); + return result; + } + function buildPrecincts(context, resolution, dimensions) { + // Section B.6 Division resolution to precincts + var precinctWidth = 1 << dimensions.PPx; + var precinctHeight = 1 << dimensions.PPy; + // Jasper introduces codeblock groups for mapping each subband codeblocks + // to precincts. Precinct partition divides a resolution according to width + // and height parameters. The subband that belongs to the resolution level + // has a different size than the level, unless it is the zero resolution. + + // From Jasper documentation: jpeg2000.pdf, section K: Tier-2 coding: + // The precinct partitioning for a particular subband is derived from a + // partitioning of its parent LL band (i.e., the LL band at the next higher + // resolution level)... The LL band associated with each resolution level is + // divided into precincts... Each of the resulting precinct regions is then + // mapped into its child subbands (if any) at the next lower resolution + // level. This is accomplished by using the coordinate transformation + // (u, v) = (ceil(x/2), ceil(y/2)) where (x, y) and (u, v) are the + // coordinates of a point in the LL band and child subband, respectively. + var isZeroRes = resolution.resLevel === 0; + var precinctWidthInSubband = 1 << (dimensions.PPx + (isZeroRes ? 0 : -1)); + var precinctHeightInSubband = 1 << (dimensions.PPy + (isZeroRes ? 0 : -1)); + var numprecinctswide = (resolution.trx1 > resolution.trx0 ? + Math.ceil(resolution.trx1 / precinctWidth) - + Math.floor(resolution.trx0 / precinctWidth) : 0); + var numprecinctshigh = (resolution.try1 > resolution.try0 ? + Math.ceil(resolution.try1 / precinctHeight) - + Math.floor(resolution.try0 / precinctHeight) : 0); + var numprecincts = numprecinctswide * numprecinctshigh; + + resolution.precinctParameters = { + precinctWidth: precinctWidth, + precinctHeight: precinctHeight, + numprecinctswide: numprecinctswide, + numprecinctshigh: numprecinctshigh, + numprecincts: numprecincts, + precinctWidthInSubband: precinctWidthInSubband, + precinctHeightInSubband: precinctHeightInSubband + }; + } + function buildCodeblocks(context, subband, dimensions) { + // Section B.7 Division sub-band into code-blocks + var xcb_ = dimensions.xcb_; + var ycb_ = dimensions.ycb_; + var codeblockWidth = 1 << xcb_; + var codeblockHeight = 1 << ycb_; + var cbx0 = subband.tbx0 >> xcb_; + var cby0 = subband.tby0 >> ycb_; + var cbx1 = (subband.tbx1 + codeblockWidth - 1) >> xcb_; + var cby1 = (subband.tby1 + codeblockHeight - 1) >> ycb_; + var precinctParameters = subband.resolution.precinctParameters; + var codeblocks = []; + var precincts = []; + var i, j, codeblock, precinctNumber; + for (j = cby0; j < cby1; j++) { + for (i = cbx0; i < cbx1; i++) { + codeblock = { + cbx: i, + cby: j, + tbx0: codeblockWidth * i, + tby0: codeblockHeight * j, + tbx1: codeblockWidth * (i + 1), + tby1: codeblockHeight * (j + 1) + }; + + codeblock.tbx0_ = Math.max(subband.tbx0, codeblock.tbx0); + codeblock.tby0_ = Math.max(subband.tby0, codeblock.tby0); + codeblock.tbx1_ = Math.min(subband.tbx1, codeblock.tbx1); + codeblock.tby1_ = Math.min(subband.tby1, codeblock.tby1); + + // Calculate precinct number for this codeblock, codeblock position + // should be relative to its subband, use actual dimension and position + // See comment about codeblock group width and height + var pi = Math.floor((codeblock.tbx0_ - subband.tbx0) / + precinctParameters.precinctWidthInSubband); + var pj = Math.floor((codeblock.tby0_ - subband.tby0) / + precinctParameters.precinctHeightInSubband); + precinctNumber = pi + (pj * precinctParameters.numprecinctswide); + + codeblock.precinctNumber = precinctNumber; + codeblock.subbandType = subband.type; + codeblock.Lblock = 3; + + if (codeblock.tbx1_ <= codeblock.tbx0_ || + codeblock.tby1_ <= codeblock.tby0_) { + continue; + } + codeblocks.push(codeblock); + // building precinct for the sub-band + var precinct = precincts[precinctNumber]; + if (precinct !== undefined) { + if (i < precinct.cbxMin) { + precinct.cbxMin = i; + } else if (i > precinct.cbxMax) { + precinct.cbxMax = i; + } + if (j < precinct.cbyMin) { + precinct.cbxMin = j; + } else if (j > precinct.cbyMax) { + precinct.cbyMax = j; + } + } else { + precincts[precinctNumber] = precinct = { + cbxMin: i, + cbyMin: j, + cbxMax: i, + cbyMax: j + }; + } + codeblock.precinct = precinct; + } + } + subband.codeblockParameters = { + codeblockWidth: xcb_, + codeblockHeight: ycb_, + numcodeblockwide: cbx1 - cbx0 + 1, + numcodeblockhigh: cby1 - cby0 + 1 + }; + subband.codeblocks = codeblocks; + subband.precincts = precincts; + } + function createPacket(resolution, precinctNumber, layerNumber) { + var precinctCodeblocks = []; + // Section B.10.8 Order of info in packet + var subbands = resolution.subbands; + // sub-bands already ordered in 'LL', 'HL', 'LH', and 'HH' sequence + for (var i = 0, ii = subbands.length; i < ii; i++) { + var subband = subbands[i]; + var codeblocks = subband.codeblocks; + for (var j = 0, jj = codeblocks.length; j < jj; j++) { + var codeblock = codeblocks[j]; + if (codeblock.precinctNumber !== precinctNumber) { + continue; + } + precinctCodeblocks.push(codeblock); + } + } + return { + layerNumber: layerNumber, + codeblocks: precinctCodeblocks + }; + } + function LayerResolutionComponentPositionIterator(context) { + var siz = context.SIZ; + var tileIndex = context.currentTile.index; + var tile = context.tiles[tileIndex]; + var layersCount = tile.codingStyleDefaultParameters.layersCount; + var componentsCount = siz.Csiz; + var maxDecompositionLevelsCount = 0; + for (var q = 0; q < componentsCount; q++) { + maxDecompositionLevelsCount = Math.max(maxDecompositionLevelsCount, + tile.components[q].codingStyleParameters.decompositionLevelsCount); + } + + var l = 0, r = 0, i = 0, k = 0; + + this.nextPacket = function JpxImage_nextPacket() { + // Section B.12.1.1 Layer-resolution-component-position + for (; l < layersCount; l++) { + for (; r <= maxDecompositionLevelsCount; r++) { + for (; i < componentsCount; i++) { + var component = tile.components[i]; + if (r > component.codingStyleParameters.decompositionLevelsCount) { + continue; + } + + var resolution = component.resolutions[r]; + var numprecincts = resolution.precinctParameters.numprecincts; + for (; k < numprecincts;) { + var packet = createPacket(resolution, k, l); + k++; + return packet; + } + k = 0; + } + i = 0; + } + r = 0; + } + throw new Error('JPX Error: Out of packets'); + }; + } + function ResolutionLayerComponentPositionIterator(context) { + var siz = context.SIZ; + var tileIndex = context.currentTile.index; + var tile = context.tiles[tileIndex]; + var layersCount = tile.codingStyleDefaultParameters.layersCount; + var componentsCount = siz.Csiz; + var maxDecompositionLevelsCount = 0; + for (var q = 0; q < componentsCount; q++) { + maxDecompositionLevelsCount = Math.max(maxDecompositionLevelsCount, + tile.components[q].codingStyleParameters.decompositionLevelsCount); + } + + var r = 0, l = 0, i = 0, k = 0; + + this.nextPacket = function JpxImage_nextPacket() { + // Section B.12.1.2 Resolution-layer-component-position + for (; r <= maxDecompositionLevelsCount; r++) { + for (; l < layersCount; l++) { + for (; i < componentsCount; i++) { + var component = tile.components[i]; + if (r > component.codingStyleParameters.decompositionLevelsCount) { + continue; + } + + var resolution = component.resolutions[r]; + var numprecincts = resolution.precinctParameters.numprecincts; + for (; k < numprecincts;) { + var packet = createPacket(resolution, k, l); + k++; + return packet; + } + k = 0; + } + i = 0; + } + l = 0; + } + throw new Error('JPX Error: Out of packets'); + }; + } + function ResolutionPositionComponentLayerIterator(context) { + var siz = context.SIZ; + var tileIndex = context.currentTile.index; + var tile = context.tiles[tileIndex]; + var layersCount = tile.codingStyleDefaultParameters.layersCount; + var componentsCount = siz.Csiz; + var l, r, c, p; + var maxDecompositionLevelsCount = 0; + for (c = 0; c < componentsCount; c++) { + var component = tile.components[c]; + maxDecompositionLevelsCount = Math.max(maxDecompositionLevelsCount, + component.codingStyleParameters.decompositionLevelsCount); + } + var maxNumPrecinctsInLevel = new Int32Array( + maxDecompositionLevelsCount + 1); + for (r = 0; r <= maxDecompositionLevelsCount; ++r) { + var maxNumPrecincts = 0; + for (c = 0; c < componentsCount; ++c) { + var resolutions = tile.components[c].resolutions; + if (r < resolutions.length) { + maxNumPrecincts = Math.max(maxNumPrecincts, + resolutions[r].precinctParameters.numprecincts); + } + } + maxNumPrecinctsInLevel[r] = maxNumPrecincts; + } + l = 0; + r = 0; + c = 0; + p = 0; + + this.nextPacket = function JpxImage_nextPacket() { + // Section B.12.1.3 Resolution-position-component-layer + for (; r <= maxDecompositionLevelsCount; r++) { + for (; p < maxNumPrecinctsInLevel[r]; p++) { + for (; c < componentsCount; c++) { + var component = tile.components[c]; + if (r > component.codingStyleParameters.decompositionLevelsCount) { + continue; + } + var resolution = component.resolutions[r]; + var numprecincts = resolution.precinctParameters.numprecincts; + if (p >= numprecincts) { + continue; + } + for (; l < layersCount;) { + var packet = createPacket(resolution, p, l); + l++; + return packet; + } + l = 0; + } + c = 0; + } + p = 0; + } + throw new Error('JPX Error: Out of packets'); + }; + } + function PositionComponentResolutionLayerIterator(context) { + var siz = context.SIZ; + var tileIndex = context.currentTile.index; + var tile = context.tiles[tileIndex]; + var layersCount = tile.codingStyleDefaultParameters.layersCount; + var componentsCount = siz.Csiz; + var precinctsSizes = getPrecinctSizesInImageScale(tile); + var precinctsIterationSizes = precinctsSizes; + var l = 0, r = 0, c = 0, px = 0, py = 0; + + this.nextPacket = function JpxImage_nextPacket() { + // Section B.12.1.4 Position-component-resolution-layer + for (; py < precinctsIterationSizes.maxNumHigh; py++) { + for (; px < precinctsIterationSizes.maxNumWide; px++) { + for (; c < componentsCount; c++) { + var component = tile.components[c]; + var decompositionLevelsCount = + component.codingStyleParameters.decompositionLevelsCount; + for (; r <= decompositionLevelsCount; r++) { + var resolution = component.resolutions[r]; + var sizeInImageScale = + precinctsSizes.components[c].resolutions[r]; + var k = getPrecinctIndexIfExist( + px, + py, + sizeInImageScale, + precinctsIterationSizes, + resolution); + if (k === null) { + continue; + } + for (; l < layersCount;) { + var packet = createPacket(resolution, k, l); + l++; + return packet; + } + l = 0; + } + r = 0; + } + c = 0; + } + px = 0; + } + throw new Error('JPX Error: Out of packets'); + }; + } + function ComponentPositionResolutionLayerIterator(context) { + var siz = context.SIZ; + var tileIndex = context.currentTile.index; + var tile = context.tiles[tileIndex]; + var layersCount = tile.codingStyleDefaultParameters.layersCount; + var componentsCount = siz.Csiz; + var precinctsSizes = getPrecinctSizesInImageScale(tile); + var l = 0, r = 0, c = 0, px = 0, py = 0; + + this.nextPacket = function JpxImage_nextPacket() { + // Section B.12.1.5 Component-position-resolution-layer + for (; c < componentsCount; ++c) { + var component = tile.components[c]; + var precinctsIterationSizes = precinctsSizes.components[c]; + var decompositionLevelsCount = + component.codingStyleParameters.decompositionLevelsCount; + for (; py < precinctsIterationSizes.maxNumHigh; py++) { + for (; px < precinctsIterationSizes.maxNumWide; px++) { + for (; r <= decompositionLevelsCount; r++) { + var resolution = component.resolutions[r]; + var sizeInImageScale = precinctsIterationSizes.resolutions[r]; + var k = getPrecinctIndexIfExist( + px, + py, + sizeInImageScale, + precinctsIterationSizes, + resolution); + if (k === null) { + continue; + } + for (; l < layersCount;) { + var packet = createPacket(resolution, k, l); + l++; + return packet; + } + l = 0; + } + r = 0; + } + px = 0; + } + py = 0; + } + throw new Error('JPX Error: Out of packets'); + }; + } + function getPrecinctIndexIfExist( + pxIndex, pyIndex, sizeInImageScale, precinctIterationSizes, resolution) { + var posX = pxIndex * precinctIterationSizes.minWidth; + var posY = pyIndex * precinctIterationSizes.minHeight; + if (posX % sizeInImageScale.width !== 0 || + posY % sizeInImageScale.height !== 0) { + return null; + } + var startPrecinctRowIndex = + (posY / sizeInImageScale.width) * + resolution.precinctParameters.numprecinctswide; + return (posX / sizeInImageScale.height) + startPrecinctRowIndex; + } + function getPrecinctSizesInImageScale(tile) { + var componentsCount = tile.components.length; + var minWidth = Number.MAX_VALUE; + var minHeight = Number.MAX_VALUE; + var maxNumWide = 0; + var maxNumHigh = 0; + var sizePerComponent = new Array(componentsCount); + for (var c = 0; c < componentsCount; c++) { + var component = tile.components[c]; + var decompositionLevelsCount = + component.codingStyleParameters.decompositionLevelsCount; + var sizePerResolution = new Array(decompositionLevelsCount + 1); + var minWidthCurrentComponent = Number.MAX_VALUE; + var minHeightCurrentComponent = Number.MAX_VALUE; + var maxNumWideCurrentComponent = 0; + var maxNumHighCurrentComponent = 0; + var scale = 1; + for (var r = decompositionLevelsCount; r >= 0; --r) { + var resolution = component.resolutions[r]; + var widthCurrentResolution = + scale * resolution.precinctParameters.precinctWidth; + var heightCurrentResolution = + scale * resolution.precinctParameters.precinctHeight; + minWidthCurrentComponent = Math.min( + minWidthCurrentComponent, + widthCurrentResolution); + minHeightCurrentComponent = Math.min( + minHeightCurrentComponent, + heightCurrentResolution); + maxNumWideCurrentComponent = Math.max(maxNumWideCurrentComponent, + resolution.precinctParameters.numprecinctswide); + maxNumHighCurrentComponent = Math.max(maxNumHighCurrentComponent, + resolution.precinctParameters.numprecinctshigh); + sizePerResolution[r] = { + width: widthCurrentResolution, + height: heightCurrentResolution + }; + scale <<= 1; + } + minWidth = Math.min(minWidth, minWidthCurrentComponent); + minHeight = Math.min(minHeight, minHeightCurrentComponent); + maxNumWide = Math.max(maxNumWide, maxNumWideCurrentComponent); + maxNumHigh = Math.max(maxNumHigh, maxNumHighCurrentComponent); + sizePerComponent[c] = { + resolutions: sizePerResolution, + minWidth: minWidthCurrentComponent, + minHeight: minHeightCurrentComponent, + maxNumWide: maxNumWideCurrentComponent, + maxNumHigh: maxNumHighCurrentComponent + }; + } + return { + components: sizePerComponent, + minWidth: minWidth, + minHeight: minHeight, + maxNumWide: maxNumWide, + maxNumHigh: maxNumHigh + }; + } + function buildPackets(context) { + var siz = context.SIZ; + var tileIndex = context.currentTile.index; + var tile = context.tiles[tileIndex]; + var componentsCount = siz.Csiz; + // Creating resolutions and sub-bands for each component + for (var c = 0; c < componentsCount; c++) { + var component = tile.components[c]; + var decompositionLevelsCount = + component.codingStyleParameters.decompositionLevelsCount; + // Section B.5 Resolution levels and sub-bands + var resolutions = []; + var subbands = []; + for (var r = 0; r <= decompositionLevelsCount; r++) { + var blocksDimensions = getBlocksDimensions(context, component, r); + var resolution = {}; + var scale = 1 << (decompositionLevelsCount - r); + resolution.trx0 = Math.ceil(component.tcx0 / scale); + resolution.try0 = Math.ceil(component.tcy0 / scale); + resolution.trx1 = Math.ceil(component.tcx1 / scale); + resolution.try1 = Math.ceil(component.tcy1 / scale); + resolution.resLevel = r; + buildPrecincts(context, resolution, blocksDimensions); + resolutions.push(resolution); + + var subband; + if (r === 0) { + // one sub-band (LL) with last decomposition + subband = {}; + subband.type = 'LL'; + subband.tbx0 = Math.ceil(component.tcx0 / scale); + subband.tby0 = Math.ceil(component.tcy0 / scale); + subband.tbx1 = Math.ceil(component.tcx1 / scale); + subband.tby1 = Math.ceil(component.tcy1 / scale); + subband.resolution = resolution; + buildCodeblocks(context, subband, blocksDimensions); + subbands.push(subband); + resolution.subbands = [subband]; + } else { + var bscale = 1 << (decompositionLevelsCount - r + 1); + var resolutionSubbands = []; + // three sub-bands (HL, LH and HH) with rest of decompositions + subband = {}; + subband.type = 'HL'; + subband.tbx0 = Math.ceil(component.tcx0 / bscale - 0.5); + subband.tby0 = Math.ceil(component.tcy0 / bscale); + subband.tbx1 = Math.ceil(component.tcx1 / bscale - 0.5); + subband.tby1 = Math.ceil(component.tcy1 / bscale); + subband.resolution = resolution; + buildCodeblocks(context, subband, blocksDimensions); + subbands.push(subband); + resolutionSubbands.push(subband); + + subband = {}; + subband.type = 'LH'; + subband.tbx0 = Math.ceil(component.tcx0 / bscale); + subband.tby0 = Math.ceil(component.tcy0 / bscale - 0.5); + subband.tbx1 = Math.ceil(component.tcx1 / bscale); + subband.tby1 = Math.ceil(component.tcy1 / bscale - 0.5); + subband.resolution = resolution; + buildCodeblocks(context, subband, blocksDimensions); + subbands.push(subband); + resolutionSubbands.push(subband); + + subband = {}; + subband.type = 'HH'; + subband.tbx0 = Math.ceil(component.tcx0 / bscale - 0.5); + subband.tby0 = Math.ceil(component.tcy0 / bscale - 0.5); + subband.tbx1 = Math.ceil(component.tcx1 / bscale - 0.5); + subband.tby1 = Math.ceil(component.tcy1 / bscale - 0.5); + subband.resolution = resolution; + buildCodeblocks(context, subband, blocksDimensions); + subbands.push(subband); + resolutionSubbands.push(subband); + + resolution.subbands = resolutionSubbands; + } + } + component.resolutions = resolutions; + component.subbands = subbands; + } + // Generate the packets sequence + var progressionOrder = tile.codingStyleDefaultParameters.progressionOrder; + switch (progressionOrder) { + case 0: + tile.packetsIterator = + new LayerResolutionComponentPositionIterator(context); + break; + case 1: + tile.packetsIterator = + new ResolutionLayerComponentPositionIterator(context); + break; + case 2: + tile.packetsIterator = + new ResolutionPositionComponentLayerIterator(context); + break; + case 3: + tile.packetsIterator = + new PositionComponentResolutionLayerIterator(context); + break; + case 4: + tile.packetsIterator = + new ComponentPositionResolutionLayerIterator(context); + break; + default: + throw new Error('JPX Error: Unsupported progression order ' + + progressionOrder); + } + } + function parseTilePackets(context, data, offset, dataLength) { + var position = 0; + var buffer, bufferSize = 0, skipNextBit = false; + function readBits(count) { + while (bufferSize < count) { + var b = data[offset + position]; + position++; + if (skipNextBit) { + buffer = (buffer << 7) | b; + bufferSize += 7; + skipNextBit = false; + } else { + buffer = (buffer << 8) | b; + bufferSize += 8; + } + if (b === 0xFF) { + skipNextBit = true; + } + } + bufferSize -= count; + return (buffer >>> bufferSize) & ((1 << count) - 1); + } + function skipMarkerIfEqual(value) { + if (data[offset + position - 1] === 0xFF && + data[offset + position] === value) { + skipBytes(1); + return true; + } else if (data[offset + position] === 0xFF && + data[offset + position + 1] === value) { + skipBytes(2); + return true; + } + return false; + } + function skipBytes(count) { + position += count; + } + function alignToByte() { + bufferSize = 0; + if (skipNextBit) { + position++; + skipNextBit = false; + } + } + function readCodingpasses() { + if (readBits(1) === 0) { + return 1; + } + if (readBits(1) === 0) { + return 2; + } + var value = readBits(2); + if (value < 3) { + return value + 3; + } + value = readBits(5); + if (value < 31) { + return value + 6; + } + value = readBits(7); + return value + 37; + } + var tileIndex = context.currentTile.index; + var tile = context.tiles[tileIndex]; + var sopMarkerUsed = context.COD.sopMarkerUsed; + var ephMarkerUsed = context.COD.ephMarkerUsed; + var packetsIterator = tile.packetsIterator; + while (position < dataLength) { + alignToByte(); + if (sopMarkerUsed && skipMarkerIfEqual(0x91)) { + // Skip also marker segment length and packet sequence ID + skipBytes(4); + } + var packet = packetsIterator.nextPacket(); + if (!readBits(1)) { + continue; + } + var layerNumber = packet.layerNumber; + var queue = [], codeblock; + for (var i = 0, ii = packet.codeblocks.length; i < ii; i++) { + codeblock = packet.codeblocks[i]; + var precinct = codeblock.precinct; + var codeblockColumn = codeblock.cbx - precinct.cbxMin; + var codeblockRow = codeblock.cby - precinct.cbyMin; + var codeblockIncluded = false; + var firstTimeInclusion = false; + var valueReady; + if (codeblock['included'] !== undefined) { + codeblockIncluded = !!readBits(1); + } else { + // reading inclusion tree + precinct = codeblock.precinct; + var inclusionTree, zeroBitPlanesTree; + if (precinct['inclusionTree'] !== undefined) { + inclusionTree = precinct.inclusionTree; + } else { + // building inclusion and zero bit-planes trees + var width = precinct.cbxMax - precinct.cbxMin + 1; + var height = precinct.cbyMax - precinct.cbyMin + 1; + inclusionTree = new InclusionTree(width, height, layerNumber); + zeroBitPlanesTree = new TagTree(width, height); + precinct.inclusionTree = inclusionTree; + precinct.zeroBitPlanesTree = zeroBitPlanesTree; + } + + if (inclusionTree.reset(codeblockColumn, codeblockRow, layerNumber)) { + while (true) { + if (readBits(1)) { + valueReady = !inclusionTree.nextLevel(); + if (valueReady) { + codeblock.included = true; + codeblockIncluded = firstTimeInclusion = true; + break; + } + } else { + inclusionTree.incrementValue(layerNumber); + break; + } + } + } + } + if (!codeblockIncluded) { + continue; + } + if (firstTimeInclusion) { + zeroBitPlanesTree = precinct.zeroBitPlanesTree; + zeroBitPlanesTree.reset(codeblockColumn, codeblockRow); + while (true) { + if (readBits(1)) { + valueReady = !zeroBitPlanesTree.nextLevel(); + if (valueReady) { + break; + } + } else { + zeroBitPlanesTree.incrementValue(); + } + } + codeblock.zeroBitPlanes = zeroBitPlanesTree.value; + } + var codingpasses = readCodingpasses(); + while (readBits(1)) { + codeblock.Lblock++; + } + var codingpassesLog2 = log2(codingpasses); + // rounding down log2 + var bits = ((codingpasses < (1 << codingpassesLog2)) ? + codingpassesLog2 - 1 : codingpassesLog2) + codeblock.Lblock; + var codedDataLength = readBits(bits); + queue.push({ + codeblock: codeblock, + codingpasses: codingpasses, + dataLength: codedDataLength + }); + } + alignToByte(); + if (ephMarkerUsed) { + skipMarkerIfEqual(0x92); + } + while (queue.length > 0) { + var packetItem = queue.shift(); + codeblock = packetItem.codeblock; + if (codeblock['data'] === undefined) { + codeblock.data = []; + } + codeblock.data.push({ + data: data, + start: offset + position, + end: offset + position + packetItem.dataLength, + codingpasses: packetItem.codingpasses + }); + position += packetItem.dataLength; + } + } + return position; + } + function copyCoefficients(coefficients, levelWidth, levelHeight, subband, + delta, mb, reversible, segmentationSymbolUsed) { + var x0 = subband.tbx0; + var y0 = subband.tby0; + var width = subband.tbx1 - subband.tbx0; + var codeblocks = subband.codeblocks; + var right = subband.type.charAt(0) === 'H' ? 1 : 0; + var bottom = subband.type.charAt(1) === 'H' ? levelWidth : 0; + + for (var i = 0, ii = codeblocks.length; i < ii; ++i) { + var codeblock = codeblocks[i]; + var blockWidth = codeblock.tbx1_ - codeblock.tbx0_; + var blockHeight = codeblock.tby1_ - codeblock.tby0_; + if (blockWidth === 0 || blockHeight === 0) { + continue; + } + if (codeblock['data'] === undefined) { + continue; + } + + var bitModel, currentCodingpassType; + bitModel = new BitModel(blockWidth, blockHeight, codeblock.subbandType, + codeblock.zeroBitPlanes, mb); + currentCodingpassType = 2; // first bit plane starts from cleanup + + // collect data + var data = codeblock.data, totalLength = 0, codingpasses = 0; + var j, jj, dataItem; + for (j = 0, jj = data.length; j < jj; j++) { + dataItem = data[j]; + totalLength += dataItem.end - dataItem.start; + codingpasses += dataItem.codingpasses; + } + var encodedData = new Uint8Array(totalLength); + var position = 0; + for (j = 0, jj = data.length; j < jj; j++) { + dataItem = data[j]; + var chunk = dataItem.data.subarray(dataItem.start, dataItem.end); + encodedData.set(chunk, position); + position += chunk.length; + } + // decoding the item + var decoder = new ArithmeticDecoder(encodedData, 0, totalLength); + bitModel.setDecoder(decoder); + + for (j = 0; j < codingpasses; j++) { + switch (currentCodingpassType) { + case 0: + bitModel.runSignificancePropogationPass(); + break; + case 1: + bitModel.runMagnitudeRefinementPass(); + break; + case 2: + bitModel.runCleanupPass(); + if (segmentationSymbolUsed) { + bitModel.checkSegmentationSymbol(); + } + break; + } + currentCodingpassType = (currentCodingpassType + 1) % 3; + } + + var offset = (codeblock.tbx0_ - x0) + (codeblock.tby0_ - y0) * width; + var sign = bitModel.coefficentsSign; + var magnitude = bitModel.coefficentsMagnitude; + var bitsDecoded = bitModel.bitsDecoded; + var magnitudeCorrection = reversible ? 0 : 0.5; + var k, n, nb; + position = 0; + // Do the interleaving of Section F.3.3 here, so we do not need + // to copy later. LL level is not interleaved, just copied. + var interleave = (subband.type !== 'LL'); + for (j = 0; j < blockHeight; j++) { + var row = (offset / width) | 0; // row in the non-interleaved subband + var levelOffset = 2 * row * (levelWidth - width) + right + bottom; + for (k = 0; k < blockWidth; k++) { + n = magnitude[position]; + if (n !== 0) { + n = (n + magnitudeCorrection) * delta; + if (sign[position] !== 0) { + n = -n; + } + nb = bitsDecoded[position]; + var pos = interleave ? (levelOffset + (offset << 1)) : offset; + if (reversible && (nb >= mb)) { + coefficients[pos] = n; + } else { + coefficients[pos] = n * (1 << (mb - nb)); + } + } + offset++; + position++; + } + offset += width - blockWidth; + } + } + } + function transformTile(context, tile, c) { + var component = tile.components[c]; + var codingStyleParameters = component.codingStyleParameters; + var quantizationParameters = component.quantizationParameters; + var decompositionLevelsCount = + codingStyleParameters.decompositionLevelsCount; + var spqcds = quantizationParameters.SPqcds; + var scalarExpounded = quantizationParameters.scalarExpounded; + var guardBits = quantizationParameters.guardBits; + var segmentationSymbolUsed = codingStyleParameters.segmentationSymbolUsed; + var precision = context.components[c].precision; + + var reversible = codingStyleParameters.reversibleTransformation; + var transform = (reversible ? new ReversibleTransform() : + new IrreversibleTransform()); + + var subbandCoefficients = []; + var b = 0; + for (var i = 0; i <= decompositionLevelsCount; i++) { + var resolution = component.resolutions[i]; + + var width = resolution.trx1 - resolution.trx0; + var height = resolution.try1 - resolution.try0; + // Allocate space for the whole sublevel. + var coefficients = new Float32Array(width * height); + + for (var j = 0, jj = resolution.subbands.length; j < jj; j++) { + var mu, epsilon; + if (!scalarExpounded) { + // formula E-5 + mu = spqcds[0].mu; + epsilon = spqcds[0].epsilon + (i > 0 ? 1 - i : 0); + } else { + mu = spqcds[b].mu; + epsilon = spqcds[b].epsilon; + b++; + } + + var subband = resolution.subbands[j]; + var gainLog2 = SubbandsGainLog2[subband.type]; + + // calulate quantization coefficient (Section E.1.1.1) + var delta = (reversible ? 1 : + Math.pow(2, precision + gainLog2 - epsilon) * (1 + mu / 2048)); + var mb = (guardBits + epsilon - 1); + + // In the first resolution level, copyCoefficients will fill the + // whole array with coefficients. In the succeding passes, + // copyCoefficients will consecutively fill in the values that belong + // to the interleaved positions of the HL, LH, and HH coefficients. + // The LL coefficients will then be interleaved in Transform.iterate(). + copyCoefficients(coefficients, width, height, subband, delta, mb, + reversible, segmentationSymbolUsed); + } + subbandCoefficients.push({ + width: width, + height: height, + items: coefficients + }); + } + + var result = transform.calculate(subbandCoefficients, + component.tcx0, component.tcy0); + return { + left: component.tcx0, + top: component.tcy0, + width: result.width, + height: result.height, + items: result.items + }; + } + function transformComponents(context) { + var siz = context.SIZ; + var components = context.components; + var componentsCount = siz.Csiz; + var resultImages = []; + for (var i = 0, ii = context.tiles.length; i < ii; i++) { + var tile = context.tiles[i]; + var transformedTiles = []; + var c; + for (c = 0; c < componentsCount; c++) { + transformedTiles[c] = transformTile(context, tile, c); + } + var tile0 = transformedTiles[0]; + var out = new Uint8Array(tile0.items.length * componentsCount); + var result = { + left: tile0.left, + top: tile0.top, + width: tile0.width, + height: tile0.height, + items: out + }; + + // Section G.2.2 Inverse multi component transform + var shift, offset, max, min, maxK; + var pos = 0, j, jj, y0, y1, y2, r, g, b, k, val; + if (tile.codingStyleDefaultParameters.multipleComponentTransform) { + var fourComponents = componentsCount === 4; + var y0items = transformedTiles[0].items; + var y1items = transformedTiles[1].items; + var y2items = transformedTiles[2].items; + var y3items = fourComponents ? transformedTiles[3].items : null; + + // HACK: The multiple component transform formulas below assume that + // all components have the same precision. With this in mind, we + // compute shift and offset only once. + shift = components[0].precision - 8; + offset = (128 << shift) + 0.5; + max = 255 * (1 << shift); + maxK = max * 0.5; + min = -maxK; + + var component0 = tile.components[0]; + var alpha01 = componentsCount - 3; + jj = y0items.length; + if (!component0.codingStyleParameters.reversibleTransformation) { + // inverse irreversible multiple component transform + for (j = 0; j < jj; j++, pos += alpha01) { + y0 = y0items[j] + offset; + y1 = y1items[j]; + y2 = y2items[j]; + r = y0 + 1.402 * y2; + g = y0 - 0.34413 * y1 - 0.71414 * y2; + b = y0 + 1.772 * y1; + out[pos++] = r <= 0 ? 0 : r >= max ? 255 : r >> shift; + out[pos++] = g <= 0 ? 0 : g >= max ? 255 : g >> shift; + out[pos++] = b <= 0 ? 0 : b >= max ? 255 : b >> shift; + } + } else { + // inverse reversible multiple component transform + for (j = 0; j < jj; j++, pos += alpha01) { + y0 = y0items[j] + offset; + y1 = y1items[j]; + y2 = y2items[j]; + g = y0 - ((y2 + y1) >> 2); + r = g + y2; + b = g + y1; + out[pos++] = r <= 0 ? 0 : r >= max ? 255 : r >> shift; + out[pos++] = g <= 0 ? 0 : g >= max ? 255 : g >> shift; + out[pos++] = b <= 0 ? 0 : b >= max ? 255 : b >> shift; + } + } + if (fourComponents) { + for (j = 0, pos = 3; j < jj; j++, pos += 4) { + k = y3items[j]; + out[pos] = k <= min ? 0 : k >= maxK ? 255 : (k + offset) >> shift; + } + } + } else { // no multi-component transform + for (c = 0; c < componentsCount; c++) { + var items = transformedTiles[c].items; + shift = components[c].precision - 8; + offset = (128 << shift) + 0.5; + max = (127.5 * (1 << shift)); + min = -max; + for (pos = c, j = 0, jj = items.length; j < jj; j++) { + val = items[j]; + out[pos] = val <= min ? 0 : + val >= max ? 255 : (val + offset) >> shift; + pos += componentsCount; + } + } + } + resultImages.push(result); + } + return resultImages; + } + function initializeTile(context, tileIndex) { + var siz = context.SIZ; + var componentsCount = siz.Csiz; + var tile = context.tiles[tileIndex]; + for (var c = 0; c < componentsCount; c++) { + var component = tile.components[c]; + var qcdOrQcc = (context.currentTile.QCC[c] !== undefined ? + context.currentTile.QCC[c] : context.currentTile.QCD); + component.quantizationParameters = qcdOrQcc; + var codOrCoc = (context.currentTile.COC[c] !== undefined ? + context.currentTile.COC[c] : context.currentTile.COD); + component.codingStyleParameters = codOrCoc; + } + tile.codingStyleDefaultParameters = context.currentTile.COD; + } + + // Section B.10.2 Tag trees + var TagTree = (function TagTreeClosure() { + function TagTree(width, height) { + var levelsLength = log2(Math.max(width, height)) + 1; + this.levels = []; + for (var i = 0; i < levelsLength; i++) { + var level = { + width: width, + height: height, + items: [] + }; + this.levels.push(level); + width = Math.ceil(width / 2); + height = Math.ceil(height / 2); + } + } + TagTree.prototype = { + reset: function TagTree_reset(i, j) { + var currentLevel = 0, value = 0, level; + while (currentLevel < this.levels.length) { + level = this.levels[currentLevel]; + var index = i + j * level.width; + if (level.items[index] !== undefined) { + value = level.items[index]; + break; + } + level.index = index; + i >>= 1; + j >>= 1; + currentLevel++; + } + currentLevel--; + level = this.levels[currentLevel]; + level.items[level.index] = value; + this.currentLevel = currentLevel; + delete this.value; + }, + incrementValue: function TagTree_incrementValue() { + var level = this.levels[this.currentLevel]; + level.items[level.index]++; + }, + nextLevel: function TagTree_nextLevel() { + var currentLevel = this.currentLevel; + var level = this.levels[currentLevel]; + var value = level.items[level.index]; + currentLevel--; + if (currentLevel < 0) { + this.value = value; + return false; + } + + this.currentLevel = currentLevel; + level = this.levels[currentLevel]; + level.items[level.index] = value; + return true; + } + }; + return TagTree; + })(); + + var InclusionTree = (function InclusionTreeClosure() { + function InclusionTree(width, height, defaultValue) { + var levelsLength = log2(Math.max(width, height)) + 1; + this.levels = []; + for (var i = 0; i < levelsLength; i++) { + var items = new Uint8Array(width * height); + for (var j = 0, jj = items.length; j < jj; j++) { + items[j] = defaultValue; + } + + var level = { + width: width, + height: height, + items: items + }; + this.levels.push(level); + + width = Math.ceil(width / 2); + height = Math.ceil(height / 2); + } + } + InclusionTree.prototype = { + reset: function InclusionTree_reset(i, j, stopValue) { + var currentLevel = 0; + while (currentLevel < this.levels.length) { + var level = this.levels[currentLevel]; + var index = i + j * level.width; + level.index = index; + var value = level.items[index]; + + if (value === 0xFF) { + break; + } + + if (value > stopValue) { + this.currentLevel = currentLevel; + // already know about this one, propagating the value to top levels + this.propagateValues(); + return false; + } + + i >>= 1; + j >>= 1; + currentLevel++; + } + this.currentLevel = currentLevel - 1; + return true; + }, + incrementValue: function InclusionTree_incrementValue(stopValue) { + var level = this.levels[this.currentLevel]; + level.items[level.index] = stopValue + 1; + this.propagateValues(); + }, + propagateValues: function InclusionTree_propagateValues() { + var levelIndex = this.currentLevel; + var level = this.levels[levelIndex]; + var currentValue = level.items[level.index]; + while (--levelIndex >= 0) { + level = this.levels[levelIndex]; + level.items[level.index] = currentValue; + } + }, + nextLevel: function InclusionTree_nextLevel() { + var currentLevel = this.currentLevel; + var level = this.levels[currentLevel]; + var value = level.items[level.index]; + level.items[level.index] = 0xFF; + currentLevel--; + if (currentLevel < 0) { + return false; + } + + this.currentLevel = currentLevel; + level = this.levels[currentLevel]; + level.items[level.index] = value; + return true; + } + }; + return InclusionTree; + })(); + + // Section D. Coefficient bit modeling + var BitModel = (function BitModelClosure() { + var UNIFORM_CONTEXT = 17; + var RUNLENGTH_CONTEXT = 18; + // Table D-1 + // The index is binary presentation: 0dddvvhh, ddd - sum of Di (0..4), + // vv - sum of Vi (0..2), and hh - sum of Hi (0..2) + var LLAndLHContextsLabel = new Uint8Array([ + 0, 5, 8, 0, 3, 7, 8, 0, 4, 7, 8, 0, 0, 0, 0, 0, 1, 6, 8, 0, 3, 7, 8, 0, 4, + 7, 8, 0, 0, 0, 0, 0, 2, 6, 8, 0, 3, 7, 8, 0, 4, 7, 8, 0, 0, 0, 0, 0, 2, 6, + 8, 0, 3, 7, 8, 0, 4, 7, 8, 0, 0, 0, 0, 0, 2, 6, 8, 0, 3, 7, 8, 0, 4, 7, 8 + ]); + var HLContextLabel = new Uint8Array([ + 0, 3, 4, 0, 5, 7, 7, 0, 8, 8, 8, 0, 0, 0, 0, 0, 1, 3, 4, 0, 6, 7, 7, 0, 8, + 8, 8, 0, 0, 0, 0, 0, 2, 3, 4, 0, 6, 7, 7, 0, 8, 8, 8, 0, 0, 0, 0, 0, 2, 3, + 4, 0, 6, 7, 7, 0, 8, 8, 8, 0, 0, 0, 0, 0, 2, 3, 4, 0, 6, 7, 7, 0, 8, 8, 8 + ]); + var HHContextLabel = new Uint8Array([ + 0, 1, 2, 0, 1, 2, 2, 0, 2, 2, 2, 0, 0, 0, 0, 0, 3, 4, 5, 0, 4, 5, 5, 0, 5, + 5, 5, 0, 0, 0, 0, 0, 6, 7, 7, 0, 7, 7, 7, 0, 7, 7, 7, 0, 0, 0, 0, 0, 8, 8, + 8, 0, 8, 8, 8, 0, 8, 8, 8, 0, 0, 0, 0, 0, 8, 8, 8, 0, 8, 8, 8, 0, 8, 8, 8 + ]); + + function BitModel(width, height, subband, zeroBitPlanes, mb) { + this.width = width; + this.height = height; + + this.contextLabelTable = (subband === 'HH' ? HHContextLabel : + (subband === 'HL' ? HLContextLabel : LLAndLHContextsLabel)); + + var coefficientCount = width * height; + + // coefficients outside the encoding region treated as insignificant + // add border state cells for significanceState + this.neighborsSignificance = new Uint8Array(coefficientCount); + this.coefficentsSign = new Uint8Array(coefficientCount); + this.coefficentsMagnitude = mb > 14 ? new Uint32Array(coefficientCount) : + mb > 6 ? new Uint16Array(coefficientCount) : + new Uint8Array(coefficientCount); + this.processingFlags = new Uint8Array(coefficientCount); + + var bitsDecoded = new Uint8Array(coefficientCount); + if (zeroBitPlanes !== 0) { + for (var i = 0; i < coefficientCount; i++) { + bitsDecoded[i] = zeroBitPlanes; + } + } + this.bitsDecoded = bitsDecoded; + + this.reset(); + } + + BitModel.prototype = { + setDecoder: function BitModel_setDecoder(decoder) { + this.decoder = decoder; + }, + reset: function BitModel_reset() { + // We have 17 contexts that are accessed via context labels, + // plus the uniform and runlength context. + this.contexts = new Int8Array(19); + + // Contexts are packed into 1 byte: + // highest 7 bits carry the index, lowest bit carries mps + this.contexts[0] = (4 << 1) | 0; + this.contexts[UNIFORM_CONTEXT] = (46 << 1) | 0; + this.contexts[RUNLENGTH_CONTEXT] = (3 << 1) | 0; + }, + setNeighborsSignificance: + function BitModel_setNeighborsSignificance(row, column, index) { + var neighborsSignificance = this.neighborsSignificance; + var width = this.width, height = this.height; + var left = (column > 0); + var right = (column + 1 < width); + var i; + + if (row > 0) { + i = index - width; + if (left) { + neighborsSignificance[i - 1] += 0x10; + } + if (right) { + neighborsSignificance[i + 1] += 0x10; + } + neighborsSignificance[i] += 0x04; + } + + if (row + 1 < height) { + i = index + width; + if (left) { + neighborsSignificance[i - 1] += 0x10; + } + if (right) { + neighborsSignificance[i + 1] += 0x10; + } + neighborsSignificance[i] += 0x04; + } + + if (left) { + neighborsSignificance[index - 1] += 0x01; + } + if (right) { + neighborsSignificance[index + 1] += 0x01; + } + neighborsSignificance[index] |= 0x80; + }, + runSignificancePropogationPass: + function BitModel_runSignificancePropogationPass() { + var decoder = this.decoder; + var width = this.width, height = this.height; + var coefficentsMagnitude = this.coefficentsMagnitude; + var coefficentsSign = this.coefficentsSign; + var neighborsSignificance = this.neighborsSignificance; + var processingFlags = this.processingFlags; + var contexts = this.contexts; + var labels = this.contextLabelTable; + var bitsDecoded = this.bitsDecoded; + var processedInverseMask = ~1; + var processedMask = 1; + var firstMagnitudeBitMask = 2; + + for (var i0 = 0; i0 < height; i0 += 4) { + for (var j = 0; j < width; j++) { + var index = i0 * width + j; + for (var i1 = 0; i1 < 4; i1++, index += width) { + var i = i0 + i1; + if (i >= height) { + break; + } + // clear processed flag first + processingFlags[index] &= processedInverseMask; + + if (coefficentsMagnitude[index] || + !neighborsSignificance[index]) { + continue; + } + + var contextLabel = labels[neighborsSignificance[index]]; + var decision = decoder.readBit(contexts, contextLabel); + if (decision) { + var sign = this.decodeSignBit(i, j, index); + coefficentsSign[index] = sign; + coefficentsMagnitude[index] = 1; + this.setNeighborsSignificance(i, j, index); + processingFlags[index] |= firstMagnitudeBitMask; + } + bitsDecoded[index]++; + processingFlags[index] |= processedMask; + } + } + } + }, + decodeSignBit: function BitModel_decodeSignBit(row, column, index) { + var width = this.width, height = this.height; + var coefficentsMagnitude = this.coefficentsMagnitude; + var coefficentsSign = this.coefficentsSign; + var contribution, sign0, sign1, significance1; + var contextLabel, decoded; + + // calculate horizontal contribution + significance1 = (column > 0 && coefficentsMagnitude[index - 1] !== 0); + if (column + 1 < width && coefficentsMagnitude[index + 1] !== 0) { + sign1 = coefficentsSign[index + 1]; + if (significance1) { + sign0 = coefficentsSign[index - 1]; + contribution = 1 - sign1 - sign0; + } else { + contribution = 1 - sign1 - sign1; + } + } else if (significance1) { + sign0 = coefficentsSign[index - 1]; + contribution = 1 - sign0 - sign0; + } else { + contribution = 0; + } + var horizontalContribution = 3 * contribution; + + // calculate vertical contribution and combine with the horizontal + significance1 = (row > 0 && coefficentsMagnitude[index - width] !== 0); + if (row + 1 < height && coefficentsMagnitude[index + width] !== 0) { + sign1 = coefficentsSign[index + width]; + if (significance1) { + sign0 = coefficentsSign[index - width]; + contribution = 1 - sign1 - sign0 + horizontalContribution; + } else { + contribution = 1 - sign1 - sign1 + horizontalContribution; + } + } else if (significance1) { + sign0 = coefficentsSign[index - width]; + contribution = 1 - sign0 - sign0 + horizontalContribution; + } else { + contribution = horizontalContribution; + } + + if (contribution >= 0) { + contextLabel = 9 + contribution; + decoded = this.decoder.readBit(this.contexts, contextLabel); + } else { + contextLabel = 9 - contribution; + decoded = this.decoder.readBit(this.contexts, contextLabel) ^ 1; + } + return decoded; + }, + runMagnitudeRefinementPass: + function BitModel_runMagnitudeRefinementPass() { + var decoder = this.decoder; + var width = this.width, height = this.height; + var coefficentsMagnitude = this.coefficentsMagnitude; + var neighborsSignificance = this.neighborsSignificance; + var contexts = this.contexts; + var bitsDecoded = this.bitsDecoded; + var processingFlags = this.processingFlags; + var processedMask = 1; + var firstMagnitudeBitMask = 2; + var length = width * height; + var width4 = width * 4; + + for (var index0 = 0, indexNext; index0 < length; index0 = indexNext) { + indexNext = Math.min(length, index0 + width4); + for (var j = 0; j < width; j++) { + for (var index = index0 + j; index < indexNext; index += width) { + + // significant but not those that have just become + if (!coefficentsMagnitude[index] || + (processingFlags[index] & processedMask) !== 0) { + continue; + } + + var contextLabel = 16; + if ((processingFlags[index] & firstMagnitudeBitMask) !== 0) { + processingFlags[index] ^= firstMagnitudeBitMask; + // first refinement + var significance = neighborsSignificance[index] & 127; + contextLabel = significance === 0 ? 15 : 14; + } + + var bit = decoder.readBit(contexts, contextLabel); + coefficentsMagnitude[index] = + (coefficentsMagnitude[index] << 1) | bit; + bitsDecoded[index]++; + processingFlags[index] |= processedMask; + } + } + } + }, + runCleanupPass: function BitModel_runCleanupPass() { + var decoder = this.decoder; + var width = this.width, height = this.height; + var neighborsSignificance = this.neighborsSignificance; + var coefficentsMagnitude = this.coefficentsMagnitude; + var coefficentsSign = this.coefficentsSign; + var contexts = this.contexts; + var labels = this.contextLabelTable; + var bitsDecoded = this.bitsDecoded; + var processingFlags = this.processingFlags; + var processedMask = 1; + var firstMagnitudeBitMask = 2; + var oneRowDown = width; + var twoRowsDown = width * 2; + var threeRowsDown = width * 3; + var iNext; + for (var i0 = 0; i0 < height; i0 = iNext) { + iNext = Math.min(i0 + 4, height); + var indexBase = i0 * width; + var checkAllEmpty = i0 + 3 < height; + for (var j = 0; j < width; j++) { + var index0 = indexBase + j; + // using the property: labels[neighborsSignificance[index]] === 0 + // when neighborsSignificance[index] === 0 + var allEmpty = (checkAllEmpty && + processingFlags[index0] === 0 && + processingFlags[index0 + oneRowDown] === 0 && + processingFlags[index0 + twoRowsDown] === 0 && + processingFlags[index0 + threeRowsDown] === 0 && + neighborsSignificance[index0] === 0 && + neighborsSignificance[index0 + oneRowDown] === 0 && + neighborsSignificance[index0 + twoRowsDown] === 0 && + neighborsSignificance[index0 + threeRowsDown] === 0); + var i1 = 0, index = index0; + var i = i0, sign; + if (allEmpty) { + var hasSignificantCoefficent = + decoder.readBit(contexts, RUNLENGTH_CONTEXT); + if (!hasSignificantCoefficent) { + bitsDecoded[index0]++; + bitsDecoded[index0 + oneRowDown]++; + bitsDecoded[index0 + twoRowsDown]++; + bitsDecoded[index0 + threeRowsDown]++; + continue; // next column + } + i1 = (decoder.readBit(contexts, UNIFORM_CONTEXT) << 1) | + decoder.readBit(contexts, UNIFORM_CONTEXT); + if (i1 !== 0) { + i = i0 + i1; + index += i1 * width; + } + + sign = this.decodeSignBit(i, j, index); + coefficentsSign[index] = sign; + coefficentsMagnitude[index] = 1; + this.setNeighborsSignificance(i, j, index); + processingFlags[index] |= firstMagnitudeBitMask; + + index = index0; + for (var i2 = i0; i2 <= i; i2++, index += width) { + bitsDecoded[index]++; + } + + i1++; + } + for (i = i0 + i1; i < iNext; i++, index += width) { + if (coefficentsMagnitude[index] || + (processingFlags[index] & processedMask) !== 0) { + continue; + } + + var contextLabel = labels[neighborsSignificance[index]]; + var decision = decoder.readBit(contexts, contextLabel); + if (decision === 1) { + sign = this.decodeSignBit(i, j, index); + coefficentsSign[index] = sign; + coefficentsMagnitude[index] = 1; + this.setNeighborsSignificance(i, j, index); + processingFlags[index] |= firstMagnitudeBitMask; + } + bitsDecoded[index]++; + } + } + } + }, + checkSegmentationSymbol: function BitModel_checkSegmentationSymbol() { + var decoder = this.decoder; + var contexts = this.contexts; + var symbol = (decoder.readBit(contexts, UNIFORM_CONTEXT) << 3) | + (decoder.readBit(contexts, UNIFORM_CONTEXT) << 2) | + (decoder.readBit(contexts, UNIFORM_CONTEXT) << 1) | + decoder.readBit(contexts, UNIFORM_CONTEXT); + if (symbol !== 0xA) { + throw new Error('JPX Error: Invalid segmentation symbol'); + } + } + }; + + return BitModel; + })(); + + // Section F, Discrete wavelet transformation + var Transform = (function TransformClosure() { + function Transform() {} + + Transform.prototype.calculate = + function transformCalculate(subbands, u0, v0) { + var ll = subbands[0]; + for (var i = 1, ii = subbands.length; i < ii; i++) { + ll = this.iterate(ll, subbands[i], u0, v0); + } + return ll; + }; + Transform.prototype.extend = function extend(buffer, offset, size) { + // Section F.3.7 extending... using max extension of 4 + var i1 = offset - 1, j1 = offset + 1; + var i2 = offset + size - 2, j2 = offset + size; + buffer[i1--] = buffer[j1++]; + buffer[j2++] = buffer[i2--]; + buffer[i1--] = buffer[j1++]; + buffer[j2++] = buffer[i2--]; + buffer[i1--] = buffer[j1++]; + buffer[j2++] = buffer[i2--]; + buffer[i1] = buffer[j1]; + buffer[j2] = buffer[i2]; + }; + Transform.prototype.iterate = function Transform_iterate(ll, hl_lh_hh, + u0, v0) { + var llWidth = ll.width, llHeight = ll.height, llItems = ll.items; + var width = hl_lh_hh.width; + var height = hl_lh_hh.height; + var items = hl_lh_hh.items; + var i, j, k, l, u, v; + + // Interleave LL according to Section F.3.3 + for (k = 0, i = 0; i < llHeight; i++) { + l = i * 2 * width; + for (j = 0; j < llWidth; j++, k++, l += 2) { + items[l] = llItems[k]; + } + } + // The LL band is not needed anymore. + llItems = ll.items = null; + + var bufferPadding = 4; + var rowBuffer = new Float32Array(width + 2 * bufferPadding); + + // Section F.3.4 HOR_SR + if (width === 1) { + // if width = 1, when u0 even keep items as is, when odd divide by 2 + if ((u0 & 1) !== 0) { + for (v = 0, k = 0; v < height; v++, k += width) { + items[k] *= 0.5; + } + } + } else { + for (v = 0, k = 0; v < height; v++, k += width) { + rowBuffer.set(items.subarray(k, k + width), bufferPadding); + + this.extend(rowBuffer, bufferPadding, width); + this.filter(rowBuffer, bufferPadding, width); + + items.set( + rowBuffer.subarray(bufferPadding, bufferPadding + width), + k); + } + } + + // Accesses to the items array can take long, because it may not fit into + // CPU cache and has to be fetched from main memory. Since subsequent + // accesses to the items array are not local when reading columns, we + // have a cache miss every time. To reduce cache misses, get up to + // 'numBuffers' items at a time and store them into the individual + // buffers. The colBuffers should be small enough to fit into CPU cache. + var numBuffers = 16; + var colBuffers = []; + for (i = 0; i < numBuffers; i++) { + colBuffers.push(new Float32Array(height + 2 * bufferPadding)); + } + var b, currentBuffer = 0; + ll = bufferPadding + height; + + // Section F.3.5 VER_SR + if (height === 1) { + // if height = 1, when v0 even keep items as is, when odd divide by 2 + if ((v0 & 1) !== 0) { + for (u = 0; u < width; u++) { + items[u] *= 0.5; + } + } + } else { + for (u = 0; u < width; u++) { + // if we ran out of buffers, copy several image columns at once + if (currentBuffer === 0) { + numBuffers = Math.min(width - u, numBuffers); + for (k = u, l = bufferPadding; l < ll; k += width, l++) { + for (b = 0; b < numBuffers; b++) { + colBuffers[b][l] = items[k + b]; + } + } + currentBuffer = numBuffers; + } + + currentBuffer--; + var buffer = colBuffers[currentBuffer]; + this.extend(buffer, bufferPadding, height); + this.filter(buffer, bufferPadding, height); + + // If this is last buffer in this group of buffers, flush all buffers. + if (currentBuffer === 0) { + k = u - numBuffers + 1; + for (l = bufferPadding; l < ll; k += width, l++) { + for (b = 0; b < numBuffers; b++) { + items[k + b] = colBuffers[b][l]; + } + } + } + } + } + + return { + width: width, + height: height, + items: items + }; + }; + return Transform; + })(); + + // Section 3.8.2 Irreversible 9-7 filter + var IrreversibleTransform = (function IrreversibleTransformClosure() { + function IrreversibleTransform() { + Transform.call(this); + } + + IrreversibleTransform.prototype = Object.create(Transform.prototype); + IrreversibleTransform.prototype.filter = + function irreversibleTransformFilter(x, offset, length) { + var len = length >> 1; + offset = offset | 0; + var j, n, current, next; + + var alpha = -1.586134342059924; + var beta = -0.052980118572961; + var gamma = 0.882911075530934; + var delta = 0.443506852043971; + var K = 1.230174104914001; + var K_ = 1 / K; + + // step 1 is combined with step 3 + + // step 2 + j = offset - 3; + for (n = len + 4; n--; j += 2) { + x[j] *= K_; + } + + // step 1 & 3 + j = offset - 2; + current = delta * x[j -1]; + for (n = len + 3; n--; j += 2) { + next = delta * x[j + 1]; + x[j] = K * x[j] - current - next; + if (n--) { + j += 2; + current = delta * x[j + 1]; + x[j] = K * x[j] - current - next; + } else { + break; + } + } + + // step 4 + j = offset - 1; + current = gamma * x[j - 1]; + for (n = len + 2; n--; j += 2) { + next = gamma * x[j + 1]; + x[j] -= current + next; + if (n--) { + j += 2; + current = gamma * x[j + 1]; + x[j] -= current + next; + } else { + break; + } + } + + // step 5 + j = offset; + current = beta * x[j - 1]; + for (n = len + 1; n--; j += 2) { + next = beta * x[j + 1]; + x[j] -= current + next; + if (n--) { + j += 2; + current = beta * x[j + 1]; + x[j] -= current + next; + } else { + break; + } + } + + // step 6 + if (len !== 0) { + j = offset + 1; + current = alpha * x[j - 1]; + for (n = len; n--; j += 2) { + next = alpha * x[j + 1]; + x[j] -= current + next; + if (n--) { + j += 2; + current = alpha * x[j + 1]; + x[j] -= current + next; + } else { + break; + } + } + } + }; + + return IrreversibleTransform; + })(); + + // Section 3.8.1 Reversible 5-3 filter + var ReversibleTransform = (function ReversibleTransformClosure() { + function ReversibleTransform() { + Transform.call(this); + } + + ReversibleTransform.prototype = Object.create(Transform.prototype); + ReversibleTransform.prototype.filter = + function reversibleTransformFilter(x, offset, length) { + var len = length >> 1; + offset = offset | 0; + var j, n; + + for (j = offset, n = len + 1; n--; j += 2) { + x[j] -= (x[j - 1] + x[j + 1] + 2) >> 2; + } + + for (j = offset + 1, n = len; n--; j += 2) { + x[j] += (x[j - 1] + x[j + 1]) >> 1; + } + }; + + return ReversibleTransform; + })(); + + return JpxImage; +})(); + + +var Jbig2Image = (function Jbig2ImageClosure() { + // Utility data structures + function ContextCache() {} + + ContextCache.prototype = { + getContexts: function(id) { + if (id in this) { + return this[id]; + } + return (this[id] = new Int8Array(1 << 16)); + } + }; + + function DecodingContext(data, start, end) { + this.data = data; + this.start = start; + this.end = end; + } + + DecodingContext.prototype = { + get decoder() { + var decoder = new ArithmeticDecoder(this.data, this.start, this.end); + return shadow(this, 'decoder', decoder); + }, + get contextCache() { + var cache = new ContextCache(); + return shadow(this, 'contextCache', cache); + } + }; + + // Annex A. Arithmetic Integer Decoding Procedure + // A.2 Procedure for decoding values + function decodeInteger(contextCache, procedure, decoder) { + var contexts = contextCache.getContexts(procedure); + var prev = 1; + + function readBits(length) { + var v = 0; + for (var i = 0; i < length; i++) { + var bit = decoder.readBit(contexts, prev); + prev = (prev < 256 ? (prev << 1) | bit : + (((prev << 1) | bit) & 511) | 256); + v = (v << 1) | bit; + } + return v >>> 0; + } + + var sign = readBits(1); + var value = readBits(1) ? + (readBits(1) ? + (readBits(1) ? + (readBits(1) ? + (readBits(1) ? + (readBits(32) + 4436) : + readBits(12) + 340) : + readBits(8) + 84) : + readBits(6) + 20) : + readBits(4) + 4) : + readBits(2); + return (sign === 0 ? value : (value > 0 ? -value : null)); + } + + // A.3 The IAID decoding procedure + function decodeIAID(contextCache, decoder, codeLength) { + var contexts = contextCache.getContexts('IAID'); + + var prev = 1; + for (var i = 0; i < codeLength; i++) { + var bit = decoder.readBit(contexts, prev); + prev = (prev << 1) | bit; + } + if (codeLength < 31) { + return prev & ((1 << codeLength) - 1); + } + return prev & 0x7FFFFFFF; + } + + // 7.3 Segment types + var SegmentTypes = [ + 'SymbolDictionary', null, null, null, 'IntermediateTextRegion', null, + 'ImmediateTextRegion', 'ImmediateLosslessTextRegion', null, null, null, + null, null, null, null, null, 'patternDictionary', null, null, null, + 'IntermediateHalftoneRegion', null, 'ImmediateHalftoneRegion', + 'ImmediateLosslessHalftoneRegion', null, null, null, null, null, null, null, + null, null, null, null, null, 'IntermediateGenericRegion', null, + 'ImmediateGenericRegion', 'ImmediateLosslessGenericRegion', + 'IntermediateGenericRefinementRegion', null, + 'ImmediateGenericRefinementRegion', + 'ImmediateLosslessGenericRefinementRegion', null, null, null, null, + 'PageInformation', 'EndOfPage', 'EndOfStripe', 'EndOfFile', 'Profiles', + 'Tables', null, null, null, null, null, null, null, null, + 'Extension' + ]; + + var CodingTemplates = [ + [{x: -1, y: -2}, {x: 0, y: -2}, {x: 1, y: -2}, {x: -2, y: -1}, + {x: -1, y: -1}, {x: 0, y: -1}, {x: 1, y: -1}, {x: 2, y: -1}, + {x: -4, y: 0}, {x: -3, y: 0}, {x: -2, y: 0}, {x: -1, y: 0}], + [{x: -1, y: -2}, {x: 0, y: -2}, {x: 1, y: -2}, {x: 2, y: -2}, + {x: -2, y: -1}, {x: -1, y: -1}, {x: 0, y: -1}, {x: 1, y: -1}, + {x: 2, y: -1}, {x: -3, y: 0}, {x: -2, y: 0}, {x: -1, y: 0}], + [{x: -1, y: -2}, {x: 0, y: -2}, {x: 1, y: -2}, {x: -2, y: -1}, + {x: -1, y: -1}, {x: 0, y: -1}, {x: 1, y: -1}, {x: -2, y: 0}, + {x: -1, y: 0}], + [{x: -3, y: -1}, {x: -2, y: -1}, {x: -1, y: -1}, {x: 0, y: -1}, + {x: 1, y: -1}, {x: -4, y: 0}, {x: -3, y: 0}, {x: -2, y: 0}, {x: -1, y: 0}] + ]; + + var RefinementTemplates = [ + { + coding: [{x: 0, y: -1}, {x: 1, y: -1}, {x: -1, y: 0}], + reference: [{x: 0, y: -1}, {x: 1, y: -1}, {x: -1, y: 0}, {x: 0, y: 0}, + {x: 1, y: 0}, {x: -1, y: 1}, {x: 0, y: 1}, {x: 1, y: 1}] + }, + { + coding: [{x: -1, y: -1}, {x: 0, y: -1}, {x: 1, y: -1}, {x: -1, y: 0}], + reference: [{x: 0, y: -1}, {x: -1, y: 0}, {x: 0, y: 0}, {x: 1, y: 0}, + {x: 0, y: 1}, {x: 1, y: 1}] + } + ]; + + // See 6.2.5.7 Decoding the bitmap. + var ReusedContexts = [ + 0x9B25, // 10011 0110010 0101 + 0x0795, // 0011 110010 101 + 0x00E5, // 001 11001 01 + 0x0195 // 011001 0101 + ]; + + var RefinementReusedContexts = [ + 0x0020, // '000' + '0' (coding) + '00010000' + '0' (reference) + 0x0008 // '0000' + '001000' + ]; + + function decodeBitmapTemplate0(width, height, decodingContext) { + var decoder = decodingContext.decoder; + var contexts = decodingContext.contextCache.getContexts('GB'); + var contextLabel, i, j, pixel, row, row1, row2, bitmap = []; + + // ...ooooo.... + // ..ooooooo... Context template for current pixel (X) + // .ooooX...... (concatenate values of 'o'-pixels to get contextLabel) + var OLD_PIXEL_MASK = 0x7BF7; // 01111 0111111 0111 + + for (i = 0; i < height; i++) { + row = bitmap[i] = new Uint8Array(width); + row1 = (i < 1) ? row : bitmap[i - 1]; + row2 = (i < 2) ? row : bitmap[i - 2]; + + // At the beginning of each row: + // Fill contextLabel with pixels that are above/right of (X) + contextLabel = (row2[0] << 13) | (row2[1] << 12) | (row2[2] << 11) | + (row1[0] << 7) | (row1[1] << 6) | (row1[2] << 5) | + (row1[3] << 4); + + for (j = 0; j < width; j++) { + row[j] = pixel = decoder.readBit(contexts, contextLabel); + + // At each pixel: Clear contextLabel pixels that are shifted + // out of the context, then add new ones. + contextLabel = ((contextLabel & OLD_PIXEL_MASK) << 1) | + (j + 3 < width ? row2[j + 3] << 11 : 0) | + (j + 4 < width ? row1[j + 4] << 4 : 0) | pixel; + } + } + + return bitmap; + } + + // 6.2 Generic Region Decoding Procedure + function decodeBitmap(mmr, width, height, templateIndex, prediction, skip, at, + decodingContext) { + if (mmr) { + error('JBIG2 error: MMR encoding is not supported'); + } + + // Use optimized version for the most common case + if (templateIndex === 0 && !skip && !prediction && at.length === 4 && + at[0].x === 3 && at[0].y === -1 && at[1].x === -3 && at[1].y === -1 && + at[2].x === 2 && at[2].y === -2 && at[3].x === -2 && at[3].y === -2) { + return decodeBitmapTemplate0(width, height, decodingContext); + } + + var useskip = !!skip; + var template = CodingTemplates[templateIndex].concat(at); + + // Sorting is non-standard, and it is not required. But sorting increases + // the number of template bits that can be reused from the previous + // contextLabel in the main loop. + template.sort(function (a, b) { + return (a.y - b.y) || (a.x - b.x); + }); + + var templateLength = template.length; + var templateX = new Int8Array(templateLength); + var templateY = new Int8Array(templateLength); + var changingTemplateEntries = []; + var reuseMask = 0, minX = 0, maxX = 0, minY = 0; + var c, k; + + for (k = 0; k < templateLength; k++) { + templateX[k] = template[k].x; + templateY[k] = template[k].y; + minX = Math.min(minX, template[k].x); + maxX = Math.max(maxX, template[k].x); + minY = Math.min(minY, template[k].y); + // Check if the template pixel appears in two consecutive context labels, + // so it can be reused. Otherwise, we add it to the list of changing + // template entries. + if (k < templateLength - 1 && + template[k].y === template[k + 1].y && + template[k].x === template[k + 1].x - 1) { + reuseMask |= 1 << (templateLength - 1 - k); + } else { + changingTemplateEntries.push(k); + } + } + var changingEntriesLength = changingTemplateEntries.length; + + var changingTemplateX = new Int8Array(changingEntriesLength); + var changingTemplateY = new Int8Array(changingEntriesLength); + var changingTemplateBit = new Uint16Array(changingEntriesLength); + for (c = 0; c < changingEntriesLength; c++) { + k = changingTemplateEntries[c]; + changingTemplateX[c] = template[k].x; + changingTemplateY[c] = template[k].y; + changingTemplateBit[c] = 1 << (templateLength - 1 - k); + } + + // Get the safe bounding box edges from the width, height, minX, maxX, minY + var sbb_left = -minX; + var sbb_top = -minY; + var sbb_right = width - maxX; + + var pseudoPixelContext = ReusedContexts[templateIndex]; + var row = new Uint8Array(width); + var bitmap = []; + + var decoder = decodingContext.decoder; + var contexts = decodingContext.contextCache.getContexts('GB'); + + var ltp = 0, j, i0, j0, contextLabel = 0, bit, shift; + for (var i = 0; i < height; i++) { + if (prediction) { + var sltp = decoder.readBit(contexts, pseudoPixelContext); + ltp ^= sltp; + if (ltp) { + bitmap.push(row); // duplicate previous row + continue; + } + } + row = new Uint8Array(row); + bitmap.push(row); + for (j = 0; j < width; j++) { + if (useskip && skip[i][j]) { + row[j] = 0; + continue; + } + // Are we in the middle of a scanline, so we can reuse contextLabel + // bits? + if (j >= sbb_left && j < sbb_right && i >= sbb_top) { + // If yes, we can just shift the bits that are reusable and only + // fetch the remaining ones. + contextLabel = (contextLabel << 1) & reuseMask; + for (k = 0; k < changingEntriesLength; k++) { + i0 = i + changingTemplateY[k]; + j0 = j + changingTemplateX[k]; + bit = bitmap[i0][j0]; + if (bit) { + bit = changingTemplateBit[k]; + contextLabel |= bit; + } + } + } else { + // compute the contextLabel from scratch + contextLabel = 0; + shift = templateLength - 1; + for (k = 0; k < templateLength; k++, shift--) { + j0 = j + templateX[k]; + if (j0 >= 0 && j0 < width) { + i0 = i + templateY[k]; + if (i0 >= 0) { + bit = bitmap[i0][j0]; + if (bit) { + contextLabel |= bit << shift; + } + } + } + } + } + var pixel = decoder.readBit(contexts, contextLabel); + row[j] = pixel; + } + } + return bitmap; + } + + // 6.3.2 Generic Refinement Region Decoding Procedure + function decodeRefinement(width, height, templateIndex, referenceBitmap, + offsetX, offsetY, prediction, at, + decodingContext) { + var codingTemplate = RefinementTemplates[templateIndex].coding; + if (templateIndex === 0) { + codingTemplate = codingTemplate.concat([at[0]]); + } + var codingTemplateLength = codingTemplate.length; + var codingTemplateX = new Int32Array(codingTemplateLength); + var codingTemplateY = new Int32Array(codingTemplateLength); + var k; + for (k = 0; k < codingTemplateLength; k++) { + codingTemplateX[k] = codingTemplate[k].x; + codingTemplateY[k] = codingTemplate[k].y; + } + + var referenceTemplate = RefinementTemplates[templateIndex].reference; + if (templateIndex === 0) { + referenceTemplate = referenceTemplate.concat([at[1]]); + } + var referenceTemplateLength = referenceTemplate.length; + var referenceTemplateX = new Int32Array(referenceTemplateLength); + var referenceTemplateY = new Int32Array(referenceTemplateLength); + for (k = 0; k < referenceTemplateLength; k++) { + referenceTemplateX[k] = referenceTemplate[k].x; + referenceTemplateY[k] = referenceTemplate[k].y; + } + var referenceWidth = referenceBitmap[0].length; + var referenceHeight = referenceBitmap.length; + + var pseudoPixelContext = RefinementReusedContexts[templateIndex]; + var bitmap = []; + + var decoder = decodingContext.decoder; + var contexts = decodingContext.contextCache.getContexts('GR'); + + var ltp = 0; + for (var i = 0; i < height; i++) { + if (prediction) { + var sltp = decoder.readBit(contexts, pseudoPixelContext); + ltp ^= sltp; + if (ltp) { + error('JBIG2 error: prediction is not supported'); + } + } + var row = new Uint8Array(width); + bitmap.push(row); + for (var j = 0; j < width; j++) { + var i0, j0; + var contextLabel = 0; + for (k = 0; k < codingTemplateLength; k++) { + i0 = i + codingTemplateY[k]; + j0 = j + codingTemplateX[k]; + if (i0 < 0 || j0 < 0 || j0 >= width) { + contextLabel <<= 1; // out of bound pixel + } else { + contextLabel = (contextLabel << 1) | bitmap[i0][j0]; + } + } + for (k = 0; k < referenceTemplateLength; k++) { + i0 = i + referenceTemplateY[k] + offsetY; + j0 = j + referenceTemplateX[k] + offsetX; + if (i0 < 0 || i0 >= referenceHeight || j0 < 0 || + j0 >= referenceWidth) { + contextLabel <<= 1; // out of bound pixel + } else { + contextLabel = (contextLabel << 1) | referenceBitmap[i0][j0]; + } + } + var pixel = decoder.readBit(contexts, contextLabel); + row[j] = pixel; + } + } + + return bitmap; + } + + // 6.5.5 Decoding the symbol dictionary + function decodeSymbolDictionary(huffman, refinement, symbols, + numberOfNewSymbols, numberOfExportedSymbols, + huffmanTables, templateIndex, at, + refinementTemplateIndex, refinementAt, + decodingContext) { + if (huffman) { + error('JBIG2 error: huffman is not supported'); + } + + var newSymbols = []; + var currentHeight = 0; + var symbolCodeLength = log2(symbols.length + numberOfNewSymbols); + + var decoder = decodingContext.decoder; + var contextCache = decodingContext.contextCache; + + while (newSymbols.length < numberOfNewSymbols) { + var deltaHeight = decodeInteger(contextCache, 'IADH', decoder); // 6.5.6 + currentHeight += deltaHeight; + var currentWidth = 0; + var totalWidth = 0; + while (true) { + var deltaWidth = decodeInteger(contextCache, 'IADW', decoder); // 6.5.7 + if (deltaWidth === null) { + break; // OOB + } + currentWidth += deltaWidth; + totalWidth += currentWidth; + var bitmap; + if (refinement) { + // 6.5.8.2 Refinement/aggregate-coded symbol bitmap + var numberOfInstances = decodeInteger(contextCache, 'IAAI', decoder); + if (numberOfInstances > 1) { + bitmap = decodeTextRegion(huffman, refinement, + currentWidth, currentHeight, 0, + numberOfInstances, 1, //strip size + symbols.concat(newSymbols), + symbolCodeLength, + 0, //transposed + 0, //ds offset + 1, //top left 7.4.3.1.1 + 0, //OR operator + huffmanTables, + refinementTemplateIndex, refinementAt, + decodingContext); + } else { + var symbolId = decodeIAID(contextCache, decoder, symbolCodeLength); + var rdx = decodeInteger(contextCache, 'IARDX', decoder); // 6.4.11.3 + var rdy = decodeInteger(contextCache, 'IARDY', decoder); // 6.4.11.4 + var symbol = (symbolId < symbols.length ? symbols[symbolId] : + newSymbols[symbolId - symbols.length]); + bitmap = decodeRefinement(currentWidth, currentHeight, + refinementTemplateIndex, symbol, rdx, rdy, false, refinementAt, + decodingContext); + } + } else { + // 6.5.8.1 Direct-coded symbol bitmap + bitmap = decodeBitmap(false, currentWidth, currentHeight, + templateIndex, false, null, at, decodingContext); + } + newSymbols.push(bitmap); + } + } + // 6.5.10 Exported symbols + var exportedSymbols = []; + var flags = [], currentFlag = false; + var totalSymbolsLength = symbols.length + numberOfNewSymbols; + while (flags.length < totalSymbolsLength) { + var runLength = decodeInteger(contextCache, 'IAEX', decoder); + while (runLength--) { + flags.push(currentFlag); + } + currentFlag = !currentFlag; + } + for (var i = 0, ii = symbols.length; i < ii; i++) { + if (flags[i]) { + exportedSymbols.push(symbols[i]); + } + } + for (var j = 0; j < numberOfNewSymbols; i++, j++) { + if (flags[i]) { + exportedSymbols.push(newSymbols[j]); + } + } + return exportedSymbols; + } + + function decodeTextRegion(huffman, refinement, width, height, + defaultPixelValue, numberOfSymbolInstances, + stripSize, inputSymbols, symbolCodeLength, + transposed, dsOffset, referenceCorner, + combinationOperator, huffmanTables, + refinementTemplateIndex, refinementAt, + decodingContext) { + if (huffman) { + error('JBIG2 error: huffman is not supported'); + } + + // Prepare bitmap + var bitmap = []; + var i, row; + for (i = 0; i < height; i++) { + row = new Uint8Array(width); + if (defaultPixelValue) { + for (var j = 0; j < width; j++) { + row[j] = defaultPixelValue; + } + } + bitmap.push(row); + } + + var decoder = decodingContext.decoder; + var contextCache = decodingContext.contextCache; + var stripT = -decodeInteger(contextCache, 'IADT', decoder); // 6.4.6 + var firstS = 0; + i = 0; + while (i < numberOfSymbolInstances) { + var deltaT = decodeInteger(contextCache, 'IADT', decoder); // 6.4.6 + stripT += deltaT; + + var deltaFirstS = decodeInteger(contextCache, 'IAFS', decoder); // 6.4.7 + firstS += deltaFirstS; + var currentS = firstS; + do { + var currentT = (stripSize === 1 ? 0 : + decodeInteger(contextCache, 'IAIT', decoder)); // 6.4.9 + var t = stripSize * stripT + currentT; + var symbolId = decodeIAID(contextCache, decoder, symbolCodeLength); + var applyRefinement = (refinement && + decodeInteger(contextCache, 'IARI', decoder)); + var symbolBitmap = inputSymbols[symbolId]; + var symbolWidth = symbolBitmap[0].length; + var symbolHeight = symbolBitmap.length; + if (applyRefinement) { + var rdw = decodeInteger(contextCache, 'IARDW', decoder); // 6.4.11.1 + var rdh = decodeInteger(contextCache, 'IARDH', decoder); // 6.4.11.2 + var rdx = decodeInteger(contextCache, 'IARDX', decoder); // 6.4.11.3 + var rdy = decodeInteger(contextCache, 'IARDY', decoder); // 6.4.11.4 + symbolWidth += rdw; + symbolHeight += rdh; + symbolBitmap = decodeRefinement(symbolWidth, symbolHeight, + refinementTemplateIndex, symbolBitmap, (rdw >> 1) + rdx, + (rdh >> 1) + rdy, false, refinementAt, + decodingContext); + } + var offsetT = t - ((referenceCorner & 1) ? 0 : symbolHeight); + var offsetS = currentS - ((referenceCorner & 2) ? symbolWidth : 0); + var s2, t2, symbolRow; + if (transposed) { + // Place Symbol Bitmap from T1,S1 + for (s2 = 0; s2 < symbolHeight; s2++) { + row = bitmap[offsetS + s2]; + if (!row) { + continue; + } + symbolRow = symbolBitmap[s2]; + // To ignore Parts of Symbol bitmap which goes + // outside bitmap region + var maxWidth = Math.min(width - offsetT, symbolWidth); + switch (combinationOperator) { + case 0: // OR + for (t2 = 0; t2 < maxWidth; t2++) { + row[offsetT + t2] |= symbolRow[t2]; + } + break; + case 2: // XOR + for (t2 = 0; t2 < maxWidth; t2++) { + row[offsetT + t2] ^= symbolRow[t2]; + } + break; + default: + error('JBIG2 error: operator ' + combinationOperator + + ' is not supported'); + } + } + currentS += symbolHeight - 1; + } else { + for (t2 = 0; t2 < symbolHeight; t2++) { + row = bitmap[offsetT + t2]; + if (!row) { + continue; + } + symbolRow = symbolBitmap[t2]; + switch (combinationOperator) { + case 0: // OR + for (s2 = 0; s2 < symbolWidth; s2++) { + row[offsetS + s2] |= symbolRow[s2]; + } + break; + case 2: // XOR + for (s2 = 0; s2 < symbolWidth; s2++) { + row[offsetS + s2] ^= symbolRow[s2]; + } + break; + default: + error('JBIG2 error: operator ' + combinationOperator + + ' is not supported'); + } + } + currentS += symbolWidth - 1; + } + i++; + var deltaS = decodeInteger(contextCache, 'IADS', decoder); // 6.4.8 + if (deltaS === null) { + break; // OOB + } + currentS += deltaS + dsOffset; + } while (true); + } + return bitmap; + } + + function readSegmentHeader(data, start) { + var segmentHeader = {}; + segmentHeader.number = readUint32(data, start); + var flags = data[start + 4]; + var segmentType = flags & 0x3F; + if (!SegmentTypes[segmentType]) { + error('JBIG2 error: invalid segment type: ' + segmentType); + } + segmentHeader.type = segmentType; + segmentHeader.typeName = SegmentTypes[segmentType]; + segmentHeader.deferredNonRetain = !!(flags & 0x80); + + var pageAssociationFieldSize = !!(flags & 0x40); + var referredFlags = data[start + 5]; + var referredToCount = (referredFlags >> 5) & 7; + var retainBits = [referredFlags & 31]; + var position = start + 6; + if (referredFlags === 7) { + referredToCount = readUint32(data, position - 1) & 0x1FFFFFFF; + position += 3; + var bytes = (referredToCount + 7) >> 3; + retainBits[0] = data[position++]; + while (--bytes > 0) { + retainBits.push(data[position++]); + } + } else if (referredFlags === 5 || referredFlags === 6) { + error('JBIG2 error: invalid referred-to flags'); + } + + segmentHeader.retainBits = retainBits; + var referredToSegmentNumberSize = (segmentHeader.number <= 256 ? 1 : + (segmentHeader.number <= 65536 ? 2 : 4)); + var referredTo = []; + var i, ii; + for (i = 0; i < referredToCount; i++) { + var number = (referredToSegmentNumberSize === 1 ? data[position] : + (referredToSegmentNumberSize === 2 ? readUint16(data, position) : + readUint32(data, position))); + referredTo.push(number); + position += referredToSegmentNumberSize; + } + segmentHeader.referredTo = referredTo; + if (!pageAssociationFieldSize) { + segmentHeader.pageAssociation = data[position++]; + } else { + segmentHeader.pageAssociation = readUint32(data, position); + position += 4; + } + segmentHeader.length = readUint32(data, position); + position += 4; + + if (segmentHeader.length === 0xFFFFFFFF) { + // 7.2.7 Segment data length, unknown segment length + if (segmentType === 38) { // ImmediateGenericRegion + var genericRegionInfo = readRegionSegmentInformation(data, position); + var genericRegionSegmentFlags = data[position + + RegionSegmentInformationFieldLength]; + var genericRegionMmr = !!(genericRegionSegmentFlags & 1); + // searching for the segment end + var searchPatternLength = 6; + var searchPattern = new Uint8Array(searchPatternLength); + if (!genericRegionMmr) { + searchPattern[0] = 0xFF; + searchPattern[1] = 0xAC; + } + searchPattern[2] = (genericRegionInfo.height >>> 24) & 0xFF; + searchPattern[3] = (genericRegionInfo.height >> 16) & 0xFF; + searchPattern[4] = (genericRegionInfo.height >> 8) & 0xFF; + searchPattern[5] = genericRegionInfo.height & 0xFF; + for (i = position, ii = data.length; i < ii; i++) { + var j = 0; + while (j < searchPatternLength && searchPattern[j] === data[i + j]) { + j++; + } + if (j === searchPatternLength) { + segmentHeader.length = i + searchPatternLength; + break; + } + } + if (segmentHeader.length === 0xFFFFFFFF) { + error('JBIG2 error: segment end was not found'); + } + } else { + error('JBIG2 error: invalid unknown segment length'); + } + } + segmentHeader.headerEnd = position; + return segmentHeader; + } + + function readSegments(header, data, start, end) { + var segments = []; + var position = start; + while (position < end) { + var segmentHeader = readSegmentHeader(data, position); + position = segmentHeader.headerEnd; + var segment = { + header: segmentHeader, + data: data + }; + if (!header.randomAccess) { + segment.start = position; + position += segmentHeader.length; + segment.end = position; + } + segments.push(segment); + if (segmentHeader.type === 51) { + break; // end of file is found + } + } + if (header.randomAccess) { + for (var i = 0, ii = segments.length; i < ii; i++) { + segments[i].start = position; + position += segments[i].header.length; + segments[i].end = position; + } + } + return segments; + } + + // 7.4.1 Region segment information field + function readRegionSegmentInformation(data, start) { + return { + width: readUint32(data, start), + height: readUint32(data, start + 4), + x: readUint32(data, start + 8), + y: readUint32(data, start + 12), + combinationOperator: data[start + 16] & 7 + }; + } + var RegionSegmentInformationFieldLength = 17; + + function processSegment(segment, visitor) { + var header = segment.header; + + var data = segment.data, position = segment.start, end = segment.end; + var args, at, i, atLength; + switch (header.type) { + case 0: // SymbolDictionary + // 7.4.2 Symbol dictionary segment syntax + var dictionary = {}; + var dictionaryFlags = readUint16(data, position); // 7.4.2.1.1 + dictionary.huffman = !!(dictionaryFlags & 1); + dictionary.refinement = !!(dictionaryFlags & 2); + dictionary.huffmanDHSelector = (dictionaryFlags >> 2) & 3; + dictionary.huffmanDWSelector = (dictionaryFlags >> 4) & 3; + dictionary.bitmapSizeSelector = (dictionaryFlags >> 6) & 1; + dictionary.aggregationInstancesSelector = (dictionaryFlags >> 7) & 1; + dictionary.bitmapCodingContextUsed = !!(dictionaryFlags & 256); + dictionary.bitmapCodingContextRetained = !!(dictionaryFlags & 512); + dictionary.template = (dictionaryFlags >> 10) & 3; + dictionary.refinementTemplate = (dictionaryFlags >> 12) & 1; + position += 2; + if (!dictionary.huffman) { + atLength = dictionary.template === 0 ? 4 : 1; + at = []; + for (i = 0; i < atLength; i++) { + at.push({ + x: readInt8(data, position), + y: readInt8(data, position + 1) + }); + position += 2; + } + dictionary.at = at; + } + if (dictionary.refinement && !dictionary.refinementTemplate) { + at = []; + for (i = 0; i < 2; i++) { + at.push({ + x: readInt8(data, position), + y: readInt8(data, position + 1) + }); + position += 2; + } + dictionary.refinementAt = at; + } + dictionary.numberOfExportedSymbols = readUint32(data, position); + position += 4; + dictionary.numberOfNewSymbols = readUint32(data, position); + position += 4; + args = [dictionary, header.number, header.referredTo, + data, position, end]; + break; + case 6: // ImmediateTextRegion + case 7: // ImmediateLosslessTextRegion + var textRegion = {}; + textRegion.info = readRegionSegmentInformation(data, position); + position += RegionSegmentInformationFieldLength; + var textRegionSegmentFlags = readUint16(data, position); + position += 2; + textRegion.huffman = !!(textRegionSegmentFlags & 1); + textRegion.refinement = !!(textRegionSegmentFlags & 2); + textRegion.stripSize = 1 << ((textRegionSegmentFlags >> 2) & 3); + textRegion.referenceCorner = (textRegionSegmentFlags >> 4) & 3; + textRegion.transposed = !!(textRegionSegmentFlags & 64); + textRegion.combinationOperator = (textRegionSegmentFlags >> 7) & 3; + textRegion.defaultPixelValue = (textRegionSegmentFlags >> 9) & 1; + textRegion.dsOffset = (textRegionSegmentFlags << 17) >> 27; + textRegion.refinementTemplate = (textRegionSegmentFlags >> 15) & 1; + if (textRegion.huffman) { + var textRegionHuffmanFlags = readUint16(data, position); + position += 2; + textRegion.huffmanFS = (textRegionHuffmanFlags) & 3; + textRegion.huffmanDS = (textRegionHuffmanFlags >> 2) & 3; + textRegion.huffmanDT = (textRegionHuffmanFlags >> 4) & 3; + textRegion.huffmanRefinementDW = (textRegionHuffmanFlags >> 6) & 3; + textRegion.huffmanRefinementDH = (textRegionHuffmanFlags >> 8) & 3; + textRegion.huffmanRefinementDX = (textRegionHuffmanFlags >> 10) & 3; + textRegion.huffmanRefinementDY = (textRegionHuffmanFlags >> 12) & 3; + textRegion.huffmanRefinementSizeSelector = + !!(textRegionHuffmanFlags & 14); + } + if (textRegion.refinement && !textRegion.refinementTemplate) { + at = []; + for (i = 0; i < 2; i++) { + at.push({ + x: readInt8(data, position), + y: readInt8(data, position + 1) + }); + position += 2; + } + textRegion.refinementAt = at; + } + textRegion.numberOfSymbolInstances = readUint32(data, position); + position += 4; + // TODO 7.4.3.1.7 Symbol ID Huffman table decoding + if (textRegion.huffman) { + error('JBIG2 error: huffman is not supported'); + } + args = [textRegion, header.referredTo, data, position, end]; + break; + case 38: // ImmediateGenericRegion + case 39: // ImmediateLosslessGenericRegion + var genericRegion = {}; + genericRegion.info = readRegionSegmentInformation(data, position); + position += RegionSegmentInformationFieldLength; + var genericRegionSegmentFlags = data[position++]; + genericRegion.mmr = !!(genericRegionSegmentFlags & 1); + genericRegion.template = (genericRegionSegmentFlags >> 1) & 3; + genericRegion.prediction = !!(genericRegionSegmentFlags & 8); + if (!genericRegion.mmr) { + atLength = genericRegion.template === 0 ? 4 : 1; + at = []; + for (i = 0; i < atLength; i++) { + at.push({ + x: readInt8(data, position), + y: readInt8(data, position + 1) + }); + position += 2; + } + genericRegion.at = at; + } + args = [genericRegion, data, position, end]; + break; + case 48: // PageInformation + var pageInfo = { + width: readUint32(data, position), + height: readUint32(data, position + 4), + resolutionX: readUint32(data, position + 8), + resolutionY: readUint32(data, position + 12) + }; + if (pageInfo.height === 0xFFFFFFFF) { + delete pageInfo.height; + } + var pageSegmentFlags = data[position + 16]; + var pageStripingInformatiom = readUint16(data, position + 17); + pageInfo.lossless = !!(pageSegmentFlags & 1); + pageInfo.refinement = !!(pageSegmentFlags & 2); + pageInfo.defaultPixelValue = (pageSegmentFlags >> 2) & 1; + pageInfo.combinationOperator = (pageSegmentFlags >> 3) & 3; + pageInfo.requiresBuffer = !!(pageSegmentFlags & 32); + pageInfo.combinationOperatorOverride = !!(pageSegmentFlags & 64); + args = [pageInfo]; + break; + case 49: // EndOfPage + break; + case 50: // EndOfStripe + break; + case 51: // EndOfFile + break; + case 62: // 7.4.15 defines 2 extension types which + // are comments and can be ignored. + break; + default: + error('JBIG2 error: segment type ' + header.typeName + '(' + + header.type + ') is not implemented'); + } + var callbackName = 'on' + header.typeName; + if (callbackName in visitor) { + visitor[callbackName].apply(visitor, args); + } + } + + function processSegments(segments, visitor) { + for (var i = 0, ii = segments.length; i < ii; i++) { + processSegment(segments[i], visitor); + } + } + + function parseJbig2(data, start, end) { + var position = start; + if (data[position] !== 0x97 || data[position + 1] !== 0x4A || + data[position + 2] !== 0x42 || data[position + 3] !== 0x32 || + data[position + 4] !== 0x0D || data[position + 5] !== 0x0A || + data[position + 6] !== 0x1A || data[position + 7] !== 0x0A) { + error('JBIG2 error: invalid header'); + } + var header = {}; + position += 8; + var flags = data[position++]; + header.randomAccess = !(flags & 1); + if (!(flags & 2)) { + header.numberOfPages = readUint32(data, position); + position += 4; + } + var segments = readSegments(header, data, position, end); + error('Not implemented'); + // processSegments(segments, new SimpleSegmentVisitor()); + } + + function parseJbig2Chunks(chunks) { + var visitor = new SimpleSegmentVisitor(); + for (var i = 0, ii = chunks.length; i < ii; i++) { + var chunk = chunks[i]; + var segments = readSegments({}, chunk.data, chunk.start, chunk.end); + processSegments(segments, visitor); + } + return visitor.buffer; + } + + function SimpleSegmentVisitor() {} + + SimpleSegmentVisitor.prototype = { + onPageInformation: function SimpleSegmentVisitor_onPageInformation(info) { + this.currentPageInfo = info; + var rowSize = (info.width + 7) >> 3; + var buffer = new Uint8Array(rowSize * info.height); + // The contents of ArrayBuffers are initialized to 0. + // Fill the buffer with 0xFF only if info.defaultPixelValue is set + if (info.defaultPixelValue) { + for (var i = 0, ii = buffer.length; i < ii; i++) { + buffer[i] = 0xFF; + } + } + this.buffer = buffer; + }, + drawBitmap: function SimpleSegmentVisitor_drawBitmap(regionInfo, bitmap) { + var pageInfo = this.currentPageInfo; + var width = regionInfo.width, height = regionInfo.height; + var rowSize = (pageInfo.width + 7) >> 3; + var combinationOperator = pageInfo.combinationOperatorOverride ? + regionInfo.combinationOperator : pageInfo.combinationOperator; + var buffer = this.buffer; + var mask0 = 128 >> (regionInfo.x & 7); + var offset0 = regionInfo.y * rowSize + (regionInfo.x >> 3); + var i, j, mask, offset; + switch (combinationOperator) { + case 0: // OR + for (i = 0; i < height; i++) { + mask = mask0; + offset = offset0; + for (j = 0; j < width; j++) { + if (bitmap[i][j]) { + buffer[offset] |= mask; + } + mask >>= 1; + if (!mask) { + mask = 128; + offset++; + } + } + offset0 += rowSize; + } + break; + case 2: // XOR + for (i = 0; i < height; i++) { + mask = mask0; + offset = offset0; + for (j = 0; j < width; j++) { + if (bitmap[i][j]) { + buffer[offset] ^= mask; + } + mask >>= 1; + if (!mask) { + mask = 128; + offset++; + } + } + offset0 += rowSize; + } + break; + default: + error('JBIG2 error: operator ' + combinationOperator + + ' is not supported'); + } + }, + onImmediateGenericRegion: + function SimpleSegmentVisitor_onImmediateGenericRegion(region, data, + start, end) { + var regionInfo = region.info; + var decodingContext = new DecodingContext(data, start, end); + var bitmap = decodeBitmap(region.mmr, regionInfo.width, regionInfo.height, + region.template, region.prediction, null, + region.at, decodingContext); + this.drawBitmap(regionInfo, bitmap); + }, + onImmediateLosslessGenericRegion: + function SimpleSegmentVisitor_onImmediateLosslessGenericRegion() { + this.onImmediateGenericRegion.apply(this, arguments); + }, + onSymbolDictionary: + function SimpleSegmentVisitor_onSymbolDictionary(dictionary, + currentSegment, + referredSegments, + data, start, end) { + var huffmanTables; + if (dictionary.huffman) { + error('JBIG2 error: huffman is not supported'); + } + + // Combines exported symbols from all referred segments + var symbols = this.symbols; + if (!symbols) { + this.symbols = symbols = {}; + } + + var inputSymbols = []; + for (var i = 0, ii = referredSegments.length; i < ii; i++) { + inputSymbols = inputSymbols.concat(symbols[referredSegments[i]]); + } + + var decodingContext = new DecodingContext(data, start, end); + symbols[currentSegment] = decodeSymbolDictionary(dictionary.huffman, + dictionary.refinement, inputSymbols, dictionary.numberOfNewSymbols, + dictionary.numberOfExportedSymbols, huffmanTables, + dictionary.template, dictionary.at, + dictionary.refinementTemplate, dictionary.refinementAt, + decodingContext); + }, + onImmediateTextRegion: + function SimpleSegmentVisitor_onImmediateTextRegion(region, + referredSegments, + data, start, end) { + var regionInfo = region.info; + var huffmanTables; + + // Combines exported symbols from all referred segments + var symbols = this.symbols; + var inputSymbols = []; + for (var i = 0, ii = referredSegments.length; i < ii; i++) { + inputSymbols = inputSymbols.concat(symbols[referredSegments[i]]); + } + var symbolCodeLength = log2(inputSymbols.length); + + var decodingContext = new DecodingContext(data, start, end); + var bitmap = decodeTextRegion(region.huffman, region.refinement, + regionInfo.width, regionInfo.height, region.defaultPixelValue, + region.numberOfSymbolInstances, region.stripSize, inputSymbols, + symbolCodeLength, region.transposed, region.dsOffset, + region.referenceCorner, region.combinationOperator, huffmanTables, + region.refinementTemplate, region.refinementAt, decodingContext); + this.drawBitmap(regionInfo, bitmap); + }, + onImmediateLosslessTextRegion: + function SimpleSegmentVisitor_onImmediateLosslessTextRegion() { + this.onImmediateTextRegion.apply(this, arguments); + } + }; + + function Jbig2Image() {} + + Jbig2Image.prototype = { + parseChunks: function Jbig2Image_parseChunks(chunks) { + return parseJbig2Chunks(chunks); + } + }; + + return Jbig2Image; +})(); + + +var bidi = PDFJS.bidi = (function bidiClosure() { + // Character types for symbols from 0000 to 00FF. + var baseTypes = [ + 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'S', 'B', 'S', 'WS', + 'B', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', + 'BN', 'BN', 'B', 'B', 'B', 'S', 'WS', 'ON', 'ON', 'ET', 'ET', 'ET', 'ON', + 'ON', 'ON', 'ON', 'ON', 'ON', 'CS', 'ON', 'CS', 'ON', 'EN', 'EN', 'EN', + 'EN', 'EN', 'EN', 'EN', 'EN', 'EN', 'EN', 'ON', 'ON', 'ON', 'ON', 'ON', + 'ON', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', + 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'ON', 'ON', + 'ON', 'ON', 'ON', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', + 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', + 'L', 'ON', 'ON', 'ON', 'ON', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'B', 'BN', + 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', + 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', + 'BN', 'CS', 'ON', 'ET', 'ET', 'ET', 'ET', 'ON', 'ON', 'ON', 'ON', 'L', 'ON', + 'ON', 'ON', 'ON', 'ON', 'ET', 'ET', 'EN', 'EN', 'ON', 'L', 'ON', 'ON', 'ON', + 'EN', 'L', 'ON', 'ON', 'ON', 'ON', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', + 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', + 'L', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', + 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', + 'L', 'L', 'L', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L' + ]; + + // Character types for symbols from 0600 to 06FF + var arabicTypes = [ + 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', + 'CS', 'AL', 'ON', 'ON', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'AL', + 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', + 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', + 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', + 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', + 'AL', 'AL', 'AL', 'AL', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', + 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'AL', 'AL', 'AL', 'AL', + 'AL', 'AL', 'AL', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN', + 'AN', 'ET', 'AN', 'AN', 'AL', 'AL', 'AL', 'NSM', 'AL', 'AL', 'AL', 'AL', + 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', + 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', + 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', + 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', + 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', + 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', + 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', + 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', + 'AL', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', + 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'ON', 'NSM', + 'NSM', 'NSM', 'NSM', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', + 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL' + ]; + + function isOdd(i) { + return (i & 1) !== 0; + } + + function isEven(i) { + return (i & 1) === 0; + } + + function findUnequal(arr, start, value) { + for (var j = start, jj = arr.length; j < jj; ++j) { + if (arr[j] !== value) { + return j; + } + } + return j; + } + + function setValues(arr, start, end, value) { + for (var j = start; j < end; ++j) { + arr[j] = value; + } + } + + function reverseValues(arr, start, end) { + for (var i = start, j = end - 1; i < j; ++i, --j) { + var temp = arr[i]; + arr[i] = arr[j]; + arr[j] = temp; + } + } + + function createBidiText(str, isLTR, vertical) { + return { + str: str, + dir: (vertical ? 'ttb' : (isLTR ? 'ltr' : 'rtl')) + }; + } + + // These are used in bidi(), which is called frequently. We re-use them on + // each call to avoid unnecessary allocations. + var chars = []; + var types = []; + + function bidi(str, startLevel, vertical) { + var isLTR = true; + var strLength = str.length; + if (strLength === 0 || vertical) { + return createBidiText(str, isLTR, vertical); + } + + // Get types and fill arrays + chars.length = strLength; + types.length = strLength; + var numBidi = 0; + + var i, ii; + for (i = 0; i < strLength; ++i) { + chars[i] = str.charAt(i); + + var charCode = str.charCodeAt(i); + var charType = 'L'; + if (charCode <= 0x00ff) { + charType = baseTypes[charCode]; + } else if (0x0590 <= charCode && charCode <= 0x05f4) { + charType = 'R'; + } else if (0x0600 <= charCode && charCode <= 0x06ff) { + charType = arabicTypes[charCode & 0xff]; + } else if (0x0700 <= charCode && charCode <= 0x08AC) { + charType = 'AL'; + } + if (charType === 'R' || charType === 'AL' || charType === 'AN') { + numBidi++; + } + types[i] = charType; + } + + // Detect the bidi method + // - If there are no rtl characters then no bidi needed + // - If less than 30% chars are rtl then string is primarily ltr + // - If more than 30% chars are rtl then string is primarily rtl + if (numBidi === 0) { + isLTR = true; + return createBidiText(str, isLTR); + } + + if (startLevel === -1) { + if ((strLength / numBidi) < 0.3) { + isLTR = true; + startLevel = 0; + } else { + isLTR = false; + startLevel = 1; + } + } + + var levels = []; + for (i = 0; i < strLength; ++i) { + levels[i] = startLevel; + } + + /* + X1-X10: skip most of this, since we are NOT doing the embeddings. + */ + var e = (isOdd(startLevel) ? 'R' : 'L'); + var sor = e; + var eor = sor; + + /* + W1. Examine each non-spacing mark (NSM) in the level run, and change the + type of the NSM to the type of the previous character. If the NSM is at the + start of the level run, it will get the type of sor. + */ + var lastType = sor; + for (i = 0; i < strLength; ++i) { + if (types[i] === 'NSM') { + types[i] = lastType; + } else { + lastType = types[i]; + } + } + + /* + W2. Search backwards from each instance of a European number until the + first strong type (R, L, AL, or sor) is found. If an AL is found, change + the type of the European number to Arabic number. + */ + lastType = sor; + var t; + for (i = 0; i < strLength; ++i) { + t = types[i]; + if (t === 'EN') { + types[i] = (lastType === 'AL') ? 'AN' : 'EN'; + } else if (t === 'R' || t === 'L' || t === 'AL') { + lastType = t; + } + } + + /* + W3. Change all ALs to R. + */ + for (i = 0; i < strLength; ++i) { + t = types[i]; + if (t === 'AL') { + types[i] = 'R'; + } + } + + /* + W4. A single European separator between two European numbers changes to a + European number. A single common separator between two numbers of the same + type changes to that type: + */ + for (i = 1; i < strLength - 1; ++i) { + if (types[i] === 'ES' && types[i - 1] === 'EN' && types[i + 1] === 'EN') { + types[i] = 'EN'; + } + if (types[i] === 'CS' && + (types[i - 1] === 'EN' || types[i - 1] === 'AN') && + types[i + 1] === types[i - 1]) { + types[i] = types[i - 1]; + } + } + + /* + W5. A sequence of European terminators adjacent to European numbers changes + to all European numbers: + */ + for (i = 0; i < strLength; ++i) { + if (types[i] === 'EN') { + // do before + var j; + for (j = i - 1; j >= 0; --j) { + if (types[j] !== 'ET') { + break; + } + types[j] = 'EN'; + } + // do after + for (j = i + 1; j < strLength; --j) { + if (types[j] !== 'ET') { + break; + } + types[j] = 'EN'; + } + } + } + + /* + W6. Otherwise, separators and terminators change to Other Neutral: + */ + for (i = 0; i < strLength; ++i) { + t = types[i]; + if (t === 'WS' || t === 'ES' || t === 'ET' || t === 'CS') { + types[i] = 'ON'; + } + } + + /* + W7. Search backwards from each instance of a European number until the + first strong type (R, L, or sor) is found. If an L is found, then change + the type of the European number to L. + */ + lastType = sor; + for (i = 0; i < strLength; ++i) { + t = types[i]; + if (t === 'EN') { + types[i] = ((lastType === 'L') ? 'L' : 'EN'); + } else if (t === 'R' || t === 'L') { + lastType = t; + } + } + + /* + N1. A sequence of neutrals takes the direction of the surrounding strong + text if the text on both sides has the same direction. European and Arabic + numbers are treated as though they were R. Start-of-level-run (sor) and + end-of-level-run (eor) are used at level run boundaries. + */ + for (i = 0; i < strLength; ++i) { + if (types[i] === 'ON') { + var end = findUnequal(types, i + 1, 'ON'); + var before = sor; + if (i > 0) { + before = types[i - 1]; + } + + var after = eor; + if (end + 1 < strLength) { + after = types[end + 1]; + } + if (before !== 'L') { + before = 'R'; + } + if (after !== 'L') { + after = 'R'; + } + if (before === after) { + setValues(types, i, end, before); + } + i = end - 1; // reset to end (-1 so next iteration is ok) + } + } + + /* + N2. Any remaining neutrals take the embedding direction. + */ + for (i = 0; i < strLength; ++i) { + if (types[i] === 'ON') { + types[i] = e; + } + } + + /* + I1. For all characters with an even (left-to-right) embedding direction, + those of type R go up one level and those of type AN or EN go up two + levels. + I2. For all characters with an odd (right-to-left) embedding direction, + those of type L, EN or AN go up one level. + */ + for (i = 0; i < strLength; ++i) { + t = types[i]; + if (isEven(levels[i])) { + if (t === 'R') { + levels[i] += 1; + } else if (t === 'AN' || t === 'EN') { + levels[i] += 2; + } + } else { // isOdd + if (t === 'L' || t === 'AN' || t === 'EN') { + levels[i] += 1; + } + } + } + + /* + L1. On each line, reset the embedding level of the following characters to + the paragraph embedding level: + + segment separators, + paragraph separators, + any sequence of whitespace characters preceding a segment separator or + paragraph separator, and any sequence of white space characters at the end + of the line. + */ + + // don't bother as text is only single line + + /* + L2. From the highest level found in the text to the lowest odd level on + each line, reverse any contiguous sequence of characters that are at that + level or higher. + */ + + // find highest level & lowest odd level + var highestLevel = -1; + var lowestOddLevel = 99; + var level; + for (i = 0, ii = levels.length; i < ii; ++i) { + level = levels[i]; + if (highestLevel < level) { + highestLevel = level; + } + if (lowestOddLevel > level && isOdd(level)) { + lowestOddLevel = level; + } + } + + // now reverse between those limits + for (level = highestLevel; level >= lowestOddLevel; --level) { + // find segments to reverse + var start = -1; + for (i = 0, ii = levels.length; i < ii; ++i) { + if (levels[i] < level) { + if (start >= 0) { + reverseValues(chars, start, i); + start = -1; + } + } else if (start < 0) { + start = i; + } + } + if (start >= 0) { + reverseValues(chars, start, levels.length); + } + } + + /* + L3. Combining marks applied to a right-to-left base character will at this + point precede their base character. If the rendering engine expects them to + follow the base characters in the final display process, then the ordering + of the marks and the base character must be reversed. + */ + + // don't bother for now + + /* + L4. A character that possesses the mirrored property as specified by + Section 4.7, Mirrored, must be depicted by a mirrored glyph if the resolved + directionality of that character is R. + */ + + // don't mirror as characters are already mirrored in the pdf + + // Finally, return string + var result = ''; + for (i = 0, ii = chars.length; i < ii; ++i) { + var ch = chars[i]; + if (ch !== '<' && ch !== '>') { + result += ch; + } + } + return createBidiText(result, isLTR); + } + + return bidi; +})(); + +/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ + +/* Copyright 2014 Opera Software ASA + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * + * Based on https://code.google.com/p/smhasher/wiki/MurmurHash3. + * Hashes roughly 100 KB per millisecond on i7 3.4 GHz. + */ +/* globals Uint32ArrayView */ + +'use strict'; + +var MurmurHash3_64 = (function MurmurHash3_64Closure (seed) { + // Workaround for missing math precison in JS. + var MASK_HIGH = 0xffff0000; + var MASK_LOW = 0xffff; + + function MurmurHash3_64 (seed) { + var SEED = 0xc3d2e1f0; + this.h1 = seed ? seed & 0xffffffff : SEED; + this.h2 = seed ? seed & 0xffffffff : SEED; + } + + var alwaysUseUint32ArrayView = false; +//#if !(FIREFOX || MOZCENTRAL || B2G || CHROME) + // old webkits have issues with non-aligned arrays + try { + new Uint32Array(new Uint8Array(5).buffer, 0, 1); + } catch (e) { + alwaysUseUint32ArrayView = true; + } +//#endif + + MurmurHash3_64.prototype = { + update: function MurmurHash3_64_update(input) { + var useUint32ArrayView = alwaysUseUint32ArrayView; + var i; + if (typeof input === 'string') { + var data = new Uint8Array(input.length * 2); + var length = 0; + for (i = 0; i < input.length; i++) { + var code = input.charCodeAt(i); + if (code <= 0xff) { + data[length++] = code; + } + else { + data[length++] = code >>> 8; + data[length++] = code & 0xff; + } + } + } else if (input instanceof Uint8Array) { + data = input; + length = data.length; + } else if (typeof input === 'object' && ('length' in input)) { + // processing regular arrays as well, e.g. for IE9 + data = input; + length = data.length; + useUint32ArrayView = true; + } else { + throw new Error('Wrong data format in MurmurHash3_64_update. ' + + 'Input must be a string or array.'); + } + + var blockCounts = length >> 2; + var tailLength = length - blockCounts * 4; + // we don't care about endianness here + var dataUint32 = useUint32ArrayView ? + new Uint32ArrayView(data, blockCounts) : + new Uint32Array(data.buffer, 0, blockCounts); + var k1 = 0; + var k2 = 0; + var h1 = this.h1; + var h2 = this.h2; + var C1 = 0xcc9e2d51; + var C2 = 0x1b873593; + var C1_LOW = C1 & MASK_LOW; + var C2_LOW = C2 & MASK_LOW; + + for (i = 0; i < blockCounts; i++) { + if (i & 1) { + k1 = dataUint32[i]; + k1 = (k1 * C1 & MASK_HIGH) | (k1 * C1_LOW & MASK_LOW); + k1 = k1 << 15 | k1 >>> 17; + k1 = (k1 * C2 & MASK_HIGH) | (k1 * C2_LOW & MASK_LOW); + h1 ^= k1; + h1 = h1 << 13 | h1 >>> 19; + h1 = h1 * 5 + 0xe6546b64; + } else { + k2 = dataUint32[i]; + k2 = (k2 * C1 & MASK_HIGH) | (k2 * C1_LOW & MASK_LOW); + k2 = k2 << 15 | k2 >>> 17; + k2 = (k2 * C2 & MASK_HIGH) | (k2 * C2_LOW & MASK_LOW); + h2 ^= k2; + h2 = h2 << 13 | h2 >>> 19; + h2 = h2 * 5 + 0xe6546b64; + } + } + + k1 = 0; + + switch (tailLength) { + case 3: + k1 ^= data[blockCounts * 4 + 2] << 16; + /* falls through */ + case 2: + k1 ^= data[blockCounts * 4 + 1] << 8; + /* falls through */ + case 1: + k1 ^= data[blockCounts * 4]; + /* falls through */ + k1 = (k1 * C1 & MASK_HIGH) | (k1 * C1_LOW & MASK_LOW); + k1 = k1 << 15 | k1 >>> 17; + k1 = (k1 * C2 & MASK_HIGH) | (k1 * C2_LOW & MASK_LOW); + if (blockCounts & 1) { + h1 ^= k1; + } else { + h2 ^= k1; + } + } + + this.h1 = h1; + this.h2 = h2; + return this; + }, + + hexdigest: function MurmurHash3_64_hexdigest () { + var h1 = this.h1; + var h2 = this.h2; + + h1 ^= h2 >>> 1; + h1 = (h1 * 0xed558ccd & MASK_HIGH) | (h1 * 0x8ccd & MASK_LOW); + h2 = (h2 * 0xff51afd7 & MASK_HIGH) | + (((h2 << 16 | h1 >>> 16) * 0xafd7ed55 & MASK_HIGH) >>> 16); + h1 ^= h2 >>> 1; + h1 = (h1 * 0x1a85ec53 & MASK_HIGH) | (h1 * 0xec53 & MASK_LOW); + h2 = (h2 * 0xc4ceb9fe & MASK_HIGH) | + (((h2 << 16 | h1 >>> 16) * 0xb9fe1a85 & MASK_HIGH) >>> 16); + h1 ^= h2 >>> 1; + + for (var i = 0, arr = [h1, h2], str = ''; i < arr.length; i++) { + var hex = (arr[i] >>> 0).toString(16); + while (hex.length < 8) { + hex = '0' + hex; + } + str += hex; + } + + return str; + } + }; + + return MurmurHash3_64; +})(); + + +}).call((typeof window === 'undefined') ? this : window); + +if (!PDFJS.workerSrc && typeof document !== 'undefined') { + // workerSrc is not set -- using last script url to define default location + PDFJS.workerSrc = (function () { + 'use strict'; + var scriptTagContainer = document.body || + document.getElementsByTagName('head')[0]; + var pdfjsSrc = scriptTagContainer.lastChild.src; + return pdfjsSrc && pdfjsSrc.replace(/\.js$/i, '.worker.js'); + })(); +} + diff --git a/muk_web_preview/static/lib/ViewerJS/pdfjsversion.js b/muk_web_preview/static/lib/ViewerJS/pdfjsversion.js new file mode 100644 index 0000000..7aefe44 --- /dev/null +++ b/muk_web_preview/static/lib/ViewerJS/pdfjsversion.js @@ -0,0 +1 @@ +var /**@const{!string}*/pdfjs_version = "v1.1.114"; diff --git a/muk_web_preview/static/lib/ViewerJS/text_layer_builder.js b/muk_web_preview/static/lib/ViewerJS/text_layer_builder.js new file mode 100644 index 0000000..7483c02 --- /dev/null +++ b/muk_web_preview/static/lib/ViewerJS/text_layer_builder.js @@ -0,0 +1,419 @@ +/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* Copyright 2012 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* globals CustomStyle, PDFJS */ + +'use strict'; + +var MAX_TEXT_DIVS_TO_RENDER = 100000; + +var NonWhitespaceRegexp = /\S/; + +function isAllWhitespace(str) { + return !NonWhitespaceRegexp.test(str); +} + +/** + * @typedef {Object} TextLayerBuilderOptions + * @property {HTMLDivElement} textLayerDiv - The text layer container. + * @property {number} pageIndex - The page index. + * @property {PageViewport} viewport - The viewport of the text layer. + * @property {PDFFindController} findController + */ + +/** + * TextLayerBuilder provides text-selection functionality for the PDF. + * It does this by creating overlay divs over the PDF text. These divs + * contain text that matches the PDF text they are overlaying. This object + * also provides a way to highlight text that is being searched for. + * @class + */ +var TextLayerBuilder = (function TextLayerBuilderClosure() { + function TextLayerBuilder(options) { + this.textLayerDiv = options.textLayerDiv; + this.renderingDone = false; + this.divContentDone = false; + this.pageIdx = options.pageIndex; + this.pageNumber = this.pageIdx + 1; + this.matches = []; + this.viewport = options.viewport; + this.textDivs = []; + this.findController = options.findController || null; + } + + TextLayerBuilder.prototype = { + _finishRendering: function TextLayerBuilder_finishRendering() { + this.renderingDone = true; + + var event = document.createEvent('CustomEvent'); + event.initCustomEvent('textlayerrendered', true, true, { + pageNumber: this.pageNumber + }); + this.textLayerDiv.dispatchEvent(event); + }, + + renderLayer: function TextLayerBuilder_renderLayer() { + var textLayerFrag = document.createDocumentFragment(); + var textDivs = this.textDivs; + var textDivsLength = textDivs.length; + var canvas = document.createElement('canvas'); + var ctx = canvas.getContext('2d'); + + // No point in rendering many divs as it would make the browser + // unusable even after the divs are rendered. + if (textDivsLength > MAX_TEXT_DIVS_TO_RENDER) { + this._finishRendering(); + return; + } + + var lastFontSize; + var lastFontFamily; + for (var i = 0; i < textDivsLength; i++) { + var textDiv = textDivs[i]; + if (textDiv.dataset.isWhitespace !== undefined) { + continue; + } + + var fontSize = textDiv.style.fontSize; + var fontFamily = textDiv.style.fontFamily; + + // Only build font string and set to context if different from last. + if (fontSize !== lastFontSize || fontFamily !== lastFontFamily) { + ctx.font = fontSize + ' ' + fontFamily; + lastFontSize = fontSize; + lastFontFamily = fontFamily; + } + + var width = ctx.measureText(textDiv.textContent).width; + if (width > 0) { + textLayerFrag.appendChild(textDiv); + var transform; + if (textDiv.dataset.canvasWidth !== undefined) { + // Dataset values come of type string. + var textScale = textDiv.dataset.canvasWidth / width; + transform = 'scaleX(' + textScale + ')'; + } else { + transform = ''; + } + var rotation = textDiv.dataset.angle; + if (rotation) { + transform = 'rotate(' + rotation + 'deg) ' + transform; + } + if (transform) { + CustomStyle.setProp('transform' , textDiv, transform); + } + } + } + + this.textLayerDiv.appendChild(textLayerFrag); + this._finishRendering(); + this.updateMatches(); + }, + + /** + * Renders the text layer. + * @param {number} timeout (optional) if specified, the rendering waits + * for specified amount of ms. + */ + render: function TextLayerBuilder_render(timeout) { + if (!this.divContentDone || this.renderingDone) { + return; + } + + if (this.renderTimer) { + clearTimeout(this.renderTimer); + this.renderTimer = null; + } + + if (!timeout) { // Render right away + this.renderLayer(); + } else { // Schedule + var self = this; + this.renderTimer = setTimeout(function() { + self.renderLayer(); + self.renderTimer = null; + }, timeout); + } + }, + + appendText: function TextLayerBuilder_appendText(geom, styles) { + var style = styles[geom.fontName]; + var textDiv = document.createElement('div'); + this.textDivs.push(textDiv); + if (isAllWhitespace(geom.str)) { + textDiv.dataset.isWhitespace = true; + return; + } + var tx = PDFJS.Util.transform(this.viewport.transform, geom.transform); + var angle = Math.atan2(tx[1], tx[0]); + if (style.vertical) { + angle += Math.PI / 2; + } + var fontHeight = Math.sqrt((tx[2] * tx[2]) + (tx[3] * tx[3])); + var fontAscent = fontHeight; + if (style.ascent) { + fontAscent = style.ascent * fontAscent; + } else if (style.descent) { + fontAscent = (1 + style.descent) * fontAscent; + } + + var left; + var top; + if (angle === 0) { + left = tx[4]; + top = tx[5] - fontAscent; + } else { + left = tx[4] + (fontAscent * Math.sin(angle)); + top = tx[5] - (fontAscent * Math.cos(angle)); + } + textDiv.style.left = left + 'px'; + textDiv.style.top = top + 'px'; + textDiv.style.fontSize = fontHeight + 'px'; + textDiv.style.fontFamily = style.fontFamily; + + textDiv.textContent = geom.str; + // |fontName| is only used by the Font Inspector. This test will succeed + // when e.g. the Font Inspector is off but the Stepper is on, but it's + // not worth the effort to do a more accurate test. + if (PDFJS.pdfBug) { + textDiv.dataset.fontName = geom.fontName; + } + // Storing into dataset will convert number into string. + if (angle !== 0) { + textDiv.dataset.angle = angle * (180 / Math.PI); + } + // We don't bother scaling single-char text divs, because it has very + // little effect on text highlighting. This makes scrolling on docs with + // lots of such divs a lot faster. + if (textDiv.textContent.length > 1) { + if (style.vertical) { + textDiv.dataset.canvasWidth = geom.height * this.viewport.scale; + } else { + textDiv.dataset.canvasWidth = geom.width * this.viewport.scale; + } + } + }, + + setTextContent: function TextLayerBuilder_setTextContent(textContent) { + this.textContent = textContent; + + var textItems = textContent.items; + for (var i = 0, len = textItems.length; i < len; i++) { + this.appendText(textItems[i], textContent.styles); + } + this.divContentDone = true; + }, + + convertMatches: function TextLayerBuilder_convertMatches(matches) { + var i = 0; + var iIndex = 0; + var bidiTexts = this.textContent.items; + var end = bidiTexts.length - 1; + var queryLen = (this.findController === null ? + 0 : this.findController.state.query.length); + var ret = []; + + for (var m = 0, len = matches.length; m < len; m++) { + // Calculate the start position. + var matchIdx = matches[m]; + + // Loop over the divIdxs. + while (i !== end && matchIdx >= (iIndex + bidiTexts[i].str.length)) { + iIndex += bidiTexts[i].str.length; + i++; + } + + if (i === bidiTexts.length) { + console.error('Could not find a matching mapping'); + } + + var match = { + begin: { + divIdx: i, + offset: matchIdx - iIndex + } + }; + + // Calculate the end position. + matchIdx += queryLen; + + // Somewhat the same array as above, but use > instead of >= to get + // the end position right. + while (i !== end && matchIdx > (iIndex + bidiTexts[i].str.length)) { + iIndex += bidiTexts[i].str.length; + i++; + } + + match.end = { + divIdx: i, + offset: matchIdx - iIndex + }; + ret.push(match); + } + + return ret; + }, + + renderMatches: function TextLayerBuilder_renderMatches(matches) { + // Early exit if there is nothing to render. + if (matches.length === 0) { + return; + } + + var bidiTexts = this.textContent.items; + var textDivs = this.textDivs; + var prevEnd = null; + var pageIdx = this.pageIdx; + var isSelectedPage = (this.findController === null ? + false : (pageIdx === this.findController.selected.pageIdx)); + var selectedMatchIdx = (this.findController === null ? + -1 : this.findController.selected.matchIdx); + var highlightAll = (this.findController === null ? + false : this.findController.state.highlightAll); + var infinity = { + divIdx: -1, + offset: undefined + }; + + function beginText(begin, className) { + var divIdx = begin.divIdx; + textDivs[divIdx].textContent = ''; + appendTextToDiv(divIdx, 0, begin.offset, className); + } + + function appendTextToDiv(divIdx, fromOffset, toOffset, className) { + var div = textDivs[divIdx]; + var content = bidiTexts[divIdx].str.substring(fromOffset, toOffset); + var node = document.createTextNode(content); + if (className) { + var span = document.createElement('span'); + span.className = className; + span.appendChild(node); + div.appendChild(span); + return; + } + div.appendChild(node); + } + + var i0 = selectedMatchIdx, i1 = i0 + 1; + if (highlightAll) { + i0 = 0; + i1 = matches.length; + } else if (!isSelectedPage) { + // Not highlighting all and this isn't the selected page, so do nothing. + return; + } + + for (var i = i0; i < i1; i++) { + var match = matches[i]; + var begin = match.begin; + var end = match.end; + var isSelected = (isSelectedPage && i === selectedMatchIdx); + var highlightSuffix = (isSelected ? ' selected' : ''); + + if (this.findController) { + this.findController.updateMatchPosition(pageIdx, i, textDivs, + begin.divIdx, end.divIdx); + } + + // Match inside new div. + if (!prevEnd || begin.divIdx !== prevEnd.divIdx) { + // If there was a previous div, then add the text at the end. + if (prevEnd !== null) { + appendTextToDiv(prevEnd.divIdx, prevEnd.offset, infinity.offset); + } + // Clear the divs and set the content until the starting point. + beginText(begin); + } else { + appendTextToDiv(prevEnd.divIdx, prevEnd.offset, begin.offset); + } + + if (begin.divIdx === end.divIdx) { + appendTextToDiv(begin.divIdx, begin.offset, end.offset, + 'highlight' + highlightSuffix); + } else { + appendTextToDiv(begin.divIdx, begin.offset, infinity.offset, + 'highlight begin' + highlightSuffix); + for (var n0 = begin.divIdx + 1, n1 = end.divIdx; n0 < n1; n0++) { + textDivs[n0].className = 'highlight middle' + highlightSuffix; + } + beginText(end, 'highlight end' + highlightSuffix); + } + prevEnd = end; + } + + if (prevEnd) { + appendTextToDiv(prevEnd.divIdx, prevEnd.offset, infinity.offset); + } + }, + + updateMatches: function TextLayerBuilder_updateMatches() { + // Only show matches when all rendering is done. + if (!this.renderingDone) { + return; + } + + // Clear all matches. + var matches = this.matches; + var textDivs = this.textDivs; + var bidiTexts = this.textContent.items; + var clearedUntilDivIdx = -1; + + // Clear all current matches. + for (var i = 0, len = matches.length; i < len; i++) { + var match = matches[i]; + var begin = Math.max(clearedUntilDivIdx, match.begin.divIdx); + for (var n = begin, end = match.end.divIdx; n <= end; n++) { + var div = textDivs[n]; + div.textContent = bidiTexts[n].str; + div.className = ''; + } + clearedUntilDivIdx = match.end.divIdx + 1; + } + + if (this.findController === null || !this.findController.active) { + return; + } + + // Convert the matches on the page controller into the match format + // used for the textLayer. + this.matches = this.convertMatches(this.findController === null ? + [] : (this.findController.pageMatches[this.pageIdx] || [])); + this.renderMatches(this.matches); + } + }; + return TextLayerBuilder; +})(); + +/** + * @constructor + * @implements IPDFTextLayerFactory + */ +function DefaultTextLayerFactory() {} +DefaultTextLayerFactory.prototype = { + /** + * @param {HTMLDivElement} textLayerDiv + * @param {number} pageIndex + * @param {PageViewport} viewport + * @returns {TextLayerBuilder} + */ + createTextLayerBuilder: function (textLayerDiv, pageIndex, viewport) { + return new TextLayerBuilder({ + textLayerDiv: textLayerDiv, + pageIndex: pageIndex, + viewport: viewport + }); + } +}; diff --git a/muk_web_preview/static/lib/ViewerJS/ui_utils.js b/muk_web_preview/static/lib/ViewerJS/ui_utils.js new file mode 100644 index 0000000..7e798e3 --- /dev/null +++ b/muk_web_preview/static/lib/ViewerJS/ui_utils.js @@ -0,0 +1,394 @@ +/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* Copyright 2012 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +'use strict'; + +var CSS_UNITS = 96.0 / 72.0; +var DEFAULT_SCALE = 'auto'; +var UNKNOWN_SCALE = 0; +var MAX_AUTO_SCALE = 1.25; +var SCROLLBAR_PADDING = 40; +var VERTICAL_PADDING = 5; + +// optimised CSS custom property getter/setter +var CustomStyle = (function CustomStyleClosure() { + + // As noted on: http://www.zachstronaut.com/posts/2009/02/17/ + // animate-css-transforms-firefox-webkit.html + // in some versions of IE9 it is critical that ms appear in this list + // before Moz + var prefixes = ['ms', 'Moz', 'Webkit', 'O']; + var _cache = {}; + + function CustomStyle() {} + + CustomStyle.getProp = function get(propName, element) { + // check cache only when no element is given + if (arguments.length === 1 && typeof _cache[propName] === 'string') { + return _cache[propName]; + } + + element = element || document.documentElement; + var style = element.style, prefixed, uPropName; + + // test standard property first + if (typeof style[propName] === 'string') { + return (_cache[propName] = propName); + } + + // capitalize + uPropName = propName.charAt(0).toUpperCase() + propName.slice(1); + + // test vendor specific properties + for (var i = 0, l = prefixes.length; i < l; i++) { + prefixed = prefixes[i] + uPropName; + if (typeof style[prefixed] === 'string') { + return (_cache[propName] = prefixed); + } + } + + //if all fails then set to undefined + return (_cache[propName] = 'undefined'); + }; + + CustomStyle.setProp = function set(propName, element, str) { + var prop = this.getProp(propName); + if (prop !== 'undefined') { + element.style[prop] = str; + } + }; + + return CustomStyle; +})(); + +function getFileName(url) { + var anchor = url.indexOf('#'); + var query = url.indexOf('?'); + var end = Math.min( + anchor > 0 ? anchor : url.length, + query > 0 ? query : url.length); + return url.substring(url.lastIndexOf('/', end) + 1, end); +} + +/** + * Returns scale factor for the canvas. It makes sense for the HiDPI displays. + * @return {Object} The object with horizontal (sx) and vertical (sy) + scales. The scaled property is set to false if scaling is + not required, true otherwise. + */ +function getOutputScale(ctx) { + var devicePixelRatio = window.devicePixelRatio || 1; + var backingStoreRatio = ctx.webkitBackingStorePixelRatio || + ctx.mozBackingStorePixelRatio || + ctx.msBackingStorePixelRatio || + ctx.oBackingStorePixelRatio || + ctx.backingStorePixelRatio || 1; + var pixelRatio = devicePixelRatio / backingStoreRatio; + return { + sx: pixelRatio, + sy: pixelRatio, + scaled: pixelRatio !== 1 + }; +} + +/** + * Scrolls specified element into view of its parent. + * element {Object} The element to be visible. + * spot {Object} An object with optional top and left properties, + * specifying the offset from the top left edge. + */ +function scrollIntoView(element, spot) { + // Assuming offsetParent is available (it's not available when viewer is in + // hidden iframe or object). We have to scroll: if the offsetParent is not set + // producing the error. See also animationStartedClosure. + var parent = element.offsetParent; + var offsetY = element.offsetTop + element.clientTop; + var offsetX = element.offsetLeft + element.clientLeft; + if (!parent) { + console.error('offsetParent is not set -- cannot scroll'); + return; + } + while (parent.clientHeight === parent.scrollHeight) { + if (parent.dataset._scaleY) { + offsetY /= parent.dataset._scaleY; + offsetX /= parent.dataset._scaleX; + } + offsetY += parent.offsetTop; + offsetX += parent.offsetLeft; + parent = parent.offsetParent; + if (!parent) { + return; // no need to scroll + } + } + if (spot) { + if (spot.top !== undefined) { + offsetY += spot.top; + } + if (spot.left !== undefined) { + offsetX += spot.left; + parent.scrollLeft = offsetX; + } + } + parent.scrollTop = offsetY; +} + +/** + * Helper function to start monitoring the scroll event and converting them into + * PDF.js friendly one: with scroll debounce and scroll direction. + */ +function watchScroll(viewAreaElement, callback) { + var debounceScroll = function debounceScroll(evt) { + if (rAF) { + return; + } + // schedule an invocation of scroll for next animation frame. + rAF = window.requestAnimationFrame(function viewAreaElementScrolled() { + rAF = null; + + var currentY = viewAreaElement.scrollTop; + var lastY = state.lastY; + if (currentY !== lastY) { + state.down = currentY > lastY; + } + state.lastY = currentY; + callback(state); + }); + }; + + var state = { + down: true, + lastY: viewAreaElement.scrollTop, + _eventHandler: debounceScroll + }; + + var rAF = null; + viewAreaElement.addEventListener('scroll', debounceScroll, true); + return state; +} + +/** + * Use binary search to find the index of the first item in a given array which + * passes a given condition. The items are expected to be sorted in the sense + * that if the condition is true for one item in the array, then it is also true + * for all following items. + * + * @returns {Number} Index of the first array element to pass the test, + * or |items.length| if no such element exists. + */ +function binarySearchFirstItem(items, condition) { + var minIndex = 0; + var maxIndex = items.length - 1; + + if (items.length === 0 || !condition(items[maxIndex])) { + return items.length; + } + if (condition(items[minIndex])) { + return minIndex; + } + + while (minIndex < maxIndex) { + var currentIndex = (minIndex + maxIndex) >> 1; + var currentItem = items[currentIndex]; + if (condition(currentItem)) { + maxIndex = currentIndex; + } else { + minIndex = currentIndex + 1; + } + } + return minIndex; /* === maxIndex */ +} + +/** + * Generic helper to find out what elements are visible within a scroll pane. + */ +function getVisibleElements(scrollEl, views, sortByVisibility) { + var top = scrollEl.scrollTop, bottom = top + scrollEl.clientHeight; + var left = scrollEl.scrollLeft, right = left + scrollEl.clientWidth; + + function isElementBottomBelowViewTop(view) { + var element = view.div; + var elementBottom = + element.offsetTop + element.clientTop + element.clientHeight; + return elementBottom > top; + } + + var visible = [], view, element; + var currentHeight, viewHeight, hiddenHeight, percentHeight; + var currentWidth, viewWidth; + var firstVisibleElementInd = (views.length === 0) ? 0 : + binarySearchFirstItem(views, isElementBottomBelowViewTop); + + for (var i = firstVisibleElementInd, ii = views.length; i < ii; i++) { + view = views[i]; + element = view.div; + currentHeight = element.offsetTop + element.clientTop; + viewHeight = element.clientHeight; + + if (currentHeight > bottom) { + break; + } + + currentWidth = element.offsetLeft + element.clientLeft; + viewWidth = element.clientWidth; + if (currentWidth + viewWidth < left || currentWidth > right) { + continue; + } + hiddenHeight = Math.max(0, top - currentHeight) + + Math.max(0, currentHeight + viewHeight - bottom); + percentHeight = ((viewHeight - hiddenHeight) * 100 / viewHeight) | 0; + + visible.push({ + id: view.id, + x: currentWidth, + y: currentHeight, + view: view, + percent: percentHeight + }); + } + + var first = visible[0]; + var last = visible[visible.length - 1]; + + if (sortByVisibility) { + visible.sort(function(a, b) { + var pc = a.percent - b.percent; + if (Math.abs(pc) > 0.001) { + return -pc; + } + return a.id - b.id; // ensure stability + }); + } + return {first: first, last: last, views: visible}; +} + +/** + * Event handler to suppress context menu. + */ +function noContextMenuHandler(e) { + e.preventDefault(); +} + +/** + * Returns the filename or guessed filename from the url (see issue 3455). + * url {String} The original PDF location. + * @return {String} Guessed PDF file name. + */ +function getPDFFileNameFromURL(url) { + var reURI = /^(?:([^:]+:)?\/\/[^\/]+)?([^?#]*)(\?[^#]*)?(#.*)?$/; + // SCHEME HOST 1.PATH 2.QUERY 3.REF + // Pattern to get last matching NAME.pdf + var reFilename = /[^\/?#=]+\.pdf\b(?!.*\.pdf\b)/i; + var splitURI = reURI.exec(url); + var suggestedFilename = reFilename.exec(splitURI[1]) || + reFilename.exec(splitURI[2]) || + reFilename.exec(splitURI[3]); + if (suggestedFilename) { + suggestedFilename = suggestedFilename[0]; + if (suggestedFilename.indexOf('%') !== -1) { + // URL-encoded %2Fpath%2Fto%2Ffile.pdf should be file.pdf + try { + suggestedFilename = + reFilename.exec(decodeURIComponent(suggestedFilename))[0]; + } catch(e) { // Possible (extremely rare) errors: + // URIError "Malformed URI", e.g. for "%AA.pdf" + // TypeError "null has no properties", e.g. for "%2F.pdf" + } + } + } + return suggestedFilename || 'document.pdf'; +} + +var ProgressBar = (function ProgressBarClosure() { + + function clamp(v, min, max) { + return Math.min(Math.max(v, min), max); + } + + function ProgressBar(id, opts) { + this.visible = true; + + // Fetch the sub-elements for later. + this.div = document.querySelector(id + ' .progress'); + + // Get the loading bar element, so it can be resized to fit the viewer. + this.bar = this.div.parentNode; + + // Get options, with sensible defaults. + this.height = opts.height || 100; + this.width = opts.width || 100; + this.units = opts.units || '%'; + + // Initialize heights. + this.div.style.height = this.height + this.units; + this.percent = 0; + } + + ProgressBar.prototype = { + + updateBar: function ProgressBar_updateBar() { + if (this._indeterminate) { + this.div.classList.add('indeterminate'); + this.div.style.width = this.width + this.units; + return; + } + + this.div.classList.remove('indeterminate'); + var progressSize = this.width * this._percent / 100; + this.div.style.width = progressSize + this.units; + }, + + get percent() { + return this._percent; + }, + + set percent(val) { + this._indeterminate = isNaN(val); + this._percent = clamp(val, 0, 100); + this.updateBar(); + }, + + setWidth: function ProgressBar_setWidth(viewer) { + if (viewer) { + var container = viewer.parentNode; + var scrollbarWidth = container.offsetWidth - viewer.offsetWidth; + if (scrollbarWidth > 0) { + this.bar.setAttribute('style', 'width: calc(100% - ' + + scrollbarWidth + 'px);'); + } + } + }, + + hide: function ProgressBar_hide() { + if (!this.visible) { + return; + } + this.visible = false; + this.bar.classList.add('hidden'); + document.body.classList.remove('loadingInProgress'); + }, + + show: function ProgressBar_show() { + if (this.visible) { + return; + } + this.visible = true; + document.body.classList.add('loadingInProgress'); + this.bar.classList.remove('hidden'); + } + }; + + return ProgressBar; +})(); diff --git a/muk_web_preview/static/lib/ViewerJS/webodf.js b/muk_web_preview/static/lib/ViewerJS/webodf.js new file mode 100644 index 0000000..dbb0d33 --- /dev/null +++ b/muk_web_preview/static/lib/ViewerJS/webodf.js @@ -0,0 +1,936 @@ +/* + + This is a generated file. DO NOT EDIT. + + Copyright (C) 2010-2015 KO GmbH + + @licstart + The code in this file is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License (GNU AGPL) + as published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + The code in this file is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with WebODF. If not, see . + + As additional permission under GNU AGPL version 3 section 7, you + may distribute UNMODIFIED VERSIONS OF THIS file without the copy of the GNU AGPL normally + required by section 4, provided you include this license notice and a URL + through which recipients can access the Corresponding Source. + + As a special exception to the AGPL, any HTML file which merely makes function + calls to this code, and for that purpose includes it in unmodified form by reference or in-line shall be + deemed a separate work for copyright law purposes. In addition, the copyright + holders of this code give you permission to combine this code with free + software libraries that are released under the GNU LGPL. You may copy and + distribute such a system following the terms of the GNU AGPL for this code + and the LGPL for the libraries. If you modify this code, you may extend this + exception to your version of the code, but you are not obligated to do so. + If you do not wish to do so, delete this exception statement from your + version. + + This license applies to this entire compilation. + @licend + + @source: http://www.webodf.org/ + @source: https://github.com/kogmbh/WebODF/ +*/ +var webodf_version="0.5.8";function Runtime(){}Runtime.prototype.getVariable=function(g){};Runtime.prototype.toJson=function(g){};Runtime.prototype.fromJson=function(g){};Runtime.prototype.byteArrayFromString=function(g,k){};Runtime.prototype.byteArrayToString=function(g,k){};Runtime.prototype.read=function(g,k,c,b){};Runtime.prototype.readFile=function(g,k,c){};Runtime.prototype.readFileSync=function(g,k){};Runtime.prototype.loadXML=function(g,k){};Runtime.prototype.writeFile=function(g,k,c){}; +Runtime.prototype.deleteFile=function(g,k){};Runtime.prototype.log=function(g,k){};Runtime.prototype.setTimeout=function(g,k){};Runtime.prototype.clearTimeout=function(g){};Runtime.prototype.libraryPaths=function(){};Runtime.prototype.currentDirectory=function(){};Runtime.prototype.setCurrentDirectory=function(g){};Runtime.prototype.type=function(){};Runtime.prototype.getDOMImplementation=function(){};Runtime.prototype.parseXML=function(g){};Runtime.prototype.exit=function(g){}; +Runtime.prototype.getWindow=function(){};Runtime.prototype.requestAnimationFrame=function(g){};Runtime.prototype.cancelAnimationFrame=function(g){};Runtime.prototype.assert=function(g,k){};var IS_COMPILED_CODE=!0; +Runtime.byteArrayToString=function(g,k){function c(b){var c="",r,q=b.length;for(r=0;rl?e.push(l):(r+=1,a=b[r],194<=l&&224>l?e.push((l&31)<<6|a&63):(r+=1,d=b[r],224<=l&&240>l?e.push((l&15)<<12|(a&63)<<6|d&63):(r+=1,m=b[r],240<=l&&245>l&&(l=(l&7)<<18|(a&63)<<12|(d&63)<<6|m&63,l-=65536,e.push((l>>10)+55296,(l&1023)+56320))))),1E3<=e.length&& +(c+=String.fromCharCode.apply(null,e),e.length=0);return c+String.fromCharCode.apply(null,e)}var f;"utf8"===k?f=b(g):("binary"!==k&&this.log("Unsupported encoding: "+k),f=c(g));return f};Runtime.getVariable=function(g){try{return eval(g)}catch(k){}};Runtime.toJson=function(g){return JSON.stringify(g)};Runtime.fromJson=function(g){return JSON.parse(g)};Runtime.getFunctionName=function(g){return void 0===g.name?(g=/function\s+(\w+)/.exec(g))&&g[1]:g.name}; +Runtime.assert=function(g,k){if(!g)throw this.log("alert","ASSERTION FAILED:\n"+k),Error(k);}; +function BrowserRuntime(){function g(b){var e=b.length,l,a,d=0;for(l=0;la&&(d+=1,l+=1);return d}function k(b,e,l){var a=b.length,d,m;e=new Uint8Array(new ArrayBuffer(e));l?(e[0]=239,e[1]=187,e[2]=191,m=3):m=0;for(l=0;ld?(e[m]=d,m+=1):2048>d?(e[m]=192|d>>>6,e[m+1]=128|d&63,m+=2):55040>=d||57344<=d?(e[m]=224|d>>>12&15,e[m+1]=128|d>>>6&63,e[m+2]=128|d&63,m+=3):(l+=1,d=(d-55296<<10|b.charCodeAt(l)-56320)+65536, +e[m]=240|d>>>18&7,e[m+1]=128|d>>>12&63,e[m+2]=128|d>>>6&63,e[m+3]=128|d&63,m+=4);return e}function c(b){var e=b.length,l=new Uint8Array(new ArrayBuffer(e)),a;for(a=0;aa.status||0===a.status?l(null):l("Status "+String(a.status)+": "+a.responseText||a.statusText):l("File "+b+" is empty."))};d=e.buffer&&!a.sendAsBinary?e.buffer:r.byteArrayToString(e,"binary");try{a.sendAsBinary?a.sendAsBinary(d):a.send(d)}catch(m){r.log("HUH? "+ +m+" "+e),l(m.message)}};this.deleteFile=function(b,e){var l=new XMLHttpRequest;l.open("DELETE",b,!0);l.onreadystatechange=function(){4===l.readyState&&(200>l.status&&300<=l.status?e(l.responseText):e(null))};l.send(null)};this.loadXML=function(b,e){var l=new XMLHttpRequest;l.open("GET",b,!0);l.overrideMimeType&&l.overrideMimeType("text/xml");l.onreadystatechange=function(){4===l.readyState&&(0!==l.status||l.responseText?200===l.status||0===l.status?e(null,l.responseXML):e(l.responseText,null):e("File "+ +b+" is empty.",null))};try{l.send(null)}catch(a){e(a.message,null)}};this.log=b;this.enableAlerts=!0;this.assert=Runtime.assert;this.setTimeout=function(b,e){return setTimeout(function(){b()},e)};this.clearTimeout=function(b){clearTimeout(b)};this.libraryPaths=function(){return["lib"]};this.setCurrentDirectory=function(){};this.currentDirectory=function(){return""};this.type=function(){return"BrowserRuntime"};this.getDOMImplementation=function(){return window.document.implementation};this.parseXML= +function(b){return(new DOMParser).parseFromString(b,"text/xml")};this.exit=function(c){b("Calling exit with code "+String(c)+", but exit() is not implemented.")};this.getWindow=function(){return window};this.requestAnimationFrame=function(b){var e=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.msRequestAnimationFrame,l=0;if(e)e.bind(window),l=e(b);else return setTimeout(b,15);return l};this.cancelAnimationFrame=function(b){var e=window.cancelAnimationFrame|| +window.webkitCancelAnimationFrame||window.mozCancelAnimationFrame||window.msCancelAnimationFrame;e?(e.bind(window),e(b)):clearTimeout(b)}} +function NodeJSRuntime(){function g(b){var e=b.length,l,a=new Uint8Array(new ArrayBuffer(e));for(l=0;l").implementation} +function RhinoRuntime(){var g=this,k={},c=k.javax.xml.parsers.DocumentBuilderFactory.newInstance(),b,f,n="";c.setValidating(!1);c.setNamespaceAware(!0);c.setExpandEntityReferences(!1);c.setSchema(null);f=k.org.xml.sax.EntityResolver({resolveEntity:function(b,c){var f=new k.java.io.FileReader(c);return new k.org.xml.sax.InputSource(f)}});b=c.newDocumentBuilder();b.setEntityResolver(f);this.byteArrayFromString=function(b,c){var f,e=b.length,l=new Uint8Array(new ArrayBuffer(e));for(f=0;f>>18],m+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[d>>>12&63],m+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[d>>>6&63],m+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[d& +63];h===b+1?(d=a[h]<<4,m+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[d>>>6],m+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[d&63],m+="=="):h===b&&(d=a[h]<<10|a[h+1]<<2,m+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[d>>>12],m+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[d>>>6&63],m+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[d&63],m+="=");return m}function c(a){a=a.replace(/[^A-Za-z0-9+\/]+/g, +"");var d=a.length,m=new Uint8Array(new ArrayBuffer(3*d)),b=a.length%4,c=0,l,e;for(l=0;l>16,m[c+1]=e>>8&255,m[c+2]=e&255,c+=3;d=3*d-[0,0,2,1][b];return m.subarray(0,d)}function b(a){var d,m,h=a.length,b=0,c=new Uint8Array(new ArrayBuffer(3*h));for(d=0;dm?c[b++]=m:(2048>m?c[b++]=192|m>>>6:(c[b++]=224|m>>>12&15,c[b++]=128|m>>>6&63),c[b++]=128|m&63);return c.subarray(0, +b)}function f(a){var d,m,h,b,c=a.length,l=new Uint8Array(new ArrayBuffer(c)),e=0;for(d=0;dm?l[e++]=m:(d+=1,h=a[d],224>m?l[e++]=(m&31)<<6|h&63:(d+=1,b=a[d],l[e++]=(m&15)<<12|(h&63)<<6|b&63));return l.subarray(0,e)}function n(a){return k(g(a))}function p(a){return String.fromCharCode.apply(String,c(a))}function r(a){return f(g(a))}function q(a){a=f(a);for(var d="",m=0;md?l+=String.fromCharCode(d):(c+=1,h=a.charCodeAt(c)&255,224>d?l+=String.fromCharCode((d&31)<<6|h&63):(c+=1,b=a.charCodeAt(c)&255,l+=String.fromCharCode((d&15)<<12|(h&63)<<6|b&63)));return l}function l(a,d){function m(){var c=b+1E5;c>a.length&&(c=a.length);h+=e(a,b,c);b=c;c=b===a.length;d(h,c)&&!c&&runtime.setTimeout(m,0)}var h="",b=0;1E5>a.length?d(e(a,0,a.length),!0):("string"!==typeof a&&(a=a.slice()),m())}function a(a){return b(g(a))}function d(a){return String.fromCharCode.apply(String, +b(a))}function m(a){return String.fromCharCode.apply(String,b(g(a)))}var h=function(a){var d={},m,h;m=0;for(h=a.length;m=a.compareBoundaryPoints(Range.START_TO_START,d)&&0<=a.compareBoundaryPoints(Range.END_TO_END,d)}function n(a,d){return 0>=a.compareBoundaryPoints(Range.END_TO_START,d)&&0<=a.compareBoundaryPoints(Range.START_TO_END,d)}function p(a,d){var b=null;a.nodeType===Node.TEXT_NODE&&(0===a.length?(a.parentNode.removeChild(a),d.nodeType===Node.TEXT_NODE&&(b=d)):(d.nodeType===Node.TEXT_NODE&&(a.appendData(d.data),d.parentNode.removeChild(d)),b=a));return b} +function r(a){for(var d=a.parentNode;a.firstChild;)d.insertBefore(a.firstChild,a);d.removeChild(a);return d}function q(a,d){var b=a.parentNode,c=a.firstChild,l=d(a),e;if(l===NodeFilter.FILTER_SKIP)return b;for(;c;)e=c.nextSibling,q(c,d),c=e;b&&l===NodeFilter.FILTER_REJECT&&r(a);return b}function e(a,d){return a===d||Boolean(a.compareDocumentPosition(d)&Node.DOCUMENT_POSITION_CONTAINED_BY)}function l(a,d){return g().unscaledRangeClientRects?a:a/d}function a(d,h,b){Object.keys(h).forEach(function(c){var l= +c.split(":"),e=l[1],f=b(l[0]),l=h[c],n=typeof l;"object"===n?Object.keys(l).length&&(c=f?d.getElementsByTagNameNS(f,e)[0]||d.ownerDocument.createElementNS(f,c):d.getElementsByTagName(e)[0]||d.ownerDocument.createElement(c),d.appendChild(c),a(c,l,b)):f&&(runtime.assert("number"===n||"string"===n,"attempting to map unsupported type '"+n+"' (key: "+c+")"),d.setAttributeNS(f,c,String(l)))})}var d=null;this.splitBoundaries=function(a){var d,c=[],l,e,f;if(a.startContainer.nodeType===Node.TEXT_NODE||a.endContainer.nodeType=== +Node.TEXT_NODE){l=a.endContainer;e=a.endContainer.nodeType!==Node.TEXT_NODE?a.endOffset===a.endContainer.childNodes.length:!1;f=a.endOffset;d=a.endContainer;if(fg))throw runtime.log("alert","watchdog timeout"),"timeout!";if(0k))throw runtime.log("alert","watchdog loop overflow"),"loop overflow";}};core.NodeFilterChain=function(g){var k=NodeFilter.FILTER_REJECT,c=NodeFilter.FILTER_ACCEPT;this.acceptNode=function(b){var f;for(f=0;f "+d.length),runtime.assert(0<=b,"Error in setPosition: "+b+" < 0"),b===d.length&&(l.nextSibling()?a=0:l.parentNode()?a=1:runtime.assert(!1,"Error in setUnfilteredPosition: position not valid."))):ba.value||"%"===a.unit)?null:a}function L(a){return(a=I(a))&&"%"!==a.unit?null:a}function E(a){switch(a.namespaceURI){case odf.Namespaces.drawns:case odf.Namespaces.svgns:case odf.Namespaces.dr3dns:return!1;case odf.Namespaces.textns:switch(a.localName){case "note-body":case "ruby-text":return!1}break;case odf.Namespaces.officens:switch(a.localName){case "annotation":case "binary-data":case "event-listeners":return!1}break;default:switch(a.localName){case "cursor":case "editinfo":return!1}}return!0} +function N(a){return Boolean(n(a)&&(!r(a.textContent)||A(a,0)))}function O(a,d){for(;0=d.value||"%"===d.unit)?null:d;return d||L(a)};this.parseFoLineHeight= +function(a){return K(a)||L(a)};this.isTextContentContainingNode=E;this.getTextNodes=function(a,d){var b;b=aa.getNodesInRange(a,function(a){var d=NodeFilter.FILTER_REJECT;a.nodeType===Node.TEXT_NODE?N(a)&&(d=NodeFilter.FILTER_ACCEPT):E(a)&&(d=NodeFilter.FILTER_SKIP);return d},NodeFilter.SHOW_ELEMENT|NodeFilter.SHOW_TEXT);d||O(a,b);return b};this.getTextElements=D;this.getParagraphElements=function(a){var d;d=aa.getNodesInRange(a,function(a){var d=NodeFilter.FILTER_REJECT;if(f(a))d=NodeFilter.FILTER_ACCEPT; +else if(E(a)||q(a))d=NodeFilter.FILTER_SKIP;return d},NodeFilter.SHOW_ELEMENT);V(a.startContainer,d,f);return d};this.getImageElements=function(a){var d;d=aa.getNodesInRange(a,function(a){var d=NodeFilter.FILTER_SKIP;g(a)&&(d=NodeFilter.FILTER_ACCEPT);return d},NodeFilter.SHOW_ELEMENT);V(a.startContainer,d,g);return d};this.getHyperlinkElements=function(a){var d=[],c=a.cloneRange();a.collapsed&&a.endContainer.nodeType===Node.ELEMENT_NODE&&(a=W(a.endContainer,a.endOffset),a.nodeType===Node.TEXT_NODE&& +c.setEnd(a,1));D(c,!0,!1).forEach(function(a){for(a=a.parentNode;!f(a);){if(b(a)&&-1===d.indexOf(a)){d.push(a);break}a=a.parentNode}});c.detach();return d};this.getNormalizedFontFamilyName=function(a){/^(["'])(?:.|[\n\r])*?\1$/.test(a)||(a=a.replace(/^[ \t\r\n\f]*((?:.|[\n\r])*?)[ \t\r\n\f]*$/,"$1"),/[ \t\r\n\f]/.test(a)&&(a="'"+a.replace(/[ \t\r\n\f]+/g," ")+"'"));return a}};odf.OdfUtils=new odf.OdfUtilsImpl; +gui.OdfTextBodyNodeFilter=function(){var g=odf.OdfUtils,k=Node.TEXT_NODE,c=NodeFilter.FILTER_REJECT,b=NodeFilter.FILTER_ACCEPT,f=odf.Namespaces.textns;this.acceptNode=function(n){if(n.nodeType===k){if(!g.isGroupingElement(n.parentNode))return c}else if(n.namespaceURI===f&&"tracked-changes"===n.localName)return c;return b}};xmldom.LSSerializerFilter=function(){};xmldom.LSSerializerFilter.prototype.acceptNode=function(g){}; +odf.OdfNodeFilter=function(){this.acceptNode=function(g){return"http://www.w3.org/1999/xhtml"===g.namespaceURI?NodeFilter.FILTER_SKIP:g.namespaceURI&&g.namespaceURI.match(/^urn:webodf:/)?NodeFilter.FILTER_REJECT:NodeFilter.FILTER_ACCEPT}};xmldom.XPathIterator=function(){};xmldom.XPathIterator.prototype.next=function(){};xmldom.XPathIterator.prototype.reset=function(){}; +function createXPathSingleton(){function g(b,a,d){return-1!==b&&(b=e&&d.push(k(b.substring(a,c)))):"["===b[c]&&(0>=e&&(a=c+1),e+=1),c+=1;return c};q=function(c,a,d){var m,h,e,n;for(m=0;m/g,">").replace(/'/g,"'").replace(/"/g,""")}function c(f,n){var g="",r=b.filter?b.filter.acceptNode(n):NodeFilter.FILTER_ACCEPT,q;if(r===NodeFilter.FILTER_ACCEPT&&n.nodeType===Node.ELEMENT_NODE){f.push();q=f.getQName(n);var e,l=n.attributes,a,d,m,h="",y;e="<"+q;a=l.length;for(d=0;d")}if(r===NodeFilter.FILTER_ACCEPT||r===NodeFilter.FILTER_SKIP){for(r=n.firstChild;r;)g+=c(f,r),r=r.nextSibling;n.nodeValue&&(g+=k(n.nodeValue))}q&&(g+="",f.pop());return g}var b=this;this.filter=null;this.writeToString=function(b,n){if(!b)return"";var k=new g(n);return c(k,b)}}; +(function(){function g(b){var a,d=r.length;for(a=0;ad)break;h=h.nextSibling}b.insertBefore(a,h)}}}var f=new odf.StyleInfo,n=core.DomUtils,p=odf.Namespaces.stylens,r="meta settings scripts font-face-decls styles automatic-styles master-styles body".split(" "), +q=Date.now()+"_webodf_",e=new core.Base64;odf.ODFElement=function(){};odf.ODFDocumentElement=function(){};odf.ODFDocumentElement.prototype=new odf.ODFElement;odf.ODFDocumentElement.prototype.constructor=odf.ODFDocumentElement;odf.ODFDocumentElement.prototype.fontFaceDecls=null;odf.ODFDocumentElement.prototype.manifest=null;odf.ODFDocumentElement.prototype.settings=null;odf.ODFDocumentElement.namespaceURI="urn:oasis:names:tc:opendocument:xmlns:office:1.0";odf.ODFDocumentElement.localName="document"; +odf.AnnotationElement=function(){};odf.OdfPart=function(b,a,d,c){var h=this;this.size=0;this.type=null;this.name=b;this.container=d;this.url=null;this.mimetype=a;this.onstatereadychange=this.document=null;this.EMPTY=0;this.LOADING=1;this.DONE=2;this.state=this.EMPTY;this.data="";this.load=function(){null!==c&&(this.mimetype=a,c.loadAsDataURL(b,a,function(a,d){a&&runtime.log(a);h.url=d;if(h.onchange)h.onchange(h);if(h.onstatereadychange)h.onstatereadychange(h)}))}};odf.OdfPart.prototype.load=function(){}; +odf.OdfPart.prototype.getUrl=function(){return this.data?"data:;base64,"+e.toBase64(this.data):null};odf.OdfContainer=function a(d,m){function h(a){for(var d=a.firstChild,b;d;)b=d.nextSibling,d.nodeType===Node.ELEMENT_NODE?h(d):d.nodeType===Node.PROCESSING_INSTRUCTION_NODE&&a.removeChild(d),d=b}function g(a){var d={},b,c,h=a.ownerDocument.createNodeIterator(a,NodeFilter.SHOW_ELEMENT,null,!1);for(a=h.nextNode();a;)"urn:oasis:names:tc:opendocument:xmlns:office:1.0"===a.namespaceURI&&("annotation"=== +a.localName?(b=a.getAttributeNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0","name"))&&(d.hasOwnProperty(b)?runtime.log("Warning: annotation name used more than once with : '"+b+"'"):d[b]=a):"annotation-end"===a.localName&&((b=a.getAttributeNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0","name"))?d.hasOwnProperty(b)?(c=d[b],c.annotationEndElement?runtime.log("Warning: annotation name used more than once with : '"+b+"'"):c.annotationEndElement= +a):runtime.log("Warning: annotation end without an annotation start, name: '"+b+"'"):runtime.log("Warning: annotation end without a name found"))),a=h.nextNode()}function r(a,d){for(var b=a&&a.firstChild;b;)b.nodeType===Node.ELEMENT_NODE&&b.setAttributeNS("urn:webodf:names:scope","scope",d),b=b.nextSibling}function z(a,d){for(var b=B.rootElement.meta,b=b&&b.firstChild;b&&(b.namespaceURI!==a||b.localName!==d);)b=b.nextSibling;for(b=b&&b.firstChild;b&&b.nodeType!==Node.TEXT_NODE;)b=b.nextSibling;return b? +b.data:null}function w(a){var d={},b;for(a=a.firstChild;a;)a.nodeType===Node.ELEMENT_NODE&&a.namespaceURI===p&&"font-face"===a.localName&&(b=a.getAttributeNS(p,"name"),d[b]=a),a=a.nextSibling;return d}function v(a,d){var b=null,c,h,e;if(a)for(b=a.cloneNode(!0),c=b.firstElementChild;c;)h=c.nextElementSibling,(e=c.getAttributeNS("urn:webodf:names:scope","scope"))&&e!==d&&b.removeChild(c),c=h;return b}function u(a,d){var b,c,h,e=null,m={};if(a)for(d.forEach(function(a){f.collectUsedFontFaces(m,a)}), +e=a.cloneNode(!0),b=e.firstElementChild;b;)c=b.nextElementSibling,h=b.getAttributeNS(p,"name"),m[h]||e.removeChild(b),b=c;return e}function t(a){var d=B.rootElement.ownerDocument,b;if(a){h(a.documentElement);try{b=d.importNode(a.documentElement,!0)}catch(c){}}return b}function A(a){B.state=a;if(B.onchange)B.onchange(B);if(B.onstatereadychange)B.onstatereadychange(B)}function I(a){Q=null;B.rootElement=a;a.fontFaceDecls=n.getDirectChild(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","font-face-decls"); +a.styles=n.getDirectChild(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","styles");a.automaticStyles=n.getDirectChild(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","automatic-styles");a.masterStyles=n.getDirectChild(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","master-styles");a.body=n.getDirectChild(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","body");a.meta=n.getDirectChild(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","meta");a.settings=n.getDirectChild(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0", +"settings");a.scripts=n.getDirectChild(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","scripts");g(a)}function K(d){var c=t(d),h=B.rootElement,e;c&&"document-styles"===c.localName&&"urn:oasis:names:tc:opendocument:xmlns:office:1.0"===c.namespaceURI?(h.fontFaceDecls=n.getDirectChild(c,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","font-face-decls"),b(h,h.fontFaceDecls),e=n.getDirectChild(c,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","styles"),h.styles=e||d.createElementNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0", +"styles"),b(h,h.styles),e=n.getDirectChild(c,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","automatic-styles"),h.automaticStyles=e||d.createElementNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0","automatic-styles"),r(h.automaticStyles,"document-styles"),b(h,h.automaticStyles),c=n.getDirectChild(c,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","master-styles"),h.masterStyles=c||d.createElementNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0","master-styles"),b(h,h.masterStyles), +f.prefixStyleNames(h.automaticStyles,q,h.masterStyles)):A(a.INVALID)}function L(d){d=t(d);var c,h,e,m;if(d&&"document-content"===d.localName&&"urn:oasis:names:tc:opendocument:xmlns:office:1.0"===d.namespaceURI){c=B.rootElement;e=n.getDirectChild(d,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","font-face-decls");if(c.fontFaceDecls&&e){m=c.fontFaceDecls;var g,k,O,q,D={};h=w(m);q=w(e);for(e=e.firstElementChild;e;){g=e.nextElementSibling;if(e.namespaceURI===p&&"font-face"===e.localName)if(k=e.getAttributeNS(p, +"name"),h.hasOwnProperty(k)){if(!e.isEqualNode(h[k])){O=k;for(var y=h,E=q,u=0,W=void 0,W=O=O.replace(/\d+$/,"");y.hasOwnProperty(W)||E.hasOwnProperty(W);)u+=1,W=O+u;O=W;e.setAttributeNS(p,"style:name",O);m.appendChild(e);h[O]=e;delete q[k];D[k]=O}}else m.appendChild(e),h[k]=e,delete q[k];e=g}m=D}else e&&(c.fontFaceDecls=e,b(c,e));h=n.getDirectChild(d,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","automatic-styles");r(h,"document-content");m&&f.changeFontFaceNames(h,m);if(c.automaticStyles&&h)for(m= +h.firstChild;m;)c.automaticStyles.appendChild(m),m=h.firstChild;else h&&(c.automaticStyles=h,b(c,h));d=n.getDirectChild(d,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","body");if(null===d)throw" tag is mising.";c.body=d;b(c,c.body)}else A(a.INVALID)}function E(a){a=t(a);var d;a&&"document-meta"===a.localName&&"urn:oasis:names:tc:opendocument:xmlns:office:1.0"===a.namespaceURI&&(d=B.rootElement,d.meta=n.getDirectChild(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","meta"), +b(d,d.meta))}function N(a){a=t(a);var d;a&&"document-settings"===a.localName&&"urn:oasis:names:tc:opendocument:xmlns:office:1.0"===a.namespaceURI&&(d=B.rootElement,d.settings=n.getDirectChild(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","settings"),b(d,d.settings))}function O(a){a=t(a);var d;if(a&&"manifest"===a.localName&&"urn:oasis:names:tc:opendocument:xmlns:manifest:1.0"===a.namespaceURI)for(d=B.rootElement,d.manifest=a,a=d.manifest.firstElementChild;a;)"file-entry"===a.localName&&"urn:oasis:names:tc:opendocument:xmlns:manifest:1.0"=== +a.namespaceURI&&(M[a.getAttributeNS("urn:oasis:names:tc:opendocument:xmlns:manifest:1.0","full-path")]=a.getAttributeNS("urn:oasis:names:tc:opendocument:xmlns:manifest:1.0","media-type")),a=a.nextElementSibling}function D(a,d,b){a=n.getElementsByTagName(a,d);var c;for(c=0;c'}function P(){var a=new xmldom.LSSerializer,d=R("document-meta");a.filter=new odf.OdfNodeFilter;d+=a.writeToString(B.rootElement.meta,odf.Namespaces.namespaceMap);return d+""}function aa(a,d){var b=document.createElementNS("urn:oasis:names:tc:opendocument:xmlns:manifest:1.0","manifest:file-entry");b.setAttributeNS("urn:oasis:names:tc:opendocument:xmlns:manifest:1.0","manifest:full-path",a);b.setAttributeNS("urn:oasis:names:tc:opendocument:xmlns:manifest:1.0", +"manifest:media-type",d);return b}function S(){var a=runtime.parseXML(''),d=a.documentElement,b=new xmldom.LSSerializer,c;for(c in M)M.hasOwnProperty(c)&&d.appendChild(aa(c,M[c]));b.filter=new odf.OdfNodeFilter;return'\n'+b.writeToString(a,odf.Namespaces.namespaceMap)}function fa(){var a,d,b,c=odf.Namespaces.namespaceMap, +h=new xmldom.LSSerializer,e=R("document-styles");d=v(B.rootElement.automaticStyles,"document-styles");b=B.rootElement.masterStyles.cloneNode(!0);a=u(B.rootElement.fontFaceDecls,[b,B.rootElement.styles,d]);f.removePrefixFromStyleNames(d,q,b);h.filter=new k(b,d);e+=h.writeToString(a,c);e+=h.writeToString(B.rootElement.styles,c);e+=h.writeToString(d,c);e+=h.writeToString(b,c);return e+""}function ha(){var a,d,b=odf.Namespaces.namespaceMap,h=new xmldom.LSSerializer,e=R("document-content"); +d=v(B.rootElement.automaticStyles,"document-content");a=u(B.rootElement.fontFaceDecls,[d]);h.filter=new c(B.rootElement.body,d);e+=h.writeToString(a,b);e+=h.writeToString(d,b);e+=h.writeToString(B.rootElement.body,b);return e+""}function C(d,b){runtime.loadXML(d,function(d,c){if(d)b(d);else if(c){V(c);W(c.documentElement);var h=t(c);h&&"document"===h.localName&&"urn:oasis:names:tc:opendocument:xmlns:office:1.0"===h.namespaceURI?(I(h),A(a.DONE)):A(a.INVALID)}else b("No DOM was loaded.")})} +function Z(a,d){var c;c=B.rootElement;var h=c.meta;h||(c.meta=h=document.createElementNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0","meta"),b(c,h));c=h;a&&n.mapKeyValObjOntoNode(c,a,odf.Namespaces.lookupNamespaceURI);d&&n.removeKeyElementsFromNode(c,d,odf.Namespaces.lookupNamespaceURI)}function ba(d,b){function c(a,d){var b;d||(d=a);b=document.createElementNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0",d);f[a]=b;f.appendChild(b)}var h=new core.Zip("",null),e="application/vnd.oasis.opendocument."+ +d+(!0===b?"-template":""),m=runtime.byteArrayFromString(e,"utf8"),f=B.rootElement,g=document.createElementNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0",d);h.save("mimetype",m,!1,new Date);c("meta");c("settings");c("scripts");c("fontFaceDecls","font-face-decls");c("styles");c("automaticStyles","automatic-styles");c("masterStyles","master-styles");c("body");f.body.appendChild(g);M["/"]=e;M["settings.xml"]="text/xml";M["meta.xml"]="text/xml";M["styles.xml"]="text/xml";M["content.xml"]="text/xml"; +A(a.DONE);return h}function U(){var a,d=new Date,b="";B.rootElement.settings&&B.rootElement.settings.firstElementChild&&(a=new xmldom.LSSerializer,b=R("document-settings"),a.filter=new odf.OdfNodeFilter,b+=a.writeToString(B.rootElement.settings,odf.Namespaces.namespaceMap),b+="");(a=b)?(a=runtime.byteArrayFromString(a,"utf8"),Y.save("settings.xml",a,!0,d)):Y.remove("settings.xml");b=runtime.getWindow();a="WebODF/"+webodf.Version;b&&(a=a+" "+b.navigator.userAgent);Z({"meta:generator":a}, +null);a=runtime.byteArrayFromString(P(),"utf8");Y.save("meta.xml",a,!0,d);a=runtime.byteArrayFromString(fa(),"utf8");Y.save("styles.xml",a,!0,d);a=runtime.byteArrayFromString(ha(),"utf8");Y.save("content.xml",a,!0,d);a=runtime.byteArrayFromString(S(),"utf8");Y.save("META-INF/manifest.xml",a,!0,d)}function ga(a,d){U();Y.writeAs(a,function(a){d(a)})}var B=this,Y,M={},Q,F="";this.onstatereadychange=m;this.state=this.onchange=null;this.getMetadata=z;this.setRootElement=I;this.getContentElement=function(){var a; +Q||(a=B.rootElement.body,Q=n.getDirectChild(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","text")||n.getDirectChild(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","presentation")||n.getDirectChild(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","spreadsheet"));if(!Q)throw"Could not find content element in .";return Q};this.getDocumentType=function(){var a=B.getContentElement();return a&&a.localName};this.isTemplate=function(){return"-template"===M["/"].substr(-9)}; +this.setIsTemplate=function(a){var d=M["/"],b="-template"===d.substr(-9);a!==b&&(d=a?d+"-template":d.substr(0,d.length-9),M["/"]=d,a=runtime.byteArrayFromString(d,"utf8"),Y.save("mimetype",a,!1,new Date))};this.getPart=function(a){return new odf.OdfPart(a,M[a],B,Y)};this.getPartData=function(a,d){Y.load(a,d)};this.setMetadata=Z;this.incrementEditingCycles=function(){var a=z(odf.Namespaces.metans,"editing-cycles"),a=a?parseInt(a,10):0;isNaN(a)&&(a=0);Z({"meta:editing-cycles":a+1},null);return a+1}; +this.createByteArray=function(a,d){U();Y.createByteArray(a,d)};this.saveAs=ga;this.save=function(a){ga(F,a)};this.getUrl=function(){return F};this.setBlob=function(a,d,b){b=e.convertBase64ToByteArray(b);Y.save(a,b,!1,new Date);M.hasOwnProperty(a)&&runtime.log(a+" has been overwritten.");M[a]=d};this.removeBlob=function(a){var d=Y.remove(a);runtime.assert(d,"file is not found: "+a);delete M[a]};this.state=a.LOADING;this.rootElement=function(a){var d=document.createElementNS(a.namespaceURI,a.localName), +b;a=new a.Type;for(b in a)a.hasOwnProperty(b)&&(d[b]=a[b]);return d}({Type:odf.ODFDocumentElement,namespaceURI:odf.ODFDocumentElement.namespaceURI,localName:odf.ODFDocumentElement.localName});d===odf.OdfContainer.DocumentType.TEXT?Y=ba("text"):d===odf.OdfContainer.DocumentType.TEXT_TEMPLATE?Y=ba("text",!0):d===odf.OdfContainer.DocumentType.PRESENTATION?Y=ba("presentation"):d===odf.OdfContainer.DocumentType.PRESENTATION_TEMPLATE?Y=ba("presentation",!0):d===odf.OdfContainer.DocumentType.SPREADSHEET? +Y=ba("spreadsheet"):d===odf.OdfContainer.DocumentType.SPREADSHEET_TEMPLATE?Y=ba("spreadsheet",!0):(F=d,Y=new core.Zip(F,function(d,b){Y=b;d?C(F,function(b){d&&(Y.error=d+"\n"+b,A(a.INVALID))}):J([{path:"styles.xml",handler:K},{path:"content.xml",handler:L},{path:"meta.xml",handler:E},{path:"settings.xml",handler:N},{path:"META-INF/manifest.xml",handler:O}])}))};odf.OdfContainer.EMPTY=0;odf.OdfContainer.LOADING=1;odf.OdfContainer.DONE=2;odf.OdfContainer.INVALID=3;odf.OdfContainer.SAVING=4;odf.OdfContainer.MODIFIED= +5;odf.OdfContainer.getContainer=function(a){return new odf.OdfContainer(a,null)}})();odf.OdfContainer.DocumentType={TEXT:1,TEXT_TEMPLATE:2,PRESENTATION:3,PRESENTATION_TEMPLATE:4,SPREADSHEET:5,SPREADSHEET_TEMPLATE:6};gui.AnnotatableCanvas=function(){};gui.AnnotatableCanvas.prototype.refreshSize=function(){};gui.AnnotatableCanvas.prototype.getZoomLevel=function(){};gui.AnnotatableCanvas.prototype.getSizer=function(){}; +gui.AnnotationViewManager=function(g,k,c,b){function f(d){var b=d.annotationEndElement,c=l.createRange(),e=d.getAttributeNS(odf.Namespaces.officens,"name");b&&(c.setStart(d,d.childNodes.length),c.setEnd(b,0),d=a.getTextNodes(c,!1),d.forEach(function(a){var d;a:{for(d=a.parentNode;d.namespaceURI!==odf.Namespaces.officens||"body"!==d.localName;){if("http://www.w3.org/1999/xhtml"===d.namespaceURI&&"webodf-annotationHighlight"===d.className&&d.getAttribute("annotation")===e){d=!0;break a}d=d.parentNode}d= +!1}d||(d=l.createElement("span"),d.className="webodf-annotationHighlight",d.setAttribute("annotation",e),a.parentNode.replaceChild(d,a),d.appendChild(a))}));c.detach()}function n(a){var b=g.getSizer();a?(c.style.display="inline-block",b.style.paddingRight=d.getComputedStyle(c).width):(c.style.display="none",b.style.paddingRight=0);g.refreshSize()}function p(){e.sort(function(a,d){return 0!==(a.compareDocumentPosition(d)&Node.DOCUMENT_POSITION_FOLLOWING)?-1:1})}function r(){var a;for(a=0;a=(n.getBoundingClientRect().top-r.bottom)/d?b.style.top=Math.abs(n.getBoundingClientRect().top-r.bottom)/d+20+"px":b.style.top="0px"): +b.style.top="0px";l.style.left=f.getBoundingClientRect().width/d+"px";var f=l.style,n=l.getBoundingClientRect().left/d,k=l.getBoundingClientRect().top/d,r=b.getBoundingClientRect().left/d,p=b.getBoundingClientRect().top/d,q=0,I=0,q=r-n,q=q*q,I=p-k,I=I*I,n=Math.sqrt(q+I);f.width=n+"px";k=Math.asin((b.getBoundingClientRect().top-l.getBoundingClientRect().top)/(d*parseFloat(l.style.width)));l.style.transform="rotate("+k+"rad)";l.style.MozTransform="rotate("+k+"rad)";l.style.WebkitTransform="rotate("+ +k+"rad)";l.style.msTransform="rotate("+k+"rad)"}}function q(a){var d=e.indexOf(a),b=a.parentNode.parentNode;"div"===b.localName&&(b.parentNode.insertBefore(a,b),b.parentNode.removeChild(b));a=a.getAttributeNS(odf.Namespaces.officens,"name");a=l.querySelectorAll('span.webodf-annotationHighlight[annotation="'+a+'"]');for(var c,b=0;bp||k.bottom>p)g.scrollTop=k.bottom-k.top<=p-f?g.scrollTop+(k.bottom-p):g.scrollTop+(k.top-f);k.leftn&&(g.scrollLeft=k.right-k.left<=n-b?g.scrollLeft+(k.right-n):g.scrollLeft-(b-k.left))}}}; +(function(){function g(c,n,k,r,q){var e,l=0,a;for(a in c)if(c.hasOwnProperty(a)){if(l===k){e=a;break}l+=1}e?n.getPartData(c[e].href,function(a,m){if(a)runtime.log(a);else if(m){var h="@font-face { font-family: "+(c[e].family||e)+"; src: url(data:application/x-font-ttf;charset=binary;base64,"+b.convertUTF8ArrayToBase64(m)+') format("truetype"); }';try{r.insertRule(h,r.cssRules.length)}catch(l){runtime.log("Problem inserting rule in CSS: "+runtime.toJson(l)+"\nRule: "+h)}}else runtime.log("missing font data for "+ +c[e].href);g(c,n,k+1,r,q)}):q&&q()}var k=xmldom.XPath,c=odf.OdfUtils,b=new core.Base64;odf.FontLoader=function(){this.loadFonts=function(b,n){for(var p=b.rootElement.fontFaceDecls;n.cssRules.length;)n.deleteRule(n.cssRules.length-1);if(p){var r={},q,e,l,a;if(p)for(p=k.getODFElementsWithXPath(p,"style:font-face[svg:font-face-src]",odf.Namespaces.lookupNamespaceURI),q=0;q text|list-item:first-child > :not(text|list):first-child:before',u+="{",u+="counter-increment: "+p+" 0;",u+="}",g(b,u));for(;l.counterIdStack.length>=k;)l.counterIdStack.pop();l.counterIdStack.push(p);t=l.contentRules[k.toString()]||"";for(u=1;u<=k;u+=1)t=t.replace(u+"webodf-listLevel",l.counterIdStack[u-1]);u='text|list[webodfhelper|counter-id="'+r+'"] > text|list-item > :not(text|list):first-child:before'; +u+="{";u+=t;u+="counter-increment: "+p+";";u+="}";g(b,u)}for(h=h.firstElementChild;h;)c(d,h,f,l),h=h.nextElementSibling}else l.continuedCounterIdStack=[]}var f=0,a="",d={};this.createCounterRules=function(a,b,n){var g=b.getAttributeNS(p,"id"),r=[];n&&(n=n.getAttributeNS("urn:webodf:names:helper","counter-id"),r=d[n].slice(0));a=new k(a,r);g?g="Y"+g:(f+=1,g="X"+f);c(g,b,0,a);d[g+"-level1-1"]=a.counterIdStack};this.initialiseCreatedCounters=function(){var d;d="office|document{"+("counter-reset: "+a+ +";");d+="}";g(b,d)}}var b=odf.Namespaces.fons,f=odf.Namespaces.stylens,n=odf.Namespaces.textns,p=odf.Namespaces.xmlns,r={1:"decimal",a:"lower-latin",A:"upper-latin",i:"lower-roman",I:"upper-roman"};odf.ListStyleToCss=function(){function k(a){var b=m.parseLength(a);return b?d.convert(b.value,b.unit,"px"):(runtime.log("Could not parse value '"+a+"'."),0)}function e(a){return a.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function l(a,d){var b;a&&(b=a.getAttributeNS(n,"style-name"));return b===d}function a(a, +d,b){d=d.getElementsByTagNameNS(n,"list");a=new c(a);var m,g,k,q,t,A,I={},K;for(K=0;K text|list-item > text|list",--x;x=E&&E.getAttributeNS(b,"text-align")||"left";switch(x){case "end":x="right";break;case "start":x="left"}"label-alignment"===N?(D=O&&O.getAttributeNS(b,"margin-left")||"0px",J=O&&O.getAttributeNS(b,"text-indent")||"0px",R=O&&O.getAttributeNS(n,"label-followed-by"),O=k(D)):(D=E&&E.getAttributeNS(n,"space-before")||"0px",V=E&&E.getAttributeNS(n,"min-label-width")||"0px", +W=E&&E.getAttributeNS(n,"min-label-distance")||"0px",O=k(D)+k(V));E=p+" > text|list-item";E+="{";E+="margin-left: "+O+"px;";E+="}";g(e,E);E=p+" > text|list-item > text|list";E+="{";E+="margin-left: "+-O+"px;";E+="}";g(e,E);E=p+" > text|list-item > :not(text|list):first-child:before";E+="{";E+="text-align: "+x+";";E+="display: inline-block;";"label-alignment"===N?(E+="margin-left: "+J+";","listtab"===R&&(E+="padding-right: 0.2cm;")):(E+="min-width: "+V+";",E+="margin-left: "+(0===parseFloat(V)?"": +"-")+V+";",E+="padding-right: "+W+";");E+="}";g(e,E)}c=c.nextElementSibling}});a(d,e,m)}}})();odf.LazyStyleProperties=function(g,k){var c={};this.value=function(b){var f;c.hasOwnProperty(b)?f=c[b]:(f=k[b](),void 0===f&&g&&(f=g.value(b)),c[b]=f);return f};this.reset=function(b){g=b;c={}}}; +odf.StyleParseUtils=function(){function g(c){var b,f;c=(c=/(-?[0-9]*[0-9][0-9]*(\.[0-9]*)?|0+\.[0-9]*[1-9][0-9]*|\.[0-9]*[1-9][0-9]*)((cm)|(mm)|(in)|(pt)|(pc)|(px))/.exec(c))?{value:parseFloat(c[1]),unit:c[3]}:null;f=c&&c.unit;"px"===f?b=c.value:"cm"===f?b=c.value/2.54*96:"mm"===f?b=c.value/25.4*96:"in"===f?b=96*c.value:"pt"===f?b=c.value/.75:"pc"===f&&(b=16*c.value);return b}var k=odf.Namespaces.stylens;this.parseLength=g;this.parsePositiveLengthOrPercent=function(c,b,f){var n;c&&(n=parseFloat(c.substr(0, +c.indexOf("%"))),isNaN(n)&&(n=void 0));var k;void 0!==n?(f&&(k=f.value(b)),n=void 0===k?void 0:k/100*n):n=g(c);return n};this.getPropertiesElement=function(c,b,f){for(b=f?f.nextElementSibling:b.firstElementChild;null!==b&&(b.localName!==c||b.namespaceURI!==k);)b=b.nextElementSibling;return b};this.parseAttributeList=function(c){c&&(c=c.replace(/^\s*(.*?)\s*$/g,"$1"));return c&&0n.value&&(m="0.75pt"+h);h=m}else if(V.hasOwnProperty(e[1])){var m= +a,f=e[0],n=e[1],g=J.parseLength(h),r=void 0,p=void 0,q=void 0,O=void 0,q=void 0;if(g&&"%"===g.unit){r=g.value/100;p=k(m.parentNode);for(O="0";p;){if(q=y.getDirectChild(p,l,"paragraph-properties"))if(q=J.parseLength(q.getAttributeNS(f,n))){if("%"!==q.unit){O=q.value*r+q.unit;break}r*=q.value/100}p=k(p)}h=O}}e[2]&&(b+=e[2]+":"+h+";")}return b}function b(a,d,b,c){return d+d+b+b+c+c}function f(a,d){var b=[a],c=d.derivedStyles;Object.keys(c).forEach(function(a){a=f(a,c[a]);b=b.concat(a)});return b}function n(a, +d,b,c){function e(d,b){var c=[],h;d.forEach(function(a){m.forEach(function(d){c.push('draw|page[webodfhelper|page-style-name="'+d+'"] draw|frame[presentation|class="'+a+'"]')})});0 +z&&(a=z);for(d=Math.floor(a/c)*c;!b&&0<=d;)b=m[d],d-=c;for(b=b||x;b.nextBookmark&&b.nextBookmark.steps<=a;)e.check(),b=b.nextBookmark;runtime.assert(-1===a||b.steps<=a,"Bookmark @"+p(b)+" at step "+b.steps+" exceeds requested step of "+a);return b}function a(a){a.previousBookmark&&(a.previousBookmark.nextBookmark=a.nextBookmark);a.nextBookmark&&(a.nextBookmark.previousBookmark=a.previousBookmark)}function d(a){for(var d,b=null;!b&&a&&a!==k;)(d=q(a))&&(b=h[d])&&b.node!==a&&(runtime.log("Cloned node detected. Creating new bookmark"), +b=null,a.removeAttributeNS("urn:webodf:names:steps","nodeId")),a=a.parentNode;return b}var m={},h={},y=core.DomUtils,x,z,w=Node.DOCUMENT_POSITION_FOLLOWING,v=Node.DOCUMENT_POSITION_PRECEDING;this.updateBookmark=function(d,b){var g,n=Math.ceil(d/c)*c,p,v,E;if(void 0!==z&&zp.steps)m[n]=v;r()};this.setToClosestStep=function(a,d){var b;r();b=l(a);b.setIteratorPosition(d); +return b.steps};this.setToClosestDomPoint=function(a,b,c){var e,h;r();if(a===k&&0===b)e=x;else if(a===k&&b===k.childNodes.length)for(h in e=x,m)m.hasOwnProperty(h)&&(a=m[h],a.steps>e.steps&&(e=a));else if(e=d(a.childNodes.item(b)||a),!e)for(c.setUnfilteredPosition(a,b);!e&&c.previousNode();)e=d(c.getCurrentNode());e=e||x;void 0!==z&&e.steps>z&&(e=l(z));e.setIteratorPosition(c);return e.steps};this.damageCacheAfterStep=function(a){0>a&&(a=-1);void 0===z?z=a:aa)throw new RangeError("Requested steps is negative ("+a+")");for(b=p.setToClosestStep(a,k);bq.comparePoints(g,0,a,b),a=g,b=b?0:g.childNodes.length);k.setUnfilteredPosition(a,b);n(k,h)||k.setUnfilteredPosition(a,b);h=k.container();b=k.unfilteredDomOffset();a=p.setToClosestDomPoint(h,b,k);if(0>q.comparePoints(k.container(),k.unfilteredDomOffset(),h,b))return 0=e.textNode.length?null:e.textNode.splitText(e.offset));for(d=e.textNode;d!==a;){d=d.parentNode;m=d.cloneNode(!1);h&&m.appendChild(h);if(y)for(;y&&y.nextSibling;)m.appendChild(y.nextSibling);else for(;d.firstChild;)m.appendChild(d.firstChild);d.parentNode.insertBefore(m,d.nextSibling);y=d;h=m}p.isListItem(h)&&(h=h.childNodes.item(0));n?h.setAttributeNS(r,"text:style-name",n):h.removeAttributeNS(r,"style-name");0===e.textNode.length&& +e.textNode.parentNode.removeChild(e.textNode);c.emit(ops.OdtDocument.signalStepsInserted,{position:b});x&&f&&(c.moveCursor(g,b+1,0),c.emit(ops.Document.signalCursorMoved,x));c.fixCursorPositions();c.getOdfCanvas().refreshSize();c.emit(ops.OdtDocument.signalParagraphChanged,{paragraphElement:l,memberId:g,timeStamp:k});c.emit(ops.OdtDocument.signalParagraphChanged,{paragraphElement:h,memberId:g,timeStamp:k});c.getOdfCanvas().rerenderAnnotations();return!0};this.spec=function(){return{optype:"SplitParagraph", +memberid:g,timestamp:k,position:b,sourceParagraphPosition:c,paragraphStyleName:n,moveCursor:f}}}; +ops.OpUpdateMember=function(){function g(c){var f="//dc:creator[@editinfo:memberid='"+k+"']";c=xmldom.XPath.getODFElementsWithXPath(c.getRootNode(),f,function(b){return"editinfo"===b?"urn:webodf:names:editinfo":odf.Namespaces.lookupNamespaceURI(b)});for(f=0;f=e.width&&(e=null),g.detach();else if(k.isCharacterElement(f.container)||k.isCharacterFrame(f.container))e=b.getBoundingClientRect(f.container); +return e}var k=odf.OdfUtils,c=new odf.StepUtils,b=core.DomUtils,f=core.StepDirection.NEXT,n=gui.StepInfo.VisualDirection.LEFT_TO_RIGHT,p=gui.StepInfo.VisualDirection.RIGHT_TO_LEFT;this.getContentRect=g;this.moveToFilteredStep=function(b,c,e){function l(a,b){b.process(w,h,k)&&(a=!0,!x&&b.token&&(x=b.token));return a}var a=c===f,d,m,h,k,x,z=b.snapshot();d=!1;var w;do d=g(b),w={token:b.snapshot(),container:b.container,offset:b.offset,direction:c,visualDirection:c===f?n:p},m=b.nextStep()?g(b):null,b.restore(w.token), +a?(h=d,k=m):(h=m,k=d),d=e.reduce(l,!1);while(!d&&b.advanceStep(c));d||e.forEach(function(a){!x&&a.token&&(x=a.token)});b.restore(x||z);return Boolean(x)}}; +gui.Caret=function(g,k,c,b){function f(){a.style.opacity="0"===a.style.opacity?"1":"0";t.trigger()}function n(){y.selectNodeContents(h);return y.getBoundingClientRect()}function p(a){return E[a]!==L[a]}function r(){Object.keys(L).forEach(function(a){E[a]=L[a]})}function q(){if(!1===L.isShown||g.getSelectionType()!==ops.OdtCursor.RangeSelection||!b&&!g.getSelectedRange().collapsed)L.visibility="hidden",a.style.visibility="hidden",t.cancel();else if(L.visibility="visible",a.style.visibility="visible", +!1===L.isFocused)a.style.opacity="1",t.cancel();else{if(A||p("visibility"))a.style.opacity="1",t.cancel();t.trigger()}if(K||I){var c;c=g.getNode();var e,h,f=z.getBoundingClientRect(x.getSizer()),q=!1,y=0;c.removeAttributeNS("urn:webodf:names:cursor","caret-sizer-active");if(0c.height&&(c={top:c.top-(8-c.height)/2,height:8,right:c.right});l.style.height=c.height+"px";l.style.top=c.top+"px"; +l.style.left=c.right-c.width+"px";l.style.width=c.width?c.width+"px":"";m&&(c=runtime.getWindow().getComputedStyle(g.getNode(),null),c.font?m.style.font=c.font:(m.style.fontStyle=c.fontStyle,m.style.fontVariant=c.fontVariant,m.style.fontWeight=c.fontWeight,m.style.fontSize=c.fontSize,m.style.lineHeight=c.lineHeight,m.style.fontFamily=c.fontFamily))}L.isShown&&I&&k.scrollIntoView(a.getBoundingClientRect());p("isFocused")&&d.markAsFocussed(L.isFocused);r();K=I=A=!1}function e(a){l.parentNode.removeChild(l); +h.parentNode.removeChild(h);a()}var l,a,d,m,h,y,x=g.getDocument().getCanvas(),z=core.DomUtils,w=new gui.GuiStepUtils,v,u,t,A=!1,I=!1,K=!1,L={isFocused:!1,isShown:!0,visibility:"hidden"},E={isFocused:!L.isFocused,isShown:!L.isShown,visibility:"hidden"};this.handleUpdate=function(){K=!0;u.trigger()};this.refreshCursorBlinking=function(){A=!0;u.trigger()};this.setFocus=function(){L.isFocused=!0;u.trigger()};this.removeFocus=function(){L.isFocused=!1;u.trigger()};this.show=function(){L.isShown=!0;u.trigger()}; +this.hide=function(){L.isShown=!1;u.trigger()};this.setAvatarImageUrl=function(a){d.setImageUrl(a)};this.setColor=function(b){a.style.borderColor=b;d.setColor(b)};this.getCursor=function(){return g};this.getFocusElement=function(){return a};this.toggleHandleVisibility=function(){d.isVisible()?d.hide():d.show()};this.showHandle=function(){d.show()};this.hideHandle=function(){d.hide()};this.setOverlayElement=function(a){m=a;l.appendChild(a);K=!0;u.trigger()};this.ensureVisible=function(){I=!0;u.trigger()}; +this.getBoundingClientRect=function(){return z.getBoundingClientRect(l)};this.destroy=function(a){core.Async.destroyAll([u.destroy,t.destroy,d.destroy,e],a)};(function(){var b=g.getDocument(),e=[b.createRootFilter(g.getMemberId()),b.getPositionFilter()],m=b.getDOMDocument();y=m.createRange();h=m.createElement("span");h.className="webodf-caretSizer";h.textContent="|";g.getNode().appendChild(h);l=m.createElement("div");l.setAttributeNS("urn:webodf:names:editinfo","editinfo:memberid",g.getMemberId()); +l.className="webodf-caretOverlay";a=m.createElement("div");a.className="caret";l.appendChild(a);d=new gui.Avatar(l,c);x.getSizer().appendChild(l);v=b.createStepIterator(g.getNode(),0,e,b.getRootNode());u=core.Task.createRedrawTask(q);t=core.Task.createTimeoutTask(f,500);u.triggerImmediate()})()}; +odf.TextSerializer=function(){function g(b){var f="",n=k.filter?k.filter.acceptNode(b):NodeFilter.FILTER_ACCEPT,p=b.nodeType,r;if((n===NodeFilter.FILTER_ACCEPT||n===NodeFilter.FILTER_SKIP)&&c.isTextContentContainingNode(b))for(r=b.firstChild;r;)f+=g(r),r=r.nextSibling;n===NodeFilter.FILTER_ACCEPT&&(p===Node.ELEMENT_NODE&&c.isParagraph(b)?f+="\n":p===Node.TEXT_NODE&&b.textContent&&(f+=b.textContent));return f}var k=this,c=odf.OdfUtils;this.filter=null;this.writeToString=function(b){if(!b)return""; +b=g(b);"\n"===b[b.length-1]&&(b=b.substr(0,b.length-1));return b}};gui.MimeDataExporter=function(){var g;this.exportRangeToDataTransfer=function(k,c){var b;b=c.startContainer.ownerDocument.createElement("span");b.appendChild(c.cloneContents());b=g.writeToString(b);try{k.setData("text/plain",b)}catch(f){k.setData("Text",b)}};g=new odf.TextSerializer;g.filter=new odf.OdfNodeFilter}; +gui.Clipboard=function(g){this.setDataFromRange=function(k,c){var b,f=k.clipboardData;b=runtime.getWindow();!f&&b&&(f=b.clipboardData);f?(b=!0,g.exportRangeToDataTransfer(f,c),k.preventDefault()):b=!1;return b}}; +gui.SessionContext=function(g,k){var c=g.getOdtDocument(),b=odf.OdfUtils;this.isLocalCursorWithinOwnAnnotation=function(){var f=c.getCursor(k),g;if(!f)return!1;g=f&&f.getNode();f=c.getMember(k).getProperties().fullName;return(g=b.getParentAnnotation(g,c.getRootNode()))&&b.getAnnotationCreator(g)===f?!0:!1}}; +gui.StyleSummary=function(g){function k(b,c){var k=b+"|"+c,q;f.hasOwnProperty(k)||(q=[],g.forEach(function(e){e=(e=e.styleProperties[b])&&e[c];-1===q.indexOf(e)&&q.push(e)}),f[k]=q);return f[k]}function c(b,c,f){return function(){var g=k(b,c);return f.length>=g.length&&g.every(function(b){return-1!==f.indexOf(b)})}}function b(b,c){var f=k(b,c);return 1===f.length?f[0]:void 0}var f={};this.getPropertyValues=k;this.getCommonValue=b;this.isBold=c("style:text-properties","fo:font-weight",["bold"]);this.isItalic= +c("style:text-properties","fo:font-style",["italic"]);this.hasUnderline=c("style:text-properties","style:text-underline-style",["solid"]);this.hasStrikeThrough=c("style:text-properties","style:text-line-through-style",["solid"]);this.fontSize=function(){var c=b("style:text-properties","fo:font-size");return c&&parseFloat(c)};this.fontName=function(){return b("style:text-properties","style:font-name")};this.isAlignedLeft=c("style:paragraph-properties","fo:text-align",["left","start"]);this.isAlignedCenter= +c("style:paragraph-properties","fo:text-align",["center"]);this.isAlignedRight=c("style:paragraph-properties","fo:text-align",["right","end"]);this.isAlignedJustified=c("style:paragraph-properties","fo:text-align",["justify"]);this.text={isBold:this.isBold,isItalic:this.isItalic,hasUnderline:this.hasUnderline,hasStrikeThrough:this.hasStrikeThrough,fontSize:this.fontSize,fontName:this.fontName};this.paragraph={isAlignedLeft:this.isAlignedLeft,isAlignedCenter:this.isAlignedCenter,isAlignedRight:this.isAlignedRight, +isAlignedJustified:this.isAlignedJustified}}; +gui.DirectFormattingController=function(g,k,c,b,f,n,p){function r(){return U.value().styleSummary}function q(){return U.value().enabledFeatures}function e(a){var b;a.collapsed?(b=a.startContainer,b.hasChildNodes()&&a.startOffseta.clientWidth||a.scrollHeight>a.clientHeight)&&b.push(new l(a)),a=a.parentNode;b.push(new e(v));return b}function w(){var a; +h()||(a=z(K),x(),K.focus(),a.forEach(function(a){a.restore()}))}var v=runtime.getWindow(),u={beforecut:!0,beforepaste:!0,longpress:!0,drag:!0,dragstop:!0},t={mousedown:!0,mouseup:!0,focus:!0},A={},I={},K,L=g.getCanvas().getElement(),E=this,N={};this.addFilter=function(b,d){a(b,!0).filters.push(d)};this.removeFilter=function(b,d){var c=a(b,!0),e=c.filters.indexOf(d);-1!==e&&c.filters.splice(e,1)};this.subscribe=d;this.unsubscribe=m;this.hasFocus=h;this.focus=w;this.getEventTrap=function(){return K}; +this.setEditing=function(a){var b=h();b&&K.blur();a?K.removeAttribute("readOnly"):K.setAttribute("readOnly","true");b&&w()};this.destroy=function(a){m("touchstart",q);Object.keys(N).forEach(function(a){b(parseInt(a,10))});N.length=0;Object.keys(A).forEach(function(a){A[a].destroy()});A={};m("mousedown",y);m("mouseup",x);m("contextmenu",x);Object.keys(I).forEach(function(a){I[a].destroy()});I={};K.parentNode.removeChild(K);a()};(function(){var a=g.getOdfCanvas().getSizer(),b=a.ownerDocument;runtime.assert(Boolean(v), +"EventManager requires a window object to operate correctly");K=b.createElement("textarea");K.id="eventTrap";K.setAttribute("tabindex","-1");K.setAttribute("readOnly","true");K.setAttribute("rows","1");a.appendChild(K);d("mousedown",y);d("mouseup",x);d("contextmenu",x);A.longpress=new c("longpress",["touchstart","touchmove","touchend"],n);A.drag=new c("drag",["touchstart","touchmove","touchend"],p);A.dragstop=new c("dragstop",["drag","touchend"],r);d("touchstart",q)})()}; +gui.IOSSafariSupport=function(g){function k(){c.innerHeight!==c.outerHeight&&(b.style.display="none",runtime.requestAnimationFrame(function(){b.style.display="block"}))}var c=runtime.getWindow(),b=g.getEventTrap();this.destroy=function(c){g.unsubscribe("focus",k);b.removeAttribute("autocapitalize");b.style.WebkitTransform="";c()};g.subscribe("focus",k);b.setAttribute("autocapitalize","off");b.style.WebkitTransform="translateX(-10000px)"}; +gui.HyperlinkController=function(g,k,c,b){function f(){var b=!0;!0===k.getState(gui.CommonConstraints.EDIT.REVIEW_MODE)&&(b=c.isLocalCursorWithinOwnAnnotation());b!==e&&(e=b,q.emit(gui.HyperlinkController.enabledChanged,e))}function n(c){c.getMemberId()===b&&f()}var p=odf.OdfUtils,r=g.getOdtDocument(),q=new core.EventNotifier([gui.HyperlinkController.enabledChanged]),e=!1;this.isEnabled=function(){return e};this.subscribe=function(b,a){q.subscribe(b,a)};this.unsubscribe=function(b,a){q.unsubscribe(b, +a)};this.addHyperlink=function(c,a){if(e){var d=r.getCursorSelection(b),f=new ops.OpApplyHyperlink,h=[];if(0===d.length||a)a=a||c,f=new ops.OpInsertText,f.init({memberid:b,position:d.position,text:a}),d.length=a.length,h.push(f);f=new ops.OpApplyHyperlink;f.init({memberid:b,position:d.position,length:d.length,hyperlink:c});h.push(f);g.enqueue(h)}};this.removeHyperlinks=function(){if(e){var c=r.createPositionIterator(r.getRootNode()),a=r.getCursor(b).getSelectedRange(),d=p.getHyperlinkElements(a), +f=a.collapsed&&1===d.length,h=r.getDOMDocument().createRange(),k=[],n,q;0!==d.length&&(d.forEach(function(a){h.selectNodeContents(a);n=r.convertDomToCursorRange({anchorNode:h.startContainer,anchorOffset:h.startOffset,focusNode:h.endContainer,focusOffset:h.endOffset});q=new ops.OpRemoveHyperlink;q.init({memberid:b,position:n.position,length:n.length});k.push(q)}),f||(f=d[0],-1===a.comparePoint(f,0)&&(h.setStart(f,0),h.setEnd(a.startContainer,a.startOffset),n=r.convertDomToCursorRange({anchorNode:h.startContainer, +anchorOffset:h.startOffset,focusNode:h.endContainer,focusOffset:h.endOffset}),0k.width&&(v=k.width/n.width);n.height>k.height&&(u=k.height/n.height);k=Math.min(v,u);n= +{width:n.width*k,height:n.height*k}}k=p.convert(n.width,"px","cm")+"cm";p=p.convert(n.height,"px","cm")+"cm";u=e.getOdfCanvas().odfContainer().rootElement.styles;n=d.toLowerCase();var v=r.hasOwnProperty(n)?r[n]:null,t;n=[];runtime.assert(null!==v,"Image type is not supported: "+d);v="Pictures/"+f.generateImageName()+v;t=new ops.OpSetBlob;t.init({memberid:b,filename:v,mimetype:d,content:c});n.push(t);a.getStyleElement("Graphics","graphic",[u])||(d=new ops.OpAddStyle,d.init({memberid:b,styleName:"Graphics", +styleFamily:"graphic",isAutomaticStyle:!1,setProperties:{"style:graphic-properties":{"text:anchor-type":"paragraph","svg:x":"0cm","svg:y":"0cm","style:wrap":"dynamic","style:number-wrapped-paragraphs":"no-limit","style:wrap-contour":"false","style:vertical-pos":"top","style:vertical-rel":"paragraph","style:horizontal-pos":"center","style:horizontal-rel":"paragraph"}}}),n.push(d));d=f.generateStyleName();c=new ops.OpAddStyle;c.init({memberid:b,styleName:d,styleFamily:"graphic",isAutomaticStyle:!0, +setProperties:{"style:parent-style-name":"Graphics","style:graphic-properties":{"style:vertical-pos":"top","style:vertical-rel":"baseline","style:horizontal-pos":"center","style:horizontal-rel":"paragraph","fo:background-color":"transparent","style:background-transparency":"100%","style:shadow":"none","style:mirror":"none","fo:clip":"rect(0cm, 0cm, 0cm, 0cm)","draw:luminance":"0%","draw:contrast":"0%","draw:red":"0%","draw:green":"0%","draw:blue":"0%","draw:gamma":"100%","draw:color-inversion":"false", +"draw:image-opacity":"100%","draw:color-mode":"standard"}}});n.push(c);t=new ops.OpInsertImage;t.init({memberid:b,position:e.getCursorPosition(b),filename:v,frameWidth:k,frameHeight:p,frameStyleName:d,frameName:f.generateFrameName()});n.push(t);g.enqueue(n)}};this.destroy=function(a){e.unsubscribe(ops.Document.signalCursorMoved,p);k.unsubscribe(gui.CommonConstraints.EDIT.REVIEW_MODE,n);a()};e.subscribe(ops.Document.signalCursorMoved,p);k.subscribe(gui.CommonConstraints.EDIT.REVIEW_MODE,n);n()}; +gui.ImageController.enabledChanged="enabled/changed"; +gui.ImageSelector=function(g){function k(){var c=g.getSizer(),k=f.createElement("div");k.id="imageSelector";k.style.borderWidth="1px";c.appendChild(k);b.forEach(function(b){var c=f.createElement("div");c.className=b;k.appendChild(c)});return k}var c=odf.Namespaces.svgns,b="topLeft topRight bottomRight bottomLeft topMiddle rightMiddle bottomMiddle leftMiddle".split(" "),f=g.getElement().ownerDocument,n=!1;this.select=function(b){var r,q,e=f.getElementById("imageSelector");e||(e=k());n=!0;r=e.parentNode; +q=b.getBoundingClientRect();var l=r.getBoundingClientRect(),a=g.getZoomLevel();r=(q.left-l.left)/a-1;q=(q.top-l.top)/a-1;e.style.display="block";e.style.left=r+"px";e.style.top=q+"px";e.style.width=b.getAttributeNS(c,"width");e.style.height=b.getAttributeNS(c,"height")};this.clearSelection=function(){var b;n&&(b=f.getElementById("imageSelector"))&&(b.style.display="none");n=!1};this.isSelectorElement=function(b){var c=f.getElementById("imageSelector");return c?b===c||b.parentNode===c:!1}}; +(function(){function g(g){function c(b){p=b.which&&String.fromCharCode(b.which)===n;n=void 0;return!1===p}function b(){p=!1}function f(b){n=b.data;p=!1}var n,p=!1;this.destroy=function(n){g.unsubscribe("textInput",b);g.unsubscribe("compositionend",f);g.removeFilter("keypress",c);n()};g.subscribe("textInput",b);g.subscribe("compositionend",f);g.addFilter("keypress",c)}gui.InputMethodEditor=function(k,c){function b(b){a&&(b?a.getNode().setAttributeNS("urn:webodf:names:cursor","composing","true"):(a.getNode().removeAttributeNS("urn:webodf:names:cursor", +"composing"),h.textContent=""))}function f(){x&&(x=!1,b(!1),w.emit(gui.InputMethodEditor.signalCompositionEnd,{data:z}),z="")}function n(){I||(I=!0,f(),a&&a.getSelectedRange().collapsed?d.value="":d.value=u.writeToString(a.getSelectedRange().cloneContents()),d.setSelectionRange(0,d.value.length),I=!1)}function p(){c.hasFocus()&&y.trigger()}function r(){v=void 0;y.cancel();b(!0);x||w.emit(gui.InputMethodEditor.signalCompositionStart,{data:""})}function q(a){a=v=a.data;x=!0;z+=a;y.trigger()}function e(a){a.data!== +v&&(a=a.data,x=!0,z+=a,y.trigger());v=void 0}function l(){h.textContent=d.value}var a=null,d=c.getEventTrap(),m=d.ownerDocument,h,y,x=!1,z="",w=new core.EventNotifier([gui.InputMethodEditor.signalCompositionStart,gui.InputMethodEditor.signalCompositionEnd]),v,u,t=[],A,I=!1;this.subscribe=w.subscribe;this.unsubscribe=w.unsubscribe;this.registerCursor=function(b){b.getMemberId()===k&&(a=b,a.getNode().appendChild(h),b.subscribe(ops.OdtCursor.signalCursorUpdated,p),c.subscribe("input",l),c.subscribe("compositionupdate", +l))};this.removeCursor=function(b){a&&b===k&&(a.getNode().removeChild(h),a.unsubscribe(ops.OdtCursor.signalCursorUpdated,p),c.unsubscribe("input",l),c.unsubscribe("compositionupdate",l),a=null)};this.destroy=function(a){c.unsubscribe("compositionstart",r);c.unsubscribe("compositionend",q);c.unsubscribe("textInput",e);c.unsubscribe("keypress",f);c.unsubscribe("focus",n);core.Async.destroyAll(A,a)};(function(){u=new odf.TextSerializer;u.filter=new odf.OdfNodeFilter;c.subscribe("compositionstart",r); +c.subscribe("compositionend",q);c.subscribe("textInput",e);c.subscribe("keypress",f);c.subscribe("focus",n);t.push(new g(c));A=t.map(function(a){return a.destroy});h=m.createElement("span");h.setAttribute("id","composer");y=core.Task.createTimeoutTask(n,1);A.push(y.destroy)})()};gui.InputMethodEditor.signalCompositionStart="input/compositionstart";gui.InputMethodEditor.signalCompositionEnd="input/compositionend"})(); +gui.MetadataController=function(g,k){function c(b){n.emit(gui.MetadataController.signalMetadataChanged,b)}function b(b){var c=-1===p.indexOf(b);c||runtime.log("Setting "+b+" is restricted.");return c}var f=g.getOdtDocument(),n=new core.EventNotifier([gui.MetadataController.signalMetadataChanged]),p=["dc:creator","dc:date","meta:editing-cycles","meta:editing-duration","meta:document-statistic"];this.setMetadata=function(c,f){var e={},l="",a;c&&Object.keys(c).filter(b).forEach(function(a){e[a]=c[a]}); +f&&(l=f.filter(b).join(","));if(0f:!1}function c(b){null!==b&&!1===k(b)&&(f=Math.abs(b-g))}var b=this,f,n=gui.StepInfo.VisualDirection.LEFT_TO_RIGHT;this.token=void 0;this.process=function(f,g,q){var e,l;f.visualDirection===n?(e=g&&g.right,l=q&&q.left):(e=g&&g.left,l=q&&q.right);if(k(e)||k(l))return!0;if(g||q)c(e),c(l),b.token=f.token;return!1}}; +gui.LineBoundaryScanner=function(){var g=this,k=null;this.token=void 0;this.process=function(c,b,f){var n;if(n=f)if(k){var p=k;n=Math.min(p.bottom-p.top,f.bottom-f.top);var r=Math.max(p.top,f.top),p=Math.min(p.bottom,f.bottom)-r;n=.4>=(0b?a.previousSibling:a.nextSibling,d(f)===NodeFilter.FILTER_ACCEPT&&(c=f),a=a.parentNode;return c}function b(a,b){var d;return null===a?m.NO_NEIGHBOUR:p.isCharacterElement(a)?m.SPACE_CHAR:a.nodeType===f||p.isTextSpan(a)||p.isHyperlink(a)?(d=a.textContent.charAt(b()),q.test(d)?m.SPACE_CHAR:r.test(d)?m.PUNCTUATION_CHAR:m.WORD_CHAR):m.OTHER}var f=Node.TEXT_NODE,n=Node.ELEMENT_NODE, +p=odf.OdfUtils,r=/[!-#%-*,-\/:-;?-@\[-\]_{}\u00a1\u00ab\u00b7\u00bb\u00bf;\u00b7\u055a-\u055f\u0589-\u058a\u05be\u05c0\u05c3\u05c6\u05f3-\u05f4\u0609-\u060a\u060c-\u060d\u061b\u061e-\u061f\u066a-\u066d\u06d4\u0700-\u070d\u07f7-\u07f9\u0964-\u0965\u0970\u0df4\u0e4f\u0e5a-\u0e5b\u0f04-\u0f12\u0f3a-\u0f3d\u0f85\u0fd0-\u0fd4\u104a-\u104f\u10fb\u1361-\u1368\u166d-\u166e\u169b-\u169c\u16eb-\u16ed\u1735-\u1736\u17d4-\u17d6\u17d8-\u17da\u1800-\u180a\u1944-\u1945\u19de-\u19df\u1a1e-\u1a1f\u1b5a-\u1b60\u1c3b-\u1c3f\u1c7e-\u1c7f\u2000-\u206e\u207d-\u207e\u208d-\u208e\u3008-\u3009\u2768-\u2775\u27c5-\u27c6\u27e6-\u27ef\u2983-\u2998\u29d8-\u29db\u29fc-\u29fd\u2cf9-\u2cfc\u2cfe-\u2cff\u2e00-\u2e7e\u3000-\u303f\u30a0\u30fb\ua60d-\ua60f\ua673\ua67e\ua874-\ua877\ua8ce-\ua8cf\ua92e-\ua92f\ua95f\uaa5c-\uaa5f\ufd3e-\ufd3f\ufe10-\ufe19\ufe30-\ufe52\ufe54-\ufe61\ufe63\ufe68\ufe6a-\ufe6b\uff01-\uff03\uff05-\uff0a\uff0c-\uff0f\uff1a-\uff1b\uff1f-\uff20\uff3b-\uff3d\uff3f\uff5b\uff5d\uff5f-\uff65]|\ud800[\udd00-\udd01\udf9f\udfd0]|\ud802[\udd1f\udd3f\ude50-\ude58]|\ud809[\udc00-\udc7e]/, +q=/\s/,e=core.PositionFilter.FilterResult.FILTER_ACCEPT,l=core.PositionFilter.FilterResult.FILTER_REJECT,a=odf.WordBoundaryFilter.IncludeWhitespace.TRAILING,d=odf.WordBoundaryFilter.IncludeWhitespace.LEADING,m={NO_NEIGHBOUR:0,SPACE_CHAR:1,PUNCTUATION_CHAR:2,WORD_CHAR:3,OTHER:4};this.acceptPosition=function(f){var g=f.container(),p=f.leftNode(),q=f.rightNode(),r=f.unfilteredDomOffset,v=function(){return f.unfilteredDomOffset()-1};g.nodeType===n&&(null===q&&(q=c(g,1,f.getNodeFilter())),null===p&&(p= +c(g,-1,f.getNodeFilter())));g!==q&&(r=function(){return 0});g!==p&&null!==p&&(v=function(){return p.textContent.length-1});g=b(p,v);q=b(q,r);return g===m.WORD_CHAR&&q===m.WORD_CHAR||g===m.PUNCTUATION_CHAR&&q===m.PUNCTUATION_CHAR||k===a&&g!==m.NO_NEIGHBOUR&&q===m.SPACE_CHAR||k===d&&g===m.SPACE_CHAR&&q!==m.NO_NEIGHBOUR?l:e}};odf.WordBoundaryFilter.IncludeWhitespace={None:0,TRAILING:1,LEADING:2}; +gui.SelectionController=function(g,k){function c(a){var b=a.spec();if(a.isEdit||b.memberid===k)I=void 0,K.cancel()}function b(){var a=x.getCursor(k).getNode();return x.createStepIterator(a,0,[v,t],x.getRootElement(a))}function f(a,b,d){d=new odf.WordBoundaryFilter(x,d);var c=x.getRootElement(a)||x.getRootNode(),e=x.createRootFilter(c);return x.createStepIterator(a,b,[v,e,d],c)}function n(a,b){return b?{anchorNode:a.startContainer,anchorOffset:a.startOffset,focusNode:a.endContainer,focusOffset:a.endOffset}: +{anchorNode:a.endContainer,anchorOffset:a.endOffset,focusNode:a.startContainer,focusOffset:a.startOffset}}function p(a,b,d){var c=new ops.OpMoveCursor;c.init({memberid:k,position:a,length:b||0,selectionType:d});return c}function r(a,b,d){var c;c=x.getCursor(k);c=n(c.getSelectedRange(),c.hasForwardSelection());c.focusNode=a;c.focusOffset=b;d||(c.anchorNode=c.focusNode,c.anchorOffset=c.focusOffset);a=x.convertDomToCursorRange(c);g.enqueue([p(a.position,a.length)])}function q(a){var b;b=f(a.startContainer, +a.startOffset,L);b.roundToPreviousStep()&&a.setStart(b.container(),b.offset());b=f(a.endContainer,a.endOffset,E);b.roundToNextStep()&&a.setEnd(b.container(),b.offset())}function e(a){var b=w.getParagraphElements(a),d=b[0],b=b[b.length-1];d&&a.setStart(d,0);b&&(w.isParagraph(a.endContainer)&&0===a.endOffset?a.setEndBefore(b):a.setEnd(b,b.childNodes.length))}function l(a,b,d,c){var e,f;c?(e=d.startContainer,f=d.startOffset):(e=d.endContainer,f=d.endOffset);z.containsNode(a,e)||(f=0>z.comparePoints(a, +0,e,f)?0:a.childNodes.length,e=a);a=x.createStepIterator(e,f,b,w.getParagraphElement(e)||a);a.roundToClosestStep()||runtime.assert(!1,"No step found in requested range");c?d.setStart(a.container(),a.offset()):d.setEnd(a.container(),a.offset())}function a(a,d){var c=b();c.advanceStep(a)&&r(c.container(),c.offset(),d)}function d(a,d){var c,e=I,f=[new gui.LineBoundaryScanner,new gui.ParagraphBoundaryScanner];void 0===e&&A&&(e=A());isNaN(e)||(c=b(),u.moveToFilteredStep(c,a,f)&&c.advanceStep(a)&&(f=[new gui.ClosestXOffsetScanner(e), +new gui.LineBoundaryScanner,new gui.ParagraphBoundaryScanner],u.moveToFilteredStep(c,a,f)&&(r(c.container(),c.offset(),d),I=e,K.restart())))}function m(a,d){var c=b(),e=[new gui.LineBoundaryScanner,new gui.ParagraphBoundaryScanner];u.moveToFilteredStep(c,a,e)&&r(c.container(),c.offset(),d)}function h(a,b){var d=x.getCursor(k),d=n(d.getSelectedRange(),d.hasForwardSelection()),d=f(d.focusNode,d.focusOffset,L);d.advanceStep(a)&&r(d.container(),d.offset(),b)}function y(a,b,d){var c=!1,e=x.getCursor(k), +e=n(e.getSelectedRange(),e.hasForwardSelection()),c=x.getRootElement(e.focusNode);runtime.assert(Boolean(c),"SelectionController: Cursor outside root");e=x.createStepIterator(e.focusNode,e.focusOffset,[v,t],c);e.roundToClosestStep();e.advanceStep(a)&&(d=d(e.container()))&&(a===N?(e.setPosition(d,0),c=e.roundToNextStep()):(e.setPosition(d,d.childNodes.length),c=e.roundToPreviousStep()),c&&r(e.container(),e.offset(),b))}var x=g.getOdtDocument(),z=core.DomUtils,w=odf.OdfUtils,v=x.getPositionFilter(), +u=new gui.GuiStepUtils,t=x.createRootFilter(k),A=null,I,K,L=odf.WordBoundaryFilter.IncludeWhitespace.TRAILING,E=odf.WordBoundaryFilter.IncludeWhitespace.LEADING,N=core.StepDirection.PREVIOUS,O=core.StepDirection.NEXT;this.selectionToRange=function(a){var b=0<=z.comparePoints(a.anchorNode,a.anchorOffset,a.focusNode,a.focusOffset),d=a.focusNode.ownerDocument.createRange();b?(d.setStart(a.anchorNode,a.anchorOffset),d.setEnd(a.focusNode,a.focusOffset)):(d.setStart(a.focusNode,a.focusOffset),d.setEnd(a.anchorNode, +a.anchorOffset));return{range:d,hasForwardSelection:b}};this.rangeToSelection=n;this.selectImage=function(a){var b=x.getRootElement(a),d=x.createRootFilter(b),b=x.createStepIterator(a,0,[d,x.getPositionFilter()],b),c;b.roundToPreviousStep()||runtime.assert(!1,"No walkable position before frame");d=b.container();c=b.offset();b.setPosition(a,a.childNodes.length);b.roundToNextStep()||runtime.assert(!1,"No walkable position after frame");a=x.convertDomToCursorRange({anchorNode:d,anchorOffset:c,focusNode:b.container(), +focusOffset:b.offset()});a=p(a.position,a.length,ops.OdtCursor.RegionSelection);g.enqueue([a])};this.expandToWordBoundaries=q;this.expandToParagraphBoundaries=e;this.selectRange=function(a,b,d){var c=x.getOdfCanvas().getElement(),f,h=[v];f=z.containsNode(c,a.startContainer);c=z.containsNode(c,a.endContainer);if(f||c)if(f&&c&&(2===d?q(a):3<=d&&e(a)),(d=b?x.getRootElement(a.startContainer):x.getRootElement(a.endContainer))||(d=x.getRootNode()),h.push(x.createRootFilter(d)),l(d,h,a,!0),l(d,h,a,!1),a= +n(a,b),b=x.convertDomToCursorRange(a),a=x.getCursorSelection(k),b.position!==a.position||b.length!==a.length)a=p(b.position,b.length,ops.OdtCursor.RangeSelection),g.enqueue([a])};this.moveCursorToLeft=function(){a(N,!1);return!0};this.moveCursorToRight=function(){a(O,!1);return!0};this.extendSelectionToLeft=function(){a(N,!0);return!0};this.extendSelectionToRight=function(){a(O,!0);return!0};this.setCaretXPositionLocator=function(a){A=a};this.moveCursorUp=function(){d(N,!1);return!0};this.moveCursorDown= +function(){d(O,!1);return!0};this.extendSelectionUp=function(){d(N,!0);return!0};this.extendSelectionDown=function(){d(O,!0);return!0};this.moveCursorBeforeWord=function(){h(N,!1);return!0};this.moveCursorPastWord=function(){h(O,!1);return!0};this.extendSelectionBeforeWord=function(){h(N,!0);return!0};this.extendSelectionPastWord=function(){h(O,!0);return!0};this.moveCursorToLineStart=function(){m(N,!1);return!0};this.moveCursorToLineEnd=function(){m(O,!1);return!0};this.extendSelectionToLineStart= +function(){m(N,!0);return!0};this.extendSelectionToLineEnd=function(){m(O,!0);return!0};this.extendSelectionToParagraphStart=function(){y(N,!0,w.getParagraphElement);return!0};this.extendSelectionToParagraphEnd=function(){y(O,!0,w.getParagraphElement);return!0};this.moveCursorToParagraphStart=function(){y(N,!1,w.getParagraphElement);return!0};this.moveCursorToParagraphEnd=function(){y(O,!1,w.getParagraphElement);return!0};this.moveCursorToDocumentStart=function(){y(N,!1,x.getRootElement);return!0}; +this.moveCursorToDocumentEnd=function(){y(O,!1,x.getRootElement);return!0};this.extendSelectionToDocumentStart=function(){y(N,!0,x.getRootElement);return!0};this.extendSelectionToDocumentEnd=function(){y(O,!0,x.getRootElement);return!0};this.extendSelectionToEntireDocument=function(){var a=x.getCursor(k),a=x.getRootElement(a.getNode()),b,d,c;runtime.assert(Boolean(a),"SelectionController: Cursor outside root");c=x.createStepIterator(a,0,[v,t],a);c.roundToClosestStep();b=c.container();d=c.offset(); +c.setPosition(a,a.childNodes.length);c.roundToClosestStep();a=x.convertDomToCursorRange({anchorNode:b,anchorOffset:d,focusNode:c.container(),focusOffset:c.offset()});g.enqueue([p(a.position,a.length)]);return!0};this.destroy=function(a){x.unsubscribe(ops.OdtDocument.signalOperationStart,c);core.Async.destroyAll([K.destroy],a)};(function(){K=core.Task.createTimeoutTask(function(){I=void 0},2E3);x.subscribe(ops.OdtDocument.signalOperationStart,c)})()}; +gui.TextController=function(g,k,c,b,f,n){function p(){y=!0===k.getState(gui.CommonConstraints.EDIT.REVIEW_MODE)?c.isLocalCursorWithinOwnAnnotation():!0}function r(a){a.getMemberId()===b&&p()}function q(a,b,c){var e=[d.getPositionFilter()];c&&e.push(d.createRootFilter(a.startContainer));c=d.createStepIterator(a.startContainer,a.startOffset,e,b);c.roundToClosestStep()||runtime.assert(!1,"No walkable step found in paragraph element at range start");b=d.convertDomPointToCursorStep(c.container(),c.offset()); +a.collapsed?a=b:(c.setPosition(a.endContainer,a.endOffset),c.roundToClosestStep()||runtime.assert(!1,"No walkable step found in paragraph element at range end"),a=d.convertDomPointToCursorStep(c.container(),c.offset()));return{position:b,length:a-b}}function e(a){var d,c,e,f=m.getParagraphElements(a),g=a.cloneRange(),l=[];d=f[0];1a.length&&(a.position+=a.length,a.length=-a.length);return a}function a(a){if(!y)return!1;var c,f=d.getCursor(b).getSelectedRange().cloneRange(), +h=l(d.getCursorSelection(b)),m;if(0===h.length){h=void 0;c=d.getCursor(b).getNode();m=d.getRootElement(c);var k=[d.getPositionFilter(),d.createRootFilter(m)];m=d.createStepIterator(c,0,k,m);m.roundToClosestStep()&&(a?m.nextStep():m.previousStep())&&(h=l(d.convertDomToCursorRange({anchorNode:c,anchorOffset:0,focusNode:m.container(),focusOffset:m.offset()})),a?(f.setStart(c,0),f.setEnd(m.container(),m.offset())):(f.setStart(m.container(),m.offset()),f.setEnd(c,0)))}h&&g.enqueue(e(f));return void 0!== +h}var d=g.getOdtDocument(),m=odf.OdfUtils,h=core.DomUtils,y=!1,x=odf.Namespaces.textns,z=core.StepDirection.NEXT;this.isEnabled=function(){return y};this.enqueueParagraphSplittingOps=function(){if(!y)return!1;var a=d.getCursor(b),c=a.getSelectedRange(),f=l(d.getCursorSelection(b)),h=[],a=m.getParagraphElement(a.getNode()),k=a.getAttributeNS(x,"style-name")||"";0c.left&&(c=v(e)))b.focusNode=c.container,b.focusOffset=c.offset, +d&&(b.anchorNode=b.focusNode,b.anchorOffset=b.focusOffset)}else S.isImage(b.focusNode.firstChild)&&1===b.focusOffset&&S.isCharacterFrame(b.focusNode)&&(c=v(b.focusNode))&&(b.anchorNode=b.focusNode=c.container,b.anchorOffset=b.focusOffset=c.offset);b.anchorNode&&b.focusNode&&(b=T.selectionToRange(b),T.selectRange(b.range,b.hasForwardSelection,0===a.button?a.detail:0));F.focus()}function t(a){var b;if(b=n(a.clientX,a.clientY))a=b.container,b=b.offset,a={anchorNode:a,anchorOffset:b,focusNode:a,focusOffset:b}, +a=T.selectionToRange(a),T.selectRange(a.range,a.hasForwardSelection,2),F.focus()}function A(a){var d=a.target||a.srcElement||null,c,e,f;ma.processRequests();U&&(S.isImage(d)&&S.isCharacterFrame(d.parentNode)&&W.getSelection().isCollapsed?(T.selectImage(d.parentNode),F.focus()):la.isSelectorElement(d)?F.focus():B?(d=b.getSelectedRange(),e=d.collapsed,S.isImage(d.endContainer)&&0===d.endOffset&&S.isCharacterFrame(d.endContainer.parentNode)&&(f=d.endContainer.parentNode,f=v(f))&&(d.setEnd(f.container, +f.offset),e&&d.collapse(!1)),T.selectRange(d,b.hasForwardSelection(),0===a.button?a.detail:0),F.focus()):ua?u(a):(c=aa.cloneEvent(a),M=runtime.setTimeout(function(){u(c)},0)),oa=0,B=U=!1)}function I(a){var b=J.getCursor(c).getSelectedRange();b.collapsed||fa.exportRangeToDataTransfer(a.dataTransfer,b)}function K(){U&&F.focus();oa=0;B=U=!1}function L(a){A(a)}function E(a){var b=a.target||a.srcElement||null,d=null;"annotationRemoveButton"===b.className?(runtime.assert(ja,"Remove buttons are displayed on annotations while annotation editing is disabled in the controller."), +d=b.parentNode.getElementsByTagNameNS(odf.Namespaces.officens,"annotation").item(0),ca.removeAnnotation(d),F.focus()):"webodf-draggable"!==b.getAttribute("class")&&A(a)}function N(a){(a=a.data)&&(-1===a.indexOf("\n")?da.insertText(a):ea.paste(a))}function O(a){return function(){a();return!0}}function D(a){return function(b){return J.getCursor(c).getSelectionType()===ops.OdtCursor.RangeSelection?a(b):!0}}function V(b){F.unsubscribe("keydown",C.handleEvent);F.unsubscribe("keypress",Z.handleEvent);F.unsubscribe("keyup", +ba.handleEvent);F.unsubscribe("copy",q);F.unsubscribe("mousedown",w);F.unsubscribe("mousemove",ma.trigger);F.unsubscribe("mouseup",E);F.unsubscribe("contextmenu",L);F.unsubscribe("dragstart",I);F.unsubscribe("dragend",K);F.unsubscribe("click",pa.handleClick);F.unsubscribe("longpress",t);F.unsubscribe("drag",y);F.unsubscribe("dragstop",x);J.unsubscribe(ops.OdtDocument.signalOperationEnd,na.trigger);J.unsubscribe(ops.Document.signalCursorAdded,ka.registerCursor);J.unsubscribe(ops.Document.signalCursorRemoved, +ka.removeCursor);J.unsubscribe(ops.OdtDocument.signalOperationEnd,a);b()}var W=runtime.getWindow(),J=k.getOdtDocument(),R=new gui.SessionConstraints,P=new gui.SessionContext(k,c),aa=core.DomUtils,S=odf.OdfUtils,fa=new gui.MimeDataExporter,ha=new gui.Clipboard(fa),C=new gui.KeyboardHandler,Z=new gui.KeyboardHandler,ba=new gui.KeyboardHandler,U=!1,ga=new odf.ObjectNameGenerator(J.getOdfCanvas().odfContainer(),c),B=!1,Y=null,M,Q=null,F=new gui.EventManager(J),ja=f.annotationsEnabled,ca=new gui.AnnotationController(k, +R,c),X=new gui.DirectFormattingController(k,R,P,c,ga,f.directTextStylingEnabled,f.directParagraphStylingEnabled),da=new gui.TextController(k,R,P,c,X.createCursorStyleOp,X.createParagraphStyleOps),qa=new gui.ImageController(k,R,P,c,ga),la=new gui.ImageSelector(J.getOdfCanvas()),ia=J.createPositionIterator(J.getRootNode()),ma,na,ea=new gui.PasteController(k,R,P,c),ka=new gui.InputMethodEditor(c,F),oa=0,pa=new gui.HyperlinkClickHandler(J.getOdfCanvas().getElement,C,ba),ta=new gui.HyperlinkController(k, +R,P,c),T=new gui.SelectionController(k,c),va=new gui.MetadataController(k,c),G=gui.KeyboardHandler.Modifier,H=gui.KeyboardHandler.KeyCode,ra=-1!==W.navigator.appVersion.toLowerCase().indexOf("mac"),ua=-1!==["iPad","iPod","iPhone"].indexOf(W.navigator.platform),sa;runtime.assert(null!==W,"Expected to be run in an environment which has a global window, like a browser.");this.undo=m;this.redo=h;this.insertLocalCursor=function(){runtime.assert(void 0===k.getOdtDocument().getCursor(c),"Inserting local cursor a second time."); +var a=new ops.OpAddCursor;a.init({memberid:c});k.enqueue([a]);F.focus()};this.removeLocalCursor=function(){runtime.assert(void 0!==k.getOdtDocument().getCursor(c),"Removing local cursor without inserting before.");var a=new ops.OpRemoveCursor;a.init({memberid:c});k.enqueue([a])};this.startEditing=function(){ka.subscribe(gui.InputMethodEditor.signalCompositionStart,da.removeCurrentSelection);ka.subscribe(gui.InputMethodEditor.signalCompositionEnd,N);F.subscribe("beforecut",r);F.subscribe("cut",p); +F.subscribe("beforepaste",l);F.subscribe("paste",e);Q&&Q.initialize();F.setEditing(!0);pa.setModifier(ra?G.Meta:G.Ctrl);C.bind(H.Backspace,G.None,O(da.removeTextByBackspaceKey),!0);C.bind(H.Delete,G.None,da.removeTextByDeleteKey);C.bind(H.Tab,G.None,D(function(){da.insertText("\t");return!0}));ra?(C.bind(H.Clear,G.None,da.removeCurrentSelection),C.bind(H.B,G.Meta,D(X.toggleBold)),C.bind(H.I,G.Meta,D(X.toggleItalic)),C.bind(H.U,G.Meta,D(X.toggleUnderline)),C.bind(H.L,G.MetaShift,D(X.alignParagraphLeft)), +C.bind(H.E,G.MetaShift,D(X.alignParagraphCenter)),C.bind(H.R,G.MetaShift,D(X.alignParagraphRight)),C.bind(H.J,G.MetaShift,D(X.alignParagraphJustified)),ja&&C.bind(H.C,G.MetaShift,ca.addAnnotation),C.bind(H.Z,G.Meta,m),C.bind(H.Z,G.MetaShift,h)):(C.bind(H.B,G.Ctrl,D(X.toggleBold)),C.bind(H.I,G.Ctrl,D(X.toggleItalic)),C.bind(H.U,G.Ctrl,D(X.toggleUnderline)),C.bind(H.L,G.CtrlShift,D(X.alignParagraphLeft)),C.bind(H.E,G.CtrlShift,D(X.alignParagraphCenter)),C.bind(H.R,G.CtrlShift,D(X.alignParagraphRight)), +C.bind(H.J,G.CtrlShift,D(X.alignParagraphJustified)),ja&&C.bind(H.C,G.CtrlAlt,ca.addAnnotation),C.bind(H.Z,G.Ctrl,m),C.bind(H.Z,G.CtrlShift,h));Z.setDefault(D(function(a){var b;b=null===a.which||void 0===a.which?String.fromCharCode(a.keyCode):0!==a.which&&0!==a.charCode?String.fromCharCode(a.which):null;return!b||a.altKey||a.ctrlKey||a.metaKey?!1:(da.insertText(b),!0)}));Z.bind(H.Enter,G.None,D(da.enqueueParagraphSplittingOps))};this.endEditing=function(){ka.unsubscribe(gui.InputMethodEditor.signalCompositionStart, +da.removeCurrentSelection);ka.unsubscribe(gui.InputMethodEditor.signalCompositionEnd,N);F.unsubscribe("cut",p);F.unsubscribe("beforecut",r);F.unsubscribe("paste",e);F.unsubscribe("beforepaste",l);F.setEditing(!1);pa.setModifier(G.None);C.bind(H.Backspace,G.None,function(){return!0},!0);C.unbind(H.Delete,G.None);C.unbind(H.Tab,G.None);ra?(C.unbind(H.Clear,G.None),C.unbind(H.B,G.Meta),C.unbind(H.I,G.Meta),C.unbind(H.U,G.Meta),C.unbind(H.L,G.MetaShift),C.unbind(H.E,G.MetaShift),C.unbind(H.R,G.MetaShift), +C.unbind(H.J,G.MetaShift),ja&&C.unbind(H.C,G.MetaShift),C.unbind(H.Z,G.Meta),C.unbind(H.Z,G.MetaShift)):(C.unbind(H.B,G.Ctrl),C.unbind(H.I,G.Ctrl),C.unbind(H.U,G.Ctrl),C.unbind(H.L,G.CtrlShift),C.unbind(H.E,G.CtrlShift),C.unbind(H.R,G.CtrlShift),C.unbind(H.J,G.CtrlShift),ja&&C.unbind(H.C,G.CtrlAlt),C.unbind(H.Z,G.Ctrl),C.unbind(H.Z,G.CtrlShift));Z.setDefault(null);Z.unbind(H.Enter,G.None)};this.getInputMemberId=function(){return c};this.getSession=function(){return k};this.getSessionConstraints=function(){return R}; +this.setUndoManager=function(a){Q&&Q.unsubscribe(gui.UndoManager.signalUndoStackChanged,d);if(Q=a)Q.setDocument(J),Q.setPlaybackFunction(k.enqueue),Q.subscribe(gui.UndoManager.signalUndoStackChanged,d)};this.getUndoManager=function(){return Q};this.getMetadataController=function(){return va};this.getAnnotationController=function(){return ca};this.getDirectFormattingController=function(){return X};this.getHyperlinkClickHandler=function(){return pa};this.getHyperlinkController=function(){return ta}; +this.getImageController=function(){return qa};this.getSelectionController=function(){return T};this.getTextController=function(){return da};this.getEventManager=function(){return F};this.getKeyboardHandlers=function(){return{keydown:C,keypress:Z}};this.destroy=function(a){var b=[ma.destroy,na.destroy,X.destroy,ka.destroy,F.destroy,pa.destroy,ta.destroy,va.destroy,T.destroy,da.destroy,V];sa&&b.unshift(sa.destroy);runtime.clearTimeout(M);core.Async.destroyAll(b,a)};ma=core.Task.createRedrawTask(z); +na=core.Task.createRedrawTask(function(){var a=J.getCursor(c);if(a&&a.getSelectionType()===ops.OdtCursor.RegionSelection&&(a=S.getImageElements(a.getSelectedRange())[0])){la.select(a.parentNode);return}la.clearSelection()});C.bind(H.Left,G.None,D(T.moveCursorToLeft));C.bind(H.Right,G.None,D(T.moveCursorToRight));C.bind(H.Up,G.None,D(T.moveCursorUp));C.bind(H.Down,G.None,D(T.moveCursorDown));C.bind(H.Left,G.Shift,D(T.extendSelectionToLeft));C.bind(H.Right,G.Shift,D(T.extendSelectionToRight));C.bind(H.Up, +G.Shift,D(T.extendSelectionUp));C.bind(H.Down,G.Shift,D(T.extendSelectionDown));C.bind(H.Home,G.None,D(T.moveCursorToLineStart));C.bind(H.End,G.None,D(T.moveCursorToLineEnd));C.bind(H.Home,G.Ctrl,D(T.moveCursorToDocumentStart));C.bind(H.End,G.Ctrl,D(T.moveCursorToDocumentEnd));C.bind(H.Home,G.Shift,D(T.extendSelectionToLineStart));C.bind(H.End,G.Shift,D(T.extendSelectionToLineEnd));C.bind(H.Up,G.CtrlShift,D(T.extendSelectionToParagraphStart));C.bind(H.Down,G.CtrlShift,D(T.extendSelectionToParagraphEnd)); +C.bind(H.Home,G.CtrlShift,D(T.extendSelectionToDocumentStart));C.bind(H.End,G.CtrlShift,D(T.extendSelectionToDocumentEnd));ra?(C.bind(H.Left,G.Alt,D(T.moveCursorBeforeWord)),C.bind(H.Right,G.Alt,D(T.moveCursorPastWord)),C.bind(H.Left,G.Meta,D(T.moveCursorToLineStart)),C.bind(H.Right,G.Meta,D(T.moveCursorToLineEnd)),C.bind(H.Home,G.Meta,D(T.moveCursorToDocumentStart)),C.bind(H.End,G.Meta,D(T.moveCursorToDocumentEnd)),C.bind(H.Left,G.AltShift,D(T.extendSelectionBeforeWord)),C.bind(H.Right,G.AltShift, +D(T.extendSelectionPastWord)),C.bind(H.Left,G.MetaShift,D(T.extendSelectionToLineStart)),C.bind(H.Right,G.MetaShift,D(T.extendSelectionToLineEnd)),C.bind(H.Up,G.AltShift,D(T.extendSelectionToParagraphStart)),C.bind(H.Down,G.AltShift,D(T.extendSelectionToParagraphEnd)),C.bind(H.Up,G.MetaShift,D(T.extendSelectionToDocumentStart)),C.bind(H.Down,G.MetaShift,D(T.extendSelectionToDocumentEnd)),C.bind(H.A,G.Meta,D(T.extendSelectionToEntireDocument))):(C.bind(H.Left,G.Ctrl,D(T.moveCursorBeforeWord)),C.bind(H.Right, +G.Ctrl,D(T.moveCursorPastWord)),C.bind(H.Left,G.CtrlShift,D(T.extendSelectionBeforeWord)),C.bind(H.Right,G.CtrlShift,D(T.extendSelectionPastWord)),C.bind(H.A,G.Ctrl,D(T.extendSelectionToEntireDocument)));ua&&(sa=new gui.IOSSafariSupport(F));F.subscribe("keydown",C.handleEvent);F.subscribe("keypress",Z.handleEvent);F.subscribe("keyup",ba.handleEvent);F.subscribe("copy",q);F.subscribe("mousedown",w);F.subscribe("mousemove",ma.trigger);F.subscribe("mouseup",E);F.subscribe("contextmenu",L);F.subscribe("dragstart", +I);F.subscribe("dragend",K);F.subscribe("click",pa.handleClick);F.subscribe("longpress",t);F.subscribe("drag",y);F.subscribe("dragstop",x);J.subscribe(ops.OdtDocument.signalOperationEnd,na.trigger);J.subscribe(ops.Document.signalCursorAdded,ka.registerCursor);J.subscribe(ops.Document.signalCursorRemoved,ka.removeCursor);J.subscribe(ops.OdtDocument.signalOperationEnd,a)}})(); +gui.CaretManager=function(g,k){function c(b){return n.hasOwnProperty(b)?n[b]:null}function b(){return Object.keys(n).map(function(b){return n[b]})}function f(b){var c=n[b];c&&(delete n[b],b===g.getInputMemberId()?(r.unsubscribe(ops.OdtDocument.signalProcessingBatchEnd,c.ensureVisible),r.unsubscribe(ops.Document.signalCursorMoved,c.refreshCursorBlinking),q.unsubscribe("compositionupdate",c.handleUpdate),q.unsubscribe("compositionend",c.handleUpdate),q.unsubscribe("focus",c.setFocus),q.unsubscribe("blur", +c.removeFocus),p.removeEventListener("focus",c.show,!1),p.removeEventListener("blur",c.hide,!1)):r.unsubscribe(ops.OdtDocument.signalProcessingBatchEnd,c.handleUpdate),c.destroy(function(){}))}var n={},p=runtime.getWindow(),r=g.getSession().getOdtDocument(),q=g.getEventManager();this.registerCursor=function(b,c,a){var d=b.getMemberId();b=new gui.Caret(b,k,c,a);n[d]=b;d===g.getInputMemberId()?(runtime.log("Starting to track input on new cursor of "+d),r.subscribe(ops.OdtDocument.signalProcessingBatchEnd, +b.ensureVisible),r.subscribe(ops.Document.signalCursorMoved,b.refreshCursorBlinking),q.subscribe("compositionupdate",b.handleUpdate),q.subscribe("compositionend",b.handleUpdate),q.subscribe("focus",b.setFocus),q.subscribe("blur",b.removeFocus),p.addEventListener("focus",b.show,!1),p.addEventListener("blur",b.hide,!1),b.setOverlayElement(q.getEventTrap())):r.subscribe(ops.OdtDocument.signalProcessingBatchEnd,b.handleUpdate);return b};this.getCaret=c;this.getCarets=b;this.destroy=function(c){var l= +b().map(function(a){return a.destroy});g.getSelectionController().setCaretXPositionLocator(null);r.unsubscribe(ops.Document.signalCursorRemoved,f);n={};core.Async.destroyAll(l,c)};g.getSelectionController().setCaretXPositionLocator(function(){var b=c(g.getInputMemberId()),f;b&&(f=b.getBoundingClientRect());return f?f.right:void 0});r.subscribe(ops.Document.signalCursorRemoved,f)}; +gui.EditInfoHandle=function(g){var k=[],c,b=g.ownerDocument,f=b.documentElement.namespaceURI;this.setEdits=function(g){k=g;var p,r,q,e;core.DomUtils.removeAllChildNodes(c);for(g=0;gd?(r=c(1,0),q=c(.5,1E4-d),e=c(.2,2E4-d)):1E4<=d&&2E4>d?(r=c(.5,0),e=c(.2,2E4-d)):r=c(.2,0)};this.getEdits=function(){return g.getEdits()};this.clearEdits=function(){g.clearEdits(); +n.setEdits([]);p.hasAttributeNS("urn:webodf:names:editinfo","editinfo:memberid")&&p.removeAttributeNS("urn:webodf:names:editinfo","editinfo:memberid")};this.getEditInfo=function(){return g};this.show=function(){p.style.display="block"};this.hide=function(){b.hideHandle();p.style.display="none"};this.showHandle=function(){n.show()};this.hideHandle=function(){n.hide()};this.destroy=function(b){runtime.clearTimeout(r);runtime.clearTimeout(q);runtime.clearTimeout(e);f.removeChild(p);n.destroy(function(a){a? +b(a):g.destroy(b)})};(function(){var c=g.getOdtDocument().getDOMDocument();p=c.createElementNS(c.documentElement.namespaceURI,"div");p.setAttribute("class","editInfoMarker");p.onmouseover=function(){b.showHandle()};p.onmouseout=function(){b.hideHandle()};f=g.getNode();f.appendChild(p);n=new gui.EditInfoHandle(f);k||b.hide()})()}; +gui.HyperlinkTooltipView=function(g,k){var c=core.DomUtils,b=odf.OdfUtils,f=runtime.getWindow(),n,p,r;runtime.assert(null!==f,"Expected to be run in an environment which has a global window, like a browser.");this.showTooltip=function(q){var e=q.target||q.srcElement,l=g.getSizer(),a=g.getZoomLevel(),d;a:{for(;e;){if(b.isHyperlink(e))break a;if(b.isParagraph(e)||b.isInlineRoot(e))break;e=e.parentNode}e=null}if(e){c.containsNode(l,r)||l.appendChild(r);d=p;var m;switch(k()){case gui.KeyboardHandler.Modifier.Ctrl:m= +runtime.tr("Ctrl-click to follow link");break;case gui.KeyboardHandler.Modifier.Meta:m=runtime.tr("\u2318-click to follow link");break;default:m=""}d.textContent=m;n.textContent=b.getHyperlinkTarget(e);r.style.display="block";d=f.innerWidth-r.offsetWidth-15;e=q.clientX>d?d:q.clientX+15;d=f.innerHeight-r.offsetHeight-10;q=q.clientY>d?d:q.clientY+10;l=l.getBoundingClientRect();e=(e-l.left)/a;q=(q-l.top)/a;r.style.left=e+"px";r.style.top=q+"px"}};this.hideTooltip=function(){r.style.display="none"};this.destroy= +function(b){r.parentNode&&r.parentNode.removeChild(r);b()};(function(){var b=g.getElement().ownerDocument;n=b.createElement("span");p=b.createElement("span");n.className="webodf-hyperlinkTooltipLink";p.className="webodf-hyperlinkTooltipText";r=b.createElement("div");r.className="webodf-hyperlinkTooltip";r.appendChild(n);r.appendChild(p);g.getElement().appendChild(r)})()}; +gui.OdfFieldView=function(g){function k(){var b=odf.OdfSchema.getFields().map(function(b){return b.replace(":","|")}),c=b.join(",\n")+"\n{ background-color: #D0D0D0; }\n",b=b.map(function(b){return b+":empty::after"}).join(",\n")+"\n{ content:' '; white-space: pre; }\n";return c+"\n"+b}var c,b=g.getElement().ownerDocument;this.showFieldHighlight=function(){c.appendChild(b.createTextNode(k()))};this.hideFieldHighlight=function(){for(var b=c.sheet,g=b.cssRules;g.length;)b.deleteRule(g.length-1)};this.destroy= +function(b){c.parentNode&&c.parentNode.removeChild(c);b()};c=function(){var c=b.getElementsByTagName("head").item(0),g=b.createElement("style"),k="";g.type="text/css";g.media="screen, print, handheld, projection";odf.Namespaces.forEachPrefix(function(b,c){k+="@namespace "+b+" url("+c+");\n"});g.appendChild(b.createTextNode(k));c.appendChild(g);return g}()}; +gui.ShadowCursor=function(g){var k=g.getDOMDocument().createRange(),c=!0;this.removeFromDocument=function(){};this.getMemberId=function(){return gui.ShadowCursor.ShadowCursorMemberId};this.getSelectedRange=function(){return k};this.setSelectedRange=function(b,f){k=b;c=!1!==f};this.hasForwardSelection=function(){return c};this.getDocument=function(){return g};this.getSelectionType=function(){return ops.OdtCursor.RangeSelection};k.setStart(g.getRootNode(),0)};gui.ShadowCursor.ShadowCursorMemberId=""; +gui.SelectionView=function(g){};gui.SelectionView.prototype.rerender=function(){};gui.SelectionView.prototype.show=function(){};gui.SelectionView.prototype.hide=function(){};gui.SelectionView.prototype.destroy=function(g){}; +gui.SelectionViewManager=function(g){function k(){return Object.keys(c).map(function(b){return c[b]})}var c={};this.getSelectionView=function(b){return c.hasOwnProperty(b)?c[b]:null};this.getSelectionViews=k;this.removeSelectionView=function(b){c.hasOwnProperty(b)&&(c[b].destroy(function(){}),delete c[b])};this.hideSelectionView=function(b){c.hasOwnProperty(b)&&c[b].hide()};this.showSelectionView=function(b){c.hasOwnProperty(b)&&c[b].show()};this.rerenderSelectionViews=function(){Object.keys(c).forEach(function(b){c[b].rerender()})}; +this.registerCursor=function(b,f){var k=b.getMemberId(),p=new g(b);f?p.show():p.hide();return c[k]=p};this.destroy=function(b){function c(k,r){r?b(r):k .webodf-draggable"),a=gui.ShadowCursor.ShadowCursorMemberId,e(".webodf-selectionOverlay","{ fill: "+d+"; stroke: "+d+";}",""),e(".webodf-touchEnabled .webodf-selectionOverlay","{ display: block; }"," > .webodf-draggable"))}function l(a){var b,d;for(d in t)t.hasOwnProperty(d)&&(b=t[d],a?b.show():b.hide())}function a(a){n.getCarets().forEach(function(b){a?b.showHandle():b.hideHandle()})}function d(a){var b=a.getMemberId();a=a.getProperties();e(b,a.fullName,a.color)}function m(a){var d= +a.getMemberId(),c=b.getOdtDocument().getMember(d).getProperties();n.registerCursor(a,E,N);p.registerCursor(a,!0);if(a=n.getCaret(d))a.setAvatarImageUrl(c.imageUrl),a.setColor(c.color);runtime.log("+++ View here +++ eagerly created an Caret for '"+d+"'! +++")}function h(a){a=a.getMemberId();var b=p.getSelectionView(c),d=p.getSelectionView(gui.ShadowCursor.ShadowCursorMemberId),e=n.getCaret(c);a===c?(d.hide(),b&&b.show(),e&&e.show()):a===gui.ShadowCursor.ShadowCursorMemberId&&(d.show(),b&&b.hide(), +e&&e.hide())}function y(a){p.removeSelectionView(a)}function x(a){var d=a.paragraphElement,c=a.memberId;a=a.timeStamp;var e,f="",h=d.getElementsByTagNameNS("urn:webodf:names:editinfo","editinfo").item(0);h?(f=h.getAttributeNS("urn:webodf:names:editinfo","id"),e=t[f]):(f=Math.random().toString(),e=new ops.EditInfo(d,b.getOdtDocument()),e=new gui.EditInfoMarker(e,L),h=d.getElementsByTagNameNS("urn:webodf:names:editinfo","editinfo").item(0),h.setAttributeNS("urn:webodf:names:editinfo","id",f),t[f]=e); +e.addEdit(c,new Date(a));K.trigger()}function z(){var a;u.hasChildNodes()&&core.DomUtils.removeAllChildNodes(u);!0===f.getState(gui.CommonConstraints.EDIT.ANNOTATIONS.ONLY_DELETE_OWN)&&(a=b.getOdtDocument().getMember(c))&&(a=a.getProperties().fullName,u.appendChild(document.createTextNode(".annotationWrapper:not([creator = '"+a+"']) .annotationRemoveButton { display: none; }")))}function w(a){var b=Object.keys(t).map(function(a){return t[a]});A.unsubscribe(ops.Document.signalMemberAdded,d);A.unsubscribe(ops.Document.signalMemberUpdated, +d);A.unsubscribe(ops.Document.signalCursorAdded,m);A.unsubscribe(ops.Document.signalCursorRemoved,y);A.unsubscribe(ops.OdtDocument.signalParagraphChanged,x);A.unsubscribe(ops.Document.signalCursorMoved,h);A.unsubscribe(ops.OdtDocument.signalParagraphChanged,p.rerenderSelectionViews);A.unsubscribe(ops.OdtDocument.signalTableAdded,p.rerenderSelectionViews);A.unsubscribe(ops.OdtDocument.signalParagraphStyleModified,p.rerenderSelectionViews);f.unsubscribe(gui.CommonConstraints.EDIT.ANNOTATIONS.ONLY_DELETE_OWN, +z);A.unsubscribe(ops.Document.signalMemberAdded,z);A.unsubscribe(ops.Document.signalMemberUpdated,z);v.parentNode.removeChild(v);u.parentNode.removeChild(u);(function W(d,c){c?a(c):da.length;b&&g(a);return b}function c(a,b){function c(f){a[f]===b&&e.push(f)}var e=[];a&&["style:parent-style-name","style:next-style-name"].forEach(c);return e}function b(a,b){function c(e){a[e]===b&&delete a[e]}a&&["style:parent-style-name","style:next-style-name"].forEach(c)}function f(a){var b={};Object.keys(a).forEach(function(c){b[c]="object"===typeof a[c]?f(a[c]):a[c]});return b}function n(a, +b,c,e){var f,g=!1,k=!1,l,n=[];e&&e.attributes&&(n=e.attributes.split(","));a&&(c||0=a.length?0:a.length-f.length)):void 0!==a.length&&(f=a.position+a.length,e<=f?a.length-=b.length:c=b.position+b.length)){e=c?a:b;g=c?b:a;if(a.position!==b.position||a.length!==b.length)r=f(e),u=f(g);b=q(g.setProperties,null,e.setProperties, +null,"style:text-properties");if(b.majorChanged||b.minorChanged)k=[],a=[],l=e.position+e.length,n=g.position+g.length,g.positionl?b.minorChanged&&(r=u,r.position=l,r.length=n-l,a.push(r),g.length=l-g.position):l>n&&b.majorChanged&&(r.position=n, +r.length=l-n,k.push(r),e.length=n-e.position),e.setProperties&&p(e.setProperties)&&k.push(e),g.setProperties&&p(g.setProperties)&&a.push(g),c?(l=k,k=a):l=a}return{opSpecsA:l,opSpecsB:k}},InsertText:function(a,b){b.position<=a.position?a.position+=b.text.length:b.position<=a.position+a.length&&(a.length+=b.text.length);return{opSpecsA:[a],opSpecsB:[b]}},MergeParagraph:function(a,b){var c=a.position,e=a.position+a.length;c>=b.sourceStartPosition&&--c;e>=b.sourceStartPosition&&--e;a.position=c;a.length= +e-c;return{opSpecsA:[a],opSpecsB:[b]}},MoveCursor:e,RemoveAnnotation:function(a,b){var c=a.position,e=a.position+a.length,f=b.position+b.length,g=[a],k=[b];b.position<=c&&e<=f?g=[]:(fb.position?a.position+=b.text.length:c?b.position+=a.text.length:a.position+= +b.text.length;return{opSpecsA:[a],opSpecsB:[b]}},MergeParagraph:function(a,b){a.position>=b.sourceStartPosition?--a.position:(a.positiona.position&&(b.position+=a.text.length);return{opSpecsA:[a],opSpecsB:[b]}},SplitParagraph:function(a,b){a.position=a.sourceStartPosition&&--f;c>=a.sourceStartPosition&&--c;0<=b.length?(b.position=f,b.length=c-f):(b.position=c,b.length=f-c);return{opSpecsA:[a],opSpecsB:[b]}},RemoveAnnotation:function(a,b){var c=b.position+b.length,e=[a],f=[b];b.position<=a.destinationStartPosition&&a.sourceStartPosition<=c?(e=[],--b.length):a.sourceStartPosition=a.sourceStartPosition?--b.position:(b.positiona.sourceStartPosition)--b.position;else if(b.position===a.destinationStartPosition||b.position===a.sourceStartPosition)b.position=a.destinationStartPosition,a.paragraphStyleName=b.styleName;return{opSpecsA:c,opSpecsB:e}},SplitParagraph:function(a,b){var c,e=[a],f=[b];b.position=a.destinationStartPosition&&b.position=a.sourceStartPosition&&(--b.position,--b.sourceParagraphPosition);return{opSpecsA:e,opSpecsB:f}},UpdateMember:e,UpdateMetadata:e, +UpdateParagraphStyle:e},MoveCursor:{MoveCursor:e,RemoveAnnotation:function(a,b){var c=k(a),e=a.position+a.length,f=b.position+b.length;b.position<=a.position&&e<=f?(a.position=b.position-1,a.length=0):(fb.position?a.position+= +1:a.position===b.sourceParagraphPosition&&(b.paragraphStyleName=a.styleName,g=f(a),g.position=b.position+1,c.push(g));return{opSpecsA:c,opSpecsB:e}},UpdateMember:e,UpdateMetadata:e,UpdateParagraphStyle:e},SplitParagraph:{SplitParagraph:function(a,b,c){var e,f;a.position + +(c) 2009-2014 Stuart Knightley +Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip/master/LICENSE.markdown. + +JSZip uses the library pako released under the MIT license : +https://github.com/nodeca/pako/blob/master/LICENSE + @licend +*/ +!function(e){var globalScope=typeof window!=="undefined"?window:typeof global!=="undefined"?global:{},externs=globalScope.externs||(globalScope.externs={});externs.JSZip=e()}(function(){var define,module,exports;return function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'");}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f, +f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o>2;enc2=(chr1&3)<<4|chr2>>4;enc3=(chr2&15)<<2|chr3>> +6;enc4=chr3&63;if(isNaN(chr2))enc3=enc4=64;else if(isNaN(chr3))enc4=64;output=output+_keyStr.charAt(enc1)+_keyStr.charAt(enc2)+_keyStr.charAt(enc3)+_keyStr.charAt(enc4)}return output};exports.decode=function(input,utf8){var output="";var chr1,chr2,chr3;var enc1,enc2,enc3,enc4;var i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,"");while(i>4;chr2=(enc2&15)<<4|enc3>>2;chr3=(enc3&3)<<6|enc4;output=output+String.fromCharCode(chr1);if(enc3!=64)output=output+String.fromCharCode(chr2);if(enc4!=64)output=output+String.fromCharCode(chr3)}return output}},{}],2:[function(_dereq_,module,exports){function CompressedObject(){this.compressedSize=0;this.uncompressedSize=0;this.crc32=0;this.compressionMethod=null;this.compressedContent=null}CompressedObject.prototype={getContent:function(){return null},getCompressedContent:function(){return null}}; +module.exports=CompressedObject},{}],3:[function(_dereq_,module,exports){exports.STORE={magic:"\x00\x00",compress:function(content){return content},uncompress:function(content){return content},compressInputType:null,uncompressInputType:null};exports.DEFLATE=_dereq_("./flate")},{"./flate":8}],4:[function(_dereq_,module,exports){var utils=_dereq_("./utils");var table=[0,1996959894,3993919788,2567524794,124634137,1886057615,3915621685,2657392035,249268274,2044508324,3772115230,2547177864,162941995,2125561021, +3887607047,2428444049,498536548,1789927666,4089016648,2227061214,450548861,1843258603,4107580753,2211677639,325883990,1684777152,4251122042,2321926636,335633487,1661365465,4195302755,2366115317,997073096,1281953886,3579855332,2724688242,1006888145,1258607687,3524101629,2768942443,901097722,1119000684,3686517206,2898065728,853044451,1172266101,3705015759,2882616665,651767980,1373503546,3369554304,3218104598,565507253,1454621731,3485111705,3099436303,671266974,1594198024,3322730930,2970347812,795835527, +1483230225,3244367275,3060149565,1994146192,31158534,2563907772,4023717930,1907459465,112637215,2680153253,3904427059,2013776290,251722036,2517215374,3775830040,2137656763,141376813,2439277719,3865271297,1802195444,476864866,2238001368,4066508878,1812370925,453092731,2181625025,4111451223,1706088902,314042704,2344532202,4240017532,1658658271,366619977,2362670323,4224994405,1303535960,984961486,2747007092,3569037538,1256170817,1037604311,2765210733,3554079995,1131014506,879679996,2909243462,3663771856, +1141124467,855842277,2852801631,3708648649,1342533948,654459306,3188396048,3373015174,1466479909,544179635,3110523913,3462522015,1591671054,702138776,2966460450,3352799412,1504918807,783551873,3082640443,3233442989,3988292384,2596254646,62317068,1957810842,3939845945,2647816111,81470997,1943803523,3814918930,2489596804,225274430,2053790376,3826175755,2466906013,167816743,2097651377,4027552580,2265490386,503444072,1762050814,4150417245,2154129355,426522225,1852507879,4275313526,2312317920,282753626, +1742555852,4189708143,2394877945,397917763,1622183637,3604390888,2714866558,953729732,1340076626,3518719985,2797360999,1068828381,1219638859,3624741850,2936675148,906185462,1090812512,3747672003,2825379669,829329135,1181335161,3412177804,3160834842,628085408,1382605366,3423369109,3138078467,570562233,1426400815,3317316542,2998733608,733239954,1555261956,3268935591,3050360625,752459403,1541320221,2607071920,3965973030,1969922972,40735498,2617837225,3943577151,1913087877,83908371,2512341634,3803740692, +2075208622,213261112,2463272603,3855990285,2094854071,198958881,2262029012,4057260610,1759359992,534414190,2176718541,4139329115,1873836001,414664567,2282248934,4279200368,1711684554,285281116,2405801727,4167216745,1634467795,376229701,2685067896,3608007406,1308918612,956543938,2808555105,3495958263,1231636301,1047427035,2932959818,3654703836,1088359270,936918E3,2847714899,3736837829,1202900863,817233897,3183342108,3401237130,1404277552,615818150,3134207493,3453421203,1423857449,601450431,3009837614, +3294710456,1567103746,711928724,3020668471,3272380065,1510334235,755167117];module.exports=function crc32(input,crc){if(typeof input==="undefined"||!input.length)return 0;var isArray=utils.getTypeOf(input)!=="string";if(typeof crc=="undefined")crc=0;var x=0;var y=0;var b=0;crc=crc^-1;for(var i=0,iTop=input.length;i>>8^x}return crc^-1}},{"./utils":21}],5:[function(_dereq_,module,exports){var utils=_dereq_("./utils"); +function DataReader(data){this.data=null;this.length=0;this.index=0}DataReader.prototype={checkOffset:function(offset){this.checkIndex(this.index+offset)},checkIndex:function(newIndex){if(this.length=this.index;i--)result=(result<<8)+this.byteAt(i);this.index+=size;return result},readString:function(size){return utils.transformTo("string",this.readData(size))},readData:function(size){},lastIndexOfSignature:function(sig){},readDate:function(){var dostime=this.readInt(4);return new Date((dostime>>25&127)+1980,(dostime>>21&15)-1,dostime>>16&31,dostime>>11&31,dostime>>5&63,(dostime&31)<<1)}};module.exports=DataReader},{"./utils":21}],6:[function(_dereq_, +module,exports){exports.base64=false;exports.binary=false;exports.dir=false;exports.createFolders=false;exports.date=null;exports.compression=null;exports.comment=null},{}],7:[function(_dereq_,module,exports){var utils=_dereq_("./utils");exports.string2binary=function(str){return utils.string2binary(str)};exports.string2Uint8Array=function(str){return utils.transformTo("uint8array",str)};exports.uint8Array2String=function(array){return utils.transformTo("string",array)};exports.string2Blob=function(str){var buffer= +utils.transformTo("arraybuffer",str);return utils.arrayBuffer2Blob(buffer)};exports.arrayBuffer2Blob=function(buffer){return utils.arrayBuffer2Blob(buffer)};exports.transformTo=function(outputType,input){return utils.transformTo(outputType,input)};exports.getTypeOf=function(input){return utils.getTypeOf(input)};exports.checkSupport=function(type){return utils.checkSupport(type)};exports.MAX_VALUE_16BITS=utils.MAX_VALUE_16BITS;exports.MAX_VALUE_32BITS=utils.MAX_VALUE_32BITS;exports.pretty=function(str){return utils.pretty(str)}; +exports.findCompression=function(compressionMethod){return utils.findCompression(compressionMethod)};exports.isRegExp=function(object){return utils.isRegExp(object)}},{"./utils":21}],8:[function(_dereq_,module,exports){var USE_TYPEDARRAY=typeof Uint8Array!=="undefined"&&typeof Uint16Array!=="undefined"&&typeof Uint32Array!=="undefined";var pako=_dereq_("pako");exports.uncompressInputType=USE_TYPEDARRAY?"uint8array":"array";exports.compressInputType=USE_TYPEDARRAY?"uint8array":"array";exports.magic= +"\b\x00";exports.compress=function(input){return pako.deflateRaw(input)};exports.uncompress=function(input){return pako.inflateRaw(input)}},{"pako":24}],9:[function(_dereq_,module,exports){var base64=_dereq_("./base64");function JSZip(data,options){if(!(this instanceof JSZip))return new JSZip(data,options);this.files={};this.comment=null;this.root="";if(data)this.load(data,options);this.clone=function(){var newObj=new JSZip;for(var i in this)if(typeof this[i]!=="function")newObj[i]=this[i];return newObj}} +JSZip.prototype=_dereq_("./object");JSZip.prototype.load=_dereq_("./load");JSZip.support=_dereq_("./support");JSZip.defaults=_dereq_("./defaults");JSZip.utils=_dereq_("./deprecatedPublicUtils");JSZip.base64={encode:function(input){return base64.encode(input)},decode:function(input){return base64.decode(input)}};JSZip.compressions=_dereq_("./compressions");module.exports=JSZip},{"./base64":1,"./compressions":3,"./defaults":6,"./deprecatedPublicUtils":7,"./load":10,"./object":13,"./support":17}],10:[function(_dereq_, +module,exports){var base64=_dereq_("./base64");var ZipEntries=_dereq_("./zipEntries");module.exports=function(data,options){var files,zipEntries,i,input;options=options||{};if(options.base64)data=base64.decode(data);zipEntries=new ZipEntries(data,options);files=zipEntries.files;for(i=0;i>>8}return hex};var extend=function(){var result={},i,attr;for(i=0;i0?path.substring(0,lastSlash):""};var folderAdd=function(name,createFolders){if(name.slice(-1)!="/")name+="/";createFolders=typeof createFolders!=="undefined"?createFolders:false;if(!this.files[name])fileAdd.call(this,name,null,{dir:true,createFolders:createFolders});return this.files[name]};var generateCompressedObjectFrom=function(file,compression){var result=new CompressedObject,content;if(file._data instanceof +CompressedObject){result.uncompressedSize=file._data.uncompressedSize;result.crc32=file._data.crc32;if(result.uncompressedSize===0||file.dir){compression=compressions["STORE"];result.compressedContent="";result.crc32=0}else if(file._data.compressionMethod===compression.magic)result.compressedContent=file._data.getCompressedContent();else{content=file._data.getContent();result.compressedContent=compression.compress(utils.transformTo(compression.compressInputType,content))}}else{content=getBinaryData(file); +if(!content||content.length===0||file.dir){compression=compressions["STORE"];content=""}result.uncompressedSize=content.length;result.crc32=crc32(content);result.compressedContent=compression.compress(utils.transformTo(compression.compressInputType,content))}result.compressedSize=result.compressedContent.length;result.compressionMethod=compression.magic;return result};var generateZipParts=function(name,file,compressedObject,offset){var data=compressedObject.compressedContent,utfEncodedFileName=utils.transformTo("string", +utf8.utf8encode(file.name)),comment=file.comment||"",utfEncodedComment=utils.transformTo("string",utf8.utf8encode(comment)),useUTF8ForFileName=utfEncodedFileName.length!==file.name.length,useUTF8ForComment=utfEncodedComment.length!==comment.length,o=file.options,dosTime,dosDate,extraFields="",unicodePathExtraField="",unicodeCommentExtraField="",dir,date;if(file._initialMetadata.dir!==file.dir)dir=file.dir;else dir=o.dir;if(file._initialMetadata.date!==file.date)date=file.date;else date=o.date;dosTime= +date.getHours();dosTime=dosTime<<6;dosTime=dosTime|date.getMinutes();dosTime=dosTime<<5;dosTime=dosTime|date.getSeconds()/2;dosDate=date.getFullYear()-1980;dosDate=dosDate<<4;dosDate=dosDate|date.getMonth()+1;dosDate=dosDate<<5;dosDate=dosDate|date.getDate();if(useUTF8ForFileName){unicodePathExtraField=decToHex(1,1)+decToHex(crc32(utfEncodedFileName),4)+utfEncodedFileName;extraFields+="up"+decToHex(unicodePathExtraField.length,2)+unicodePathExtraField}if(useUTF8ForComment){unicodeCommentExtraField= +decToHex(1,1)+decToHex(this.crc32(utfEncodedComment),4)+utfEncodedComment;extraFields+="uc"+decToHex(unicodeCommentExtraField.length,2)+unicodeCommentExtraField}var header="";header+="\n\x00";header+=useUTF8ForFileName||useUTF8ForComment?"\x00\b":"\x00\x00";header+=compressedObject.compressionMethod;header+=decToHex(dosTime,2);header+=decToHex(dosDate,2);header+=decToHex(compressedObject.crc32,4);header+=decToHex(compressedObject.compressedSize,4);header+=decToHex(compressedObject.uncompressedSize, +4);header+=decToHex(utfEncodedFileName.length,2);header+=decToHex(extraFields.length,2);var fileRecord=signature.LOCAL_FILE_HEADER+header+utfEncodedFileName+extraFields;var dirRecord=signature.CENTRAL_FILE_HEADER+"\u0014\x00"+header+decToHex(utfEncodedComment.length,2)+"\x00\x00"+"\x00\x00"+(dir===true?"\u0010\x00\x00\x00":"\x00\x00\x00\x00")+decToHex(offset,4)+utfEncodedFileName+extraFields+utfEncodedComment;return{fileRecord:fileRecord,dirRecord:dirRecord,compressedObject:compressedObject}};var out= +{load:function(stream,options){throw new Error("Load method is not defined. Is the file jszip-load.js included ?");},filter:function(search){var result=[],filename,relativePath,file,fileClone;for(filename in this.files){if(!this.files.hasOwnProperty(filename))continue;file=this.files[filename];fileClone=new ZipObject(file.name,file._data,extend(file.options));relativePath=filename.slice(this.root.length,filename.length);if(filename.slice(0,this.root.length)===this.root&&search(relativePath,fileClone))result.push(fileClone)}return result}, +file:function(name,data,o){if(arguments.length===1)if(utils.isRegExp(name)){var regexp=name;return this.filter(function(relativePath,file){return!file.dir&®exp.test(relativePath)})}else return this.filter(function(relativePath,file){return!file.dir&&relativePath===name})[0]||null;else{name=this.root+name;fileAdd.call(this,name,data,o)}return this},folder:function(arg){if(!arg)return this;if(utils.isRegExp(arg))return this.filter(function(relativePath,file){return file.dir&&arg.test(relativePath)}); +var name=this.root+arg;var newFolder=folderAdd.call(this,name);var ret=this.clone();ret.root=newFolder.name;return ret},remove:function(name){name=this.root+name;var file=this.files[name];if(!file){if(name.slice(-1)!="/")name+="/";file=this.files[name]}if(file&&!file.dir)delete this.files[name];else{var kids=this.filter(function(relativePath,file){return file.name.slice(0,name.length)===name});for(var i=0;i=0;--i)if(this.data[i]===sig0&&this.data[i+1]===sig1&&this.data[i+2]===sig2&&this.data[i+3]===sig3)return i;return-1};Uint8ArrayReader.prototype.readData=function(size){this.checkOffset(size);if(size===0)return new Uint8Array(0);var result=this.data.subarray(this.index, +this.index+size);this.index+=size;return result};module.exports=Uint8ArrayReader},{"./dataReader":5}],19:[function(_dereq_,module,exports){var utils=_dereq_("./utils");var Uint8ArrayWriter=function(length){this.data=new Uint8Array(length);this.index=0};Uint8ArrayWriter.prototype={append:function(input){if(input.length!==0){input=utils.transformTo("uint8array",input);this.data.set(input,this.index);this.index+=input.length}},finalize:function(){return this.data}};module.exports=Uint8ArrayWriter},{"./utils":21}], +20:[function(_dereq_,module,exports){var utils=_dereq_("./utils");var support=_dereq_("./support");var nodeBuffer=_dereq_("./nodeBuffer");var _utf8len=new Array(256);for(var i=0;i<256;i++)_utf8len[i]=i>=252?6:i>=248?5:i>=240?4:i>=224?3:i>=192?2:1;_utf8len[254]=_utf8len[254]=1;var string2buf=function(str){var buf,c,c2,m_pos,i,str_len=str.length,buf_len=0;for(m_pos=0;m_pos>>6;buf[i++]=128|c&63}else if(c<65536){buf[i++]=224|c>>>12;buf[i++]=128|c>>>6&63;buf[i++]=128|c&63}else{buf[i++]= +240|c>>>18;buf[i++]=128|c>>>12&63;buf[i++]=128|c>>>6&63;buf[i++]=128|c&63}}return buf};var utf8border=function(buf,max){var pos;max=max||buf.length;if(max>buf.length)max=buf.length;pos=max-1;while(pos>=0&&(buf[pos]&192)===128)pos--;if(pos<0)return max;if(pos===0)return max;return pos+_utf8len[buf[pos]]>max?pos:max};var buf2string=function(buf){var str,i,out,c,c_len;var len=buf.length;var utf16buf=new Array(len*2);for(out=0,i=0;i4){utf16buf[out++]=65533;i+=c_len-1;continue}c&=c_len===2?31:c_len===3?15:7;while(c_len>1&&i1){utf16buf[out++]=65533;continue}if(c<65536)utf16buf[out++]=c;else{c-=65536;utf16buf[out++]=55296|c>>10&1023;utf16buf[out++]=56320|c&1023}}if(utf16buf.length!==out)if(utf16buf.subarray)utf16buf=utf16buf.subarray(0,out);else utf16buf.length=out;return utils.applyFromCharCode(utf16buf)};exports.utf8encode=function utf8encode(str){if(support.nodebuffer)return nodeBuffer(str, +"utf-8");return string2buf(str)};exports.utf8decode=function utf8decode(buf){if(support.nodebuffer)return utils.transformTo("nodebuffer",buf).toString("utf-8");buf=utils.transformTo(support.uint8array?"uint8array":"array",buf);var result=[],k=0,len=buf.length,chunk=65536;while(k1)try{if(type==="array"||type==="nodebuffer")result.push(String.fromCharCode.apply(null,array.slice(k,Math.min(k+chunk,len))));else result.push(String.fromCharCode.apply(null, +array.subarray(k,Math.min(k+chunk,len))));k+=chunk}catch(e){chunk=Math.floor(chunk/2)}return result.join("")}exports.applyFromCharCode=arrayLikeToString;function arrayLikeToArrayLike(arrayFrom,arrayTo){for(var i=0;i1)throw new Error("Multi-volumes zip are not supported");},readLocalFiles:function(){var i,file;for(i=0;i0)opt.windowBits=-opt.windowBits;else if(opt.gzip&&opt.windowBits>0&&opt.windowBits<16)opt.windowBits+=16;this.err=0;this.msg="";this.ended=false;this.chunks=[];this.strm=new zstream;this.strm.avail_out=0;var status=zlib_deflate.deflateInit2(this.strm,opt.level,opt.method,opt.windowBits,opt.memLevel,opt.strategy);if(status!==Z_OK)throw new Error(msg[status]); +if(opt.header)zlib_deflate.deflateSetHeader(this.strm,opt.header)};Deflate.prototype.push=function(data,mode){var strm=this.strm;var chunkSize=this.options.chunkSize;var status,_mode;if(this.ended)return false;_mode=mode===~~mode?mode:mode===true?Z_FINISH:Z_NO_FLUSH;if(typeof data==="string")strm.input=strings.string2buf(data);else strm.input=data;strm.next_in=0;strm.avail_in=strm.input.length;do{if(strm.avail_out===0){strm.output=new utils.Buf8(chunkSize);strm.next_out=0;strm.avail_out=chunkSize}status= +zlib_deflate.deflate(strm,_mode);if(status!==Z_STREAM_END&&status!==Z_OK){this.onEnd(status);this.ended=true;return false}if(strm.avail_out===0||strm.avail_in===0&&_mode===Z_FINISH)if(this.options.to==="string")this.onData(strings.buf2binstring(utils.shrinkBuf(strm.output,strm.next_out)));else this.onData(utils.shrinkBuf(strm.output,strm.next_out))}while((strm.avail_in>0||strm.avail_out===0)&&status!==Z_STREAM_END);if(_mode===Z_FINISH){status=zlib_deflate.deflateEnd(this.strm);this.onEnd(status); +this.ended=true;return status===Z_OK}return true};Deflate.prototype.onData=function(chunk){this.chunks.push(chunk)};Deflate.prototype.onEnd=function(status){if(status===Z_OK)if(this.options.to==="string")this.result=this.chunks.join("");else this.result=utils.flattenChunks(this.chunks);this.chunks=[];this.err=status;this.msg=this.strm.msg};function deflate(input,options){var deflator=new Deflate(options);deflator.push(input,true);if(deflator.err)throw deflator.msg;return deflator.result}function deflateRaw(input, +options){options=options||{};options.raw=true;return deflate(input,options)}function gzip(input,options){options=options||{};options.gzip=true;return deflate(input,options)}exports.Deflate=Deflate;exports.deflate=deflate;exports.deflateRaw=deflateRaw;exports.gzip=gzip},{"./utils/common":27,"./utils/strings":28,"./zlib/deflate.js":32,"./zlib/messages":37,"./zlib/zstream":39}],26:[function(_dereq_,module,exports){var zlib_inflate=_dereq_("./zlib/inflate.js");var utils=_dereq_("./utils/common");var strings= +_dereq_("./utils/strings");var c=_dereq_("./zlib/constants");var msg=_dereq_("./zlib/messages");var zstream=_dereq_("./zlib/zstream");var gzheader=_dereq_("./zlib/gzheader");var Inflate=function(options){this.options=utils.assign({chunkSize:16384,windowBits:0,to:""},options||{});var opt=this.options;if(opt.raw&&opt.windowBits>=0&&opt.windowBits<16){opt.windowBits=-opt.windowBits;if(opt.windowBits===0)opt.windowBits=-15}if(opt.windowBits>=0&&opt.windowBits<16&&!(options&&options.windowBits))opt.windowBits+= +32;if(opt.windowBits>15&&opt.windowBits<48)if((opt.windowBits&15)===0)opt.windowBits|=15;this.err=0;this.msg="";this.ended=false;this.chunks=[];this.strm=new zstream;this.strm.avail_out=0;var status=zlib_inflate.inflateInit2(this.strm,opt.windowBits);if(status!==c.Z_OK)throw new Error(msg[status]);this.header=new gzheader;zlib_inflate.inflateGetHeader(this.strm,this.header)};Inflate.prototype.push=function(data,mode){var strm=this.strm;var chunkSize=this.options.chunkSize;var status,_mode;var next_out_utf8, +tail,utf8str;if(this.ended)return false;_mode=mode===~~mode?mode:mode===true?c.Z_FINISH:c.Z_NO_FLUSH;if(typeof data==="string")strm.input=strings.binstring2buf(data);else strm.input=data;strm.next_in=0;strm.avail_in=strm.input.length;do{if(strm.avail_out===0){strm.output=new utils.Buf8(chunkSize);strm.next_out=0;strm.avail_out=chunkSize}status=zlib_inflate.inflate(strm,c.Z_NO_FLUSH);if(status!==c.Z_STREAM_END&&status!==c.Z_OK){this.onEnd(status);this.ended=true;return false}if(strm.next_out)if(strm.avail_out=== +0||status===c.Z_STREAM_END||strm.avail_in===0&&_mode===c.Z_FINISH)if(this.options.to==="string"){next_out_utf8=strings.utf8border(strm.output,strm.next_out);tail=strm.next_out-next_out_utf8;utf8str=strings.buf2string(strm.output,next_out_utf8);strm.next_out=tail;strm.avail_out=chunkSize-tail;if(tail)utils.arraySet(strm.output,strm.output,next_out_utf8,tail,0);this.onData(utf8str)}else this.onData(utils.shrinkBuf(strm.output,strm.next_out))}while(strm.avail_in>0&&status!==c.Z_STREAM_END);if(status=== +c.Z_STREAM_END)_mode=c.Z_FINISH;if(_mode===c.Z_FINISH){status=zlib_inflate.inflateEnd(this.strm);this.onEnd(status);this.ended=true;return status===c.Z_OK}return true};Inflate.prototype.onData=function(chunk){this.chunks.push(chunk)};Inflate.prototype.onEnd=function(status){if(status===c.Z_OK)if(this.options.to==="string")this.result=this.chunks.join("");else this.result=utils.flattenChunks(this.chunks);this.chunks=[];this.err=status;this.msg=this.strm.msg};function inflate(input,options){var inflator= +new Inflate(options);inflator.push(input,true);if(inflator.err)throw inflator.msg;return inflator.result}function inflateRaw(input,options){options=options||{};options.raw=true;return inflate(input,options)}exports.Inflate=Inflate;exports.inflate=inflate;exports.inflateRaw=inflateRaw;exports.ungzip=inflate},{"./utils/common":27,"./utils/strings":28,"./zlib/constants":30,"./zlib/gzheader":33,"./zlib/inflate.js":35,"./zlib/messages":37,"./zlib/zstream":39}],27:[function(_dereq_,module,exports){var TYPED_OK= +typeof Uint8Array!=="undefined"&&typeof Uint16Array!=="undefined"&&typeof Int32Array!=="undefined";exports.assign=function(obj){var sources=Array.prototype.slice.call(arguments,1);while(sources.length){var source=sources.shift();if(!source)continue;if(typeof source!=="object")throw new TypeError(source+"must be non-object");for(var p in source)if(source.hasOwnProperty(p))obj[p]=source[p]}return obj};exports.shrinkBuf=function(buf,size){if(buf.length===size)return buf;if(buf.subarray)return buf.subarray(0, +size);buf.length=size;return buf};var fnTyped={arraySet:function(dest,src,src_offs,len,dest_offs){if(src.subarray&&dest.subarray){dest.set(src.subarray(src_offs,src_offs+len),dest_offs);return}for(var i=0;i=252?6:i>=248?5:i>=240?4:i>=224?3:i>=192?2:1;_utf8len[254]=_utf8len[254]=1;exports.string2buf=function(str){var buf,c,c2,m_pos,i,str_len=str.length,buf_len=0;for(m_pos=0;m_pos>>6;buf[i++]=128|c&63}else if(c<65536){buf[i++]=224|c>>>12;buf[i++]= +128|c>>>6&63;buf[i++]=128|c&63}else{buf[i++]=240|c>>>18;buf[i++]=128|c>>>12&63;buf[i++]=128|c>>>6&63;buf[i++]=128|c&63}}return buf};function buf2binstring(buf,len){if(len<65537)if(buf.subarray&&STR_APPLY_UIA_OK||!buf.subarray&&STR_APPLY_OK)return String.fromCharCode.apply(null,utils.shrinkBuf(buf,len));var result="";for(var i=0;i4){utf16buf[out++]=65533;i+=c_len-1;continue}c&=c_len===2?31:c_len===3?15:7;while(c_len>1&&i1){utf16buf[out++]=65533;continue}if(c<65536)utf16buf[out++]= +c;else{c-=65536;utf16buf[out++]=55296|c>>10&1023;utf16buf[out++]=56320|c&1023}}return buf2binstring(utf16buf,out)};exports.utf8border=function(buf,max){var pos;max=max||buf.length;if(max>buf.length)max=buf.length;pos=max-1;while(pos>=0&&(buf[pos]&192)===128)pos--;if(pos<0)return max;if(pos===0)return max;return pos+_utf8len[buf[pos]]>max?pos:max}},{"./common":27}],29:[function(_dereq_,module,exports){function adler32(adler,buf,len,pos){var s1=adler&65535|0,s2=adler>>>16&65535|0,n=0;while(len!==0){n= +len>2E3?2E3:len;len-=n;do{s1=s1+buf[pos++]|0;s2=s2+s1|0}while(--n);s1%=65521;s2%=65521}return s1|s2<<16|0}module.exports=adler32},{}],30:[function(_dereq_,module,exports){module.exports={Z_NO_FLUSH:0,Z_PARTIAL_FLUSH:1,Z_SYNC_FLUSH:2,Z_FULL_FLUSH:3,Z_FINISH:4,Z_BLOCK:5,Z_TREES:6,Z_OK:0,Z_STREAM_END:1,Z_NEED_DICT:2,Z_ERRNO:-1,Z_STREAM_ERROR:-2,Z_DATA_ERROR:-3,Z_BUF_ERROR:-5,Z_NO_COMPRESSION:0,Z_BEST_SPEED:1,Z_BEST_COMPRESSION:9,Z_DEFAULT_COMPRESSION:-1,Z_FILTERED:1,Z_HUFFMAN_ONLY:2,Z_RLE:3,Z_FIXED:4, +Z_DEFAULT_STRATEGY:0,Z_BINARY:0,Z_TEXT:1,Z_UNKNOWN:2,Z_DEFLATED:8}},{}],31:[function(_dereq_,module,exports){function makeTable(){var c,table=[];for(var n=0;n<256;n++){c=n;for(var k=0;k<8;k++)c=c&1?3988292384^c>>>1:c>>>1;table[n]=c}return table}var crcTable=makeTable();function crc32(crc,buf,len,pos){var t=crcTable,end=pos+len;crc=crc^-1;for(var i=pos;i>>8^t[(crc^buf[i])&255];return crc^-1}module.exports=crc32},{}],32:[function(_dereq_,module,exports){var utils=_dereq_("../utils/common"); +var trees=_dereq_("./trees");var adler32=_dereq_("./adler32");var crc32=_dereq_("./crc32");var msg=_dereq_("./messages");var Z_NO_FLUSH=0;var Z_PARTIAL_FLUSH=1;var Z_FULL_FLUSH=3;var Z_FINISH=4;var Z_BLOCK=5;var Z_OK=0;var Z_STREAM_END=1;var Z_STREAM_ERROR=-2;var Z_DATA_ERROR=-3;var Z_BUF_ERROR=-5;var Z_DEFAULT_COMPRESSION=-1;var Z_FILTERED=1;var Z_HUFFMAN_ONLY=2;var Z_RLE=3;var Z_FIXED=4;var Z_DEFAULT_STRATEGY=0;var Z_UNKNOWN=2;var Z_DEFLATED=8;var MAX_MEM_LEVEL=9;var MAX_WBITS=15;var DEF_MEM_LEVEL= +8;var LENGTH_CODES=29;var LITERALS=256;var L_CODES=LITERALS+1+LENGTH_CODES;var D_CODES=30;var BL_CODES=19;var HEAP_SIZE=2*L_CODES+1;var MAX_BITS=15;var MIN_MATCH=3;var MAX_MATCH=258;var MIN_LOOKAHEAD=MAX_MATCH+MIN_MATCH+1;var PRESET_DICT=32;var INIT_STATE=42;var EXTRA_STATE=69;var NAME_STATE=73;var COMMENT_STATE=91;var HCRC_STATE=103;var BUSY_STATE=113;var FINISH_STATE=666;var BS_NEED_MORE=1;var BS_BLOCK_DONE=2;var BS_FINISH_STARTED=3;var BS_FINISH_DONE=4;var OS_CODE=3;function err(strm,errorCode){strm.msg= +msg[errorCode];return errorCode}function rank(f){return(f<<1)-(f>4?9:0)}function zero(buf){var len=buf.length;while(--len>=0)buf[len]=0}function flush_pending(strm){var s=strm.state;var len=s.pending;if(len>strm.avail_out)len=strm.avail_out;if(len===0)return;utils.arraySet(strm.output,s.pending_buf,s.pending_out,len,strm.next_out);strm.next_out+=len;s.pending_out+=len;strm.total_out+=len;strm.avail_out-=len;s.pending-=len;if(s.pending===0)s.pending_out=0}function flush_block_only(s,last){trees._tr_flush_block(s, +s.block_start>=0?s.block_start:-1,s.strstart-s.block_start,last);s.block_start=s.strstart;flush_pending(s.strm)}function put_byte(s,b){s.pending_buf[s.pending++]=b}function putShortMSB(s,b){s.pending_buf[s.pending++]=b>>>8&255;s.pending_buf[s.pending++]=b&255}function read_buf(strm,buf,start,size){var len=strm.avail_in;if(len>size)len=size;if(len===0)return 0;strm.avail_in-=len;utils.arraySet(buf,strm.input,strm.next_in,len,start);if(strm.state.wrap===1)strm.adler=adler32(strm.adler,buf,len,start); +else if(strm.state.wrap===2)strm.adler=crc32(strm.adler,buf,len,start);strm.next_in+=len;strm.total_in+=len;return len}function longest_match(s,cur_match){var chain_length=s.max_chain_length;var scan=s.strstart;var match;var len;var best_len=s.prev_length;var nice_match=s.nice_match;var limit=s.strstart>s.w_size-MIN_LOOKAHEAD?s.strstart-(s.w_size-MIN_LOOKAHEAD):0;var _win=s.window;var wmask=s.w_mask;var prev=s.prev;var strend=s.strstart+MAX_MATCH;var scan_end1=_win[scan+best_len-1];var scan_end=_win[scan+ +best_len];if(s.prev_length>=s.good_match)chain_length>>=2;if(nice_match>s.lookahead)nice_match=s.lookahead;do{match=cur_match;if(_win[match+best_len]!==scan_end||_win[match+best_len-1]!==scan_end1||_win[match]!==_win[scan]||_win[++match]!==_win[scan+1])continue;scan+=2;match++;do;while(_win[++scan]===_win[++match]&&_win[++scan]===_win[++match]&&_win[++scan]===_win[++match]&&_win[++scan]===_win[++match]&&_win[++scan]===_win[++match]&&_win[++scan]===_win[++match]&&_win[++scan]===_win[++match]&&_win[++scan]=== +_win[++match]&&scanbest_len){s.match_start=cur_match;best_len=len;if(len>=nice_match)break;scan_end1=_win[scan+best_len-1];scan_end=_win[scan+best_len]}}while((cur_match=prev[cur_match&wmask])>limit&&--chain_length!==0);if(best_len<=s.lookahead)return best_len;return s.lookahead}function fill_window(s){var _w_size=s.w_size;var p,n,m,more,str;do{more=s.window_size-s.lookahead-s.strstart;if(s.strstart>=_w_size+(_w_size-MIN_LOOKAHEAD)){utils.arraySet(s.window, +s.window,_w_size,_w_size,0);s.match_start-=_w_size;s.strstart-=_w_size;s.block_start-=_w_size;n=s.hash_size;p=n;do{m=s.head[--p];s.head[p]=m>=_w_size?m-_w_size:0}while(--n);n=_w_size;p=n;do{m=s.prev[--p];s.prev[p]=m>=_w_size?m-_w_size:0}while(--n);more+=_w_size}if(s.strm.avail_in===0)break;n=read_buf(s.strm,s.window,s.strstart+s.lookahead,more);s.lookahead+=n;if(s.lookahead+s.insert>=MIN_MATCH){str=s.strstart-s.insert;s.ins_h=s.window[str];s.ins_h=(s.ins_h<s.pending_buf_size-5)max_block_size=s.pending_buf_size-5;for(;;){if(s.lookahead<=1){fill_window(s);if(s.lookahead===0&&flush===Z_NO_FLUSH)return BS_NEED_MORE;if(s.lookahead=== +0)break}s.strstart+=s.lookahead;s.lookahead=0;var max_start=s.block_start+max_block_size;if(s.strstart===0||s.strstart>=max_start){s.lookahead=s.strstart-max_start;s.strstart=max_start;flush_block_only(s,false);if(s.strm.avail_out===0)return BS_NEED_MORE}if(s.strstart-s.block_start>=s.w_size-MIN_LOOKAHEAD){flush_block_only(s,false);if(s.strm.avail_out===0)return BS_NEED_MORE}}s.insert=0;if(flush===Z_FINISH){flush_block_only(s,true);if(s.strm.avail_out===0)return BS_FINISH_STARTED;return BS_FINISH_DONE}if(s.strstart> +s.block_start){flush_block_only(s,false);if(s.strm.avail_out===0)return BS_NEED_MORE}return BS_NEED_MORE}function deflate_fast(s,flush){var hash_head;var bflush;for(;;){if(s.lookahead=MIN_MATCH){s.ins_h=(s.ins_h<=MIN_MATCH){bflush=trees._tr_tally(s,s.strstart-s.match_start,s.match_length-MIN_MATCH);s.lookahead-=s.match_length;if(s.match_length<=s.max_lazy_match&&s.lookahead>=MIN_MATCH){s.match_length--;do{s.strstart++;s.ins_h=(s.ins_h<=MIN_MATCH){s.ins_h=(s.ins_h<4096))s.match_length=MIN_MATCH-1}if(s.prev_length>=MIN_MATCH&&s.match_length<=s.prev_length){max_insert=s.strstart+s.lookahead-MIN_MATCH;bflush=trees._tr_tally(s,s.strstart-1-s.prev_match,s.prev_length- +MIN_MATCH);s.lookahead-=s.prev_length-1;s.prev_length-=2;do if(++s.strstart<=max_insert){s.ins_h=(s.ins_h<=MIN_MATCH&&s.strstart>0){scan=s.strstart-1;prev=_win[scan];if(prev===_win[++scan]&&prev===_win[++scan]&&prev===_win[++scan]){strend=s.strstart+MAX_MATCH;do;while(prev===_win[++scan]&&prev===_win[++scan]&&prev===_win[++scan]&&prev===_win[++scan]&& +prev===_win[++scan]&&prev===_win[++scan]&&prev===_win[++scan]&&prev===_win[++scan]&&scans.lookahead)s.match_length=s.lookahead}}if(s.match_length>=MIN_MATCH){bflush=trees._tr_tally(s,1,s.match_length-MIN_MATCH);s.lookahead-=s.match_length;s.strstart+=s.match_length;s.match_length=0}else{bflush=trees._tr_tally(s,0,s.window[s.strstart]);s.lookahead--;s.strstart++}if(bflush){flush_block_only(s,false);if(s.strm.avail_out===0)return BS_NEED_MORE}}s.insert= +0;if(flush===Z_FINISH){flush_block_only(s,true);if(s.strm.avail_out===0)return BS_FINISH_STARTED;return BS_FINISH_DONE}if(s.last_lit){flush_block_only(s,false);if(s.strm.avail_out===0)return BS_NEED_MORE}return BS_BLOCK_DONE}function deflate_huff(s,flush){var bflush;for(;;){if(s.lookahead===0){fill_window(s);if(s.lookahead===0){if(flush===Z_NO_FLUSH)return BS_NEED_MORE;break}}s.match_length=0;bflush=trees._tr_tally(s,0,s.window[s.strstart]);s.lookahead--;s.strstart++;if(bflush){flush_block_only(s, +false);if(s.strm.avail_out===0)return BS_NEED_MORE}}s.insert=0;if(flush===Z_FINISH){flush_block_only(s,true);if(s.strm.avail_out===0)return BS_FINISH_STARTED;return BS_FINISH_DONE}if(s.last_lit){flush_block_only(s,false);if(s.strm.avail_out===0)return BS_NEED_MORE}return BS_BLOCK_DONE}var Config=function(good_length,max_lazy,nice_length,max_chain,func){this.good_length=good_length;this.max_lazy=max_lazy;this.nice_length=nice_length;this.max_chain=max_chain;this.func=func};var configuration_table; +configuration_table=[new Config(0,0,0,0,deflate_stored),new Config(4,4,8,4,deflate_fast),new Config(4,5,16,8,deflate_fast),new Config(4,6,32,32,deflate_fast),new Config(4,4,16,16,deflate_slow),new Config(8,16,32,32,deflate_slow),new Config(8,16,128,128,deflate_slow),new Config(8,32,128,256,deflate_slow),new Config(32,128,258,1024,deflate_slow),new Config(32,258,258,4096,deflate_slow)];function lm_init(s){s.window_size=2*s.w_size;zero(s.head);s.max_lazy_match=configuration_table[s.level].max_lazy; +s.good_match=configuration_table[s.level].good_length;s.nice_match=configuration_table[s.level].nice_length;s.max_chain_length=configuration_table[s.level].max_chain;s.strstart=0;s.block_start=0;s.lookahead=0;s.insert=0;s.match_length=s.prev_length=MIN_MATCH-1;s.match_available=0;s.ins_h=0}function DeflateState(){this.strm=null;this.status=0;this.pending_buf=null;this.pending_buf_size=0;this.pending_out=0;this.pending=0;this.wrap=0;this.gzhead=null;this.gzindex=0;this.method=Z_DEFLATED;this.last_flush= +-1;this.w_size=0;this.w_bits=0;this.w_mask=0;this.window=null;this.window_size=0;this.prev=null;this.head=null;this.ins_h=0;this.hash_size=0;this.hash_bits=0;this.hash_mask=0;this.hash_shift=0;this.block_start=0;this.match_length=0;this.prev_match=0;this.match_available=0;this.strstart=0;this.match_start=0;this.lookahead=0;this.prev_length=0;this.max_chain_length=0;this.max_lazy_match=0;this.level=0;this.strategy=0;this.good_match=0;this.nice_match=0;this.dyn_ltree=new utils.Buf16(HEAP_SIZE*2);this.dyn_dtree= +new utils.Buf16((2*D_CODES+1)*2);this.bl_tree=new utils.Buf16((2*BL_CODES+1)*2);zero(this.dyn_ltree);zero(this.dyn_dtree);zero(this.bl_tree);this.l_desc=null;this.d_desc=null;this.bl_desc=null;this.bl_count=new utils.Buf16(MAX_BITS+1);this.heap=new utils.Buf16(2*L_CODES+1);zero(this.heap);this.heap_len=0;this.heap_max=0;this.depth=new utils.Buf16(2*L_CODES+1);zero(this.depth);this.l_buf=0;this.lit_bufsize=0;this.last_lit=0;this.d_buf=0;this.opt_len=0;this.static_len=0;this.matches=0;this.insert=0; +this.bi_buf=0;this.bi_valid=0}function deflateResetKeep(strm){var s;if(!strm||!strm.state)return err(strm,Z_STREAM_ERROR);strm.total_in=strm.total_out=0;strm.data_type=Z_UNKNOWN;s=strm.state;s.pending=0;s.pending_out=0;if(s.wrap<0)s.wrap=-s.wrap;s.status=s.wrap?INIT_STATE:BUSY_STATE;strm.adler=s.wrap===2?0:1;s.last_flush=Z_NO_FLUSH;trees._tr_init(s);return Z_OK}function deflateReset(strm){var ret=deflateResetKeep(strm);if(ret===Z_OK)lm_init(strm.state);return ret}function deflateSetHeader(strm,head){if(!strm|| +!strm.state)return Z_STREAM_ERROR;if(strm.state.wrap!==2)return Z_STREAM_ERROR;strm.state.gzhead=head;return Z_OK}function deflateInit2(strm,level,method,windowBits,memLevel,strategy){if(!strm)return Z_STREAM_ERROR;var wrap=1;if(level===Z_DEFAULT_COMPRESSION)level=6;if(windowBits<0){wrap=0;windowBits=-windowBits}else if(windowBits>15){wrap=2;windowBits-=16}if(memLevel<1||memLevel>MAX_MEM_LEVEL||method!==Z_DEFLATED||windowBits<8||windowBits>15||level<0||level>9||strategy<0||strategy>Z_FIXED)return err(strm, +Z_STREAM_ERROR);if(windowBits===8)windowBits=9;var s=new DeflateState;strm.state=s;s.strm=strm;s.wrap=wrap;s.gzhead=null;s.w_bits=windowBits;s.w_size=1<>1;s.l_buf=(1+2)*s.lit_bufsize;s.level=level;s.strategy=strategy;s.method=method;return deflateReset(strm)}function deflateInit(strm,level){return deflateInit2(strm,level,Z_DEFLATED,MAX_WBITS,DEF_MEM_LEVEL,Z_DEFAULT_STRATEGY)}function deflate(strm,flush){var old_flush,s;var beg,val;if(!strm||!strm.state||flush>Z_BLOCK||flush<0)return strm?err(strm,Z_STREAM_ERROR):Z_STREAM_ERROR;s=strm.state;if(!strm.output||!strm.input&&strm.avail_in!==0||s.status===FINISH_STATE&&flush!==Z_FINISH)return err(strm, +strm.avail_out===0?Z_BUF_ERROR:Z_STREAM_ERROR);s.strm=strm;old_flush=s.last_flush;s.last_flush=flush;if(s.status===INIT_STATE)if(s.wrap===2){strm.adler=0;put_byte(s,31);put_byte(s,139);put_byte(s,8);if(!s.gzhead){put_byte(s,0);put_byte(s,0);put_byte(s,0);put_byte(s,0);put_byte(s,0);put_byte(s,s.level===9?2:s.strategy>=Z_HUFFMAN_ONLY||s.level<2?4:0);put_byte(s,OS_CODE);s.status=BUSY_STATE}else{put_byte(s,(s.gzhead.text?1:0)+(s.gzhead.hcrc?2:0)+(!s.gzhead.extra?0:4)+(!s.gzhead.name?0:8)+(!s.gzhead.comment? +0:16));put_byte(s,s.gzhead.time&255);put_byte(s,s.gzhead.time>>8&255);put_byte(s,s.gzhead.time>>16&255);put_byte(s,s.gzhead.time>>24&255);put_byte(s,s.level===9?2:s.strategy>=Z_HUFFMAN_ONLY||s.level<2?4:0);put_byte(s,s.gzhead.os&255);if(s.gzhead.extra&&s.gzhead.extra.length){put_byte(s,s.gzhead.extra.length&255);put_byte(s,s.gzhead.extra.length>>8&255)}if(s.gzhead.hcrc)strm.adler=crc32(strm.adler,s.pending_buf,s.pending,0);s.gzindex=0;s.status=EXTRA_STATE}}else{var header=Z_DEFLATED+(s.w_bits-8<< +4)<<8;var level_flags=-1;if(s.strategy>=Z_HUFFMAN_ONLY||s.level<2)level_flags=0;else if(s.level<6)level_flags=1;else if(s.level===6)level_flags=2;else level_flags=3;header|=level_flags<<6;if(s.strstart!==0)header|=PRESET_DICT;header+=31-header%31;s.status=BUSY_STATE;putShortMSB(s,header);if(s.strstart!==0){putShortMSB(s,strm.adler>>>16);putShortMSB(s,strm.adler&65535)}strm.adler=1}if(s.status===EXTRA_STATE)if(s.gzhead.extra){beg=s.pending;while(s.gzindex<(s.gzhead.extra.length&65535)){if(s.pending=== +s.pending_buf_size){if(s.gzhead.hcrc&&s.pending>beg)strm.adler=crc32(strm.adler,s.pending_buf,s.pending-beg,beg);flush_pending(strm);beg=s.pending;if(s.pending===s.pending_buf_size)break}put_byte(s,s.gzhead.extra[s.gzindex]&255);s.gzindex++}if(s.gzhead.hcrc&&s.pending>beg)strm.adler=crc32(strm.adler,s.pending_buf,s.pending-beg,beg);if(s.gzindex===s.gzhead.extra.length){s.gzindex=0;s.status=NAME_STATE}}else s.status=NAME_STATE;if(s.status===NAME_STATE)if(s.gzhead.name){beg=s.pending;do{if(s.pending=== +s.pending_buf_size){if(s.gzhead.hcrc&&s.pending>beg)strm.adler=crc32(strm.adler,s.pending_buf,s.pending-beg,beg);flush_pending(strm);beg=s.pending;if(s.pending===s.pending_buf_size){val=1;break}}if(s.gzindexbeg)strm.adler=crc32(strm.adler,s.pending_buf,s.pending-beg,beg);if(val===0){s.gzindex=0;s.status=COMMENT_STATE}}else s.status=COMMENT_STATE;if(s.status===COMMENT_STATE)if(s.gzhead.comment){beg= +s.pending;do{if(s.pending===s.pending_buf_size){if(s.gzhead.hcrc&&s.pending>beg)strm.adler=crc32(strm.adler,s.pending_buf,s.pending-beg,beg);flush_pending(strm);beg=s.pending;if(s.pending===s.pending_buf_size){val=1;break}}if(s.gzindexbeg)strm.adler=crc32(strm.adler,s.pending_buf,s.pending-beg,beg);if(val===0)s.status=HCRC_STATE}else s.status=HCRC_STATE;if(s.status=== +HCRC_STATE)if(s.gzhead.hcrc){if(s.pending+2>s.pending_buf_size)flush_pending(strm);if(s.pending+2<=s.pending_buf_size){put_byte(s,strm.adler&255);put_byte(s,strm.adler>>8&255);strm.adler=0;s.status=BUSY_STATE}}else s.status=BUSY_STATE;if(s.pending!==0){flush_pending(strm);if(strm.avail_out===0){s.last_flush=-1;return Z_OK}}else if(strm.avail_in===0&&rank(flush)<=rank(old_flush)&&flush!==Z_FINISH)return err(strm,Z_BUF_ERROR);if(s.status===FINISH_STATE&&strm.avail_in!==0)return err(strm,Z_BUF_ERROR); +if(strm.avail_in!==0||s.lookahead!==0||flush!==Z_NO_FLUSH&&s.status!==FINISH_STATE){var bstate=s.strategy===Z_HUFFMAN_ONLY?deflate_huff(s,flush):s.strategy===Z_RLE?deflate_rle(s,flush):configuration_table[s.level].func(s,flush);if(bstate===BS_FINISH_STARTED||bstate===BS_FINISH_DONE)s.status=FINISH_STATE;if(bstate===BS_NEED_MORE||bstate===BS_FINISH_STARTED){if(strm.avail_out===0)s.last_flush=-1;return Z_OK}if(bstate===BS_BLOCK_DONE){if(flush===Z_PARTIAL_FLUSH)trees._tr_align(s);else if(flush!==Z_BLOCK){trees._tr_stored_block(s, +0,0,false);if(flush===Z_FULL_FLUSH){zero(s.head);if(s.lookahead===0){s.strstart=0;s.block_start=0;s.insert=0}}}flush_pending(strm);if(strm.avail_out===0){s.last_flush=-1;return Z_OK}}}if(flush!==Z_FINISH)return Z_OK;if(s.wrap<=0)return Z_STREAM_END;if(s.wrap===2){put_byte(s,strm.adler&255);put_byte(s,strm.adler>>8&255);put_byte(s,strm.adler>>16&255);put_byte(s,strm.adler>>24&255);put_byte(s,strm.total_in&255);put_byte(s,strm.total_in>>8&255);put_byte(s,strm.total_in>>16&255);put_byte(s,strm.total_in>> +24&255)}else{putShortMSB(s,strm.adler>>>16);putShortMSB(s,strm.adler&65535)}flush_pending(strm);if(s.wrap>0)s.wrap=-s.wrap;return s.pending!==0?Z_OK:Z_STREAM_END}function deflateEnd(strm){var status;if(!strm||!strm.state)return Z_STREAM_ERROR;status=strm.state.status;if(status!==INIT_STATE&&status!==EXTRA_STATE&&status!==NAME_STATE&&status!==COMMENT_STATE&&status!==HCRC_STATE&&status!==BUSY_STATE&&status!==FINISH_STATE)return err(strm,Z_STREAM_ERROR);strm.state=null;return status===BUSY_STATE?err(strm, +Z_DATA_ERROR):Z_OK}exports.deflateInit=deflateInit;exports.deflateInit2=deflateInit2;exports.deflateReset=deflateReset;exports.deflateResetKeep=deflateResetKeep;exports.deflateSetHeader=deflateSetHeader;exports.deflate=deflate;exports.deflateEnd=deflateEnd;exports.deflateInfo="pako deflate (from Nodeca project)"},{"../utils/common":27,"./adler32":29,"./crc32":31,"./messages":37,"./trees":38}],33:[function(_dereq_,module,exports){function GZheader(){this.text=0;this.time=0;this.xflags=0;this.os=0; +this.extra=null;this.extra_len=0;this.name="";this.comment="";this.hcrc=0;this.done=false}module.exports=GZheader},{}],34:[function(_dereq_,module,exports){var BAD=30;var TYPE=12;module.exports=function inflate_fast(strm,start){var state;var _in;var last;var _out;var beg;var end;var dmax;var wsize;var whave;var wnext;var window;var hold;var bits;var lcode;var dcode;var lmask;var dmask;var here;var op;var len;var dist;var from;var from_source;var input,output;state=strm.state;_in=strm.next_in;input= +strm.input;last=_in+(strm.avail_in-5);_out=strm.next_out;output=strm.output;beg=_out-(start-strm.avail_out);end=_out+(strm.avail_out-257);dmax=state.dmax;wsize=state.wsize;whave=state.whave;wnext=state.wnext;window=state.window;hold=state.hold;bits=state.bits;lcode=state.lencode;dcode=state.distcode;lmask=(1<>>24;hold>>>=op; +bits-=op;op=here>>>16&255;if(op===0)output[_out++]=here&65535;else if(op&16){len=here&65535;op&=15;if(op){if(bits>>=op;bits-=op}if(bits<15){hold+=input[_in++]<>>24;hold>>>=op;bits-=op;op=here>>>16&255;if(op&16){dist=here&65535;op&=15;if(bitsdmax){strm.msg="invalid distance too far back";state.mode=BAD;break top}hold>>>=op;bits-=op;op=_out-beg;if(dist>op){op=dist-op;if(op>whave)if(state.sane){strm.msg="invalid distance too far back";state.mode=BAD;break top}from=0;from_source=window;if(wnext===0){from+=wsize-op;if(op2){output[_out++]=from_source[from++];output[_out++]=from_source[from++];output[_out++]=from_source[from++];len-=3}if(len){output[_out++]=from_source[from++];if(len>1)output[_out++]=from_source[from++]}}else{from=_out-dist;do{output[_out++]=output[from++];output[_out++]= +output[from++];output[_out++]=output[from++];len-=3}while(len>2);if(len){output[_out++]=output[from++];if(len>1)output[_out++]=output[from++]}}}else if((op&64)===0){here=dcode[(here&65535)+(hold&(1<>3;_in-=len;bits-=len<<3;hold&=(1<>>24&255)+(q>>>8&65280)+((q&65280)<<8)+((q&255)<<24)}function InflateState(){this.mode=0;this.last=false;this.wrap=0;this.havedict=false;this.flags=0;this.dmax=0;this.check=0;this.total=0;this.head=null;this.wbits=0;this.wsize=0;this.whave=0;this.wnext=0;this.window=null;this.hold=0;this.bits=0;this.length=0;this.offset= +0;this.extra=0;this.lencode=null;this.distcode=null;this.lenbits=0;this.distbits=0;this.ncode=0;this.nlen=0;this.ndist=0;this.have=0;this.next=null;this.lens=new utils.Buf16(320);this.work=new utils.Buf16(288);this.lendyn=null;this.distdyn=null;this.sane=0;this.back=0;this.was=0}function inflateResetKeep(strm){var state;if(!strm||!strm.state)return Z_STREAM_ERROR;state=strm.state;strm.total_in=strm.total_out=state.total=0;strm.msg="";if(state.wrap)strm.adler=state.wrap&1;state.mode=HEAD;state.last= +0;state.havedict=0;state.dmax=32768;state.head=null;state.hold=0;state.bits=0;state.lencode=state.lendyn=new utils.Buf32(ENOUGH_LENS);state.distcode=state.distdyn=new utils.Buf32(ENOUGH_DISTS);state.sane=1;state.back=-1;return Z_OK}function inflateReset(strm){var state;if(!strm||!strm.state)return Z_STREAM_ERROR;state=strm.state;state.wsize=0;state.whave=0;state.wnext=0;return inflateResetKeep(strm)}function inflateReset2(strm,windowBits){var wrap;var state;if(!strm||!strm.state)return Z_STREAM_ERROR; +state=strm.state;if(windowBits<0){wrap=0;windowBits=-windowBits}else{wrap=(windowBits>>4)+1;if(windowBits<48)windowBits&=15}if(windowBits&&(windowBits<8||windowBits>15))return Z_STREAM_ERROR;if(state.window!==null&&state.wbits!==windowBits)state.window=null;state.wrap=wrap;state.wbits=windowBits;return inflateReset(strm)}function inflateInit2(strm,windowBits){var ret;var state;if(!strm)return Z_STREAM_ERROR;state=new InflateState;strm.state=state;state.window=null;ret=inflateReset2(strm,windowBits); +if(ret!==Z_OK)strm.state=null;return ret}function inflateInit(strm){return inflateInit2(strm,DEF_WBITS)}var virgin=true;var lenfix,distfix;function fixedtables(state){if(virgin){var sym;lenfix=new utils.Buf32(512);distfix=new utils.Buf32(32);sym=0;while(sym<144)state.lens[sym++]=8;while(sym<256)state.lens[sym++]=9;while(sym<280)state.lens[sym++]=7;while(sym<288)state.lens[sym++]=8;inflate_table(LENS,state.lens,0,288,lenfix,0,state.work,{bits:9});sym=0;while(sym<32)state.lens[sym++]=5;inflate_table(DISTS, +state.lens,0,32,distfix,0,state.work,{bits:5});virgin=false}state.lencode=lenfix;state.lenbits=9;state.distcode=distfix;state.distbits=5}function updatewindow(strm,src,end,copy){var dist;var state=strm.state;if(state.window===null){state.wsize=1<=state.wsize){utils.arraySet(state.window,src,end-state.wsize,state.wsize,0);state.wnext=0;state.whave=state.wsize}else{dist=state.wsize-state.wnext;if(dist>copy)dist= +copy;utils.arraySet(state.window,src,end-copy,dist,state.wnext);copy-=dist;if(copy){utils.arraySet(state.window,src,end-copy,copy,0);state.wnext=copy;state.whave=state.wsize}else{state.wnext+=dist;if(state.wnext===state.wsize)state.wnext=0;if(state.whave>>8&255;state.check=crc32(state.check,hbuf,2,0);hold=0;bits=0;state.mode=FLAGS;break}state.flags=0;if(state.head)state.head.done=false;if(!(state.wrap&1)||(((hold&255)<<8)+(hold>>8))%31){strm.msg="incorrect header check";state.mode=BAD;break}if((hold&15)!==Z_DEFLATED){strm.msg="unknown compression method";state.mode= +BAD;break}hold>>>=4;bits-=4;len=(hold&15)+8;if(state.wbits===0)state.wbits=len;else if(len>state.wbits){strm.msg="invalid window size";state.mode=BAD;break}state.dmax=1<>8&1;if(state.flags&512){hbuf[0]=hold&255;hbuf[1]=hold>>>8&255;state.check=crc32(state.check,hbuf,2,0)}hold=0;bits=0;state.mode=TIME;case TIME:while(bits<32){if(have===0)break inf_leave;have--;hold+=input[next++]<>>8&255;hbuf[2]=hold>>>16&255;hbuf[3]=hold>>>24&255;state.check=crc32(state.check,hbuf,4,0)}hold=0;bits=0;state.mode=OS;case OS:while(bits< +16){if(have===0)break inf_leave;have--;hold+=input[next++]<>8}if(state.flags&512){hbuf[0]=hold&255;hbuf[1]=hold>>>8&255;state.check=crc32(state.check,hbuf,2,0)}hold=0;bits=0;state.mode=EXLEN;case EXLEN:if(state.flags&1024){while(bits<16){if(have===0)break inf_leave;have--;hold+=input[next++]<>>8&255;state.check= +crc32(state.check,hbuf,2,0)}hold=0;bits=0}else if(state.head)state.head.extra=null;state.mode=EXTRA;case EXTRA:if(state.flags&1024){copy=state.length;if(copy>have)copy=have;if(copy){if(state.head){len=state.head.extra_len-state.length;if(!state.head.extra)state.head.extra=new Array(state.head.extra_len);utils.arraySet(state.head.extra,input,next,copy,len)}if(state.flags&512)state.check=crc32(state.check,input,copy,next);have-=copy;next+=copy;state.length-=copy}if(state.length)break inf_leave}state.length= +0;state.mode=NAME;case NAME:if(state.flags&2048){if(have===0)break inf_leave;copy=0;do{len=input[next+copy++];if(state.head&&len&&state.length<65536)state.head.name+=String.fromCharCode(len)}while(len&©>9&1;state.head.done=true}strm.adler=state.check=0;state.mode=TYPE;break;case DICTID:while(bits<32){if(have===0)break inf_leave;have--;hold+=input[next++]<>>=bits&7;bits-=bits&7;state.mode=CHECK;break}while(bits<3){if(have===0)break inf_leave;have--;hold+=input[next++]<>>=1;bits-=1;switch(hold&3){case 0:state.mode=STORED;break;case 1:fixedtables(state);state.mode=LEN_;if(flush===Z_TREES){hold>>>=2;bits-=2;break inf_leave}break;case 2:state.mode=TABLE;break;case 3:strm.msg="invalid block type";state.mode=BAD}hold>>>=2;bits-=2;break;case STORED:hold>>>=bits&7;bits-=bits&7;while(bits< +32){if(have===0)break inf_leave;have--;hold+=input[next++]<>>16^65535)){strm.msg="invalid stored block lengths";state.mode=BAD;break}state.length=hold&65535;hold=0;bits=0;state.mode=COPY_;if(flush===Z_TREES)break inf_leave;case COPY_:state.mode=COPY;case COPY:copy=state.length;if(copy){if(copy>have)copy=have;if(copy>left)copy=left;if(copy===0)break inf_leave;utils.arraySet(output,input,next,copy,put);have-=copy;next+=copy;left-=copy;put+=copy;state.length-=copy; +break}state.mode=TYPE;break;case TABLE:while(bits<14){if(have===0)break inf_leave;have--;hold+=input[next++]<>>=5;bits-=5;state.ndist=(hold&31)+1;hold>>>=5;bits-=5;state.ncode=(hold&15)+4;hold>>>=4;bits-=4;if(state.nlen>286||state.ndist>30){strm.msg="too many length or distance symbols";state.mode=BAD;break}state.have=0;state.mode=LENLENS;case LENLENS:while(state.have>>=3;bits-=3}while(state.have<19)state.lens[order[state.have++]]=0;state.lencode=state.lendyn;state.lenbits=7;opts={bits:state.lenbits};ret=inflate_table(CODES,state.lens,0,19,state.lencode,0,state.work,opts);state.lenbits=opts.bits;if(ret){strm.msg="invalid code lengths set";state.mode=BAD;break}state.have=0;state.mode=CODELENS;case CODELENS:while(state.have>>24;here_op=here>>>16&255;here_val=here&65535;if(here_bits<=bits)break;if(have===0)break inf_leave;have--;hold+=input[next++]<>>=here_bits;bits-=here_bits;state.lens[state.have++]=here_val}else{if(here_val===16){n=here_bits+2;while(bits>>=here_bits;bits-=here_bits;if(state.have===0){strm.msg="invalid bit length repeat";state.mode=BAD;break}len=state.lens[state.have-1];copy=3+(hold& +3);hold>>>=2;bits-=2}else if(here_val===17){n=here_bits+3;while(bits>>=here_bits;bits-=here_bits;len=0;copy=3+(hold&7);hold>>>=3;bits-=3}else{n=here_bits+7;while(bits>>=here_bits;bits-=here_bits;len=0;copy=11+(hold&127);hold>>>=7;bits-=7}if(state.have+copy>state.nlen+state.ndist){strm.msg="invalid bit length repeat";state.mode=BAD;break}while(copy--)state.lens[state.have++]= +len}}if(state.mode===BAD)break;if(state.lens[256]===0){strm.msg="invalid code -- missing end-of-block";state.mode=BAD;break}state.lenbits=9;opts={bits:state.lenbits};ret=inflate_table(LENS,state.lens,0,state.nlen,state.lencode,0,state.work,opts);state.lenbits=opts.bits;if(ret){strm.msg="invalid literal/lengths set";state.mode=BAD;break}state.distbits=6;state.distcode=state.distdyn;opts={bits:state.distbits};ret=inflate_table(DISTS,state.lens,state.nlen,state.ndist,state.distcode,0,state.work,opts); +state.distbits=opts.bits;if(ret){strm.msg="invalid distances set";state.mode=BAD;break}state.mode=LEN_;if(flush===Z_TREES)break inf_leave;case LEN_:state.mode=LEN;case LEN:if(have>=6&&left>=258){strm.next_out=put;strm.avail_out=left;strm.next_in=next;strm.avail_in=have;state.hold=hold;state.bits=bits;inflate_fast(strm,_out);put=strm.next_out;output=strm.output;left=strm.avail_out;next=strm.next_in;input=strm.input;have=strm.avail_in;hold=state.hold;bits=state.bits;if(state.mode===TYPE)state.back= +-1;break}state.back=0;for(;;){here=state.lencode[hold&(1<>>24;here_op=here>>>16&255;here_val=here&65535;if(here_bits<=bits)break;if(have===0)break inf_leave;have--;hold+=input[next++]<>last_bits)];here_bits=here>>>24;here_op=here>>>16&255;here_val=here&65535;if(last_bits+here_bits<=bits)break;if(have=== +0)break inf_leave;have--;hold+=input[next++]<>>=last_bits;bits-=last_bits;state.back+=last_bits}hold>>>=here_bits;bits-=here_bits;state.back+=here_bits;state.length=here_val;if(here_op===0){state.mode=LIT;break}if(here_op&32){state.back=-1;state.mode=TYPE;break}if(here_op&64){strm.msg="invalid literal/length code";state.mode=BAD;break}state.extra=here_op&15;state.mode=LENEXT;case LENEXT:if(state.extra){n=state.extra;while(bits>>=state.extra;bits-=state.extra;state.back+=state.extra}state.was=state.length;state.mode=DIST;case DIST:for(;;){here=state.distcode[hold&(1<>>24;here_op=here>>>16&255;here_val=here&65535;if(here_bits<=bits)break;if(have===0)break inf_leave;have--;hold+=input[next++]<>last_bits)];here_bits=here>>>24;here_op=here>>>16&255;here_val=here&65535;if(last_bits+here_bits<=bits)break;if(have===0)break inf_leave;have--;hold+=input[next++]<>>=last_bits;bits-=last_bits;state.back+=last_bits}hold>>>=here_bits;bits-=here_bits;state.back+=here_bits;if(here_op&64){strm.msg="invalid distance code";state.mode=BAD;break}state.offset=here_val;state.extra=here_op&15;state.mode=DISTEXT;case DISTEXT:if(state.extra){n=state.extra;while(bits>>=state.extra;bits-=state.extra;state.back+=state.extra}if(state.offset>state.dmax){strm.msg="invalid distance too far back";state.mode=BAD;break}state.mode=MATCH;case MATCH:if(left===0)break inf_leave;copy=_out-left;if(state.offset>copy){copy=state.offset-copy;if(copy>state.whave)if(state.sane){strm.msg="invalid distance too far back";state.mode=BAD;break}if(copy>state.wnext){copy-=state.wnext; +from=state.wsize-copy}else from=state.wnext-copy;if(copy>state.length)copy=state.length;from_source=state.window}else{from_source=output;from=put-state.offset;copy=state.length}if(copy>left)copy=left;left-=copy;state.length-=copy;do output[put++]=from_source[from++];while(--copy);if(state.length===0)state.mode=LEN;break;case LIT:if(left===0)break inf_leave;output[put++]=state.length;left--;state.mode=LEN;break;case CHECK:if(state.wrap){while(bits<32){if(have===0)break inf_leave;have--;hold|=input[next++]<< +bits;bits+=8}_out-=left;strm.total_out+=_out;state.total+=_out;if(_out)strm.adler=state.check=state.flags?crc32(state.check,output,_out,put-_out):adler32(state.check,output,_out,put-_out);_out=left;if((state.flags?hold:ZSWAP32(hold))!==state.check){strm.msg="incorrect data check";state.mode=BAD;break}hold=0;bits=0}state.mode=LENGTH;case LENGTH:if(state.wrap&&state.flags){while(bits<32){if(have===0)break inf_leave;have--;hold+=input[next++]<=1;max--)if(count[max]!==0)break;if(root>max)root=max;if(max===0){table[table_index++]=1<<24|64<<16|0;table[table_index++]= +1<<24|64<<16|0;opts.bits=1;return 0}for(min=1;min0&&(type===CODES||max!==1))return-1;offs[1]=0;for(len=1;lenENOUGH_LENS||type===DISTS&&used>ENOUGH_DISTS)return 1;var i=0;for(;;){i++;here_bits=len-drop;if(work[sym]end){here_op=extra[extra_index+work[sym]];here_val=base[base_index+work[sym]]}else{here_op=32+64;here_val=0}incr=1<>drop)+fill]= +here_bits<<24|here_op<<16|here_val|0}while(fill!==0);incr=1<>=1;if(incr!==0){huff&=incr-1;huff+=incr}else huff=0;sym++;if(--count[len]===0){if(len===max)break;len=lens[lens_index+work[sym]]}if(len>root&&(huff&mask)!==low){if(drop===0)drop=root;next+=min;curr=len-drop;left=1<ENOUGH_LENS||type===DISTS&&used>ENOUGH_DISTS)return 1;low=huff&mask;table[low]=root<< +24|curr<<16|next-table_index|0}}if(huff!==0)table[next+huff]=len-drop<<24|64<<16|0;opts.bits=root;return 0}},{"../utils/common":27}],37:[function(_dereq_,module,exports){module.exports={2:"need dictionary",1:"stream end",0:"","-1":"file error","-2":"stream error","-3":"data error","-4":"insufficient memory","-5":"buffer error","-6":"incompatible version"}},{}],38:[function(_dereq_,module,exports){var utils=_dereq_("../utils/common");var Z_FIXED=4;var Z_BINARY=0;var Z_TEXT=1;var Z_UNKNOWN=2;function zero(buf){var len= +buf.length;while(--len>=0)buf[len]=0}var STORED_BLOCK=0;var STATIC_TREES=1;var DYN_TREES=2;var MIN_MATCH=3;var MAX_MATCH=258;var LENGTH_CODES=29;var LITERALS=256;var L_CODES=LITERALS+1+LENGTH_CODES;var D_CODES=30;var BL_CODES=19;var HEAP_SIZE=2*L_CODES+1;var MAX_BITS=15;var Buf_size=16;var MAX_BL_BITS=7;var END_BLOCK=256;var REP_3_6=16;var REPZ_3_10=17;var REPZ_11_138=18;var extra_lbits=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0];var extra_dbits=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7, +7,8,8,9,9,10,10,11,11,12,12,13,13];var extra_blbits=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7];var bl_order=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15];var DIST_CODE_LEN=512;var static_ltree=new Array((L_CODES+2)*2);zero(static_ltree);var static_dtree=new Array(D_CODES*2);zero(static_dtree);var _dist_code=new Array(DIST_CODE_LEN);zero(_dist_code);var _length_code=new Array(MAX_MATCH-MIN_MATCH+1);zero(_length_code);var base_length=new Array(LENGTH_CODES);zero(base_length);var base_dist=new Array(D_CODES); +zero(base_dist);var StaticTreeDesc=function(static_tree,extra_bits,extra_base,elems,max_length){this.static_tree=static_tree;this.extra_bits=extra_bits;this.extra_base=extra_base;this.elems=elems;this.max_length=max_length;this.has_stree=static_tree&&static_tree.length};var static_l_desc;var static_d_desc;var static_bl_desc;var TreeDesc=function(dyn_tree,stat_desc){this.dyn_tree=dyn_tree;this.max_code=0;this.stat_desc=stat_desc};function d_code(dist){return dist<256?_dist_code[dist]:_dist_code[256+ +(dist>>>7)]}function put_short(s,w){s.pending_buf[s.pending++]=w&255;s.pending_buf[s.pending++]=w>>>8&255}function send_bits(s,value,length){if(s.bi_valid>Buf_size-length){s.bi_buf|=value<>Buf_size-s.bi_valid;s.bi_valid+=length-Buf_size}else{s.bi_buf|=value<>>=1;res<<=1}while(--len>0); +return res>>>1}function bi_flush(s){if(s.bi_valid===16){put_short(s,s.bi_buf);s.bi_buf=0;s.bi_valid=0}else if(s.bi_valid>=8){s.pending_buf[s.pending++]=s.bi_buf&255;s.bi_buf>>=8;s.bi_valid-=8}}function gen_bitlen(s,desc){var tree=desc.dyn_tree;var max_code=desc.max_code;var stree=desc.stat_desc.static_tree;var has_stree=desc.stat_desc.has_stree;var extra=desc.stat_desc.extra_bits;var base=desc.stat_desc.extra_base;var max_length=desc.stat_desc.max_length;var h;var n,m;var bits;var xbits;var f;var overflow= +0;for(bits=0;bits<=MAX_BITS;bits++)s.bl_count[bits]=0;tree[s.heap[s.heap_max]*2+1]=0;for(h=s.heap_max+1;hmax_length){bits=max_length;overflow++}tree[n*2+1]=bits;if(n>max_code)continue;s.bl_count[bits]++;xbits=0;if(n>=base)xbits=extra[n-base];f=tree[n*2];s.opt_len+=f*(bits+xbits);if(has_stree)s.static_len+=f*(stree[n*2+1]+xbits)}if(overflow===0)return;do{bits=max_length-1;while(s.bl_count[bits]===0)bits--;s.bl_count[bits]--;s.bl_count[bits+ +1]+=2;s.bl_count[max_length]--;overflow-=2}while(overflow>0);for(bits=max_length;bits!==0;bits--){n=s.bl_count[bits];while(n!==0){m=s.heap[--h];if(m>max_code)continue;if(tree[m*2+1]!==bits){s.opt_len+=(bits-tree[m*2+1])*tree[m*2];tree[m*2+1]=bits}n--}}}function gen_codes(tree,max_code,bl_count){var next_code=new Array(MAX_BITS+1);var code=0;var bits;var n;for(bits=1;bits<=MAX_BITS;bits++)next_code[bits]=code=code+bl_count[bits-1]<<1;for(n=0;n<=max_code;n++){var len=tree[n*2+1];if(len===0)continue; +tree[n*2]=bi_reverse(next_code[len]++,len)}}function tr_static_init(){var n;var bits;var length;var code;var dist;var bl_count=new Array(MAX_BITS+1);length=0;for(code=0;code>=7;for(;code8)put_short(s,s.bi_buf);else if(s.bi_valid>0)s.pending_buf[s.pending++]= +s.bi_buf;s.bi_buf=0;s.bi_valid=0}function copy_block(s,buf,len,header){bi_windup(s);if(header){put_short(s,len);put_short(s,~len)}utils.arraySet(s.pending_buf,s.window,buf,len,s.pending);s.pending+=len}function smaller(tree,n,m,depth){var _n2=n*2;var _m2=m*2;return tree[_n2]>1;n>=1;n--)pqdownheap(s,tree,n);node=elems;do{n=s.heap[1];s.heap[1]=s.heap[s.heap_len--];pqdownheap(s,tree,1);m=s.heap[1];s.heap[--s.heap_max]=n;s.heap[--s.heap_max]=m;tree[node*2]=tree[n*2]+tree[m*2];s.depth[node]=(s.depth[n]>=s.depth[m]?s.depth[n]:s.depth[m])+1;tree[n*2+1]=tree[m*2+1]=node;s.heap[1]=node++;pqdownheap(s,tree,1)}while(s.heap_len>=2);s.heap[--s.heap_max]=s.heap[1];gen_bitlen(s, +desc);gen_codes(tree,max_code,s.bl_count)}function scan_tree(s,tree,max_code){var n;var prevlen=-1;var curlen;var nextlen=tree[0*2+1];var count=0;var max_count=7;var min_count=4;if(nextlen===0){max_count=138;min_count=3}tree[(max_code+1)*2+1]=65535;for(n=0;n<=max_code;n++){curlen=nextlen;nextlen=tree[(n+1)*2+1];if(++count=3;max_blindex--)if(s.bl_tree[bl_order[max_blindex]*2+1]!==0)break;s.opt_len+=3*(max_blindex+1)+5+5+4;return max_blindex}function send_all_trees(s,lcodes,dcodes,blcodes){var rank;send_bits(s,lcodes-257,5);send_bits(s,dcodes-1,5);send_bits(s,blcodes-4,4);for(rank=0;rank>>=1)if(black_mask&1&&s.dyn_ltree[n*2]!==0)return Z_BINARY;if(s.dyn_ltree[9*2]!==0||s.dyn_ltree[10*2]!==0||s.dyn_ltree[13*2]!==0)return Z_TEXT;for(n=32;n0){if(s.strm.data_type===Z_UNKNOWN)s.strm.data_type= +detect_data_type(s);build_tree(s,s.l_desc);build_tree(s,s.d_desc);max_blindex=build_bl_tree(s);opt_lenb=s.opt_len+3+7>>>3;static_lenb=s.static_len+3+7>>>3;if(static_lenb<=opt_lenb)opt_lenb=static_lenb}else opt_lenb=static_lenb=stored_len+5;if(stored_len+4<=opt_lenb&&buf!==-1)_tr_stored_block(s,buf,stored_len,last);else if(s.strategy===Z_FIXED||static_lenb===opt_lenb){send_bits(s,(STATIC_TREES<<1)+(last?1:0),3);compress_block(s,static_ltree,static_dtree)}else{send_bits(s,(DYN_TREES<<1)+(last?1:0), +3);send_all_trees(s,s.l_desc.max_code+1,s.d_desc.max_code+1,max_blindex+1);compress_block(s,s.dyn_ltree,s.dyn_dtree)}init_block(s);if(last)bi_windup(s)}function _tr_tally(s,dist,lc){s.pending_buf[s.d_buf+s.last_lit*2]=dist>>>8&255;s.pending_buf[s.d_buf+s.last_lit*2+1]=dist&255;s.pending_buf[s.l_buf+s.last_lit]=lc&255;s.last_lit++;if(dist===0)s.dyn_ltree[lc*2]++;else{s.matches++;dist--;s.dyn_ltree[(_length_code[lc]+LITERALS+1)*2]++;s.dyn_dtree[d_code(dist)*2]++}return s.last_lit===s.lit_bufsize-1} +exports._tr_init=_tr_init;exports._tr_stored_block=_tr_stored_block;exports._tr_flush_block=_tr_flush_block;exports._tr_tally=_tr_tally;exports._tr_align=_tr_align},{"../utils/common":27}],39:[function(_dereq_,module,exports){function ZStream(){this.input=null;this.next_in=0;this.avail_in=0;this.total_in=0;this.output=null;this.next_out=0;this.avail_out=0;this.total_out=0;this.msg="";this.state=null;this.data_type=2;this.adler=0}module.exports=ZStream},{}]},{},[9])(9)}); diff --git a/muk_web_preview/static/src/js/preview_dialog.js b/muk_web_preview/static/src/js/preview_dialog.js new file mode 100644 index 0000000..97dce3e --- /dev/null +++ b/muk_web_preview/static/src/js/preview_dialog.js @@ -0,0 +1,102 @@ +/********************************************************************************** +* +* Copyright (C) 2017 MuK IT GmbH +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU Affero 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 Affero General Public License for more details. +* +* You should have received a copy of the GNU Affero General Public License +* along with this program. If not, see . +* +**********************************************************************************/ + +odoo.define('muk_preview.PreviewDialog', function (require) { +"use strict"; + +var core = require('web.core'); +var Widget = require('web.Widget'); + +var PreviewHandler = require('muk_preview.PreviewHandler'); +var PreviewGenerator = require('muk_preview.PreviewGenerator'); + +var QWeb = core.qweb; +var _t = core._t; + +var PreviewDialog = Widget.extend({ + init: function(parent, generator, url, mimetype, extension, title) { + var self = this; + this._super(parent); + this.generator = generator; + this._opened = $.Deferred(); + this.title = title || _t('Preview'); + this.url = url; + this.mimetype = mimetype; + this.extension = extension; + this.$modal = $(QWeb.render('PreviewDialog', {title: this.title, url: this.url})); + this.$modal.on('hidden.bs.modal', _.bind(this.destroy, this)); + this.$modal.find('.preview-maximize').on('click', _.bind(this.maximize, this)); + this.$modal.find('.preview-minimize').on('click', _.bind(this.minimize, this)); + }, + renderElement: function() { + this._super(); + var self = this; + this.generator.createPreview(this.url, this.mimetype, this.extension, this.title).then(function($content) { + self.setElement($("
").addClass("modal-body preview-body").append($content)); + }); + }, + open: function() { + var self = this; + $('.tooltip').remove(); + this.replace(this.$modal.find(".modal-body")).then(function() { + self.$modal.modal('show'); + self._opened.resolve(); + }); + return self; + }, + maximize: function(e) { + this.$modal.find('.preview-maximize').toggle(); + this.$modal.find('.preview-minimize').toggle(); + this.$modal.addClass("modal-fullscreen"); + + }, + minimize: function(e) { + this.$modal.find('.preview-maximize').toggle(); + this.$modal.find('.preview-minimize').toggle(); + this.$modal .removeClass("modal-fullscreen"); + }, + close: function() { + this.$modal.modal('hide'); + }, + destroy: function(reason) { + $('.tooltip').remove(); + if(this.isDestroyed()) { + return; + } + this.trigger("closed", reason); + this._super(); + this.$modal.modal('hide'); + this.$modal.remove(); + setTimeout(function () { + var modals = $('body > .modal').filter(':visible'); + if(modals.length) { + modals.last().focus(); + $('body').addClass('modal-open'); + } + }, 0); + } +}); + +PreviewDialog.createPreviewDialog = function (owner, url, mimetype, extension, title) { + return new PreviewDialog(owner, new PreviewGenerator(), url, mimetype, extension, title).open(); +}; + +return PreviewDialog; + +}); \ No newline at end of file diff --git a/muk_web_preview/static/src/js/preview_generator.js b/muk_web_preview/static/src/js/preview_generator.js new file mode 100644 index 0000000..c646ca7 --- /dev/null +++ b/muk_web_preview/static/src/js/preview_generator.js @@ -0,0 +1,92 @@ +/********************************************************************************** +* +* Copyright (C) 2017 MuK IT GmbH +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU Affero 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 Affero General Public License for more details. +* +* You should have received a copy of the GNU Affero General Public License +* along with this program. If not, see . +* +**********************************************************************************/ + +odoo.define('muk_preview.PreviewGenerator', function (require) { +"use strict"; + +var core = require('web.core'); + +var PreviewHandler = require('muk_preview.PreviewHandler'); + +var QWeb = core.qweb; +var _t = core._t; + +var PDFHandler = PreviewHandler.extend({ + checkExtension: function(extension) { + return ['.pdf', 'pdf'].includes(extension); + }, + checkType: function(mimetype) { + return ['application/pdf'].includes(mimetype); + }, + createHtml: function(url, mimetype, extension, title) { + var result = $.Deferred(); + var viewerUrlTempalte = _.template('/muk_web_preview/static/lib/ViewerJS/index.html#<%= url %>'); + result.resolve($(QWeb.render('ViewerJSFrame', {url: viewerUrlTempalte({url})}))); + return $.when(result); + }, +}); + +var OpenOfficeHandler = PreviewHandler.extend({ + checkExtension: function(extension) { + return ['.odt', '.odp', '.ods', '.fodt', '.ott', '.fodp', '.otp', '.fods', '.ots', + 'odt', 'odp', 'ods', 'fodt', 'ott', 'fodp', 'otp', 'fods', 'ots'].includes(extension); + }, + checkType: function(mimetype) { + return ['application/vnd.oasis.opendocument.text', 'application/vnd.oasis.opendocument.presentation', + 'application/vnd.oasis.opendocument.spreadsheet'].includes(mimetype); + }, + createHtml: function(url, mimetype, extension, title) { + var result = $.Deferred(); + var viewerUrlTempalte = _.template('/muk_web_preview/static/lib/ViewerJS/index.html#<%= url %>'); + result.resolve($(QWeb.render('ViewerJSFrame', {url: viewerUrlTempalte({url})}))); + return $.when(result); + }, +}); + +var PreviewGenerator = core.Class.extend({ + handler: { + "PDFHandler": new PDFHandler(), + "OpenOfficeHandler": new OpenOfficeHandler(), + }, + init: function(additional_handler) { + this.handler = _.extend(this.handler, additional_handler); + }, + createPreview: function(url, mimetype, extension, title) { + var matchedHandler = false; + _.each(this.handler, function(handler, key, handler_list) { + if(handler.checkType(mimetype) || handler.checkExtension(extension)) { + matchedHandler = handler; + } + }); + if(matchedHandler) { + return matchedHandler.createHtml(url, mimetype, extension, title); + } else { + return $.when($.Deferred().resolve($(QWeb.render('UnsupportedContent', + {url: url, mimetype: mimetype || _t('Unknown'), extension: extension || _t('Unknown'), title: title || _t('Unknown')})))); + } + } +}); + +PreviewGenerator.createPreview = function(url, mimetype, extension, title) { + return new PreviewGenerator({}).createPreview(url, mimetype, extension, title); +}; + +return PreviewGenerator; + +}); \ No newline at end of file diff --git a/muk_web_preview/static/src/js/preview_handler.js b/muk_web_preview/static/src/js/preview_handler.js new file mode 100644 index 0000000..83c2809 --- /dev/null +++ b/muk_web_preview/static/src/js/preview_handler.js @@ -0,0 +1,39 @@ +/********************************************************************************** +* +* Copyright (C) 2017 MuK IT GmbH +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU Affero 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 Affero General Public License for more details. +* +* You should have received a copy of the GNU Affero General Public License +* along with this program. If not, see . +* +**********************************************************************************/ + +odoo.define('muk_preview.PreviewHandler', function (require) { +"use strict"; + +var core = require('web.core'); + +var Handler = core.Class.extend({ + checkExtension: function(extension) { + return false; + }, + checkType: function(mimetype) { + return false; + }, + createHtml: function(url, mimetype, extension, title) { + $.when(); + }, +}); + +return Handler; + +}); \ No newline at end of file diff --git a/muk_web_preview/static/src/js/preview_widgets.js b/muk_web_preview/static/src/js/preview_widgets.js new file mode 100644 index 0000000..8a9543c --- /dev/null +++ b/muk_web_preview/static/src/js/preview_widgets.js @@ -0,0 +1,78 @@ +/********************************************************************************** +* +* Copyright (C) 2017 MuK IT GmbH +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU Affero 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 Affero General Public License for more details. +* +* You should have received a copy of the GNU Affero General Public License +* along with this program. If not, see . +* +**********************************************************************************/ + +odoo.define('muk_preview.PreviewWidgets', function (require) { +"use strict"; + +var core = require('web.core'); +var utils = require('web.utils'); +var Widget = require('web.Widget'); + +var PreviewHandler = require('muk_preview.PreviewHandler'); +var PreviewGenerator = require('muk_preview.PreviewGenerator'); +var PreviewDialog = require('muk_preview.PreviewDialog'); + +var QWeb = core.qweb; +var _t = core._t; + +core.form_widget_registry.get("binary").include({ + initialize_content: function() { + var self = this; + this._super(); + if (this.get("effective_readonly")) { + this.$('.o_binary_preview').click(function(e) { + e.stopPropagation(); + var value = self.get('value'); + var filename_fieldname = self.node.attrs.filename; + var filename_field = self.view.fields && self.view.fields[filename_fieldname]; + var filename = filename_field ? filename_field.get('value') : null; + PreviewDialog.createPreviewDialog(self, '/web/content?' + $.param({ + 'model': self.view.dataset.model, + 'id': self.view.datarecord.id, + 'field': self.name, + 'filename_field': filename_fieldname, + 'filename': filename, + 'download': true, + 'data': utils.is_bin_size(value) ? null : value, + }), false, filename.split('.').pop(), filename); + }); + } + }, + render_value: function() { + var filename = this.view.datarecord[this.node.attrs.filename]; + if (this.get("effective_readonly")) { + this.do_toggle(!!this.get('value')); + if (this.get('value')) { + var $link = this.$el.find('a') + $link.empty().append($("").addClass('fa fa-download')); + if (filename) { + $link.append(" " + filename); + } else { + $link.append(" " + _t("Download")); + } + } + } else { + this._super(); + } + } + +}); + + +}); \ No newline at end of file diff --git a/muk_web_preview/static/src/less/preview_content.less b/muk_web_preview/static/src/less/preview_content.less new file mode 100644 index 0000000..80e560e --- /dev/null +++ b/muk_web_preview/static/src/less/preview_content.less @@ -0,0 +1,57 @@ +/********************************************************************************** +* +* Copyright (C) 2017 MuK IT GmbH +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU Affero 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 Affero General Public License for more details. +* +* You should have received a copy of the GNU Affero General Public License +* along with this program. If not, see . +* +**********************************************************************************/ + +.o_preview_viewerjs , .o_preview_viewerjs iframe { + position: absolute; + width: 100%; + height: 100%; +} + +.o_preview_unsupported { + padding: 20px 30px 20px 30px; + + .o_preview_unsupported_body { + padding-top: 25px; + } + + .o_preview_unsupported_info { + padding-bottom: 15px; + } + + .o_preview_unsupported_icon { + padding-top: 15px; + } + + .o_preview_unsupported_table > tbody > tr { + border-top: 1px solid rgb(221, 221, 221); + } + + .o_preview_unsupported_table > tbody > tr:first-child { + border-top: 0; + } + + .o_preview_unsupported_table > tbody > tr > td { + border-top: 0; + } + + .o_preview_unsupported_download { + padding-top: 25px; + } +} + diff --git a/muk_web_preview/static/src/less/preview_dialog.less b/muk_web_preview/static/src/less/preview_dialog.less new file mode 100644 index 0000000..5b8c59d --- /dev/null +++ b/muk_web_preview/static/src/less/preview_dialog.less @@ -0,0 +1,134 @@ +/********************************************************************************** +* +* Copyright (C) 2017 MuK IT GmbH +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU Affero 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 Affero General Public License for more details. +* +* You should have received a copy of the GNU Affero General Public License +* along with this program. If not, see . +* +**********************************************************************************/ + +.preview-header { + padding: 10px; +} + +.preview-title { + font-size: 19px; +} + +.preview-dialog-btn { + float: right; + border: 0; + cursor: pointer; + background: transparent; + -webkit-appearance: none; +} + +a.preview-dialog-btn { + padding: 0 10px 0 10px; + font-size: 16px; + font-weight: bold; + color: #000000; + text-shadow: 0 1px 0 #ffffff; + opacity: 0.3; + filter: alpha(opacity=20); + + &:hover , &:focus { + opacity: 0.5; + filter: alpha(opacity=50); + } +} + +button.preview-dialog-btn { + font-size: 16px; + font-weight: bold; + color: #000000; + text-shadow: 0 1px 0 #ffffff; + opacity: 0.3; + filter: alpha(opacity=20); + + &:hover , &:focus { + opacity: 0.5; + filter: alpha(opacity=50); + } +} + +button.preview-close { + font-size: 18px; +} + +button.preview-maximize, +button.preview-minimize, +a.preview-download { + margin-top: 3px; +} + +button.preview-minimize { + display: none; +} + +.preview-body { + padding: 0; + min-height: 450px; +} + + +.modal.modal-fullscreen { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + overflow: hidden; + + .modal-dialog { + position: fixed; + margin: 0; + width: 100%; + height: 100%; + padding: 0; + } + + .modal-content { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + } + + .modal-header { + position: absolute; + top: 0; + right: 0; + left: 0; + height: 50px; + } + + .modal-body { + position: absolute; + top: 50px; + bottom: 60px; + width: 100%; + font-weight: 300; + overflow: auto; + } + + .modal-footer { + position: absolute; + right: 0; + bottom: 0; + left: 0; + height: 60px; + } +} + diff --git a/muk_web_preview/static/src/less/preview_widgets.less b/muk_web_preview/static/src/less/preview_widgets.less new file mode 100644 index 0000000..948d19f --- /dev/null +++ b/muk_web_preview/static/src/less/preview_widgets.less @@ -0,0 +1,34 @@ +/********************************************************************************** +* +* Copyright (C) 2017 MuK IT GmbH +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU Affero 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 Affero General Public License for more details. +* +* You should have received a copy of the GNU Affero General Public License +* along with this program. If not, see . +* +**********************************************************************************/ + +.o_binary_preview { + border: 0; + cursor: pointer; + padding: 0 2px 0 2px; + background: transparent; + -webkit-appearance: none; + opacity: 0.9; + filter: alpha(opacity=90); + + &:hover , &:focus { + opacity: 1; + filter: alpha(opacity=100); + } +} + diff --git a/muk_web_preview/static/src/xml/preview_content.xml b/muk_web_preview/static/src/xml/preview_content.xml new file mode 100644 index 0000000..61a00d9 --- /dev/null +++ b/muk_web_preview/static/src/xml/preview_content.xml @@ -0,0 +1,66 @@ + + + + + +
+ +
+ +
+
+

Unsupported File Extension

+
+
+ +
+
+
+
+ + + + + + + + + + + + + + + +
Filename:
Type:
Extension:
+
+
+ Download +
+
+
+ \ No newline at end of file diff --git a/muk_web_preview/static/src/xml/preview_dialog.xml b/muk_web_preview/static/src/xml/preview_dialog.xml new file mode 100644 index 0000000..5f514dd --- /dev/null +++ b/muk_web_preview/static/src/xml/preview_dialog.xml @@ -0,0 +1,39 @@ + + + + + + + \ No newline at end of file diff --git a/muk_web_preview/static/src/xml/preview_widgets.xml b/muk_web_preview/static/src/xml/preview_widgets.xml new file mode 100644 index 0000000..5d9ba14 --- /dev/null +++ b/muk_web_preview/static/src/xml/preview_widgets.xml @@ -0,0 +1,29 @@ + + + + + + + +
+ + +
+
+
+
\ No newline at end of file diff --git a/muk_web_preview/template/assets.xml b/muk_web_preview/template/assets.xml new file mode 100644 index 0000000..957e03e --- /dev/null +++ b/muk_web_preview/template/assets.xml @@ -0,0 +1,32 @@ + + + + + +