diff --git a/attachment_preview/static/lib/ViewerJS/AGPL-3.0.txt b/attachment_preview/static/lib/ViewerJS/AGPL-3.0.txt
deleted file mode 100644
index dba13ed2..00000000
--- a/attachment_preview/static/lib/ViewerJS/AGPL-3.0.txt
+++ /dev/null
@@ -1,661 +0,0 @@
- 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
-
- How to Apply These Terms to Your New Programs
-
- If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
- To do so, attach the following notices to the program. It is safest
-to attach them to the start of each source file to most effectively
-state the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-
- Copyright (C)
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU 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 .
-
-Also add information on how to contact you by electronic and paper mail.
-
- If your software can interact with users remotely through a computer
-network, you should also make sure that it provides a way for users to
-get its source. For example, if your program is a web application, its
-interface could display a "Source" link that leads users to an archive
-of the code. There are many ways you could offer source, and different
-solutions will be better for different programs; see section 13 for the
-specific requirements.
-
- You should also get your employer (if you work as a programmer) or school,
-if any, to sign a "copyright disclaimer" for the program, if necessary.
-For more information on this, and how to apply and follow the GNU AGPL, see
-.
diff --git a/attachment_preview/static/lib/ViewerJS/ODFViewerPlugin.css b/attachment_preview/static/lib/ViewerJS/ODFViewerPlugin.css
deleted file mode 100644
index 90f0dbe1..00000000
--- a/attachment_preview/static/lib/ViewerJS/ODFViewerPlugin.css
+++ /dev/null
@@ -1,29 +0,0 @@
-/**
- * Copyright (C) 2013-2014 KO GmbH
- *
- * @licstart
- * This file is part of WebODF.
- *
- * WebODF 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.
- *
- * WebODF is distributed in the hope that 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 .
- * @licend
- *
- * @source: http://www.webodf.org/
- * @source: https://github.com/kogmbh/WebODF/
- */
-
-@namespace cursor url(urn:webodf:names:cursor);
-
-.caret {
- opacity: 0 !important;
-}
diff --git a/attachment_preview/static/lib/ViewerJS/ODFViewerPlugin.js b/attachment_preview/static/lib/ViewerJS/ODFViewerPlugin.js
deleted file mode 100644
index c2ddae36..00000000
--- a/attachment_preview/static/lib/ViewerJS/ODFViewerPlugin.js
+++ /dev/null
@@ -1,219 +0,0 @@
-/**
- * Copyright (C) 2012 KO GmbH
- *
- * @licstart
- * This file is part of WebODF.
- *
- * WebODF 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.
- *
- * WebODF is distributed in the hope that 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 .
- * @licend
- *
- * @source: http://www.webodf.org/
- * @source: https://github.com/kogmbh/WebODF/
- */
-
-/*global runtime, document, odf, gui, console, webodf*/
-
-function ODFViewerPlugin() {
- "use strict";
-
- function init(callback) {
- var lib = document.createElement('script'),
- pluginCSS;
-
- lib.async = false;
- lib.src = './webodf.js';
- lib.type = 'text/javascript';
- lib.onload = function () {
- runtime.loadClass('gui.HyperlinkClickHandler');
- runtime.loadClass('odf.OdfCanvas');
- runtime.loadClass('ops.Session');
- runtime.loadClass('gui.CaretManager');
- runtime.loadClass("gui.HyperlinkTooltipView");
- runtime.loadClass('gui.SessionController');
- runtime.loadClass('gui.SvgSelectionView');
- runtime.loadClass('gui.SelectionViewManager');
- runtime.loadClass('gui.ShadowCursor');
- runtime.loadClass('gui.SessionView');
-
- callback();
- };
-
- document.getElementsByTagName('head')[0].appendChild(lib);
-
- pluginCSS = document.createElement('link');
- pluginCSS.setAttribute("rel", "stylesheet");
- pluginCSS.setAttribute("type", "text/css");
- pluginCSS.setAttribute("href", "./ODFViewerPlugin.css");
- document.head.appendChild(pluginCSS);
- }
-
- // that should probably be provided by webodf
- function nsResolver(prefix) {
- var ns = {
- 'draw' : "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0",
- 'presentation' : "urn:oasis:names:tc:opendocument:xmlns:presentation:1.0",
- 'text' : "urn:oasis:names:tc:opendocument:xmlns:text:1.0",
- 'office' : "urn:oasis:names:tc:opendocument:xmlns:office:1.0"
- };
- return ns[prefix] || console.log('prefix [' + prefix + '] unknown.');
- }
-
- var self = this,
- pluginName = "WebODF",
- pluginURL = "http://webodf.org",
- odfCanvas = null,
- odfElement = null,
- initialized = false,
- root = null,
- documentType = null,
- pages = [],
- currentPage = null;
-
- this.initialize = function (viewerElement, documentUrl) {
- // If the URL has a fragment (#...), try to load the file it represents
- init(function () {
- var session,
- sessionController,
- sessionView,
- odtDocument,
- shadowCursor,
- selectionViewManager,
- caretManager,
- localMemberId = 'localuser',
- hyperlinkTooltipView,
- eventManager;
-
- odfElement = document.getElementById('canvas');
- odfCanvas = new odf.OdfCanvas(odfElement);
- odfCanvas.load(documentUrl);
-
- odfCanvas.addListener('statereadychange', function () {
- root = odfCanvas.odfContainer().rootElement;
- initialized = true;
- documentType = odfCanvas.odfContainer().getDocumentType(root);
- if (documentType === 'text') {
- odfCanvas.enableAnnotations(true, false);
-
- session = new ops.Session(odfCanvas);
- odtDocument = session.getOdtDocument();
- shadowCursor = new gui.ShadowCursor(odtDocument);
- sessionController = new gui.SessionController(session, localMemberId, shadowCursor, {});
- eventManager = sessionController.getEventManager();
- caretManager = new gui.CaretManager(sessionController, odfCanvas.getViewport());
- selectionViewManager = new gui.SelectionViewManager(gui.SvgSelectionView);
- sessionView = new gui.SessionView({
- caretAvatarsInitiallyVisible: false
- }, localMemberId, session, sessionController.getSessionConstraints(), caretManager, selectionViewManager);
- selectionViewManager.registerCursor(shadowCursor);
- hyperlinkTooltipView = new gui.HyperlinkTooltipView(odfCanvas,
- sessionController.getHyperlinkClickHandler().getModifier);
- eventManager.subscribe("mousemove", hyperlinkTooltipView.showTooltip);
- eventManager.subscribe("mouseout", hyperlinkTooltipView.hideTooltip);
-
- var op = new ops.OpAddMember();
- op.init({
- memberid: localMemberId,
- setProperties: {
- fillName: runtime.tr("Unknown Author"),
- color: "blue"
- }
- });
- session.enqueue([op]);
- sessionController.insertLocalCursor();
- }
-
- self.onLoad();
- });
- });
- };
-
- this.isSlideshow = function () {
- return documentType === 'presentation';
- };
-
- this.onLoad = function () {};
-
- this.getWidth = function () {
- return odfElement.clientWidth;
- };
-
- this.getHeight = function () {
- return odfElement.clientHeight;
- };
-
- this.fitToWidth = function (width) {
- odfCanvas.fitToWidth(width);
- };
-
- this.fitToHeight = function (height) {
- odfCanvas.fitToHeight(height);
- };
-
- this.fitToPage = function (width, height) {
- odfCanvas.fitToContainingElement(width, height);
- };
-
- this.fitSmart = function (width) {
- odfCanvas.fitSmart(width);
- };
-
- this.getZoomLevel = function () {
- return odfCanvas.getZoomLevel();
- };
-
- this.setZoomLevel = function (value) {
- odfCanvas.setZoomLevel(value);
- };
-
- // return a list of tuples (pagename, pagenode)
- this.getPages = function () {
- var pageNodes = Array.prototype.slice.call(root.getElementsByTagNameNS(nsResolver('draw'), 'page')),
- pages = [],
- i,
- tuple;
-
- for (i = 0; i < pageNodes.length; i += 1) {
- tuple = [
- pageNodes[i].getAttribute('draw:name'),
- pageNodes[i]
- ];
- pages.push(tuple);
- }
- return pages;
- };
-
- this.showPage = function (n) {
- odfCanvas.showPage(n);
- };
-
- this.getPluginName = function () {
- return pluginName;
- };
-
- this.getPluginVersion = function () {
- var version;
-
- if (String(typeof webodf) !== "undefined") {
- version = webodf.Version;
- } else {
- version = "Unknown";
- }
-
- return version;
- };
-
- this.getPluginURL = function () {
- return pluginURL;
- };
-}
diff --git a/attachment_preview/static/lib/ViewerJS/PDFViewerPlugin.css b/attachment_preview/static/lib/ViewerJS/PDFViewerPlugin.css
deleted file mode 100644
index d1012783..00000000
--- a/attachment_preview/static/lib/ViewerJS/PDFViewerPlugin.css
+++ /dev/null
@@ -1,36 +0,0 @@
-.page {
- margin: 7px auto 7px auto;
- position: relative;
- overflow: hidden;
- background-clip: content-box;
- background-color: white;
-
- box-shadow: 0px 0px 7px rgba(0, 0, 0, 0.75);
- -webkit-box-shadow: 0px 0px 7px rgba(0, 0, 0, 0.75);
- -moz-box-shadow: 0px 0px 7px rgba(0, 0, 0, 0.75);
- -ms-box-shadow: 0px 0px 7px rgba(0, 0, 0, 0.75);
- -o-box-shadow: 0px 0px 7px rgba(0, 0, 0, 0.75);
-}
-
-.textLayer {
- position: absolute;
- left: 0;
- top: 0;
- right: 0;
- bottom: 0;
- color: #000;
- font-family: sans-serif;
- overflow: hidden;
-}
-
-.textLayer > div {
- color: transparent;
- position: absolute;
- line-height: 1;
- white-space: pre;
- cursor: text;
-}
-
-::selection { background:rgba(0,0,255,0.3); }
-::-moz-selection { background:rgba(0,0,255,0.3); }
-
diff --git a/attachment_preview/static/lib/ViewerJS/PDFViewerPlugin.js b/attachment_preview/static/lib/ViewerJS/PDFViewerPlugin.js
deleted file mode 100644
index 541447d8..00000000
--- a/attachment_preview/static/lib/ViewerJS/PDFViewerPlugin.js
+++ /dev/null
@@ -1,364 +0,0 @@
-/**
- * @license
- * Copyright (C) 2013-2014 KO GmbH
- *
- * @licstart
- * The JavaScript code in this page 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 is distributed
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this code. If not, see .
- *
- * As additional permission under GNU AGPL version 3 section 7, you
- * may distribute non-source (e.g., minimized or compacted) forms of
- * that code without the copy of the GNU GPL 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 by reference 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://viewerjs.org/
- * @source: http://github.com/kogmbh/ViewerJS
- */
-
-/*global document, PDFJS, console, TextLayerBuilder*/
-
-
-function PDFViewerPlugin() {
- "use strict";
-
- function loadScript(path, callback) {
- var script = document.createElement('script');
- script.async = false;
- script.src = path;
- script.type = 'text/javascript';
- script.onload = callback || script.onload;
- document.getElementsByTagName('head')[0].appendChild(script);
- }
-
- function init(callback) {
- var pdfLib, textLayerLib, pluginCSS;
-
- loadScript('./compatibility.js', function () {
- loadScript('./pdf.js');
- loadScript('./pdf_find_bar.js');
- loadScript('./pdf_find_controller.js');
- loadScript('./ui_utils.js');
- loadScript('./text_layer_builder.js');
- loadScript('./pdfjsversion.js', callback);
- });
-
- pluginCSS = document.createElement('link');
- pluginCSS.setAttribute("rel", "stylesheet");
- pluginCSS.setAttribute("type", "text/css");
- pluginCSS.setAttribute("href", "./PDFViewerPlugin.css");
- document.head.appendChild(pluginCSS);
- }
-
- var self = this,
- pages = [],
- domPages = [],
- pageText = [],
- renderingStates = [],
- RENDERING = {
- BLANK: 0,
- RUNNING: 1,
- FINISHED: 2
- },
- startedTextExtraction = false,
- container = null,
- initialized = false,
- pdfDocument = null,
- pageViewScroll = null,
- isPresentationMode = false,
- scale = 1,
- currentPage = 1,
- pageWidth,
- pageHeight,
- createdPageCount = 0;
-
- function scrollIntoView(elem) {
- elem.parentNode.scrollTop = elem.offsetTop;
- }
-
- function isScrolledIntoView(elem) {
- var docViewTop = container.scrollTop,
- docViewBottom = docViewTop + container.clientHeight,
- elemTop = elem.offsetTop,
- elemBottom = elemTop + elem.clientHeight;
-
- // Is in view if either the top or the bottom of the page is between the
- // document viewport bounds,
- // or if the top is above the viewport and the bottom is below it.
- return (elemTop >= docViewTop && elemTop < docViewBottom)
- || (elemBottom >= docViewTop && elemBottom < docViewBottom)
- || (elemTop < docViewTop && elemBottom >= docViewBottom);
- }
-
- function getDomPage(page) {
- return domPages[page.pageInfo.pageIndex];
- }
- function getPageText(page) {
- return pageText[page.pageInfo.pageIndex];
- }
- function getRenderingStatus(page) {
- return renderingStates[page.pageInfo.pageIndex];
- }
- function setRenderingStatus(page, renderStatus) {
- renderingStates[page.pageInfo.pageIndex] = renderStatus;
- }
-
- function updatePageDimensions(page, width, height) {
- var domPage = getDomPage(page),
- canvas = domPage.getElementsByTagName('canvas')[0],
- textLayer = domPage.getElementsByTagName('div')[0],
- cssScale = 'scale(' + scale + ', ' + scale + ')';
-
- domPage.style.width = width + "px";
- domPage.style.height = height + "px";
-
- canvas.width = width;
- canvas.height = height;
-
- textLayer.style.width = width + "px";
- textLayer.style.height = height + "px";
-
- CustomStyle.setProp('transform', textLayer, cssScale);
- CustomStyle.setProp('transformOrigin', textLayer, '0% 0%');
-
- // Once the page dimension is updated, the rendering state is blank.
- setRenderingStatus(page, RENDERING.BLANK);
- }
-
- function renderPage(page) {
- var domPage = getDomPage(page),
- textLayer = getPageText(page),
- canvas = domPage.getElementsByTagName('canvas')[0];
-
- if (getRenderingStatus(page) === RENDERING.BLANK) {
- setRenderingStatus(page, RENDERING.RUNNING);
- page.render({
- canvasContext: canvas.getContext('2d'),
- textLayer: textLayer,
- viewport: page.getViewport(scale)
- }).promise.then(function () {
- setRenderingStatus(page, RENDERING.FINISHED);
- });
- }
- }
-
- function createPage(page) {
- var pageNumber,
- textLayerDiv,
- textLayer,
- canvas,
- domPage,
- viewport;
-
- pageNumber = page.pageInfo.pageIndex + 1;
-
- viewport = page.getViewport(scale);
-
- domPage = document.createElement('div');
- domPage.id = 'pageContainer' + pageNumber;
- domPage.className = 'page';
-
- canvas = document.createElement('canvas');
- canvas.id = 'canvas' + pageNumber;
-
- textLayerDiv = document.createElement('div');
- textLayerDiv.className = 'textLayer';
- textLayerDiv.id = 'textLayer' + pageNumber;
-
- container.appendChild(domPage);
- domPage.appendChild(canvas);
- domPage.appendChild(textLayerDiv);
-
- pages.push(page);
- domPages.push(domPage);
- renderingStates.push(RENDERING.BLANK);
-
- updatePageDimensions(page, viewport.width, viewport.height);
- pageWidth = viewport.width;
- pageHeight = viewport.height;
-
- textLayer = new TextLayerBuilder({
- textLayerDiv: textLayerDiv,
- pageIndex: pageNumber - 1
- });
- page.getTextContent().then(function (textContent) {
- textLayer.setTextContent(textContent);
- });
- pageText.push(textLayer);
-
- createdPageCount += 1;
- if (createdPageCount === (pdfDocument.numPages)) {
- if (self.isSlideshow()) {
- domPages.forEach(function (pageElement) {
- pageElement.style.display = "none";
- });
- self.showPage(1);
- }
- self.onLoad();
- }
- }
-
- this.initialize = function (viewContainer, location) {
- var self = this,
- i,
- pluginCSS;
-
- init(function () {
- PDFJS.workerSrc = "./pdf.worker.js";
- PDFJS.getDocument(location).then(function loadPDF(doc) {
- pdfDocument = doc;
- container = viewContainer;
-
- for (i = 0; i < pdfDocument.numPages; i += 1) {
- pdfDocument.getPage(i + 1).then(createPage);
- }
-
- initialized = true;
- });
- });
- };
-
- this.isSlideshow = function () {
- // A very simple but generally true guess - if the width is greater than the height, treat it as a slideshow
- return pageWidth > pageHeight;
- };
-
- this.onLoad = function () {};
-
- this.getPages = function () {
- return domPages;
- };
-
- this.getWidth = function () {
- return pageWidth;
- };
-
- this.getHeight = function () {
- return pageHeight;
- };
-
- this.fitToWidth = function (width) {
- var zoomLevel;
-
- if (self.getWidth() === width) {
- return;
- }
- zoomLevel = width / pageWidth;
- self.setZoomLevel(zoomLevel);
- };
-
- this.fitToHeight = function (height) {
- var zoomLevel;
-
- if (self.getHeight() === height) {
- return;
- }
- zoomLevel = height / pageHeight;
- self.setZoomLevel(zoomLevel);
- };
-
- this.fitToPage = function (width, height) {
- var zoomLevel = width / pageWidth;
- if (height / pageHeight < zoomLevel) {
- zoomLevel = height / pageHeight;
- }
- self.setZoomLevel(zoomLevel);
- };
-
- this.fitSmart = function (width, height) {
- var zoomLevel = width / pageWidth;
- if (height && (height / pageHeight) < zoomLevel) {
- zoomLevel = height / pageHeight;
- }
- zoomLevel = Math.min(1.0, zoomLevel);
- self.setZoomLevel(zoomLevel);
- };
-
- this.setZoomLevel = function (zoomLevel) {
- var i;
-
- if (scale !== zoomLevel) {
- scale = zoomLevel;
-
- for (i = 0; i < pages.length; i += 1) {
- updatePageDimensions(pages[i], pageWidth * scale, pageHeight * scale);
- }
- }
- };
-
- this.getZoomLevel = function () {
- return scale;
- };
-
- this.onScroll = function () {
- var i;
-
- for (i = 0; i < domPages.length; i += 1) {
- if (isScrolledIntoView(domPages[i])) {
- if (getRenderingStatus(pages[i]) === RENDERING.BLANK) {
- renderPage(pages[i]);
- }
- }
- }
- };
-
- this.getPageInView = function () {
- var i;
-
- if (self.isSlideshow()) {
- return currentPage;
- } else {
- for (i = 0; i < domPages.length; i += 1) {
- if (isScrolledIntoView(domPages[i])) {
- return i + 1;
- }
- }
- }
- };
-
- this.showPage = function (n) {
- if (self.isSlideshow()) {
- domPages[currentPage - 1].style.display = "none";
- currentPage = n;
- domPages[n - 1].style.display = "block";
- } else {
- scrollIntoView(domPages[n - 1]);
- }
- };
-
- this.getPluginName = function () {
- return "PDF.js"
- };
-
- this.getPluginVersion = function () {
- var version = (String(typeof pdfjs_version) !== "undefined"
- ? pdfjs_version
- : "From Source"
- );
- return version;
- };
-
- this.getPluginURL = function () {
- return "https://github.com/mozilla/pdf.js/";
- };
-}
diff --git a/attachment_preview/static/lib/ViewerJS/PluginLoader.js b/attachment_preview/static/lib/ViewerJS/PluginLoader.js
deleted file mode 100644
index e99e1e58..00000000
--- a/attachment_preview/static/lib/ViewerJS/PluginLoader.js
+++ /dev/null
@@ -1,91 +0,0 @@
-/**
- * @license
- * Copyright (C) 2012 KO GmbH
- *
- * @licstart
- * The JavaScript code in this page 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 is distributed
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this code. If not, see .
- *
- * As additional permission under GNU AGPL version 3 section 7, you
- * may distribute non-source (e.g., minimized or compacted) forms of
- * that code without the copy of the GNU GPL 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 by reference 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://viewerjs.org/
- * @source: http://github.com/kogmbh/ViewerJS
- */
-
-/*global document, window, Viewer, ODFViewerPlugin, PDFViewerPlugin*/
-
-var viewer;
-
-function loadPlugin(pluginName, callback) {
- "use strict";
- var script, style;
-
- // Load script
- script = document.createElement('script');
- script.async = false;
- script.onload = callback;
- script.src = pluginName + '.js';
- script.type = 'text/javascript';
- document.getElementsByTagName('head')[0].appendChild(script);
-}
-
-function loadDocument(documentUrl) {
- "use strict";
-
- if (documentUrl) {
- var extension = documentUrl.split('.').pop(),
- Plugin;
- extension = extension.toLowerCase();
-
- switch (extension) {
- case 'odt':
- case 'fodt':
- case 'ott':
- case 'odp':
- case 'fodp':
- case 'otp':
- case 'ods':
- case 'fods':
- case 'ots':
- loadPlugin('./ODFViewerPlugin', function () {
- Plugin = ODFViewerPlugin;
- });
- break;
- case 'pdf':
- loadPlugin('./PDFViewerPlugin', function () {
- Plugin = PDFViewerPlugin;
- });
- break;
- }
-
- window.onload = function () {
- if (Plugin) {
- viewer = new Viewer(new Plugin());
- }
- };
- }
-}
diff --git a/attachment_preview/static/lib/ViewerJS/compatibility.js b/attachment_preview/static/lib/ViewerJS/compatibility.js
index 433e617a..967e312a 100644
--- a/attachment_preview/static/lib/ViewerJS/compatibility.js
+++ b/attachment_preview/static/lib/ViewerJS/compatibility.js
@@ -25,9 +25,10 @@ if (typeof PDFJS === 'undefined') {
}
// Checking if the typed arrays are supported
+// Support: iOS<6.0 (subarray), IE<10, Android<4.0
(function checkTypedArrayCompatibility() {
if (typeof Uint8Array !== 'undefined') {
- // some mobile versions do not support subarray (e.g. safari 5 / iOS)
+ // Support: iOS<6.0
if (typeof Uint8Array.prototype.subarray === 'undefined') {
Uint8Array.prototype.subarray = function subarray(start, end) {
return new Uint8Array(this.slice(start, end));
@@ -37,10 +38,10 @@ if (typeof PDFJS === 'undefined') {
};
}
- // some mobile version might not support Float64Array
- if (typeof Float64Array === 'undefined')
+ // Support: Android<4.1
+ if (typeof Float64Array === 'undefined') {
window.Float64Array = Float32Array;
-
+ }
return;
}
@@ -49,23 +50,26 @@ if (typeof PDFJS === 'undefined') {
}
function setArrayOffset(array, offset) {
- if (arguments.length < 2)
+ if (arguments.length < 2) {
offset = 0;
- for (var i = 0, n = array.length; i < n; ++i, ++offset)
+ }
+ for (var i = 0, n = array.length; i < n; ++i, ++offset) {
this[offset] = array[i] & 0xFF;
+ }
}
function TypedArray(arg1) {
- var result;
+ var result, i, n;
if (typeof arg1 === 'number') {
result = [];
- for (var i = 0; i < arg1; ++i)
+ for (i = 0; i < arg1; ++i) {
result[i] = 0;
+ }
} else if ('slice' in arg1) {
result = arg1.slice(0);
} else {
result = [];
- for (var i = 0, n = arg1.length; i < n; ++i) {
+ for (i = 0, n = arg1.length; i < n; ++i) {
result[i] = arg1[i];
}
}
@@ -75,13 +79,14 @@ if (typeof PDFJS === 'undefined') {
result.byteLength = result.length;
result.set = setArrayOffset;
- if (typeof arg1 === 'object' && arg1.buffer)
+ if (typeof arg1 === 'object' && arg1.buffer) {
result.buffer = arg1.buffer;
-
+ }
return result;
}
window.Uint8Array = TypedArray;
+ window.Int8Array = TypedArray;
// we don't need support for set, byteLength for 32-bit array
// so we can use the TypedArray as well
@@ -93,25 +98,15 @@ if (typeof PDFJS === 'undefined') {
})();
// URL = URL || webkitURL
+// Support: Safari<7, Android 4.2+
(function normalizeURLObject() {
if (!window.URL) {
window.URL = window.webkitURL;
}
})();
-// Object.create() ?
-(function checkObjectCreateCompatibility() {
- if (typeof Object.create !== 'undefined')
- return;
-
- Object.create = function objectCreate(proto) {
- function Constructor() {}
- Constructor.prototype = proto;
- return new Constructor();
- };
-})();
-
-// Object.defineProperty() ?
+// Object.defineProperty()?
+// Support: Android<4.0, Safari<5.1
(function checkObjectDefinePropertyCompatibility() {
if (typeof Object.defineProperty !== 'undefined') {
var definePropertyPossible = true;
@@ -127,15 +122,19 @@ if (typeof PDFJS === 'undefined') {
} catch (e) {
definePropertyPossible = false;
}
- if (definePropertyPossible) return;
+ if (definePropertyPossible) {
+ return;
+ }
}
Object.defineProperty = function objectDefineProperty(obj, name, def) {
delete obj[name];
- if ('get' in def)
+ if ('get' in def) {
obj.__defineGetter__(name, def['get']);
- if ('set' in def)
+ }
+ if ('set' in def) {
obj.__defineSetter__(name, def['set']);
+ }
if ('value' in def) {
obj.__defineSetter__(name, function objectDefinePropertySetter(value) {
this.__defineGetter__(name, function objectDefinePropertyGetter() {
@@ -148,105 +147,77 @@ if (typeof PDFJS === 'undefined') {
};
})();
-// Object.keys() ?
-(function checkObjectKeysCompatibility() {
- if (typeof Object.keys !== 'undefined')
- return;
- Object.keys = function objectKeys(obj) {
- var result = [];
- for (var i in obj) {
- if (obj.hasOwnProperty(i))
- result.push(i);
- }
- return result;
- };
-})();
-
-// No readAsArrayBuffer ?
-(function checkFileReaderReadAsArrayBuffer() {
- if (typeof FileReader === 'undefined')
- return; // FileReader is not implemented
- var frPrototype = FileReader.prototype;
- // Older versions of Firefox might not have readAsArrayBuffer
- if ('readAsArrayBuffer' in frPrototype)
- return; // readAsArrayBuffer is implemented
- Object.defineProperty(frPrototype, 'readAsArrayBuffer', {
- value: function fileReaderReadAsArrayBuffer(blob) {
- var fileReader = new FileReader();
- var originalReader = this;
- fileReader.onload = function fileReaderOnload(evt) {
- var data = evt.target.result;
- var buffer = new ArrayBuffer(data.length);
- var uint8Array = new Uint8Array(buffer);
-
- for (var i = 0, ii = data.length; i < ii; i++)
- uint8Array[i] = data.charCodeAt(i);
-
- Object.defineProperty(originalReader, 'result', {
- value: buffer,
- enumerable: true,
- writable: false,
- configurable: true
- });
-
- var event = document.createEvent('HTMLEvents');
- event.initEvent('load', false, false);
- originalReader.dispatchEvent(event);
- };
- fileReader.readAsBinaryString(blob);
- }
- });
-})();
-
-// No XMLHttpRequest.response ?
+// No XMLHttpRequest#response?
+// Support: IE<11, Android <4.0
(function checkXMLHttpRequestResponseCompatibility() {
var xhrPrototype = XMLHttpRequest.prototype;
- if (!('overrideMimeType' in xhrPrototype)) {
+ var xhr = new XMLHttpRequest();
+ if (!('overrideMimeType' in xhr)) {
// IE10 might have response, but not overrideMimeType
+ // Support: IE10
Object.defineProperty(xhrPrototype, 'overrideMimeType', {
value: function xmlHttpRequestOverrideMimeType(mimeType) {}
});
}
- if ('response' in xhrPrototype ||
- 'mozResponseArrayBuffer' in xhrPrototype ||
- 'mozResponse' in xhrPrototype ||
- 'responseArrayBuffer' in xhrPrototype)
+ if ('responseType' in xhr) {
return;
- // IE9 ?
+ }
+
+ // The worker will be using XHR, so we can save time and disable worker.
+ PDFJS.disableWorker = true;
+
+ Object.defineProperty(xhrPrototype, 'responseType', {
+ get: function xmlHttpRequestGetResponseType() {
+ return this._responseType || 'text';
+ },
+ set: function xmlHttpRequestSetResponseType(value) {
+ if (value === 'text' || value === 'arraybuffer') {
+ this._responseType = value;
+ if (value === 'arraybuffer' &&
+ typeof this.overrideMimeType === 'function') {
+ this.overrideMimeType('text/plain; charset=x-user-defined');
+ }
+ }
+ }
+ });
+
+ // Support: IE9
if (typeof VBArray !== 'undefined') {
Object.defineProperty(xhrPrototype, 'response', {
get: function xmlHttpRequestResponseGet() {
- return new Uint8Array(new VBArray(this.responseBody).toArray());
+ if (this.responseType === 'arraybuffer') {
+ return new Uint8Array(new VBArray(this.responseBody).toArray());
+ } else {
+ return this.responseText;
+ }
}
});
return;
}
- // other browsers
- function responseTypeSetter() {
- // will be only called to set "arraybuffer"
- this.overrideMimeType('text/plain; charset=x-user-defined');
- }
- if (typeof xhrPrototype.overrideMimeType === 'function') {
- Object.defineProperty(xhrPrototype, 'responseType',
- { set: responseTypeSetter });
- }
- function responseGetter() {
- var text = this.responseText;
- var i, n = text.length;
- var result = new Uint8Array(n);
- for (i = 0; i < n; ++i)
- result[i] = text.charCodeAt(i) & 0xFF;
- return result;
- }
- Object.defineProperty(xhrPrototype, 'response', { get: responseGetter });
+ Object.defineProperty(xhrPrototype, 'response', {
+ get: function xmlHttpRequestResponseGet() {
+ if (this.responseType !== 'arraybuffer') {
+ return this.responseText;
+ }
+ var text = this.responseText;
+ var i, n = text.length;
+ var result = new Uint8Array(n);
+ for (i = 0; i < n; ++i) {
+ result[i] = text.charCodeAt(i) & 0xFF;
+ }
+ return result.buffer;
+ }
+ });
})();
// window.btoa (base64 encode function) ?
+// Support: IE<10
(function checkWindowBtoaCompatibility() {
- if ('btoa' in window)
+ if ('btoa' in window) {
return;
+ }
var digits =
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
@@ -268,17 +239,21 @@ if (typeof PDFJS === 'undefined') {
};
})();
-// window.atob (base64 encode function) ?
+// window.atob (base64 encode function)?
+// Support: IE<10
(function checkWindowAtobCompatibility() {
- if ('atob' in window)
+ 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');
+ if (input.length % 4 === 1) {
+ throw new Error('bad atob input');
+ }
for (
// initialize result and counters
var bc = 0, bs, buffer, idx = 0, output = '';
@@ -298,15 +273,17 @@ if (typeof PDFJS === 'undefined') {
};
})();
-// Function.prototype.bind ?
+// Function.prototype.bind?
+// Support: Android<4.0, iOS<6.0
(function checkFunctionPrototypeBindCompatibility() {
- if (typeof Function.prototype.bind !== 'undefined')
+ 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 = Array.prototype.concat.apply(headArgs, arguments);
+ var args = headArgs.concat(Array.prototype.slice.call(arguments));
return fn.apply(obj, args);
};
return bound;
@@ -314,23 +291,29 @@ if (typeof PDFJS === 'undefined') {
})();
// HTMLElement dataset property
+// Support: IE<11, Safari<5.1, Android<4.0
(function checkDatasetProperty() {
var div = document.createElement('div');
- if ('dataset' in div)
+ if ('dataset' in div) {
return; // dataset property exists
+ }
Object.defineProperty(HTMLElement.prototype, 'dataset', {
get: function() {
- if (this._dataset)
+ 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-')
+ if (attribute.name.substring(0, 5) !== 'data-') {
continue;
+ }
var key = attribute.name.substring(5).replace(/\-([a-z])/g,
- function(all, ch) { return ch.toUpperCase(); });
+ function(all, ch) {
+ return ch.toUpperCase();
+ });
dataset[key] = attribute.value;
}
@@ -346,20 +329,26 @@ if (typeof PDFJS === 'undefined') {
})();
// HTMLElement classList property
+// Support: IE<10, Android<4.0, iOS<5.0
(function checkClassListProperty() {
var div = document.createElement('div');
- if ('classList' in 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();
+ if (list[0] === '') {
+ list.shift();
+ }
var index = list.indexOf(itemName);
- if (index < 0 && add)
+ if (index < 0 && add) {
list.push(itemName);
- if (index >= 0 && remove)
+ }
+ if (index >= 0 && remove) {
list.splice(index, 1);
+ }
element.className = list.join(' ');
return (index >= 0);
}
@@ -381,8 +370,9 @@ if (typeof PDFJS === 'undefined') {
Object.defineProperty(HTMLElement.prototype, 'classList', {
get: function() {
- if (this._classList)
+ if (this._classList) {
return this._classList;
+ }
var classList = Object.create(classListPrototype, {
element: {
@@ -403,6 +393,9 @@ if (typeof PDFJS === 'undefined') {
})();
// 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 = {
@@ -425,6 +418,7 @@ if (typeof PDFJS === 'undefined') {
})();
// 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
@@ -436,13 +430,14 @@ if (typeof PDFJS === 'undefined') {
function isDisabled(node) {
return node.disabled || (node.parentNode && isDisabled(node.parentNode));
}
- if (navigator.userAgent.indexOf('Opera') != -1) {
+ 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) {
@@ -452,22 +447,27 @@ if (typeof PDFJS === 'undefined') {
// Checks if navigator.language is supported
(function checkNavigatorLanguage() {
- if ('language' in navigator)
+ if ('language' in navigator &&
+ /^[a-z]+(-[A-Z]+)?$/.test(navigator.language)) {
return;
- Object.defineProperty(navigator, 'language', {
- get: function navigatorLanguage() {
- var language = navigator.userLanguage || 'en-US';
- return language.substring(0, 2).toLowerCase() +
- language.substring(2).toUpperCase();
- },
- enumerable: true
- });
+ }
+ function formatLocale(locale) {
+ var split = locale.split(/[-_]/);
+ split[0] = split[0].toLowerCase();
+ if (split.length > 1) {
+ split[1] = split[1].toUpperCase();
+ }
+ return split.join('-');
+ }
+ var language = navigator.language || navigator.userLanguage || 'en-US';
+ PDFJS.locale = formatLocale(language);
})();
(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;
@@ -475,17 +475,100 @@ if (typeof PDFJS === 'undefined') {
// 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);
if (isSafari || isOldAndroid) {
PDFJS.disableRange = true;
+ PDFJS.disableStream = true;
}
})();
// Check if the browser supports manipulation of the history.
+// Support: IE<10, Android<4.2
(function checkHistoryManipulation() {
- if (!window.history.pushState) {
+ // 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;
+ }
+})();
diff --git a/attachment_preview/static/lib/ViewerJS/example.local.css b/attachment_preview/static/lib/ViewerJS/example.local.css
index 4ef1b672..034347d4 100644
--- a/attachment_preview/static/lib/ViewerJS/example.local.css
+++ b/attachment_preview/static/lib/ViewerJS/example.local.css
@@ -7,7 +7,7 @@
src: url("/ViewerJS/fonts/Novecentowide-Bold-webfont.eot");
src: url("/ViewerJS/fonts/Novecentowide-Bold-webfont.eot?#iefix") format("embedded-opentype"),
url("/ViewerJS/fonts/Novecentowide-Bold-webfont.woff") format("woff"),
- url("/fonts/Novecentowide-Bold-webfont.ttf") format("truetype"),
+ url("/fonts/Novecentowide-Bold-webfont.ttf") format("truetype"),
url("/fonts/Novecentowide-Bold-webfont.svg#NovecentowideBookBold") format("svg");
font-weight: normal;
font-style: normal;
diff --git a/attachment_preview/static/lib/ViewerJS/index.html b/attachment_preview/static/lib/ViewerJS/index.html
index 90b6618d..c7496ceb 100644
--- a/attachment_preview/static/lib/ViewerJS/index.html
+++ b/attachment_preview/static/lib/ViewerJS/index.html
@@ -1,75 +1,88 @@
-
-
-
-
-
-
-
+
+
+
ViewerJS
-
-
-
-
+
+
-
-
+
@@ -113,6 +126,8 @@ limitations under the License.
+
+
diff --git a/attachment_preview/static/lib/ViewerJS/pdf.js b/attachment_preview/static/lib/ViewerJS/pdf.js
index 3e50f6c3..41509814 100644
--- a/attachment_preview/static/lib/ViewerJS/pdf.js
+++ b/attachment_preview/static/lib/ViewerJS/pdf.js
@@ -14,14 +14,16 @@
* 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 = '0.8.958';
-PDFJS.build = 'd45d7bc';
+PDFJS.version = '1.0.1040';
+PDFJS.build = '997096f';
(function pdfjsWrapper() {
// Use strict in our context only - users might not want it
@@ -50,7 +52,7 @@ PDFJS.build = 'd45d7bc';
var globalScope = (typeof window === 'undefined') ? this : window;
-var isWorker = (typeof window == 'undefined');
+var isWorker = (typeof window === 'undefined');
var FONT_IDENTITY_MATRIX = [0.001, 0, 0, 0.001, 0, 0];
@@ -67,6 +69,45 @@ var TextRenderingMode = {
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
@@ -172,7 +213,11 @@ var OPS = PDFJS.OPS = {
paintImageMaskXObjectGroup: 84,
paintImageXObject: 85,
paintInlineImageXObject: 86,
- paintInlineImageXObjectGroup: 87
+ 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
@@ -218,8 +263,9 @@ function backtrace() {
}
function assert(cond, msg) {
- if (!cond)
+ if (!cond) {
error(msg);
+ }
}
var UNSUPPORTED_FEATURES = PDFJS.UNSUPPORTED_FEATURES = {
@@ -250,18 +296,25 @@ var UnsupportedManager = PDFJS.UnsupportedManager =
// 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)
+ if (!url) {
return baseUrl;
- if (/^[a-z][a-z0-9+\-.]*:/i.test(url))
+ }
+ if (/^[a-z][a-z0-9+\-.]*:/i.test(url)) {
return url;
- if (url.charAt(0) == '/') {
+ }
+ var i;
+ if (url.charAt(0) === '/') {
// absolute path
- var i = baseUrl.indexOf('://');
- i = baseUrl.indexOf('/', i + 3);
+ 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;
+ var pathLength = baseUrl.length;
i = baseUrl.lastIndexOf('#');
pathLength = i >= 0 ? i : pathLength;
i = baseUrl.lastIndexOf('?', pathLength);
@@ -295,13 +348,6 @@ function isValidUrl(url, allowRelative) {
}
PDFJS.isValidUrl = isValidUrl;
-// In a well-formed PDF, |cond| holds. If it doesn't, subsequent
-// behavior is undefined.
-function assertWellFormed(cond, msg) {
- if (!cond)
- error(msg);
-}
-
function shadow(obj, prop, value) {
Object.defineProperty(obj, prop, { value: value,
enumerable: true,
@@ -327,6 +373,7 @@ var PasswordException = (function PasswordExceptionClosure() {
return PasswordException;
})();
+PDFJS.PasswordException = PasswordException;
var UnknownErrorException = (function UnknownErrorExceptionClosure() {
function UnknownErrorException(msg, details) {
@@ -340,6 +387,7 @@ var UnknownErrorException = (function UnknownErrorExceptionClosure() {
return UnknownErrorException;
})();
+PDFJS.UnknownErrorException = UnknownErrorException;
var InvalidPDFException = (function InvalidPDFExceptionClosure() {
function InvalidPDFException(msg) {
@@ -352,6 +400,7 @@ var InvalidPDFException = (function InvalidPDFExceptionClosure() {
return InvalidPDFException;
})();
+PDFJS.InvalidPDFException = InvalidPDFException;
var MissingPDFException = (function MissingPDFExceptionClosure() {
function MissingPDFException(msg) {
@@ -364,6 +413,22 @@ var MissingPDFException = (function MissingPDFExceptionClosure() {
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) {
@@ -405,33 +470,146 @@ var XRefParseException = (function XRefParseExceptionClosure() {
function bytesToString(bytes) {
- var str = '';
var length = bytes.length;
- for (var n = 0; n < length; ++n)
- str += String.fromCharCode(bytes[n]);
- return str;
+ 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) {
var length = str.length;
var bytes = new Uint8Array(length);
- for (var n = 0; n < length; ++n)
- bytes[n] = str.charCodeAt(n) & 0xFF;
+ 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() {}
- Util.makeCssRgb = function Util_makeCssRgb(rgb) {
- return 'rgb(' + rgb[0] + ',' + rgb[1] + ',' + rgb[2] + ')';
- };
+ var rgbBuf = ['rgb(', 0, ',', 0, ',', 0, ')'];
- Util.makeCssCmyk = function Util_makeCssCmyk(cmyk) {
- var rgb = ColorSpace.singletons.cmyk.getRgb(cmyk, 0);
- return Util.makeCssRgb(rgb);
+ // 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.
@@ -581,12 +759,11 @@ var Util = PDFJS.Util = (function UtilClosure() {
return num < 0 ? -1 : 1;
};
- // TODO(mack): Rename appendToArray
- Util.concatenateToArray = function concatenateToArray(arr1, arr2) {
+ Util.appendToArray = function Util_appendToArray(arr1, arr2) {
Array.prototype.push.apply(arr1, arr2);
};
- Util.prependToArray = function concatenateToArray(arr1, arr2) {
+ Util.prependToArray = function Util_prependToArray(arr1, arr2) {
Array.prototype.unshift.apply(arr1, arr2);
};
@@ -633,7 +810,22 @@ var Util = PDFJS.Util = (function UtilClosure() {
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;
@@ -697,7 +889,14 @@ var PageViewport = PDFJS.PageViewport = (function PageViewportClosure() {
this.height = height;
this.fontScale = scale;
}
- PageViewport.prototype = {
+ 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;
@@ -705,15 +904,41 @@ var PageViewport = PDFJS.PageViewport = (function PageViewportClosure() {
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);
}
@@ -734,19 +959,20 @@ var PDFStringTranslateTable = [
];
function stringToPDFString(str) {
- var i, n = str.length, str2 = '';
+ var i, n = str.length, strBuf = [];
if (str[0] === '\xFE' && str[1] === '\xFF') {
// UTF16BE BOM
- for (i = 2; i < n; i += 2)
- str2 += String.fromCharCode(
- (str.charCodeAt(i) << 8) | str.charCodeAt(i + 1));
+ 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)];
- str2 += code ? String.fromCharCode(code) : str.charAt(i);
+ strBuf.push(code ? String.fromCharCode(code) : str.charAt(i));
}
}
- return str2;
+ return strBuf.join('');
}
function stringToUTF8String(str) {
@@ -761,19 +987,19 @@ function isEmptyObj(obj) {
}
function isBool(v) {
- return typeof v == 'boolean';
+ return typeof v === 'boolean';
}
function isInt(v) {
- return typeof v == 'number' && ((v | 0) == v);
+ return typeof v === 'number' && ((v | 0) === v);
}
function isNum(v) {
- return typeof v == 'number';
+ return typeof v === 'number';
}
function isString(v) {
- return typeof v == 'string';
+ return typeof v === 'string';
}
function isNull(v) {
@@ -785,7 +1011,7 @@ function isName(v) {
}
function isCmd(v, cmd) {
- return v instanceof Cmd && (!cmd || v.cmd == cmd);
+ return v instanceof Cmd && (cmd === undefined || v.cmd === cmd);
}
function isDict(v, type) {
@@ -796,7 +1022,7 @@ function isDict(v, type) {
return true;
}
var dictType = v.get('Type');
- return isName(dictType) && dictType.name == type;
+ return isName(dictType) && dictType.name === type;
}
function isArray(v) {
@@ -804,52 +1030,47 @@ function isArray(v) {
}
function isStream(v) {
- return typeof v == 'object' && v !== null && v !== undefined &&
- ('getBytes' in v);
+ return typeof v === 'object' && v !== null && v.getBytes !== undefined;
}
function isArrayBuffer(v) {
- return typeof v == 'object' && v !== null && v !== undefined &&
- ('byteLength' in v);
+ return typeof v === 'object' && v !== null && v.byteLength !== undefined;
}
function isRef(v) {
return v instanceof Ref;
}
-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');
-}
+/**
+ * Promise Capability object.
+ *
+ * @typedef {Object} PromiseCapability
+ * @property {Promise} promise - A promise object.
+ * @property {function} resolve - Fullfills the promise.
+ * @property {function} reject - Rejects the promise.
+ */
/**
- * Legacy support for PDFJS Promise implementation.
- * TODO remove eventually
+ * Creates a promise capability object.
+ * @alias PDFJS.createPromiseCapability
+ *
+ * @return {PromiseCapability} A capability object contains:
+ * - a Promise, resolve and reject methods.
*/
-var LegacyPromise = PDFJS.LegacyPromise = (function LegacyPromiseClosure() {
- return function LegacyPromise() {
- var resolve, reject;
- var promise = new Promise(function (resolve_, reject_) {
- resolve = resolve_;
- reject = reject_;
- });
- promise.resolve = resolve;
- promise.reject = reject;
- return promise;
- };
-})();
+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 implment the
+ * 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.
@@ -884,12 +1105,25 @@ var LegacyPromise = PDFJS.LegacyPromise = (function LegacyPromiseClosure() {
};
}
if (typeof globalScope.Promise.resolve !== 'function') {
- globalScope.Promise.resolve = function (x) {
- return new globalScope.Promise(function (resolve) { resolve(x); });
+ 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;
@@ -906,7 +1140,7 @@ var LegacyPromise = PDFJS.LegacyPromise = (function LegacyPromiseClosure() {
pendingRejectionCheck: false,
scheduleHandlers: function scheduleHandlers(promise) {
- if (promise._status == STATUS_PENDING) {
+ if (promise._status === STATUS_PENDING) {
return;
}
@@ -932,10 +1166,10 @@ var LegacyPromise = PDFJS.LegacyPromise = (function LegacyPromiseClosure() {
try {
if (nextStatus === STATUS_RESOLVED) {
- if (typeof(handler.onResolve) == 'function') {
+ if (typeof handler.onResolve === 'function') {
nextValue = handler.onResolve(nextValue);
}
- } else if (typeof(handler.onReject) === 'function') {
+ } else if (typeof handler.onReject === 'function') {
nextValue = handler.onReject(nextValue);
nextStatus = STATUS_RESOLVED;
@@ -1010,7 +1244,11 @@ var LegacyPromise = PDFJS.LegacyPromise = (function LegacyPromiseClosure() {
function Promise(resolver) {
this._status = STATUS_PENDING;
this._handlers = [];
- resolver.call(this, this._resolve.bind(this), this._reject.bind(this));
+ 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
@@ -1046,8 +1284,9 @@ var LegacyPromise = PDFJS.LegacyPromise = (function LegacyPromiseClosure() {
}
results[i] = value;
unresolved--;
- if (unresolved === 0)
+ if (unresolved === 0) {
resolveAll(results);
+ }
};
})(i);
if (Promise.isPromise(promise)) {
@@ -1061,18 +1300,28 @@ var LegacyPromise = PDFJS.LegacyPromise = (function LegacyPromiseClosure() {
/**
* Checks if the value is likely a promise (has a 'then' function).
- * @return {boolean} true if x is thenable
+ * @return {boolean} true if value is thenable
*/
Promise.isPromise = function Promise_isPromise(value) {
return value && typeof value.then === 'function';
};
+
/**
* Creates resolved promise
- * @param x resolve value
+ * @param value resolve value
* @returns {Promise}
*/
- Promise.resolve = function Promise_resolve(x) {
- return new Promise(function (resolve) { resolve(x); });
+ 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 = {
@@ -1087,7 +1336,7 @@ var LegacyPromise = PDFJS.LegacyPromise = (function LegacyPromiseClosure() {
return;
}
- if (status == STATUS_RESOLVED &&
+ if (status === STATUS_RESOLVED &&
Promise.isPromise(value)) {
value.then(this._updateStatus.bind(this, STATUS_RESOLVED),
this._updateStatus.bind(this, STATUS_REJECTED));
@@ -1115,7 +1364,7 @@ var LegacyPromise = PDFJS.LegacyPromise = (function LegacyPromiseClosure() {
then: function Promise_then(onResolve, onReject) {
var nextPromise = new Promise(function (resolve, reject) {
- this.resolve = reject;
+ this.resolve = resolve;
this.reject = reject;
});
this._handlers.push({
@@ -1126,16 +1375,24 @@ var LegacyPromise = PDFJS.LegacyPromise = (function LegacyPromiseClosure() {
});
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)
+ while (str.length < length) {
str += pad;
+ }
return str;
}
function StatTimer() {
@@ -1145,17 +1402,21 @@ var StatTimer = (function StatTimerClosure() {
}
StatTimer.prototype = {
time: function StatTimer_time(name) {
- if (!this.enabled)
+ if (!this.enabled) {
return;
- if (name in this.started)
+ }
+ 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)
+ if (!this.enabled) {
return;
- if (!(name in this.started))
+ }
+ if (!(name in this.started)) {
warn('Timer has not been started for ' + name);
+ }
this.times.push({
'name': name,
'start': this.started[name],
@@ -1165,16 +1426,18 @@ var StatTimer = (function StatTimerClosure() {
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 (var i = 0, ii = times.length; i < ii; ++i) {
+ for (i = 0, ii = times.length; i < ii; ++i) {
var name = times[i]['name'];
- if (name.length > longest)
+ if (name.length > longest) {
longest = name.length;
+ }
}
- for (var i = 0, ii = times.length; i < ii; ++i) {
+ 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';
@@ -1186,8 +1449,9 @@ var StatTimer = (function StatTimerClosure() {
})();
PDFJS.createBlob = function createBlob(data, contentType) {
- if (typeof Blob !== 'undefined')
+ 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);
@@ -1225,7 +1489,7 @@ function MessageHandler(name, comObj) {
this.comObj = comObj;
this.callbackIndex = 1;
this.postMessageTransfers = true;
- var callbacks = this.callbacks = {};
+ var callbacksCapabilities = this.callbacksCapabilities = {};
var ah = this.actionHandler = {};
ah['console_log'] = [function ahConsoleLog(data) {
@@ -1242,35 +1506,40 @@ function MessageHandler(name, comObj) {
var data = event.data;
if (data.isReply) {
var callbackId = data.callbackId;
- if (data.callbackId in callbacks) {
- var callback = callbacks[callbackId];
- delete callbacks[callbackId];
- callback(data.data);
+ 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) {
- var deferred = {};
- var promise = new Promise(function (resolve, reject) {
- deferred.resolve = resolve;
- deferred.reject = reject;
- });
- deferred.promise = promise;
- promise.then(function(resolvedData) {
+ Promise.resolve().then(function () {
+ return action[0].call(action[1], data.data);
+ }).then(function (result) {
comObj.postMessage({
isReply: true,
callbackId: data.callbackId,
- data: resolvedData
+ data: result
+ });
+ }, function (reason) {
+ comObj.postMessage({
+ isReply: true,
+ callbackId: data.callbackId,
+ error: reason
});
});
- action[0].call(action[1], data.data, deferred);
} else {
action[0].call(action[1], data.data);
}
} else {
- error('Unkown action from worker: ' + data.action);
+ error('Unknown action from worker: ' + data.action);
}
};
}
@@ -1287,19 +1556,47 @@ MessageHandler.prototype = {
* 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 {function} [callback] Optional callback that will handle a reply.
* @param {Array} [transfers] Optional list of transfers/ArrayBuffers
*/
- send: function messageHandlerSend(actionName, data, callback, transfers) {
+ send: function messageHandlerSend(actionName, data, transfers) {
var message = {
action: actionName,
data: data
};
- if (callback) {
- var callbackId = this.callbackIndex++;
- this.callbacks[callbackId] = callback;
- message.callbackId = callbackId;
+ 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 {
@@ -1313,2542 +1610,51 @@ function loadJpegStream(id, imageUrl, objs) {
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;
}
-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) {
- error('Should not call ColorSpace.getRgb');
- },
- /**
- * 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_getRgb(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 an RGBA buffer.
- */
- fillRgb: function ColorSpace_fillRgb(rgbaBuf, originalWidth,
- originalHeight, width, height,
- actualHeight, bpc, comps) {
- var count = originalWidth * originalHeight;
- var rgbBuf = null;
- var numComponentColors = 1 << bpc;
- var needsResizing = originalHeight != height || originalWidth != width;
-
- 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);
- for (var i = 0; i < numComponentColors; i++) {
- allColors[i] = i;
- }
- var colorMap = new Uint8Array(numComponentColors * 3);
- this.getRgbBuffer(allColors, 0, numComponentColors, colorMap, 0, bpc,
- /* alpha01 = */ 0);
-
- if (!needsResizing) {
- // Fill in the RGB values directly into |rgbaBuf|.
- var rgbaPos = 0;
- for (var i = 0; i < count; ++i) {
- var key = comps[i] * 3;
- rgbaBuf[rgbaPos++] = colorMap[key];
- rgbaBuf[rgbaPos++] = colorMap[key + 1];
- rgbaBuf[rgbaPos++] = colorMap[key + 2];
- rgbaPos++;
- }
- } else {
- rgbBuf = new Uint8Array(count * 3);
- var rgbPos = 0;
- for (var i = 0; i < count; ++i) {
- var 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 |rgbaBuf|.
- this.getRgbBuffer(comps, 0, width * actualHeight, rgbaBuf, 0, bpc,
- /* alpha01 = */ 1);
- } else {
- rgbBuf = new Uint8Array(count * 3);
- this.getRgbBuffer(comps, 0, count, rgbBuf, 0, bpc,
- /* alpha01 = */ 0);
- }
- }
-
- if (rgbBuf) {
- if (needsResizing) {
- rgbBuf = PDFImage.resize(rgbBuf, bpc, 3, originalWidth,
- originalHeight, width, height);
- }
- var rgbPos = 0;
- var actualLength = width * actualHeight * 4;
- for (var i = 0; i < actualLength; i += 4) {
- rgbaBuf[i] = rgbBuf[rgbPos++];
- rgbaBuf[i + 1] = rgbBuf[rgbPos++];
- rgbaBuf[i + 2] = rgbBuf[rgbPos++];
- }
- }
- },
- /**
- * 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;
-
- switch (name) {
- case 'DeviceGrayCS':
- return this.singletons.gray;
- case 'DeviceRgbCS':
- return this.singletons.rgb;
- case 'DeviceCmykCS':
- return this.singletons.cmyk;
- case 'CalGrayCS':
- var whitePoint = IR[1].WhitePoint;
- var blackPoint = IR[1].BlackPoint;
- var gamma = IR[1].Gamma;
- return new CalGrayCS(whitePoint, blackPoint, gamma);
- 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':
- var whitePoint = IR[1].WhitePoint;
- var blackPoint = IR[1].BlackPoint;
- var range = IR[1].Range;
- return new LabCS(whitePoint, blackPoint, range);
- default:
- error('Unkown 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;
-
- switch (mode) {
- case 'DeviceGray':
- case 'G':
- return 'DeviceGrayCS';
- case 'DeviceRGB':
- case 'RGB':
- return 'DeviceRgbCS';
- case 'DeviceCMYK':
- case 'CMYK':
- return 'DeviceCmykCS';
- case 'CalGray':
- var params = cs[1].getAll();
- return ['CalGrayCS', params];
- case 'CalRGB':
- return 'DeviceRgbCS';
- case 'ICCBased':
- var stream = xref.fetchIfRef(cs[1]);
- var dict = stream.dict;
- var numComps = dict.get('N');
- if (numComps == 1)
- return 'DeviceGrayCS';
- if (numComps == 3)
- return 'DeviceRgbCS';
- 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];
- var 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':
- var 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;
- }
-
- AlternateCS.prototype = {
- getRgb: function AlternateCS_getRgb(src, srcOffset) {
- var rgb = new Uint8Array(3);
- this.getRgbItem(src, srcOffset, rgb, 0);
- return rgb;
- },
- getRgbItem: function AlternateCS_getRgbItem(src, srcOffset,
- dest, destOffset) {
- var baseNumComps = this.base.numComps;
- var input = 'subarray' in src ?
- src.subarray(srcOffset, srcOffset + this.numComps) :
- Array.prototype.slice.call(src, srcOffset, srcOffset + this.numComps);
- var tinted = this.tintFn(input);
- this.base.getRgbItem(tinted, 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);
- for (var i = 0; i < count; i++) {
- for (var j = 0; j < numComps; j++) {
- scaled[j] = src[srcOffset++] * scale;
- }
- var tinted = tintFn(scaled);
- if (usesZeroToOneRange) {
- for (var j = 0; j < baseNumComps; j++) {
- baseBuf[pos++] = tinted[j] * 255;
- }
- } else {
- 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: function IndexedCS_getRgb(src, srcOffset) {
- var numComps = this.base.numComps;
- var start = src[srcOffset] * numComps;
- return this.base.getRgb(this.lookup, start);
- },
- 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: function DeviceGrayCS_getRgb(src, srcOffset) {
- var rgb = new Uint8Array(3);
- this.getRgbItem(src, srcOffset, rgb, 0);
- return rgb;
- },
- 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: function DeviceRgbCS_getRgb(src, srcOffset) {
- var rgb = new Uint8Array(3);
- this.getRgbItem(src, srcOffset, rgb, 0);
- return rgb;
- },
- 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;
- 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;
- 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;
-
- 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: function DeviceCmykCS_getRgb(src, srcOffset) {
- var rgb = new Uint8Array(3);
- convertToRgb(src, srcOffset, 1, rgb, 0);
- return rgb;
- },
- 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 intermediate variables M, L, N as per spec.
- // Except if other than default BlackPoint values are used.
- var M = cs.XW * AG;
- var L = cs.YW * AG;
- var N = cs.ZW * AG;
-
- // Decode XYZ, as per spec.
- var X = M;
- var Y = L;
- var Z = N;
-
- // http://www.poynton.com/notes/colour_and_gamma/ColorFAQ.html, Ch 4.
- // This yields values in range [0, 100].
- var Lstar = Math.max(116 * Math.pow(Y, 1 / 3) - 16, 0);
-
- // Convert values to rgb range [0, 255].
- dest[destOffset] = Lstar * 255 / 100;
- dest[destOffset + 1] = Lstar * 255 / 100;
- dest[destOffset + 2] = Lstar * 255 / 100;
- }
-
- CalGrayCS.prototype = {
- getRgb: function CalGrayCS_getRgb(src, srcOffset) {
- var rgb = new Uint8Array(3);
- this.getRgbItem(src, srcOffset, rgb, 0);
- return rgb;
- },
- 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;
-})();
-
-//
-// 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] = Math.sqrt(r < 0 ? 0 : r > 1 ? 1 : r) * 255;
- dest[destOffset + 1] = Math.sqrt(g < 0 ? 0 : g > 1 ? 1 : g) * 255;
- dest[destOffset + 2] = Math.sqrt(b < 0 ? 0 : b > 1 ? 1 : b) * 255;
- }
-
- LabCS.prototype = {
- getRgb: function LabCS_getRgb(src, srcOffset) {
- var rgb = new Uint8Array(3);
- convertToRgb(this, src, srcOffset, false, rgb, 0);
- return rgb;
- },
- 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,
- 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 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 length = 1;
- for (var i = 0, ii = size.length; i < ii; i++)
- length *= size[i];
- length *= outputSize;
-
- var array = [];
- 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 (var i = 0; i < length; i++) {
- while (codeSize < bps) {
- codeBuf <<= 8;
- codeBuf |= strBytes[strIdx++];
- codeSize += 8;
- }
- codeSize -= bps;
- array.push((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);
- },
-
- constructSampled: function PDFFunction_constructSampled(str, dict) {
- function toMultiArray(arr) {
- var inputLength = arr.length;
- var outputLength = arr.length / 2;
- 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(args) {
- // 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];
-
- if (m != args.length)
- error('Incorrect number of arguments: ' + m + ' != ' +
- args.length);
-
- var x = args;
-
- // 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);
- for (var 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 (var 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(x[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 (var 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;
- }
-
- var y = new Float64Array(n);
- for (var j = 0; j < n; ++j) {
- // Sum all cube vertices' samples portions
- var rj = 0;
- for (var 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)
- y[j] = Math.min(Math.max(rj, range[j][0]), range[j][1]);
- }
-
- return y;
- };
- },
-
- 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(args) {
- var x = n == 1 ? args[0] : Math.pow(args[0], n);
-
- var out = [];
- for (var j = 0; j < length; ++j)
- out.push(c0[j] + (x * diff[j]));
-
- return out;
-
- };
- },
-
- 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 = [];
-
- for (var i = 0, ii = fnsIR.length; i < ii; i++) {
- fns.push(PDFFunction.fromIR(fnsIR[i]));
- }
-
- return function constructStichedFromIRResult(args) {
- 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(args[0], 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];
-
- var v2 = rmin + (v - dmin) * (rmax - rmin) / (dmax - dmin);
-
- // call the appropropriate function
- return fns[i]([v2]);
- };
- },
-
- 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 numOutputs = range.length / 2;
- 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 = new FunctionCache();
- return function constructPostScriptFromIRResult(args) {
- var initialStack = [];
- for (var i = 0, ii = (domain.length / 2); i < ii; ++i) {
- initialStack.push(args[i]);
- }
-
- var key = initialStack.join('_');
- if (cache.has(key))
- return cache.get(key);
-
- var stack = evaluator.execute(initialStack);
- var transformed = [];
- for (i = numOutputs - 1; i >= 0; --i) {
- var out = stack.pop();
- var rangeIndex = 2 * i;
- if (out < range[rangeIndex])
- out = range[rangeIndex];
- else if (out > range[rangeIndex + 1])
- out = range[rangeIndex + 1];
- transformed[i] = out;
- }
- cache.set(key, transformed);
- return transformed;
- };
- }
- };
-})();
-
-var FunctionCache = (function FunctionCacheClosure() {
- // Of 10 PDF's with type4 functions the maxium number of distinct values seen
- // was 256. This still may need some tweaking in the future though.
- var MAX_CACHE_SIZE = 1024;
- function FunctionCache() {
- this.cache = {};
- this.total = 0;
- }
- FunctionCache.prototype = {
- has: function FunctionCache_has(key) {
- return key in this.cache;
- },
- get: function FunctionCache_get(key) {
- return this.cache[key];
- },
- set: function FunctionCache_set(key, value) {
- if (this.total < MAX_CACHE_SIZE) {
- this.cache[key] = value;
- this.total++;
- }
- }
- };
- return FunctionCache;
-})();
-
-var PostScriptStack = (function PostScriptStackClosure() {
- var MAX_STACK_SIZE = 100;
- function PostScriptStack(initialStack) {
- this.stack = initialStack || [];
- }
-
- 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, operands) {
- this.operators = operators;
- this.operands = operands;
- }
- 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(-b);
- break;
- case 'not':
- a = stack.pop();
- if (isBool(a) && isBool(b))
- stack.push(a && b);
- else
- stack.push(a & b);
- 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;
-})();
-
-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();
- }
- PostScriptLexer.prototype = {
- nextChar: function PostScriptLexer_nextChar() {
- return (this.currentChar = this.stream.getByte());
- },
- getToken: function PostScriptLexer_getToken() {
- var s = '';
- 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 str = String.fromCharCode(ch);
- while ((ch = this.nextChar()) >= 0 && // and 'A'-'Z', 'a'-'z'
- ((ch >= 0x41 && ch <= 0x5A) || (ch >= 0x61 && ch <= 0x7A))) {
- str += String.fromCharCode(ch);
- }
- 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 str = String.fromCharCode(ch);
- while ((ch = this.nextChar()) >= 0) {
- if ((ch >= 0x30 && ch <= 0x39) || // '0'-'9'
- ch === 0x2D || ch === 0x2E) { // '-', '.'
- str += String.fromCharCode(ch);
- } else {
- break;
- }
- }
- var value = parseFloat(str);
- if (isNaN(value))
- error('Invalid floating point number: ' + value);
- return value;
- }
- };
- return PostScriptLexer;
-})();
-
-
-
-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) {
- if (params.data) {
- this.data = params.data;
- return;
- }
-
- var dict = params.dict;
- var data = this.data = {};
-
- data.subtype = dict.get('Subtype').name;
- var rect = dict.get('Rect');
- data.rect = Util.normalizeRect(rect);
- data.annotationFlags = dict.get('F');
-
- var color = dict.get('C');
- if (isArray(color) && color.length === 3) {
- // TODO(mack): currently only supporting rgb; need support different
- // colorspaces
- data.color = color;
- } else {
- data.color = [0, 0, 0];
- }
-
- // 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 && isArray(dashArray)) {
- 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++) {
- if (!(+dashArray[i] >= 0)) {
- isInvalid = true;
- break;
- } else if (dashArray[i] > 0) {
- numPositive++;
- }
- }
- if (isInvalid || numPositive === 0) {
- data.borderWidth = 0;
- }
- }
- }
- }
-
- this.appearance = getDefaultAppearance(dict);
- data.hasAppearance = !!this.appearance;
- }
-
- Annotation.prototype = {
-
- getData: function Annotation_getData() {
- return this.data;
- },
-
- hasHtml: function Annotation_hasHtml() {
- return false;
- },
-
- getHtmlElement: function Annotation_getHtmlElement(commonObjs) {
- throw new NotImplementedException(
- 'getHtmlElement() should be implemented in subclass');
- },
-
- // TODO(mack): Remove this, it's not really that helpful.
- getEmptyContainer: function Annotation_getEmptyContainer(tagName, rect) {
- assert(!isWorker,
- 'getEmptyContainer() should be called from main thread');
-
- rect = rect || this.data.rect;
- var element = document.createElement(tagName);
- element.style.width = Math.ceil(rect[2] - rect[0]) + 'px';
- element.style.height = Math.ceil(rect[3] - rect[1]) + 'px';
- return element;
- },
-
- isViewable: function Annotation_isViewable() {
- var data = this.data;
- return !!(
- data &&
- (!data.annotationFlags ||
- !(data.annotationFlags & 0x22)) && // Hidden or NoView
- data.rect // rectangle is nessessary
- );
- },
-
- loadResources: function(keys) {
- var promise = new LegacyPromise();
- this.appearance.dict.getAsync('Resources').then(function(resources) {
- if (!resources) {
- promise.resolve();
- return;
- }
- var objectLoader = new ObjectLoader(resources.map,
- keys,
- resources.xref);
- objectLoader.load().then(function() {
- promise.resolve(resources);
- });
- }.bind(this));
-
- return promise;
- },
-
- getOperatorList: function Annotation_getToOperatorList(evaluator) {
-
- var promise = new LegacyPromise();
-
- if (!this.appearance) {
- promise.resolve(new OperatorList());
- return promise;
- }
-
- 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 border = data.border;
-
- resourcesPromise.then(function(resources) {
- var opList = new OperatorList();
- opList.addOp(OPS.beginAnnotation, [data.rect, transform, matrix]);
- evaluator.getOperatorList(this.appearance, resources, opList);
- opList.addOp(OPS.endAnnotation, []);
- promise.resolve(opList);
- }.bind(this));
-
- return promise;
- }
- };
-
- 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;
- }
- };
-
- // TODO(mack): Support loading annotation from data
- Annotation.fromData = function Annotation_fromData(data) {
- var subtype = data.subtype;
- var fieldType = data.fieldType;
- var Constructor = Annotation.getConstructor(subtype, fieldType);
- if (Constructor) {
- return new Constructor({ data: data });
- }
- };
-
- 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()) {
- return annotation;
- } else {
- warn('unimplemented annotation type: ' + subtype);
- }
- };
-
- Annotation.appendToOperatorList = function Annotation_appendToOperatorList(
- annotations, opList, pdfManager, partialEvaluator) {
-
- function reject(e) {
- annotationsReadyPromise.reject(e);
- }
-
- var annotationsReadyPromise = new LegacyPromise();
-
- var annotationPromises = [];
- for (var i = 0, n = annotations.length; i < n; ++i) {
- 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, []);
- annotationsReadyPromise.resolve();
- }, reject);
-
- return annotationsReadyPromise;
- };
-
- return Annotation;
-})();
-PDFJS.Annotation = Annotation;
-
-
-var WidgetAnnotation = (function WidgetAnnotationClosure() {
-
- function WidgetAnnotation(params) {
- Annotation.call(this, params);
-
- if (params.data) {
- return;
- }
-
- 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') || new Dict();
-
- // 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 {
- // 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);
-
- if (params.data) {
- return;
- }
-
- this.data.textAlignment = Util.getInheritableProperty(params.dict, 'Q');
- }
-
- // 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;
- }
-
-
- var parent = WidgetAnnotation.prototype;
- Util.inherit(TextWidgetAnnotation, WidgetAnnotation, {
- hasHtml: function TextWidgetAnnotation_hasHtml() {
- return !this.data.hasAppearance && !!this.data.fieldValue;
- },
-
- getHtmlElement: function TextWidgetAnnotation_getHtmlElement(commonObjs) {
- assert(!isWorker, 'getHtmlElement() shall be called from main thread');
-
- var item = this.data;
-
- var element = this.getEmptyContainer('div');
- 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;
- var cssRules = setTextStyles(content, item, fontObj);
-
- element.appendChild(content);
-
- return element;
- },
-
- getOperatorList: function TextWidgetAnnotation_getOperatorList(evaluator) {
- if (this.appearance) {
- return Annotation.prototype.getOperatorList.call(this, evaluator);
- }
-
- var promise = new LegacyPromise();
- 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.
-
- var defaultAppearance = data.defaultAppearance;
- if (!defaultAppearance) {
- promise.resolve(opList);
- return promise;
- }
-
- // Include any font resources found in the default appearance
-
- var stream = new Stream(stringToBytes(defaultAppearance));
- evaluator.getOperatorList(stream, this.fieldResources, opList);
- var appearanceFnArray = opList.fnArray;
- var appearanceArgsArray = opList.argsArray;
- var fnArray = [];
- var argsArray = [];
-
- // TODO(mack): Add support for stroke color
- data.rgb = [0, 0, 0];
- // TODO THIS DOESN'T MAKE ANY SENSE SINCE THE fnArray IS EMPTY!
- for (var i = 0, n = fnArray.length; i < n; ++i) {
- var fnId = appearanceFnArray[i];
- var args = appearanceArgsArray[i];
-
- if (fnId === OPS.setFont) {
- data.fontRefName = args[0];
- var size = args[1];
- if (size < 0) {
- data.fontDirection = -1;
- data.fontSize = -size;
- } else {
- data.fontDirection = 1;
- data.fontSize = size;
- }
- } else if (fnId === OPS.setFillRGBColor) {
- data.rgb = args;
- } else if (fnId === OPS.setFillGray) {
- var rgbValue = args[0] * 255;
- data.rgb = [rgbValue, rgbValue, rgbValue];
- }
- }
- promise.resolve(opList);
- return promise;
- }
- });
-
- return TextWidgetAnnotation;
-})();
-
-var TextAnnotation = (function TextAnnotationClosure() {
- function TextAnnotation(params) {
- Annotation.call(this, params);
-
- if (params.data) {
- return;
- }
-
- var dict = params.dict;
- var data = this.data;
-
- var content = dict.get('Contents');
- var title = dict.get('T');
- data.content = stringToPDFString(content || '');
- data.title = stringToPDFString(title || '');
- data.name = !dict.has('Name') ? 'Note' : dict.get('Name').name;
- }
-
- var ANNOT_MIN_SIZE = 10;
-
- Util.inherit(TextAnnotation, Annotation, {
-
- getOperatorList: function TextAnnotation_getOperatorList(evaluator) {
- var promise = new LegacyPromise();
- promise.resolve(new OperatorList());
- return promise;
- },
-
- hasHtml: function TextAnnotation_hasHtml() {
- return true;
- },
-
- getHtmlElement: function TextAnnotation_getHtmlElement(commonObjs) {
- assert(!isWorker, 'getHtmlElement() shall be called from main thread');
-
- var item = this.data;
- 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 = this.getEmptyContainer('section', rect);
- container.className = 'annotText';
-
- var image = document.createElement('img');
- image.style.height = container.style.height;
- 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 content = document.createElement('div');
- content.setAttribute('hidden', true);
- var title = document.createElement('h1');
- var text = document.createElement('p');
- content.style.left = Math.floor(rect[2] - rect[0]) + 'px';
- content.style.top = '0px';
- 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 (var 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 showAnnotation = function showAnnotation() {
- container.style.zIndex += 1;
- content.removeAttribute('hidden');
- };
-
- var hideAnnotation = function hideAnnotation(e) {
- if (e.toElement || e.relatedTarget) { // No context menu is used
- container.style.zIndex -= 1;
- content.setAttribute('hidden', true);
- }
- };
-
- content.addEventListener('mouseover', showAnnotation, false);
- content.addEventListener('mouseout', hideAnnotation, false);
- image.addEventListener('mouseover', showAnnotation, false);
- image.addEventListener('mouseout', hideAnnotation, false);
- }
-
- content.appendChild(title);
- content.appendChild(text);
- container.appendChild(image);
- container.appendChild(content);
-
- return container;
- }
- });
-
- return TextAnnotation;
-})();
-
-var LinkAnnotation = (function LinkAnnotationClosure() {
- function LinkAnnotation(params) {
- Annotation.call(this, params);
-
- if (params.data) {
- return;
- }
-
- var dict = params.dict;
- var data = this.data;
-
- var action = dict.get('A');
- if (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 {
- 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.indexOf('www.') === 0) {
- return ('http://' + url);
- }
- return url;
- }
-
- Util.inherit(LinkAnnotation, Annotation, {
- hasOperatorList: function LinkAnnotation_hasOperatorList() {
- return false;
- },
-
- hasHtml: function LinkAnnotation_hasHtml() {
- return true;
- },
-
- getHtmlElement: function LinkAnnotation_getHtmlElement(commonObjs) {
- var rect = this.data.rect;
- var element = document.createElement('a');
- var borderWidth = this.data.borderWidth;
-
- element.style.borderWidth = borderWidth + 'px';
- var color = this.data.color;
- var rgb = [];
- for (var i = 0; i < 3; ++i) {
- rgb[i] = Math.round(color[i] * 255);
- }
- element.style.borderColor = Util.makeCssRgb(rgb);
- element.style.borderStyle = 'solid';
-
- var width = rect[2] - rect[0] - 2 * borderWidth;
- var height = rect[3] - rect[1] - 2 * borderWidth;
- element.style.width = width + 'px';
- element.style.height = height + 'px';
-
- element.href = this.data.url || '';
- return element;
- }
- });
-
- return LinkAnnotation;
-})();
-
-
/**
* 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;
+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;
+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;
+PDFJS.imageResourcesPath = (PDFJS.imageResourcesPath === undefined ?
+ '' : PDFJS.imageResourcesPath);
/**
* Disable the web worker and run all code on the main thread. This will happen
@@ -3856,8 +1662,8 @@ PDFJS.imageResourcesPath = PDFJS.imageResourcesPath === undefined ?
* to workers.
* @var {boolean}
*/
-PDFJS.disableWorker = PDFJS.disableWorker === undefined ?
- false : PDFJS.disableWorker;
+PDFJS.disableWorker = (PDFJS.disableWorker === undefined ?
+ false : PDFJS.disableWorker);
/**
* Path and filename of the worker file. Required when the worker is enabled in
@@ -3865,7 +1671,7 @@ PDFJS.disableWorker = PDFJS.disableWorker === undefined ?
* loaded based on the location of the pdf.js file.
* @var {string}
*/
-PDFJS.workerSrc = PDFJS.workerSrc === undefined ? null : PDFJS.workerSrc;
+PDFJS.workerSrc = (PDFJS.workerSrc === undefined ? null : PDFJS.workerSrc);
/**
* Disable range request loading of PDF files. When enabled and if the server
@@ -3873,8 +1679,16 @@ PDFJS.workerSrc = PDFJS.workerSrc === undefined ? null : PDFJS.workerSrc;
* Enabled (false) by default.
* @var {boolean}
*/
-PDFJS.disableRange = PDFJS.disableRange === undefined ?
- false : PDFJS.disableRange;
+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
@@ -3882,28 +1696,42 @@ PDFJS.disableRange = PDFJS.disableRange === undefined ?
* the current page. This default behavior can be disabled.
* @var {boolean}
*/
-PDFJS.disableAutoFetch = PDFJS.disableAutoFetch === undefined ?
- false : PDFJS.disableAutoFetch;
+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;
+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;
+PDFJS.postMessageTransfers = (PDFJS.postMessageTransfers === undefined ?
+ true : PDFJS.postMessageTransfers);
/**
* Disables URL.createObjectURL usage.
* @var {boolean}
*/
-PDFJS.disableCreateObjectURL = PDFJS.disableCreateObjectURL === undefined ?
- false : PDFJS.disableCreateObjectURL;
+PDFJS.disableCreateObjectURL = (PDFJS.disableCreateObjectURL === undefined ?
+ false : PDFJS.disableCreateObjectURL);
+
+/**
+ * Disables WebGL usage.
+ * @var {boolean}
+ */
+PDFJS.disableWebGL = (PDFJS.disableWebGL === undefined ?
+ true : PDFJS.disableWebGL);
+
+/**
+ * Enables CSS only zooming.
+ * @var {boolean}
+ */
+PDFJS.useOnlyCssZoom = (PDFJS.useOnlyCssZoom === undefined ?
+ false : PDFJS.useOnlyCssZoom);
/**
* Controls the logging level.
@@ -3913,8 +1741,16 @@ PDFJS.disableCreateObjectURL = PDFJS.disableCreateObjectURL === undefined ?
* - infos
* @var {number}
*/
-PDFJS.verbosity = PDFJS.verbosity === undefined ?
- PDFJS.VERBOSITY_LEVELS.warnings : PDFJS.verbosity;
+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);
/**
* Document initialization / loading parameters object.
@@ -3932,6 +1768,14 @@ PDFJS.verbosity = PDFJS.verbosity === undefined ?
* loaded before the switch to range requests.
*/
+/**
+ * @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)
@@ -3951,6 +1795,11 @@ PDFJS.verbosity = PDFJS.verbosity === undefined ?
* parameters: function that needs to be called with new password and reason
* (see {PasswordResponses}).
*
+ * @param {function} progressCallback is optional. 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 {Promise} A promise that is resolved with {@link PDFDocumentProxy}
* object.
*/
@@ -3958,7 +1807,7 @@ PDFJS.getDocument = function getDocument(source,
pdfDataRangeTransport,
passwordCallback,
progressCallback) {
- var workerInitializedPromise, workerReadyPromise, transport;
+ var workerInitializedCapability, workerReadyCapability, transport;
if (typeof source === 'string') {
source = { url: source };
@@ -3969,8 +1818,9 @@ PDFJS.getDocument = function getDocument(source,
'string or a parameter object');
}
- if (!source.url && !source.data)
+ if (!source.url && !source.data) {
error('Invalid parameter array, need either .data or .url');
+ }
// copy/use all keys as is except 'url' -- full path is required
var params = {};
@@ -3982,15 +1832,16 @@ PDFJS.getDocument = function getDocument(source,
params[key] = source[key];
}
- workerInitializedPromise = new PDFJS.LegacyPromise();
- workerReadyPromise = new PDFJS.LegacyPromise();
- transport = new WorkerTransport(workerInitializedPromise,
- workerReadyPromise, pdfDataRangeTransport, progressCallback);
- workerInitializedPromise.then(function transportInitialized() {
+ workerInitializedCapability = createPromiseCapability();
+ workerReadyCapability = createPromiseCapability();
+ transport = new WorkerTransport(workerInitializedCapability,
+ workerReadyCapability, pdfDataRangeTransport,
+ progressCallback);
+ workerInitializedCapability.promise.then(function transportInitialized() {
transport.passwordCallback = passwordCallback;
transport.fetchDocument(params);
});
- return workerReadyPromise;
+ return workerReadyCapability.promise;
};
/**
@@ -4017,13 +1868,6 @@ var PDFDocumentProxy = (function PDFDocumentProxyClosure() {
get fingerprint() {
return this.pdfInfo.fingerprint;
},
- /**
- * @return {boolean} true if embedded document fonts are in use. Will be
- * set during rendering of the pages.
- */
- get embeddedFontsUsed() {
- return this.transport.embeddedFontsUsed;
- },
/**
* @param {number} pageNumber The page number to get. The first page is 1.
* @return {Promise} A promise that is resolved with a {@link PDFPageProxy}
@@ -4044,19 +1888,33 @@ var PDFDocumentProxy = (function PDFDocumentProxyClosure() {
/**
* @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() {
- var promise = new PDFJS.LegacyPromise();
- var js = this.pdfInfo.javaScript;
- promise.resolve(js);
- return promise;
+ return this.transport.getJavaScript();
},
/**
* @return {Promise} A promise that is resolved with an {Array} that is a
@@ -4074,10 +1932,7 @@ var PDFDocumentProxy = (function PDFDocumentProxyClosure() {
* ].
*/
getOutline: function PDFDocumentProxy_getOutline() {
- var promise = new PDFJS.LegacyPromise();
- var outline = this.pdfInfo.outline;
- promise.resolve(outline);
- return promise;
+ return this.transport.getOutline();
},
/**
* @return {Promise} A promise that is resolved with an {Object} that has
@@ -4086,30 +1941,29 @@ var PDFDocumentProxy = (function PDFDocumentProxyClosure() {
* {Metadata} object with information from the metadata section of the PDF.
*/
getMetadata: function PDFDocumentProxy_getMetadata() {
- var promise = new PDFJS.LegacyPromise();
- var info = this.pdfInfo.info;
- var metadata = this.pdfInfo.metadata;
- promise.resolve({
- info: info,
- metadata: metadata ? new PDFJS.Metadata(metadata) : null
- });
- return promise;
+ 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() {
- var promise = new PDFJS.LegacyPromise();
- this.transport.getData(promise);
- return promise;
+ return this.transport.getData();
},
/**
* @return {Promise} A promise that is resolved when the document's data
- * is loaded
+ * is loaded. It is resolved with an {Object} that contains the length
+ * property that indicates size of the PDF data in bytes.
*/
- dataLoaded: function PDFDocumentProxy_dataLoaded() {
- return this.transport.dataLoaded();
+ getDownloadInfo: function PDFDocumentProxy_getDownloadInfo() {
+ return this.transport.downloadInfoCapability.promise;
+ },
+ /**
+ * @returns {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.
@@ -4127,16 +1981,61 @@ var PDFDocumentProxy = (function PDFDocumentProxyClosure() {
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} BidiText
+ * @typedef {Object} TextItem
* @property {string} str - text content.
* @property {string} dir - text direction: 'ttb', 'ltr' or 'rtl'.
- * @property {number} x - x position of the text on the page.
- * @property {number} y - y position of the text on the page.
- * @property {number} angle - text rotation.
- * @property {number} size - font size.
+ * @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 - (optional) 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.
*/
/**
@@ -4144,24 +2043,24 @@ var PDFDocumentProxy = (function PDFDocumentProxyClosure() {
* @class
*/
var PDFPageProxy = (function PDFPageProxyClosure() {
- function PDFPageProxy(pageInfo, transport) {
+ 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.receivingOperatorList = false;
this.cleanupAfterRender = false;
this.pendingDestroy = false;
- this.renderTasks = [];
+ this.intentStates = {};
}
PDFPageProxy.prototype = /** @lends PDFPageProxy.prototype */ {
/**
* @return {number} Page number of the page. First page is 1.
*/
get pageNumber() {
- return this.pageInfo.pageIndex + 1;
+ return this.pageIndex + 1;
},
/**
* @return {number} The number of degrees the page is rotated clockwise.
@@ -4187,12 +2086,13 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
* @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 {PageViewport} Contains 'width' and 'height' properties along
- * with transforms required for rendering.
+ * @return {PDFJS.PageViewport} Contains 'width' and 'height' properties
+ * along with transforms required for rendering.
*/
getViewport: function PDFPageProxy_getViewport(scale, rotate) {
- if (arguments.length < 2)
+ if (arguments.length < 2) {
rotate = this.rotate;
+ }
return new PDFJS.PageViewport(this.view, scale, rotate, 0, 0);
},
/**
@@ -4200,30 +2100,19 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
* annotation objects.
*/
getAnnotations: function PDFPageProxy_getAnnotations() {
- if (this.annotationsPromise)
+ if (this.annotationsPromise) {
return this.annotationsPromise;
+ }
- var promise = new PDFJS.LegacyPromise();
+ var promise = this.transport.getAnnotations(this.pageIndex);
this.annotationsPromise = promise;
- this.transport.getAnnotations(this.pageInfo.pageIndex);
return promise;
},
/**
* Begins the process of rendering a page to the desired context.
- * @param {Object} params A parameter object that supports:
- * {
- * canvasContext(required): A 2D context of a DOM Canvas object.,
- * textLayer(optional): An object that has beginLayout, endLayout, and
- * appendText functions.,
- * imageLayer(optional): An object that has beginLayout, endLayout and
- * appendImage functions.,
- * continueCallback(optional): 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.
- * }.
- * @return {RenderTask} An extended promise that is resolved when the page
- * finishes rendering (see RenderTask).
+ * @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;
@@ -4233,12 +2122,19 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
// this call to render.
this.pendingDestroy = false;
- // If there is no displayReadyPromise yet, then the operatorList was never
- // requested before. Make the request and create the promise.
- if (!this.displayReadyPromise) {
- this.receivingOperatorList = true;
- this.displayReadyPromise = new LegacyPromise();
- this.operatorList = {
+ 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
@@ -4246,18 +2142,24 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
this.stats.time('Page Request');
this.transport.messageHandler.send('RenderPageRequest', {
- pageIndex: this.pageNumber - 1
+ pageIndex: this.pageNumber - 1,
+ intent: renderingIntent
});
}
var internalRenderTask = new InternalRenderTask(complete, params,
- this.objs, this.commonObjs,
- this.operatorList, this.pageNumber);
- this.renderTasks.push(internalRenderTask);
+ this.objs,
+ this.commonObjs,
+ intentState.operatorList,
+ this.pageNumber);
+ if (!intentState.renderTasks) {
+ intentState.renderTasks = [];
+ }
+ intentState.renderTasks.push(internalRenderTask);
var renderTask = new RenderTask(internalRenderTask);
var self = this;
- this.displayReadyPromise.then(
+ intentState.displayReadyCapability.promise.then(
function pageDisplayReadyPromise(transparency) {
if (self.pendingDestroy) {
complete();
@@ -4273,9 +2175,9 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
);
function complete(error) {
- var i = self.renderTasks.indexOf(internalRenderTask);
+ var i = intentState.renderTasks.indexOf(internalRenderTask);
if (i >= 0) {
- self.renderTasks.splice(i, 1);
+ intentState.renderTasks.splice(i, 1);
}
if (self.cleanupAfterRender) {
@@ -4284,9 +2186,9 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
self._tryDestroy();
if (error) {
- renderTask.promise.reject(error);
+ internalRenderTask.capability.reject(error);
} else {
- renderTask.promise.resolve();
+ internalRenderTask.capability.resolve();
}
stats.timeEnd('Rendering');
stats.timeEnd('Overall');
@@ -4294,20 +2196,53 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
return renderTask;
},
+
/**
- * @return {Promise} That is resolved with the array of {@link BidiText}
- * objects that represent the page text content.
+ * @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() {
- var promise = new PDFJS.LegacyPromise();
- this.transport.messageHandler.send('GetTextContent', {
- pageIndex: this.pageNumber - 1
- },
- function textContentCallback(textContent) {
- promise.resolve(textContent);
- }
- );
- return promise;
+ return this.transport.messageHandler.sendWithPromise('GetTextContent', {
+ pageIndex: this.pageNumber - 1
+ });
},
/**
* Destroys resources allocated by the page.
@@ -4323,42 +2258,57 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
*/
_tryDestroy: function PDFPageProxy__destroy() {
if (!this.pendingDestroy ||
- this.renderTasks.length !== 0 ||
- this.receivingOperatorList) {
+ Object.keys(this.intentStates).some(function(intent) {
+ var intentState = this.intentStates[intent];
+ return (intentState.renderTasks.length !== 0 ||
+ intentState.receivingOperatorList);
+ }, this)) {
return;
}
- delete this.operatorList;
- delete this.displayReadyPromise;
+ 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) {
- this.displayReadyPromise.resolve(transparency);
+ _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) {
+ _renderPageChunk: function PDFPageProxy_renderPageChunk(operatorListChunk,
+ intent) {
+ var intentState = this.intentStates[intent];
+ var i, ii;
// Add the new chunk to the current operator list.
- for (var i = 0, ii = operatorListChunk.length; i < ii; i++) {
- this.operatorList.fnArray.push(operatorListChunk.fnArray[i]);
- this.operatorList.argsArray.push(operatorListChunk.argsArray[i]);
+ for (i = 0, ii = operatorListChunk.length; i < ii; i++) {
+ intentState.operatorList.fnArray.push(operatorListChunk.fnArray[i]);
+ intentState.operatorList.argsArray.push(
+ operatorListChunk.argsArray[i]);
}
- this.operatorList.lastChunk = operatorListChunk.lastChunk;
+ intentState.operatorList.lastChunk = operatorListChunk.lastChunk;
// Notify all the rendering tasks there are more operators to be consumed.
- for (var i = 0; i < this.renderTasks.length; i++) {
- this.renderTasks[i].operatorListChanged();
+ for (i = 0; i < intentState.renderTasks.length; i++) {
+ intentState.renderTasks[i].operatorListChanged();
}
if (operatorListChunk.lastChunk) {
- this.receivingOperatorList = false;
+ intentState.receivingOperatorList = false;
this._tryDestroy();
}
}
@@ -4371,18 +2321,18 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
* @ignore
*/
var WorkerTransport = (function WorkerTransportClosure() {
- function WorkerTransport(workerInitializedPromise, workerReadyPromise,
- pdfDataRangeTransport, progressCallback) {
+ function WorkerTransport(workerInitializedCapability, workerReadyCapability,
+ pdfDataRangeTransport, progressCallback) {
this.pdfDataRangeTransport = pdfDataRangeTransport;
- this.workerReadyPromise = workerReadyPromise;
+ this.workerInitializedCapability = workerInitializedCapability;
+ this.workerReadyCapability = workerReadyCapability;
this.progressCallback = progressCallback;
this.commonObjs = new PDFObjects();
this.pageCache = [];
this.pagePromises = [];
- this.embeddedFontsUsed = false;
-
+ this.downloadInfoCapability = createPromiseCapability();
this.passwordCallback = null;
// If worker support isn't disabled explicit and the browser has worker
@@ -4390,6 +2340,7 @@ var WorkerTransport = (function WorkerTransportClosure() {
// 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) {
@@ -4411,13 +2362,9 @@ var WorkerTransport = (function WorkerTransportClosure() {
PDFJS.postMessageTransfers = false;
}
this.setupMessageHandler(messageHandler);
- workerInitializedPromise.resolve();
+ workerInitializedCapability.resolve();
} else {
- globalScope.PDFJS.disableWorker = true;
- this.loadFakeWorkerFiles().then(function() {
- this.setupFakeWorker();
- workerInitializedPromise.resolve();
- }.bind(this));
+ this.setupFakeWorker();
}
}.bind(this));
@@ -4425,7 +2372,7 @@ var WorkerTransport = (function WorkerTransportClosure() {
// 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, null, [testObj.buffer]);
+ messageHandler.send('test', testObj, [testObj.buffer]);
} catch (ex) {
info('Cannot use postMessage transfers');
testObj[0] = 0;
@@ -4436,20 +2383,17 @@ var WorkerTransport = (function WorkerTransportClosure() {
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.
- globalScope.PDFJS.disableWorker = true;
- this.loadFakeWorkerFiles().then(function() {
- this.setupFakeWorker();
- workerInitializedPromise.resolve();
- }.bind(this));
+ this.setupFakeWorker();
}
WorkerTransport.prototype = {
destroy: function WorkerTransport_destroy() {
this.pageCache = [];
this.pagePromises = [];
var self = this;
- this.messageHandler.send('Terminate', null, function () {
+ this.messageHandler.sendWithPromise('Terminate', null).then(function () {
FontLoader.clear();
if (self.worker) {
self.worker.terminate();
@@ -4457,35 +2401,45 @@ var WorkerTransport = (function WorkerTransportClosure() {
});
},
- loadFakeWorkerFiles: function WorkerTransport_loadFakeWorkerFiles() {
- if (!PDFJS.fakeWorkerFilesLoadedPromise) {
- PDFJS.fakeWorkerFilesLoadedPromise = new LegacyPromise();
+ 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.
- Util.loadScript(PDFJS.workerSrc, function() {
- PDFJS.fakeWorkerFilesLoadedPromise.resolve();
- });
+//#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
}
- return PDFJS.fakeWorkerFilesLoadedPromise;
- },
+ 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() {}
+ };
- setupFakeWorker: function WorkerTransport_setupFakeWorker() {
- 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);
- 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);
- // 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:
@@ -4511,6 +2465,12 @@ var WorkerTransport = (function WorkerTransportClosure() {
});
});
+ pdfDataRangeTransport.addProgressiveReadListener(function(chunk) {
+ messageHandler.send('OnDataRange', {
+ chunk: chunk
+ });
+ });
+
messageHandler.on('RequestDataRange',
function transportDataRange(data) {
pdfDataRangeTransport.requestDataRange(data.begin, data.end);
@@ -4519,71 +2479,83 @@ var WorkerTransport = (function WorkerTransportClosure() {
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.workerReadyPromise.resolve(pdfDocument);
+ this.workerReadyCapability.resolve(pdfDocument);
}, this);
- messageHandler.on('NeedPassword', function transportPassword(data) {
+ messageHandler.on('NeedPassword',
+ function transportNeedPassword(exception) {
if (this.passwordCallback) {
return this.passwordCallback(updatePassword,
PasswordResponses.NEED_PASSWORD);
}
- this.workerReadyPromise.reject(data.exception.message, data.exception);
+ this.workerReadyCapability.reject(
+ new PasswordException(exception.message, exception.code));
}, this);
- messageHandler.on('IncorrectPassword', function transportBadPass(data) {
+ messageHandler.on('IncorrectPassword',
+ function transportIncorrectPassword(exception) {
if (this.passwordCallback) {
return this.passwordCallback(updatePassword,
PasswordResponses.INCORRECT_PASSWORD);
}
- this.workerReadyPromise.reject(data.exception.message, data.exception);
+ this.workerReadyCapability.reject(
+ new PasswordException(exception.message, exception.code));
}, this);
- messageHandler.on('InvalidPDF', function transportInvalidPDF(data) {
- this.workerReadyPromise.reject(data.exception.name, data.exception);
+ messageHandler.on('InvalidPDF', function transportInvalidPDF(exception) {
+ this.workerReadyCapability.reject(
+ new InvalidPDFException(exception.message));
}, this);
- messageHandler.on('MissingPDF', function transportMissingPDF(data) {
- this.workerReadyPromise.reject(data.exception.message, data.exception);
+ messageHandler.on('MissingPDF', function transportMissingPDF(exception) {
+ this.workerReadyCapability.reject(
+ new MissingPDFException(exception.message));
}, this);
- messageHandler.on('UnknownError', function transportUnknownError(data) {
- this.workerReadyPromise.reject(data.exception.message, data.exception);
+ messageHandler.on('UnexpectedResponse',
+ function transportUnexpectedResponse(exception) {
+ this.workerReadyCapability.reject(
+ new UnexpectedResponseException(exception.message, exception.status));
}, this);
- messageHandler.on('GetPage', function transportPage(data) {
- var pageInfo = data.pageInfo;
- var page = new PDFPageProxy(pageInfo, this);
- this.pageCache[pageInfo.pageIndex] = page;
- var promise = this.pagePromises[pageInfo.pageIndex];
- promise.resolve(page);
+ messageHandler.on('UnknownError',
+ function transportUnknownError(exception) {
+ this.workerReadyCapability.reject(
+ new UnknownErrorException(exception.message, exception.details));
}, this);
- messageHandler.on('GetAnnotations', function transportAnnotations(data) {
- var annotations = data.annotations;
- var promise = this.pageCache[data.pageIndex].annotationsPromise;
- promise.resolve(annotations);
+ 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);
+ page._startRenderPage(data.transparency, data.intent);
}, this);
messageHandler.on('RenderPageChunk', function transportRender(data) {
var page = this.pageCache[data.pageIndex];
- page._renderPageChunk(data.operatorList);
+ 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))
+ if (this.commonObjs.hasData(id)) {
return;
+ }
switch (type) {
case 'Font':
@@ -4596,7 +2568,7 @@ var WorkerTransport = (function WorkerTransportClosure() {
this.commonObjs.resolve(id, error);
break;
} else {
- font = new FontFace(exportedData);
+ font = new FontFaceObject(exportedData);
}
FontLoader.bind(
@@ -4619,21 +2591,23 @@ var WorkerTransport = (function WorkerTransportClosure() {
var pageIndex = data[1];
var type = data[2];
var pageProxy = this.pageCache[pageIndex];
- if (pageProxy.objs.hasData(id))
+ var imageData;
+ if (pageProxy.objs.hasData(id)) {
return;
+ }
switch (type) {
case 'JpegStream':
- var imageData = data[3];
+ imageData = data[3];
loadJpegStream(id, imageData, pageProxy.objs);
break;
case 'Image':
- var imageData = data[3];
+ 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 ('data' in imageData &&
+ if (imageData && 'data' in imageData &&
imageData.data.length > MAX_IMAGE_SIZE_TO_STORE) {
pageProxy.cleanupAfterRender = true;
}
@@ -4652,132 +2626,155 @@ var WorkerTransport = (function WorkerTransportClosure() {
}
}, this);
- messageHandler.on('DocError', function transportDocError(data) {
- this.workerReadyPromise.reject(data);
- }, this);
-
messageHandler.on('PageError', function transportError(data) {
var page = this.pageCache[data.pageNum - 1];
- if (page.displayReadyPromise)
- page.displayReadyPromise.reject(data.error);
- else
+ var intentState = page.intentStates[data.intent];
+ if (intentState.displayReadyCapability) {
+ intentState.displayReadyCapability.reject(data.error);
+ } else {
error(data.error);
+ }
}, this);
- messageHandler.on('JpegDecode', function(data, deferred) {
+ messageHandler.on('JpegDecode', function(data) {
var imageUrl = data[0];
var components = data[1];
- if (components != 3 && components != 1)
- error('Only 3 component or 1 component can be returned');
+ if (components !== 3 && components !== 1) {
+ return Promise.reject(
+ new Error('Only 3 components or 1 component can be returned'));
+ }
- var img = new Image();
- img.onload = (function messageHandler_onloadClosure() {
- 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;
+ 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 (var 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];
+ 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];
+ }
}
- } else if (components == 1) {
- for (var i = 0, j = 0; i < rgbaLength; i += 4, j++) {
- buf[j] = data[i];
- }
- }
- deferred.resolve({ data: buf, width: width, height: height});
- }).bind(this);
- img.src = imageUrl;
+ 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(source) {
source.disableAutoFetch = PDFJS.disableAutoFetch;
+ source.disableStream = PDFJS.disableStream;
source.chunkedViewerLoading = !!this.pdfDataRangeTransport;
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(promise) {
- this.messageHandler.send('GetData', null, function(data) {
- promise.resolve(data);
- });
+ getData: function WorkerTransport_getData() {
+ return this.messageHandler.sendWithPromise('GetData', null);
},
- dataLoaded: function WorkerTransport_dataLoaded() {
- if (this.dataLoadedPromise) {
- return this.dataLoadedPromise;
+ getPage: function WorkerTransport_getPage(pageNumber, capability) {
+ if (pageNumber <= 0 || pageNumber > this.numPages ||
+ (pageNumber|0) !== pageNumber) {
+ return Promise.reject(new Error('Invalid page request'));
}
- var promise = new PDFJS.LegacyPromise();
- this.messageHandler.send('DataLoaded', null, function(args) {
- promise.resolve(args);
- });
- this.dataLoadedPromise = promise;
- return promise;
- },
- getPage: function WorkerTransport_getPage(pageNumber, promise) {
var pageIndex = pageNumber - 1;
- if (pageIndex in this.pagePromises)
+ if (pageIndex in this.pagePromises) {
return this.pagePromises[pageIndex];
- var promise = new PDFJS.LegacyPromise();
+ }
+ 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;
- this.messageHandler.send('GetPageRequest', { pageIndex: pageIndex });
return promise;
},
getPageIndex: function WorkerTransport_getPageIndexByRef(ref) {
- var promise = new PDFJS.LegacyPromise();
- this.messageHandler.send('GetPageIndex', { ref: ref },
- function (pageIndex) {
- promise.resolve(pageIndex);
- }
- );
- return promise;
+ return this.messageHandler.sendWithPromise('GetPageIndex', { ref: ref });
},
getAnnotations: function WorkerTransport_getAnnotations(pageIndex) {
- this.messageHandler.send('GetAnnotationsRequest',
+ return this.messageHandler.sendWithPromise('GetAnnotations',
{ pageIndex: pageIndex });
},
getDestinations: function WorkerTransport_getDestinations() {
- var promise = new PDFJS.LegacyPromise();
- this.messageHandler.send('GetDestinations', null,
- function transportDestinations(destinations) {
- promise.resolve(destinations);
- }
- );
- return promise;
+ 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.send('Cleanup', null,
- function endCleanup() {
- for (var i = 0, ii = this.pageCache.length; i < ii; i++) {
- var page = this.pageCache[i];
- if (page) {
- page.destroy();
- }
+ 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)
- );
+ }
+ this.commonObjs.clear();
+ FontLoader.clear();
+ }.bind(this));
}
};
return WorkerTransport;
@@ -4802,11 +2799,12 @@ var PDFObjects = (function PDFObjectsClosure() {
* Ensures there is an object defined for `objId`.
*/
ensureObj: function PDFObjects_ensureObj(objId) {
- if (this.objs[objId])
+ if (this.objs[objId]) {
return this.objs[objId];
+ }
var obj = {
- promise: new LegacyPromise(),
+ capability: createPromiseCapability(),
data: null,
resolved: false
};
@@ -4828,7 +2826,7 @@ var PDFObjects = (function PDFObjectsClosure() {
// 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).promise.then(callback);
+ this.ensureObj(objId).capability.promise.then(callback);
return null;
}
@@ -4838,8 +2836,9 @@ var PDFObjects = (function PDFObjectsClosure() {
// If there isn't an object yet or the object isn't resolved, then the
// data isn't ready yet!
- if (!obj || !obj.resolved)
+ if (!obj || !obj.resolved) {
error('Requesting object that isn\'t resolved yet ' + objId);
+ }
return obj.data;
},
@@ -4852,7 +2851,7 @@ var PDFObjects = (function PDFObjectsClosure() {
obj.resolved = true;
obj.data = data;
- obj.promise.resolve(data);
+ obj.capability.resolve(data);
},
isResolved: function PDFObjects_isResolved(objId) {
@@ -4899,7 +2898,7 @@ var RenderTask = (function RenderTaskClosure() {
* Promise for rendering task completion.
* @type {Promise}
*/
- this.promise = new PDFJS.LegacyPromise();
+ this.promise = this.internalRenderTask.capability.promise;
}
RenderTask.prototype = /** @lends RenderTask.prototype */ {
@@ -4910,7 +2909,18 @@ var RenderTask = (function RenderTaskClosure() {
*/
cancel: function RenderTask_cancel() {
this.internalRenderTask.cancel();
- this.promise.reject(new Error('Rendering is cancelled'));
+ },
+
+ /**
+ * Registers callback 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(onFulfilled, onRejected);
}
};
@@ -4936,6 +2946,11 @@ var InternalRenderTask = (function InternalRenderTaskClosure() {
this.graphicsReadyCallback = null;
this.graphicsReady = false;
this.cancelled = false;
+ this.capability = createPromiseCapability();
+ // caching this-bound methods
+ this._continueBound = this._continue.bind(this);
+ this._scheduleNextBound = this._scheduleNext.bind(this);
+ this._nextBound = this._next.bind(this);
}
InternalRenderTask.prototype = {
@@ -4955,8 +2970,7 @@ var InternalRenderTask = (function InternalRenderTaskClosure() {
var params = this.params;
this.gfx = new CanvasGraphics(params.canvasContext, this.commonObjs,
- this.objs, params.textLayer,
- params.imageLayer);
+ this.objs, params.imageLayer);
this.gfx.beginDrawing(params.viewport, transparency);
this.operatorListIdx = 0;
@@ -4975,7 +2989,7 @@ var InternalRenderTask = (function InternalRenderTaskClosure() {
operatorListChanged: function InternalRenderTask_operatorListChanged() {
if (!this.graphicsReady) {
if (!this.graphicsReadyCallback) {
- this.graphicsReadyCallback = this._continue.bind(this);
+ this.graphicsReadyCallback = this._continueBound;
}
return;
}
@@ -4996,19 +3010,23 @@ var InternalRenderTask = (function InternalRenderTaskClosure() {
return;
}
if (this.params.continueCallback) {
- this.params.continueCallback(this._next.bind(this));
+ this.params.continueCallback(this._scheduleNextBound);
} else {
- this._next();
+ 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._continue.bind(this),
+ this._continueBound,
this.stepper);
if (this.operatorListIdx === this.operatorList.argsArray.length) {
this.running = false;
@@ -5035,8 +3053,8 @@ var Metadata = PDFJS.Metadata = (function MetadataClosure() {
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) :
+ chars += code >= 32 && code < 127 && code !== 60 && code !== 62 &&
+ code !== 38 && false ? String.fromCharCode(code) :
'' + (0x10000 + code).toString(16).substring(1) + ';';
}
return '>' + chars;
@@ -5066,20 +3084,22 @@ var Metadata = PDFJS.Metadata = (function MetadataClosure() {
if (rdf.nodeName.toLowerCase() !== 'rdf:rdf') { // Wrapped in
rdf = rdf.firstChild;
- while (rdf && rdf.nodeName.toLowerCase() !== 'rdf:rdf')
+ while (rdf && rdf.nodeName.toLowerCase() !== 'rdf:rdf') {
rdf = rdf.nextSibling;
+ }
}
var nodeName = (rdf) ? rdf.nodeName.toLowerCase() : null;
- if (!rdf || nodeName !== 'rdf:rdf' || !rdf.hasChildNodes())
+ 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')
+ if (desc.nodeName.toLowerCase() !== 'rdf:description') {
continue;
+ }
for (ii = 0, iLength = desc.childNodes.length; ii < iLength; ii++) {
if (desc.childNodes[ii].nodeName.toLowerCase() !== '#text') {
@@ -5109,8 +3129,17 @@ var Metadata = PDFJS.Metadata = (function MetadataClosure() {
// 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');
@@ -5244,7 +3273,7 @@ var CachedCanvases = (function CachedCanvasesClosure() {
getCanvas: function CachedCanvases_getCanvas(id, width, height,
trackTransform) {
var canvasEntry;
- if (id in cache) {
+ if (cache[id] !== undefined) {
canvasEntry = cache[id];
canvasEntry.canvas.width = width;
canvasEntry.canvas.height = height;
@@ -5261,7 +3290,14 @@ var CachedCanvases = (function CachedCanvasesClosure() {
return canvasEntry;
},
clear: function () {
- cache = {};
+ 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];
+ }
}
};
})();
@@ -5380,7 +3416,9 @@ function compileType3Glyph(imgData) {
var type = points[p], p0 = p, pp;
do {
var step = steps[type];
- do { p += step; } while (!points[p]);
+ do {
+ p += step;
+ } while (!points[p]);
pp = points[p];
if (pp !== 5 && pp !== 10) {
@@ -5431,6 +3469,7 @@ var CanvasExtraState = (function CanvasExtraStateClosure() {
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)
@@ -5445,16 +3484,10 @@ var CanvasExtraState = (function CanvasExtraStateClosure() {
this.textHScale = 1;
this.textRenderingMode = TextRenderingMode.FILL;
this.textRise = 0;
- // Color spaces
- this.fillColorSpace = ColorSpace.singletons.gray;
- this.fillColorSpaceObj = null;
- this.strokeColorSpace = ColorSpace.singletons.gray;
- this.strokeColorSpaceObj = null;
- this.fillColorObj = null;
- this.strokeColorObj = null;
// 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;
@@ -5480,8 +3513,10 @@ 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, textLayer, imageLayer) {
+ function CanvasGraphics(canvasCtx, commonObjs, objs, imageLayer) {
this.ctx = canvasCtx;
this.current = new CanvasExtraState();
this.stateStack = [];
@@ -5491,7 +3526,6 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
this.xobjs = null;
this.commonObjs = commonObjs;
this.objs = objs;
- this.textLayer = textLayer;
this.imageLayer = imageLayer;
this.groupStack = [];
this.processingType3 = null;
@@ -5506,6 +3540,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
if (canvasCtx) {
addContextCurrentTransform(canvasCtx);
}
+ this.cachedGetSinglePixelWidth = null;
}
function putBinaryImageData(ctx, imgData) {
@@ -5520,74 +3555,147 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
// 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 rowsInFullChunks = 16;
- var fullChunks = (imgData.height / rowsInFullChunks) | 0;
- var rowsInLastChunk = imgData.height - fullChunks * rowsInFullChunks;
- var elemsInFullChunks = imgData.width * rowsInFullChunks * 4;
- var elemsInLastChunk = imgData.width * rowsInLastChunk * 4;
+ 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(imgData.width, rowsInFullChunks);
- var srcPos = 0;
+ var chunkImgData = ctx.createImageData(width, FULL_CHUNK_HEIGHT);
+ var srcPos = 0, destPos;
var src = imgData.data;
- var dst = chunkImgData.data;
- var haveSetAndSubarray = 'set' in dst && 'subarray' in src;
+ var dest = chunkImgData.data;
+ var i, j, thisChunkHeight, elemsInThisChunk;
- // Do all the full-size chunks.
- for (var i = 0; i < fullChunks; i++) {
- if (haveSetAndSubarray) {
- dst.set(src.subarray(srcPos, srcPos + elemsInFullChunks));
- srcPos += elemsInFullChunks;
- } else {
- for (var j = 0; j < elemsInFullChunks; j++) {
- chunkImgData.data[j] = imgData.data[srcPos++];
- }
- }
- ctx.putImageData(chunkImgData, 0, i * rowsInFullChunks);
- }
+ // 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;
+ }
- // Do the final, partial chunk, if required.
- if (rowsInLastChunk !== 0) {
- if (haveSetAndSubarray) {
- dst.set(src.subarray(srcPos, srcPos + elemsInLastChunk));
- srcPos += elemsInLastChunk;
- } else {
- for (var j = 0; j < elemsInLastChunk; j++) {
- chunkImgData.data[j] = imgData.data[srcPos++];
+ 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);
}
- // This (conceptually) puts pixels past the bounds of the canvas. But
- // that's ok; any such pixels are ignored.
- ctx.putImageData(chunkImgData, 0, fullChunks * rowsInFullChunks);
+ } 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 width = imgData.width, height = imgData.height;
- var tmpImgData = ctx.createImageData(width, height);
- var data = imgData.data;
- var tmpImgDataPixels = tmpImgData.data;
- var dataPos = 0;
+ 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;
- // Expand the mask so it can be used by the canvas. Any required inversion
- // has already been handled.
- var tmpPos = 3; // alpha component offset
- for (var i = 0; i < height; i++) {
- var mask = 0;
- for (var j = 0; j < width; j++) {
- if (!mask) {
- var elem = data[dataPos++];
- mask = 128;
+ 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;
}
- if (!(elem & mask)) {
- tmpImgDataPixels[tmpPos] = 255;
- }
- tmpPos += 4;
- mask >>= 1;
}
+ ctx.putImageData(chunkImgData, 0, i * FULL_CHUNK_HEIGHT);
}
-
- ctx.putImageData(tmpImgData, 0, 0);
}
function copyCtxState(sourceCtx, destCtx) {
@@ -5596,84 +3704,104 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
'globalCompositeOperation', 'font'];
for (var i = 0, ii = properties.length; i < ii; i++) {
var property = properties[i];
- if (property in sourceCtx) {
+ if (sourceCtx[property] !== undefined) {
destCtx[property] = sourceCtx[property];
}
}
- if ('setLineDash' in sourceCtx) {
+ if (sourceCtx.setLineDash !== undefined) {
destCtx.setLineDash(sourceCtx.getLineDash());
destCtx.lineDashOffset = sourceCtx.lineDashOffset;
- } else if ('mozDash' in sourceCtx) {
+ } 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;
- var width = mask.width, height = mask.height;
- var addBackdropFn;
- if (smask.backdrop) {
- var cs = smask.colorSpace || ColorSpace.singletons.rgb;
- var backdrop = cs.getRgb(smask.backdrop, 0);
- addBackdropFn = function (r0, g0, b0, bytes) {
- var length = bytes.length;
- for (var i = 3; i < length; i += 4) {
- var alpha = bytes[i] / 255;
- if (alpha === 0) {
- bytes[i - 3] = r0;
- bytes[i - 2] = g0;
- bytes[i - 1] = b0;
- } else if (alpha < 1) {
- var alpha_ = 1 - alpha;
- bytes[i - 3] = (bytes[i - 3] * alpha + r0 * alpha_) | 0;
- bytes[i - 2] = (bytes[i - 2] * alpha + g0 * alpha_) | 0;
- bytes[i - 1] = (bytes[i - 1] * alpha + b0 * alpha_) | 0;
- }
- }
- }.bind(null, backdrop[0], backdrop[1], backdrop[2]);
- } else {
- addBackdropFn = function () {};
+ 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;
}
-
- var composeFn;
- if (smask.subtype === 'Luminosity') {
- composeFn = function (maskDataBytes, layerDataBytes) {
- var length = maskDataBytes.length;
- for (var i = 3; i < length; i += 4) {
- var y = ((maskDataBytes[i - 3] * 77) + // * 0.3 / 255 * 0x10000
- (maskDataBytes[i - 2] * 152) + // * 0.59 ....
- (maskDataBytes[i - 1] * 28)) | 0; // * 0.11 ....
- layerDataBytes[i] = (layerDataBytes[i] * y) >> 16;
- }
- };
- } else {
- composeFn = function (maskDataBytes, layerDataBytes) {
- var length = maskDataBytes.length;
- for (var i = 3; i < length; i += 4) {
- var alpha = maskDataBytes[i];
- layerDataBytes[i] = (layerDataBytes[i] * alpha / 255) | 0;
- }
- };
- }
-
- // processing image in chunks to save memory
- var chunkSize = 16;
- 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);
-
- addBackdropFn(maskData.data);
- composeFn(maskData.data, layerData.data);
-
- maskCtx.putImageData(layerData, 0, row);
- }
-
- ctx.setTransform(1, 0, 0, 1, 0, 0);
- ctx.drawImage(mask, smask.offsetX, smask.offsetY);
+ genericComposeSMask(maskCtx, layerCtx, mask.width, mask.height,
+ smask.subtype, backdrop);
+ ctx.drawImage(mask, 0, 0);
}
var LINE_CAP_STYLES = ['butt', 'round', 'square'];
@@ -5702,13 +3830,12 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
}
var transform = viewport.transform;
- this.baseTransform = transform.slice();
+
this.ctx.save();
this.ctx.transform.apply(this.ctx, transform);
- if (this.textLayer) {
- this.textLayer.beginLayout();
- }
+ this.baseTransform = this.ctx.mozCurrentTransform.slice();
+
if (this.imageLayer) {
this.imageLayer.beginLayout();
}
@@ -5724,20 +3851,21 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
var argsArrayLen = argsArray.length;
// Sometimes the OperatorList to execute is empty.
- if (argsArrayLen == i) {
+ if (argsArrayLen === i) {
return i;
}
- var executionEndIdx;
- var endTime = Date.now() + EXECUTION_TIME;
+ 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;
- var deferred = Promise.resolve();
while (true) {
- if (stepper && i === stepper.nextBreakPoint) {
+ if (stepper !== undefined && i === stepper.nextBreakPoint) {
stepper.breakIt(i, continueCallback);
return i;
}
@@ -5750,16 +3878,13 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
var deps = argsArray[i];
for (var n = 0, nn = deps.length; n < nn; n++) {
var depObjId = deps[n];
- var common = depObjId.substring(0, 2) == 'g_';
+ 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 (!common && !objs.isResolved(depObjId)) {
- objs.get(depObjId, continueCallback);
- return i;
- }
- if (common && !commonObjs.isResolved(depObjId)) {
- commonObjs.get(depObjId, continueCallback);
+ if (!objsPool.isResolved(depObjId)) {
+ objsPool.get(depObjId, continueCallback);
return i;
}
}
@@ -5768,16 +3893,18 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
i++;
// If the entire operatorList was executed, stop as were done.
- if (i == argsArrayLen) {
+ if (i === argsArrayLen) {
return i;
}
- // If the execution took longer then a certain amount of time, schedule
- // to continue exeution after a short delay.
- // However, this is only possible if a 'continueCallback' is passed in.
- if (continueCallback && Date.now() > endTime) {
- deferred.then(continueCallback);
- 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
@@ -5788,10 +3915,8 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
endDrawing: function CanvasGraphics_endDrawing() {
this.ctx.restore();
CachedCanvases.clear();
+ WebGLUtils.clear();
- if (this.textLayer) {
- this.textLayer.endLayout();
- }
if (this.imageLayer) {
this.imageLayer.endLayout();
}
@@ -5813,7 +3938,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
},
setDash: function CanvasGraphics_setDash(dashArray, dashPhase) {
var ctx = this.ctx;
- if ('setLineDash' in ctx) {
+ if (ctx.setLineDash !== undefined) {
ctx.setLineDash(dashArray);
ctx.lineDashOffset = dashPhase;
} else {
@@ -5911,6 +4036,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
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);
@@ -5937,59 +4063,100 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
var old = this.current;
this.stateStack.push(old);
this.current = old.clone();
- if (this.current.activeSMask) {
- this.current.activeSMask = null;
- }
+ this.current.activeSMask = null;
},
restore: function CanvasGraphics_restore() {
- var prev = this.stateStack.pop();
- if (prev) {
- if (this.current.activeSMask) {
+ if (this.stateStack.length !== 0) {
+ if (this.current.activeSMask !== null) {
this.endSMaskGroup();
}
- this.current = prev;
+ 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
- moveTo: function CanvasGraphics_moveTo(x, y) {
- this.ctx.moveTo(x, y);
- this.current.setCurrentPoint(x, y);
- },
- lineTo: function CanvasGraphics_lineTo(x, y) {
- this.ctx.lineTo(x, y);
- this.current.setCurrentPoint(x, y);
- },
- curveTo: function CanvasGraphics_curveTo(x1, y1, x2, y2, x3, y3) {
- this.ctx.bezierCurveTo(x1, y1, x2, y2, x3, y3);
- this.current.setCurrentPoint(x3, y3);
- },
- curveTo2: function CanvasGraphics_curveTo2(x2, y2, x3, y3) {
+ constructPath: function CanvasGraphics_constructPath(ops, args) {
+ var ctx = this.ctx;
var current = this.current;
- this.ctx.bezierCurveTo(current.x, current.y, x2, y2, x3, y3);
- current.setCurrentPoint(x3, y3);
- },
- curveTo3: function CanvasGraphics_curveTo3(x1, y1, x3, y3) {
- this.curveTo(x1, y1, x3, y3, x3, y3);
- this.current.setCurrentPoint(x3, y3);
+ 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();
},
- rectangle: function CanvasGraphics_rectangle(x, y, width, height) {
- this.ctx.rect(x, y, width, height);
- },
stroke: function CanvasGraphics_stroke(consumePath) {
consumePath = typeof consumePath !== 'undefined' ? consumePath : true;
var ctx = this.ctx;
var strokeColor = this.current.strokeColor;
- if (this.current.lineWidth === 0)
- ctx.lineWidth = this.getSinglePixelWidth();
+ // 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;
@@ -6004,8 +4171,9 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
} else {
ctx.stroke();
}
- if (consumePath)
+ if (consumePath) {
this.consumePath();
+ }
// Restore the global alpha to the fill alpha
ctx.globalAlpha = this.current.fillAlpha;
},
@@ -6017,31 +4185,31 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
consumePath = typeof consumePath !== 'undefined' ? consumePath : true;
var ctx = this.ctx;
var fillColor = this.current.fillColor;
+ var isPatternFill = this.current.patternFill;
var needRestore = false;
- if (fillColor && fillColor.hasOwnProperty('type') &&
- fillColor.type === 'Pattern') {
+ if (isPatternFill) {
ctx.save();
ctx.fillStyle = fillColor.getPattern(ctx, this);
needRestore = true;
}
if (this.pendingEOFill) {
- if ('mozFillRule' in this.ctx) {
- this.ctx.mozFillRule = 'evenodd';
- this.ctx.fill();
- this.ctx.mozFillRule = 'nonzero';
+ if (ctx.mozFillRule !== undefined) {
+ ctx.mozFillRule = 'evenodd';
+ ctx.fill();
+ ctx.mozFillRule = 'nonzero';
} else {
try {
- this.ctx.fill('evenodd');
+ ctx.fill('evenodd');
} catch (ex) {
// shouldn't really happen, but browsers might think differently
- this.ctx.fill();
+ ctx.fill();
}
}
this.pendingEOFill = false;
} else {
- this.ctx.fill();
+ ctx.fill();
}
if (needRestore) {
@@ -6089,16 +4257,17 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
// 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() {
- if (!('pendingTextPaths' in this)) {
- this.ctx.beginPath();
- return;
- }
var paths = this.pendingTextPaths;
var ctx = this.ctx;
+ if (paths === undefined) {
+ ctx.beginPath();
+ return;
+ }
ctx.save();
ctx.beginPath();
@@ -6129,11 +4298,12 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
var fontObj = this.commonObjs.get(fontRefName);
var current = this.current;
- if (!fontObj)
+ if (!fontObj) {
error('Can\'t find font for ' + fontRefName);
+ }
- current.fontMatrix = fontObj.fontMatrix ? fontObj.fontMatrix :
- FONT_IDENTITY_MATRIX;
+ 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.
@@ -6154,8 +4324,9 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
this.current.font = fontObj;
this.current.fontSize = size;
- if (fontObj.coded)
+ 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') :
@@ -6168,9 +4339,9 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
// 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 ? size : MIN_FONT_SIZE;
- this.current.fontSizeScale = browserFontSize != MIN_FONT_SIZE ? 1.0 :
- size / MIN_FONT_SIZE;
+ 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;
@@ -6191,6 +4362,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
},
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;
@@ -6198,51 +4370,13 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
nextLine: function CanvasGraphics_nextLine() {
this.moveText(0, this.current.leading);
},
- applyTextTransforms: function CanvasGraphics_applyTextTransforms() {
- var ctx = this.ctx;
- var current = this.current;
- ctx.transform.apply(ctx, current.textMatrix);
- ctx.translate(current.x, current.y + current.textRise);
- if (current.fontDirection > 0) {
- ctx.scale(current.textHScale, -1);
- } else {
- ctx.scale(-current.textHScale, 1);
- }
- },
- createTextGeometry: function CanvasGraphics_createTextGeometry() {
- var geometry = {};
- var ctx = this.ctx;
- var font = this.current.font;
- var ctxMatrix = ctx.mozCurrentTransform;
- var a = ctxMatrix[0], b = ctxMatrix[1], c = ctxMatrix[2];
- var d = ctxMatrix[3], e = ctxMatrix[4], f = ctxMatrix[5];
- var sx = (a >= 0) ?
- Math.sqrt((a * a) + (b * b)) : -Math.sqrt((a * a) + (b * b));
- var sy = (d >= 0) ?
- Math.sqrt((c * c) + (d * d)) : -Math.sqrt((c * c) + (d * d));
- var angle = Math.atan2(b, a);
- var x = e;
- var y = f;
- geometry.x = x;
- geometry.y = y;
- geometry.hScale = sx;
- geometry.vScale = sy;
- geometry.angle = angle;
- geometry.spaceWidth = font.spaceWidth;
- geometry.fontName = font.loadedName;
- geometry.fontFamily = font.fallbackName;
- geometry.fontSize = this.current.fontSize;
- geometry.ascent = font.ascent;
- geometry.descent = font.descent;
- return geometry;
- },
- paintChar: function (character, x, y) {
+ paintChar: function CanvasGraphics_paintChar(character, x, y) {
var ctx = this.ctx;
var current = this.current;
var font = current.font;
- var fontSize = current.fontSize / current.fontSizeScale;
var textRenderingMode = current.textRenderingMode;
+ var fontSize = current.fontSize / current.fontSizeScale;
var fillStrokeMode = textRenderingMode &
TextRenderingMode.FILL_STROKE_MASK;
var isAddToPathSet = !!(textRenderingMode &
@@ -6307,234 +4441,196 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
return shadow(this, 'isFontSubpixelAAEnabled', enabled);
},
- showText: function CanvasGraphics_showText(glyphs, skipTextSelection) {
- var ctx = this.ctx;
+ 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 textHScale = current.textHScale * current.fontDirection;
- var fontMatrix = current.fontMatrix || FONT_IDENTITY_MATRIX;
+ var fontDirection = current.fontDirection;
+ var textHScale = current.textHScale * fontDirection;
var glyphsLength = glyphs.length;
- var textLayer = this.textLayer;
- var geom;
- var textSelection = textLayer && !skipTextSelection ? true : false;
- var canvasWidth = 0.0;
var vertical = font.vertical;
var defaultVMetrics = font.defaultVMetrics;
+ var widthAdvanceScale = fontSize * current.fontMatrix[0];
- // Type3 fonts - each glyph is a "mini-PDF"
- if (font.coded) {
- ctx.save();
- ctx.transform.apply(ctx, current.textMatrix);
- ctx.translate(current.x, current.y);
+ var simpleFillText =
+ current.textRenderingMode === TextRenderingMode.FILL &&
+ !font.disableFontFace;
- ctx.scale(textHScale, 1);
+ ctx.save();
+ ctx.transform.apply(ctx, current.textMatrix);
+ ctx.translate(current.x, current.y + current.textRise);
- if (textSelection) {
- this.save();
- ctx.scale(1, -1);
- geom = this.createTextGeometry();
- this.restore();
- }
- for (var i = 0; i < glyphsLength; ++i) {
-
- var glyph = glyphs[i];
- if (glyph === null) {
- // word break
- this.ctx.translate(wordSpacing, 0);
- current.x += wordSpacing * textHScale;
- continue;
- }
-
- this.processingType3 = glyph;
- this.save();
- ctx.scale(fontSize, fontSize);
- ctx.transform.apply(ctx, fontMatrix);
- this.executeOperatorList(glyph.operatorList);
- this.restore();
-
- var transformed = Util.applyTransform([glyph.width, 0], fontMatrix);
- var width = (transformed[0] * fontSize + charSpacing) *
- current.fontDirection;
-
- ctx.translate(width, 0);
- current.x += width * textHScale;
-
- canvasWidth += width;
- }
- ctx.restore();
- this.processingType3 = null;
+ if (fontDirection > 0) {
+ ctx.scale(textHScale, -1);
} else {
- ctx.save();
- this.applyTextTransforms();
+ ctx.scale(textHScale, 1);
+ }
- var lineWidth = current.lineWidth;
- var a1 = current.textMatrix[0], b1 = current.textMatrix[1];
- var scale = Math.sqrt(a1 * a1 + b1 * b1);
- if (scale === 0 || lineWidth === 0)
- lineWidth = this.getSinglePixelWidth();
- else
- lineWidth /= scale;
+ 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 (textSelection)
- geom = this.createTextGeometry();
+ if (fontSizeScale !== 1.0) {
+ ctx.scale(fontSizeScale, fontSizeScale);
+ lineWidth /= fontSizeScale;
+ }
- 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;
}
- ctx.lineWidth = lineWidth;
-
- var x = 0;
- for (var i = 0; i < glyphsLength; ++i) {
- var glyph = glyphs[i];
- if (glyph === null) {
- // word break
- x += current.fontDirection * wordSpacing;
- continue;
- }
-
- var restoreNeeded = false;
- var character = glyph.fontChar;
- var vmetric = glyph.vmetric || defaultVMetrics;
- if (vertical) {
- var vx = glyph.vmetric ? vmetric[1] : glyph.width * 0.5;
- vx = -vx * fontSize * current.fontMatrix[0];
- var vy = vmetric[2] * fontSize * current.fontMatrix[0];
- }
- var width = vmetric ? -vmetric[0] : glyph.width;
- var charWidth = width * fontSize * current.fontMatrix[0] +
- charSpacing * current.fontDirection;
- var accent = glyph.accent;
-
- var scaledX, scaledY, scaledAccentX, scaledAccentY;
- if (!glyph.disabled) {
- if (vertical) {
- 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 /
- current.fontSize * current.fontSizeScale;
- var characterScaleX = width / measuredWidth;
- restoreNeeded = true;
- ctx.save();
- ctx.scale(characterScaleX, 1);
- scaledX /= characterScaleX;
- if (accent) {
- scaledAccentX /= characterScaleX;
- }
- }
-
- 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);
- }
- }
-
- x += charWidth;
-
- canvasWidth += charWidth;
-
- if (restoreNeeded) {
- ctx.restore();
- }
- }
+ var restoreNeeded = false;
+ var character = glyph.fontChar;
+ var accent = glyph.accent;
+ var scaledX, scaledY, scaledAccentX, scaledAccentY;
+ var width = glyph.width;
if (vertical) {
- current.y -= x * textHScale;
+ 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 {
- current.x += x * textHScale;
+ scaledX = x / fontSizeScale;
+ scaledY = 0;
}
- ctx.restore();
- }
- if (textSelection) {
- geom.canvasWidth = canvasWidth;
- if (vertical) {
- var VERTICAL_TEXT_ROTATION = Math.PI / 2;
- geom.angle += VERTICAL_TEXT_ROTATION;
+ 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;
}
- this.textLayer.appendText(geom);
- }
- return canvasWidth;
+ 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();
},
- showSpacedText: function CanvasGraphics_showSpacedText(arr) {
+
+ 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;
- // TJ array's number is independent from fontMatrix
- var textHScale = current.textHScale * 0.001 * current.fontDirection;
- var arrLength = arr.length;
- var textLayer = this.textLayer;
- var geom;
- var canvasWidth = 0.0;
- var textSelection = textLayer ? true : false;
- var vertical = font.vertical;
- var spacingAccumulator = 0;
+ 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 (textSelection) {
- ctx.save();
- this.applyTextTransforms();
- geom = this.createTextGeometry();
- ctx.restore();
+ if (isTextInvisible || fontSize === 0) {
+ return;
}
- for (var i = 0; i < arrLength; ++i) {
- var e = arr[i];
- if (isNum(e)) {
- var spacingLength = -e * fontSize * textHScale;
- if (vertical) {
- current.y += spacingLength;
- } else {
- current.x += spacingLength;
- }
+ ctx.save();
+ ctx.transform.apply(ctx, current.textMatrix);
+ ctx.translate(current.x, current.y);
- if (textSelection)
- spacingAccumulator += spacingLength;
- } else {
- var shownCanvasWidth = this.showText(e, true);
+ ctx.scale(textHScale, fontDirection);
- if (textSelection) {
- canvasWidth += spacingAccumulator + shownCanvasWidth;
- spacingAccumulator = 0;
- }
+ 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;
}
- }
- if (textSelection) {
- geom.canvasWidth = canvasWidth;
- if (vertical) {
- var VERTICAL_TEXT_ROTATION = Math.PI / 2;
- geom.angle += VERTICAL_TEXT_ROTATION;
+ var operatorList = font.charProcOperatorList[glyph.operatorListId];
+ if (!operatorList) {
+ warn('Type3 character \"' + glyph.operatorListId +
+ '\" is not available');
+ continue;
}
- this.textLayer.appendText(geom);
+ 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;
}
- },
- nextLineShowText: function CanvasGraphics_nextLineShowText(text) {
- this.nextLine();
- this.showText(text);
- },
- nextLineSetSpacingShowText:
- function CanvasGraphics_nextLineSetSpacingShowText(wordSpacing,
- charSpacing,
- text) {
- this.setWordSpacing(wordSpacing);
- this.setCharSpacing(charSpacing);
- this.nextLineShowText(text);
+ ctx.restore();
+ this.processingType3 = null;
},
// Type3 fonts
@@ -6550,114 +4646,40 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
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.rectangle(llx, lly, urx - llx, ury - lly);
+ this.ctx.rect(llx, lly, urx - llx, ury - lly);
this.clip();
this.endPath();
},
// Color
- setStrokeColorSpace: function CanvasGraphics_setStrokeColorSpace(raw) {
- this.current.strokeColorSpace = ColorSpace.fromIR(raw);
- },
- setFillColorSpace: function CanvasGraphics_setFillColorSpace(raw) {
- this.current.fillColorSpace = ColorSpace.fromIR(raw);
- },
- setStrokeColor: function CanvasGraphics_setStrokeColor(/*...*/) {
- var cs = this.current.strokeColorSpace;
- var rgbColor = cs.getRgb(arguments, 0);
- var color = Util.makeCssRgb(rgbColor);
- this.ctx.strokeStyle = color;
- this.current.strokeColor = color;
- },
- getColorN_Pattern: function CanvasGraphics_getColorN_Pattern(IR, cs) {
- if (IR[0] == 'TilingPattern') {
- var args = IR[1];
- var base = cs.base;
- var color;
- if (base) {
- var baseComps = base.numComps;
-
- color = base.getRgb(args, 0);
- }
- var pattern = new TilingPattern(IR, color, this.ctx, this.objs,
- this.commonObjs, this.baseTransform);
- } else if (IR[0] == 'RadialAxial' || IR[0] == 'Dummy') {
- var pattern = getShadingPatternFromIR(IR);
+ 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 {
- error('Unkown IR type ' + IR[0]);
+ pattern = getShadingPatternFromIR(IR);
}
return pattern;
},
setStrokeColorN: function CanvasGraphics_setStrokeColorN(/*...*/) {
- var cs = this.current.strokeColorSpace;
-
- if (cs.name == 'Pattern') {
- this.current.strokeColor = this.getColorN_Pattern(arguments, cs);
- } else {
- this.setStrokeColor.apply(this, arguments);
- }
- },
- setFillColor: function CanvasGraphics_setFillColor(/*...*/) {
- var cs = this.current.fillColorSpace;
- var rgbColor = cs.getRgb(arguments, 0);
- var color = Util.makeCssRgb(rgbColor);
- this.ctx.fillStyle = color;
- this.current.fillColor = color;
+ this.current.strokeColor = this.getColorN_Pattern(arguments);
},
setFillColorN: function CanvasGraphics_setFillColorN(/*...*/) {
- var cs = this.current.fillColorSpace;
-
- if (cs.name == 'Pattern') {
- this.current.fillColor = this.getColorN_Pattern(arguments, cs);
- } else {
- this.setFillColor.apply(this, arguments);
- }
- },
- setStrokeGray: function CanvasGraphics_setStrokeGray(gray) {
- this.current.strokeColorSpace = ColorSpace.singletons.gray;
-
- var rgbColor = this.current.strokeColorSpace.getRgb(arguments, 0);
- var color = Util.makeCssRgb(rgbColor);
- this.ctx.strokeStyle = color;
- this.current.strokeColor = color;
- },
- setFillGray: function CanvasGraphics_setFillGray(gray) {
- this.current.fillColorSpace = ColorSpace.singletons.gray;
-
- var rgbColor = this.current.fillColorSpace.getRgb(arguments, 0);
- var color = Util.makeCssRgb(rgbColor);
- this.ctx.fillStyle = color;
- this.current.fillColor = color;
+ this.current.fillColor = this.getColorN_Pattern(arguments);
+ this.current.patternFill = true;
},
setStrokeRGBColor: function CanvasGraphics_setStrokeRGBColor(r, g, b) {
- this.current.strokeColorSpace = ColorSpace.singletons.rgb;
-
- var rgbColor = this.current.strokeColorSpace.getRgb(arguments, 0);
- var color = Util.makeCssRgb(rgbColor);
+ var color = Util.makeCssRgb(r, g, b);
this.ctx.strokeStyle = color;
this.current.strokeColor = color;
},
setFillRGBColor: function CanvasGraphics_setFillRGBColor(r, g, b) {
- this.current.fillColorSpace = ColorSpace.singletons.rgb;
-
- var rgbColor = this.current.fillColorSpace.getRgb(arguments, 0);
- var color = Util.makeCssRgb(rgbColor);
- this.ctx.fillStyle = color;
- this.current.fillColor = color;
- },
- setStrokeCMYKColor: function CanvasGraphics_setStrokeCMYKColor(c, m, y, k) {
- this.current.strokeColorSpace = ColorSpace.singletons.cmyk;
-
- var color = Util.makeCssCmyk(arguments);
- this.ctx.strokeStyle = color;
- this.current.strokeColor = color;
- },
- setFillCMYKColor: function CanvasGraphics_setFillCMYKColor(c, m, y, k) {
- this.current.fillColorSpace = ColorSpace.singletons.cmyk;
-
- var color = Util.makeCssCmyk(arguments);
+ var color = Util.makeCssRgb(r, g, b);
this.ctx.fillStyle = color;
this.current.fillColor = color;
+ this.current.patternFill = false;
},
shadingFill: function CanvasGraphics_shadingFill(patternIR) {
@@ -6665,7 +4687,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
this.save();
var pattern = getShadingPatternFromIR(patternIR);
- ctx.fillStyle = pattern.getPattern(ctx, this);
+ ctx.fillStyle = pattern.getPattern(ctx, this, true);
var inv = ctx.mozCurrentTransformInverse;
if (inv) {
@@ -6710,15 +4732,16 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
this.save();
this.baseTransformStack.push(this.baseTransform);
- if (matrix && isArray(matrix) && 6 == matrix.length)
+ if (isArray(matrix) && 6 === matrix.length) {
this.transform.apply(this, matrix);
+ }
this.baseTransform = this.ctx.mozCurrentTransform;
- if (bbox && isArray(bbox) && 4 == bbox.length) {
+ if (isArray(bbox) && 4 === bbox.length) {
var width = bbox[2] - bbox[0];
var height = bbox[3] - bbox[1];
- this.rectangle(bbox[0], bbox[1], width, height);
+ this.ctx.rect(bbox[0], bbox[1], width, height);
this.clip();
this.endPath();
}
@@ -6774,8 +4797,19 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
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 drawnWidth = Math.max(Math.ceil(bounds[2] - bounds[0]), 1);
- var drawnHeight = Math.max(Math.ceil(bounds[3] - bounds[1]), 1);
+ 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) {
@@ -6788,8 +4822,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
// Since we created a new canvas that is just the size of the bounding box
// we have to translate the group ctx.
- var offsetX = bounds[0];
- var offsetY = bounds[1];
+ groupCtx.scale(1 / scaleX, 1 / scaleY);
groupCtx.translate(-offsetX, -offsetY);
groupCtx.transform.apply(groupCtx, currentTransform);
@@ -6800,15 +4833,17 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
context: groupCtx,
offsetX: offsetX,
offsetY: offsetY,
+ scaleX: scaleX,
+ scaleY: scaleY,
subtype: group.smask.subtype,
- backdrop: group.smask.backdrop,
- colorSpace: group.colorSpace && ColorSpace.fromIR(group.colorSpace)
+ 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.
@@ -6829,7 +4864,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
this.ctx = this.groupStack.pop();
// Turn off image smoothing to avoid sub pixel interpolation which can
// look kind of blurry for some pdfs.
- if ('imageSmoothingEnabled' in this.ctx) {
+ if (this.ctx.imageSmoothingEnabled !== undefined) {
this.ctx.imageSmoothingEnabled = false;
} else {
this.ctx.mozImageSmoothingEnabled = false;
@@ -6855,10 +4890,10 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
matrix) {
this.save();
- if (rect && isArray(rect) && 4 == rect.length) {
+ if (isArray(rect) && 4 === rect.length) {
var width = rect[2] - rect[0];
var height = rect[3] - rect[1];
- this.rectangle(rect[0], rect[1], width, height);
+ this.ctx.rect(rect[0], rect[1], width, height);
this.clip();
this.endPath();
}
@@ -6874,7 +4909,8 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
paintJpegXObject: function CanvasGraphics_paintJpegXObject(objId, w, h) {
var domImage = this.objs.get(objId);
if (!domImage) {
- error('Dependent image isn\'t ready yet');
+ warn('Dependent image isn\'t ready yet');
+ return;
}
this.save();
@@ -6902,11 +4938,12 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
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 && !('compiled' in glyph)) {
- var MAX_SIZE_TO_COMPILE = 1000;
+ 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});
@@ -6928,9 +4965,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
maskCtx.globalCompositeOperation = 'source-in';
- var fillColor = this.current.fillColor;
- maskCtx.fillStyle = (fillColor && fillColor.hasOwnProperty('type') &&
- fillColor.type === 'Pattern') ?
+ maskCtx.fillStyle = isPatternFill ?
fillColor.getPattern(maskCtx, this) : fillColor;
maskCtx.fillRect(0, 0, width, height);
@@ -6939,10 +4974,45 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
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;
@@ -6955,9 +5025,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
maskCtx.globalCompositeOperation = 'source-in';
- var fillColor = this.current.fillColor;
- maskCtx.fillStyle = (fillColor && fillColor.hasOwnProperty('type') &&
- fillColor.type === 'Pattern') ?
+ maskCtx.fillStyle = isPatternFill ?
fillColor.getPattern(maskCtx, this) : fillColor;
maskCtx.fillRect(0, 0, width, height);
@@ -6974,12 +5042,33 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
paintImageXObject: function CanvasGraphics_paintImageXObject(objId) {
var imgData = this.objs.get(objId);
- if (!imgData)
- error('Dependent image isn\'t ready yet');
+ 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;
@@ -6996,12 +5085,12 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
var c = currentTransform[2], d = currentTransform[3];
var heightScale = Math.max(Math.sqrt(c * c + d * d), 1);
- var imgToPaint;
+ var imgToPaint, tmpCanvas;
// instanceof HTMLElement does not work in jsdom node.js module
if (imgData instanceof HTMLElement || !imgData.data) {
imgToPaint = imgData;
} else {
- var tmpCanvas = CachedCanvases.getCanvas('inlineImage', width, height);
+ tmpCanvas = CachedCanvases.getCanvas('inlineImage', width, height);
var tmpCtx = tmpCanvas.context;
putBinaryImageData(tmpCtx, imgData);
imgToPaint = tmpCanvas.canvas;
@@ -7023,8 +5112,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
newHeight = Math.ceil(paintHeight / 2);
heightScale /= paintHeight / newHeight;
}
- var tmpCanvas = CachedCanvases.getCanvas(tmpCanvasId,
- newWidth, newHeight);
+ tmpCanvas = CachedCanvases.getCanvas(tmpCanvasId, newWidth, newHeight);
tmpCtx = tmpCanvas.context;
tmpCtx.clearRect(0, 0, newWidth, newHeight);
tmpCtx.drawImage(imgToPaint, 0, 0, paintWidth, paintHeight,
@@ -7081,6 +5169,11 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
}
},
+ paintSolidColorImageMask:
+ function CanvasGraphics_paintSolidColorImageMask() {
+ this.ctx.fillRect(0, 0, 1, 1);
+ },
+
// Marked content
markPoint: function CanvasGraphics_markPoint(tag) {
@@ -7112,33 +5205,37 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
// Helper functions
consumePath: function CanvasGraphics_consumePath() {
+ var ctx = this.ctx;
if (this.pendingClip) {
- if (this.pendingClip == EO_CLIP) {
- if ('mozFillRule' in this.ctx) {
- this.ctx.mozFillRule = 'evenodd';
- this.ctx.clip();
- this.ctx.mozFillRule = 'nonzero';
+ if (this.pendingClip === EO_CLIP) {
+ if (ctx.mozFillRule !== undefined) {
+ ctx.mozFillRule = 'evenodd';
+ ctx.clip();
+ ctx.mozFillRule = 'nonzero';
} else {
try {
- this.ctx.clip('evenodd');
+ ctx.clip('evenodd');
} catch (ex) {
// shouldn't really happen, but browsers might think differently
- this.ctx.clip();
+ ctx.clip();
}
}
} else {
- this.ctx.clip();
+ ctx.clip();
}
this.pendingClip = null;
}
- this.ctx.beginPath();
+ ctx.beginPath();
},
getSinglePixelWidth: function CanvasGraphics_getSinglePixelWidth(scale) {
- var inverse = this.ctx.mozCurrentTransformInverse;
- // max of the current horizontal and vertical scale
- return Math.sqrt(Math.max(
- (inverse[0] * inverse[0] + inverse[1] * inverse[1]),
- (inverse[2] * inverse[2] + inverse[3] * inverse[3])));
+ 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;
@@ -7158,6 +5255,424 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
+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 = {
@@ -7188,6 +5703,220 @@ ShadingIRs.RadialAxial = {
}
};
+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 {
@@ -7200,7 +5929,11 @@ ShadingIRs.Dummy = {
};
function getShadingPatternFromIR(raw) {
- return ShadingIRs[raw[0]].fromIR(raw);
+ var shadingIR = ShadingIRs[raw[0]];
+ if (!shadingIR) {
+ error('Unknown IR type: ' + raw[0]);
+ }
+ return shadingIR.fromIR(raw);
}
var TilingPattern = (function TilingPatternClosure() {
@@ -7212,7 +5945,6 @@ var TilingPattern = (function TilingPatternClosure() {
var MAX_PATTERN_SIZE = 3000; // 10in @ 300dpi shall be enough
function TilingPattern(IR, color, ctx, objs, commonObjs, baseTransform) {
- this.name = IR[1][0].name;
this.operatorList = IR[2];
this.matrix = IR[3] || [1, 0, 0, 1, 0, 0];
this.bbox = IR[4];
@@ -7239,7 +5971,6 @@ var TilingPattern = (function TilingPatternClosure() {
var color = this.color;
var objs = this.objs;
var commonObjs = this.commonObjs;
- var ctx = this.ctx;
info('TilingType: ' + tilingType);
@@ -7305,10 +6036,10 @@ var TilingPattern = (function TilingPatternClosure() {
},
clipBbox: function clipBbox(graphics, bbox, x0, y0, x1, y1) {
- if (bbox && isArray(bbox) && 4 == bbox.length) {
+ if (bbox && isArray(bbox) && bbox.length === 4) {
var bboxWidth = x1 - x0;
var bboxHeight = y1 - y0;
- graphics.rectangle(x0, y0, bboxWidth, bboxHeight);
+ graphics.ctx.rect(x0, y0, bboxWidth, bboxHeight);
graphics.clip();
graphics.endPath();
}
@@ -7323,8 +6054,7 @@ var TilingPattern = (function TilingPatternClosure() {
context.strokeStyle = ctx.strokeStyle;
break;
case PaintType.UNCOLORED:
- var rgbColor = ColorSpace.singletons.rgb.getRgb(color, 0);
- var cssColor = Util.makeCssRgb(rgbColor);
+ var cssColor = Util.makeCssRgb(color[0], color[1], color[2]);
context.fillStyle = cssColor;
context.strokeStyle = cssColor;
break;
@@ -7336,7 +6066,7 @@ var TilingPattern = (function TilingPatternClosure() {
getPattern: function TilingPattern_getPattern(ctx, owner) {
var temporaryPatternCanvas = this.createPatternCanvas(owner);
- var ctx = this.ctx;
+ ctx = this.ctx;
ctx.setTransform.apply(ctx, this.baseTransform);
ctx.transform.apply(ctx, this.matrix);
this.scaleToContext();
@@ -7355,21 +6085,29 @@ 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);
+ 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.
@@ -7407,23 +6145,39 @@ var FontLoader = {
},
isSyncFontLoadingSupported: (function detectSyncFontLoadingSupport() {
- if (isWorker)
+ 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)
+ if (m && m[1] >= 14) {
return true;
+ }
// TODO other browsers
+ if (userAgent === 'node') {
+ return true;
+ }
return false;
})(),
+ nativeFontFaces: [],
+
+ isFontLoadingAPISupported: !isWorker && !!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 = [], fontsToLoad = [];
+ var rules = [];
+ var fontsToLoad = [];
+ var fontLoadPromises = [];
for (var i = 0, ii = fonts.length; i < ii; i++) {
var font = fonts[i];
@@ -7434,15 +6188,26 @@ var FontLoader = {
}
font.attached = true;
- var rule = font.bindDOM();
- if (rule) {
- rules.push(rule);
- fontsToLoad.push(font);
+ 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 (rules.length > 0 && !this.isSyncFontLoadingSupported) {
+ 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();
@@ -7490,16 +6255,9 @@ var FontLoader = {
(data.charCodeAt(offset + 3) & 0xff);
}
- function string32(value) {
- return String.fromCharCode((value >> 24) & 0xff) +
- String.fromCharCode((value >> 16) & 0xff) +
- String.fromCharCode((value >> 8) & 0xff) +
- String.fromCharCode(value & 0xff);
- }
-
function spliceString(s, offset, remove, insert) {
- var chunk1 = data.substr(0, offset);
- var chunk2 = data.substr(offset + remove);
+ var chunk1 = s.substr(0, offset);
+ var chunk2 = s.substr(offset + remove);
return chunk1 + insert + chunk2;
}
@@ -7582,10 +6340,27 @@ var FontLoader = {
});
/** 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 FontFace = (function FontFaceClosure() {
- function FontFace(name, file, properties) {
+var FontFaceObject = (function FontFaceObjectClosure() {
+ function FontFaceObject(name, file, properties) {
this.compiledGlyphs = {};
if (arguments.length === 1) {
// importing translated data
@@ -7596,33 +6371,58 @@ var FontFace = (function FontFaceClosure() {
return;
}
}
- FontFace.prototype = {
- bindDOM: function FontFace_bindDOM() {
- if (!this.data)
+ FontFaceObject.prototype = {
+//#if !(MOZCENTRAL)
+ createNativeFontFace: function FontFaceObject_createNativeFontFace() {
+ if (!this.data) {
return null;
+ }
if (PDFJS.disableFontFace) {
this.disableFontFace = true;
return null;
}
- var data = bytesToString(this.data);
+ 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'].enabled) {
globalScope['FontInspector'].fontAdded(this, url);
+ }
return rule;
},
- getPathGenerator: function (objs, character) {
+
+ getPathGenerator: function FontLoader_getPathGenerator(objs, character) {
if (!(character in this.compiledGlyphs)) {
var js = objs.get(this.loadedName + '_path_' + character);
/*jshint -W054 */
@@ -7631,10 +6431,1407 @@ var FontFace = (function FontFaceClosure() {
return this.compiledGlyphs[character];
}
};
- return FontFace;
+ 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 || '';
+
+ 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.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') {
@@ -7648,4 +7845,3 @@ if (!PDFJS.workerSrc && typeof document !== 'undefined') {
})();
}
-
diff --git a/attachment_preview/static/lib/ViewerJS/pdf.worker.js b/attachment_preview/static/lib/ViewerJS/pdf.worker.js
index b3ef5ebf..9f1b4097 100644
--- a/attachment_preview/static/lib/ViewerJS/pdf.worker.js
+++ b/attachment_preview/static/lib/ViewerJS/pdf.worker.js
@@ -14,14 +14,16 @@
* 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 = '0.8.958';
-PDFJS.build = 'd45d7bc';
+PDFJS.version = '1.0.1040';
+PDFJS.build = '997096f';
(function pdfjsWrapper() {
// Use strict in our context only - users might not want it
@@ -50,7 +52,7 @@ PDFJS.build = 'd45d7bc';
var globalScope = (typeof window === 'undefined') ? this : window;
-var isWorker = (typeof window == 'undefined');
+var isWorker = (typeof window === 'undefined');
var FONT_IDENTITY_MATRIX = [0.001, 0, 0, 0.001, 0, 0];
@@ -67,6 +69,45 @@ var TextRenderingMode = {
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
@@ -172,7 +213,11 @@ var OPS = PDFJS.OPS = {
paintImageMaskXObjectGroup: 84,
paintImageXObject: 85,
paintInlineImageXObject: 86,
- paintInlineImageXObjectGroup: 87
+ 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
@@ -218,8 +263,9 @@ function backtrace() {
}
function assert(cond, msg) {
- if (!cond)
+ if (!cond) {
error(msg);
+ }
}
var UNSUPPORTED_FEATURES = PDFJS.UNSUPPORTED_FEATURES = {
@@ -250,18 +296,25 @@ var UnsupportedManager = PDFJS.UnsupportedManager =
// 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)
+ if (!url) {
return baseUrl;
- if (/^[a-z][a-z0-9+\-.]*:/i.test(url))
+ }
+ if (/^[a-z][a-z0-9+\-.]*:/i.test(url)) {
return url;
- if (url.charAt(0) == '/') {
+ }
+ var i;
+ if (url.charAt(0) === '/') {
// absolute path
- var i = baseUrl.indexOf('://');
- i = baseUrl.indexOf('/', i + 3);
+ 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;
+ var pathLength = baseUrl.length;
i = baseUrl.lastIndexOf('#');
pathLength = i >= 0 ? i : pathLength;
i = baseUrl.lastIndexOf('?', pathLength);
@@ -295,13 +348,6 @@ function isValidUrl(url, allowRelative) {
}
PDFJS.isValidUrl = isValidUrl;
-// In a well-formed PDF, |cond| holds. If it doesn't, subsequent
-// behavior is undefined.
-function assertWellFormed(cond, msg) {
- if (!cond)
- error(msg);
-}
-
function shadow(obj, prop, value) {
Object.defineProperty(obj, prop, { value: value,
enumerable: true,
@@ -327,6 +373,7 @@ var PasswordException = (function PasswordExceptionClosure() {
return PasswordException;
})();
+PDFJS.PasswordException = PasswordException;
var UnknownErrorException = (function UnknownErrorExceptionClosure() {
function UnknownErrorException(msg, details) {
@@ -340,6 +387,7 @@ var UnknownErrorException = (function UnknownErrorExceptionClosure() {
return UnknownErrorException;
})();
+PDFJS.UnknownErrorException = UnknownErrorException;
var InvalidPDFException = (function InvalidPDFExceptionClosure() {
function InvalidPDFException(msg) {
@@ -352,6 +400,7 @@ var InvalidPDFException = (function InvalidPDFExceptionClosure() {
return InvalidPDFException;
})();
+PDFJS.InvalidPDFException = InvalidPDFException;
var MissingPDFException = (function MissingPDFExceptionClosure() {
function MissingPDFException(msg) {
@@ -364,6 +413,22 @@ var MissingPDFException = (function MissingPDFExceptionClosure() {
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) {
@@ -405,33 +470,146 @@ var XRefParseException = (function XRefParseExceptionClosure() {
function bytesToString(bytes) {
- var str = '';
var length = bytes.length;
- for (var n = 0; n < length; ++n)
- str += String.fromCharCode(bytes[n]);
- return str;
+ 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) {
var length = str.length;
var bytes = new Uint8Array(length);
- for (var n = 0; n < length; ++n)
- bytes[n] = str.charCodeAt(n) & 0xFF;
+ 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() {}
- Util.makeCssRgb = function Util_makeCssRgb(rgb) {
- return 'rgb(' + rgb[0] + ',' + rgb[1] + ',' + rgb[2] + ')';
- };
+ var rgbBuf = ['rgb(', 0, ',', 0, ',', 0, ')'];
- Util.makeCssCmyk = function Util_makeCssCmyk(cmyk) {
- var rgb = ColorSpace.singletons.cmyk.getRgb(cmyk, 0);
- return Util.makeCssRgb(rgb);
+ // 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.
@@ -581,12 +759,11 @@ var Util = PDFJS.Util = (function UtilClosure() {
return num < 0 ? -1 : 1;
};
- // TODO(mack): Rename appendToArray
- Util.concatenateToArray = function concatenateToArray(arr1, arr2) {
+ Util.appendToArray = function Util_appendToArray(arr1, arr2) {
Array.prototype.push.apply(arr1, arr2);
};
- Util.prependToArray = function concatenateToArray(arr1, arr2) {
+ Util.prependToArray = function Util_prependToArray(arr1, arr2) {
Array.prototype.unshift.apply(arr1, arr2);
};
@@ -633,7 +810,22 @@ var Util = PDFJS.Util = (function UtilClosure() {
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;
@@ -697,7 +889,14 @@ var PageViewport = PDFJS.PageViewport = (function PageViewportClosure() {
this.height = height;
this.fontScale = scale;
}
- PageViewport.prototype = {
+ 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;
@@ -705,15 +904,41 @@ var PageViewport = PDFJS.PageViewport = (function PageViewportClosure() {
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);
}
@@ -734,19 +959,20 @@ var PDFStringTranslateTable = [
];
function stringToPDFString(str) {
- var i, n = str.length, str2 = '';
+ var i, n = str.length, strBuf = [];
if (str[0] === '\xFE' && str[1] === '\xFF') {
// UTF16BE BOM
- for (i = 2; i < n; i += 2)
- str2 += String.fromCharCode(
- (str.charCodeAt(i) << 8) | str.charCodeAt(i + 1));
+ 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)];
- str2 += code ? String.fromCharCode(code) : str.charAt(i);
+ strBuf.push(code ? String.fromCharCode(code) : str.charAt(i));
}
}
- return str2;
+ return strBuf.join('');
}
function stringToUTF8String(str) {
@@ -761,19 +987,19 @@ function isEmptyObj(obj) {
}
function isBool(v) {
- return typeof v == 'boolean';
+ return typeof v === 'boolean';
}
function isInt(v) {
- return typeof v == 'number' && ((v | 0) == v);
+ return typeof v === 'number' && ((v | 0) === v);
}
function isNum(v) {
- return typeof v == 'number';
+ return typeof v === 'number';
}
function isString(v) {
- return typeof v == 'string';
+ return typeof v === 'string';
}
function isNull(v) {
@@ -785,7 +1011,7 @@ function isName(v) {
}
function isCmd(v, cmd) {
- return v instanceof Cmd && (!cmd || v.cmd == cmd);
+ return v instanceof Cmd && (cmd === undefined || v.cmd === cmd);
}
function isDict(v, type) {
@@ -796,7 +1022,7 @@ function isDict(v, type) {
return true;
}
var dictType = v.get('Type');
- return isName(dictType) && dictType.name == type;
+ return isName(dictType) && dictType.name === type;
}
function isArray(v) {
@@ -804,52 +1030,47 @@ function isArray(v) {
}
function isStream(v) {
- return typeof v == 'object' && v !== null && v !== undefined &&
- ('getBytes' in v);
+ return typeof v === 'object' && v !== null && v.getBytes !== undefined;
}
function isArrayBuffer(v) {
- return typeof v == 'object' && v !== null && v !== undefined &&
- ('byteLength' in v);
+ return typeof v === 'object' && v !== null && v.byteLength !== undefined;
}
function isRef(v) {
return v instanceof Ref;
}
-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');
-}
+/**
+ * Promise Capability object.
+ *
+ * @typedef {Object} PromiseCapability
+ * @property {Promise} promise - A promise object.
+ * @property {function} resolve - Fullfills the promise.
+ * @property {function} reject - Rejects the promise.
+ */
/**
- * Legacy support for PDFJS Promise implementation.
- * TODO remove eventually
+ * Creates a promise capability object.
+ * @alias PDFJS.createPromiseCapability
+ *
+ * @return {PromiseCapability} A capability object contains:
+ * - a Promise, resolve and reject methods.
*/
-var LegacyPromise = PDFJS.LegacyPromise = (function LegacyPromiseClosure() {
- return function LegacyPromise() {
- var resolve, reject;
- var promise = new Promise(function (resolve_, reject_) {
- resolve = resolve_;
- reject = reject_;
- });
- promise.resolve = resolve;
- promise.reject = reject;
- return promise;
- };
-})();
+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 implment the
+ * 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.
@@ -884,12 +1105,25 @@ var LegacyPromise = PDFJS.LegacyPromise = (function LegacyPromiseClosure() {
};
}
if (typeof globalScope.Promise.resolve !== 'function') {
- globalScope.Promise.resolve = function (x) {
- return new globalScope.Promise(function (resolve) { resolve(x); });
+ 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;
@@ -906,7 +1140,7 @@ var LegacyPromise = PDFJS.LegacyPromise = (function LegacyPromiseClosure() {
pendingRejectionCheck: false,
scheduleHandlers: function scheduleHandlers(promise) {
- if (promise._status == STATUS_PENDING) {
+ if (promise._status === STATUS_PENDING) {
return;
}
@@ -932,10 +1166,10 @@ var LegacyPromise = PDFJS.LegacyPromise = (function LegacyPromiseClosure() {
try {
if (nextStatus === STATUS_RESOLVED) {
- if (typeof(handler.onResolve) == 'function') {
+ if (typeof handler.onResolve === 'function') {
nextValue = handler.onResolve(nextValue);
}
- } else if (typeof(handler.onReject) === 'function') {
+ } else if (typeof handler.onReject === 'function') {
nextValue = handler.onReject(nextValue);
nextStatus = STATUS_RESOLVED;
@@ -1010,7 +1244,11 @@ var LegacyPromise = PDFJS.LegacyPromise = (function LegacyPromiseClosure() {
function Promise(resolver) {
this._status = STATUS_PENDING;
this._handlers = [];
- resolver.call(this, this._resolve.bind(this), this._reject.bind(this));
+ 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
@@ -1046,8 +1284,9 @@ var LegacyPromise = PDFJS.LegacyPromise = (function LegacyPromiseClosure() {
}
results[i] = value;
unresolved--;
- if (unresolved === 0)
+ if (unresolved === 0) {
resolveAll(results);
+ }
};
})(i);
if (Promise.isPromise(promise)) {
@@ -1061,18 +1300,28 @@ var LegacyPromise = PDFJS.LegacyPromise = (function LegacyPromiseClosure() {
/**
* Checks if the value is likely a promise (has a 'then' function).
- * @return {boolean} true if x is thenable
+ * @return {boolean} true if value is thenable
*/
Promise.isPromise = function Promise_isPromise(value) {
return value && typeof value.then === 'function';
};
+
/**
* Creates resolved promise
- * @param x resolve value
+ * @param value resolve value
* @returns {Promise}
*/
- Promise.resolve = function Promise_resolve(x) {
- return new Promise(function (resolve) { resolve(x); });
+ 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 = {
@@ -1087,7 +1336,7 @@ var LegacyPromise = PDFJS.LegacyPromise = (function LegacyPromiseClosure() {
return;
}
- if (status == STATUS_RESOLVED &&
+ if (status === STATUS_RESOLVED &&
Promise.isPromise(value)) {
value.then(this._updateStatus.bind(this, STATUS_RESOLVED),
this._updateStatus.bind(this, STATUS_REJECTED));
@@ -1115,7 +1364,7 @@ var LegacyPromise = PDFJS.LegacyPromise = (function LegacyPromiseClosure() {
then: function Promise_then(onResolve, onReject) {
var nextPromise = new Promise(function (resolve, reject) {
- this.resolve = reject;
+ this.resolve = resolve;
this.reject = reject;
});
this._handlers.push({
@@ -1126,16 +1375,24 @@ var LegacyPromise = PDFJS.LegacyPromise = (function LegacyPromiseClosure() {
});
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)
+ while (str.length < length) {
str += pad;
+ }
return str;
}
function StatTimer() {
@@ -1145,17 +1402,21 @@ var StatTimer = (function StatTimerClosure() {
}
StatTimer.prototype = {
time: function StatTimer_time(name) {
- if (!this.enabled)
+ if (!this.enabled) {
return;
- if (name in this.started)
+ }
+ 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)
+ if (!this.enabled) {
return;
- if (!(name in this.started))
+ }
+ if (!(name in this.started)) {
warn('Timer has not been started for ' + name);
+ }
this.times.push({
'name': name,
'start': this.started[name],
@@ -1165,16 +1426,18 @@ var StatTimer = (function StatTimerClosure() {
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 (var i = 0, ii = times.length; i < ii; ++i) {
+ for (i = 0, ii = times.length; i < ii; ++i) {
var name = times[i]['name'];
- if (name.length > longest)
+ if (name.length > longest) {
longest = name.length;
+ }
}
- for (var i = 0, ii = times.length; i < ii; ++i) {
+ 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';
@@ -1186,8 +1449,9 @@ var StatTimer = (function StatTimerClosure() {
})();
PDFJS.createBlob = function createBlob(data, contentType) {
- if (typeof Blob !== 'undefined')
+ 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);
@@ -1225,7 +1489,7 @@ function MessageHandler(name, comObj) {
this.comObj = comObj;
this.callbackIndex = 1;
this.postMessageTransfers = true;
- var callbacks = this.callbacks = {};
+ var callbacksCapabilities = this.callbacksCapabilities = {};
var ah = this.actionHandler = {};
ah['console_log'] = [function ahConsoleLog(data) {
@@ -1242,35 +1506,40 @@ function MessageHandler(name, comObj) {
var data = event.data;
if (data.isReply) {
var callbackId = data.callbackId;
- if (data.callbackId in callbacks) {
- var callback = callbacks[callbackId];
- delete callbacks[callbackId];
- callback(data.data);
+ 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) {
- var deferred = {};
- var promise = new Promise(function (resolve, reject) {
- deferred.resolve = resolve;
- deferred.reject = reject;
- });
- deferred.promise = promise;
- promise.then(function(resolvedData) {
+ Promise.resolve().then(function () {
+ return action[0].call(action[1], data.data);
+ }).then(function (result) {
comObj.postMessage({
isReply: true,
callbackId: data.callbackId,
- data: resolvedData
+ data: result
+ });
+ }, function (reason) {
+ comObj.postMessage({
+ isReply: true,
+ callbackId: data.callbackId,
+ error: reason
});
});
- action[0].call(action[1], data.data, deferred);
} else {
action[0].call(action[1], data.data);
}
} else {
- error('Unkown action from worker: ' + data.action);
+ error('Unknown action from worker: ' + data.action);
}
};
}
@@ -1287,19 +1556,47 @@ MessageHandler.prototype = {
* 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 {function} [callback] Optional callback that will handle a reply.
* @param {Array} [transfers] Optional list of transfers/ArrayBuffers
*/
- send: function messageHandlerSend(actionName, data, callback, transfers) {
+ send: function messageHandlerSend(actionName, data, transfers) {
var message = {
action: actionName,
data: data
};
- if (callback) {
- var callbackId = this.callbackIndex++;
- this.callbacks[callbackId] = callback;
- message.callbackId = callbackId;
+ 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 {
@@ -1313,2520 +1610,30 @@ function loadJpegStream(id, imageUrl, objs) {
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;
}
-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) {
- error('Should not call ColorSpace.getRgb');
- },
- /**
- * 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_getRgb(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 an RGBA buffer.
- */
- fillRgb: function ColorSpace_fillRgb(rgbaBuf, originalWidth,
- originalHeight, width, height,
- actualHeight, bpc, comps) {
- var count = originalWidth * originalHeight;
- var rgbBuf = null;
- var numComponentColors = 1 << bpc;
- var needsResizing = originalHeight != height || originalWidth != width;
-
- 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);
- for (var i = 0; i < numComponentColors; i++) {
- allColors[i] = i;
- }
- var colorMap = new Uint8Array(numComponentColors * 3);
- this.getRgbBuffer(allColors, 0, numComponentColors, colorMap, 0, bpc,
- /* alpha01 = */ 0);
-
- if (!needsResizing) {
- // Fill in the RGB values directly into |rgbaBuf|.
- var rgbaPos = 0;
- for (var i = 0; i < count; ++i) {
- var key = comps[i] * 3;
- rgbaBuf[rgbaPos++] = colorMap[key];
- rgbaBuf[rgbaPos++] = colorMap[key + 1];
- rgbaBuf[rgbaPos++] = colorMap[key + 2];
- rgbaPos++;
- }
- } else {
- rgbBuf = new Uint8Array(count * 3);
- var rgbPos = 0;
- for (var i = 0; i < count; ++i) {
- var 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 |rgbaBuf|.
- this.getRgbBuffer(comps, 0, width * actualHeight, rgbaBuf, 0, bpc,
- /* alpha01 = */ 1);
- } else {
- rgbBuf = new Uint8Array(count * 3);
- this.getRgbBuffer(comps, 0, count, rgbBuf, 0, bpc,
- /* alpha01 = */ 0);
- }
- }
-
- if (rgbBuf) {
- if (needsResizing) {
- rgbBuf = PDFImage.resize(rgbBuf, bpc, 3, originalWidth,
- originalHeight, width, height);
- }
- var rgbPos = 0;
- var actualLength = width * actualHeight * 4;
- for (var i = 0; i < actualLength; i += 4) {
- rgbaBuf[i] = rgbBuf[rgbPos++];
- rgbaBuf[i + 1] = rgbBuf[rgbPos++];
- rgbaBuf[i + 2] = rgbBuf[rgbPos++];
- }
- }
- },
- /**
- * 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;
-
- switch (name) {
- case 'DeviceGrayCS':
- return this.singletons.gray;
- case 'DeviceRgbCS':
- return this.singletons.rgb;
- case 'DeviceCmykCS':
- return this.singletons.cmyk;
- case 'CalGrayCS':
- var whitePoint = IR[1].WhitePoint;
- var blackPoint = IR[1].BlackPoint;
- var gamma = IR[1].Gamma;
- return new CalGrayCS(whitePoint, blackPoint, gamma);
- 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':
- var whitePoint = IR[1].WhitePoint;
- var blackPoint = IR[1].BlackPoint;
- var range = IR[1].Range;
- return new LabCS(whitePoint, blackPoint, range);
- default:
- error('Unkown 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;
-
- switch (mode) {
- case 'DeviceGray':
- case 'G':
- return 'DeviceGrayCS';
- case 'DeviceRGB':
- case 'RGB':
- return 'DeviceRgbCS';
- case 'DeviceCMYK':
- case 'CMYK':
- return 'DeviceCmykCS';
- case 'CalGray':
- var params = cs[1].getAll();
- return ['CalGrayCS', params];
- case 'CalRGB':
- return 'DeviceRgbCS';
- case 'ICCBased':
- var stream = xref.fetchIfRef(cs[1]);
- var dict = stream.dict;
- var numComps = dict.get('N');
- if (numComps == 1)
- return 'DeviceGrayCS';
- if (numComps == 3)
- return 'DeviceRgbCS';
- 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];
- var 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':
- var 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;
- }
-
- AlternateCS.prototype = {
- getRgb: function AlternateCS_getRgb(src, srcOffset) {
- var rgb = new Uint8Array(3);
- this.getRgbItem(src, srcOffset, rgb, 0);
- return rgb;
- },
- getRgbItem: function AlternateCS_getRgbItem(src, srcOffset,
- dest, destOffset) {
- var baseNumComps = this.base.numComps;
- var input = 'subarray' in src ?
- src.subarray(srcOffset, srcOffset + this.numComps) :
- Array.prototype.slice.call(src, srcOffset, srcOffset + this.numComps);
- var tinted = this.tintFn(input);
- this.base.getRgbItem(tinted, 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);
- for (var i = 0; i < count; i++) {
- for (var j = 0; j < numComps; j++) {
- scaled[j] = src[srcOffset++] * scale;
- }
- var tinted = tintFn(scaled);
- if (usesZeroToOneRange) {
- for (var j = 0; j < baseNumComps; j++) {
- baseBuf[pos++] = tinted[j] * 255;
- }
- } else {
- 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: function IndexedCS_getRgb(src, srcOffset) {
- var numComps = this.base.numComps;
- var start = src[srcOffset] * numComps;
- return this.base.getRgb(this.lookup, start);
- },
- 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: function DeviceGrayCS_getRgb(src, srcOffset) {
- var rgb = new Uint8Array(3);
- this.getRgbItem(src, srcOffset, rgb, 0);
- return rgb;
- },
- 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: function DeviceRgbCS_getRgb(src, srcOffset) {
- var rgb = new Uint8Array(3);
- this.getRgbItem(src, srcOffset, rgb, 0);
- return rgb;
- },
- 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;
- 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;
- 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;
-
- 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: function DeviceCmykCS_getRgb(src, srcOffset) {
- var rgb = new Uint8Array(3);
- convertToRgb(src, srcOffset, 1, rgb, 0);
- return rgb;
- },
- 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;
-})();
+//#if (FIREFOX || MOZCENTRAL)
//
-// CalGrayCS: Based on "PDF Reference, Sixth Ed", p.245
+//Components.utils.import('resource://gre/modules/Services.jsm');
//
-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 intermediate variables M, L, N as per spec.
- // Except if other than default BlackPoint values are used.
- var M = cs.XW * AG;
- var L = cs.YW * AG;
- var N = cs.ZW * AG;
-
- // Decode XYZ, as per spec.
- var X = M;
- var Y = L;
- var Z = N;
-
- // http://www.poynton.com/notes/colour_and_gamma/ColorFAQ.html, Ch 4.
- // This yields values in range [0, 100].
- var Lstar = Math.max(116 * Math.pow(Y, 1 / 3) - 16, 0);
-
- // Convert values to rgb range [0, 255].
- dest[destOffset] = Lstar * 255 / 100;
- dest[destOffset + 1] = Lstar * 255 / 100;
- dest[destOffset + 2] = Lstar * 255 / 100;
- }
-
- CalGrayCS.prototype = {
- getRgb: function CalGrayCS_getRgb(src, srcOffset) {
- var rgb = new Uint8Array(3);
- this.getRgbItem(src, srcOffset, rgb, 0);
- return rgb;
- },
- 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;
-})();
-
+//var EXPORTED_SYMBOLS = ['NetworkManager'];
//
-// 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] = Math.sqrt(r < 0 ? 0 : r > 1 ? 1 : r) * 255;
- dest[destOffset + 1] = Math.sqrt(g < 0 ? 0 : g > 1 ? 1 : g) * 255;
- dest[destOffset + 2] = Math.sqrt(b < 0 ? 0 : b > 1 ? 1 : b) * 255;
- }
-
- LabCS.prototype = {
- getRgb: function LabCS_getRgb(src, srcOffset) {
- var rgb = new Uint8Array(3);
- convertToRgb(this, src, srcOffset, false, rgb, 0);
- return rgb;
- },
- 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,
- 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 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 length = 1;
- for (var i = 0, ii = size.length; i < ii; i++)
- length *= size[i];
- length *= outputSize;
-
- var array = [];
- 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 (var i = 0; i < length; i++) {
- while (codeSize < bps) {
- codeBuf <<= 8;
- codeBuf |= strBytes[strIdx++];
- codeSize += 8;
- }
- codeSize -= bps;
- array.push((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);
- },
-
- constructSampled: function PDFFunction_constructSampled(str, dict) {
- function toMultiArray(arr) {
- var inputLength = arr.length;
- var outputLength = arr.length / 2;
- 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(args) {
- // 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];
-
- if (m != args.length)
- error('Incorrect number of arguments: ' + m + ' != ' +
- args.length);
-
- var x = args;
-
- // 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);
- for (var 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 (var 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(x[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 (var 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;
- }
-
- var y = new Float64Array(n);
- for (var j = 0; j < n; ++j) {
- // Sum all cube vertices' samples portions
- var rj = 0;
- for (var 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)
- y[j] = Math.min(Math.max(rj, range[j][0]), range[j][1]);
- }
-
- return y;
- };
- },
-
- 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(args) {
- var x = n == 1 ? args[0] : Math.pow(args[0], n);
-
- var out = [];
- for (var j = 0; j < length; ++j)
- out.push(c0[j] + (x * diff[j]));
-
- return out;
-
- };
- },
-
- 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 = [];
-
- for (var i = 0, ii = fnsIR.length; i < ii; i++) {
- fns.push(PDFFunction.fromIR(fnsIR[i]));
- }
-
- return function constructStichedFromIRResult(args) {
- 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(args[0], 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];
-
- var v2 = rmin + (v - dmin) * (rmax - rmin) / (dmax - dmin);
-
- // call the appropropriate function
- return fns[i]([v2]);
- };
- },
-
- 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 numOutputs = range.length / 2;
- 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 = new FunctionCache();
- return function constructPostScriptFromIRResult(args) {
- var initialStack = [];
- for (var i = 0, ii = (domain.length / 2); i < ii; ++i) {
- initialStack.push(args[i]);
- }
-
- var key = initialStack.join('_');
- if (cache.has(key))
- return cache.get(key);
-
- var stack = evaluator.execute(initialStack);
- var transformed = [];
- for (i = numOutputs - 1; i >= 0; --i) {
- var out = stack.pop();
- var rangeIndex = 2 * i;
- if (out < range[rangeIndex])
- out = range[rangeIndex];
- else if (out > range[rangeIndex + 1])
- out = range[rangeIndex + 1];
- transformed[i] = out;
- }
- cache.set(key, transformed);
- return transformed;
- };
- }
- };
-})();
-
-var FunctionCache = (function FunctionCacheClosure() {
- // Of 10 PDF's with type4 functions the maxium number of distinct values seen
- // was 256. This still may need some tweaking in the future though.
- var MAX_CACHE_SIZE = 1024;
- function FunctionCache() {
- this.cache = {};
- this.total = 0;
- }
- FunctionCache.prototype = {
- has: function FunctionCache_has(key) {
- return key in this.cache;
- },
- get: function FunctionCache_get(key) {
- return this.cache[key];
- },
- set: function FunctionCache_set(key, value) {
- if (this.total < MAX_CACHE_SIZE) {
- this.cache[key] = value;
- this.total++;
- }
- }
- };
- return FunctionCache;
-})();
-
-var PostScriptStack = (function PostScriptStackClosure() {
- var MAX_STACK_SIZE = 100;
- function PostScriptStack(initialStack) {
- this.stack = initialStack || [];
- }
-
- 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, operands) {
- this.operators = operators;
- this.operands = operands;
- }
- 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(-b);
- break;
- case 'not':
- a = stack.pop();
- if (isBool(a) && isBool(b))
- stack.push(a && b);
- else
- stack.push(a & b);
- 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;
-})();
-
-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();
- }
- PostScriptLexer.prototype = {
- nextChar: function PostScriptLexer_nextChar() {
- return (this.currentChar = this.stream.getByte());
- },
- getToken: function PostScriptLexer_getToken() {
- var s = '';
- 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 str = String.fromCharCode(ch);
- while ((ch = this.nextChar()) >= 0 && // and 'A'-'Z', 'a'-'z'
- ((ch >= 0x41 && ch <= 0x5A) || (ch >= 0x61 && ch <= 0x7A))) {
- str += String.fromCharCode(ch);
- }
- 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 str = String.fromCharCode(ch);
- while ((ch = this.nextChar()) >= 0) {
- if ((ch >= 0x30 && ch <= 0x39) || // '0'-'9'
- ch === 0x2D || ch === 0x2E) { // '-', '.'
- str += String.fromCharCode(ch);
- } else {
- break;
- }
- }
- var value = parseFloat(str);
- if (isNaN(value))
- error('Invalid floating point number: ' + value);
- return value;
- }
- };
- return PostScriptLexer;
-})();
-
-
-
-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) {
- if (params.data) {
- this.data = params.data;
- return;
- }
-
- var dict = params.dict;
- var data = this.data = {};
-
- data.subtype = dict.get('Subtype').name;
- var rect = dict.get('Rect');
- data.rect = Util.normalizeRect(rect);
- data.annotationFlags = dict.get('F');
-
- var color = dict.get('C');
- if (isArray(color) && color.length === 3) {
- // TODO(mack): currently only supporting rgb; need support different
- // colorspaces
- data.color = color;
- } else {
- data.color = [0, 0, 0];
- }
-
- // 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 && isArray(dashArray)) {
- 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++) {
- if (!(+dashArray[i] >= 0)) {
- isInvalid = true;
- break;
- } else if (dashArray[i] > 0) {
- numPositive++;
- }
- }
- if (isInvalid || numPositive === 0) {
- data.borderWidth = 0;
- }
- }
- }
- }
-
- this.appearance = getDefaultAppearance(dict);
- data.hasAppearance = !!this.appearance;
- }
-
- Annotation.prototype = {
-
- getData: function Annotation_getData() {
- return this.data;
- },
-
- hasHtml: function Annotation_hasHtml() {
- return false;
- },
-
- getHtmlElement: function Annotation_getHtmlElement(commonObjs) {
- throw new NotImplementedException(
- 'getHtmlElement() should be implemented in subclass');
- },
-
- // TODO(mack): Remove this, it's not really that helpful.
- getEmptyContainer: function Annotation_getEmptyContainer(tagName, rect) {
- assert(!isWorker,
- 'getEmptyContainer() should be called from main thread');
-
- rect = rect || this.data.rect;
- var element = document.createElement(tagName);
- element.style.width = Math.ceil(rect[2] - rect[0]) + 'px';
- element.style.height = Math.ceil(rect[3] - rect[1]) + 'px';
- return element;
- },
-
- isViewable: function Annotation_isViewable() {
- var data = this.data;
- return !!(
- data &&
- (!data.annotationFlags ||
- !(data.annotationFlags & 0x22)) && // Hidden or NoView
- data.rect // rectangle is nessessary
- );
- },
-
- loadResources: function(keys) {
- var promise = new LegacyPromise();
- this.appearance.dict.getAsync('Resources').then(function(resources) {
- if (!resources) {
- promise.resolve();
- return;
- }
- var objectLoader = new ObjectLoader(resources.map,
- keys,
- resources.xref);
- objectLoader.load().then(function() {
- promise.resolve(resources);
- });
- }.bind(this));
-
- return promise;
- },
-
- getOperatorList: function Annotation_getToOperatorList(evaluator) {
-
- var promise = new LegacyPromise();
-
- if (!this.appearance) {
- promise.resolve(new OperatorList());
- return promise;
- }
-
- 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 border = data.border;
-
- resourcesPromise.then(function(resources) {
- var opList = new OperatorList();
- opList.addOp(OPS.beginAnnotation, [data.rect, transform, matrix]);
- evaluator.getOperatorList(this.appearance, resources, opList);
- opList.addOp(OPS.endAnnotation, []);
- promise.resolve(opList);
- }.bind(this));
-
- return promise;
- }
- };
-
- 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;
- }
- };
-
- // TODO(mack): Support loading annotation from data
- Annotation.fromData = function Annotation_fromData(data) {
- var subtype = data.subtype;
- var fieldType = data.fieldType;
- var Constructor = Annotation.getConstructor(subtype, fieldType);
- if (Constructor) {
- return new Constructor({ data: data });
- }
- };
-
- 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()) {
- return annotation;
- } else {
- warn('unimplemented annotation type: ' + subtype);
- }
- };
-
- Annotation.appendToOperatorList = function Annotation_appendToOperatorList(
- annotations, opList, pdfManager, partialEvaluator) {
-
- function reject(e) {
- annotationsReadyPromise.reject(e);
- }
-
- var annotationsReadyPromise = new LegacyPromise();
-
- var annotationPromises = [];
- for (var i = 0, n = annotations.length; i < n; ++i) {
- 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, []);
- annotationsReadyPromise.resolve();
- }, reject);
-
- return annotationsReadyPromise;
- };
-
- return Annotation;
-})();
-PDFJS.Annotation = Annotation;
-
-
-var WidgetAnnotation = (function WidgetAnnotationClosure() {
-
- function WidgetAnnotation(params) {
- Annotation.call(this, params);
-
- if (params.data) {
- return;
- }
-
- 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') || new Dict();
-
- // 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 {
- // 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);
-
- if (params.data) {
- return;
- }
-
- this.data.textAlignment = Util.getInheritableProperty(params.dict, 'Q');
- }
-
- // 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;
- }
-
-
- var parent = WidgetAnnotation.prototype;
- Util.inherit(TextWidgetAnnotation, WidgetAnnotation, {
- hasHtml: function TextWidgetAnnotation_hasHtml() {
- return !this.data.hasAppearance && !!this.data.fieldValue;
- },
-
- getHtmlElement: function TextWidgetAnnotation_getHtmlElement(commonObjs) {
- assert(!isWorker, 'getHtmlElement() shall be called from main thread');
-
- var item = this.data;
-
- var element = this.getEmptyContainer('div');
- 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;
- var cssRules = setTextStyles(content, item, fontObj);
-
- element.appendChild(content);
-
- return element;
- },
-
- getOperatorList: function TextWidgetAnnotation_getOperatorList(evaluator) {
- if (this.appearance) {
- return Annotation.prototype.getOperatorList.call(this, evaluator);
- }
-
- var promise = new LegacyPromise();
- 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.
-
- var defaultAppearance = data.defaultAppearance;
- if (!defaultAppearance) {
- promise.resolve(opList);
- return promise;
- }
-
- // Include any font resources found in the default appearance
-
- var stream = new Stream(stringToBytes(defaultAppearance));
- evaluator.getOperatorList(stream, this.fieldResources, opList);
- var appearanceFnArray = opList.fnArray;
- var appearanceArgsArray = opList.argsArray;
- var fnArray = [];
- var argsArray = [];
-
- // TODO(mack): Add support for stroke color
- data.rgb = [0, 0, 0];
- // TODO THIS DOESN'T MAKE ANY SENSE SINCE THE fnArray IS EMPTY!
- for (var i = 0, n = fnArray.length; i < n; ++i) {
- var fnId = appearanceFnArray[i];
- var args = appearanceArgsArray[i];
-
- if (fnId === OPS.setFont) {
- data.fontRefName = args[0];
- var size = args[1];
- if (size < 0) {
- data.fontDirection = -1;
- data.fontSize = -size;
- } else {
- data.fontDirection = 1;
- data.fontSize = size;
- }
- } else if (fnId === OPS.setFillRGBColor) {
- data.rgb = args;
- } else if (fnId === OPS.setFillGray) {
- var rgbValue = args[0] * 255;
- data.rgb = [rgbValue, rgbValue, rgbValue];
- }
- }
- promise.resolve(opList);
- return promise;
- }
- });
-
- return TextWidgetAnnotation;
-})();
-
-var TextAnnotation = (function TextAnnotationClosure() {
- function TextAnnotation(params) {
- Annotation.call(this, params);
-
- if (params.data) {
- return;
- }
-
- var dict = params.dict;
- var data = this.data;
-
- var content = dict.get('Contents');
- var title = dict.get('T');
- data.content = stringToPDFString(content || '');
- data.title = stringToPDFString(title || '');
- data.name = !dict.has('Name') ? 'Note' : dict.get('Name').name;
- }
-
- var ANNOT_MIN_SIZE = 10;
-
- Util.inherit(TextAnnotation, Annotation, {
-
- getOperatorList: function TextAnnotation_getOperatorList(evaluator) {
- var promise = new LegacyPromise();
- promise.resolve(new OperatorList());
- return promise;
- },
-
- hasHtml: function TextAnnotation_hasHtml() {
- return true;
- },
-
- getHtmlElement: function TextAnnotation_getHtmlElement(commonObjs) {
- assert(!isWorker, 'getHtmlElement() shall be called from main thread');
-
- var item = this.data;
- 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 = this.getEmptyContainer('section', rect);
- container.className = 'annotText';
-
- var image = document.createElement('img');
- image.style.height = container.style.height;
- 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 content = document.createElement('div');
- content.setAttribute('hidden', true);
- var title = document.createElement('h1');
- var text = document.createElement('p');
- content.style.left = Math.floor(rect[2] - rect[0]) + 'px';
- content.style.top = '0px';
- 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 (var 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 showAnnotation = function showAnnotation() {
- container.style.zIndex += 1;
- content.removeAttribute('hidden');
- };
-
- var hideAnnotation = function hideAnnotation(e) {
- if (e.toElement || e.relatedTarget) { // No context menu is used
- container.style.zIndex -= 1;
- content.setAttribute('hidden', true);
- }
- };
-
- content.addEventListener('mouseover', showAnnotation, false);
- content.addEventListener('mouseout', hideAnnotation, false);
- image.addEventListener('mouseover', showAnnotation, false);
- image.addEventListener('mouseout', hideAnnotation, false);
- }
-
- content.appendChild(title);
- content.appendChild(text);
- container.appendChild(image);
- container.appendChild(content);
-
- return container;
- }
- });
-
- return TextAnnotation;
-})();
-
-var LinkAnnotation = (function LinkAnnotationClosure() {
- function LinkAnnotation(params) {
- Annotation.call(this, params);
-
- if (params.data) {
- return;
- }
-
- var dict = params.dict;
- var data = this.data;
-
- var action = dict.get('A');
- if (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 {
- 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.indexOf('www.') === 0) {
- return ('http://' + url);
- }
- return url;
- }
-
- Util.inherit(LinkAnnotation, Annotation, {
- hasOperatorList: function LinkAnnotation_hasOperatorList() {
- return false;
- },
-
- hasHtml: function LinkAnnotation_hasHtml() {
- return true;
- },
-
- getHtmlElement: function LinkAnnotation_getHtmlElement(commonObjs) {
- var rect = this.data.rect;
- var element = document.createElement('a');
- var borderWidth = this.data.borderWidth;
-
- element.style.borderWidth = borderWidth + 'px';
- var color = this.data.color;
- var rgb = [];
- for (var i = 0; i < 3; ++i) {
- rgb[i] = Math.round(color[i] * 255);
- }
- element.style.borderColor = Util.makeCssRgb(rgb);
- element.style.borderStyle = 'solid';
-
- var width = rect[2] - rect[0] - 2 * borderWidth;
- var height = rect[3] - rect[1] - 2 * borderWidth;
- element.style.width = width + 'px';
- element.style.height = height + 'px';
-
- element.href = this.data.url || '';
- return element;
- }
- });
-
- return LinkAnnotation;
-})();
-
-
-
+//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() {
@@ -3836,11 +1643,16 @@ var NetworkManager = (function NetworkManagerClosure() {
function NetworkManager(url, args) {
this.url = url;
args = args || {};
- this.httpHeaders = args.httpHeaders || {};
+ 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;
@@ -3849,17 +1661,16 @@ var NetworkManager = (function NetworkManagerClosure() {
}
function getArrayBuffer(xhr) {
- var data = (xhr.mozResponseArrayBuffer || xhr.mozResponse ||
- xhr.responseArrayBuffer || xhr.response);
+ var data = xhr.response;
if (typeof data !== 'string') {
return data;
}
var length = data.length;
- var buffer = new Uint8Array(length);
+ var array = new Uint8Array(length);
for (var i = 0; i < length; i++) {
- buffer[i] = data.charCodeAt(i) & 0xFF;
+ array[i] = data.charCodeAt(i) & 0xFF;
}
- return buffer;
+ return array.buffer;
}
NetworkManager.prototype = {
@@ -3874,11 +1685,11 @@ var NetworkManager = (function NetworkManagerClosure() {
return this.request(args);
},
- requestFull: function NetworkManager_requestRange(listeners) {
+ requestFull: function NetworkManager_requestFull(listeners) {
return this.request(listeners);
},
- request: function NetworkManager_requestRange(args) {
+ request: function NetworkManager_request(args) {
var xhr = this.getXhr();
var xhrId = this.currXhrId++;
var pendingRequest = this.pendingRequests[xhrId] = {
@@ -3894,7 +1705,7 @@ var NetworkManager = (function NetworkManagerClosure() {
}
xhr.setRequestHeader(property, value);
}
- if ('begin' in args && 'end' in args) {
+ if (this.isHttp && 'begin' in args && 'end' in args) {
var rangeStr = args.begin + '-' + (args.end - 1);
xhr.setRequestHeader('Range', 'bytes=' + rangeStr);
pendingRequest.expectedStatus = 206;
@@ -3902,27 +1713,57 @@ var NetworkManager = (function NetworkManagerClosure() {
pendingRequest.expectedStatus = 200;
}
- xhr.mozResponseType = xhr.responseType = 'arraybuffer';
-
- if (args.onProgress) {
- xhr.onprogress = args.onProgress;
+ 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) {
@@ -3949,7 +1790,7 @@ var NetworkManager = (function NetworkManagerClosure() {
delete this.pendingRequests[xhrId];
// success status == 0 can be on ftp, file and other protocols
- if (xhr.status === 0 && /^https?:/i.test(this.url)) {
+ if (xhr.status === 0 && this.isHttp) {
if (pendingRequest.onError) {
pendingRequest.onError(xhr.status);
}
@@ -3983,6 +1824,8 @@ var NetworkManager = (function NetworkManagerClosure() {
begin: begin,
chunk: chunk
});
+ } else if (pendingRequest.onProgressiveData) {
+ pendingRequest.onDone(null);
} else {
pendingRequest.onDone({
begin: 0,
@@ -4002,6 +1845,10 @@ var NetworkManager = (function NetworkManagerClosure() {
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;
},
@@ -4039,7 +1886,8 @@ var ChunkedStream = (function ChunkedStreamClosure() {
this.numChunksLoaded = 0;
this.numChunks = Math.ceil(length / chunkSize);
this.manager = manager;
- this.initialDataLength = 0;
+ this.progressiveDataLength = 0;
+ this.lastSuccessfulEnsureByteChunk = -1; // a single-entry cache
}
// required methods for a stream. if a particular stream does not
@@ -4049,7 +1897,7 @@ var ChunkedStream = (function ChunkedStreamClosure() {
getMissingChunks: function ChunkedStream_getMissingChunks() {
var chunks = [];
for (var chunk = 0, n = this.numChunks; chunk < n; ++chunk) {
- if (!(chunk in this.loadedChunks)) {
+ if (!this.loadedChunks[chunk]) {
chunks.push(chunk);
}
}
@@ -4064,7 +1912,7 @@ var ChunkedStream = (function ChunkedStreamClosure() {
return this.numChunksLoaded === this.numChunks;
},
- onReceiveData: function(begin, chunk) {
+ onReceiveData: function ChunkedStream_onReceiveData(begin, chunk) {
var end = begin + chunk.byteLength;
assert(begin % this.chunkSize === 0, 'Bad begin offset: ' + begin);
@@ -4072,38 +1920,59 @@ var ChunkedStream = (function ChunkedStreamClosure() {
// See ChunkedStream.moveStart()
var length = this.bytes.length;
assert(end % this.chunkSize === 0 || end === length,
- 'Bad end offset: ' + end);
+ '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 (var chunk = beginChunk; chunk < endChunk; ++chunk) {
- if (!(chunk in this.loadedChunks)) {
- this.loadedChunks[chunk] = true;
+ for (curChunk = beginChunk; curChunk < endChunk; ++curChunk) {
+ if (!this.loadedChunks[curChunk]) {
+ this.loadedChunks[curChunk] = true;
++this.numChunksLoaded;
}
}
},
- onReceiveInitialData: function (data) {
- this.bytes.set(data);
- this.initialDataLength = data.length;
- var endChunk = this.end === data.length ?
- this.numChunks : Math.floor(data.length / this.chunkSize);
- for (var i = 0; i < endChunk; i++) {
- this.loadedChunks[i] = 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.initialDataLength) {
+ if (end <= this.progressiveDataLength) {
return;
}
@@ -4111,21 +1980,22 @@ var ChunkedStream = (function ChunkedStreamClosure() {
var beginChunk = Math.floor(begin / chunkSize);
var endChunk = Math.floor((end - 1) / chunkSize) + 1;
for (var chunk = beginChunk; chunk < endChunk; ++chunk) {
- if (!(chunk in this.loadedChunks)) {
+ if (!this.loadedChunks[chunk]) {
throw new MissingDataException(begin, end);
}
}
},
nextEmptyChunk: function ChunkedStream_nextEmptyChunk(beginChunk) {
- for (var chunk = beginChunk, n = this.numChunks; chunk < n; ++chunk) {
- if (!(chunk in this.loadedChunks)) {
+ var chunk, n;
+ for (chunk = beginChunk, n = this.numChunks; chunk < n; ++chunk) {
+ if (!this.loadedChunks[chunk]) {
return chunk;
}
}
// Wrap around to beginning
- for (var chunk = 0; chunk < beginChunk; ++chunk) {
- if (!(chunk in this.loadedChunks)) {
+ for (chunk = 0; chunk < beginChunk; ++chunk) {
+ if (!this.loadedChunks[chunk]) {
return chunk;
}
}
@@ -4133,22 +2003,40 @@ var ChunkedStream = (function ChunkedStreamClosure() {
},
hasChunk: function ChunkedStream_hasChunk(chunk) {
- return chunk in this.loadedChunks;
+ 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.ensureRange(pos, pos + 1);
+ this.ensureByte(pos);
return this.bytes[this.pos++];
},
+ getUint16: function ChunkedStream_getUint16() {
+ var b0 = this.getByte();
+ var b1 = this.getByte();
+ 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) {
@@ -4162,14 +2050,21 @@ var ChunkedStream = (function ChunkedStreamClosure() {
}
var end = pos + length;
- if (end > strEnd)
+ 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;
@@ -4182,8 +2077,9 @@ var ChunkedStream = (function ChunkedStreamClosure() {
},
skip: function ChunkedStream_skip(n) {
- if (!n)
+ if (!n) {
n = 1;
+ }
this.pos += n;
},
@@ -4196,6 +2092,8 @@ var ChunkedStream = (function ChunkedStreamClosure() {
},
makeSubStream: function ChunkedStream_makeSubStream(start, length, dict) {
+ this.ensureRange(start, start + length);
+
function ChunkedStreamSubstream() {}
ChunkedStreamSubstream.prototype = Object.create(this);
ChunkedStreamSubstream.prototype.getMissingChunks = function() {
@@ -4204,7 +2102,7 @@ var ChunkedStream = (function ChunkedStreamClosure() {
var endChunk = Math.floor((this.end - 1) / chunkSize) + 1;
var missingChunks = [];
for (var chunk = beginChunk; chunk < endChunk; ++chunk) {
- if (!(chunk in this.loadedChunks)) {
+ if (!this.loadedChunks[chunk]) {
missingChunks.push(chunk);
}
}
@@ -4226,7 +2124,6 @@ var ChunkedStream = (function ChunkedStreamClosure() {
var ChunkedStreamManager = (function ChunkedStreamManagerClosure() {
function ChunkedStreamManager(length, chunkSize, url, args) {
- var self = this;
this.stream = new ChunkedStream(length, chunkSize, this);
this.length = length;
this.chunkSize = chunkSize;
@@ -4243,7 +2140,11 @@ var ChunkedStreamManager = (function ChunkedStreamManagerClosure() {
} 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,
@@ -4263,29 +2164,18 @@ var ChunkedStreamManager = (function ChunkedStreamManagerClosure() {
this.chunksNeededByRequest = {};
this.requestsByChunk = {};
this.callbacksByRequest = {};
+ this.progressiveDataLength = 0;
+
+ this._loadedStreamCapability = createPromiseCapability();
- this.loadedStream = new LegacyPromise();
if (args.initialData) {
- this.setInitialData(args.initialData);
+ this.onReceiveData({chunk: args.initialData});
}
}
ChunkedStreamManager.prototype = {
-
- setInitialData: function ChunkedStreamManager_setInitialData(data) {
- this.stream.onReceiveInitialData(data);
- if (this.stream.allChunksLoaded()) {
- this.loadedStream.resolve(this.stream);
- } else if (this.msgHandler) {
- this.msgHandler.send('DocProgress', {
- loaded: data.length,
- total: this.length
- });
- }
- },
-
onLoadedStream: function ChunkedStreamManager_getLoadedStream() {
- return this.loadedStream;
+ return this._loadedStreamCapability.promise;
},
// Get all the chunks that are not yet loaded and groups them into
@@ -4293,7 +2183,7 @@ var ChunkedStreamManager = (function ChunkedStreamManagerClosure() {
requestAllChunks: function ChunkedStreamManager_requestAllChunks() {
var missingChunks = this.stream.getMissingChunks();
this.requestChunks(missingChunks);
- return this.loadedStream;
+ return this._loadedStreamCapability.promise;
},
requestChunks: function ChunkedStreamManager_requestChunks(chunks,
@@ -4301,8 +2191,9 @@ var ChunkedStreamManager = (function ChunkedStreamManagerClosure() {
var requestId = this.currRequestId++;
var chunksNeeded;
+ var i, ii;
this.chunksNeededByRequest[requestId] = chunksNeeded = {};
- for (var i = 0, ii = chunks.length; i < ii; i++) {
+ for (i = 0, ii = chunks.length; i < ii; i++) {
if (!this.stream.hasChunk(chunks[i])) {
chunksNeeded[chunks[i]] = true;
}
@@ -4333,7 +2224,7 @@ var ChunkedStreamManager = (function ChunkedStreamManagerClosure() {
var groupedChunksToRequest = this.groupChunks(chunksToRequest);
- for (var i = 0; i < groupedChunksToRequest.length; ++i) {
+ 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);
@@ -4395,13 +2286,13 @@ var ChunkedStreamManager = (function ChunkedStreamManagerClosure() {
}
if (prevChunk >= 0 && prevChunk + 1 !== chunk) {
- groupedChunks.push({
- beginChunk: beginChunk, endChunk: prevChunk + 1});
+ groupedChunks.push({ beginChunk: beginChunk,
+ endChunk: prevChunk + 1 });
beginChunk = chunk;
}
if (i + 1 === chunks.length) {
- groupedChunks.push({
- beginChunk: beginChunk, endChunk: chunk + 1});
+ groupedChunks.push({ beginChunk: beginChunk,
+ endChunk: chunk + 1 });
}
prevChunk = chunk;
@@ -4410,8 +2301,8 @@ var ChunkedStreamManager = (function ChunkedStreamManagerClosure() {
},
onProgress: function ChunkedStreamManager_onProgress(args) {
- var bytesLoaded = this.stream.numChunksLoaded * this.chunkSize +
- args.loaded;
+ var bytesLoaded = (this.stream.numChunksLoaded * this.chunkSize +
+ args.loaded);
this.msgHandler.send('DocProgress', {
loaded: bytesLoaded,
total: this.length
@@ -4420,26 +2311,34 @@ var ChunkedStreamManager = (function ChunkedStreamManagerClosure() {
onReceiveData: function ChunkedStreamManager_onReceiveData(args) {
var chunk = args.chunk;
- var begin = args.begin;
+ var isProgressive = args.begin === undefined;
+ var begin = isProgressive ? this.progressiveDataLength : args.begin;
var end = begin + chunk.byteLength;
- var beginChunk = this.getBeginChunk(begin);
- var endChunk = this.getEndChunk(end);
+ 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);
+ }
- this.stream.onReceiveData(begin, chunk);
if (this.stream.allChunksLoaded()) {
- this.loadedStream.resolve(this.stream);
+ this._loadedStreamCapability.resolve(this.stream);
}
var loadedRequests = [];
- for (var chunk = beginChunk; chunk < endChunk; ++chunk) {
-
+ 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 (var i = 0; i < requestIds.length; ++i) {
- var requestId = requestIds[i];
+ for (i = 0; i < requestIds.length; ++i) {
+ requestId = requestIds[i];
var chunksNeeded = this.chunksNeededByRequest[requestId];
if (chunk in chunksNeeded) {
delete chunksNeeded[chunk];
@@ -4473,8 +2372,8 @@ var ChunkedStreamManager = (function ChunkedStreamManagerClosure() {
}
}
- for (var i = 0; i < loadedRequests.length; ++i) {
- var requestId = loadedRequests[i];
+ for (i = 0; i < loadedRequests.length; ++i) {
+ requestId = loadedRequests[i];
var callback = this.callbacksByRequest[requestId];
delete this.callbacksByRequest[requestId];
if (callback) {
@@ -4488,6 +2387,10 @@ var ChunkedStreamManager = (function ChunkedStreamManagerClosure() {
});
},
+ onError: function ChunkedStreamManager_onError(err) {
+ this._loadedStreamCapability.reject(err);
+ },
+
getBeginChunk: function ChunkedStreamManager_getBeginChunk(begin) {
var chunk = Math.floor(begin / this.chunkSize);
return chunk;
@@ -4513,6 +2416,9 @@ var ChunkedStreamManager = (function ChunkedStreamManagerClosure() {
+// 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() {
@@ -4524,24 +2430,24 @@ var BasePdfManager = (function BasePdfManagerClosure() {
throw new NotImplementedException();
},
- ensureModel: function BasePdfManager_ensureModel(prop, args) {
- return this.ensure(this.pdfModel, prop, args);
+ ensureDoc: function BasePdfManager_ensureDoc(prop, args) {
+ return this.ensure(this.pdfDocument, prop, args);
},
ensureXRef: function BasePdfManager_ensureXRef(prop, args) {
- return this.ensure(this.pdfModel.xref, prop, args);
+ return this.ensure(this.pdfDocument.xref, prop, args);
},
ensureCatalog: function BasePdfManager_ensureCatalog(prop, args) {
- return this.ensure(this.pdfModel.catalog, prop, args);
+ return this.ensure(this.pdfDocument.catalog, prop, args);
},
getPage: function BasePdfManager_pagePage(pageIndex) {
- return this.pdfModel.getPage(pageIndex);
+ return this.pdfDocument.getPage(pageIndex);
},
cleanup: function BasePdfManager_cleanup() {
- return this.pdfModel.cleanup();
+ return this.pdfDocument.cleanup();
},
ensure: function BasePdfManager_ensure(obj, prop, args) {
@@ -4556,13 +2462,22 @@ var BasePdfManager = (function BasePdfManagerClosure() {
return new NotImplementedException();
},
+ sendProgressiveData: function BasePdfManager_sendProgressiveData(chunk) {
+ return new NotImplementedException();
+ },
+
updatePassword: function BasePdfManager_updatePassword(password) {
- this.pdfModel.xref.password = this.password = password;
- if (this.passwordChangedPromise) {
- this.passwordChangedPromise.resolve();
+ 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();
}
@@ -4574,9 +2489,9 @@ var BasePdfManager = (function BasePdfManagerClosure() {
var LocalPdfManager = (function LocalPdfManagerClosure() {
function LocalPdfManager(data, password) {
var stream = new Stream(data);
- this.pdfModel = new PDFDocument(this, stream, password);
- this.loadedStream = new LegacyPromise();
- this.loadedStream.resolve(stream);
+ this.pdfDocument = new PDFDocument(this, stream, password);
+ this._loadedStreamCapability = createPromiseCapability();
+ this._loadedStreamCapability.resolve(stream);
}
LocalPdfManager.prototype = Object.create(BasePdfManager.prototype);
@@ -4584,28 +2499,25 @@ var LocalPdfManager = (function LocalPdfManagerClosure() {
LocalPdfManager.prototype.ensure =
function LocalPdfManager_ensure(obj, prop, args) {
- var promise = new LegacyPromise();
- try {
- var value = obj[prop];
- var result;
- if (typeof(value) === 'function') {
- result = value.apply(obj, args);
- } else {
- result = value;
+ 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);
}
- promise.resolve(result);
- } catch (e) {
- console.log(e.stack);
- promise.reject(e);
- }
- return promise;
+ });
};
LocalPdfManager.prototype.requestRange =
function LocalPdfManager_requestRange(begin, end) {
- var promise = new LegacyPromise();
- promise.resolve();
- return promise;
+ return Promise.resolve();
};
LocalPdfManager.prototype.requestLoadedStream =
@@ -4614,7 +2526,7 @@ var LocalPdfManager = (function LocalPdfManagerClosure() {
LocalPdfManager.prototype.onLoadedStream =
function LocalPdfManager_getLoadedStream() {
- return this.loadedStream;
+ return this._loadedStreamCapability.promise;
};
LocalPdfManager.prototype.terminate =
@@ -4626,9 +2538,6 @@ var LocalPdfManager = (function LocalPdfManagerClosure() {
})();
var NetworkPdfManager = (function NetworkPdfManagerClosure() {
-
- var CHUNK_SIZE = 65536;
-
function NetworkPdfManager(args, msgHandler) {
this.msgHandler = msgHandler;
@@ -4641,10 +2550,10 @@ var NetworkPdfManager = (function NetworkPdfManagerClosure() {
disableAutoFetch: args.disableAutoFetch,
initialData: args.initialData
};
- this.streamManager = new ChunkedStreamManager(args.length, CHUNK_SIZE,
+ this.streamManager = new ChunkedStreamManager(args.length, RANGE_CHUNK_SIZE,
args.url, params);
- this.pdfModel = new PDFDocument(this, this.streamManager.getStream(),
+ this.pdfDocument = new PDFDocument(this, this.streamManager.getStream(),
args.password);
}
@@ -4653,42 +2562,39 @@ var NetworkPdfManager = (function NetworkPdfManagerClosure() {
NetworkPdfManager.prototype.ensure =
function NetworkPdfManager_ensure(obj, prop, args) {
- var promise = new LegacyPromise();
- this.ensureHelper(promise, obj, prop, args);
- return promise;
- };
+ var pdfManager = this;
- NetworkPdfManager.prototype.ensureHelper =
- function NetworkPdfManager_ensureHelper(promise, obj, prop, args) {
- try {
- var result;
- var value = obj[prop];
- if (typeof(value) === 'function') {
- result = value.apply(obj, args);
- } else {
- result = value;
- }
- promise.resolve(result);
- } catch(e) {
- if (!(e instanceof MissingDataException)) {
- console.log(e.stack);
- promise.reject(e);
- return;
+ 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);
+ }
}
- this.streamManager.requestRange(e.begin, e.end, function() {
- this.ensureHelper(promise, obj, prop, args);
- }.bind(this));
- }
+ ensureHelper();
+ });
};
NetworkPdfManager.prototype.requestRange =
function NetworkPdfManager_requestRange(begin, end) {
- var promise = new LegacyPromise();
- this.streamManager.requestRange(begin, end, function() {
- promise.resolve();
- });
- return promise;
+ return new Promise(function (resolve) {
+ this.streamManager.requestRange(begin, end, function() {
+ resolve();
+ });
+ }.bind(this));
};
NetworkPdfManager.prototype.requestLoadedStream =
@@ -4696,6 +2602,11 @@ var NetworkPdfManager = (function NetworkPdfManagerClosure() {
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();
@@ -4713,6 +2624,8 @@ var NetworkPdfManager = (function NetworkPdfManagerClosure() {
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;
@@ -4730,51 +2643,69 @@ var Page = (function PageClosure() {
getPageProp: function Page_getPageProp(key) {
return this.pageDict.get(key);
},
- inheritPageProp: function Page_inheritPageProp(key) {
+
+ getInheritedPageProp: function Page_inheritPageProp(key) {
var dict = this.pageDict;
- var obj = dict.get(key);
- while (obj === undefined) {
+ var value = dict.get(key);
+ while (value === undefined) {
dict = dict.get('Parent');
- if (!dict)
+ if (!dict) {
break;
- obj = dict.get(key);
+ }
+ value = dict.get(key);
}
- return obj;
+ return value;
},
+
get content() {
return this.getPageProp('Contents');
},
+
get resources() {
- return shadow(this, 'resources', this.inheritPageProp('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.inheritPageProp('MediaBox');
+ var obj = this.getInheritedPageProp('MediaBox');
// Reset invalid media box to letter size.
- if (!isArray(obj) || obj.length !== 4)
- obj = [0, 0, 612, 792];
+ if (!isArray(obj) || obj.length !== 4) {
+ obj = LETTER_SIZE_MEDIABOX;
+ }
return shadow(this, 'mediaBox', obj);
},
+
get view() {
var mediaBox = this.mediaBox;
- var cropBox = this.inheritPageProp('CropBox');
- if (!isArray(cropBox) || cropBox.length !== 4)
+ 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)
+ if (!cropBox) {
return shadow(this, 'view', mediaBox);
-
+ }
return shadow(this, 'view', cropBox);
},
+
get annotationRefs() {
- return shadow(this, 'annotationRefs', this.inheritPageProp('Annots'));
+ return shadow(this, 'annotationRefs',
+ this.getInheritedPageProp('Annots'));
},
+
get rotate() {
- var rotate = this.inheritPageProp('Rotate') || 0;
+ 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;
@@ -4787,6 +2718,7 @@ var Page = (function PageClosure() {
}
return shadow(this, 'rotate', rotate);
},
+
getContentStream: function Page_getContentStream() {
var content = this.content;
var stream;
@@ -4795,8 +2727,9 @@ var Page = (function PageClosure() {
var xref = this.xref;
var i, n = content.length;
var streams = [];
- for (i = 0; i < n; ++i)
+ for (i = 0; i < n; ++i) {
streams.push(xref.fetchIfRef(content[i]));
+ }
stream = new StreamsSequenceStream(streams);
} else if (isStream(content)) {
stream = content;
@@ -4806,31 +2739,22 @@ var Page = (function PageClosure() {
}
return stream;
},
- loadResources: function(keys) {
+
+ loadResources: function Page_loadResources(keys) {
if (!this.resourcesPromise) {
- // TODO: add async inheritPageProp and remove this.
+ // TODO: add async getInheritedPageProp and remove this.
this.resourcesPromise = this.pdfManager.ensure(this, 'resources');
}
- var promise = new LegacyPromise();
- this.resourcesPromise.then(function resourceSuccess() {
+ return this.resourcesPromise.then(function resourceSuccess() {
var objectLoader = new ObjectLoader(this.resources.map,
keys,
this.xref);
- objectLoader.load().then(function objectLoaderSuccess() {
- promise.resolve();
- });
+ return objectLoader.load();
}.bind(this));
- return promise;
},
- getOperatorList: function Page_getOperatorList(handler) {
+
+ getOperatorList: function Page_getOperatorList(handler, intent) {
var self = this;
- var promise = new LegacyPromise();
-
- function reject(e) {
- promise.reject(e);
- }
-
- var pageListPromise = new LegacyPromise();
var pdfManager = this.pdfManager;
var contentStreamPromise = pdfManager.ensure(this, 'getContentStream',
@@ -4841,53 +2765,53 @@ var Page = (function PageClosure() {
'Pattern',
'Shading',
'XObject',
- 'Font',
+ 'Font'
// ProcSet
// Properties
]);
- var partialEvaluator = new PartialEvaluator(
- pdfManager, this.xref, handler,
- this.pageIndex, 'p' + this.pageIndex + '_',
- this.idCounters, this.fontCache);
+ var partialEvaluator = new PartialEvaluator(pdfManager, this.xref,
+ handler, this.pageIndex,
+ 'p' + this.pageIndex + '_',
+ this.idCounters,
+ this.fontCache);
- var dataPromises = Promise.all(
- [contentStreamPromise, resourcesPromise], reject);
- dataPromises.then(function(data) {
+ var dataPromises = Promise.all([contentStreamPromise, resourcesPromise]);
+ var pageListPromise = dataPromises.then(function(data) {
var contentStream = data[0];
-
-
- var opList = new OperatorList(handler, self.pageIndex);
+ var opList = new OperatorList(intent, handler, self.pageIndex);
handler.send('StartRenderPage', {
transparency: partialEvaluator.hasBlendModes(self.resources),
- pageIndex: self.pageIndex
+ pageIndex: self.pageIndex,
+ intent: intent
});
- partialEvaluator.getOperatorList(contentStream, self.resources, opList);
- pageListPromise.resolve(opList);
+ return partialEvaluator.getOperatorList(contentStream, self.resources,
+ opList).then(function () {
+ return opList;
+ });
});
var annotationsPromise = pdfManager.ensure(this, 'annotations');
- Promise.all([pageListPromise, annotationsPromise]).then(function(datas) {
+ return Promise.all([pageListPromise, annotationsPromise]).then(
+ function(datas) {
var pageOpList = datas[0];
var annotations = datas[1];
if (annotations.length === 0) {
pageOpList.flush(true);
- promise.resolve(pageOpList);
- return;
+ return pageOpList;
}
var annotationsReadyPromise = Annotation.appendToOperatorList(
- annotations, pageOpList, pdfManager, partialEvaluator);
- annotationsReadyPromise.then(function () {
+ annotations, pageOpList, pdfManager, partialEvaluator, intent);
+ return annotationsReadyPromise.then(function () {
pageOpList.flush(true);
- promise.resolve(pageOpList);
- }, reject);
- }, reject);
-
- return promise;
+ return pageOpList;
+ });
+ });
},
+
extractTextContent: function Page_extractTextContent() {
var handler = {
on: function nullHandlerOn() {},
@@ -4896,8 +2820,6 @@ var Page = (function PageClosure() {
var self = this;
- var textContentPromise = new LegacyPromise();
-
var pdfManager = this.pdfManager;
var contentStreamPromise = pdfManager.ensure(this, 'getContentStream',
[]);
@@ -4910,19 +2832,17 @@ var Page = (function PageClosure() {
var dataPromises = Promise.all([contentStreamPromise,
resourcesPromise]);
- dataPromises.then(function(data) {
+ 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);
+ var partialEvaluator = new PartialEvaluator(pdfManager, self.xref,
+ handler, self.pageIndex,
+ 'p' + self.pageIndex + '_',
+ self.idCounters,
+ self.fontCache);
- var bidiTexts = partialEvaluator.getTextContent(contentStream,
- self.resources);
- textContentPromise.resolve(bidiTexts);
+ return partialEvaluator.getTextContent(contentStream,
+ self.resources);
});
-
- return textContentPromise;
},
getAnnotationsData: function Page_getAnnotationsData() {
@@ -4936,7 +2856,7 @@ var Page = (function PageClosure() {
get annotations() {
var annotations = [];
- var annotationRefs = this.annotationRefs || [];
+ 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);
@@ -4959,17 +2879,22 @@ var Page = (function PageClosure() {
* `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))
+ if (isStream(arg)) {
init.call(this, pdfManager, arg, password);
- else if (isArrayBuffer(arg))
+ } else if (isArrayBuffer(arg)) {
init.call(this, pdfManager, new Stream(arg), password);
- else
+ } else {
error('PDFDocument: Unknown argument type');
+ }
}
function init(pdfManager, stream, password) {
- assertWellFormed(stream.length > 0, 'stream must have data');
+ assert(stream.length > 0, 'stream must have data');
this.pdfManager = pdfManager;
this.stream = stream;
var xref = new XRef(this.stream, password, pdfManager);
@@ -4979,15 +2904,19 @@ var PDFDocument = (function PDFDocumentClosure() {
function find(stream, needle, limit, backwards) {
var pos = stream.pos;
var end = stream.end;
- var str = '';
- if (pos + limit > end)
+ var strBuf = [];
+ if (pos + limit > end) {
limit = end - pos;
- for (var n = 0; n < limit; ++n)
- str += String.fromCharCode(stream.getByte());
+ }
+ 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)
+ if (index === -1) {
return false; /* not found */
+ }
stream.pos += index;
return true; /* found */
}
@@ -5032,22 +2961,15 @@ var PDFDocument = (function PDFDocumentClosure() {
},
get linearization() {
- var length = this.stream.length;
- var linearization = false;
- if (length) {
+ var linearization = null;
+ if (this.stream.length) {
try {
- linearization = new Linearization(this.stream);
- if (linearization.length != length) {
- linearization = false;
- }
+ linearization = Linearization.create(this.stream);
} catch (err) {
if (err instanceof MissingDataException) {
throw err;
}
-
- info('The linearization data is not available ' +
- 'or unreadable PDF data is found');
- linearization = false;
+ info(err);
}
}
// shadow the prototype getter with a data property
@@ -5060,16 +2982,18 @@ var PDFDocument = (function PDFDocumentClosure() {
if (linearization) {
// Find end of first obj.
stream.reset();
- if (find(stream, 'endobj', 1024))
+ 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)
+ if (pos < 0) {
pos = 0;
+ }
stream.pos = pos;
found = find(stream, 'startxref', step, true);
}
@@ -5085,8 +3009,9 @@ var PDFDocument = (function PDFDocumentClosure() {
ch = stream.getByte();
}
startXRef = parseInt(str, 10);
- if (isNaN(startXRef))
+ if (isNaN(startXRef)) {
startXRef = 0;
+ }
}
}
// shadow the prototype getter with a data property
@@ -5095,8 +3020,9 @@ var PDFDocument = (function PDFDocumentClosure() {
get mainXRefEntriesOffset() {
var mainXRefEntriesOffset = 0;
var linearization = this.linearization;
- if (linearization)
+ if (linearization) {
mainXRefEntriesOffset = linearization.mainXRefEntriesOffset;
+ }
// shadow the prototype getter with a data property
return shadow(this, 'mainXRefEntriesOffset', mainXRefEntriesOffset);
},
@@ -5157,8 +3083,8 @@ var PDFDocument = (function PDFDocumentClosure() {
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);
+ docInfo[key] = (typeof value !== 'string' ?
+ value : stringToPDFString(value));
} else {
info('Bad value in document info for "' + key + '"');
}
@@ -5168,16 +3094,25 @@ var PDFDocument = (function PDFDocumentClosure() {
return shadow(this, 'documentInfo', docInfo);
},
get fingerprint() {
- var xref = this.xref, hash, fileID = '';
+ var xref = this.xref, idArray, hash, fileID = '';
if (xref.trailer.has('ID')) {
- hash = stringToBytes(xref.trailer.get('ID')[0]);
+ idArray = xref.trailer.get('ID');
+ }
+ if (idArray && isArray(idArray) && idArray[0] !== EMPTY_FINGERPRINT) {
+ hash = stringToBytes(idArray[0]);
} else {
- hash = calculateMD5(this.stream.bytes.subarray(0, 100), 0, 100);
+ 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++) {
- fileID += hash[i].toString(16);
+ var hex = hash[i].toString(16);
+ fileID += hex.length === 1 ? '0' + hex : hex;
}
return shadow(this, 'fingerprint', fileID);
@@ -5204,6 +3139,13 @@ var Name = (function NameClosure() {
Name.prototype = {};
+ var nameCache = {};
+
+ Name.get = function Name_get(name) {
+ var nameValue = nameCache[name];
+ return (nameValue ? nameValue : (nameCache[name] = new Name(name)));
+ };
+
return Name;
})();
@@ -5218,10 +3160,7 @@ var Cmd = (function CmdClosure() {
Cmd.get = function Cmd_get(cmd) {
var cmdValue = cmdCache[cmd];
- if (cmdValue)
- return cmdValue;
-
- return cmdCache[cmd] = new Cmd(cmd);
+ return (cmdValue ? cmdValue : (cmdCache[cmd] = new Cmd(cmd)));
};
return Cmd;
@@ -5232,11 +3171,30 @@ var Dict = (function DictClosure() {
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
}
@@ -5249,12 +3207,12 @@ var Dict = (function DictClosure() {
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') {
+ 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') {
+ 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;
@@ -5264,33 +3222,26 @@ var Dict = (function DictClosure() {
// Same as get(), but returns a promise and uses fetchIfRefAsync().
getAsync: function Dict_getAsync(key1, key2, key3) {
var value;
- var promise;
var xref = this.xref;
- if (typeof (value = this.map[key1]) !== undefined || key1 in this.map ||
- typeof key2 === undefined) {
+ if (typeof (value = this.map[key1]) !== 'undefined' || key1 in this.map ||
+ typeof key2 === 'undefined') {
if (xref) {
return xref.fetchIfRefAsync(value);
}
- promise = new LegacyPromise();
- promise.resolve(value);
- return promise;
+ return Promise.resolve(value);
}
- if (typeof (value = this.map[key2]) !== undefined || key2 in this.map ||
- typeof key3 === undefined) {
+ if (typeof (value = this.map[key2]) !== 'undefined' || key2 in this.map ||
+ typeof key3 === 'undefined') {
if (xref) {
return xref.fetchIfRefAsync(value);
}
- promise = new LegacyPromise();
- promise.resolve(value);
- return promise;
+ return Promise.resolve(value);
}
value = this.map[key3] || null;
if (xref) {
return xref.fetchIfRefAsync(value);
}
- promise = new LegacyPromise();
- promise.resolve(value);
- return promise;
+ return Promise.resolve(value);
},
// no dereferencing
@@ -5300,10 +3251,52 @@ var Dict = (function DictClosure() {
// creates new map and dereferences all Refs
getAll: function Dict_getAll() {
- var all = {};
- for (var key in this.map) {
- var obj = this.get(key);
- all[key] = obj instanceof Dict ? obj.getAll() : obj;
+ 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;
},
@@ -5323,6 +3316,8 @@ var Dict = (function DictClosure() {
}
};
+ Dict.empty = new Dict(null);
+
return Dict;
})();
@@ -5332,13 +3327,23 @@ var Ref = (function RefClosure() {
this.gen = gen;
}
- Ref.prototype = {};
+ 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.
+// 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 = {};
@@ -5346,15 +3351,15 @@ var RefSet = (function RefSetClosure() {
RefSet.prototype = {
has: function RefSet_has(ref) {
- return ('R' + ref.num + '.' + ref.gen) in this.dict;
+ return ref.toString() in this.dict;
},
put: function RefSet_put(ref) {
- this.dict['R' + ref.num + '.' + ref.gen] = true;
+ this.dict[ref.toString()] = true;
},
remove: function RefSet_remove(ref) {
- delete this.dict['R' + ref.num + '.' + ref.gen];
+ delete this.dict[ref.toString()];
}
};
@@ -5368,15 +3373,19 @@ var RefSetCache = (function RefSetCacheClosure() {
RefSetCache.prototype = {
get: function RefSetCache_get(ref) {
- return this.dict['R' + ref.num + '.' + ref.gen];
+ return this.dict[ref.toString()];
},
has: function RefSetCache_has(ref) {
- return ('R' + ref.num + '.' + ref.gen) in this.dict;
+ return ref.toString() in this.dict;
},
put: function RefSetCache_put(ref, obj) {
- this.dict['R' + ref.num + '.' + ref.gen] = 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) {
@@ -5399,7 +3408,7 @@ var Catalog = (function CatalogClosure() {
this.xref = xref;
this.catDict = xref.getCatalogObj();
this.fontCache = new RefSetCache();
- assertWellFormed(isDict(this.catDict),
+ assert(isDict(this.catDict),
'catalog object is not a dictionary');
this.pagePromises = [];
@@ -5408,11 +3417,12 @@ var Catalog = (function CatalogClosure() {
Catalog.prototype = {
get metadata() {
var streamRef = this.catDict.getRaw('Metadata');
- if (!isRef(streamRef))
+ if (!isRef(streamRef)) {
return shadow(this, 'metadata', null);
+ }
- var encryptMetadata = !this.xref.encrypt ? false :
- this.xref.encrypt.encryptMetadata;
+ var encryptMetadata = (!this.xref.encrypt ? false :
+ this.xref.encrypt.encryptMetadata);
var stream = this.xref.fetch(streamRef, !encryptMetadata);
var metadata;
@@ -5439,7 +3449,7 @@ var Catalog = (function CatalogClosure() {
},
get toplevelPagesDict() {
var pagesObj = this.catDict.get('Pages');
- assertWellFormed(isDict(pagesObj), 'invalid top-level pages dictionary');
+ assert(isDict(pagesObj), 'invalid top-level pages dictionary');
// shadow the prototype getter
return shadow(this, 'toplevelPagesDict', pagesObj);
},
@@ -5470,17 +3480,20 @@ var Catalog = (function CatalogClosure() {
while (queue.length > 0) {
var i = queue.shift();
var outlineDict = xref.fetchIfRef(i.obj);
- if (outlineDict === null)
+ if (outlineDict === null) {
continue;
- if (!outlineDict.has('Title'))
+ }
+ if (!outlineDict.has('Title')) {
error('Invalid outline item');
+ }
var dest = outlineDict.get('A');
- if (dest)
+ if (dest) {
dest = dest.get('D');
- else if (outlineDict.has('Dest')) {
+ } else if (outlineDict.has('Dest')) {
dest = outlineDict.getRaw('Dest');
- if (isName(dest))
+ if (isName(dest)) {
dest = dest.name;
+ }
}
var title = outlineDict.get('Title');
var outlineItem = {
@@ -5506,11 +3519,11 @@ var Catalog = (function CatalogClosure() {
}
}
}
- return root.items.length > 0 ? root.items : null;
+ return (root.items.length > 0 ? root.items : null);
},
get numPages() {
var obj = this.toplevelPagesDict.get('Count');
- assertWellFormed(
+ assert(
isInt(obj),
'page count in top level pages object is not an integer'
);
@@ -5525,16 +3538,19 @@ var Catalog = (function CatalogClosure() {
var xref = this.xref;
var dests = {}, nameTreeRef, nameDictionaryRef;
var obj = this.catDict.get('Names');
- if (obj)
+ if (obj && obj.has('Dests')) {
nameTreeRef = obj.getRaw('Dests');
- else if (this.catDict.has('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 (!value) {
+ return;
+ }
dests[key] = fetchDestination(value);
});
}
@@ -5550,6 +3566,62 @@ var Catalog = (function CatalogClosure() {
}
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');
@@ -5562,7 +3634,7 @@ var Catalog = (function CatalogClosure() {
if (!names.hasOwnProperty(name)) {
continue;
}
- // We don't really use the JavaScript right now so this code is
+ // 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)) {
@@ -5582,15 +3654,37 @@ var Catalog = (function CatalogClosure() {
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() {
- this.fontCache.forEach(function (font) {
- delete font.sent;
- delete font.translated;
+ var promises = [];
+ this.fontCache.forEach(function (promise) {
+ promises.push(promise);
});
- this.fontCache.clear();
+ 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) {
@@ -5608,7 +3702,7 @@ var Catalog = (function CatalogClosure() {
},
getPageDict: function Catalog_getPageDict(pageIndex) {
- var promise = new LegacyPromise();
+ var capability = createPromiseCapability();
var nodesToVisit = [this.catDict.getRaw('Pages')];
var currentPageIndex = 0;
var xref = this.xref;
@@ -5621,7 +3715,7 @@ var Catalog = (function CatalogClosure() {
xref.fetchAsync(currentNode).then(function (obj) {
if ((isDict(obj, 'Page') || (isDict(obj) && !obj.has('Kids')))) {
if (pageIndex === currentPageIndex) {
- promise.resolve([obj, currentNode]);
+ capability.resolve([obj, currentNode]);
} else {
currentPageIndex++;
next();
@@ -5630,7 +3724,7 @@ var Catalog = (function CatalogClosure() {
}
nodesToVisit.push(obj);
next();
- }.bind(this), promise.reject.bind(promise));
+ }, capability.reject);
return;
}
@@ -5665,10 +3759,10 @@ var Catalog = (function CatalogClosure() {
}
}
}
- promise.reject('Page index ' + pageIndex + ' not found.');
+ capability.reject('Page index ' + pageIndex + ' not found.');
}
next();
- return promise;
+ return capability.promise;
},
getPageIndex: function Catalog_getPageIndex(ref) {
@@ -5698,8 +3792,8 @@ var Catalog = (function CatalogClosure() {
var found = false;
for (var i = 0; i < kids.length; i++) {
var kid = kids[i];
- assert(isRef(kid), 'kids must be an ref');
- if (kid.num == kidRef.num) {
+ assert(isRef(kid), 'kids must be a ref');
+ if (kid.num === kidRef.num) {
found = true;
break;
}
@@ -5743,13 +3837,16 @@ var Catalog = (function CatalogClosure() {
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 = {
@@ -5773,8 +3870,8 @@ var XRef = (function XRefClosure() {
if (encrypt) {
var ids = trailerDict.get('ID');
var fileId = (ids && ids.length) ? ids[0] : '';
- this.encrypt = new CipherTransformFactory(
- encrypt, fileId, this.password);
+ this.encrypt = new CipherTransformFactory(encrypt, fileId,
+ this.password);
}
// get the root dictionary (catalog) object
@@ -5798,9 +3895,9 @@ var XRef = (function XRefClosure() {
var obj = this.readXRefTable(parser);
// Sanity check
- if (!isCmd(obj, 'trailer'))
+ if (!isCmd(obj, 'trailer')) {
error('Invalid XRef table: could not find trailer dictionary');
-
+ }
// Read trailer dictionary, e.g.
// trailer
// << /Size 22
@@ -5811,9 +3908,14 @@ var XRef = (function XRefClosure() {
// The parser goes through the entire stream << ... >> and provides
// a getter interface for the key-value table
var dict = parser.getObj();
- if (!isDict(dict))
- error('Invalid XRef table: could not parse trailer dictionary');
+ // 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;
@@ -5850,9 +3952,9 @@ var XRef = (function XRefClosure() {
var first = tableState.firstEntryNum;
var count = tableState.entryCount;
- if (!isInt(first) || !isInt(count))
+ 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;
@@ -5865,21 +3967,21 @@ var XRef = (function XRefClosure() {
entry.gen = parser.getObj();
var type = parser.getObj();
- if (isCmd(type, 'f'))
+ if (isCmd(type, 'f')) {
entry.free = true;
- else if (isCmd(type, 'n'))
+ } else if (isCmd(type, 'n')) {
entry.uncompressed = true;
+ }
// Validate entry obj
if (!isInt(entry.offset) || !isInt(entry.gen) ||
!(entry.free || entry.uncompressed)) {
- console.log(entry.offset, entry.gen, entry.free,
- entry.uncompressed);
error('Invalid entry in XRef subsection: ' + first + ', ' + count);
}
- if (!this.entries[i + first])
+ if (!this.entries[i + first]) {
this.entries[i + first] = entry;
+ }
}
tableState.entryNum = 0;
@@ -5897,9 +3999,9 @@ var XRef = (function XRefClosure() {
}
// Sanity check: as per spec, first object must be free
- if (this.entries[0] && !this.entries[0].free)
+ if (this.entries[0] && !this.entries[0].free) {
error('Invalid XRef table: unexpected first object');
-
+ }
return obj;
},
@@ -5939,13 +4041,12 @@ var XRef = (function XRefClosure() {
var entryRanges = streamState.entryRanges;
while (entryRanges.length > 0) {
-
var first = entryRanges[0];
var n = entryRanges[1];
- if (!isInt(first) || !isInt(n))
+ 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);
@@ -5955,15 +4056,19 @@ var XRef = (function XRefClosure() {
streamState.streamPos = stream.pos;
var type = 0, offset = 0, generation = 0;
- for (j = 0; j < typeFieldWidth; ++j)
+ for (j = 0; j < typeFieldWidth; ++j) {
type = (type << 8) | stream.getByte();
- // if type field is absent, its default value = 1
- if (typeFieldWidth === 0)
+ }
+ // if type field is absent, its default value is 1
+ if (typeFieldWidth === 0) {
type = 1;
- for (j = 0; j < offsetFieldWidth; ++j)
+ }
+ for (j = 0; j < offsetFieldWidth; ++j) {
offset = (offset << 8) | stream.getByte();
- for (j = 0; j < generationFieldWidth; ++j)
+ }
+ for (j = 0; j < generationFieldWidth; ++j) {
generation = (generation << 8) | stream.getByte();
+ }
var entry = {};
entry.offset = offset;
entry.gen = generation;
@@ -5979,8 +4084,9 @@ var XRef = (function XRefClosure() {
default:
error('Invalid XRef entry type: ' + type);
}
- if (!this.entries[first + i])
+ if (!this.entries[first + i]) {
this.entries[first + i] = entry;
+ }
}
streamState.entryNum = 0;
@@ -5988,14 +4094,16 @@ var XRef = (function XRefClosure() {
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)
+ if (++offset >= data.length) {
break;
+ }
token += String.fromCharCode(ch);
ch = data[offset];
}
@@ -6007,11 +4115,12 @@ var XRef = (function XRefClosure() {
// finding byte sequence
while (offset < dataLength) {
var i = 0;
- while (i < length && data[offset + i] == what[i])
+ while (i < length && data[offset + i] === what[i]) {
++i;
- if (i >= length)
+ }
+ if (i >= length) {
break; // sequence found
-
+ }
offset++;
skipped++;
}
@@ -6028,8 +4137,6 @@ var XRef = (function XRefClosure() {
var buffer = stream.getBytes();
var position = stream.start, length = buffer.length;
var trailers = [], xrefStms = [];
- var state = 0;
- var currentToken;
while (position < length) {
var ch = buffer[position];
if (ch === 32 || ch === 9 || ch === 13 || ch === 10) {
@@ -6072,32 +4179,38 @@ var XRef = (function XRefClosure() {
}
position += contentLength;
- } else
+ } else {
position += token.length + 1;
+ }
}
// reading XRef streams
- for (var i = 0, ii = xrefStms.length; i < ii; ++i) {
+ 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 (var i = 0, ii = trailers.length; i < ii; ++i) {
+ for (i = 0, ii = trailers.length; i < ii; ++i) {
stream.pos = trailers[i];
- var parser = new Parser(new Lexer(stream), true, null);
+ var parser = new Parser(new Lexer(stream), true, this);
var obj = parser.getObj();
- if (!isCmd(obj, 'trailer'))
+ if (!isCmd(obj, 'trailer')) {
continue;
+ }
// read the trailer dictionary
- if (!isDict(dict = parser.getObj()))
+ if (!isDict(dict = parser.getObj())) {
continue;
+ }
// taking the first one with 'ID'
- if (dict.has('ID'))
+ if (dict.has('ID')) {
return dict;
+ }
}
// no tailer with 'ID', taking last one (if exists)
- if (dict)
+ if (dict) {
return dict;
+ }
// nothing helps
// calling error() would reject worker with an UnknownErrorException.
throw new InvalidPDFException('Invalid PDF structure');
@@ -6110,15 +4223,14 @@ var XRef = (function XRefClosure() {
while (this.startXRefQueue.length) {
var startXRef = this.startXRefQueue[0];
- stream.pos = startXRef;
+ stream.pos = startXRef + stream.start;
- var parser = new Parser(new Lexer(stream), true, null);
+ 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) {
@@ -6137,7 +4249,6 @@ var XRef = (function XRefClosure() {
}
}
} else if (isInt(obj)) {
-
// Parse in-stream XRef
if (!isInt(parser.getObj()) ||
!isCmd(parser.getObj(), 'obj') ||
@@ -6148,9 +4259,9 @@ var XRef = (function XRefClosure() {
if (!this.topDict) {
this.topDict = dict;
}
-
- if (!dict)
+ if (!dict) {
error('Failed to read XRef stream');
+ }
} else {
error('Invalid XRef stream header');
}
@@ -6176,95 +4287,109 @@ var XRef = (function XRefClosure() {
info('(while reading XRef): ' + e);
}
- if (recoveryMode)
+ if (recoveryMode) {
return;
+ }
throw new XRefParseException();
},
getEntry: function XRef_getEntry(i) {
- var e = this.entries[i];
- if (e === null)
- return null;
- return e.free || !e.offset ? null : e; // returns null if entry is free
+ var xrefEntry = this.entries[i];
+ if (xrefEntry && !xrefEntry.free && xrefEntry.offset) {
+ return xrefEntry;
+ }
+ return null;
},
+
fetchIfRef: function XRef_fetchIfRef(obj) {
- if (!isRef(obj))
+ if (!isRef(obj)) {
return obj;
+ }
return this.fetch(obj);
},
+
fetch: function XRef_fetch(ref, suppressEncryption) {
- assertWellFormed(isRef(ref), 'ref object is not a reference');
+ assert(isRef(ref), 'ref object is not a reference');
var num = ref.num;
- var e;
if (num in this.cache) {
- e = this.cache[num];
- if (e instanceof Stream) {
- return e.makeSubStream(e.start, e.length, e.dict);
- }
- return e;
+ var cacheEntry = this.cache[num];
+ return cacheEntry;
}
- e = this.getEntry(num);
+ var xrefEntry = this.getEntry(num);
// the referenced entry can be free
- if (e === null)
- return (this.cache[num] = e);
-
- var gen = ref.gen;
- var stream, parser;
- if (e.uncompressed) {
- if (e.gen != gen)
- error('inconsistent generation in XRef');
- stream = this.stream.makeSubStream(e.offset);
- parser = new Parser(new Lexer(stream), true, this);
- var obj1 = parser.getObj();
- var obj2 = parser.getObj();
- var obj3 = parser.getObj();
- if (!isInt(obj1) || obj1 != num ||
- !isInt(obj2) || obj2 != 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) {
- try {
- e = parser.getObj(this.encrypt.createCipherTransform(num, gen));
- } catch (ex) {
- // almost all streams must be encrypted, but sometimes
- // they are not probably due to some broken generators
- // re-trying without encryption
- return this.fetch(ref, true);
- }
- } else {
- e = parser.getObj();
- }
- if (!isStream(e)) {
- this.cache[num] = e;
- }
- return e;
+ if (xrefEntry === null) {
+ return (this.cache[num] = null);
}
- // compressed entry
- var tableOffset = e.offset;
- stream = this.fetch(new Ref(tableOffset, 0));
- if (!isStream(stream))
+ 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');
}
- parser = new Parser(new Lexer(stream), false, this);
+ var parser = new Parser(new Lexer(stream), false, this);
parser.allowStreams = true;
- var i, entries = [], nums = [];
+ var i, entries = [], num, nums = [];
// read the object numbers to populate cache
for (i = 0; i < n; ++i) {
num = parser.getObj();
@@ -6286,36 +4411,38 @@ var XRef = (function XRefClosure() {
this.cache[num] = entries[i];
}
}
- e = entries[e.gen];
- if (e === undefined) {
+ xrefEntry = entries[xrefEntry.gen];
+ if (xrefEntry === undefined) {
error('bad XRef entry for compressed object');
}
- return e;
+ return xrefEntry;
},
+
fetchIfRefAsync: function XRef_fetchIfRefAsync(obj) {
if (!isRef(obj)) {
- var promise = new LegacyPromise();
- promise.resolve(obj);
- return promise;
+ return Promise.resolve(obj);
}
return this.fetchAsync(obj);
},
+
fetchAsync: function XRef_fetchAsync(ref, suppressEncryption) {
- var promise = new LegacyPromise();
- var tryFetch = function (promise) {
+ var streamManager = this.stream.manager;
+ var xref = this;
+ return new Promise(function tryFetch(resolve, reject) {
try {
- promise.resolve(this.fetch(ref, suppressEncryption));
+ resolve(xref.fetch(ref, suppressEncryption));
} catch (e) {
if (e instanceof MissingDataException) {
- this.stream.manager.requestRange(e.begin, e.end, tryFetch);
+ streamManager.requestRange(e.begin, e.end, function () {
+ tryFetch(resolve, reject);
+ });
return;
}
- promise.reject(e);
+ reject(e);
}
- }.bind(this, promise);
- tryFetch();
- return promise;
+ });
},
+
getCatalogObj: function XRef_getCatalogObj() {
return this.root;
}
@@ -6325,8 +4452,8 @@ var XRef = (function XRefClosure() {
})();
/**
- * A NameTree is like a Dict but has some adventagous properties, see the spec
- * (7.9.6) for more details.
+ * 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() {
@@ -6356,8 +4483,9 @@ var NameTree = (function NameTreeClosure() {
var kids = obj.get('Kids');
for (i = 0, n = kids.length; i < n; i++) {
var kid = kids[i];
- if (processed.has(kid))
+ if (processed.has(kid)) {
error('invalid destinations');
+ }
queue.push(kid);
processed.put(kid);
}
@@ -6371,11 +4499,172 @@ var NameTree = (function NameTreeClosure() {
}
}
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
@@ -6388,12 +4677,12 @@ var NameTree = (function NameTreeClosure() {
* 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)) {
@@ -6402,14 +4691,14 @@ var ObjectLoader = (function() {
map = node.dict.map;
}
for (var key in map) {
- var value = map[key];
+ value = map[key];
if (mayHaveChildren(value)) {
nodesToVisit.push(value);
}
}
} else if (isArray(node)) {
for (var i = 0, ii = node.length; i < ii; i++) {
- var value = node[i];
+ value = node[i];
if (mayHaveChildren(value)) {
nodesToVisit.push(value);
}
@@ -6425,15 +4714,14 @@ var ObjectLoader = (function() {
}
ObjectLoader.prototype = {
-
load: function ObjectLoader_load() {
var keys = this.keys;
- this.promise = new LegacyPromise();
+ 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.promise.resolve();
- return this.promise;
+ this.capability.resolve();
+ return this.capability.promise;
}
this.refSet = new RefSet();
@@ -6444,7 +4732,7 @@ var ObjectLoader = (function() {
}
this.walk(nodesToVisit);
- return this.promise;
+ return this.capability.promise;
},
walk: function ObjectLoader_walk(nodesToVisit) {
@@ -6511,17 +4799,14 @@ var ObjectLoader = (function() {
}
// Everything is loaded.
this.refSet = null;
- this.promise.resolve();
+ this.capability.resolve();
}
-
};
return ObjectLoader;
})();
-
-
var ISOAdobeCharset = [
'.notdef', 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar',
'percent', 'ampersand', 'quoteright', 'parenleft', 'parenright',
@@ -6624,6935 +4909,2868 @@ var ExpertSubsetCharset = [
-var CIDToUnicodeMaps = {
- 'Adobe-Japan1': [[32, 160], {f: 12, c: 33}, [45, 8209], {f: 46, c: 46}, 165,
- {f: 2, c: 93}, [95, 818], [96, 768], {f: 27, c: 97}, 166, 125, [732, 771],
- [700, 8217], 92, [699, 8216], 124, [126, 8764], {f: 3, c: 161}, 8260, 402,
- 0, 164, 8220, 171, {f: 2, c: 8249}, {f: 2, c: 64257}, [8210, 8211], 0, 0,
- [183, 8729], 0, 8226, 8218, 8222, 8221, 187, 0, 0, 191, {f: 2, c: 769},
- [175, 772], {f: 3, c: 774}, 778, [184, 807], 779, 808, 780, [822, 8212],
- 198, 170, 321, 216, 338, 186, 230, 305, 322, 248, 339, 223, 173, 169, 172,
- 174, 0, 0, {f: 2, c: 178}, 181, 185, {f: 3, c: 188}, {f: 6, c: 192},
- {f: 16, c: 199}, 0, {f: 6, c: 217}, {f: 6, c: 224}, {f: 16, c: 231}, 0,
- {f: 7, c: 249}, 352, 376, 381, [773, 8254], 353, 8482, 382, 0, 8194,
- {f: 59, c: 33}, 165, {f: 31, c: 93}, 65512, {f: 2, c: 125}, 0,
- {f: 63, c: 65377}, {s: 243}, [8195, 12288],
- {f: 2, c: 12289}, 65292, 65294, 12539, {f: 2, c: 65306}, 65311, 65281,
- {f: 2, c: 12443}, 180, 65344, 168, 65342, 65507, 65343, {f: 2, c: 12541},
- {f: 2, c: 12445}, 12291, 20189, {f: 3, c: 12293}, 12540, 8213, 8208, 65295,
- 65340, [12316, 65374], 8214, 65372, 8230, 8229, {s: 4}, {f: 2, c: 65288},
- {f: 2, c: 12308}, 65339, 65341, 65371, 65373, {f: 10, c: 12296}, 65291,
- [8722, 65293], 177, 215, 247, 65309, 8800, 65308, 65310, {f: 2, c: 8806},
- 8734, 8756, 9794, 9792, 176, {f: 2, c: 8242}, 8451, 65509, 65284,
- {f: 2, c: 65504}, 65285, 65283, 65286, 65290, 65312, 167, 9734, 9733, 9675,
- 9679, 9678, 9671, 9670, 9633, 9632, 9651, 9650, 9661, 9660, 8251, 12306,
- 8594, {f: 2, c: 8592}, 8595, 12307, 8712, 8715, {f: 2, c: 8838},
- {f: 2, c: 8834}, 8746, 8745, {f: 2, c: 8743}, 65506, 8658, 8660, 8704,
- 8707, 8736, 8869, 8978, 8706, 8711, 8801, 8786, {f: 2, c: 8810}, 8730,
- 8765, 8733, 8757, {f: 2, c: 8747}, 8491, 8240, 9839, 9837, 9834,
- {f: 2, c: 8224}, 182, 9711, {f: 10, c: 65296}, {f: 26, c: 65313},
- {f: 26, c: 65345}, {f: 83, c: 12353}, {f: 86, c: 12449}, {f: 17, c: 913},
- {f: 7, c: 931}, {f: 17, c: 945}, {f: 7, c: 963}, {f: 6, c: 1040}, 1025,
- {f: 32, c: 1046}, 1105, {f: 26, c: 1078}, 20124, 21782, 23043, 38463,
- 21696, 24859, 25384, 23030, 36898, 33909, 33564, 31312, 24746, 25569,
- 28197, 26093, 33894, 33446, 39925, 26771, 22311, 26017, 25201, 23451,
- 22992, 34427, 39156, 32098, 32190, 39822, 25110, 31903, 34999, 23433,
- 24245, 25353, 26263, 26696, 38343, 38797, 26447, 20197, 20234, 20301,
- 20381, 20553, 22258, 22839, 22996, 23041, 23561, 24799, 24847, 24944,
- 26131, 26885, 28858, 30031, 30064, 31227, 32173, 32239, 32963, 33806,
- [12176, 34915], 35586, 36949, 36986, 21307, 20117, 20133, 22495, 32946,
- 37057, 30959, [12032, 19968], 22769, 28322, 36920, 31282, 33576, 33419,
- 39983, 20801, 21360, 21693, 21729, 22240, 23035, 24341, 39154, 28139,
- 32996, 34093, 38498, 38512, 38560, 38907, 21515, 21491, 23431, 28879,
- [12155, 32701], 36802, [12204, 38632], 21359, 40284, 31418, 19985, 30867,
- [12165, 33276], 28198, 22040, 21764, 27421, 34074, 39995, 23013, 21417,
- 28006, [12128, 29916], 38287, 22082, 20113, 36939, 38642, 33615, 39180,
- 21473, 21942, 23344, 24433, 26144, 26355, 26628, 27704, 27891, 27945,
- 29787, 30408, 31310, 38964, 33521, 34907, 35424, 37613, 28082, 30123,
- 30410, 39365, 24742, 35585, 36234, 38322, 27022, 21421, 20870, 22290,
- 22576, 22852, 23476, 24310, 24616, 25513, 25588, 27839, 28436, 28814,
- 28948, 29017, 29141, 29503, 32257, 33398, 33489, 34199, 36960, 37467,
- 40219, 22633, 26044, 27738, 29989, 20985, 22830, 22885, 24448, 24540,
- 25276, 26106, 27178, 27431, 27572, 29579, 32705, 35158, 40236, 40206,
- [12009, 40644], 23713, 27798, 33659, 20740, 23627, 25014, 33222, 26742,
- 29281, [12036, 20057], 20474, 21368, 24681, 28201, 31311, [12211, 38899],
- 19979, 21270, 20206, 20309, 20285, 20385, 20339, 21152, 21487, 22025,
- 22799, 23233, 23478, 23521, 31185, 26247, 26524, 26550, 27468, 27827,
- [12117, 28779], 29634, 31117, [12146, 31166], 31292, 31623, 33457, 33499,
- 33540, 33655, 33775, 33747, 34662, 35506, 22057, 36008, 36838, 36942,
- 38686, 34442, 20420, 23784, 25105, [12123, 29273], 30011, 33253, 33469,
- 34558, 36032, 38597, 39187, 39381, 20171, 20250, 35299, 22238, 22602,
- 22730, 24315, 24555, 24618, 24724, 24674, 25040, 25106, 25296, 25913,
- 39745, 26214, 26800, 28023, 28784, 30028, 30342, 32117, 33445, 34809,
- 38283, 38542, [12185, 35997], 20977, 21182, 22806, 21683, 23475, 23830,
- 24936, 27010, 28079, 30861, 33995, 34903, 35442, 37799, 39608, 28012,
- 39336, 34521, 22435, 26623, 34510, 37390, 21123, 22151, 21508, 24275,
- 25313, 25785, 26684, 26680, 27579, 29554, 30906, 31339, 35226,
- [12179, 35282], 36203, 36611, 37101, 38307, 38548, [12208, 38761], 23398,
- 23731, 27005, {f: 2, c: 38989}, 25499, 31520, 27179, 27263, 26806, 39949,
- 28511, 21106, 21917, 24688, 25324, 27963, 28167, 28369, 33883, 35088,
- 36676, 19988, 39993, 21494, 26907, 27194, 38788, 26666, 20828, 31427,
- 33970, 37340, 37772, 22107, 40232, 26658, 33541, 33841, 31909, 21000,
- 33477, [12129, 29926], 20094, 20355, 20896, 23506, 21002, 21208, 21223,
- 24059, 21914, 22570, 23014, 23436, 23448, 23515, [12082, 24178], 24185,
- 24739, 24863, 24931, 25022, 25563, 25954, 26577, 26707, 26874, 27454,
- 27475, 27735, 28450, 28567, 28485, 29872, [12130, 29976], 30435, 30475,
- 31487, 31649, 31777, 32233, [12152, 32566], 32752, 32925, 33382, 33694,
- 35251, 35532, 36011, 36996, 37969, 38291, 38289, 38306, 38501, 38867,
- 39208, 33304, 20024, 21547, 23736, 24012, 29609, 30284, 30524, 23721,
- 32747, 36107, 38593, 38929, 38996, 39000, 20225, 20238, 21361, 21916,
- 22120, 22522, 22855, 23305, 23492, 23696, 24076, 24190, 24524, 25582,
- 26426, 26071, 26082, 26399, 26827, 26820, 27231, 24112, 27589, 27671,
- 27773, 30079, 31048, 23395, 31232, 32000, 24509, 35215, 35352, 36020,
- 36215, 36556, 36637, 39138, 39438, [12004, 12225, 39740], [12018, 20096],
- 20605, 20736, 22931, 23452, 25135, 25216, 25836, 27450, 29344, 30097,
- 31047, 32681, 34811, 35516, 35696, 25516, 33738, 38816, 21513, 21507,
- 21931, 26708, 27224, 35440, 30759, 26485, [12233, 40653], 21364, 23458,
- 33050, 34384, 36870, 19992, 20037, 20167, 20241, 21450, 21560, 23470,
- [12088, 24339], 24613, 25937, 26429, 27714, 27762, 27875, 28792, 29699,
- 31350, 31406, 31496, 32026, 31998, 32102, 26087, [12124, 29275], 21435,
- 23621, 24040, 25298, 25312, 25369, 28192, 34394, 35377, 36317, 37624,
- 28417, 31142, [12226, 39770], 20136, {f: 2, c: 20139}, 20379, 20384, 20689,
- 20807, 31478, 20849, 20982, 21332, 21281, 21375, 21483, 21932, 22659,
- 23777, 24375, 24394, 24623, 24656, 24685, 25375, 25945, 27211, 27841,
- 29378, 29421, 30703, 33016, 33029, 33288, 34126, 37111, 37857, 38911,
- 39255, 39514, 20208, 20957, 23597, 26241, 26989, 23616, 26354, 26997,
- [12127, 29577], 26704, 31873, 20677, 21220, 22343, [12081, 24062], 37670,
- [12100, 26020], 27427, 27453, 29748, 31105, 31165, 31563, 32202, 33465,
- 33740, 34943, 35167, 35641, 36817, [12198, 37329], 21535, 37504, 20061,
- 20534, 21477, 21306, 29399, 29590, 30697, 33510, 36527, 39366, 39368,
- 39378, 20855, 24858, 34398, 21936, 31354, 20598, 23507, 36935, 38533,
- 20018, 27355, 37351, 23633, 23624, 25496, 31391, 27795, 38772, 36705,
- 31402, 29066, 38536, 31874, 26647, 32368, 26705, 37740, 21234, 21531,
- 34219, 35347, 32676, 36557, 37089, 21350, 34952, 31041, 20418, 20670,
- 21009, 20804, 21843, 22317, 29674, 22411, 22865, 24418, 24452, 24693,
- 24950, 24935, 25001, 25522, 25658, 25964, 26223, 26690, 28179, 30054,
- 31293, 31995, 32076, 32153, 32331, 32619, 33550, 33610, 34509, 35336,
- 35427, 35686, 36605, 38938, 40335, 33464, 36814, 39912, 21127, 25119,
- 25731, 28608, 38553, 26689, 20625, [12107, 27424], 27770, 28500,
- [12147, 31348], 32080, [12174, 34880], 35363, [12105, 26376], 20214, 20537,
- 20518, 20581, 20860, 21048, 21091, 21927, 22287, 22533, 23244, 24314,
- 25010, 25080, 25331, 25458, 26908, 27177, 29309, [12125, 29356], 29486,
- 30740, 30831, 32121, 30476, 32937, [12178, 35211], 35609, 36066, 36562,
- 36963, 37749, 38522, 38997, 39443, 40568, 20803, 21407, 21427, 24187,
- 24358, 28187, 28304, [12126, 29572], 29694, 32067, 33335, [12180, 35328],
- 35578, 38480, 20046, 20491, 21476, 21628, 22266, 22993, 23396,
- [12080, 24049], 24235, 24359, [12094, 25144], 25925, 26543, 28246, 29392,
- 31946, 34996, 32929, 32993, 33776, [11969, 34382], 35463, 36328, 37431,
- 38599, 39015, [12238, 40723], 20116, 20114, 20237, 21320, 21577, 21566,
- 23087, 24460, 24481, 24735, 26791, 27278, 29786, 30849, 35486, 35492,
- 35703, 37264, 20062, 39881, 20132, 20348, 20399, 20505, 20502, 20809,
- 20844, 21151, 21177, 21246, 21402, [12061, 21475], 21521, 21518, 21897,
- 22353, 22434, 22909, 23380, 23389, 23439, [12079, 24037], 24039, 24055,
- 24184, 24195, 24218, 24247, 24344, 24658, 24908, 25239, 25304, 25511,
- 25915, 26114, 26179, 26356, 26477, 26657, 26775, 27083, 27743, 27946,
- 28009, 28207, 28317, 30002, 30343, 30828, 31295, 31968, 32005, 32024,
- 32094, 32177, 32789, 32771, 32943, 32945, 33108, 33167, 33322, 33618,
- [12175, 34892], 34913, 35611, 36002, 36092, 37066, 37237, 37489, 30783,
- 37628, 38308, 38477, 38917, [12217, 39321], [12220, 39640], 40251, 21083,
- 21163, 21495, 21512, 22741, 25335, 28640, 35946, 36703, 40633, 20811,
- 21051, 21578, 22269, 31296, 37239, 40288, [12234, 40658], 29508, 28425,
- 33136, 29969, 24573, 24794, [12219, 39592], 29403, 36796, 27492, 38915,
- 20170, 22256, 22372, 22718, 23130, 24680, 25031, 26127, 26118, 26681,
- 26801, 28151, 30165, 32058, [12169, 33390], 39746, 20123, 20304, 21449,
- 21766, 23919, 24038, 24046, 26619, 27801, 29811, 30722, 35408, 37782,
- 35039, 22352, 24231, 25387, 20661, 20652, 20877, 26368, 21705, 22622,
- 22971, 23472, 24425, 25165, 25505, 26685, 27507, 28168, 28797, 37319,
- 29312, 30741, 30758, 31085, 25998, 32048, 33756, 35009, 36617, 38555,
- 21092, 22312, 26448, 32618, 36001, 20916, 22338, 38442, 22586, 27018,
- 32948, 21682, 23822, 22524, 30869, 40442, 20316, 21066, 21643, 25662,
- 26152, 26388, 26613, 31364, 31574, 32034, 37679, 26716, 39853, 31545,
- 21273, 20874, 21047, 23519, 25334, 25774, 25830, 26413, 27578, 34217,
- 38609, 30352, 39894, 25420, 37638, 39851, [12139, 30399], 26194, 19977,
- 20632, 21442, [12077, 23665], 24808, 25746, 25955, 26719, 29158, 29642,
- 29987, 31639, 32386, 34453, 35715, 36059, 37240, 39184, 26028, 26283,
- 27531, 20181, 20180, 20282, 20351, 21050, 21496, 21490, 21987, 22235,
- [12064, 22763], 22987, 22985, 23039, [12070, 23376], 23629, 24066, 24107,
- 24535, 24605, 25351, [12096, 25903], 23388, 26031, 26045, 26088, 26525,
- [12108, 27490], 27515, [12114, 27663], 29509, 31049, 31169, [12151, 31992],
- 32025, 32043, 32930, 33026, [12164, 33267], 35222, 35422, 35433, 35430,
- 35468, 35566, 36039, 36060, 38604, 39164, [12013, 27503], 20107, 20284,
- 20365, 20816, 23383, 23546, 24904, 25345, 26178, 27425, 28363, 27835,
- 29246, 29885, 30164, 30913, [12144, 31034], [12157, 32780], [12159, 32819],
- [12163, 33258], 33940, 36766, 27728, [12229, 40575], 24335, 35672, 40235,
- 31482, 36600, 23437, 38635, 19971, 21489, 22519, 22833, 23241, 23460,
- 24713, 28287, 28422, 30142, 36074, 23455, 34048, 31712, 20594, 26612,
- 33437, 23649, 34122, 32286, 33294, 20889, 23556, 25448, 36198, 26012,
- 29038, 31038, 32023, 32773, 35613, [12190, 36554], 36974, 34503, 37034,
- 20511, 21242, 23610, 26451, 28796, 29237, 37196, 37320, 37675, 33509,
- 23490, 24369, 24825, 20027, 21462, 23432, [12095, 25163], 26417, 27530,
- 29417, 29664, 31278, 33131, 36259, 37202, [12216, 39318], 20754, 21463,
- 21610, 23551, 25480, 27193, 32172, 38656, 22234, 21454, 21608, 23447,
- 23601, 24030, 20462, 24833, 25342, 27954, 31168, 31179, 32066, 32333,
- 32722, 33261, [12168, 33311], 33936, 34886, 35186, 35728, 36468, 36655,
- 36913, 37195, 37228, 38598, 37276, 20160, 20303, 20805, [12055, 21313],
- 24467, 25102, 26580, 27713, 28171, 29539, 32294, 37325, 37507, 21460,
- 22809, 23487, 28113, 31069, 32302, 31899, 22654, 29087, 20986, 34899,
- 36848, 20426, 23803, 26149, 30636, 31459, 33308, 39423, 20934, 24490,
- 26092, 26991, 27529, 28147, 28310, 28516, 30462, 32020, 24033, 36981,
- 37255, 38918, 20966, 21021, 25152, 26257, 26329, 28186, 24246, 32210,
- 32626, 26360, 34223, 34295, 35576, 21161, 21465, [12069, 22899], 24207,
- 24464, 24661, 37604, 38500, 20663, 20767, 21213, 21280, 21319, 21484,
- 21736, 21830, 21809, 22039, 22888, 22974, 23100, 23477, 23558,
- [12073, 23567], 23569, 23578, 24196, 24202, 24288, 24432, 25215, 25220,
- 25307, 25484, 25463, 26119, 26124, 26157, 26230, 26494, 26786, 27167,
- 27189, 27836, 28040, 28169, 28248, 28988, 28966, 29031, 30151, 30465,
- 30813, 30977, 31077, 31216, 31456, 31505, 31911, 32057, 32918, 33750,
- 33931, 34121, 34909, 35059, 35359, 35388, 35412, 35443, 35937, 36062,
- 37284, 37478, 37758, 37912, 38556, 38808, 19978, 19976, 19998, 20055,
- 20887, 21104, 22478, 22580, 22732, 23330, 24120, 24773, 25854, 26465,
- 26454, 27972, 29366, 30067, 31331, 33976, 35698, 37304, 37664, 22065,
- 22516, 39166, 25325, 26893, 27542, 29165, 32340, 32887, [12170, 33394],
- 35302, [12215, 39135], 34645, 36785, 23611, 20280, 20449, 20405, 21767,
- 23072, 23517, 23529, [12092, 24515], 24910, 25391, 26032, 26187, 26862,
- 27035, 28024, 28145, 30003, 30137, 30495, 31070, 31206, 32051,
- [12162, 33251], 33455, 34218, 35242, 35386, [12189, 36523], [12191, 36763],
- 36914, 37341, 38663, [12040, 20154], 20161, 20995, 22645, 22764, 23563,
- 29978, 23613, 33102, 35338, 36805, 38499, 38765, 31525, 35535, 38920,
- 37218, 22259, 21416, 36887, 21561, 22402, 24101, 25512, [12116, 27700],
- 28810, 30561, 31883, 32736, 34928, 36930, 37204, 37648, 37656, 38543,
- 29790, 39620, 23815, 23913, 25968, 26530, 36264, 38619, 25454, 26441,
- 26905, 33733, 38935, 38592, 35070, 28548, 25722, [12072, 23544], 19990,
- 28716, 30045, 26159, 20932, 21046, 21218, 22995, 24449, 24615, 25104,
- 25919, 25972, 26143, 26228, 26866, 26646, 27491, 28165, 29298,
- [12131, 29983], 30427, 31934, 32854, 22768, 35069, [11972, 35199], 35488,
- 35475, 35531, 36893, 37266, [11992, 38738], 38745, [12011, 25993], 31246,
- 33030, 38587, 24109, 24796, 25114, 26021, 26132, 26512, [12143, 30707],
- 31309, 31821, 32318, 33034, 36012, [12186, 36196], 36321, 36447, 30889,
- 20999, 25305, 25509, 25666, 25240, 35373, 31363, 31680, 35500, 38634,
- 32118, [12166, 33292], 34633, 20185, 20808, 21315, 21344, 23459, 23554,
- 23574, 24029, 25126, 25159, 25776, 26643, 26676, 27849, 27973, 27927,
- 26579, 28508, 29006, 29053, 26059, 31359, 31661, 32218, 32330, 32680,
- 33146, [12167, 33307], 33337, 34214, 35438, 36046, 36341, 36984, 36983,
- 37549, 37521, 38275, 39854, 21069, 21892, 28472, 28982, 20840, 31109,
- 32341, 33203, 31950, 22092, 22609, 23720, 25514, 26366, 26365, 26970,
- 29401, 30095, 30094, 30990, 31062, 31199, 31895, 32032, 32068, 34311,
- 35380, 38459, 36961, [12239, 40736], 20711, 21109, 21452, 21474, 20489,
- 21930, 22766, 22863, 29245, 23435, 23652, 21277, 24803, 24819, 25436,
- 25475, 25407, 25531, 25805, 26089, 26361, 24035, 27085, 27133, 28437,
- 29157, 20105, 30185, 30456, 31379, 31967, 32207, 32156, 32865, 33609,
- 33624, 33900, 33980, 34299, 35013, [12187, 36208], 36865, 36973, 37783,
- 38684, 39442, 20687, 22679, 24974, 33235, 34101, 36104, 36896, 20419,
- 20596, 21063, 21363, 24687, 25417, 26463, 28204, [12188, 36275], 36895,
- 20439, 23646, 36042, 26063, 32154, 21330, 34966, 20854, 25539, 23384,
- 23403, 23562, 25613, 26449, 36956, 20182, 22810, 22826, 27760, 35409,
- 21822, 22549, 22949, 24816, 25171, 26561, 33333, 26965, 38464, 39364,
- 39464, 20307, 22534, 23550, 32784, 23729, 24111, 24453, 24608, 24907,
- 25140, 26367, 27888, 28382, 32974, 33151, 33492, 34955, 36024, 36864,
- 36910, 38538, 40667, 39899, 20195, 21488, [12068, 22823], 31532, 37261,
- 38988, 40441, 28381, 28711, 21331, 21828, 23429, 25176, 25246, 25299,
- 27810, 28655, 29730, 35351, 37944, 28609, 35582, 33592, 20967, 34552,
- 21482, 21481, 20294, 36948, [12192, 36784], 22890, 33073, 24061, 31466,
- 36799, 26842, [12181, 35895], 29432, 40008, 27197, 35504, 20025, 21336,
- 22022, 22374, 25285, 25506, 26086, 27470, 28129, 28251, 28845, 30701,
- 31471, 31658, 32187, 32829, 32966, 34507, 35477, 37723, 22243, 22727,
- 24382, 26029, 26262, 27264, 27573, 30007, 35527, 20516, 30693, 22320,
- 24347, 24677, 26234, 27744, 30196, 31258, 32622, 33268, 34584, 36933,
- 39347, 31689, 30044, [12149, 31481], 31569, 33988, 36880, 31209, 31378,
- 33590, 23265, 30528, 20013, 20210, 23449, 24544, 25277, 26172, 26609,
- 27880, [12173, 34411], 34935, 35387, 37198, 37619, 39376, 27159, 28710,
- 29482, 33511, 33879, 36015, 19969, 20806, 20939, 21899, 23541, 24086,
- 24115, 24193, 24340, 24373, 24427, 24500, 25074, 25361, 26274, 26397,
- 28526, 29266, 30010, 30522, 32884, 33081, 33144, 34678, 35519, 35548,
- 36229, 36339, 37530, [11985, 12199, 38263], 38914, [12227, 40165], 21189,
- 25431, 30452, 26389, 27784, 29645, 36035, 37806, 38515, 27941, 22684,
- 26894, 27084, 36861, 37786, 30171, 36890, 22618, 26626, 25524, 27131,
- 20291, 28460, 26584, 36795, 34086, 32180, 37716, 26943, 28528, 22378,
- 22775, 23340, 32044, [12118, 29226], 21514, 37347, 40372, 20141, 20302,
- 20572, 20597, 21059, 35998, 21576, 22564, 23450, 24093, 24213, 24237,
- 24311, 24351, 24716, 25269, 25402, 25552, 26799, 27712, 30855, 31118,
- 31243, 32224, 33351, 35330, 35558, 36420, 36883, 37048, 37165, 37336,
- [12237, 40718], 27877, 25688, 25826, 25973, 28404, 30340, 31515, 36969,
- 37841, 28346, 21746, 24505, 25764, 36685, 36845, 37444, 20856, 22635,
- 22825, 23637, 24215, 28155, 32399, 29980, 36028, 36578, 39003, 28857,
- 20253, 27583, 28593, [12133, 30000], 38651, 20814, 21520, 22581, 22615,
- 22956, 23648, 24466, [12099, 26007], 26460, 28193, 30331, 33759, 36077,
- 36884, 37117, 37709, 30757, 30778, 21162, 24230, [12063, 22303], 22900,
- 24594, 20498, 20826, 20908, 20941, [12049, 20992], 21776, 22612, 22616,
- 22871, 23445, 23798, 23947, 24764, 25237, 25645, 26481, 26691, 26812,
- 26847, 30423, 28120, 28271, 28059, 28783, 29128, 24403, 30168, 31095,
- 31561, 31572, 31570, 31958, 32113, 21040, 33891, 34153, 34276, 35342,
- 35588, [12182, 35910], 36367, 36867, 36879, 37913, 38518, 38957, 39472,
- 38360, 20685, 21205, 21516, 22530, 23566, 24999, 25758, 27934, 30643,
- 31461, 33012, 33796, 36947, 37509, 23776, 40199, 21311, 24471, 24499,
- 28060, 29305, 30563, 31167, 31716, 27602, 29420, 35501, 26627, 27233,
- 20984, 31361, 26932, 23626, 40182, 33515, 23493, [12195, 37193], 28702,
- 22136, 23663, 24775, 25958, 27788, 35930, 36929, 38931, 21585, 26311,
- 37389, 22856, 37027, 20869, 20045, 20970, 34201, 35598, 28760, 25466,
- 37707, 26978, 39348, 32260, 30071, 21335, 26976, 36575, 38627, 27741,
- [12038, 20108], 23612, 24336, 36841, 21250, 36049, [12161, 32905], 34425,
- 24319, [12103, 26085], 20083, [12042, 20837], 22914, 23615, 38894, 20219,
- 22922, 24525, 35469, 28641, 31152, 31074, 23527, 33905, 29483, 29105,
- 24180, 24565, 25467, 25754, 29123, 31896, 20035, 24316, 20043, 22492,
- 22178, 24745, 28611, 32013, 33021, 33075, 33215, 36786, 35223, 34468,
- 24052, 25226, 25773, 35207, 26487, 27874, 27966, 29750, 30772, 23110,
- 32629, 33453, [12218, 39340], 20467, 24259, 25309, 25490, 25943, 26479,
- 30403, 29260, 32972, 32954, 36649, 37197, 20493, 22521, 23186, 26757,
- 26995, 29028, 29437, 36023, 22770, 36064, 38506, 36889, 34687, 31204,
- 30695, 33833, 20271, 21093, 21338, 25293, 26575, 27850, [12137, 30333],
- 31636, 31893, 33334, 34180, 36843, 26333, 28448, 29190, 32283, 33707,
- 39361, [12008, 40614], 20989, 31665, 30834, 31672, 32903, 31560, 27368,
- 24161, 32908, 30033, 30048, [12043, 20843], 37474, 28300, 30330, 37271,
- 39658, 20240, 32624, 25244, 31567, 38309, 40169, 22138, 22617, 34532,
- 38588, 20276, 21028, 21322, 21453, 21467, 24070, 25644, 26001, 26495,
- 27710, 27726, 29256, 29359, 29677, 30036, 32321, 33324, 34281, 36009,
- 31684, [12196, 37318], 29033, 38930, 39151, 25405, 26217, 30058, 30436,
- 30928, 34115, 34542, 21290, 21329, 21542, 22915, 24199, 24444, 24754,
- 25161, 25209, 25259, 26000, [12112, 27604], 27852, 30130, [12138, 30382],
- 30865, 31192, 32203, 32631, 32933, 34987, 35513, 36027, 36991,
- [12206, 38750], [12214, 39131], 27147, 31800, 20633, 23614, 24494, 26503,
- 27608, 29749, 30473, 32654, [12240, 40763], 26570, 31255, 21305,
- [12134, 30091], 39661, 24422, 33181, 33777, 32920, 24380, 24517, 30050,
- 31558, 36924, 26727, 23019, 23195, 32016, 30334, 35628, 20469, 24426,
- 27161, 27703, 28418, 29922, 31080, 34920, 35413, 35961, 24287, 25551,
- 30149, 31186, 33495, 37672, 37618, 33948, 34541, 39981, 21697, 24428,
- 25996, 27996, 28693, 36007, 36051, 38971, 25935, 29942, 19981, 20184,
- 22496, 22827, 23142, 23500, 20904, 24067, 24220, 24598, 25206, 25975,
- 26023, 26222, 28014, [12119, 29238], 31526, 33104, 33178, 33433, 35676,
- 36000, 36070, 36212, [12201, 38428], 38468, 20398, 25771, 27494, 33310,
- 33889, 34154, 37096, 23553, 26963, [12213, 39080], 33914, 34135, 20239,
- 21103, 24489, 24133, 26381, 31119, 33145, 35079, 35206, 28149, 24343,
- 25173, 27832, 20175, 29289, 39826, 20998, 21563, 22132, 22707, 24996,
- 25198, 28954, 22894, 31881, 31966, 32027, 38640, [12098, 25991], 32862,
- 19993, 20341, 20853, 22592, 24163, 24179, 24330, 26564, 20006, 34109,
- 38281, 38491, [12150, 31859], [12212, 38913], 20731, 22721, 30294, 30887,
- 21029, 30629, 34065, 31622, 20559, 22793, [12122, 29255], 31687, 32232,
- 36794, 36820, 36941, 20415, 21193, 23081, 24321, 38829, 20445, 33303,
- 37610, 22275, 25429, 27497, 29995, 35036, 36628, 31298, 21215, 22675,
- 24917, 25098, 26286, [11935, 27597], 31807, 33769, 20515, 20472, 21253,
- 21574, 22577, 22857, 23453, 23792, 23791, 23849, 24214, 25265, 25447,
- 25918, [12101, 26041], 26379, 27861, 27873, 28921, 30770, 32299, 32990,
- 33459, 33804, 34028, 34562, 35090, 35370, 35914, 37030, 37586, 39165,
- 40179, 40300, 20047, 20129, 20621, 21078, 22346, 22952, 24125,
- {f: 2, c: 24536}, 25151, 26292, 26395, 26576, 26834, 20882, 32033, 32938,
- 33192, 35584, 35980, 36031, 37502, 38450, 21536, 38956, 21271, 20693,
- [12056, 21340], 22696, 25778, 26420, 29287, 30566, 31302, 37350, 21187,
- 27809, 27526, 22528, 24140, 22868, 26412, 32763, 20961, 30406, 25705,
- 30952, 39764, [12231, 40635], 22475, 22969, 26151, 26522, 27598, 21737,
- 27097, 24149, 33180, 26517, 39850, 26622, 40018, 26717, 20134, 20451,
- [12060, 21448], 25273, 26411, 27819, 36804, 20397, 32365, 40639, 19975,
- 24930, 28288, 28459, 34067, 21619, 26410, 39749, [11922, 24051], 31637,
- 23724, 23494, 34588, 28234, 34001, 31252, 33032, 22937, 31885,
- [11936, 27665], 30496, 21209, 22818, 28961, 29279, [12141, 30683], 38695,
- 40289, 26891, 23167, 23064, 20901, 21517, 21629, 26126, 30431, 36855,
- 37528, 40180, 23018, 29277, 28357, 20813, 26825, 32191, 32236,
- [12207, 38754], 40634, 25720, 27169, 33538, 22916, 23391, [12113, 27611],
- 29467, 30450, 32178, 32791, 33945, 20786, [12106, 26408], 40665,
- [12140, 30446], 26466, 21247, 39173, 23588, 25147, 31870, 36016, 21839,
- 24758, 32011, [12200, 38272], 21249, 20063, 20918, 22812, 29242, 32822,
- 37326, 24357, [12142, 30690], 21380, 24441, 32004, 34220, 35379, 36493,
- 38742, 26611, 34222, 37971, 24841, 24840, 27833, 30290, 35565, 36664,
- 21807, 20305, 20778, 21191, 21451, 23461, 24189, 24736, 24962, 25558,
- 26377, 26586, 28263, 28044, {f: 2, c: 29494}, 30001, 31056, 35029, 35480,
- 36938, [12194, 37009], 37109, 38596, 34701, [12067, 22805], 20104, 20313,
- 19982, 35465, 36671, 38928, 20653, 24188, 22934, 23481, 24248, 25562,
- 25594, 25793, 26332, 26954, 27096, 27915, 28342, 29076, [12132, 29992],
- 31407, [12154, 32650], 32768, 33865, 33993, 35201, 35617, 36362, 36965,
- 38525, 39178, 24958, 25233, 27442, 27779, 28020, 32716, 32764, 28096,
- 32645, 34746, 35064, 26469, 33713, 38972, 38647, 27931, 32097, 33853,
- 37226, 20081, 21365, 23888, 27396, 28651, 34253, 34349, 35239, 21033,
- 21519, 23653, 26446, 26792, 29702, 29827, 30178, 35023, 35041,
- [12197, 37324], 38626, 38520, 24459, 29575, [12148, 31435], 33870, 25504,
- 30053, 21129, 27969, 28316, 29705, 30041, 30827, 31890, 38534,
- [12015, 31452], [12243, 40845], 20406, 24942, 26053, 34396, 20102, 20142,
- 20698, 20001, 20940, 23534, 26009, 26753, 28092, 29471, 30274, 30637,
- 31260, 31975, 33391, 35538, 36988, 37327, 38517, 38936, [12050, 21147],
- 32209, 20523, 21400, 26519, 28107, 29136, 29747, 33256, 36650, 38563,
- 40023, 40607, 29792, 22593, 28057, 32047, 39006, 20196, 20278, 20363,
- 20919, 21169, 23994, 24604, 29618, 31036, 33491, 37428, 38583, 38646,
- 38666, 40599, 40802, 26278, 27508, 21015, 21155, 28872, 35010, 24265,
- 24651, 24976, 28451, 29001, 31806, 32244, 32879, 34030, 36899, 37676,
- 21570, 39791, 27347, 28809, 36034, 36335, 38706, 21172, 23105, 24266,
- 24324, 26391, 27004, 27028, 28010, 28431, 29282, 29436, 31725,
- [12156, 32769], 32894, 34635, 37070, 20845, 40595, 31108, 32907, 37682,
- 35542, 20525, 21644, 35441, 27498, 36036, 33031, 24785, 26528, 40434,
- 20121, 20120, 39952, 35435, 34241, 34152, 26880, 28286, 30871, 33109,
- 24332, 19984, 19989, 20010, 20017, [12034, 20022], 20028, [12035, 20031],
- 20034, 20054, 20056, 20098, [12037, 20101], 35947, 20106, 33298, 24333,
- 20110, {f: 2, c: 20126}, [12039, 20128], 20130, 20144, 20147, 20150, 20174,
- 20173, 20164, 20166, 20162, 20183, 20190, 20205, 20191, 20215, 20233,
- 20314, 20272, 20315, 20317, 20311, 20295, 20342, 20360, 20367, 20376,
- 20347, 20329, 20336, 20369, 20335, 20358, 20374, 20760, 20436, 20447,
- 20430, 20440, 20443, 20433, 20442, 20432, {f: 2, c: 20452}, 20506, 20520,
- 20500, 20522, 20517, 20485, 20252, 20470, 20513, 20521, 20524, 20478,
- 20463, 20497, 20486, 20547, 20551, 26371, 20565, 20560, 20552, 20570,
- 20566, 20588, 20600, 20608, 20634, 20613, 20660, 20658, {f: 2, c: 20681},
- 20659, 20674, 20694, 20702, 20709, 20717, 20707, 20718, 20729, 20725,
- 20745, {f: 2, c: 20737}, 20758, 20757, 20756, 20762, 20769, 20794, 20791,
- 20796, 20795, [12041, 20799], [11918, 20800], 20818, 20812, 20820, 20834,
- 31480, {f: 2, c: 20841}, 20846, 20864, [12044, 20866], 22232, 20876, 20873,
- 20879, 20881, 20883, 20885, [12045, 20886], 20900, 20902, 20898,
- {f: 2, c: 20905}, [12046, 20907], 20915, {f: 2, c: 20913}, 20912, 20917,
- 20925, 20933, 20937, 20955, [12047, 20960], 34389, 20969, 20973, 20976,
- [12048, 20981], 20990, 20996, 21003, 21012, 21006, 21031, 21034, 21038,
- 21043, 21049, 21071, 21060, {f: 2, c: 21067}, 21086, 21076, 21098, 21108,
- 21097, 21107, 21119, 21117, 21133, 21140, 21138, 21105, 21128, 21137,
- 36776, 36775, {f: 2, c: 21164}, 21180, 21173, 21185, 21197, 21207, 21214,
- 21219, 21222, 39149, 21216, 21235, 21237, 21240, [12051, 21241], 21254,
- 21256, 30008, 21261, 21264, 21263, [12052, 21269], [12053, 21274], 21283,
- 21295, 21297, 21299, [12054, 21304], 21312, 21318, 21317, 19991, 21321,
- 21325, 20950, 21342, [12057, 21353], 21358, 22808, 21371, 21367,
- [12058, 21378], 21398, 21408, 21414, 21413, 21422, 21424, [12059, 21430],
- 21443, 31762, 38617, 21471, 26364, 29166, 21486, 21480, 21485, 21498,
- 21505, 21565, 21568, {f: 2, c: 21548}, 21564, 21550, 21558, 21545, 21533,
- 21582, 21647, 21621, 21646, 21599, 21617, 21623, 21616, 21650, 21627,
- 21632, 21622, 21636, 21648, 21638, 21703, 21666, 21688, 21669, 21676,
- 21700, 21704, 21672, 21675, 21698, 21668, 21694, 21692, 21720,
- {f: 2, c: 21733}, 21775, 21780, 21757, 21742, 21741, 21754, 21730, 21817,
- 21824, 21859, 21836, 21806, 21852, 21829, {f: 2, c: 21846}, 21816, 21811,
- 21853, 21913, 21888, 21679, 21898, 21919, 21883, 21886, 21912, 21918,
- 21934, 21884, 21891, 21929, 21895, 21928, 21978, 21957, 21983, 21956,
- 21980, 21988, 21972, 22036, 22007, 22038, 22014, 22013, 22043, 22009,
- 22094, 22096, 29151, 22068, 22070, 22066, 22072, 22123, 22116, 22063,
- 22124, 22122, 22150, 22144, 22154, 22176, 22164, 22159, 22181, 22190,
- 22198, 22196, 22210, 22204, 22209, 22211, 22208, 22216, 22222, 22225,
- 22227, [12062, 22231], 22254, 22265, 22272, 22271, 22276, 22281, 22280,
- 22283, 22285, 22291, 22296, 22294, 21959, 22300, 22310, {f: 2, c: 22327},
- 22350, 22331, 22336, 22351, 22377, 22464, 22408, 22369, 22399, 22409,
- 22419, 22432, 22451, 22436, 22442, 22448, 22467, 22470, 22484,
- {f: 2, c: 22482}, 22538, 22486, 22499, 22539, 22553, 22557, 22642, 22561,
- 22626, 22603, 22640, 27584, 22610, 22589, 22649, 22661, 22713, 22687,
- 22699, 22714, 22750, 22715, 22712, 22702, 22725, 22739, 22737, 22743,
- 22745, 22744, 22757, 22748, 22756, 22751, 22767, 22778, 22777,
- {f: 3, c: 22779}, [12065, 22786], [12066, 22794], 22800, 22811, 26790,
- 22821, {f: 2, c: 22828}, 22834, 22840, 22846, 31442, 22869, 22864, 22862,
- 22874, 22872, 22882, 22880, 22887, 22892, 22889, 22904, 22913, 22941,
- 20318, 20395, 22947, 22962, 22982, 23016, 23004, 22925, {f: 2, c: 23001},
- 23077, 23071, 23057, 23068, 23049, 23066, 23104, 23148, 23113,
- {f: 2, c: 23093}, 23138, 23146, 23194, 23228, 23230, 23243, 23234, 23229,
- 23267, 23255, 23270, 23273, 23254, {f: 2, c: 23290}, 23308, 23307, 23318,
- 23346, 23248, 23338, 23350, 23358, 23363, 23365, 23360, 23377, 23381,
- {f: 2, c: 23386}, 23397, 23401, 23408, 23411, 23413, 23416, 25992, 23418,
- [12071, 23424], 23427, 23462, 23480, 23491, 23495, 23497, 23508, 23504,
- 23524, 23526, 23522, 23518, 23525, 23531, 23536, 23542, 23539, 23557,
- {f: 2, c: 23559}, 23565, 23571, 23584, [11920, 12074, 23586], 23592,
- [12075, 23608], 23609, 23617, 23622, 23630, 23635, 23632, 23631, 23409,
- 23660, [12076, 23662], 20066, 23670, 23673, 23692, 23697, 23700, 22939,
- 23723, 23739, 23734, 23740, 23735, 23749, 23742, 23751, 23769, 23785,
- 23805, 23802, 23789, 23948, 23786, 23819, 23829, 23831, 23900, 23839,
- 23835, 23825, 23828, 23842, 23834, 23833, 23832, 23884, 23890, 23886,
- 23883, 23916, 23923, 23926, 23943, 23940, 23938, 23970, 23965, 23980,
- 23982, 23997, 23952, 23991, 23996, 24009, 24013, 24019, 24018, 24022,
- [12078, 24027], 24043, 24050, 24053, 24075, 24090, 24089, 24081, 24091,
- {f: 2, c: 24118}, 24132, 24131, 24128, 24142, 24151, 24148, 24159, 24162,
- 24164, 24135, {f: 2, c: 24181}, [11923, 12083, 24186], 40636,
- [12084, 24191], 24224, {f: 2, c: 24257}, 24264, 24272, 24271, 24278, 24291,
- 24285, {f: 2, c: 24282}, 24290, 24289, {f: 2, c: 24296}, 24300, 24305,
- 24307, 24304, [12085, 24308], 24312, [12086, 24318], 24323, 24329, 24413,
- 24412, [12087, 24331], 24337, 24342, 24361, 24365, 24376, 24385, 24392,
- 24396, 24398, 24367, [11924, 24401], {f: 2, c: 24406}, 24409,
- [12090, 24417], 24429, [12091, 24435], 24439, 24451, 24450, 24447, 24458,
- 24456, 24465, 24455, 24478, 24473, 24472, 24480, 24488, 24493, 24508,
- 24534, 24571, 24548, 24568, 24561, 24541, 24755, 24575, 24609, 24672,
- 24601, 24592, 24617, 24590, 24625, 24603, 24597, 24619, 24614, 24591,
- 24634, 24666, 24641, 24682, 24695, 24671, 24650, 24646, 24653, 24675,
- 24643, 24676, 24642, 24684, 24683, 24665, 24705, 24717, 24807, 24707,
- 24730, 24708, 24731, {f: 2, c: 24726}, 24722, 24743, 24715, 24801, 24760,
- 24800, 24787, 24756, 24560, 24765, 24774, 24757, 24792, 24909, 24853,
- 24838, {f: 2, c: 24822}, 24832, 24820, 24826, 24835, 24865, 24827, 24817,
- {f: 2, c: 24845}, 24903, 24894, 24872, 24871, 24906, 24895, 24892, 24876,
- 24884, 24893, 24898, 24900, 24947, 24951, {f: 3, c: 24920}, 24939, 24948,
- 24943, 24933, 24945, 24927, 24925, 24915, 24949, 24985, 24982, 24967,
- 25004, 24980, 24986, 24970, 24977, 25003, 25006, 25036, 25034, 25033,
- 25079, 25032, 25027, 25030, 25018, 25035, 32633, 25037, 25062, 25059,
- 25078, 25082, 25076, 25087, 25085, 25084, 25086, 25088, [12093, 25096],
- 25097, 25101, 25100, 25108, 25115, 25118, 25121, 25130, 25134, 25136,
- {f: 2, c: 25138}, 25153, 25166, 25182, 25187, 25179, 25184, 25192, 25212,
- 25218, 25225, 25214, {f: 2, c: 25234}, 25238, 25300, 25219, 25236, 25303,
- 25297, 25275, 25295, 25343, 25286, 25812, 25288, 25308, 25292, 25290,
- 25282, 25287, 25243, 25289, 25356, 25326, 25329, 25383, 25346, 25352,
- 25327, 25333, 25424, 25406, 25421, 25628, 25423, 25494, 25486, 25472,
- 25515, 25462, 25507, 25487, 25481, 25503, 25525, 25451, 25449, 25534,
- 25577, 25536, 25542, 25571, 25545, 25554, 25590, 25540, 25622, 25652,
- 25606, 25619, 25638, 25654, 25885, 25623, 25640, 25615, 25703, 25711,
- 25718, 25678, 25898, 25749, 25747, 25765, 25769, 25736, 25788, 25818,
- 25810, 25797, 25799, 25787, 25816, 25794, 25841, 25831, 33289,
- {f: 2, c: 25824}, 25260, 25827, 25839, 25900, 25846, 25844, 25842, 25850,
- 25856, 25853, 25880, 25884, 25861, 25892, 25891, 25899, [12097, 25908],
- [11929, 25909], 25911, 25910, 25912, 30027, 25928, 25942, 25941, 25933,
- 25944, 25950, 25949, 25970, 25976, {f: 2, c: 25986}, 35722, 26011, 26015,
- 26027, 26039, 26051, 26054, 26049, 26052, 26060, 26066, 26075, 26073,
- [12102, 26080], [11931, 26081], 26097, 26482, 26122, 26115, 26107, 26483,
- {f: 2, c: 26165}, 26164, 26140, 26191, 26180, 26185, 26177, 26206, 26205,
- 26212, {f: 2, c: 26215}, 26207, 26210, 26224, 26243, 26248, 26254, 26249,
- 26244, 26264, 26269, 26305, 26297, 26313, 26302, 26300, 26308, 26296,
- 26326, 26330, 26336, 26175, 26342, 26345, [12104, 26352], 26357, 26359,
- 26383, 26390, 26398, {f: 2, c: 26406}, 38712, 26414, 26431, 26422, 26433,
- 26424, 26423, 26438, 26462, 26464, 26457, {f: 2, c: 26467}, 26505, 26480,
- 26537, 26492, 26474, 26508, 26507, 26534, 26529, 26501, 26551, 26607,
- 26548, 26604, 26547, 26601, 26552, 26596, 26590, 26589, 26594, 26606,
- 26553, 26574, 26566, 26599, 27292, 26654, 26694, 26665, 26688, 26701,
- 26674, 26702, 26803, 26667, 26713, 26723, 26743, 26751, 26783, 26767,
- 26797, 26772, 26781, 26779, 26755, 27310, 26809, 26740, 26805, 26784,
- 26810, 26895, 26765, 26750, 26881, 26826, 26888, 26840, 26914, 26918,
- 26849, 26892, 26829, 26836, 26855, 26837, 26934, 26898, 26884, 26839,
- 26851, 26917, 26873, 26848, 26863, 26920, 26922, 26906, 26915, 26913,
- 26822, 27001, 26999, 26972, 27000, 26987, 26964, 27006, 26990, 26937,
- 26996, 26941, 26969, 26928, 26977, 26974, 26973, 27009, 26986, 27058,
- 27054, 27088, 27071, 27073, 27091, 27070, 27086, 23528, 27082, 27101,
- 27067, 27075, 27047, 27182, 27025, 27040, 27036, 27029, 27060, 27102,
- 27112, 27138, 27163, 27135, 27402, 27129, 27122, 27111, 27141, 27057,
- 27166, 27117, 27156, 27115, 27146, 27154, 27329, 27171, 27155, 27204,
- 27148, 27250, 27190, 27256, 27207, 27234, 27225, 27238, 27208, 27192,
- 27170, 27280, 27277, 27296, 27268, {f: 2, c: 27298}, 27287, 34327, 27323,
- 27331, 27330, 27320, 27315, 27308, 27358, 27345, 27359, 27306, 27354,
- 27370, 27387, 27397, 34326, 27386, 27410, 27414, 39729, 27423, 27448,
- 27447, 30428, 27449, 39150, 27463, 27459, 27465, 27472, 27481, 27476,
- 27483, 27487, 27489, 27512, [12109, 27513], {f: 2, c: 27519}, 27524, 27523,
- 27533, 27544, 27541, 27550, 27556, {f: 2, c: 27562}, 27567, 27570, 27569,
- [12110, 27571], 27575, 27580, 27590, [12111, 27595], 27603, 27615, 27628,
- 27627, 27635, 27631, 40638, 27656, 27667, [12115, 27668], 27675, 27684,
- 27683, 27742, 27733, 27746, 27754, 27778, 27789, 27802, 27777, 27803,
- 27774, 27752, 27763, 27794, 27792, 27844, 27889, 27859, 27837, 27863,
- 27845, 27869, 27822, 27825, 27838, 27834, 27867, 27887, 27865, 27882,
- 27935, 34893, 27958, 27947, 27965, 27960, 27929, 27957, 27955, 27922,
- 27916, 28003, 28051, 28004, 27994, 28025, 27993, 28046, 28053, 28644,
- 28037, 28153, 28181, 28170, 28085, 28103, 28134, 28088, 28102, 28140,
- 28126, 28108, 28136, 28114, 28101, 28154, 28121, 28132, 28117, 28138,
- 28142, 28205, 28270, 28206, 28185, 28274, 28255, 28222, 28195, 28267,
- 28203, 28278, 28237, 28191, 28227, 28218, 28238, 28196, 28415, 28189,
- 28216, 28290, 28330, 28312, 28361, 28343, 28371, 28349, 28335, 28356,
- 28338, {f: 2, c: 28372}, 28303, 28325, 28354, 28319, 28481, 28433, 28748,
- 28396, 28408, 28414, 28479, 28402, 28465, 28399, 28466, 28364, 28478,
- 28435, 28407, 28550, 28538, 28536, 28545, 28544, 28527, 28507, 28659,
- 28525, 28546, 28540, 28504, 28558, 28561, 28610, 28518, 28595, 28579,
- 28577, 28580, 28601, 28614, 28586, 28639, 28629, 28652, 28628, 28632,
- 28657, 28654, 28635, 28681, 28683, 28666, 28689, 28673, 28687, 28670,
- 28699, 28698, 28532, 28701, 28696, 28703, 28720, 28734, 28722, 28753,
- 28771, 28825, 28818, 28847, 28913, 28844, 28856, 28851, 28846, 28895,
- 28875, 28893, 28889, 28937, 28925, 28956, 28953, 29029, 29013, 29064,
- 29030, 29026, 29004, 29014, 29036, 29071, 29179, 29060, 29077, 29096,
- 29100, 29143, 29113, 29118, 29138, 29129, 29140, 29134, 29152, 29164,
- 29159, 29173, 29180, 29177, 29183, 29197, 29200, 29211, 29224, 29229,
- 29228, 29232, 29234, [12120, 29243], 29244, [12121, 29247], 29248, 29254,
- 29259, 29272, 29300, 29310, 29314, 29313, 29319, 29330, 29334, 29346,
- 29351, 29369, 29362, 29379, 29382, 29380, 29390, 29394, 29410,
- {f: 2, c: 29408}, 29433, 29431, 20495, 29463, 29450, 29468, 29462, 29469,
- 29492, 29487, 29481, 29477, 29502, {f: 2, c: 29518}, 40664, 29527, 29546,
- 29544, 29552, 29560, 29557, 29563, 29562, 29640, 29619, 29646, 29627,
- 29632, 29669, 29678, 29662, 29858, 29701, 29807, 29733, 29688, 29746,
- 29754, 29781, 29759, 29791, 29785, 29761, 29788, 29801, 29808, 29795,
- 29802, 29814, 29822, 29835, 29854, 29863, 29898, 29903, 29908, 29681,
- 29920, 29923, 29927, 29929, 29934, 29938, {f: 2, c: 29936}, 29944, 29943,
- 29956, 29955, 29957, 29964, 29966, 29965, 29973, 29971, 29982, 29990,
- 29996, 30012, 30020, 30029, 30026, 30025, 30043, 30022, 30042, 30057,
- 30052, 30055, 30059, 30061, 30072, 30070, {f: 2, c: 30086}, 30068, 30090,
- 30089, 30082, 30100, 30106, 30109, 30117, 30115, 30146, 30131, 30147,
- 30133, 30141, 30136, 30140, 30129, 30157, 30154, 30162, 30169, 30179,
- 30174, {f: 2, c: 30206}, 30204, 30209, 30192, 30202, {f: 2, c: 30194},
- 30219, 30221, 30217, 30239, 30247, {f: 3, c: 30240}, 30244, 30260, 30256,
- 30267, {f: 2, c: 30279}, 30278, 30300, 30296, {f: 2, c: 30305},
- {f: 3, c: 30312}, 30311, 30316, 30320, 30322, [12136, 30326], 30328, 30332,
- 30336, 30339, 30344, 30347, 30350, 30358, 30355, {f: 2, c: 30361}, 30384,
- 30388, {f: 3, c: 30392}, 30402, 30413, 30422, 30418, 30430, 30433, 30437,
- 30439, 30442, 34351, 30459, 30472, 30471, 30468, 30505, 30500, 30494,
- {f: 2, c: 30501}, 30491, {f: 2, c: 30519}, 30535, 30554, 30568, 30571,
- 30555, 30565, 30591, 30590, 30585, 30606, 30603, 30609, 30624, 30622,
- 30640, 30646, 30649, 30655, {f: 2, c: 30652}, 30651, 30663, 30669, 30679,
- 30682, 30684, 30691, 30702, 30716, 30732, 30738, 31014, 30752, 31018,
- 30789, 30862, 30836, 30854, 30844, 30874, 30860, 30883, 30901, 30890,
- 30895, 30929, 30918, 30923, 30932, 30910, 30908, 30917, 30922, 30956,
- 30951, 30938, 30973, 30964, 30983, 30994, 30993, 31001, 31020, 31019,
- 31040, 31072, 31063, 31071, 31066, 31061, 31059, 31098, 31103, 31114,
- 31133, 31143, 40779, 31146, 31150, 31155, {f: 2, c: 31161}, 31177, 31189,
- 31207, 31212, 31201, 31203, 31240, 31245, {f: 2, c: 31256}, 31264, 31263,
- 31104, 31281, 31291, 31294, 31287, 31299, 31319, 31305, {f: 2, c: 31329},
- 31337, 40861, 31344, 31353, 31357, 31368, 31383, 31381, 31384, 31382,
- 31401, 31432, 31408, 31414, 31429, 31428, 31423, 36995, 31431, 31434,
- 31437, 31439, 31445, 31443, {f: 2, c: 31449}, 31453, {f: 2, c: 31457},
- 31462, 31469, 31472, 31490, 31503, 31498, 31494, 31539, {f: 2, c: 31512},
- 31518, 31541, 31528, 31542, 31568, 31610, 31492, 31565, 31499, 31564,
- 31557, 31605, 31589, 31604, 31591, {f: 2, c: 31600}, 31596, 31598, 31645,
- 31640, 31647, 31629, 31644, 31642, 31627, 31634, 31631, 31581, 31641,
- 31691, 31681, 31692, 31695, 31668, 31686, 31709, 31721, 31761, 31764,
- 31718, 31717, 31840, 31744, 31751, 31763, 31731, 31735, 31767, 31757,
- 31734, 31779, 31783, 31786, 31775, 31799, 31787, 31805, 31820, 31811,
- 31828, 31823, 31808, 31824, 31832, 31839, 31844, 31830, 31845, 31852,
- 31861, 31875, 31888, 31908, 31917, 31906, 31915, 31905, 31912, 31923,
- 31922, 31921, 31918, 31929, 31933, 31936, 31941, 31938, 31960, 31954,
- 31964, 31970, 39739, 31983, 31986, 31988, 31990, 31994, 32006, 32002,
- 32028, 32021, 32010, 32069, 32075, 32046, 32050, 32063, 32053, 32070,
- 32115, 32086, 32078, 32114, 32104, 32110, 32079, 32099, 32147, 32137,
- 32091, 32143, 32125, 32155, 32186, 32174, 32163, 32181, 32199, 32189,
- 32171, 32317, 32162, 32175, 32220, 32184, 32159, 32176, 32216, 32221,
- 32228, 32222, 32251, 32242, 32225, 32261, 32266, 32291, 32289, 32274,
- 32305, 32287, 32265, 32267, 32290, 32326, 32358, 32315, 32309, 32313,
- 32323, 32311, 32306, 32314, 32359, 32349, 32342, 32350, {f: 2, c: 32345},
- 32377, 32362, 32361, 32380, 32379, 32387, 32213, 32381, 36782, 32383,
- {f: 2, c: 32392}, 32396, 32402, 32400, {f: 2, c: 32403}, 32406, 32398,
- {f: 2, c: 32411}, 32568, 32570, 32581, {f: 3, c: 32588}, 32592,
- [12153, 32593], 32597, 32596, 32600, {f: 2, c: 32607}, {f: 2, c: 32616},
- 32615, 32632, 32642, 32646, 32643, 32648, 32647, 32652, 32660, 32670,
- 32669, 32666, 32675, 32687, 32690, 32697, 32686, 32694, 32696, 35697,
- {f: 2, c: 32709}, 32714, 32725, 32724, 32737, 32742, 32745, 32755, 32761,
- 39132, 32774, 32772, 32779, [12158, 32786], {f: 2, c: 32792}, 32796, 32801,
- 32808, 32831, 32827, 32842, 32838, 32850, 32856, 32858, 32863, 32866,
- 32872, 32883, 32882, 32880, 32886, 32889, 32893, [12160, 32895], 32900,
- 32902, 32901, 32923, 32915, 32922, 32941, 20880, 32940, 32987, 32997,
- 32985, 32989, 32964, 32986, 32982, 33033, 33007, 33009, 33051, 33065,
- 33059, 33071, 33099, 38539, 33094, 33086, 33107, 33105, 33020, 33137,
- 33134, {f: 2, c: 33125}, 33140, 33155, 33160, 33162, 33152, 33154, 33184,
- 33173, 33188, 33187, 33119, 33171, 33193, 33200, 33205, 33214, 33208,
- 33213, 33216, 33218, 33210, 33225, 33229, 33233, 33241, 33240, 33224,
- 33242, {f: 2, c: 33247}, 33255, {f: 2, c: 33274}, 33278, {f: 2, c: 33281},
- 33285, 33287, 33290, 33293, 33296, 33302, 33321, 33323, 33336, 33331,
- 33344, 33369, 33368, 33373, 33370, 33375, 33380, 33378, 33384,
- {f: 2, c: 33386}, 33326, 33393, 33399, [12171, 33400], 33406, 33421, 33426,
- 33451, 33439, 33467, 33452, 33505, 33507, 33503, 33490, 33524, 33523,
- 33530, 33683, 33539, 33531, 33529, 33502, 33542, 33500, 33545, 33497,
- 33589, 33588, 33558, 33586, 33585, 33600, 33593, 33616, 33605, 33583,
- 33579, {f: 2, c: 33559}, 33669, 33690, 33706, 33695, 33698, 33686, 33571,
- 33678, 33671, 33674, 33660, 33717, 33651, 33653, 33696, 33673, 33704,
- 33780, 33811, 33771, 33742, 33789, 33795, 33752, 33803, 33729, 33783,
- 33799, 33760, 33778, 33805, 33826, 33824, 33725, 33848, 34054, 33787,
- 33901, 33834, 33852, 34138, 33924, 33911, 33899, 33965, 33902, 33922,
- 33897, 33862, 33836, 33903, 33913, 33845, 33994, 33890, 33977, 33983,
- 33951, 34009, 33997, 33979, 34010, 34000, 33985, 33990, 34006, 33953,
- 34081, 34047, 34036, {f: 2, c: 34071}, 34092, 34079, 34069, 34068, 34044,
- 34112, 34147, 34136, 34120, 34113, 34306, 34123, 34133, 34176, 34212,
- 34184, 34193, 34186, 34216, 34157, 34196, 34203, 34282, 34183, 34204,
- 34167, 34174, 34192, 34249, 34234, 34255, 34233, 34256, 34261, 34269,
- 34277, 34268, 34297, 34314, 34323, 34315, 34302, 34298, 34310, 34338,
- 34330, 34352, 34367, [12172, 34381], 20053, 34388, 34399, 34407, 34417,
- 34451, 34467, {f: 2, c: 34473}, {f: 2, c: 34443}, 34486, 34479, 34500,
- 34502, 34480, 34505, 34851, 34475, 34516, 34526, 34537, 34540, 34527,
- 34523, 34543, 34578, 34566, 34568, 34560, 34563, 34555, 34577, 34569,
- 34573, 34553, 34570, 34612, 34623, 34615, 34619, 34597, 34601, 34586,
- 34656, 34655, 34680, 34636, 34638, 34676, 34647, 34664, 34670, 34649,
- 34643, 34659, 34666, 34821, 34722, 34719, 34690, 34735, 34763, 34749,
- 34752, 34768, 38614, 34731, 34756, 34739, 34759, 34758, 34747, 34799,
- 34802, 34784, 34831, 34829, 34814, {f: 2, c: 34806}, 34830, 34770, 34833,
- 34838, 34837, 34850, 34849, 34865, 34870, 34873, 34855, 34875, 34884,
- 34882, 34898, 34905, 34910, 34914, 34923, 34945, 34942, 34974, 34933,
- 34941, 34997, 34930, 34946, 34967, 34962, 34990, 34969, 34978, 34957,
- 34980, 34992, 35007, 34993, {f: 2, c: 35011}, 35028, {f: 2, c: 35032},
- 35037, 35065, 35074, 35068, 35060, 35048, 35058, 35076, 35084, 35082,
- 35091, 35139, 35102, 35109, {f: 2, c: 35114}, 35137, 35140, 35131, 35126,
- 35128, 35148, 35101, 35168, 35166, 35174, 35172, 35181, 35178, 35183,
- 35188, 35191, [12177, 35198], 35203, 35208, 35210, 35219, 35224, 35233,
- 35241, 35238, 35244, 35247, 35250, 35258, 35261, {f: 2, c: 35263}, 35290,
- {f: 2, c: 35292}, 35303, 35316, 35320, 35331, 35350, 35344, 35340, 35355,
- 35357, 35365, 35382, 35393, 35419, 35410, 35398, 35400, 35452, 35437,
- 35436, 35426, 35461, 35458, 35460, 35496, 35489, 35473, {f: 2, c: 35493},
- 35482, 35491, 35524, 35533, 35522, 35546, 35563, 35571, 35559, 35556,
- 35569, 35604, 35552, 35554, 35575, 35550, 35547, 35596, 35591, 35610,
- 35553, 35606, 35600, 35607, 35616, 35635, 38827, 35622, 35627, 35646,
- 35624, 35649, 35660, 35663, 35662, 35657, 35670, 35675, 35674, 35691,
- 35679, 35692, 35695, 35700, 35709, 35712, 35724, 35726, {f: 2, c: 35730},
- 35734, {f: 2, c: 35737}, 35898, 35905, 35903, 35912, 35916, 35918, 35920,
- [12183, 35925], 35938, 35948, [12184, 35960], 35962, 35970, 35977, 35973,
- 35978, {f: 2, c: 35981}, 35988, 35964, 35992, 25117, 36013, 36010, 36029,
- {f: 2, c: 36018}, 36014, 36022, 36040, 36033, 36068, 36067, 36058, 36093,
- {f: 2, c: 36090}, {f: 2, c: 36100}, 36106, 36103, 36111, 36109, 36112,
- 40782, 36115, 36045, 36116, 36118, 36199, 36205, 36209, 36211, 36225,
- 36249, 36290, 36286, 36282, 36303, 36314, 36310, 36300, 36315, 36299,
- {f: 2, c: 36330}, 36319, 36323, 36348, {f: 2, c: 36360}, 36351,
- {f: 2, c: 36381}, 36368, 36383, 36418, 36405, 36400, 36404, 36426, 36423,
- 36425, 36428, 36432, 36424, 36441, 36452, 36448, 36394, 36451, 36437,
- 36470, 36466, 36476, 36481, 36487, 36485, 36484, 36491, 36490, 36499,
- 36497, 36500, 36505, 36522, 36513, 36524, 36528, 36550, 36529, 36542,
- 36549, 36552, 36555, 36571, 36579, 36604, 36603, 36587, 36606, 36618,
- 36613, 36629, 36626, 36633, 36627, 36636, 36639, 36635, 36620, 36646,
- 36659, 36667, 36665, 36677, 36674, 36670, 36684, 36681, 36678, 36686,
- 36695, 36700, {f: 3, c: 36706}, 36764, 36767, 36771, 36781, 36783, 36791,
- 36826, 36837, 36834, 36842, 36847, 36999, 36852, 36869, {f: 2, c: 36857},
- 36881, 36885, 36897, 36877, 36894, 36886, 36875, 36903, 36918, 36917,
- 36921, 36856, {f: 4, c: 36943}, 36878, 36937, 36926, 36950, 36952, 36958,
- 36968, 36975, 36982, 38568, 36978, 36994, 36989, 36993, 36992, 37002,
- 37001, 37007, 37032, 37039, 37041, 37045, 37090, 37092, 25160, 37083,
- 37122, 37138, 37145, 37170, 37168, 37194, 37206, 37208, 37219, 37221,
- 37225, 37235, 37234, 37259, 37257, 37250, 37282, 37291, 37295, 37290,
- 37301, 37300, 37306, {f: 2, c: 37312}, 37321, 37323, 37328, 37334, 37343,
- 37345, 37339, 37372, {f: 2, c: 37365}, 37406, 37375, 37396, 37420, 37397,
- 37393, 37470, 37463, 37445, 37449, 37476, 37448, 37525, 37439, 37451,
- 37456, 37532, 37526, 37523, 37531, 37466, 37583, 37561, 37559, 37609,
- 37647, 37626, 37700, 37678, 37657, 37666, 37658, 37667, 37690, 37685,
- 37691, 37724, 37728, 37756, 37742, 37718, 37808, {f: 2, c: 37804}, 37780,
- 37817, {f: 2, c: 37846}, 37864, 37861, 37848, 37827, 37853, 37840, 37832,
- 37860, 37914, 37908, 37907, 37891, 37895, 37904, 37942, 37931, 37941,
- 37921, 37946, 37953, 37970, 37956, 37979, 37984, 37986, 37982, 37994,
- 37417, 38000, 38005, 38007, 38013, 37978, 38012, 38014, 38017, 38015,
- 38274, 38279, 38282, 38292, 38294, {f: 2, c: 38296}, 38304, 38312, 38311,
- 38317, 38332, 38331, 38329, 38334, 38346, 28662, 38339, 38349, 38348,
- 38357, 38356, 38358, 38364, 38369, 38373, 38370, 38433, 38440,
- {f: 2, c: 38446}, 38466, 38476, 38479, 38475, 38519, 38492, 38494, 38493,
- 38495, 38502, 38514, 38508, 38541, 38552, 38549, 38551, 38570, 38567,
- {f: 2, c: 38577}, 38576, 38580, [12202, 38582], 38584, [12203, 38585],
- 38606, 38603, 38601, 38605, 35149, 38620, 38669, 38613, 38649, 38660,
- 38662, 38664, 38675, 38670, 38673, 38671, 38678, 38681, 38692, 38698,
- 38704, 38713, {f: 2, c: 38717}, 38724, 38726, 38728, 38722, 38729, 38748,
- 38752, 38756, 38758, 38760, 21202, 38763, 38769, 38777, 38789, 38780,
- 38785, 38778, 38790, 38795, {f: 2, c: 38799}, 38812, 38824, 38822, 38819,
- {f: 2, c: 38835}, 38851, 38854, 38856, [12209, 38859], 38876,
- [12210, 38893], 40783, 38898, 31455, 38902, 38901, 38927, 38924, 38968,
- 38948, 38945, 38967, 38973, 38982, 38991, 38987, 39019, {f: 3, c: 39023},
- 39028, 39027, 39082, 39087, 39089, 39094, 39108, 39107, 39110, 39145,
- 39147, 39171, 39177, 39186, 39188, 39192, 39201, {f: 2, c: 39197}, 39204,
- 39200, 39212, 39214, {f: 2, c: 39229}, 39234, 39241, 39237, 39248, 39243,
- {f: 2, c: 39249}, 39244, 39253, {f: 2, c: 39319}, 39333, {f: 2, c: 39341},
- 39356, 39391, 39387, 39389, 39384, 39377, {f: 2, c: 39405},
- {f: 2, c: 39409}, 39419, 39416, 39425, 39439, 39429, 39394, 39449, 39467,
- 39479, 39493, 39490, 39488, 39491, 39486, 39509, 39501, 39515, 39511,
- 39519, 39522, 39525, 39524, 39529, 39531, 39530, 39597, 39600, 39612,
- 39616, 39631, 39633, {f: 2, c: 39635}, 39646, [12221, 39647],
- {f: 2, c: 39650}, 39654, 39663, 39659, 39662, 39668, 39665, 39671, 39675,
- 39686, 39704, 39706, 39711, {f: 2, c: 39714}, [12222, 39717],
- {f: 4, c: 39719}, 39726, [12223, 39727], [12224, 39730], 39748, 39747,
- 39759, {f: 2, c: 39757}, 39761, 39768, 39796, 39827, 39811, 39825,
- {f: 2, c: 39830}, {f: 2, c: 39839}, 39848, 39860, 39872, 39882, 39865,
- 39878, 39887, {f: 2, c: 39889}, 39907, 39906, 39908, 39892, 39905, 39994,
- 39922, 39921, 39920, 39957, 39956, 39945, 39955, 39948, 39942, 39944,
- 39954, 39946, 39940, 39982, 39963, 39973, 39972, 39969, 39984, 40007,
- 39986, 40006, 39998, 40026, 40032, 40039, 40054, 40056, 40167, 40172,
- 40176, 40201, 40200, 40171, 40195, 40198, 40234, 40230, 40367, 40227,
- 40223, 40260, 40213, 40210, 40257, 40255, 40254, 40262, 40264,
- {f: 2, c: 40285}, 40292, 40273, 40272, 40281, 40306, 40329, 40327, 40363,
- 40303, 40314, 40346, 40356, 40361, 40370, 40388, 40385, 40379, 40376,
- 40378, 40390, 40399, 40386, 40409, 40403, 40440, 40422, 40429, 40431,
- 40445, {f: 2, c: 40474}, 40478, [12228, 40565], 40569, 40573, 40577, 40584,
- {f: 2, c: 40587}, 40594, 40597, 40593, 40605, [12230, 40613], 40617, 40632,
- 40618, 40621, 38753, 40652, {f: 3, c: 40654}, 40660, 40668, 40670, 40669,
- 40672, 40677, 40680, 40687, 40692, {f: 2, c: 40694}, [12235, 40697],
- {f: 2, c: 40699}, [12236, 40701], {f: 2, c: 40711}, 30391, 40725, 40737,
- 40748, 40766, [12241, 40778], [12242, 40786], 40788, 40803,
- {f: 3, c: 40799}, {f: 2, c: 40806}, 40812, 40810, 40823, 40818, 40822,
- 40853, [12244, 40860], [12245, 40864], 22575, 27079, 36953, 29796, 0,
- {f: 76, c: 9472}, {f: 20, c: 9312}, {f: 10, c: 8544}, 13129, 13076, 0,
- 13133, 0, 13095, 0, 13110, 13137, 0, 13069, 13094, 0, 13099, 13130, 0,
- {f: 3, c: 13212}, {f: 2, c: 13198}, 13252, 13217, 12317, 12319, 8470,
- 13261, 0, {f: 5, c: 12964}, {f: 2, c: 12849}, 12857, 13182, 13181, 13180,
- 8750, 8721, {s: 3}, 8735, 8895, 0, 0, 21854, {s: 7}, 167133, 0, 0, 28976,
- 0, 40407, {s: 4}, 64054, 0, 0, 22169, 15694, {s: 4}, 20448, 0, 0, 36544, 0,
- 194797, {s: 4}, 153716, 32363, 33606, 167670, {s: 3}, 40572, 0, 0, 26171,
- 0, 40628, {s: 4}, 26629, {s: 5}, 23650, 0, 194780, 0, 32353, 0, 0, 64070,
- {s: 5}, 34083, 37292, {s: 7}, 34796, {s: 8}, 25620, 0, 0, 39506, {s: 4},
- 64074, 0, 194692, {s: 4}, 31774, {s: 6}, 64016, 25681, 0, 0, 63980, 22625,
- 39002, 0, 194679, {s: 3}, 31153, 0, 28678, {s: 9}, 22218, {s: 3}, 21085, 0,
- 28497, 37297, {s: 10}, 64106, {s: 6}, 38960, 0, 40629, {s: 9}, 33802,
- 63939, {f: 2, c: 63890}, 63897, 0, 34847, 194575, 0, 194771, 194584,
- {s: 7}, 137754, 23643, {s: 4}, 25890, 0, 0, 26618, 0, 26766, 0, 148432,
- 194848, {s: 21}, 34110, {s: 15}, 30562, {s: 12}, 65075, 0,
- {f: 2, c: 65073}, {s: 4}, 65072, {f: 2, c: 65077}, {f: 2, c: 65081}, 0, 0,
- {f: 2, c: 65079}, {f: 2, c: 65087}, {f: 2, c: 65085}, {f: 4, c: 65089},
- {f: 2, c: 65083}, {s: 41}, {f: 3, c: 12436}, 0, 0, 22099, {s: 41}, 65508,
- 65287, 65282, 0, 9665, 9655, 8681, 8679, 8678, 8680, 9634, 9831, 9825,
- 9828, 9826, 13216, 13218, {f: 2, c: 13220}, 13207, 8467, 13208, 13235,
- 13234, 13233, 13232, {f: 3, c: 13189}, 13259, 13200, 13268, 13206, 13090,
- 13078, 13080, 13077, 13059, 13091, 13143, 13122, 13113, 13115, 13056,
- 13105, 13127, 13086, 13098, 0, 13183, 8481, 9742, 12342, 12320, {s: 3},
- {f: 9, c: 9352}, {f: 20, c: 9332}, 12881, {f: 10, c: 8560},
- {f: 10, c: 12882}, {f: 26, c: 9372}, 12867, 12861, 12863, 12852, 12856,
- 12851, 12860, 12866, 12862, 12854, 12853, 12859, 12864, 12858, 12976,
- 12973, 12969, 12975, 12948, 12970, 12952, 12971, 12946, 12945, 12947,
- 12972, 12974, 12950, {s: 8}, {f: 3, c: 9131}, 0, {f: 3, c: 9127}, 0, 13260,
- 13061, 0, 0, 13215, 13219, 13222, 0, 0, 12958, {f: 2, c: 13192}, 13256,
- 8749, 0, 12848, {f: 6, c: 12842}, 12855, 12865, 10145, {s: 3}, 9673, 9824,
- 9829, 9827, 9830, {f: 4, c: 9728}, 9758, {f: 2, c: 9756}, 9759, 12953,
- 9450, {f: 2, c: 8554}, {s: 3}, {f: 8, c: 9601}, 9615, 9614, 9613, 9612,
- 9611, 9610, 9609, {f: 2, c: 9620}, {f: 2, c: 9581}, 9584, 9583, 9552, 9566,
- 9578, 9569, {f: 2, c: 9698}, 9701, 9700, 0, 0, {f: 3, c: 9585}, {s: 20},
- 20956, 29081, {f: 9, c: 10102}, {s: 3}, {f: 2, c: 8570}, {s: 3}, 8575,
- 8458, 8457, 0, 0, 12292, 8646, {f: 2, c: 8644}, 0, {f: 4, c: 12535}, 0, 0,
- 12957, {s: 3}, 13179, {s: 3}, 13107, 13134, {s: 30}, 32394, 35100, 37704,
- 37512, 34012, 20425, 28859, 26161, 26824, 37625, 26363, 24389,
- [12033, 20008], 20193, 20220, 20224, 20227, 20281, 20310, 20370, 20362,
- 20378, 20372, 20429, 20544, 20514, 20479, 20510, 20550, 20592, 20546,
- 20628, 20724, 20696, 20810, 20836, 20893, 20926, 20972, 21013, 21148,
- 21158, 21184, 21211, 21248, 0, 21284, 21362, 21395, 21426, 21469, 64014,
- 21660, 21642, 21673, 21759, 21894, 22361, 22373, 22444, 22472, 22471,
- 64015, 0, 22686, 22706, 22795, 22867, 22875, 22877, 22883, 22948, 22970,
- 23382, 23488, 29999, 23512, 0, 23582, 23718, 23738, 23797, 23847, 23891, 0,
- 23874, 23917, {f: 2, c: 23992}, 24016, 24353, 24372, 24423, 24503, 24542,
- 24669, 24709, 24714, 24798, 24789, 24864, 24818, 24849, 24887, 24880,
- 24984, 25107, 25254, 25589, 25696, 25757, 25806, 25934, 26112, 26133,
- 26121, 26158, 0, 26148, 26213, 26199, 26201, 64018, 26227, 26265, 26272,
- 26290, 26303, 26362, 26382, 0, 26470, 26555, 26706, 26560, 0, 26692, 26831,
- 64019, 26984, 64020, 27032, 27106, 27184, 27243, 27206, 27251, 27262,
- 27362, 27364, 27606, 27711, 27740, 27782, 27759, 27866, 27908, 28039,
- 28015, 28054, 28076, 28111, 28152, 28146, 28156, 28217, 28252, 28199,
- 28220, 28351, 28552, 28597, 28661, 28677, 28679, 28712, 28805, 28843,
- 28943, 28932, 29020, {f: 2, c: 28998}, 0, 29121, 29182, 29361, 29374,
- 29476, 64022, 29559, 29629, 29641, 29654, 29667, 29650, 29703, 29685,
- 29734, 29738, 29737, 29742, 0, 29833, 29855, 29953, 30063, 30338, 30364,
- 30366, 30363, 30374, 64023, 30534, 21167, 30753, 30798, 30820, 30842,
- 31024, {f: 3, c: 64024}, 31124, 64027, 31131, 31441, 31463, 64028, 31467,
- 31646, 64029, 32072, 0, 32183, 32160, 32214, 32338, 32583, 32673, 64030,
- 33537, 33634, 33663, 33735, 33782, 33864, 33972, 34131, 34137, 34155,
- 64031, 34224, {f: 2, c: 64032}, 34823, 35061, 35346, 35383, 35449, 35495,
- 35518, 35551, 64034, 35574, 35667, 35711, 36080, 36084, 36114, 36214,
- 64035, 36559, 0, 64037, 36967, 37086, 64038, 37141, 37159, 37338, 37335,
- 37342, {f: 2, c: 37357}, {f: 2, c: 37348}, 37382, 37392, 37386, 37434,
- 37440, 37436, 37454, 37465, 37457, 37433, 37479, 37543, {f: 2, c: 37495},
- 37607, 37591, 37593, 37584, 64039, 37589, 37600, 37587, 37669, 37665,
- 37627, 64040, 37662, 37631, 37661, 37634, 37744, 37719, 37796, 37830,
- 37854, 37880, 37937, 37957, 37960, 38290, 0, 64041, 38557, 38575, 38707,
- 38715, 38723, 38733, 38735, [12205, 38737], 0, 38999, 39013,
- {f: 2, c: 64042}, 39207, 64044, 39326, 39502, 39641, 39644, 39797, 39794,
- 39823, 39857, 39867, 39936, 40304, 40299, 64045, 40473, 40657, 0, 92,
- {s: 634}, 8364, 8486, 0, 0, 64256, {f: 2, c: 64259}, 257, 299, 363, 275,
- 333, 256, 298, 362, 274, 332, {f: 4, c: 8539}, {f: 2, c: 8531}, 8304,
- {f: 6, c: 8308}, {f: 10, c: 8320}, 461, 282, 0, 7868, 463, 0, 296, 465, 0,
- 467, 366, 360, 462, 283, 0, 7869, 464, 0, 297, 466, 0, 468, 367, 361, 593,
- 8049, 8048, 509, 0, 596, 0, 0, 601, 0, 0, 602, 0, 0, 603, 8051, 8050, 0,
- 331, 629, 652, 0, 0, 658, 643, 720, {s: 682}, {f: 10, c: 12832}, {s: 108},
- {f: 4, c: 12892}, {f: 15, c: 12977}, {s: 50}, {f: 26, c: 9424},
- {f: 26, c: 9398}, {s: 48}, {f: 47, c: 13008}, 0, {f: 10, c: 12928}, 12944,
- {f: 6, c: 12938}, 0, 12959, {s: 6}, {f: 2, c: 12960}, 12955, 12954, 12963,
- 12962, 12951, 0, 12956, 12949, {s: 6}, 9676, {s: 11}, 10111,
- {f: 10, c: 9451}, {s: 510}, 8414, {s: 815}, 13274, {s: 3}, 8448, 13250, 0,
- 0, 8453, 0, 13169, 0, 0, 13197, 13211, {s: 3}, {f: 2, c: 13271}, {s: 3},
- {f: 2, c: 13057}, 13060, 13062, 0, 13064, 0, 13063, 13066, 0, 13065, 0,
- 13067, 0, 13068, {f: 6, c: 13070}, 0, 13079, 0, 13081, 0, {f: 4, c: 13082},
- {f: 3, c: 13087}, 13092, 0, 13093, 0, 0, {f: 2, c: 13096}, 0, 13101, 0, 0,
- {f: 3, c: 13102}, 13106, 0, 0, {f: 2, c: 13108}, 13116, {s: 3}, 13111, 0,
- 13112, 13114, 13117, 13121, {f: 3, c: 13118}, {f: 4, c: 13123}, 13128,
- {f: 2, c: 13131}, {f: 2, c: 13135}, 0, 0, 13138, 13140, 0, 0, 13139,
- {f: 2, c: 13141}, {s: 132}, 8501, 976, 8714, 8463, 0, 981, 987, 977, 0,
- {f: 2, c: 9832}, 9836, {s: 5}, 12347, 0, {f: 3, c: 12339}, 8252, 8265,
- {s: 5}, 8723, 0, 8771, {f: 2, c: 8818}, {s: 6}, {f: 2, c: 12312},
- {f: 2, c: 65375}, {s: 10}, 9115, {f: 2, c: 9117}, 9120, {s: 4}, 9121,
- {f: 2, c: 9123}, 9126, {s: 12}, [9116, 9119, 9122, 9125, 9130], {s: 8},
- 9986, 0, 0, 12349, 0, 12447, 0, 0, 8709, 8864, 8854, 8856, 8853, 8855,
- {s: 4}, 9664, 9654, {s: 4}, 8656, 8596, {f: 2, c: 8600}, {f: 2, c: 8598},
- 8652, 8651, {s: 10}, 12336, 8967, {s: 8}, 10048, 10047, {s: 7}, 9643, 0,
- 9642, 0, 10010, {s: 12}, 9702, {s: 4}, 10070, {s: 379}, {f: 2, c: 65093},
- {s: 679}, 64103, 64098, 32227, [12232, 40643], 28331, 64082, 64061, 64069,
- 64062, 27114, 28212, 64096, 64071, 64056, 64066, 64078, 34395, 64105,
- 64052, 64099, 25581, 25802, 30799, 64084, 63856, 64077, 64097, 64072,
- 64076, {f: 2, c: 64091}, 64081, 64067, 64090, 28041, 29376, 0, 194885,
- 64086, 64080, 64049, 64059, 24034, 64063, 64101, 21373, 64055, 64095,
- 24501, 64064, 0, 64083, 0, 64085, 64104, 64068, 64089, 26202, 64053, 64075,
- 64100, 64065, 64048, 0, 64057, 64051, 27493, 64058, 27599, 64050, 25150,
- 64079, 63773, 63964, 63798, 28122, 63952, 26310, 27511, 64087, 37706, 0,
- 37636, {s: 120}, 133390, {s: 120}, 35999, 11991, [11965, 158033], {s: 5},
- 37555, 38321, 0, 0, 194812, {s: 13}, 194965, {s: 8}, 194794, 0, 26478,
- 11974, 0, 194594, {s: 13}, 13314, 0, 0, 26083, {s: 4}, 134071, {s: 10},
- 171339, 0, 194611, 24378, {s: 8}, 11945, 0, 20465, {s: 7}, 63753, {s: 7},
- 11964, 0, 0, 194732, 26435, {s: 3}, 133732, 35329, 25142, 0, 0, 21555,
- 23067, {s: 3}, 25221, 0, 0, 194819, {s: 6}, 21567, {s: 9}, 27506, {s: 4},
- 29986, 19256, 0, 0, 24063, {s: 6}, 194827, 29626, 134047, {s: 3}, 194600,
- 0, 194849, {s: 5}, 194623, {s: 16}, 194675, {f: 2, c: 11916}, 23577,
- {s: 3}, 131083, 23426, 194642, {s: 5}, 11997, [11999, 39136],
- [11998, 169599], 14221, 0, [11927, 14586], 0, 194887, 0, [11909, 20155],
- 131490, {s: 7}, 13599, 0, 194738, 0, 0, [11971, 35200], {s: 4}, 31237,
- {s: 4}, 35498, 0, 32085, 0, 28568, {s: 7}, 25591, 30246, {s: 4},
- [11978, 163767], {s: 5}, 146686, {s: 5}, 13351, 0, 0, 33067, 0, 0, 194842,
- {s: 5}, 11950, {s: 5}, 194714, {s: 3}, 194831, {s: 19}, 22305, 135741,
- 194586, 0, 64003, {s: 7}, 21534, 15240, 20839, {s: 4}, 63839, {s: 9},
- 20023, {s: 13}, [11946, 150804], 24421, 23020, 194658, 0, 24217, {s: 46},
- 13416, {s: 8}, 21200, {s: 9}, 26625, 0, 195024, 195039, {s: 5}, 153215, 0,
- 0, 11959, {s: 4}, 36534, 63775, {s: 3}, 63875, {s: 5}, 31867, 63906, 0,
- 63898, 0, [11961, 32770], 157360, {s: 4}, [11911, 132648], 0, 0, 131210,
- 194604, [11915, 13630], {s: 4}, 21589, 0, 22841, 0, 0, 23414, 194669,
- 23572, 14306, 23782, 0, 20040, 0, 0, 194742, {s: 4}, 158105, 25371, 0, 0,
- 26211, 0, 194779, 0, 0, 27126, 27014, {s: 3}, 27596, 0, 28183, 0, 0, 27818,
- {s: 3}, [11942, 20012], 0, 0, 29935, 30069, 30188, 30286, 16305, 30570,
- 30633, {s: 6}, 31571, 0, 0, 16996, {s: 3}, 194924, 0, 0, 32328, {s: 5},
- 11955, {s: 4}, 33089, 17491, 0, [11966, 33401], [11967, 64094],
- [11968, 64093], 0, 20857, 33626, {s: 3}, 17701, 0, 34292, 131248, {s: 4},
- 34429, 0, 13358, 35014, {s: 6}, 18406, {s: 8}, 36808, {s: 19}, 166279, 0,
- 0, 167447, 0, 0, 38969, {s: 6}, 39432, {s: 4}, 39903, {s: 10}, 148206,
- {s: 5}, 21385, 0, 64017, 194785, 0, 146622, 132625, 0, {f: 2, c: 19972},
- 19999, 20011, {f: 2, c: 20015}, {f: 2, c: 20032}, 20036, [11907, 20058],
- 20095, 20109, 20118, 20153, 20176, 20192, 20221, 20223, 20235, 20245,
- 20320, 20283, 20297, 20308, 20346, {f: 2, c: 20349}, 20375, 20414, 20431,
- 20477, {f: 2, c: 20480}, 20496, 20507, 20519, 20526, 20567, 20582, 20586,
- 20539, 20623, 20630, 20636, 20684, 20710, 20713, 20719, 20744, 20747,
- 20752, 20763, 20766, 20831, 20897, 20924, 0, 20974, 20980, 20993,
- [11913, 20994], 21011, 21065, 21089, 21094, 21139, 21192, 21232,
- {f: 2, c: 21258}, 21310, 21324, 21323, 21345, 21356, 21419, 21466, 21478,
- 21493, 21543, 21581, 21606, 21611, 21620, 21645, 21654, 21665, 21677,
- 21689, 21695, 21702, 21709, 21774, 21803, 21813, 21834, 21856, 0, 21896,
- 21902, 22024, {f: 2, c: 22030}, 22071, 22079, 22089, 22091, 22095, 22118,
- 22121, 22127, {f: 2, c: 22129}, 22165, 22170, {f: 2, c: 22188}, 22193,
- 22217, 22237, 22244, 22282, 22293, 22307, 22319, {f: 2, c: 22323}, 22348,
- 22384, 22412, 22428, 22456, 22502, 22509, {f: 2, c: 22517}, 22527, 22537,
- 22560, 22578, 22652, 22656, 22697, 22734, 22736, 22740, 22746, 22761,
- 22796, 22820, 22831, 22881, 22893, 22986, 22994, 23005, {f: 2, c: 23011},
- 23044, 23052, 23075, 23111, 23125, 23139, 23149, 23166, 23198, 23207,
- 23212, 23219, 23264, 23296, 23321, 23333, 23341, 23361, 23420,
- {f: 2, c: 23422}, 23434, [11919, 23587], 23595, 23600, 23651, 23657, 23676,
- 23755, 23762, 23796, 23844, 23846, 23875, 23878, 23882, 23954, 23956,
- 23961, 23968, 24024, 24032, 24056, 24064, 24082, {f: 2, c: 24084}, 24088,
- 24110, 24152, {f: 2, c: 24171}, 24232, 24234, {f: 2, c: 24254}, 0, 24274,
- 24327, 24334, {f: 2, c: 24348}, 24354, 24360, 24374, 24379, 24384,
- [12089, 24400], 24408, 24420, 24457, 24476, 24487, 24484, 24495, 24504,
- [11926, 24516], 24521, 24545, 24553, 24557, 24572, 24599, 24602, 24627,
- 24673, 24703, 24734, 24740, 24752, 24779, 24795, 24824, {f: 3, c: 24850},
- 24860, 24956, 24973, 24991, 25000, 25026, 25055, 25109, 25129, 25155,
- 25158, [11928, 25164], 25169, 25174, 25284, 25340, 25354, 25357, 25368,
- 25401, {f: 2, c: 25410}, 25445, 25460, 25469, 25476, 25479, 25488, 25502,
- 25553, 25564, 25609, 25616, 25634, 25684, 25691, 25709, 25723,
- {f: 2, c: 25790}, 25829, 25847, 25851, 25860, 25878, 25881, 25927, 25959,
- 25985, 25989, 26050, 26096, 26098, 26156, 26188, {f: 2, c: 26203}, 26209,
- 26219, 0, 26276, 26312, 26348, 26373, 26387, 26419, 26440, 26444, 26486,
- 26491, 26544, 26546, 26617, 26583, 26585, 26608, 26668, {f: 2, c: 26672},
- 26715, 26738, 26741, 26746, 26756, 26789, 26802, 26832, 26838, 26856,
- 26861, {f: 2, c: 26864}, 26876, 26897, 26899, 26933, 26939, 26967, 26979,
- 26994, {f: 2, c: 27007}, 27046, 27053, 27063, {f: 2, c: 27094}, 27137,
- 27151, 27157, 27176, 27188, 27198, 27205, {f: 2, c: 27216}, 27222, 27227,
- 27267, 27273, 27281, {f: 3, c: 27293}, 27356, 27367, 27372, 27422, 27428,
- 27445, 27462, 27478, 27488, 27522, 27582, 27617, 27633, 27664, 27699,
- [11937, 27701], 11938, 27737, 27766, 27771, 27781, 27797, 27804, 27856,
- 27860, 27862, 27872, {f: 2, c: 27883}, 27886, 27914, 27918, 27921, 27950,
- 27991, 27998, 28005, 28034, 28095, 28100, 28106, 28118, 28137, 28194,
- 28241, 28359, 28362, 28366, 28413, 28442, 28458, 28463, 28467, 28506,
- 28510, 28514, 28541, 28555, 28557, 28562, 28564, 28570, {f: 2, c: 28583},
- 28598, 28634, 28638, 0, 28729, 28732, 0, 28756, {f: 2, c: 28765}, 28772,
- [11939, 28780], 28798, 28801, 28821, 28855, {f: 2, c: 28883}, 28888, 28892,
- 28935, 28960, 28977, 29002, 29010, 29024, 29049, 29074, 0, 29131, 29139,
- 29142, 29184, 29213, 29227, 29240, 29249, 29267, {f: 2, c: 29269}, 29276,
- 29325, [11944, 29357], 29364, 29383, 29435, {f: 2, c: 29444}, 29480, 29489,
- 29507, 29548, 29564, 29571, {f: 2, c: 29573}, 29589, {f: 3, c: 29598},
- 29606, 29611, 29621, 29623, 29628, 29647, 29657, 29673, 29684, 29693,
- 29700, 29706, {f: 2, c: 29722}, 29732, 29736, 29740, {f: 3, c: 29743},
- 29753, 29764, 29767, 29771, 29773, 29777, 29783, 29798, 29803, 29809,
- 29824, {f: 3, c: 29829}, 29840, 29848, 29852, 29856, 29859, 29864, 29867,
- 29877, 29887, 29896, 29914, 29918, 30030, 30073, 30081, 30096,
- [12135, 30098], 30099, 30132, 30180, 30201, 30208, 30218, {f: 2, c: 30229},
- 30233, 30238, 30253, 30261, 30275, 30283, 30309, 30317, 30319, 30321,
- 30324, {f: 2, c: 30372}, 30405, 30412, 30444, 30460, 30516, 30518, 30556,
- {f: 2, c: 30559}, 30578, 30589, 30613, 30634, 30694, 30704, 30708, 30726,
- 30754, {f: 2, c: 30765}, 30768, 30773, 30824, 30878, 30920, 30924, 30926,
- 30948, {f: 2, c: 30944}, 30962, 30967, 30971, 31025, 0, [11949, 31035],
- 31037, 31045, {f: 2, c: 31067}, 31115, 31126, 31128, [12145, 31160], 31163,
- 31178, 31194, 31235, 31241, 31249, 31262, 31277, 31289, 31301, 31308,
- 31325, 0, 31341, 31352, 31392, 31395, 31411, {f: 2, c: 31419}, 31430,
- 31495, 31508, 31527, 31537, 31559, 31566, 31584, 31593, 31597, 31602,
- 31633, 31663, 31703, 31705, 31755, 31759, 31776, 31782, 31793, 31798,
- 31825, 31833, 31847, 31854, 31856, 31932, 31935, {f: 2, c: 31944}, 31959,
- 31961, 31965, 31979, {f: 3, c: 32007}, 32019, 32029, 32035, 32065, 32083,
- 32089, 32093, 32122, 32134, {f: 2, c: 32139}, 32204, 32235, 32241, 32249,
- 32264, 32273, 32277, 32288, 32327, 32354, 32366, 32371, 32397, 32401,
- 32408, 32580, 32591, [11947, 11954, 32594], [11953, 32595], 32609, 32657,
- 32703, 32718, 32735, 32741, 32748, {f: 2, c: 32750}, 32762, 32782, 32785,
- 32788, 32804, 32806, 32826, 32828, 32864, 32881, 32885, 32926, 32934,
- 32939, {f: 2, c: 32983}, 33046, 33048, 33082, 33098, 33100, 33153, 33156,
- 33204, 33231, 33273, 33283, 33313, 33330, 33332, 33350, 33355, 33359,
- 33422, 33454, 33463, 33470, 33478, 33534, 33603, 33617, 33621, 33670,
- 33677, 33682, 33688, 33705, {f: 2, c: 33727}, 33770, 33807, 33809, 33866,
- 33910, 33960, 33967, 33984, 33986, 34032, 34045, 34060, 34100, 34142,
- 34191, 34231, 34254, 34221, 34322, 34345, 34386, 34403, 34412, 34415,
- 34426, 34445, 34449, 34456, {f: 2, c: 34471}, 34554, 34557, 34571, 34579,
- 34585, 34590, 34600, 34622, 34673, 34696, 34713, {f: 2, c: 34732}, 34741,
- 34774, 34795, 34797, 34817, 0, 34822, 34827, 34836, 34844, 34902, 34911,
- [11970, 34916], 34968, 34986, {f: 2, c: 35005}, 35018, 35026, 35035,
- {f: 2, c: 35056}, 35078, {f: 3, c: 35096}, 35111, 35120, 35134, 35195,
- 35284, 35286, 35301, 35313, 35335, 35343, 35349, 35362, 35406, 35455,
- 35572, 35615, 35639, {f: 2, c: 35651}, 35668, 35740, 35742, 35911, 35924,
- 35955, 36004, 36057, 36065, 36088, 36094, 36123, 36201, 36204, 36228,
- 36237, 36245, 36262, 36294, 36302, 36324, 36332, 36384, 36427, 36460,
- 36464, 36474, 36498, 36526, 36531, 36561, 36564, 36601, 36631, 36662,
- 36774, [12193, 36789], [11981, 36790], 0, 36832, 36836, 36854, 36866,
- 36908, 36932, 37000, 37013, 37017, 37019, 37026, 37044, 37079, 37085,
- 37108, 37143, 37148, 37169, 37178, 37181, 37192, 37211, 37217, 37220,
- 37262, 37278, 37288, {f: 2, c: 37293}, 37298, 37308, 37360, 37367, 37371,
- 37383, 37416, 37427, 37432, 37443, 37447, 37455, 37472, 37570,
- {f: 2, c: 37579}, 37599, 37645, 37653, 37663, 37671, 37703, 37714, 0,
- 37738, 37741, 37787, 37818, 37801, 37825, 37834, 37858, 37882, 37885,
- 37903, 37940, 37951, 37973, 37995, 38002, [11986, 38264], 38310, 38313, 0,
- 38324, 38333, 38362, [11983, 11990, 38429], 38465, 38488, 38532, 38564,
- 38569, 38610, 195060, 38622, 38633, 38641, 38658, 38665, 38746, 38755,
- 38766, 38771, 38810, 38818, {f: 2, c: 38837}, 38873, 38878, 38900, 38922,
- 38926, 38942, 38947, 38955, 38974, {f: 2, c: 38994}, 39001, 39020, 39096,
- 39098, 39103, 39112, 39141, {f: 2, c: 39218}, 39232, 39245, 39260, 39263,
- 39345, {f: 2, c: 39353}, 39369, 39426, 39446, 39460, 39463,
- {f: 2, c: 39469}, 39478, 39480, 39498, 39510, {f: 2, c: 39605}, 39673,
- 39683, 39712, {f: 2, c: 39731}, 39795, 39801, 39847, 39873, 39879, 39895,
- 39911, 39915, 39927, 39930, 39933, 39947, 39975, 39978, 39990, 40001,
- 40019, 40035, 40048, 40055, 40194, 40258, 40263, 40291, 40297, 40316,
- 40318, 40333, 40369, 40387, 40391, 40406, 40415, 40427, 40436, 40469,
- 40477, 40612, 40616, 40620, 40679, 40686, 40720, 40722, 40727, 40729,
- 40751, 40759, 40761, 40769, 40773, 40791, 40808, 40817, 40821, 40848,
- 40852, 40866, 0, 13317, 194564, 22048, 24267, 11925, 0, 144954, 0, 28665,
- 28390, 29107, [11940, 64073], {s: 4}, [11980, 64102], 0, 23986, 0, 20435,
- 20697, 20720, 20931, 22134, 27220, 27905, 28112, 28226, 28377, 29668,
- 29729, 30060, 30801, 34805, 144382, 29608, 15091, 13531, 17420, 16010, 0,
- 0, 19432, 0, 16090, 15138, 0, 17786, 16531, 0, 18021, 16643, 17043, 18094,
- 13448, 140809, {f: 3, c: 63584}, 63610, 63615, {s: 23}, {f: 2, c: 8836},
- {f: 2, c: 8842}, 8713, 0, {f: 2, c: 8965}, {s: 9}, {f: 2, c: 8741},
- {s: 14}, 8802, 0, 8773, 8776, {f: 2, c: 8822}, {s: 4}, 8487, {s: 209},
- {f: 2, c: 8922}, 8533, 8984, {f: 2, c: 7742}, {f: 2, c: 504}, 470, 472,
- 474, 476, 260, 728, 317, 346, 350, 356, 377, 379, 261, 731, 318, 347, 711,
- 351, 357, 378, 733, 380, 340, 258, 313, 262, 268, 280, 270, 323, 327, 336,
- 344, 368, 354, 341, 259, 314, 263, 269, 281, 271, 273, 324, 328, 337, 345,
- 369, 355, 729, 264, 284, 292, 308, 348, 364, 265, 285, 293, 309, 349, 365,
- 625, 651, 638, 620, 622, 633, 648, 598, 627, 637, 642, 656, 635, 621, 607,
- 626, 669, 654, 609, 624, 641, 295, 661, 660, 614, 664, 450, 595, 599, 644,
- 608, 403, 616, 649, 600, 604, 606, 592, 623, 650, 612, 594, 653, 613, 674,
- 673, 597, 657, 634, 615, 865, 712, 716, 721, 8255, 783, {f: 5, c: 741}, 0,
- 0, 805, 812, 825, 796, {f: 2, c: 799}, 829, 809, 815, 734, 804, 816, 828,
- 820, {f: 2, c: 797}, {f: 2, c: 792}, 810, {f: 2, c: 826}, 794, {s: 3},
- {f: 2, c: 610}, 618, 628, 630, 632, 640, 655, 665, 668, 671, 688, 690, 695,
- 704, {f: 2, c: 736}, {s: 6}, 8862, {s: 287}, 12348, 12543, 0,
- {f: 2, c: 12310}, 9838, 9835, {f: 2, c: 10548}, 10687, 0, 12448, 0,
- {f: 2, c: 10746}, {s: 13}, 962, {f: 10, c: 9461}, {f: 2, c: 9750}, 9649,
- {f: 10, c: 12784}, 0, {f: 6, c: 12794}, {f: 15, c: 9150}, 0, 0, 10003, 0,
- 9251, 9166, {f: 4, c: 9680}, {f: 2, c: 8263}, 0, 8273, 8258,
- {f: 16, c: 12688}, {s: 13}, {f: 2, c: 9136}, {f: 12, c: 9842},
- {f: 2, c: 12441}, 8413, {s: 450}, 20296, 20319, 20330, 20332, 20494, 20504,
- 20545, 20722, 20688, 20742, 20739, 20789, 20821, 20823, 13493, 20938,
- 20962, 21079, 21196, 21206, 21243, 21276, 21347, 21405, 21522, 21631,
- 21640, 21840, 21889, 21933, 21966, 22075, 22174, 22185, 22195, 22391,
- 22396, 135963, 22479, 22500, 22628, 22665, 136302, 22738, 22752, 34369,
- 22923, 22930, 22979, 23059, 23143, 23159, 23172, 23236, 137405, 23421,
- 23443, 23570, 64060, 136884, 23674, 23695, 23711, 23715, 23722, 23760,
- 138804, 23821, 23879, 23937, 23972, 23975, 24011, 24158, 24313, 24320,
- 24322, 24355, 24381, 24404, 24445, 24589, 24596, 24600, 24629, 24647,
- 24733, 24788, 24797, 24875, 25020, 25017, 25122, 25178, 25199, 25302,
- 25468, 25573, 25721, 25796, 25808, 25897, 26013, 26170, 26146, 26155,
- 26160, 26163, 26184, 143812, {f: 2, c: 26231}, 26253, 26299, 26331, 26344,
- 26439, 26497, 26515, 26520, 26523, 26620, 26653, 26787, 26890, 26953,
- 144836, 26946, 26980, 27045, 27087, 15286, 15299, 27113, 27125, 145215,
- 27195, 145251, 27284, 27301, 15375, 27419, 27436, 27495, 27561, 27565,
- 27607, 27647, 27653, 27764, 27800, 27899, 27846, 27953, 27961, 27967,
- 27992, 28052, 28074, 28123, 28125, 28228, 28254, 28337, 28353, 28432,
- 28505, 28513, 28542, 28556, 28576, 28604, 28615, 28618, 28656, 28750,
- 28789, 28836, 28900, 28971, 28958, 28974, 29009, 29032, 29061, 29063,
- 29114, 29124, 29205, 15935, 29339, 149489, 29479, 29520, 29542, 29602,
- 29739, 29766, 29794, 29805, 29862, 29865, 29897, 29951, 29975, 16242,
- 30158, 30210, 30216, 30308, 30337, 30365, 30378, 30390, 30414, 30420,
- 30438, 30449, 30474, 30489, {f: 2, c: 30541}, 30586, 30592, 30612, 30688,
- 152718, 30787, 30830, 30896, 152846, 30893, 30976, 31004, 31022, 31028,
- 31046, 31097, 31176, 153457, 31188, 31198, 31211, 31213, 31365, 154052,
- 31438, 31485, 31506, 31533, 31547, 31599, 31745, 31795, 155041, 31853,
- 31865, 31887, 31892, 31904, 31957, 32049, 32092, 32131, 32166, 32194,
- 32296, 32663, 32731, 32821, 32823, 32970, 32992, 33011, 33120,
- {f: 2, c: 33127}, 33133, 33211, 33226, 33239, 17499, 33376, 33396, 158463,
- 33441, {f: 2, c: 33443}, 33449, 33471, 33493, 33533, 33536, 33570, 33581,
- 33594, 33607, 33661, 33703, 33743, 33745, 33761, 33793, 33798, 33887,
- 33904, 33907, 33925, 33950, 33978, 159296, 34098, 34078, 34095, 34148,
- 34170, 34188, 34210, 34251, 34285, 34303, {f: 2, c: 34308}, 34320, 159988,
- 34328, 34360, 34391, 34402, 17821, 34421, 34488, 34556, 34695, 17898,
- 34826, 34832, 35022, 161412, 35122, 35129, 35136, 35220, 35318, 35399,
- 35421, 35425, 35445, 35536, 35654, 35673, 35689, 35741, 35913, 35944,
- 36271, 36305, 36311, 36387, 36413, 36475, 164471, 18500, 36602, 36638,
- 36653, 36692, 164813, 36840, 36846, 36872, 36909, 37015, 37043, 37054,
- {f: 2, c: 37060}, 37063, 37103, 37140, 37142, {f: 2, c: 37154}, 37167,
- 37172, 37251, 37361, 37705, {f: 2, c: 37732}, 37795, 37855, 37892, 37939,
- 37962, 37987, 38001, 38286, 38303, 38316, 38326, 38347, 38352, 38355,
- 18864, 38366, 38565, 38639, 38734, 38805, 38830, 38842, 38849, 38857,
- 38875, 38998, 39143, 39256, 39427, 39617, 39619, 39630, 39638, 39682,
- 39688, 19479, 39725, 39774, 39782, 39812, 39818, 39838, 39886, 39909,
- 39928, 39971, {f: 2, c: 40015}, 40037, {f: 2, c: 40221}, 40259, 40274,
- 40330, 40342, 40384, 40364, 40380, 172432, 40423, 40455, 40606, 40623,
- 40855, 131209, 19970, 19983, 19986, 20009, 20014, 20039, 131234, 20049,
- 13318, 131236, 20073, 20125, 13356, 20156, 20163, 20168, 20203, 20186,
- 20209, 20213, 20246, 20324, 20279, 20286, 20312, 131603, {f: 2, c: 20343},
- 20354, 20357, 20454, 20402, 20421, 20427, 20434, 13418, 20466, 20499,
- 20508, 20558, 20563, 20579, 20643, 20616, {f: 2, c: 20626}, 20629, 20650,
- 131883, 20657, {f: 2, c: 20666}, 20676, 20679, 20723, 131969, 20686,
- 131953, 20692, 20705, 13458, 132089, 20759, 132170, 20832, 132361, 20851,
- 20867, 20875, 13500, 20888, 20899, 20909, 13511, 132566, 20979, 21010,
- 21014, 132943, 21077, 21084, 21100, 21111, 21124, 21122, 133127, 21144,
- 133178, 21156, {f: 2, c: 21178}, 21194, 21201, 133305, 21239, 21301, 21314,
- 133500, 133533, 21351, 21370, 21412, 21428, 133843, 21431, 21440, 133917,
- {f: 2, c: 13661}, 21461, 13667, 21492, 21540, 21544, 13678, 21571, 21602,
- 21612, 21653, 21664, 21670, 21678, 21687, 21690, 21699, 134469, 21740,
- 21743, 21745, 21747, {f: 2, c: 21760}, 21769, 21820, 21825, 13734, 21831,
- 13736, 21860, 134625, 21885, 21890, 21905, 13765, 21970, 134805, 134765,
- 21951, 21961, 21964, 21969, 21981, 13786, 21986, 134756, 21993, 22056,
- 135007, 22023, 22032, 22064, 13812, 22077, 22080, 22087, 22110, 22112,
- 22125, 13829, 22152, 22156, 22173, 22184, 22194, 22213, 22221, 22239,
- 22248, {f: 2, c: 22262}, 135681, 135765, 22313, 135803, {f: 2, c: 22341},
- 22349, 135796, 22376, 22383, {f: 3, c: 22387}, 22395, 135908, 135895,
- 22426, {f: 2, c: 22429}, 22440, 22487, 135933, 22476, 135990, 136004,
- 22494, 22512, 13898, 22520, 22523, 22525, 22532, 22558, 22567, 22585,
- 136132, 22601, 22604, 22631, {f: 2, c: 22666}, 22669, {f: 2, c: 22671},
- 22676, 22685, 22698, 22705, 136301, 22723, 22733, 22754, {f: 2, c: 22771},
- {f: 2, c: 22789}, 22797, 22804, 136663, 13969, 22845, 13977, 22854, 13974,
- 158761, 22879, 136775, {f: 2, c: 22901}, 22908, 22943, 22958, 22972, 22984,
- 22989, 23006, 23015, 23022, 136966, 137026, 14031, 23053, 23063, 23079,
- 23085, 23141, 23162, 23179, 23196, {f: 2, c: 23199}, 23202, 23217, 23221,
- 23226, 23231, 23258, 23260, 23269, 23280, 23278, 23285, 23304, 23319,
- 23348, 23372, 23378, 23400, 23407, 23425, 23428, 137667, 23446, 23468,
- {f: 2, c: 14177}, 23502, 23510, 14188, 14187, 23537, 23549, 14197, 23555,
- 23593, 138326, 23647, {f: 2, c: 23655}, 23664, 138541, 138565, 138616,
- 138594, 23688, 23690, 14273, 138657, 138652, 23712, 23714, 23719, 138642,
- 23725, 23733, 138679, 23753, 138720, 138803, 23814, 23824, 23851, 23837,
- 23840, 23857, 23865, 14312, 23905, 23914, 14324, 23920, 139038, 14333,
- 23944, 14336, 23959, 23984, 23988, 139126, 24017, 24023, 139258, 24036,
- 24041, 14383, 14390, 14400, 24095, 24126, 24137, 14428, 24150, 14433,
- {f: 2, c: 24173}, 139643, 24229, 24236, 24249, 24262, 24281, 140062, 24317,
- 24328, 140205, 24350, 24391, 24419, 24434, 24446, 24463, 24482, 24519,
- 24523, {f: 3, c: 24530}, 24546, {f: 2, c: 24558}, 24563, 14615, 24610,
- 24612, 14618, 24652, 24725, 24744, 141043, 24753, 24766, 24776, 24793,
- 24814, 24821, 24848, 24857, 24862, 24890, 14703, 24897, 24902, 24928,
- 141403, {f: 2, c: 24978}, 24983, 24997, 25005, 141483, 25045, 25053, 25077,
- 141711, 25123, 25170, 25185, 25188, 25211, 25197, 25203, 25241, 25301,
- 142008, 25341, 25347, 25360, {f: 2, c: 142159}, 25394, 25397,
- {f: 2, c: 25403}, 25409, 25412, 25422, 142150, 25433, 142365, 142246,
- 25452, 25497, 142372, 25492, 25533, {f: 2, c: 25556}, 25568,
- {f: 2, c: 25579}, 25586, 25630, 25637, 25641, 25647, 25690, 25693, 25715,
- 25725, 25735, 25745, 25759, {f: 2, c: 25803}, 25813, 25815, 142817, 25828,
- 25855, 14958, 25871, 25876, 14963, 25886, 25906, 25924, 25940, 25963,
- 25978, 25988, 25994, 26034, 26037, 26040, 26047, 26057, 26068, 15062,
- 26105, 26108, 26116, 26120, 26145, 26154, 26181, 26193, 26190, 15082,
- 143811, 143861, 143798, 26218, {f: 2, c: 26220}, 26235, 26240, 26256,
- 26258, 15118, 26285, 26289, 26293, 15130, 15132, 15063, 26369, 26386,
- 144242, 26393, 144339, 144338, 26445, 26452, 26461, 144336, 144356, 144341,
- 26484, 144346, 26514, 144351, 33635, 26640, 26563, 26568, 26578, 26587,
- 26615, 144458, 144465, 144459, 26648, 26655, 26669, 144485, 26675, 26683,
- 26686, 26693, 26697, 26700, 26709, 26711, 15223, 26731, 26734, 26748,
- 26754, 26768, 26774, 15213, {f: 3, c: 26776}, 26780, {f: 2, c: 26794},
- 26804, 26811, 26875, 144612, 144730, 26819, 26821, 26828, 26841,
- {f: 2, c: 26852}, 26860, 26871, 26883, 26887, 15239, 144788, 15245, 26950,
- 26985, 26988, 27002, 27026, 15268, 27030, 27056, 27066, 27068, 27072,
- 27089, 144953, 144967, 144952, 27107, {f: 2, c: 27118}, 27123, 15309,
- 27124, 27134, 27153, 27162, 27165, 145180, {f: 2, c: 27186}, 27199, 27209,
- 27258, 27214, 27218, 27236, 145164, 27275, 15344, 27297, 145252, 27307,
- 27325, 27334, 27348, 27344, 27357, 145407, 145383, {f: 3, c: 27377}, 27389,
- 145444, 27403, {f: 3, c: 27407}, 145469, 27415, 15398, 27439, 27466, 27480,
- 27500, 27509, [11934, 27514], 27521, 27547, 27566, 146072, 27581,
- {f: 3, c: 27591}, 27610, {f: 2, c: 27622}, 27630, 27650, 27658, 27662,
- 27702, 146559, 27725, 27739, 27757, 27780, 27785, 15555, 27796, 27799,
- 27821, 27842, 15570, 27868, 27881, 27885, 146688, 27904, 27940,
- {f: 2, c: 27942}, 27751, 27951, 27964, 27995, 28000, 28016,
- {f: 2, c: 28032}, 28042, 28045, 28049, 28056, 146752, 146938, 146937,
- 146899, 28075, 28078, 28084, 28098, 27956, 28104, 28110, 28127, 28150,
- 28214, 28190, 15633, 28210, {f: 2, c: 28232}, {f: 2, c: 28235}, 28239,
- {f: 2, c: 28243}, 28247, 28259, 15646, 28307, 28327, 28340, 28355, 28469,
- 28395, 28409, 28411, 28426, 28428, 28440, 28453, 28470, 28476, 147326,
- 28498, 28503, 28512, 28520, 28560, 28566, 28606, 28575, 28581, 28591,
- 15716, {f: 2, c: 28616}, 28649, 147606, 28668, 28672, 28682, 28707, 147715,
- 28730, 28739, 28743, 28747, 15770, 28773, 28777, 28782, 28790, 28806,
- 28823, 147910, 28831, 28849, 147966, 28908, 28874, 28881, 28931, 28934,
- 28936, 28940, 15808, 28975, 29008, 29011, 29022, 15828, 29078, 29056,
- 29083, 29088, 29090, {f: 2, c: 29102}, 148412, 29145, 29148, 29191, 15877,
- 29236, 29241, 29250, 29271, 29283, 149033, {f: 2, c: 29294}, 29304, 29311,
- 29326, 149157, 29358, 29360, 29377, 15968, 29388, 15974, 15976, 29427,
- 29434, 29447, 29458, {f: 2, c: 29464}, 16003, 29497, 29484, 29491, 29501,
- 29522, 16020, 29547, 149654, {f: 2, c: 29550}, 29553, 29569, 29578, 29588,
- 29592, 29596, 29605, 29625, 29631, 29637, 29643, 29665, 29671, 29689,
- 29715, 29690, 29697, 29779, 29760, 29763, 29778, 29789, 29825, 29832,
- 150093, 29842, 29847, 29849, 29857, 29861, 29866, 29881, 29883, 29882,
- 29910, 29912, 29931, 150358, 29946, 150383, 29984, 29988, 29994, 16215,
- 150550, {f: 2, c: 30013}, 30016, 30024, 30032, 30034, 30066, 30065, 30074,
- {f: 2, c: 30077}, 30092, 16245, 30114, 16247, 30128, 30135,
- {f: 2, c: 30143}, 30150, 30159, 30163, 30173, {f: 2, c: 30175}, 30183,
- 30190, 30193, 30211, 30232, 30215, 30223, 16302, 151054, 30227,
- {f: 2, c: 30235}, 151095, 30245, 30248, 30268, 30259, 151146, 16329, 30273,
- 151179, 30281, 30293, 16343, 30318, 30357, 30369, 30368, {f: 2, c: 30375},
- 30383, 151626, 30409, 151637, 30440, 151842, 30487, 30490, 30509, 30517,
- 151977, 16441, 152037, 152013, 30552, 152094, 30588, 152140, 16472, 30618,
- 30623, 30626, 30628, {f: 2, c: 30686}, 30692, 30698, 30700, 30715, 152622,
- 30725, 30729, 30733, 30745, 30764, 30791, 30826, 152793, 30858, 30868,
- 30884, 30877, 30879, 30907, 30933, 30950, {f: 2, c: 30969}, 30974, 152999,
- 30992, 31003, 31013, 31050, 31064, 16645, 31079, 31090, 31125, 31137,
- 31145, 31156, 31170, 31175, {f: 2, c: 31180}, 31190, 16712, 153513, 153524,
- 16719, 31242, 31253, 31259, 16739, 31288, 31303, 31318, 31321, 31324,
- 31327, 31335, 31338, 31349, 31362, 31370, 31376, 31404, 154068, 16820,
- 31417, 31422, 16831, 31436, 31464, 31476, 154340, 154339, 154353, 31549,
- 31530, {f: 2, c: 31534}, 16870, 16883, 31615, 31553, 16878, 31573, 31609,
- 31588, 31590, 31603, 154546, 16903, 31632, 31643, 16910, 31669, 31676,
- 31685, 31690, 154699, 154724, 31700, 31702, 31706, 31722, 31728, 31747,
- 31758, 31813, 31818, 31831, 31838, 31841, 31849, 31855, 155182, 155222,
- 155237, 31910, 155234, {f: 2, c: 31926}, 155352, 31940, 155330, 31949,
- 155368, 155427, 31974, 155484, 31989, 32003, 17094, 32018, 32030, 155616,
- 155604, {f: 2, c: 32061}, 32064, 32071, 155660, 155643, 17110, 32090,
- 32106, 32112, 17117, 32127, 155671, 32136, 32151, 155744, 32157, 32167,
- 32170, 32182, 32192, 32215, 32217, 32230, 17154, 155885, 64088, 32272,
- 32279, 32285, 32295, 32300, 32325, 32373, 32382, {f: 2, c: 32390}, 17195,
- 32410, 17219, 32572, 32571, 32574, 32579, 13505, 156272, 156294,
- {f: 2, c: 32611}, 32621, {f: 2, c: 32637}, 32656, 20859, 146702, 32662,
- 32668, 32685, 156674, 32707, 32719, 32739, 32754, 32778, 32776, 32790,
- 32812, 32816, 32835, 32870, 32891, 32921, 32924, 32932, 32935, 32952,
- 157310, 32965, 32981, 32998, 33037, 33013, 33019, 17390, 33077, 33054,
- 17392, 33060, 33063, 33068, 157469, 33085, 17416, 33129, 17431, 17436,
- 33157, 17442, 33176, 33202, 33217, 33219, 33238, 33243, 157917, 33252,
- 157930, 33260, 33277, 33279, 158063, 33284, 158173, 33305, 33314, 158238,
- 33340, 33353, 33349, 158296, 17526, 17530, 33367, 158348, 33372, 33379,
- 158391, 17553, 33405, 33407, 33411, 33418, 33427, {f: 2, c: 33447}, 33458,
- 33460, 33466, 33468, 33506, 33512, 33527, {f: 2, c: 33543}, 33548, 33620,
- 33563, 33565, 33584, 33596, 33604, 33623, 17598, 17620, 17587,
- {f: 2, c: 33684}, 33691, 33693, 33737, 33744, 33748, 33757, 33765, 33785,
- 33813, 158835, 33815, 33849, 33871, {f: 2, c: 33873}, {f: 2, c: 33881},
- 33884, 158941, 33893, 33912, 33916, 33921, 17677, 33943, 33958, 33982,
- 17672, {f: 2, c: 33998}, 34003, 159333, 34023, 34026, 34031, 34033, 34042,
- 34075, {f: 2, c: 34084}, 34091, 34127, 34159, 17731, 34129,
- {f: 2, c: 34145}, 159636, 34171, 34173, 34175, 34177, 34182, 34195, 34205,
- 34207, 159736, {f: 2, c: 159734}, 34236, 34247, 34250, {f: 2, c: 34264},
- 34271, 34273, 34278, 34294, 34304, 34321, 34334, 34337, 34340, 34343,
- 160013, 34361, 34364, 160057, 34368, 34387, 34390, 34423, 34439, 34441,
- {f: 2, c: 34460}, 34481, 34483, 34497, 34499, 34513, 34517, 34519, 34531,
- 34534, 17848, 34565, 34567, 34574, 34576, 34591, 34593, 34595, 34609,
- 34618, 34624, 34627, 34641, 34648, {f: 2, c: 34660}, 34674, 34684, 160731,
- 160730, 34727, 34697, 34699, 34707, 34720, 160766, 17893, 34750, 160784,
- 34753, 34766, 34783, 160841, 34787, {f: 2, c: 34789}, 34794, 34835, 34856,
- 34862, 34866, 34876, 17935, 34890, 34904, 161301, 161300, 34921, 161329,
- 34927, 34976, 35004, 35008, 161427, 35025, 35027, 17985, 35073, 161550,
- 35127, 161571, 35138, 35141, 35145, 161618, 35170, 35209, 35216, 35231,
- 35248, 35255, 35288, 35307, 18081, 35315, 35325, 35327, 18095, 35345,
- 35348, 162181, 35361, 35381, 35390, 35397, 35405, 35416, 35502, 35472,
- 35511, 35543, 35580, 162436, 35594, 35589, 35597, 35612, 35629, 18188,
- 35665, 35678, 35702, 35713, 35723, {f: 2, c: 35732}, 35897, 162739, 35901,
- 162750, 162759, 35909, 35919, 35927, 35945, 35949, 163000, 35987, 35986,
- 35993, 18276, 35995, 36054, 36053, 163232, 36081, 163344, 36105, 36110,
- 36296, 36313, 36364, 18429, 36349, 36358, 163978, 36372, 36374,
- {f: 2, c: 36385}, 36391, 164027, 18454, 36406, 36409, 36436, 36450, 36461,
- 36463, 36504, 36510, 36533, 36539, 164482, 18510, 164595, 36608, 36616,
- 36651, 36672, 36682, 36696, 164876, 36772, 36788, 164949, 36801, 36806,
- 64036, 36810, 36813, 36819, 36821, 36849, 36853, 36859, 36876, 36919,
- 165227, 36931, 36957, {f: 2, c: 165320}, 36997, 37004, 37008, 37025, 18613,
- 37040, 37046, 37059, 37064, 165591, 37084, 37087, 165626, 37110, 37106,
- 37120, 37099, {f: 2, c: 37118}, 37124, 37126, 37144, 37150, 37175, 37177,
- {f: 2, c: 37190}, 37207, 37209, 37236, 37241, 37253, 37299, 37302,
- {f: 2, c: 37315}, 166217, 166214, 37356, 37377, {f: 2, c: 37398}, 166251,
- 37442, 37450, 37462, 37473, 37477, 37480, 166280, {f: 2, c: 37500}, 37503,
- 37513, 37517, 37527, 37529, 37535, 37547, {f: 2, c: 166330}, 37554,
- {f: 2, c: 37567}, 37574, 37582, 37605, 37649, 166430, 166441, 37623, 37673,
- 166513, 166467, 37713, 37722, 37739, 37745, 37747, 37793, 166553, 166605,
- 37768, 37771, 37775, 37790, 37877, 166628, 166621, 37873, 37831, 37852,
- 37863, 37897, {f: 2, c: 37910}, 37883, 37938, 37947, 166849, 166895, 37997,
- 37999, 38265, 38278, {f: 2, c: 38284}, 167184, 167281, 38344, 167419,
- 167455, 38444, {f: 2, c: 38451}, 167478, 38460, 38497, 167561, 38530,
- 167659, 38554, 167730, 18919, 38579, 38586, 38589, 18938, 167928, 38616,
- 38618, 38621, 18948, 38676, 38691, 18985, 38710, 38721, 38727, 38743,
- 38747, 38762, 168608, 168625, 38806, 38814, {f: 2, c: 38833}, 38846, 38860,
- 38865, 38868, 38872, 38881, 38897, 38916, 38925, 38932, 38934, 19132,
- 169104, {f: 2, c: 38962}, 38949, 38983, 39014, 39083, 39085, 39088, 169423,
- 39095, {f: 2, c: 39099}, 39106, 39111, 39115, 39137, 39139, 39146,
- {f: 2, c: 39152}, 39155, 39176, 19259, 169712, {f: 2, c: 39190}, 169753,
- {f: 3, c: 39194}, 169808, 39217, {f: 3, c: 39226}, 39233, 39238, 39246,
- 39264, 39331, 39334, 39357, 39359, 39363, 39380, 39385, 39390, 170182,
- 39408, 39417, 39420, 39434, 39441, 39450, 39456, 39473, 39492, 39500,
- 39512, 19394, 39599, 19402, 39607, 19410, 39609, 170610, 39622, 39632,
- 39634, 39637, 39648, 39653, 39657, 39692, 39696, 39698, 39702, 39708,
- 39723, 39741, 19488, 39755, 39779, 39781, {f: 2, c: 39787},
- {f: 2, c: 39798}, 39846, 39852, 171483, 39858, 39864, 39870, 39923, 39896,
- 39901, 39914, 39919, 39918, 171541, 171658, 171593, 39958,
- {f: 3, c: 39960}, 39965, 39970, 39977, 171716, 39985, 39991, 40005, 40028,
- 171753, {f: 2, c: 40009}, 171739, 40020, 40024, 40027, 40029, 40031,
- {f: 3, c: 40041}, {f: 2, c: 40045}, 40050, 40053, 40058, 40166, 40178,
- 40203, [171982, 171991], 40209, {f: 2, c: 40215}, 172079, 19652, 172058,
- 40242, 19665, 40266, 40287, 40290, 172281, 172162, 40307, {f: 2, c: 40310},
- 40324, 40345, 40353, 40383, 40373, 40377, 40381, 40393, 40410, 40416,
- 40419, 19719, 40458, 40450, 40461, 40476, 40571, 139800, 40576, 40581,
- 40603, 172940, 40637, 173111, 40671, 40703, 40706, 19831, 40707, 40762,
- 40765, 40774, 40787, 40789, 40792, 173553, 40797, 173570, 40809, 40813,
- 40816, 173746, 11948, 13844, 14509, 15820, 16348, 17854, 17936, 19326,
- 19512, 19681, 19980, {f: 2, c: 20003}, 20089, 20211, 20236, 20249, 20267,
- 20270, 20273, 20356, 20382, 20407, 20484, 20492, 20556, 20575, 20578,
- 20599, 20622, 20638, 20642, 20675, 20712, 20721, 20734, 20743,
- {f: 3, c: 20748}, 20787, 20792, 20852, 20868, 20920, 20922, 20936, 20943,
- 20945, {f: 2, c: 20947}, 20952, 20959, 20997, 21030, 21032, 21035,
- {f: 2, c: 21041}, 21045, 21052, 21082, 21088, 21102, {f: 2, c: 21112},
- 21130, 21132, 21217, 21225, 21233, 21251, 21265, 21279, 21293, 21298,
- 21309, 21349, 21357, 21369, 21374, 21396, 21401, 21418, 21423, 21434,
- 21441, {f: 2, c: 21444}, 21472, 21523, 21546, 21553, {f: 2, c: 21556},
- 21580, 21671, 21674, 21681, 21691, 21710, 21738, 21756, 21765, 21768,
- 21781, 21799, 21802, 21814, 21841, 21862, 21903, 21906, 21908, 21924,
- 21938, 21955, 21958, 21971, 21979, 21996, 21998, 22001, 22006, 22008,
- 22021, 22029, {f: 2, c: 22033}, 22060, 22069, 22073, 22093, 22100, 22149,
- 22175, 22182, 22199, 22220, 22223, 22233, 22241, 22251, 22253, 22257,
- 22279, 22284, {f: 2, c: 22298}, 22301, 22316, 22318, {f: 2, c: 22333},
- 22367, 22379, 22381, 22394, 22403, 22423, 22446, 22485, 22503, 22541,
- 22566, 22605, 22607, 22623, 22637, 22655, 22657, 22680, 22716, 22815,
- 22819, 22873, 22905, 22935, 22959, 22963, 23007, 23025, 23032, 23218,
- 23224, 23274, 23286, 23323, 23325, 23329, 23352, 23479, 23511, 23520,
- 23583, 23594, 23596, 23606, 23641, 23644, 23661, 23773, 23809, 23860,
- 23869, 23897, 23934, 23939, 24007, 24057, 24104, 24114, 24117, 24155,
- 24168, 24170, 24183, 24192, 24203, 24243, 24253, 24273, {f: 2, c: 24276},
- 24397, 24492, 24554, 24583, 24649, 24660, 24679, 24763, 24772, 24829,
- 24842, 24854, 24874, 24886, 24926, 24932, 24955, 24957, 24959, 24989,
- 25016, 25052, 25058, 25061, 25064, 25092, 25095, 25137, 25145, 25149,
- 25210, 25232, 25256, 25306, 25332, 25366, 25386, 25398, 25414, 25419,
- 25427, 25457, 25461, 25471, 25474, 25482, {f: 2, c: 25518}, 25578,
- {f: 2, c: 25592}, 25618, 25624, 25632, 25636, 25642, 25653, 25661, 25663,
- 25682, 25695, 25716, 25744, {f: 2, c: 25752}, 25772, 25779, 25837, 25840,
- 25883, 25887, 25902, 25929, 25952, 26002, 26005, 26036, 26046, 26056,
- 26062, 26064, 26079, 26238, {f: 2, c: 26251}, 26291, 26304, 26319, 26405,
- 26421, 26453, 26496, 26511, 26513, 26532, 26545, 26549, 26558, 26664,
- 26758, 26859, 26869, 26903, 26931, 26936, 26971, 26981, 27048, 27051,
- 27055, 27109, 27121, 27210, 27221, 27239, 27249, 27311, {f: 2, c: 27336},
- 27395, 27451, 27455, {f: 2, c: 27517}, 27568, 27639, 27641, 27652, 27657,
- 27661, 27692, 27722, 27730, 27732, 27769, 27820, 27828, 27858, 28001,
- 28028, 28089, 28144, 28229, 28275, 28283, 28285, 28297, 28348,
- {f: 2, c: 28378}, 28454, 28457, 28464, 28551, 28573, 28590, 28599, 28685,
- 28704, 28745, 28824, 28848, {f: 2, c: 28885}, 28997, 29106, 29172, 29207,
- 29215, 29251, {f: 2, c: 29263}, 29274, 29280, 29288, 29303, 29316, 29385,
- 29413, 29428, 29442, 29451, 29470, 29474, {f: 2, c: 29498}, 29517, 29528,
- 29543, 29810, 29871, 29919, 29924, 29940, 29947, 29974, 29985, 30015,
- 30046, 30105, 30116, 30145, 30148, 30156, 30167, 30172, 30177, 30191,
- 30212, 30220, 30237, 30258, 30264, 30277, 30282, 30303, 30381, 30397,
- 30425, 30443, 30448, 30457, 30464, 30478, 30498, 30504, 30511, 30521,
- 30526, 30533, 30538, 30543, 30558, 30564, 30567, 30572, 30596,
- {f: 2, c: 30604}, 30614, 30631, 30639, 30647, 30654, 30665, 30673, 30681,
- 30705, 30775, 30812, 30846, 30872, 30881, 30897, 30899, 30921, 30931,
- 30988, 31007, {f: 2, c: 31015}, 31039, 31042, 31060, 31083, 31100, 31147,
- 31172, 31210, 31234, 31244, 31280, 31290, 31300, 31360, 31366, 31380,
- 31413, 31421, 31486, 31531, 31607, 31648, 31660, 31664, 31720, 31730,
- 31736, 31740, 31742, 31753, 31784, 31791, 31810, {f: 2, c: 31826},
- {f: 3, c: 31835}, 31858, 31869, 31879, 31902, 31930, 31943, 31955, 31962,
- 32060, 32077, 32130, 32133, 32141, 32145, 32158, 32179, 32185, 32208,
- 32229, {f: 2, c: 32245}, 32303, 32310, 32324, 32367, 32376, 32385, 32573,
- 32603, 32605, 32613, 32625, {f: 2, c: 32639}, 32651, 32674,
- {f: 3, c: 32765}, 32775, 32781, 32798, 32825, 32904, 32910, 32975, 32980,
- 33005, 33008, 33015, 33018, 33022, 33027, 33047, 33072, 33111, 33135,
- 33139, 33163, 33168, 33179, 33182, 33227, 33237, {f: 2, c: 33245}, 33249,
- 33263, 33270, 33280, 33291, {f: 2, c: 33299}, 33306, 33338, 33348, 33389,
- 33412, 33417, 33425, 33450, 33456, 33488, 33514, 33519, 33526, 33622,
- 33656, 33784, 33788, 33880, 33939, 33969, 33981, 34043, 34118, 34134,
- 34141, 34181, 34200, 34370, 34374, 34496, 34580, 34594, 34606, 34617,
- 34653, 34683, 34700, 34702, {f: 2, c: 34711}, 34718, 34723, 34734, 34751,
- 34761, 34778, 34840, 34843, 34861, 34874, 34885, 34891, 34894, 34901,
- 34906, 34926, {f: 3, c: 34970}, 35021, 35040, 35055, {f: 2, c: 35086},
- 35110, 35125, 35162, 35164, 35179, 35184, 35196, 35237, 35253, 35260,
- 35285, 35401, 35415, 35431, 35454, 35462, 35478, 35510, 35529, 35537,
- 35549, 35564, 35573, 35590, 35599, 35601, 35653, 35666, 35693, 35704,
- 35708, 35710, 35717, 35743, 35915, 35923, 35963, 36026, 36037, 36041,
- 36050, 36076, 36085, 36087, 36097, 36099, 36119, 36124, 36206, 36241,
- 36255, 36267, 36274, 36309, 36327, {f: 2, c: 36337}, 36340, 36353, 36363,
- 36390, 36401, {f: 2, c: 36416}, 36429, 36431, 36444, 36449, 36457, 36465,
- 36469, 36471, 36489, 36496, 36501, 36506, 36519, 36521, 36525, 36584,
- 36592, 36615, 36632, 36645, 36647, 36652, 36661, 36666, 36675, 36679,
- 36689, 36693, {f: 3, c: 36768}, 36773, 36868, 36891, 36911, 36940, 36955,
- 36976, 36980, 36985, 37003, 37016, 37024, 37042, 37053, 37065, 37104,
- 37125, 37157, 37210, 37223, 37242, 37258, 37265, 37269, 37296, 37307,
- 37309, 37314, 37317, 37376, 37385, 37411, 37494, 37518, 37551,
- {f: 2, c: 37563}, 37569, 37571, 37573, 37576, 37652, 37683, 37686, 37720,
- 37759, 37762, 37770, 37819, 37836, 37862, 37881, 37890, {f: 2, c: 37901},
- 37934, 37964, 38280, 38305, 38335, 38342, 38345, {f: 2, c: 38353}, 38368,
- 38372, 38374, 38436, 38449, 38456, 38461, 38484, 38516, 38523, 38527,
- 38529, 38531, 38537, 38550, 38574, 38659, 38683, {f: 2, c: 38689}, 38696,
- 38705, 38759, 38774, 38781, 38783, 38809, 38815, 38828, 38841, 38861,
- 38880, 38895, 38919, 38950, 38958, {f: 2, c: 39010}, 39092, 39109, 39170,
- 39185, 39189, 39221, 39240, 39252, 39262, 39393, 39436, 39440, 39459,
- 39489, 39505, {f: 2, c: 39613}, 39681, 39689, 39691, {f: 2, c: 39693},
- 39705, 39733, 39752, 39765, 39784, 39808, 39814, 39824, 39837, 39856,
- 39871, 39880, 39935, 39938, 39964, 39989, 40004, 40022, 40033, 40040,
- 40240, 40253, 40298, 40315, 40421, 40425, 40435, 40570, {f: 3, c: 40578},
- 40624, 40676, 40688, 40690, 40713, 40719, 40724, 40731, 40738, 40742,
- {f: 2, c: 40746}, 40756, 40794, 40815, 40862, 40869, 131317, 151044,
- 151538, 163187, 194581, 194630, 194713, 194726, 194789, 195038, 13790,
- {s: 4}, 172722, 0, 0, 131416, {s: 4}, 132529, 0, 0, 132844, {s: 6}, 134488,
- {s: 21}, 154060, {s: 9}, 14756, 14776, 142914, 0, 0, 14940, 0, 0, 143339,
- 0, 0, 162228, 0, 15044, 15051, {s: 5}, 14981, {s: 8}, 15347, 27384, {s: 5},
- 15665, {s: 9}, 147531, 0, 15936, 14497, {s: 34}, 158878, {s: 12}, 18207,
- 162876, {s: 4}, 18462, {s: 71}, 39709, 39724, 20482, 20958, 21255, 23532,
- 63784, 26142, 63785, 28746, 64021, 21857, 27706, 31328, 156492, 34819,
- 38315, 38741, 171581, 173594],
- 'Adobe-Korea1': [{f: 95, c: 32}, 8361, 8208, 169, 0, 0, [12288, 12644],
- {f: 2, c: 12289}, 12539, 8229, [8230, 8943], 168, 12291, {f: 2, c: 8211},
- 8214, 65340, 65374, {f: 2, c: 8216}, {f: 2, c: 8220}, {f: 2, c: 12308},
- {f: 10, c: 12296}, 177, 215, 247, 8800, {f: 2, c: 8804}, 8734, 8756, 176,
- {f: 2, c: 8242}, 8451, 8491, {f: 2, c: 65504}, 65509, 9794, 9792, 8736,
- 8869, 8978, 8706, 8711, 8801, 8786, 167, 8251, 9734, 9733, 9675, 9679,
- 9678, 9671, 9670, 9633, 9632, 9651, 9650, 9661, 9660, 8594,
- {f: 2, c: 8592}, {f: 2, c: 8595}, 12307, 171, 187, 8730, 8765, 8733, 8757,
- {f: 2, c: 8747}, 8712, 8715, {f: 2, c: 8838}, {f: 2, c: 8834}, 8746, 8745,
- {f: 2, c: 8743}, 65506, 8658, 8660, 8704, 8707, 180, 732, 711, 728, 733,
- 730, 729, 184, 731, 161, 191, 8758, 8750, 8721, 8719, 164, 8457, 8240,
- 9665, 9664, 9655, 9654, 9828, {f: 2, c: 9824}, 9829, 9831, 9827, 9673,
- 9672, 9635, {f: 2, c: 9680}, 9618, {f: 2, c: 9636}, 9640, 9639, 9638, 9641,
- 9832, 9743, 9742, 9756, 9758, 182, {f: 2, c: 8224}, 8597, 8599, 8601, 8598,
- 8600, 9837, {f: 2, c: 9833}, 9836, 12927, 12828, 8470, 13255, 8482, 13250,
- 13272, 8481, {f: 59, c: 65281}, 65510, {f: 33, c: 65341}, 65507,
- {f: 51, c: 12593}, {f: 42, c: 12645}, {f: 10, c: 8560}, {f: 10, c: 8544},
- {f: 17, c: 913}, {f: 7, c: 931}, {f: 17, c: 945}, {f: 7, c: 963}, 9472,
- 9474, 9484, 9488, 9496, 9492, 9500, 9516, 9508, 9524, 9532, 9473, 9475,
- 9487, 9491, 9499, 9495, 9507, 9523, 9515, 9531, 9547, 9504, 9519, 9512,
- 9527, 9535, 9501, 9520, 9509, 9528, 9538, 9490, 9489, 9498, 9497, 9494,
- 9493, 9486, 9485, {f: 2, c: 9502}, {f: 2, c: 9505}, {f: 2, c: 9510},
- {f: 2, c: 9513}, {f: 2, c: 9517}, {f: 2, c: 9521}, {f: 2, c: 9525},
- {f: 2, c: 9529}, {f: 2, c: 9533}, {f: 2, c: 9536}, {f: 8, c: 9539},
- {f: 3, c: 13205}, 8467, 13208, 13252, {f: 4, c: 13219}, {f: 10, c: 13209},
- 13258, {f: 3, c: 13197}, 13263, {f: 2, c: 13192}, 13256, {f: 2, c: 13223},
- {f: 10, c: 13232}, {f: 5, c: 13184}, {f: 6, c: 13242}, {f: 5, c: 13200},
- 8486, {f: 2, c: 13248}, {f: 3, c: 13194}, 13270, 13253, {f: 3, c: 13229},
- 13275, {f: 4, c: 13225}, 13277, 13264, 13267, 13251, 13257, 13276, 13254,
- 198, 208, 170, 294, 306, 319, 321, 216, 338, 186, 222, 358, 330,
- {f: 28, c: 12896}, {f: 26, c: 9424}, {f: 15, c: 9312}, 189,
- {f: 2, c: 8531}, 188, 190, {f: 4, c: 8539}, 230, 273, 240, 295, 305, 307,
- 312, 320, 322, 248, 339, 223, 254, 359, 331, 329, {f: 28, c: 12800},
- {f: 26, c: 9372}, {f: 15, c: 9332}, 185, {f: 2, c: 178}, 8308, 8319,
- {f: 4, c: 8321}, {f: 83, c: 12353}, {f: 86, c: 12449}, {f: 6, c: 1040},
- 1025, {f: 32, c: 1046}, 1105, {f: 26, c: 1078}, {f: 2, c: 44032}, 44036,
- {f: 4, c: 44039}, {f: 8, c: 44048}, {f: 5, c: 44057}, 44064, 44068,
- {f: 2, c: 44076}, {f: 3, c: 44079}, {f: 2, c: 44088}, 44092, 44096, 44107,
- 44109, 44116, 44120, 44124, {f: 2, c: 44144}, 44148, {f: 2, c: 44151},
- 44154, {f: 2, c: 44160}, {f: 4, c: 44163}, {f: 4, c: 44169}, 44176, 44180,
- {f: 2, c: 44188}, {f: 3, c: 44191}, {f: 3, c: 44200}, 44204,
- {f: 2, c: 44207}, {f: 2, c: 44216}, {f: 3, c: 44219}, 44225, 44228, 44232,
- 44236, 44245, 44247, {f: 2, c: 44256}, 44260, {f: 2, c: 44263}, 44266,
- 44268, {f: 3, c: 44271}, 44275, {f: 2, c: 44277}, {f: 2, c: 44284}, 44288,
- 44292, 44294, {f: 2, c: 44300}, 44303, 44305, 44312, 44316, 44320, 44329,
- {f: 2, c: 44332}, {f: 2, c: 44340}, 44344, 44348, {f: 2, c: 44356}, 44359,
- 44361, 44368, 44372, 44376, 44385, 44387, {f: 2, c: 44396}, 44400,
- {f: 4, c: 44403}, {f: 3, c: 44411}, 44415, {f: 2, c: 44417},
- {f: 2, c: 44424}, 44428, 44432, {f: 2, c: 44444}, 44452, 44471,
- {f: 2, c: 44480}, 44484, 44488, {f: 2, c: 44496}, 44499, 44508, 44512,
- 44516, {f: 2, c: 44536}, 44540, {f: 3, c: 44543}, {f: 2, c: 44552}, 44555,
- 44557, 44564, {f: 2, c: 44592}, 44596, {f: 2, c: 44599}, 44602,
- {f: 2, c: 44608}, 44611, {f: 2, c: 44613}, 44618, {f: 3, c: 44620}, 44624,
- 44628, 44630, {f: 2, c: 44636}, {f: 3, c: 44639}, 44645, {f: 2, c: 44648},
- 44652, 44656, {f: 2, c: 44664}, {f: 3, c: 44667}, {f: 2, c: 44676}, 44684,
- {f: 3, c: 44732}, 44736, 44740, {f: 2, c: 44748}, {f: 3, c: 44751},
- {f: 2, c: 44760}, 44764, 44776, 44779, 44781, 44788, 44792, 44796,
- {f: 2, c: 44807}, 44813, 44816, {f: 2, c: 44844}, 44848, 44850, 44852,
- {f: 2, c: 44860}, 44863, {f: 3, c: 44865}, {f: 2, c: 44872}, 44880,
- {f: 2, c: 44892}, {f: 2, c: 44900}, 44921, 44928, 44932, 44936,
- {f: 2, c: 44944}, 44949, 44956, {f: 2, c: 44984}, 44988, 44992,
- {f: 3, c: 44999}, 45003, {f: 2, c: 45005}, 45012, 45020, {f: 2, c: 45032},
- {f: 2, c: 45040}, 45044, 45048, {f: 2, c: 45056}, 45060, 45068, 45072,
- 45076, {f: 2, c: 45084}, 45096, {f: 2, c: 45124}, 45128, 45130, 45132,
- 45134, {f: 3, c: 45139}, 45143, 45145, 45149, {f: 2, c: 45180}, 45184,
- 45188, {f: 2, c: 45196}, 45199, 45201, {f: 3, c: 45208}, 45212,
- {f: 4, c: 45215}, {f: 2, c: 45224}, {f: 5, c: 45227}, 45233,
- {f: 3, c: 45235}, 45240, 45244, {f: 2, c: 45252}, {f: 3, c: 45255},
- {f: 2, c: 45264}, 45268, 45272, 45280, 45285, {f: 2, c: 45320},
- {f: 2, c: 45323}, 45328, {f: 2, c: 45330}, {f: 2, c: 45336},
- {f: 3, c: 45339}, {f: 3, c: 45347}, 45352, 45356, {f: 2, c: 45364},
- {f: 3, c: 45367}, {f: 2, c: 45376}, 45380, 45384, {f: 2, c: 45392},
- {f: 2, c: 45396}, 45400, 45404, 45408, {f: 2, c: 45432}, 45436, 45440,
- 45442, {f: 2, c: 45448}, 45451, 45453, {f: 3, c: 45458}, 45464, 45468,
- 45480, 45516, 45520, 45524, {f: 2, c: 45532}, 45535, {f: 2, c: 45544},
- 45548, 45552, 45561, 45563, 45565, {f: 2, c: 45572}, 45576,
- {f: 2, c: 45579}, {f: 2, c: 45588}, 45591, 45593, 45600, 45620, 45628,
- 45656, 45660, 45664, {f: 2, c: 45672}, {f: 2, c: 45684}, 45692,
- {f: 2, c: 45700}, 45705, {f: 2, c: 45712}, 45716, {f: 3, c: 45720},
- {f: 2, c: 45728}, 45731, {f: 2, c: 45733}, 45738, 45740, 45744, 45748,
- {f: 2, c: 45768}, 45772, 45776, 45778, {f: 2, c: 45784}, 45787, 45789,
- 45794, {f: 3, c: 45796}, 45800, {f: 5, c: 45803}, {f: 3, c: 45811},
- {f: 5, c: 45815}, {f: 3, c: 45823}, 45828, 45832, {f: 2, c: 45840},
- {f: 3, c: 45843}, 45852, {f: 3, c: 45908}, 45912, {f: 2, c: 45915},
- {f: 2, c: 45918}, {f: 2, c: 45924}, 45927, 45929, 45931, 45934,
- {f: 2, c: 45936}, 45940, 45944, {f: 2, c: 45952}, {f: 3, c: 45955}, 45964,
- 45968, 45972, {f: 2, c: 45984}, 45992, 45996, {f: 2, c: 46020}, 46024,
- {f: 2, c: 46027}, 46030, 46032, {f: 2, c: 46036}, 46039, 46041, 46043,
- 46045, 46048, 46052, 46056, 46076, 46096, 46104, 46108, 46112,
- {f: 2, c: 46120}, 46123, 46132, {f: 2, c: 46160}, 46164, 46168,
- {f: 2, c: 46176}, 46179, 46181, 46188, 46208, 46216, 46237, 46244, 46248,
- 46252, 46261, 46263, 46265, 46272, 46276, 46280, 46288, 46293,
- {f: 2, c: 46300}, 46304, {f: 2, c: 46307}, 46310, {f: 2, c: 46316}, 46319,
- 46321, 46328, {f: 2, c: 46356}, 46360, {f: 2, c: 46363}, {f: 2, c: 46372},
- {f: 4, c: 46375}, {f: 2, c: 46384}, 46388, 46392, {f: 2, c: 46400},
- {f: 3, c: 46403}, {f: 3, c: 46411}, 46416, 46420, {f: 2, c: 46428},
- {f: 3, c: 46431}, {f: 2, c: 46496}, 46500, 46504, {f: 2, c: 46506},
- {f: 2, c: 46512}, {f: 3, c: 46515}, {f: 3, c: 46523}, 46528, 46532,
- {f: 2, c: 46540}, {f: 3, c: 46543}, 46552, 46572, {f: 2, c: 46608}, 46612,
- 46616, 46629, 46636, 46644, 46664, 46692, 46696, {f: 2, c: 46748}, 46752,
- 46756, {f: 2, c: 46763}, 46769, 46804, 46832, 46836, 46840,
- {f: 2, c: 46848}, 46853, {f: 2, c: 46888}, 46892, {f: 2, c: 46895},
- {f: 2, c: 46904}, 46907, 46916, 46920, 46924, {f: 2, c: 46932}, 46944,
- 46948, 46952, {f: 2, c: 46960}, 46963, 46965, {f: 2, c: 46972}, 46976,
- 46980, {f: 2, c: 46988}, {f: 4, c: 46991}, {f: 4, c: 46998}, 47004, 47008,
- {f: 2, c: 47016}, {f: 3, c: 47019}, {f: 2, c: 47028}, 47032, 47047, 47049,
- {f: 2, c: 47084}, 47088, 47092, {f: 2, c: 47100}, {f: 3, c: 47103},
- {f: 3, c: 47111}, 47116, 47120, {f: 2, c: 47128}, 47131, 47133,
- {f: 2, c: 47140}, 47144, 47148, {f: 2, c: 47156}, {f: 3, c: 47159}, 47168,
- 47172, 47185, 47187, {f: 2, c: 47196}, 47200, 47204, {f: 2, c: 47212},
- 47215, 47217, 47224, 47228, 47245, 47272, 47280, 47284, 47288,
- {f: 2, c: 47296}, 47299, 47301, 47308, 47312, 47316, 47325, 47327, 47329,
- {f: 2, c: 47336}, 47340, 47344, {f: 2, c: 47352}, 47355, 47357, 47364,
- 47384, 47392, {f: 2, c: 47420}, 47424, 47428, 47436, 47439, 47441,
- {f: 2, c: 47448}, 47452, 47456, {f: 2, c: 47464}, 47467, 47469,
- {f: 2, c: 47476}, 47480, 47484, {f: 2, c: 47492}, 47495, {f: 2, c: 47497},
- {f: 2, c: 47501}, {f: 2, c: 47532}, 47536, 47540, {f: 2, c: 47548}, 47551,
- 47553, {f: 2, c: 47560}, 47564, {f: 5, c: 47566}, {f: 2, c: 47576}, 47579,
- {f: 2, c: 47581}, 47585, {f: 3, c: 47587}, 47592, 47596, {f: 2, c: 47604},
- {f: 4, c: 47607}, {f: 2, c: 47616}, 47624, 47637, {f: 2, c: 47672}, 47676,
- 47680, 47682, {f: 2, c: 47688}, 47691, {f: 2, c: 47693}, {f: 3, c: 47699},
- 47704, 47708, {f: 2, c: 47716}, {f: 3, c: 47719}, {f: 2, c: 47728}, 47732,
- 47736, {f: 3, c: 47747}, 47751, 47756, {f: 2, c: 47784}, {f: 2, c: 47787},
- 47792, 47794, {f: 2, c: 47800}, 47803, 47805, 47812, 47816,
- {f: 2, c: 47832}, 47868, 47872, 47876, 47885, 47887, 47889, 47896, 47900,
- 47904, 47913, 47915, {f: 3, c: 47924}, 47928, {f: 4, c: 47931},
- {f: 2, c: 47940}, 47943, 47945, 47949, {f: 2, c: 47951}, 47956, 47960,
- 47969, 47971, 47980, 48008, 48012, 48016, 48036, 48040, 48044, 48052,
- 48055, 48064, 48068, 48072, 48080, 48083, {f: 2, c: 48120}, 48124,
- {f: 2, c: 48127}, 48130, {f: 2, c: 48136}, {f: 3, c: 48139}, 48143, 48145,
- {f: 5, c: 48148}, {f: 5, c: 48155}, {f: 2, c: 48164}, 48167, 48169, 48173,
- {f: 2, c: 48176}, 48180, 48184, {f: 2, c: 48192}, {f: 3, c: 48195}, 48201,
- {f: 2, c: 48204}, 48208, 48221, {f: 2, c: 48260}, 48264, {f: 2, c: 48267},
- 48270, {f: 2, c: 48276}, 48279, {f: 2, c: 48281}, {f: 2, c: 48288}, 48292,
- {f: 2, c: 48295}, {f: 2, c: 48304}, {f: 3, c: 48307}, {f: 2, c: 48316},
- 48320, 48324, 48333, {f: 3, c: 48335}, 48341, 48344, 48348,
- {f: 3, c: 48372}, 48376, 48380, {f: 2, c: 48388}, 48391, 48393, 48400,
- 48404, 48420, 48428, 48448, {f: 2, c: 48456}, 48460, 48464,
- {f: 2, c: 48472}, 48484, 48488, {f: 2, c: 48512}, 48516, {f: 4, c: 48519},
- {f: 2, c: 48528}, 48531, 48533, {f: 2, c: 48537}, 48540, 48548, 48560,
- 48568, {f: 2, c: 48596}, 48600, 48604, 48617, 48624, 48628, 48632, 48640,
- 48643, 48645, {f: 2, c: 48652}, 48656, 48660, {f: 2, c: 48668}, 48671,
- {f: 2, c: 48708}, 48712, 48716, 48718, {f: 2, c: 48724}, 48727,
- {f: 3, c: 48729}, {f: 2, c: 48736}, 48740, 48744, 48746, {f: 2, c: 48752},
- {f: 3, c: 48755}, {f: 3, c: 48763}, 48768, 48772, {f: 2, c: 48780},
- {f: 3, c: 48783}, {f: 2, c: 48792}, 48808, {f: 2, c: 48848}, 48852,
- {f: 2, c: 48855}, 48864, {f: 3, c: 48867}, 48876, 48897, {f: 2, c: 48904},
- {f: 2, c: 48920}, {f: 3, c: 48923}, {f: 2, c: 48960}, 48964, 48968,
- {f: 2, c: 48976}, 48981, 49044, 49072, 49093, {f: 2, c: 49100}, 49104,
- 49108, 49116, 49119, 49121, 49212, 49233, 49240, 49244, 49248,
- {f: 2, c: 49256}, {f: 2, c: 49296}, 49300, 49304, {f: 2, c: 49312}, 49315,
- 49317, {f: 2, c: 49324}, {f: 2, c: 49327}, {f: 4, c: 49331},
- {f: 2, c: 49340}, {f: 3, c: 49343}, 49349, {f: 2, c: 49352}, 49356, 49360,
- {f: 2, c: 49368}, {f: 3, c: 49371}, {f: 2, c: 49380}, 49384, 49388,
- {f: 2, c: 49396}, 49399, 49401, 49408, 49412, 49416, 49424, 49429,
- {f: 5, c: 49436}, {f: 2, c: 49443}, {f: 2, c: 49446}, {f: 2, c: 49452},
- {f: 3, c: 49455}, 49462, {f: 2, c: 49464}, 49468, 49472, {f: 2, c: 49480},
- {f: 3, c: 49483}, {f: 2, c: 49492}, 49496, 49500, {f: 2, c: 49508},
- {f: 3, c: 49511}, 49520, 49524, 49528, 49541, {f: 3, c: 49548}, 49552,
- 49556, 49558, {f: 2, c: 49564}, 49567, 49569, 49573, {f: 2, c: 49576},
- 49580, 49584, 49597, 49604, 49608, 49612, 49620, {f: 2, c: 49623}, 49632,
- 49636, 49640, {f: 2, c: 49648}, 49651, {f: 2, c: 49660}, 49664, 49668,
- {f: 2, c: 49676}, 49679, 49681, {f: 2, c: 49688}, 49692, {f: 2, c: 49695},
- {f: 2, c: 49704}, 49707, 49709, 49711, {f: 2, c: 49713}, 49716, 49736,
- {f: 2, c: 49744}, 49748, 49752, 49760, 49765, {f: 2, c: 49772}, 49776,
- 49780, {f: 2, c: 49788}, 49791, 49793, {f: 2, c: 49800}, 49808, 49816,
- 49819, 49821, {f: 2, c: 49828}, 49832, {f: 2, c: 49836}, {f: 2, c: 49844},
- 49847, 49849, {f: 2, c: 49884}, 49888, {f: 2, c: 49891}, {f: 3, c: 49899},
- 49903, 49905, 49910, {f: 2, c: 49912}, {f: 2, c: 49915}, 49920,
- {f: 2, c: 49928}, {f: 2, c: 49932}, {f: 3, c: 49939}, 49944, 49948,
- {f: 2, c: 49956}, {f: 2, c: 49960}, 49989, {f: 2, c: 50024}, 50028, 50032,
- 50034, {f: 2, c: 50040}, {f: 2, c: 50044}, 50052, 50056, 50060, 50112,
- {f: 2, c: 50136}, 50140, {f: 2, c: 50143}, 50146, {f: 2, c: 50152}, 50157,
- {f: 2, c: 50164}, 50168, 50184, 50192, 50212, 50220, 50224, 50228,
- {f: 2, c: 50236}, 50248, {f: 2, c: 50276}, 50280, 50284, {f: 2, c: 50292},
- 50297, 50304, 50324, 50332, 50360, 50364, 50409, {f: 2, c: 50416}, 50420,
- 50424, 50426, {f: 3, c: 50431}, 50444, 50448, 50452, 50460,
- {f: 2, c: 50472}, 50476, 50480, {f: 2, c: 50488}, 50491, 50493,
- {f: 2, c: 50500}, {f: 3, c: 50504}, {f: 3, c: 50508}, {f: 3, c: 50515},
- {f: 3, c: 50519}, {f: 2, c: 50525}, {f: 2, c: 50528}, 50532, 50536,
- {f: 2, c: 50544}, {f: 3, c: 50547}, {f: 2, c: 50556}, 50560, 50564, 50567,
- {f: 2, c: 50572}, 50575, 50577, 50581, {f: 2, c: 50583}, 50588, 50592,
- 50601, {f: 2, c: 50612}, {f: 2, c: 50616}, {f: 4, c: 50619},
- {f: 7, c: 50628}, 50636, 50638, {f: 2, c: 50640}, 50644, 50648,
- {f: 2, c: 50656}, 50659, 50661, {f: 3, c: 50668}, 50672, 50676,
- {f: 2, c: 50678}, {f: 6, c: 50684}, {f: 4, c: 50693}, 50700, 50704,
- {f: 2, c: 50712}, {f: 2, c: 50715}, {f: 2, c: 50724}, 50728,
- {f: 3, c: 50732}, 50736, {f: 3, c: 50739}, 50743, 50745, 50747,
- {f: 2, c: 50752}, 50756, 50760, {f: 2, c: 50768}, {f: 3, c: 50771},
- {f: 2, c: 50780}, 50784, 50796, 50799, 50801, {f: 2, c: 50808}, 50812,
- 50816, {f: 2, c: 50824}, 50827, 50829, {f: 2, c: 50836}, 50840, 50844,
- {f: 2, c: 50852}, 50855, 50857, {f: 2, c: 50864}, 50868, {f: 3, c: 50872},
- {f: 2, c: 50880}, 50883, 50885, {f: 2, c: 50892}, 50896, 50900,
- {f: 2, c: 50908}, {f: 2, c: 50912}, {f: 2, c: 50920}, 50924, 50928,
- {f: 2, c: 50936}, 50941, {f: 2, c: 50948}, 50952, 50956, {f: 2, c: 50964},
- 50967, 50969, {f: 2, c: 50976}, 50980, 50984, {f: 2, c: 50992}, 50995,
- 50997, 50999, {f: 2, c: 51004}, 51008, 51012, 51018, {f: 2, c: 51020},
- 51023, {f: 8, c: 51025}, 51036, 51040, 51048, 51051, {f: 2, c: 51060},
- 51064, {f: 3, c: 51068}, {f: 3, c: 51075}, {f: 4, c: 51079}, 51086,
- {f: 2, c: 51088}, 51092, {f: 3, c: 51094}, 51098, {f: 2, c: 51104},
- {f: 4, c: 51107}, {f: 2, c: 51116}, 51120, 51124, {f: 2, c: 51132},
- {f: 3, c: 51135}, {f: 2, c: 51144}, 51148, 51150, 51152, 51160, 51165,
- 51172, 51176, 51180, {f: 2, c: 51200}, 51204, 51208, 51210,
- {f: 2, c: 51216}, 51219, {f: 2, c: 51221}, {f: 2, c: 51228}, 51232, 51236,
- {f: 2, c: 51244}, 51247, 51249, 51256, 51260, 51264, {f: 2, c: 51272},
- {f: 2, c: 51276}, 51284, {f: 2, c: 51312}, 51316, 51320, 51322,
- {f: 2, c: 51328}, 51331, {f: 3, c: 51333}, {f: 3, c: 51339}, 51348, 51357,
- 51359, 51361, 51368, {f: 2, c: 51388}, 51396, 51400, 51404,
- {f: 2, c: 51412}, 51415, 51417, {f: 2, c: 51424}, 51428, 51445,
- {f: 2, c: 51452}, 51456, {f: 3, c: 51460}, {f: 2, c: 51468}, 51471, 51473,
- 51480, 51500, 51508, {f: 2, c: 51536}, 51540, 51544, {f: 2, c: 51552},
- 51555, 51564, 51568, 51572, 51580, {f: 2, c: 51592}, 51596, 51600,
- {f: 2, c: 51608}, 51611, 51613, {f: 2, c: 51648}, 51652, {f: 2, c: 51655},
- 51658, {f: 2, c: 51664}, 51667, {f: 2, c: 51669}, {f: 2, c: 51673},
- {f: 2, c: 51676}, 51680, 51682, 51684, 51687, {f: 2, c: 51692},
- {f: 3, c: 51695}, {f: 2, c: 51704}, 51708, 51712, {f: 2, c: 51720},
- {f: 3, c: 51723}, 51732, 51736, 51753, {f: 2, c: 51788}, 51792, 51796,
- {f: 2, c: 51804}, {f: 3, c: 51807}, 51816, 51837, 51844, 51864,
- {f: 2, c: 51900}, 51904, 51908, {f: 2, c: 51916}, 51919, 51921, 51923,
- {f: 2, c: 51928}, 51936, 51948, 51956, 51976, 51984, 51988, 51992,
- {f: 2, c: 52000}, 52033, {f: 2, c: 52040}, 52044, 52048, {f: 2, c: 52056},
- 52061, 52068, {f: 2, c: 52088}, 52124, 52152, 52180, 52196, 52199, 52201,
- {f: 2, c: 52236}, 52240, 52244, {f: 2, c: 52252}, {f: 2, c: 52257},
- {f: 3, c: 52263}, 52268, 52270, 52272, {f: 2, c: 52280}, {f: 4, c: 52283},
- {f: 2, c: 52292}, 52296, 52300, {f: 2, c: 52308}, {f: 3, c: 52311}, 52320,
- 52324, 52326, 52328, 52336, 52341, {f: 2, c: 52376}, 52380, 52384,
- {f: 2, c: 52392}, {f: 3, c: 52395}, {f: 2, c: 52404}, 52408, 52412,
- {f: 2, c: 52420}, 52423, 52425, 52432, 52436, 52452, 52460, 52464, 52481,
- {f: 2, c: 52488}, 52492, 52496, {f: 2, c: 52504}, 52507, 52509, 52516,
- 52520, 52524, 52537, 52572, 52576, 52580, {f: 2, c: 52588}, 52591, 52593,
- 52600, 52616, {f: 2, c: 52628}, 52632, 52636, {f: 2, c: 52644}, 52647,
- 52649, 52656, 52676, 52684, 52688, 52712, 52716, 52720, {f: 2, c: 52728},
- 52731, 52733, 52740, 52744, 52748, 52756, 52761, {f: 2, c: 52768}, 52772,
- 52776, {f: 2, c: 52784}, 52787, 52789, {f: 2, c: 52824}, 52828,
- {f: 3, c: 52831}, {f: 2, c: 52840}, 52843, 52845, {f: 2, c: 52852}, 52856,
- 52860, {f: 2, c: 52868}, 52871, 52873, {f: 2, c: 52880}, 52884, 52888,
- {f: 2, c: 52896}, {f: 3, c: 52899}, {f: 2, c: 52908}, 52929,
- {f: 2, c: 52964}, 52968, {f: 2, c: 52971}, {f: 2, c: 52980},
- {f: 3, c: 52983}, {f: 2, c: 52992}, 52996, 53000, {f: 2, c: 53008}, 53011,
- 53013, 53020, 53024, 53028, {f: 2, c: 53036}, {f: 3, c: 53039}, 53048,
- {f: 2, c: 53076}, 53080, 53084, {f: 2, c: 53092}, 53095, 53097,
- {f: 2, c: 53104}, 53108, 53112, 53120, 53125, 53132, 53153, 53160, 53168,
- 53188, {f: 2, c: 53216}, 53220, 53224, {f: 2, c: 53232}, 53235, 53237,
- 53244, 53248, 53252, 53265, 53272, 53293, {f: 2, c: 53300}, 53304, 53308,
- {f: 2, c: 53316}, 53319, 53321, 53328, 53332, 53336, 53344,
- {f: 2, c: 53356}, 53360, 53364, {f: 2, c: 53372}, 53377, {f: 2, c: 53412},
- 53416, 53420, {f: 2, c: 53428}, 53431, 53433, {f: 2, c: 53440}, 53444,
- {f: 2, c: 53448}, {f: 2, c: 53456}, {f: 3, c: 53459}, {f: 2, c: 53468},
- 53472, 53476, {f: 2, c: 53484}, {f: 3, c: 53487}, 53496, 53517,
- {f: 2, c: 53552}, 53556, 53560, 53562, {f: 2, c: 53568}, {f: 3, c: 53571},
- {f: 2, c: 53580}, 53584, 53588, {f: 2, c: 53596}, 53599, 53601, 53608,
- 53612, 53628, 53636, 53640, {f: 2, c: 53664}, 53668, 53672,
- {f: 2, c: 53680}, 53683, 53685, 53690, 53692, 53696, 53720, 53748, 53752,
- 53767, 53769, 53776, {f: 2, c: 53804}, 53808, 53812, {f: 2, c: 53820},
- 53823, 53825, 53832, 53852, 53860, {f: 2, c: 53888}, 53892, 53896,
- {f: 2, c: 53904}, 53909, 53916, 53920, 53924, 53932, 53937,
- {f: 2, c: 53944}, 53948, {f: 2, c: 53951}, 53954, {f: 2, c: 53960}, 53963,
- 53972, 53976, 53980, {f: 2, c: 53988}, {f: 2, c: 54000}, 54004, 54008,
- {f: 2, c: 54016}, 54019, 54021, {f: 3, c: 54028}, 54032, 54036, 54038,
- {f: 2, c: 54044}, {f: 3, c: 54047}, 54053, {f: 2, c: 54056}, 54060, 54064,
- {f: 2, c: 54072}, {f: 3, c: 54075}, {f: 2, c: 54084}, {f: 2, c: 54140},
- 54144, 54148, {f: 2, c: 54156}, {f: 3, c: 54159}, {f: 2, c: 54168}, 54172,
- 54176, {f: 2, c: 54184}, 54187, 54189, 54196, 54200, 54204,
- {f: 2, c: 54212}, {f: 2, c: 54216}, 54224, 54232, 54241, 54243,
- {f: 2, c: 54252}, 54256, 54260, {f: 2, c: 54268}, 54271, 54273, 54280,
- 54301, 54336, 54340, 54364, 54368, 54372, 54381, 54383, {f: 2, c: 54392},
- 54396, {f: 2, c: 54399}, 54402, {f: 2, c: 54408}, 54411, 54413, 54420,
- 54441, 54476, 54480, 54484, 54492, 54495, 54504, 54508, 54512, 54520,
- 54523, 54525, 54532, 54536, 54540, {f: 2, c: 54548}, 54551,
- {f: 2, c: 54588}, 54592, 54596, {f: 2, c: 54604}, 54607, 54609,
- {f: 2, c: 54616}, 54620, 54624, 54629, {f: 2, c: 54632}, 54635, 54637,
- {f: 2, c: 54644}, 54648, 54652, {f: 2, c: 54660}, {f: 3, c: 54663}, 54672,
- 54693, {f: 2, c: 54728}, 54732, 54736, 54738, {f: 2, c: 54744}, 54747,
- 54749, {f: 2, c: 54756}, 54760, 54764, {f: 2, c: 54772}, 54775, 54777,
- {f: 2, c: 54784}, 54788, 54792, {f: 2, c: 54800}, {f: 3, c: 54803}, 54812,
- 54816, 54820, 54829, {f: 2, c: 54840}, 54844, 54848, 54853,
- {f: 2, c: 54856}, 54859, 54861, 54865, {f: 2, c: 54868}, 54872, 54876,
- 54887, 54889, {f: 2, c: 54896}, 54900, 54915, 54917, {f: 2, c: 54924},
- 54928, 54932, 54941, 54943, 54945, 54952, 54956, 54960, 54969, 54971,
- {f: 2, c: 54980}, 54984, 54988, 54993, 54996, 54999, 55001, 55008, 55012,
- 55016, 55024, 55029, {f: 2, c: 55036}, 55040, 55044, 55057,
- {f: 2, c: 55064}, 55068, 55072, {f: 2, c: 55080}, 55083, 55085,
- {f: 2, c: 55092}, 55096, 55100, 55108, 55111, 55113, {f: 2, c: 55120},
- 55124, {f: 4, c: 55126}, {f: 2, c: 55136}, 55139, 55141, 55145, 55148,
- 55152, 55156, {f: 2, c: 55164}, 55169, {f: 2, c: 55176}, 55180, 55184,
- {f: 2, c: 55192}, 55195, 55197, 20285, 20339, 20551, 20729, 21152, 21487,
- 21621, 21733, 22025, 23233, 23478, 26247, {f: 2, c: 26550}, 26607, 27468,
- 29634, 30146, 31292, 33499, 33540, 34903, 34952, 35382, [36040, 63747],
- 36303, 36603, 36838, 39381, 21051, 21364, 21508, 24682, 24932, 27580,
- 29647, 33050, 35258, [12179, 35282], 38307, 20355, 21002, 22718, 22904,
- 23014, [12082, 24178], 24185, 25031, 25536, 26438, 26604, 26751, 28567,
- 30286, 30475, 30965, 31240, 31487, 31777, 32925, [12169, 33390], 33393,
- 35563, 38291, 20075, 21917, 26359, 28212, 30883, 31469, 33883, 35088,
- 34638, 38824, 21208, 22350, 22570, 23884, 24863, 25022, 25121, 25954,
- 26577, 27204, 28187, [12130, 29976], 30131, 30435, 30640, 32058, 37039,
- {f: 2, c: 37969}, 40853, 21283, 23724, 30002, 32987, 37440, 38296, 21083,
- 22536, 23004, 23713, 23831, 24247, 24378, 24394, 24951, 27743, 30074,
- 30086, 31968, 32115, 32177, 32652, 33108, 33313, 34193, 35137, 35611,
- 37628, [38477, 64009], 40007, 20171, 20215, 20491, 20977, 22607, 24887,
- 24894, 24936, 25913, 27114, 28433, 30117, 30342, 30422, 31623, 33445,
- 33995, 37799, 38283, 21888, 23458, 22353, 31923, 32697, 37301, 20520,
- 21435, 23621, 24040, 25298, 25454, 25818, 25831, 28192, 28844, 31067,
- 36317, 36382, 36989, 37445, 37624, 20094, 20214, 20581, [12081, 24062],
- 24314, 24838, 26967, 33137, 34388, 36423, 37749, 39467, 20062, 20625,
- 26480, 26688, 20745, 21133, 21138, 27298, 30652, 37392, 40660, 21163,
- 24623, 36850, 20552, 25001, 25581, 25802, 26684, 27268, 28608, 33160,
- 35233, 38548, 22533, 29309, [12125, 29356], 29956, 32121, 32365, 32937,
- [12178, 35211, 64010], 35700, 36963, 40273, 25225, 27770, 28500, 32080,
- 32570, 35363, 20860, 24906, 31645, 35609, 37463, 37772, 20140, 20435,
- 20510, 20670, 20742, 21185, 21197, 21375, 22384, 22659, 24218, 24465,
- 24950, 25004, 25806, 25964, 26223, 26299, [26356, 63745], 26775, 28039,
- 28805, 28913, 29855, 29861, 29898, 30169, 30828, 30956, 31455, 31478,
- 32069, 32147, 32789, 32831, 33051, 33686, 35686, 36629, 36885, 37857,
- 38915, 38968, 39514, 39912, 20418, 21843, 22586, [22865, 63753], 23395,
- 23622, 24760, 25106, 26690, 26800, 26856, 28330, 30028, 30328, 30926,
- 31293, 31995, 32363, 32380, 35336, 35489, 35903, 38542, 40388, 21476,
- 21481, 21578, 21617, 22266, 22993, 23396, 23611, 24235, 25335, 25911,
- 25925, 25970, 26272, 26543, 27073, 27837, 30204, 30352, 30590, 31295,
- 32660, 32771, 32929, 33167, 33510, 33533, 33776, 34241, 34865, 34996,
- 35493, 36764, 37678, 38599, 39015, [12220, 39640], [12238, 40723], 21741,
- 26011, 26354, 26767, 31296, [12181, 35895], 40288, 22256, 22372, 23825,
- 26118, 26801, 26829, 28414, 29736, 34974, 39908, 27752, [12219, 39592],
- 20379, 20844, 20849, 21151, 23380, [12079, 24037], 24656, 24685, 25329,
- 25511, 25915, 29657, 31354, 34467, 36002, 38799, [20018, 63749], 23521,
- [12093, 25096], 26524, [12128, 29916], 31185, 33747, 35463, 35506, 36328,
- 36942, 37707, 38982, [24275, 64011], 27112, 34303, 37101, 20896, 23448,
- 23532, 24931, 26874, 27454, 28748, 29743, 29912, 31649, 32592, 33733,
- 35264, 36011, 38364, 39208, 21038, 24669, 25324, 36866, 20362, 20809,
- 21281, 22745, 24291, 26336, 27960, 28826, 29378, 29654, 31568, 33009,
- 37979, 21350, 25499, 32619, 20054, 20608, 22602, 22750, 24618, 24871,
- 25296, 27088, 39745, 23439, 32024, 32945, 36703, 20132, 20689, 21676,
- 21932, 23308, 23968, 24039, 25898, 25934, 26657, 27211, 29409, 30350,
- 30703, 32094, 32761, 33184, 34126, 34527, 36611, 36686, 37066, 39171,
- 39509, 39851, 19992, 20037, 20061, 20167, 20465, 20855, 21246, 21312,
- [12061, 21475], [21477, 63750], 21646, 22036, 22389, 22434, 23495, 23943,
- 24272, 25084, 25304, 25937, 26552, 26601, 27083, 27472, 27590, 27628,
- 27714, 28317, 28792, 29399, 29590, 29699, 30655, 30697, 31350, 32127,
- 32777, [12165, 33276], 33285, 33290, 33503, 34914, 35635, 36092, 36544,
- 36881, 37041, 37476, 37558, 39378, 39493, 40169, 40407,
- [12244, 40860, 63751, 63752], 22283, 23616, 33738, 38816, 38827, 40628,
- 21531, 31384, 32676, 35033, 36557, 37089, 22528, 23624, 25496, 31391,
- 23470, [12088, 24339], 31353, 31406, 33422, 36524, 20518, 21048, 21240,
- 21367, 22280, 25331, 25458, 27402, 28099, 30519, 21413, 29527, 34152,
- 36470, 38357, 26426, 27331, 28528, 35437, 36556, 39243, 26231, 27512,
- 36020, [12225, 39740], 21483, 22317, 22862, 25542, 27131, 29674, 30789,
- 31418, 31429, 31998, 33909, 35215, 36211, 36917, 38312, 21243, 22343,
- 30023, 31584, 33740, 37406, 27224, 20811, 21067, 21127, 25119, 26840,
- 26997, 38553, 20677, 21156, 21220, 25027, [12100, 26020], 26681, 27135,
- 29822, 31563, 33465, 33771, 35250, 35641, 36817, 39241, 20170, 22935,
- 25810, 26129, 27278, 29748, 31105, 31165, 33449, {f: 2, c: 34942}, 35167,
- 37670, 20235, 21450, 24613, 25201, 27762, 32026, 32102, 20120, 20834,
- 30684, 32943, 20225, 20238, 20854, 20864, 21980, 22120, 22331, 22522,
- 22524, 22804, 22855, 22931, 23492, 23696, 23822, [12080, 24049], 24190,
- 24524, 25216, 26071, 26083, {f: 2, c: 26398}, 26462, 26827, 26820, 27231,
- 27450, 27683, 27773, 27778, 28103, 29592, 29734, 29738, 29826, 29859,
- 30072, 30079, 30849, 30959, 31041, {f: 2, c: 31047}, 31098, 31637, 32000,
- 32186, 32648, 32774, 32813, 32908, 35352, 35663, [35912, 63744], 36215,
- 37665, 37668, 39138, 39249, {f: 2, c: 39438}, 39525, 40594, 32202, 20342,
- 21513, 25326, 26708, [12198, 37329, 63754], 21931, 20794, 23068, 25062,
- [25295, 63835], 25343, 37027, [35582, 63837], 26262, 29014, 38627, 25423,
- 25466, 21335, 26511, 26976, 28275, 30007, 32013, 34930, 22218, 23064,
- 20035, 20839, [22856, 63756], 26608, 32784, [12069, 22899, 63873],
- [24180, 63886], [25754, 63889], [31178, 63893], [24565, 63907], 24684,
- 25288, [25467, 63908], [23527, 63839, 63914], 23511, 21162, 22900, 24361,
- [24594, 63840], 29785, 39377, 28611, 33215, 36786, 24817, 33126,
- [23615, 63933], 23273, 35365, [26491, 63944], [32016, 63951], 33021, 23612,
- [27877, 63971], [21311, 63979], [28346, 63980], 22810, [33590, 63998],
- [20025, 63838], 20150, 20294, 21934, 22296, 22727, 24406, 26039, 26086,
- 27264, 27573, 28237, 30701, 31471, 31774, 32222, 34507, 34962, 37170,
- 37723, 25787, 28606, 29562, 30136, 36948, 21846, 22349, 25018, 25812,
- 26311, 28129, 28251, 28525, 28601, 30192, 32835, 33213, 34113, 35203,
- 35527, 35674, 37663, 27795, 30035, 31572, 36367, 36957, 21776, 22530,
- 22616, 24162, 25095, 25758, 26848, 30070, [31958, 64003], 34739, 40680,
- 20195, 22408, 22382, [12068, 22823], 23565, 23729, 24118, 24453, 25140,
- 25825, 29619, 33274, 34955, 36024, 38538, 40667, [23429, 64004], 24503,
- 24755, 20498, [12049, 20992], 21040, 22294, 22581, 22615, 23566, 23648,
- 23798, 23947, [24230, 64001], 24466, 24764, 25361, 25481, 25623, 26691,
- 26873, 27330, 28120, 28193, 28372, 28644, 29182, 30428, 30585, 31153,
- 31291, 33796, 35241, 36077, 36339, 36424, 36867, 36884, 36947, 37117,
- 37709, 38518, 38876, 27602, 28678, 29272, 29346, 29544, 30563, 31167,
- 31716, 32411, [35712, 63834], 22697, 24775, 25958, 26109, 26302, 27788,
- 28958, 29129, 35930, 38931, 20077, 31361, 20189, 20908, 20941, 21205,
- 21516, 24999, 26481, 26704, 26847, [27934, 64005], 28540, 30140, 30643,
- 31461, 33012, 33891, 37509, 20828, [12099, 26007], 26460, 26515, 30168,
- 31431, 33651, [12182, 35910], 36887, 38957, 23663, 33216, 33434, 36929,
- 36975, 37389, 24471, 23965, 27225, 29128, 30331, 31561, 34276, 35588,
- 37159, 39472, [21895, 63755], [25078, 63757], [30313, 63758],
- [32645, 63759], [34367, 63760], [34746, 63761], [35064, 63762],
- [37007, 63763], [27931, 63765], [28889, 63766], [29662, 63767], 32097,
- [33853, 63768], [37226, 63769], [39409, 63770], [20098, 63771],
- [21365, 63772], [27396, 63773], 27410, 28734, [29211, 63774],
- [34349, 63775], [40478, 63776], 21068, 36771, [23888, 63777], 25829, 25900,
- 27414, [28651, 63778], 31811, 32412, [34253, 63779], [35172, 63780], 35261,
- [25289, 63781], [33240, 63782], [34847, 63783], [24266, 63784],
- [26391, 63785], [28010, 63786], [29436, 63787], 29701, 29807, 34690,
- [37086, 63788], [20358, 63789], 23821, 24480, 33802, [20919, 63790],
- [25504, 63861], [30053, 63862], [20142, 63863], 20486, [20841, 63864],
- [20937, 63865], [26753, 63866], 27153, 31918, 31921, [31975, 63867],
- [33391, 63868], [35538, 63869], 36635, [37327, 63870], 20406, 20791,
- [21237, 63871], [21570, 63872], [24300, 63874], 24942, 25150,
- [26053, 63875], 27354, [28670, 63876], [31018, 63877], 34268, 34851,
- [38317, 63878], 39522, [39530, 63879], [40599, 63880], [40654, 63881],
- [12050, 21147, 63882], [26310, 63883], [27511, 63884], 28701, 31019,
- [36706, 63885], 38722, [24976, 63887], [25088, 63888], 25891,
- [28451, 63890], [29001, 63891], [29833, 63892], [32244, 63894],
- [32879, 63895], [34030, 63897], [36646, 63896], [36899, 63898],
- [37706, 63899], 20925, [21015, 63900], [21155, 63901], 27916,
- [28872, 63903], [35010, 63904], [24265, 63906], 25986, [27566, 63909],
- 28610, [31806, 63910], [29557, 63911], [20196, 63912], 20278,
- [22265, 63913], 23738, [23994, 63915], [24604, 63916], [29618, 63917],
- 31533, [32666, 63919], 32718, [32838, 63920], 36894, [37428, 63921],
- [38646, 63922], [38728, 63923], [38936, 63924], 40801, [20363, 63925],
- 28583, [31150, 63926], [37300, 63927], [38583, 63928], [21214, 63791],
- 25736, [25796, 63792], [27347, 63793], 28510, 28696, [29200, 63794],
- [30439, 63795], [12156, 32769, 63796], [34310, 63797], [34396, 63798],
- [36335, 63799], 36613, [38706, 63800], [39791, 63801], [40442, 63802],
- [12228, 40565], [30860, 63803], [31103, 63804], [32160, 63805],
- [33737, 63806], [37636, 63807], [12229, 40575, 63808], 40595,
- [35542, 63809], [22751, 63810], [24324, 63811], 26407, 28711, 29903,
- [31840, 63812], [32894, 63813], 20769, 28712, [29282, 63814],
- [30922, 63815], [36034, 63816], 36058, 36084, [38647, 63817],
- [20102, 63930], [20698, 63931], [23534, 63932], 24278, [26009, 63934],
- [29134, 63936], [30274, 63937], 30637, 32842, [34044, 63938],
- [36988, 63939], 39719, [12243, 40845, 63940], [22744, 63818], 23105,
- [23650, 63819], [27155, 63820], [28122, 63821], [28431, 63822], 30267,
- [32047, 63823], [32311, 63824], 34078, 35128, 37860, [38475, 63825],
- [21129, 63943], 26066, [26611, 63945], 27060, [27969, 63946],
- [28316, 63947], 28687, [29705, 63948], 29792, [30041, 63949], 30244,
- [30827, 63950], 35628, [39006, 63952], [20845, 63953], [25134, 63954],
- [38520, 63955], 20374, [20523, 63956], [23833, 63957], [28138, 63958],
- 32184, [36650, 63959], [24459, 63960], [24900, 63961], [26647, 63962],
- [38534, 63964], [21202, 63826], [32907, 63827], [20956, 63828],
- [20940, 63829], 26974, [31260, 63830], [32190, 63831], [33777, 63832],
- [38517, 63833], 20442, [21033, 63965], 21400, [21519, 63966], 21774,
- [23653, 63967], 24743, [26446, 63969], [26792, 63970], 28012, 29313, 29432,
- [29702, 63972], 29827, [30178, 63973], 31852, [32633, 63974], 32696, 33673,
- [35023, 63975], [35041, 63976], [12197, 37324, 63977], 37328,
- [38626, 63978], 39881, [21533, 63981], 28542, [29136, 63982],
- [29848, 63983], [34298, 63984], 36522, [38563, 63985], [40023, 63986],
- [40607, 63987], [26519, 63988], [28107, 63989], 29747, [33256, 63990],
- 38678, 30764, [12148, 31435, 63991], [31520, 63992], [31890, 63993], 25705,
- 29802, 30194, 30908, 30952, [12218, 39340], 39764, [12231, 40635], 23518,
- 24149, 28448, 33180, 33707, 37000, 19975, 21325, 23081, 24018, 24398,
- 24930, 25405, 26217, 26364, 28415, 28459, 28771, 30622, 33836, 34067,
- 34875, 36627, 39237, 39995, 21788, 25273, 26411, 27819, 33545, 35178,
- 38778, 20129, 22916, {f: 2, c: 24536}, 26395, 32178, 32596, 33426, 33579,
- 33725, 36638, 37017, 22475, 22969, 23186, 23504, 26151, 26522, 26757,
- 27599, 29028, 32629, 36023, 36067, 36993, 39749, 33032, 35978, 38476,
- 39488, [12230, 40613], 23391, 27667, 29467, 30450, 30431, 33804, 20906,
- 35219, 20813, 20885, 21193, 26825, 27796, 30468, 30496, 32191, 32236,
- [12207, 38754], 40629, 28357, 34065, 20901, 21517, 21629, 26126, 26269,
- 26919, 28319, [12139, 30399], 30609, 33559, 33986, 34719, 37225, 37528,
- 40180, 34946, 20398, 20882, 21215, 22982, 24125, 24917, {f: 2, c: 25720},
- 26286, 26576, 27169, 27597, [12113, 27611], 29279, 29281, 29761, 30520,
- [12141, 30683], 32791, 33468, 33541, 35584, 35624, 35980, [12106, 26408],
- 27792, 29287, [12140, 30446], 30566, 31302, 40361, 27519, 27794, 22818,
- 26406, 33945, 21359, 22675, 22937, 24287, 25551, 26164, 26483, 28218,
- 29483, 31447, 33495, 37672, 21209, 24043, 25006, 25035, 25098, 25287,
- 25771, [12102, 26080], 26969, 27494, [12111, 27595], 28961, 29687, 30045,
- 32326, 33310, 33538, 34154, 35491, 36031, 38695, 40289, 22696, 40664,
- 20497, 21006, 21563, 21839, [12098, 25991], 27766, {f: 2, c: 32010}, 32862,
- 34442, [12200, 38272], 38639, 21247, 27797, 29289, 21619, 23194, 23614,
- 23883, 24396, 24494, 26410, 26806, 26979, 28220, 28228, 30473,
- [12150, 31859], 32654, 34183, 35598, 36855, 38753, 40692, 23735, 24758,
- 24845, 25003, 25935, {f: 2, c: 26107}, 27665, 27887, 29599, 29641, 32225,
- 38292, 23494, 34588, 35600, 21085, 21338, 25293, 25615, 25778, 26420,
- 27192, 27850, 29632, 29854, 31636, 31893, 32283, 33162, 33334, 34180,
- 36843, 38649, 39361, 20276, 21322, 21453, 21467, 25292, 25644, 25856,
- 26001, 27075, 27886, 28504, 29677, 30036, 30242, 30436, 30460, 30928,
- [30971, 63844], 31020, 32070, 33324, 34784, 36820, 38930, 39151, 21187,
- 25300, 25765, 28196, 28497, 30332, 36299, 37297, 37474, 39662, 39747,
- 20515, 20621, 22346, 22952, 23592, 24135, 24439, 25151, 25918,
- [12101, 26041], 26049, 26121, 26507, 27036, 28354, 30917, 32033, 32938,
- 33152, 33323, 33459, 33953, 34444, 35370, 35607, 37030, 38450, 40848,
- 20493, 20467, 22521, 24472, 25308, 25490, 26479, 28227, 28953, 30403,
- 32972, 32986, {f: 2, c: 35060}, 35097, 36064, 36649, 37197, 38506, 20271,
- 20336, 24091, 26575, 26658, [12137, 30333], 30334, 39748, 24161, 27146,
- 29033, 29140, 30058, 32321, 34115, 34281, 39132, 20240, 31567, 32624,
- 38309, 20961, 24070, 26805, 27710, 27726, 27867, 29359, 31684, 33539,
- 27861, 29754, 20731, 21128, 22721, 25816, 27287, 29863, 30294, 30887,
- 34327, 38370, 38713, 21342, 24321, 35722, 36776, 36783, 37002, 21029,
- 30629, 40009, 40712, 19993, 20482, 20853, 23643, 24183, 26142, 26170,
- 26564, 26821, 28851, 29953, 30149, 31177, 31453, 36647, 39200, 39432,
- 20445, 22561, 22577, 23542, 26222, 27493, 27921, 28282, 28541, 29668,
- 29995, 33769, 35036, 35091, 35676, 36628, 20239, 20693, 21264,
- [12056, 21340], 23443, [24489, 63846], 26381, 31119, 33145, 33583, 34068,
- 35079, 35206, 36665, [36667, 64007], 39333, 39954, 26412, 20086, 20472,
- 22857, 23553, {f: 2, c: 23791}, 25447, 26834, 28925, 29090, 29739, 32299,
- 34028, 34562, 36898, 37586, 40179, [19981, 63847], 20184, 20463, 20613,
- 21078, 21103, 21542, 21648, 22496, 22827, 23142, 23386, 23413, 23500,
- 24220, 25206, 25975, 26023, 28014, 28325, [12119, 29238], 31526, 31807,
- [12152, 32566], {f: 2, c: 33104}, 33178, 33344, 33433, 33705, 35331, 36000,
- 36070, 36091, 36212, 36282, 37096, 37340, [12201, 38428], 38468, 39385,
- 40167, [21271, 63843], 20998, 21545, 22132, 22707, 22868, 22894, 24575,
- 24996, 25198, 26128, 27774, 28954, 30406, 31881, 31966, 32027, 33452,
- 36033, 38640, 20315, 24343, 24447, 25282, 23849, 26379, 26842, 30844,
- 32323, 40300, 19989, 20633, [12052, 21269], 21290, 21329, 22915, 23138,
- 24199, 24754, 24970, 25161, 25209, 26000, 26503, 27047, [12112, 27604],
- {f: 3, c: 27606}, 27832, 29749, 30202, 30738, 30865, 31189, 31192, 31875,
- 32203, 32737, 32933, 33086, 33218, 33778, 34586, 35048, 35513, 35692,
- 36027, 37145, [12206, 38750], [12214, 39131], [12240, 40763], 22188, 23338,
- 24428, 25996, 27315, 27567, 27996, 28657, 28693, 29277, 29613, 36007,
- 36051, 38971, 24977, 27703, 32856, 39425, 20045, 20107, 20123, 20181,
- 20282, 20284, 20351, 20447, 20735, 21490, 21496, 21766, 21987, 22235,
- [12064, 22763], 22882, 23057, 23531, 23546, 23556, 24051, 24107, 24473,
- 24605, 25448, 26012, 26031, 26614, 26619, 26797, 27515, 27801, 27863,
- 28195, 28681, 29509, 30722, 31038, 31040, 31072, 31169, 31721, 32023,
- 32114, 32902, 33293, 33678, 34001, 34503, 35039, 35408, 35422, 35613,
- 36060, 36198, 36781, 37034, 39164, 39391, 40605, 21066, 26388, 20632,
- 21034, [12077, 23665], 25955, 27733, 29642, 29987, 30109, 31639, 33948,
- 37240, 38704, 20087, 25746, [27578, 63856], 29022, 34217, 19977, 26441,
- 26862, 28183, 33439, 34072, 34923, 25591, 28545, 37394, 39087, 19978,
- 20663, 20687, 20767, 21830, 21930, 22039, 23360, 23577, 23776, 24120,
- 24202, 24224, 24258, 24819, 26705, 27233, 28248, 29245, 29248,
- [29376, 63994], 30456, 31077, 31665, 32724, 35059, 35316, 35443, 35937,
- 36062, 38684, [22622, 63852], 29885, 36093, 21959, 31329, [32034, 63850],
- [12170, 33394], 29298, [12131, 29983], 29989, 31513, 22661, 22779, 23996,
- 24207, 24246, 24464, 24661, 25234, 25471, 25933, 26257, 26329, 26360,
- 26646, 26866, 29312, 29790, 31598, 32110, 32214, 32626, 32997, 33298,
- 34223, 35199, 35475, 36893, 37604, [12233, 40653], [12239, 40736],
- [12067, 22805], 22893, 24109, 24796, 26132, 26227, 26512, 27728, 28101,
- 28511, [12143, 30707], 30889, 33990, 37323, 37675, 20185, 20682, 20808,
- 21892, 23307, 23459, 25159, 25982, 26059, 28210, 29053, 29697, 29764,
- 29831, 29887, 30316, 31146, 32218, 32341, 32680, 33146, 33203, 33337,
- 34330, 34796, 35445, 36323, 36984, 37521, 37925, 39245, 39854, 21352,
- 23633, 26964, 27844, 27945, 28203, [12166, 33292], 34203, 35131, 35373,
- [35498, 63855, 63905], 38634, 40807, 21089, 26297, 27570, 32406, 34814,
- 36109, 38275, 38493, 25885, 28041, 29166, 22478, 22995, 23468, 24615,
- 24826, 25104, 26143, 26207, 29481, 29689, 30427, [30465, 63853], 31596,
- 32854, 32882, 33125, 35488, 37266, 19990, 21218, 27506, 27927, 31237,
- 31545, 32048, 36016, 21484, 22063, 22609, 23477, [12073, 23567], 23569,
- 24034, 25152, 25475, 25620, 26157, 26803, 27836, 28040, 28335, 28703,
- 28836, 29138, 29990, 30095, 30094, 30233, 31505, 31712, 31787, 32032,
- 32057, 34092, 34157, 34311, 35380, 36877, 36961, 37045, 37559, 38902,
- 39479, 20439, 23660, 26463, 28049, 31903, 32396, 35606, 36118, 36895,
- 23403, 24061, 25613, 33984, 36956, 39137, [29575, 63841, 63963], 23435,
- 24730, 26494, 28126, 35359, 35494, 36865, 38924, 21047, 28753, 30862,
- 37782, 34928, 37335, 20462, 21463, 22013, 22234, 22402, 22781, 23234,
- 23432, 23723, 23744, 24101, 24833, 25101, [12095, 25163], 25480, 25628,
- 25910, [25976, 63849], 27193, 27530, [12116, 27700], 27929, 28465, 29159,
- 29417, 29560, 29703, 29874, 30246, 30561, 31168, 31319, 31466, 31929,
- 32143, 32172, 32353, 32670, 33065, 33585, 33936, 34010, 34282, 34966,
- 35504, 35728, 36664, 36930, 36995, 37228, 37526, 37561, 38539,
- {f: 2, c: 38567}, 38614, 38656, 38920, [12216, 39318], 39635, 39706, 21460,
- 22654, 22809, 23408, 23487, 28113, 28506, 29087, 29729, 29881, 32901,
- 33789, 24033, 24455, 24490, 24642, 26092, 26642, 26991, 27219, 27529,
- 27957, 28147, 29667, 30462, 30636, 31565, 32020, 33059, 33308, 33600,
- 34036, 34147, 35426, 35524, 37255, 37662, 38918, 39348, 25100, 34899,
- 36848, 37477, 23815, 23847, 23913, 29791, 33181, 34664, 28629,
- [25342, 63859], 32722, 35126, 35186, 19998, 20056, 20711, 21213, 21319,
- 25215, 26119, 32361, 34821, 38494, 20365, 21273, 22070, 22987, 23204,
- [12075, 23608], 23630, 23629, 24066, 24337, 24643, 26045, 26159, 26178,
- 26558, 26612, 29468, [12142, 30690], [12144, 31034], 32709, 33940, 33997,
- 35222, 35430, 35433, 35553, [12183, 35925], 35962, 22516, 23508, 24335,
- 24687, 25325, 26893, 27542, 28252, 29060, 31698, 34645, [35672, 63996],
- 36606, [12215, 39135], 39166, 20280, 20353, 20449, 21627, 23072, 23480,
- 24892, 26032, 26216, 29180, 30003, 31070, 32051, 33102, [12162, 33251],
- 33688, 34218, 34254, 34563, 35338, [12189, 36523], [12191, 36763], 36805,
- 22833, 23460, 23526, 24713, 23529, 23563, [12092, 24515], 27777, 28145,
- 28683, 29978, 33455, 35574, [20160, 63997], [12055, 21313], 38617,
- [12114, 27663], 20126, 20420, 20818, 21854, 23077, 23784, 25105,
- [12123, 29273], 33469, 33706, 34558, 34905, 35357, 38463, 38597, 39187,
- 40201, 40285, 22538, 23731, 23997, 24132, [24801, 63929], 24853, 25569,
- [27138, 63764, 63836, 63935], 28197, 37122, 37716, 38990, 39952, 40823,
- 23433, 23736, 25353, 26191, 26696, 30524, 38593, 38797, 38996, 39839,
- 26017, 35585, 36555, 38332, 21813, 23721, 24022, 24245, 26263, 30284,
- 33780, 38343, 22739, 25276, 29390, 40232, 20208, 22830, 24591, 26171,
- 27523, 31207, 40230, 21395, 21696, 22467, 23830, 24859, 26326, 28079,
- 30861, 33406, 38552, 38724, 21380, 25212, 25494, 28082, 32266, 33099,
- 38989, 27387, 32588, 40367, 40474, 20063, 20539, 20918, 22812, 24825,
- 25590, 26928, 29242, 32822, 37326, 24369, 32004, [33509, 63860], 33903,
- 33979, 34277, 36493, 20335, 22756, 23363, 24665, 25562, 25880, 25965,
- 26264, 26954, 27171, 27915, 28673, 29036, 30162, 30221, 31155, 31344,
- [12154, 32650], 35140, 35731, 37312, 38525, 39178, 22276, 24481, 26044,
- 28417, 30208, 31142, 35486, 39341, [12226, 39770], 40812, 20740, 25014,
- 25233, 27277, 33222, 20547, 22576, 24422, 28937, [12180, 35328], 35578,
- 23420, 34326, 20474, 20796, 22196, 22852, 25513, 28153, 23978, 26989,
- 20870, 20104, 20313, 22914, 27487, 27741, 29877, 30998, 33287, 33349,
- 33593, 36671, 36701, 39192, 20134, 22495, 24441, [26131, 63968], 30123,
- 32377, 35695, 36870, 39515, 22181, 22567, 23032, 23071, 23476, 24310,
- 25424, 25403, 26941, 27783, 27839, 28046, 28051, 28149, 28436, 28895,
- 28982, 29017, 29123, 29141, 30799, 30831, 31605, 32227, 32303, 34893,
- 36575, 37467, 40182, 24709, 28037, 29105, 38321, 21421, 26579, 28814,
- 28976, 29744, 33398, 33490, 38331, 39653, 40573, 26308, 29121,
- [33865, 63854], 22603, 23992, 24433, 26144, 26254, 27001, 27054, 27704,
- 27891, 28214, 28481, 28634, 28699, 28719, 29008, 29151, 29552, 29787,
- 29908, 30408, 31310, 32403, 33521, 35424, 36814, 37704, 38681, 20034,
- 20522, 21000, 21473, 26355, 27757, 28618, 29450, 30591, 31330, 33454,
- 34269, 34306, 35028, 35427, 35709, 35947, 37555, 38675, 38928, 20116,
- 20237, 20425, 20658, 21320, 21566, 21555, 21978, 22626, 22714, 22887,
- 23067, 23524, 24735, 25034, 25942, 26111, 26212, 26791, 27738, 28595,
- 28879, 29100, 29522, 31613, 34568, 35492, 39986, 40711, 23627, 27779,
- 29508, [12127, 29577], 37434, 28331, 29797, 30239, 31337, 32277, 34314,
- 20800, 22725, 25793, 29934, 29973, 30320, 32705, 37013, 38605, 39252,
- 28198, [12129, 29926], {f: 2, c: 31401}, 33253, 34521, 34680, 35355, 23113,
- 23436, 23451, 26785, 26880, 28003, 29609, 29715, 29740, 30871, 32233,
- 32747, 33048, 33109, 33694, 35916, [38446, 63942], 38929, [12104, 26352],
- 24448, 26106, 26505, 27754, 29579, 20525, 23043, 27498, 30702, 22806,
- 23916, 24013, 29477, 30031, 20709, 20985, 22575, 22829, 22934, 23002,
- 23525, 23970, 25303, 25622, 25747, 25854, 26332, 27208, 29183, 29796,
- 31368, 31407, 32327, 32350, 32768, 33136, 34799, 35201, 35616, 36953,
- 36992, 39250, 24958, 27442, 28020, 32287, 35109, 36785, 20433, 20653,
- 20887, 21191, 22471, 22665, 23481, 24248, 24898, 27029, 28044, 28263,
- 28342, 29076, 29794, [12132, 29992], 29996, 32883, 33592, 33993, 36362,
- 37780, 37854, 20110, 20305, 20598, 20778, [12060, 21448], 21451, 21491,
- 23431, 23507, 23588, 24858, 24962, 26100, [12124, 29275], 29591, 29760,
- 30402, 31056, 31121, 31161, 32006, [12155, 32701], 33419, 34261, 34398,
- 36802, 36935, 37109, 37354, 38533, [12204, 38632], 38633, 21206, 24423,
- 26093, 26161, 26671, 29020, 31286, 37057, 38922, 20113, 27218, 27550,
- 28560, 29065, 32792, 33464, 34131, 36939, 38549, 38642, 38907, 34074,
- 39729, 20112, 29066, 38596, 20803, 21407, 21729, 22291, 22290, 22435,
- 23195, 23236, 23491, 24616, 24895, 25588, 27781, 27961, 28274, 28304,
- 29232, 29503, 29783, 33489, 34945, 36677, 36960, 38498, 39000, 40219,
- [12105, 26376], 36234, 37470, 20301, 20553, 20702, 21361, 22285, 22996,
- 23041, 23561, 24944, 26256, 28205, 29234, 29771, 32239, 32963, 33806,
- 33894, 34111, 34655, 34907, 35096, 35586, 36949, [12209, 38859], 39759,
- 20083, 20369, 20754, 20842, 21807, 21929, 23418, 23461, {f: 2, c: 24188},
- 24254, 24736, 24799, {f: 2, c: 24840}, 25540, 25912, 26377, 26580, 26586,
- {f: 2, c: 26977}, 27833, 27943, 28216, 28641, {f: 2, c: 29494}, 29788,
- 30001, 30290, 32173, 33278, 33848, 35029, 35480, 35547, 35565, 36400,
- 36418, 36938, 36926, 36986, [12195, 37193], 37321, 37742, 22537, 27603,
- [12161, 32905], 32946, 20801, 22891, 23609, 28516, 29607, 32996, 36103,
- 37399, 38287, [12160, 32895], 25102, 28700, 32104, 34701, 22432, 24681,
- 24903, 27575, 35518, 37504, 38577, [12036, 20057], 21535, 28139, 34093,
- 38512, [12211, 38899], 39150, 25558, 27875, [12194, 37009], 20957, 25033,
- 33210, 40441, 20381, 20506, 20736, 23452, 24847, 25087, 25836, 26885,
- 27589, 30097, 30691, 32681, 33380, 34191, 34811, [12176, 34915], 35516,
- 35696, 37291, [12038, 20108], 20197, 20234, 22839, 23016, 24050, 24347,
- 24411, 24609, 29246, 29669, [30064, 63842], 30157, 31227, [12157, 32780],
- [12159, 32819], 32900, 33505, 33617, 36029, 36019, 36999, 39156, 39180,
- 28727, 30410, 32714, 32716, 32764, 35610, [12040, 20154], 20161, 20995,
- 21360, [21693, 63902], 22240, 23035, 23493, 24341, 24525, 28270, 32106,
- 33589, 34451, 35469, 38765, 38775, [12032, 19968], 20314, 20350, 22777,
- [12103, 26085], 28322, 36920, 37808, 39353, 20219, 22764, 22922, 23001,
- 24641, 31252, 33615, 36035, [12042, 20837], 21316, 20173, 21097, 23381,
- 33471, 20180, [21050, 63999], 21672, 22985, 23039, [12070, 23376], 23383,
- 23388, 24675, 24904, 28363, [28825, 63995], 29038, 29574, 29943, 30133,
- 30913, 32043, 32773, [12163, 33258], 33576, 34071, 34249, 35566, 36039,
- 38604, 20316, 21242, 22204, 26027, 26152, 28796, 28856, 29237, 32189,
- 33421, 37196, 38592, 40306, 23409, 26855, 27544, 28538, 30430, 23697,
- 26283, 28507, 31668, 31786, 34870, 38620, 19976, 20183, 21280, 22580,
- 22715, 22767, 22892, 23559, 24115, 24196, 24373, 25484, 26290, 26454,
- 27167, 27299, 27404, 28479, 29254, 29520, 29835, 31456, 31911, 33144,
- 33247, 33255, 33674, 33900, 34083, 34196, 34255, 35037, 36115, 37292,
- [12199, 38263], 38556, 20877, 21705, 22312, 23472, 25165, 26448, 26685,
- 26771, 28221, 28371, 28797, 32289, 35009, 36001, 36617, 40779, 40782,
- 29229, 31631, 35533, 37658, 20295, 20302, 20786, 21632, 22992, 24213,
- 25269, 26485, 26990, 27159, 27822, 28186, 29401, 29482, 30141, 31672,
- 32053, 33511, 33785, 33879, 34295, 35419, 36015, 36487, 36889, 37048,
- 38606, 40799, 21219, 21514, 23265, 23490, 25688, 25973, 28404, 29380,
- 30340, 31309, 31515, 31821, 32318, 32735, 33659, 35627, 36042,
- [12186, 36196], 36321, 36447, 36842, 36857, 36969, 37841, 20291, 20346,
- 20659, 20840, 20856, 21069, 21098, 22625, 22652, 22880, 23560, 23637,
- 24283, 24731, 25136, 26643, 27583, 27656, 28593, 29006, 29728,
- [12133, 30000], 30008, 30033, 30322, 31564, 31627, 31661, 31686, 32399,
- 35438, 36670, 36681, 37439, 37523, 37666, 37931, 38651, 39002, 39019,
- 39198, [20999, 64000], 25130, 25240, 27993, 30308, 31434, 31680, 32118,
- 21344, 23742, 24215, 28472, 28857, 31896, 38673, 39822, 40670, 25509,
- 25722, 34678, 19969, 20117, 20141, 20572, 20597, 21576, 22979, 23450,
- 24128, 24237, 24311, 24449, 24773, 25402, 25919, 25972, 26060, 26230,
- 26232, 26622, 26984, 27273, 27491, 27712, 28096, 28136, 28191, 28254,
- 28702, 28833, 29582, 29693, 30010, 30555, 30855, 31118, 31243, 31357,
- 31934, 32142, 33351, 35330, 35562, 35998, 37165, 37194, 37336, 37478,
- 37580, 37664, 38662, 38742, 38748, 38914, [12237, 40718], 21046, 21137,
- 21884, 22564, 24093, 24351, 24716, 25552, 26799, 28639, 31085, 31532,
- 33229, 34234, 35069, 35576, 36420, 37261, 38500, 38555, 38717, 38988,
- [12241, 40778], 20430, 20806, 20939, 21161, 22066, 24340, 24427, 25514,
- 25805, 26089, 26177, 26362, 26361, 26397, 26781, 26839, 27133, 28437,
- 28526, 29031, 29157, [12118, 29226], 29866, 30522, 31062, 31066, 31199,
- 31264, 31381, 31895, 31967, 32068, 32368, 32903, 34299, 34468, 35412,
- 35519, 36249, 36481, 36896, 36973, 37347, 38459, 38613, [12227, 40165],
- 26063, 31751, [12188, 36275], 37827, 23384, 23562, 21330, 25305, 29469,
- 20519, 23447, 24478, 24752, 24939, 26837, 28121, 29742, 31278, 32066,
- 32156, 32305, 33131, 36394, 36405, 37758, 37912, 20304, 22352, 24038,
- 24231, 25387, 32618, 20027, 20303, 20367, 20570, 23005, 32964, 21610,
- 21608, 22014, 22863, 23449, 24030, 24282, 26205, 26417, 26609, 26666,
- 27880, 27954, 28234, 28557, 28855, 29664, 30087, 31820, 32002, 32044,
- 32162, [12168, 33311], 34523, 35387, 35461, [12187, 36208], 36490, 36659,
- 36913, 37198, 37202, 37956, 39376, [12149, 31481], 31909, 20426, 20737,
- 20934, 22472, 23535, 23803, 26201, 27197, 27994, 28310, 28652, 28940,
- 30063, 31459, 34850, 36897, 36981, 38603, 39423, 33537, 20013, 20210,
- 34886, 37325, 21373, 27355, 26987, 27713, 33914, 22686, 24974, 26366,
- 25327, 28893, 29969, 30151, 32338, 33976, 35657, 36104, 20043, 21482,
- 21675, 22320, 22336, 24535, 25345, 25351, 25711, [12096, 25903], 26088,
- 26234, 26525, 26547, [12108, 27490], 27744, 27802, 28460, 30693, 30757,
- 31049, 31063, 32025, 32930, 33026, [12164, 33267], 33437, 33463, 34584,
- 35468, 36100, 36286, 36978, 30452, 31257, 31287, 32340, 32887, 21767,
- 21972, 22645, 25391, 25634, 26185, 26187, 26733, 27035, 27524, 27941,
- 28337, 29645, 29800, 29857, 30043, 30137, 30433, 30494, 30603, 31206,
- 32265, 32285, 33275, 34095, 34967, 35386, 36049, 36587,
- [12192, 36784, 63857], 36914, 37805, 38499, 38515, 38663, 20356, 21489,
- 23018, 23241, 24089, 26702, 29894, 30142, 31209, 31378, 33187, 34541,
- 36074, 36300, 36845, 26015, 26389, 22519, 28503, 32221, 36655, 37878,
- 38598, 24501, 25074, 28548, 19988, 20376, 20511, 21449, 21983, 23919,
- 24046, 27425, 27492, 30923, 31642, 36425, [12190, 36554, 63746], 36974,
- 25417, 25662, 30528, 31364, 37679, 38015, 40810, 25776, 28591, 29158,
- 29864, 29914, 31428, 31762, 32386, 31922, 32408, 35738, 36106, 38013,
- 39184, 39244, 21049, 23519, 25830, 26413, 32046, 20717, [21443, 63851],
- 22649, {f: 2, c: 24920}, 25082, 26028, 31449, 35730, 35734, 20489, 20513,
- 21109, 21809, 23100, 24288, 24432, 24884, 25950, 26124, 26166, 26274,
- 27085, 28356, 28466, 29462, 30241, 31379, 33081, 33369, 33750, 33980,
- 20661, 22512, 23488, 23528, 24425, 25505, 30758, 32181, 33756, 34081,
- 37319, 37365, 20874, 26613, 31574, 36012, 20932, 22971, 24765, 34389,
- 20508, 21076, 23610, 24957, 25114, [25299, 64002], 25842, 26021, 28364,
- 30240, 33034, 36448, 38495, 38587, 20191, 21315, 21912, 22825, 24029,
- 25797, 27849, 28154, 29588, 31359, [12167, 33307], 34214, 36068, 36368,
- 36983, 37351, 38369, 38433, 38854, 20984, 21746, 21894, 24505, 25764,
- 28552, 32180, 36639, 36685, 37941, 20681, 23574, 27838, 28155, 29979,
- 30651, 31805, 31844, 35449, 35522, 22558, 22974, 24086, 25463, 29266,
- 30090, 30571, 35548, 36028, 36626, 24307, 26228, 28152, 32893, 33729,
- 35531, [12205, 38737], 39894, 21059, 26367, 28053, 28399, 32224, 35558,
- 36910, 36958, 39636, 21021, 21119, 21736, 24980, 25220, 25307, 26786,
- 26898, 26970, 27189, 28818, 28966, 30813, 30977, 30990, 31186, 31245,
- 32918, [12171, 33400], 33493, 33609, 34121, 35970, 36229, 37218, 37259,
- 37294, 20419, 22225, 29165, 30679, 34560, 35320, [12072, 23544], 24534,
- 26449, 37032, 21474, 22618, 23541, 24740, 24961, 25696, 32317, 32880,
- 34085, 37507, 25774, 20652, 23828, 26368, 22684, 25277, 25512, 26894,
- 27000, 27166, 28267, 30394, 31179, 33467, 33833, 35535, 36264, 36861,
- 37138, 37195, 37276, 37648, 37656, 37786, 38619, 39478, 39949, 19985,
- 30044, 31069, 31482, 31569, 31689, 32302, 33988, 36441, 36468, 36600,
- 36880, 26149, 26943, 29763, 20986, 26414, 40668, 20805, 24544, 27798,
- 34802, 34909, 34935, 24756, 33205, 33795, 36101, 21462, 21561, 22068,
- 23094, 23601, 28810, 32736, 32858, 33030, 33261, 36259, 37257, 39519,
- 40434, 20596, 20164, 21408, 24827, 28204, 23652, 20360, 20516, 21988,
- 23769, 24159, 24677, 26772, 27835, 28100, 29118, 30164, 30196, 30305,
- 31258, 31305, 32199, 32251, 32622, 33268, 34473, 36636, 38601, 39347,
- [12242, 40786], 21063, 21189, 39149, 35242, 19971, 26578, 28422, 20405,
- 23522, 26517, [27784, 63858], 28024, 29723, 30759, 37341, 37756, 34756,
- 31204, 31281, 24555, 20182, 21668, 21822, 22702, 22949, 24816, 25171,
- 25302, 26422, 26965, 33333, 38464, 39345, 39389, 20524, 21331, 21828,
- 22396, 25176, 25826, 26219, 26589, 28609, 28655, 29730, 29752, 35351,
- 37944, 21585, 22022, 22374, 24392, 24986, 27470, 28760, 28845, 32187,
- 35477, 22890, 33067, 25506, 30472, 32829, 36010, 22612, 25645, 27067,
- 23445, 24081, 28271, 34153, 20812, 21488, 22826, 24608, 24907, 27526,
- 27760, 27888, 31518, 32974, 33492, 36294, 37040, 39089, 25799, 28580,
- 25745, 25860, 20814, 21520, [12063, 22303], 35342, 24927, 26742, 30171,
- 31570, 32113, 36890, 22534, 27084, 33151, 35114, 36864, 38969, 20600,
- 22871, 22956, 25237, 36879, 39722, 24925, 29305, 38358, 22369, 23110,
- 24052, 25226, 25773, 25850, 26487, 27874, 27966, 29228, 29750, 30772,
- 32631, 33453, 36315, 38935, 21028, 22338, 26495, 29256, 29923, 36009,
- 36774, 37393, 38442, [12043, 20843], 21485, 25420, 20329, 21764, 24726,
- 25943, 27803, 28031, 29260, 29437, 31255, 35207, [12185, 35997], 24429,
- 28558, 28921, 33192, 24846, [20415, 63845], 20559, 25153, [12122, 29255],
- 31687, 32232, 32745, 36941, 38829, 39449, 36022, 22378, 24179, 26544,
- 33805, 35413, 21536, 23318, 24163, 24290, 24330, 25987, 32954, 34109,
- 38281, 38491, 20296, 21253, 21261, 21263, 21638, 21754, 22275, 24067,
- 24598, 25243, 25265, 25429, 27873, 28006, 30129, 30770, 32990, 33071,
- 33502, 33889, 33970, 34957, 35090, 36875, 37610, 39165, 39825, 24133,
- [26292, 64006], 26333, 28689, 29190, 20469, 21117, 24426, 24915, 26451,
- 27161, 28418, 29922, 31080, 34920, 35961, 39111, 39108, 39491, 21697,
- 31263, 26963, 35575, 35914, [12213, 39080], 39342, 24444, 25259, 30130,
- [12138, 30382], 34987, 36991, 38466, 21305, 24380, 24517, [27852, 63848],
- 29644, 30050, [12134, 30091], 31558, 33534, 39325, 20047, 36924, 19979,
- 20309, 21414, 22799, 24264, 26160, 27827, 29781, 33655, 34662, 36032,
- 36944, 38686, 39957, 22737, 23416, 34384, 35604, 40372, 23506, 24680,
- 24717, 26097, 27735, 28450, 28579, 28698, 32597, 32752, {f: 2, c: 38289},
- 38480, 38867, 21106, 36676, 20989, 21547, 21688, 21859, 21898, 27323,
- 28085, 32216, 33382, 37532, 38519, 40569, 21512, 21704, 30418, 34532,
- 38308, 38356, 38492, 20130, 20233, 23022, 23270, 24055, 24658, 25239,
- 26477, 26689, 27782, 28207, 32568, 32923, 33322, 38917, 20133, 20565,
- 21683, 22419, 22874, 23401, 23475, 25032, 26999, 28023, 28707, 34809,
- 35299, 35442, 35559, 36994, 39405, 39608, 21182, 26680, 20502, 24184,
- 26447, 33607, [12175, 34892, 64008], 20139, 21521, 22190, 29670, 37141,
- 38911, 39177, 39255, [12217, 39321], 22099, 22687, 34395, 35377, 25010,
- 27382, 29563, 36562, 27463, 38570, 39511, 22869, 29184, 36203,
- [12208, 38761], 20436, 23796, 24358, 25080, 26203, 27883, 28843,
- [12126, 29572], 29625, 29694, 30505, 30541, 32067, 32098, 32291, 33335,
- 34898, 36066, 37449, 39023, 23377, [12147, 31348], [12174, 34880],
- [12212, 38913], 23244, 20448, 21332, 22846, 23805, 25406, 28025, 29433,
- 33029, 33031, 33698, 37583, 38960, 20136, 20804, 21009, 22411, 24418,
- 27842, 28366, 28677, 28752, 28847, 29074, 29673, [29801, 63918], 33610,
- 34722, 34913, 36872, 37026, 37795, 39336, 20846, 24407, 24800, 24935,
- 26291, 34137, 36426, 37295, 38795, 20046, 20114, 21628, 22741, 22778,
- 22909, 23733, 24359, [12094, 25142], 25160, 26122, 26215, 27627, 28009,
- 28111, 28246, 28408, 28564, 28640, 28649, 28765, 29392, 29733, 29786,
- 29920, 30355, 31068, 31946, 32286, 32993, 33446, 33899, 33983, 34382,
- 34399, 34676, 35703, 35946, 37804, 38912, 39013, 24785, 25110, 37239,
- 23130, 26127, 28151, 28222, 29759, 39746, 24573, 24794, 31503, 21700,
- 24344, 27742, 27859, 27946, 28888, 32005, 34425, 35340, 40251, 21270,
- 21644, 23301, 27194, [12117, 28779], 30069, 31117, [12146, 31166], 33457,
- 33775, 35441, 35649, 36008, 38772, 25844, 25899, {f: 2, c: 30906}, 31339,
- 20024, 21914, 22864, 23462, 24187, 24739, 25563, 27489, 26213, 26707,
- 28185, 29029, 29872, 32008, 36996, 39529, 39973, 27963, [28369, 63748],
- 29502, 35905, 38346, 20976, 24140, 24488, 24653, 24822, 24880, 24908,
- {f: 2, c: 26179}, 27045, 27841, 28255, 28361, 28514, 29004, 29852, 30343,
- 31681, 31783, 33618, 34647, 36945, 38541, [12232, 40643], 21295, 22238,
- 24315, 24458, 24674, 24724, 25079, 26214, 26371, 27292, 28142, 28590,
- 28784, 29546, 32362, 33214, 33588, 34516, 35496, 36036, 21123, 29554,
- 23446, 27243, 37892, 21742, 22150, 23389, 25928, 25989, 26313, 26783,
- 28045, 28102, [12120, 29243], 32948, 37237, 39501, 20399, 20505, 21402,
- 21518, 21564, 21897, 21957, 24127, 24460, 26429, 29030, 29661, 36869,
- 21211, 21235, 22628, 22734, 28932, 29071, 29179, 34224, 35347,
- [26248, 63941], 34216, 21927, 26244, 29002, 33841, 21321, 21913, 27585,
- 24409, 24509, 25582, 26249, 28999, 35569, 36637, 40638, 20241, 25658,
- 28875, 30054, 34407, 24676, 35662, 40440, 20807, 20982, 21256, 27958,
- 33016, [12234, 40657], 26133, 27427, 28824, 30165, 21507, 23673, 32007,
- 35350, [12107, 27424], 27453, 27462, 21560, 24688, 27965, 32725, 33288,
- 20694, 20958, 21916, 22123, 22221, 23020, 23305, 24076, 24985, 24984,
- 25137, 26206, 26342, 29081, {f: 2, c: 29113}, 29351, 31143, 31232, 32690,
- 35440, {s: 163}, {f: 4, c: 12310}, {s: 14}, 8223, 8219, {f: 2, c: 8314},
- {s: 7}, 8316, 0, {f: 2, c: 8317}, {s: 23}, 700, {s: 44}, 8942, 8759,
- {s: 20}, {f: 10, c: 10122}, {s: 36}, {f: 26, c: 9398}, {s: 61},
- {f: 2, c: 8826}, {f: 2, c: 8910}, {f: 2, c: 8832}, {f: 4, c: 8816}, 0,
- 8842, 0, 8843, {f: 2, c: 8822}, 8825, {f: 2, c: 8922}, {s: 5}, 8773, 8771,
- 8776, 0, 8868, {s: 78}, 8244, {s: 11}, 9839, {s: 4}, 8258, {s: 4}, 10045,
- 0, 0, 8226, {s: 4}, {f: 2, c: 8249}, {s: 16}, 10010, 10006, 0, 9711,
- {s: 3}, 10070, 0, 9676, {s: 24}, 9775, {s: 6}, 12320, 0, {f: 10, c: 10102},
- {s: 17}, 12306, 12342, {s: 13}, 8710, 0, 8735, 0, {f: 2, c: 8741}, 0, 8787,
- 8785, {f: 2, c: 8806}, 8723, {f: 3, c: 8853}, 0, 8980, 0, 0, 8802, 0, 9649,
- 0, 8738, 8784, 0, 0, 8867, 0, 0, {f: 2, c: 8814}, 8837, 8836, 8713, 8716,
- {f: 2, c: 8891}, 8794, 8966, {s: 6}, 12958, 0, 8252, {s: 11}, 9702, {s: 3},
- 9663, 9653, 9657, 9667, {s: 4}, 9674, 12849, 12857, 13259, {f: 5, c: 9327},
- {s: 18}, 8656, 8655, 8653, {s: 37}, 8657, 8659, {s: 8}, 8626, 8625, 0,
- 8628, 8624, 8627, {s: 14}, 8636, 8640, {s: 10}, {f: 2, c: 8644}, {s: 144},
- {f: 5, c: 9347}, {s: 33}, 12948, {s: 15}, 12965, {s: 93}, 8672, 8674, 8673,
- 8675, {s: 4}, 8678, 8680, 8679, 8681, {s: 20}, 9757, 9759, {s: 76}, 12944,
- {f: 6, c: 12938}, {s: 15}, {f: 2, c: 12318}, 8246, 0, 8245, {s: 3}, 12540,
- 0, 0, {f: 2, c: 44034}, {f: 2, c: 44037}, {f: 5, c: 44043}, 44056,
- {f: 2, c: 44062}, {f: 3, c: 44065}, {f: 7, c: 44069}, 44078,
- {f: 6, c: 44082}, {f: 2, c: 44090}, {f: 3, c: 44093}, {f: 10, c: 44097},
- 44108, {f: 6, c: 44110}, {f: 3, c: 44117}, {f: 3, c: 44121},
- {f: 19, c: 44125}, {f: 2, c: 44146}, {f: 2, c: 44149}, 44153,
- {f: 5, c: 44155}, 44162, {f: 2, c: 44167}, {f: 3, c: 44173},
- {f: 3, c: 44177}, {f: 7, c: 44181}, 44190, {f: 6, c: 44194}, 44203,
- {f: 2, c: 44205}, {f: 7, c: 44209}, 44218, {f: 3, c: 44222},
- {f: 2, c: 44226}, {f: 3, c: 44229}, {f: 3, c: 44233}, {f: 8, c: 44237},
- 44246, {f: 8, c: 44248}, {f: 2, c: 44258}, {f: 2, c: 44261}, 44265, 44267,
- {f: 2, c: 44269}, 44274, 44276, {f: 5, c: 44279}, {f: 2, c: 44286},
- {f: 3, c: 44289}, 44293, {f: 5, c: 44295}, 44302, 44304, {f: 6, c: 44306},
- {f: 3, c: 44313}, {f: 3, c: 44317}, {f: 8, c: 44321}, {f: 2, c: 44330},
- {f: 6, c: 44334}, {f: 2, c: 44342}, {f: 3, c: 44345}, {f: 7, c: 44349},
- 44358, 44360, {f: 6, c: 44362}, {f: 3, c: 44369}, {f: 3, c: 44373},
- {f: 8, c: 44377}, 44386, {f: 8, c: 44388}, {f: 2, c: 44398},
- {f: 2, c: 44401}, {f: 4, c: 44407}, 44414, 44416, {f: 5, c: 44419},
- {f: 2, c: 44426}, {f: 3, c: 44429}, {f: 11, c: 44433}, {f: 6, c: 44446},
- {f: 18, c: 44453}, {f: 8, c: 44472}, {f: 2, c: 44482}, {f: 3, c: 44485},
- {f: 7, c: 44489}, 44498, {f: 8, c: 44500}, {f: 3, c: 44509},
- {f: 3, c: 44513}, {f: 19, c: 44517}, {f: 2, c: 44538}, {f: 2, c: 44541},
- {f: 6, c: 44546}, 44554, 44556, {f: 6, c: 44558}, {f: 27, c: 44565},
- {f: 2, c: 44594}, {f: 2, c: 44597}, 44601, {f: 5, c: 44603}, 44610, 44612,
- {f: 3, c: 44615}, 44619, 44623, {f: 3, c: 44625}, 44629, {f: 5, c: 44631},
- 44638, {f: 3, c: 44642}, {f: 2, c: 44646}, {f: 2, c: 44650},
- {f: 3, c: 44653}, {f: 7, c: 44657}, 44666, {f: 6, c: 44670},
- {f: 6, c: 44678}, {f: 47, c: 44685}, 44735, {f: 3, c: 44737},
- {f: 7, c: 44741}, 44750, {f: 6, c: 44754}, {f: 2, c: 44762},
- {f: 11, c: 44765}, {f: 2, c: 44777}, 44780, {f: 6, c: 44782},
- {f: 3, c: 44789}, {f: 3, c: 44793}, {f: 10, c: 44797}, {f: 4, c: 44809},
- {f: 2, c: 44814}, {f: 27, c: 44817}, {f: 2, c: 44846}, 44849, 44851,
- {f: 7, c: 44853}, 44862, 44864, {f: 4, c: 44868}, {f: 6, c: 44874},
- {f: 11, c: 44881}, {f: 6, c: 44894}, {f: 19, c: 44902}, {f: 6, c: 44922},
- {f: 3, c: 44929}, {f: 3, c: 44933}, {f: 7, c: 44937}, {f: 3, c: 44946},
- {f: 6, c: 44950}, {f: 27, c: 44957}, {f: 2, c: 44986}, {f: 3, c: 44989},
- {f: 6, c: 44993}, 45002, 45004, {f: 5, c: 45007}, {f: 7, c: 45013},
- {f: 11, c: 45021}, {f: 6, c: 45034}, {f: 2, c: 45042}, {f: 3, c: 45045},
- {f: 7, c: 45049}, {f: 2, c: 45058}, {f: 7, c: 45061}, {f: 3, c: 45069},
- {f: 3, c: 45073}, {f: 7, c: 45077}, {f: 10, c: 45086}, {f: 27, c: 45097},
- {f: 2, c: 45126}, 45129, 45131, 45133, {f: 4, c: 45135}, 45142, 45144,
- {f: 3, c: 45146}, {f: 30, c: 45150}, {f: 2, c: 45182}, {f: 3, c: 45185},
- {f: 7, c: 45189}, 45198, 45200, {f: 6, c: 45202}, 45211, {f: 2, c: 45213},
- {f: 5, c: 45219}, 45226, 45232, 45234, {f: 2, c: 45238}, {f: 3, c: 45241},
- {f: 7, c: 45245}, 45254, {f: 6, c: 45258}, {f: 2, c: 45266},
- {f: 3, c: 45269}, {f: 7, c: 45273}, {f: 4, c: 45281}, {f: 34, c: 45286},
- 45322, {f: 3, c: 45325}, 45329, {f: 4, c: 45332}, 45338, {f: 5, c: 45342},
- {f: 2, c: 45350}, {f: 3, c: 45353}, {f: 7, c: 45357}, 45366,
- {f: 6, c: 45370}, {f: 2, c: 45378}, {f: 3, c: 45381}, {f: 7, c: 45385},
- {f: 2, c: 45394}, {f: 2, c: 45398}, {f: 3, c: 45401}, {f: 3, c: 45405},
- {f: 23, c: 45409}, {f: 2, c: 45434}, {f: 3, c: 45437}, 45441,
- {f: 5, c: 45443}, 45450, 45452, {f: 4, c: 45454}, {f: 3, c: 45461},
- {f: 3, c: 45465}, {f: 11, c: 45469}, {f: 35, c: 45481}, {f: 3, c: 45517},
- {f: 3, c: 45521}, {f: 7, c: 45525}, 45534, {f: 8, c: 45536},
- {f: 2, c: 45546}, {f: 3, c: 45549}, {f: 8, c: 45553}, 45562, 45564,
- {f: 6, c: 45566}, {f: 2, c: 45574}, {f: 2, c: 45577}, {f: 7, c: 45581},
- 45590, 45592, {f: 6, c: 45594}, {f: 19, c: 45601}, {f: 7, c: 45621},
- {f: 27, c: 45629}, {f: 3, c: 45657}, {f: 3, c: 45661}, {f: 7, c: 45665},
- {f: 10, c: 45674}, {f: 6, c: 45686}, {f: 7, c: 45693}, {f: 3, c: 45702},
- {f: 6, c: 45706}, {f: 2, c: 45714}, {f: 3, c: 45717}, {f: 5, c: 45723},
- 45730, 45732, {f: 3, c: 45735}, 45739, {f: 3, c: 45741}, {f: 3, c: 45745},
- {f: 19, c: 45749}, {f: 2, c: 45770}, {f: 3, c: 45773}, 45777,
- {f: 5, c: 45779}, 45786, 45788, {f: 4, c: 45790}, 45795, 45799,
- {f: 2, c: 45801}, {f: 3, c: 45808}, 45814, {f: 3, c: 45820},
- {f: 2, c: 45826}, {f: 3, c: 45829}, {f: 7, c: 45833}, 45842,
- {f: 6, c: 45846}, {f: 55, c: 45853}, 45911, {f: 2, c: 45913}, 45917,
- {f: 4, c: 45920}, 45926, 45928, 45930, {f: 2, c: 45932}, 45935,
- {f: 2, c: 45938}, {f: 3, c: 45941}, {f: 7, c: 45945}, 45954,
- {f: 6, c: 45958}, {f: 3, c: 45965}, {f: 3, c: 45969}, {f: 11, c: 45973},
- {f: 6, c: 45986}, {f: 3, c: 45993}, {f: 23, c: 45997}, {f: 2, c: 46022},
- {f: 2, c: 46025}, 46029, 46031, {f: 3, c: 46033}, 46038, 46040, 46042,
- 46044, {f: 2, c: 46046}, {f: 3, c: 46049}, {f: 3, c: 46053},
- {f: 19, c: 46057}, {f: 19, c: 46077}, {f: 7, c: 46097}, {f: 3, c: 46105},
- {f: 3, c: 46109}, {f: 7, c: 46113}, 46122, {f: 8, c: 46124},
- {f: 27, c: 46133}, {f: 2, c: 46162}, {f: 3, c: 46165}, {f: 7, c: 46169},
- 46178, 46180, {f: 6, c: 46182}, {f: 19, c: 46189}, {f: 7, c: 46209},
- {f: 20, c: 46217}, {f: 6, c: 46238}, {f: 3, c: 46245}, {f: 3, c: 46249},
- {f: 8, c: 46253}, 46262, 46264, {f: 6, c: 46266}, {f: 3, c: 46273},
- {f: 3, c: 46277}, {f: 7, c: 46281}, {f: 4, c: 46289}, {f: 6, c: 46294},
- {f: 2, c: 46302}, {f: 2, c: 46305}, 46309, {f: 5, c: 46311}, 46318, 46320,
- {f: 6, c: 46322}, {f: 27, c: 46329}, {f: 2, c: 46358}, {f: 2, c: 46361},
- {f: 7, c: 46365}, 46374, {f: 5, c: 46379}, {f: 2, c: 46386},
- {f: 3, c: 46389}, {f: 7, c: 46393}, 46402, {f: 5, c: 46406},
- {f: 2, c: 46414}, {f: 3, c: 46417}, {f: 7, c: 46421}, 46430,
- {f: 62, c: 46434}, {f: 2, c: 46498}, {f: 3, c: 46501}, 46505,
- {f: 4, c: 46508}, 46514, {f: 5, c: 46518}, {f: 2, c: 46526},
- {f: 3, c: 46529}, {f: 7, c: 46533}, 46542, {f: 6, c: 46546},
- {f: 19, c: 46553}, {f: 35, c: 46573}, {f: 2, c: 46610}, {f: 3, c: 46613},
- {f: 12, c: 46617}, {f: 6, c: 46630}, {f: 7, c: 46637}, {f: 19, c: 46645},
- {f: 27, c: 46665}, {f: 3, c: 46693}, {f: 51, c: 46697}, {f: 2, c: 46750},
- {f: 3, c: 46753}, {f: 6, c: 46757}, {f: 4, c: 46765}, {f: 34, c: 46770},
- {f: 27, c: 46805}, {f: 3, c: 46833}, {f: 3, c: 46837}, {f: 7, c: 46841},
- {f: 3, c: 46850}, {f: 34, c: 46854}, {f: 2, c: 46890}, {f: 2, c: 46893},
- {f: 7, c: 46897}, 46906, {f: 8, c: 46908}, {f: 3, c: 46917},
- {f: 3, c: 46921}, {f: 7, c: 46925}, {f: 10, c: 46934}, {f: 3, c: 46945},
- {f: 3, c: 46949}, {f: 7, c: 46953}, 46962, 46964, {f: 6, c: 46966},
- {f: 2, c: 46974}, {f: 3, c: 46977}, {f: 7, c: 46981}, 46990,
- {f: 3, c: 46995}, {f: 2, c: 47002}, {f: 3, c: 47005}, {f: 7, c: 47009},
- 47018, {f: 6, c: 47022}, {f: 2, c: 47030}, {f: 14, c: 47033}, 47048,
- {f: 34, c: 47050}, {f: 2, c: 47086}, {f: 3, c: 47089}, {f: 7, c: 47093},
- 47102, {f: 5, c: 47106}, {f: 2, c: 47114}, {f: 3, c: 47117},
- {f: 7, c: 47121}, 47130, 47132, {f: 6, c: 47134}, {f: 2, c: 47142},
- {f: 3, c: 47145}, {f: 7, c: 47149}, 47158, {f: 6, c: 47162},
- {f: 3, c: 47169}, {f: 12, c: 47173}, 47186, {f: 8, c: 47188},
- {f: 2, c: 47198}, {f: 3, c: 47201}, {f: 7, c: 47205}, 47214, 47216,
- {f: 6, c: 47218}, {f: 3, c: 47225}, {f: 16, c: 47229}, {f: 26, c: 47246},
- {f: 7, c: 47273}, {f: 3, c: 47281}, {f: 3, c: 47285}, {f: 7, c: 47289},
- 47298, 47300, {f: 6, c: 47302}, {f: 3, c: 47309}, {f: 3, c: 47313},
- {f: 8, c: 47317}, 47326, 47328, {f: 6, c: 47330}, {f: 2, c: 47338},
- {f: 3, c: 47341}, {f: 7, c: 47345}, 47354, 47356, {f: 6, c: 47358},
- {f: 19, c: 47365}, {f: 7, c: 47385}, {f: 27, c: 47393}, {f: 2, c: 47422},
- {f: 3, c: 47425}, {f: 7, c: 47429}, {f: 2, c: 47437}, 47440,
- {f: 6, c: 47442}, {f: 2, c: 47450}, {f: 3, c: 47453}, {f: 7, c: 47457},
- 47466, 47468, {f: 6, c: 47470}, {f: 2, c: 47478}, {f: 3, c: 47481},
- {f: 7, c: 47485}, 47494, 47496, {f: 2, c: 47499}, {f: 29, c: 47503},
- {f: 2, c: 47534}, {f: 3, c: 47537}, {f: 7, c: 47541}, 47550, 47552,
- {f: 6, c: 47554}, {f: 2, c: 47562}, 47565, {f: 5, c: 47571}, 47578, 47580,
- {f: 2, c: 47583}, 47586, {f: 2, c: 47590}, {f: 3, c: 47593},
- {f: 7, c: 47597}, 47606, {f: 5, c: 47611}, {f: 6, c: 47618},
- {f: 12, c: 47625}, {f: 34, c: 47638}, {f: 2, c: 47674}, {f: 3, c: 47677},
- 47681, {f: 5, c: 47683}, 47690, 47692, {f: 4, c: 47695}, {f: 2, c: 47702},
- {f: 3, c: 47705}, {f: 7, c: 47709}, 47718, {f: 6, c: 47722},
- {f: 2, c: 47730}, {f: 3, c: 47733}, {f: 10, c: 47737}, 47750,
- {f: 4, c: 47752}, {f: 27, c: 47757}, 47786, {f: 3, c: 47789}, 47793,
- {f: 5, c: 47795}, 47802, 47804, {f: 6, c: 47806}, {f: 3, c: 47813},
- {f: 15, c: 47817}, {f: 34, c: 47834}, {f: 3, c: 47869}, {f: 3, c: 47873},
- {f: 8, c: 47877}, 47886, 47888, {f: 6, c: 47890}, {f: 3, c: 47897},
- {f: 3, c: 47901}, {f: 8, c: 47905}, 47914, {f: 8, c: 47916}, 47927,
- {f: 2, c: 47929}, {f: 5, c: 47935}, 47942, 47944, {f: 3, c: 47946}, 47950,
- {f: 3, c: 47953}, {f: 3, c: 47957}, {f: 8, c: 47961}, 47970,
- {f: 8, c: 47972}, {f: 27, c: 47981}, {f: 3, c: 48009}, {f: 3, c: 48013},
- {f: 19, c: 48017}, {f: 3, c: 48037}, {f: 3, c: 48041}, {f: 7, c: 48045},
- {f: 2, c: 48053}, {f: 8, c: 48056}, {f: 3, c: 48065}, {f: 3, c: 48069},
- {f: 7, c: 48073}, {f: 2, c: 48081}, {f: 36, c: 48084}, {f: 2, c: 48122},
- {f: 2, c: 48125}, 48129, {f: 5, c: 48131}, 48138, 48142, 48144,
- {f: 2, c: 48146}, {f: 2, c: 48153}, {f: 4, c: 48160}, 48166, 48168,
- {f: 3, c: 48170}, {f: 2, c: 48174}, {f: 2, c: 48178}, {f: 3, c: 48181},
- {f: 7, c: 48185}, 48194, {f: 3, c: 48198}, {f: 2, c: 48202},
- {f: 2, c: 48206}, {f: 12, c: 48209}, {f: 38, c: 48222}, {f: 2, c: 48262},
- {f: 2, c: 48265}, 48269, {f: 5, c: 48271}, 48278, 48280, {f: 5, c: 48283},
- {f: 2, c: 48290}, {f: 2, c: 48293}, {f: 7, c: 48297}, 48306,
- {f: 6, c: 48310}, {f: 2, c: 48318}, {f: 3, c: 48321}, {f: 8, c: 48325},
- 48334, {f: 3, c: 48338}, {f: 2, c: 48342}, {f: 3, c: 48345},
- {f: 23, c: 48349}, 48375, {f: 3, c: 48377}, {f: 7, c: 48381}, 48390, 48392,
- {f: 6, c: 48394}, {f: 3, c: 48401}, {f: 15, c: 48405}, {f: 7, c: 48421},
- {f: 19, c: 48429}, {f: 7, c: 48449}, {f: 2, c: 48458}, {f: 3, c: 48461},
- {f: 7, c: 48465}, {f: 10, c: 48474}, {f: 3, c: 48485}, {f: 23, c: 48489},
- {f: 2, c: 48514}, {f: 2, c: 48517}, {f: 5, c: 48523}, 48530, 48532,
- {f: 3, c: 48534}, 48539, {f: 7, c: 48541}, {f: 11, c: 48549},
- {f: 7, c: 48561}, {f: 27, c: 48569}, {f: 2, c: 48598}, {f: 3, c: 48601},
- {f: 12, c: 48605}, {f: 6, c: 48618}, {f: 3, c: 48625}, {f: 3, c: 48629},
- {f: 7, c: 48633}, {f: 2, c: 48641}, 48644, {f: 6, c: 48646},
- {f: 2, c: 48654}, {f: 3, c: 48657}, {f: 7, c: 48661}, 48670,
- {f: 36, c: 48672}, {f: 2, c: 48710}, {f: 3, c: 48713}, 48717,
- {f: 5, c: 48719}, 48726, 48728, {f: 4, c: 48732}, {f: 2, c: 48738},
- {f: 3, c: 48741}, 48745, {f: 5, c: 48747}, 48754, {f: 5, c: 48758},
- {f: 2, c: 48766}, {f: 3, c: 48769}, {f: 7, c: 48773}, 48782,
- {f: 6, c: 48786}, {f: 14, c: 48794}, {f: 39, c: 48809}, {f: 2, c: 48850},
- {f: 2, c: 48853}, {f: 7, c: 48857}, {f: 2, c: 48865}, {f: 6, c: 48870},
- {f: 20, c: 48877}, {f: 6, c: 48898}, {f: 14, c: 48906}, 48922,
- {f: 34, c: 48926}, {f: 2, c: 48962}, {f: 3, c: 48965}, {f: 7, c: 48969},
- {f: 3, c: 48978}, {f: 62, c: 48982}, {f: 27, c: 49045}, {f: 20, c: 49073},
- {f: 6, c: 49094}, {f: 2, c: 49102}, {f: 3, c: 49105}, {f: 7, c: 49109},
- {f: 2, c: 49117}, 49120, {f: 90, c: 49122}, {f: 20, c: 49213},
- {f: 6, c: 49234}, {f: 3, c: 49241}, {f: 3, c: 49245}, {f: 7, c: 49249},
- {f: 38, c: 49258}, {f: 2, c: 49298}, {f: 3, c: 49301}, {f: 7, c: 49305},
- 49314, 49316, {f: 6, c: 49318}, 49326, {f: 2, c: 49329}, {f: 5, c: 49335},
- 49342, {f: 3, c: 49346}, {f: 2, c: 49350}, {f: 2, c: 49354},
- {f: 3, c: 49357}, {f: 7, c: 49361}, 49370, {f: 6, c: 49374},
- {f: 2, c: 49382}, {f: 3, c: 49385}, {f: 7, c: 49389}, 49398, 49400,
- {f: 6, c: 49402}, {f: 3, c: 49409}, {f: 3, c: 49413}, {f: 7, c: 49417},
- {f: 4, c: 49425}, {f: 6, c: 49430}, {f: 2, c: 49441}, 49445,
- {f: 4, c: 49448}, 49454, {f: 4, c: 49458}, 49463, {f: 2, c: 49466},
- {f: 3, c: 49469}, {f: 7, c: 49473}, 49482, {f: 6, c: 49486},
- {f: 2, c: 49494}, {f: 3, c: 49497}, {f: 7, c: 49501}, 49510,
- {f: 6, c: 49514}, {f: 3, c: 49521}, {f: 3, c: 49525}, {f: 12, c: 49529},
- {f: 6, c: 49542}, 49551, {f: 3, c: 49553}, 49557, {f: 5, c: 49559}, 49566,
- 49568, {f: 3, c: 49570}, {f: 2, c: 49574}, {f: 2, c: 49578},
- {f: 3, c: 49581}, {f: 12, c: 49585}, {f: 6, c: 49598}, {f: 3, c: 49605},
- {f: 3, c: 49609}, {f: 7, c: 49613}, {f: 2, c: 49621}, {f: 7, c: 49625},
- {f: 3, c: 49633}, {f: 3, c: 49637}, {f: 7, c: 49641}, 49650,
- {f: 8, c: 49652}, {f: 2, c: 49662}, {f: 3, c: 49665}, {f: 7, c: 49669},
- 49678, 49680, {f: 6, c: 49682}, {f: 2, c: 49690}, {f: 2, c: 49693},
- {f: 7, c: 49697}, 49706, 49708, 49710, 49712, 49715, {f: 19, c: 49717},
- {f: 7, c: 49737}, {f: 2, c: 49746}, {f: 3, c: 49749}, {f: 7, c: 49753},
- {f: 4, c: 49761}, {f: 6, c: 49766}, {f: 2, c: 49774}, {f: 3, c: 49777},
- {f: 7, c: 49781}, 49790, 49792, {f: 6, c: 49794}, {f: 6, c: 49802},
- {f: 7, c: 49809}, {f: 2, c: 49817}, 49820, {f: 6, c: 49822},
- {f: 2, c: 49830}, {f: 3, c: 49833}, {f: 6, c: 49838}, 49846, 49848,
- {f: 34, c: 49850}, {f: 2, c: 49886}, {f: 2, c: 49889}, {f: 6, c: 49893},
- 49902, 49904, {f: 4, c: 49906}, 49911, 49914, {f: 3, c: 49917},
- {f: 7, c: 49921}, {f: 2, c: 49930}, {f: 5, c: 49934}, {f: 2, c: 49942},
- {f: 3, c: 49945}, {f: 7, c: 49949}, {f: 2, c: 49958}, {f: 27, c: 49962},
- {f: 34, c: 49990}, {f: 2, c: 50026}, {f: 3, c: 50029}, 50033,
- {f: 5, c: 50035}, {f: 2, c: 50042}, {f: 6, c: 50046}, {f: 3, c: 50053},
- {f: 3, c: 50057}, {f: 51, c: 50061}, {f: 23, c: 50113}, {f: 2, c: 50138},
- {f: 2, c: 50141}, 50145, {f: 5, c: 50147}, {f: 3, c: 50154},
- {f: 6, c: 50158}, {f: 2, c: 50166}, {f: 15, c: 50169}, {f: 7, c: 50185},
- {f: 19, c: 50193}, {f: 7, c: 50213}, {f: 3, c: 50221}, {f: 3, c: 50225},
- {f: 7, c: 50229}, {f: 10, c: 50238}, {f: 27, c: 50249}, {f: 2, c: 50278},
- {f: 3, c: 50281}, {f: 7, c: 50285}, {f: 3, c: 50294}, {f: 6, c: 50298},
- {f: 19, c: 50305}, {f: 7, c: 50325}, {f: 27, c: 50333}, {f: 3, c: 50361},
- {f: 44, c: 50365}, {f: 6, c: 50410}, {f: 2, c: 50418}, {f: 3, c: 50421},
- 50425, {f: 4, c: 50427}, {f: 10, c: 50434}, {f: 3, c: 50445},
- {f: 3, c: 50449}, {f: 7, c: 50453}, {f: 11, c: 50461}, {f: 2, c: 50474},
- {f: 3, c: 50477}, {f: 7, c: 50481}, 50490, 50492, {f: 6, c: 50494},
- {f: 2, c: 50502}, 50507, {f: 4, c: 50511}, 50518, {f: 3, c: 50522}, 50527,
- {f: 2, c: 50530}, {f: 3, c: 50533}, {f: 7, c: 50537}, 50546,
- {f: 6, c: 50550}, {f: 2, c: 50558}, {f: 3, c: 50561}, {f: 2, c: 50565},
- {f: 4, c: 50568}, 50574, 50576, {f: 3, c: 50578}, 50582, {f: 3, c: 50585},
- {f: 3, c: 50589}, {f: 8, c: 50593}, {f: 10, c: 50602}, {f: 2, c: 50614},
- 50618, {f: 5, c: 50623}, 50635, 50637, 50639, {f: 2, c: 50642},
- {f: 3, c: 50645}, {f: 7, c: 50649}, 50658, 50660, {f: 6, c: 50662}, 50671,
- {f: 3, c: 50673}, 50677, {f: 4, c: 50680}, {f: 3, c: 50690},
- {f: 3, c: 50697}, {f: 3, c: 50701}, {f: 7, c: 50705}, 50714,
- {f: 7, c: 50717}, {f: 2, c: 50726}, {f: 3, c: 50729}, 50735,
- {f: 2, c: 50737}, 50742, 50744, 50746, {f: 4, c: 50748}, {f: 2, c: 50754},
- {f: 3, c: 50757}, {f: 7, c: 50761}, 50770, {f: 6, c: 50774},
- {f: 2, c: 50782}, {f: 11, c: 50785}, {f: 2, c: 50797}, 50800,
- {f: 6, c: 50802}, {f: 2, c: 50810}, {f: 3, c: 50813}, {f: 7, c: 50817},
- 50826, 50828, {f: 6, c: 50830}, {f: 2, c: 50838}, {f: 3, c: 50841},
- {f: 7, c: 50845}, 50854, 50856, {f: 6, c: 50858}, {f: 2, c: 50866},
- {f: 3, c: 50869}, {f: 5, c: 50875}, 50882, 50884, {f: 6, c: 50886},
- {f: 2, c: 50894}, {f: 3, c: 50897}, {f: 7, c: 50901}, {f: 2, c: 50910},
- {f: 6, c: 50914}, {f: 2, c: 50922}, {f: 3, c: 50925}, {f: 7, c: 50929},
- {f: 3, c: 50938}, {f: 6, c: 50942}, {f: 2, c: 50950}, {f: 3, c: 50953},
- {f: 7, c: 50957}, 50966, 50968, {f: 6, c: 50970}, {f: 2, c: 50978},
- {f: 3, c: 50981}, {f: 7, c: 50985}, 50994, 50996, 50998, {f: 4, c: 51000},
- {f: 2, c: 51006}, {f: 3, c: 51009}, {f: 5, c: 51013}, 51019, 51022, 51024,
- {f: 3, c: 51033}, {f: 3, c: 51037}, {f: 7, c: 51041}, {f: 2, c: 51049},
- {f: 8, c: 51052}, {f: 2, c: 51062}, {f: 3, c: 51065}, {f: 4, c: 51071},
- 51078, {f: 3, c: 51083}, 51087, {f: 2, c: 51090}, 51093, 51097,
- {f: 5, c: 51099}, 51106, {f: 5, c: 51111}, {f: 2, c: 51118},
- {f: 3, c: 51121}, {f: 7, c: 51125}, 51134, {f: 6, c: 51138},
- {f: 2, c: 51146}, 51149, 51151, {f: 7, c: 51153}, {f: 4, c: 51161},
- {f: 6, c: 51166}, {f: 3, c: 51173}, {f: 3, c: 51177}, {f: 19, c: 51181},
- {f: 2, c: 51202}, {f: 3, c: 51205}, 51209, {f: 5, c: 51211}, 51218, 51220,
- {f: 5, c: 51223}, {f: 2, c: 51230}, {f: 3, c: 51233}, {f: 7, c: 51237},
- 51246, 51248, {f: 6, c: 51250}, {f: 3, c: 51257}, {f: 3, c: 51261},
- {f: 7, c: 51265}, {f: 2, c: 51274}, {f: 6, c: 51278}, {f: 27, c: 51285},
- {f: 2, c: 51314}, {f: 3, c: 51317}, 51321, {f: 5, c: 51323}, 51330, 51332,
- {f: 3, c: 51336}, {f: 6, c: 51342}, {f: 8, c: 51349}, 51358, 51360,
- {f: 6, c: 51362}, {f: 19, c: 51369}, {f: 6, c: 51390}, {f: 3, c: 51397},
- {f: 3, c: 51401}, {f: 7, c: 51405}, 51414, 51416, {f: 6, c: 51418},
- {f: 2, c: 51426}, {f: 16, c: 51429}, {f: 6, c: 51446}, {f: 2, c: 51454},
- {f: 3, c: 51457}, {f: 5, c: 51463}, 51470, 51472, {f: 6, c: 51474},
- {f: 19, c: 51481}, {f: 7, c: 51501}, {f: 27, c: 51509}, {f: 2, c: 51538},
- {f: 3, c: 51541}, {f: 7, c: 51545}, 51554, {f: 8, c: 51556},
- {f: 3, c: 51565}, {f: 3, c: 51569}, {f: 7, c: 51573}, {f: 11, c: 51581},
- {f: 2, c: 51594}, {f: 3, c: 51597}, {f: 7, c: 51601}, 51610, 51612,
- {f: 34, c: 51614}, {f: 2, c: 51650}, {f: 2, c: 51653}, 51657,
- {f: 5, c: 51659}, 51666, 51668, {f: 2, c: 51671}, 51675, {f: 2, c: 51678},
- 51681, 51683, {f: 2, c: 51685}, {f: 4, c: 51688}, 51694, {f: 6, c: 51698},
- {f: 2, c: 51706}, {f: 3, c: 51709}, {f: 7, c: 51713}, 51722,
- {f: 6, c: 51726}, {f: 3, c: 51733}, {f: 16, c: 51737}, {f: 34, c: 51754},
- {f: 2, c: 51790}, {f: 3, c: 51793}, {f: 7, c: 51797}, 51806,
- {f: 6, c: 51810}, {f: 20, c: 51817}, {f: 6, c: 51838}, {f: 19, c: 51845},
- {f: 35, c: 51865}, {f: 2, c: 51902}, {f: 3, c: 51905}, {f: 7, c: 51909},
- 51918, 51920, 51922, {f: 4, c: 51924}, {f: 6, c: 51930}, {f: 11, c: 51937},
- {f: 7, c: 51949}, {f: 19, c: 51957}, {f: 7, c: 51977}, {f: 3, c: 51985},
- {f: 3, c: 51989}, {f: 7, c: 51993}, {f: 31, c: 52002}, {f: 6, c: 52034},
- {f: 2, c: 52042}, {f: 3, c: 52045}, {f: 7, c: 52049}, {f: 3, c: 52058},
- {f: 6, c: 52062}, {f: 19, c: 52069}, {f: 34, c: 52090}, {f: 27, c: 52125},
- {f: 27, c: 52153}, {f: 15, c: 52181}, {f: 2, c: 52197}, 52200,
- {f: 34, c: 52202}, {f: 2, c: 52238}, {f: 3, c: 52241}, {f: 7, c: 52245},
- {f: 3, c: 52254}, {f: 4, c: 52259}, {f: 2, c: 52266}, 52269, 52271,
- {f: 7, c: 52273}, 52282, {f: 5, c: 52287}, {f: 2, c: 52294},
- {f: 3, c: 52297}, {f: 7, c: 52301}, 52310, {f: 6, c: 52314},
- {f: 3, c: 52321}, 52325, 52327, {f: 7, c: 52329}, {f: 4, c: 52337},
- {f: 34, c: 52342}, {f: 2, c: 52378}, {f: 3, c: 52381}, {f: 7, c: 52385},
- 52394, {f: 6, c: 52398}, {f: 2, c: 52406}, {f: 3, c: 52409},
- {f: 7, c: 52413}, 52422, 52424, {f: 6, c: 52426}, {f: 3, c: 52433},
- {f: 15, c: 52437}, {f: 7, c: 52453}, {f: 3, c: 52461}, {f: 16, c: 52465},
- {f: 6, c: 52482}, {f: 2, c: 52490}, {f: 3, c: 52493}, {f: 7, c: 52497},
- 52506, 52508, {f: 6, c: 52510}, {f: 3, c: 52517}, {f: 3, c: 52521},
- {f: 12, c: 52525}, {f: 34, c: 52538}, {f: 3, c: 52573}, {f: 3, c: 52577},
- {f: 7, c: 52581}, 52590, 52592, {f: 6, c: 52594}, {f: 15, c: 52601},
- {f: 11, c: 52617}, {f: 2, c: 52630}, {f: 3, c: 52633}, {f: 7, c: 52637},
- 52646, 52648, {f: 6, c: 52650}, {f: 19, c: 52657}, {f: 7, c: 52677},
- {f: 3, c: 52685}, {f: 23, c: 52689}, {f: 3, c: 52713}, {f: 3, c: 52717},
- {f: 7, c: 52721}, 52730, 52732, {f: 6, c: 52734}, {f: 3, c: 52741},
- {f: 3, c: 52745}, {f: 7, c: 52749}, {f: 4, c: 52757}, {f: 6, c: 52762},
- {f: 2, c: 52770}, {f: 3, c: 52773}, {f: 7, c: 52777}, 52786, 52788,
- {f: 34, c: 52790}, {f: 2, c: 52826}, {f: 2, c: 52829}, {f: 6, c: 52834},
- 52842, 52844, {f: 6, c: 52846}, {f: 2, c: 52854}, {f: 3, c: 52857},
- {f: 7, c: 52861}, 52870, 52872, {f: 6, c: 52874}, {f: 2, c: 52882},
- {f: 3, c: 52885}, {f: 7, c: 52889}, 52898, {f: 6, c: 52902},
- {f: 19, c: 52910}, {f: 34, c: 52930}, {f: 2, c: 52966}, {f: 2, c: 52969},
- {f: 7, c: 52973}, 52982, {f: 6, c: 52986}, {f: 2, c: 52994},
- {f: 3, c: 52997}, {f: 7, c: 53001}, 53010, 53012, {f: 6, c: 53014},
- {f: 3, c: 53021}, {f: 3, c: 53025}, {f: 7, c: 53029}, 53038,
- {f: 6, c: 53042}, {f: 27, c: 53049}, {f: 2, c: 53078}, {f: 3, c: 53081},
- {f: 7, c: 53085}, 53094, 53096, {f: 6, c: 53098}, {f: 2, c: 53106},
- {f: 3, c: 53109}, {f: 7, c: 53113}, {f: 4, c: 53121}, {f: 6, c: 53126},
- {f: 20, c: 53133}, {f: 6, c: 53154}, {f: 7, c: 53161}, {f: 19, c: 53169},
- {f: 27, c: 53189}, {f: 2, c: 53218}, {f: 3, c: 53221}, {f: 7, c: 53225},
- 53234, 53236, {f: 6, c: 53238}, {f: 3, c: 53245}, {f: 3, c: 53249},
- {f: 12, c: 53253}, {f: 6, c: 53266}, {f: 20, c: 53273}, {f: 6, c: 53294},
- {f: 2, c: 53302}, {f: 3, c: 53305}, {f: 7, c: 53309}, 53318, 53320,
- {f: 6, c: 53322}, {f: 3, c: 53329}, {f: 3, c: 53333}, {f: 7, c: 53337},
- {f: 11, c: 53345}, {f: 2, c: 53358}, {f: 3, c: 53361}, {f: 7, c: 53365},
- {f: 3, c: 53374}, {f: 34, c: 53378}, {f: 2, c: 53414}, {f: 3, c: 53417},
- {f: 7, c: 53421}, 53430, 53432, {f: 6, c: 53434}, {f: 2, c: 53442},
- {f: 3, c: 53445}, {f: 6, c: 53450}, 53458, {f: 6, c: 53462},
- {f: 2, c: 53470}, {f: 3, c: 53473}, {f: 7, c: 53477}, 53486,
- {f: 6, c: 53490}, {f: 20, c: 53497}, {f: 34, c: 53518}, {f: 2, c: 53554},
- {f: 3, c: 53557}, 53561, {f: 5, c: 53563}, 53570, {f: 6, c: 53574},
- {f: 2, c: 53582}, {f: 3, c: 53585}, {f: 7, c: 53589}, 53598, 53600,
- {f: 6, c: 53602}, {f: 3, c: 53609}, {f: 15, c: 53613}, {f: 7, c: 53629},
- {f: 3, c: 53637}, {f: 23, c: 53641}, {f: 2, c: 53666}, {f: 3, c: 53669},
- {f: 7, c: 53673}, 53682, 53684, {f: 4, c: 53686}, 53691, {f: 3, c: 53693},
- {f: 23, c: 53697}, {f: 27, c: 53721}, {f: 3, c: 53749}, {f: 14, c: 53753},
- 53768, {f: 6, c: 53770}, {f: 27, c: 53777}, {f: 2, c: 53806},
- {f: 3, c: 53809}, {f: 7, c: 53813}, 53822, 53824, {f: 6, c: 53826},
- {f: 19, c: 53833}, {f: 7, c: 53853}, {f: 27, c: 53861}, {f: 2, c: 53890},
- {f: 3, c: 53893}, {f: 7, c: 53897}, {f: 3, c: 53906}, {f: 6, c: 53910},
- {f: 3, c: 53917}, {f: 3, c: 53921}, {f: 7, c: 53925}, {f: 4, c: 53933},
- {f: 6, c: 53938}, {f: 2, c: 53946}, {f: 2, c: 53949}, 53953,
- {f: 5, c: 53955}, 53962, {f: 8, c: 53964}, {f: 3, c: 53973},
- {f: 3, c: 53977}, {f: 7, c: 53981}, {f: 10, c: 53990}, {f: 2, c: 54002},
- {f: 3, c: 54005}, {f: 7, c: 54009}, 54018, 54020, {f: 6, c: 54022}, 54031,
- {f: 3, c: 54033}, 54037, {f: 5, c: 54039}, 54046, {f: 3, c: 54050},
- {f: 2, c: 54054}, {f: 2, c: 54058}, {f: 3, c: 54061}, {f: 7, c: 54065},
- 54074, {f: 6, c: 54078}, {f: 54, c: 54086}, {f: 2, c: 54142},
- {f: 3, c: 54145}, {f: 7, c: 54149}, 54158, {f: 6, c: 54162},
- {f: 2, c: 54170}, {f: 3, c: 54173}, {f: 7, c: 54177}, 54186, 54188,
- {f: 6, c: 54190}, {f: 3, c: 54197}, {f: 3, c: 54201}, {f: 7, c: 54205},
- {f: 2, c: 54214}, {f: 6, c: 54218}, {f: 7, c: 54225}, {f: 8, c: 54233},
- 54242, {f: 8, c: 54244}, {f: 2, c: 54254}, {f: 3, c: 54257},
- {f: 7, c: 54261}, 54270, 54272, {f: 6, c: 54274}, {f: 20, c: 54281},
- {f: 34, c: 54302}, {f: 3, c: 54337}, {f: 23, c: 54341}, {f: 3, c: 54365},
- {f: 3, c: 54369}, {f: 8, c: 54373}, 54382, {f: 8, c: 54384},
- {f: 2, c: 54394}, {f: 2, c: 54397}, 54401, {f: 5, c: 54403}, 54410, 54412,
- {f: 6, c: 54414}, {f: 20, c: 54421}, {f: 34, c: 54442}, {f: 3, c: 54477},
- {f: 3, c: 54481}, {f: 7, c: 54485}, {f: 2, c: 54493}, {f: 8, c: 54496},
- {f: 3, c: 54505}, {f: 3, c: 54509}, {f: 7, c: 54513}, {f: 2, c: 54521},
- 54524, {f: 6, c: 54526}, {f: 3, c: 54533}, {f: 3, c: 54537},
- {f: 7, c: 54541}, 54550, {f: 36, c: 54552}, {f: 2, c: 54590},
- {f: 3, c: 54593}, {f: 7, c: 54597}, 54606, 54608, {f: 6, c: 54610},
- {f: 2, c: 54618}, {f: 3, c: 54621}, {f: 4, c: 54625}, {f: 2, c: 54630},
- 54634, 54636, {f: 6, c: 54638}, {f: 2, c: 54646}, {f: 3, c: 54649},
- {f: 7, c: 54653}, 54662, {f: 6, c: 54666}, {f: 20, c: 54673},
- {f: 34, c: 54694}, {f: 2, c: 54730}, {f: 3, c: 54733}, 54737,
- {f: 5, c: 54739}, 54746, 54748, {f: 6, c: 54750}, {f: 2, c: 54758},
- {f: 3, c: 54761}, {f: 7, c: 54765}, 54774, 54776, {f: 6, c: 54778},
- {f: 2, c: 54786}, {f: 3, c: 54789}, {f: 7, c: 54793}, 54802,
- {f: 6, c: 54806}, {f: 3, c: 54813}, {f: 3, c: 54817}, {f: 8, c: 54821},
- {f: 10, c: 54830}, {f: 2, c: 54842}, {f: 3, c: 54845}, {f: 4, c: 54849},
- {f: 2, c: 54854}, 54858, 54860, {f: 3, c: 54862}, {f: 2, c: 54866},
- {f: 2, c: 54870}, {f: 3, c: 54873}, {f: 10, c: 54877}, 54888,
- {f: 6, c: 54890}, {f: 2, c: 54898}, {f: 14, c: 54901}, 54916,
- {f: 6, c: 54918}, {f: 2, c: 54926}, {f: 3, c: 54929}, {f: 8, c: 54933},
- 54942, 54944, {f: 6, c: 54946}, {f: 3, c: 54953}, {f: 3, c: 54957},
- {f: 8, c: 54961}, 54970, {f: 8, c: 54972}, {f: 2, c: 54982},
- {f: 3, c: 54985}, {f: 4, c: 54989}, {f: 2, c: 54994}, {f: 2, c: 54997},
- 55000, {f: 6, c: 55002}, {f: 3, c: 55009}, {f: 3, c: 55013},
- {f: 7, c: 55017}, {f: 4, c: 55025}, {f: 6, c: 55030}, {f: 2, c: 55038},
- {f: 3, c: 55041}, {f: 12, c: 55045}, {f: 6, c: 55058}, {f: 2, c: 55066},
- {f: 3, c: 55069}, {f: 7, c: 55073}, 55082, 55084, {f: 6, c: 55086},
- {f: 2, c: 55094}, {f: 3, c: 55097}, {f: 7, c: 55101}, {f: 2, c: 55109},
- 55112, {f: 6, c: 55114}, {f: 2, c: 55122}, 55125, {f: 6, c: 55130}, 55138,
- 55140, {f: 3, c: 55142}, {f: 2, c: 55146}, {f: 3, c: 55149},
- {f: 3, c: 55153}, {f: 7, c: 55157}, {f: 3, c: 55166}, {f: 6, c: 55170},
- {f: 2, c: 55178}, {f: 3, c: 55181}, {f: 7, c: 55185}, 55194, 55196,
- {f: 6, c: 55198}],
- 'Adobe-CNS1': [{f: 95, c: 32}, {s: 3}, 12288, 65292, {f: 2, c: 12289}, 65294,
- 8226, 65307, 65306, 65311, 65281, 65072, 8230, 8229, 65104, 65380, 65106,
- 183, {f: 4, c: 65108}, 65372, 8211, 65073, 8212, {s: 4}, {f: 2, c: 65288},
- {f: 2, c: 65077}, 65371, 65373, {f: 2, c: 65079}, {f: 2, c: 12308},
- {f: 2, c: 65081}, {f: 2, c: 12304}, {f: 2, c: 65083}, {f: 2, c: 12298},
- {f: 2, c: 65085}, {f: 2, c: 12296}, {f: 2, c: 65087}, {f: 2, c: 12300},
- {f: 2, c: 65089}, {f: 2, c: 12302}, {f: 2, c: 65091}, {f: 6, c: 65113},
- {f: 2, c: 8216}, {f: 2, c: 8220}, {f: 2, c: 12317}, 8245, 8242, 65283,
- 65286, 65290, 8251, 167, 12291, 9675, 9679, 9651, 9650, 9678, 9734, 9733,
- 9671, 9670, 9633, 9632, 9661, 9660, 12963, 8453, 8254, 0, 65343, 0,
- {f: 2, c: 65097}, {f: 2, c: 65101}, {f: 2, c: 65099}, {f: 3, c: 65119},
- 65291, 65293, 215, 247, 177, 8730, 65308, 65310, 65309, {f: 2, c: 8806},
- 8800, 8734, 8786, 8801, {f: 5, c: 65122}, 8764, {f: 2, c: 8745}, 8869,
- 8736, 8735, 8895, 13266, 13265, 8747, 8750, 8757, 8756, 9792, 9794, 9793,
- 9737, 8593, 8595, 8594, 8592, {f: 2, c: 8598}, 8601, 8600, 8741, 8739, 0,
- 0, 65295, 65340, 65284, 165, 12306, {f: 2, c: 162}, 65285, 65312, 8451,
- 8457, {f: 3, c: 65129}, 13269, {f: 3, c: 13212}, 13262, 13217,
- {f: 2, c: 13198}, 13252, 176, [20825, 58834], [20827, 58835],
- [20830, 58837], [20829, 58836], 20833, 20835, 21991, [29929, 58044],
- [31950, 58191], {f: 8, c: 9601}, 9615, 9614, 9613, 9612, 9611, 9610, 9609,
- 9532, 9524, 9516, 9508, 9500, 9620, 9472, 9474, 9621, 9484, 9488, 9492,
- 9496, {f: 2, c: 9581}, 9584, 9583, 9552, 9566, 9578, 9569, {f: 2, c: 9698},
- 9701, 9700, {f: 3, c: 9585}, {f: 10, c: 65296}, {f: 10, c: 8544},
- {f: 9, c: 12321}, 0, [21316, 57443], 0, {f: 26, c: 65313},
- {f: 26, c: 65345}, {f: 17, c: 913}, {f: 7, c: 931}, {f: 17, c: 945},
- {f: 7, c: 963}, {f: 37, c: 12549}, 729, 714, 711, 715, [9312, 63153],
- [9313, 63154], [9314, 63155], [9315, 63156], [9316, 63157], [9317, 63158],
- [9318, 63159], [9319, 63160], [9320, 63161], [9321, 63162], [9332, 63163],
- [9333, 63164], [9334, 63165], [9335, 63166], [9336, 63167], [9337, 63168],
- [9338, 63169], [9339, 63170], [9340, 63171], [9341, 63172], [8560, 63173],
- [8561, 63174], [8562, 63175], [8563, 63176], [8564, 63177], [8565, 63178],
- [8566, 63179], [8567, 63180], [8568, 63181], [8569, 63182], [12033, 20008],
- [12034, 20022, 63183], [12035, 20031, 63184], [12037, 20101, 63185],
- [12039, 20128, 63186], [12044, 20866, 63187], [12045, 20886, 63188],
- [12046, 20907, 63189], [12051, 21241, 63190], [12054, 21304, 63191],
- [12057, 21353, 63192], [12059, 21430, 63193],
- [12065, 12066, 22786, 22794, 63194], [12071, 23424, 63195],
- [12078, 24027, 63196], [12083, 24186, 63197], [12084, 24191, 63198],
- [12085, 24308], [12089, 24400, 63200], [12090, 24417, 63201],
- [12097, 25908, 63202], [12102, 26080], [12135, 30098, 63204],
- [12136, 30326], [12193, 36789, 63206], [12202, 38582], {f: 32, c: 9216},
- 9249, [12032, 19968], [12036, 20057], 19969, 19971, 20035, 20061, 20102,
- [12038, 20108], [12040, 20154], [12041, 20799], [12042, 20837],
- [12043, 20843], [12047, 20960], [12049, 20992], 20993, [12050, 21147],
- [12052, 21269], [12055, 21313], [12056, 21340], [12060, 21448], 19977,
- 19979, 19976, 19978, 20011, 20024, 20961, 20037, 20040, 20063, 20062,
- 20110, 20129, [20800, 64012], 20995, 21242, 21315, 21449, [12061, 21475],
- [12063, 22303], [12064, 22763], [12067, 22805], [12068, 22823],
- [12069, 22899], [12070, 23376], 23377, 23379, [12072, 23544],
- [12073, 23567], [12074, 23586], [12075, 23608], [12077, 23665], 24029,
- [12079, 24037], [12080, 24049], {f: 2, c: 24050}, [12081, 24062],
- [12082, 24178], [12086, 24318], [12087, 24331], [12088, 24339], 25165,
- 19985, 19984, 19981, 20013, 20016, 20025, 20043, 23609, 20104, 20113,
- 20117, 20114, 20116, 20130, 20161, 20160, 20163, {f: 2, c: 20166}, 20173,
- {f: 2, c: 20170}, 20164, 20803, 20801, 20839, {f: 2, c: 20845}, 20844,
- 20887, 20982, {f: 3, c: 20998}, 21243, {f: 2, c: 21246}, 21270, 21305,
- 21320, 21319, 21317, 21342, 21380, 21451, 21450, 21453, 22764, 22825,
- 22827, 22826, 22829, 23380, 23569, 23588, 23610, 23663, 24052, 24187,
- 24319, {f: 2, c: 24340}, [12092, 24515], [12093, 25096], [12094, 25142],
- [12095, 25163], 25166, [12096, 25903], [12098, 25991], [12099, 26007],
- [12100, 26020], [12101, 26041], [12103, 26085], [12104, 26352],
- [12105, 26376], [12106, 26408], [12107, 27424], [12108, 27490],
- [12109, 27513], [12111, 27595], [12112, 27604], [12113, 27611],
- [12114, 27663], [12116, 27700], [12117, 28779], [12118, 29226],
- [12119, 29238], [12120, 29243], [12122, 29255], [12123, 29273],
- [12124, 29275], [12125, 29356], 29579, 19993, 19990, 19989, 19988, 19992,
- 20027, 20045, 20047, 20046, 20197, 20184, {f: 4, c: 20180},
- {f: 2, c: 20195}, 20185, 20190, 20805, 20804, {f: 2, c: 20873}, 20908,
- {f: 2, c: 20985}, 20984, 21002, 21152, 21151, [21253, 57435], 21254, 21271,
- 21277, 20191, 21322, 21321, 21345, 21344, 21359, 21358, 21435, 21487,
- 21476, 21491, 21484, 21486, 21481, 21480, 21500, 21496, 21493, 21483,
- 21478, 21482, 21490, 21489, 21488, 21477, 21485, 21499, 22235, 22234,
- 22806, 22830, 22833, 22900, 22902, 23381, 23427, 23612, 24040, 24039,
- 24038, {f: 2, c: 24066}, 24179, 24188, 24321, 24344, 24343, 24517, 25098,
- {f: 2, c: 25171}, 25170, 25169, 26021, 26086, 26414, 26412,
- {f: 2, c: 26410}, 26413, 27491, 27597, 27665, 27664, 27704, 27713, 27712,
- 27710, 29359, [12126, 29572], [12127, 29577], [12128, 29916],
- [12129, 29926], [12130, 29976], [12131, 29983], [12132, 29992], 29993,
- [12133, 30000], {f: 3, c: 30001}, [12134, 30091], [12137, 30333],
- [12138, 30382], [12139, 30399], [12140, 30446], [12141, 30683],
- [12142, 30690], [12143, 30707], [12144, 31034], [12146, 31166],
- [12147, 31348], [12148, 31435], {f: 2, c: 19998}, {f: 2, c: 20050}, 20073,
- 20121, 20132, 20134, 20133, 20223, 20233, 20249, 20234, 20245, 20237,
- {f: 2, c: 20240}, 20239, 20210, 20214, 20219, 20208, 20211, 20221, 20225,
- 20235, 20809, 20807, 20806, 20808, 20840, 20849, 20877, 20912, 21015,
- {f: 2, c: 21009}, 21006, 21014, 21155, 21256, 21281, 21280,
- {f: 2, c: 21360}, 21513, 21519, 21516, 21514, 21520, 21505, 21515, 21508,
- 21521, 21517, 21512, 21507, 21518, 21510, 21522, 22240, 22238, 22237,
- 22323, 22320, 22312, 22317, 22316, 22319, 22313, {f: 2, c: 22809},
- {f: 2, c: 22839}, 22916, 22904, 22915, 22909, 22905, 22914, 22913,
- {f: 2, c: 23383}, {f: 2, c: 23431}, 23429, 23433, 23546, 23574, 23673,
- 24030, 24070, 24182, 24180, 24335, 24347, 24537, 24534, 25102,
- {f: 2, c: 25100}, 25104, 25187, 25179, 25176, 25910, 26089, 26088,
- {f: 2, c: 26092}, {f: 2, c: 26354}, 26377, 26429, 26420, 26417, 26421,
- 27425, 27492, 27515, 27670, 27741, 27735, 27737, {f: 2, c: 27743}, 27728,
- 27733, 27745, 27739, {f: 2, c: 27725}, 28784, 29279, 29277, 30334,
- [12149, 31481], [12150, 31859], [12151, 31992], [12152, 32566],
- [12154, 32650], [12155, 32701], [12156, 32769], 32771, [12157, 32780],
- [12158, 32786], [12159, 32819], [12160, 32895], [12161, 32905],
- {f: 2, c: 32907}, [12162, 33251], [12163, 33258], [12164, 33267],
- [12165, 33276], [12166, 33292], [12167, 33307], [12168, 33311],
- [12169, 33390], [12170, 33394], 33406, [12173, 34411], [12174, 34880],
- [12175, 34892], [12176, 34915], 35199, 38433, 20018, 20136, 20301, 20303,
- 20295, 20311, 20318, 20276, 20315, 20309, 20272, {f: 2, c: 20304}, 20285,
- 20282, 20280, 20291, 20308, 20284, 20294, 20323, 20316, 20320, 20271,
- 20302, 20278, 20313, 20317, 20296, 20314, 20812, 20811, 20813, 20853,
- {f: 2, c: 20918}, 21029, 21028, {f: 2, c: 21033}, 21032, 21163,
- {f: 2, c: 21161}, 21164, 21283, 21363, 21365, 21533, 21549, 21534, 21566,
- 21542, 21582, 21543, 21574, 21571, 21555, 21576, 21570, 21531, 21545,
- 21578, 21561, 21563, 21560, 21550, {f: 2, c: 21557}, 21536, 21564, 21568,
- 21553, 21547, 21535, 21548, 22250, 22256, 22244, 22251, 22346, 22353,
- 22336, 22349, 22343, 22350, 22334, 22352, 22351, 22331, 22767, 22846,
- 22941, 22930, 22952, 22942, 22947, 22937, 22934, 22925, 22948, 22931,
- 22922, 22949, 23389, 23388, {f: 2, c: 23386}, 23436, 23435, 23439, 23596,
- {f: 2, c: 23616}, 23615, 23614, {f: 2, c: 23696}, 23700, 23692, 24043,
- 24076, 24207, 24199, 24202, 24311, 24324, 24351, 24420, 24418, 24439,
- 24441, 24536, 24524, 24535, 24525, 24561, 24555, 24568, 24554, 25106,
- 25105, 25220, 25239, 25238, 25216, 25206, 25225, 25197, 25226, 25212,
- 25214, 25209, 25203, 25234, 25199, 25240, 25198, 25237, 25235, 25233,
- 25222, 25913, 25915, 25912, 26097, 26356, 26463, {f: 4, c: 26446}, 26460,
- 26454, [26462, 57801], 26441, 26438, 26464, 26451, 26455, 27493, 27599,
- 27714, 27742, 27801, 27777, {f: 2, c: 27784}, 27781, 27803, 27754, 27770,
- 27792, 27760, 27788, 27752, 27798, 27794, 27773, 27779, 27762, 27774,
- 27764, 27782, 27766, 27789, 27796, 27800, 27778, 28790, {f: 2, c: 28796},
- 28792, 29282, 29281, 29280, 29380, 29378, 29590, 29996, 29995,
- {f: 2, c: 30007}, 30338, 30447, 30691, 31169, 31168, 31167, 31350, 31995,
- 32597, 32918, 32915, 32925, 32920, 32923, 32922, 32946, 33391, 33426,
- 33419, 33421, [12178, 35211], [12179, 35282], [12180, 35328],
- [12181, 35895], [12182, 35910], [12183, 35925], [12185, 35997],
- [12186, 36196], [12187, 36208], [12188, 36275], [12189, 36523],
- [12190, 36554], [12191, 36763], [12192, 36784], 36802, 36806, 36805, 36804,
- 24033, [12194, 37009], 37026, 37034, 37030, 37027, [12195, 37193],
- [12196, 37318], [12197, 37324], 38450, 38446, 38449, 38442, 38444, 20006,
- 20054, 20083, 20107, 20123, 20126, {f: 2, c: 20139}, 20335, 20381, 20365,
- 20339, 20351, 20332, 20379, 20363, 20358, 20355, 20336, 20341, 20360,
- 20329, 20347, 20374, 20350, 20367, 20369, 20346, 20820, 20818, 20821,
- 20841, 20855, 20854, 20856, 20925, 20989, 21051, 21048, 21047, 21050,
- 21040, 21038, 21046, 21057, 21182, 21179, 21330, 21332, 21331, 21329,
- 21350, {f: 3, c: 21367}, 21462, 21460, 21463, 21619, 21621, 21654, 21624,
- 21653, 21632, 21627, 21623, 21636, 21650, 21638, 21628, 21648, 21617,
- 21622, 21644, 21658, 21602, 21608, 21643, 21629, 21646, 22266, 22403,
- 22391, 22378, 22377, 22369, 22374, 22372, 22396, 22812, 22857,
- {f: 2, c: 22855}, 22852, 22868, 22974, 22971, 22996, 22969, 22958, 22993,
- 22982, 22992, 22989, 22987, 22995, 22986, 22959, 22963, 22994, 22981,
- 23391, 23396, 23395, 23447, 23450, 23448, 23452, 23449, 23451, 23578,
- 23624, {f: 2, c: 23621}, 23735, 23713, 23736, 23721, 23723, 23729, 23731,
- 24088, 24090, 24086, 24085, 24091, 24081, 24184, 24218, 24215, 24220,
- {f: 2, c: 24213}, 24310, {f: 2, c: 24358}, 24361, {f: 2, c: 24448}, 24447,
- 24444, 24541, 24544, 24573, 24565, 24575, 24591, 24596, 24623, 24629,
- 24598, 24618, 24597, 24609, 24615, 24617, 24619, 24603, 25110, 25109,
- 25151, 25150, 25152, 25215, 25289, 25292, 25284, 25279, 25282, 25273,
- 25298, 25307, 25259, {f: 2, c: 25299}, 25291, 25288, 25256, 25277, 25276,
- [25296, 60582], 25305, 25287, 25293, 25269, 25306, 25265, 25304,
- {f: 2, c: 25302}, 25286, 25260, [25294, 61010], 25918, 26023, 26044, 26106,
- 26132, 26131, 26124, 26118, 26114, 26126, 26112, 26127, 26133, 26122,
- 26119, 26381, 26379, 26477, 26507, 26517, 26481, 26524, 26483, 26487,
- 26503, 26525, 26519, {f: 2, c: 26479}, 26495, 26505, 26494, 26512, 26485,
- 26522, 26515, 26492, 26474, 26482, 27427, {f: 2, c: 27494}, 27519, 27667,
- 27675, 27875, 27880, 27891, 27825, 27852, 27877, 27827, {f: 2, c: 27837},
- 27836, 27874, 27819, 27861, 27859, 27832, 27844, 27833, 27841, 27822,
- 27863, 27845, 27889, 27839, 27835, 27873, 27867, 27850, 27820, 27887,
- 27868, 27862, 27872, 28821, 28814, 28818, 28810, 28825, {f: 2, c: 29228},
- 29240, 29256, 29287, 29289, 29376, 29390, 29401, 29399, 29392, 29609,
- 29608, 29599, 29611, 29605, 30013, 30109, {f: 2, c: 30105}, 30340, 30402,
- 30450, 30452, 30693, 30717, 31038, {f: 2, c: 31040}, 31177, 31176, 31354,
- 31353, 31482, 31998, 32596, 32652, 32651, [32773, 58236], 32954, 32933,
- 32930, 32945, 32929, 32939, 32937, 32948, 32938, 32943, 33253, 33278,
- 33293, 33459, 33437, 33433, 33453, 33469, 33439, 33465, 33457, 33452,
- 33445, 33455, 33464, 33443, 33456, 33470, 33463, 34382, 34417, 21021,
- 34920, 36555, 36814, 36820, 36817, 37045, 37048, 37041, 37046, 37319,
- [12198, 37329], [12199, 38263], [12200, 38272], [12201, 38428], 38464,
- 38463, 38459, 38468, 38466, [12203, 38585], [12204, 38632], 38738,
- [12206, 38750], 20127, {f: 2, c: 20141}, 20449, 20405, 20399, 20415, 20448,
- 20433, 20431, 20445, 20419, 20406, 20440, 20447, 20426, 20439, 20398,
- 20432, 20420, 20418, 20442, 20430, 20446, 20407, 20823, 20882, 20881,
- 20896, 21070, 21059, 21066, 21069, 21068, 21067, 21063, 21191, 21193,
- 21187, 21185, 21261, 21335, 21371, 21402, 21467, 21676, 21696, 21672,
- 21710, 21705, 21688, 21670, 21683, 21703, 21698, 21693, 21674, 21697,
- 21700, 21704, 21679, 21675, 21681, 21691, 21673, 21671, 21695, 22271,
- 22402, 22411, 22432, 22435, 22434, 22478, 22446, 22419, 22869, 22865,
- 22863, 22862, 22864, 23004, 23000, 23039, 23011, 23016, 23043, 23013,
- 23018, 23002, 23014, 23041, 23035, 23401, 23459, 23462, 23460, 23458,
- 23461, 23553, {f: 2, c: 23630}, 23629, 23627, 23769, 23762, 24055, 24093,
- 24101, 24095, 24189, 24224, 24230, 24314, 24328, 24365, 24421, 24456,
- 24453, {f: 2, c: 24458}, 24455, 24460, 24457, 24594, 24605, 24608, 24613,
- 24590, 24616, 24653, 24688, 24680, [24674, 60712], 24646, 24643, 24684,
- 24683, 24682, 24676, 25153, 25308, 25366, 25353, 25340, 25325, 25345,
- 25326, 25341, 25351, 25329, 25335, 25327, 25324, 25342, 25332, 25361,
- 25346, 25919, 25925, 26027, 26045, 26082, 26149, 26157, 26144, 26151,
- 26159, 26143, 26152, 26161, 26148, 26359, 26623, 26579, 26609, 26580,
- 26576, 26604, 26550, 26543, 26613, 26601, 26607, 26564, 26577, 26548,
- 26586, 26597, 26552, 26575, 26590, 26611, 26544, 26585, 26594, 26589,
- 26578, 27498, 27523, 27526, 27573, 27602, 27607, 27679, 27849, 27915,
- 27954, 27946, 27969, 27941, 27916, 27953, 27934, 27927, 27963,
- {f: 2, c: 27965}, 27958, 27931, 27893, 27961, 27943, 27960, 27945, 27950,
- 27957, 27918, 27947, 28843, 28858, 28851, 28844, 28847, 28845, 28856,
- 28846, 28836, 29232, 29298, 29295, 29300, 29417, {f: 2, c: 29408}, 29623,
- 29642, 29627, 29618, 29645, 29632, 29619, 29978, 29997, 30031, 30028,
- 30030, 30027, 30123, {f: 2, c: 30116}, {f: 2, c: 30114}, 30328,
- {f: 3, c: 30342}, 30408, 30406, 30403, 30405, 30465, 30457, 30456, 30473,
- 30475, 30462, 30460, 30471, 30684, 30722, 30740, {f: 2, c: 30732}, 31046,
- 31049, 31048, 31047, {f: 2, c: 31161}, {f: 2, c: 31185}, 31179, 31359,
- 31361, 31487, 31485, 31869, 32002, 32005, 32000, 32009, 32007, 32004,
- 32006, 32568, 32654, 32703, 32784, 32781, 32785, 32822, 32982, 32997,
- 32986, {f: 2, c: 32963}, 32972, 32993, 32987, 32974, 32990, 32996, 32989,
- 33268, 33314, 33511, 33539, 33541, 33507, 33499, 33510, 33540, 33509,
- 33538, 33545, 33490, 33495, 33521, 33537, 33500, 33492, 33489, 33502,
- 33491, 33503, 33519, 33542, 34384, 34425, 34427, 34426, 34893, 34923,
- 35201, 35284, 35336, {f: 2, c: 35330}, 35998, 36000, 36212, 36211, 36276,
- 36557, 36556, 36848, 36838, 36834, 36842, 36837, 36845, 36843, 36836,
- 36840, 37066, 37070, 37057, 37059, 37195, 37194, 37325, 38274, 38480,
- {f: 3, c: 38475}, [12207, 38754], [12208, 38761], [12209, 38859],
- [12210, 38893], [12211, 38899], [12212, 38913], [12213, 39080],
- [12214, 39131], [12215, 39135], [12216, 39318], [12217, 39321], 20056,
- 20147, {f: 2, c: 20492}, 20515, 20463, 20518, 20517, 20472, [20521, 57375],
- 20502, 20486, 20540, 20511, 20506, 20498, 20497, 20474, 20480, 20500,
- 20520, 20465, 20513, 20491, 20505, 20504, 20467, 20462, 20525, 20522,
- 20478, 20523, 20489, 20860, {f: 2, c: 20900}, 20898, 20941, 20940, 20934,
- 20939, 21078, 21084, 21076, 21083, 21085, 21290, [21375, 57459], 21407,
- 21405, 21471, 21736, 21776, 21761, 21815, 21756, 21733, 21746, 21766,
- 21754, 21780, 21737, 21741, 21729, 21769, 21742, 21738, 21734, 21799,
- 21767, 21757, 21775, {f: 2, c: 22275}, 22466, 22484, 22475, 22467, 22537,
- 22799, {f: 2, c: 22871}, 22874, 23057, 23064, 23068, 23071, 23067, 23059,
- 23020, 23072, 23075, 23081, 23077, 23052, 23049, 23403, 23640, 23472,
- 23475, 23478, 23476, 23470, 23477, 23481, 23480, 23556, 23633, 23637,
- 23632, 23789, 23805, 23803, 23786, 23784, 23792, 23798, 23809, 23796,
- 24046, 24109, 24107, 24235, 24237, 24231, 24369, 24466, 24465, 24464,
- 24665, 24675, 24677, 24656, 24661, 24685, 24681, 24687, 24708, 24735,
- 24730, 24717, 24724, 24716, 24709, 24726, 25159, 25331, 25352, 25343,
- 25422, 25406, 25391, 25429, 25410, 25414, 25423, 25417, 25402, 25424,
- 25405, {f: 2, c: 25386}, 25384, 25421, 25420, {f: 2, c: 25928}, 26009,
- 26049, 26053, 26178, 26185, 26191, 26179, 26194, 26188, 26181, 26177,
- 26360, {f: 2, c: 26388}, 26391, 26657, 26680, 26696, 26694, 26707, 26681,
- 26690, 26708, 26665, 26803, 26647, 26700, 26705, 26685, 26612, 26704,
- 26688, 26684, 26691, 26666, 26693, 26643, 26648, 26689, 27530, 27529,
- 27575, 27683, {f: 2, c: 27687}, 27686, 27684, 27888, 28010, 28053, 28040,
- 28039, 28006, 28024, 28023, 27993, 28051, 28012, 28041, 28014, 27994,
- 28020, 28009, 28044, 28042, 28025, 28037, 28005, 28052, 28874, 28888,
- 28900, 28889, 28872, 28879, 29241, 29305, 29436, 29433, 29437, 29432,
- 29431, 29574, 29677, 29705, 29678, 29664, 29674, 29662, 30036, 30045,
- 30044, 30042, 30041, 30142, 30149, 30151, {f: 2, c: 30130}, 30141, 30140,
- 30137, 30146, 30136, 30347, 30384, 30410, {f: 2, c: 30413}, 30505,
- {f: 2, c: 30495}, 30504, 30697, 30768, 30759, 30776, 30749, 30772, 30775,
- 30757, 30765, 30752, 30751, 30770, 31061, 31056, 31072, 31071, 31062,
- 31070, 31069, 31063, 31066, 31204, [31203, 60418], 31207, 31199, 31206,
- 31209, 31192, 31364, 31368, 31449, 31494, 31505, 31881, 32033, 32023,
- 32011, 32010, 32032, 32034, 32020, 32016, 32021, 32026, 32028, 32013,
- 32025, 32027, 32570, 32607, 32660, 32709, 32705, 32774, 32772, 32792,
- 32789, 32793, 32791, 32829, 32831, 33009, 33026, 33008, 33029, 33005,
- 33012, 33030, 33016, 33011, 33032, 33021, 33034, 33020, 33007, 33261,
- 33260, 33280, 33296, {f: 2, c: 33322}, 33320, 33324, 33467, 33579, 33618,
- 33620, 33610, 33592, 33616, 33609, 33589, 33588, 33615, 33586, 33593,
- 33590, 33559, 33600, 33585, 33576, 33603, 34388, 34442, 34474, 34451,
- 34468, 34473, 34444, 34467, 34460, 34928, 34935, {f: 2, c: 34945}, 34941,
- 34937, 35352, 35344, 35342, 35340, 35349, 35338, 35351, 35347, 35350,
- 35343, 35345, 35912, 35962, 35961, {f: 2, c: 36001}, [36215, 58442], 36524,
- 36562, 36564, 36559, 36785, 36865, 36870, 36855, 36864, 36858, 36852,
- 36867, 36861, 36869, 36856, 37013, 37089, 37085, 37090, 37202, 37197,
- 37196, 37336, 37341, 37335, 37340, 37337, 38275, {f: 2, c: 38498}, 38497,
- 38491, 38493, 38500, 38488, 38494, 38587, 39138, [12218, 39340],
- [12219, 39592], [12220, 39640], [12222, 39717], [12224, 39730],
- [12225, 39740], 20094, 20602, [20605, 57382], 20572, 20551, 20547, 20556,
- 20570, 20553, 20581, 20598, 20558, 20565, 20597, 20596, 20599, 20559,
- 20495, 20591, 20589, 20828, 20885, 20976, 21098, 21103, 21202, 21209,
- 21208, 21205, 21264, 21263, 21273, {f: 2, c: 21311}, 21310, 21443, 26364,
- 21830, 21866, 21862, 21828, 21854, 21857, 21827, 21834, 21809, 21846,
- 21839, 21845, 21807, 21860, 21816, 21806, 21852, 21804, 21859, 21811,
- 21825, 21847, 22280, 22283, 22281, 22495, 22533, 22538, 22534, 22496,
- 22500, 22522, 22530, 22581, 22519, 22521, 22816, 22882, 23094, 23105,
- 23113, 23142, 23146, 23104, 23100, 23138, 23130, 23110, 23114, 23408,
- 23495, 23493, 23492, 23490, 23487, 23494, 23561, 23560, 23559, 23648,
- {f: 2, c: 23644}, 23815, 23814, 23822, 23835, 23830, 23842, 23825, 23849,
- 23828, 23833, 23844, 23847, 23831, 24034, 24120, 24118, 24115, 24119,
- {f: 2, c: 24247}, 24246, 24245, 24254, 24373, 24375, 24407, 24428, 24425,
- 24427, 24471, 24473, 24478, 24472, 24481, 24480, 24476, 24703, 24739,
- 24713, 24736, 24744, 24779, 24756, 24806, 24765, 24773, 24763, 24757,
- 24796, 24764, 24792, 24789, 24774, 24799, 24760, 24794, 24775,
- {f: 2, c: 25114}, 25160, 25504, 25511, 25458, 25494, 25506, 25509, 25463,
- 25447, 25496, 25514, 25457, 25513, 25481, 25475, 25499, 25451, 25512,
- 25476, 25480, 25497, 25505, 25516, 25490, 25487, 25472, 25467, 25449,
- 25448, 25466, 25949, 25942, 25937, 25945, 25943, 21855, 25935, 25944,
- 25941, 25940, 26012, 26011, 26028, 26063, {f: 2, c: 26059}, 26062, 26205,
- 26202, 26212, 26216, 26214, 26206, 26361, 21207, 26395, 26753, 26799,
- 26786, 26771, 26805, 26751, 26742, 26801, 26791, 26775, 26800, 26755,
- 26820, 26797, 26758, 26757, 26772, 26781, 26792, 26783, 26785, 26754,
- 27442, 27578, {f: 2, c: 27627}, 27691, 28046, 28092, 28147, 28121, 28082,
- 28129, 28108, 28132, 28155, 28154, 28165, 28103, 28107, 28079, 28113,
- 28078, 28126, 28153, 28088, 28151, 28149, 28101, 28114, 28186, 28085,
- 28122, 28139, 28120, 28138, 28145, 28142, 28136, 28102, 28100, 28074,
- 28140, 28095, 28134, 28921, {f: 2, c: 28937}, 28925, 28911, 29245, 29309,
- 29313, 29468, 29467, 29462, 29459, 29465, 29575, 29701, 29706, 29699,
- 29702, 29694, 29709, 29920, {f: 2, c: 29942}, 29980, 29986,
- {f: 2, c: 30053}, 30050, 30064, 30095, {f: 2, c: 30164}, 30133, 30154,
- 30157, 30350, 30420, 30418, 30427, 30519, 30526, 30524, 30518, 30520,
- 30522, 30827, 30787, 30798, 31077, 31080, 31085, 31227, 31378, 31381,
- 31520, 31528, 31515, 31532, 31526, 31513, 31518, 31534, 31890, 31895,
- 31893, 32070, 32067, 32113, 32046, 32057, 32060, 32064, 32048, 32051,
- 32068, 32047, 32066, 32050, 32049, 32573, 32670, 32666, 32716, 32718,
- 32722, 32796, 32842, 32838, 33071, 33046, 33059, 33067, 33065, 33072,
- 33060, 33282, 33333, 33335, 33334, 33337, 33678, 33694, 33688, 33656,
- 33698, 33686, 33725, 33707, 33682, 33674, 33683, 33673, 33696, 33655,
- {f: 2, c: 33659}, 33670, 33703, 34389, 24426, 34503, 34496, 34486, 34500,
- 34485, 34502, 34507, 34481, 34479, 34505, 34899, 34974, 34952, 34987,
- 34962, 34966, 34957, 34955, 35219, 35215, 35370, 35357, 35363, 35365,
- 35377, 35373, 35359, 35355, 35362, 35913, 35930, 36009, 36012, 36011,
- 36008, 36010, 36007, 36199, 36198, 36286, 36282, 36571, 36575, 36889,
- 36877, 36890, 36887, 36899, 36895, 36893, 36880, 36885, 36894, 36896,
- 36879, 36898, 36886, 36891, 36884, 37096, 37101, [37117, 58488], 37207,
- 37326, 37365, 37350, 37347, 37351, 37357, 37353, 38281, 38506, 38517,
- 38515, 38520, 38512, 38516, {f: 2, c: 38518}, 38508, 38592, 38634, 38633,
- 31456, 31455, {f: 2, c: 38914}, [12226, 39770], [12227, 40165],
- [12228, 40565], [12229, 40575], [12230, 40613], [12231, 40635], 20642,
- 20621, 20613, 20633, 20625, 20608, 20630, 20632, 20634, 26368, 20977,
- 21106, {f: 2, c: 21108}, 21097, 21214, 21213, 21211, 21338, 21413, 21883,
- 21888, 21927, 21884, 21898, 21917, 21912, 21890, 21916, 21930, 21908,
- 21895, 21899, 21891, 21939, 21934, 21919, 21822, 21938, 21914, 21947,
- 21932, 21937, 21886, 21897, 21931, 21913, 22285, 22575, 22570, 22580,
- 22564, {f: 2, c: 22576}, 22561, 22557, 22560, {f: 2, c: 22777}, 22880,
- [23159, 57587], 23194, 23167, 23186, 23195, 23207, 23411, 23409, 23506,
- 23500, 23507, 23504, {f: 2, c: 23562}, 23601, 23884, 23888, 23860, 23879,
- 24061, 24133, 24125, 24128, 24131, 24190, 24266, {f: 2, c: 24257}, 24260,
- 24380, 24429, {f: 2, c: 24489}, 24488, 24785, 24801, 24754, 24758, 24800,
- 24860, 24867, 24826, 24853, 24816, 24827, 24820, 24936, 24817, 24846,
- 24822, 24841, 24832, 24850, 25119, 25161, 25507, 25484, 25551, 25536,
- 25577, 25545, 25542, 25549, 25554, 25571, 25552, 25569, 25558,
- {f: 2, c: 25581}, 25462, 25588, 25578, 25563, 25682, 25562, 25593, 25950,
- 25958, {f: 2, c: 25954}, 26001, 26000, 26031, 26222, 26224, [26228, 57786],
- 26230, 26223, 26257, 26234, 26238, 26231, {f: 2, c: 26366}, 26399, 26397,
- 26874, 26837, 26848, 26840, 26839, 26885, 26847, 26869, 26862, 26855,
- 26873, 26834, 26866, 26851, 26827, 26829, 26893, 26898, 26894, 26825,
- 26842, 26990, 26875, 27454, 27450, 27453, 27544, 27542, 27580, 27631,
- {f: 2, c: 27694}, 27692, [28207, 57904], 28216, 28244, 28193, 28210, 28263,
- 28234, 28192, 28197, 28195, 28187, 28251, 28248, 28196, 28246, 28270,
- 28205, 28198, 28271, 28212, 28237, 28218, 28204, 28227, [28189, 57901],
- 28222, 28363, 28297, 28185, 28238, 28259, 28228, 28274, 28265, 28255,
- {f: 2, c: 28953}, 28966, 28976, 28961, 28982, [29038, 57958], 28956, 29260,
- 29316, 29312, 29494, 29477, 29492, 29481, 29754, 29738, 29747, 29730,
- 29733, {f: 2, c: 29749}, 29748, 29743, 29723, 29734, 29736,
- {f: 2, c: 29989}, 30059, 30058, 30178, 30171, 30179, 30169, 30168, 30174,
- 30176, {f: 2, c: 30331}, 30358, 30355, 30388, 30428, 30543, 30701, 30813,
- 30828, 30831, 31245, 31240, 31243, 31237, 31232, 31384, 31383, 31382,
- 31461, 31459, 31561, 31574, 31558, 31568, 31570, 31572, 31565, 31563,
- 31567, [31569, 60510], 31903, 31909, 32094, 32080, 32104, 32085, 32043,
- 32110, 32114, 32097, 32102, 32098, 32112, 32115, 21892, {f: 2, c: 32724},
- 32779, 32850, 32901, 33109, 33108, 33099, 33105, 33102, 33081, 33094,
- 33086, 33100, 33107, 33140, 33298, 33308, 33769, 33795, 33784, 33805,
- 33760, 33733, 33803, [33729, 58309], 33775, 33777, 33780, 33879, 33802,
- 33776, 33804, 33740, 33789, 33778, 33738, 33848, 33806, 33796, 33756,
- 33799, 33748, 33759, 34395, 34527, 34521, 34541, 34516, 34523, 34532,
- 34512, 34526, 34903, {f: 2, c: 35009}, 34993, 35203, 35222, 35387, 35424,
- 35413, 35422, 35388, 35393, 35412, 35419, 35408, 35398, 35380, 35386,
- 35382, 35414, 35937, 35970, 36015, 36028, 36019, 36029, 36033, 36027,
- 36032, 36020, 36023, 36022, 36031, 36024, 36234, 36229, 36225, 36302,
- 36317, 36299, 36314, 36305, 36300, 36315, 36294, 36603, 36600, 36604,
- 36764, 36910, 36917, 36913, 36920, 36914, 36918, 37122, 37109, 37129,
- 37118, 37219, 37221, 37327, {f: 2, c: 37396}, 37411, 37385, 37406, 37389,
- 37392, 37383, 37393, 38292, 38287, 38283, 38289, 38291, 38290, 38286,
- 38538, 38542, 38539, 38525, {f: 2, c: 38533}, 38541, 38514, 38532, 38593,
- 38597, 38596, {f: 2, c: 38598}, 38639, 38642, 38860, {f: 2, c: 38917},
- 38920, 39143, 39146, 39151, 39145, 39154, 39149, 39342, 39341,
- [12232, 40643], [12233, 40653], [12234, 40657], 20098, 20653, 20661,
- {f: 2, c: 20658}, 20677, 20670, 20652, 20663, 20667, 20655, 20679, 21119,
- 21111, 21117, 21215, 21222, 21220, {f: 2, c: 21218}, 21295, 21983, 21992,
- 21971, 21990, 21966, 21980, 21959, 21969, {f: 2, c: 21987}, 21999, 21978,
- 21985, {f: 2, c: 21957}, 21989, 21961, {f: 2, c: 22290}, 22622, 22609,
- 22616, 22615, 22618, 22612, 22635, 22604, 22637, 22602, 22626, 22610,
- 22603, 22887, 23233, 23241, 23244, 23230, 23229, 23228, 23219, 23234,
- 23218, 23913, 23919, 24140, 24185, 24265, 24264, 24338, 24409, 24492,
- 24494, 24858, 24847, 24904, 24863, 24819, 24859, 24825, 24833, 24840,
- 24910, 24908, 24900, 24909, 24894, 24884, 24871, 24845, 24838, 24887,
- {f: 2, c: 25121}, 25619, 25662, 25630, 25642, 25645, 25661, 25644, 25615,
- 25628, 25620, 25613, 25654, {f: 2, c: 25622}, 25606, 25964, 26015, 26032,
- 26263, 26249, {f: 2, c: 26247}, 26262, 26244, 26264, 26253, 26371, 27028,
- 26989, 26970, 26999, 26976, 26964, 26997, 26928, 27010, 26954, 26984,
- 26987, 26974, 26963, 27001, 27014, 26973, 26979, 26971, 27463, 27506,
- 27584, 27583, 27603, 27645, 28322, 28335, 28371, 28342, 28354, 28304,
- 28317, 28359, 28357, 28325, 28312, 28348, 28346, 28331, 28369, 28310,
- 28316, 28356, 28372, 28330, 28327, 28340, 29006, 29017, 29033, 29028,
- 29001, 29031, 29020, 29036, 29030, 29004, 29029, 29022, 28998, 29032,
- 29014, 29242, 29266, 29495, 29509, 29503, 29502, 29807, 29786, 29781,
- 29791, 29790, 29761, 29759, 29785, 29787, [29788, 58019], 30070, 30072,
- 30208, 30192, 30209, 30194, 30193, 30202, 30207, 30196, 30195,
- {f: 2, c: 30430}, 30555, 30571, 30566, 30558, 30563, 30585, 30570, 30572,
- 30556, 30565, 30568, 30562, 30702, 30862, 30896, {f: 2, c: 30871}, 30860,
- 30857, 30844, 30865, 30867, 30847, 31098, 31103, 31105, 33836, 31165,
- 31260, 31258, 31264, 31252, 31263, 31262, {f: 2, c: 31391}, 31607, 31680,
- 31584, 31598, 31591, 31921, 31923, 31925, 32147, 32121, 32145, 32129,
- 32143, 32091, 32622, {f: 2, c: 32617}, 32626, 32681, 32680, 32676, 32854,
- 32856, 32902, 32900, 33137, 33136, 33144, 33125, 33134, 33139, 33131,
- {f: 2, c: 33145}, 33126, 33285, 33351, 33922, 33911, 33853, 33841, 33909,
- 33894, 33899, 33865, 33900, 33883, 33852, 33845, 33889, 33891, 33897,
- 33901, 33862, 34398, 34396, 34399, 34553, 34579, 34568, 34567, 34560,
- 34558, 34555, {f: 2, c: 34562}, 34566, 34570, 34905, 35039, 35028, 35033,
- 35036, 35032, 35037, 35041, 35018, 35029, 35026, 35228, 35299, 35435,
- {f: 2, c: 35442}, 35430, 35433, 35440, 35463, 35452, 35427, 35488, 35441,
- 35461, 35437, 35426, 35438, 35436, 35449, 35451, 35390, 35432, 35938,
- 35978, 35977, 36042, {f: 2, c: 36039}, 36036, 36018, 36035, 36034, 36037,
- 36321, 36319, 36328, 36335, 36339, 36346, 36330, 36324, 36326, 36530,
- 36611, 36617, 36606, 36618, 36767, 36786, 36939, 36938, 36947, 36930,
- 36948, 36924, 36949, 36944, 36935, 36943, 36942, 36941, 36945, 36926,
- 36929, 37138, 37143, 37228, 37226, 37225, 37321, 37431, 37463, 37432,
- 37437, 37440, 37438, 37467, 37451, 37476, 37457, 37428, 37449, 37453,
- 37445, 37433, 37439, 37466, 38296, 38552, {f: 2, c: 38548}, 38605, 38603,
- {f: 2, c: 38601}, 38647, 38651, 38649, 38646, 38742, 38772, 38774,
- {f: 2, c: 38928}, 38931, 38922, 38930, 38924, 39164, 39156,
- {f: 2, c: 39165}, 39347, 39345, 39348, 39649, 40169, 40578, [12237, 40718],
- [12238, 40723], [12239, 40736], 20711, 20718, 20709, 20694, [20717, 60903],
- 20698, 20693, 20687, 20689, 20721, 20686, 20713, 20834, 20979, 21123,
- 21122, 21297, 21421, 22014, 22016, 22043, 22039, 22013, 22036, 22022,
- 22025, {f: 2, c: 22029}, 22007, 22038, 22047, 22024, 22032, 22006, 22296,
- 22294, 22645, 22654, 22659, 22675, 22666, 22649, 22661, 22653, 22781,
- 22821, 22818, 22820, 22890, 22889, 23265, 23270, 23273, 23255, 23254,
- 23256, 23267, 23413, 23518, 23527, 23521, {f: 2, c: 23525}, 23528, 23522,
- 23524, 23519, 23565, 23650, 23940, 23943, 24155, 24163, 24149, 24151,
- 24148, 24275, 24278, 24330, 24390, 24432, 24505, 24903, 24895, 24907,
- 24951, {f: 2, c: 24930}, 24927, 24922, 24920, 24949, 25130, 25735, 25688,
- 25684, 25764, 25720, 25695, 25722, 25681, 25703, 25652, 25709, 25723,
- 25970, 26017, 26071, 26070, 26274, 26280, 26269, 27036, 27048, 27029,
- 27073, 27054, 27091, 27083, 27035, 27063, 27067, 27051, 27060, 27088,
- 27085, 27053, 27084, 27046, 27075, 27043, 27465, 27468, 27699, 28467,
- 28436, 28414, 28435, 28404, 28457, 28478, 28448, 28460, 28431, 28418,
- 28450, 28415, 28399, 28422, 28465, 28472, 28466, 28451, 28437, 28459,
- 28463, 28552, 28458, 28396, 28417, 28402, 28364, 28407, 29076, 29081,
- 29053, 29066, 29060, 29074, 29246, 29330, 29334, 29508, 29520, 29796,
- 29795, 29802, 29808, 29805, 29956, 30097, 30247, 30221, 30219, 30217,
- 30227, 30433, 30435, 30596, 30589, 30591, 30561, 30913, 30879, 30887,
- 30899, 30889, 30883, {f: 2, c: 31118}, 31117, 31278, 31281, 31402, 31401,
- 31469, 31471, 31649, 31637, 31627, 31605, 31639, 31645, 31636, 31631,
- [31672, 58170], 31623, 31620, 31929, {f: 2, c: 31933}, 32187, 32176, 32156,
- {f: 2, c: 32189}, 32160, 32202, 32180, 32178, 32177, 32186, 32162, 32191,
- 32181, 32184, 32173, [32210, 58202], 32199, 32172, 32624, {f: 2, c: 32736},
- 32735, 32862, 32858, 32903, 33104, 33152, 33167, 33160, 33162, 33151,
- 33154, 33255, 33274, 33287, 33300, 33310, 33355, 33993, 33983, 33990,
- 33988, 33945, 33950, 33970, 33948, 33995, 33976, 33984, 34003, 33936,
- 33980, 34001, 33994, 34623, 34588, 34619, 34594, 34597, 34612, 34584,
- 34645, 34615, 34601, 35059, 35074, 35060, 35065, 35064, 35069, 35048,
- 35098, 35055, 35494, 35468, 35486, 35491, 35469, 35489, 35475, 35492,
- 35498, 35493, 35496, 35480, 35473, 35482, 35495, 35946, 35981, 35980,
- 36051, {f: 2, c: 36049}, 36203, 36249, 36245, 36348, 36628, 36626, 36629,
- 36627, 36771, 36960, 36952, 36956, 36963, 36953, 36958, 36962, 36957,
- 36955, 37145, 37144, 37150, 37237, 37240, 37239, 37236, 37496, 37548,
- 37504, 37509, 37528, 37526, 37499, 37523, 37532, 37544, 37500, 37521,
- 38305, {f: 2, c: 38312}, 38307, 38309, 38308, 38553, 38556, 38555, 38604,
- 38610, 38656, 38780, 38789, 38902, {f: 2, c: 38935}, 39087, 39089, 39171,
- 39173, 39180, 39177, 39361, {f: 2, c: 39599}, 39654, {f: 2, c: 39745},
- 40180, 40182, 40179, 40636, [12240, 40763], [12241, 40778], 20740, 20736,
- 20731, 20725, 20729, 20738, {f: 2, c: 20744}, 20741, 20956,
- {f: 3, c: 21127}, 21133, 21130, 21232, 21426, 22062, 22075, 22073, 22066,
- 22079, 22068, 22057, 22099, 22094, 22103, 22132, 22070, {f: 2, c: 22063},
- 22656, 22687, 22686, 22707, 22684, 22702, 22697, 22694, 22893, 23305,
- 23291, 23307, 23285, 23308, 23304, 23534, 23532, 23529, 23531,
- {f: 2, c: 23652}, 23965, 23956, 24162, 24159, 24161, 24290, 24282, 24287,
- 24285, 24291, 24288, 24392, 24433, 24503, 24501, 24950, 24935, 24942,
- 24925, 24917, 24962, 24956, 24944, 24939, 24958, 24999, 24976, 25003,
- 24974, 25004, 24986, 24996, 24980, 25006, 25134, 25705, 25711, 25721,
- 25758, 25778, 25736, [25744, 57745], 25776, 25765, 25747, 25749, 25769,
- 25746, 25774, 25773, 25771, 25754, 25772, 25753, 25762, 25779, 25973,
- {f: 2, c: 25975}, 26286, 26283, 26292, 26289, 27171, 27167, 27112, 27137,
- 27166, 27161, 27133, 27169, 27155, 27146, 27123, 27138, 27141, 27117,
- 27153, 27472, 27470, 27556, {f: 2, c: 27589}, 28479, 28540, 28548, 28497,
- 28518, 28500, 28550, 28525, 28507, 28536, 28526, 28558, 28538, 28528,
- 28516, 28567, 28504, 28373, 28527, 28512, 28511, 29087, 29100, 29105,
- 29096, 29270, 29339, 29518, 29527, 29801, 29835, 29827, 29822, 29824,
- 30079, 30240, 30249, 30239, 30244, 30246, {f: 2, c: 30241}, 30362, 30394,
- 30436, 30606, 30599, 30604, 30609, 30603, 30923, 30917, 30906, 30922,
- 30910, 30933, 30908, 30928, 31295, 31292, 31296, 31293, 31287, 31291,
- 31407, 31406, 31661, 31665, 31684, 31668, {f: 2, c: 31686}, 31681, 31648,
- 31692, 31946, 32224, 32244, 32239, 32251, 32216, 32236, 32221, 32232,
- 32227, 32218, 32222, 32233, 32158, 32217, 32242, 32249, 32629, 32631,
- 32687, 32745, 32806, {f: 3, c: 33179}, 33184, 33178, 33176, 34071, 34109,
- 34074, 34030, {f: 2, c: 34092}, 34067, 34065, 34083, 34081, 34068, 34028,
- 34085, 34047, 34054, 34690, 34676, 34678, 34656, 34662, 34680, 34664,
- 34649, 34647, 34636, 34643, 34907, 34909, 35088, 35079, {f: 2, c: 35090},
- 35093, 35082, 35516, 35538, 35527, 35524, 35477, 35531, 35576, 35506,
- 35529, 35522, 35519, 35504, 35542, 35533, 35510, 35513, 35547, 35916,
- 35918, 35948, 36064, 36062, 36070, 36068, {f: 2, c: 36076},
- {f: 2, c: 36066}, 36060, 36074, 36065, 36205, 36255, 36259, 36395, 36368,
- 36381, 36386, 36367, 36393, 36383, 36385, 36382, 36538, 36637, 36635,
- 36639, 36649, 36646, 36650, 36636, 36638, 36645, 36969, 36974, 36968,
- 36973, 36983, 37168, 37165, 37159, 37169, 37255, 37257, 37259, 37251,
- 37573, 37563, 37559, 37610, 37604, 37569, 37555, 37564, 37586, 37575,
- 37616, 37554, 38317, 38321, 38660, {f: 2, c: 38662}, 38665, 38752, 38797,
- 38795, 38799, 38945, 38955, 38940, 39091, 39178, 39187, 39186, 39192,
- 39389, 39376, 39391, 39387, 39377, 39381, 39378, 39385, 39607,
- {f: 2, c: 39662}, 39719, 39749, 39748, 39799, 39791, 40198, 40201, 40195,
- 40617, 40638, 40654, 22696, [12242, 40786], 20754, 20760, 20756, 20752,
- 20757, 20864, 20906, 20957, 21137, 21139, 21235, 22105, 22123, 22137,
- 22121, 22116, 22136, 22122, 22120, 22117, 22129, 22127, 22124, 22114,
- 22134, 22721, 22718, 22727, 22725, 22894, 23325, 23348, 23416, 23536,
- 23566, 24394, 25010, 24977, 25001, 24970, 25037, 25014, 25022, 25034,
- 25032, 25136, 25797, 25793, 25803, {f: 2, c: 25787}, 25818, 25796, 25799,
- 25794, 25805, 25791, 25810, 25812, 25790, 25972, 26310, 26313, 26297,
- 26308, 26311, 26296, 27197, 27192, 27194, 27225, 27243, 27224, 27193,
- 27204, 27234, 27233, 27211, 27207, 27189, 27231, 27208, 27481, 27511,
- 27653, 28610, 28593, 28577, 28611, 28580, 28609, 28583, 28595, 28608,
- 28601, [28598, 60318], 28582, 28576, 28596, 29118, 29129, 29136, 29138,
- 29128, 29141, 29113, 29134, 29145, 29148, {f: 2, c: 29123}, 29544, 29852,
- 29859, 29848, 29855, 29854, 29922, {f: 2, c: 29964}, 30260, 30264, 30266,
- 30439, 30437, 30624, {f: 2, c: 30622}, 30629, 30952, 30938, 30956, 30951,
- 31142, {f: 2, c: 31309}, 31302, 31308, 31307, 31418, 31705, 31761, 31689,
- 31716, 31707, 31713, 31721, 31718, {f: 2, c: 31957}, 32266, 32273, 32264,
- 32283, 32291, 32286, [32285, 58211], 32265, 32272, 32633, 32690,
- {f: 2, c: 32752}, 32750, [32808, 58239], 33203, 33193, 33192, 33275, 33288,
- {f: 2, c: 33368}, 34122, 34137, 34120, {f: 2, c: 34152}, 34115, 34121,
- 34157, 34154, 34142, 34691, 34719, 34718, 34722, 34701, 34913, 35114,
- 35122, 35109, 35115, 35105, 35242, [35238, 58391], 35558, 35578, 35563,
- 35569, 35584, 35548, 35559, 35566, 35582, {f: 2, c: 35585}, 35575, 35565,
- 35571, 35574, 35580, 35947, 35949, 35987, 36084, 36420, 36401, 36404,
- 36418, 36409, 36405, 36667, 36655, 36664, 36659, 36776, 36774, 36981,
- 36980, 36984, 36978, 36988, 36986, 37172, 37266, 37664, 37686, 37624,
- 37683, 37679, 37666, 37628, 37675, 37636, 37658, 37648, 37670, 37665,
- 37653, 37678, 37657, 38331, {f: 2, c: 38567}, 38570, 38613, 38670, 38673,
- 38678, 38669, 38675, 38671, 38747, [38748, 58565], 38758, 38808, 38960,
- 38968, 38971, 38967, 38957, 38969, 38948, 39184, 39208, 39198, 39195,
- 39201, 39194, 39405, 39394, 39409, 39608, 39612, 39675, 39661, 39720,
- 39825, 40213, 40227, 40230, 40232, 40210, 40219, 40664, 40660,
- [12243, 40845], [12244, 40860], 20778, 20767, 20769, 20786, 21237, 22158,
- 22144, 22160, 22149, 22151, 22159, 22741, 22739, 22737, 22734, 23344,
- 23338, 23332, 23418, 23607, 23656, 23996, 23994, 23997, 23992, 24171,
- 24396, 24509, 25033, 25026, 25031, 25062, 25035, 25138, 25140, 25806,
- 25802, 25816, 25824, 25840, 25830, 25836, 25841, 25826, 25837,
- {f: 2, c: 25986}, 26329, 26326, 27264, 27284, 27268, 27298, 27292, 27355,
- 27299, 27262, 27287, 27280, 27296, 27484, 27566, 27610, 27656, 28632,
- 28657, {f: 2, c: 28639}, 28635, 28644, 28651, 28655, 28544, 28652, 28641,
- 28649, 28629, 28654, 28656, 29159, [29151, 60361], 29166, 29158, 29157,
- 29165, 29164, 29172, 29152, 29237, 29254, 29552, 29554, 29865, 29872,
- 29862, 29864, 30278, 30274, 30284, 30442, 30643, 30634, 30640, 30636,
- 30631, 30637, 30703, 30967, 30970, 30964, 30959, 30977, 31143, 31146,
- 31319, 31423, 31751, 31757, 31742, 31735, 31756, 31712, 31968, 31964,
- 31966, 31970, 31967, 31961, 31965, 32302, 32318, 32326, 32311, 32306,
- 32323, 32299, 32317, 32305, 32325, 32321, 32308, 32313, 32328, 32309,
- 32319, 32303, 32580, 32755, 32764, {f: 2, c: 32881}, 32880, 32879, 32883,
- 33222, 33219, 33210, 33218, 33216, 33215, 33213, 33225, 33214, 33256,
- 33289, 33393, 34218, 34180, 34174, 34204, 34193, 34196, 34223, 34203,
- 34183, 34216, 34186, 34214, 34407, 34752, 34769, 34739, 34770, 34758,
- 34731, 34747, 34746, 34760, 34763, 35131, 35126, 35140, 35128, 35133,
- 35244, 35598, 35607, 35609, 35611, 35594, 35616, 35613, 35588, 35600,
- 35905, 35903, 35955, 36090, 36093, 36092, 36088, 36091, 36264, 36425,
- 36427, 36424, 36426, 36676, 36670, 36674, 36677, 36671, 36991, 36989,
- 36996, {f: 2, c: 36993}, 36992, 37177, 37283, 37278, 37276, 37709, 37762,
- 37672, 37749, 37706, 37733, 37707, 37656, 37758, 37740, 37723, 37744,
- 37722, 37716, {f: 3, c: 38346}, 38344, 38342, 38577, 38584, 38614, 38684,
- 38686, 38816, 38867, 38982, 39094, 39221, 39425, 39423, 39854, 39851,
- 39850, 39853, 40251, 40255, 40587, 40655, 40670, {f: 2, c: 40668}, 40667,
- 40766, 40779, 21474, 22165, 22190, 22745, 22744, 23352, 24413, 25059,
- 25139, 25844, 25842, 25854, 25862, {f: 2, c: 25850}, 25847, 26039, 26332,
- 26406, 27315, 27308, 27331, 27323, 27320, 27330, {f: 2, c: 27310}, 27487,
- 27512, 27567, 28681, 28683, 28670, 28678, 28666, 28689, 28687,
- {f: 2, c: 29179}, 29182, 29176, 29559, 29557, 29863, 29887, 29973, 30294,
- 30296, 30290, 30653, 30655, {f: 2, c: 30651}, 30990, 31150,
- {f: 2, c: 31329}, 31328, {f: 2, c: 31428}, 31787, 31783, 31786, 31774,
- 31779, 31777, 31975, {f: 2, c: 32340}, 32350, 32346, 32353, 32338, 32345,
- 32584, 32761, 32763, 32887, 32886, 33229, 33231, 33290, 34255, 34217,
- 34253, 34256, 34249, 34224, 34234, 34233, 34799, 34796, 34802, 34784,
- 35206, 35250, 35316, 35624, 35641, 35628, 35627, 35920, 36101, 36441,
- 36451, 36454, 36452, 36447, 36437, 36544, 36681, 36685, 36999, 36995,
- 37000, {f: 2, c: 37291}, 37328, 37780, 37770, 37782, 37794, 37811, 37806,
- 37804, 37808, 37784, 37786, 37783, 38356, 38358, 38352, 38357, 38626,
- 38620, 38617, 38619, 38622, 38692, 38819, 38822, 38829, 38905, 38989,
- 38991, 38988, 38990, 38995, 39098, {f: 2, c: 39230}, 39229, 39214, 39333,
- 39438, 39617, 39683, 39686, 39759, 39758, 39757, 39882, 39881, 39933,
- 39880, 39872, 40273, 40285, 40288, 40672, 40725, 40748, 20787, 22181,
- 22184, {f: 2, c: 22750}, 22754, 23541, 40848, 24300, 25074, 25079, 25078,
- 25077, 25856, 25871, 26336, 26333, 27365, 27357, 27354, 27347, 28699,
- 28703, 28712, 28698, 28701, 28693, 28696, 29190, 29197, 29272, 29346,
- 29560, 29562, 29885, 29898, 29923, 30087, 30086, 30303, 30305, 30663,
- 31001, 31153, 31339, 31337, {f: 2, c: 31806}, 31800, 31805, 31799, 31808,
- 32363, 32365, 32377, {f: 2, c: 32361}, 32371, 32645, 32694, 32697, 32696,
- 33240, 34281, 34269, 34282, 34261, {f: 2, c: 34276}, 34295, 34811, 34821,
- 34829, 34809, 34814, 35168, 35167, 35158, 35166, 35649, 35676, 35672,
- 35657, 35674, {f: 2, c: 35662}, 35654, 35673, 36104, 36106, 36476, 36466,
- 36487, 36470, 36460, 36474, 36468, 36692, 36686, 36781, {f: 2, c: 37002},
- 37297, 37294, 37857, 37841, 37855, 37827, 37832, {f: 2, c: 37852}, 37846,
- 37858, 37837, 37848, 37860, 37847, 37864, 38364, 38580, 38627, 38698,
- 38695, 38753, 38876, 38907, 39006, 39000, 39003, 39100, 39237, 39241,
- 39446, 39449, 39693, 39912, 39911, 39894, 39899, 40329, 40289, 40306,
- 40298, 40300, 40594, 40599, 40595, 40628, 21240, 22199, 22198, 22196,
- 22204, 22756, 23360, 23363, 23421, 23542, 24009, 25080, 25082, 25880,
- 25876, 25881, 26342, 26407, 27372, 28734, 28720, 28722, 29200, 29563,
- 29903, 30306, 30309, 31014, 31018, 31020, 31019, 31431, 31478, 31820,
- 31811, 31821, {f: 2, c: 31983}, 36782, 32381, 32380, 32386, 32588, 32768,
- 33242, 33382, 34299, 34297, 34321, 34298, 34310, 34315, 34311, 34314,
- {f: 2, c: 34836}, 35172, 35258, 35320, 35696, 35692, 35686, 35695, 35679,
- 35691, 36111, 36109, 36489, 36481, 36485, 36482, 37300, 37323, 37912,
- 37891, 37885, 38369, 38704, 39108, 39250, 39249, 39336, 39467, 39472,
- 39479, 39477, 39955, 39949, 40569, 40629, 40680, 40751, 40799, 40803,
- 40801, {f: 2, c: 20791}, 22209, 22208, 22210, 22804, 23660, 24013, 25084,
- 25086, 25885, 25884, 26005, 26345, 27387, 27396, 27386, 27570, 28748,
- 29211, 29351, 29910, 29908, 30313, 30675, 31824, 32399, 32396, 32700,
- 34327, 34349, 34330, 34851, 34850, 34849, 34847, 35178, 35180, 35261,
- 35700, 35703, 35709, 36115, 36490, 36493, 36491, 36703, 36783, 37306,
- 37934, 37939, 37941, 37946, 37944, 37938, 37931, 38370, {f: 2, c: 38712},
- 38706, [38911, 58586], 39015, 39013, 39255, 39493, 39491, 39488, 39486,
- 39631, 39764, 39761, 39981, 39973, 40367, 40372, 40386, 40376, 40605,
- 40687, 40729, 40796, {f: 2, c: 40806}, 20796, 20795, 22216, 22218, 22217,
- 23423, 24020, 24018, 24398, 25087, 25892, 27402, 27489, 28753, 28760,
- 29568, 29924, 30090, 30318, 30316, 31155, 31840, 31839, 32894, 32893,
- 33247, 35186, 35183, 35324, 35712, {f: 2, c: 36118}, 36497, 36499, 36705,
- 37192, 37956, {f: 2, c: 37969}, {f: 2, c: 38717}, 38851, 38849, 39019,
- 39253, 39509, 39501, 39634, 39706, 40009, 39985, 39998, 39995, 40403,
- 40407, 40756, 40812, 40810, 40852, 22220, 24022, 25088, 25891, 25899,
- 25898, 26348, 27408, 29914, 31434, 31844, 31843, 31845, 32403, 32406,
- 32404, 33250, 34360, 34367, 34865, 35722, 37008, 37007, 37987, 37984,
- 37988, 38760, 39023, 39260, {f: 2, c: 39514}, 39511, {f: 2, c: 39635},
- 39633, 40020, 40023, 40022, 40421, 40607, 40692, 22225, 22761, 25900,
- 28766, {f: 2, c: 30321}, [30679, 60226], 32592, 32648, 34870, 34873, 34914,
- 35731, 35730, 35734, 33399, 36123, 37312, 37994, 38722, 38728, 38724,
- 38854, 39024, 39519, 39714, 39768, 40031, {f: 2, c: 40441},
- {f: 2, c: 40572}, 40711, 40823, 40818, 24307, 27414, 28771, 31852, 31854,
- 34875, 35264, 36513, 37313, 38002, 38000, 39025, 39262, 39638, 39715,
- 40652, 28772, 30682, 35738, 38007, 38857, 39522, 39525, 32412, 35740,
- 36522, 37317, {f: 2, c: 38013}, 38012, {f: 2, c: 40055}, 40695, 35924,
- 38015, 40474, 29224, 39530, 39729, 40475, 40478, 31858, 20034, 20060,
- [12048, 20981], [12053, 21274], [12058, 21378], 19975, 19980, 20039, 20109,
- [12062, 22231], [12076, 23662], [12091, 24435], 19983, 20871, 19982, 20014,
- 20115, 20162, 20169, 20168, 20888, 21244, 21356, 21433, 22304, 22787,
- 22828, [23568, 60417], 24063, 26081, [12110, 27571], 27596, [12115, 27668],
- [12121, 29247], 20017, 20028, 20200, 20188, 20201, 20193, 20189, 20186,
- 21004, 21001, 21276, 21324, {f: 2, c: 22306}, 22807, 22831, 23425, 23428,
- 23570, 23611, 23668, 23667, 24068, 24192, 24194, 24521, 25097, 25168,
- 27669, 27702, 27715, 27711, 27707, 29358, 29360, 29578, [12145, 31160],
- 32906, 38430, 20238, 20248, 20268, 20213, 20244, 20209, 20224, 20215,
- 20232, 20253, 20226, 20229, 20258, 20243, 20228, 20212, 20242, 20913,
- 21011, 21008, 21158, 21282, 21279, 21325, 21386, 21511, 22241, 22239,
- 22318, 22314, 22324, 22844, 22912, 22908, 22917, 22907, 22910, 22903,
- 22911, 23382, 23573, 23589, 23676, {f: 2, c: 23674}, 23678, 24031,
- [24181, 57646], 24196, 24322, 24346, 24436, 24533, 24532, 24527, 25180,
- 25182, 25188, 25185, 25190, 25186, 25177, 25184, 25178, 25189, 25911,
- 26095, 26094, 26430, 26425, 26424, 26427, 26426, 26431, 26428, 26419,
- 27672, 27718, 27730, 27740, 27727, [27722, 60796], 27732, {f: 2, c: 27723},
- 28785, 29278, {f: 2, c: 29364}, 29582, 29994, 30335, 31349, [12153, 32593],
- [12171, 33400], 33404, 33408, 33405, 33407, [12172, 34381], [12177, 35198],
- 37017, [37015, 59347], 37016, 37019, 37012, 38434, 38436, 38432, 38435,
- 20310, 20283, 20322, 20297, 20307, 20324, 20286, 20327, 20306, 20319,
- 20289, 20312, 20269, 20275, 20287, 20321, 20879, 20921, 21020, 21022,
- 21025, {f: 2, c: 21165}, 21257, 21347, 21362, {f: 2, c: 21390}, 21552,
- 21559, 21546, 21588, 21573, 21529, 21532, 21541, 21528, 21565, 21583,
- 21569, 21544, 21540, 21575, 22254, 22247, 22245, 22337, 22341, 22348,
- 22345, 22347, 22354, 22790, 22848, 22950, 22936, 22944, 22935, 22926,
- 22946, 22928, 22927, 22951, 22945, 23438, 23442, 23592, 23594, 23693,
- 23695, 23688, 23691, 23689, 23698, 23690, 23686, 23699, 23701, 24032,
- 24074, 24078, 24203, 24201, 24204, 24200, 24205, 24325, 24349, 24440,
- 24438, 24530, 24529, 24528, 24557, 24552, 24558, 24563, 24545, 24548,
- 24547, 24570, 24559, 24567, 24571, 24576, 24564, 25146, 25219, 25228,
- {f: 2, c: 25230}, 25236, 25223, 25201, 25211, 25210, 25200, 25217, 25224,
- 25207, 25213, 25202, 25204, 26096, 26100, 26099, 26098, 26101, 26437,
- 26439, 26457, 26453, 26444, 26440, 26461, 26445, 26458, 26443, 27600,
- {f: 2, c: 27673}, 27768, 27751, 27755, 27780, 27787, 27791, 27761, 27759,
- 27753, 27802, 27757, 27783, 27797, [27804, 57900], 27750, 27763, 27749,
- 27771, 27790, 28788, 28794, 29283, 29375, 29373, 29379, 29382, 29377,
- 29370, 29381, 29589, 29591, {f: 2, c: 29587}, 29586, 30010, 30009,
- {f: 2, c: 30100}, 30337, 31037, 32820, 32917, 32921, 32912, 32914, 32924,
- 33424, 33423, 33413, 33422, 33425, 33427, 33418, {f: 2, c: 33411},
- [12184, 35960], 36809, 36799, 37023, 37025, 37029, 37022, 37031, 37024,
- 38448, 38440, 38447, 38445, 20019, 20376, 20348, 20357, 20349, 20352,
- 20359, 20342, 20340, 20361, 20356, 20343, 20300, 20375, 20330, 20378,
- 20345, 20353, 20344, 20368, 20380, 20372, 20382, 20370, 20354, 20373,
- 20331, 20334, 20894, 20924, 20926, 21045, {f: 2, c: 21042}, 21062, 21041,
- 21180, {f: 2, c: 21258}, 21308, 21394, 21396, 21639, 21631, 21633, 21649,
- 21634, 21640, 21611, 21626, 21630, 21605, 21612, 21620, 21606, 21645,
- 21615, 21601, 21600, 21656, 21603, 21607, 21604, 22263, 22265, 22383,
- 22386, 22381, 22379, 22385, 22384, 22390, 22400, 22389, 22395,
- {f: 2, c: 22387}, 22370, 22376, 22397, 22796, 22853, 22965, 22970, 22991,
- 22990, 22962, 22988, 22977, 22966, 22972, 22979, 22998, 22961, 22973,
- 22976, 22984, 22964, 22983, 23394, 23397, 23443, 23445, 23620, 23623,
- 23726, 23716, 23712, 23733, 23727, 23720, 23724, 23711, 23715, 23725,
- 23714, 23722, 23719, 23709, 23717, 23734, 23728, 23718, 24087, 24084,
- 24089, 24360, {f: 3, c: 24354}, 24404, 24450, 24446, 24445, 24542, 24549,
- 24621, 24614, 24601, 24626, 24587, 24628, 24586, 24599, 24627, 24602,
- 24606, 24620, 24610, 24589, 24592, 24622, 24595, 24593, 24588, 24585,
- 24604, 25108, 25149, 25261, 25268, 25297, 25278, 25258, 25270, 25290,
- 25262, 25267, 25263, 25275, 25257, 25264, 25272, 25917, 26024, 26043,
- 26121, 26108, 26116, 26130, 26120, 26107, 26115, 26123, 26125, 26117,
- 26109, 26129, 26128, 26358, 26378, 26501, 26476, 26510, 26514, 26486,
- 26491, 26520, 26502, 26500, 26484, 26509, 26508, 26490, 26527, 26513,
- 26521, 26499, 26493, 26497, {f: 2, c: 26488}, 26516, 27429, 27520, 27518,
- 27614, 27677, 27795, 27884, 27883, 27886, 27865, 27830, 27860, 27821,
- 27879, 27831, 27856, 27842, 27834, 27843, 27846, 27885, 27890, 27858,
- 27869, 27828, 27786, 27805, 27776, 27870, 27840, 27952, 27853, 27847,
- 27824, 27897, 27855, 27881, 27857, 28820, 28824, 28805, 28819, 28806,
- 28804, 28817, 28822, 28802, 28826, 28803, 29290, 29398, 29387, 29400,
- 29385, 29404, 29394, 29396, 29402, 29388, 29393, 29604, 29601, 29613,
- 29606, 29602, 29600, 29612, 29597, 29917, 29928, {f: 2, c: 30015}, 30014,
- 30092, 30104, 30383, 30451, 30449, 30448, 30453, 30712, 30716, 30713,
- 30715, 30714, 30711, 31042, 31039, 31173, 31352, 31355, 31483, 31861,
- 31997, 32821, 32911, 32942, 32931, 32952, 32949, 32941, 33312, 33440,
- 33472, 33451, 33434, 33432, 33435, 33461, 33447, 33454, 33468, 33438,
- 33466, 33460, 33448, 33441, 33449, 33474, 33444, 33475, 33462, 33442,
- 34416, 34415, {f: 2, c: 34413}, 35926, 36818, 36811, 36819, 36813, 36822,
- 36821, 36823, 37042, 37044, 37039, 37043, 37040, 38457, 38461, 38460,
- 38458, 38467, 20429, 20421, 20435, 20402, 20425, 20427, 20417, 20436,
- 20444, 20441, [20411, 60346], 20403, 20443, 20423, 20438, 20410, 20416,
- 20409, 20460, 21060, 21065, 21184, 21186, 21309, 21372, 21399, 21398,
- 21401, 21400, 21690, 21665, 21677, 21669, 21711, 21699, 33549, 21687,
- 21678, 21718, 21686, {f: 2, c: 21701}, 21664, 21616, 21692, 21666, 21694,
- 21618, 21726, 21680, 22453, {f: 2, c: 22430}, 22436, 22412, 22423, 22429,
- 22427, 22420, 22424, 22415, 22425, 22437, 22426, 22421, 22772, 22797,
- 22867, 23009, 23006, 23022, 23040, 23025, 23005, 23034, 23037, 23036,
- 23030, 23012, 23026, 23031, 23003, 23017, 23027, 23029, 23008, 23038,
- 23028, 23021, 23464, 23628, 23760, 23768, 23756, 23767, 23755, 23771,
- 23774, 23770, 23753, 23751, 23754, 23766, {f: 2, c: 23763}, 23759, 23752,
- 23750, 23758, 23775, 23800, 24057, {f: 3, c: 24097}, 24096, 24100, 24240,
- 24228, 24226, 24219, 24227, 24229, 24327, 24366, 24406, 24454, 24631,
- 24633, 24660, 24690, 24670, 24645, 24659, 24647, 24649, 24667, 24652,
- 24640, 24642, 24671, 24612, 24644, 24664, 24678, 24686, {f: 2, c: 25154},
- 25295, 25357, 25355, 25333, 25358, 25347, 25323, 25337, 25359, 25356,
- 25336, 25334, 25344, {f: 2, c: 25363}, 25338, 25365, 25339, 25328, 25921,
- 25923, 26026, 26047, 26166, 26145, 26162, 26165, 26140, 26150, 26146,
- 26163, 26155, 26170, 26141, 26164, 26169, 26158, {f: 2, c: 26383}, 26561,
- 26610, 26568, 26554, 26588, 26555, 26616, 26584, 26560, 26551, 26565,
- 26603, 26596, 26591, 26549, 26573, 26547, 26615, 26614, 26606, 26595,
- 26562, 26553, 26574, 26599, 26608, 26546, 26620, 26566, 26605, 26572,
- 26542, 26598, 26587, 26618, {f: 2, c: 26569}, 26563, 26602, 26571, 27432,
- 27522, 27524, 27574, 27606, 27608, 27616, {f: 2, c: 27680}, 27944, 27956,
- 27949, 27935, 27964, 27967, 27922, 27914, 27866, 27955, 27908, 27929,
- 27962, 27930, 27921, 27904, 27933, 27970, 27905, 27928, 27959, 27907,
- 27919, 27968, 27911, 27936, 27948, 27912, 27938, 27913, 27920, 28855,
- 28831, 28862, 28849, 28848, 28833, {f: 2, c: 28852}, 28841, 29249,
- {f: 2, c: 29257}, 29292, 29296, 29299, 29294, 29386, 29412, 29416, 29419,
- 29407, 29418, 29414, 29411, 29573, 29644, 29634, 29640, 29637, 29625,
- 29622, 29621, 29620, 29675, 29631, 29639, 29630, 29635, 29638, 29624,
- 29643, 29932, 29934, 29998, {f: 2, c: 30023}, 30119, 30122, 30329, 30404,
- 30472, {f: 3, c: 30467}, 30474, 30455, 30459, 30458, {f: 2, c: 30695},
- 30726, {f: 2, c: 30737}, 30725, 30736, 30735, 30734, [30729, 58095], 30723,
- 30739, 31050, 31052, 31051, 31045, 31044, 31189, 31181, 31183, 31190,
- 31182, 31360, 31358, 31441, {f: 2, c: 31488}, 31866, {f: 2, c: 31864},
- {f: 3, c: 31871}, 32003, 32008, 32001, 32600, 32657, 32653, 32702, 32775,
- {f: 2, c: 32782}, 32788, 32823, 32984, 32967, 32992, 32977, 32968, 32962,
- 32976, 32965, 32995, 32985, 32988, 32970, 32981, 32969, 32975, 32983,
- 32998, 32973, 33279, 33313, 33428, 33497, 33534, 33529, 33543, 33512,
- 33536, 33493, 33594, 33515, 33494, 33524, 33516, 33505, 33522, 33525,
- 33548, 33531, 33526, 33520, 33514, 33508, 33504, 33530, 33523, 33517,
- 34423, 34420, 34428, 34419, 34881, 34894, 34919, 34922, 34921, 35283,
- 35332, 35335, 36210, 36835, 36833, 36846, 36832, 37105, 37053, 37055,
- 37077, 37061, 37054, 37063, 37067, 37064, [37332, 60294], 37331, 38484,
- 38479, 38481, 38483, 38474, 38478, 20510, 20485, 20487, 20499, 20514,
- 20528, 20507, 20469, 20468, 20531, 20535, 20524, {f: 2, c: 20470}, 20503,
- 20508, 20512, 20519, 20533, 20527, 20529, 20494, 20826, 20884, 20883,
- 20938, {f: 2, c: 20932}, 20936, 20942, 21089, 21082, 21074,
- {f: 2, c: 21086}, 21077, 21090, 21197, 21262, 21406, 21798, 21730, 21783,
- 21778, 21735, 21747, 21732, 21786, 21759, 21764, 21768, 21739, 21777,
- 21765, 21745, 21770, 21755, {f: 2, c: 21751}, 21728, 21774, 21763, 21771,
- {f: 2, c: 22273}, 22476, 22578, 22485, 22482, 22458, 22470, 22461, 22460,
- 22456, 22454, 22463, 22471, 22480, 22457, 22465, 22798, 22858, 23065,
- 23062, {f: 2, c: 23085}, 23061, 23055, 23063, 23050, 23070, 23091, 23404,
- 23463, 23469, 23468, 23555, 23638, 23636, 23788, 23807, 23790, 23793,
- 23799, 23808, 23801, 24105, 24104, 24232, 24238, 24234, 24236, 24371,
- 24368, 24423, 24669, 24666, 24679, 24641, 24738, 24712, 24704, 24722,
- 24705, 24733, 24707, 24725, 24731, 24727, 24711, 24732, 24718, 25113,
- 25158, 25330, 25360, 25430, 25388, {f: 2, c: 25412}, 25398, 25411, 25572,
- 25401, 25419, 25418, 25404, 25385, 25409, 25396, 25432, 25428, 25433,
- 25389, 25415, 25395, 25434, 25425, 25400, 25431, 25408, 25416, 25930,
- 25926, 26054, {f: 2, c: 26051}, 26050, 26186, 26207, 26183, 26193,
- {f: 2, c: 26386}, 26655, 26650, 26697, {f: 2, c: 26674}, 26683, 26699,
- 26703, 26646, 26673, 26652, 26677, 26667, 26669, 26671, 26702, 26692,
- 26676, 26653, 26642, 26644, 26662, 26664, 26670, 26701, 26682, 26661,
- 26656, 27436, 27439, 27437, 27441, 27444, 27501, 32898, 27528, 27622,
- 27620, 27624, 27619, 27618, 27623, 27685, 28026, {f: 2, c: 28003}, 28022,
- 27917, 28001, 28050, 27992, 28002, 28013, 28015, 28049, 28045, 28143,
- 28031, 28038, 27998, [28007, 59078], 28000, 28055, 28016, 28028, 27999,
- 28034, 28056, 27951, 28008, 28043, 28030, 28032, 28036, 27926, 28035,
- 28027, 28029, 28021, 28048, 28892, 28883, 28881, 28893, 28875, 32569,
- 28898, 28887, 28882, 28894, 28896, 28884, 28877, {f: 3, c: 28869}, 28890,
- 28878, 28897, 29250, 29304, 29303, 29302, 29440, 29434, 29428, 29438,
- 29430, 29427, 29435, 29441, 29651, 29657, 29669, 29654, 29628, 29671,
- 29667, 29673, 29660, 29650, 29659, 29652, 29661, 29658, {f: 2, c: 29655},
- 29672, {f: 2, c: 29918}, {f: 2, c: 29940}, 29985, 30043, 30047, 30128,
- 30145, 30139, 30148, 30144, 30143, 30134, 30138, 30346, 30409, 30493,
- 30491, 30480, 30483, 30482, 30499, 30481, 30485, {f: 2, c: 30489}, 30498,
- 30503, 30755, 30764, 30754, 30773, 30767, 30760, 30766, 30763, 30753,
- 30761, 30771, 30762, 30769, 31060, 31067, 31055, 31068, 31059, 31058,
- 31057, {f: 2, c: 31211}, 31200, 31214, 31213, 31210, 31196, 31198, 31197,
- 31366, 31369, 31365, {f: 2, c: 31371}, 31370, 31367, 31448, 31504, 31492,
- 31507, 31493, 31503, 31496, 31498, 31502, 31497, 31506, 31876, 31889,
- 31882, 31884, 31880, 31885, 31877, 32030, 32029, 32017, 32014, 32024,
- 32022, 32019, 32031, 32018, 32015, 32012, 32604, 32609, 32606, 32608,
- 32605, 32603, 32662, 32658, 32707, 32706, 32704, 32790, 32830, 32825,
- 33018, 33010, 33017, 33013, 33025, 33019, 33024, 33281, 33327, 33317,
- 33587, 33581, 33604, 33561, 33617, 33573, 33622, 33599, 33601, 33574,
- 33564, 33570, 33602, 33614, 33563, 33578, 33544, 33596, 33613, 33558,
- 33572, 33568, 33591, 33583, 33577, 33607, 33605, 33612, 33619, 33566,
- 33580, 33611, 33575, 33608, 34387, 34386, 34466, 34472, 34454, 34445,
- 34449, 34462, 34439, 34455, 34438, 34443, 34458, 34437, 34469, 34457,
- 34465, 34471, 34453, 34456, 34446, 34461, 34448, 34452, {f: 2, c: 34883},
- 34925, {f: 2, c: 34933}, 34930, 34944, 34929, 34943, 34927, 34947, 34942,
- 34932, 34940, 35346, 35911, 35927, 35963, 36004, 36003, 36214, 36216,
- 36277, 36279, 36278, 36561, 36563, 36862, 36853, 36866, 36863, 36859,
- 36868, 36860, 36854, 37078, 37088, {f: 2, c: 37081}, 37091, 37087, 37093,
- 37080, 37083, 37079, 37084, 37092, 37200, {f: 2, c: 37198}, 37333, 37346,
- 37338, 38492, 38495, 38588, 39139, [12221, 39647], [12223, 39727], 20095,
- 20592, 20586, 20577, 20574, 20576, 20563, 20555, 20573, 20594, 20552,
- 20557, 20545, 20571, 20554, 20578, 20501, 20549, 20575, 20585, 20587,
- {f: 2, c: 20579}, 20550, 20544, 20590, 20595, 20567, 20561, 20944, 21099,
- 21101, 21100, 21102, 21206, 21203, 21293, 21404, {f: 2, c: 21877}, 21820,
- 21837, 21840, 21812, 21802, 21841, 21858, 21814, 21813, 21808, 21842,
- 21829, 21772, 21810, 21861, 21838, 21817, 21832, 21805, 21819, 21824,
- 21835, 22282, 22279, 22523, 22548, 22498, 22518, 22492, 22516, 22528,
- 22509, 22525, 22536, 22520, 22539, 22515, 22479, 22535, 22510, 22499,
- 22514, 22501, 22508, 22497, 22542, 22524, 22544, 22503, 22529, 22540,
- 22513, 22505, 22512, 22541, 22532, 22876, 23136, 23128, 23125,
- [23143, 60437], 23134, 23096, 23093, 23149, 23120, 23135, 23141, 23148,
- 23123, 23140, 23127, 23107, 23133, 23122, 23108, 23131, 23112, 23182,
- 23102, 23117, 23097, 23116, 23152, 23145, 23111, 23121, 23126, 23106,
- 23132, 23410, 23406, 23489, 23488, 23641, 23838, 23819, 23837, 23834,
- 23840, 23820, 23848, 23821, 23846, 23845, 23823, 23856, 23826, 23843,
- 23839, 23854, 24126, 24116, 24241, 24244, 24249, {f: 2, c: 24242}, 24374,
- 24376, 24475, 24470, 24479, 24714, 24720, 24710, 24766, 24752, 24762,
- {f: 2, c: 24787}, 24783, 24804, 24793, 24797, 24776, 24753, 24795, 24759,
- 24778, 24767, 24771, 24781, 24768, 25394, 25445, 25482, 25474, 25469,
- 25533, 25502, 25517, 25501, 25495, 25515, 25486, 25455, 25479, 25488,
- 25454, 25519, 25461, 25500, 25453, 25518, 25468, 25508, 25403, 25503,
- 25464, 25477, 25473, 25489, 25485, 25456, 25939, 26061, 26213, 26209,
- 26203, 26201, 26204, 26210, 26392, 26745, 26759, 26768, 26780,
- {f: 2, c: 26733}, 26798, 26795, 26966, 26735, 26787, 26796, 26793, 26741,
- 26740, 26802, 26767, 26743, 26770, 26748, 26731, 26738, 26794, 26752,
- 26737, 26750, 26779, 26774, 26763, 26784, 26761, 26788, 26744, 26747,
- 26769, 26764, 26762, 26749, 27446, 27443, {f: 2, c: 27447}, 27537, 27535,
- {f: 2, c: 27533}, 27532, 27690, 28096, 28075, 28084, 28083, 28276, 28076,
- 28137, 28130, 28087, 28150, 28116, 28160, 28104, 28128, 28127, 28118,
- 28094, 28133, {f: 2, c: 28124}, 28123, 28148, 28106, 28093, 28141, 28144,
- 28090, 28117, 28098, 28111, 28105, 28112, 28146, 28115, 28157, 28119,
- 28109, 28131, 28091, 28922, 28941, 28919, 28951, 28916, 28940, 28912,
- 28932, 28915, 28944, 28924, 28927, 28934, 28947, 28928, 28920, 28918,
- 28939, 28930, 28942, 29310, {f: 2, c: 29307}, 29311, 29469, 29463, 29447,
- 29457, 29464, 29450, 29448, 29439, 29455, 29470, 29576, 29686, 29688,
- 29685, 29700, 29697, 29693, 29703, 29696, 29690, 29692, 29695, 29708,
- 29707, 29684, 29704, 30052, 30051, 30158, 30162, 30159, {f: 2, c: 30155},
- 30161, 30160, 30351, 30345, 30419, 30521, 30511, 30509, {f: 2, c: 30513},
- 30516, 30515, 30525, 30501, 30523, 30517, 30792, 30802, 30793, 30797,
- 30794, 30796, 30758, 30789, 30800, 31076, 31079, {f: 2, c: 31081}, 31075,
- 31083, 31073, 31163, 31226, 31224, {f: 2, c: 31222}, 31375, 31380, 31376,
- 31541, 31547, 31540, 31525, 31536, 31522, 31524, 31539, 31512, 31530,
- 31517, 31537, 31531, 31533, 31535, 31538, 31544, 31514, 31523, 31892,
- 31896, 31894, 31907, 32053, 32061, 32056, 32054, 32058, 32069, 32044,
- 32041, 32065, 32071, {f: 2, c: 32062}, 32074, 32059, 32040, 32611, 32661,
- {f: 2, c: 32668}, 32667, {f: 2, c: 32714}, 32717, {f: 2, c: 32720}, 32711,
- 32719, 32713, 32799, 32798, 32795, 32839, 32835, 32840, 33048, 33061,
- 33049, 33051, 33069, 33055, 33068, 33054, 33057, 33045, 33063, 33053,
- 33058, 33297, 33336, 33331, 33338, 33332, 33330, 33396, 33680, 33699,
- 33704, 33677, 33658, 33651, 33700, 33652, 33679, 33665, 33685, 33689,
- 33653, 33684, 33705, 33661, 33667, 33676, 33693, 33691, 33706, 33675,
- 33662, 33701, 33711, 33672, 33687, 33712, 33663, 33702, 33671, 33710,
- 33654, 34393, 34390, 34495, 34487, 34498, 34497, 34501, 34490, 34480,
- 34504, 34489, 34483, 34488, 34508, 34484, {f: 2, c: 34491}, 34499,
- {f: 2, c: 34493}, 34898, 34953, 34965, 34984, 34978, 34986, 34970, 34961,
- 34977, 34975, 34968, 34983, 34969, 34971, 34967, 34980, 34988, 34956,
- 34963, 34958, 35202, 35286, 35289, 35285, 35376, 35367, 35372, 35358,
- 35897, 35899, {f: 2, c: 35932}, 35965, 36005, 36221, 36219, 36217, 36284,
- 36290, 36281, 36287, 36289, 36568, 36574, 36573, 36572, 36567,
- {f: 2, c: 36576}, 36900, 36875, 36881, 36892, 36876, 36897, 37103, 37098,
- 37104, 37108, {f: 2, c: 37106}, 37076, {f: 2, c: 37099}, 37097, 37206,
- 37208, 37210, 37203, 37205, 37356, 37364, 37361, 37363, 37368, 37348,
- 37369, {f: 2, c: 37354}, 37367, 37352, 37358, 38266, 38278, 38280, 38524,
- 38509, 38507, 38513, 38511, 38591, 38762, 38916, 39141, 39319, 20635,
- 20629, 20628, 20638, 20619, 20643, 20611, 20620, 20622, 20637, 20584,
- 20636, 20626, 20610, 20615, 20831, 20948, 21266, 21265, 21412, 21415,
- 21905, 21928, 21925, 21933, 21879, 22085, 21922, 21907, 21896, 21903,
- 21941, 21889, 21923, 21906, 21924, 21885, 21900, 21926, 21887, 21909,
- 21921, 21902, 22284, 22569, 22583, 22553, 22558, 22567, 22563, 22568,
- 22517, 22600, 22565, 22556, 22555, 22579, 22591, 22582, 22574, 22585,
- 22584, 22573, 22572, 22587, 22881, 23215, 23188, 23199, 23162, 23202,
- 23198, 23160, 23206, 23164, 23205, 23212, 23189, 23214, 23095, 23172,
- 23178, 23191, 23171, 23179, 23209, 23163, 23165, 23180, 23196, 23183,
- 23187, 23197, 23530, 23501, 23499, 23508, 23505, 23498, 23502, 23564,
- 23600, 23863, 23875, 23915, 23873, 23883, 23871, 23861, 23889, 23886,
- 23893, 23859, 23866, 23890, 23869, 23857, 23897, 23874, 23865, 23881,
- 23864, 23868, 23858, 23862, 23872, 23877, 24132, 24129, [24408, 57673],
- 24486, 24485, 24491, 24777, 24761, 24780, 24802, 24782, 24772, 24852,
- 24818, 24842, 24854, 24837, 24821, 24851, 24824, 24828, 24830, 24769,
- 24835, 24856, 24861, 24848, 24831, 24836, 24843, 25162, 25492, 25521,
- 25520, 25550, 25573, 25576, 25583, 25539, 25757, 25587, 25546, 25568,
- 25590, 25557, 25586, 25589, 25697, 25567, 25534, 25565, 25564, 25540,
- 25560, 25555, 25538, 25543, 25548, 25547, 25544, 25584, 25559, 25561,
- 25906, 25959, 25962, 25956, 25948, 25960, 25957, 25996, {f: 2, c: 26013},
- 26030, 26064, 26066, 26236, 26220, 26235, 26240, 26225, 26233, 26218,
- 26226, 26369, 26892, 26835, 26884, 26844, 26922, 26860, 26858, 26865,
- 26895, 26838, 26871, 26859, 26852, 26870, 26899, 26896, 26867, 26849,
- 26887, 26828, 26888, 26992, 26804, 26897, 26863, 26822, 26900, 26872,
- 26832, 26877, 26876, 26856, 26891, 26890, 26903, 26830, 26824,
- {f: 2, c: 26845}, 26854, 26868, 26833, 26886, 26836, 26857, 26901, 26917,
- 26823, 27449, 27451, 27455, 27452, 27540, 27543, 27545, 27541, 27581,
- 27632, {f: 2, c: 27634}, 27696, 28156, {f: 2, c: 28230}, 28191, 28233,
- 28296, {f: 2, c: 28220}, 28229, 28258, 28203, 28223, 28225, 28253, 28275,
- 28188, 28211, 28235, 28224, 28241, 28219, 28163, 28206, 28254, 28264,
- 28252, 28257, 28209, 28200, 28256, 28273, 28267, 28217, 28194, 28208,
- 28243, 28261, 28199, 28280, 28260, 28279, 28245, 28281, 28242, 28262,
- {f: 2, c: 28213}, 28250, 28960, 28958, 28975, 28923, 28974, 28977, 28963,
- 28965, 28962, 28978, 28959, 28968, 28986, 28955, 29259, 29274,
- {f: 2, c: 29320}, 29318, 29317, 29323, 29458, 29451, 29488, 29474, 29489,
- 29491, 29479, 29490, 29485, 29478, 29475, 29493, 29452, 29742, 29740,
- 29744, 29739, 29718, 29722, 29729, 29741, 29745, 29732, 29731, 29725,
- 29737, 29728, 29746, 29947, 29999, 30063, 30060, 30183, 30170, 30177,
- 30182, 30173, 30175, 30180, 30167, 30357, 30354, 30426, {f: 2, c: 30534},
- 30532, 30541, 30533, 30538, 30542, {f: 2, c: 30539}, 30686, 30700, 30816,
- {f: 2, c: 30820}, 30812, 30829, 30833, 30826, 30830, 30832, 30825, 30824,
- 30814, 30818, 31092, 31091, 31090, 31088, 31234, 31242, 31235, 31244,
- 31236, 31385, 31462, 31460, 31562, 31559, 31556, 31560, 31564, 31566,
- 31552, 31576, 31557, 31906, 31902, 31912, 31905, 32088, 32111, 32099,
- 32083, 32086, 32103, 32106, 32079, 32109, 32092, 32107, 32082, 32084,
- 32105, 32081, 32095, 32078, {f: 2, c: 32574}, {f: 2, c: 32613}, 32674,
- {f: 2, c: 32672}, 32727, 32849, {f: 2, c: 32847}, 33022, 32980, 33091,
- 33098, 33106, 33103, 33095, 33085, 33101, 33082, 33254, 33262,
- {f: 3, c: 33271}, 33284, {f: 2, c: 33340}, 33343, 33397, 33595,
- [33743, 60382], 33785, 33827, 33728, 33768, 33810, 33767, 33764, 33788,
- 33782, 33808, 33734, 33736, 33771, 33763, 33727, 33793, 33757, 33765,
- 33752, 33791, 33761, 33739, 33742, 33750, 33781, 33737, 33801,
- [33807, 58332], 33758, 33809, 33798, 33730, 33779, 33749, 33786, 33735,
- 33745, 33770, 33811, 33690, 33731, 33772, 33774, 33732, 33787, 33751,
- 33762, 33819, 33755, 33790, 34520, 34530, 34534, 34515, 34531, 34522,
- 34538, 34525, 34539, 34524, 34540, 34537, 34519, 34536, 34513, 34888,
- 34902, 34901, 35002, 35031, 35001, 35000, 35008, 35006, 34998, 35004,
- 34999, 35005, 34994, 35073, 35017, 35221, 35224, 35223, 35293,
- {f: 2, c: 35290}, 35406, 35405, 35385, 35417, 35392, {f: 2, c: 35415},
- {f: 2, c: 35396}, 35410, 35400, 35409, 35402, 35404, 35407, 35935, 35969,
- 35968, 36026, 36030, 36016, 36025, 36021, 36228, 36224, 36233, 36312,
- 36307, 36301, 36295, 36310, 36316, 36303, 36309, 36313, 36296, 36311,
- 36293, 36591, 36599, 36602, 36601, 36582, 36590, 36581, 36597,
- {f: 2, c: 36583}, 36598, 36587, 36593, 36588, 36596, 36585, 36909, 36916,
- 36911, 37126, 37164, [37124, 60367], 37119, 37116, 37128, 37113, 37115,
- 37121, 37120, 37127, 37125, 37123, 37217, 37220, 37215, 37218, 37216,
- 37377, 37386, 37413, 37379, 37402, 37414, 37391, 37388, 37376, 37394,
- 37375, 37373, 37382, 37380, 37415, 37378, 37404, 37412, 37401, 37399,
- 37381, 37398, 38267, 38285, 38284, 38288, 38535, 38526, {f: 2, c: 38536},
- 38531, 38528, 38594, 38600, 38595, 38641, 38640, 38764, 38768, 38766,
- 38919, 39081, 39147, 40166, [12235, 40697], {f: 2, c: 20099}, 20150, 20669,
- 20671, 20678, 20654, 20676, 20682, 20660, 20680, 20674, 20656, 20673,
- 20666, 20657, 20683, 20681, 20662, 20664, 20951, 21114, 21112,
- {f: 2, c: 21115}, 21955, 21979, 21964, 21968, 21963, 21962, 21981,
- [21952, 64013], 21972, 21956, 21993, 21951, 21970, 21901, 21967, 21973,
- 21986, 21974, 21960, 22002, 21965, 21977, 21954, 22292, 22611, 22632,
- 22628, 22607, 22605, 22601, 22639, 22613, 22606, 22621, 22617, 22629,
- 22619, 22589, 22627, 22641, 22780, 23239, 23236, 23243, 23226, 23224,
- 23217, 23221, 23216, 23231, 23240, 23227, 23238, 23223, 23232, 23242,
- 23220, 23222, 23245, 23225, 23184, 23510, {f: 2, c: 23512}, 23583, 23603,
- 23921, 23907, 23882, 23909, 23922, 23916, 23902, 23912, 23911, 23906,
- 24048, 24143, 24142, 24138, 24141, 24139, 24261, 24268, 24262, 24267,
- 24263, 24384, 24495, 24493, 24823, {f: 2, c: 24905}, 24875, 24901, 24886,
- 24882, 24878, 24902, 24879, 24911, 24873, 24896, 25120, 37224, 25123,
- 25125, 25124, 25541, 25585, 25579, 25616, 25618, 25609, 25632, 25636,
- 25651, 25667, 25631, 25621, 25624, 25657, 25655, {f: 2, c: 25634}, 25612,
- 25638, 25648, 25640, 25665, 25653, 25647, 25610, 25626, 25664, 25637,
- 25639, 25611, 25575, 25627, 25646, 25633, 25614, 25967, 26002, 26067,
- 26246, 26252, 26261, 26256, 26251, 26250, 26265, 26260, 26232, 26400,
- 26982, 26975, 26936, 26958, 26978, 26993, 26943, 26949, 26986, 26937,
- 26946, 26967, 26969, 27002, {f: 2, c: 26952}, 26933, 26988, 26931, 26941,
- 26981, 26864, 27000, 26932, 26985, 26944, 26991, 26948, 26998, 26968,
- 26945, 26996, 26956, 26939, 26955, 26935, 26972, 26959, 26961, 26930,
- 26962, 26927, 27003, 26940, 27462, 27461, 27459, 27458, 27464, 27457,
- 27547, {f: 2, c: 27643}, 27641, {f: 2, c: 27639}, 28315, 28374, 28360,
- 28303, 28352, 28319, {f: 2, c: 28307}, 28320, 28337, 28345, 28358, 28370,
- 28349, 28353, 28318, 28361, 28343, 28336, 28365, 28326, 28367, 28338,
- 28350, 28355, 28380, 28376, 28313, 28306, 28302, 28301, 28324, 28321,
- 28351, 28339, 28368, 28362, 28311, 28334, 28323, 28999, 29012, 29010,
- 29027, 29024, 28993, 29021, [29026, 61080], 29042, 29048, 29034, 29025,
- 28994, 29016, 28995, 29003, 29040, 29023, 29008, 29011, 28996, 29005,
- 29018, 29263, 29325, 29324, 29329, 29328, 29326, 29500, 29506, 29499,
- 29498, 29504, 29514, 29513, 29764, {f: 2, c: 29770}, 29778, 29777, 29783,
- 29760, {f: 2, c: 29775}, 29774, 29762, 29766, 29773, 29780, 29921, 29951,
- 29950, 29949, 29981, 30073, 30071, 27011, 30191, 30223, 30211, 30199,
- 30206, 30204, [30201, 60782], 30200, 30224, 30203, 30198, 30189, 30197,
- 30205, 30361, 30389, 30429, 30549, {f: 2, c: 30559}, 30546, 30550, 30554,
- 30569, 30567, 30548, 30553, 30573, 30688, 30855, 30874, 30868, 30863,
- 30852, 30869, {f: 2, c: 30853}, 30881, 30851, 30841, 30873, 30848, 30870,
- 30843, 31100, 31106, 31101, 31097, 31249, {f: 2, c: 31256}, 31250, 31255,
- 31253, 31266, 31251, 31259, 31248, 31395, 31394, 31390, 31467, 31590,
- 31588, 31597, 31604, 31593, 31602, 31589, 31603, 31601, 31600, 31585,
- 31608, 31606, 31587, 31922, 31924, 31919, 32136, 32134, 32128, 32141,
- 32127, 32133, 32122, 32142, 32123, 32131, 32124, 32140, 32148, 32132,
- 32125, 32146, 32621, 32619, {f: 2, c: 32615}, 32620, 32678, 32677, 32679,
- {f: 2, c: 32731}, 32801, 33124, 33120, 33143, 33116, 33129, 33115, 33122,
- 33138, 26401, 33118, 33142, 33127, 33135, 33092, 33121, 33309, 33353,
- 33348, 33344, 33346, 33349, 34033, 33855, 33878, 33910, 33913, 33935,
- 33933, 33893, 33873, 33856, 33926, 33895, 33840, 33869, 33917, 33882,
- 33881, 33908, 33907, 33885, 34055, 33886, 33847, 33850, 33844, 33914,
- 33859, 33912, 33842, 33861, 33833, 33753, 33867, 33839, 33858, 33837,
- 33887, 33904, 33849, 33870, 33868, 33874, 33903, 33989, 33934, 33851,
- 33863, 33846, 33843, 33896, 33918, 33860, 33835, 33888, 33876, 33902,
- 33872, 34571, 34564, 34551, 34572, 34554, 34518, 34549, 34637, 34552,
- 34574, 34569, 34561, 34550, 34573, 34565, 35030, 35019, {f: 2, c: 35021},
- 35038, 35035, 35034, 35020, 35024, 35205, 35227, 35295, 35301, 35300,
- 35297, 35296, 35298, 35292, 35302, 35446, 35462, 35455, 35425, 35391,
- 35447, 35458, 35460, 35445, 35459, 35457, 35444, 35450, 35900, 35915,
- 35914, 35941, 35940, 35942, 35974, {f: 2, c: 35972}, 36044,
- {f: 2, c: 36200}, 36241, 36236, {f: 2, c: 36238}, 36237, {f: 2, c: 36243},
- 36240, 36242, 36336, 36320, 36332, 36337, 36334, 36304, 36329, 36323,
- 36322, 36327, 36338, 36331, 36340, 36614, 36607, 36609, 36608, 36613,
- {f: 2, c: 36615}, 36610, [36619, 60507], 36946, 36927, 36932, 36937, 36925,
- 37136, 37133, 37135, 37137, 37142, 37140, 37131, 37134, {f: 2, c: 37230},
- 37448, 37458, 37424, 37434, 37478, 37427, 37477, 37470, 37507, 37422,
- 37450, 37446, 37485, 37484, 37455, 37472, 37479, 37487, 37430, 37473,
- 37488, 37425, 37460, 37475, 37456, 37490, 37454, 37459, 37452, 37462,
- 37426, 38303, 38300, 38302, 38299, {f: 2, c: 38546}, 38545, 38551, 38606,
- 38650, 38653, 38648, 38645, 38771, {f: 2, c: 38775}, 38770, 38927,
- {f: 2, c: 38925}, 39084, 39158, 39161, 39343, 39346, 39344, 39349, 39597,
- 39595, 39771, 40170, 40173, 40167, 40576, [12236, 40701], 20710, 20692,
- 20695, 20712, 20723, 20699, 20714, 20701, 20708, 20691, 20716, 20720,
- 20719, 20707, 20704, 20952, {f: 2, c: 21120}, 21225, 21227, 21296, 21420,
- 22055, 22037, 22028, 22034, 22012, 22031, 22044, 22017, 22035, 22018,
- 22010, 22045, 22020, 22015, 22009, 22665, 22652, 22672, 22680, 22662,
- 22657, 22655, 22644, 22667, 22650, 22663, 22673, 22670, 22646, 22658,
- 22664, 22651, 22676, 22671, 22782, 22891, 23260, 23278, 23269, 23253,
- 23274, 23258, 23277, 23275, 23283, 23266, 23264, 23259, 23276, 23262,
- 23261, 23257, 23272, 23263, 23415, 23520, 23523, 23651, 23938, 23936,
- 23933, 23942, 23930, 23937, 23927, 23946, 23945, 23944, 23934, 23932,
- 23949, 23929, 23935, {f: 2, c: 24152}, 24147, 24280, 24273, 24279, 24270,
- 24284, 24277, 24281, 24274, 24276, 24388, 24387, 24431, 24502, 24876,
- 24872, 24897, 24926, 24945, 24947, {f: 2, c: 24914}, 24946, 24940, 24960,
- 24948, 24916, 24954, 24923, 24933, 24891, 24938, 24929, 24918, 25129,
- 25127, 25131, 25643, 25677, 25691, 25693, 25716, 25718, {f: 2, c: 25714},
- 25725, 25717, 25702, 25766, 25678, 25730, 25694, 25692, 25675, 25683,
- 25696, 25680, 25727, 25663, 25708, 25707, 25689, 25701, 25719, 25971,
- 26016, 26273, 26272, 26271, 26373, 26372, 26402, 27057, 27062, 27081,
- 27040, 27086, 27030, 27056, 27052, 27068, 27025, 27033, 27022, 27047,
- 27021, 27049, 27070, 27055, 27071, 27076, 27069, 27044, 27092, 27065,
- 27082, 27034, 27087, 27059, 27027, 27050, 27041, 27038, 27097, 27031,
- 27024, 27074, 27061, 27045, 27078, 27466, 27469, 27467, {f: 3, c: 27550},
- {f: 2, c: 27587}, 27646, 28366, 28405, 28401, 28419, 28453, 28408, 28471,
- 28411, 28462, 28425, 28494, {f: 2, c: 28441}, 28455, 28440, 28475, 28434,
- 28397, 28426, 28470, 28531, 28409, 28398, 28461, 28480, 28464, 28476,
- 28469, 28395, 28423, 28430, 28483, 28421, 28413, 28406, 28473, 28444,
- 28412, 28474, 28447, 28429, 28446, 28424, 28449, 29063, 29072, 29065,
- 29056, 29061, 29058, 29071, 29051, 29062, 29057, 29079, 29252, 29267,
- 29335, 29333, 29331, 29507, 29517, 29521, 29516, 29794, 29811, 29809,
- 29813, 29810, 29799, 29806, 29952, {f: 2, c: 29954}, 30077, 30096, 30230,
- 30216, 30220, 30229, 30225, 30218, 30228, 30392, 30593, 30588, 30597,
- 30594, 30574, 30592, 30575, 30590, 30595, 30898, 30890, 30900, 30893,
- 30888, 30846, 30891, 30878, 30885, 30880, 30892, 30882, 30884, 31128,
- {f: 2, c: 31114}, 31126, 31125, 31124, 31123, 31127, 31112, 31122, 31120,
- 31275, 31306, 31280, 31279, 31272, 31270, 31400, {f: 2, c: 31403}, 31470,
- 31624, 31644, 31626, 31633, 31632, 31638, 31629, 31628, 31643, 31630,
- 31621, 31640, 21124, 31641, 31652, 31618, 31931, 31935, 31932, 31930,
- 32167, 32183, 32194, 32163, 32170, 32193, 32192, 32197, 32157, 32206,
- 32196, 32198, {f: 2, c: 32203}, 32175, 32185, 32150, 32188, 32159, 32166,
- 32174, 32169, 32161, 32201, 32627, {f: 2, c: 32738}, 32741, 32734, 32804,
- 32861, 32860, 33161, 33158, 33155, 33159, 33165, 33164, 33163, 33301,
- 33943, 33956, 33953, 33951, 33978, 33998, 33986, 33964, 33966, 33963,
- 33977, 33972, 33985, 33997, 33962, 33946, 33969, 34000, 33949, 33959,
- 33979, 33954, 33940, 33991, 33996, 33947, 33961, 33967, [33960, 58327],
- 34006, 33944, 33974, 33999, 33952, 34007, 34004, 34002, 34011, 33968,
- 33937, 34401, 34611, 34595, 34600, 34667, 34624, 34606, 34590, 34593,
- 34585, 34587, 34627, 34604, 34625, 34622, 34630, 34592, 34610, 34602,
- 34605, 34620, 34578, 34618, 34609, 34613, 34626, {f: 2, c: 34598}, 34616,
- 34596, 34586, 34608, 34577, 35063, 35047, {f: 2, c: 35057}, 35066, 35070,
- 35054, 35068, 35062, 35067, 35056, 35052, 35051, 35229, 35233, 35231,
- 35230, 35305, 35307, 35304, 35499, 35481, 35467, 35474, 35471, 35478,
- 35901, {f: 2, c: 35944}, 36053, 36047, 36055, 36246, 36361, 36354, 36351,
- 36365, 36349, 36362, 36355, 36359, 36358, 36357, 36350, 36352, 36356,
- {f: 2, c: 36624}, 36622, 36621, 37155, 37148, 37152, 37154, 37151, 37149,
- 37146, 37156, 37153, 37147, 37242, 37234, 37241, 37235, 37541, 37540,
- 37494, 37531, 37498, 37536, 37524, 37546, 37517, 37542, 37530, 37547,
- 37497, 37527, 37503, 37539, 37614, 37518, 37506, 37525, 37538, 37501,
- 37512, 37537, 37514, 37510, 37516, 37529, 37543, 37502, 37511, 37545,
- 37533, 37515, 37421, 38558, 38561, 38655, 38744, 38781, 38778, 38782,
- 38787, 38784, 38786, 38779, 38788, 38785, 38783, 38862, 38861, 38934,
- {f: 2, c: 39085}, 39170, 39168, 39175, 39325, 39324, 39363, 39353, 39355,
- 39354, 39362, 39357, 39367, 39601, 39651, 39655, {f: 2, c: 39742},
- {f: 2, c: 39776}, 39775, {f: 2, c: 40177}, 40181, 40615, 20735, 20739,
- 20784, 20728, {f: 2, c: 20742}, 20726, 20734, {f: 2, c: 20747}, 20733,
- 20746, {f: 2, c: 21131}, 21233, 21231, 22088, 22082, 22092, 22069, 22081,
- 22090, 22089, 22086, 22104, 22106, 22080, 22067, 22077, 22060, 22078,
- 22072, 22058, 22074, 22298, 22699, 22685, 22705, 22688, 22691, 22703,
- 22700, 22693, 22689, 22783, 23295, 23284, 23293, 23287, 23286, 23299,
- 23288, 23298, 23289, 23297, 23303, 23301, 23311, 23655, 23961, 23959,
- 23967, 23954, 23970, 23955, 23957, 23968, 23964, 23969, 23962, 23966,
- 24169, 24157, 24160, 24156, 32243, 24283, 24286, 24289, 24393, 24498,
- 24971, 24963, 24953, 25009, 25008, 24994, 24969, 24987, 24979, 25007,
- 25005, 24991, 24978, 25002, 24993, 24973, 24934, 25011, 25133, 25710,
- 25712, 25750, 25760, 25733, 25751, 25756, 25743, 25739, 25738, 25740,
- 25763, 25759, 25704, 25777, 25752, 25974, 25978, 25977, 25979,
- {f: 2, c: 26034}, 26293, 26288, 26281, 26290, 26295, 26282, 26287, 27136,
- 27142, 27159, 27109, 27128, 27157, 27121, 27108, 27168, 27135, 27116,
- 27106, 27163, 27165, 27134, 27175, 27122, 27118, 27156, 27127, 27111,
- 27200, 27144, 27110, 27131, 27149, 27132, 27115, 27145, 27140, 27160,
- 27173, 27151, 27126, 27174, 27143, 27124, 27158, 27473, 27557, 27555,
- 27554, 27558, 27649, 27648, 27647, 27650, 28481, 28454, 28542, 28551,
- 28614, 28562, 28557, 28553, 28556, 28514, 28495, 28549, 28506, 28566,
- 28534, 28524, 28546, 28501, 28530, 28498, 28496, 28503, 28564, 28563,
- 28509, 28416, 28513, 28523, 28541, 28519, 28560, 28499, 28555, 28521,
- 28543, 28565, 28515, 28535, 28522, 28539, 29106, 29103, 29083, 29104,
- 29088, 29082, 29097, 29109, 29085, 29093, 29086, 29092, 29089, 29098,
- 29084, 29095, 29107, 29336, 29338, 29528, 29522, {f: 3, c: 29534}, 29533,
- 29531, 29537, 29530, 29529, 29538, 29831, {f: 2, c: 29833}, 29830, 29825,
- 29821, 29829, 29832, 29820, [29817, 58868], 29960, 29959, 30078, 30245,
- 30238, 30233, 30237, 30236, 30243, 30234, 30248, 30235, {f: 3, c: 30364},
- 30363, 30605, 30607, 30601, 30600, 30925, 30907, 30927, 30924, 30929,
- 30926, 30932, 30920, {f: 2, c: 30915}, 30921, 31130, 31137, 31136, 31132,
- 31138, [31131, 59175], 27510, 31289, 31410, 31412, 31411, 31671, 31691,
- 31678, 31660, 31694, 31663, 31673, 31690, 31669, 31941, 31944, 31948,
- 31947, 32247, 32219, 32234, 32231, 32215, 32225, 32259, 32250, 32230,
- 32246, 32241, 32240, 32238, 32223, 32630, 32684, 32688, 32685, 32749,
- 32747, 32746, 32748, 32742, 32744, 32868, 32871, 33187, 33183, 33182,
- 33173, 33186, 33177, 33175, 33302, 33359, 33363, 33362, 33360, 33358,
- 33361, 34084, 34107, 34063, 34048, 34089, 34062, 34057, 34061, 34079,
- 34058, 34087, 34076, 34043, 34091, 34042, 34056, 34060, 34036, 34090,
- 34034, 34069, 34039, 34027, 34035, 34044, 34066, 34026, 34025, 34070,
- 34046, 34088, 34077, 34094, 34050, 34045, 34078, 34038, 34097, 34086,
- {f: 2, c: 34023}, 34032, 34031, 34041, 34072, 34080, 34096, 34059, 34073,
- 34095, 34402, 34646, {f: 2, c: 34659}, 34679, 34785, 34675, 34648, 34644,
- 34651, 34642, 34657, 34650, 34641, 34654, 34669, 34666, 34640, 34638,
- 34655, 34653, 34671, 34668, 34682, 34670, 34652, 34661, 34639, 34683,
- 34677, 34658, 34663, 34665, 34906, 35077, 35084, 35092, 35083,
- {f: 3, c: 35095}, 35078, 35094, 35089, 35086, 35081, 35234, 35236, 35235,
- 35309, 35312, 35308, 35535, 35526, 35512, 35539, 35537, {f: 2, c: 35540},
- 35515, 35543, 35518, 35520, 35525, 35544, 35523, 35514, 35517, 35545,
- 35902, 35917, 35983, 36069, 36063, 36057, 36072, 36058, 36061, 36071,
- 36256, 36252, 36257, 36251, 36384, 36387, 36389, 36388, 36398, 36373,
- 36379, 36374, 36369, 36377, {f: 2, c: 36390}, 36372, 36370, 36376, 36371,
- 36380, 36375, 36378, 36652, 36644, 36632, 36634, 36640, 36643,
- {f: 2, c: 36630}, 36979, 36976, 36975, 36967, 36971, 37167, 37163,
- {f: 2, c: 37161}, 37170, 37158, 37166, {f: 2, c: 37253}, 37258,
- {f: 2, c: 37249}, 37252, 37248, 37584, {f: 2, c: 37571}, 37568, 37593,
- 37558, 37583, 37617, 37599, 37592, 37609, 37591, 37597, 37580, 37615,
- 37570, 37608, 37578, 37576, 37582, 37606, 37581, 37589, 37577, 37600,
- 37598, 37607, 37585, 37587, 37557, 37601, 37669, 37574, 37556, 38268,
- 38316, 38315, 38318, 38320, 38564, 38562, 38611, 38661, 38664, 38658,
- 38746, 38794, 38798, 38792, 38864, 38863, 38942, 38941, 38950, 38953,
- 38952, 38944, 38939, 38951, 39090, 39176, 39162, 39185, 39188,
- {f: 2, c: 39190}, 39189, 39388, 39373, 39375, {f: 2, c: 39379}, 39374,
- 39369, [39382, 60270], 39384, 39371, 39383, 39372, 39603, 39660, 39659,
- 39667, 39666, 39665, 39750, 39747, 39783, 39796, 39793, 39782, 39798,
- 39797, 39792, 39784, 39780, 39788, 40188, 40186, 40189, 40191, 40183,
- 40199, 40192, 40185, 40187, 40200, 40197, 40196, 40579, 40659,
- {f: 2, c: 40719}, 20764, 20755, 20759, 20762, 20753, 20958, 21300, 21473,
- 22128, 22112, 22126, 22131, 22118, 22115, 22125, 22130, 22110, 22135,
- 22300, 22299, 22728, 22717, 22729, 22719, 22714, 22722, 22716, 22726,
- 23319, 23321, 23323, 23329, 23316, 23315, 23312, 23318, [23336, 59539],
- 23322, 23328, 23326, 23535, 23980, 23985, 23977, 23975, 23989, 23984,
- 23982, 23978, 23976, 23986, 23981, 23983, 23988, {f: 2, c: 24167}, 24166,
- 24175, 24297, 24295, 24294, 24296, 24293, 24395, 24508, 24507, 24989,
- 25000, 24982, 25029, 25012, 25030, 25025, 25036, 25018, 25023, 25016,
- 24972, 25815, 25814, 25808, 25807, 25801, 25789, 25737, 25795, 25819,
- 25843, 25817, 25907, 25983, 25980, 26018, 26312, 26302, 26304,
- {f: 2, c: 26314}, 26319, 26301, 26299, 26298, 26316, 26403, 27188, 27238,
- 27209, 27239, 27186, 27240, 27198, 27229, 27245, 27254, 27227, 27217,
- 27176, 27226, 27195, 27199, 27201, 27242, 27236, 27216, 27215, 27220,
- 27247, 27241, 27232, 27196, 27230, 27222, 27221, {f: 2, c: 27213}, 27206,
- 27477, 27476, 27478, 27559, {f: 2, c: 27562}, 27592, 27591, 27652, 27651,
- 27654, 28589, 28619, 28579, 28615, 28604, 28622, 28616, 28510, 28612,
- 28605, 28574, 28618, 28584, 28676, 28581, 28590, 28602, 28588, 28586,
- 28623, 28607, 28600, 28578, 28617, 28587, 28621, 28591, 28594, 28592,
- 29125, 29122, 29119, 29112, 29142, {f: 2, c: 29120}, 29131, 29140, 29130,
- 29127, 29135, 29117, 29144, 29116, 29126, {f: 2, c: 29146},
- {f: 2, c: 29341}, 29545, {f: 2, c: 29542}, 29548, 29541, 29547, 29546,
- 29823, 29850, 29856, 29844, 29842, 29845, 29857, 29963, 30080, 30255,
- 30253, 30257, 30269, 30259, 30268, 30261, 30258, 30256, 30395, 30438,
- 30618, 30621, 30625, 30620, 30619, {f: 2, c: 30626}, 30613, 30617, 30615,
- 30941, 30953, 30949, 30954, 30942, 30947, 30939, {f: 2, c: 30945}, 30957,
- {f: 2, c: 30943}, 31140, 31300, 31304, 31303, 31414, 31416, 31413, 31409,
- 31415, 31710, 31715, 31719, 31709, 31701, 31717, 31706, 31720, 31737,
- 31700, 31722, 31714, 31708, 31723, 31704, 31711, 31954, 31956, 31959,
- {f: 2, c: 31952}, 32274, 32289, 32279, 32268, {f: 2, c: 32287}, 32275,
- 32270, 32284, 32277, 32282, 32290, 32267, 32271, 32278, 32269, 32276,
- 32293, 32292, 32579, {f: 2, c: 32635}, 32634, 32689, 32751, 32810, 32809,
- 32876, 33201, 33190, 33198, 33209, 33205, 33195, 33200, 33196, 33204,
- 33202, 33207, 33191, 33266, {f: 3, c: 33365}, 34134, 34117, 34155, 34125,
- 34131, 34145, 34136, 34112, 34118, 34148, 34113, 34146, 34116, 34129,
- 34119, 34147, 34110, 34139, 34161, 34126, 34158, 34165, 34133, 34151,
- 34144, 34188, 34150, 34141, 34132, 34149, 34156, 34403, 34405, 34404,
- 34724, 34715, 34703, 34711, 34707, 34706, 34696, 34689, 34710, 34712,
- 34681, 34695, 34723, 34693, {f: 2, c: 34704}, 34717, 34692, 34708, 34716,
- 34714, 34697, 35102, 35110, 35120, {f: 2, c: 35117}, 35111, 35121, 35106,
- 35113, 35107, 35119, 35116, 35103, 35313, 35552, 35554, 35570,
- {f: 2, c: 35572}, 35549, 35604, 35556, 35551, 35568, 35528, 35550, 35553,
- 35560, 35583, 35567, 35579, {f: 2, c: 35985}, 35984, 36085, 36078, 36081,
- 36080, 36083, 36204, 36206, 36261, 36263, 36403, 36414, 36408, 36416,
- 36421, 36406, {f: 2, c: 36412}, 36417, 36400, 36415, 36541, [36662, 60329],
- 36654, 36661, 36658, 36665, 36663, 36660, 36982, 36985, 36987, 36998,
- 37114, 37171, {f: 2, c: 37173}, 37267, {f: 2, c: 37264}, 37261, 37263,
- 37671, 37662, 37640, 37663, 37638, 37647, 37754, 37688, 37692, 37659,
- 37667, 37650, 37633, 37702, 37677, 37646, 37645, 37579, 37661, 37626,
- 37651, 37625, 37623, 37684, 37634, 37668, 37631, 37673, 37689, 37685,
- 37674, 37652, 37644, 37643, 37630, 37641, 37632, 37627, 37654, 38332,
- 38349, 38334, {f: 2, c: 38329}, 38326, 38335, 38325, 38333, 38569, 38612,
- 38667, 38674, 38672, 38809, 38807, 38804, 38896, 38904, 38965, 38959,
- 38962, 39204, 39199, 39207, 39209, 39326, 39406, 39404, 39397, 39396,
- 39408, 39395, 39402, 39401, 39399, 39609, 39615, 39604, 39611, 39670,
- 39674, 39673, 39671, 39731, 39808, 39813, 39815, 39804, 39806, 39803,
- 39810, 39827, 39826, 39824, 39802, 39829, 39805, 39816, 40229, 40215,
- 40224, 40222, 40212, 40233, 40221, 40216, 40226, 40208, 40217, 40223,
- 40584, {f: 2, c: 40582}, 40622, 40621, {f: 2, c: 40661}, 40698, 40722,
- 40765, 20774, 20773, 20770, 20772, 20768, 20777, 21236, 22163,
- {f: 2, c: 22156}, 22150, 22148, 22147, 22142, 22146, 22143, 22145, 22742,
- 22740, 22735, 22738, 23341, 23333, 23346, 23331, 23340, 23335, 23334,
- 23343, 23342, 23419, {f: 2, c: 23537}, 23991, 24172, 24170, 24510, 25027,
- 25013, 25020, 25063, 25056, 25061, 25060, 25064, 25054, 25839, 25833,
- 25827, 25835, 25828, 25832, 25985, 25984, 26038, 26074, 26322, 27277,
- 27286, 27265, 27301, 27273, 27295, 27291, 27297, 27294, 27271, 27283,
- 27278, 27285, 27267, 27304, 27300, 27281, 27263, 27302, 27290, 27269,
- 27276, 27282, 27483, 27565, 27657, 28620, 28585, 28660, 28628, 28643,
- 28636, 28653, 28647, 28646, 28638, 28658, 28637, 28642, 28648, 29153,
- 29169, 29160, 29170, 29156, 29168, 29154, 29555, {f: 2, c: 29550}, 29847,
- 29874, 29867, 29840, 29866, 29869, 29873, 29861, 29871, {f: 3, c: 29968},
- 29967, 30084, 30275, {f: 2, c: 30280}, 30279, 30372, 30441, 30645, 30635,
- 30642, 30647, 30646, 30644, 30641, 30632, 30704, 30963, 30973, 30978,
- {f: 2, c: 30971}, 30975, 30962, 30981, 30969, 30974, 30980, 31147, 31144,
- 31324, 31323, 31318, 31320, 31316, 31322, 31422, {f: 2, c: 31424}, 31749,
- 31759, 31730, 31744, 31743, 31739, 31758, 31732, 31755, 31731, 31746,
- 31753, 31747, 31745, 31736, 31741, [31750, 58176], {f: 2, c: 31728}, 31760,
- 31754, 31976, 32301, 32316, 32322, 32307, 38984, 32312, 32298, 32329,
- 32320, 32327, 32297, 32332, 32304, 32315, 32310, 32324, 32314, 32581,
- 32639, 32638, 32637, 32756, 32754, 32812, 33211, 33220, 33228, 33226,
- 33221, 33223, 33212, 33257, 33371, 33370, 33372, 34179, 34176, 34191,
- 34215, 34197, 34208, 34187, 34211, 34171, 34212, 34202, 34206, 34167,
- 34172, 34185, 34209, 34170, 34168, 34135, 34190, 34198, 34182, 34189,
- 34201, 34205, 34177, 34210, 34178, 34184, 34181, 34169, 34166, 34200,
- 34192, 34207, 34408, 34750, 34730, 34733, 34757, 34736, 34732, 34745,
- 34741, 34748, 34734, 34761, 34755, 34754, 34764, 34743, 34735, 34756,
- 34762, 34740, 34742, 34751, 34744, 34749, 34782, 34738, 35125, 35123,
- 35132, 35134, 35137, 35154, 35127, 35138, 35245, 35247, 35246,
- {f: 2, c: 35314}, 35614, 35608, 35606, 35601, 35589, 35595, 35618, 35599,
- 35602, 35605, 35591, 35597, 35592, 35590, 35612, 35603, 35610, 35919,
- 35952, 35954, 35953, 35951, 35989, 35988, 36089, 36207, 36430, 36429,
- 36435, 36432, 36428, 36423, 36675, 36672, 36997, 36990, 37176, 37274,
- 37282, 37275, 37273, 37279, 37281, 37277, 37280, 37793, 37763, 37807,
- 37732, 37718, 37703, 37756, 37720, 37724, 37750, 37705, {f: 2, c: 37712},
- 37728, 37741, 37775, 37708, 37738, 37753, 37719, 37717, 37714, 37711,
- 37745, 37751, 37755, 37729, 37726, 37731, 37735, 37710, 37721, 38343,
- 38336, 38345, 38339, 38341, 38327, 38574, 38576, 38572, 38688, 38687,
- 38680, 38685, 38681, 38810, 38817, 38812, 38814, 38813, 38869, 38868,
- 38897, 38977, 38980, 38986, 38985, 38981, 38979, 39205, {f: 2, c: 39211},
- 39210, 39219, 39218, 39215, 39213, 39217, 39216, 39320, 39331, 39329,
- 39426, 39418, 39412, 39415, 39417, 39416, 39414, 39419, {f: 2, c: 39421},
- 39420, 39427, 39614, 39678, 39677, 39681, 39676, 39752, 39834, 39848,
- 39838, 39835, 39846, 39841, 39845, 39844, 39814, 39842, 39840, 39855,
- 40243, 40257, 40295, 40246, {f: 2, c: 40238}, 40241, 40248, 40240, 40261,
- {f: 2, c: 40258}, 40254, 40247, 40256, 40253, 32757, 40237, 40586, 40585,
- 40589, 40624, 40648, 40666, 40699, 40703, 40740, 40739, 40738, 40788,
- [12245, 40864], 20785, {f: 2, c: 20781}, 22168, 22172, 22167, 22170, 22173,
- 22169, 22896, 23356, {f: 2, c: 23657}, 24000, {f: 2, c: 24173}, 25048,
- 25055, {f: 2, c: 25069}, 25073, 25066, 25072, 25067, 25046, 25065, 25855,
- 25860, 25853, 25848, 25857, 25859, 25852, 26004, 26075, {f: 2, c: 26330},
- 26328, 27333, 27321, 27325, 27361, 27334, 27322, {f: 2, c: 27318}, 27335,
- 27316, 27309, 27486, 27593, 27659, 28679, {f: 2, c: 28684}, 28673, 28677,
- 28692, 28686, {f: 2, c: 28671}, 28667, 28710, 28668, 28663, 28682,
- [29185, 60224], 29183, 29177, 29187, 29181, 29558, 29880, 29888, 29877,
- 29889, 29886, 29878, 29883, 29890, 29972, 29971, 30300, 30308, 30297,
- 30288, 30291, 30295, 30298, 30374, 30397, 30444, 30658, 30650, 30988,
- {f: 2, c: 30995}, 30985, 30992, 30994, 30993, 31149, 31148, 31327, 31772,
- 31785, 31769, 31776, 31775, 31789, 31773, 31782, 31784, 31778, 31781,
- 31792, 32348, 32336, 32342, 32355, 32344, 32354, 32351, 32337, 32352,
- 32343, 32339, 32693, 32691, {f: 2, c: 32759}, 32885, {f: 2, c: 33233},
- 33232, 33375, 33374, 34228, 34246, 34240, 34243, 34242, 34227, 34229,
- 34237, 34247, 34244, 34239, 34251, 34254, 34248, 34245, 34225, 34230,
- 34258, 34340, 34232, 34231, 34238, 34409, 34791, 34790, 34786, 34779,
- 34795, 34794, 34789, 34783, 34803, 34788, 34772, 34780, 34771, 34797,
- 34776, 34787, 34775, 34777, 34817, 34804, 34792, 34781, 35155, 35147,
- 35151, 35148, 35142, {f: 2, c: 35152}, 35145, 35626, 35623, 35619, 35635,
- 35632, 35637, 35655, 35631, 35644, 35646, 35633, 35621, 35639, 35622,
- 35638, 35630, 35620, 35643, 35645, 35642, 35906, 35957, 35993, 35992,
- 35991, 36094, 36100, 36098, 36096, 36444, 36450, 36448, 36439, 36438,
- 36446, 36453, 36455, 36443, 36442, 36449, 36445, 36457, 36436,
- {f: 3, c: 36678}, 36683, 37160, {f: 2, c: 37178}, 37182, 37288, 37285,
- 37287, 37295, 37290, 37813, 37772, 37778, 37815, 37787, 37789, 37769,
- 37799, 37774, 37802, 37790, 37798, 37781, 37768, 37785, 37791, 37760,
- 37773, 37809, 37777, 37810, 37796, 37800, 37812, 37795, {f: 2, c: 38354},
- 38353, 38579, 38615, 38618, 24002, 38623, 38616, 38621, 38691, 38690,
- 38693, 38828, 38830, 38824, 38827, 38820, 38826, 38818, 38821, 38871,
- 38873, 38870, 38872, 38906, {f: 3, c: 38992}, 39096, 39233, 39228, 39226,
- 39439, 39435, 39433, 39437, 39428, 39441, 39434, 39429, 39431, 39430,
- 39616, 39644, 39688, {f: 2, c: 39684}, 39721, 39733, 39754, 39756, 39755,
- 39879, 39878, 39875, 39871, 39873, 39861, 39864, 39891, 39862, 39876,
- 39865, 39869, 40284, 40275, 40271, 40266, 40283, 40267, 40281, 40278,
- 40268, 40279, 40274, 40276, 40287, 40280, 40282, 40590, 40588, 40671,
- 40705, 40704, [40726, 58693], 40741, 40747, 40746, 40745, 40744, 40780,
- 40789, {f: 2, c: 20788}, 21142, 21239, 21428, 22187, 22189,
- {f: 2, c: 22182}, 22186, 22188, 22746, 22749, 22747, 22802,
- {f: 3, c: 23357}, 24003, 24176, 24511, 25083, 25863, 25872, 25869, 25865,
- 25868, 25870, 25988, 26078, 26077, 26334, 27367, 27360, 27340, 27345,
- 27353, 27339, 27359, 27356, 27344, 27371, 27343, 27341, 27358, 27488,
- 27568, 27660, 28697, 28711, 28704, 28694, 28715, {f: 3, c: 28705}, 28713,
- 28695, 28708, 28700, 29196, 29194, 29191, 29186, 29189, {f: 2, c: 29349},
- 29348, 29347, 29345, 29899, 29893, 29879, 29891, 29974, 30304,
- {f: 2, c: 30665}, 30660, 30705, 31005, 31003, 31009, 31004, 30999, 31006,
- 31152, {f: 2, c: 31335}, 31795, 31804, 31801, 31788, 31803, 31980, 31978,
- 32374, 32373, 32376, 32368, 32375, 32367, 32378, 32370, 32372, 32360,
- 32587, 32586, 32643, 32646, 32695, {f: 2, c: 32765}, 32888, 33239, 33237,
- 33291, 33380, 33377, 33379, 34283, 34289, 34285, 34265, 34273, 34280,
- 34266, 34263, 34284, 34290, 34296, 34264, 34271, 34275, 34268, 34257,
- 34288, 34278, 34287, 34270, 34274, 34816, 34810, 34819, {f: 2, c: 34806},
- 34825, 34828, 34827, 34822, 34812, 34824, 34815, 34826, 34818, 35170,
- {f: 2, c: 35162}, 35159, 35169, 35164, 35160, 35165, 35161, 35208, 35255,
- 35254, 35318, 35664, 35656, 35658, 35648, 35667, 35670, 35668, 35659,
- 35669, 35665, 35650, 35666, 35671, 35907, 35959, 35958, 35994,
- {f: 2, c: 36102}, 36105, 36268, 36266, 36269, 36267, 36461, 36472, 36467,
- 36458, 36463, 36475, 36546, 36690, 36689, {f: 2, c: 36687}, 36691, 36788,
- 37184, 37183, 37296, 37293, 37854, 37831, 37839, 37826, 37850, 37840,
- 37881, 37868, 37836, 37849, 37801, 37862, 37834, 37844, 37870, 37859,
- 37845, 37828, 37838, 37824, 37842, 37797, 37863, 38269, {f: 2, c: 38362},
- 38625, 38697, {f: 2, c: 38699}, 38696, 38694, 38835, 38839, 38838,
- {f: 3, c: 38877}, 39004, 39001, 39005, 38999, 39103, 39101, 39099, 39102,
- 39240, 39239, 39235, {f: 2, c: 39334}, 39450, 39445, 39461, 39453, 39460,
- 39451, 39458, 39456, 39463, 39459, 39454, 39452, 39444, 39618, 39691,
- 39690, 39694, 39692, 39735, {f: 2, c: 39914}, 39904, 39902, 39908, 39910,
- 39906, 39920, 39892, 39895, 39916, 39900, 39897, 39909, 39893, 39905,
- 39898, 40311, 40321, 40330, 40324, 40328, 40305, 40320, 40312, 40326,
- {f: 2, c: 40331}, 40317, 40299, {f: 2, c: 40308}, 40304, 40297, 40325,
- 40307, 40315, 40322, 40303, 40313, 40319, 40327, 40296, 40596, 40593,
- 40640, 40700, 40749, {f: 2, c: 40768}, 40781, {f: 3, c: 40790}, 21303,
- 22194, 22197, 22195, 22755, 23365, {f: 2, c: 24006}, {f: 2, c: 24302},
- {f: 2, c: 24512}, 25081, 25879, 25878, 25877, 25875, 26079, 26344,
- {f: 2, c: 26339}, 27379, 27376, 27370, 27368, 27385, 27377,
- {f: 2, c: 27374}, 28732, 28725, 28719, 28727, 28724, 28721, 28738, 28728,
- 28735, 28730, 28729, 28714, 28736, 28731, 28723, 28737, {f: 2, c: 29203},
- 29352, 29565, 29564, 29882, 30379, 30378, 30398, 30445, 30668,
- {f: 2, c: 30670}, 30669, 30706, 31013, 31011, {f: 2, c: 31015}, 31012,
- 31017, 31154, 31342, {f: 2, c: 31340}, 31479, 31817, 31816, 31818, 31815,
- 31813, 31982, 32379, 32382, 32385, 32384, 32698, 32767, 32889, 33243,
- 33241, {f: 2, c: 33384}, 34338, 34303, 34305, 34302, 34331, 34304, 34294,
- 34308, 34313, 34309, 34316, 34301, 34841, {f: 2, c: 34832}, 34839, 34835,
- 34838, 35171, 35174, 35257, 35319, 35680, 35690, 35677, 35688, 35683,
- 35685, 35687, 35693, 36270, 36486, 36488, 36484, 36697, {f: 2, c: 36694},
- 36693, 36696, 36698, 37005, 37187, 37185, 37303, 37301, {f: 2, c: 37298},
- 37899, 37907, 37883, 37920, 37903, 37908, 37886, 37909, 37904, 37928,
- 37913, 37901, 37877, 37888, 37879, 37895, 37902, 37910, 37906, 37882,
- 37897, 37880, 37948, 37898, 37887, 37884, 37900, 37878, 37905, 37894,
- 38366, 38368, 38367, {f: 2, c: 38702}, 38841, 38843, {f: 2, c: 38909},
- 39008, {f: 2, c: 39010}, 39007, {f: 2, c: 39105}, 39248, 39246, 39257,
- 39244, 39243, 39251, 39474, 39476, 39473, 39468, 39466, 39478, 39465,
- 39470, 39480, 39469, 39623, 39626, 39622, 39696, 39698, 39697, 39947,
- 39944, 39927, 39941, 39954, 39928, 40000, 39943, 39950, 39942, 39959,
- 39956, 39945, 40351, 40345, 40356, 40349, 40338, 40344, 40336, 40347,
- 40352, 40340, 40348, 40362, 40343, 40353, 40346, 40354, 40360, 40350,
- 40355, 40383, 40361, 40342, {f: 2, c: 40358}, 40601, 40603, 40602, 40677,
- 40676, 40679, 40678, 40752, 40750, 40795, 40800, 40798, 40797, 40793,
- 40849, 20794, 20793, 21144, 21143, 22211, {f: 2, c: 22205}, 23368, 23367,
- 24011, 24015, 24305, 25085, 25883, 27394, 27388, 27395, 27384, 27392,
- {f: 2, c: 28739}, 28746, {f: 2, c: 28744}, {f: 2, c: 28741}, 29213, 29210,
- 29209, 29566, 29975, 30314, 30672, 31021, 31025, 31023, 31828, 31827,
- 31986, 32394, [32391, 60229], 32392, 32395, 32390, 32397, 32589, 32699,
- 32816, 33245, 34328, 34346, 34342, 34335, 34339, 34332, 34329, 34343,
- 34350, 34337, 34336, 34345, 34334, 34341, 34857, 34845, 34843, 34848,
- 34852, 34844, 34859, 34890, 35181, 35177, 35182, 35179, 35322, 35705,
- 35704, 35653, {f: 2, c: 35706}, 36112, 36116, 36271, 36494, 36492, 36702,
- 36699, 36701, 37190, {f: 2, c: 37188}, 37305, 37951, 37947, 37942, 37929,
- 37949, 37936, 37945, 37930, 37943, 37932, 37952, 37937, 38373, 38372,
- 38371, 38709, 38714, 38847, 38881, 39012, 39113, 39110, 39104, 39256,
- 39254, 39481, 39485, 39494, 39492, 39490, 39489, 39482, 39487, 39629,
- 39701, {f: 2, c: 39703}, 39702, 39738, 39762, 39979, 39965, 39964, 39980,
- 39971, {f: 2, c: 39976}, 39972, 39969, 40375, 40374, 40380, 40385, 40391,
- 40394, 40399, 40382, 40389, 40387, 40379, 40373, 40398, {f: 2, c: 40377},
- 40364, 40392, 40369, 40365, 40396, 40371, 40397, 40370, 40570, 40604,
- 40683, 40686, 40685, 40731, 40728, 40730, 40753, 40782, 40805, 40804,
- 40850, 20153, 22214, 22213, 22219, 22897, {f: 2, c: 23371}, 24021, 24017,
- 24306, 25889, 25888, 25894, 25890, 27403, {f: 2, c: 27400}, 27661,
- {f: 3, c: 28757}, 28754, {f: 2, c: 29214}, 29353, 29567, 29912, 29909,
- 29913, 29911, 30317, 30381, 31029, 31156, {f: 2, c: 31344}, 31831, 31836,
- 31833, 31835, 31834, 31988, 31985, 32401, 32591, 32647, 33246, 33387,
- {f: 2, c: 34356}, 34355, 34348, 34354, 34358, 34860, 34856, 34854, 34858,
- 34853, 35185, 35263, 35262, 35323, 35710, 35716, 35714, 35718, 35717,
- 35711, 36117, 36501, 36500, 36506, 36498, 36496, {f: 2, c: 36502}, 36704,
- 36706, 37191, 37964, 37968, {f: 2, c: 37962}, 37967, 37959, 37957,
- {f: 2, c: 37960}, 37958, 38719, 38883, 39018, 39017, 39115, 39252, 39259,
- 39502, {f: 2, c: 39507}, 39500, 39503, 39496, 39498, 39497, 39506, 39504,
- 39632, 39705, 39723, 39739, 39766, 39765, 40006, 40008, 39999, 40004,
- 39993, 39987, 40001, 39996, 39991, 39988, 39986, 39997, 39990, 40411,
- 40402, 40414, 40410, 40395, 40400, 40412, 40401, 40415, 40425, 40409,
- 40408, 40406, 40437, 40405, 40413, 40630, 40688, 40757, 40755, 40754,
- 40770, 40811, 40853, 40866, 20797, 21145, 22760, 22759, 22898, 23373,
- 24024, 34863, 24399, 25089, {f: 2, c: 25091}, 25897, 25893, 26006, 26347,
- {f: 2, c: 27409}, 27407, 27594, 28763, 28762, 29218, 29570, 29569, 29571,
- 30320, 30676, 31847, 31846, 32405, 33388, 34362, 34368, 34361, 34364,
- 34353, 34363, 34366, 34864, 34866, 34862, 34867, 35190, 35188, 35187,
- 35326, 35724, 35726, 35723, 35720, 35909, 36121, 36504, 36708, 36707,
- 37308, 37986, 37973, 37981, 37975, 37982, {f: 2, c: 38852}, 38912, 39510,
- 39513, {f: 3, c: 39710}, 40018, 40024, 40016, 40010, 40013, 40011, 40021,
- 40025, 40012, 40014, 40443, 40439, 40431, 40419, 40427, 40440, 40420,
- 40438, 40417, 40430, 40422, 40434, [40432, 60370], 40418, 40428, 40436,
- 40435, 40424, 40429, 40642, 40656, {f: 2, c: 40690}, 40710, 40732, 40760,
- 40759, 40758, 40771, 40783, 40817, 40816, {f: 2, c: 40814}, 22227, 22221,
- 23374, 23661, 25901, {f: 2, c: 26349}, 27411, 28767, 28769, 28765, 28768,
- 29219, 29915, 29925, 30677, 31032, 31159, 31158, 31850, 32407, 32649,
- 33389, 34371, 34872, 34871, 34869, 34891, {f: 2, c: 35732},
- {f: 3, c: 36510}, 36509, 37310, 37309, 37314, 37995, {f: 2, c: 37992},
- 38629, 38726, 38723, 38727, 38855, 38885, 39518, 39637, 39769, 40035,
- 40039, 40038, 40034, 40030, 40032, 40450, 40446, 40455, 40451, 40454,
- 40453, {f: 2, c: 40448}, 40457, 40447, 40445, 40452, 40608, 40734, 40774,
- {f: 3, c: 40820}, 22228, 25902, 26040, {f: 2, c: 27416}, 27415, 27418,
- 28770, 29222, 29354, {f: 2, c: 30680}, 31033, 31849, 31851, 31990, 32410,
- 32408, 32411, 32409, {f: 2, c: 33248}, {f: 3, c: 34374}, {f: 2, c: 35193},
- 35196, 35195, 35327, {f: 2, c: 35736}, 36517, 36516, 36515, 37998, 37997,
- 37999, 38001, 38003, 38729, 39026, 39263, 40040, 40046, 40045, 40459,
- 40461, 40464, 40463, 40466, 40465, 40609, 40693, 40713, 40775, 40824,
- 40827, 40826, 40825, 22302, 28774, 31855, 34876, 36274, 36518, 37315,
- 38004, 38008, 38006, 38005, 39520, [39726, 60830], 40052, 40051, 40049,
- 40053, 40468, 40467, 40694, 40714, 40868, 28776, 28773, 31991, 34410,
- 34878, 34877, 34879, 35742, 35996, 36521, 36553, 38731, {f: 2, c: 39027},
- 39116, 39265, 39339, 39524, {f: 2, c: 39526}, 39716, 40469, 40471, 40776,
- 25095, 27422, 29223, 34380, 36520, 38018, {f: 2, c: 38016}, 39529, 39528,
- 40473, 34379, 35743, 38019, 40057, 40631, 30325, 39531, 40058, 40477,
- {f: 2, c: 28777}, 29225, 40612, 40830, 40777, 40856, {s: 97}, 65075, 0,
- 65076, 65103, [168, 776, 63208], [710, 63209, 65342], [12541, 63210],
- [12542, 63211], [12445, 63212], [12446, 63213], 0, [12293, 63216],
- [12294, 63217], [12295, 63218], [12540, 63219], [63220, 65339],
- [63221, 65341], [10045, 63222], [12353, 63223], [12354, 63224],
- [12355, 63225], [12356, 63226], [12357, 63227], [12358, 63228],
- [12359, 63229], [12360, 63230], [12361, 63231], [12362, 63232],
- [12363, 63233], [12364, 63234], [12365, 63235], [12366, 63236],
- [12367, 63237], [12368, 63238], [12369, 63239], [12370, 63240],
- [12371, 63241], [12372, 63242], [12373, 63243], [12374, 63244],
- [12375, 63245], [12376, 63246], [12377, 63247], [12378, 63248],
- [12379, 63249], [12380, 63250], [12381, 63251], [12382, 63252],
- [12383, 63253], [12384, 63254], [12385, 63255], [12386, 63256],
- [12387, 63257], [12388, 63258], [12389, 63259], [12390, 63260],
- [12391, 63261], [12392, 63262], [12393, 63263], [12394, 63264],
- [12395, 63265], [12396, 63266], [12397, 63267], [12398, 63268],
- [12399, 63269], [12400, 63270], [12401, 63271], [12402, 63272],
- [12403, 63273], [12404, 63274], [12405, 63275], [12406, 63276],
- [12407, 63277], [12408, 63278], [12409, 63279], [12410, 63280],
- [12411, 63281], [12412, 63282], [12413, 63283], [12414, 63284],
- [12415, 63285], [12416, 63286], [12417, 63287], [12418, 63288],
- [12419, 63289], [12420, 63290], [12421, 63291], [12422, 63292],
- [12423, 63293], [12424, 63294], [12425, 63295], [12426, 63296],
- [12427, 63297], [12428, 63298], [12429, 63299], [12430, 63300],
- [12431, 63301], [12432, 63302], [12433, 63303], [12434, 63304],
- [12435, 63305], [12449, 63306], [12450, 63307], [12451, 63308],
- [12452, 63309], [12453, 63310], [12454, 63311], [12455, 63312],
- [12456, 63313], [12457, 63314], [12458, 63315], [12459, 63316],
- [12460, 63317], [12461, 63318], [12462, 63319], [12463, 63320],
- [12464, 63321], [12465, 63322], [12466, 63323], [12467, 63324],
- [12468, 63325], [12469, 63326], [12470, 63327], [12471, 63328],
- [12472, 63329], [12473, 63330], [12474, 63331], [12475, 63332],
- [12476, 63333], [12477, 63334], [12478, 63335], [12479, 63336],
- [12480, 63337], [12481, 63338], [12482, 63339], [12483, 63340],
- [12484, 63341], [12485, 63342], [12486, 63343], [12487, 63344],
- [12488, 63345], [12489, 63346], [12490, 63347], [12491, 63348],
- [12492, 63349], [12493, 63350], [12494, 63351], [12495, 63352],
- [12496, 63353], [12497, 63354], [12498, 63355], [12499, 63356],
- [12500, 63357], [12501, 63358], [12502, 63359], [12503, 63360],
- [12504, 63361], [12505, 63362], [12506, 63363], [12507, 63364],
- [12508, 63365], [12509, 63366], [12510, 63367], [12511, 63368],
- [12512, 63369], [12513, 63370], [12514, 63371], [12515, 63372],
- [12516, 63373], [12517, 63374], [12518, 63375], [12519, 63376],
- [12520, 63377], [12521, 63378], [12522, 63379], [12523, 63380],
- [12524, 63381], [12525, 63382], [12526, 63383], [12527, 63384],
- [12528, 63385], [12529, 63386], [12530, 63387], [12531, 63388],
- [12532, 63389], [12533, 63390], [12534, 63391], [1040, 63392],
- [1041, 63393], [1042, 63394], [1043, 63395], [1044, 63396], [1045, 63397],
- [1025, 63398], [1046, 63399], [1047, 63400], [1048, 63401], [1049, 63402],
- [1050, 63403], [1051, 63404], [1052, 63405], [1053, 63406], [1054, 63407],
- [1055, 63408], [1056, 63409], [1057, 63410], [1058, 63411], [1059, 63412],
- [1060, 63413], [1061, 63414], [1062, 63415], [1063, 63416], [1064, 63417],
- [1065, 63418], [1066, 63419], [1067, 63420], [1068, 63421], [1069, 63422],
- [1070, 63423], [1071, 63424], [1072, 63425], [1073, 63426], [1074, 63427],
- [1075, 63428], [1076, 63429], [1077, 63430], [1105, 63431], [1078, 63432],
- [1079, 63433], [1080, 63434], [1081, 63435], [1082, 63436], [1083, 63437],
- [1084, 63438], [1085, 63439], [1086, 63440], [1087, 63441], [1088, 63442],
- [1089, 63443], [1090, 63444], [1091, 63445], [1092, 63446], [1093, 63447],
- [1094, 63448], [1095, 63449], [1096, 63450], [1097, 63451], [1098, 63452],
- [1099, 63453], [1100, 63454], [1101, 63455], [1102, 63456], [1103, 63457],
- [8679, 63458], [8632, 63459], [8633, 63460], [20033, 63461],
- [63462, 131276], [20058, 63463], [63464, 131210], [20994, 63465],
- [17553, 63466], 63467, [20872, 63468], [13853, 63469], [63470, 161287],
- {s: 40}, [172, 63511, 65506], [63512, 65508], [63513, 65287],
- [63514, 65282], [12849, 63515], [8470, 63516], [8481, 63517], 30849,
- [37561, 58501], 35023, 22715, 24658, 31911, 23290, 9556, 9574, 9559, 9568,
- 9580, 9571, 9562, 9577, 9565, 9554, 9572, 9557, {s: 3}, 9560, 9575, 9563,
- 9555, 9573, 9558, 9567, 9579, 9570, 9561, 9576, 9564, 9553, {s: 5}, 9619,
- {s: 26}, [58129, 147159], [22462, 58130], [58131, 159443], [28990, 58132],
- [58133, 153568], [27042, 58135], [58136, 166889], [23412, 58137],
- [31305, 58138], [58139, 153825], [58140, 169177], [31333, 58141],
- [31357, 58142], [58143, 154028], [31419, 58144], [31408, 58145],
- [31426, 58146], [31427, 58147], [29137, 58148], [58149, 156813],
- [16842, 58150], [31450, 58151], [31453, 58152], [31466, 58153],
- [16879, 58154], [21682, 58155], [58156, 154625], [31499, 58157],
- [31573, 58158], [31529, 58159], [58160, 152334], [58161, 154878],
- [31650, 58162], [31599, 58163], [33692, 58164], [58165, 154548],
- [58166, 158847], [31696, 58167], [33825, 58168], [31634, 58169], 0,
- [58171, 154912], 0, [33938, 58174], [31738, 58175], 0, [31797, 58177],
- [58178, 154817], [31812, 58179], [31875, 58180], [58181, 149634],
- [31910, 58182], [58184, 148856], [31945, 58185], [31943, 58186],
- [31974, 58187], 0, [31987, 58189], [31989, 58190], [32359, 58192],
- [17693, 58193], [58194, 159300], [32093, 58195], [58196, 159446],
- [32137, 58198], [32171, 58199], [28981, 58200], [32179, 58201], 32214,
- [58203, 147543], [58204, 155689], [32228, 58205], [15635, 58206],
- [32245, 58207], [58208, 137209], [32229, 58209], [58210, 164717], 0,
- [58212, 155937], [58213, 155994], [32366, 58214], 0, [17195, 58216],
- [37996, 58217], [32295, 58218], [32576, 58219], [32577, 58220],
- [32583, 58221], [31030, 58222], [58223, 156368], [39393, 58224],
- [32663, 58225], [58226, 156497], [32675, 58227], [58228, 136801],
- [58229, 131176], [17756, 58230], [58231, 145254], [58233, 164666],
- [32762, 58234], [58235, 156809], 0, [32776, 58237], [32797, 58238], 0,
- [32815, 58240], [58241, 172167], [58242, 158915], [32827, 58243],
- [32828, 58244], [32865, 58245], [58246, 141076], [18825, 58247],
- [58248, 157222], [58249, 146915], [58250, 157416], [26405, 58251],
- [32935, 58252], [58253, 166472], [33031, 58254], [33050, 58255],
- [22704, 58256], [58257, 141046], [27775, 58258], [58259, 156824],
- [25831, 58261], [58262, 136330], [33304, 58263], [58264, 137310],
- [27219, 58265], [58266, 150117], [58267, 150165], [17530, 58268],
- [33321, 58269], [58271, 158290], [58272, 146814], [20473, 58273],
- [58274, 136445], [34018, 58275], [33634, 58276], 0, [58278, 149927],
- [58279, 144688], [58280, 137075], [58281, 146936], [33450, 58282],
- [26907, 58283], [58284, 194964], [16859, 58285], [34123, 58286],
- [33488, 58287], [33562, 58288], [58289, 134678], [58290, 137140],
- [14017, 58291], [58292, 143741], [58293, 144730], [33403, 58294],
- [33506, 58295], [33560, 58296], [58297, 147083], [58298, 159139],
- [58299, 158469], [58300, 158615], [58301, 144846], [15807, 58302],
- [33565, 58303], [21996, 58304], [33669, 58305], [17675, 58306],
- [58307, 159141], [33708, 58308], 0, [33747, 58310], [58312, 159444],
- [27223, 58313], [34138, 58314], [13462, 58315], [58316, 159298],
- [33880, 58318], [58319, 154596], [33905, 58320], [15827, 58321],
- [17636, 58322], [27303, 58323], [33866, 58324], [31064, 58326], 0,
- [58328, 158614], [58329, 159351], [58330, 159299], [34014, 58331], 0,
- [33681, 58333], [17568, 58334], [33939, 58335], [34020, 58336],
- [58337, 154769], [16960, 58338], [58339, 154816], [17731, 58340],
- [34100, 58341], [23282, 58342], 0, [17703, 58344], [34163, 58345],
- [17686, 58346], [26559, 58347], [34326, 58348], [58349, 165413],
- [58350, 165435], [34241, 58351], [58352, 159880], [34306, 58353],
- [58354, 136578], [58355, 159949], [58356, 194994], [17770, 58357],
- [34344, 58358], [13896, 58359], [58360, 137378], [21495, 58361],
- [58362, 160666], [34430, 58363], 0, [58365, 172280], [34798, 58366],
- [58367, 142375], [34737, 58368], [34778, 58369], [34831, 58370, 60990],
- [22113, 58371], [34412, 58372], [26710, 58373], [17935, 58374],
- [34885, 58375], [34886, 58376], [58377, 161248], [58378, 146873],
- [58379, 161252], [34910, 58380], [34972, 58381], [18011, 58382],
- [34996, 58383], [34997, 58384], [35013, 58386], [58388, 161551],
- [35207, 58389], {s: 3}, [35239, 58393], [35260, 58394], [58395, 166437],
- [35303, 58396], [58397, 162084], [58398, 162493], [35484, 58399],
- [30611, 58400], [37374, 58401], [35472, 58402], [58403, 162393],
- [31465, 58404], [58405, 162618], [18195, 58407], [58408, 162616],
- [29052, 58409], [35596, 58410], [35615, 58411], [58412, 152624],
- [58413, 152933], [35647, 58414], 0, [35661, 58416], [35497, 58417],
- [58418, 150138], [35728, 58419], [35739, 58420], [35503, 58421],
- [58422, 136927], [17941, 58423], [34895, 58424], [35995, 58425],
- [58426, 163156], [58427, 163215], [58428, 195028], [14117, 58429],
- [58430, 163155], [36054, 58431], [58432, 163224], [58433, 163261],
- [36114, 58434], [36099, 58435], [58436, 137488], [36059, 58437],
- [28764, 58438], [36113, 58439], [16080, 58441], 0, [36265, 58443],
- [58444, 163842], [58445, 135188], [58446, 149898], [15228, 58447],
- [58448, 164284], [58449, 160012], [31463, 58450], [36525, 58451],
- [36534, 58452], [36547, 58453], [37588, 58454], [36633, 58455],
- [36653, 58456], [58457, 164709], [58458, 164882], [36773, 58459],
- [37635, 58460], [58461, 172703], [58462, 133712], [36787, 58463], 0,
- [58465, 166366], [58466, 165181], [58467, 146875], [24312, 58468],
- [58469, 143970], [36857, 58470], 0, [58474, 140069], [14720, 58475],
- [58476, 159447], [36919, 58477], [58478, 165180], [58479, 162494],
- [36961, 58480], [58481, 165228], [58482, 165387], [37032, 58483],
- [58484, 165651], [37060, 58485], [58486, 165606], [37038, 58487], 0,
- [37223, 58489], [37289, 58491], [37316, 58492], [31916, 58493],
- [58494, 166195], [58495, 138889], [37390, 58496], [27807, 58497],
- [37441, 58498], [37474, 58499], [58500, 153017], [58502, 166598],
- [58503, 146587], [58504, 166668], [58505, 153051], [58506, 134449],
- [37676, 58507], [37739, 58508], [58509, 166625], [58510, 166891],
- [23235, 58512], [58513, 166626], [58514, 166629], [18789, 58515],
- [37444, 58516], [58517, 166892], [58518, 166969], [58519, 166911],
- [37747, 58520], [37979, 58521], [36540, 58522], [38277, 58523],
- [38310, 58524], [37926, 58525], [38304, 58526], [28662, 58527],
- [17081, 58528], [58530, 165592], [58531, 135804], [58532, 146990],
- [18911, 58533], [27676, 58534], [38523, 58535], [38550, 58536],
- [16748, 58537], [38563, 58538], [58539, 159445], [25050, 58540], 58541,
- [30965, 58542], [58543, 166624], [38589, 58544], [21452, 58545],
- [18849, 58546], [58547, 158904], [58548, 131700], [58549, 156688],
- [58550, 168111], [58551, 168165], [58552, 150225], [58553, 137493],
- [58554, 144138], [38705, 58555], [34370, 58556], [38710, 58557],
- [18959, 58558], [17725, 58559], [17797, 58560], [58561, 150249],
- [28789, 58562], [23361, 58563], [38683, 58564], 0, [58566, 168405],
- [38743, 58567], [23370, 58568], [58569, 168427], [38751, 58570],
- [37925, 58571], [20688, 58572], [58573, 143543], [58574, 143548],
- [38793, 58575], [38815, 58576], [38833, 58577], [38846, 58578],
- [38848, 58579], [38866, 58580], [38880, 58581], [58582, 152684],
- [38894, 58583], [29724, 58584], [58585, 169011], 0, [38901, 58587],
- [58588, 168989], [58589, 162170], [19153, 58590], [38964, 58591],
- [38963, 58592], [38987, 58593], [39014, 58594], [15118, 58595],
- [58596, 160117], [15697, 58597], [58598, 132656], [58599, 147804],
- [58600, 153350], [39114, 58601], [39095, 58602], [39112, 58603],
- [39111, 58604], [19199, 58605], [58606, 159015], [58607, 136915],
- [21936, 58608], [39137, 58609], [39142, 58610], [39148, 58611],
- [37752, 58612], [39225, 58613], [58614, 150057], [19314, 58615],
- [58616, 170071], [58617, 170245], [39413, 58618], [39436, 58619],
- [39483, 58620], [39440, 58621], [39512, 58622], [58623, 153381],
- [14020, 58624], [58625, 168113], [58626, 170965], [39648, 58627],
- [39650, 58628], [58629, 170757], [39668, 58630], [19470, 58631],
- [39700, 58632], [39725, 58633], [58634, 165376], [20532, 58635],
- [39732, 58636], [14531, 58638], [58639, 143485], [39760, 58640],
- [39744, 58641], [58642, 171326], [23109, 58643], [58644, 137315],
- [39822, 58645], [39938, 58647], [39935, 58648], [39948, 58649],
- [58650, 171624], [40404, 58651], [58652, 171959], [58653, 172434],
- [58654, 172459], [58655, 172257], [58656, 172323], [58657, 172511],
- [40318, 58658], [40323, 58659], [58660, 172340], [40462, 58661],
- [40388, 58663], [58665, 172435], [58666, 172576], [58667, 137531],
- [58668, 172595], [40249, 58669], [58670, 172217], [58671, 172724],
- [40592, 58672], [40597, 58673], [40606, 58674], [40610, 58675],
- [19764, 58676], [40618, 58677], [40623, 58678], [58679, 148324],
- [40641, 58680], [15200, 58681], [14821, 58682], [15645, 58683],
- [20274, 58684], [14270, 58685], [58686, 166955], [40706, 58687],
- [40712, 58688], [19350, 58689], [37924, 58690], [58691, 159138],
- [40727, 58692, 60836], 0, [40761, 58694], [22175, 58695], [22154, 58696],
- [40773, 58697], [39352, 58698], [58699, 168075], [38898, 58700],
- [33919, 58701], 0, [40809, 58703], [31452, 58704], [40846, 58705],
- [29206, 58706], [19390, 58707], [58708, 149877], [58709, 149947],
- [29047, 58710], [58711, 150008], [58712, 148296], [58713, 150097],
- [29598, 58714], [58715, 166874], [58716, 137466], [31135, 58717],
- [58718, 166270], [58719, 167478], [37737, 58720], [37875, 58721],
- [58722, 166468], [37612, 58723], [37761, 58724], [37835, 58725],
- [58726, 166252], [58727, 148665], [29207, 58728], [16107, 58729],
- [30578, 58730], [31299, 58731], [28880, 58732], [58733, 148595],
- [58734, 148472], [29054, 58735], [58736, 137199], [28835, 58737],
- [58738, 137406], [58739, 144793], [16071, 58740], [58741, 137349],
- [58742, 152623], [58743, 137208], [14114, 58744], [58745, 136955],
- [58746, 137273], [14049, 58747], [58748, 137076], [58749, 137425],
- [58750, 155467], [14115, 58751], [58752, 136896], [22363, 58753],
- [58754, 150053], [58755, 136190], [58756, 135848], [58757, 136134],
- [58758, 136374], [34051, 58759, 58761], [58760, 145062], 0, [33877, 58762],
- [58763, 149908], [58764, 160101], [58765, 146993], [58766, 152924],
- [58767, 147195], [58768, 159826], [17652, 58769], [58770, 145134],
- [58771, 170397], [58772, 159526], [26617, 58773], [14131, 58774],
- [15381, 58775], [15847, 58776], [22636, 58777], [58778, 137506],
- [26640, 58779], [16471, 58780], [58781, 145215], [58782, 147681],
- [58783, 147595], [58784, 147727], [58785, 158753], [21707, 58786],
- [22174, 58787], [58788, 157361], [22162, 58789], [58790, 135135],
- [58791, 134056], [58792, 134669], 0, [58794, 166675], [37788, 58795],
- [20216, 58796], [20779, 58797], [14361, 58798], [58799, 148534],
- [20156, 58800], [58801, 132197], 0, [20299, 58803], [20362, 58804],
- [58805, 153169], [23144, 58806], [58807, 131499], [58808, 132043],
- [14745, 58809], [58810, 131850], [58811, 132116], [13365, 58812],
- [20265, 58813], [58814, 131776], [58815, 167603], [58816, 131701],
- [35546, 58817], [58818, 131596], [20120, 58819], [20685, 58820],
- [20749, 58821], [20386, 58822], [20227, 58823], [58824, 150030],
- [58825, 147082], [20290, 58826], [20526, 58827], [20588, 58828],
- [20609, 58829], [20428, 58830], [20453, 58831], [20568, 58832],
- [20732, 58833], [28278, 58838], [58839, 144789], [58840, 147001],
- [58841, 147135], [28018, 58842], [58843, 137348], [58844, 147081],
- [20904, 58845], [20931, 58846], [58847, 132576], [17629, 58848],
- [58849, 132259], [58850, 132242], [58851, 132241], [36218, 58852],
- [58853, 166556], [58854, 132878], [21081, 58855], [21156, 58856],
- [58857, 133235], [21217, 58858], 0, [18042, 58860], [29068, 58861],
- [58862, 148364], [58863, 134176], [58864, 149932], [58865, 135396],
- [27089, 58866], [58867, 134685], 0, [16094, 58869], [29849, 58870],
- [29716, 58871], [29782, 58872], [29592, 58873], [19342, 58874],
- [58875, 150204], [58876, 147597], [21456, 58877], [13700, 58878],
- [29199, 58879], [58880, 147657], [21940, 58881], [58882, 131909],
- [21709, 58883], [58884, 134086], [22301, 58885], [37469, 58886],
- [38644, 58887], [22493, 58889], [22413, 58890], [22399, 58891],
- [13886, 58892], [22731, 58893], [23193, 58894], [58895, 166470],
- [58896, 136954], [58897, 137071], [58898, 136976], [23084, 58899],
- [22968, 58900], [23166, 58902], [23247, 58903], [23058, 58904],
- [58905, 153926], [58906, 137715], [58907, 137313], [58908, 148117],
- [14069, 58909], [27909, 58910], [29763, 58911], [23073, 58912],
- [58913, 155267], [23169, 58914], [58915, 166871], [58916, 132115],
- [37856, 58917], [29836, 58918], [58919, 135939], [28933, 58920],
- [18802, 58921], [37896, 58922], [58923, 166395], [37821, 58924],
- [14240, 58925], [23582, 58926], [23710, 58927], [24158, 58928],
- [24136, 58929], [58930, 137622], [58931, 137596], [58932, 146158],
- [24269, 58933], [23375, 58934], [58935, 137475], [58936, 137476],
- [14081, 58937], [58938, 137376], [14045, 58939], [58940, 136958],
- [14035, 58941], [33066, 58942], [58943, 166471], [58944, 138682],
- [58945, 144498], [58946, 166312], [24332, 58947, 60916], [24334, 58948],
- [58949, 137511], [58950, 137131], [23147, 58951], [58952, 137019],
- [23364, 58953], [58955, 161277], [34912, 58956], [24702, 58957],
- [58958, 141408], [58959, 140843], [24539, 58960], [16056, 58961],
- [58962, 140719], [58963, 140734], [58964, 168072], [58965, 159603],
- [25024, 58966], [58967, 131134], [58968, 131142], [58969, 140827],
- [24985, 58970], [24984, 58971], [24693, 58972], [58973, 142491],
- [58974, 142599], [58975, 149204], [58976, 168269], [25713, 58977],
- [58978, 149093], [58979, 142186], [14889, 58980], [58981, 142114],
- [58982, 144464], [58983, 170218], [58984, 142968], [25399, 58985],
- [25782, 58987], [25393, 58988], [25553, 58989], [58990, 149987],
- [58991, 142695], [25252, 58992], [58993, 142497], [25659, 58994],
- [25963, 58995], [26994, 58996], [15348, 58997], [58998, 143502],
- [58999, 144045], [59000, 149897], [59001, 144043], [21773, 59002],
- [59003, 144096], [59004, 137433], [59005, 169023], [26318, 59006],
- [59007, 144009], [59008, 143795], [15072, 59009], [59011, 152964],
- [59012, 166690], [59013, 152975], [59014, 136956], [59015, 152923],
- [59016, 152613], [30958, 59017], [59018, 143619], [59019, 137258],
- [59020, 143924], [13412, 59021], [59022, 143887], [59023, 143746],
- [59024, 148169], [26254, 59025], [59026, 159012], [26219, 59027],
- [19347, 59028], [26160, 59029], [59030, 161904], [59031, 138731],
- [26211, 59032], [59033, 144082], [59034, 144097], [26142, 59035],
- [59036, 153714], [14545, 59037], [59038, 145466], [59039, 145340],
- [15257, 59040], [59041, 145314], [59042, 144382], [29904, 59043],
- [15254, 59044], [59046, 149034], [26806, 59047], 0, [15300, 59049],
- [27326, 59050], [59052, 145365], [59053, 148615], [27187, 59054],
- [27218, 59055], [27337, 59056], [27397, 59057], [59058, 137490],
- [25873, 59059], [26776, 59060], [27212, 59061], [15319, 59062],
- [27258, 59063], [27479, 59064], [59065, 147392], [59066, 146586],
- [37792, 59067], [37618, 59068], [59069, 166890], [59070, 166603],
- [37513, 59071], [59072, 163870], [59073, 166364], [37991, 59074],
- [28069, 59075], [28427, 59076], 0, [59079, 147327], [15759, 59080],
- [28164, 59081], [59082, 147516], [23101, 59083], [28170, 59084],
- [22599, 59085], [27940, 59086], [30786, 59087], [28987, 59088],
- [59089, 148250], [59090, 148086], [28913, 59091], [29264, 59092, 61085],
- [29319, 59093], [29332, 59094], [59095, 149391], [59096, 149285],
- [20857, 59097], [59098, 150180], [59099, 132587], [29818, 59100],
- [59101, 147192], [59102, 144991], [59103, 150090], [59104, 149783],
- [59105, 155617], [16134, 59106], [16049, 59107], [59108, 150239],
- [59109, 166947], [59110, 147253], [24743, 59111], [16115, 59112],
- [29900, 59113], [29756, 59114], [37767, 59115], [29751, 59116],
- [17567, 59117], [59118, 159210], [17745, 59119], [30083, 59120],
- [16227, 59121], [59122, 150745], [59123, 150790], [16216, 59124],
- [30037, 59125], [30323, 59126], [59127, 173510], 0, [29800, 59129, 61070],
- [59130, 166604], [59131, 149931], [59132, 149902], [15099, 59133],
- [15821, 59134], [59135, 150094], [16127, 59136], [59137, 149957],
- [59138, 149747], [37370, 59139], [22322, 59140], [37698, 59141],
- [59142, 166627], [59143, 137316], [20703, 59144], [59145, 152097],
- [59146, 152039], [30584, 59147], [59148, 143922], [30478, 59149],
- [30479, 59150], [30587, 59151], [59152, 149143], [59153, 145281],
- [14942, 59154], [59155, 149744], [29752, 59156], [29851, 59157],
- [16063, 59158], [59159, 150202], [59160, 150215], [16584, 59161],
- [59162, 150166], [59163, 156078], [37639, 59164], [59165, 152961],
- [30750, 59166], [30861, 59167], [30856, 59168], [30930, 59169],
- [29648, 59170], [31065, 59171], [59172, 161601], [59173, 153315],
- [16654, 59174], 0, 0, [31141, 59177], [27181, 59178], [59179, 147194],
- [31290, 59180], [31220, 59181], [16750, 59182], [59183, 136934],
- [16690, 59184], [37429, 59185], [31217, 59186], [59187, 134476],
- [59188, 149900], [59189, 131737], [59190, 146874], [59191, 137070],
- [13719, 59192], [21867, 59193], [13680, 59194], [13994, 59195],
- [59196, 131540], [59197, 134157], [31458, 59198], [23129, 59199],
- [59200, 141045], [59201, 154287], [59202, 154268], [23053, 59203],
- [59204, 131675], [30960, 59205], [23082, 59206], [59207, 154566],
- [31486, 59208], [16889, 59209], [31837, 59210], [31853, 59211],
- [16913, 59212], [59213, 154547], [59214, 155324], [59215, 155302],
- [31949, 59216], [59217, 150009], [59218, 137136], [31886, 59219],
- [31868, 59220], [31918, 59221], [27314, 59222], [32220, 59223],
- [32263, 59224], [32211, 59225], [32590, 59226], [59227, 156257],
- [59228, 155996], [59229, 162632], [32151, 59230], [59231, 155266],
- [17002, 59232], [59233, 158581], [59234, 133398], [26582, 59235],
- [59236, 131150], [59237, 144847], [22468, 59238], [59239, 156690],
- [59240, 156664], [32733, 59242], [31527, 59243], [59244, 133164],
- [59245, 154345], [59246, 154947], [31500, 59247], [59248, 155150],
- [39398, 59249], [34373, 59250], [39523, 59251], [27164, 59252],
- [59253, 144447], [59255, 150007], [59256, 157101], [39455, 59257],
- [59258, 157088], 0, [59260, 160039], [59261, 158929], [17642, 59262],
- [33079, 59263], [17410, 59264], [32966, 59265], [33033, 59266],
- [33090, 59267], [59268, 157620], [39107, 59269], [59270, 158274],
- [33378, 59271], [33381, 59272], [59273, 158289], [33875, 59274],
- [59275, 159143], [34320, 59276], [59277, 160283], [23174, 59278],
- [16767, 59279], [59280, 137280], [23339, 59281], [59282, 137377],
- [23268, 59283], [59284, 137432], [34464, 59285], [59286, 195004],
- [59287, 146831], [34861, 59288], [59289, 160802], [23042, 59290],
- [34926, 59291], [20293, 59292], [34951, 59293], [35007, 59294],
- [35046, 59295], [35173, 59296], [35149, 59297], [59298, 153219],
- [35156, 59299], [59300, 161669], [59301, 161668], [59302, 166901],
- [59303, 166873], [59304, 166812], [59305, 166393], [16045, 59306],
- [33955, 59307], [18165, 59308], [18127, 59309], [14322, 59310],
- [35389, 59311], [35356, 59312], [59313, 169032], [24397, 59314],
- [37419, 59315], [59316, 148100], [26068, 59317], [28969, 59318],
- [28868, 59319], [59320, 137285], [40301, 59321], [35999, 59322],
- [36073, 59323], [59324, 163292], [22938, 59325], [30659, 59326],
- [23024, 59327], [14036, 59329], [36394, 59330], [36519, 59331],
- [59332, 150537], [36656, 59333], [36682, 59334], [17140, 59335],
- [27736, 59336], [28603, 59337], [59338, 140065], [18587, 59339],
- [28537, 59340], [28299, 59341], [59342, 137178], [39913, 59343],
- [14005, 59344], [59345, 149807], [37051, 59346], 0, [21873, 59348],
- [18694, 59349], [37307, 59350], [37892, 59351], [59352, 166475],
- [16482, 59353], [59354, 166652], [37927, 59355], [59356, 166941],
- [59357, 166971], [34021, 59358], [35371, 59359], [38297, 59360],
- [38311, 59361], [38295, 59362], [38294, 59363], [59364, 167220],
- [29765, 59365], [16066, 59366], [59367, 149759], [59368, 150082],
- [59369, 148458], [16103, 59370], [59371, 143909], [38543, 59372],
- [59373, 167655], [59374, 167526], [59375, 167525], [16076, 59376],
- [59377, 149997], [59378, 150136], [59379, 147438], [29714, 59380],
- [29803, 59381], [16124, 59382], [38721, 59383], [59384, 168112],
- [26695, 59385], [18973, 59386], [59387, 168083], [59388, 153567], 0,
- [37736, 59390], [59391, 166281], [59392, 166950], [59393, 166703],
- [59394, 156606], [37562, 59395], [23313, 59396], [35689, 59397],
- [18748, 59398], [29689, 59399], [59400, 147995], [38811, 59401], 0,
- [39224, 59403], [59404, 134950], [24001, 59405], [59406, 166853],
- [59407, 150194], [38943, 59408], [59409, 169178], [37622, 59410],
- [59411, 169431], [37349, 59412], [17600, 59413], [59414, 166736],
- [59415, 150119], [59416, 166756], [39132, 59417], [59418, 166469],
- [16128, 59419], [37418, 59420], [18725, 59421], [33812, 59422],
- [39227, 59423], [39245, 59424], [59425, 162566], [15869, 59426], 0,
- [19311, 59428], [39338, 59429], [39516, 59430], [59431, 166757],
- [59432, 153800], [27279, 59433], [39457, 59434], [23294, 59435],
- [39471, 59436], [59437, 170225], [19344, 59438], [59439, 170312],
- [39356, 59440], [19389, 59441], [19351, 59442], [37757, 59443],
- [22642, 59444], [59445, 135938], [22562, 59446], [59447, 149944],
- [59448, 136424], [30788, 59449], [59450, 141087], [59451, 146872],
- [26821, 59452], [15741, 59453], [37976, 59454], [14631, 59455],
- [24912, 59456], [59457, 141185], [59458, 141675], [24839, 59459],
- [40015, 59460], [40019, 59461], [40059, 59462], [39989, 59463],
- [39952, 59464], [39807, 59465], [39887, 59466], [59467, 171565],
- [39839, 59468], [59469, 172533], [59470, 172286], [40225, 59471],
- [19630, 59472], [59473, 147716], [40472, 59474], [19632, 59475],
- [40204, 59476], [59477, 172468], [59478, 172269], [59479, 172275],
- [59480, 170287], [40357, 59481], [33981, 59482], [59483, 159250],
- [59484, 159711], [59485, 158594], [34300, 59486], [17715, 59487],
- [59488, 159140], [59489, 159364], [59490, 159216], [33824, 59491],
- [34286, 59492], [59493, 159232], [59494, 145367], [59495, 155748],
- [31202, 59496], [59497, 144796], [59498, 144960], [59500, 149982],
- [15714, 59501], [37851, 59502], [37566, 59503], [37704, 59504],
- [59505, 131775], [30905, 59506], [37495, 59507], [37965, 59508],
- [20452, 59509], [13376, 59510], [36964, 59511], [59512, 152925],
- [30781, 59513], [30804, 59514], [30902, 59515], [30795, 59516],
- [59517, 137047], [59518, 143817], [59519, 149825], [13978, 59520],
- [20338, 59521], [28634, 59522], [28633, 59523], 0, [28702, 59524, 59525],
- [21524, 59526], [59527, 147893], [22459, 59528], [22771, 59529],
- [22410, 59530], [40214, 59531], [22487, 59532], [28980, 59533],
- [13487, 59534], [59535, 147884], [29163, 59536], [59537, 158784],
- [59538, 151447], 0, [59540, 137141], [59541, 166473], [24844, 59542],
- [23246, 59543], [23051, 59544], [17084, 59545], [59546, 148616],
- [14124, 59547], [19323, 59548], [59549, 166396], [37819, 59550],
- [37816, 59551], [59552, 137430], [59553, 134941], [33906, 59554],
- [59555, 158912], [59556, 136211], [59557, 148218], [59558, 142374],
- [59559, 148417], [22932, 59560], [59561, 146871], [59562, 157505],
- [32168, 59563], [59564, 155995], [59565, 155812], [59566, 149945],
- [59567, 149899], [59568, 166394], [37605, 59569], [29666, 59570],
- [16105, 59571], [29876, 59572], [59573, 166755], [59574, 137375],
- [16097, 59575], [59576, 150195], [27352, 59577], [29683, 59578],
- [29691, 59579], [16086, 59580], [59581, 150078], [59582, 150164],
- [59583, 137177], [59584, 150118], [59585, 132007], [59586, 136228],
- [59587, 149989], [29768, 59588], [59589, 149782], [28837, 59590],
- [59591, 149878], [37508, 59592], [29670, 59593], [37727, 59594],
- [59595, 132350], [37681, 59596], [59597, 166606], [59598, 166422],
- [37766, 59599], [59600, 166887], [59601, 153045], [18741, 59602],
- [59603, 166530], [29035, 59604], [59605, 149827], [59606, 134399],
- [22180, 59607], [59608, 132634], [59609, 134123], [59610, 134328],
- [21762, 59611], [31172, 59612], [59613, 137210], [32254, 59614],
- [59615, 136898], [59616, 150096], [59617, 137298], [17710, 59618],
- [37889, 59619], [14090, 59620], [59621, 166592], [59622, 149933],
- [22960, 59623], [59624, 137407], [59625, 137347], [59626, 160900],
- [23201, 59627], [14050, 59628], [59629, 146779], [14000, 59630],
- [37471, 59631], [23161, 59632], [59633, 166529], [59634, 137314],
- [37748, 59635], [15565, 59636], [59637, 133812], [19094, 59638],
- [14730, 59639], [20724, 59640], [15721, 59641], [15692, 59642],
- [59643, 136092], [29045, 59644], [17147, 59645], [59646, 164376],
- [28175, 59647], [59648, 168164], [17643, 59649], [27991, 59650],
- [59651, 163407], [28775, 59652], [27823, 59653], [15574, 59654],
- [59655, 147437], [59656, 146989], [28162, 59657], [28428, 59658],
- [15727, 59659], [59660, 132085], [30033, 59661], [14012, 59662],
- [13512, 59663], [18048, 59664], [16090, 59665], [18545, 59666],
- [22980, 59667], [37486, 59668], [18750, 59669], [36673, 59670],
- [59671, 166940], [59672, 158656], [22546, 59673], [22472, 59674],
- [14038, 59675], [59676, 136274], [28926, 59677], [59678, 148322],
- [59679, 150129], [59680, 143331], [59681, 135856], [59682, 140221],
- [26809, 59683], [26983, 59684], [59685, 136088], [59686, 144613],
- [59687, 162804], [59688, 145119], [59689, 166531], [59690, 145366],
- [59691, 144378], [59692, 150687], [27162, 59693], [59694, 145069],
- [59695, 158903], [33854, 59696], [17631, 59697], [17614, 59698],
- [59699, 159014], [59700, 159057], [59701, 158850], [59702, 159710], 0, 0,
- [33597, 59705], [59706, 137018], [33773, 59707], [59708, 158848],
- [59709, 159827], [59710, 137179], [22921, 59711], [23170, 59712],
- [59713, 137139], [23137, 59714], [23153, 59715], [59716, 137477],
- [59717, 147964], [14125, 59718], [23023, 59719], [59720, 137020],
- [14023, 59721], [29070, 59722], [37776, 59723], [26266, 59724],
- [59725, 148133], [23150, 59726], [23083, 59727], [59728, 148115],
- [27179, 59729], [59730, 147193], [59731, 161590], [59732, 148571],
- [59733, 148170], [28957, 59734], [59735, 148057], [59736, 166369],
- [20400, 59737], [59738, 159016], [23746, 59739], [59740, 148686],
- [59741, 163405], [59742, 148413], [27148, 59743], [59744, 148054],
- [59745, 135940], 0, [28979, 59747], [59748, 148457], [15781, 59749],
- [27871, 59750], [59751, 194597], [23019, 59754], [24412, 59757],
- [59764, 144128], [31955, 59776], [59783, 162548], [59786, 153334],
- [59790, 162584], [36972, 59791], [33270, 59795], [30476, 59797],
- [27810, 59799], [22269, 59800], [22633, 59828], [26465, 59832],
- [23646, 59838], [22770, 59841], [28857, 59843], [26627, 59853],
- [36795, 59859], [36796, 59861], [20001, 59871], [31545, 59898],
- [15820, 59902], [29482, 57990, 59909], [30048, 59912], [22586, 59920],
- [33446, 59932], [27018, 59940], [24803, 59944], [20206, 59984],
- [39364, 60002], [40639, 60023], [21249, 60025], [26528, 60038],
- [24808, 60046], [20916, 60053], [31363, 60064], [39994, 60075],
- [31432, 60093], [26906, 60098], [22956, 60100], [22592, 60102],
- [21610, 60114], [24807, 60123], [22138, 60125], [26965, 60132],
- [39983, 60133], [34725, 60134], [23584, 60141], [24075, 60143],
- [26398, 60147], [33965, 60157], [35713, 60161], [20088, 60166],
- [25283, 60176], [26709, 60180], 0, [33533, 60190], [35237, 60194],
- [36768, 60196], [38840, 60198], [38983, 60200], [39613, 60201],
- [24497, 60218], [26184, 60219], [26303, 60220], [60221, 162425], 0,
- [60225, 149946], 0, 0, [60230, 131910], [26382, 60232], [26904, 60233],
- [60235, 161367], [60236, 155618], [60239, 161278], [60240, 139418],
- [18640, 60241], [19128, 60242], [60244, 166554], [60247, 147515],
- [60250, 150085], [60251, 132554], [20946, 60252], [60253, 132625],
- [22943, 60254], [60255, 138920], [15294, 60256], [60257, 146687],
- [14747, 60262], [60264, 165352], [60265, 170441], [14178, 60266],
- [60267, 139715], [35678, 60268], [60269, 166734], 0, [29193, 60274],
- [60276, 134264], [60280, 132985], [36570, 60281], [21135, 60283],
- [29041, 60285], [60288, 147274], [60289, 150183], [21948, 60290],
- [60293, 158546], [13427, 60295], [60297, 161330], [18200, 60299],
- [60303, 149823], [20582, 60305], [13563, 60306], [60307, 144332], 0,
- [18300, 60310], [60311, 166216], [60315, 138640], 0, [60320, 162834],
- [36950, 60321], [60323, 151450], [35682, 60324], [23899, 60327],
- [60328, 158711], 0, [60331, 137500], [35562, 60332], [60333, 150006],
- [60335, 147439], [19392, 60337], [60340, 141083], [37989, 60341],
- [60342, 153569], [24981, 60343], [23079, 60344], [60345, 194765], 0,
- [60348, 148769], [20074, 60350], [60351, 149812], [38486, 60352],
- [28047, 60353], [60354, 158909], [35191, 60356], [60359, 156689], 0,
- [31554, 60363], [60364, 168128], [60365, 133649], 0, [31301, 60369],
- [39462, 60372], [13919, 60374], [60375, 156777], [60376, 131105],
- [31107, 60377], [23852, 60380], [60381, 144665], 0, [18128, 60384],
- [30011, 60386], [34917, 60387], [22710, 60389], [14108, 60390],
- [60391, 140685], [15444, 60394], [37505, 60397], [60398, 139642],
- [37680, 60400], [60402, 149968], [27705, 60403], [60406, 134904],
- [34855, 60407], [35061, 60408], [60409, 141606], [60410, 164979],
- [60411, 137137], [28344, 60412], [60413, 150058], [60414, 137248],
- [14756, 60415], 0, 0, [17727, 60419], [26294, 60420], [60421, 171181],
- [60422, 170148], [35139, 60423], [16607, 60427], [60428, 136714],
- [14753, 60429], [60430, 145199], [60431, 164072], [60432, 136133],
- [29101, 60433], [33638, 60434], [60436, 168360], 0, [19639, 60438],
- [60439, 159919], [60440, 166315], [60445, 147834], [31555, 60446],
- [31102, 60447], [28597, 60449], [60450, 172767], [27139, 60451],
- [60452, 164632], [21410, 60453], [60454, 159239], [37823, 60455],
- [26678, 60456], [38749, 59389, 60457], [60458, 164207], [60460, 158133],
- [60461, 136173], [60462, 143919], [23941, 60464], [60465, 166960],
- [22293, 60467], [38947, 60468], [60469, 166217], [23979, 60470],
- [60471, 149896], [26046, 60472], [27093, 60473], [21458, 60474],
- [60475, 150181], [60476, 147329], [15377, 60477], [26422, 60478],
- [60482, 139169], [13770, 60490], [18682, 60493], 0, [30728, 60496],
- [37461, 60497], [17394, 60499], [17375, 60501], [23032, 60505], 0,
- [22155, 60518], [60520, 169449], [36882, 60541], [21953, 60546],
- [17673, 60551], [32383, 60552], [28502, 60553], [27313, 60554],
- [13540, 60556], [60558, 161949], [14138, 60559], 0, [60562, 163876],
- [60565, 162366], [15851, 60567], [60569, 146615], [60574, 156248],
- [22207, 60575], [36366, 60577], [23405, 60578], [25566, 60581], 0,
- [25904, 60585], [22061, 60586], [21530, 60588], [60591, 171416],
- [19581, 60592], [22050, 60593], [22046, 60594], [32585, 60595],
- [22901, 60597], [60598, 146752], [34672, 60599], [33047, 60604],
- [40286, 60605], [36120, 60606], [30267, 60607], [40005, 60608],
- [30286, 60609], [30649, 60610], [37701, 60611], [21554, 60612],
- [33096, 60613], [33527, 60614], [22053, 60615], [33074, 60616],
- [33816, 60617], [32957, 60618], [21994, 60619], [31074, 60620],
- [22083, 60621], [21526, 60622], [60623, 134813], [13774, 60624],
- [22021, 57509, 60625], [22001, 60626], [26353, 60627], [60628, 164578],
- [13869, 60629], [30004, 60630], [22000, 60631], [21946, 60632],
- [21655, 60633], [21874, 60634], [60635, 134209], [60636, 134294],
- [24272, 57652, 60637], [60639, 134774], [60640, 142434], [60641, 134818],
- [40619, 60642], [32090, 60643], 0, [60645, 135285], [25245, 60646],
- [38765, 60647], [21652, 60648], [36045, 60649], [29174, 60650],
- [37238, 60651], [25596, 60652], [25529, 60653], [25598, 60654],
- [21865, 60655], [60656, 142147], [40050, 60657], [60658, 143027],
- [20890, 60659], [13535, 60660], [60661, 134567], [20903, 60662],
- [21581, 60663], [21790, 60664], [21779, 60665], [30310, 60666],
- [36397, 60667], [60668, 157834], [30129, 60669], [32950, 60670],
- [34820, 60671], 0, [35015, 60673], [33206, 60674], [33820, 60675],
- [17644, 60677], [29444, 60678], [33547, 60681], [22139, 60683],
- [37232, 60690], [37384, 60692], [60696, 134905], [29286, 60697],
- [18254, 60699], [60701, 163833], [16634, 60703], [40029, 60704],
- [25887, 60705], [18675, 60707], [60708, 149472], [60709, 171388], 0,
- [60713, 161187], 60715, [60716, 155720], [29091, 60718], [32398, 60719],
- [40272, 60720], [13687, 60723], [27826, 60725], [21351, 60726],
- [14812, 60728], [60731, 149016], [33325, 60734], [21579, 60735], 60739,
- [14930, 60740], [29556, 60742], [60743, 171692], [19721, 60744],
- [39917, 60745], 0, [19547, 60748], [60751, 171998], [33884, 60752],
- [60754, 160434], [25390, 60757], [32037, 60758], [14890, 60761],
- [36872, 60762], [21196, 60763], [15988, 60764], [13946, 60765],
- [17897, 60766], [60767, 132238], [30272, 60768], [23280, 60769],
- [60770, 134838], [30842, 60771], [18358, 60772], [22695, 60773],
- [16575, 60774], [22140, 60775], [39819, 60776], [23924, 60777],
- [30292, 60778], [60779, 173108], [40581, 60780], [19681, 60781], 0,
- [14331, 60783], [24857, 60784], [60786, 148466], 60787, [22109, 60788],
- [60792, 171526], [21044, 60793], [13741, 60795], 0, [40316, 60797],
- [31830, 60798], [39737, 60799], [22494, 60800], [23635, 60802],
- [25811, 60803], [60804, 169168], [60805, 156469], [34477, 60807],
- [60808, 134440], [60811, 134513], 60812, [20990, 60813], [60814, 139023],
- [23950, 60815], [38659, 60816], [60817, 138705], [40577, 60818],
- [36940, 60819], [31519, 60820], [39682, 60821], [23761, 60822],
- [31651, 60823], [25192, 60824], [25397, 60825], [39679, 60826],
- [31695, 60827], [39722, 60828], [31870, 60829], 0, [31810, 60831],
- [31878, 60832], [39957, 60833], [31740, 60834], [39689, 60835], 0, 39982,
- [40794, 60839], [21875, 60840], [23491, 60841], [20477, 60842],
- [40600, 60843], [20466, 60844], [21088, 60845], [21201, 60847],
- [22375, 60848], [20566, 60849], [22967, 60850], [24082, 60851],
- [38856, 60852], [40363, 60853], [36700, 60854], [21609, 60855],
- [38836, 60856], [39232, 60857], [38842, 60858], [21292, 60859],
- [24880, 60860], [26924, 60861], [21466, 60862], [39946, 60863],
- [40194, 60864], [19515, 60865], [38465, 60866], [27008, 60867],
- [20646, 60868], [30022, 60869], [60870, 137069], [39386, 60871],
- [21107, 60872], 60873, [37209, 60874], [38529, 60875], [37212, 60876],
- 60877, [37201, 60878], [60879, 167575], [25471, 60880], [27338, 60882],
- [22033, 60883], [37262, 60884], [30074, 60885], [25221, 60886],
- [29519, 60888], [31856, 60889], [60890, 154657], 60892, [30422, 60894],
- [39837, 60895], [20010, 60896], [60897, 134356], [33726, 60898],
- [34882, 60899], 60900, [23626, 60901], [27072, 60902], 0, 0,
- [21023, 60905], [24053, 60906], [20174, 60907], [27697, 60908],
- [60909, 131570], [20281, 60910], [21660, 60911], 0, [21146, 60913],
- [36226, 60914], [13822, 60915], 0, [13811, 60917], 60918, [27474, 60919],
- [37244, 60920], [40869, 60921], [39831, 60922], [38958, 60923],
- [39092, 60924], [39610, 60925], [40616, 60926], [40580, 60927],
- [31508, 60929], 60930, [27642, 60931], [34840, 60932], [32632, 60933],
- 60934, [22048, 60935], [60936, 173642], [36471, 60937], [40787, 60938],
- 60939, [36308, 60940], [36431, 60941], [40476, 60942], [36353, 60943],
- [25218, 60944], [60945, 164733], [36392, 60946], [36469, 60947],
- [31443, 60948], [31294, 60950], [30936, 60951], [27882, 60952],
- [35431, 60953], [30215, 60954], [40742, 60956], [27854, 60957],
- [34774, 60958], [30147, 60959], [60960, 172722], [30803, 60961],
- [36108, 60963], [29410, 60964], [29553, 60965], [35629, 60966],
- [29442, 60967], [29937, 60968], [36075, 60969], [60970, 150203],
- [34351, 60971], [24506, 60972], [34976, 60973], [17591, 60974], 60975,
- [60977, 159237], 60978, [35454, 60979], [60980, 140571], 60981,
- [24829, 60982], [30311, 60983], [39639, 60984], [40260, 60985],
- [37742, 58859, 60986], [39823, 60987], [34805, 60988], 60989, 0,
- [36087, 60991], [29484, 60992], [38689, 60993], [39856, 60994],
- [13782, 60995], [29362, 60996], [19463, 60997], [31825, 60998],
- [39242, 60999], [24921, 61001], [19460, 61002], [40598, 61003],
- [24957, 61004], 61005, [22367, 61006], [24943, 61007], [25254, 61008],
- [25145, 61009], 0, [14940, 61011], [25058, 61012], [21418, 61013],
- [25444, 61015], [26626, 61016], [13778, 61017], [23895, 61018],
- [36826, 61020], [61021, 167481], 61022, [20697, 61023], [30982, 61025],
- [21298, 61026], [38456, 61027], [61028, 134971], [16485, 61029], 61030,
- [30718, 61031], 61032, [31938, 61033], [61034, 155418], [31962, 61035],
- [31277, 61036], [32870, 61037], [32867, 61038], [32077, 61039],
- [29957, 61040], [29938, 61041], [35220, 61042], [33306, 61043],
- [26380, 61044], [32866, 61045], [61046, 160902], [32859, 61047],
- [29936, 61048], [33027, 61049], [30500, 61050], [35209, 61051],
- [61052, 157644], [30035, 61053], [34729, 61055], [34766, 61056],
- [33224, 61057], [34700, 61058], [35401, 61059], [36013, 61060],
- [35651, 61061], [30507, 61062], [29944, 61063], [34010, 61064],
- [27058, 61066], [36262, 61067], 61068, [35241, 58392, 61069], 0,
- [28089, 61071], [34753, 61072], [61073, 147473], [29927, 61074],
- [15835, 61075], [29046, 61076], [24740, 57702, 61077], [24988, 61078],
- [15569, 61079], 0, [24695, 61081], 61082, [32625, 61083], 0,
- [24809, 61086], [19326, 61087], [57344, 132423], [37595, 57345],
- [57346, 132575], [57347, 147397], [34124, 57348], [17077, 57349],
- [29679, 57350], [20917, 57351], [13897, 57352], [57353, 149826],
- [57354, 166372], [37700, 57355], [57356, 137691], [33518, 57357],
- [57358, 146632], [30780, 57359], [26436, 57360], [25311, 57361],
- [57362, 149811], [57363, 166314], [57364, 131744], [57365, 158643],
- [57366, 135941], [20395, 57367], [57368, 140525], [20488, 57369],
- [57370, 159017], [57371, 162436], [57372, 144896], [57373, 150193],
- [57374, 140563], 0, [57376, 131966], [24484, 57377], [57378, 131968],
- [57379, 131911], [28379, 57380], [57381, 132127], 20702, [20737, 57383],
- [13434, 57384], [20750, 57385], [39020, 57386], [14147, 57387],
- [33814, 57388], [57389, 149924], [57390, 132231], [20832, 57391],
- [57392, 144308], [20842, 57393], [57394, 134143], [57395, 139516],
- [57396, 131813], [57397, 140592], [57398, 132494], [57399, 143923],
- [57400, 137603], [23426, 57401], [34685, 57402], [57403, 132531],
- [57404, 146585], [20914, 57405], [20920, 57406], [40244, 57407],
- [20937, 57408], [20943, 57409], [20945, 57410], [15580, 57411],
- [20947, 57412], [57413, 150182], [20915, 57414], 0, 0, [20973, 57417],
- [33741, 57418], [26942, 57419], [57420, 145197], [24443, 57421],
- [21003, 57422], [21030, 57423], [21052, 57424], [21173, 57425],
- [21079, 57426], [21140, 57427], [21177, 57428], [21189, 57429],
- [31765, 57430], [34114, 57431], [21216, 57432], [34317, 57433],
- [57434, 158483], 0, [57436, 166622], [21833, 57437], [28377, 57438],
- [57439, 147328], [57440, 133460], [57441, 147436], [21299, 57442], 0,
- [57444, 134114], [27851, 57445], [57446, 136998], [26651, 57447],
- [29653, 57448], [24650, 57449], [16042, 57450], [14540, 57451],
- [57452, 136936], [29149, 57453], [17570, 57454], [21357, 57455],
- [21364, 57456], [57457, 165547], [21374, 57458], 0, [57460, 136598],
- [57461, 136723], [30694, 57462], [21395, 57463], [57464, 166555],
- [21408, 57465], [21419, 57466], [21422, 57467], [29607, 57468],
- [57469, 153458], [16217, 57470], [29596, 57471], [21441, 57472],
- [21445, 57473], [27721, 57474], [20041, 57475], [22526, 57476],
- [21465, 57477], [15019, 57478], [57479, 134031], [21472, 57480],
- [57481, 147435], [57482, 142755], [21494, 57483], [57484, 134263],
- [21523, 57485], [28793, 57486], [21803, 57487], [26199, 57488],
- [27995, 57489], [21613, 57490], [57491, 158547], [57492, 134516],
- [21853, 57493], [21647, 57494], [21668, 57495], [18342, 57496],
- [57497, 136973], [57498, 134877], [15796, 57499], [57500, 134477],
- [57501, 166332], [57502, 140952], [21831, 57503], [19693, 57504],
- [21551, 57505], [29719, 57506], [21894, 57507], [21929, 57508], 0,
- [57510, 137431], [57511, 147514], [17746, 57512], [57513, 148533],
- [26291, 57514], [57515, 135348], [22071, 57516], [26317, 57517],
- [57518, 144010], [26276, 57519], 0, [22093, 57521], [22095, 57522],
- [30961, 57523], [22257, 57524], [38791, 57525], [21502, 57526],
- [22272, 57527], [22255, 57528], [22253, 57529], [57530, 166758],
- [13859, 57531], [57532, 135759], [22342, 57533], [57534, 147877],
- [27758, 57535], [28811, 57536], [22338, 57537], [14001, 57538],
- [57539, 158846], [22502, 57540], [57541, 136214], [22531, 57542],
- [57543, 136276], [57544, 148323], [22566, 57545], [57546, 150517], 0,
- [22698, 57548], [13665, 57549], [22752, 57550], [22748, 57551],
- [57552, 135740], [22779, 57553], [23551, 57554], [22339, 57555],
- [57556, 172368], [57557, 148088], [37843, 57558], [13729, 57559],
- [22815, 57560], [26790, 57561], [14019, 57562], [28249, 57563],
- [57564, 136766], [23076, 57565], 0, [57567, 136850], [34053, 57568],
- [22985, 57569], [57570, 134478], [57571, 158849], [57572, 159018],
- [57573, 137180], [23001, 57574], [57575, 137211], [57576, 137138],
- [57577, 159142], [28017, 57578], [57579, 137256], [57580, 136917],
- [23033, 57581], [57582, 159301], [23211, 57583], [23139, 57584],
- [14054, 57585], [57586, 149929], 0, [14088, 57588], [23190, 57589],
- [29797, 57590], [23251, 57591], [57592, 159649], [57593, 140628],
- [57595, 137489], [14130, 57596], [57597, 136888], [24195, 57598],
- [21200, 57599], [23414, 57600], [25992, 57601], [23420, 57602],
- [57603, 162318], [16388, 57604], [18525, 57605], [57606, 131588],
- [23509, 57607], [57609, 137780], [57610, 154060], [57611, 132517],
- [23539, 57612], [23453, 57613], [19728, 57614], [23557, 57615],
- [57616, 138052], [23571, 57617], [29646, 57618], [23572, 57619],
- [57620, 138405], [57621, 158504], [23625, 57622], [18653, 57623],
- [23685, 57624], [23785, 57625], [23791, 57626], [23947, 57627],
- [57628, 138745], [57629, 138807], [23824, 57630], [23832, 57631],
- [23878, 57632], [57633, 138916], [23738, 57634], [24023, 57635],
- [33532, 57636], [14381, 57637], [57638, 149761], [57639, 139337],
- [57640, 139635], [33415, 57641], [14390, 57642], [15298, 57643],
- [24110, 57644], [27274, 57645], 0, 57647, [57648, 148668], [57649, 134355],
- [21414, 57650], [20151, 57651], 0, [21416, 57653], [57654, 137073],
- [24073, 57655], 57656, [57657, 164994], [24313, 57658], [24315, 57659],
- [14496, 57660], [24316, 57661], [26686, 57662], [37915, 57663],
- [24333, 57664], [57665, 131521], [57666, 194708], [15070, 57667],
- [57669, 135994], [24378, 57670], [57671, 157832], [57672, 140240],
- [57674, 140401], [24419, 57675], [57677, 159342], [24434, 57678],
- [37696, 57679], [57680, 166454], [24487, 57681], [23990, 57682],
- [15711, 57683], [57684, 152144], [57685, 139114], [57686, 159992],
- [57687, 140904], [37334, 57688], [57689, 131742], [57690, 166441],
- [24625, 57691], [26245, 57692], [14691, 57694], [15815, 57695],
- [13881, 57696], [22416, 57697], [57698, 141236], [31089, 57699],
- [15936, 57700], [24734, 57701], 0, 0, [57704, 149890], [57705, 149903],
- [57706, 162387], [29860, 57707], [20705, 57708], [23200, 57709],
- [24932, 57710], [24898, 57712], [57713, 194726], [57714, 159442],
- [24961, 57715], [20980, 57716], [57717, 132694], [24967, 57718],
- [23466, 57719], [57720, 147383], [57721, 141407], [25043, 57722],
- [57723, 166813], [57724, 170333], [25040, 57725], [14642, 57726],
- [57727, 141696], [57728, 141505], [24611, 57729], [24924, 57730],
- [25886, 57731], [25483, 57732], [57733, 131352], [25285, 57734],
- [57735, 137072], [25301, 57736], [57737, 142861], [25452, 57738],
- [57739, 149983], [14871, 57740], [25656, 57741], [25592, 57742],
- [57743, 136078], [57744, 137212], [28554, 57746], [57747, 142902], 0,
- [57750, 153373], [25825, 57751], [25829, 57752], [38011, 57753],
- [14950, 57754], [25658, 57755], [14935, 57756], [25933, 57757],
- [28438, 57758], [57759, 150056], [57760, 150051], [25989, 57761],
- [25965, 57762], [25951, 57763], 0, [26037, 57765], [57766, 149824],
- [19255, 57767], [26065, 57768], [16600, 57769], [57770, 137257], 57771,
- [26083, 57772], [24543, 57773], [57774, 144384], [26136, 57775],
- [57776, 143863], [57777, 143864], [26180, 57778], [57779, 143780],
- [57780, 143781], [26187, 57781], [57782, 134773], [26215, 57783],
- [57784, 152038], [26227, 57785], 0, [57788, 143921], [57789, 165364],
- [57790, 143816], [57791, 152339], [30661, 57792], [57793, 141559],
- [39332, 57794], [26370, 57795], [57796, 148380], [57797, 150049],
- [27130, 57799], [57800, 145346], 0, [26471, 57802], [26466, 57803],
- [57804, 147917], [57805, 168173], [26583, 57806], [17641, 57807],
- [26658, 57808], [28240, 57809], [37436, 57810], [26625, 57811],
- [57812, 144358], [57813, 159136], [26717, 57814], [57815, 144495],
- [27105, 57816], [27147, 57817], [57818, 166623], [26995, 57819],
- [26819, 57820], [57821, 144845], [26881, 57822], [26880, 57823],
- [14849, 57825], [57826, 144956], [15232, 57827], [26540, 57828],
- [26977, 57829], [57830, 166474], [17148, 57831], [26934, 57832],
- [27032, 57833], [15265, 57834], [57835, 132041], [33635, 57836],
- [20624, 57837], [27129, 57838], [57839, 144985], [57840, 139562],
- [27205, 57841], [57842, 145155], [27293, 57843], [15347, 57844],
- [26545, 57845], [27336, 57846], [57847, 168348], [15373, 57848],
- [27421, 57849], [57850, 133411], [24798, 57851, 60308], [27445, 57852],
- [27508, 57853], [57854, 141261], [28341, 57855], [57856, 146139], 0,
- [57858, 137560], [14144, 57859], [21537, 57860], [57861, 146266],
- [27617, 57862], [57863, 147196], [27612, 57864], [27703, 57865],
- [57866, 140427], [57867, 149745], [57868, 158545], [27738, 57869],
- [33318, 57870], [27769, 57871], [57872, 146876], [17605, 57873],
- [57874, 146877], [57875, 147876], [57876, 149772], [57877, 149760],
- [57878, 146633], [14053, 57879], [15595, 57880], [57881, 134450],
- [39811, 57882], [57883, 143865], [57884, 140433], [32655, 57885],
- [26679, 57886], [57887, 159013], [57888, 159137], [57889, 159211],
- [28054, 57890], [27996, 57891], [28284, 57892], [28420, 57893],
- [57894, 149887], [57895, 147589], [57896, 159346], [34099, 57897],
- [57898, 159604], [20935, 57899], 0, 0, [33838, 57902], [57903, 166689], 0,
- [57905, 146991], [29779, 57906], [57907, 147330], [31180, 57908],
- [28239, 57909], [23185, 57910], [57911, 143435], [28664, 57912],
- [14093, 57913], [28573, 57914], [57915, 146992], [28410, 57916],
- [57917, 136343], [57918, 147517], [17749, 57919], [37872, 57920],
- [28484, 57921], [28508, 57922], [15694, 57923], [28532, 57924],
- [57925, 168304], [15675, 57926], [28575, 57927], [57928, 147780],
- [28627, 57929], [57930, 147601], [57931, 147797], [57932, 147513],
- [57933, 147440], [57934, 147380], [57935, 147775], [20959, 57936],
- [57937, 147798], [57938, 147799], [57939, 147776], [57940, 156125],
- [28747, 57941], [28798, 57942], [28839, 57943], 0, [28876, 57945],
- [28885, 57946], [28886, 57947], [28895, 57948], [16644, 57949],
- [15848, 57950], [29108, 57951], [29078, 57952], [57953, 148087],
- [28971, 57954], [28997, 57955], [23176, 57956], [29002, 57957], 0,
- [57960, 148325], [29007, 57961], [37730, 57962], [57963, 148161],
- [28972, 57964], [57965, 148570], [57966, 150055], [57967, 150050],
- [29114, 57968], [57969, 166888], [28861, 57970], [29198, 57971],
- [37954, 57972], [29205, 57973], [22801, 57974], [37955, 57975],
- [29220, 57976], [37697, 57977], [57978, 153093], [29230, 57979],
- [29248, 57980], [57981, 149876], [26813, 57982], [29269, 57983],
- [29271, 57984], [15957, 57985], [57986, 143428], [26637, 57987],
- [28477, 57988], [29314, 57989], 0, [29483, 57991], [57992, 149539],
- [57993, 165931], [18669, 57994], [57995, 165892], [29480, 57996],
- [29486, 57997], [29647, 57998], [29610, 57999], [58000, 134202],
- [58001, 158254], [29641, 58002], [29769, 58003], [58004, 147938],
- [58005, 136935], [58006, 150052], [26147, 58007], [14021, 58008],
- [58009, 149943], [58010, 149901], [58011, 150011], [29687, 58012],
- [29717, 58013], [26883, 58014], [58015, 150054], [29753, 58016],
- [16087, 58018], 0, [58020, 141485], [29792, 58021], [58022, 167602],
- [29767, 58023], [29668, 58024], [29814, 58025], [33721, 58026],
- [29804, 58027], [29812, 58029], [37873, 58030], [27180, 58031],
- [29826, 58032], [18771, 58033], [58034, 150156], [58035, 147807],
- [58036, 150137], [58037, 166799], [23366, 58038], [58039, 166915],
- [58040, 137374], [29896, 58041], [58042, 137608], [29966, 58043],
- [29982, 58045], [58046, 167641], [58047, 137803], [23511, 58048],
- [58049, 167596], [37765, 58050], [30029, 58051], [30026, 58052],
- [30055, 58053], [30062, 58054], [58055, 151426], [16132, 58056],
- [58057, 150803], [30094, 58058], [29789, 58059], [30110, 58060],
- [30132, 58061], [30210, 58062], [30252, 58063], [30289, 58064],
- [30287, 58065], [30319, 58066], 58067, [58068, 156661], [30352, 58069],
- [33263, 58070], [14328, 58071], [58072, 157969], [58073, 157966],
- [30369, 58074], [30373, 58075], [30391, 58076], [30412, 58077],
- [58078, 159647], [33890, 58079], [58080, 151709], [58081, 151933],
- [58082, 138780], [30494, 58083], [30502, 58084], [30528, 58085],
- [25775, 58086], [58087, 152096], [30552, 58088], [58089, 144044],
- [30639, 58090], [58091, 166244], [58092, 166248], [58093, 136897],
- [30708, 58094], 0, [26826, 58098], [30895, 58099], [30919, 58100],
- [30931, 58101], [38565, 58102], [31022, 58103], [58104, 153056],
- [30935, 58105], [31028, 58106], [30897, 58107], [58108, 161292],
- [36792, 58109], [34948, 58110], [58113, 140828], [31110, 58114],
- [35072, 58115], [26882, 58116], [31104, 58117], [58118, 153687],
- [31133, 58119], [58120, 162617], [31036, 58121], [31145, 58122],
- [28202, 58123], [58124, 160038], [16040, 58125], [31174, 58126],
- [58127, 168205], [31188, 58128], 0, [21797, 62526], 0, [62528, 134210],
- [62529, 134421], [62530, 151851], [21904, 62531], [62532, 142534],
- [14828, 62533], [62534, 131905], [36422, 62535], [62536, 150968],
- [62537, 169189], 0, [62539, 164030], [30586, 62540], [62541, 142392],
- [14900, 62542], [18389, 62543], [62544, 164189], [62545, 158194],
- [62546, 151018], [25821, 62547], [62548, 134524], [62549, 135092],
- [62550, 134357], 0, [25741, 62552], [36478, 62553], [62554, 134806], 0,
- [62556, 135012], [62557, 142505], [62558, 164438], [62559, 148691], 0,
- [62561, 134470], [62562, 170573], [62563, 164073], [18420, 62564],
- [62565, 151207], [62566, 142530], [39602, 62567], [14951, 62568],
- [62569, 169460], [16365, 62570], [13574, 62571], [62572, 152263],
- [62573, 169940], 0, [62575, 142660], [40302, 62576], [38933, 62577], 0,
- [17369, 62579], 0, [25780, 62581], [21731, 62582], 0, [62584, 142282], 0,
- [14843, 62586], 0, [62588, 157402], [62589, 157462], [62590, 162208],
- [25834, 62591], [62592, 151634], [62593, 134211], [36456, 62594], 0,
- [62596, 166732], [62597, 132913], 0, [18443, 62599], [62600, 131497],
- [16378, 62601], [22643, 62602], [62603, 142733], 0, [62605, 148936],
- [62606, 132348], [62607, 155799], [62608, 134988], 0, [21881, 62610], 0,
- [17338, 62612], 0, [19124, 62614], [62615, 141926], [62616, 135325],
- [33194, 62617], [39157, 62618], [62619, 134556], [25465, 62620],
- [14846, 62621], [62622, 141173], [36288, 62623], [22177, 62624],
- [25724, 62625], [15939, 62626], 0, [62628, 173569], [62629, 134665],
- [62630, 142031], 0, 0, [62633, 135368], [62634, 145858], [14738, 62635],
- [14854, 62636], [62637, 164507], [13688, 62638], [62639, 155209],
- [62640, 139463], 0, 0, [62643, 142514], [62644, 169760], [13500, 62645],
- [27709, 62646], [62647, 151099], 0, 0, [62650, 161140], [62651, 142987],
- [62652, 139784], [62653, 173659], [62654, 167117], [62655, 134778],
- [62656, 134196], [62683, 161337], [62684, 142286], [62687, 142417],
- [14872, 62689], [62691, 135367], [62693, 173618], [62695, 167122],
- [62696, 167321], [62697, 167114], [38314, 62698], 0, [62706, 161630],
- [28992, 62708], 0, [20822, 62385], 0, [20616, 62487], 0, [13459, 62489],
- [20870, 62491], [24130, 63037], [20997, 62495], [21031, 62436],
- [21113, 62497], 0, [13651, 62504], [21442, 62505], [21343, 62715], 0,
- [21823, 62520], 0, [21976, 59986], [13789, 62722], [22049, 63067], 0,
- [22100, 60044], [60148, 135291], 0, [60153, 135379], 0, [61095, 135934], 0,
- 0, [14265, 60104], [23745, 61099], [23829, 63066], [23894, 63030],
- [14392, 63036], [20097, 62477], [24253, 63038], [14612, 63042],
- [25017, 63050], [25232, 63054], [25368, 63056], [25690, 63063],
- [25745, 62381], [33133, 62709], [33156, 59922], [33171, 59924],
- [26624, 63080], [15292, 63093], [29327, 60517], [29389, 59781], 0,
- [29497, 59785], [30018, 59811], [30172, 59817], [16320, 59818],
- [60278, 151205], [16343, 59820], 0, 30336, [30348, 59824, 151388],
- [16552, 59845], [30777, 59846], [16643, 59855], [31377, 59863],
- [31771, 59876], [31981, 59884], [32659, 62658], [32686, 59892], 0,
- [33535, 59936], [22623, 59981], [34482, 59960], 0, [34699, 59963],
- [35143, 59969], 0, [35369, 59972], 0, [36465, 59988], [60484, 164233],
- [36528, 59990], 0, [37214, 62443], [37260, 62441], [39182, 60051],
- [39196, 60054], 0, 0, [39809, 60066], [40384, 60080], [40339, 60078],
- [40620, 60085], [19857, 60540], 0, 37818, [40571, 60084], [28809, 63148],
- [29512, 59788], 0, [31129, 59858], [36791, 59997], 0, [39234, 60056],
- {s: 193}, 8364, {s: 4}, [12443, 63518], [12444, 63519], [11904, 63520],
- {f: 5, c: 62211}, [62216, 131340], 62217, [62218, 131281], [62219, 131277],
- {f: 2, c: 62220}, [62222, 131275], [62223, 139240], 62224, [62225, 131274],
- {f: 4, c: 62226}, [62230, 131342], {f: 2, c: 62231}, {f: 2, c: 62776},
- [62778, 138177], [62779, 194680], [12205, 38737, 62780], [62781, 131206],
- [20059, 62782], [20155, 62783], [13630, 62784], [23587, 62785],
- [24401, 62786], [24516, 62787], [14586, 62788], [25164, 62789],
- [25909, 62790], [27514, 62791], [27701, 62792], [27706, 62793],
- [28780, 62794], [29227, 62795], [20012, 62796], [29357, 62797],
- [62798, 149737], [32594, 62799], [31035, 62800], [31993, 62801],
- [32595, 62802], [62803, 156266], [13505, 62804], [62806, 156491],
- [32770, 62807], [32896, 62808], [62809, 157202], [62810, 158033],
- [21341, 62811], [34916, 62812], [35265, 62813], [62814, 161970],
- [35744, 62815], [36125, 62816], [38021, 62817], [38264, 62818],
- [38271, 62819], [38376, 62820], [62821, 167439], [38886, 62822],
- [39029, 62823], [39118, 62824], [39134, 62825], [39267, 62826],
- [62827, 170000], [40060, 62828], [40479, 62829], [40644, 62830],
- [27503, 62831], [62832, 63751], [20023, 62833], [62834, 131207],
- [38429, 62835], [25143, 62836], [38050, 62837], [11908, 63521],
- [11910, 63522], [11911, 63523], [11912, 63524], [11914, 63525],
- [11916, 63526], [11917, 63527], [11925, 63528], [11932, 63529],
- [11941, 63531], [11943, 63532], [11946, 63533], [11948, 63534],
- [11950, 63535], [11958, 63536], [11964, 63537], [11966, 63538],
- [11978, 63540], [11980, 63541], [11981, 63542], [11983, 63543],
- [11990, 63544], [11991, 63545], [11998, 63546], [62368, 172969],
- [62369, 135493], [25866, 62371], [20029, 62374], [28381, 62375],
- [40270, 62376], [37343, 62377], [62380, 161589], [20250, 62382],
- [20264, 62383], [20392, 62384], [20852, 62386], [20892, 62387],
- [20964, 62388], [21153, 62389], [21160, 62390], [21307, 62391],
- [21326, 62392], [21457, 62393], [21464, 62394], [22242, 62395],
- [22768, 62396], [22788, 62397], [22791, 62398], [22834, 62399],
- [22836, 62400], [23398, 62401], [23454, 62402], [23455, 62403],
- [23706, 62404], [24198, 62405], [24635, 62406], [25993, 62407],
- [26622, 62408], [26628, 62409], [26725, 62410], [27982, 62411],
- [28860, 62412], [30005, 62413], [32420, 62414], [32428, 62415],
- [32442, 62416], [32455, 62417], [32463, 62418], [32479, 62419],
- [32518, 62420], [32567, 62421], [33402, 62422], [33487, 62423],
- [33647, 62424], [35270, 62425], [35774, 62426], [35810, 62427],
- [36710, 62428], [36711, 62429], [36718, 62430], [29713, 62431],
- [31996, 62432], [32205, 62433], [26950, 62434], [31433, 62435],
- [30904, 62442], [32956, 62444], [36107, 62446], [33014, 62447],
- [62448, 133607], [32927, 62451], [40647, 62452], [19661, 62453],
- [40393, 62454], [40460, 62455], [19518, 62456], [62457, 171510],
- [62458, 159758], [40458, 62459], [62460, 172339], [13761, 62461],
- [28314, 62463], [33342, 62464], [29977, 62465], [18705, 62467],
- [39532, 62468], [39567, 62469], [40857, 62470], [31111, 62471],
- [62472, 164972], [62473, 138698], [62474, 132560], [62475, 142054],
- [20004, 62476], [20096, 62478], [20103, 62479], [20159, 62480],
- [20203, 62481], [20279, 62482], [13388, 62483], [20413, 62484],
- [15944, 62485], [20483, 62486], [13437, 62488], [13477, 62490],
- [22789, 62492], [20955, 62493], [20988, 62494], [20105, 62496],
- [21136, 62498], [21287, 62499], [13767, 62500], [21417, 62501],
- [13649, 62502], [21424, 62503], [21539, 62506], [13677, 62507],
- [13682, 62508], [13953, 62509], [21651, 62510], [21667, 62511],
- [21684, 62512], [21689, 62513], [21712, 62514], [21743, 62515],
- [21784, 62516], [21795, 62517], [21800, 62518], [13720, 62519],
- [13733, 62521], [13759, 62522], [21975, 62523], [13765, 62524],
- [62525, 163204], [16467, 62538], [62551, 135412], [62555, 134155],
- [62574, 161992], [62580, 155813], [62583, 142668], [62585, 135287],
- [62587, 135279], [62595, 139681], [62609, 134550], [16571, 62611],
- [62631, 142537], [22098, 62641], [62642, 134961], [62657, 157724],
- [62659, 135375], [62660, 141315], [62661, 141625], [13819, 62662],
- [62663, 152035], [62664, 134796], [62665, 135053], [62666, 134826],
- [16275, 62667], [62668, 134960], [62669, 134471], [62670, 135503],
- [62671, 134732], [62673, 134827], [62674, 134057], [62675, 134472],
- [62676, 135360], [62677, 135485], [16377, 62678], [62679, 140950],
- [25650, 62680], [62681, 135085], [62682, 144372], [62685, 134526],
- [62686, 134527], [62688, 142421], [62690, 134808], [62692, 134958],
- [62694, 158544], [21708, 62699], [33476, 62700], [21945, 62701],
- [62703, 171715], [39974, 62704], [39606, 62705], [62707, 142830],
- [33004, 62710], [23580, 62711], [62712, 157042], [33076, 62713],
- [14231, 62714], [62716, 164029], [37302, 62717], [62718, 134906],
- [62719, 134671], [62720, 134775], [62721, 134907], [62723, 151019],
- [13833, 62724], [62725, 134358], [22191, 62726], [62727, 141237],
- [62728, 135369], [62729, 134672], [62730, 134776], [62731, 135288],
- [62732, 135496], [62733, 164359], [62734, 136277], [62735, 134777],
- [62736, 151120], [62737, 142756], [23124, 62738], [62739, 135197],
- [62740, 135198], [62741, 135413], [62742, 135414], [22428, 62743],
- [62744, 134673], [62745, 161428], [62746, 164557], [62747, 135093],
- [62748, 134779], [62749, 151934], [14083, 62750], [62751, 135094],
- [62752, 135552], [62753, 152280], [62754, 172733], [62755, 149978],
- [62756, 137274], [62757, 147831], [62758, 164476], [22681, 62759],
- [21096, 62760], [13850, 62761], [62762, 153405], [31666, 62763],
- [23400, 62764], [18432, 62765], [19244, 62766], [40743, 62767],
- [18919, 62768], [39967, 62769], [39821, 62770], [62771, 154484],
- [62772, 143677], [22011, 62773], [13810, 62774], [22153, 62775],
- [23870, 63028], [23880, 63029], [15868, 63031], [14351, 63032],
- [23972, 63033], [23993, 63034], [14368, 63035], [24357, 63039],
- [24451, 63040], [14600, 63041], [14655, 63043], [14669, 63044],
- [24791, 63045], [24893, 63046], [23781, 63047], [14729, 63048],
- [25015, 63049], [25039, 63051], [14776, 63052], [25132, 63053],
- [25317, 63055], [14840, 63057], [22193, 63058], [14851, 63059],
- [25570, 63060], [25595, 63061], [25607, 63062], [14923, 63064],
- [25792, 63065], [40863, 63068], [14999, 63069], [25990, 63070],
- [15037, 63071], [26111, 63072], [26195, 63073], [15090, 63074],
- [26258, 63075], [15138, 63076], [26390, 63077], [15170, 63078],
- [26532, 63079], [15192, 63081], [26698, 63082], [26756, 63083],
- [15218, 63084], [15217, 63085], [15227, 63086], [26889, 63087],
- [26947, 63088], [29276, 63089], [26980, 63090], [27039, 63091],
- [27013, 63092], [27094, 63094], [15325, 63095], [27237, 63096],
- [27252, 63097], [27249, 63098], [27266, 63099], [15340, 63100],
- [27289, 63101], [15346, 63102], [27307, 63103], [27317, 63104],
- [27348, 63105], [27382, 63106], [27521, 63107], [27585, 63108],
- [27626, 63109], [27765, 63110], [27818, 63111], [15563, 63112],
- [27906, 63113], [27910, 63114], [27942, 63115], [28033, 63116],
- [15599, 63117], [28068, 63118], [28081, 63119], [28181, 63120],
- [28184, 63121], [28201, 63122], [28294, 63123], [63124, 166336],
- [28347, 63125], [28386, 63126], [28378, 63127], [40831, 63128],
- [28392, 63129], [28393, 63130], [28452, 63131], [28468, 63132],
- [15686, 63133], [63134, 147265], [28545, 63135], [28606, 63136],
- [15722, 63137], [15733, 63138], [29111, 63139], [23705, 63140],
- [15754, 63141], [28716, 63142], [15761, 63143], [28752, 63144],
- [28756, 63145], [28783, 63146], [28799, 63147], [63149, 131877],
- [17345, 63150], [13809, 63151], [63152, 134872], [13902, 58134],
- [15789, 58172], [58173, 154725], [26237, 58183], [31860, 58188],
- [29837, 58197], [32402, 58215], [17667, 58232], [58260, 151480],
- [58270, 133901], [58277, 158474], [13438, 58311], [58317, 143087],
- [58325, 146613], [58343, 159385], [34673, 58364], [25537, 58385],
- [30583, 58387], [35210, 58390], [58406, 147343], [35660, 58415],
- [58440, 150729], [18730, 58464], [58471, 172052], [58472, 165564],
- [58473, 165121], [15088, 58490], [28815, 58511], [58529, 140922],
- [58637, 158120], [58646, 148043], [26760, 58662], [58664, 139611],
- [40802, 58702], [37830, 58793], [58802, 131967], [37734, 58888],
- [37519, 58901], [34324, 58954], [58986, 173147], [16784, 59010],
- [26511, 59045], [26654, 59048], [14435, 59051], [59077, 149996],
- [15129, 59128], [33942, 59176], [59241, 149858], [14818, 59254],
- [33920, 59259], [17262, 59328], [38769, 59402], [39323, 59427],
- [18733, 59499], [28439, 59703], [59704, 160009], [28838, 59746],
- [59752, 150095], [32357, 59753], [23855, 59755], [15859, 59756],
- [59758, 150109], [59759, 137183], [32164, 59760], [33830, 59761],
- [21637, 59762], [59763, 146170], [59765, 131604], [22398, 59766],
- [59767, 133333], [59768, 132633], [16357, 59769], [59770, 139166],
- [59771, 172726], [28675, 59772], [59773, 168283], [23920, 59774],
- [29583, 59775], [59777, 166489], [59778, 168992], [20424, 59779],
- [32743, 59780], [29456, 59782], [29496, 59784], [29505, 59787],
- [16041, 59789], [29173, 59792], [59793, 149746], [29665, 59794],
- [16074, 59796], [16081, 59798], [29721, 59801], [29726, 59802],
- [29727, 59803], [16098, 59804], [16112, 59805], [16116, 59806],
- [16122, 59807], [29907, 59808], [16142, 59809], [16211, 59810],
- [30061, 59812], [30066, 59813], [30093, 59814], [16252, 59815],
- [30152, 59816], [30285, 59819], [30324, 59821], [16348, 59822],
- [30330, 59823], [29064, 59825], [22051, 59826], [35200, 59827],
- [16413, 59829], [30531, 59830], [16441, 59831], [16453, 59833],
- [13787, 59834], [30616, 59835], [16490, 59836], [16495, 59837],
- [30654, 59839], [30667, 59840], [30744, 59842], [30748, 59844],
- [30791, 59847], [30801, 59848], [30822, 59849], [33864, 59850],
- [59851, 152885], [31027, 59852], [31026, 59854], [16649, 59856],
- [31121, 59857], [31238, 59860], [16743, 59862], [16818, 59864],
- [31420, 59865], [33401, 59866], [16836, 59867], [31439, 59868],
- [31451, 59869], [16847, 59870], [31586, 59872], [31596, 59873],
- [31611, 59874], [31762, 59875], [16992, 59877], [17018, 59878],
- [31867, 59879], [31900, 59880], [17036, 59881], [31928, 59882],
- [17044, 59883], [36755, 59885], [28864, 59886], [59887, 134351],
- [32207, 59888], [32212, 59889], [32208, 59890], [32253, 59891],
- [32692, 59893], [29343, 59894], [17303, 59895], [32800, 59896],
- [32805, 59897], [32814, 59899], [32817, 59900], [32852, 59901],
- [22452, 59903], [28832, 59904], [32951, 59905], [33001, 59906],
- [17389, 59907], [33036, 59908], [33038, 59910], [33042, 59911],
- [33044, 59913], [17409, 59914], [15161, 59915], [33110, 59916],
- [33113, 59917], [33114, 59918], [17427, 59919], [33148, 59921],
- [17445, 59923], [17453, 59925], [33189, 59926], [22511, 59927],
- [33217, 59928], [33252, 59929], [33364, 59930], [17551, 59931],
- [33398, 59933], [33482, 59934], [33496, 59935], [17584, 59937],
- [33623, 59938], [38505, 59939], [33797, 59941], [28917, 59942],
- [33892, 59943], [33928, 59945], [17668, 59946], [33982, 59947],
- [34017, 59948], [34040, 59949], [34064, 59950], [34104, 59951],
- [34130, 59952], [17723, 59953], [34159, 59954], [34160, 59955],
- [34272, 59956], [17783, 59957], [34418, 59958], [34450, 59959],
- [34543, 59961], [38469, 59962], [17926, 59964], [17943, 59965],
- [34990, 59966], [35071, 59967], [35108, 59968], [35217, 59970],
- [59971, 162151], [35384, 59973], [35476, 59974], [35508, 59975],
- [35921, 59976], [36052, 59977], [36082, 59978], [36124, 59979],
- [18328, 59980], [36291, 59982], [18413, 59983], [36410, 59985],
- [22356, 59987], [22005, 59989], [18487, 59991], [36558, 59992],
- [36578, 59993], [36580, 59994], [36589, 59995], [36594, 59996],
- [36801, 59998], [36810, 59999], [36812, 60000], [36915, 60001],
- [18605, 60003], [39136, 60004], [37395, 60005], [18718, 60006],
- [37416, 60007], [37464, 60008], [37483, 60009], [37553, 60010],
- [37550, 60011], [37567, 60012], [37603, 60013], [37611, 60014],
- [37619, 60015], [37620, 60016], [37629, 60017], [37699, 60018],
- [37764, 60019], [37805, 60020], [18757, 60021], [18769, 60022],
- [37911, 60024], [37917, 60026], [37933, 60027], [37950, 60028],
- [18794, 60029], [37972, 60030], [38009, 60031], [38189, 60032],
- [38306, 60033], [18855, 60034], [38388, 60035], [38451, 60036],
- [18917, 60037], [18980, 60039], [38720, 60040], [18997, 60041],
- [38834, 60042], [38850, 60043], [19172, 60045], [39097, 60047],
- [19225, 60048], [39153, 60049], [22596, 60050], [39193, 60052],
- [39223, 60055], [39261, 60057], [39266, 60058], [19312, 60059],
- [39365, 60060], [19357, 60061], [39484, 60062], [39695, 60063],
- [39785, 60065], [39901, 60067], [39921, 60068], [39924, 60069],
- [19565, 60070], [39968, 60071], [14191, 60072], [60073, 138178],
- [40265, 60074], [40702, 60076], [22096, 60077], [40381, 60079],
- [40444, 60081], [38134, 60082], [36790, 60083], [40625, 60086],
- [40637, 60087], [40646, 60088], [38108, 60089], [40674, 60090],
- [40689, 60091], [40696, 60092], [40772, 60094], [60095, 131220],
- [60096, 131767], [60097, 132000], [38083, 60099], [60101, 132311],
- [38081, 60103], [60105, 132565], [60106, 132629], [60107, 132726],
- [60108, 136890], [22359, 60109], [29043, 60110], [60111, 133826],
- [60112, 133837], [60113, 134079], [60115, 194619], [60116, 134091],
- [21662, 60117], [60118, 134139], [60119, 134203], [60120, 134227],
- [60121, 134245], [60122, 134268], [60124, 134285], [60126, 134325],
- [60127, 134365], [60128, 134381], [60129, 134511], [60130, 134578],
- [60131, 134600], [60135, 134660], [60136, 134670], [60137, 134871],
- [60138, 135056], [60139, 134957], [60140, 134771], [60142, 135100],
- [60144, 135260], [60145, 135247], [60146, 135286], [60149, 135304],
- [60150, 135318], [13895, 60151], [60152, 135359], [60154, 135471],
- [60155, 135483], [21348, 60156], [60158, 135907], [60159, 136053],
- [60160, 135990], [60162, 136567], [60163, 136729], [60164, 137155],
- [60165, 137159], [28859, 60167], [60168, 137261], [60169, 137578],
- [60170, 137773], [60171, 137797], [60172, 138282], [60173, 138352],
- [60174, 138412], [60175, 138952], [60177, 138965], [60178, 139029],
- [29080, 60179], [60181, 139333], [27113, 60182], [14024, 60183],
- [60184, 139900], [60185, 140247], [60186, 140282], [60187, 141098],
- [60188, 141425], [60189, 141647], [60191, 141671], [60192, 141715],
- [60193, 142037], [60195, 142056], [60197, 142094], [60199, 142143],
- [60202, 142412], [60204, 142472], [60205, 142519], [60206, 154600],
- [60207, 142600], [60208, 142610], [60209, 142775], [60210, 142741],
- [60211, 142914], [60212, 143220], [60213, 143308], [60214, 143411],
- [60215, 143462], [60216, 144159], [60217, 144350], [60222, 144743],
- [60223, 144883], [60227, 144922], [60228, 145174], [22709, 60231],
- [60234, 146087], [60237, 146961], [60238, 147129], [60243, 147737],
- [60245, 148206], [60246, 148237], [60248, 148276], [60249, 148374],
- [60258, 148484], [60259, 148694], [22408, 60260], [60261, 149108],
- [60263, 149295], [60271, 149522], [60272, 149755], [60273, 150037],
- [60275, 150208], [22885, 60277], [60279, 151430], [60282, 151596],
- [22335, 60284], [60286, 152217], [60287, 152601], [60291, 152646],
- [60292, 152686], [60296, 152895], [60298, 152926], [60300, 152930],
- [60301, 152934], [60302, 153543], [60304, 153693], [60309, 153859],
- [60312, 154286], [60313, 154505], [60314, 154630], [22433, 60316],
- [29009, 60317], [60319, 155906], [60322, 156082], [60325, 156674],
- [60326, 156746], [60330, 156804], [60334, 156808], [60336, 156946],
- [60338, 157119], [60339, 157365], [22201, 60347], [60349, 157436],
- [13848, 60355], [60357, 157593], [60358, 157806], [60360, 157790],
- [60362, 157895], [60366, 157990], [60368, 158009], [60371, 158202],
- [60373, 158253], [60378, 158260], [60379, 158555], [60383, 158621],
- [60385, 158884], [60388, 159150], [60392, 159819], [60393, 160205],
- [60395, 160384], [60396, 160389], [60399, 160395], [60401, 160486],
- [38047, 60404], [60405, 160848], [14009, 60416], [60424, 161740],
- [60425, 161880], [22230, 60426], [60435, 162269], [60441, 162301],
- [60442, 162314], [60443, 162571], [60444, 163174], [60448, 163849],
- [60459, 163875], [60463, 163912], [60466, 163971], [60479, 163984],
- [60480, 164084], [60481, 164142], [60483, 164175], [60485, 164271],
- [60486, 164378], [60487, 164614], [60488, 164655], [60489, 164746],
- [60491, 164968], [60492, 165546], [25574, 60494], [60495, 166230],
- [60498, 166328], [60500, 166375], [60502, 166376], [60503, 166726],
- [60504, 166868], [60506, 166921], [60508, 167877], [60509, 168172],
- [60511, 168208], [60512, 168252], [15863, 60513], [60514, 168286],
- [60515, 150218], [36816, 60516], [60519, 169191], [60521, 169392],
- [60522, 169400], [60523, 169778], [60524, 170193], [60525, 170313],
- [60526, 170346], [60527, 170435], [60528, 170536], [60529, 170766],
- [60530, 171354], [60531, 171419], [32415, 60532], [60533, 171768],
- [60534, 171811], [19620, 60535], [38215, 60536], [60537, 172691],
- [29090, 60538], [60539, 172799], [60542, 173515], [19868, 60543],
- [60544, 134300], [36798, 60545], [36794, 60547], [60548, 140464],
- [36793, 60549], [60550, 150163], [20202, 60555], [60557, 166700],
- [36480, 60560], [60561, 137205], [60563, 166764], [60564, 166809],
- [60566, 157359], [60568, 161365], [60570, 153141], [60571, 153942],
- [20122, 60572], [60573, 155265], [60576, 134765], [60579, 147080],
- [60580, 150686], [60583, 137206], [60584, 137339], [60587, 154698],
- [60589, 152337], [15814, 60590], [60596, 155352], [19996, 60600],
- [60601, 135146], [60602, 134473], [60603, 145082], [60638, 151880],
- [21982, 60644], [34694, 60672], [60676, 135361], [60679, 149254],
- [23440, 60680], [60682, 157843], [60684, 141044], [60685, 163119],
- [60686, 147875], [60687, 163187], [60688, 159440], [60689, 160438],
- [60691, 135641], [60693, 146684], [60694, 173737], [60695, 134828],
- [60698, 138402], [60700, 151490], [60702, 135147], [60706, 142752],
- [60710, 135148], [60711, 134666], [60714, 135149], [60717, 135559],
- [19994, 60721], [19972, 60722], [23309, 60724], [13996, 60727],
- [21373, 60729], [13989, 60730], [22682, 60732], [60733, 150382],
- [22442, 60736], [60737, 154261], [60738, 133497], [60741, 140389],
- [60746, 146686], [60747, 171824], [60749, 151465], [60750, 169374],
- [60753, 146870], [60755, 157619], [60756, 145184], [60759, 147191],
- [60760, 146988], [60785, 143578], [60789, 135849], [22439, 60790],
- [60791, 149859], [60794, 159918], [60801, 137068], [60806, 160100],
- [60809, 159010], [60810, 150242], [39963, 60837], [60838, 149822],
- [15878, 60846], [60881, 159011], [60887, 132092], [60891, 146685],
- [60893, 149785], [22394, 60904], [21722, 60912], [29050, 60928],
- [60949, 150135], [60955, 166490], [60962, 194624], [60976, 137275],
- [61000, 155993], [61014, 144373], [61019, 166850], [61024, 138566],
- [61054, 159441], [13877, 61065], [61084, 166701], [21024, 61088],
- [15384, 61089], [61090, 146631], [61091, 155351], [61092, 161366],
- [61093, 152881], [61094, 137540], [61096, 170243], [61097, 159196],
- [61098, 159917], [61100, 156077], [61101, 166415], [61102, 145015],
- [61103, 131310], [61104, 157766], [61105, 151310], [17762, 61106],
- [23327, 61107], [61108, 156492], [40784, 61109], [40614, 61110],
- [61111, 156267], [20962, 57415], [21314, 57416], [26285, 57520],
- [22620, 57547], [21843, 57566], [15749, 57594], [24928, 57608],
- [18606, 57668], [38845, 57676], [57693, 137335], [24755, 57703],
- [33828, 57711], [38932, 57748], [57749, 147596], [57764, 143486],
- [57787, 138813], [15147, 57798], [15666, 57824], [57857, 132021],
- [28801, 57944], [23708, 57959], [58017, 132547], [14128, 58028],
- [58096, 136054], [58097, 150034], [58111, 166699], [58112, 155779],
- [256, 62233], [193, 62234], [461, 62235], [192, 62236], [274, 62237],
- [201, 62238], [282, 62239], [200, 62240], [332, 62241], [211, 62242],
- [465, 62243], [210, 62244], 62245, [7870, 62246], 62247, [7872, 62248],
- [202, 62249], [257, 62250], [225, 62251], [462, 62252], [224, 62253],
- [593, 62254], [275, 62255], [233, 62256], [283, 62257], [232, 62258],
- [299, 62259], [237, 62260], [464, 62261], [236, 62262], [333, 62263],
- [243, 62264], [466, 62265], [242, 62266], [363, 62267], [250, 62268],
- [468, 62269], [249, 62270], [470, 62271], [472, 62272], [474, 62273],
- [476, 62274], [252, 62275], 62276, [7871, 62277], 62278, [7873, 62279],
- [234, 62280], [609, 62281], [643, 63551], [592, 63552], [603, 63553],
- [596, 63554], [629, 63555], [339, 63556], [248, 63557], [331, 63558],
- [650, 63559], [618, 63560], {f: 2, c: 62282}, [11933, 63530],
- [11974, 63539], [12003, 63547], 20539, 28158, [62841, 171123], 62842,
- [15817, 62843], 34959, [62845, 147790], 28791, 23797, [19232, 62848],
- [62849, 152013], [13657, 62850], [62851, 154928], 24866, [62853, 166450],
- 36775, 37366, 29073, 26393, 29626, [62859, 144001], [62860, 172295],
- [15499, 62861], [62862, 137600], [19216, 62863], 30948, 29698, 20910,
- [62867, 165647], [16393, 62868], 27235, [62870, 172730], [16931, 62871],
- 34319, 31274, [62875, 170311], [62876, 166634], 38741, 28749, 21284,
- [62880, 139390], 37876, 30425, [62883, 166371], 62884, 30685, 20131, 20464,
- 20668, 20015, 20247, 62891, 21556, 32139, 22674, 22736, [62896, 138678],
- 24210, 24217, 24514, [62900, 141074], 25995, [62902, 144377], 26905, 27203,
- [62905, 146531], 27903, 29184, [62909, 148741], 29580, [16091, 62911],
- [62912, 150035], 23317, 29881, 35715, [62916, 154788], [62917, 153237],
- 31379, 31724, 31939, 32364, 33528, 34199, 62924, 34960, 62926, 36537,
- 62928, 36815, 34143, 39392, 37409, 62933, [62934, 167353], [62935, 136255],
- [16497, 62936], [17058, 62937], 23066, 39016, 26475, [17014, 62944], 22333,
- 34262, [62948, 149883], 33471, [62950, 160013], [19585, 62951],
- [62952, 159092], 23931, [62954, 158485], [62955, 159678], {f: 2, c: 62956},
- 23446, 62959, 32347],
- 'Adobe-GB1': [{f: 95, c: 32}, {f: 3, c: 12288}, [183, 12539], 713, 711, 168,
- 12291, 12293, 8212, 65374, 8214, [8230, 8943], {f: 2, c: 8216},
- {f: 2, c: 8220}, {f: 2, c: 12308}, {f: 8, c: 12296}, {f: 2, c: 12310},
- {f: 2, c: 12304}, 177, 215, 247, 8758, {f: 2, c: 8743}, 8721, 8719, 8746,
- 8745, 8712, 8759, 8730, 8869, 8741, 8736, 8978, 8857, 8747, 8750, 8801,
- 8780, 8776, 8765, 8733, 8800, {f: 2, c: 8814}, {f: 2, c: 8804}, 8734, 8757,
- 8756, 9794, 9792, 176, {f: 2, c: 8242}, 8451, 65284, 164, {f: 2, c: 65504},
- 8240, 167, 8470, 9734, 9733, 9675, 9679, 9678, 9671, 9670, 9633, 9632,
- 9651, 9650, 8251, 8594, {f: 2, c: 8592}, 8595, 12307, {f: 20, c: 9352},
- {f: 20, c: 9332}, {f: 10, c: 9312}, {f: 10, c: 12832}, {f: 12, c: 8544},
- {f: 3, c: 65281}, 65509, {f: 89, c: 65285}, 65507, {f: 83, c: 12353},
- {f: 86, c: 12449}, {f: 17, c: 913}, {f: 7, c: 931}, {f: 17, c: 945},
- {f: 7, c: 963}, {f: 7, c: 59277}, {f: 2, c: 65077}, {f: 2, c: 65081},
- {f: 2, c: 65087}, {f: 2, c: 65085}, {f: 4, c: 65089}, {f: 2, c: 59284},
- {f: 2, c: 65083}, {f: 2, c: 65079}, 65073, 59286, {f: 2, c: 65075},
- {f: 6, c: 1040}, 1025, {f: 32, c: 1046}, 1105, {f: 26, c: 1078}, 257, 225,
- 462, 224, 275, 233, 283, 232, 299, 237, 464, 236, 333, 243, 466, 242, 363,
- 250, 468, 249, 470, 472, 474, 476, 252, 234, 593, 7743, 324, 328, 505, 609,
- {f: 37, c: 12549}, 0, {f: 76, c: 9472}, {s: 126}, 21834, 38463, 22467,
- 25384, 21710, 21769, 21696, 30353, 30284, 34108, 30702, 33406, 30861,
- 29233, 38552, 38797, 27688, 23433, 20474, 25353, 26263, 23736, 33018,
- 26696, 32942, 26114, 30414, 20985, 25942, 29100, 32753, 34948, 20658,
- 22885, 25034, 28595, 33453, 25420, 25170, 21485, 21543, 31494,
- [12043, 20843], 30116, 24052, 25300, 36299, 38774, 25226, 32793, 22365,
- 38712, 32610, 29240, [12137, 30333], 26575, 30334, 25670, 20336, 36133,
- 25308, 31255, 26001, 29677, 25644, 25203, 33324, 39041, 26495, 29256,
- 25198, 25292, 20276, 29923, 21322, 21150, 32458, 37030, 24110, 26758,
- 27036, 33152, 32465, 26834, 30917, 34444, 38225, 20621, 35876, 33502,
- 32990, 21253, 35090, 21093, 34180, 38649, 20445, 22561, 39281, 23453,
- 25265, 25253, 26292, 35961, 40077, 29190, 26479, 30865, 24754, 21329,
- 21271, 36744, 32972, 36125, 38049, 20493, 29384, 22791, 24811, 28953,
- 34987, 22868, 33519, 26412, 31528, 23849, 32503, 29997, 27893, 36454,
- 36856, 36924, [12240, 40763], [12112, 27604], 37145, 31508, 24444, 30887,
- 34006, 34109, 27605, 27609, 27606, 24065, 24199, 30201, 38381, 25949,
- 24330, 24517, 36767, 22721, 33218, 36991, 38491, 38829, 36793, 32534,
- 36140, 25153, 20415, 21464, 21342, {f: 2, c: 36776}, 36779, 36941, 26631,
- 24426, 33176, 34920, 40150, 24971, 21035, 30250, 24428, 25996, 28626,
- 28392, 23486, 25672, 20853, 20912, 26564, 19993, 31177, 39292, 28851,
- 30149, 24182, 29627, 33760, 25773, 25320, 38069, 27874, 21338, 21187,
- 25615, 38082, 31636, 20271, 24091, 33334, 33046, 33162, 28196, 27850,
- 39539, 25429, [12056, 21340], 21754, 34917, 22496, 19981, 24067, 27493,
- 31807, 37096, 24598, 25830, 29468, 35009, 26448, 25165, 36130, 30572,
- 36393, 37319, 24425, 33756, 34081, 39184, 21442, 34453, 27531, 24813,
- 24808, 28799, 33485, 33329, 20179, 27815, 34255, 25805, 31961, 27133,
- 26361, 33609, 21397, 31574, 20391, 20876, 27979, 23618, 36461, 25554,
- 21449, 33580, 33590, 26597, 30900, 25661, 23519, 23700, 24046, 35815,
- 25286, 26612, 35962, 25600, 25530, 34633, 39307, 35863, 32544, 38130,
- 20135, 38416, 39076, 26124, 29462, 22330, 23581, 24120, 38271, 20607,
- 32928, [12058, 21378], 25950, 30021, 21809, 20513, 36229, 25220, 38046,
- 26397, 22066, 28526, 24034, 21557, 28818, 36710, 25199, 25764, 25507,
- 24443, 28552, 37108, [12162, 33251], [12192, 36784], 23576, 26216, 24561,
- 27785, 38472, 36225, 34924, 25745, 31216, 22478, 27225, 25104, 21576,
- 20056, 31243, 24809, 28548, 35802, 25215, 36894, 39563, 31204, 21507,
- 30196, 25345, 21273, 27744, 36831, 24347, 39536, 32827, 40831, 20360,
- 23610, [12186, 36196], 32709, 26021, 28861, 20805, 20914, [12173, 34411],
- 23815, 23456, 25277, 37228, 30068, 36364, 31264, 24833, 31609, 20167,
- 32504, 30597, 19985, 33261, 21021, 20986, 27249, 21416, 36487, 38148,
- 38607, 28353, 38500, 26970, 30784, 20648, 30679, 25616, 35302, 22788,
- 25571, 24029, 31359, 26941, 20256, 33337, 21912, 20018, 30126, 31383,
- 24162, 24202, 38383, 21019, 21561, 28810, 25462, 38180, 22402, 26149,
- 26943, 37255, 21767, 28147, 32431, 34850, 25139, 32496, 30133, 33576,
- 30913, 38604, 36766, 24904, 29943, 35789, 27492, 21050, 36176, 27425,
- 32874, 33905, 22257, 21254, 20174, 19995, 20945, 31895, 37259, 31751,
- 20419, 36479, 31713, 31388, 25703, 23828, 20652, 33030, 30209, 31929,
- 28140, 32736, 26449, 23384, [12072, 23544], 30923, 25774, 25619, 25514,
- 25387, 38169, 25645, 36798, 31572, 30249, 25171, [12068, 22823], 21574,
- [12109, 27513], 20643, 25140, 24102, 27526, 20195, 36151, 34955, 24453,
- 36910, 24608, 32829, 25285, 20025, 21333, 37112, 25528, 32966, 26086,
- 27694, 20294, 24814, 28129, 35806, 24377, 34507, 24403, 25377, 20826,
- 33633, 26723, [12049, 20992], 25443, 36424, 20498, 23707, 31095, 23548,
- 21040, 31291, 24764, 36947, 30423, 24503, 24471, 30340, 36460, 28783,
- 30331, 31561, 30634, 20979, 37011, 22564, 20302, 28404, 36842, 25932,
- 31515, 29380, 28068, 32735, 23265, 25269, 24213, 22320, 33922, 31532,
- 24093, 24351, 36882, 32532, 39072, 25474, 28359, 30872, 28857, 20856,
- 38747, 22443, 30005, 20291, 30008, 24215, 24806, 22880, 28096, 27583,
- 30857, 21500, 38613, 20939, 20993, 25481, 21514, 38035, 35843, 36300,
- 29241, 30879, 34678, 36845, 35853, 21472, 19969, 30447, 21486, 38025,
- 39030, [12237, 40718], 38189, 23450, 35746, 20002, 19996, 20908, 33891,
- 25026, 21160, 26635, 20375, 24683, 20923, 27934, 20828, 25238,
- [12099, 26007], 38497, [12182, 35910], 36887, 30168, 37117, 30563, 27602,
- 29322, 29420, 35835, 22581, 30585, 36172, 26460, 38208, 32922, 24230,
- 28193, 22930, 31471, 30701, 38203, 27573, 26029, 32526, 22534, 20817,
- 38431, 23545, 22697, 21544, 36466, 25958, 39039, 22244, 38045, 30462,
- 36929, 25479, 21702, 22810, 22842, 22427, 36530, 26421, 36346, 33333,
- 21057, 24816, 22549, 34558, 23784, 40517, 20420, 39069, 35769, 23077,
- 24694, 21380, 25212, 36943, 37122, 39295, 24681, [12157, 32780],
- [12041, 20799], [12159, 32819], 23572, 39285, 27953, [12038, 20108], 36144,
- 21457, 32602, 31567, 20240, 20047, 38400, 27861, 29648, 34281, 24070,
- 30058, 32763, 27146, 30718, 38034, 32321, 20961, 28902, 21453, 36820,
- 33539, 36137, 29359, 39277, 27867, 22346, 33459, [12101, 26041], 32938,
- 25151, 38450, 22952, 20223, 35775, 32442, 25918, 33778, [12206, 38750],
- 21857, 39134, 32933, 21290, 35837, 21536, 32954, 24223, 27832, 36153,
- 33452, 37210, 21545, 27675, 20998, 32439, 22367, 28954, 27774, 31881,
- 22859, 20221, 24575, 24868, 31914, 20016, 23553, 26539, 34562, 23792,
- 38155, 39118, 30127, 28925, 36898, 20911, 32541, 35773, 22857, 20964,
- 20315, 21542, 22827, 25975, 32932, 23413, 25206, 25282, 36752, 24133,
- 27679, 31526, 20239, 20440, 26381, 28014, 28074, 31119, 34993, 24343,
- 29995, 25242, 36741, 20463, 37340, 26023, 33071, 33105, 24220, 33104,
- 36212, 21103, 35206, 36171, 22797, 20613, 20184, [12201, 38428],
- [12119, 29238], 33145, 36127, 23500, 35747, 38468, 22919, 32538, 21648,
- 22134, 22030, 35813, 25913, 27010, 38041, 30422, 28297, [12082, 24178],
- [12130, 29976], 26438, 26577, 31487, 32925, 36214, 24863, 31174, 25954,
- 36195, 20872, 21018, 38050, 32568, 32923, 32434, 23703, 28207, 26464,
- 31705, 30347, [12220, 39640], 33167, 32660, 31957, 25630, 38224, 31295,
- 21578, 21733, 27468, 25601, [12093, 25096], 40509, 33011, 30105, 21106,
- [12208, 38761], 33883, 26684, 34532, 38401, 38548, 38124, 20010, 21508,
- 32473, 26681, 36319, 32789, 26356, 24218, 32697, 22466, 32831, 26775,
- [12079, 24037], 25915, 21151, 24685, 40858, 20379, 36524, 20844, 23467,
- [12088, 24339], 24041, 27742, 25329, 36129, 20849, 38057, 21246, 27807,
- 33503, 29399, 22434, 26500, 36141, 22815, 36764, 33735, 21653, 31629,
- 20272, 27837, 23396, 22993, [12238, 40723], 21476, 34506, [12219, 39592],
- [12181, 35895], 32929, 25925, 39038, 22266, 38599, 21038, [12128, 29916],
- 21072, 23521, 25346, 35074, 20054, 25296, 24618, 26874, 20851, 23448,
- 20896, 35266, 31649, 39302, 32592, 24815, 28748, 36143, 20809,
- [12084, 24191], 36891, 29808, 35268, 22317, 30789, 24402, 40863, 38394,
- 36712, [12225, 39740], 35809, 30328, 26690, 26588, 36330, 36149, 21053,
- 36746, 28378, 26829, 38149, 37101, 22269, 26524, 35065, 36807, 21704,
- 39608, 23401, 28023, 27686, 20133, 23475, 39559, 37219, 25000, 37039,
- 38889, 21547, 28085, 23506, 20989, 21898, 32597, 32752, 25788, 25421,
- 26097, 25022, 24717, 28938, 27735, 27721, 22831, 26477, 33322, 22741,
- 22158, 35946, 27627, 37085, 22909, 32791, 21495, 28009, 21621, 21917,
- 33655, 33743, 26680, [12146, 31166], 21644, 20309, 21512, 30418, 35977,
- 38402, 27827, 28088, 36203, 35088, 40548, 36154, 22079, [12234, 40657],
- 30165, 24456, 29408, 24680, 21756, 20136, 27178, 34913, 24658, 36720,
- 21700, 28888, 34425, 40511, 27946, 23439, 24344, 32418, 21897, 20399,
- 29492, 21564, 21402, 20505, 21518, 21628, 20046, 24573, 29786, 22774,
- 33899, 32993, 34676, 29392, 31946, 28246, 24359, 34382, 21804, 25252,
- 20114, 27818, 25143, 33457, 21719, 21326, 29502, 28369, 30011, 21010,
- 21270, 35805, 27088, 24458, 24576, 28142, 22351, 27426, 29615, 26707,
- 36824, 32531, 25442, 24739, 21796, 30186, 35938, 28949, 28067, 23462,
- 24187, 33618, 24908, 40644, 30970, 34647, 31783, 30343, 20976, 24822,
- 29004, 26179, 24140, 24653, 35854, 28784, 25381, 36745, 24509, 24674,
- 34516, 22238, 27585, 24724, 24935, 21321, 24800, 26214, 36159, 31229,
- 20250, 28905, 27719, 35763, 35826, 32472, 33636, 26127, 23130, 39746,
- 27985, 28151, 35905, 27963, 20249, [12117, 28779], 33719, 25110, 24785,
- 38669, 36135, 31096, 20987, 22334, 22522, 26426, 30072, 31293, 31215,
- 31637, 32908, 39269, 36857, 28608, 35749, 40481, 23020, 32489, 32521,
- 21513, 26497, 26840, 36753, 31821, 38598, 21450, 24613, 30142, 27762,
- 21363, 23241, 32423, 25380, [12047, 20960], 33034, [12080, 24049], 34015,
- 25216, 20864, 23395, 20238, 31085, 21058, 24760, 27982, 23492, 23490,
- 35745, 35760, 26082, 24524, 38469, 22931, 32487, 32426, 22025, 26551,
- 22841, 20339, 23478, 21152, 33626, 39050, 36158, 30002, 38078, 20551,
- 31292, 20215, 26550, 39550, 23233, 27516, 30417, 22362, 23574, 31546,
- 38388, 29006, 20860, 32937, 33392, 22904, 32516, 33575, 26816, 26604,
- 30897, 30839, 25315, 25441, 31616, 20461, 21098, 20943, 33616, 27099,
- 37492, 36341, 36145, 35265, 38190, 31661, 20214, 20581, 33328, 21073,
- 39279, 28176, 28293, 28071, 24314, 20725, 23004, 23558, 27974, 27743,
- 30086, 33931, 26728, 22870, 35762, 21280, 37233, 38477, 34121, 26898,
- 30977, 28966, 33014, 20132, 37066, 27975, 39556, 23047, 22204, 25605,
- 38128, 30699, 20389, 33050, 29409, [12179, 35282], 39290, 32564, 32478,
- 21119, 25945, 37237, 36735, 36739, 21483, 31382, 25581, 25509, 30342,
- 31224, 34903, 38454, 25130, 21163, 33410, 26708, 26480, 25463, 30571,
- 31469, 27905, 32467, 35299, 22992, 25106, 34249, 33445, 30028, 20511,
- 20171, 30117, 35819, 23626, [12081, 24062], 31563, [12100, 26020],
- [12198, 37329], 20170, 27941, 35167, 32039, 38182, 20165, 35880, 36827,
- 38771, 26187, 31105, 36817, 28908, 28024, 23613, 21170, 33606, 20834,
- 33550, 30555, 26230, 40120, 20140, 24778, 31934, 31923, 32463, 20117,
- 35686, 26223, 39048, 38745, 22659, 25964, 38236, 24452, 30153, 38742,
- 31455, 31454, 20928, 28847, 31384, 25578, 31350, 32416, 29590,
- [12210, 38893], 20037, 28792, 20061, 37202, 21417, 25937, 26087,
- [12165, 33276], 33285, 21646, 23601, 30106, 38816, 25304, 29401, 30141,
- 23621, 39545, 33738, 23616, 21632, 30697, 20030, 27822, 32858, 25298,
- 25454, 24040, 20855, 36317, 36382, 38191, 20465, 21477, 24807, 28844,
- 21095, 25424, 40515, 23071, 20518, 30519, 21367, 32482, 25733, 25899,
- 25225, 25496, 20500, 29237, 35273, 20915, 35776, 32477, 22343, 33740,
- 38055, 20891, 21531, 23803, 20426, 31459, 27994, 37089, 39567, 21888,
- 21654, 21345, 21679, 24320, 25577, 26999, 20975, 24936, 21002, 22570,
- 21208, 22350, 30733, 30475, 24247, 24951, 31968, 25179, 25239, 20130,
- 28821, 32771, 25335, 28900, 38752, 22391, 33499, 26607, 26869, 30933,
- 39063, 31185, 22771, 21683, 21487, 28212, 20811, 21051, 23458, 35838,
- 32943, 21827, 22438, 24691, 22353, 21549, 31354, 24656, 23380, 25511,
- 25248, [12061, 21475], 25187, 23495, 26543, 21741, 31391, 33510, 37239,
- 24211, 35044, 22840, 22446, 25358, 36328, 33007, 22359, 31607, 20393,
- 24555, 23485, 27454, 21281, 31568, 29378, 26694, 30719, 30518, 26103,
- 20917, 20111, 30420, 23743, 31397, 33909, 22862, 39745, 20608, 39304,
- 24871, 28291, 22372, 26118, 25414, 22256, 25324, 25193, 24275, 38420,
- 22403, 25289, 21895, 34593, 33098, 36771, 21862, 33713, 26469, 36182,
- 34013, 23146, 26639, 25318, 31726, 38417, 20848, 28572, 35888, 25597,
- 35272, 25042, 32518, 28866, 28389, 29701, 27028, 29436, 24266, 37070,
- 26391, 28010, 25438, 21171, 29282, [12156, 32769], 20332, 23013, 37226,
- 28889, 28061, 21202, 20048, 38647, 38253, 34174, 30922, 32047, 20769,
- 22418, 25794, 32907, 31867, 27882, 26865, 26974, 20919, 21400, 26792,
- 29313, 40654, 31729, 29432, 31163, 28435, 29702, 26446, [12197, 37324],
- 40100, 31036, 33673, 33620, 21519, 26647, 20029, 21385, 21169, 30782,
- 21382, 21033, 20616, 20363, 20432, 30178, [12148, 31435], 31890, 27813,
- [12202, 38582], [12050, 21147], 29827, 21737, 20457, 32852, 33714, 36830,
- 38256, 24265, 24604, 28063, 24088, 25947, 33080, 38142, 24651, 28860,
- 32451, 31918, 20937, 26753, 31921, 33391, 20004, 36742, 37327, 26238,
- 20142, 35845, 25769, 32842, 20698, 30103, 29134, 23525, 36797, 28518,
- 20102, 25730, 38243, 24278, 26009, 21015, 35010, 28872, 21155, 29454,
- 29747, 26519, 30967, 38678, 20020, 37051, 40158, 28107, 20955, 36161,
- 21533, 25294, 29618, 33777, 38646, 40836, 38083, 20278, 32666, 20940,
- 28789, 38517, 23725, 39046, 21478, 20196, 28316, 29705, 27060, 30827,
- 39311, 30041, 21016, 30244, 27969, 26611, 20845, 40857, 32843, 21657,
- 31548, 31423, 38534, 22404, 25314, 38471, 27004, 23044, 25602, 31699,
- 28431, 38475, 33446, 21346, 39045, 24208, 28809, 25523, 21348, 34383,
- 40065, 40595, 30860, 38706, 36335, 36162, [12229, 40575], 28510, 31108,
- 24405, 38470, 25134, 39540, 21525, 38109, 20387, 26053, 23653, 23649,
- 32533, 34385, 27695, 24459, 29575, 28388, 32511, 23782, 25371, 23402,
- 28390, 21365, 20081, 25504, 30053, 25249, 36718, 20262, 20177, 27814,
- 32438, 35770, 33821, 34746, 32599, 36923, 38179, 31657, 39585, 35064,
- 33853, 27931, 39558, 32476, 22920, [12231, 40635], 29595, 30721, 34434,
- 39532, 39554, 22043, 21527, 22475, 20080, 40614, 21334, 36808, 33033,
- 30610, 39314, 34542, 28385, 34067, 26364, 24930, 28459, 35881, 33426,
- 33579, 30450, 27667, 24537, 33725, 29483, 33541, 38170, [12113, 27611],
- [12141, 30683], 38086, 21359, 33538, 20882, 24125, 35980, 36152, 20040,
- 29611, 26522, 26757, 37238, 38665, 29028, 27809, 30473, 23186, 38209,
- 27599, 32654, 26151, 23504, 22969, 23194, 38376, 38391, 20204, 33804,
- 33945, 27308, 30431, 38192, 29467, 26790, 23391, 30511, 37274, 38753,
- 31964, 36855, 35868, 24357, [12150, 31859], 31192, 35269, 27852, 34588,
- 23494, 24130, 26825, 30496, 32501, 20885, 20813, 21193, 23081, 32517,
- [12207, 38754], 33495, 25551, 30596, 34256, 31186, 28218, 24217, 22937,
- 34065, 28781, 27665, 25279, [12139, 30399], 25935, 24751, 38397, 26126,
- 34719, 40483, 38125, 21517, 21629, 35884, {f: 2, c: 25720}, 34321, 27169,
- 33180, 30952, 25705, 39764, 25273, 26411, 33707, 22696, 40664, 27819,
- 28448, 23518, 38476, 35851, 29279, 26576, 25287, 29281, 20137, 22982,
- 27597, 22675, 26286, 24149, 21215, 24917, [12106, 26408], [12140, 30446],
- 30566, 29287, 31302, 25343, 21738, 21584, 38048, 37027, 23068, 32435,
- 27670, 20035, 22902, 32784, 22856, 21335, 30007, 38590, 22218, 25376,
- 33041, 24700, 38393, 28118, 21602, 39297, 20869, 23273, 33021, 22958,
- 38675, 20522, 27877, 23612, 25311, 20320, 21311, 33147, 36870, 28346,
- 34091, 25288, 24180, 30910, 25781, 25467, 24565, 23064, 37247, 40479,
- 23615, 25423, 32834, 23421, 21870, 38218, 38221, 28037, 24744, 26592,
- 29406, 20957, 23425, 25319, 27870, [12124, 29275], 25197, 38062, 32445,
- 33043, 27987, 20892, 24324, 22900, 21162, 24594, [12069, 22899], 26262,
- 34384, 30111, 25386, 25062, 31983, 35834, 21734, 27431, 40485, 27572,
- 34261, 21589, 20598, 27812, 21866, 36276, 29228, 24085, 24597, 29750,
- 25293, 25490, 29260, 24472, 28227, 27966, 25856, 28504, 30424, 30928,
- 30460, 30036, 21028, 21467, 20051, 24222, 26049, 32810, 32982, 25243,
- 21638, 21032, 28846, 34957, 36305, 27873, 21624, 32986, 22521, 35060,
- 36180, 38506, 37197, 20329, 27803, 21943, 30406, 30768, 25256, 28921,
- 28558, 24429, 34028, 26842, 30844, 31735, 33192, 26379, 40527, 25447,
- 30896, 22383, 30738, 38713, 25209, 25259, 21128, 29749, 27607, 21860,
- 33086, 30130, [12138, 30382], 21305, 30174, 20731, 23617, 35692, 31687,
- 20559, [12122, 29255], 39575, 39128, 28418, 29922, 31080, 25735, 30629,
- 25340, 39057, 36139, 21697, 32856, 20050, 22378, 33529, 33805, 24179,
- 20973, 29942, 35780, 23631, 22369, 27900, 39047, 23110, 30772, 39748,
- 36843, 31893, 21078, 25169, 38138, 20166, 33670, 33889, 33769, 33970,
- 22484, 26420, 22275, 26222, 28006, 35889, 26333, 28689, 26399, 27450,
- 26646, 25114, 22971, 19971, 20932, 28422, 26578, 27791, 20854, 26827,
- 22855, 27495, 30054, 23822, 33040, 40784, 26071, 31048, 31041, 39569,
- 36215, 23682, 20062, 20225, 21551, 22865, 30732, 22120, [12115, 27668],
- 36804, 24323, 27773, 27875, 35755, 25488, 24688, 27965, 29301, 25190,
- 38030, 38085, 21315, 36801, 31614, 20191, 35878, 20094, 40660, 38065,
- 38067, 21069, 28508, 36963, 27973, 35892, 22545, 23884, [12107, 27424],
- 27465, 26538, 21595, 33108, 32652, 22681, 34103, 24378, 25250, 27207,
- 38201, 25970, 24708, 26725, 30631, 20052, 20392, 24039, 38808, 25772,
- 32728, 23789, 20431, 31373, 20999, 33540, 19988, 24623, 31363, 38054,
- 20405, 20146, 31206, 29748, 21220, 33465, 25810, 31165, 23517, 27777,
- 38738, 36731, 27682, 20542, 21375, 28165, 25806, 26228, 27696, 24773,
- 39031, 35831, 24198, 29756, 31351, 31179, 19992, 37041, 29699, 27714,
- 22234, 37195, 27845, 36235, 21306, 34502, 26354, 36527, 23624, 39537,
- 28192, 21462, 23094, 40843, 36259, 21435, 22280, 39079, 26435, 37275,
- 27849, 20840, 30154, 25331, [12125, 29356], 21048, 21149, 32570, 28820,
- 30264, 21364, 40522, 27063, 30830, 38592, 35033, 32676, 28982, 29123,
- 20873, 26579, 29924, 22756, 25880, 22199, 35753, 39286, 25200, 32469,
- 24825, 28909, 22764, 20161, [12040, 20154], 24525, 38887, 20219, 35748,
- 20995, 22922, 32427, 25172, 20173, [12103, 26085], 25102, 33592, 33993,
- 33635, 34701, 29076, 28342, 23481, 32466, 20887, 25545, 26580,
- [12161, 32905], 33593, 34837, 20754, 23418, 22914, 36785, 20083, 27741,
- [12042, 20837], 35109, 36719, 38446, 34122, 29790, 38160, 38384, 28070,
- 33509, 24369, 25746, 27922, 33832, 33134, 40131, 22622, 36187, 19977,
- 21441, 20254, 25955, 26705, 21971, 20007, 25620, 39578, 25195, 23234,
- 29791, [12170, 33394], 28073, 26862, 20711, 33678, 30722, 26432, 21049,
- 27801, 32433, 20667, 21861, 29022, 31579, 26194, 29642, 33515, 26441,
- [12077, 23665], 21024, 29053, 34923, 38378, 38485, 25797, 36193, 33203,
- 21892, 27733, 25159, 32558, 22674, 20260, 21830, 36175, 26188, 19978,
- 23578, 35059, 26786, 25422, 31245, 28903, 33421, 21242, 38902, 23569,
- 21736, 37045, 32461, 22882, 36170, 34503, [12166, 33292], 33293, 36198,
- 25668, 23556, 24913, 28041, 31038, 35774, 30775, 30003, 21627, 20280,
- [12189, 36523], 28145, 23072, 32453, 31070, 27784, 23457, 23158, 29978,
- 32958, 24910, 28183, 22768, [12131, 29983], 29989, 29298, 21319, 32499,
- 30465, 30427, 21097, 32988, 22307, 24072, 22833, 29422, 26045, 28287,
- 35799, [12075, 23608], 34417, [12055, 21313], [12143, 30707], 25342, 26102,
- 20160, [12215, 39135], 34432, 23454, 35782, 21490, [12142, 30690], 20351,
- 23630, 39542, 22987, 24335, [12144, 31034], [12064, 22763], 19990, 26623,
- 20107, 25325, 35475, 36893, 21183, 26159, 21980, 22124, 36866, 20181,
- 20365, 37322, 39280, [12114, 27663], 24066, 24643, 23460, 35270, 35797,
- 25910, [12095, 25163], [12216, 39318], 23432, 23551, 25480, 21806, 21463,
- 30246, 20861, 34092, 26530, 26803, 27530, 25234, 36755, 21460, 33298,
- 28113, 30095, 20070, 36174, 23408, 29087, 34223, 26257, 26329, 32626,
- 34560, [12233, 40653], [12239, 40736], 23646, 26415, 36848, 26641, 26463,
- 25101, 31446, 22661, 24246, 25968, 28465, 24661, 21047, 32781, 25684,
- 34928, 29993, 24069, 26643, 25332, 38684, 21452, 29245, 35841,
- [12116, 27700], 30561, 31246, 21550, 30636, 39034, 33308, 35828, 30805,
- 26388, 28865, 26031, 25749, 22070, 24605, 31169, 21496, 19997, 27515,
- 32902, 23546, 21987, 22235, 20282, 20284, 39282, 24051, 26494, 32824,
- 24578, 39042, 36865, 23435, 35772, 35829, 25628, 33368, 25822, 22013,
- 33487, 37221, 20439, 32032, 36895, 31903, 20723, 22609, 28335, 23487,
- 35785, 32899, 37240, 33948, 31639, 34429, 38539, 38543, 32485, 39635,
- 30862, 23681, 31319, 36930, 38567, 31071, 23385, 25439, 31499, 34001,
- 26797, 21766, 32553, 29712, 32034, 38145, 25152, 22604, 20182, 23427,
- 22905, 22612, 29549, 25374, 36427, 36367, 32974, 33492, 25260, 21488,
- 27888, 37214, 22826, 24577, 27760, 22349, 25674, 36138, 30251, 28393,
- 22363, 27264, 30192, 28525, 35885, 35848, 22374, 27631, 34962, 30899,
- 25506, 21497, 28845, 27748, 22616, 25642, 22530, 26848, 33179, 21776,
- 31958, 20504, 36538, 28108, 36255, 28907, 25487, 28059, 28372, 32486,
- 33796, 26691, 36867, 28120, 38518, 35752, 22871, 29305, 34276, 33150,
- 30140, 35466, 26799, 21076, 36386, 38161, 25552, 39064, 36420, 21884,
- 20307, 26367, 22159, 24789, 28053, 21059, 23625, 22825, 28155, 22635,
- [12133, 30000], 29980, 24684, 33300, 33094, 25361, 26465, 36834, 30522,
- 36339, 36148, 38081, 24086, 21381, 21548, 28867, 27712, 24311, 20572,
- 20141, 24237, 25402, 33351, 36890, 26704, 37230, 30643, 21516, 38108,
- 24420, 31461, 26742, 25413, 31570, 32479, 30171, 20599, 25237, 22836,
- 36879, 20984, 31171, 31361, 22270, 24466, 36884, 28034, 23648,
- [12063, 22303], 21520, 20820, 28237, 22242, 25512, 39059, 33151, 34581,
- 35114, 36864, 21534, 23663, 33216, 25302, 25176, 33073, 40501, 38464,
- 39534, 39548, 26925, 22949, 25299, 21822, 25366, 21703, 34521, 27964,
- 23043, [12129, 29926], 34972, 27498, 22806, 35916, 24367, 28286, 29609,
- 39037, 20024, 28919, 23436, 30871, 25405, 26202, 30358, 24779, 23451,
- 23113, 19975, 33109, 27754, 29579, 20129, 26505, [12153, 32593], 24448,
- 26106, 26395, 24536, 22916, 23041, 24013, 24494, 21361, 38886, 36829,
- 26693, 22260, 21807, 24799, 20026, 28493, 32500, 33479, 33806, 22996,
- 20255, 20266, 23614, 32428, 26410, 34074, 21619, 30031, 32963, 21890,
- 39759, 20301, 28205, 35859, 23561, 24944, 21355, 30239, 28201, 34442,
- [12098, 25991], 38395, 32441, 21563, 31283, 32010, 38382, 21985, 32705,
- 29934, 25373, 34583, 28065, 31389, 25105, 26017, 21351, 25569, 27779,
- 24043, 21596, 38056, 20044, 27745, 35820, 23627, [12102, 26080], 33436,
- 26791, 21566, 21556, [12111, 27595], 27494, 20116, 25410, 21320, 33310,
- 20237, 20398, 22366, 25098, 38654, 26212, 29289, 21247, 21153, 24735,
- 35823, 26132, 29081, 26512, 35199, 30802, 30717, 26224, 22075, 21560,
- 38177, 29306, 31232, 24687, 24076, 24713, 33181, [12067, 22805], 24796,
- 29060, 28911, 28330, 27728, 29312, 27268, 34989, 24109, 20064, 23219,
- 21916, 38115, 27927, 31995, 38553, 25103, 32454, 30606, 34430, 21283,
- 38686, 36758, 26247, 23777, 20384, 29421, 19979, 21414, 22799, 21523,
- 25472, 38184, 20808, 20185, 40092, 32420, 21688, 36132, 34900, 33335,
- 38386, 28046, 24358, 23244, 26174, 38505, 29616, 29486, 21439, 33146,
- 39301, 32673, 23466, 38519, 38480, 32447, 30456, 21410, 38262,
- [12217, 39321], 31665, 35140, 28248, 20065, 32724, 31077, 35814, 24819,
- 21709, 20139, 39033, 24055, 27233, 20687, 21521, 35937, 33831, 30813,
- 38660, 21066, 21742, 22179, 38144, 28040, 23477, 28102, 26195,
- [12073, 23567], 23389, 26657, 32918, 21880, 31505, 25928, 26964, 20123,
- 27463, 34638, 38795, 21327, 25375, 25658, 37034, 26012, 32961, 35856,
- 20889, 26800, 21368, 34809, 25032, 27844, 27899, 35874, 23633, 34218,
- 33455, 38156, 27427, [12191, 36763], 26032, 24571, [12092, 24515], 20449,
- 34885, 26143, 33125, 29481, 24826, 20852, 21009, 22411, 24418, 37026,
- [12175, 34892], 37266, 24184, 26447, 24615, 22995, 20804, 20982, 33016,
- 21256, 27769, 38596, 29066, 20241, 20462, 32670, 26429, 21957, 38152,
- 31168, 34966, 32483, 22687, 25100, 38656, 34394, 22040, 39035, 24464,
- 35768, 33988, 37207, 21465, 26093, 24207, 30044, 24676, 32110, 23167,
- 32490, 32493, 36713, 21927, 23459, 24748, 26059, [12126, 29572], 36873,
- 30307, 30505, 32474, 38772, 34203, 23398, [12147, 31348], 38634,
- [12174, 34880], 21195, 29071, 24490, 26092, 35810, 23547, 39535, 24033,
- 27529, 27739, 35757, 35759, 36874, 36805, 21387, 25276, 40486, 40493,
- 21568, 20011, 33469, [12123, 29273], 34460, 23830, 34905, 28079, 38597,
- 21713, 20122, 35766, 28937, 21693, 38409, 28895, 28153, 30416, 20005,
- 30740, 34578, 23721, 24310, [12180, 35328], 39068, 38414, 28814, 27839,
- 22852, 25513, 30524, 34893, 28436, 33395, 22576, 29141, 21388, 30746,
- 38593, 21761, 24422, 28976, 23476, 35866, 39564, 27523, 22830, 40495,
- 31207, 26472, 25196, 20335, 30113, [12154, 32650], 27915, 38451, 27687,
- 20208, 30162, 20859, 26679, 28478, 36992, 33136, 22934, 29814, 25671,
- 23591, 36965, 31377, 35875, 23002, 21676, 33280, 33647, 35201, 32768,
- 26928, 22094, 32822, 29239, 37326, 20918, 20063, 39029, 25494, 19994,
- 21494, 26355, 33099, 22812, 28082, [12032, 19968], 22777, 21307, 25558,
- 38129, 20381, 20234, [12176, 34915], 39056, 22839, 36951, 31227, 20202,
- 33008, 30097, 27778, 23452, 23016, 24413, 26885, 34433, 20506, 24050,
- [12036, 20057], 30691, 20197, 33402, 25233, 26131, [12194, 37009], 23673,
- 20159, 24441, 33222, 36920, 32900, 30123, 20134, 35028, 24847, 27589,
- 24518, 20041, 30410, 28322, 35811, 35758, 35850, 35793, 24322, 32764,
- 32716, 32462, 33589, 33643, 22240, 27575, [12211, 38899], 38452, 23035,
- 21535, 38134, 28139, 23493, 39278, 23609, 24341, 38544, 21360, 33521,
- 27185, 23156, 40560, 24212, 32552, 33721, {f: 2, c: 33828}, 33639, 34631,
- 36814, 36194, 30408, 24433, 39062, 30828, 26144, 21727, 25317, 20323,
- 33219, 30152, 24248, 38605, 36362, 34553, 21647, 27891, 28044, 27704,
- 24703, 21191, [12132, 29992], 24189, 20248, 24736, 24551, 23588, 30001,
- 37038, 38080, 29369, 27833, 28216, [12195, 37193], 26377, 21451, 21491,
- 20305, 37321, 35825, [12060, 21448], 24188, 36802, 28132, 20110, 30402,
- 27014, 34398, 24858, 33286, 20313, 20446, 36926, 40060, 24841, 28189,
- 28180, 38533, 20104, 23089, [12204, 38632], 19982, 23679, 31161, 23431,
- 35821, [12155, 32701], [12127, 29577], 22495, 33419, 37057, 21505, 36935,
- 21947, 23786, 24481, 24840, 27442, 29425, 32946, 35465, 28020, 23507,
- 35029, 39044, 35947, 39533, 40499, 28170, 20900, 20803, 22435, 34945,
- 21407, 25588, 36757, 22253, 21592, 22278, 29503, 28304, 32536, 36828,
- 33489, 24895, 24616, 38498, [12104, 26352], 32422, 36234, 36291, 38053,
- 23731, 31908, [12105, 26376], 24742, 38405, 32792, 20113, 37095, 21248,
- 38504, 20801, 36816, 34164, 37213, 26197, 38901, 23381, 21277, 30776,
- 26434, 26685, 21705, 28798, 23472, 36733, 20877, 22312, 21681, 25874,
- 26242, 36190, 36163, 33039, 33900, 36973, 31967, 20991, 34299, 26531,
- 26089, 28577, 34468, 36481, 22122, 36896, 30338, 28790, 29157, 36131,
- 25321, 21017, 27901, 36156, 24590, 22686, 24974, 26366, 36192, 25166,
- 21939, 28195, 26413, 36711, 38113, 38392, 30504, 26629, 27048, 21643,
- 20045, 28856, 35784, 25688, 25995, 23429, 31364, 20538, 23528, 30651,
- 27617, 35449, 31896, 27838, 30415, 26025, 36759, 23853, 23637, 34360,
- 26632, 21344, 25112, 31449, 28251, 32509, 27167, 31456, 24432, 28467,
- 24352, 25484, 28072, 26454, 19976, 24080, 36134, 20183, 32960, 30260,
- 38556, 25307, 26157, 25214, 27836, 36213, 29031, 32617, 20806, 32903,
- 21484, 36974, 25240, 21746, 34544, 36761, 32773, 38167, 34071, 36825,
- 27993, 29645, 26015, 30495, 29956, 30759, 33275, 36126, 38024, 20390,
- 26517, 30137, 35786, 38663, 25391, 38215, 38453, 33976, 25379, 30529,
- 24449, 29424, 20105, 24596, 25972, 25327, 27491, 25919, 24103, 30151,
- 37073, 35777, 33437, 26525, [12096, 25903], 21553, 34584, 30693, 32930,
- 33026, 27713, 20043, 32455, 32844, 30452, 26893, 27542, 25191, 20540,
- 20356, 22336, 25351, [12108, 27490], 36286, 21482, 26088, 32440, 24535,
- 25370, 25527, [12164, 33267], 33268, 32622, 24092, 23769, 21046, 26234,
- 31209, 31258, 36136, 28825, 30164, 28382, 27835, 31378, 20013, 30405,
- 24544, 38047, 34935, 32456, 31181, 32959, 37325, 20210, 20247,
- [12168, 33311], 21608, 24030, 27954, 35788, 31909, 36724, 32920, 24090,
- 21650, 30385, 23449, 26172, 39588, 29664, 26666, 34523, 26417, 29482,
- 35832, 35803, 36880, [12149, 31481], 28891, 29038, 25284, 30633, 22065,
- 20027, 33879, 26609, 21161, 34496, 36142, 38136, 31569, 20303, 27880,
- 31069, 39547, 25235, [12118, 29226], 25341, 19987, 30742, 36716, 25776,
- 36186, 31686, 26729, 24196, 35013, 22918, 25758, 22766, 29366, 26894,
- 38181, 36861, 36184, 22368, 32512, 35846, 20934, 25417, 25305, 21331,
- 26700, 29730, 33537, 37196, 21828, 30528, 28796, 27978, 20857, 21672,
- 36164, 23039, 28363, 28100, 23388, 32043, 20180, 31869, 28371,
- [12070, 23376], [12163, 33258], 28173, 23383, 39683, 26837, 36394, 23447,
- 32508, 24635, 32437, 37049, [12187, 36208], 22863, 25549, 31199,
- [12188, 36275], 21330, 26063, 31062, 35781, 38459, 32452, 38075, 32386,
- 22068, 37257, 26368, 32618, 23562, 36981, 26152, 24038, 20304, 26590,
- 20570, 20316, 22352, 24231, 20109, 19980, 20800, 19984, 24319, 21317,
- 19989, 20120, 19998, [12224, 39730], 23404, 22121, [12033, 20008], 31162,
- [12035, 20031], [12052, 21269], 20039, 22829, [12120, 29243], 21358, 27664,
- 22239, 32996, 39319, 27603, 30590, 40727, [12034, 20022], 20127, 40720,
- 20060, 20073, 20115, 33416, 23387, 21868, 22031, 20164, 21389, 21405,
- 21411, 21413, 21422, 38757, 36189, [12053, 21274], 21493, 21286, 21294,
- 21310, 36188, 21350, 21347, 20994, 21000, 21006, 21037, 21043,
- {f: 2, c: 21055}, 21068, 21086, 21089, 21084, 33967, 21117, 21122, 21121,
- 21136, 21139, [12044, 20866], 32596, 20155, 20163, 20169, 20162, 20200,
- 20193, 20203, 20190, 20251, 20211, 20258, 20324, 20213, 20261, 20263,
- 20233, 20267, 20318, 20327, 25912, 20314, 20317, 20319, 20311, 20274,
- 20285, 20342, 20340, 20369, 20361, 20355, 20367, 20350, 20347, 20394,
- 20348, 20396, 20372, 20454, 20456, 20458, 20421, 20442, 20451, 20444,
- 20433, 20447, 20472, 20521, 20556, 20467, 20524, 20495, 20526, 20525,
- 20478, 20508, 20492, 20517, 20520, 20606, 20547, 20565, 20552, 20558,
- 20588, 20603, 20645, 20647, 20649, 20666, 20694, 20742, 20717, 20716,
- 20710, 20718, 20743, 20747, 20189, 27709, 20312, 20325, 20430,
- [12245, 40864], 27718, 31860, 20846, 24061, 40649, 39320, 20865, 22804,
- [12051, 21241], 21261, 35335, 21264, 20971, 22809, 20821, [12039, 20128],
- 20822, 20147, 34926, 34980, 20149, 33044, 35026, 31104, 23348, 34819,
- 32696, [12046, 20907], 20913, 20925, 20924, 20935, [12045, 20886], 20898,
- 20901, 35744, {f: 2, c: 35750}, 35754, {f: 2, c: 35764}, 35767,
- {f: 2, c: 35778}, 35787, 35791, 35790, {f: 3, c: 35794}, 35798,
- {f: 2, c: 35800}, 35804, {f: 2, c: 35807}, 35812, {f: 2, c: 35816}, 35822,
- 35824, 35827, 35830, 35833, 35836, {f: 2, c: 35839}, 35842, 35844, 35847,
- 35852, 35855, {f: 2, c: 35857}, {f: 3, c: 35860}, 35865, 35867, 35864,
- 35869, {f: 3, c: 35871}, 35877, 35879, {f: 2, c: 35882}, {f: 2, c: 35886},
- {f: 2, c: 35890}, {f: 2, c: 35893}, [12057, 21353], 21370, 38429, 38434,
- 38433, 38449, 38442, 38461, 38460, 38466, 38473, 38484, 38495, 38503,
- 38508, 38514, 38516, 38536, 38541, 38551, 38576, 37015, 37019, 37021,
- 37017, 37036, 37025, 37044, 37043, 37046, 37050, 37048, 37040, 37071,
- 37061, 37054, 37072, 37060, 37063, 37075, 37094, 37090, 37084, 37079,
- 37083, 37099, 37103, 37118, 37124, 37154, 37150, 37155, 37169, 37167,
- 37177, 37187, 37190, 21005, 22850, 21154, {f: 2, c: 21164}, 21182, 21759,
- 21200, 21206, 21232, 21471, 29166, 30669, [12085, 24308], [12048, 20981],
- 20988, [12223, 39727], [12059, 21430], 24321, 30042, 24047, 22348, 22441,
- 22433, 22654, 22716, 22725, 22737, 22313, 22316, 22314, 22323, 22329,
- {f: 2, c: 22318}, 22364, 22331, 22338, 22377, 22405, 22379, 22406, 22396,
- 22395, 22376, 22381, 22390, 22387, 22445, 22436, 22412, 22450, 22479,
- 22439, 22452, 22419, 22432, 22485, 22488, 22490, 22489, 22482, 22456,
- 22516, 22511, 22520, 22500, 22493, 22539, 22541, 22525, 22509, 22528,
- 22558, 22553, 22596, 22560, 22629, 22636, 22657, 22665, 22682, 22656,
- 39336, 40729, 25087, 33401, 33405, 33407, 33423, 33418, 33448, 33412,
- 33422, 33425, 33431, 33433, 33451, 33464, 33470, 33456, 33480, 33482,
- 33507, 33432, 33463, 33454, {f: 2, c: 33483}, 33473, 33449, 33460, 33441,
- 33450, 33439, 33476, 33486, 33444, 33505, 33545, 33527, 33508, 33551,
- 33543, 33500, 33524, 33490, 33496, 33548, 33531, 33491, 33553, 33562,
- 33542, {f: 2, c: 33556}, 33504, 33493, 33564, 33617, {f: 2, c: 33627},
- 33544, 33682, 33596, 33588, 33585, 33691, 33630, 33583, 33615, 33607,
- 33603, 33631, 33600, 33559, 33632, 33581, 33594, 33587, 33638, 33637,
- 33640, 33563, 33641, 33644, 33642, {f: 2, c: 33645}, 33712, 33656,
- {f: 2, c: 33715}, 33696, 33706, 33683, 33692, 33669, 33660, 33718, 33705,
- 33661, 33720, 33659, 33688, 33694, 33704, 33722, 33724, 33729, 33793,
- 33765, 33752, 22535, 33816, 33803, 33757, 33789, 33750, 33820, 33848,
- 33809, 33798, 33748, 33759, 33807, 33795, {f: 2, c: 33784}, 33770, 33733,
- 33728, 33830, 33776, 33761, 33884, 33873, 33882, 33881, 33907,
- {f: 2, c: 33927}, 33914, 33929, 33912, 33852, 33862, 33897, 33910, 33932,
- 33934, 33841, 33901, 33985, 33997, 34000, 34022, 33981, 34003, 33994,
- 33983, 33978, 34016, 33953, 33977, 33972, 33943, 34021, 34019, 34060,
- 29965, 34104, 34032, 34105, 34079, 34106, 34134, 34107, 34047, 34044,
- 34137, 34120, 34152, 34148, 34142, 34170, 30626, 34115, 34162, 34171,
- 34212, 34216, 34183, 34191, 34169, 34222, 34204, 34181, 34233, 34231,
- 34224, 34259, 34241, 34268, 34303, 34343, 34309, 34345, 34326, 34364,
- [12086, 24318], 24328, 22844, 22849, 32823, 22869, 22874, 22872, 21263,
- [12074, 23586], 23589, 23596, 23604, 25164, 25194, 25247, 25275, 25290,
- 25306, 25303, 25326, 25378, 25334, 25401, 25419, 25411, 25517, 25590,
- 25457, 25466, 25486, 25524, 25453, 25516, 25482, 25449, 25518, 25532,
- 25586, 25592, 25568, 25599, 25540, 25566, 25550, 25682, 25542, 25534,
- 25669, 25665, 25611, 25627, 25632, 25612, 25638, 25633, 25694, 25732,
- 25709, 25750, 25722, {f: 2, c: 25783}, 25753, 25786, 25792, 25808, 25815,
- 25828, 25826, 25865, 25893, 25902, [12087, 24331], 24530, 29977, 24337,
- 21343, 21489, 21501, 21481, 21480, 21499, 21522, 21526, 21510, 21579,
- {f: 3, c: 21586}, 21590, 21571, 21537, 21591, 21593, 21539, 21554, 21634,
- 21652, 21623, 21617, 21604, {f: 2, c: 21658}, 21636, 21622, 21606, 21661,
- 21712, 21677, 21698, 21684, 21714, 21671, 21670, {f: 2, c: 21715}, 21618,
- 21667, 21717, 21691, 21695, 21708, {f: 2, c: 21721}, 21724,
- {f: 2, c: 21673}, 21668, 21725, 21711, 21726, 21787, 21735, 21792, 21757,
- 21780, 21747, {f: 2, c: 21794}, 21775, 21777, 21799, 21802, 21863, 21903,
- 21941, 21833, 21869, 21825, 21845, 21823, 21840, 21820, 21815, 21846,
- {f: 3, c: 21877}, 21811, 21808, 21852, 21899, 21970, 21891, 21937, 21945,
- 21896, 21889, 21919, 21886, 21974, 21905, 21883, 21983, {f: 2, c: 21949},
- 21908, 21913, 21994, 22007, 21961, 22047, 21969, {f: 2, c: 21995}, 21972,
- 21990, 21981, 21956, 21999, 21989, {f: 2, c: 22002}, {f: 2, c: 21964},
- 21992, 22005, 21988, 36756, 22046, 22024, 22028, 22017, 22052, 22051,
- 22014, 22016, 22055, 22061, 22104, 22073, 22103, 22060, 22093, 22114,
- 22105, 22108, 22092, 22100, 22150, 22116, 22129, 22123, {f: 2, c: 22139},
- 22149, 22163, 22191, 22228, [12062, 22231], 22237, 22241, 22261, 22251,
- 22265, 22271, 22276, 22282, 22281, 22300, 24079, 24089, 24084, 24081,
- 24113, {f: 2, c: 24123}, 24119, 24132, 24148, 24155, 24158, 24161, 23692,
- 23674, 23693, 23696, 23702, 23688, {f: 2, c: 23704}, 23697, 23706, 23708,
- 23733, 23714, 23741, 23724, 23723, 23729, 23715, 23745, 23735, 23748,
- 23762, 23780, 23755, 23781, {f: 2, c: 23810}, 23847, 23846, 23854, 23844,
- 23838, 23814, 23835, 23896, 23870, 23860, 23869, 23916, 23899, 23919,
- 23901, 23915, 23883, 23882, 23913, 23924, 23938, 23961, 23965, 35955,
- 23991, 24005, [12091, 24435], 24439, 24450, 24455, 24457, 24460, 24469,
- 24473, 24476, 24488, 24493, 24501, 24508, 34914, [12090, 24417], 29357,
- 29360, 29364, {f: 2, c: 29367}, 29379, 29377, 29390, 29389, 29394, 29416,
- 29423, 29417, 29426, 29428, 29431, 29441, 29427, 29443, {f: 2, c: 29434},
- 29463, 29459, 29473, 29450, 29470, 29469, 29461, 29474, 29497, 29477,
- 29484, 29496, 29489, 29520, 29517, 29527, 29536, 29548, 29551, 29566,
- [12167, 33307], 22821, 39143, 22820, [12065, 22786], 39267,
- {f: 6, c: 39271}, 39284, 39287, 39293, 39296, 39300, 39303, 39306, 39309,
- {f: 2, c: 39312}, {f: 3, c: 39315}, 24192, 24209, 24203, 24214, 24229,
- 24224, 24249, 24245, 24254, 24243, 36179, 24274, 24273, 24283, 24296,
- 24298, 33210, 24516, 24521, 24534, 24527, 24579, 24558, 24580, 24545,
- 24548, 24574, {f: 2, c: 24581}, 24554, 24557, 24568, 24601, 24629, 24614,
- 24603, 24591, 24589, 24617, 24619, 24586, 24639, 24609, {f: 2, c: 24696},
- 24699, 24698, 24642, 24682, 24701, 24726, 24730, 24749, 24733, 24707,
- 24722, 24716, 24731, 24812, 24763, 24753, 24797, 24792, 24774, 24794,
- 24756, 24864, 24870, 24853, 24867, 24820, 24832, 24846, 24875, 24906,
- 24949, 25004, 24980, 24999, 25015, 25044, 25077, 24541, 38579, 38377,
- 38379, 38385, 38387, {f: 2, c: 38389}, 38396, 38398, {f: 2, c: 38403},
- 38406, 38408, {f: 4, c: 38410}, 38415, 38418, {f: 3, c: 38421},
- {f: 2, c: 38425}, 20012, [12121, 29247], 25109, 27701, 27732, 27740, 27722,
- 27811, 27781, 27792, 27796, 27788, {f: 2, c: 27752}, 27764, 27766, 27782,
- 27817, 27856, 27860, 27821, {f: 2, c: 27895}, 27889, 27863, 27826, 27872,
- 27862, 27898, 27883, 27886, 27825, 27859, 27887, 27902, 27961, 27943,
- 27916, 27971, 27976, 27911, 27908, 27929, 27918, 27947, 27981, 27950,
- 27957, 27930, 27983, 27986, 27988, 27955, 28049, 28015, 28062, 28064,
- 27998, {f: 2, c: 28051}, 27996, 28000, 28028, 28003, 28186, 28103, 28101,
- 28126, 28174, 28095, 28128, 28177, 28134, 28125, 28121, 28182, 28075,
- 28172, 28078, 28203, 28270, 28238, 28267, 28338, 28255, 28294,
- {f: 2, c: 28243}, 28210, 28197, 28228, 28383, 28337, 28312, 28384, 28461,
- 28386, 28325, 28327, 28349, 28347, 28343, 28375, 28340, 28367, 28303,
- 28354, 28319, 28514, {f: 2, c: 28486}, 28452, 28437, 28409, 28463, 28470,
- 28491, 28532, 28458, 28425, 28457, 28553, 28557, 28556, 28536, 28530,
- 28540, 28538, 28625, 28617, 28583, 28601, 28598, 28610, 28641, 28654,
- 28638, 28640, 28655, 28698, 28707, 28699, 28729, 28725, 28751, 28766,
- [12071, 23424], 23428, 23445, 23443, 23461, 23480, 29999, 39582, 25652,
- 23524, 23534, 35120, 23536, 36423, 35591, 36790, 36819, 36821, 36837,
- 36846, 36836, 36841, 36838, 36851, 36840, 36869, 36868, 36875, 36902,
- 36881, 36877, 36886, 36897, {f: 2, c: 36917}, 36909, 36911, 36932,
- {f: 2, c: 36945}, 36944, 36968, 36952, 36962, 36955, 26297, 36980, 36989,
- 36994, 37000, 36995, 37003, [12089, 24400], 24407, 24406, 24408, 23611,
- 21675, 23632, 23641, 23409, 23651, 23654, 32700, 24362, 24361, 24365,
- 33396, 24380, 39739, [12076, 23662], 22913, 22915, 22925, {f: 2, c: 22953},
- 22947, 22935, 22986, 22955, 22942, 22948, 22994, 22962, 22959, 22999,
- 22974, {f: 2, c: 23045}, 23005, 23048, 23011, 23000, 23033, 23052, 23049,
- 23090, 23092, 23057, 23075, 23059, 23104, 23143, 23114, 23125, 23100,
- 23138, 23157, 33004, 23210, 23195, 23159, 23162, 23230, 23275, 23218,
- 23250, 23252, 23224, 23264, 23267, 23281, 23254, 23270, 23256, 23260,
- 23305, 23319, 23318, 23346, 23351, 23360, 23573, 23580, 23386, 23397,
- 23411, 23377, 23379, 23394, 39541, {f: 2, c: 39543}, 39546, 39551, 39549,
- {f: 2, c: 39552}, 39557, 39560, 39562, 39568, {f: 2, c: 39570}, 39574,
- 39576, {f: 3, c: 39579}, {f: 2, c: 39583}, {f: 2, c: 39586}, 39589, 39591,
- 32415, 32417, 32419, 32421, {f: 2, c: 32424}, 32429, 32432, 32446,
- {f: 3, c: 32448}, 32457, {f: 2, c: 32459}, 32464, 32468, 32471, 32475,
- {f: 2, c: 32480}, 32488, 32491, {f: 2, c: 32494}, {f: 2, c: 32497}, 32525,
- 32502, {f: 2, c: 32506}, 32510, {f: 3, c: 32513}, {f: 2, c: 32519},
- {f: 2, c: 32523}, 32527, {f: 2, c: 32529}, 32535, 32537, 32540, 32539,
- 32543, {f: 7, c: 32545}, {f: 4, c: 32554}, {f: 5, c: 32559}, 32565,
- [12083, 24186], 30079, [12078, 24027], 30014, 37013, 29582, 29585, 29614,
- 29602, 29599, 29647, 29634, 29649, 29623, 29619, 29632, 29641, 29640,
- 29669, 29657, 39036, 29706, 29673, 29671, 29662, 29626, 29682, 29711,
- 29738, 29787, 29734, 29733, 29736, 29744, 29742, 29740, 29723, 29722,
- 29761, 29788, 29783, 29781, 29785, 29815, 29805, 29822, 29852, 29838,
- {f: 2, c: 29824}, 29831, 29835, 29854, {f: 2, c: 29864}, 29840, 29863,
- 29906, 29882, {f: 3, c: 38890}, 26444, 26451, 26462, 26440, 26473, 26533,
- 26503, 26474, 26483, 26520, 26535, 26485, 26536, 26526, 26541, 26507,
- 26487, 26492, 26608, 26633, 26584, 26634, 26601, 26544, 26636, 26585,
- 26549, 26586, 26547, 26589, 26624, 26563, 26552, 26594, 26638, 26561,
- 26621, {f: 2, c: 26674}, {f: 2, c: 26720}, 26702, 26722, 26692, 26724,
- 26755, 26653, 26709, 26726, 26689, 26727, 26688, 26686, 26698, 26697,
- 26665, 26805, 26767, 26740, 26743, 26771, 26731, 26818, 26990, 26876,
- {f: 2, c: 26911}, 26873, 26916, 26864, 26891, 26881, 26967, 26851, 26896,
- 26993, 26937, 26976, 26946, 26973, 27012, 26987, 27008, 27032, 27000,
- 26932, 27084, {f: 2, c: 27015}, 27086, 27017, 26982, 26979, 27001, 27035,
- 27047, 27067, 27051, 27053, 27092, 27057, 27073, 27082, 27103, 27029,
- 27104, 27021, 27135, 27183, 27117, {f: 2, c: 27159}, 27237, 27122, 27204,
- 27198, 27296, 27216, 27227, 27189, 27278, 27257, 27197, 27176, 27224,
- 27260, 27281, 27280, 27305, 27287, 27307, 29495, 29522, {f: 2, c: 27521},
- 27527, 27524, {f: 2, c: 27538}, 27533, {f: 2, c: 27546}, 27553, 27562,
- 36715, 36717, {f: 3, c: 36721}, {f: 2, c: 36725}, 36728, 36727,
- {f: 2, c: 36729}, 36732, 36734, {f: 2, c: 36737}, 36740, 36743, 36747,
- {f: 3, c: 36749}, 36760, 36762, 36558, 25099, 25111, 25115, 25119, 25122,
- 25121, 25125, 25124, 25132, 33255, 29935, 29940, 29951, 29967, 29969,
- 29971, [12097, 25908], {f: 3, c: 26094}, 26122, 26137, 26482, 26115, 26133,
- 26112, 28805, 26359, 26141, 26164, 26161, 26166, 26165, 32774, 26207,
- 26196, 26177, 26191, 26198, 26209, 26199, 26231, 26244, 26252, 26279,
- 26269, 26302, {f: 2, c: 26331}, 26342, 26345, {f: 2, c: 36146}, 36150,
- 36155, 36157, 36160, {f: 2, c: 36165}, {f: 2, c: 36168}, 36167, 36173,
- 36181, 36185, 35271, {f: 3, c: 35274}, {f: 4, c: 35278}, 29294, 29343,
- 29277, 29286, 29295, {f: 2, c: 29310}, 29316, 29323, 29325, 29327, 29330,
- 25352, 25394, 25520, 25663, 25816, 32772, 27626, 27635, 27645, 27637,
- 27641, 27653, 27655, 27654, 27661, 27669, {f: 3, c: 27672}, 27681, 27689,
- 27684, 27690, 27698, 25909, 25941, 25963, 29261, 29266, 29270, 29232,
- 34402, 21014, 32927, 32924, 32915, 32956, 26378, 32957, 32945, 32939,
- 32941, 32948, 32951, {f: 4, c: 32999}, 32987, 32962, 32964, 32985, 32973,
- 32983, 26384, 32989, 33003, 33009, 33012, 33005, {f: 2, c: 33037}, 33010,
- 33020, 26389, 33042, 35930, 33078, 33054, 33068, 33048, 33074, 33096,
- 33100, 33107, 33140, {f: 2, c: 33113}, 33137, 33120, 33129,
- {f: 2, c: 33148}, 33133, 33127, 22605, 23221, 33160, 33154, 33169, 28373,
- 33187, 33194, 33228, 26406, 33226, 33211, 33217, 33190, 27428, 27447,
- 27449, 27459, 27462, 27481, {f: 3, c: 39121}, 39125, {f: 2, c: 39129},
- [12110, 27571], 24384, 27586, 35315, 26000, 40785, 26003, 26044, 26054,
- 26052, 26051, 26060, 26062, 26066, 26070, 28800, 28828, 28822, 28829,
- 28859, 28864, 28855, 28843, 28849, 28904, 28874, 28944, 28947, 28950,
- 28975, 28977, 29043, 29020, 29032, 28997, 29042, 29002, 29048, 29050,
- 29080, 29107, 29109, 29096, 29088, 29152, 29140, 29159, 29177, 29213,
- 29224, 28780, 28952, 29030, 29113, 25150, 25149, 25155, {f: 2, c: 25160},
- 31035, 31040, 31046, 31049, {f: 2, c: 31067}, 31059, 31066, 31074, 31063,
- 31072, 31087, 31079, 31098, 31109, 31114, 31130, 31143, 31155, 24529,
- 24528, 24636, 24669, 24666, 24679, 24641, 24665, 24675, 24747, 24838,
- 24845, 24925, 25001, 24989, 25035, 25041, 25094, 32896, [12160, 32895],
- 27795, 27894, 28156, 30710, 30712, 30720, 30729, {f: 2, c: 30743}, 30737,
- 26027, 30765, {f: 2, c: 30748}, {f: 3, c: 30777}, 30751, 30780, 30757,
- 30764, 30755, 30761, 30798, 30829, {f: 2, c: 30806}, 30758, 30800, 30791,
- 30796, 30826, 30875, 30867, 30874, 30855, 30876, 30881, 30883, 30898,
- 30905, 30885, 30932, 30937, 30921, 30956, 30962, 30981, 30964, 30995,
- 31012, 31006, 31028, 40859, [12235, 40697], {f: 2, c: 40699}, 30449, 30468,
- 30477, 30457, {f: 2, c: 30471}, 30490, 30498, 30489, 30509, 30502, 30517,
- 30520, {f: 2, c: 30544}, 30535, 30531, 30554, 30568, 30562, 30565, 30591,
- 30605, 30589, 30592, 30604, 30609, {f: 2, c: 30623}, 30640, 30645, 30653,
- 30010, 30016, 30030, 30027, 30024, 30043, 30066, 30073, 30083, 32600,
- 32609, 32607, 35400, 32616, 32628, 32625, 32633, 32641, 32638, 30413,
- 30437, 34866, {f: 3, c: 38021}, 38027, 38026, {f: 2, c: 38028},
- {f: 2, c: 38031}, 38036, 38039, 38037, {f: 3, c: 38042}, {f: 2, c: 38051},
- 38059, 38058, 38061, 38060, {f: 2, c: 38063}, 38066, 38068,
- {f: 5, c: 38070}, {f: 2, c: 38076}, 38079, 38084, {f: 7, c: 38088},
- {f: 3, c: 38096}, {f: 3, c: 38101}, 38105, 38104, 38107, {f: 3, c: 38110},
- 38114, {f: 2, c: 38116}, {f: 2, c: 38119}, 38122, 38121, 38123,
- {f: 2, c: 38126}, {f: 3, c: 38131}, 38135, 38137, {f: 2, c: 38140}, 38143,
- 38147, 38146, {f: 2, c: 38150}, {f: 2, c: 38153}, {f: 3, c: 38157},
- {f: 5, c: 38162}, 38168, 38171, {f: 3, c: 38173}, 38178, {f: 2, c: 38186},
- 38185, 38188, {f: 2, c: 38193}, 38196, {f: 3, c: 38198}, 38204,
- {f: 2, c: 38206}, 38210, 38197, {f: 3, c: 38212}, 38217, 38220,
- {f: 2, c: 38222}, {f: 3, c: 38226}, {f: 4, c: 38230}, 38235,
- {f: 2, c: 38238}, 38237, {f: 2, c: 38241}, {f: 9, c: 38244}, 38255,
- {f: 3, c: 38257}, 38202, 30695, 30700, 38601, 31189, 31213, 31203, 31211,
- 31238, 23879, 31235, 31234, 31262, 31252, 31289, 31287, 31313, 40655,
- 39333, 31344, 30344, 30350, 30355, 30361, 30372, 29918, 29920, 29996,
- 40480, 40482, {f: 5, c: 40488}, 40498, 40497, 40502, 40504, 40503,
- {f: 2, c: 40505}, 40510, {f: 2, c: 40513}, 40516, {f: 4, c: 40518},
- {f: 2, c: 40523}, 40526, 40529, 40533, 40535, {f: 3, c: 40538}, 40542,
- 40547, {f: 7, c: 40550}, 40561, 40557, 40563, [12135, 30098], 30100, 30102,
- 30112, 30109, 30124, 30115, {f: 2, c: 30131}, 30136, 30148, 30129, 30128,
- 30147, 30146, 30166, 30157, 30179, 30184, 30182, 30180, 30187, 30183,
- 30211, 30193, 30204, 30207, 30224, 30208, 30213, 30220, 30231, 30218,
- 30245, 30232, 30229, 30233, 30235, 30268, 30242, 30240, 30272, 30253,
- 30256, 30271, 30261, 30275, 30270, 30259, 30285, 30302, 30292, 30300,
- 30294, 30315, 30319, 32714, 31462, {f: 2, c: 31352}, 31360, 31366, 31368,
- 31381, 31398, 31392, 31404, 31400, 31405, 31411, 34916, 34921, 34930,
- 34941, 34943, 34946, 34978, 35014, 34999, 35004, 35017, 35042, 35022,
- 35043, 35045, 35057, 35098, 35068, 35048, 35070, 35056, 35105, 35097,
- 35091, 35099, 35082, 35124, 35115, 35126, 35137, 35174, 35195,
- [12134, 30091], 32997, 30386, 30388, 30684, [12158, 32786], 32788, 32790,
- 32796, 32800, 32802, {f: 3, c: 32805}, 32809, 32808, 32817, 32779, 32821,
- 32835, 32838, 32845, 32850, 32873, 32881, 35203, 39032, 39040, 39043,
- 39049, {f: 2, c: 39052}, 39055, 39060, {f: 2, c: 39066}, {f: 2, c: 39070},
- {f: 2, c: 39073}, {f: 2, c: 39077}, [12172, 34381], 34388, 34412, 34414,
- 34431, 34426, 34428, 34427, 34472, 34445, 34443, 34476, 34461, 34471,
- 34467, 34474, 34451, 34473, 34486, 34500, 34485, 34510, 34480, 34490,
- 34481, 34479, 34505, 34511, 34484, 34537, {f: 2, c: 34545}, 34541, 34547,
- 34512, 34579, 34526, 34548, 34527, 34520, 34513, 34563, 34567, 34552,
- 34568, 34570, 34573, 34569, 34595, 34619, 34590, 34597, 34606, 34586,
- 34622, 34632, 34612, 34609, 34601, 34615, 34623, 34690, 34594,
- {f: 2, c: 34685}, 34683, 34656, 34672, 34636, 34670, 34699, 34643, 34659,
- 34684, 34660, 34649, 34661, 34707, 34735, 34728, 34770, 34758, 34696,
- 34693, 34733, 34711, 34691, 34731, 34789, 34732, 34741, 34739, 34763,
- 34771, 34749, 34769, 34752, 34762, 34779, 34794, 34784, 34798, 34838,
- 34835, 34814, 34826, 34843, 34849, 34873, 34876, [12152, 32566], 32578,
- {f: 2, c: 32580}, 33296, 31482, 31485, 31496, {f: 2, c: 31491}, 31509,
- 31498, 31531, 31503, 31559, 31544, 31530, 31513, 31534, 31537, 31520,
- 31525, 31524, 31539, 31550, 31518, 31576, 31578, 31557, 31605, 31564,
- 31581, 31584, 31598, 31611, 31586, 31602, 31601, 31632, {f: 2, c: 31654},
- 31672, 31660, 31645, 31656, 31621, 31658, 31644, 31650, 31659, 31668,
- 31697, 31681, 31692, 31709, 31706, {f: 2, c: 31717}, 31722, 31756, 31742,
- 31740, 31759, 31766, 31755, 31775, 31786, 31782, 31800, 31809, 31808,
- 33278, {f: 2, c: 33281}, 33284, 33260, 34884, {f: 3, c: 33313}, 33325,
- 33327, 33320, 33323, 33336, 33339, {f: 2, c: 33331}, 33342, 33348, 33353,
- 33355, 33359, 33370, 33375, 33384, 34942, 34949, 34952, 35032, 35039,
- 35166, 32669, 32671, 32679, {f: 2, c: 32687}, 32690, 31868, 25929, 31889,
- 31901, 31900, 31902, 31906, 31922, {f: 2, c: 31932}, 31937, 31943,
- {f: 2, c: 31948}, 31944, 31941, 31959, 31976, [12169, 33390], 26280, 32703,
- 32718, 32725, 32741, 32737, 32742, 32745, 32750, 32755, [12151, 31992],
- 32119, 32166, 32174, 32327, 32411, 40632, 40628, 36211, 36228, 36244,
- 36241, 36273, 36199, 36205, 35911, 35913, 37194, 37200, {f: 2, c: 37198},
- 37220, 37218, 37217, 37232, 37225, 37231, {f: 2, c: 37245}, 37234, 37236,
- 37241, 37260, 37253, 37264, 37261, 37265, {f: 2, c: 37282}, 37290,
- {f: 3, c: 37293}, 37301, 37300, 37306, [12183, 35925], 40574, 36280, 36331,
- 36357, 36441, 36457, 36277, 36287, 36284, 36282, 36292, {f: 2, c: 36310},
- 36314, 36318, {f: 2, c: 36302}, 36315, 36294, 36332, {f: 2, c: 36343},
- 36323, 36345, 36347, 36324, 36361, 36349, 36372, 36381, 36383, 36396,
- 36398, 36387, 36399, 36410, 36416, 36409, 36405, 36413, 36401, 36425,
- {f: 2, c: 36417}, {f: 2, c: 36433}, 36426, 36464, 36470, 36476, 36463,
- 36468, 36485, 36495, 36500, 36496, 36508, 36510, [12184, 35960], 35970,
- 35978, 35973, 35992, 35988, 26011, 35286, 35294, 35290, 35292, 35301,
- 35307, 35311, 35390, 35622, 38739, 38633, 38643, 38639, 38662, 38657,
- 38664, 38671, 38670, 38698, 38701, 38704, 38718, 40832, 40835,
- {f: 6, c: 40837}, 40844, 40702, 40715, 40717, [12203, 38585],
- {f: 2, c: 38588}, 38606, 38610, 30655, 38624, 37518, 37550, 37576, 37694,
- 37738, 37834, 37775, 37950, 37995, 40063, 40066, {f: 4, c: 40069}, 31267,
- 40075, 40078, {f: 3, c: 40080}, {f: 2, c: 40084}, {f: 2, c: 40090},
- {f: 6, c: 40094}, {f: 5, c: 40101}, 40107, {f: 2, c: 40109},
- {f: 8, c: 40112}, {f: 4, c: 40122}, {f: 4, c: 40132}, {f: 7, c: 40138},
- {f: 3, c: 40147}, {f: 3, c: 40151}, {f: 2, c: 40156}, 40159, 40162, 38780,
- 38789, {f: 2, c: 38801}, 38804, 38831, 38827, 38819, 38834, 38836, 39601,
- 39600, 39607, 40536, 39606, 39610, 39612, 39617, 39616, 39621, 39618,
- {f: 2, c: 39627}, 39633, 39749, 39747, 39751, 39753, 39752, 39757, 39761,
- 39144, 39181, 39214, 39253, 39252, [12221, 39647], 39649, 39654, 39663,
- 39659, 39675, 39661, 39673, 39688, 39695, 39699, 39711, 39715,
- {f: 2, c: 40637}, 32315, 40578, {f: 2, c: 40583}, 40587, 40594, 37846,
- 40605, 40607, {f: 3, c: 40667}, 40672, 40671, 40674, 40681, 40679, 40677,
- 40682, 40687, 40738, 40748, 40751, 40761, 40759, {f: 2, c: 40765}, 40772,
- 12295, {s: 13}, 30362, 34297, 31001, 24859, 39599, 35158, 22761, 32631,
- 25850, 25943, 38930, 36774, 32070, 24171, 32129, 37770, 35607, 39165,
- 23542, 22577, 39825, 36649, [12185, 35997], 37575, 29437, 20633, 24970,
- 32179, 31558, 30050, 25987, 24163, 38281, 37002, 32232, 36022, 35722,
- 36783, 36782, 27161, 40009, 30303, 28693, 28657, 36051, 25839, 39173,
- 25765, 37474, 37457, 39361, 35036, 36001, 21443, 34870, 27544, 24922,
- 24920, 29158, 33980, 33369, 20489, 28356, 21408, 20596, 28204, 23652,
- 35435, 25881, 25723, 34796, 39262, 35730, 32399, 37855, 29987, 38369,
- 39019, 22580, 22039, [12199, 38263], 20767, 33144, 24288, 26274, 37396,
- [12190, 36554], 24505, 22645, 38515, 35183, 31281, 25074, 35488, 39425,
- 36978, 39347, [12242, 40786], 29118, 34909, 34802, 23541, 30087, 36490,
- 31820, 32162, 37276, 37604, 38619, 30990, 20786, 35320, 34389, 20659,
- 30241, 38358, 21109, 37656, 32020, 32189, 36781, 35422, 36060, 32880,
- 24478, 21474, 36517, 31428, 37679, 36948, 24118, 36024, 25812, 21934,
- 37170, 25763, 33213, 24986, 35477, 24392, 30070, 25803, 40680, 34153,
- 27284, 25623, 23798, 31153, 23566, 29128, 37159, 25973, 28364, 36958,
- 32224, 39003, 40670, 22666, 38651, 28593, 37347, 35519, 35548, 37336,
- 38914, 37664, 35330, 26481, 21205, 26847, 20941, [12222, 39717], 29346,
- 29544, 35712, 36077, 37709, 37723, 26039, 32222, 38538, 23565, 22136,
- 38931, 37389, 22890, 22702, 40285, 38989, 35355, 24801, 39187, 20818,
- 29246, 39180, 36019, 30332, 32624, 38309, 31020, 37353, 29033, 31684,
- 36009, 39151, 35370, 32033, [12214, 39131], 35513, 24290, 36027, 32027,
- 22707, 22894, 24996, 31966, 35920, 26963, 37586, [12213, 39080], 30219,
- 39342, 32299, 35575, 40179, 33178, 36667, 25771, 36628, 36070, 24489,
- 36000, 35331, 23142, 32283, 35442, 37411, 33995, 24185, 36245, 36123,
- 23713, 21083, 37628, 32177, 23831, 37804, 25841, 40255, 38307, 37499,
- 20491, 32102, 40852, 38799, 36002, 37390, 28317, 27083, 36092, 34865,
- 39015, 21102, 38364, 35264, 39208, 24931, 36011, 24291, 35215, 27512,
- [12244, 40860], 38312, 36556, 35437, 27331, 36020, 21130, 36645, 37707,
- 22283, 36942, 39405, 38867, 28450, 34399, 38305, 40372, 36032, 36703,
- 40251, 32005, 22778, 35703, 28396, 22057, 33775, 30059, 21123, 35441,
- 25079, 22750, 27489, 29872, 36996, 32233, 35594, 25582, 36637, 36036,
- 31330, 26371, 29172, 21295, 35569, 35496, 32362, 33911, 28222, 29554,
- 36008, 31117, 25802, 27231, 31309, 39249, 35663, 40388, 32318, 32221,
- 26997, 36655, 32026, 25824, 24190, 34186, 21137, 28639, 35336, 35352,
- 38555, 32380, 32000, 22846, 33698, 38960, 36040, 37440, 20729, 39381,
- 27570, 30435, 22533, 31627, 38291, 33393, 32216, 32365, 27298, 40572,
- 25536, 25791, 31777, 20745, 34214, 27323, 37970, 36368, 36068,
- [12178, 35211], 37749, 33382, 21133, 39198, 28472, 28666, 28567, 23559,
- 28479, 34083, 27123, 22892, 35611, 37292, 33184, 28550, 39509, 23308,
- 25898, 37496, 30703, 20709, 39171, 32371, 32094, 36686, 36611, 38542,
- 31680, 28500, 32080, 35489, 32202, 37670, 20677, 35641, 36914, 29180,
- 30433, 21185, 33686, 39912, 39514, 32147, 38968, 37857, 24465, 30169,
- 31478, 31998, 33290, 39378, 33289, 25818, 37624, 25084, 21127, 40273,
- 32121, 35258, 35363, 32118, 37406, 36557, 39423, 38283, 20977, 38982,
- 27579, 35506, 22718, 25031, 25715, 24235, 35122, 35463, 22602, 20744,
- 23532, 31014, 26336, 34407, 24011, 31418, 39243, 28528, 25844, 38346,
- 34847, 33240, 33802, 20358, 36084, 34253, 27396, 25876, 31811, 38348,
- 34349, 28734, 35733, 25900, 35261, 25078, 32412, 29211, 28651, 25736,
- 21214, 28551, 27138, 37939, 22744, 39006, 31852, 38626, 28757, 35023,
- 39881, 31150, 40599, 21426, 21237, 31019, 27511, 28701, 38584, 20486,
- 32879, 34030, 36899, 37934, 24976, 28451, 31806, 25986, 33225, 37832,
- 25088, 29001, 32244, 31975, 20841, 36635, 35538, 30274, 36988, 37904,
- 29557, 33256, 37168, 40023, 36035, 40801, 37428, 38728, 23994, 38936,
- 39230, 21129, [12243, 40845], 32894, 22184, 31840, 22751, 25871, 38580,
- 27155, 23105, 25695, 31757, 34310, 30439, 39025, 24300, 29200, 25796,
- 28407, 34396, 39791, 36034, 37682, 38520, 39522, 37569, 23650, 32311,
- 24942, 28670, 32209, 24018, 25891, 23423, 28772, 20098, 25476, 36650,
- 20523, 20374, 28138, 32184, 35542, 34367, 32645, 37007, 38012, 31854,
- 39486, 39409, 32097, 23229, 29802, 30908, 34718, [12218, 39340], 39393,
- 21966, 36023, [12230, 40613], 36067, 36993, 30622, 39237, 34875, 28415,
- 35646, 37672, 37466, 36031, 37762, [12200, 38272], 24758, 20497, 37683,
- 22818, 35598, 24396, 35219, 32191, 32236, 24287, 28357, 25003, 38313,
- 40180, 37528, 35628, 35584, 30045, 37385, 32013, 38627, 25747, 33126,
- 24817, 39719, 39186, 25836, 33193, 25862, 37312, [12227, 40165], 32886,
- 22169, 38007, 37811, 27320, 29552, 23527, 25840, 28632, 37397, 32016,
- 33215, 28611, 36786, 30247, 35582, 27472, 40407, 27590, 22036, 28442,
- 30436, 40848, 36064, 22132, 40300, 39449, 39108, 38971, 36007, 34315,
- 24977, 35413, 28497, 38935, 25778, 37610, 20693, 27192, 35676, 33229,
- [12241, 40778], 39438, 35912, 21843, 27683, 35350, 29309, 37370, 37467,
- 36983, 31805, 35609, 37666, 37463, 28154, 35700, 22649, 27085, 21958,
- 22715, 34196, 25654, 37740, 27211, 21932, 20689, 32761, 31429, 31434,
- 27453, 35242, 23522, 36629, 27691, 20670, 38915, 35531, 24950, 29898,
- 31406, 36264, 21312, 36544, 39493, 40818, 39028, 27402, 21240, 40306,
- 30906, 35731, 39250, 25854, 32350, 29105, 38860, 35469, 32009, 27054,
- 32104, 36575, 37613, 38287, 28516, 28753, 34217, 39955, 36093, 20632,
- 21930, 39479, 25475, 28544, 27578, 32023, 31721, 26348, 38275, 38493,
- 36109, 32341, 20663, 36062, 29138, 32057, 36050, 25448, 25885, 25086,
- 35373, 32051, 23529, 23352, 33102, 28402, 32882, 32361, 21213, 32854,
- 24107, 29509, 28629, 35433, 26178, 34645, 23526, 35672, 39387, 21218,
- 36969, 37323, 39166, 35222, 35430, 22781, 29560, 27166, 36664, 26360,
- 36118, 23660, 34899, 27193, 31466, 25976, 24101, 38617, 35504, 38918,
- 35500, 30889, 29197, 32114, 39164, 39686, 32883, 24939, 38924, 35359,
- 35494, 25851, 34311, 35380, 32901, 38614, 38568, 32143, 27506, 23403,
- 25613, 32302, 29795, 37782, 29562, 25787, 33274, 24907, 25892, 36010,
- 30321, 28760, 22727, 35674, 35527, 22022, 28271, 29145, 28644, 32295,
- 35342, 39472, 35588, 37563, 38988, 39636, 26781, 36028, 37941, 24307,
- 32893, 28916, 37509, 32113, 38957, 22294, 22615, 22296, 38973, 40213,
- 39345, 39389, 27234, 31402, 35178, 24398, 28771, 38929, 33836, 32178,
- [12209, 38859], 36949, 22285, 29234, 28656, 32173, 33894, 20553, 20702,
- 32239, 35586, 34907, 32862, 32011, 31337, 21839, 25790, 34680, 28198,
- 31401, 21978, 37794, 28879, 35491, 28961, 34154, 22626, 38695, 21209,
- 35492, 37675, 29351, 35186, 32722, 37521, 25138, 32048, 34662, 36676,
- 23805, 20448, 29433, 22151, 37697, 39854, 32406, 36066, 37532, 38289,
- 39023, 38570, 29694, 29563, 32291, 39201, 25010, 32171, 38002, 37129,
- 35443, 38911, 38917, 34157, 22210, 37559, 26313, 22063, 21332, 25406,
- 33029, 35559, 23531, 28681, 35613, 37573, 37313, 33288, 37561, 32137,
- 38920, 35377, 32210, 32396, 36562, 25080, 36984, 30316, 32098, 23416,
- 21211, 35426, 23563, 39348, 35347, 35338, 36956, 22739, 40201, 40232,
- 21854, 20126, 35357, 38329, 40573, 22196, 38996, 38331, 33399, 21421,
- 30831, 35578, 39511, 40230, 26954, 25562, 30221, 38525, 30306, 39178,
- 27171, 22575, 35617, 34277, 29242, [12212, 38913], 26989, 33865, 37291,
- 37541, 38948, 36986, 20736, 34811, 34269, 20740, 25014, 32681, 35427,
- 35696, 35516, 35695, 32377, 34093, 38512, 37504, 39154, 38577, 27387,
- 23344, 40441, 25033, 32403, 29801, 34722, 29151, 29074, 34821, 36111,
- 31310, 21938, 25793, 20653, 30320, 36404, 20778, 24962, 37109, 37438,
- 29494, 35480, 36671, 39192, [12226, 39770], 28417, 33287, 23996, 35486,
- 39729, 29508, 35709, 38928, 39341, 40219, 28149, 36677, 22290, 21729,
- 22291, 32227, 36960, 39000, 32004, 36493, 38000, 38322, 38642, 37142,
- 38549, 36939, 34292, 37270, 26248, 38620, 36617, 25890, 26283, 36106,
- 36124, 33247, 38015, 26839, 31432, 36012, 25799, 21063, 28580, 36042,
- 36104, 36555, 37720, 38296, 35408, 40779, 20661, 27656, 30430, 26028,
- 36670, 23940, 26855, 25136, 32187, 24373, 28466, 24115, 36076, 33081,
- 36249, 34756, 36685, 37754, 36889, 35998, 37341, 20597, 35386, 37806,
- 38499, 24128, 30309, 37165, 35657, 32340, 32887, 22519, 34937, 32025,
- 25711, 25842, 24159, 36074, 28399, 37912, 32066, 31278, 33131, 34886,
- 35589, 36600, 30394, 26205, 39519, 35576, 35461, 29165, 30682, 22225,
- 36015, 37956, 31689, 39376, 23560, 30938, 36681, 36090, 27137, 33674,
- 35037, 22941, 22767, 29376, 37648, 36101, 22684, 32180, 35524, 28310,
- 28609, 36039, 28460, 32156, 32317, 32305, 37138, 35419, 32068, 38013,
- 21959, 21401, 21428, 38760, 36107, 21293, 21297, 36094, 21060, 21132,
- 21108, 20660, 20480, 20630, 20757, 20738, 20756, 20796, 20791, 20712,
- 20674, 20795, 20752, 20794, 20681, 31988, 40652, 22213, 40172, 35131,
- 33248, 35329, 35344, 35340, 35349, 35635, 35406, 35365, 35393, 35382,
- 35398, 35412, 35416, 35410, 35462, 35460, 35455, 35440, 35452, 35445,
- 35436, 35438, 35533, 35554, 35425, 35482, 35493, {f: 2, c: 35473}, 35535,
- 35537, 35529, 35547, 35543, 35522, 35510, 35574, 35563, 35604, 35585,
- 35556, 35565, 35580, 35571, 35558, 35566, 35550, 35624, 35740, 35606,
- 35610, 35600, 35627, 35629, 35670, 35673, 35662, 35742, 35691, 35734,
- 38488, 37178, 37140, 37172, 37087, 37174, 37126, 37192, 33467, 21233,
- 24048, 22538, 22745, 22754, 22752, 22746, 22497, 22607, 22550, 22610,
- 22557, 22628, 34188, 34131, 34294, 33703, 33799, 34031, 33511, 34338,
- 34086, 22603, 29026, 34136, 34045, 34126, 34184, 34234, 29334, 28366,
- 34113, 34254, 34130, 33984, 33874, 33892, 33940, 33845, 34207, 34133,
- 40367, 33939, 32264, 34118, 34146, 34078, 39488, 34362, 37795, 34167,
- 34334, 34298, 34308, 34282, 34330, 22889, 23607, 25451, 25718, 25759,
- 25681, 25692, 25779, 25860, 25878, 25847, 25852, 25883, 22064, 22072,
- 22216, 22182, 21764, 21692, 22144, 22109, 22112, 22069, 22006, 22118,
- 22130, 22156, 22117, 22044, 22062, 21993, 22038, 22208, 22029, 22195,
- 22209, 22127, 36705, 22198, 22165, 22279, 24131, 24172, 24152, 24151,
- 23943, 23796, 23888, 23852, 23975, 23968, 23959, 23821, 23992, 23937,
- 24020, 24480, 29559, 29505, 29546, 29499, 29547, 29568, 29564, 39136,
- 39219, 39145, 39228, {f: 2, c: 39146}, 39149, 39156, 39177, 39185, 39195,
- 39223, 39231, 39235, {f: 3, c: 39240}, 39244, 39266, 24289, 36065, 25082,
- 25006, 24938, 24894, 24757, 24884, 25036, 24927, 25064, 24827, 24887,
- 24818, 24947, 24860, 24978, 38274, 38278, 38344, 38286, 38292, 38284,
- 38373, 38317, 38315, 39726, 38316, 38334, 38326, 39721, 38335, 38333,
- 38332, 38339, 38347, 38356, 38352, 38357, 38366, 28739, 28505, 28711,
- 28696, 28668, 28039, 28025, 28254, 28590, 28687, 28408, 28527, 28150,
- 28543, 28678, 28576, 28683, 28775, 28740, 28677, 28535, 28704, 28703,
- 28722, 28712, 28765, 39467, 36999, 36885, 37008, 23656, 24371, 23285,
- 23255, 23296, 23149, 23304, 23372, 23207, 23291, 23307, 23329, 23338,
- 23321, 39380, 39391, 39385, 39478, 39515, 39377, 39384, 39501, 39498,
- 39394, 39530, 39439, 39437, 39429, 39490, 39469, 39446, 39489, 39470,
- 39480, {f: 2, c: 39491}, 39503, 39525, 39524, 31993, 32006, 32002,
- {f: 2, c: 32007}, 32394, 32028, 32021, 32019, 32058, 32050, 32049, 32272,
- 32060, 32064, 32063, 32093, 32078, 32115, 32134, 32131, 32136, 32190,
- 32186, 32203, 32212, 32196, 32158, 32172, 32185, 32163, 32176, 32199,
- 32217, 32215, 32249, 32242, 32354, 32230, 32246, 32241, 32267, 32225,
- 32265, 32285, 32287, 32286, 32301, 32266, 32273, 32381, 32313, 32309,
- 32306, 32326, 32325, 32392, 32346, 32338, 32366, 32382, 32368, 32367,
- 32408, 29859, 29771, 29903, 38922, 29885, 29759, 29833, 29862, 29908,
- 29914, 38873, 38878, 38876, 27050, 27370, 26776, 26838, 27141, 26783,
- 27355, 27379, 27368, 27359, 27273, 26895, 27208, 26984, 27071, 27194,
- 27292, 27410, 27422, 27357, 27111, 27407, 27414, 27372, 27354, 27384,
- 27315, 27367, 27299, 27347, 27358, 27556, 27550, 27566, 27563, 27567,
- 36564, 36571, 36594, 36603, 36708, 36601, 36604, 36587, 36580, 36706,
- 36602, 36606, 36618, 36615, 36613, 36626, 36646, {f: 2, c: 36638}, 36636,
- 36659, 36678, 36692, 25108, 25127, 29964, 26311, 26308, 26249, 26326,
- 36033, 36016, 36026, 36029, 36100, 36018, 36037, 36112, 36049, 36058,
- 36053, 36075, 36071, 36091, 35224, 35244, 35233, 35263, 35238, 35247,
- 35250, 35255, 27647, 27660, 27692, 29272, 26407, 33110, 33242, 33051,
- 33214, 33121, 33231, 27487, {f: 2, c: 39086}, 39094, 39100, 39110, 39112,
- 36674, 40783, 26005, 29036, 29010, 29079, 29121, 29148, 29182, 31152,
- 31118, 31146, 25055, 24932, 25059, 25095, 28585, 30959, 30893, 30824,
- 30904, 31018, 31025, 30820, 30973, 30951, 30947, 40853, 30616, 30558,
- 30652, 32646, 32648, {f: 3, c: 37330}, 37337, 37335, 37333, 37367, 37351,
- 37348, 37702, 37365, 37369, 37384, 37414, 37445, 37393, 37392, 37377,
- 37415, 37380, 37413, 37376, 37434, 37478, 37431, 37427, 37461, 37437,
- 37432, 37470, {f: 2, c: 37484}, 37439, 37984, 37424, 37449, 37448, 37453,
- 37422, 37433, 37944, 37548, 37536, 37498, 37546, 37614, 37583, 37891,
- 37603, 37946, 37553, 37542, 37799, 37526, 37580, 37545, 37877, 37523,
- 37503, 37801, 37530, 37658, 37547, 37507, 37899, 37544, 37539, 37906,
- 37688, 37617, 37847, 37605, 37616, 37615, 37608, 37564, 37597, 37622,
- {f: 2, c: 37926}, 37571, 37599, 37606, 37650, 37638, 37737, 37659, 37696,
- 37633, 37653, 37678, 37699, {f: 2, c: 37639}, 37663, 37657, 37733, 37703,
- 37750, 37716, 37732, 37802, 37744, 37764, 37860, 37848, 37928, 37767,
- 37836, 37784, 37816, 37823, 37798, 37808, 37813, 37964, 37858,
- {f: 2, c: 37852}, 37837, 37854, 37827, 37831, 37841, 37908, 37917, 37879,
- 37989, 37907, 37997, 37920, 38009, 37881, 37913, 37962, 37938, 37951,
- 37972, 37987, 37758, 31329, 40169, 40182, 40199, 40198, 40227, 40327,
- 40469, 40221, 40223, 40421, 40239, 40409, 40240, 40258, 40478, 40275,
- 40477, 40288, 40274, 40435, 40284, 40289, 40339, 40298, 40303, 40329,
- 40344, 40346, 40384, 40357, 40361, 40386, 40380, 40474, 40403, 40410,
- 40431, 40422, 40434, 40440, 40460, 40442, 40475, 30308, 30296, 30311,
- 30210, {f: 2, c: 30278}, 30281, 30238, 30267, {f: 2, c: 30317}, 30313,
- 30322, 31431, 31414, 35168, 35123, 35165, 35143, 35128, 35172, 30392,
- 32814, 32812, 32889, 32885, 38919, {f: 2, c: 38926}, 38945, 38940, 28481,
- 38950, 38967, 38990, 38995, 39027, 39010, 39001, 39013, 39020, 39024,
- 34787, 34822, 34566, 34851, 34806, 34554, 34799, 34692, 34832, 34760,
- 34833, 34747, 34766, 32588, 31716, 31591, 31849, 31731, 31744, 31691,
- 31836, 31774, 31787, 31779, 31850, 31839, 33380, 33387, 35018, 32677,
- 31986, 31990, 31965, 32310, 40617, 36274, 37317, 37315, 40570, 36489,
- 36428, 36498, 36474, 36437, 36506, 36491, 36499, 36497, 36513, 36451,
- 36522, 36518, 35316, 35318, 38746, 38722, 38717, 38724, 40788, 40799,
- 40793, 40800, 40796, 40806, 40812, 40810, 40823, [12236, 40701], 40703,
- 40713, 35726, 38014, 37864, 39799, 39796, 39809, 39811, 39822, 40056,
- 31308, 39826, 40031, 39824, 39853, 39834, 39850, 39838, 40045, 39851,
- 39837, 40024, 39873, 40058, 39985, 39993, 39971, 39991, 39872, 39882,
- 39879, 39933, 39894, {f: 2, c: 39914}, 39905, 39908, 39911, 39901, 39906,
- 39920, 39899, 39924, 39892, 40029, 39944, 39952, 39949, 39954, 39945,
- 39935, 39968, 39986, 39981, 39976, 39973, 39977, 39987, 39998, 40008,
- 39995, 39989, 40005, 40022, 40020, 40018, 40039, 38851, 38845, 38857,
- 40379, 39631, 39638, 39637, 39768, 39758, 39255, 39260, 39714, 40695,
- 40690, 35180, 38342, 37686, 24390, 34068, 32404, 40803, 22137, 40725,
- 22081, 39662, 35079, 31296, 39091, 38308, 39693, 36852, 24409, 31339,
- 39138, 20642, 34193, 20760, 25458, 21067, 30543, 32397, 26310, 30637,
- [12228, 40565], 22217, 40692, 28635, 25054, 30663, 28720, 40629, 34890,
- 38370, 38854, 31844, 32308, 38822, 40623, 22220, 39089, 27311, 32590,
- 31984, 20418, 32363, 40569, 22190, 39706, 33903, 31142, 31858, 39634,
- 38587, 32251, 35069, 30787, {f: 10, c: 8560}, {f: 2, c: 714}, 729, 8211,
- 8213, 8229, 8245, 8453, 8457, {f: 4, c: 8598}, 8725, 8735, 8739, 8786,
- {f: 2, c: 8806}, 8895, {f: 36, c: 9552}, {f: 15, c: 9601}, {f: 3, c: 9619},
- {f: 2, c: 9660}, {f: 4, c: 9698}, 9737, 8853, 12306, {f: 2, c: 12317},
- {f: 9, c: 12321}, 12963, {f: 2, c: 13198}, {f: 3, c: 13212}, 13217, 13252,
- 13262, {f: 2, c: 13265}, 13269, 65072, 65506, 65508, 8481, 12849, 8208,
- 12540, {f: 2, c: 12443}, {f: 2, c: 12541}, 12294, {f: 2, c: 12445},
- {f: 10, c: 65097}, {f: 4, c: 65108}, {f: 14, c: 65113}, {f: 4, c: 65128},
- 12350, {f: 12, c: 12272}, 19970, {f: 3, c: 19972}, 19983, 19986, 19991,
- {f: 3, c: 19999}, 20003, 20006, 20009, {f: 2, c: 20014}, 20017, 20019,
- 20021, 20023, 20028, {f: 3, c: 20032}, 20036, 20038, 20042, 20049, 20053,
- 20055, {f: 2, c: 20058}, {f: 4, c: 20066}, {f: 2, c: 20071},
- {f: 6, c: 20074}, 20082, {f: 10, c: 20084}, {f: 3, c: 20095},
- {f: 2, c: 20099}, [12037, 20101], 20103, 20106, 20112, {f: 2, c: 20118},
- 20121, {f: 2, c: 20124}, 20131, 20138, {f: 3, c: 20143}, 20148,
- {f: 4, c: 20150}, {f: 3, c: 20156}, 20168, 20172, {f: 2, c: 20175}, 20178,
- {f: 3, c: 20186}, 20192, 20194, {f: 2, c: 20198}, 20201, {f: 3, c: 20205},
- 20209, 20212, {f: 3, c: 20216}, 20220, 20222, 20224, {f: 7, c: 20226},
- {f: 2, c: 20235}, {f: 5, c: 20242}, {f: 2, c: 20252}, 20257, 20259,
- {f: 2, c: 20264}, {f: 3, c: 20268}, 20273, 20275, 20277, 20279, 20281,
- 20283, {f: 5, c: 20286}, {f: 2, c: 20292}, {f: 6, c: 20295}, 20306, 20308,
- 20310, {f: 2, c: 20321}, 20326, 20328, {f: 2, c: 20330}, {f: 2, c: 20333},
- {f: 2, c: 20337}, 20341, {f: 4, c: 20343}, 20349, {f: 3, c: 20352}, 20357,
- 20359, 20362, 20364, 20366, 20368, {f: 2, c: 20370}, 20373,
- {f: 3, c: 20376}, 20380, {f: 2, c: 20382}, {f: 2, c: 20385}, 20388, 20395,
- 20397, {f: 5, c: 20400}, {f: 9, c: 20406}, {f: 2, c: 20416},
- {f: 4, c: 20422}, {f: 3, c: 20427}, {f: 5, c: 20434}, 20441, 20443, 20450,
- {f: 2, c: 20452}, 20455, {f: 2, c: 20459}, 20464, 20466, {f: 4, c: 20468},
- 20473, {f: 3, c: 20475}, 20479, {f: 5, c: 20481}, {f: 2, c: 20487}, 20490,
- 20494, 20496, 20499, {f: 3, c: 20501}, 20507, {f: 2, c: 20509}, 20512,
- {f: 3, c: 20514}, 20519, {f: 11, c: 20527}, 20539, 20541, {f: 4, c: 20543},
- {f: 3, c: 20548}, {f: 2, c: 20554}, 20557, {f: 5, c: 20560},
- {f: 4, c: 20566}, 20571, {f: 8, c: 20573}, {f: 6, c: 20582},
- {f: 7, c: 20589}, {f: 3, c: 20600}, {f: 2, c: 20604}, {f: 4, c: 20609},
- {f: 2, c: 20614}, {f: 4, c: 20617}, {f: 8, c: 20622}, 20631,
- {f: 8, c: 20634}, 20644, 20646, {f: 2, c: 20650}, {f: 4, c: 20654}, 20662,
- {f: 2, c: 20664}, {f: 2, c: 20668}, {f: 3, c: 20671}, {f: 2, c: 20675},
- {f: 3, c: 20678}, {f: 5, c: 20682}, 20688, {f: 3, c: 20690},
- {f: 3, c: 20695}, {f: 3, c: 20699}, {f: 6, c: 20703}, {f: 3, c: 20713},
- {f: 4, c: 20719}, 20724, {f: 3, c: 20726}, 20730, {f: 4, c: 20732}, 20737,
- 20739, 20741, 20746, {f: 4, c: 20748}, 20753, 20755, {f: 2, c: 20758},
- {f: 6, c: 20761}, 20768, {f: 8, c: 20770}, {f: 7, c: 20779},
- {f: 4, c: 20787}, {f: 2, c: 20792}, {f: 2, c: 20797}, 20802, 20807, 20810,
- 20812, {f: 3, c: 20814}, 20819, {f: 3, c: 20823}, 20827, {f: 5, c: 20829},
- {f: 2, c: 20835}, {f: 2, c: 20838}, 20842, 20847, 20850, 20858,
- {f: 2, c: 20862}, {f: 2, c: 20867}, {f: 2, c: 20870}, {f: 2, c: 20874},
- {f: 4, c: 20878}, {f: 2, c: 20883}, 20888, 20890, {f: 3, c: 20893}, 20897,
- 20899, {f: 5, c: 20902}, {f: 2, c: 20909}, 20916, {f: 3, c: 20920},
- {f: 2, c: 20926}, {f: 3, c: 20929}, 20933, 20936, 20938, 20942, 20944,
- {f: 9, c: 20946}, 20956, {f: 2, c: 20958}, {f: 2, c: 20962},
- {f: 6, c: 20965}, 20972, 20974, 20978, 20980, 20983, 20990,
- {f: 2, c: 20996}, 21001, {f: 2, c: 21003}, {f: 2, c: 21007},
- {f: 3, c: 21011}, 21020, {f: 2, c: 21022}, {f: 3, c: 21025},
- {f: 3, c: 21029}, 21034, 21036, 21039, {f: 2, c: 21041}, {f: 2, c: 21044},
- 21052, 21054, {f: 2, c: 21061}, {f: 2, c: 21064}, {f: 2, c: 21070},
- {f: 2, c: 21074}, 21077, {f: 4, c: 21079}, 21085, {f: 2, c: 21087},
- {f: 3, c: 21090}, 21094, 21096, {f: 3, c: 21099}, {f: 2, c: 21104}, 21107,
- {f: 7, c: 21110}, 21118, 21120, {f: 3, c: 21124}, 21131, {f: 2, c: 21134},
- 21138, {f: 7, c: 21140}, 21148, {f: 4, c: 21156}, {f: 3, c: 21166},
- {f: 10, c: 21172}, 21184, 21186, {f: 3, c: 21188}, 21192, 21194,
- {f: 4, c: 21196}, 21201, {f: 2, c: 21203}, 21207, 21210, 21212,
- {f: 2, c: 21216}, 21219, {f: 11, c: 21221}, {f: 3, c: 21234},
- {f: 2, c: 21238}, {f: 3, c: 21243}, {f: 4, c: 21249}, 21255,
- {f: 4, c: 21257}, 21262, {f: 4, c: 21265}, 21272, {f: 2, c: 21275},
- {f: 2, c: 21278}, 21282, {f: 2, c: 21284}, {f: 3, c: 21287},
- {f: 2, c: 21291}, 21296, {f: 6, c: 21298}, [12054, 21304],
- {f: 2, c: 21308}, 21314, 21316, 21318, {f: 3, c: 21323}, 21328,
- {f: 2, c: 21336}, 21339, 21341, 21349, 21352, 21354, {f: 2, c: 21356},
- 21362, 21366, 21369, {f: 4, c: 21371}, {f: 2, c: 21376}, 21379,
- {f: 2, c: 21383}, 21386, {f: 7, c: 21390}, {f: 2, c: 21398},
- {f: 2, c: 21403}, 21406, 21409, 21412, 21415, {f: 3, c: 21418},
- {f: 3, c: 21423}, 21427, 21429, {f: 4, c: 21431}, {f: 3, c: 21436}, 21440,
- {f: 4, c: 21444}, {f: 3, c: 21454}, {f: 2, c: 21458}, 21461, 21466,
- {f: 3, c: 21468}, 21473, 21479, 21492, 21498, {f: 3, c: 21502}, 21506,
- 21509, 21511, 21515, 21524, {f: 3, c: 21528}, 21532, 21538,
- {f: 2, c: 21540}, 21546, 21552, 21555, {f: 2, c: 21558}, 21562, 21565,
- 21567, {f: 2, c: 21569}, {f: 2, c: 21572}, 21575, 21577, {f: 4, c: 21580},
- 21585, 21594, {f: 5, c: 21597}, 21603, 21605, 21607, {f: 8, c: 21609},
- 21620, {f: 2, c: 21625}, {f: 2, c: 21630}, 21633, 21635, 21637,
- {f: 4, c: 21639}, 21645, 21649, 21651, {f: 2, c: 21655}, 21660,
- {f: 5, c: 21662}, 21669, 21678, 21680, 21682, {f: 3, c: 21685},
- {f: 2, c: 21689}, 21694, 21699, 21701, {f: 2, c: 21706}, 21718, 21720,
- 21723, 21728, {f: 3, c: 21730}, {f: 2, c: 21739}, {f: 3, c: 21743},
- {f: 6, c: 21748}, 21755, 21758, 21760, {f: 2, c: 21762}, 21765, 21768,
- {f: 5, c: 21770}, {f: 2, c: 21778}, {f: 6, c: 21781}, {f: 4, c: 21788},
- 21793, {f: 2, c: 21797}, {f: 2, c: 21800}, 21803, 21805, 21810,
- {f: 3, c: 21812}, {f: 4, c: 21816}, 21821, 21824, 21826, 21829,
- {f: 2, c: 21831}, {f: 4, c: 21835}, {f: 2, c: 21841}, 21844,
- {f: 5, c: 21847}, 21853, {f: 2, c: 21855}, {f: 2, c: 21858},
- {f: 2, c: 21864}, 21867, {f: 6, c: 21871}, {f: 2, c: 21881}, 21885, 21887,
- {f: 2, c: 21893}, {f: 3, c: 21900}, 21904, {f: 2, c: 21906},
- {f: 3, c: 21909}, {f: 2, c: 21914}, 21918, {f: 7, c: 21920},
- {f: 2, c: 21928}, 21931, 21933, {f: 2, c: 21935}, 21940, 21942, 21944,
- 21946, 21948, {f: 5, c: 21951}, 21960, {f: 2, c: 21962}, {f: 2, c: 21967},
- 21973, {f: 3, c: 21975}, 21979, 21982, 21984, 21986, 21991,
- {f: 2, c: 21997}, {f: 2, c: 22000}, 22004, {f: 5, c: 22008}, 22015,
- {f: 4, c: 22018}, 22023, {f: 2, c: 22026}, {f: 4, c: 22032}, 22037,
- {f: 2, c: 22041}, 22045, {f: 3, c: 22048}, {f: 2, c: 22053}, 22056,
- {f: 2, c: 22058}, 22067, 22071, 22074, {f: 3, c: 22076}, 22080,
- {f: 10, c: 22082}, {f: 5, c: 22095}, {f: 2, c: 22101}, {f: 2, c: 22106},
- {f: 2, c: 22110}, 22113, 22115, 22119, {f: 2, c: 22125}, 22128, 22131,
- 22133, 22135, 22138, {f: 3, c: 22141}, {f: 4, c: 22145}, {f: 4, c: 22152},
- 22157, {f: 3, c: 22160}, 22164, {f: 3, c: 22166}, {f: 9, c: 22170},
- {f: 2, c: 22180}, 22183, {f: 5, c: 22185}, {f: 3, c: 22192}, 22197,
- {f: 4, c: 22200}, {f: 3, c: 22205}, {f: 2, c: 22211}, {f: 2, c: 22214},
- 22219, {f: 4, c: 22221}, {f: 2, c: 22226}, {f: 2, c: 22229},
- {f: 2, c: 22232}, 22236, 22243, {f: 6, c: 22245}, 22252, {f: 2, c: 22254},
- {f: 2, c: 22258}, {f: 3, c: 22262}, {f: 2, c: 22267}, {f: 3, c: 22272},
- 22277, 22284, {f: 4, c: 22286}, {f: 2, c: 22292}, 22295, {f: 3, c: 22297},
- {f: 2, c: 22301}, {f: 3, c: 22304}, {f: 4, c: 22308}, 22315,
- {f: 2, c: 22321}, {f: 5, c: 22324}, {f: 2, c: 22332}, 22335, 22337,
- {f: 4, c: 22339}, {f: 2, c: 22344}, 22347, {f: 5, c: 22354},
- {f: 2, c: 22360}, {f: 2, c: 22370}, 22373, 22375, 22380, 22382,
- {f: 3, c: 22384}, {f: 2, c: 22388}, {f: 3, c: 22392}, {f: 5, c: 22397},
- {f: 4, c: 22407}, {f: 5, c: 22413}, {f: 7, c: 22420}, {f: 4, c: 22428},
- 22437, 22440, 22442, 22444, {f: 3, c: 22447}, 22451, {f: 3, c: 22453},
- {f: 9, c: 22457}, {f: 7, c: 22468}, {f: 2, c: 22476}, {f: 2, c: 22480},
- 22483, {f: 2, c: 22486}, {f: 2, c: 22491}, 22494, {f: 2, c: 22498},
- {f: 8, c: 22501}, 22510, {f: 4, c: 22512}, {f: 2, c: 22517},
- {f: 2, c: 22523}, {f: 2, c: 22526}, 22529, {f: 2, c: 22531},
- {f: 2, c: 22536}, 22540, {f: 3, c: 22542}, {f: 3, c: 22546},
- {f: 2, c: 22551}, {f: 3, c: 22554}, 22559, {f: 2, c: 22562},
- {f: 5, c: 22565}, {f: 4, c: 22571}, {f: 2, c: 22578}, {f: 14, c: 22582},
- {f: 5, c: 22597}, 22606, 22608, 22611, {f: 2, c: 22613}, {f: 5, c: 22617},
- {f: 3, c: 22623}, 22627, {f: 5, c: 22630}, {f: 8, c: 22637},
- {f: 3, c: 22646}, {f: 4, c: 22650}, 22655, 22658, 22660, {f: 3, c: 22662},
- {f: 7, c: 22667}, {f: 5, c: 22676}, 22683, 22685, {f: 8, c: 22688},
- {f: 4, c: 22698}, {f: 4, c: 22703}, {f: 7, c: 22708}, 22717,
- {f: 2, c: 22719}, {f: 3, c: 22722}, 22726, {f: 9, c: 22728}, 22738, 22740,
- {f: 2, c: 22742}, {f: 3, c: 22747}, 22753, 22755, {f: 4, c: 22757}, 22762,
- 22765, {f: 2, c: 22769}, {f: 2, c: 22772}, {f: 2, c: 22775},
- {f: 2, c: 22779}, {f: 4, c: 22782}, 22787, {f: 2, c: 22789},
- {f: 2, c: 22792}, [12066, 22794], {f: 2, c: 22795}, 22798,
- {f: 4, c: 22800}, {f: 2, c: 22807}, 22811, {f: 2, c: 22813},
- {f: 2, c: 22816}, 22819, 22822, 22824, 22828, 22832, {f: 2, c: 22834},
- {f: 2, c: 22837}, 22843, 22845, {f: 2, c: 22847}, 22851, {f: 2, c: 22853},
- 22858, {f: 2, c: 22860}, 22864, {f: 2, c: 22866}, 22873, {f: 5, c: 22875},
- 22881, {f: 2, c: 22883}, {f: 3, c: 22886}, 22891, 22893, {f: 4, c: 22895},
- 22901, 22903, {f: 3, c: 22906}, {f: 3, c: 22910}, 22917, 22921,
- {f: 2, c: 22923}, {f: 4, c: 22926}, {f: 2, c: 22932}, 22936,
- {f: 3, c: 22938}, {f: 4, c: 22943}, {f: 2, c: 22950}, {f: 2, c: 22956},
- {f: 2, c: 22960}, {f: 6, c: 22963}, 22970, {f: 2, c: 22972},
- {f: 7, c: 22975}, {f: 3, c: 22983}, {f: 4, c: 22988}, {f: 2, c: 22997},
- 23001, 23003, {f: 5, c: 23006}, 23012, {f: 2, c: 23014}, {f: 3, c: 23017},
- {f: 12, c: 23021}, 23034, {f: 3, c: 23036}, 23040, 23042, {f: 2, c: 23050},
- {f: 4, c: 23053}, 23058, {f: 4, c: 23060}, {f: 3, c: 23065},
- {f: 2, c: 23069}, {f: 2, c: 23073}, 23076, {f: 3, c: 23078},
- {f: 7, c: 23082}, 23091, 23093, {f: 5, c: 23095}, {f: 3, c: 23101},
- {f: 4, c: 23106}, {f: 2, c: 23111}, {f: 10, c: 23115}, {f: 4, c: 23126},
- {f: 7, c: 23131}, {f: 3, c: 23139}, {f: 2, c: 23144}, {f: 2, c: 23147},
- {f: 6, c: 23150}, {f: 2, c: 23160}, {f: 4, c: 23163}, {f: 18, c: 23168},
- {f: 7, c: 23187}, {f: 11, c: 23196}, {f: 2, c: 23208}, {f: 7, c: 23211},
- 23220, {f: 2, c: 23222}, {f: 4, c: 23225}, {f: 2, c: 23231},
- {f: 6, c: 23235}, {f: 2, c: 23242}, {f: 5, c: 23245}, 23251, 23253,
- {f: 3, c: 23257}, {f: 3, c: 23261}, 23266, {f: 2, c: 23268},
- {f: 2, c: 23271}, 23274, {f: 5, c: 23276}, {f: 3, c: 23282},
- {f: 5, c: 23286}, {f: 4, c: 23292}, {f: 7, c: 23297}, 23306,
- {f: 9, c: 23309}, 23320, {f: 7, c: 23322}, {f: 8, c: 23330},
- {f: 5, c: 23339}, 23345, 23347, {f: 2, c: 23349}, {f: 7, c: 23353},
- {f: 11, c: 23361}, {f: 3, c: 23373}, 23378, 23382, 23390, {f: 2, c: 23392},
- {f: 2, c: 23399}, {f: 3, c: 23405}, 23410, 23412, {f: 2, c: 23414}, 23417,
- {f: 2, c: 23419}, 23422, 23426, 23430, 23434, {f: 2, c: 23437},
- {f: 3, c: 23440}, 23444, 23446, 23455, {f: 3, c: 23463}, {f: 4, c: 23468},
- {f: 2, c: 23473}, 23479, {f: 3, c: 23482}, {f: 2, c: 23488}, 23491,
- {f: 4, c: 23496}, {f: 3, c: 23501}, 23505, {f: 9, c: 23508}, 23520, 23523,
- 23530, 23533, 23535, {f: 4, c: 23537}, 23543, {f: 2, c: 23549}, 23552,
- {f: 2, c: 23554}, 23557, 23564, 23568, {f: 2, c: 23570}, 23575, 23577,
- 23579, {f: 4, c: 23582}, 23587, 23590, {f: 4, c: 23592}, {f: 4, c: 23597},
- {f: 2, c: 23602}, {f: 2, c: 23605}, {f: 2, c: 23619}, {f: 2, c: 23622},
- {f: 2, c: 23628}, {f: 3, c: 23634}, {f: 3, c: 23638}, {f: 4, c: 23642},
- 23647, 23655, {f: 3, c: 23657}, 23661, 23664, {f: 7, c: 23666},
- {f: 4, c: 23675}, 23680, {f: 5, c: 23683}, {f: 3, c: 23689},
- {f: 2, c: 23694}, {f: 2, c: 23698}, 23701, {f: 4, c: 23709},
- {f: 5, c: 23716}, 23722, {f: 3, c: 23726}, 23730, 23732, 23734,
- {f: 4, c: 23737}, 23742, 23744, {f: 2, c: 23746}, {f: 6, c: 23749},
- {f: 6, c: 23756}, {f: 6, c: 23763}, {f: 7, c: 23770}, {f: 2, c: 23778},
- 23783, 23785, {f: 2, c: 23787}, {f: 2, c: 23790}, {f: 3, c: 23793}, 23797,
- {f: 4, c: 23799}, 23804, {f: 4, c: 23806}, {f: 2, c: 23812},
- {f: 5, c: 23816}, {f: 5, c: 23823}, 23829, {f: 3, c: 23832},
- {f: 2, c: 23836}, {f: 5, c: 23839}, 23845, 23848, {f: 2, c: 23850},
- {f: 5, c: 23855}, {f: 8, c: 23861}, {f: 8, c: 23871}, {f: 2, c: 23880},
- {f: 3, c: 23885}, {f: 7, c: 23889}, {f: 2, c: 23897}, 23900,
- {f: 11, c: 23902}, 23914, {f: 2, c: 23917}, {f: 4, c: 23920},
- {f: 12, c: 23925}, 23939, {f: 2, c: 23941}, {f: 15, c: 23944}, 23960,
- {f: 3, c: 23962}, {f: 2, c: 23966}, {f: 6, c: 23969}, {f: 15, c: 23976},
- 23993, 23995, {f: 8, c: 23997}, {f: 5, c: 24006}, 24012, {f: 4, c: 24014},
- 24019, {f: 6, c: 24021}, 24028, {f: 2, c: 24031}, {f: 2, c: 24035}, 24042,
- {f: 2, c: 24044}, {f: 2, c: 24053}, {f: 5, c: 24056}, {f: 2, c: 24063},
- 24068, 24071, {f: 3, c: 24073}, {f: 2, c: 24077}, {f: 2, c: 24082}, 24087,
- {f: 7, c: 24094}, {f: 3, c: 24104}, 24108, {f: 2, c: 24111}, 24114,
- {f: 2, c: 24116}, {f: 2, c: 24121}, {f: 2, c: 24126}, 24129,
- {f: 6, c: 24134}, {f: 7, c: 24141}, 24150, {f: 2, c: 24153},
- {f: 2, c: 24156}, 24160, {f: 7, c: 24164}, {f: 5, c: 24173}, 24181, 24183,
- {f: 3, c: 24193}, 24197, {f: 2, c: 24200}, {f: 3, c: 24204}, 24210, 24216,
- 24219, 24221, {f: 4, c: 24225}, {f: 3, c: 24232}, 24236, {f: 5, c: 24238},
- 24244, {f: 4, c: 24250}, {f: 10, c: 24255}, {f: 6, c: 24267},
- {f: 2, c: 24276}, {f: 4, c: 24279}, {f: 3, c: 24284}, {f: 4, c: 24292},
- 24297, 24299, {f: 6, c: 24301}, 24309, {f: 2, c: 24312}, {f: 3, c: 24315},
- {f: 3, c: 24325}, 24329, {f: 3, c: 24332}, 24336, 24338, 24340, 24342,
- {f: 2, c: 24345}, {f: 3, c: 24348}, {f: 4, c: 24353}, 24360,
- {f: 2, c: 24363}, 24366, 24368, 24370, 24372, {f: 3, c: 24374}, 24379,
- {f: 3, c: 24381}, {f: 5, c: 24385}, 24391, {f: 3, c: 24393}, 24397, 24399,
- 24401, 24404, {f: 3, c: 24410}, {f: 3, c: 24414}, 24419, 24421,
- {f: 2, c: 24423}, 24427, {f: 2, c: 24430}, 24434, {f: 3, c: 24436}, 24440,
- 24442, {f: 3, c: 24445}, 24451, 24454, {f: 3, c: 24461}, {f: 2, c: 24467},
- 24470, {f: 2, c: 24474}, 24477, 24479, {f: 6, c: 24482}, {f: 2, c: 24491},
- {f: 6, c: 24495}, 24502, 24504, {f: 2, c: 24506}, {f: 5, c: 24510},
- {f: 2, c: 24519}, {f: 2, c: 24522}, 24526, {f: 3, c: 24531},
- {f: 3, c: 24538}, {f: 2, c: 24542}, {f: 2, c: 24546}, {f: 2, c: 24549},
- {f: 2, c: 24552}, 24556, {f: 2, c: 24559}, {f: 3, c: 24562},
- {f: 2, c: 24566}, {f: 2, c: 24569}, 24572, {f: 3, c: 24583},
- {f: 2, c: 24587}, {f: 2, c: 24592}, 24595, {f: 2, c: 24599}, 24602,
- {f: 2, c: 24606}, {f: 3, c: 24610}, {f: 3, c: 24620}, {f: 5, c: 24624},
- {f: 5, c: 24630}, {f: 2, c: 24637}, 24640, {f: 7, c: 24644}, 24652,
- {f: 2, c: 24654}, 24657, {f: 2, c: 24659}, {f: 3, c: 24662},
- {f: 2, c: 24667}, {f: 4, c: 24670}, {f: 2, c: 24677}, 24686,
- {f: 2, c: 24689}, {f: 2, c: 24692}, 24695, 24702, {f: 3, c: 24704},
- {f: 4, c: 24709}, {f: 2, c: 24714}, {f: 4, c: 24718}, 24723, 24725,
- {f: 3, c: 24727}, 24732, 24734, {f: 2, c: 24737}, {f: 2, c: 24740}, 24743,
- {f: 2, c: 24745}, 24750, 24752, 24755, 24759, {f: 2, c: 24761},
- {f: 8, c: 24765}, {f: 3, c: 24775}, {f: 5, c: 24780}, {f: 3, c: 24786},
- {f: 2, c: 24790}, 24793, 24795, 24798, {f: 4, c: 24802}, 24810, 24821,
- {f: 2, c: 24823}, {f: 4, c: 24828}, {f: 4, c: 24834}, 24839,
- {f: 3, c: 24842}, {f: 5, c: 24848}, {f: 4, c: 24854}, {f: 2, c: 24861},
- {f: 2, c: 24865}, 24869, {f: 3, c: 24872}, {f: 8, c: 24876},
- {f: 2, c: 24885}, {f: 6, c: 24888}, {f: 8, c: 24896}, 24905, 24909,
- {f: 2, c: 24911}, {f: 3, c: 24914}, {f: 2, c: 24918}, 24921,
- {f: 2, c: 24923}, 24926, {f: 2, c: 24928}, {f: 2, c: 24933}, 24937,
- {f: 2, c: 24940}, 24943, {f: 2, c: 24945}, 24948, {f: 10, c: 24952},
- {f: 7, c: 24963}, {f: 2, c: 24972}, 24975, 24979, {f: 5, c: 24981},
- {f: 2, c: 24987}, {f: 6, c: 24990}, {f: 2, c: 24997}, 25002, 25005,
- {f: 3, c: 25007}, {f: 3, c: 25011}, {f: 6, c: 25016}, {f: 3, c: 25023},
- {f: 4, c: 25027}, {f: 4, c: 25037}, 25043, {f: 9, c: 25045},
- {f: 3, c: 25056}, {f: 2, c: 25060}, 25063, {f: 9, c: 25065},
- {f: 2, c: 25075}, 25081, 25083, 25085, {f: 5, c: 25089}, 25097, 25107,
- 25113, {f: 3, c: 25116}, 25120, 25123, 25126, {f: 2, c: 25128}, 25131,
- 25133, 25135, 25137, 25141, [12094, 25142], {f: 5, c: 25144}, 25154,
- {f: 3, c: 25156}, 25162, {f: 2, c: 25167}, {f: 3, c: 25173},
- {f: 2, c: 25177}, {f: 7, c: 25180}, {f: 2, c: 25188}, 25192,
- {f: 2, c: 25201}, {f: 2, c: 25204}, {f: 2, c: 25207}, {f: 2, c: 25210},
- 25213, {f: 3, c: 25217}, {f: 4, c: 25221}, {f: 6, c: 25227}, 25236, 25241,
- {f: 3, c: 25244}, 25251, {f: 2, c: 25254}, {f: 2, c: 25257},
- {f: 4, c: 25261}, {f: 3, c: 25266}, {f: 3, c: 25270}, 25274, 25278,
- {f: 2, c: 25280}, 25283, 25291, 25295, 25297, 25301, {f: 2, c: 25309},
- {f: 2, c: 25312}, 25316, {f: 2, c: 25322}, 25328, 25330, 25333,
- {f: 4, c: 25336}, 25344, {f: 4, c: 25347}, {f: 4, c: 25354},
- {f: 2, c: 25359}, {f: 4, c: 25362}, {f: 3, c: 25367}, 25372,
- {f: 2, c: 25382}, 25385, {f: 3, c: 25388}, {f: 2, c: 25392},
- {f: 6, c: 25395}, {f: 2, c: 25403}, {f: 3, c: 25407}, 25412,
- {f: 2, c: 25415}, 25418, {f: 4, c: 25425}, {f: 8, c: 25430}, 25440,
- {f: 3, c: 25444}, 25450, 25452, {f: 2, c: 25455}, {f: 3, c: 25459},
- {f: 2, c: 25464}, {f: 4, c: 25468}, 25473, {f: 2, c: 25477}, 25483, 25485,
- 25489, {f: 3, c: 25491}, 25495, {f: 7, c: 25497}, 25505, 25508, 25510,
- 25515, 25519, {f: 2, c: 25521}, {f: 2, c: 25525}, 25529, 25531, 25533,
- 25535, {f: 3, c: 25537}, 25541, {f: 2, c: 25543}, {f: 3, c: 25546}, 25553,
- {f: 3, c: 25555}, {f: 3, c: 25559}, {f: 3, c: 25563}, 25567, 25570,
- {f: 5, c: 25572}, {f: 2, c: 25579}, {f: 3, c: 25583}, 25587, 25589, 25591,
- {f: 4, c: 25593}, 25598, {f: 2, c: 25603}, {f: 5, c: 25606}, 25614,
- {f: 2, c: 25617}, {f: 2, c: 25621}, {f: 3, c: 25624}, 25629, 25631,
- {f: 4, c: 25634}, {f: 3, c: 25639}, 25643, {f: 6, c: 25646}, 25653,
- {f: 3, c: 25655}, {f: 2, c: 25659}, 25662, 25664, {f: 2, c: 25666}, 25673,
- {f: 6, c: 25675}, 25683, {f: 3, c: 25685}, {f: 3, c: 25689}, 25693,
- {f: 7, c: 25696}, 25704, {f: 3, c: 25706}, 25710, {f: 3, c: 25712},
- {f: 2, c: 25716}, 25719, {f: 6, c: 25724}, 25731, 25734, {f: 8, c: 25737},
- 25748, {f: 2, c: 25751}, {f: 4, c: 25754}, {f: 3, c: 25760},
- {f: 3, c: 25766}, 25770, 25775, 25777, 25780, 25782, 25785, 25789, 25795,
- 25798, {f: 2, c: 25800}, 25804, 25807, 25809, 25811, {f: 2, c: 25813},
- 25817, {f: 3, c: 25819}, 25823, 25825, 25827, 25829, {f: 5, c: 25831},
- {f: 2, c: 25837}, 25843, {f: 2, c: 25845}, {f: 2, c: 25848}, 25853, 25855,
- {f: 3, c: 25857}, 25861, {f: 2, c: 25863}, {f: 5, c: 25866},
- {f: 2, c: 25872}, 25875, 25877, 25879, 25882, 25884, {f: 4, c: 25886},
- {f: 4, c: 25894}, 25901, {f: 4, c: 25904}, 25911, 25914, {f: 2, c: 25916},
- {f: 5, c: 25920}, {f: 2, c: 25926}, {f: 2, c: 25930}, {f: 2, c: 25933},
- 25936, {f: 3, c: 25938}, 25944, 25946, 25948, {f: 3, c: 25951},
- {f: 2, c: 25956}, {f: 4, c: 25959}, {f: 3, c: 25965}, 25969, 25971, 25974,
- {f: 9, c: 25977}, {f: 3, c: 25988}, {f: 3, c: 25992}, {f: 3, c: 25997},
- 26002, 26004, 26006, 26008, 26010, {f: 2, c: 26013}, 26016,
- {f: 2, c: 26018}, 26022, 26024, 26026, 26030, {f: 6, c: 26033}, 26040,
- {f: 2, c: 26042}, {f: 3, c: 26046}, 26050, {f: 4, c: 26055}, 26061,
- {f: 2, c: 26064}, {f: 3, c: 26067}, {f: 8, c: 26072}, 26081,
- {f: 2, c: 26083}, {f: 2, c: 26090}, {f: 4, c: 26098}, {f: 2, c: 26104},
- {f: 5, c: 26107}, 26113, {f: 2, c: 26116}, {f: 3, c: 26119}, 26123, 26125,
- {f: 3, c: 26128}, {f: 3, c: 26134}, {f: 3, c: 26138}, 26142,
- {f: 4, c: 26145}, 26150, {f: 4, c: 26153}, 26158, 26160, {f: 2, c: 26162},
- {f: 5, c: 26167}, 26173, {f: 2, c: 26175}, {f: 7, c: 26180},
- {f: 2, c: 26189}, {f: 2, c: 26192}, {f: 2, c: 26200}, {f: 2, c: 26203},
- 26206, 26208, {f: 2, c: 26210}, 26213, 26215, {f: 5, c: 26217},
- {f: 3, c: 26225}, 26229, {f: 2, c: 26232}, {f: 3, c: 26235},
- {f: 3, c: 26239}, 26243, {f: 2, c: 26245}, {f: 2, c: 26250},
- {f: 4, c: 26253}, {f: 4, c: 26258}, {f: 5, c: 26264}, {f: 4, c: 26270},
- {f: 4, c: 26275}, {f: 2, c: 26281}, {f: 2, c: 26284}, {f: 5, c: 26287},
- {f: 4, c: 26293}, {f: 4, c: 26298}, {f: 5, c: 26303}, 26309, 26312,
- {f: 12, c: 26314}, {f: 2, c: 26327}, 26330, {f: 2, c: 26334},
- {f: 5, c: 26337}, {f: 2, c: 26343}, {f: 2, c: 26346}, {f: 3, c: 26349},
- 26353, {f: 2, c: 26357}, {f: 2, c: 26362}, 26365, {f: 2, c: 26369},
- {f: 4, c: 26372}, 26380, {f: 2, c: 26382}, {f: 3, c: 26385}, 26390,
- {f: 3, c: 26392}, 26396, 26398, {f: 6, c: 26400}, 26409, 26414, 26416,
- {f: 2, c: 26418}, {f: 4, c: 26422}, {f: 2, c: 26427}, {f: 2, c: 26430},
- 26433, {f: 2, c: 26436}, 26439, {f: 2, c: 26442}, 26445, 26450,
- {f: 2, c: 26452}, {f: 5, c: 26455}, 26461, {f: 3, c: 26466},
- {f: 2, c: 26470}, {f: 2, c: 26475}, 26478, 26484, 26486, {f: 4, c: 26488},
- 26493, 26496, {f: 2, c: 26498}, {f: 2, c: 26501}, 26504, 26506,
- {f: 4, c: 26508}, {f: 4, c: 26513}, 26518, 26521, 26523, {f: 3, c: 26527},
- 26532, 26534, 26537, 26540, 26542, {f: 2, c: 26545}, 26548,
- {f: 8, c: 26553}, 26562, {f: 10, c: 26565}, {f: 3, c: 26581}, 26587, 26591,
- 26593, {f: 2, c: 26595}, {f: 3, c: 26598}, {f: 2, c: 26602},
- {f: 2, c: 26605}, 26610, {f: 8, c: 26613}, 26622, {f: 4, c: 26625}, 26630,
- 26637, 26640, 26642, {f: 2, c: 26644}, {f: 5, c: 26648}, {f: 3, c: 26654},
- {f: 7, c: 26658}, {f: 7, c: 26667}, {f: 3, c: 26676}, {f: 2, c: 26682},
- 26687, 26695, 26699, 26701, 26703, 26706, {f: 10, c: 26710}, 26730,
- {f: 8, c: 26732}, 26741, {f: 9, c: 26744}, 26754, 26756, {f: 8, c: 26759},
- {f: 3, c: 26768}, {f: 3, c: 26772}, {f: 4, c: 26777}, 26782,
- {f: 2, c: 26784}, {f: 3, c: 26787}, {f: 4, c: 26793}, 26798,
- {f: 2, c: 26801}, 26804, {f: 10, c: 26806}, 26817, {f: 6, c: 26819}, 26826,
- 26828, {f: 4, c: 26830}, {f: 2, c: 26835}, 26841, {f: 4, c: 26843},
- {f: 2, c: 26849}, {f: 3, c: 26852}, {f: 6, c: 26856}, 26863,
- {f: 3, c: 26866}, {f: 3, c: 26870}, 26875, {f: 4, c: 26877},
- {f: 3, c: 26882}, {f: 5, c: 26886}, 26892, 26897, {f: 12, c: 26899},
- {f: 3, c: 26913}, {f: 8, c: 26917}, {f: 2, c: 26926}, {f: 3, c: 26929},
- {f: 4, c: 26933}, {f: 3, c: 26938}, 26942, {f: 2, c: 26944},
- {f: 7, c: 26947}, {f: 8, c: 26955}, {f: 2, c: 26965}, {f: 2, c: 26968},
- {f: 2, c: 26971}, 26975, {f: 2, c: 26977}, {f: 2, c: 26980}, 26983,
- {f: 2, c: 26985}, 26988, {f: 2, c: 26991}, {f: 3, c: 26994}, 26998,
- {f: 2, c: 27002}, {f: 3, c: 27005}, 27009, 27011, 27013, {f: 3, c: 27018},
- {f: 6, c: 27022}, {f: 2, c: 27030}, {f: 2, c: 27033}, {f: 10, c: 27037},
- 27049, 27052, {f: 2, c: 27055}, {f: 2, c: 27058}, {f: 2, c: 27061},
- {f: 3, c: 27064}, {f: 3, c: 27068}, 27072, {f: 8, c: 27074}, 27087,
- {f: 3, c: 27089}, {f: 6, c: 27093}, {f: 3, c: 27100}, {f: 6, c: 27105},
- {f: 5, c: 27112}, {f: 4, c: 27118}, {f: 9, c: 27124}, 27134, 27136,
- {f: 2, c: 27139}, {f: 4, c: 27142}, {f: 8, c: 27147}, {f: 3, c: 27156},
- {f: 4, c: 27162}, 27168, 27170, {f: 4, c: 27172}, 27177, {f: 4, c: 27179},
- 27184, {f: 3, c: 27186}, {f: 2, c: 27190}, {f: 2, c: 27195},
- {f: 5, c: 27199}, {f: 2, c: 27205}, {f: 2, c: 27209}, {f: 4, c: 27212},
- {f: 7, c: 27217}, 27226, {f: 3, c: 27228}, 27232, {f: 2, c: 27235},
- {f: 11, c: 27238}, {f: 7, c: 27250}, {f: 2, c: 27258}, {f: 3, c: 27261},
- {f: 3, c: 27265}, {f: 4, c: 27269}, {f: 4, c: 27274}, 27279,
- {f: 2, c: 27282}, {f: 2, c: 27285}, {f: 4, c: 27288}, {f: 3, c: 27293},
- 27297, {f: 5, c: 27300}, 27306, {f: 2, c: 27309}, {f: 3, c: 27312},
- {f: 4, c: 27316}, {f: 2, c: 27321}, {f: 7, c: 27324}, {f: 15, c: 27332},
- {f: 6, c: 27348}, 27356, {f: 7, c: 27360}, 27369, 27371, {f: 6, c: 27373},
- {f: 4, c: 27380}, {f: 2, c: 27385}, {f: 8, c: 27388}, {f: 5, c: 27397},
- {f: 4, c: 27403}, {f: 2, c: 27408}, {f: 3, c: 27411}, {f: 7, c: 27415},
- 27423, {f: 2, c: 27429}, {f: 10, c: 27432}, {f: 4, c: 27443}, 27448,
- {f: 2, c: 27451}, {f: 4, c: 27455}, {f: 2, c: 27460}, 27464,
- {f: 2, c: 27466}, {f: 3, c: 27469}, {f: 8, c: 27473}, {f: 5, c: 27482},
- 27488, {f: 2, c: 27496}, {f: 7, c: 27499}, {f: 4, c: 27507}, 27514,
- {f: 4, c: 27517}, 27525, 27528, 27532, {f: 4, c: 27534}, {f: 2, c: 27540},
- 27543, 27545, {f: 2, c: 27548}, {f: 2, c: 27551}, {f: 2, c: 27554},
- {f: 5, c: 27557}, {f: 2, c: 27564}, {f: 2, c: 27568}, 27574,
- {f: 2, c: 27576}, {f: 3, c: 27580}, 27584, {f: 2, c: 27587},
- {f: 4, c: 27591}, 27596, 27598, {f: 2, c: 27600}, 27608, 27610,
- {f: 5, c: 27612}, {f: 8, c: 27618}, {f: 3, c: 27628}, {f: 3, c: 27632},
- 27636, {f: 3, c: 27638}, {f: 3, c: 27642}, 27646, {f: 5, c: 27648},
- {f: 3, c: 27657}, 27662, 27666, 27671, {f: 3, c: 27676}, 27680, 27685,
- 27693, 27697, 27699, {f: 2, c: 27702}, {f: 4, c: 27705}, {f: 2, c: 27710},
- {f: 3, c: 27715}, 27720, {f: 5, c: 27723}, {f: 3, c: 27729}, 27734,
- {f: 3, c: 27736}, {f: 2, c: 27746}, {f: 3, c: 27749}, {f: 5, c: 27755},
- 27761, 27763, 27765, {f: 2, c: 27767}, {f: 3, c: 27770}, {f: 2, c: 27775},
- 27780, 27783, {f: 2, c: 27786}, {f: 2, c: 27789}, {f: 2, c: 27793},
- {f: 4, c: 27797}, 27802, {f: 3, c: 27804}, 27808, 27810, 27816, 27820,
- {f: 2, c: 27823}, {f: 4, c: 27828}, 27834, {f: 4, c: 27840},
- {f: 3, c: 27846}, 27851, {f: 3, c: 27853}, {f: 2, c: 27857},
- {f: 3, c: 27864}, {f: 2, c: 27868}, 27871, 27876, {f: 2, c: 27878}, 27881,
- {f: 2, c: 27884}, 27890, 27892, 27897, {f: 2, c: 27903}, {f: 2, c: 27906},
- {f: 2, c: 27909}, {f: 3, c: 27912}, 27917, {f: 3, c: 27919},
- {f: 4, c: 27923}, 27928, {f: 2, c: 27932}, {f: 6, c: 27935}, 27942,
- {f: 2, c: 27944}, {f: 2, c: 27948}, {f: 2, c: 27951}, 27956,
- {f: 3, c: 27958}, 27962, {f: 2, c: 27967}, 27970, 27972, 27977, 27980,
- 27984, {f: 4, c: 27989}, 27995, 27997, 27999, {f: 2, c: 28001},
- {f: 2, c: 28004}, {f: 2, c: 28007}, {f: 3, c: 28011}, {f: 4, c: 28016},
- {f: 2, c: 28021}, {f: 2, c: 28026}, {f: 5, c: 28029}, {f: 2, c: 28035},
- 28038, {f: 2, c: 28042}, 28045, {f: 2, c: 28047}, 28050, {f: 5, c: 28054},
- 28060, 28066, 28069, {f: 2, c: 28076}, {f: 2, c: 28080}, {f: 2, c: 28083},
- {f: 2, c: 28086}, {f: 6, c: 28089}, {f: 3, c: 28097}, {f: 3, c: 28104},
- {f: 4, c: 28109}, {f: 4, c: 28114}, 28119, {f: 3, c: 28122}, 28127,
- {f: 2, c: 28130}, 28133, {f: 3, c: 28135}, 28141, {f: 2, c: 28143}, 28146,
- 28148, 28152, {f: 8, c: 28157}, {f: 4, c: 28166}, 28171, 28175,
- {f: 2, c: 28178}, 28181, {f: 2, c: 28184}, {f: 2, c: 28187},
- {f: 2, c: 28190}, 28194, {f: 2, c: 28199}, 28202, 28206, {f: 2, c: 28208},
- 28211, {f: 3, c: 28213}, 28217, {f: 3, c: 28219}, {f: 4, c: 28223},
- {f: 8, c: 28229}, {f: 4, c: 28239}, 28245, 28247, {f: 2, c: 28249},
- {f: 2, c: 28252}, {f: 11, c: 28256}, {f: 2, c: 28268}, {f: 14, c: 28272},
- {f: 3, c: 28288}, 28292, {f: 2, c: 28295}, {f: 5, c: 28298},
- {f: 5, c: 28305}, 28311, {f: 3, c: 28313}, 28318, {f: 2, c: 28320},
- {f: 2, c: 28323}, 28326, {f: 2, c: 28328}, {f: 4, c: 28331}, 28336, 28339,
- 28341, {f: 2, c: 28344}, 28348, {f: 3, c: 28350}, 28355, 28358,
- {f: 3, c: 28360}, 28365, 28368, 28370, 28374, {f: 2, c: 28376},
- {f: 3, c: 28379}, 28387, 28391, {f: 2, c: 28394}, {f: 2, c: 28397},
- {f: 2, c: 28400}, 28403, {f: 2, c: 28405}, {f: 5, c: 28410}, 28416,
- {f: 3, c: 28419}, {f: 2, c: 28423}, {f: 5, c: 28426}, {f: 3, c: 28432},
- {f: 4, c: 28438}, {f: 5, c: 28443}, 28449, {f: 4, c: 28453}, 28462, 28464,
- {f: 2, c: 28468}, 28471, {f: 5, c: 28473}, 28480, {f: 4, c: 28482},
- {f: 3, c: 28488}, 28492, {f: 3, c: 28494}, {f: 2, c: 28498},
- {f: 3, c: 28501}, {f: 2, c: 28506}, 28509, {f: 3, c: 28511}, 28515, 28517,
- {f: 6, c: 28519}, 28529, 28531, {f: 2, c: 28533}, 28537, 28539,
- {f: 2, c: 28541}, {f: 3, c: 28545}, 28549, {f: 2, c: 28554},
- {f: 8, c: 28559}, {f: 4, c: 28568}, {f: 3, c: 28573}, {f: 2, c: 28578},
- {f: 2, c: 28581}, 28584, {f: 4, c: 28586}, {f: 2, c: 28591}, 28594,
- {f: 2, c: 28596}, {f: 2, c: 28599}, {f: 6, c: 28602}, {f: 5, c: 28612},
- {f: 7, c: 28618}, {f: 2, c: 28627}, {f: 2, c: 28630}, {f: 2, c: 28633},
- {f: 2, c: 28636}, {f: 2, c: 28642}, {f: 6, c: 28645}, {f: 2, c: 28652},
- {f: 8, c: 28658}, 28667, 28669, {f: 6, c: 28671}, {f: 2, c: 28679}, 28682,
- {f: 3, c: 28684}, 28688, {f: 3, c: 28690}, {f: 2, c: 28694}, 28697, 28700,
- 28702, {f: 2, c: 28705}, {f: 3, c: 28708}, {f: 7, c: 28713}, 28721,
- {f: 2, c: 28723}, {f: 3, c: 28726}, {f: 4, c: 28730}, {f: 4, c: 28735},
- {f: 7, c: 28741}, {f: 2, c: 28749}, 28752, {f: 3, c: 28754},
- {f: 2, c: 28758}, {f: 4, c: 28761}, {f: 4, c: 28767}, {f: 2, c: 28773},
- {f: 3, c: 28776}, 28782, {f: 4, c: 28785}, 28791, {f: 3, c: 28793}, 28797,
- {f: 4, c: 28801}, {f: 3, c: 28806}, {f: 3, c: 28811}, {f: 3, c: 28815},
- 28819, {f: 2, c: 28823}, {f: 2, c: 28826}, {f: 13, c: 28830}, 28848, 28850,
- {f: 3, c: 28852}, 28858, {f: 2, c: 28862}, {f: 4, c: 28868}, 28873,
- {f: 4, c: 28875}, {f: 8, c: 28880}, 28890, {f: 3, c: 28892},
- {f: 4, c: 28896}, 28901, 28906, 28910, {f: 4, c: 28912}, {f: 2, c: 28917},
- 28920, {f: 3, c: 28922}, {f: 11, c: 28926}, {f: 5, c: 28939},
- {f: 2, c: 28945}, 28948, 28951, {f: 6, c: 28955}, {f: 4, c: 28962},
- {f: 8, c: 28967}, {f: 4, c: 28978}, {f: 14, c: 28983}, {f: 3, c: 28998},
- 29003, 29005, {f: 3, c: 29007}, {f: 9, c: 29011}, 29021, {f: 3, c: 29023},
- 29027, 29029, {f: 2, c: 29034}, 29037, {f: 3, c: 29039}, {f: 4, c: 29044},
- 29049, {f: 2, c: 29051}, {f: 6, c: 29054}, {f: 5, c: 29061},
- {f: 4, c: 29067}, {f: 2, c: 29072}, 29075, {f: 2, c: 29077},
- {f: 5, c: 29082}, {f: 7, c: 29089}, {f: 3, c: 29097}, {f: 4, c: 29101},
- 29106, 29108, {f: 3, c: 29110}, {f: 4, c: 29114}, {f: 2, c: 29119}, 29122,
- {f: 4, c: 29124}, {f: 5, c: 29129}, {f: 3, c: 29135}, 29139,
- {f: 3, c: 29142}, {f: 2, c: 29146}, {f: 2, c: 29149}, {f: 4, c: 29153},
- {f: 5, c: 29160}, {f: 5, c: 29167}, {f: 4, c: 29173}, {f: 2, c: 29178},
- 29181, {f: 7, c: 29183}, {f: 6, c: 29191}, {f: 2, c: 29198},
- {f: 10, c: 29201}, 29212, {f: 10, c: 29214}, 29225, 29227,
- {f: 3, c: 29229}, {f: 2, c: 29235}, 29244, {f: 7, c: 29248},
- {f: 3, c: 29257}, {f: 4, c: 29262}, {f: 3, c: 29267}, 29271, 29274, 29276,
- 29278, 29280, {f: 3, c: 29283}, 29288, {f: 4, c: 29290}, {f: 2, c: 29296},
- {f: 2, c: 29299}, {f: 3, c: 29302}, {f: 2, c: 29307}, {f: 2, c: 29314},
- {f: 5, c: 29317}, 29324, 29326, {f: 2, c: 29328}, {f: 3, c: 29331},
- {f: 8, c: 29335}, {f: 2, c: 29344}, {f: 4, c: 29347}, {f: 4, c: 29352},
- 29358, {f: 3, c: 29361}, 29365, {f: 6, c: 29370}, {f: 3, c: 29381},
- {f: 4, c: 29385}, 29391, 29393, {f: 4, c: 29395}, 29400, {f: 4, c: 29402},
- 29407, {f: 6, c: 29410}, {f: 2, c: 29418}, {f: 2, c: 29429},
- {f: 3, c: 29438}, 29442, {f: 6, c: 29444}, {f: 3, c: 29451},
- {f: 4, c: 29455}, 29460, {f: 3, c: 29464}, {f: 2, c: 29471},
- {f: 2, c: 29475}, {f: 3, c: 29478}, 29485, {f: 2, c: 29487},
- {f: 2, c: 29490}, 29493, 29498, {f: 2, c: 29500}, 29504, {f: 2, c: 29506},
- {f: 7, c: 29510}, {f: 2, c: 29518}, 29521, {f: 4, c: 29523},
- {f: 8, c: 29528}, {f: 7, c: 29537}, 29545, 29550, 29553, {f: 2, c: 29555},
- 29558, 29561, 29565, 29567, {f: 3, c: 29569}, {f: 2, c: 29573}, 29576,
- 29578, {f: 2, c: 29580}, {f: 2, c: 29583}, {f: 4, c: 29586},
- {f: 4, c: 29591}, {f: 3, c: 29596}, {f: 2, c: 29600}, {f: 6, c: 29603},
- 29610, {f: 2, c: 29612}, 29617, {f: 3, c: 29620}, {f: 2, c: 29624},
- {f: 4, c: 29628}, 29633, {f: 5, c: 29635}, {f: 2, c: 29643}, 29646,
- {f: 7, c: 29650}, {f: 4, c: 29658}, 29663, {f: 4, c: 29665}, 29670, 29672,
- {f: 3, c: 29674}, {f: 4, c: 29678}, {f: 11, c: 29683}, {f: 4, c: 29695},
- 29700, {f: 2, c: 29703}, {f: 4, c: 29707}, {f: 9, c: 29713},
- {f: 6, c: 29724}, {f: 2, c: 29731}, 29735, 29737, 29739, 29741, 29743,
- {f: 2, c: 29745}, {f: 5, c: 29751}, {f: 2, c: 29757}, 29760,
- {f: 9, c: 29762}, {f: 9, c: 29772}, 29782, 29784, 29789, {f: 3, c: 29792},
- {f: 5, c: 29796}, {f: 2, c: 29803}, {f: 2, c: 29806}, {f: 5, c: 29809},
- {f: 6, c: 29816}, 29823, 29826, {f: 3, c: 29828}, 29832, 29834,
- {f: 2, c: 29836}, 29839, {f: 11, c: 29841}, 29853, {f: 4, c: 29855},
- {f: 2, c: 29860}, {f: 6, c: 29866}, {f: 9, c: 29873}, {f: 2, c: 29883},
- {f: 12, c: 29886}, {f: 4, c: 29899}, {f: 2, c: 29904}, 29907,
- {f: 5, c: 29909}, 29915, 29917, 29919, 29921, 29925, {f: 7, c: 29927},
- {f: 4, c: 29936}, 29941, {f: 7, c: 29944}, {f: 4, c: 29952},
- {f: 7, c: 29957}, 29966, 29968, 29970, {f: 4, c: 29972}, 29979,
- {f: 2, c: 29981}, {f: 3, c: 29984}, 29988, {f: 2, c: 29990}, 29994, 29998,
- 30004, 30006, 30009, {f: 2, c: 30012}, 30015, {f: 4, c: 30017},
- {f: 2, c: 30022}, {f: 2, c: 30025}, 30029, {f: 4, c: 30032},
- {f: 4, c: 30037}, {f: 4, c: 30046}, {f: 2, c: 30051}, {f: 3, c: 30055},
- {f: 6, c: 30060}, 30067, 30069, 30071, {f: 5, c: 30074}, {f: 3, c: 30080},
- {f: 2, c: 30084}, {f: 3, c: 30088}, {f: 3, c: 30092}, 30096, 30099, 30101,
- 30104, {f: 2, c: 30107}, 30110, 30114, {f: 5, c: 30118}, 30125,
- {f: 2, c: 30134}, {f: 2, c: 30138}, {f: 3, c: 30143}, 30150,
- {f: 2, c: 30155}, {f: 4, c: 30158}, 30163, 30167, 30170, {f: 2, c: 30172},
- {f: 3, c: 30175}, 30181, 30185, {f: 4, c: 30188}, {f: 2, c: 30194},
- {f: 4, c: 30197}, {f: 2, c: 30202}, {f: 2, c: 30205}, 30212,
- {f: 4, c: 30214}, {f: 2, c: 30222}, {f: 4, c: 30225}, 30230, 30234,
- {f: 2, c: 30236}, 30243, 30248, 30252, {f: 2, c: 30254}, {f: 2, c: 30257},
- {f: 2, c: 30262}, {f: 2, c: 30265}, 30269, 30273, {f: 2, c: 30276}, 30280,
- {f: 2, c: 30282}, {f: 6, c: 30286}, 30293, 30295, {f: 3, c: 30297}, 30301,
- {f: 2, c: 30304}, 30310, 30312, 30314, {f: 3, c: 30323}, [12136, 30326],
- 30327, {f: 2, c: 30329}, {f: 3, c: 30335}, 30339, 30341, {f: 2, c: 30345},
- {f: 2, c: 30348}, {f: 2, c: 30351}, 30354, {f: 2, c: 30356},
- {f: 2, c: 30359}, {f: 9, c: 30363}, {f: 9, c: 30373}, {f: 2, c: 30383},
- 30387, {f: 3, c: 30389}, 30393, {f: 4, c: 30395}, {f: 2, c: 30400},
- {f: 2, c: 30403}, 30407, 30409, {f: 2, c: 30411}, 30419, 30421,
- {f: 2, c: 30425}, {f: 2, c: 30428}, 30432, 30434, 30438, {f: 6, c: 30440},
- 30448, 30451, {f: 3, c: 30453}, {f: 2, c: 30458}, 30461, {f: 2, c: 30463},
- {f: 2, c: 30466}, {f: 2, c: 30469}, 30474, 30476, {f: 11, c: 30478},
- {f: 4, c: 30491}, 30497, {f: 3, c: 30499}, 30503, {f: 3, c: 30506}, 30510,
- {f: 5, c: 30512}, 30521, 30523, {f: 3, c: 30525}, 30530, {f: 3, c: 30532},
- {f: 7, c: 30536}, {f: 8, c: 30546}, {f: 2, c: 30556}, {f: 2, c: 30559},
- 30564, 30567, {f: 2, c: 30569}, {f: 12, c: 30573}, {f: 3, c: 30586},
- {f: 3, c: 30593}, {f: 6, c: 30598}, {f: 2, c: 30607}, {f: 5, c: 30611},
- {f: 5, c: 30617}, 30625, {f: 2, c: 30627}, 30630, 30632, 30635,
- {f: 2, c: 30638}, {f: 2, c: 30641}, 30644, {f: 5, c: 30646}, 30654,
- {f: 7, c: 30656}, {f: 5, c: 30664}, {f: 9, c: 30670}, {f: 2, c: 30680},
- {f: 5, c: 30685}, 30692, 30694, 30696, 30698, {f: 3, c: 30704},
- {f: 2, c: 30708}, 30711, {f: 4, c: 30713}, {f: 6, c: 30723},
- {f: 2, c: 30730}, {f: 3, c: 30734}, 30739, 30741, 30745, 30747, 30750,
- {f: 3, c: 30752}, 30756, 30760, {f: 2, c: 30762}, {f: 2, c: 30766},
- {f: 3, c: 30769}, {f: 2, c: 30773}, 30781, 30783, {f: 2, c: 30785}, 30788,
- 30790, {f: 4, c: 30792}, 30797, 30799, 30801, {f: 2, c: 30803},
- {f: 5, c: 30808}, {f: 6, c: 30814}, {f: 3, c: 30821}, 30825,
- {f: 7, c: 30832}, {f: 4, c: 30840}, {f: 10, c: 30845}, 30856,
- {f: 2, c: 30858}, {f: 2, c: 30863}, 30866, {f: 3, c: 30868}, 30873,
- {f: 2, c: 30877}, 30880, 30882, 30884, 30886, 30888, {f: 3, c: 30890},
- {f: 2, c: 30894}, {f: 3, c: 30901}, 30907, 30909, {f: 2, c: 30911},
- {f: 3, c: 30914}, {f: 3, c: 30918}, {f: 4, c: 30924}, {f: 3, c: 30929},
- {f: 3, c: 30934}, {f: 8, c: 30939}, {f: 3, c: 30948}, {f: 3, c: 30953},
- {f: 2, c: 30957}, {f: 2, c: 30960}, 30963, {f: 2, c: 30965},
- {f: 2, c: 30968}, {f: 2, c: 30971}, {f: 3, c: 30974}, {f: 3, c: 30978},
- {f: 8, c: 30982}, {f: 4, c: 30991}, {f: 5, c: 30996}, {f: 4, c: 31002},
- {f: 5, c: 31007}, 31013, {f: 3, c: 31015}, {f: 4, c: 31021},
- {f: 2, c: 31026}, {f: 5, c: 31029}, 31037, 31039, {f: 4, c: 31042}, 31047,
- {f: 9, c: 31050}, {f: 2, c: 31060}, {f: 2, c: 31064}, 31073,
- {f: 2, c: 31075}, 31078, {f: 4, c: 31081}, 31086, {f: 7, c: 31088}, 31097,
- {f: 5, c: 31099}, {f: 2, c: 31106}, {f: 4, c: 31110}, {f: 2, c: 31115},
- {f: 10, c: 31120}, {f: 11, c: 31131}, {f: 2, c: 31144}, {f: 3, c: 31147},
- 31151, 31154, {f: 4, c: 31156}, [12145, 31160], 31164, 31167, 31170,
- {f: 2, c: 31172}, {f: 2, c: 31175}, 31178, 31180, {f: 3, c: 31182},
- {f: 2, c: 31187}, {f: 2, c: 31190}, {f: 6, c: 31193}, {f: 3, c: 31200},
- 31205, 31208, 31210, 31212, 31214, {f: 7, c: 31217}, {f: 2, c: 31225},
- 31228, {f: 2, c: 31230}, 31233, {f: 2, c: 31236}, {f: 4, c: 31239}, 31244,
- {f: 5, c: 31247}, {f: 2, c: 31253}, {f: 2, c: 31256}, {f: 3, c: 31259},
- 31263, {f: 2, c: 31265}, {f: 10, c: 31268}, {f: 2, c: 31279}, 31282,
- {f: 3, c: 31284}, 31288, 31290, 31294, {f: 5, c: 31297}, {f: 5, c: 31303},
- {f: 2, c: 31311}, {f: 5, c: 31314}, {f: 9, c: 31320}, {f: 6, c: 31331},
- 31338, {f: 4, c: 31340}, {f: 3, c: 31345}, 31349, {f: 4, c: 31355}, 31362,
- 31365, 31367, {f: 4, c: 31369}, {f: 3, c: 31374}, {f: 2, c: 31379},
- {f: 3, c: 31385}, 31390, {f: 4, c: 31393}, 31399, 31403, {f: 4, c: 31407},
- {f: 2, c: 31412}, {f: 3, c: 31415}, {f: 4, c: 31419}, {f: 4, c: 31424},
- 31430, 31433, {f: 10, c: 31436}, {f: 2, c: 31447}, {f: 4, c: 31450},
- {f: 2, c: 31457}, 31460, {f: 3, c: 31463}, {f: 2, c: 31467}, 31470,
- {f: 6, c: 31472}, {f: 2, c: 31479}, {f: 2, c: 31483}, 31486,
- {f: 3, c: 31488}, 31493, 31495, 31497, {f: 3, c: 31500}, 31504,
- {f: 2, c: 31506}, {f: 3, c: 31510}, 31514, {f: 2, c: 31516}, 31519,
- {f: 3, c: 31521}, 31527, 31529, 31533, {f: 2, c: 31535}, 31538,
- {f: 4, c: 31540}, 31545, 31547, 31549, {f: 6, c: 31551}, 31560, 31562,
- {f: 2, c: 31565}, 31571, 31573, 31575, 31577, 31580, {f: 2, c: 31582},
- 31585, {f: 4, c: 31587}, {f: 6, c: 31592}, {f: 2, c: 31599},
- {f: 2, c: 31603}, 31606, 31608, 31610, {f: 2, c: 31612}, 31615,
- {f: 4, c: 31617}, {f: 5, c: 31622}, 31628, {f: 2, c: 31630},
- {f: 3, c: 31633}, 31638, {f: 4, c: 31640}, {f: 3, c: 31646},
- {f: 3, c: 31651}, {f: 3, c: 31662}, {f: 2, c: 31666}, {f: 3, c: 31669},
- {f: 7, c: 31673}, {f: 2, c: 31682}, 31685, 31688, 31690, {f: 4, c: 31693},
- 31698, {f: 5, c: 31700}, {f: 2, c: 31707}, {f: 3, c: 31710},
- {f: 2, c: 31714}, {f: 2, c: 31719}, {f: 3, c: 31723}, {f: 2, c: 31727},
- 31730, {f: 3, c: 31732}, {f: 4, c: 31736}, 31741, 31743, {f: 6, c: 31745},
- {f: 3, c: 31752}, 31758, {f: 6, c: 31760}, {f: 7, c: 31767}, 31776, 31778,
- {f: 2, c: 31780}, {f: 2, c: 31784}, {f: 12, c: 31788}, {f: 4, c: 31801},
- 31810, {f: 8, c: 31812}, {f: 14, c: 31822}, {f: 2, c: 31837},
- {f: 3, c: 31841}, {f: 4, c: 31845}, 31851, 31853, {f: 3, c: 31855},
- {f: 6, c: 31861}, {f: 11, c: 31870}, {f: 7, c: 31882}, {f: 2, c: 31891},
- 31894, {f: 3, c: 31897}, {f: 2, c: 31904}, 31907, {f: 4, c: 31910},
- {f: 3, c: 31915}, {f: 2, c: 31919}, {f: 5, c: 31924}, {f: 2, c: 31930},
- {f: 2, c: 31935}, {f: 3, c: 31938}, 31942, 31945, 31947, {f: 7, c: 31950},
- 31960, {f: 2, c: 31962}, {f: 6, c: 31969}, {f: 6, c: 31977}, 31985, 31987,
- 31989, 31991, 31994, {f: 2, c: 31996}, 31999, 32001, 32003, 32012,
- {f: 2, c: 32014}, {f: 2, c: 32017}, 32022, 32024, {f: 3, c: 32029},
- {f: 4, c: 32035}, {f: 3, c: 32040}, {f: 3, c: 32044}, {f: 5, c: 32052},
- 32059, {f: 2, c: 32061}, 32065, 32067, 32069, {f: 7, c: 32071}, 32079,
- {f: 12, c: 32081}, {f: 2, c: 32095}, {f: 3, c: 32099}, 32103,
- {f: 5, c: 32105}, {f: 2, c: 32111}, {f: 2, c: 32116}, 32120,
- {f: 7, c: 32122}, 32130, {f: 2, c: 32132}, 32135, {f: 5, c: 32138},
- {f: 3, c: 32144}, {f: 8, c: 32148}, 32157, {f: 3, c: 32159},
- {f: 2, c: 32164}, {f: 4, c: 32167}, 32175, {f: 3, c: 32181}, 32188,
- {f: 4, c: 32192}, {f: 2, c: 32197}, {f: 2, c: 32200}, {f: 5, c: 32204},
- 32211, {f: 2, c: 32213}, {f: 3, c: 32218}, 32223, 32226, {f: 2, c: 32228},
- 32231, {f: 2, c: 32234}, {f: 2, c: 32237}, 32240, 32243, 32245,
- {f: 2, c: 32247}, 32250, {f: 12, c: 32252}, {f: 4, c: 32268},
- {f: 9, c: 32274}, 32284, {f: 3, c: 32288}, {f: 3, c: 32292},
- {f: 3, c: 32296}, 32300, {f: 2, c: 32303}, 32307, 32312, 32314, 32316,
- {f: 2, c: 32319}, {f: 3, c: 32322}, {f: 10, c: 32328}, 32339,
- {f: 4, c: 32342}, {f: 3, c: 32347}, {f: 3, c: 32351}, {f: 6, c: 32355},
- 32364, {f: 2, c: 32369}, {f: 5, c: 32372}, {f: 2, c: 32378},
- {f: 3, c: 32383}, {f: 5, c: 32387}, 32393, 32395, 32398, {f: 3, c: 32400},
- 32405, 32407, {f: 2, c: 32409}, {f: 2, c: 32413}, 32430, 32436,
- {f: 2, c: 32443}, 32470, 32484, 32492, 32505, 32522, 32528, 32542, 32567,
- 32569, {f: 7, c: 32571}, 32579, {f: 6, c: 32582}, 32589, 32591,
- {f: 2, c: 32594}, 32598, 32601, {f: 4, c: 32603}, 32608, {f: 5, c: 32611},
- {f: 3, c: 32619}, 32623, 32627, {f: 2, c: 32629}, 32632, {f: 4, c: 32634},
- {f: 2, c: 32639}, {f: 3, c: 32642}, 32647, 32649, 32651, 32653,
- {f: 5, c: 32655}, {f: 5, c: 32661}, {f: 2, c: 32667}, 32672,
- {f: 2, c: 32674}, 32678, 32680, {f: 5, c: 32682}, 32689, {f: 5, c: 32691},
- {f: 2, c: 32698}, 32702, 32704, {f: 3, c: 32706}, {f: 4, c: 32710}, 32715,
- 32717, {f: 3, c: 32719}, 32723, {f: 2, c: 32726}, {f: 6, c: 32729},
- {f: 3, c: 32738}, {f: 2, c: 32743}, {f: 4, c: 32746}, 32751, 32754,
- {f: 5, c: 32756}, 32762, {f: 3, c: 32765}, 32770, {f: 4, c: 32775},
- {f: 2, c: 32782}, 32785, 32787, {f: 2, c: 32794}, {f: 3, c: 32797}, 32801,
- {f: 2, c: 32803}, 32811, 32813, {f: 2, c: 32815}, 32818, 32820,
- {f: 2, c: 32825}, 32828, 32830, {f: 2, c: 32832}, {f: 2, c: 32836},
- {f: 3, c: 32839}, {f: 4, c: 32846}, 32851, 32853, 32855, 32857,
- {f: 3, c: 32859}, {f: 10, c: 32863}, {f: 4, c: 32875}, 32884, 32888,
- {f: 3, c: 32890}, {f: 2, c: 32897}, 32904, 32906, {f: 6, c: 32909},
- {f: 2, c: 32916}, 32919, 32921, 32926, 32931, {f: 3, c: 32934}, 32940,
- 32944, 32947, {f: 2, c: 32949}, {f: 2, c: 32952}, 32955, 32965,
- {f: 5, c: 32967}, {f: 7, c: 32975}, 32984, {f: 2, c: 32991},
- {f: 2, c: 32994}, 32998, 33006, 33013, 33015, 33017, 33019,
- {f: 4, c: 33022}, {f: 2, c: 33027}, {f: 2, c: 33031}, {f: 2, c: 33035},
- 33045, 33047, 33049, {f: 2, c: 33052}, {f: 13, c: 33055}, {f: 2, c: 33069},
- 33072, {f: 3, c: 33075}, 33079, {f: 4, c: 33082}, {f: 7, c: 33087}, 33095,
- 33097, 33101, 33103, 33106, {f: 2, c: 33111}, {f: 5, c: 33115},
- {f: 3, c: 33122}, 33128, 33130, 33132, 33135, {f: 2, c: 33138},
- {f: 3, c: 33141}, 33153, {f: 5, c: 33155}, 33161, {f: 4, c: 33163}, 33168,
- {f: 6, c: 33170}, 33177, {f: 2, c: 33182}, {f: 2, c: 33185},
- {f: 2, c: 33188}, 33191, {f: 8, c: 33195}, {f: 6, c: 33204}, 33212,
- {f: 2, c: 33220}, {f: 2, c: 33223}, 33227, 33230, {f: 8, c: 33232}, 33241,
- {f: 4, c: 33243}, {f: 2, c: 33249}, {f: 3, c: 33252}, 33257, 33259,
- {f: 5, c: 33262}, {f: 5, c: 33269}, 33277, 33279, 33283, 33291,
- {f: 2, c: 33294}, 33297, 33299, {f: 6, c: 33301}, 33309, 33312,
- {f: 4, c: 33316}, 33321, 33326, 33330, 33338, {f: 2, c: 33340},
- {f: 5, c: 33343}, {f: 2, c: 33349}, 33352, 33354, {f: 3, c: 33356},
- {f: 8, c: 33360}, {f: 4, c: 33371}, {f: 4, c: 33376}, 33381, 33383,
- {f: 2, c: 33385}, {f: 2, c: 33388}, {f: 2, c: 33397}, [12171, 33400],
- {f: 2, c: 33403}, {f: 2, c: 33408}, 33411, {f: 3, c: 33413}, 33417, 33420,
- 33424, {f: 4, c: 33427}, {f: 2, c: 33434}, 33438, 33440, {f: 2, c: 33442},
- 33447, 33458, {f: 2, c: 33461}, 33466, 33468, {f: 2, c: 33471},
- {f: 2, c: 33474}, {f: 2, c: 33477}, 33481, 33488, 33494, {f: 2, c: 33497},
- 33501, 33506, {f: 3, c: 33512}, {f: 3, c: 33516}, 33520, {f: 2, c: 33522},
- {f: 2, c: 33525}, 33528, 33530, {f: 5, c: 33532}, {f: 2, c: 33546}, 33549,
- 33552, {f: 2, c: 33554}, 33558, {f: 2, c: 33560}, {f: 10, c: 33565},
- {f: 2, c: 33577}, 33582, 33584, 33586, 33591, 33595, {f: 3, c: 33597},
- {f: 2, c: 33601}, {f: 2, c: 33604}, 33608, {f: 5, c: 33610}, 33619,
- {f: 5, c: 33621}, 33629, 33634, {f: 7, c: 33648}, {f: 2, c: 33657},
- {f: 7, c: 33662}, {f: 2, c: 33671}, {f: 3, c: 33675}, {f: 3, c: 33679},
- {f: 2, c: 33684}, 33687, {f: 2, c: 33689}, 33693, 33695, 33697,
- {f: 4, c: 33699}, {f: 4, c: 33708}, 33717, 33723, {f: 2, c: 33726},
- {f: 3, c: 33730}, 33734, {f: 2, c: 33736}, 33739, {f: 2, c: 33741},
- {f: 4, c: 33744}, 33749, 33751, {f: 3, c: 33753}, 33758, {f: 3, c: 33762},
- {f: 3, c: 33766}, {f: 4, c: 33771}, {f: 5, c: 33779}, {f: 3, c: 33786},
- {f: 3, c: 33790}, 33794, 33797, {f: 2, c: 33800}, 33808, {f: 6, c: 33810},
- {f: 3, c: 33817}, {f: 6, c: 33822}, {f: 3, c: 33833}, {f: 4, c: 33837},
- {f: 3, c: 33842}, {f: 2, c: 33846}, {f: 3, c: 33849}, {f: 8, c: 33854},
- {f: 2, c: 33863}, {f: 7, c: 33866}, {f: 4, c: 33875}, 33880,
- {f: 4, c: 33885}, 33890, 33893, {f: 2, c: 33895}, 33898, 33902, 33904,
- 33906, 33908, 33913, {f: 7, c: 33915}, {f: 4, c: 33923}, 33930, 33933,
- {f: 4, c: 33935}, {f: 2, c: 33941}, 33944, {f: 2, c: 33946},
- {f: 4, c: 33949}, {f: 13, c: 33954}, {f: 2, c: 33968}, 33971,
- {f: 3, c: 33973}, 33979, 33982, {f: 2, c: 33986}, {f: 4, c: 33989}, 33996,
- {f: 2, c: 33998}, 34002, {f: 2, c: 34004}, {f: 6, c: 34007}, 34014,
- {f: 2, c: 34017}, 34020, {f: 5, c: 34023}, 34029, {f: 11, c: 34033}, 34046,
- {f: 12, c: 34048}, {f: 4, c: 34061}, 34066, {f: 2, c: 34069},
- {f: 2, c: 34072}, {f: 3, c: 34075}, 34080, 34082, {f: 2, c: 34084},
- {f: 4, c: 34087}, {f: 9, c: 34094}, {f: 3, c: 34110}, 34114,
- {f: 2, c: 34116}, 34119, {f: 3, c: 34123}, {f: 3, c: 34127}, 34132, 34135,
- {f: 4, c: 34138}, {f: 3, c: 34143}, 34147, {f: 3, c: 34149},
- {f: 2, c: 34155}, {f: 4, c: 34158}, 34163, {f: 2, c: 34165}, 34168,
- {f: 2, c: 34172}, {f: 5, c: 34175}, 34182, 34185, 34187, {f: 2, c: 34189},
- 34192, {f: 2, c: 34194}, {f: 6, c: 34197}, {f: 2, c: 34205},
- {f: 4, c: 34208}, 34213, 34215, {f: 3, c: 34219}, {f: 6, c: 34225}, 34232,
- {f: 6, c: 34235}, {f: 7, c: 34242}, {f: 3, c: 34250}, {f: 2, c: 34257},
- 34260, {f: 6, c: 34262}, {f: 6, c: 34270}, {f: 3, c: 34278},
- {f: 9, c: 34283}, 34293, {f: 2, c: 34295}, {f: 3, c: 34300},
- {f: 4, c: 34304}, {f: 3, c: 34312}, {f: 5, c: 34316}, {f: 4, c: 34322},
- {f: 3, c: 34327}, {f: 3, c: 34331}, {f: 3, c: 34335}, {f: 4, c: 34339},
- 34344, {f: 3, c: 34346}, {f: 10, c: 34350}, 34361, 34363, {f: 2, c: 34365},
- {f: 13, c: 34368}, {f: 2, c: 34386}, {f: 4, c: 34390}, 34395, 34397,
- {f: 2, c: 34400}, {f: 4, c: 34403}, {f: 3, c: 34408}, 34413,
- {f: 2, c: 34415}, {f: 7, c: 34418}, {f: 7, c: 34435}, {f: 5, c: 34446},
- 34452, {f: 6, c: 34454}, {f: 5, c: 34462}, {f: 2, c: 34469}, 34475,
- {f: 2, c: 34477}, {f: 2, c: 34482}, {f: 3, c: 34487}, {f: 5, c: 34491},
- {f: 3, c: 34497}, 34501, 34504, {f: 2, c: 34508}, {f: 2, c: 34514},
- {f: 3, c: 34517}, 34522, {f: 2, c: 34524}, {f: 4, c: 34528},
- {f: 4, c: 34533}, {f: 3, c: 34538}, 34543, {f: 3, c: 34549},
- {f: 3, c: 34555}, 34559, 34561, {f: 2, c: 34564}, {f: 2, c: 34571},
- {f: 4, c: 34574}, 34580, 34582, 34585, 34587, 34589, {f: 2, c: 34591},
- 34596, {f: 3, c: 34598}, {f: 4, c: 34602}, {f: 2, c: 34607},
- {f: 2, c: 34610}, {f: 2, c: 34613}, {f: 3, c: 34616}, {f: 2, c: 34620},
- {f: 7, c: 34624}, {f: 2, c: 34634}, 34637, {f: 4, c: 34639}, 34644, 34646,
- 34648, {f: 6, c: 34650}, {f: 2, c: 34657}, {f: 7, c: 34663}, 34671,
- {f: 3, c: 34673}, 34677, 34679, {f: 2, c: 34681}, {f: 3, c: 34687},
- {f: 2, c: 34694}, {f: 2, c: 34697}, 34700, {f: 5, c: 34702},
- {f: 3, c: 34708}, {f: 6, c: 34712}, {f: 2, c: 34720}, {f: 5, c: 34723},
- {f: 2, c: 34729}, 34734, {f: 3, c: 34736}, 34740, {f: 4, c: 34742}, 34748,
- {f: 2, c: 34750}, {f: 3, c: 34753}, 34757, 34759, 34761, {f: 2, c: 34764},
- {f: 2, c: 34767}, {f: 7, c: 34772}, {f: 4, c: 34780}, {f: 2, c: 34785},
- 34788, {f: 4, c: 34790}, 34795, 34797, {f: 2, c: 34800}, {f: 3, c: 34803},
- {f: 2, c: 34807}, 34810, {f: 2, c: 34812}, {f: 4, c: 34815}, 34820,
- {f: 3, c: 34823}, {f: 5, c: 34827}, 34834, 34836, {f: 4, c: 34839},
- {f: 3, c: 34844}, 34848, {f: 13, c: 34852}, {f: 3, c: 34867},
- {f: 2, c: 34871}, 34874, {f: 3, c: 34877}, {f: 3, c: 34881},
- {f: 3, c: 34887}, 34891, {f: 5, c: 34894}, {f: 2, c: 34901}, 34904, 34906,
- 34908, {f: 3, c: 34910}, {f: 2, c: 34918}, 34922, 34925, 34927, 34929,
- {f: 4, c: 34931}, 34936, {f: 3, c: 34938}, 34944, 34947, {f: 2, c: 34950},
- {f: 2, c: 34953}, 34956, {f: 4, c: 34958}, {f: 3, c: 34963},
- {f: 5, c: 34967}, {f: 5, c: 34973}, 34979, {f: 6, c: 34981}, 34988,
- {f: 3, c: 34990}, {f: 5, c: 34994}, {f: 4, c: 35000}, {f: 4, c: 35005},
- {f: 2, c: 35011}, {f: 2, c: 35015}, {f: 3, c: 35019}, {f: 2, c: 35024},
- 35027, {f: 2, c: 35030}, {f: 2, c: 35034}, 35038, {f: 2, c: 35040},
- {f: 2, c: 35046}, {f: 7, c: 35049}, 35058, {f: 3, c: 35061},
- {f: 2, c: 35066}, {f: 3, c: 35071}, {f: 4, c: 35075}, {f: 2, c: 35080},
- {f: 5, c: 35083}, 35089, {f: 5, c: 35092}, {f: 5, c: 35100},
- {f: 3, c: 35106}, {f: 4, c: 35110}, {f: 4, c: 35116}, 35121, 35125, 35127,
- {f: 2, c: 35129}, {f: 5, c: 35132}, {f: 2, c: 35138}, {f: 2, c: 35141},
- {f: 14, c: 35144}, {f: 6, c: 35159}, {f: 3, c: 35169}, 35173,
- {f: 3, c: 35175}, 35179, {f: 2, c: 35181}, {f: 2, c: 35184},
- {f: 8, c: 35187}, {f: 2, c: 35196}, [12177, 35198], 35200, 35202,
- {f: 2, c: 35204}, {f: 4, c: 35207}, {f: 3, c: 35212}, {f: 3, c: 35216},
- {f: 2, c: 35220}, 35223, {f: 8, c: 35225}, {f: 4, c: 35234},
- {f: 3, c: 35239}, 35243, {f: 2, c: 35245}, {f: 2, c: 35248},
- {f: 4, c: 35251}, {f: 2, c: 35256}, {f: 2, c: 35259}, 35262, 35267, 35277,
- {f: 3, c: 35283}, {f: 3, c: 35287}, 35291, 35293, {f: 4, c: 35295}, 35300,
- {f: 4, c: 35303}, {f: 3, c: 35308}, {f: 3, c: 35312}, 35317, 35319,
- {f: 7, c: 35321}, {f: 3, c: 35332}, 35337, 35339, 35341, 35343,
- {f: 2, c: 35345}, 35348, 35351, {f: 2, c: 35353}, 35356, 35358,
- {f: 3, c: 35360}, 35364, {f: 4, c: 35366}, {f: 2, c: 35371},
- {f: 3, c: 35374}, {f: 2, c: 35378}, 35381, {f: 3, c: 35383},
- {f: 3, c: 35387}, {f: 2, c: 35391}, {f: 4, c: 35394}, 35399,
- {f: 5, c: 35401}, 35407, 35409, 35411, {f: 2, c: 35414}, {f: 2, c: 35417},
- {f: 2, c: 35420}, {f: 2, c: 35423}, {f: 2, c: 35428}, {f: 2, c: 35431},
- 35434, 35439, 35444, {f: 3, c: 35446}, {f: 2, c: 35450}, {f: 2, c: 35453},
- {f: 4, c: 35456}, 35464, {f: 2, c: 35467}, {f: 3, c: 35470}, 35476,
- {f: 2, c: 35478}, 35481, {f: 3, c: 35483}, 35487, 35490, 35495,
- {f: 3, c: 35497}, {f: 3, c: 35501}, 35505, {f: 3, c: 35507},
- {f: 2, c: 35511}, {f: 2, c: 35514}, {f: 2, c: 35517}, {f: 2, c: 35520},
- 35523, {f: 2, c: 35525}, 35528, 35530, 35532, 35534, 35536,
- {f: 3, c: 35539}, {f: 3, c: 35544}, 35549, {f: 3, c: 35551}, 35555, 35557,
- {f: 3, c: 35560}, 35564, {f: 2, c: 35567}, 35570, {f: 2, c: 35572}, 35577,
- 35579, 35581, 35583, 35587, 35590, {f: 2, c: 35592}, {f: 3, c: 35595},
- 35599, {f: 3, c: 35601}, 35605, 35608, 35612, {f: 3, c: 35614},
- {f: 4, c: 35618}, 35623, {f: 2, c: 35625}, {f: 5, c: 35630},
- {f: 5, c: 35636}, {f: 4, c: 35642}, {f: 10, c: 35647}, {f: 4, c: 35658},
- {f: 6, c: 35664}, 35671, 35675, {f: 9, c: 35677}, {f: 4, c: 35687},
- {f: 2, c: 35693}, {f: 3, c: 35697}, {f: 2, c: 35701}, {f: 5, c: 35704},
- {f: 2, c: 35710}, {f: 9, c: 35713}, {f: 3, c: 35723}, {f: 3, c: 35727},
- 35732, {f: 5, c: 35735}, 35741, 35743, 35756, 35761, 35771, 35783, 35792,
- 35818, 35849, 35870, {f: 9, c: 35896}, {f: 4, c: 35906}, {f: 2, c: 35914},
- {f: 3, c: 35917}, {f: 4, c: 35921}, {f: 4, c: 35926}, {f: 6, c: 35931},
- {f: 7, c: 35939}, {f: 7, c: 35948}, {f: 4, c: 35956}, {f: 7, c: 35963},
- {f: 2, c: 35971}, {f: 3, c: 35974}, 35979, {f: 7, c: 35981},
- {f: 3, c: 35989}, {f: 4, c: 35993}, 35999, {f: 4, c: 36003},
- {f: 2, c: 36013}, 36017, 36021, 36025, 36030, 36038, 36041,
- {f: 6, c: 36043}, 36052, {f: 4, c: 36054}, 36059, 36061, 36063, 36069,
- {f: 2, c: 36072}, {f: 6, c: 36078}, {f: 5, c: 36085}, {f: 5, c: 36095},
- {f: 2, c: 36102}, 36105, 36108, 36110, {f: 5, c: 36113}, {f: 4, c: 36119},
- 36128, {f: 2, c: 36177}, 36183, 36191, 36197, {f: 3, c: 36200}, 36204,
- {f: 2, c: 36206}, {f: 2, c: 36209}, {f: 9, c: 36216}, {f: 2, c: 36226},
- {f: 4, c: 36230}, {f: 5, c: 36236}, {f: 2, c: 36242}, {f: 3, c: 36246},
- {f: 5, c: 36250}, {f: 3, c: 36256}, {f: 4, c: 36260}, {f: 8, c: 36265},
- {f: 2, c: 36278}, 36281, 36283, 36285, {f: 3, c: 36288}, 36293,
- {f: 4, c: 36295}, 36301, 36304, {f: 4, c: 36306}, {f: 2, c: 36312}, 36316,
- {f: 3, c: 36320}, {f: 3, c: 36325}, 36329, {f: 2, c: 36333},
- {f: 3, c: 36336}, 36340, 36342, 36348, {f: 7, c: 36350}, {f: 3, c: 36358},
- 36363, {f: 2, c: 36365}, {f: 3, c: 36369}, {f: 8, c: 36373},
- {f: 2, c: 36384}, {f: 5, c: 36388}, 36395, 36397, 36400, {f: 2, c: 36402},
- {f: 3, c: 36406}, {f: 2, c: 36411}, {f: 2, c: 36414}, 36419,
- {f: 2, c: 36421}, {f: 4, c: 36429}, {f: 2, c: 36435}, {f: 3, c: 36438},
- {f: 9, c: 36442}, {f: 2, c: 36452}, {f: 2, c: 36455}, {f: 2, c: 36458},
- 36462, 36465, 36467, 36469, {f: 3, c: 36471}, 36475, {f: 2, c: 36477},
- 36480, {f: 3, c: 36482}, 36486, 36488, 36492, 36494, {f: 5, c: 36501},
- 36507, 36509, {f: 2, c: 36511}, {f: 3, c: 36514}, {f: 3, c: 36519},
- {f: 2, c: 36525}, {f: 2, c: 36528}, {f: 7, c: 36531}, {f: 5, c: 36539},
- {f: 9, c: 36545}, {f: 3, c: 36559}, 36563, {f: 6, c: 36565},
- {f: 3, c: 36572}, {f: 4, c: 36576}, {f: 6, c: 36581}, {f: 6, c: 36588},
- {f: 5, c: 36595}, 36605, {f: 4, c: 36607}, 36612, 36614, 36616,
- {f: 7, c: 36619}, 36627, {f: 5, c: 36630}, {f: 5, c: 36640},
- {f: 2, c: 36647}, {f: 4, c: 36651}, {f: 3, c: 36656}, {f: 4, c: 36660},
- {f: 2, c: 36665}, {f: 2, c: 36668}, {f: 2, c: 36672}, 36675,
- {f: 2, c: 36679}, {f: 3, c: 36682}, {f: 5, c: 36687}, {f: 10, c: 36693},
- 36704, 36707, 36709, 36714, 36736, 36748, 36754, 36765, {f: 3, c: 36768},
- {f: 2, c: 36772}, 36775, 36778, 36780, {f: 2, c: 36787}, [12193, 36789],
- {f: 2, c: 36791}, {f: 3, c: 36794}, {f: 2, c: 36799}, 36803, 36806,
- {f: 5, c: 36809}, 36815, 36818, {f: 2, c: 36822}, 36826, {f: 2, c: 36832},
- 36835, 36839, 36844, 36847, {f: 2, c: 36849}, {f: 2, c: 36853},
- {f: 3, c: 36858}, {f: 2, c: 36862}, {f: 2, c: 36871}, 36876, 36878, 36883,
- 36888, 36892, {f: 2, c: 36900}, {f: 6, c: 36903}, {f: 2, c: 36912},
- {f: 2, c: 36915}, 36919, {f: 2, c: 36921}, 36925, {f: 2, c: 36927}, 36931,
- {f: 2, c: 36933}, {f: 3, c: 36936}, 36940, 36950, {f: 2, c: 36953}, 36957,
- 36959, 36961, 36964, {f: 2, c: 36966}, {f: 3, c: 36970}, {f: 3, c: 36975},
- 36979, 36982, 36985, 36987, 36990, {f: 2, c: 36997}, 37001,
- {f: 3, c: 37004}, 37010, 37012, 37014, 37016, 37018, 37020,
- {f: 3, c: 37022}, {f: 2, c: 37028}, {f: 3, c: 37031}, 37035, 37037, 37042,
- 37047, {f: 2, c: 37052}, {f: 2, c: 37055}, {f: 2, c: 37058}, 37062,
- {f: 2, c: 37064}, {f: 3, c: 37067}, 37074, {f: 3, c: 37076},
- {f: 3, c: 37080}, 37086, 37088, {f: 3, c: 37091}, {f: 2, c: 37097}, 37100,
- 37102, {f: 4, c: 37104}, {f: 2, c: 37110}, {f: 4, c: 37113},
- {f: 3, c: 37119}, 37123, 37125, {f: 2, c: 37127}, {f: 8, c: 37130}, 37139,
- 37141, {f: 2, c: 37143}, {f: 4, c: 37146}, {f: 3, c: 37151},
- {f: 3, c: 37156}, {f: 5, c: 37160}, 37166, 37171, 37173, {f: 2, c: 37175},
- {f: 8, c: 37179}, {f: 2, c: 37188}, 37191, 37201, {f: 4, c: 37203},
- {f: 2, c: 37208}, {f: 2, c: 37211}, {f: 2, c: 37215}, {f: 3, c: 37222},
- 37227, 37229, 37235, {f: 3, c: 37242}, {f: 5, c: 37248}, 37254, 37256,
- 37258, {f: 2, c: 37262}, {f: 3, c: 37267}, {f: 3, c: 37271},
- {f: 5, c: 37277}, {f: 6, c: 37284}, {f: 4, c: 37296}, {f: 4, c: 37302},
- {f: 5, c: 37307}, 37314, 37316, [12196, 37318], 37320, 37328, 37334,
- {f: 2, c: 37338}, {f: 5, c: 37342}, {f: 2, c: 37349}, 37352,
- {f: 11, c: 37354}, 37366, 37368, {f: 5, c: 37371}, {f: 2, c: 37378},
- {f: 3, c: 37381}, {f: 3, c: 37386}, 37391, {f: 2, c: 37394},
- {f: 8, c: 37398}, {f: 4, c: 37407}, 37412, {f: 6, c: 37416}, 37423,
- {f: 2, c: 37425}, {f: 2, c: 37429}, {f: 2, c: 37435}, {f: 4, c: 37441},
- {f: 2, c: 37446}, {f: 3, c: 37450}, {f: 3, c: 37454}, {f: 3, c: 37458},
- 37462, {f: 2, c: 37464}, {f: 2, c: 37468}, {f: 3, c: 37471},
- {f: 3, c: 37475}, {f: 5, c: 37479}, {f: 6, c: 37486}, {f: 3, c: 37493},
- 37497, {f: 3, c: 37500}, {f: 2, c: 37505}, 37508, {f: 8, c: 37510},
- {f: 2, c: 37519}, 37522, {f: 2, c: 37524}, 37527, 37529, 37531,
- {f: 3, c: 37533}, {f: 2, c: 37537}, 37540, 37543, 37549, {f: 2, c: 37551},
- {f: 5, c: 37554}, 37560, 37562, {f: 4, c: 37565}, 37570, 37572, 37574,
- {f: 3, c: 37577}, {f: 2, c: 37581}, {f: 2, c: 37584}, {f: 10, c: 37587},
- 37598, {f: 3, c: 37600}, 37607, 37609, {f: 2, c: 37611}, {f: 4, c: 37618},
- 37623, {f: 3, c: 37625}, {f: 4, c: 37629}, {f: 4, c: 37634},
- {f: 7, c: 37641}, 37649, {f: 2, c: 37651}, {f: 2, c: 37654},
- {f: 3, c: 37660}, 37665, {f: 3, c: 37667}, 37671, {f: 2, c: 37673},
- {f: 2, c: 37676}, {f: 2, c: 37680}, {f: 2, c: 37684}, 37687,
- {f: 5, c: 37689}, 37695, 37698, {f: 2, c: 37700}, {f: 3, c: 37704}, 37708,
- {f: 6, c: 37710}, {f: 3, c: 37717}, {f: 2, c: 37721}, {f: 8, c: 37724},
- {f: 3, c: 37734}, 37739, {f: 3, c: 37741}, {f: 4, c: 37745},
- {f: 3, c: 37751}, {f: 3, c: 37755}, {f: 3, c: 37759}, 37763,
- {f: 2, c: 37765}, {f: 2, c: 37768}, {f: 4, c: 37771}, {f: 6, c: 37776},
- 37783, {f: 9, c: 37785}, {f: 2, c: 37796}, 37800, 37803, 37805, 37807,
- {f: 2, c: 37809}, 37812, {f: 2, c: 37814}, {f: 6, c: 37817},
- {f: 3, c: 37824}, {f: 3, c: 37828}, 37833, 37835, {f: 3, c: 37838},
- {f: 4, c: 37842}, {f: 3, c: 37849}, 37856, 37859, {f: 3, c: 37861},
- {f: 12, c: 37865}, 37878, 37880, {f: 9, c: 37882}, {f: 7, c: 37892},
- {f: 4, c: 37900}, 37905, {f: 3, c: 37909}, {f: 3, c: 37914},
- {f: 2, c: 37918}, {f: 5, c: 37921}, {f: 5, c: 37929}, {f: 3, c: 37935},
- 37940, {f: 2, c: 37942}, 37945, {f: 3, c: 37947}, {f: 4, c: 37952},
- {f: 5, c: 37957}, 37963, {f: 5, c: 37965}, 37971, {f: 11, c: 37973},
- {f: 2, c: 37985}, 37988, {f: 5, c: 37990}, 37996, {f: 2, c: 37998}, 38001,
- {f: 4, c: 38003}, 38008, {f: 2, c: 38010}, {f: 5, c: 38016}, 38033, 38038,
- 38040, 38087, 38095, {f: 2, c: 38099}, 38106, 38118, 38139, 38172, 38176,
- 38183, 38195, 38205, 38211, 38216, 38219, 38229, 38234, 38240, 38254,
- {f: 2, c: 38260}, {f: 7, c: 38264}, 38273, {f: 2, c: 38276},
- {f: 2, c: 38279}, 38282, 38285, 38288, 38290, {f: 3, c: 38293},
- {f: 8, c: 38297}, 38306, {f: 2, c: 38310}, 38314, {f: 4, c: 38318},
- {f: 3, c: 38323}, {f: 2, c: 38327}, 38330, {f: 3, c: 38336},
- {f: 2, c: 38340}, 38343, 38345, {f: 3, c: 38349}, {f: 3, c: 38353},
- {f: 5, c: 38359}, 38365, {f: 2, c: 38367}, {f: 2, c: 38371},
- {f: 2, c: 38374}, 38380, 38399, 38407, 38419, 38424, 38427, 38430, 38432,
- {f: 7, c: 38435}, {f: 3, c: 38443}, {f: 2, c: 38447}, {f: 4, c: 38455},
- 38462, 38465, 38467, 38474, {f: 2, c: 38478}, {f: 3, c: 38481},
- {f: 2, c: 38486}, {f: 2, c: 38489}, 38492, 38494, 38496, {f: 2, c: 38501},
- 38507, {f: 3, c: 38509}, 38513, {f: 4, c: 38521}, {f: 7, c: 38526}, 38535,
- 38537, 38540, {f: 3, c: 38545}, 38550, 38554, {f: 10, c: 38557}, 38569,
- {f: 5, c: 38571}, 38578, 38581, 38583, 38586, 38591, {f: 2, c: 38594},
- 38600, {f: 2, c: 38602}, {f: 2, c: 38608}, {f: 2, c: 38611},
- {f: 2, c: 38615}, 38618, {f: 3, c: 38621}, 38625, {f: 4, c: 38628},
- {f: 4, c: 38635}, {f: 2, c: 38640}, {f: 2, c: 38644}, 38648, 38650,
- {f: 2, c: 38652}, 38655, {f: 2, c: 38658}, 38661, {f: 3, c: 38666},
- {f: 3, c: 38672}, {f: 2, c: 38676}, {f: 5, c: 38679}, 38685,
- {f: 8, c: 38687}, {f: 2, c: 38696}, {f: 2, c: 38699}, {f: 2, c: 38702},
- 38705, {f: 5, c: 38707}, {f: 3, c: 38714}, {f: 3, c: 38719}, 38723,
- {f: 3, c: 38725}, {f: 8, c: 38729}, [12205, 38737], {f: 2, c: 38740},
- {f: 2, c: 38743}, {f: 2, c: 38748}, 38751, {f: 2, c: 38755},
- {f: 2, c: 38758}, {f: 9, c: 38762}, 38773, {f: 5, c: 38775},
- {f: 8, c: 38781}, {f: 5, c: 38790}, 38796, 38798, 38800, 38803,
- {f: 3, c: 38805}, {f: 7, c: 38809}, {f: 2, c: 38817}, {f: 2, c: 38820},
- {f: 4, c: 38823}, 38828, 38830, {f: 2, c: 38832}, 38835, {f: 8, c: 38837},
- {f: 5, c: 38846}, {f: 2, c: 38852}, {f: 2, c: 38855}, 38858,
- {f: 6, c: 38861}, {f: 5, c: 38868}, {f: 2, c: 38874}, 38877,
- {f: 7, c: 38879}, 38888, {f: 5, c: 38894}, 38900, {f: 8, c: 38903}, 38912,
- 38916, 38921, 38923, 38925, {f: 3, c: 38932}, {f: 3, c: 38937},
- {f: 4, c: 38941}, {f: 2, c: 38946}, 38949, {f: 6, c: 38951},
- {f: 2, c: 38958}, {f: 6, c: 38961}, {f: 2, c: 38969}, 38972,
- {f: 8, c: 38974}, {f: 5, c: 38983}, {f: 4, c: 38991}, {f: 3, c: 38997},
- 39002, {f: 2, c: 39004}, {f: 3, c: 39007}, {f: 2, c: 39011}, 39014,
- {f: 3, c: 39016}, {f: 2, c: 39021}, 39026, 39051, 39054, 39058, 39061,
- 39065, 39075, {f: 5, c: 39081}, 39088, 39090, {f: 2, c: 39092},
- {f: 5, c: 39095}, {f: 7, c: 39101}, 39109, 39111, {f: 5, c: 39113},
- {f: 2, c: 39119}, 39124, {f: 2, c: 39126}, {f: 2, c: 39132}, 39137,
- {f: 4, c: 39139}, 39148, 39150, {f: 2, c: 39152}, 39155, {f: 7, c: 39157},
- {f: 4, c: 39167}, 39172, {f: 3, c: 39174}, 39179, {f: 2, c: 39182},
- {f: 4, c: 39188}, {f: 2, c: 39193}, {f: 2, c: 39196}, {f: 2, c: 39199},
- {f: 6, c: 39202}, {f: 5, c: 39209}, {f: 4, c: 39215}, {f: 3, c: 39220},
- {f: 4, c: 39224}, 39229, {f: 3, c: 39232}, 39236, {f: 2, c: 39238},
- {f: 4, c: 39245}, 39251, 39254, {f: 4, c: 39256}, 39261, {f: 3, c: 39263},
- 39268, 39270, 39283, {f: 2, c: 39288}, 39291, 39294, {f: 2, c: 39298},
- 39305, 39308, 39310, {f: 11, c: 39322}, {f: 2, c: 39334}, {f: 3, c: 39337},
- {f: 2, c: 39343}, 39346, {f: 12, c: 39349}, {f: 14, c: 39362}, 39379,
- {f: 2, c: 39382}, 39386, 39388, 39390, 39392, {f: 10, c: 39395},
- {f: 3, c: 39406}, {f: 13, c: 39410}, 39424, {f: 3, c: 39426},
- {f: 7, c: 39430}, {f: 6, c: 39440}, {f: 2, c: 39447}, {f: 17, c: 39450},
- 39468, 39471, {f: 5, c: 39473}, {f: 5, c: 39481}, 39487, {f: 4, c: 39494},
- {f: 2, c: 39499}, 39502, {f: 5, c: 39504}, 39510, {f: 2, c: 39512},
- {f: 3, c: 39516}, {f: 2, c: 39520}, 39523, {f: 4, c: 39526}, 39531, 39538,
- 39555, 39561, {f: 2, c: 39565}, {f: 2, c: 39572}, 39577, 39590,
- {f: 6, c: 39593}, {f: 4, c: 39602}, 39609, 39611, {f: 3, c: 39613},
- {f: 2, c: 39619}, {f: 5, c: 39622}, {f: 2, c: 39629}, 39632, 39639,
- {f: 6, c: 39641}, 39648, {f: 4, c: 39650}, {f: 4, c: 39655}, 39660,
- {f: 9, c: 39664}, 39674, {f: 7, c: 39676}, {f: 2, c: 39684}, 39687,
- {f: 4, c: 39689}, 39694, {f: 3, c: 39696}, {f: 6, c: 39700},
- {f: 4, c: 39707}, {f: 2, c: 39712}, 39716, 39718, 39720, {f: 4, c: 39722},
- 39728, {f: 8, c: 39731}, {f: 4, c: 39741}, 39750, {f: 3, c: 39754}, 39760,
- {f: 2, c: 39762}, {f: 3, c: 39765}, 39769, {f: 20, c: 39771},
- {f: 4, c: 39792}, {f: 2, c: 39797}, {f: 9, c: 39800}, 39810,
- {f: 10, c: 39812}, 39823, {f: 7, c: 39827}, {f: 2, c: 39835},
- {f: 11, c: 39839}, 39852, {f: 17, c: 39855}, {f: 5, c: 39874}, 39880,
- {f: 9, c: 39883}, 39893, {f: 4, c: 39895}, 39900, {f: 3, c: 39902}, 39907,
- {f: 2, c: 39909}, 39913, {f: 4, c: 39916}, {f: 3, c: 39921},
- {f: 8, c: 39925}, 39934, {f: 8, c: 39936}, {f: 3, c: 39946},
- {f: 2, c: 39950}, 39953, {f: 12, c: 39956}, {f: 2, c: 39969}, 39972,
- {f: 2, c: 39974}, {f: 3, c: 39978}, {f: 3, c: 39982}, 39988, 39990, 39992,
- 39994, {f: 2, c: 39996}, {f: 6, c: 39999}, {f: 2, c: 40006},
- {f: 8, c: 40010}, 40019, 40021, {f: 4, c: 40025}, 40030, {f: 7, c: 40032},
- {f: 5, c: 40040}, {f: 10, c: 40046}, 40057, 40059, {f: 2, c: 40061}, 40064,
- {f: 2, c: 40067}, {f: 2, c: 40073}, 40076, 40079, 40083, {f: 4, c: 40086},
- 40093, 40106, 40108, 40111, 40121, {f: 5, c: 40126}, {f: 2, c: 40136},
- {f: 2, c: 40145}, {f: 2, c: 40154}, {f: 2, c: 40160}, {f: 2, c: 40163},
- {f: 3, c: 40166}, {f: 2, c: 40170}, {f: 6, c: 40173}, 40181,
- {f: 15, c: 40183}, 40200, {f: 11, c: 40202}, {f: 5, c: 40214}, 40220,
- 40222, {f: 3, c: 40224}, {f: 2, c: 40228}, 40231, {f: 6, c: 40233},
- {f: 10, c: 40241}, {f: 3, c: 40252}, {f: 2, c: 40256}, {f: 14, c: 40259},
- {f: 8, c: 40276}, {f: 2, c: 40286}, {f: 8, c: 40290}, 40299,
- {f: 2, c: 40301}, {f: 2, c: 40304}, {f: 20, c: 40307}, 40328,
- {f: 9, c: 40330}, {f: 4, c: 40340}, 40345, {f: 10, c: 40347},
- {f: 3, c: 40358}, {f: 5, c: 40362}, {f: 4, c: 40368}, {f: 6, c: 40373},
- {f: 3, c: 40381}, 40385, 40387, {f: 14, c: 40389}, {f: 3, c: 40404}, 40408,
- {f: 10, c: 40411}, {f: 8, c: 40423}, {f: 2, c: 40432}, {f: 4, c: 40436},
- {f: 17, c: 40443}, {f: 8, c: 40461}, {f: 4, c: 40470}, 40476, 40484, 40487,
- 40494, 40496, 40500, {f: 2, c: 40507}, 40512, 40525, 40528,
- {f: 3, c: 40530}, 40534, 40537, 40541, {f: 4, c: 40543}, 40549,
- {f: 2, c: 40558}, 40562, 40564, {f: 3, c: 40566}, 40571, {f: 2, c: 40576},
- {f: 4, c: 40579}, {f: 2, c: 40585}, {f: 6, c: 40588}, {f: 3, c: 40596},
- {f: 5, c: 40600}, 40606, {f: 5, c: 40608}, {f: 2, c: 40615},
- {f: 5, c: 40618}, {f: 4, c: 40624}, {f: 2, c: 40630}, {f: 2, c: 40633},
- 40636, {f: 4, c: 40639}, [12232, 40643], {f: 4, c: 40645},
- {f: 2, c: 40650}, 40656, {f: 2, c: 40658}, {f: 3, c: 40661},
- {f: 2, c: 40665}, 40673, {f: 2, c: 40675}, 40678, {f: 4, c: 40683},
- {f: 2, c: 40688}, 40691, {f: 2, c: 40693}, 40696, 40698, {f: 9, c: 40704},
- 40714, 40716, 40719, {f: 2, c: 40721}, 40724, 40726, 40728,
- {f: 6, c: 40730}, 40737, {f: 9, c: 40739}, {f: 2, c: 40749},
- {f: 7, c: 40752}, 40760, 40762, 40764, {f: 5, c: 40767}, {f: 5, c: 40773},
- {f: 3, c: 40780}, 40787, {f: 4, c: 40789}, {f: 2, c: 40794},
- {f: 2, c: 40797}, 40802, {f: 2, c: 40804}, {f: 3, c: 40807}, 40811,
- {f: 5, c: 40813}, {f: 4, c: 40819}, {f: 7, c: 40824}, {f: 2, c: 40833},
- {f: 2, c: 40846}, {f: 3, c: 40849}, {f: 3, c: 40854}, {f: 2, c: 40861},
- {f: 5, c: 40865}, 63788, {f: 3, c: 64013}, 64017, {f: 2, c: 64019}, 64024,
- {f: 3, c: 64031}, {f: 2, c: 64035}, {f: 3, c: 64039}, 11905,
- [59414, 131207], [59415, 131209], [59416, 131276], 11908, 13427, 13383,
- 11912, 11915, 59422, 13726, 13850, 13838, 11916, 11927, 14702, 14616,
- 59430, 14799, 14815, 14963, 14800, {f: 2, c: 59435}, 15182, 15470, 15584,
- 11943, [59441, 136663], 59442, 11946, 16470, 16735, 11950, 17207, 11955,
- {f: 2, c: 11958}, [59451, 141711], 17329, 17324, 11963, 17373, 17622,
- 18017, 17996, [59459, 132361], 18211, 18217, 18300, 18317, 11978, 18759,
- 18810, 18813, {f: 2, c: 18818}, {f: 2, c: 18821}, 18847, 18843, 18871,
- 18870, [59476, 133533], [59477, 147966], 19619, {f: 3, c: 19615}, 19575,
- 19618, {f: 7, c: 19731}, 19886, 59492, {s: 226}, 8364, 165, 0, 0, 12351,
- {s: 17}, 12436, {s: 14}, 12535, 12537, 12536, 12538, 0, {f: 3, c: 12339},
- {f: 3, c: 12344}, {f: 3, c: 12586}, {f: 24, c: 12704}, 11904,
- {f: 2, c: 11906}, {f: 3, c: 11909}, {f: 2, c: 11913}, {f: 10, c: 11917},
- {f: 2, c: 11928}, {f: 12, c: 11931}, {f: 2, c: 11944}, {f: 3, c: 11947},
- {f: 4, c: 11951}, {f: 2, c: 11956}, {f: 3, c: 11960}, {f: 14, c: 11964},
- {f: 41, c: 11979}, {f: 71, c: 13312}, {f: 43, c: 13384},
- {f: 298, c: 13428}, {f: 111, c: 13727}, {f: 11, c: 13839},
- {f: 765, c: 13851}, {f: 85, c: 14617}, {f: 96, c: 14703},
- {f: 14, c: 14801}, {f: 147, c: 14816}, {f: 218, c: 14964},
- {f: 287, c: 15183}, {f: 113, c: 15471}, {f: 885, c: 15585},
- {f: 264, c: 16471}, {f: 471, c: 16736}, {f: 116, c: 17208},
- {f: 4, c: 17325}, {f: 43, c: 17330}, {f: 248, c: 17374},
- {f: 373, c: 17623}, {f: 20, c: 17997}, {f: 193, c: 18018},
- {f: 5, c: 18212}, {f: 82, c: 18218}, {f: 16, c: 18301}, {f: 441, c: 18318},
- {f: 50, c: 18760}, {f: 2, c: 18811}, {f: 4, c: 18814}, 18820,
- {f: 20, c: 18823}, {f: 3, c: 18844}, {f: 22, c: 18848}, {f: 703, c: 18872},
- {f: 39, c: 19576}, {f: 111, c: 19620}, {f: 148, c: 19738},
- {f: 7, c: 19887}]
-};
+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) {
+ 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 = cs[1].getAll();
+ return ['CalGrayCS', params];
+ case 'CalRGB':
+ params = 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() {
@@ -13561,8 +7779,9 @@ var ARCFourCipher = (function ARCFourCipherClosure() {
this.b = 0;
var s = new Uint8Array(256);
var i, j = 0, tmp, keyLength = key.length;
- for (i = 0; i < 256; ++i)
+ 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;
@@ -13622,12 +7841,14 @@ var calculateMD5 = (function calculateMD5Closure() {
var paddedLength = (length + 72) & ~63; // data + 9 extra bytes
var padded = new Uint8Array(paddedLength);
var i, j, n;
- for (i = 0; i < length; ++i)
+ for (i = 0; i < length; ++i) {
padded[i] = data[offset++];
+ }
padded[i++] = 0x80;
n = paddedLength - 8;
- while (i < n)
+ while (i < n) {
padded[i++] = 0;
+ }
padded[i++] = (length << 3) & 0xFF;
padded[i++] = (length >> 5) & 0xFF;
padded[i++] = (length >> 13) & 0xFF;
@@ -13636,13 +7857,11 @@ var calculateMD5 = (function calculateMD5Closure() {
padded[i++] = 0;
padded[i++] = 0;
padded[i++] = 0;
- // chunking
- // TODO ArrayBuffer ?
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));
+ (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) {
@@ -13671,15 +7890,487 @@ var calculateMD5 = (function calculateMD5Closure() {
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
+ 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() {
}
@@ -13765,7 +8456,14 @@ var AES128Cipher = (function AES128CipherClosure() {
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,
@@ -13819,14 +8517,21 @@ var AES128Cipher = (function AES128CipherClosure() {
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];
+ 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++;
+ 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;
@@ -13838,28 +8543,43 @@ var AES128Cipher = (function AES128CipherClosure() {
var i, j, k;
var t, u, v;
// AddRoundKey
- for (j = 0, k = 160; j < 16; ++j, ++k)
+ 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;
+ 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)
+ for (j = 0; j < 16; ++j) {
state[j] = inv_s[state[j]];
+ }
// AddRoundKey
- for (j = 0, k = i * 16; j < 16; ++j, ++k)
+ 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]];
+ s2 = mix[state[j + 2]], s3 = mix[state[j + 3]];
t = (s0 ^ (s1 >>> 8) ^ (s1 << 24) ^ (s2 >>> 16) ^ (s2 << 16) ^
- (s3 >>> 24) ^ (s3 << 8));
+ (s3 >>> 24) ^ (s3 << 8));
state[j] = (t >>> 24) & 0xFF;
state[j + 1] = (t >> 16) & 0xFF;
state[j + 2] = (t >> 8) & 0xFF;
@@ -13867,12 +8587,24 @@ var AES128Cipher = (function AES128CipherClosure() {
}
}
// 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;
+ 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]];
@@ -13882,6 +8614,85 @@ var AES128Cipher = (function AES128CipherClosure() {
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);
@@ -13895,13 +8706,15 @@ var AES128Cipher = (function AES128CipherClosure() {
for (i = 0; i < sourceLength; ++i) {
buffer[bufferLength] = data[i];
++bufferLength;
- if (bufferLength < 16)
+ 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)
+ for (j = 0; j < 16; ++j) {
plain[j] ^= iv[j];
+ }
iv = buffer;
result.push(plain);
buffer = new Uint8Array(16);
@@ -13919,12 +8732,23 @@ var AES128Cipher = (function AES128CipherClosure() {
if (finalize) {
// undo a padding that is described in RFC 2898
var lastBlock = result[result.length - 1];
- outputLength -= lastBlock[15];
- result[result.length - 1] = lastBlock.subarray(0, 16 - lastBlock[15]);
+ 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)
+ for (i = 0, j = 0, ii = result.length; i < ii; ++i, j += 16) {
output.set(result[i], j);
+ }
return output;
}
@@ -13933,8 +8757,9 @@ var AES128Cipher = (function AES128CipherClosure() {
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)
+ for (i = 0; bufferLength < 16 && i < sourceLength; ++i, ++bufferLength) {
buffer[bufferLength] = data[i];
+ }
if (bufferLength < 16) {
// need more data
this.bufferLength = bufferLength;
@@ -13946,21 +8771,707 @@ var AES128Cipher = (function AES128CipherClosure() {
// 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) {
+ createStream: function CipherTransform_createStream(stream, length) {
var cipher = new this.streamCipherConstructor();
- return new DecryptStream(stream,
+ return new DecryptStream(stream, length,
function cipherTransformDecryptStream(data, finalize) {
return cipher.decryptBlock(data, finalize);
}
@@ -13983,28 +9494,63 @@ var CipherTransformFactory = (function CipherTransformFactoryClosure() {
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)
+ 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)
+ 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)
+ for (j = 0, n = fileId.length; j < n; ++j) {
hashData[i++] = fileId[j];
+ }
if (revision >= 4 && !encryptMetadata) {
hashData[i++] = 0xFF;
hashData[i++] = 0xFF;
@@ -14015,46 +9561,53 @@ var CipherTransformFactory = (function CipherTransformFactoryClosure() {
var keyLengthInBytes = keyLength >> 3;
if (revision >= 3) {
for (j = 0; j < 50; ++j) {
- hash = calculateMD5(hash, 0, keyLengthInBytes);
+ hash = calculateMD5(hash, 0, keyLengthInBytes);
}
}
var encryptionKey = hash.subarray(0, keyLengthInBytes);
var cipher, checkData;
if (revision >= 3) {
- for (i = 0; i < 32; ++i)
+ for (i = 0; i < 32; ++i) {
hashData[i] = defaultPasswordBytes[i];
- for (j = 0, n = fileId.length; j < n; ++j)
+ }
+ for (j = 0, n = fileId.length; j < n; ++j) {
hashData[i++] = fileId[j];
+ }
cipher = new ARCFourCipher(encryptionKey);
- var checkData = cipher.encryptBlock(calculateMD5(hashData, 0, i));
+ 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)
+ 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])
+ 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])
+ 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)
+ for (; i < n; ++i) {
hashData[i] = password[i];
+ }
j = 0;
while (i < 32) {
hashData[i++] = defaultPasswordBytes[j++];
@@ -14063,7 +9616,7 @@ var CipherTransformFactory = (function CipherTransformFactoryClosure() {
var keyLengthInBytes = keyLength >> 3;
if (revision >= 3) {
for (j = 0; j < 50; ++j) {
- hash = calculateMD5(hash, 0, hash.length);
+ hash = calculateMD5(hash, 0, hash.length);
}
}
@@ -14072,8 +9625,9 @@ var CipherTransformFactory = (function CipherTransformFactoryClosure() {
userPassword = ownerPassword;
var derivedKey = new Uint8Array(keyLengthInBytes), k;
for (j = 19; j >= 0; j--) {
- for (k = 0; k < keyLengthInBytes; ++k)
+ for (k = 0; k < keyLengthInBytes; ++k) {
derivedKey[k] = hash[k] ^ j;
+ }
cipher = new ARCFourCipher(derivedKey);
userPassword = cipher.encryptBlock(userPassword);
}
@@ -14084,39 +9638,66 @@ var CipherTransformFactory = (function CipherTransformFactoryClosure() {
return userPassword;
}
- var identityName = new Name('Identity');
+ var identityName = Name.get('Identity');
function CipherTransformFactory(dict, fileId, password) {
var filter = dict.get('Filter');
- if (!isName(filter) || filter.name != 'Standard')
+ 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 !== 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)
+ 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');
- var encryptMetadata = algorithm == 4 && // meaningful when V is 4
- dict.get('EncryptMetadata') !== false; // makes true as default value
+ // 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)
+ if (password) {
passwordBytes = stringToBytes(password);
+ }
- var encryptionKey = prepareKeyData(fileIdBytes, passwordBytes,
- ownerPassword, userPassword, flags,
- revision, keyLength, encryptMetadata);
+ 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);
@@ -14129,13 +9710,14 @@ var CipherTransformFactory = (function CipherTransformFactoryClosure() {
revision, keyLength, encryptMetadata);
}
- if (!encryptionKey)
+ if (!encryptionKey) {
throw new PasswordException('Incorrect Password',
PasswordResponses.INCORRECT_PASSWORD);
+ }
this.encryptionKey = encryptionKey;
- if (algorithm == 4) {
+ if (algorithm >= 4) {
this.cf = dict.get('CF');
this.stmf = dict.get('StmF') || identityName;
this.strf = dict.get('StrF') || identityName;
@@ -14145,8 +9727,9 @@ var CipherTransformFactory = (function CipherTransformFactoryClosure() {
function buildObjectKey(num, gen, encryptionKey, isAes) {
var key = new Uint8Array(encryptionKey.length + 9), i, n;
- for (i = 0, n = encryptionKey.length; i < n; ++i)
+ 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;
@@ -14165,23 +9748,27 @@ var CipherTransformFactory = (function CipherTransformFactoryClosure() {
function buildCipherConstructor(cf, name, num, gen, key) {
var cryptFilter = cf.get(name.name);
var cfm;
- if (cryptFilter !== null && cryptFilter !== undefined)
+ if (cryptFilter !== null && cryptFilter !== undefined) {
cfm = cryptFilter.get('CFM');
- if (!cfm || cfm.name == 'None') {
+ }
+ if (!cfm || cfm.name === 'None') {
return function cipherTransformFactoryBuildCipherConstructorNone() {
return new NullCipher();
};
}
- if ('V2' == cfm.name) {
+ if ('V2' === cfm.name) {
return function cipherTransformFactoryBuildCipherConstructorV2() {
- return new ARCFourCipher(
- buildObjectKey(num, gen, key, false));
+ return new ARCFourCipher(buildObjectKey(num, gen, key, false));
};
}
- if ('AESV2' == cfm.name) {
+ if ('AESV2' === cfm.name) {
return function cipherTransformFactoryBuildCipherConstructorAESV2() {
- return new AES128Cipher(
- buildObjectKey(num, gen, key, true));
+ return new AES128Cipher(buildObjectKey(num, gen, key, true));
+ };
+ }
+ if ('AESV3' === cfm.name) {
+ return function cipherTransformFactoryBuildCipherConstructorAESV3() {
+ return new AES256Cipher(key);
};
}
error('Unknown crypto method');
@@ -14190,12 +9777,12 @@ var CipherTransformFactory = (function CipherTransformFactoryClosure() {
CipherTransformFactory.prototype = {
createCipherTransform:
function CipherTransformFactory_createCipherTransform(num, gen) {
- if (this.algorithm == 4) {
+ if (this.algorithm === 4 || this.algorithm === 5) {
return new CipherTransform(
buildCipherConstructor(this.cf, this.stmf,
- num, gen, this.encryptionKey),
+ num, gen, this.encryptionKey),
buildCipherConstructor(this.cf, this.strf,
- num, gen, this.encryptionKey));
+ num, gen, this.encryptionKey));
}
// algorithms 1 and 2
var key = buildObjectKey(num, gen, this.encryptionKey, false);
@@ -14209,11 +9796,14 @@ var CipherTransformFactory = (function CipherTransformFactoryClosure() {
return CipherTransformFactory;
})();
-
-
var PatternType = {
+ FUNCTION_BASED: 1,
AXIAL: 2,
- RADIAL: 3
+ RADIAL: 3,
+ FREE_FORM_MESH: 4,
+ LATTICE_FORM_MESH: 5,
+ COONS_PATCH_MESH: 6,
+ TENSOR_PATCH_MESH: 7
};
var Pattern = (function PatternClosure() {
@@ -14236,14 +9826,27 @@ var Pattern = (function PatternClosure() {
var dict = isStream(shading) ? shading.dict : shading;
var type = dict.get('ShadingType');
- 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);
- default:
- UnsupportedManager.notify(UNSUPPORTED_FEATURES.shadingPattern);
- return new Shadings.Dummy();
+ 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;
@@ -14304,29 +9907,7 @@ Shadings.RadialAxial = (function RadialAxialClosure() {
this.extendEnd = extendEnd;
var fnObj = dict.get('Function');
- var fn;
- if (isArray(fnObj)) {
- var fnArray = [];
- for (var j = 0, jj = fnObj.length; j < jj; j++) {
- var obj = xref.fetchIfRef(fnObj[j]);
- if (!isPDFFunction(obj)) {
- error('Invalid function');
- }
- fnArray.push(PDFFunction.parse(xref, obj));
- }
- fn = function radialAxialColorFunction(arg) {
- var out = [];
- for (var i = 0, ii = fnArray.length; i < ii; i++) {
- out.push(fnArray[i](arg)[0]);
- }
- return out;
- };
- } else {
- if (!isPDFFunction(fnObj)) {
- error('Invalid function');
- }
- fn = PDFFunction.parse(xref, fnObj);
- }
+ 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
@@ -14344,16 +9925,20 @@ Shadings.RadialAxial = (function RadialAxialClosure() {
return;
}
+ var color = new Float32Array(cs.numComps), ratio = new Float32Array(1);
+ var rgbColor;
for (var i = t0; i <= t1; i += step) {
- var rgbColor = cs.getRgb(fn([i]), 0);
- var cssColor = Util.makeCssRgb(rgbColor);
+ 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')) {
- var rgbColor = cs.getRgb(dict.get('Background'), 0);
- background = Util.makeCssRgb(rgbColor);
+ rgbColor = cs.getRgb(dict.get('Background'), 0);
+ background = Util.makeCssRgb(rgbColor[0], rgbColor[1], rgbColor[2]);
}
if (!extendStart) {
@@ -14376,13 +9961,13 @@ Shadings.RadialAxial = (function RadialAxialClosure() {
var coordsArr = this.coordsArr;
var shadingType = this.shadingType;
var type, p0, p1, r0, r1;
- if (shadingType == PatternType.AXIAL) {
+ 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) {
+ } else if (shadingType === PatternType.RADIAL) {
p0 = [coordsArr[0], coordsArr[1]];
p1 = [coordsArr[3], coordsArr[4]];
r0 = coordsArr[2];
@@ -14405,6 +9990,568 @@ Shadings.RadialAxial = (function RadialAxialClosure() {
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';
@@ -14436,9 +10583,6 @@ function getTilingPatternIR(operatorList, dict, args) {
var PartialEvaluator = (function PartialEvaluatorClosure() {
function PartialEvaluator(pdfManager, xref, handler, pageIndex,
uniquePrefix, idCounters, fontCache) {
- this.state = new EvalState();
- this.stateStack = [];
-
this.pdfManager = pdfManager;
this.xref = xref;
this.handler = handler;
@@ -14448,6 +10592,28 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
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 = {
@@ -14456,14 +10622,20 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
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 (var key in graphicStates) {
+ for (key in graphicStates) {
var graphicState = graphicStates[key];
var bm = graphicState['BM'];
if (isName(bm) && bm.name !== 'Normal') {
@@ -14477,14 +10649,26 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
continue;
}
xObjects = xObjects.getAll();
- for (var key in xObjects) {
+ 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');
- if (isDict(xResources)) {
+ // 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;
+ }
}
}
}
@@ -14494,9 +10678,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
buildFormXObject: function PartialEvaluator_buildFormXObject(resources,
xobj, smask,
operatorList,
- state) {
- var self = this;
-
+ initialState) {
var matrix = xobj.dict.get('Matrix');
var bbox = xobj.dict.get('BBox');
var group = xobj.dict.get('Group');
@@ -14510,42 +10692,57 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
};
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;
- var colorSpace = group.get('CS');
- groupOptions.colorSpace = colorSpace ?
- ColorSpace.parseToIR(colorSpace, this.xref, resources) : null;
+ 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]);
- this.getOperatorList(xobj, xobj.dict.get('Resources') || resources,
- operatorList, state);
- operatorList.addOp(OPS.paintFormXObjectEnd, []);
+ return this.getOperatorList(xobj,
+ (xobj.dict.get('Resources') || resources), operatorList, initialState).
+ then(function () {
+ operatorList.addOp(OPS.paintFormXObjectEnd, []);
- if (group) {
- operatorList.addOp(OPS.endGroup, [groupOptions]);
- }
+ if (group) {
+ operatorList.addOp(OPS.endGroup, [groupOptions]);
+ }
+ });
},
- buildPaintImageXObject: function PartialEvaluator_buildPaintImageXObject(
- resources, image, inline, operatorList) {
+ 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 imageMask = (dict.get('ImageMask', 'IM') || false);
+ var imgData, args;
if (imageMask) {
- // This depends on a tmpCanvas beeing filled with the
+ // 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
@@ -14556,121 +10753,139 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
var bitStrideLength = (width + 7) >> 3;
var imgArray = image.getBytes(bitStrideLength * height);
var decode = dict.get('Decode', 'D');
- var inverseDecode = !!decode && decode[0] > 0;
+ var inverseDecode = (!!decode && decode[0] > 0);
- operatorList.addOp(OPS.paintImageMaskXObject,
- [PDFImage.createMask(imgArray, width, height, inverseDecode)]
- );
+ 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 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) &&
+ if (inline && !softMask && !mask && !(image instanceof JpegStream) &&
(w + h) < SMALL_IMAGE_DIMENSIONS) {
var imageObj = new PDFImage(this.xref, resources, image,
inline, null, null);
- var imgData = imageObj.getImageData();
+ // 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 uniquePrefix = (this.uniquePrefix || '');
var objId = 'img_' + uniquePrefix + (++this.idCounters.obj);
operatorList.addDependency(objId);
- var args = [objId, w, h];
+ 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()]);
+ this.handler.send('obj',
+ [objId, this.pageIndex, 'JpegStream', image.getIR()]);
return;
}
-
- PDFImage.buildImage(function(imageObj) {
- var imgData = imageObj.getImageData();
+ 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],
- null, [imgData.data.buffer]);
- }, self.handler, self.xref, resources, image, inline);
+ [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) {
+ operatorList,
+ stateManager) {
var smaskContent = smask.get('G');
var smaskOptions = {
subtype: smask.get('S').name,
backdrop: smask.get('BC')
};
-
- this.buildFormXObject(resources, smaskContent, smaskOptions,
- operatorList);
+ return this.buildFormXObject(resources, smaskContent, smaskOptions,
+ operatorList, stateManager.state.clone());
},
- handleTilingType: function PartialEvaluator_handleTilingType(
- fn, args, resources, pattern, patternDict,
- operatorList) {
+ handleTilingType:
+ function PartialEvaluator_handleTilingType(fn, args, resources,
+ pattern, patternDict,
+ operatorList) {
// Create an IR of the pattern code.
- var tilingOpList = this.getOperatorList(pattern,
- patternDict.get('Resources') || resources);
- // 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));
+ 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) {
-
+ 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;
- var font = this.loadFont(fontName, fontRef, this.xref, resources,
- operatorList);
- this.state.font = font;
- var loadedName = font.loadedName;
- if (!font.sent) {
- var fontData = font.translated.exportData();
-
- self.handler.send('commonobj', [
- loadedName,
- 'Font',
- fontData
- ]);
- font.sent = true;
- }
-
- return loadedName;
+ 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) {
- var font = this.state.font.translated;
+ handleText: function PartialEvaluator_handleText(chars, state) {
+ var font = state.font;
var glyphs = font.charsToGlyphs(chars);
- var isAddToPathSet = !!(this.state.textRenderingMode &
+ var isAddToPathSet = !!(state.textRenderingMode &
TextRenderingMode.ADD_TO_PATH_FLAG);
if (font.data && (isAddToPathSet || PDFJS.disableFontFace)) {
- for (var i = 0; i < glyphs.length; i++) {
- if (glyphs[i] === null) {
- continue;
- }
- var fontChar = glyphs[i].fontChar;
+ var buildPath = function (fontChar) {
if (!font.renderer.hasBuiltPath(fontChar)) {
var path = font.renderer.getPathJs(fontChar);
this.handler.send('commonobj', [
@@ -14679,6 +10894,21 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
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);
+ }
}
}
@@ -14686,12 +10916,15 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
},
setGState: function PartialEvaluator_setGState(resources, gState,
- operatorList, xref) {
-
+ operatorList, xref,
+ stateManager) {
+ // This array holds the converted/processed state data.
+ var gStateObj = [];
+ var gStateMap = gState.map;
var self = this;
- // TODO(mack): This should be rewritten so that this function returns
- // what should be added to the queue during each iteration
- function setGStateForKey(gStateObj, key, value) {
+ var promise = Promise.resolve();
+ for (var key in gStateMap) {
+ var value = gStateMap[key];
switch (key) {
case 'Type':
break;
@@ -14707,10 +10940,14 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
gStateObj.push([key, value]);
break;
case 'Font':
- var loadedName = self.handleSetFont(resources, null, value[0],
- operatorList);
- operatorList.addDependency(loadedName);
- gStateObj.push([key, [loadedName, value[1]]]);
+ 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]);
@@ -14722,7 +10959,10 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
}
var dict = xref.fetchIfRef(value);
if (isDict(dict)) {
- self.handleSMask(dict, resources, operatorList);
+ promise = promise.then(function () {
+ return self.handleSMask(dict, resources, operatorList,
+ stateManager);
+ });
gStateObj.push([key, true]);
} else {
warn('Unsupported SMask type');
@@ -14730,7 +10970,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
break;
// Only generate info log messages for the following since
- // they are unlikey to have a big impact on the rendering.
+ // they are unlikely to have a big impact on the rendering.
case 'OP':
case 'op':
case 'OPM':
@@ -14753,29 +10993,20 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
break;
}
}
-
- // This array holds the converted/processed state data.
- var gStateObj = [];
- var gStateMap = gState.map;
- for (var key in gStateMap) {
- var value = gStateMap[key];
- setGStateForKey(gStateObj, key, value);
- }
-
- operatorList.addOp(OPS.setGState, [gStateObj]);
+ return promise.then(function () {
+ if (gStateObj.length >= 0) {
+ operatorList.addOp(OPS.setGState, [gStateObj]);
+ }
+ });
},
loadFont: function PartialEvaluator_loadFont(fontName, font, xref,
- resources,
- parentOperatorList) {
+ resources) {
function errorFont() {
- return {
- translated: new ErrorFont('Font ' + fontName + ' is not available'),
- loadedName: 'g_font_error'
- };
+ 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));
@@ -14789,6 +11020,11 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
return errorFont();
}
}
+ if (!fontRef) {
+ warn('fontRef not available');
+ return errorFont();
+ }
+
if (this.fontCache.has(fontRef)) {
return this.fontCache.get(fontRef);
}
@@ -14797,140 +11033,216 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
if (!isDict(font)) {
return errorFont();
}
- // Workaround for bad PDF generators that doesn't reference fonts
+
+ // 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, font);
+ 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
+ // 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, '') : (fontRef.num + '_' + fontRef.gen));
+ 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);
- if (!font.translated) {
- var translated;
try {
- translated = this.translateFont(font, xref);
- } catch (e) {
- UnsupportedManager.notify(UNSUPPORTED_FEATURES.font);
- translated = new ErrorFont(e instanceof Error ? e.message : e);
- }
- font.translated = translated;
- }
+ // 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) { }
- if (font.translated.loadCharProcs) {
- var charProcs = font.get('CharProcs').getAll();
- var fontResources = font.get('Resources') || resources;
- var charProcKeys = Object.keys(charProcs);
- var charProcOperatorList = {};
- for (var i = 0, n = charProcKeys.length; i < n; ++i) {
- var key = charProcKeys[i];
- var glyphStream = charProcs[key];
- var operatorList = this.getOperatorList(glyphStream, fontResources);
- charProcOperatorList[key] = operatorList.getIR();
- if (!parentOperatorList) {
- continue;
- }
- // Add the dependencies to the parent operator list so they are
- // resolved before sub operator list is executed synchronously.
- parentOperatorList.addDependencies(charProcOperatorList.dependencies);
- }
- font.translated.charProcOperatorList = charProcOperatorList;
- font.loaded = true;
- } else {
- font.loaded = true;
+ 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 = [];
}
- return font;
+ 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,
- evaluatorState) {
+ initialState) {
var self = this;
var xref = this.xref;
- var handler = this.handler;
+ var imageCache = {};
- operatorList = operatorList || new OperatorList();
+ assert(operatorList);
- resources = resources || new Dict();
- var xobjs = resources.get('XObject') || new Dict();
- var patterns = resources.get('Pattern') || new Dict();
- var preprocessor = new EvaluatorPreprocessor(stream, xref);
- if (evaluatorState) {
- preprocessor.setState(evaluatorState);
- }
+ 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();
- var promise = new LegacyPromise();
- var operation;
- while ((operation = preprocessor.read())) {
+ 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) {
- case OPS.setStrokeColorN:
- case OPS.setFillColorN:
- if (args[args.length - 1].code) {
- break;
- }
- // 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) {
- self.handleTilingType(fn, args, resources, pattern, dict,
- operatorList);
- args = [];
- continue;
- } else if (typeNum == SHADING_PATTERN) {
- var shading = dict.get('Shading');
- var matrix = dict.get('Matrix');
- var pattern = Pattern.parseShading(shading, matrix, xref,
- resources);
- args = pattern.getIR();
- } else {
- error('Unkown PatternType ' + typeNum);
- }
- }
- break;
+ 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) {
- assertWellFormed(
- isStream(xobj), 'XObject should be a stream');
+ assert(isStream(xobj), 'XObject should be a stream');
var type = xobj.dict.get('Subtype');
- assertWellFormed(
- isName(type),
- 'XObject should have a Name subtype'
- );
+ assert(isName(type),
+ 'XObject should have a Name subtype');
- if ('Form' == type.name) {
- self.buildFormXObject(resources, xobj, null, operatorList,
- preprocessor.getState());
- args = [];
- continue;
- } else if ('Image' == type.name) {
+ 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);
- args = [];
+ 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);
@@ -14938,65 +11250,146 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
}
break;
case OPS.setFont:
+ var fontSize = args[1];
// eagerly collect all fonts
- var loadedName = self.handleSetFont(resources, args, null,
- operatorList);
- operatorList.addDependency(loadedName);
- args[0] = loadedName;
- break;
+ 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:
- self.buildPaintImageXObject(resources, args[0], true,
- operatorList);
- args = [];
- continue;
- case OPS.save:
- var old = this.state;
- this.stateStack.push(this.state);
- this.state = old.clone();
- break;
- case OPS.restore:
- var prev = this.stateStack.pop();
- if (prev) {
- this.state = prev;
+ var cacheKey = args[0].cacheKey;
+ if (cacheKey) {
+ var cacheEntry = imageCache[cacheKey];
+ if (cacheEntry !== undefined) {
+ operatorList.addOp(cacheEntry.fn, cacheEntry.args);
+ args = null;
+ continue;
+ }
}
- break;
+ self.buildPaintImageXObject(resources, args[0], true,
+ operatorList, cacheKey, imageCache);
+ args = null;
+ continue;
case OPS.showText:
- args[0] = this.handleText(args[0]);
+ args[0] = self.handleText(args[0], stateManager.state);
break;
case OPS.showSpacedText:
var arr = args[0];
+ var combinedGlyphs = [];
var arrLength = arr.length;
- for (var i = 0; i < arrLength; ++i) {
- if (isString(arr[i])) {
- arr[i] = this.handleText(arr[i]);
+ 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:
- args[0] = this.handleText(args[0]);
+ operatorList.addOp(OPS.nextLine);
+ args[0] = self.handleText(args[0], stateManager.state);
+ fn = OPS.showText;
break;
case OPS.nextLineSetSpacingShowText:
- args[2] = this.handleText(args[2]);
+ 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:
- this.state.textRenderingMode = args[0];
+ stateManager.state.textRenderingMode = args[0];
break;
- // Parse the ColorSpace data to a raw format.
+
case OPS.setFillColorSpace:
+ stateManager.state.fillColorSpace =
+ ColorSpace.parse(args[0], xref, resources);
+ continue;
case OPS.setStrokeColorSpace:
- args = [ColorSpace.parseToIR(args[0], xref, resources)];
+ 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)
+ if (!shadingRes) {
error('No shading resource found');
+ }
var shading = shadingRes.get(args[0].name);
- if (!shading)
+ if (!shading) {
error('No shading object found');
+ }
- var shadingFill = Pattern.parseShading(
- shading, null, xref, resources);
+ var shadingFill = Pattern.parseShading(shading, null, xref,
+ resources);
var patternIR = shadingFill.getIR();
args = [patternIR];
fn = OPS.shadingFill;
@@ -15005,63 +11398,225 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
var dictName = args[0];
var extGState = resources.get('ExtGState');
- if (!isDict(extGState) || !extGState.has(dictName.name))
+ if (!isDict(extGState) || !extGState.has(dictName.name)) {
break;
+ }
var gState = extGState.get(dictName.name);
- self.setGState(resources, gState, operatorList, xref);
- args = [];
+ 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;
- } // switch
-
+ case OPS.rectangle:
+ self.buildPath(operatorList, fn, args);
+ continue;
+ }
operatorList.addOp(fn, args);
- }
-
- // some pdf don't close all restores inside object/form
- // closing those for them
- for (var i = 0, ii = preprocessor.savedStatesDepth; i < ii; i++) {
- operatorList.addOp(OPS.restore, []);
- }
-
- return operatorList;
+ }
+ 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, textState) {
+ getTextContent: function PartialEvaluator_getTextContent(stream, resources,
+ stateManager) {
- textState = textState || new TextState();
+ stateManager = (stateManager || new StateManager(new TextState()));
- var bidiTexts = [];
+ var textContent = {
+ items: [],
+ styles: Object.create(null)
+ };
+ var bidiTexts = textContent.items;
var SPACE_FACTOR = 0.35;
var MULTI_SPACE_FACTOR = 1.5;
var self = this;
var xref = this.xref;
- function handleSetFont(fontName, fontRef) {
- return self.loadFont(fontName, fontRef, xref, resources, null);
- }
+ resources = (xref.fetchIfRef(resources) || Dict.empty);
- resources = xref.fetchIfRef(resources) || new Dict();
// 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);
- var res = resources;
+ var preprocessor = new EvaluatorPreprocessor(stream, xref, stateManager);
- var chunk = '';
- var font = null;
- var charSpace = 0, wordSpace = 0;
- var operation;
- while ((operation = preprocessor.read())) {
+ 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;
- var args = operation.args;
- switch (fn) {
- // TODO: Add support for SAVE/RESTORE and XFORM here.
+ args = operation.args;
+
+ switch (fn | 0) {
case OPS.setFont:
- font = handleSetFont(args[0].name).translated;
textState.fontSize = args[1];
- break;
+ return handleSetFont(args[0].name).then(function() {
+ next(resolve, reject);
+ }, reject);
case OPS.setTextRise:
textState.textRise = args[0];
break;
@@ -15072,153 +11627,176 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
textState.leading = args[0];
break;
case OPS.moveText:
- textState.translateTextMatrix(args[0], args[1]);
+ textState.translateTextLineMatrix(args[0], args[1]);
+ textState.textMatrix = textState.textLineMatrix.slice();
break;
case OPS.setLeadingMoveText:
textState.leading = -args[1];
- textState.translateTextMatrix(args[0], args[1]);
+ textState.translateTextLineMatrix(args[0], args[1]);
+ textState.textMatrix = textState.textLineMatrix.slice();
break;
case OPS.nextLine:
- textState.translateTextMatrix(0, -textState.leading);
+ textState.carriageReturn();
break;
case OPS.setTextMatrix:
- textState.setTextMatrix(args[0], args[1],
- args[2], args[3], args[4], args[5]);
+ 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:
- charSpace = args[0];
+ textState.charSpacing = args[0];
break;
case OPS.setWordSpacing:
- wordSpace = args[0];
+ textState.wordSpacing = args[0];
break;
case OPS.beginText:
- textState.initialiseTextObj();
+ 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') {
- chunk += fontCharsToUnicode(items[j], font);
- } else if (items[j] < 0 && font.spaceWidth > 0) {
- var fakeSpaces = -items[j] / font.spaceWidth;
- if (fakeSpaces > MULTI_SPACE_FACTOR) {
- fakeSpaces = Math.round(fakeSpaces);
- while (fakeSpaces--) {
- chunk += ' ';
+ 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(' ');
}
- } else if (fakeSpaces > SPACE_FACTOR) {
- chunk += ' ';
}
}
}
+ bidiTexts.push(runBidi(textChunk));
break;
case OPS.showText:
- chunk += fontCharsToUnicode(args[0], font);
+ bidiTexts.push(runBidi(buildTextGeometry(args[0])));
break;
case OPS.nextLineShowText:
- // For search, adding a extra white space for line breaks would be
- // better here, but that causes too much spaces in the
- // text-selection divs.
- chunk += fontCharsToUnicode(args[0], font);
+ textState.carriageReturn();
+ bidiTexts.push(runBidi(buildTextGeometry(args[0])));
break;
case OPS.nextLineSetSpacingShowText:
- // Note comment in "'"
- chunk += fontCharsToUnicode(args[2], font);
+ textState.wordSpacing = args[0];
+ textState.charSpacing = args[1];
+ textState.carriageReturn();
+ bidiTexts.push(runBidi(buildTextGeometry(args[2])));
break;
case OPS.paintXObject:
- // Set the chunk such that the following if won't add something
- // to the state.
- chunk = '';
-
if (args[0].code) {
break;
}
if (!xobjs) {
- xobjs = resources.get('XObject') || new Dict();
+ xobjs = (resources.get('XObject') || Dict.empty);
}
var name = args[0].name;
- var xobj = xobjs.get(name);
- if (!xobj)
+ if (xobjsCache.key === name) {
+ if (xobjsCache.texts) {
+ Util.appendToArray(bidiTexts, xobjsCache.texts.items);
+ Util.extendObj(textContent.styles, xobjsCache.texts.styles);
+ }
break;
- assertWellFormed(isStream(xobj), 'XObject should be a stream');
+ }
+
+ var xobj = xobjs.get(name);
+ if (!xobj) {
+ break;
+ }
+ assert(isStream(xobj), 'XObject should be a stream');
var type = xobj.dict.get('Subtype');
- assertWellFormed(
- isName(type),
- 'XObject should have a Name subtype'
- );
+ assert(isName(type),
+ 'XObject should have a Name subtype');
- if ('Form' !== type.name)
+ if ('Form' !== type.name) {
+ xobjsCache.key = name;
+ xobjsCache.texts = null;
break;
+ }
- var formTexts = this.getTextContent(
- xobj,
- xobj.dict.get('Resources') || resources,
- textState
- );
- Util.concatenateToArray(bidiTexts, formTexts);
- 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))
+ if (!isDict(extGState) || !extGState.has(dictName.name)) {
break;
+ }
- var gsState = extGState.get(dictName.name);
-
- for (var i = 0; i < gsState.length; i++) {
- if (gsState[i] === 'Font') {
- font = handleSetFont(args[0].name).translated;
+ 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
-
- if (chunk !== '') {
- var bidiResult = PDFJS.bidi(chunk, -1, font.vertical);
- var bidiText = {
- str: bidiResult.str,
- dir: bidiResult.dir
- };
- var renderParams = textState.calcRenderParams(preprocessor.ctm);
- bidiText.x = renderParams.renderMatrix[4] - (textState.fontSize *
- renderParams.vScale * Math.sin(renderParams.angle));
- bidiText.y = renderParams.renderMatrix[5] + (textState.fontSize *
- renderParams.vScale * Math.cos(renderParams.angle));
- var fontHeight = textState.fontSize * renderParams.vScale;
- var fontAscent = font.ascent ? font.ascent * fontHeight :
- font.descent ? (1 + font.descent) * fontHeight : fontHeight;
- bidiText.x = renderParams.renderMatrix[4] - (fontAscent *
- Math.sin(renderParams.angle));
- bidiText.y = renderParams.renderMatrix[5] + (fontAscent *
- Math.cos(renderParams.angle));
- if (bidiText.dir == 'ttb') {
- bidiText.x += renderParams.vScale / 2;
- bidiText.y -= renderParams.vScale;
- }
- bidiText.angle = renderParams.angle;
- bidiText.size = fontHeight;
- bidiTexts.push(bidiText);
-
- chunk = '';
- }
- } // while
-
- return bidiTexts;
+ } // 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, xref, properties);
-
+ 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');
@@ -15231,94 +11809,91 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
}
var cidToGidMap = dict.get('CIDToGIDMap');
- if (isStream(cidToGidMap))
+ if (isStream(cidToGidMap)) {
properties.cidToGidMap = this.readCidToGidMap(cidToGidMap);
+ }
}
// Based on 9.6.6 of the spec the encoding can come from multiple places
- // but should be prioritized in the following order:
- // 1. Encoding dictionary
- // 2. Encoding within font file (Type1 or Type1C)
- // 3. Default (depends on font type)
- // Differences applied to the above.
- // Note: we don't fill in the encoding from the font file(2) here but use
- // the flag overridableEncoding to signal that the font can override the
- // encoding if it has one built in.
- var overridableEncoding = true;
- var hasEncoding = false;
- var flags = properties.flags;
+ // 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 baseEncoding = 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 and has
- // Symbolic font name
- if (!!(flags & FontFlags.Symbolic)) {
- baseEncoding = !properties.file && /Symbol/i.test(properties.name) ?
- Encodings.SymbolSetEncoding : Encodings.MacRomanEncoding;
- }
+ var baseEncodingName = null;
+ var encoding;
if (dict.has('Encoding')) {
- var encoding = dict.get('Encoding');
+ encoding = dict.get('Encoding');
if (isDict(encoding)) {
- var baseName = encoding.get('BaseEncoding');
- if (baseName) {
- overridableEncoding = false;
- hasEncoding = true;
- baseEncoding = Encodings[baseName.name];
- }
-
+ baseEncodingName = encoding.get('BaseEncoding');
+ baseEncodingName = (isName(baseEncodingName) ?
+ baseEncodingName.name : null);
// Load the differences between the base and original
if (encoding.has('Differences')) {
- hasEncoding = true;
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))
+ if (isNum(data)) {
index = data;
- else
+ } else {
differences[index++] = data.name;
+ }
}
}
} else if (isName(encoding)) {
- overridableEncoding = false;
- hasEncoding = true;
- var currentEncoding = Encodings[encoding.name];
-
- // Some bad PDF files contain fonts whose encoding name is not among
- // the predefined encodings, causing baseEncoding to be undefined.
- // In this case, fallback to using the baseEncoding as defined above
- // and let the font override the encoding if one is available.
- if (currentEncoding) {
- baseEncoding = currentEncoding;
- } else {
- overridableEncoding = true;
- }
+ 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.baseEncoding = baseEncoding;
- properties.hasEncoding = hasEncoding;
- properties.overridableEncoding = overridableEncoding;
+ properties.baseEncodingName = baseEncodingName;
+ properties.dict = dict;
},
- readToUnicode: function PartialEvaluator_readToUnicode(toUnicode, xref,
- properties) {
- var cmapObj = toUnicode;
- var charToUnicode = [];
+ readToUnicode: function PartialEvaluator_readToUnicode(toUnicode) {
+ var cmap, cmapObj = toUnicode;
if (isName(cmapObj)) {
- var isIdentityMap = cmapObj.name.substr(0, 9) == 'Identity-';
- if (!isIdentityMap)
- error('ToUnicode file cmap translation not implemented');
+ cmap = CMapFactory.create(cmapObj,
+ { url: PDFJS.cMapUrl, packed: PDFJS.cMapPacked }, null).getMap();
+ return new ToUnicodeMap(cmap);
} else if (isStream(cmapObj)) {
- var cmap = CMapFactory.create(cmapObj).map;
+ cmap = CMapFactory.create(cmapObj,
+ { url: PDFJS.cMapUrl, packed: PDFJS.cMapPacked }, null).getMap();
// Convert UTF-16BE
- for (var i in cmap) {
- var token = cmap[i];
+ // 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);
@@ -15331,11 +11906,12 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
str.push(((w1 & 0x3ff) << 10) + (w2 & 0x3ff) + 0x10000);
}
cmap[i] = String.fromCharCode.apply(String, str);
- }
- return cmap;
+ });
+ return new ToUnicodeMap(cmap);
}
- return charToUnicode;
+ return null;
},
+
readCidToGidMap: function PartialEvaluator_readCidToGidMap(cidToGidStream) {
// Extract the encoding from the CIDToGIDMap
var glyphsData = cidToGidStream.getBytes();
@@ -15344,98 +11920,107 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
var result = [];
for (var j = 0, jj = glyphsData.length; j < jj; j++) {
var glyphID = (glyphsData[j++] << 8) | glyphsData[j];
- if (glyphID === 0)
+ if (glyphID === 0) {
continue;
-
+ }
var code = j >> 1;
result[code] = glyphID;
}
return result;
},
- extractWidths: function PartialEvaluator_extractWidths(dict,
- xref,
- descriptor,
- properties) {
+ 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;
- var widths = dict.get('W');
+ widths = dict.get('W');
if (widths) {
- for (var i = 0, ii = widths.length; i < ii; i++) {
- var start = widths[i++];
- var code = xref.fetchIfRef(widths[i]);
+ for (i = 0, ii = widths.length; i < ii; i++) {
+ start = widths[i++];
+ code = xref.fetchIfRef(widths[i]);
if (isArray(code)) {
- for (var j = 0, jj = code.length; j < jj; j++)
+ for (j = 0, jj = code.length; j < jj; j++) {
glyphsWidths[start++] = code[j];
+ }
} else {
var width = widths[++i];
- for (var j = start; j <= code; j++)
+ for (j = start; j <= code; j++) {
glyphsWidths[j] = width;
+ }
}
}
}
if (properties.vertical) {
- var vmetrics = dict.get('DW2') || [880, -1000];
+ var vmetrics = (dict.get('DW2') || [880, -1000]);
defaultVMetrics = [vmetrics[1], defaultWidth * 0.5, vmetrics[0]];
vmetrics = dict.get('W2');
if (vmetrics) {
- for (var i = 0, ii = vmetrics.length; i < ii; i++) {
- var start = vmetrics[i++];
- var code = xref.fetchIfRef(vmetrics[i]);
+ for (i = 0, ii = vmetrics.length; i < ii; i++) {
+ start = vmetrics[i++];
+ code = xref.fetchIfRef(vmetrics[i]);
if (isArray(code)) {
- for (var j = 0, jj = code.length; j < jj; j++)
+ 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 (var j = start; j <= code; j++)
+ for (j = start; j <= code; j++) {
glyphsVMetrics[j] = vmetric;
+ }
}
}
}
}
} else {
var firstChar = properties.firstChar;
- var widths = dict.get('Widths');
+ widths = dict.get('Widths');
if (widths) {
- var j = firstChar;
- for (var i = 0, ii = widths.length; i < ii; i++)
+ j = firstChar;
+ for (i = 0, ii = widths.length; i < ii; i++) {
glyphsWidths[j++] = widths[i];
- defaultWidth = parseFloat(descriptor.get('MissingWidth')) || 0;
+ }
+ 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 = metrics.widths;
+ glyphsWidths = this.buildCharCodeToWidth(metrics.widths,
+ properties);
defaultWidth = metrics.defaultWidth;
}
}
}
// Heuristic: detection of monospace font by checking all non-zero widths
- var isMonospace = true, firstWidth = defaultWidth;
+ var isMonospace = true;
+ var firstWidth = defaultWidth;
for (var glyph in glyphsWidths) {
var glyphWidth = glyphsWidths[glyph];
- if (!glyphWidth)
+ if (!glyphWidth) {
continue;
+ }
if (!firstWidth) {
firstWidth = glyphWidth;
continue;
}
- if (firstWidth != glyphWidth) {
+ if (firstWidth !== glyphWidth) {
isMonospace = false;
break;
}
}
- if (isMonospace)
+ if (isMonospace) {
properties.flags |= FontFlags.FixedPitch;
+ }
properties.defaultWidth = defaultWidth;
properties.widths = glyphsWidths;
@@ -15444,17 +12029,17 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
},
isSerifFont: function PartialEvaluator_isSerifFont(baseFontName) {
-
// Simulating descriptor flags attribute
var fontNameWoStyle = baseFontName.split('-')[0];
return (fontNameWoStyle in serifFonts) ||
- (fontNameWoStyle.search(/serif/gi) !== -1);
+ (fontNameWoStyle.search(/serif/gi) !== -1);
},
getBaseFontMetrics: function PartialEvaluator_getBaseFontMetrics(name) {
- var defaultWidth = 0, widths = [], monospace = false;
-
- var lookupName = stdFontMap[name] || 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
@@ -15481,44 +12066,113 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
};
},
- translateFont: function PartialEvaluator_translateFont(dict,
- xref) {
+ 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');
- assertWellFormed(isName(type), 'invalid font Subtype');
+ assert(isName(type), 'invalid font Subtype');
var composite = false;
- if (type.name == 'Type0') {
+ 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)
+ if (!df) {
error('Descendant fonts are not specified');
-
- dict = isArray(df) ? xref.fetchIfRef(df[0]) : df;
+ }
+ dict = (isArray(df) ? xref.fetchIfRef(df[0]) : df);
type = dict.get('Subtype');
- assertWellFormed(isName(type), 'invalid font Subtype');
+ assert(isName(type), 'invalid font Subtype');
composite = true;
}
- var maxCharIndex = composite ? 0xFFFF : 0xFF;
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);
+ }
+
+ 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.name == 'Type3') {
+ 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();
- descriptor.set('FontName', new Name(type.name));
+ 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))
+ if (!isName(baseFontName)) {
error('Base font is not specified');
+ }
// Using base font name as a font name.
baseFontName = baseFontName.name.replace(/[,_]/g, '-');
@@ -15526,14 +12180,14 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
// Simulating descriptor flags attribute
var fontNameWoStyle = baseFontName.split('-')[0];
- var flags = (
- this.isSerifFont(fontNameWoStyle) ? FontFlags.Serif : 0) |
+ var flags =
+ (this.isSerifFont(fontNameWoStyle) ? FontFlags.Serif : 0) |
(metrics.monospace ? FontFlags.FixedPitch : 0) |
(symbolsFonts[fontNameWoStyle] ? FontFlags.Symbolic :
- FontFlags.Nonsymbolic);
+ FontFlags.Nonsymbolic);
- var properties = {
- type: type.name,
+ properties = {
+ type: type,
name: baseFontName,
widths: metrics.widths,
defaultWidth: metrics.defaultWidth,
@@ -15542,7 +12196,8 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
lastChar: maxCharIndex
};
this.extractDataStructures(dict, dict, xref, properties);
-
+ properties.widths = this.buildCharCodeToWidth(metrics.widths,
+ properties);
return new Font(baseFontName, null, properties);
}
}
@@ -15552,47 +12207,52 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
// 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 firstChar = (dict.get('FirstChar') || 0);
+ var lastChar = (dict.get('LastChar') || maxCharIndex);
var fontName = descriptor.get('FontName');
var baseFont = dict.get('BaseFont');
- // Some bad pdf's have a string as the font name.
+ // Some bad PDFs have a string as the font name.
if (isString(fontName)) {
- fontName = new Name(fontName);
+ fontName = Name.get(fontName);
}
if (isString(baseFont)) {
- baseFont = new Name(baseFont);
+ baseFont = Name.get(baseFont);
}
- if (type.name !== 'Type3') {
+ 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;
+ fontName = (fontName || baseFont);
- assertWellFormed(isName(fontName), 'invalid font name');
+ 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)
+ if (subtype) {
subtype = subtype.name;
-
+ }
var length1 = fontFile.dict.get('Length1');
-
var length2 = fontFile.dict.get('Length2');
}
}
- var properties = {
- type: type.name,
+ properties = {
+ type: type,
name: fontName.name,
subtype: subtype,
file: fontFile,
@@ -15602,9 +12262,9 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
composite: composite,
wideChars: composite,
fixedPitch: false,
- fontMatrix: dict.get('FontMatrix') || FONT_IDENTITY_MATRIX,
+ fontMatrix: (dict.get('FontMatrix') || FONT_IDENTITY_MATRIX),
firstChar: firstChar || 0,
- lastChar: lastChar || maxCharIndex,
+ lastChar: (lastChar || maxCharIndex),
bbox: descriptor.get('FontBBox'),
ascent: descriptor.get('Ascent'),
descent: descriptor.get('Descent'),
@@ -15619,204 +12279,133 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
var cidEncoding = baseDict.get('Encoding');
if (isName(cidEncoding)) {
properties.cidEncoding = cidEncoding.name;
- properties.vertical = /-V$/.test(cidEncoding.name);
}
- properties.cmap = CMapFactory.create(cidEncoding);
+ properties.cMap = CMapFactory.create(cidEncoding,
+ { url: PDFJS.cMapUrl, packed: PDFJS.cMapPacked }, null);
+ properties.vertical = properties.cMap.vertical;
}
- this.extractWidths(dict, xref, descriptor, properties);
this.extractDataStructures(dict, baseDict, xref, properties);
+ this.extractWidths(dict, xref, descriptor, properties);
- if (type.name === 'Type3') {
- properties.coded = true;
+ if (type === 'Type3') {
+ properties.isType3Font = true;
}
return new Font(fontName.name, fontFile, properties);
}
};
- PartialEvaluator.optimizeQueue =
- function PartialEvaluator_optimizeQueue(queue) {
-
- function squash(array, index, howMany, element) {
- if (isArray(array)) {
- array.splice(index, howMany, element);
- } else {
- // Replace the element.
- array[index] = element;
- // Shift everything after the element up.
- var sub = array.subarray(index + howMany);
- array.set(sub, index + 1);
- }
- }
-
- var fnArray = queue.fnArray, argsArray = queue.argsArray;
- // grouping paintInlineImageXObject's into paintInlineImageXObjectGroup
- // searching for (save, transform, paintInlineImageXObject, restore)+
- var MIN_IMAGES_IN_INLINE_IMAGES_BLOCK = 10;
- var MAX_IMAGES_IN_INLINE_IMAGES_BLOCK = 200;
- var MAX_WIDTH = 1000;
- var IMAGE_PADDING = 1;
- for (var i = 0, ii = argsArray.length; i < ii; i++) {
- if (fnArray[i] === OPS.paintInlineImageXObject &&
- fnArray[i - 2] === OPS.save && fnArray[i - 1] === OPS.transform &&
- fnArray[i + 1] === OPS.restore) {
- var j = i - 2;
- for (i += 2; i < ii && fnArray[i - 4] === fnArray[i]; i++) {
- }
- var count = Math.min((i - j) >> 2,
- MAX_IMAGES_IN_INLINE_IMAGES_BLOCK);
- if (count < MIN_IMAGES_IN_INLINE_IMAGES_BLOCK) {
- continue;
- }
- // 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;
- for (var q = 0; q < count; q++) {
- var transform = argsArray[j + (q << 2) + 1];
- var img = argsArray[j + (q << 2) + 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 (var q = 0; q < count; q++) {
- var data = argsArray[j + (q << 2) + 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;
- }
- }
- // replacing queue items
- squash(fnArray, j, count * 4, OPS.paintInlineImageXObjectGroup);
- argsArray.splice(j, count * 4,
- [{width: imgWidth, height: imgHeight, data: imgData}, map]);
- i = j;
- ii = argsArray.length;
- }
- }
- // grouping paintImageMaskXObject's into paintImageMaskXObjectGroup
- // searching for (save, transform, paintImageMaskXObject, restore)+
- var MIN_IMAGES_IN_MASKS_BLOCK = 10;
- var MAX_IMAGES_IN_MASKS_BLOCK = 100;
- for (var i = 0, ii = argsArray.length; i < ii; i++) {
- if (fnArray[i] === OPS.paintImageMaskXObject &&
- fnArray[i - 2] === OPS.save && fnArray[i - 1] === OPS.transform &&
- fnArray[i + 1] === OPS.restore) {
- var j = i - 2;
- for (i += 2; i < ii && fnArray[i - 4] === fnArray[i]; i++) {
- }
- var count = Math.min((i - j) >> 2,
- MAX_IMAGES_IN_MASKS_BLOCK);
- if (count < MIN_IMAGES_IN_MASKS_BLOCK) {
- continue;
- }
- var images = [];
- for (var q = 0; q < count; q++) {
- var transform = argsArray[j + (q << 2) + 1];
- var maskParams = argsArray[j + (q << 2) + 2][0];
- images.push({data: maskParams.data, width: maskParams.width,
- height: maskParams.height, transform: transform});
- }
- // replacing queue items
- squash(fnArray, j, count * 4, OPS.paintImageMaskXObjectGroup);
- argsArray.splice(j, count * 4, [images]);
- i = j;
- ii = argsArray.length;
- }
- }
- };
-
return PartialEvaluator;
})();
-var OperatorList = (function OperatorListClosure() {
- var CHUNK_SIZE = 100;
-
- 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
- transfers.push(arg.data.buffer);
- break;
- }
+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;
}
- return transfers;
+ 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 OperatorList(messageHandler, pageIndex) {
+ 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;
- // When there isn't a message handler the fn array needs to be able to grow
- // since we can't flush the operators.
- if (messageHandler) {
- this.fnArray = new Uint8Array(CHUNK_SIZE);
- } else {
- this.fnArray = [];
- }
+ this.fnArray = [];
this.argsArray = [];
- this.dependencies = {},
+ this.dependencies = {};
this.pageIndex = pageIndex;
- this.fnIndex = 0;
+ 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) {
- this.fnArray[this.fnIndex++] = fn;
- this.argsArray.push(args);
- if (this.fnIndex >= CHUNK_SIZE) {
+ 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();
}
- } else {
- this.fnArray.push(fn);
- this.argsArray.push(args);
}
},
@@ -15850,7 +12439,9 @@ var OperatorList = (function OperatorListClosure() {
},
flush: function(lastChunk) {
- PartialEvaluator.optimizeQueue(this);
+ if (this.intent !== 'oplist') {
+ new QueueOptimizer().optimize(this);
+ }
var transfers = getTransfers(this);
this.messageHandler.send('RenderPageChunk', {
operatorList: {
@@ -15859,76 +12450,105 @@ var OperatorList = (function OperatorListClosure() {
lastChunk: lastChunk,
length: this.length
},
- pageIndex: this.pageIndex
- }, null, transfers);
- this.dependencies = [];
- this.fnIndex = 0;
- this.argsArray = [];
+ 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.textMatrix = [1, 0, 0, 1, 0, 0];
- this.stateStack = [];
- //textState variables
+ 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 = {
- initialiseTextObj: function TextState_initialiseTextObj() {
- var m = this.textMatrix;
- m[0] = 1, m[1] = 0, m[2] = 0, m[3] = 1, m[4] = 0, m[5] = 0;
- },
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;
+ 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];
},
- calcRenderParams: function TextState_calcRenderingParams(cm) {
- var tm = this.textMatrix;
- var a = this.fontSize;
- var b = a * this.textHScale;
- var c = this.textRise;
- var vScale = Math.sqrt((tm[2] * tm[2]) + (tm[3] * tm[3]));
- var angle = Math.atan2(tm[1], tm[0]);
- var m0 = tm[0] * cm[0] + tm[1] * cm[2];
- var m1 = tm[0] * cm[1] + tm[1] * cm[3];
- var m2 = tm[2] * cm[0] + tm[3] * cm[2];
- var m3 = tm[2] * cm[1] + tm[3] * cm[3];
- var m4 = tm[4] * cm[0] + tm[5] * cm[2] + cm[4];
- var m5 = tm[4] * cm[1] + tm[5] * cm[3] + cm[5];
- var renderMatrix = [
- b * m0,
- b * m1,
- a * m2,
- a * m3,
- c * m2 + m4,
- c * m3 + m5
- ];
- return {
- renderMatrix: renderMatrix,
- vScale: vScale,
- angle: angle
- };
+ 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() {
@@ -15938,7 +12558,7 @@ var EvalState = (function EvalStateClosure() {
return EvalState;
})();
-var EvaluatorPreprocessor = (function EvaluatorPreprocessor() {
+var EvaluatorPreprocessor = (function EvaluatorPreprocessorClosure() {
// Specifies properties for each command
//
// If variableArgs === true: [0, `numArgs`] expected
@@ -15998,7 +12618,7 @@ var EvaluatorPreprocessor = (function EvaluatorPreprocessor() {
TJ: { id: OPS.showSpacedText, numArgs: 1, variableArgs: false },
'\'': { id: OPS.nextLineShowText, numArgs: 1, variableArgs: false },
'"': { id: OPS.nextLineSetSpacingShowText, numArgs: 3,
- variableArgs: false },
+ variableArgs: false },
// Type3 fonts
d0: { id: OPS.setCharWidth, numArgs: 2, variableArgs: false },
@@ -16032,7 +12652,7 @@ var EvaluatorPreprocessor = (function EvaluatorPreprocessor() {
DP: { id: OPS.markPointProps, numArgs: 2, variableArgs: false },
BMC: { id: OPS.beginMarkedContent, numArgs: 1, variableArgs: false },
BDC: { id: OPS.beginMarkedContentProps, numArgs: 2,
- variableArgs: false },
+ variableArgs: false },
EMC: { id: OPS.endMarkedContent, numArgs: 0, variableArgs: false },
// Compatibility
@@ -16052,101 +12672,121 @@ var EvaluatorPreprocessor = (function EvaluatorPreprocessor() {
'null': null
};
- function EvaluatorPreprocessor(stream, xref) {
+ 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.ctm = new Float32Array([1, 0, 0, 1, 0, 0]);
- this.savedStates = [];
+ this.stateManager = stateManager;
+ this.nonProcessedArgs = [];
}
+
EvaluatorPreprocessor.prototype = {
get savedStatesDepth() {
- return this.savedStates.length;
+ return this.stateManager.stateStack.length;
},
- read: function EvaluatorPreprocessor_read() {
- var args = [];
+
+ // |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 (isEOF(obj)) {
- return null; // no more commands
- }
- if (!isCmd(obj)) {
- // argument
- if (obj !== null && obj !== undefined) {
- args.push(obj instanceof Dict ? obj.getAll() : obj);
- assertWellFormed(args.length <= 33, 'Too many arguments');
- }
- continue;
- }
-
- 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;
-
- // Validate the number of arguments for the command
- if (opSpec.variableArgs) {
- if (args.length > opSpec.numArgs) {
- info('Command ' + fn + ': expected [0,' + opSpec.numArgs +
- '] args, but received ' + args.length + ' args');
- }
- } else {
- if (args.length < opSpec.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 ' +
- opSpec.numArgs + ' args, but received ' + args.length +
- ' args; skipping');
- args = [];
+ 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;
- } else if (args.length > opSpec.numArgs) {
- info('Command ' + fn + ': expected ' + opSpec.numArgs +
- ' args, but received ' + args.length + ' args');
+ }
+
+ 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');
}
}
-
- // TODO figure out how to type-check vararg functions
-
- this.preprocessCommand(fn, args);
-
- return {fn: fn, args: args};
}
},
- getState: function EvaluatorPreprocessor_getState() {
- return {
- ctm: this.ctm
- };
- },
- setState: function EvaluatorPreprocessor_setState(state) {
- this.ctm = state.ctm;
- },
- preprocessCommand: function EvaluatorPreprocessor_preprocessCommand(fn,
- args) {
+
+ preprocessCommand:
+ function EvaluatorPreprocessor_preprocessCommand(fn, args) {
switch (fn | 0) {
case OPS.save:
- this.savedStates.push(this.getState());
+ this.stateManager.save();
break;
case OPS.restore:
- var previousState = this.savedStates.pop();
- if (previousState) {
- this.setState(previousState);
- }
+ this.stateManager.restore();
break;
case OPS.transform:
- var ctm = this.ctm;
- var m = new Float32Array(6);
- m[0] = ctm[0] * args[0] + ctm[2] * args[1];
- m[1] = ctm[1] * args[0] + ctm[3] * args[1];
- m[2] = ctm[0] * args[2] + ctm[2] * args[3];
- m[3] = ctm[1] * args[2] + ctm[3] * args[3];
- m[4] = ctm[0] * args[4] + ctm[2] * args[5] + ctm[4];
- m[5] = ctm[1] * args[4] + ctm[3] * args[5] + ctm[5];
- this.ctm = m;
+ this.stateManager.transform(args);
break;
}
}
@@ -16154,11 +12794,1352 @@ var EvaluatorPreprocessor = (function EvaluatorPreprocessor() {
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.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;
+ }
+ };
+ return CMap;
+})();
+
+// A special case of CMap, where the _map array implicitly has a length of
+// 65535 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
+ };
+
+ 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 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);
+ }
+ 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);
+ }
+ return cMap;
+ }
+ error('Encoding required.');
+ }
+ };
+})();
+
// Unicode Private Use Area
-var CMAP_GLYPH_OFFSET = 0xE000;
-var GLYPH_AREA_SIZE = 0x1900;
-var SYMBOLIC_FONT_GLYPH_OFFSET = 0xF000;
+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
@@ -16290,7 +14271,7 @@ var Encodings = {
'summation', 'product', 'pi', 'integral', 'ordfeminine', 'ordmasculine',
'Omega', 'ae', 'oslash', 'questiondown', 'exclamdown', 'logicalnot',
'radical', 'florin', 'approxequal', 'Delta', 'guillemotleft',
- 'guillemotright', 'ellipsis', '', 'Agrave', 'Atilde', 'Otilde', 'OE',
+ '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',
@@ -16342,7 +14323,7 @@ var Encodings = {
'guilsinglleft', 'OE', 'bullet', 'Zcaron', 'bullet', 'bullet', 'quoteleft',
'quoteright', 'quotedblleft', 'quotedblright', 'bullet', 'endash',
'emdash', 'tilde', 'trademark', 'scaron', 'guilsinglright', 'oe', 'bullet',
- 'zcaron', 'Ydieresis', '', 'exclamdown', 'cent', 'sterling',
+ 'zcaron', 'Ydieresis', 'space', 'exclamdown', 'cent', 'sterling',
'currency', 'yen', 'brokenbar', 'section', 'dieresis', 'copyright',
'ordfeminine', 'guillemotleft', 'logicalnot', 'hyphen', 'registered',
'macron', 'degree', 'plusminus', 'twosuperior', 'threesuperior', 'acute',
@@ -16395,7 +14376,7 @@ var Encodings = {
'parenrighttp', 'parenrightex', 'parenrightbt', 'bracketrighttp',
'bracketrightex', 'bracketrightbt', 'bracerighttp', 'bracerightmid',
'bracerightbt'],
- zapfDingbatsEncoding: ['', '', '', '', '', '', '', '', '', '', '', '', '', '',
+ ZapfDingbatsEncoding: ['', '', '', '', '', '', '', '', '', '', '', '', '', '',
'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
'space', 'a1', 'a2', 'a202', 'a3', 'a4', 'a5', 'a119', 'a118', 'a117',
'a11', 'a12', 'a13', 'a14', 'a15', 'a16', 'a105', 'a17', 'a18', 'a19',
@@ -16406,19 +14387,19 @@ var Encodings = {
'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', '', '', '', '', '', '', '', '', '', '', '', '', '',
- '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
- '', '', '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']
+ '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']
};
/**
@@ -16453,9 +14434,12 @@ var stdFontMap = {
'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',
@@ -16481,6 +14465,10 @@ var stdFontMap = {
* 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',
@@ -16505,6 +14493,7 @@ var nonStdFontMap = {
'MS-PMincho-Bold': 'MS PMincho-Bold',
'MS-PMincho-BoldItalic': 'MS PMincho-BoldItalic',
'MS-PMincho-Italic': 'MS PMincho-Italic',
+ 'Wingdings': 'ZapfDingbats'
};
var serifFonts = {
@@ -16558,43 +14547,12 @@ var symbolsFonts = {
'Dingbats': true, 'Symbol': true, 'ZapfDingbats': true
};
-var CMapConverterList = {
- 'H': jis7ToUnicode,
- 'V': jis7ToUnicode,
- 'EUC-H': eucjpToUnicode,
- 'EUC-V': eucjpToUnicode,
- '83pv-RKSJ-H': sjis83pvToUnicode,
- '90pv-RKSJ-H': sjis90pvToUnicode,
- '90ms-RKSJ-H': sjisToUnicode,
- '90ms-RKSJ-V': sjisToUnicode,
- '90msp-RKSJ-H': sjisToUnicode,
- '90msp-RKSJ-V': sjisToUnicode,
- 'GBK-EUC-H': gbkToUnicode,
- 'GBKp-EUC-H': gbkToUnicode,
- 'B5pc-H': big5ToUnicode,
- 'ETenms-B5-H': big5ToUnicode,
- 'ETenms-B5-V': big5ToUnicode,
-};
-
-// CMaps using Hankaku (Halfwidth) Latin glyphs instead of proportional one.
-// We need to distinguish them to get correct widths from CIDFont dicts.
-var HalfwidthCMaps = {
- 'H': true,
- 'V': true,
- 'EUC-H': true,
- 'EUC-V': true,
- '90ms-RKSJ-H': true,
- '90ms-RKSJ-V': true,
- 'UniJIS-UCS2-HW-H': true,
- 'UniJIS-UCS2-HW-V': 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': 173,
+ '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,
@@ -16618,7 +14576,12 @@ var GlyphMapForStandardFonts = {
'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, '305': 963,
+ '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,
@@ -16659,82 +14622,42 @@ var GlyphMapForStandardFonts = {
'3316': 578, '3379': 42785, '3393': 1159, '3416': 8377
};
-var decodeBytes;
-if (typeof TextDecoder !== 'undefined') {
- // The encodings supported by TextDecoder can be found at:
- // http://encoding.spec.whatwg.org/#concept-encoding-get
- decodeBytes = function(bytes, encoding, fatal) {
- return new TextDecoder(encoding, {fatal: !!fatal}).decode(bytes);
- };
-} else if (typeof FileReaderSync !== 'undefined') {
- decodeBytes = function(bytes, encoding) {
- return new FileReaderSync().readAsText(new Blob([bytes]), encoding);
- };
-} else {
- // Clear the list so that decodeBytes will never be called.
- CMapConverterList = {};
-}
-
-function jis7ToUnicode(str) {
- var bytes = stringToBytes(str);
- var length = bytes.length;
- for (var i = 0; i < length; ++i) {
- bytes[i] |= 0x80;
- }
- return decodeBytes(bytes, 'euc-jp');
-}
-
-function eucjpToUnicode(str) {
- return decodeBytes(stringToBytes(str), 'euc-jp');
-}
-
-function sjisToUnicode(str) {
- return decodeBytes(stringToBytes(str), 'shift_jis');
-}
-
-function sjis83pvToUnicode(str) {
- var bytes = stringToBytes(str);
- try {
- // TODO: 83pv has incompatible mappings in ed40..ee9c range.
- return decodeBytes(bytes, 'shift_jis', true);
- } catch (e) {
- warn('Unsupported 83pv character found');
- // Just retry without checking errors for now.
- return decodeBytes(bytes, 'shift_jis');
- }
-}
-
-function sjis90pvToUnicode(str) {
- var bytes = stringToBytes(str);
- try {
- // TODO: 90pv has incompatible mappings in 8740..879c and eb41..ee9c.
- return decodeBytes(bytes, 'shift_jis', true);
- } catch (e) {
- warn('Unsupported 90pv character found');
- // Just retry without checking errors for now.
- return decodeBytes(bytes, 'shift_jis');
- }
-}
-
-function gbkToUnicode(str) {
- return decodeBytes(stringToBytes(str), 'gbk');
-}
-
-function big5ToUnicode(str) {
- return decodeBytes(stringToBytes(str), 'big5');
-}
-
-// Some characters, e.g. copyrightserif, mapped to the private use area and
+// 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.
-function mapPrivateUseChars(code) {
- switch (code) {
- case 0xF8E9: // copyrightsans
- case 0xF6D9: // copyrightserif
- return 0x00A9; // copyright
- default:
- return code;
+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, // bracerightmid (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 = [
@@ -16904,28 +14827,25 @@ var MacStandardGlyphOrdering = [
function getUnicodeRangeFor(value) {
for (var i = 0, ii = UnicodeRanges.length; i < ii; i++) {
var range = UnicodeRanges[i];
- if (value >= range.begin && value < range.end)
+ 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)
+ if (value >= range.begin && value < range.end) {
return true;
+ }
range = UnicodeRanges[11];
- if (value >= range.begin && value < range.end)
+ if (value >= range.begin && value < range.end) {
return true;
+ }
return false;
}
-function isSpecialUnicode(unicode) {
- return (unicode <= 0x1F || (unicode >= 127 && unicode < GLYPH_AREA_SIZE)) ||
- (unicode >= CMAP_GLYPH_OFFSET &&
- unicode < CMAP_GLYPH_OFFSET + GLYPH_AREA_SIZE);
-}
-
// The normalization table is obtained by filtering the Unicode characters
// database with entries.
var NormalizedUnicodes = {
@@ -18311,29 +16231,14 @@ var NormalizedUnicodes = {
function reverseIfRtl(chars) {
var charsLength = chars.length;
//reverse an arabic ligature
- if (charsLength <= 1 || !isRTLRangeFor(chars.charCodeAt(0)))
+ 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 fontCharsToUnicode(charCodes, font) {
- var glyphs = font.charsToGlyphs(charCodes);
- var result = '';
- for (var i = 0, ii = glyphs.length; i < ii; i++) {
- var glyph = glyphs[i];
- if (!glyph)
- continue;
-
- var glyphUnicode = glyph.unicode;
- if (glyphUnicode in NormalizedUnicodes)
- glyphUnicode = NormalizedUnicodes[glyphUnicode];
- result += reverseIfRtl(glyphUnicode);
}
- return result;
+ var s = '';
+ for (var ii = charsLength - 1; ii >= 0; ii--) {
+ s += chars[ii];
+ }
+ return s;
}
function adjustWidths(properties) {
@@ -18349,6 +16254,254 @@ function adjustWidths(properties) {
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));
+ }
+ },
+
+ 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() {
+ error('should not access .length');
+ },
+
+ forEach: function (callback) {
+ for (var i = this.firstChar, ii = this.lastChar; i <= ii; i++) {
+ callback(i, i);
+ }
+ },
+
+ 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).
@@ -18359,13 +16512,15 @@ function adjustWidths(properties) {
*/
var Font = (function FontClosure() {
function Font(name, file, properties) {
+ var charCode, glyphName, fontChar;
this.name = name;
this.loadedName = properties.loadedName;
- this.coded = properties.coded;
- this.loadCharProcs = properties.coded;
+ 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];
@@ -18374,29 +16529,35 @@ var Font = (function FontClosure() {
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.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.hasEncoding = properties.hasEncoding;
- this.cmap = properties.cmap;
+ this.cMap = properties.cMap;
this.ascent = properties.ascent / PDF_GLYPH_SPACE_UNITS;
this.descent = properties.descent / PDF_GLYPH_SPACE_UNITS;
-
this.fontMatrix = properties.fontMatrix;
- if (properties.type == 'Type3') {
- this.encoding = properties.baseEncoding;
+
+ 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;
}
- // Trying to fix encoding using glyph CIDSystemInfo.
- this.loadCidToUnicode(properties);
this.cidEncoding = properties.cidEncoding;
this.vertical = properties.vertical;
if (this.vertical) {
@@ -18404,33 +16565,31 @@ var Font = (function FontClosure() {
this.defaultVMetrics = properties.defaultVMetrics;
}
- if (properties.toUnicode && properties.toUnicode.length > 0)
- this.toUnicode = properties.toUnicode;
- else
- this.rebuildToUnicode(properties);
+ 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.toFontChar = this.buildToFontChar(this.toUnicode);
-
- if (!file) {
+ 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 = fontName in stdFontMap;
+ 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);
+ 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);
+ 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;
-
- this.encoding = properties.baseEncoding;
- this.noUnicodeAdaptation = true;
if (isStandardFont && type === 'CIDFontType2' &&
properties.cidEncoding.indexOf('Identity-') === 0) {
// Standard fonts might be embedded as CID font without glyph mapping.
@@ -18439,20 +16598,86 @@ var Font = (function FontClosure() {
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 = 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
- var subtype = properties.subtype;
- if (subtype == 'Type1C' && (type != 'Type1' && type != 'MMType1'))
- type = 'Type1';
- if (subtype == 'CIDFontType0C' && type != 'CIDFontType0')
+ 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';
+ }
// XXX: Temporarily change the type for open type so we trigger a warning.
// This should be removed when we add support for open type.
if (subtype === 'OpenType') {
@@ -18461,11 +16686,14 @@ var Font = (function FontClosure() {
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') ?
+ var cff = (subtype === 'Type1C' || subtype === 'CIDFontType0C') ?
new CFFFont(file, properties) : new Type1Font(name, file, properties);
adjustWidths(properties);
@@ -18482,6 +16710,9 @@ var Font = (function FontClosure() {
// 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:
@@ -18490,6 +16721,7 @@ var Font = (function FontClosure() {
}
this.data = data;
+ this.fontType = getFontType(type, subtype);
// Transfer some properties again that could change during font conversion
this.fontMatrix = properties.fontMatrix;
@@ -18501,144 +16733,141 @@ var Font = (function FontClosure() {
this.loading = true;
}
- var numFonts = 0;
- function getUniqueName() {
- return 'pdfFont' + numFonts++;
+ Font.getFontID = (function () {
+ var ID = 1;
+ return function Font_getFontID() {
+ return String(ID++);
+ };
+ })();
+
+ function int16(b0, b1) {
+ return (b0 << 8) + b1;
}
- function stringToArray(str) {
- var array = [];
- for (var i = 0, ii = str.length; i < ii; ++i)
- array[i] = str.charCodeAt(i);
-
- return array;
- }
-
- function arrayToString(arr) {
- var str = '';
- for (var i = 0, ii = arr.length; i < ii; ++i)
- str += String.fromCharCode(arr[i]);
-
- return str;
- }
-
- function int16(bytes) {
- return (bytes[0] << 8) + (bytes[1] & 0xff);
- }
-
- function int32(bytes) {
- return (bytes[0] << 24) + (bytes[1] << 16) +
- (bytes[2] << 8) + (bytes[3] & 0xff);
- }
-
- function getMaxPower2(number) {
- var maxPower = 0;
- var value = number;
- while (value >= 2) {
- value /= 2;
- maxPower++;
- }
-
- value = 2;
- for (var i = 1; i < maxPower; i++)
- value *= 2;
- return value;
+ function int32(b0, b1, b2, b3) {
+ return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3;
}
function string16(value) {
- return String.fromCharCode((value >> 8) & 0xff) +
- String.fromCharCode(value & 0xff);
+ 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) +
- String.fromCharCode(value & 0xff);
+ value = (value > 0x7FFF ? 0x7FFF : (value < -0x8000 ? -0x8000 : value));
+ return String.fromCharCode((value >> 8) & 0xff, value & 0xff);
}
- function string32(value) {
- return String.fromCharCode((value >> 24) & 0xff) +
- String.fromCharCode((value >> 16) & 0xff) +
- String.fromCharCode((value >> 8) & 0xff) +
- String.fromCharCode(value & 0xff);
+ function isTrueTypeFile(file) {
+ var header = file.peekBytes(4);
+ return readUint32(header, 0) === 0x00010000;
}
- function createOpenTypeHeader(sfnt, file, numTables) {
- // Windows hates the Mac TrueType sfnt version number
- if (sfnt == 'true')
- sfnt = string32(0x00010000);
+ /**
+ * 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 isCidFontType2 = (properties.type === 'CIDFontType2');
+ 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) {
+ if (toUnicode.get(originalCharCode) !== undefined) {
+ var unicode = toUnicode.get(fontCharCode);
+ // TODO: Try to map ligatures to the correct spot.
+ if (unicode.length === 1) {
+ fontCharCode = unicode.charCodeAt(0);
+ }
+ } else if (isCidFontType2) {
+ // For CIDFontType2, move characters not present in toUnicode
+ // to the private use area (fixes bug 1028735 and issue 4881).
+ fontCharCode = nextAvailableFontCharCode;
+ }
+ }
+ // 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 ||
+ fontCharCode <= 0x1f || // Control chars
+ fontCharCode === 0x7F || // Control char
+ fontCharCode === 0xAD || // Soft hyphen
+ fontCharCode === 0xA0 || // Non breaking space
+ (fontCharCode >= 0x80 && fontCharCode <= 0x9F) || // Control chars
+ // Prevent drawing characters in the specials unicode block.
+ (fontCharCode >= 0xFFF0 && fontCharCode <= 0xFFFF) ||
+ (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++;
- // sfnt version (4 bytes)
- var header = sfnt;
+ if (SKIP_PRIVATE_USE_RANGE_F000_TO_F01F && fontCharCode === 0xF000) {
+ fontCharCode = 0xF020;
+ nextAvailableFontCharCode = fontCharCode + 1;
+ }
- // numTables (2 bytes)
- header += string16(numTables);
+ } while (usedFontCharCodes[fontCharCode] !== undefined &&
+ nextAvailableFontCharCode <= PRIVATE_USE_OFFSET_END);
+ }
- // searchRange (2 bytes)
- var tablesMaxPower2 = getMaxPower2(numTables);
- var searchRange = tablesMaxPower2 * 16;
- header += string16(searchRange);
-
- // entrySelector (2 bytes)
- header += string16(Math.log(tablesMaxPower2) / Math.log(2));
-
- // rangeShift (2 bytes)
- header += string16(numTables * 16 - searchRange);
-
- file.file += header;
- file.virtualOffset += header.length;
+ newMap[fontCharCode] = glyphId;
+ toFontChar[originalCharCode] = fontCharCode;
+ usedFontCharCodes[fontCharCode] = true;
+ }
+ return {
+ toFontChar: toFontChar,
+ charCodeToGlyphId: newMap,
+ nextAvailableFontCharCode: nextAvailableFontCharCode
+ };
}
- function createTableEntry(file, tag, data) {
- // offset
- var offset = file.virtualOffset;
-
- // length
- var length = data.length;
-
- // Per spec tables must be 4-bytes align so add padding as needed
- while (data.length & 3)
- data.push(0x00);
-
- while (file.virtualOffset & 3)
- file.virtualOffset++;
-
- // checksum
- var checksum = 0, n = data.length;
- for (var i = 0; i < n; i += 4)
- checksum = (checksum + int32([data[i], data[i + 1], data[i + 2],
- data[i + 3]])) | 0;
-
- var tableEntry = (tag + string32(checksum) +
- string32(offset) + string32(length));
- file.file += tableEntry;
- file.virtualOffset += data.length;
- }
-
- function getRanges(glyphs, deltas) {
+ function getRanges(glyphs) {
// Array.sort() sorts by characters, not numerically, so convert to an
// array of characters.
var codes = [];
- var length = glyphs.length;
- for (var n = 0; n < length; ++n)
- codes.push({ unicode: glyphs[n].unicode, code: n });
+ for (var charCode in glyphs) {
+ codes.push({ fontCharCode: charCode | 0, glyphId: glyphs[charCode] });
+ }
codes.sort(function fontGetRangesSort(a, b) {
- return a.unicode - b.unicode;
+ 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].unicode;
- var codeIndices = [deltas ? deltas[codes[n].code] : codes[n].code + 1];
+ var start = codes[n].fontCharCode;
+ var codeIndices = [codes[n].glyphId];
++n;
var end = start;
- while (n < length && end + 1 == codes[n].unicode) {
- codeIndices.push(deltas ? deltas[codes[n].code] : codes[n].code + 1);
+ while (n < length && end + 1 === codes[n].fontCharCode) {
+ codeIndices.push(codes[n].glyphId);
++end;
++n;
- if (end === 0xFFFF) { break; }
+ if (end === 0xFFFF) {
+ break;
+ }
}
ranges.push([start, end, codeIndices]);
}
@@ -18646,9 +16875,8 @@ var Font = (function FontClosure() {
return ranges;
}
- function createCmapTable(glyphs, deltas) {
- var ranges = getRanges(glyphs, deltas);
-
+ 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
@@ -18656,7 +16884,8 @@ var Font = (function FontClosure() {
'\x00\x01' + // encodingID
string32(4 + numTables * 8); // start of the table record
- for (var i = ranges.length - 1; i >= 0; --i) {
+ var i, ii, j, jj;
+ for (i = ranges.length - 1; i >= 0; --i) {
if (ranges[i][0] <= 0xFFFF) { break; }
}
var bmpLength = i + 1;
@@ -18666,10 +16895,7 @@ var Font = (function FontClosure() {
}
var trailingRangesCount = ranges[i][1] < 0xFFFF ? 1 : 0;
var segCount = bmpLength + trailingRangesCount;
- var segCount2 = segCount * 2;
- var searchRange = getMaxPower2(segCount) * 2;
- var searchEntry = Math.log(segCount) / Math.log(2);
- var rangeShift = 2 * segCount - searchRange;
+ var searchParams = OpenTypeFileBuilder.getSearchParams(segCount, 2);
// Fill up the 4 parallel arrays describing the segments.
var startCount = '';
@@ -18679,15 +16905,16 @@ var Font = (function FontClosure() {
var glyphsIds = '';
var bias = 0;
- for (var i = 0, ii = bmpLength; i < ii; i++) {
- var range = ranges[i];
- var start = range[0];
- var end = range[1];
+ 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);
- var codes = range[2];
+ codes = range[2];
var contiguous = true;
- for (var j = 1, jj = codes.length; j < jj; ++j) {
+ for (j = 1, jj = codes.length; j < jj; ++j) {
if (codes[j] !== codes[j - 1] + 1) {
contiguous = false;
break;
@@ -18700,7 +16927,7 @@ var Font = (function FontClosure() {
idDeltas += string16(0);
idRangeOffsets += string16(offset);
- for (var j = 0, jj = codes.length; j < jj; ++j) {
+ for (j = 0, jj = codes.length; j < jj; ++j) {
glyphsIds += string16(codes[j]);
}
} else {
@@ -18719,10 +16946,10 @@ var Font = (function FontClosure() {
}
var format314 = '\x00\x00' + // language
- string16(segCount2) +
- string16(searchRange) +
- string16(searchEntry) +
- string16(rangeShift) +
+ string16(2 * segCount) +
+ string16(searchParams.range) +
+ string16(searchParams.entry) +
+ string16(searchParams.rangeShift) +
endCount + '\x00\x00' + startCount +
idDeltas + idRangeOffsets + glyphsIds;
@@ -18734,14 +16961,14 @@ var Font = (function FontClosure() {
string32(4 + numTables * 8 +
4 + format314.length); // start of the table record
format31012 = '';
- for (var i = 0, ii = ranges.length; i < ii; i++) {
- var range = ranges[i];
- var start = range[0];
- var codes = range[2];
+ for (i = 0, ii = ranges.length; i < ii; i++) {
+ range = ranges[i];
+ start = range[0];
+ codes = range[2];
var code = codes[0];
- for (var j = 1, jj = codes.length; j < jj; ++j) {
+ for (j = 1, jj = codes.length; j < jj; ++j) {
if (codes[j] !== codes[j - 1] + 1) {
- var end = range[0] + j - 1;
+ end = range[0] + j - 1;
format31012 += string32(start) + // startCharCode
string32(end) + // endCharCode
string32(code); // startGlyphID
@@ -18760,29 +16987,28 @@ var Font = (function FontClosure() {
string32(format31012.length / 12); // nGroups
}
- return stringToArray(cmap +
- '\x00\x04' + // format
- string16(format314.length + 4) + // length
- format314 + header31012 + format31012);
+ return cmap + '\x00\x04' + // format
+ string16(format314.length + 4) + // length
+ format314 + header31012 + format31012;
}
function validateOS2Table(os2) {
var stream = new Stream(os2.data);
- var version = int16(stream.getBytes(2));
+ 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 = int16(stream.getBytes(2));
+ var selection = stream.getUint16();
if (version < 4 && (selection & 0x0300)) {
return false;
}
- var firstChar = int16(stream.getBytes(2));
- var lastChar = int16(stream.getBytes(2));
+ var firstChar = stream.getUint16();
+ var lastChar = stream.getUint16();
if (firstChar > lastChar) {
return false;
}
stream.getBytes(6); // skipping sTypoAscender/Descender/LineGap
- var usWinAscent = int16(stream.getBytes(2));
+ var usWinAscent = stream.getUint16();
if (usWinAscent === 0) { // makes font unreadable by windows
return false;
}
@@ -18810,12 +17036,14 @@ var Font = (function FontClosure() {
var lastCharIndex = 0;
if (charstrings) {
- for (var i = 0; i < charstrings.length; ++i) {
- var code = charstrings[i].unicode;
- if (firstCharIndex > code || !firstCharIndex)
+ for (var code in charstrings) {
+ code |= 0;
+ if (firstCharIndex > code || !firstCharIndex) {
firstCharIndex = code;
- if (lastCharIndex < code)
+ }
+ if (lastCharIndex < code) {
lastCharIndex = code;
+ }
var position = getUnicodeRangeFor(code);
if (position < 32) {
@@ -18837,18 +17065,18 @@ var Font = (function FontClosure() {
}
var bbox = properties.bbox || [0, 0, 0, 0];
- var unitsPerEm = override.unitsPerEm ||
- 1 / (properties.fontMatrix || FONT_IDENTITY_MATRIX)[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 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]));
+ 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
}
@@ -18899,15 +17127,15 @@ var Font = (function FontClosure() {
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
+ 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) {
@@ -18931,13 +17159,15 @@ var Font = (function FontClosure() {
// Mac want 1-byte per character strings while Windows want
// 2-bytes per character, so duplicate the names table
var stringsUnicode = [];
- for (var i = 0, ii = strings.length; i < ii; i++) {
- var str = proto[1][i] || strings[i];
+ var i, ii, j, jj, str;
+ for (i = 0, ii = strings.length; i < ii; i++) {
+ str = proto[1][i] || strings[i];
- var strUnicode = '';
- for (var j = 0, jj = str.length; j < jj; j++)
- strUnicode += string16(str.charCodeAt(j));
- stringsUnicode.push(strUnicode);
+ 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];
@@ -18953,10 +17183,10 @@ var Font = (function FontClosure() {
// Build the name records field
var strOffset = 0;
- for (var i = 0, ii = platforms.length; i < ii; i++) {
+ for (i = 0, ii = platforms.length; i < ii; i++) {
var strs = names[i];
- for (var j = 0, jj = strs.length; j < jj; j++) {
- var str = strs[j];
+ for (j = 0, jj = strs.length; j < jj; j++) {
+ str = strs[j];
var nameRecord =
platforms[i] + // platform ID
encodings[i] + // encoding ID
@@ -18973,37 +17203,6 @@ var Font = (function FontClosure() {
return nameTable;
}
- // Normalize the charcodes in the cmap table into unicode values
- // that will work with the (3, 1) cmap table we will write out.
- function cmapCharcodeToUnicode(charcode, symbolic, platformId, encodingId) {
- var unicode;
- if (symbolic) {
- // These codes will be shifted into the range
- // SYMBOLIC_FONT_GLYPH_OFFSET to (SYMBOLIC_FONT_GLYPH_OFFSET + 0xFF)
- // so that they are not in the control character range that could
- // be displayed as spaces by browsers.
- if (platformId === 3 && encodingId === 0 ||
- platformId === 1 && encodingId === 0) {
- unicode = SYMBOLIC_FONT_GLYPH_OFFSET | (charcode & 0xFF);
- }
- } else {
- if (platformId === 3 && encodingId === 1) {
- // A (3, 1) table is alredy unicode (Microsoft Unicode format)
- unicode = charcode;
- } else if (platformId === 1 && encodingId === 0) {
- // TODO(mack): Should apply the changes to convert the
- // MacRomanEncoding to Mac OS Roman encoding in 9.6.6.4
- // table 115 of the pdf spec
- var glyphName = Encodings.MacRomanEncoding[charcode];
- if (glyphName) {
- unicode = GlyphsUnicode[glyphName];
- }
- }
- }
- return unicode;
- }
-
-
Font.prototype = {
name: null,
font: null,
@@ -19017,23 +17216,20 @@ var Font = (function FontClosure() {
exportData: function Font_exportData() {
var data = {};
for (var i in this) {
- if (this.hasOwnProperty(i))
+ if (this.hasOwnProperty(i)) {
data[i] = this[i];
+ }
}
return data;
},
checkAndRepair: function Font_checkAndRepair(name, font, properties) {
function readTableEntry(file) {
- var tag = file.getBytes(4);
- tag = String.fromCharCode(tag[0]) +
- String.fromCharCode(tag[1]) +
- String.fromCharCode(tag[2]) +
- String.fromCharCode(tag[3]);
+ var tag = bytesToString(file.getBytes(4));
- var checksum = int32(file.getBytes(4));
- var offset = int32(file.getBytes(4));
- var length = int32(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;
@@ -19042,7 +17238,7 @@ var Font = (function FontClosure() {
var data = file.getBytes(length);
file.pos = previousPosition;
- if (tag == 'head') {
+ if (tag === 'head') {
// clearing checksum adjustment
data[8] = data[9] = data[10] = data[11] = 0;
data[17] |= 0x20; //Set font optimized for cleartype flag
@@ -19059,116 +17255,57 @@ var Font = (function FontClosure() {
function readOpenTypeHeader(ttf) {
return {
- version: arrayToString(ttf.getBytes(4)),
- numTables: int16(ttf.getBytes(2)),
- searchRange: int16(ttf.getBytes(2)),
- entrySelector: int16(ttf.getBytes(2)),
- rangeShift: int16(ttf.getBytes(2))
+ version: bytesToString(ttf.getBytes(4)),
+ numTables: ttf.getUint16(),
+ searchRange: ttf.getUint16(),
+ entrySelector: ttf.getUint16(),
+ rangeShift: ttf.getUint16()
};
}
- function createGlyphNameMap(glyphs, ids, properties) {
- var glyphNames = properties.glyphNames;
- if (!glyphNames) {
- properties.glyphNameMap = {};
- return;
- }
- var glyphsLength = glyphs.length;
- var glyphNameMap = {};
- var encoding = [];
- for (var i = 0; i < glyphsLength; ++i) {
- var glyphName = glyphNames[ids[i]];
- if (!glyphName)
- continue;
- var unicode = glyphs[i].unicode;
- glyphNameMap[glyphName] = unicode;
- var code = glyphs[i].code;
- encoding[code] = glyphName;
- }
- properties.glyphNameMap = glyphNameMap;
- if (properties.overridableEncoding)
- properties.baseEncoding = encoding;
- }
-
/**
* Read the appropriate subtable from the cmap according to 9.6.6.4 from
* PDF spec
*/
- function readCmapTable(cmap, font, hasEncoding, isSymbolicFont) {
+ function readCmapTable(cmap, font, isSymbolicFont) {
+ var segment;
var start = (font.start ? font.start : 0) + cmap.offset;
font.pos = start;
- var version = int16(font.getBytes(2));
- var numTables = int16(font.getBytes(2));
+ var version = font.getUint16();
+ var numTables = font.getUint16();
var potentialTable;
- var foundPreferredTable;
- // There's an order of preference in terms of which cmap subtable we
- // want to use. So scan through them to find our preferred table.
+ 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 = int16(font.getBytes(2));
- var encodingId = int16(font.getBytes(2));
- var offset = int32(font.getBytes(4));
+ var platformId = font.getUint16();
+ var encodingId = font.getUint16();
+ var offset = font.getInt32() >>> 0;
var useTable = false;
- var canBreak = false;
- // The following block implements the following from the spec:
- //
- // When the font has no Encoding entry, or the font descriptor’s
- // Symbolic flag is set (in which case the Encoding entry
- // is ignored), this shall occur:
- // - If the font contains a (3, 0) subtable, the range of
- // - Otherwise, the (1, 0) subtable will be used.
- // Otherwise, if the font does have an encoding:
- // - Use the (3, 1) cmap subtable
- // - Otherwise, use the (1, 0) subtable if present
- //
- // The following diverges slightly from the above spec in order
- // to handle the case that hasEncoding and isSymbolicFont are both
- // true. In this, based on the ordering of the rules in the spec,
- // my interpretation is that we should be acting as if the font is
- // symbolic.
- //
- // However, in this case, the test pdf 'preistabelle.pdf'
- // is interpreting this case as a non-symbolic font. In this case
- // though, 'presitabelle.pdf' does contain a (3, 1) table and does
- // not contain a (3, 0) table which indicates it is non-symbolic.
- //
- // Thus, I am using this heurisitic of looking at which table is
- // found to truly determine whether or not the font is symbolic.
- // That is, if the specific symbolic/non-symbolic font specific
- // tables (3, 0) or (3, 1) is found, that information is used for
- // deciding if the font is symbolic or not.
- //
- // TODO(mack): This section needs some more thought on whether the
- // heuristic is good enough. For now, it passes all the regression
- // tests.
- if (isSymbolicFont && platformId === 3 && encodingId === 0) {
+ if (platformId === 1 && encodingId === 0) {
+ useTable = true;
+ // Continue the loop since there still may be a higher priority
+ // table.
+ } else if (!isSymbolicFont && platformId === 3 && encodingId === 1) {
useTable = true;
canBreak = true;
- foundPreferredTable = true;
- } else if (hasEncoding && platformId === 3 && encodingId === 1) {
+ } else if (isSymbolicFont && platformId === 3 && encodingId === 0) {
useTable = true;
canBreak = true;
- foundPreferredTable = true;
- // Update the isSymbolicFont based on this heuristic
- isSymbolicFont = false;
- } else if (platformId === 1 && encodingId === 0 &&
- !foundPreferredTable) {
- useTable = true;
- foundPreferredTable = true;
- } else if (!potentialTable) {
- // We will use an arbitrary table if we cannot find a preferred
- // table
- useTable = true;
}
if (useTable) {
potentialTable = {
platformId: platformId,
encodingId: encodingId,
- offset: offset,
- isSymbolicFont: isSymbolicFont
+ offset: offset
};
}
if (canBreak) {
@@ -19177,35 +17314,33 @@ var Font = (function FontClosure() {
}
if (!potentialTable) {
- error('Could not find a cmap table');
- return;
- }
-
- if (!foundPreferredTable) {
- warn('Did not find a cmap of suitable format. Interpreting (' +
- potentialTable.platformId + ', ' + potentialTable.encodingId +
- ') as (3, 1) table');
- potentialTable.platformId = 3;
- potentialTable.encodingId = 1;
+ warn('Could not find a preferred cmap table.');
+ return {
+ platformId: -1,
+ encodingId: -1,
+ mappings: [],
+ hasShortCmap: false
+ };
}
font.pos = start + potentialTable.offset;
- var format = int16(font.getBytes(2));
- var length = int16(font.getBytes(2));
- var language = int16(font.getBytes(2));
+ 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 (var j = 0; j < 256; j++) {
+ for (j = 0; j < 256; j++) {
var index = font.getByte();
if (!index) {
continue;
}
mappings.push({
- charcode: j,
+ charCode: j,
glyphId: index
});
}
@@ -19213,25 +17348,25 @@ var Font = (function FontClosure() {
} else if (format === 4) {
// re-creating the table in format 4 since the encoding
// might be changed
- var segCount = (int16(font.getBytes(2)) >> 1);
+ var segCount = (font.getUint16() >> 1);
font.getBytes(6); // skipping range fields
var segIndex, segments = [];
for (segIndex = 0; segIndex < segCount; segIndex++) {
- segments.push({ end: int16(font.getBytes(2)) });
+ segments.push({ end: font.getUint16() });
}
- font.getBytes(2);
+ font.getUint16();
for (segIndex = 0; segIndex < segCount; segIndex++) {
- segments[segIndex].start = int16(font.getBytes(2));
+ segments[segIndex].start = font.getUint16();
}
for (segIndex = 0; segIndex < segCount; segIndex++) {
- segments[segIndex].delta = int16(font.getBytes(2));
+ segments[segIndex].delta = font.getUint16();
}
var offsetsCount = 0;
for (segIndex = 0; segIndex < segCount; segIndex++) {
- var segment = segments[segIndex];
- var rangeOffset = int16(font.getBytes(2));
+ segment = segments[segIndex];
+ var rangeOffset = font.getUint16();
if (!rangeOffset) {
segment.offsetIndex = -1;
continue;
@@ -19240,53 +17375,53 @@ var Font = (function FontClosure() {
var offsetIndex = (rangeOffset >> 1) - (segCount - segIndex);
segment.offsetIndex = offsetIndex;
offsetsCount = Math.max(offsetsCount, offsetIndex +
- segment.end - segment.start + 1);
+ segment.end - segment.start + 1);
}
var offsets = [];
- for (var j = 0; j < offsetsCount; j++) {
- offsets.push(int16(font.getBytes(2)));
+ for (j = 0; j < offsetsCount; j++) {
+ offsets.push(font.getUint16());
}
for (segIndex = 0; segIndex < segCount; segIndex++) {
- var segment = segments[segIndex];
- var start = segment.start, end = segment.end;
- var delta = segment.delta, offsetIndex = segment.offsetIndex;
+ segment = segments[segIndex];
+ start = segment.start;
+ var end = segment.end;
+ var delta = segment.delta;
+ offsetIndex = segment.offsetIndex;
- for (var j = start; j <= end; j++) {
- if (j == 0xFFFF) {
+ for (j = start; j <= end; j++) {
+ if (j === 0xFFFF) {
continue;
}
- var glyphId = offsetIndex < 0 ? j :
- offsets[offsetIndex + j - start];
+ glyphId = (offsetIndex < 0 ?
+ j : offsets[offsetIndex + j - start]);
glyphId = (glyphId + delta) & 0xFFFF;
if (glyphId === 0) {
continue;
}
mappings.push({
- charcode: j,
+ charCode: j,
glyphId: glyphId
});
}
}
- } else if (format == 6) {
+ } 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 = int16(font.getBytes(2));
- var entryCount = int16(font.getBytes(2));
+ var firstCode = font.getUint16();
+ var entryCount = font.getUint16();
- var glyphs = [];
- var ids = [];
- for (var j = 0; j < entryCount; j++) {
- var glyphId = int16(font.getBytes(2));
- var charcode = firstCode + j;
+ for (j = 0; j < entryCount; j++) {
+ glyphId = font.getUint16();
+ var charCode = firstCode + j;
mappings.push({
- charcode: charcode,
+ charCode: charCode,
glyphId: glyphId
});
}
@@ -19296,10 +17431,10 @@ var Font = (function FontClosure() {
// removing duplicate entries
mappings.sort(function (a, b) {
- return a.charcode - b.charcode;
+ return a.charCode - b.charCode;
});
- for (var i = 1; i < mappings.length; i++) {
- if (mappings[i - 1].charcode === mappings[i].charcode) {
+ for (i = 1; i < mappings.length; i++) {
+ if (mappings[i - 1].charCode === mappings[i].charCode) {
mappings.splice(i, 1);
i--;
}
@@ -19308,7 +17443,6 @@ var Font = (function FontClosure() {
return {
platformId: potentialTable.platformId,
encodingId: potentialTable.encodingId,
- isSymbolicFont: potentialTable.isSymbolicFont,
mappings: mappings,
hasShortCmap: hasShortCmap
};
@@ -19324,7 +17458,7 @@ var Font = (function FontClosure() {
font.pos = (font.start ? font.start : 0) + header.offset;
font.pos += header.length - 2;
- var numOfMetrics = int16(font.getBytes(2));
+ var numOfMetrics = font.getUint16();
if (numOfMetrics > numGlyphs) {
info('The numOfMetrics (' + numOfMetrics + ') should not be ' +
@@ -19340,13 +17474,12 @@ var Font = (function FontClosure() {
((metrics.length - numOfMetrics * 4) >> 1);
if (numMissing > 0) {
- font.pos = (font.start ? font.start : 0) + metrics.offset;
- var entries = '';
- for (var i = 0, ii = metrics.length; i < ii; i++)
- entries += String.fromCharCode(font.getByte());
- for (var i = 0; i < numMissing; i++)
- entries += '\x00\x00';
- metrics.data = stringToArray(entries);
+ // 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;
}
}
@@ -19364,8 +17497,8 @@ var Font = (function FontClosure() {
return glyf.length;
}
- var j = 10, flagsCount = 0;
- for (var i = 0; i < contoursCount; i++) {
+ 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;
@@ -19377,7 +17510,7 @@ var Font = (function FontClosure() {
var instructionsEnd = j;
// validating flags
var coordinatesLength = 0;
- for (var i = 0; i < flagsCount; i++) {
+ for (i = 0; i < flagsCount; i++) {
var flag = glyf[j++];
if (flag & 0xC0) {
// reserved flags must be zero, cleaning up
@@ -19428,7 +17561,7 @@ var Font = (function FontClosure() {
// Validate version:
// Should always be 0x00010000
- var version = int32([data[0], data[1], data[2], data[3]]);
+ 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;
@@ -19437,7 +17570,7 @@ var Font = (function FontClosure() {
data[3] = 0;
}
- var indexToLocFormat = int16([data[50], data[51]]);
+ var indexToLocFormat = int16(data[50], data[51]);
if (indexToLocFormat < 0 || indexToLocFormat > 1) {
info('Attempting to fix invalid indexToLocFormat in head table: ' +
indexToLocFormat);
@@ -19508,8 +17641,15 @@ var Font = (function FontClosure() {
var startOffset = itemDecode(locaData, 0);
var writeOffset = 0;
itemEncode(locaData, 0, writeOffset);
- for (var i = 0, j = itemSize; i < numGlyphs; i++, j += itemSize) {
+ 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);
@@ -19529,8 +17669,9 @@ var Font = (function FontClosure() {
// 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 (var i = 0, j = itemSize; i < numGlyphs; i++, j += itemSize)
+ for (i = 0, j = itemSize; i < numGlyphs; i++, j += itemSize) {
itemEncode(locaData, j, simpleGlyph.length);
+ }
glyf.data = simpleGlyph;
return;
}
@@ -19556,25 +17697,27 @@ var Font = (function FontClosure() {
font.pos = start;
var length = post.length, end = start + length;
- var version = int32(font.getBytes(4));
+ 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 = int16(font.getBytes(2));
- if (numGlyphs != maxpNumGlyphs) {
+ var numGlyphs = font.getUint16();
+ if (numGlyphs !== maxpNumGlyphs) {
valid = false;
break;
}
var glyphNameIndexes = [];
- for (var i = 0; i < numGlyphs; ++i) {
- var index = int16(font.getBytes(2));
+ for (i = 0; i < numGlyphs; ++i) {
+ var index = font.getUint16();
if (index >= 32768) {
valid = false;
break;
@@ -19585,16 +17728,17 @@ var Font = (function FontClosure() {
break;
}
var customNames = [];
+ var strBuf = [];
while (font.pos < end) {
var stringLength = font.getByte();
- var string = '';
- for (var i = 0; i < stringLength; ++i) {
- string += String.fromCharCode(font.getByte());
+ strBuf.length = stringLength;
+ for (i = 0; i < stringLength; ++i) {
+ strBuf[i] = String.fromCharCode(font.getByte());
}
- customNames.push(string);
+ customNames.push(strBuf.join(''));
}
glyphNames = [];
- for (var i = 0; i < numGlyphs; ++i) {
+ for (i = 0; i < numGlyphs; ++i) {
var j = glyphNameIndexes[i];
if (j < 258) {
glyphNames.push(MacStandardGlyphOrdering[j]);
@@ -19620,33 +17764,35 @@ var Font = (function FontClosure() {
var names = [[], []];
var length = nameTable.length, end = start + length;
- var format = int16(font.getBytes(2));
+ 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 = int16(font.getBytes(2));
- var stringsStart = int16(font.getBytes(2));
+ var numRecords = font.getUint16();
+ var stringsStart = font.getUint16();
var records = [];
var NAME_RECORD_LENGTH = 12;
- for (var i = 0; i < numRecords &&
+ var i, ii;
+
+ for (i = 0; i < numRecords &&
font.pos + NAME_RECORD_LENGTH <= end; i++) {
var r = {
- platform: int16(font.getBytes(2)),
- encoding: int16(font.getBytes(2)),
- language: int16(font.getBytes(2)),
- name: int16(font.getBytes(2)),
- length: int16(font.getBytes(2)),
- offset: int16(font.getBytes(2))
+ 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)) {
+ if ((r.platform === 1 && r.encoding === 0 && r.language === 0) ||
+ (r.platform === 3 && r.encoding === 1 && r.language === 0x409)) {
records.push(r);
}
}
- for (var i = 0, ii = records.length; i < ii; i++) {
+ for (i = 0, ii = records.length; i < ii; i++) {
var record = records[i];
var pos = start + stringsStart + record.offset;
if (pos + record.length > end) {
@@ -19654,12 +17800,11 @@ var Font = (function FontClosure() {
}
font.pos = pos;
var nameIndex = record.name;
- var encoding = record.encoding ? 1 : 0;
if (record.encoding) {
// unicode
var str = '';
for (var j = 0, jj = record.length; j < jj; j += 2) {
- str += String.fromCharCode(int16(font.getBytes(2)));
+ str += String.fromCharCode(font.getUint16());
}
names[1][nameIndex] = str;
} else {
@@ -19683,7 +17828,7 @@ var Font = (function FontClosure() {
function sanitizeTTProgram(table, ttContext) {
var data = table.data;
- var i = 0, n, lastEndf = 0, lastDeff = 0;
+ var i = 0, j, n, b, funcId, pc, lastEndf = 0, lastDeff = 0;
var stack = [];
var callstack = [];
var functionsCalled = [];
@@ -19699,7 +17844,7 @@ var Font = (function FontClosure() {
if (inFDEF || inELSE) {
i += n;
} else {
- for (var j = 0; j < n; j++) {
+ for (j = 0; j < n; j++) {
stack.push(data[i++]);
}
}
@@ -19708,8 +17853,8 @@ var Font = (function FontClosure() {
if (inFDEF || inELSE) {
i += n * 2;
} else {
- for (var j = 0; j < n; j++) {
- var b = data[i++];
+ for (j = 0; j < n; j++) {
+ b = data[i++];
stack.push((b << 8) | data[i++]);
}
}
@@ -19718,7 +17863,7 @@ var Font = (function FontClosure() {
if (inFDEF || inELSE) {
i += n;
} else {
- for (var j = 0; j < n; j++) {
+ for (j = 0; j < n; j++) {
stack.push(data[i++]);
}
}
@@ -19727,15 +17872,15 @@ var Font = (function FontClosure() {
if (inFDEF || inELSE) {
i += n * 2;
} else {
- for (var j = 0; j < n; j++) {
- var b = data[i++];
+ 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
- var funcId = stack[stack.length - 1];
+ funcId = stack[stack.length - 1];
ttContext.functionsUsed[funcId] = true;
if (funcId in ttContext.functionsStackDeltas) {
stack.length += ttContext.functionsStackDeltas[funcId];
@@ -19743,7 +17888,7 @@ var Font = (function FontClosure() {
functionsCalled.indexOf(funcId) < 0) {
callstack.push({data: data, i: i, stackTop: stack.length - 1});
functionsCalled.push(funcId);
- var pc = ttContext.functionsDefined[funcId];
+ pc = ttContext.functionsDefined[funcId];
if (!pc) {
warn('TT: CALL non-existent function');
ttContext.hintsValid = false;
@@ -19761,20 +17906,20 @@ var Font = (function FontClosure() {
inFDEF = true;
// collecting inforamtion about which functions are defined
lastDeff = i;
- var funcId = stack.pop();
+ 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 {
- var pc = callstack.pop();
+ pc = callstack.pop();
if (!pc) {
warn('TT: ENDF bad stack');
ttContext.hintsValid = false;
return;
}
- var funcId = functionsCalled.pop();
+ funcId = functionsCalled.pop();
data = pc.data;
i = pc.i;
ttContext.functionsStackDeltas[funcId] =
@@ -19798,9 +17943,13 @@ var Font = (function FontClosure() {
}
--ifLevel;
} else if (op === 0x1C) { // JMPR
- var offset = stack[stack.length - 1];
- // only jumping forward to prevent infinite loop
- if (offset > 0) { i += offset - 1; }
+ 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) {
@@ -19840,6 +17989,11 @@ var Font = (function FontClosure() {
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);
@@ -19858,13 +18012,14 @@ var Font = (function FontClosure() {
if (content.length > 1) {
// concatenating the content items
var newLength = 0;
- for (var j = 0, jj = content.length; j < jj; j++) {
+ 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 (var j = 0, jj = content.length; j < jj; j++) {
+ for (j = 0, jj = content.length; j < jj; j++) {
result.set(content[j], pos);
pos += content[j].length;
}
@@ -19906,11 +18061,13 @@ var Font = (function FontClosure() {
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};
+ hmtx: null, maxp: null, name: null, post: null };
+ var table;
for (var i = 0; i < numTables; i++) {
- var table = readTableEntry(font);
+ table = readTableEntry(font);
if (VALID_TABLES.indexOf(table.tag) < 0) {
continue; // skipping table if it's not a required or optional table
}
@@ -19925,8 +18082,8 @@ var Font = (function FontClosure() {
// OpenType font
if (!tables.head || !tables.hhea || !tables.maxp || !tables.post) {
// no major tables: throwing everything at CFFFont
- var cffFile = new Stream(tables['CFF '].data);
- var cff = new CFFFont(cffFile, properties);
+ cffFile = new Stream(tables['CFF '].data);
+ cff = new CFFFont(cffFile, properties);
return this.convert(name, cff, properties);
}
@@ -19936,10 +18093,12 @@ var Font = (function FontClosure() {
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) {
@@ -19947,24 +18106,24 @@ var Font = (function FontClosure() {
}
font.pos = (font.start || 0) + tables.maxp.offset;
- var version = int32(font.getBytes(4));
- var numGlyphs = int16(font.getBytes(2));
+ 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 = int16(font.getBytes(2));
+ 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 = int16(font.getBytes(2));
+ maxFunctionDefs = font.getUint16();
}
var dupFirstEntry = false;
- if (properties.type == 'CIDFontType2' && properties.toUnicode &&
- properties.toUnicode[0] > '\u0000') {
+ if (properties.type === 'CIDFontType2' && properties.toUnicode &&
+ properties.toUnicode.get(0) > '\u0000') {
// oracle's defect (see 3427), duplicating first entry
dupFirstEntry = true;
numGlyphs++;
@@ -19980,24 +18139,6 @@ var Font = (function FontClosure() {
delete tables['cvt '];
}
- // Tables needs to be written by ascendant alphabetic order
- var tablesNames = Object.keys(tables);
- tablesNames.sort();
-
- numTables = tablesNames.length;
-
- // header and new offsets. Table entry information is appended to the
- // end of file. The virtualOffset represents where to put the actual
- // data of a particular table;
- var ttf = {
- file: '',
- virtualOffset: numTables * (4 * 4)
- };
-
- // The new numbers of tables will be the last one plus the num
- // of missing tables
- createOpenTypeHeader(header.version, ttf, numTables);
-
// Ensure the hmtx table contains the advance width and
// sidebearings information for numGlyphs in the maxp table
sanitizeMetrics(font, tables.hhea, tables.hmtx, numGlyphs);
@@ -20009,8 +18150,8 @@ var Font = (function FontClosure() {
sanitizeHead(tables.head, numGlyphs, isTrueType ? tables.loca.length : 0);
if (isTrueType) {
- var isGlyphLocationsLong = int16([tables.head.data[50],
- tables.head.data[51]]);
+ var isGlyphLocationsLong = int16(tables.head.data[50],
+ tables.head.data[51]);
sanitizeGlyphLocations(tables.loca, tables.glyf, numGlyphs,
isGlyphLocationsLong, hintsValid, dupFirstEntry);
}
@@ -20034,244 +18175,142 @@ var Font = (function FontClosure() {
}
}
- var glyphs, ids;
- if (properties.type == 'CIDFontType2') {
- // Replace the old CMAP table with a shiny new one
- // Type2 composite fonts map characters directly to glyphs so the cmap
- // table must be replaced.
- // canvas fillText will reencode some characters even if the font has a
- // glyph at that position - e.g. newline is converted to a space and
- // U+00AD (soft hyphen) is not drawn.
- // So, offset all the glyphs by 0xFF to avoid these cases and use
- // the encoding to map incoming characters to the new glyph positions
- if (!tables.cmap) {
- tables.cmap = {
- tag: 'cmap',
- data: null
- };
- }
-
+ var charCodeToGlyphId = [], charCode;
+ if (properties.type === 'CIDFontType2') {
var cidToGidMap = properties.cidToGidMap || [];
- var gidToCidMap = [0];
- if (cidToGidMap.length > 0) {
- for (var j = cidToGidMap.length - 1; j >= 0; j--) {
- var gid = cidToGidMap[j];
- if (gid)
- gidToCidMap[gid] = j;
+ var cidToGidMapLength = cidToGidMap.length;
+ properties.cMap.forEach(function(charCode, cid) {
+ assert(cid <= 0xffff, 'Max size of CID is 65,535');
+ var glyphId = -1;
+ if (cidToGidMapLength === 0) {
+ glyphId = charCode;
+ } else if (cidToGidMap[cid] !== undefined) {
+ glyphId = cidToGidMap[cid];
}
- // filling the gaps using CID above the CIDs currently used in font
- var nextCid = cidToGidMap.length;
- for (var i = 1; i < numGlyphs; i++) {
- if (!gidToCidMap[i])
- gidToCidMap[i] = nextCid++;
- }
- } else {
- for (var i = 1; i < numGlyphs; i++) {
- gidToCidMap[i] = i;
- }
- if (dupFirstEntry) {
- gidToCidMap[numGlyphs - 1] = 0;
- }
- }
-
- glyphs = [];
- ids = [];
-
- var usedUnicodes = [];
- var unassignedUnicodeItems = [];
- var toFontChar = this.cidToFontChar || this.toFontChar;
- for (var i = 1; i < numGlyphs; i++) {
- var cid = gidToCidMap[i];
- var unicode = toFontChar[cid];
- if (!unicode || typeof unicode !== 'number' ||
- isSpecialUnicode(unicode) || unicode in usedUnicodes) {
- unassignedUnicodeItems.push(i);
- continue;
- }
- usedUnicodes[unicode] = true;
- glyphs.push({ unicode: unicode, code: cid });
- ids.push(i);
- }
-
- // unassigned codepoints will never be used for non-Identity CMap
- // because the input will be Unicode
- if (!this.cidToFontChar) {
- // trying to fit as many unassigned symbols as we can
- // in the range allocated for the user defined symbols
- var unusedUnicode = CMAP_GLYPH_OFFSET;
- for (var j = 0, jj = unassignedUnicodeItems.length; j < jj; j++) {
- var i = unassignedUnicodeItems[j];
- var cid = gidToCidMap[i];
- while (unusedUnicode in usedUnicodes)
- unusedUnicode++;
- if (unusedUnicode >= CMAP_GLYPH_OFFSET + GLYPH_AREA_SIZE)
- break;
- var unicode = unusedUnicode++;
- this.toFontChar[cid] = unicode;
- usedUnicodes[unicode] = true;
- glyphs.push({ unicode: unicode, code: cid });
- ids.push(i);
+ if (glyphId >= 0 && glyphId < numGlyphs) {
+ charCodeToGlyphId[charCode] = glyphId;
}
+ });
+ if (dupFirstEntry) {
+ charCodeToGlyphId[0] = numGlyphs - 1;
}
} else {
- this.useToFontChar = true;
// Most of the following logic in this code branch is based on the
// 9.6.6.4 of the PDF spec.
-
- // TODO(mack):
- // We are using this.hasEncoding to mean that the encoding is either
- // MacRomanEncoding or WinAnsiEncoding (following spec in 9.6.6.4),
- // but this.hasEncoding is currently true for any encodings on the
- // Encodings object (e.g. MacExpertEncoding). So should consider using
- // better check for this.
- var cmapTable = readCmapTable(tables.cmap, font, this.hasEncoding,
- this.isSymbolicFont);
-
- // TODO(mack): If the (3, 0) cmap table used, then the font is
- // symbolic. The range of charcodes in the cmap table should be
- // one of the following:
- // -> 0x0000 - 0x00FF
- // -> 0xF000 - 0xF0FF
- // -> 0xF100 - 0xF1FF
- // -> 0xF200 - 0xF2FF
- // If it is not, we should change not consider this a symbolic font
- this.isSymbolicFont = cmapTable.isSymbolicFont;
-
+ 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 glyphs = [];
- var ids = [];
- for (var i = 0; i < cmapMappingsLength; ++i) {
- var cmapMapping = cmapMappings[i];
- var charcode = cmapMapping.charcode;
- var unicode = cmapCharcodeToUnicode(charcode, this.isSymbolicFont,
- cmapPlatformId, cmapEncodingId);
+ var hasEncoding = properties.differences.length ||
+ !!properties.baseEncodingName;
- if (!unicode) {
- // TODO(mack): gotta check if skipping mappings where we cannot find
- // a unicode is the correct behaviour
- continue;
+ // 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];
}
- glyphs.push({
- code: charcode,
- unicode: unicode
- });
- ids.push(cmapMapping.glyphId);
- }
-
- var hasShortCmap = cmapTable.hasShortCmap;
- var toFontChar = this.toFontChar;
-
- if (hasShortCmap && ids.length == numGlyphs) {
- // Fixes the short cmap tables -- some generators use incorrect
- // glyph id.
- for (var i = 0, ii = ids.length; i < ii; i++) {
- ids[i] = i;
- }
- }
-
- // Rewrite the whole toFontChar dictionary with a new one using the
- // information from the mappings in the cmap table.
- var newToFontChar = [];
- if (this.isSymbolicFont) {
- for (var i = 0, ii = glyphs.length; i < ii; i++) {
- var glyph = glyphs[i];
- // For (3, 0) cmap tables:
- // The charcode key being stored in toFontChar 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.code & 0xFF === glyph.code
- newToFontChar[glyph.code & 0xFF] = glyph.unicode;
- }
- } else {
-
- var encoding = properties.baseEncoding;
- var differences = properties.differences;
-
- // TODO(mack): check if it is necessary to shift control characters
- // for non-symbolic fonts so that browsers dont't render them using
- // space characters
-
- var glyphCodeMapping = cmapTable.glyphCodeMapping;
- for (var charcode = 0; charcode < encoding.length; ++charcode) {
- if (!encoding.hasOwnProperty(charcode)) {
+ 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;
}
-
- // Since the cmap table that we will be writing out is a (3, 1)
- // unicode table, in this section we will rewrites the charcodes
- // in the pdf into unicodes
-
- var glyphName = encoding[charcode];
- // A nonsymbolic font should not have a Differences array, but
- // if it does have one, we should still use it
- if (charcode in differences) {
- glyphName = differences[charcode];
+ 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);
}
- // Finally, any undefined entries in the table shall be filled
- // using StandardEncoding
- if (!glyphName) {
- glyphName = Encodings.StandardEncoding[charcode];
+ var found = false;
+ for (i = 0; i < cmapMappingsLength; ++i) {
+ if (cmapMappings[i].charCode === unicodeOrCharCode) {
+ charCodeToGlyphId[charCode] = cmapMappings[i].glyphId;
+ found = true;
+ break;
+ }
}
-
- // TODO(mack): Handle the case that the glyph name cannot be
- // mapped as specified, in which case the glyph name shall be
- // looked up in the font program's 'post' table (if one is
- // present) and the associated glyph id shall be used.
- //
- // For now, we're just using the '.notdef' glyph name in this
- // case.
- glyphName = glyphName || '.notdef';
-
- var unicode = GlyphsUnicode[glyphName];
- newToFontChar[charcode] = unicode;
+ 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) {
+ charCodeToGlyphId[charCode] = 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;
}
}
- this.toFontChar = toFontChar = newToFontChar;
-
- createGlyphNameMap(glyphs, ids, properties);
- this.glyphNameMap = properties.glyphNameMap;
}
- if (glyphs.length === 0) {
+ if (charCodeToGlyphId.length === 0) {
// defines at least one glyph
- glyphs.push({ unicode: 0xF000, code: 0xF000, glyph: '.notdef' });
- ids.push(0);
+ charCodeToGlyphId[0] = 0;
}
// Converting glyphs and ids into font's cmap table
- tables.cmap.data = createCmapTable(glyphs, ids);
- var unicodeIsEnabled = [];
- for (var i = 0, ii = glyphs.length; i < ii; i++) {
- unicodeIsEnabled[glyphs[i].unicode] = true;
- }
- this.unicodeIsEnabled = unicodeIsEnabled;
+ 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
+ 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: stringToArray(createOS2Table(properties, glyphs, override))
+ data: createOS2Table(properties, newMapping.charCodeToGlyphId,
+ override)
};
}
@@ -20279,16 +18318,16 @@ var Font = (function FontClosure() {
if (!tables.post) {
tables.post = {
tag: 'post',
- data: stringToArray(createPostTable(properties))
+ data: createPostTable(properties)
};
}
if (!isTrueType) {
try {
// Trying to repair CFF file
- var cffFile = new Stream(tables['CFF '].data);
+ cffFile = new Stream(tables['CFF '].data);
var parser = new CFFParser(cffFile, properties);
- var cff = parser.parse();
+ cff = parser.parse();
var compiler = new CFFCompiler(cff);
tables['CFF '].data = compiler.compile();
} catch (e) {
@@ -20300,330 +18339,304 @@ var Font = (function FontClosure() {
if (!tables.name) {
tables.name = {
tag: 'name',
- data: stringToArray(createNameTable(this.name))
+ data: createNameTable(this.name)
};
} else {
// ... using existing 'name' table as prototype
var namePrototype = readNameTable(tables.name);
- tables.name.data = stringToArray(createNameTable(name, namePrototype));
+ tables.name.data = createNameTable(name, namePrototype);
}
- // rewrite the tables but tweak offsets
- for (var i = 0; i < numTables; i++) {
- var table = tables[tablesNames[i]];
- var data = [];
-
- var tableData = table.data;
- for (var j = 0, jj = tableData.length; j < jj; j++)
- data.push(tableData[j]);
- createTableEntry(ttf, table.tag, data);
+ var builder = new OpenTypeFileBuilder(header.version);
+ for (var tableTag in tables) {
+ builder.addTable(tableTag, tables[tableTag].data);
}
-
- // Add the table datas
- for (var i = 0; i < numTables; i++) {
- var table = tables[tablesNames[i]];
- var tableData = table.data;
- ttf.file += arrayToString(tableData);
-
- // 4-byte aligned data
- while (ttf.file.length & 3)
- ttf.file += String.fromCharCode(0);
- }
-
- return stringToArray(ttf.file);
+ return builder.toArray();
},
convert: function Font_convert(fontName, font, properties) {
- function isFixedPitch(glyphs) {
- for (var i = 0, ii = glyphs.length - 1; i < ii; i++) {
- if (glyphs[i] != glyphs[i + 1])
- return false;
+ // 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 true;
+ return charCodes;
}
- // The offsets object holds at the same time a representation of where
- // to write the table entry information about a table and another offset
- // representing the offset where to draw the actual data of a particular
- // table
- var REQ_TABLES_CNT = 9;
-
- var otf = {
- file: '',
- virtualOffset: 9 * (4 * 4)
- };
-
- createOpenTypeHeader('\x4F\x54\x54\x4F', otf, 9);
-
- var charstrings = font.charstrings;
- properties.fixedPitch = isFixedPitch(charstrings);
-
- var glyphNameMap = {};
- for (var i = 0; i < charstrings.length; ++i) {
- var charstring = charstrings[i];
- glyphNameMap[charstring.glyph] = charstring.unicode;
+ function createCharCode(charCodeToGlyphId, glyphId) {
+ for (var charCode in charCodeToGlyphId) {
+ if (glyphId === charCodeToGlyphId[charCode]) {
+ return charCode | 0;
+ }
+ }
+ newMapping.charCodeToGlyphId[newMapping.nextAvailableFontCharCode] =
+ glyphId;
+ return newMapping.nextAvailableFontCharCode++;
}
- this.glyphNameMap = glyphNameMap;
var seacs = font.seacs;
- if (SEAC_ANALYSIS_ENABLED && seacs) {
- var seacMap = [];
+ if (SEAC_ANALYSIS_ENABLED && seacs && seacs.length) {
var matrix = properties.fontMatrix || FONT_IDENTITY_MATRIX;
- for (var i = 0; i < charstrings.length; ++i) {
- var charstring = charstrings[i];
- var seac = seacs[charstring.gid];
- if (!seac) {
- continue;
- }
+ 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 baseUnicode = glyphNameMap[baseGlyphName];
var accentGlyphName = Encodings.StandardEncoding[seac[3]];
- var accentUnicode = glyphNameMap[accentGlyphName];
- if (!baseUnicode || !accentUnicode) {
+ 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]
};
- seacMap[charstring.unicode] = {
- baseUnicode: baseUnicode,
- accentUnicode: accentUnicode,
- accentOffset: accentOffset
- };
+
+ 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;
}
- if (properties.overridableEncoding && (properties.subtype == 'Type1C' ||
- properties.subtype == 'CIDFontType0C')) {
- var encoding = [];
- for (var i = 0; i < charstrings.length; ++i) {
- var charstring = charstrings[i];
- encoding[charstring.code] = charstring.glyph;
- }
- properties.baseEncoding = encoding;
- }
- if (properties.subtype == 'CIDFontType0C') {
- var toFontChar = [];
- for (var i = 0; i < charstrings.length; ++i) {
- var charstring = charstrings[i];
- toFontChar[charstring.code] = charstring.unicode;
- }
- this.toFontChar = toFontChar;
- }
var unitsPerEm = 1 / (properties.fontMatrix || FONT_IDENTITY_MATRIX)[0];
- var fields = {
- // PostScript Font Program
- 'CFF ': font.data,
+ 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
- // OS/2 and Windows Specific metrics
- 'OS/2': stringToArray(createOS2Table(properties, charstrings)),
+ // 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
- // Character to glyphs mapping
- 'cmap': createCmapTable(charstrings.slice(),
- ('glyphIds' in font) ? font.glyphIds : null),
-
- // Font header
- 'head': (function fontFieldsHead() {
- return stringToArray(
- '\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
- 'hhea': (function fontFieldsHhea() {
- return stringToArray(
- '\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(charstrings.length + 1)); // Number of HMetrics
- })(),
-
- // Horizontal metrics
- 'hmtx': (function fontFieldsHmtx() {
+ // 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 = 0, ii = charstrings.length; i < ii; i++) {
- var charstring = charstrings[i];
- var width = 'width' in charstring ? charstring.width : 0;
+ 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 stringToArray(hmtx);
- })(),
+ return hmtx;
+ })());
- // Maximum profile
- 'maxp': (function fontFieldsMaxp() {
- return stringToArray(
- '\x00\x00\x50\x00' + // Version number
- string16(charstrings.length + 1)); // Num of glyphs
- })(),
+ // Maximum profile
+ builder.addTable('maxp',
+ '\x00\x00\x50\x00' + // Version number
+ string16(numGlyphs)); // Num of glyphs
- // Naming tables
- 'name': stringToArray(createNameTable(fontName)),
+ // Naming tables
+ builder.addTable('name', createNameTable(fontName));
- // PostScript informations
- 'post': stringToArray(createPostTable(properties))
- };
+ // PostScript informations
+ builder.addTable('post', createPostTable(properties));
- for (var field in fields)
- createTableEntry(otf, field, fields[field]);
-
- for (var field in fields) {
- var table = fields[field];
- otf.file += arrayToString(table);
- }
-
- return stringToArray(otf.file);
+ return builder.toArray();
},
- buildToFontChar: function Font_buildToFontChar(toUnicode) {
- var result = [];
- var unusedUnicode = CMAP_GLYPH_OFFSET;
- for (var i = 0, ii = toUnicode.length; i < ii; i++) {
- var unicode = toUnicode[i];
- var fontCharCode = typeof unicode === 'object' ? unusedUnicode++ :
- unicode;
- if (typeof unicode !== 'undefined') {
- if (isString(fontCharCode) && fontCharCode.length === 1) {
- fontCharCode = fontCharCode.charCodeAt(0);
- }
- result[i] = fontCharCode;
- }
+ /**
+ * 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;
}
- return result;
- },
-
- rebuildToUnicode: function Font_rebuildToUnicode(properties) {
- var firstChar = properties.firstChar, lastChar = properties.lastChar;
- var map = [];
- var toUnicode = this.toUnicode || this.cidToUnicode;
- if (toUnicode) {
- var isIdentityMap = toUnicode.length === 0;
- for (var i = firstChar, ii = lastChar; i <= ii; i++) {
- // TODO missing map the character according font's CMap
- map[i] = isIdentityMap ? String.fromCharCode(i) : toUnicode[i];
+ // 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];
}
- } else {
- for (var i = firstChar, ii = lastChar; i <= ii; i++) {
- var glyph = properties.differences[i];
- if (!glyph)
- glyph = properties.baseEncoding[i];
- if (!!glyph && (glyph in GlyphsUnicode))
- map[i] = String.fromCharCode(GlyphsUnicode[glyph]);
- }
- }
- this.toUnicode = map;
- },
-
- loadCidToUnicode: function Font_loadCidToUnicode(properties) {
- if (!properties.cidSystemInfo)
- return;
-
- var cidToUnicodeMap = [], unicodeToCIDMap = [];
- this.cidToUnicode = cidToUnicodeMap;
- this.unicodeToCID = unicodeToCIDMap;
-
- var cidEncoding = properties.cidEncoding;
- if (properties.toUnicode) {
- if (cidEncoding && cidEncoding.indexOf('Identity-') !== 0) {
- warn('Need to create a reverse mapping from \'ToUnicode\' CMap');
- }
- return; // 'ToUnicode' CMap will be used
- }
-
- var cidSystemInfo = properties.cidSystemInfo;
- var cidToUnicode;
- if (cidSystemInfo) {
- cidToUnicode = CIDToUnicodeMaps[
- cidSystemInfo.registry + '-' + cidSystemInfo.ordering];
- }
-
- if (!cidToUnicode)
- return; // identity encoding
-
- var overwrite = HalfwidthCMaps[cidEncoding];
- var cid = 1, i, j, k, ii;
- for (i = 0, ii = cidToUnicode.length; i < ii; ++i) {
- var unicode = cidToUnicode[i];
- if (isArray(unicode)) {
- var length = unicode.length;
- for (j = 0; j < length; j++) {
- cidToUnicodeMap[cid] = k = unicode[j];
- if (!unicodeToCIDMap[k] || overwrite) {
- unicodeToCIDMap[k] = cid;
+ 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;
}
- }
- cid++;
- } else if (typeof unicode === 'object') {
- var fillLength = unicode.f;
- if (fillLength) {
- k = unicode.c;
- for (j = 0; j < fillLength; ++j) {
- cidToUnicodeMap[cid] = k;
- if (!unicodeToCIDMap[k] || overwrite) {
- unicodeToCIDMap[k] = cid;
+ 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;
+ }
}
- cid++;
- k++;
+ toUnicode[charcode] = String.fromCharCode(code);
}
- } else
- cid += unicode.s;
- } else if (unicode) {
- cidToUnicodeMap[cid] = unicode;
- if (!unicodeToCIDMap[unicode] || overwrite) {
- unicodeToCIDMap[unicode] = cid;
+ continue;
}
- cid++;
- } else
- cid++;
+ 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);
}
- if (!cidEncoding) {
- return;
- }
- if (cidEncoding.indexOf('Identity-') !== 0) {
- // input is already Unicode for non-Identity CMap encodings.
- this.cidToUnicode = [];
- // For CIDFontType2, however, we need cid-to-Unicode conversion
- // to rebuild cmap.
- if (properties.type == 'CIDFontType2') {
- this.cidToFontChar = cidToUnicodeMap;
- }
- } else {
- // We don't have to do reverse conversions if the string is
- // already CID.
- this.unicodeToCID = [];
- }
+ // The viewer's choice, just use an identity map.
+ return new IdentityToUnicodeMap(properties.firstChar,
+ properties.lastChar);
},
get spaceWidth() {
@@ -20644,18 +18657,24 @@ var Font = (function FontClosure() {
var glyphUnicode = GlyphsUnicode[glyphName];
// finding the charcode via unicodeToCID map
var charcode = 0;
- if (this.composite)
- charcode = this.unicodeToCID[glyphUnicode];
+ if (this.composite) {
+ if (this.cMap.contains(glyphUnicode)) {
+ charcode = this.cMap.lookup(glyphUnicode);
+ }
+ }
// ... via toUnicode map
- if (!charcode && 'toUnicode' in this)
- charcode = this.toUnicode.indexOf(glyphUnicode);
+ if (!charcode && 'toUnicode' in this) {
+ charcode = this.toUnicode.charCodeOf(glyphUnicode);
+ }
// setting it to unicode if negative or undefined
- if (charcode <= 0)
+ if (charcode <= 0) {
charcode = glyphUnicode;
+ }
// trying to get width via charcode
width = this.widths[charcode];
- if (width)
+ if (width) {
break; // the non-zero width found
+ }
}
width = width || this.defaultWidth;
// Do not shadow the property here. See discussion:
@@ -20665,153 +18684,87 @@ var Font = (function FontClosure() {
},
charToGlyph: function Font_charToGlyph(charcode) {
- var fontCharCode, width, operatorList, disabled;
+ var fontCharCode, width, operatorListId;
- var width = this.widths[charcode];
- var vmetric = this.vmetrics && this.vmetrics[charcode];
-
- switch (this.type) {
- case 'CIDFontType0':
- var cid = this.unicodeToCID[charcode] || charcode;
- if (this.unicodeToCID.length > 0) {
- width = this.widths[cid];
- vmetric = this.vmetrics && this.vmetrics[cid];
- }
- if (this.noUnicodeAdaptation) {
- fontCharCode = this.toFontChar[charcode] || charcode;
- break;
- }
- // CIDFontType0 is not encoded in Unicode.
- fontCharCode = this.toFontChar[cid] || cid;
- break;
- case 'CIDFontType2':
- if (this.unicodeToCID.length > 0) {
- var cid = this.unicodeToCID[charcode] || charcode;
- width = this.widths[cid];
- vmetric = this.vmetrics && this.vmetrics[cid];
- fontCharCode = charcode;
- break;
- }
- fontCharCode = this.toFontChar[charcode] || charcode;
- break;
- case 'MMType1': // XXX at the moment only "standard" fonts are supported
- case 'Type1':
- var glyphName = this.differences[charcode] || this.encoding[charcode];
- if (!isNum(width))
- width = this.widths[glyphName];
- if (this.noUnicodeAdaptation) {
- fontCharCode = mapPrivateUseChars(GlyphsUnicode[glyphName] ||
- charcode);
- break;
- }
- fontCharCode = this.glyphNameMap[glyphName] ||
- GlyphsUnicode[glyphName] || charcode;
- break;
- case 'Type3':
- var glyphName = this.differences[charcode] || this.encoding[charcode];
- operatorList = this.charProcOperatorList[glyphName];
- fontCharCode = charcode;
- break;
- case 'TrueType':
- if (this.useToFontChar) {
- fontCharCode = this.toFontChar[charcode] || charcode;
- break;
- }
- var glyphName = this.differences[charcode] || this.encoding[charcode];
- if (!glyphName)
- glyphName = Encodings.StandardEncoding[charcode];
- if (!isNum(width))
- width = this.widths[glyphName];
- if (this.noUnicodeAdaptation) {
- fontCharCode = GlyphsUnicode[glyphName] || charcode;
- break;
- }
- if (!this.hasEncoding || this.isSymbolicFont) {
- fontCharCode = this.useToFontChar ? this.toFontChar[charcode] :
- charcode;
- break;
- }
-
- // MacRoman encoding address by re-encoding the cmap table
-
- fontCharCode = glyphName in this.glyphNameMap ?
- this.glyphNameMap[glyphName] : GlyphsUnicode[glyphName];
- break;
- default:
- warn('Unsupported font type: ' + this.type);
- break;
+ var widthCode = charcode;
+ if (this.cMap && this.cMap.contains(charcode)) {
+ widthCode = this.cMap.lookup(charcode);
}
-
- var unicodeChars = !('toUnicode' in this) ? charcode :
- this.toUnicode[charcode] || charcode;
- if (typeof unicodeChars === 'number') {
- unicodeChars = String.fromCharCode(unicodeChars);
- }
-
+ width = this.widths[widthCode];
width = isNum(width) ? width : this.defaultWidth;
- disabled = this.unicodeIsEnabled ?
- !this.unicodeIsEnabled[fontCharCode] : false;
+ 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[fontCharCode]) {
- var seac = this.seacMap[fontCharCode];
- fontCharCode = seac.baseUnicode;
+ if (this.seacMap && this.seacMap[charcode]) {
+ var seac = this.seacMap[charcode];
+ fontCharCode = seac.baseFontCharCode;
accent = {
- fontChar: String.fromCharCode(seac.accentUnicode),
+ fontChar: String.fromCharCode(seac.accentFontCharCode),
offset: seac.accentOffset
};
}
- return {
- fontChar: String.fromCharCode(fontCharCode),
- unicode: unicodeChars,
- accent: accent,
- width: width,
- vmetric: vmetric,
- disabled: disabled,
- operatorList: operatorList
- };
+ 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;
+ var glyphs, glyph, charcode;
// if we translated this string before, just grab it from the cache
if (charsCache) {
glyphs = charsCache[chars];
- if (glyphs)
+ if (glyphs) {
return glyphs;
+ }
}
// lazily create the translation cache
- if (!charsCache)
+ if (!charsCache) {
charsCache = this.charsCache = Object.create(null);
+ }
glyphs = [];
var charsCacheKey = chars;
+ var i = 0, ii;
- var converter;
- var cidEncoding = this.cidEncoding;
- if (cidEncoding) {
- converter = CMapConverterList[cidEncoding];
- if (converter) {
- chars = converter(chars);
- } else if (cidEncoding.indexOf('Uni') !== 0 &&
- cidEncoding.indexOf('Identity-') !== 0) {
- warn('Unsupported CMap: ' + cidEncoding);
- }
- }
- if (!converter && this.cmap) {
- var i = 0;
+ if (this.cMap) {
// composite fonts have multi-byte strings convert the string from
// single-byte to multi-byte
+ var c = {};
while (i < chars.length) {
- var c = this.cmap.readCharCode(chars, i);
- var charcode = c[0];
- var length = c[1];
+ this.cMap.readCharCode(chars, i, c);
+ charcode = c.charcode;
+ var length = c.length;
i += length;
- var glyph = this.charToGlyph(charcode);
+ glyph = this.charToGlyph(charcode);
glyphs.push(glyph);
// placing null after each word break charcode (ASCII SPACE)
// Ignore occurences of 0x20 in multiple-byte codes.
@@ -20819,14 +18772,14 @@ var Font = (function FontClosure() {
glyphs.push(null);
}
}
- }
- else {
- for (var i = 0, ii = chars.length; i < ii; ++i) {
- var charcode = chars.charCodeAt(i);
- var glyph = this.charToGlyph(charcode);
+ } else {
+ for (i = 0, ii = chars.length; i < ii; ++i) {
+ charcode = chars.charCodeAt(i);
+ glyph = this.charToGlyph(charcode);
glyphs.push(glyph);
- if (charcode == 0x20)
+ if (charcode === 0x20) {
glyphs.push(null);
+ }
}
}
@@ -20841,6 +18794,8 @@ var Font = (function FontClosure() {
var ErrorFont = (function ErrorFontClosure() {
function ErrorFont(error) {
this.error = error;
+ this.loadedName = 'g_font_error';
+ this.loading = false;
}
ErrorFont.prototype = {
@@ -20855,6 +18810,67 @@ var ErrorFont = (function ErrorFontClosure() {
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.
@@ -20924,6 +18940,7 @@ var Type1CharString = (function Type1CharStringClosure() {
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) {
@@ -20981,7 +18998,7 @@ var Type1CharString = (function Type1CharStringClosure() {
error = true;
break;
}
- var subrNumber = this.stack.pop();
+ subrNumber = this.stack.pop();
error = this.convert(subrs[subrNumber], subrs);
break;
case 11: // return
@@ -20993,12 +19010,12 @@ var Type1CharString = (function Type1CharStringClosure() {
}
// To convert to type2 we have to move the width value to the
// first part of the charstring and then use hmoveto with lsb.
- var wx = this.stack.pop();
- var sbx = this.stack.pop();
+ wx = this.stack.pop();
+ sbx = this.stack.pop();
this.lsb = sbx;
this.width = wx;
- this.stack.push(sbx);
- error = this.executeCommand(1, COMMAND_MAP.hmoveto);
+ this.stack.push(wx, sbx);
+ error = this.executeCommand(2, COMMAND_MAP.hmoveto);
break;
case 14: // endchar
this.output.push(COMMAND_MAP.endchar[0]);
@@ -21067,13 +19084,13 @@ var Type1CharString = (function Type1CharStringClosure() {
// (dx, dy). The height argument will not be used for vmtx and
// vhea tables reconstruction -- ignoring it.
var wy = this.stack.pop();
- var wx = this.stack.pop();
+ wx = this.stack.pop();
var sby = this.stack.pop();
- var sbx = this.stack.pop();
+ sbx = this.stack.pop();
this.lsb = sbx;
this.width = wx;
- this.stack.push(sbx, sby);
- error = this.executeCommand(2, COMMAND_MAP.rmoveto);
+ this.stack.push(wx, sbx, sby);
+ error = this.executeCommand(3, COMMAND_MAP.rmoveto);
break;
case (12 << 8) + 12: // div
if (this.stack.length < 2) {
@@ -21089,7 +19106,7 @@ var Type1CharString = (function Type1CharStringClosure() {
error = true;
break;
}
- var subrNumber = this.stack.pop();
+ subrNumber = this.stack.pop();
var numArgs = this.stack.pop();
if (subrNumber === 0 && numArgs === 3) {
var flexArgs = this.stack.splice(this.stack.length - 17, 17);
@@ -21170,7 +19187,7 @@ var Type1CharString = (function Type1CharStringClosure() {
if (keepStack) {
this.stack.splice(start, howManyArgs);
} else {
- this.stack = [];
+ this.stack.length = 0;
}
return false;
}
@@ -21196,18 +19213,46 @@ var Type1Parser = (function Type1ParserClosure() {
var EEXEC_ENCRYPT_KEY = 55665;
var CHAR_STRS_ENCRYPT_KEY = 4330;
- function decrypt(stream, key, discardNumber) {
- var r = key, c1 = 52845, c2 = 22719;
- var decryptedString = [];
+ function isHexDigit(code) {
+ return code >= 48 && code <= 57 || // '0'-'9'
+ code >= 65 && code <= 70 || // 'A'-'F'
+ code >= 97 && code <= 102; // 'a'-'f'
+ }
- var value = '';
- var count = stream.length;
+ 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++) {
- value = stream[i];
- decryptedString[i] = value ^ (r >> 8);
+ var value = data[i];
+ decrypted[i] = value ^ (r >> 8);
r = ((value + r) * c1 + c2) & ((1 << 16) - 1);
}
- return decryptedString.slice(discardNumber);
+ 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) {
@@ -21219,7 +19264,11 @@ var Type1Parser = (function Type1ParserClosure() {
function Type1Parser(stream, encrypted) {
if (encrypted) {
- stream = new Stream(decrypt(stream.getBytes(), EEXEC_ENCRYPT_KEY, 4));
+ 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();
@@ -21311,7 +19360,7 @@ var Type1Parser = (function Type1ParserClosure() {
}
}
};
- var token;
+ var token, length, data, lenIV, encoded;
while ((token = this.getToken()) !== null) {
if (token !== '/') {
continue;
@@ -21335,12 +19384,11 @@ var Type1Parser = (function Type1ParserClosure() {
continue;
}
var glyph = this.getToken();
- var length = this.readInt();
+ length = this.readInt();
this.getToken(); // read in 'RD' or '-|'
- var data = stream.makeSubStream(stream.pos, length);
- var lenIV = program.properties.privateData['lenIV'];
- var encoded = decrypt(data.getBytes(), CHAR_STRS_ENCRYPT_KEY,
- lenIV);
+ 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();
@@ -21359,12 +19407,11 @@ var Type1Parser = (function Type1ParserClosure() {
this.getToken(); // read in 'array'
while ((token = this.getToken()) === 'dup') {
var index = this.readInt();
- var length = this.readInt();
+ length = this.readInt();
this.getToken(); // read in 'RD' or '-|'
- var data = stream.makeSubStream(stream.pos, length);
- var lenIV = program.properties.privateData['lenIV'];
- var encoded = decrypt(data.getBytes(), CHAR_STRS_ENCRYPT_KEY,
- lenIV);
+ 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();
@@ -21411,8 +19458,8 @@ var Type1Parser = (function Type1ParserClosure() {
}
for (var i = 0; i < charstrings.length; i++) {
- var glyph = charstrings[i].glyph;
- var encoded = charstrings[i].encoded;
+ glyph = charstrings[i].glyph;
+ encoded = charstrings[i].encoded;
var charString = new Type1CharString();
var error = charString.convert(encoded, subrs);
var output = charString.output;
@@ -21423,11 +19470,11 @@ var Type1Parser = (function Type1ParserClosure() {
output = [14];
}
program.charstrings.push({
- glyph: glyph,
- data: output,
- seac: charString.seac,
+ glyphName: glyph,
+ charstring: output,
+ width: charString.width,
lsb: charString.lsb,
- width: charString.width
+ seac: charString.seac
});
}
@@ -21458,7 +19505,7 @@ var Type1Parser = (function Type1ParserClosure() {
this.getToken(); // read in 'array'
for (var j = 0; j < size; j++) {
- var token = this.getToken();
+ token = this.getToken();
// skipping till first dup or def (e.g. ignoring for statement)
while (token !== 'dup' && token !== 'def') {
token = this.getToken();
@@ -21476,10 +19523,7 @@ var Type1Parser = (function Type1ParserClosure() {
this.getToken(); // read the in 'put'
}
}
- if (properties.overridableEncoding && encoding) {
- properties.baseEncoding = encoding;
- break;
- }
+ properties.builtInEncoding = encoding;
break;
case 'FontBBox':
var fontBBox = this.readNumberArray();
@@ -21534,7 +19578,7 @@ var CFFStandardStrings = [
'odieresis', 'ograve', 'otilde', 'scaron', 'uacute', 'ucircumflex',
'udieresis', 'ugrave', 'yacute', 'ydieresis', 'zcaron', 'exclamsmall',
'Hungarumlautsmall', 'dollaroldstyle', 'dollarsuperior', 'ampersandsmall',
- 'Acutesmall', 'parenleftsuperior', 'parenrightsuperior', '266 ff',
+ 'Acutesmall', 'parenleftsuperior', 'parenrightsuperior', 'twodotenleader',
'onedotenleader', 'zerooldstyle', 'oneoldstyle', 'twooldstyle',
'threeoldstyle', 'fouroldstyle', 'fiveoldstyle', 'sixoldstyle',
'sevenoldstyle', 'eightoldstyle', 'nineoldstyle', 'commasuperior',
@@ -21577,7 +19621,7 @@ var Type1Font = function Type1Font(name, file, properties) {
var headerBlockLength = properties.length1;
var eexecBlockLength = properties.length2;
var pfbHeader = file.peekBytes(PFB_HEADER_SIZE);
- var pfbHeaderPresent = pfbHeader[0] == 0x80 && pfbHeader[1] == 0x01;
+ var pfbHeaderPresent = pfbHeader[0] === 0x80 && pfbHeader[1] === 0x01;
if (pfbHeaderPresent) {
file.skip(PFB_HEADER_SIZE);
headerBlockLength = (pfbHeader[5] << 24) | (pfbHeader[4] << 16) |
@@ -21599,10 +19643,11 @@ var Type1Font = function Type1Font(name, file, properties) {
var eexecBlock = new Stream(file.getBytes(eexecBlockLength));
var eexecBlockParser = new Type1Parser(eexecBlock, true);
var data = eexecBlockParser.extractFontProgram();
- for (var info in data.properties)
+ for (var info in data.properties) {
properties[info] = data.properties[info];
+ }
- var charstrings = this.getOrderedCharStrings(data.charstrings, properties);
+ var charstrings = data.charstrings;
var type2Charstrings = this.getType2Charstrings(charstrings);
var subrs = this.getType2Subrs(data.subrs);
@@ -21613,35 +19658,37 @@ var Type1Font = function Type1Font(name, file, properties) {
};
Type1Font.prototype = {
- getOrderedCharStrings: function Type1Font_getOrderedCharStrings(glyphs,
- properties) {
- var charstrings = [];
- var usedUnicodes = [];
- var i, length, glyphName;
- var unusedUnicode = CMAP_GLYPH_OFFSET;
- for (i = 0, length = glyphs.length; i < length; i++) {
- var item = glyphs[i];
- var glyphName = item.glyph;
- var unicode = glyphName in GlyphsUnicode ?
- GlyphsUnicode[glyphName] : unusedUnicode++;
- while (usedUnicodes[unicode]) {
- unicode = unusedUnicode++;
+ 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;
+ }
}
- usedUnicodes[unicode] = true;
- charstrings.push({
- glyph: glyphName,
- unicode: unicode,
- gid: i,
- charstring: item.data,
- width: item.width,
- lsb: item.lsb
- });
}
- charstrings.sort(function charstrings_sort(a, b) {
- return a.unicode - b.unicode;
- });
- return charstrings;
+ return type1FontGlyphMapping(properties, builtInEncoding, glyphNames);
},
getSeacs: function Type1Font_getSeacs(charstrings) {
@@ -21650,7 +19697,8 @@ Type1Font.prototype = {
for (i = 0, ii = charstrings.length; i < ii; i++) {
var charstring = charstrings[i];
if (charstring.seac) {
- seacMap[i] = charstring.seac;
+ // Offset by 1 for .notdef
+ seacMap[i + 1] = charstring.seac;
}
}
return seacMap;
@@ -21668,19 +19716,22 @@ Type1Font.prototype = {
getType2Subrs: function Type1Font_getType2Subrs(type1Subrs) {
var bias = 0;
var count = type1Subrs.length;
- if (count < 1133)
+ if (count < 1133) {
bias = 107;
- else if (count < 33769)
+ } else if (count < 33769) {
bias = 1131;
- else
+ } else {
bias = 32768;
+ }
// Add a bunch of empty subrs to deal with the Type2 bias
var type2Subrs = [];
- for (var i = 0; i < bias; i++)
+ var i;
+ for (i = 0; i < bias; i++) {
type2Subrs.push([0x0B]);
+ }
- for (var i = 0; i < count; i++) {
+ for (i = 0; i < count; i++) {
type2Subrs.push(type1Subrs[i]);
}
@@ -21721,22 +19772,23 @@ Type1Font.prototype = {
var count = glyphs.length;
var charsetArray = [0];
- for (var i = 0; i < count; i++) {
- var index = CFFStandardStrings.indexOf(charstrings[i].glyph);
- // Some characters like asterikmath && circlecopyrt are
- // missing from the original strings, for the moment let's
- // map them to .notdef and see later if it cause any
- // problems
- if (index == -1)
+ 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 (var i = 0; i < count; i++) {
+ for (i = 0; i < count; i++) {
charStringsIndex.add(glyphs[i]);
}
cff.charStrings = charStringsIndex;
@@ -21759,10 +19811,11 @@ Type1Font.prototype = {
'StdHW',
'StdVW'
];
- for (var i = 0, ii = fields.length; i < ii; i++) {
+ for (i = 0, ii = fields.length; i < ii; i++) {
var field = fields[i];
- if (!properties.privateData.hasOwnProperty(field))
+ 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
@@ -21776,7 +19829,7 @@ Type1Font.prototype = {
cff.topDict.privateDict = privateDict;
var subrIndex = new CFFIndex();
- for (var i = 0, ii = subrs.length; i < ii; i++) {
+ for (i = 0, ii = subrs.length; i < ii; i++) {
subrIndex.add(subrs[i]);
}
privateDict.subrsIndex = subrIndex;
@@ -21793,7 +19846,7 @@ var CFFFont = (function CFFFontClosure() {
var parser = new CFFParser(file, properties);
this.cff = parser.parse();
var compiler = new CFFCompiler(this.cff);
- this.readExtra();
+ this.seacs = this.cff.seacs;
try {
this.data = compiler.compile();
} catch (e) {
@@ -21805,111 +19858,42 @@ var CFFFont = (function CFFFontClosure() {
}
CFFFont.prototype = {
- readExtra: function CFFFont_readExtra() {
- // charstrings contains info about glyphs (one element per glyph
- // containing mappings for {unicode, width})
- var charstrings = this.getCharStrings();
-
- // create the mapping between charstring and glyph id
- var glyphIds = [];
- for (var i = 0, ii = charstrings.length; i < ii; i++)
- glyphIds.push(charstrings[i].gid);
-
- this.charstrings = charstrings;
- this.glyphIds = glyphIds;
- this.seacs = this.cff.seacs;
+ get numGlyphs() {
+ return this.cff.charStrings.count;
},
- getCharStrings: function CFFFont_getCharStrings() {
+ 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 encoding = cff.encoding ? cff.encoding.encoding : null;
- var charstrings = [];
- var unicodeUsed = [];
- var unassignedUnicodeItems = [];
- var inverseEncoding = [];
- var gidStart = 0;
- if (charsets[0] === '.notdef') {
- gidStart = 1;
- }
- // According to section 9.7.4.2 CIDFontType0C glyph selection should be
- // handled differently.
- if (this.properties.subtype === 'CIDFontType0C') {
- if (this.cff.isCIDFont) {
+ 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.
- inverseEncoding = charsets;
+ 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.
- inverseEncoding = [];
- for (var i = 0, ii = cff.charStrings.count; i < ii; i++) {
- inverseEncoding.push(i);
- }
- // Use the identity map for charsets as well.
- charsets = inverseEncoding;
- }
- } else {
- for (var charcode in encoding) {
- var gid = encoding[charcode];
- if (gid in inverseEncoding) {
- // Glyphs can be multiply-encoded if there was an encoding
- // supplement. Convert to an array and append the charcode.
- var previousCharcode = inverseEncoding[gid];
- if (!isArray(previousCharcode)) {
- inverseEncoding[gid] = [previousCharcode];
- }
- inverseEncoding[gid].push(charcode | 0);
- } else {
- inverseEncoding[gid] = charcode | 0;
+ for (glyphId = 0; glyphId < cff.charStrings.count; glyphId++) {
+ charCodeToGlyphId[glyphId] = glyphId;
}
}
+ return charCodeToGlyphId;
}
- for (var i = gidStart, ii = charsets.length; i < ii; i++) {
- var glyph = charsets[i];
-
- var codes = inverseEncoding[i];
- if (!isArray(codes)) {
- codes = [codes];
- }
-
- for (var j = 0; j < codes.length; j++) {
- var code = codes[j];
-
- if (!code || isSpecialUnicode(code)) {
- unassignedUnicodeItems.push(i, code);
- continue;
- }
- charstrings.push({
- unicode: code,
- code: code,
- gid: i,
- glyph: glyph
- });
- unicodeUsed[code] = true;
- }
- }
-
- var nextUnusedUnicode = CMAP_GLYPH_OFFSET;
- for (var j = 0, jj = unassignedUnicodeItems.length; j < jj; j += 2) {
- var i = unassignedUnicodeItems[j];
- // giving unicode value anyway
- while (nextUnusedUnicode in unicodeUsed)
- nextUnusedUnicode++;
- var unicode = nextUnusedUnicode++;
- charstrings.push({
- unicode: unicode,
- code: unassignedUnicodeItems[j + 1] || 0,
- gid: i,
- glyph: charsets[i]
- });
- }
-
- // sort the array by the unicode value (again)
- charstrings.sort(function getCharStringsSort(a, b) {
- return a.unicode - b.unicode;
- });
- return charstrings;
+ var encoding = cff.encoding ? cff.encoding.encoding : null;
+ charCodeToGlyphId = type1FontGlyphMapping(properties, encoding, charsets);
+ return charCodeToGlyphId;
}
};
@@ -21919,10 +19903,10 @@ var CFFFont = (function CFFFontClosure() {
var CFFParser = (function CFFParserClosure() {
var CharstringValidationData = [
null,
- { id: 'hstem', min: 2, resetStack: true, stem: true },
+ { id: 'hstem', min: 2, stackClearing: true, stem: true },
null,
- { id: 'vstem', min: 2, resetStack: true, stem: true },
- { id: 'vmoveto', min: 1, resetStack: true },
+ { 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 },
@@ -21932,16 +19916,16 @@ var CFFParser = (function CFFParserClosure() {
{ id: 'return', min: 0, undefStack: true },
null, // 12
null,
- null, // endchar
+ { id: 'endchar', min: 0, stackClearing: true },
null,
null,
null,
- { id: 'hstemhm', min: 2, resetStack: true, stem: true },
- null, // hintmask
- null, // cntrmask
- { id: 'rmoveto', min: 2, resetStack: true },
- { id: 'hmoveto', min: 1, resetStack: true },
- { id: 'vstemhm', min: 2, resetStack: true, stem: true },
+ { 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 },
@@ -22047,6 +20031,7 @@ var CFFParser = (function CFFParserClosure() {
var charStringsAndSeacs = this.parseCharStrings(charStringOffset);
cff.charStrings = charStringsAndSeacs.charStrings;
cff.seacs = charStringsAndSeacs.seacs;
+ cff.widths = charStringsAndSeacs.widths;
var fontMatrix = topDict.getByName('FontMatrix');
if (fontMatrix) {
@@ -22091,12 +20076,17 @@ var CFFParser = (function CFFParserClosure() {
},
parseHeader: function CFFParser_parseHeader() {
var bytes = this.bytes;
+ var bytesLength = bytes.length;
var offset = 0;
- while (bytes[offset] != 1)
+ // 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 !== 0) {
+ }
+ if (offset >= bytesLength) {
+ error('Invalid CFF header');
+ } else if (offset !== 0) {
info('cff data is shifted');
bytes = bytes.subarray(offset);
this.bytes = bytes;
@@ -22106,7 +20096,7 @@ var CFFParser = (function CFFParserClosure() {
var hdrSize = bytes[2];
var offSize = bytes[3];
var header = new CFFHeader(major, minor, hdrSize, offSize);
- return {obj: header, endPos: hdrSize};
+ return { obj: header, endPos: hdrSize };
},
parseDict: function CFFParser_parseDict(dict) {
var pos = 0;
@@ -22148,12 +20138,14 @@ var CFFParser = (function CFFParserClosure() {
var b1 = b >> 4;
var b2 = b & 15;
- if (b1 == eof)
+ if (b1 === eof) {
break;
+ }
str += lookup[b1];
- if (b2 == eof)
+ if (b2 === eof) {
break;
+ }
str += lookup[b2];
}
return parseFloat(str);
@@ -22162,13 +20154,14 @@ var CFFParser = (function CFFParserClosure() {
var operands = [];
var entries = [];
- var pos = 0;
+ pos = 0;
var end = dict.length;
while (pos < end) {
var b = dict[pos];
if (b <= 21) {
- if (b === 12)
+ if (b === 12) {
b = (b << 8) | dict[++pos];
+ }
entries.push([b, operands]);
operands = [];
++pos;
@@ -22183,15 +20176,15 @@ var CFFParser = (function CFFParserClosure() {
var bytes = this.bytes;
var count = (bytes[pos++] << 8) | bytes[pos++];
var offsets = [];
- var start = pos;
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 (var i = 0, ii = count + 1; i < ii; ++i) {
+ for (i = 0, ii = count + 1; i < ii; ++i) {
var offset = 0;
for (var j = 0; j < offsetSize; ++j) {
offset <<= 8;
@@ -22201,7 +20194,7 @@ var CFFParser = (function CFFParserClosure() {
}
end = offsets[count];
}
- for (var i = 0, ii = offsets.length - 1; i < ii; ++i) {
+ 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));
@@ -22225,13 +20218,13 @@ var CFFParser = (function CFFParserClosure() {
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 === 47 /* / */ || c === 37 /* % */ || c === 35 /* # */) {
data[j] = 95;
continue;
}
data[j] = c;
}
- names.push(String.fromCharCode.apply(null, data));
+ names.push(bytesToString(data));
}
return names;
},
@@ -22239,14 +20232,12 @@ var CFFParser = (function CFFParserClosure() {
var strings = new CFFStrings();
for (var i = 0, ii = index.count; i < ii; ++i) {
var data = index.get(i);
- strings.add(String.fromCharCode.apply(null, data));
+ strings.add(bytesToString(data));
}
return strings;
},
createDict: function CFFParser_createDict(Type, dict, strings) {
var cffDict = new Type(strings);
- var types = cffDict.types;
-
for (var i = 0, ii = dict.length; i < ii; ++i) {
var pair = dict[i];
var key = pair[0];
@@ -22258,6 +20249,7 @@ var CFFParser = (function CFFParserClosure() {
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);
@@ -22269,10 +20261,11 @@ var CFFParser = (function CFFParserClosure() {
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) {
+ if (value === 12) {
var q = data[j++];
if (q === 0) {
// The CFF specification state that the 'dotsection' command
@@ -22290,7 +20283,7 @@ var CFFParser = (function CFFParserClosure() {
stack[stackSize] = ((data[j] << 24) | (data[j + 1] << 16)) >> 16;
j += 2;
stackSize++;
- } else if (value == 14) {
+ } else if (value === 14) {
if (stackSize >= 4) {
stackSize -= 4;
if (SEAC_ANALYSIS_ENABLED) {
@@ -22298,24 +20291,26 @@ var CFFParser = (function CFFParserClosure() {
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;
+ 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)
+ } else if (value === 255) { // number (32 bit)
stack[stackSize] = ((data[j] << 24) | (data[j + 1] << 16) |
- (data[j + 2] << 8) | data[j + 3]) / 65536;
+ (data[j + 2] << 8) | data[j + 3]) / 65536;
j += 4;
stackSize++;
- } else if (value == 19 || value == 20) {
+ } else if (value === 19 || value === 20) {
hints += stackSize >> 1;
j += (hints + 7) >> 3; // skipping right amount of hints flag data
- stackSize = 0;
+ stackSize %= 2;
+ validationCommand = CharstringValidationData[value];
} else {
validationCommand = CharstringValidationData[value];
}
@@ -22332,17 +20327,35 @@ var CFFParser = (function CFFParserClosure() {
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;
}
}
}
@@ -22351,7 +20364,7 @@ var CFFParser = (function CFFParserClosure() {
charStrings.set(i, new Uint8Array([14]));
}
}
- return { charStrings: charStrings, seacs: seacs };
+ return { charStrings: charStrings, seacs: seacs, widths: widths };
},
emptyPrivateDictionary:
function CFFParser_emptyPrivateDictionary(parentDict) {
@@ -22388,8 +20401,9 @@ var CFFParser = (function CFFParserClosure() {
parentDict.privateDict = privateDict;
// Parse the Subrs index also since it's relative to the private dict.
- if (!privateDict.getByName('Subrs'))
+ if (!privateDict.getByName('Subrs')) {
return;
+ }
var subrsOffset = privateDict.getByName('Subrs');
var relativeOffset = offset + subrsOffset;
// Validate the offset.
@@ -22404,10 +20418,10 @@ var CFFParser = (function CFFParserClosure() {
if (pos === 0) {
return new CFFCharset(true, CFFCharsetPredefinedTypes.ISO_ADOBE,
ISOAdobeCharset);
- } else if (pos == 1) {
+ } else if (pos === 1) {
return new CFFCharset(true, CFFCharsetPredefinedTypes.EXPERT,
ExpertCharset);
- } else if (pos == 2) {
+ } else if (pos === 2) {
return new CFFCharset(true, CFFCharsetPredefinedTypes.EXPERT_SUBSET,
ExpertSubsetCharset);
}
@@ -22416,31 +20430,34 @@ var CFFParser = (function CFFParserClosure() {
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 (var i = 0; i < length; i++) {
- var id = (bytes[pos++] << 8) | bytes[pos++];
+ 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) {
- var id = (bytes[pos++] << 8) | bytes[pos++];
- var count = bytes[pos++];
- for (var i = 0; i <= count; i++)
+ 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) {
- var id = (bytes[pos++] << 8) | bytes[pos++];
- var count = (bytes[pos++] << 8) | bytes[pos++];
- for (var i = 0; i <= count; i++)
+ 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:
@@ -22460,47 +20477,49 @@ var CFFParser = (function CFFParserClosure() {
var bytes = this.bytes;
var predefined = false;
var hasSupplement = false;
- var format;
+ var format, i, ii;
var raw = null;
function readSupplement() {
var supplementsCount = bytes[pos++];
- for (var i = 0; i < supplementsCount; i++) {
+ 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) {
+ if (pos === 0 || pos === 1) {
predefined = true;
format = pos;
var baseEncoding = pos ? Encodings.ExpertEncoding :
Encodings.StandardEncoding;
- for (var i = 0, ii = charset.length; i < ii; i++) {
+ for (i = 0, ii = charset.length; i < ii; i++) {
var index = baseEncoding.indexOf(charset[i]);
- if (index != -1) {
+ if (index !== -1) {
encoding[index] = i;
}
}
} else {
var dataStart = pos;
- var format = bytes[pos++];
+ format = bytes[pos++];
switch (format & 0x7f) {
case 0:
var glyphsCount = bytes[pos++];
- for (var i = 1; i <= glyphsCount; i++)
+ for (i = 1; i <= glyphsCount; i++) {
encoding[bytes[pos++]] = i;
+ }
break;
case 1:
var rangesCount = bytes[pos++];
var gid = 1;
- for (var i = 0; i < rangesCount; i++) {
+ for (i = 0; i < rangesCount; i++) {
var start = bytes[pos++];
var left = bytes[pos++];
- for (var j = start; j <= start + left; j++)
+ for (var j = start; j <= start + left; j++) {
encoding[j] = gid++;
+ }
}
break;
@@ -22529,21 +20548,24 @@ var CFFParser = (function CFFParserClosure() {
var bytes = this.bytes;
var format = bytes[pos++];
var fdSelect = [];
+ var i;
+
switch (format) {
case 0:
- for (var i = 0; i < length; ++i) {
+ for (i = 0; i < length; ++i) {
var id = bytes[pos++];
fdSelect.push(id);
}
break;
case 3:
var rangesCount = (bytes[pos++] << 8) | bytes[pos++];
- for (var i = 0; i < rangesCount; ++i) {
+ 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)
+ for (var j = first; j < next; ++j) {
fdSelect.push(fdIndex);
+ }
}
// Advance past the sentinel(next).
pos += 2;
@@ -22597,10 +20619,12 @@ var CFFStrings = (function CFFStringsClosure() {
}
CFFStrings.prototype = {
get: function CFFStrings_get(index) {
- if (index >= 0 && index <= 390)
+ if (index >= 0 && index <= 390) {
return CFFStandardStrings[index];
- if (index - 391 <= this.strings.length)
+ }
+ if (index - 391 <= this.strings.length) {
return this.strings[index - 391];
+ }
return CFFStandardStrings[0];
},
add: function CFFStrings_add(value) {
@@ -22651,15 +20675,18 @@ var CFFDict = (function CFFDictClosure() {
CFFDict.prototype = {
// value should always be an array
setByKey: function CFFDict_setByKey(key, value) {
- if (!(key in this.keyToNameMap))
+ if (!(key in this.keyToNameMap)) {
return false;
+ }
// ignore empty values
- if (value.length === 0)
+ 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')
+ if (type === 'num' || type === 'sid' || type === 'offset') {
value = value[0];
+ }
this.values[key] = value;
return true;
},
@@ -22673,11 +20700,13 @@ var CFFDict = (function CFFDictClosure() {
return this.nameToKeyMap[name] in this.values;
},
getByName: function CFFDict_getByName(name) {
- if (!(name in this.nameToKeyMap))
+ if (!(name in this.nameToKeyMap)) {
error('Invalid dictionary name "' + name + '"');
+ }
var key = this.nameToKeyMap[name];
- if (!(key in this.values))
+ if (!(key in this.values)) {
return this.defaults[key];
+ }
return this.values[key];
},
removeByName: function CFFDict_removeByName(name) {
@@ -22750,8 +20779,9 @@ var CFFTopDict = (function CFFTopDictClosure() {
];
var tables = null;
function CFFTopDict(strings) {
- if (tables === null)
+ if (tables === null) {
tables = CFFDict.createTables(layout);
+ }
CFFDict.call(this, tables, strings);
this.privateDict = null;
}
@@ -22782,8 +20812,9 @@ var CFFPrivateDict = (function CFFPrivateDictClosure() {
];
var tables = null;
function CFFPrivateDict(strings) {
- if (tables === null)
+ if (tables === null) {
tables = CFFDict.createTables(layout);
+ }
CFFDict.call(this, tables, strings);
this.subrsIndex = null;
}
@@ -22796,11 +20827,6 @@ var CFFCharsetPredefinedTypes = {
EXPERT: 1,
EXPERT_SUBSET: 2
};
-var CFFCharsetEmbeddedTypes = {
- FORMAT0: 0,
- FORMAT1: 1,
- FORMAT2: 2
-};
var CFFCharset = (function CFFCharsetClosure() {
function CFFCharset(predefined, format, charset, raw) {
this.predefined = predefined;
@@ -22811,14 +20837,6 @@ var CFFCharset = (function CFFCharsetClosure() {
return CFFCharset;
})();
-var CFFEncodingPredefinedTypes = {
- STANDARD: 0,
- EXPERT: 1
-};
-var CFFCharsetEmbeddedTypes = {
- FORMAT0: 0,
- FORMAT1: 1
-};
var CFFEncoding = (function CFFEncodingClosure() {
function CFFEncoding(predefined, format, encoding, raw) {
this.predefined = predefined;
@@ -22848,8 +20866,9 @@ var CFFOffsetTracker = (function CFFOffsetTrackerClosure() {
return key in this.offsets;
},
track: function CFFOffsetTracker_track(key, location) {
- if (key in this.offsets)
+ if (key in this.offsets) {
error('Already tracking location of ' + key);
+ }
this.offsets[key] = location;
},
offset: function CFFOffsetTracker_offset(value) {
@@ -22860,8 +20879,9 @@ var CFFOffsetTracker = (function CFFOffsetTrackerClosure() {
setEntryLocation: function CFFOffsetTracker_setEntryLocation(key,
values,
output) {
- if (!(key in this.offsets))
+ if (!(key in this.offsets)) {
error('Not tracking location of ' + key);
+ }
var data = output.data;
var dataOffset = this.offsets[key];
var size = 5;
@@ -22873,8 +20893,9 @@ var CFFOffsetTracker = (function CFFOffsetTrackerClosure() {
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)
+ 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;
@@ -22889,13 +20910,6 @@ var CFFOffsetTracker = (function CFFOffsetTrackerClosure() {
// Takes a CFF and converts it to the binary representation.
var CFFCompiler = (function CFFCompilerClosure() {
- function stringToArray(str) {
- var array = [];
- for (var i = 0, ii = str.length; i < ii; ++i)
- array[i] = str.charCodeAt(i);
-
- return array;
- }
function CFFCompiler(cff) {
this.cff = cff;
}
@@ -22992,7 +21006,7 @@ var CFFCompiler = (function CFFCompilerClosure() {
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.
- var compiled = this.compileTopDicts(cff.fdArray, output.length, true);
+ compiled = this.compileTopDicts(cff.fdArray, output.length, true);
topDictTracker.setEntryLocation('FDArray', [output.length], output);
output.add(compiled.output);
var fontDictTrackers = compiled.trackers;
@@ -23009,10 +21023,11 @@ var CFFCompiler = (function CFFCompilerClosure() {
return output.data;
},
encodeNumber: function CFFCompiler_encodeNumber(value) {
- if (parseFloat(value) == parseInt(value, 10) && !isNaN(value)) // isInt
+ if (parseFloat(value) === parseInt(value, 10) && !isNaN(value)) { // isInt
return this.encodeInteger(value);
- else
+ } else {
return this.encodeFloat(value);
+ }
},
encodeFloat: function CFFCompiler_encodeFloat(num) {
var value = num.toString();
@@ -23025,7 +21040,8 @@ var CFFCompiler = (function CFFCompilerClosure() {
}
var nibbles = '';
- for (var i = 0, ii = value.length; i < ii; ++i) {
+ var i, ii;
+ for (i = 0, ii = value.length; i < ii; ++i) {
var a = value[i];
if (a === 'e') {
nibbles += value[++i] === '-' ? 'c' : 'b';
@@ -23039,7 +21055,7 @@ var CFFCompiler = (function CFFCompilerClosure() {
}
nibbles += (nibbles.length & 1) ? 'f' : 'ff';
var out = [30];
- for (var i = 0, ii = nibbles.length; i < ii; i += 2) {
+ for (i = 0, ii = nibbles.length; i < ii; i += 2) {
out.push(parseInt(nibbles.substr(i, 2), 16));
}
return out;
@@ -23075,8 +21091,9 @@ var CFFCompiler = (function CFFCompilerClosure() {
},
compileNameIndex: function CFFCompiler_compileNameIndex(names) {
var nameIndex = new CFFIndex();
- for (var i = 0, ii = names.length; i < ii; ++i)
- nameIndex.add(stringToArray(names[i]));
+ for (var i = 0, ii = names.length; i < ii; ++i) {
+ nameIndex.add(stringToBytes(names[i]));
+ }
return this.compileIndex(nameIndex);
},
compileTopDicts: function CFFCompiler_compileTopDicts(dicts,
@@ -23144,16 +21161,22 @@ var CFFCompiler = (function CFFCompilerClosure() {
var order = dict.order;
for (var i = 0; i < order.length; ++i) {
var key = order[i];
- if (!(key in dict.values))
+ 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];
+ if (!isArray(types)) {
+ types = [types];
+ }
+ if (!isArray(values)) {
+ values = [values];
+ }
// Remove any empty dict values.
- if (values.length === 0)
+ if (values.length === 0) {
continue;
+ }
for (var j = 0, jj = types.length; j < jj; ++j) {
var type = types[j];
@@ -23170,15 +21193,17 @@ var CFFCompiler = (function CFFCompilerClosure() {
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))
+ 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)
+ 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);
@@ -23191,8 +21216,9 @@ var CFFCompiler = (function CFFCompilerClosure() {
},
compileStringIndex: function CFFCompiler_compileStringIndex(strings) {
var stringIndex = new CFFIndex();
- for (var i = 0, ii = strings.length; i < ii; ++i)
- stringIndex.add(stringToArray(strings[i]));
+ for (var i = 0, ii = strings.length; i < ii; ++i) {
+ stringIndex.add(stringToBytes(strings[i]));
+ }
return this.compileIndex(stringIndex);
},
compileGlobalSubrIndex: function CFFCompiler_compileGlobalSubrIndex() {
@@ -23213,8 +21239,9 @@ var CFFCompiler = (function CFFCompilerClosure() {
},
compileTypedArray: function CFFCompiler_compileTypedArray(data) {
var out = [];
- for (var i = 0, ii = data.length; i < ii; ++i)
+ for (var i = 0, ii = data.length; i < ii; ++i) {
out[i] = data[i];
+ }
return out;
},
compileIndex: function CFFCompiler_compileIndex(index, trackers) {
@@ -23225,31 +21252,34 @@ var CFFCompiler = (function CFFCompilerClosure() {
// 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)
+ if (count === 0) {
return [0, 0, 0];
+ }
var data = [(count >> 8) & 0xFF, count & 0xff];
- var lastOffset = 1;
- for (var i = 0; i < count; ++i)
+ var lastOffset = 1, i;
+ for (i = 0; i < count; ++i) {
lastOffset += objects[i].length;
+ }
var offsetSize;
- if (lastOffset < 0x100)
+ if (lastOffset < 0x100) {
offsetSize = 1;
- else if (lastOffset < 0x10000)
+ } else if (lastOffset < 0x10000) {
offsetSize = 2;
- else if (lastOffset < 0x1000000)
+ } else if (lastOffset < 0x1000000) {
offsetSize = 3;
- else
+ } 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 (var i = 0; i < count + 1; i++) {
+ for (i = 0; i < count + 1; i++) {
if (offsetSize === 1) {
data.push(relativeOffset & 0xFF);
} else if (offsetSize === 2) {
@@ -23266,17 +21296,19 @@ var CFFCompiler = (function CFFCompilerClosure() {
relativeOffset & 0xFF);
}
- if (objects[i])
+ if (objects[i]) {
relativeOffset += objects[i].length;
+ }
}
- var offset = data.length;
- for (var i = 0; i < count; i++) {
+ for (i = 0; i < count; i++) {
// Notify the tracker where the object will be offset in the data.
- if (trackers[i])
+ if (trackers[i]) {
trackers[i].offset(data.length);
- for (var j = 0, jj = objects[i].length; j < jj; j++)
+ }
+ for (var j = 0, jj = objects[i].length; j < jj; j++) {
data.push(objects[i][j]);
+ }
}
return data;
}
@@ -23296,7 +21328,7 @@ var CFFCompiler = (function CFFCompilerClosure() {
// https://github.com/mozilla/pdf.js/issues/1689
(function checkChromeWindows() {
if (/Windows.*Chrome/.test(navigator.userAgent)) {
- SYMBOLIC_FONT_GLYPH_OFFSET = 0xF100;
+ SKIP_PRIVATE_USE_RANGE_F000_TO_F01F = true;
}
})();
@@ -23312,25 +21344,26 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
}
function parseCmap(data, start, end) {
- var offset = getUshort(data, start + 2) === 1 ? getLong(data, start + 8) :
- getLong(data, start + 16);
+ 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) {
- var length = getUshort(data, start + offset + 2);
+ length = getUshort(data, start + offset + 2);
var segCount = getUshort(data, start + offset + 6) >> 1;
- var p = start + offset + 14;
- var ranges = [];
- for (var i = 0; i < segCount; i++, p += 2) {
+ p = start + offset + 14;
+ ranges = [];
+ for (i = 0; i < segCount; i++, p += 2) {
ranges[i] = {end: getUshort(data, p)};
}
p += 2;
- for (var i = 0; i < segCount; i++, p += 2) {
+ for (i = 0; i < segCount; i++, p += 2) {
ranges[i].start = getUshort(data, p);
}
- for (var i = 0; i < segCount; i++, p += 2) {
+ for (i = 0; i < segCount; i++, p += 2) {
ranges[i].idDelta = getUshort(data, p);
}
- for (var i = 0; i < segCount; i++, p += 2) {
+ for (i = 0; i < segCount; i++, p += 2) {
var idOffset = getUshort(data, p);
if (idOffset === 0) {
continue;
@@ -23343,11 +21376,11 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
}
return ranges;
} else if (format === 12) {
- var length = getLong(data, start + offset + 4);
+ length = getLong(data, start + offset + 4);
var groups = getLong(data, start + offset + 12);
- var p = start + offset + 16;
- var ranges = [];
- for (var i = 0; i < groups; i++) {
+ p = start + offset + 16;
+ ranges = [];
+ for (i = 0; i < groups; i++) {
ranges.push({
start: getLong(data, p),
end: getLong(data, p + 4),
@@ -23362,13 +21395,13 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
function parseCff(data, start, end) {
var properties = {};
- var parser = new CFFParser(
- new Stream(data, start, end - start), 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,
+ subrs: (cff.topDict.privateDict && cff.topDict.privateDict.subrsIndex &&
+ cff.topDict.privateDict.subrsIndex.objects),
gsubrs: cff.globalSubrIndex && cff.globalSubrIndex.objects
};
}
@@ -23429,16 +21462,13 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
var i = 0;
var numberOfContours = ((code[i] << 24) | (code[i + 1] << 16)) >> 16;
- var xMin = ((code[i + 2] << 24) | (code[i + 3] << 16)) >> 16;
- var yMin = ((code[i + 4] << 24) | (code[i + 5] << 16)) >> 16;
- var xMax = ((code[i + 6] << 24) | (code[i + 7] << 16)) >> 16;
- var yMax = ((code[i + 8] << 24) | (code[i + 9] << 16)) >> 16;
+ var flags;
+ var x = 0, y = 0;
i += 10;
if (numberOfContours < 0) {
// composite glyph
- var x = 0, y = 0;
do {
- var flags = (code[i] << 8) | code[i + 1];
+ flags = (code[i] << 8) | code[i + 1];
var glyphIndex = (code[i + 2] << 8) | code[i + 3];
i += 4;
var arg1, arg2;
@@ -23483,7 +21513,8 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
} else {
// simple glyph
var endPtsOfContours = [];
- for (var j = 0; j < numberOfContours; j++) {
+ var j, jj;
+ for (j = 0; j < numberOfContours; j++) {
endPtsOfContours.push((code[i] << 8) | code[i + 1]);
i += 2;
}
@@ -23492,7 +21523,8 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
var numberOfPoints = endPtsOfContours[endPtsOfContours.length - 1] + 1;
var points = [];
while (points.length < numberOfPoints) {
- var flags = code[i++], repeat = 1;
+ flags = code[i++];
+ var repeat = 1;
if ((flags & 0x08)) {
repeat += code[i++];
}
@@ -23500,8 +21532,7 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
points.push({flags: flags});
}
}
- var x = 0, y = 0;
- for (var j = 0; j < numberOfPoints; j++) {
+ for (j = 0; j < numberOfPoints; j++) {
switch (points[j].flags & 0x12) {
case 0x00:
x += ((code[i] << 24) | (code[i + 1] << 16)) >> 16;
@@ -23516,7 +21547,7 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
}
points[j].x = x;
}
- for (var j = 0; j < numberOfPoints; j++) {
+ for (j = 0; j < numberOfPoints; j++) {
switch (points[j].flags & 0x24) {
case 0x00:
y += ((code[i] << 24) | (code[i + 1] << 16)) >> 16;
@@ -23533,7 +21564,7 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
}
var startPoint = 0;
- for (var i = 0; i < numberOfContours; i++) {
+ 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
@@ -23554,7 +21585,7 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
contour.push(p);
}
moveTo(contour[0].x, contour[0].y);
- for (var j = 1, jj = contour.length; j < jj; j++) {
+ 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)){
@@ -23593,6 +21624,7 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
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;
@@ -23638,15 +21670,15 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
break;
case 8: // rrcurveto
while (stack.length > 0) {
- var xa = x + stack.shift(), ya = y + stack.shift();
- var xb = xa + stack.shift(), yb = ya + stack.shift();
+ 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
- var n = stack.pop() + font.subrsBias;
- var subrCode = font.subrs[n];
+ n = stack.pop() + font.subrsBias;
+ subrCode = font.subrs[n];
if (subrCode) {
parse(subrCode);
}
@@ -23657,49 +21689,50 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
v = code[i++];
switch (v) {
case 34: // flex
- var xa = x + stack.shift();
- var xb = xa + stack.shift(), y1 = y + stack.shift();
+ xa = x + stack.shift();
+ xb = xa + stack.shift(); y1 = y + stack.shift();
x = xb + stack.shift();
bezierCurveTo(xa, y, xb, y1, x, y1);
- var xa = x + stack.shift();
- var xb = xa + stack.shift();
+ xa = x + stack.shift();
+ xb = xa + stack.shift();
x = xb + stack.shift();
bezierCurveTo(xa, y1, xb, y, x, y);
break;
case 35: // flex
- var xa = x + stack.shift(), ya = y + stack.shift();
- var xb = xa + stack.shift(), yb = ya + stack.shift();
+ 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);
- var xa = x + stack.shift(), ya = y + stack.shift();
- var xb = xa + stack.shift(), yb = ya + stack.shift();
+ 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
- var xa = x + stack.shift(), y1 = y + stack.shift();
- var xb = xa + stack.shift(), y2 = y1 + stack.shift();
+ 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);
- var xa = x + stack.shift();
- var xb = xa + stack.shift(), y3 = y2 + stack.shift();
+ 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;
- var xa = x + stack.shift(), ya = y + stack.shift();
- var xb = xa + stack.shift(), yb = ya + stack.shift();
+ 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);
- var xa = x + stack.shift(), ya = y + stack.shift();
- var xb = xa + stack.shift(), yb = ya + stack.shift();
+ 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))
+ if (Math.abs(x - x0) > Math.abs(y - y0)) {
x += stack.shift();
- else
+ } else {
y += stack.shift();
+ }
bezierCurveTo(xa, ya, xb, yb, x, y);
break;
default:
@@ -23755,8 +21788,8 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
break;
case 24: // rcurveline
while (stack.length > 2) {
- var xa = x + stack.shift(), ya = y + stack.shift();
- var xb = xa + stack.shift(), yb = ya + stack.shift();
+ 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);
}
@@ -23770,8 +21803,8 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
y += stack.shift();
lineTo(x, y);
}
- var xa = x + stack.shift(), ya = y + stack.shift();
- var xb = xa + stack.shift(), yb = ya + stack.shift();
+ 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;
@@ -23780,8 +21813,8 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
x += stack.shift();
}
while (stack.length > 0) {
- var xa = x, ya = y + stack.shift();
- var xb = xa + stack.shift(), yb = ya + stack.shift();
+ 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);
}
@@ -23791,8 +21824,8 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
y += stack.shift();
}
while (stack.length > 0) {
- var xa = x + stack.shift(), ya = y;
- var xb = xa + stack.shift(), yb = ya + stack.shift();
+ 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);
}
@@ -23802,16 +21835,16 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
i += 2;
break;
case 29: // callgsubr
- var n = stack.pop() + font.gsubrsBias;
- var subrCode = font.gsubrs[n];
+ n = stack.pop() + font.gsubrsBias;
+ subrCode = font.gsubrs[n];
if (subrCode) {
parse(subrCode);
}
break;
case 30: // vhcurveto
while (stack.length > 0) {
- var xa = x, ya = y + stack.shift();
- var xb = xa + stack.shift(), yb = ya + stack.shift();
+ 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);
@@ -23819,8 +21852,8 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
break;
}
- var xa = x + stack.shift(), ya = y;
- var xb = xa + stack.shift(), yb = ya + stack.shift();
+ 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);
@@ -23828,8 +21861,8 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
break;
case 31: // hvcurveto
while (stack.length > 0) {
- var xa = x + stack.shift(), ya = y;
- var xb = xa + stack.shift(), yb = ya + stack.shift();
+ 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);
@@ -23837,23 +21870,24 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
break;
}
- var xa = x, ya = y + stack.shift();
- var xb = xa + stack.shift(), yb = ya + stack.shift();
+ 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)
+ if (v < 32) {
error('unknown operator: ' + v);
- if (v < 247)
+ }
+ if (v < 247) {
stack.push(v - 139);
- else if (v < 251)
+ } else if (v < 251) {
stack.push((v - 247) * 256 + code[i++] + 108);
- else if (v < 255)
+ } else if (v < 255) {
stack.push(-(v - 251) * 256 - code[i++] - 108);
- else {
+ } else {
stack.push(((code[i] << 24) | (code[i + 1] << 16) |
(code[i + 2] << 8) | code[i + 3]) / 65536);
i += 4;
@@ -23937,10 +21971,10 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
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;
+ 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, {
@@ -23956,7 +21990,7 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
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 = String.fromCharCode.apply(null, data.subarray(p, p + 4));
+ var tag = bytesToString(data.subarray(p, p + 4));
var offset = getLong(data, p + 8);
var length = getLong(data, p + 12);
switch (tag) {
@@ -23980,8 +22014,8 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
}
if (glyf) {
- var fontMatrix = !unitsPerEm ? font.fontMatrix :
- [1 / unitsPerEm, 0, 0, 1 / unitsPerEm, 0, 0];
+ var fontMatrix = (!unitsPerEm ? font.fontMatrix :
+ [1 / unitsPerEm, 0, 0, 1 / unitsPerEm, 0, 0]);
return new TrueTypeCompiled(
parseGlyfTable(glyf, loca, indexToLocFormat), cmap, fontMatrix);
} else {
@@ -28200,6 +26234,211 @@ var GlyphsUnicode = {
'.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() {
@@ -28207,22 +26446,24 @@ 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, promise) {
+ 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;
- handler.send('JpegDecode', [image.getIR(), numComps], function(message) {
+ var decodePromise = handler.sendWithPromise('JpegDecode',
+ [image.getIR(), numComps]);
+ return decodePromise.then(function (message) {
var data = message.data;
- var stream = new Stream(data, 0, data.length, image.dict);
- promise.resolve(stream);
+ return new Stream(data, 0, data.length, image.dict);
});
} else {
- promise.resolve(image);
+ 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.
@@ -28230,26 +26471,34 @@ var PDFImage = (function PDFImageClosure() {
function decodeAndClamp(value, addend, coefficient, max) {
value = addend + value * coefficient;
// Clamp the value to the range
- return value < 0 ? 0 : value > max ? max : value;
+ return (value < 0 ? 0 : (value > max ? max : value));
}
+
function PDFImage(xref, res, image, inline, smask, mask, isMask) {
this.image = image;
- if (image.getParams) {
- // JPX/JPEG2000 streams directly contain bits per component
- // and color space mode information.
- warn('get params from actual stream');
- // var bits = ...
- // var colorspace = ...
+ 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?
- var dict = image.dict;
this.width = dict.get('Width', 'W');
this.height = dict.get('Height', 'H');
- if (this.width < 1 || this.height < 1)
+ 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;
@@ -28259,10 +26508,11 @@ var PDFImage = (function PDFImageClosure() {
if (!bitsPerComponent) {
bitsPerComponent = dict.get('BitsPerComponent', 'BPC');
if (!bitsPerComponent) {
- if (this.imageMask)
+ if (this.imageMask) {
bitsPerComponent = 1;
- else
+ } else {
error('Bits per component missing in image: ' + this.imageMask);
+ }
}
}
this.bpc = bitsPerComponent;
@@ -28270,8 +26520,21 @@ var PDFImage = (function PDFImageClosure() {
if (!this.imageMask) {
var colorSpace = dict.get('ColorSpace', 'CS');
if (!colorSpace) {
- warn('JPX images (which don"t require color spaces');
- colorSpace = new Name('DeviceRGB');
+ 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;
@@ -28307,51 +26570,47 @@ var PDFImage = (function PDFImageClosure() {
}
}
/**
- * Handles processing of image data and calls the callback with an argument
- * of a PDFImage when the image is ready to be used.
+ * 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(callback, handler, xref,
+ PDFImage.buildImage = function PDFImage_buildImage(handler, xref,
res, image, inline) {
- var imageDataPromise = new LegacyPromise();
- var smaskPromise = new LegacyPromise();
- var maskPromise = new LegacyPromise();
- // The image data and smask data may not be ready yet, wait till both are
- // resolved.
- Promise.all([imageDataPromise, smaskPromise, maskPromise]).then(
- function(results) {
- var imageData = results[0], smaskData = results[1], maskData = results[2];
- var image = new PDFImage(xref, res, imageData, inline, smaskData,
- maskData);
- callback(image);
- });
-
- handleImageData(handler, xref, res, image, imageDataPromise);
+ 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) {
- handleImageData(handler, xref, res, smask, smaskPromise);
- maskPromise.resolve(null);
+ smaskPromise = handleImageData(handler, xref, res, smask);
+ maskPromise = Promise.resolve(null);
} else {
- smaskPromise.resolve(null);
+ smaskPromise = Promise.resolve(null);
if (mask) {
if (isStream(mask)) {
- handleImageData(handler, xref, res, mask, maskPromise);
+ maskPromise = handleImageData(handler, xref, res, mask);
} else if (isArray(mask)) {
- maskPromise.resolve(mask);
+ maskPromise = Promise.resolve(mask);
} else {
warn('Unsupported mask format.');
- maskPromise.resolve(null);
+ maskPromise = Promise.resolve(null);
}
} else {
- maskPromise.resolve(null);
+ 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
+ * 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.
@@ -28360,49 +26619,92 @@ var PDFImage = (function PDFImageClosure() {
* @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) {
+ w1, h1, w2, h2, dest, alpha01) {
+
+ if (components !== 1 && components !== 3) {
+ error('Unsupported component count for resizing.');
+ }
+
var length = w2 * h2 * components;
- var temp = bpc <= 8 ? new Uint8Array(length) :
- bpc <= 16 ? new Uint16Array(length) : new Uint32Array(length);
+ 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 px, py, newIndex, oldIndex;
- for (var i = 0; i < h2; i++) {
- for (var j = 0; j < w2; j++) {
- px = Math.floor(j * xRatio);
- py = Math.floor(i * yRatio);
- newIndex = (i * w2) + j;
- oldIndex = ((py * w1) + px);
- if (components === 1) {
- temp[newIndex] = pixels[oldIndex];
- } else if (components === 3) {
- newIndex *= 3;
- oldIndex *= 3;
- temp[newIndex] = pixels[oldIndex];
- temp[newIndex + 1] = pixels[oldIndex + 1];
- temp[newIndex + 2] = pixels[oldIndex + 2];
+ 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,
- inverseDecode) {
- // Copy imgArray into a typed array (inverting if necessary) so it can be
- // transferred to the main thread.
- var length = ((width + 7) >> 3) * height;
- var data = new Uint8Array(length);
- if (inverseDecode) {
- for (var i = 0; i < length; i++) {
- data[i] = ~imgArray[i];
- }
+ 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 {
- for (var i = 0; i < length; i++) {
- data[i] = imgArray[i];
+ 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];
}
}
@@ -28411,85 +26713,100 @@ var PDFImage = (function PDFImageClosure() {
PDFImage.prototype = {
get drawWidth() {
- if (!this.smask)
- return this.width;
- return Math.max(this.width, this.smask.width);
+ return Math.max(this.width,
+ this.smask && this.smask.width || 0,
+ this.mask && this.mask.width || 0);
},
+
get drawHeight() {
- if (!this.smask)
- return this.height;
- return Math.max(this.height, this.smask.height);
+ 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 decodeMap = this.decode;
var numComps = this.numComps;
- var decodeAddends, decodeCoefficients;
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 (var i = 0, ii = buffer.length; i < ii; i++) {
+ for (i = 0, ii = buffer.length; i < ii; i++) {
buffer[i] = +!(buffer[i]);
}
return;
}
var index = 0;
- for (var i = 0, ii = this.width * this.height; i < ii; i++) {
+ 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);
+ decodeCoefficients[j], max);
index++;
}
}
},
+
getComponents: function PDFImage_getComponents(buffer) {
var bpc = this.bpc;
// This image doesn't require any extra work.
- if (bpc === 8)
+ if (bpc === 8) {
return buffer;
+ }
- var bufferLength = buffer.length;
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 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 = 0;
- var buf = 0;
+ var mask, loop1End, loop2End;
+ for (var j = 0; j < height; j++) {
+ loop1End = i + (rowComps & ~7);
+ loop2End = i + rowComps;
- for (var i = 0, ii = length; i < ii; ++i) {
- if (i % rowComps === 0) {
- mask = 0;
- buf = 0;
- } else {
- mask >>= 1;
+ // 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;
}
- if (mask <= 0) {
+ // handle remaing bits
+ if (i < loop2End) {
buf = buffer[bufferPos++];
mask = 128;
+ while (i < loop2End) {
+ output[i++] = +!!(buf & mask);
+ mask >>= 1;
+ }
}
-
- output[i] = +!!(buf & mask);
}
} else {
// The general case that handles all other bpc values.
- var bits = 0, buf = 0;
- for (var i = 0, ii = length; i < ii; ++i) {
+ var bits = 0;
+ buf = 0;
+ for (i = 0, ii = length; i < ii; ++i) {
if (i % rowComps === 0) {
buf = 0;
bits = 0;
@@ -28502,51 +26819,55 @@ var PDFImage = (function PDFImageClosure() {
var remainingBits = bits - bpc;
var value = buf >> remainingBits;
- output[i] = value < 0 ? 0 : value > max ? max : value;
+ 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;
+ var alphaBuf, sw, sh, i, ii, j;
if (smask) {
- var sw = smask.width;
- var sh = smask.height;
+ sw = smask.width;
+ sh = smask.height;
alphaBuf = new Uint8Array(sw * sh);
smask.fillGrayBuffer(alphaBuf);
- if (sw != width || sh != height)
+ if (sw !== width || sh !== height) {
alphaBuf = PDFImage.resize(alphaBuf, smask.bpc, 1, sw, sh, width,
height);
+ }
} else if (mask) {
if (mask instanceof PDFImage) {
- var sw = mask.width;
- var sh = mask.height;
+ sw = mask.width;
+ sh = mask.height;
alphaBuf = new Uint8Array(sw * sh);
mask.numComps = 1;
mask.fillGrayBuffer(alphaBuf);
// Need to invert values in rgbaBuf
- for (var i = 0, ii = sw * sh; i < ii; ++i)
+ for (i = 0, ii = sw * sh; i < ii; ++i) {
alphaBuf[i] = 255 - alphaBuf[i];
+ }
- if (sw != width || sh != height)
+ 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 (var i = 0, ii = width * height; i < ii; ++i) {
+ for (i = 0, ii = width * height; i < ii; ++i) {
var opacity = 0;
var imageOffset = i * numComps;
- for (var j = 0; j < numComps; ++j) {
+ for (j = 0; j < numComps; ++j) {
var color = image[imageOffset + j];
var maskOffset = j * 2;
if (color < mask[maskOffset] || color > mask[maskOffset + 1]) {
@@ -28562,109 +26883,206 @@ var PDFImage = (function PDFImageClosure() {
}
if (alphaBuf) {
- for (var i = 0, j = 3, ii = width * actualHeight; i < ii; ++i, j += 4) {
+ for (i = 0, j = 3, ii = width * actualHeight; i < ii; ++i, j += 4) {
rgbaBuf[j] = alphaBuf[i];
}
} else {
- // Common case: no mask (and no need to allocate the extra buffer).
- for (var i = 0, j = 3, ii = width * actualHeight; i < ii; ++i, j += 4) {
+ // 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;
}
-
- function clamp(value) {
- return (value < 0 ? 0 : value > 255 ? 255 : value) | 0;
- }
-
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 as white (tipical paper color) should be okay
+ // 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;
- buffer[i] = clamp((buffer[i] - matteRgb[0]) * k + matteRgb[0]);
- buffer[i + 1] = clamp((buffer[i + 1] - matteRgb[1]) * k + matteRgb[1]);
- buffer[i + 2] = clamp((buffer[i + 2] - matteRgb[2]) * k + matteRgb[2]);
+ 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;
}
},
- fillRgbaBuffer: function PDFImage_fillRgbaBuffer(buffer, width, height) {
+
+ 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;
+ // Rows start at byte boundary.
var rowBytes = (originalWidth * numComps * bpc + 7) >> 3;
- var imgArray = this.getImageBytes(originalHeight * rowBytes);
+ var imgArray;
- // imgArray can be incomplete (e.g. after CCITT fax encoding)
+ 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 *
- height / originalHeight);
+ drawHeight / originalHeight);
+
var comps = this.getComponents(imgArray);
- // Handle opacity here since color key masking needs to be performed on
- // undecoded values.
- this.fillOpacity(buffer, width, height, actualHeight, comps);
+ // 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);
+ }
- this.colorSpace.fillRgb(buffer, originalWidth, originalHeight, width,
- height, actualHeight, bpc, comps);
-
- this.undoPreblend(buffer, width, actualHeight);
+ return imgData;
},
+
fillGrayBuffer: function PDFImage_fillGrayBuffer(buffer) {
var numComps = this.numComps;
- if (numComps != 1)
+ 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;
+ // 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);
}
- var length = width * height;
+ length = width * height;
// we aren't using a colorspace so we need to scale the value
var scale = 255 / ((1 << bpc) - 1);
- for (var i = 0; i < length; ++i)
+ for (i = 0; i < length; ++i) {
buffer[i] = (scale * comps[i]) | 0;
+ }
},
- getImageData: function PDFImage_getImageData() {
- var drawWidth = this.drawWidth;
- var drawHeight = this.drawHeight;
- var imgData = {
- width: drawWidth,
- height: drawHeight,
- data: new Uint8Array(drawWidth * drawHeight * 4)
- };
- var pixels = imgData.data;
- this.fillRgbaBuffer(pixels, drawWidth, drawHeight);
- return imgData;
- },
- getImageBytes: function PDFImage_getImageBytes(length) {
+
+ 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);
}
};
@@ -31619,14 +30037,17 @@ var Metrics = {
var EOF = {};
function isEOF(v) {
- return v == EOF;
+ 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();
}
@@ -31645,51 +30066,58 @@ var Parser = (function ParserClosure() {
}
},
getObj: function Parser_getObj(cipherTransform) {
- if (isCmd(this.buf1, 'BI')) { // inline image
- this.shift();
- return this.makeInlineImage(cipherTransform);
- }
- if (isCmd(this.buf1, '[')) { // array
- this.shift();
- 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;
- }
- if (isCmd(this.buf1, '<<')) { // dictionary or stream
- this.shift();
- 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');
+ 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();
- continue;
- }
+ 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');
+ 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;
+ // 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;
}
- this.shift();
- return dict;
}
- if (isInt(this.buf1)) { // indirect reference or integer
- var num = this.buf1;
- this.shift();
+
+ 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();
@@ -31698,76 +30126,191 @@ var Parser = (function ParserClosure() {
}
return num;
}
- if (isString(this.buf1)) { // string
- var str = this.buf1;
- this.shift();
- if (cipherTransform)
+
+ if (isString(buf1)) { // string
+ var str = buf1;
+ if (cipherTransform) {
str = cipherTransform.decryptString(str);
+ }
return str;
}
// simple object
- var obj = this.buf1;
- this.shift();
- return obj;
+ 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 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();
+ // Parse dictionary.
+ var dict = new Dict(null);
while (!isCmd(this.buf1, 'ID') && !isEOF(this.buf1)) {
- if (!isName(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))
+ if (isEOF(this.buf1)) {
break;
+ }
dict.set(key, this.getObj(cipherTransform));
}
- // parse image stream
- var startPos = stream.pos;
+ // 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;
+ }
- // searching for the /EI\s/
- var state = 0, ch, i, ii;
- while (state != 4 && (ch = stream.getByte()) !== -1) {
- switch (ch | 0) {
- case 0x20:
- case 0x0D:
- case 0x0A:
- // let's check next five bytes to be ASCII... just be sure
- var followingBytes = stream.peekBytes(5);
- for (i = 0, ii = followingBytes.length; i < ii; i++) {
- ch = followingBytes[i];
- if (ch !== 0x0A && ch !== 0x0D && (ch < 0x20 || ch > 0x7F)) {
- // not a LF, CR, SPACE or any visible ASCII character
- state = 0;
- break; // some binary stuff found, resetting the state
- }
- }
- state = state === 3 ? 4 : 0;
- break;
- case 0x45:
- state = 2;
- break;
- case 0x49:
- state = state === 2 ? 3 : 0;
- break;
- default:
- state = 0;
- break;
+ // Parse image stream.
+ var startPos = stream.pos, length, i, ii;
+ 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];
}
}
- var length = (stream.pos - 4) - startPos;
- var imageStream = stream.makeSubStream(startPos, length, dict);
- if (cipherTransform)
- imageStream = cipherTransform.createStream(imageStream);
+ 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();
@@ -31776,7 +30319,7 @@ var Parser = (function ParserClosure() {
},
fetchIfRef: function Parser_fetchIfRef(obj) {
// not relying on the xref.fetchIfRef -- xref might not be set
- return isRef(obj) ? this.xref.fetch(obj) : obj;
+ return (isRef(obj) ? this.xref.fetch(obj) : obj);
},
makeStream: function Parser_makeStream(dict, cipherTransform) {
var lexer = this.lexer;
@@ -31806,11 +30349,14 @@ var Parser = (function ParserClosure() {
var ENDSTREAM_SIGNATURE_LENGTH = 9;
var ENDSTREAM_SIGNATURE = [0x65, 0x6E, 0x64, 0x73, 0x74, 0x72, 0x65,
0x61, 0x6D];
- var skipped = 0, found = false;
+ 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;
- var found = false, i, ii, j;
+ if (scanLength <= 0) {
+ break;
+ }
+ found = false;
for (i = 0, j = 0; i < scanLength; i++) {
var b = scanBytes[i];
if (b !== ENDSTREAM_SIGNATURE[j]) {
@@ -31819,6 +30365,7 @@ var Parser = (function ParserClosure() {
} else {
j++;
if (j >= ENDSTREAM_SIGNATURE_LENGTH) {
+ i++;
found = true;
break;
}
@@ -31844,8 +30391,9 @@ var Parser = (function ParserClosure() {
this.shift(); // 'endstream'
stream = stream.makeSubStream(pos, length, dict);
- if (cipherTransform)
- stream = cipherTransform.createStream(stream);
+ if (cipherTransform) {
+ stream = cipherTransform.createStream(stream, length);
+ }
stream = this.filter(stream, dict, length);
stream.dict = dict;
return stream;
@@ -31853,72 +30401,98 @@ var Parser = (function ParserClosure() {
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))
+ 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))
+ if (!isName(filter)) {
error('Bad filter name: ' + filter);
+ }
params = null;
- if (isArray(paramsArray) && (i in paramsArray))
+ if (isArray(paramsArray) && (i in paramsArray)) {
params = paramsArray[i];
- stream = this.makeFilter(stream, filter.name, length, params);
+ }
+ stream = this.makeFilter(stream, filter.name, maybeLength, params);
// after the first stream the length variable is invalid
- length = null;
+ maybeLength = null;
}
}
return stream;
},
- makeFilter: function Parser_makeFilter(stream, name, length, params) {
+ makeFilter: function Parser_makeFilter(stream, name, maybeLength, params) {
if (stream.dict.get('Length') === 0) {
return new NullStream(stream);
}
- if (name == 'FlateDecode' || name == 'Fl') {
+ try {
if (params) {
- return new PredictorStream(new FlateStream(stream), params);
+ params = this.fetchIfRef(params);
}
- return new FlateStream(stream);
- }
- if (name == 'LZWDecode' || name == 'LZW') {
- var earlyChange = 1;
- if (params) {
- if (params.has('EarlyChange'))
- earlyChange = params.get('EarlyChange');
- return new PredictorStream(
- new LZWStream(stream, earlyChange), 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);
}
- return new LZWStream(stream, earlyChange);
+ 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);
}
- if (name == 'DCTDecode' || name == 'DCT') {
- var bytes = stream.getBytes(length);
- return new JpegStream(bytes, stream.dict, this.xref);
- }
- if (name == 'JPXDecode' || name == 'JPX') {
- var bytes = stream.getBytes(length);
- return new JpxStream(bytes, stream.dict);
- }
- if (name == 'ASCII85Decode' || name == 'A85') {
- return new Ascii85Stream(stream);
- }
- if (name == 'ASCIIHexDecode' || name == 'AHx') {
- return new AsciiHexStream(stream);
- }
- if (name == 'CCITTFaxDecode' || name == 'CCF') {
- return new CCITTFaxStream(stream, params);
- }
- if (name == 'RunLengthDecode' || name == 'RL') {
- return new RunLengthStream(stream);
- }
- if (name == 'JBIG2Decode') {
- var bytes = stream.getBytes(length);
- return new Jbig2Stream(bytes, stream.dict);
- }
- warn('filter "' + name + '" not supported yet');
- return stream;
}
};
@@ -31930,6 +30504,13 @@ var Lexer = (function LexerClosure() {
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:
@@ -31941,29 +30522,29 @@ var Lexer = (function LexerClosure() {
}
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;
+ // 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
+ // 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
+ 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) {
@@ -31981,36 +30562,87 @@ var Lexer = (function LexerClosure() {
nextChar: function Lexer_nextChar() {
return (this.currentChar = this.stream.getByte());
},
+ peekChar: function Lexer_peekChar() {
+ return this.stream.peekByte();
+ },
getNumber: function Lexer_getNumber() {
- var floating = false;
var ch = this.currentChar;
- var str = String.fromCharCode(ch);
+ 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 (ch === 0x2E && !floating) { // '.'
- str += '.';
- floating = true;
+ 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 >= 0x30 && ch <= 0x39) { // '0'-'9'
- str += String.fromCharCode(ch);
} else if (ch === 0x45 || ch === 0x65) { // 'E', 'e'
- floating = true;
+ // '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;
}
}
- var value = parseFloat(str);
- if (isNaN(value))
- error('Invalid floating point number: ' + value);
- return value;
+
+ 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 str = '';
+ var strBuf = this.strBuf;
+ strBuf.length = 0;
var ch = this.nextChar();
while (true) {
@@ -32022,14 +30654,14 @@ var Lexer = (function LexerClosure() {
break;
case 0x28: // '('
++numParen;
- str += '(';
+ strBuf.push('(');
break;
case 0x29: // ')'
if (--numParen === 0) {
this.nextChar(); // consume strings ')'
done = true;
} else {
- str += ')';
+ strBuf.push(')');
}
break;
case 0x5C: // '\\'
@@ -32040,24 +30672,24 @@ var Lexer = (function LexerClosure() {
done = true;
break;
case 0x6E: // 'n'
- str += '\n';
+ strBuf.push('\n');
break;
case 0x72: // 'r'
- str += '\r';
+ strBuf.push('\r');
break;
case 0x74: // 't'
- str += '\t';
+ strBuf.push('\t');
break;
case 0x62: // 'b'
- str += '\b';
+ strBuf.push('\b');
break;
case 0x66: // 'f'
- str += '\f';
+ strBuf.push('\f');
break;
case 0x5C: // '\'
case 0x28: // '('
case 0x29: // ')'
- str += String.fromCharCode(ch);
+ 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'
@@ -32072,18 +30704,22 @@ var Lexer = (function LexerClosure() {
x = (x << 3) + (ch & 0x0F);
}
}
-
- str += String.fromCharCode(x);
+ strBuf.push(String.fromCharCode(x));
break;
- case 0x0A: case 0x0D: // LF, CR
+ case 0x0D: // CR
+ if (this.peekChar() === 0x0A) { // LF
+ this.nextChar();
+ }
+ break;
+ case 0x0A: // LF
break;
default:
- str += String.fromCharCode(ch);
+ strBuf.push(String.fromCharCode(ch));
break;
}
break;
default:
- str += String.fromCharCode(ch);
+ strBuf.push(String.fromCharCode(ch));
break;
}
if (done) {
@@ -32093,35 +30729,38 @@ var Lexer = (function LexerClosure() {
ch = this.nextChar();
}
}
- return str;
+ return strBuf.join('');
},
getName: function Lexer_getName() {
- var str = '', ch;
+ 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) {
+ if (x !== -1) {
var x2 = toHexDigit(this.nextChar());
- if (x2 == -1)
+ if (x2 === -1) {
error('Illegal digit in hex char in name: ' + x2);
- str += String.fromCharCode((x << 4) | x2);
+ }
+ strBuf.push(String.fromCharCode((x << 4) | x2));
} else {
- str += '#';
- str += String.fromCharCode(ch);
+ strBuf.push('#', String.fromCharCode(ch));
}
} else {
- str += String.fromCharCode(ch);
+ strBuf.push(String.fromCharCode(ch));
}
}
- if (str.length > 128) {
+ if (strBuf.length > 128) {
error('Warning: name token is longer than allowed by the spec: ' +
- str.length);
+ strBuf.length);
}
- return new Name(str);
+ return Name.get(strBuf.join(''));
},
getHexString: function Lexer_getHexString() {
- var str = '';
+ var strBuf = this.strBuf;
+ strBuf.length = 0;
var ch = this.currentChar;
var isFirstHex = true;
var firstDigit;
@@ -32151,13 +30790,13 @@ var Lexer = (function LexerClosure() {
ch = this.nextChar();
continue;
}
- str += String.fromCharCode((firstDigit << 4) | secondDigit);
+ strBuf.push(String.fromCharCode((firstDigit << 4) | secondDigit));
}
isFirstHex = !isFirstHex;
ch = this.nextChar();
}
}
- return str;
+ return strBuf.join('');
},
getObj: function Lexer_getObj() {
// skip whitespace and comments
@@ -32168,8 +30807,9 @@ var Lexer = (function LexerClosure() {
return EOF;
}
if (comment) {
- if (ch === 0x0A || ch == 0x0D) // LF, CR
+ if (ch === 0x0A || ch === 0x0D) { // LF, CR
comment = false;
+ }
} else if (ch === 0x25) { // '%'
comment = true;
} else if (specialChars[ch] !== 1) {
@@ -32226,29 +30866,32 @@ var Lexer = (function LexerClosure() {
// command
var str = String.fromCharCode(ch);
var knownCommands = this.knownCommands;
- var knownCommandFound = knownCommands && (str in 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 && !(possibleCommand in knownCommands)) {
+ if (knownCommandFound && knownCommands[possibleCommand] === undefined) {
break;
}
- if (str.length == 128)
+ if (str.length === 128) {
error('Command token too long: ' + str.length);
+ }
str = possibleCommand;
- knownCommandFound = knownCommands && (str in knownCommands);
+ knownCommandFound = knownCommands && knownCommands[str] !== undefined;
}
- if (str == 'true')
+ if (str === 'true') {
return true;
- if (str == 'false')
+ }
+ if (str === 'false') {
return false;
- if (str == 'null')
+ }
+ if (str === 'null') {
return null;
+ }
return Cmd.get(str);
},
skipToNextLine: function Lexer_skipToNextLine() {
- var stream = this.stream;
var ch = this.currentChar;
while (ch >= 0) {
if (ch === 0x0D) { // CR
@@ -32269,87 +30912,264 @@ var Lexer = (function LexerClosure() {
return Lexer;
})();
-var Linearization = (function LinearizationClosure() {
- function Linearization(stream) {
- this.parser = new Parser(new Lexer(stream), false, null);
- var obj1 = this.parser.getObj();
- var obj2 = this.parser.getObj();
- var obj3 = this.parser.getObj();
- this.linDict = this.parser.getObj();
- if (isInt(obj1) && isInt(obj2) && isCmd(obj3, 'obj') &&
- isDict(this.linDict)) {
- var obj = this.linDict.get('Linearized');
- if (!(isNum(obj) && obj > 0))
- this.linDict = null;
- }
- }
-
- Linearization.prototype = {
- getInt: function Linearization_getInt(name) {
- var linDict = this.linDict;
- var obj;
- if (isDict(linDict) &&
- isInt(obj = linDict.get(name)) &&
- obj > 0) {
+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;
}
- error('"' + name + '" field in linearization table is invalid');
- },
- getHint: function Linearization_getHint(index) {
- var linDict = this.linDict;
- var obj1, obj2;
- if (isDict(linDict) &&
- isArray(obj1 = linDict.get('H')) &&
- obj1.length >= 2 &&
- isInt(obj2 = obj1[index]) &&
- obj2 > 0) {
- return obj2;
+ 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;
}
- error('Hints table in linearization table is invalid: ' + index);
+ 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();
},
- get length() {
- if (!isDict(this.linDict))
- return 0;
- return this.getInt('L');
+ accept: function PostScriptParser_accept(type) {
+ if (this.token.type === type) {
+ this.nextToken();
+ return true;
+ }
+ return false;
},
- get hintsOffset() {
- return this.getHint(0);
+ expect: function PostScriptParser_expect(type) {
+ if (this.accept(type)) {
+ return true;
+ }
+ error('Unexpected symbol: found ' + this.token.type + ' expected ' +
+ type + '.');
},
- get hintsLength() {
- return this.getHint(1);
+ parse: function PostScriptParser_parse() {
+ this.nextToken();
+ this.expect(PostScriptTokenTypes.LBRACE);
+ this.parseBlock();
+ this.expect(PostScriptTokenTypes.RBRACE);
+ return this.operators;
},
- get hintsOffset2() {
- return this.getHint(2);
+ 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;
+ }
+ }
},
- get hintsLenth2() {
- return this.getHint(3);
- },
- get objectNumberFirst() {
- return this.getInt('O');
- },
- get endFirst() {
- return this.getInt('E');
- },
- get numPages() {
- return this.getInt('N');
- },
- get mainXRefEntriesOffset() {
- return this.getInt('T');
- },
- get pageFirst() {
- return this.getInt('P');
+ 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 Linearization;
+ 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.bytes = (arrayBuffer instanceof Uint8Array ?
+ arrayBuffer : new Uint8Array(arrayBuffer));
this.start = start || 0;
this.pos = this.start;
this.end = (start + length) || this.bytes.length;
@@ -32362,11 +31182,27 @@ var Stream = (function StreamClosure() {
get length() {
return this.end - this.start;
},
+ get isEmpty() {
+ return this.length === 0;
+ },
getByte: function Stream_getByte() {
- if (this.pos >= this.end)
+ if (this.pos >= this.end) {
return -1;
+ }
return this.bytes[this.pos++];
},
+ getUint16: function Stream_getUint16() {
+ var b0 = this.getByte();
+ var b1 = this.getByte();
+ 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) {
@@ -32374,24 +31210,30 @@ var Stream = (function StreamClosure() {
var pos = this.pos;
var strEnd = this.end;
- if (!length)
+ if (!length) {
return bytes.subarray(pos, strEnd);
-
+ }
var end = pos + length;
- if (end > strEnd)
+ 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)
+ if (!n) {
n = 1;
+ }
this.pos += n;
},
reset: function Stream_reset() {
@@ -32413,8 +31255,9 @@ var StringStream = (function StringStreamClosure() {
function StringStream(str) {
var length = str.length;
var bytes = new Uint8Array(length);
- for (var n = 0; n < length; ++n)
+ for (var n = 0; n < length; ++n) {
bytes[n] = str.charCodeAt(n);
+ }
Stream.call(this, bytes);
}
@@ -32425,36 +31268,68 @@ var StringStream = (function StringStreamClosure() {
// super class for the decoding streams
var DecodeStream = (function DecodeStreamClosure() {
- function DecodeStream() {
+ // 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 = null;
+ 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;
- var current = buffer ? buffer.byteLength : 0;
- if (requested < current)
+ if (requested <= buffer.byteLength) {
return buffer;
- var size = 512;
- while (size < requested)
- size <<= 1;
+ }
+ var size = this.minBufferLength;
+ while (size < requested) {
+ size *= 2;
+ }
var buffer2 = new Uint8Array(size);
- for (var i = 0; i < current; ++i)
- buffer2[i] = buffer[i];
+ buffer2.set(buffer);
return (this.buffer = buffer2);
},
getByte: function DecodeStream_getByte() {
var pos = this.pos;
while (this.bufferLength <= pos) {
- if (this.eof)
+ if (this.eof) {
return -1;
+ }
this.readBlock();
}
return this.buffer[this.pos++];
},
+ getUint16: function DecodeStream_getUint16() {
+ var b0 = this.getByte();
+ var b1 = this.getByte();
+ 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;
@@ -32462,27 +31337,28 @@ var DecodeStream = (function DecodeStreamClosure() {
this.ensureBuffer(pos + length);
end = pos + length;
- while (!this.eof && this.bufferLength < end)
+ while (!this.eof && this.bufferLength < end) {
this.readBlock();
-
+ }
var bufEnd = this.bufferLength;
- if (end > bufEnd)
+ if (end > bufEnd) {
end = bufEnd;
+ }
} else {
- while (!this.eof)
+ while (!this.eof) {
this.readBlock();
-
+ }
end = this.bufferLength;
-
- // checking if bufferLength is still 0 then
- // the buffer has to be initialized
- if (!end)
- this.buffer = new Uint8Array(0);
}
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;
@@ -32490,13 +31366,15 @@ var DecodeStream = (function DecodeStreamClosure() {
},
makeSubStream: function DecodeStream_makeSubStream(start, length, dict) {
var end = start + length;
- while (this.bufferLength <= end && !this.eof)
+ while (this.bufferLength <= end && !this.eof) {
this.readBlock();
+ }
return new Stream(this.buffer, start, length, dict);
},
- skip: function Stream_skip(n) {
- if (!n)
+ skip: function DecodeStream_skip(n) {
+ if (!n) {
n = 1;
+ }
this.pos += n;
},
reset: function DecodeStream_reset() {
@@ -32513,55 +31391,16 @@ var DecodeStream = (function DecodeStreamClosure() {
return DecodeStream;
})();
-var FakeStream = (function FakeStreamClosure() {
- function FakeStream(stream) {
- this.dict = stream.dict;
- DecodeStream.call(this);
- }
-
- FakeStream.prototype = Object.create(DecodeStream.prototype);
- FakeStream.prototype.readBlock = function FakeStream_readBlock() {
- var bufferLength = this.bufferLength;
- bufferLength += 1024;
- var buffer = this.ensureBuffer(bufferLength);
- this.bufferLength = bufferLength;
- };
-
- FakeStream.prototype.getBytes = function FakeStream_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 {
- this.eof = true;
- end = this.bufferLength;
- }
-
- this.pos = end;
- return this.buffer.subarray(pos, end);
- };
-
- return FakeStream;
-})();
-
var StreamsSequenceStream = (function StreamsSequenceStreamClosure() {
function StreamsSequenceStream(streams) {
this.streams = streams;
- DecodeStream.call(this);
+ DecodeStream.call(this, /* maybeLength = */ null);
}
StreamsSequenceStream.prototype = Object.create(DecodeStream.prototype);
StreamsSequenceStream.prototype.readBlock =
- function streamSequenceStreamReadBlock() {
+ function streamSequenceStreamReadBlock() {
var streams = this.streams;
if (streams.length === 0) {
@@ -32584,7 +31423,7 @@ var StreamsSequenceStream = (function StreamsSequenceStreamClosure() {
for (var i = 0, ii = this.streams.length; i < ii; i++) {
var stream = this.streams[i];
if (stream.getBaseStreams) {
- Util.concatenateToArray(baseStreams, stream.getBaseStreams());
+ Util.appendToArray(baseStreams, stream.getBaseStreams());
}
}
return baseStreams;
@@ -32686,88 +31525,92 @@ var FlateStream = (function FlateStreamClosure() {
0x50003, 0x50013, 0x5000b, 0x5001b, 0x50007, 0x50017, 0x5000f, 0x00000
]), 5];
- function FlateStream(stream) {
- var bytes = stream.getBytes();
- var bytesPos = 0;
+ function FlateStream(str, maybeLength) {
+ this.str = str;
+ this.dict = str.dict;
- this.dict = stream.dict;
- var cmf = bytes[bytesPos++];
- var flg = bytes[bytesPos++];
- if (cmf == -1 || flg == -1)
+ 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)
+ }
+ if ((cmf & 0x0f) !== 0x08) {
error('Unknown compression method in flate stream: ' + cmf + ', ' + flg);
- if ((((cmf << 8) + flg) % 31) !== 0)
+ }
+ if ((((cmf << 8) + flg) % 31) !== 0) {
error('Bad FCHECK in flate stream: ' + cmf + ', ' + flg);
- if (flg & 0x20)
+ }
+ if (flg & 0x20) {
error('FDICT bit set in flate stream: ' + cmf + ', ' + flg);
-
- this.bytes = bytes;
- this.bytesPos = bytesPos;
+ }
this.codeSize = 0;
this.codeBuf = 0;
- DecodeStream.call(this);
+ 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 bytes = this.bytes;
- var bytesPos = this.bytesPos;
var b;
while (codeSize < bits) {
- if (typeof (b = bytes[bytesPos++]) == 'undefined')
+ 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;
- this.bytesPos = bytesPos;
+
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 bytes = this.bytes;
- var bytesPos = this.bytesPos;
+ var b;
while (codeSize < maxLen) {
- var b;
- if (typeof (b = bytes[bytesPos++]) == 'undefined')
- error('Bad encoding in flate stream');
+ 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 (codeSize === 0 || codeSize < codeLen || codeLen === 0)
+ if (codeLen < 1 || codeSize < codeLen) {
error('Bad encoding in flate stream');
+ }
this.codeBuf = (codeBuf >> codeLen);
this.codeSize = (codeSize - codeLen);
- this.bytesPos = bytesPos;
return codeVal;
};
FlateStream.prototype.generateHuffmanTable =
- function flateStreamGenerateHuffmanTable(lengths) {
+ function flateStreamGenerateHuffmanTable(lengths) {
var n = lengths.length;
// find max code length
var maxLen = 0;
- for (var i = 0; i < n; ++i) {
- if (lengths[i] > maxLen)
+ var i;
+ for (i = 0; i < n; ++i) {
+ if (lengths[i] > maxLen) {
maxLen = lengths[i];
+ }
}
// build the table
@@ -32777,19 +31620,19 @@ var FlateStream = (function FlateStreamClosure() {
len <= maxLen;
++len, code <<= 1, skip <<= 1) {
for (var val = 0; val < n; ++val) {
- if (lengths[val] == len) {
+ if (lengths[val] === len) {
// bit-reverse the code
var code2 = 0;
var t = code;
- for (var i = 0; i < len; ++i) {
+ for (i = 0; i < len; ++i) {
code2 = (code2 << 1) | (t & 1);
t >>= 1;
}
// fill the table entries
- for (var i = code2; i < size; i += skip)
+ for (i = code2; i < size; i += skip) {
codes[i] = (len << 16) | val;
-
+ }
++code;
}
}
@@ -32799,30 +31642,35 @@ var FlateStream = (function FlateStreamClosure() {
};
FlateStream.prototype.readBlock = function FlateStream_readBlock() {
+ var buffer, len;
+ var str = this.str;
// read block header
var hdr = this.getBits(3);
- if (hdr & 1)
+ if (hdr & 1) {
this.eof = true;
+ }
hdr >>= 1;
if (hdr === 0) { // uncompressed block
- var bytes = this.bytes;
- var bytesPos = this.bytesPos;
var b;
- if (typeof (b = bytes[bytesPos++]) == 'undefined')
+ if ((b = str.getByte()) === -1) {
error('Bad block header in flate stream');
+ }
var blockLen = b;
- if (typeof (b = bytes[bytesPos++]) == 'undefined')
+ if ((b = str.getByte()) === -1) {
error('Bad block header in flate stream');
+ }
blockLen |= (b << 8);
- if (typeof (b = bytes[bytesPos++]) == 'undefined')
+ if ((b = str.getByte()) === -1) {
error('Bad block header in flate stream');
+ }
var check = b;
- if (typeof (b = bytes[bytesPos++]) == 'undefined')
+ if ((b = str.getByte()) === -1) {
error('Bad block header in flate stream');
+ }
check |= (b << 8);
- if (check != (~blockLen & 0xffff) &&
+ 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');
@@ -32832,32 +31680,31 @@ var FlateStream = (function FlateStreamClosure() {
this.codeSize = 0;
var bufferLength = this.bufferLength;
- var buffer = this.ensureBuffer(bufferLength + blockLen);
+ buffer = this.ensureBuffer(bufferLength + blockLen);
var end = bufferLength + blockLen;
this.bufferLength = end;
if (blockLen === 0) {
- if (typeof bytes[bytesPos] == 'undefined') {
+ if (str.peekByte() === -1) {
this.eof = true;
}
} else {
for (var n = bufferLength; n < end; ++n) {
- if (typeof (b = bytes[bytesPos++]) == 'undefined') {
+ if ((b = str.getByte()) === -1) {
this.eof = true;
break;
}
buffer[n] = b;
}
}
- this.bytesPos = bytesPos;
return;
}
var litCodeTable;
var distCodeTable;
- if (hdr == 1) { // compressed block, fixed codes
+ if (hdr === 1) { // compressed block, fixed codes
litCodeTable = fixedLitCodeTab;
distCodeTable = fixedDistCodeTab;
- } else if (hdr == 2) { // compressed block, dynamic codes
+ } 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;
@@ -32865,31 +31712,35 @@ var FlateStream = (function FlateStreamClosure() {
// build the code lengths code table
var codeLenCodeLengths = new Uint8Array(codeLenCodeMap.length);
- for (var i = 0; i < numCodeLenCodes; ++i)
+ 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
- var len = 0;
- var i = 0;
+ 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) {
- var bitsLength = 2, bitsOffset = 3, what = len;
- } else if (code == 17) {
- var bitsLength = 3, bitsOffset = 3, what = (len = 0);
- } else if (code == 18) {
- var bitsLength = 7, bitsOffset = 11, what = (len = 0);
+ 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)
+ while (repeatLength-- > 0) {
codeLengths[i++] = what;
+ }
}
litCodeTable =
@@ -32900,7 +31751,7 @@ var FlateStream = (function FlateStreamClosure() {
error('Unknown block type in flate stream');
}
- var buffer = this.buffer;
+ buffer = this.buffer;
var limit = buffer ? buffer.length : 0;
var pos = this.bufferLength;
while (true) {
@@ -32913,28 +31764,31 @@ var FlateStream = (function FlateStreamClosure() {
buffer[pos++] = code1;
continue;
}
- if (code1 == 256) {
+ if (code1 === 256) {
this.bufferLength = pos;
return;
}
code1 -= 257;
code1 = lengthDecode[code1];
var code2 = code1 >> 16;
- if (code2 > 0)
+ if (code2 > 0) {
code2 = this.getBits(code2);
- var len = (code1 & 0xffff) + code2;
+ }
+ len = (code1 & 0xffff) + code2;
code1 = this.getCode(distCodeTable);
code1 = distDecode[code1];
code2 = code1 >> 16;
- if (code2 > 0)
+ 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)
+ for (var k = 0; k < len; ++k, ++pos) {
buffer[pos] = buffer[pos - dist];
+ }
}
};
@@ -32942,18 +31796,21 @@ var FlateStream = (function FlateStreamClosure() {
})();
var PredictorStream = (function PredictorStreamClosure() {
- function PredictorStream(str, params) {
+ function PredictorStream(str, maybeLength, params) {
var predictor = this.predictor = params.get('Predictor') || 1;
- if (predictor <= 1)
+ if (predictor <= 1) {
return str; // no prediction
- if (predictor !== 2 && (predictor < 10 || predictor > 15))
+ }
+ if (predictor !== 2 && (predictor < 10 || predictor > 15)) {
error('Unsupported predictor: ' + predictor);
+ }
- if (predictor === 2)
+ if (predictor === 2) {
this.readBlock = this.readBlockTiff;
- else
+ } else {
this.readBlock = this.readBlockPng;
+ }
this.str = str;
this.dict = str.dict;
@@ -32965,14 +31822,14 @@ var PredictorStream = (function PredictorStreamClosure() {
this.pixBytes = (colors * bits + 7) >> 3;
this.rowBytes = (columns * colors * bits + 7) >> 3;
- DecodeStream.call(this);
+ DecodeStream.call(this, maybeLength);
return this;
}
PredictorStream.prototype = Object.create(DecodeStream.prototype);
PredictorStream.prototype.readBlockTiff =
- function predictorStreamReadBlockTiff() {
+ function predictorStreamReadBlockTiff() {
var rowBytes = this.rowBytes;
var bufferLength = this.bufferLength;
@@ -32990,9 +31847,10 @@ var PredictorStream = (function PredictorStreamClosure() {
var inbuf = 0, outbuf = 0;
var inbits = 0, outbits = 0;
var pos = bufferLength;
+ var i;
if (bits === 1) {
- for (var i = 0; i < rowBytes; ++i) {
+ for (i = 0; i < rowBytes; ++i) {
var c = rawBytes[i];
inbuf = (inbuf << 8) | c;
// bitwise addition is exclusive or
@@ -33002,8 +31860,9 @@ var PredictorStream = (function PredictorStreamClosure() {
inbuf &= 0xFFFF;
}
} else if (bits === 8) {
- for (var i = 0; i < colors; ++i)
+ for (i = 0; i < colors; ++i) {
buffer[pos++] = rawBytes[i];
+ }
for (; i < rowBytes; ++i) {
buffer[pos] = buffer[pos - colors] + rawBytes[i];
pos++;
@@ -33013,7 +31872,7 @@ var PredictorStream = (function PredictorStreamClosure() {
var bitMask = (1 << bits) - 1;
var j = 0, k = bufferLength;
var columns = this.columns;
- for (var i = 0; i < columns; ++i) {
+ for (i = 0; i < columns; ++i) {
for (var kk = 0; kk < colors; ++kk) {
if (inbits < bits) {
inbuf = (inbuf << 8) | (rawBytes[j++] & 0xFF);
@@ -33032,14 +31891,14 @@ var PredictorStream = (function PredictorStreamClosure() {
}
if (outbits > 0) {
buffer[k++] = (outbuf << (8 - outbits)) +
- (inbuf & ((1 << (8 - outbits)) - 1));
+ (inbuf & ((1 << (8 - outbits)) - 1));
}
}
this.bufferLength += rowBytes;
};
PredictorStream.prototype.readBlockPng =
- function predictorStreamReadBlockPng() {
+ function predictorStreamReadBlockPng() {
var rowBytes = this.rowBytes;
var pixBytes = this.pixBytes;
@@ -33055,30 +31914,35 @@ var PredictorStream = (function PredictorStreamClosure() {
var buffer = this.ensureBuffer(bufferLength + rowBytes);
var prevRow = buffer.subarray(bufferLength - rowBytes, bufferLength);
- if (prevRow.length === 0)
+ if (prevRow.length === 0) {
prevRow = new Uint8Array(rowBytes);
+ }
- var j = bufferLength;
+ var i, j = bufferLength, up, c;
switch (predictor) {
case 0:
- for (var i = 0; i < rowBytes; ++i)
+ for (i = 0; i < rowBytes; ++i) {
buffer[j++] = rawBytes[i];
+ }
break;
case 1:
- for (var i = 0; i < pixBytes; ++i)
+ 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 (var i = 0; i < rowBytes; ++i)
+ for (i = 0; i < rowBytes; ++i) {
buffer[j++] = (prevRow[i] + rawBytes[i]) & 0xFF;
+ }
break;
case 3:
- for (var i = 0; i < pixBytes; ++i)
+ 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;
@@ -33088,34 +31952,38 @@ var PredictorStream = (function PredictorStreamClosure() {
case 4:
// we need to save the up left pixels values. the simplest way
// is to create a new buffer
- for (var i = 0; i < pixBytes; ++i) {
- var up = prevRow[i];
- var c = rawBytes[i];
+ for (i = 0; i < pixBytes; ++i) {
+ up = prevRow[i];
+ c = rawBytes[i];
buffer[j++] = up + c;
}
for (; i < rowBytes; ++i) {
- var up = prevRow[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)
+ if (pa < 0) {
pa = -pa;
+ }
var pb = p - up;
- if (pb < 0)
+ if (pb < 0) {
pb = -pb;
+ }
var pc = p - upLeft;
- if (pc < 0)
+ if (pc < 0) {
pc = -pc;
+ }
- var c = rawBytes[i];
- if (pa <= pb && pa <= pc)
+ c = rawBytes[i];
+ if (pa <= pb && pa <= pc) {
buffer[j++] = left + c;
- else if (pb <= pc)
+ } else if (pb <= pc) {
buffer[j++] = up + c;
- else
+ } else {
buffer[j++] = upLeft + c;
+ }
}
break;
default:
@@ -33135,28 +32003,63 @@ var PredictorStream = (function PredictorStreamClosure() {
* DecodeStreams.
*/
var JpegStream = (function JpegStreamClosure() {
- function JpegStream(bytes, dict, xref) {
- // TODO: per poppler, some images may have 'junk' before that
- // need to be removed
+ 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;
- this.bytes = bytes;
- DecodeStream.call(this);
+ 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)
+ if (this.bufferLength) {
return;
+ }
try {
var jpegImage = new JpegImage();
- if (this.colorTransform != -1)
- jpegImage.colorTransform = this.colorTransform;
+
+ // 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 width = jpegImage.width;
- var height = jpegImage.height;
- var data = jpegImage.getData(width, height);
+ var data = jpegImage.getData(this.drawWidth, this.drawHeight,
+ this.forceRGB);
this.buffer = data;
this.bufferLength = data.length;
this.eof = true;
@@ -33164,6 +32067,12 @@ var JpegStream = (function JpegStreamClosure() {
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');
};
@@ -33172,7 +32081,7 @@ var JpegStream = (function JpegStreamClosure() {
* further processing such as color space conversions.
*/
JpegStream.prototype.isNativelySupported =
- function JpegStream_isNativelySupported(xref, res) {
+ function JpegStream_isNativelySupported(xref, res) {
var cs = ColorSpace.parse(this.dict.get('ColorSpace', 'CS'), xref, res);
return cs.name === 'DeviceGray' || cs.name === 'DeviceRGB';
};
@@ -33180,10 +32089,10 @@ var JpegStream = (function JpegStreamClosure() {
* Checks if the image can be decoded by the browser.
*/
JpegStream.prototype.isNativelyDecodable =
- function JpegStream_isNativelyDecodable(xref, res) {
+ 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 numComps === 1 || numComps === 3;
};
return JpegStream;
@@ -33194,18 +32103,28 @@ var JpegStream = (function JpegStreamClosure() {
* the stream behaves like all the other DecodeStreams.
*/
var JpxStream = (function JpxStreamClosure() {
- function JpxStream(bytes, dict) {
+ function JpxStream(stream, maybeLength, dict) {
+ this.stream = stream;
+ this.maybeLength = maybeLength;
this.dict = dict;
- this.bytes = bytes;
- DecodeStream.call(this);
+ 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)
+ if (this.bufferLength) {
return;
+ }
var jpxImage = new JpxImage();
jpxImage.parse(this.bytes);
@@ -33213,75 +32132,35 @@ var JpxStream = (function JpxStreamClosure() {
var width = jpxImage.width;
var height = jpxImage.height;
var componentsCount = jpxImage.componentsCount;
- if (componentsCount != 1 && componentsCount != 3 && componentsCount != 4)
- error('JPX with ' + componentsCount + ' components is not supported');
+ var tileCount = jpxImage.tiles.length;
+ if (tileCount === 1) {
+ this.buffer = jpxImage.tiles[0].items;
+ } else {
+ var data = new Uint8Array(width * height * componentsCount);
- 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;
- for (var k = 0, kk = jpxImage.tiles.length; k < kk; k++) {
- var tileCompoments = jpxImage.tiles[k];
- var tileWidth = tileCompoments[0].width;
- var tileHeight = tileCompoments[0].height;
- var tileLeft = tileCompoments[0].left;
- var tileTop = tileCompoments[0].top;
+ var src = tileComponents.items;
+ var srcPosition = 0;
+ var dataPosition = (width * tileTop + tileLeft) * componentsCount;
+ var imgRowSize = width * componentsCount;
+ var tileRowSize = tileWidth * componentsCount;
- var dataPosition, sourcePosition, data0, data1, data2, data3, rowFeed;
- switch (componentsCount) {
- case 1:
- data0 = tileCompoments[0].items;
-
- dataPosition = width * tileTop + tileLeft;
- rowFeed = width - tileWidth;
- sourcePosition = 0;
- for (var j = 0; j < tileHeight; j++) {
- for (var i = 0; i < tileWidth; i++)
- data[dataPosition++] = data0[sourcePosition++];
- dataPosition += rowFeed;
- }
- break;
- case 3:
- data0 = tileCompoments[0].items;
- data1 = tileCompoments[1].items;
- data2 = tileCompoments[2].items;
-
- dataPosition = (width * tileTop + tileLeft) * 3;
- rowFeed = (width - tileWidth) * 3;
- sourcePosition = 0;
- for (var j = 0; j < tileHeight; j++) {
- for (var i = 0; i < tileWidth; i++) {
- data[dataPosition++] = data0[sourcePosition];
- data[dataPosition++] = data1[sourcePosition];
- data[dataPosition++] = data2[sourcePosition];
- sourcePosition++;
- }
- dataPosition += rowFeed;
- }
- break;
- case 4:
- data0 = tileCompoments[0].items;
- data1 = tileCompoments[1].items;
- data2 = tileCompoments[2].items;
- data3 = tileCompoments[3].items;
-
- dataPosition = (width * tileTop + tileLeft) * 4;
- rowFeed = (width - tileWidth) * 4;
- sourcePosition = 0;
- for (var j = 0; j < tileHeight; j++) {
- for (var i = 0; i < tileWidth; i++) {
- data[dataPosition++] = data0[sourcePosition];
- data[dataPosition++] = data1[sourcePosition];
- data[dataPosition++] = data2[sourcePosition];
- data[dataPosition++] = data3[sourcePosition];
- sourcePosition++;
- }
- dataPosition += rowFeed;
- }
- break;
+ 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.buffer = data;
- this.bufferLength = data.length;
+ this.bufferLength = this.buffer.length;
this.eof = true;
};
@@ -33293,22 +32172,33 @@ var JpxStream = (function JpxStreamClosure() {
* the stream behaves like all the other DecodeStreams.
*/
var Jbig2Stream = (function Jbig2StreamClosure() {
- function Jbig2Stream(bytes, dict) {
+ function Jbig2Stream(stream, maybeLength, dict) {
+ this.stream = stream;
+ this.maybeLength = maybeLength;
this.dict = dict;
- this.bytes = bytes;
- DecodeStream.call(this);
+ 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)
+ if (this.bufferLength) {
return;
+ }
var jbig2Image = new Jbig2Image();
- var chunks = [], decodeParams = this.dict.get('DecodeParms');
+ 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.
@@ -33317,7 +32207,7 @@ var Jbig2Stream = (function Jbig2StreamClosure() {
warn('JBIG2 - \'DecodeParms\' array with multiple elements ' +
'not supported.');
}
- decodeParams = decodeParams[0];
+ decodeParams = xref.fetchIfRef(decodeParams[0]);
}
if (decodeParams && decodeParams.has('JBIG2Globals')) {
var globalsStream = decodeParams.get('JBIG2Globals');
@@ -33329,8 +32219,9 @@ var Jbig2Stream = (function Jbig2StreamClosure() {
var dataLength = data.length;
// JBIG2 had black as 1 and white as 0, inverting the colors
- for (var i = 0; i < dataLength; i++)
+ for (var i = 0; i < dataLength; i++) {
data[i] ^= 0xFF;
+ }
this.buffer = data;
this.bufferLength = dataLength;
@@ -33341,14 +32232,14 @@ var Jbig2Stream = (function Jbig2StreamClosure() {
})();
var DecryptStream = (function DecryptStreamClosure() {
- function DecryptStream(str, decrypt) {
+ function DecryptStream(str, maybeLength, decrypt) {
this.str = str;
this.dict = str.dict;
this.decrypt = decrypt;
this.nextChunk = null;
this.initialized = false;
- DecodeStream.call(this);
+ DecodeStream.call(this, maybeLength);
}
var chunkSize = 512;
@@ -33376,8 +32267,9 @@ var DecryptStream = (function DecryptStreamClosure() {
var bufferLength = this.bufferLength;
var i, n = chunk.length;
var buffer = this.ensureBuffer(bufferLength + n);
- for (i = 0; i < n; i++)
+ for (i = 0; i < n; i++) {
buffer[bufferLength++] = chunk[i];
+ }
this.bufferLength = bufferLength;
};
@@ -33385,12 +32277,17 @@ var DecryptStream = (function DecryptStreamClosure() {
})();
var Ascii85Stream = (function Ascii85StreamClosure() {
- function Ascii85Stream(str) {
+ function Ascii85Stream(str, maybeLength) {
this.str = str;
this.dict = str.dict;
this.input = new Uint8Array(5);
- DecodeStream.call(this);
+ // 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);
@@ -33413,17 +32310,19 @@ var Ascii85Stream = (function Ascii85StreamClosure() {
}
var bufferLength = this.bufferLength, buffer;
+ var i;
// special code for z
- if (c == Z_LOWER_CHAR) {
+ if (c === Z_LOWER_CHAR) {
buffer = this.ensureBuffer(bufferLength + 4);
- for (var i = 0; i < 4; ++i)
+ for (i = 0; i < 4; ++i) {
buffer[bufferLength + i] = 0;
+ }
this.bufferLength += 4;
} else {
var input = this.input;
input[0] = c;
- for (var i = 1; i < 5; ++i) {
+ for (i = 1; i < 5; ++i) {
c = str.getByte();
while (Lexer.isSpace(c)) {
c = str.getByte();
@@ -33431,23 +32330,26 @@ var Ascii85Stream = (function Ascii85StreamClosure() {
input[i] = c;
- if (c === EOF || c == TILDA_CHAR)
+ 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)
+ for (; i < 5; ++i) {
input[i] = 0x21 + 84;
+ }
this.eof = true;
}
var t = 0;
- for (var i = 0; i < 5; ++i)
+ for (i = 0; i < 5; ++i) {
t = t * 85 + (input[i] - 0x21);
+ }
- for (var i = 3; i >= 0; --i) {
+ for (i = 3; i >= 0; --i) {
buffer[bufferLength + i] = t & 0xFF;
t >>= 8;
}
@@ -33458,13 +32360,18 @@ var Ascii85Stream = (function Ascii85StreamClosure() {
})();
var AsciiHexStream = (function AsciiHexStreamClosure() {
- function AsciiHexStream(str) {
+ function AsciiHexStream(str, maybeLength) {
this.str = str;
this.dict = str.dict;
this.firstDigit = -1;
- DecodeStream.call(this);
+ // 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);
@@ -33515,11 +32422,11 @@ var AsciiHexStream = (function AsciiHexStreamClosure() {
})();
var RunLengthStream = (function RunLengthStreamClosure() {
- function RunLengthStream(str) {
+ function RunLengthStream(str, maybeLength) {
this.str = str;
this.dict = str.dict;
- DecodeStream.call(this);
+ DecodeStream.call(this, maybeLength);
}
RunLengthStream.prototype = Object.create(DecodeStream.prototype);
@@ -33530,16 +32437,17 @@ var RunLengthStream = (function RunLengthStreamClosure() {
// (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) {
+ 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
- var buffer = this.ensureBuffer(bufferLength + n + 1);
+ buffer = this.ensureBuffer(bufferLength + n + 1);
buffer[bufferLength++] = repeatHeader[1];
if (n > 0) {
var source = this.str.getBytes(n);
@@ -33549,9 +32457,10 @@ var RunLengthStream = (function RunLengthStreamClosure() {
} else {
n = 257 - n;
var b = repeatHeader[1];
- var buffer = this.ensureBuffer(bufferLength + n + 1);
- for (var i = 0; i < n; i++)
+ buffer = this.ensureBuffer(bufferLength + n + 1);
+ for (var i = 0; i < n; i++) {
buffer[bufferLength++] = b;
+ }
}
this.bufferLength = bufferLength;
};
@@ -33987,11 +32896,11 @@ var CCITTFaxStream = (function CCITTFaxStreamClosure() {
[2, 2], [2, 2], [2, 2], [2, 2]
];
- function CCITTFaxStream(str, params) {
+ function CCITTFaxStream(str, maybeLength, params) {
this.str = str;
this.dict = str.dict;
- params = params || new Dict();
+ params = params || Dict.empty;
this.encoding = params.get('K') || 0;
this.eoline = params.get('EndOfLine') || false;
@@ -33999,8 +32908,9 @@ var CCITTFaxStream = (function CCITTFaxStreamClosure() {
this.columns = params.get('Columns') || 1728;
this.rows = params.get('Rows') || 0;
var eoblock = params.get('EndOfBlock');
- if (eoblock === null || eoblock === undefined)
+ if (eoblock === null || eoblock === undefined) {
eoblock = true;
+ }
this.eoblock = eoblock;
this.black = params.get('BlackIs1') || false;
@@ -34015,13 +32925,12 @@ var CCITTFaxStream = (function CCITTFaxStreamClosure() {
this.inputBits = 0;
this.inputBuf = 0;
this.outputBits = 0;
- this.buf = EOF;
var code1;
while ((code1 = this.lookBits(12)) === 0) {
this.eatBits(1);
}
- if (code1 == 1) {
+ if (code1 === 1) {
this.eatBits(12);
}
if (this.encoding > 0) {
@@ -34029,7 +32938,7 @@ var CCITTFaxStream = (function CCITTFaxStreamClosure() {
this.eatBits(1);
}
- DecodeStream.call(this);
+ DecodeStream.call(this, maybeLength);
}
CCITTFaxStream.prototype = Object.create(DecodeStream.prototype);
@@ -34037,14 +32946,13 @@ var CCITTFaxStream = (function CCITTFaxStreamClosure() {
CCITTFaxStream.prototype.readBlock = function CCITTFaxStream_readBlock() {
while (!this.eof) {
var c = this.lookChar();
- this.buf = EOF;
this.ensureBuffer(this.bufferLength + 1);
this.buffer[this.bufferLength++] = c;
}
};
CCITTFaxStream.prototype.addPixels =
- function ccittFaxStreamAddPixels(a1, blackPixels) {
+ function ccittFaxStreamAddPixels(a1, blackPixels) {
var codingLine = this.codingLine;
var codingPos = this.codingPos;
@@ -34064,7 +32972,7 @@ var CCITTFaxStream = (function CCITTFaxStreamClosure() {
};
CCITTFaxStream.prototype.addPixelsNeg =
- function ccittFaxStreamAddPixelsNeg(a1, blackPixels) {
+ function ccittFaxStreamAddPixelsNeg(a1, blackPixels) {
var codingLine = this.codingLine;
var codingPos = this.codingPos;
@@ -34074,8 +32982,9 @@ var CCITTFaxStream = (function CCITTFaxStreamClosure() {
this.err = true;
a1 = this.columns;
}
- if ((codingPos & 1) ^ blackPixels)
+ if ((codingPos & 1) ^ blackPixels) {
++codingPos;
+ }
codingLine[codingPos] = a1;
} else if (a1 < codingLine[codingPos]) {
@@ -34084,8 +32993,9 @@ var CCITTFaxStream = (function CCITTFaxStreamClosure() {
this.err = true;
a1 = 0;
}
- while (codingPos > 0 && a1 < codingLine[codingPos - 1])
+ while (codingPos > 0 && a1 < codingLine[codingPos - 1]) {
--codingPos;
+ }
codingLine[codingPos] = a1;
}
@@ -34093,26 +33003,23 @@ var CCITTFaxStream = (function CCITTFaxStreamClosure() {
};
CCITTFaxStream.prototype.lookChar = function CCITTFaxStream_lookChar() {
- if (this.buf != EOF)
- return this.buf;
-
var refLine = this.refLine;
var codingLine = this.codingLine;
var columns = this.columns;
- var refPos, blackPixels, bits;
+ var refPos, blackPixels, bits, i;
if (this.outputBits === 0) {
- if (this.eof)
+ if (this.eof) {
return null;
-
+ }
this.err = false;
var code1, code2, code3;
if (this.nextLine2D) {
- for (var i = 0; codingLine[i] < columns; ++i)
+ for (i = 0; codingLine[i] < columns; ++i) {
refLine[i] = codingLine[i];
-
+ }
refLine[i++] = columns;
refLine[i] = columns;
codingLine[0] = 0;
@@ -34125,8 +33032,9 @@ var CCITTFaxStream = (function CCITTFaxStreamClosure() {
switch (code1) {
case twoDimPass:
this.addPixels(refLine[refPos + 1], blackPixels);
- if (refLine[refPos + 1] < columns)
+ if (refLine[refPos + 1] < columns) {
refPos += 2;
+ }
break;
case twoDimHoriz:
code1 = code2 = 0;
@@ -34162,8 +33070,9 @@ var CCITTFaxStream = (function CCITTFaxStreamClosure() {
if (codingLine[this.codingPos] < columns) {
++refPos;
while (refLine[refPos] <= codingLine[this.codingPos] &&
- refLine[refPos] < columns)
+ refLine[refPos] < columns) {
refPos += 2;
+ }
}
break;
case twoDimVertR2:
@@ -34183,8 +33092,9 @@ var CCITTFaxStream = (function CCITTFaxStreamClosure() {
if (codingLine[this.codingPos] < columns) {
++refPos;
while (refLine[refPos] <= codingLine[this.codingPos] &&
- refLine[refPos] < columns)
+ refLine[refPos] < columns) {
refPos += 2;
+ }
}
break;
case twoDimVert0:
@@ -34193,48 +33103,54 @@ var CCITTFaxStream = (function CCITTFaxStreamClosure() {
if (codingLine[this.codingPos] < columns) {
++refPos;
while (refLine[refPos] <= codingLine[this.codingPos] &&
- refLine[refPos] < columns)
+ refLine[refPos] < columns) {
refPos += 2;
+ }
}
break;
case twoDimVertL3:
this.addPixelsNeg(refLine[refPos] - 3, blackPixels);
blackPixels ^= 1;
if (codingLine[this.codingPos] < columns) {
- if (refPos > 0)
+ if (refPos > 0) {
--refPos;
- else
+ } else {
++refPos;
+ }
while (refLine[refPos] <= codingLine[this.codingPos] &&
- refLine[refPos] < columns)
+ refLine[refPos] < columns) {
refPos += 2;
+ }
}
break;
case twoDimVertL2:
this.addPixelsNeg(refLine[refPos] - 2, blackPixels);
blackPixels ^= 1;
if (codingLine[this.codingPos] < columns) {
- if (refPos > 0)
+ if (refPos > 0) {
--refPos;
- else
+ } else {
++refPos;
+ }
while (refLine[refPos] <= codingLine[this.codingPos] &&
- refLine[refPos] < columns)
+ refLine[refPos] < columns) {
refPos += 2;
+ }
}
break;
case twoDimVertL1:
this.addPixelsNeg(refLine[refPos] - 1, blackPixels);
blackPixels ^= 1;
if (codingLine[this.codingPos] < columns) {
- if (refPos > 0)
+ if (refPos > 0) {
--refPos;
- else
+ } else {
++refPos;
-
+ }
while (refLine[refPos] <= codingLine[this.codingPos] &&
- refLine[refPos] < columns)
+ refLine[refPos] < columns) {
refPos += 2;
+ }
}
break;
case EOF:
@@ -34267,45 +33183,54 @@ var CCITTFaxStream = (function CCITTFaxStreamClosure() {
}
}
- if (this.byteAlign)
- this.inputBits &= ~7;
-
var gotEOL = false;
- if (!this.eoblock && this.row == this.rows - 1) {
+ if (!this.eoblock && this.row === this.rows - 1) {
this.eof = true;
} else {
code1 = this.lookBits(12);
- while (code1 === 0) {
- this.eatBits(1);
- 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) {
+ if (code1 === 1) {
this.eatBits(12);
gotEOL = true;
- } else if (code1 == EOF) {
+ } else if (code1 === EOF) {
this.eof = true;
}
}
+ if (this.byteAlign && !gotEOL) {
+ this.inputBits &= ~7;
+ }
+
if (!this.eof && this.encoding > 0) {
this.nextLine2D = !this.lookBits(1);
this.eatBits(1);
}
- if (this.eoblock && gotEOL) {
+ if (this.eoblock && gotEOL && this.byteAlign) {
code1 = this.lookBits(12);
- if (code1 == 1) {
+ if (code1 === 1) {
this.eatBits(12);
if (this.encoding > 0) {
this.lookBits(1);
this.eatBits(1);
}
if (this.encoding >= 0) {
- for (var i = 0; i < 4; ++i) {
+ for (i = 0; i < 4; ++i) {
code1 = this.lookBits(12);
- if (code1 != 1)
+ if (code1 !== 1) {
info('bad rtc code: ' + code1);
+ }
this.eatBits(12);
if (this.encoding > 0) {
this.lookBits(1);
@@ -34318,11 +33243,11 @@ var CCITTFaxStream = (function CCITTFaxStreamClosure() {
} else if (this.err && this.eoline) {
while (true) {
code1 = this.lookBits(13);
- if (code1 == EOF) {
+ if (code1 === EOF) {
this.eof = true;
return null;
}
- if ((code1 >> 1) == 1) {
+ if ((code1 >> 1) === 1) {
break;
}
this.eatBits(1);
@@ -34334,15 +33259,17 @@ var CCITTFaxStream = (function CCITTFaxStreamClosure() {
}
}
- if (codingLine[0] > 0)
+ if (codingLine[0] > 0) {
this.outputBits = codingLine[this.codingPos = 0];
- else
+ } else {
this.outputBits = codingLine[this.codingPos = 1];
+ }
this.row++;
}
+ var c;
if (this.outputBits >= 8) {
- this.buf = (this.codingPos & 1) ? 0 : 0xFF;
+ c = (this.codingPos & 1) ? 0 : 0xFF;
this.outputBits -= 8;
if (this.outputBits === 0 && codingLine[this.codingPos] < columns) {
this.codingPos++;
@@ -34350,20 +33277,20 @@ var CCITTFaxStream = (function CCITTFaxStreamClosure() {
codingLine[this.codingPos - 1]);
}
} else {
- var bits = 8;
- this.buf = 0;
+ bits = 8;
+ c = 0;
do {
if (this.outputBits > bits) {
- this.buf <<= bits;
+ c <<= bits;
if (!(this.codingPos & 1)) {
- this.buf |= 0xFF >> (8 - bits);
+ c |= 0xFF >> (8 - bits);
}
this.outputBits -= bits;
bits = 0;
} else {
- this.buf <<= this.outputBits;
+ c <<= this.outputBits;
if (!(this.codingPos & 1)) {
- this.buf |= 0xFF >> (8 - this.outputBits);
+ c |= 0xFF >> (8 - this.outputBits);
}
bits -= this.outputBits;
this.outputBits = 0;
@@ -34372,16 +33299,16 @@ var CCITTFaxStream = (function CCITTFaxStreamClosure() {
this.outputBits = (codingLine[this.codingPos] -
codingLine[this.codingPos - 1]);
} else if (bits > 0) {
- this.buf <<= bits;
+ c <<= bits;
bits = 0;
}
}
} while (bits);
}
if (this.black) {
- this.buf ^= 0xFF;
+ c ^= 0xFF;
}
- return this.buf;
+ return c;
};
// This functions returns the code found from the table.
@@ -34391,18 +33318,20 @@ var CCITTFaxStream = (function CCITTFaxStreamClosure() {
// 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) {
+ 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)
+ if (code === EOF) {
return [true, 1, false];
- if (i < end)
+ }
+ if (i < end) {
code <<= end - i;
+ }
if (!limitValue || code >= limitValue) {
var p = table[code - limitValue];
- if (p[0] == i) {
+ if (p[0] === i) {
this.eatBits(i);
return [true, p[1], true];
}
@@ -34412,7 +33341,7 @@ var CCITTFaxStream = (function CCITTFaxStreamClosure() {
};
CCITTFaxStream.prototype.getTwoDimCode =
- function ccittFaxStreamGetTwoDimCode() {
+ function ccittFaxStreamGetTwoDimCode() {
var code = 0;
var p;
@@ -34425,28 +33354,30 @@ var CCITTFaxStream = (function CCITTFaxStreamClosure() {
}
} else {
var result = this.findTableCode(1, 7, twoDimTable);
- if (result[0] && result[2])
+ if (result[0] && result[2]) {
return result[1];
+ }
}
info('Bad two dim code');
return EOF;
};
CCITTFaxStream.prototype.getWhiteCode =
- function ccittFaxStreamGetWhiteCode() {
+ function ccittFaxStreamGetWhiteCode() {
var code = 0;
var p;
- var n;
if (this.eoblock) {
code = this.lookBits(12);
- if (code == EOF)
+ if (code === EOF) {
return 1;
+ }
- if ((code >> 5) === 0)
+ if ((code >> 5) === 0) {
p = whiteTable1[code];
- else
+ } else {
p = whiteTable2[code >> 3];
+ }
if (p[0] > 0) {
this.eatBits(p[0]);
@@ -34454,12 +33385,14 @@ var CCITTFaxStream = (function CCITTFaxStreamClosure() {
}
} else {
var result = this.findTableCode(1, 9, whiteTable2);
- if (result[0])
+ if (result[0]) {
return result[1];
+ }
result = this.findTableCode(11, 12, whiteTable1);
- if (result[0])
+ if (result[0]) {
return result[1];
+ }
}
info('bad white code');
this.eatBits(1);
@@ -34467,19 +33400,21 @@ var CCITTFaxStream = (function CCITTFaxStreamClosure() {
};
CCITTFaxStream.prototype.getBlackCode =
- function ccittFaxStreamGetBlackCode() {
+ function ccittFaxStreamGetBlackCode() {
var code, p;
if (this.eoblock) {
code = this.lookBits(13);
- if (code == EOF)
+ if (code === EOF) {
return 1;
- if ((code >> 7) === 0)
+ }
+ if ((code >> 7) === 0) {
p = blackTable1[code];
- else if ((code >> 9) === 0 && (code >> 7) !== 0)
+ } else if ((code >> 9) === 0 && (code >> 7) !== 0) {
p = blackTable2[(code >> 1) - 64];
- else
+ } else {
p = blackTable3[code >> 7];
+ }
if (p[0] > 0) {
this.eatBits(p[0]);
@@ -34487,16 +33422,19 @@ var CCITTFaxStream = (function CCITTFaxStreamClosure() {
}
} else {
var result = this.findTableCode(2, 6, blackTable3);
- if (result[0])
+ if (result[0]) {
return result[1];
+ }
result = this.findTableCode(7, 12, blackTable2, 64);
- if (result[0])
+ if (result[0]) {
return result[1];
+ }
result = this.findTableCode(10, 13, blackTable1);
- if (result[0])
+ if (result[0]) {
return result[1];
+ }
}
info('bad black code');
this.eatBits(1);
@@ -34507,8 +33445,9 @@ var CCITTFaxStream = (function CCITTFaxStreamClosure() {
var c;
while (this.inputBits < n) {
if ((c = this.str.getByte()) === -1) {
- if (this.inputBits === 0)
+ if (this.inputBits === 0) {
return EOF;
+ }
return ((this.inputBuf << (n - this.inputBits)) &
(0xFFFF >> (16 - n)));
}
@@ -34519,15 +33458,16 @@ var CCITTFaxStream = (function CCITTFaxStreamClosure() {
};
CCITTFaxStream.prototype.eatBits = function CCITTFaxStream_eatBits(n) {
- if ((this.inputBits -= n) < 0)
+ if ((this.inputBits -= n) < 0) {
this.inputBits = 0;
+ }
};
return CCITTFaxStream;
})();
var LZWStream = (function LZWStreamClosure() {
- function LZWStream(str, earlyChange) {
+ function LZWStream(str, maybeLength, earlyChange) {
this.str = str;
this.dict = str.dict;
this.cachedData = 0;
@@ -34550,7 +33490,7 @@ var LZWStream = (function LZWStreamClosure() {
}
this.lzwState = lzwState;
- DecodeStream.call(this);
+ DecodeStream.call(this, maybeLength);
}
LZWStream.prototype = Object.create(DecodeStream.prototype);
@@ -34579,8 +33519,9 @@ var LZWStream = (function LZWStreamClosure() {
var i, j, q;
var lzwState = this.lzwState;
- if (!lzwState)
+ if (!lzwState) {
return; // eof was found
+ }
var earlyChange = lzwState.earlyChange;
var nextCode = lzwState.nextCode;
@@ -34612,7 +33553,7 @@ var LZWStream = (function LZWStreamClosure() {
} else {
currentSequence[currentSequenceLength++] = currentSequence[0];
}
- } else if (code == 256) {
+ } else if (code === 256) {
codeLength = 9;
nextCode = 258;
currentSequenceLength = 0;
@@ -34641,8 +33582,9 @@ var LZWStream = (function LZWStreamClosure() {
} while (estimatedDecodedSize < decodedLength);
buffer = this.ensureBuffer(this.bufferLength + estimatedDecodedSize);
}
- for (j = 0; j < currentSequenceLength; j++)
+ for (j = 0; j < currentSequenceLength; j++) {
buffer[currentBufferLength++] = currentSequence[j];
+ }
}
lzwState.nextCode = nextCode;
lzwState.codeLength = codeLength;
@@ -34671,76 +33613,66 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
var pdfManager;
function loadDocument(recoveryMode) {
- var loadDocumentPromise = new LegacyPromise();
+ var loadDocumentCapability = createPromiseCapability();
var parseSuccess = function parseSuccess() {
- var numPagesPromise = pdfManager.ensureModel('numPages');
- var fingerprintPromise = pdfManager.ensureModel('fingerprint');
- var outlinePromise = pdfManager.ensureCatalog('documentOutline');
- var infoPromise = pdfManager.ensureModel('documentInfo');
- var metadataPromise = pdfManager.ensureCatalog('metadata');
+ var numPagesPromise = pdfManager.ensureDoc('numPages');
+ var fingerprintPromise = pdfManager.ensureDoc('fingerprint');
var encryptedPromise = pdfManager.ensureXRef('encrypt');
- var javaScriptPromise = pdfManager.ensureCatalog('javaScript');
- Promise.all([numPagesPromise, fingerprintPromise, outlinePromise,
- infoPromise, metadataPromise, encryptedPromise,
- javaScriptPromise]).then(
- function onDocReady(results) {
-
+ Promise.all([numPagesPromise, fingerprintPromise,
+ encryptedPromise]).then(function onDocReady(results) {
var doc = {
numPages: results[0],
fingerprint: results[1],
- outline: results[2],
- info: results[3],
- metadata: results[4],
- encrypted: !!results[5],
- javaScript: results[6]
+ encrypted: !!results[2],
};
- loadDocumentPromise.resolve(doc);
+ loadDocumentCapability.resolve(doc);
},
parseFailure);
};
var parseFailure = function parseFailure(e) {
- loadDocumentPromise.reject(e);
+ loadDocumentCapability.reject(e);
};
- pdfManager.ensureModel('checkHeader', []).then(function() {
- pdfManager.ensureModel('parseStartXRef', []).then(function() {
- pdfManager.ensureModel('parse', [recoveryMode]).then(
- parseSuccess, parseFailure);
+ pdfManager.ensureDoc('checkHeader', []).then(function() {
+ pdfManager.ensureDoc('parseStartXRef', []).then(function() {
+ pdfManager.ensureDoc('parse', [recoveryMode]).then(
+ parseSuccess, parseFailure);
}, parseFailure);
}, parseFailure);
- return loadDocumentPromise;
+ return loadDocumentCapability.promise;
}
function getPdfManager(data) {
- var pdfManagerPromise = new LegacyPromise();
+ var pdfManagerCapability = createPromiseCapability();
var source = data.source;
var disableRange = data.disableRange;
if (source.data) {
try {
pdfManager = new LocalPdfManager(source.data, source.password);
- pdfManagerPromise.resolve();
+ pdfManagerCapability.resolve();
} catch (ex) {
- pdfManagerPromise.reject(ex);
+ pdfManagerCapability.reject(ex);
}
- return pdfManagerPromise;
+ return pdfManagerCapability.promise;
} else if (source.chunkedViewerLoading) {
try {
pdfManager = new NetworkPdfManager(source, handler);
- pdfManagerPromise.resolve();
+ pdfManagerCapability.resolve();
} catch (ex) {
- pdfManagerPromise.reject(ex);
+ pdfManagerCapability.reject(ex);
}
- return pdfManagerPromise;
+ 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) {
@@ -34763,53 +33695,102 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
if (!isInt(length)) {
return;
}
-
- // 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);
-
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);
- pdfManagerPromise.resolve(pdfManager);
+ pdfManagerCapability.resolve(pdfManager);
} catch (ex) {
- pdfManagerPromise.reject(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(args.chunk, source.password);
- pdfManagerPromise.resolve();
+ pdfManager = new LocalPdfManager(pdfFile, source.password);
+ pdfManagerCapability.resolve();
} catch (ex) {
- pdfManagerPromise.reject(ex);
+ pdfManagerCapability.reject(ex);
}
},
onError: function onError(status) {
- if (status == 404) {
- var exception = new MissingPDFException( 'Missing PDF "' +
- source.url + '".');
- handler.send('MissingPDF', { exception: exception });
+ var exception;
+ if (status === 404) {
+ exception = new MissingPDFException('Missing PDF "' +
+ source.url + '".');
+ handler.send('MissingPDF', exception);
} else {
- handler.send('DocError', 'Unexpected server response (' +
- status + ') while retrieving PDF "' +
- source.url + '".');
+ 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 : void(0)
+ total: evt.lengthComputable ? evt.total : source.length
});
}
});
- return pdfManagerPromise;
+ return pdfManagerCapability.promise;
}
handler.on('test', function wphSetupTest(data) {
@@ -34849,26 +33830,19 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
var onFailure = function(e) {
if (e instanceof PasswordException) {
if (e.code === PasswordResponses.NEED_PASSWORD) {
- handler.send('NeedPassword', {
- exception: e
- });
+ handler.send('NeedPassword', e);
} else if (e.code === PasswordResponses.INCORRECT_PASSWORD) {
- handler.send('IncorrectPassword', {
- exception: e
- });
+ handler.send('IncorrectPassword', e);
}
} else if (e instanceof InvalidPDFException) {
- handler.send('InvalidPDF', {
- exception: e
- });
+ handler.send('InvalidPDF', e);
} else if (e instanceof MissingPDFException) {
- handler.send('MissingPDF', {
- exception: e
- });
+ handler.send('MissingPDF', e);
+ } else if (e instanceof UnexpectedResponseException) {
+ handler.send('UnexpectedResponse', e);
} else {
- handler.send('UnknownError', {
- exception: new UnknownErrorException(e.message, e.toString())
- });
+ handler.send('UnknownError',
+ new UnknownErrorException(e.message, e.toString()));
}
};
@@ -34877,17 +33851,23 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
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 pdfManagerReady() {
+ 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.passwordChangedPromise =
- new LegacyPromise();
- pdfManager.passwordChangedPromise.then(pdfManagerReady);
+ pdfManager.passwordChanged().then(pdfManagerReady);
}
onFailure(ex);
@@ -34902,69 +33882,86 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
}, onFailure);
});
- handler.on('GetPageRequest', function wphSetupGetPage(data) {
- var pageIndex = data.pageIndex;
- pdfManager.getPage(pageIndex).then(function(page) {
+ 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');
- Promise.all([rotatePromise, refPromise, viewPromise]).then(
+ return Promise.all([rotatePromise, refPromise, viewPromise]).then(
function(results) {
- var page = {
- pageIndex: data.pageIndex,
+ return {
rotate: results[0],
ref: results[1],
view: results[2]
};
-
- handler.send('GetPage', { pageInfo: page });
});
});
});
- handler.on('GetPageIndex', function wphSetupGetPageIndex(data, deferred) {
+ handler.on('GetPageIndex', function wphSetupGetPageIndex(data) {
var ref = new Ref(data.ref.num, data.ref.gen);
- pdfManager.pdfModel.catalog.getPageIndex(ref).then(function (pageIndex) {
- deferred.resolve(pageIndex);
- }, deferred.reject);
+ var catalog = pdfManager.pdfDocument.catalog;
+ return catalog.getPageIndex(ref);
});
handler.on('GetDestinations',
- function wphSetupGetDestinations(data, deferred) {
- pdfManager.ensureCatalog('destinations').then(function(destinations) {
- deferred.resolve(destinations);
- });
+ function wphSetupGetDestinations(data) {
+ return pdfManager.ensureCatalog('destinations');
}
);
- handler.on('GetData', function wphSetupGetData(data, deferred) {
+ 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();
- pdfManager.onLoadedStream().then(function(stream) {
- deferred.resolve(stream.bytes);
+ return pdfManager.onLoadedStream().then(function(stream) {
+ return stream.bytes;
});
});
- handler.on('DataLoaded', function wphSetupDataLoaded(data, deferred) {
- pdfManager.onLoadedStream().then(function(stream) {
- deferred.resolve({ length: stream.bytes.byteLength });
- });
- });
+ handler.on('GetStats',
+ function wphSetupGetStats(data) {
+ return pdfManager.pdfDocument.xref.stats;
+ }
+ );
handler.on('UpdatePassword', function wphSetupUpdatePassword(data) {
pdfManager.updatePassword(data);
});
- handler.on('GetAnnotationsRequest', function wphSetupGetAnnotations(data) {
- pdfManager.getPage(data.pageIndex).then(function(page) {
- pdfManager.ensure(page, 'getAnnotationsData', []).then(
- function(annotationsData) {
- handler.send('GetAnnotations', {
- pageIndex: data.pageIndex,
- annotations: annotationsData
- });
- }
- );
+ handler.on('GetAnnotations', function wphSetupGetAnnotations(data) {
+ return pdfManager.getPage(data.pageIndex).then(function(page) {
+ return pdfManager.ensure(page, 'getAnnotationsData', []);
});
});
@@ -34974,15 +33971,15 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
var pageNum = data.pageIndex + 1;
var start = Date.now();
// Pre compile the pdf page and fetch the fonts/images.
- page.getOperatorList(handler).then(function(operatorList) {
+ page.getOperatorList(handler, data.intent).then(function(operatorList) {
- info('page=%d - getOperatorList: time=%dms, len=%d', pageNum,
- Date.now() - start, operatorList.fnArray.length);
+ 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()';
+ 'worker.js: while trying to getPage() and getOperatorList()';
var wrappedException;
@@ -35006,35 +34003,31 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
handler.send('PageError', {
pageNum: pageNum,
- error: wrappedException
+ error: wrappedException,
+ intent: data.intent
});
});
});
}, this);
- handler.on('GetTextContent', function wphExtractText(data, deferred) {
- pdfManager.getPage(data.pageIndex).then(function(page) {
+ handler.on('GetTextContent', function wphExtractText(data) {
+ return pdfManager.getPage(data.pageIndex).then(function(page) {
var pageNum = data.pageIndex + 1;
var start = Date.now();
- page.extractTextContent().then(function(textContent) {
- deferred.resolve(textContent);
- info('text indexing: page=%d - time=%dms', pageNum,
- Date.now() - start);
- }, function (e) {
- // Skip errored pages
- deferred.reject(e);
+ return page.extractTextContent().then(function(textContent) {
+ info('text indexing: page=' + pageNum + ' - time=' +
+ (Date.now() - start) + 'ms');
+ return textContent;
});
});
});
- handler.on('Cleanup', function wphCleanup(data, deferred) {
- pdfManager.cleanup();
- deferred.resolve(true);
+ handler.on('Cleanup', function wphCleanup(data) {
+ return pdfManager.cleanup();
});
- handler.on('Terminate', function wphTerminate(data, deferred) {
+ handler.on('Terminate', function wphTerminate(data) {
pdfManager.terminate();
- deferred.resolve();
});
}
};
@@ -35092,6 +34085,1173 @@ if (typeof window === 'undefined') {
}
+/* 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 && appData[5] === 0) { // 'Adobe\x00'
+ adobe = {
+ version: 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;
+ 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 = {
@@ -35104,70 +35264,125 @@ var JpxImage = (function JpxImageClosure() {
this.failOnCorruptedImage = false;
}
JpxImage.prototype = {
- load: function JpxImage_load(url) {
- var xhr = new XMLHttpRequest();
- xhr.open('GET', url, true);
- xhr.responseType = 'arraybuffer';
- xhr.onload = (function() {
- // TODO catch parse error
- var data = new Uint8Array(xhr.response || xhr.mozResponseArrayBuffer);
- this.parse(data);
- if (this.onload)
- this.onload();
- }).bind(this);
- xhr.send(null);
- },
parse: function JpxImage_parse(data) {
- function readUint(data, offset, bytes) {
- var n = 0;
- for (var i = 0; i < bytes; i++)
- n = n * 256 + (data[offset + i] & 0xFF);
- return n;
+
+ 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 = readUint(data, position, 4);
- var tbox = readUint(data, position + 4, 4);
+ var lbox = readUint32(data, position);
+ var tbox = readUint32(data, position + 4);
position += headerSize;
- if (lbox == 1) {
- lbox = readUint(data, position, 8);
+ 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)
+ if (lbox === 0) {
lbox = length - position + headerSize;
- if (lbox < headerSize)
- error('JPX error: Invalid box field size');
+ }
+ if (lbox < headerSize) {
+ throw new Error('JPX Error: Invalid box field size');
+ }
var dataLength = lbox - headerSize;
var jumpDataLength = true;
switch (tbox) {
- case 0x6A501A1A: // 'jP\032\032'
- // TODO
- break;
case 0x6A703268: // 'jp2h'
jumpDataLength = false; // parsing child boxes
break;
case 0x636F6C72: // 'colr'
- // TODO
+ // 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)
+ 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 < end) {
+ while (position + 1 < end) {
var code = readUint16(data, position);
position += 2;
- var length = 0, j;
+ var length = 0, j, sqcd, spqcds, spqcdSize, scalarExpounded, tile;
switch (code) {
case 0xFF4F: // Start of codestream (SOC)
context.mainHeader = true;
@@ -35205,12 +35420,16 @@ var JpxImage = (function JpxImageClosure() {
context.QCC = [];
context.COC = [];
break;
+ case 0xFF55: // Tile-part lengths, main header (TLM)
+ var Ltlm = readUint16(data, position); // Marker segment length
+ // Skip tile length markers
+ position += Ltlm;
+ break;
case 0xFF5C: // Quantization default (QCD)
length = readUint16(data, position);
var qcd = {};
j = position + 2;
- var sqcd = data[j++];
- var spqcdSize, scalarExpounded;
+ sqcd = data[j++];
switch (sqcd & 0x1F) {
case 0:
spqcdSize = 8;
@@ -35225,15 +35444,15 @@ var JpxImage = (function JpxImageClosure() {
scalarExpounded = true;
break;
default:
- throw 'Invalid SQcd value ' + sqcd;
+ throw new Error('JPX Error: Invalid SQcd value ' + sqcd);
}
- qcd.noQuantization = spqcdSize == 8;
+ qcd.noQuantization = (spqcdSize === 8);
qcd.scalarExpounded = scalarExpounded;
qcd.guardBits = sqcd >> 5;
- var spqcds = [];
+ spqcds = [];
while (j < length + position) {
var spqcd = {};
- if (spqcdSize == 8) {
+ if (spqcdSize === 8) {
spqcd.epsilon = data[j++] >> 3;
spqcd.mu = 0;
} else {
@@ -35244,9 +35463,9 @@ var JpxImage = (function JpxImageClosure() {
spqcds.push(spqcd);
}
qcd.SPqcds = spqcds;
- if (context.mainHeader)
+ if (context.mainHeader) {
context.QCD = qcd;
- else {
+ } else {
context.currentTile.QCD = qcd;
context.currentTile.QCC = [];
}
@@ -35256,14 +35475,13 @@ var JpxImage = (function JpxImageClosure() {
var qcc = {};
j = position + 2;
var cqcc;
- if (context.SIZ.Csiz < 257)
+ if (context.SIZ.Csiz < 257) {
cqcc = data[j++];
- else {
+ } else {
cqcc = readUint16(data, j);
j += 2;
}
- var sqcd = data[j++];
- var spqcdSize, scalarExpounded;
+ sqcd = data[j++];
switch (sqcd & 0x1F) {
case 0:
spqcdSize = 8;
@@ -35278,15 +35496,15 @@ var JpxImage = (function JpxImageClosure() {
scalarExpounded = true;
break;
default:
- throw 'Invalid SQcd value ' + sqcd;
+ throw new Error('JPX Error: Invalid SQcd value ' + sqcd);
}
- qcc.noQuantization = spqcdSize == 8;
+ qcc.noQuantization = (spqcdSize === 8);
qcc.scalarExpounded = scalarExpounded;
qcc.guardBits = sqcd >> 5;
- var spqcds = [];
- while (j < length + position) {
- var spqcd = {};
- if (spqcdSize == 8) {
+ spqcds = [];
+ while (j < (length + position)) {
+ spqcd = {};
+ if (spqcdSize === 8) {
spqcd.epsilon = data[j++] >> 3;
spqcd.mu = 0;
} else {
@@ -35297,10 +35515,11 @@ var JpxImage = (function JpxImageClosure() {
spqcds.push(spqcd);
}
qcc.SPqcds = spqcds;
- if (context.mainHeader)
+ if (context.mainHeader) {
context.QCC[cqcc] = qcc;
- else
+ } else {
context.currentTile.QCC[cqcc] = qcc;
+ }
break;
case 0xFF52: // Coding style default (COD)
length = readUint16(data, position);
@@ -35310,7 +35529,6 @@ var JpxImage = (function JpxImageClosure() {
cod.entropyCoderWithCustomPrecincts = !!(scod & 1);
cod.sopMarkerUsed = !!(scod & 2);
cod.ephMarkerUsed = !!(scod & 4);
- var codingStyle = {};
cod.progressionOrder = data[j++];
cod.layersCount = readUint16(data, j);
j += 2;
@@ -35326,11 +35544,11 @@ var JpxImage = (function JpxImageClosure() {
cod.verticalyStripe = !!(blockStyle & 8);
cod.predictableTermination = !!(blockStyle & 16);
cod.segmentationSymbolUsed = !!(blockStyle & 32);
- cod.transformation = data[j++];
+ cod.reversibleTransformation = data[j++];
if (cod.entropyCoderWithCustomPrecincts) {
- var precinctsSizes = {};
+ var precinctsSizes = [];
while (j < length + position) {
- var precinctsSize = data[j];
+ var precinctsSize = data[j++];
precinctsSizes.push({
PPx: precinctsSize & 0xF,
PPy: precinctsSize >> 4
@@ -35338,25 +35556,37 @@ var JpxImage = (function JpxImageClosure() {
}
cod.precinctsSizes = precinctsSizes;
}
-
- if (cod.sopMarkerUsed || cod.ephMarkerUsed ||
- cod.selectiveArithmeticCodingBypass ||
- cod.resetContextProbabilities ||
- cod.terminationOnEachCodingPass ||
- cod.verticalyStripe || cod.predictableTermination)
- throw 'Unsupported COD options: ' +
- globalScope.JSON.stringify(cod);
-
- if (context.mainHeader)
+ 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 {
+ } else {
context.currentTile.COD = cod;
context.currentTile.COC = [];
}
break;
case 0xFF90: // Start of tile-part (SOT)
length = readUint16(data, position);
- var tile = {};
+ tile = {};
tile.index = readUint16(data, position + 2);
tile.length = readUint32(data, position + 4);
tile.dataEnd = tile.length + position - 2;
@@ -35374,7 +35604,7 @@ var JpxImage = (function JpxImageClosure() {
context.currentTile = tile;
break;
case 0xFF93: // Start of data (SOD)
- var tile = context.currentTile;
+ tile = context.currentTile;
if (tile.partIndex === 0) {
initializeTile(context, tile.index);
buildPackets(context);
@@ -35382,23 +35612,27 @@ var JpxImage = (function JpxImageClosure() {
// moving to the end of the data
length = tile.dataEnd - position;
-
parseTilePackets(context, data, position, length);
break;
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 'Unknown codestream code: ' + code.toString(16);
+ throw new Error('JPX Error: Unknown codestream code: ' +
+ code.toString(16));
}
position += length;
}
} catch (e) {
- if (this.failOnCorruptedImage)
- error('JPX error: ' + e);
- else
- warn('JPX error: ' + e + '. Trying to recover');
+ 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;
@@ -35406,21 +35640,6 @@ var JpxImage = (function JpxImageClosure() {
this.componentsCount = context.SIZ.Csiz;
}
};
- function readUint32(data, offset) {
- return (data[offset] << 24) | (data[offset + 1] << 16) |
- (data[offset + 2] << 8) | data[offset + 3];
- }
- function readUint16(data, offset) {
- return (data[offset] << 8) | data[offset + 1];
- }
- function log2(x) {
- var n = 1, i = 0;
- while (x > n) {
- n <<= 1;
- i++;
- }
- return i;
- }
function calculateComponentDimensions(component, siz) {
// Section B.2 Component mapping
component.x0 = Math.ceil(siz.XOsiz / component.XRsiz);
@@ -35433,12 +35652,12 @@ var JpxImage = (function JpxImageClosure() {
function calculateTileGrids(context, components) {
var siz = context.SIZ;
// Section B.3 Division into tile and tile-components
- var tiles = [];
+ 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++) {
- var tile = {};
+ 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);
@@ -35454,9 +35673,9 @@ var JpxImage = (function JpxImageClosure() {
var componentsCount = siz.Csiz;
for (var i = 0, ii = componentsCount; i < ii; i++) {
var component = components[i];
- var tileComponents = [];
for (var j = 0, jj = tiles.length; j < jj; j++) {
- var tileComponent = {}, tile = tiles[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);
@@ -35478,35 +35697,49 @@ var JpxImage = (function JpxImageClosure() {
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);
+ 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;
- var numprecinctswide = resolution.trx1 > resolution.trx0 ?
+ // 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.floor(resolution.trx0 / precinctWidth) : 0);
+ var numprecinctshigh = (resolution.try1 > resolution.try0 ?
Math.ceil(resolution.try1 / precinctHeight) -
- Math.floor(resolution.try0 / precinctHeight) : 0;
+ Math.floor(resolution.try0 / precinctHeight) : 0);
var numprecincts = numprecinctswide * numprecinctshigh;
- var precinctXOffset = Math.floor(resolution.trx0 / precinctWidth) *
- precinctWidth;
- var precinctYOffset = Math.floor(resolution.try0 / precinctHeight) *
- precinctHeight;
+
resolution.precinctParameters = {
- precinctXOffset: precinctXOffset,
- precinctYOffset: precinctYOffset,
precinctWidth: precinctWidth,
precinctHeight: precinctHeight,
numprecinctswide: numprecinctswide,
numprecinctshigh: numprecinctshigh,
- numprecincts: numprecincts
+ numprecincts: numprecincts,
+ precinctWidthInSubband: precinctWidthInSubband,
+ precinctHeightInSubband: precinctHeightInSubband
};
}
function buildCodeblocks(context, subband, dimensions) {
@@ -35515,16 +35748,17 @@ var JpxImage = (function JpxImageClosure() {
var ycb_ = dimensions.ycb_;
var codeblockWidth = 1 << xcb_;
var codeblockHeight = 1 << ycb_;
- var cbx0 = Math.floor(subband.tbx0 / codeblockWidth);
- var cby0 = Math.floor(subband.tby0 / codeblockHeight);
- var cbx1 = Math.ceil(subband.tbx1 / codeblockWidth);
- var cby1 = Math.ceil(subband.tby1 / codeblockHeight);
+ 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 = [];
- for (var j = cby0; j < cby1; j++) {
- for (var i = cbx0; i < cbx1; i++) {
- var codeblock = {
+ 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,
@@ -35532,33 +35766,43 @@ var JpxImage = (function JpxImageClosure() {
tbx1: codeblockWidth * (i + 1),
tby1: codeblockHeight * (j + 1)
};
- // calculate precinct number
- var pi = Math.floor((codeblock.tbx0 -
- precinctParameters.precinctXOffset) /
- precinctParameters.precinctWidth);
- var pj = Math.floor((codeblock.tby0 -
- precinctParameters.precinctYOffset) /
- precinctParameters.precinctHeight);
- var precinctNumber = pj +
- pi * precinctParameters.numprecinctswide;
+
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;
- var coefficientsLength = (codeblock.tbx1_ - codeblock.tbx0_) *
- (codeblock.tby1_ - codeblock.tby0_);
codeblock.Lblock = 3;
+
+ if (codeblock.tbx1_ <= codeblock.tbx0_ ||
+ codeblock.tby1_ <= codeblock.tby0_) {
+ continue;
+ }
codeblocks.push(codeblock);
// building precinct for the sub-band
- var precinct;
- if (precinctNumber in precincts) {
- precinct = precincts[precinctNumber];
- precinct.cbxMin = Math.min(precinct.cbxMin, i);
- precinct.cbyMin = Math.min(precinct.cbyMin, j);
- precinct.cbxMax = Math.max(precinct.cbxMax, i);
- precinct.cbyMax = Math.max(precinct.cbyMax, j);
+ 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,
@@ -35574,13 +35818,9 @@ var JpxImage = (function JpxImageClosure() {
codeblockWidth: xcb_,
codeblockHeight: ycb_,
numcodeblockwide: cbx1 - cbx0 + 1,
- numcodeblockhigh: cby1 - cby1 + 1
+ numcodeblockhigh: cby1 - cby0 + 1
};
subband.codeblocks = codeblocks;
- for (var i = 0, ii = codeblocks.length; i < ii; i++) {
- var codeblock = codeblocks[i];
- var precinctNumber = codeblock.precinctNumber;
- }
subband.precincts = precincts;
}
function createPacket(resolution, precinctNumber, layerNumber) {
@@ -35593,8 +35833,9 @@ var JpxImage = (function JpxImageClosure() {
var codeblocks = subband.codeblocks;
for (var j = 0, jj = codeblocks.length; j < jj; j++) {
var codeblock = codeblocks[j];
- if (codeblock.precinctNumber != precinctNumber)
+ if (codeblock.precinctNumber !== precinctNumber) {
continue;
+ }
precinctCodeblocks.push(codeblock);
}
}
@@ -35623,8 +35864,9 @@ var JpxImage = (function JpxImageClosure() {
for (; r <= maxDecompositionLevelsCount; r++) {
for (; i < componentsCount; i++) {
var component = tile.components[i];
- if (r > component.codingStyleParameters.decompositionLevelsCount)
+ if (r > component.codingStyleParameters.decompositionLevelsCount) {
continue;
+ }
var resolution = component.resolutions[r];
var numprecincts = resolution.precinctParameters.numprecincts;
@@ -35639,7 +35881,7 @@ var JpxImage = (function JpxImageClosure() {
}
r = 0;
}
- throw 'Out of packets';
+ throw new Error('JPX Error: Out of packets');
};
}
function ResolutionLayerComponentPositionIterator(context) {
@@ -35662,8 +35904,9 @@ var JpxImage = (function JpxImageClosure() {
for (; l < layersCount; l++) {
for (; i < componentsCount; i++) {
var component = tile.components[i];
- if (r > component.codingStyleParameters.decompositionLevelsCount)
+ if (r > component.codingStyleParameters.decompositionLevelsCount) {
continue;
+ }
var resolution = component.resolutions[r];
var numprecincts = resolution.precinctParameters.numprecincts;
@@ -35678,7 +35921,231 @@ var JpxImage = (function JpxImageClosure() {
}
l = 0;
}
- throw 'Out of packets';
+ 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) {
@@ -35702,6 +36169,7 @@ var JpxImage = (function JpxImageClosure() {
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);
@@ -35763,7 +36231,6 @@ var JpxImage = (function JpxImageClosure() {
}
// Generate the packets sequence
var progressionOrder = tile.codingStyleDefaultParameters.progressionOrder;
- var packetsIterator;
switch (progressionOrder) {
case 0:
tile.packetsIterator =
@@ -35773,8 +36240,21 @@ var JpxImage = (function JpxImageClosure() {
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 'Unsupported progression order ' + progressionOrder;
+ throw new Error('JPX Error: Unsupported progression order ' +
+ progressionOrder);
}
}
function parseTilePackets(context, data, offset, dataLength) {
@@ -35792,13 +36272,28 @@ var JpxImage = (function JpxImageClosure() {
buffer = (buffer << 8) | b;
bufferSize += 8;
}
- if (b == 0xFF) {
+ 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) {
@@ -35807,46 +36302,55 @@ var JpxImage = (function JpxImageClosure() {
}
}
function readCodingpasses() {
- var value = readBits(1);
- if (value === 0)
+ if (readBits(1) === 0) {
return 1;
- value = (value << 1) | readBits(1);
- if (value == 0x02)
+ }
+ if (readBits(1) === 0) {
return 2;
- value = (value << 2) | readBits(2);
- if (value <= 0x0E)
- return (value & 0x03) + 3;
- value = (value << 5) | readBits(5);
- if (value <= 0x1FE)
- return (value & 0x1F) + 6;
- value = (value << 7) | readBits(7);
- return (value & 0x7F) + 37;
+ }
+ 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)) {
- alignToByte();
continue;
}
var layerNumber = packet.layerNumber;
- var queue = [];
+ var queue = [], codeblock;
for (var i = 0, ii = packet.codeblocks.length; i < ii; i++) {
- var codeblock = packet.codeblocks[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;
- if ('included' in codeblock) {
+ var valueReady;
+ if (codeblock['included'] !== undefined) {
codeblockIncluded = !!readBits(1);
} else {
// reading inclusion tree
- var precinct = codeblock.precinct;
+ precinct = codeblock.precinct;
var inclusionTree, zeroBitPlanesTree;
- if ('inclusionTree' in precinct) {
+ if (precinct['inclusionTree'] !== undefined) {
inclusionTree = precinct.inclusionTree;
} else {
// building inclusion and zero bit-planes trees
@@ -35861,7 +36365,7 @@ var JpxImage = (function JpxImageClosure() {
if (inclusionTree.reset(codeblockColumn, codeblockRow, layerNumber)) {
while (true) {
if (readBits(1)) {
- var valueReady = !inclusionTree.nextLevel();
+ valueReady = !inclusionTree.nextLevel();
if (valueReady) {
codeblock.included = true;
codeblockIncluded = firstTimeInclusion = true;
@@ -35874,24 +36378,28 @@ var JpxImage = (function JpxImageClosure() {
}
}
}
- if (!codeblockIncluded)
+ if (!codeblockIncluded) {
continue;
+ }
if (firstTimeInclusion) {
zeroBitPlanesTree = precinct.zeroBitPlanesTree;
zeroBitPlanesTree.reset(codeblockColumn, codeblockRow);
while (true) {
if (readBits(1)) {
- var valueReady = !zeroBitPlanesTree.nextLevel();
- if (valueReady)
+ valueReady = !zeroBitPlanesTree.nextLevel();
+ if (valueReady) {
break;
- } else
+ }
+ } else {
zeroBitPlanesTree.incrementValue();
+ }
}
codeblock.zeroBitPlanes = zeroBitPlanesTree.value;
}
var codingpasses = readCodingpasses();
- while (readBits(1))
+ while (readBits(1)) {
codeblock.Lblock++;
+ }
var codingpassesLog2 = log2(codingpasses);
// rounding down log2
var bits = ((codingpasses < (1 << codingpassesLog2)) ?
@@ -35904,11 +36412,15 @@ var JpxImage = (function JpxImageClosure() {
});
}
alignToByte();
+ if (ephMarkerUsed) {
+ skipMarkerIfEqual(0x92);
+ }
while (queue.length > 0) {
var packetItem = queue.shift();
- var codeblock = packetItem.codeblock;
- if (!('data' in codeblock))
+ codeblock = packetItem.codeblock;
+ if (codeblock['data'] === undefined) {
codeblock.data = [];
+ }
codeblock.data.push({
data: data,
start: offset + position,
@@ -35920,43 +36432,52 @@ var JpxImage = (function JpxImageClosure() {
}
return position;
}
- function copyCoefficients(coefficients, x0, y0, width, height,
- delta, mb, codeblocks, transformation,
- segmentationSymbolUsed) {
- var r = 0.5; // formula (E-6)
+ 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)
+ if (blockWidth === 0 || blockHeight === 0) {
continue;
- if (!('data' in codeblock))
+ }
+ if (codeblock['data'] === undefined) {
continue;
+ }
var bitModel, currentCodingpassType;
bitModel = new BitModel(blockWidth, blockHeight, codeblock.subbandType,
- codeblock.zeroBitPlanes);
+ codeblock.zeroBitPlanes, mb);
currentCodingpassType = 2; // first bit plane starts from cleanup
// collect data
var data = codeblock.data, totalLength = 0, codingpasses = 0;
- for (var q = 0, qq = data.length; q < qq; q++) {
- var dataItem = data[q];
+ 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), k = 0;
- for (var q = 0, qq = data.length; q < qq; q++) {
- var dataItem = data[q];
+ 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, k);
- k += chunk.length;
+ encodedData.set(chunk, position);
+ position += chunk.length;
}
// decoding the item
var decoder = new ArithmeticDecoder(encodedData, 0, totalLength);
bitModel.setDecoder(decoder);
- for (var q = 0; q < codingpasses; q++) {
+ for (j = 0; j < codingpasses; j++) {
switch (currentCodingpassType) {
case 0:
bitModel.runSignificancePropogationPass();
@@ -35966,28 +36487,43 @@ var JpxImage = (function JpxImageClosure() {
break;
case 2:
bitModel.runCleanupPass();
- if (segmentationSymbolUsed)
+ if (segmentationSymbolUsed) {
bitModel.checkSegmentationSymbol();
+ }
break;
}
currentCodingpassType = (currentCodingpassType + 1) % 3;
}
var offset = (codeblock.tbx0_ - x0) + (codeblock.tby0_ - y0) * width;
- var position = 0;
- for (var j = 0; j < blockHeight; j++) {
- for (var k = 0; k < blockWidth; k++) {
- var n = (bitModel.coefficentsSign[position] ? -1 : 1) *
- bitModel.coefficentsMagnitude[position];
- var nb = bitModel.bitsDecoded[position], correction;
- if (transformation === 0 || mb > nb) {
- // use r only if transformation is irreversible or
- // not all bitplanes were decoded for reversible transformation
- n += n < 0 ? n - r : n > 0 ? n + r : 0;
- correction = 1 << (mb - nb);
- } else
- correction = 1;
- coefficients[offset++] = n * correction * delta;
+ 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;
@@ -36003,15 +36539,23 @@ var JpxImage = (function JpxImageClosure() {
var spqcds = quantizationParameters.SPqcds;
var scalarExpounded = quantizationParameters.scalarExpounded;
var guardBits = quantizationParameters.guardBits;
- var transformation = codingStyleParameters.transformation;
var segmentationSymbolUsed = codingStyleParameters.segmentationSymbolUsed;
var precision = context.components[c].precision;
+ var reversible = codingStyleParameters.reversibleTransformation;
+ var transform = (reversible ? new ReversibleTransform() :
+ new IrreversibleTransform());
+
var subbandCoefficients = [];
- var k = 0, b = 0;
+ 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) {
@@ -36021,38 +36565,34 @@ var JpxImage = (function JpxImageClosure() {
} else {
mu = spqcds[b].mu;
epsilon = spqcds[b].epsilon;
+ b++;
}
var subband = resolution.subbands[j];
- var width = subband.tbx1 - subband.tbx0;
- var height = subband.tby1 - subband.tby0;
var gainLog2 = SubbandsGainLog2[subband.type];
// calulate quantization coefficient (Section E.1.1.1)
- var delta = Math.pow(2, (precision + gainLog2) - epsilon) *
- (1 + mu / 2048);
+ var delta = (reversible ? 1 :
+ Math.pow(2, precision + gainLog2 - epsilon) * (1 + mu / 2048));
var mb = (guardBits + epsilon - 1);
- var coefficients = new Float32Array(width * height);
- copyCoefficients(coefficients, subband.tbx0, subband.tby0,
- width, height, delta, mb, subband.codeblocks, transformation,
- segmentationSymbolUsed);
-
- subbandCoefficients.push({
- width: width,
- height: height,
- items: coefficients
- });
-
- b++;
+ // 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 transformation = codingStyleParameters.transformation;
- var transform = transformation === 0 ? new IrreversibleTransform() :
- new ReversibleTransform();
var result = transform.calculate(subbandCoefficients,
- component.tcx0, component.tcy0);
+ component.tcx0, component.tcy0);
return {
left: component.tcx0,
top: component.tcy0,
@@ -36068,54 +36608,91 @@ var JpxImage = (function JpxImageClosure() {
var resultImages = [];
for (var i = 0, ii = context.tiles.length; i < ii; i++) {
var tile = context.tiles[i];
- var result = [];
- for (var c = 0; c < componentsCount; c++) {
- var image = transformTile(context, tile, c);
- result.push(image);
+ 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 y0items = result[0].items;
- var y1items = result[1].items;
- var y2items = result[2].items;
- for (var j = 0, jj = y0items.length; j < jj; j++) {
- var y0 = y0items[j], y1 = y1items[j], y2 = y2items[j];
- var i1 = y0 - ((y2 + y1) >> 2);
- y1items[j] = i1;
- y0items[j] = y2 + i1;
- y2items[j] = y1 + i1;
+ 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;
+ }
}
}
-
- // Section G.1 DC level shifting to unsigned component values
- for (var c = 0; c < componentsCount; c++) {
- var component = components[c];
- if (component.isSigned)
- continue;
-
- var offset = 1 << (component.precision - 1);
- var tileImage = result[c];
- var items = tileImage.items;
- for (var j = 0, jj = items.length; j < jj; j++)
- items[j] += offset;
- }
-
- // To simplify things: shift and clamp output to 8 bit unsigned
- for (var c = 0; c < componentsCount; c++) {
- var component = components[c];
- var offset = component.isSigned ? 128 : 0;
- var shift = component.precision - 8;
- var tileImage = result[c];
- var items = tileImage.items;
- var data = new Uint8Array(items.length);
- for (var j = 0, jj = items.length; j < jj; j++) {
- var value = (items[j] >> shift) + offset;
- data[j] = value < 0 ? 0 : value > 255 ? 255 : value;
- }
- result[c].items = data;
- }
-
resultImages.push(result);
}
return resultImages;
@@ -36124,14 +36701,13 @@ var JpxImage = (function JpxImageClosure() {
var siz = context.SIZ;
var componentsCount = siz.Csiz;
var tile = context.tiles[tileIndex];
- var resultTiles = [];
for (var c = 0; c < componentsCount; c++) {
var component = tile.components[c];
- var qcdOrQcc = c in context.currentTile.QCC ?
- context.currentTile.QCC[c] : context.currentTile.QCD;
+ var qcdOrQcc = (context.currentTile.QCC[c] !== undefined ?
+ context.currentTile.QCC[c] : context.currentTile.QCD);
component.quantizationParameters = qcdOrQcc;
- var codOrCoc = c in context.currentTile.COC ?
- context.currentTile.COC[c] : context.currentTile.COD;
+ var codOrCoc = (context.currentTile.COC[c] !== undefined ?
+ context.currentTile.COC[c] : context.currentTile.COD);
component.codingStyleParameters = codOrCoc;
}
tile.codingStyleDefaultParameters = context.currentTile.COD;
@@ -36155,11 +36731,11 @@ var JpxImage = (function JpxImageClosure() {
}
TagTree.prototype = {
reset: function TagTree_reset(i, j) {
- var currentLevel = 0, value = 0;
+ var currentLevel = 0, value = 0, level;
while (currentLevel < this.levels.length) {
- var level = this.levels[currentLevel];
+ level = this.levels[currentLevel];
var index = i + j * level.width;
- if (index in level.items) {
+ if (level.items[index] !== undefined) {
value = level.items[index];
break;
}
@@ -36169,7 +36745,7 @@ var JpxImage = (function JpxImageClosure() {
currentLevel++;
}
currentLevel--;
- var level = this.levels[currentLevel];
+ level = this.levels[currentLevel];
level.items[level.index] = value;
this.currentLevel = currentLevel;
delete this.value;
@@ -36189,7 +36765,7 @@ var JpxImage = (function JpxImageClosure() {
}
this.currentLevel = currentLevel;
- var level = this.levels[currentLevel];
+ level = this.levels[currentLevel];
level.items[level.index] = value;
return true;
}
@@ -36203,8 +36779,9 @@ var JpxImage = (function JpxImageClosure() {
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++)
+ for (var j = 0, jj = items.length; j < jj; j++) {
items[j] = defaultValue;
+ }
var level = {
width: width,
@@ -36226,8 +36803,9 @@ var JpxImage = (function JpxImageClosure() {
level.index = index;
var value = level.items[index];
- if (value == 0xFF)
+ if (value === 0xFF) {
break;
+ }
if (value > stopValue) {
this.currentLevel = currentLevel;
@@ -36253,7 +36831,7 @@ var JpxImage = (function JpxImageClosure() {
var level = this.levels[levelIndex];
var currentValue = level.items[level.index];
while (--levelIndex >= 0) {
- var level = this.levels[levelIndex];
+ level = this.levels[levelIndex];
level.items[level.index] = currentValue;
}
},
@@ -36263,11 +36841,12 @@ var JpxImage = (function JpxImageClosure() {
var value = level.items[level.index];
level.items[level.index] = 0xFF;
currentLevel--;
- if (currentLevel < 0)
+ if (currentLevel < 0) {
return false;
+ }
this.currentLevel = currentLevel;
- var level = this.levels[currentLevel];
+ level = this.levels[currentLevel];
level.items[level.index] = value;
return true;
}
@@ -36275,171 +36854,10 @@ var JpxImage = (function JpxImageClosure() {
return InclusionTree;
})();
- // Implements C.3. Arithmetic decoding procedures
- var ArithmeticDecoder = (function ArithmeticDecoderClosure() {
- 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}
- ];
-
- 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 = {
- 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;
- }
- },
- readBit: function ArithmeticDecoder_readBit(cx) {
- var qeIcx = QeTable[cx.index].qe;
- this.a -= qeIcx;
-
- if (this.chigh < qeIcx) {
- var d = this.exchangeLps(cx);
- this.renormD();
- return d;
- } else {
- this.chigh -= qeIcx;
- if ((this.a & 0x8000) === 0) {
- var d = this.exchangeMps(cx);
- this.renormD();
- return d;
- } else {
- return cx.mps;
- }
- }
- },
- renormD: function ArithmeticDecoder_renormD() {
- do {
- if (this.ct === 0)
- this.byteIn();
-
- this.a <<= 1;
- this.chigh = ((this.chigh << 1) & 0xFFFF) | ((this.clow >> 15) & 1);
- this.clow = (this.clow << 1) & 0xFFFF;
- this.ct--;
- } while ((this.a & 0x8000) === 0);
- },
- exchangeMps: function ArithmeticDecoder_exchangeMps(cx) {
- var d;
- var qeTableIcx = QeTable[cx.index];
- if (this.a < qeTableIcx.qe) {
- d = 1 - cx.mps;
-
- if (qeTableIcx.switchFlag == 1) {
- cx.mps = 1 - cx.mps;
- }
- cx.index = qeTableIcx.nlps;
- } else {
- d = cx.mps;
- cx.index = qeTableIcx.nmps;
- }
- return d;
- },
- exchangeLps: function ArithmeticDecoder_exchangeLps(cx) {
- var d;
- var qeTableIcx = QeTable[cx.index];
- if (this.a < qeTableIcx.qe) {
- this.a = qeTableIcx.qe;
- d = cx.mps;
- cx.index = qeTableIcx.nmps;
- } else {
- this.a = qeTableIcx.qe;
- d = 1 - cx.mps;
-
- if (qeTableIcx.switchFlag == 1) {
- cx.mps = 1 - cx.mps;
- }
- cx.index = qeTableIcx.nlps;
- }
- return d;
- }
- };
-
- return ArithmeticDecoder;
- })();
-
// 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)
@@ -36459,35 +36877,12 @@ var JpxImage = (function JpxImageClosure() {
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
]);
- // Table D-2
- function calcSignContribution(significance0, sign0, significance1, sign1) {
- if (significance1) {
- if (!sign1)
- return significance0 ? (!sign0 ? 1 : 0) : 1;
- else
- return significance0 ? (!sign0 ? 0 : -1) : -1;
- } else
- return significance0 ? (!sign0 ? 1 : -1) : 0;
- }
- // Table D-3
- var SignContextLabels = [
- {contextLabel: 13, xorBit: 0},
- {contextLabel: 12, xorBit: 0},
- {contextLabel: 11, xorBit: 0},
- {contextLabel: 10, xorBit: 0},
- {contextLabel: 9, xorBit: 0},
- {contextLabel: 10, xorBit: 1},
- {contextLabel: 11, xorBit: 1},
- {contextLabel: 12, xorBit: 1},
- {contextLabel: 13, xorBit: 1}
- ];
-
- function BitModel(width, height, subband, zeroBitPlanes) {
+ function BitModel(width, height, subband, zeroBitPlanes, mb) {
this.width = width;
this.height = height;
- this.contextLabelTable = subband == 'HH' ? HHContextLabel :
- subband == 'HL' ? HLContextLabel : LLAndLHContextsLabel;
+ this.contextLabelTable = (subband === 'HH' ? HHContextLabel :
+ (subband === 'HL' ? HLContextLabel : LLAndLHContextsLabel));
var coefficientCount = width * height;
@@ -36495,12 +36890,17 @@ var JpxImage = (function JpxImageClosure() {
// add border state cells for significanceState
this.neighborsSignificance = new Uint8Array(coefficientCount);
this.coefficentsSign = new Uint8Array(coefficientCount);
- this.coefficentsMagnitude = new Uint32Array(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(this.width * this.height);
- for (var i = 0, ii = bitsDecoded.length; i < ii; i++)
- bitsDecoded[i] = zeroBitPlanes;
+ var bitsDecoded = new Uint8Array(coefficientCount);
+ if (zeroBitPlanes !== 0) {
+ for (var i = 0; i < coefficientCount; i++) {
+ bitsDecoded[i] = zeroBitPlanes;
+ }
+ }
this.bitsDecoded = bitsDecoded;
this.reset();
@@ -36511,36 +36911,52 @@ var JpxImage = (function JpxImageClosure() {
this.decoder = decoder;
},
reset: function BitModel_reset() {
- this.uniformContext = {index: 46, mps: 0};
- this.runLengthContext = {index: 3, mps: 0};
- this.contexts = [];
- this.contexts.push({index: 4, mps: 0});
- for (var i = 1; i <= 16; i++)
- this.contexts.push({index: 0, mps: 0});
+ // 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) {
+ function BitModel_setNeighborsSignificance(row, column, index) {
var neighborsSignificance = this.neighborsSignificance;
var width = this.width, height = this.height;
- var index = row * width + column;
+ var left = (column > 0);
+ var right = (column + 1 < width);
+ var i;
+
if (row > 0) {
- if (column > 0)
- neighborsSignificance[index - width - 1] += 0x10;
- if (column + 1 < width)
- neighborsSignificance[index - width + 1] += 0x10;
- neighborsSignificance[index - width] += 0x04;
+ i = index - width;
+ if (left) {
+ neighborsSignificance[i - 1] += 0x10;
+ }
+ if (right) {
+ neighborsSignificance[i + 1] += 0x10;
+ }
+ neighborsSignificance[i] += 0x04;
}
+
if (row + 1 < height) {
- if (column > 0)
- neighborsSignificance[index + width - 1] += 0x10;
- if (column + 1 < width)
- neighborsSignificance[index + width + 1] += 0x10;
- neighborsSignificance[index + width] += 0x04;
+ i = index + width;
+ if (left) {
+ neighborsSignificance[i - 1] += 0x10;
+ }
+ if (right) {
+ neighborsSignificance[i + 1] += 0x10;
+ }
+ neighborsSignificance[i] += 0x04;
}
- if (column > 0)
+
+ if (left) {
neighborsSignificance[index - 1] += 0x01;
- if (column + 1 < width)
+ }
+ if (right) {
neighborsSignificance[index + 1] += 0x01;
+ }
neighborsSignificance[index] |= 0x80;
},
runSignificancePropogationPass:
@@ -36549,38 +36965,38 @@ var JpxImage = (function JpxImageClosure() {
var width = this.width, height = this.height;
var coefficentsMagnitude = this.coefficentsMagnitude;
var coefficentsSign = this.coefficentsSign;
- var contextLabels = this.contextLabels;
var neighborsSignificance = this.neighborsSignificance;
var processingFlags = this.processingFlags;
var contexts = this.contexts;
var labels = this.contextLabelTable;
var bitsDecoded = this.bitsDecoded;
- // clear processed flag
var processedInverseMask = ~1;
var processedMask = 1;
var firstMagnitudeBitMask = 2;
- for (var q = 0, qq = width * height; q < qq; q++)
- processingFlags[q] &= processedInverseMask;
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)
+ if (i >= height) {
break;
+ }
+ // clear processed flag first
+ processingFlags[index] &= processedInverseMask;
- if (coefficentsMagnitude[index] || !neighborsSignificance[index])
+ if (coefficentsMagnitude[index] ||
+ !neighborsSignificance[index]) {
continue;
+ }
var contextLabel = labels[neighborsSignificance[index]];
- var cx = contexts[contextLabel];
- var decision = decoder.readBit(cx);
+ var decision = decoder.readBit(contexts, contextLabel);
if (decision) {
- var sign = this.decodeSignBit(i, j);
+ var sign = this.decodeSignBit(i, j, index);
coefficentsSign[index] = sign;
coefficentsMagnitude[index] = 1;
- this.setNeighborsSignificance(i, j);
+ this.setNeighborsSignificance(i, j, index);
processingFlags[index] |= firstMagnitudeBitMask;
}
bitsDecoded[index]++;
@@ -36589,28 +37005,56 @@ var JpxImage = (function JpxImageClosure() {
}
}
},
- decodeSignBit: function BitModel_decodeSignBit(row, column) {
+ decodeSignBit: function BitModel_decodeSignBit(row, column, index) {
var width = this.width, height = this.height;
- var index = row * width + column;
var coefficentsMagnitude = this.coefficentsMagnitude;
var coefficentsSign = this.coefficentsSign;
- var horizontalContribution = calcSignContribution(
- column > 0 && coefficentsMagnitude[index - 1],
- coefficentsSign[index - 1],
- column + 1 < width && coefficentsMagnitude[index + 1],
- coefficentsSign[index + 1]);
- var verticalContribution = calcSignContribution(
- row > 0 && coefficentsMagnitude[index - width],
- coefficentsSign[index - width],
- row + 1 < height && coefficentsMagnitude[index + width],
- coefficentsSign[index + width]);
+ var contribution, sign0, sign1, significance1;
+ var contextLabel, decoded;
- var contextLabelAndXor = SignContextLabels[
- 3 * (1 - horizontalContribution) + (1 - verticalContribution)];
- var contextLabel = contextLabelAndXor.contextLabel;
- var cx = this.contexts[contextLabel];
- var decoded = this.decoder.readBit(cx);
- return decoded ^ contextLabelAndXor.xorBit;
+ // 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() {
@@ -36623,32 +37067,29 @@ var JpxImage = (function JpxImageClosure() {
var processingFlags = this.processingFlags;
var processedMask = 1;
var firstMagnitudeBitMask = 2;
- for (var i0 = 0; i0 < height; i0 += 4) {
+ 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 i1 = 0; i1 < 4; i1++) {
- var i = i0 + i1;
- if (i >= height)
- break;
- var index = i * 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)
+ (processingFlags[index] & processedMask) !== 0) {
continue;
-
- var contextLabel = 16;
- if ((processingFlags[index] &
- firstMagnitudeBitMask) !== 0) {
- processingFlags[i * width + j] ^= firstMagnitudeBitMask;
- // first refinement
- var significance = neighborsSignificance[index];
- var sumOfSignificance = (significance & 3) +
- ((significance >> 2) & 3) + ((significance >> 4) & 7);
- contextLabel = sumOfSignificance >= 1 ? 15 : 14;
}
- var cx = contexts[contextLabel];
- var bit = decoder.readBit(cx);
+ 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]++;
@@ -36661,7 +37102,6 @@ var JpxImage = (function JpxImageClosure() {
var decoder = this.decoder;
var width = this.width, height = this.height;
var neighborsSignificance = this.neighborsSignificance;
- var significanceState = this.significanceState;
var coefficentsMagnitude = this.coefficentsMagnitude;
var coefficentsSign = this.coefficentsSign;
var contexts = this.contexts;
@@ -36673,12 +37113,16 @@ var JpxImage = (function JpxImageClosure() {
var oneRowDown = width;
var twoRowsDown = width * 2;
var threeRowsDown = width * 3;
- for (var i0 = 0; i0 < height; i0 += 4) {
+ 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 = i0 * width + j;
- // using the property: labels[neighborsSignificance[index]] == 0
- // when neighborsSignificance[index] == 0
- var allEmpty = i0 + 3 < height &&
+ 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 &&
@@ -36686,12 +37130,12 @@ var JpxImage = (function JpxImageClosure() {
neighborsSignificance[index0] === 0 &&
neighborsSignificance[index0 + oneRowDown] === 0 &&
neighborsSignificance[index0 + twoRowsDown] === 0 &&
- neighborsSignificance[index0 + threeRowsDown] === 0;
+ neighborsSignificance[index0 + threeRowsDown] === 0);
var i1 = 0, index = index0;
- var cx, i;
+ var i = i0, sign;
if (allEmpty) {
- cx = this.runLengthContext;
- var hasSignificantCoefficent = decoder.readBit(cx);
+ var hasSignificantCoefficent =
+ decoder.readBit(contexts, RUNLENGTH_CONTEXT);
if (!hasSignificantCoefficent) {
bitsDecoded[index0]++;
bitsDecoded[index0 + oneRowDown]++;
@@ -36699,40 +37143,39 @@ var JpxImage = (function JpxImageClosure() {
bitsDecoded[index0 + threeRowsDown]++;
continue; // next column
}
- cx = this.uniformContext;
- i1 = (decoder.readBit(cx) << 1) | decoder.readBit(cx);
- i = i0 + i1;
- index += i1 * width;
+ i1 = (decoder.readBit(contexts, UNIFORM_CONTEXT) << 1) |
+ decoder.readBit(contexts, UNIFORM_CONTEXT);
+ if (i1 !== 0) {
+ i = i0 + i1;
+ index += i1 * width;
+ }
- var sign = this.decodeSignBit(i, j);
+ sign = this.decodeSignBit(i, j, index);
coefficentsSign[index] = sign;
coefficentsMagnitude[index] = 1;
- this.setNeighborsSignificance(i, j);
+ this.setNeighborsSignificance(i, j, index);
processingFlags[index] |= firstMagnitudeBitMask;
index = index0;
- for (var i2 = i0; i2 <= i; i2++, index += width)
+ for (var i2 = i0; i2 <= i; i2++, index += width) {
bitsDecoded[index]++;
+ }
i1++;
}
- for (; i1 < 4; i1++, index += width) {
- i = i0 + i1;
- if (i >= height)
- break;
-
+ for (i = i0 + i1; i < iNext; i++, index += width) {
if (coefficentsMagnitude[index] ||
- (processingFlags[index] & processedMask) !== 0)
+ (processingFlags[index] & processedMask) !== 0) {
continue;
+ }
var contextLabel = labels[neighborsSignificance[index]];
- cx = contexts[contextLabel];
- var decision = decoder.readBit(cx);
- if (decision == 1) {
- var sign = this.decodeSignBit(i, j);
+ 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);
+ this.setNeighborsSignificance(i, j, index);
processingFlags[index] |= firstMagnitudeBitMask;
}
bitsDecoded[index]++;
@@ -36742,128 +37185,139 @@ var JpxImage = (function JpxImageClosure() {
},
checkSegmentationSymbol: function BitModel_checkSegmentationSymbol() {
var decoder = this.decoder;
- var cx = this.uniformContext;
- var symbol = (decoder.readBit(cx) << 3) | (decoder.readBit(cx) << 2) |
- (decoder.readBit(cx) << 1) | decoder.readBit(cx);
- if (symbol != 0xA)
- throw 'Invalid segmentation symbol';
+ 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 transofrmation
+ // Section F, Discrete wavelet transformation
var Transform = (function TransformClosure() {
- function Transform() {
- }
+ function Transform() {}
+
Transform.prototype.calculate =
function transformCalculate(subbands, u0, v0) {
var ll = subbands[0];
- for (var i = 1, ii = subbands.length, j = 1; i < ii; i += 3, j++) {
- ll = this.iterate(ll, subbands[i], subbands[i + 1],
- subbands[i + 2], u0, v0);
+ for (var i = 1, ii = subbands.length; i < ii; i++) {
+ ll = this.iterate(ll, subbands[i], u0, v0);
}
return ll;
};
- Transform.prototype.expand = function expand(buffer, bufferPadding, step) {
- // Section F.3.7 extending... using max extension of 4
- var i1 = bufferPadding - 1, j1 = bufferPadding + 1;
- var i2 = bufferPadding + step - 2, j2 = bufferPadding + step;
- 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.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) {
+ Transform.prototype.iterate = function Transform_iterate(ll, hl_lh_hh,
+ u0, v0) {
var llWidth = ll.width, llHeight = ll.height, llItems = ll.items;
- var hlWidth = hl.width, hlHeight = hl.height, hlItems = hl.items;
- var lhWidth = lh.width, lhHeight = lh.height, lhItems = lh.items;
- var hhWidth = hh.width, hhHeight = hh.height, hhItems = hh.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;
- // Section F.3.3 interleave
- var width = llWidth + hlWidth;
- var height = llHeight + lhHeight;
- var items = new Float32Array(width * height);
- for (var i = 0, ii = llHeight; i < ii; i++) {
- var k = i * llWidth, l = i * 2 * width;
- for (var j = 0, jj = llWidth; j < jj; j++, k++, l += 2)
+ // 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];
+ }
}
- for (var i = 0, ii = hlHeight; i < ii; i++) {
- var k = i * hlWidth, l = i * 2 * width + 1;
- for (var j = 0, jj = hlWidth; j < jj; j++, k++, l += 2)
- items[l] = hlItems[k];
- }
- for (var i = 0, ii = lhHeight; i < ii; i++) {
- var k = i * lhWidth, l = (i * 2 + 1) * width;
- for (var j = 0, jj = lhWidth; j < jj; j++, k++, l += 2)
- items[l] = lhItems[k];
- }
- for (var i = 0, ii = hhHeight; i < ii; i++) {
- var k = i * hhWidth, l = (i * 2 + 1) * width + 1;
- for (var j = 0, jj = hhWidth; j < jj; j++, k++, l += 2)
- items[l] = hhItems[k];
- }
+ // The LL band is not needed anymore.
+ llItems = ll.items = null;
var bufferPadding = 4;
- var bufferLength = new Float32Array(Math.max(width, height) +
- 2 * bufferPadding);
- var buffer = new Float32Array(bufferLength);
- var bufferOut = new Float32Array(bufferLength);
+ var rowBuffer = new Float32Array(width + 2 * bufferPadding);
// Section F.3.4 HOR_SR
- for (var v = 0; v < height; v++) {
- if (width == 1) {
- // if width = 1, when u0 even keep items as is, when odd divide by 2
- if ((u0 % 1) !== 0) {
- items[v * width] /= 2;
+ 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;
}
- continue;
}
+ } else {
+ for (v = 0, k = 0; v < height; v++, k += width) {
+ rowBuffer.set(items.subarray(k, k + width), bufferPadding);
- var k = v * width;
- var l = bufferPadding;
- for (var u = 0; u < width; u++, k++, l++)
- buffer[l] = items[k];
+ this.extend(rowBuffer, bufferPadding, width);
+ this.filter(rowBuffer, bufferPadding, width);
- this.expand(buffer, bufferPadding, width);
- this.filter(buffer, bufferPadding, width, u0, bufferOut);
-
- k = v * width;
- l = bufferPadding;
- for (var u = 0; u < width; u++, k++, l++)
- items[k] = bufferOut[l];
+ 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
- for (var u = 0; u < width; u++) {
- if (height == 1) {
+ if (height === 1) {
// if height = 1, when v0 even keep items as is, when odd divide by 2
- if ((v0 % 1) !== 0) {
- items[u] /= 2;
+ if ((v0 & 1) !== 0) {
+ for (u = 0; u < width; u++) {
+ items[u] *= 0.5;
}
- continue;
}
+ } 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;
+ }
- var k = u;
- var l = bufferPadding;
- for (var v = 0; v < height; v++, k += width, l++)
- buffer[l] = items[k];
+ currentBuffer--;
+ var buffer = colBuffers[currentBuffer];
+ this.extend(buffer, bufferPadding, height);
+ this.filter(buffer, bufferPadding, height);
- this.expand(buffer, bufferPadding, height);
- this.filter(buffer, bufferPadding, height, v0, bufferOut);
-
- k = u;
- l = bufferPadding;
- for (var v = 0; v < height; v++, k += width, l++)
- items[k] = bufferOut[l];
+ // 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,
@@ -36881,10 +37335,10 @@ var JpxImage = (function JpxImageClosure() {
IrreversibleTransform.prototype = Object.create(Transform.prototype);
IrreversibleTransform.prototype.filter =
- function irreversibleTransformFilter(y, offset, length, i0, x) {
- var i0_ = Math.floor(i0 / 2);
- var i1_ = Math.floor((i0 + length) / 2);
- var offset_ = offset - (i0 % 1);
+ 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;
@@ -36893,35 +37347,75 @@ var JpxImage = (function JpxImageClosure() {
var K = 1.230174104914001;
var K_ = 1 / K;
- // step 1
- var j = offset_ - 2;
- for (var n = i0_ - 1, nn = i1_ + 2; n < nn; n++, j += 2)
- x[j] = K * y[j];
+ // step 1 is combined with step 3
// step 2
- var j = offset_ - 3;
- for (var n = i0_ - 2, nn = i1_ + 2; n < nn; n++, j += 2)
- x[j] = K_ * y[j];
+ j = offset - 3;
+ for (n = len + 4; n--; j += 2) {
+ x[j] *= K_;
+ }
- // step 3
- var j = offset_ - 2;
- for (var n = i0_ - 1, nn = i1_ + 2; n < nn; n++, j += 2)
- x[j] -= delta * (x[j - 1] + x[j + 1]);
+ // 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
- var j = offset_ - 1;
- for (var n = i0_ - 1, nn = i1_ + 1; n < nn; n++, j += 2)
- x[j] -= gamma * (x[j - 1] + x[j + 1]);
+ 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
- var j = offset_;
- for (var n = i0_, nn = i1_ + 1; n < nn; n++, j += 2)
- x[j] -= beta * (x[j - 1] + x[j + 1]);
+ 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
- var j = offset_ + 1;
- for (var n = i0_, nn = i1_; n < nn; n++, j += 2)
- x[j] -= alpha * (x[j - 1] + x[j + 1]);
+ 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;
@@ -36935,16 +37429,18 @@ var JpxImage = (function JpxImageClosure() {
ReversibleTransform.prototype = Object.create(Transform.prototype);
ReversibleTransform.prototype.filter =
- function reversibleTransformFilter(y, offset, length, i0, x) {
- var i0_ = Math.floor(i0 / 2);
- var i1_ = Math.floor((i0 + length) / 2);
- var offset_ = offset - (i0 % 1);
+ function reversibleTransformFilter(x, offset, length) {
+ var len = length >> 1;
+ offset = offset | 0;
+ var j, n;
- for (var n = i0_, nn = i1_ + 1, j = offset_; n < nn; n++, j += 2)
- x[j] = y[j] - Math.floor((y[j - 1] + y[j + 1] + 2) / 4);
+ for (j = offset, n = len + 1; n--; j += 2) {
+ x[j] -= (x[j - 1] + x[j + 1] + 2) >> 2;
+ }
- for (var n = i0_, nn = i1_, j = offset_ + 1; n < nn; n++, j += 2)
- x[j] = y[j] + Math.floor((x[j - 1] + x[j + 1]) / 2);
+ for (j = offset + 1, n = len; n--; j += 2) {
+ x[j] += (x[j - 1] + x[j + 1]) >> 1;
+ }
};
return ReversibleTransform;
@@ -36956,171 +37452,15 @@ var JpxImage = (function JpxImageClosure() {
var Jbig2Image = (function Jbig2ImageClosure() {
-
- // Annex E. Arithmetic Coding
- var ArithmeticDecoder = (function ArithmeticDecoderClosure() {
- 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}
- ];
-
- 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 = {
- 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;
- }
- },
- 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 nmpsIcx = qeTableIcx.nmps;
- var nlpsIcx = qeTableIcx.nlps;
- var switchIcx = qeTableIcx.switchFlag;
- var d;
- this.a -= qeIcx;
-
- if (this.chigh < qeIcx) {
- // exchangeLps
- if (this.a < qeIcx) {
- this.a = qeIcx;
- d = cx_mps;
- cx_index = nmpsIcx;
- } else {
- this.a = qeIcx;
- d = 1 - cx_mps;
- if (switchIcx) {
- cx_mps = d;
- }
- cx_index = nlpsIcx;
- }
- } else {
- this.chigh -= qeIcx;
- if ((this.a & 0x8000) !== 0) {
- return cx_mps;
- }
- // exchangeMps
- if (this.a < qeIcx) {
- d = 1 - cx_mps;
- if (switchIcx) {
- cx_mps = d;
- }
- cx_index = nlpsIcx;
- } else {
- d = cx_mps;
- cx_index = nmpsIcx;
- }
- }
- // renormD;
- do {
- if (this.ct === 0)
- this.byteIn();
-
- this.a <<= 1;
- this.chigh = ((this.chigh << 1) & 0xFFFF) | ((this.clow >> 15) & 1);
- this.clow = (this.clow << 1) & 0xFFFF;
- this.ct--;
- } while ((this.a & 0x8000) === 0);
-
- contexts[pos] = cx_index << 1 | cx_mps;
- return d;
- }
- };
-
- return ArithmeticDecoder;
- })();
-
// Utility data structures
function ContextCache() {}
ContextCache.prototype = {
getContexts: function(id) {
- if (id in this)
+ if (id in this) {
return this[id];
- return (this[id] = new Int8Array(1<<16));
+ }
+ return (this[id] = new Int8Array(1 << 16));
}
};
@@ -37145,58 +37485,32 @@ var Jbig2Image = (function Jbig2ImageClosure() {
// A.2 Procedure for decoding values
function decodeInteger(contextCache, procedure, decoder) {
var contexts = contextCache.getContexts(procedure);
-
var prev = 1;
- var state = 1, v = 0, s;
- var toRead = 32, offset = 4436; // defaults for state 7
- while (state) {
- var bit = decoder.readBit(contexts, prev);
- prev = prev < 256 ? (prev << 1) | bit :
- (((prev << 1) | bit) & 511) | 256;
- switch (state) {
- case 1:
- s = !!bit;
- break;
- case 2:
- if (bit) break;
- state = 7;
- toRead = 2;
- offset = 0;
- break;
- case 3:
- if (bit) break;
- state = 7;
- toRead = 4;
- offset = 4;
- break;
- case 4:
- if (bit) break;
- state = 7;
- toRead = 6;
- offset = 20;
- break;
- case 5:
- if (bit) break;
- state = 7;
- toRead = 8;
- offset = 84;
- break;
- case 6:
- if (bit) break;
- state = 7;
- toRead = 12;
- offset = 340;
- break;
- default:
- v = v * 2 + bit;
- if (--toRead === 0)
- state = 0;
- continue;
+
+ 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;
}
- state++;
+ return v >>> 0;
}
- v += offset;
- return !s ? v : v > 0 ? -v : null;
+
+ 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
@@ -37206,12 +37520,12 @@ var Jbig2Image = (function Jbig2ImageClosure() {
var prev = 1;
for (var i = 0; i < codeLength; i++) {
var bit = decoder.readBit(contexts, prev);
- prev = (prev * 2) + bit;
+ prev = (prev << 1) | bit;
}
- if (codeLength < 31)
+ if (codeLength < 31) {
return prev & ((1 << codeLength) - 1);
- else
- return prev - Math.pow(2, codeLength);
+ }
+ return prev & 0x7FFFFFFF;
}
// 7.3 Segment types
@@ -37258,11 +37572,12 @@ var Jbig2Image = (function Jbig2ImageClosure() {
}
];
+ // See 6.2.5.7 Decoding the bitmap.
var ReusedContexts = [
- 0x1CD3, // '00111001101' (template) + '0011' (at),
- 0x079A, // '001111001101' + '0',
- 0x00E3, // '001110001' + '1',
- 0x018B // '011000101' + '1'
+ 0x9B25, // 10011 0110010 0101
+ 0x0795, // 0011 110010 101
+ 0x00E5, // 001 11001 01
+ 0x0195 // 011001 0101
];
var RefinementReusedContexts = [
@@ -37270,79 +37585,162 @@ var Jbig2Image = (function Jbig2ImageClosure() {
0x0008 // '0000' + '001000'
];
- function log2(x) {
- var n = 1, i = 0;
- while (x > n) {
- n <<= 1;
- i++;
+ 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.
+ // If j + n is out of range at the right image border, then
+ // the undefined value of bitmap[i - 2][j + n] is shifted to 0
+ contextLabel = ((contextLabel & OLD_PIXEL_MASK) << 1) |
+ (row2[j + 3] << 11) | (row1[j + 4] << 4) | pixel;
+ }
}
- return i;
- }
- function readInt32(data, start) {
- return (data[start] << 24) | (data[start + 1] << 16) |
- (data[start + 2] << 8) | data[start + 3];
- }
-
- function readUint32(data, start) {
- var value = readInt32(data, start);
- return value & 0x80000000 ? (value + 4294967296) : value;
- }
-
- function readUint16(data, start) {
- return (data[start] << 8) | data[start + 1];
- }
-
- function readInt8(data, start) {
- return (data[start] << 24) >> 24;
+ return bitmap;
}
// 6.2 Generic Region Decoding Procedure
function decodeBitmap(mmr, width, height, templateIndex, prediction, skip, at,
decodingContext) {
- if (mmr)
+ 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 Int32Array(templateLength);
- var templateY = new Int32Array(templateLength);
- for (var k = 0; k < templateLength; k++) {
+ 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;
+ 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;
+ }
}
- if (ltp) {
- bitmap.push(bitmap[bitmap.length - 1]); // duplicate previous row
- continue;
- }
- var row = new Uint8Array(width);
+ row = new Uint8Array(row);
bitmap.push(row);
- for (var j = 0; j < width; j++) {
+ for (j = 0; j < width; j++) {
if (useskip && skip[i][j]) {
row[j] = 0;
continue;
}
- var contextLabel = 0;
- for (var k = 0; k < templateLength; k++) {
- var i0 = i + templateY[k], j0 = j + templateX[k];
- if (i0 < 0 || j0 < 0 || j0 >= width)
- contextLabel <<= 1; // out of bound pixel
- else
- contextLabel = (contextLabel << 1) | bitmap[i0][j0];
+ // 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;
@@ -37356,22 +37754,26 @@ var Jbig2Image = (function Jbig2ImageClosure() {
offsetX, offsetY, prediction, at,
decodingContext) {
var codingTemplate = RefinementTemplates[templateIndex].coding;
- if (templateIndex === 0)
+ if (templateIndex === 0) {
codingTemplate = codingTemplate.concat([at[0]]);
+ }
var codingTemplateLength = codingTemplate.length;
var codingTemplateX = new Int32Array(codingTemplateLength);
var codingTemplateY = new Int32Array(codingTemplateLength);
- for (var k = 0; k < codingTemplateLength; k++) {
+ 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)
+ if (templateIndex === 0) {
referenceTemplate = referenceTemplate.concat([at[1]]);
+ }
var referenceTemplateLength = referenceTemplate.length;
var referenceTemplateX = new Int32Array(referenceTemplateLength);
var referenceTemplateY = new Int32Array(referenceTemplateLength);
- for (var k = 0; k < referenceTemplateLength; k++) {
+ for (k = 0; k < referenceTemplateLength; k++) {
referenceTemplateX[k] = referenceTemplate[k].x;
referenceTemplateY[k] = referenceTemplate[k].y;
}
@@ -37389,28 +37791,33 @@ var Jbig2Image = (function Jbig2ImageClosure() {
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++) {
- if (ltp)
- error('JBIG2 error: prediction is not supported');
-
+ var i0, j0;
var contextLabel = 0;
- for (var k = 0; k < codingTemplateLength; k++) {
- var i0 = i + codingTemplateY[k], j0 = j + codingTemplateX[k];
- if (i0 < 0 || j0 < 0 || j0 >= width)
+ 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
+ } else {
contextLabel = (contextLabel << 1) | bitmap[i0][j0];
+ }
}
- for (var k = 0; k < referenceTemplateLength; k++) {
- var i0 = i + referenceTemplateY[k] + offsetY;
- var j0 = j + referenceTemplateX[k] + offsetX;
- if (i0 < 0 || i0 >= referenceHeight || j0 < 0 || j0 >= referenceWidth)
+ 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
+ } else {
contextLabel = (contextLabel << 1) | referenceBitmap[i0][j0];
+ }
}
var pixel = decoder.readBit(contexts, contextLabel);
row[j] = pixel;
@@ -37426,8 +37833,9 @@ var Jbig2Image = (function Jbig2ImageClosure() {
huffmanTables, templateIndex, at,
refinementTemplateIndex, refinementAt,
decodingContext) {
- if (huffman)
+ if (huffman) {
error('JBIG2 error: huffman is not supported');
+ }
var newSymbols = [];
var currentHeight = 0;
@@ -37443,24 +37851,38 @@ var Jbig2Image = (function Jbig2ImageClosure() {
var totalWidth = 0;
while (true) {
var deltaWidth = decodeInteger(contextCache, 'IADW', decoder); // 6.5.7
- if (deltaWidth === null)
+ 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)
- error('JBIG2 error: number of instances > 1 is not supported');
- 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,
+ 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,
@@ -37475,14 +37897,21 @@ var Jbig2Image = (function Jbig2ImageClosure() {
var totalSymbolsLength = symbols.length + numberOfNewSymbols;
while (flags.length < totalSymbolsLength) {
var runLength = decodeInteger(contextCache, 'IAEX', decoder);
- while (runLength--)
+ 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]);
+ 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;
}
@@ -37493,16 +37922,19 @@ var Jbig2Image = (function Jbig2ImageClosure() {
combinationOperator, huffmanTables,
refinementTemplateIndex, refinementAt,
decodingContext) {
- if (huffman)
+ if (huffman) {
error('JBIG2 error: huffman is not supported');
+ }
// Prepare bitmap
var bitmap = [];
- for (var i = 0; i < height; i++) {
- var row = new Uint8Array(width);
+ var i, row;
+ for (i = 0; i < height; i++) {
+ row = new Uint8Array(width);
if (defaultPixelValue) {
- for (var j = 0; j < width; j++)
+ for (var j = 0; j < width; j++) {
row[j] = defaultPixelValue;
+ }
}
bitmap.push(row);
}
@@ -37511,7 +37943,7 @@ var Jbig2Image = (function Jbig2ImageClosure() {
var contextCache = decodingContext.contextCache;
var stripT = -decodeInteger(contextCache, 'IADT', decoder); // 6.4.6
var firstS = 0;
- var i = 0;
+ i = 0;
while (i < numberOfSymbolInstances) {
var deltaT = decodeInteger(contextCache, 'IADT', decoder); // 6.4.6
stripT += deltaT;
@@ -37520,12 +37952,12 @@ var Jbig2Image = (function Jbig2ImageClosure() {
firstS += deltaFirstS;
var currentS = firstS;
do {
- var currentT = stripSize == 1 ? 0 :
- decodeInteger(contextCache, 'IAIT', decoder); // 6.4.9
+ 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 applyRefinement = (refinement &&
+ decodeInteger(contextCache, 'IARI', decoder));
var symbolBitmap = inputSymbols[symbolId];
var symbolWidth = symbolBitmap[0].length;
var symbolHeight = symbolBitmap.length;
@@ -37543,25 +37975,26 @@ var Jbig2Image = (function Jbig2ImageClosure() {
}
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 (var s2 = 0; s2 < symbolHeight; s2++) {
- var row = bitmap[offsetS + s2];
+ // Place Symbol Bitmap from T1,S1
+ for (s2 = 0; s2 < symbolHeight; s2++) {
+ row = bitmap[offsetS + s2];
if (!row) {
continue;
}
- var symbolRow = symbolBitmap[s2];
+ 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 (var t2 = 0; t2 < maxWidth; t2++) {
+ for (t2 = 0; t2 < maxWidth; t2++) {
row[offsetT + t2] |= symbolRow[t2];
}
break;
case 2: // XOR
- for (var t2 = 0; t2 < maxWidth; t2++) {
+ for (t2 = 0; t2 < maxWidth; t2++) {
row[offsetT + t2] ^= symbolRow[t2];
}
break;
@@ -37572,20 +38005,20 @@ var Jbig2Image = (function Jbig2ImageClosure() {
}
currentS += symbolHeight - 1;
} else {
- for (var t2 = 0; t2 < symbolHeight; t2++) {
- var row = bitmap[offsetT + t2];
+ for (t2 = 0; t2 < symbolHeight; t2++) {
+ row = bitmap[offsetT + t2];
if (!row) {
continue;
}
- var symbolRow = symbolBitmap[t2];
+ symbolRow = symbolBitmap[t2];
switch (combinationOperator) {
case 0: // OR
- for (var s2 = 0; s2 < symbolWidth; s2++) {
+ for (s2 = 0; s2 < symbolWidth; s2++) {
row[offsetS + s2] |= symbolRow[s2];
}
break;
case 2: // XOR
- for (var s2 = 0; s2 < symbolWidth; s2++) {
+ for (s2 = 0; s2 < symbolWidth; s2++) {
row[offsetS + s2] ^= symbolRow[s2];
}
break;
@@ -37598,8 +38031,9 @@ var Jbig2Image = (function Jbig2ImageClosure() {
}
i++;
var deltaS = decodeInteger(contextCache, 'IADS', decoder); // 6.4.8
- if (deltaS === null)
+ if (deltaS === null) {
break; // OOB
+ }
currentS += deltaS + dsOffset;
} while (true);
}
@@ -37611,47 +38045,53 @@ var Jbig2Image = (function Jbig2ImageClosure() {
segmentHeader.number = readUint32(data, start);
var flags = data[start + 4];
var segmentType = flags & 0x3F;
- if (!SegmentTypes[segmentType])
+ 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 = readInt32(data, position - 1) & 0x1FFFFFFF;
+ 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)
+ } 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 referredToSegmentNumberSize = (segmentHeader.number <= 256 ? 1 :
+ (segmentHeader.number <= 65536 ? 2 : 4));
var referredTo = [];
- for (var i = 0; i < referredToCount; i++) {
- var number = referredToSegmentNumberSize == 1 ? data[position] :
- referredToSegmentNumberSize == 2 ? readUint16(data, position) :
- readUint32(data, position);
+ 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)
+ if (!pageAssociationFieldSize) {
segmentHeader.pageAssociation = data[position++];
- else {
+ } else {
segmentHeader.pageAssociation = readUint32(data, position);
position += 4;
}
segmentHeader.length = readUint32(data, position);
position += 4;
- if (segmentHeader.length == 0xFFFFFFFF) {
+
+ if (segmentHeader.length === 0xFFFFFFFF) {
// 7.2.7 Segment data length, unknown segment length
if (segmentType === 38) { // ImmediateGenericRegion
var genericRegionInfo = readRegionSegmentInformation(data, position);
@@ -37669,17 +38109,17 @@ var Jbig2Image = (function Jbig2ImageClosure() {
searchPattern[3] = (genericRegionInfo.height >> 16) & 0xFF;
searchPattern[4] = (genericRegionInfo.height >> 8) & 0xFF;
searchPattern[5] = genericRegionInfo.height & 0xFF;
- for (var i = position, ii = data.length; i < ii; i++) {
+ for (i = position, ii = data.length; i < ii; i++) {
var j = 0;
while (j < searchPatternLength && searchPattern[j] === data[i + j]) {
j++;
}
- if (j == searchPatternLength) {
+ if (j === searchPatternLength) {
segmentHeader.length = i + searchPatternLength;
break;
}
}
- if (segmentHeader.length == 0xFFFFFFFF) {
+ if (segmentHeader.length === 0xFFFFFFFF) {
error('JBIG2 error: segment end was not found');
}
} else {
@@ -37706,8 +38146,9 @@ var Jbig2Image = (function Jbig2ImageClosure() {
segment.end = position;
}
segments.push(segment);
- if (segmentHeader.type == 51)
+ if (segmentHeader.type === 51) {
break; // end of file is found
+ }
}
if (header.randomAccess) {
for (var i = 0, ii = segments.length; i < ii; i++) {
@@ -37735,7 +38176,7 @@ var Jbig2Image = (function Jbig2ImageClosure() {
var header = segment.header;
var data = segment.data, position = segment.start, end = segment.end;
- var args;
+ var args, at, i, atLength;
switch (header.type) {
case 0: // SymbolDictionary
// 7.4.2 Symbol dictionary segment syntax
@@ -37753,9 +38194,9 @@ var Jbig2Image = (function Jbig2ImageClosure() {
dictionary.refinementTemplate = (dictionaryFlags >> 12) & 1;
position += 2;
if (!dictionary.huffman) {
- var atLength = dictionary.template === 0 ? 4 : 1;
- var at = [];
- for (var i = 0; i < atLength; i++) {
+ atLength = dictionary.template === 0 ? 4 : 1;
+ at = [];
+ for (i = 0; i < atLength; i++) {
at.push({
x: readInt8(data, position),
y: readInt8(data, position + 1)
@@ -37765,8 +38206,8 @@ var Jbig2Image = (function Jbig2ImageClosure() {
dictionary.at = at;
}
if (dictionary.refinement && !dictionary.refinementTemplate) {
- var at = [];
- for (var i = 0; i < 2; i++) {
+ at = [];
+ for (i = 0; i < 2; i++) {
at.push({
x: readInt8(data, position),
y: readInt8(data, position + 1)
@@ -37812,8 +38253,8 @@ var Jbig2Image = (function Jbig2ImageClosure() {
!!(textRegionHuffmanFlags & 14);
}
if (textRegion.refinement && !textRegion.refinementTemplate) {
- var at = [];
- for (var i = 0; i < 2; i++) {
+ at = [];
+ for (i = 0; i < 2; i++) {
at.push({
x: readInt8(data, position),
y: readInt8(data, position + 1)
@@ -37825,8 +38266,9 @@ var Jbig2Image = (function Jbig2ImageClosure() {
textRegion.numberOfSymbolInstances = readUint32(data, position);
position += 4;
// TODO 7.4.3.1.7 Symbol ID Huffman table decoding
- if (textRegion.huffman)
+ if (textRegion.huffman) {
error('JBIG2 error: huffman is not supported');
+ }
args = [textRegion, header.referredTo, data, position, end];
break;
case 38: // ImmediateGenericRegion
@@ -37839,9 +38281,9 @@ var Jbig2Image = (function Jbig2ImageClosure() {
genericRegion.template = (genericRegionSegmentFlags >> 1) & 3;
genericRegion.prediction = !!(genericRegionSegmentFlags & 8);
if (!genericRegion.mmr) {
- var atLength = genericRegion.template === 0 ? 4 : 1;
- var at = [];
- for (var i = 0; i < atLength; i++) {
+ atLength = genericRegion.template === 0 ? 4 : 1;
+ at = [];
+ for (i = 0; i < atLength; i++) {
at.push({
x: readInt8(data, position),
y: readInt8(data, position + 1)
@@ -37859,8 +38301,9 @@ var Jbig2Image = (function Jbig2ImageClosure() {
resolutionX: readUint32(data, position + 8),
resolutionY: readUint32(data, position + 12)
};
- if (pageInfo.height == 0xFFFFFFFF)
+ if (pageInfo.height === 0xFFFFFFFF) {
delete pageInfo.height;
+ }
var pageSegmentFlags = data[position + 16];
var pageStripingInformatiom = readUint16(data, position + 17);
pageInfo.lossless = !!(pageSegmentFlags & 1);
@@ -37885,22 +38328,25 @@ var Jbig2Image = (function Jbig2ImageClosure() {
header.type + ') is not implemented');
}
var callbackName = 'on' + header.typeName;
- if (callbackName in visitor)
+ if (callbackName in visitor) {
visitor[callbackName].apply(visitor, args);
+ }
}
function processSegments(segments, visitor) {
- for (var i = 0, ii = segments.length; i < ii; i++)
+ 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)
+ 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++];
@@ -37931,9 +38377,13 @@ var Jbig2Image = (function Jbig2ImageClosure() {
this.currentPageInfo = info;
var rowSize = (info.width + 7) >> 3;
var buffer = new Uint8Array(rowSize * info.height);
- var fill = info.defaultPixelValue ? 0xFF : 0;
- for (var i = 0, ii = buffer.length; i < ii; i++)
- buffer[i] = fill;
+ // 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) {
@@ -37943,34 +38393,47 @@ var Jbig2Image = (function Jbig2ImageClosure() {
var combinationOperator = pageInfo.combinationOperatorOverride ?
regionInfo.combinationOperator : pageInfo.combinationOperator;
var buffer = this.buffer;
- for (var i = 0; i < height; i++) {
- var mask = 128 >> (regionInfo.x & 7);
- var offset = (i + regionInfo.y) * rowSize + (regionInfo.x >> 3);
- switch (combinationOperator) {
- case 0: // OR
- for (var j = 0; j < width; j++) {
- buffer[offset] |= bitmap[i][j] ? mask : 0;
+ 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++;
}
}
- break;
- case 2: // XOR
- for (var j = 0; j < width; j++) {
- buffer[offset] ^= bitmap[i][j] ? mask : 0;
+ 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++;
}
}
- break;
- default:
- error('JBIG2 error: operator ' + combinationOperator +
- ' is not supported');
- }
+ offset0 += rowSize;
+ }
+ break;
+ default:
+ error('JBIG2 error: operator ' + combinationOperator +
+ ' is not supported');
}
},
onImmediateGenericRegion:
@@ -37993,17 +38456,20 @@ var Jbig2Image = (function Jbig2ImageClosure() {
referredSegments,
data, start, end) {
var huffmanTables;
- if (dictionary.huffman)
+ if (dictionary.huffman) {
error('JBIG2 error: huffman is not supported');
+ }
// Combines exported symbols from all referred segments
var symbols = this.symbols;
- if (!symbols)
+ if (!symbols) {
this.symbols = symbols = {};
+ }
var inputSymbols = [];
- for (var i = 0, ii = referredSegments.length; i < ii; i++)
+ 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,
@@ -38023,8 +38489,9 @@ var Jbig2Image = (function Jbig2ImageClosure() {
// Combines exported symbols from all referred segments
var symbols = this.symbols;
var inputSymbols = [];
- for (var i = 0, ii = referredSegments.length; i < ii; i++)
+ 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);
@@ -38038,7 +38505,7 @@ var Jbig2Image = (function Jbig2ImageClosure() {
},
onImmediateLosslessTextRegion:
function SimpleSegmentVisitor_onImmediateLosslessTextRegion() {
- this.onImmediateTextRegion.apply(this, arguments);
+ this.onImmediateTextRegion.apply(this, arguments);
}
};
@@ -38113,10 +38580,10 @@ var bidi = PDFJS.bidi = (function bidiClosure() {
}
function findUnequal(arr, start, value) {
- var j;
for (var j = start, jj = arr.length; j < jj; ++j) {
- if (arr[j] != value)
+ if (arr[j] !== value) {
return j;
+ }
}
return j;
}
@@ -38135,94 +38602,61 @@ var bidi = PDFJS.bidi = (function bidiClosure() {
}
}
- function mirrorGlyphs(c) {
- /*
- # BidiMirroring-1.txt
- 0028; 0029 # LEFT PARENTHESIS
- 0029; 0028 # RIGHT PARENTHESIS
- 003C; 003E # LESS-THAN SIGN
- 003E; 003C # GREATER-THAN SIGN
- 005B; 005D # LEFT SQUARE BRACKET
- 005D; 005B # RIGHT SQUARE BRACKET
- 007B; 007D # LEFT CURLY BRACKET
- 007D; 007B # RIGHT CURLY BRACKET
- 00AB; 00BB # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
- 00BB; 00AB # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
- */
- switch (c) {
- case '(':
- return ')';
- case ')':
- return '(';
- case '<':
- return '>';
- case '>':
- return '<';
- case ']':
- return '[';
- case '[':
- return ']';
- case '}':
- return '{';
- case '{':
- return '}';
- case '\u00AB':
- return '\u00BB';
- case '\u00BB':
- return '\u00AB';
- default:
- return c;
- }
+ function createBidiText(str, isLTR, vertical) {
+ return {
+ str: str,
+ dir: (vertical ? 'ttb' : (isLTR ? 'ltr' : 'rtl'))
+ };
}
- function BidiResult(str, isLTR, vertical) {
- this.str = str;
- this.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 new BidiResult(str, isLTR, vertical);
+ if (strLength === 0 || vertical) {
+ return createBidiText(str, isLTR, vertical);
+ }
- // get types, fill arrays
-
- var chars = [];
- var types = [];
- var oldtypes = [];
+ // Get types and fill arrays
+ chars.length = strLength;
+ types.length = strLength;
var numBidi = 0;
- for (var i = 0; i < strLength; ++i) {
+ 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)
+ if (charCode <= 0x00ff) {
charType = baseTypes[charCode];
- else if (0x0590 <= charCode && charCode <= 0x05f4)
+ } else if (0x0590 <= charCode && charCode <= 0x05f4) {
charType = 'R';
- else if (0x0600 <= charCode && charCode <= 0x06ff)
+ } else if (0x0600 <= charCode && charCode <= 0x06ff) {
charType = arabicTypes[charCode & 0xff];
- else if (0x0700 <= charCode && charCode <= 0x08AC)
+ } else if (0x0700 <= charCode && charCode <= 0x08AC) {
charType = 'AL';
-
- if (charType == 'R' || charType == 'AL' || charType == 'AN')
+ }
+ if (charType === 'R' || charType === 'AL' || charType === 'AN') {
numBidi++;
-
- oldtypes[i] = types[i] = charType;
+ }
+ 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
+ // 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 new BidiResult(str, isLTR);
+ return createBidiText(str, isLTR);
}
- if (startLevel == -1) {
+ if (startLevel === -1) {
if ((strLength / numBidi) < 0.3) {
isLTR = true;
startLevel = 0;
@@ -38233,16 +38667,14 @@ var bidi = PDFJS.bidi = (function bidiClosure() {
}
var levels = [];
-
- for (var i = 0; i < strLength; ++i) {
+ 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 e = (isOdd(startLevel) ? 'R' : 'L');
var sor = e;
var eor = sor;
@@ -38251,13 +38683,13 @@ var bidi = PDFJS.bidi = (function bidiClosure() {
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 (var i = 0; i < strLength; ++i) {
- if (types[i] == 'NSM')
+ for (i = 0; i < strLength; ++i) {
+ if (types[i] === 'NSM') {
types[i] = lastType;
- else
+ } else {
lastType = types[i];
+ }
}
/*
@@ -38265,24 +38697,25 @@ var bidi = PDFJS.bidi = (function bidiClosure() {
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.
*/
-
- var lastType = sor;
- for (var i = 0; i < strLength; ++i) {
- var t = types[i];
- if (t == 'EN')
- types[i] = (lastType == 'AL') ? 'AN' : 'EN';
- else if (t == 'R' || t == 'L' || t == 'AL')
+ 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 (var i = 0; i < strLength; ++i) {
- var t = types[i];
- if (t == 'AL')
+ for (i = 0; i < strLength; ++i) {
+ t = types[i];
+ if (t === 'AL') {
types[i] = 'R';
+ }
}
/*
@@ -38290,32 +38723,36 @@ var bidi = PDFJS.bidi = (function bidiClosure() {
European number. A single common separator between two numbers of the same
type changes to that type:
*/
-
- for (var i = 1; i < strLength - 1; ++i) {
- if (types[i] == 'ES' && types[i - 1] == 'EN' && types[i + 1] == 'EN')
+ 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])
+ }
+ 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 (var i = 0; i < strLength; ++i) {
- if (types[i] == 'EN') {
+ for (i = 0; i < strLength; ++i) {
+ if (types[i] === 'EN') {
// do before
- for (var j = i - 1; j >= 0; --j) {
- if (types[j] != 'ET')
+ var j;
+ for (j = i - 1; j >= 0; --j) {
+ if (types[j] !== 'ET') {
break;
+ }
types[j] = 'EN';
}
// do after
- for (var j = i + 1; j < strLength; --j) {
- if (types[j] != 'ET')
+ for (j = i + 1; j < strLength; --j) {
+ if (types[j] !== 'ET') {
break;
+ }
types[j] = 'EN';
}
}
@@ -38324,11 +38761,11 @@ var bidi = PDFJS.bidi = (function bidiClosure() {
/*
W6. Otherwise, separators and terminators change to Other Neutral:
*/
-
- for (var i = 0; i < strLength; ++i) {
- var t = types[i];
- if (t == 'WS' || t == 'ES' || t == 'ET' || t == 'CS')
+ for (i = 0; i < strLength; ++i) {
+ t = types[i];
+ if (t === 'WS' || t === 'ES' || t === 'ET' || t === 'CS') {
types[i] = 'ON';
+ }
}
/*
@@ -38336,14 +38773,14 @@ var bidi = PDFJS.bidi = (function bidiClosure() {
first strong type (R, L, or sor) is found. If an L is found, then change
the type of the European number to L.
*/
-
- var lastType = sor;
- for (var i = 0; i < strLength; ++i) {
- var t = types[i];
- if (t == 'EN')
- types[i] = (lastType == 'L') ? 'L' : 'EN';
- else if (t == 'R' || t == '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;
+ }
}
/*
@@ -38352,22 +38789,27 @@ var bidi = PDFJS.bidi = (function bidiClosure() {
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 (var i = 0; i < strLength; ++i) {
- if (types[i] == 'ON') {
+ for (i = 0; i < strLength; ++i) {
+ if (types[i] === 'ON') {
var end = findUnequal(types, i + 1, 'ON');
var before = sor;
- if (i > 0)
+ if (i > 0) {
before = types[i - 1];
+ }
+
var after = eor;
- if (end + 1 < strLength)
+ if (end + 1 < strLength) {
after = types[end + 1];
- if (before != 'L')
+ }
+ if (before !== 'L') {
before = 'R';
- if (after != 'L')
+ }
+ if (after !== 'L') {
after = 'R';
- if (before == after)
+ }
+ if (before === after) {
setValues(types, i, end, before);
+ }
i = end - 1; // reset to end (-1 so next iteration is ok)
}
}
@@ -38375,10 +38817,10 @@ var bidi = PDFJS.bidi = (function bidiClosure() {
/*
N2. Any remaining neutrals take the embedding direction.
*/
-
- for (var i = 0; i < strLength; ++i) {
- if (types[i] == 'ON')
+ for (i = 0; i < strLength; ++i) {
+ if (types[i] === 'ON') {
types[i] = e;
+ }
}
/*
@@ -38388,17 +38830,16 @@ var bidi = PDFJS.bidi = (function bidiClosure() {
I2. For all characters with an odd (right-to-left) embedding direction,
those of type L, EN or AN go up one level.
*/
-
- for (var i = 0; i < strLength; ++i) {
- var t = types[i];
+ for (i = 0; i < strLength; ++i) {
+ t = types[i];
if (isEven(levels[i])) {
- if (t == 'R') {
+ if (t === 'R') {
levels[i] += 1;
- } else if (t == 'AN' || t == 'EN') {
+ } else if (t === 'AN' || t === 'EN') {
levels[i] += 2;
}
- } else { // isOdd, so
- if (t == 'L' || t == 'AN' || t == 'EN') {
+ } else { // isOdd
+ if (t === 'L' || t === 'AN' || t === 'EN') {
levels[i] += 1;
}
}
@@ -38424,23 +38865,24 @@ var bidi = PDFJS.bidi = (function bidiClosure() {
*/
// find highest level & lowest odd level
-
var highestLevel = -1;
var lowestOddLevel = 99;
- for (var i = 0, ii = levels.length; i < ii; ++i) {
- var level = levels[i];
- if (highestLevel < level)
+ var level;
+ for (i = 0, ii = levels.length; i < ii; ++i) {
+ level = levels[i];
+ if (highestLevel < level) {
highestLevel = level;
- if (lowestOddLevel > level && isOdd(level))
+ }
+ if (lowestOddLevel > level && isOdd(level)) {
lowestOddLevel = level;
+ }
}
// now reverse between those limits
-
- for (var level = highestLevel; level >= lowestOddLevel; --level) {
+ for (level = highestLevel; level >= lowestOddLevel; --level) {
// find segments to reverse
var start = -1;
- for (var i = 0, ii = levels.length; i < ii; ++i) {
+ for (i = 0, ii = levels.length; i < ii; ++i) {
if (levels[i] < level) {
if (start >= 0) {
reverseValues(chars, start, i);
@@ -38473,1414 +38915,185 @@ var bidi = PDFJS.bidi = (function bidiClosure() {
// don't mirror as characters are already mirrored in the pdf
// Finally, return string
-
var result = '';
- for (var i = 0, ii = chars.length; i < ii; ++i) {
+ for (i = 0, ii = chars.length; i < ii; ++i) {
var ch = chars[i];
- if (ch != '<' && ch != '>')
+ if (ch !== '<' && ch !== '>') {
result += ch;
+ }
}
-
- return new BidiResult(result, isLTR);
+ return createBidiText(result, isLTR);
}
return bidi;
})();
-
-var CMAP_CODESPACES = {
- 'Adobe-CNS1-0': [[], [0, 14335]],
- 'Adobe-CNS1-1': [[], [0, 17407]],
- 'Adobe-CNS1-2': [[], [0, 17663]],
- 'Adobe-CNS1-3': [[], [0, 18943]],
- 'Adobe-CNS1-4': [[], [0, 19199]],
- 'Adobe-CNS1-5': [[], [0, 19199]],
- 'Adobe-CNS1-6': [[], [0, 19199]],
- 'Adobe-CNS1-UCS2': [[], [0, 65535]],
- 'B5-H': [[0, 128], [41280, 65278]],
- 'B5-V': [[0, 128], [41280, 65278]],
- 'B5pc-H': [[0, 128, 253, 255], [41280, 64766]],
- 'B5pc-V': [[0, 128, 253, 255], [41280, 64766]],
- 'CNS-EUC-H': [[0, 128], [41377, 65278], [],
- [2392957345, 2392981246, 2393022881, 2393046782, 2393088417, 2393112318]],
- 'CNS-EUC-V': [[0, 128], [41377, 65278], [],
- [2392957345, 2392981246, 2393022881, 2393046782, 2393088417, 2393112318]],
- 'CNS1-H': [[], [8481, 32382]],
- 'CNS1-V': [[], [8481, 32382]],
- 'CNS2-H': [[], [8481, 32382]],
- 'CNS2-V': [[], [8481, 32382]],
- 'ETen-B5-H': [[0, 128], [41280, 65278]],
- 'ETen-B5-V': [[0, 128], [41280, 65278]],
- 'ETenms-B5-H': [[0, 128], [41280, 65278]],
- 'ETenms-B5-V': [[0, 128], [41280, 65278]],
- 'ETHK-B5-H': [[0, 128], [34624, 65278]],
- 'ETHK-B5-V': [[0, 128], [34624, 65278]],
- 'HKdla-B5-H': [[0, 128], [41280, 65278]],
- 'HKdla-B5-V': [[0, 128], [41280, 65278]],
- 'HKdlb-B5-H': [[0, 128], [36416, 65278]],
- 'HKdlb-B5-V': [[0, 128], [36416, 65278]],
- 'HKgccs-B5-H': [[0, 128], [35392, 65278]],
- 'HKgccs-B5-V': [[0, 128], [35392, 65278]],
- 'HKm314-B5-H': [[0, 128], [41280, 65278]],
- 'HKm314-B5-V': [[0, 128], [41280, 65278]],
- 'HKm471-B5-H': [[0, 128], [41280, 65278]],
- 'HKm471-B5-V': [[0, 128], [41280, 65278]],
- 'HKscs-B5-H': [[0, 128], [34624, 65278]],
- 'HKscs-B5-V': [[0, 128], [34624, 65278]],
- 'UniCNS-UCS2-H': [[], [0, 55295, 57344, 65535]],
- 'UniCNS-UCS2-V': [[], [0, 55295, 57344, 65535]],
- 'UniCNS-UTF16-H': [[], [0, 55295, 57344, 65535], [],
- [3623934976, 3690979327]],
- 'UniCNS-UTF16-V': [[], [0, 55295, 57344, 65535], [],
- [3623934976, 3690979327]],
- 'Adobe-GB1-0': [[], [0, 7935]],
- 'Adobe-GB1-1': [[], [0, 9983]],
- 'Adobe-GB1-2': [[], [0, 22271]],
- 'Adobe-GB1-3': [[], [0, 22527]],
- 'Adobe-GB1-4': [[], [0, 29183]],
- 'Adobe-GB1-5': [[], [0, 30463]],
- 'Adobe-GB1-UCS2': [[], [0, 65535]],
- 'GB-EUC-H': [[0, 128], [41377, 65278]],
- 'GB-EUC-V': [[0, 128], [41377, 65278]],
- 'GB-H': [[], [8481, 32382]],
- 'GB-V': [[], [8481, 32382]],
- 'GBK-EUC-H': [[0, 128], [33088, 65278]],
- 'GBK-EUC-V': [[0, 128], [33088, 65278]],
- 'GBK2K-H': [[0, 127], [33088, 65278], [], [2167439664, 4265213497]],
- 'GBK2K-V': [[0, 127], [33088, 65278], [], [2167439664, 4265213497]],
- 'GBKp-EUC-H': [[0, 128], [33088, 65278]],
- 'GBKp-EUC-V': [[0, 128], [33088, 65278]],
- 'GBpc-EUC-H': [[0, 128, 253, 255], [41377, 64766]],
- 'GBpc-EUC-V': [[0, 128, 253, 255], [41377, 64766]],
- 'GBT-EUC-H': [[0, 128], [41377, 65278]],
- 'GBT-EUC-V': [[0, 128], [41377, 65278]],
- 'GBT-H': [[], [8481, 32382]],
- 'GBT-V': [[], [8481, 32382]],
- 'GBTpc-EUC-H': [[0, 128, 253, 255], [41377, 64766]],
- 'GBTpc-EUC-V': [[0, 128, 253, 255], [41377, 64766]],
- 'UniGB-UCS2-H': [[], [0, 55295, 57344, 65535]],
- 'UniGB-UCS2-V': [[], [0, 55295, 57344, 65535]],
- 'UniGB-UTF16-H': [[], [0, 55295, 57344, 65535], [], [3623934976, 3690979327]],
- 'UniGB-UTF16-V': [[], [0, 55295, 57344, 65535], [], [3623934976, 3690979327]],
- '78-EUC-H': [[0, 128], [36512, 36575, 41377, 65278]],
- '78-EUC-V': [[0, 128], [36512, 36575, 41377, 65278]],
- '78-H': [[], [8481, 32382]],
- '78-RKSJ-H': [[0, 128, 160, 223], [33088, 40956, 57408, 64764]],
- '78-RKSJ-V': [[0, 128, 160, 223], [33088, 40956, 57408, 64764]],
- '78-V': [[], [8481, 32382]],
- '78ms-RKSJ-H': [[0, 128, 160, 223], [33088, 40956, 57408, 64764]],
- '78ms-RKSJ-V': [[0, 128, 160, 223], [33088, 40956, 57408, 64764]],
- '83pv-RKSJ-H': [[0, 128, 160, 223, 253, 255], [33088, 40956, 57408, 64764]],
- '90ms-RKSJ-H': [[0, 128, 160, 223], [33088, 40956, 57408, 64764]],
- '90ms-RKSJ-V': [[0, 128, 160, 223], [33088, 40956, 57408, 64764]],
- '90msp-RKSJ-H': [[0, 128, 160, 223], [33088, 40956, 57408, 64764]],
- '90msp-RKSJ-V': [[0, 128, 160, 223], [33088, 40956, 57408, 64764]],
- '90pv-RKSJ-H': [[0, 128, 160, 223, 253, 255], [33088, 40956, 57408, 64764]],
- '90pv-RKSJ-V': [[0, 128, 160, 223, 253, 255], [33088, 40956, 57408, 64764]],
- 'Add-H': [[], [8481, 32382]],
- 'Add-RKSJ-H': [[0, 128, 160, 223], [33088, 40956, 57408, 64764]],
- 'Add-RKSJ-V': [[0, 128, 160, 223], [33088, 40956, 57408, 64764]],
- 'Add-V': [[], [8481, 32382]],
- 'Adobe-Japan1-0': [[], [0, 8447]],
- 'Adobe-Japan1-1': [[], [0, 8447]],
- 'Adobe-Japan1-2': [[], [0, 8959]],
- 'Adobe-Japan1-3': [[], [0, 9471]],
- 'Adobe-Japan1-4': [[], [0, 15615]],
- 'Adobe-Japan1-5': [[], [0, 20479]],
- 'Adobe-Japan1-6': [[], [0, 23295]],
- 'Adobe-Japan1-UCS2': [[], [0, 65535]],
- 'Adobe-Japan2-0': [[], [0, 6143]],
- 'EUC-H': [[0, 128], [36512, 36575, 41377, 65278]],
- 'EUC-V': [[0, 128], [36512, 36575, 41377, 65278]],
- 'Ext-H': [[], [8481, 32382]],
- 'Ext-RKSJ-H': [[0, 128, 160, 223], [33088, 40956, 57408, 64764]],
- 'Ext-RKSJ-V': [[0, 128, 160, 223], [33088, 40956, 57408, 64764]],
- 'Ext-V': [[], [8481, 32382]],
- 'H': [[], [8481, 32382]],
- 'Hankaku': [[0, 255], []],
- 'Hiragana': [[0, 255], []],
- 'Hojo-EUC-H': [[], [], [9413025, 9436926], []],
- 'Hojo-EUC-V': [[], [], [9413025, 9436926], []],
- 'Hojo-H': [[], [8481, 32382]],
- 'Hojo-V': [[], [8481, 32382]],
- 'Katakana': [[0, 255], []],
- 'NWP-H': [[], [8481, 32382]],
- 'NWP-V': [[], [8481, 32382]],
- 'RKSJ-H': [[0, 128, 160, 223], [33088, 40956, 57408, 64764]],
- 'RKSJ-V': [[0, 128, 160, 223], [33088, 40956, 57408, 64764]],
- 'Roman': [[0, 255], []],
- 'UniHojo-UCS2-H': [[], [0, 55295, 57344, 65535]],
- 'UniHojo-UCS2-V': [[], [0, 55295, 57344, 65535]],
- 'UniHojo-UTF16-H': [[], [0, 55295, 57344, 65535], [],
- [3623934976, 3690979327]],
- 'UniHojo-UTF16-V': [[], [0, 55295, 57344, 65535], [],
- [3623934976, 3690979327]],
- 'UniJIS-UCS2-H': [[], [0, 55295, 57344, 65535]],
- 'UniJIS-UCS2-HW-H': [[], [0, 55295, 57344, 65535]],
- 'UniJIS-UCS2-HW-V': [[], [0, 55295, 57344, 65535]],
- 'UniJIS-UCS2-V': [[], [0, 55295, 57344, 65535]],
- 'UniJIS-UTF16-H': [[], [0, 55295, 57344, 65535], [],
- [3623934976, 3690979327]],
- 'UniJIS-UTF16-V': [[], [0, 55295, 57344, 65535], [],
- [3623934976, 3690979327]],
- 'UniJISPro-UCS2-HW-V': [[], [0, 55295, 57344, 65535]],
- 'UniJISPro-UCS2-V': [[], [0, 55295, 57344, 65535]],
- 'V': [[], [8481, 32382]],
- 'WP-Symbol': [[0, 255], []],
- 'Adobe-Korea1-0': [[], [0, 9471]],
- 'Adobe-Korea1-1': [[], [0, 18175]],
- 'Adobe-Korea1-2': [[], [0, 18431]],
- 'Adobe-Korea1-UCS2': [[], [0, 65535]],
- 'KSC-EUC-H': [[0, 128], [41377, 65278]],
- 'KSC-EUC-V': [[0, 128], [41377, 65278]],
- 'KSC-H': [[], [8481, 32382]],
- 'KSC-Johab-H': [[0, 128], [33857, 54270, 55345, 57086, 57393, 63998]],
- 'KSC-Johab-V': [[0, 128], [33857, 54270, 55345, 57086, 57393, 63998]],
- 'KSC-V': [[], [8481, 32382]],
- 'KSCms-UHC-H': [[0, 128], [33089, 65278]],
- 'KSCms-UHC-HW-H': [[0, 128], [33089, 65278]],
- 'KSCms-UHC-HW-V': [[0, 128], [33089, 65278]],
- 'KSCms-UHC-V': [[0, 128], [33089, 65278]],
- 'KSCpc-EUC-H': [[0, 132, 254, 255], [41281, 65022]],
- 'KSCpc-EUC-V': [[0, 132, 254, 255], [41281, 65022]],
- 'UniKS-UCS2-H': [[], [0, 55295, 57344, 65535]],
- 'UniKS-UCS2-V': [[], [0, 55295, 57344, 65535]],
- 'UniKS-UTF16-H': [[], [0, 55295, 57344, 65535], [], [3623934976, 3690979327]],
- 'UniKS-UTF16-V': [[], [0, 55295, 57344, 65535], [], [3623934976, 3690979327]]
-};
-
-// CMap, not to be confused with TrueType's cmap.
-var CMap = (function CMapClosure() {
- function CMap() {
- // Codespace ranges are stored as follows:
- // [[1BytePairs], [2BytePairs], [3BytePairs], [4BytePairs]]
- // where nBytePairs are ranges e.g. [low1, high1, low2, high2, ...]
- this.codespaceRanges = [[], [], [], []];
- this.map = [];
- this.vertical = false;
- }
- CMap.prototype = {
- addCodespaceRange: function(n, low, high) {
- this.codespaceRanges[n - 1].push(low, high);
- },
-
- mapRange: 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);
- ++low;
- }
- },
-
- mapRangeToArray: function(low, high, array) {
- var i = 0;
- while (low <= high) {
- this.map[low] = array[i++];
- ++low;
- }
- },
-
- mapOne: function(src, dst) {
- this.map[src] = dst;
- },
-
- lookup: function(code) {
- return this.map[code];
- },
-
- readCharCode: function(str, offset) {
- 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) {
- return [c, n + 1];
- }
- }
- }
-
- return [0, 1];
- }
-
- };
- return CMap;
-})();
-
-var IdentityCMap = (function IdentityCMapClosure() {
- function IdentityCMap(vertical, n) {
- CMap.call(this);
- this.vertical = vertical;
- this.addCodespaceRange(n, 0, 0xffff);
- this.mapRange(0, 0xffff, '\u0000');
- }
- Util.inherit(IdentityCMap, CMap, {});
-
- return IdentityCMap;
-})();
-
-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.mapRange(low, high, dstLow);
- } else if (isCmd(obj, '[')) {
- obj = lexer.getObj();
- var array = [];
- while (!isCmd(obj, ']') && !isEOF(obj)) {
- array.push(obj);
- obj = lexer.getObj();
- }
- cMap.mapRangeToArray(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 = String.fromCharCode(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 = String.fromCharCode(obj);
- cMap.mapRange(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 parseCmap(cMap, lexer) {
- objLoop: while (true) {
- var obj = lexer.getObj();
- if (isEOF(obj)) {
- break;
- } else if (isCmd(obj)) {
- switch (obj.cmd) {
- case 'endcMap':
- break objLoop;
- case 'usecMap':
- // TODO
- 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;
- }
- }
- }
- }
- return {
- create: function (encoding) {
- if (isName(encoding)) {
- switch (encoding.name) {
- case 'Identity-H':
- return new IdentityCMap(false, 2);
- case 'Identity-V':
- return new IdentityCMap(true, 2);
- default:
- if (encoding.name in CMAP_CODESPACES) {
- // XXX: Temporary hack so the correct amount of bytes are read in
- // CMap.readCharCode.
- var cMap = new CMap();
- cMap.codespaceRanges = CMAP_CODESPACES[encoding.name];
- return cMap;
- }
- return null;
- }
- } else if (isStream(encoding)) {
- var cMap = new CMap();
- var lexer = new Lexer(encoding);
- try {
- parseCmap(cMap, lexer);
- } catch (e) {
- warn('Invalid CMap data. ' + e);
- }
- return cMap;
- }
- error('Encoding required.');
- }
- };
-})();
-/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
+/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
-/*
- Copyright 2011 notmasteryet
- 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
+/* 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 */
- http://www.apache.org/licenses/LICENSE-2.0
+'use strict';
- 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.
-*/
+var MurmurHash3_64 = (function MurmurHash3_64Closure (seed) {
+ // Workaround for missing math precison in JS.
+ var MASK_HIGH = 0xffff0000;
+ var MASK_LOW = 0xffff;
-// - The JPEG specification can be found in the ITU CCITT Recommendation T.81
-// (www.w3.org/Graphics/JPEG/itu-t81.pdf)
-// - The JFIF specification can be found in the JPEG File Interchange Format
-// (www.w3.org/Graphics/JPEG/jfif3.pdf)
-// - The Adobe Application-Specific JPEG markers in the Supporting the DCT Filters
-// in PostScript Level 2, Technical Note #5116
-// (partners.adobe.com/public/developer/en/ps/sdk/5116.DCT_Filter.pdf)
-
-var JpegImage = (function jpegImage() {
- "use strict";
- var dctZigZag = new Int32Array([
- 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 MurmurHash3_64 (seed) {
+ var SEED = 0xc3d2e1f0;
+ this.h1 = seed ? seed & 0xffffffff : SEED;
+ this.h2 = seed ? seed & 0xffffffff : SEED;
}
- 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;
+ 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
- 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, bit;
- while ((bit = readBit()) !== null) {
- node = node[bit];
- if (typeof node === 'number')
- return node;
- if (typeof node !== 'object')
- throw "invalid huffman sequence";
- }
- return null;
- }
- function receive(length) {
- var n = 0;
- while (length > 0) {
- var bit = readBit();
- if (bit === null) return;
- n = (n << 1) | bit;
- length--;
- }
- return n;
- }
- function receiveAndExtend(length) {
- var n = receive(length);
- if (n >= 1 << (length - 1))
- return n;
- return n + (-1 << length) + 1;
- }
- function decodeBaseline(component, zz) {
- var t = decodeHuffman(component.huffmanTableDC);
- var diff = t === 0 ? 0 : receiveAndExtend(t);
- zz[0]= (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];
- zz[z] = receiveAndExtend(s);
- k++;
- }
- }
- function decodeDCFirst(component, zz) {
- var t = decodeHuffman(component.huffmanTableDC);
- var diff = t === 0 ? 0 : (receiveAndExtend(t) << successive);
- zz[0] = (component.pred += diff);
- }
- function decodeDCSuccessive(component, zz) {
- zz[0] |= readBit() << successive;
- }
- var eobrun = 0;
- function decodeACFirst(component, zz) {
- 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];
- zz[z] = receiveAndExtend(s) * (1 << successive);
- k++;
- }
- }
- var successiveACState = 0, successiveACNextValue;
- function decodeACSuccessive(component, zz) {
- var k = spectralStart, e = spectralEnd, r = 0;
- while (k <= e) {
- var z = dctZigZag[k];
- switch (successiveACState) {
- case 0: // initial state
- var rs = decodeHuffman(component.huffmanTableAC);
- var 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 (zz[z])
- zz[z] += (readBit() << successive);
- else {
- r--;
- if (r === 0)
- successiveACState = successiveACState == 2 ? 3 : 0;
- }
- break;
- case 3: // set value for a zero item
- if (zz[z])
- zz[z] += (readBit() << successive);
- else {
- zz[z] = successiveACNextValue << successive;
- successiveACState = 0;
- }
- break;
- case 4: // eob
- if (zz[z])
- zz[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;
- decode(component, component.blocks[blockRow][blockCol]);
- }
- function decodeBlock(component, decode, mcu) {
- var blockRow = (mcu / component.blocksPerLine) | 0;
- var blockCol = mcu % component.blocksPerLine;
- decode(component, component.blocks[blockRow][blockCol]);
- }
-
- 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;
- }
-
- function buildComponentData(frame, component) {
- var lines = [];
- var blocksPerLine = component.blocksPerLine;
- var blocksPerColumn = component.blocksPerColumn;
- var samplesPerLine = blocksPerLine << 3;
- var R = new Int32Array(64), r = new Uint8Array(64);
-
- // 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(zz, dataOut, dataIn) {
- var qt = component.quantizationTable;
- var v0, v1, v2, v3, v4, v5, v6, v7, t;
- var p = dataIn;
+ MurmurHash3_64.prototype = {
+ update: function MurmurHash3_64_update(input) {
+ var useUint32ArrayView = alwaysUseUint32ArrayView;
var i;
-
- // dequant
- for (i = 0; i < 64; i++)
- p[i] = zz[i] * qt[i];
-
- // inverse DCT on rows
- for (i = 0; i < 8; ++i) {
- var row = 8 * i;
-
- // check for all-zero AC coefficients
- if (p[1 + row] == 0 && p[2 + row] == 0 && p[3 + row] == 0 &&
- p[4 + row] == 0 && p[5 + row] == 0 && p[6 + row] == 0 &&
- p[7 + row] == 0) {
- t = (dctSqrt2 * p[0 + row] + 512) >> 10;
- p[0 + row] = t;
- p[1 + row] = t;
- p[2 + row] = t;
- p[3 + row] = t;
- p[4 + row] = t;
- p[5 + row] = t;
- p[6 + row] = t;
- p[7 + row] = t;
- continue;
- }
-
- // stage 4
- v0 = (dctSqrt2 * p[0 + row] + 128) >> 8;
- v1 = (dctSqrt2 * p[4 + row] + 128) >> 8;
- v2 = p[2 + row];
- v3 = p[6 + row];
- v4 = (dctSqrt1d2 * (p[1 + row] - p[7 + row]) + 128) >> 8;
- v7 = (dctSqrt1d2 * (p[1 + row] + p[7 + row]) + 128) >> 8;
- v5 = p[3 + row] << 4;
- v6 = p[5 + row] << 4;
-
- // stage 3
- t = (v0 - v1+ 1) >> 1;
- v0 = (v0 + v1 + 1) >> 1;
- v1 = t;
- t = (v2 * dctSin6 + v3 * dctCos6 + 128) >> 8;
- v2 = (v2 * dctCos6 - v3 * dctSin6 + 128) >> 8;
- v3 = t;
- t = (v4 - v6 + 1) >> 1;
- v4 = (v4 + v6 + 1) >> 1;
- v6 = t;
- t = (v7 + v5 + 1) >> 1;
- v5 = (v7 - v5 + 1) >> 1;
- v7 = t;
-
- // stage 2
- t = (v0 - v3 + 1) >> 1;
- v0 = (v0 + v3 + 1) >> 1;
- v3 = t;
- t = (v1 - v2 + 1) >> 1;
- v1 = (v1 + v2 + 1) >> 1;
- v2 = t;
- 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[0 + row] = v0 + v7;
- p[7 + row] = v0 - v7;
- p[1 + row] = v1 + v6;
- p[6 + row] = v1 - v6;
- p[2 + row] = v2 + v5;
- p[5 + row] = v2 - v5;
- p[3 + row] = v3 + v4;
- p[4 + row] = v3 - v4;
- }
-
- // inverse DCT on columns
- for (i = 0; i < 8; ++i) {
- var col = i;
-
- // check for all-zero AC coefficients
- if (p[1*8 + col] == 0 && p[2*8 + col] == 0 && p[3*8 + col] == 0 &&
- p[4*8 + col] == 0 && p[5*8 + col] == 0 && p[6*8 + col] == 0 &&
- p[7*8 + col] == 0) {
- t = (dctSqrt2 * dataIn[i+0] + 8192) >> 14;
- p[0*8 + col] = t;
- p[1*8 + col] = t;
- p[2*8 + col] = t;
- p[3*8 + col] = t;
- p[4*8 + col] = t;
- p[5*8 + col] = t;
- p[6*8 + col] = t;
- p[7*8 + col] = t;
- continue;
- }
-
- // stage 4
- v0 = (dctSqrt2 * p[0*8 + col] + 2048) >> 12;
- v1 = (dctSqrt2 * p[4*8 + col] + 2048) >> 12;
- v2 = p[2*8 + col];
- v3 = p[6*8 + col];
- v4 = (dctSqrt1d2 * (p[1*8 + col] - p[7*8 + col]) + 2048) >> 12;
- v7 = (dctSqrt1d2 * (p[1*8 + col] + p[7*8 + col]) + 2048) >> 12;
- v5 = p[3*8 + col];
- v6 = p[5*8 + col];
-
- // stage 3
- t = (v0 - v1 + 1) >> 1;
- v0 = (v0 + v1 + 1) >> 1;
- v1 = t;
- t = (v2 * dctSin6 + v3 * dctCos6 + 2048) >> 12;
- v2 = (v2 * dctCos6 - v3 * dctSin6 + 2048) >> 12;
- v3 = t;
- t = (v4 - v6 + 1) >> 1;
- v4 = (v4 + v6 + 1) >> 1;
- v6 = t;
- t = (v7 + v5 + 1) >> 1;
- v5 = (v7 - v5 + 1) >> 1;
- v7 = t;
-
- // stage 2
- t = (v0 - v3 + 1) >> 1;
- v0 = (v0 + v3 + 1) >> 1;
- v3 = t;
- t = (v1 - v2 + 1) >> 1;
- v1 = (v1 + v2 + 1) >> 1;
- v2 = t;
- 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[0*8 + col] = v0 + v7;
- p[7*8 + col] = v0 - v7;
- p[1*8 + col] = v1 + v6;
- p[6*8 + col] = v1 - v6;
- p[2*8 + col] = v2 + v5;
- p[5*8 + col] = v2 - v5;
- p[3*8 + col] = v3 + v4;
- p[4*8 + col] = v3 - v4;
- }
-
- // convert to 8-bit integers
- for (i = 0; i < 64; ++i) {
- var sample = 128 + ((p[i] + 8) >> 4);
- dataOut[i] = sample < 0 ? 0 : sample > 0xFF ? 0xFF : sample;
- }
- }
-
- var i, j;
- for (var blockRow = 0; blockRow < blocksPerColumn; blockRow++) {
- var scanLine = blockRow << 3;
- for (i = 0; i < 8; i++)
- lines.push(new Uint8Array(samplesPerLine));
- for (var blockCol = 0; blockCol < blocksPerLine; blockCol++) {
- quantizeAndInverse(component.blocks[blockRow][blockCol], r, R);
-
- var offset = 0, sample = blockCol << 3;
- for (j = 0; j < 8; j++) {
- var line = lines[scanLine + j];
- for (i = 0; i < 8; i++)
- line[sample + i] = r[offset++];
- }
- }
- }
- return lines;
- }
-
- function clampTo8bit(a) {
- return a < 0 ? 0 : a > 255 ? 255 : a;
- }
-
- constructor.prototype = {
- load: function load(path) {
- var xhr = new XMLHttpRequest();
- xhr.open("GET", path, true);
- xhr.responseType = "arraybuffer";
- xhr.onload = (function() {
- // TODO catch parse error
- var data = new Uint8Array(xhr.response || xhr.mozResponseArrayBuffer);
- this.parse(data);
- if (this.onload)
- this.onload();
- }).bind(this);
- xhr.send(null);
- },
- parse: function parse(data) {
- var offset = 0, length = data.length;
- 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 maxH = 0, maxV = 0;
- var component, componentId;
- for (componentId in frame.components) {
- if (frame.components.hasOwnProperty(componentId)) {
- component = frame.components[componentId];
- if (maxH < component.h) maxH = component.h;
- if (maxV < component.v) maxV = component.v;
+ 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;
}
}
- var mcusPerLine = Math.ceil(frame.samplesPerLine / 8 / maxH);
- var mcusPerColumn = Math.ceil(frame.scanLines / 8 / maxV);
- for (componentId in frame.components) {
- if (frame.components.hasOwnProperty(componentId)) {
- component = frame.components[componentId];
- var blocksPerLine = Math.ceil(Math.ceil(frame.samplesPerLine / 8) * component.h / maxH);
- var blocksPerColumn = Math.ceil(Math.ceil(frame.scanLines / 8) * component.v / maxV);
- var blocksPerLineForMcu = mcusPerLine * component.h;
- var blocksPerColumnForMcu = mcusPerColumn * component.v;
- var blocks = [];
- for (var i = 0; i < blocksPerColumnForMcu; i++) {
- var row = [];
- for (var j = 0; j < blocksPerLineForMcu; j++)
- row.push(new Int32Array(64));
- blocks.push(row);
- }
- component.blocksPerLine = blocksPerLine;
- component.blocksPerColumn = blocksPerColumn;
- component.blocks = blocks;
- }
+ } 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;
}
- frame.maxH = maxH;
- frame.maxV = maxV;
- frame.mcusPerLine = mcusPerLine;
- frame.mcusPerColumn = mcusPerColumn;
- }
- var jfif = null;
- var adobe = null;
- var pixels = null;
- var frame, resetInterval;
- var quantizationTables = [], frames = [];
- 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();
+ k1 = 0;
- 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 && appData[5] === 0) { // 'Adobe\x00'
- adobe = {
- version: 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;
- while (offset < quantizationTablesEnd) {
- var quantizationTableSpec = data[offset++];
- var tableData = new Int32Array(64);
- if ((quantizationTableSpec >> 4) === 0) { // 8 bit values
- for (j = 0; j < 64; j++) {
- var z = dctZigZag[j];
- tableData[z] = data[offset++];
- }
- } else if ((quantizationTableSpec >> 4) === 1) { //16 bit
- for (j = 0; j < 64; j++) {
- var 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)
- 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.componentsOrder = [];
- 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;
- var qId = data[offset + 2];
- frame.componentsOrder.push(componentId);
- frame.components[componentId] = {
- h: h,
- v: v,
- quantizationTable: quantizationTables[qId]
- };
- offset += 3;
- }
- prepareComponents(frame);
- frames.push(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++) {
- component = frame.components[data[offset++]];
- 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;
- 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();
- }
- if (frames.length != 1)
- throw "only single frame JPEGs supported";
-
- this.width = frame.samplesPerLine;
- this.height = frame.scanLines;
- this.jfif = jfif;
- this.adobe = adobe;
- this.components = [];
- for (var i = 0; i < frame.componentsOrder.length; i++) {
- var component = frame.components[frame.componentsOrder[i]];
- this.components.push({
- lines: buildComponentData(frame, component),
- scaleX: component.h / frame.maxH,
- scaleY: component.v / frame.maxV
- });
- }
- },
- getData: function getData(width, height) {
- var scaleX = this.width / width, scaleY = this.height / height;
-
- var component1, component2, component3, component4;
- var component1Line, component2Line, component3Line, component4Line;
- var x, y;
- var offset = 0;
- var Y, Cb, Cr, K, C, M, Ye, R, G, B;
- var colorTransform;
- var dataLength = width * height * this.components.length;
- var data = new Uint8Array(dataLength);
- switch (this.components.length) {
- case 1:
- component1 = this.components[0];
- for (y = 0; y < height; y++) {
- component1Line = component1.lines[0 | (y * component1.scaleY * scaleY)];
- for (x = 0; x < width; x++) {
- Y = component1Line[0 | (x * component1.scaleX * scaleX)];
-
- data[offset++] = Y;
- }
- }
- break;
+ switch (tailLength) {
+ case 3:
+ k1 ^= data[blockCounts * 4 + 2] << 16;
+ /* falls through */
case 2:
- // PDF might compress two component data in custom colorspace
- component1 = this.components[0];
- component2 = this.components[1];
- for (y = 0; y < height; y++) {
- component1Line = component1.lines[0 | (y * component1.scaleY * scaleY)];
- component2Line = component2.lines[0 | (y * component2.scaleY * scaleY)];
- for (x = 0; x < width; x++) {
- Y = component1Line[0 | (x * component1.scaleX * scaleX)];
- data[offset++] = Y;
- Y = component2Line[0 | (x * component2.scaleX * scaleX)];
- data[offset++] = Y;
- }
- }
- break;
- case 3:
- // The default transform for three components is true
- colorTransform = true;
- // The adobe transform marker overrides any previous setting
- if (this.adobe && this.adobe.transformCode)
- colorTransform = true;
- else if (typeof this.colorTransform !== 'undefined')
- colorTransform = !!this.colorTransform;
-
- component1 = this.components[0];
- component2 = this.components[1];
- component3 = this.components[2];
- for (y = 0; y < height; y++) {
- component1Line = component1.lines[0 | (y * component1.scaleY * scaleY)];
- component2Line = component2.lines[0 | (y * component2.scaleY * scaleY)];
- component3Line = component3.lines[0 | (y * component3.scaleY * scaleY)];
- for (x = 0; x < width; x++) {
- if (!colorTransform) {
- R = component1Line[0 | (x * component1.scaleX * scaleX)];
- G = component2Line[0 | (x * component2.scaleX * scaleX)];
- B = component3Line[0 | (x * component3.scaleX * scaleX)];
- } else {
- Y = component1Line[0 | (x * component1.scaleX * scaleX)];
- Cb = component2Line[0 | (x * component2.scaleX * scaleX)];
- Cr = component3Line[0 | (x * component3.scaleX * scaleX)];
-
- R = clampTo8bit(Y + 1.402 * (Cr - 128));
- G = clampTo8bit(Y - 0.3441363 * (Cb - 128) - 0.71413636 * (Cr - 128));
- B = clampTo8bit(Y + 1.772 * (Cb - 128));
- }
-
- data[offset++] = R;
- data[offset++] = G;
- data[offset++] = B;
- }
- }
- break;
- case 4:
- // The default transform for four components is false
- colorTransform = false;
- // The adobe transform marker overrides any previous setting
- if (this.adobe && this.adobe.transformCode)
- colorTransform = true;
- else if (typeof this.colorTransform !== 'undefined')
- colorTransform = !!this.colorTransform;
-
- component1 = this.components[0];
- component2 = this.components[1];
- component3 = this.components[2];
- component4 = this.components[3];
- for (y = 0; y < height; y++) {
- component1Line = component1.lines[0 | (y * component1.scaleY * scaleY)];
- component2Line = component2.lines[0 | (y * component2.scaleY * scaleY)];
- component3Line = component3.lines[0 | (y * component3.scaleY * scaleY)];
- component4Line = component4.lines[0 | (y * component4.scaleY * scaleY)];
- for (x = 0; x < width; x++) {
- if (!colorTransform) {
- C = component1Line[0 | (x * component1.scaleX * scaleX)];
- M = component2Line[0 | (x * component2.scaleX * scaleX)];
- Ye = component3Line[0 | (x * component3.scaleX * scaleX)];
- K = component4Line[0 | (x * component4.scaleX * scaleX)];
- } else {
- Y = component1Line[0 | (x * component1.scaleX * scaleX)];
- Cb = component2Line[0 | (x * component2.scaleX * scaleX)];
- Cr = component3Line[0 | (x * component3.scaleX * scaleX)];
- K = component4Line[0 | (x * component4.scaleX * scaleX)];
-
- C = 255 - clampTo8bit(Y + 1.402 * (Cr - 128));
- M = 255 - clampTo8bit(Y - 0.3441363 * (Cb - 128) - 0.71413636 * (Cr - 128));
- Ye = 255 - clampTo8bit(Y + 1.772 * (Cb - 128));
- }
- data[offset++] = C;
- data[offset++] = M;
- data[offset++] = Ye;
- data[offset++] = K;
- }
- }
- break;
- default:
- throw 'Unsupported color mode';
- }
- return data;
- },
- copyToImageData: function copyToImageData(imageData) {
- var width = imageData.width, height = imageData.height;
- var imageDataArray = imageData.data;
- var data = this.getData(width, height);
- var i = 0, j = 0, x, y;
- var Y, K, C, M, R, G, B;
- switch (this.components.length) {
+ k1 ^= data[blockCounts * 4 + 1] << 8;
+ /* falls through */
case 1:
- for (y = 0; y < height; y++) {
- for (x = 0; x < width; x++) {
- Y = data[i++];
-
- imageDataArray[j++] = Y;
- imageDataArray[j++] = Y;
- imageDataArray[j++] = Y;
- imageDataArray[j++] = 255;
- }
- }
- break;
- case 3:
- for (y = 0; y < height; y++) {
- for (x = 0; x < width; x++) {
- R = data[i++];
- G = data[i++];
- B = data[i++];
-
- imageDataArray[j++] = R;
- imageDataArray[j++] = G;
- imageDataArray[j++] = B;
- imageDataArray[j++] = 255;
- }
- }
- break;
- case 4:
- for (y = 0; y < height; y++) {
- for (x = 0; x < width; x++) {
- C = data[i++];
- M = data[i++];
- Y = data[i++];
- K = data[i++];
-
- R = 255 - clampTo8bit(C * (1 - K / 255) + K);
- G = 255 - clampTo8bit(M * (1 - K / 255) + K);
- B = 255 - clampTo8bit(Y * (1 - K / 255) + K);
-
- imageDataArray[j++] = R;
- imageDataArray[j++] = G;
- imageDataArray[j++] = B;
- imageDataArray[j++] = 255;
- }
- }
- break;
- default:
- throw 'Unsupported color mode';
+ 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 constructor;
+ return MurmurHash3_64;
})();
@@ -39897,4 +39110,3 @@ if (!PDFJS.workerSrc && typeof document !== 'undefined') {
})();
}
-
diff --git a/attachment_preview/static/lib/ViewerJS/pdf_find_bar.js b/attachment_preview/static/lib/ViewerJS/pdf_find_bar.js
deleted file mode 100644
index 2054c6d1..00000000
--- a/attachment_preview/static/lib/ViewerJS/pdf_find_bar.js
+++ /dev/null
@@ -1,175 +0,0 @@
-/* -*- 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';
-
-/* globals PDFFindController, FindStates, mozL10n */
-
-/**
- * Creates a "search bar" given set of DOM elements
- * that act as controls for searching, or for setting
- * search preferences in the UI. This object also sets
- * up the appropriate events for the controls. Actual
- * searching is done by PDFFindController
- */
-var PDFFindBar = {
-
- opened: false,
- bar: null,
- toggleButton: null,
- findField: null,
- highlightAll: null,
- caseSensitive: null,
- findMsg: null,
- findStatusIcon: null,
- findPreviousButton: null,
- findNextButton: null,
-
- initialize: function(options) {
- if(typeof PDFFindController === 'undefined' || PDFFindController === null) {
- throw 'PDFFindBar cannot be initialized ' +
- 'without a PDFFindController instance.';
- }
-
- this.bar = options.bar;
- this.toggleButton = options.toggleButton;
- this.findField = options.findField;
- this.highlightAll = options.highlightAllCheckbox;
- this.caseSensitive = options.caseSensitiveCheckbox;
- this.findMsg = options.findMsg;
- this.findStatusIcon = options.findStatusIcon;
- this.findPreviousButton = options.findPreviousButton;
- this.findNextButton = options.findNextButton;
-
- var self = this;
- this.toggleButton.addEventListener('click', function() {
- self.toggle();
- });
-
- this.findField.addEventListener('input', function() {
- self.dispatchEvent('');
- });
-
- this.bar.addEventListener('keydown', function(evt) {
- switch (evt.keyCode) {
- case 13: // Enter
- if (evt.target === self.findField) {
- self.dispatchEvent('again', evt.shiftKey);
- }
- break;
- case 27: // Escape
- self.close();
- break;
- }
- });
-
- this.findPreviousButton.addEventListener('click',
- function() { self.dispatchEvent('again', true); }
- );
-
- this.findNextButton.addEventListener('click', function() {
- self.dispatchEvent('again', false);
- });
-
- this.highlightAll.addEventListener('click', function() {
- self.dispatchEvent('highlightallchange');
- });
-
- this.caseSensitive.addEventListener('click', function() {
- self.dispatchEvent('casesensitivitychange');
- });
- },
-
- dispatchEvent: function(aType, aFindPrevious) {
- var event = document.createEvent('CustomEvent');
- event.initCustomEvent('find' + aType, true, true, {
- query: this.findField.value,
- caseSensitive: this.caseSensitive.checked,
- highlightAll: this.highlightAll.checked,
- findPrevious: aFindPrevious
- });
- return window.dispatchEvent(event);
- },
-
- updateUIState: function(state, previous) {
- var notFound = false;
- var findMsg = '';
- var status = '';
-
- switch (state) {
- case FindStates.FIND_FOUND:
- break;
-
- case FindStates.FIND_PENDING:
- status = 'pending';
- break;
-
- case FindStates.FIND_NOTFOUND:
- findMsg = mozL10n.get('find_not_found', null, 'Phrase not found');
- notFound = true;
- break;
-
- case FindStates.FIND_WRAPPED:
- if (previous) {
- findMsg = mozL10n.get('find_reached_top', null,
- 'Reached top of document, continued from bottom');
- } else {
- findMsg = mozL10n.get('find_reached_bottom', null,
- 'Reached end of document, continued from top');
- }
- break;
- }
-
- if (notFound) {
- this.findField.classList.add('notFound');
- } else {
- this.findField.classList.remove('notFound');
- }
-
- this.findField.setAttribute('data-status', status);
- this.findMsg.textContent = findMsg;
- },
-
- open: function() {
- if (!this.opened) {
- this.opened = true;
- this.toggleButton.classList.add('toggled');
- this.bar.classList.remove('hidden');
- }
-
- this.findField.select();
- this.findField.focus();
- },
-
- close: function() {
- if (!this.opened) return;
-
- this.opened = false;
- this.toggleButton.classList.remove('toggled');
- this.bar.classList.add('hidden');
-
- PDFFindController.active = false;
- },
-
- toggle: function() {
- if (this.opened) {
- this.close();
- } else {
- this.open();
- }
- }
-};
-
diff --git a/attachment_preview/static/lib/ViewerJS/pdf_find_controller.js b/attachment_preview/static/lib/ViewerJS/pdf_find_controller.js
deleted file mode 100644
index e48246fa..00000000
--- a/attachment_preview/static/lib/ViewerJS/pdf_find_controller.js
+++ /dev/null
@@ -1,355 +0,0 @@
-/* -*- 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';
-
-/* globals PDFFindBar, PDFJS, FindStates, FirefoxCom, Promise */
-
-/**
- * Provides a "search" or "find" functionality for the PDF.
- * This object actually performs the search for a given string.
- */
-
-var PDFFindController = {
- startedTextExtraction: false,
-
- extractTextPromises: [],
-
- pendingFindMatches: {},
-
- // If active, find results will be highlighted.
- active: false,
-
- // Stores the text for each page.
- pageContents: [],
-
- pageMatches: [],
-
- // Currently selected match.
- selected: {
- pageIdx: -1,
- matchIdx: -1
- },
-
- // Where find algorithm currently is in the document.
- offset: {
- pageIdx: null,
- matchIdx: null
- },
-
- resumePageIdx: null,
-
- state: null,
-
- dirtyMatch: false,
-
- findTimeout: null,
-
- pdfPageSource: null,
-
- integratedFind: false,
-
- initialize: function(options) {
- if(typeof PDFFindBar === 'undefined' || PDFFindBar === null) {
- throw 'PDFFindController cannot be initialized ' +
- 'without a PDFFindController instance';
- }
-
- this.pdfPageSource = options.pdfPageSource;
- this.integratedFind = options.integratedFind;
-
- var events = [
- 'find',
- 'findagain',
- 'findhighlightallchange',
- 'findcasesensitivitychange'
- ];
-
- this.firstPagePromise = new Promise(function (resolve) {
- this.resolveFirstPage = resolve;
- }.bind(this));
- this.handleEvent = this.handleEvent.bind(this);
-
- for (var i = 0; i < events.length; i++) {
- window.addEventListener(events[i], this.handleEvent);
- }
- },
-
- reset: function pdfFindControllerReset() {
- this.startedTextExtraction = false;
- this.extractTextPromises = [];
- this.active = false;
- },
-
- calcFindMatch: function(pageIndex) {
- var pageContent = this.pageContents[pageIndex];
- var query = this.state.query;
- var caseSensitive = this.state.caseSensitive;
- var queryLen = query.length;
-
- if (queryLen === 0) {
- // Do nothing the matches should be wiped out already.
- return;
- }
-
- if (!caseSensitive) {
- pageContent = pageContent.toLowerCase();
- query = query.toLowerCase();
- }
-
- var matches = [];
-
- var matchIdx = -queryLen;
- while (true) {
- matchIdx = pageContent.indexOf(query, matchIdx + queryLen);
- if (matchIdx === -1) {
- break;
- }
-
- matches.push(matchIdx);
- }
- this.pageMatches[pageIndex] = matches;
- this.updatePage(pageIndex);
- if (this.resumePageIdx === pageIndex) {
- this.resumePageIdx = null;
- this.nextPageMatch();
- }
- },
-
- extractText: function() {
- if (this.startedTextExtraction) {
- return;
- }
- this.startedTextExtraction = true;
-
- this.pageContents = [];
- var extractTextPromisesResolves = [];
- for (var i = 0, ii = this.pdfPageSource.pdfDocument.numPages; i < ii; i++) {
- this.extractTextPromises.push(new Promise(function (resolve) {
- extractTextPromisesResolves.push(resolve);
- }));
- }
-
- var self = this;
- function extractPageText(pageIndex) {
- self.pdfPageSource.pages[pageIndex].getTextContent().then(
- function textContentResolved(bidiTexts) {
- var str = '';
-
- for (var i = 0; i < bidiTexts.length; i++) {
- str += bidiTexts[i].str;
- }
-
- // Store the pageContent as a string.
- self.pageContents.push(str);
-
- extractTextPromisesResolves[pageIndex](pageIndex);
- if ((pageIndex + 1) < self.pdfPageSource.pages.length)
- extractPageText(pageIndex + 1);
- }
- );
- }
- extractPageText(0);
- },
-
- handleEvent: function(e) {
- if (this.state === null || e.type !== 'findagain') {
- this.dirtyMatch = true;
- }
- this.state = e.detail;
- this.updateUIState(FindStates.FIND_PENDING);
-
- this.firstPagePromise.then(function() {
- this.extractText();
-
- clearTimeout(this.findTimeout);
- if (e.type === 'find') {
- // Only trigger the find action after 250ms of silence.
- this.findTimeout = setTimeout(this.nextMatch.bind(this), 250);
- } else {
- this.nextMatch();
- }
- }.bind(this));
- },
-
- updatePage: function(idx) {
- var page = this.pdfPageSource.pages[idx];
-
- if (this.selected.pageIdx === idx) {
- // If the page is selected, scroll the page into view, which triggers
- // rendering the page, which adds the textLayer. Once the textLayer is
- // build, it will scroll onto the selected match.
- page.scrollIntoView();
- }
-
- if (page.textLayer) {
- page.textLayer.updateMatches();
- }
- },
-
- nextMatch: function() {
- var previous = this.state.findPrevious;
- var currentPageIndex = this.pdfPageSource.page - 1;
- var numPages = this.pdfPageSource.pages.length;
-
- this.active = true;
-
- if (this.dirtyMatch) {
- // Need to recalculate the matches, reset everything.
- this.dirtyMatch = false;
- this.selected.pageIdx = this.selected.matchIdx = -1;
- this.offset.pageIdx = currentPageIndex;
- this.offset.matchIdx = null;
- this.hadMatch = false;
- this.resumePageIdx = null;
- this.pageMatches = [];
- var self = this;
-
- for (var i = 0; i < numPages; i++) {
- // Wipe out any previous highlighted matches.
- this.updatePage(i);
-
- // As soon as the text is extracted start finding the matches.
- if (!(i in this.pendingFindMatches)) {
- this.pendingFindMatches[i] = true;
- this.extractTextPromises[i].then(function(pageIdx) {
- delete self.pendingFindMatches[pageIdx];
- self.calcFindMatch(pageIdx);
- });
- }
- }
- }
-
- // If there's no query there's no point in searching.
- if (this.state.query === '') {
- this.updateUIState(FindStates.FIND_FOUND);
- return;
- }
-
- // If we're waiting on a page, we return since we can't do anything else.
- if (this.resumePageIdx) {
- return;
- }
-
- var offset = this.offset;
- // If there's already a matchIdx that means we are iterating through a
- // page's matches.
- if (offset.matchIdx !== null) {
- var numPageMatches = this.pageMatches[offset.pageIdx].length;
- if ((!previous && offset.matchIdx + 1 < numPageMatches) ||
- (previous && offset.matchIdx > 0)) {
- // The simple case, we just have advance the matchIdx to select the next
- // match on the page.
- this.hadMatch = true;
- offset.matchIdx = previous ? offset.matchIdx - 1 : offset.matchIdx + 1;
- this.updateMatch(true);
- return;
- }
- // We went beyond the current page's matches, so we advance to the next
- // page.
- this.advanceOffsetPage(previous);
- }
- // Start searching through the page.
- this.nextPageMatch();
- },
-
- matchesReady: function(matches) {
- var offset = this.offset;
- var numMatches = matches.length;
- var previous = this.state.findPrevious;
- if (numMatches) {
- // There were matches for the page, so initialize the matchIdx.
- this.hadMatch = true;
- offset.matchIdx = previous ? numMatches - 1 : 0;
- this.updateMatch(true);
- // matches were found
- return true;
- } else {
- // No matches attempt to search the next page.
- this.advanceOffsetPage(previous);
- if (offset.wrapped) {
- offset.matchIdx = null;
- if (!this.hadMatch) {
- // No point in wrapping there were no matches.
- this.updateMatch(false);
- // while matches were not found, searching for a page
- // with matches should nevertheless halt.
- return true;
- }
- }
- // matches were not found (and searching is not done)
- return false;
- }
- },
-
- nextPageMatch: function() {
- if (this.resumePageIdx !== null) {
- console.error('There can only be one pending page.');
- }
- do {
- var pageIdx = this.offset.pageIdx;
- var matches = this.pageMatches[pageIdx];
- if (!matches) {
- // The matches don't exist yet for processing by "matchesReady",
- // so set a resume point for when they do exist.
- this.resumePageIdx = pageIdx;
- break;
- }
- } while (!this.matchesReady(matches));
- },
-
- advanceOffsetPage: function(previous) {
- var offset = this.offset;
- var numPages = this.extractTextPromises.length;
- offset.pageIdx = previous ? offset.pageIdx - 1 : offset.pageIdx + 1;
- offset.matchIdx = null;
- if (offset.pageIdx >= numPages || offset.pageIdx < 0) {
- offset.pageIdx = previous ? numPages - 1 : 0;
- offset.wrapped = true;
- return;
- }
- },
-
- updateMatch: function(found) {
- var state = FindStates.FIND_NOTFOUND;
- var wrapped = this.offset.wrapped;
- this.offset.wrapped = false;
- if (found) {
- var previousPage = this.selected.pageIdx;
- this.selected.pageIdx = this.offset.pageIdx;
- this.selected.matchIdx = this.offset.matchIdx;
- state = wrapped ? FindStates.FIND_WRAPPED : FindStates.FIND_FOUND;
- // Update the currently selected page to wipe out any selected matches.
- if (previousPage !== -1 && previousPage !== this.selected.pageIdx) {
- this.updatePage(previousPage);
- }
- }
- this.updateUIState(state, this.state.findPrevious);
- if (this.selected.pageIdx !== -1) {
- this.updatePage(this.selected.pageIdx, true);
- }
- },
-
- updateUIState: function(state, previous) {
- if (this.integratedFind) {
- FirefoxCom.request('updateFindControlState',
- {result: state, findPrevious: previous});
- return;
- }
- PDFFindBar.updateUIState(state, previous);
- }
-};
-
diff --git a/attachment_preview/static/lib/ViewerJS/pdfjsversion.js b/attachment_preview/static/lib/ViewerJS/pdfjsversion.js
index 9d3e0e4d..aabaa0d2 100644
--- a/attachment_preview/static/lib/ViewerJS/pdfjsversion.js
+++ b/attachment_preview/static/lib/ViewerJS/pdfjsversion.js
@@ -1 +1 @@
-var /**@const{!string}*/pdfjs_version = "d45d7bc";
+var /**@const{!string}*/pdfjs_version = "v1.0.1040";
diff --git a/attachment_preview/static/lib/ViewerJS/text_layer_builder.js b/attachment_preview/static/lib/ViewerJS/text_layer_builder.js
index c2f8043e..5fac1c49 100644
--- a/attachment_preview/static/lib/ViewerJS/text_layer_builder.js
+++ b/attachment_preview/static/lib/ViewerJS/text_layer_builder.js
@@ -13,373 +13,377 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-/* globals CustomStyle, PDFFindController, scrollIntoView */
+/* globals CustomStyle, scrollIntoView, PDFJS */
'use strict';
var FIND_SCROLL_OFFSET_TOP = -50;
var FIND_SCROLL_OFFSET_LEFT = -400;
+var MAX_TEXT_DIVS_TO_RENDER = 100000;
+var RENDER_DELAY = 200; // ms
+
+var NonWhitespaceRegexp = /\S/;
+
+function isAllWhitespace(str) {
+ return !NonWhitespaceRegexp.test(str);
+}
/**
- * TextLayerBuilder provides text-selection
- * functionality for the PDF. It does this
- * by creating overlay divs over the PDF
- * text. This divs contain text that matches
- * the PDF text they are overlaying. This
- * object also provides for a way to highlight
- * text that is being searched for.
+ * @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 {ILastScrollSource} lastScrollSource - The object that records when
+ * last time scroll happened.
+ * @property {boolean} isViewerInPresentationMode
+ * @property {PDFFindController} findController
*/
-var TextLayerBuilder = function textLayerBuilder(options) {
- var textLayerFrag = document.createDocumentFragment();
- this.textLayerDiv = options.textLayerDiv;
- this.layoutDone = false;
- this.divContentDone = false;
- this.pageIdx = options.pageIndex;
- this.matches = [];
- this.lastScrollSource = options.lastScrollSource;
- this.viewport = options.viewport;
- this.isViewerInPresentationMode = options.isViewerInPresentationMode;
-
- if(typeof PDFFindController === 'undefined') {
- window.PDFFindController = null;
- }
-
- if(typeof this.lastScrollSource === 'undefined') {
- this.lastScrollSource = null;
- }
-
- this.beginLayout = function textLayerBuilderBeginLayout() {
+/**
+ * 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.layoutDone = false;
+ this.divContentDone = false;
+ this.pageIdx = options.pageIndex;
+ this.matches = [];
+ this.lastScrollSource = options.lastScrollSource || null;
+ this.viewport = options.viewport;
+ this.isViewerInPresentationMode = options.isViewerInPresentationMode;
this.textDivs = [];
- this.renderingDone = false;
- };
+ this.findController = options.findController || null;
+ }
- this.endLayout = function textLayerBuilderEndLayout() {
- this.layoutDone = true;
- this.insertDivContent();
- };
+ TextLayerBuilder.prototype = {
+ 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');
- this.renderLayer = function textLayerBuilderRenderLayer() {
- var self = this;
- var textDivs = this.textDivs;
- var bidiTexts = this.textContent;
- var textLayerDiv = this.textLayerDiv;
- var canvas = document.createElement('canvas');
- var ctx = canvas.getContext('2d');
-
- // No point in rendering so many divs as it'd make the browser unusable
- // even after the divs are rendered
- var MAX_TEXT_DIVS_TO_RENDER = 100000;
- if (textDivs.length > MAX_TEXT_DIVS_TO_RENDER)
- return;
-
- for (var i = 0, ii = textDivs.length; i < ii; i++) {
- var textDiv = textDivs[i];
- if ('isWhitespace' in textDiv.dataset) {
- continue;
+ // 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) {
+ return;
}
- ctx.font = textDiv.style.fontSize + ' ' + textDiv.style.fontFamily;
- var width = ctx.measureText(textDiv.textContent).width;
+ var lastFontSize;
+ var lastFontFamily;
+ for (var i = 0; i < textDivsLength; i++) {
+ var textDiv = textDivs[i];
+ if (textDiv.dataset.isWhitespace !== undefined) {
+ continue;
+ }
- if (width > 0) {
- textLayerFrag.appendChild(textDiv);
- var textScale = textDiv.dataset.canvasWidth / width;
- var rotation = textDiv.dataset.angle;
- var transform = 'scale(' + textScale + ', 1)';
- transform = 'rotate(' + rotation + 'deg) ' + transform;
- CustomStyle.setProp('transform' , textDiv, transform);
- CustomStyle.setProp('transformOrigin' , textDiv, '0% 0%');
+ 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);
+ }
+ }
}
- }
- textLayerDiv.appendChild(textLayerFrag);
- this.renderingDone = true;
- this.updateMatches();
- };
+ this.textLayerDiv.appendChild(textLayerFrag);
+ this.renderingDone = true;
+ this.updateMatches();
+ },
- this.setupRenderLayoutTimer = function textLayerSetupRenderLayoutTimer() {
- // Schedule renderLayout() if user has been scrolling, otherwise
- // run it right away
- var RENDER_DELAY = 200; // in ms
- var self = this;
- var lastScroll = this.lastScrollSource === null ?
- 0 : this.lastScrollSource.lastScroll;
+ setupRenderLayoutTimer:
+ function TextLayerBuilder_setupRenderLayoutTimer() {
+ // Schedule renderLayout() if the user has been scrolling,
+ // otherwise run it right away.
+ var self = this;
+ var lastScroll = (this.lastScrollSource === null ?
+ 0 : this.lastScrollSource.lastScroll);
- if (Date.now() - lastScroll > RENDER_DELAY) {
- // Render right away
- this.renderLayer();
- } else {
- // Schedule
- if (this.renderTimer)
- clearTimeout(this.renderTimer);
- this.renderTimer = setTimeout(function() {
- self.setupRenderLayoutTimer();
- }, RENDER_DELAY);
- }
- };
+ if (Date.now() - lastScroll > RENDER_DELAY) { // Render right away
+ this.renderLayer();
+ } else { // Schedule
+ if (this.renderTimer) {
+ clearTimeout(this.renderTimer);
+ }
+ this.renderTimer = setTimeout(function() {
+ self.setupRenderLayoutTimer();
+ }, RENDER_DELAY);
+ }
+ },
- this.appendText = function textLayerBuilderAppendText(geom) {
- var textDiv = document.createElement('div');
-
- // vScale and hScale already contain the scaling to pixel units
- var fontHeight = geom.fontSize * Math.abs(geom.vScale);
- textDiv.dataset.canvasWidth = geom.canvasWidth * Math.abs(geom.hScale);
- textDiv.dataset.fontName = geom.fontName;
- textDiv.dataset.angle = geom.angle * (180 / Math.PI);
-
- textDiv.style.fontSize = fontHeight + 'px';
- textDiv.style.fontFamily = geom.fontFamily;
- var fontAscent = geom.ascent ? geom.ascent * fontHeight :
- geom.descent ? (1 + geom.descent) * fontHeight : fontHeight;
- textDiv.style.left = (geom.x + (fontAscent * Math.sin(geom.angle))) + 'px';
- textDiv.style.top = (geom.y - (fontAscent * Math.cos(geom.angle))) + 'px';
-
- // The content of the div is set in the `setTextContent` function.
-
- this.textDivs.push(textDiv);
- };
-
- this.insertDivContent = function textLayerUpdateTextContent() {
- // Only set the content of the divs once layout has finished, the content
- // for the divs is available and content is not yet set on the divs.
- if (!this.layoutDone || this.divContentDone || !this.textContent)
- return;
-
- this.divContentDone = true;
-
- var textDivs = this.textDivs;
- var bidiTexts = this.textContent;
-
- for (var i = 0; i < bidiTexts.length; i++) {
- var bidiText = bidiTexts[i];
- var textDiv = textDivs[i];
- if (!/\S/.test(bidiText.str)) {
+ 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;
- continue;
+ 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;
}
- textDiv.textContent = bidiText.str;
- // TODO refactor text layer to use text content position
- /**
- * var arr = this.viewport.convertToViewportPoint(bidiText.x, bidiText.y);
- * textDiv.style.left = arr[0] + 'px';
- * textDiv.style.top = arr[1] + 'px';
- */
- // bidiText.dir may be 'ttb' for vertical texts.
- textDiv.dir = bidiText.dir;
- }
-
- this.setupRenderLayoutTimer();
- };
-
- this.setTextContent = function textLayerBuilderSetTextContent(textContent) {
- this.textContent = textContent;
- this.insertDivContent();
- };
-
- this.convertMatches = function textLayerBuilderConvertMatches(matches) {
- var i = 0;
- var iIndex = 0;
- var bidiTexts = this.textContent;
- var end = bidiTexts.length - 1;
- var queryLen = PDFFindController === null ?
- 0 : PDFFindController.state.query.length;
-
- var lastDivIdx = -1;
- var pos;
-
- var ret = [];
-
- // Loop over all the matches.
- for (var m = 0; m < matches.length; m++) {
- var matchIdx = matches[m];
- // # Calculate the begin position.
-
- // Loop over the divIdxs.
- while (i !== end && matchIdx >= (iIndex + bidiTexts[i].str.length)) {
- iIndex += bidiTexts[i].str.length;
- i++;
+ 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;
- // TODO: Do proper handling here if something goes wrong.
- if (i == bidiTexts.length) {
- console.error('Could not find matching mapping');
+ 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;
+ }
+ }
+ },
- var match = {
- begin: {
+ 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;
+ this.setupRenderLayoutTimer();
+ },
+
+ 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
- }
- };
-
- // # Calculate the end position.
- matchIdx += queryLen;
-
- // Somewhat same array as above, but use a > instead of >= to get the end
- // position right.
- while (i !== end && matchIdx > (iIndex + bidiTexts[i].str.length)) {
- iIndex += bidiTexts[i].str.length;
- i++;
+ };
+ ret.push(match);
}
- match.end = {
- divIdx: i,
- offset: matchIdx - iIndex
- };
- ret.push(match);
- }
+ return ret;
+ },
- return ret;
- };
-
- this.renderMatches = function textLayerBuilder_renderMatches(matches) {
- // Early exit if there is nothing to render.
- if (matches.length === 0) {
- return;
- }
-
- var bidiTexts = this.textContent;
- var textDivs = this.textDivs;
- var prevEnd = null;
- var isSelectedPage = PDFFindController === null ?
- false : (this.pageIdx === PDFFindController.selected.pageIdx);
-
- var selectedMatchIdx = PDFFindController === null ?
- -1 : PDFFindController.selected.matchIdx;
-
- var highlightAll = PDFFindController === null ?
- false : PDFFindController.state.highlightAll;
-
- var infty = {
- divIdx: -1,
- offset: undefined
- };
-
- function beginText(begin, className) {
- var divIdx = begin.divIdx;
- var div = textDivs[divIdx];
- div.textContent = '';
-
- var content = bidiTexts[divIdx].str.substring(0, begin.offset);
- var node = document.createTextNode(content);
- if (className) {
- var isSelected = isSelectedPage &&
- divIdx === selectedMatchIdx;
- var span = document.createElement('span');
- span.className = className + (isSelected ? ' selected' : '');
- span.appendChild(node);
- div.appendChild(span);
+ renderMatches: function TextLayerBuilder_renderMatches(matches) {
+ // Early exit if there is nothing to render.
+ if (matches.length === 0) {
return;
}
- div.appendChild(node);
- }
- function appendText(from, to, className) {
- var divIdx = from.divIdx;
- var div = textDivs[divIdx];
+ var bidiTexts = this.textContent.items;
+ var textDivs = this.textDivs;
+ var prevEnd = null;
+ var isSelectedPage = (this.findController === null ?
+ false : (this.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
+ };
- var content = bidiTexts[divIdx].str.substring(from.offset, to.offset);
- var node = document.createTextNode(content);
- if (className) {
- var span = document.createElement('span');
- span.className = className;
- span.appendChild(node);
- div.appendChild(span);
+ 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;
}
- div.appendChild(node);
- }
- function highlightDiv(divIdx, className) {
- textDivs[divIdx].className = className;
- }
+ 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' : '');
- var i0 = selectedMatchIdx, i1 = i0 + 1, i;
-
- 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 (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 (isSelected && !this.isViewerInPresentationMode) {
- scrollIntoView(textDivs[begin.divIdx], { top: FIND_SCROLL_OFFSET_TOP,
- left: FIND_SCROLL_OFFSET_LEFT });
- }
-
- // 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) {
- appendText(prevEnd, infty);
+ if (isSelected && !this.isViewerInPresentationMode) {
+ scrollIntoView(textDivs[begin.divIdx],
+ { top: FIND_SCROLL_OFFSET_TOP,
+ left: FIND_SCROLL_OFFSET_LEFT });
}
- // clears the divs and set the content until the begin point.
- beginText(begin);
- } else {
- appendText(prevEnd, begin);
- }
- if (begin.divIdx === end.divIdx) {
- appendText(begin, end, 'highlight' + highlightSuffix);
- } else {
- appendText(begin, infty, 'highlight begin' + highlightSuffix);
- for (var n = begin.divIdx + 1; n < end.divIdx; n++) {
- highlightDiv(n, 'highlight middle' + highlightSuffix);
+ // 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);
}
- beginText(end, 'highlight end' + highlightSuffix);
- }
- prevEnd = end;
- }
- if (prevEnd) {
- appendText(prevEnd, infty);
+ 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);
}
};
-
- this.updateMatches = function textLayerUpdateMatches() {
- // Only show matches, once all rendering is done.
- if (!this.renderingDone)
- return;
-
- // Clear out all matches.
- var matches = this.matches;
- var textDivs = this.textDivs;
- var bidiTexts = this.textContent;
- var clearedUntilDivIdx = -1;
-
- // Clear out all current matches.
- for (var i = 0; i < matches.length; i++) {
- var match = matches[i];
- var begin = Math.max(clearedUntilDivIdx, match.begin.divIdx);
- for (var n = begin; n <= match.end.divIdx; n++) {
- var div = textDivs[n];
- div.textContent = bidiTexts[n].str;
- div.className = '';
- }
- clearedUntilDivIdx = match.end.divIdx + 1;
- }
-
- if (PDFFindController === null || !PDFFindController.active)
- return;
-
- // Convert the matches on the page controller into the match format used
- // for the textLayer.
- this.matches = matches =
- this.convertMatches(PDFFindController === null ?
- [] : (PDFFindController.pageMatches[this.pageIdx] || []));
-
- this.renderMatches(this.matches);
- };
-};
-
+ return TextLayerBuilder;
+})();
diff --git a/attachment_preview/static/lib/ViewerJS/ui_utils.js b/attachment_preview/static/lib/ViewerJS/ui_utils.js
index c832dc7a..b4f2d736 100644
--- a/attachment_preview/static/lib/ViewerJS/ui_utils.js
+++ b/attachment_preview/static/lib/ViewerJS/ui_utils.js
@@ -16,6 +16,14 @@
'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;
+var DEFAULT_CACHE_SIZE = 10;
+
// optimised CSS custom property getter/setter
var CustomStyle = (function CustomStyleClosure() {
@@ -24,14 +32,13 @@ var CustomStyle = (function CustomStyleClosure() {
// in some versions of IE9 it is critical that ms appear in this list
// before Moz
var prefixes = ['ms', 'Moz', 'Webkit', 'O'];
- var _cache = { };
+ var _cache = {};
- function CustomStyle() {
- }
+ function CustomStyle() {}
CustomStyle.getProp = function get(propName, element) {
// check cache only when no element is given
- if (arguments.length == 1 && typeof _cache[propName] == 'string') {
+ if (arguments.length === 1 && typeof _cache[propName] === 'string') {
return _cache[propName];
}
@@ -39,7 +46,7 @@ var CustomStyle = (function CustomStyleClosure() {
var style = element.style, prefixed, uPropName;
// test standard property first
- if (typeof style[propName] == 'string') {
+ if (typeof style[propName] === 'string') {
return (_cache[propName] = propName);
}
@@ -49,7 +56,7 @@ var CustomStyle = (function CustomStyleClosure() {
// test vendor specific properties
for (var i = 0, l = prefixes.length; i < l; i++) {
prefixed = prefixes[i] + uPropName;
- if (typeof style[prefixed] == 'string') {
+ if (typeof style[prefixed] === 'string') {
return (_cache[propName] = prefixed);
}
}
@@ -60,8 +67,9 @@ var CustomStyle = (function CustomStyleClosure() {
CustomStyle.setProp = function set(propName, element, str) {
var prop = this.getProp(propName);
- if (prop != 'undefined')
+ if (prop !== 'undefined') {
element.style[prop] = str;
+ }
};
return CustomStyle;
@@ -93,7 +101,7 @@ function getOutputScale(ctx) {
return {
sx: pixelRatio,
sy: pixelRatio,
- scaled: pixelRatio != 1
+ scaled: pixelRatio !== 1
};
}
@@ -138,6 +146,91 @@ function scrollIntoView(element, spot) {
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 = true;
+ } else if (currentY < lastY) {
+ state.down = false;
+ }
+ state.lastY = currentY;
+ // else do nothing and use previous value
+ callback(state);
+ });
+ };
+
+ var state = {
+ down: true,
+ lastY: viewAreaElement.scrollTop,
+ _eventHandler: debounceScroll
+ };
+
+ var rAF = null;
+ viewAreaElement.addEventListener('scroll', debounceScroll, true);
+ return state;
+}
+
+/**
+ * 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;
+
+ var visible = [], view;
+ var currentHeight, viewHeight, hiddenHeight, percentHeight;
+ var currentWidth, viewWidth;
+ for (var i = 0, ii = views.length; i < ii; ++i) {
+ view = views[i];
+ currentHeight = view.el.offsetTop + view.el.clientTop;
+ viewHeight = view.el.clientHeight;
+ if ((currentHeight + viewHeight) < top) {
+ continue;
+ }
+ if (currentHeight > bottom) {
+ break;
+ }
+ currentWidth = view.el.offsetLeft + view.el.clientLeft;
+ viewWidth = view.el.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.
*/
@@ -161,7 +254,7 @@ function getPDFFileNameFromURL(url) {
reFilename.exec(splitURI[3]);
if (suggestedFilename) {
suggestedFilename = suggestedFilename[0];
- if (suggestedFilename.indexOf('%') != -1) {
+ if (suggestedFilename.indexOf('%') !== -1) {
// URL-encoded %2Fpath%2Fto%2Ffile.pdf should be file.pdf
try {
suggestedFilename =
@@ -182,6 +275,7 @@ var ProgressBar = (function ProgressBarClosure() {
}
function ProgressBar(id, opts) {
+ this.visible = true;
// Fetch the sub-elements for later.
this.div = document.querySelector(id + ' .progress');
@@ -235,8 +329,21 @@ var ProgressBar = (function ProgressBarClosure() {
},
hide: function ProgressBar_hide() {
+ if (!this.visible) {
+ return;
+ }
+ this.visible = false;
this.bar.classList.add('hidden');
- this.bar.removeAttribute('style');
+ 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');
}
};
@@ -247,24 +354,18 @@ var Cache = function cacheCache(size) {
var data = [];
this.push = function cachePush(view) {
var i = data.indexOf(view);
- if (i >= 0)
- data.splice(i);
+ if (i >= 0) {
+ data.splice(i, 1);
+ }
data.push(view);
- if (data.length > size)
+ if (data.length > size) {
data.shift().destroy();
+ }
+ };
+ this.resize = function (newSize) {
+ size = newSize;
+ while (data.length > size) {
+ data.shift().destroy();
+ }
};
};
-
-//#if !(FIREFOX || MOZCENTRAL || B2G)
-var isLocalStorageEnabled = (function isLocalStorageEnabledClosure() {
- // Feature test as per http://diveintohtml5.info/storage.html
- // The additional localStorage call is to get around a FF quirk, see
- // bug #495747 in bugzilla
- try {
- return ('localStorage' in window && window['localStorage'] !== null &&
- localStorage);
- } catch (e) {
- return false;
- }
-})();
-//#endif
diff --git a/attachment_preview/static/lib/ViewerJS/viewer.css b/attachment_preview/static/lib/ViewerJS/viewer.css
deleted file mode 100644
index 4edb1c26..00000000
--- a/attachment_preview/static/lib/ViewerJS/viewer.css
+++ /dev/null
@@ -1,812 +0,0 @@
-/**
- * Copyright (C) 2012-2014 KO GmbH
- *
- * @licstart
- * This file is part of WebODF.
- *
- * WebODF 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.
- *
- * WebODF is distributed in the hope that 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 .
- * @licend
- *
- * @source: http://www.webodf.org/
- * @source: https://github.com/kogmbh/WebODF/
- */
-
-/*
- * This file is a derivative from a part of Mozilla's PDF.js project. The
- * original license header follows.
- */
-
-/* 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.
- */
-
-* {
- padding: 0;
- margin: 0;
-}
-
-html > body {
- font-family: sans-serif;
- overflow: hidden;
-}
-
-.titlebar > span,
-.toolbarLabel,
-input,
-button,
-select {
- font: message-box;
-}
-
-#titlebar {
- position: absolute;
- z-index: 2;
- top: 0px;
- left: 0px;
- height: 32px;
- width: 100%;
- overflow: hidden;
-
- -webkit-box-shadow: 0px 1px 3px rgba(50, 50, 50, 0.75);
- -moz-box-shadow: 0px 1px 3px rgba(50, 50, 50, 0.75);
- box-shadow: 0px 1px 3px rgba(50, 50, 50, 0.75);
-
- background-image: url(images/texture.png), linear-gradient(rgba(69, 69, 69, .95), rgba(82, 82, 82, .99));
- background-image: url(images/texture.png), -webkit-linear-gradient(rgba(69, 69, 69, .95), rgba(82, 82, 82, .99));
- background-image: url(images/texture.png), -moz-linear-gradient(rgba(69, 69, 69, .95), rgba(82, 82, 82, .99));
- background-image: url(images/texture.png), -ms-linear-gradient(rgba(69, 69, 69, .95), rgba(82, 82, 82, .99));
- background-image: url(images/texture.png), -o-linear-gradient(rgba(69, 69, 69, .95), rgba(82, 82, 82, .99));
-}
-
-#titlebar a, #aboutDialog a, #titlebar a:visited, #aboutDialog a:visited {
- color: #ccc;
-}
-
-#documentName {
- margin-right: 10px;
- margin-left: 10px;
- margin-top: 8px;
- color: #F2F2F2;
- line-height: 14px;
- font-family: sans-serif;
-}
-#documentName {
- font-size: 14px;
-}
-
-#toolbarContainer {
- position: absolute;
- z-index: 2;
- bottom: 0px;
- left: 0px;
- height: 32px;
- width: 100%;
- overflow: hidden;
-
- -webkit-box-shadow: 0px -1px 3px rgba(50, 50, 50, 0.75);
- -moz-box-shadow: 0px -1px 3px rgba(50, 50, 50, 0.75);
- box-shadow: 0px -1px 3px rgba(50, 50, 50, 0.75);
-
- background-image: url(images/texture.png), linear-gradient(rgba(82, 82, 82, .99), rgba(69, 69, 69, .95));
- background-image: url(images/texture.png), -webkit-linear-gradient(rgba(82, 82, 82, .99), rgba(69, 69, 69, .95));
- background-image: url(images/texture.png), -moz-linear-gradient(rgba(82, 82, 82, .99), rgba(69, 69, 69, .95));
- background-image: url(images/texture.png), -ms-linear-gradient(rgba(82, 82, 82, .99), rgba(69, 69, 69, .95));
- background-image: url(images/texture.png), -o-linear-gradient(rgba(82, 82, 82, .99), rgba(69, 69, 69, .95));
-}
-
-#toolbar {
- position: relative;
-}
-
-#toolbarMiddleContainer, #toolbarLeft {
- visibility: hidden;
-}
-
-html[dir='ltr'] #toolbarLeft {
- margin-left: -1px;
-}
-html[dir='rtl'] #toolbarRight {
- margin-left: -1px;
-}
-html[dir='ltr'] #toolbarLeft,
-html[dir='rtl'] #toolbarRight {
- position: absolute;
- top: 0;
- left: 0;
-}
-html[dir='ltr'] #toolbarRight,
-html[dir='rtl'] #toolbarLeft {
- position: absolute;
- top: 0;
- right: 0;
-}
-html[dir='ltr'] #toolbarLeft > *,
-html[dir='ltr'] #toolbarMiddle > *,
-html[dir='ltr'] #toolbarRight > * {
- float: left;
-}
-html[dir='rtl'] #toolbarLeft > *,
-html[dir='rtl'] #toolbarMiddle > *,
-html[dir='rtl'] #toolbarRight > * {
- float: right;
-}
-
-/* outer/inner center provides horizontal center */
-html[dir='ltr'] .outerCenter {
- float: right;
- position: relative;
- right: 50%;
-}
-html[dir='rtl'] .outerCenter {
- float: left;
- position: relative;
- left: 50%;
-}
-html[dir='ltr'] .innerCenter {
- float: right;
- position: relative;
- right: -50%;
-}
-html[dir='rtl'] .innerCenter {
- float: left;
- position: relative;
- left: -50%;
-}
-
-html[dir='ltr'] .splitToolbarButton {
- margin: 3px 2px 4px 0;
- display: inline-block;
-}
-html[dir='rtl'] .splitToolbarButton {
- margin: 3px 0 4px 2px;
- display: inline-block;
-}
-html[dir='ltr'] .splitToolbarButton > .toolbarButton {
- border-radius: 0;
- float: left;
-}
-html[dir='rtl'] .splitToolbarButton > .toolbarButton {
- border-radius: 0;
- float: right;
-}
-
-.splitToolbarButton.toggled .toolbarButton {
- margin: 0;
-}
-
-.toolbarButton {
- border: 0 none;
- background-color: rgba(0, 0, 0, 0);
- min-width: 32px;
- height: 25px;
- border-radius: 2px;
- background-image: none;
-}
-
-html[dir='ltr'] .toolbarButton,
-html[dir='ltr'] .dropdownToolbarButton {
- margin: 3px 2px 4px 0;
-}
-html[dir='rtl'] .toolbarButton,
-html[dir='rtl'] .dropdownToolbarButton {
- margin: 3px 0 4px 2px;
-}
-
-.toolbarButton:hover,
-.toolbarButton:focus,
-.dropdownToolbarButton {
- background-color: hsla(0,0%,0%,.12);
- background-image: linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
- background-image: -webkit-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
- background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
- background-image: -ms-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
- background-image: -o-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
- background-clip: padding-box;
- border: 1px solid hsla(0,0%,0%,.35);
- border-color: hsla(0,0%,0%,.32) hsla(0,0%,0%,.38) hsla(0,0%,0%,.42);
- box-shadow: 0 1px 0 hsla(0,0%,100%,.05) inset,
- 0 0 1px hsla(0,0%,100%,.15) inset,
- 0 1px 0 hsla(0,0%,100%,.05);
-}
-
-.toolbarButton:hover:active,
-.dropdownToolbarButton:hover:active {
- background-color: hsla(0,0%,0%,.2);
- background-image: linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
- background-image: -webkit-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
- background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
- background-image: -ms-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
- background-image: -o-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
- border-color: hsla(0,0%,0%,.35) hsla(0,0%,0%,.4) hsla(0,0%,0%,.45);
- box-shadow: 0 1px 1px hsla(0,0%,0%,.1) inset,
- 0 0 1px hsla(0,0%,0%,.2) inset,
- 0 1px 0 hsla(0,0%,100%,.05);
-}
-
-.splitToolbarButton:hover > .toolbarButton,
-.splitToolbarButton:focus > .toolbarButton,
-.splitToolbarButton.toggled > .toolbarButton,
-.toolbarButton.textButton {
- background-color: hsla(0,0%,0%,.12);
- background-image: -webkit-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
- background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
- background-image: -ms-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
- background-image: -o-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
- background-image: linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
- background-clip: padding-box;
- border: 1px solid hsla(0,0%,0%,.35);
- border-color: hsla(0,0%,0%,.32) hsla(0,0%,0%,.38) hsla(0,0%,0%,.42);
- box-shadow: 0 1px 0 hsla(0,0%,100%,.05) inset,
- 0 0 1px hsla(0,0%,100%,.15) inset,
- 0 1px 0 hsla(0,0%,100%,.05);
- -webkit-transition-property: background-color, border-color, box-shadow;
- -webkit-transition-duration: 150ms;
- -webkit-transition-timing-function: ease;
- -moz-transition-property: background-color, border-color, box-shadow;
- -moz-transition-duration: 150ms;
- -moz-transition-timing-function: ease;
- -ms-transition-property: background-color, border-color, box-shadow;
- -ms-transition-duration: 150ms;
- -ms-transition-timing-function: ease;
- -o-transition-property: background-color, border-color, box-shadow;
- -o-transition-duration: 150ms;
- -o-transition-timing-function: ease;
- transition-property: background-color, border-color, box-shadow;
- transition-duration: 150ms;
- transition-timing-function: ease;
-
-}
-.splitToolbarButton > .toolbarButton:hover,
-.splitToolbarButton > .toolbarButton:focus,
-.dropdownToolbarButton:hover,
-.toolbarButton.textButton:hover,
-.toolbarButton.textButton:focus {
- background-color: hsla(0,0%,0%,.2);
- box-shadow: 0 1px 0 hsla(0,0%,100%,.05) inset,
- 0 0 1px hsla(0,0%,100%,.15) inset,
- 0 0 1px hsla(0,0%,0%,.05);
- z-index: 199;
-}
-
-
-.splitToolbarButton:hover > .toolbarButton,
-.splitToolbarButton:focus > .toolbarButton,
-.splitToolbarButton.toggled > .toolbarButton,
-.toolbarButton.textButton {
- background-color: hsla(0,0%,0%,.12);
- background-image: -webkit-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
- background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
- background-image: -ms-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
- background-image: -o-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
- background-image: linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
- background-clip: padding-box;
- border: 1px solid hsla(0,0%,0%,.35);
- border-color: hsla(0,0%,0%,.32) hsla(0,0%,0%,.38) hsla(0,0%,0%,.42);
- box-shadow: 0 1px 0 hsla(0,0%,100%,.05) inset,
- 0 0 1px hsla(0,0%,100%,.15) inset,
- 0 1px 0 hsla(0,0%,100%,.05);
- -webkit-transition-property: background-color, border-color, box-shadow;
- -webkit-transition-duration: 150ms;
- -webkit-transition-timing-function: ease;
- -moz-transition-property: background-color, border-color, box-shadow;
- -moz-transition-duration: 150ms;
- -moz-transition-timing-function: ease;
- -ms-transition-property: background-color, border-color, box-shadow;
- -ms-transition-duration: 150ms;
- -ms-transition-timing-function: ease;
- -o-transition-property: background-color, border-color, box-shadow;
- -o-transition-duration: 150ms;
- -o-transition-timing-function: ease;
- transition-property: background-color, border-color, box-shadow;
- transition-duration: 150ms;
- transition-timing-function: ease;
-
-}
-.splitToolbarButton > .toolbarButton:hover,
-.splitToolbarButton > .toolbarButton:focus,
-.dropdownToolbarButton:hover,
-.toolbarButton.textButton:hover,
-.toolbarButton.textButton:focus {
- background-color: hsla(0,0%,0%,.2);
- box-shadow: 0 1px 0 hsla(0,0%,100%,.05) inset,
- 0 0 1px hsla(0,0%,100%,.15) inset,
- 0 0 1px hsla(0,0%,0%,.05);
- z-index: 199;
-}
-
-.dropdownToolbarButton {
- border: 1px solid #333 !important;
-}
-
-.toolbarButton,
-.dropdownToolbarButton {
- min-width: 16px;
- padding: 2px 6px 2px;
- border: 1px solid transparent;
- border-radius: 2px;
- color: hsl(0,0%,95%);
- font-size: 12px;
- line-height: 14px;
- -webkit-user-select:none;
- -moz-user-select:none;
- -ms-user-select:none;
- /* Opera does not support user-select, use <... unselectable="on"> instead */
- cursor: default;
- -webkit-transition-property: background-color, border-color, box-shadow;
- -webkit-transition-duration: 150ms;
- -webkit-transition-timing-function: ease;
- -moz-transition-property: background-color, border-color, box-shadow;
- -moz-transition-duration: 150ms;
- -moz-transition-timing-function: ease;
- -ms-transition-property: background-color, border-color, box-shadow;
- -ms-transition-duration: 150ms;
- -ms-transition-timing-function: ease;
- -o-transition-property: background-color, border-color, box-shadow;
- -o-transition-duration: 150ms;
- -o-transition-timing-function: ease;
- transition-property: background-color, border-color, box-shadow;
- transition-duration: 150ms;
- transition-timing-function: ease;
-}
-
-html[dir='ltr'] .toolbarButton,
-html[dir='ltr'] .dropdownToolbarButton {
- margin: 3px 2px 4px 0;
-}
-html[dir='rtl'] .toolbarButton,
-html[dir='rtl'] .dropdownToolbarButton {
- margin: 3px 0 4px 2px;
-}
-
-.splitToolbarButton:hover > .splitToolbarButtonSeparator,
-.splitToolbarButton.toggled > .splitToolbarButtonSeparator {
- padding: 12px 0;
- margin: 0;
- box-shadow: 0 0 0 1px hsla(0,0%,100%,.03);
- -webkit-transition-property: padding;
- -webkit-transition-duration: 10ms;
- -webkit-transition-timing-function: ease;
- -moz-transition-property: padding;
- -moz-transition-duration: 10ms;
- -moz-transition-timing-function: ease;
- -ms-transition-property: padding;
- -ms-transition-duration: 10ms;
- -ms-transition-timing-function: ease;
- -o-transition-property: padding;
- -o-transition-duration: 10ms;
- -o-transition-timing-function: ease;
- transition-property: padding;
- transition-duration: 10ms;
- transition-timing-function: ease;
-}
-
-.toolbarButton.toggled:hover:active,
-.splitToolbarButton > .toolbarButton:hover:active {
- background-color: hsla(0,0%,0%,.4);
- border-color: hsla(0,0%,0%,.4) hsla(0,0%,0%,.5) hsla(0,0%,0%,.55);
- box-shadow: 0 1px 1px hsla(0,0%,0%,.2) inset,
- 0 0 1px hsla(0,0%,0%,.3) inset,
- 0 1px 0 hsla(0,0%,100%,.05);
-}
-
-html[dir='ltr'] .splitToolbarButton > .toolbarButton:first-child,
-html[dir='rtl'] .splitToolbarButton > .toolbarButton:last-child {
- position: relative;
- margin: 0;
- margin-left: 4px;
- margin-right: -1px;
- border-top-left-radius: 2px;
- border-bottom-left-radius: 2px;
- border-right-color: transparent;
-}
-html[dir='ltr'] .splitToolbarButton > .toolbarButton:last-child,
-html[dir='rtl'] .splitToolbarButton > .toolbarButton:first-child {
- position: relative;
- margin: 0;
- margin-left: -1px;
- border-top-right-radius: 2px;
- border-bottom-right-radius: 2px;
- border-left-color: transparent;
-}
-.splitToolbarButtonSeparator {
- padding: 8px 0;
- width: 1px;
- background-color: hsla(0,0%,00%,.5);
- z-index: 99;
- box-shadow: 0 0 0 1px hsla(0,0%,100%,.08);
- display: inline-block;
- margin: 5px 0;
-}
-html[dir='ltr'] .splitToolbarButtonSeparator {
- float:left;
-}
-html[dir='rtl'] .splitToolbarButtonSeparator {
- float:right;
-}
-
-.dropdownToolbarButton {
- min-width: 120px;
- max-width: 120px;
- padding: 4px 2px 4px;
- overflow: hidden;
- background: url(images/toolbarButton-menuArrows.png) no-repeat;
-}
-
-.dropdownToolbarButton > select {
- -webkit-appearance: none;
- -moz-appearance: none; /* in the future this might matter, see bugzilla bug #649849 */
- min-width: 140px;
- font-size: 12px;
- color: hsl(0,0%,95%);
- margin:0;
- padding:0;
- border:none;
- background: rgba(0,0,0,0); /* Opera does not support 'transparent'