From 2ead898a685baf0e0168ec1b9fecd4a15fb8c26d Mon Sep 17 00:00:00 2001 From: Holger Brunn Date: Thu, 15 Jan 2015 11:17:18 +0100 Subject: [PATCH 01/41] [ADD] preliminary port of attachment_preview --- attachment_preview/__init__.py | 21 + attachment_preview/__openerp__.py | 59 + attachment_preview/model/__init__.py | 21 + attachment_preview/model/ir_attachment.py | 68 + .../static/description/icon.png | Bin 0 -> 14657 bytes .../static/lib/ViewerJS/AGPL-3.0.txt | 661 + .../static/lib/ViewerJS/ODFViewerPlugin.css | 29 + .../static/lib/ViewerJS/ODFViewerPlugin.js | 219 + .../static/lib/ViewerJS/PDFViewerPlugin.css | 36 + .../static/lib/ViewerJS/PDFViewerPlugin.js | 364 + .../static/lib/ViewerJS/PluginLoader.js | 86 + .../static/lib/ViewerJS/compatibility.js | 491 + .../static/lib/ViewerJS/example.local.css | 27 + .../static/lib/ViewerJS/images/kogmbh.png | Bin 0 -> 2835 bytes .../static/lib/ViewerJS/images/nlnet.png | Bin 0 -> 5400 bytes .../static/lib/ViewerJS/images/texture.png | Bin 0 -> 2459 bytes .../images/toolbarButton-download.png | Bin 0 -> 512 bytes .../images/toolbarButton-fullscreen.png | Bin 0 -> 491 bytes .../images/toolbarButton-menuArrows.png | Bin 0 -> 237 bytes .../images/toolbarButton-pageDown.png | Bin 0 -> 353 bytes .../ViewerJS/images/toolbarButton-pageUp.png | Bin 0 -> 344 bytes .../images/toolbarButton-presentation.png | Bin 0 -> 4366 bytes .../ViewerJS/images/toolbarButton-zoomIn.png | Bin 0 -> 228 bytes .../ViewerJS/images/toolbarButton-zoomOut.png | Bin 0 -> 143 bytes .../static/lib/ViewerJS/index.html | 131 + attachment_preview/static/lib/ViewerJS/pdf.js | 7651 +++ .../static/lib/ViewerJS/pdf.worker.js | 39900 ++++++++++++++++ .../static/lib/ViewerJS/pdf_find_bar.js | 175 + .../lib/ViewerJS/pdf_find_controller.js | 355 + .../static/lib/ViewerJS/pdfjsversion.js | 1 + .../static/lib/ViewerJS/text_layer_builder.js | 385 + .../static/lib/ViewerJS/ui_utils.js | 270 + .../static/lib/ViewerJS/viewer.css | 801 + .../static/lib/ViewerJS/viewer.js | 16 + .../static/lib/ViewerJS/webodf.js | 631 + .../static/src/css/attachment_preview.css | 26 + .../static/src/js/attachment_preview.js | 233 + .../static/src/js/viewerjs_tweaks.js | 40 + .../static/src/xml/attachment_preview.xml | 15 + .../view/attachment_preview.xml | 11 + 40 files changed, 52723 insertions(+) create mode 100644 attachment_preview/__init__.py create mode 100644 attachment_preview/__openerp__.py create mode 100644 attachment_preview/model/__init__.py create mode 100644 attachment_preview/model/ir_attachment.py create mode 100644 attachment_preview/static/description/icon.png create mode 100644 attachment_preview/static/lib/ViewerJS/AGPL-3.0.txt create mode 100644 attachment_preview/static/lib/ViewerJS/ODFViewerPlugin.css create mode 100644 attachment_preview/static/lib/ViewerJS/ODFViewerPlugin.js create mode 100644 attachment_preview/static/lib/ViewerJS/PDFViewerPlugin.css create mode 100644 attachment_preview/static/lib/ViewerJS/PDFViewerPlugin.js create mode 100644 attachment_preview/static/lib/ViewerJS/PluginLoader.js create mode 100644 attachment_preview/static/lib/ViewerJS/compatibility.js create mode 100644 attachment_preview/static/lib/ViewerJS/example.local.css create mode 100644 attachment_preview/static/lib/ViewerJS/images/kogmbh.png create mode 100644 attachment_preview/static/lib/ViewerJS/images/nlnet.png create mode 100644 attachment_preview/static/lib/ViewerJS/images/texture.png create mode 100644 attachment_preview/static/lib/ViewerJS/images/toolbarButton-download.png create mode 100644 attachment_preview/static/lib/ViewerJS/images/toolbarButton-fullscreen.png create mode 100644 attachment_preview/static/lib/ViewerJS/images/toolbarButton-menuArrows.png create mode 100644 attachment_preview/static/lib/ViewerJS/images/toolbarButton-pageDown.png create mode 100644 attachment_preview/static/lib/ViewerJS/images/toolbarButton-pageUp.png create mode 100644 attachment_preview/static/lib/ViewerJS/images/toolbarButton-presentation.png create mode 100644 attachment_preview/static/lib/ViewerJS/images/toolbarButton-zoomIn.png create mode 100644 attachment_preview/static/lib/ViewerJS/images/toolbarButton-zoomOut.png create mode 100644 attachment_preview/static/lib/ViewerJS/index.html create mode 100644 attachment_preview/static/lib/ViewerJS/pdf.js create mode 100644 attachment_preview/static/lib/ViewerJS/pdf.worker.js create mode 100644 attachment_preview/static/lib/ViewerJS/pdf_find_bar.js create mode 100644 attachment_preview/static/lib/ViewerJS/pdf_find_controller.js create mode 100644 attachment_preview/static/lib/ViewerJS/pdfjsversion.js create mode 100644 attachment_preview/static/lib/ViewerJS/text_layer_builder.js create mode 100644 attachment_preview/static/lib/ViewerJS/ui_utils.js create mode 100644 attachment_preview/static/lib/ViewerJS/viewer.css create mode 100644 attachment_preview/static/lib/ViewerJS/viewer.js create mode 100644 attachment_preview/static/lib/ViewerJS/webodf.js create mode 100644 attachment_preview/static/src/css/attachment_preview.css create mode 100644 attachment_preview/static/src/js/attachment_preview.js create mode 100644 attachment_preview/static/src/js/viewerjs_tweaks.js create mode 100644 attachment_preview/static/src/xml/attachment_preview.xml create mode 100644 attachment_preview/view/attachment_preview.xml diff --git a/attachment_preview/__init__.py b/attachment_preview/__init__.py new file mode 100644 index 00000000000..fcf92314d85 --- /dev/null +++ b/attachment_preview/__init__.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# This module copyright (C) 2014 Therp BV (). +# +# 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 . +# +############################################################################## +from . import model diff --git a/attachment_preview/__openerp__.py b/attachment_preview/__openerp__.py new file mode 100644 index 00000000000..0f7f6efaa04 --- /dev/null +++ b/attachment_preview/__openerp__.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# This module copyright (C) 2014 Therp BV (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## +{ + "name": "Preview attachments", + "version": "1.1", + "author": "Therp BV", + "license": "AGPL-3", + "complexity": "normal", + "description": """ +This addon allows to preview attachments supported by http://viewerjs.org. + +Currently, that's most Libreoffice files and PDFs. + +For filetype recognition, you'll get the best results by installing +``python-magic``. + +Acknowledgements +================ + +Addon icon courtesy of http://commons.wikimedia.org/wiki/Crystal_Clear + """, + "category": "Knowledge Management", + "depends": [ + 'web', + 'document', + ], + "data": [ + "view/attachment_preview.xml", + ], + "qweb": [ + 'static/src/xml/attachment_preview.xml', + ], + "test": [ + ], + "auto_install": False, + "installable": True, + "application": False, + "external_dependencies": { + 'python': [], + }, +} diff --git a/attachment_preview/model/__init__.py b/attachment_preview/model/__init__.py new file mode 100644 index 00000000000..4466fe6dfca --- /dev/null +++ b/attachment_preview/model/__init__.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# This module copyright (C) 2014 Therp BV (). +# +# 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 . +# +############################################################################## +from . import ir_attachment diff --git a/attachment_preview/model/ir_attachment.py b/attachment_preview/model/ir_attachment.py new file mode 100644 index 00000000000..908247ff22a --- /dev/null +++ b/attachment_preview/model/ir_attachment.py @@ -0,0 +1,68 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# This module copyright (C) 2014 Therp BV (). +# +# 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 . +# +############################################################################## +import collections +import os.path +import mimetypes +import base64 +from openerp.osv.orm import Model + + +class IrAttachment(Model): + _inherit = 'ir.attachment' + + def get_binary_extension( + self, cr, uid, model, ids, binary_field, filename_field=None, + context=None): + result = {} + for this in self.pool[model].browse( + cr, uid, + ids if isinstance(ids, collections.Iterable) else [ids], + context=context): + if not this.id: + result[this.id] = False + continue + extension = '' + if filename_field and this[filename_field]: + filename, extension = os.path.splitext(this[filename_field]) + if not this[binary_field]: + result[this.id] = False + continue + if not extension: + try: + import magic + ms = magic.open( + hasattr(magic, 'MAGIC_MIME_TYPE') + and magic.MAGIC_MIME_TYPE or magic.MAGIC_MIME) + ms.load() + mimetype = ms.buffer( + base64.b64decode(this[binary_field])) + except ImportError: + (mimetype, encoding) = mimetypes.guess_type( + 'data:;base64,' + this[binary_field], strict=False) + extension = mimetypes.guess_extension( + mimetype.split(';')[0], strict=False) + + result[this.id] = (extension or '').lstrip('.').lower() + return result if isinstance(ids, collections.Iterable) else result[ids] + + def get_attachment_extension(self, cr, uid, ids, context=None): + return self.get_binary_extension( + cr, uid, self._name, ids, 'datas', 'datas_fname', context=context) diff --git a/attachment_preview/static/description/icon.png b/attachment_preview/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..b833a5ddb2e1da964985bb5670be1ba3047228bc GIT binary patch literal 14657 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 o|C=}Xe65BhS?IgtQm`L}XaGG;;l2d74;IRF3v literal 0 HcmV?d00001 diff --git a/attachment_preview/static/lib/ViewerJS/AGPL-3.0.txt b/attachment_preview/static/lib/ViewerJS/AGPL-3.0.txt new file mode 100644 index 00000000000..dba13ed2ddf --- /dev/null +++ b/attachment_preview/static/lib/ViewerJS/AGPL-3.0.txt @@ -0,0 +1,661 @@ + 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 new file mode 100644 index 00000000000..90f0dbe10dc --- /dev/null +++ b/attachment_preview/static/lib/ViewerJS/ODFViewerPlugin.css @@ -0,0 +1,29 @@ +/** + * 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 new file mode 100644 index 00000000000..0fa7da737e9 --- /dev/null +++ b/attachment_preview/static/lib/ViewerJS/ODFViewerPlugin.js @@ -0,0 +1,219 @@ +/** + * 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); + 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 new file mode 100644 index 00000000000..d1012783fc0 --- /dev/null +++ b/attachment_preview/static/lib/ViewerJS/PDFViewerPlugin.css @@ -0,0 +1,36 @@ +.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 new file mode 100644 index 00000000000..541447d8b34 --- /dev/null +++ b/attachment_preview/static/lib/ViewerJS/PDFViewerPlugin.js @@ -0,0 +1,364 @@ +/** + * @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 new file mode 100644 index 00000000000..4b285f2a090 --- /dev/null +++ b/attachment_preview/static/lib/ViewerJS/PluginLoader.js @@ -0,0 +1,86 @@ +/** + * @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 'odp': + case 'ods': + case 'fodt': + 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 new file mode 100644 index 00000000000..433e617af59 --- /dev/null +++ b/attachment_preview/static/lib/ViewerJS/compatibility.js @@ -0,0 +1,491 @@ +/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ +/* Copyright 2012 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* globals VBArray, PDFJS */ + +'use strict'; + +// Initializing PDFJS global object here, it case if we need to change/disable +// some PDF.js features, e.g. range requests +if (typeof PDFJS === 'undefined') { + (typeof window !== 'undefined' ? window : this).PDFJS = {}; +} + +// Checking if the typed arrays are supported +(function checkTypedArrayCompatibility() { + if (typeof Uint8Array !== 'undefined') { + // some mobile versions do not support subarray (e.g. safari 5 / iOS) + if (typeof Uint8Array.prototype.subarray === 'undefined') { + Uint8Array.prototype.subarray = function subarray(start, end) { + return new Uint8Array(this.slice(start, end)); + }; + Float32Array.prototype.subarray = function subarray(start, end) { + return new Float32Array(this.slice(start, end)); + }; + } + + // some mobile version might not support Float64Array + if (typeof Float64Array === 'undefined') + window.Float64Array = Float32Array; + + return; + } + + function subarray(start, end) { + return new TypedArray(this.slice(start, end)); + } + + function setArrayOffset(array, offset) { + if (arguments.length < 2) + offset = 0; + for (var i = 0, n = array.length; i < n; ++i, ++offset) + this[offset] = array[i] & 0xFF; + } + + function TypedArray(arg1) { + var result; + if (typeof arg1 === 'number') { + result = []; + for (var 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) { + result[i] = arg1[i]; + } + } + + result.subarray = subarray; + result.buffer = result; + result.byteLength = result.length; + result.set = setArrayOffset; + + if (typeof arg1 === 'object' && arg1.buffer) + result.buffer = arg1.buffer; + + return result; + } + + window.Uint8Array = TypedArray; + + // we don't need support for set, byteLength for 32-bit array + // so we can use the TypedArray as well + window.Uint32Array = TypedArray; + window.Int32Array = TypedArray; + window.Uint16Array = TypedArray; + window.Float32Array = TypedArray; + window.Float64Array = TypedArray; +})(); + +// URL = URL || webkitURL +(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() ? +(function checkObjectDefinePropertyCompatibility() { + if (typeof Object.defineProperty !== 'undefined') { + var definePropertyPossible = true; + try { + // some browsers (e.g. safari) cannot use defineProperty() on DOM objects + // and thus the native version is not sufficient + Object.defineProperty(new Image(), 'id', { value: 'test' }); + // ... another test for android gb browser for non-DOM objects + var Test = function Test() {}; + Test.prototype = { get id() { } }; + Object.defineProperty(new Test(), 'id', + { value: '', configurable: true, enumerable: true, writable: false }); + } catch (e) { + definePropertyPossible = false; + } + if (definePropertyPossible) return; + } + + Object.defineProperty = function objectDefineProperty(obj, name, def) { + delete obj[name]; + if ('get' in def) + obj.__defineGetter__(name, def['get']); + if ('set' in def) + obj.__defineSetter__(name, def['set']); + if ('value' in def) { + obj.__defineSetter__(name, function objectDefinePropertySetter(value) { + this.__defineGetter__(name, function objectDefinePropertyGetter() { + return value; + }); + return value; + }); + obj[name] = def.value; + } + }; +})(); + +// 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 ? +(function checkXMLHttpRequestResponseCompatibility() { + var xhrPrototype = XMLHttpRequest.prototype; + if (!('overrideMimeType' in xhrPrototype)) { + // IE10 might have response, but not overrideMimeType + Object.defineProperty(xhrPrototype, 'overrideMimeType', { + value: function xmlHttpRequestOverrideMimeType(mimeType) {} + }); + } + if ('response' in xhrPrototype || + 'mozResponseArrayBuffer' in xhrPrototype || + 'mozResponse' in xhrPrototype || + 'responseArrayBuffer' in xhrPrototype) + return; + // IE9 ? + if (typeof VBArray !== 'undefined') { + Object.defineProperty(xhrPrototype, 'response', { + get: function xmlHttpRequestResponseGet() { + return new Uint8Array(new VBArray(this.responseBody).toArray()); + } + }); + 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 }); +})(); + +// window.btoa (base64 encode function) ? +(function checkWindowBtoaCompatibility() { + if ('btoa' in window) + return; + + var digits = + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; + + window.btoa = function windowBtoa(chars) { + var buffer = ''; + var i, n; + for (i = 0, n = chars.length; i < n; i += 3) { + var b1 = chars.charCodeAt(i) & 0xFF; + var b2 = chars.charCodeAt(i + 1) & 0xFF; + var b3 = chars.charCodeAt(i + 2) & 0xFF; + var d1 = b1 >> 2, d2 = ((b1 & 3) << 4) | (b2 >> 4); + var d3 = i + 1 < n ? ((b2 & 0xF) << 2) | (b3 >> 6) : 64; + var d4 = i + 2 < n ? (b3 & 0x3F) : 64; + buffer += (digits.charAt(d1) + digits.charAt(d2) + + digits.charAt(d3) + digits.charAt(d4)); + } + return buffer; + }; +})(); + +// window.atob (base64 encode function) ? +(function checkWindowAtobCompatibility() { + if ('atob' in window) + return; + + // https://github.com/davidchambers/Base64.js + var digits = + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; + window.atob = function (input) { + input = input.replace(/=+$/, ''); + if (input.length % 4 == 1) throw new Error('bad atob input'); + for ( + // initialize result and counters + var bc = 0, bs, buffer, idx = 0, output = ''; + // get next character + buffer = input.charAt(idx++); + // character found in table? + // initialize bit storage and add its ascii value + ~buffer && (bs = bc % 4 ? bs * 64 + buffer : buffer, + // and if not first of each 4 characters, + // convert the first 8 bits to one ascii character + bc++ % 4) ? output += String.fromCharCode(255 & bs >> (-2 * bc & 6)) : 0 + ) { + // try to find character in table (0-63, not found => -1) + buffer = digits.indexOf(buffer); + } + return output; + }; +})(); + +// Function.prototype.bind ? +(function checkFunctionPrototypeBindCompatibility() { + if (typeof Function.prototype.bind !== 'undefined') + return; + + Function.prototype.bind = function functionPrototypeBind(obj) { + var fn = this, headArgs = Array.prototype.slice.call(arguments, 1); + var bound = function functionPrototypeBindBound() { + var args = Array.prototype.concat.apply(headArgs, arguments); + return fn.apply(obj, args); + }; + return bound; + }; +})(); + +// HTMLElement dataset property +(function checkDatasetProperty() { + var div = document.createElement('div'); + if ('dataset' in div) + return; // dataset property exists + + Object.defineProperty(HTMLElement.prototype, 'dataset', { + get: function() { + if (this._dataset) + return this._dataset; + + var dataset = {}; + for (var j = 0, jj = this.attributes.length; j < jj; j++) { + var attribute = this.attributes[j]; + if (attribute.name.substring(0, 5) != 'data-') + continue; + var key = attribute.name.substring(5).replace(/\-([a-z])/g, + function(all, ch) { return ch.toUpperCase(); }); + dataset[key] = attribute.value; + } + + Object.defineProperty(this, '_dataset', { + value: dataset, + writable: false, + enumerable: false + }); + return dataset; + }, + enumerable: true + }); +})(); + +// HTMLElement classList property +(function checkClassListProperty() { + var div = document.createElement('div'); + if ('classList' in div) + return; // classList property exists + + function changeList(element, itemName, add, remove) { + var s = element.className || ''; + var list = s.split(/\s+/g); + if (list[0] === '') list.shift(); + var index = list.indexOf(itemName); + if (index < 0 && add) + list.push(itemName); + if (index >= 0 && remove) + list.splice(index, 1); + element.className = list.join(' '); + return (index >= 0); + } + + var classListPrototype = { + add: function(name) { + changeList(this.element, name, true, false); + }, + contains: function(name) { + return changeList(this.element, name, false, false); + }, + remove: function(name) { + changeList(this.element, name, false, true); + }, + toggle: function(name) { + changeList(this.element, name, true, true); + } + }; + + Object.defineProperty(HTMLElement.prototype, 'classList', { + get: function() { + if (this._classList) + return this._classList; + + var classList = Object.create(classListPrototype, { + element: { + value: this, + writable: false, + enumerable: true + } + }); + Object.defineProperty(this, '_classList', { + value: classList, + writable: false, + enumerable: false + }); + return classList; + }, + enumerable: true + }); +})(); + +// Check console compatibility +(function checkConsoleCompatibility() { + if (!('console' in window)) { + window.console = { + log: function() {}, + error: function() {}, + warn: function() {} + }; + } else if (!('bind' in console.log)) { + // native functions in IE9 might not have bind + console.log = (function(fn) { + return function(msg) { return fn(msg); }; + })(console.log); + console.error = (function(fn) { + return function(msg) { return fn(msg); }; + })(console.error); + console.warn = (function(fn) { + return function(msg) { return fn(msg); }; + })(console.warn); + } +})(); + +// Check onclick compatibility in Opera +(function checkOnClickCompatibility() { + // workaround for reported Opera bug DSK-354448: + // onclick fires on disabled buttons with opaque content + function ignoreIfTargetDisabled(event) { + if (isDisabled(event.target)) { + event.stopPropagation(); + } + } + function isDisabled(node) { + return node.disabled || (node.parentNode && isDisabled(node.parentNode)); + } + if (navigator.userAgent.indexOf('Opera') != -1) { + // use browser detection since we cannot feature-check this bug + document.addEventListener('click', ignoreIfTargetDisabled, true); + } +})(); + +// Checks if possible to use URL.createObjectURL() +(function checkOnBlobSupport() { + // sometimes IE loosing the data created with createObjectURL(), see #3977 + if (navigator.userAgent.indexOf('Trident') >= 0) { + PDFJS.disableCreateObjectURL = true; + } +})(); + +// Checks if navigator.language is supported +(function checkNavigatorLanguage() { + if ('language' in navigator) + return; + 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 checkRangeRequests() { + // Safari has issues with cached range requests see: + // https://github.com/mozilla/pdf.js/issues/3260 + // Last tested with version 6.0.4. + var isSafari = Object.prototype.toString.call( + window.HTMLElement).indexOf('Constructor') > 0; + + // Older versions of Android (pre 3.0) has issues with range requests, see: + // https://github.com/mozilla/pdf.js/issues/3381. + // Make sure that we only match webkit-based Android browsers, + // since Firefox/Fennec works as expected. + var regex = /Android\s[0-2][^\d]/; + var isOldAndroid = regex.test(navigator.userAgent); + + if (isSafari || isOldAndroid) { + PDFJS.disableRange = true; + } +})(); + +// Check if the browser supports manipulation of the history. +(function checkHistoryManipulation() { + if (!window.history.pushState) { + PDFJS.disableHistory = true; + } +})(); diff --git a/attachment_preview/static/lib/ViewerJS/example.local.css b/attachment_preview/static/lib/ViewerJS/example.local.css new file mode 100644 index 00000000000..4ef1b6727ab --- /dev/null +++ b/attachment_preview/static/lib/ViewerJS/example.local.css @@ -0,0 +1,27 @@ +/* This is just a sample file with CSS rules. You should write your own @font-face declarations + * to add support for your desired fonts. + */ + +@font-face { + font-family: 'Novecentowide Book'; + 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.svg#NovecentowideBookBold") format("svg"); + font-weight: normal; + font-style: normal; +} + +@font-face { + font-family: 'exotica'; + src: url('/ViewerJS/fonts/Exotica-webfont.eot'); + src: url('/ViewerJS/fonts/Exotica-webfont.eot?#iefix') format('embedded-opentype'), + url('/ViewerJS/fonts/Exotica-webfont.woff') format('woff'), + url('/ViewerJS/fonts/Exotica-webfont.ttf') format('truetype'), + url('/ViewerJS/fonts/Exotica-webfont.svg#exoticamedium') format('svg'); + font-weight: normal; + font-style: normal; + +} + diff --git a/attachment_preview/static/lib/ViewerJS/images/kogmbh.png b/attachment_preview/static/lib/ViewerJS/images/kogmbh.png new file mode 100644 index 0000000000000000000000000000000000000000..00e8f4debdda56ba5a57472b43a23b020080bfa9 GIT binary patch literal 2835 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 O5r8?-l2B*lk?>!&x?|k{ literal 0 HcmV?d00001 diff --git a/attachment_preview/static/lib/ViewerJS/images/toolbarButton-download.png b/attachment_preview/static/lib/ViewerJS/images/toolbarButton-download.png new file mode 100644 index 0000000000000000000000000000000000000000..8676d8e2c2c0bac77cfce486f6f18639a8caa987 GIT binary patch literal 512 zcmV+b0{{JqP)z}Is24wg34Vg0&(Nh)A4KqyCy|cYNsu~v@z2dmB9tj1uH`lp^J3U`8~E{N z-p=3On^hdg5sIR03L*9Y+kk-hD<6Ofzy>Vo6d1ck4*P?_;4T~v8^TAR$Zf0DN+pxY zdoYJGiL9nW@D^3_!$~5MNL4D8YtWAX>pTG(3u?~~8-RJKR61@po0nw&j-Zf}uM`Re z1IBnHvj;%lW(tv*fb&ZHFIX|iIJtqC9%tO0lVf5?1zr z%n1($UyPgb4t7C5rMH$zKiPV#uKO2UXNZ0M7GMAtm#g$qt>3!<0000gp@kF&{Rb5bN zGzijG&{UKVshtpNClNu)%Ekhbw2`1J>Z6HtgGN0xKEhh;{0EDsrSU_qGw%`SWF~jc zxpQak3{VFTy2*App+P}o)NW`Vy70=Y$@eYTjRgDq)}ID15R?~1J&mx+C#(qTX;VcI z7?3B$uiL;R>R}-rT@%F{Q^f$#FZUOjQcfPeZ$<}E18p$$rORXa`Z6Q;=m%OKw=v~i zDrMy^zYYg%xi!g`vmMKrqSFdWO=yItW9DoVJ*XuE>5afFEf*aJP=P8AjY%zNU{t}` z&6S2q!}*1UI~}}%g2r}h|1FKpX|M(R^hMUF<}P<`VJOHX(}C-46~4}~;<03|R$zne zd{Hvx6aP5;bXPIK`>N>asx-f>p5`o;?TlKMQ-6LJb45R#;%UHjic=P>Ck@ z+{d0AQcWVHUUFA4oxlhWu<(*~7(R)cs(MMk>=;Zw$5hvZ{W->}h6+FUwIhgP8WFVd hn-r{!B2=PuoIg4=n|)8MY<2(u002ovPDHLkV1hfJ)Vlxx literal 0 HcmV?d00001 diff --git a/attachment_preview/static/lib/ViewerJS/images/toolbarButton-menuArrows.png b/attachment_preview/static/lib/ViewerJS/images/toolbarButton-menuArrows.png new file mode 100644 index 0000000000000000000000000000000000000000..31b06b5af9e548b15e274677b8ecaac1c1d06e77 GIT binary patch literal 237 zcmeAS@N?(olHy`uVBq!ia0vp^>_9BQ!2%=;I@VSLDajJoh?3y^w370~qErUQl>DSr z1<%~X^wgl##FWaylc_d9Mg5*Gjv*Y;$q5RA21W%&988AFF7neS9({Y$O^hc-fzNvT zy{kX}UyqMIu=e3{csed~)S6b>9XaCpJd2PXwsj@)uEyTHN9Cd}ro z5XP`c@(2I(zwen392I~4ZeZ0+OPe6@{r)uVcjpxtQN)i16KOjF~A%cy9L}N?{*aRypMbKt#Y{Wu@^dWzc zB43gw@m?5VSf4XKI1uvgxkJb(Jp(WVYhVPnHDj;=mcX2{j2A`GW>r;L-}l82ZQFh| zO*2i?^oZrQ5>KD9SC-`y?f{*0oaG|B7xlwaLz8mj}qKT!aP_teqVs_y##kUGoqtiwOACzF#-<;cM@iX z4qc!Yz$DM}D=cpR1G99rt30p*4zet}M&QNP=Y&2{#AlocLCwd zgzqHz&yp|CdBw$>ph$U z)hTRj6#q=2*TFhKHzx|6MzWGs8Z{*folGT{Oft!nX+2TscPHu_w7sJZOjQKt!iL$+`E7GKObZu1M&0Q qn}h0!&|(*d3p}p4q{kr^2K)fvg`AtvZ>v!N0000gLY5juG`4KT z&x9li$(}8dZOBJ&zuvyy@ArNGe9v**&vQTLbzawXpXYJk$MeLQndt9l6J!Gb0Q(UJ zIu^T6uD!v+w0l3cyn_M&*fg=)+GYrCZLpay-W7|(000L2vu*`gSq|{U(x{5m*9ReB z(G|g9R&dW*1747M93spN7!w8c*V(7X!+pxe#j1fpKNjMw%flWSf$nGh%4OEtXs)9> zF+}oYT`ZMf9?sluLyingRrL?JEfV`{0A^bepeBMXLzrByEziPiqy51{9nEXN!(0rU zwhRrUuC5^cbsgZFEvjlp#sh;^%IX3v%%yfvqTUSZ_jV^V8KS5y!USN`?Nd+*f$~oP zZ(34X1Y~wVuU67d$;3#@@a3}RJ%o%km*Z9oCr{VDOeaIfa|MxI0?*~LNwsFfnWCfl zBv7t>y68u@{Hx3usudy=FtK*Bw|D)HF+hqZ!?AM;nv08*(d7|Xi2Dizu-t4`dhW}4 zeM8AT8xVNkZ9ESEu(9)-GzBo5}Ezp>@Qps^cia)Fze@mA^ z6zP@Wo;+VFJU@?oJL$erKQMAM#By7;J(zC21f8R0Ym%~&Be=PTa4H{QRmAT05lUT} zHK5XqNn>L4q3I$R@O2-ca`?{j(HPvtl;%$yV(i!F=5T%tIi9f7(~9(*2>h%17^St0 zjs?2S+57zJ;U^HhvKZZo`-S(7bUHgZILS1Z?KQ5Qu?8jVzh1tOxRcYszZ5-fZ9aXI zH7d@%Hd-azHVNj!78Tkz8hThkj9DNg%ah0bvLk>Ptz=e>U~b2&0<=#sig>FB1BtU2 zxTM+I>z=!pCYSpq$^?I(+C0W?AMZVCtO>E4T;)h~@fFRJ5Xc{i!ZiX9CNUH4vdM+R zq<|7m`-Q_~eHe$qfT%D7F2-AoFasb~1N2x^?cMGclzzwHAL-!(coQD{8e|fo;KO7O zI^VG0hn*u#UxO{C(MXD6I2_9o@r8>wPqR3Qui!w2)>|$iJC-1AO|vsRj4j%6Nn9x! z8?T`c4vR+?=W3g&uACqU*04B4Zr){n4VGitW*|m!rvrOY``-bch7DAl6=uiDP= z$a{yGzhQ9Hu$oVev#N=IROkypBHFPjl|`eSg|S=DmPKeuM=Qxzgn|3GXELM!Sfrbo z#91KpEWsf8(l{eiY%VJOFkh>{SS*q>inc+$MH@=>r8}qF81qjmxN^ycZ$#Wf_dU9A zEA~*`pH+eTc7kNHjZ>o2g$nW`#&@W>v%;Kh4FaEpeL|`a+sk;%mw~Dd^pk4CW?$?d zg)Rj?7a!(Xj5yHf_XU0RcpY1)aOlyI#AB`XVo9uaAkT;c$8Ui}a3WS*f-F-k+fm$2 za^~R=ObL(}uApXn^r=TT-f2EZ2t!R$c@Qxo{1zgoGAhHZ5FQW*s4A3tJoTlri@xt+ zq{cE25@1`^f=hM_7)SRDO?nFLgv; zv4Gy2I@7XpY?`{liV?+Jm^e8hJRvwid1b-WB;~X&YawutluD{4B`(WNKBJA%1{KP& z7k8eYO4|_k7QdPXNpnqONJ}g>w#N7I^ko%$6`Q`1@_>4vJO(`IeXx=QS|KeUo0jD$ zw==#K`?;bfF1UKr{crnDp4(Uen7Ex%QvBP9dby4T~O4lvahlX&@wfG z+rk~o%@=dk%yUX}3hMRiFND5ocnyB$cak_=fl#CFUh8C1)j$Ax|Oq*?LueuGoC>zB$v=!I{_=<1yw;>AF8O z`J}W+a>T!Wo_IFXp<;-y)})rU%DD=mL+R4Ysdm^|qUZsZ)Y9_KVlZ<>!;nmsh2%p%*;?xq< z4%PYBl@Q_UsBPf3|K`wg|Cg!Fe!3~>4Co>2G+O~k4`jov#xBEpaNlLni$;dV+K6ND z9!C-TH+(>?Ep7j36;^o;2i{G;!!QZChtRp8YU{v|zyOdWT31KAxz-@Dy{BFOdIFyj zUx40A{TAIm{d2lkbji9#WLpU&Wn7PBM*`nh_e?~{q54q91~Vx6s;?gtUqCqNs%bHx`R;J`|mY7AP&c|#gyggc* zeamq!1UvI&(Th6cL)pGHR(hjuA8~5afes&Dtszd_*vS%Nyw0?_0IR#QbMb@f3~_k7 zo4M$~MfJ|$Gu!Ul&U0gVVr-`3*~RLm+kNZ(u0_<9xx4*NG|Dx%#F%Pr_)gkJx#^32 zv?AJRy-K~$`lb3b(gtZL_|ZzsmktuScPzU8)c2=rY276`Apvx%8~SDQ7tik540Xfd z2X#uDZ&$shT&Bl+1F(zt3*(1N>eN@mw{z*vD{aX$bEfO2X*mh%0asbKz6L_QTqj4? zqL%40%E*x2e@a##1Ee1Sz|90mYD5UiCg!SoVTBHpep1CLwR?;2g4!Y9~6S8D#Z4j8CVO%>u!AowW5;Q;{wumD*Y-q#H-t)!#`my&_Y$Vl!oB>jTC38+9x zZ@&|N75R4^9gLr|FV=^E#e0MI>Y~v2%LG*jWUtY$>*qSXe10|Z_WP-7S06kO88#4u^V)j_%fMv*%KSb4GgSq?r{OnEKMdPj&L8;yrImnn{oB?5CU!6K zPqllfvZ*f?v+MGnmuk`~@PA;x>H85wT44O}xXVBIio2rz0sfhwjra2L#rXN{HIV0n*MI#@4^ z_YXg0b`AL-1HZ}p5!c4!@V=HlC}+%`A%8-DvVXKe{--v-1^!o4{<3QK%&M{N?%jW% ze>JubOimmC08kg9qiJ=9JIm6j#KN3sn7$q&&jmlv%y~6QE0w9`h&+#2|DC8*cj3`y z%^h$z!bdYxZno#-PNQgTZZwyP_HlCw>COhl;FZ9xnG0uECpg*i_R${_SM5fs>Zo1H zxcZS1>7Cv%s;6X{VTXap*H$TxeJXQ~B)={mUFp`br4+`7+M$JI4e%Ft%77GP;}Cav zL6FK(g)9@tHuR%H8;kPUntt>nVRJwyu69TU$d%kX<5D|xRa8IYd1v_d&yRH=sd53C#m?kLC+m)_{$YfltzrhW%dFL+o`Mh|VrTtj+ zLp`>wkR9%8XSOcM2_~HIk7PNi2W0^pwPkh1w|r{Tf#jwb+jjuUm4rE&-7CU@k*<^t z>?7MP5pdB7N>8MCl-6;fdCI`tzJ)ER4CABZjtR7IOvORYSUgi?W5wY7s(H2*SOM_d z!us2CFqP8+&{0%;TlS7n$3)K^+7xu7&qGw@6I5_J#Wxy=^XH5m<8uksIMB5e!nPrH zn1|_`)t6UBGd=7;5%!HFe*Fd6@CL>Lv{72S$hFmjCs>O6JdPwRqZ|_QK<1C-5MfFm z(-VVXWI8dLpiCU}t|}~|AH0SyXK0r`Bs`_8VZ(J&M=LVw` t(cvVco%6ur2oX5nhALapLBh}u(C|}?$GL+WyPqEb0HJH5Q>Nt<@n1WHo`(Pc literal 0 HcmV?d00001 diff --git a/attachment_preview/static/lib/ViewerJS/images/toolbarButton-zoomIn.png b/attachment_preview/static/lib/ViewerJS/images/toolbarButton-zoomIn.png new file mode 100644 index 0000000000000000000000000000000000000000..670acd93f5324c0f32e37e13d43c31890bdd123a GIT binary patch literal 228 zcmVviSpk+Ka&^`vn5+K)IU-oAe*-xp*r + + + + + + + + + + + ViewerJS + + + + + + + + + + + +
+
+
+
+ + + +
+
+
+
+
+ + + + +
+
+
+
+ +
+ +
+ + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ✖ +
+
+
+ + diff --git a/attachment_preview/static/lib/ViewerJS/pdf.js b/attachment_preview/static/lib/ViewerJS/pdf.js new file mode 100644 index 00000000000..3e50f6c3e3c --- /dev/null +++ b/attachment_preview/static/lib/ViewerJS/pdf.js @@ -0,0 +1,7651 @@ +/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ +/* Copyright 2012 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// 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'; + +(function pdfjsWrapper() { + // Use strict in our context only - users might not want it + 'use strict'; + +/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ +/* Copyright 2012 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* globals Cmd, ColorSpace, Dict, MozBlobBuilder, Name, PDFJS, Ref, URL, + Promise */ + +'use strict'; + +var globalScope = (typeof window === 'undefined') ? this : window; + +var isWorker = (typeof window == 'undefined'); + +var FONT_IDENTITY_MATRIX = [0.001, 0, 0, 0.001, 0, 0]; + +var TextRenderingMode = { + FILL: 0, + STROKE: 1, + FILL_STROKE: 2, + INVISIBLE: 3, + FILL_ADD_TO_PATH: 4, + STROKE_ADD_TO_PATH: 5, + FILL_STROKE_ADD_TO_PATH: 6, + ADD_TO_PATH: 7, + FILL_STROKE_MASK: 3, + ADD_TO_PATH_FLAG: 4 +}; + +// The global PDFJS object exposes the API +// In production, it will be declared outside a global wrapper +// In development, it will be declared here +if (!globalScope.PDFJS) { + globalScope.PDFJS = {}; +} + +globalScope.PDFJS.pdfBug = false; + +PDFJS.VERBOSITY_LEVELS = { + errors: 0, + warnings: 1, + infos: 5 +}; + +// All the possible operations for an operator list. +var OPS = PDFJS.OPS = { + // Intentionally start from 1 so it is easy to spot bad operators that will be + // 0's. + dependency: 1, + setLineWidth: 2, + setLineCap: 3, + setLineJoin: 4, + setMiterLimit: 5, + setDash: 6, + setRenderingIntent: 7, + setFlatness: 8, + setGState: 9, + save: 10, + restore: 11, + transform: 12, + moveTo: 13, + lineTo: 14, + curveTo: 15, + curveTo2: 16, + curveTo3: 17, + closePath: 18, + rectangle: 19, + stroke: 20, + closeStroke: 21, + fill: 22, + eoFill: 23, + fillStroke: 24, + eoFillStroke: 25, + closeFillStroke: 26, + closeEOFillStroke: 27, + endPath: 28, + clip: 29, + eoClip: 30, + beginText: 31, + endText: 32, + setCharSpacing: 33, + setWordSpacing: 34, + setHScale: 35, + setLeading: 36, + setFont: 37, + setTextRenderingMode: 38, + setTextRise: 39, + moveText: 40, + setLeadingMoveText: 41, + setTextMatrix: 42, + nextLine: 43, + showText: 44, + showSpacedText: 45, + nextLineShowText: 46, + nextLineSetSpacingShowText: 47, + setCharWidth: 48, + setCharWidthAndBounds: 49, + setStrokeColorSpace: 50, + setFillColorSpace: 51, + setStrokeColor: 52, + setStrokeColorN: 53, + setFillColor: 54, + setFillColorN: 55, + setStrokeGray: 56, + setFillGray: 57, + setStrokeRGBColor: 58, + setFillRGBColor: 59, + setStrokeCMYKColor: 60, + setFillCMYKColor: 61, + shadingFill: 62, + beginInlineImage: 63, + beginImageData: 64, + endInlineImage: 65, + paintXObject: 66, + markPoint: 67, + markPointProps: 68, + beginMarkedContent: 69, + beginMarkedContentProps: 70, + endMarkedContent: 71, + beginCompat: 72, + endCompat: 73, + paintFormXObjectBegin: 74, + paintFormXObjectEnd: 75, + beginGroup: 76, + endGroup: 77, + beginAnnotations: 78, + endAnnotations: 79, + beginAnnotation: 80, + endAnnotation: 81, + paintJpegXObject: 82, + paintImageMaskXObject: 83, + paintImageMaskXObjectGroup: 84, + paintImageXObject: 85, + paintInlineImageXObject: 86, + paintInlineImageXObjectGroup: 87 +}; + +// A notice for devs. These are good for things that are helpful to devs, such +// as warning that Workers were disabled, which is important to devs but not +// end users. +function info(msg) { + if (PDFJS.verbosity >= PDFJS.VERBOSITY_LEVELS.infos) { + console.log('Info: ' + msg); + } +} + +// Non-fatal warnings. +function warn(msg) { + if (PDFJS.verbosity >= PDFJS.VERBOSITY_LEVELS.warnings) { + console.log('Warning: ' + msg); + } +} + +// Fatal errors that should trigger the fallback UI and halt execution by +// throwing an exception. +function error(msg) { + // If multiple arguments were passed, pass them all to the log function. + if (arguments.length > 1) { + var logArguments = ['Error:']; + logArguments.push.apply(logArguments, arguments); + console.log.apply(console, logArguments); + // Join the arguments into a single string for the lines below. + msg = [].join.call(arguments, ' '); + } else { + console.log('Error: ' + msg); + } + console.log(backtrace()); + UnsupportedManager.notify(UNSUPPORTED_FEATURES.unknown); + throw new Error(msg); +} + +function backtrace() { + try { + throw new Error(); + } catch (e) { + return e.stack ? e.stack.split('\n').slice(2).join('\n') : ''; + } +} + +function assert(cond, msg) { + if (!cond) + error(msg); +} + +var UNSUPPORTED_FEATURES = PDFJS.UNSUPPORTED_FEATURES = { + unknown: 'unknown', + forms: 'forms', + javaScript: 'javaScript', + smask: 'smask', + shadingPattern: 'shadingPattern', + font: 'font' +}; + +var UnsupportedManager = PDFJS.UnsupportedManager = + (function UnsupportedManagerClosure() { + var listeners = []; + return { + listen: function (cb) { + listeners.push(cb); + }, + notify: function (featureId) { + warn('Unsupported feature "' + featureId + '"'); + for (var i = 0, ii = listeners.length; i < ii; i++) { + listeners[i](featureId); + } + } + }; +})(); + +// Combines two URLs. The baseUrl shall be absolute URL. If the url is an +// absolute URL, it will be returned as is. +function combineUrl(baseUrl, url) { + if (!url) + return baseUrl; + if (/^[a-z][a-z0-9+\-.]*:/i.test(url)) + return url; + if (url.charAt(0) == '/') { + // absolute path + var i = baseUrl.indexOf('://'); + i = baseUrl.indexOf('/', i + 3); + return baseUrl.substring(0, i) + url; + } else { + // relative path + var pathLength = baseUrl.length, i; + i = baseUrl.lastIndexOf('#'); + pathLength = i >= 0 ? i : pathLength; + i = baseUrl.lastIndexOf('?', pathLength); + pathLength = i >= 0 ? i : pathLength; + var prefixLength = baseUrl.lastIndexOf('/', pathLength); + return baseUrl.substring(0, prefixLength + 1) + url; + } +} + +// Validates if URL is safe and allowed, e.g. to avoid XSS. +function isValidUrl(url, allowRelative) { + if (!url) { + return false; + } + // RFC 3986 (http://tools.ietf.org/html/rfc3986#section-3.1) + // scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) + var protocol = /^[a-z][a-z0-9+\-.]*(?=:)/i.exec(url); + if (!protocol) { + return allowRelative; + } + protocol = protocol[0].toLowerCase(); + switch (protocol) { + case 'http': + case 'https': + case 'ftp': + case 'mailto': + return true; + default: + return false; + } +} +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, + configurable: true, + writable: false }); + return value; +} + +var PasswordResponses = PDFJS.PasswordResponses = { + NEED_PASSWORD: 1, + INCORRECT_PASSWORD: 2 +}; + +var PasswordException = (function PasswordExceptionClosure() { + function PasswordException(msg, code) { + this.name = 'PasswordException'; + this.message = msg; + this.code = code; + } + + PasswordException.prototype = new Error(); + PasswordException.constructor = PasswordException; + + return PasswordException; +})(); + +var UnknownErrorException = (function UnknownErrorExceptionClosure() { + function UnknownErrorException(msg, details) { + this.name = 'UnknownErrorException'; + this.message = msg; + this.details = details; + } + + UnknownErrorException.prototype = new Error(); + UnknownErrorException.constructor = UnknownErrorException; + + return UnknownErrorException; +})(); + +var InvalidPDFException = (function InvalidPDFExceptionClosure() { + function InvalidPDFException(msg) { + this.name = 'InvalidPDFException'; + this.message = msg; + } + + InvalidPDFException.prototype = new Error(); + InvalidPDFException.constructor = InvalidPDFException; + + return InvalidPDFException; +})(); + +var MissingPDFException = (function MissingPDFExceptionClosure() { + function MissingPDFException(msg) { + this.name = 'MissingPDFException'; + this.message = msg; + } + + MissingPDFException.prototype = new Error(); + MissingPDFException.constructor = MissingPDFException; + + return MissingPDFException; +})(); + +var NotImplementedException = (function NotImplementedExceptionClosure() { + function NotImplementedException(msg) { + this.message = msg; + } + + NotImplementedException.prototype = new Error(); + NotImplementedException.prototype.name = 'NotImplementedException'; + NotImplementedException.constructor = NotImplementedException; + + return NotImplementedException; +})(); + +var MissingDataException = (function MissingDataExceptionClosure() { + function MissingDataException(begin, end) { + this.begin = begin; + this.end = end; + this.message = 'Missing data [' + begin + ', ' + end + ')'; + } + + MissingDataException.prototype = new Error(); + MissingDataException.prototype.name = 'MissingDataException'; + MissingDataException.constructor = MissingDataException; + + return MissingDataException; +})(); + +var XRefParseException = (function XRefParseExceptionClosure() { + function XRefParseException(msg) { + this.message = msg; + } + + XRefParseException.prototype = new Error(); + XRefParseException.prototype.name = 'XRefParseException'; + XRefParseException.constructor = XRefParseException; + + return XRefParseException; +})(); + + +function bytesToString(bytes) { + var str = ''; + var length = bytes.length; + for (var n = 0; n < length; ++n) + str += String.fromCharCode(bytes[n]); + return str; +} + +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; + return bytes; +} + +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] + ')'; + }; + + Util.makeCssCmyk = function Util_makeCssCmyk(cmyk) { + var rgb = ColorSpace.singletons.cmyk.getRgb(cmyk, 0); + return Util.makeCssRgb(rgb); + }; + + // Concatenates two transformation matrices together and returns the result. + Util.transform = function Util_transform(m1, m2) { + return [ + m1[0] * m2[0] + m1[2] * m2[1], + m1[1] * m2[0] + m1[3] * m2[1], + m1[0] * m2[2] + m1[2] * m2[3], + m1[1] * m2[2] + m1[3] * m2[3], + m1[0] * m2[4] + m1[2] * m2[5] + m1[4], + m1[1] * m2[4] + m1[3] * m2[5] + m1[5] + ]; + }; + + // For 2d affine transforms + Util.applyTransform = function Util_applyTransform(p, m) { + var xt = p[0] * m[0] + p[1] * m[2] + m[4]; + var yt = p[0] * m[1] + p[1] * m[3] + m[5]; + return [xt, yt]; + }; + + Util.applyInverseTransform = function Util_applyInverseTransform(p, m) { + var d = m[0] * m[3] - m[1] * m[2]; + var xt = (p[0] * m[3] - p[1] * m[2] + m[2] * m[5] - m[4] * m[3]) / d; + var yt = (-p[0] * m[1] + p[1] * m[0] + m[4] * m[1] - m[5] * m[0]) / d; + return [xt, yt]; + }; + + // Applies the transform to the rectangle and finds the minimum axially + // aligned bounding box. + Util.getAxialAlignedBoundingBox = + function Util_getAxialAlignedBoundingBox(r, m) { + + var p1 = Util.applyTransform(r, m); + var p2 = Util.applyTransform(r.slice(2, 4), m); + var p3 = Util.applyTransform([r[0], r[3]], m); + var p4 = Util.applyTransform([r[2], r[1]], m); + return [ + Math.min(p1[0], p2[0], p3[0], p4[0]), + Math.min(p1[1], p2[1], p3[1], p4[1]), + Math.max(p1[0], p2[0], p3[0], p4[0]), + Math.max(p1[1], p2[1], p3[1], p4[1]) + ]; + }; + + Util.inverseTransform = function Util_inverseTransform(m) { + var d = m[0] * m[3] - m[1] * m[2]; + return [m[3] / d, -m[1] / d, -m[2] / d, m[0] / d, + (m[2] * m[5] - m[4] * m[3]) / d, (m[4] * m[1] - m[5] * m[0]) / d]; + }; + + // Apply a generic 3d matrix M on a 3-vector v: + // | a b c | | X | + // | d e f | x | Y | + // | g h i | | Z | + // M is assumed to be serialized as [a,b,c,d,e,f,g,h,i], + // with v as [X,Y,Z] + Util.apply3dTransform = function Util_apply3dTransform(m, v) { + return [ + m[0] * v[0] + m[1] * v[1] + m[2] * v[2], + m[3] * v[0] + m[4] * v[1] + m[5] * v[2], + m[6] * v[0] + m[7] * v[1] + m[8] * v[2] + ]; + }; + + // This calculation uses Singular Value Decomposition. + // The SVD can be represented with formula A = USV. We are interested in the + // matrix S here because it represents the scale values. + Util.singularValueDecompose2dScale = + function Util_singularValueDecompose2dScale(m) { + + var transpose = [m[0], m[2], m[1], m[3]]; + + // Multiply matrix m with its transpose. + var a = m[0] * transpose[0] + m[1] * transpose[2]; + var b = m[0] * transpose[1] + m[1] * transpose[3]; + var c = m[2] * transpose[0] + m[3] * transpose[2]; + var d = m[2] * transpose[1] + m[3] * transpose[3]; + + // Solve the second degree polynomial to get roots. + var first = (a + d) / 2; + var second = Math.sqrt((a + d) * (a + d) - 4 * (a * d - c * b)) / 2; + var sx = first + second || 1; + var sy = first - second || 1; + + // Scale values are the square roots of the eigenvalues. + return [Math.sqrt(sx), Math.sqrt(sy)]; + }; + + // Normalize rectangle rect=[x1, y1, x2, y2] so that (x1,y1) < (x2,y2) + // For coordinate systems whose origin lies in the bottom-left, this + // means normalization to (BL,TR) ordering. For systems with origin in the + // top-left, this means (TL,BR) ordering. + Util.normalizeRect = function Util_normalizeRect(rect) { + var r = rect.slice(0); // clone rect + if (rect[0] > rect[2]) { + r[0] = rect[2]; + r[2] = rect[0]; + } + if (rect[1] > rect[3]) { + r[1] = rect[3]; + r[3] = rect[1]; + } + return r; + }; + + // Returns a rectangle [x1, y1, x2, y2] corresponding to the + // intersection of rect1 and rect2. If no intersection, returns 'false' + // The rectangle coordinates of rect1, rect2 should be [x1, y1, x2, y2] + Util.intersect = function Util_intersect(rect1, rect2) { + function compare(a, b) { + return a - b; + } + + // Order points along the axes + var orderedX = [rect1[0], rect1[2], rect2[0], rect2[2]].sort(compare), + orderedY = [rect1[1], rect1[3], rect2[1], rect2[3]].sort(compare), + result = []; + + rect1 = Util.normalizeRect(rect1); + rect2 = Util.normalizeRect(rect2); + + // X: first and second points belong to different rectangles? + if ((orderedX[0] === rect1[0] && orderedX[1] === rect2[0]) || + (orderedX[0] === rect2[0] && orderedX[1] === rect1[0])) { + // Intersection must be between second and third points + result[0] = orderedX[1]; + result[2] = orderedX[2]; + } else { + return false; + } + + // Y: first and second points belong to different rectangles? + if ((orderedY[0] === rect1[1] && orderedY[1] === rect2[1]) || + (orderedY[0] === rect2[1] && orderedY[1] === rect1[1])) { + // Intersection must be between second and third points + result[1] = orderedY[1]; + result[3] = orderedY[2]; + } else { + return false; + } + + return result; + }; + + Util.sign = function Util_sign(num) { + return num < 0 ? -1 : 1; + }; + + // TODO(mack): Rename appendToArray + Util.concatenateToArray = function concatenateToArray(arr1, arr2) { + Array.prototype.push.apply(arr1, arr2); + }; + + Util.prependToArray = function concatenateToArray(arr1, arr2) { + Array.prototype.unshift.apply(arr1, arr2); + }; + + Util.extendObj = function extendObj(obj1, obj2) { + for (var key in obj2) { + obj1[key] = obj2[key]; + } + }; + + Util.getInheritableProperty = function Util_getInheritableProperty(dict, + name) { + while (dict && !dict.has(name)) { + dict = dict.get('Parent'); + } + if (!dict) { + return null; + } + return dict.get(name); + }; + + Util.inherit = function Util_inherit(sub, base, prototype) { + sub.prototype = Object.create(base.prototype); + sub.prototype.constructor = sub; + for (var prop in prototype) { + sub.prototype[prop] = prototype[prop]; + } + }; + + Util.loadScript = function Util_loadScript(src, callback) { + var script = document.createElement('script'); + var loaded = false; + script.setAttribute('src', src); + if (callback) { + script.onload = function() { + if (!loaded) { + callback(); + } + loaded = true; + }; + } + document.getElementsByTagName('head')[0].appendChild(script); + }; + + return Util; +})(); + +var PageViewport = PDFJS.PageViewport = (function PageViewportClosure() { + function PageViewport(viewBox, scale, rotation, offsetX, offsetY, dontFlip) { + this.viewBox = viewBox; + this.scale = scale; + this.rotation = rotation; + this.offsetX = offsetX; + this.offsetY = offsetY; + + // creating transform to convert pdf coordinate system to the normal + // canvas like coordinates taking in account scale and rotation + var centerX = (viewBox[2] + viewBox[0]) / 2; + var centerY = (viewBox[3] + viewBox[1]) / 2; + var rotateA, rotateB, rotateC, rotateD; + rotation = rotation % 360; + rotation = rotation < 0 ? rotation + 360 : rotation; + switch (rotation) { + case 180: + rotateA = -1; rotateB = 0; rotateC = 0; rotateD = 1; + break; + case 90: + rotateA = 0; rotateB = 1; rotateC = 1; rotateD = 0; + break; + case 270: + rotateA = 0; rotateB = -1; rotateC = -1; rotateD = 0; + break; + //case 0: + default: + rotateA = 1; rotateB = 0; rotateC = 0; rotateD = -1; + break; + } + + if (dontFlip) { + rotateC = -rotateC; rotateD = -rotateD; + } + + var offsetCanvasX, offsetCanvasY; + var width, height; + if (rotateA === 0) { + offsetCanvasX = Math.abs(centerY - viewBox[1]) * scale + offsetX; + offsetCanvasY = Math.abs(centerX - viewBox[0]) * scale + offsetY; + width = Math.abs(viewBox[3] - viewBox[1]) * scale; + height = Math.abs(viewBox[2] - viewBox[0]) * scale; + } else { + offsetCanvasX = Math.abs(centerX - viewBox[0]) * scale + offsetX; + offsetCanvasY = Math.abs(centerY - viewBox[1]) * scale + offsetY; + width = Math.abs(viewBox[2] - viewBox[0]) * scale; + height = Math.abs(viewBox[3] - viewBox[1]) * scale; + } + // creating transform for the following operations: + // translate(-centerX, -centerY), rotate and flip vertically, + // scale, and translate(offsetCanvasX, offsetCanvasY) + this.transform = [ + rotateA * scale, + rotateB * scale, + rotateC * scale, + rotateD * scale, + offsetCanvasX - rotateA * scale * centerX - rotateC * scale * centerY, + offsetCanvasY - rotateB * scale * centerX - rotateD * scale * centerY + ]; + + this.width = width; + this.height = height; + this.fontScale = scale; + } + PageViewport.prototype = { + clone: function PageViewPort_clone(args) { + args = args || {}; + var scale = 'scale' in args ? args.scale : this.scale; + var rotation = 'rotation' in args ? args.rotation : this.rotation; + return new PageViewport(this.viewBox.slice(), scale, rotation, + this.offsetX, this.offsetY, args.dontFlip); + }, + convertToViewportPoint: function PageViewport_convertToViewportPoint(x, y) { + return Util.applyTransform([x, y], this.transform); + }, + 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]]; + }, + convertToPdfPoint: function PageViewport_convertToPdfPoint(x, y) { + return Util.applyInverseTransform([x, y], this.transform); + } + }; + return PageViewport; +})(); + +var PDFStringTranslateTable = [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0x2D8, 0x2C7, 0x2C6, 0x2D9, 0x2DD, 0x2DB, 0x2DA, 0x2DC, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2022, 0x2020, 0x2021, 0x2026, 0x2014, + 0x2013, 0x192, 0x2044, 0x2039, 0x203A, 0x2212, 0x2030, 0x201E, 0x201C, + 0x201D, 0x2018, 0x2019, 0x201A, 0x2122, 0xFB01, 0xFB02, 0x141, 0x152, 0x160, + 0x178, 0x17D, 0x131, 0x142, 0x153, 0x161, 0x17E, 0, 0x20AC +]; + +function stringToPDFString(str) { + var i, n = str.length, str2 = ''; + 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)); + } else { + for (i = 0; i < n; ++i) { + var code = PDFStringTranslateTable[str.charCodeAt(i)]; + str2 += code ? String.fromCharCode(code) : str.charAt(i); + } + } + return str2; +} + +function stringToUTF8String(str) { + return decodeURIComponent(escape(str)); +} + +function isEmptyObj(obj) { + for (var key in obj) { + return false; + } + return true; +} + +function isBool(v) { + return typeof v == 'boolean'; +} + +function isInt(v) { + return typeof v == 'number' && ((v | 0) == v); +} + +function isNum(v) { + return typeof v == 'number'; +} + +function isString(v) { + return typeof v == 'string'; +} + +function isNull(v) { + return v === null; +} + +function isName(v) { + return v instanceof Name; +} + +function isCmd(v, cmd) { + return v instanceof Cmd && (!cmd || v.cmd == cmd); +} + +function isDict(v, type) { + if (!(v instanceof Dict)) { + return false; + } + if (!type) { + return true; + } + var dictType = v.get('Type'); + return isName(dictType) && dictType.name == type; +} + +function isArray(v) { + return v instanceof Array; +} + +function isStream(v) { + return typeof v == 'object' && v !== null && v !== undefined && + ('getBytes' in v); +} + +function isArrayBuffer(v) { + return typeof v == 'object' && v !== null && v !== undefined && + ('byteLength' in v); +} + +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'); +} + +/** + * Legacy support for PDFJS Promise implementation. + * TODO remove eventually + */ +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; + }; +})(); + +/** + * Polyfill for Promises: + * The following promise implementation tries to generally implment the + * Promise/A+ spec. Some notable differences from other promise libaries are: + * - There currently isn't a seperate deferred and promise object. + * - Unhandled rejections eventually show an error if they aren't handled. + * + * Based off of the work in: + * https://bugzilla.mozilla.org/show_bug.cgi?id=810490 + */ +(function PromiseClosure() { + if (globalScope.Promise) { + // Promises existing in the DOM/Worker, checking presence of all/resolve + if (typeof globalScope.Promise.all !== 'function') { + globalScope.Promise.all = function (iterable) { + var count = 0, results = [], resolve, reject; + var promise = new globalScope.Promise(function (resolve_, reject_) { + resolve = resolve_; + reject = reject_; + }); + iterable.forEach(function (p, i) { + count++; + p.then(function (result) { + results[i] = result; + count--; + if (count === 0) { + resolve(results); + } + }, reject); + }); + if (count === 0) { + resolve(results); + } + return promise; + }; + } + if (typeof globalScope.Promise.resolve !== 'function') { + globalScope.Promise.resolve = function (x) { + return new globalScope.Promise(function (resolve) { resolve(x); }); + }; + } + return; + } + var STATUS_PENDING = 0; + var STATUS_RESOLVED = 1; + var STATUS_REJECTED = 2; + + // In an attempt to avoid silent exceptions, unhandled rejections are + // tracked and if they aren't handled in a certain amount of time an + // error is logged. + var REJECTION_TIMEOUT = 500; + + var HandlerManager = { + handlers: [], + running: false, + unhandledRejections: [], + pendingRejectionCheck: false, + + scheduleHandlers: function scheduleHandlers(promise) { + if (promise._status == STATUS_PENDING) { + return; + } + + this.handlers = this.handlers.concat(promise._handlers); + promise._handlers = []; + + if (this.running) { + return; + } + this.running = true; + + setTimeout(this.runHandlers.bind(this), 0); + }, + + runHandlers: function runHandlers() { + var RUN_TIMEOUT = 1; // ms + var timeoutAt = Date.now() + RUN_TIMEOUT; + while (this.handlers.length > 0) { + var handler = this.handlers.shift(); + + var nextStatus = handler.thisPromise._status; + var nextValue = handler.thisPromise._value; + + try { + if (nextStatus === STATUS_RESOLVED) { + if (typeof(handler.onResolve) == 'function') { + nextValue = handler.onResolve(nextValue); + } + } else if (typeof(handler.onReject) === 'function') { + nextValue = handler.onReject(nextValue); + nextStatus = STATUS_RESOLVED; + + if (handler.thisPromise._unhandledRejection) { + this.removeUnhandeledRejection(handler.thisPromise); + } + } + } catch (ex) { + nextStatus = STATUS_REJECTED; + nextValue = ex; + } + + handler.nextPromise._updateStatus(nextStatus, nextValue); + if (Date.now() >= timeoutAt) { + break; + } + } + + if (this.handlers.length > 0) { + setTimeout(this.runHandlers.bind(this), 0); + return; + } + + this.running = false; + }, + + addUnhandledRejection: function addUnhandledRejection(promise) { + this.unhandledRejections.push({ + promise: promise, + time: Date.now() + }); + this.scheduleRejectionCheck(); + }, + + removeUnhandeledRejection: function removeUnhandeledRejection(promise) { + promise._unhandledRejection = false; + for (var i = 0; i < this.unhandledRejections.length; i++) { + if (this.unhandledRejections[i].promise === promise) { + this.unhandledRejections.splice(i); + i--; + } + } + }, + + scheduleRejectionCheck: function scheduleRejectionCheck() { + if (this.pendingRejectionCheck) { + return; + } + this.pendingRejectionCheck = true; + setTimeout(function rejectionCheck() { + this.pendingRejectionCheck = false; + var now = Date.now(); + for (var i = 0; i < this.unhandledRejections.length; i++) { + if (now - this.unhandledRejections[i].time > REJECTION_TIMEOUT) { + var unhandled = this.unhandledRejections[i].promise._value; + var msg = 'Unhandled rejection: ' + unhandled; + if (unhandled.stack) { + msg += '\n' + unhandled.stack; + } + warn(msg); + this.unhandledRejections.splice(i); + i--; + } + } + if (this.unhandledRejections.length) { + this.scheduleRejectionCheck(); + } + }.bind(this), REJECTION_TIMEOUT); + } + }; + + function Promise(resolver) { + this._status = STATUS_PENDING; + this._handlers = []; + resolver.call(this, this._resolve.bind(this), this._reject.bind(this)); + } + /** + * Builds a promise that is resolved when all the passed in promises are + * resolved. + * @param {array} array of data and/or promises to wait for. + * @return {Promise} New dependant promise. + */ + Promise.all = function Promise_all(promises) { + var resolveAll, rejectAll; + var deferred = new Promise(function (resolve, reject) { + resolveAll = resolve; + rejectAll = reject; + }); + var unresolved = promises.length; + var results = []; + if (unresolved === 0) { + resolveAll(results); + return deferred; + } + function reject(reason) { + if (deferred._status === STATUS_REJECTED) { + return; + } + results = []; + rejectAll(reason); + } + for (var i = 0, ii = promises.length; i < ii; ++i) { + var promise = promises[i]; + var resolve = (function(i) { + return function(value) { + if (deferred._status === STATUS_REJECTED) { + return; + } + results[i] = value; + unresolved--; + if (unresolved === 0) + resolveAll(results); + }; + })(i); + if (Promise.isPromise(promise)) { + promise.then(resolve, reject); + } else { + resolve(promise); + } + } + return deferred; + }; + + /** + * Checks if the value is likely a promise (has a 'then' function). + * @return {boolean} true if x is thenable + */ + Promise.isPromise = function Promise_isPromise(value) { + return value && typeof value.then === 'function'; + }; + /** + * Creates resolved promise + * @param x resolve value + * @returns {Promise} + */ + Promise.resolve = function Promise_resolve(x) { + return new Promise(function (resolve) { resolve(x); }); + }; + + Promise.prototype = { + _status: null, + _value: null, + _handlers: null, + _unhandledRejection: null, + + _updateStatus: function Promise__updateStatus(status, value) { + if (this._status === STATUS_RESOLVED || + this._status === STATUS_REJECTED) { + return; + } + + if (status == STATUS_RESOLVED && + Promise.isPromise(value)) { + value.then(this._updateStatus.bind(this, STATUS_RESOLVED), + this._updateStatus.bind(this, STATUS_REJECTED)); + return; + } + + this._status = status; + this._value = value; + + if (status === STATUS_REJECTED && this._handlers.length === 0) { + this._unhandledRejection = true; + HandlerManager.addUnhandledRejection(this); + } + + HandlerManager.scheduleHandlers(this); + }, + + _resolve: function Promise_resolve(value) { + this._updateStatus(STATUS_RESOLVED, value); + }, + + _reject: function Promise_reject(reason) { + this._updateStatus(STATUS_REJECTED, reason); + }, + + then: function Promise_then(onResolve, onReject) { + var nextPromise = new Promise(function (resolve, reject) { + this.resolve = reject; + this.reject = reject; + }); + this._handlers.push({ + thisPromise: this, + onResolve: onResolve, + onReject: onReject, + nextPromise: nextPromise + }); + HandlerManager.scheduleHandlers(this); + return nextPromise; + } + }; + + globalScope.Promise = Promise; +})(); + +var StatTimer = (function StatTimerClosure() { + function rpad(str, pad, length) { + while (str.length < length) + str += pad; + return str; + } + function StatTimer() { + this.started = {}; + this.times = []; + this.enabled = true; + } + StatTimer.prototype = { + time: function StatTimer_time(name) { + if (!this.enabled) + return; + if (name in this.started) + warn('Timer is already running for ' + name); + this.started[name] = Date.now(); + }, + timeEnd: function StatTimer_timeEnd(name) { + if (!this.enabled) + return; + if (!(name in this.started)) + warn('Timer has not been started for ' + name); + this.times.push({ + 'name': name, + 'start': this.started[name], + 'end': Date.now() + }); + // Remove timer from started so it can be called again. + delete this.started[name]; + }, + toString: function StatTimer_toString() { + var 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) { + var name = times[i]['name']; + if (name.length > longest) + longest = name.length; + } + for (var i = 0, ii = times.length; i < ii; ++i) { + var span = times[i]; + var duration = span.end - span.start; + out += rpad(span['name'], ' ', longest) + ' ' + duration + 'ms\n'; + } + return out; + } + }; + return StatTimer; +})(); + +PDFJS.createBlob = function createBlob(data, contentType) { + if (typeof Blob !== 'undefined') + return new Blob([data], { type: contentType }); + // Blob builder is deprecated in FF14 and removed in FF18. + var bb = new MozBlobBuilder(); + bb.append(data); + return bb.getBlob(contentType); +}; + +PDFJS.createObjectURL = (function createObjectURLClosure() { + // Blob/createObjectURL is not available, falling back to data schema. + var digits = + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; + + return function createObjectURL(data, contentType) { + if (!PDFJS.disableCreateObjectURL && + typeof URL !== 'undefined' && URL.createObjectURL) { + var blob = PDFJS.createBlob(data, contentType); + return URL.createObjectURL(blob); + } + + var buffer = 'data:' + contentType + ';base64,'; + for (var i = 0, ii = data.length; i < ii; i += 3) { + var b1 = data[i] & 0xFF; + var b2 = data[i + 1] & 0xFF; + var b3 = data[i + 2] & 0xFF; + var d1 = b1 >> 2, d2 = ((b1 & 3) << 4) | (b2 >> 4); + var d3 = i + 1 < ii ? ((b2 & 0xF) << 2) | (b3 >> 6) : 64; + var d4 = i + 2 < ii ? (b3 & 0x3F) : 64; + buffer += digits[d1] + digits[d2] + digits[d3] + digits[d4]; + } + return buffer; + }; +})(); + +function MessageHandler(name, comObj) { + this.name = name; + this.comObj = comObj; + this.callbackIndex = 1; + this.postMessageTransfers = true; + var callbacks = this.callbacks = {}; + var ah = this.actionHandler = {}; + + ah['console_log'] = [function ahConsoleLog(data) { + console.log.apply(console, data); + }]; + ah['console_error'] = [function ahConsoleError(data) { + console.error.apply(console, data); + }]; + ah['_unsupported_feature'] = [function ah_unsupportedFeature(data) { + UnsupportedManager.notify(data); + }]; + + comObj.onmessage = function messageHandlerComObjOnMessage(event) { + var data = event.data; + if (data.isReply) { + var callbackId = data.callbackId; + if (data.callbackId in callbacks) { + var callback = callbacks[callbackId]; + delete callbacks[callbackId]; + callback(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) { + comObj.postMessage({ + isReply: true, + callbackId: data.callbackId, + data: resolvedData + }); + }); + action[0].call(action[1], data.data, deferred); + } else { + action[0].call(action[1], data.data); + } + } else { + error('Unkown action from worker: ' + data.action); + } + }; +} + +MessageHandler.prototype = { + on: function messageHandlerOn(actionName, handler, scope) { + var ah = this.actionHandler; + if (ah[actionName]) { + error('There is already an actionName called "' + actionName + '"'); + } + ah[actionName] = [handler, scope]; + }, + /** + * Sends a message to the comObj to invoke the action with the supplied data. + * @param {String} actionName Action to call. + * @param {JSON} data JSON data to send. + * @param {function} [callback] Optional callback that will handle a reply. + * @param {Array} [transfers] Optional list of transfers/ArrayBuffers + */ + send: function messageHandlerSend(actionName, data, callback, transfers) { + var message = { + action: actionName, + data: data + }; + if (callback) { + var callbackId = this.callbackIndex++; + this.callbacks[callbackId] = callback; + message.callbackId = callbackId; + } + if (transfers && this.postMessageTransfers) { + this.comObj.postMessage(message, transfers); + } else { + this.comObj.postMessage(message); + } + } +}; + +function loadJpegStream(id, imageUrl, objs) { + var img = new Image(); + img.onload = (function loadJpegStream_onloadClosure() { + objs.resolve(id, img); + }); + img.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; + +/** + * By default fonts are converted to OpenType fonts and loaded via font face + * rules. If disabled, the font will be rendered using a built in font renderer + * that constructs the glyphs with primitive path commands. + * @var {boolean} + */ +PDFJS.disableFontFace = PDFJS.disableFontFace === undefined ? + false : PDFJS.disableFontFace; + +/** + * Path for image resources, mainly for annotation icons. Include trailing + * slash. + * @var {string} + */ +PDFJS.imageResourcesPath = PDFJS.imageResourcesPath === undefined ? + '' : PDFJS.imageResourcesPath; + +/** + * Disable the web worker and run all code on the main thread. This will happen + * automatically if the browser doesn't support workers or sending typed arrays + * to workers. + * @var {boolean} + */ +PDFJS.disableWorker = PDFJS.disableWorker === undefined ? + false : PDFJS.disableWorker; + +/** + * Path and filename of the worker file. Required when the worker is enabled in + * development mode. If unspecified in the production build, the worker will be + * loaded based on the location of the pdf.js file. + * @var {string} + */ +PDFJS.workerSrc = PDFJS.workerSrc === undefined ? null : PDFJS.workerSrc; + +/** + * Disable range request loading of PDF files. When enabled and if the server + * supports partial content requests then the PDF will be fetched in chunks. + * Enabled (false) by default. + * @var {boolean} + */ +PDFJS.disableRange = PDFJS.disableRange === undefined ? + false : PDFJS.disableRange; + +/** + * Disable pre-fetching of PDF file data. When range requests are enabled PDF.js + * will automatically keep fetching more data even if it isn't needed to display + * the current page. This default behavior can be disabled. + * @var {boolean} + */ +PDFJS.disableAutoFetch = PDFJS.disableAutoFetch === undefined ? + false : PDFJS.disableAutoFetch; + +/** + * Enables special hooks for debugging PDF.js. + * @var {boolean} + */ +PDFJS.pdfBug = PDFJS.pdfBug === undefined ? false : PDFJS.pdfBug; + +/** + * Enables transfer usage in postMessage for ArrayBuffers. + * @var {boolean} + */ +PDFJS.postMessageTransfers = PDFJS.postMessageTransfers === undefined ? + true : PDFJS.postMessageTransfers; + +/** + * Disables URL.createObjectURL usage. + * @var {boolean} + */ +PDFJS.disableCreateObjectURL = PDFJS.disableCreateObjectURL === undefined ? + false : PDFJS.disableCreateObjectURL; + +/** + * Controls the logging level. + * The constants from PDFJS.VERBOSITY_LEVELS should be used: + * - errors + * - warnings [default] + * - infos + * @var {number} + */ +PDFJS.verbosity = PDFJS.verbosity === undefined ? + PDFJS.VERBOSITY_LEVELS.warnings : PDFJS.verbosity; + +/** + * Document initialization / loading parameters object. + * + * @typedef {Object} DocumentInitParameters + * @property {string} url - The URL of the PDF. + * @property {TypedArray} data - A typed array with PDF data. + * @property {Object} httpHeaders - Basic authentication headers. + * @property {boolean} withCredentials - Indicates whether or not cross-site + * Access-Control requests should be made using credentials such as cookies + * or authorization headers. The default is false. + * @property {string} password - For decrypting password-protected PDFs. + * @property {TypedArray} initialData - A typed array with the first portion or + * all of the pdf data. Used by the extension since some data is already + * loaded before the switch to range requests. + */ + +/** + * This is the main entry point for loading a PDF and interacting with it. + * NOTE: If a URL is used to fetch the PDF data a standard XMLHttpRequest(XHR) + * is used, which means it must follow the same origin rules that any XHR does + * e.g. No cross domain requests without CORS. + * + * @param {string|TypedArray|DocumentInitParameters} source Can be a url to + * where a PDF is located, a typed array (Uint8Array) already populated with + * data or parameter object. + * + * @param {Object} pdfDataRangeTransport is optional. It is used if you want + * to manually serve range requests for data in the PDF. See viewer.js for + * an example of pdfDataRangeTransport's interface. + * + * @param {function} passwordCallback is optional. It is used to request a + * password if wrong or no password was provided. The callback receives two + * parameters: function that needs to be called with new password and reason + * (see {PasswordResponses}). + * + * @return {Promise} A promise that is resolved with {@link PDFDocumentProxy} + * object. + */ +PDFJS.getDocument = function getDocument(source, + pdfDataRangeTransport, + passwordCallback, + progressCallback) { + var workerInitializedPromise, workerReadyPromise, transport; + + if (typeof source === 'string') { + source = { url: source }; + } else if (isArrayBuffer(source)) { + source = { data: source }; + } else if (typeof source !== 'object') { + error('Invalid parameter in getDocument, need either Uint8Array, ' + + 'string or a parameter object'); + } + + 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 = {}; + for (var key in source) { + if (key === 'url' && typeof window !== 'undefined') { + params[key] = combineUrl(window.location.href, source[key]); + continue; + } + params[key] = source[key]; + } + + workerInitializedPromise = new PDFJS.LegacyPromise(); + workerReadyPromise = new PDFJS.LegacyPromise(); + transport = new WorkerTransport(workerInitializedPromise, + workerReadyPromise, pdfDataRangeTransport, progressCallback); + workerInitializedPromise.then(function transportInitialized() { + transport.passwordCallback = passwordCallback; + transport.fetchDocument(params); + }); + return workerReadyPromise; +}; + +/** + * Proxy to a PDFDocument in the worker thread. Also, contains commonly used + * properties that can be read synchronously. + * @class + */ +var PDFDocumentProxy = (function PDFDocumentProxyClosure() { + function PDFDocumentProxy(pdfInfo, transport) { + this.pdfInfo = pdfInfo; + this.transport = transport; + } + PDFDocumentProxy.prototype = /** @lends PDFDocumentProxy.prototype */ { + /** + * @return {number} Total number of pages the PDF contains. + */ + get numPages() { + return this.pdfInfo.numPages; + }, + /** + * @return {string} A unique ID to identify a PDF. Not guaranteed to be + * unique. + */ + get fingerprint() { + return this.pdfInfo.fingerprint; + }, + /** + * @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} + * object. + */ + getPage: function PDFDocumentProxy_getPage(pageNumber) { + return this.transport.getPage(pageNumber); + }, + /** + * @param {{num: number, gen: number}} ref The page reference. Must have + * the 'num' and 'gen' properties. + * @return {Promise} A promise that is resolved with the page index that is + * associated with the reference. + */ + getPageIndex: function PDFDocumentProxy_getPageIndex(ref) { + return this.transport.getPageIndex(ref); + }, + /** + * @return {Promise} A promise that is resolved with a lookup table for + * mapping named destinations to reference numbers. + */ + getDestinations: function PDFDocumentProxy_getDestinations() { + return this.transport.getDestinations(); + }, + /** + * @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 {Promise} A promise that is resolved with an {Array} that is a + * tree outline (if it has one) of the PDF. The tree is in the format of: + * [ + * { + * title: string, + * bold: boolean, + * italic: boolean, + * color: rgb array, + * dest: dest obj, + * items: array of more items like this + * }, + * ... + * ]. + */ + getOutline: function PDFDocumentProxy_getOutline() { + var promise = new PDFJS.LegacyPromise(); + var outline = this.pdfInfo.outline; + promise.resolve(outline); + return promise; + }, + /** + * @return {Promise} A promise that is resolved with an {Object} that has + * info and metadata properties. Info is an {Object} filled with anything + * available in the information dictionary and similarly metadata is a + * {Metadata} object with information from the metadata section of the PDF. + */ + getMetadata: function PDFDocumentProxy_getMetadata() { + 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 {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 {Promise} A promise that is resolved when the document's data + * is loaded + */ + dataLoaded: function PDFDocumentProxy_dataLoaded() { + return this.transport.dataLoaded(); + }, + /** + * Cleans up resources allocated by the document, e.g. created @font-face. + */ + cleanup: function PDFDocumentProxy_cleanup() { + this.transport.startCleanup(); + }, + /** + * Destroys current document instance and terminates worker. + */ + destroy: function PDFDocumentProxy_destroy() { + this.transport.destroy(); + } + }; + return PDFDocumentProxy; +})(); + +/** + * Page text content part. + * + * @typedef {Object} BidiText + * @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. + */ + +/** + * Proxy to a PDFPage in the worker thread. + * @class + */ +var PDFPageProxy = (function PDFPageProxyClosure() { + function PDFPageProxy(pageInfo, transport) { + 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 = []; + } + PDFPageProxy.prototype = /** @lends PDFPageProxy.prototype */ { + /** + * @return {number} Page number of the page. First page is 1. + */ + get pageNumber() { + return this.pageInfo.pageIndex + 1; + }, + /** + * @return {number} The number of degrees the page is rotated clockwise. + */ + get rotate() { + return this.pageInfo.rotate; + }, + /** + * @return {Object} The reference that points to this page. It has 'num' and + * 'gen' properties. + */ + get ref() { + return this.pageInfo.ref; + }, + /** + * @return {Array} An array of the visible portion of the PDF page in the + * user space units - [x1, y1, x2, y2]. + */ + get view() { + return this.pageInfo.view; + }, + /** + * @param {number} scale The desired scale of the viewport. + * @param {number} rotate Degrees to rotate the viewport. If omitted this + * defaults to the page rotation. + * @return {PageViewport} Contains 'width' and 'height' properties along + * with transforms required for rendering. + */ + getViewport: function PDFPageProxy_getViewport(scale, rotate) { + if (arguments.length < 2) + rotate = this.rotate; + return new PDFJS.PageViewport(this.view, scale, rotate, 0, 0); + }, + /** + * @return {Promise} A promise that is resolved with an {Array} of the + * annotation objects. + */ + getAnnotations: function PDFPageProxy_getAnnotations() { + if (this.annotationsPromise) + return this.annotationsPromise; + + var promise = new PDFJS.LegacyPromise(); + 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). + */ + render: function PDFPageProxy_render(params) { + var stats = this.stats; + stats.time('Overall'); + + // If there was a pending destroy cancel it so no cleanup happens during + // this call to render. + this.pendingDestroy = false; + + // 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 = { + fnArray: [], + argsArray: [], + lastChunk: false + }; + + this.stats.time('Page Request'); + this.transport.messageHandler.send('RenderPageRequest', { + pageIndex: this.pageNumber - 1 + }); + } + + var internalRenderTask = new InternalRenderTask(complete, params, + this.objs, this.commonObjs, + this.operatorList, this.pageNumber); + this.renderTasks.push(internalRenderTask); + var renderTask = new RenderTask(internalRenderTask); + + var self = this; + this.displayReadyPromise.then( + function pageDisplayReadyPromise(transparency) { + if (self.pendingDestroy) { + complete(); + return; + } + stats.time('Rendering'); + internalRenderTask.initalizeGraphics(transparency); + internalRenderTask.operatorListChanged(); + }, + function pageDisplayReadPromiseError(reason) { + complete(reason); + } + ); + + function complete(error) { + var i = self.renderTasks.indexOf(internalRenderTask); + if (i >= 0) { + self.renderTasks.splice(i, 1); + } + + if (self.cleanupAfterRender) { + self.pendingDestroy = true; + } + self._tryDestroy(); + + if (error) { + renderTask.promise.reject(error); + } else { + renderTask.promise.resolve(); + } + stats.timeEnd('Rendering'); + stats.timeEnd('Overall'); + } + + return renderTask; + }, + /** + * @return {Promise} That is resolved with the array of {@link BidiText} + * objects 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; + }, + /** + * Destroys resources allocated by the page. + */ + destroy: function PDFPageProxy_destroy() { + this.pendingDestroy = true; + this._tryDestroy(); + }, + /** + * For internal use only. Attempts to clean up if rendering is in a state + * where that's possible. + * @ignore + */ + _tryDestroy: function PDFPageProxy__destroy() { + if (!this.pendingDestroy || + this.renderTasks.length !== 0 || + this.receivingOperatorList) { + return; + } + + delete this.operatorList; + delete this.displayReadyPromise; + this.objs.clear(); + this.pendingDestroy = false; + }, + /** + * For internal use only. + * @ignore + */ + _startRenderPage: function PDFPageProxy_startRenderPage(transparency) { + this.displayReadyPromise.resolve(transparency); + }, + /** + * For internal use only. + * @ignore + */ + _renderPageChunk: function PDFPageProxy_renderPageChunk(operatorListChunk) { + // 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]); + } + this.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(); + } + + if (operatorListChunk.lastChunk) { + this.receivingOperatorList = false; + this._tryDestroy(); + } + } + }; + return PDFPageProxy; +})(); + +/** + * For internal use only. + * @ignore + */ +var WorkerTransport = (function WorkerTransportClosure() { + function WorkerTransport(workerInitializedPromise, workerReadyPromise, + pdfDataRangeTransport, progressCallback) { + this.pdfDataRangeTransport = pdfDataRangeTransport; + + this.workerReadyPromise = workerReadyPromise; + this.progressCallback = progressCallback; + this.commonObjs = new PDFObjects(); + + this.pageCache = []; + this.pagePromises = []; + this.embeddedFontsUsed = false; + + this.passwordCallback = null; + + // If worker support isn't disabled explicit and the browser has worker + // support, create a new web worker and test if it/the browser fullfills + // all requirements to run parts of pdf.js in a web worker. + // Right now, the requirement is, that an Uint8Array is still an Uint8Array + // as it arrives on the worker. Chrome added this with version 15. + if (!globalScope.PDFJS.disableWorker && typeof Worker !== 'undefined') { + var workerSrc = PDFJS.workerSrc; + if (!workerSrc) { + error('No PDFJS.workerSrc specified'); + } + + try { + // Some versions of FF can't create a worker on localhost, see: + // https://bugzilla.mozilla.org/show_bug.cgi?id=683280 + var worker = new Worker(workerSrc); + var messageHandler = new MessageHandler('main', worker); + this.messageHandler = messageHandler; + + messageHandler.on('test', function transportTest(data) { + var supportTypedArray = data && data.supportTypedArray; + if (supportTypedArray) { + this.worker = worker; + if (!data.supportTransfers) { + PDFJS.postMessageTransfers = false; + } + this.setupMessageHandler(messageHandler); + workerInitializedPromise.resolve(); + } else { + globalScope.PDFJS.disableWorker = true; + this.loadFakeWorkerFiles().then(function() { + this.setupFakeWorker(); + workerInitializedPromise.resolve(); + }.bind(this)); + } + }.bind(this)); + + var testObj = new Uint8Array([PDFJS.postMessageTransfers ? 255 : 0]); + // Some versions of Opera throw a DATA_CLONE_ERR on serializing the + // typed array. Also, checking if we can use transfers. + try { + messageHandler.send('test', testObj, null, [testObj.buffer]); + } catch (ex) { + info('Cannot use postMessage transfers'); + testObj[0] = 0; + messageHandler.send('test', testObj); + } + return; + } catch (e) { + info('The worker has been disabled.'); + } + } + // 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)); + } + WorkerTransport.prototype = { + destroy: function WorkerTransport_destroy() { + this.pageCache = []; + this.pagePromises = []; + var self = this; + this.messageHandler.send('Terminate', null, function () { + FontLoader.clear(); + if (self.worker) { + self.worker.terminate(); + } + }); + }, + + loadFakeWorkerFiles: function WorkerTransport_loadFakeWorkerFiles() { + if (!PDFJS.fakeWorkerFilesLoadedPromise) { + PDFJS.fakeWorkerFilesLoadedPromise = new LegacyPromise(); + // 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(); + }); + } + return PDFJS.fakeWorkerFilesLoadedPromise; + }, + + 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); + + // If the main thread is our worker, setup the handling for the messages + // the main thread sends to it self. + PDFJS.WorkerMessageHandler.setup(messageHandler); + }, + + setupMessageHandler: + function WorkerTransport_setupMessageHandler(messageHandler) { + this.messageHandler = messageHandler; + + function updatePassword(password) { + messageHandler.send('UpdatePassword', password); + } + + var pdfDataRangeTransport = this.pdfDataRangeTransport; + if (pdfDataRangeTransport) { + pdfDataRangeTransport.addRangeListener(function(begin, chunk) { + messageHandler.send('OnDataRange', { + begin: begin, + chunk: chunk + }); + }); + + pdfDataRangeTransport.addProgressListener(function(loaded) { + messageHandler.send('OnDataProgress', { + loaded: loaded + }); + }); + + messageHandler.on('RequestDataRange', + function transportDataRange(data) { + pdfDataRangeTransport.requestDataRange(data.begin, data.end); + }, this); + } + + messageHandler.on('GetDoc', function transportDoc(data) { + var pdfInfo = data.pdfInfo; + var pdfDocument = new PDFDocumentProxy(pdfInfo, this); + this.pdfDocument = pdfDocument; + this.workerReadyPromise.resolve(pdfDocument); + }, this); + + messageHandler.on('NeedPassword', function transportPassword(data) { + if (this.passwordCallback) { + return this.passwordCallback(updatePassword, + PasswordResponses.NEED_PASSWORD); + } + this.workerReadyPromise.reject(data.exception.message, data.exception); + }, this); + + messageHandler.on('IncorrectPassword', function transportBadPass(data) { + if (this.passwordCallback) { + return this.passwordCallback(updatePassword, + PasswordResponses.INCORRECT_PASSWORD); + } + this.workerReadyPromise.reject(data.exception.message, data.exception); + }, this); + + messageHandler.on('InvalidPDF', function transportInvalidPDF(data) { + this.workerReadyPromise.reject(data.exception.name, data.exception); + }, this); + + messageHandler.on('MissingPDF', function transportMissingPDF(data) { + this.workerReadyPromise.reject(data.exception.message, data.exception); + }, this); + + messageHandler.on('UnknownError', function transportUnknownError(data) { + this.workerReadyPromise.reject(data.exception.message, data.exception); + }, 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); + }, this); + + messageHandler.on('GetAnnotations', function transportAnnotations(data) { + var annotations = data.annotations; + var promise = this.pageCache[data.pageIndex].annotationsPromise; + promise.resolve(annotations); + }, this); + + messageHandler.on('StartRenderPage', function transportRender(data) { + var page = this.pageCache[data.pageIndex]; + + page.stats.timeEnd('Page Request'); + page._startRenderPage(data.transparency); + }, this); + + messageHandler.on('RenderPageChunk', function transportRender(data) { + var page = this.pageCache[data.pageIndex]; + + page._renderPageChunk(data.operatorList); + }, this); + + messageHandler.on('commonobj', function transportObj(data) { + var id = data[0]; + var type = data[1]; + if (this.commonObjs.hasData(id)) + return; + + switch (type) { + case 'Font': + var exportedData = data[2]; + + var font; + if ('error' in exportedData) { + var error = exportedData.error; + warn('Error during font loading: ' + error); + this.commonObjs.resolve(id, error); + break; + } else { + font = new FontFace(exportedData); + } + + FontLoader.bind( + [font], + function fontReady(fontObjs) { + this.commonObjs.resolve(id, font); + }.bind(this) + ); + break; + case 'FontPath': + this.commonObjs.resolve(id, data[2]); + break; + default: + error('Got unknown common object type ' + type); + } + }, this); + + messageHandler.on('obj', function transportObj(data) { + var id = data[0]; + var pageIndex = data[1]; + var type = data[2]; + var pageProxy = this.pageCache[pageIndex]; + if (pageProxy.objs.hasData(id)) + return; + + switch (type) { + case 'JpegStream': + var imageData = data[3]; + loadJpegStream(id, imageData, pageProxy.objs); + break; + case 'Image': + var 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 && + imageData.data.length > MAX_IMAGE_SIZE_TO_STORE) { + pageProxy.cleanupAfterRender = true; + } + break; + default: + error('Got unknown object type ' + type); + } + }, this); + + messageHandler.on('DocProgress', function transportDocProgress(data) { + if (this.progressCallback) { + this.progressCallback({ + loaded: data.loaded, + total: data.total + }); + } + }, 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 + error(data.error); + }, this); + + messageHandler.on('JpegDecode', function(data, deferred) { + var imageUrl = data[0]; + var components = data[1]; + if (components != 3 && components != 1) + error('Only 3 component 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; + + 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]; + } + } 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; + }); + }, + + fetchDocument: function WorkerTransport_fetchDocument(source) { + source.disableAutoFetch = PDFJS.disableAutoFetch; + source.chunkedViewerLoading = !!this.pdfDataRangeTransport; + this.messageHandler.send('GetDocRequest', { + source: source, + disableRange: PDFJS.disableRange, + maxImageSize: PDFJS.maxImageSize, + disableFontFace: PDFJS.disableFontFace, + disableCreateObjectURL: PDFJS.disableCreateObjectURL, + verbosity: PDFJS.verbosity + }); + }, + + getData: function WorkerTransport_getData(promise) { + this.messageHandler.send('GetData', null, function(data) { + promise.resolve(data); + }); + }, + + dataLoaded: function WorkerTransport_dataLoaded() { + if (this.dataLoadedPromise) { + return this.dataLoadedPromise; + } + 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) + return this.pagePromises[pageIndex]; + var promise = new PDFJS.LegacyPromise(); + 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; + }, + + getAnnotations: function WorkerTransport_getAnnotations(pageIndex) { + this.messageHandler.send('GetAnnotationsRequest', + { pageIndex: pageIndex }); + }, + + getDestinations: function WorkerTransport_getDestinations() { + var promise = new PDFJS.LegacyPromise(); + this.messageHandler.send('GetDestinations', null, + function transportDestinations(destinations) { + promise.resolve(destinations); + } + ); + return promise; + }, + + 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.commonObjs.clear(); + FontLoader.clear(); + }.bind(this) + ); + } + }; + return WorkerTransport; + +})(); + +/** + * A PDF document and page is built of many objects. E.g. there are objects + * for fonts, images, rendering code and such. These objects might get processed + * inside of a worker. The `PDFObjects` implements some basic functions to + * manage these objects. + * @ignore + */ +var PDFObjects = (function PDFObjectsClosure() { + function PDFObjects() { + this.objs = {}; + } + + PDFObjects.prototype = { + /** + * Internal function. + * Ensures there is an object defined for `objId`. + */ + ensureObj: function PDFObjects_ensureObj(objId) { + if (this.objs[objId]) + return this.objs[objId]; + + var obj = { + promise: new LegacyPromise(), + data: null, + resolved: false + }; + this.objs[objId] = obj; + + return obj; + }, + + /** + * If called *without* callback, this returns the data of `objId` but the + * object needs to be resolved. If it isn't, this function throws. + * + * If called *with* a callback, the callback is called with the data of the + * object once the object is resolved. That means, if you call this + * function and the object is already resolved, the callback gets called + * right away. + */ + get: function PDFObjects_get(objId, callback) { + // If there is a callback, then the get can be async and the object is + // not required to be resolved right now + if (callback) { + this.ensureObj(objId).promise.then(callback); + return null; + } + + // If there isn't a callback, the user expects to get the resolved data + // directly. + var obj = this.objs[objId]; + + // If there isn't an object yet or the object isn't resolved, then the + // data isn't ready yet! + if (!obj || !obj.resolved) + error('Requesting object that isn\'t resolved yet ' + objId); + + return obj.data; + }, + + /** + * Resolves the object `objId` with optional `data`. + */ + resolve: function PDFObjects_resolve(objId, data) { + var obj = this.ensureObj(objId); + + obj.resolved = true; + obj.data = data; + obj.promise.resolve(data); + }, + + isResolved: function PDFObjects_isResolved(objId) { + var objs = this.objs; + + if (!objs[objId]) { + return false; + } else { + return objs[objId].resolved; + } + }, + + hasData: function PDFObjects_hasData(objId) { + return this.isResolved(objId); + }, + + /** + * Returns the data of `objId` if object exists, null otherwise. + */ + getData: function PDFObjects_getData(objId) { + var objs = this.objs; + if (!objs[objId] || !objs[objId].resolved) { + return null; + } else { + return objs[objId].data; + } + }, + + clear: function PDFObjects_clear() { + this.objs = {}; + } + }; + return PDFObjects; +})(); + +/** + * Allows controlling of the rendering tasks. + * @class + */ +var RenderTask = (function RenderTaskClosure() { + function RenderTask(internalRenderTask) { + this.internalRenderTask = internalRenderTask; + /** + * Promise for rendering task completion. + * @type {Promise} + */ + this.promise = new PDFJS.LegacyPromise(); + } + + RenderTask.prototype = /** @lends RenderTask.prototype */ { + /** + * Cancels the rendering task. If the task is currently rendering it will + * not be cancelled until graphics pauses with a timeout. The promise that + * this object extends will resolved when cancelled. + */ + cancel: function RenderTask_cancel() { + this.internalRenderTask.cancel(); + this.promise.reject(new Error('Rendering is cancelled')); + } + }; + + return RenderTask; +})(); + +/** + * For internal use only. + * @ignore + */ +var InternalRenderTask = (function InternalRenderTaskClosure() { + + function InternalRenderTask(callback, params, objs, commonObjs, operatorList, + pageNumber) { + this.callback = callback; + this.params = params; + this.objs = objs; + this.commonObjs = commonObjs; + this.operatorListIdx = null; + this.operatorList = operatorList; + this.pageNumber = pageNumber; + this.running = false; + this.graphicsReadyCallback = null; + this.graphicsReady = false; + this.cancelled = false; + } + + InternalRenderTask.prototype = { + + initalizeGraphics: + function InternalRenderTask_initalizeGraphics(transparency) { + + if (this.cancelled) { + return; + } + if (PDFJS.pdfBug && 'StepperManager' in globalScope && + globalScope.StepperManager.enabled) { + this.stepper = globalScope.StepperManager.create(this.pageNumber - 1); + this.stepper.init(this.operatorList); + this.stepper.nextBreakPoint = this.stepper.getNextBreakPoint(); + } + + var params = this.params; + this.gfx = new CanvasGraphics(params.canvasContext, this.commonObjs, + this.objs, params.textLayer, + params.imageLayer); + + this.gfx.beginDrawing(params.viewport, transparency); + this.operatorListIdx = 0; + this.graphicsReady = true; + if (this.graphicsReadyCallback) { + this.graphicsReadyCallback(); + } + }, + + cancel: function InternalRenderTask_cancel() { + this.running = false; + this.cancelled = true; + this.callback('cancelled'); + }, + + operatorListChanged: function InternalRenderTask_operatorListChanged() { + if (!this.graphicsReady) { + if (!this.graphicsReadyCallback) { + this.graphicsReadyCallback = this._continue.bind(this); + } + return; + } + + if (this.stepper) { + this.stepper.updateOperatorList(this.operatorList); + } + + if (this.running) { + return; + } + this._continue(); + }, + + _continue: function InternalRenderTask__continue() { + this.running = true; + if (this.cancelled) { + return; + } + if (this.params.continueCallback) { + this.params.continueCallback(this._next.bind(this)); + } else { + this._next(); + } + }, + + _next: function InternalRenderTask__next() { + if (this.cancelled) { + return; + } + this.operatorListIdx = this.gfx.executeOperatorList(this.operatorList, + this.operatorListIdx, + this._continue.bind(this), + this.stepper); + if (this.operatorListIdx === this.operatorList.argsArray.length) { + this.running = false; + if (this.operatorList.lastChunk) { + this.gfx.endDrawing(); + this.callback(); + } + } + } + + }; + + return InternalRenderTask; +})(); + + +var Metadata = PDFJS.Metadata = (function MetadataClosure() { + function fixMetadata(meta) { + return meta.replace(/>\\376\\377([^<]+)/g, function(all, codes) { + var bytes = codes.replace(/\\([0-3])([0-7])([0-7])/g, + function(code, d1, d2, d3) { + return String.fromCharCode(d1 * 64 + d2 * 8 + d3 * 1); + }); + var chars = ''; + for (var i = 0; i < bytes.length; i += 2) { + var code = bytes.charCodeAt(i) * 256 + bytes.charCodeAt(i + 1); + chars += code >= 32 && code < 127 && code != 60 && code != 62 && + code != 38 && false ? String.fromCharCode(code) : + '&#x' + (0x10000 + code).toString(16).substring(1) + ';'; + } + return '>' + chars; + }); + } + + function Metadata(meta) { + if (typeof meta === 'string') { + // Ghostscript produces invalid metadata + meta = fixMetadata(meta); + + var parser = new DOMParser(); + meta = parser.parseFromString(meta, 'application/xml'); + } else if (!(meta instanceof Document)) { + error('Metadata: Invalid metadata object'); + } + + this.metaDocument = meta; + this.metadata = {}; + this.parse(); + } + + Metadata.prototype = { + parse: function Metadata_parse() { + var doc = this.metaDocument; + var rdf = doc.documentElement; + + if (rdf.nodeName.toLowerCase() !== 'rdf:rdf') { // Wrapped in + rdf = rdf.firstChild; + while (rdf && rdf.nodeName.toLowerCase() !== 'rdf:rdf') + rdf = rdf.nextSibling; + } + + var nodeName = (rdf) ? rdf.nodeName.toLowerCase() : null; + if (!rdf || nodeName !== 'rdf:rdf' || !rdf.hasChildNodes()) + return; + + var children = rdf.childNodes, desc, entry, name, i, ii, length, iLength; + + for (i = 0, length = children.length; i < length; i++) { + desc = children[i]; + if (desc.nodeName.toLowerCase() !== 'rdf:description') + continue; + + for (ii = 0, iLength = desc.childNodes.length; ii < iLength; ii++) { + if (desc.childNodes[ii].nodeName.toLowerCase() !== '#text') { + entry = desc.childNodes[ii]; + name = entry.nodeName.toLowerCase(); + this.metadata[name] = entry.textContent.trim(); + } + } + } + }, + + get: function Metadata_get(name) { + return this.metadata[name] || null; + }, + + has: function Metadata_has(name) { + return typeof this.metadata[name] !== 'undefined'; + } + }; + + return Metadata; +})(); + + +// contexts store most of the state we need natively. +// However, PDF needs a bit more state, which we store here. + +// Minimal font size that would be used during canvas fillText operations. +var MIN_FONT_SIZE = 16; + +var COMPILE_TYPE3_GLYPHS = true; + +function createScratchCanvas(width, height) { + var canvas = document.createElement('canvas'); + canvas.width = width; + canvas.height = height; + return canvas; +} + +function addContextCurrentTransform(ctx) { + // If the context doesn't expose a `mozCurrentTransform`, add a JS based on. + if (!ctx.mozCurrentTransform) { + // Store the original context + ctx._scaleX = ctx._scaleX || 1.0; + ctx._scaleY = ctx._scaleY || 1.0; + ctx._originalSave = ctx.save; + ctx._originalRestore = ctx.restore; + ctx._originalRotate = ctx.rotate; + ctx._originalScale = ctx.scale; + ctx._originalTranslate = ctx.translate; + ctx._originalTransform = ctx.transform; + ctx._originalSetTransform = ctx.setTransform; + + ctx._transformMatrix = [ctx._scaleX, 0, 0, ctx._scaleY, 0, 0]; + ctx._transformStack = []; + + Object.defineProperty(ctx, 'mozCurrentTransform', { + get: function getCurrentTransform() { + return this._transformMatrix; + } + }); + + Object.defineProperty(ctx, 'mozCurrentTransformInverse', { + get: function getCurrentTransformInverse() { + // Calculation done using WolframAlpha: + // http://www.wolframalpha.com/input/? + // i=Inverse+{{a%2C+c%2C+e}%2C+{b%2C+d%2C+f}%2C+{0%2C+0%2C+1}} + + var m = this._transformMatrix; + var a = m[0], b = m[1], c = m[2], d = m[3], e = m[4], f = m[5]; + + var ad_bc = a * d - b * c; + var bc_ad = b * c - a * d; + + return [ + d / ad_bc, + b / bc_ad, + c / bc_ad, + a / ad_bc, + (d * e - c * f) / bc_ad, + (b * e - a * f) / ad_bc + ]; + } + }); + + ctx.save = function ctxSave() { + var old = this._transformMatrix; + this._transformStack.push(old); + this._transformMatrix = old.slice(0, 6); + + this._originalSave(); + }; + + ctx.restore = function ctxRestore() { + var prev = this._transformStack.pop(); + if (prev) { + this._transformMatrix = prev; + this._originalRestore(); + } + }; + + ctx.translate = function ctxTranslate(x, y) { + var m = this._transformMatrix; + m[4] = m[0] * x + m[2] * y + m[4]; + m[5] = m[1] * x + m[3] * y + m[5]; + + this._originalTranslate(x, y); + }; + + ctx.scale = function ctxScale(x, y) { + var m = this._transformMatrix; + m[0] = m[0] * x; + m[1] = m[1] * x; + m[2] = m[2] * y; + m[3] = m[3] * y; + + this._originalScale(x, y); + }; + + ctx.transform = function ctxTransform(a, b, c, d, e, f) { + var m = this._transformMatrix; + this._transformMatrix = [ + m[0] * a + m[2] * b, + m[1] * a + m[3] * b, + m[0] * c + m[2] * d, + m[1] * c + m[3] * d, + m[0] * e + m[2] * f + m[4], + m[1] * e + m[3] * f + m[5] + ]; + + ctx._originalTransform(a, b, c, d, e, f); + }; + + ctx.setTransform = function ctxSetTransform(a, b, c, d, e, f) { + this._transformMatrix = [a, b, c, d, e, f]; + + ctx._originalSetTransform(a, b, c, d, e, f); + }; + + ctx.rotate = function ctxRotate(angle) { + var cosValue = Math.cos(angle); + var sinValue = Math.sin(angle); + + var m = this._transformMatrix; + this._transformMatrix = [ + m[0] * cosValue + m[2] * sinValue, + m[1] * cosValue + m[3] * sinValue, + m[0] * (-sinValue) + m[2] * cosValue, + m[1] * (-sinValue) + m[3] * cosValue, + m[4], + m[5] + ]; + + this._originalRotate(angle); + }; + } +} + +var CachedCanvases = (function CachedCanvasesClosure() { + var cache = {}; + return { + getCanvas: function CachedCanvases_getCanvas(id, width, height, + trackTransform) { + var canvasEntry; + if (id in cache) { + canvasEntry = cache[id]; + canvasEntry.canvas.width = width; + canvasEntry.canvas.height = height; + // reset canvas transform for emulated mozCurrentTransform, if needed + canvasEntry.context.setTransform(1, 0, 0, 1, 0, 0); + } else { + var canvas = createScratchCanvas(width, height); + var ctx = canvas.getContext('2d'); + if (trackTransform) { + addContextCurrentTransform(ctx); + } + cache[id] = canvasEntry = {canvas: canvas, context: ctx}; + } + return canvasEntry; + }, + clear: function () { + cache = {}; + } + }; +})(); + +function compileType3Glyph(imgData) { + var POINT_TO_PROCESS_LIMIT = 1000; + + var width = imgData.width, height = imgData.height; + var i, j, j0, width1 = width + 1; + var points = new Uint8Array(width1 * (height + 1)); + var POINT_TYPES = + new Uint8Array([0, 2, 4, 0, 1, 0, 5, 4, 8, 10, 0, 8, 0, 2, 1, 0]); + + // decodes bit-packed mask data + var lineSize = (width + 7) & ~7, data0 = imgData.data; + var data = new Uint8Array(lineSize * height), pos = 0, ii; + for (i = 0, ii = data0.length; i < ii; i++) { + var mask = 128, elem = data0[i]; + while (mask > 0) { + data[pos++] = (elem & mask) ? 0 : 255; + mask >>= 1; + } + } + + // finding iteresting points: every point is located between mask pixels, + // so there will be points of the (width + 1)x(height + 1) grid. Every point + // will have flags assigned based on neighboring mask pixels: + // 4 | 8 + // --P-- + // 2 | 1 + // We are interested only in points with the flags: + // - outside corners: 1, 2, 4, 8; + // - inside corners: 7, 11, 13, 14; + // - and, intersections: 5, 10. + var count = 0; + pos = 0; + if (data[pos] !== 0) { + points[0] = 1; + ++count; + } + for (j = 1; j < width; j++) { + if (data[pos] !== data[pos + 1]) { + points[j] = data[pos] ? 2 : 1; + ++count; + } + pos++; + } + if (data[pos] !== 0) { + points[j] = 2; + ++count; + } + for (i = 1; i < height; i++) { + pos = i * lineSize; + j0 = i * width1; + if (data[pos - lineSize] !== data[pos]) { + points[j0] = data[pos] ? 1 : 8; + ++count; + } + // 'sum' is the position of the current pixel configuration in the 'TYPES' + // array (in order 8-1-2-4, so we can use '>>2' to shift the column). + var sum = (data[pos] ? 4 : 0) + (data[pos - lineSize] ? 8 : 0); + for (j = 1; j < width; j++) { + sum = (sum >> 2) + (data[pos + 1] ? 4 : 0) + + (data[pos - lineSize + 1] ? 8 : 0); + if (POINT_TYPES[sum]) { + points[j0 + j] = POINT_TYPES[sum]; + ++count; + } + pos++; + } + if (data[pos - lineSize] !== data[pos]) { + points[j0 + j] = data[pos] ? 2 : 4; + ++count; + } + + if (count > POINT_TO_PROCESS_LIMIT) { + return null; + } + } + + pos = lineSize * (height - 1); + j0 = i * width1; + if (data[pos] !== 0) { + points[j0] = 8; + ++count; + } + for (j = 1; j < width; j++) { + if (data[pos] !== data[pos + 1]) { + points[j0 + j] = data[pos] ? 4 : 8; + ++count; + } + pos++; + } + if (data[pos] !== 0) { + points[j0 + j] = 4; + ++count; + } + if (count > POINT_TO_PROCESS_LIMIT) { + return null; + } + + // building outlines + var steps = new Int32Array([0, width1, -1, 0, -width1, 0, 0, 0, 1]); + var outlines = []; + for (i = 0; count && i <= height; i++) { + var p = i * width1; + var end = p + width; + while (p < end && !points[p]) { + p++; + } + if (p === end) { + continue; + } + var coords = [p % width1, i]; + + var type = points[p], p0 = p, pp; + do { + var step = steps[type]; + do { p += step; } while (!points[p]); + + pp = points[p]; + if (pp !== 5 && pp !== 10) { + // set new direction + type = pp; + // delete mark + points[p] = 0; + } else { // type is 5 or 10, ie, a crossing + // set new direction + type = pp & ((0x33 * type) >> 4); + // set new type for "future hit" + points[p] &= (type >> 2 | type << 2); + } + + coords.push(p % width1); + coords.push((p / width1) | 0); + --count; + } while (p0 !== p); + outlines.push(coords); + --i; + } + + var drawOutline = function(c) { + c.save(); + // the path shall be painted in [0..1]x[0..1] space + c.scale(1 / width, -1 / height); + c.translate(0, -height); + c.beginPath(); + for (var i = 0, ii = outlines.length; i < ii; i++) { + var o = outlines[i]; + c.moveTo(o[0], o[1]); + for (var j = 2, jj = o.length; j < jj; j += 2) { + c.lineTo(o[j], o[j+1]); + } + } + c.fill(); + c.beginPath(); + c.restore(); + }; + + return drawOutline; +} + +var CanvasExtraState = (function CanvasExtraStateClosure() { + function CanvasExtraState(old) { + // Are soft masks and alpha values shapes or opacities? + this.alphaIsShape = false; + this.fontSize = 0; + this.fontSizeScale = 1; + this.textMatrix = IDENTITY_MATRIX; + this.fontMatrix = FONT_IDENTITY_MATRIX; + this.leading = 0; + // Current point (in user coordinates) + this.x = 0; + this.y = 0; + // Start of text line (in text coordinates) + this.lineX = 0; + this.lineY = 0; + // Character and word spacing + this.charSpacing = 0; + this.wordSpacing = 0; + this.textHScale = 1; + this.textRenderingMode = TextRenderingMode.FILL; + this.textRise = 0; + // 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'; + // Note: fill alpha applies to all non-stroking operations + this.fillAlpha = 1; + this.strokeAlpha = 1; + this.lineWidth = 1; + this.activeSMask = null; // nonclonable field (see the save method below) + + this.old = old; + } + + CanvasExtraState.prototype = { + clone: function CanvasExtraState_clone() { + return Object.create(this); + }, + setCurrentPoint: function CanvasExtraState_setCurrentPoint(x, y) { + this.x = x; + this.y = y; + } + }; + return CanvasExtraState; +})(); + +var CanvasGraphics = (function CanvasGraphicsClosure() { + // Defines the time the executeOperatorList is going to be executing + // before it stops and shedules a continue of execution. + var EXECUTION_TIME = 15; + + function CanvasGraphics(canvasCtx, commonObjs, objs, textLayer, imageLayer) { + this.ctx = canvasCtx; + this.current = new CanvasExtraState(); + this.stateStack = []; + this.pendingClip = null; + this.pendingEOFill = false; + this.res = null; + this.xobjs = null; + this.commonObjs = commonObjs; + this.objs = objs; + this.textLayer = textLayer; + this.imageLayer = imageLayer; + this.groupStack = []; + this.processingType3 = null; + // Patterns are painted relative to the initial page/form transform, see pdf + // spec 8.7.2 NOTE 1. + this.baseTransform = null; + this.baseTransformStack = []; + this.groupLevel = 0; + this.smaskStack = []; + this.smaskCounter = 0; + this.tempSMask = null; + if (canvasCtx) { + addContextCurrentTransform(canvasCtx); + } + } + + function putBinaryImageData(ctx, imgData) { + if (typeof ImageData !== 'undefined' && imgData instanceof ImageData) { + ctx.putImageData(imgData, 0, 0); + return; + } + + // Put the image data to the canvas in chunks, rather than putting the + // whole image at once. This saves JS memory, because the ImageData object + // is smaller. It also possibly saves C++ memory within the implementation + // of putImageData(). (E.g. in Firefox we make two short-lived copies of + // the data passed to putImageData()). |n| shouldn't be too small, however, + // because too many putImageData() calls will slow things down. + + 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 chunkImgData = ctx.createImageData(imgData.width, rowsInFullChunks); + var srcPos = 0; + var src = imgData.data; + var dst = chunkImgData.data; + var haveSetAndSubarray = 'set' in dst && 'subarray' in src; + + // 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); + } + + // 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++]; + } + } + // 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); + } + } + + 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; + + // 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; + } + if (!(elem & mask)) { + tmpImgDataPixels[tmpPos] = 255; + } + tmpPos += 4; + mask >>= 1; + } + } + + ctx.putImageData(tmpImgData, 0, 0); + } + + function copyCtxState(sourceCtx, destCtx) { + var properties = ['strokeStyle', 'fillStyle', 'fillRule', 'globalAlpha', + 'lineWidth', 'lineCap', 'lineJoin', 'miterLimit', + 'globalCompositeOperation', 'font']; + for (var i = 0, ii = properties.length; i < ii; i++) { + var property = properties[i]; + if (property in sourceCtx) { + destCtx[property] = sourceCtx[property]; + } + } + if ('setLineDash' in sourceCtx) { + destCtx.setLineDash(sourceCtx.getLineDash()); + destCtx.lineDashOffset = sourceCtx.lineDashOffset; + } else if ('mozDash' in sourceCtx) { + destCtx.mozDash = sourceCtx.mozDash; + destCtx.mozDashOffset = sourceCtx.mozDashOffset; + } + } + + 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 () {}; + } + + 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); + } + + var LINE_CAP_STYLES = ['butt', 'round', 'square']; + var LINE_JOIN_STYLES = ['miter', 'round', 'bevel']; + var NORMAL_CLIP = {}; + var EO_CLIP = {}; + + CanvasGraphics.prototype = { + + beginDrawing: function CanvasGraphics_beginDrawing(viewport, transparency) { + // For pdfs that use blend modes we have to clear the canvas else certain + // blend modes can look wrong since we'd be blending with a white + // backdrop. The problem with a transparent backdrop though is we then + // don't get sub pixel anti aliasing on text, so we fill with white if + // we can. + var width = this.ctx.canvas.width; + var height = this.ctx.canvas.height; + if (transparency) { + this.ctx.clearRect(0, 0, width, height); + } else { + this.ctx.mozOpaque = true; + this.ctx.save(); + this.ctx.fillStyle = 'rgb(255, 255, 255)'; + this.ctx.fillRect(0, 0, width, height); + this.ctx.restore(); + } + + var transform = viewport.transform; + this.baseTransform = transform.slice(); + this.ctx.save(); + this.ctx.transform.apply(this.ctx, transform); + + if (this.textLayer) { + this.textLayer.beginLayout(); + } + if (this.imageLayer) { + this.imageLayer.beginLayout(); + } + }, + + executeOperatorList: function CanvasGraphics_executeOperatorList( + operatorList, + executionStartIdx, continueCallback, + stepper) { + var argsArray = operatorList.argsArray; + var fnArray = operatorList.fnArray; + var i = executionStartIdx || 0; + var argsArrayLen = argsArray.length; + + // Sometimes the OperatorList to execute is empty. + if (argsArrayLen == i) { + return i; + } + + var executionEndIdx; + var endTime = Date.now() + EXECUTION_TIME; + + var commonObjs = this.commonObjs; + var objs = this.objs; + var fnId; + var deferred = Promise.resolve(); + + while (true) { + if (stepper && i === stepper.nextBreakPoint) { + stepper.breakIt(i, continueCallback); + return i; + } + + fnId = fnArray[i]; + + if (fnId !== OPS.dependency) { + this[fnId].apply(this, argsArray[i]); + } else { + var deps = argsArray[i]; + for (var n = 0, nn = deps.length; n < nn; n++) { + var depObjId = deps[n]; + var common = depObjId.substring(0, 2) == 'g_'; + + // 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); + return i; + } + } + } + + i++; + + // If the entire operatorList was executed, stop as were done. + if (i == argsArrayLen) { + return i; + } + + // If the execution took longer then a certain amount of time, 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 operatorList isn't executed completely yet OR the execution + // time was short enough, do another execution round. + } + }, + + endDrawing: function CanvasGraphics_endDrawing() { + this.ctx.restore(); + CachedCanvases.clear(); + + if (this.textLayer) { + this.textLayer.endLayout(); + } + if (this.imageLayer) { + this.imageLayer.endLayout(); + } + }, + + // Graphics state + setLineWidth: function CanvasGraphics_setLineWidth(width) { + this.current.lineWidth = width; + this.ctx.lineWidth = width; + }, + setLineCap: function CanvasGraphics_setLineCap(style) { + this.ctx.lineCap = LINE_CAP_STYLES[style]; + }, + setLineJoin: function CanvasGraphics_setLineJoin(style) { + this.ctx.lineJoin = LINE_JOIN_STYLES[style]; + }, + setMiterLimit: function CanvasGraphics_setMiterLimit(limit) { + this.ctx.miterLimit = limit; + }, + setDash: function CanvasGraphics_setDash(dashArray, dashPhase) { + var ctx = this.ctx; + if ('setLineDash' in ctx) { + ctx.setLineDash(dashArray); + ctx.lineDashOffset = dashPhase; + } else { + ctx.mozDash = dashArray; + ctx.mozDashOffset = dashPhase; + } + }, + setRenderingIntent: function CanvasGraphics_setRenderingIntent(intent) { + // Maybe if we one day fully support color spaces this will be important + // for now we can ignore. + // TODO set rendering intent? + }, + setFlatness: function CanvasGraphics_setFlatness(flatness) { + // There's no way to control this with canvas, but we can safely ignore. + // TODO set flatness? + }, + setGState: function CanvasGraphics_setGState(states) { + for (var i = 0, ii = states.length; i < ii; i++) { + var state = states[i]; + var key = state[0]; + var value = state[1]; + + switch (key) { + case 'LW': + this.setLineWidth(value); + break; + case 'LC': + this.setLineCap(value); + break; + case 'LJ': + this.setLineJoin(value); + break; + case 'ML': + this.setMiterLimit(value); + break; + case 'D': + this.setDash(value[0], value[1]); + break; + case 'RI': + this.setRenderingIntent(value); + break; + case 'FL': + this.setFlatness(value); + break; + case 'Font': + this.setFont(value[0], value[1]); + break; + case 'CA': + this.current.strokeAlpha = state[1]; + break; + case 'ca': + this.current.fillAlpha = state[1]; + this.ctx.globalAlpha = state[1]; + break; + case 'BM': + if (value && value.name && (value.name !== 'Normal')) { + var mode = value.name.replace(/([A-Z])/g, + function(c) { + return '-' + c.toLowerCase(); + } + ).substring(1); + this.ctx.globalCompositeOperation = mode; + if (this.ctx.globalCompositeOperation !== mode) { + warn('globalCompositeOperation "' + mode + + '" is not supported'); + } + } else { + this.ctx.globalCompositeOperation = 'source-over'; + } + break; + case 'SMask': + if (this.current.activeSMask) { + this.endSMaskGroup(); + } + this.current.activeSMask = value ? this.tempSMask : null; + if (this.current.activeSMask) { + this.beginSMaskGroup(); + } + this.tempSMask = null; + break; + } + } + }, + beginSMaskGroup: function CanvasGraphics_beginSMaskGroup() { + + var activeSMask = this.current.activeSMask; + var drawnWidth = activeSMask.canvas.width; + var drawnHeight = activeSMask.canvas.height; + var cacheId = 'smaskGroupAt' + this.groupLevel; + var scratchCanvas = CachedCanvases.getCanvas( + cacheId, drawnWidth, drawnHeight, true); + + var currentCtx = this.ctx; + var currentTransform = currentCtx.mozCurrentTransform; + this.ctx.save(); + + var groupCtx = scratchCanvas.context; + groupCtx.translate(-activeSMask.offsetX, -activeSMask.offsetY); + groupCtx.transform.apply(groupCtx, currentTransform); + + copyCtxState(currentCtx, groupCtx); + this.ctx = groupCtx; + this.setGState([ + ['BM', 'Normal'], + ['ca', 1], + ['CA', 1] + ]); + this.groupStack.push(currentCtx); + this.groupLevel++; + }, + endSMaskGroup: function CanvasGraphics_endSMaskGroup() { + var groupCtx = this.ctx; + this.groupLevel--; + this.ctx = this.groupStack.pop(); + + composeSMask(this.ctx, this.current.activeSMask, groupCtx); + this.ctx.restore(); + }, + save: function CanvasGraphics_save() { + this.ctx.save(); + var old = this.current; + this.stateStack.push(old); + this.current = old.clone(); + if (this.current.activeSMask) { + this.current.activeSMask = null; + } + }, + restore: function CanvasGraphics_restore() { + var prev = this.stateStack.pop(); + if (prev) { + if (this.current.activeSMask) { + this.endSMaskGroup(); + } + + this.current = prev; + this.ctx.restore(); + } + }, + transform: function CanvasGraphics_transform(a, b, c, d, e, f) { + this.ctx.transform(a, b, c, d, e, f); + }, + + // 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) { + 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); + }, + 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(); + // For stroke we want to temporarily change the global alpha to the + // stroking alpha. + ctx.globalAlpha = this.current.strokeAlpha; + if (strokeColor && strokeColor.hasOwnProperty('type') && + strokeColor.type === 'Pattern') { + // for patterns, we transform to pattern space, calculate + // the pattern, call stroke, and restore to user space + ctx.save(); + ctx.strokeStyle = strokeColor.getPattern(ctx, this); + ctx.stroke(); + ctx.restore(); + } else { + ctx.stroke(); + } + if (consumePath) + this.consumePath(); + // Restore the global alpha to the fill alpha + ctx.globalAlpha = this.current.fillAlpha; + }, + closeStroke: function CanvasGraphics_closeStroke() { + this.closePath(); + this.stroke(); + }, + fill: function CanvasGraphics_fill(consumePath) { + consumePath = typeof consumePath !== 'undefined' ? consumePath : true; + var ctx = this.ctx; + var fillColor = this.current.fillColor; + var needRestore = false; + + if (fillColor && fillColor.hasOwnProperty('type') && + fillColor.type === 'Pattern') { + 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'; + } else { + try { + this.ctx.fill('evenodd'); + } catch (ex) { + // shouldn't really happen, but browsers might think differently + this.ctx.fill(); + } + } + this.pendingEOFill = false; + } else { + this.ctx.fill(); + } + + if (needRestore) { + ctx.restore(); + } + if (consumePath) { + this.consumePath(); + } + }, + eoFill: function CanvasGraphics_eoFill() { + this.pendingEOFill = true; + this.fill(); + }, + fillStroke: function CanvasGraphics_fillStroke() { + this.fill(false); + this.stroke(false); + + this.consumePath(); + }, + eoFillStroke: function CanvasGraphics_eoFillStroke() { + this.pendingEOFill = true; + this.fillStroke(); + }, + closeFillStroke: function CanvasGraphics_closeFillStroke() { + this.closePath(); + this.fillStroke(); + }, + closeEOFillStroke: function CanvasGraphics_closeEOFillStroke() { + this.pendingEOFill = true; + this.closePath(); + this.fillStroke(); + }, + endPath: function CanvasGraphics_endPath() { + this.consumePath(); + }, + + // Clipping + clip: function CanvasGraphics_clip() { + this.pendingClip = NORMAL_CLIP; + }, + eoClip: function CanvasGraphics_eoClip() { + this.pendingClip = EO_CLIP; + }, + + // Text + beginText: function CanvasGraphics_beginText() { + this.current.textMatrix = IDENTITY_MATRIX; + this.current.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; + + ctx.save(); + ctx.beginPath(); + for (var i = 0; i < paths.length; i++) { + var path = paths[i]; + ctx.setTransform.apply(ctx, path.transform); + ctx.translate(path.x, path.y); + path.addToPath(ctx, path.fontSize); + } + ctx.restore(); + ctx.clip(); + ctx.beginPath(); + delete this.pendingTextPaths; + }, + setCharSpacing: function CanvasGraphics_setCharSpacing(spacing) { + this.current.charSpacing = spacing; + }, + setWordSpacing: function CanvasGraphics_setWordSpacing(spacing) { + this.current.wordSpacing = spacing; + }, + setHScale: function CanvasGraphics_setHScale(scale) { + this.current.textHScale = scale / 100; + }, + setLeading: function CanvasGraphics_setLeading(leading) { + this.current.leading = -leading; + }, + setFont: function CanvasGraphics_setFont(fontRefName, size) { + var fontObj = this.commonObjs.get(fontRefName); + var current = this.current; + + if (!fontObj) + error('Can\'t find font for ' + fontRefName); + + current.fontMatrix = fontObj.fontMatrix ? fontObj.fontMatrix : + FONT_IDENTITY_MATRIX; + + // A valid matrix needs all main diagonal elements to be non-zero + // This also ensures we bypass FF bugzilla bug #719844. + if (current.fontMatrix[0] === 0 || + current.fontMatrix[3] === 0) { + warn('Invalid font matrix for font ' + fontRefName); + } + + // The spec for Tf (setFont) says that 'size' specifies the font 'scale', + // and in some docs this can be negative (inverted x-y axes). + if (size < 0) { + size = -size; + current.fontDirection = -1; + } else { + current.fontDirection = 1; + } + + this.current.font = fontObj; + this.current.fontSize = size; + + if (fontObj.coded) + return; // we don't need ctx.font for Type3 fonts + + var name = fontObj.loadedName || 'sans-serif'; + var bold = fontObj.black ? (fontObj.bold ? 'bolder' : 'bold') : + (fontObj.bold ? 'bold' : 'normal'); + + var italic = fontObj.italic ? 'italic' : 'normal'; + var typeface = '"' + name + '", ' + fontObj.fallbackName; + + // Some font backends cannot handle fonts below certain size. + // Keeping the font at minimal size and using the fontSizeScale to change + // the current transformation matrix before the fillText/strokeText. + // See https://bugzilla.mozilla.org/show_bug.cgi?id=726227 + var browserFontSize = size >= MIN_FONT_SIZE ? size : MIN_FONT_SIZE; + this.current.fontSizeScale = browserFontSize != MIN_FONT_SIZE ? 1.0 : + size / MIN_FONT_SIZE; + + var rule = italic + ' ' + bold + ' ' + browserFontSize + 'px ' + typeface; + this.ctx.font = rule; + }, + setTextRenderingMode: function CanvasGraphics_setTextRenderingMode(mode) { + this.current.textRenderingMode = mode; + }, + setTextRise: function CanvasGraphics_setTextRise(rise) { + this.current.textRise = rise; + }, + moveText: function CanvasGraphics_moveText(x, y) { + this.current.x = this.current.lineX += x; + this.current.y = this.current.lineY += y; + }, + setLeadingMoveText: function CanvasGraphics_setLeadingMoveText(x, y) { + this.setLeading(-y); + this.moveText(x, y); + }, + setTextMatrix: function CanvasGraphics_setTextMatrix(a, b, c, d, e, f) { + this.current.textMatrix = [a, b, c, d, e, f]; + + this.current.x = this.current.lineX = 0; + this.current.y = this.current.lineY = 0; + }, + 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) { + var ctx = this.ctx; + var current = this.current; + var font = current.font; + var fontSize = current.fontSize / current.fontSizeScale; + var textRenderingMode = current.textRenderingMode; + var fillStrokeMode = textRenderingMode & + TextRenderingMode.FILL_STROKE_MASK; + var isAddToPathSet = !!(textRenderingMode & + TextRenderingMode.ADD_TO_PATH_FLAG); + + var addToPath; + if (font.disableFontFace || isAddToPathSet) { + addToPath = font.getPathGenerator(this.commonObjs, character); + } + + if (font.disableFontFace) { + ctx.save(); + ctx.translate(x, y); + ctx.beginPath(); + addToPath(ctx, fontSize); + if (fillStrokeMode === TextRenderingMode.FILL || + fillStrokeMode === TextRenderingMode.FILL_STROKE) { + ctx.fill(); + } + if (fillStrokeMode === TextRenderingMode.STROKE || + fillStrokeMode === TextRenderingMode.FILL_STROKE) { + ctx.stroke(); + } + ctx.restore(); + } else { + if (fillStrokeMode === TextRenderingMode.FILL || + fillStrokeMode === TextRenderingMode.FILL_STROKE) { + ctx.fillText(character, x, y); + } + if (fillStrokeMode === TextRenderingMode.STROKE || + fillStrokeMode === TextRenderingMode.FILL_STROKE) { + ctx.strokeText(character, x, y); + } + } + + if (isAddToPathSet) { + var paths = this.pendingTextPaths || (this.pendingTextPaths = []); + paths.push({ + transform: ctx.mozCurrentTransform, + x: x, + y: y, + fontSize: fontSize, + addToPath: addToPath + }); + } + }, + + get isFontSubpixelAAEnabled() { + // Checks if anti-aliasing is enabled when scaled text is painted. + // On Windows GDI scaled fonts looks bad. + var ctx = document.createElement('canvas').getContext('2d'); + ctx.scale(1.5, 1); + ctx.fillText('I', 0, 10); + var data = ctx.getImageData(0, 0, 10, 10).data; + var enabled = false; + for (var i = 3; i < data.length; i += 4) { + if (data[i] > 0 && data[i] < 255) { + enabled = true; + break; + } + } + return shadow(this, 'isFontSubpixelAAEnabled', enabled); + }, + + showText: function CanvasGraphics_showText(glyphs, skipTextSelection) { + var ctx = this.ctx; + var current = this.current; + var font = current.font; + var fontSize = current.fontSize; + 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 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; + + // 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); + + ctx.scale(textHScale, 1); + + 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; + } else { + ctx.save(); + this.applyTextTransforms(); + + 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; + + if (textSelection) + geom = this.createTextGeometry(); + + if (fontSizeScale != 1.0) { + ctx.scale(fontSizeScale, fontSizeScale); + lineWidth /= fontSizeScale; + } + + 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(); + } + } + if (vertical) { + current.y -= x * textHScale; + } else { + current.x += x * textHScale; + } + ctx.restore(); + } + + if (textSelection) { + geom.canvasWidth = canvasWidth; + if (vertical) { + var VERTICAL_TEXT_ROTATION = Math.PI / 2; + geom.angle += VERTICAL_TEXT_ROTATION; + } + this.textLayer.appendText(geom); + } + + return canvasWidth; + }, + showSpacedText: function CanvasGraphics_showSpacedText(arr) { + 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; + + if (textSelection) { + ctx.save(); + this.applyTextTransforms(); + geom = this.createTextGeometry(); + ctx.restore(); + } + + 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; + } + + if (textSelection) + spacingAccumulator += spacingLength; + } else { + var shownCanvasWidth = this.showText(e, true); + + if (textSelection) { + canvasWidth += spacingAccumulator + shownCanvasWidth; + spacingAccumulator = 0; + } + } + } + + if (textSelection) { + geom.canvasWidth = canvasWidth; + if (vertical) { + var VERTICAL_TEXT_ROTATION = Math.PI / 2; + geom.angle += VERTICAL_TEXT_ROTATION; + } + this.textLayer.appendText(geom); + } + }, + 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); + }, + + // Type3 fonts + setCharWidth: function CanvasGraphics_setCharWidth(xWidth, yWidth) { + // We can safely ignore this since the width should be the same + // as the width in the Widths array. + }, + setCharWidthAndBounds: function CanvasGraphics_setCharWidthAndBounds(xWidth, + yWidth, + llx, + lly, + urx, + ury) { + // TODO According to the spec we're also suppose to ignore any operators + // that set color or include images while processing this type3 font. + this.rectangle(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); + } else { + error('Unkown IR type ' + IR[0]); + } + 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; + }, + 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; + }, + 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); + 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); + this.ctx.fillStyle = color; + this.current.fillColor = color; + }, + + shadingFill: function CanvasGraphics_shadingFill(patternIR) { + var ctx = this.ctx; + + this.save(); + var pattern = getShadingPatternFromIR(patternIR); + ctx.fillStyle = pattern.getPattern(ctx, this); + + var inv = ctx.mozCurrentTransformInverse; + if (inv) { + var canvas = ctx.canvas; + var width = canvas.width; + var height = canvas.height; + + var bl = Util.applyTransform([0, 0], inv); + var br = Util.applyTransform([0, height], inv); + var ul = Util.applyTransform([width, 0], inv); + var ur = Util.applyTransform([width, height], inv); + + var x0 = Math.min(bl[0], br[0], ul[0], ur[0]); + var y0 = Math.min(bl[1], br[1], ul[1], ur[1]); + var x1 = Math.max(bl[0], br[0], ul[0], ur[0]); + var y1 = Math.max(bl[1], br[1], ul[1], ur[1]); + + this.ctx.fillRect(x0, y0, x1 - x0, y1 - y0); + } else { + // HACK to draw the gradient onto an infinite rectangle. + // PDF gradients are drawn across the entire image while + // Canvas only allows gradients to be drawn in a rectangle + // The following bug should allow us to remove this. + // https://bugzilla.mozilla.org/show_bug.cgi?id=664884 + + this.ctx.fillRect(-1e10, -1e10, 2e10, 2e10); + } + + this.restore(); + }, + + // Images + beginInlineImage: function CanvasGraphics_beginInlineImage() { + error('Should not call beginInlineImage'); + }, + beginImageData: function CanvasGraphics_beginImageData() { + error('Should not call beginImageData'); + }, + + paintFormXObjectBegin: function CanvasGraphics_paintFormXObjectBegin(matrix, + bbox) { + this.save(); + this.baseTransformStack.push(this.baseTransform); + + if (matrix && isArray(matrix) && 6 == matrix.length) + this.transform.apply(this, matrix); + + this.baseTransform = this.ctx.mozCurrentTransform; + + if (bbox && 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.clip(); + this.endPath(); + } + }, + + paintFormXObjectEnd: function CanvasGraphics_paintFormXObjectEnd() { + this.restore(); + this.baseTransform = this.baseTransformStack.pop(); + }, + + beginGroup: function CanvasGraphics_beginGroup(group) { + this.save(); + var currentCtx = this.ctx; + // TODO non-isolated groups - according to Rik at adobe non-isolated + // group results aren't usually that different and they even have tools + // that ignore this setting. Notes from Rik on implmenting: + // - When you encounter an transparency group, create a new canvas with + // the dimensions of the bbox + // - copy the content from the previous canvas to the new canvas + // - draw as usual + // - remove the backdrop alpha: + // alphaNew = 1 - (1 - alpha)/(1 - alphaBackdrop) with 'alpha' the alpha + // value of your transparency group and 'alphaBackdrop' the alpha of the + // backdrop + // - remove background color: + // colorNew = color - alphaNew *colorBackdrop /(1 - alphaNew) + if (!group.isolated) { + info('TODO: Support non-isolated groups.'); + } + + // TODO knockout - supposedly possible with the clever use of compositing + // modes. + if (group.knockout) { + warn('Knockout groups not supported.'); + } + + var currentTransform = currentCtx.mozCurrentTransform; + if (group.matrix) { + currentCtx.transform.apply(currentCtx, group.matrix); + } + assert(group.bbox, 'Bounding box is required.'); + + // Based on the current transform figure out how big the bounding box + // will actually be. + var bounds = Util.getAxialAlignedBoundingBox( + group.bbox, + currentCtx.mozCurrentTransform); + // Clip the bounding box to the current canvas. + var canvasBounds = [0, + 0, + currentCtx.canvas.width, + currentCtx.canvas.height]; + bounds = Util.intersect(bounds, canvasBounds) || [0, 0, 0, 0]; + // Use ceil in case we're between sizes so we don't create canvas that is + // too small and make the canvas at least 1x1 pixels. + var drawnWidth = Math.max(Math.ceil(bounds[2] - bounds[0]), 1); + var drawnHeight = Math.max(Math.ceil(bounds[3] - bounds[1]), 1); + + var cacheId = 'groupAt' + this.groupLevel; + if (group.smask) { + // Using two cache entries is case if masks are used one after another. + cacheId += '_smask_' + ((this.smaskCounter++) % 2); + } + var scratchCanvas = CachedCanvases.getCanvas( + cacheId, drawnWidth, drawnHeight, true); + var groupCtx = scratchCanvas.context; + + // Since we created a new canvas that is just the size of the bounding box + // we have to translate the group ctx. + var offsetX = bounds[0]; + var offsetY = bounds[1]; + groupCtx.translate(-offsetX, -offsetY); + groupCtx.transform.apply(groupCtx, currentTransform); + + if (group.smask) { + // Saving state and cached mask to be used in setGState. + this.smaskStack.push({ + canvas: scratchCanvas.canvas, + context: groupCtx, + offsetX: offsetX, + offsetY: offsetY, + subtype: group.smask.subtype, + backdrop: group.smask.backdrop, + colorSpace: group.colorSpace && ColorSpace.fromIR(group.colorSpace) + }); + } 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); + } + // The transparency group inherits all off the current graphics state + // except the blend mode, soft mask, and alpha constants. + copyCtxState(currentCtx, groupCtx); + this.ctx = groupCtx; + this.setGState([ + ['BM', 'Normal'], + ['ca', 1], + ['CA', 1] + ]); + this.groupStack.push(currentCtx); + this.groupLevel++; + }, + + endGroup: function CanvasGraphics_endGroup(group) { + this.groupLevel--; + var groupCtx = this.ctx; + this.ctx = this.groupStack.pop(); + // Turn off image smoothing to avoid sub pixel interpolation which can + // look kind of blurry for some pdfs. + if ('imageSmoothingEnabled' in this.ctx) { + this.ctx.imageSmoothingEnabled = false; + } else { + this.ctx.mozImageSmoothingEnabled = false; + } + if (group.smask) { + this.tempSMask = this.smaskStack.pop(); + } else { + this.ctx.drawImage(groupCtx.canvas, 0, 0); + } + this.restore(); + }, + + beginAnnotations: function CanvasGraphics_beginAnnotations() { + this.save(); + this.current = new CanvasExtraState(); + }, + + endAnnotations: function CanvasGraphics_endAnnotations() { + this.restore(); + }, + + beginAnnotation: function CanvasGraphics_beginAnnotation(rect, transform, + matrix) { + this.save(); + + if (rect && 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.clip(); + this.endPath(); + } + + this.transform.apply(this, transform); + this.transform.apply(this, matrix); + }, + + endAnnotation: function CanvasGraphics_endAnnotation() { + this.restore(); + }, + + paintJpegXObject: function CanvasGraphics_paintJpegXObject(objId, w, h) { + var domImage = this.objs.get(objId); + if (!domImage) { + error('Dependent image isn\'t ready yet'); + } + + this.save(); + + var ctx = this.ctx; + // scale the image to the unit square + ctx.scale(1 / w, -1 / h); + + ctx.drawImage(domImage, 0, 0, domImage.width, domImage.height, + 0, -h, w, h); + if (this.imageLayer) { + var currentTransform = ctx.mozCurrentTransformInverse; + var position = this.getCanvasPosition(0, 0); + this.imageLayer.appendImage({ + objId: objId, + left: position[0], + top: position[1], + width: w / currentTransform[0], + height: h / currentTransform[3] + }); + } + this.restore(); + }, + + paintImageMaskXObject: function CanvasGraphics_paintImageMaskXObject(img) { + var ctx = this.ctx; + var width = img.width, height = img.height; + + var glyph = this.processingType3; + + if (COMPILE_TYPE3_GLYPHS && glyph && !('compiled' in glyph)) { + var MAX_SIZE_TO_COMPILE = 1000; + if (width <= MAX_SIZE_TO_COMPILE && height <= MAX_SIZE_TO_COMPILE) { + glyph.compiled = + compileType3Glyph({data: img.data, width: width, height: height}); + } else { + glyph.compiled = null; + } + } + + if (glyph && glyph.compiled) { + glyph.compiled(ctx); + return; + } + + var maskCanvas = CachedCanvases.getCanvas('maskCanvas', width, height); + var maskCtx = maskCanvas.context; + maskCtx.save(); + + putBinaryImageMask(maskCtx, img); + + maskCtx.globalCompositeOperation = 'source-in'; + + var fillColor = this.current.fillColor; + maskCtx.fillStyle = (fillColor && fillColor.hasOwnProperty('type') && + fillColor.type === 'Pattern') ? + fillColor.getPattern(maskCtx, this) : fillColor; + maskCtx.fillRect(0, 0, width, height); + + maskCtx.restore(); + + this.paintInlineImageXObject(maskCanvas.canvas); + }, + + paintImageMaskXObjectGroup: + function CanvasGraphics_paintImageMaskXObjectGroup(images) { + var ctx = this.ctx; + + for (var i = 0, ii = images.length; i < ii; i++) { + var image = images[i]; + var width = image.width, height = image.height; + + var maskCanvas = CachedCanvases.getCanvas('maskCanvas', width, height); + var maskCtx = maskCanvas.context; + maskCtx.save(); + + putBinaryImageMask(maskCtx, image); + + maskCtx.globalCompositeOperation = 'source-in'; + + var fillColor = this.current.fillColor; + maskCtx.fillStyle = (fillColor && fillColor.hasOwnProperty('type') && + fillColor.type === 'Pattern') ? + fillColor.getPattern(maskCtx, this) : fillColor; + maskCtx.fillRect(0, 0, width, height); + + maskCtx.restore(); + + ctx.save(); + ctx.transform.apply(ctx, image.transform); + ctx.scale(1, -1); + ctx.drawImage(maskCanvas.canvas, 0, 0, width, height, + 0, -1, 1, 1); + ctx.restore(); + } + }, + + paintImageXObject: function CanvasGraphics_paintImageXObject(objId) { + var imgData = this.objs.get(objId); + if (!imgData) + error('Dependent image isn\'t ready yet'); + + this.paintInlineImageXObject(imgData); + }, + + paintInlineImageXObject: + function CanvasGraphics_paintInlineImageXObject(imgData) { + var width = imgData.width; + var height = imgData.height; + var ctx = this.ctx; + + this.save(); + // scale the image to the unit square + ctx.scale(1 / width, -1 / height); + + var currentTransform = ctx.mozCurrentTransformInverse; + var a = currentTransform[0], b = currentTransform[1]; + var widthScale = Math.max(Math.sqrt(a * a + b * b), 1); + var c = currentTransform[2], d = currentTransform[3]; + var heightScale = Math.max(Math.sqrt(c * c + d * d), 1); + + var imgToPaint; + // 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); + var tmpCtx = tmpCanvas.context; + putBinaryImageData(tmpCtx, imgData); + imgToPaint = tmpCanvas.canvas; + } + + var paintWidth = width, paintHeight = height; + var tmpCanvasId = 'prescale1'; + // Vertial or horizontal scaling shall not be more than 2 to not loose the + // pixels during drawImage operation, painting on the temporary canvas(es) + // that are twice smaller in size + while ((widthScale > 2 && paintWidth > 1) || + (heightScale > 2 && paintHeight > 1)) { + var newWidth = paintWidth, newHeight = paintHeight; + if (widthScale > 2 && paintWidth > 1) { + newWidth = Math.ceil(paintWidth / 2); + widthScale /= paintWidth / newWidth; + } + if (heightScale > 2 && paintHeight > 1) { + newHeight = Math.ceil(paintHeight / 2); + heightScale /= paintHeight / newHeight; + } + var tmpCanvas = CachedCanvases.getCanvas(tmpCanvasId, + newWidth, newHeight); + tmpCtx = tmpCanvas.context; + tmpCtx.clearRect(0, 0, newWidth, newHeight); + tmpCtx.drawImage(imgToPaint, 0, 0, paintWidth, paintHeight, + 0, 0, newWidth, newHeight); + imgToPaint = tmpCanvas.canvas; + paintWidth = newWidth; + paintHeight = newHeight; + tmpCanvasId = tmpCanvasId === 'prescale1' ? 'prescale2' : 'prescale1'; + } + ctx.drawImage(imgToPaint, 0, 0, paintWidth, paintHeight, + 0, -height, width, height); + + if (this.imageLayer) { + var position = this.getCanvasPosition(0, -height); + this.imageLayer.appendImage({ + imgData: imgData, + left: position[0], + top: position[1], + width: width / currentTransform[0], + height: height / currentTransform[3] + }); + } + this.restore(); + }, + + paintInlineImageXObjectGroup: + function CanvasGraphics_paintInlineImageXObjectGroup(imgData, map) { + var ctx = this.ctx; + var w = imgData.width; + var h = imgData.height; + + var tmpCanvas = CachedCanvases.getCanvas('inlineImage', w, h); + var tmpCtx = tmpCanvas.context; + putBinaryImageData(tmpCtx, imgData); + + for (var i = 0, ii = map.length; i < ii; i++) { + var entry = map[i]; + ctx.save(); + ctx.transform.apply(ctx, entry.transform); + ctx.scale(1, -1); + ctx.drawImage(tmpCanvas.canvas, entry.x, entry.y, entry.w, entry.h, + 0, -1, 1, 1); + if (this.imageLayer) { + var position = this.getCanvasPosition(entry.x, entry.y); + this.imageLayer.appendImage({ + imgData: imgData, + left: position[0], + top: position[1], + width: w, + height: h + }); + } + ctx.restore(); + } + }, + + // Marked content + + markPoint: function CanvasGraphics_markPoint(tag) { + // TODO Marked content. + }, + markPointProps: function CanvasGraphics_markPointProps(tag, properties) { + // TODO Marked content. + }, + beginMarkedContent: function CanvasGraphics_beginMarkedContent(tag) { + // TODO Marked content. + }, + beginMarkedContentProps: function CanvasGraphics_beginMarkedContentProps( + tag, properties) { + // TODO Marked content. + }, + endMarkedContent: function CanvasGraphics_endMarkedContent() { + // TODO Marked content. + }, + + // Compatibility + + beginCompat: function CanvasGraphics_beginCompat() { + // TODO ignore undefined operators (should we do that anyway?) + }, + endCompat: function CanvasGraphics_endCompat() { + // TODO stop ignoring undefined operators + }, + + // Helper functions + + consumePath: function CanvasGraphics_consumePath() { + if (this.pendingClip) { + if (this.pendingClip == EO_CLIP) { + if ('mozFillRule' in this.ctx) { + this.ctx.mozFillRule = 'evenodd'; + this.ctx.clip(); + this.ctx.mozFillRule = 'nonzero'; + } else { + try { + this.ctx.clip('evenodd'); + } catch (ex) { + // shouldn't really happen, but browsers might think differently + this.ctx.clip(); + } + } + } else { + this.ctx.clip(); + } + this.pendingClip = null; + } + this.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]))); + }, + getCanvasPosition: function CanvasGraphics_getCanvasPosition(x, y) { + var transform = this.ctx.mozCurrentTransform; + return [ + transform[0] * x + transform[2] * y + transform[4], + transform[1] * x + transform[3] * y + transform[5] + ]; + } + }; + + for (var op in OPS) { + CanvasGraphics.prototype[OPS[op]] = CanvasGraphics.prototype[op]; + } + + return CanvasGraphics; +})(); + + + +var ShadingIRs = {}; + +ShadingIRs.RadialAxial = { + fromIR: function RadialAxial_fromIR(raw) { + var type = raw[1]; + var colorStops = raw[2]; + var p0 = raw[3]; + var p1 = raw[4]; + var r0 = raw[5]; + var r1 = raw[6]; + return { + type: 'Pattern', + getPattern: function RadialAxial_getPattern(ctx) { + var grad; + if (type === 'axial') { + grad = ctx.createLinearGradient(p0[0], p0[1], p1[0], p1[1]); + } else if (type === 'radial') { + grad = ctx.createRadialGradient(p0[0], p0[1], r0, p1[0], p1[1], r1); + } + + for (var i = 0, ii = colorStops.length; i < ii; ++i) { + var c = colorStops[i]; + grad.addColorStop(c[0], c[1]); + } + return grad; + } + }; + } +}; + +ShadingIRs.Dummy = { + fromIR: function Dummy_fromIR() { + return { + type: 'Pattern', + getPattern: function Dummy_fromIR_getPattern() { + return 'hotpink'; + } + }; + } +}; + +function getShadingPatternFromIR(raw) { + return ShadingIRs[raw[0]].fromIR(raw); +} + +var TilingPattern = (function TilingPatternClosure() { + var PaintType = { + COLORED: 1, + UNCOLORED: 2 + }; + + var MAX_PATTERN_SIZE = 3000; // 10in @ 300dpi shall be enough + + function TilingPattern(IR, color, ctx, objs, commonObjs, baseTransform) { + this.name = IR[1][0].name; + this.operatorList = IR[2]; + this.matrix = IR[3] || [1, 0, 0, 1, 0, 0]; + this.bbox = IR[4]; + this.xstep = IR[5]; + this.ystep = IR[6]; + this.paintType = IR[7]; + this.tilingType = IR[8]; + this.color = color; + this.objs = objs; + this.commonObjs = commonObjs; + this.baseTransform = baseTransform; + this.type = 'Pattern'; + this.ctx = ctx; + } + + TilingPattern.prototype = { + createPatternCanvas: function TilinPattern_createPatternCanvas(owner) { + var operatorList = this.operatorList; + var bbox = this.bbox; + var xstep = this.xstep; + var ystep = this.ystep; + var paintType = this.paintType; + var tilingType = this.tilingType; + var color = this.color; + var objs = this.objs; + var commonObjs = this.commonObjs; + var ctx = this.ctx; + + info('TilingType: ' + tilingType); + + var x0 = bbox[0], y0 = bbox[1], x1 = bbox[2], y1 = bbox[3]; + + var topLeft = [x0, y0]; + // we want the canvas to be as large as the step size + var botRight = [x0 + xstep, y0 + ystep]; + + var width = botRight[0] - topLeft[0]; + var height = botRight[1] - topLeft[1]; + + // Obtain scale from matrix and current transformation matrix. + var matrixScale = Util.singularValueDecompose2dScale(this.matrix); + var curMatrixScale = Util.singularValueDecompose2dScale( + this.baseTransform); + var combinedScale = [matrixScale[0] * curMatrixScale[0], + matrixScale[1] * curMatrixScale[1]]; + + // MAX_PATTERN_SIZE is used to avoid OOM situation. + // Use width and height values that are as close as possible to the end + // result when the pattern is used. Too low value makes the pattern look + // blurry. Too large value makes it look too crispy. + width = Math.min(Math.ceil(Math.abs(width * combinedScale[0])), + MAX_PATTERN_SIZE); + + height = Math.min(Math.ceil(Math.abs(height * combinedScale[1])), + MAX_PATTERN_SIZE); + + var tmpCanvas = CachedCanvases.getCanvas('pattern', width, height, true); + var tmpCtx = tmpCanvas.context; + var graphics = new CanvasGraphics(tmpCtx, commonObjs, objs); + graphics.groupLevel = owner.groupLevel; + + this.setFillAndStrokeStyleToContext(tmpCtx, paintType, color); + + this.setScale(width, height, xstep, ystep); + this.transformToScale(graphics); + + // transform coordinates to pattern space + var tmpTranslate = [1, 0, 0, 1, -topLeft[0], -topLeft[1]]; + graphics.transform.apply(graphics, tmpTranslate); + + this.clipBbox(graphics, bbox, x0, y0, x1, y1); + + graphics.executeOperatorList(operatorList); + return tmpCanvas.canvas; + }, + + setScale: function TilingPattern_setScale(width, height, xstep, ystep) { + this.scale = [width / xstep, height / ystep]; + }, + + transformToScale: function TilingPattern_transformToScale(graphics) { + var scale = this.scale; + var tmpScale = [scale[0], 0, 0, scale[1], 0, 0]; + graphics.transform.apply(graphics, tmpScale); + }, + + scaleToContext: function TilingPattern_scaleToContext() { + var scale = this.scale; + this.ctx.scale(1 / scale[0], 1 / scale[1]); + }, + + clipBbox: function clipBbox(graphics, bbox, x0, y0, x1, y1) { + if (bbox && isArray(bbox) && 4 == bbox.length) { + var bboxWidth = x1 - x0; + var bboxHeight = y1 - y0; + graphics.rectangle(x0, y0, bboxWidth, bboxHeight); + graphics.clip(); + graphics.endPath(); + } + }, + + setFillAndStrokeStyleToContext: + function setFillAndStrokeStyleToContext(context, paintType, color) { + switch (paintType) { + case PaintType.COLORED: + var ctx = this.ctx; + context.fillStyle = ctx.fillStyle; + context.strokeStyle = ctx.strokeStyle; + break; + case PaintType.UNCOLORED: + var rgbColor = ColorSpace.singletons.rgb.getRgb(color, 0); + var cssColor = Util.makeCssRgb(rgbColor); + context.fillStyle = cssColor; + context.strokeStyle = cssColor; + break; + default: + error('Unsupported paint type: ' + paintType); + } + }, + + getPattern: function TilingPattern_getPattern(ctx, owner) { + var temporaryPatternCanvas = this.createPatternCanvas(owner); + + var ctx = this.ctx; + ctx.setTransform.apply(ctx, this.baseTransform); + ctx.transform.apply(ctx, this.matrix); + this.scaleToContext(); + + return ctx.createPattern(temporaryPatternCanvas, 'repeat'); + } + }; + + return TilingPattern; +})(); + + +PDFJS.disableFontFace = false; + +var FontLoader = { + insertRule: function fontLoaderInsertRule(rule) { + var styleElement = document.getElementById('PDFJS_FONT_STYLE_TAG'); + if (!styleElement) { + styleElement = document.createElement('style'); + styleElement.id = 'PDFJS_FONT_STYLE_TAG'; + document.documentElement.getElementsByTagName('head')[0].appendChild( + styleElement); + } + + var styleSheet = styleElement.sheet; + styleSheet.insertRule(rule, styleSheet.cssRules.length); + }, + clear: function fontLoaderClear() { + var styleElement = document.getElementById('PDFJS_FONT_STYLE_TAG'); + if (styleElement) { + styleElement.parentNode.removeChild(styleElement); + } + }, + get loadTestFont() { + // This is a CFF font with 1 glyph for '.' that fills its entire width and + // height. + return shadow(this, 'loadTestFont', atob( + 'T1RUTwALAIAAAwAwQ0ZGIDHtZg4AAAOYAAAAgUZGVE1lkzZwAAAEHAAAABxHREVGABQAFQ' + + 'AABDgAAAAeT1MvMlYNYwkAAAEgAAAAYGNtYXABDQLUAAACNAAAAUJoZWFk/xVFDQAAALwA' + + 'AAA2aGhlYQdkA+oAAAD0AAAAJGhtdHgD6AAAAAAEWAAAAAZtYXhwAAJQAAAAARgAAAAGbm' + + 'FtZVjmdH4AAAGAAAAAsXBvc3T/hgAzAAADeAAAACAAAQAAAAEAALZRFsRfDzz1AAsD6AAA' + + 'AADOBOTLAAAAAM4KHDwAAAAAA+gDIQAAAAgAAgAAAAAAAAABAAADIQAAAFoD6AAAAAAD6A' + + 'ABAAAAAAAAAAAAAAAAAAAAAQAAUAAAAgAAAAQD6AH0AAUAAAKKArwAAACMAooCvAAAAeAA' + + 'MQECAAACAAYJAAAAAAAAAAAAAQAAAAAAAAAAAAAAAFBmRWQAwAAuAC4DIP84AFoDIQAAAA' + + 'AAAQAAAAAAAAAAACAAIAABAAAADgCuAAEAAAAAAAAAAQAAAAEAAAAAAAEAAQAAAAEAAAAA' + + 'AAIAAQAAAAEAAAAAAAMAAQAAAAEAAAAAAAQAAQAAAAEAAAAAAAUAAQAAAAEAAAAAAAYAAQ' + + 'AAAAMAAQQJAAAAAgABAAMAAQQJAAEAAgABAAMAAQQJAAIAAgABAAMAAQQJAAMAAgABAAMA' + + 'AQQJAAQAAgABAAMAAQQJAAUAAgABAAMAAQQJAAYAAgABWABYAAAAAAAAAwAAAAMAAAAcAA' + + 'EAAAAAADwAAwABAAAAHAAEACAAAAAEAAQAAQAAAC7//wAAAC7////TAAEAAAAAAAABBgAA' + + 'AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAA' + + 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' + + 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' + + 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' + + 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAA' + + 'AAAAD/gwAyAAAAAQAAAAAAAAAAAAAAAAAAAAABAAQEAAEBAQJYAAEBASH4DwD4GwHEAvgc' + + 'A/gXBIwMAYuL+nz5tQXkD5j3CBLnEQACAQEBIVhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWF' + + 'hYWFhYWFhYAAABAQAADwACAQEEE/t3Dov6fAH6fAT+fPp8+nwHDosMCvm1Cvm1DAz6fBQA' + + 'AAAAAAABAAAAAMmJbzEAAAAAzgTjFQAAAADOBOQpAAEAAAAAAAAADAAUAAQAAAABAAAAAg' + + 'ABAAAAAAAAAAAD6AAAAAAAAA==' + )); + }, + + loadTestFontId: 0, + + loadingContext: { + requests: [], + nextRequestId: 0 + }, + + isSyncFontLoadingSupported: (function detectSyncFontLoadingSupport() { + if (isWorker) + return false; + + // User agent string sniffing is bad, but there is no reliable way to tell + // if font is fully loaded and ready to be used with canvas. + var userAgent = window.navigator.userAgent; + var m = /Mozilla\/5.0.*?rv:(\d+).*? Gecko/.exec(userAgent); + if (m && m[1] >= 14) + return true; + // TODO other browsers + return false; + })(), + + bind: function fontLoaderBind(fonts, callback) { + assert(!isWorker, 'bind() shall be called from main thread'); + + var rules = [], fontsToLoad = []; + for (var i = 0, ii = fonts.length; i < ii; i++) { + var font = fonts[i]; + + // Add the font to the DOM only once or skip if the font + // is already loaded. + if (font.attached || font.loading === false) { + continue; + } + font.attached = true; + + var rule = font.bindDOM(); + if (rule) { + rules.push(rule); + fontsToLoad.push(font); + } + } + + var request = FontLoader.queueLoadingCallback(callback); + if (rules.length > 0 && !this.isSyncFontLoadingSupported) { + FontLoader.prepareFontLoadEvent(rules, fontsToLoad, request); + } else { + request.complete(); + } + }, + + queueLoadingCallback: function FontLoader_queueLoadingCallback(callback) { + function LoadLoader_completeRequest() { + assert(!request.end, 'completeRequest() cannot be called twice'); + request.end = Date.now(); + + // sending all completed requests in order how they were queued + while (context.requests.length > 0 && context.requests[0].end) { + var otherRequest = context.requests.shift(); + setTimeout(otherRequest.callback, 0); + } + } + + var context = FontLoader.loadingContext; + var requestId = 'pdfjs-font-loading-' + (context.nextRequestId++); + var request = { + id: requestId, + complete: LoadLoader_completeRequest, + callback: callback, + started: Date.now() + }; + context.requests.push(request); + return request; + }, + + prepareFontLoadEvent: function fontLoaderPrepareFontLoadEvent(rules, + fonts, + request) { + /** Hack begin */ + // There's currently no event when a font has finished downloading so the + // following code is a dirty hack to 'guess' when a font is + // ready. It's assumed fonts are loaded in order, so add a known test + // font after the desired fonts and then test for the loading of that + // test font. + + function int32(data, offset) { + return (data.charCodeAt(offset) << 24) | + (data.charCodeAt(offset + 1) << 16) | + (data.charCodeAt(offset + 2) << 8) | + (data.charCodeAt(offset + 3) & 0xff); + } + + function 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); + return chunk1 + insert + chunk2; + } + + var i, ii; + + var canvas = document.createElement('canvas'); + canvas.width = 1; + canvas.height = 1; + var ctx = canvas.getContext('2d'); + + var called = 0; + function isFontReady(name, callback) { + called++; + // With setTimeout clamping this gives the font ~100ms to load. + if(called > 30) { + warn('Load test font never loaded.'); + callback(); + return; + } + ctx.font = '30px ' + name; + ctx.fillText('.', 0, 20); + var imageData = ctx.getImageData(0, 0, 1, 1); + if (imageData.data[3] > 0) { + callback(); + return; + } + setTimeout(isFontReady.bind(null, name, callback)); + } + + var loadTestFontId = 'lt' + Date.now() + this.loadTestFontId++; + // Chromium seems to cache fonts based on a hash of the actual font data, + // so the font must be modified for each load test else it will appear to + // be loaded already. + // TODO: This could maybe be made faster by avoiding the btoa of the full + // font by splitting it in chunks before hand and padding the font id. + var data = this.loadTestFont; + var COMMENT_OFFSET = 976; // has to be on 4 byte boundary (for checksum) + data = spliceString(data, COMMENT_OFFSET, loadTestFontId.length, + loadTestFontId); + // CFF checksum is important for IE, adjusting it + var CFF_CHECKSUM_OFFSET = 16; + var XXXX_VALUE = 0x58585858; // the "comment" filled with 'X' + var checksum = int32(data, CFF_CHECKSUM_OFFSET); + for (i = 0, ii = loadTestFontId.length - 3; i < ii; i += 4) { + checksum = (checksum - XXXX_VALUE + int32(loadTestFontId, i)) | 0; + } + if (i < loadTestFontId.length) { // align to 4 bytes boundary + checksum = (checksum - XXXX_VALUE + + int32(loadTestFontId + 'XXX', i)) | 0; + } + data = spliceString(data, CFF_CHECKSUM_OFFSET, 4, string32(checksum)); + + var url = 'url(data:font/opentype;base64,' + btoa(data) + ');'; + var rule = '@font-face { font-family:"' + loadTestFontId + '";src:' + + url + '}'; + FontLoader.insertRule(rule); + + var names = []; + for (i = 0, ii = fonts.length; i < ii; i++) { + names.push(fonts[i].loadedName); + } + names.push(loadTestFontId); + + var div = document.createElement('div'); + div.setAttribute('style', + 'visibility: hidden;' + + 'width: 10px; height: 10px;' + + 'position: absolute; top: 0px; left: 0px;'); + for (i = 0, ii = names.length; i < ii; ++i) { + var span = document.createElement('span'); + span.textContent = 'Hi'; + span.style.fontFamily = names[i]; + div.appendChild(span); + } + document.body.appendChild(div); + + isFontReady(loadTestFontId, function() { + document.body.removeChild(div); + request.complete(); + }); + /** Hack end */ + } +}; + +var FontFace = (function FontFaceClosure() { + function FontFace(name, file, properties) { + this.compiledGlyphs = {}; + if (arguments.length === 1) { + // importing translated data + var data = arguments[0]; + for (var i in data) { + this[i] = data[i]; + } + return; + } + } + FontFace.prototype = { + bindDOM: function FontFace_bindDOM() { + if (!this.data) + return null; + + if (PDFJS.disableFontFace) { + this.disableFontFace = true; + return null; + } + + var data = bytesToString(this.data); + var fontName = this.loadedName; + + // Add the font-face rule to the document + var url = ('url(data:' + this.mimetype + ';base64,' + + window.btoa(data) + ');'); + var rule = '@font-face { font-family:"' + fontName + '";src:' + url + '}'; + + FontLoader.insertRule(rule); + + if (PDFJS.pdfBug && 'FontInspector' in globalScope && + globalScope['FontInspector'].enabled) + globalScope['FontInspector'].fontAdded(this, url); + + return rule; + }, + getPathGenerator: function (objs, character) { + if (!(character in this.compiledGlyphs)) { + var js = objs.get(this.loadedName + '_path_' + character); + /*jshint -W054 */ + this.compiledGlyphs[character] = new Function('c', 'size', js); + } + return this.compiledGlyphs[character]; + } + }; + return FontFace; +})(); + + +}).call((typeof window === 'undefined') ? this : window); + +if (!PDFJS.workerSrc && typeof document !== 'undefined') { + // workerSrc is not set -- using last script url to define default location + PDFJS.workerSrc = (function () { + 'use strict'; + var scriptTagContainer = document.body || + document.getElementsByTagName('head')[0]; + var pdfjsSrc = scriptTagContainer.lastChild.src; + return pdfjsSrc && pdfjsSrc.replace(/\.js$/i, '.worker.js'); + })(); +} + + diff --git a/attachment_preview/static/lib/ViewerJS/pdf.worker.js b/attachment_preview/static/lib/ViewerJS/pdf.worker.js new file mode 100644 index 00000000000..b3ef5ebf5af --- /dev/null +++ b/attachment_preview/static/lib/ViewerJS/pdf.worker.js @@ -0,0 +1,39900 @@ +/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ +/* Copyright 2012 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// 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'; + +(function pdfjsWrapper() { + // Use strict in our context only - users might not want it + 'use strict'; + +/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ +/* Copyright 2012 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* globals Cmd, ColorSpace, Dict, MozBlobBuilder, Name, PDFJS, Ref, URL, + Promise */ + +'use strict'; + +var globalScope = (typeof window === 'undefined') ? this : window; + +var isWorker = (typeof window == 'undefined'); + +var FONT_IDENTITY_MATRIX = [0.001, 0, 0, 0.001, 0, 0]; + +var TextRenderingMode = { + FILL: 0, + STROKE: 1, + FILL_STROKE: 2, + INVISIBLE: 3, + FILL_ADD_TO_PATH: 4, + STROKE_ADD_TO_PATH: 5, + FILL_STROKE_ADD_TO_PATH: 6, + ADD_TO_PATH: 7, + FILL_STROKE_MASK: 3, + ADD_TO_PATH_FLAG: 4 +}; + +// The global PDFJS object exposes the API +// In production, it will be declared outside a global wrapper +// In development, it will be declared here +if (!globalScope.PDFJS) { + globalScope.PDFJS = {}; +} + +globalScope.PDFJS.pdfBug = false; + +PDFJS.VERBOSITY_LEVELS = { + errors: 0, + warnings: 1, + infos: 5 +}; + +// All the possible operations for an operator list. +var OPS = PDFJS.OPS = { + // Intentionally start from 1 so it is easy to spot bad operators that will be + // 0's. + dependency: 1, + setLineWidth: 2, + setLineCap: 3, + setLineJoin: 4, + setMiterLimit: 5, + setDash: 6, + setRenderingIntent: 7, + setFlatness: 8, + setGState: 9, + save: 10, + restore: 11, + transform: 12, + moveTo: 13, + lineTo: 14, + curveTo: 15, + curveTo2: 16, + curveTo3: 17, + closePath: 18, + rectangle: 19, + stroke: 20, + closeStroke: 21, + fill: 22, + eoFill: 23, + fillStroke: 24, + eoFillStroke: 25, + closeFillStroke: 26, + closeEOFillStroke: 27, + endPath: 28, + clip: 29, + eoClip: 30, + beginText: 31, + endText: 32, + setCharSpacing: 33, + setWordSpacing: 34, + setHScale: 35, + setLeading: 36, + setFont: 37, + setTextRenderingMode: 38, + setTextRise: 39, + moveText: 40, + setLeadingMoveText: 41, + setTextMatrix: 42, + nextLine: 43, + showText: 44, + showSpacedText: 45, + nextLineShowText: 46, + nextLineSetSpacingShowText: 47, + setCharWidth: 48, + setCharWidthAndBounds: 49, + setStrokeColorSpace: 50, + setFillColorSpace: 51, + setStrokeColor: 52, + setStrokeColorN: 53, + setFillColor: 54, + setFillColorN: 55, + setStrokeGray: 56, + setFillGray: 57, + setStrokeRGBColor: 58, + setFillRGBColor: 59, + setStrokeCMYKColor: 60, + setFillCMYKColor: 61, + shadingFill: 62, + beginInlineImage: 63, + beginImageData: 64, + endInlineImage: 65, + paintXObject: 66, + markPoint: 67, + markPointProps: 68, + beginMarkedContent: 69, + beginMarkedContentProps: 70, + endMarkedContent: 71, + beginCompat: 72, + endCompat: 73, + paintFormXObjectBegin: 74, + paintFormXObjectEnd: 75, + beginGroup: 76, + endGroup: 77, + beginAnnotations: 78, + endAnnotations: 79, + beginAnnotation: 80, + endAnnotation: 81, + paintJpegXObject: 82, + paintImageMaskXObject: 83, + paintImageMaskXObjectGroup: 84, + paintImageXObject: 85, + paintInlineImageXObject: 86, + paintInlineImageXObjectGroup: 87 +}; + +// A notice for devs. These are good for things that are helpful to devs, such +// as warning that Workers were disabled, which is important to devs but not +// end users. +function info(msg) { + if (PDFJS.verbosity >= PDFJS.VERBOSITY_LEVELS.infos) { + console.log('Info: ' + msg); + } +} + +// Non-fatal warnings. +function warn(msg) { + if (PDFJS.verbosity >= PDFJS.VERBOSITY_LEVELS.warnings) { + console.log('Warning: ' + msg); + } +} + +// Fatal errors that should trigger the fallback UI and halt execution by +// throwing an exception. +function error(msg) { + // If multiple arguments were passed, pass them all to the log function. + if (arguments.length > 1) { + var logArguments = ['Error:']; + logArguments.push.apply(logArguments, arguments); + console.log.apply(console, logArguments); + // Join the arguments into a single string for the lines below. + msg = [].join.call(arguments, ' '); + } else { + console.log('Error: ' + msg); + } + console.log(backtrace()); + UnsupportedManager.notify(UNSUPPORTED_FEATURES.unknown); + throw new Error(msg); +} + +function backtrace() { + try { + throw new Error(); + } catch (e) { + return e.stack ? e.stack.split('\n').slice(2).join('\n') : ''; + } +} + +function assert(cond, msg) { + if (!cond) + error(msg); +} + +var UNSUPPORTED_FEATURES = PDFJS.UNSUPPORTED_FEATURES = { + unknown: 'unknown', + forms: 'forms', + javaScript: 'javaScript', + smask: 'smask', + shadingPattern: 'shadingPattern', + font: 'font' +}; + +var UnsupportedManager = PDFJS.UnsupportedManager = + (function UnsupportedManagerClosure() { + var listeners = []; + return { + listen: function (cb) { + listeners.push(cb); + }, + notify: function (featureId) { + warn('Unsupported feature "' + featureId + '"'); + for (var i = 0, ii = listeners.length; i < ii; i++) { + listeners[i](featureId); + } + } + }; +})(); + +// Combines two URLs. The baseUrl shall be absolute URL. If the url is an +// absolute URL, it will be returned as is. +function combineUrl(baseUrl, url) { + if (!url) + return baseUrl; + if (/^[a-z][a-z0-9+\-.]*:/i.test(url)) + return url; + if (url.charAt(0) == '/') { + // absolute path + var i = baseUrl.indexOf('://'); + i = baseUrl.indexOf('/', i + 3); + return baseUrl.substring(0, i) + url; + } else { + // relative path + var pathLength = baseUrl.length, i; + i = baseUrl.lastIndexOf('#'); + pathLength = i >= 0 ? i : pathLength; + i = baseUrl.lastIndexOf('?', pathLength); + pathLength = i >= 0 ? i : pathLength; + var prefixLength = baseUrl.lastIndexOf('/', pathLength); + return baseUrl.substring(0, prefixLength + 1) + url; + } +} + +// Validates if URL is safe and allowed, e.g. to avoid XSS. +function isValidUrl(url, allowRelative) { + if (!url) { + return false; + } + // RFC 3986 (http://tools.ietf.org/html/rfc3986#section-3.1) + // scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) + var protocol = /^[a-z][a-z0-9+\-.]*(?=:)/i.exec(url); + if (!protocol) { + return allowRelative; + } + protocol = protocol[0].toLowerCase(); + switch (protocol) { + case 'http': + case 'https': + case 'ftp': + case 'mailto': + return true; + default: + return false; + } +} +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, + configurable: true, + writable: false }); + return value; +} + +var PasswordResponses = PDFJS.PasswordResponses = { + NEED_PASSWORD: 1, + INCORRECT_PASSWORD: 2 +}; + +var PasswordException = (function PasswordExceptionClosure() { + function PasswordException(msg, code) { + this.name = 'PasswordException'; + this.message = msg; + this.code = code; + } + + PasswordException.prototype = new Error(); + PasswordException.constructor = PasswordException; + + return PasswordException; +})(); + +var UnknownErrorException = (function UnknownErrorExceptionClosure() { + function UnknownErrorException(msg, details) { + this.name = 'UnknownErrorException'; + this.message = msg; + this.details = details; + } + + UnknownErrorException.prototype = new Error(); + UnknownErrorException.constructor = UnknownErrorException; + + return UnknownErrorException; +})(); + +var InvalidPDFException = (function InvalidPDFExceptionClosure() { + function InvalidPDFException(msg) { + this.name = 'InvalidPDFException'; + this.message = msg; + } + + InvalidPDFException.prototype = new Error(); + InvalidPDFException.constructor = InvalidPDFException; + + return InvalidPDFException; +})(); + +var MissingPDFException = (function MissingPDFExceptionClosure() { + function MissingPDFException(msg) { + this.name = 'MissingPDFException'; + this.message = msg; + } + + MissingPDFException.prototype = new Error(); + MissingPDFException.constructor = MissingPDFException; + + return MissingPDFException; +})(); + +var NotImplementedException = (function NotImplementedExceptionClosure() { + function NotImplementedException(msg) { + this.message = msg; + } + + NotImplementedException.prototype = new Error(); + NotImplementedException.prototype.name = 'NotImplementedException'; + NotImplementedException.constructor = NotImplementedException; + + return NotImplementedException; +})(); + +var MissingDataException = (function MissingDataExceptionClosure() { + function MissingDataException(begin, end) { + this.begin = begin; + this.end = end; + this.message = 'Missing data [' + begin + ', ' + end + ')'; + } + + MissingDataException.prototype = new Error(); + MissingDataException.prototype.name = 'MissingDataException'; + MissingDataException.constructor = MissingDataException; + + return MissingDataException; +})(); + +var XRefParseException = (function XRefParseExceptionClosure() { + function XRefParseException(msg) { + this.message = msg; + } + + XRefParseException.prototype = new Error(); + XRefParseException.prototype.name = 'XRefParseException'; + XRefParseException.constructor = XRefParseException; + + return XRefParseException; +})(); + + +function bytesToString(bytes) { + var str = ''; + var length = bytes.length; + for (var n = 0; n < length; ++n) + str += String.fromCharCode(bytes[n]); + return str; +} + +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; + return bytes; +} + +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] + ')'; + }; + + Util.makeCssCmyk = function Util_makeCssCmyk(cmyk) { + var rgb = ColorSpace.singletons.cmyk.getRgb(cmyk, 0); + return Util.makeCssRgb(rgb); + }; + + // Concatenates two transformation matrices together and returns the result. + Util.transform = function Util_transform(m1, m2) { + return [ + m1[0] * m2[0] + m1[2] * m2[1], + m1[1] * m2[0] + m1[3] * m2[1], + m1[0] * m2[2] + m1[2] * m2[3], + m1[1] * m2[2] + m1[3] * m2[3], + m1[0] * m2[4] + m1[2] * m2[5] + m1[4], + m1[1] * m2[4] + m1[3] * m2[5] + m1[5] + ]; + }; + + // For 2d affine transforms + Util.applyTransform = function Util_applyTransform(p, m) { + var xt = p[0] * m[0] + p[1] * m[2] + m[4]; + var yt = p[0] * m[1] + p[1] * m[3] + m[5]; + return [xt, yt]; + }; + + Util.applyInverseTransform = function Util_applyInverseTransform(p, m) { + var d = m[0] * m[3] - m[1] * m[2]; + var xt = (p[0] * m[3] - p[1] * m[2] + m[2] * m[5] - m[4] * m[3]) / d; + var yt = (-p[0] * m[1] + p[1] * m[0] + m[4] * m[1] - m[5] * m[0]) / d; + return [xt, yt]; + }; + + // Applies the transform to the rectangle and finds the minimum axially + // aligned bounding box. + Util.getAxialAlignedBoundingBox = + function Util_getAxialAlignedBoundingBox(r, m) { + + var p1 = Util.applyTransform(r, m); + var p2 = Util.applyTransform(r.slice(2, 4), m); + var p3 = Util.applyTransform([r[0], r[3]], m); + var p4 = Util.applyTransform([r[2], r[1]], m); + return [ + Math.min(p1[0], p2[0], p3[0], p4[0]), + Math.min(p1[1], p2[1], p3[1], p4[1]), + Math.max(p1[0], p2[0], p3[0], p4[0]), + Math.max(p1[1], p2[1], p3[1], p4[1]) + ]; + }; + + Util.inverseTransform = function Util_inverseTransform(m) { + var d = m[0] * m[3] - m[1] * m[2]; + return [m[3] / d, -m[1] / d, -m[2] / d, m[0] / d, + (m[2] * m[5] - m[4] * m[3]) / d, (m[4] * m[1] - m[5] * m[0]) / d]; + }; + + // Apply a generic 3d matrix M on a 3-vector v: + // | a b c | | X | + // | d e f | x | Y | + // | g h i | | Z | + // M is assumed to be serialized as [a,b,c,d,e,f,g,h,i], + // with v as [X,Y,Z] + Util.apply3dTransform = function Util_apply3dTransform(m, v) { + return [ + m[0] * v[0] + m[1] * v[1] + m[2] * v[2], + m[3] * v[0] + m[4] * v[1] + m[5] * v[2], + m[6] * v[0] + m[7] * v[1] + m[8] * v[2] + ]; + }; + + // This calculation uses Singular Value Decomposition. + // The SVD can be represented with formula A = USV. We are interested in the + // matrix S here because it represents the scale values. + Util.singularValueDecompose2dScale = + function Util_singularValueDecompose2dScale(m) { + + var transpose = [m[0], m[2], m[1], m[3]]; + + // Multiply matrix m with its transpose. + var a = m[0] * transpose[0] + m[1] * transpose[2]; + var b = m[0] * transpose[1] + m[1] * transpose[3]; + var c = m[2] * transpose[0] + m[3] * transpose[2]; + var d = m[2] * transpose[1] + m[3] * transpose[3]; + + // Solve the second degree polynomial to get roots. + var first = (a + d) / 2; + var second = Math.sqrt((a + d) * (a + d) - 4 * (a * d - c * b)) / 2; + var sx = first + second || 1; + var sy = first - second || 1; + + // Scale values are the square roots of the eigenvalues. + return [Math.sqrt(sx), Math.sqrt(sy)]; + }; + + // Normalize rectangle rect=[x1, y1, x2, y2] so that (x1,y1) < (x2,y2) + // For coordinate systems whose origin lies in the bottom-left, this + // means normalization to (BL,TR) ordering. For systems with origin in the + // top-left, this means (TL,BR) ordering. + Util.normalizeRect = function Util_normalizeRect(rect) { + var r = rect.slice(0); // clone rect + if (rect[0] > rect[2]) { + r[0] = rect[2]; + r[2] = rect[0]; + } + if (rect[1] > rect[3]) { + r[1] = rect[3]; + r[3] = rect[1]; + } + return r; + }; + + // Returns a rectangle [x1, y1, x2, y2] corresponding to the + // intersection of rect1 and rect2. If no intersection, returns 'false' + // The rectangle coordinates of rect1, rect2 should be [x1, y1, x2, y2] + Util.intersect = function Util_intersect(rect1, rect2) { + function compare(a, b) { + return a - b; + } + + // Order points along the axes + var orderedX = [rect1[0], rect1[2], rect2[0], rect2[2]].sort(compare), + orderedY = [rect1[1], rect1[3], rect2[1], rect2[3]].sort(compare), + result = []; + + rect1 = Util.normalizeRect(rect1); + rect2 = Util.normalizeRect(rect2); + + // X: first and second points belong to different rectangles? + if ((orderedX[0] === rect1[0] && orderedX[1] === rect2[0]) || + (orderedX[0] === rect2[0] && orderedX[1] === rect1[0])) { + // Intersection must be between second and third points + result[0] = orderedX[1]; + result[2] = orderedX[2]; + } else { + return false; + } + + // Y: first and second points belong to different rectangles? + if ((orderedY[0] === rect1[1] && orderedY[1] === rect2[1]) || + (orderedY[0] === rect2[1] && orderedY[1] === rect1[1])) { + // Intersection must be between second and third points + result[1] = orderedY[1]; + result[3] = orderedY[2]; + } else { + return false; + } + + return result; + }; + + Util.sign = function Util_sign(num) { + return num < 0 ? -1 : 1; + }; + + // TODO(mack): Rename appendToArray + Util.concatenateToArray = function concatenateToArray(arr1, arr2) { + Array.prototype.push.apply(arr1, arr2); + }; + + Util.prependToArray = function concatenateToArray(arr1, arr2) { + Array.prototype.unshift.apply(arr1, arr2); + }; + + Util.extendObj = function extendObj(obj1, obj2) { + for (var key in obj2) { + obj1[key] = obj2[key]; + } + }; + + Util.getInheritableProperty = function Util_getInheritableProperty(dict, + name) { + while (dict && !dict.has(name)) { + dict = dict.get('Parent'); + } + if (!dict) { + return null; + } + return dict.get(name); + }; + + Util.inherit = function Util_inherit(sub, base, prototype) { + sub.prototype = Object.create(base.prototype); + sub.prototype.constructor = sub; + for (var prop in prototype) { + sub.prototype[prop] = prototype[prop]; + } + }; + + Util.loadScript = function Util_loadScript(src, callback) { + var script = document.createElement('script'); + var loaded = false; + script.setAttribute('src', src); + if (callback) { + script.onload = function() { + if (!loaded) { + callback(); + } + loaded = true; + }; + } + document.getElementsByTagName('head')[0].appendChild(script); + }; + + return Util; +})(); + +var PageViewport = PDFJS.PageViewport = (function PageViewportClosure() { + function PageViewport(viewBox, scale, rotation, offsetX, offsetY, dontFlip) { + this.viewBox = viewBox; + this.scale = scale; + this.rotation = rotation; + this.offsetX = offsetX; + this.offsetY = offsetY; + + // creating transform to convert pdf coordinate system to the normal + // canvas like coordinates taking in account scale and rotation + var centerX = (viewBox[2] + viewBox[0]) / 2; + var centerY = (viewBox[3] + viewBox[1]) / 2; + var rotateA, rotateB, rotateC, rotateD; + rotation = rotation % 360; + rotation = rotation < 0 ? rotation + 360 : rotation; + switch (rotation) { + case 180: + rotateA = -1; rotateB = 0; rotateC = 0; rotateD = 1; + break; + case 90: + rotateA = 0; rotateB = 1; rotateC = 1; rotateD = 0; + break; + case 270: + rotateA = 0; rotateB = -1; rotateC = -1; rotateD = 0; + break; + //case 0: + default: + rotateA = 1; rotateB = 0; rotateC = 0; rotateD = -1; + break; + } + + if (dontFlip) { + rotateC = -rotateC; rotateD = -rotateD; + } + + var offsetCanvasX, offsetCanvasY; + var width, height; + if (rotateA === 0) { + offsetCanvasX = Math.abs(centerY - viewBox[1]) * scale + offsetX; + offsetCanvasY = Math.abs(centerX - viewBox[0]) * scale + offsetY; + width = Math.abs(viewBox[3] - viewBox[1]) * scale; + height = Math.abs(viewBox[2] - viewBox[0]) * scale; + } else { + offsetCanvasX = Math.abs(centerX - viewBox[0]) * scale + offsetX; + offsetCanvasY = Math.abs(centerY - viewBox[1]) * scale + offsetY; + width = Math.abs(viewBox[2] - viewBox[0]) * scale; + height = Math.abs(viewBox[3] - viewBox[1]) * scale; + } + // creating transform for the following operations: + // translate(-centerX, -centerY), rotate and flip vertically, + // scale, and translate(offsetCanvasX, offsetCanvasY) + this.transform = [ + rotateA * scale, + rotateB * scale, + rotateC * scale, + rotateD * scale, + offsetCanvasX - rotateA * scale * centerX - rotateC * scale * centerY, + offsetCanvasY - rotateB * scale * centerX - rotateD * scale * centerY + ]; + + this.width = width; + this.height = height; + this.fontScale = scale; + } + PageViewport.prototype = { + clone: function PageViewPort_clone(args) { + args = args || {}; + var scale = 'scale' in args ? args.scale : this.scale; + var rotation = 'rotation' in args ? args.rotation : this.rotation; + return new PageViewport(this.viewBox.slice(), scale, rotation, + this.offsetX, this.offsetY, args.dontFlip); + }, + convertToViewportPoint: function PageViewport_convertToViewportPoint(x, y) { + return Util.applyTransform([x, y], this.transform); + }, + 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]]; + }, + convertToPdfPoint: function PageViewport_convertToPdfPoint(x, y) { + return Util.applyInverseTransform([x, y], this.transform); + } + }; + return PageViewport; +})(); + +var PDFStringTranslateTable = [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0x2D8, 0x2C7, 0x2C6, 0x2D9, 0x2DD, 0x2DB, 0x2DA, 0x2DC, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2022, 0x2020, 0x2021, 0x2026, 0x2014, + 0x2013, 0x192, 0x2044, 0x2039, 0x203A, 0x2212, 0x2030, 0x201E, 0x201C, + 0x201D, 0x2018, 0x2019, 0x201A, 0x2122, 0xFB01, 0xFB02, 0x141, 0x152, 0x160, + 0x178, 0x17D, 0x131, 0x142, 0x153, 0x161, 0x17E, 0, 0x20AC +]; + +function stringToPDFString(str) { + var i, n = str.length, str2 = ''; + 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)); + } else { + for (i = 0; i < n; ++i) { + var code = PDFStringTranslateTable[str.charCodeAt(i)]; + str2 += code ? String.fromCharCode(code) : str.charAt(i); + } + } + return str2; +} + +function stringToUTF8String(str) { + return decodeURIComponent(escape(str)); +} + +function isEmptyObj(obj) { + for (var key in obj) { + return false; + } + return true; +} + +function isBool(v) { + return typeof v == 'boolean'; +} + +function isInt(v) { + return typeof v == 'number' && ((v | 0) == v); +} + +function isNum(v) { + return typeof v == 'number'; +} + +function isString(v) { + return typeof v == 'string'; +} + +function isNull(v) { + return v === null; +} + +function isName(v) { + return v instanceof Name; +} + +function isCmd(v, cmd) { + return v instanceof Cmd && (!cmd || v.cmd == cmd); +} + +function isDict(v, type) { + if (!(v instanceof Dict)) { + return false; + } + if (!type) { + return true; + } + var dictType = v.get('Type'); + return isName(dictType) && dictType.name == type; +} + +function isArray(v) { + return v instanceof Array; +} + +function isStream(v) { + return typeof v == 'object' && v !== null && v !== undefined && + ('getBytes' in v); +} + +function isArrayBuffer(v) { + return typeof v == 'object' && v !== null && v !== undefined && + ('byteLength' in v); +} + +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'); +} + +/** + * Legacy support for PDFJS Promise implementation. + * TODO remove eventually + */ +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; + }; +})(); + +/** + * Polyfill for Promises: + * The following promise implementation tries to generally implment the + * Promise/A+ spec. Some notable differences from other promise libaries are: + * - There currently isn't a seperate deferred and promise object. + * - Unhandled rejections eventually show an error if they aren't handled. + * + * Based off of the work in: + * https://bugzilla.mozilla.org/show_bug.cgi?id=810490 + */ +(function PromiseClosure() { + if (globalScope.Promise) { + // Promises existing in the DOM/Worker, checking presence of all/resolve + if (typeof globalScope.Promise.all !== 'function') { + globalScope.Promise.all = function (iterable) { + var count = 0, results = [], resolve, reject; + var promise = new globalScope.Promise(function (resolve_, reject_) { + resolve = resolve_; + reject = reject_; + }); + iterable.forEach(function (p, i) { + count++; + p.then(function (result) { + results[i] = result; + count--; + if (count === 0) { + resolve(results); + } + }, reject); + }); + if (count === 0) { + resolve(results); + } + return promise; + }; + } + if (typeof globalScope.Promise.resolve !== 'function') { + globalScope.Promise.resolve = function (x) { + return new globalScope.Promise(function (resolve) { resolve(x); }); + }; + } + return; + } + var STATUS_PENDING = 0; + var STATUS_RESOLVED = 1; + var STATUS_REJECTED = 2; + + // In an attempt to avoid silent exceptions, unhandled rejections are + // tracked and if they aren't handled in a certain amount of time an + // error is logged. + var REJECTION_TIMEOUT = 500; + + var HandlerManager = { + handlers: [], + running: false, + unhandledRejections: [], + pendingRejectionCheck: false, + + scheduleHandlers: function scheduleHandlers(promise) { + if (promise._status == STATUS_PENDING) { + return; + } + + this.handlers = this.handlers.concat(promise._handlers); + promise._handlers = []; + + if (this.running) { + return; + } + this.running = true; + + setTimeout(this.runHandlers.bind(this), 0); + }, + + runHandlers: function runHandlers() { + var RUN_TIMEOUT = 1; // ms + var timeoutAt = Date.now() + RUN_TIMEOUT; + while (this.handlers.length > 0) { + var handler = this.handlers.shift(); + + var nextStatus = handler.thisPromise._status; + var nextValue = handler.thisPromise._value; + + try { + if (nextStatus === STATUS_RESOLVED) { + if (typeof(handler.onResolve) == 'function') { + nextValue = handler.onResolve(nextValue); + } + } else if (typeof(handler.onReject) === 'function') { + nextValue = handler.onReject(nextValue); + nextStatus = STATUS_RESOLVED; + + if (handler.thisPromise._unhandledRejection) { + this.removeUnhandeledRejection(handler.thisPromise); + } + } + } catch (ex) { + nextStatus = STATUS_REJECTED; + nextValue = ex; + } + + handler.nextPromise._updateStatus(nextStatus, nextValue); + if (Date.now() >= timeoutAt) { + break; + } + } + + if (this.handlers.length > 0) { + setTimeout(this.runHandlers.bind(this), 0); + return; + } + + this.running = false; + }, + + addUnhandledRejection: function addUnhandledRejection(promise) { + this.unhandledRejections.push({ + promise: promise, + time: Date.now() + }); + this.scheduleRejectionCheck(); + }, + + removeUnhandeledRejection: function removeUnhandeledRejection(promise) { + promise._unhandledRejection = false; + for (var i = 0; i < this.unhandledRejections.length; i++) { + if (this.unhandledRejections[i].promise === promise) { + this.unhandledRejections.splice(i); + i--; + } + } + }, + + scheduleRejectionCheck: function scheduleRejectionCheck() { + if (this.pendingRejectionCheck) { + return; + } + this.pendingRejectionCheck = true; + setTimeout(function rejectionCheck() { + this.pendingRejectionCheck = false; + var now = Date.now(); + for (var i = 0; i < this.unhandledRejections.length; i++) { + if (now - this.unhandledRejections[i].time > REJECTION_TIMEOUT) { + var unhandled = this.unhandledRejections[i].promise._value; + var msg = 'Unhandled rejection: ' + unhandled; + if (unhandled.stack) { + msg += '\n' + unhandled.stack; + } + warn(msg); + this.unhandledRejections.splice(i); + i--; + } + } + if (this.unhandledRejections.length) { + this.scheduleRejectionCheck(); + } + }.bind(this), REJECTION_TIMEOUT); + } + }; + + function Promise(resolver) { + this._status = STATUS_PENDING; + this._handlers = []; + resolver.call(this, this._resolve.bind(this), this._reject.bind(this)); + } + /** + * Builds a promise that is resolved when all the passed in promises are + * resolved. + * @param {array} array of data and/or promises to wait for. + * @return {Promise} New dependant promise. + */ + Promise.all = function Promise_all(promises) { + var resolveAll, rejectAll; + var deferred = new Promise(function (resolve, reject) { + resolveAll = resolve; + rejectAll = reject; + }); + var unresolved = promises.length; + var results = []; + if (unresolved === 0) { + resolveAll(results); + return deferred; + } + function reject(reason) { + if (deferred._status === STATUS_REJECTED) { + return; + } + results = []; + rejectAll(reason); + } + for (var i = 0, ii = promises.length; i < ii; ++i) { + var promise = promises[i]; + var resolve = (function(i) { + return function(value) { + if (deferred._status === STATUS_REJECTED) { + return; + } + results[i] = value; + unresolved--; + if (unresolved === 0) + resolveAll(results); + }; + })(i); + if (Promise.isPromise(promise)) { + promise.then(resolve, reject); + } else { + resolve(promise); + } + } + return deferred; + }; + + /** + * Checks if the value is likely a promise (has a 'then' function). + * @return {boolean} true if x is thenable + */ + Promise.isPromise = function Promise_isPromise(value) { + return value && typeof value.then === 'function'; + }; + /** + * Creates resolved promise + * @param x resolve value + * @returns {Promise} + */ + Promise.resolve = function Promise_resolve(x) { + return new Promise(function (resolve) { resolve(x); }); + }; + + Promise.prototype = { + _status: null, + _value: null, + _handlers: null, + _unhandledRejection: null, + + _updateStatus: function Promise__updateStatus(status, value) { + if (this._status === STATUS_RESOLVED || + this._status === STATUS_REJECTED) { + return; + } + + if (status == STATUS_RESOLVED && + Promise.isPromise(value)) { + value.then(this._updateStatus.bind(this, STATUS_RESOLVED), + this._updateStatus.bind(this, STATUS_REJECTED)); + return; + } + + this._status = status; + this._value = value; + + if (status === STATUS_REJECTED && this._handlers.length === 0) { + this._unhandledRejection = true; + HandlerManager.addUnhandledRejection(this); + } + + HandlerManager.scheduleHandlers(this); + }, + + _resolve: function Promise_resolve(value) { + this._updateStatus(STATUS_RESOLVED, value); + }, + + _reject: function Promise_reject(reason) { + this._updateStatus(STATUS_REJECTED, reason); + }, + + then: function Promise_then(onResolve, onReject) { + var nextPromise = new Promise(function (resolve, reject) { + this.resolve = reject; + this.reject = reject; + }); + this._handlers.push({ + thisPromise: this, + onResolve: onResolve, + onReject: onReject, + nextPromise: nextPromise + }); + HandlerManager.scheduleHandlers(this); + return nextPromise; + } + }; + + globalScope.Promise = Promise; +})(); + +var StatTimer = (function StatTimerClosure() { + function rpad(str, pad, length) { + while (str.length < length) + str += pad; + return str; + } + function StatTimer() { + this.started = {}; + this.times = []; + this.enabled = true; + } + StatTimer.prototype = { + time: function StatTimer_time(name) { + if (!this.enabled) + return; + if (name in this.started) + warn('Timer is already running for ' + name); + this.started[name] = Date.now(); + }, + timeEnd: function StatTimer_timeEnd(name) { + if (!this.enabled) + return; + if (!(name in this.started)) + warn('Timer has not been started for ' + name); + this.times.push({ + 'name': name, + 'start': this.started[name], + 'end': Date.now() + }); + // Remove timer from started so it can be called again. + delete this.started[name]; + }, + toString: function StatTimer_toString() { + var 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) { + var name = times[i]['name']; + if (name.length > longest) + longest = name.length; + } + for (var i = 0, ii = times.length; i < ii; ++i) { + var span = times[i]; + var duration = span.end - span.start; + out += rpad(span['name'], ' ', longest) + ' ' + duration + 'ms\n'; + } + return out; + } + }; + return StatTimer; +})(); + +PDFJS.createBlob = function createBlob(data, contentType) { + if (typeof Blob !== 'undefined') + return new Blob([data], { type: contentType }); + // Blob builder is deprecated in FF14 and removed in FF18. + var bb = new MozBlobBuilder(); + bb.append(data); + return bb.getBlob(contentType); +}; + +PDFJS.createObjectURL = (function createObjectURLClosure() { + // Blob/createObjectURL is not available, falling back to data schema. + var digits = + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; + + return function createObjectURL(data, contentType) { + if (!PDFJS.disableCreateObjectURL && + typeof URL !== 'undefined' && URL.createObjectURL) { + var blob = PDFJS.createBlob(data, contentType); + return URL.createObjectURL(blob); + } + + var buffer = 'data:' + contentType + ';base64,'; + for (var i = 0, ii = data.length; i < ii; i += 3) { + var b1 = data[i] & 0xFF; + var b2 = data[i + 1] & 0xFF; + var b3 = data[i + 2] & 0xFF; + var d1 = b1 >> 2, d2 = ((b1 & 3) << 4) | (b2 >> 4); + var d3 = i + 1 < ii ? ((b2 & 0xF) << 2) | (b3 >> 6) : 64; + var d4 = i + 2 < ii ? (b3 & 0x3F) : 64; + buffer += digits[d1] + digits[d2] + digits[d3] + digits[d4]; + } + return buffer; + }; +})(); + +function MessageHandler(name, comObj) { + this.name = name; + this.comObj = comObj; + this.callbackIndex = 1; + this.postMessageTransfers = true; + var callbacks = this.callbacks = {}; + var ah = this.actionHandler = {}; + + ah['console_log'] = [function ahConsoleLog(data) { + console.log.apply(console, data); + }]; + ah['console_error'] = [function ahConsoleError(data) { + console.error.apply(console, data); + }]; + ah['_unsupported_feature'] = [function ah_unsupportedFeature(data) { + UnsupportedManager.notify(data); + }]; + + comObj.onmessage = function messageHandlerComObjOnMessage(event) { + var data = event.data; + if (data.isReply) { + var callbackId = data.callbackId; + if (data.callbackId in callbacks) { + var callback = callbacks[callbackId]; + delete callbacks[callbackId]; + callback(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) { + comObj.postMessage({ + isReply: true, + callbackId: data.callbackId, + data: resolvedData + }); + }); + action[0].call(action[1], data.data, deferred); + } else { + action[0].call(action[1], data.data); + } + } else { + error('Unkown action from worker: ' + data.action); + } + }; +} + +MessageHandler.prototype = { + on: function messageHandlerOn(actionName, handler, scope) { + var ah = this.actionHandler; + if (ah[actionName]) { + error('There is already an actionName called "' + actionName + '"'); + } + ah[actionName] = [handler, scope]; + }, + /** + * Sends a message to the comObj to invoke the action with the supplied data. + * @param {String} actionName Action to call. + * @param {JSON} data JSON data to send. + * @param {function} [callback] Optional callback that will handle a reply. + * @param {Array} [transfers] Optional list of transfers/ArrayBuffers + */ + send: function messageHandlerSend(actionName, data, callback, transfers) { + var message = { + action: actionName, + data: data + }; + if (callback) { + var callbackId = this.callbackIndex++; + this.callbacks[callbackId] = callback; + message.callbackId = callbackId; + } + if (transfers && this.postMessageTransfers) { + this.comObj.postMessage(message, transfers); + } else { + this.comObj.postMessage(message); + } + } +}; + +function loadJpegStream(id, imageUrl, objs) { + var img = new Image(); + img.onload = (function loadJpegStream_onloadClosure() { + objs.resolve(id, img); + }); + img.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; +})(); + + + + +var NetworkManager = (function NetworkManagerClosure() { + + var OK_RESPONSE = 200; + var PARTIAL_CONTENT_RESPONSE = 206; + + function NetworkManager(url, args) { + this.url = url; + args = args || {}; + this.httpHeaders = args.httpHeaders || {}; + this.withCredentials = args.withCredentials || false; + this.getXhr = args.getXhr || + function NetworkManager_getXhr() { + return new XMLHttpRequest(); + }; + + this.currXhrId = 0; + this.pendingRequests = {}; + this.loadedRequests = {}; + } + + function getArrayBuffer(xhr) { + var data = (xhr.mozResponseArrayBuffer || xhr.mozResponse || + xhr.responseArrayBuffer || xhr.response); + if (typeof data !== 'string') { + return data; + } + var length = data.length; + var buffer = new Uint8Array(length); + for (var i = 0; i < length; i++) { + buffer[i] = data.charCodeAt(i) & 0xFF; + } + return buffer; + } + + NetworkManager.prototype = { + requestRange: function NetworkManager_requestRange(begin, end, listeners) { + var args = { + begin: begin, + end: end + }; + for (var prop in listeners) { + args[prop] = listeners[prop]; + } + return this.request(args); + }, + + requestFull: function NetworkManager_requestRange(listeners) { + return this.request(listeners); + }, + + request: function NetworkManager_requestRange(args) { + var xhr = this.getXhr(); + var xhrId = this.currXhrId++; + var pendingRequest = this.pendingRequests[xhrId] = { + xhr: xhr + }; + + xhr.open('GET', this.url); + xhr.withCredentials = this.withCredentials; + for (var property in this.httpHeaders) { + var value = this.httpHeaders[property]; + if (typeof value === 'undefined') { + continue; + } + xhr.setRequestHeader(property, value); + } + if ('begin' in args && 'end' in args) { + var rangeStr = args.begin + '-' + (args.end - 1); + xhr.setRequestHeader('Range', 'bytes=' + rangeStr); + pendingRequest.expectedStatus = 206; + } else { + pendingRequest.expectedStatus = 200; + } + + xhr.mozResponseType = xhr.responseType = 'arraybuffer'; + + if (args.onProgress) { + xhr.onprogress = args.onProgress; + } + if (args.onError) { + xhr.onerror = function(evt) { + args.onError(xhr.status); + }; + } + xhr.onreadystatechange = this.onStateChange.bind(this, xhrId); + + pendingRequest.onHeadersReceived = args.onHeadersReceived; + pendingRequest.onDone = args.onDone; + pendingRequest.onError = args.onError; + + xhr.send(null); + + return xhrId; + }, + + onStateChange: function NetworkManager_onStateChange(xhrId, evt) { + var pendingRequest = this.pendingRequests[xhrId]; + if (!pendingRequest) { + // Maybe abortRequest was called... + return; + } + + var xhr = pendingRequest.xhr; + if (xhr.readyState >= 2 && pendingRequest.onHeadersReceived) { + pendingRequest.onHeadersReceived(); + delete pendingRequest.onHeadersReceived; + } + + if (xhr.readyState !== 4) { + return; + } + + if (!(xhrId in this.pendingRequests)) { + // The XHR request might have been aborted in onHeadersReceived() + // callback, in which case we should abort request + return; + } + + delete this.pendingRequests[xhrId]; + + // success status == 0 can be on ftp, file and other protocols + if (xhr.status === 0 && /^https?:/i.test(this.url)) { + if (pendingRequest.onError) { + pendingRequest.onError(xhr.status); + } + return; + } + var xhrStatus = xhr.status || OK_RESPONSE; + + // From http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35.2: + // "A server MAY ignore the Range header". This means it's possible to + // get a 200 rather than a 206 response from a range request. + var ok_response_on_range_request = + xhrStatus === OK_RESPONSE && + pendingRequest.expectedStatus === PARTIAL_CONTENT_RESPONSE; + + if (!ok_response_on_range_request && + xhrStatus !== pendingRequest.expectedStatus) { + if (pendingRequest.onError) { + pendingRequest.onError(xhr.status); + } + return; + } + + this.loadedRequests[xhrId] = true; + + var chunk = getArrayBuffer(xhr); + if (xhrStatus === PARTIAL_CONTENT_RESPONSE) { + var rangeHeader = xhr.getResponseHeader('Content-Range'); + var matches = /bytes (\d+)-(\d+)\/(\d+)/.exec(rangeHeader); + var begin = parseInt(matches[1], 10); + pendingRequest.onDone({ + begin: begin, + chunk: chunk + }); + } else { + pendingRequest.onDone({ + begin: 0, + chunk: chunk + }); + } + }, + + hasPendingRequests: function NetworkManager_hasPendingRequests() { + for (var xhrId in this.pendingRequests) { + return true; + } + return false; + }, + + getRequestXhr: function NetworkManager_getXhr(xhrId) { + return this.pendingRequests[xhrId].xhr; + }, + + isPendingRequest: function NetworkManager_isPendingRequest(xhrId) { + return xhrId in this.pendingRequests; + }, + + isLoadedRequest: function NetworkManager_isLoadedRequest(xhrId) { + return xhrId in this.loadedRequests; + }, + + abortAllRequests: function NetworkManager_abortAllRequests() { + for (var xhrId in this.pendingRequests) { + this.abortRequest(xhrId | 0); + } + }, + + abortRequest: function NetworkManager_abortRequest(xhrId) { + var xhr = this.pendingRequests[xhrId].xhr; + delete this.pendingRequests[xhrId]; + xhr.abort(); + } + }; + + return NetworkManager; +})(); + + + +var ChunkedStream = (function ChunkedStreamClosure() { + function ChunkedStream(length, chunkSize, manager) { + this.bytes = new Uint8Array(length); + this.start = 0; + this.pos = 0; + this.end = length; + this.chunkSize = chunkSize; + this.loadedChunks = []; + this.numChunksLoaded = 0; + this.numChunks = Math.ceil(length / chunkSize); + this.manager = manager; + this.initialDataLength = 0; + } + + // required methods for a stream. if a particular stream does not + // implement these, an error should be thrown + ChunkedStream.prototype = { + + getMissingChunks: function ChunkedStream_getMissingChunks() { + var chunks = []; + for (var chunk = 0, n = this.numChunks; chunk < n; ++chunk) { + if (!(chunk in this.loadedChunks)) { + chunks.push(chunk); + } + } + return chunks; + }, + + getBaseStreams: function ChunkedStream_getBaseStreams() { + return [this]; + }, + + allChunksLoaded: function ChunkedStream_allChunksLoaded() { + return this.numChunksLoaded === this.numChunks; + }, + + onReceiveData: function(begin, chunk) { + var end = begin + chunk.byteLength; + + assert(begin % this.chunkSize === 0, 'Bad begin offset: ' + begin); + // Using this.length is inaccurate here since this.start can be moved + // See ChunkedStream.moveStart() + var length = this.bytes.length; + assert(end % this.chunkSize === 0 || end === length, + 'Bad end offset: ' + end); + + this.bytes.set(new Uint8Array(chunk), begin); + var chunkSize = this.chunkSize; + var beginChunk = Math.floor(begin / chunkSize); + var endChunk = Math.floor((end - 1) / chunkSize) + 1; + + for (var chunk = beginChunk; chunk < endChunk; ++chunk) { + if (!(chunk in this.loadedChunks)) { + this.loadedChunks[chunk] = 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; + } + }, + + ensureRange: function ChunkedStream_ensureRange(begin, end) { + if (begin >= end) { + return; + } + + if (end <= this.initialDataLength) { + return; + } + + var chunkSize = this.chunkSize; + var beginChunk = Math.floor(begin / chunkSize); + var endChunk = Math.floor((end - 1) / chunkSize) + 1; + for (var chunk = beginChunk; chunk < endChunk; ++chunk) { + if (!(chunk in this.loadedChunks)) { + 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)) { + return chunk; + } + } + // Wrap around to beginning + for (var chunk = 0; chunk < beginChunk; ++chunk) { + if (!(chunk in this.loadedChunks)) { + return chunk; + } + } + return null; + }, + + hasChunk: function ChunkedStream_hasChunk(chunk) { + return chunk in this.loadedChunks; + }, + + get length() { + return this.end - this.start; + }, + + getByte: function ChunkedStream_getByte() { + var pos = this.pos; + if (pos >= this.end) { + return -1; + } + this.ensureRange(pos, pos + 1); + return this.bytes[this.pos++]; + }, + + // returns subarray of original buffer + // should only be read + getBytes: function ChunkedStream_getBytes(length) { + var bytes = this.bytes; + var pos = this.pos; + var strEnd = this.end; + + if (!length) { + this.ensureRange(pos, strEnd); + return bytes.subarray(pos, strEnd); + } + + var end = pos + length; + if (end > strEnd) + end = strEnd; + this.ensureRange(pos, end); + + this.pos = end; + return bytes.subarray(pos, end); + }, + + peekBytes: function ChunkedStream_peekBytes(length) { + var bytes = this.getBytes(length); + this.pos -= bytes.length; + return bytes; + }, + + getByteRange: function ChunkedStream_getBytes(begin, end) { + this.ensureRange(begin, end); + return this.bytes.subarray(begin, end); + }, + + skip: function ChunkedStream_skip(n) { + if (!n) + n = 1; + this.pos += n; + }, + + reset: function ChunkedStream_reset() { + this.pos = this.start; + }, + + moveStart: function ChunkedStream_moveStart() { + this.start = this.pos; + }, + + makeSubStream: function ChunkedStream_makeSubStream(start, length, dict) { + function ChunkedStreamSubstream() {} + ChunkedStreamSubstream.prototype = Object.create(this); + ChunkedStreamSubstream.prototype.getMissingChunks = function() { + var chunkSize = this.chunkSize; + var beginChunk = Math.floor(this.start / chunkSize); + var endChunk = Math.floor((this.end - 1) / chunkSize) + 1; + var missingChunks = []; + for (var chunk = beginChunk; chunk < endChunk; ++chunk) { + if (!(chunk in this.loadedChunks)) { + missingChunks.push(chunk); + } + } + return missingChunks; + }; + var subStream = new ChunkedStreamSubstream(); + subStream.pos = subStream.start = start; + subStream.end = start + length || this.end; + subStream.dict = dict; + return subStream; + }, + + isStream: true + }; + + return ChunkedStream; +})(); + +var ChunkedStreamManager = (function ChunkedStreamManagerClosure() { + + function ChunkedStreamManager(length, chunkSize, url, args) { + var self = this; + this.stream = new ChunkedStream(length, chunkSize, this); + this.length = length; + this.chunkSize = chunkSize; + this.url = url; + this.disableAutoFetch = args.disableAutoFetch; + var msgHandler = this.msgHandler = args.msgHandler; + + if (args.chunkedViewerLoading) { + msgHandler.on('OnDataRange', this.onReceiveData.bind(this)); + msgHandler.on('OnDataProgress', this.onProgress.bind(this)); + this.sendRequest = function ChunkedStreamManager_sendRequest(begin, end) { + msgHandler.send('RequestDataRange', { begin: begin, end: end }); + }; + } else { + + var getXhr = function getXhr() { + return new XMLHttpRequest(); + }; + this.networkManager = new NetworkManager(this.url, { + getXhr: getXhr, + httpHeaders: args.httpHeaders, + withCredentials: args.withCredentials + }); + this.sendRequest = function ChunkedStreamManager_sendRequest(begin, end) { + this.networkManager.requestRange(begin, end, { + onDone: this.onReceiveData.bind(this), + onProgress: this.onProgress.bind(this) + }); + }; + } + + this.currRequestId = 0; + + this.chunksNeededByRequest = {}; + this.requestsByChunk = {}; + this.callbacksByRequest = {}; + + this.loadedStream = new LegacyPromise(); + if (args.initialData) { + this.setInitialData(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; + }, + + // Get all the chunks that are not yet loaded and groups them into + // contiguous ranges to load in as few requests as possible + requestAllChunks: function ChunkedStreamManager_requestAllChunks() { + var missingChunks = this.stream.getMissingChunks(); + this.requestChunks(missingChunks); + return this.loadedStream; + }, + + requestChunks: function ChunkedStreamManager_requestChunks(chunks, + callback) { + var requestId = this.currRequestId++; + + var chunksNeeded; + this.chunksNeededByRequest[requestId] = chunksNeeded = {}; + for (var i = 0, ii = chunks.length; i < ii; i++) { + if (!this.stream.hasChunk(chunks[i])) { + chunksNeeded[chunks[i]] = true; + } + } + + if (isEmptyObj(chunksNeeded)) { + if (callback) { + callback(); + } + return; + } + + this.callbacksByRequest[requestId] = callback; + + var chunksToRequest = []; + for (var chunk in chunksNeeded) { + chunk = chunk | 0; + if (!(chunk in this.requestsByChunk)) { + this.requestsByChunk[chunk] = []; + chunksToRequest.push(chunk); + } + this.requestsByChunk[chunk].push(requestId); + } + + if (!chunksToRequest.length) { + return; + } + + var groupedChunksToRequest = this.groupChunks(chunksToRequest); + + for (var i = 0; i < groupedChunksToRequest.length; ++i) { + var groupedChunk = groupedChunksToRequest[i]; + var begin = groupedChunk.beginChunk * this.chunkSize; + var end = Math.min(groupedChunk.endChunk * this.chunkSize, this.length); + this.sendRequest(begin, end); + } + }, + + getStream: function ChunkedStreamManager_getStream() { + return this.stream; + }, + + // Loads any chunks in the requested range that are not yet loaded + requestRange: function ChunkedStreamManager_requestRange( + begin, end, callback) { + + end = Math.min(end, this.length); + + var beginChunk = this.getBeginChunk(begin); + var endChunk = this.getEndChunk(end); + + var chunks = []; + for (var chunk = beginChunk; chunk < endChunk; ++chunk) { + chunks.push(chunk); + } + + this.requestChunks(chunks, callback); + }, + + requestRanges: function ChunkedStreamManager_requestRanges(ranges, + callback) { + ranges = ranges || []; + var chunksToRequest = []; + + for (var i = 0; i < ranges.length; i++) { + var beginChunk = this.getBeginChunk(ranges[i].begin); + var endChunk = this.getEndChunk(ranges[i].end); + for (var chunk = beginChunk; chunk < endChunk; ++chunk) { + if (chunksToRequest.indexOf(chunk) < 0) { + chunksToRequest.push(chunk); + } + } + } + + chunksToRequest.sort(function(a, b) { return a - b; }); + this.requestChunks(chunksToRequest, callback); + }, + + // Groups a sorted array of chunks into as few continguous larger + // chunks as possible + groupChunks: function ChunkedStreamManager_groupChunks(chunks) { + var groupedChunks = []; + var beginChunk = -1; + var prevChunk = -1; + for (var i = 0; i < chunks.length; ++i) { + var chunk = chunks[i]; + + if (beginChunk < 0) { + beginChunk = chunk; + } + + if (prevChunk >= 0 && prevChunk + 1 !== chunk) { + groupedChunks.push({ + beginChunk: beginChunk, endChunk: prevChunk + 1}); + beginChunk = chunk; + } + if (i + 1 === chunks.length) { + groupedChunks.push({ + beginChunk: beginChunk, endChunk: chunk + 1}); + } + + prevChunk = chunk; + } + return groupedChunks; + }, + + onProgress: function ChunkedStreamManager_onProgress(args) { + var bytesLoaded = this.stream.numChunksLoaded * this.chunkSize + + args.loaded; + this.msgHandler.send('DocProgress', { + loaded: bytesLoaded, + total: this.length + }); + }, + + onReceiveData: function ChunkedStreamManager_onReceiveData(args) { + var chunk = args.chunk; + var begin = args.begin; + var end = begin + chunk.byteLength; + + var beginChunk = this.getBeginChunk(begin); + var endChunk = this.getEndChunk(end); + + this.stream.onReceiveData(begin, chunk); + if (this.stream.allChunksLoaded()) { + this.loadedStream.resolve(this.stream); + } + + var loadedRequests = []; + for (var 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]; + var chunksNeeded = this.chunksNeededByRequest[requestId]; + if (chunk in chunksNeeded) { + delete chunksNeeded[chunk]; + } + + if (!isEmptyObj(chunksNeeded)) { + continue; + } + + loadedRequests.push(requestId); + } + } + + // If there are no pending requests, automatically fetch the next + // unfetched chunk of the PDF + if (!this.disableAutoFetch && isEmptyObj(this.requestsByChunk)) { + var nextEmptyChunk; + if (this.stream.numChunksLoaded === 1) { + // This is a special optimization so that after fetching the first + // chunk, rather than fetching the second chunk, we fetch the last + // chunk. + var lastChunk = this.stream.numChunks - 1; + if (!this.stream.hasChunk(lastChunk)) { + nextEmptyChunk = lastChunk; + } + } else { + nextEmptyChunk = this.stream.nextEmptyChunk(endChunk); + } + if (isInt(nextEmptyChunk)) { + this.requestChunks([nextEmptyChunk]); + } + } + + for (var i = 0; i < loadedRequests.length; ++i) { + var requestId = loadedRequests[i]; + var callback = this.callbacksByRequest[requestId]; + delete this.callbacksByRequest[requestId]; + if (callback) { + callback(); + } + } + + this.msgHandler.send('DocProgress', { + loaded: this.stream.numChunksLoaded * this.chunkSize, + total: this.length + }); + }, + + getBeginChunk: function ChunkedStreamManager_getBeginChunk(begin) { + var chunk = Math.floor(begin / this.chunkSize); + return chunk; + }, + + getEndChunk: function ChunkedStreamManager_getEndChunk(end) { + if (end % this.chunkSize === 0) { + return end / this.chunkSize; + } + + // 0 -> 0 + // 1 -> 1 + // 99 -> 1 + // 100 -> 1 + // 101 -> 2 + var chunk = Math.floor((end - 1) / this.chunkSize) + 1; + return chunk; + } + }; + + return ChunkedStreamManager; +})(); + + + +// TODO(mack): Make use of PDFJS.Util.inherit() when it becomes available +var BasePdfManager = (function BasePdfManagerClosure() { + function BasePdfManager() { + throw new Error('Cannot initialize BaseManagerManager'); + } + + BasePdfManager.prototype = { + onLoadedStream: function BasePdfManager_onLoadedStream() { + throw new NotImplementedException(); + }, + + ensureModel: function BasePdfManager_ensureModel(prop, args) { + return this.ensure(this.pdfModel, prop, args); + }, + + ensureXRef: function BasePdfManager_ensureXRef(prop, args) { + return this.ensure(this.pdfModel.xref, prop, args); + }, + + ensureCatalog: function BasePdfManager_ensureCatalog(prop, args) { + return this.ensure(this.pdfModel.catalog, prop, args); + }, + + getPage: function BasePdfManager_pagePage(pageIndex) { + return this.pdfModel.getPage(pageIndex); + }, + + cleanup: function BasePdfManager_cleanup() { + return this.pdfModel.cleanup(); + }, + + ensure: function BasePdfManager_ensure(obj, prop, args) { + return new NotImplementedException(); + }, + + requestRange: function BasePdfManager_ensure(begin, end) { + return new NotImplementedException(); + }, + + requestLoadedStream: function BasePdfManager_requestLoadedStream() { + return new NotImplementedException(); + }, + + updatePassword: function BasePdfManager_updatePassword(password) { + this.pdfModel.xref.password = this.password = password; + if (this.passwordChangedPromise) { + this.passwordChangedPromise.resolve(); + } + }, + + terminate: function BasePdfManager_terminate() { + return new NotImplementedException(); + } + }; + + return BasePdfManager; +})(); + +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); + } + + LocalPdfManager.prototype = Object.create(BasePdfManager.prototype); + LocalPdfManager.prototype.constructor = LocalPdfManager; + + 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; + } + 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; + }; + + LocalPdfManager.prototype.requestLoadedStream = + function LocalPdfManager_requestLoadedStream() { + }; + + LocalPdfManager.prototype.onLoadedStream = + function LocalPdfManager_getLoadedStream() { + return this.loadedStream; + }; + + LocalPdfManager.prototype.terminate = + function LocalPdfManager_terminate() { + return; + }; + + return LocalPdfManager; +})(); + +var NetworkPdfManager = (function NetworkPdfManagerClosure() { + + var CHUNK_SIZE = 65536; + + function NetworkPdfManager(args, msgHandler) { + + this.msgHandler = msgHandler; + + var params = { + msgHandler: msgHandler, + httpHeaders: args.httpHeaders, + withCredentials: args.withCredentials, + chunkedViewerLoading: args.chunkedViewerLoading, + disableAutoFetch: args.disableAutoFetch, + initialData: args.initialData + }; + this.streamManager = new ChunkedStreamManager(args.length, CHUNK_SIZE, + args.url, params); + + this.pdfModel = new PDFDocument(this, this.streamManager.getStream(), + args.password); + } + + NetworkPdfManager.prototype = Object.create(BasePdfManager.prototype); + NetworkPdfManager.prototype.constructor = NetworkPdfManager; + + NetworkPdfManager.prototype.ensure = + function NetworkPdfManager_ensure(obj, prop, args) { + var promise = new LegacyPromise(); + this.ensureHelper(promise, obj, prop, args); + return promise; + }; + + 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; + } + + this.streamManager.requestRange(e.begin, e.end, function() { + this.ensureHelper(promise, obj, prop, args); + }.bind(this)); + } + }; + + NetworkPdfManager.prototype.requestRange = + function NetworkPdfManager_requestRange(begin, end) { + var promise = new LegacyPromise(); + this.streamManager.requestRange(begin, end, function() { + promise.resolve(); + }); + return promise; + }; + + NetworkPdfManager.prototype.requestLoadedStream = + function NetworkPdfManager_requestLoadedStream() { + this.streamManager.requestAllChunks(); + }; + + NetworkPdfManager.prototype.onLoadedStream = + function NetworkPdfManager_getLoadedStream() { + return this.streamManager.onLoadedStream(); + }; + + NetworkPdfManager.prototype.terminate = + function NetworkPdfManager_terminate() { + this.streamManager.networkManager.abortAllRequests(); + }; + + return NetworkPdfManager; +})(); + + + +var Page = (function PageClosure() { + + function Page(pdfManager, xref, pageIndex, pageDict, ref, fontCache) { + this.pdfManager = pdfManager; + this.pageIndex = pageIndex; + this.pageDict = pageDict; + this.xref = xref; + this.ref = ref; + this.fontCache = fontCache; + this.idCounters = { + obj: 0 + }; + this.resourcesPromise = null; + } + + Page.prototype = { + getPageProp: function Page_getPageProp(key) { + return this.pageDict.get(key); + }, + inheritPageProp: function Page_inheritPageProp(key) { + var dict = this.pageDict; + var obj = dict.get(key); + while (obj === undefined) { + dict = dict.get('Parent'); + if (!dict) + break; + obj = dict.get(key); + } + return obj; + }, + get content() { + return this.getPageProp('Contents'); + }, + get resources() { + return shadow(this, 'resources', this.inheritPageProp('Resources')); + }, + get mediaBox() { + var obj = this.inheritPageProp('MediaBox'); + // Reset invalid media box to letter size. + if (!isArray(obj) || obj.length !== 4) + obj = [0, 0, 612, 792]; + return shadow(this, 'mediaBox', obj); + }, + get view() { + var mediaBox = this.mediaBox; + var cropBox = this.inheritPageProp('CropBox'); + if (!isArray(cropBox) || cropBox.length !== 4) + return shadow(this, 'view', mediaBox); + + // From the spec, 6th ed., p.963: + // "The crop, bleed, trim, and art boxes should not ordinarily + // extend beyond the boundaries of the media box. If they do, they are + // effectively reduced to their intersection with the media box." + cropBox = Util.intersect(cropBox, mediaBox); + if (!cropBox) + return shadow(this, 'view', mediaBox); + + return shadow(this, 'view', cropBox); + }, + get annotationRefs() { + return shadow(this, 'annotationRefs', this.inheritPageProp('Annots')); + }, + get rotate() { + var rotate = this.inheritPageProp('Rotate') || 0; + // Normalize rotation so it's a multiple of 90 and between 0 and 270 + if (rotate % 90 !== 0) { + rotate = 0; + } else if (rotate >= 360) { + rotate = rotate % 360; + } else if (rotate < 0) { + // The spec doesn't cover negatives, assume its counterclockwise + // rotation. The following is the other implementation of modulo. + rotate = ((rotate % 360) + 360) % 360; + } + return shadow(this, 'rotate', rotate); + }, + getContentStream: function Page_getContentStream() { + var content = this.content; + var stream; + if (isArray(content)) { + // fetching items + var xref = this.xref; + var i, n = content.length; + var streams = []; + for (i = 0; i < n; ++i) + streams.push(xref.fetchIfRef(content[i])); + stream = new StreamsSequenceStream(streams); + } else if (isStream(content)) { + stream = content; + } else { + // replacing non-existent page content with empty one + stream = new NullStream(); + } + return stream; + }, + loadResources: function(keys) { + if (!this.resourcesPromise) { + // TODO: add async inheritPageProp and remove this. + this.resourcesPromise = this.pdfManager.ensure(this, 'resources'); + } + var promise = new LegacyPromise(); + this.resourcesPromise.then(function resourceSuccess() { + var objectLoader = new ObjectLoader(this.resources.map, + keys, + this.xref); + objectLoader.load().then(function objectLoaderSuccess() { + promise.resolve(); + }); + }.bind(this)); + return promise; + }, + getOperatorList: function Page_getOperatorList(handler) { + 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', + []); + var resourcesPromise = this.loadResources([ + 'ExtGState', + 'ColorSpace', + 'Pattern', + 'Shading', + 'XObject', + 'Font', + // ProcSet + // Properties + ]); + + var partialEvaluator = new PartialEvaluator( + pdfManager, this.xref, handler, + this.pageIndex, 'p' + this.pageIndex + '_', + this.idCounters, this.fontCache); + + var dataPromises = Promise.all( + [contentStreamPromise, resourcesPromise], reject); + dataPromises.then(function(data) { + var contentStream = data[0]; + + + var opList = new OperatorList(handler, self.pageIndex); + + handler.send('StartRenderPage', { + transparency: partialEvaluator.hasBlendModes(self.resources), + pageIndex: self.pageIndex + }); + partialEvaluator.getOperatorList(contentStream, self.resources, opList); + pageListPromise.resolve(opList); + }); + + var annotationsPromise = pdfManager.ensure(this, 'annotations'); + 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; + } + + var annotationsReadyPromise = Annotation.appendToOperatorList( + annotations, pageOpList, pdfManager, partialEvaluator); + annotationsReadyPromise.then(function () { + pageOpList.flush(true); + promise.resolve(pageOpList); + }, reject); + }, reject); + + return promise; + }, + extractTextContent: function Page_extractTextContent() { + var handler = { + on: function nullHandlerOn() {}, + send: function nullHandlerSend() {} + }; + + var self = this; + + var textContentPromise = new LegacyPromise(); + + var pdfManager = this.pdfManager; + var contentStreamPromise = pdfManager.ensure(this, 'getContentStream', + []); + + var resourcesPromise = this.loadResources([ + 'ExtGState', + 'XObject', + 'Font' + ]); + + var dataPromises = Promise.all([contentStreamPromise, + resourcesPromise]); + 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 bidiTexts = partialEvaluator.getTextContent(contentStream, + self.resources); + textContentPromise.resolve(bidiTexts); + }); + + return textContentPromise; + }, + + getAnnotationsData: function Page_getAnnotationsData() { + var annotations = this.annotations; + var annotationsData = []; + for (var i = 0, n = annotations.length; i < n; ++i) { + annotationsData.push(annotations[i].getData()); + } + return annotationsData; + }, + + get annotations() { + var annotations = []; + var annotationRefs = this.annotationRefs || []; + for (var i = 0, n = annotationRefs.length; i < n; ++i) { + var annotationRef = annotationRefs[i]; + var annotation = Annotation.fromRef(this.xref, annotationRef); + if (annotation) { + annotations.push(annotation); + } + } + return shadow(this, 'annotations', annotations); + } + }; + + return Page; +})(); + +/** + * The `PDFDocument` holds all the data of the PDF file. Compared to the + * `PDFDoc`, this one doesn't have any job management code. + * Right now there exists one PDFDocument on the main thread + one object + * for each worker. If there is no worker support enabled, there are two + * `PDFDocument` objects on the main thread created. + */ +var PDFDocument = (function PDFDocumentClosure() { + function PDFDocument(pdfManager, arg, password) { + if (isStream(arg)) + init.call(this, pdfManager, arg, password); + else if (isArrayBuffer(arg)) + init.call(this, pdfManager, new Stream(arg), password); + else + error('PDFDocument: Unknown argument type'); + } + + function init(pdfManager, stream, password) { + assertWellFormed(stream.length > 0, 'stream must have data'); + this.pdfManager = pdfManager; + this.stream = stream; + var xref = new XRef(this.stream, password, pdfManager); + this.xref = xref; + } + + function find(stream, needle, limit, backwards) { + var pos = stream.pos; + var end = stream.end; + var str = ''; + if (pos + limit > end) + limit = end - pos; + for (var n = 0; n < limit; ++n) + str += String.fromCharCode(stream.getByte()); + stream.pos = pos; + var index = backwards ? str.lastIndexOf(needle) : str.indexOf(needle); + if (index == -1) + return false; /* not found */ + stream.pos += index; + return true; /* found */ + } + + var DocumentInfoValidators = { + get entries() { + // Lazily build this since all the validation functions below are not + // defined until after this file loads. + return shadow(this, 'entries', { + Title: isString, + Author: isString, + Subject: isString, + Keywords: isString, + Creator: isString, + Producer: isString, + CreationDate: isString, + ModDate: isString, + Trapped: isName + }); + } + }; + + PDFDocument.prototype = { + parse: function PDFDocument_parse(recoveryMode) { + this.setup(recoveryMode); + try { + // checking if AcroForm is present + this.acroForm = this.catalog.catDict.get('AcroForm'); + if (this.acroForm) { + this.xfa = this.acroForm.get('XFA'); + var fields = this.acroForm.get('Fields'); + if ((!fields || !isArray(fields) || fields.length === 0) && + !this.xfa) { + // no fields and no XFA -- not a form (?) + this.acroForm = null; + } + } + } catch (ex) { + info('Something wrong with AcroForm entry'); + this.acroForm = null; + } + }, + + get linearization() { + var length = this.stream.length; + var linearization = false; + if (length) { + try { + linearization = new Linearization(this.stream); + if (linearization.length != length) { + linearization = false; + } + } catch (err) { + if (err instanceof MissingDataException) { + throw err; + } + + info('The linearization data is not available ' + + 'or unreadable PDF data is found'); + linearization = false; + } + } + // shadow the prototype getter with a data property + return shadow(this, 'linearization', linearization); + }, + get startXRef() { + var stream = this.stream; + var startXRef = 0; + var linearization = this.linearization; + if (linearization) { + // Find end of first obj. + stream.reset(); + if (find(stream, 'endobj', 1024)) + startXRef = stream.pos + 6; + } else { + // Find startxref by jumping backward from the end of the file. + var step = 1024; + var found = false, pos = stream.end; + while (!found && pos > 0) { + pos -= step - 'startxref'.length; + if (pos < 0) + pos = 0; + stream.pos = pos; + found = find(stream, 'startxref', step, true); + } + if (found) { + stream.skip(9); + var ch; + do { + ch = stream.getByte(); + } while (Lexer.isSpace(ch)); + var str = ''; + while (ch >= 0x20 && ch <= 0x39) { // < '9' + str += String.fromCharCode(ch); + ch = stream.getByte(); + } + startXRef = parseInt(str, 10); + if (isNaN(startXRef)) + startXRef = 0; + } + } + // shadow the prototype getter with a data property + return shadow(this, 'startXRef', startXRef); + }, + get mainXRefEntriesOffset() { + var mainXRefEntriesOffset = 0; + var linearization = this.linearization; + if (linearization) + mainXRefEntriesOffset = linearization.mainXRefEntriesOffset; + // shadow the prototype getter with a data property + return shadow(this, 'mainXRefEntriesOffset', mainXRefEntriesOffset); + }, + // Find the header, remove leading garbage and setup the stream + // starting from the header. + checkHeader: function PDFDocument_checkHeader() { + var stream = this.stream; + stream.reset(); + if (find(stream, '%PDF-', 1024)) { + // Found the header, trim off any garbage before it. + stream.moveStart(); + // Reading file format version + var MAX_VERSION_LENGTH = 12; + var version = '', ch; + while ((ch = stream.getByte()) > 0x20) { // SPACE + if (version.length >= MAX_VERSION_LENGTH) { + break; + } + version += String.fromCharCode(ch); + } + // removing "%PDF-"-prefix + this.pdfFormatVersion = version.substring(5); + return; + } + // May not be a PDF file, continue anyway. + }, + parseStartXRef: function PDFDocument_parseStartXRef() { + var startXRef = this.startXRef; + this.xref.setStartXRef(startXRef); + }, + setup: function PDFDocument_setup(recoveryMode) { + this.xref.parse(recoveryMode); + this.catalog = new Catalog(this.pdfManager, this.xref); + }, + get numPages() { + var linearization = this.linearization; + var num = linearization ? linearization.numPages : this.catalog.numPages; + // shadow the prototype getter + return shadow(this, 'numPages', num); + }, + get documentInfo() { + var docInfo = { + PDFFormatVersion: this.pdfFormatVersion, + IsAcroFormPresent: !!this.acroForm, + IsXFAPresent: !!this.xfa + }; + var infoDict; + try { + infoDict = this.xref.trailer.get('Info'); + } catch (err) { + info('The document information dictionary is invalid.'); + } + if (infoDict) { + var validEntries = DocumentInfoValidators.entries; + // Only fill the document info with valid entries from the spec. + for (var key in validEntries) { + if (infoDict.has(key)) { + var value = infoDict.get(key); + // Make sure the value conforms to the spec. + if (validEntries[key](value)) { + docInfo[key] = typeof value !== 'string' ? value : + stringToPDFString(value); + } else { + info('Bad value in document info for "' + key + '"'); + } + } + } + } + return shadow(this, 'documentInfo', docInfo); + }, + get fingerprint() { + var xref = this.xref, hash, fileID = ''; + + if (xref.trailer.has('ID')) { + hash = stringToBytes(xref.trailer.get('ID')[0]); + } else { + hash = calculateMD5(this.stream.bytes.subarray(0, 100), 0, 100); + } + + for (var i = 0, n = hash.length; i < n; i++) { + fileID += hash[i].toString(16); + } + + return shadow(this, 'fingerprint', fileID); + }, + + getPage: function PDFDocument_getPage(pageIndex) { + return this.catalog.getPage(pageIndex); + }, + + cleanup: function PDFDocument_cleanup() { + return this.catalog.cleanup(); + } + }; + + return PDFDocument; +})(); + + + +var Name = (function NameClosure() { + function Name(name) { + this.name = name; + } + + Name.prototype = {}; + + return Name; +})(); + +var Cmd = (function CmdClosure() { + function Cmd(cmd) { + this.cmd = cmd; + } + + Cmd.prototype = {}; + + var cmdCache = {}; + + Cmd.get = function Cmd_get(cmd) { + var cmdValue = cmdCache[cmd]; + if (cmdValue) + return cmdValue; + + return cmdCache[cmd] = new Cmd(cmd); + }; + + return Cmd; +})(); + +var Dict = (function DictClosure() { + var nonSerializable = function nonSerializableClosure() { + return nonSerializable; // creating closure on some variable + }; + + // 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.__nonSerializable__ = nonSerializable; // disable cloning of the Dict + } + + Dict.prototype = { + assignXref: function Dict_assignXref(newXref) { + this.xref = newXref; + }, + + // automatically dereferences Ref objects + get: function Dict_get(key1, key2, key3) { + var value; + var xref = this.xref; + if (typeof (value = this.map[key1]) != 'undefined' || key1 in this.map || + typeof key2 == 'undefined') { + return xref ? xref.fetchIfRef(value) : value; + } + if (typeof (value = this.map[key2]) != 'undefined' || key2 in this.map || + typeof key3 == 'undefined') { + return xref ? xref.fetchIfRef(value) : value; + } + value = this.map[key3] || null; + return xref ? xref.fetchIfRef(value) : value; + }, + + // Same as get(), but returns a promise and uses fetchIfRefAsync(). + getAsync: function Dict_getAsync(key1, key2, key3) { + var value; + var promise; + var xref = this.xref; + 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; + } + 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; + } + value = this.map[key3] || null; + if (xref) { + return xref.fetchIfRefAsync(value); + } + promise = new LegacyPromise(); + promise.resolve(value); + return promise; + }, + + // no dereferencing + getRaw: function Dict_getRaw(key) { + return this.map[key]; + }, + + // 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; + } + return all; + }, + + set: function Dict_set(key, value) { + this.map[key] = value; + }, + + has: function Dict_has(key) { + return key in this.map; + }, + + forEach: function Dict_forEach(callback) { + for (var key in this.map) { + callback(key, this.get(key)); + } + } + }; + + return Dict; +})(); + +var Ref = (function RefClosure() { + function Ref(num, gen) { + this.num = num; + this.gen = gen; + } + + Ref.prototype = {}; + + return Ref; +})(); + +// The reference is identified by number and generation, +// this structure stores only one instance of the reference. +var RefSet = (function RefSetClosure() { + function RefSet() { + this.dict = {}; + } + + RefSet.prototype = { + has: function RefSet_has(ref) { + return ('R' + ref.num + '.' + ref.gen) in this.dict; + }, + + put: function RefSet_put(ref) { + this.dict['R' + ref.num + '.' + ref.gen] = true; + }, + + remove: function RefSet_remove(ref) { + delete this.dict['R' + ref.num + '.' + ref.gen]; + } + }; + + return RefSet; +})(); + +var RefSetCache = (function RefSetCacheClosure() { + function RefSetCache() { + this.dict = Object.create(null); + } + + RefSetCache.prototype = { + get: function RefSetCache_get(ref) { + return this.dict['R' + ref.num + '.' + ref.gen]; + }, + + has: function RefSetCache_has(ref) { + return ('R' + ref.num + '.' + ref.gen) in this.dict; + }, + + put: function RefSetCache_put(ref, obj) { + this.dict['R' + ref.num + '.' + ref.gen] = obj; + }, + + forEach: function RefSetCache_forEach(fn, thisArg) { + for (var i in this.dict) { + fn.call(thisArg, this.dict[i]); + } + }, + + clear: function RefSetCache_clear() { + this.dict = Object.create(null); + } + }; + + return RefSetCache; +})(); + +var Catalog = (function CatalogClosure() { + function Catalog(pdfManager, xref) { + this.pdfManager = pdfManager; + this.xref = xref; + this.catDict = xref.getCatalogObj(); + this.fontCache = new RefSetCache(); + assertWellFormed(isDict(this.catDict), + 'catalog object is not a dictionary'); + + this.pagePromises = []; + } + + Catalog.prototype = { + get metadata() { + var streamRef = this.catDict.getRaw('Metadata'); + if (!isRef(streamRef)) + return shadow(this, 'metadata', null); + + var encryptMetadata = !this.xref.encrypt ? false : + this.xref.encrypt.encryptMetadata; + + var stream = this.xref.fetch(streamRef, !encryptMetadata); + var metadata; + if (stream && isDict(stream.dict)) { + var type = stream.dict.get('Type'); + var subtype = stream.dict.get('Subtype'); + + if (isName(type) && isName(subtype) && + type.name === 'Metadata' && subtype.name === 'XML') { + // XXX: This should examine the charset the XML document defines, + // however since there are currently no real means to decode + // arbitrary charsets, let's just hope that the author of the PDF + // was reasonable enough to stick with the XML default charset, + // which is UTF-8. + try { + metadata = stringToUTF8String(bytesToString(stream.getBytes())); + } catch (e) { + info('Skipping invalid metadata.'); + } + } + } + + return shadow(this, 'metadata', metadata); + }, + get toplevelPagesDict() { + var pagesObj = this.catDict.get('Pages'); + assertWellFormed(isDict(pagesObj), 'invalid top-level pages dictionary'); + // shadow the prototype getter + return shadow(this, 'toplevelPagesDict', pagesObj); + }, + get documentOutline() { + var obj = null; + try { + obj = this.readDocumentOutline(); + } catch (ex) { + if (ex instanceof MissingDataException) { + throw ex; + } + warn('Unable to read document outline'); + } + return shadow(this, 'documentOutline', obj); + }, + readDocumentOutline: function Catalog_readDocumentOutline() { + var xref = this.xref; + var obj = this.catDict.get('Outlines'); + var root = { items: [] }; + if (isDict(obj)) { + obj = obj.getRaw('First'); + var processed = new RefSet(); + if (isRef(obj)) { + var queue = [{obj: obj, parent: root}]; + // to avoid recursion keeping track of the items + // in the processed dictionary + processed.put(obj); + while (queue.length > 0) { + var i = queue.shift(); + var outlineDict = xref.fetchIfRef(i.obj); + if (outlineDict === null) + continue; + if (!outlineDict.has('Title')) + error('Invalid outline item'); + var dest = outlineDict.get('A'); + if (dest) + dest = dest.get('D'); + else if (outlineDict.has('Dest')) { + dest = outlineDict.getRaw('Dest'); + if (isName(dest)) + dest = dest.name; + } + var title = outlineDict.get('Title'); + var outlineItem = { + dest: dest, + title: stringToPDFString(title), + color: outlineDict.get('C') || [0, 0, 0], + count: outlineDict.get('Count'), + bold: !!(outlineDict.get('F') & 2), + italic: !!(outlineDict.get('F') & 1), + items: [] + }; + i.parent.items.push(outlineItem); + obj = outlineDict.getRaw('First'); + if (isRef(obj) && !processed.has(obj)) { + queue.push({obj: obj, parent: outlineItem}); + processed.put(obj); + } + obj = outlineDict.getRaw('Next'); + if (isRef(obj) && !processed.has(obj)) { + queue.push({obj: obj, parent: i.parent}); + processed.put(obj); + } + } + } + } + return root.items.length > 0 ? root.items : null; + }, + get numPages() { + var obj = this.toplevelPagesDict.get('Count'); + assertWellFormed( + isInt(obj), + 'page count in top level pages object is not an integer' + ); + // shadow the prototype getter + return shadow(this, 'num', obj); + }, + get destinations() { + function fetchDestination(dest) { + return isDict(dest) ? dest.get('D') : dest; + } + + var xref = this.xref; + var dests = {}, nameTreeRef, nameDictionaryRef; + var obj = this.catDict.get('Names'); + if (obj) + nameTreeRef = obj.getRaw('Dests'); + else if (this.catDict.has('Dests')) + nameDictionaryRef = this.catDict.get('Dests'); + + if (nameDictionaryRef) { + // reading simple destination dictionary + obj = nameDictionaryRef; + obj.forEach(function catalogForEach(key, value) { + if (!value) return; + dests[key] = fetchDestination(value); + }); + } + if (nameTreeRef) { + var nameTree = new NameTree(nameTreeRef, xref); + var names = nameTree.getAll(); + for (var name in names) { + if (!names.hasOwnProperty(name)) { + continue; + } + dests[name] = fetchDestination(names[name]); + } + } + return shadow(this, 'destinations', dests); + }, + get javaScript() { + var xref = this.xref; + var obj = this.catDict.get('Names'); + + var javaScript = []; + if (obj && obj.has('JavaScript')) { + var nameTree = new NameTree(obj.getRaw('JavaScript'), xref); + var names = nameTree.getAll(); + for (var name in names) { + if (!names.hasOwnProperty(name)) { + continue; + } + // We don't really use the JavaScript right now so this code is + // defensive so we don't cause errors on document load. + var jsDict = names[name]; + if (!isDict(jsDict)) { + continue; + } + var type = jsDict.get('S'); + if (!isName(type) || type.name !== 'JavaScript') { + continue; + } + var js = jsDict.get('JS'); + if (!isString(js) && !isStream(js)) { + continue; + } + if (isStream(js)) { + js = bytesToString(js.getBytes()); + } + javaScript.push(stringToPDFString(js)); + } + } + return shadow(this, 'javaScript', javaScript); + }, + + cleanup: function Catalog_cleanup() { + this.fontCache.forEach(function (font) { + delete font.sent; + delete font.translated; + }); + this.fontCache.clear(); + }, + + getPage: function Catalog_getPage(pageIndex) { + if (!(pageIndex in this.pagePromises)) { + this.pagePromises[pageIndex] = this.getPageDict(pageIndex).then( + function (a) { + var dict = a[0]; + var ref = a[1]; + return new Page(this.pdfManager, this.xref, pageIndex, dict, ref, + this.fontCache); + }.bind(this) + ); + } + return this.pagePromises[pageIndex]; + }, + + getPageDict: function Catalog_getPageDict(pageIndex) { + var promise = new LegacyPromise(); + var nodesToVisit = [this.catDict.getRaw('Pages')]; + var currentPageIndex = 0; + var xref = this.xref; + + function next() { + while (nodesToVisit.length) { + var currentNode = nodesToVisit.pop(); + + if (isRef(currentNode)) { + xref.fetchAsync(currentNode).then(function (obj) { + if ((isDict(obj, 'Page') || (isDict(obj) && !obj.has('Kids')))) { + if (pageIndex === currentPageIndex) { + promise.resolve([obj, currentNode]); + } else { + currentPageIndex++; + next(); + } + return; + } + nodesToVisit.push(obj); + next(); + }.bind(this), promise.reject.bind(promise)); + return; + } + + // must be a child page dictionary + assert( + isDict(currentNode), + 'page dictionary kid reference points to wrong type of object' + ); + var count = currentNode.get('Count'); + // Skip nodes where the page can't be. + if (currentPageIndex + count <= pageIndex) { + currentPageIndex += count; + continue; + } + + var kids = currentNode.get('Kids'); + assert(isArray(kids), 'page dictionary kids object is not an array'); + if (count === kids.length) { + // Nodes that don't have the page have been skipped and this is the + // bottom of the tree which means the page requested must be a + // descendant of this pages node. Ideally we would just resolve the + // promise with the page ref here, but there is the case where more + // pages nodes could link to single a page (see issue 3666 pdf). To + // handle this push it back on the queue so if it is a pages node it + // will be descended into. + nodesToVisit = [kids[pageIndex - currentPageIndex]]; + currentPageIndex = pageIndex; + continue; + } else { + for (var last = kids.length - 1; last >= 0; last--) { + nodesToVisit.push(kids[last]); + } + } + } + promise.reject('Page index ' + pageIndex + ' not found.'); + } + next(); + return promise; + }, + + getPageIndex: function Catalog_getPageIndex(ref) { + // The page tree nodes have the count of all the leaves below them. To get + // how many pages are before we just have to walk up the tree and keep + // adding the count of siblings to the left of the node. + var xref = this.xref; + function pagesBeforeRef(kidRef) { + var total = 0; + var parentRef; + return xref.fetchAsync(kidRef).then(function (node) { + if (!node) { + return null; + } + parentRef = node.getRaw('Parent'); + return node.getAsync('Parent'); + }).then(function (parent) { + if (!parent) { + return null; + } + return parent.getAsync('Kids'); + }).then(function (kids) { + if (!kids) { + return null; + } + var kidPromises = []; + var found = false; + for (var i = 0; i < kids.length; i++) { + var kid = kids[i]; + assert(isRef(kid), 'kids must be an ref'); + if (kid.num == kidRef.num) { + found = true; + break; + } + kidPromises.push(xref.fetchAsync(kid).then(function (kid) { + if (kid.has('Count')) { + var count = kid.get('Count'); + total += count; + } else { // page leaf node + total++; + } + })); + } + if (!found) { + error('kid ref not found in parents kids'); + } + return Promise.all(kidPromises).then(function () { + return [total, parentRef]; + }); + }); + } + + var total = 0; + function next(ref) { + return pagesBeforeRef(ref).then(function (args) { + if (!args) { + return total; + } + var count = args[0]; + var parentRef = args[1]; + total += count; + return next(parentRef); + }); + } + + return next(ref); + } + }; + + return Catalog; +})(); + +var XRef = (function XRefClosure() { + function XRef(stream, password) { + + this.stream = stream; + this.entries = []; + this.xrefstms = {}; + // prepare the XRef cache + this.cache = []; + this.password = password; + } + + XRef.prototype = { + setStartXRef: function XRef_setStartXRef(startXRef) { + // Store the starting positions of xref tables as we process them + // so we can recover from missing data errors + this.startXRefQueue = [startXRef]; + }, + + parse: function XRef_parse(recoveryMode) { + var trailerDict; + if (!recoveryMode) { + trailerDict = this.readXRef(); + } else { + warn('Indexing all PDF objects'); + trailerDict = this.indexObjects(); + } + trailerDict.assignXref(this); + this.trailer = trailerDict; + var encrypt = trailerDict.get('Encrypt'); + if (encrypt) { + var ids = trailerDict.get('ID'); + var fileId = (ids && ids.length) ? ids[0] : ''; + this.encrypt = new CipherTransformFactory( + encrypt, fileId, this.password); + } + + // get the root dictionary (catalog) object + if (!(this.root = trailerDict.get('Root'))) { + error('Invalid root reference'); + } + }, + + processXRefTable: function XRef_processXRefTable(parser) { + if (!('tableState' in this)) { + // Stores state of the table as we process it so we can resume + // from middle of table in case of missing data error + this.tableState = { + entryNum: 0, + streamPos: parser.lexer.stream.pos, + parserBuf1: parser.buf1, + parserBuf2: parser.buf2 + }; + } + + var obj = this.readXRefTable(parser); + + // Sanity check + if (!isCmd(obj, 'trailer')) + error('Invalid XRef table: could not find trailer dictionary'); + + // Read trailer dictionary, e.g. + // trailer + // << /Size 22 + // /Root 20R + // /Info 10R + // /ID [ <81b14aafa313db63dbd6f981e49f94f4> ] + // >> + // The parser goes through the entire stream << ... >> and provides + // a getter interface for the key-value table + var dict = parser.getObj(); + if (!isDict(dict)) + error('Invalid XRef table: could not parse trailer dictionary'); + + delete this.tableState; + + return dict; + }, + + readXRefTable: function XRef_readXRefTable(parser) { + // Example of cross-reference table: + // xref + // 0 1 <-- subsection header (first obj #, obj count) + // 0000000000 65535 f <-- actual object (offset, generation #, f/n) + // 23 2 <-- subsection header ... and so on ... + // 0000025518 00002 n + // 0000025635 00000 n + // trailer + // ... + + var stream = parser.lexer.stream; + var tableState = this.tableState; + stream.pos = tableState.streamPos; + parser.buf1 = tableState.parserBuf1; + parser.buf2 = tableState.parserBuf2; + + // Outer loop is over subsection headers + var obj; + + while (true) { + if (!('firstEntryNum' in tableState) || !('entryCount' in tableState)) { + if (isCmd(obj = parser.getObj(), 'trailer')) { + break; + } + tableState.firstEntryNum = obj; + tableState.entryCount = parser.getObj(); + } + + var first = tableState.firstEntryNum; + var count = tableState.entryCount; + if (!isInt(first) || !isInt(count)) + error('Invalid XRef table: wrong types in subsection header'); + + // Inner loop is over objects themselves + for (var i = tableState.entryNum; i < count; i++) { + tableState.streamPos = stream.pos; + tableState.entryNum = i; + tableState.parserBuf1 = parser.buf1; + tableState.parserBuf2 = parser.buf2; + + var entry = {}; + entry.offset = parser.getObj(); + entry.gen = parser.getObj(); + var type = parser.getObj(); + + if (isCmd(type, 'f')) + entry.free = true; + else if (isCmd(type, 'n')) + entry.uncompressed = true; + + // Validate entry obj + if (!isInt(entry.offset) || !isInt(entry.gen) || + !(entry.free || entry.uncompressed)) { + console.log(entry.offset, entry.gen, entry.free, + entry.uncompressed); + error('Invalid entry in XRef subsection: ' + first + ', ' + count); + } + + if (!this.entries[i + first]) + this.entries[i + first] = entry; + } + + tableState.entryNum = 0; + tableState.streamPos = stream.pos; + tableState.parserBuf1 = parser.buf1; + tableState.parserBuf2 = parser.buf2; + delete tableState.firstEntryNum; + delete tableState.entryCount; + } + + // Per issue 3248: hp scanners generate bad XRef + if (first === 1 && this.entries[1] && this.entries[1].free) { + // shifting the entries + this.entries.shift(); + } + + // Sanity check: as per spec, first object must be free + if (this.entries[0] && !this.entries[0].free) + error('Invalid XRef table: unexpected first object'); + + return obj; + }, + + processXRefStream: function XRef_processXRefStream(stream) { + if (!('streamState' in this)) { + // Stores state of the stream as we process it so we can resume + // from middle of stream in case of missing data error + var streamParameters = stream.dict; + var byteWidths = streamParameters.get('W'); + var range = streamParameters.get('Index'); + if (!range) { + range = [0, streamParameters.get('Size')]; + } + + this.streamState = { + entryRanges: range, + byteWidths: byteWidths, + entryNum: 0, + streamPos: stream.pos + }; + } + this.readXRefStream(stream); + delete this.streamState; + + return stream.dict; + }, + + readXRefStream: function XRef_readXRefStream(stream) { + var i, j; + var streamState = this.streamState; + stream.pos = streamState.streamPos; + + var byteWidths = streamState.byteWidths; + var typeFieldWidth = byteWidths[0]; + var offsetFieldWidth = byteWidths[1]; + var generationFieldWidth = byteWidths[2]; + + var entryRanges = streamState.entryRanges; + while (entryRanges.length > 0) { + + var first = entryRanges[0]; + var n = entryRanges[1]; + + if (!isInt(first) || !isInt(n)) + error('Invalid XRef range fields: ' + first + ', ' + n); + + if (!isInt(typeFieldWidth) || !isInt(offsetFieldWidth) || + !isInt(generationFieldWidth)) { + error('Invalid XRef entry fields length: ' + first + ', ' + n); + } + for (i = streamState.entryNum; i < n; ++i) { + streamState.entryNum = i; + streamState.streamPos = stream.pos; + + var type = 0, offset = 0, generation = 0; + for (j = 0; j < typeFieldWidth; ++j) + type = (type << 8) | stream.getByte(); + // if type field is absent, its default value = 1 + if (typeFieldWidth === 0) + type = 1; + for (j = 0; j < offsetFieldWidth; ++j) + offset = (offset << 8) | stream.getByte(); + for (j = 0; j < generationFieldWidth; ++j) + generation = (generation << 8) | stream.getByte(); + var entry = {}; + entry.offset = offset; + entry.gen = generation; + switch (type) { + case 0: + entry.free = true; + break; + case 1: + entry.uncompressed = true; + break; + case 2: + break; + default: + error('Invalid XRef entry type: ' + type); + } + if (!this.entries[first + i]) + this.entries[first + i] = entry; + } + + streamState.entryNum = 0; + streamState.streamPos = stream.pos; + entryRanges.splice(0, 2); + } + }, + indexObjects: function XRef_indexObjects() { + // Simple scan through the PDF content to find objects, + // trailers and XRef streams. + function readToken(data, offset) { + var token = '', ch = data[offset]; + while (ch !== 13 && ch !== 10) { + if (++offset >= data.length) + break; + token += String.fromCharCode(ch); + ch = data[offset]; + } + return token; + } + function skipUntil(data, offset, what) { + var length = what.length, dataLength = data.length; + var skipped = 0; + // finding byte sequence + while (offset < dataLength) { + var i = 0; + while (i < length && data[offset + i] == what[i]) + ++i; + if (i >= length) + break; // sequence found + + offset++; + skipped++; + } + return skipped; + } + var trailerBytes = new Uint8Array([116, 114, 97, 105, 108, 101, 114]); + var startxrefBytes = new Uint8Array([115, 116, 97, 114, 116, 120, 114, + 101, 102]); + var endobjBytes = new Uint8Array([101, 110, 100, 111, 98, 106]); + var xrefBytes = new Uint8Array([47, 88, 82, 101, 102]); + + var stream = this.stream; + stream.pos = 0; + var buffer = stream.getBytes(); + var position = stream.start, length = buffer.length; + var trailers = [], xrefStms = []; + var state = 0; + var currentToken; + while (position < length) { + var ch = buffer[position]; + if (ch === 32 || ch === 9 || ch === 13 || ch === 10) { + ++position; + continue; + } + if (ch === 37) { // %-comment + do { + ++position; + if (position >= length) { + break; + } + ch = buffer[position]; + } while (ch !== 13 && ch !== 10); + continue; + } + var token = readToken(buffer, position); + var m; + if (token === 'xref') { + position += skipUntil(buffer, position, trailerBytes); + trailers.push(position); + position += skipUntil(buffer, position, startxrefBytes); + } else if ((m = /^(\d+)\s+(\d+)\s+obj\b/.exec(token))) { + this.entries[m[1]] = { + offset: position, + gen: m[2] | 0, + uncompressed: true + }; + + var contentLength = skipUntil(buffer, position, endobjBytes) + 7; + var content = buffer.subarray(position, position + contentLength); + + // checking XRef stream suspect + // (it shall have '/XRef' and next char is not a letter) + var xrefTagOffset = skipUntil(content, 0, xrefBytes); + if (xrefTagOffset < contentLength && + content[xrefTagOffset + 5] < 64) { + xrefStms.push(position); + this.xrefstms[position] = 1; // don't read it recursively + } + + position += contentLength; + } else + position += token.length + 1; + } + // reading XRef streams + for (var 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) { + stream.pos = trailers[i]; + var parser = new Parser(new Lexer(stream), true, null); + var obj = parser.getObj(); + if (!isCmd(obj, 'trailer')) + continue; + // read the trailer dictionary + if (!isDict(dict = parser.getObj())) + continue; + // taking the first one with 'ID' + if (dict.has('ID')) + return dict; + } + // no tailer with 'ID', taking last one (if exists) + if (dict) + return dict; + // nothing helps + // calling error() would reject worker with an UnknownErrorException. + throw new InvalidPDFException('Invalid PDF structure'); + }, + + readXRef: function XRef_readXRef(recoveryMode) { + var stream = this.stream; + + try { + while (this.startXRefQueue.length) { + var startXRef = this.startXRefQueue[0]; + + stream.pos = startXRef; + + var parser = new Parser(new Lexer(stream), true, null); + var obj = parser.getObj(); + var dict; + + // Get dictionary + if (isCmd(obj, 'xref')) { + + // Parse end-of-file XRef + dict = this.processXRefTable(parser); + if (!this.topDict) { + this.topDict = dict; + } + + // Recursively get other XRefs 'XRefStm', if any + obj = dict.get('XRefStm'); + if (isInt(obj)) { + var pos = obj; + // ignore previously loaded xref streams + // (possible infinite recursion) + if (!(pos in this.xrefstms)) { + this.xrefstms[pos] = 1; + this.startXRefQueue.push(pos); + } + } + } else if (isInt(obj)) { + + // Parse in-stream XRef + if (!isInt(parser.getObj()) || + !isCmd(parser.getObj(), 'obj') || + !isStream(obj = parser.getObj())) { + error('Invalid XRef stream'); + } + dict = this.processXRefStream(obj); + if (!this.topDict) { + this.topDict = dict; + } + + if (!dict) + error('Failed to read XRef stream'); + } else { + error('Invalid XRef stream header'); + } + + // Recursively get previous dictionary, if any + obj = dict.get('Prev'); + if (isInt(obj)) { + this.startXRefQueue.push(obj); + } else if (isRef(obj)) { + // The spec says Prev must not be a reference, i.e. "/Prev NNN" + // This is a fallback for non-compliant PDFs, i.e. "/Prev NNN 0 R" + this.startXRefQueue.push(obj.num); + } + + this.startXRefQueue.shift(); + } + + return this.topDict; + } catch (e) { + if (e instanceof MissingDataException) { + throw e; + } + info('(while reading XRef): ' + e); + } + + if (recoveryMode) + return; + throw new XRefParseException(); + }, + + getEntry: function XRef_getEntry(i) { + var e = this.entries[i]; + if (e === null) + return null; + return e.free || !e.offset ? null : e; // returns null if entry is free + }, + fetchIfRef: function XRef_fetchIfRef(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'); + 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; + } + + e = 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; + } + + // compressed entry + var tableOffset = e.offset; + 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); + parser.allowStreams = true; + var i, entries = [], nums = []; + // read the object numbers to populate cache + for (i = 0; i < n; ++i) { + num = parser.getObj(); + if (!isInt(num)) { + error('invalid object number in the ObjStm stream: ' + num); + } + nums.push(num); + var offset = parser.getObj(); + if (!isInt(offset)) { + error('invalid object offset in the ObjStm stream: ' + offset); + } + } + // read stream objects for cache + for (i = 0; i < n; ++i) { + entries.push(parser.getObj()); + num = nums[i]; + var entry = this.entries[num]; + if (entry && entry.offset === tableOffset && entry.gen === i) { + this.cache[num] = entries[i]; + } + } + e = entries[e.gen]; + if (e === undefined) { + error('bad XRef entry for compressed object'); + } + return e; + }, + fetchIfRefAsync: function XRef_fetchIfRefAsync(obj) { + if (!isRef(obj)) { + var promise = new LegacyPromise(); + promise.resolve(obj); + return promise; + } + return this.fetchAsync(obj); + }, + fetchAsync: function XRef_fetchAsync(ref, suppressEncryption) { + var promise = new LegacyPromise(); + var tryFetch = function (promise) { + try { + promise.resolve(this.fetch(ref, suppressEncryption)); + } catch (e) { + if (e instanceof MissingDataException) { + this.stream.manager.requestRange(e.begin, e.end, tryFetch); + return; + } + promise.reject(e); + } + }.bind(this, promise); + tryFetch(); + return promise; + }, + getCatalogObj: function XRef_getCatalogObj() { + return this.root; + } + }; + + return XRef; +})(); + +/** + * A NameTree is like a Dict but has some adventagous properties, see the spec + * (7.9.6) for more details. + * TODO: implement all the Dict functions and make this more efficent. + */ +var NameTree = (function NameTreeClosure() { + function NameTree(root, xref) { + this.root = root; + this.xref = xref; + } + + NameTree.prototype = { + getAll: function NameTree_getAll() { + var dict = {}; + if (!this.root) { + return dict; + } + var xref = this.xref; + // reading name tree + var processed = new RefSet(); + processed.put(this.root); + var queue = [this.root]; + while (queue.length > 0) { + var i, n; + var obj = xref.fetchIfRef(queue.shift()); + if (!isDict(obj)) { + continue; + } + if (obj.has('Kids')) { + var kids = obj.get('Kids'); + for (i = 0, n = kids.length; i < n; i++) { + var kid = kids[i]; + if (processed.has(kid)) + error('invalid destinations'); + queue.push(kid); + processed.put(kid); + } + continue; + } + var names = obj.get('Names'); + if (names) { + for (i = 0, n = names.length; i < n; i += 2) { + dict[names[i]] = xref.fetchIfRef(names[i + 1]); + } + } + } + return dict; + } + }; + return NameTree; +})(); + +/** + * A helper for loading missing data in object graphs. It traverses the graph + * depth first and queues up any objects that have missing data. Once it has + * has traversed as many objects that are available it attempts to bundle the + * missing data requests and then resume from the nodes that weren't ready. + * + * NOTE: It provides protection from circular references by keeping track of + * of loaded references. However, you must be careful not to load any graphs + * that have references to the catalog or other pages since that will cause the + * entire PDF document object graph to be traversed. + */ +var ObjectLoader = (function() { + + function mayHaveChildren(value) { + return isRef(value) || isDict(value) || isArray(value) || isStream(value); + } + + function addChildren(node, nodesToVisit) { + if (isDict(node) || isStream(node)) { + var map; + if (isDict(node)) { + map = node.map; + } else { + map = node.dict.map; + } + for (var key in map) { + var 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]; + if (mayHaveChildren(value)) { + nodesToVisit.push(value); + } + } + } + } + + function ObjectLoader(obj, keys, xref) { + this.obj = obj; + this.keys = keys; + this.xref = xref; + this.refSet = null; + } + + ObjectLoader.prototype = { + + load: function ObjectLoader_load() { + var keys = this.keys; + this.promise = new LegacyPromise(); + // 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.refSet = new RefSet(); + // Setup the initial nodes to visit. + var nodesToVisit = []; + for (var i = 0; i < keys.length; i++) { + nodesToVisit.push(this.obj[keys[i]]); + } + + this.walk(nodesToVisit); + return this.promise; + }, + + walk: function ObjectLoader_walk(nodesToVisit) { + var nodesToRevisit = []; + var pendingRequests = []; + // DFS walk of the object graph. + while (nodesToVisit.length) { + var currentNode = nodesToVisit.pop(); + + // Only references or chunked streams can cause missing data exceptions. + if (isRef(currentNode)) { + // Skip nodes that have already been visited. + if (this.refSet.has(currentNode)) { + continue; + } + try { + var ref = currentNode; + this.refSet.put(ref); + currentNode = this.xref.fetch(currentNode); + } catch (e) { + if (!(e instanceof MissingDataException)) { + throw e; + } + nodesToRevisit.push(currentNode); + pendingRequests.push({ begin: e.begin, end: e.end }); + } + } + if (currentNode && currentNode.getBaseStreams) { + var baseStreams = currentNode.getBaseStreams(); + var foundMissingData = false; + for (var i = 0; i < baseStreams.length; i++) { + var stream = baseStreams[i]; + if (stream.getMissingChunks && stream.getMissingChunks().length) { + foundMissingData = true; + pendingRequests.push({ + begin: stream.start, + end: stream.end + }); + } + } + if (foundMissingData) { + nodesToRevisit.push(currentNode); + } + } + + addChildren(currentNode, nodesToVisit); + } + + if (pendingRequests.length) { + this.xref.stream.manager.requestRanges(pendingRequests, + function pendingRequestCallback() { + nodesToVisit = nodesToRevisit; + for (var i = 0; i < nodesToRevisit.length; i++) { + var node = nodesToRevisit[i]; + // Remove any reference nodes from the currrent refset so they + // aren't skipped when we revist them. + if (isRef(node)) { + this.refSet.remove(node); + } + } + this.walk(nodesToVisit); + }.bind(this)); + return; + } + // Everything is loaded. + this.refSet = null; + this.promise.resolve(); + } + + }; + + return ObjectLoader; +})(); + + + + +var ISOAdobeCharset = [ + '.notdef', 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', + 'percent', 'ampersand', 'quoteright', 'parenleft', 'parenright', + 'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash', 'zero', + 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', + 'nine', 'colon', 'semicolon', 'less', 'equal', 'greater', 'question', + 'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', + 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', + 'bracketleft', 'backslash', 'bracketright', 'asciicircum', 'underscore', + 'quoteleft', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', + 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', + 'braceleft', 'bar', 'braceright', 'asciitilde', 'exclamdown', 'cent', + 'sterling', 'fraction', 'yen', 'florin', 'section', 'currency', + 'quotesingle', 'quotedblleft', 'guillemotleft', 'guilsinglleft', + 'guilsinglright', 'fi', 'fl', 'endash', 'dagger', 'daggerdbl', + 'periodcentered', 'paragraph', 'bullet', 'quotesinglbase', + 'quotedblbase', 'quotedblright', 'guillemotright', 'ellipsis', + 'perthousand', 'questiondown', 'grave', 'acute', 'circumflex', 'tilde', + 'macron', 'breve', 'dotaccent', 'dieresis', 'ring', 'cedilla', + 'hungarumlaut', 'ogonek', 'caron', 'emdash', 'AE', 'ordfeminine', + 'Lslash', 'Oslash', 'OE', 'ordmasculine', 'ae', 'dotlessi', 'lslash', + 'oslash', 'oe', 'germandbls', 'onesuperior', 'logicalnot', 'mu', + 'trademark', 'Eth', 'onehalf', 'plusminus', 'Thorn', 'onequarter', + 'divide', 'brokenbar', 'degree', 'thorn', 'threequarters', 'twosuperior', + 'registered', 'minus', 'eth', 'multiply', 'threesuperior', 'copyright', + 'Aacute', 'Acircumflex', 'Adieresis', 'Agrave', 'Aring', 'Atilde', + 'Ccedilla', 'Eacute', 'Ecircumflex', 'Edieresis', 'Egrave', 'Iacute', + 'Icircumflex', 'Idieresis', 'Igrave', 'Ntilde', 'Oacute', 'Ocircumflex', + 'Odieresis', 'Ograve', 'Otilde', 'Scaron', 'Uacute', 'Ucircumflex', + 'Udieresis', 'Ugrave', 'Yacute', 'Ydieresis', 'Zcaron', 'aacute', + 'acircumflex', 'adieresis', 'agrave', 'aring', 'atilde', 'ccedilla', + 'eacute', 'ecircumflex', 'edieresis', 'egrave', 'iacute', 'icircumflex', + 'idieresis', 'igrave', 'ntilde', 'oacute', 'ocircumflex', 'odieresis', + 'ograve', 'otilde', 'scaron', 'uacute', 'ucircumflex', 'udieresis', + 'ugrave', 'yacute', 'ydieresis', 'zcaron' +]; + +var ExpertCharset = [ + '.notdef', 'space', 'exclamsmall', 'Hungarumlautsmall', 'dollaroldstyle', + 'dollarsuperior', 'ampersandsmall', 'Acutesmall', 'parenleftsuperior', + 'parenrightsuperior', 'twodotenleader', 'onedotenleader', 'comma', + 'hyphen', 'period', 'fraction', 'zerooldstyle', 'oneoldstyle', + 'twooldstyle', 'threeoldstyle', 'fouroldstyle', 'fiveoldstyle', + 'sixoldstyle', 'sevenoldstyle', 'eightoldstyle', 'nineoldstyle', + 'colon', 'semicolon', 'commasuperior', 'threequartersemdash', + 'periodsuperior', 'questionsmall', 'asuperior', 'bsuperior', + 'centsuperior', 'dsuperior', 'esuperior', 'isuperior', 'lsuperior', + 'msuperior', 'nsuperior', 'osuperior', 'rsuperior', 'ssuperior', + 'tsuperior', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'parenleftinferior', + 'parenrightinferior', 'Circumflexsmall', 'hyphensuperior', 'Gravesmall', + 'Asmall', 'Bsmall', 'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall', + 'Hsmall', 'Ismall', 'Jsmall', 'Ksmall', 'Lsmall', 'Msmall', 'Nsmall', + 'Osmall', 'Psmall', 'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall', + 'Vsmall', 'Wsmall', 'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary', + 'onefitted', 'rupiah', 'Tildesmall', 'exclamdownsmall', 'centoldstyle', + 'Lslashsmall', 'Scaronsmall', 'Zcaronsmall', 'Dieresissmall', + 'Brevesmall', 'Caronsmall', 'Dotaccentsmall', 'Macronsmall', + 'figuredash', 'hypheninferior', 'Ogoneksmall', 'Ringsmall', + 'Cedillasmall', 'onequarter', 'onehalf', 'threequarters', + 'questiondownsmall', 'oneeighth', 'threeeighths', 'fiveeighths', + 'seveneighths', 'onethird', 'twothirds', 'zerosuperior', 'onesuperior', + 'twosuperior', 'threesuperior', 'foursuperior', 'fivesuperior', + 'sixsuperior', 'sevensuperior', 'eightsuperior', 'ninesuperior', + 'zeroinferior', 'oneinferior', 'twoinferior', 'threeinferior', + 'fourinferior', 'fiveinferior', 'sixinferior', 'seveninferior', + 'eightinferior', 'nineinferior', 'centinferior', 'dollarinferior', + 'periodinferior', 'commainferior', 'Agravesmall', 'Aacutesmall', + 'Acircumflexsmall', 'Atildesmall', 'Adieresissmall', 'Aringsmall', + 'AEsmall', 'Ccedillasmall', 'Egravesmall', 'Eacutesmall', + 'Ecircumflexsmall', 'Edieresissmall', 'Igravesmall', 'Iacutesmall', + 'Icircumflexsmall', 'Idieresissmall', 'Ethsmall', 'Ntildesmall', + 'Ogravesmall', 'Oacutesmall', 'Ocircumflexsmall', 'Otildesmall', + 'Odieresissmall', 'OEsmall', 'Oslashsmall', 'Ugravesmall', 'Uacutesmall', + 'Ucircumflexsmall', 'Udieresissmall', 'Yacutesmall', 'Thornsmall', + 'Ydieresissmall' +]; + +var ExpertSubsetCharset = [ + '.notdef', 'space', 'dollaroldstyle', 'dollarsuperior', + 'parenleftsuperior', 'parenrightsuperior', 'twodotenleader', + 'onedotenleader', 'comma', 'hyphen', 'period', 'fraction', + 'zerooldstyle', 'oneoldstyle', 'twooldstyle', 'threeoldstyle', + 'fouroldstyle', 'fiveoldstyle', 'sixoldstyle', 'sevenoldstyle', + 'eightoldstyle', 'nineoldstyle', 'colon', 'semicolon', 'commasuperior', + 'threequartersemdash', 'periodsuperior', 'asuperior', 'bsuperior', + 'centsuperior', 'dsuperior', 'esuperior', 'isuperior', 'lsuperior', + 'msuperior', 'nsuperior', 'osuperior', 'rsuperior', 'ssuperior', + 'tsuperior', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'parenleftinferior', + 'parenrightinferior', 'hyphensuperior', 'colonmonetary', 'onefitted', + 'rupiah', 'centoldstyle', 'figuredash', 'hypheninferior', 'onequarter', + 'onehalf', 'threequarters', 'oneeighth', 'threeeighths', 'fiveeighths', + 'seveneighths', 'onethird', 'twothirds', 'zerosuperior', 'onesuperior', + 'twosuperior', 'threesuperior', 'foursuperior', 'fivesuperior', + 'sixsuperior', 'sevensuperior', 'eightsuperior', 'ninesuperior', + 'zeroinferior', 'oneinferior', 'twoinferior', 'threeinferior', + 'fourinferior', 'fiveinferior', 'sixinferior', 'seveninferior', + 'eightinferior', 'nineinferior', 'centinferior', 'dollarinferior', + 'periodinferior', 'commainferior' +]; + + + +var 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 ARCFourCipher = (function ARCFourCipherClosure() { + function ARCFourCipher(key) { + this.a = 0; + this.b = 0; + var s = new Uint8Array(256); + var i, j = 0, tmp, keyLength = key.length; + for (i = 0; i < 256; ++i) + s[i] = i; + for (i = 0; i < 256; ++i) { + tmp = s[i]; + j = (j + tmp + key[i % keyLength]) & 0xFF; + s[i] = s[j]; + s[j] = tmp; + } + this.s = s; + } + + ARCFourCipher.prototype = { + encryptBlock: function ARCFourCipher_encryptBlock(data) { + var i, n = data.length, tmp, tmp2; + var a = this.a, b = this.b, s = this.s; + var output = new Uint8Array(n); + for (i = 0; i < n; ++i) { + a = (a + 1) & 0xFF; + tmp = s[a]; + b = (b + tmp) & 0xFF; + tmp2 = s[b]; + s[a] = tmp2; + s[b] = tmp; + output[i] = data[i] ^ s[(tmp + tmp2) & 0xFF]; + } + this.a = a; + this.b = b; + return output; + } + }; + ARCFourCipher.prototype.decryptBlock = ARCFourCipher.prototype.encryptBlock; + + return ARCFourCipher; +})(); + +var calculateMD5 = (function calculateMD5Closure() { + var r = new Uint8Array([ + 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, + 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, + 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, + 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21]); + + var k = new Int32Array([ + -680876936, -389564586, 606105819, -1044525330, -176418897, 1200080426, + -1473231341, -45705983, 1770035416, -1958414417, -42063, -1990404162, + 1804603682, -40341101, -1502002290, 1236535329, -165796510, -1069501632, + 643717713, -373897302, -701558691, 38016083, -660478335, -405537848, + 568446438, -1019803690, -187363961, 1163531501, -1444681467, -51403784, + 1735328473, -1926607734, -378558, -2022574463, 1839030562, -35309556, + -1530992060, 1272893353, -155497632, -1094730640, 681279174, -358537222, + -722521979, 76029189, -640364487, -421815835, 530742520, -995338651, + -198630844, 1126891415, -1416354905, -57434055, 1700485571, -1894986606, + -1051523, -2054922799, 1873313359, -30611744, -1560198380, 1309151649, + -145523070, -1120210379, 718787259, -343485551]); + + function hash(data, offset, length) { + var h0 = 1732584193, h1 = -271733879, h2 = -1732584194, h3 = 271733878; + // pre-processing + var paddedLength = (length + 72) & ~63; // data + 9 extra bytes + var padded = new Uint8Array(paddedLength); + var i, j, n; + for (i = 0; i < length; ++i) + padded[i] = data[offset++]; + padded[i++] = 0x80; + n = paddedLength - 8; + while (i < n) + padded[i++] = 0; + padded[i++] = (length << 3) & 0xFF; + padded[i++] = (length >> 5) & 0xFF; + padded[i++] = (length >> 13) & 0xFF; + padded[i++] = (length >> 21) & 0xFF; + padded[i++] = (length >>> 29) & 0xFF; + padded[i++] = 0; + padded[i++] = 0; + padded[i++] = 0; + // 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)); + } + var a = h0, b = h1, c = h2, d = h3, f, g; + for (j = 0; j < 64; ++j) { + if (j < 16) { + f = (b & c) | ((~b) & d); + g = j; + } else if (j < 32) { + f = (d & b) | ((~d) & c); + g = (5 * j + 1) & 15; + } else if (j < 48) { + f = b ^ c ^ d; + g = (3 * j + 5) & 15; + } else { + f = c ^ (b | (~d)); + g = (7 * j) & 15; + } + var tmp = d, rotateArg = (a + f + k[j] + w[g]) | 0, rotate = r[j]; + d = c; + c = b; + b = (b + ((rotateArg << rotate) | (rotateArg >>> (32 - rotate)))) | 0; + a = tmp; + } + h0 = (h0 + a) | 0; + h1 = (h1 + b) | 0; + h2 = (h2 + c) | 0; + h3 = (h3 + d) | 0; + } + return new Uint8Array([ + h0 & 0xFF, (h0 >> 8) & 0xFF, (h0 >> 16) & 0xFF, (h0 >>> 24) & 0xFF, + h1 & 0xFF, (h1 >> 8) & 0xFF, (h1 >> 16) & 0xFF, (h1 >>> 24) & 0xFF, + h2 & 0xFF, (h2 >> 8) & 0xFF, (h2 >> 16) & 0xFF, (h2 >>> 24) & 0xFF, + h3 & 0xFF, (h3 >> 8) & 0xFF, (h3 >> 16) & 0xFF, (h3 >>> 24) & 0xFF + ]); + } + return hash; +})(); + +var NullCipher = (function NullCipherClosure() { + function NullCipher() { + } + + NullCipher.prototype = { + decryptBlock: function NullCipher_decryptBlock(data) { + return data; + } + }; + + return NullCipher; +})(); + +var AES128Cipher = (function AES128CipherClosure() { + var rcon = new Uint8Array([ + 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, + 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, + 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, + 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, + 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, + 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, + 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, + 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, + 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, + 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, + 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, + 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, + 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, + 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, + 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, + 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, + 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, + 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, + 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, + 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, + 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, + 0x74, 0xe8, 0xcb, 0x8d]); + + var s = new Uint8Array([ + 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, + 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, + 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, + 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, + 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, + 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, + 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, + 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, + 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, + 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, + 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec, + 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, + 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, + 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, + 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, + 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, + 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, + 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, + 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, + 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, + 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, + 0xb0, 0x54, 0xbb, 0x16]); + + var inv_s = new Uint8Array([ + 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, + 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, + 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, + 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, + 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, + 0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, + 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, + 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, + 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, + 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, + 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41, + 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, + 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, + 0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, + 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, + 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, + 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, + 0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, + 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d, + 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, + 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, + 0x55, 0x21, 0x0c, 0x7d]); + + var mix = new Uint32Array([ + 0x00000000, 0x0e090d0b, 0x1c121a16, 0x121b171d, 0x3824342c, 0x362d3927, + 0x24362e3a, 0x2a3f2331, 0x70486858, 0x7e416553, 0x6c5a724e, 0x62537f45, + 0x486c5c74, 0x4665517f, 0x547e4662, 0x5a774b69, 0xe090d0b0, 0xee99ddbb, + 0xfc82caa6, 0xf28bc7ad, 0xd8b4e49c, 0xd6bde997, 0xc4a6fe8a, 0xcaaff381, + 0x90d8b8e8, 0x9ed1b5e3, 0x8ccaa2fe, 0x82c3aff5, 0xa8fc8cc4, 0xa6f581cf, + 0xb4ee96d2, 0xbae79bd9, 0xdb3bbb7b, 0xd532b670, 0xc729a16d, 0xc920ac66, + 0xe31f8f57, 0xed16825c, 0xff0d9541, 0xf104984a, 0xab73d323, 0xa57ade28, + 0xb761c935, 0xb968c43e, 0x9357e70f, 0x9d5eea04, 0x8f45fd19, 0x814cf012, + 0x3bab6bcb, 0x35a266c0, 0x27b971dd, 0x29b07cd6, 0x038f5fe7, 0x0d8652ec, + 0x1f9d45f1, 0x119448fa, 0x4be30393, 0x45ea0e98, 0x57f11985, 0x59f8148e, + 0x73c737bf, 0x7dce3ab4, 0x6fd52da9, 0x61dc20a2, 0xad766df6, 0xa37f60fd, + 0xb16477e0, 0xbf6d7aeb, 0x955259da, 0x9b5b54d1, 0x894043cc, 0x87494ec7, + 0xdd3e05ae, 0xd33708a5, 0xc12c1fb8, 0xcf2512b3, 0xe51a3182, 0xeb133c89, + 0xf9082b94, 0xf701269f, 0x4de6bd46, 0x43efb04d, 0x51f4a750, 0x5ffdaa5b, + 0x75c2896a, 0x7bcb8461, 0x69d0937c, 0x67d99e77, 0x3daed51e, 0x33a7d815, + 0x21bccf08, 0x2fb5c203, 0x058ae132, 0x0b83ec39, 0x1998fb24, 0x1791f62f, + 0x764dd68d, 0x7844db86, 0x6a5fcc9b, 0x6456c190, 0x4e69e2a1, 0x4060efaa, + 0x527bf8b7, 0x5c72f5bc, 0x0605bed5, 0x080cb3de, 0x1a17a4c3, 0x141ea9c8, + 0x3e218af9, 0x302887f2, 0x223390ef, 0x2c3a9de4, 0x96dd063d, 0x98d40b36, + 0x8acf1c2b, 0x84c61120, 0xaef93211, 0xa0f03f1a, 0xb2eb2807, 0xbce2250c, + 0xe6956e65, 0xe89c636e, 0xfa877473, 0xf48e7978, 0xdeb15a49, 0xd0b85742, + 0xc2a3405f, 0xccaa4d54, 0x41ecdaf7, 0x4fe5d7fc, 0x5dfec0e1, 0x53f7cdea, + 0x79c8eedb, 0x77c1e3d0, 0x65daf4cd, 0x6bd3f9c6, 0x31a4b2af, 0x3fadbfa4, + 0x2db6a8b9, 0x23bfa5b2, 0x09808683, 0x07898b88, 0x15929c95, 0x1b9b919e, + 0xa17c0a47, 0xaf75074c, 0xbd6e1051, 0xb3671d5a, 0x99583e6b, 0x97513360, + 0x854a247d, 0x8b432976, 0xd134621f, 0xdf3d6f14, 0xcd267809, 0xc32f7502, + 0xe9105633, 0xe7195b38, 0xf5024c25, 0xfb0b412e, 0x9ad7618c, 0x94de6c87, + 0x86c57b9a, 0x88cc7691, 0xa2f355a0, 0xacfa58ab, 0xbee14fb6, 0xb0e842bd, + 0xea9f09d4, 0xe49604df, 0xf68d13c2, 0xf8841ec9, 0xd2bb3df8, 0xdcb230f3, + 0xcea927ee, 0xc0a02ae5, 0x7a47b13c, 0x744ebc37, 0x6655ab2a, 0x685ca621, + 0x42638510, 0x4c6a881b, 0x5e719f06, 0x5078920d, 0x0a0fd964, 0x0406d46f, + 0x161dc372, 0x1814ce79, 0x322bed48, 0x3c22e043, 0x2e39f75e, 0x2030fa55, + 0xec9ab701, 0xe293ba0a, 0xf088ad17, 0xfe81a01c, 0xd4be832d, 0xdab78e26, + 0xc8ac993b, 0xc6a59430, 0x9cd2df59, 0x92dbd252, 0x80c0c54f, 0x8ec9c844, + 0xa4f6eb75, 0xaaffe67e, 0xb8e4f163, 0xb6edfc68, 0x0c0a67b1, 0x02036aba, + 0x10187da7, 0x1e1170ac, 0x342e539d, 0x3a275e96, 0x283c498b, 0x26354480, + 0x7c420fe9, 0x724b02e2, 0x605015ff, 0x6e5918f4, 0x44663bc5, 0x4a6f36ce, + 0x587421d3, 0x567d2cd8, 0x37a10c7a, 0x39a80171, 0x2bb3166c, 0x25ba1b67, + 0x0f853856, 0x018c355d, 0x13972240, 0x1d9e2f4b, 0x47e96422, 0x49e06929, + 0x5bfb7e34, 0x55f2733f, 0x7fcd500e, 0x71c45d05, 0x63df4a18, 0x6dd64713, + 0xd731dcca, 0xd938d1c1, 0xcb23c6dc, 0xc52acbd7, 0xef15e8e6, 0xe11ce5ed, + 0xf307f2f0, 0xfd0efffb, 0xa779b492, 0xa970b999, 0xbb6bae84, 0xb562a38f, + 0x9f5d80be, 0x91548db5, 0x834f9aa8, 0x8d4697a3]); + + function expandKey128(cipherKey) { + var b = 176, result = new Uint8Array(b); + result.set(cipherKey); + for (var j = 16, i = 1; j < b; ++i) { + // RotWord + var t1 = result[j - 3], t2 = result[j - 2], + t3 = result[j - 1], t4 = result[j - 4]; + // SubWord + t1 = s[t1]; t2 = s[t2]; t3 = s[t3]; t4 = s[t4]; + // Rcon + t1 = t1 ^ rcon[i]; + for (var n = 0; n < 4; ++n) { + result[j] = (t1 ^= result[j - 16]); j++; + result[j] = (t2 ^= result[j - 16]); j++; + result[j] = (t3 ^= result[j - 16]); j++; + result[j] = (t4 ^= result[j - 16]); j++; + } + } + return result; + } + + function decrypt128(input, key) { + var state = new Uint8Array(16); + state.set(input); + var i, j, k; + var t, u, v; + // AddRoundKey + for (j = 0, k = 160; j < 16; ++j, ++k) + state[j] ^= key[k]; + for (i = 9; i >= 1; --i) { + // InvShiftRows + t = state[13]; state[13] = state[9]; state[9] = state[5]; + state[5] = state[1]; state[1] = t; + t = state[14]; u = state[10]; state[14] = state[6]; + state[10] = state[2]; state[6] = t; state[2] = u; + t = state[15]; u = state[11]; v = state[7]; state[15] = state[3]; + state[11] = t; state[7] = u; state[3] = v; + // InvSubBytes + for (j = 0; j < 16; ++j) + state[j] = inv_s[state[j]]; + // AddRoundKey + for (j = 0, k = i * 16; j < 16; ++j, ++k) + state[j] ^= key[k]; + // InvMixColumns + for (j = 0; j < 16; j += 4) { + var s0 = mix[state[j]], s1 = mix[state[j + 1]], + s2 = mix[state[j + 2]], s3 = mix[state[j + 3]]; + t = (s0 ^ (s1 >>> 8) ^ (s1 << 24) ^ (s2 >>> 16) ^ (s2 << 16) ^ + (s3 >>> 24) ^ (s3 << 8)); + state[j] = (t >>> 24) & 0xFF; + state[j + 1] = (t >> 16) & 0xFF; + state[j + 2] = (t >> 8) & 0xFF; + state[j + 3] = t & 0xFF; + } + } + // InvShiftRows + t = state[13]; state[13] = state[9]; state[9] = state[5]; + state[5] = state[1]; state[1] = t; + t = state[14]; u = state[10]; state[14] = state[6]; + state[10] = state[2]; state[6] = t; state[2] = u; + t = state[15]; u = state[11]; v = state[7]; state[15] = state[3]; + state[11] = t; state[7] = u; state[3] = v; + for (j = 0; j < 16; ++j) { + // InvSubBytes + state[j] = inv_s[state[j]]; + // AddRoundKey + state[j] ^= key[j]; + } + return state; + } + + function AES128Cipher(key) { + this.key = expandKey128(key); + this.buffer = new Uint8Array(16); + this.bufferPosition = 0; + } + + function decryptBlock2(data, finalize) { + var i, j, ii, sourceLength = data.length, + buffer = this.buffer, bufferLength = this.bufferPosition, + result = [], iv = this.iv; + for (i = 0; i < sourceLength; ++i) { + buffer[bufferLength] = data[i]; + ++bufferLength; + if (bufferLength < 16) + continue; + // buffer is full, decrypting + var plain = decrypt128(buffer, this.key); + // xor-ing the IV vector to get plain text + for (j = 0; j < 16; ++j) + plain[j] ^= iv[j]; + iv = buffer; + result.push(plain); + buffer = new Uint8Array(16); + bufferLength = 0; + } + // saving incomplete buffer + this.buffer = buffer; + this.bufferLength = bufferLength; + this.iv = iv; + if (result.length === 0) { + return new Uint8Array([]); + } + // combining plain text blocks into one + var outputLength = 16 * result.length; + if (finalize) { + // undo a padding that is described in RFC 2898 + var lastBlock = result[result.length - 1]; + outputLength -= lastBlock[15]; + result[result.length - 1] = lastBlock.subarray(0, 16 - lastBlock[15]); + } + var output = new Uint8Array(outputLength); + for (i = 0, j = 0, ii = result.length; i < ii; ++i, j += 16) + output.set(result[i], j); + return output; + } + + AES128Cipher.prototype = { + decryptBlock: function AES128Cipher_decryptBlock(data, finalize) { + var i, sourceLength = data.length; + var buffer = this.buffer, bufferLength = this.bufferPosition; + // waiting for IV values -- they are at the start of the stream + for (i = 0; bufferLength < 16 && i < sourceLength; ++i, ++bufferLength) + buffer[bufferLength] = data[i]; + if (bufferLength < 16) { + // need more data + this.bufferLength = bufferLength; + return new Uint8Array([]); + } + this.iv = buffer; + this.buffer = new Uint8Array(16); + this.bufferLength = 0; + // starting decryption + this.decryptBlock = decryptBlock2; + return this.decryptBlock(data.subarray(16), finalize); + } + }; + + return AES128Cipher; +})(); + +var CipherTransform = (function CipherTransformClosure() { + function CipherTransform(stringCipherConstructor, streamCipherConstructor) { + this.stringCipherConstructor = stringCipherConstructor; + this.streamCipherConstructor = streamCipherConstructor; + } + CipherTransform.prototype = { + createStream: function CipherTransform_createStream(stream) { + var cipher = new this.streamCipherConstructor(); + return new DecryptStream(stream, + function cipherTransformDecryptStream(data, finalize) { + return cipher.decryptBlock(data, finalize); + } + ); + }, + decryptString: function CipherTransform_decryptString(s) { + var cipher = new this.stringCipherConstructor(); + var data = stringToBytes(s); + data = cipher.decryptBlock(data, true); + return bytesToString(data); + } + }; + return CipherTransform; +})(); + +var CipherTransformFactory = (function CipherTransformFactoryClosure() { + var defaultPasswordBytes = new Uint8Array([ + 0x28, 0xBF, 0x4E, 0x5E, 0x4E, 0x75, 0x8A, 0x41, + 0x64, 0x00, 0x4E, 0x56, 0xFF, 0xFA, 0x01, 0x08, + 0x2E, 0x2E, 0x00, 0xB6, 0xD0, 0x68, 0x3E, 0x80, + 0x2F, 0x0C, 0xA9, 0xFE, 0x64, 0x53, 0x69, 0x7A]); + + function prepareKeyData(fileId, password, ownerPassword, userPassword, + flags, revision, keyLength, encryptMetadata) { + var hashDataSize = 40 + ownerPassword.length + fileId.length; + var hashData = new Uint8Array(hashDataSize), i = 0, j, n; + if (password) { + n = Math.min(32, password.length); + for (; i < n; ++i) + hashData[i] = password[i]; + } + j = 0; + while (i < 32) { + hashData[i++] = defaultPasswordBytes[j++]; + } + // as now the padded password in the hashData[0..i] + for (j = 0, n = ownerPassword.length; j < n; ++j) + hashData[i++] = ownerPassword[j]; + hashData[i++] = flags & 0xFF; + hashData[i++] = (flags >> 8) & 0xFF; + hashData[i++] = (flags >> 16) & 0xFF; + hashData[i++] = (flags >>> 24) & 0xFF; + for (j = 0, n = fileId.length; j < n; ++j) + hashData[i++] = fileId[j]; + if (revision >= 4 && !encryptMetadata) { + hashData[i++] = 0xFF; + hashData[i++] = 0xFF; + hashData[i++] = 0xFF; + hashData[i++] = 0xFF; + } + var hash = calculateMD5(hashData, 0, i); + var keyLengthInBytes = keyLength >> 3; + if (revision >= 3) { + for (j = 0; j < 50; ++j) { + hash = calculateMD5(hash, 0, keyLengthInBytes); + } + } + var encryptionKey = hash.subarray(0, keyLengthInBytes); + var cipher, checkData; + + if (revision >= 3) { + for (i = 0; i < 32; ++i) + hashData[i] = defaultPasswordBytes[i]; + for (j = 0, n = fileId.length; j < n; ++j) + hashData[i++] = fileId[j]; + cipher = new ARCFourCipher(encryptionKey); + var checkData = cipher.encryptBlock(calculateMD5(hashData, 0, i)); + n = encryptionKey.length; + var derivedKey = new Uint8Array(n), k; + for (j = 1; j <= 19; ++j) { + for (k = 0; k < n; ++k) + derivedKey[k] = encryptionKey[k] ^ j; + cipher = new ARCFourCipher(derivedKey); + checkData = cipher.encryptBlock(checkData); + } + for (j = 0, n = checkData.length; j < n; ++j) { + if (userPassword[j] != checkData[j]) + return null; + } + } else { + cipher = new ARCFourCipher(encryptionKey); + checkData = cipher.encryptBlock(defaultPasswordBytes); + for (j = 0, n = checkData.length; j < n; ++j) { + if (userPassword[j] != checkData[j]) + return null; + } + } + return encryptionKey; + } + function decodeUserPassword(password, ownerPassword, revision, keyLength) { + var hashData = new Uint8Array(32), i = 0, j, n; + n = Math.min(32, password.length); + for (; i < n; ++i) + hashData[i] = password[i]; + j = 0; + while (i < 32) { + hashData[i++] = defaultPasswordBytes[j++]; + } + var hash = calculateMD5(hashData, 0, i); + var keyLengthInBytes = keyLength >> 3; + if (revision >= 3) { + for (j = 0; j < 50; ++j) { + hash = calculateMD5(hash, 0, hash.length); + } + } + + var cipher, userPassword; + if (revision >= 3) { + userPassword = ownerPassword; + var derivedKey = new Uint8Array(keyLengthInBytes), k; + for (j = 19; j >= 0; j--) { + for (k = 0; k < keyLengthInBytes; ++k) + derivedKey[k] = hash[k] ^ j; + cipher = new ARCFourCipher(derivedKey); + userPassword = cipher.encryptBlock(userPassword); + } + } else { + cipher = new ARCFourCipher(hash.subarray(0, keyLengthInBytes)); + userPassword = cipher.encryptBlock(ownerPassword); + } + return userPassword; + } + + var identityName = new Name('Identity'); + + function CipherTransformFactory(dict, fileId, password) { + var filter = dict.get('Filter'); + if (!isName(filter) || filter.name != 'Standard') + error('unknown encryption method'); + this.dict = dict; + var algorithm = dict.get('V'); + if (!isInt(algorithm) || + (algorithm != 1 && algorithm != 2 && algorithm != 4)) + error('unsupported encryption algorithm'); + this.algorithm = algorithm; + var keyLength = dict.get('Length') || 40; + if (!isInt(keyLength) || + keyLength < 40 || (keyLength % 8) !== 0) + error('invalid key length'); + // prepare keys + var ownerPassword = stringToBytes(dict.get('O')).subarray(0, 32); + var userPassword = stringToBytes(dict.get('U')).subarray(0, 32); + var flags = dict.get('P'); + var revision = dict.get('R'); + var encryptMetadata = algorithm == 4 && // meaningful when V is 4 + dict.get('EncryptMetadata') !== false; // makes true as default value + this.encryptMetadata = encryptMetadata; + + var fileIdBytes = stringToBytes(fileId); + var passwordBytes; + if (password) + passwordBytes = stringToBytes(password); + + var encryptionKey = prepareKeyData(fileIdBytes, passwordBytes, + ownerPassword, userPassword, flags, + revision, keyLength, encryptMetadata); + if (!encryptionKey && !password) { + throw new PasswordException('No password given', + PasswordResponses.NEED_PASSWORD); + } else if (!encryptionKey && password) { + // Attempting use the password as an owner password + var decodedPassword = decodeUserPassword(passwordBytes, ownerPassword, + revision, keyLength); + encryptionKey = prepareKeyData(fileIdBytes, decodedPassword, + ownerPassword, userPassword, flags, + revision, keyLength, encryptMetadata); + } + + if (!encryptionKey) + throw new PasswordException('Incorrect Password', + PasswordResponses.INCORRECT_PASSWORD); + + this.encryptionKey = encryptionKey; + + if (algorithm == 4) { + this.cf = dict.get('CF'); + this.stmf = dict.get('StmF') || identityName; + this.strf = dict.get('StrF') || identityName; + this.eff = dict.get('EFF') || this.strf; + } + } + + function buildObjectKey(num, gen, encryptionKey, isAes) { + var key = new Uint8Array(encryptionKey.length + 9), i, n; + for (i = 0, n = encryptionKey.length; i < n; ++i) + key[i] = encryptionKey[i]; + key[i++] = num & 0xFF; + key[i++] = (num >> 8) & 0xFF; + key[i++] = (num >> 16) & 0xFF; + key[i++] = gen & 0xFF; + key[i++] = (gen >> 8) & 0xFF; + if (isAes) { + key[i++] = 0x73; + key[i++] = 0x41; + key[i++] = 0x6C; + key[i++] = 0x54; + } + var hash = calculateMD5(key, 0, i); + return hash.subarray(0, Math.min(encryptionKey.length + 5, 16)); + } + + function buildCipherConstructor(cf, name, num, gen, key) { + var cryptFilter = cf.get(name.name); + var cfm; + if (cryptFilter !== null && cryptFilter !== undefined) + cfm = cryptFilter.get('CFM'); + if (!cfm || cfm.name == 'None') { + return function cipherTransformFactoryBuildCipherConstructorNone() { + return new NullCipher(); + }; + } + if ('V2' == cfm.name) { + return function cipherTransformFactoryBuildCipherConstructorV2() { + return new ARCFourCipher( + buildObjectKey(num, gen, key, false)); + }; + } + if ('AESV2' == cfm.name) { + return function cipherTransformFactoryBuildCipherConstructorAESV2() { + return new AES128Cipher( + buildObjectKey(num, gen, key, true)); + }; + } + error('Unknown crypto method'); + } + + CipherTransformFactory.prototype = { + createCipherTransform: + function CipherTransformFactory_createCipherTransform(num, gen) { + if (this.algorithm == 4) { + return new CipherTransform( + buildCipherConstructor(this.cf, this.stmf, + num, gen, this.encryptionKey), + buildCipherConstructor(this.cf, this.strf, + num, gen, this.encryptionKey)); + } + // algorithms 1 and 2 + var key = buildObjectKey(num, gen, this.encryptionKey, false); + var cipherConstructor = function buildCipherCipherConstructor() { + return new ARCFourCipher(key); + }; + return new CipherTransform(cipherConstructor, cipherConstructor); + } + }; + + return CipherTransformFactory; +})(); + + + +var PatternType = { + AXIAL: 2, + RADIAL: 3 +}; + +var Pattern = (function PatternClosure() { + // Constructor should define this.getPattern + function Pattern() { + error('should not call Pattern constructor'); + } + + Pattern.prototype = { + // Input: current Canvas context + // Output: the appropriate fillStyle or strokeStyle + getPattern: function Pattern_getPattern(ctx) { + error('Should not call Pattern.getStyle: ' + ctx); + } + }; + + Pattern.parseShading = function Pattern_parseShading(shading, matrix, xref, + res) { + + var dict = isStream(shading) ? shading.dict : shading; + var type = dict.get('ShadingType'); + + 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(); + } + }; + return Pattern; +})(); + +var Shadings = {}; + +// A small number to offset the first/last color stops so we can insert ones to +// support extend. Number.MIN_VALUE appears to be too small and breaks the +// extend. 1e-7 works in FF but chrome seems to use an even smaller sized number +// internally so we have to go bigger. +Shadings.SMALL_NUMBER = 1e-2; + +// Radial and axial shading have very similar implementations +// If needed, the implementations can be broken into two classes +Shadings.RadialAxial = (function RadialAxialClosure() { + function RadialAxial(dict, matrix, xref, res) { + this.matrix = matrix; + this.coordsArr = dict.get('Coords'); + this.shadingType = dict.get('ShadingType'); + this.type = 'Pattern'; + var cs = dict.get('ColorSpace', 'CS'); + cs = ColorSpace.parse(cs, xref, res); + this.cs = cs; + + var t0 = 0.0, t1 = 1.0; + if (dict.has('Domain')) { + var domainArr = dict.get('Domain'); + t0 = domainArr[0]; + t1 = domainArr[1]; + } + + var extendStart = false, extendEnd = false; + if (dict.has('Extend')) { + var extendArr = dict.get('Extend'); + extendStart = extendArr[0]; + extendEnd = extendArr[1]; + } + + if (this.shadingType === PatternType.RADIAL && + (!extendStart || !extendEnd)) { + // Radial gradient only currently works if either circle is fully within + // the other circle. + var x1 = this.coordsArr[0]; + var y1 = this.coordsArr[1]; + var r1 = this.coordsArr[2]; + var x2 = this.coordsArr[3]; + var y2 = this.coordsArr[4]; + var r2 = this.coordsArr[5]; + var distance = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)); + if (r1 <= r2 + distance && + r2 <= r1 + distance) { + warn('Unsupported radial gradient.'); + } + } + + this.extendStart = extendStart; + this.extendEnd = extendEnd; + + var fnObj = dict.get('Function'); + var fn; + 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); + } + + // 10 samples seems good enough for now, but probably won't work + // if there are sharp color changes. Ideally, we would implement + // the spec faithfully and add lossless optimizations. + var diff = t1 - t0; + var step = diff / 10; + + var colorStops = this.colorStops = []; + + // Protect against bad domains so we don't end up in an infinte loop below. + if (t0 >= t1 || step <= 0) { + // Acrobat doesn't seem to handle these cases so we'll ignore for + // now. + info('Bad shading domain.'); + return; + } + + for (var i = t0; i <= t1; i += step) { + var rgbColor = cs.getRgb(fn([i]), 0); + var cssColor = Util.makeCssRgb(rgbColor); + 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); + } + + if (!extendStart) { + // Insert a color stop at the front and offset the first real color stop + // so it doesn't conflict with the one we insert. + colorStops.unshift([0, background]); + colorStops[1][0] += Shadings.SMALL_NUMBER; + } + if (!extendEnd) { + // Same idea as above in extendStart but for the end. + colorStops[colorStops.length - 1][0] -= Shadings.SMALL_NUMBER; + colorStops.push([1, background]); + } + + this.colorStops = colorStops; + } + + RadialAxial.prototype = { + getIR: function RadialAxial_getIR() { + var coordsArr = this.coordsArr; + var shadingType = this.shadingType; + var type, p0, p1, r0, r1; + if (shadingType == PatternType.AXIAL) { + p0 = [coordsArr[0], coordsArr[1]]; + p1 = [coordsArr[2], coordsArr[3]]; + r0 = null; + r1 = null; + type = 'axial'; + } else if (shadingType == PatternType.RADIAL) { + p0 = [coordsArr[0], coordsArr[1]]; + p1 = [coordsArr[3], coordsArr[4]]; + r0 = coordsArr[2]; + r1 = coordsArr[5]; + type = 'radial'; + } else { + error('getPattern type unknown: ' + shadingType); + } + + var matrix = this.matrix; + if (matrix) { + p0 = Util.applyTransform(p0, matrix); + p1 = Util.applyTransform(p1, matrix); + } + + return ['RadialAxial', type, this.colorStops, p0, p1, r0, r1]; + } + }; + + return RadialAxial; +})(); + +Shadings.Dummy = (function DummyClosure() { + function Dummy() { + this.type = 'Pattern'; + } + + Dummy.prototype = { + getIR: function Dummy_getIR() { + return ['Dummy']; + } + }; + return Dummy; +})(); + +function getTilingPatternIR(operatorList, dict, args) { + var matrix = dict.get('Matrix'); + var bbox = dict.get('BBox'); + var xstep = dict.get('XStep'); + var ystep = dict.get('YStep'); + var paintType = dict.get('PaintType'); + var tilingType = dict.get('TilingType'); + + return [ + 'TilingPattern', args, operatorList, matrix, bbox, xstep, ystep, + paintType, tilingType + ]; +} + + +var PartialEvaluator = (function PartialEvaluatorClosure() { + function PartialEvaluator(pdfManager, xref, handler, pageIndex, + uniquePrefix, idCounters, fontCache) { + this.state = new EvalState(); + this.stateStack = []; + + this.pdfManager = pdfManager; + this.xref = xref; + this.handler = handler; + this.pageIndex = pageIndex; + this.uniquePrefix = uniquePrefix; + this.idCounters = idCounters; + this.fontCache = fontCache; + } + + var TILING_PATTERN = 1, SHADING_PATTERN = 2; + + PartialEvaluator.prototype = { + hasBlendModes: function PartialEvaluator_hasBlendModes(resources) { + if (!isDict(resources)) { + return false; + } + + var nodes = [resources]; + while (nodes.length) { + 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) { + var graphicState = graphicStates[key]; + var bm = graphicState['BM']; + if (isName(bm) && bm.name !== 'Normal') { + return true; + } + } + } + // Descend into the XObjects to look for more resources and blend modes. + var xObjects = node.get('XObject'); + if (!isDict(xObjects)) { + continue; + } + xObjects = xObjects.getAll(); + for (var key in xObjects) { + var xObject = xObjects[key]; + if (!isStream(xObject)) { + continue; + } + var xResources = xObject.dict.get('Resources'); + if (isDict(xResources)) { + nodes.push(xResources); + } + } + } + return false; + }, + + buildFormXObject: function PartialEvaluator_buildFormXObject(resources, + xobj, smask, + operatorList, + state) { + var self = this; + + var matrix = xobj.dict.get('Matrix'); + var bbox = xobj.dict.get('BBox'); + var group = xobj.dict.get('Group'); + if (group) { + var groupOptions = { + matrix: matrix, + bbox: bbox, + smask: smask, + isolated: false, + knockout: false + }; + + var groupSubtype = group.get('S'); + 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; + } + 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, []); + + if (group) { + operatorList.addOp(OPS.endGroup, [groupOptions]); + } + }, + + buildPaintImageXObject: function PartialEvaluator_buildPaintImageXObject( + resources, image, inline, operatorList) { + var self = this; + var dict = image.dict; + var w = dict.get('Width', 'W'); + var h = dict.get('Height', 'H'); + + 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; + if (imageMask) { + // This depends on a tmpCanvas beeing filled with the + // current fillStyle, such that processing the pixel + // data can't be done here. Instead of creating a + // complete PDFImage, only read the information needed + // for later. + + var width = dict.get('Width', 'W'); + var height = dict.get('Height', 'H'); + var bitStrideLength = (width + 7) >> 3; + var imgArray = image.getBytes(bitStrideLength * height); + var decode = dict.get('Decode', 'D'); + var inverseDecode = !!decode && decode[0] > 0; + + operatorList.addOp(OPS.paintImageMaskXObject, + [PDFImage.createMask(imgArray, width, height, inverseDecode)] + ); + return; + } + + var softMask = dict.get('SMask', 'SM') || false; + var mask = dict.get('Mask') || false; + + var SMALL_IMAGE_DIMENSIONS = 200; + // Inlining small images into the queue as RGB data + if (inline && !softMask && !mask && + !(image instanceof JpegStream) && + (w + h) < SMALL_IMAGE_DIMENSIONS) { + var imageObj = new PDFImage(this.xref, resources, image, + inline, null, null); + var imgData = imageObj.getImageData(); + operatorList.addOp(OPS.paintInlineImageXObject, [imgData]); + return; + } + + // If there is no imageMask, create the PDFImage and a lot + // of image processing can be done here. + var uniquePrefix = this.uniquePrefix || ''; + var objId = 'img_' + uniquePrefix + (++this.idCounters.obj); + operatorList.addDependency(objId); + var args = [objId, w, h]; + + if (!softMask && !mask && image instanceof JpegStream && + image.isNativelySupported(this.xref, resources)) { + // These JPEGs don't need any more processing so we can just send it. + operatorList.addOp(OPS.paintJpegXObject, args); + this.handler.send( + 'obj', [objId, this.pageIndex, 'JpegStream', image.getIR()]); + return; + } + + + PDFImage.buildImage(function(imageObj) { + var imgData = imageObj.getImageData(); + self.handler.send('obj', [objId, self.pageIndex, 'Image', imgData], + null, [imgData.data.buffer]); + }, self.handler, self.xref, resources, image, inline); + + operatorList.addOp(OPS.paintImageXObject, args); + }, + + handleSMask: function PartialEvaluator_handleSmask(smask, resources, + operatorList) { + var smaskContent = smask.get('G'); + var smaskOptions = { + subtype: smask.get('S').name, + backdrop: smask.get('BC') + }; + + this.buildFormXObject(resources, smaskContent, smaskOptions, + 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)); + }, + + handleSetFont: function PartialEvaluator_handleSetFont( + resources, fontArgs, fontRef, operatorList) { + + // 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; + }, + + handleText: function PartialEvaluator_handleText(chars) { + var font = this.state.font.translated; + var glyphs = font.charsToGlyphs(chars); + var isAddToPathSet = !!(this.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; + if (!font.renderer.hasBuiltPath(fontChar)) { + var path = font.renderer.getPathJs(fontChar); + this.handler.send('commonobj', [ + font.loadedName + '_path_' + fontChar, + 'FontPath', + path + ]); + } + } + } + + return glyphs; + }, + + setGState: function PartialEvaluator_setGState(resources, gState, + operatorList, xref) { + + 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) { + switch (key) { + case 'Type': + break; + case 'LW': + case 'LC': + case 'LJ': + case 'ML': + case 'D': + case 'RI': + case 'FL': + case 'CA': + case 'ca': + gStateObj.push([key, value]); + break; + case 'Font': + var loadedName = self.handleSetFont(resources, null, value[0], + operatorList); + operatorList.addDependency(loadedName); + gStateObj.push([key, [loadedName, value[1]]]); + break; + case 'BM': + gStateObj.push([key, value]); + break; + case 'SMask': + if (isName(value) && value.name === 'None') { + gStateObj.push([key, false]); + break; + } + var dict = xref.fetchIfRef(value); + if (isDict(dict)) { + self.handleSMask(dict, resources, operatorList); + gStateObj.push([key, true]); + } else { + warn('Unsupported SMask type'); + } + + break; + // Only generate info log messages for the following since + // they are unlikey to have a big impact on the rendering. + case 'OP': + case 'op': + case 'OPM': + case 'BG': + case 'BG2': + case 'UCR': + case 'UCR2': + case 'TR': + case 'TR2': + case 'HT': + case 'SM': + case 'SA': + case 'AIS': + case 'TK': + // TODO implement these operators. + info('graphic state operator ' + key); + break; + default: + info('Unknown graphic state operator ' + key); + break; + } + } + + // 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]); + }, + + loadFont: function PartialEvaluator_loadFont(fontName, font, xref, + resources, + parentOperatorList) { + + function errorFont() { + return { + translated: new ErrorFont('Font ' + fontName + ' is not available'), + loadedName: 'g_font_error' + }; + } + + var fontRef; + if (font) { // Loading by ref. + assert(isRef(font)); + fontRef = font; + } else { // Loading by name. + var fontRes = resources.get('Font'); + if (fontRes) { + fontRef = fontRes.getRaw(fontName); + } else { + warn('fontRes not available'); + return errorFont(); + } + } + if (this.fontCache.has(fontRef)) { + return this.fontCache.get(fontRef); + } + + font = xref.fetchIfRef(fontRef); + if (!isDict(font)) { + return errorFont(); + } + // Workaround for bad PDF generators that doesn'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); + } + + // 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)); + + 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; + } + + 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; + } + return font; + }, + + getOperatorList: function PartialEvaluator_getOperatorList(stream, + resources, + operatorList, + evaluatorState) { + + var self = this; + var xref = this.xref; + var handler = this.handler; + + operatorList = operatorList || new 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); + } + + var promise = new LegacyPromise(); + var operation; + while ((operation = preprocessor.read())) { + 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; + case OPS.paintXObject: + if (args[0].code) { + break; + } + // eagerly compile XForm objects + var name = args[0].name; + var xobj = xobjs.get(name); + if (xobj) { + assertWellFormed( + isStream(xobj), 'XObject should be a stream'); + + var type = xobj.dict.get('Subtype'); + assertWellFormed( + 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) { + self.buildPaintImageXObject(resources, xobj, false, + operatorList); + args = []; + continue; + } else { + error('Unhandled XObject subtype ' + type.name); + } + } + break; + case OPS.setFont: + // eagerly collect all fonts + var loadedName = self.handleSetFont(resources, args, null, + operatorList); + operatorList.addDependency(loadedName); + args[0] = loadedName; + break; + 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; + } + break; + case OPS.showText: + args[0] = this.handleText(args[0]); + break; + case OPS.showSpacedText: + var arr = args[0]; + var arrLength = arr.length; + for (var i = 0; i < arrLength; ++i) { + if (isString(arr[i])) { + arr[i] = this.handleText(arr[i]); + } + } + break; + case OPS.nextLineShowText: + args[0] = this.handleText(args[0]); + break; + case OPS.nextLineSetSpacingShowText: + args[2] = this.handleText(args[2]); + break; + case OPS.setTextRenderingMode: + this.state.textRenderingMode = args[0]; + break; + // Parse the ColorSpace data to a raw format. + case OPS.setFillColorSpace: + case OPS.setStrokeColorSpace: + args = [ColorSpace.parseToIR(args[0], xref, resources)]; + break; + case OPS.shadingFill: + var shadingRes = resources.get('Shading'); + if (!shadingRes) + error('No shading resource found'); + + var shading = shadingRes.get(args[0].name); + if (!shading) + error('No shading object found'); + + var shadingFill = Pattern.parseShading( + shading, null, xref, resources); + var patternIR = shadingFill.getIR(); + args = [patternIR]; + fn = OPS.shadingFill; + break; + case OPS.setGState: + var dictName = args[0]; + var extGState = resources.get('ExtGState'); + + if (!isDict(extGState) || !extGState.has(dictName.name)) + break; + + var gState = extGState.get(dictName.name); + self.setGState(resources, gState, operatorList, xref); + args = []; + continue; + } // switch + + 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; + }, + + getTextContent: function PartialEvaluator_getTextContent( + stream, resources, textState) { + + textState = textState || new TextState(); + + var bidiTexts = []; + 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) || new Dict(); + // The xobj is parsed iff it's needed, e.g. if there is a `DO` cmd. + var xobjs = null; + + var preprocessor = new EvaluatorPreprocessor(stream, xref); + var res = resources; + + var chunk = ''; + var font = null; + var charSpace = 0, wordSpace = 0; + var operation; + while ((operation = preprocessor.read())) { + var fn = operation.fn; + var args = operation.args; + switch (fn) { + // TODO: Add support for SAVE/RESTORE and XFORM here. + case OPS.setFont: + font = handleSetFont(args[0].name).translated; + textState.fontSize = args[1]; + break; + case OPS.setTextRise: + textState.textRise = args[0]; + break; + case OPS.setHScale: + textState.textHScale = args[0] / 100; + break; + case OPS.setLeading: + textState.leading = args[0]; + break; + case OPS.moveText: + textState.translateTextMatrix(args[0], args[1]); + break; + case OPS.setLeadingMoveText: + textState.leading = -args[1]; + textState.translateTextMatrix(args[0], args[1]); + break; + case OPS.nextLine: + textState.translateTextMatrix(0, -textState.leading); + break; + case OPS.setTextMatrix: + textState.setTextMatrix(args[0], args[1], + args[2], args[3], args[4], args[5]); + break; + case OPS.setCharSpacing: + charSpace = args[0]; + break; + case OPS.setWordSpacing: + wordSpace = args[0]; + break; + case OPS.beginText: + textState.initialiseTextObj(); + break; + case OPS.showSpacedText: + var items = args[0]; + 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 += ' '; + } + } else if (fakeSpaces > SPACE_FACTOR) { + chunk += ' '; + } + } + } + break; + case OPS.showText: + chunk += fontCharsToUnicode(args[0], font); + 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); + break; + case OPS.nextLineSetSpacingShowText: + // Note comment in "'" + chunk += fontCharsToUnicode(args[2], font); + 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(); + } + + var name = args[0].name; + var xobj = xobjs.get(name); + if (!xobj) + break; + assertWellFormed(isStream(xobj), 'XObject should be a stream'); + + var type = xobj.dict.get('Subtype'); + assertWellFormed( + isName(type), + 'XObject should have a Name subtype' + ); + + if ('Form' !== type.name) + break; + + var formTexts = this.getTextContent( + xobj, + xobj.dict.get('Resources') || resources, + textState + ); + Util.concatenateToArray(bidiTexts, formTexts); + break; + case OPS.setGState: + var dictName = args[0]; + var extGState = resources.get('ExtGState'); + + 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; + } + } + 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; + }, + + 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); + + if (properties.composite) { + // CIDSystemInfo helps to match CID to glyphs + var cidSystemInfo = dict.get('CIDSystemInfo'); + if (isDict(cidSystemInfo)) { + properties.cidSystemInfo = { + registry: cidSystemInfo.get('Registry'), + ordering: cidSystemInfo.get('Ordering'), + supplement: cidSystemInfo.get('Supplement') + }; + } + + var cidToGidMap = dict.get('CIDToGIDMap'); + if (isStream(cidToGidMap)) + properties.cidToGidMap = this.readCidToGidMap(cidToGidMap); + } + + // Based on 9.6.6 of the spec the encoding can come from multiple places + // 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; + 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; + } + if (dict.has('Encoding')) { + var encoding = dict.get('Encoding'); + if (isDict(encoding)) { + var baseName = encoding.get('BaseEncoding'); + if (baseName) { + overridableEncoding = false; + hasEncoding = true; + baseEncoding = Encodings[baseName.name]; + } + + // 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)) + index = data; + 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; + } + } else { + error('Encoding is not a Name nor a Dict'); + } + } + + properties.differences = differences; + properties.baseEncoding = baseEncoding; + properties.hasEncoding = hasEncoding; + properties.overridableEncoding = overridableEncoding; + }, + + readToUnicode: function PartialEvaluator_readToUnicode(toUnicode, xref, + properties) { + var cmapObj = toUnicode; + var charToUnicode = []; + if (isName(cmapObj)) { + var isIdentityMap = cmapObj.name.substr(0, 9) == 'Identity-'; + if (!isIdentityMap) + error('ToUnicode file cmap translation not implemented'); + } else if (isStream(cmapObj)) { + var cmap = CMapFactory.create(cmapObj).map; + // Convert UTF-16BE + for (var i in cmap) { + var token = cmap[i]; + var str = []; + for (var k = 0; k < token.length; k += 2) { + var w1 = (token.charCodeAt(k) << 8) | token.charCodeAt(k + 1); + if ((w1 & 0xF800) !== 0xD800) { // w1 < 0xD800 || w1 > 0xDFFF + str.push(w1); + continue; + } + k += 2; + var w2 = (token.charCodeAt(k) << 8) | token.charCodeAt(k + 1); + str.push(((w1 & 0x3ff) << 10) + (w2 & 0x3ff) + 0x10000); + } + cmap[i] = String.fromCharCode.apply(String, str); + } + return cmap; + } + return charToUnicode; + }, + readCidToGidMap: function PartialEvaluator_readCidToGidMap(cidToGidStream) { + // Extract the encoding from the CIDToGIDMap + var glyphsData = cidToGidStream.getBytes(); + + // Set encoding 0 to later verify the font has an encoding + var result = []; + for (var j = 0, jj = glyphsData.length; j < jj; j++) { + var glyphID = (glyphsData[j++] << 8) | glyphsData[j]; + if (glyphID === 0) + continue; + + var code = j >> 1; + result[code] = glyphID; + } + return result; + }, + + extractWidths: function PartialEvaluator_extractWidths(dict, + xref, + descriptor, + properties) { + var glyphsWidths = []; + var defaultWidth = 0; + var glyphsVMetrics = []; + var defaultVMetrics; + if (properties.composite) { + defaultWidth = dict.get('DW') || 1000; + + var 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]); + if (isArray(code)) { + for (var j = 0, jj = code.length; j < jj; j++) + glyphsWidths[start++] = code[j]; + } else { + var width = widths[++i]; + for (var j = start; j <= code; j++) + glyphsWidths[j] = width; + } + } + } + + if (properties.vertical) { + var vmetrics = dict.get('DW2') || [880, -1000]; + defaultVMetrics = [vmetrics[1], defaultWidth * 0.5, vmetrics[0]]; + vmetrics = dict.get('W2'); + if (vmetrics) { + for (var i = 0, ii = vmetrics.length; i < ii; i++) { + var start = vmetrics[i++]; + var code = xref.fetchIfRef(vmetrics[i]); + if (isArray(code)) { + for (var 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++) + glyphsVMetrics[j] = vmetric; + } + } + } + } + } else { + var firstChar = properties.firstChar; + var widths = dict.get('Widths'); + if (widths) { + var j = firstChar; + for (var i = 0, ii = widths.length; i < ii; i++) + glyphsWidths[j++] = widths[i]; + defaultWidth = parseFloat(descriptor.get('MissingWidth')) || 0; + } else { + // Trying get the BaseFont metrics (see comment above). + var baseFontName = dict.get('BaseFont'); + if (isName(baseFontName)) { + var metrics = this.getBaseFontMetrics(baseFontName.name); + + glyphsWidths = metrics.widths; + defaultWidth = metrics.defaultWidth; + } + } + } + + // Heuristic: detection of monospace font by checking all non-zero widths + var isMonospace = true, firstWidth = defaultWidth; + for (var glyph in glyphsWidths) { + var glyphWidth = glyphsWidths[glyph]; + if (!glyphWidth) + continue; + if (!firstWidth) { + firstWidth = glyphWidth; + continue; + } + if (firstWidth != glyphWidth) { + isMonospace = false; + break; + } + } + if (isMonospace) + properties.flags |= FontFlags.FixedPitch; + + properties.defaultWidth = defaultWidth; + properties.widths = glyphsWidths; + properties.defaultVMetrics = defaultVMetrics; + properties.vmetrics = glyphsVMetrics; + }, + + isSerifFont: function PartialEvaluator_isSerifFont(baseFontName) { + + // Simulating descriptor flags attribute + var fontNameWoStyle = baseFontName.split('-')[0]; + return (fontNameWoStyle in serifFonts) || + (fontNameWoStyle.search(/serif/gi) !== -1); + }, + + getBaseFontMetrics: function PartialEvaluator_getBaseFontMetrics(name) { + var defaultWidth = 0, widths = [], monospace = false; + + var lookupName = stdFontMap[name] || name; + + if (!(lookupName in Metrics)) { + // Use default fonts for looking up font metrics if the passed + // font is not a base font + if (this.isSerifFont(name)) { + lookupName = 'Times-Roman'; + } else { + lookupName = 'Helvetica'; + } + } + var glyphWidths = Metrics[lookupName]; + + if (isNum(glyphWidths)) { + defaultWidth = glyphWidths; + monospace = true; + } else { + widths = glyphWidths; + } + + return { + defaultWidth: defaultWidth, + monospace: monospace, + widths: widths + }; + }, + + translateFont: function PartialEvaluator_translateFont(dict, + xref) { + var baseDict = dict; + var type = dict.get('Subtype'); + assertWellFormed(isName(type), 'invalid font Subtype'); + + var composite = false; + if (type.name == 'Type0') { + // If font is a composite + // - get the descendant font + // - set the type according to the descendant font + // - get the FontDescriptor from the descendant font + var df = dict.get('DescendantFonts'); + if (!df) + error('Descendant fonts are not specified'); + + dict = isArray(df) ? xref.fetchIfRef(df[0]) : df; + + type = dict.get('Subtype'); + assertWellFormed(isName(type), 'invalid font Subtype'); + composite = true; + } + var maxCharIndex = composite ? 0xFFFF : 0xFF; + + var descriptor = dict.get('FontDescriptor'); + if (!descriptor) { + if (type.name == '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)); + } else { + // Before PDF 1.5 if the font was one of the base 14 fonts, having a + // FontDescriptor was not required. + // This case is here for compatibility. + var baseFontName = dict.get('BaseFont'); + if (!isName(baseFontName)) + error('Base font is not specified'); + + // Using base font name as a font name. + baseFontName = baseFontName.name.replace(/[,_]/g, '-'); + var metrics = this.getBaseFontMetrics(baseFontName); + + // Simulating descriptor flags attribute + var fontNameWoStyle = baseFontName.split('-')[0]; + var flags = ( + this.isSerifFont(fontNameWoStyle) ? FontFlags.Serif : 0) | + (metrics.monospace ? FontFlags.FixedPitch : 0) | + (symbolsFonts[fontNameWoStyle] ? FontFlags.Symbolic : + FontFlags.Nonsymbolic); + + var properties = { + type: type.name, + name: baseFontName, + widths: metrics.widths, + defaultWidth: metrics.defaultWidth, + flags: flags, + firstChar: 0, + lastChar: maxCharIndex + }; + this.extractDataStructures(dict, dict, xref, properties); + + return new Font(baseFontName, null, properties); + } + } + + // According to the spec if 'FontDescriptor' is declared, 'FirstChar', + // 'LastChar' and 'Widths' should exist too, but some PDF encoders seem + // to ignore this rule when a variant of a standart font is used. + // TODO Fill the width array depending on which of the base font this is + // a variant. + var firstChar = dict.get('FirstChar') || 0; + var lastChar = dict.get('LastChar') || maxCharIndex; + + var fontName = descriptor.get('FontName'); + var baseFont = dict.get('BaseFont'); + // Some bad pdf's have a string as the font name. + if (isString(fontName)) { + fontName = new Name(fontName); + } + if (isString(baseFont)) { + baseFont = new Name(baseFont); + } + + if (type.name !== '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 + '"'); + } + } + fontName = fontName || baseFont; + + assertWellFormed(isName(fontName), 'invalid font name'); + + var fontFile = descriptor.get('FontFile', 'FontFile2', 'FontFile3'); + if (fontFile) { + if (fontFile.dict) { + var subtype = fontFile.dict.get('Subtype'); + if (subtype) + subtype = subtype.name; + + var length1 = fontFile.dict.get('Length1'); + + var length2 = fontFile.dict.get('Length2'); + } + } + + var properties = { + type: type.name, + name: fontName.name, + subtype: subtype, + file: fontFile, + length1: length1, + length2: length2, + loadedName: baseDict.loadedName, + composite: composite, + wideChars: composite, + fixedPitch: false, + fontMatrix: dict.get('FontMatrix') || FONT_IDENTITY_MATRIX, + firstChar: firstChar || 0, + lastChar: lastChar || maxCharIndex, + bbox: descriptor.get('FontBBox'), + ascent: descriptor.get('Ascent'), + descent: descriptor.get('Descent'), + xHeight: descriptor.get('XHeight'), + capHeight: descriptor.get('CapHeight'), + flags: descriptor.get('Flags'), + italicAngle: descriptor.get('ItalicAngle'), + coded: false + }; + + if (composite) { + var cidEncoding = baseDict.get('Encoding'); + if (isName(cidEncoding)) { + properties.cidEncoding = cidEncoding.name; + properties.vertical = /-V$/.test(cidEncoding.name); + } + properties.cmap = CMapFactory.create(cidEncoding); + } + this.extractWidths(dict, xref, descriptor, properties); + this.extractDataStructures(dict, baseDict, xref, properties); + + if (type.name === 'Type3') { + properties.coded = 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; + } + } + return transfers; + } + + + function OperatorList(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.argsArray = []; + this.dependencies = {}, + this.pageIndex = pageIndex; + this.fnIndex = 0; + } + + OperatorList.prototype = { + + get length() { + return this.argsArray.length; + }, + + addOp: function(fn, args) { + if (this.messageHandler) { + this.fnArray[this.fnIndex++] = fn; + this.argsArray.push(args); + if (this.fnIndex >= CHUNK_SIZE) { + this.flush(); + } + } else { + this.fnArray.push(fn); + this.argsArray.push(args); + } + }, + + addDependency: function(dependency) { + if (dependency in this.dependencies) { + return; + } + this.dependencies[dependency] = true; + this.addOp(OPS.dependency, [dependency]); + }, + + addDependencies: function(dependencies) { + for (var key in dependencies) { + this.addDependency(key); + } + }, + + addOpList: function(opList) { + Util.extendObj(this.dependencies, opList.dependencies); + for (var i = 0, ii = opList.length; i < ii; i++) { + this.addOp(opList.fnArray[i], opList.argsArray[i]); + } + }, + + getIR: function() { + return { + fnArray: this.fnArray, + argsArray: this.argsArray, + length: this.length + }; + }, + + flush: function(lastChunk) { + PartialEvaluator.optimizeQueue(this); + var transfers = getTransfers(this); + this.messageHandler.send('RenderPageChunk', { + operatorList: { + fnArray: this.fnArray, + argsArray: this.argsArray, + lastChunk: lastChunk, + length: this.length + }, + pageIndex: this.pageIndex + }, null, transfers); + this.dependencies = []; + this.fnIndex = 0; + this.argsArray = []; + } + }; + + return OperatorList; +})(); + +var TextState = (function TextStateClosure() { + function TextState() { + this.fontSize = 0; + this.textMatrix = [1, 0, 0, 1, 0, 0]; + this.stateStack = []; + //textState variables + 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; + }, + 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 + }; + }, + }; + return TextState; +})(); + +var EvalState = (function EvalStateClosure() { + function EvalState() { + this.font = null; + this.textRenderingMode = TextRenderingMode.FILL; + } + EvalState.prototype = { + clone: function CanvasExtraState_clone() { + return Object.create(this); + }, + }; + return EvalState; +})(); + +var EvaluatorPreprocessor = (function EvaluatorPreprocessor() { + // Specifies properties for each command + // + // If variableArgs === true: [0, `numArgs`] expected + // If variableArgs === false: exactly `numArgs` expected + var OP_MAP = { + // Graphic state + w: { id: OPS.setLineWidth, numArgs: 1, variableArgs: false }, + J: { id: OPS.setLineCap, numArgs: 1, variableArgs: false }, + j: { id: OPS.setLineJoin, numArgs: 1, variableArgs: false }, + M: { id: OPS.setMiterLimit, numArgs: 1, variableArgs: false }, + d: { id: OPS.setDash, numArgs: 2, variableArgs: false }, + ri: { id: OPS.setRenderingIntent, numArgs: 1, variableArgs: false }, + i: { id: OPS.setFlatness, numArgs: 1, variableArgs: false }, + gs: { id: OPS.setGState, numArgs: 1, variableArgs: false }, + q: { id: OPS.save, numArgs: 0, variableArgs: false }, + Q: { id: OPS.restore, numArgs: 0, variableArgs: false }, + cm: { id: OPS.transform, numArgs: 6, variableArgs: false }, + + // Path + m: { id: OPS.moveTo, numArgs: 2, variableArgs: false }, + l: { id: OPS.lineTo, numArgs: 2, variableArgs: false }, + c: { id: OPS.curveTo, numArgs: 6, variableArgs: false }, + v: { id: OPS.curveTo2, numArgs: 4, variableArgs: false }, + y: { id: OPS.curveTo3, numArgs: 4, variableArgs: false }, + h: { id: OPS.closePath, numArgs: 0, variableArgs: false }, + re: { id: OPS.rectangle, numArgs: 4, variableArgs: false }, + S: { id: OPS.stroke, numArgs: 0, variableArgs: false }, + s: { id: OPS.closeStroke, numArgs: 0, variableArgs: false }, + f: { id: OPS.fill, numArgs: 0, variableArgs: false }, + F: { id: OPS.fill, numArgs: 0, variableArgs: false }, + 'f*': { id: OPS.eoFill, numArgs: 0, variableArgs: false }, + B: { id: OPS.fillStroke, numArgs: 0, variableArgs: false }, + 'B*': { id: OPS.eoFillStroke, numArgs: 0, variableArgs: false }, + b: { id: OPS.closeFillStroke, numArgs: 0, variableArgs: false }, + 'b*': { id: OPS.closeEOFillStroke, numArgs: 0, variableArgs: false }, + n: { id: OPS.endPath, numArgs: 0, variableArgs: false }, + + // Clipping + W: { id: OPS.clip, numArgs: 0, variableArgs: false }, + 'W*': { id: OPS.eoClip, numArgs: 0, variableArgs: false }, + + // Text + BT: { id: OPS.beginText, numArgs: 0, variableArgs: false }, + ET: { id: OPS.endText, numArgs: 0, variableArgs: false }, + Tc: { id: OPS.setCharSpacing, numArgs: 1, variableArgs: false }, + Tw: { id: OPS.setWordSpacing, numArgs: 1, variableArgs: false }, + Tz: { id: OPS.setHScale, numArgs: 1, variableArgs: false }, + TL: { id: OPS.setLeading, numArgs: 1, variableArgs: false }, + Tf: { id: OPS.setFont, numArgs: 2, variableArgs: false }, + Tr: { id: OPS.setTextRenderingMode, numArgs: 1, variableArgs: false }, + Ts: { id: OPS.setTextRise, numArgs: 1, variableArgs: false }, + Td: { id: OPS.moveText, numArgs: 2, variableArgs: false }, + TD: { id: OPS.setLeadingMoveText, numArgs: 2, variableArgs: false }, + Tm: { id: OPS.setTextMatrix, numArgs: 6, variableArgs: false }, + 'T*': { id: OPS.nextLine, numArgs: 0, variableArgs: false }, + Tj: { id: OPS.showText, numArgs: 1, variableArgs: false }, + TJ: { id: OPS.showSpacedText, numArgs: 1, variableArgs: false }, + '\'': { id: OPS.nextLineShowText, numArgs: 1, variableArgs: false }, + '"': { id: OPS.nextLineSetSpacingShowText, numArgs: 3, + variableArgs: false }, + + // Type3 fonts + d0: { id: OPS.setCharWidth, numArgs: 2, variableArgs: false }, + d1: { id: OPS.setCharWidthAndBounds, numArgs: 6, variableArgs: false }, + + // Color + CS: { id: OPS.setStrokeColorSpace, numArgs: 1, variableArgs: false }, + cs: { id: OPS.setFillColorSpace, numArgs: 1, variableArgs: false }, + SC: { id: OPS.setStrokeColor, numArgs: 4, variableArgs: true }, + SCN: { id: OPS.setStrokeColorN, numArgs: 33, variableArgs: true }, + sc: { id: OPS.setFillColor, numArgs: 4, variableArgs: true }, + scn: { id: OPS.setFillColorN, numArgs: 33, variableArgs: true }, + G: { id: OPS.setStrokeGray, numArgs: 1, variableArgs: false }, + g: { id: OPS.setFillGray, numArgs: 1, variableArgs: false }, + RG: { id: OPS.setStrokeRGBColor, numArgs: 3, variableArgs: false }, + rg: { id: OPS.setFillRGBColor, numArgs: 3, variableArgs: false }, + K: { id: OPS.setStrokeCMYKColor, numArgs: 4, variableArgs: false }, + k: { id: OPS.setFillCMYKColor, numArgs: 4, variableArgs: false }, + + // Shading + sh: { id: OPS.shadingFill, numArgs: 1, variableArgs: false }, + + // Images + BI: { id: OPS.beginInlineImage, numArgs: 0, variableArgs: false }, + ID: { id: OPS.beginImageData, numArgs: 0, variableArgs: false }, + EI: { id: OPS.endInlineImage, numArgs: 1, variableArgs: false }, + + // XObjects + Do: { id: OPS.paintXObject, numArgs: 1, variableArgs: false }, + MP: { id: OPS.markPoint, numArgs: 1, variableArgs: false }, + DP: { id: OPS.markPointProps, numArgs: 2, variableArgs: false }, + BMC: { id: OPS.beginMarkedContent, numArgs: 1, variableArgs: false }, + BDC: { id: OPS.beginMarkedContentProps, numArgs: 2, + variableArgs: false }, + EMC: { id: OPS.endMarkedContent, numArgs: 0, variableArgs: false }, + + // Compatibility + BX: { id: OPS.beginCompat, numArgs: 0, variableArgs: false }, + EX: { id: OPS.endCompat, numArgs: 0, variableArgs: false }, + + // (reserved partial commands for the lexer) + BM: null, + BD: null, + 'true': null, + fa: null, + fal: null, + fals: null, + 'false': null, + nu: null, + nul: null, + 'null': null + }; + + function EvaluatorPreprocessor(stream, xref) { + // 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 = []; + } + EvaluatorPreprocessor.prototype = { + get savedStatesDepth() { + return this.savedStates.length; + }, + read: function EvaluatorPreprocessor_read() { + var 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 = []; + continue; + } else if (args.length > opSpec.numArgs) { + info('Command ' + fn + ': expected ' + opSpec.numArgs + + ' args, but received ' + args.length + ' args'); + } + } + + // 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) { + switch (fn | 0) { + case OPS.save: + this.savedStates.push(this.getState()); + break; + case OPS.restore: + var previousState = this.savedStates.pop(); + if (previousState) { + this.setState(previousState); + } + 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; + break; + } + } + }; + return EvaluatorPreprocessor; +})(); + + +// Unicode Private Use Area +var CMAP_GLYPH_OFFSET = 0xE000; +var GLYPH_AREA_SIZE = 0x1900; +var SYMBOLIC_FONT_GLYPH_OFFSET = 0xF000; + +// PDF Glyph Space Units are one Thousandth of a TextSpace Unit +// except for Type 3 fonts +var PDF_GLYPH_SPACE_UNITS = 1000; + +// Hinting is currently disabled due to unknown problems on windows +// in tracemonkey and various other pdfs with type1 fonts. +var HINTING_ENABLED = false; + +// Accented charactars are not displayed properly on windows, using this flag +// to control analysis of seac charstrings. +var SEAC_ANALYSIS_ENABLED = false; + +var FontFlags = { + FixedPitch: 1, + Serif: 2, + Symbolic: 4, + Script: 8, + Nonsymbolic: 32, + Italic: 64, + AllCap: 65536, + SmallCap: 131072, + ForceBold: 262144 +}; + +var Encodings = { + ExpertEncoding: ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 'space', 'exclamsmall', 'Hungarumlautsmall', '', 'dollaroldstyle', + 'dollarsuperior', 'ampersandsmall', 'Acutesmall', 'parenleftsuperior', + 'parenrightsuperior', 'twodotenleader', 'onedotenleader', 'comma', + 'hyphen', 'period', 'fraction', 'zerooldstyle', 'oneoldstyle', + 'twooldstyle', 'threeoldstyle', 'fouroldstyle', 'fiveoldstyle', + 'sixoldstyle', 'sevenoldstyle', 'eightoldstyle', 'nineoldstyle', 'colon', + 'semicolon', 'commasuperior', 'threequartersemdash', 'periodsuperior', + 'questionsmall', '', 'asuperior', 'bsuperior', 'centsuperior', 'dsuperior', + 'esuperior', '', '', 'isuperior', '', '', 'lsuperior', 'msuperior', + 'nsuperior', 'osuperior', '', '', 'rsuperior', 'ssuperior', 'tsuperior', + '', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'parenleftinferior', '', + 'parenrightinferior', 'Circumflexsmall', 'hyphensuperior', 'Gravesmall', + 'Asmall', 'Bsmall', 'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall', + 'Hsmall', 'Ismall', 'Jsmall', 'Ksmall', 'Lsmall', 'Msmall', 'Nsmall', + 'Osmall', 'Psmall', 'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall', + 'Vsmall', 'Wsmall', 'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary', + 'onefitted', 'rupiah', 'Tildesmall', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', 'exclamdownsmall', 'centoldstyle', 'Lslashsmall', + '', '', 'Scaronsmall', 'Zcaronsmall', 'Dieresissmall', 'Brevesmall', + 'Caronsmall', '', 'Dotaccentsmall', '', '', 'Macronsmall', '', '', + 'figuredash', 'hypheninferior', '', '', 'Ogoneksmall', 'Ringsmall', + 'Cedillasmall', '', '', '', 'onequarter', 'onehalf', 'threequarters', + 'questiondownsmall', 'oneeighth', 'threeeighths', 'fiveeighths', + 'seveneighths', 'onethird', 'twothirds', '', '', 'zerosuperior', + 'onesuperior', 'twosuperior', 'threesuperior', 'foursuperior', + 'fivesuperior', 'sixsuperior', 'sevensuperior', 'eightsuperior', + 'ninesuperior', 'zeroinferior', 'oneinferior', 'twoinferior', + 'threeinferior', 'fourinferior', 'fiveinferior', 'sixinferior', + 'seveninferior', 'eightinferior', 'nineinferior', 'centinferior', + 'dollarinferior', 'periodinferior', 'commainferior', 'Agravesmall', + 'Aacutesmall', 'Acircumflexsmall', 'Atildesmall', 'Adieresissmall', + 'Aringsmall', 'AEsmall', 'Ccedillasmall', 'Egravesmall', 'Eacutesmall', + 'Ecircumflexsmall', 'Edieresissmall', 'Igravesmall', 'Iacutesmall', + 'Icircumflexsmall', 'Idieresissmall', 'Ethsmall', 'Ntildesmall', + 'Ogravesmall', 'Oacutesmall', 'Ocircumflexsmall', 'Otildesmall', + 'Odieresissmall', 'OEsmall', 'Oslashsmall', 'Ugravesmall', 'Uacutesmall', + 'Ucircumflexsmall', 'Udieresissmall', 'Yacutesmall', 'Thornsmall', + 'Ydieresissmall'], + MacExpertEncoding: ['', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 'space', 'exclamsmall', 'Hungarumlautsmall', 'centoldstyle', + 'dollaroldstyle', 'dollarsuperior', 'ampersandsmall', 'Acutesmall', + 'parenleftsuperior', 'parenrightsuperior', 'twodotenleader', + 'onedotenleader', 'comma', 'hyphen', 'period', 'fraction', 'zerooldstyle', + 'oneoldstyle', 'twooldstyle', 'threeoldstyle', 'fouroldstyle', + 'fiveoldstyle', 'sixoldstyle', 'sevenoldstyle', 'eightoldstyle', + 'nineoldstyle', 'colon', 'semicolon', '', 'threequartersemdash', '', + 'questionsmall', '', '', '', '', 'Ethsmall', '', '', 'onequarter', + 'onehalf', 'threequarters', 'oneeighth', 'threeeighths', 'fiveeighths', + 'seveneighths', 'onethird', 'twothirds', '', '', '', '', '', '', 'ff', + 'fi', 'fl', 'ffi', 'ffl', 'parenleftinferior', '', 'parenrightinferior', + 'Circumflexsmall', 'hypheninferior', 'Gravesmall', 'Asmall', 'Bsmall', + 'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall', 'Hsmall', 'Ismall', + 'Jsmall', 'Ksmall', 'Lsmall', 'Msmall', 'Nsmall', 'Osmall', 'Psmall', + 'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall', 'Vsmall', 'Wsmall', + 'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary', 'onefitted', 'rupiah', + 'Tildesmall', '', '', 'asuperior', 'centsuperior', '', '', '', '', + 'Aacutesmall', 'Agravesmall', 'Acircumflexsmall', 'Adieresissmall', + 'Atildesmall', 'Aringsmall', 'Ccedillasmall', 'Eacutesmall', 'Egravesmall', + 'Ecircumflexsmall', 'Edieresissmall', 'Iacutesmall', 'Igravesmall', + 'Icircumflexsmall', 'Idieresissmall', 'Ntildesmall', 'Oacutesmall', + 'Ogravesmall', 'Ocircumflexsmall', 'Odieresissmall', 'Otildesmall', + 'Uacutesmall', 'Ugravesmall', 'Ucircumflexsmall', 'Udieresissmall', '', + 'eightsuperior', 'fourinferior', 'threeinferior', 'sixinferior', + 'eightinferior', 'seveninferior', 'Scaronsmall', '', 'centinferior', + 'twoinferior', '', 'Dieresissmall', '', 'Caronsmall', 'osuperior', + 'fiveinferior', '', 'commainferior', 'periodinferior', 'Yacutesmall', '', + 'dollarinferior', '', 'Thornsmall', '', 'nineinferior', 'zeroinferior', + 'Zcaronsmall', 'AEsmall', 'Oslashsmall', 'questiondownsmall', + 'oneinferior', 'Lslashsmall', '', '', '', '', '', '', 'Cedillasmall', '', + '', '', '', '', 'OEsmall', 'figuredash', 'hyphensuperior', '', '', '', '', + 'exclamdownsmall', '', 'Ydieresissmall', '', 'onesuperior', 'twosuperior', + 'threesuperior', 'foursuperior', 'fivesuperior', 'sixsuperior', + 'sevensuperior', 'ninesuperior', 'zerosuperior', '', 'esuperior', + 'rsuperior', 'tsuperior', '', '', 'isuperior', 'ssuperior', 'dsuperior', + '', '', '', '', '', 'lsuperior', 'Ogoneksmall', 'Brevesmall', + 'Macronsmall', 'bsuperior', 'nsuperior', 'msuperior', 'commasuperior', + 'periodsuperior', 'Dotaccentsmall', 'Ringsmall'], + MacRomanEncoding: ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent', + 'ampersand', 'quotesingle', 'parenleft', 'parenright', 'asterisk', 'plus', + 'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two', 'three', + 'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', + 'less', 'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F', + 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', + 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright', + 'asciicircum', 'underscore', 'grave', 'a', 'b', 'c', 'd', 'e', 'f', 'g', + 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', + 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde', '', + 'Adieresis', 'Aring', 'Ccedilla', 'Eacute', 'Ntilde', 'Odieresis', + 'Udieresis', 'aacute', 'agrave', 'acircumflex', 'adieresis', 'atilde', + 'aring', 'ccedilla', 'eacute', 'egrave', 'ecircumflex', 'edieresis', + 'iacute', 'igrave', 'icircumflex', 'idieresis', 'ntilde', 'oacute', + 'ograve', 'ocircumflex', 'odieresis', 'otilde', 'uacute', 'ugrave', + 'ucircumflex', 'udieresis', 'dagger', 'degree', 'cent', 'sterling', + 'section', 'bullet', 'paragraph', 'germandbls', 'registered', 'copyright', + 'trademark', 'acute', 'dieresis', 'notequal', 'AE', 'Oslash', 'infinity', + 'plusminus', 'lessequal', 'greaterequal', 'yen', 'mu', 'partialdiff', + 'summation', 'product', 'pi', 'integral', 'ordfeminine', 'ordmasculine', + 'Omega', 'ae', 'oslash', 'questiondown', 'exclamdown', 'logicalnot', + 'radical', 'florin', 'approxequal', 'Delta', 'guillemotleft', + 'guillemotright', 'ellipsis', '', 'Agrave', 'Atilde', 'Otilde', 'OE', + 'oe', 'endash', 'emdash', 'quotedblleft', 'quotedblright', 'quoteleft', + 'quoteright', 'divide', 'lozenge', 'ydieresis', 'Ydieresis', 'fraction', + 'currency', 'guilsinglleft', 'guilsinglright', 'fi', 'fl', 'daggerdbl', + 'periodcentered', 'quotesinglbase', 'quotedblbase', 'perthousand', + 'Acircumflex', 'Ecircumflex', 'Aacute', 'Edieresis', 'Egrave', 'Iacute', + 'Icircumflex', 'Idieresis', 'Igrave', 'Oacute', 'Ocircumflex', 'apple', + 'Ograve', 'Uacute', 'Ucircumflex', 'Ugrave', 'dotlessi', 'circumflex', + 'tilde', 'macron', 'breve', 'dotaccent', 'ring', 'cedilla', 'hungarumlaut', + 'ogonek', 'caron'], + StandardEncoding: ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent', + 'ampersand', 'quoteright', 'parenleft', 'parenright', 'asterisk', 'plus', + 'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two', 'three', + 'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', + 'less', 'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F', + 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', + 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright', + 'asciicircum', 'underscore', 'quoteleft', 'a', 'b', 'c', 'd', 'e', 'f', + 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', + 'v', 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'exclamdown', + 'cent', 'sterling', 'fraction', 'yen', 'florin', 'section', 'currency', + 'quotesingle', 'quotedblleft', 'guillemotleft', 'guilsinglleft', + 'guilsinglright', 'fi', 'fl', '', 'endash', 'dagger', 'daggerdbl', + 'periodcentered', '', 'paragraph', 'bullet', 'quotesinglbase', + 'quotedblbase', 'quotedblright', 'guillemotright', 'ellipsis', + 'perthousand', '', 'questiondown', '', 'grave', 'acute', 'circumflex', + 'tilde', 'macron', 'breve', 'dotaccent', 'dieresis', '', 'ring', 'cedilla', + '', 'hungarumlaut', 'ogonek', 'caron', 'emdash', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', 'AE', '', 'ordfeminine', '', '', + '', '', 'Lslash', 'Oslash', 'OE', 'ordmasculine', '', '', '', '', '', 'ae', + '', '', '', 'dotlessi', '', '', 'lslash', 'oslash', 'oe', 'germandbls'], + WinAnsiEncoding: ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent', + 'ampersand', 'quotesingle', 'parenleft', 'parenright', 'asterisk', 'plus', + 'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two', 'three', + 'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', + 'less', 'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F', + 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', + 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright', + 'asciicircum', 'underscore', 'grave', 'a', 'b', 'c', 'd', 'e', 'f', 'g', + 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', + 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde', + 'bullet', 'Euro', 'bullet', 'quotesinglbase', 'florin', 'quotedblbase', + 'ellipsis', 'dagger', 'daggerdbl', 'circumflex', 'perthousand', 'Scaron', + 'guilsinglleft', 'OE', 'bullet', 'Zcaron', 'bullet', 'bullet', 'quoteleft', + 'quoteright', 'quotedblleft', 'quotedblright', 'bullet', 'endash', + 'emdash', 'tilde', 'trademark', 'scaron', 'guilsinglright', 'oe', 'bullet', + 'zcaron', 'Ydieresis', '', 'exclamdown', 'cent', 'sterling', + 'currency', 'yen', 'brokenbar', 'section', 'dieresis', 'copyright', + 'ordfeminine', 'guillemotleft', 'logicalnot', 'hyphen', 'registered', + 'macron', 'degree', 'plusminus', 'twosuperior', 'threesuperior', 'acute', + 'mu', 'paragraph', 'periodcentered', 'cedilla', 'onesuperior', + 'ordmasculine', 'guillemotright', 'onequarter', 'onehalf', 'threequarters', + 'questiondown', 'Agrave', 'Aacute', 'Acircumflex', 'Atilde', 'Adieresis', + 'Aring', 'AE', 'Ccedilla', 'Egrave', 'Eacute', 'Ecircumflex', 'Edieresis', + 'Igrave', 'Iacute', 'Icircumflex', 'Idieresis', 'Eth', 'Ntilde', 'Ograve', + 'Oacute', 'Ocircumflex', 'Otilde', 'Odieresis', 'multiply', 'Oslash', + 'Ugrave', 'Uacute', 'Ucircumflex', 'Udieresis', 'Yacute', 'Thorn', + 'germandbls', 'agrave', 'aacute', 'acircumflex', 'atilde', 'adieresis', + 'aring', 'ae', 'ccedilla', 'egrave', 'eacute', 'ecircumflex', 'edieresis', + 'igrave', 'iacute', 'icircumflex', 'idieresis', 'eth', 'ntilde', 'ograve', + 'oacute', 'ocircumflex', 'otilde', 'odieresis', 'divide', 'oslash', + 'ugrave', 'uacute', 'ucircumflex', 'udieresis', 'yacute', 'thorn', + 'ydieresis'], + SymbolSetEncoding: ['', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 'space', 'exclam', 'universal', 'numbersign', 'existential', 'percent', + 'ampersand', 'suchthat', 'parenleft', 'parenright', 'asteriskmath', 'plus', + 'comma', 'minus', 'period', 'slash', 'zero', 'one', 'two', 'three', 'four', + 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', 'less', + 'equal', 'greater', 'question', 'congruent', 'Alpha', 'Beta', 'Chi', + 'Delta', 'Epsilon', 'Phi', 'Gamma', 'Eta', 'Iota', 'theta1', 'Kappa', + 'Lambda', 'Mu', 'Nu', 'Omicron', 'Pi', 'Theta', 'Rho', 'Sigma', 'Tau', + 'Upsilon', 'sigma1', 'Omega', 'Xi', 'Psi', 'Zeta', 'bracketleft', + 'therefore', 'bracketright', 'perpendicular', 'underscore', 'radicalex', + 'alpha', 'beta', 'chi', 'delta', 'epsilon', 'phi', 'gamma', 'eta', 'iota', + 'phi1', 'kappa', 'lambda', 'mu', 'nu', 'omicron', 'pi', 'theta', 'rho', + 'sigma', 'tau', 'upsilon', 'omega1', 'omega', 'xi', 'psi', 'zeta', + 'braceleft', 'bar', 'braceright', 'similar', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', 'Euro', 'Upsilon1', 'minute', 'lessequal', + 'fraction', 'infinity', 'florin', 'club', 'diamond', 'heart', 'spade', + 'arrowboth', 'arrowleft', 'arrowup', 'arrowright', 'arrowdown', 'degree', + 'plusminus', 'second', 'greaterequal', 'multiply', 'proportional', + 'partialdiff', 'bullet', 'divide', 'notequal', 'equivalence', + 'approxequal', 'ellipsis', 'arrowvertex', 'arrowhorizex', 'carriagereturn', + 'aleph', 'Ifraktur', 'Rfraktur', 'weierstrass', 'circlemultiply', + 'circleplus', 'emptyset', 'intersection', 'union', 'propersuperset', + 'reflexsuperset', 'notsubset', 'propersubset', 'reflexsubset', 'element', + 'notelement', 'angle', 'gradient', 'registerserif', 'copyrightserif', + 'trademarkserif', 'product', 'radical', 'dotmath', 'logicalnot', + 'logicaland', 'logicalor', 'arrowdblboth', 'arrowdblleft', 'arrowdblup', + 'arrowdblright', 'arrowdbldown', 'lozenge', 'angleleft', 'registersans', + 'copyrightsans', 'trademarksans', 'summation', 'parenlefttp', + 'parenleftex', 'parenleftbt', 'bracketlefttp', 'bracketleftex', + 'bracketleftbt', 'bracelefttp', 'braceleftmid', 'braceleftbt', 'braceex', + '', 'angleright', 'integral', 'integraltp', 'integralex', 'integralbt', + 'parenrighttp', 'parenrightex', 'parenrightbt', 'bracketrighttp', + 'bracketrightex', 'bracketrightbt', 'bracerighttp', 'bracerightmid', + 'bracerightbt'], + zapfDingbatsEncoding: ['', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + 'space', 'a1', 'a2', 'a202', 'a3', 'a4', 'a5', 'a119', 'a118', 'a117', + 'a11', 'a12', 'a13', 'a14', 'a15', 'a16', 'a105', 'a17', 'a18', 'a19', + 'a20', 'a21', 'a22', 'a23', 'a24', 'a25', 'a26', 'a27', 'a28', 'a6', 'a7', + 'a8', 'a9', 'a10', 'a29', 'a30', 'a31', 'a32', 'a33', 'a34', 'a35', 'a36', + 'a37', 'a38', 'a39', 'a40', 'a41', 'a42', 'a43', 'a44', 'a45', 'a46', + 'a47', 'a48', 'a49', 'a50', 'a51', 'a52', 'a53', 'a54', 'a55', 'a56', + 'a57', 'a58', 'a59', 'a60', 'a61', 'a62', 'a63', 'a64', 'a65', 'a66', + 'a67', 'a68', 'a69', 'a70', 'a71', 'a72', 'a73', 'a74', 'a203', 'a75', + 'a204', 'a76', 'a77', 'a78', 'a79', 'a81', 'a82', 'a83', 'a84', 'a97', + 'a98', 'a99', 'a100', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', 'a101', 'a102', 'a103', 'a104', 'a106', 'a107', 'a108', 'a112', + 'a111', 'a110', 'a109', 'a120', 'a121', 'a122', 'a123', 'a124', 'a125', + 'a126', 'a127', 'a128', 'a129', 'a130', 'a131', 'a132', 'a133', 'a134', + 'a135', 'a136', 'a137', 'a138', 'a139', 'a140', 'a141', 'a142', 'a143', + 'a144', 'a145', 'a146', 'a147', 'a148', 'a149', 'a150', 'a151', 'a152', + 'a153', 'a154', 'a155', 'a156', 'a157', 'a158', 'a159', 'a160', 'a161', + 'a163', 'a164', 'a196', 'a165', 'a192', 'a166', 'a167', 'a168', 'a169', + 'a170', 'a171', 'a172', 'a173', 'a162', 'a174', 'a175', 'a176', 'a177', + 'a178', 'a179', 'a193', 'a180', 'a199', 'a181', 'a200', 'a182', '', 'a201', + 'a183', 'a184', 'a197', 'a185', 'a194', 'a198', 'a186', 'a195', 'a187', + 'a188', 'a189', 'a190', 'a191'] +}; + +/** + * Hold a map of decoded fonts and of the standard fourteen Type1 + * fonts and their acronyms. + */ +var stdFontMap = { + 'ArialNarrow': 'Helvetica', + 'ArialNarrow-Bold': 'Helvetica-Bold', + 'ArialNarrow-BoldItalic': 'Helvetica-BoldOblique', + 'ArialNarrow-Italic': 'Helvetica-Oblique', + 'ArialBlack': 'Helvetica', + 'ArialBlack-Bold': 'Helvetica-Bold', + 'ArialBlack-BoldItalic': 'Helvetica-BoldOblique', + 'ArialBlack-Italic': 'Helvetica-Oblique', + 'Arial': 'Helvetica', + 'Arial-Bold': 'Helvetica-Bold', + 'Arial-BoldItalic': 'Helvetica-BoldOblique', + 'Arial-Italic': 'Helvetica-Oblique', + 'Arial-BoldItalicMT': 'Helvetica-BoldOblique', + 'Arial-BoldMT': 'Helvetica-Bold', + 'Arial-ItalicMT': 'Helvetica-Oblique', + 'ArialMT': 'Helvetica', + 'Courier-Bold': 'Courier-Bold', + 'Courier-BoldItalic': 'Courier-BoldOblique', + 'Courier-Italic': 'Courier-Oblique', + 'CourierNew': 'Courier', + 'CourierNew-Bold': 'Courier-Bold', + 'CourierNew-BoldItalic': 'Courier-BoldOblique', + 'CourierNew-Italic': 'Courier-Oblique', + 'CourierNewPS-BoldItalicMT': 'Courier-BoldOblique', + 'CourierNewPS-BoldMT': 'Courier-Bold', + 'CourierNewPS-ItalicMT': 'Courier-Oblique', + 'CourierNewPSMT': 'Courier', + 'Helvetica-Bold': 'Helvetica-Bold', + 'Helvetica-BoldItalic': 'Helvetica-BoldOblique', + 'Helvetica-Italic': 'Helvetica-Oblique', + 'Symbol-Bold': 'Symbol', + 'Symbol-BoldItalic': 'Symbol', + 'Symbol-Italic': 'Symbol', + 'TimesNewRoman': 'Times-Roman', + 'TimesNewRoman-Bold': 'Times-Bold', + 'TimesNewRoman-BoldItalic': 'Times-BoldItalic', + 'TimesNewRoman-Italic': 'Times-Italic', + 'TimesNewRomanPS': 'Times-Roman', + 'TimesNewRomanPS-Bold': 'Times-Bold', + 'TimesNewRomanPS-BoldItalic': 'Times-BoldItalic', + 'TimesNewRomanPS-BoldItalicMT': 'Times-BoldItalic', + 'TimesNewRomanPS-BoldMT': 'Times-Bold', + 'TimesNewRomanPS-Italic': 'Times-Italic', + 'TimesNewRomanPS-ItalicMT': 'Times-Italic', + 'TimesNewRomanPSMT': 'Times-Roman', + 'TimesNewRomanPSMT-Bold': 'Times-Bold', + 'TimesNewRomanPSMT-BoldItalic': 'Times-BoldItalic', + 'TimesNewRomanPSMT-Italic': 'Times-Italic' +}; + +/** + * Holds the map of the non-standard fonts that might be included as a standard + * fonts without glyph data. + */ +var nonStdFontMap = { + 'ComicSansMS': 'Comic Sans MS', + 'ComicSansMS-Bold': 'Comic Sans MS-Bold', + 'ComicSansMS-BoldItalic': 'Comic Sans MS-BoldItalic', + 'ComicSansMS-Italic': 'Comic Sans MS-Italic', + 'LucidaConsole': 'Courier', + 'LucidaConsole-Bold': 'Courier-Bold', + 'LucidaConsole-BoldItalic': 'Courier-BoldOblique', + 'LucidaConsole-Italic': 'Courier-Oblique', + 'MS-Gothic': 'MS Gothic', + 'MS-Gothic-Bold': 'MS Gothic-Bold', + 'MS-Gothic-BoldItalic': 'MS Gothic-BoldItalic', + 'MS-Gothic-Italic': 'MS Gothic-Italic', + 'MS-Mincho': 'MS Mincho', + 'MS-Mincho-Bold': 'MS Mincho-Bold', + 'MS-Mincho-BoldItalic': 'MS Mincho-BoldItalic', + 'MS-Mincho-Italic': 'MS Mincho-Italic', + 'MS-PGothic': 'MS PGothic', + 'MS-PGothic-Bold': 'MS PGothic-Bold', + 'MS-PGothic-BoldItalic': 'MS PGothic-BoldItalic', + 'MS-PGothic-Italic': 'MS PGothic-Italic', + 'MS-PMincho': 'MS PMincho', + 'MS-PMincho-Bold': 'MS PMincho-Bold', + 'MS-PMincho-BoldItalic': 'MS PMincho-BoldItalic', + 'MS-PMincho-Italic': 'MS PMincho-Italic', +}; + +var serifFonts = { + 'Adobe Jenson': true, 'Adobe Text': true, 'Albertus': true, + 'Aldus': true, 'Alexandria': true, 'Algerian': true, + 'American Typewriter': true, 'Antiqua': true, 'Apex': true, + 'Arno': true, 'Aster': true, 'Aurora': true, + 'Baskerville': true, 'Bell': true, 'Bembo': true, + 'Bembo Schoolbook': true, 'Benguiat': true, 'Berkeley Old Style': true, + 'Bernhard Modern': true, 'Berthold City': true, 'Bodoni': true, + 'Bauer Bodoni': true, 'Book Antiqua': true, 'Bookman': true, + 'Bordeaux Roman': true, 'Californian FB': true, 'Calisto': true, + 'Calvert': true, 'Capitals': true, 'Cambria': true, + 'Cartier': true, 'Caslon': true, 'Catull': true, + 'Centaur': true, 'Century Old Style': true, 'Century Schoolbook': true, + 'Chaparral': true, 'Charis SIL': true, 'Cheltenham': true, + 'Cholla Slab': true, 'Clarendon': true, 'Clearface': true, + 'Cochin': true, 'Colonna': true, 'Computer Modern': true, + 'Concrete Roman': true, 'Constantia': true, 'Cooper Black': true, + 'Corona': true, 'Ecotype': true, 'Egyptienne': true, + 'Elephant': true, 'Excelsior': true, 'Fairfield': true, + 'FF Scala': true, 'Folkard': true, 'Footlight': true, + 'FreeSerif': true, 'Friz Quadrata': true, 'Garamond': true, + 'Gentium': true, 'Georgia': true, 'Gloucester': true, + 'Goudy Old Style': true, 'Goudy Schoolbook': true, 'Goudy Pro Font': true, + 'Granjon': true, 'Guardian Egyptian': true, 'Heather': true, + 'Hercules': true, 'High Tower Text': true, 'Hiroshige': true, + 'Hoefler Text': true, 'Humana Serif': true, 'Imprint': true, + 'Ionic No. 5': true, 'Janson': true, 'Joanna': true, + 'Korinna': true, 'Lexicon': true, 'Liberation Serif': true, + 'Linux Libertine': true, 'Literaturnaya': true, 'Lucida': true, + 'Lucida Bright': true, 'Melior': true, 'Memphis': true, + 'Miller': true, 'Minion': true, 'Modern': true, + 'Mona Lisa': true, 'Mrs Eaves': true, 'MS Serif': true, + 'Museo Slab': true, 'New York': true, 'Nimbus Roman': true, + 'NPS Rawlinson Roadway': true, 'Palatino': true, 'Perpetua': true, + 'Plantin': true, 'Plantin Schoolbook': true, 'Playbill': true, + 'Poor Richard': true, 'Rawlinson Roadway': true, 'Renault': true, + 'Requiem': true, 'Rockwell': true, 'Roman': true, + 'Rotis Serif': true, 'Sabon': true, 'Scala': true, + 'Seagull': true, 'Sistina': true, 'Souvenir': true, + 'STIX': true, 'Stone Informal': true, 'Stone Serif': true, + 'Sylfaen': true, 'Times': true, 'Trajan': true, + 'Trinité': true, 'Trump Mediaeval': true, 'Utopia': true, + 'Vale Type': true, 'Bitstream Vera': true, 'Vera Serif': true, + 'Versailles': true, 'Wanted': true, 'Weiss': true, + 'Wide Latin': true, 'Windsor': true, 'XITS': true +}; + +var symbolsFonts = { + 'Dingbats': true, 'Symbol': true, 'ZapfDingbats': true +}; + +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, + '17': 46, '18': 47, '19': 48, '20': 49, '21': 50, '22': 51, '23': 52, + '24': 53, '25': 54, '26': 55, '27': 56, '28': 57, '29': 58, '30': 894, + '31': 60, '32': 61, '33': 62, '34': 63, '35': 64, '36': 65, '37': 66, + '38': 67, '39': 68, '40': 69, '41': 70, '42': 71, '43': 72, '44': 73, + '45': 74, '46': 75, '47': 76, '48': 77, '49': 78, '50': 79, '51': 80, + '52': 81, '53': 82, '54': 83, '55': 84, '56': 85, '57': 86, '58': 87, + '59': 88, '60': 89, '61': 90, '62': 91, '63': 92, '64': 93, '65': 94, + '66': 95, '67': 96, '68': 97, '69': 98, '70': 99, '71': 100, '72': 101, + '73': 102, '74': 103, '75': 104, '76': 105, '77': 106, '78': 107, '79': 108, + '80': 109, '81': 110, '82': 111, '83': 112, '84': 113, '85': 114, '86': 115, + '87': 116, '88': 117, '89': 118, '90': 119, '91': 120, '92': 121, '93': 122, + '94': 123, '95': 124, '96': 125, '97': 126, '98': 196, '99': 197, '100': 199, + '101': 201, '102': 209, '103': 214, '104': 220, '105': 225, '106': 224, + '107': 226, '108': 228, '109': 227, '110': 229, '111': 231, '112': 233, + '113': 232, '114': 234, '115': 235, '116': 237, '117': 236, '118': 238, + '119': 239, '120': 241, '121': 243, '122': 242, '123': 244, '124': 246, + '125': 245, '126': 250, '127': 249, '128': 251, '129': 252, '130': 8224, + '131': 176, '132': 162, '133': 163, '134': 167, '135': 8226, '136': 182, + '137': 223, '138': 174, '139': 169, '140': 8482, '141': 180, '142': 168, + '143': 8800, '144': 198, '145': 216, '146': 8734, '147': 177, '148': 8804, + '149': 8805, '150': 165, '151': 181, '152': 8706, '153': 8721, '154': 8719, + '156': 8747, '157': 170, '158': 186, '159': 8486, '160': 230, '161': 248, + '162': 191, '163': 161, '164': 172, '165': 8730, '166': 402, '167': 8776, + '168': 8710, '169': 171, '170': 187, '171': 8230, '210': 218, '305': 963, + '306': 964, '307': 966, '308': 8215, '309': 8252, '310': 8319, '311': 8359, + '312': 8592, '313': 8593, '337': 9552, '493': 1039, '494': 1040, '705': 1524, + '706': 8362, '710': 64288, '711': 64298, '759': 1617, '761': 1776, + '763': 1778, '775': 1652, '777': 1764, '778': 1780, '779': 1781, '780': 1782, + '782': 771, '783': 64726, '786': 8363, '788': 8532, '790': 768, '791': 769, + '792': 768, '795': 803, '797': 64336, '798': 64337, '799': 64342, + '800': 64343, '801': 64344, '802': 64345, '803': 64362, '804': 64363, + '805': 64364, '2424': 7821, '2425': 7822, '2426': 7823, '2427': 7824, + '2428': 7825, '2429': 7826, '2430': 7827, '2433': 7682, '2678': 8045, + '2679': 8046, '2830': 1552, '2838': 686, '2840': 751, '2842': 753, + '2843': 754, '2844': 755, '2846': 757, '2856': 767, '2857': 848, '2858': 849, + '2862': 853, '2863': 854, '2864': 855, '2865': 861, '2866': 862, '2906': 7460, + '2908': 7462, '2909': 7463, '2910': 7464, '2912': 7466, '2913': 7467, + '2914': 7468, '2916': 7470, '2917': 7471, '2918': 7472, '2920': 7474, + '2921': 7475, '2922': 7476, '2924': 7478, '2925': 7479, '2926': 7480, + '2928': 7482, '2929': 7483, '2930': 7484, '2932': 7486, '2933': 7487, + '2934': 7488, '2936': 7490, '2937': 7491, '2938': 7492, '2940': 7494, + '2941': 7495, '2942': 7496, '2944': 7498, '2946': 7500, '2948': 7502, + '2950': 7504, '2951': 7505, '2952': 7506, '2954': 7508, '2955': 7509, + '2956': 7510, '2958': 7512, '2959': 7513, '2960': 7514, '2962': 7516, + '2963': 7517, '2964': 7518, '2966': 7520, '2967': 7521, '2968': 7522, + '2970': 7524, '2971': 7525, '2972': 7526, '2974': 7528, '2975': 7529, + '2976': 7530, '2978': 1537, '2979': 1538, '2980': 1539, '2982': 1549, + '2983': 1551, '2984': 1552, '2986': 1554, '2987': 1555, '2988': 1556, + '2990': 1623, '2991': 1624, '2995': 1775, '2999': 1791, '3002': 64290, + '3003': 64291, '3004': 64292, '3006': 64294, '3007': 64295, '3008': 64296, + '3011': 1900, '3014': 8223, '3015': 8244, '3017': 7532, '3018': 7533, + '3019': 7534, '3075': 7590, '3076': 7591, '3079': 7594, '3080': 7595, + '3083': 7598, '3084': 7599, '3087': 7602, '3088': 7603, '3091': 7606, + '3092': 7607, '3095': 7610, '3096': 7611, '3099': 7614, '3100': 7615, + '3103': 7618, '3104': 7619, '3107': 8337, '3108': 8338, '3116': 1884, + '3119': 1885, '3120': 1885, '3123': 1886, '3124': 1886, '3127': 1887, + '3128': 1887, '3131': 1888, '3132': 1888, '3135': 1889, '3136': 1889, + '3139': 1890, '3140': 1890, '3143': 1891, '3144': 1891, '3147': 1892, + '3148': 1892, '3153': 580, '3154': 581, '3157': 584, '3158': 585, '3161': 588, + '3162': 589, '3165': 891, '3166': 892, '3169': 1274, '3170': 1275, + '3173': 1278, '3174': 1279, '3181': 7622, '3182': 7623, '3282': 11799, + '3316': 578, '3379': 42785, '3393': 1159, '3416': 8377 +}; + +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 +// 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 UnicodeRanges = [ + { 'begin': 0x0000, 'end': 0x007F }, // Basic Latin + { 'begin': 0x0080, 'end': 0x00FF }, // Latin-1 Supplement + { 'begin': 0x0100, 'end': 0x017F }, // Latin Extended-A + { 'begin': 0x0180, 'end': 0x024F }, // Latin Extended-B + { 'begin': 0x0250, 'end': 0x02AF }, // IPA Extensions + { 'begin': 0x02B0, 'end': 0x02FF }, // Spacing Modifier Letters + { 'begin': 0x0300, 'end': 0x036F }, // Combining Diacritical Marks + { 'begin': 0x0370, 'end': 0x03FF }, // Greek and Coptic + { 'begin': 0x2C80, 'end': 0x2CFF }, // Coptic + { 'begin': 0x0400, 'end': 0x04FF }, // Cyrillic + { 'begin': 0x0530, 'end': 0x058F }, // Armenian + { 'begin': 0x0590, 'end': 0x05FF }, // Hebrew + { 'begin': 0xA500, 'end': 0xA63F }, // Vai + { 'begin': 0x0600, 'end': 0x06FF }, // Arabic + { 'begin': 0x07C0, 'end': 0x07FF }, // NKo + { 'begin': 0x0900, 'end': 0x097F }, // Devanagari + { 'begin': 0x0980, 'end': 0x09FF }, // Bengali + { 'begin': 0x0A00, 'end': 0x0A7F }, // Gurmukhi + { 'begin': 0x0A80, 'end': 0x0AFF }, // Gujarati + { 'begin': 0x0B00, 'end': 0x0B7F }, // Oriya + { 'begin': 0x0B80, 'end': 0x0BFF }, // Tamil + { 'begin': 0x0C00, 'end': 0x0C7F }, // Telugu + { 'begin': 0x0C80, 'end': 0x0CFF }, // Kannada + { 'begin': 0x0D00, 'end': 0x0D7F }, // Malayalam + { 'begin': 0x0E00, 'end': 0x0E7F }, // Thai + { 'begin': 0x0E80, 'end': 0x0EFF }, // Lao + { 'begin': 0x10A0, 'end': 0x10FF }, // Georgian + { 'begin': 0x1B00, 'end': 0x1B7F }, // Balinese + { 'begin': 0x1100, 'end': 0x11FF }, // Hangul Jamo + { 'begin': 0x1E00, 'end': 0x1EFF }, // Latin Extended Additional + { 'begin': 0x1F00, 'end': 0x1FFF }, // Greek Extended + { 'begin': 0x2000, 'end': 0x206F }, // General Punctuation + { 'begin': 0x2070, 'end': 0x209F }, // Superscripts And Subscripts + { 'begin': 0x20A0, 'end': 0x20CF }, // Currency Symbol + { 'begin': 0x20D0, 'end': 0x20FF }, // Combining Diacritical Marks For Symbols + { 'begin': 0x2100, 'end': 0x214F }, // Letterlike Symbols + { 'begin': 0x2150, 'end': 0x218F }, // Number Forms + { 'begin': 0x2190, 'end': 0x21FF }, // Arrows + { 'begin': 0x2200, 'end': 0x22FF }, // Mathematical Operators + { 'begin': 0x2300, 'end': 0x23FF }, // Miscellaneous Technical + { 'begin': 0x2400, 'end': 0x243F }, // Control Pictures + { 'begin': 0x2440, 'end': 0x245F }, // Optical Character Recognition + { 'begin': 0x2460, 'end': 0x24FF }, // Enclosed Alphanumerics + { 'begin': 0x2500, 'end': 0x257F }, // Box Drawing + { 'begin': 0x2580, 'end': 0x259F }, // Block Elements + { 'begin': 0x25A0, 'end': 0x25FF }, // Geometric Shapes + { 'begin': 0x2600, 'end': 0x26FF }, // Miscellaneous Symbols + { 'begin': 0x2700, 'end': 0x27BF }, // Dingbats + { 'begin': 0x3000, 'end': 0x303F }, // CJK Symbols And Punctuation + { 'begin': 0x3040, 'end': 0x309F }, // Hiragana + { 'begin': 0x30A0, 'end': 0x30FF }, // Katakana + { 'begin': 0x3100, 'end': 0x312F }, // Bopomofo + { 'begin': 0x3130, 'end': 0x318F }, // Hangul Compatibility Jamo + { 'begin': 0xA840, 'end': 0xA87F }, // Phags-pa + { 'begin': 0x3200, 'end': 0x32FF }, // Enclosed CJK Letters And Months + { 'begin': 0x3300, 'end': 0x33FF }, // CJK Compatibility + { 'begin': 0xAC00, 'end': 0xD7AF }, // Hangul Syllables + { 'begin': 0xD800, 'end': 0xDFFF }, // Non-Plane 0 * + { 'begin': 0x10900, 'end': 0x1091F }, // Phoenicia + { 'begin': 0x4E00, 'end': 0x9FFF }, // CJK Unified Ideographs + { 'begin': 0xE000, 'end': 0xF8FF }, // Private Use Area (plane 0) + { 'begin': 0x31C0, 'end': 0x31EF }, // CJK Strokes + { 'begin': 0xFB00, 'end': 0xFB4F }, // Alphabetic Presentation Forms + { 'begin': 0xFB50, 'end': 0xFDFF }, // Arabic Presentation Forms-A + { 'begin': 0xFE20, 'end': 0xFE2F }, // Combining Half Marks + { 'begin': 0xFE10, 'end': 0xFE1F }, // Vertical Forms + { 'begin': 0xFE50, 'end': 0xFE6F }, // Small Form Variants + { 'begin': 0xFE70, 'end': 0xFEFF }, // Arabic Presentation Forms-B + { 'begin': 0xFF00, 'end': 0xFFEF }, // Halfwidth And Fullwidth Forms + { 'begin': 0xFFF0, 'end': 0xFFFF }, // Specials + { 'begin': 0x0F00, 'end': 0x0FFF }, // Tibetan + { 'begin': 0x0700, 'end': 0x074F }, // Syriac + { 'begin': 0x0780, 'end': 0x07BF }, // Thaana + { 'begin': 0x0D80, 'end': 0x0DFF }, // Sinhala + { 'begin': 0x1000, 'end': 0x109F }, // Myanmar + { 'begin': 0x1200, 'end': 0x137F }, // Ethiopic + { 'begin': 0x13A0, 'end': 0x13FF }, // Cherokee + { 'begin': 0x1400, 'end': 0x167F }, // Unified Canadian Aboriginal Syllabics + { 'begin': 0x1680, 'end': 0x169F }, // Ogham + { 'begin': 0x16A0, 'end': 0x16FF }, // Runic + { 'begin': 0x1780, 'end': 0x17FF }, // Khmer + { 'begin': 0x1800, 'end': 0x18AF }, // Mongolian + { 'begin': 0x2800, 'end': 0x28FF }, // Braille Patterns + { 'begin': 0xA000, 'end': 0xA48F }, // Yi Syllables + { 'begin': 0x1700, 'end': 0x171F }, // Tagalog + { 'begin': 0x10300, 'end': 0x1032F }, // Old Italic + { 'begin': 0x10330, 'end': 0x1034F }, // Gothic + { 'begin': 0x10400, 'end': 0x1044F }, // Deseret + { 'begin': 0x1D000, 'end': 0x1D0FF }, // Byzantine Musical Symbols + { 'begin': 0x1D400, 'end': 0x1D7FF }, // Mathematical Alphanumeric Symbols + { 'begin': 0xFF000, 'end': 0xFFFFD }, // Private Use (plane 15) + { 'begin': 0xFE00, 'end': 0xFE0F }, // Variation Selectors + { 'begin': 0xE0000, 'end': 0xE007F }, // Tags + { 'begin': 0x1900, 'end': 0x194F }, // Limbu + { 'begin': 0x1950, 'end': 0x197F }, // Tai Le + { 'begin': 0x1980, 'end': 0x19DF }, // New Tai Lue + { 'begin': 0x1A00, 'end': 0x1A1F }, // Buginese + { 'begin': 0x2C00, 'end': 0x2C5F }, // Glagolitic + { 'begin': 0x2D30, 'end': 0x2D7F }, // Tifinagh + { 'begin': 0x4DC0, 'end': 0x4DFF }, // Yijing Hexagram Symbols + { 'begin': 0xA800, 'end': 0xA82F }, // Syloti Nagri + { 'begin': 0x10000, 'end': 0x1007F }, // Linear B Syllabary + { 'begin': 0x10140, 'end': 0x1018F }, // Ancient Greek Numbers + { 'begin': 0x10380, 'end': 0x1039F }, // Ugaritic + { 'begin': 0x103A0, 'end': 0x103DF }, // Old Persian + { 'begin': 0x10450, 'end': 0x1047F }, // Shavian + { 'begin': 0x10480, 'end': 0x104AF }, // Osmanya + { 'begin': 0x10800, 'end': 0x1083F }, // Cypriot Syllabary + { 'begin': 0x10A00, 'end': 0x10A5F }, // Kharoshthi + { 'begin': 0x1D300, 'end': 0x1D35F }, // Tai Xuan Jing Symbols + { 'begin': 0x12000, 'end': 0x123FF }, // Cuneiform + { 'begin': 0x1D360, 'end': 0x1D37F }, // Counting Rod Numerals + { 'begin': 0x1B80, 'end': 0x1BBF }, // Sundanese + { 'begin': 0x1C00, 'end': 0x1C4F }, // Lepcha + { 'begin': 0x1C50, 'end': 0x1C7F }, // Ol Chiki + { 'begin': 0xA880, 'end': 0xA8DF }, // Saurashtra + { 'begin': 0xA900, 'end': 0xA92F }, // Kayah Li + { 'begin': 0xA930, 'end': 0xA95F }, // Rejang + { 'begin': 0xAA00, 'end': 0xAA5F }, // Cham + { 'begin': 0x10190, 'end': 0x101CF }, // Ancient Symbols + { 'begin': 0x101D0, 'end': 0x101FF }, // Phaistos Disc + { 'begin': 0x102A0, 'end': 0x102DF }, // Carian + { 'begin': 0x1F030, 'end': 0x1F09F } // Domino Tiles +]; + +var MacStandardGlyphOrdering = [ + '.notdef', '.null', 'nonmarkingreturn', 'space', 'exclam', 'quotedbl', + 'numbersign', 'dollar', 'percent', 'ampersand', 'quotesingle', 'parenleft', + 'parenright', 'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash', + 'zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', + 'nine', 'colon', 'semicolon', 'less', 'equal', 'greater', 'question', 'at', + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', + 'backslash', 'bracketright', 'asciicircum', 'underscore', 'grave', 'a', 'b', + 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', + 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', + 'asciitilde', 'Adieresis', 'Aring', 'Ccedilla', 'Eacute', 'Ntilde', + 'Odieresis', 'Udieresis', 'aacute', 'agrave', 'acircumflex', 'adieresis', + 'atilde', 'aring', 'ccedilla', 'eacute', 'egrave', 'ecircumflex', 'edieresis', + 'iacute', 'igrave', 'icircumflex', 'idieresis', 'ntilde', 'oacute', 'ograve', + 'ocircumflex', 'odieresis', 'otilde', 'uacute', 'ugrave', 'ucircumflex', + 'udieresis', 'dagger', 'degree', 'cent', 'sterling', 'section', 'bullet', + 'paragraph', 'germandbls', 'registered', 'copyright', 'trademark', 'acute', + 'dieresis', 'notequal', 'AE', 'Oslash', 'infinity', 'plusminus', 'lessequal', + 'greaterequal', 'yen', 'mu', 'partialdiff', 'summation', 'product', 'pi', + 'integral', 'ordfeminine', 'ordmasculine', 'Omega', 'ae', 'oslash', + 'questiondown', 'exclamdown', 'logicalnot', 'radical', 'florin', + 'approxequal', 'Delta', 'guillemotleft', 'guillemotright', 'ellipsis', + 'nonbreakingspace', 'Agrave', 'Atilde', 'Otilde', 'OE', 'oe', 'endash', + 'emdash', 'quotedblleft', 'quotedblright', 'quoteleft', 'quoteright', + 'divide', 'lozenge', 'ydieresis', 'Ydieresis', 'fraction', 'currency', + 'guilsinglleft', 'guilsinglright', 'fi', 'fl', 'daggerdbl', 'periodcentered', + 'quotesinglbase', 'quotedblbase', 'perthousand', 'Acircumflex', + 'Ecircumflex', 'Aacute', 'Edieresis', 'Egrave', 'Iacute', 'Icircumflex', + 'Idieresis', 'Igrave', 'Oacute', 'Ocircumflex', 'apple', 'Ograve', 'Uacute', + 'Ucircumflex', 'Ugrave', 'dotlessi', 'circumflex', 'tilde', 'macron', + 'breve', 'dotaccent', 'ring', 'cedilla', 'hungarumlaut', 'ogonek', 'caron', + 'Lslash', 'lslash', 'Scaron', 'scaron', 'Zcaron', 'zcaron', 'brokenbar', + 'Eth', 'eth', 'Yacute', 'yacute', 'Thorn', 'thorn', 'minus', 'multiply', + 'onesuperior', 'twosuperior', 'threesuperior', 'onehalf', 'onequarter', + 'threequarters', 'franc', 'Gbreve', 'gbreve', 'Idotaccent', 'Scedilla', + 'scedilla', 'Cacute', 'cacute', 'Ccaron', 'ccaron', 'dcroat']; + +function getUnicodeRangeFor(value) { + for (var i = 0, ii = UnicodeRanges.length; i < ii; i++) { + var range = UnicodeRanges[i]; + if (value >= range.begin && value < range.end) + return i; + } + return -1; +} + +function isRTLRangeFor(value) { + var range = UnicodeRanges[13]; + if (value >= range.begin && value < range.end) + return true; + range = UnicodeRanges[11]; + if (value >= range.begin && value < range.end) + return true; + return false; +} + +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 = { + '\u00A8': '\u0020\u0308', + '\u00AF': '\u0020\u0304', + '\u00B4': '\u0020\u0301', + '\u00B5': '\u03BC', + '\u00B8': '\u0020\u0327', + '\u0132': '\u0049\u004A', + '\u0133': '\u0069\u006A', + '\u013F': '\u004C\u00B7', + '\u0140': '\u006C\u00B7', + '\u0149': '\u02BC\u006E', + '\u017F': '\u0073', + '\u01C4': '\u0044\u017D', + '\u01C5': '\u0044\u017E', + '\u01C6': '\u0064\u017E', + '\u01C7': '\u004C\u004A', + '\u01C8': '\u004C\u006A', + '\u01C9': '\u006C\u006A', + '\u01CA': '\u004E\u004A', + '\u01CB': '\u004E\u006A', + '\u01CC': '\u006E\u006A', + '\u01F1': '\u0044\u005A', + '\u01F2': '\u0044\u007A', + '\u01F3': '\u0064\u007A', + '\u02D8': '\u0020\u0306', + '\u02D9': '\u0020\u0307', + '\u02DA': '\u0020\u030A', + '\u02DB': '\u0020\u0328', + '\u02DC': '\u0020\u0303', + '\u02DD': '\u0020\u030B', + '\u037A': '\u0020\u0345', + '\u0384': '\u0020\u0301', + '\u03D0': '\u03B2', + '\u03D1': '\u03B8', + '\u03D2': '\u03A5', + '\u03D5': '\u03C6', + '\u03D6': '\u03C0', + '\u03F0': '\u03BA', + '\u03F1': '\u03C1', + '\u03F2': '\u03C2', + '\u03F4': '\u0398', + '\u03F5': '\u03B5', + '\u03F9': '\u03A3', + '\u0587': '\u0565\u0582', + '\u0675': '\u0627\u0674', + '\u0676': '\u0648\u0674', + '\u0677': '\u06C7\u0674', + '\u0678': '\u064A\u0674', + '\u0E33': '\u0E4D\u0E32', + '\u0EB3': '\u0ECD\u0EB2', + '\u0EDC': '\u0EAB\u0E99', + '\u0EDD': '\u0EAB\u0EA1', + '\u0F77': '\u0FB2\u0F81', + '\u0F79': '\u0FB3\u0F81', + '\u1E9A': '\u0061\u02BE', + '\u1FBD': '\u0020\u0313', + '\u1FBF': '\u0020\u0313', + '\u1FC0': '\u0020\u0342', + '\u1FFE': '\u0020\u0314', + '\u2002': '\u0020', + '\u2003': '\u0020', + '\u2004': '\u0020', + '\u2005': '\u0020', + '\u2006': '\u0020', + '\u2008': '\u0020', + '\u2009': '\u0020', + '\u200A': '\u0020', + '\u2017': '\u0020\u0333', + '\u2024': '\u002E', + '\u2025': '\u002E\u002E', + '\u2026': '\u002E\u002E\u002E', + '\u2033': '\u2032\u2032', + '\u2034': '\u2032\u2032\u2032', + '\u2036': '\u2035\u2035', + '\u2037': '\u2035\u2035\u2035', + '\u203C': '\u0021\u0021', + '\u203E': '\u0020\u0305', + '\u2047': '\u003F\u003F', + '\u2048': '\u003F\u0021', + '\u2049': '\u0021\u003F', + '\u2057': '\u2032\u2032\u2032\u2032', + '\u205F': '\u0020', + '\u20A8': '\u0052\u0073', + '\u2100': '\u0061\u002F\u0063', + '\u2101': '\u0061\u002F\u0073', + '\u2103': '\u00B0\u0043', + '\u2105': '\u0063\u002F\u006F', + '\u2106': '\u0063\u002F\u0075', + '\u2107': '\u0190', + '\u2109': '\u00B0\u0046', + '\u2116': '\u004E\u006F', + '\u2121': '\u0054\u0045\u004C', + '\u2135': '\u05D0', + '\u2136': '\u05D1', + '\u2137': '\u05D2', + '\u2138': '\u05D3', + '\u213B': '\u0046\u0041\u0058', + '\u2160': '\u0049', + '\u2161': '\u0049\u0049', + '\u2162': '\u0049\u0049\u0049', + '\u2163': '\u0049\u0056', + '\u2164': '\u0056', + '\u2165': '\u0056\u0049', + '\u2166': '\u0056\u0049\u0049', + '\u2167': '\u0056\u0049\u0049\u0049', + '\u2168': '\u0049\u0058', + '\u2169': '\u0058', + '\u216A': '\u0058\u0049', + '\u216B': '\u0058\u0049\u0049', + '\u216C': '\u004C', + '\u216D': '\u0043', + '\u216E': '\u0044', + '\u216F': '\u004D', + '\u2170': '\u0069', + '\u2171': '\u0069\u0069', + '\u2172': '\u0069\u0069\u0069', + '\u2173': '\u0069\u0076', + '\u2174': '\u0076', + '\u2175': '\u0076\u0069', + '\u2176': '\u0076\u0069\u0069', + '\u2177': '\u0076\u0069\u0069\u0069', + '\u2178': '\u0069\u0078', + '\u2179': '\u0078', + '\u217A': '\u0078\u0069', + '\u217B': '\u0078\u0069\u0069', + '\u217C': '\u006C', + '\u217D': '\u0063', + '\u217E': '\u0064', + '\u217F': '\u006D', + '\u222C': '\u222B\u222B', + '\u222D': '\u222B\u222B\u222B', + '\u222F': '\u222E\u222E', + '\u2230': '\u222E\u222E\u222E', + '\u2474': '\u0028\u0031\u0029', + '\u2475': '\u0028\u0032\u0029', + '\u2476': '\u0028\u0033\u0029', + '\u2477': '\u0028\u0034\u0029', + '\u2478': '\u0028\u0035\u0029', + '\u2479': '\u0028\u0036\u0029', + '\u247A': '\u0028\u0037\u0029', + '\u247B': '\u0028\u0038\u0029', + '\u247C': '\u0028\u0039\u0029', + '\u247D': '\u0028\u0031\u0030\u0029', + '\u247E': '\u0028\u0031\u0031\u0029', + '\u247F': '\u0028\u0031\u0032\u0029', + '\u2480': '\u0028\u0031\u0033\u0029', + '\u2481': '\u0028\u0031\u0034\u0029', + '\u2482': '\u0028\u0031\u0035\u0029', + '\u2483': '\u0028\u0031\u0036\u0029', + '\u2484': '\u0028\u0031\u0037\u0029', + '\u2485': '\u0028\u0031\u0038\u0029', + '\u2486': '\u0028\u0031\u0039\u0029', + '\u2487': '\u0028\u0032\u0030\u0029', + '\u2488': '\u0031\u002E', + '\u2489': '\u0032\u002E', + '\u248A': '\u0033\u002E', + '\u248B': '\u0034\u002E', + '\u248C': '\u0035\u002E', + '\u248D': '\u0036\u002E', + '\u248E': '\u0037\u002E', + '\u248F': '\u0038\u002E', + '\u2490': '\u0039\u002E', + '\u2491': '\u0031\u0030\u002E', + '\u2492': '\u0031\u0031\u002E', + '\u2493': '\u0031\u0032\u002E', + '\u2494': '\u0031\u0033\u002E', + '\u2495': '\u0031\u0034\u002E', + '\u2496': '\u0031\u0035\u002E', + '\u2497': '\u0031\u0036\u002E', + '\u2498': '\u0031\u0037\u002E', + '\u2499': '\u0031\u0038\u002E', + '\u249A': '\u0031\u0039\u002E', + '\u249B': '\u0032\u0030\u002E', + '\u249C': '\u0028\u0061\u0029', + '\u249D': '\u0028\u0062\u0029', + '\u249E': '\u0028\u0063\u0029', + '\u249F': '\u0028\u0064\u0029', + '\u24A0': '\u0028\u0065\u0029', + '\u24A1': '\u0028\u0066\u0029', + '\u24A2': '\u0028\u0067\u0029', + '\u24A3': '\u0028\u0068\u0029', + '\u24A4': '\u0028\u0069\u0029', + '\u24A5': '\u0028\u006A\u0029', + '\u24A6': '\u0028\u006B\u0029', + '\u24A7': '\u0028\u006C\u0029', + '\u24A8': '\u0028\u006D\u0029', + '\u24A9': '\u0028\u006E\u0029', + '\u24AA': '\u0028\u006F\u0029', + '\u24AB': '\u0028\u0070\u0029', + '\u24AC': '\u0028\u0071\u0029', + '\u24AD': '\u0028\u0072\u0029', + '\u24AE': '\u0028\u0073\u0029', + '\u24AF': '\u0028\u0074\u0029', + '\u24B0': '\u0028\u0075\u0029', + '\u24B1': '\u0028\u0076\u0029', + '\u24B2': '\u0028\u0077\u0029', + '\u24B3': '\u0028\u0078\u0029', + '\u24B4': '\u0028\u0079\u0029', + '\u24B5': '\u0028\u007A\u0029', + '\u2A0C': '\u222B\u222B\u222B\u222B', + '\u2A74': '\u003A\u003A\u003D', + '\u2A75': '\u003D\u003D', + '\u2A76': '\u003D\u003D\u003D', + '\u2E9F': '\u6BCD', + '\u2EF3': '\u9F9F', + '\u2F00': '\u4E00', + '\u2F01': '\u4E28', + '\u2F02': '\u4E36', + '\u2F03': '\u4E3F', + '\u2F04': '\u4E59', + '\u2F05': '\u4E85', + '\u2F06': '\u4E8C', + '\u2F07': '\u4EA0', + '\u2F08': '\u4EBA', + '\u2F09': '\u513F', + '\u2F0A': '\u5165', + '\u2F0B': '\u516B', + '\u2F0C': '\u5182', + '\u2F0D': '\u5196', + '\u2F0E': '\u51AB', + '\u2F0F': '\u51E0', + '\u2F10': '\u51F5', + '\u2F11': '\u5200', + '\u2F12': '\u529B', + '\u2F13': '\u52F9', + '\u2F14': '\u5315', + '\u2F15': '\u531A', + '\u2F16': '\u5338', + '\u2F17': '\u5341', + '\u2F18': '\u535C', + '\u2F19': '\u5369', + '\u2F1A': '\u5382', + '\u2F1B': '\u53B6', + '\u2F1C': '\u53C8', + '\u2F1D': '\u53E3', + '\u2F1E': '\u56D7', + '\u2F1F': '\u571F', + '\u2F20': '\u58EB', + '\u2F21': '\u5902', + '\u2F22': '\u590A', + '\u2F23': '\u5915', + '\u2F24': '\u5927', + '\u2F25': '\u5973', + '\u2F26': '\u5B50', + '\u2F27': '\u5B80', + '\u2F28': '\u5BF8', + '\u2F29': '\u5C0F', + '\u2F2A': '\u5C22', + '\u2F2B': '\u5C38', + '\u2F2C': '\u5C6E', + '\u2F2D': '\u5C71', + '\u2F2E': '\u5DDB', + '\u2F2F': '\u5DE5', + '\u2F30': '\u5DF1', + '\u2F31': '\u5DFE', + '\u2F32': '\u5E72', + '\u2F33': '\u5E7A', + '\u2F34': '\u5E7F', + '\u2F35': '\u5EF4', + '\u2F36': '\u5EFE', + '\u2F37': '\u5F0B', + '\u2F38': '\u5F13', + '\u2F39': '\u5F50', + '\u2F3A': '\u5F61', + '\u2F3B': '\u5F73', + '\u2F3C': '\u5FC3', + '\u2F3D': '\u6208', + '\u2F3E': '\u6236', + '\u2F3F': '\u624B', + '\u2F40': '\u652F', + '\u2F41': '\u6534', + '\u2F42': '\u6587', + '\u2F43': '\u6597', + '\u2F44': '\u65A4', + '\u2F45': '\u65B9', + '\u2F46': '\u65E0', + '\u2F47': '\u65E5', + '\u2F48': '\u66F0', + '\u2F49': '\u6708', + '\u2F4A': '\u6728', + '\u2F4B': '\u6B20', + '\u2F4C': '\u6B62', + '\u2F4D': '\u6B79', + '\u2F4E': '\u6BB3', + '\u2F4F': '\u6BCB', + '\u2F50': '\u6BD4', + '\u2F51': '\u6BDB', + '\u2F52': '\u6C0F', + '\u2F53': '\u6C14', + '\u2F54': '\u6C34', + '\u2F55': '\u706B', + '\u2F56': '\u722A', + '\u2F57': '\u7236', + '\u2F58': '\u723B', + '\u2F59': '\u723F', + '\u2F5A': '\u7247', + '\u2F5B': '\u7259', + '\u2F5C': '\u725B', + '\u2F5D': '\u72AC', + '\u2F5E': '\u7384', + '\u2F5F': '\u7389', + '\u2F60': '\u74DC', + '\u2F61': '\u74E6', + '\u2F62': '\u7518', + '\u2F63': '\u751F', + '\u2F64': '\u7528', + '\u2F65': '\u7530', + '\u2F66': '\u758B', + '\u2F67': '\u7592', + '\u2F68': '\u7676', + '\u2F69': '\u767D', + '\u2F6A': '\u76AE', + '\u2F6B': '\u76BF', + '\u2F6C': '\u76EE', + '\u2F6D': '\u77DB', + '\u2F6E': '\u77E2', + '\u2F6F': '\u77F3', + '\u2F70': '\u793A', + '\u2F71': '\u79B8', + '\u2F72': '\u79BE', + '\u2F73': '\u7A74', + '\u2F74': '\u7ACB', + '\u2F75': '\u7AF9', + '\u2F76': '\u7C73', + '\u2F77': '\u7CF8', + '\u2F78': '\u7F36', + '\u2F79': '\u7F51', + '\u2F7A': '\u7F8A', + '\u2F7B': '\u7FBD', + '\u2F7C': '\u8001', + '\u2F7D': '\u800C', + '\u2F7E': '\u8012', + '\u2F7F': '\u8033', + '\u2F80': '\u807F', + '\u2F81': '\u8089', + '\u2F82': '\u81E3', + '\u2F83': '\u81EA', + '\u2F84': '\u81F3', + '\u2F85': '\u81FC', + '\u2F86': '\u820C', + '\u2F87': '\u821B', + '\u2F88': '\u821F', + '\u2F89': '\u826E', + '\u2F8A': '\u8272', + '\u2F8B': '\u8278', + '\u2F8C': '\u864D', + '\u2F8D': '\u866B', + '\u2F8E': '\u8840', + '\u2F8F': '\u884C', + '\u2F90': '\u8863', + '\u2F91': '\u897E', + '\u2F92': '\u898B', + '\u2F93': '\u89D2', + '\u2F94': '\u8A00', + '\u2F95': '\u8C37', + '\u2F96': '\u8C46', + '\u2F97': '\u8C55', + '\u2F98': '\u8C78', + '\u2F99': '\u8C9D', + '\u2F9A': '\u8D64', + '\u2F9B': '\u8D70', + '\u2F9C': '\u8DB3', + '\u2F9D': '\u8EAB', + '\u2F9E': '\u8ECA', + '\u2F9F': '\u8F9B', + '\u2FA0': '\u8FB0', + '\u2FA1': '\u8FB5', + '\u2FA2': '\u9091', + '\u2FA3': '\u9149', + '\u2FA4': '\u91C6', + '\u2FA5': '\u91CC', + '\u2FA6': '\u91D1', + '\u2FA7': '\u9577', + '\u2FA8': '\u9580', + '\u2FA9': '\u961C', + '\u2FAA': '\u96B6', + '\u2FAB': '\u96B9', + '\u2FAC': '\u96E8', + '\u2FAD': '\u9751', + '\u2FAE': '\u975E', + '\u2FAF': '\u9762', + '\u2FB0': '\u9769', + '\u2FB1': '\u97CB', + '\u2FB2': '\u97ED', + '\u2FB3': '\u97F3', + '\u2FB4': '\u9801', + '\u2FB5': '\u98A8', + '\u2FB6': '\u98DB', + '\u2FB7': '\u98DF', + '\u2FB8': '\u9996', + '\u2FB9': '\u9999', + '\u2FBA': '\u99AC', + '\u2FBB': '\u9AA8', + '\u2FBC': '\u9AD8', + '\u2FBD': '\u9ADF', + '\u2FBE': '\u9B25', + '\u2FBF': '\u9B2F', + '\u2FC0': '\u9B32', + '\u2FC1': '\u9B3C', + '\u2FC2': '\u9B5A', + '\u2FC3': '\u9CE5', + '\u2FC4': '\u9E75', + '\u2FC5': '\u9E7F', + '\u2FC6': '\u9EA5', + '\u2FC7': '\u9EBB', + '\u2FC8': '\u9EC3', + '\u2FC9': '\u9ECD', + '\u2FCA': '\u9ED1', + '\u2FCB': '\u9EF9', + '\u2FCC': '\u9EFD', + '\u2FCD': '\u9F0E', + '\u2FCE': '\u9F13', + '\u2FCF': '\u9F20', + '\u2FD0': '\u9F3B', + '\u2FD1': '\u9F4A', + '\u2FD2': '\u9F52', + '\u2FD3': '\u9F8D', + '\u2FD4': '\u9F9C', + '\u2FD5': '\u9FA0', + '\u3036': '\u3012', + '\u3038': '\u5341', + '\u3039': '\u5344', + '\u303A': '\u5345', + '\u309B': '\u0020\u3099', + '\u309C': '\u0020\u309A', + '\u3131': '\u1100', + '\u3132': '\u1101', + '\u3133': '\u11AA', + '\u3134': '\u1102', + '\u3135': '\u11AC', + '\u3136': '\u11AD', + '\u3137': '\u1103', + '\u3138': '\u1104', + '\u3139': '\u1105', + '\u313A': '\u11B0', + '\u313B': '\u11B1', + '\u313C': '\u11B2', + '\u313D': '\u11B3', + '\u313E': '\u11B4', + '\u313F': '\u11B5', + '\u3140': '\u111A', + '\u3141': '\u1106', + '\u3142': '\u1107', + '\u3143': '\u1108', + '\u3144': '\u1121', + '\u3145': '\u1109', + '\u3146': '\u110A', + '\u3147': '\u110B', + '\u3148': '\u110C', + '\u3149': '\u110D', + '\u314A': '\u110E', + '\u314B': '\u110F', + '\u314C': '\u1110', + '\u314D': '\u1111', + '\u314E': '\u1112', + '\u314F': '\u1161', + '\u3150': '\u1162', + '\u3151': '\u1163', + '\u3152': '\u1164', + '\u3153': '\u1165', + '\u3154': '\u1166', + '\u3155': '\u1167', + '\u3156': '\u1168', + '\u3157': '\u1169', + '\u3158': '\u116A', + '\u3159': '\u116B', + '\u315A': '\u116C', + '\u315B': '\u116D', + '\u315C': '\u116E', + '\u315D': '\u116F', + '\u315E': '\u1170', + '\u315F': '\u1171', + '\u3160': '\u1172', + '\u3161': '\u1173', + '\u3162': '\u1174', + '\u3163': '\u1175', + '\u3164': '\u1160', + '\u3165': '\u1114', + '\u3166': '\u1115', + '\u3167': '\u11C7', + '\u3168': '\u11C8', + '\u3169': '\u11CC', + '\u316A': '\u11CE', + '\u316B': '\u11D3', + '\u316C': '\u11D7', + '\u316D': '\u11D9', + '\u316E': '\u111C', + '\u316F': '\u11DD', + '\u3170': '\u11DF', + '\u3171': '\u111D', + '\u3172': '\u111E', + '\u3173': '\u1120', + '\u3174': '\u1122', + '\u3175': '\u1123', + '\u3176': '\u1127', + '\u3177': '\u1129', + '\u3178': '\u112B', + '\u3179': '\u112C', + '\u317A': '\u112D', + '\u317B': '\u112E', + '\u317C': '\u112F', + '\u317D': '\u1132', + '\u317E': '\u1136', + '\u317F': '\u1140', + '\u3180': '\u1147', + '\u3181': '\u114C', + '\u3182': '\u11F1', + '\u3183': '\u11F2', + '\u3184': '\u1157', + '\u3185': '\u1158', + '\u3186': '\u1159', + '\u3187': '\u1184', + '\u3188': '\u1185', + '\u3189': '\u1188', + '\u318A': '\u1191', + '\u318B': '\u1192', + '\u318C': '\u1194', + '\u318D': '\u119E', + '\u318E': '\u11A1', + '\u3200': '\u0028\u1100\u0029', + '\u3201': '\u0028\u1102\u0029', + '\u3202': '\u0028\u1103\u0029', + '\u3203': '\u0028\u1105\u0029', + '\u3204': '\u0028\u1106\u0029', + '\u3205': '\u0028\u1107\u0029', + '\u3206': '\u0028\u1109\u0029', + '\u3207': '\u0028\u110B\u0029', + '\u3208': '\u0028\u110C\u0029', + '\u3209': '\u0028\u110E\u0029', + '\u320A': '\u0028\u110F\u0029', + '\u320B': '\u0028\u1110\u0029', + '\u320C': '\u0028\u1111\u0029', + '\u320D': '\u0028\u1112\u0029', + '\u320E': '\u0028\u1100\u1161\u0029', + '\u320F': '\u0028\u1102\u1161\u0029', + '\u3210': '\u0028\u1103\u1161\u0029', + '\u3211': '\u0028\u1105\u1161\u0029', + '\u3212': '\u0028\u1106\u1161\u0029', + '\u3213': '\u0028\u1107\u1161\u0029', + '\u3214': '\u0028\u1109\u1161\u0029', + '\u3215': '\u0028\u110B\u1161\u0029', + '\u3216': '\u0028\u110C\u1161\u0029', + '\u3217': '\u0028\u110E\u1161\u0029', + '\u3218': '\u0028\u110F\u1161\u0029', + '\u3219': '\u0028\u1110\u1161\u0029', + '\u321A': '\u0028\u1111\u1161\u0029', + '\u321B': '\u0028\u1112\u1161\u0029', + '\u321C': '\u0028\u110C\u116E\u0029', + '\u321D': '\u0028\u110B\u1169\u110C\u1165\u11AB\u0029', + '\u321E': '\u0028\u110B\u1169\u1112\u116E\u0029', + '\u3220': '\u0028\u4E00\u0029', + '\u3221': '\u0028\u4E8C\u0029', + '\u3222': '\u0028\u4E09\u0029', + '\u3223': '\u0028\u56DB\u0029', + '\u3224': '\u0028\u4E94\u0029', + '\u3225': '\u0028\u516D\u0029', + '\u3226': '\u0028\u4E03\u0029', + '\u3227': '\u0028\u516B\u0029', + '\u3228': '\u0028\u4E5D\u0029', + '\u3229': '\u0028\u5341\u0029', + '\u322A': '\u0028\u6708\u0029', + '\u322B': '\u0028\u706B\u0029', + '\u322C': '\u0028\u6C34\u0029', + '\u322D': '\u0028\u6728\u0029', + '\u322E': '\u0028\u91D1\u0029', + '\u322F': '\u0028\u571F\u0029', + '\u3230': '\u0028\u65E5\u0029', + '\u3231': '\u0028\u682A\u0029', + '\u3232': '\u0028\u6709\u0029', + '\u3233': '\u0028\u793E\u0029', + '\u3234': '\u0028\u540D\u0029', + '\u3235': '\u0028\u7279\u0029', + '\u3236': '\u0028\u8CA1\u0029', + '\u3237': '\u0028\u795D\u0029', + '\u3238': '\u0028\u52B4\u0029', + '\u3239': '\u0028\u4EE3\u0029', + '\u323A': '\u0028\u547C\u0029', + '\u323B': '\u0028\u5B66\u0029', + '\u323C': '\u0028\u76E3\u0029', + '\u323D': '\u0028\u4F01\u0029', + '\u323E': '\u0028\u8CC7\u0029', + '\u323F': '\u0028\u5354\u0029', + '\u3240': '\u0028\u796D\u0029', + '\u3241': '\u0028\u4F11\u0029', + '\u3242': '\u0028\u81EA\u0029', + '\u3243': '\u0028\u81F3\u0029', + '\u32C0': '\u0031\u6708', + '\u32C1': '\u0032\u6708', + '\u32C2': '\u0033\u6708', + '\u32C3': '\u0034\u6708', + '\u32C4': '\u0035\u6708', + '\u32C5': '\u0036\u6708', + '\u32C6': '\u0037\u6708', + '\u32C7': '\u0038\u6708', + '\u32C8': '\u0039\u6708', + '\u32C9': '\u0031\u0030\u6708', + '\u32CA': '\u0031\u0031\u6708', + '\u32CB': '\u0031\u0032\u6708', + '\u3358': '\u0030\u70B9', + '\u3359': '\u0031\u70B9', + '\u335A': '\u0032\u70B9', + '\u335B': '\u0033\u70B9', + '\u335C': '\u0034\u70B9', + '\u335D': '\u0035\u70B9', + '\u335E': '\u0036\u70B9', + '\u335F': '\u0037\u70B9', + '\u3360': '\u0038\u70B9', + '\u3361': '\u0039\u70B9', + '\u3362': '\u0031\u0030\u70B9', + '\u3363': '\u0031\u0031\u70B9', + '\u3364': '\u0031\u0032\u70B9', + '\u3365': '\u0031\u0033\u70B9', + '\u3366': '\u0031\u0034\u70B9', + '\u3367': '\u0031\u0035\u70B9', + '\u3368': '\u0031\u0036\u70B9', + '\u3369': '\u0031\u0037\u70B9', + '\u336A': '\u0031\u0038\u70B9', + '\u336B': '\u0031\u0039\u70B9', + '\u336C': '\u0032\u0030\u70B9', + '\u336D': '\u0032\u0031\u70B9', + '\u336E': '\u0032\u0032\u70B9', + '\u336F': '\u0032\u0033\u70B9', + '\u3370': '\u0032\u0034\u70B9', + '\u33E0': '\u0031\u65E5', + '\u33E1': '\u0032\u65E5', + '\u33E2': '\u0033\u65E5', + '\u33E3': '\u0034\u65E5', + '\u33E4': '\u0035\u65E5', + '\u33E5': '\u0036\u65E5', + '\u33E6': '\u0037\u65E5', + '\u33E7': '\u0038\u65E5', + '\u33E8': '\u0039\u65E5', + '\u33E9': '\u0031\u0030\u65E5', + '\u33EA': '\u0031\u0031\u65E5', + '\u33EB': '\u0031\u0032\u65E5', + '\u33EC': '\u0031\u0033\u65E5', + '\u33ED': '\u0031\u0034\u65E5', + '\u33EE': '\u0031\u0035\u65E5', + '\u33EF': '\u0031\u0036\u65E5', + '\u33F0': '\u0031\u0037\u65E5', + '\u33F1': '\u0031\u0038\u65E5', + '\u33F2': '\u0031\u0039\u65E5', + '\u33F3': '\u0032\u0030\u65E5', + '\u33F4': '\u0032\u0031\u65E5', + '\u33F5': '\u0032\u0032\u65E5', + '\u33F6': '\u0032\u0033\u65E5', + '\u33F7': '\u0032\u0034\u65E5', + '\u33F8': '\u0032\u0035\u65E5', + '\u33F9': '\u0032\u0036\u65E5', + '\u33FA': '\u0032\u0037\u65E5', + '\u33FB': '\u0032\u0038\u65E5', + '\u33FC': '\u0032\u0039\u65E5', + '\u33FD': '\u0033\u0030\u65E5', + '\u33FE': '\u0033\u0031\u65E5', + '\uFB00': '\u0066\u0066', + '\uFB01': '\u0066\u0069', + '\uFB02': '\u0066\u006C', + '\uFB03': '\u0066\u0066\u0069', + '\uFB04': '\u0066\u0066\u006C', + '\uFB05': '\u017F\u0074', + '\uFB06': '\u0073\u0074', + '\uFB13': '\u0574\u0576', + '\uFB14': '\u0574\u0565', + '\uFB15': '\u0574\u056B', + '\uFB16': '\u057E\u0576', + '\uFB17': '\u0574\u056D', + '\uFB4F': '\u05D0\u05DC', + '\uFB50': '\u0671', + '\uFB51': '\u0671', + '\uFB52': '\u067B', + '\uFB53': '\u067B', + '\uFB54': '\u067B', + '\uFB55': '\u067B', + '\uFB56': '\u067E', + '\uFB57': '\u067E', + '\uFB58': '\u067E', + '\uFB59': '\u067E', + '\uFB5A': '\u0680', + '\uFB5B': '\u0680', + '\uFB5C': '\u0680', + '\uFB5D': '\u0680', + '\uFB5E': '\u067A', + '\uFB5F': '\u067A', + '\uFB60': '\u067A', + '\uFB61': '\u067A', + '\uFB62': '\u067F', + '\uFB63': '\u067F', + '\uFB64': '\u067F', + '\uFB65': '\u067F', + '\uFB66': '\u0679', + '\uFB67': '\u0679', + '\uFB68': '\u0679', + '\uFB69': '\u0679', + '\uFB6A': '\u06A4', + '\uFB6B': '\u06A4', + '\uFB6C': '\u06A4', + '\uFB6D': '\u06A4', + '\uFB6E': '\u06A6', + '\uFB6F': '\u06A6', + '\uFB70': '\u06A6', + '\uFB71': '\u06A6', + '\uFB72': '\u0684', + '\uFB73': '\u0684', + '\uFB74': '\u0684', + '\uFB75': '\u0684', + '\uFB76': '\u0683', + '\uFB77': '\u0683', + '\uFB78': '\u0683', + '\uFB79': '\u0683', + '\uFB7A': '\u0686', + '\uFB7B': '\u0686', + '\uFB7C': '\u0686', + '\uFB7D': '\u0686', + '\uFB7E': '\u0687', + '\uFB7F': '\u0687', + '\uFB80': '\u0687', + '\uFB81': '\u0687', + '\uFB82': '\u068D', + '\uFB83': '\u068D', + '\uFB84': '\u068C', + '\uFB85': '\u068C', + '\uFB86': '\u068E', + '\uFB87': '\u068E', + '\uFB88': '\u0688', + '\uFB89': '\u0688', + '\uFB8A': '\u0698', + '\uFB8B': '\u0698', + '\uFB8C': '\u0691', + '\uFB8D': '\u0691', + '\uFB8E': '\u06A9', + '\uFB8F': '\u06A9', + '\uFB90': '\u06A9', + '\uFB91': '\u06A9', + '\uFB92': '\u06AF', + '\uFB93': '\u06AF', + '\uFB94': '\u06AF', + '\uFB95': '\u06AF', + '\uFB96': '\u06B3', + '\uFB97': '\u06B3', + '\uFB98': '\u06B3', + '\uFB99': '\u06B3', + '\uFB9A': '\u06B1', + '\uFB9B': '\u06B1', + '\uFB9C': '\u06B1', + '\uFB9D': '\u06B1', + '\uFB9E': '\u06BA', + '\uFB9F': '\u06BA', + '\uFBA0': '\u06BB', + '\uFBA1': '\u06BB', + '\uFBA2': '\u06BB', + '\uFBA3': '\u06BB', + '\uFBA4': '\u06C0', + '\uFBA5': '\u06C0', + '\uFBA6': '\u06C1', + '\uFBA7': '\u06C1', + '\uFBA8': '\u06C1', + '\uFBA9': '\u06C1', + '\uFBAA': '\u06BE', + '\uFBAB': '\u06BE', + '\uFBAC': '\u06BE', + '\uFBAD': '\u06BE', + '\uFBAE': '\u06D2', + '\uFBAF': '\u06D2', + '\uFBB0': '\u06D3', + '\uFBB1': '\u06D3', + '\uFBD3': '\u06AD', + '\uFBD4': '\u06AD', + '\uFBD5': '\u06AD', + '\uFBD6': '\u06AD', + '\uFBD7': '\u06C7', + '\uFBD8': '\u06C7', + '\uFBD9': '\u06C6', + '\uFBDA': '\u06C6', + '\uFBDB': '\u06C8', + '\uFBDC': '\u06C8', + '\uFBDD': '\u0677', + '\uFBDE': '\u06CB', + '\uFBDF': '\u06CB', + '\uFBE0': '\u06C5', + '\uFBE1': '\u06C5', + '\uFBE2': '\u06C9', + '\uFBE3': '\u06C9', + '\uFBE4': '\u06D0', + '\uFBE5': '\u06D0', + '\uFBE6': '\u06D0', + '\uFBE7': '\u06D0', + '\uFBE8': '\u0649', + '\uFBE9': '\u0649', + '\uFBEA': '\u0626\u0627', + '\uFBEB': '\u0626\u0627', + '\uFBEC': '\u0626\u06D5', + '\uFBED': '\u0626\u06D5', + '\uFBEE': '\u0626\u0648', + '\uFBEF': '\u0626\u0648', + '\uFBF0': '\u0626\u06C7', + '\uFBF1': '\u0626\u06C7', + '\uFBF2': '\u0626\u06C6', + '\uFBF3': '\u0626\u06C6', + '\uFBF4': '\u0626\u06C8', + '\uFBF5': '\u0626\u06C8', + '\uFBF6': '\u0626\u06D0', + '\uFBF7': '\u0626\u06D0', + '\uFBF8': '\u0626\u06D0', + '\uFBF9': '\u0626\u0649', + '\uFBFA': '\u0626\u0649', + '\uFBFB': '\u0626\u0649', + '\uFBFC': '\u06CC', + '\uFBFD': '\u06CC', + '\uFBFE': '\u06CC', + '\uFBFF': '\u06CC', + '\uFC00': '\u0626\u062C', + '\uFC01': '\u0626\u062D', + '\uFC02': '\u0626\u0645', + '\uFC03': '\u0626\u0649', + '\uFC04': '\u0626\u064A', + '\uFC05': '\u0628\u062C', + '\uFC06': '\u0628\u062D', + '\uFC07': '\u0628\u062E', + '\uFC08': '\u0628\u0645', + '\uFC09': '\u0628\u0649', + '\uFC0A': '\u0628\u064A', + '\uFC0B': '\u062A\u062C', + '\uFC0C': '\u062A\u062D', + '\uFC0D': '\u062A\u062E', + '\uFC0E': '\u062A\u0645', + '\uFC0F': '\u062A\u0649', + '\uFC10': '\u062A\u064A', + '\uFC11': '\u062B\u062C', + '\uFC12': '\u062B\u0645', + '\uFC13': '\u062B\u0649', + '\uFC14': '\u062B\u064A', + '\uFC15': '\u062C\u062D', + '\uFC16': '\u062C\u0645', + '\uFC17': '\u062D\u062C', + '\uFC18': '\u062D\u0645', + '\uFC19': '\u062E\u062C', + '\uFC1A': '\u062E\u062D', + '\uFC1B': '\u062E\u0645', + '\uFC1C': '\u0633\u062C', + '\uFC1D': '\u0633\u062D', + '\uFC1E': '\u0633\u062E', + '\uFC1F': '\u0633\u0645', + '\uFC20': '\u0635\u062D', + '\uFC21': '\u0635\u0645', + '\uFC22': '\u0636\u062C', + '\uFC23': '\u0636\u062D', + '\uFC24': '\u0636\u062E', + '\uFC25': '\u0636\u0645', + '\uFC26': '\u0637\u062D', + '\uFC27': '\u0637\u0645', + '\uFC28': '\u0638\u0645', + '\uFC29': '\u0639\u062C', + '\uFC2A': '\u0639\u0645', + '\uFC2B': '\u063A\u062C', + '\uFC2C': '\u063A\u0645', + '\uFC2D': '\u0641\u062C', + '\uFC2E': '\u0641\u062D', + '\uFC2F': '\u0641\u062E', + '\uFC30': '\u0641\u0645', + '\uFC31': '\u0641\u0649', + '\uFC32': '\u0641\u064A', + '\uFC33': '\u0642\u062D', + '\uFC34': '\u0642\u0645', + '\uFC35': '\u0642\u0649', + '\uFC36': '\u0642\u064A', + '\uFC37': '\u0643\u0627', + '\uFC38': '\u0643\u062C', + '\uFC39': '\u0643\u062D', + '\uFC3A': '\u0643\u062E', + '\uFC3B': '\u0643\u0644', + '\uFC3C': '\u0643\u0645', + '\uFC3D': '\u0643\u0649', + '\uFC3E': '\u0643\u064A', + '\uFC3F': '\u0644\u062C', + '\uFC40': '\u0644\u062D', + '\uFC41': '\u0644\u062E', + '\uFC42': '\u0644\u0645', + '\uFC43': '\u0644\u0649', + '\uFC44': '\u0644\u064A', + '\uFC45': '\u0645\u062C', + '\uFC46': '\u0645\u062D', + '\uFC47': '\u0645\u062E', + '\uFC48': '\u0645\u0645', + '\uFC49': '\u0645\u0649', + '\uFC4A': '\u0645\u064A', + '\uFC4B': '\u0646\u062C', + '\uFC4C': '\u0646\u062D', + '\uFC4D': '\u0646\u062E', + '\uFC4E': '\u0646\u0645', + '\uFC4F': '\u0646\u0649', + '\uFC50': '\u0646\u064A', + '\uFC51': '\u0647\u062C', + '\uFC52': '\u0647\u0645', + '\uFC53': '\u0647\u0649', + '\uFC54': '\u0647\u064A', + '\uFC55': '\u064A\u062C', + '\uFC56': '\u064A\u062D', + '\uFC57': '\u064A\u062E', + '\uFC58': '\u064A\u0645', + '\uFC59': '\u064A\u0649', + '\uFC5A': '\u064A\u064A', + '\uFC5B': '\u0630\u0670', + '\uFC5C': '\u0631\u0670', + '\uFC5D': '\u0649\u0670', + '\uFC5E': '\u0020\u064C\u0651', + '\uFC5F': '\u0020\u064D\u0651', + '\uFC60': '\u0020\u064E\u0651', + '\uFC61': '\u0020\u064F\u0651', + '\uFC62': '\u0020\u0650\u0651', + '\uFC63': '\u0020\u0651\u0670', + '\uFC64': '\u0626\u0631', + '\uFC65': '\u0626\u0632', + '\uFC66': '\u0626\u0645', + '\uFC67': '\u0626\u0646', + '\uFC68': '\u0626\u0649', + '\uFC69': '\u0626\u064A', + '\uFC6A': '\u0628\u0631', + '\uFC6B': '\u0628\u0632', + '\uFC6C': '\u0628\u0645', + '\uFC6D': '\u0628\u0646', + '\uFC6E': '\u0628\u0649', + '\uFC6F': '\u0628\u064A', + '\uFC70': '\u062A\u0631', + '\uFC71': '\u062A\u0632', + '\uFC72': '\u062A\u0645', + '\uFC73': '\u062A\u0646', + '\uFC74': '\u062A\u0649', + '\uFC75': '\u062A\u064A', + '\uFC76': '\u062B\u0631', + '\uFC77': '\u062B\u0632', + '\uFC78': '\u062B\u0645', + '\uFC79': '\u062B\u0646', + '\uFC7A': '\u062B\u0649', + '\uFC7B': '\u062B\u064A', + '\uFC7C': '\u0641\u0649', + '\uFC7D': '\u0641\u064A', + '\uFC7E': '\u0642\u0649', + '\uFC7F': '\u0642\u064A', + '\uFC80': '\u0643\u0627', + '\uFC81': '\u0643\u0644', + '\uFC82': '\u0643\u0645', + '\uFC83': '\u0643\u0649', + '\uFC84': '\u0643\u064A', + '\uFC85': '\u0644\u0645', + '\uFC86': '\u0644\u0649', + '\uFC87': '\u0644\u064A', + '\uFC88': '\u0645\u0627', + '\uFC89': '\u0645\u0645', + '\uFC8A': '\u0646\u0631', + '\uFC8B': '\u0646\u0632', + '\uFC8C': '\u0646\u0645', + '\uFC8D': '\u0646\u0646', + '\uFC8E': '\u0646\u0649', + '\uFC8F': '\u0646\u064A', + '\uFC90': '\u0649\u0670', + '\uFC91': '\u064A\u0631', + '\uFC92': '\u064A\u0632', + '\uFC93': '\u064A\u0645', + '\uFC94': '\u064A\u0646', + '\uFC95': '\u064A\u0649', + '\uFC96': '\u064A\u064A', + '\uFC97': '\u0626\u062C', + '\uFC98': '\u0626\u062D', + '\uFC99': '\u0626\u062E', + '\uFC9A': '\u0626\u0645', + '\uFC9B': '\u0626\u0647', + '\uFC9C': '\u0628\u062C', + '\uFC9D': '\u0628\u062D', + '\uFC9E': '\u0628\u062E', + '\uFC9F': '\u0628\u0645', + '\uFCA0': '\u0628\u0647', + '\uFCA1': '\u062A\u062C', + '\uFCA2': '\u062A\u062D', + '\uFCA3': '\u062A\u062E', + '\uFCA4': '\u062A\u0645', + '\uFCA5': '\u062A\u0647', + '\uFCA6': '\u062B\u0645', + '\uFCA7': '\u062C\u062D', + '\uFCA8': '\u062C\u0645', + '\uFCA9': '\u062D\u062C', + '\uFCAA': '\u062D\u0645', + '\uFCAB': '\u062E\u062C', + '\uFCAC': '\u062E\u0645', + '\uFCAD': '\u0633\u062C', + '\uFCAE': '\u0633\u062D', + '\uFCAF': '\u0633\u062E', + '\uFCB0': '\u0633\u0645', + '\uFCB1': '\u0635\u062D', + '\uFCB2': '\u0635\u062E', + '\uFCB3': '\u0635\u0645', + '\uFCB4': '\u0636\u062C', + '\uFCB5': '\u0636\u062D', + '\uFCB6': '\u0636\u062E', + '\uFCB7': '\u0636\u0645', + '\uFCB8': '\u0637\u062D', + '\uFCB9': '\u0638\u0645', + '\uFCBA': '\u0639\u062C', + '\uFCBB': '\u0639\u0645', + '\uFCBC': '\u063A\u062C', + '\uFCBD': '\u063A\u0645', + '\uFCBE': '\u0641\u062C', + '\uFCBF': '\u0641\u062D', + '\uFCC0': '\u0641\u062E', + '\uFCC1': '\u0641\u0645', + '\uFCC2': '\u0642\u062D', + '\uFCC3': '\u0642\u0645', + '\uFCC4': '\u0643\u062C', + '\uFCC5': '\u0643\u062D', + '\uFCC6': '\u0643\u062E', + '\uFCC7': '\u0643\u0644', + '\uFCC8': '\u0643\u0645', + '\uFCC9': '\u0644\u062C', + '\uFCCA': '\u0644\u062D', + '\uFCCB': '\u0644\u062E', + '\uFCCC': '\u0644\u0645', + '\uFCCD': '\u0644\u0647', + '\uFCCE': '\u0645\u062C', + '\uFCCF': '\u0645\u062D', + '\uFCD0': '\u0645\u062E', + '\uFCD1': '\u0645\u0645', + '\uFCD2': '\u0646\u062C', + '\uFCD3': '\u0646\u062D', + '\uFCD4': '\u0646\u062E', + '\uFCD5': '\u0646\u0645', + '\uFCD6': '\u0646\u0647', + '\uFCD7': '\u0647\u062C', + '\uFCD8': '\u0647\u0645', + '\uFCD9': '\u0647\u0670', + '\uFCDA': '\u064A\u062C', + '\uFCDB': '\u064A\u062D', + '\uFCDC': '\u064A\u062E', + '\uFCDD': '\u064A\u0645', + '\uFCDE': '\u064A\u0647', + '\uFCDF': '\u0626\u0645', + '\uFCE0': '\u0626\u0647', + '\uFCE1': '\u0628\u0645', + '\uFCE2': '\u0628\u0647', + '\uFCE3': '\u062A\u0645', + '\uFCE4': '\u062A\u0647', + '\uFCE5': '\u062B\u0645', + '\uFCE6': '\u062B\u0647', + '\uFCE7': '\u0633\u0645', + '\uFCE8': '\u0633\u0647', + '\uFCE9': '\u0634\u0645', + '\uFCEA': '\u0634\u0647', + '\uFCEB': '\u0643\u0644', + '\uFCEC': '\u0643\u0645', + '\uFCED': '\u0644\u0645', + '\uFCEE': '\u0646\u0645', + '\uFCEF': '\u0646\u0647', + '\uFCF0': '\u064A\u0645', + '\uFCF1': '\u064A\u0647', + '\uFCF2': '\u0640\u064E\u0651', + '\uFCF3': '\u0640\u064F\u0651', + '\uFCF4': '\u0640\u0650\u0651', + '\uFCF5': '\u0637\u0649', + '\uFCF6': '\u0637\u064A', + '\uFCF7': '\u0639\u0649', + '\uFCF8': '\u0639\u064A', + '\uFCF9': '\u063A\u0649', + '\uFCFA': '\u063A\u064A', + '\uFCFB': '\u0633\u0649', + '\uFCFC': '\u0633\u064A', + '\uFCFD': '\u0634\u0649', + '\uFCFE': '\u0634\u064A', + '\uFCFF': '\u062D\u0649', + '\uFD00': '\u062D\u064A', + '\uFD01': '\u062C\u0649', + '\uFD02': '\u062C\u064A', + '\uFD03': '\u062E\u0649', + '\uFD04': '\u062E\u064A', + '\uFD05': '\u0635\u0649', + '\uFD06': '\u0635\u064A', + '\uFD07': '\u0636\u0649', + '\uFD08': '\u0636\u064A', + '\uFD09': '\u0634\u062C', + '\uFD0A': '\u0634\u062D', + '\uFD0B': '\u0634\u062E', + '\uFD0C': '\u0634\u0645', + '\uFD0D': '\u0634\u0631', + '\uFD0E': '\u0633\u0631', + '\uFD0F': '\u0635\u0631', + '\uFD10': '\u0636\u0631', + '\uFD11': '\u0637\u0649', + '\uFD12': '\u0637\u064A', + '\uFD13': '\u0639\u0649', + '\uFD14': '\u0639\u064A', + '\uFD15': '\u063A\u0649', + '\uFD16': '\u063A\u064A', + '\uFD17': '\u0633\u0649', + '\uFD18': '\u0633\u064A', + '\uFD19': '\u0634\u0649', + '\uFD1A': '\u0634\u064A', + '\uFD1B': '\u062D\u0649', + '\uFD1C': '\u062D\u064A', + '\uFD1D': '\u062C\u0649', + '\uFD1E': '\u062C\u064A', + '\uFD1F': '\u062E\u0649', + '\uFD20': '\u062E\u064A', + '\uFD21': '\u0635\u0649', + '\uFD22': '\u0635\u064A', + '\uFD23': '\u0636\u0649', + '\uFD24': '\u0636\u064A', + '\uFD25': '\u0634\u062C', + '\uFD26': '\u0634\u062D', + '\uFD27': '\u0634\u062E', + '\uFD28': '\u0634\u0645', + '\uFD29': '\u0634\u0631', + '\uFD2A': '\u0633\u0631', + '\uFD2B': '\u0635\u0631', + '\uFD2C': '\u0636\u0631', + '\uFD2D': '\u0634\u062C', + '\uFD2E': '\u0634\u062D', + '\uFD2F': '\u0634\u062E', + '\uFD30': '\u0634\u0645', + '\uFD31': '\u0633\u0647', + '\uFD32': '\u0634\u0647', + '\uFD33': '\u0637\u0645', + '\uFD34': '\u0633\u062C', + '\uFD35': '\u0633\u062D', + '\uFD36': '\u0633\u062E', + '\uFD37': '\u0634\u062C', + '\uFD38': '\u0634\u062D', + '\uFD39': '\u0634\u062E', + '\uFD3A': '\u0637\u0645', + '\uFD3B': '\u0638\u0645', + '\uFD3C': '\u0627\u064B', + '\uFD3D': '\u0627\u064B', + '\uFD50': '\u062A\u062C\u0645', + '\uFD51': '\u062A\u062D\u062C', + '\uFD52': '\u062A\u062D\u062C', + '\uFD53': '\u062A\u062D\u0645', + '\uFD54': '\u062A\u062E\u0645', + '\uFD55': '\u062A\u0645\u062C', + '\uFD56': '\u062A\u0645\u062D', + '\uFD57': '\u062A\u0645\u062E', + '\uFD58': '\u062C\u0645\u062D', + '\uFD59': '\u062C\u0645\u062D', + '\uFD5A': '\u062D\u0645\u064A', + '\uFD5B': '\u062D\u0645\u0649', + '\uFD5C': '\u0633\u062D\u062C', + '\uFD5D': '\u0633\u062C\u062D', + '\uFD5E': '\u0633\u062C\u0649', + '\uFD5F': '\u0633\u0645\u062D', + '\uFD60': '\u0633\u0645\u062D', + '\uFD61': '\u0633\u0645\u062C', + '\uFD62': '\u0633\u0645\u0645', + '\uFD63': '\u0633\u0645\u0645', + '\uFD64': '\u0635\u062D\u062D', + '\uFD65': '\u0635\u062D\u062D', + '\uFD66': '\u0635\u0645\u0645', + '\uFD67': '\u0634\u062D\u0645', + '\uFD68': '\u0634\u062D\u0645', + '\uFD69': '\u0634\u062C\u064A', + '\uFD6A': '\u0634\u0645\u062E', + '\uFD6B': '\u0634\u0645\u062E', + '\uFD6C': '\u0634\u0645\u0645', + '\uFD6D': '\u0634\u0645\u0645', + '\uFD6E': '\u0636\u062D\u0649', + '\uFD6F': '\u0636\u062E\u0645', + '\uFD70': '\u0636\u062E\u0645', + '\uFD71': '\u0637\u0645\u062D', + '\uFD72': '\u0637\u0645\u062D', + '\uFD73': '\u0637\u0645\u0645', + '\uFD74': '\u0637\u0645\u064A', + '\uFD75': '\u0639\u062C\u0645', + '\uFD76': '\u0639\u0645\u0645', + '\uFD77': '\u0639\u0645\u0645', + '\uFD78': '\u0639\u0645\u0649', + '\uFD79': '\u063A\u0645\u0645', + '\uFD7A': '\u063A\u0645\u064A', + '\uFD7B': '\u063A\u0645\u0649', + '\uFD7C': '\u0641\u062E\u0645', + '\uFD7D': '\u0641\u062E\u0645', + '\uFD7E': '\u0642\u0645\u062D', + '\uFD7F': '\u0642\u0645\u0645', + '\uFD80': '\u0644\u062D\u0645', + '\uFD81': '\u0644\u062D\u064A', + '\uFD82': '\u0644\u062D\u0649', + '\uFD83': '\u0644\u062C\u062C', + '\uFD84': '\u0644\u062C\u062C', + '\uFD85': '\u0644\u062E\u0645', + '\uFD86': '\u0644\u062E\u0645', + '\uFD87': '\u0644\u0645\u062D', + '\uFD88': '\u0644\u0645\u062D', + '\uFD89': '\u0645\u062D\u062C', + '\uFD8A': '\u0645\u062D\u0645', + '\uFD8B': '\u0645\u062D\u064A', + '\uFD8C': '\u0645\u062C\u062D', + '\uFD8D': '\u0645\u062C\u0645', + '\uFD8E': '\u0645\u062E\u062C', + '\uFD8F': '\u0645\u062E\u0645', + '\uFD92': '\u0645\u062C\u062E', + '\uFD93': '\u0647\u0645\u062C', + '\uFD94': '\u0647\u0645\u0645', + '\uFD95': '\u0646\u062D\u0645', + '\uFD96': '\u0646\u062D\u0649', + '\uFD97': '\u0646\u062C\u0645', + '\uFD98': '\u0646\u062C\u0645', + '\uFD99': '\u0646\u062C\u0649', + '\uFD9A': '\u0646\u0645\u064A', + '\uFD9B': '\u0646\u0645\u0649', + '\uFD9C': '\u064A\u0645\u0645', + '\uFD9D': '\u064A\u0645\u0645', + '\uFD9E': '\u0628\u062E\u064A', + '\uFD9F': '\u062A\u062C\u064A', + '\uFDA0': '\u062A\u062C\u0649', + '\uFDA1': '\u062A\u062E\u064A', + '\uFDA2': '\u062A\u062E\u0649', + '\uFDA3': '\u062A\u0645\u064A', + '\uFDA4': '\u062A\u0645\u0649', + '\uFDA5': '\u062C\u0645\u064A', + '\uFDA6': '\u062C\u062D\u0649', + '\uFDA7': '\u062C\u0645\u0649', + '\uFDA8': '\u0633\u062E\u0649', + '\uFDA9': '\u0635\u062D\u064A', + '\uFDAA': '\u0634\u062D\u064A', + '\uFDAB': '\u0636\u062D\u064A', + '\uFDAC': '\u0644\u062C\u064A', + '\uFDAD': '\u0644\u0645\u064A', + '\uFDAE': '\u064A\u062D\u064A', + '\uFDAF': '\u064A\u062C\u064A', + '\uFDB0': '\u064A\u0645\u064A', + '\uFDB1': '\u0645\u0645\u064A', + '\uFDB2': '\u0642\u0645\u064A', + '\uFDB3': '\u0646\u062D\u064A', + '\uFDB4': '\u0642\u0645\u062D', + '\uFDB5': '\u0644\u062D\u0645', + '\uFDB6': '\u0639\u0645\u064A', + '\uFDB7': '\u0643\u0645\u064A', + '\uFDB8': '\u0646\u062C\u062D', + '\uFDB9': '\u0645\u062E\u064A', + '\uFDBA': '\u0644\u062C\u0645', + '\uFDBB': '\u0643\u0645\u0645', + '\uFDBC': '\u0644\u062C\u0645', + '\uFDBD': '\u0646\u062C\u062D', + '\uFDBE': '\u062C\u062D\u064A', + '\uFDBF': '\u062D\u062C\u064A', + '\uFDC0': '\u0645\u062C\u064A', + '\uFDC1': '\u0641\u0645\u064A', + '\uFDC2': '\u0628\u062D\u064A', + '\uFDC3': '\u0643\u0645\u0645', + '\uFDC4': '\u0639\u062C\u0645', + '\uFDC5': '\u0635\u0645\u0645', + '\uFDC6': '\u0633\u062E\u064A', + '\uFDC7': '\u0646\u062C\u064A', + '\uFE49': '\u203E', + '\uFE4A': '\u203E', + '\uFE4B': '\u203E', + '\uFE4C': '\u203E', + '\uFE4D': '\u005F', + '\uFE4E': '\u005F', + '\uFE4F': '\u005F', + '\uFE80': '\u0621', + '\uFE81': '\u0622', + '\uFE82': '\u0622', + '\uFE83': '\u0623', + '\uFE84': '\u0623', + '\uFE85': '\u0624', + '\uFE86': '\u0624', + '\uFE87': '\u0625', + '\uFE88': '\u0625', + '\uFE89': '\u0626', + '\uFE8A': '\u0626', + '\uFE8B': '\u0626', + '\uFE8C': '\u0626', + '\uFE8D': '\u0627', + '\uFE8E': '\u0627', + '\uFE8F': '\u0628', + '\uFE90': '\u0628', + '\uFE91': '\u0628', + '\uFE92': '\u0628', + '\uFE93': '\u0629', + '\uFE94': '\u0629', + '\uFE95': '\u062A', + '\uFE96': '\u062A', + '\uFE97': '\u062A', + '\uFE98': '\u062A', + '\uFE99': '\u062B', + '\uFE9A': '\u062B', + '\uFE9B': '\u062B', + '\uFE9C': '\u062B', + '\uFE9D': '\u062C', + '\uFE9E': '\u062C', + '\uFE9F': '\u062C', + '\uFEA0': '\u062C', + '\uFEA1': '\u062D', + '\uFEA2': '\u062D', + '\uFEA3': '\u062D', + '\uFEA4': '\u062D', + '\uFEA5': '\u062E', + '\uFEA6': '\u062E', + '\uFEA7': '\u062E', + '\uFEA8': '\u062E', + '\uFEA9': '\u062F', + '\uFEAA': '\u062F', + '\uFEAB': '\u0630', + '\uFEAC': '\u0630', + '\uFEAD': '\u0631', + '\uFEAE': '\u0631', + '\uFEAF': '\u0632', + '\uFEB0': '\u0632', + '\uFEB1': '\u0633', + '\uFEB2': '\u0633', + '\uFEB3': '\u0633', + '\uFEB4': '\u0633', + '\uFEB5': '\u0634', + '\uFEB6': '\u0634', + '\uFEB7': '\u0634', + '\uFEB8': '\u0634', + '\uFEB9': '\u0635', + '\uFEBA': '\u0635', + '\uFEBB': '\u0635', + '\uFEBC': '\u0635', + '\uFEBD': '\u0636', + '\uFEBE': '\u0636', + '\uFEBF': '\u0636', + '\uFEC0': '\u0636', + '\uFEC1': '\u0637', + '\uFEC2': '\u0637', + '\uFEC3': '\u0637', + '\uFEC4': '\u0637', + '\uFEC5': '\u0638', + '\uFEC6': '\u0638', + '\uFEC7': '\u0638', + '\uFEC8': '\u0638', + '\uFEC9': '\u0639', + '\uFECA': '\u0639', + '\uFECB': '\u0639', + '\uFECC': '\u0639', + '\uFECD': '\u063A', + '\uFECE': '\u063A', + '\uFECF': '\u063A', + '\uFED0': '\u063A', + '\uFED1': '\u0641', + '\uFED2': '\u0641', + '\uFED3': '\u0641', + '\uFED4': '\u0641', + '\uFED5': '\u0642', + '\uFED6': '\u0642', + '\uFED7': '\u0642', + '\uFED8': '\u0642', + '\uFED9': '\u0643', + '\uFEDA': '\u0643', + '\uFEDB': '\u0643', + '\uFEDC': '\u0643', + '\uFEDD': '\u0644', + '\uFEDE': '\u0644', + '\uFEDF': '\u0644', + '\uFEE0': '\u0644', + '\uFEE1': '\u0645', + '\uFEE2': '\u0645', + '\uFEE3': '\u0645', + '\uFEE4': '\u0645', + '\uFEE5': '\u0646', + '\uFEE6': '\u0646', + '\uFEE7': '\u0646', + '\uFEE8': '\u0646', + '\uFEE9': '\u0647', + '\uFEEA': '\u0647', + '\uFEEB': '\u0647', + '\uFEEC': '\u0647', + '\uFEED': '\u0648', + '\uFEEE': '\u0648', + '\uFEEF': '\u0649', + '\uFEF0': '\u0649', + '\uFEF1': '\u064A', + '\uFEF2': '\u064A', + '\uFEF3': '\u064A', + '\uFEF4': '\u064A', + '\uFEF5': '\u0644\u0622', + '\uFEF6': '\u0644\u0622', + '\uFEF7': '\u0644\u0623', + '\uFEF8': '\u0644\u0623', + '\uFEF9': '\u0644\u0625', + '\uFEFA': '\u0644\u0625', + '\uFEFB': '\u0644\u0627', + '\uFEFC': '\u0644\u0627' +}; + +function reverseIfRtl(chars) { + var charsLength = chars.length; + //reverse an arabic ligature + if (charsLength <= 1 || !isRTLRangeFor(chars.charCodeAt(0))) + return chars; + + var s = ''; + for (var ii = charsLength - 1; ii >= 0; ii--) + s += chars[ii]; + return s; +} + +function 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; +} + +function adjustWidths(properties) { + if (properties.fontMatrix[0] === FONT_IDENTITY_MATRIX[0]) { + return; + } + // adjusting width to fontMatrix scale + var scale = 0.001 / properties.fontMatrix[0]; + var glyphsWidths = properties.widths; + for (var glyph in glyphsWidths) { + glyphsWidths[glyph] *= scale; + } + properties.defaultWidth *= scale; +} + +/** + * 'Font' is the class the outside world should use, it encapsulate all the font + * decoding logics whatever type it is (assuming the font type is supported). + * + * For example to read a Type1 font and to attach it to the document: + * var type1Font = new Font("MyFontName", binaryFile, propertiesObject); + * type1Font.bind(); + */ +var Font = (function FontClosure() { + function Font(name, file, properties) { + + this.name = name; + this.loadedName = properties.loadedName; + this.coded = properties.coded; + this.loadCharProcs = properties.coded; + this.sizes = []; + + var names = name.split('+'); + names = names.length > 1 ? names[1] : names[0]; + names = names.split(/[-,_]/g)[0]; + this.isSerifFont = !!(properties.flags & FontFlags.Serif); + this.isSymbolicFont = !!(properties.flags & FontFlags.Symbolic); + this.isMonospace = !!(properties.flags & FontFlags.FixedPitch); + + var type = properties.type; + this.type = type; + + this.fallbackName = this.isMonospace ? 'monospace' : + this.isSerifFont ? 'serif' : 'sans-serif'; + + this.differences = properties.differences; + this.widths = properties.widths; + this.defaultWidth = properties.defaultWidth; + this.composite = properties.composite; + this.wideChars = properties.wideChars; + this.hasEncoding = properties.hasEncoding; + 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; + return; + } + + // Trying to fix encoding using glyph CIDSystemInfo. + this.loadCidToUnicode(properties); + this.cidEncoding = properties.cidEncoding; + this.vertical = properties.vertical; + if (this.vertical) { + this.vmetrics = properties.vmetrics; + this.defaultVMetrics = properties.defaultVMetrics; + } + + if (properties.toUnicode && properties.toUnicode.length > 0) + this.toUnicode = properties.toUnicode; + else + this.rebuildToUnicode(properties); + + this.toFontChar = this.buildToFontChar(this.toUnicode); + + if (!file) { + // 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; + fontName = stdFontMap[fontName] || nonStdFontMap[fontName] || fontName; + + this.bold = (fontName.search(/bold/gi) != -1); + this.italic = (fontName.search(/oblique/gi) != -1) || + (fontName.search(/italic/gi) != -1); + + // Use 'name' instead of 'fontName' here because the original + // name ArialBlack for example will be replaced by Helvetica. + this.black = (name.search(/Black/g) != -1); + + // if at least one width is present, remeasure all chars when exists + this.remeasure = Object.keys(this.widths).length > 0; + + 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. + // Building one based on GlyphMapForStandardFonts. + var map = []; + for (var code in GlyphMapForStandardFonts) { + map[+code] = GlyphMapForStandardFonts[code]; + } + this.toFontChar = map; + this.toUnicode = map; + } + this.loadedName = fontName.split('-')[0]; + this.loading = false; + 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') + 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') { + type = 'OpenType'; + } + + var data; + switch (type) { + case 'Type1': + case 'CIDFontType0': + this.mimetype = 'font/opentype'; + + var cff = (subtype == 'Type1C' || subtype == 'CIDFontType0C') ? + new CFFFont(file, properties) : new Type1Font(name, file, properties); + + adjustWidths(properties); + + // Wrap the CFF data inside an OTF font file + data = this.convert(name, cff, properties); + break; + + case 'OpenType': + case 'TrueType': + case 'CIDFontType2': + this.mimetype = 'font/opentype'; + + // Repair the TrueType file. It is can be damaged in the point of + // view of the sanitizer + data = this.checkAndRepair(name, file, properties); + break; + + default: + error('Font ' + type + ' is not supported'); + break; + } + + this.data = data; + + // Transfer some properties again that could change during font conversion + this.fontMatrix = properties.fontMatrix; + this.widths = properties.widths; + this.defaultWidth = properties.defaultWidth; + this.encoding = properties.baseEncoding; + this.seacMap = properties.seacMap; + + this.loading = true; + } + + var numFonts = 0; + function getUniqueName() { + return 'pdfFont' + numFonts++; + } + + 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 string16(value) { + return String.fromCharCode((value >> 8) & 0xff) + + String.fromCharCode(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); + } + + function string32(value) { + return String.fromCharCode((value >> 24) & 0xff) + + String.fromCharCode((value >> 16) & 0xff) + + String.fromCharCode((value >> 8) & 0xff) + + String.fromCharCode(value & 0xff); + } + + function createOpenTypeHeader(sfnt, file, numTables) { + // Windows hates the Mac TrueType sfnt version number + if (sfnt == 'true') + sfnt = string32(0x00010000); + + // sfnt version (4 bytes) + var header = sfnt; + + // numTables (2 bytes) + header += string16(numTables); + + // 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; + } + + 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) { + // 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 }); + codes.sort(function fontGetRangesSort(a, b) { + return a.unicode - b.unicode; + }); + + // Split the sorted codes into ranges. + var ranges = []; + for (var n = 0; n < length; ) { + var start = codes[n].unicode; + var codeIndices = [deltas ? deltas[codes[n].code] : codes[n].code + 1]; + ++n; + var end = start; + while (n < length && end + 1 == codes[n].unicode) { + codeIndices.push(deltas ? deltas[codes[n].code] : codes[n].code + 1); + ++end; + ++n; + if (end === 0xFFFF) { break; } + } + ranges.push([start, end, codeIndices]); + } + + return ranges; + } + + function createCmapTable(glyphs, deltas) { + var ranges = getRanges(glyphs, deltas); + + var numTables = ranges[ranges.length - 1][1] > 0xFFFF ? 2 : 1; + var cmap = '\x00\x00' + // version + string16(numTables) + // numTables + '\x00\x03' + // platformID + '\x00\x01' + // encodingID + string32(4 + numTables * 8); // start of the table record + + for (var i = ranges.length - 1; i >= 0; --i) { + if (ranges[i][0] <= 0xFFFF) { break; } + } + var bmpLength = i + 1; + + if (ranges[i][0] < 0xFFFF && ranges[i][1] === 0xFFFF) { + ranges[i][1] = 0xFFFE; + } + var trailingRangesCount = ranges[i][1] < 0xFFFF ? 1 : 0; + var segCount = bmpLength + trailingRangesCount; + var segCount2 = segCount * 2; + var searchRange = getMaxPower2(segCount) * 2; + var searchEntry = Math.log(segCount) / Math.log(2); + var rangeShift = 2 * segCount - searchRange; + + // Fill up the 4 parallel arrays describing the segments. + var startCount = ''; + var endCount = ''; + var idDeltas = ''; + var idRangeOffsets = ''; + 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]; + startCount += string16(start); + endCount += string16(end); + var codes = range[2]; + var contiguous = true; + for (var j = 1, jj = codes.length; j < jj; ++j) { + if (codes[j] !== codes[j - 1] + 1) { + contiguous = false; + break; + } + } + if (!contiguous) { + var offset = (segCount - i) * 2 + bias * 2; + bias += (end - start + 1); + + idDeltas += string16(0); + idRangeOffsets += string16(offset); + + for (var j = 0, jj = codes.length; j < jj; ++j) { + glyphsIds += string16(codes[j]); + } + } else { + var startCode = codes[0]; + + idDeltas += string16((startCode - start) & 0xFFFF); + idRangeOffsets += string16(0); + } + } + + if (trailingRangesCount > 0) { + endCount += '\xFF\xFF'; + startCount += '\xFF\xFF'; + idDeltas += '\x00\x01'; + idRangeOffsets += '\x00\x00'; + } + + var format314 = '\x00\x00' + // language + string16(segCount2) + + string16(searchRange) + + string16(searchEntry) + + string16(rangeShift) + + endCount + '\x00\x00' + startCount + + idDeltas + idRangeOffsets + glyphsIds; + + var format31012 = ''; + var header31012 = ''; + if (numTables > 1) { + cmap += '\x00\x03' + // platformID + '\x00\x0A' + // encodingID + string32(4 + numTables * 8 + + 4 + format314.length); // start of the table record + format31012 = ''; + for (var i = 0, ii = ranges.length; i < ii; i++) { + var range = ranges[i]; + var start = range[0]; + var codes = range[2]; + var code = codes[0]; + for (var j = 1, jj = codes.length; j < jj; ++j) { + if (codes[j] !== codes[j - 1] + 1) { + var end = range[0] + j - 1; + format31012 += string32(start) + // startCharCode + string32(end) + // endCharCode + string32(code); // startGlyphID + start = end + 1; + code = codes[j]; + } + } + format31012 += string32(start) + // startCharCode + string32(range[1]) + // endCharCode + string32(code); // startGlyphID + } + header31012 = '\x00\x0C' + // format + '\x00\x00' + // reserved + string32(format31012.length + 16) + // length + '\x00\x00\x00\x00' + // language + string32(format31012.length / 12); // nGroups + } + + return stringToArray(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)); + // 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)); + if (version < 4 && (selection & 0x0300)) { + return false; + } + var firstChar = int16(stream.getBytes(2)); + var lastChar = int16(stream.getBytes(2)); + if (firstChar > lastChar) { + return false; + } + stream.getBytes(6); // skipping sTypoAscender/Descender/LineGap + var usWinAscent = int16(stream.getBytes(2)); + if (usWinAscent === 0) { // makes font unreadable by windows + return false; + } + + // OS/2 appears to be valid, resetting some fields + os2.data[8] = os2.data[9] = 0; // IE rejects fonts if fsType != 0 + return true; + } + + function createOS2Table(properties, charstrings, override) { + override = override || { + unitsPerEm: 0, + yMax: 0, + yMin: 0, + ascent: 0, + descent: 0 + }; + + var ulUnicodeRange1 = 0; + var ulUnicodeRange2 = 0; + var ulUnicodeRange3 = 0; + var ulUnicodeRange4 = 0; + + var firstCharIndex = null; + var lastCharIndex = 0; + + if (charstrings) { + for (var i = 0; i < charstrings.length; ++i) { + var code = charstrings[i].unicode; + if (firstCharIndex > code || !firstCharIndex) + firstCharIndex = code; + if (lastCharIndex < code) + lastCharIndex = code; + + var position = getUnicodeRangeFor(code); + if (position < 32) { + ulUnicodeRange1 |= 1 << position; + } else if (position < 64) { + ulUnicodeRange2 |= 1 << position - 32; + } else if (position < 96) { + ulUnicodeRange3 |= 1 << position - 64; + } else if (position < 123) { + ulUnicodeRange4 |= 1 << position - 96; + } else { + error('Unicode ranges Bits > 123 are reserved for internal usage'); + } + } + } else { + // TODO + firstCharIndex = 0; + lastCharIndex = 255; + } + + var bbox = properties.bbox || [0, 0, 0, 0]; + var unitsPerEm = override.unitsPerEm || + 1 / (properties.fontMatrix || FONT_IDENTITY_MATRIX)[0]; + + // if the font units differ to the PDF glyph space units + // then scale up the values + var scale = properties.ascentScaled ? 1.0 : + unitsPerEm / PDF_GLYPH_SPACE_UNITS; + + var typoAscent = override.ascent || Math.round(scale * + (properties.ascent || bbox[3])); + var typoDescent = override.descent || Math.round(scale * + (properties.descent || bbox[1])); + if (typoDescent > 0 && properties.descent > 0 && bbox[1] < 0) { + typoDescent = -typoDescent; // fixing incorrect descent + } + var winAscent = override.yMax || typoAscent; + var winDescent = -override.yMin || -typoDescent; + + return '\x00\x03' + // version + '\x02\x24' + // xAvgCharWidth + '\x01\xF4' + // usWeightClass + '\x00\x05' + // usWidthClass + '\x00\x00' + // fstype (0 to let the font loads via font-face on IE) + '\x02\x8A' + // ySubscriptXSize + '\x02\xBB' + // ySubscriptYSize + '\x00\x00' + // ySubscriptXOffset + '\x00\x8C' + // ySubscriptYOffset + '\x02\x8A' + // ySuperScriptXSize + '\x02\xBB' + // ySuperScriptYSize + '\x00\x00' + // ySuperScriptXOffset + '\x01\xDF' + // ySuperScriptYOffset + '\x00\x31' + // yStrikeOutSize + '\x01\x02' + // yStrikeOutPosition + '\x00\x00' + // sFamilyClass + '\x00\x00\x06' + + String.fromCharCode(properties.fixedPitch ? 0x09 : 0x00) + + '\x00\x00\x00\x00\x00\x00' + // Panose + string32(ulUnicodeRange1) + // ulUnicodeRange1 (Bits 0-31) + string32(ulUnicodeRange2) + // ulUnicodeRange2 (Bits 32-63) + string32(ulUnicodeRange3) + // ulUnicodeRange3 (Bits 64-95) + string32(ulUnicodeRange4) + // ulUnicodeRange4 (Bits 96-127) + '\x2A\x32\x31\x2A' + // achVendID + string16(properties.italicAngle ? 1 : 0) + // fsSelection + string16(firstCharIndex || + properties.firstChar) + // usFirstCharIndex + string16(lastCharIndex || properties.lastChar) + // usLastCharIndex + string16(typoAscent) + // sTypoAscender + string16(typoDescent) + // sTypoDescender + '\x00\x64' + // sTypoLineGap (7%-10% of the unitsPerEM value) + string16(winAscent) + // usWinAscent + string16(winDescent) + // usWinDescent + '\x00\x00\x00\x00' + // ulCodePageRange1 (Bits 0-31) + '\x00\x00\x00\x00' + // ulCodePageRange2 (Bits 32-63) + string16(properties.xHeight) + // sxHeight + string16(properties.capHeight) + // sCapHeight + string16(0) + // usDefaultChar + string16(firstCharIndex || properties.firstChar) + // usBreakChar + '\x00\x03'; // usMaxContext + } + + function createPostTable(properties) { + var angle = Math.floor(properties.italicAngle * (Math.pow(2, 16))); + return '\x00\x03\x00\x00' + // Version number + string32(angle) + // italicAngle + '\x00\x00' + // underlinePosition + '\x00\x00' + // underlineThickness + string32(properties.fixedPitch) + // isFixedPitch + '\x00\x00\x00\x00' + // minMemType42 + '\x00\x00\x00\x00' + // maxMemType42 + '\x00\x00\x00\x00' + // minMemType1 + '\x00\x00\x00\x00'; // maxMemType1 + } + + function createNameTable(name, proto) { + if (!proto) { + proto = [[], []]; // no strings and unicode strings + } + + var strings = [ + proto[0][0] || 'Original licence', // 0.Copyright + proto[0][1] || name, // 1.Font family + proto[0][2] || 'Unknown', // 2.Font subfamily (font weight) + proto[0][3] || 'uniqueID', // 3.Unique ID + proto[0][4] || name, // 4.Full font name + proto[0][5] || 'Version 0.11', // 5.Version + proto[0][6] || '', // 6.Postscript name + proto[0][7] || 'Unknown', // 7.Trademark + proto[0][8] || 'Unknown', // 8.Manufacturer + proto[0][9] || 'Unknown' // 9.Designer + ]; + + // Mac want 1-byte per character strings while Windows want + // 2-bytes per character, so duplicate the names table + var stringsUnicode = []; + for (var i = 0, ii = strings.length; i < ii; i++) { + var 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 names = [strings, stringsUnicode]; + var platforms = ['\x00\x01', '\x00\x03']; + var encodings = ['\x00\x00', '\x00\x01']; + var languages = ['\x00\x00', '\x04\x09']; + + var namesRecordCount = strings.length * platforms.length; + var nameTable = + '\x00\x00' + // format + string16(namesRecordCount) + // Number of names Record + string16(namesRecordCount * 12 + 6); // Storage + + // Build the name records field + var strOffset = 0; + for (var 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]; + var nameRecord = + platforms[i] + // platform ID + encodings[i] + // encoding ID + languages[i] + // language ID + string16(j) + // name ID + string16(str.length) + + string16(strOffset); + nameTable += nameRecord; + strOffset += str.length; + } + } + + nameTable += strings.join('') + stringsUnicode.join(''); + return nameTable; + } + + // 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, + mimetype: null, + encoding: null, + get renderer() { + var renderer = FontRendererFactory.create(this); + return shadow(this, 'renderer', renderer); + }, + + exportData: function Font_exportData() { + var data = {}; + for (var i in this) { + if (this.hasOwnProperty(i)) + data[i] = this[i]; + } + return data; + }, + + checkAndRepair: function Font_checkAndRepair(name, font, properties) { + function readTableEntry(file) { + var tag = file.getBytes(4); + tag = String.fromCharCode(tag[0]) + + String.fromCharCode(tag[1]) + + String.fromCharCode(tag[2]) + + String.fromCharCode(tag[3]); + + var checksum = int32(file.getBytes(4)); + var offset = int32(file.getBytes(4)); + var length = int32(file.getBytes(4)); + + // Read the table associated data + var previousPosition = file.pos; + file.pos = file.start ? file.start : 0; + file.skip(offset); + var data = file.getBytes(length); + file.pos = previousPosition; + + if (tag == 'head') { + // clearing checksum adjustment + data[8] = data[9] = data[10] = data[11] = 0; + data[17] |= 0x20; //Set font optimized for cleartype flag + } + + return { + tag: tag, + checksum: checksum, + length: length, + offset: offset, + data: data + }; + } + + function readOpenTypeHeader(ttf) { + return { + version: arrayToString(ttf.getBytes(4)), + numTables: int16(ttf.getBytes(2)), + searchRange: int16(ttf.getBytes(2)), + entrySelector: int16(ttf.getBytes(2)), + rangeShift: int16(ttf.getBytes(2)) + }; + } + + 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) { + 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 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. + 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 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) { + useTable = true; + canBreak = true; + foundPreferredTable = true; + } else if (hasEncoding && platformId === 3 && encodingId === 1) { + 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 + }; + } + if (canBreak) { + break; + } + } + + 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; + } + + font.pos = start + potentialTable.offset; + var format = int16(font.getBytes(2)); + var length = int16(font.getBytes(2)); + var language = int16(font.getBytes(2)); + + var hasShortCmap = false; + var mappings = []; + + // TODO(mack): refactor this cmap subtable reading logic out + if (format === 0) { + for (var j = 0; j < 256; j++) { + var index = font.getByte(); + if (!index) { + continue; + } + mappings.push({ + charcode: j, + glyphId: index + }); + } + hasShortCmap = true; + } else if (format === 4) { + // re-creating the table in format 4 since the encoding + // might be changed + var segCount = (int16(font.getBytes(2)) >> 1); + font.getBytes(6); // skipping range fields + var segIndex, segments = []; + for (segIndex = 0; segIndex < segCount; segIndex++) { + segments.push({ end: int16(font.getBytes(2)) }); + } + font.getBytes(2); + for (segIndex = 0; segIndex < segCount; segIndex++) { + segments[segIndex].start = int16(font.getBytes(2)); + } + + for (segIndex = 0; segIndex < segCount; segIndex++) { + segments[segIndex].delta = int16(font.getBytes(2)); + } + + var offsetsCount = 0; + for (segIndex = 0; segIndex < segCount; segIndex++) { + var segment = segments[segIndex]; + var rangeOffset = int16(font.getBytes(2)); + if (!rangeOffset) { + segment.offsetIndex = -1; + continue; + } + + var offsetIndex = (rangeOffset >> 1) - (segCount - segIndex); + segment.offsetIndex = offsetIndex; + offsetsCount = Math.max(offsetsCount, offsetIndex + + segment.end - segment.start + 1); + } + + var offsets = []; + for (var j = 0; j < offsetsCount; j++) { + offsets.push(int16(font.getBytes(2))); + } + + for (segIndex = 0; segIndex < segCount; segIndex++) { + var segment = segments[segIndex]; + var start = segment.start, end = segment.end; + var delta = segment.delta, offsetIndex = segment.offsetIndex; + + for (var j = start; j <= end; j++) { + if (j == 0xFFFF) { + continue; + } + + var glyphId = offsetIndex < 0 ? j : + offsets[offsetIndex + j - start]; + glyphId = (glyphId + delta) & 0xFFFF; + if (glyphId === 0) { + continue; + } + mappings.push({ + charcode: j, + glyphId: glyphId + }); + } + } + } else if (format == 6) { + // Format 6 is a 2-bytes dense mapping, which means the font data + // lives glue together even if they are pretty far in the unicode + // table. (This looks weird, so I can have missed something), this + // works on Linux but seems to fails on Mac so let's rewrite the + // cmap table to a 3-1-4 style + var firstCode = int16(font.getBytes(2)); + var entryCount = int16(font.getBytes(2)); + + var glyphs = []; + var ids = []; + for (var j = 0; j < entryCount; j++) { + var glyphId = int16(font.getBytes(2)); + var charcode = firstCode + j; + + mappings.push({ + charcode: charcode, + glyphId: glyphId + }); + } + } else { + error('cmap table has unsupported format: ' + format); + } + + // removing duplicate entries + mappings.sort(function (a, b) { + return a.charcode - b.charcode; + }); + for (var i = 1; i < mappings.length; i++) { + if (mappings[i - 1].charcode === mappings[i].charcode) { + mappings.splice(i, 1); + i--; + } + } + + return { + platformId: potentialTable.platformId, + encodingId: potentialTable.encodingId, + isSymbolicFont: potentialTable.isSymbolicFont, + mappings: mappings, + hasShortCmap: hasShortCmap + }; + } + + function sanitizeMetrics(font, header, metrics, numGlyphs) { + if (!header) { + if (metrics) { + metrics.data = null; + } + return; + } + + font.pos = (font.start ? font.start : 0) + header.offset; + font.pos += header.length - 2; + var numOfMetrics = int16(font.getBytes(2)); + + if (numOfMetrics > numGlyphs) { + info('The numOfMetrics (' + numOfMetrics + ') should not be ' + + 'greater than the numGlyphs (' + numGlyphs + ')'); + // Reduce numOfMetrics if it is greater than numGlyphs + numOfMetrics = numGlyphs; + header.data[34] = (numOfMetrics & 0xff00) >> 8; + header.data[35] = numOfMetrics & 0x00ff; + } + + var numOfSidebearings = numGlyphs - numOfMetrics; + var numMissing = numOfSidebearings - + ((metrics.length - numOfMetrics * 4) >> 1); + + if (numMissing > 0) { + 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); + } + } + + function sanitizeGlyph(source, sourceStart, sourceEnd, dest, destStart, + hintsValid) { + if (sourceEnd - sourceStart <= 12) { + // glyph with data less than 12 is invalid one + return 0; + } + var glyf = source.subarray(sourceStart, sourceEnd); + var contoursCount = (glyf[0] << 8) | glyf[1]; + if (contoursCount & 0x8000) { + // complex glyph, writing as is + dest.set(glyf, destStart); + return glyf.length; + } + + var j = 10, flagsCount = 0; + for (var i = 0; i < contoursCount; i++) { + var endPoint = (glyf[j] << 8) | glyf[j + 1]; + flagsCount = endPoint + 1; + j += 2; + } + // skipping instructions + var instructionsStart = j; + var instructionsLength = (glyf[j] << 8) | glyf[j + 1]; + j += 2 + instructionsLength; + var instructionsEnd = j; + // validating flags + var coordinatesLength = 0; + for (var i = 0; i < flagsCount; i++) { + var flag = glyf[j++]; + if (flag & 0xC0) { + // reserved flags must be zero, cleaning up + glyf[j - 1] = flag & 0x3F; + } + var xyLength = ((flag & 2) ? 1 : (flag & 16) ? 0 : 2) + + ((flag & 4) ? 1 : (flag & 32) ? 0 : 2); + coordinatesLength += xyLength; + if (flag & 8) { + var repeat = glyf[j++]; + i += repeat; + coordinatesLength += repeat * xyLength; + } + } + // glyph without coordinates will be rejected + if (coordinatesLength === 0) { + return 0; + } + var glyphDataLength = j + coordinatesLength; + if (glyphDataLength > glyf.length) { + // not enough data for coordinates + return 0; + } + if (!hintsValid && instructionsLength > 0) { + dest.set(glyf.subarray(0, instructionsStart), destStart); + dest.set([0, 0], destStart + instructionsStart); + dest.set(glyf.subarray(instructionsEnd, glyphDataLength), + destStart + instructionsStart + 2); + glyphDataLength -= instructionsLength; + if (glyf.length - glyphDataLength > 3) { + glyphDataLength = (glyphDataLength + 3) & ~3; + } + return glyphDataLength; + } + if (glyf.length - glyphDataLength > 3) { + // truncating and aligning to 4 bytes the long glyph data + glyphDataLength = (glyphDataLength + 3) & ~3; + dest.set(glyf.subarray(0, glyphDataLength), destStart); + return glyphDataLength; + } + // glyph data is fine + dest.set(glyf, destStart); + return glyf.length; + } + + function sanitizeHead(head, numGlyphs, locaLength) { + var data = head.data; + + // Validate version: + // Should always be 0x00010000 + var version = int32([data[0], data[1], data[2], data[3]]); + if (version >> 16 !== 1) { + info('Attempting to fix invalid version in head table: ' + version); + data[0] = 0; + data[1] = 1; + data[2] = 0; + data[3] = 0; + } + + var indexToLocFormat = int16([data[50], data[51]]); + if (indexToLocFormat < 0 || indexToLocFormat > 1) { + info('Attempting to fix invalid indexToLocFormat in head table: ' + + indexToLocFormat); + + // The value of indexToLocFormat should be 0 if the loca table + // consists of short offsets, and should be 1 if the loca table + // consists of long offsets. + // + // The number of entries in the loca table should be numGlyphs + 1. + // + // Using this information, we can work backwards to deduce if the + // size of each offset in the loca table, and thus figure out the + // appropriate value for indexToLocFormat. + + var numGlyphsPlusOne = numGlyphs + 1; + if (locaLength === numGlyphsPlusOne << 1) { + // 0x0000 indicates the loca table consists of short offsets + data[50] = 0; + data[51] = 0; + } else if (locaLength === numGlyphsPlusOne << 2) { + // 0x0001 indicates the loca table consists of long offsets + data[50] = 0; + data[51] = 1; + } else { + warn('Could not fix indexToLocFormat: ' + indexToLocFormat); + } + } + } + + function sanitizeGlyphLocations(loca, glyf, numGlyphs, + isGlyphLocationsLong, hintsValid, + dupFirstEntry) { + var itemSize, itemDecode, itemEncode; + if (isGlyphLocationsLong) { + itemSize = 4; + itemDecode = function fontItemDecodeLong(data, offset) { + return (data[offset] << 24) | (data[offset + 1] << 16) | + (data[offset + 2] << 8) | data[offset + 3]; + }; + itemEncode = function fontItemEncodeLong(data, offset, value) { + data[offset] = (value >>> 24) & 0xFF; + data[offset + 1] = (value >> 16) & 0xFF; + data[offset + 2] = (value >> 8) & 0xFF; + data[offset + 3] = value & 0xFF; + }; + } else { + itemSize = 2; + itemDecode = function fontItemDecode(data, offset) { + return (data[offset] << 9) | (data[offset + 1] << 1); + }; + itemEncode = function fontItemEncode(data, offset, value) { + data[offset] = (value >> 9) & 0xFF; + data[offset + 1] = (value >> 1) & 0xFF; + }; + } + var locaData = loca.data; + var locaDataSize = itemSize * (1 + numGlyphs); + // is loca.data too short or long? + if (locaData.length !== locaDataSize) { + locaData = new Uint8Array(locaDataSize); + locaData.set(loca.data.subarray(0, locaDataSize)); + loca.data = locaData; + } + // removing the invalid glyphs + var oldGlyfData = glyf.data; + var oldGlyfDataLength = oldGlyfData.length; + var newGlyfData = new Uint8Array(oldGlyfDataLength); + var startOffset = itemDecode(locaData, 0); + var writeOffset = 0; + itemEncode(locaData, 0, writeOffset); + for (var i = 0, j = itemSize; i < numGlyphs; i++, j += itemSize) { + var endOffset = itemDecode(locaData, j); + if (endOffset > oldGlyfDataLength) { + // glyph end offset points outside glyf data, rejecting the glyph + itemEncode(locaData, j, writeOffset); + startOffset = endOffset; + continue; + } + + var newLength = sanitizeGlyph(oldGlyfData, startOffset, endOffset, + newGlyfData, writeOffset, hintsValid); + writeOffset += newLength; + itemEncode(locaData, j, writeOffset); + startOffset = endOffset; + } + + if (writeOffset === 0) { + // glyf table cannot be empty -- redoing the glyf and loca tables + // to have single glyph with one point + var simpleGlyph = new Uint8Array( + [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 0]); + for (var i = 0, j = itemSize; i < numGlyphs; i++, j += itemSize) + itemEncode(locaData, j, simpleGlyph.length); + glyf.data = simpleGlyph; + return; + } + + if (dupFirstEntry) { + var firstEntryLength = itemDecode(locaData, itemSize); + if (newGlyfData.length > firstEntryLength + writeOffset) { + glyf.data = newGlyfData.subarray(0, firstEntryLength + writeOffset); + } else { + glyf.data = new Uint8Array(firstEntryLength + writeOffset); + glyf.data.set(newGlyfData.subarray(0, writeOffset)); + } + glyf.data.set(newGlyfData.subarray(0, firstEntryLength), writeOffset); + itemEncode(loca.data, locaData.length - itemSize, + writeOffset + firstEntryLength); + } else { + glyf.data = newGlyfData.subarray(0, writeOffset); + } + } + + function readPostScriptTable(post, properties, maxpNumGlyphs) { + var start = (font.start ? font.start : 0) + post.offset; + font.pos = start; + + var length = post.length, end = start + length; + var version = int32(font.getBytes(4)); + // skip rest to the tables + font.getBytes(28); + + var glyphNames; + var valid = true; + switch (version) { + case 0x00010000: + glyphNames = MacStandardGlyphOrdering; + break; + case 0x00020000: + var numGlyphs = int16(font.getBytes(2)); + if (numGlyphs != maxpNumGlyphs) { + valid = false; + break; + } + var glyphNameIndexes = []; + for (var i = 0; i < numGlyphs; ++i) { + var index = int16(font.getBytes(2)); + if (index >= 32768) { + valid = false; + break; + } + glyphNameIndexes.push(index); + } + if (!valid) { + break; + } + var customNames = []; + while (font.pos < end) { + var stringLength = font.getByte(); + var string = ''; + for (var i = 0; i < stringLength; ++i) { + string += String.fromCharCode(font.getByte()); + } + customNames.push(string); + } + glyphNames = []; + for (var i = 0; i < numGlyphs; ++i) { + var j = glyphNameIndexes[i]; + if (j < 258) { + glyphNames.push(MacStandardGlyphOrdering[j]); + continue; + } + glyphNames.push(customNames[j - 258]); + } + break; + case 0x00030000: + break; + default: + warn('Unknown/unsupported post table version ' + version); + valid = false; + break; + } + properties.glyphNames = glyphNames; + return valid; + } + + function readNameTable(nameTable) { + var start = (font.start ? font.start : 0) + nameTable.offset; + font.pos = start; + + var names = [[], []]; + var length = nameTable.length, end = start + length; + var format = int16(font.getBytes(2)); + 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 records = []; + var NAME_RECORD_LENGTH = 12; + for (var 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)) + }; + // using only Macintosh and Windows platform/encoding names + if ((r.platform == 1 && r.encoding === 0 && r.language === 0) || + (r.platform == 3 && r.encoding == 1 && r.language == 0x409)) { + records.push(r); + } + } + for (var i = 0, ii = records.length; i < ii; i++) { + var record = records[i]; + var pos = start + stringsStart + record.offset; + if (pos + record.length > end) { + continue; // outside of name table, ignoring + } + font.pos = pos; + var nameIndex = record.name; + 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))); + } + names[1][nameIndex] = str; + } else { + names[0][nameIndex] = bytesToString(font.getBytes(record.length)); + } + } + return names; + } + + var TTOpsStackDeltas = [ + 0, 0, 0, 0, 0, 0, 0, 0, -2, -2, -2, -2, 0, 0, -2, -5, + -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, -1, 0, -1, -1, -1, -1, + 1, -1, -999, 0, 1, 0, -1, -2, 0, -1, -2, -1, -1, 0, -1, -1, + 0, 0, -999, -999, -1, -1, -1, -1, -2, -999, -2, -2, -999, 0, -2, -2, + 0, 0, -2, 0, -2, 0, 0, 0, -2, -1, -1, 1, 1, 0, 0, -1, + -1, -1, -1, -1, -1, -1, 0, 0, -1, 0, -1, -1, 0, -999, -1, -1, + -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -2, -999, -999, -999, -999, -999, -1, -1, -2, -2, 0, 0, 0, 0, -1, -1, + -999, -2, -2, 0, 0, -1, -2, -2, 0, 0, 0, -1, -1, -1, -2]; + // 0xC0-DF == -1 and 0xE0-FF == -2 + + function sanitizeTTProgram(table, ttContext) { + var data = table.data; + var i = 0, n, lastEndf = 0, lastDeff = 0; + var stack = []; + var callstack = []; + var functionsCalled = []; + var tooComplexToFollowFunctions = + ttContext.tooComplexToFollowFunctions; + var inFDEF = false, ifLevel = 0, inELSE = 0; + for (var ii = data.length; i < ii;) { + var op = data[i++]; + // The TrueType instruction set docs can be found at + // https://developer.apple.com/fonts/TTRefMan/RM05/Chap5.html + if (op === 0x40) { // NPUSHB - pushes n bytes + n = data[i++]; + if (inFDEF || inELSE) { + i += n; + } else { + for (var j = 0; j < n; j++) { + stack.push(data[i++]); + } + } + } else if (op === 0x41) { // NPUSHW - pushes n words + n = data[i++]; + if (inFDEF || inELSE) { + i += n * 2; + } else { + for (var j = 0; j < n; j++) { + var b = data[i++]; + stack.push((b << 8) | data[i++]); + } + } + } else if ((op & 0xF8) === 0xB0) { // PUSHB - pushes bytes + n = op - 0xB0 + 1; + if (inFDEF || inELSE) { + i += n; + } else { + for (var j = 0; j < n; j++) { + stack.push(data[i++]); + } + } + } else if ((op & 0xF8) === 0xB8) { // PUSHW - pushes words + n = op - 0xB8 + 1; + if (inFDEF || inELSE) { + i += n * 2; + } else { + for (var j = 0; j < n; j++) { + var 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]; + ttContext.functionsUsed[funcId] = true; + if (funcId in ttContext.functionsStackDeltas) { + stack.length += ttContext.functionsStackDeltas[funcId]; + } else if (funcId in ttContext.functionsDefined && + functionsCalled.indexOf(funcId) < 0) { + callstack.push({data: data, i: i, stackTop: stack.length - 1}); + functionsCalled.push(funcId); + var pc = ttContext.functionsDefined[funcId]; + if (!pc) { + warn('TT: CALL non-existent function'); + ttContext.hintsValid = false; + return; + } + data = pc.data; + i = pc.i; + } + } + } else if (op === 0x2C && !tooComplexToFollowFunctions) { // FDEF + if (inFDEF || inELSE) { + warn('TT: nested FDEFs not allowed'); + tooComplexToFollowFunctions = true; + } + inFDEF = true; + // collecting inforamtion about which functions are defined + lastDeff = i; + var 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(); + if (!pc) { + warn('TT: ENDF bad stack'); + ttContext.hintsValid = false; + return; + } + var funcId = functionsCalled.pop(); + data = pc.data; + i = pc.i; + ttContext.functionsStackDeltas[funcId] = + stack.length - pc.stackTop; + } + } else if (op === 0x89) { // IDEF - instruction definition + if (inFDEF || inELSE) { + warn('TT: nested IDEFs not allowed'); + tooComplexToFollowFunctions = true; + } + inFDEF = true; + // recording it as a function to track ENDF + lastDeff = i; + } else if (op === 0x58) { // IF + ++ifLevel; + } else if (op === 0x1B) { // ELSE + inELSE = ifLevel; + } else if (op === 0x59) { // EIF + if (inELSE === ifLevel) { + inELSE = 0; + } + --ifLevel; + } else if (op === 0x1C) { // JMPR + var offset = stack[stack.length - 1]; + // only jumping forward to prevent infinite loop + if (offset > 0) { i += offset - 1; } + } + // Adjusting stack not extactly, but just enough to get function id + if (!inFDEF && !inELSE) { + var stackDelta = op <= 0x8E ? TTOpsStackDeltas[op] : + op >= 0xC0 && op <= 0xDF ? -1 : op >= 0xE0 ? -2 : 0; + if (op >= 0x71 && op <= 0x75) { + n = stack.pop(); + if (n === n) { + stackDelta = -n * 2; + } + } + while (stackDelta < 0 && stack.length > 0) { + stack.pop(); + stackDelta++; + } + while (stackDelta > 0) { + stack.push(NaN); // pushing any number into stack + stackDelta--; + } + } + } + ttContext.tooComplexToFollowFunctions = tooComplexToFollowFunctions; + var content = [data]; + if (i > data.length) { + content.push(new Uint8Array(i - data.length)); + } + if (lastDeff > lastEndf) { + warn('TT: complementing a missing function tail'); + // new function definition started, but not finished + // complete function by [CLEAR, ENDF] + content.push(new Uint8Array([0x22, 0x2D])); + } + foldTTTable(table, content); + } + + function checkInvalidFunctions(ttContext, maxFunctionDefs) { + if (ttContext.tooComplexToFollowFunctions) { + return; + } + for (var j = 0, jj = ttContext.functionsUsed.length; j < jj; j++) { + if (j > maxFunctionDefs) { + warn('TT: invalid function id: ' + j); + ttContext.hintsValid = false; + return; + } + if (ttContext.functionsUsed[j] && !ttContext.functionsDefined[j]) { + warn('TT: undefined function: ' + j); + ttContext.hintsValid = false; + return; + } + } + } + + function foldTTTable(table, content) { + if (content.length > 1) { + // concatenating the content items + var newLength = 0; + for (var 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++) { + result.set(content[j], pos); + pos += content[j].length; + } + table.data = result; + table.length = newLength; + } + } + + function sanitizeTTPrograms(fpgm, prep, cvt) { + var ttContext = { + functionsDefined: [], + functionsUsed: [], + functionsStackDeltas: [], + tooComplexToFollowFunctions: false, + hintsValid: true + }; + if (fpgm) { + sanitizeTTProgram(fpgm, ttContext); + } + if (prep) { + sanitizeTTProgram(prep, ttContext); + } + if (fpgm) { + checkInvalidFunctions(ttContext, maxFunctionDefs); + } + if (cvt && (cvt.length & 1)) { + var cvtData = new Uint8Array(cvt.length + 1); + cvtData.set(cvt.data); + cvt.data = cvtData; + } + return ttContext.hintsValid; + } + + // The following steps modify the original font data, making copy + font = new Stream(new Uint8Array(font.getBytes())); + + var VALID_TABLES = ['OS/2', 'cmap', 'head', 'hhea', 'hmtx', 'maxp', + 'name', 'post', 'loca', 'glyf', 'fpgm', 'prep', 'cvt ', 'CFF ']; + + var header = readOpenTypeHeader(font); + var numTables = header.numTables; + + var tables = { 'OS/2': null, cmap: null, head: null, hhea: null, + hmtx: null, maxp: null, name: null, post: null}; + for (var i = 0; i < numTables; i++) { + var table = readTableEntry(font); + if (VALID_TABLES.indexOf(table.tag) < 0) { + continue; // skipping table if it's not a required or optional table + } + if (table.length === 0) { + continue; // skipping empty tables + } + tables[table.tag] = table; + } + + var isTrueType = !tables['CFF ']; + if (!isTrueType) { + // OpenType font + if (!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); + + return this.convert(name, cff, properties); + } + + delete tables.glyf; + delete tables.loca; + delete tables.fpgm; + delete tables.prep; + delete tables['cvt ']; + } else { + if (!tables.glyf || !tables.loca) { + error('Required "glyf" or "loca" tables are not found'); + } + } + + if (!tables.maxp) { + error('Required "maxp" table is not found'); + } + + font.pos = (font.start || 0) + tables.maxp.offset; + var version = int32(font.getBytes(4)); + var numGlyphs = int16(font.getBytes(2)); + var maxFunctionDefs = 0; + if (version >= 0x00010000 && tables.maxp.length >= 22) { + // maxZones can be invalid + font.pos += 8; + var maxZones = int16(font.getBytes(2)); + 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)); + } + + var dupFirstEntry = false; + if (properties.type == 'CIDFontType2' && properties.toUnicode && + properties.toUnicode[0] > '\u0000') { + // oracle's defect (see 3427), duplicating first entry + dupFirstEntry = true; + numGlyphs++; + tables.maxp.data[4] = numGlyphs >> 8; + tables.maxp.data[5] = numGlyphs & 255; + } + + var hintsValid = sanitizeTTPrograms(tables.fpgm, tables.prep, + tables['cvt '], maxFunctionDefs); + if (!hintsValid) { + delete tables.fpgm; + delete tables.prep; + delete tables['cvt ']; + } + + // 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); + + if (!tables.head) { + error('Required "head" table is not found'); + } + + sanitizeHead(tables.head, numGlyphs, isTrueType ? tables.loca.length : 0); + + if (isTrueType) { + var isGlyphLocationsLong = int16([tables.head.data[50], + tables.head.data[51]]); + sanitizeGlyphLocations(tables.loca, tables.glyf, numGlyphs, + isGlyphLocationsLong, hintsValid, dupFirstEntry); + } + + if (!tables.hhea) { + error('Required "hhea" table is not found'); + } + + // Sanitizer reduces the glyph advanceWidth to the maxAdvanceWidth + // Sometimes it's 0. That needs to be fixed + if (tables.hhea.data[10] === 0 && tables.hhea.data[11] === 0) { + tables.hhea.data[10] = 0xFF; + tables.hhea.data[11] = 0xFF; + } + + // The 'post' table has glyphs names. + if (tables.post) { + var valid = readPostScriptTable(tables.post, properties, numGlyphs); + if (!valid) { + tables.post = null; + } + } + + var 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 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; + } + // 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); + } + } + } 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 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); + + if (!unicode) { + // TODO(mack): gotta check if skipping mappings where we cannot find + // a unicode is the correct behaviour + continue; + } + 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)) { + 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]; + } + + // Finally, any undefined entries in the table shall be filled + // using StandardEncoding + if (!glyphName) { + glyphName = Encodings.StandardEncoding[charcode]; + } + + // 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; + } + } + this.toFontChar = toFontChar = newToFontChar; + + createGlyphNameMap(glyphs, ids, properties); + this.glyphNameMap = properties.glyphNameMap; + } + + if (glyphs.length === 0) { + // defines at least one glyph + glyphs.push({ unicode: 0xF000, code: 0xF000, glyph: '.notdef' }); + ids.push(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; + + if (!tables['OS/2'] || !validateOS2Table(tables['OS/2'])) { + // extract some more font properties from the OpenType head and + // hhea tables; yMin and descent value are always negative + var override = { + unitsPerEm: int16([tables.head.data[18], tables.head.data[19]]), + yMax: int16([tables.head.data[42], tables.head.data[43]]), + yMin: int16([tables.head.data[38], tables.head.data[39]]) - 0x10000, + ascent: int16([tables.hhea.data[4], tables.hhea.data[5]]), + descent: int16([tables.hhea.data[6], tables.hhea.data[7]]) - 0x10000 + }; + + tables['OS/2'] = { + tag: 'OS/2', + data: stringToArray(createOS2Table(properties, glyphs, override)) + }; + } + + // Rewrite the 'post' table if needed + if (!tables.post) { + tables.post = { + tag: 'post', + data: stringToArray(createPostTable(properties)) + }; + } + + if (!isTrueType) { + try { + // Trying to repair CFF file + var cffFile = new Stream(tables['CFF '].data); + var parser = new CFFParser(cffFile, properties); + var cff = parser.parse(); + var compiler = new CFFCompiler(cff); + tables['CFF '].data = compiler.compile(); + } catch (e) { + warn('Failed to compile font ' + properties.loadedName); + } + } + + // Re-creating 'name' table + if (!tables.name) { + tables.name = { + tag: 'name', + data: stringToArray(createNameTable(this.name)) + }; + } else { + // ... using existing 'name' table as prototype + var namePrototype = readNameTable(tables.name); + tables.name.data = stringToArray(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); + } + + // 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); + }, + + 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; + } + return true; + } + + // 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; + } + this.glyphNameMap = glyphNameMap; + + var seacs = font.seacs; + if (SEAC_ANALYSIS_ENABLED && seacs) { + var seacMap = []; + 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 baseGlyphName = Encodings.StandardEncoding[seac[2]]; + var baseUnicode = glyphNameMap[baseGlyphName]; + var accentGlyphName = Encodings.StandardEncoding[seac[3]]; + var accentUnicode = glyphNameMap[accentGlyphName]; + if (!baseUnicode || !accentUnicode) { + 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 + }; + } + 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, + + // OS/2 and Windows Specific metrics + 'OS/2': stringToArray(createOS2Table(properties, charstrings)), + + // 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() { + 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; + hmtx += string16(width) + string16(0); + } + return stringToArray(hmtx); + })(), + + // Maximum profile + 'maxp': (function fontFieldsMaxp() { + return stringToArray( + '\x00\x00\x50\x00' + // Version number + string16(charstrings.length + 1)); // Num of glyphs + })(), + + // Naming tables + 'name': stringToArray(createNameTable(fontName)), + + // PostScript informations + 'post': stringToArray(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); + }, + + 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; + } + } + 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]; + } + } 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; + } + } + 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; + } + cid++; + k++; + } + } else + cid += unicode.s; + } else if (unicode) { + cidToUnicodeMap[cid] = unicode; + if (!unicodeToCIDMap[unicode] || overwrite) { + unicodeToCIDMap[unicode] = cid; + } + cid++; + } else + cid++; + } + + 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 = []; + } + }, + + get spaceWidth() { + if ('_shadowWidth' in this) { + return this._shadowWidth; + } + + // trying to estimate space character width + var possibleSpaceReplacements = ['space', 'minus', 'one', 'i']; + var width; + for (var i = 0, ii = possibleSpaceReplacements.length; i < ii; i++) { + var glyphName = possibleSpaceReplacements[i]; + // if possible, getting width by glyph name + if (glyphName in this.widths) { + width = this.widths[glyphName]; + break; + } + var glyphUnicode = GlyphsUnicode[glyphName]; + // finding the charcode via unicodeToCID map + var charcode = 0; + if (this.composite) + charcode = this.unicodeToCID[glyphUnicode]; + // ... via toUnicode map + if (!charcode && 'toUnicode' in this) + charcode = this.toUnicode.indexOf(glyphUnicode); + // setting it to unicode if negative or undefined + if (charcode <= 0) + charcode = glyphUnicode; + // trying to get width via charcode + width = this.widths[charcode]; + if (width) + break; // the non-zero width found + } + width = width || this.defaultWidth; + // Do not shadow the property here. See discussion: + // https://github.com/mozilla/pdf.js/pull/2127#discussion_r1662280 + this._shadowWidth = width; + return width; + }, + + charToGlyph: function Font_charToGlyph(charcode) { + var fontCharCode, width, operatorList, disabled; + + 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 unicodeChars = !('toUnicode' in this) ? charcode : + this.toUnicode[charcode] || charcode; + if (typeof unicodeChars === 'number') { + unicodeChars = String.fromCharCode(unicodeChars); + } + + width = isNum(width) ? width : this.defaultWidth; + disabled = this.unicodeIsEnabled ? + !this.unicodeIsEnabled[fontCharCode] : false; + + var accent = null; + if (this.seacMap && this.seacMap[fontCharCode]) { + var seac = this.seacMap[fontCharCode]; + fontCharCode = seac.baseUnicode; + accent = { + fontChar: String.fromCharCode(seac.accentUnicode), + offset: seac.accentOffset + }; + } + + return { + fontChar: String.fromCharCode(fontCharCode), + unicode: unicodeChars, + accent: accent, + width: width, + vmetric: vmetric, + disabled: disabled, + operatorList: operatorList + }; + }, + + charsToGlyphs: function Font_charsToGlyphs(chars) { + var charsCache = this.charsCache; + var glyphs; + + // if we translated this string before, just grab it from the cache + if (charsCache) { + glyphs = charsCache[chars]; + if (glyphs) + return glyphs; + } + + // lazily create the translation cache + if (!charsCache) + charsCache = this.charsCache = Object.create(null); + + glyphs = []; + var charsCacheKey = chars; + + var 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; + // composite fonts have multi-byte strings convert the string from + // single-byte to multi-byte + while (i < chars.length) { + var c = this.cmap.readCharCode(chars, i); + var charcode = c[0]; + var length = c[1]; + i += length; + var glyph = this.charToGlyph(charcode); + glyphs.push(glyph); + // placing null after each word break charcode (ASCII SPACE) + // Ignore occurences of 0x20 in multiple-byte codes. + if (length === 1 && chars.charCodeAt(i - 1) === 0x20) { + glyphs.push(null); + } + } + } + else { + for (var i = 0, ii = chars.length; i < ii; ++i) { + var charcode = chars.charCodeAt(i); + var glyph = this.charToGlyph(charcode); + glyphs.push(glyph); + if (charcode == 0x20) + glyphs.push(null); + } + } + + // Enter the translated string into the cache + return (charsCache[charsCacheKey] = glyphs); + } + }; + + return Font; +})(); + +var ErrorFont = (function ErrorFontClosure() { + function ErrorFont(error) { + this.error = error; + } + + ErrorFont.prototype = { + charsToGlyphs: function ErrorFont_charsToGlyphs() { + return []; + }, + exportData: function ErrorFont_exportData() { + return {error: this.error}; + } + }; + + return ErrorFont; +})(); + +/* + * CharStrings are encoded following the the CharString Encoding sequence + * describe in Chapter 6 of the "Adobe Type1 Font Format" specification. + * The value in a byte indicates a command, a number, or subsequent bytes + * that are to be interpreted in a special way. + * + * CharString Number Encoding: + * A CharString byte containing the values from 32 through 255 inclusive + * indicate an integer. These values are decoded in four ranges. + * + * 1. A CharString byte containing a value, v, between 32 and 246 inclusive, + * indicate the integer v - 139. Thus, the integer values from -107 through + * 107 inclusive may be encoded in single byte. + * + * 2. A CharString byte containing a value, v, between 247 and 250 inclusive, + * indicates an integer involving the next byte, w, according to the formula: + * [(v - 247) x 256] + w + 108 + * + * 3. A CharString byte containing a value, v, between 251 and 254 inclusive, + * indicates an integer involving the next byte, w, according to the formula: + * -[(v - 251) * 256] - w - 108 + * + * 4. A CharString containing the value 255 indicates that the next 4 bytes + * are a two complement signed integer. The first of these bytes contains the + * highest order bits, the second byte contains the next higher order bits + * and the fourth byte contain the lowest order bits. + * + * + * CharString Command Encoding: + * CharStrings commands are encoded in 1 or 2 bytes. + * + * Single byte commands are encoded in 1 byte that contains a value between + * 0 and 31 inclusive. + * If a command byte contains the value 12, then the value in the next byte + * indicates a command. This "escape" mechanism allows many extra commands + * to be encoded and this encoding technique helps to minimize the length of + * the charStrings. + */ +var Type1CharString = (function Type1CharStringClosure() { + var COMMAND_MAP = { + 'hstem': [1], + 'vstem': [3], + 'vmoveto': [4], + 'rlineto': [5], + 'hlineto': [6], + 'vlineto': [7], + 'rrcurveto': [8], + 'callsubr': [10], + 'flex': [12, 35], + 'drop' : [12, 18], + 'endchar': [14], + 'rmoveto': [21], + 'hmoveto': [22], + 'vhcurveto': [30], + 'hvcurveto': [31] + }; + + function Type1CharString() { + this.width = 0; + this.lsb = 0; + this.flexing = false; + this.output = []; + this.stack = []; + } + + Type1CharString.prototype = { + convert: function Type1CharString_convert(encoded, subrs) { + var count = encoded.length; + var error = false; + for (var i = 0; i < count; i++) { + var value = encoded[i]; + if (value < 32) { + if (value === 12) { + value = (value << 8) + encoded[++i]; + } + switch (value) { + case 1: // hstem + if (!HINTING_ENABLED) { + this.stack = []; + break; + } + error = this.executeCommand(2, COMMAND_MAP.hstem); + break; + case 3: // vstem + if (!HINTING_ENABLED) { + this.stack = []; + break; + } + error = this.executeCommand(2, COMMAND_MAP.vstem); + break; + case 4: // vmoveto + if (this.flexing) { + if (this.stack.length < 1) { + error = true; + break; + } + // Add the dx for flex and but also swap the values so they are + // the right order. + var dy = this.stack.pop(); + this.stack.push(0, dy); + break; + } + error = this.executeCommand(1, COMMAND_MAP.vmoveto); + break; + case 5: // rlineto + error = this.executeCommand(2, COMMAND_MAP.rlineto); + break; + case 6: // hlineto + error = this.executeCommand(1, COMMAND_MAP.hlineto); + break; + case 7: // vlineto + error = this.executeCommand(1, COMMAND_MAP.vlineto); + break; + case 8: // rrcurveto + error = this.executeCommand(6, COMMAND_MAP.rrcurveto); + break; + case 9: // closepath + // closepath is a Type1 command that does not take argument and is + // useless in Type2 and it can simply be ignored. + this.stack = []; + break; + case 10: // callsubr + if (this.stack.length < 1) { + error = true; + break; + } + var subrNumber = this.stack.pop(); + error = this.convert(subrs[subrNumber], subrs); + break; + case 11: // return + return error; + case 13: // hsbw + if (this.stack.length < 2) { + error = true; + break; + } + // To convert to type2 we have to move the width value to the + // first part of the charstring and then use hmoveto with lsb. + var wx = this.stack.pop(); + var sbx = this.stack.pop(); + this.lsb = sbx; + this.width = wx; + this.stack.push(sbx); + error = this.executeCommand(1, COMMAND_MAP.hmoveto); + break; + case 14: // endchar + this.output.push(COMMAND_MAP.endchar[0]); + break; + case 21: // rmoveto + if (this.flexing) { + break; + } + error = this.executeCommand(2, COMMAND_MAP.rmoveto); + break; + case 22: // hmoveto + if (this.flexing) { + // Add the dy for flex. + this.stack.push(0); + break; + } + error = this.executeCommand(1, COMMAND_MAP.hmoveto); + break; + case 30: // vhcurveto + error = this.executeCommand(4, COMMAND_MAP.vhcurveto); + break; + case 31: // hvcurveto + error = this.executeCommand(4, COMMAND_MAP.hvcurveto); + break; + case (12 << 8) + 0: // dotsection + // dotsection is a Type1 command to specify some hinting feature + // for dots that do not take a parameter and it can safely be + // ignored for Type2. + this.stack = []; + break; + case (12 << 8) + 1: // vstem3 + if (!HINTING_ENABLED) { + this.stack = []; + break; + } + // [vh]stem3 are Type1 only and Type2 supports [vh]stem with + // multiple parameters, so instead of returning [vh]stem3 take a + // shortcut and return [vhstem] instead. + error = this.executeCommand(2, COMMAND_MAP.vstem); + break; + case (12 << 8) + 2: // hstem3 + if (!HINTING_ENABLED) { + this.stack = []; + break; + } + // See vstem3. + error = this.executeCommand(2, COMMAND_MAP.hstem); + break; + case (12 << 8) + 6: // seac + // seac is like type 2's special endchar but it doesn't use the + // first argument asb, so remove it. + if (SEAC_ANALYSIS_ENABLED) { + this.seac = this.stack.splice(-4, 4); + error = this.executeCommand(0, COMMAND_MAP.endchar); + } else { + error = this.executeCommand(4, COMMAND_MAP.endchar); + } + break; + case (12 << 8) + 7: // sbw + if (this.stack.length < 4) { + error = true; + break; + } + // To convert to type2 we have to move the width value to the + // first part of the charstring and then use rmoveto with + // (dx, dy). The height argument will not be used for vmtx and + // vhea tables reconstruction -- ignoring it. + var wy = this.stack.pop(); + var wx = this.stack.pop(); + var sby = this.stack.pop(); + var sbx = this.stack.pop(); + this.lsb = sbx; + this.width = wx; + this.stack.push(sbx, sby); + error = this.executeCommand(2, COMMAND_MAP.rmoveto); + break; + case (12 << 8) + 12: // div + if (this.stack.length < 2) { + error = true; + break; + } + var num2 = this.stack.pop(); + var num1 = this.stack.pop(); + this.stack.push(num1 / num2); + break; + case (12 << 8) + 16: // callothersubr + if (this.stack.length < 2) { + error = true; + break; + } + var subrNumber = this.stack.pop(); + var numArgs = this.stack.pop(); + if (subrNumber === 0 && numArgs === 3) { + var flexArgs = this.stack.splice(this.stack.length - 17, 17); + this.stack.push( + flexArgs[2] + flexArgs[0], // bcp1x + rpx + flexArgs[3] + flexArgs[1], // bcp1y + rpy + flexArgs[4], // bcp2x + flexArgs[5], // bcp2y + flexArgs[6], // p2x + flexArgs[7], // p2y + flexArgs[8], // bcp3x + flexArgs[9], // bcp3y + flexArgs[10], // bcp4x + flexArgs[11], // bcp4y + flexArgs[12], // p3x + flexArgs[13], // p3y + flexArgs[14] // flexDepth + // 15 = finalx unused by flex + // 16 = finaly unused by flex + ); + error = this.executeCommand(13, COMMAND_MAP.flex, true); + this.flexing = false; + this.stack.push(flexArgs[15], flexArgs[16]); + } else if (subrNumber === 1 && numArgs === 0) { + this.flexing = true; + } + break; + case (12 << 8) + 17: // pop + // Ignore this since it is only used with othersubr. + break; + case (12 << 8) + 33: // setcurrentpoint + // Ignore for now. + this.stack = []; + break; + default: + warn('Unknown type 1 charstring command of "' + value + '"'); + break; + } + if (error) { + break; + } + continue; + } else if (value <= 246) { + value = value - 139; + } else if (value <= 250) { + value = ((value - 247) * 256) + encoded[++i] + 108; + } else if (value <= 254) { + value = -((value - 251) * 256) - encoded[++i] - 108; + } else { + value = (encoded[++i] & 0xff) << 24 | (encoded[++i] & 0xff) << 16 | + (encoded[++i] & 0xff) << 8 | (encoded[++i] & 0xff) << 0; + } + this.stack.push(value); + } + return error; + }, + + executeCommand: function(howManyArgs, command, keepStack) { + var stackLength = this.stack.length; + if (howManyArgs > stackLength) { + return true; + } + var start = stackLength - howManyArgs; + for (var i = start; i < stackLength; i++) { + var value = this.stack[i]; + if (value === (value | 0)) { // int + this.output.push(28, (value >> 8) & 0xff, value & 0xff); + } else { // fixed point + value = (65536 * value) | 0; + this.output.push(255, + (value >> 24) & 0xFF, + (value >> 16) & 0xFF, + (value >> 8) & 0xFF, + value & 0xFF); + } + } + this.output.push.apply(this.output, command); + if (keepStack) { + this.stack.splice(start, howManyArgs); + } else { + this.stack = []; + } + return false; + } + }; + + return Type1CharString; +})(); + +/* + * Type1Parser encapsulate the needed code for parsing a Type1 font + * program. Some of its logic depends on the Type2 charstrings + * structure. + * Note: this doesn't really parse the font since that would require evaluation + * of PostScript, but it is possible in most cases to extract what we need + * without a full parse. + */ +var Type1Parser = (function Type1ParserClosure() { + /* + * Decrypt a Sequence of Ciphertext Bytes to Produce the Original Sequence + * of Plaintext Bytes. The function took a key as a parameter which can be + * for decrypting the eexec block of for decoding charStrings. + */ + var EEXEC_ENCRYPT_KEY = 55665; + var CHAR_STRS_ENCRYPT_KEY = 4330; + + function decrypt(stream, key, discardNumber) { + var r = key, c1 = 52845, c2 = 22719; + var decryptedString = []; + + var value = ''; + var count = stream.length; + for (var i = 0; i < count; i++) { + value = stream[i]; + decryptedString[i] = value ^ (r >> 8); + r = ((value + r) * c1 + c2) & ((1 << 16) - 1); + } + return decryptedString.slice(discardNumber); + } + + function isSpecial(c) { + return c === 0x2F || // '/' + c === 0x5B || c === 0x5D || // '[', ']' + c === 0x7B || c === 0x7D || // '{', '}' + c === 0x28 || c === 0x29; // '(', ')' + } + + function Type1Parser(stream, encrypted) { + if (encrypted) { + stream = new Stream(decrypt(stream.getBytes(), EEXEC_ENCRYPT_KEY, 4)); + } + this.stream = stream; + this.nextChar(); + } + + Type1Parser.prototype = { + readNumberArray: function Type1Parser_readNumberArray() { + this.getToken(); // read '[' or '{' (arrays can start with either) + var array = []; + while (true) { + var token = this.getToken(); + if (token === null || token === ']' || token === '}') { + break; + } + array.push(parseFloat(token || 0)); + } + return array; + }, + + readNumber: function Type1Parser_readNumber() { + var token = this.getToken(); + return parseFloat(token || 0); + }, + + readInt: function Type1Parser_readInt() { + // Use '| 0' to prevent setting a double into length such as the double + // does not flow into the loop variable. + var token = this.getToken(); + return parseInt(token || 0, 10) | 0; + }, + + readBoolean: function Type1Parser_readBoolean() { + var token = this.getToken(); + + // Use 1 and 0 since that's what type2 charstrings use. + return token === 'true' ? 1 : 0; + }, + + nextChar : function Type1_nextChar() { + return (this.currentChar = this.stream.getByte()); + }, + + getToken: function Type1Parser_getToken() { + // Eat whitespace and comments. + var comment = false; + var ch = this.currentChar; + while (true) { + if (ch === -1) { + return null; + } + + if (comment) { + if (ch === 0x0A || ch === 0x0D) { + comment = false; + } + } else if (ch === 0x25) { // '%' + comment = true; + } else if (!Lexer.isSpace(ch)) { + break; + } + ch = this.nextChar(); + } + if (isSpecial(ch)) { + this.nextChar(); + return String.fromCharCode(ch); + } + var token = ''; + do { + token += String.fromCharCode(ch); + ch = this.nextChar(); + } while (ch >= 0 && !Lexer.isSpace(ch) && !isSpecial(ch)); + return token; + }, + + /* + * Returns an object containing a Subrs array and a CharStrings + * array extracted from and eexec encrypted block of data + */ + extractFontProgram: function Type1Parser_extractFontProgram() { + var stream = this.stream; + + var subrs = [], charstrings = []; + var program = { + subrs: [], + charstrings: [], + properties: { + 'privateData': { + 'lenIV': 4 + } + } + }; + var token; + while ((token = this.getToken()) !== null) { + if (token !== '/') { + continue; + } + token = this.getToken(); + switch (token) { + case 'CharStrings': + // The number immediately following CharStrings must be greater or + // equal to the number of CharStrings. + this.getToken(); + this.getToken(); // read in 'dict' + this.getToken(); // read in 'dup' + this.getToken(); // read in 'begin' + while(true) { + token = this.getToken(); + if (token === null || token === 'end') { + break; + } + + if (token !== '/') { + continue; + } + var glyph = this.getToken(); + var 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); + // Skip past the required space and binary data. + stream.skip(length); + this.nextChar(); + token = this.getToken(); // read in 'ND' or '|-' + if (token === 'noaccess') { + this.getToken(); // read in 'def' + } + charstrings.push({ + glyph: glyph, + encoded: encoded + }); + } + break; + case 'Subrs': + var num = this.readInt(); + this.getToken(); // read in 'array' + while ((token = this.getToken()) === 'dup') { + var index = this.readInt(); + var 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); + // Skip past the required space and binary data. + stream.skip(length); + this.nextChar(); + token = this.getToken(); // read in 'NP' or '|' + if (token === 'noaccess') { + this.getToken(); // read in 'put' + } + subrs[index] = encoded; + } + break; + case 'BlueValues': + case 'OtherBlues': + case 'FamilyBlues': + case 'FamilyOtherBlues': + var blueArray = this.readNumberArray(); + // *Blue* values may contain invalid data: disables reading of + // those values when hinting is disabled. + if (blueArray.length > 0 && (blueArray.length % 2) === 0 && + HINTING_ENABLED) { + program.properties.privateData[token] = blueArray; + } + break; + case 'StemSnapH': + case 'StemSnapV': + program.properties.privateData[token] = this.readNumberArray(); + break; + case 'StdHW': + case 'StdVW': + program.properties.privateData[token] = + this.readNumberArray()[0]; + break; + case 'BlueShift': + case 'lenIV': + case 'BlueFuzz': + case 'BlueScale': + case 'LanguageGroup': + case 'ExpansionFactor': + program.properties.privateData[token] = this.readNumber(); + break; + case 'ForceBold': + program.properties.privateData[token] = this.readBoolean(); + break; + } + } + + for (var i = 0; i < charstrings.length; i++) { + var glyph = charstrings[i].glyph; + var encoded = charstrings[i].encoded; + var charString = new Type1CharString(); + var error = charString.convert(encoded, subrs); + var output = charString.output; + if (error) { + // It seems when FreeType encounters an error while evaluating a glyph + // that it completely ignores the glyph so we'll mimic that behaviour + // here and put an endchar to make the validator happy. + output = [14]; + } + program.charstrings.push({ + glyph: glyph, + data: output, + seac: charString.seac, + lsb: charString.lsb, + width: charString.width + }); + } + + return program; + }, + + extractFontHeader: function Type1Parser_extractFontHeader(properties) { + var token; + while ((token = this.getToken()) !== null) { + if (token !== '/') { + continue; + } + token = this.getToken(); + switch (token) { + case 'FontMatrix': + var matrix = this.readNumberArray(); + properties.fontMatrix = matrix; + break; + case 'Encoding': + var encodingArg = this.getToken(); + var encoding; + if (!/^\d+$/.test(encodingArg)) { + // encoding name is specified + encoding = Encodings[encodingArg]; + } else { + encoding = []; + var size = parseInt(encodingArg, 10) | 0; + this.getToken(); // read in 'array' + + for (var j = 0; j < size; j++) { + var token = this.getToken(); + // skipping till first dup or def (e.g. ignoring for statement) + while (token !== 'dup' && token !== 'def') { + token = this.getToken(); + if (token === null) { + return; // invalid header + } + } + if (token === 'def') { + break; // read all array data + } + var index = this.readInt(); + this.getToken(); // read in '/' + var glyph = this.getToken(); + encoding[index] = glyph; + this.getToken(); // read the in 'put' + } + } + if (properties.overridableEncoding && encoding) { + properties.baseEncoding = encoding; + break; + } + break; + case 'FontBBox': + var fontBBox = this.readNumberArray(); + // adjusting ascent/descent + properties.ascent = fontBBox[3]; + properties.descent = fontBBox[1]; + properties.ascentScaled = true; + break; + } + } + } + }; + + return Type1Parser; +})(); + +/** + * The CFF class takes a Type1 file and wrap it into a + * 'Compact Font Format' which itself embed Type2 charstrings. + */ +var CFFStandardStrings = [ + '.notdef', 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent', + 'ampersand', 'quoteright', 'parenleft', 'parenright', 'asterisk', 'plus', + 'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two', 'three', 'four', + 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', 'less', + 'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', + 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', + 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright', 'asciicircum', + 'underscore', 'quoteleft', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', + 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', + 'z', 'braceleft', 'bar', 'braceright', 'asciitilde', 'exclamdown', 'cent', + 'sterling', 'fraction', 'yen', 'florin', 'section', 'currency', + 'quotesingle', 'quotedblleft', 'guillemotleft', 'guilsinglleft', + 'guilsinglright', 'fi', 'fl', 'endash', 'dagger', 'daggerdbl', + 'periodcentered', 'paragraph', 'bullet', 'quotesinglbase', 'quotedblbase', + 'quotedblright', 'guillemotright', 'ellipsis', 'perthousand', 'questiondown', + 'grave', 'acute', 'circumflex', 'tilde', 'macron', 'breve', 'dotaccent', + 'dieresis', 'ring', 'cedilla', 'hungarumlaut', 'ogonek', 'caron', 'emdash', + 'AE', 'ordfeminine', 'Lslash', 'Oslash', 'OE', 'ordmasculine', 'ae', + 'dotlessi', 'lslash', 'oslash', 'oe', 'germandbls', 'onesuperior', + 'logicalnot', 'mu', 'trademark', 'Eth', 'onehalf', 'plusminus', 'Thorn', + 'onequarter', 'divide', 'brokenbar', 'degree', 'thorn', 'threequarters', + 'twosuperior', 'registered', 'minus', 'eth', 'multiply', 'threesuperior', + 'copyright', 'Aacute', 'Acircumflex', 'Adieresis', 'Agrave', 'Aring', + 'Atilde', 'Ccedilla', 'Eacute', 'Ecircumflex', 'Edieresis', 'Egrave', + 'Iacute', 'Icircumflex', 'Idieresis', 'Igrave', 'Ntilde', 'Oacute', + 'Ocircumflex', 'Odieresis', 'Ograve', 'Otilde', 'Scaron', 'Uacute', + 'Ucircumflex', 'Udieresis', 'Ugrave', 'Yacute', 'Ydieresis', 'Zcaron', + 'aacute', 'acircumflex', 'adieresis', 'agrave', 'aring', 'atilde', + 'ccedilla', 'eacute', 'ecircumflex', 'edieresis', 'egrave', 'iacute', + 'icircumflex', 'idieresis', 'igrave', 'ntilde', 'oacute', 'ocircumflex', + 'odieresis', 'ograve', 'otilde', 'scaron', 'uacute', 'ucircumflex', + 'udieresis', 'ugrave', 'yacute', 'ydieresis', 'zcaron', 'exclamsmall', + 'Hungarumlautsmall', 'dollaroldstyle', 'dollarsuperior', 'ampersandsmall', + 'Acutesmall', 'parenleftsuperior', 'parenrightsuperior', '266 ff', + 'onedotenleader', 'zerooldstyle', 'oneoldstyle', 'twooldstyle', + 'threeoldstyle', 'fouroldstyle', 'fiveoldstyle', 'sixoldstyle', + 'sevenoldstyle', 'eightoldstyle', 'nineoldstyle', 'commasuperior', + 'threequartersemdash', 'periodsuperior', 'questionsmall', 'asuperior', + 'bsuperior', 'centsuperior', 'dsuperior', 'esuperior', 'isuperior', + 'lsuperior', 'msuperior', 'nsuperior', 'osuperior', 'rsuperior', 'ssuperior', + 'tsuperior', 'ff', 'ffi', 'ffl', 'parenleftinferior', 'parenrightinferior', + 'Circumflexsmall', 'hyphensuperior', 'Gravesmall', 'Asmall', 'Bsmall', + 'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall', 'Hsmall', 'Ismall', + 'Jsmall', 'Ksmall', 'Lsmall', 'Msmall', 'Nsmall', 'Osmall', 'Psmall', + 'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall', 'Vsmall', 'Wsmall', + 'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary', 'onefitted', 'rupiah', + 'Tildesmall', 'exclamdownsmall', 'centoldstyle', 'Lslashsmall', + 'Scaronsmall', 'Zcaronsmall', 'Dieresissmall', 'Brevesmall', 'Caronsmall', + 'Dotaccentsmall', 'Macronsmall', 'figuredash', 'hypheninferior', + 'Ogoneksmall', 'Ringsmall', 'Cedillasmall', 'questiondownsmall', 'oneeighth', + 'threeeighths', 'fiveeighths', 'seveneighths', 'onethird', 'twothirds', + 'zerosuperior', 'foursuperior', 'fivesuperior', 'sixsuperior', + 'sevensuperior', 'eightsuperior', 'ninesuperior', 'zeroinferior', + 'oneinferior', 'twoinferior', 'threeinferior', 'fourinferior', + 'fiveinferior', 'sixinferior', 'seveninferior', 'eightinferior', + 'nineinferior', 'centinferior', 'dollarinferior', 'periodinferior', + 'commainferior', 'Agravesmall', 'Aacutesmall', 'Acircumflexsmall', + 'Atildesmall', 'Adieresissmall', 'Aringsmall', 'AEsmall', 'Ccedillasmall', + 'Egravesmall', 'Eacutesmall', 'Ecircumflexsmall', 'Edieresissmall', + 'Igravesmall', 'Iacutesmall', 'Icircumflexsmall', 'Idieresissmall', + 'Ethsmall', 'Ntildesmall', 'Ogravesmall', 'Oacutesmall', 'Ocircumflexsmall', + 'Otildesmall', 'Odieresissmall', 'OEsmall', 'Oslashsmall', 'Ugravesmall', + 'Uacutesmall', 'Ucircumflexsmall', 'Udieresissmall', 'Yacutesmall', + 'Thornsmall', 'Ydieresissmall', '001.000', '001.001', '001.002', '001.003', + 'Black', 'Bold', 'Book', 'Light', 'Medium', 'Regular', 'Roman', 'Semibold' +]; + +// Type1Font is also a CIDFontType0. +var Type1Font = function Type1Font(name, file, properties) { + // Some bad generators embed pfb file as is, we have to strip 6-byte headers. + // Also, length1 and length2 might be off by 6 bytes as well. + // http://www.math.ubc.ca/~cass/piscript/type1.pdf + var PFB_HEADER_SIZE = 6; + var headerBlockLength = properties.length1; + var eexecBlockLength = properties.length2; + var pfbHeader = file.peekBytes(PFB_HEADER_SIZE); + var pfbHeaderPresent = pfbHeader[0] == 0x80 && pfbHeader[1] == 0x01; + if (pfbHeaderPresent) { + file.skip(PFB_HEADER_SIZE); + headerBlockLength = (pfbHeader[5] << 24) | (pfbHeader[4] << 16) | + (pfbHeader[3] << 8) | pfbHeader[2]; + } + + // Get the data block containing glyphs and subrs informations + var headerBlock = new Stream(file.getBytes(headerBlockLength)); + var headerBlockParser = new Type1Parser(headerBlock); + headerBlockParser.extractFontHeader(properties); + + if (pfbHeaderPresent) { + pfbHeader = file.getBytes(PFB_HEADER_SIZE); + eexecBlockLength = (pfbHeader[5] << 24) | (pfbHeader[4] << 16) | + (pfbHeader[3] << 8) | pfbHeader[2]; + } + + // Decrypt the data blocks and retrieve it's content + var eexecBlock = new Stream(file.getBytes(eexecBlockLength)); + var eexecBlockParser = new Type1Parser(eexecBlock, true); + var data = eexecBlockParser.extractFontProgram(); + for (var info in data.properties) + properties[info] = data.properties[info]; + + var charstrings = this.getOrderedCharStrings(data.charstrings, properties); + var type2Charstrings = this.getType2Charstrings(charstrings); + var subrs = this.getType2Subrs(data.subrs); + + this.charstrings = charstrings; + this.data = this.wrap(name, type2Charstrings, this.charstrings, + subrs, properties); + this.seacs = this.getSeacs(data.charstrings); +}; + +Type1Font.prototype = { + 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++; + } + 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; + }, + + getSeacs: function Type1Font_getSeacs(charstrings) { + var i, ii; + var seacMap = []; + for (i = 0, ii = charstrings.length; i < ii; i++) { + var charstring = charstrings[i]; + if (charstring.seac) { + seacMap[i] = charstring.seac; + } + } + return seacMap; + }, + + getType2Charstrings: function Type1Font_getType2Charstrings( + type1Charstrings) { + var type2Charstrings = []; + for (var i = 0, ii = type1Charstrings.length; i < ii; i++) { + type2Charstrings.push(type1Charstrings[i].charstring); + } + return type2Charstrings; + }, + + getType2Subrs: function Type1Font_getType2Subrs(type1Subrs) { + var bias = 0; + var count = type1Subrs.length; + if (count < 1133) + bias = 107; + else if (count < 33769) + bias = 1131; + else + bias = 32768; + + // Add a bunch of empty subrs to deal with the Type2 bias + var type2Subrs = []; + for (var i = 0; i < bias; i++) + type2Subrs.push([0x0B]); + + for (var i = 0; i < count; i++) { + type2Subrs.push(type1Subrs[i]); + } + + return type2Subrs; + }, + + wrap: function Type1Font_wrap(name, glyphs, charstrings, subrs, properties) { + var cff = new CFF(); + cff.header = new CFFHeader(1, 0, 4, 4); + + cff.names = [name]; + + var topDict = new CFFTopDict(); + // CFF strings IDs 0...390 are predefined names, so refering + // to entries in our own String INDEX starts at SID 391. + topDict.setByName('version', 391); + topDict.setByName('Notice', 392); + topDict.setByName('FullName', 393); + topDict.setByName('FamilyName', 394); + topDict.setByName('Weight', 395); + topDict.setByName('Encoding', null); // placeholder + topDict.setByName('FontMatrix', properties.fontMatrix); + topDict.setByName('FontBBox', properties.bbox); + topDict.setByName('charset', null); // placeholder + topDict.setByName('CharStrings', null); // placeholder + topDict.setByName('Private', null); // placeholder + cff.topDict = topDict; + + var strings = new CFFStrings(); + strings.add('Version 0.11'); // Version + strings.add('See original notice'); // Notice + strings.add(name); // FullName + strings.add(name); // FamilyName + strings.add('Medium'); // Weight + cff.strings = strings; + + cff.globalSubrIndex = new CFFIndex(); + + var count = glyphs.length; + var charsetArray = [0]; + 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) + 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++) { + charStringsIndex.add(glyphs[i]); + } + cff.charStrings = charStringsIndex; + + var privateDict = new CFFPrivateDict(); + privateDict.setByName('Subrs', null); // placeholder + var fields = [ + 'BlueValues', + 'OtherBlues', + 'FamilyBlues', + 'FamilyOtherBlues', + 'StemSnapH', + 'StemSnapV', + 'BlueShift', + 'BlueFuzz', + 'BlueScale', + 'LanguageGroup', + 'ExpansionFactor', + 'ForceBold', + 'StdHW', + 'StdVW' + ]; + for (var i = 0, ii = fields.length; i < ii; i++) { + var field = fields[i]; + if (!properties.privateData.hasOwnProperty(field)) + continue; + var value = properties.privateData[field]; + if (isArray(value)) { + // All of the private dictionary array data in CFF must be stored as + // "delta-encoded" numbers. + for (var j = value.length - 1; j > 0; j--) { + value[j] -= value[j - 1]; // ... difference from previous value + } + } + privateDict.setByName(field, value); + } + cff.topDict.privateDict = privateDict; + + var subrIndex = new CFFIndex(); + for (var i = 0, ii = subrs.length; i < ii; i++) { + subrIndex.add(subrs[i]); + } + privateDict.subrsIndex = subrIndex; + + var compiler = new CFFCompiler(cff); + return compiler.compile(); + } +}; + +var CFFFont = (function CFFFontClosure() { + function CFFFont(file, properties) { + this.properties = properties; + + var parser = new CFFParser(file, properties); + this.cff = parser.parse(); + var compiler = new CFFCompiler(this.cff); + this.readExtra(); + try { + this.data = compiler.compile(); + } catch (e) { + warn('Failed to compile font ' + properties.loadedName); + // There may have just been an issue with the compiler, set the data + // anyway and hope the font loaded. + this.data = file; + } + } + + CFFFont.prototype = { + 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; + }, + getCharStrings: function CFFFont_getCharStrings() { + var cff = this.cff; + 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) { + // If the font is actually a CID font then we should use the charset + // to map CIDs to GIDs. + inverseEncoding = charsets; + } 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 (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; + } + }; + + return CFFFont; +})(); + +var CFFParser = (function CFFParserClosure() { + var CharstringValidationData = [ + null, + { id: 'hstem', min: 2, resetStack: true, stem: true }, + null, + { id: 'vstem', min: 2, resetStack: true, stem: true }, + { id: 'vmoveto', min: 1, resetStack: true }, + { id: 'rlineto', min: 2, resetStack: true }, + { id: 'hlineto', min: 1, resetStack: true }, + { id: 'vlineto', min: 1, resetStack: true }, + { id: 'rrcurveto', min: 6, resetStack: true }, + null, + { id: 'callsubr', min: 1, undefStack: true }, + { id: 'return', min: 0, undefStack: true }, + null, // 12 + null, + null, // endchar + 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: 'rcurveline', min: 8, resetStack: true }, + { id: 'rlinecurve', min: 8, resetStack: true }, + { id: 'vvcurveto', min: 4, resetStack: true }, + { id: 'hhcurveto', min: 4, resetStack: true }, + null, // shortint + { id: 'callgsubr', min: 1, undefStack: true }, + { id: 'vhcurveto', min: 4, resetStack: true }, + { id: 'hvcurveto', min: 4, resetStack: true } + ]; + var CharstringValidationData12 = [ + null, + null, + null, + { id: 'and', min: 2, stackDelta: -1 }, + { id: 'or', min: 2, stackDelta: -1 }, + { id: 'not', min: 1, stackDelta: 0 }, + null, + null, + null, + { id: 'abs', min: 1, stackDelta: 0 }, + { id: 'add', min: 2, stackDelta: -1, + stackFn: function stack_div(stack, index) { + stack[index - 2] = stack[index - 2] + stack[index - 1]; + } + }, + { id: 'sub', min: 2, stackDelta: -1, + stackFn: function stack_div(stack, index) { + stack[index - 2] = stack[index - 2] - stack[index - 1]; + } + }, + { id: 'div', min: 2, stackDelta: -1, + stackFn: function stack_div(stack, index) { + stack[index - 2] = stack[index - 2] / stack[index - 1]; + } + }, + null, + { id: 'neg', min: 1, stackDelta: 0, + stackFn: function stack_div(stack, index) { + stack[index - 1] = -stack[index - 1]; + } + }, + { id: 'eq', min: 2, stackDelta: -1 }, + null, + null, + { id: 'drop', min: 1, stackDelta: -1 }, + null, + { id: 'put', min: 2, stackDelta: -2 }, + { id: 'get', min: 1, stackDelta: 0 }, + { id: 'ifelse', min: 4, stackDelta: -3 }, + { id: 'random', min: 0, stackDelta: 1 }, + { id: 'mul', min: 2, stackDelta: -1, + stackFn: function stack_div(stack, index) { + stack[index - 2] = stack[index - 2] * stack[index - 1]; + } + }, + null, + { id: 'sqrt', min: 1, stackDelta: 0 }, + { id: 'dup', min: 1, stackDelta: 1 }, + { id: 'exch', min: 2, stackDelta: 0 }, + { id: 'index', min: 2, stackDelta: 0 }, + { id: 'roll', min: 3, stackDelta: -2 }, + null, + null, + null, + { id: 'hflex', min: 7, resetStack: true }, + { id: 'flex', min: 13, resetStack: true }, + { id: 'hflex1', min: 9, resetStack: true }, + { id: 'flex1', min: 11, resetStack: true } + ]; + + function CFFParser(file, properties) { + this.bytes = file.getBytes(); + this.properties = properties; + } + CFFParser.prototype = { + parse: function CFFParser_parse() { + var properties = this.properties; + var cff = new CFF(); + this.cff = cff; + + // The first five sections must be in order, all the others are reached + // via offsets contained in one of the below. + var header = this.parseHeader(); + var nameIndex = this.parseIndex(header.endPos); + var topDictIndex = this.parseIndex(nameIndex.endPos); + var stringIndex = this.parseIndex(topDictIndex.endPos); + var globalSubrIndex = this.parseIndex(stringIndex.endPos); + + var topDictParsed = this.parseDict(topDictIndex.obj.get(0)); + var topDict = this.createDict(CFFTopDict, topDictParsed, cff.strings); + + cff.header = header.obj; + cff.names = this.parseNameIndex(nameIndex.obj); + cff.strings = this.parseStringIndex(stringIndex.obj); + cff.topDict = topDict; + cff.globalSubrIndex = globalSubrIndex.obj; + + this.parsePrivateDict(cff.topDict); + + cff.isCIDFont = topDict.hasName('ROS'); + + var charStringOffset = topDict.getByName('CharStrings'); + var charStringsAndSeacs = this.parseCharStrings(charStringOffset); + cff.charStrings = charStringsAndSeacs.charStrings; + cff.seacs = charStringsAndSeacs.seacs; + + var fontMatrix = topDict.getByName('FontMatrix'); + if (fontMatrix) { + properties.fontMatrix = fontMatrix; + } + + var fontBBox = topDict.getByName('FontBBox'); + if (fontBBox) { + // adjusting ascent/descent + properties.ascent = fontBBox[3]; + properties.descent = fontBBox[1]; + properties.ascentScaled = true; + } + + var charset, encoding; + if (cff.isCIDFont) { + var fdArrayIndex = this.parseIndex(topDict.getByName('FDArray')).obj; + for (var i = 0, ii = fdArrayIndex.count; i < ii; ++i) { + var dictRaw = fdArrayIndex.get(i); + var fontDict = this.createDict(CFFTopDict, this.parseDict(dictRaw), + cff.strings); + this.parsePrivateDict(fontDict); + cff.fdArray.push(fontDict); + } + // cid fonts don't have an encoding + encoding = null; + charset = this.parseCharsets(topDict.getByName('charset'), + cff.charStrings.count, cff.strings, true); + cff.fdSelect = this.parseFDSelect(topDict.getByName('FDSelect'), + cff.charStrings.count); + } else { + charset = this.parseCharsets(topDict.getByName('charset'), + cff.charStrings.count, cff.strings, false); + encoding = this.parseEncoding(topDict.getByName('Encoding'), + properties, + cff.strings, charset.charset); + } + cff.charset = charset; + cff.encoding = encoding; + + return cff; + }, + parseHeader: function CFFParser_parseHeader() { + var bytes = this.bytes; + var offset = 0; + + while (bytes[offset] != 1) + ++offset; + + if (offset !== 0) { + info('cff data is shifted'); + bytes = bytes.subarray(offset); + this.bytes = bytes; + } + var major = bytes[0]; + var minor = bytes[1]; + var hdrSize = bytes[2]; + var offSize = bytes[3]; + var header = new CFFHeader(major, minor, hdrSize, offSize); + return {obj: header, endPos: hdrSize}; + }, + parseDict: function CFFParser_parseDict(dict) { + var pos = 0; + + function parseOperand() { + var value = dict[pos++]; + if (value === 30) { + return parseFloatOperand(pos); + } else if (value === 28) { + value = dict[pos++]; + value = ((value << 24) | (dict[pos++] << 16)) >> 16; + return value; + } else if (value === 29) { + value = dict[pos++]; + value = (value << 8) | dict[pos++]; + value = (value << 8) | dict[pos++]; + value = (value << 8) | dict[pos++]; + return value; + } else if (value >= 32 && value <= 246) { + return value - 139; + } else if (value >= 247 && value <= 250) { + return ((value - 247) * 256) + dict[pos++] + 108; + } else if (value >= 251 && value <= 254) { + return -((value - 251) * 256) - dict[pos++] - 108; + } else { + error('255 is not a valid DICT command'); + } + return -1; + } + + function parseFloatOperand() { + var str = ''; + var eof = 15; + var lookup = ['0', '1', '2', '3', '4', '5', '6', '7', '8', + '9', '.', 'E', 'E-', null, '-']; + var length = dict.length; + while (pos < length) { + var b = dict[pos++]; + var b1 = b >> 4; + var b2 = b & 15; + + if (b1 == eof) + break; + str += lookup[b1]; + + if (b2 == eof) + break; + str += lookup[b2]; + } + return parseFloat(str); + } + + var operands = []; + var entries = []; + + var pos = 0; + var end = dict.length; + while (pos < end) { + var b = dict[pos]; + if (b <= 21) { + if (b === 12) + b = (b << 8) | dict[++pos]; + entries.push([b, operands]); + operands = []; + ++pos; + } else { + operands.push(parseOperand()); + } + } + return entries; + }, + parseIndex: function CFFParser_parseIndex(pos) { + var cffIndex = new CFFIndex(); + var bytes = this.bytes; + var count = (bytes[pos++] << 8) | bytes[pos++]; + var offsets = []; + var start = pos; + var end = pos; + + 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) { + var offset = 0; + for (var j = 0; j < offsetSize; ++j) { + offset <<= 8; + offset += bytes[pos++]; + } + offsets.push(startPos + offset); + } + end = offsets[count]; + } + for (var i = 0, ii = offsets.length - 1; i < ii; ++i) { + var offsetStart = offsets[i]; + var offsetEnd = offsets[i + 1]; + cffIndex.add(bytes.subarray(offsetStart, offsetEnd)); + } + return {obj: cffIndex, endPos: end}; + }, + parseNameIndex: function CFFParser_parseNameIndex(index) { + var names = []; + for (var i = 0, ii = index.count; i < ii; ++i) { + var name = index.get(i); + // OTS doesn't allow names to be over 127 characters. + var length = Math.min(name.length, 127); + var data = []; + // OTS also only permits certain characters in the name. + for (var j = 0; j < length; ++j) { + var c = name[j]; + if (j === 0 && c === 0) { + data[j] = c; + continue; + } + if ((c < 33 || c > 126) || c === 91 /* [ */ || c === 93 /* ] */ || + c === 40 /* ( */ || c === 41 /* ) */ || c === 123 /* { */ || + c === 125 /* } */ || c === 60 /* < */ || c === 62 /* > */ || + c === 47 /* / */ || c === 37 /* % */) { + data[j] = 95; + continue; + } + data[j] = c; + } + names.push(String.fromCharCode.apply(null, data)); + } + return names; + }, + parseStringIndex: function CFFParser_parseStringIndex(index) { + var strings = new CFFStrings(); + for (var i = 0, ii = index.count; i < ii; ++i) { + var data = index.get(i); + strings.add(String.fromCharCode.apply(null, 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]; + var value = pair[1]; + cffDict.setByKey(key, value); + } + return cffDict; + }, + parseCharStrings: function CFFParser_parseCharStrings(charStringOffset) { + var charStrings = this.parseIndex(charStringOffset).obj; + var seacs = []; + var count = charStrings.count; + for (var i = 0; i < count; i++) { + var charstring = charStrings.get(i); + + var stackSize = 0; + var stack = []; + var undefStack = true; + var hints = 0; + var valid = true; + var data = charstring; + var length = data.length; + for (var j = 0; j < length;) { + var value = data[j++]; + var validationCommand = null; + if (value == 12) { + var q = data[j++]; + if (q === 0) { + // The CFF specification state that the 'dotsection' command + // (12, 0) is deprecated and treated as a no-op, but all Type2 + // charstrings processors should support them. Unfortunately + // the font sanitizer don't. As a workaround the sequence (12, 0) + // is replaced by a useless (0, hmoveto). + data[j - 2] = 139; + data[j - 1] = 22; + stackSize = 0; + } else { + validationCommand = CharstringValidationData12[q]; + } + } else if (value === 28) { // number (16 bit) + stack[stackSize] = ((data[j] << 24) | (data[j + 1] << 16)) >> 16; + j += 2; + stackSize++; + } else if (value == 14) { + if (stackSize >= 4) { + stackSize -= 4; + if (SEAC_ANALYSIS_ENABLED) { + seacs[i] = stack.slice(stackSize, stackSize + 4); + valid = false; + } + } + } else if (value >= 32 && value <= 246) { // number + stack[stackSize] = value - 139; + stackSize++; + } else if (value >= 247 && value <= 254) { // number (+1 bytes) + stack[stackSize] = value < 251 ? + ((value - 247) << 8) + data[j] + 108 : + -((value - 251) << 8) - data[j] - 108; + j++; + stackSize++; + } else if (value == 255) { // number (32 bit) + stack[stackSize] = ((data[j] << 24) | (data[j + 1] << 16) | + (data[j + 2] << 8) | data[j + 3]) / 65536; + j += 4; + stackSize++; + } else if (value == 19 || value == 20) { + hints += stackSize >> 1; + j += (hints + 7) >> 3; // skipping right amount of hints flag data + stackSize = 0; + } else { + validationCommand = CharstringValidationData[value]; + } + if (validationCommand) { + if (validationCommand.stem) { + hints += stackSize >> 1; + } + if ('min' in validationCommand) { + if (!undefStack && stackSize < validationCommand.min) { + warn('Not enough parameters for ' + validationCommand.id + + '; actual: ' + stackSize + + ', expected: ' + validationCommand.min); + valid = false; + break; + } + } + if ('stackDelta' in validationCommand) { + if ('stackFn' in validationCommand) { + validationCommand.stackFn(stack, stackSize); + } + stackSize += validationCommand.stackDelta; + } else if (validationCommand.resetStack) { + stackSize = 0; + undefStack = false; + } else if (validationCommand.undefStack) { + stackSize = 0; + undefStack = true; + } + } + } + if (!valid) { + // resetting invalid charstring to single 'endchar' + charStrings.set(i, new Uint8Array([14])); + } + } + return { charStrings: charStrings, seacs: seacs }; + }, + emptyPrivateDictionary: + function CFFParser_emptyPrivateDictionary(parentDict) { + var privateDict = this.createDict(CFFPrivateDict, [], + parentDict.strings); + parentDict.setByKey(18, [0, 0]); + parentDict.privateDict = privateDict; + }, + parsePrivateDict: function CFFParser_parsePrivateDict(parentDict) { + // no private dict, do nothing + if (!parentDict.hasName('Private')) { + this.emptyPrivateDictionary(parentDict); + return; + } + var privateOffset = parentDict.getByName('Private'); + // make sure the params are formatted correctly + if (!isArray(privateOffset) || privateOffset.length !== 2) { + parentDict.removeByName('Private'); + return; + } + var size = privateOffset[0]; + var offset = privateOffset[1]; + // remove empty dicts or ones that refer to invalid location + if (size === 0 || offset >= this.bytes.length) { + this.emptyPrivateDictionary(parentDict); + return; + } + + var privateDictEnd = offset + size; + var dictData = this.bytes.subarray(offset, privateDictEnd); + var dict = this.parseDict(dictData); + var privateDict = this.createDict(CFFPrivateDict, dict, + parentDict.strings); + parentDict.privateDict = privateDict; + + // Parse the Subrs index also since it's relative to the private dict. + if (!privateDict.getByName('Subrs')) + return; + var subrsOffset = privateDict.getByName('Subrs'); + var relativeOffset = offset + subrsOffset; + // Validate the offset. + if (subrsOffset === 0 || relativeOffset >= this.bytes.length) { + this.emptyPrivateDictionary(parentDict); + return; + } + var subrsIndex = this.parseIndex(relativeOffset); + privateDict.subrsIndex = subrsIndex.obj; + }, + parseCharsets: function CFFParser_parseCharsets(pos, length, strings, cid) { + if (pos === 0) { + return new CFFCharset(true, CFFCharsetPredefinedTypes.ISO_ADOBE, + ISOAdobeCharset); + } else if (pos == 1) { + return new CFFCharset(true, CFFCharsetPredefinedTypes.EXPERT, + ExpertCharset); + } else if (pos == 2) { + return new CFFCharset(true, CFFCharsetPredefinedTypes.EXPERT_SUBSET, + ExpertSubsetCharset); + } + + var bytes = this.bytes; + var start = pos; + var format = bytes[pos++]; + var charset = ['.notdef']; + + // 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++]; + 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++) + 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++) + charset.push(cid ? id++ : strings.get(id++)); + } + break; + default: + error('Unknown charset format'); + } + // Raw won't be needed if we actually compile the charset. + var end = pos; + var raw = bytes.subarray(start, end); + + return new CFFCharset(false, format, charset, raw); + }, + parseEncoding: function CFFParser_parseEncoding(pos, + properties, + strings, + charset) { + var encoding = {}; + var bytes = this.bytes; + var predefined = false; + var hasSupplement = false; + var format; + var raw = null; + + function readSupplement() { + var supplementsCount = bytes[pos++]; + for (var i = 0; i < supplementsCount; i++) { + var code = bytes[pos++]; + var sid = (bytes[pos++] << 8) + (bytes[pos++] & 0xff); + encoding[code] = charset.indexOf(strings.get(sid)); + } + } + + if (pos === 0 || pos == 1) { + predefined = true; + format = pos; + var baseEncoding = pos ? Encodings.ExpertEncoding : + Encodings.StandardEncoding; + for (var i = 0, ii = charset.length; i < ii; i++) { + var index = baseEncoding.indexOf(charset[i]); + if (index != -1) { + encoding[index] = i; + } + } + } else { + var dataStart = pos; + var format = bytes[pos++]; + switch (format & 0x7f) { + case 0: + var glyphsCount = bytes[pos++]; + for (var 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++) { + var start = bytes[pos++]; + var left = bytes[pos++]; + for (var j = start; j <= start + left; j++) + encoding[j] = gid++; + } + break; + + default: + error('Unknow encoding format: ' + format + ' in CFF'); + break; + } + var dataEnd = pos; + if (format & 0x80) { + // The font sanitizer does not support CFF encoding with a + // supplement, since the encoding is not really used to map + // between gid to glyph, let's overwrite what is declared in + // the top dictionary to let the sanitizer think the font use + // StandardEncoding, that's a lie but that's ok. + bytes[dataStart] &= 0x7f; + readSupplement(); + hasSupplement = true; + } + raw = bytes.subarray(dataStart, dataEnd); + } + format = format & 0x7f; + return new CFFEncoding(predefined, format, encoding, raw); + }, + parseFDSelect: function CFFParser_parseFDSelect(pos, length) { + var start = pos; + var bytes = this.bytes; + var format = bytes[pos++]; + var fdSelect = []; + switch (format) { + case 0: + for (var 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) { + var first = (bytes[pos++] << 8) | bytes[pos++]; + var fdIndex = bytes[pos++]; + var next = (bytes[pos] << 8) | bytes[pos + 1]; + for (var j = first; j < next; ++j) + fdSelect.push(fdIndex); + } + // Advance past the sentinel(next). + pos += 2; + break; + default: + error('Unknown fdselect format ' + format); + break; + } + var end = pos; + return new CFFFDSelect(fdSelect, bytes.subarray(start, end)); + } + }; + return CFFParser; +})(); + +// Compact Font Format +var CFF = (function CFFClosure() { + function CFF() { + this.header = null; + this.names = []; + this.topDict = null; + this.strings = new CFFStrings(); + this.globalSubrIndex = null; + + // The following could really be per font, but since we only have one font + // store them here. + this.encoding = null; + this.charset = null; + this.charStrings = null; + this.fdArray = []; + this.fdSelect = null; + + this.isCIDFont = false; + } + return CFF; +})(); + +var CFFHeader = (function CFFHeaderClosure() { + function CFFHeader(major, minor, hdrSize, offSize) { + this.major = major; + this.minor = minor; + this.hdrSize = hdrSize; + this.offSize = offSize; + } + return CFFHeader; +})(); + +var CFFStrings = (function CFFStringsClosure() { + function CFFStrings() { + this.strings = []; + } + CFFStrings.prototype = { + get: function CFFStrings_get(index) { + if (index >= 0 && index <= 390) + return CFFStandardStrings[index]; + if (index - 391 <= this.strings.length) + return this.strings[index - 391]; + return CFFStandardStrings[0]; + }, + add: function CFFStrings_add(value) { + this.strings.push(value); + }, + get count() { + return this.strings.length; + } + }; + return CFFStrings; +})(); + +var CFFIndex = (function CFFIndexClosure() { + function CFFIndex() { + this.objects = []; + this.length = 0; + } + CFFIndex.prototype = { + add: function CFFIndex_add(data) { + this.length += data.length; + this.objects.push(data); + }, + set: function CFFIndex_set(index, data) { + this.length += data.length - this.objects[index].length; + this.objects[index] = data; + }, + get: function CFFIndex_get(index) { + return this.objects[index]; + }, + get count() { + return this.objects.length; + } + }; + return CFFIndex; +})(); + +var CFFDict = (function CFFDictClosure() { + function CFFDict(tables, strings) { + this.keyToNameMap = tables.keyToNameMap; + this.nameToKeyMap = tables.nameToKeyMap; + this.defaults = tables.defaults; + this.types = tables.types; + this.opcodes = tables.opcodes; + this.order = tables.order; + this.strings = strings; + this.values = {}; + } + CFFDict.prototype = { + // value should always be an array + setByKey: function CFFDict_setByKey(key, value) { + if (!(key in this.keyToNameMap)) + return false; + // ignore empty values + if (value.length === 0) + return true; + var type = this.types[key]; + // remove the array wrapping these types of values + if (type === 'num' || type === 'sid' || type === 'offset') + value = value[0]; + this.values[key] = value; + return true; + }, + setByName: function CFFDict_setByName(name, value) { + if (!(name in this.nameToKeyMap)) { + error('Invalid dictionary name "' + name + '"'); + } + this.values[this.nameToKeyMap[name]] = value; + }, + hasName: function CFFDict_hasName(name) { + return this.nameToKeyMap[name] in this.values; + }, + getByName: function CFFDict_getByName(name) { + if (!(name in this.nameToKeyMap)) + error('Invalid dictionary name "' + name + '"'); + var key = this.nameToKeyMap[name]; + if (!(key in this.values)) + return this.defaults[key]; + return this.values[key]; + }, + removeByName: function CFFDict_removeByName(name) { + delete this.values[this.nameToKeyMap[name]]; + } + }; + CFFDict.createTables = function CFFDict_createTables(layout) { + var tables = { + keyToNameMap: {}, + nameToKeyMap: {}, + defaults: {}, + types: {}, + opcodes: {}, + order: [] + }; + for (var i = 0, ii = layout.length; i < ii; ++i) { + var entry = layout[i]; + var key = isArray(entry[0]) ? (entry[0][0] << 8) + entry[0][1] : entry[0]; + tables.keyToNameMap[key] = entry[1]; + tables.nameToKeyMap[entry[1]] = key; + tables.types[key] = entry[2]; + tables.defaults[key] = entry[3]; + tables.opcodes[key] = isArray(entry[0]) ? entry[0] : [entry[0]]; + tables.order.push(key); + } + return tables; + }; + return CFFDict; +})(); + +var CFFTopDict = (function CFFTopDictClosure() { + var layout = [ + [[12, 30], 'ROS', ['sid', 'sid', 'num'], null], + [[12, 20], 'SyntheticBase', 'num', null], + [0, 'version', 'sid', null], + [1, 'Notice', 'sid', null], + [[12, 0], 'Copyright', 'sid', null], + [2, 'FullName', 'sid', null], + [3, 'FamilyName', 'sid', null], + [4, 'Weight', 'sid', null], + [[12, 1], 'isFixedPitch', 'num', 0], + [[12, 2], 'ItalicAngle', 'num', 0], + [[12, 3], 'UnderlinePosition', 'num', -100], + [[12, 4], 'UnderlineThickness', 'num', 50], + [[12, 5], 'PaintType', 'num', 0], + [[12, 6], 'CharstringType', 'num', 2], + [[12, 7], 'FontMatrix', ['num', 'num', 'num', 'num', 'num', 'num'], + [0.001, 0, 0, 0.001, 0, 0]], + [13, 'UniqueID', 'num', null], + [5, 'FontBBox', ['num', 'num', 'num', 'num'], [0, 0, 0, 0]], + [[12, 8], 'StrokeWidth', 'num', 0], + [14, 'XUID', 'array', null], + [15, 'charset', 'offset', 0], + [16, 'Encoding', 'offset', 0], + [17, 'CharStrings', 'offset', 0], + [18, 'Private', ['offset', 'offset'], null], + [[12, 21], 'PostScript', 'sid', null], + [[12, 22], 'BaseFontName', 'sid', null], + [[12, 23], 'BaseFontBlend', 'delta', null], + [[12, 31], 'CIDFontVersion', 'num', 0], + [[12, 32], 'CIDFontRevision', 'num', 0], + [[12, 33], 'CIDFontType', 'num', 0], + [[12, 34], 'CIDCount', 'num', 8720], + [[12, 35], 'UIDBase', 'num', null], + // XXX: CID Fonts on DirectWrite 6.1 only seem to work if FDSelect comes + // before FDArray. + [[12, 37], 'FDSelect', 'offset', null], + [[12, 36], 'FDArray', 'offset', null], + [[12, 38], 'FontName', 'sid', null] + ]; + var tables = null; + function CFFTopDict(strings) { + if (tables === null) + tables = CFFDict.createTables(layout); + CFFDict.call(this, tables, strings); + this.privateDict = null; + } + CFFTopDict.prototype = Object.create(CFFDict.prototype); + return CFFTopDict; +})(); + +var CFFPrivateDict = (function CFFPrivateDictClosure() { + var layout = [ + [6, 'BlueValues', 'delta', null], + [7, 'OtherBlues', 'delta', null], + [8, 'FamilyBlues', 'delta', null], + [9, 'FamilyOtherBlues', 'delta', null], + [[12, 9], 'BlueScale', 'num', 0.039625], + [[12, 10], 'BlueShift', 'num', 7], + [[12, 11], 'BlueFuzz', 'num', 1], + [10, 'StdHW', 'num', null], + [11, 'StdVW', 'num', null], + [[12, 12], 'StemSnapH', 'delta', null], + [[12, 13], 'StemSnapV', 'delta', null], + [[12, 14], 'ForceBold', 'num', 0], + [[12, 17], 'LanguageGroup', 'num', 0], + [[12, 18], 'ExpansionFactor', 'num', 0.06], + [[12, 19], 'initialRandomSeed', 'num', 0], + [20, 'defaultWidthX', 'num', 0], + [21, 'nominalWidthX', 'num', 0], + [19, 'Subrs', 'offset', null] + ]; + var tables = null; + function CFFPrivateDict(strings) { + if (tables === null) + tables = CFFDict.createTables(layout); + CFFDict.call(this, tables, strings); + this.subrsIndex = null; + } + CFFPrivateDict.prototype = Object.create(CFFDict.prototype); + return CFFPrivateDict; +})(); + +var CFFCharsetPredefinedTypes = { + ISO_ADOBE: 0, + EXPERT: 1, + EXPERT_SUBSET: 2 +}; +var CFFCharsetEmbeddedTypes = { + FORMAT0: 0, + FORMAT1: 1, + FORMAT2: 2 +}; +var CFFCharset = (function CFFCharsetClosure() { + function CFFCharset(predefined, format, charset, raw) { + this.predefined = predefined; + this.format = format; + this.charset = charset; + this.raw = raw; + } + return CFFCharset; +})(); + +var CFFEncodingPredefinedTypes = { + STANDARD: 0, + EXPERT: 1 +}; +var CFFCharsetEmbeddedTypes = { + FORMAT0: 0, + FORMAT1: 1 +}; +var CFFEncoding = (function CFFEncodingClosure() { + function CFFEncoding(predefined, format, encoding, raw) { + this.predefined = predefined; + this.format = format; + this.encoding = encoding; + this.raw = raw; + } + return CFFEncoding; +})(); + +var CFFFDSelect = (function CFFFDSelectClosure() { + function CFFFDSelect(fdSelect, raw) { + this.fdSelect = fdSelect; + this.raw = raw; + } + return CFFFDSelect; +})(); + +// Helper class to keep track of where an offset is within the data and helps +// filling in that offset once it's known. +var CFFOffsetTracker = (function CFFOffsetTrackerClosure() { + function CFFOffsetTracker() { + this.offsets = {}; + } + CFFOffsetTracker.prototype = { + isTracking: function CFFOffsetTracker_isTracking(key) { + return key in this.offsets; + }, + track: function CFFOffsetTracker_track(key, location) { + if (key in this.offsets) + error('Already tracking location of ' + key); + this.offsets[key] = location; + }, + offset: function CFFOffsetTracker_offset(value) { + for (var key in this.offsets) { + this.offsets[key] += value; + } + }, + setEntryLocation: function CFFOffsetTracker_setEntryLocation(key, + values, + output) { + if (!(key in this.offsets)) + error('Not tracking location of ' + key); + var data = output.data; + var dataOffset = this.offsets[key]; + var size = 5; + for (var i = 0, ii = values.length; i < ii; ++i) { + var offset0 = i * size + dataOffset; + var offset1 = offset0 + 1; + var offset2 = offset0 + 2; + var offset3 = offset0 + 3; + var offset4 = offset0 + 4; + // It's easy to screw up offsets so perform this sanity check. + if (data[offset0] !== 0x1d || data[offset1] !== 0 || + data[offset2] !== 0 || data[offset3] !== 0 || data[offset4] !== 0) + error('writing to an offset that is not empty'); + var value = values[i]; + data[offset0] = 0x1d; + data[offset1] = (value >> 24) & 0xFF; + data[offset2] = (value >> 16) & 0xFF; + data[offset3] = (value >> 8) & 0xFF; + data[offset4] = value & 0xFF; + } + } + }; + return CFFOffsetTracker; +})(); + +// Takes a CFF and converts it to the binary representation. +var CFFCompiler = (function CFFCompilerClosure() { + function 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; + } + CFFCompiler.prototype = { + compile: function CFFCompiler_compile() { + var cff = this.cff; + var output = { + data: [], + length: 0, + add: function CFFCompiler_add(data) { + this.data = this.data.concat(data); + this.length = this.data.length; + } + }; + + // Compile the five entries that must be in order. + var header = this.compileHeader(cff.header); + output.add(header); + + var nameIndex = this.compileNameIndex(cff.names); + output.add(nameIndex); + + if (cff.isCIDFont) { + // The spec is unclear on how font matrices should relate to each other + // when there is one in the main top dict and the sub top dicts. + // Windows handles this differently than linux and osx so we have to + // normalize to work on all. + // Rules based off of some mailing list discussions: + // - If main font has a matrix and subfont doesn't, use the main matrix. + // - If no main font matrix and there is a subfont matrix, use the + // subfont matrix. + // - If both have matrices, concat together. + // - If neither have matrices, use default. + // To make this work on all platforms we move the top matrix into each + // sub top dict and concat if necessary. + if (cff.topDict.hasName('FontMatrix')) { + var base = cff.topDict.getByName('FontMatrix'); + cff.topDict.removeByName('FontMatrix'); + for (var i = 0, ii = cff.fdArray.length; i < ii; i++) { + var subDict = cff.fdArray[i]; + var matrix = base.slice(0); + if (subDict.hasName('FontMatrix')) { + matrix = Util.transform(matrix, subDict.getByName('FontMatrix')); + } + subDict.setByName('FontMatrix', matrix); + } + } + } + + var compiled = this.compileTopDicts([cff.topDict], + output.length, + cff.isCIDFont); + output.add(compiled.output); + var topDictTracker = compiled.trackers[0]; + + var stringIndex = this.compileStringIndex(cff.strings.strings); + output.add(stringIndex); + + var globalSubrIndex = this.compileIndex(cff.globalSubrIndex); + output.add(globalSubrIndex); + + // Now start on the other entries that have no specfic order. + if (cff.encoding && cff.topDict.hasName('Encoding')) { + if (cff.encoding.predefined) { + topDictTracker.setEntryLocation('Encoding', [cff.encoding.format], + output); + } else { + var encoding = this.compileEncoding(cff.encoding); + topDictTracker.setEntryLocation('Encoding', [output.length], output); + output.add(encoding); + } + } + + if (cff.charset && cff.topDict.hasName('charset')) { + if (cff.charset.predefined) { + topDictTracker.setEntryLocation('charset', [cff.charset.format], + output); + } else { + var charset = this.compileCharset(cff.charset); + topDictTracker.setEntryLocation('charset', [output.length], output); + output.add(charset); + } + } + + var charStrings = this.compileCharStrings(cff.charStrings); + topDictTracker.setEntryLocation('CharStrings', [output.length], output); + output.add(charStrings); + + if (cff.isCIDFont) { + // For some reason FDSelect must be in front of FDArray on windows. OSX + // and linux don't seem to care. + topDictTracker.setEntryLocation('FDSelect', [output.length], output); + var fdSelect = this.compileFDSelect(cff.fdSelect.raw); + output.add(fdSelect); + // It is unclear if the sub font dictionary can have CID related + // dictionary keys, but the sanitizer doesn't like them so remove them. + var compiled = this.compileTopDicts(cff.fdArray, output.length, true); + topDictTracker.setEntryLocation('FDArray', [output.length], output); + output.add(compiled.output); + var fontDictTrackers = compiled.trackers; + + this.compilePrivateDicts(cff.fdArray, fontDictTrackers, output); + } + + this.compilePrivateDicts([cff.topDict], [topDictTracker], output); + + // If the font data ends with INDEX whose object data is zero-length, + // the sanitizer will bail out. Add a dummy byte to avoid that. + output.add([0]); + + return output.data; + }, + encodeNumber: function CFFCompiler_encodeNumber(value) { + if (parseFloat(value) == parseInt(value, 10) && !isNaN(value)) // isInt + return this.encodeInteger(value); + else + return this.encodeFloat(value); + }, + encodeFloat: function CFFCompiler_encodeFloat(num) { + var value = num.toString(); + + // rounding inaccurate doubles + var m = /\.(\d*?)(?:9{5,20}|0{5,20})\d{0,2}(?:e(.+)|$)/.exec(value); + if (m) { + var epsilon = parseFloat('1e' + ((m[2] ? +m[2] : 0) + m[1].length)); + value = (Math.round(num * epsilon) / epsilon).toString(); + } + + var nibbles = ''; + for (var i = 0, ii = value.length; i < ii; ++i) { + var a = value[i]; + if (a === 'e') { + nibbles += value[++i] === '-' ? 'c' : 'b'; + } else if (a === '.') { + nibbles += 'a'; + } else if (a === '-') { + nibbles += 'e'; + } else { + nibbles += a; + } + } + nibbles += (nibbles.length & 1) ? 'f' : 'ff'; + var out = [30]; + for (var i = 0, ii = nibbles.length; i < ii; i += 2) { + out.push(parseInt(nibbles.substr(i, 2), 16)); + } + return out; + }, + encodeInteger: function CFFCompiler_encodeInteger(value) { + var code; + if (value >= -107 && value <= 107) { + code = [value + 139]; + } else if (value >= 108 && value <= 1131) { + value = [value - 108]; + code = [(value >> 8) + 247, value & 0xFF]; + } else if (value >= -1131 && value <= -108) { + value = -value - 108; + code = [(value >> 8) + 251, value & 0xFF]; + } else if (value >= -32768 && value <= 32767) { + code = [0x1c, (value >> 8) & 0xFF, value & 0xFF]; + } else { + code = [0x1d, + (value >> 24) & 0xFF, + (value >> 16) & 0xFF, + (value >> 8) & 0xFF, + value & 0xFF]; + } + return code; + }, + compileHeader: function CFFCompiler_compileHeader(header) { + return [ + header.major, + header.minor, + header.hdrSize, + header.offSize + ]; + }, + compileNameIndex: function CFFCompiler_compileNameIndex(names) { + var nameIndex = new CFFIndex(); + for (var i = 0, ii = names.length; i < ii; ++i) + nameIndex.add(stringToArray(names[i])); + return this.compileIndex(nameIndex); + }, + compileTopDicts: function CFFCompiler_compileTopDicts(dicts, + length, + removeCidKeys) { + var fontDictTrackers = []; + var fdArrayIndex = new CFFIndex(); + for (var i = 0, ii = dicts.length; i < ii; ++i) { + var fontDict = dicts[i]; + if (removeCidKeys) { + fontDict.removeByName('CIDFontVersion'); + fontDict.removeByName('CIDFontRevision'); + fontDict.removeByName('CIDFontType'); + fontDict.removeByName('CIDCount'); + fontDict.removeByName('UIDBase'); + } + var fontDictTracker = new CFFOffsetTracker(); + var fontDictData = this.compileDict(fontDict, fontDictTracker); + fontDictTrackers.push(fontDictTracker); + fdArrayIndex.add(fontDictData); + fontDictTracker.offset(length); + } + fdArrayIndex = this.compileIndex(fdArrayIndex, fontDictTrackers); + return { + trackers: fontDictTrackers, + output: fdArrayIndex + }; + }, + compilePrivateDicts: function CFFCompiler_compilePrivateDicts(dicts, + trackers, + output) { + for (var i = 0, ii = dicts.length; i < ii; ++i) { + var fontDict = dicts[i]; + assert(fontDict.privateDict && fontDict.hasName('Private'), + 'There must be an private dictionary.'); + var privateDict = fontDict.privateDict; + var privateDictTracker = new CFFOffsetTracker(); + var privateDictData = this.compileDict(privateDict, privateDictTracker); + + var outputLength = output.length; + privateDictTracker.offset(outputLength); + if (!privateDictData.length) { + // The private dictionary was empty, set the output length to zero to + // ensure the offset length isn't out of bounds in the eyes of the + // sanitizer. + outputLength = 0; + } + + trackers[i].setEntryLocation('Private', + [privateDictData.length, outputLength], + output); + output.add(privateDictData); + + if (privateDict.subrsIndex && privateDict.hasName('Subrs')) { + var subrs = this.compileIndex(privateDict.subrsIndex); + privateDictTracker.setEntryLocation('Subrs', [privateDictData.length], + output); + output.add(subrs); + } + } + }, + compileDict: function CFFCompiler_compileDict(dict, offsetTracker) { + var out = []; + // The dictionary keys must be in a certain order. + var order = dict.order; + for (var i = 0; i < order.length; ++i) { + var key = order[i]; + if (!(key in dict.values)) + continue; + var values = dict.values[key]; + var types = dict.types[key]; + if (!isArray(types)) types = [types]; + if (!isArray(values)) values = [values]; + + // Remove any empty dict values. + if (values.length === 0) + continue; + + for (var j = 0, jj = types.length; j < jj; ++j) { + var type = types[j]; + var value = values[j]; + switch (type) { + case 'num': + case 'sid': + out = out.concat(this.encodeNumber(value)); + break; + case 'offset': + // For offsets we just insert a 32bit integer so we don't have to + // deal with figuring out the length of the offset when it gets + // replaced later on by the compiler. + var name = dict.keyToNameMap[key]; + // Some offsets have the offset and the length, so just record the + // position of the first one. + if (!offsetTracker.isTracking(name)) + offsetTracker.track(name, out.length); + out = out.concat([0x1d, 0, 0, 0, 0]); + break; + case 'array': + case 'delta': + out = out.concat(this.encodeNumber(value)); + for (var k = 1, kk = values.length; k < kk; ++k) + out = out.concat(this.encodeNumber(values[k])); + break; + default: + error('Unknown data type of ' + type); + break; + } + } + out = out.concat(dict.opcodes[key]); + } + return out; + }, + compileStringIndex: function CFFCompiler_compileStringIndex(strings) { + var stringIndex = new CFFIndex(); + for (var i = 0, ii = strings.length; i < ii; ++i) + stringIndex.add(stringToArray(strings[i])); + return this.compileIndex(stringIndex); + }, + compileGlobalSubrIndex: function CFFCompiler_compileGlobalSubrIndex() { + var globalSubrIndex = this.cff.globalSubrIndex; + this.out.writeByteArray(this.compileIndex(globalSubrIndex)); + }, + compileCharStrings: function CFFCompiler_compileCharStrings(charStrings) { + return this.compileIndex(charStrings); + }, + compileCharset: function CFFCompiler_compileCharset(charset) { + return this.compileTypedArray(charset.raw); + }, + compileEncoding: function CFFCompiler_compileEncoding(encoding) { + return this.compileTypedArray(encoding.raw); + }, + compileFDSelect: function CFFCompiler_compileFDSelect(fdSelect) { + return this.compileTypedArray(fdSelect); + }, + compileTypedArray: function CFFCompiler_compileTypedArray(data) { + var out = []; + for (var i = 0, ii = data.length; i < ii; ++i) + out[i] = data[i]; + return out; + }, + compileIndex: function CFFCompiler_compileIndex(index, trackers) { + trackers = trackers || []; + var objects = index.objects; + // First 2 bytes contains the number of objects contained into this index + var count = objects.length; + + // If there is no object, just create an index. This technically + // should just be [0, 0] but OTS has an issue with that. + if (count === 0) + return [0, 0, 0]; + + var data = [(count >> 8) & 0xFF, count & 0xff]; + + var lastOffset = 1; + for (var i = 0; i < count; ++i) + lastOffset += objects[i].length; + + var offsetSize; + if (lastOffset < 0x100) + offsetSize = 1; + else if (lastOffset < 0x10000) + offsetSize = 2; + else if (lastOffset < 0x1000000) + offsetSize = 3; + else + offsetSize = 4; + + // Next byte contains the offset size use to reference object in the file + data.push(offsetSize); + + // Add another offset after this one because we need a new offset + var relativeOffset = 1; + for (var i = 0; i < count + 1; i++) { + if (offsetSize === 1) { + data.push(relativeOffset & 0xFF); + } else if (offsetSize === 2) { + data.push((relativeOffset >> 8) & 0xFF, + relativeOffset & 0xFF); + } else if (offsetSize === 3) { + data.push((relativeOffset >> 16) & 0xFF, + (relativeOffset >> 8) & 0xFF, + relativeOffset & 0xFF); + } else { + data.push((relativeOffset >>> 24) & 0xFF, + (relativeOffset >> 16) & 0xFF, + (relativeOffset >> 8) & 0xFF, + relativeOffset & 0xFF); + } + + if (objects[i]) + relativeOffset += objects[i].length; + } + var offset = data.length; + + for (var i = 0; i < count; i++) { + // Notify the tracker where the object will be offset in the data. + if (trackers[i]) + trackers[i].offset(data.length); + for (var j = 0, jj = objects[i].length; j < jj; j++) + data.push(objects[i][j]); + } + return data; + } + }; + return CFFCompiler; +})(); + +// Workaround for seac on Windows. +(function checkSeacSupport() { + if (/Windows/.test(navigator.userAgent)) { + SEAC_ANALYSIS_ENABLED = true; + } +})(); + +// Workaround for Private Use Area characters in Chrome on Windows +// http://code.google.com/p/chromium/issues/detail?id=122465 +// https://github.com/mozilla/pdf.js/issues/1689 +(function checkChromeWindows() { + if (/Windows.*Chrome/.test(navigator.userAgent)) { + SYMBOLIC_FONT_GLYPH_OFFSET = 0xF100; + } +})(); + + +var FontRendererFactory = (function FontRendererFactoryClosure() { + function getLong(data, offset) { + return (data[offset] << 24) | (data[offset + 1] << 16) | + (data[offset + 2] << 8) | data[offset + 3]; + } + + function getUshort(data, offset) { + return (data[offset] << 8) | data[offset + 1]; + } + + function parseCmap(data, start, end) { + var offset = getUshort(data, start + 2) === 1 ? getLong(data, start + 8) : + getLong(data, start + 16); + var format = getUshort(data, start + offset); + if (format === 4) { + var 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) { + ranges[i] = {end: getUshort(data, p)}; + } + p += 2; + for (var i = 0; i < segCount; i++, p += 2) { + ranges[i].start = getUshort(data, p); + } + for (var i = 0; i < segCount; i++, p += 2) { + ranges[i].idDelta = getUshort(data, p); + } + for (var i = 0; i < segCount; i++, p += 2) { + var idOffset = getUshort(data, p); + if (idOffset === 0) { + continue; + } + ranges[i].ids = []; + for (var j = 0, jj = ranges[i].end - ranges[i].start + 1; j < jj; j++) { + ranges[i].ids[j] = getUshort(data, p + idOffset); + idOffset += 2; + } + } + return ranges; + } else if (format === 12) { + var 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++) { + ranges.push({ + start: getLong(data, p), + end: getLong(data, p + 4), + idDelta: getLong(data, p + 8) - getLong(data, p) + }); + p += 12; + } + return ranges; + } + error('not supported cmap: ' + format); + } + + function parseCff(data, start, end) { + var properties = {}; + var parser = new CFFParser( + new Stream(data, start, end - start), properties); + var cff = parser.parse(); + return { + glyphs: cff.charStrings.objects, + subrs: cff.topDict.privateDict && cff.topDict.privateDict.subrsIndex && + cff.topDict.privateDict.subrsIndex.objects, + gsubrs: cff.globalSubrIndex && cff.globalSubrIndex.objects + }; + } + + function parseGlyfTable(glyf, loca, isGlyphLocationsLong) { + var itemSize, itemDecode; + if (isGlyphLocationsLong) { + itemSize = 4; + itemDecode = function fontItemDecodeLong(data, offset) { + return (data[offset] << 24) | (data[offset + 1] << 16) | + (data[offset + 2] << 8) | data[offset + 3]; + }; + } else { + itemSize = 2; + itemDecode = function fontItemDecode(data, offset) { + return (data[offset] << 9) | (data[offset + 1] << 1); + }; + } + var glyphs = []; + var startOffset = itemDecode(loca, 0); + for (var j = itemSize; j < loca.length; j += itemSize) { + var endOffset = itemDecode(loca, j); + glyphs.push(glyf.subarray(startOffset, endOffset)); + startOffset = endOffset; + } + return glyphs; + } + + function lookupCmap(ranges, unicode) { + var code = unicode.charCodeAt(0); + var l = 0, r = ranges.length - 1; + while (l < r) { + var c = (l + r + 1) >> 1; + if (code < ranges[c].start) { + r = c - 1; + } else { + l = c; + } + } + if (ranges[l].start <= code && code <= ranges[l].end) { + return (ranges[l].idDelta + (ranges[l].ids ? + ranges[l].ids[code - ranges[l].start] : code)) & 0xFFFF; + } + return 0; + } + + function compileGlyf(code, js, font) { + function moveTo(x, y) { + js.push('c.moveTo(' + x + ',' + y + ');'); + } + function lineTo(x, y) { + js.push('c.lineTo(' + x + ',' + y + ');'); + } + function quadraticCurveTo(xa, ya, x, y) { + js.push('c.quadraticCurveTo(' + xa + ',' + ya + ',' + + x + ',' + y + ');'); + } + + var i = 0; + var numberOfContours = ((code[i] << 24) | (code[i + 1] << 16)) >> 16; + var 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; + i += 10; + if (numberOfContours < 0) { + // composite glyph + var x = 0, y = 0; + do { + var flags = (code[i] << 8) | code[i + 1]; + var glyphIndex = (code[i + 2] << 8) | code[i + 3]; + i += 4; + var arg1, arg2; + if ((flags & 0x01)) { + arg1 = ((code[i] << 24) | (code[i + 1] << 16)) >> 16; + arg2 = ((code[i + 2] << 24) | (code[i + 3] << 16)) >> 16; + i += 4; + } else { + arg1 = code[i++]; arg2 = code[i++]; + } + if ((flags & 0x02)) { + x = arg1; + y = arg2; + } else { + x = 0; y = 0; // TODO "they are points" ? + } + var scaleX = 1, scaleY = 1, scale01 = 0, scale10 = 0; + if ((flags & 0x08)) { + scaleX = + scaleY = ((code[i] << 24) | (code[i + 1] << 16)) / 1073741824; + i += 2; + } else if ((flags & 0x40)) { + scaleX = ((code[i] << 24) | (code[i + 1] << 16)) / 1073741824; + scaleY = ((code[i + 2] << 24) | (code[i + 3] << 16)) / 1073741824; + i += 4; + } else if ((flags & 0x80)) { + scaleX = ((code[i] << 24) | (code[i + 1] << 16)) / 1073741824; + scale01 = ((code[i + 2] << 24) | (code[i + 3] << 16)) / 1073741824; + scale10 = ((code[i + 4] << 24) | (code[i + 5] << 16)) / 1073741824; + scaleY = ((code[i + 6] << 24) | (code[i + 7] << 16)) / 1073741824; + i += 8; + } + var subglyph = font.glyphs[glyphIndex]; + if (subglyph) { + js.push('c.save();'); + js.push('c.transform(' + scaleX + ',' + scale01 + ',' + + scale10 + ',' + scaleY + ',' + x + ',' + y + ');'); + compileGlyf(subglyph, js, font); + js.push('c.restore();'); + } + } while ((flags & 0x20)); + } else { + // simple glyph + var endPtsOfContours = []; + for (var j = 0; j < numberOfContours; j++) { + endPtsOfContours.push((code[i] << 8) | code[i + 1]); + i += 2; + } + var instructionLength = (code[i] << 8) | code[i + 1]; + i += 2 + instructionLength; // skipping the instructions + var numberOfPoints = endPtsOfContours[endPtsOfContours.length - 1] + 1; + var points = []; + while (points.length < numberOfPoints) { + var flags = code[i++], repeat = 1; + if ((flags & 0x08)) { + repeat += code[i++]; + } + while (repeat-- > 0) { + points.push({flags: flags}); + } + } + var x = 0, y = 0; + for (var j = 0; j < numberOfPoints; j++) { + switch (points[j].flags & 0x12) { + case 0x00: + x += ((code[i] << 24) | (code[i + 1] << 16)) >> 16; + i += 2; + break; + case 0x02: + x -= code[i++]; + break; + case 0x12: + x += code[i++]; + break; + } + points[j].x = x; + } + for (var j = 0; j < numberOfPoints; j++) { + switch (points[j].flags & 0x24) { + case 0x00: + y += ((code[i] << 24) | (code[i + 1] << 16)) >> 16; + i += 2; + break; + case 0x04: + y -= code[i++]; + break; + case 0x24: + y += code[i++]; + break; + } + points[j].y = y; + } + + var startPoint = 0; + for (var i = 0; i < numberOfContours; i++) { + var endPoint = endPtsOfContours[i]; + // contours might have implicit points, which is located in the middle + // between two neighboring off-curve points + var contour = points.slice(startPoint, endPoint + 1); + if ((contour[0].flags & 1)) { + contour.push(contour[0]); // using start point at the contour end + } else if ((contour[contour.length - 1].flags & 1)) { + // first is off-curve point, trying to use one from the end + contour.unshift(contour[contour.length - 1]); + } else { + // start and end are off-curve points, creating implicit one + var p = { + flags: 1, + x: (contour[0].x + contour[contour.length - 1].x) / 2, + y: (contour[0].y + contour[contour.length - 1].y) / 2 + }; + contour.unshift(p); + contour.push(p); + } + moveTo(contour[0].x, contour[0].y); + for (var j = 1, jj = contour.length; j < jj; j++) { + if ((contour[j].flags & 1)) { + lineTo(contour[j].x, contour[j].y); + } else if ((contour[j + 1].flags & 1)){ + quadraticCurveTo(contour[j].x, contour[j].y, + contour[j + 1].x, contour[j + 1].y); + j++; + } else { + quadraticCurveTo(contour[j].x, contour[j].y, + (contour[j].x + contour[j + 1].x) / 2, + (contour[j].y + contour[j + 1].y) / 2); + } + } + startPoint = endPoint + 1; + } + } + } + + function compileCharString(code, js, font) { + var stack = []; + var x = 0, y = 0; + var stems = 0; + + function moveTo(x, y) { + js.push('c.moveTo(' + x + ',' + y + ');'); + } + function lineTo(x, y) { + js.push('c.lineTo(' + x + ',' + y + ');'); + } + function bezierCurveTo(x1, y1, x2, y2, x, y) { + js.push('c.bezierCurveTo(' + x1 + ',' + y1 + ',' + x2 + ',' + y2 + ',' + + x + ',' + y + ');'); + } + + function parse(code) { + var i = 0; + while (i < code.length) { + var stackClean = false; + var v = code[i++]; + switch (v) { + case 1: // hstem + stems += stack.length >> 1; + stackClean = true; + break; + case 3: // vstem + stems += stack.length >> 1; + stackClean = true; + break; + case 4: // vmoveto + y += stack.pop(); + moveTo(x, y); + stackClean = true; + break; + case 5: // rlineto + while (stack.length > 0) { + x += stack.shift(); + y += stack.shift(); + lineTo(x, y); + } + break; + case 6: // hlineto + while (stack.length > 0) { + x += stack.shift(); + lineTo(x, y); + if (stack.length === 0) { + break; + } + y += stack.shift(); + lineTo(x, y); + } + break; + case 7: // vlineto + while (stack.length > 0) { + y += stack.shift(); + lineTo(x, y); + if (stack.length === 0) { + break; + } + x += stack.shift(); + lineTo(x, y); + } + break; + case 8: // rrcurveto + while (stack.length > 0) { + var xa = x + stack.shift(), ya = y + stack.shift(); + var 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]; + if (subrCode) { + parse(subrCode); + } + break; + case 11: // return + return; + case 12: + v = code[i++]; + switch (v) { + case 34: // flex + var xa = x + stack.shift(); + var 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(); + 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(); + 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(); + 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(); + 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(); + 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(); + 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(); + x = xb; y = yb; + if (Math.abs(x - x0) > Math.abs(y - y0)) + x += stack.shift(); + else + y += stack.shift(); + bezierCurveTo(xa, ya, xb, yb, x, y); + break; + default: + error('unknown operator: 12 ' + v); + } + break; + case 14: // endchar + if (stack.length >= 4) { + var achar = stack.pop(); + var bchar = stack.pop(); + y = stack.pop(); + x = stack.pop(); + js.push('c.save();'); + js.push('c.translate('+ x + ',' + y + ');'); + var gid = lookupCmap(font.cmap, String.fromCharCode( + font.glyphNameMap[Encodings.StandardEncoding[achar]])); + compileCharString(font.glyphs[gid], js, font); + js.push('c.restore();'); + + gid = lookupCmap(font.cmap, String.fromCharCode( + font.glyphNameMap[Encodings.StandardEncoding[bchar]])); + compileCharString(font.glyphs[gid], js, font); + } + return; + case 18: // hstemhm + stems += stack.length >> 1; + stackClean = true; + break; + case 19: // hintmask + stems += stack.length >> 1; + i += (stems + 7) >> 3; + stackClean = true; + break; + case 20: // cntrmask + stems += stack.length >> 1; + i += (stems + 7) >> 3; + stackClean = true; + break; + case 21: // rmoveto + y += stack.pop(); + x += stack.pop(); + moveTo(x, y); + stackClean = true; + break; + case 22: // hmoveto + x += stack.pop(); + moveTo(x, y); + stackClean = true; + break; + case 23: // vstemhm + stems += stack.length >> 1; + stackClean = true; + break; + case 24: // rcurveline + while (stack.length > 2) { + var xa = x + stack.shift(), ya = y + stack.shift(); + var xb = xa + stack.shift(), yb = ya + stack.shift(); + x = xb + stack.shift(); y = yb + stack.shift(); + bezierCurveTo(xa, ya, xb, yb, x, y); + } + x += stack.shift(); + y += stack.shift(); + lineTo(x, y); + break; + case 25: // rlinecurve + while (stack.length > 6) { + x += stack.shift(); + y += stack.shift(); + lineTo(x, y); + } + var xa = x + stack.shift(), ya = y + stack.shift(); + var xb = xa + stack.shift(), yb = ya + stack.shift(); + x = xb + stack.shift(); y = yb + stack.shift(); + bezierCurveTo(xa, ya, xb, yb, x, y); + break; + case 26: // vvcurveto + if (stack.length % 2) { + x += stack.shift(); + } + while (stack.length > 0) { + var xa = x, ya = y + stack.shift(); + var xb = xa + stack.shift(), yb = ya + stack.shift(); + x = xb; y = yb + stack.shift(); + bezierCurveTo(xa, ya, xb, yb, x, y); + } + break; + case 27: // hhcurveto + if (stack.length % 2) { + y += stack.shift(); + } + while (stack.length > 0) { + var xa = x + stack.shift(), ya = y; + var xb = xa + stack.shift(), yb = ya + stack.shift(); + x = xb + stack.shift(); y = yb; + bezierCurveTo(xa, ya, xb, yb, x, y); + } + break; + case 28: + stack.push(((code[i] << 24) | (code[i + 1] << 16)) >> 16); + i += 2; + break; + case 29: // callgsubr + var n = stack.pop() + font.gsubrsBias; + var 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(); + x = xb + stack.shift(); + y = yb + (stack.length === 1 ? stack.shift() : 0); + bezierCurveTo(xa, ya, xb, yb, x, y); + if (stack.length === 0) { + break; + } + + var xa = x + stack.shift(), ya = y; + var xb = xa + stack.shift(), yb = ya + stack.shift(); + y = yb + stack.shift(); + x = xb + (stack.length === 1 ? stack.shift() : 0); + bezierCurveTo(xa, ya, xb, yb, x, y); + } + break; + case 31: // hvcurveto + while (stack.length > 0) { + var xa = x + stack.shift(), ya = y; + var xb = xa + stack.shift(), yb = ya + stack.shift(); + y = yb + stack.shift(); + x = xb + (stack.length === 1 ? stack.shift() : 0); + bezierCurveTo(xa, ya, xb, yb, x, y); + if (stack.length === 0) { + break; + } + + var xa = x, ya = y + stack.shift(); + var xb = xa + stack.shift(), yb = ya + stack.shift(); + x = xb + stack.shift(); + y = yb + (stack.length === 1 ? stack.shift() : 0); + bezierCurveTo(xa, ya, xb, yb, x, y); + } + break; + default: + if (v < 32) + error('unknown operator: ' + v); + if (v < 247) + stack.push(v - 139); + else if (v < 251) + stack.push((v - 247) * 256 + code[i++] + 108); + else if (v < 255) + stack.push(-(v - 251) * 256 - code[i++] - 108); + else { + stack.push(((code[i] << 24) | (code[i + 1] << 16) | + (code[i + 2] << 8) | code[i + 3]) / 65536); + i += 4; + } + break; + } + if (stackClean) { + stack.length = 0; + } + } + } + parse(code); + } + + var noop = ''; + + function CompiledFont(fontMatrix) { + this.compiledGlyphs = {}; + this.fontMatrix = fontMatrix; + } + CompiledFont.prototype = { + getPathJs: function (unicode) { + var gid = lookupCmap(this.cmap, unicode); + var fn = this.compiledGlyphs[gid]; + if (!fn) { + this.compiledGlyphs[gid] = fn = this.compileGlyph(this.glyphs[gid]); + } + return fn; + }, + + compileGlyph: function (code) { + if (!code || code.length === 0 || code[0] === 14) { + return noop; + } + + var js = []; + js.push('c.save();'); + js.push('c.transform(' + this.fontMatrix.join(',') + ');'); + js.push('c.scale(size, -size);'); + + this.compileGlyphImpl(code, js); + + js.push('c.restore();'); + + return js.join('\n'); + }, + + compileGlyphImpl: function () { + error('Children classes should implement this.'); + }, + + hasBuiltPath: function (unicode) { + var gid = lookupCmap(this.cmap, unicode); + return gid in this.compiledGlyphs; + } + }; + + function TrueTypeCompiled(glyphs, cmap, fontMatrix) { + fontMatrix = fontMatrix || [0.000488, 0, 0, 0.000488, 0, 0]; + CompiledFont.call(this, fontMatrix); + + this.glyphs = glyphs; + this.cmap = cmap; + + this.compiledGlyphs = []; + } + + Util.inherit(TrueTypeCompiled, CompiledFont, { + compileGlyphImpl: function (code, js) { + compileGlyf(code, js, this); + } + }); + + function Type2Compiled(cffInfo, cmap, fontMatrix, glyphNameMap) { + fontMatrix = fontMatrix || [0.001, 0, 0, 0.001, 0, 0]; + CompiledFont.call(this, fontMatrix); + this.glyphs = cffInfo.glyphs; + this.gsubrs = cffInfo.gsubrs || []; + this.subrs = cffInfo.subrs || []; + this.cmap = cmap; + this.glyphNameMap = glyphNameMap || GlyphsUnicode; + + this.compiledGlyphs = []; + this.gsubrsBias = this.gsubrs.length < 1240 ? 107 : + this.gsubrs.length < 33900 ? 1131 : 32768; + this.subrsBias = this.subrs.length < 1240 ? 107 : + this.subrs.length < 33900 ? 1131 : 32768; + } + + Util.inherit(Type2Compiled, CompiledFont, { + compileGlyphImpl: function (code, js) { + compileCharString(code, js, this); + } + }); + + + return { + create: function FontRendererFactory_create(font) { + var data = new Uint8Array(font.data); + var cmap, glyf, loca, cff, indexToLocFormat, unitsPerEm; + var numTables = getUshort(data, 4); + for (var i = 0, p = 12; i < numTables; i++, p += 16) { + var tag = String.fromCharCode.apply(null, data.subarray(p, p + 4)); + var offset = getLong(data, p + 8); + var length = getLong(data, p + 12); + switch (tag) { + case 'cmap': + cmap = parseCmap(data, offset, offset + length); + break; + case 'glyf': + glyf = data.subarray(offset, offset + length); + break; + case 'loca': + loca = data.subarray(offset, offset + length); + break; + case 'head': + unitsPerEm = getUshort(data, offset + 18); + indexToLocFormat = getUshort(data, offset + 50); + break; + case 'CFF ': + cff = parseCff(data, offset, offset + length); + break; + } + } + + if (glyf) { + var fontMatrix = !unitsPerEm ? font.fontMatrix : + [1 / unitsPerEm, 0, 0, 1 / unitsPerEm, 0, 0]; + return new TrueTypeCompiled( + parseGlyfTable(glyf, loca, indexToLocFormat), cmap, fontMatrix); + } else { + return new Type2Compiled(cff, cmap, font.fontMatrix, font.glyphNameMap); + } + } + }; +})(); + + + +var GlyphsUnicode = { + A: 0x0041, + AE: 0x00C6, + AEacute: 0x01FC, + AEmacron: 0x01E2, + AEsmall: 0xF7E6, + Aacute: 0x00C1, + Aacutesmall: 0xF7E1, + Abreve: 0x0102, + Abreveacute: 0x1EAE, + Abrevecyrillic: 0x04D0, + Abrevedotbelow: 0x1EB6, + Abrevegrave: 0x1EB0, + Abrevehookabove: 0x1EB2, + Abrevetilde: 0x1EB4, + Acaron: 0x01CD, + Acircle: 0x24B6, + Acircumflex: 0x00C2, + Acircumflexacute: 0x1EA4, + Acircumflexdotbelow: 0x1EAC, + Acircumflexgrave: 0x1EA6, + Acircumflexhookabove: 0x1EA8, + Acircumflexsmall: 0xF7E2, + Acircumflextilde: 0x1EAA, + Acute: 0xF6C9, + Acutesmall: 0xF7B4, + Acyrillic: 0x0410, + Adblgrave: 0x0200, + Adieresis: 0x00C4, + Adieresiscyrillic: 0x04D2, + Adieresismacron: 0x01DE, + Adieresissmall: 0xF7E4, + Adotbelow: 0x1EA0, + Adotmacron: 0x01E0, + Agrave: 0x00C0, + Agravesmall: 0xF7E0, + Ahookabove: 0x1EA2, + Aiecyrillic: 0x04D4, + Ainvertedbreve: 0x0202, + Alpha: 0x0391, + Alphatonos: 0x0386, + Amacron: 0x0100, + Amonospace: 0xFF21, + Aogonek: 0x0104, + Aring: 0x00C5, + Aringacute: 0x01FA, + Aringbelow: 0x1E00, + Aringsmall: 0xF7E5, + Asmall: 0xF761, + Atilde: 0x00C3, + Atildesmall: 0xF7E3, + Aybarmenian: 0x0531, + B: 0x0042, + Bcircle: 0x24B7, + Bdotaccent: 0x1E02, + Bdotbelow: 0x1E04, + Becyrillic: 0x0411, + Benarmenian: 0x0532, + Beta: 0x0392, + Bhook: 0x0181, + Blinebelow: 0x1E06, + Bmonospace: 0xFF22, + Brevesmall: 0xF6F4, + Bsmall: 0xF762, + Btopbar: 0x0182, + C: 0x0043, + Caarmenian: 0x053E, + Cacute: 0x0106, + Caron: 0xF6CA, + Caronsmall: 0xF6F5, + Ccaron: 0x010C, + Ccedilla: 0x00C7, + Ccedillaacute: 0x1E08, + Ccedillasmall: 0xF7E7, + Ccircle: 0x24B8, + Ccircumflex: 0x0108, + Cdot: 0x010A, + Cdotaccent: 0x010A, + Cedillasmall: 0xF7B8, + Chaarmenian: 0x0549, + Cheabkhasiancyrillic: 0x04BC, + Checyrillic: 0x0427, + Chedescenderabkhasiancyrillic: 0x04BE, + Chedescendercyrillic: 0x04B6, + Chedieresiscyrillic: 0x04F4, + Cheharmenian: 0x0543, + Chekhakassiancyrillic: 0x04CB, + Cheverticalstrokecyrillic: 0x04B8, + Chi: 0x03A7, + Chook: 0x0187, + Circumflexsmall: 0xF6F6, + Cmonospace: 0xFF23, + Coarmenian: 0x0551, + Csmall: 0xF763, + D: 0x0044, + DZ: 0x01F1, + DZcaron: 0x01C4, + Daarmenian: 0x0534, + Dafrican: 0x0189, + Dcaron: 0x010E, + Dcedilla: 0x1E10, + Dcircle: 0x24B9, + Dcircumflexbelow: 0x1E12, + Dcroat: 0x0110, + Ddotaccent: 0x1E0A, + Ddotbelow: 0x1E0C, + Decyrillic: 0x0414, + Deicoptic: 0x03EE, + Delta: 0x2206, + Deltagreek: 0x0394, + Dhook: 0x018A, + Dieresis: 0xF6CB, + DieresisAcute: 0xF6CC, + DieresisGrave: 0xF6CD, + Dieresissmall: 0xF7A8, + Digammagreek: 0x03DC, + Djecyrillic: 0x0402, + Dlinebelow: 0x1E0E, + Dmonospace: 0xFF24, + Dotaccentsmall: 0xF6F7, + Dslash: 0x0110, + Dsmall: 0xF764, + Dtopbar: 0x018B, + Dz: 0x01F2, + Dzcaron: 0x01C5, + Dzeabkhasiancyrillic: 0x04E0, + Dzecyrillic: 0x0405, + Dzhecyrillic: 0x040F, + E: 0x0045, + Eacute: 0x00C9, + Eacutesmall: 0xF7E9, + Ebreve: 0x0114, + Ecaron: 0x011A, + Ecedillabreve: 0x1E1C, + Echarmenian: 0x0535, + Ecircle: 0x24BA, + Ecircumflex: 0x00CA, + Ecircumflexacute: 0x1EBE, + Ecircumflexbelow: 0x1E18, + Ecircumflexdotbelow: 0x1EC6, + Ecircumflexgrave: 0x1EC0, + Ecircumflexhookabove: 0x1EC2, + Ecircumflexsmall: 0xF7EA, + Ecircumflextilde: 0x1EC4, + Ecyrillic: 0x0404, + Edblgrave: 0x0204, + Edieresis: 0x00CB, + Edieresissmall: 0xF7EB, + Edot: 0x0116, + Edotaccent: 0x0116, + Edotbelow: 0x1EB8, + Efcyrillic: 0x0424, + Egrave: 0x00C8, + Egravesmall: 0xF7E8, + Eharmenian: 0x0537, + Ehookabove: 0x1EBA, + Eightroman: 0x2167, + Einvertedbreve: 0x0206, + Eiotifiedcyrillic: 0x0464, + Elcyrillic: 0x041B, + Elevenroman: 0x216A, + Emacron: 0x0112, + Emacronacute: 0x1E16, + Emacrongrave: 0x1E14, + Emcyrillic: 0x041C, + Emonospace: 0xFF25, + Encyrillic: 0x041D, + Endescendercyrillic: 0x04A2, + Eng: 0x014A, + Enghecyrillic: 0x04A4, + Enhookcyrillic: 0x04C7, + Eogonek: 0x0118, + Eopen: 0x0190, + Epsilon: 0x0395, + Epsilontonos: 0x0388, + Ercyrillic: 0x0420, + Ereversed: 0x018E, + Ereversedcyrillic: 0x042D, + Escyrillic: 0x0421, + Esdescendercyrillic: 0x04AA, + Esh: 0x01A9, + Esmall: 0xF765, + Eta: 0x0397, + Etarmenian: 0x0538, + Etatonos: 0x0389, + Eth: 0x00D0, + Ethsmall: 0xF7F0, + Etilde: 0x1EBC, + Etildebelow: 0x1E1A, + Euro: 0x20AC, + Ezh: 0x01B7, + Ezhcaron: 0x01EE, + Ezhreversed: 0x01B8, + F: 0x0046, + Fcircle: 0x24BB, + Fdotaccent: 0x1E1E, + Feharmenian: 0x0556, + Feicoptic: 0x03E4, + Fhook: 0x0191, + Fitacyrillic: 0x0472, + Fiveroman: 0x2164, + Fmonospace: 0xFF26, + Fourroman: 0x2163, + Fsmall: 0xF766, + G: 0x0047, + GBsquare: 0x3387, + Gacute: 0x01F4, + Gamma: 0x0393, + Gammaafrican: 0x0194, + Gangiacoptic: 0x03EA, + Gbreve: 0x011E, + Gcaron: 0x01E6, + Gcedilla: 0x0122, + Gcircle: 0x24BC, + Gcircumflex: 0x011C, + Gcommaaccent: 0x0122, + Gdot: 0x0120, + Gdotaccent: 0x0120, + Gecyrillic: 0x0413, + Ghadarmenian: 0x0542, + Ghemiddlehookcyrillic: 0x0494, + Ghestrokecyrillic: 0x0492, + Gheupturncyrillic: 0x0490, + Ghook: 0x0193, + Gimarmenian: 0x0533, + Gjecyrillic: 0x0403, + Gmacron: 0x1E20, + Gmonospace: 0xFF27, + Grave: 0xF6CE, + Gravesmall: 0xF760, + Gsmall: 0xF767, + Gsmallhook: 0x029B, + Gstroke: 0x01E4, + H: 0x0048, + H18533: 0x25CF, + H18543: 0x25AA, + H18551: 0x25AB, + H22073: 0x25A1, + HPsquare: 0x33CB, + Haabkhasiancyrillic: 0x04A8, + Hadescendercyrillic: 0x04B2, + Hardsigncyrillic: 0x042A, + Hbar: 0x0126, + Hbrevebelow: 0x1E2A, + Hcedilla: 0x1E28, + Hcircle: 0x24BD, + Hcircumflex: 0x0124, + Hdieresis: 0x1E26, + Hdotaccent: 0x1E22, + Hdotbelow: 0x1E24, + Hmonospace: 0xFF28, + Hoarmenian: 0x0540, + Horicoptic: 0x03E8, + Hsmall: 0xF768, + Hungarumlaut: 0xF6CF, + Hungarumlautsmall: 0xF6F8, + Hzsquare: 0x3390, + I: 0x0049, + IAcyrillic: 0x042F, + IJ: 0x0132, + IUcyrillic: 0x042E, + Iacute: 0x00CD, + Iacutesmall: 0xF7ED, + Ibreve: 0x012C, + Icaron: 0x01CF, + Icircle: 0x24BE, + Icircumflex: 0x00CE, + Icircumflexsmall: 0xF7EE, + Icyrillic: 0x0406, + Idblgrave: 0x0208, + Idieresis: 0x00CF, + Idieresisacute: 0x1E2E, + Idieresiscyrillic: 0x04E4, + Idieresissmall: 0xF7EF, + Idot: 0x0130, + Idotaccent: 0x0130, + Idotbelow: 0x1ECA, + Iebrevecyrillic: 0x04D6, + Iecyrillic: 0x0415, + Ifraktur: 0x2111, + Igrave: 0x00CC, + Igravesmall: 0xF7EC, + Ihookabove: 0x1EC8, + Iicyrillic: 0x0418, + Iinvertedbreve: 0x020A, + Iishortcyrillic: 0x0419, + Imacron: 0x012A, + Imacroncyrillic: 0x04E2, + Imonospace: 0xFF29, + Iniarmenian: 0x053B, + Iocyrillic: 0x0401, + Iogonek: 0x012E, + Iota: 0x0399, + Iotaafrican: 0x0196, + Iotadieresis: 0x03AA, + Iotatonos: 0x038A, + Ismall: 0xF769, + Istroke: 0x0197, + Itilde: 0x0128, + Itildebelow: 0x1E2C, + Izhitsacyrillic: 0x0474, + Izhitsadblgravecyrillic: 0x0476, + J: 0x004A, + Jaarmenian: 0x0541, + Jcircle: 0x24BF, + Jcircumflex: 0x0134, + Jecyrillic: 0x0408, + Jheharmenian: 0x054B, + Jmonospace: 0xFF2A, + Jsmall: 0xF76A, + K: 0x004B, + KBsquare: 0x3385, + KKsquare: 0x33CD, + Kabashkircyrillic: 0x04A0, + Kacute: 0x1E30, + Kacyrillic: 0x041A, + Kadescendercyrillic: 0x049A, + Kahookcyrillic: 0x04C3, + Kappa: 0x039A, + Kastrokecyrillic: 0x049E, + Kaverticalstrokecyrillic: 0x049C, + Kcaron: 0x01E8, + Kcedilla: 0x0136, + Kcircle: 0x24C0, + Kcommaaccent: 0x0136, + Kdotbelow: 0x1E32, + Keharmenian: 0x0554, + Kenarmenian: 0x053F, + Khacyrillic: 0x0425, + Kheicoptic: 0x03E6, + Khook: 0x0198, + Kjecyrillic: 0x040C, + Klinebelow: 0x1E34, + Kmonospace: 0xFF2B, + Koppacyrillic: 0x0480, + Koppagreek: 0x03DE, + Ksicyrillic: 0x046E, + Ksmall: 0xF76B, + L: 0x004C, + LJ: 0x01C7, + LL: 0xF6BF, + Lacute: 0x0139, + Lambda: 0x039B, + Lcaron: 0x013D, + Lcedilla: 0x013B, + Lcircle: 0x24C1, + Lcircumflexbelow: 0x1E3C, + Lcommaaccent: 0x013B, + Ldot: 0x013F, + Ldotaccent: 0x013F, + Ldotbelow: 0x1E36, + Ldotbelowmacron: 0x1E38, + Liwnarmenian: 0x053C, + Lj: 0x01C8, + Ljecyrillic: 0x0409, + Llinebelow: 0x1E3A, + Lmonospace: 0xFF2C, + Lslash: 0x0141, + Lslashsmall: 0xF6F9, + Lsmall: 0xF76C, + M: 0x004D, + MBsquare: 0x3386, + Macron: 0xF6D0, + Macronsmall: 0xF7AF, + Macute: 0x1E3E, + Mcircle: 0x24C2, + Mdotaccent: 0x1E40, + Mdotbelow: 0x1E42, + Menarmenian: 0x0544, + Mmonospace: 0xFF2D, + Msmall: 0xF76D, + Mturned: 0x019C, + Mu: 0x039C, + N: 0x004E, + NJ: 0x01CA, + Nacute: 0x0143, + Ncaron: 0x0147, + Ncedilla: 0x0145, + Ncircle: 0x24C3, + Ncircumflexbelow: 0x1E4A, + Ncommaaccent: 0x0145, + Ndotaccent: 0x1E44, + Ndotbelow: 0x1E46, + Nhookleft: 0x019D, + Nineroman: 0x2168, + Nj: 0x01CB, + Njecyrillic: 0x040A, + Nlinebelow: 0x1E48, + Nmonospace: 0xFF2E, + Nowarmenian: 0x0546, + Nsmall: 0xF76E, + Ntilde: 0x00D1, + Ntildesmall: 0xF7F1, + Nu: 0x039D, + O: 0x004F, + OE: 0x0152, + OEsmall: 0xF6FA, + Oacute: 0x00D3, + Oacutesmall: 0xF7F3, + Obarredcyrillic: 0x04E8, + Obarreddieresiscyrillic: 0x04EA, + Obreve: 0x014E, + Ocaron: 0x01D1, + Ocenteredtilde: 0x019F, + Ocircle: 0x24C4, + Ocircumflex: 0x00D4, + Ocircumflexacute: 0x1ED0, + Ocircumflexdotbelow: 0x1ED8, + Ocircumflexgrave: 0x1ED2, + Ocircumflexhookabove: 0x1ED4, + Ocircumflexsmall: 0xF7F4, + Ocircumflextilde: 0x1ED6, + Ocyrillic: 0x041E, + Odblacute: 0x0150, + Odblgrave: 0x020C, + Odieresis: 0x00D6, + Odieresiscyrillic: 0x04E6, + Odieresissmall: 0xF7F6, + Odotbelow: 0x1ECC, + Ogoneksmall: 0xF6FB, + Ograve: 0x00D2, + Ogravesmall: 0xF7F2, + Oharmenian: 0x0555, + Ohm: 0x2126, + Ohookabove: 0x1ECE, + Ohorn: 0x01A0, + Ohornacute: 0x1EDA, + Ohorndotbelow: 0x1EE2, + Ohorngrave: 0x1EDC, + Ohornhookabove: 0x1EDE, + Ohorntilde: 0x1EE0, + Ohungarumlaut: 0x0150, + Oi: 0x01A2, + Oinvertedbreve: 0x020E, + Omacron: 0x014C, + Omacronacute: 0x1E52, + Omacrongrave: 0x1E50, + Omega: 0x2126, + Omegacyrillic: 0x0460, + Omegagreek: 0x03A9, + Omegaroundcyrillic: 0x047A, + Omegatitlocyrillic: 0x047C, + Omegatonos: 0x038F, + Omicron: 0x039F, + Omicrontonos: 0x038C, + Omonospace: 0xFF2F, + Oneroman: 0x2160, + Oogonek: 0x01EA, + Oogonekmacron: 0x01EC, + Oopen: 0x0186, + Oslash: 0x00D8, + Oslashacute: 0x01FE, + Oslashsmall: 0xF7F8, + Osmall: 0xF76F, + Ostrokeacute: 0x01FE, + Otcyrillic: 0x047E, + Otilde: 0x00D5, + Otildeacute: 0x1E4C, + Otildedieresis: 0x1E4E, + Otildesmall: 0xF7F5, + P: 0x0050, + Pacute: 0x1E54, + Pcircle: 0x24C5, + Pdotaccent: 0x1E56, + Pecyrillic: 0x041F, + Peharmenian: 0x054A, + Pemiddlehookcyrillic: 0x04A6, + Phi: 0x03A6, + Phook: 0x01A4, + Pi: 0x03A0, + Piwrarmenian: 0x0553, + Pmonospace: 0xFF30, + Psi: 0x03A8, + Psicyrillic: 0x0470, + Psmall: 0xF770, + Q: 0x0051, + Qcircle: 0x24C6, + Qmonospace: 0xFF31, + Qsmall: 0xF771, + R: 0x0052, + Raarmenian: 0x054C, + Racute: 0x0154, + Rcaron: 0x0158, + Rcedilla: 0x0156, + Rcircle: 0x24C7, + Rcommaaccent: 0x0156, + Rdblgrave: 0x0210, + Rdotaccent: 0x1E58, + Rdotbelow: 0x1E5A, + Rdotbelowmacron: 0x1E5C, + Reharmenian: 0x0550, + Rfraktur: 0x211C, + Rho: 0x03A1, + Ringsmall: 0xF6FC, + Rinvertedbreve: 0x0212, + Rlinebelow: 0x1E5E, + Rmonospace: 0xFF32, + Rsmall: 0xF772, + Rsmallinverted: 0x0281, + Rsmallinvertedsuperior: 0x02B6, + S: 0x0053, + SF010000: 0x250C, + SF020000: 0x2514, + SF030000: 0x2510, + SF040000: 0x2518, + SF050000: 0x253C, + SF060000: 0x252C, + SF070000: 0x2534, + SF080000: 0x251C, + SF090000: 0x2524, + SF100000: 0x2500, + SF110000: 0x2502, + SF190000: 0x2561, + SF200000: 0x2562, + SF210000: 0x2556, + SF220000: 0x2555, + SF230000: 0x2563, + SF240000: 0x2551, + SF250000: 0x2557, + SF260000: 0x255D, + SF270000: 0x255C, + SF280000: 0x255B, + SF360000: 0x255E, + SF370000: 0x255F, + SF380000: 0x255A, + SF390000: 0x2554, + SF400000: 0x2569, + SF410000: 0x2566, + SF420000: 0x2560, + SF430000: 0x2550, + SF440000: 0x256C, + SF450000: 0x2567, + SF460000: 0x2568, + SF470000: 0x2564, + SF480000: 0x2565, + SF490000: 0x2559, + SF500000: 0x2558, + SF510000: 0x2552, + SF520000: 0x2553, + SF530000: 0x256B, + SF540000: 0x256A, + Sacute: 0x015A, + Sacutedotaccent: 0x1E64, + Sampigreek: 0x03E0, + Scaron: 0x0160, + Scarondotaccent: 0x1E66, + Scaronsmall: 0xF6FD, + Scedilla: 0x015E, + Schwa: 0x018F, + Schwacyrillic: 0x04D8, + Schwadieresiscyrillic: 0x04DA, + Scircle: 0x24C8, + Scircumflex: 0x015C, + Scommaaccent: 0x0218, + Sdotaccent: 0x1E60, + Sdotbelow: 0x1E62, + Sdotbelowdotaccent: 0x1E68, + Seharmenian: 0x054D, + Sevenroman: 0x2166, + Shaarmenian: 0x0547, + Shacyrillic: 0x0428, + Shchacyrillic: 0x0429, + Sheicoptic: 0x03E2, + Shhacyrillic: 0x04BA, + Shimacoptic: 0x03EC, + Sigma: 0x03A3, + Sixroman: 0x2165, + Smonospace: 0xFF33, + Softsigncyrillic: 0x042C, + Ssmall: 0xF773, + Stigmagreek: 0x03DA, + T: 0x0054, + Tau: 0x03A4, + Tbar: 0x0166, + Tcaron: 0x0164, + Tcedilla: 0x0162, + Tcircle: 0x24C9, + Tcircumflexbelow: 0x1E70, + Tcommaaccent: 0x0162, + Tdotaccent: 0x1E6A, + Tdotbelow: 0x1E6C, + Tecyrillic: 0x0422, + Tedescendercyrillic: 0x04AC, + Tenroman: 0x2169, + Tetsecyrillic: 0x04B4, + Theta: 0x0398, + Thook: 0x01AC, + Thorn: 0x00DE, + Thornsmall: 0xF7FE, + Threeroman: 0x2162, + Tildesmall: 0xF6FE, + Tiwnarmenian: 0x054F, + Tlinebelow: 0x1E6E, + Tmonospace: 0xFF34, + Toarmenian: 0x0539, + Tonefive: 0x01BC, + Tonesix: 0x0184, + Tonetwo: 0x01A7, + Tretroflexhook: 0x01AE, + Tsecyrillic: 0x0426, + Tshecyrillic: 0x040B, + Tsmall: 0xF774, + Twelveroman: 0x216B, + Tworoman: 0x2161, + U: 0x0055, + Uacute: 0x00DA, + Uacutesmall: 0xF7FA, + Ubreve: 0x016C, + Ucaron: 0x01D3, + Ucircle: 0x24CA, + Ucircumflex: 0x00DB, + Ucircumflexbelow: 0x1E76, + Ucircumflexsmall: 0xF7FB, + Ucyrillic: 0x0423, + Udblacute: 0x0170, + Udblgrave: 0x0214, + Udieresis: 0x00DC, + Udieresisacute: 0x01D7, + Udieresisbelow: 0x1E72, + Udieresiscaron: 0x01D9, + Udieresiscyrillic: 0x04F0, + Udieresisgrave: 0x01DB, + Udieresismacron: 0x01D5, + Udieresissmall: 0xF7FC, + Udotbelow: 0x1EE4, + Ugrave: 0x00D9, + Ugravesmall: 0xF7F9, + Uhookabove: 0x1EE6, + Uhorn: 0x01AF, + Uhornacute: 0x1EE8, + Uhorndotbelow: 0x1EF0, + Uhorngrave: 0x1EEA, + Uhornhookabove: 0x1EEC, + Uhorntilde: 0x1EEE, + Uhungarumlaut: 0x0170, + Uhungarumlautcyrillic: 0x04F2, + Uinvertedbreve: 0x0216, + Ukcyrillic: 0x0478, + Umacron: 0x016A, + Umacroncyrillic: 0x04EE, + Umacrondieresis: 0x1E7A, + Umonospace: 0xFF35, + Uogonek: 0x0172, + Upsilon: 0x03A5, + Upsilon1: 0x03D2, + Upsilonacutehooksymbolgreek: 0x03D3, + Upsilonafrican: 0x01B1, + Upsilondieresis: 0x03AB, + Upsilondieresishooksymbolgreek: 0x03D4, + Upsilonhooksymbol: 0x03D2, + Upsilontonos: 0x038E, + Uring: 0x016E, + Ushortcyrillic: 0x040E, + Usmall: 0xF775, + Ustraightcyrillic: 0x04AE, + Ustraightstrokecyrillic: 0x04B0, + Utilde: 0x0168, + Utildeacute: 0x1E78, + Utildebelow: 0x1E74, + V: 0x0056, + Vcircle: 0x24CB, + Vdotbelow: 0x1E7E, + Vecyrillic: 0x0412, + Vewarmenian: 0x054E, + Vhook: 0x01B2, + Vmonospace: 0xFF36, + Voarmenian: 0x0548, + Vsmall: 0xF776, + Vtilde: 0x1E7C, + W: 0x0057, + Wacute: 0x1E82, + Wcircle: 0x24CC, + Wcircumflex: 0x0174, + Wdieresis: 0x1E84, + Wdotaccent: 0x1E86, + Wdotbelow: 0x1E88, + Wgrave: 0x1E80, + Wmonospace: 0xFF37, + Wsmall: 0xF777, + X: 0x0058, + Xcircle: 0x24CD, + Xdieresis: 0x1E8C, + Xdotaccent: 0x1E8A, + Xeharmenian: 0x053D, + Xi: 0x039E, + Xmonospace: 0xFF38, + Xsmall: 0xF778, + Y: 0x0059, + Yacute: 0x00DD, + Yacutesmall: 0xF7FD, + Yatcyrillic: 0x0462, + Ycircle: 0x24CE, + Ycircumflex: 0x0176, + Ydieresis: 0x0178, + Ydieresissmall: 0xF7FF, + Ydotaccent: 0x1E8E, + Ydotbelow: 0x1EF4, + Yericyrillic: 0x042B, + Yerudieresiscyrillic: 0x04F8, + Ygrave: 0x1EF2, + Yhook: 0x01B3, + Yhookabove: 0x1EF6, + Yiarmenian: 0x0545, + Yicyrillic: 0x0407, + Yiwnarmenian: 0x0552, + Ymonospace: 0xFF39, + Ysmall: 0xF779, + Ytilde: 0x1EF8, + Yusbigcyrillic: 0x046A, + Yusbigiotifiedcyrillic: 0x046C, + Yuslittlecyrillic: 0x0466, + Yuslittleiotifiedcyrillic: 0x0468, + Z: 0x005A, + Zaarmenian: 0x0536, + Zacute: 0x0179, + Zcaron: 0x017D, + Zcaronsmall: 0xF6FF, + Zcircle: 0x24CF, + Zcircumflex: 0x1E90, + Zdot: 0x017B, + Zdotaccent: 0x017B, + Zdotbelow: 0x1E92, + Zecyrillic: 0x0417, + Zedescendercyrillic: 0x0498, + Zedieresiscyrillic: 0x04DE, + Zeta: 0x0396, + Zhearmenian: 0x053A, + Zhebrevecyrillic: 0x04C1, + Zhecyrillic: 0x0416, + Zhedescendercyrillic: 0x0496, + Zhedieresiscyrillic: 0x04DC, + Zlinebelow: 0x1E94, + Zmonospace: 0xFF3A, + Zsmall: 0xF77A, + Zstroke: 0x01B5, + a: 0x0061, + aabengali: 0x0986, + aacute: 0x00E1, + aadeva: 0x0906, + aagujarati: 0x0A86, + aagurmukhi: 0x0A06, + aamatragurmukhi: 0x0A3E, + aarusquare: 0x3303, + aavowelsignbengali: 0x09BE, + aavowelsigndeva: 0x093E, + aavowelsigngujarati: 0x0ABE, + abbreviationmarkarmenian: 0x055F, + abbreviationsigndeva: 0x0970, + abengali: 0x0985, + abopomofo: 0x311A, + abreve: 0x0103, + abreveacute: 0x1EAF, + abrevecyrillic: 0x04D1, + abrevedotbelow: 0x1EB7, + abrevegrave: 0x1EB1, + abrevehookabove: 0x1EB3, + abrevetilde: 0x1EB5, + acaron: 0x01CE, + acircle: 0x24D0, + acircumflex: 0x00E2, + acircumflexacute: 0x1EA5, + acircumflexdotbelow: 0x1EAD, + acircumflexgrave: 0x1EA7, + acircumflexhookabove: 0x1EA9, + acircumflextilde: 0x1EAB, + acute: 0x00B4, + acutebelowcmb: 0x0317, + acutecmb: 0x0301, + acutecomb: 0x0301, + acutedeva: 0x0954, + acutelowmod: 0x02CF, + acutetonecmb: 0x0341, + acyrillic: 0x0430, + adblgrave: 0x0201, + addakgurmukhi: 0x0A71, + adeva: 0x0905, + adieresis: 0x00E4, + adieresiscyrillic: 0x04D3, + adieresismacron: 0x01DF, + adotbelow: 0x1EA1, + adotmacron: 0x01E1, + ae: 0x00E6, + aeacute: 0x01FD, + aekorean: 0x3150, + aemacron: 0x01E3, + afii00208: 0x2015, + afii08941: 0x20A4, + afii10017: 0x0410, + afii10018: 0x0411, + afii10019: 0x0412, + afii10020: 0x0413, + afii10021: 0x0414, + afii10022: 0x0415, + afii10023: 0x0401, + afii10024: 0x0416, + afii10025: 0x0417, + afii10026: 0x0418, + afii10027: 0x0419, + afii10028: 0x041A, + afii10029: 0x041B, + afii10030: 0x041C, + afii10031: 0x041D, + afii10032: 0x041E, + afii10033: 0x041F, + afii10034: 0x0420, + afii10035: 0x0421, + afii10036: 0x0422, + afii10037: 0x0423, + afii10038: 0x0424, + afii10039: 0x0425, + afii10040: 0x0426, + afii10041: 0x0427, + afii10042: 0x0428, + afii10043: 0x0429, + afii10044: 0x042A, + afii10045: 0x042B, + afii10046: 0x042C, + afii10047: 0x042D, + afii10048: 0x042E, + afii10049: 0x042F, + afii10050: 0x0490, + afii10051: 0x0402, + afii10052: 0x0403, + afii10053: 0x0404, + afii10054: 0x0405, + afii10055: 0x0406, + afii10056: 0x0407, + afii10057: 0x0408, + afii10058: 0x0409, + afii10059: 0x040A, + afii10060: 0x040B, + afii10061: 0x040C, + afii10062: 0x040E, + afii10063: 0xF6C4, + afii10064: 0xF6C5, + afii10065: 0x0430, + afii10066: 0x0431, + afii10067: 0x0432, + afii10068: 0x0433, + afii10069: 0x0434, + afii10070: 0x0435, + afii10071: 0x0451, + afii10072: 0x0436, + afii10073: 0x0437, + afii10074: 0x0438, + afii10075: 0x0439, + afii10076: 0x043A, + afii10077: 0x043B, + afii10078: 0x043C, + afii10079: 0x043D, + afii10080: 0x043E, + afii10081: 0x043F, + afii10082: 0x0440, + afii10083: 0x0441, + afii10084: 0x0442, + afii10085: 0x0443, + afii10086: 0x0444, + afii10087: 0x0445, + afii10088: 0x0446, + afii10089: 0x0447, + afii10090: 0x0448, + afii10091: 0x0449, + afii10092: 0x044A, + afii10093: 0x044B, + afii10094: 0x044C, + afii10095: 0x044D, + afii10096: 0x044E, + afii10097: 0x044F, + afii10098: 0x0491, + afii10099: 0x0452, + afii10100: 0x0453, + afii10101: 0x0454, + afii10102: 0x0455, + afii10103: 0x0456, + afii10104: 0x0457, + afii10105: 0x0458, + afii10106: 0x0459, + afii10107: 0x045A, + afii10108: 0x045B, + afii10109: 0x045C, + afii10110: 0x045E, + afii10145: 0x040F, + afii10146: 0x0462, + afii10147: 0x0472, + afii10148: 0x0474, + afii10192: 0xF6C6, + afii10193: 0x045F, + afii10194: 0x0463, + afii10195: 0x0473, + afii10196: 0x0475, + afii10831: 0xF6C7, + afii10832: 0xF6C8, + afii10846: 0x04D9, + afii299: 0x200E, + afii300: 0x200F, + afii301: 0x200D, + afii57381: 0x066A, + afii57388: 0x060C, + afii57392: 0x0660, + afii57393: 0x0661, + afii57394: 0x0662, + afii57395: 0x0663, + afii57396: 0x0664, + afii57397: 0x0665, + afii57398: 0x0666, + afii57399: 0x0667, + afii57400: 0x0668, + afii57401: 0x0669, + afii57403: 0x061B, + afii57407: 0x061F, + afii57409: 0x0621, + afii57410: 0x0622, + afii57411: 0x0623, + afii57412: 0x0624, + afii57413: 0x0625, + afii57414: 0x0626, + afii57415: 0x0627, + afii57416: 0x0628, + afii57417: 0x0629, + afii57418: 0x062A, + afii57419: 0x062B, + afii57420: 0x062C, + afii57421: 0x062D, + afii57422: 0x062E, + afii57423: 0x062F, + afii57424: 0x0630, + afii57425: 0x0631, + afii57426: 0x0632, + afii57427: 0x0633, + afii57428: 0x0634, + afii57429: 0x0635, + afii57430: 0x0636, + afii57431: 0x0637, + afii57432: 0x0638, + afii57433: 0x0639, + afii57434: 0x063A, + afii57440: 0x0640, + afii57441: 0x0641, + afii57442: 0x0642, + afii57443: 0x0643, + afii57444: 0x0644, + afii57445: 0x0645, + afii57446: 0x0646, + afii57448: 0x0648, + afii57449: 0x0649, + afii57450: 0x064A, + afii57451: 0x064B, + afii57452: 0x064C, + afii57453: 0x064D, + afii57454: 0x064E, + afii57455: 0x064F, + afii57456: 0x0650, + afii57457: 0x0651, + afii57458: 0x0652, + afii57470: 0x0647, + afii57505: 0x06A4, + afii57506: 0x067E, + afii57507: 0x0686, + afii57508: 0x0698, + afii57509: 0x06AF, + afii57511: 0x0679, + afii57512: 0x0688, + afii57513: 0x0691, + afii57514: 0x06BA, + afii57519: 0x06D2, + afii57534: 0x06D5, + afii57636: 0x20AA, + afii57645: 0x05BE, + afii57658: 0x05C3, + afii57664: 0x05D0, + afii57665: 0x05D1, + afii57666: 0x05D2, + afii57667: 0x05D3, + afii57668: 0x05D4, + afii57669: 0x05D5, + afii57670: 0x05D6, + afii57671: 0x05D7, + afii57672: 0x05D8, + afii57673: 0x05D9, + afii57674: 0x05DA, + afii57675: 0x05DB, + afii57676: 0x05DC, + afii57677: 0x05DD, + afii57678: 0x05DE, + afii57679: 0x05DF, + afii57680: 0x05E0, + afii57681: 0x05E1, + afii57682: 0x05E2, + afii57683: 0x05E3, + afii57684: 0x05E4, + afii57685: 0x05E5, + afii57686: 0x05E6, + afii57687: 0x05E7, + afii57688: 0x05E8, + afii57689: 0x05E9, + afii57690: 0x05EA, + afii57694: 0xFB2A, + afii57695: 0xFB2B, + afii57700: 0xFB4B, + afii57705: 0xFB1F, + afii57716: 0x05F0, + afii57717: 0x05F1, + afii57718: 0x05F2, + afii57723: 0xFB35, + afii57793: 0x05B4, + afii57794: 0x05B5, + afii57795: 0x05B6, + afii57796: 0x05BB, + afii57797: 0x05B8, + afii57798: 0x05B7, + afii57799: 0x05B0, + afii57800: 0x05B2, + afii57801: 0x05B1, + afii57802: 0x05B3, + afii57803: 0x05C2, + afii57804: 0x05C1, + afii57806: 0x05B9, + afii57807: 0x05BC, + afii57839: 0x05BD, + afii57841: 0x05BF, + afii57842: 0x05C0, + afii57929: 0x02BC, + afii61248: 0x2105, + afii61289: 0x2113, + afii61352: 0x2116, + afii61573: 0x202C, + afii61574: 0x202D, + afii61575: 0x202E, + afii61664: 0x200C, + afii63167: 0x066D, + afii64937: 0x02BD, + agrave: 0x00E0, + agujarati: 0x0A85, + agurmukhi: 0x0A05, + ahiragana: 0x3042, + ahookabove: 0x1EA3, + aibengali: 0x0990, + aibopomofo: 0x311E, + aideva: 0x0910, + aiecyrillic: 0x04D5, + aigujarati: 0x0A90, + aigurmukhi: 0x0A10, + aimatragurmukhi: 0x0A48, + ainarabic: 0x0639, + ainfinalarabic: 0xFECA, + aininitialarabic: 0xFECB, + ainmedialarabic: 0xFECC, + ainvertedbreve: 0x0203, + aivowelsignbengali: 0x09C8, + aivowelsigndeva: 0x0948, + aivowelsigngujarati: 0x0AC8, + akatakana: 0x30A2, + akatakanahalfwidth: 0xFF71, + akorean: 0x314F, + alef: 0x05D0, + alefarabic: 0x0627, + alefdageshhebrew: 0xFB30, + aleffinalarabic: 0xFE8E, + alefhamzaabovearabic: 0x0623, + alefhamzaabovefinalarabic: 0xFE84, + alefhamzabelowarabic: 0x0625, + alefhamzabelowfinalarabic: 0xFE88, + alefhebrew: 0x05D0, + aleflamedhebrew: 0xFB4F, + alefmaddaabovearabic: 0x0622, + alefmaddaabovefinalarabic: 0xFE82, + alefmaksuraarabic: 0x0649, + alefmaksurafinalarabic: 0xFEF0, + alefmaksurainitialarabic: 0xFEF3, + alefmaksuramedialarabic: 0xFEF4, + alefpatahhebrew: 0xFB2E, + alefqamatshebrew: 0xFB2F, + aleph: 0x2135, + allequal: 0x224C, + alpha: 0x03B1, + alphatonos: 0x03AC, + amacron: 0x0101, + amonospace: 0xFF41, + ampersand: 0x0026, + ampersandmonospace: 0xFF06, + ampersandsmall: 0xF726, + amsquare: 0x33C2, + anbopomofo: 0x3122, + angbopomofo: 0x3124, + angbracketleft: 0x3008, // This glyph is missing from Adobe's original list. + angbracketright: 0x3009, // This glyph is missing from Adobe's original list. + angkhankhuthai: 0x0E5A, + angle: 0x2220, + anglebracketleft: 0x3008, + anglebracketleftvertical: 0xFE3F, + anglebracketright: 0x3009, + anglebracketrightvertical: 0xFE40, + angleleft: 0x2329, + angleright: 0x232A, + angstrom: 0x212B, + anoteleia: 0x0387, + anudattadeva: 0x0952, + anusvarabengali: 0x0982, + anusvaradeva: 0x0902, + anusvaragujarati: 0x0A82, + aogonek: 0x0105, + apaatosquare: 0x3300, + aparen: 0x249C, + apostrophearmenian: 0x055A, + apostrophemod: 0x02BC, + apple: 0xF8FF, + approaches: 0x2250, + approxequal: 0x2248, + approxequalorimage: 0x2252, + approximatelyequal: 0x2245, + araeaekorean: 0x318E, + araeakorean: 0x318D, + arc: 0x2312, + arighthalfring: 0x1E9A, + aring: 0x00E5, + aringacute: 0x01FB, + aringbelow: 0x1E01, + arrowboth: 0x2194, + arrowdashdown: 0x21E3, + arrowdashleft: 0x21E0, + arrowdashright: 0x21E2, + arrowdashup: 0x21E1, + arrowdblboth: 0x21D4, + arrowdbldown: 0x21D3, + arrowdblleft: 0x21D0, + arrowdblright: 0x21D2, + arrowdblup: 0x21D1, + arrowdown: 0x2193, + arrowdownleft: 0x2199, + arrowdownright: 0x2198, + arrowdownwhite: 0x21E9, + arrowheaddownmod: 0x02C5, + arrowheadleftmod: 0x02C2, + arrowheadrightmod: 0x02C3, + arrowheadupmod: 0x02C4, + arrowhorizex: 0xF8E7, + arrowleft: 0x2190, + arrowleftdbl: 0x21D0, + arrowleftdblstroke: 0x21CD, + arrowleftoverright: 0x21C6, + arrowleftwhite: 0x21E6, + arrowright: 0x2192, + arrowrightdblstroke: 0x21CF, + arrowrightheavy: 0x279E, + arrowrightoverleft: 0x21C4, + arrowrightwhite: 0x21E8, + arrowtableft: 0x21E4, + arrowtabright: 0x21E5, + arrowup: 0x2191, + arrowupdn: 0x2195, + arrowupdnbse: 0x21A8, + arrowupdownbase: 0x21A8, + arrowupleft: 0x2196, + arrowupleftofdown: 0x21C5, + arrowupright: 0x2197, + arrowupwhite: 0x21E7, + arrowvertex: 0xF8E6, + asciicircum: 0x005E, + asciicircummonospace: 0xFF3E, + asciitilde: 0x007E, + asciitildemonospace: 0xFF5E, + ascript: 0x0251, + ascriptturned: 0x0252, + asmallhiragana: 0x3041, + asmallkatakana: 0x30A1, + asmallkatakanahalfwidth: 0xFF67, + asterisk: 0x002A, + asteriskaltonearabic: 0x066D, + asteriskarabic: 0x066D, + asteriskmath: 0x2217, + asteriskmonospace: 0xFF0A, + asterisksmall: 0xFE61, + asterism: 0x2042, + asuperior: 0xF6E9, + asymptoticallyequal: 0x2243, + at: 0x0040, + atilde: 0x00E3, + atmonospace: 0xFF20, + atsmall: 0xFE6B, + aturned: 0x0250, + aubengali: 0x0994, + aubopomofo: 0x3120, + audeva: 0x0914, + augujarati: 0x0A94, + augurmukhi: 0x0A14, + aulengthmarkbengali: 0x09D7, + aumatragurmukhi: 0x0A4C, + auvowelsignbengali: 0x09CC, + auvowelsigndeva: 0x094C, + auvowelsigngujarati: 0x0ACC, + avagrahadeva: 0x093D, + aybarmenian: 0x0561, + ayin: 0x05E2, + ayinaltonehebrew: 0xFB20, + ayinhebrew: 0x05E2, + b: 0x0062, + babengali: 0x09AC, + backslash: 0x005C, + backslashmonospace: 0xFF3C, + badeva: 0x092C, + bagujarati: 0x0AAC, + bagurmukhi: 0x0A2C, + bahiragana: 0x3070, + bahtthai: 0x0E3F, + bakatakana: 0x30D0, + bar: 0x007C, + barmonospace: 0xFF5C, + bbopomofo: 0x3105, + bcircle: 0x24D1, + bdotaccent: 0x1E03, + bdotbelow: 0x1E05, + beamedsixteenthnotes: 0x266C, + because: 0x2235, + becyrillic: 0x0431, + beharabic: 0x0628, + behfinalarabic: 0xFE90, + behinitialarabic: 0xFE91, + behiragana: 0x3079, + behmedialarabic: 0xFE92, + behmeeminitialarabic: 0xFC9F, + behmeemisolatedarabic: 0xFC08, + behnoonfinalarabic: 0xFC6D, + bekatakana: 0x30D9, + benarmenian: 0x0562, + bet: 0x05D1, + beta: 0x03B2, + betasymbolgreek: 0x03D0, + betdagesh: 0xFB31, + betdageshhebrew: 0xFB31, + bethebrew: 0x05D1, + betrafehebrew: 0xFB4C, + bhabengali: 0x09AD, + bhadeva: 0x092D, + bhagujarati: 0x0AAD, + bhagurmukhi: 0x0A2D, + bhook: 0x0253, + bihiragana: 0x3073, + bikatakana: 0x30D3, + bilabialclick: 0x0298, + bindigurmukhi: 0x0A02, + birusquare: 0x3331, + blackcircle: 0x25CF, + blackdiamond: 0x25C6, + blackdownpointingtriangle: 0x25BC, + blackleftpointingpointer: 0x25C4, + blackleftpointingtriangle: 0x25C0, + blacklenticularbracketleft: 0x3010, + blacklenticularbracketleftvertical: 0xFE3B, + blacklenticularbracketright: 0x3011, + blacklenticularbracketrightvertical: 0xFE3C, + blacklowerlefttriangle: 0x25E3, + blacklowerrighttriangle: 0x25E2, + blackrectangle: 0x25AC, + blackrightpointingpointer: 0x25BA, + blackrightpointingtriangle: 0x25B6, + blacksmallsquare: 0x25AA, + blacksmilingface: 0x263B, + blacksquare: 0x25A0, + blackstar: 0x2605, + blackupperlefttriangle: 0x25E4, + blackupperrighttriangle: 0x25E5, + blackuppointingsmalltriangle: 0x25B4, + blackuppointingtriangle: 0x25B2, + blank: 0x2423, + blinebelow: 0x1E07, + block: 0x2588, + bmonospace: 0xFF42, + bobaimaithai: 0x0E1A, + bohiragana: 0x307C, + bokatakana: 0x30DC, + bparen: 0x249D, + bqsquare: 0x33C3, + braceex: 0xF8F4, + braceleft: 0x007B, + braceleftbt: 0xF8F3, + braceleftmid: 0xF8F2, + braceleftmonospace: 0xFF5B, + braceleftsmall: 0xFE5B, + bracelefttp: 0xF8F1, + braceleftvertical: 0xFE37, + braceright: 0x007D, + bracerightbt: 0xF8FE, + bracerightmid: 0xF8FD, + bracerightmonospace: 0xFF5D, + bracerightsmall: 0xFE5C, + bracerighttp: 0xF8FC, + bracerightvertical: 0xFE38, + bracketleft: 0x005B, + bracketleftbt: 0xF8F0, + bracketleftex: 0xF8EF, + bracketleftmonospace: 0xFF3B, + bracketlefttp: 0xF8EE, + bracketright: 0x005D, + bracketrightbt: 0xF8FB, + bracketrightex: 0xF8FA, + bracketrightmonospace: 0xFF3D, + bracketrighttp: 0xF8F9, + breve: 0x02D8, + brevebelowcmb: 0x032E, + brevecmb: 0x0306, + breveinvertedbelowcmb: 0x032F, + breveinvertedcmb: 0x0311, + breveinverteddoublecmb: 0x0361, + bridgebelowcmb: 0x032A, + bridgeinvertedbelowcmb: 0x033A, + brokenbar: 0x00A6, + bstroke: 0x0180, + bsuperior: 0xF6EA, + btopbar: 0x0183, + buhiragana: 0x3076, + bukatakana: 0x30D6, + bullet: 0x2022, + bulletinverse: 0x25D8, + bulletoperator: 0x2219, + bullseye: 0x25CE, + c: 0x0063, + caarmenian: 0x056E, + cabengali: 0x099A, + cacute: 0x0107, + cadeva: 0x091A, + cagujarati: 0x0A9A, + cagurmukhi: 0x0A1A, + calsquare: 0x3388, + candrabindubengali: 0x0981, + candrabinducmb: 0x0310, + candrabindudeva: 0x0901, + candrabindugujarati: 0x0A81, + capslock: 0x21EA, + careof: 0x2105, + caron: 0x02C7, + caronbelowcmb: 0x032C, + caroncmb: 0x030C, + carriagereturn: 0x21B5, + cbopomofo: 0x3118, + ccaron: 0x010D, + ccedilla: 0x00E7, + ccedillaacute: 0x1E09, + ccircle: 0x24D2, + ccircumflex: 0x0109, + ccurl: 0x0255, + cdot: 0x010B, + cdotaccent: 0x010B, + cdsquare: 0x33C5, + cedilla: 0x00B8, + cedillacmb: 0x0327, + cent: 0x00A2, + centigrade: 0x2103, + centinferior: 0xF6DF, + centmonospace: 0xFFE0, + centoldstyle: 0xF7A2, + centsuperior: 0xF6E0, + chaarmenian: 0x0579, + chabengali: 0x099B, + chadeva: 0x091B, + chagujarati: 0x0A9B, + chagurmukhi: 0x0A1B, + chbopomofo: 0x3114, + cheabkhasiancyrillic: 0x04BD, + checkmark: 0x2713, + checyrillic: 0x0447, + chedescenderabkhasiancyrillic: 0x04BF, + chedescendercyrillic: 0x04B7, + chedieresiscyrillic: 0x04F5, + cheharmenian: 0x0573, + chekhakassiancyrillic: 0x04CC, + cheverticalstrokecyrillic: 0x04B9, + chi: 0x03C7, + chieuchacirclekorean: 0x3277, + chieuchaparenkorean: 0x3217, + chieuchcirclekorean: 0x3269, + chieuchkorean: 0x314A, + chieuchparenkorean: 0x3209, + chochangthai: 0x0E0A, + chochanthai: 0x0E08, + chochingthai: 0x0E09, + chochoethai: 0x0E0C, + chook: 0x0188, + cieucacirclekorean: 0x3276, + cieucaparenkorean: 0x3216, + cieuccirclekorean: 0x3268, + cieuckorean: 0x3148, + cieucparenkorean: 0x3208, + cieucuparenkorean: 0x321C, + circle: 0x25CB, + circlecopyrt: 0x00A9, // This glyph is missing from Adobe's original list. + circlemultiply: 0x2297, + circleot: 0x2299, + circleplus: 0x2295, + circlepostalmark: 0x3036, + circlewithlefthalfblack: 0x25D0, + circlewithrighthalfblack: 0x25D1, + circumflex: 0x02C6, + circumflexbelowcmb: 0x032D, + circumflexcmb: 0x0302, + clear: 0x2327, + clickalveolar: 0x01C2, + clickdental: 0x01C0, + clicklateral: 0x01C1, + clickretroflex: 0x01C3, + club: 0x2663, + clubsuitblack: 0x2663, + clubsuitwhite: 0x2667, + cmcubedsquare: 0x33A4, + cmonospace: 0xFF43, + cmsquaredsquare: 0x33A0, + coarmenian: 0x0581, + colon: 0x003A, + colonmonetary: 0x20A1, + colonmonospace: 0xFF1A, + colonsign: 0x20A1, + colonsmall: 0xFE55, + colontriangularhalfmod: 0x02D1, + colontriangularmod: 0x02D0, + comma: 0x002C, + commaabovecmb: 0x0313, + commaaboverightcmb: 0x0315, + commaaccent: 0xF6C3, + commaarabic: 0x060C, + commaarmenian: 0x055D, + commainferior: 0xF6E1, + commamonospace: 0xFF0C, + commareversedabovecmb: 0x0314, + commareversedmod: 0x02BD, + commasmall: 0xFE50, + commasuperior: 0xF6E2, + commaturnedabovecmb: 0x0312, + commaturnedmod: 0x02BB, + compass: 0x263C, + congruent: 0x2245, + contourintegral: 0x222E, + control: 0x2303, + controlACK: 0x0006, + controlBEL: 0x0007, + controlBS: 0x0008, + controlCAN: 0x0018, + controlCR: 0x000D, + controlDC1: 0x0011, + controlDC2: 0x0012, + controlDC3: 0x0013, + controlDC4: 0x0014, + controlDEL: 0x007F, + controlDLE: 0x0010, + controlEM: 0x0019, + controlENQ: 0x0005, + controlEOT: 0x0004, + controlESC: 0x001B, + controlETB: 0x0017, + controlETX: 0x0003, + controlFF: 0x000C, + controlFS: 0x001C, + controlGS: 0x001D, + controlHT: 0x0009, + controlLF: 0x000A, + controlNAK: 0x0015, + controlRS: 0x001E, + controlSI: 0x000F, + controlSO: 0x000E, + controlSOT: 0x0002, + controlSTX: 0x0001, + controlSUB: 0x001A, + controlSYN: 0x0016, + controlUS: 0x001F, + controlVT: 0x000B, + copyright: 0x00A9, + copyrightsans: 0xF8E9, + copyrightserif: 0xF6D9, + cornerbracketleft: 0x300C, + cornerbracketlefthalfwidth: 0xFF62, + cornerbracketleftvertical: 0xFE41, + cornerbracketright: 0x300D, + cornerbracketrighthalfwidth: 0xFF63, + cornerbracketrightvertical: 0xFE42, + corporationsquare: 0x337F, + cosquare: 0x33C7, + coverkgsquare: 0x33C6, + cparen: 0x249E, + cruzeiro: 0x20A2, + cstretched: 0x0297, + curlyand: 0x22CF, + curlyor: 0x22CE, + currency: 0x00A4, + cyrBreve: 0xF6D1, + cyrFlex: 0xF6D2, + cyrbreve: 0xF6D4, + cyrflex: 0xF6D5, + d: 0x0064, + daarmenian: 0x0564, + dabengali: 0x09A6, + dadarabic: 0x0636, + dadeva: 0x0926, + dadfinalarabic: 0xFEBE, + dadinitialarabic: 0xFEBF, + dadmedialarabic: 0xFEC0, + dagesh: 0x05BC, + dageshhebrew: 0x05BC, + dagger: 0x2020, + daggerdbl: 0x2021, + dagujarati: 0x0AA6, + dagurmukhi: 0x0A26, + dahiragana: 0x3060, + dakatakana: 0x30C0, + dalarabic: 0x062F, + dalet: 0x05D3, + daletdagesh: 0xFB33, + daletdageshhebrew: 0xFB33, + dalethebrew: 0x05D3, + dalfinalarabic: 0xFEAA, + dammaarabic: 0x064F, + dammalowarabic: 0x064F, + dammatanaltonearabic: 0x064C, + dammatanarabic: 0x064C, + danda: 0x0964, + dargahebrew: 0x05A7, + dargalefthebrew: 0x05A7, + dasiapneumatacyrilliccmb: 0x0485, + dblGrave: 0xF6D3, + dblanglebracketleft: 0x300A, + dblanglebracketleftvertical: 0xFE3D, + dblanglebracketright: 0x300B, + dblanglebracketrightvertical: 0xFE3E, + dblarchinvertedbelowcmb: 0x032B, + dblarrowleft: 0x21D4, + dblarrowright: 0x21D2, + dbldanda: 0x0965, + dblgrave: 0xF6D6, + dblgravecmb: 0x030F, + dblintegral: 0x222C, + dbllowline: 0x2017, + dbllowlinecmb: 0x0333, + dbloverlinecmb: 0x033F, + dblprimemod: 0x02BA, + dblverticalbar: 0x2016, + dblverticallineabovecmb: 0x030E, + dbopomofo: 0x3109, + dbsquare: 0x33C8, + dcaron: 0x010F, + dcedilla: 0x1E11, + dcircle: 0x24D3, + dcircumflexbelow: 0x1E13, + dcroat: 0x0111, + ddabengali: 0x09A1, + ddadeva: 0x0921, + ddagujarati: 0x0AA1, + ddagurmukhi: 0x0A21, + ddalarabic: 0x0688, + ddalfinalarabic: 0xFB89, + dddhadeva: 0x095C, + ddhabengali: 0x09A2, + ddhadeva: 0x0922, + ddhagujarati: 0x0AA2, + ddhagurmukhi: 0x0A22, + ddotaccent: 0x1E0B, + ddotbelow: 0x1E0D, + decimalseparatorarabic: 0x066B, + decimalseparatorpersian: 0x066B, + decyrillic: 0x0434, + degree: 0x00B0, + dehihebrew: 0x05AD, + dehiragana: 0x3067, + deicoptic: 0x03EF, + dekatakana: 0x30C7, + deleteleft: 0x232B, + deleteright: 0x2326, + delta: 0x03B4, + deltaturned: 0x018D, + denominatorminusonenumeratorbengali: 0x09F8, + dezh: 0x02A4, + dhabengali: 0x09A7, + dhadeva: 0x0927, + dhagujarati: 0x0AA7, + dhagurmukhi: 0x0A27, + dhook: 0x0257, + dialytikatonos: 0x0385, + dialytikatonoscmb: 0x0344, + diamond: 0x2666, + diamondsuitwhite: 0x2662, + dieresis: 0x00A8, + dieresisacute: 0xF6D7, + dieresisbelowcmb: 0x0324, + dieresiscmb: 0x0308, + dieresisgrave: 0xF6D8, + dieresistonos: 0x0385, + dihiragana: 0x3062, + dikatakana: 0x30C2, + dittomark: 0x3003, + divide: 0x00F7, + divides: 0x2223, + divisionslash: 0x2215, + djecyrillic: 0x0452, + dkshade: 0x2593, + dlinebelow: 0x1E0F, + dlsquare: 0x3397, + dmacron: 0x0111, + dmonospace: 0xFF44, + dnblock: 0x2584, + dochadathai: 0x0E0E, + dodekthai: 0x0E14, + dohiragana: 0x3069, + dokatakana: 0x30C9, + dollar: 0x0024, + dollarinferior: 0xF6E3, + dollarmonospace: 0xFF04, + dollaroldstyle: 0xF724, + dollarsmall: 0xFE69, + dollarsuperior: 0xF6E4, + dong: 0x20AB, + dorusquare: 0x3326, + dotaccent: 0x02D9, + dotaccentcmb: 0x0307, + dotbelowcmb: 0x0323, + dotbelowcomb: 0x0323, + dotkatakana: 0x30FB, + dotlessi: 0x0131, + dotlessj: 0xF6BE, + dotlessjstrokehook: 0x0284, + dotmath: 0x22C5, + dottedcircle: 0x25CC, + doubleyodpatah: 0xFB1F, + doubleyodpatahhebrew: 0xFB1F, + downtackbelowcmb: 0x031E, + downtackmod: 0x02D5, + dparen: 0x249F, + dsuperior: 0xF6EB, + dtail: 0x0256, + dtopbar: 0x018C, + duhiragana: 0x3065, + dukatakana: 0x30C5, + dz: 0x01F3, + dzaltone: 0x02A3, + dzcaron: 0x01C6, + dzcurl: 0x02A5, + dzeabkhasiancyrillic: 0x04E1, + dzecyrillic: 0x0455, + dzhecyrillic: 0x045F, + e: 0x0065, + eacute: 0x00E9, + earth: 0x2641, + ebengali: 0x098F, + ebopomofo: 0x311C, + ebreve: 0x0115, + ecandradeva: 0x090D, + ecandragujarati: 0x0A8D, + ecandravowelsigndeva: 0x0945, + ecandravowelsigngujarati: 0x0AC5, + ecaron: 0x011B, + ecedillabreve: 0x1E1D, + echarmenian: 0x0565, + echyiwnarmenian: 0x0587, + ecircle: 0x24D4, + ecircumflex: 0x00EA, + ecircumflexacute: 0x1EBF, + ecircumflexbelow: 0x1E19, + ecircumflexdotbelow: 0x1EC7, + ecircumflexgrave: 0x1EC1, + ecircumflexhookabove: 0x1EC3, + ecircumflextilde: 0x1EC5, + ecyrillic: 0x0454, + edblgrave: 0x0205, + edeva: 0x090F, + edieresis: 0x00EB, + edot: 0x0117, + edotaccent: 0x0117, + edotbelow: 0x1EB9, + eegurmukhi: 0x0A0F, + eematragurmukhi: 0x0A47, + efcyrillic: 0x0444, + egrave: 0x00E8, + egujarati: 0x0A8F, + eharmenian: 0x0567, + ehbopomofo: 0x311D, + ehiragana: 0x3048, + ehookabove: 0x1EBB, + eibopomofo: 0x311F, + eight: 0x0038, + eightarabic: 0x0668, + eightbengali: 0x09EE, + eightcircle: 0x2467, + eightcircleinversesansserif: 0x2791, + eightdeva: 0x096E, + eighteencircle: 0x2471, + eighteenparen: 0x2485, + eighteenperiod: 0x2499, + eightgujarati: 0x0AEE, + eightgurmukhi: 0x0A6E, + eighthackarabic: 0x0668, + eighthangzhou: 0x3028, + eighthnotebeamed: 0x266B, + eightideographicparen: 0x3227, + eightinferior: 0x2088, + eightmonospace: 0xFF18, + eightoldstyle: 0xF738, + eightparen: 0x247B, + eightperiod: 0x248F, + eightpersian: 0x06F8, + eightroman: 0x2177, + eightsuperior: 0x2078, + eightthai: 0x0E58, + einvertedbreve: 0x0207, + eiotifiedcyrillic: 0x0465, + ekatakana: 0x30A8, + ekatakanahalfwidth: 0xFF74, + ekonkargurmukhi: 0x0A74, + ekorean: 0x3154, + elcyrillic: 0x043B, + element: 0x2208, + elevencircle: 0x246A, + elevenparen: 0x247E, + elevenperiod: 0x2492, + elevenroman: 0x217A, + ellipsis: 0x2026, + ellipsisvertical: 0x22EE, + emacron: 0x0113, + emacronacute: 0x1E17, + emacrongrave: 0x1E15, + emcyrillic: 0x043C, + emdash: 0x2014, + emdashvertical: 0xFE31, + emonospace: 0xFF45, + emphasismarkarmenian: 0x055B, + emptyset: 0x2205, + enbopomofo: 0x3123, + encyrillic: 0x043D, + endash: 0x2013, + endashvertical: 0xFE32, + endescendercyrillic: 0x04A3, + eng: 0x014B, + engbopomofo: 0x3125, + enghecyrillic: 0x04A5, + enhookcyrillic: 0x04C8, + enspace: 0x2002, + eogonek: 0x0119, + eokorean: 0x3153, + eopen: 0x025B, + eopenclosed: 0x029A, + eopenreversed: 0x025C, + eopenreversedclosed: 0x025E, + eopenreversedhook: 0x025D, + eparen: 0x24A0, + epsilon: 0x03B5, + epsilontonos: 0x03AD, + equal: 0x003D, + equalmonospace: 0xFF1D, + equalsmall: 0xFE66, + equalsuperior: 0x207C, + equivalence: 0x2261, + erbopomofo: 0x3126, + ercyrillic: 0x0440, + ereversed: 0x0258, + ereversedcyrillic: 0x044D, + escyrillic: 0x0441, + esdescendercyrillic: 0x04AB, + esh: 0x0283, + eshcurl: 0x0286, + eshortdeva: 0x090E, + eshortvowelsigndeva: 0x0946, + eshreversedloop: 0x01AA, + eshsquatreversed: 0x0285, + esmallhiragana: 0x3047, + esmallkatakana: 0x30A7, + esmallkatakanahalfwidth: 0xFF6A, + estimated: 0x212E, + esuperior: 0xF6EC, + eta: 0x03B7, + etarmenian: 0x0568, + etatonos: 0x03AE, + eth: 0x00F0, + etilde: 0x1EBD, + etildebelow: 0x1E1B, + etnahtafoukhhebrew: 0x0591, + etnahtafoukhlefthebrew: 0x0591, + etnahtahebrew: 0x0591, + etnahtalefthebrew: 0x0591, + eturned: 0x01DD, + eukorean: 0x3161, + euro: 0x20AC, + evowelsignbengali: 0x09C7, + evowelsigndeva: 0x0947, + evowelsigngujarati: 0x0AC7, + exclam: 0x0021, + exclamarmenian: 0x055C, + exclamdbl: 0x203C, + exclamdown: 0x00A1, + exclamdownsmall: 0xF7A1, + exclammonospace: 0xFF01, + exclamsmall: 0xF721, + existential: 0x2203, + ezh: 0x0292, + ezhcaron: 0x01EF, + ezhcurl: 0x0293, + ezhreversed: 0x01B9, + ezhtail: 0x01BA, + f: 0x0066, + fadeva: 0x095E, + fagurmukhi: 0x0A5E, + fahrenheit: 0x2109, + fathaarabic: 0x064E, + fathalowarabic: 0x064E, + fathatanarabic: 0x064B, + fbopomofo: 0x3108, + fcircle: 0x24D5, + fdotaccent: 0x1E1F, + feharabic: 0x0641, + feharmenian: 0x0586, + fehfinalarabic: 0xFED2, + fehinitialarabic: 0xFED3, + fehmedialarabic: 0xFED4, + feicoptic: 0x03E5, + female: 0x2640, + ff: 0xFB00, + ffi: 0xFB03, + ffl: 0xFB04, + fi: 0xFB01, + fifteencircle: 0x246E, + fifteenparen: 0x2482, + fifteenperiod: 0x2496, + figuredash: 0x2012, + filledbox: 0x25A0, + filledrect: 0x25AC, + finalkaf: 0x05DA, + finalkafdagesh: 0xFB3A, + finalkafdageshhebrew: 0xFB3A, + finalkafhebrew: 0x05DA, + finalmem: 0x05DD, + finalmemhebrew: 0x05DD, + finalnun: 0x05DF, + finalnunhebrew: 0x05DF, + finalpe: 0x05E3, + finalpehebrew: 0x05E3, + finaltsadi: 0x05E5, + finaltsadihebrew: 0x05E5, + firsttonechinese: 0x02C9, + fisheye: 0x25C9, + fitacyrillic: 0x0473, + five: 0x0035, + fivearabic: 0x0665, + fivebengali: 0x09EB, + fivecircle: 0x2464, + fivecircleinversesansserif: 0x278E, + fivedeva: 0x096B, + fiveeighths: 0x215D, + fivegujarati: 0x0AEB, + fivegurmukhi: 0x0A6B, + fivehackarabic: 0x0665, + fivehangzhou: 0x3025, + fiveideographicparen: 0x3224, + fiveinferior: 0x2085, + fivemonospace: 0xFF15, + fiveoldstyle: 0xF735, + fiveparen: 0x2478, + fiveperiod: 0x248C, + fivepersian: 0x06F5, + fiveroman: 0x2174, + fivesuperior: 0x2075, + fivethai: 0x0E55, + fl: 0xFB02, + florin: 0x0192, + fmonospace: 0xFF46, + fmsquare: 0x3399, + fofanthai: 0x0E1F, + fofathai: 0x0E1D, + fongmanthai: 0x0E4F, + forall: 0x2200, + four: 0x0034, + fourarabic: 0x0664, + fourbengali: 0x09EA, + fourcircle: 0x2463, + fourcircleinversesansserif: 0x278D, + fourdeva: 0x096A, + fourgujarati: 0x0AEA, + fourgurmukhi: 0x0A6A, + fourhackarabic: 0x0664, + fourhangzhou: 0x3024, + fourideographicparen: 0x3223, + fourinferior: 0x2084, + fourmonospace: 0xFF14, + fournumeratorbengali: 0x09F7, + fouroldstyle: 0xF734, + fourparen: 0x2477, + fourperiod: 0x248B, + fourpersian: 0x06F4, + fourroman: 0x2173, + foursuperior: 0x2074, + fourteencircle: 0x246D, + fourteenparen: 0x2481, + fourteenperiod: 0x2495, + fourthai: 0x0E54, + fourthtonechinese: 0x02CB, + fparen: 0x24A1, + fraction: 0x2044, + franc: 0x20A3, + g: 0x0067, + gabengali: 0x0997, + gacute: 0x01F5, + gadeva: 0x0917, + gafarabic: 0x06AF, + gaffinalarabic: 0xFB93, + gafinitialarabic: 0xFB94, + gafmedialarabic: 0xFB95, + gagujarati: 0x0A97, + gagurmukhi: 0x0A17, + gahiragana: 0x304C, + gakatakana: 0x30AC, + gamma: 0x03B3, + gammalatinsmall: 0x0263, + gammasuperior: 0x02E0, + gangiacoptic: 0x03EB, + gbopomofo: 0x310D, + gbreve: 0x011F, + gcaron: 0x01E7, + gcedilla: 0x0123, + gcircle: 0x24D6, + gcircumflex: 0x011D, + gcommaaccent: 0x0123, + gdot: 0x0121, + gdotaccent: 0x0121, + gecyrillic: 0x0433, + gehiragana: 0x3052, + gekatakana: 0x30B2, + geometricallyequal: 0x2251, + gereshaccenthebrew: 0x059C, + gereshhebrew: 0x05F3, + gereshmuqdamhebrew: 0x059D, + germandbls: 0x00DF, + gershayimaccenthebrew: 0x059E, + gershayimhebrew: 0x05F4, + getamark: 0x3013, + ghabengali: 0x0998, + ghadarmenian: 0x0572, + ghadeva: 0x0918, + ghagujarati: 0x0A98, + ghagurmukhi: 0x0A18, + ghainarabic: 0x063A, + ghainfinalarabic: 0xFECE, + ghaininitialarabic: 0xFECF, + ghainmedialarabic: 0xFED0, + ghemiddlehookcyrillic: 0x0495, + ghestrokecyrillic: 0x0493, + gheupturncyrillic: 0x0491, + ghhadeva: 0x095A, + ghhagurmukhi: 0x0A5A, + ghook: 0x0260, + ghzsquare: 0x3393, + gihiragana: 0x304E, + gikatakana: 0x30AE, + gimarmenian: 0x0563, + gimel: 0x05D2, + gimeldagesh: 0xFB32, + gimeldageshhebrew: 0xFB32, + gimelhebrew: 0x05D2, + gjecyrillic: 0x0453, + glottalinvertedstroke: 0x01BE, + glottalstop: 0x0294, + glottalstopinverted: 0x0296, + glottalstopmod: 0x02C0, + glottalstopreversed: 0x0295, + glottalstopreversedmod: 0x02C1, + glottalstopreversedsuperior: 0x02E4, + glottalstopstroke: 0x02A1, + glottalstopstrokereversed: 0x02A2, + gmacron: 0x1E21, + gmonospace: 0xFF47, + gohiragana: 0x3054, + gokatakana: 0x30B4, + gparen: 0x24A2, + gpasquare: 0x33AC, + gradient: 0x2207, + grave: 0x0060, + gravebelowcmb: 0x0316, + gravecmb: 0x0300, + gravecomb: 0x0300, + gravedeva: 0x0953, + gravelowmod: 0x02CE, + gravemonospace: 0xFF40, + gravetonecmb: 0x0340, + greater: 0x003E, + greaterequal: 0x2265, + greaterequalorless: 0x22DB, + greatermonospace: 0xFF1E, + greaterorequivalent: 0x2273, + greaterorless: 0x2277, + greateroverequal: 0x2267, + greatersmall: 0xFE65, + gscript: 0x0261, + gstroke: 0x01E5, + guhiragana: 0x3050, + guillemotleft: 0x00AB, + guillemotright: 0x00BB, + guilsinglleft: 0x2039, + guilsinglright: 0x203A, + gukatakana: 0x30B0, + guramusquare: 0x3318, + gysquare: 0x33C9, + h: 0x0068, + haabkhasiancyrillic: 0x04A9, + haaltonearabic: 0x06C1, + habengali: 0x09B9, + hadescendercyrillic: 0x04B3, + hadeva: 0x0939, + hagujarati: 0x0AB9, + hagurmukhi: 0x0A39, + haharabic: 0x062D, + hahfinalarabic: 0xFEA2, + hahinitialarabic: 0xFEA3, + hahiragana: 0x306F, + hahmedialarabic: 0xFEA4, + haitusquare: 0x332A, + hakatakana: 0x30CF, + hakatakanahalfwidth: 0xFF8A, + halantgurmukhi: 0x0A4D, + hamzaarabic: 0x0621, + hamzalowarabic: 0x0621, + hangulfiller: 0x3164, + hardsigncyrillic: 0x044A, + harpoonleftbarbup: 0x21BC, + harpoonrightbarbup: 0x21C0, + hasquare: 0x33CA, + hatafpatah: 0x05B2, + hatafpatah16: 0x05B2, + hatafpatah23: 0x05B2, + hatafpatah2f: 0x05B2, + hatafpatahhebrew: 0x05B2, + hatafpatahnarrowhebrew: 0x05B2, + hatafpatahquarterhebrew: 0x05B2, + hatafpatahwidehebrew: 0x05B2, + hatafqamats: 0x05B3, + hatafqamats1b: 0x05B3, + hatafqamats28: 0x05B3, + hatafqamats34: 0x05B3, + hatafqamatshebrew: 0x05B3, + hatafqamatsnarrowhebrew: 0x05B3, + hatafqamatsquarterhebrew: 0x05B3, + hatafqamatswidehebrew: 0x05B3, + hatafsegol: 0x05B1, + hatafsegol17: 0x05B1, + hatafsegol24: 0x05B1, + hatafsegol30: 0x05B1, + hatafsegolhebrew: 0x05B1, + hatafsegolnarrowhebrew: 0x05B1, + hatafsegolquarterhebrew: 0x05B1, + hatafsegolwidehebrew: 0x05B1, + hbar: 0x0127, + hbopomofo: 0x310F, + hbrevebelow: 0x1E2B, + hcedilla: 0x1E29, + hcircle: 0x24D7, + hcircumflex: 0x0125, + hdieresis: 0x1E27, + hdotaccent: 0x1E23, + hdotbelow: 0x1E25, + he: 0x05D4, + heart: 0x2665, + heartsuitblack: 0x2665, + heartsuitwhite: 0x2661, + hedagesh: 0xFB34, + hedageshhebrew: 0xFB34, + hehaltonearabic: 0x06C1, + heharabic: 0x0647, + hehebrew: 0x05D4, + hehfinalaltonearabic: 0xFBA7, + hehfinalalttwoarabic: 0xFEEA, + hehfinalarabic: 0xFEEA, + hehhamzaabovefinalarabic: 0xFBA5, + hehhamzaaboveisolatedarabic: 0xFBA4, + hehinitialaltonearabic: 0xFBA8, + hehinitialarabic: 0xFEEB, + hehiragana: 0x3078, + hehmedialaltonearabic: 0xFBA9, + hehmedialarabic: 0xFEEC, + heiseierasquare: 0x337B, + hekatakana: 0x30D8, + hekatakanahalfwidth: 0xFF8D, + hekutaarusquare: 0x3336, + henghook: 0x0267, + herutusquare: 0x3339, + het: 0x05D7, + hethebrew: 0x05D7, + hhook: 0x0266, + hhooksuperior: 0x02B1, + hieuhacirclekorean: 0x327B, + hieuhaparenkorean: 0x321B, + hieuhcirclekorean: 0x326D, + hieuhkorean: 0x314E, + hieuhparenkorean: 0x320D, + hihiragana: 0x3072, + hikatakana: 0x30D2, + hikatakanahalfwidth: 0xFF8B, + hiriq: 0x05B4, + hiriq14: 0x05B4, + hiriq21: 0x05B4, + hiriq2d: 0x05B4, + hiriqhebrew: 0x05B4, + hiriqnarrowhebrew: 0x05B4, + hiriqquarterhebrew: 0x05B4, + hiriqwidehebrew: 0x05B4, + hlinebelow: 0x1E96, + hmonospace: 0xFF48, + hoarmenian: 0x0570, + hohipthai: 0x0E2B, + hohiragana: 0x307B, + hokatakana: 0x30DB, + hokatakanahalfwidth: 0xFF8E, + holam: 0x05B9, + holam19: 0x05B9, + holam26: 0x05B9, + holam32: 0x05B9, + holamhebrew: 0x05B9, + holamnarrowhebrew: 0x05B9, + holamquarterhebrew: 0x05B9, + holamwidehebrew: 0x05B9, + honokhukthai: 0x0E2E, + hookabovecomb: 0x0309, + hookcmb: 0x0309, + hookpalatalizedbelowcmb: 0x0321, + hookretroflexbelowcmb: 0x0322, + hoonsquare: 0x3342, + horicoptic: 0x03E9, + horizontalbar: 0x2015, + horncmb: 0x031B, + hotsprings: 0x2668, + house: 0x2302, + hparen: 0x24A3, + hsuperior: 0x02B0, + hturned: 0x0265, + huhiragana: 0x3075, + huiitosquare: 0x3333, + hukatakana: 0x30D5, + hukatakanahalfwidth: 0xFF8C, + hungarumlaut: 0x02DD, + hungarumlautcmb: 0x030B, + hv: 0x0195, + hyphen: 0x002D, + hypheninferior: 0xF6E5, + hyphenmonospace: 0xFF0D, + hyphensmall: 0xFE63, + hyphensuperior: 0xF6E6, + hyphentwo: 0x2010, + i: 0x0069, + iacute: 0x00ED, + iacyrillic: 0x044F, + ibengali: 0x0987, + ibopomofo: 0x3127, + ibreve: 0x012D, + icaron: 0x01D0, + icircle: 0x24D8, + icircumflex: 0x00EE, + icyrillic: 0x0456, + idblgrave: 0x0209, + ideographearthcircle: 0x328F, + ideographfirecircle: 0x328B, + ideographicallianceparen: 0x323F, + ideographiccallparen: 0x323A, + ideographiccentrecircle: 0x32A5, + ideographicclose: 0x3006, + ideographiccomma: 0x3001, + ideographiccommaleft: 0xFF64, + ideographiccongratulationparen: 0x3237, + ideographiccorrectcircle: 0x32A3, + ideographicearthparen: 0x322F, + ideographicenterpriseparen: 0x323D, + ideographicexcellentcircle: 0x329D, + ideographicfestivalparen: 0x3240, + ideographicfinancialcircle: 0x3296, + ideographicfinancialparen: 0x3236, + ideographicfireparen: 0x322B, + ideographichaveparen: 0x3232, + ideographichighcircle: 0x32A4, + ideographiciterationmark: 0x3005, + ideographiclaborcircle: 0x3298, + ideographiclaborparen: 0x3238, + ideographicleftcircle: 0x32A7, + ideographiclowcircle: 0x32A6, + ideographicmedicinecircle: 0x32A9, + ideographicmetalparen: 0x322E, + ideographicmoonparen: 0x322A, + ideographicnameparen: 0x3234, + ideographicperiod: 0x3002, + ideographicprintcircle: 0x329E, + ideographicreachparen: 0x3243, + ideographicrepresentparen: 0x3239, + ideographicresourceparen: 0x323E, + ideographicrightcircle: 0x32A8, + ideographicsecretcircle: 0x3299, + ideographicselfparen: 0x3242, + ideographicsocietyparen: 0x3233, + ideographicspace: 0x3000, + ideographicspecialparen: 0x3235, + ideographicstockparen: 0x3231, + ideographicstudyparen: 0x323B, + ideographicsunparen: 0x3230, + ideographicsuperviseparen: 0x323C, + ideographicwaterparen: 0x322C, + ideographicwoodparen: 0x322D, + ideographiczero: 0x3007, + ideographmetalcircle: 0x328E, + ideographmooncircle: 0x328A, + ideographnamecircle: 0x3294, + ideographsuncircle: 0x3290, + ideographwatercircle: 0x328C, + ideographwoodcircle: 0x328D, + ideva: 0x0907, + idieresis: 0x00EF, + idieresisacute: 0x1E2F, + idieresiscyrillic: 0x04E5, + idotbelow: 0x1ECB, + iebrevecyrillic: 0x04D7, + iecyrillic: 0x0435, + ieungacirclekorean: 0x3275, + ieungaparenkorean: 0x3215, + ieungcirclekorean: 0x3267, + ieungkorean: 0x3147, + ieungparenkorean: 0x3207, + igrave: 0x00EC, + igujarati: 0x0A87, + igurmukhi: 0x0A07, + ihiragana: 0x3044, + ihookabove: 0x1EC9, + iibengali: 0x0988, + iicyrillic: 0x0438, + iideva: 0x0908, + iigujarati: 0x0A88, + iigurmukhi: 0x0A08, + iimatragurmukhi: 0x0A40, + iinvertedbreve: 0x020B, + iishortcyrillic: 0x0439, + iivowelsignbengali: 0x09C0, + iivowelsigndeva: 0x0940, + iivowelsigngujarati: 0x0AC0, + ij: 0x0133, + ikatakana: 0x30A4, + ikatakanahalfwidth: 0xFF72, + ikorean: 0x3163, + ilde: 0x02DC, + iluyhebrew: 0x05AC, + imacron: 0x012B, + imacroncyrillic: 0x04E3, + imageorapproximatelyequal: 0x2253, + imatragurmukhi: 0x0A3F, + imonospace: 0xFF49, + increment: 0x2206, + infinity: 0x221E, + iniarmenian: 0x056B, + integral: 0x222B, + integralbottom: 0x2321, + integralbt: 0x2321, + integralex: 0xF8F5, + integraltop: 0x2320, + integraltp: 0x2320, + intersection: 0x2229, + intisquare: 0x3305, + invbullet: 0x25D8, + invcircle: 0x25D9, + invsmileface: 0x263B, + iocyrillic: 0x0451, + iogonek: 0x012F, + iota: 0x03B9, + iotadieresis: 0x03CA, + iotadieresistonos: 0x0390, + iotalatin: 0x0269, + iotatonos: 0x03AF, + iparen: 0x24A4, + irigurmukhi: 0x0A72, + ismallhiragana: 0x3043, + ismallkatakana: 0x30A3, + ismallkatakanahalfwidth: 0xFF68, + issharbengali: 0x09FA, + istroke: 0x0268, + isuperior: 0xF6ED, + iterationhiragana: 0x309D, + iterationkatakana: 0x30FD, + itilde: 0x0129, + itildebelow: 0x1E2D, + iubopomofo: 0x3129, + iucyrillic: 0x044E, + ivowelsignbengali: 0x09BF, + ivowelsigndeva: 0x093F, + ivowelsigngujarati: 0x0ABF, + izhitsacyrillic: 0x0475, + izhitsadblgravecyrillic: 0x0477, + j: 0x006A, + jaarmenian: 0x0571, + jabengali: 0x099C, + jadeva: 0x091C, + jagujarati: 0x0A9C, + jagurmukhi: 0x0A1C, + jbopomofo: 0x3110, + jcaron: 0x01F0, + jcircle: 0x24D9, + jcircumflex: 0x0135, + jcrossedtail: 0x029D, + jdotlessstroke: 0x025F, + jecyrillic: 0x0458, + jeemarabic: 0x062C, + jeemfinalarabic: 0xFE9E, + jeeminitialarabic: 0xFE9F, + jeemmedialarabic: 0xFEA0, + jeharabic: 0x0698, + jehfinalarabic: 0xFB8B, + jhabengali: 0x099D, + jhadeva: 0x091D, + jhagujarati: 0x0A9D, + jhagurmukhi: 0x0A1D, + jheharmenian: 0x057B, + jis: 0x3004, + jmonospace: 0xFF4A, + jparen: 0x24A5, + jsuperior: 0x02B2, + k: 0x006B, + kabashkircyrillic: 0x04A1, + kabengali: 0x0995, + kacute: 0x1E31, + kacyrillic: 0x043A, + kadescendercyrillic: 0x049B, + kadeva: 0x0915, + kaf: 0x05DB, + kafarabic: 0x0643, + kafdagesh: 0xFB3B, + kafdageshhebrew: 0xFB3B, + kaffinalarabic: 0xFEDA, + kafhebrew: 0x05DB, + kafinitialarabic: 0xFEDB, + kafmedialarabic: 0xFEDC, + kafrafehebrew: 0xFB4D, + kagujarati: 0x0A95, + kagurmukhi: 0x0A15, + kahiragana: 0x304B, + kahookcyrillic: 0x04C4, + kakatakana: 0x30AB, + kakatakanahalfwidth: 0xFF76, + kappa: 0x03BA, + kappasymbolgreek: 0x03F0, + kapyeounmieumkorean: 0x3171, + kapyeounphieuphkorean: 0x3184, + kapyeounpieupkorean: 0x3178, + kapyeounssangpieupkorean: 0x3179, + karoriisquare: 0x330D, + kashidaautoarabic: 0x0640, + kashidaautonosidebearingarabic: 0x0640, + kasmallkatakana: 0x30F5, + kasquare: 0x3384, + kasraarabic: 0x0650, + kasratanarabic: 0x064D, + kastrokecyrillic: 0x049F, + katahiraprolongmarkhalfwidth: 0xFF70, + kaverticalstrokecyrillic: 0x049D, + kbopomofo: 0x310E, + kcalsquare: 0x3389, + kcaron: 0x01E9, + kcedilla: 0x0137, + kcircle: 0x24DA, + kcommaaccent: 0x0137, + kdotbelow: 0x1E33, + keharmenian: 0x0584, + kehiragana: 0x3051, + kekatakana: 0x30B1, + kekatakanahalfwidth: 0xFF79, + kenarmenian: 0x056F, + kesmallkatakana: 0x30F6, + kgreenlandic: 0x0138, + khabengali: 0x0996, + khacyrillic: 0x0445, + khadeva: 0x0916, + khagujarati: 0x0A96, + khagurmukhi: 0x0A16, + khaharabic: 0x062E, + khahfinalarabic: 0xFEA6, + khahinitialarabic: 0xFEA7, + khahmedialarabic: 0xFEA8, + kheicoptic: 0x03E7, + khhadeva: 0x0959, + khhagurmukhi: 0x0A59, + khieukhacirclekorean: 0x3278, + khieukhaparenkorean: 0x3218, + khieukhcirclekorean: 0x326A, + khieukhkorean: 0x314B, + khieukhparenkorean: 0x320A, + khokhaithai: 0x0E02, + khokhonthai: 0x0E05, + khokhuatthai: 0x0E03, + khokhwaithai: 0x0E04, + khomutthai: 0x0E5B, + khook: 0x0199, + khorakhangthai: 0x0E06, + khzsquare: 0x3391, + kihiragana: 0x304D, + kikatakana: 0x30AD, + kikatakanahalfwidth: 0xFF77, + kiroguramusquare: 0x3315, + kiromeetorusquare: 0x3316, + kirosquare: 0x3314, + kiyeokacirclekorean: 0x326E, + kiyeokaparenkorean: 0x320E, + kiyeokcirclekorean: 0x3260, + kiyeokkorean: 0x3131, + kiyeokparenkorean: 0x3200, + kiyeoksioskorean: 0x3133, + kjecyrillic: 0x045C, + klinebelow: 0x1E35, + klsquare: 0x3398, + kmcubedsquare: 0x33A6, + kmonospace: 0xFF4B, + kmsquaredsquare: 0x33A2, + kohiragana: 0x3053, + kohmsquare: 0x33C0, + kokaithai: 0x0E01, + kokatakana: 0x30B3, + kokatakanahalfwidth: 0xFF7A, + kooposquare: 0x331E, + koppacyrillic: 0x0481, + koreanstandardsymbol: 0x327F, + koroniscmb: 0x0343, + kparen: 0x24A6, + kpasquare: 0x33AA, + ksicyrillic: 0x046F, + ktsquare: 0x33CF, + kturned: 0x029E, + kuhiragana: 0x304F, + kukatakana: 0x30AF, + kukatakanahalfwidth: 0xFF78, + kvsquare: 0x33B8, + kwsquare: 0x33BE, + l: 0x006C, + labengali: 0x09B2, + lacute: 0x013A, + ladeva: 0x0932, + lagujarati: 0x0AB2, + lagurmukhi: 0x0A32, + lakkhangyaothai: 0x0E45, + lamaleffinalarabic: 0xFEFC, + lamalefhamzaabovefinalarabic: 0xFEF8, + lamalefhamzaaboveisolatedarabic: 0xFEF7, + lamalefhamzabelowfinalarabic: 0xFEFA, + lamalefhamzabelowisolatedarabic: 0xFEF9, + lamalefisolatedarabic: 0xFEFB, + lamalefmaddaabovefinalarabic: 0xFEF6, + lamalefmaddaaboveisolatedarabic: 0xFEF5, + lamarabic: 0x0644, + lambda: 0x03BB, + lambdastroke: 0x019B, + lamed: 0x05DC, + lameddagesh: 0xFB3C, + lameddageshhebrew: 0xFB3C, + lamedhebrew: 0x05DC, + lamfinalarabic: 0xFEDE, + lamhahinitialarabic: 0xFCCA, + laminitialarabic: 0xFEDF, + lamjeeminitialarabic: 0xFCC9, + lamkhahinitialarabic: 0xFCCB, + lamlamhehisolatedarabic: 0xFDF2, + lammedialarabic: 0xFEE0, + lammeemhahinitialarabic: 0xFD88, + lammeeminitialarabic: 0xFCCC, + largecircle: 0x25EF, + lbar: 0x019A, + lbelt: 0x026C, + lbopomofo: 0x310C, + lcaron: 0x013E, + lcedilla: 0x013C, + lcircle: 0x24DB, + lcircumflexbelow: 0x1E3D, + lcommaaccent: 0x013C, + ldot: 0x0140, + ldotaccent: 0x0140, + ldotbelow: 0x1E37, + ldotbelowmacron: 0x1E39, + leftangleabovecmb: 0x031A, + lefttackbelowcmb: 0x0318, + less: 0x003C, + lessequal: 0x2264, + lessequalorgreater: 0x22DA, + lessmonospace: 0xFF1C, + lessorequivalent: 0x2272, + lessorgreater: 0x2276, + lessoverequal: 0x2266, + lesssmall: 0xFE64, + lezh: 0x026E, + lfblock: 0x258C, + lhookretroflex: 0x026D, + lira: 0x20A4, + liwnarmenian: 0x056C, + lj: 0x01C9, + ljecyrillic: 0x0459, + ll: 0xF6C0, + lladeva: 0x0933, + llagujarati: 0x0AB3, + llinebelow: 0x1E3B, + llladeva: 0x0934, + llvocalicbengali: 0x09E1, + llvocalicdeva: 0x0961, + llvocalicvowelsignbengali: 0x09E3, + llvocalicvowelsigndeva: 0x0963, + lmiddletilde: 0x026B, + lmonospace: 0xFF4C, + lmsquare: 0x33D0, + lochulathai: 0x0E2C, + logicaland: 0x2227, + logicalnot: 0x00AC, + logicalnotreversed: 0x2310, + logicalor: 0x2228, + lolingthai: 0x0E25, + longs: 0x017F, + lowlinecenterline: 0xFE4E, + lowlinecmb: 0x0332, + lowlinedashed: 0xFE4D, + lozenge: 0x25CA, + lparen: 0x24A7, + lslash: 0x0142, + lsquare: 0x2113, + lsuperior: 0xF6EE, + ltshade: 0x2591, + luthai: 0x0E26, + lvocalicbengali: 0x098C, + lvocalicdeva: 0x090C, + lvocalicvowelsignbengali: 0x09E2, + lvocalicvowelsigndeva: 0x0962, + lxsquare: 0x33D3, + m: 0x006D, + mabengali: 0x09AE, + macron: 0x00AF, + macronbelowcmb: 0x0331, + macroncmb: 0x0304, + macronlowmod: 0x02CD, + macronmonospace: 0xFFE3, + macute: 0x1E3F, + madeva: 0x092E, + magujarati: 0x0AAE, + magurmukhi: 0x0A2E, + mahapakhhebrew: 0x05A4, + mahapakhlefthebrew: 0x05A4, + mahiragana: 0x307E, + maichattawalowleftthai: 0xF895, + maichattawalowrightthai: 0xF894, + maichattawathai: 0x0E4B, + maichattawaupperleftthai: 0xF893, + maieklowleftthai: 0xF88C, + maieklowrightthai: 0xF88B, + maiekthai: 0x0E48, + maiekupperleftthai: 0xF88A, + maihanakatleftthai: 0xF884, + maihanakatthai: 0x0E31, + maitaikhuleftthai: 0xF889, + maitaikhuthai: 0x0E47, + maitholowleftthai: 0xF88F, + maitholowrightthai: 0xF88E, + maithothai: 0x0E49, + maithoupperleftthai: 0xF88D, + maitrilowleftthai: 0xF892, + maitrilowrightthai: 0xF891, + maitrithai: 0x0E4A, + maitriupperleftthai: 0xF890, + maiyamokthai: 0x0E46, + makatakana: 0x30DE, + makatakanahalfwidth: 0xFF8F, + male: 0x2642, + mansyonsquare: 0x3347, + maqafhebrew: 0x05BE, + mars: 0x2642, + masoracirclehebrew: 0x05AF, + masquare: 0x3383, + mbopomofo: 0x3107, + mbsquare: 0x33D4, + mcircle: 0x24DC, + mcubedsquare: 0x33A5, + mdotaccent: 0x1E41, + mdotbelow: 0x1E43, + meemarabic: 0x0645, + meemfinalarabic: 0xFEE2, + meeminitialarabic: 0xFEE3, + meemmedialarabic: 0xFEE4, + meemmeeminitialarabic: 0xFCD1, + meemmeemisolatedarabic: 0xFC48, + meetorusquare: 0x334D, + mehiragana: 0x3081, + meizierasquare: 0x337E, + mekatakana: 0x30E1, + mekatakanahalfwidth: 0xFF92, + mem: 0x05DE, + memdagesh: 0xFB3E, + memdageshhebrew: 0xFB3E, + memhebrew: 0x05DE, + menarmenian: 0x0574, + merkhahebrew: 0x05A5, + merkhakefulahebrew: 0x05A6, + merkhakefulalefthebrew: 0x05A6, + merkhalefthebrew: 0x05A5, + mhook: 0x0271, + mhzsquare: 0x3392, + middledotkatakanahalfwidth: 0xFF65, + middot: 0x00B7, + mieumacirclekorean: 0x3272, + mieumaparenkorean: 0x3212, + mieumcirclekorean: 0x3264, + mieumkorean: 0x3141, + mieumpansioskorean: 0x3170, + mieumparenkorean: 0x3204, + mieumpieupkorean: 0x316E, + mieumsioskorean: 0x316F, + mihiragana: 0x307F, + mikatakana: 0x30DF, + mikatakanahalfwidth: 0xFF90, + minus: 0x2212, + minusbelowcmb: 0x0320, + minuscircle: 0x2296, + minusmod: 0x02D7, + minusplus: 0x2213, + minute: 0x2032, + miribaarusquare: 0x334A, + mirisquare: 0x3349, + mlonglegturned: 0x0270, + mlsquare: 0x3396, + mmcubedsquare: 0x33A3, + mmonospace: 0xFF4D, + mmsquaredsquare: 0x339F, + mohiragana: 0x3082, + mohmsquare: 0x33C1, + mokatakana: 0x30E2, + mokatakanahalfwidth: 0xFF93, + molsquare: 0x33D6, + momathai: 0x0E21, + moverssquare: 0x33A7, + moverssquaredsquare: 0x33A8, + mparen: 0x24A8, + mpasquare: 0x33AB, + mssquare: 0x33B3, + msuperior: 0xF6EF, + mturned: 0x026F, + mu: 0x00B5, + mu1: 0x00B5, + muasquare: 0x3382, + muchgreater: 0x226B, + muchless: 0x226A, + mufsquare: 0x338C, + mugreek: 0x03BC, + mugsquare: 0x338D, + muhiragana: 0x3080, + mukatakana: 0x30E0, + mukatakanahalfwidth: 0xFF91, + mulsquare: 0x3395, + multiply: 0x00D7, + mumsquare: 0x339B, + munahhebrew: 0x05A3, + munahlefthebrew: 0x05A3, + musicalnote: 0x266A, + musicalnotedbl: 0x266B, + musicflatsign: 0x266D, + musicsharpsign: 0x266F, + mussquare: 0x33B2, + muvsquare: 0x33B6, + muwsquare: 0x33BC, + mvmegasquare: 0x33B9, + mvsquare: 0x33B7, + mwmegasquare: 0x33BF, + mwsquare: 0x33BD, + n: 0x006E, + nabengali: 0x09A8, + nabla: 0x2207, + nacute: 0x0144, + nadeva: 0x0928, + nagujarati: 0x0AA8, + nagurmukhi: 0x0A28, + nahiragana: 0x306A, + nakatakana: 0x30CA, + nakatakanahalfwidth: 0xFF85, + napostrophe: 0x0149, + nasquare: 0x3381, + nbopomofo: 0x310B, + nbspace: 0x00A0, + ncaron: 0x0148, + ncedilla: 0x0146, + ncircle: 0x24DD, + ncircumflexbelow: 0x1E4B, + ncommaaccent: 0x0146, + ndotaccent: 0x1E45, + ndotbelow: 0x1E47, + nehiragana: 0x306D, + nekatakana: 0x30CD, + nekatakanahalfwidth: 0xFF88, + newsheqelsign: 0x20AA, + nfsquare: 0x338B, + ngabengali: 0x0999, + ngadeva: 0x0919, + ngagujarati: 0x0A99, + ngagurmukhi: 0x0A19, + ngonguthai: 0x0E07, + nhiragana: 0x3093, + nhookleft: 0x0272, + nhookretroflex: 0x0273, + nieunacirclekorean: 0x326F, + nieunaparenkorean: 0x320F, + nieuncieuckorean: 0x3135, + nieuncirclekorean: 0x3261, + nieunhieuhkorean: 0x3136, + nieunkorean: 0x3134, + nieunpansioskorean: 0x3168, + nieunparenkorean: 0x3201, + nieunsioskorean: 0x3167, + nieuntikeutkorean: 0x3166, + nihiragana: 0x306B, + nikatakana: 0x30CB, + nikatakanahalfwidth: 0xFF86, + nikhahitleftthai: 0xF899, + nikhahitthai: 0x0E4D, + nine: 0x0039, + ninearabic: 0x0669, + ninebengali: 0x09EF, + ninecircle: 0x2468, + ninecircleinversesansserif: 0x2792, + ninedeva: 0x096F, + ninegujarati: 0x0AEF, + ninegurmukhi: 0x0A6F, + ninehackarabic: 0x0669, + ninehangzhou: 0x3029, + nineideographicparen: 0x3228, + nineinferior: 0x2089, + ninemonospace: 0xFF19, + nineoldstyle: 0xF739, + nineparen: 0x247C, + nineperiod: 0x2490, + ninepersian: 0x06F9, + nineroman: 0x2178, + ninesuperior: 0x2079, + nineteencircle: 0x2472, + nineteenparen: 0x2486, + nineteenperiod: 0x249A, + ninethai: 0x0E59, + nj: 0x01CC, + njecyrillic: 0x045A, + nkatakana: 0x30F3, + nkatakanahalfwidth: 0xFF9D, + nlegrightlong: 0x019E, + nlinebelow: 0x1E49, + nmonospace: 0xFF4E, + nmsquare: 0x339A, + nnabengali: 0x09A3, + nnadeva: 0x0923, + nnagujarati: 0x0AA3, + nnagurmukhi: 0x0A23, + nnnadeva: 0x0929, + nohiragana: 0x306E, + nokatakana: 0x30CE, + nokatakanahalfwidth: 0xFF89, + nonbreakingspace: 0x00A0, + nonenthai: 0x0E13, + nonuthai: 0x0E19, + noonarabic: 0x0646, + noonfinalarabic: 0xFEE6, + noonghunnaarabic: 0x06BA, + noonghunnafinalarabic: 0xFB9F, + nooninitialarabic: 0xFEE7, + noonjeeminitialarabic: 0xFCD2, + noonjeemisolatedarabic: 0xFC4B, + noonmedialarabic: 0xFEE8, + noonmeeminitialarabic: 0xFCD5, + noonmeemisolatedarabic: 0xFC4E, + noonnoonfinalarabic: 0xFC8D, + notcontains: 0x220C, + notelement: 0x2209, + notelementof: 0x2209, + notequal: 0x2260, + notgreater: 0x226F, + notgreaternorequal: 0x2271, + notgreaternorless: 0x2279, + notidentical: 0x2262, + notless: 0x226E, + notlessnorequal: 0x2270, + notparallel: 0x2226, + notprecedes: 0x2280, + notsubset: 0x2284, + notsucceeds: 0x2281, + notsuperset: 0x2285, + nowarmenian: 0x0576, + nparen: 0x24A9, + nssquare: 0x33B1, + nsuperior: 0x207F, + ntilde: 0x00F1, + nu: 0x03BD, + nuhiragana: 0x306C, + nukatakana: 0x30CC, + nukatakanahalfwidth: 0xFF87, + nuktabengali: 0x09BC, + nuktadeva: 0x093C, + nuktagujarati: 0x0ABC, + nuktagurmukhi: 0x0A3C, + numbersign: 0x0023, + numbersignmonospace: 0xFF03, + numbersignsmall: 0xFE5F, + numeralsigngreek: 0x0374, + numeralsignlowergreek: 0x0375, + numero: 0x2116, + nun: 0x05E0, + nundagesh: 0xFB40, + nundageshhebrew: 0xFB40, + nunhebrew: 0x05E0, + nvsquare: 0x33B5, + nwsquare: 0x33BB, + nyabengali: 0x099E, + nyadeva: 0x091E, + nyagujarati: 0x0A9E, + nyagurmukhi: 0x0A1E, + o: 0x006F, + oacute: 0x00F3, + oangthai: 0x0E2D, + obarred: 0x0275, + obarredcyrillic: 0x04E9, + obarreddieresiscyrillic: 0x04EB, + obengali: 0x0993, + obopomofo: 0x311B, + obreve: 0x014F, + ocandradeva: 0x0911, + ocandragujarati: 0x0A91, + ocandravowelsigndeva: 0x0949, + ocandravowelsigngujarati: 0x0AC9, + ocaron: 0x01D2, + ocircle: 0x24DE, + ocircumflex: 0x00F4, + ocircumflexacute: 0x1ED1, + ocircumflexdotbelow: 0x1ED9, + ocircumflexgrave: 0x1ED3, + ocircumflexhookabove: 0x1ED5, + ocircumflextilde: 0x1ED7, + ocyrillic: 0x043E, + odblacute: 0x0151, + odblgrave: 0x020D, + odeva: 0x0913, + odieresis: 0x00F6, + odieresiscyrillic: 0x04E7, + odotbelow: 0x1ECD, + oe: 0x0153, + oekorean: 0x315A, + ogonek: 0x02DB, + ogonekcmb: 0x0328, + ograve: 0x00F2, + ogujarati: 0x0A93, + oharmenian: 0x0585, + ohiragana: 0x304A, + ohookabove: 0x1ECF, + ohorn: 0x01A1, + ohornacute: 0x1EDB, + ohorndotbelow: 0x1EE3, + ohorngrave: 0x1EDD, + ohornhookabove: 0x1EDF, + ohorntilde: 0x1EE1, + ohungarumlaut: 0x0151, + oi: 0x01A3, + oinvertedbreve: 0x020F, + okatakana: 0x30AA, + okatakanahalfwidth: 0xFF75, + okorean: 0x3157, + olehebrew: 0x05AB, + omacron: 0x014D, + omacronacute: 0x1E53, + omacrongrave: 0x1E51, + omdeva: 0x0950, + omega: 0x03C9, + omega1: 0x03D6, + omegacyrillic: 0x0461, + omegalatinclosed: 0x0277, + omegaroundcyrillic: 0x047B, + omegatitlocyrillic: 0x047D, + omegatonos: 0x03CE, + omgujarati: 0x0AD0, + omicron: 0x03BF, + omicrontonos: 0x03CC, + omonospace: 0xFF4F, + one: 0x0031, + onearabic: 0x0661, + onebengali: 0x09E7, + onecircle: 0x2460, + onecircleinversesansserif: 0x278A, + onedeva: 0x0967, + onedotenleader: 0x2024, + oneeighth: 0x215B, + onefitted: 0xF6DC, + onegujarati: 0x0AE7, + onegurmukhi: 0x0A67, + onehackarabic: 0x0661, + onehalf: 0x00BD, + onehangzhou: 0x3021, + oneideographicparen: 0x3220, + oneinferior: 0x2081, + onemonospace: 0xFF11, + onenumeratorbengali: 0x09F4, + oneoldstyle: 0xF731, + oneparen: 0x2474, + oneperiod: 0x2488, + onepersian: 0x06F1, + onequarter: 0x00BC, + oneroman: 0x2170, + onesuperior: 0x00B9, + onethai: 0x0E51, + onethird: 0x2153, + oogonek: 0x01EB, + oogonekmacron: 0x01ED, + oogurmukhi: 0x0A13, + oomatragurmukhi: 0x0A4B, + oopen: 0x0254, + oparen: 0x24AA, + openbullet: 0x25E6, + option: 0x2325, + ordfeminine: 0x00AA, + ordmasculine: 0x00BA, + orthogonal: 0x221F, + oshortdeva: 0x0912, + oshortvowelsigndeva: 0x094A, + oslash: 0x00F8, + oslashacute: 0x01FF, + osmallhiragana: 0x3049, + osmallkatakana: 0x30A9, + osmallkatakanahalfwidth: 0xFF6B, + ostrokeacute: 0x01FF, + osuperior: 0xF6F0, + otcyrillic: 0x047F, + otilde: 0x00F5, + otildeacute: 0x1E4D, + otildedieresis: 0x1E4F, + oubopomofo: 0x3121, + overline: 0x203E, + overlinecenterline: 0xFE4A, + overlinecmb: 0x0305, + overlinedashed: 0xFE49, + overlinedblwavy: 0xFE4C, + overlinewavy: 0xFE4B, + overscore: 0x00AF, + ovowelsignbengali: 0x09CB, + ovowelsigndeva: 0x094B, + ovowelsigngujarati: 0x0ACB, + p: 0x0070, + paampssquare: 0x3380, + paasentosquare: 0x332B, + pabengali: 0x09AA, + pacute: 0x1E55, + padeva: 0x092A, + pagedown: 0x21DF, + pageup: 0x21DE, + pagujarati: 0x0AAA, + pagurmukhi: 0x0A2A, + pahiragana: 0x3071, + paiyannoithai: 0x0E2F, + pakatakana: 0x30D1, + palatalizationcyrilliccmb: 0x0484, + palochkacyrillic: 0x04C0, + pansioskorean: 0x317F, + paragraph: 0x00B6, + parallel: 0x2225, + parenleft: 0x0028, + parenleftaltonearabic: 0xFD3E, + parenleftbt: 0xF8ED, + parenleftex: 0xF8EC, + parenleftinferior: 0x208D, + parenleftmonospace: 0xFF08, + parenleftsmall: 0xFE59, + parenleftsuperior: 0x207D, + parenlefttp: 0xF8EB, + parenleftvertical: 0xFE35, + parenright: 0x0029, + parenrightaltonearabic: 0xFD3F, + parenrightbt: 0xF8F8, + parenrightex: 0xF8F7, + parenrightinferior: 0x208E, + parenrightmonospace: 0xFF09, + parenrightsmall: 0xFE5A, + parenrightsuperior: 0x207E, + parenrighttp: 0xF8F6, + parenrightvertical: 0xFE36, + partialdiff: 0x2202, + paseqhebrew: 0x05C0, + pashtahebrew: 0x0599, + pasquare: 0x33A9, + patah: 0x05B7, + patah11: 0x05B7, + patah1d: 0x05B7, + patah2a: 0x05B7, + patahhebrew: 0x05B7, + patahnarrowhebrew: 0x05B7, + patahquarterhebrew: 0x05B7, + patahwidehebrew: 0x05B7, + pazerhebrew: 0x05A1, + pbopomofo: 0x3106, + pcircle: 0x24DF, + pdotaccent: 0x1E57, + pe: 0x05E4, + pecyrillic: 0x043F, + pedagesh: 0xFB44, + pedageshhebrew: 0xFB44, + peezisquare: 0x333B, + pefinaldageshhebrew: 0xFB43, + peharabic: 0x067E, + peharmenian: 0x057A, + pehebrew: 0x05E4, + pehfinalarabic: 0xFB57, + pehinitialarabic: 0xFB58, + pehiragana: 0x307A, + pehmedialarabic: 0xFB59, + pekatakana: 0x30DA, + pemiddlehookcyrillic: 0x04A7, + perafehebrew: 0xFB4E, + percent: 0x0025, + percentarabic: 0x066A, + percentmonospace: 0xFF05, + percentsmall: 0xFE6A, + period: 0x002E, + periodarmenian: 0x0589, + periodcentered: 0x00B7, + periodhalfwidth: 0xFF61, + periodinferior: 0xF6E7, + periodmonospace: 0xFF0E, + periodsmall: 0xFE52, + periodsuperior: 0xF6E8, + perispomenigreekcmb: 0x0342, + perpendicular: 0x22A5, + perthousand: 0x2030, + peseta: 0x20A7, + pfsquare: 0x338A, + phabengali: 0x09AB, + phadeva: 0x092B, + phagujarati: 0x0AAB, + phagurmukhi: 0x0A2B, + phi: 0x03C6, + phi1: 0x03D5, + phieuphacirclekorean: 0x327A, + phieuphaparenkorean: 0x321A, + phieuphcirclekorean: 0x326C, + phieuphkorean: 0x314D, + phieuphparenkorean: 0x320C, + philatin: 0x0278, + phinthuthai: 0x0E3A, + phisymbolgreek: 0x03D5, + phook: 0x01A5, + phophanthai: 0x0E1E, + phophungthai: 0x0E1C, + phosamphaothai: 0x0E20, + pi: 0x03C0, + pieupacirclekorean: 0x3273, + pieupaparenkorean: 0x3213, + pieupcieuckorean: 0x3176, + pieupcirclekorean: 0x3265, + pieupkiyeokkorean: 0x3172, + pieupkorean: 0x3142, + pieupparenkorean: 0x3205, + pieupsioskiyeokkorean: 0x3174, + pieupsioskorean: 0x3144, + pieupsiostikeutkorean: 0x3175, + pieupthieuthkorean: 0x3177, + pieuptikeutkorean: 0x3173, + pihiragana: 0x3074, + pikatakana: 0x30D4, + pisymbolgreek: 0x03D6, + piwrarmenian: 0x0583, + plus: 0x002B, + plusbelowcmb: 0x031F, + pluscircle: 0x2295, + plusminus: 0x00B1, + plusmod: 0x02D6, + plusmonospace: 0xFF0B, + plussmall: 0xFE62, + plussuperior: 0x207A, + pmonospace: 0xFF50, + pmsquare: 0x33D8, + pohiragana: 0x307D, + pointingindexdownwhite: 0x261F, + pointingindexleftwhite: 0x261C, + pointingindexrightwhite: 0x261E, + pointingindexupwhite: 0x261D, + pokatakana: 0x30DD, + poplathai: 0x0E1B, + postalmark: 0x3012, + postalmarkface: 0x3020, + pparen: 0x24AB, + precedes: 0x227A, + prescription: 0x211E, + primemod: 0x02B9, + primereversed: 0x2035, + product: 0x220F, + projective: 0x2305, + prolongedkana: 0x30FC, + propellor: 0x2318, + propersubset: 0x2282, + propersuperset: 0x2283, + proportion: 0x2237, + proportional: 0x221D, + psi: 0x03C8, + psicyrillic: 0x0471, + psilipneumatacyrilliccmb: 0x0486, + pssquare: 0x33B0, + puhiragana: 0x3077, + pukatakana: 0x30D7, + pvsquare: 0x33B4, + pwsquare: 0x33BA, + q: 0x0071, + qadeva: 0x0958, + qadmahebrew: 0x05A8, + qafarabic: 0x0642, + qaffinalarabic: 0xFED6, + qafinitialarabic: 0xFED7, + qafmedialarabic: 0xFED8, + qamats: 0x05B8, + qamats10: 0x05B8, + qamats1a: 0x05B8, + qamats1c: 0x05B8, + qamats27: 0x05B8, + qamats29: 0x05B8, + qamats33: 0x05B8, + qamatsde: 0x05B8, + qamatshebrew: 0x05B8, + qamatsnarrowhebrew: 0x05B8, + qamatsqatanhebrew: 0x05B8, + qamatsqatannarrowhebrew: 0x05B8, + qamatsqatanquarterhebrew: 0x05B8, + qamatsqatanwidehebrew: 0x05B8, + qamatsquarterhebrew: 0x05B8, + qamatswidehebrew: 0x05B8, + qarneyparahebrew: 0x059F, + qbopomofo: 0x3111, + qcircle: 0x24E0, + qhook: 0x02A0, + qmonospace: 0xFF51, + qof: 0x05E7, + qofdagesh: 0xFB47, + qofdageshhebrew: 0xFB47, + qofhebrew: 0x05E7, + qparen: 0x24AC, + quarternote: 0x2669, + qubuts: 0x05BB, + qubuts18: 0x05BB, + qubuts25: 0x05BB, + qubuts31: 0x05BB, + qubutshebrew: 0x05BB, + qubutsnarrowhebrew: 0x05BB, + qubutsquarterhebrew: 0x05BB, + qubutswidehebrew: 0x05BB, + question: 0x003F, + questionarabic: 0x061F, + questionarmenian: 0x055E, + questiondown: 0x00BF, + questiondownsmall: 0xF7BF, + questiongreek: 0x037E, + questionmonospace: 0xFF1F, + questionsmall: 0xF73F, + quotedbl: 0x0022, + quotedblbase: 0x201E, + quotedblleft: 0x201C, + quotedblmonospace: 0xFF02, + quotedblprime: 0x301E, + quotedblprimereversed: 0x301D, + quotedblright: 0x201D, + quoteleft: 0x2018, + quoteleftreversed: 0x201B, + quotereversed: 0x201B, + quoteright: 0x2019, + quoterightn: 0x0149, + quotesinglbase: 0x201A, + quotesingle: 0x0027, + quotesinglemonospace: 0xFF07, + r: 0x0072, + raarmenian: 0x057C, + rabengali: 0x09B0, + racute: 0x0155, + radeva: 0x0930, + radical: 0x221A, + radicalex: 0xF8E5, + radoverssquare: 0x33AE, + radoverssquaredsquare: 0x33AF, + radsquare: 0x33AD, + rafe: 0x05BF, + rafehebrew: 0x05BF, + ragujarati: 0x0AB0, + ragurmukhi: 0x0A30, + rahiragana: 0x3089, + rakatakana: 0x30E9, + rakatakanahalfwidth: 0xFF97, + ralowerdiagonalbengali: 0x09F1, + ramiddlediagonalbengali: 0x09F0, + ramshorn: 0x0264, + ratio: 0x2236, + rbopomofo: 0x3116, + rcaron: 0x0159, + rcedilla: 0x0157, + rcircle: 0x24E1, + rcommaaccent: 0x0157, + rdblgrave: 0x0211, + rdotaccent: 0x1E59, + rdotbelow: 0x1E5B, + rdotbelowmacron: 0x1E5D, + referencemark: 0x203B, + reflexsubset: 0x2286, + reflexsuperset: 0x2287, + registered: 0x00AE, + registersans: 0xF8E8, + registerserif: 0xF6DA, + reharabic: 0x0631, + reharmenian: 0x0580, + rehfinalarabic: 0xFEAE, + rehiragana: 0x308C, + rekatakana: 0x30EC, + rekatakanahalfwidth: 0xFF9A, + resh: 0x05E8, + reshdageshhebrew: 0xFB48, + reshhebrew: 0x05E8, + reversedtilde: 0x223D, + reviahebrew: 0x0597, + reviamugrashhebrew: 0x0597, + revlogicalnot: 0x2310, + rfishhook: 0x027E, + rfishhookreversed: 0x027F, + rhabengali: 0x09DD, + rhadeva: 0x095D, + rho: 0x03C1, + rhook: 0x027D, + rhookturned: 0x027B, + rhookturnedsuperior: 0x02B5, + rhosymbolgreek: 0x03F1, + rhotichookmod: 0x02DE, + rieulacirclekorean: 0x3271, + rieulaparenkorean: 0x3211, + rieulcirclekorean: 0x3263, + rieulhieuhkorean: 0x3140, + rieulkiyeokkorean: 0x313A, + rieulkiyeoksioskorean: 0x3169, + rieulkorean: 0x3139, + rieulmieumkorean: 0x313B, + rieulpansioskorean: 0x316C, + rieulparenkorean: 0x3203, + rieulphieuphkorean: 0x313F, + rieulpieupkorean: 0x313C, + rieulpieupsioskorean: 0x316B, + rieulsioskorean: 0x313D, + rieulthieuthkorean: 0x313E, + rieultikeutkorean: 0x316A, + rieulyeorinhieuhkorean: 0x316D, + rightangle: 0x221F, + righttackbelowcmb: 0x0319, + righttriangle: 0x22BF, + rihiragana: 0x308A, + rikatakana: 0x30EA, + rikatakanahalfwidth: 0xFF98, + ring: 0x02DA, + ringbelowcmb: 0x0325, + ringcmb: 0x030A, + ringhalfleft: 0x02BF, + ringhalfleftarmenian: 0x0559, + ringhalfleftbelowcmb: 0x031C, + ringhalfleftcentered: 0x02D3, + ringhalfright: 0x02BE, + ringhalfrightbelowcmb: 0x0339, + ringhalfrightcentered: 0x02D2, + rinvertedbreve: 0x0213, + rittorusquare: 0x3351, + rlinebelow: 0x1E5F, + rlongleg: 0x027C, + rlonglegturned: 0x027A, + rmonospace: 0xFF52, + rohiragana: 0x308D, + rokatakana: 0x30ED, + rokatakanahalfwidth: 0xFF9B, + roruathai: 0x0E23, + rparen: 0x24AD, + rrabengali: 0x09DC, + rradeva: 0x0931, + rragurmukhi: 0x0A5C, + rreharabic: 0x0691, + rrehfinalarabic: 0xFB8D, + rrvocalicbengali: 0x09E0, + rrvocalicdeva: 0x0960, + rrvocalicgujarati: 0x0AE0, + rrvocalicvowelsignbengali: 0x09C4, + rrvocalicvowelsigndeva: 0x0944, + rrvocalicvowelsigngujarati: 0x0AC4, + rsuperior: 0xF6F1, + rtblock: 0x2590, + rturned: 0x0279, + rturnedsuperior: 0x02B4, + ruhiragana: 0x308B, + rukatakana: 0x30EB, + rukatakanahalfwidth: 0xFF99, + rupeemarkbengali: 0x09F2, + rupeesignbengali: 0x09F3, + rupiah: 0xF6DD, + ruthai: 0x0E24, + rvocalicbengali: 0x098B, + rvocalicdeva: 0x090B, + rvocalicgujarati: 0x0A8B, + rvocalicvowelsignbengali: 0x09C3, + rvocalicvowelsigndeva: 0x0943, + rvocalicvowelsigngujarati: 0x0AC3, + s: 0x0073, + sabengali: 0x09B8, + sacute: 0x015B, + sacutedotaccent: 0x1E65, + sadarabic: 0x0635, + sadeva: 0x0938, + sadfinalarabic: 0xFEBA, + sadinitialarabic: 0xFEBB, + sadmedialarabic: 0xFEBC, + sagujarati: 0x0AB8, + sagurmukhi: 0x0A38, + sahiragana: 0x3055, + sakatakana: 0x30B5, + sakatakanahalfwidth: 0xFF7B, + sallallahoualayhewasallamarabic: 0xFDFA, + samekh: 0x05E1, + samekhdagesh: 0xFB41, + samekhdageshhebrew: 0xFB41, + samekhhebrew: 0x05E1, + saraaathai: 0x0E32, + saraaethai: 0x0E41, + saraaimaimalaithai: 0x0E44, + saraaimaimuanthai: 0x0E43, + saraamthai: 0x0E33, + saraathai: 0x0E30, + saraethai: 0x0E40, + saraiileftthai: 0xF886, + saraiithai: 0x0E35, + saraileftthai: 0xF885, + saraithai: 0x0E34, + saraothai: 0x0E42, + saraueeleftthai: 0xF888, + saraueethai: 0x0E37, + saraueleftthai: 0xF887, + sarauethai: 0x0E36, + sarauthai: 0x0E38, + sarauuthai: 0x0E39, + sbopomofo: 0x3119, + scaron: 0x0161, + scarondotaccent: 0x1E67, + scedilla: 0x015F, + schwa: 0x0259, + schwacyrillic: 0x04D9, + schwadieresiscyrillic: 0x04DB, + schwahook: 0x025A, + scircle: 0x24E2, + scircumflex: 0x015D, + scommaaccent: 0x0219, + sdotaccent: 0x1E61, + sdotbelow: 0x1E63, + sdotbelowdotaccent: 0x1E69, + seagullbelowcmb: 0x033C, + second: 0x2033, + secondtonechinese: 0x02CA, + section: 0x00A7, + seenarabic: 0x0633, + seenfinalarabic: 0xFEB2, + seeninitialarabic: 0xFEB3, + seenmedialarabic: 0xFEB4, + segol: 0x05B6, + segol13: 0x05B6, + segol1f: 0x05B6, + segol2c: 0x05B6, + segolhebrew: 0x05B6, + segolnarrowhebrew: 0x05B6, + segolquarterhebrew: 0x05B6, + segoltahebrew: 0x0592, + segolwidehebrew: 0x05B6, + seharmenian: 0x057D, + sehiragana: 0x305B, + sekatakana: 0x30BB, + sekatakanahalfwidth: 0xFF7E, + semicolon: 0x003B, + semicolonarabic: 0x061B, + semicolonmonospace: 0xFF1B, + semicolonsmall: 0xFE54, + semivoicedmarkkana: 0x309C, + semivoicedmarkkanahalfwidth: 0xFF9F, + sentisquare: 0x3322, + sentosquare: 0x3323, + seven: 0x0037, + sevenarabic: 0x0667, + sevenbengali: 0x09ED, + sevencircle: 0x2466, + sevencircleinversesansserif: 0x2790, + sevendeva: 0x096D, + seveneighths: 0x215E, + sevengujarati: 0x0AED, + sevengurmukhi: 0x0A6D, + sevenhackarabic: 0x0667, + sevenhangzhou: 0x3027, + sevenideographicparen: 0x3226, + seveninferior: 0x2087, + sevenmonospace: 0xFF17, + sevenoldstyle: 0xF737, + sevenparen: 0x247A, + sevenperiod: 0x248E, + sevenpersian: 0x06F7, + sevenroman: 0x2176, + sevensuperior: 0x2077, + seventeencircle: 0x2470, + seventeenparen: 0x2484, + seventeenperiod: 0x2498, + seventhai: 0x0E57, + sfthyphen: 0x00AD, + shaarmenian: 0x0577, + shabengali: 0x09B6, + shacyrillic: 0x0448, + shaddaarabic: 0x0651, + shaddadammaarabic: 0xFC61, + shaddadammatanarabic: 0xFC5E, + shaddafathaarabic: 0xFC60, + shaddakasraarabic: 0xFC62, + shaddakasratanarabic: 0xFC5F, + shade: 0x2592, + shadedark: 0x2593, + shadelight: 0x2591, + shademedium: 0x2592, + shadeva: 0x0936, + shagujarati: 0x0AB6, + shagurmukhi: 0x0A36, + shalshelethebrew: 0x0593, + shbopomofo: 0x3115, + shchacyrillic: 0x0449, + sheenarabic: 0x0634, + sheenfinalarabic: 0xFEB6, + sheeninitialarabic: 0xFEB7, + sheenmedialarabic: 0xFEB8, + sheicoptic: 0x03E3, + sheqel: 0x20AA, + sheqelhebrew: 0x20AA, + sheva: 0x05B0, + sheva115: 0x05B0, + sheva15: 0x05B0, + sheva22: 0x05B0, + sheva2e: 0x05B0, + shevahebrew: 0x05B0, + shevanarrowhebrew: 0x05B0, + shevaquarterhebrew: 0x05B0, + shevawidehebrew: 0x05B0, + shhacyrillic: 0x04BB, + shimacoptic: 0x03ED, + shin: 0x05E9, + shindagesh: 0xFB49, + shindageshhebrew: 0xFB49, + shindageshshindot: 0xFB2C, + shindageshshindothebrew: 0xFB2C, + shindageshsindot: 0xFB2D, + shindageshsindothebrew: 0xFB2D, + shindothebrew: 0x05C1, + shinhebrew: 0x05E9, + shinshindot: 0xFB2A, + shinshindothebrew: 0xFB2A, + shinsindot: 0xFB2B, + shinsindothebrew: 0xFB2B, + shook: 0x0282, + sigma: 0x03C3, + sigma1: 0x03C2, + sigmafinal: 0x03C2, + sigmalunatesymbolgreek: 0x03F2, + sihiragana: 0x3057, + sikatakana: 0x30B7, + sikatakanahalfwidth: 0xFF7C, + siluqhebrew: 0x05BD, + siluqlefthebrew: 0x05BD, + similar: 0x223C, + sindothebrew: 0x05C2, + siosacirclekorean: 0x3274, + siosaparenkorean: 0x3214, + sioscieuckorean: 0x317E, + sioscirclekorean: 0x3266, + sioskiyeokkorean: 0x317A, + sioskorean: 0x3145, + siosnieunkorean: 0x317B, + siosparenkorean: 0x3206, + siospieupkorean: 0x317D, + siostikeutkorean: 0x317C, + six: 0x0036, + sixarabic: 0x0666, + sixbengali: 0x09EC, + sixcircle: 0x2465, + sixcircleinversesansserif: 0x278F, + sixdeva: 0x096C, + sixgujarati: 0x0AEC, + sixgurmukhi: 0x0A6C, + sixhackarabic: 0x0666, + sixhangzhou: 0x3026, + sixideographicparen: 0x3225, + sixinferior: 0x2086, + sixmonospace: 0xFF16, + sixoldstyle: 0xF736, + sixparen: 0x2479, + sixperiod: 0x248D, + sixpersian: 0x06F6, + sixroman: 0x2175, + sixsuperior: 0x2076, + sixteencircle: 0x246F, + sixteencurrencydenominatorbengali: 0x09F9, + sixteenparen: 0x2483, + sixteenperiod: 0x2497, + sixthai: 0x0E56, + slash: 0x002F, + slashmonospace: 0xFF0F, + slong: 0x017F, + slongdotaccent: 0x1E9B, + smileface: 0x263A, + smonospace: 0xFF53, + sofpasuqhebrew: 0x05C3, + softhyphen: 0x00AD, + softsigncyrillic: 0x044C, + sohiragana: 0x305D, + sokatakana: 0x30BD, + sokatakanahalfwidth: 0xFF7F, + soliduslongoverlaycmb: 0x0338, + solidusshortoverlaycmb: 0x0337, + sorusithai: 0x0E29, + sosalathai: 0x0E28, + sosothai: 0x0E0B, + sosuathai: 0x0E2A, + space: 0x0020, + spacehackarabic: 0x0020, + spade: 0x2660, + spadesuitblack: 0x2660, + spadesuitwhite: 0x2664, + sparen: 0x24AE, + squarebelowcmb: 0x033B, + squarecc: 0x33C4, + squarecm: 0x339D, + squarediagonalcrosshatchfill: 0x25A9, + squarehorizontalfill: 0x25A4, + squarekg: 0x338F, + squarekm: 0x339E, + squarekmcapital: 0x33CE, + squareln: 0x33D1, + squarelog: 0x33D2, + squaremg: 0x338E, + squaremil: 0x33D5, + squaremm: 0x339C, + squaremsquared: 0x33A1, + squareorthogonalcrosshatchfill: 0x25A6, + squareupperlefttolowerrightfill: 0x25A7, + squareupperrighttolowerleftfill: 0x25A8, + squareverticalfill: 0x25A5, + squarewhitewithsmallblack: 0x25A3, + srsquare: 0x33DB, + ssabengali: 0x09B7, + ssadeva: 0x0937, + ssagujarati: 0x0AB7, + ssangcieuckorean: 0x3149, + ssanghieuhkorean: 0x3185, + ssangieungkorean: 0x3180, + ssangkiyeokkorean: 0x3132, + ssangnieunkorean: 0x3165, + ssangpieupkorean: 0x3143, + ssangsioskorean: 0x3146, + ssangtikeutkorean: 0x3138, + ssuperior: 0xF6F2, + sterling: 0x00A3, + sterlingmonospace: 0xFFE1, + strokelongoverlaycmb: 0x0336, + strokeshortoverlaycmb: 0x0335, + subset: 0x2282, + subsetnotequal: 0x228A, + subsetorequal: 0x2286, + succeeds: 0x227B, + suchthat: 0x220B, + suhiragana: 0x3059, + sukatakana: 0x30B9, + sukatakanahalfwidth: 0xFF7D, + sukunarabic: 0x0652, + summation: 0x2211, + sun: 0x263C, + superset: 0x2283, + supersetnotequal: 0x228B, + supersetorequal: 0x2287, + svsquare: 0x33DC, + syouwaerasquare: 0x337C, + t: 0x0074, + tabengali: 0x09A4, + tackdown: 0x22A4, + tackleft: 0x22A3, + tadeva: 0x0924, + tagujarati: 0x0AA4, + tagurmukhi: 0x0A24, + taharabic: 0x0637, + tahfinalarabic: 0xFEC2, + tahinitialarabic: 0xFEC3, + tahiragana: 0x305F, + tahmedialarabic: 0xFEC4, + taisyouerasquare: 0x337D, + takatakana: 0x30BF, + takatakanahalfwidth: 0xFF80, + tatweelarabic: 0x0640, + tau: 0x03C4, + tav: 0x05EA, + tavdages: 0xFB4A, + tavdagesh: 0xFB4A, + tavdageshhebrew: 0xFB4A, + tavhebrew: 0x05EA, + tbar: 0x0167, + tbopomofo: 0x310A, + tcaron: 0x0165, + tccurl: 0x02A8, + tcedilla: 0x0163, + tcheharabic: 0x0686, + tchehfinalarabic: 0xFB7B, + tchehinitialarabic: 0xFB7C, + tchehmedialarabic: 0xFB7D, + tcircle: 0x24E3, + tcircumflexbelow: 0x1E71, + tcommaaccent: 0x0163, + tdieresis: 0x1E97, + tdotaccent: 0x1E6B, + tdotbelow: 0x1E6D, + tecyrillic: 0x0442, + tedescendercyrillic: 0x04AD, + teharabic: 0x062A, + tehfinalarabic: 0xFE96, + tehhahinitialarabic: 0xFCA2, + tehhahisolatedarabic: 0xFC0C, + tehinitialarabic: 0xFE97, + tehiragana: 0x3066, + tehjeeminitialarabic: 0xFCA1, + tehjeemisolatedarabic: 0xFC0B, + tehmarbutaarabic: 0x0629, + tehmarbutafinalarabic: 0xFE94, + tehmedialarabic: 0xFE98, + tehmeeminitialarabic: 0xFCA4, + tehmeemisolatedarabic: 0xFC0E, + tehnoonfinalarabic: 0xFC73, + tekatakana: 0x30C6, + tekatakanahalfwidth: 0xFF83, + telephone: 0x2121, + telephoneblack: 0x260E, + telishagedolahebrew: 0x05A0, + telishaqetanahebrew: 0x05A9, + tencircle: 0x2469, + tenideographicparen: 0x3229, + tenparen: 0x247D, + tenperiod: 0x2491, + tenroman: 0x2179, + tesh: 0x02A7, + tet: 0x05D8, + tetdagesh: 0xFB38, + tetdageshhebrew: 0xFB38, + tethebrew: 0x05D8, + tetsecyrillic: 0x04B5, + tevirhebrew: 0x059B, + tevirlefthebrew: 0x059B, + thabengali: 0x09A5, + thadeva: 0x0925, + thagujarati: 0x0AA5, + thagurmukhi: 0x0A25, + thalarabic: 0x0630, + thalfinalarabic: 0xFEAC, + thanthakhatlowleftthai: 0xF898, + thanthakhatlowrightthai: 0xF897, + thanthakhatthai: 0x0E4C, + thanthakhatupperleftthai: 0xF896, + theharabic: 0x062B, + thehfinalarabic: 0xFE9A, + thehinitialarabic: 0xFE9B, + thehmedialarabic: 0xFE9C, + thereexists: 0x2203, + therefore: 0x2234, + theta: 0x03B8, + theta1: 0x03D1, + thetasymbolgreek: 0x03D1, + thieuthacirclekorean: 0x3279, + thieuthaparenkorean: 0x3219, + thieuthcirclekorean: 0x326B, + thieuthkorean: 0x314C, + thieuthparenkorean: 0x320B, + thirteencircle: 0x246C, + thirteenparen: 0x2480, + thirteenperiod: 0x2494, + thonangmonthothai: 0x0E11, + thook: 0x01AD, + thophuthaothai: 0x0E12, + thorn: 0x00FE, + thothahanthai: 0x0E17, + thothanthai: 0x0E10, + thothongthai: 0x0E18, + thothungthai: 0x0E16, + thousandcyrillic: 0x0482, + thousandsseparatorarabic: 0x066C, + thousandsseparatorpersian: 0x066C, + three: 0x0033, + threearabic: 0x0663, + threebengali: 0x09E9, + threecircle: 0x2462, + threecircleinversesansserif: 0x278C, + threedeva: 0x0969, + threeeighths: 0x215C, + threegujarati: 0x0AE9, + threegurmukhi: 0x0A69, + threehackarabic: 0x0663, + threehangzhou: 0x3023, + threeideographicparen: 0x3222, + threeinferior: 0x2083, + threemonospace: 0xFF13, + threenumeratorbengali: 0x09F6, + threeoldstyle: 0xF733, + threeparen: 0x2476, + threeperiod: 0x248A, + threepersian: 0x06F3, + threequarters: 0x00BE, + threequartersemdash: 0xF6DE, + threeroman: 0x2172, + threesuperior: 0x00B3, + threethai: 0x0E53, + thzsquare: 0x3394, + tihiragana: 0x3061, + tikatakana: 0x30C1, + tikatakanahalfwidth: 0xFF81, + tikeutacirclekorean: 0x3270, + tikeutaparenkorean: 0x3210, + tikeutcirclekorean: 0x3262, + tikeutkorean: 0x3137, + tikeutparenkorean: 0x3202, + tilde: 0x02DC, + tildebelowcmb: 0x0330, + tildecmb: 0x0303, + tildecomb: 0x0303, + tildedoublecmb: 0x0360, + tildeoperator: 0x223C, + tildeoverlaycmb: 0x0334, + tildeverticalcmb: 0x033E, + timescircle: 0x2297, + tipehahebrew: 0x0596, + tipehalefthebrew: 0x0596, + tippigurmukhi: 0x0A70, + titlocyrilliccmb: 0x0483, + tiwnarmenian: 0x057F, + tlinebelow: 0x1E6F, + tmonospace: 0xFF54, + toarmenian: 0x0569, + tohiragana: 0x3068, + tokatakana: 0x30C8, + tokatakanahalfwidth: 0xFF84, + tonebarextrahighmod: 0x02E5, + tonebarextralowmod: 0x02E9, + tonebarhighmod: 0x02E6, + tonebarlowmod: 0x02E8, + tonebarmidmod: 0x02E7, + tonefive: 0x01BD, + tonesix: 0x0185, + tonetwo: 0x01A8, + tonos: 0x0384, + tonsquare: 0x3327, + topatakthai: 0x0E0F, + tortoiseshellbracketleft: 0x3014, + tortoiseshellbracketleftsmall: 0xFE5D, + tortoiseshellbracketleftvertical: 0xFE39, + tortoiseshellbracketright: 0x3015, + tortoiseshellbracketrightsmall: 0xFE5E, + tortoiseshellbracketrightvertical: 0xFE3A, + totaothai: 0x0E15, + tpalatalhook: 0x01AB, + tparen: 0x24AF, + trademark: 0x2122, + trademarksans: 0xF8EA, + trademarkserif: 0xF6DB, + tretroflexhook: 0x0288, + triagdn: 0x25BC, + triaglf: 0x25C4, + triagrt: 0x25BA, + triagup: 0x25B2, + ts: 0x02A6, + tsadi: 0x05E6, + tsadidagesh: 0xFB46, + tsadidageshhebrew: 0xFB46, + tsadihebrew: 0x05E6, + tsecyrillic: 0x0446, + tsere: 0x05B5, + tsere12: 0x05B5, + tsere1e: 0x05B5, + tsere2b: 0x05B5, + tserehebrew: 0x05B5, + tserenarrowhebrew: 0x05B5, + tserequarterhebrew: 0x05B5, + tserewidehebrew: 0x05B5, + tshecyrillic: 0x045B, + tsuperior: 0xF6F3, + ttabengali: 0x099F, + ttadeva: 0x091F, + ttagujarati: 0x0A9F, + ttagurmukhi: 0x0A1F, + tteharabic: 0x0679, + ttehfinalarabic: 0xFB67, + ttehinitialarabic: 0xFB68, + ttehmedialarabic: 0xFB69, + tthabengali: 0x09A0, + tthadeva: 0x0920, + tthagujarati: 0x0AA0, + tthagurmukhi: 0x0A20, + tturned: 0x0287, + tuhiragana: 0x3064, + tukatakana: 0x30C4, + tukatakanahalfwidth: 0xFF82, + tusmallhiragana: 0x3063, + tusmallkatakana: 0x30C3, + tusmallkatakanahalfwidth: 0xFF6F, + twelvecircle: 0x246B, + twelveparen: 0x247F, + twelveperiod: 0x2493, + twelveroman: 0x217B, + twentycircle: 0x2473, + twentyhangzhou: 0x5344, + twentyparen: 0x2487, + twentyperiod: 0x249B, + two: 0x0032, + twoarabic: 0x0662, + twobengali: 0x09E8, + twocircle: 0x2461, + twocircleinversesansserif: 0x278B, + twodeva: 0x0968, + twodotenleader: 0x2025, + twodotleader: 0x2025, + twodotleadervertical: 0xFE30, + twogujarati: 0x0AE8, + twogurmukhi: 0x0A68, + twohackarabic: 0x0662, + twohangzhou: 0x3022, + twoideographicparen: 0x3221, + twoinferior: 0x2082, + twomonospace: 0xFF12, + twonumeratorbengali: 0x09F5, + twooldstyle: 0xF732, + twoparen: 0x2475, + twoperiod: 0x2489, + twopersian: 0x06F2, + tworoman: 0x2171, + twostroke: 0x01BB, + twosuperior: 0x00B2, + twothai: 0x0E52, + twothirds: 0x2154, + u: 0x0075, + uacute: 0x00FA, + ubar: 0x0289, + ubengali: 0x0989, + ubopomofo: 0x3128, + ubreve: 0x016D, + ucaron: 0x01D4, + ucircle: 0x24E4, + ucircumflex: 0x00FB, + ucircumflexbelow: 0x1E77, + ucyrillic: 0x0443, + udattadeva: 0x0951, + udblacute: 0x0171, + udblgrave: 0x0215, + udeva: 0x0909, + udieresis: 0x00FC, + udieresisacute: 0x01D8, + udieresisbelow: 0x1E73, + udieresiscaron: 0x01DA, + udieresiscyrillic: 0x04F1, + udieresisgrave: 0x01DC, + udieresismacron: 0x01D6, + udotbelow: 0x1EE5, + ugrave: 0x00F9, + ugujarati: 0x0A89, + ugurmukhi: 0x0A09, + uhiragana: 0x3046, + uhookabove: 0x1EE7, + uhorn: 0x01B0, + uhornacute: 0x1EE9, + uhorndotbelow: 0x1EF1, + uhorngrave: 0x1EEB, + uhornhookabove: 0x1EED, + uhorntilde: 0x1EEF, + uhungarumlaut: 0x0171, + uhungarumlautcyrillic: 0x04F3, + uinvertedbreve: 0x0217, + ukatakana: 0x30A6, + ukatakanahalfwidth: 0xFF73, + ukcyrillic: 0x0479, + ukorean: 0x315C, + umacron: 0x016B, + umacroncyrillic: 0x04EF, + umacrondieresis: 0x1E7B, + umatragurmukhi: 0x0A41, + umonospace: 0xFF55, + underscore: 0x005F, + underscoredbl: 0x2017, + underscoremonospace: 0xFF3F, + underscorevertical: 0xFE33, + underscorewavy: 0xFE4F, + union: 0x222A, + universal: 0x2200, + uogonek: 0x0173, + uparen: 0x24B0, + upblock: 0x2580, + upperdothebrew: 0x05C4, + upsilon: 0x03C5, + upsilondieresis: 0x03CB, + upsilondieresistonos: 0x03B0, + upsilonlatin: 0x028A, + upsilontonos: 0x03CD, + uptackbelowcmb: 0x031D, + uptackmod: 0x02D4, + uragurmukhi: 0x0A73, + uring: 0x016F, + ushortcyrillic: 0x045E, + usmallhiragana: 0x3045, + usmallkatakana: 0x30A5, + usmallkatakanahalfwidth: 0xFF69, + ustraightcyrillic: 0x04AF, + ustraightstrokecyrillic: 0x04B1, + utilde: 0x0169, + utildeacute: 0x1E79, + utildebelow: 0x1E75, + uubengali: 0x098A, + uudeva: 0x090A, + uugujarati: 0x0A8A, + uugurmukhi: 0x0A0A, + uumatragurmukhi: 0x0A42, + uuvowelsignbengali: 0x09C2, + uuvowelsigndeva: 0x0942, + uuvowelsigngujarati: 0x0AC2, + uvowelsignbengali: 0x09C1, + uvowelsigndeva: 0x0941, + uvowelsigngujarati: 0x0AC1, + v: 0x0076, + vadeva: 0x0935, + vagujarati: 0x0AB5, + vagurmukhi: 0x0A35, + vakatakana: 0x30F7, + vav: 0x05D5, + vavdagesh: 0xFB35, + vavdagesh65: 0xFB35, + vavdageshhebrew: 0xFB35, + vavhebrew: 0x05D5, + vavholam: 0xFB4B, + vavholamhebrew: 0xFB4B, + vavvavhebrew: 0x05F0, + vavyodhebrew: 0x05F1, + vcircle: 0x24E5, + vdotbelow: 0x1E7F, + vecyrillic: 0x0432, + veharabic: 0x06A4, + vehfinalarabic: 0xFB6B, + vehinitialarabic: 0xFB6C, + vehmedialarabic: 0xFB6D, + vekatakana: 0x30F9, + venus: 0x2640, + verticalbar: 0x007C, + verticallineabovecmb: 0x030D, + verticallinebelowcmb: 0x0329, + verticallinelowmod: 0x02CC, + verticallinemod: 0x02C8, + vewarmenian: 0x057E, + vhook: 0x028B, + vikatakana: 0x30F8, + viramabengali: 0x09CD, + viramadeva: 0x094D, + viramagujarati: 0x0ACD, + visargabengali: 0x0983, + visargadeva: 0x0903, + visargagujarati: 0x0A83, + vmonospace: 0xFF56, + voarmenian: 0x0578, + voicediterationhiragana: 0x309E, + voicediterationkatakana: 0x30FE, + voicedmarkkana: 0x309B, + voicedmarkkanahalfwidth: 0xFF9E, + vokatakana: 0x30FA, + vparen: 0x24B1, + vtilde: 0x1E7D, + vturned: 0x028C, + vuhiragana: 0x3094, + vukatakana: 0x30F4, + w: 0x0077, + wacute: 0x1E83, + waekorean: 0x3159, + wahiragana: 0x308F, + wakatakana: 0x30EF, + wakatakanahalfwidth: 0xFF9C, + wakorean: 0x3158, + wasmallhiragana: 0x308E, + wasmallkatakana: 0x30EE, + wattosquare: 0x3357, + wavedash: 0x301C, + wavyunderscorevertical: 0xFE34, + wawarabic: 0x0648, + wawfinalarabic: 0xFEEE, + wawhamzaabovearabic: 0x0624, + wawhamzaabovefinalarabic: 0xFE86, + wbsquare: 0x33DD, + wcircle: 0x24E6, + wcircumflex: 0x0175, + wdieresis: 0x1E85, + wdotaccent: 0x1E87, + wdotbelow: 0x1E89, + wehiragana: 0x3091, + weierstrass: 0x2118, + wekatakana: 0x30F1, + wekorean: 0x315E, + weokorean: 0x315D, + wgrave: 0x1E81, + whitebullet: 0x25E6, + whitecircle: 0x25CB, + whitecircleinverse: 0x25D9, + whitecornerbracketleft: 0x300E, + whitecornerbracketleftvertical: 0xFE43, + whitecornerbracketright: 0x300F, + whitecornerbracketrightvertical: 0xFE44, + whitediamond: 0x25C7, + whitediamondcontainingblacksmalldiamond: 0x25C8, + whitedownpointingsmalltriangle: 0x25BF, + whitedownpointingtriangle: 0x25BD, + whiteleftpointingsmalltriangle: 0x25C3, + whiteleftpointingtriangle: 0x25C1, + whitelenticularbracketleft: 0x3016, + whitelenticularbracketright: 0x3017, + whiterightpointingsmalltriangle: 0x25B9, + whiterightpointingtriangle: 0x25B7, + whitesmallsquare: 0x25AB, + whitesmilingface: 0x263A, + whitesquare: 0x25A1, + whitestar: 0x2606, + whitetelephone: 0x260F, + whitetortoiseshellbracketleft: 0x3018, + whitetortoiseshellbracketright: 0x3019, + whiteuppointingsmalltriangle: 0x25B5, + whiteuppointingtriangle: 0x25B3, + wihiragana: 0x3090, + wikatakana: 0x30F0, + wikorean: 0x315F, + wmonospace: 0xFF57, + wohiragana: 0x3092, + wokatakana: 0x30F2, + wokatakanahalfwidth: 0xFF66, + won: 0x20A9, + wonmonospace: 0xFFE6, + wowaenthai: 0x0E27, + wparen: 0x24B2, + wring: 0x1E98, + wsuperior: 0x02B7, + wturned: 0x028D, + wynn: 0x01BF, + x: 0x0078, + xabovecmb: 0x033D, + xbopomofo: 0x3112, + xcircle: 0x24E7, + xdieresis: 0x1E8D, + xdotaccent: 0x1E8B, + xeharmenian: 0x056D, + xi: 0x03BE, + xmonospace: 0xFF58, + xparen: 0x24B3, + xsuperior: 0x02E3, + y: 0x0079, + yaadosquare: 0x334E, + yabengali: 0x09AF, + yacute: 0x00FD, + yadeva: 0x092F, + yaekorean: 0x3152, + yagujarati: 0x0AAF, + yagurmukhi: 0x0A2F, + yahiragana: 0x3084, + yakatakana: 0x30E4, + yakatakanahalfwidth: 0xFF94, + yakorean: 0x3151, + yamakkanthai: 0x0E4E, + yasmallhiragana: 0x3083, + yasmallkatakana: 0x30E3, + yasmallkatakanahalfwidth: 0xFF6C, + yatcyrillic: 0x0463, + ycircle: 0x24E8, + ycircumflex: 0x0177, + ydieresis: 0x00FF, + ydotaccent: 0x1E8F, + ydotbelow: 0x1EF5, + yeharabic: 0x064A, + yehbarreearabic: 0x06D2, + yehbarreefinalarabic: 0xFBAF, + yehfinalarabic: 0xFEF2, + yehhamzaabovearabic: 0x0626, + yehhamzaabovefinalarabic: 0xFE8A, + yehhamzaaboveinitialarabic: 0xFE8B, + yehhamzaabovemedialarabic: 0xFE8C, + yehinitialarabic: 0xFEF3, + yehmedialarabic: 0xFEF4, + yehmeeminitialarabic: 0xFCDD, + yehmeemisolatedarabic: 0xFC58, + yehnoonfinalarabic: 0xFC94, + yehthreedotsbelowarabic: 0x06D1, + yekorean: 0x3156, + yen: 0x00A5, + yenmonospace: 0xFFE5, + yeokorean: 0x3155, + yeorinhieuhkorean: 0x3186, + yerahbenyomohebrew: 0x05AA, + yerahbenyomolefthebrew: 0x05AA, + yericyrillic: 0x044B, + yerudieresiscyrillic: 0x04F9, + yesieungkorean: 0x3181, + yesieungpansioskorean: 0x3183, + yesieungsioskorean: 0x3182, + yetivhebrew: 0x059A, + ygrave: 0x1EF3, + yhook: 0x01B4, + yhookabove: 0x1EF7, + yiarmenian: 0x0575, + yicyrillic: 0x0457, + yikorean: 0x3162, + yinyang: 0x262F, + yiwnarmenian: 0x0582, + ymonospace: 0xFF59, + yod: 0x05D9, + yoddagesh: 0xFB39, + yoddageshhebrew: 0xFB39, + yodhebrew: 0x05D9, + yodyodhebrew: 0x05F2, + yodyodpatahhebrew: 0xFB1F, + yohiragana: 0x3088, + yoikorean: 0x3189, + yokatakana: 0x30E8, + yokatakanahalfwidth: 0xFF96, + yokorean: 0x315B, + yosmallhiragana: 0x3087, + yosmallkatakana: 0x30E7, + yosmallkatakanahalfwidth: 0xFF6E, + yotgreek: 0x03F3, + yoyaekorean: 0x3188, + yoyakorean: 0x3187, + yoyakthai: 0x0E22, + yoyingthai: 0x0E0D, + yparen: 0x24B4, + ypogegrammeni: 0x037A, + ypogegrammenigreekcmb: 0x0345, + yr: 0x01A6, + yring: 0x1E99, + ysuperior: 0x02B8, + ytilde: 0x1EF9, + yturned: 0x028E, + yuhiragana: 0x3086, + yuikorean: 0x318C, + yukatakana: 0x30E6, + yukatakanahalfwidth: 0xFF95, + yukorean: 0x3160, + yusbigcyrillic: 0x046B, + yusbigiotifiedcyrillic: 0x046D, + yuslittlecyrillic: 0x0467, + yuslittleiotifiedcyrillic: 0x0469, + yusmallhiragana: 0x3085, + yusmallkatakana: 0x30E5, + yusmallkatakanahalfwidth: 0xFF6D, + yuyekorean: 0x318B, + yuyeokorean: 0x318A, + yyabengali: 0x09DF, + yyadeva: 0x095F, + z: 0x007A, + zaarmenian: 0x0566, + zacute: 0x017A, + zadeva: 0x095B, + zagurmukhi: 0x0A5B, + zaharabic: 0x0638, + zahfinalarabic: 0xFEC6, + zahinitialarabic: 0xFEC7, + zahiragana: 0x3056, + zahmedialarabic: 0xFEC8, + zainarabic: 0x0632, + zainfinalarabic: 0xFEB0, + zakatakana: 0x30B6, + zaqefgadolhebrew: 0x0595, + zaqefqatanhebrew: 0x0594, + zarqahebrew: 0x0598, + zayin: 0x05D6, + zayindagesh: 0xFB36, + zayindageshhebrew: 0xFB36, + zayinhebrew: 0x05D6, + zbopomofo: 0x3117, + zcaron: 0x017E, + zcircle: 0x24E9, + zcircumflex: 0x1E91, + zcurl: 0x0291, + zdot: 0x017C, + zdotaccent: 0x017C, + zdotbelow: 0x1E93, + zecyrillic: 0x0437, + zedescendercyrillic: 0x0499, + zedieresiscyrillic: 0x04DF, + zehiragana: 0x305C, + zekatakana: 0x30BC, + zero: 0x0030, + zeroarabic: 0x0660, + zerobengali: 0x09E6, + zerodeva: 0x0966, + zerogujarati: 0x0AE6, + zerogurmukhi: 0x0A66, + zerohackarabic: 0x0660, + zeroinferior: 0x2080, + zeromonospace: 0xFF10, + zerooldstyle: 0xF730, + zeropersian: 0x06F0, + zerosuperior: 0x2070, + zerothai: 0x0E50, + zerowidthjoiner: 0xFEFF, + zerowidthnonjoiner: 0x200C, + zerowidthspace: 0x200B, + zeta: 0x03B6, + zhbopomofo: 0x3113, + zhearmenian: 0x056A, + zhebrevecyrillic: 0x04C2, + zhecyrillic: 0x0436, + zhedescendercyrillic: 0x0497, + zhedieresiscyrillic: 0x04DD, + zihiragana: 0x3058, + zikatakana: 0x30B8, + zinorhebrew: 0x05AE, + zlinebelow: 0x1E95, + zmonospace: 0xFF5A, + zohiragana: 0x305E, + zokatakana: 0x30BE, + zparen: 0x24B5, + zretroflexhook: 0x0290, + zstroke: 0x01B6, + zuhiragana: 0x305A, + zukatakana: 0x30BA, + '.notdef': 0x0000 +}; + + + +var 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) { + 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 data = message.data; + var stream = new Stream(data, 0, data.length, image.dict); + promise.resolve(stream); + }); + } else { + promise.resolve(image); + } + } + /** + * Decode and clamp a value. The formula is different from the spec because we + * don't decode to float range [0,1], we decode it in the [0,max] range. + */ + function decodeAndClamp(value, addend, coefficient, max) { + value = addend + value * coefficient; + // Clamp the value to the range + return value < 0 ? 0 : value > max ? max : value; + } + function PDFImage(xref, res, image, inline, smask, mask, isMask) { + this.image = image; + 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 = ... + } + // 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) + error('Invalid image width: ' + this.width + ' or height: ' + + this.height); + + this.interpolate = dict.get('Interpolate', 'I') || false; + this.imageMask = dict.get('ImageMask', 'IM') || false; + this.matte = dict.get('Matte') || false; + + var bitsPerComponent = image.bitsPerComponent; + if (!bitsPerComponent) { + bitsPerComponent = dict.get('BitsPerComponent', 'BPC'); + if (!bitsPerComponent) { + if (this.imageMask) + bitsPerComponent = 1; + else + error('Bits per component missing in image: ' + this.imageMask); + } + } + this.bpc = bitsPerComponent; + + if (!this.imageMask) { + var colorSpace = dict.get('ColorSpace', 'CS'); + if (!colorSpace) { + warn('JPX images (which don"t require color spaces'); + colorSpace = new Name('DeviceRGB'); + } + this.colorSpace = ColorSpace.parse(colorSpace, xref, res); + this.numComps = this.colorSpace.numComps; + } + + this.decode = dict.get('Decode', 'D'); + this.needsDecode = false; + if (this.decode && + ((this.colorSpace && !this.colorSpace.isDefaultDecode(this.decode)) || + (isMask && !ColorSpace.isDefaultDecode(this.decode, 1)))) { + this.needsDecode = true; + // Do some preprocessing to avoid more math. + var max = (1 << bitsPerComponent) - 1; + this.decodeCoefficients = []; + this.decodeAddends = []; + for (var i = 0, j = 0; i < this.decode.length; i += 2, ++j) { + var dmin = this.decode[i]; + var dmax = this.decode[i + 1]; + this.decodeCoefficients[j] = dmax - dmin; + this.decodeAddends[j] = max * dmin; + } + } + + if (smask) { + this.smask = new PDFImage(xref, res, smask, false); + } else if (mask) { + if (isStream(mask)) { + this.mask = new PDFImage(xref, res, mask, false, null, null, true); + } else { + // Color key mask (just an array). + this.mask = mask; + } + } + } + /** + * Handles processing of image data and calls the callback with an argument + * of a PDFImage when the image is ready to be used. + */ + PDFImage.buildImage = function PDFImage_buildImage(callback, 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 smask = image.dict.get('SMask'); + var mask = image.dict.get('Mask'); + + if (smask) { + handleImageData(handler, xref, res, smask, smaskPromise); + maskPromise.resolve(null); + } else { + smaskPromise.resolve(null); + if (mask) { + if (isStream(mask)) { + handleImageData(handler, xref, res, mask, maskPromise); + } else if (isArray(mask)) { + maskPromise.resolve(mask); + } else { + warn('Unsupported mask format.'); + maskPromise.resolve(null); + } + } else { + maskPromise.resolve(null); + } + } + }; + + /** + * Resize an image using the nearest neighbor algorithm. Currently only + * supports one and three component images. + * @param {TypedArray} pixels The original image with one component. + * @param {Number} bpc Number of bits per component. + * @param {Number} components Number of color components, 1 or 3 is supported. + * @param {Number} w1 Original width. + * @param {Number} h1 Original height. + * @param {Number} w2 New width. + * @param {Number} h2 New height. + * @return {TypedArray} Resized image data. + */ + PDFImage.resize = function PDFImage_resize(pixels, bpc, components, + w1, h1, w2, h2) { + var length = w2 * h2 * components; + var temp = 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]; + } + } + } + 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]; + } + } else { + for (var i = 0; i < length; i++) { + data[i] = imgArray[i]; + } + } + + return {data: data, width: width, height: height}; + }; + + PDFImage.prototype = { + get drawWidth() { + if (!this.smask) + return this.width; + return Math.max(this.width, this.smask.width); + }, + get drawHeight() { + if (!this.smask) + return this.height; + return Math.max(this.height, this.smask.height); + }, + 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; + + 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++) { + buffer[i] = +!(buffer[i]); + } + return; + } + var index = 0; + for (var i = 0, ii = this.width * this.height; i < ii; i++) { + for (var j = 0; j < numComps; j++) { + buffer[index] = decodeAndClamp(buffer[index], decodeAddends[j], + decodeCoefficients[j], max); + index++; + } + } + }, + getComponents: function PDFImage_getComponents(buffer) { + var bpc = this.bpc; + + // This image doesn't require any extra work. + if (bpc === 8) + return buffer; + + var 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 rowComps = width * numComps; + + var max = (1 << bpc) - 1; + + if (bpc === 1) { + // Optimization for reading 1 bpc images. + var mask = 0; + var buf = 0; + + for (var i = 0, ii = length; i < ii; ++i) { + if (i % rowComps === 0) { + mask = 0; + buf = 0; + } else { + mask >>= 1; + } + + if (mask <= 0) { + buf = buffer[bufferPos++]; + mask = 128; + } + + 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) { + if (i % rowComps === 0) { + buf = 0; + bits = 0; + } + + while (bits < bpc) { + buf = (buf << 8) | buffer[bufferPos++]; + bits += 8; + } + + var remainingBits = bits - bpc; + var value = buf >> remainingBits; + output[i] = value < 0 ? 0 : value > max ? max : value; + buf = buf & ((1 << remainingBits) - 1); + bits = remainingBits; + } + } + return output; + }, + fillOpacity: function PDFImage_fillOpacity(rgbaBuf, width, height, + actualHeight, image) { + var smask = this.smask; + var mask = this.mask; + var alphaBuf; + + if (smask) { + var sw = smask.width; + var sh = smask.height; + alphaBuf = new Uint8Array(sw * sh); + smask.fillGrayBuffer(alphaBuf); + if (sw != width || sh != height) + alphaBuf = PDFImage.resize(alphaBuf, smask.bpc, 1, sw, sh, width, + height); + } else if (mask) { + if (mask instanceof PDFImage) { + var sw = mask.width; + var 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) + alphaBuf[i] = 255 - alphaBuf[i]; + + if (sw != width || sh != height) + alphaBuf = PDFImage.resize(alphaBuf, mask.bpc, 1, sw, sh, width, + height); + } else if (isArray(mask)) { + // Color key mask: if any of the compontents are outside the range + // then they should be painted. + alphaBuf = new Uint8Array(width * height); + var numComps = this.numComps; + for (var i = 0, ii = width * height; i < ii; ++i) { + var opacity = 0; + var imageOffset = i * numComps; + for (var j = 0; j < numComps; ++j) { + var color = image[imageOffset + j]; + var maskOffset = j * 2; + if (color < mask[maskOffset] || color > mask[maskOffset + 1]) { + opacity = 255; + break; + } + } + alphaBuf[i] = opacity; + } + } else { + error('Unknown mask format.'); + } + } + + if (alphaBuf) { + for (var 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) { + 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 length = width * height * 4; + 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 + 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]); + } + }, + fillRgbaBuffer: function PDFImage_fillRgbaBuffer(buffer, width, height) { + var numComps = this.numComps; + var originalWidth = this.width; + var originalHeight = this.height; + var bpc = this.bpc; + + // rows start at byte boundary; + var rowBytes = (originalWidth * numComps * bpc + 7) >> 3; + var imgArray = this.getImageBytes(originalHeight * rowBytes); + + // imgArray can be incomplete (e.g. after CCITT fax encoding) + var actualHeight = 0 | (imgArray.length / rowBytes * + height / 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 (this.needsDecode) { + this.decodeBuffer(comps); + } + + this.colorSpace.fillRgb(buffer, originalWidth, originalHeight, width, + height, actualHeight, bpc, comps); + + this.undoPreblend(buffer, width, actualHeight); + }, + fillGrayBuffer: function PDFImage_fillGrayBuffer(buffer) { + var numComps = this.numComps; + if (numComps != 1) + error('Reading gray scale from a color image: ' + numComps); + + var width = this.width; + var height = this.height; + var bpc = this.bpc; + + // rows start at byte boundary; + var rowBytes = (width * numComps * bpc + 7) >> 3; + var imgArray = this.getImageBytes(height * rowBytes); + + var comps = this.getComponents(imgArray); + if (this.needsDecode) { + this.decodeBuffer(comps); + } + var 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) + 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) { + this.image.reset(); + return this.image.getBytes(length); + } + }; + return PDFImage; +})(); + + +// The Metrics object contains glyph widths (in glyph space units). +// As per PDF spec, for most fonts (Type 3 being an exception) a glyph +// space unit corresponds to 1/1000th of text space unit. +var Metrics = { + 'Courier': 600, + 'Courier-Bold': 600, + 'Courier-BoldOblique': 600, + 'Courier-Oblique': 600, + 'Helvetica' : { + 'space': 278, + 'exclam': 278, + 'quotedbl': 355, + 'numbersign': 556, + 'dollar': 556, + 'percent': 889, + 'ampersand': 667, + 'quoteright': 222, + 'parenleft': 333, + 'parenright': 333, + 'asterisk': 389, + 'plus': 584, + 'comma': 278, + 'hyphen': 333, + 'period': 278, + 'slash': 278, + 'zero': 556, + 'one': 556, + 'two': 556, + 'three': 556, + 'four': 556, + 'five': 556, + 'six': 556, + 'seven': 556, + 'eight': 556, + 'nine': 556, + 'colon': 278, + 'semicolon': 278, + 'less': 584, + 'equal': 584, + 'greater': 584, + 'question': 556, + 'at': 1015, + 'A': 667, + 'B': 667, + 'C': 722, + 'D': 722, + 'E': 667, + 'F': 611, + 'G': 778, + 'H': 722, + 'I': 278, + 'J': 500, + 'K': 667, + 'L': 556, + 'M': 833, + 'N': 722, + 'O': 778, + 'P': 667, + 'Q': 778, + 'R': 722, + 'S': 667, + 'T': 611, + 'U': 722, + 'V': 667, + 'W': 944, + 'X': 667, + 'Y': 667, + 'Z': 611, + 'bracketleft': 278, + 'backslash': 278, + 'bracketright': 278, + 'asciicircum': 469, + 'underscore': 556, + 'quoteleft': 222, + 'a': 556, + 'b': 556, + 'c': 500, + 'd': 556, + 'e': 556, + 'f': 278, + 'g': 556, + 'h': 556, + 'i': 222, + 'j': 222, + 'k': 500, + 'l': 222, + 'm': 833, + 'n': 556, + 'o': 556, + 'p': 556, + 'q': 556, + 'r': 333, + 's': 500, + 't': 278, + 'u': 556, + 'v': 500, + 'w': 722, + 'x': 500, + 'y': 500, + 'z': 500, + 'braceleft': 334, + 'bar': 260, + 'braceright': 334, + 'asciitilde': 584, + 'exclamdown': 333, + 'cent': 556, + 'sterling': 556, + 'fraction': 167, + 'yen': 556, + 'florin': 556, + 'section': 556, + 'currency': 556, + 'quotesingle': 191, + 'quotedblleft': 333, + 'guillemotleft': 556, + 'guilsinglleft': 333, + 'guilsinglright': 333, + 'fi': 500, + 'fl': 500, + 'endash': 556, + 'dagger': 556, + 'daggerdbl': 556, + 'periodcentered': 278, + 'paragraph': 537, + 'bullet': 350, + 'quotesinglbase': 222, + 'quotedblbase': 333, + 'quotedblright': 333, + 'guillemotright': 556, + 'ellipsis': 1000, + 'perthousand': 1000, + 'questiondown': 611, + 'grave': 333, + 'acute': 333, + 'circumflex': 333, + 'tilde': 333, + 'macron': 333, + 'breve': 333, + 'dotaccent': 333, + 'dieresis': 333, + 'ring': 333, + 'cedilla': 333, + 'hungarumlaut': 333, + 'ogonek': 333, + 'caron': 333, + 'emdash': 1000, + 'AE': 1000, + 'ordfeminine': 370, + 'Lslash': 556, + 'Oslash': 778, + 'OE': 1000, + 'ordmasculine': 365, + 'ae': 889, + 'dotlessi': 278, + 'lslash': 222, + 'oslash': 611, + 'oe': 944, + 'germandbls': 611, + 'Idieresis': 278, + 'eacute': 556, + 'abreve': 556, + 'uhungarumlaut': 556, + 'ecaron': 556, + 'Ydieresis': 667, + 'divide': 584, + 'Yacute': 667, + 'Acircumflex': 667, + 'aacute': 556, + 'Ucircumflex': 722, + 'yacute': 500, + 'scommaaccent': 500, + 'ecircumflex': 556, + 'Uring': 722, + 'Udieresis': 722, + 'aogonek': 556, + 'Uacute': 722, + 'uogonek': 556, + 'Edieresis': 667, + 'Dcroat': 722, + 'commaaccent': 250, + 'copyright': 737, + 'Emacron': 667, + 'ccaron': 500, + 'aring': 556, + 'Ncommaaccent': 722, + 'lacute': 222, + 'agrave': 556, + 'Tcommaaccent': 611, + 'Cacute': 722, + 'atilde': 556, + 'Edotaccent': 667, + 'scaron': 500, + 'scedilla': 500, + 'iacute': 278, + 'lozenge': 471, + 'Rcaron': 722, + 'Gcommaaccent': 778, + 'ucircumflex': 556, + 'acircumflex': 556, + 'Amacron': 667, + 'rcaron': 333, + 'ccedilla': 500, + 'Zdotaccent': 611, + 'Thorn': 667, + 'Omacron': 778, + 'Racute': 722, + 'Sacute': 667, + 'dcaron': 643, + 'Umacron': 722, + 'uring': 556, + 'threesuperior': 333, + 'Ograve': 778, + 'Agrave': 667, + 'Abreve': 667, + 'multiply': 584, + 'uacute': 556, + 'Tcaron': 611, + 'partialdiff': 476, + 'ydieresis': 500, + 'Nacute': 722, + 'icircumflex': 278, + 'Ecircumflex': 667, + 'adieresis': 556, + 'edieresis': 556, + 'cacute': 500, + 'nacute': 556, + 'umacron': 556, + 'Ncaron': 722, + 'Iacute': 278, + 'plusminus': 584, + 'brokenbar': 260, + 'registered': 737, + 'Gbreve': 778, + 'Idotaccent': 278, + 'summation': 600, + 'Egrave': 667, + 'racute': 333, + 'omacron': 556, + 'Zacute': 611, + 'Zcaron': 611, + 'greaterequal': 549, + 'Eth': 722, + 'Ccedilla': 722, + 'lcommaaccent': 222, + 'tcaron': 317, + 'eogonek': 556, + 'Uogonek': 722, + 'Aacute': 667, + 'Adieresis': 667, + 'egrave': 556, + 'zacute': 500, + 'iogonek': 222, + 'Oacute': 778, + 'oacute': 556, + 'amacron': 556, + 'sacute': 500, + 'idieresis': 278, + 'Ocircumflex': 778, + 'Ugrave': 722, + 'Delta': 612, + 'thorn': 556, + 'twosuperior': 333, + 'Odieresis': 778, + 'mu': 556, + 'igrave': 278, + 'ohungarumlaut': 556, + 'Eogonek': 667, + 'dcroat': 556, + 'threequarters': 834, + 'Scedilla': 667, + 'lcaron': 299, + 'Kcommaaccent': 667, + 'Lacute': 556, + 'trademark': 1000, + 'edotaccent': 556, + 'Igrave': 278, + 'Imacron': 278, + 'Lcaron': 556, + 'onehalf': 834, + 'lessequal': 549, + 'ocircumflex': 556, + 'ntilde': 556, + 'Uhungarumlaut': 722, + 'Eacute': 667, + 'emacron': 556, + 'gbreve': 556, + 'onequarter': 834, + 'Scaron': 667, + 'Scommaaccent': 667, + 'Ohungarumlaut': 778, + 'degree': 400, + 'ograve': 556, + 'Ccaron': 722, + 'ugrave': 556, + 'radical': 453, + 'Dcaron': 722, + 'rcommaaccent': 333, + 'Ntilde': 722, + 'otilde': 556, + 'Rcommaaccent': 722, + 'Lcommaaccent': 556, + 'Atilde': 667, + 'Aogonek': 667, + 'Aring': 667, + 'Otilde': 778, + 'zdotaccent': 500, + 'Ecaron': 667, + 'Iogonek': 278, + 'kcommaaccent': 500, + 'minus': 584, + 'Icircumflex': 278, + 'ncaron': 556, + 'tcommaaccent': 278, + 'logicalnot': 584, + 'odieresis': 556, + 'udieresis': 556, + 'notequal': 549, + 'gcommaaccent': 556, + 'eth': 556, + 'zcaron': 500, + 'ncommaaccent': 556, + 'onesuperior': 333, + 'imacron': 278, + 'Euro': 556 + }, + 'Helvetica-Bold': { + 'space': 278, + 'exclam': 333, + 'quotedbl': 474, + 'numbersign': 556, + 'dollar': 556, + 'percent': 889, + 'ampersand': 722, + 'quoteright': 278, + 'parenleft': 333, + 'parenright': 333, + 'asterisk': 389, + 'plus': 584, + 'comma': 278, + 'hyphen': 333, + 'period': 278, + 'slash': 278, + 'zero': 556, + 'one': 556, + 'two': 556, + 'three': 556, + 'four': 556, + 'five': 556, + 'six': 556, + 'seven': 556, + 'eight': 556, + 'nine': 556, + 'colon': 333, + 'semicolon': 333, + 'less': 584, + 'equal': 584, + 'greater': 584, + 'question': 611, + 'at': 975, + 'A': 722, + 'B': 722, + 'C': 722, + 'D': 722, + 'E': 667, + 'F': 611, + 'G': 778, + 'H': 722, + 'I': 278, + 'J': 556, + 'K': 722, + 'L': 611, + 'M': 833, + 'N': 722, + 'O': 778, + 'P': 667, + 'Q': 778, + 'R': 722, + 'S': 667, + 'T': 611, + 'U': 722, + 'V': 667, + 'W': 944, + 'X': 667, + 'Y': 667, + 'Z': 611, + 'bracketleft': 333, + 'backslash': 278, + 'bracketright': 333, + 'asciicircum': 584, + 'underscore': 556, + 'quoteleft': 278, + 'a': 556, + 'b': 611, + 'c': 556, + 'd': 611, + 'e': 556, + 'f': 333, + 'g': 611, + 'h': 611, + 'i': 278, + 'j': 278, + 'k': 556, + 'l': 278, + 'm': 889, + 'n': 611, + 'o': 611, + 'p': 611, + 'q': 611, + 'r': 389, + 's': 556, + 't': 333, + 'u': 611, + 'v': 556, + 'w': 778, + 'x': 556, + 'y': 556, + 'z': 500, + 'braceleft': 389, + 'bar': 280, + 'braceright': 389, + 'asciitilde': 584, + 'exclamdown': 333, + 'cent': 556, + 'sterling': 556, + 'fraction': 167, + 'yen': 556, + 'florin': 556, + 'section': 556, + 'currency': 556, + 'quotesingle': 238, + 'quotedblleft': 500, + 'guillemotleft': 556, + 'guilsinglleft': 333, + 'guilsinglright': 333, + 'fi': 611, + 'fl': 611, + 'endash': 556, + 'dagger': 556, + 'daggerdbl': 556, + 'periodcentered': 278, + 'paragraph': 556, + 'bullet': 350, + 'quotesinglbase': 278, + 'quotedblbase': 500, + 'quotedblright': 500, + 'guillemotright': 556, + 'ellipsis': 1000, + 'perthousand': 1000, + 'questiondown': 611, + 'grave': 333, + 'acute': 333, + 'circumflex': 333, + 'tilde': 333, + 'macron': 333, + 'breve': 333, + 'dotaccent': 333, + 'dieresis': 333, + 'ring': 333, + 'cedilla': 333, + 'hungarumlaut': 333, + 'ogonek': 333, + 'caron': 333, + 'emdash': 1000, + 'AE': 1000, + 'ordfeminine': 370, + 'Lslash': 611, + 'Oslash': 778, + 'OE': 1000, + 'ordmasculine': 365, + 'ae': 889, + 'dotlessi': 278, + 'lslash': 278, + 'oslash': 611, + 'oe': 944, + 'germandbls': 611, + 'Idieresis': 278, + 'eacute': 556, + 'abreve': 556, + 'uhungarumlaut': 611, + 'ecaron': 556, + 'Ydieresis': 667, + 'divide': 584, + 'Yacute': 667, + 'Acircumflex': 722, + 'aacute': 556, + 'Ucircumflex': 722, + 'yacute': 556, + 'scommaaccent': 556, + 'ecircumflex': 556, + 'Uring': 722, + 'Udieresis': 722, + 'aogonek': 556, + 'Uacute': 722, + 'uogonek': 611, + 'Edieresis': 667, + 'Dcroat': 722, + 'commaaccent': 250, + 'copyright': 737, + 'Emacron': 667, + 'ccaron': 556, + 'aring': 556, + 'Ncommaaccent': 722, + 'lacute': 278, + 'agrave': 556, + 'Tcommaaccent': 611, + 'Cacute': 722, + 'atilde': 556, + 'Edotaccent': 667, + 'scaron': 556, + 'scedilla': 556, + 'iacute': 278, + 'lozenge': 494, + 'Rcaron': 722, + 'Gcommaaccent': 778, + 'ucircumflex': 611, + 'acircumflex': 556, + 'Amacron': 722, + 'rcaron': 389, + 'ccedilla': 556, + 'Zdotaccent': 611, + 'Thorn': 667, + 'Omacron': 778, + 'Racute': 722, + 'Sacute': 667, + 'dcaron': 743, + 'Umacron': 722, + 'uring': 611, + 'threesuperior': 333, + 'Ograve': 778, + 'Agrave': 722, + 'Abreve': 722, + 'multiply': 584, + 'uacute': 611, + 'Tcaron': 611, + 'partialdiff': 494, + 'ydieresis': 556, + 'Nacute': 722, + 'icircumflex': 278, + 'Ecircumflex': 667, + 'adieresis': 556, + 'edieresis': 556, + 'cacute': 556, + 'nacute': 611, + 'umacron': 611, + 'Ncaron': 722, + 'Iacute': 278, + 'plusminus': 584, + 'brokenbar': 280, + 'registered': 737, + 'Gbreve': 778, + 'Idotaccent': 278, + 'summation': 600, + 'Egrave': 667, + 'racute': 389, + 'omacron': 611, + 'Zacute': 611, + 'Zcaron': 611, + 'greaterequal': 549, + 'Eth': 722, + 'Ccedilla': 722, + 'lcommaaccent': 278, + 'tcaron': 389, + 'eogonek': 556, + 'Uogonek': 722, + 'Aacute': 722, + 'Adieresis': 722, + 'egrave': 556, + 'zacute': 500, + 'iogonek': 278, + 'Oacute': 778, + 'oacute': 611, + 'amacron': 556, + 'sacute': 556, + 'idieresis': 278, + 'Ocircumflex': 778, + 'Ugrave': 722, + 'Delta': 612, + 'thorn': 611, + 'twosuperior': 333, + 'Odieresis': 778, + 'mu': 611, + 'igrave': 278, + 'ohungarumlaut': 611, + 'Eogonek': 667, + 'dcroat': 611, + 'threequarters': 834, + 'Scedilla': 667, + 'lcaron': 400, + 'Kcommaaccent': 722, + 'Lacute': 611, + 'trademark': 1000, + 'edotaccent': 556, + 'Igrave': 278, + 'Imacron': 278, + 'Lcaron': 611, + 'onehalf': 834, + 'lessequal': 549, + 'ocircumflex': 611, + 'ntilde': 611, + 'Uhungarumlaut': 722, + 'Eacute': 667, + 'emacron': 556, + 'gbreve': 611, + 'onequarter': 834, + 'Scaron': 667, + 'Scommaaccent': 667, + 'Ohungarumlaut': 778, + 'degree': 400, + 'ograve': 611, + 'Ccaron': 722, + 'ugrave': 611, + 'radical': 549, + 'Dcaron': 722, + 'rcommaaccent': 389, + 'Ntilde': 722, + 'otilde': 611, + 'Rcommaaccent': 722, + 'Lcommaaccent': 611, + 'Atilde': 722, + 'Aogonek': 722, + 'Aring': 722, + 'Otilde': 778, + 'zdotaccent': 500, + 'Ecaron': 667, + 'Iogonek': 278, + 'kcommaaccent': 556, + 'minus': 584, + 'Icircumflex': 278, + 'ncaron': 611, + 'tcommaaccent': 333, + 'logicalnot': 584, + 'odieresis': 611, + 'udieresis': 611, + 'notequal': 549, + 'gcommaaccent': 611, + 'eth': 611, + 'zcaron': 500, + 'ncommaaccent': 611, + 'onesuperior': 333, + 'imacron': 278, + 'Euro': 556 + }, + 'Helvetica-BoldOblique': { + 'space': 278, + 'exclam': 333, + 'quotedbl': 474, + 'numbersign': 556, + 'dollar': 556, + 'percent': 889, + 'ampersand': 722, + 'quoteright': 278, + 'parenleft': 333, + 'parenright': 333, + 'asterisk': 389, + 'plus': 584, + 'comma': 278, + 'hyphen': 333, + 'period': 278, + 'slash': 278, + 'zero': 556, + 'one': 556, + 'two': 556, + 'three': 556, + 'four': 556, + 'five': 556, + 'six': 556, + 'seven': 556, + 'eight': 556, + 'nine': 556, + 'colon': 333, + 'semicolon': 333, + 'less': 584, + 'equal': 584, + 'greater': 584, + 'question': 611, + 'at': 975, + 'A': 722, + 'B': 722, + 'C': 722, + 'D': 722, + 'E': 667, + 'F': 611, + 'G': 778, + 'H': 722, + 'I': 278, + 'J': 556, + 'K': 722, + 'L': 611, + 'M': 833, + 'N': 722, + 'O': 778, + 'P': 667, + 'Q': 778, + 'R': 722, + 'S': 667, + 'T': 611, + 'U': 722, + 'V': 667, + 'W': 944, + 'X': 667, + 'Y': 667, + 'Z': 611, + 'bracketleft': 333, + 'backslash': 278, + 'bracketright': 333, + 'asciicircum': 584, + 'underscore': 556, + 'quoteleft': 278, + 'a': 556, + 'b': 611, + 'c': 556, + 'd': 611, + 'e': 556, + 'f': 333, + 'g': 611, + 'h': 611, + 'i': 278, + 'j': 278, + 'k': 556, + 'l': 278, + 'm': 889, + 'n': 611, + 'o': 611, + 'p': 611, + 'q': 611, + 'r': 389, + 's': 556, + 't': 333, + 'u': 611, + 'v': 556, + 'w': 778, + 'x': 556, + 'y': 556, + 'z': 500, + 'braceleft': 389, + 'bar': 280, + 'braceright': 389, + 'asciitilde': 584, + 'exclamdown': 333, + 'cent': 556, + 'sterling': 556, + 'fraction': 167, + 'yen': 556, + 'florin': 556, + 'section': 556, + 'currency': 556, + 'quotesingle': 238, + 'quotedblleft': 500, + 'guillemotleft': 556, + 'guilsinglleft': 333, + 'guilsinglright': 333, + 'fi': 611, + 'fl': 611, + 'endash': 556, + 'dagger': 556, + 'daggerdbl': 556, + 'periodcentered': 278, + 'paragraph': 556, + 'bullet': 350, + 'quotesinglbase': 278, + 'quotedblbase': 500, + 'quotedblright': 500, + 'guillemotright': 556, + 'ellipsis': 1000, + 'perthousand': 1000, + 'questiondown': 611, + 'grave': 333, + 'acute': 333, + 'circumflex': 333, + 'tilde': 333, + 'macron': 333, + 'breve': 333, + 'dotaccent': 333, + 'dieresis': 333, + 'ring': 333, + 'cedilla': 333, + 'hungarumlaut': 333, + 'ogonek': 333, + 'caron': 333, + 'emdash': 1000, + 'AE': 1000, + 'ordfeminine': 370, + 'Lslash': 611, + 'Oslash': 778, + 'OE': 1000, + 'ordmasculine': 365, + 'ae': 889, + 'dotlessi': 278, + 'lslash': 278, + 'oslash': 611, + 'oe': 944, + 'germandbls': 611, + 'Idieresis': 278, + 'eacute': 556, + 'abreve': 556, + 'uhungarumlaut': 611, + 'ecaron': 556, + 'Ydieresis': 667, + 'divide': 584, + 'Yacute': 667, + 'Acircumflex': 722, + 'aacute': 556, + 'Ucircumflex': 722, + 'yacute': 556, + 'scommaaccent': 556, + 'ecircumflex': 556, + 'Uring': 722, + 'Udieresis': 722, + 'aogonek': 556, + 'Uacute': 722, + 'uogonek': 611, + 'Edieresis': 667, + 'Dcroat': 722, + 'commaaccent': 250, + 'copyright': 737, + 'Emacron': 667, + 'ccaron': 556, + 'aring': 556, + 'Ncommaaccent': 722, + 'lacute': 278, + 'agrave': 556, + 'Tcommaaccent': 611, + 'Cacute': 722, + 'atilde': 556, + 'Edotaccent': 667, + 'scaron': 556, + 'scedilla': 556, + 'iacute': 278, + 'lozenge': 494, + 'Rcaron': 722, + 'Gcommaaccent': 778, + 'ucircumflex': 611, + 'acircumflex': 556, + 'Amacron': 722, + 'rcaron': 389, + 'ccedilla': 556, + 'Zdotaccent': 611, + 'Thorn': 667, + 'Omacron': 778, + 'Racute': 722, + 'Sacute': 667, + 'dcaron': 743, + 'Umacron': 722, + 'uring': 611, + 'threesuperior': 333, + 'Ograve': 778, + 'Agrave': 722, + 'Abreve': 722, + 'multiply': 584, + 'uacute': 611, + 'Tcaron': 611, + 'partialdiff': 494, + 'ydieresis': 556, + 'Nacute': 722, + 'icircumflex': 278, + 'Ecircumflex': 667, + 'adieresis': 556, + 'edieresis': 556, + 'cacute': 556, + 'nacute': 611, + 'umacron': 611, + 'Ncaron': 722, + 'Iacute': 278, + 'plusminus': 584, + 'brokenbar': 280, + 'registered': 737, + 'Gbreve': 778, + 'Idotaccent': 278, + 'summation': 600, + 'Egrave': 667, + 'racute': 389, + 'omacron': 611, + 'Zacute': 611, + 'Zcaron': 611, + 'greaterequal': 549, + 'Eth': 722, + 'Ccedilla': 722, + 'lcommaaccent': 278, + 'tcaron': 389, + 'eogonek': 556, + 'Uogonek': 722, + 'Aacute': 722, + 'Adieresis': 722, + 'egrave': 556, + 'zacute': 500, + 'iogonek': 278, + 'Oacute': 778, + 'oacute': 611, + 'amacron': 556, + 'sacute': 556, + 'idieresis': 278, + 'Ocircumflex': 778, + 'Ugrave': 722, + 'Delta': 612, + 'thorn': 611, + 'twosuperior': 333, + 'Odieresis': 778, + 'mu': 611, + 'igrave': 278, + 'ohungarumlaut': 611, + 'Eogonek': 667, + 'dcroat': 611, + 'threequarters': 834, + 'Scedilla': 667, + 'lcaron': 400, + 'Kcommaaccent': 722, + 'Lacute': 611, + 'trademark': 1000, + 'edotaccent': 556, + 'Igrave': 278, + 'Imacron': 278, + 'Lcaron': 611, + 'onehalf': 834, + 'lessequal': 549, + 'ocircumflex': 611, + 'ntilde': 611, + 'Uhungarumlaut': 722, + 'Eacute': 667, + 'emacron': 556, + 'gbreve': 611, + 'onequarter': 834, + 'Scaron': 667, + 'Scommaaccent': 667, + 'Ohungarumlaut': 778, + 'degree': 400, + 'ograve': 611, + 'Ccaron': 722, + 'ugrave': 611, + 'radical': 549, + 'Dcaron': 722, + 'rcommaaccent': 389, + 'Ntilde': 722, + 'otilde': 611, + 'Rcommaaccent': 722, + 'Lcommaaccent': 611, + 'Atilde': 722, + 'Aogonek': 722, + 'Aring': 722, + 'Otilde': 778, + 'zdotaccent': 500, + 'Ecaron': 667, + 'Iogonek': 278, + 'kcommaaccent': 556, + 'minus': 584, + 'Icircumflex': 278, + 'ncaron': 611, + 'tcommaaccent': 333, + 'logicalnot': 584, + 'odieresis': 611, + 'udieresis': 611, + 'notequal': 549, + 'gcommaaccent': 611, + 'eth': 611, + 'zcaron': 500, + 'ncommaaccent': 611, + 'onesuperior': 333, + 'imacron': 278, + 'Euro': 556 + }, + 'Helvetica-Oblique' : { + 'space': 278, + 'exclam': 278, + 'quotedbl': 355, + 'numbersign': 556, + 'dollar': 556, + 'percent': 889, + 'ampersand': 667, + 'quoteright': 222, + 'parenleft': 333, + 'parenright': 333, + 'asterisk': 389, + 'plus': 584, + 'comma': 278, + 'hyphen': 333, + 'period': 278, + 'slash': 278, + 'zero': 556, + 'one': 556, + 'two': 556, + 'three': 556, + 'four': 556, + 'five': 556, + 'six': 556, + 'seven': 556, + 'eight': 556, + 'nine': 556, + 'colon': 278, + 'semicolon': 278, + 'less': 584, + 'equal': 584, + 'greater': 584, + 'question': 556, + 'at': 1015, + 'A': 667, + 'B': 667, + 'C': 722, + 'D': 722, + 'E': 667, + 'F': 611, + 'G': 778, + 'H': 722, + 'I': 278, + 'J': 500, + 'K': 667, + 'L': 556, + 'M': 833, + 'N': 722, + 'O': 778, + 'P': 667, + 'Q': 778, + 'R': 722, + 'S': 667, + 'T': 611, + 'U': 722, + 'V': 667, + 'W': 944, + 'X': 667, + 'Y': 667, + 'Z': 611, + 'bracketleft': 278, + 'backslash': 278, + 'bracketright': 278, + 'asciicircum': 469, + 'underscore': 556, + 'quoteleft': 222, + 'a': 556, + 'b': 556, + 'c': 500, + 'd': 556, + 'e': 556, + 'f': 278, + 'g': 556, + 'h': 556, + 'i': 222, + 'j': 222, + 'k': 500, + 'l': 222, + 'm': 833, + 'n': 556, + 'o': 556, + 'p': 556, + 'q': 556, + 'r': 333, + 's': 500, + 't': 278, + 'u': 556, + 'v': 500, + 'w': 722, + 'x': 500, + 'y': 500, + 'z': 500, + 'braceleft': 334, + 'bar': 260, + 'braceright': 334, + 'asciitilde': 584, + 'exclamdown': 333, + 'cent': 556, + 'sterling': 556, + 'fraction': 167, + 'yen': 556, + 'florin': 556, + 'section': 556, + 'currency': 556, + 'quotesingle': 191, + 'quotedblleft': 333, + 'guillemotleft': 556, + 'guilsinglleft': 333, + 'guilsinglright': 333, + 'fi': 500, + 'fl': 500, + 'endash': 556, + 'dagger': 556, + 'daggerdbl': 556, + 'periodcentered': 278, + 'paragraph': 537, + 'bullet': 350, + 'quotesinglbase': 222, + 'quotedblbase': 333, + 'quotedblright': 333, + 'guillemotright': 556, + 'ellipsis': 1000, + 'perthousand': 1000, + 'questiondown': 611, + 'grave': 333, + 'acute': 333, + 'circumflex': 333, + 'tilde': 333, + 'macron': 333, + 'breve': 333, + 'dotaccent': 333, + 'dieresis': 333, + 'ring': 333, + 'cedilla': 333, + 'hungarumlaut': 333, + 'ogonek': 333, + 'caron': 333, + 'emdash': 1000, + 'AE': 1000, + 'ordfeminine': 370, + 'Lslash': 556, + 'Oslash': 778, + 'OE': 1000, + 'ordmasculine': 365, + 'ae': 889, + 'dotlessi': 278, + 'lslash': 222, + 'oslash': 611, + 'oe': 944, + 'germandbls': 611, + 'Idieresis': 278, + 'eacute': 556, + 'abreve': 556, + 'uhungarumlaut': 556, + 'ecaron': 556, + 'Ydieresis': 667, + 'divide': 584, + 'Yacute': 667, + 'Acircumflex': 667, + 'aacute': 556, + 'Ucircumflex': 722, + 'yacute': 500, + 'scommaaccent': 500, + 'ecircumflex': 556, + 'Uring': 722, + 'Udieresis': 722, + 'aogonek': 556, + 'Uacute': 722, + 'uogonek': 556, + 'Edieresis': 667, + 'Dcroat': 722, + 'commaaccent': 250, + 'copyright': 737, + 'Emacron': 667, + 'ccaron': 500, + 'aring': 556, + 'Ncommaaccent': 722, + 'lacute': 222, + 'agrave': 556, + 'Tcommaaccent': 611, + 'Cacute': 722, + 'atilde': 556, + 'Edotaccent': 667, + 'scaron': 500, + 'scedilla': 500, + 'iacute': 278, + 'lozenge': 471, + 'Rcaron': 722, + 'Gcommaaccent': 778, + 'ucircumflex': 556, + 'acircumflex': 556, + 'Amacron': 667, + 'rcaron': 333, + 'ccedilla': 500, + 'Zdotaccent': 611, + 'Thorn': 667, + 'Omacron': 778, + 'Racute': 722, + 'Sacute': 667, + 'dcaron': 643, + 'Umacron': 722, + 'uring': 556, + 'threesuperior': 333, + 'Ograve': 778, + 'Agrave': 667, + 'Abreve': 667, + 'multiply': 584, + 'uacute': 556, + 'Tcaron': 611, + 'partialdiff': 476, + 'ydieresis': 500, + 'Nacute': 722, + 'icircumflex': 278, + 'Ecircumflex': 667, + 'adieresis': 556, + 'edieresis': 556, + 'cacute': 500, + 'nacute': 556, + 'umacron': 556, + 'Ncaron': 722, + 'Iacute': 278, + 'plusminus': 584, + 'brokenbar': 260, + 'registered': 737, + 'Gbreve': 778, + 'Idotaccent': 278, + 'summation': 600, + 'Egrave': 667, + 'racute': 333, + 'omacron': 556, + 'Zacute': 611, + 'Zcaron': 611, + 'greaterequal': 549, + 'Eth': 722, + 'Ccedilla': 722, + 'lcommaaccent': 222, + 'tcaron': 317, + 'eogonek': 556, + 'Uogonek': 722, + 'Aacute': 667, + 'Adieresis': 667, + 'egrave': 556, + 'zacute': 500, + 'iogonek': 222, + 'Oacute': 778, + 'oacute': 556, + 'amacron': 556, + 'sacute': 500, + 'idieresis': 278, + 'Ocircumflex': 778, + 'Ugrave': 722, + 'Delta': 612, + 'thorn': 556, + 'twosuperior': 333, + 'Odieresis': 778, + 'mu': 556, + 'igrave': 278, + 'ohungarumlaut': 556, + 'Eogonek': 667, + 'dcroat': 556, + 'threequarters': 834, + 'Scedilla': 667, + 'lcaron': 299, + 'Kcommaaccent': 667, + 'Lacute': 556, + 'trademark': 1000, + 'edotaccent': 556, + 'Igrave': 278, + 'Imacron': 278, + 'Lcaron': 556, + 'onehalf': 834, + 'lessequal': 549, + 'ocircumflex': 556, + 'ntilde': 556, + 'Uhungarumlaut': 722, + 'Eacute': 667, + 'emacron': 556, + 'gbreve': 556, + 'onequarter': 834, + 'Scaron': 667, + 'Scommaaccent': 667, + 'Ohungarumlaut': 778, + 'degree': 400, + 'ograve': 556, + 'Ccaron': 722, + 'ugrave': 556, + 'radical': 453, + 'Dcaron': 722, + 'rcommaaccent': 333, + 'Ntilde': 722, + 'otilde': 556, + 'Rcommaaccent': 722, + 'Lcommaaccent': 556, + 'Atilde': 667, + 'Aogonek': 667, + 'Aring': 667, + 'Otilde': 778, + 'zdotaccent': 500, + 'Ecaron': 667, + 'Iogonek': 278, + 'kcommaaccent': 500, + 'minus': 584, + 'Icircumflex': 278, + 'ncaron': 556, + 'tcommaaccent': 278, + 'logicalnot': 584, + 'odieresis': 556, + 'udieresis': 556, + 'notequal': 549, + 'gcommaaccent': 556, + 'eth': 556, + 'zcaron': 500, + 'ncommaaccent': 556, + 'onesuperior': 333, + 'imacron': 278, + 'Euro': 556 + }, + 'Symbol': { + 'space': 250, + 'exclam': 333, + 'universal': 713, + 'numbersign': 500, + 'existential': 549, + 'percent': 833, + 'ampersand': 778, + 'suchthat': 439, + 'parenleft': 333, + 'parenright': 333, + 'asteriskmath': 500, + 'plus': 549, + 'comma': 250, + 'minus': 549, + 'period': 250, + 'slash': 278, + 'zero': 500, + 'one': 500, + 'two': 500, + 'three': 500, + 'four': 500, + 'five': 500, + 'six': 500, + 'seven': 500, + 'eight': 500, + 'nine': 500, + 'colon': 278, + 'semicolon': 278, + 'less': 549, + 'equal': 549, + 'greater': 549, + 'question': 444, + 'congruent': 549, + 'Alpha': 722, + 'Beta': 667, + 'Chi': 722, + 'Delta': 612, + 'Epsilon': 611, + 'Phi': 763, + 'Gamma': 603, + 'Eta': 722, + 'Iota': 333, + 'theta1': 631, + 'Kappa': 722, + 'Lambda': 686, + 'Mu': 889, + 'Nu': 722, + 'Omicron': 722, + 'Pi': 768, + 'Theta': 741, + 'Rho': 556, + 'Sigma': 592, + 'Tau': 611, + 'Upsilon': 690, + 'sigma1': 439, + 'Omega': 768, + 'Xi': 645, + 'Psi': 795, + 'Zeta': 611, + 'bracketleft': 333, + 'therefore': 863, + 'bracketright': 333, + 'perpendicular': 658, + 'underscore': 500, + 'radicalex': 500, + 'alpha': 631, + 'beta': 549, + 'chi': 549, + 'delta': 494, + 'epsilon': 439, + 'phi': 521, + 'gamma': 411, + 'eta': 603, + 'iota': 329, + 'phi1': 603, + 'kappa': 549, + 'lambda': 549, + 'mu': 576, + 'nu': 521, + 'omicron': 549, + 'pi': 549, + 'theta': 521, + 'rho': 549, + 'sigma': 603, + 'tau': 439, + 'upsilon': 576, + 'omega1': 713, + 'omega': 686, + 'xi': 493, + 'psi': 686, + 'zeta': 494, + 'braceleft': 480, + 'bar': 200, + 'braceright': 480, + 'similar': 549, + 'Euro': 750, + 'Upsilon1': 620, + 'minute': 247, + 'lessequal': 549, + 'fraction': 167, + 'infinity': 713, + 'florin': 500, + 'club': 753, + 'diamond': 753, + 'heart': 753, + 'spade': 753, + 'arrowboth': 1042, + 'arrowleft': 987, + 'arrowup': 603, + 'arrowright': 987, + 'arrowdown': 603, + 'degree': 400, + 'plusminus': 549, + 'second': 411, + 'greaterequal': 549, + 'multiply': 549, + 'proportional': 713, + 'partialdiff': 494, + 'bullet': 460, + 'divide': 549, + 'notequal': 549, + 'equivalence': 549, + 'approxequal': 549, + 'ellipsis': 1000, + 'arrowvertex': 603, + 'arrowhorizex': 1000, + 'carriagereturn': 658, + 'aleph': 823, + 'Ifraktur': 686, + 'Rfraktur': 795, + 'weierstrass': 987, + 'circlemultiply': 768, + 'circleplus': 768, + 'emptyset': 823, + 'intersection': 768, + 'union': 768, + 'propersuperset': 713, + 'reflexsuperset': 713, + 'notsubset': 713, + 'propersubset': 713, + 'reflexsubset': 713, + 'element': 713, + 'notelement': 713, + 'angle': 768, + 'gradient': 713, + 'registerserif': 790, + 'copyrightserif': 790, + 'trademarkserif': 890, + 'product': 823, + 'radical': 549, + 'dotmath': 250, + 'logicalnot': 713, + 'logicaland': 603, + 'logicalor': 603, + 'arrowdblboth': 1042, + 'arrowdblleft': 987, + 'arrowdblup': 603, + 'arrowdblright': 987, + 'arrowdbldown': 603, + 'lozenge': 494, + 'angleleft': 329, + 'registersans': 790, + 'copyrightsans': 790, + 'trademarksans': 786, + 'summation': 713, + 'parenlefttp': 384, + 'parenleftex': 384, + 'parenleftbt': 384, + 'bracketlefttp': 384, + 'bracketleftex': 384, + 'bracketleftbt': 384, + 'bracelefttp': 494, + 'braceleftmid': 494, + 'braceleftbt': 494, + 'braceex': 494, + 'angleright': 329, + 'integral': 274, + 'integraltp': 686, + 'integralex': 686, + 'integralbt': 686, + 'parenrighttp': 384, + 'parenrightex': 384, + 'parenrightbt': 384, + 'bracketrighttp': 384, + 'bracketrightex': 384, + 'bracketrightbt': 384, + 'bracerighttp': 494, + 'bracerightmid': 494, + 'bracerightbt': 494, + 'apple': 790 + }, + 'Times-Roman': { + 'space': 250, + 'exclam': 333, + 'quotedbl': 408, + 'numbersign': 500, + 'dollar': 500, + 'percent': 833, + 'ampersand': 778, + 'quoteright': 333, + 'parenleft': 333, + 'parenright': 333, + 'asterisk': 500, + 'plus': 564, + 'comma': 250, + 'hyphen': 333, + 'period': 250, + 'slash': 278, + 'zero': 500, + 'one': 500, + 'two': 500, + 'three': 500, + 'four': 500, + 'five': 500, + 'six': 500, + 'seven': 500, + 'eight': 500, + 'nine': 500, + 'colon': 278, + 'semicolon': 278, + 'less': 564, + 'equal': 564, + 'greater': 564, + 'question': 444, + 'at': 921, + 'A': 722, + 'B': 667, + 'C': 667, + 'D': 722, + 'E': 611, + 'F': 556, + 'G': 722, + 'H': 722, + 'I': 333, + 'J': 389, + 'K': 722, + 'L': 611, + 'M': 889, + 'N': 722, + 'O': 722, + 'P': 556, + 'Q': 722, + 'R': 667, + 'S': 556, + 'T': 611, + 'U': 722, + 'V': 722, + 'W': 944, + 'X': 722, + 'Y': 722, + 'Z': 611, + 'bracketleft': 333, + 'backslash': 278, + 'bracketright': 333, + 'asciicircum': 469, + 'underscore': 500, + 'quoteleft': 333, + 'a': 444, + 'b': 500, + 'c': 444, + 'd': 500, + 'e': 444, + 'f': 333, + 'g': 500, + 'h': 500, + 'i': 278, + 'j': 278, + 'k': 500, + 'l': 278, + 'm': 778, + 'n': 500, + 'o': 500, + 'p': 500, + 'q': 500, + 'r': 333, + 's': 389, + 't': 278, + 'u': 500, + 'v': 500, + 'w': 722, + 'x': 500, + 'y': 500, + 'z': 444, + 'braceleft': 480, + 'bar': 200, + 'braceright': 480, + 'asciitilde': 541, + 'exclamdown': 333, + 'cent': 500, + 'sterling': 500, + 'fraction': 167, + 'yen': 500, + 'florin': 500, + 'section': 500, + 'currency': 500, + 'quotesingle': 180, + 'quotedblleft': 444, + 'guillemotleft': 500, + 'guilsinglleft': 333, + 'guilsinglright': 333, + 'fi': 556, + 'fl': 556, + 'endash': 500, + 'dagger': 500, + 'daggerdbl': 500, + 'periodcentered': 250, + 'paragraph': 453, + 'bullet': 350, + 'quotesinglbase': 333, + 'quotedblbase': 444, + 'quotedblright': 444, + 'guillemotright': 500, + 'ellipsis': 1000, + 'perthousand': 1000, + 'questiondown': 444, + 'grave': 333, + 'acute': 333, + 'circumflex': 333, + 'tilde': 333, + 'macron': 333, + 'breve': 333, + 'dotaccent': 333, + 'dieresis': 333, + 'ring': 333, + 'cedilla': 333, + 'hungarumlaut': 333, + 'ogonek': 333, + 'caron': 333, + 'emdash': 1000, + 'AE': 889, + 'ordfeminine': 276, + 'Lslash': 611, + 'Oslash': 722, + 'OE': 889, + 'ordmasculine': 310, + 'ae': 667, + 'dotlessi': 278, + 'lslash': 278, + 'oslash': 500, + 'oe': 722, + 'germandbls': 500, + 'Idieresis': 333, + 'eacute': 444, + 'abreve': 444, + 'uhungarumlaut': 500, + 'ecaron': 444, + 'Ydieresis': 722, + 'divide': 564, + 'Yacute': 722, + 'Acircumflex': 722, + 'aacute': 444, + 'Ucircumflex': 722, + 'yacute': 500, + 'scommaaccent': 389, + 'ecircumflex': 444, + 'Uring': 722, + 'Udieresis': 722, + 'aogonek': 444, + 'Uacute': 722, + 'uogonek': 500, + 'Edieresis': 611, + 'Dcroat': 722, + 'commaaccent': 250, + 'copyright': 760, + 'Emacron': 611, + 'ccaron': 444, + 'aring': 444, + 'Ncommaaccent': 722, + 'lacute': 278, + 'agrave': 444, + 'Tcommaaccent': 611, + 'Cacute': 667, + 'atilde': 444, + 'Edotaccent': 611, + 'scaron': 389, + 'scedilla': 389, + 'iacute': 278, + 'lozenge': 471, + 'Rcaron': 667, + 'Gcommaaccent': 722, + 'ucircumflex': 500, + 'acircumflex': 444, + 'Amacron': 722, + 'rcaron': 333, + 'ccedilla': 444, + 'Zdotaccent': 611, + 'Thorn': 556, + 'Omacron': 722, + 'Racute': 667, + 'Sacute': 556, + 'dcaron': 588, + 'Umacron': 722, + 'uring': 500, + 'threesuperior': 300, + 'Ograve': 722, + 'Agrave': 722, + 'Abreve': 722, + 'multiply': 564, + 'uacute': 500, + 'Tcaron': 611, + 'partialdiff': 476, + 'ydieresis': 500, + 'Nacute': 722, + 'icircumflex': 278, + 'Ecircumflex': 611, + 'adieresis': 444, + 'edieresis': 444, + 'cacute': 444, + 'nacute': 500, + 'umacron': 500, + 'Ncaron': 722, + 'Iacute': 333, + 'plusminus': 564, + 'brokenbar': 200, + 'registered': 760, + 'Gbreve': 722, + 'Idotaccent': 333, + 'summation': 600, + 'Egrave': 611, + 'racute': 333, + 'omacron': 500, + 'Zacute': 611, + 'Zcaron': 611, + 'greaterequal': 549, + 'Eth': 722, + 'Ccedilla': 667, + 'lcommaaccent': 278, + 'tcaron': 326, + 'eogonek': 444, + 'Uogonek': 722, + 'Aacute': 722, + 'Adieresis': 722, + 'egrave': 444, + 'zacute': 444, + 'iogonek': 278, + 'Oacute': 722, + 'oacute': 500, + 'amacron': 444, + 'sacute': 389, + 'idieresis': 278, + 'Ocircumflex': 722, + 'Ugrave': 722, + 'Delta': 612, + 'thorn': 500, + 'twosuperior': 300, + 'Odieresis': 722, + 'mu': 500, + 'igrave': 278, + 'ohungarumlaut': 500, + 'Eogonek': 611, + 'dcroat': 500, + 'threequarters': 750, + 'Scedilla': 556, + 'lcaron': 344, + 'Kcommaaccent': 722, + 'Lacute': 611, + 'trademark': 980, + 'edotaccent': 444, + 'Igrave': 333, + 'Imacron': 333, + 'Lcaron': 611, + 'onehalf': 750, + 'lessequal': 549, + 'ocircumflex': 500, + 'ntilde': 500, + 'Uhungarumlaut': 722, + 'Eacute': 611, + 'emacron': 444, + 'gbreve': 500, + 'onequarter': 750, + 'Scaron': 556, + 'Scommaaccent': 556, + 'Ohungarumlaut': 722, + 'degree': 400, + 'ograve': 500, + 'Ccaron': 667, + 'ugrave': 500, + 'radical': 453, + 'Dcaron': 722, + 'rcommaaccent': 333, + 'Ntilde': 722, + 'otilde': 500, + 'Rcommaaccent': 667, + 'Lcommaaccent': 611, + 'Atilde': 722, + 'Aogonek': 722, + 'Aring': 722, + 'Otilde': 722, + 'zdotaccent': 444, + 'Ecaron': 611, + 'Iogonek': 333, + 'kcommaaccent': 500, + 'minus': 564, + 'Icircumflex': 333, + 'ncaron': 500, + 'tcommaaccent': 278, + 'logicalnot': 564, + 'odieresis': 500, + 'udieresis': 500, + 'notequal': 549, + 'gcommaaccent': 500, + 'eth': 500, + 'zcaron': 444, + 'ncommaaccent': 500, + 'onesuperior': 300, + 'imacron': 278, + 'Euro': 500 + }, + 'Times-Bold': { + 'space': 250, + 'exclam': 333, + 'quotedbl': 555, + 'numbersign': 500, + 'dollar': 500, + 'percent': 1000, + 'ampersand': 833, + 'quoteright': 333, + 'parenleft': 333, + 'parenright': 333, + 'asterisk': 500, + 'plus': 570, + 'comma': 250, + 'hyphen': 333, + 'period': 250, + 'slash': 278, + 'zero': 500, + 'one': 500, + 'two': 500, + 'three': 500, + 'four': 500, + 'five': 500, + 'six': 500, + 'seven': 500, + 'eight': 500, + 'nine': 500, + 'colon': 333, + 'semicolon': 333, + 'less': 570, + 'equal': 570, + 'greater': 570, + 'question': 500, + 'at': 930, + 'A': 722, + 'B': 667, + 'C': 722, + 'D': 722, + 'E': 667, + 'F': 611, + 'G': 778, + 'H': 778, + 'I': 389, + 'J': 500, + 'K': 778, + 'L': 667, + 'M': 944, + 'N': 722, + 'O': 778, + 'P': 611, + 'Q': 778, + 'R': 722, + 'S': 556, + 'T': 667, + 'U': 722, + 'V': 722, + 'W': 1000, + 'X': 722, + 'Y': 722, + 'Z': 667, + 'bracketleft': 333, + 'backslash': 278, + 'bracketright': 333, + 'asciicircum': 581, + 'underscore': 500, + 'quoteleft': 333, + 'a': 500, + 'b': 556, + 'c': 444, + 'd': 556, + 'e': 444, + 'f': 333, + 'g': 500, + 'h': 556, + 'i': 278, + 'j': 333, + 'k': 556, + 'l': 278, + 'm': 833, + 'n': 556, + 'o': 500, + 'p': 556, + 'q': 556, + 'r': 444, + 's': 389, + 't': 333, + 'u': 556, + 'v': 500, + 'w': 722, + 'x': 500, + 'y': 500, + 'z': 444, + 'braceleft': 394, + 'bar': 220, + 'braceright': 394, + 'asciitilde': 520, + 'exclamdown': 333, + 'cent': 500, + 'sterling': 500, + 'fraction': 167, + 'yen': 500, + 'florin': 500, + 'section': 500, + 'currency': 500, + 'quotesingle': 278, + 'quotedblleft': 500, + 'guillemotleft': 500, + 'guilsinglleft': 333, + 'guilsinglright': 333, + 'fi': 556, + 'fl': 556, + 'endash': 500, + 'dagger': 500, + 'daggerdbl': 500, + 'periodcentered': 250, + 'paragraph': 540, + 'bullet': 350, + 'quotesinglbase': 333, + 'quotedblbase': 500, + 'quotedblright': 500, + 'guillemotright': 500, + 'ellipsis': 1000, + 'perthousand': 1000, + 'questiondown': 500, + 'grave': 333, + 'acute': 333, + 'circumflex': 333, + 'tilde': 333, + 'macron': 333, + 'breve': 333, + 'dotaccent': 333, + 'dieresis': 333, + 'ring': 333, + 'cedilla': 333, + 'hungarumlaut': 333, + 'ogonek': 333, + 'caron': 333, + 'emdash': 1000, + 'AE': 1000, + 'ordfeminine': 300, + 'Lslash': 667, + 'Oslash': 778, + 'OE': 1000, + 'ordmasculine': 330, + 'ae': 722, + 'dotlessi': 278, + 'lslash': 278, + 'oslash': 500, + 'oe': 722, + 'germandbls': 556, + 'Idieresis': 389, + 'eacute': 444, + 'abreve': 500, + 'uhungarumlaut': 556, + 'ecaron': 444, + 'Ydieresis': 722, + 'divide': 570, + 'Yacute': 722, + 'Acircumflex': 722, + 'aacute': 500, + 'Ucircumflex': 722, + 'yacute': 500, + 'scommaaccent': 389, + 'ecircumflex': 444, + 'Uring': 722, + 'Udieresis': 722, + 'aogonek': 500, + 'Uacute': 722, + 'uogonek': 556, + 'Edieresis': 667, + 'Dcroat': 722, + 'commaaccent': 250, + 'copyright': 747, + 'Emacron': 667, + 'ccaron': 444, + 'aring': 500, + 'Ncommaaccent': 722, + 'lacute': 278, + 'agrave': 500, + 'Tcommaaccent': 667, + 'Cacute': 722, + 'atilde': 500, + 'Edotaccent': 667, + 'scaron': 389, + 'scedilla': 389, + 'iacute': 278, + 'lozenge': 494, + 'Rcaron': 722, + 'Gcommaaccent': 778, + 'ucircumflex': 556, + 'acircumflex': 500, + 'Amacron': 722, + 'rcaron': 444, + 'ccedilla': 444, + 'Zdotaccent': 667, + 'Thorn': 611, + 'Omacron': 778, + 'Racute': 722, + 'Sacute': 556, + 'dcaron': 672, + 'Umacron': 722, + 'uring': 556, + 'threesuperior': 300, + 'Ograve': 778, + 'Agrave': 722, + 'Abreve': 722, + 'multiply': 570, + 'uacute': 556, + 'Tcaron': 667, + 'partialdiff': 494, + 'ydieresis': 500, + 'Nacute': 722, + 'icircumflex': 278, + 'Ecircumflex': 667, + 'adieresis': 500, + 'edieresis': 444, + 'cacute': 444, + 'nacute': 556, + 'umacron': 556, + 'Ncaron': 722, + 'Iacute': 389, + 'plusminus': 570, + 'brokenbar': 220, + 'registered': 747, + 'Gbreve': 778, + 'Idotaccent': 389, + 'summation': 600, + 'Egrave': 667, + 'racute': 444, + 'omacron': 500, + 'Zacute': 667, + 'Zcaron': 667, + 'greaterequal': 549, + 'Eth': 722, + 'Ccedilla': 722, + 'lcommaaccent': 278, + 'tcaron': 416, + 'eogonek': 444, + 'Uogonek': 722, + 'Aacute': 722, + 'Adieresis': 722, + 'egrave': 444, + 'zacute': 444, + 'iogonek': 278, + 'Oacute': 778, + 'oacute': 500, + 'amacron': 500, + 'sacute': 389, + 'idieresis': 278, + 'Ocircumflex': 778, + 'Ugrave': 722, + 'Delta': 612, + 'thorn': 556, + 'twosuperior': 300, + 'Odieresis': 778, + 'mu': 556, + 'igrave': 278, + 'ohungarumlaut': 500, + 'Eogonek': 667, + 'dcroat': 556, + 'threequarters': 750, + 'Scedilla': 556, + 'lcaron': 394, + 'Kcommaaccent': 778, + 'Lacute': 667, + 'trademark': 1000, + 'edotaccent': 444, + 'Igrave': 389, + 'Imacron': 389, + 'Lcaron': 667, + 'onehalf': 750, + 'lessequal': 549, + 'ocircumflex': 500, + 'ntilde': 556, + 'Uhungarumlaut': 722, + 'Eacute': 667, + 'emacron': 444, + 'gbreve': 500, + 'onequarter': 750, + 'Scaron': 556, + 'Scommaaccent': 556, + 'Ohungarumlaut': 778, + 'degree': 400, + 'ograve': 500, + 'Ccaron': 722, + 'ugrave': 556, + 'radical': 549, + 'Dcaron': 722, + 'rcommaaccent': 444, + 'Ntilde': 722, + 'otilde': 500, + 'Rcommaaccent': 722, + 'Lcommaaccent': 667, + 'Atilde': 722, + 'Aogonek': 722, + 'Aring': 722, + 'Otilde': 778, + 'zdotaccent': 444, + 'Ecaron': 667, + 'Iogonek': 389, + 'kcommaaccent': 556, + 'minus': 570, + 'Icircumflex': 389, + 'ncaron': 556, + 'tcommaaccent': 333, + 'logicalnot': 570, + 'odieresis': 500, + 'udieresis': 556, + 'notequal': 549, + 'gcommaaccent': 500, + 'eth': 500, + 'zcaron': 444, + 'ncommaaccent': 556, + 'onesuperior': 300, + 'imacron': 278, + 'Euro': 500 + }, + 'Times-BoldItalic': { + 'space': 250, + 'exclam': 389, + 'quotedbl': 555, + 'numbersign': 500, + 'dollar': 500, + 'percent': 833, + 'ampersand': 778, + 'quoteright': 333, + 'parenleft': 333, + 'parenright': 333, + 'asterisk': 500, + 'plus': 570, + 'comma': 250, + 'hyphen': 333, + 'period': 250, + 'slash': 278, + 'zero': 500, + 'one': 500, + 'two': 500, + 'three': 500, + 'four': 500, + 'five': 500, + 'six': 500, + 'seven': 500, + 'eight': 500, + 'nine': 500, + 'colon': 333, + 'semicolon': 333, + 'less': 570, + 'equal': 570, + 'greater': 570, + 'question': 500, + 'at': 832, + 'A': 667, + 'B': 667, + 'C': 667, + 'D': 722, + 'E': 667, + 'F': 667, + 'G': 722, + 'H': 778, + 'I': 389, + 'J': 500, + 'K': 667, + 'L': 611, + 'M': 889, + 'N': 722, + 'O': 722, + 'P': 611, + 'Q': 722, + 'R': 667, + 'S': 556, + 'T': 611, + 'U': 722, + 'V': 667, + 'W': 889, + 'X': 667, + 'Y': 611, + 'Z': 611, + 'bracketleft': 333, + 'backslash': 278, + 'bracketright': 333, + 'asciicircum': 570, + 'underscore': 500, + 'quoteleft': 333, + 'a': 500, + 'b': 500, + 'c': 444, + 'd': 500, + 'e': 444, + 'f': 333, + 'g': 500, + 'h': 556, + 'i': 278, + 'j': 278, + 'k': 500, + 'l': 278, + 'm': 778, + 'n': 556, + 'o': 500, + 'p': 500, + 'q': 500, + 'r': 389, + 's': 389, + 't': 278, + 'u': 556, + 'v': 444, + 'w': 667, + 'x': 500, + 'y': 444, + 'z': 389, + 'braceleft': 348, + 'bar': 220, + 'braceright': 348, + 'asciitilde': 570, + 'exclamdown': 389, + 'cent': 500, + 'sterling': 500, + 'fraction': 167, + 'yen': 500, + 'florin': 500, + 'section': 500, + 'currency': 500, + 'quotesingle': 278, + 'quotedblleft': 500, + 'guillemotleft': 500, + 'guilsinglleft': 333, + 'guilsinglright': 333, + 'fi': 556, + 'fl': 556, + 'endash': 500, + 'dagger': 500, + 'daggerdbl': 500, + 'periodcentered': 250, + 'paragraph': 500, + 'bullet': 350, + 'quotesinglbase': 333, + 'quotedblbase': 500, + 'quotedblright': 500, + 'guillemotright': 500, + 'ellipsis': 1000, + 'perthousand': 1000, + 'questiondown': 500, + 'grave': 333, + 'acute': 333, + 'circumflex': 333, + 'tilde': 333, + 'macron': 333, + 'breve': 333, + 'dotaccent': 333, + 'dieresis': 333, + 'ring': 333, + 'cedilla': 333, + 'hungarumlaut': 333, + 'ogonek': 333, + 'caron': 333, + 'emdash': 1000, + 'AE': 944, + 'ordfeminine': 266, + 'Lslash': 611, + 'Oslash': 722, + 'OE': 944, + 'ordmasculine': 300, + 'ae': 722, + 'dotlessi': 278, + 'lslash': 278, + 'oslash': 500, + 'oe': 722, + 'germandbls': 500, + 'Idieresis': 389, + 'eacute': 444, + 'abreve': 500, + 'uhungarumlaut': 556, + 'ecaron': 444, + 'Ydieresis': 611, + 'divide': 570, + 'Yacute': 611, + 'Acircumflex': 667, + 'aacute': 500, + 'Ucircumflex': 722, + 'yacute': 444, + 'scommaaccent': 389, + 'ecircumflex': 444, + 'Uring': 722, + 'Udieresis': 722, + 'aogonek': 500, + 'Uacute': 722, + 'uogonek': 556, + 'Edieresis': 667, + 'Dcroat': 722, + 'commaaccent': 250, + 'copyright': 747, + 'Emacron': 667, + 'ccaron': 444, + 'aring': 500, + 'Ncommaaccent': 722, + 'lacute': 278, + 'agrave': 500, + 'Tcommaaccent': 611, + 'Cacute': 667, + 'atilde': 500, + 'Edotaccent': 667, + 'scaron': 389, + 'scedilla': 389, + 'iacute': 278, + 'lozenge': 494, + 'Rcaron': 667, + 'Gcommaaccent': 722, + 'ucircumflex': 556, + 'acircumflex': 500, + 'Amacron': 667, + 'rcaron': 389, + 'ccedilla': 444, + 'Zdotaccent': 611, + 'Thorn': 611, + 'Omacron': 722, + 'Racute': 667, + 'Sacute': 556, + 'dcaron': 608, + 'Umacron': 722, + 'uring': 556, + 'threesuperior': 300, + 'Ograve': 722, + 'Agrave': 667, + 'Abreve': 667, + 'multiply': 570, + 'uacute': 556, + 'Tcaron': 611, + 'partialdiff': 494, + 'ydieresis': 444, + 'Nacute': 722, + 'icircumflex': 278, + 'Ecircumflex': 667, + 'adieresis': 500, + 'edieresis': 444, + 'cacute': 444, + 'nacute': 556, + 'umacron': 556, + 'Ncaron': 722, + 'Iacute': 389, + 'plusminus': 570, + 'brokenbar': 220, + 'registered': 747, + 'Gbreve': 722, + 'Idotaccent': 389, + 'summation': 600, + 'Egrave': 667, + 'racute': 389, + 'omacron': 500, + 'Zacute': 611, + 'Zcaron': 611, + 'greaterequal': 549, + 'Eth': 722, + 'Ccedilla': 667, + 'lcommaaccent': 278, + 'tcaron': 366, + 'eogonek': 444, + 'Uogonek': 722, + 'Aacute': 667, + 'Adieresis': 667, + 'egrave': 444, + 'zacute': 389, + 'iogonek': 278, + 'Oacute': 722, + 'oacute': 500, + 'amacron': 500, + 'sacute': 389, + 'idieresis': 278, + 'Ocircumflex': 722, + 'Ugrave': 722, + 'Delta': 612, + 'thorn': 500, + 'twosuperior': 300, + 'Odieresis': 722, + 'mu': 576, + 'igrave': 278, + 'ohungarumlaut': 500, + 'Eogonek': 667, + 'dcroat': 500, + 'threequarters': 750, + 'Scedilla': 556, + 'lcaron': 382, + 'Kcommaaccent': 667, + 'Lacute': 611, + 'trademark': 1000, + 'edotaccent': 444, + 'Igrave': 389, + 'Imacron': 389, + 'Lcaron': 611, + 'onehalf': 750, + 'lessequal': 549, + 'ocircumflex': 500, + 'ntilde': 556, + 'Uhungarumlaut': 722, + 'Eacute': 667, + 'emacron': 444, + 'gbreve': 500, + 'onequarter': 750, + 'Scaron': 556, + 'Scommaaccent': 556, + 'Ohungarumlaut': 722, + 'degree': 400, + 'ograve': 500, + 'Ccaron': 667, + 'ugrave': 556, + 'radical': 549, + 'Dcaron': 722, + 'rcommaaccent': 389, + 'Ntilde': 722, + 'otilde': 500, + 'Rcommaaccent': 667, + 'Lcommaaccent': 611, + 'Atilde': 667, + 'Aogonek': 667, + 'Aring': 667, + 'Otilde': 722, + 'zdotaccent': 389, + 'Ecaron': 667, + 'Iogonek': 389, + 'kcommaaccent': 500, + 'minus': 606, + 'Icircumflex': 389, + 'ncaron': 556, + 'tcommaaccent': 278, + 'logicalnot': 606, + 'odieresis': 500, + 'udieresis': 556, + 'notequal': 549, + 'gcommaaccent': 500, + 'eth': 500, + 'zcaron': 389, + 'ncommaaccent': 556, + 'onesuperior': 300, + 'imacron': 278, + 'Euro': 500 + }, + 'Times-Italic': { + 'space': 250, + 'exclam': 333, + 'quotedbl': 420, + 'numbersign': 500, + 'dollar': 500, + 'percent': 833, + 'ampersand': 778, + 'quoteright': 333, + 'parenleft': 333, + 'parenright': 333, + 'asterisk': 500, + 'plus': 675, + 'comma': 250, + 'hyphen': 333, + 'period': 250, + 'slash': 278, + 'zero': 500, + 'one': 500, + 'two': 500, + 'three': 500, + 'four': 500, + 'five': 500, + 'six': 500, + 'seven': 500, + 'eight': 500, + 'nine': 500, + 'colon': 333, + 'semicolon': 333, + 'less': 675, + 'equal': 675, + 'greater': 675, + 'question': 500, + 'at': 920, + 'A': 611, + 'B': 611, + 'C': 667, + 'D': 722, + 'E': 611, + 'F': 611, + 'G': 722, + 'H': 722, + 'I': 333, + 'J': 444, + 'K': 667, + 'L': 556, + 'M': 833, + 'N': 667, + 'O': 722, + 'P': 611, + 'Q': 722, + 'R': 611, + 'S': 500, + 'T': 556, + 'U': 722, + 'V': 611, + 'W': 833, + 'X': 611, + 'Y': 556, + 'Z': 556, + 'bracketleft': 389, + 'backslash': 278, + 'bracketright': 389, + 'asciicircum': 422, + 'underscore': 500, + 'quoteleft': 333, + 'a': 500, + 'b': 500, + 'c': 444, + 'd': 500, + 'e': 444, + 'f': 278, + 'g': 500, + 'h': 500, + 'i': 278, + 'j': 278, + 'k': 444, + 'l': 278, + 'm': 722, + 'n': 500, + 'o': 500, + 'p': 500, + 'q': 500, + 'r': 389, + 's': 389, + 't': 278, + 'u': 500, + 'v': 444, + 'w': 667, + 'x': 444, + 'y': 444, + 'z': 389, + 'braceleft': 400, + 'bar': 275, + 'braceright': 400, + 'asciitilde': 541, + 'exclamdown': 389, + 'cent': 500, + 'sterling': 500, + 'fraction': 167, + 'yen': 500, + 'florin': 500, + 'section': 500, + 'currency': 500, + 'quotesingle': 214, + 'quotedblleft': 556, + 'guillemotleft': 500, + 'guilsinglleft': 333, + 'guilsinglright': 333, + 'fi': 500, + 'fl': 500, + 'endash': 500, + 'dagger': 500, + 'daggerdbl': 500, + 'periodcentered': 250, + 'paragraph': 523, + 'bullet': 350, + 'quotesinglbase': 333, + 'quotedblbase': 556, + 'quotedblright': 556, + 'guillemotright': 500, + 'ellipsis': 889, + 'perthousand': 1000, + 'questiondown': 500, + 'grave': 333, + 'acute': 333, + 'circumflex': 333, + 'tilde': 333, + 'macron': 333, + 'breve': 333, + 'dotaccent': 333, + 'dieresis': 333, + 'ring': 333, + 'cedilla': 333, + 'hungarumlaut': 333, + 'ogonek': 333, + 'caron': 333, + 'emdash': 889, + 'AE': 889, + 'ordfeminine': 276, + 'Lslash': 556, + 'Oslash': 722, + 'OE': 944, + 'ordmasculine': 310, + 'ae': 667, + 'dotlessi': 278, + 'lslash': 278, + 'oslash': 500, + 'oe': 667, + 'germandbls': 500, + 'Idieresis': 333, + 'eacute': 444, + 'abreve': 500, + 'uhungarumlaut': 500, + 'ecaron': 444, + 'Ydieresis': 556, + 'divide': 675, + 'Yacute': 556, + 'Acircumflex': 611, + 'aacute': 500, + 'Ucircumflex': 722, + 'yacute': 444, + 'scommaaccent': 389, + 'ecircumflex': 444, + 'Uring': 722, + 'Udieresis': 722, + 'aogonek': 500, + 'Uacute': 722, + 'uogonek': 500, + 'Edieresis': 611, + 'Dcroat': 722, + 'commaaccent': 250, + 'copyright': 760, + 'Emacron': 611, + 'ccaron': 444, + 'aring': 500, + 'Ncommaaccent': 667, + 'lacute': 278, + 'agrave': 500, + 'Tcommaaccent': 556, + 'Cacute': 667, + 'atilde': 500, + 'Edotaccent': 611, + 'scaron': 389, + 'scedilla': 389, + 'iacute': 278, + 'lozenge': 471, + 'Rcaron': 611, + 'Gcommaaccent': 722, + 'ucircumflex': 500, + 'acircumflex': 500, + 'Amacron': 611, + 'rcaron': 389, + 'ccedilla': 444, + 'Zdotaccent': 556, + 'Thorn': 611, + 'Omacron': 722, + 'Racute': 611, + 'Sacute': 500, + 'dcaron': 544, + 'Umacron': 722, + 'uring': 500, + 'threesuperior': 300, + 'Ograve': 722, + 'Agrave': 611, + 'Abreve': 611, + 'multiply': 675, + 'uacute': 500, + 'Tcaron': 556, + 'partialdiff': 476, + 'ydieresis': 444, + 'Nacute': 667, + 'icircumflex': 278, + 'Ecircumflex': 611, + 'adieresis': 500, + 'edieresis': 444, + 'cacute': 444, + 'nacute': 500, + 'umacron': 500, + 'Ncaron': 667, + 'Iacute': 333, + 'plusminus': 675, + 'brokenbar': 275, + 'registered': 760, + 'Gbreve': 722, + 'Idotaccent': 333, + 'summation': 600, + 'Egrave': 611, + 'racute': 389, + 'omacron': 500, + 'Zacute': 556, + 'Zcaron': 556, + 'greaterequal': 549, + 'Eth': 722, + 'Ccedilla': 667, + 'lcommaaccent': 278, + 'tcaron': 300, + 'eogonek': 444, + 'Uogonek': 722, + 'Aacute': 611, + 'Adieresis': 611, + 'egrave': 444, + 'zacute': 389, + 'iogonek': 278, + 'Oacute': 722, + 'oacute': 500, + 'amacron': 500, + 'sacute': 389, + 'idieresis': 278, + 'Ocircumflex': 722, + 'Ugrave': 722, + 'Delta': 612, + 'thorn': 500, + 'twosuperior': 300, + 'Odieresis': 722, + 'mu': 500, + 'igrave': 278, + 'ohungarumlaut': 500, + 'Eogonek': 611, + 'dcroat': 500, + 'threequarters': 750, + 'Scedilla': 500, + 'lcaron': 300, + 'Kcommaaccent': 667, + 'Lacute': 556, + 'trademark': 980, + 'edotaccent': 444, + 'Igrave': 333, + 'Imacron': 333, + 'Lcaron': 611, + 'onehalf': 750, + 'lessequal': 549, + 'ocircumflex': 500, + 'ntilde': 500, + 'Uhungarumlaut': 722, + 'Eacute': 611, + 'emacron': 444, + 'gbreve': 500, + 'onequarter': 750, + 'Scaron': 500, + 'Scommaaccent': 500, + 'Ohungarumlaut': 722, + 'degree': 400, + 'ograve': 500, + 'Ccaron': 667, + 'ugrave': 500, + 'radical': 453, + 'Dcaron': 722, + 'rcommaaccent': 389, + 'Ntilde': 667, + 'otilde': 500, + 'Rcommaaccent': 611, + 'Lcommaaccent': 556, + 'Atilde': 611, + 'Aogonek': 611, + 'Aring': 611, + 'Otilde': 722, + 'zdotaccent': 389, + 'Ecaron': 611, + 'Iogonek': 333, + 'kcommaaccent': 444, + 'minus': 675, + 'Icircumflex': 333, + 'ncaron': 500, + 'tcommaaccent': 278, + 'logicalnot': 675, + 'odieresis': 500, + 'udieresis': 500, + 'notequal': 549, + 'gcommaaccent': 500, + 'eth': 500, + 'zcaron': 389, + 'ncommaaccent': 500, + 'onesuperior': 300, + 'imacron': 278, + 'Euro': 500 + }, + 'ZapfDingbats': { + 'space': 278, + 'a1': 974, + 'a2': 961, + 'a202': 974, + 'a3': 980, + 'a4': 719, + 'a5': 789, + 'a119': 790, + 'a118': 791, + 'a117': 690, + 'a11': 960, + 'a12': 939, + 'a13': 549, + 'a14': 855, + 'a15': 911, + 'a16': 933, + 'a105': 911, + 'a17': 945, + 'a18': 974, + 'a19': 755, + 'a20': 846, + 'a21': 762, + 'a22': 761, + 'a23': 571, + 'a24': 677, + 'a25': 763, + 'a26': 760, + 'a27': 759, + 'a28': 754, + 'a6': 494, + 'a7': 552, + 'a8': 537, + 'a9': 577, + 'a10': 692, + 'a29': 786, + 'a30': 788, + 'a31': 788, + 'a32': 790, + 'a33': 793, + 'a34': 794, + 'a35': 816, + 'a36': 823, + 'a37': 789, + 'a38': 841, + 'a39': 823, + 'a40': 833, + 'a41': 816, + 'a42': 831, + 'a43': 923, + 'a44': 744, + 'a45': 723, + 'a46': 749, + 'a47': 790, + 'a48': 792, + 'a49': 695, + 'a50': 776, + 'a51': 768, + 'a52': 792, + 'a53': 759, + 'a54': 707, + 'a55': 708, + 'a56': 682, + 'a57': 701, + 'a58': 826, + 'a59': 815, + 'a60': 789, + 'a61': 789, + 'a62': 707, + 'a63': 687, + 'a64': 696, + 'a65': 689, + 'a66': 786, + 'a67': 787, + 'a68': 713, + 'a69': 791, + 'a70': 785, + 'a71': 791, + 'a72': 873, + 'a73': 761, + 'a74': 762, + 'a203': 762, + 'a75': 759, + 'a204': 759, + 'a76': 892, + 'a77': 892, + 'a78': 788, + 'a79': 784, + 'a81': 438, + 'a82': 138, + 'a83': 277, + 'a84': 415, + 'a97': 392, + 'a98': 392, + 'a99': 668, + 'a100': 668, + 'a89': 390, + 'a90': 390, + 'a93': 317, + 'a94': 317, + 'a91': 276, + 'a92': 276, + 'a205': 509, + 'a85': 509, + 'a206': 410, + 'a86': 410, + 'a87': 234, + 'a88': 234, + 'a95': 334, + 'a96': 334, + 'a101': 732, + 'a102': 544, + 'a103': 544, + 'a104': 910, + 'a106': 667, + 'a107': 760, + 'a108': 760, + 'a112': 776, + 'a111': 595, + 'a110': 694, + 'a109': 626, + 'a120': 788, + 'a121': 788, + 'a122': 788, + 'a123': 788, + 'a124': 788, + 'a125': 788, + 'a126': 788, + 'a127': 788, + 'a128': 788, + 'a129': 788, + 'a130': 788, + 'a131': 788, + 'a132': 788, + 'a133': 788, + 'a134': 788, + 'a135': 788, + 'a136': 788, + 'a137': 788, + 'a138': 788, + 'a139': 788, + 'a140': 788, + 'a141': 788, + 'a142': 788, + 'a143': 788, + 'a144': 788, + 'a145': 788, + 'a146': 788, + 'a147': 788, + 'a148': 788, + 'a149': 788, + 'a150': 788, + 'a151': 788, + 'a152': 788, + 'a153': 788, + 'a154': 788, + 'a155': 788, + 'a156': 788, + 'a157': 788, + 'a158': 788, + 'a159': 788, + 'a160': 894, + 'a161': 838, + 'a163': 1016, + 'a164': 458, + 'a196': 748, + 'a165': 924, + 'a192': 748, + 'a166': 918, + 'a167': 927, + 'a168': 928, + 'a169': 928, + 'a170': 834, + 'a171': 873, + 'a172': 828, + 'a173': 924, + 'a162': 924, + 'a174': 917, + 'a175': 930, + 'a176': 931, + 'a177': 463, + 'a178': 883, + 'a179': 836, + 'a193': 836, + 'a180': 867, + 'a199': 867, + 'a181': 696, + 'a200': 696, + 'a182': 874, + 'a201': 874, + 'a183': 760, + 'a184': 946, + 'a197': 771, + 'a185': 865, + 'a194': 771, + 'a198': 888, + 'a186': 967, + 'a195': 888, + 'a187': 831, + 'a188': 873, + 'a189': 927, + 'a190': 970, + 'a191': 918 + } +}; + + + +var EOF = {}; + +function isEOF(v) { + return v == EOF; +} + +var Parser = (function ParserClosure() { + function Parser(lexer, allowStreams, xref) { + this.lexer = lexer; + this.allowStreams = allowStreams; + this.xref = xref; + this.refill(); + } + + Parser.prototype = { + refill: function Parser_refill() { + this.buf1 = this.lexer.getObj(); + this.buf2 = this.lexer.getObj(); + }, + shift: function Parser_shift() { + if (isCmd(this.buf2, 'ID')) { + this.buf1 = this.buf2; + this.buf2 = null; + } else { + this.buf1 = this.buf2; + this.buf2 = this.lexer.getObj(); + } + }, + getObj: function Parser_getObj(cipherTransform) { + 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'); + this.shift(); + continue; + } + + var key = this.buf1.name; + this.shift(); + if (isEOF(this.buf1)) + break; + dict.set(key, this.getObj(cipherTransform)); + } + if (isEOF(this.buf1)) + error('End of file inside dictionary'); + + // stream objects are not allowed inside content streams or + // object streams + if (isCmd(this.buf2, 'stream')) { + return this.allowStreams ? + this.makeStream(dict, cipherTransform) : dict; + } + this.shift(); + return dict; + } + if (isInt(this.buf1)) { // indirect reference or integer + var num = this.buf1; + this.shift(); + if (isInt(this.buf1) && isCmd(this.buf2, 'R')) { + var ref = new Ref(num, this.buf1); + this.shift(); + this.shift(); + return ref; + } + return num; + } + if (isString(this.buf1)) { // string + var str = this.buf1; + this.shift(); + if (cipherTransform) + str = cipherTransform.decryptString(str); + return str; + } + + // simple object + var obj = this.buf1; + this.shift(); + return obj; + }, + makeInlineImage: function Parser_makeInlineImage(cipherTransform) { + var lexer = this.lexer; + var stream = lexer.stream; + + // parse dictionary + var dict = new Dict(); + while (!isCmd(this.buf1, 'ID') && !isEOF(this.buf1)) { + if (!isName(this.buf1)) + error('Dictionary key must be a name object'); + + var key = this.buf1.name; + this.shift(); + if (isEOF(this.buf1)) + break; + dict.set(key, this.getObj(cipherTransform)); + } + + // parse image stream + var startPos = stream.pos; + + // 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; + } + } + + var length = (stream.pos - 4) - startPos; + var imageStream = stream.makeSubStream(startPos, length, dict); + if (cipherTransform) + imageStream = cipherTransform.createStream(imageStream); + imageStream = this.filter(imageStream, dict, length); + imageStream.dict = dict; + + this.buf2 = Cmd.get('EI'); + this.shift(); + + return imageStream; + }, + fetchIfRef: function Parser_fetchIfRef(obj) { + // not relying on the xref.fetchIfRef -- xref might not be set + return isRef(obj) ? this.xref.fetch(obj) : obj; + }, + makeStream: function Parser_makeStream(dict, cipherTransform) { + var lexer = this.lexer; + var stream = lexer.stream; + + // get stream start position + lexer.skipToNextLine(); + var pos = stream.pos - 1; + + // get length + var length = this.fetchIfRef(dict.get('Length')); + if (!isInt(length)) { + info('Bad ' + length + ' attribute in stream'); + length = 0; + } + + // skip over the stream data + stream.pos = pos + length; + lexer.nextChar(); + + this.shift(); // '>>' + this.shift(); // 'stream' + if (!isCmd(this.buf1, 'endstream')) { + // bad stream length, scanning for endstream + stream.pos = pos; + var SCAN_BLOCK_SIZE = 2048; + var ENDSTREAM_SIGNATURE_LENGTH = 9; + var ENDSTREAM_SIGNATURE = [0x65, 0x6E, 0x64, 0x73, 0x74, 0x72, 0x65, + 0x61, 0x6D]; + var skipped = 0, found = false; + 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; + for (i = 0, j = 0; i < scanLength; i++) { + var b = scanBytes[i]; + if (b !== ENDSTREAM_SIGNATURE[j]) { + i -= j; + j = 0; + } else { + j++; + if (j >= ENDSTREAM_SIGNATURE_LENGTH) { + found = true; + break; + } + } + } + if (found) { + skipped += i - ENDSTREAM_SIGNATURE_LENGTH; + stream.pos += i - ENDSTREAM_SIGNATURE_LENGTH; + break; + } + skipped += scanLength; + stream.pos += scanLength; + } + if (!found) { + error('Missing endstream'); + } + length = skipped; + + lexer.nextChar(); + this.shift(); + this.shift(); + } + this.shift(); // 'endstream' + + stream = stream.makeSubStream(pos, length, dict); + if (cipherTransform) + stream = cipherTransform.createStream(stream); + stream = this.filter(stream, dict, length); + stream.dict = dict; + return stream; + }, + filter: function Parser_filter(stream, dict, length) { + var filter = this.fetchIfRef(dict.get('Filter', 'F')); + var params = this.fetchIfRef(dict.get('DecodeParms', 'DP')); + if (isName(filter)) + return this.makeFilter(stream, filter.name, length, params); + if (isArray(filter)) { + var filterArray = filter; + var paramsArray = params; + for (var i = 0, ii = filterArray.length; i < ii; ++i) { + filter = filterArray[i]; + if (!isName(filter)) + error('Bad filter name: ' + filter); + + params = null; + if (isArray(paramsArray) && (i in paramsArray)) + params = paramsArray[i]; + stream = this.makeFilter(stream, filter.name, length, params); + // after the first stream the length variable is invalid + length = null; + } + } + return stream; + }, + makeFilter: function Parser_makeFilter(stream, name, length, params) { + if (stream.dict.get('Length') === 0) { + return new NullStream(stream); + } + if (name == 'FlateDecode' || name == 'Fl') { + if (params) { + return new PredictorStream(new FlateStream(stream), 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); + } + return new LZWStream(stream, earlyChange); + } + 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; + } + }; + + return Parser; +})(); + +var Lexer = (function LexerClosure() { + function Lexer(stream, knownCommands) { + this.stream = stream; + this.nextChar(); + + // The PDFs might have "glued" commands with other commands, operands or + // literals, e.g. "q1". The knownCommands is a dictionary of the valid + // commands and their prefixes. The prefixes are built the following way: + // if there a command that is a prefix of the other valid command or + // literal (e.g. 'f' and 'false') the following prefixes must be included, + // 'fa', 'fal', 'fals'. The prefixes are not needed, if the command has no + // other commands or literals as a prefix. The knowCommands is optional. + this.knownCommands = knownCommands; + } + + Lexer.isSpace = function Lexer_isSpace(ch) { + // space is one of the following characters: SPACE, TAB, CR, or LF + return ch === 0x20 || ch === 0x09 || ch === 0x0D || ch === 0x0A; + }; + + // A '1' in this array means the character is white space. A '1' or + // '2' means the character ends a name or command. + var specialChars = [ + 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, // 0x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x + 1, 0, 0, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 0, 0, 2, // 2x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, // 3x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, // 5x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, // 7x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9x + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // ax + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // bx + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // cx + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // dx + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // ex + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // fx + ]; + + function toHexDigit(ch) { + if (ch >= 0x30 && ch <= 0x39) { // '0'-'9' + return ch & 0x0F; + } + if ((ch >= 0x41 && ch <= 0x46) || (ch >= 0x61 && ch <= 0x66)) { + // 'A'-'F', 'a'-'f' + return (ch & 0x0F) + 9; + } + return -1; + } + + Lexer.prototype = { + nextChar: function Lexer_nextChar() { + return (this.currentChar = this.stream.getByte()); + }, + getNumber: function Lexer_getNumber() { + var floating = false; + var ch = this.currentChar; + var str = String.fromCharCode(ch); + while ((ch = this.nextChar()) >= 0) { + if (ch === 0x2E && !floating) { // '.' + str += '.'; + floating = true; + } 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; + } 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; + }, + getString: function Lexer_getString() { + var numParen = 1; + var done = false; + var str = ''; + + var ch = this.nextChar(); + while (true) { + var charBuffered = false; + switch (ch | 0) { + case -1: + warn('Unterminated string'); + done = true; + break; + case 0x28: // '(' + ++numParen; + str += '('; + break; + case 0x29: // ')' + if (--numParen === 0) { + this.nextChar(); // consume strings ')' + done = true; + } else { + str += ')'; + } + break; + case 0x5C: // '\\' + ch = this.nextChar(); + switch (ch) { + case -1: + warn('Unterminated string'); + done = true; + break; + case 0x6E: // 'n' + str += '\n'; + break; + case 0x72: // 'r' + str += '\r'; + break; + case 0x74: // 't' + str += '\t'; + break; + case 0x62: // 'b' + str += '\b'; + break; + case 0x66: // 'f' + str += '\f'; + break; + case 0x5C: // '\' + case 0x28: // '(' + case 0x29: // ')' + str += String.fromCharCode(ch); + break; + case 0x30: case 0x31: case 0x32: case 0x33: // '0'-'3' + case 0x34: case 0x35: case 0x36: case 0x37: // '4'-'7' + var x = ch & 0x0F; + ch = this.nextChar(); + charBuffered = true; + if (ch >= 0x30 && ch <= 0x37) { // '0'-'7' + x = (x << 3) + (ch & 0x0F); + ch = this.nextChar(); + if (ch >= 0x30 && ch <= 0x37) { // '0'-'7' + charBuffered = false; + x = (x << 3) + (ch & 0x0F); + } + } + + str += String.fromCharCode(x); + break; + case 0x0A: case 0x0D: // LF, CR + break; + default: + str += String.fromCharCode(ch); + break; + } + break; + default: + str += String.fromCharCode(ch); + break; + } + if (done) { + break; + } + if (!charBuffered) { + ch = this.nextChar(); + } + } + return str; + }, + getName: function Lexer_getName() { + var str = '', ch; + while ((ch = this.nextChar()) >= 0 && !specialChars[ch]) { + if (ch === 0x23) { // '#' + ch = this.nextChar(); + var x = toHexDigit(ch); + if (x != -1) { + var x2 = toHexDigit(this.nextChar()); + if (x2 == -1) + error('Illegal digit in hex char in name: ' + x2); + str += String.fromCharCode((x << 4) | x2); + } else { + str += '#'; + str += String.fromCharCode(ch); + } + } else { + str += String.fromCharCode(ch); + } + } + if (str.length > 128) { + error('Warning: name token is longer than allowed by the spec: ' + + str.length); + } + return new Name(str); + }, + getHexString: function Lexer_getHexString() { + var str = ''; + var ch = this.currentChar; + var isFirstHex = true; + var firstDigit; + var secondDigit; + while (true) { + if (ch < 0) { + warn('Unterminated hex string'); + break; + } else if (ch === 0x3E) { // '>' + this.nextChar(); + break; + } else if (specialChars[ch] === 1) { + ch = this.nextChar(); + continue; + } else { + if (isFirstHex) { + firstDigit = toHexDigit(ch); + if (firstDigit === -1) { + warn('Ignoring invalid character "' + ch + '" in hex string'); + ch = this.nextChar(); + continue; + } + } else { + secondDigit = toHexDigit(ch); + if (secondDigit === -1) { + warn('Ignoring invalid character "' + ch + '" in hex string'); + ch = this.nextChar(); + continue; + } + str += String.fromCharCode((firstDigit << 4) | secondDigit); + } + isFirstHex = !isFirstHex; + ch = this.nextChar(); + } + } + return str; + }, + getObj: function Lexer_getObj() { + // skip whitespace and comments + var comment = false; + var ch = this.currentChar; + while (true) { + if (ch < 0) { + return EOF; + } + if (comment) { + if (ch === 0x0A || ch == 0x0D) // LF, CR + comment = false; + } else if (ch === 0x25) { // '%' + comment = true; + } else if (specialChars[ch] !== 1) { + break; + } + ch = this.nextChar(); + } + + // start reading token + switch (ch | 0) { + case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: // '0'-'4' + case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: // '5'-'9' + case 0x2B: case 0x2D: case 0x2E: // '+', '-', '.' + return this.getNumber(); + case 0x28: // '(' + return this.getString(); + case 0x2F: // '/' + return this.getName(); + // array punctuation + case 0x5B: // '[' + this.nextChar(); + return Cmd.get('['); + case 0x5D: // ']' + this.nextChar(); + return Cmd.get(']'); + // hex string or dict punctuation + case 0x3C: // '<' + ch = this.nextChar(); + if (ch === 0x3C) { + // dict punctuation + this.nextChar(); + return Cmd.get('<<'); + } + return this.getHexString(); + // dict punctuation + case 0x3E: // '>' + ch = this.nextChar(); + if (ch === 0x3E) { + this.nextChar(); + return Cmd.get('>>'); + } + return Cmd.get('>'); + case 0x7B: // '{' + this.nextChar(); + return Cmd.get('{'); + case 0x7D: // '}' + this.nextChar(); + return Cmd.get('}'); + case 0x29: // ')' + error('Illegal character: ' + ch); + break; + } + + // command + var str = String.fromCharCode(ch); + var knownCommands = this.knownCommands; + var knownCommandFound = knownCommands && (str in knownCommands); + 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)) { + break; + } + if (str.length == 128) + error('Command token too long: ' + str.length); + str = possibleCommand; + knownCommandFound = knownCommands && (str in knownCommands); + } + if (str == 'true') + return true; + if (str == 'false') + return false; + 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 + ch = this.nextChar(); + if (ch === 0x0A) { // LF + this.nextChar(); + } + break; + } else if (ch === 0x0A) { // LF + this.nextChar(); + break; + } + ch = this.nextChar(); + } + } + }; + + return Lexer; +})(); + +var Linearization = (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) { + 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; + } + error('Hints table in linearization table is invalid: ' + index); + }, + get length() { + if (!isDict(this.linDict)) + return 0; + return this.getInt('L'); + }, + get hintsOffset() { + return this.getHint(0); + }, + get hintsLength() { + return this.getHint(1); + }, + get hintsOffset2() { + return this.getHint(2); + }, + 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'); + } + }; + + return Linearization; +})(); + + + +var Stream = (function StreamClosure() { + function Stream(arrayBuffer, start, length, dict) { + this.bytes = arrayBuffer instanceof Uint8Array ? arrayBuffer : + new Uint8Array(arrayBuffer); + this.start = start || 0; + this.pos = this.start; + this.end = (start + length) || this.bytes.length; + this.dict = dict; + } + + // required methods for a stream. if a particular stream does not + // implement these, an error should be thrown + Stream.prototype = { + get length() { + return this.end - this.start; + }, + getByte: function Stream_getByte() { + if (this.pos >= this.end) + return -1; + return this.bytes[this.pos++]; + }, + // returns subarray of original buffer + // should only be read + getBytes: function Stream_getBytes(length) { + var bytes = this.bytes; + var pos = this.pos; + var strEnd = this.end; + + if (!length) + return bytes.subarray(pos, strEnd); + + var end = pos + length; + if (end > strEnd) + end = strEnd; + + this.pos = end; + return bytes.subarray(pos, end); + }, + peekBytes: function Stream_peekBytes(length) { + var bytes = this.getBytes(length); + this.pos -= bytes.length; + return bytes; + }, + skip: function Stream_skip(n) { + if (!n) + n = 1; + this.pos += n; + }, + reset: function Stream_reset() { + this.pos = this.start; + }, + moveStart: function Stream_moveStart() { + this.start = this.pos; + }, + makeSubStream: function Stream_makeSubStream(start, length, dict) { + return new Stream(this.bytes.buffer, start, length, dict); + }, + isStream: true + }; + + return Stream; +})(); + +var StringStream = (function StringStreamClosure() { + function StringStream(str) { + var length = str.length; + var bytes = new Uint8Array(length); + for (var n = 0; n < length; ++n) + bytes[n] = str.charCodeAt(n); + Stream.call(this, bytes); + } + + StringStream.prototype = Stream.prototype; + + return StringStream; +})(); + +// super class for the decoding streams +var DecodeStream = (function DecodeStreamClosure() { + function DecodeStream() { + this.pos = 0; + this.bufferLength = 0; + this.eof = false; + this.buffer = null; + } + + DecodeStream.prototype = { + ensureBuffer: function DecodeStream_ensureBuffer(requested) { + var buffer = this.buffer; + var current = buffer ? buffer.byteLength : 0; + if (requested < current) + return buffer; + var size = 512; + while (size < requested) + size <<= 1; + var buffer2 = new Uint8Array(size); + for (var i = 0; i < current; ++i) + buffer2[i] = buffer[i]; + return (this.buffer = buffer2); + }, + getByte: function DecodeStream_getByte() { + var pos = this.pos; + while (this.bufferLength <= pos) { + if (this.eof) + return -1; + this.readBlock(); + } + return this.buffer[this.pos++]; + }, + getBytes: function DecodeStream_getBytes(length) { + var end, pos = this.pos; + + if (length) { + this.ensureBuffer(pos + length); + end = pos + length; + + while (!this.eof && this.bufferLength < end) + this.readBlock(); + + var bufEnd = this.bufferLength; + if (end > bufEnd) + end = bufEnd; + } else { + while (!this.eof) + this.readBlock(); + + end = this.bufferLength; + + // 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); + }, + peekBytes: function DecodeStream_peekBytes(length) { + var bytes = this.getBytes(length); + this.pos -= bytes.length; + return bytes; + }, + makeSubStream: function DecodeStream_makeSubStream(start, length, dict) { + var end = start + length; + while (this.bufferLength <= end && !this.eof) + this.readBlock(); + return new Stream(this.buffer, start, length, dict); + }, + skip: function Stream_skip(n) { + if (!n) + n = 1; + this.pos += n; + }, + reset: function DecodeStream_reset() { + this.pos = 0; + }, + getBaseStreams: function DecodeStream_getBaseStreams() { + if (this.str && this.str.getBaseStreams) { + return this.str.getBaseStreams(); + } + return []; + } + }; + + return DecodeStream; +})(); + +var 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); + } + + StreamsSequenceStream.prototype = Object.create(DecodeStream.prototype); + + StreamsSequenceStream.prototype.readBlock = + function streamSequenceStreamReadBlock() { + + var streams = this.streams; + if (streams.length === 0) { + this.eof = true; + return; + } + var stream = streams.shift(); + var chunk = stream.getBytes(); + var bufferLength = this.bufferLength; + var newLength = bufferLength + chunk.length; + var buffer = this.ensureBuffer(newLength); + buffer.set(chunk, bufferLength); + this.bufferLength = newLength; + }; + + StreamsSequenceStream.prototype.getBaseStreams = + function StreamsSequenceStream_getBaseStreams() { + + var baseStreams = []; + for (var i = 0, ii = this.streams.length; i < ii; i++) { + var stream = this.streams[i]; + if (stream.getBaseStreams) { + Util.concatenateToArray(baseStreams, stream.getBaseStreams()); + } + } + return baseStreams; + }; + + return StreamsSequenceStream; +})(); + +var FlateStream = (function FlateStreamClosure() { + var codeLenCodeMap = new Uint32Array([ + 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 + ]); + + var lengthDecode = new Uint32Array([ + 0x00003, 0x00004, 0x00005, 0x00006, 0x00007, 0x00008, 0x00009, 0x0000a, + 0x1000b, 0x1000d, 0x1000f, 0x10011, 0x20013, 0x20017, 0x2001b, 0x2001f, + 0x30023, 0x3002b, 0x30033, 0x3003b, 0x40043, 0x40053, 0x40063, 0x40073, + 0x50083, 0x500a3, 0x500c3, 0x500e3, 0x00102, 0x00102, 0x00102 + ]); + + var distDecode = new Uint32Array([ + 0x00001, 0x00002, 0x00003, 0x00004, 0x10005, 0x10007, 0x20009, 0x2000d, + 0x30011, 0x30019, 0x40021, 0x40031, 0x50041, 0x50061, 0x60081, 0x600c1, + 0x70101, 0x70181, 0x80201, 0x80301, 0x90401, 0x90601, 0xa0801, 0xa0c01, + 0xb1001, 0xb1801, 0xc2001, 0xc3001, 0xd4001, 0xd6001 + ]); + + var fixedLitCodeTab = [new Uint32Array([ + 0x70100, 0x80050, 0x80010, 0x80118, 0x70110, 0x80070, 0x80030, 0x900c0, + 0x70108, 0x80060, 0x80020, 0x900a0, 0x80000, 0x80080, 0x80040, 0x900e0, + 0x70104, 0x80058, 0x80018, 0x90090, 0x70114, 0x80078, 0x80038, 0x900d0, + 0x7010c, 0x80068, 0x80028, 0x900b0, 0x80008, 0x80088, 0x80048, 0x900f0, + 0x70102, 0x80054, 0x80014, 0x8011c, 0x70112, 0x80074, 0x80034, 0x900c8, + 0x7010a, 0x80064, 0x80024, 0x900a8, 0x80004, 0x80084, 0x80044, 0x900e8, + 0x70106, 0x8005c, 0x8001c, 0x90098, 0x70116, 0x8007c, 0x8003c, 0x900d8, + 0x7010e, 0x8006c, 0x8002c, 0x900b8, 0x8000c, 0x8008c, 0x8004c, 0x900f8, + 0x70101, 0x80052, 0x80012, 0x8011a, 0x70111, 0x80072, 0x80032, 0x900c4, + 0x70109, 0x80062, 0x80022, 0x900a4, 0x80002, 0x80082, 0x80042, 0x900e4, + 0x70105, 0x8005a, 0x8001a, 0x90094, 0x70115, 0x8007a, 0x8003a, 0x900d4, + 0x7010d, 0x8006a, 0x8002a, 0x900b4, 0x8000a, 0x8008a, 0x8004a, 0x900f4, + 0x70103, 0x80056, 0x80016, 0x8011e, 0x70113, 0x80076, 0x80036, 0x900cc, + 0x7010b, 0x80066, 0x80026, 0x900ac, 0x80006, 0x80086, 0x80046, 0x900ec, + 0x70107, 0x8005e, 0x8001e, 0x9009c, 0x70117, 0x8007e, 0x8003e, 0x900dc, + 0x7010f, 0x8006e, 0x8002e, 0x900bc, 0x8000e, 0x8008e, 0x8004e, 0x900fc, + 0x70100, 0x80051, 0x80011, 0x80119, 0x70110, 0x80071, 0x80031, 0x900c2, + 0x70108, 0x80061, 0x80021, 0x900a2, 0x80001, 0x80081, 0x80041, 0x900e2, + 0x70104, 0x80059, 0x80019, 0x90092, 0x70114, 0x80079, 0x80039, 0x900d2, + 0x7010c, 0x80069, 0x80029, 0x900b2, 0x80009, 0x80089, 0x80049, 0x900f2, + 0x70102, 0x80055, 0x80015, 0x8011d, 0x70112, 0x80075, 0x80035, 0x900ca, + 0x7010a, 0x80065, 0x80025, 0x900aa, 0x80005, 0x80085, 0x80045, 0x900ea, + 0x70106, 0x8005d, 0x8001d, 0x9009a, 0x70116, 0x8007d, 0x8003d, 0x900da, + 0x7010e, 0x8006d, 0x8002d, 0x900ba, 0x8000d, 0x8008d, 0x8004d, 0x900fa, + 0x70101, 0x80053, 0x80013, 0x8011b, 0x70111, 0x80073, 0x80033, 0x900c6, + 0x70109, 0x80063, 0x80023, 0x900a6, 0x80003, 0x80083, 0x80043, 0x900e6, + 0x70105, 0x8005b, 0x8001b, 0x90096, 0x70115, 0x8007b, 0x8003b, 0x900d6, + 0x7010d, 0x8006b, 0x8002b, 0x900b6, 0x8000b, 0x8008b, 0x8004b, 0x900f6, + 0x70103, 0x80057, 0x80017, 0x8011f, 0x70113, 0x80077, 0x80037, 0x900ce, + 0x7010b, 0x80067, 0x80027, 0x900ae, 0x80007, 0x80087, 0x80047, 0x900ee, + 0x70107, 0x8005f, 0x8001f, 0x9009e, 0x70117, 0x8007f, 0x8003f, 0x900de, + 0x7010f, 0x8006f, 0x8002f, 0x900be, 0x8000f, 0x8008f, 0x8004f, 0x900fe, + 0x70100, 0x80050, 0x80010, 0x80118, 0x70110, 0x80070, 0x80030, 0x900c1, + 0x70108, 0x80060, 0x80020, 0x900a1, 0x80000, 0x80080, 0x80040, 0x900e1, + 0x70104, 0x80058, 0x80018, 0x90091, 0x70114, 0x80078, 0x80038, 0x900d1, + 0x7010c, 0x80068, 0x80028, 0x900b1, 0x80008, 0x80088, 0x80048, 0x900f1, + 0x70102, 0x80054, 0x80014, 0x8011c, 0x70112, 0x80074, 0x80034, 0x900c9, + 0x7010a, 0x80064, 0x80024, 0x900a9, 0x80004, 0x80084, 0x80044, 0x900e9, + 0x70106, 0x8005c, 0x8001c, 0x90099, 0x70116, 0x8007c, 0x8003c, 0x900d9, + 0x7010e, 0x8006c, 0x8002c, 0x900b9, 0x8000c, 0x8008c, 0x8004c, 0x900f9, + 0x70101, 0x80052, 0x80012, 0x8011a, 0x70111, 0x80072, 0x80032, 0x900c5, + 0x70109, 0x80062, 0x80022, 0x900a5, 0x80002, 0x80082, 0x80042, 0x900e5, + 0x70105, 0x8005a, 0x8001a, 0x90095, 0x70115, 0x8007a, 0x8003a, 0x900d5, + 0x7010d, 0x8006a, 0x8002a, 0x900b5, 0x8000a, 0x8008a, 0x8004a, 0x900f5, + 0x70103, 0x80056, 0x80016, 0x8011e, 0x70113, 0x80076, 0x80036, 0x900cd, + 0x7010b, 0x80066, 0x80026, 0x900ad, 0x80006, 0x80086, 0x80046, 0x900ed, + 0x70107, 0x8005e, 0x8001e, 0x9009d, 0x70117, 0x8007e, 0x8003e, 0x900dd, + 0x7010f, 0x8006e, 0x8002e, 0x900bd, 0x8000e, 0x8008e, 0x8004e, 0x900fd, + 0x70100, 0x80051, 0x80011, 0x80119, 0x70110, 0x80071, 0x80031, 0x900c3, + 0x70108, 0x80061, 0x80021, 0x900a3, 0x80001, 0x80081, 0x80041, 0x900e3, + 0x70104, 0x80059, 0x80019, 0x90093, 0x70114, 0x80079, 0x80039, 0x900d3, + 0x7010c, 0x80069, 0x80029, 0x900b3, 0x80009, 0x80089, 0x80049, 0x900f3, + 0x70102, 0x80055, 0x80015, 0x8011d, 0x70112, 0x80075, 0x80035, 0x900cb, + 0x7010a, 0x80065, 0x80025, 0x900ab, 0x80005, 0x80085, 0x80045, 0x900eb, + 0x70106, 0x8005d, 0x8001d, 0x9009b, 0x70116, 0x8007d, 0x8003d, 0x900db, + 0x7010e, 0x8006d, 0x8002d, 0x900bb, 0x8000d, 0x8008d, 0x8004d, 0x900fb, + 0x70101, 0x80053, 0x80013, 0x8011b, 0x70111, 0x80073, 0x80033, 0x900c7, + 0x70109, 0x80063, 0x80023, 0x900a7, 0x80003, 0x80083, 0x80043, 0x900e7, + 0x70105, 0x8005b, 0x8001b, 0x90097, 0x70115, 0x8007b, 0x8003b, 0x900d7, + 0x7010d, 0x8006b, 0x8002b, 0x900b7, 0x8000b, 0x8008b, 0x8004b, 0x900f7, + 0x70103, 0x80057, 0x80017, 0x8011f, 0x70113, 0x80077, 0x80037, 0x900cf, + 0x7010b, 0x80067, 0x80027, 0x900af, 0x80007, 0x80087, 0x80047, 0x900ef, + 0x70107, 0x8005f, 0x8001f, 0x9009f, 0x70117, 0x8007f, 0x8003f, 0x900df, + 0x7010f, 0x8006f, 0x8002f, 0x900bf, 0x8000f, 0x8008f, 0x8004f, 0x900ff + ]), 9]; + + var fixedDistCodeTab = [new Uint32Array([ + 0x50000, 0x50010, 0x50008, 0x50018, 0x50004, 0x50014, 0x5000c, 0x5001c, + 0x50002, 0x50012, 0x5000a, 0x5001a, 0x50006, 0x50016, 0x5000e, 0x00000, + 0x50001, 0x50011, 0x50009, 0x50019, 0x50005, 0x50015, 0x5000d, 0x5001d, + 0x50003, 0x50013, 0x5000b, 0x5001b, 0x50007, 0x50017, 0x5000f, 0x00000 + ]), 5]; + + function FlateStream(stream) { + var bytes = stream.getBytes(); + var bytesPos = 0; + + this.dict = stream.dict; + var cmf = bytes[bytesPos++]; + var flg = bytes[bytesPos++]; + if (cmf == -1 || flg == -1) + error('Invalid header in flate stream: ' + cmf + ', ' + flg); + if ((cmf & 0x0f) != 0x08) + error('Unknown compression method in flate stream: ' + cmf + ', ' + flg); + if ((((cmf << 8) + flg) % 31) !== 0) + error('Bad FCHECK in flate stream: ' + cmf + ', ' + flg); + if (flg & 0x20) + error('FDICT bit set in flate stream: ' + cmf + ', ' + flg); + + this.bytes = bytes; + this.bytesPos = bytesPos; + + this.codeSize = 0; + this.codeBuf = 0; + + DecodeStream.call(this); + } + + FlateStream.prototype = Object.create(DecodeStream.prototype); + + FlateStream.prototype.getBits = function FlateStream_getBits(bits) { + 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') + 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 codes = table[0]; + var maxLen = table[1]; + var codeSize = this.codeSize; + var codeBuf = this.codeBuf; + var bytes = this.bytes; + var bytesPos = this.bytesPos; + + while (codeSize < maxLen) { + var b; + if (typeof (b = bytes[bytesPos++]) == 'undefined') + error('Bad encoding in flate stream'); + 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) + 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) { + var n = lengths.length; + + // find max code length + var maxLen = 0; + for (var i = 0; i < n; ++i) { + if (lengths[i] > maxLen) + maxLen = lengths[i]; + } + + // build the table + var size = 1 << maxLen; + var codes = new Uint32Array(size); + for (var len = 1, code = 0, skip = 2; + len <= maxLen; + ++len, code <<= 1, skip <<= 1) { + for (var val = 0; val < n; ++val) { + if (lengths[val] == len) { + // bit-reverse the code + var code2 = 0; + var t = code; + for (var i = 0; i < len; ++i) { + code2 = (code2 << 1) | (t & 1); + t >>= 1; + } + + // fill the table entries + for (var i = code2; i < size; i += skip) + codes[i] = (len << 16) | val; + + ++code; + } + } + } + + return [codes, maxLen]; + }; + + FlateStream.prototype.readBlock = function FlateStream_readBlock() { + // read block header + var hdr = this.getBits(3); + 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') + error('Bad block header in flate stream'); + var blockLen = b; + if (typeof (b = bytes[bytesPos++]) == 'undefined') + error('Bad block header in flate stream'); + blockLen |= (b << 8); + if (typeof (b = bytes[bytesPos++]) == 'undefined') + error('Bad block header in flate stream'); + var check = b; + if (typeof (b = bytes[bytesPos++]) == 'undefined') + error('Bad block header in flate stream'); + check |= (b << 8); + if (check != (~blockLen & 0xffff) && + (blockLen !== 0 || check !== 0)) { + // Ignoring error for bad "empty" block (see issue 1277) + error('Bad uncompressed block length in flate stream'); + } + + this.codeBuf = 0; + this.codeSize = 0; + + var bufferLength = this.bufferLength; + var buffer = this.ensureBuffer(bufferLength + blockLen); + var end = bufferLength + blockLen; + this.bufferLength = end; + if (blockLen === 0) { + if (typeof bytes[bytesPos] == 'undefined') { + this.eof = true; + } + } else { + for (var n = bufferLength; n < end; ++n) { + if (typeof (b = bytes[bytesPos++]) == 'undefined') { + this.eof = true; + break; + } + buffer[n] = b; + } + } + this.bytesPos = bytesPos; + return; + } + + var litCodeTable; + var distCodeTable; + if (hdr == 1) { // compressed block, fixed codes + litCodeTable = fixedLitCodeTab; + distCodeTable = fixedDistCodeTab; + } else if (hdr == 2) { // compressed block, dynamic codes + var numLitCodes = this.getBits(5) + 257; + var numDistCodes = this.getBits(5) + 1; + var numCodeLenCodes = this.getBits(4) + 4; + + // build the code lengths code table + var codeLenCodeLengths = new Uint8Array(codeLenCodeMap.length); + + for (var 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; + var codes = numLitCodes + numDistCodes; + var codeLengths = new Uint8Array(codes); + 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); + } else { + codeLengths[i++] = len = code; + continue; + } + + var repeatLength = this.getBits(bitsLength) + bitsOffset; + while (repeatLength-- > 0) + codeLengths[i++] = what; + } + + litCodeTable = + this.generateHuffmanTable(codeLengths.subarray(0, numLitCodes)); + distCodeTable = + this.generateHuffmanTable(codeLengths.subarray(numLitCodes, codes)); + } else { + error('Unknown block type in flate stream'); + } + + var buffer = this.buffer; + var limit = buffer ? buffer.length : 0; + var pos = this.bufferLength; + while (true) { + var code1 = this.getCode(litCodeTable); + if (code1 < 256) { + if (pos + 1 >= limit) { + buffer = this.ensureBuffer(pos + 1); + limit = buffer.length; + } + buffer[pos++] = code1; + continue; + } + if (code1 == 256) { + this.bufferLength = pos; + return; + } + code1 -= 257; + code1 = lengthDecode[code1]; + var code2 = code1 >> 16; + if (code2 > 0) + code2 = this.getBits(code2); + var len = (code1 & 0xffff) + code2; + code1 = this.getCode(distCodeTable); + code1 = distDecode[code1]; + code2 = code1 >> 16; + if (code2 > 0) + code2 = this.getBits(code2); + var dist = (code1 & 0xffff) + code2; + if (pos + len >= limit) { + buffer = this.ensureBuffer(pos + len); + limit = buffer.length; + } + for (var k = 0; k < len; ++k, ++pos) + buffer[pos] = buffer[pos - dist]; + } + }; + + return FlateStream; +})(); + +var PredictorStream = (function PredictorStreamClosure() { + function PredictorStream(str, params) { + var predictor = this.predictor = params.get('Predictor') || 1; + + if (predictor <= 1) + return str; // no prediction + if (predictor !== 2 && (predictor < 10 || predictor > 15)) + error('Unsupported predictor: ' + predictor); + + if (predictor === 2) + this.readBlock = this.readBlockTiff; + else + this.readBlock = this.readBlockPng; + + this.str = str; + this.dict = str.dict; + + var colors = this.colors = params.get('Colors') || 1; + var bits = this.bits = params.get('BitsPerComponent') || 8; + var columns = this.columns = params.get('Columns') || 1; + + this.pixBytes = (colors * bits + 7) >> 3; + this.rowBytes = (columns * colors * bits + 7) >> 3; + + DecodeStream.call(this); + return this; + } + + PredictorStream.prototype = Object.create(DecodeStream.prototype); + + PredictorStream.prototype.readBlockTiff = + function predictorStreamReadBlockTiff() { + var rowBytes = this.rowBytes; + + var bufferLength = this.bufferLength; + var buffer = this.ensureBuffer(bufferLength + rowBytes); + + var bits = this.bits; + var colors = this.colors; + + var rawBytes = this.str.getBytes(rowBytes); + this.eof = !rawBytes.length; + if (this.eof) { + return; + } + + var inbuf = 0, outbuf = 0; + var inbits = 0, outbits = 0; + var pos = bufferLength; + + if (bits === 1) { + for (var i = 0; i < rowBytes; ++i) { + var c = rawBytes[i]; + inbuf = (inbuf << 8) | c; + // bitwise addition is exclusive or + // first shift inbuf and then add + buffer[pos++] = (c ^ (inbuf >> colors)) & 0xFF; + // truncate inbuf (assumes colors < 16) + inbuf &= 0xFFFF; + } + } else if (bits === 8) { + for (var i = 0; i < colors; ++i) + buffer[pos++] = rawBytes[i]; + for (; i < rowBytes; ++i) { + buffer[pos] = buffer[pos - colors] + rawBytes[i]; + pos++; + } + } else { + var compArray = new Uint8Array(colors + 1); + var bitMask = (1 << bits) - 1; + var j = 0, k = bufferLength; + var columns = this.columns; + for (var i = 0; i < columns; ++i) { + for (var kk = 0; kk < colors; ++kk) { + if (inbits < bits) { + inbuf = (inbuf << 8) | (rawBytes[j++] & 0xFF); + inbits += 8; + } + compArray[kk] = (compArray[kk] + + (inbuf >> (inbits - bits))) & bitMask; + inbits -= bits; + outbuf = (outbuf << bits) | compArray[kk]; + outbits += bits; + if (outbits >= 8) { + buffer[k++] = (outbuf >> (outbits - 8)) & 0xFF; + outbits -= 8; + } + } + } + if (outbits > 0) { + buffer[k++] = (outbuf << (8 - outbits)) + + (inbuf & ((1 << (8 - outbits)) - 1)); + } + } + this.bufferLength += rowBytes; + }; + + PredictorStream.prototype.readBlockPng = + function predictorStreamReadBlockPng() { + + var rowBytes = this.rowBytes; + var pixBytes = this.pixBytes; + + var predictor = this.str.getByte(); + var rawBytes = this.str.getBytes(rowBytes); + this.eof = !rawBytes.length; + if (this.eof) { + return; + } + + var bufferLength = this.bufferLength; + var buffer = this.ensureBuffer(bufferLength + rowBytes); + + var prevRow = buffer.subarray(bufferLength - rowBytes, bufferLength); + if (prevRow.length === 0) + prevRow = new Uint8Array(rowBytes); + + var j = bufferLength; + switch (predictor) { + case 0: + for (var i = 0; i < rowBytes; ++i) + buffer[j++] = rawBytes[i]; + break; + case 1: + for (var 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) + buffer[j++] = (prevRow[i] + rawBytes[i]) & 0xFF; + break; + case 3: + for (var i = 0; i < pixBytes; ++i) + buffer[j++] = (prevRow[i] >> 1) + rawBytes[i]; + for (; i < rowBytes; ++i) { + buffer[j] = (((prevRow[i] + buffer[j - pixBytes]) >> 1) + + rawBytes[i]) & 0xFF; + j++; + } + break; + case 4: + // we need to save the up left pixels values. the simplest way + // is to create a new buffer + for (var i = 0; i < pixBytes; ++i) { + var up = prevRow[i]; + var c = rawBytes[i]; + buffer[j++] = up + c; + } + for (; i < rowBytes; ++i) { + var up = prevRow[i]; + var upLeft = prevRow[i - pixBytes]; + var left = buffer[j - pixBytes]; + var p = left + up - upLeft; + + var pa = p - left; + if (pa < 0) + pa = -pa; + var pb = p - up; + if (pb < 0) + pb = -pb; + var pc = p - upLeft; + if (pc < 0) + pc = -pc; + + var c = rawBytes[i]; + if (pa <= pb && pa <= pc) + buffer[j++] = left + c; + else if (pb <= pc) + buffer[j++] = up + c; + else + buffer[j++] = upLeft + c; + } + break; + default: + error('Unsupported predictor: ' + predictor); + } + this.bufferLength += rowBytes; + }; + + return PredictorStream; +})(); + +/** + * Depending on the type of JPEG a JpegStream is handled in different ways. For + * JPEG's that are supported natively such as DeviceGray and DeviceRGB the image + * data is stored and then loaded by the browser. For unsupported JPEG's we use + * a library to decode these images and the stream behaves like all the other + * DecodeStreams. + */ +var JpegStream = (function JpegStreamClosure() { + function JpegStream(bytes, dict, xref) { + // TODO: per poppler, some images may have 'junk' before that + // need to be removed + this.dict = dict; + this.bytes = bytes; + + DecodeStream.call(this); + } + + JpegStream.prototype = Object.create(DecodeStream.prototype); + + JpegStream.prototype.ensureBuffer = function JpegStream_ensureBuffer(req) { + if (this.bufferLength) + return; + try { + var jpegImage = new JpegImage(); + if (this.colorTransform != -1) + jpegImage.colorTransform = this.colorTransform; + jpegImage.parse(this.bytes); + var width = jpegImage.width; + var height = jpegImage.height; + var data = jpegImage.getData(width, height); + this.buffer = data; + this.bufferLength = data.length; + this.eof = true; + } catch (e) { + error('JPEG error: ' + e); + } + }; + JpegStream.prototype.getIR = function JpegStream_getIR() { + return PDFJS.createObjectURL(this.bytes, 'image/jpeg'); + }; + /** + * Checks if the image can be decoded and displayed by the browser without any + * further processing such as color space conversions. + */ + JpegStream.prototype.isNativelySupported = + function JpegStream_isNativelySupported(xref, res) { + var cs = ColorSpace.parse(this.dict.get('ColorSpace', 'CS'), xref, res); + return cs.name === 'DeviceGray' || cs.name === 'DeviceRGB'; + }; + /** + * Checks if the image can be decoded by the browser. + */ + JpegStream.prototype.isNativelyDecodable = + function JpegStream_isNativelyDecodable(xref, res) { + var cs = ColorSpace.parse(this.dict.get('ColorSpace', 'CS'), xref, res); + var numComps = cs.numComps; + return numComps == 1 || numComps == 3; + }; + + return JpegStream; +})(); + +/** + * For JPEG 2000's we use a library to decode these images and + * the stream behaves like all the other DecodeStreams. + */ +var JpxStream = (function JpxStreamClosure() { + function JpxStream(bytes, dict) { + this.dict = dict; + this.bytes = bytes; + + DecodeStream.call(this); + } + + JpxStream.prototype = Object.create(DecodeStream.prototype); + + JpxStream.prototype.ensureBuffer = function JpxStream_ensureBuffer(req) { + if (this.bufferLength) + return; + + var jpxImage = new JpxImage(); + jpxImage.parse(this.bytes); + + var width = jpxImage.width; + var height = jpxImage.height; + var componentsCount = jpxImage.componentsCount; + if (componentsCount != 1 && componentsCount != 3 && componentsCount != 4) + error('JPX with ' + componentsCount + ' components is not supported'); + + var data = new Uint8Array(width * height * componentsCount); + + 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 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; + } + } + + this.buffer = data; + this.bufferLength = data.length; + this.eof = true; + }; + + return JpxStream; +})(); + +/** + * For JBIG2's we use a library to decode these images and + * the stream behaves like all the other DecodeStreams. + */ +var Jbig2Stream = (function Jbig2StreamClosure() { + function Jbig2Stream(bytes, dict) { + this.dict = dict; + this.bytes = bytes; + + DecodeStream.call(this); + } + + Jbig2Stream.prototype = Object.create(DecodeStream.prototype); + + Jbig2Stream.prototype.ensureBuffer = function Jbig2Stream_ensureBuffer(req) { + if (this.bufferLength) + return; + + var jbig2Image = new Jbig2Image(); + + var chunks = [], decodeParams = this.dict.get('DecodeParms'); + + // According to the PDF specification, DecodeParms can be either + // a dictionary, or an array whose elements are dictionaries. + if (isArray(decodeParams)) { + if (decodeParams.length > 1) { + warn('JBIG2 - \'DecodeParms\' array with multiple elements ' + + 'not supported.'); + } + decodeParams = decodeParams[0]; + } + if (decodeParams && decodeParams.has('JBIG2Globals')) { + var globalsStream = decodeParams.get('JBIG2Globals'); + var globals = globalsStream.getBytes(); + chunks.push({data: globals, start: 0, end: globals.length}); + } + chunks.push({data: this.bytes, start: 0, end: this.bytes.length}); + var data = jbig2Image.parseChunks(chunks); + var dataLength = data.length; + + // JBIG2 had black as 1 and white as 0, inverting the colors + for (var i = 0; i < dataLength; i++) + data[i] ^= 0xFF; + + this.buffer = data; + this.bufferLength = dataLength; + this.eof = true; + }; + + return Jbig2Stream; +})(); + +var DecryptStream = (function DecryptStreamClosure() { + function DecryptStream(str, decrypt) { + this.str = str; + this.dict = str.dict; + this.decrypt = decrypt; + this.nextChunk = null; + this.initialized = false; + + DecodeStream.call(this); + } + + var chunkSize = 512; + + DecryptStream.prototype = Object.create(DecodeStream.prototype); + + DecryptStream.prototype.readBlock = function DecryptStream_readBlock() { + var chunk; + if (this.initialized) { + chunk = this.nextChunk; + } else { + chunk = this.str.getBytes(chunkSize); + this.initialized = true; + } + if (!chunk || chunk.length === 0) { + this.eof = true; + return; + } + this.nextChunk = this.str.getBytes(chunkSize); + var hasMoreData = this.nextChunk && this.nextChunk.length > 0; + + var decrypt = this.decrypt; + chunk = decrypt(chunk, !hasMoreData); + + var bufferLength = this.bufferLength; + var i, n = chunk.length; + var buffer = this.ensureBuffer(bufferLength + n); + for (i = 0; i < n; i++) + buffer[bufferLength++] = chunk[i]; + this.bufferLength = bufferLength; + }; + + return DecryptStream; +})(); + +var Ascii85Stream = (function Ascii85StreamClosure() { + function Ascii85Stream(str) { + this.str = str; + this.dict = str.dict; + this.input = new Uint8Array(5); + + DecodeStream.call(this); + } + + Ascii85Stream.prototype = Object.create(DecodeStream.prototype); + + Ascii85Stream.prototype.readBlock = function Ascii85Stream_readBlock() { + var TILDA_CHAR = 0x7E; // '~' + var Z_LOWER_CHAR = 0x7A; // 'z' + var EOF = -1; + + var str = this.str; + + var c = str.getByte(); + while (Lexer.isSpace(c)) { + c = str.getByte(); + } + + if (c === EOF || c === TILDA_CHAR) { + this.eof = true; + return; + } + + var bufferLength = this.bufferLength, buffer; + + // special code for z + if (c == Z_LOWER_CHAR) { + buffer = this.ensureBuffer(bufferLength + 4); + for (var 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) { + c = str.getByte(); + while (Lexer.isSpace(c)) { + c = str.getByte(); + } + + input[i] = c; + + if (c === EOF || c == TILDA_CHAR) + break; + } + buffer = this.ensureBuffer(bufferLength + i - 1); + this.bufferLength += i - 1; + + // partial ending; + if (i < 5) { + for (; i < 5; ++i) + input[i] = 0x21 + 84; + this.eof = true; + } + var t = 0; + for (var i = 0; i < 5; ++i) + t = t * 85 + (input[i] - 0x21); + + for (var i = 3; i >= 0; --i) { + buffer[bufferLength + i] = t & 0xFF; + t >>= 8; + } + } + }; + + return Ascii85Stream; +})(); + +var AsciiHexStream = (function AsciiHexStreamClosure() { + function AsciiHexStream(str) { + this.str = str; + this.dict = str.dict; + + this.firstDigit = -1; + + DecodeStream.call(this); + } + + AsciiHexStream.prototype = Object.create(DecodeStream.prototype); + + AsciiHexStream.prototype.readBlock = function AsciiHexStream_readBlock() { + var UPSTREAM_BLOCK_SIZE = 8000; + var bytes = this.str.getBytes(UPSTREAM_BLOCK_SIZE); + if (!bytes.length) { + this.eof = true; + return; + } + + var maxDecodeLength = (bytes.length + 1) >> 1; + var buffer = this.ensureBuffer(this.bufferLength + maxDecodeLength); + var bufferLength = this.bufferLength; + + var firstDigit = this.firstDigit; + for (var i = 0, ii = bytes.length; i < ii; i++) { + var ch = bytes[i], digit; + if (ch >= 0x30 && ch <= 0x39) { // '0'-'9' + digit = ch & 0x0F; + } else if ((ch >= 0x41 && ch <= 0x46) || (ch >= 0x61 && ch <= 0x66)) { + // 'A'-'Z', 'a'-'z' + digit = (ch & 0x0F) + 9; + } else if (ch === 0x3E) { // '>' + this.eof = true; + break; + } else { // probably whitespace + continue; // ignoring + } + if (firstDigit < 0) { + firstDigit = digit; + } else { + buffer[bufferLength++] = (firstDigit << 4) | digit; + firstDigit = -1; + } + } + if (firstDigit >= 0 && this.eof) { + // incomplete byte + buffer[bufferLength++] = (firstDigit << 4); + firstDigit = -1; + } + this.firstDigit = firstDigit; + this.bufferLength = bufferLength; + }; + + return AsciiHexStream; +})(); + +var RunLengthStream = (function RunLengthStreamClosure() { + function RunLengthStream(str) { + this.str = str; + this.dict = str.dict; + + DecodeStream.call(this); + } + + RunLengthStream.prototype = Object.create(DecodeStream.prototype); + + RunLengthStream.prototype.readBlock = function RunLengthStream_readBlock() { + // The repeatHeader has following format. The first byte defines type of run + // and amount of bytes to repeat/copy: n = 0 through 127 - copy next n bytes + // (in addition to the second byte from the header), n = 129 through 255 - + // duplicate the second byte from the header (257 - n) times, n = 128 - end. + var repeatHeader = this.str.getBytes(2); + if (!repeatHeader || repeatHeader.length < 2 || repeatHeader[0] == 128) { + this.eof = true; + return; + } + + var bufferLength = this.bufferLength; + var n = repeatHeader[0]; + if (n < 128) { + // copy n bytes + var buffer = this.ensureBuffer(bufferLength + n + 1); + buffer[bufferLength++] = repeatHeader[1]; + if (n > 0) { + var source = this.str.getBytes(n); + buffer.set(source, bufferLength); + bufferLength += n; + } + } else { + n = 257 - n; + var b = repeatHeader[1]; + var buffer = this.ensureBuffer(bufferLength + n + 1); + for (var i = 0; i < n; i++) + buffer[bufferLength++] = b; + } + this.bufferLength = bufferLength; + }; + + return RunLengthStream; +})(); + +var CCITTFaxStream = (function CCITTFaxStreamClosure() { + + var ccittEOL = -2; + var twoDimPass = 0; + var twoDimHoriz = 1; + var twoDimVert0 = 2; + var twoDimVertR1 = 3; + var twoDimVertL1 = 4; + var twoDimVertR2 = 5; + var twoDimVertL2 = 6; + var twoDimVertR3 = 7; + var twoDimVertL3 = 8; + + var twoDimTable = [ + [-1, -1], [-1, -1], // 000000x + [7, twoDimVertL3], // 0000010 + [7, twoDimVertR3], // 0000011 + [6, twoDimVertL2], [6, twoDimVertL2], // 000010x + [6, twoDimVertR2], [6, twoDimVertR2], // 000011x + [4, twoDimPass], [4, twoDimPass], // 0001xxx + [4, twoDimPass], [4, twoDimPass], + [4, twoDimPass], [4, twoDimPass], + [4, twoDimPass], [4, twoDimPass], + [3, twoDimHoriz], [3, twoDimHoriz], // 001xxxx + [3, twoDimHoriz], [3, twoDimHoriz], + [3, twoDimHoriz], [3, twoDimHoriz], + [3, twoDimHoriz], [3, twoDimHoriz], + [3, twoDimHoriz], [3, twoDimHoriz], + [3, twoDimHoriz], [3, twoDimHoriz], + [3, twoDimHoriz], [3, twoDimHoriz], + [3, twoDimHoriz], [3, twoDimHoriz], + [3, twoDimVertL1], [3, twoDimVertL1], // 010xxxx + [3, twoDimVertL1], [3, twoDimVertL1], + [3, twoDimVertL1], [3, twoDimVertL1], + [3, twoDimVertL1], [3, twoDimVertL1], + [3, twoDimVertL1], [3, twoDimVertL1], + [3, twoDimVertL1], [3, twoDimVertL1], + [3, twoDimVertL1], [3, twoDimVertL1], + [3, twoDimVertL1], [3, twoDimVertL1], + [3, twoDimVertR1], [3, twoDimVertR1], // 011xxxx + [3, twoDimVertR1], [3, twoDimVertR1], + [3, twoDimVertR1], [3, twoDimVertR1], + [3, twoDimVertR1], [3, twoDimVertR1], + [3, twoDimVertR1], [3, twoDimVertR1], + [3, twoDimVertR1], [3, twoDimVertR1], + [3, twoDimVertR1], [3, twoDimVertR1], + [3, twoDimVertR1], [3, twoDimVertR1], + [1, twoDimVert0], [1, twoDimVert0], // 1xxxxxx + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0], + [1, twoDimVert0], [1, twoDimVert0] + ]; + + var whiteTable1 = [ + [-1, -1], // 00000 + [12, ccittEOL], // 00001 + [-1, -1], [-1, -1], // 0001x + [-1, -1], [-1, -1], [-1, -1], [-1, -1], // 001xx + [-1, -1], [-1, -1], [-1, -1], [-1, -1], // 010xx + [-1, -1], [-1, -1], [-1, -1], [-1, -1], // 011xx + [11, 1792], [11, 1792], // 1000x + [12, 1984], // 10010 + [12, 2048], // 10011 + [12, 2112], // 10100 + [12, 2176], // 10101 + [12, 2240], // 10110 + [12, 2304], // 10111 + [11, 1856], [11, 1856], // 1100x + [11, 1920], [11, 1920], // 1101x + [12, 2368], // 11100 + [12, 2432], // 11101 + [12, 2496], // 11110 + [12, 2560] // 11111 + ]; + + var whiteTable2 = [ + [-1, -1], [-1, -1], [-1, -1], [-1, -1], // 0000000xx + [8, 29], [8, 29], // 00000010x + [8, 30], [8, 30], // 00000011x + [8, 45], [8, 45], // 00000100x + [8, 46], [8, 46], // 00000101x + [7, 22], [7, 22], [7, 22], [7, 22], // 0000011xx + [7, 23], [7, 23], [7, 23], [7, 23], // 0000100xx + [8, 47], [8, 47], // 00001010x + [8, 48], [8, 48], // 00001011x + [6, 13], [6, 13], [6, 13], [6, 13], // 000011xxx + [6, 13], [6, 13], [6, 13], [6, 13], + [7, 20], [7, 20], [7, 20], [7, 20], // 0001000xx + [8, 33], [8, 33], // 00010010x + [8, 34], [8, 34], // 00010011x + [8, 35], [8, 35], // 00010100x + [8, 36], [8, 36], // 00010101x + [8, 37], [8, 37], // 00010110x + [8, 38], [8, 38], // 00010111x + [7, 19], [7, 19], [7, 19], [7, 19], // 0001100xx + [8, 31], [8, 31], // 00011010x + [8, 32], [8, 32], // 00011011x + [6, 1], [6, 1], [6, 1], [6, 1], // 000111xxx + [6, 1], [6, 1], [6, 1], [6, 1], + [6, 12], [6, 12], [6, 12], [6, 12], // 001000xxx + [6, 12], [6, 12], [6, 12], [6, 12], + [8, 53], [8, 53], // 00100100x + [8, 54], [8, 54], // 00100101x + [7, 26], [7, 26], [7, 26], [7, 26], // 0010011xx + [8, 39], [8, 39], // 00101000x + [8, 40], [8, 40], // 00101001x + [8, 41], [8, 41], // 00101010x + [8, 42], [8, 42], // 00101011x + [8, 43], [8, 43], // 00101100x + [8, 44], [8, 44], // 00101101x + [7, 21], [7, 21], [7, 21], [7, 21], // 0010111xx + [7, 28], [7, 28], [7, 28], [7, 28], // 0011000xx + [8, 61], [8, 61], // 00110010x + [8, 62], [8, 62], // 00110011x + [8, 63], [8, 63], // 00110100x + [8, 0], [8, 0], // 00110101x + [8, 320], [8, 320], // 00110110x + [8, 384], [8, 384], // 00110111x + [5, 10], [5, 10], [5, 10], [5, 10], // 00111xxxx + [5, 10], [5, 10], [5, 10], [5, 10], + [5, 10], [5, 10], [5, 10], [5, 10], + [5, 10], [5, 10], [5, 10], [5, 10], + [5, 11], [5, 11], [5, 11], [5, 11], // 01000xxxx + [5, 11], [5, 11], [5, 11], [5, 11], + [5, 11], [5, 11], [5, 11], [5, 11], + [5, 11], [5, 11], [5, 11], [5, 11], + [7, 27], [7, 27], [7, 27], [7, 27], // 0100100xx + [8, 59], [8, 59], // 01001010x + [8, 60], [8, 60], // 01001011x + [9, 1472], // 010011000 + [9, 1536], // 010011001 + [9, 1600], // 010011010 + [9, 1728], // 010011011 + [7, 18], [7, 18], [7, 18], [7, 18], // 0100111xx + [7, 24], [7, 24], [7, 24], [7, 24], // 0101000xx + [8, 49], [8, 49], // 01010010x + [8, 50], [8, 50], // 01010011x + [8, 51], [8, 51], // 01010100x + [8, 52], [8, 52], // 01010101x + [7, 25], [7, 25], [7, 25], [7, 25], // 0101011xx + [8, 55], [8, 55], // 01011000x + [8, 56], [8, 56], // 01011001x + [8, 57], [8, 57], // 01011010x + [8, 58], [8, 58], // 01011011x + [6, 192], [6, 192], [6, 192], [6, 192], // 010111xxx + [6, 192], [6, 192], [6, 192], [6, 192], + [6, 1664], [6, 1664], [6, 1664], [6, 1664], // 011000xxx + [6, 1664], [6, 1664], [6, 1664], [6, 1664], + [8, 448], [8, 448], // 01100100x + [8, 512], [8, 512], // 01100101x + [9, 704], // 011001100 + [9, 768], // 011001101 + [8, 640], [8, 640], // 01100111x + [8, 576], [8, 576], // 01101000x + [9, 832], // 011010010 + [9, 896], // 011010011 + [9, 960], // 011010100 + [9, 1024], // 011010101 + [9, 1088], // 011010110 + [9, 1152], // 011010111 + [9, 1216], // 011011000 + [9, 1280], // 011011001 + [9, 1344], // 011011010 + [9, 1408], // 011011011 + [7, 256], [7, 256], [7, 256], [7, 256], // 0110111xx + [4, 2], [4, 2], [4, 2], [4, 2], // 0111xxxxx + [4, 2], [4, 2], [4, 2], [4, 2], + [4, 2], [4, 2], [4, 2], [4, 2], + [4, 2], [4, 2], [4, 2], [4, 2], + [4, 2], [4, 2], [4, 2], [4, 2], + [4, 2], [4, 2], [4, 2], [4, 2], + [4, 2], [4, 2], [4, 2], [4, 2], + [4, 2], [4, 2], [4, 2], [4, 2], + [4, 3], [4, 3], [4, 3], [4, 3], // 1000xxxxx + [4, 3], [4, 3], [4, 3], [4, 3], + [4, 3], [4, 3], [4, 3], [4, 3], + [4, 3], [4, 3], [4, 3], [4, 3], + [4, 3], [4, 3], [4, 3], [4, 3], + [4, 3], [4, 3], [4, 3], [4, 3], + [4, 3], [4, 3], [4, 3], [4, 3], + [4, 3], [4, 3], [4, 3], [4, 3], + [5, 128], [5, 128], [5, 128], [5, 128], // 10010xxxx + [5, 128], [5, 128], [5, 128], [5, 128], + [5, 128], [5, 128], [5, 128], [5, 128], + [5, 128], [5, 128], [5, 128], [5, 128], + [5, 8], [5, 8], [5, 8], [5, 8], // 10011xxxx + [5, 8], [5, 8], [5, 8], [5, 8], + [5, 8], [5, 8], [5, 8], [5, 8], + [5, 8], [5, 8], [5, 8], [5, 8], + [5, 9], [5, 9], [5, 9], [5, 9], // 10100xxxx + [5, 9], [5, 9], [5, 9], [5, 9], + [5, 9], [5, 9], [5, 9], [5, 9], + [5, 9], [5, 9], [5, 9], [5, 9], + [6, 16], [6, 16], [6, 16], [6, 16], // 101010xxx + [6, 16], [6, 16], [6, 16], [6, 16], + [6, 17], [6, 17], [6, 17], [6, 17], // 101011xxx + [6, 17], [6, 17], [6, 17], [6, 17], + [4, 4], [4, 4], [4, 4], [4, 4], // 1011xxxxx + [4, 4], [4, 4], [4, 4], [4, 4], + [4, 4], [4, 4], [4, 4], [4, 4], + [4, 4], [4, 4], [4, 4], [4, 4], + [4, 4], [4, 4], [4, 4], [4, 4], + [4, 4], [4, 4], [4, 4], [4, 4], + [4, 4], [4, 4], [4, 4], [4, 4], + [4, 4], [4, 4], [4, 4], [4, 4], + [4, 5], [4, 5], [4, 5], [4, 5], // 1100xxxxx + [4, 5], [4, 5], [4, 5], [4, 5], + [4, 5], [4, 5], [4, 5], [4, 5], + [4, 5], [4, 5], [4, 5], [4, 5], + [4, 5], [4, 5], [4, 5], [4, 5], + [4, 5], [4, 5], [4, 5], [4, 5], + [4, 5], [4, 5], [4, 5], [4, 5], + [4, 5], [4, 5], [4, 5], [4, 5], + [6, 14], [6, 14], [6, 14], [6, 14], // 110100xxx + [6, 14], [6, 14], [6, 14], [6, 14], + [6, 15], [6, 15], [6, 15], [6, 15], // 110101xxx + [6, 15], [6, 15], [6, 15], [6, 15], + [5, 64], [5, 64], [5, 64], [5, 64], // 11011xxxx + [5, 64], [5, 64], [5, 64], [5, 64], + [5, 64], [5, 64], [5, 64], [5, 64], + [5, 64], [5, 64], [5, 64], [5, 64], + [4, 6], [4, 6], [4, 6], [4, 6], // 1110xxxxx + [4, 6], [4, 6], [4, 6], [4, 6], + [4, 6], [4, 6], [4, 6], [4, 6], + [4, 6], [4, 6], [4, 6], [4, 6], + [4, 6], [4, 6], [4, 6], [4, 6], + [4, 6], [4, 6], [4, 6], [4, 6], + [4, 6], [4, 6], [4, 6], [4, 6], + [4, 6], [4, 6], [4, 6], [4, 6], + [4, 7], [4, 7], [4, 7], [4, 7], // 1111xxxxx + [4, 7], [4, 7], [4, 7], [4, 7], + [4, 7], [4, 7], [4, 7], [4, 7], + [4, 7], [4, 7], [4, 7], [4, 7], + [4, 7], [4, 7], [4, 7], [4, 7], + [4, 7], [4, 7], [4, 7], [4, 7], + [4, 7], [4, 7], [4, 7], [4, 7], + [4, 7], [4, 7], [4, 7], [4, 7] + ]; + + var blackTable1 = [ + [-1, -1], [-1, -1], // 000000000000x + [12, ccittEOL], [12, ccittEOL], // 000000000001x + [-1, -1], [-1, -1], [-1, -1], [-1, -1], // 00000000001xx + [-1, -1], [-1, -1], [-1, -1], [-1, -1], // 00000000010xx + [-1, -1], [-1, -1], [-1, -1], [-1, -1], // 00000000011xx + [-1, -1], [-1, -1], [-1, -1], [-1, -1], // 00000000100xx + [-1, -1], [-1, -1], [-1, -1], [-1, -1], // 00000000101xx + [-1, -1], [-1, -1], [-1, -1], [-1, -1], // 00000000110xx + [-1, -1], [-1, -1], [-1, -1], [-1, -1], // 00000000111xx + [11, 1792], [11, 1792], [11, 1792], [11, 1792], // 00000001000xx + [12, 1984], [12, 1984], // 000000010010x + [12, 2048], [12, 2048], // 000000010011x + [12, 2112], [12, 2112], // 000000010100x + [12, 2176], [12, 2176], // 000000010101x + [12, 2240], [12, 2240], // 000000010110x + [12, 2304], [12, 2304], // 000000010111x + [11, 1856], [11, 1856], [11, 1856], [11, 1856], // 00000001100xx + [11, 1920], [11, 1920], [11, 1920], [11, 1920], // 00000001101xx + [12, 2368], [12, 2368], // 000000011100x + [12, 2432], [12, 2432], // 000000011101x + [12, 2496], [12, 2496], // 000000011110x + [12, 2560], [12, 2560], // 000000011111x + [10, 18], [10, 18], [10, 18], [10, 18], // 0000001000xxx + [10, 18], [10, 18], [10, 18], [10, 18], + [12, 52], [12, 52], // 000000100100x + [13, 640], // 0000001001010 + [13, 704], // 0000001001011 + [13, 768], // 0000001001100 + [13, 832], // 0000001001101 + [12, 55], [12, 55], // 000000100111x + [12, 56], [12, 56], // 000000101000x + [13, 1280], // 0000001010010 + [13, 1344], // 0000001010011 + [13, 1408], // 0000001010100 + [13, 1472], // 0000001010101 + [12, 59], [12, 59], // 000000101011x + [12, 60], [12, 60], // 000000101100x + [13, 1536], // 0000001011010 + [13, 1600], // 0000001011011 + [11, 24], [11, 24], [11, 24], [11, 24], // 00000010111xx + [11, 25], [11, 25], [11, 25], [11, 25], // 00000011000xx + [13, 1664], // 0000001100100 + [13, 1728], // 0000001100101 + [12, 320], [12, 320], // 000000110011x + [12, 384], [12, 384], // 000000110100x + [12, 448], [12, 448], // 000000110101x + [13, 512], // 0000001101100 + [13, 576], // 0000001101101 + [12, 53], [12, 53], // 000000110111x + [12, 54], [12, 54], // 000000111000x + [13, 896], // 0000001110010 + [13, 960], // 0000001110011 + [13, 1024], // 0000001110100 + [13, 1088], // 0000001110101 + [13, 1152], // 0000001110110 + [13, 1216], // 0000001110111 + [10, 64], [10, 64], [10, 64], [10, 64], // 0000001111xxx + [10, 64], [10, 64], [10, 64], [10, 64] + ]; + + var blackTable2 = [ + [8, 13], [8, 13], [8, 13], [8, 13], // 00000100xxxx + [8, 13], [8, 13], [8, 13], [8, 13], + [8, 13], [8, 13], [8, 13], [8, 13], + [8, 13], [8, 13], [8, 13], [8, 13], + [11, 23], [11, 23], // 00000101000x + [12, 50], // 000001010010 + [12, 51], // 000001010011 + [12, 44], // 000001010100 + [12, 45], // 000001010101 + [12, 46], // 000001010110 + [12, 47], // 000001010111 + [12, 57], // 000001011000 + [12, 58], // 000001011001 + [12, 61], // 000001011010 + [12, 256], // 000001011011 + [10, 16], [10, 16], [10, 16], [10, 16], // 0000010111xx + [10, 17], [10, 17], [10, 17], [10, 17], // 0000011000xx + [12, 48], // 000001100100 + [12, 49], // 000001100101 + [12, 62], // 000001100110 + [12, 63], // 000001100111 + [12, 30], // 000001101000 + [12, 31], // 000001101001 + [12, 32], // 000001101010 + [12, 33], // 000001101011 + [12, 40], // 000001101100 + [12, 41], // 000001101101 + [11, 22], [11, 22], // 00000110111x + [8, 14], [8, 14], [8, 14], [8, 14], // 00000111xxxx + [8, 14], [8, 14], [8, 14], [8, 14], + [8, 14], [8, 14], [8, 14], [8, 14], + [8, 14], [8, 14], [8, 14], [8, 14], + [7, 10], [7, 10], [7, 10], [7, 10], // 0000100xxxxx + [7, 10], [7, 10], [7, 10], [7, 10], + [7, 10], [7, 10], [7, 10], [7, 10], + [7, 10], [7, 10], [7, 10], [7, 10], + [7, 10], [7, 10], [7, 10], [7, 10], + [7, 10], [7, 10], [7, 10], [7, 10], + [7, 10], [7, 10], [7, 10], [7, 10], + [7, 10], [7, 10], [7, 10], [7, 10], + [7, 11], [7, 11], [7, 11], [7, 11], // 0000101xxxxx + [7, 11], [7, 11], [7, 11], [7, 11], + [7, 11], [7, 11], [7, 11], [7, 11], + [7, 11], [7, 11], [7, 11], [7, 11], + [7, 11], [7, 11], [7, 11], [7, 11], + [7, 11], [7, 11], [7, 11], [7, 11], + [7, 11], [7, 11], [7, 11], [7, 11], + [7, 11], [7, 11], [7, 11], [7, 11], + [9, 15], [9, 15], [9, 15], [9, 15], // 000011000xxx + [9, 15], [9, 15], [9, 15], [9, 15], + [12, 128], // 000011001000 + [12, 192], // 000011001001 + [12, 26], // 000011001010 + [12, 27], // 000011001011 + [12, 28], // 000011001100 + [12, 29], // 000011001101 + [11, 19], [11, 19], // 00001100111x + [11, 20], [11, 20], // 00001101000x + [12, 34], // 000011010010 + [12, 35], // 000011010011 + [12, 36], // 000011010100 + [12, 37], // 000011010101 + [12, 38], // 000011010110 + [12, 39], // 000011010111 + [11, 21], [11, 21], // 00001101100x + [12, 42], // 000011011010 + [12, 43], // 000011011011 + [10, 0], [10, 0], [10, 0], [10, 0], // 0000110111xx + [7, 12], [7, 12], [7, 12], [7, 12], // 0000111xxxxx + [7, 12], [7, 12], [7, 12], [7, 12], + [7, 12], [7, 12], [7, 12], [7, 12], + [7, 12], [7, 12], [7, 12], [7, 12], + [7, 12], [7, 12], [7, 12], [7, 12], + [7, 12], [7, 12], [7, 12], [7, 12], + [7, 12], [7, 12], [7, 12], [7, 12], + [7, 12], [7, 12], [7, 12], [7, 12] + ]; + + var blackTable3 = [ + [-1, -1], [-1, -1], [-1, -1], [-1, -1], // 0000xx + [6, 9], // 000100 + [6, 8], // 000101 + [5, 7], [5, 7], // 00011x + [4, 6], [4, 6], [4, 6], [4, 6], // 0010xx + [4, 5], [4, 5], [4, 5], [4, 5], // 0011xx + [3, 1], [3, 1], [3, 1], [3, 1], // 010xxx + [3, 1], [3, 1], [3, 1], [3, 1], + [3, 4], [3, 4], [3, 4], [3, 4], // 011xxx + [3, 4], [3, 4], [3, 4], [3, 4], + [2, 3], [2, 3], [2, 3], [2, 3], // 10xxxx + [2, 3], [2, 3], [2, 3], [2, 3], + [2, 3], [2, 3], [2, 3], [2, 3], + [2, 3], [2, 3], [2, 3], [2, 3], + [2, 2], [2, 2], [2, 2], [2, 2], // 11xxxx + [2, 2], [2, 2], [2, 2], [2, 2], + [2, 2], [2, 2], [2, 2], [2, 2], + [2, 2], [2, 2], [2, 2], [2, 2] + ]; + + function CCITTFaxStream(str, params) { + this.str = str; + this.dict = str.dict; + + params = params || new Dict(); + + this.encoding = params.get('K') || 0; + this.eoline = params.get('EndOfLine') || false; + this.byteAlign = params.get('EncodedByteAlign') || false; + this.columns = params.get('Columns') || 1728; + this.rows = params.get('Rows') || 0; + var eoblock = params.get('EndOfBlock'); + if (eoblock === null || eoblock === undefined) + eoblock = true; + this.eoblock = eoblock; + this.black = params.get('BlackIs1') || false; + + this.codingLine = new Uint32Array(this.columns + 1); + this.refLine = new Uint32Array(this.columns + 2); + + this.codingLine[0] = this.columns; + this.codingPos = 0; + + this.row = 0; + this.nextLine2D = this.encoding < 0; + this.inputBits = 0; + this.inputBuf = 0; + this.outputBits = 0; + this.buf = EOF; + + var code1; + while ((code1 = this.lookBits(12)) === 0) { + this.eatBits(1); + } + if (code1 == 1) { + this.eatBits(12); + } + if (this.encoding > 0) { + this.nextLine2D = !this.lookBits(1); + this.eatBits(1); + } + + DecodeStream.call(this); + } + + CCITTFaxStream.prototype = Object.create(DecodeStream.prototype); + + 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) { + var codingLine = this.codingLine; + var codingPos = this.codingPos; + + if (a1 > codingLine[codingPos]) { + if (a1 > this.columns) { + info('row is wrong length'); + this.err = true; + a1 = this.columns; + } + if ((codingPos & 1) ^ blackPixels) { + ++codingPos; + } + + codingLine[codingPos] = a1; + } + this.codingPos = codingPos; + }; + + CCITTFaxStream.prototype.addPixelsNeg = + function ccittFaxStreamAddPixelsNeg(a1, blackPixels) { + var codingLine = this.codingLine; + var codingPos = this.codingPos; + + if (a1 > codingLine[codingPos]) { + if (a1 > this.columns) { + info('row is wrong length'); + this.err = true; + a1 = this.columns; + } + if ((codingPos & 1) ^ blackPixels) + ++codingPos; + + codingLine[codingPos] = a1; + } else if (a1 < codingLine[codingPos]) { + if (a1 < 0) { + info('invalid code'); + this.err = true; + a1 = 0; + } + while (codingPos > 0 && a1 < codingLine[codingPos - 1]) + --codingPos; + codingLine[codingPos] = a1; + } + + this.codingPos = codingPos; + }; + + CCITTFaxStream.prototype.lookChar = function CCITTFaxStream_lookChar() { + if (this.buf != EOF) + return this.buf; + + var refLine = this.refLine; + var codingLine = this.codingLine; + var columns = this.columns; + + var refPos, blackPixels, bits; + + if (this.outputBits === 0) { + if (this.eof) + return null; + + this.err = false; + + var code1, code2, code3; + if (this.nextLine2D) { + for (var i = 0; codingLine[i] < columns; ++i) + refLine[i] = codingLine[i]; + + refLine[i++] = columns; + refLine[i] = columns; + codingLine[0] = 0; + this.codingPos = 0; + refPos = 0; + blackPixels = 0; + + while (codingLine[this.codingPos] < columns) { + code1 = this.getTwoDimCode(); + switch (code1) { + case twoDimPass: + this.addPixels(refLine[refPos + 1], blackPixels); + if (refLine[refPos + 1] < columns) + refPos += 2; + break; + case twoDimHoriz: + code1 = code2 = 0; + if (blackPixels) { + do { + code1 += (code3 = this.getBlackCode()); + } while (code3 >= 64); + do { + code2 += (code3 = this.getWhiteCode()); + } while (code3 >= 64); + } else { + do { + code1 += (code3 = this.getWhiteCode()); + } while (code3 >= 64); + do { + code2 += (code3 = this.getBlackCode()); + } while (code3 >= 64); + } + this.addPixels(codingLine[this.codingPos] + + code1, blackPixels); + if (codingLine[this.codingPos] < columns) { + this.addPixels(codingLine[this.codingPos] + code2, + blackPixels ^ 1); + } + while (refLine[refPos] <= codingLine[this.codingPos] && + refLine[refPos] < columns) { + refPos += 2; + } + break; + case twoDimVertR3: + this.addPixels(refLine[refPos] + 3, blackPixels); + blackPixels ^= 1; + if (codingLine[this.codingPos] < columns) { + ++refPos; + while (refLine[refPos] <= codingLine[this.codingPos] && + refLine[refPos] < columns) + refPos += 2; + } + break; + case twoDimVertR2: + this.addPixels(refLine[refPos] + 2, blackPixels); + blackPixels ^= 1; + if (codingLine[this.codingPos] < columns) { + ++refPos; + while (refLine[refPos] <= codingLine[this.codingPos] && + refLine[refPos] < columns) { + refPos += 2; + } + } + break; + case twoDimVertR1: + this.addPixels(refLine[refPos] + 1, blackPixels); + blackPixels ^= 1; + if (codingLine[this.codingPos] < columns) { + ++refPos; + while (refLine[refPos] <= codingLine[this.codingPos] && + refLine[refPos] < columns) + refPos += 2; + } + break; + case twoDimVert0: + this.addPixels(refLine[refPos], blackPixels); + blackPixels ^= 1; + if (codingLine[this.codingPos] < columns) { + ++refPos; + while (refLine[refPos] <= codingLine[this.codingPos] && + refLine[refPos] < columns) + refPos += 2; + } + break; + case twoDimVertL3: + this.addPixelsNeg(refLine[refPos] - 3, blackPixels); + blackPixels ^= 1; + if (codingLine[this.codingPos] < columns) { + if (refPos > 0) + --refPos; + else + ++refPos; + while (refLine[refPos] <= codingLine[this.codingPos] && + refLine[refPos] < columns) + refPos += 2; + } + break; + case twoDimVertL2: + this.addPixelsNeg(refLine[refPos] - 2, blackPixels); + blackPixels ^= 1; + if (codingLine[this.codingPos] < columns) { + if (refPos > 0) + --refPos; + else + ++refPos; + while (refLine[refPos] <= codingLine[this.codingPos] && + refLine[refPos] < columns) + refPos += 2; + } + break; + case twoDimVertL1: + this.addPixelsNeg(refLine[refPos] - 1, blackPixels); + blackPixels ^= 1; + if (codingLine[this.codingPos] < columns) { + if (refPos > 0) + --refPos; + else + ++refPos; + + while (refLine[refPos] <= codingLine[this.codingPos] && + refLine[refPos] < columns) + refPos += 2; + } + break; + case EOF: + this.addPixels(columns, 0); + this.eof = true; + break; + default: + info('bad 2d code'); + this.addPixels(columns, 0); + this.err = true; + } + } + } else { + codingLine[0] = 0; + this.codingPos = 0; + blackPixels = 0; + while (codingLine[this.codingPos] < columns) { + code1 = 0; + if (blackPixels) { + do { + code1 += (code3 = this.getBlackCode()); + } while (code3 >= 64); + } else { + do { + code1 += (code3 = this.getWhiteCode()); + } while (code3 >= 64); + } + this.addPixels(codingLine[this.codingPos] + code1, blackPixels); + blackPixels ^= 1; + } + } + + if (this.byteAlign) + this.inputBits &= ~7; + + var gotEOL = false; + + 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 (code1 == 1) { + this.eatBits(12); + gotEOL = true; + } else if (code1 == EOF) { + this.eof = true; + } + } + + if (!this.eof && this.encoding > 0) { + this.nextLine2D = !this.lookBits(1); + this.eatBits(1); + } + + if (this.eoblock && gotEOL) { + code1 = this.lookBits(12); + if (code1 == 1) { + this.eatBits(12); + if (this.encoding > 0) { + this.lookBits(1); + this.eatBits(1); + } + if (this.encoding >= 0) { + for (var i = 0; i < 4; ++i) { + code1 = this.lookBits(12); + if (code1 != 1) + info('bad rtc code: ' + code1); + this.eatBits(12); + if (this.encoding > 0) { + this.lookBits(1); + this.eatBits(1); + } + } + } + this.eof = true; + } + } else if (this.err && this.eoline) { + while (true) { + code1 = this.lookBits(13); + if (code1 == EOF) { + this.eof = true; + return null; + } + if ((code1 >> 1) == 1) { + break; + } + this.eatBits(1); + } + this.eatBits(12); + if (this.encoding > 0) { + this.eatBits(1); + this.nextLine2D = !(code1 & 1); + } + } + + if (codingLine[0] > 0) + this.outputBits = codingLine[this.codingPos = 0]; + else + this.outputBits = codingLine[this.codingPos = 1]; + this.row++; + } + + if (this.outputBits >= 8) { + this.buf = (this.codingPos & 1) ? 0 : 0xFF; + this.outputBits -= 8; + if (this.outputBits === 0 && codingLine[this.codingPos] < columns) { + this.codingPos++; + this.outputBits = (codingLine[this.codingPos] - + codingLine[this.codingPos - 1]); + } + } else { + var bits = 8; + this.buf = 0; + do { + if (this.outputBits > bits) { + this.buf <<= bits; + if (!(this.codingPos & 1)) { + this.buf |= 0xFF >> (8 - bits); + } + this.outputBits -= bits; + bits = 0; + } else { + this.buf <<= this.outputBits; + if (!(this.codingPos & 1)) { + this.buf |= 0xFF >> (8 - this.outputBits); + } + bits -= this.outputBits; + this.outputBits = 0; + if (codingLine[this.codingPos] < columns) { + this.codingPos++; + this.outputBits = (codingLine[this.codingPos] - + codingLine[this.codingPos - 1]); + } else if (bits > 0) { + this.buf <<= bits; + bits = 0; + } + } + } while (bits); + } + if (this.black) { + this.buf ^= 0xFF; + } + return this.buf; + }; + + // This functions returns the code found from the table. + // The start and end parameters set the boundaries for searching the table. + // The limit parameter is optional. Function returns an array with three + // values. The first array element indicates whether a valid code is being + // returned. The second array element is the actual code. The third array + // element indicates whether EOF was reached. + CCITTFaxStream.prototype.findTableCode = + function ccittFaxStreamFindTableCode(start, end, table, limit) { + + var limitValue = limit || 0; + for (var i = start; i <= end; ++i) { + var code = this.lookBits(i); + if (code == EOF) + return [true, 1, false]; + if (i < end) + code <<= end - i; + if (!limitValue || code >= limitValue) { + var p = table[code - limitValue]; + if (p[0] == i) { + this.eatBits(i); + return [true, p[1], true]; + } + } + } + return [false, 0, false]; + }; + + CCITTFaxStream.prototype.getTwoDimCode = + function ccittFaxStreamGetTwoDimCode() { + + var code = 0; + var p; + if (this.eoblock) { + code = this.lookBits(7); + p = twoDimTable[code]; + if (p && p[0] > 0) { + this.eatBits(p[0]); + return p[1]; + } + } else { + var result = this.findTableCode(1, 7, twoDimTable); + if (result[0] && result[2]) + return result[1]; + } + info('Bad two dim code'); + return EOF; + }; + + CCITTFaxStream.prototype.getWhiteCode = + function ccittFaxStreamGetWhiteCode() { + + var code = 0; + var p; + var n; + if (this.eoblock) { + code = this.lookBits(12); + if (code == EOF) + return 1; + + if ((code >> 5) === 0) + p = whiteTable1[code]; + else + p = whiteTable2[code >> 3]; + + if (p[0] > 0) { + this.eatBits(p[0]); + return p[1]; + } + } else { + var result = this.findTableCode(1, 9, whiteTable2); + if (result[0]) + return result[1]; + + result = this.findTableCode(11, 12, whiteTable1); + if (result[0]) + return result[1]; + } + info('bad white code'); + this.eatBits(1); + return 1; + }; + + CCITTFaxStream.prototype.getBlackCode = + function ccittFaxStreamGetBlackCode() { + + var code, p; + if (this.eoblock) { + code = this.lookBits(13); + if (code == EOF) + return 1; + if ((code >> 7) === 0) + p = blackTable1[code]; + else if ((code >> 9) === 0 && (code >> 7) !== 0) + p = blackTable2[(code >> 1) - 64]; + else + p = blackTable3[code >> 7]; + + if (p[0] > 0) { + this.eatBits(p[0]); + return p[1]; + } + } else { + var result = this.findTableCode(2, 6, blackTable3); + if (result[0]) + return result[1]; + + result = this.findTableCode(7, 12, blackTable2, 64); + if (result[0]) + return result[1]; + + result = this.findTableCode(10, 13, blackTable1); + if (result[0]) + return result[1]; + } + info('bad black code'); + this.eatBits(1); + return 1; + }; + + CCITTFaxStream.prototype.lookBits = function CCITTFaxStream_lookBits(n) { + var c; + while (this.inputBits < n) { + if ((c = this.str.getByte()) === -1) { + if (this.inputBits === 0) + return EOF; + return ((this.inputBuf << (n - this.inputBits)) & + (0xFFFF >> (16 - n))); + } + this.inputBuf = (this.inputBuf << 8) + c; + this.inputBits += 8; + } + return (this.inputBuf >> (this.inputBits - n)) & (0xFFFF >> (16 - n)); + }; + + CCITTFaxStream.prototype.eatBits = function CCITTFaxStream_eatBits(n) { + if ((this.inputBits -= n) < 0) + this.inputBits = 0; + }; + + return CCITTFaxStream; +})(); + +var LZWStream = (function LZWStreamClosure() { + function LZWStream(str, earlyChange) { + this.str = str; + this.dict = str.dict; + this.cachedData = 0; + this.bitsCached = 0; + + var maxLzwDictionarySize = 4096; + var lzwState = { + earlyChange: earlyChange, + codeLength: 9, + nextCode: 258, + dictionaryValues: new Uint8Array(maxLzwDictionarySize), + dictionaryLengths: new Uint16Array(maxLzwDictionarySize), + dictionaryPrevCodes: new Uint16Array(maxLzwDictionarySize), + currentSequence: new Uint8Array(maxLzwDictionarySize), + currentSequenceLength: 0 + }; + for (var i = 0; i < 256; ++i) { + lzwState.dictionaryValues[i] = i; + lzwState.dictionaryLengths[i] = 1; + } + this.lzwState = lzwState; + + DecodeStream.call(this); + } + + LZWStream.prototype = Object.create(DecodeStream.prototype); + + LZWStream.prototype.readBits = function LZWStream_readBits(n) { + var bitsCached = this.bitsCached; + var cachedData = this.cachedData; + while (bitsCached < n) { + var c = this.str.getByte(); + if (c === -1) { + this.eof = true; + return null; + } + cachedData = (cachedData << 8) | c; + bitsCached += 8; + } + this.bitsCached = (bitsCached -= n); + this.cachedData = cachedData; + this.lastCode = null; + return (cachedData >>> bitsCached) & ((1 << n) - 1); + }; + + LZWStream.prototype.readBlock = function LZWStream_readBlock() { + var blockSize = 512; + var estimatedDecodedSize = blockSize * 2, decodedSizeDelta = blockSize; + var i, j, q; + + var lzwState = this.lzwState; + if (!lzwState) + return; // eof was found + + var earlyChange = lzwState.earlyChange; + var nextCode = lzwState.nextCode; + var dictionaryValues = lzwState.dictionaryValues; + var dictionaryLengths = lzwState.dictionaryLengths; + var dictionaryPrevCodes = lzwState.dictionaryPrevCodes; + var codeLength = lzwState.codeLength; + var prevCode = lzwState.prevCode; + var currentSequence = lzwState.currentSequence; + var currentSequenceLength = lzwState.currentSequenceLength; + + var decodedLength = 0; + var currentBufferLength = this.bufferLength; + var buffer = this.ensureBuffer(this.bufferLength + estimatedDecodedSize); + + for (i = 0; i < blockSize; i++) { + var code = this.readBits(codeLength); + var hasPrev = currentSequenceLength > 0; + if (code < 256) { + currentSequence[0] = code; + currentSequenceLength = 1; + } else if (code >= 258) { + if (code < nextCode) { + currentSequenceLength = dictionaryLengths[code]; + for (j = currentSequenceLength - 1, q = code; j >= 0; j--) { + currentSequence[j] = dictionaryValues[q]; + q = dictionaryPrevCodes[q]; + } + } else { + currentSequence[currentSequenceLength++] = currentSequence[0]; + } + } else if (code == 256) { + codeLength = 9; + nextCode = 258; + currentSequenceLength = 0; + continue; + } else { + this.eof = true; + delete this.lzwState; + break; + } + + if (hasPrev) { + dictionaryPrevCodes[nextCode] = prevCode; + dictionaryLengths[nextCode] = dictionaryLengths[prevCode] + 1; + dictionaryValues[nextCode] = currentSequence[0]; + nextCode++; + codeLength = (nextCode + earlyChange) & (nextCode + earlyChange - 1) ? + codeLength : Math.min(Math.log(nextCode + earlyChange) / + 0.6931471805599453 + 1, 12) | 0; + } + prevCode = code; + + decodedLength += currentSequenceLength; + if (estimatedDecodedSize < decodedLength) { + do { + estimatedDecodedSize += decodedSizeDelta; + } while (estimatedDecodedSize < decodedLength); + buffer = this.ensureBuffer(this.bufferLength + estimatedDecodedSize); + } + for (j = 0; j < currentSequenceLength; j++) + buffer[currentBufferLength++] = currentSequence[j]; + } + lzwState.nextCode = nextCode; + lzwState.codeLength = codeLength; + lzwState.prevCode = prevCode; + lzwState.currentSequenceLength = currentSequenceLength; + + this.bufferLength = currentBufferLength; + }; + + return LZWStream; +})(); + +var NullStream = (function NullStreamClosure() { + function NullStream() { + Stream.call(this, new Uint8Array(0)); + } + + NullStream.prototype = Stream.prototype; + + return NullStream; +})(); + + +var WorkerMessageHandler = PDFJS.WorkerMessageHandler = { + setup: function wphSetup(handler) { + var pdfManager; + + function loadDocument(recoveryMode) { + var loadDocumentPromise = new LegacyPromise(); + + 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 encryptedPromise = pdfManager.ensureXRef('encrypt'); + var javaScriptPromise = pdfManager.ensureCatalog('javaScript'); + Promise.all([numPagesPromise, fingerprintPromise, outlinePromise, + infoPromise, metadataPromise, encryptedPromise, + javaScriptPromise]).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] + }; + loadDocumentPromise.resolve(doc); + }, + parseFailure); + }; + + var parseFailure = function parseFailure(e) { + loadDocumentPromise.reject(e); + }; + + pdfManager.ensureModel('checkHeader', []).then(function() { + pdfManager.ensureModel('parseStartXRef', []).then(function() { + pdfManager.ensureModel('parse', [recoveryMode]).then( + parseSuccess, parseFailure); + }, parseFailure); + }, parseFailure); + + return loadDocumentPromise; + } + + function getPdfManager(data) { + var pdfManagerPromise = new LegacyPromise(); + + var source = data.source; + var disableRange = data.disableRange; + if (source.data) { + try { + pdfManager = new LocalPdfManager(source.data, source.password); + pdfManagerPromise.resolve(); + } catch (ex) { + pdfManagerPromise.reject(ex); + } + return pdfManagerPromise; + } else if (source.chunkedViewerLoading) { + try { + pdfManager = new NetworkPdfManager(source, handler); + pdfManagerPromise.resolve(); + } catch (ex) { + pdfManagerPromise.reject(ex); + } + return pdfManagerPromise; + } + + var networkManager = new NetworkManager(source.url, { + httpHeaders: source.httpHeaders, + withCredentials: source.withCredentials + }); + var fullRequestXhrId = networkManager.requestFull({ + onHeadersReceived: function onHeadersReceived() { + if (disableRange) { + return; + } + + var fullRequestXhr = networkManager.getRequestXhr(fullRequestXhrId); + if (fullRequestXhr.getResponseHeader('Accept-Ranges') !== 'bytes') { + return; + } + + var contentEncoding = + fullRequestXhr.getResponseHeader('Content-Encoding') || 'identity'; + if (contentEncoding !== 'identity') { + return; + } + + var length = fullRequestXhr.getResponseHeader('Content-Length'); + length = parseInt(length, 10); + if (!isInt(length)) { + return; + } + + // 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; + try { + pdfManager = new NetworkPdfManager(source, handler); + pdfManagerPromise.resolve(pdfManager); + } catch (ex) { + pdfManagerPromise.reject(ex); + } + }, + + onDone: function onDone(args) { + // the data is array, instantiating directly from it + try { + pdfManager = new LocalPdfManager(args.chunk, source.password); + pdfManagerPromise.resolve(); + } catch (ex) { + pdfManagerPromise.reject(ex); + } + }, + + onError: function onError(status) { + if (status == 404) { + var exception = new MissingPDFException( 'Missing PDF "' + + source.url + '".'); + handler.send('MissingPDF', { exception: exception }); + } else { + handler.send('DocError', 'Unexpected server response (' + + status + ') while retrieving PDF "' + + source.url + '".'); + } + }, + + onProgress: function onProgress(evt) { + handler.send('DocProgress', { + loaded: evt.loaded, + total: evt.lengthComputable ? evt.total : void(0) + }); + } + }); + + return pdfManagerPromise; + } + + handler.on('test', function wphSetupTest(data) { + // check if Uint8Array can be sent to worker + if (!(data instanceof Uint8Array)) { + handler.send('test', false); + return; + } + // making sure postMessage transfers are working + var supportTransfers = data[0] === 255; + handler.postMessageTransfers = supportTransfers; + // check if the response property is supported by xhr + var xhr = new XMLHttpRequest(); + var responseExists = 'response' in xhr; + // check if the property is actually implemented + try { + var dummy = xhr.responseType; + } catch (e) { + responseExists = false; + } + if (!responseExists) { + handler.send('test', false); + return; + } + handler.send('test', { + supportTypedArray: true, + supportTransfers: supportTransfers + }); + }); + + handler.on('GetDocRequest', function wphSetupDoc(data) { + + var onSuccess = function(doc) { + handler.send('GetDoc', { pdfInfo: doc }); + }; + + var onFailure = function(e) { + if (e instanceof PasswordException) { + if (e.code === PasswordResponses.NEED_PASSWORD) { + handler.send('NeedPassword', { + exception: e + }); + } else if (e.code === PasswordResponses.INCORRECT_PASSWORD) { + handler.send('IncorrectPassword', { + exception: e + }); + } + } else if (e instanceof InvalidPDFException) { + handler.send('InvalidPDF', { + exception: e + }); + } else if (e instanceof MissingPDFException) { + handler.send('MissingPDF', { + exception: e + }); + } else { + handler.send('UnknownError', { + exception: new UnknownErrorException(e.message, e.toString()) + }); + } + }; + + PDFJS.maxImageSize = data.maxImageSize === undefined ? + -1 : data.maxImageSize; + PDFJS.disableFontFace = data.disableFontFace; + PDFJS.disableCreateObjectURL = data.disableCreateObjectURL; + PDFJS.verbosity = data.verbosity; + + getPdfManager(data).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); + } + + onFailure(ex); + return; + } + + pdfManager.requestLoadedStream(); + pdfManager.onLoadedStream().then(function() { + loadDocument(true).then(onSuccess, onFailure); + }); + }, onFailure); + }, onFailure); + }); + + handler.on('GetPageRequest', function wphSetupGetPage(data) { + var pageIndex = data.pageIndex; + pdfManager.getPage(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( + function(results) { + var page = { + pageIndex: data.pageIndex, + rotate: results[0], + ref: results[1], + view: results[2] + }; + + handler.send('GetPage', { pageInfo: page }); + }); + }); + }); + + handler.on('GetPageIndex', function wphSetupGetPageIndex(data, deferred) { + var ref = new Ref(data.ref.num, data.ref.gen); + pdfManager.pdfModel.catalog.getPageIndex(ref).then(function (pageIndex) { + deferred.resolve(pageIndex); + }, deferred.reject); + }); + + handler.on('GetDestinations', + function wphSetupGetDestinations(data, deferred) { + pdfManager.ensureCatalog('destinations').then(function(destinations) { + deferred.resolve(destinations); + }); + } + ); + + handler.on('GetData', function wphSetupGetData(data, deferred) { + pdfManager.requestLoadedStream(); + pdfManager.onLoadedStream().then(function(stream) { + deferred.resolve(stream.bytes); + }); + }); + + handler.on('DataLoaded', function wphSetupDataLoaded(data, deferred) { + pdfManager.onLoadedStream().then(function(stream) { + deferred.resolve({ length: stream.bytes.byteLength }); + }); + }); + + 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('RenderPageRequest', function wphSetupRenderPage(data) { + pdfManager.getPage(data.pageIndex).then(function(page) { + + var pageNum = data.pageIndex + 1; + var start = Date.now(); + // Pre compile the pdf page and fetch the fonts/images. + page.getOperatorList(handler).then(function(operatorList) { + + info('page=%d - getOperatorList: time=%dms, len=%d', pageNum, + Date.now() - start, operatorList.fnArray.length); + + }, function(e) { + + var minimumStackMessage = + 'worker.js: while trying to getPage() and getOperatorList()'; + + var wrappedException; + + // Turn the error into an obj that can be serialized + if (typeof e === 'string') { + wrappedException = { + message: e, + stack: minimumStackMessage + }; + } else if (typeof e === 'object') { + wrappedException = { + message: e.message || e.toString(), + stack: e.stack || minimumStackMessage + }; + } else { + wrappedException = { + message: 'Unknown exception type: ' + (typeof e), + stack: minimumStackMessage + }; + } + + handler.send('PageError', { + pageNum: pageNum, + error: wrappedException + }); + }); + }); + }, this); + + handler.on('GetTextContent', function wphExtractText(data, deferred) { + 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); + }); + }); + }); + + handler.on('Cleanup', function wphCleanup(data, deferred) { + pdfManager.cleanup(); + deferred.resolve(true); + }); + + handler.on('Terminate', function wphTerminate(data, deferred) { + pdfManager.terminate(); + deferred.resolve(); + }); + } +}; + +var consoleTimer = {}; + +var workerConsole = { + log: function log() { + var args = Array.prototype.slice.call(arguments); + globalScope.postMessage({ + action: 'console_log', + data: args + }); + }, + + error: function error() { + var args = Array.prototype.slice.call(arguments); + globalScope.postMessage({ + action: 'console_error', + data: args + }); + throw 'pdf.js execution error'; + }, + + time: function time(name) { + consoleTimer[name] = Date.now(); + }, + + timeEnd: function timeEnd(name) { + var time = consoleTimer[name]; + if (!time) { + error('Unknown timer name ' + name); + } + this.log('Timer:', name, Date.now() - time); + } +}; + + +// Worker thread? +if (typeof window === 'undefined') { + if (!('console' in globalScope)) { + globalScope.console = workerConsole; + } + + // Listen for unsupported features so we can pass them on to the main thread. + PDFJS.UnsupportedManager.listen(function (msg) { + globalScope.postMessage({ + action: '_unsupported_feature', + data: msg + }); + }); + + var handler = new MessageHandler('worker_processor', this); + WorkerMessageHandler.setup(handler); +} + + +var JpxImage = (function JpxImageClosure() { + // Table E.1 + var SubbandsGainLog2 = { + 'LL': 0, + 'LH': 1, + 'HL': 1, + 'HH': 2 + }; + function JpxImage() { + 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 position = 0, length = data.length; + while (position < length) { + var headerSize = 8; + var lbox = readUint(data, position, 4); + var tbox = readUint(data, position + 4, 4); + position += headerSize; + if (lbox == 1) { + lbox = readUint(data, position, 8); + position += 8; + headerSize += 8; + } + if (lbox === 0) + lbox = length - position + headerSize; + if (lbox < headerSize) + 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 + break; + case 0x6A703263: // 'jp2c' + this.parseCodestream(data, position, position + dataLength); + break; + } + if (jumpDataLength) + position += dataLength; + } + }, + parseCodestream: function JpxImage_parseCodestream(data, start, end) { + var context = {}; + try { + var position = start; + while (position < end) { + var code = readUint16(data, position); + position += 2; + + var length = 0, j; + switch (code) { + case 0xFF4F: // Start of codestream (SOC) + context.mainHeader = true; + break; + case 0xFFD9: // End of codestream (EOC) + break; + case 0xFF51: // Image and tile size (SIZ) + length = readUint16(data, position); + var siz = {}; + siz.Xsiz = readUint32(data, position + 4); + siz.Ysiz = readUint32(data, position + 8); + siz.XOsiz = readUint32(data, position + 12); + siz.YOsiz = readUint32(data, position + 16); + siz.XTsiz = readUint32(data, position + 20); + siz.YTsiz = readUint32(data, position + 24); + siz.XTOsiz = readUint32(data, position + 28); + siz.YTOsiz = readUint32(data, position + 32); + var componentsCount = readUint16(data, position + 36); + siz.Csiz = componentsCount; + var components = []; + j = position + 38; + for (var i = 0; i < componentsCount; i++) { + var component = { + precision: (data[j] & 0x7F) + 1, + isSigned: !!(data[j] & 0x80), + XRsiz: data[j + 1], + YRsiz: data[j + 1] + }; + calculateComponentDimensions(component, siz); + components.push(component); + } + context.SIZ = siz; + context.components = components; + calculateTileGrids(context, components); + context.QCC = []; + context.COC = []; + break; + case 0xFF5C: // Quantization default (QCD) + length = readUint16(data, position); + var qcd = {}; + j = position + 2; + var sqcd = data[j++]; + var spqcdSize, scalarExpounded; + switch (sqcd & 0x1F) { + case 0: + spqcdSize = 8; + scalarExpounded = true; + break; + case 1: + spqcdSize = 16; + scalarExpounded = false; + break; + case 2: + spqcdSize = 16; + scalarExpounded = true; + break; + default: + throw 'Invalid SQcd value ' + sqcd; + } + qcd.noQuantization = spqcdSize == 8; + qcd.scalarExpounded = scalarExpounded; + qcd.guardBits = sqcd >> 5; + var spqcds = []; + while (j < length + position) { + var spqcd = {}; + if (spqcdSize == 8) { + spqcd.epsilon = data[j++] >> 3; + spqcd.mu = 0; + } else { + spqcd.epsilon = data[j] >> 3; + spqcd.mu = ((data[j] & 0x7) << 8) | data[j + 1]; + j += 2; + } + spqcds.push(spqcd); + } + qcd.SPqcds = spqcds; + if (context.mainHeader) + context.QCD = qcd; + else { + context.currentTile.QCD = qcd; + context.currentTile.QCC = []; + } + break; + case 0xFF5D: // Quantization component (QCC) + length = readUint16(data, position); + var qcc = {}; + j = position + 2; + var cqcc; + if (context.SIZ.Csiz < 257) + cqcc = data[j++]; + else { + cqcc = readUint16(data, j); + j += 2; + } + var sqcd = data[j++]; + var spqcdSize, scalarExpounded; + switch (sqcd & 0x1F) { + case 0: + spqcdSize = 8; + scalarExpounded = true; + break; + case 1: + spqcdSize = 16; + scalarExpounded = false; + break; + case 2: + spqcdSize = 16; + scalarExpounded = true; + break; + default: + throw 'Invalid SQcd value ' + sqcd; + } + qcc.noQuantization = spqcdSize == 8; + qcc.scalarExpounded = scalarExpounded; + qcc.guardBits = sqcd >> 5; + var spqcds = []; + while (j < length + position) { + var spqcd = {}; + if (spqcdSize == 8) { + spqcd.epsilon = data[j++] >> 3; + spqcd.mu = 0; + } else { + spqcd.epsilon = data[j] >> 3; + spqcd.mu = ((data[j] & 0x7) << 8) | data[j + 1]; + j += 2; + } + spqcds.push(spqcd); + } + qcc.SPqcds = spqcds; + if (context.mainHeader) + context.QCC[cqcc] = qcc; + else + context.currentTile.QCC[cqcc] = qcc; + break; + case 0xFF52: // Coding style default (COD) + length = readUint16(data, position); + var cod = {}; + j = position + 2; + var scod = data[j++]; + cod.entropyCoderWithCustomPrecincts = !!(scod & 1); + cod.sopMarkerUsed = !!(scod & 2); + cod.ephMarkerUsed = !!(scod & 4); + var codingStyle = {}; + cod.progressionOrder = data[j++]; + cod.layersCount = readUint16(data, j); + j += 2; + cod.multipleComponentTransform = data[j++]; + + cod.decompositionLevelsCount = data[j++]; + cod.xcb = (data[j++] & 0xF) + 2; + cod.ycb = (data[j++] & 0xF) + 2; + var blockStyle = data[j++]; + cod.selectiveArithmeticCodingBypass = !!(blockStyle & 1); + cod.resetContextProbabilities = !!(blockStyle & 2); + cod.terminationOnEachCodingPass = !!(blockStyle & 4); + cod.verticalyStripe = !!(blockStyle & 8); + cod.predictableTermination = !!(blockStyle & 16); + cod.segmentationSymbolUsed = !!(blockStyle & 32); + cod.transformation = data[j++]; + if (cod.entropyCoderWithCustomPrecincts) { + var precinctsSizes = {}; + while (j < length + position) { + var precinctsSize = data[j]; + precinctsSizes.push({ + PPx: precinctsSize & 0xF, + PPy: precinctsSize >> 4 + }); + } + cod.precinctsSizes = precinctsSizes; + } + + 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) + context.COD = cod; + else { + context.currentTile.COD = cod; + context.currentTile.COC = []; + } + break; + case 0xFF90: // Start of tile-part (SOT) + length = readUint16(data, position); + var tile = {}; + tile.index = readUint16(data, position + 2); + tile.length = readUint32(data, position + 4); + tile.dataEnd = tile.length + position - 2; + tile.partIndex = data[position + 8]; + tile.partsCount = data[position + 9]; + + context.mainHeader = false; + if (tile.partIndex === 0) { + // reset component specific settings + tile.COD = context.COD; + tile.COC = context.COC.slice(0); // clone of the global COC + tile.QCD = context.QCD; + tile.QCC = context.QCC.slice(0); // clone of the global COC + } + context.currentTile = tile; + break; + case 0xFF93: // Start of data (SOD) + var tile = context.currentTile; + if (tile.partIndex === 0) { + initializeTile(context, tile.index); + buildPackets(context); + } + + // moving to the end of the data + length = tile.dataEnd - position; + + parseTilePackets(context, data, position, length); + break; + case 0xFF64: // Comment (COM) + length = readUint16(data, position); + // skipping content + break; + default: + throw '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'); + } + this.tiles = transformComponents(context); + this.width = context.SIZ.Xsiz - context.SIZ.XOsiz; + this.height = context.SIZ.Ysiz - context.SIZ.YOsiz; + this.componentsCount = context.SIZ.Csiz; + } + }; + function 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); + component.x1 = Math.ceil(siz.Xsiz / component.XRsiz); + component.y0 = Math.ceil(siz.YOsiz / component.YRsiz); + component.y1 = Math.ceil(siz.Ysiz / component.YRsiz); + component.width = component.x1 - component.x0; + component.height = component.y1 - component.y0; + } + function calculateTileGrids(context, components) { + var siz = context.SIZ; + // Section B.3 Division into tile and tile-components + var 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.tx0 = Math.max(siz.XTOsiz + p * siz.XTsiz, siz.XOsiz); + tile.ty0 = Math.max(siz.YTOsiz + q * siz.YTsiz, siz.YOsiz); + tile.tx1 = Math.min(siz.XTOsiz + (p + 1) * siz.XTsiz, siz.Xsiz); + tile.ty1 = Math.min(siz.YTOsiz + (q + 1) * siz.YTsiz, siz.Ysiz); + tile.width = tile.tx1 - tile.tx0; + tile.height = tile.ty1 - tile.ty0; + tile.components = []; + tiles.push(tile); + } + } + context.tiles = tiles; + + var componentsCount = siz.Csiz; + for (var i = 0, ii = componentsCount; i < ii; i++) { + var component = components[i]; + var tileComponents = []; + for (var j = 0, jj = tiles.length; j < jj; j++) { + var tileComponent = {}, tile = tiles[j]; + tileComponent.tcx0 = Math.ceil(tile.tx0 / component.XRsiz); + tileComponent.tcy0 = Math.ceil(tile.ty0 / component.YRsiz); + tileComponent.tcx1 = Math.ceil(tile.tx1 / component.XRsiz); + tileComponent.tcy1 = Math.ceil(tile.ty1 / component.YRsiz); + tileComponent.width = tileComponent.tcx1 - tileComponent.tcx0; + tileComponent.height = tileComponent.tcy1 - tileComponent.tcy0; + tile.components[i] = tileComponent; + } + } + } + function getBlocksDimensions(context, component, r) { + var codOrCoc = component.codingStyleParameters; + var result = {}; + if (!codOrCoc.entropyCoderWithCustomPrecincts) { + result.PPx = 15; + result.PPy = 15; + } else { + result.PPx = codOrCoc.precinctsSizes[r].PPx; + result.PPy = codOrCoc.precinctsSizes[r].PPy; + } + // calculate codeblock size as described in section B.7 + result.xcb_ = r > 0 ? Math.min(codOrCoc.xcb, result.PPx - 1) : + Math.min(codOrCoc.xcb, result.PPx); + result.ycb_ = r > 0 ? Math.min(codOrCoc.ycb, result.PPy - 1) : + Math.min(codOrCoc.ycb, result.PPy); + return result; + } + function buildPrecincts(context, resolution, dimensions) { + // Section B.6 Division resolution to precincts + var precinctWidth = 1 << dimensions.PPx; + var precinctHeight = 1 << dimensions.PPy; + var numprecinctswide = resolution.trx1 > resolution.trx0 ? + Math.ceil(resolution.trx1 / precinctWidth) - + Math.floor(resolution.trx0 / precinctWidth) : 0; + var numprecinctshigh = resolution.try1 > resolution.try0 ? + Math.ceil(resolution.try1 / precinctHeight) - + Math.floor(resolution.try0 / precinctHeight) : 0; + var numprecincts = numprecinctswide * numprecinctshigh; + 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 + }; + } + function buildCodeblocks(context, subband, dimensions) { + // Section B.7 Division sub-band into code-blocks + var xcb_ = dimensions.xcb_; + var ycb_ = dimensions.ycb_; + var codeblockWidth = 1 << xcb_; + var codeblockHeight = 1 << ycb_; + var cbx0 = 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 precinctParameters = subband.resolution.precinctParameters; + var codeblocks = []; + var precincts = []; + for (var j = cby0; j < cby1; j++) { + for (var i = cbx0; i < cbx1; i++) { + var codeblock = { + cbx: i, + cby: j, + tbx0: codeblockWidth * i, + tby0: codeblockHeight * j, + 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); + codeblock.precinctNumber = precinctNumber; + codeblock.subbandType = subband.type; + var coefficientsLength = (codeblock.tbx1_ - codeblock.tbx0_) * + (codeblock.tby1_ - codeblock.tby0_); + codeblock.Lblock = 3; + 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); + } else { + precincts[precinctNumber] = precinct = { + cbxMin: i, + cbyMin: j, + cbxMax: i, + cbyMax: j + }; + } + codeblock.precinct = precinct; + } + } + subband.codeblockParameters = { + codeblockWidth: xcb_, + codeblockHeight: ycb_, + numcodeblockwide: cbx1 - cbx0 + 1, + numcodeblockhigh: cby1 - cby1 + 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) { + var precinctCodeblocks = []; + // Section B.10.8 Order of info in packet + var subbands = resolution.subbands; + // sub-bands already ordered in 'LL', 'HL', 'LH', and 'HH' sequence + for (var i = 0, ii = subbands.length; i < ii; i++) { + var subband = subbands[i]; + var codeblocks = subband.codeblocks; + for (var j = 0, jj = codeblocks.length; j < jj; j++) { + var codeblock = codeblocks[j]; + if (codeblock.precinctNumber != precinctNumber) + continue; + precinctCodeblocks.push(codeblock); + } + } + return { + layerNumber: layerNumber, + codeblocks: precinctCodeblocks + }; + } + function LayerResolutionComponentPositionIterator(context) { + var siz = context.SIZ; + var tileIndex = context.currentTile.index; + var tile = context.tiles[tileIndex]; + var layersCount = tile.codingStyleDefaultParameters.layersCount; + var componentsCount = siz.Csiz; + var maxDecompositionLevelsCount = 0; + for (var q = 0; q < componentsCount; q++) { + maxDecompositionLevelsCount = Math.max(maxDecompositionLevelsCount, + tile.components[q].codingStyleParameters.decompositionLevelsCount); + } + + var l = 0, r = 0, i = 0, k = 0; + + this.nextPacket = function JpxImage_nextPacket() { + // Section B.12.1.1 Layer-resolution-component-position + for (; l < layersCount; l++) { + for (; r <= maxDecompositionLevelsCount; r++) { + for (; i < componentsCount; i++) { + var component = tile.components[i]; + if (r > component.codingStyleParameters.decompositionLevelsCount) + continue; + + var resolution = component.resolutions[r]; + var numprecincts = resolution.precinctParameters.numprecincts; + for (; k < numprecincts;) { + var packet = createPacket(resolution, k, l); + k++; + return packet; + } + k = 0; + } + i = 0; + } + r = 0; + } + throw 'Out of packets'; + }; + } + function ResolutionLayerComponentPositionIterator(context) { + var siz = context.SIZ; + var tileIndex = context.currentTile.index; + var tile = context.tiles[tileIndex]; + var layersCount = tile.codingStyleDefaultParameters.layersCount; + var componentsCount = siz.Csiz; + var maxDecompositionLevelsCount = 0; + for (var q = 0; q < componentsCount; q++) { + maxDecompositionLevelsCount = Math.max(maxDecompositionLevelsCount, + tile.components[q].codingStyleParameters.decompositionLevelsCount); + } + + var r = 0, l = 0, i = 0, k = 0; + + this.nextPacket = function JpxImage_nextPacket() { + // Section B.12.1.2 Resolution-layer-component-position + for (; r <= maxDecompositionLevelsCount; r++) { + for (; l < layersCount; l++) { + for (; i < componentsCount; i++) { + var component = tile.components[i]; + if (r > component.codingStyleParameters.decompositionLevelsCount) + continue; + + var resolution = component.resolutions[r]; + var numprecincts = resolution.precinctParameters.numprecincts; + for (; k < numprecincts;) { + var packet = createPacket(resolution, k, l); + k++; + return packet; + } + k = 0; + } + i = 0; + } + l = 0; + } + throw 'Out of packets'; + }; + } + function buildPackets(context) { + var siz = context.SIZ; + var tileIndex = context.currentTile.index; + var tile = context.tiles[tileIndex]; + var componentsCount = siz.Csiz; + // Creating resolutions and sub-bands for each component + for (var c = 0; c < componentsCount; c++) { + var component = tile.components[c]; + var decompositionLevelsCount = + component.codingStyleParameters.decompositionLevelsCount; + // Section B.5 Resolution levels and sub-bands + var resolutions = []; + var subbands = []; + for (var r = 0; r <= decompositionLevelsCount; r++) { + var blocksDimensions = getBlocksDimensions(context, component, r); + var resolution = {}; + var scale = 1 << (decompositionLevelsCount - r); + resolution.trx0 = Math.ceil(component.tcx0 / scale); + resolution.try0 = Math.ceil(component.tcy0 / scale); + resolution.trx1 = Math.ceil(component.tcx1 / scale); + resolution.try1 = Math.ceil(component.tcy1 / scale); + buildPrecincts(context, resolution, blocksDimensions); + resolutions.push(resolution); + + var subband; + if (r === 0) { + // one sub-band (LL) with last decomposition + subband = {}; + subband.type = 'LL'; + subband.tbx0 = Math.ceil(component.tcx0 / scale); + subband.tby0 = Math.ceil(component.tcy0 / scale); + subband.tbx1 = Math.ceil(component.tcx1 / scale); + subband.tby1 = Math.ceil(component.tcy1 / scale); + subband.resolution = resolution; + buildCodeblocks(context, subband, blocksDimensions); + subbands.push(subband); + resolution.subbands = [subband]; + } else { + var bscale = 1 << (decompositionLevelsCount - r + 1); + var resolutionSubbands = []; + // three sub-bands (HL, LH and HH) with rest of decompositions + subband = {}; + subband.type = 'HL'; + subband.tbx0 = Math.ceil(component.tcx0 / bscale - 0.5); + subband.tby0 = Math.ceil(component.tcy0 / bscale); + subband.tbx1 = Math.ceil(component.tcx1 / bscale - 0.5); + subband.tby1 = Math.ceil(component.tcy1 / bscale); + subband.resolution = resolution; + buildCodeblocks(context, subband, blocksDimensions); + subbands.push(subband); + resolutionSubbands.push(subband); + + subband = {}; + subband.type = 'LH'; + subband.tbx0 = Math.ceil(component.tcx0 / bscale); + subband.tby0 = Math.ceil(component.tcy0 / bscale - 0.5); + subband.tbx1 = Math.ceil(component.tcx1 / bscale); + subband.tby1 = Math.ceil(component.tcy1 / bscale - 0.5); + subband.resolution = resolution; + buildCodeblocks(context, subband, blocksDimensions); + subbands.push(subband); + resolutionSubbands.push(subband); + + subband = {}; + subband.type = 'HH'; + subband.tbx0 = Math.ceil(component.tcx0 / bscale - 0.5); + subband.tby0 = Math.ceil(component.tcy0 / bscale - 0.5); + subband.tbx1 = Math.ceil(component.tcx1 / bscale - 0.5); + subband.tby1 = Math.ceil(component.tcy1 / bscale - 0.5); + subband.resolution = resolution; + buildCodeblocks(context, subband, blocksDimensions); + subbands.push(subband); + resolutionSubbands.push(subband); + + resolution.subbands = resolutionSubbands; + } + } + component.resolutions = resolutions; + component.subbands = subbands; + } + // Generate the packets sequence + var progressionOrder = tile.codingStyleDefaultParameters.progressionOrder; + var packetsIterator; + switch (progressionOrder) { + case 0: + tile.packetsIterator = + new LayerResolutionComponentPositionIterator(context); + break; + case 1: + tile.packetsIterator = + new ResolutionLayerComponentPositionIterator(context); + break; + default: + throw 'Unsupported progression order ' + progressionOrder; + } + } + function parseTilePackets(context, data, offset, dataLength) { + var position = 0; + var buffer, bufferSize = 0, skipNextBit = false; + function readBits(count) { + while (bufferSize < count) { + var b = data[offset + position]; + position++; + if (skipNextBit) { + buffer = (buffer << 7) | b; + bufferSize += 7; + skipNextBit = false; + } else { + buffer = (buffer << 8) | b; + bufferSize += 8; + } + if (b == 0xFF) { + skipNextBit = true; + } + } + bufferSize -= count; + return (buffer >>> bufferSize) & ((1 << count) - 1); + } + function alignToByte() { + bufferSize = 0; + if (skipNextBit) { + position++; + skipNextBit = false; + } + } + function readCodingpasses() { + var value = readBits(1); + if (value === 0) + return 1; + value = (value << 1) | readBits(1); + if (value == 0x02) + 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 tileIndex = context.currentTile.index; + var tile = context.tiles[tileIndex]; + var packetsIterator = tile.packetsIterator; + while (position < dataLength) { + var packet = packetsIterator.nextPacket(); + if (!readBits(1)) { + alignToByte(); + continue; + } + var layerNumber = packet.layerNumber; + var queue = []; + for (var i = 0, ii = packet.codeblocks.length; i < ii; i++) { + var 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) { + codeblockIncluded = !!readBits(1); + } else { + // reading inclusion tree + var precinct = codeblock.precinct; + var inclusionTree, zeroBitPlanesTree; + if ('inclusionTree' in precinct) { + inclusionTree = precinct.inclusionTree; + } else { + // building inclusion and zero bit-planes trees + var width = precinct.cbxMax - precinct.cbxMin + 1; + var height = precinct.cbyMax - precinct.cbyMin + 1; + inclusionTree = new InclusionTree(width, height, layerNumber); + zeroBitPlanesTree = new TagTree(width, height); + precinct.inclusionTree = inclusionTree; + precinct.zeroBitPlanesTree = zeroBitPlanesTree; + } + + if (inclusionTree.reset(codeblockColumn, codeblockRow, layerNumber)) { + while (true) { + if (readBits(1)) { + var valueReady = !inclusionTree.nextLevel(); + if (valueReady) { + codeblock.included = true; + codeblockIncluded = firstTimeInclusion = true; + break; + } + } else { + inclusionTree.incrementValue(layerNumber); + break; + } + } + } + } + if (!codeblockIncluded) + continue; + if (firstTimeInclusion) { + zeroBitPlanesTree = precinct.zeroBitPlanesTree; + zeroBitPlanesTree.reset(codeblockColumn, codeblockRow); + while (true) { + if (readBits(1)) { + var valueReady = !zeroBitPlanesTree.nextLevel(); + if (valueReady) + break; + } else + zeroBitPlanesTree.incrementValue(); + } + codeblock.zeroBitPlanes = zeroBitPlanesTree.value; + } + var codingpasses = readCodingpasses(); + while (readBits(1)) + codeblock.Lblock++; + var codingpassesLog2 = log2(codingpasses); + // rounding down log2 + var bits = ((codingpasses < (1 << codingpassesLog2)) ? + codingpassesLog2 - 1 : codingpassesLog2) + codeblock.Lblock; + var codedDataLength = readBits(bits); + queue.push({ + codeblock: codeblock, + codingpasses: codingpasses, + dataLength: codedDataLength + }); + } + alignToByte(); + while (queue.length > 0) { + var packetItem = queue.shift(); + var codeblock = packetItem.codeblock; + if (!('data' in codeblock)) + codeblock.data = []; + codeblock.data.push({ + data: data, + start: offset + position, + end: offset + position + packetItem.dataLength, + codingpasses: packetItem.codingpasses + }); + position += packetItem.dataLength; + } + } + return position; + } + function copyCoefficients(coefficients, x0, y0, width, height, + delta, mb, codeblocks, transformation, + segmentationSymbolUsed) { + var r = 0.5; // formula (E-6) + for (var i = 0, ii = codeblocks.length; i < ii; ++i) { + var codeblock = codeblocks[i]; + var blockWidth = codeblock.tbx1_ - codeblock.tbx0_; + var blockHeight = codeblock.tby1_ - codeblock.tby0_; + if (blockWidth === 0 || blockHeight === 0) + continue; + if (!('data' in codeblock)) + continue; + + var bitModel, currentCodingpassType; + bitModel = new BitModel(blockWidth, blockHeight, codeblock.subbandType, + codeblock.zeroBitPlanes); + 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]; + 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 chunk = dataItem.data.subarray(dataItem.start, dataItem.end); + encodedData.set(chunk, k); + k += chunk.length; + } + // decoding the item + var decoder = new ArithmeticDecoder(encodedData, 0, totalLength); + bitModel.setDecoder(decoder); + + for (var q = 0; q < codingpasses; q++) { + switch (currentCodingpassType) { + case 0: + bitModel.runSignificancePropogationPass(); + break; + case 1: + bitModel.runMagnitudeRefinementPass(); + break; + case 2: + bitModel.runCleanupPass(); + if (segmentationSymbolUsed) + bitModel.checkSegmentationSymbol(); + break; + } + currentCodingpassType = (currentCodingpassType + 1) % 3; + } + + var offset = (codeblock.tbx0_ - x0) + (codeblock.tby0_ - y0) * width; + var 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; + position++; + } + offset += width - blockWidth; + } + } + } + function transformTile(context, tile, c) { + var component = tile.components[c]; + var codingStyleParameters = component.codingStyleParameters; + var quantizationParameters = component.quantizationParameters; + var decompositionLevelsCount = + codingStyleParameters.decompositionLevelsCount; + var spqcds = quantizationParameters.SPqcds; + var scalarExpounded = quantizationParameters.scalarExpounded; + var guardBits = quantizationParameters.guardBits; + var transformation = codingStyleParameters.transformation; + var segmentationSymbolUsed = codingStyleParameters.segmentationSymbolUsed; + var precision = context.components[c].precision; + + var subbandCoefficients = []; + var k = 0, b = 0; + for (var i = 0; i <= decompositionLevelsCount; i++) { + var resolution = component.resolutions[i]; + + for (var j = 0, jj = resolution.subbands.length; j < jj; j++) { + var mu, epsilon; + if (!scalarExpounded) { + // formula E-5 + mu = spqcds[0].mu; + epsilon = spqcds[0].epsilon + (i > 0 ? 1 - i : 0); + } else { + mu = spqcds[b].mu; + epsilon = spqcds[b].epsilon; + } + + 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 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++; + } + } + + var transformation = codingStyleParameters.transformation; + var transform = transformation === 0 ? new IrreversibleTransform() : + new ReversibleTransform(); + var result = transform.calculate(subbandCoefficients, + component.tcx0, component.tcy0); + return { + left: component.tcx0, + top: component.tcy0, + width: result.width, + height: result.height, + items: result.items + }; + } + function transformComponents(context) { + var siz = context.SIZ; + var components = context.components; + var componentsCount = siz.Csiz; + var resultImages = []; + for (var i = 0, ii = context.tiles.length; i < ii; i++) { + var tile = context.tiles[i]; + var result = []; + for (var c = 0; c < componentsCount; c++) { + var image = transformTile(context, tile, c); + result.push(image); + } + + // Section G.2.2 Inverse multi component transform + 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; + } + } + + // 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; + } + function initializeTile(context, tileIndex) { + 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; + component.quantizationParameters = qcdOrQcc; + var codOrCoc = c in context.currentTile.COC ? + context.currentTile.COC[c] : context.currentTile.COD; + component.codingStyleParameters = codOrCoc; + } + tile.codingStyleDefaultParameters = context.currentTile.COD; + } + + // Section B.10.2 Tag trees + var TagTree = (function TagTreeClosure() { + function TagTree(width, height) { + var levelsLength = log2(Math.max(width, height)) + 1; + this.levels = []; + for (var i = 0; i < levelsLength; i++) { + var level = { + width: width, + height: height, + items: [] + }; + this.levels.push(level); + width = Math.ceil(width / 2); + height = Math.ceil(height / 2); + } + } + TagTree.prototype = { + reset: function TagTree_reset(i, j) { + var currentLevel = 0, value = 0; + while (currentLevel < this.levels.length) { + var level = this.levels[currentLevel]; + var index = i + j * level.width; + if (index in level.items) { + value = level.items[index]; + break; + } + level.index = index; + i >>= 1; + j >>= 1; + currentLevel++; + } + currentLevel--; + var level = this.levels[currentLevel]; + level.items[level.index] = value; + this.currentLevel = currentLevel; + delete this.value; + }, + incrementValue: function TagTree_incrementValue() { + var level = this.levels[this.currentLevel]; + level.items[level.index]++; + }, + nextLevel: function TagTree_nextLevel() { + var currentLevel = this.currentLevel; + var level = this.levels[currentLevel]; + var value = level.items[level.index]; + currentLevel--; + if (currentLevel < 0) { + this.value = value; + return false; + } + + this.currentLevel = currentLevel; + var level = this.levels[currentLevel]; + level.items[level.index] = value; + return true; + } + }; + return TagTree; + })(); + + var InclusionTree = (function InclusionTreeClosure() { + function InclusionTree(width, height, defaultValue) { + var levelsLength = log2(Math.max(width, height)) + 1; + this.levels = []; + for (var i = 0; i < levelsLength; i++) { + var items = new Uint8Array(width * height); + for (var j = 0, jj = items.length; j < jj; j++) + items[j] = defaultValue; + + var level = { + width: width, + height: height, + items: items + }; + this.levels.push(level); + + width = Math.ceil(width / 2); + height = Math.ceil(height / 2); + } + } + InclusionTree.prototype = { + reset: function InclusionTree_reset(i, j, stopValue) { + var currentLevel = 0; + while (currentLevel < this.levels.length) { + var level = this.levels[currentLevel]; + var index = i + j * level.width; + level.index = index; + var value = level.items[index]; + + if (value == 0xFF) + break; + + if (value > stopValue) { + this.currentLevel = currentLevel; + // already know about this one, propagating the value to top levels + this.propagateValues(); + return false; + } + + i >>= 1; + j >>= 1; + currentLevel++; + } + this.currentLevel = currentLevel - 1; + return true; + }, + incrementValue: function InclusionTree_incrementValue(stopValue) { + var level = this.levels[this.currentLevel]; + level.items[level.index] = stopValue + 1; + this.propagateValues(); + }, + propagateValues: function InclusionTree_propagateValues() { + var levelIndex = this.currentLevel; + var level = this.levels[levelIndex]; + var currentValue = level.items[level.index]; + while (--levelIndex >= 0) { + var level = this.levels[levelIndex]; + level.items[level.index] = currentValue; + } + }, + nextLevel: function InclusionTree_nextLevel() { + var currentLevel = this.currentLevel; + var level = this.levels[currentLevel]; + var value = level.items[level.index]; + level.items[level.index] = 0xFF; + currentLevel--; + if (currentLevel < 0) + return false; + + this.currentLevel = currentLevel; + var level = this.levels[currentLevel]; + level.items[level.index] = value; + return true; + } + }; + 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() { + // Table D-1 + // The index is binary presentation: 0dddvvhh, ddd - sum of Di (0..4), + // vv - sum of Vi (0..2), and hh - sum of Hi (0..2) + var LLAndLHContextsLabel = new Uint8Array([ + 0, 5, 8, 0, 3, 7, 8, 0, 4, 7, 8, 0, 0, 0, 0, 0, 1, 6, 8, 0, 3, 7, 8, 0, 4, + 7, 8, 0, 0, 0, 0, 0, 2, 6, 8, 0, 3, 7, 8, 0, 4, 7, 8, 0, 0, 0, 0, 0, 2, 6, + 8, 0, 3, 7, 8, 0, 4, 7, 8, 0, 0, 0, 0, 0, 2, 6, 8, 0, 3, 7, 8, 0, 4, 7, 8 + ]); + var HLContextLabel = new Uint8Array([ + 0, 3, 4, 0, 5, 7, 7, 0, 8, 8, 8, 0, 0, 0, 0, 0, 1, 3, 4, 0, 6, 7, 7, 0, 8, + 8, 8, 0, 0, 0, 0, 0, 2, 3, 4, 0, 6, 7, 7, 0, 8, 8, 8, 0, 0, 0, 0, 0, 2, 3, + 4, 0, 6, 7, 7, 0, 8, 8, 8, 0, 0, 0, 0, 0, 2, 3, 4, 0, 6, 7, 7, 0, 8, 8, 8 + ]); + var HHContextLabel = new Uint8Array([ + 0, 1, 2, 0, 1, 2, 2, 0, 2, 2, 2, 0, 0, 0, 0, 0, 3, 4, 5, 0, 4, 5, 5, 0, 5, + 5, 5, 0, 0, 0, 0, 0, 6, 7, 7, 0, 7, 7, 7, 0, 7, 7, 7, 0, 0, 0, 0, 0, 8, 8, + 8, 0, 8, 8, 8, 0, 8, 8, 8, 0, 0, 0, 0, 0, 8, 8, 8, 0, 8, 8, 8, 0, 8, 8, 8 + ]); + + // 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) { + this.width = width; + this.height = height; + + this.contextLabelTable = subband == 'HH' ? HHContextLabel : + subband == 'HL' ? HLContextLabel : LLAndLHContextsLabel; + + var coefficientCount = width * height; + + // coefficients outside the encoding region treated as insignificant + // add border state cells for significanceState + this.neighborsSignificance = new Uint8Array(coefficientCount); + this.coefficentsSign = new Uint8Array(coefficientCount); + this.coefficentsMagnitude = new Uint32Array(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; + this.bitsDecoded = bitsDecoded; + + this.reset(); + } + + BitModel.prototype = { + setDecoder: function BitModel_setDecoder(decoder) { + 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}); + }, + setNeighborsSignificance: + function BitModel_setNeighborsSignificance(row, column) { + var neighborsSignificance = this.neighborsSignificance; + var width = this.width, height = this.height; + var index = row * width + column; + if (row > 0) { + if (column > 0) + neighborsSignificance[index - width - 1] += 0x10; + if (column + 1 < width) + neighborsSignificance[index - width + 1] += 0x10; + neighborsSignificance[index - width] += 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; + } + if (column > 0) + neighborsSignificance[index - 1] += 0x01; + if (column + 1 < width) + neighborsSignificance[index + 1] += 0x01; + neighborsSignificance[index] |= 0x80; + }, + runSignificancePropogationPass: + function BitModel_runSignificancePropogationPass() { + var decoder = this.decoder; + var width = this.width, height = this.height; + var coefficentsMagnitude = this.coefficentsMagnitude; + var coefficentsSign = this.coefficentsSign; + var 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) + break; + + if (coefficentsMagnitude[index] || !neighborsSignificance[index]) + continue; + + var contextLabel = labels[neighborsSignificance[index]]; + var cx = contexts[contextLabel]; + var decision = decoder.readBit(cx); + if (decision) { + var sign = this.decodeSignBit(i, j); + coefficentsSign[index] = sign; + coefficentsMagnitude[index] = 1; + this.setNeighborsSignificance(i, j); + processingFlags[index] |= firstMagnitudeBitMask; + } + bitsDecoded[index]++; + processingFlags[index] |= processedMask; + } + } + } + }, + decodeSignBit: function BitModel_decodeSignBit(row, column) { + 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 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; + }, + runMagnitudeRefinementPass: + function BitModel_runMagnitudeRefinementPass() { + var decoder = this.decoder; + var width = this.width, height = this.height; + var coefficentsMagnitude = this.coefficentsMagnitude; + var neighborsSignificance = this.neighborsSignificance; + var contexts = this.contexts; + var bitsDecoded = this.bitsDecoded; + var processingFlags = this.processingFlags; + var processedMask = 1; + var firstMagnitudeBitMask = 2; + for (var i0 = 0; i0 < height; i0 += 4) { + 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; + + // significant but not those that have just become + if (!coefficentsMagnitude[index] || + (processingFlags[index] & processedMask) !== 0) + continue; + + var contextLabel = 16; + if ((processingFlags[index] & + firstMagnitudeBitMask) !== 0) { + processingFlags[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); + coefficentsMagnitude[index] = + (coefficentsMagnitude[index] << 1) | bit; + bitsDecoded[index]++; + processingFlags[index] |= processedMask; + } + } + } + }, + runCleanupPass: function BitModel_runCleanupPass() { + var decoder = this.decoder; + var width = this.width, height = this.height; + var neighborsSignificance = this.neighborsSignificance; + var significanceState = this.significanceState; + var coefficentsMagnitude = this.coefficentsMagnitude; + var coefficentsSign = this.coefficentsSign; + var contexts = this.contexts; + var labels = this.contextLabelTable; + var bitsDecoded = this.bitsDecoded; + var processingFlags = this.processingFlags; + var processedMask = 1; + var firstMagnitudeBitMask = 2; + var oneRowDown = width; + var twoRowsDown = width * 2; + var threeRowsDown = width * 3; + for (var i0 = 0; i0 < height; i0 += 4) { + 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 && + processingFlags[index0] === 0 && + processingFlags[index0 + oneRowDown] === 0 && + processingFlags[index0 + twoRowsDown] === 0 && + processingFlags[index0 + threeRowsDown] === 0 && + neighborsSignificance[index0] === 0 && + neighborsSignificance[index0 + oneRowDown] === 0 && + neighborsSignificance[index0 + twoRowsDown] === 0 && + neighborsSignificance[index0 + threeRowsDown] === 0; + var i1 = 0, index = index0; + var cx, i; + if (allEmpty) { + cx = this.runLengthContext; + var hasSignificantCoefficent = decoder.readBit(cx); + if (!hasSignificantCoefficent) { + bitsDecoded[index0]++; + bitsDecoded[index0 + oneRowDown]++; + bitsDecoded[index0 + twoRowsDown]++; + bitsDecoded[index0 + threeRowsDown]++; + continue; // next column + } + cx = this.uniformContext; + i1 = (decoder.readBit(cx) << 1) | decoder.readBit(cx); + i = i0 + i1; + index += i1 * width; + + var sign = this.decodeSignBit(i, j); + coefficentsSign[index] = sign; + coefficentsMagnitude[index] = 1; + this.setNeighborsSignificance(i, j); + processingFlags[index] |= firstMagnitudeBitMask; + + index = index0; + 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; + + if (coefficentsMagnitude[index] || + (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); + coefficentsSign[index] = sign; + coefficentsMagnitude[index] = 1; + this.setNeighborsSignificance(i, j); + processingFlags[index] |= firstMagnitudeBitMask; + } + bitsDecoded[index]++; + } + } + } + }, + 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'; + } + }; + + return BitModel; + })(); + + // Section F, Discrete wavelet transofrmation + var Transform = (function TransformClosure() { + function Transform() { + } + Transform.prototype.calculate = + function transformCalculate(subbands, u0, v0) { + var ll = subbands[0]; + for (var i = 1, ii = subbands.length, j = 1; i < ii; i += 3, j++) { + ll = this.iterate(ll, subbands[i], subbands[i + 1], + subbands[i + 2], 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.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; + + // 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) + 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]; + } + + var bufferPadding = 4; + var bufferLength = new Float32Array(Math.max(width, height) + + 2 * bufferPadding); + var buffer = new Float32Array(bufferLength); + var bufferOut = new Float32Array(bufferLength); + + // 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; + } + continue; + } + + var k = v * width; + var l = bufferPadding; + for (var u = 0; u < width; u++, k++, l++) + buffer[l] = items[k]; + + 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]; + } + + // Section F.3.5 VER_SR + for (var u = 0; u < width; u++) { + 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; + } + continue; + } + + var k = u; + var l = bufferPadding; + for (var v = 0; v < height; v++, k += width, l++) + buffer[l] = items[k]; + + 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]; + } + return { + width: width, + height: height, + items: items + }; + }; + return Transform; + })(); + + // Section 3.8.2 Irreversible 9-7 filter + var IrreversibleTransform = (function IrreversibleTransformClosure() { + function IrreversibleTransform() { + Transform.call(this); + } + + IrreversibleTransform.prototype = Object.create(Transform.prototype); + IrreversibleTransform.prototype.filter = + function irreversibleTransformFilter(y, offset, length, i0, x) { + var i0_ = Math.floor(i0 / 2); + var i1_ = Math.floor((i0 + length) / 2); + var offset_ = offset - (i0 % 1); + + var alpha = -1.586134342059924; + var beta = -0.052980118572961; + var gamma = 0.882911075530934; + var delta = 0.443506852043971; + var K = 1.230174104914001; + var K_ = 1 / K; + + // step 1 + var j = offset_ - 2; + for (var n = i0_ - 1, nn = i1_ + 2; n < nn; n++, j += 2) + x[j] = K * y[j]; + + // step 2 + var j = offset_ - 3; + for (var n = i0_ - 2, nn = i1_ + 2; n < nn; n++, j += 2) + x[j] = K_ * y[j]; + + // 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 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]); + + // 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]); + + // 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]); + }; + + return IrreversibleTransform; + })(); + + // Section 3.8.1 Reversible 5-3 filter + var ReversibleTransform = (function ReversibleTransformClosure() { + function ReversibleTransform() { + Transform.call(this); + } + + ReversibleTransform.prototype = Object.create(Transform.prototype); + ReversibleTransform.prototype.filter = + function reversibleTransformFilter(y, offset, length, i0, x) { + var i0_ = Math.floor(i0 / 2); + var i1_ = Math.floor((i0 + length) / 2); + var offset_ = offset - (i0 % 1); + + 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 (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); + }; + + return ReversibleTransform; + })(); + + return JpxImage; +})(); + + + +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) + return this[id]; + return (this[id] = new Int8Array(1<<16)); + } + }; + + function DecodingContext(data, start, end) { + this.data = data; + this.start = start; + this.end = end; + } + + DecodingContext.prototype = { + get decoder() { + var decoder = new ArithmeticDecoder(this.data, this.start, this.end); + return shadow(this, 'decoder', decoder); + }, + get contextCache() { + var cache = new ContextCache(); + return shadow(this, 'contextCache', cache); + } + }; + + // Annex A. Arithmetic Integer Decoding Procedure + // A.2 Procedure for decoding values + function decodeInteger(contextCache, procedure, decoder) { + var contexts = contextCache.getContexts(procedure); + + var prev = 1; + 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; + } + state++; + } + v += offset; + return !s ? v : v > 0 ? -v : null; + } + + // A.3 The IAID decoding procedure + function decodeIAID(contextCache, decoder, codeLength) { + var contexts = contextCache.getContexts('IAID'); + + var prev = 1; + for (var i = 0; i < codeLength; i++) { + var bit = decoder.readBit(contexts, prev); + prev = (prev * 2) + bit; + } + if (codeLength < 31) + return prev & ((1 << codeLength) - 1); + else + return prev - Math.pow(2, codeLength); + } + + // 7.3 Segment types + var SegmentTypes = [ + 'SymbolDictionary', null, null, null, 'IntermediateTextRegion', null, + 'ImmediateTextRegion', 'ImmediateLosslessTextRegion', null, null, null, + null, null, null, null, null, 'patternDictionary', null, null, null, + 'IntermediateHalftoneRegion', null, 'ImmediateHalftoneRegion', + 'ImmediateLosslessHalftoneRegion', null, null, null, null, null, null, null, + null, null, null, null, null, 'IntermediateGenericRegion', null, + 'ImmediateGenericRegion', 'ImmediateLosslessGenericRegion', + 'IntermediateGenericRefinementRegion', null, + 'ImmediateGenericRefinementRegion', + 'ImmediateLosslessGenericRefinementRegion', null, null, null, null, + 'PageInformation', 'EndOfPage', 'EndOfStripe', 'EndOfFile', 'Profiles', + 'Tables', null, null, null, null, null, null, null, null, + 'Extension' + ]; + + var CodingTemplates = [ + [{x: -1, y: -2}, {x: 0, y: -2}, {x: 1, y: -2}, {x: -2, y: -1}, + {x: -1, y: -1}, {x: 0, y: -1}, {x: 1, y: -1}, {x: 2, y: -1}, + {x: -4, y: 0}, {x: -3, y: 0}, {x: -2, y: 0}, {x: -1, y: 0}], + [{x: -1, y: -2}, {x: 0, y: -2}, {x: 1, y: -2}, {x: 2, y: -2}, + {x: -2, y: -1}, {x: -1, y: -1}, {x: 0, y: -1}, {x: 1, y: -1}, + {x: 2, y: -1}, {x: -3, y: 0}, {x: -2, y: 0}, {x: -1, y: 0}], + [{x: -1, y: -2}, {x: 0, y: -2}, {x: 1, y: -2}, {x: -2, y: -1}, + {x: -1, y: -1}, {x: 0, y: -1}, {x: 1, y: -1}, {x: -2, y: 0}, + {x: -1, y: 0}], + [{x: -3, y: -1}, {x: -2, y: -1}, {x: -1, y: -1}, {x: 0, y: -1}, + {x: 1, y: -1}, {x: -4, y: 0}, {x: -3, y: 0}, {x: -2, y: 0}, {x: -1, y: 0}] + ]; + + var RefinementTemplates = [ + { + coding: [{x: 0, y: -1}, {x: 1, y: -1}, {x: -1, y: 0}], + reference: [{x: 0, y: -1}, {x: 1, y: -1}, {x: -1, y: 0}, {x: 0, y: 0}, + {x: 1, y: 0}, {x: -1, y: 1}, {x: 0, y: 1}, {x: 1, y: 1}] + }, + { + coding: [{x: -1, y: -1}, {x: 0, y: -1}, {x: 1, y: -1}, {x: -1, y: 0}], + reference: [{x: 0, y: -1}, {x: -1, y: 0}, {x: 0, y: 0}, {x: 1, y: 0}, + {x: 0, y: 1}, {x: 1, y: 1}] + } + ]; + + var ReusedContexts = [ + 0x1CD3, // '00111001101' (template) + '0011' (at), + 0x079A, // '001111001101' + '0', + 0x00E3, // '001110001' + '1', + 0x018B // '011000101' + '1' + ]; + + var RefinementReusedContexts = [ + 0x0020, // '000' + '0' (coding) + '00010000' + '0' (reference) + 0x0008 // '0000' + '001000' + ]; + + function log2(x) { + var n = 1, i = 0; + while (x > n) { + n <<= 1; + i++; + } + 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; + } + + // 6.2 Generic Region Decoding Procedure + function decodeBitmap(mmr, width, height, templateIndex, prediction, skip, at, + decodingContext) { + if (mmr) + error('JBIG2 error: MMR encoding is not supported'); + + var useskip = !!skip; + var template = CodingTemplates[templateIndex].concat(at); + var templateLength = template.length; + var templateX = new Int32Array(templateLength); + var templateY = new Int32Array(templateLength); + for (var k = 0; k < templateLength; k++) { + templateX[k] = template[k].x; + templateY[k] = template[k].y; + } + + var pseudoPixelContext = ReusedContexts[templateIndex]; + var bitmap = []; + + var decoder = decodingContext.decoder; + var contexts = decodingContext.contextCache.getContexts('GB'); + + var ltp = 0; + for (var i = 0; i < height; i++) { + if (prediction) { + var sltp = decoder.readBit(contexts, pseudoPixelContext); + ltp ^= sltp; + } + if (ltp) { + bitmap.push(bitmap[bitmap.length - 1]); // duplicate previous row + continue; + } + var row = new Uint8Array(width); + bitmap.push(row); + for (var 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]; + } + var pixel = decoder.readBit(contexts, contextLabel); + row[j] = pixel; + } + } + return bitmap; + } + + // 6.3.2 Generic Refinement Region Decoding Procedure + function decodeRefinement(width, height, templateIndex, referenceBitmap, + offsetX, offsetY, prediction, at, + decodingContext) { + var codingTemplate = RefinementTemplates[templateIndex].coding; + if (templateIndex === 0) + codingTemplate = codingTemplate.concat([at[0]]); + var codingTemplateLength = codingTemplate.length; + var codingTemplateX = new Int32Array(codingTemplateLength); + var codingTemplateY = new Int32Array(codingTemplateLength); + for (var k = 0; k < codingTemplateLength; k++) { + codingTemplateX[k] = codingTemplate[k].x; + codingTemplateY[k] = codingTemplate[k].y; + } + var referenceTemplate = RefinementTemplates[templateIndex].reference; + if (templateIndex === 0) + referenceTemplate = referenceTemplate.concat([at[1]]); + var referenceTemplateLength = referenceTemplate.length; + var referenceTemplateX = new Int32Array(referenceTemplateLength); + var referenceTemplateY = new Int32Array(referenceTemplateLength); + for (var k = 0; k < referenceTemplateLength; k++) { + referenceTemplateX[k] = referenceTemplate[k].x; + referenceTemplateY[k] = referenceTemplate[k].y; + } + var referenceWidth = referenceBitmap[0].length; + var referenceHeight = referenceBitmap.length; + + var pseudoPixelContext = RefinementReusedContexts[templateIndex]; + var bitmap = []; + + var decoder = decodingContext.decoder; + var contexts = decodingContext.contextCache.getContexts('GR'); + + var ltp = 0; + for (var i = 0; i < height; i++) { + if (prediction) { + var sltp = decoder.readBit(contexts, pseudoPixelContext); + ltp ^= sltp; + } + 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 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) + contextLabel <<= 1; // out of bound pixel + 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) + contextLabel <<= 1; // out of bound pixel + else + contextLabel = (contextLabel << 1) | referenceBitmap[i0][j0]; + } + var pixel = decoder.readBit(contexts, contextLabel); + row[j] = pixel; + } + } + + return bitmap; + } + + // 6.5.5 Decoding the symbol dictionary + function decodeSymbolDictionary(huffman, refinement, symbols, + numberOfNewSymbols, numberOfExportedSymbols, + huffmanTables, templateIndex, at, + refinementTemplateIndex, refinementAt, + decodingContext) { + if (huffman) + error('JBIG2 error: huffman is not supported'); + + var newSymbols = []; + var currentHeight = 0; + var symbolCodeLength = log2(symbols.length + numberOfNewSymbols); + + var decoder = decodingContext.decoder; + var contextCache = decodingContext.contextCache; + + while (newSymbols.length < numberOfNewSymbols) { + var deltaHeight = decodeInteger(contextCache, 'IADH', decoder); // 6.5.6 + currentHeight += deltaHeight; + var currentWidth = 0; + var totalWidth = 0; + while (true) { + var deltaWidth = decodeInteger(contextCache, 'IADW', decoder); // 6.5.7 + if (deltaWidth === null) + break; // OOB + currentWidth += deltaWidth; + totalWidth += currentWidth; + var bitmap; + if (refinement) { + // 6.5.8.2 Refinement/aggregate-coded symbol bitmap + var numberOfInstances = decodeInteger(contextCache, 'IAAI', decoder); + if (numberOfInstances > 1) + 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, + refinementTemplateIndex, symbol, rdx, rdy, false, refinementAt, + decodingContext); + } else { + // 6.5.8.1 Direct-coded symbol bitmap + bitmap = decodeBitmap(false, currentWidth, currentHeight, + templateIndex, false, null, at, decodingContext); + } + newSymbols.push(bitmap); + } + } + // 6.5.10 Exported symbols + var exportedSymbols = []; + var flags = [], currentFlag = false; + var totalSymbolsLength = symbols.length + numberOfNewSymbols; + while (flags.length < totalSymbolsLength) { + var runLength = decodeInteger(contextCache, 'IAEX', decoder); + while (runLength--) + flags.push(currentFlag); + currentFlag = !currentFlag; + } + for (var i = 0, ii = symbols.length; i < ii; i++) + if (flags[i]) exportedSymbols.push(symbols[i]); + for (var j = 0; j < numberOfNewSymbols; i++, j++) + if (flags[i]) exportedSymbols.push(newSymbols[j]); + return exportedSymbols; + } + + function decodeTextRegion(huffman, refinement, width, height, + defaultPixelValue, numberOfSymbolInstances, + stripSize, inputSymbols, symbolCodeLength, + transposed, dsOffset, referenceCorner, + combinationOperator, huffmanTables, + refinementTemplateIndex, refinementAt, + decodingContext) { + if (huffman) + error('JBIG2 error: huffman is not supported'); + + // Prepare bitmap + var bitmap = []; + for (var i = 0; i < height; i++) { + var row = new Uint8Array(width); + if (defaultPixelValue) { + for (var j = 0; j < width; j++) + row[j] = defaultPixelValue; + } + bitmap.push(row); + } + + var decoder = decodingContext.decoder; + var contextCache = decodingContext.contextCache; + var stripT = -decodeInteger(contextCache, 'IADT', decoder); // 6.4.6 + var firstS = 0; + var i = 0; + while (i < numberOfSymbolInstances) { + var deltaT = decodeInteger(contextCache, 'IADT', decoder); // 6.4.6 + stripT += deltaT; + + var deltaFirstS = decodeInteger(contextCache, 'IAFS', decoder); // 6.4.7 + firstS += deltaFirstS; + var currentS = firstS; + do { + var currentT = stripSize == 1 ? 0 : + decodeInteger(contextCache, 'IAIT', decoder); // 6.4.9 + var t = stripSize * stripT + currentT; + var symbolId = decodeIAID(contextCache, decoder, symbolCodeLength); + var applyRefinement = refinement && + decodeInteger(contextCache, 'IARI', decoder); + var symbolBitmap = inputSymbols[symbolId]; + var symbolWidth = symbolBitmap[0].length; + var symbolHeight = symbolBitmap.length; + if (applyRefinement) { + var rdw = decodeInteger(contextCache, 'IARDW', decoder); // 6.4.11.1 + var rdh = decodeInteger(contextCache, 'IARDH', decoder); // 6.4.11.2 + var rdx = decodeInteger(contextCache, 'IARDX', decoder); // 6.4.11.3 + var rdy = decodeInteger(contextCache, 'IARDY', decoder); // 6.4.11.4 + symbolWidth += rdw; + symbolHeight += rdh; + symbolBitmap = decodeRefinement(symbolWidth, symbolHeight, + refinementTemplateIndex, symbolBitmap, (rdw >> 1) + rdx, + (rdh >> 1) + rdy, false, refinementAt, + decodingContext); + } + var offsetT = t - ((referenceCorner & 1) ? 0 : symbolHeight); + var offsetS = currentS - ((referenceCorner & 2) ? symbolWidth : 0); + if (transposed) { + // Place Symbol Bitmap from T1,S1 + for (var s2 = 0; s2 < symbolHeight; s2++) { + var row = bitmap[offsetS + s2]; + if (!row) { + continue; + } + var 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++) { + row[offsetT + t2] |= symbolRow[t2]; + } + break; + case 2: // XOR + for (var t2 = 0; t2 < maxWidth; t2++) { + row[offsetT + t2] ^= symbolRow[t2]; + } + break; + default: + error('JBIG2 error: operator ' + combinationOperator + + ' is not supported'); + } + } + currentS += symbolHeight - 1; + } else { + for (var t2 = 0; t2 < symbolHeight; t2++) { + var row = bitmap[offsetT + t2]; + if (!row) { + continue; + } + var symbolRow = symbolBitmap[t2]; + switch (combinationOperator) { + case 0: // OR + for (var s2 = 0; s2 < symbolWidth; s2++) { + row[offsetS + s2] |= symbolRow[s2]; + } + break; + case 2: // XOR + for (var s2 = 0; s2 < symbolWidth; s2++) { + row[offsetS + s2] ^= symbolRow[s2]; + } + break; + default: + error('JBIG2 error: operator ' + combinationOperator + + ' is not supported'); + } + } + currentS += symbolWidth - 1; + } + i++; + var deltaS = decodeInteger(contextCache, 'IADS', decoder); // 6.4.8 + if (deltaS === null) + break; // OOB + currentS += deltaS + dsOffset; + } while (true); + } + return bitmap; + } + + function readSegmentHeader(data, start) { + var segmentHeader = {}; + segmentHeader.number = readUint32(data, start); + var flags = data[start + 4]; + var segmentType = flags & 0x3F; + if (!SegmentTypes[segmentType]) + error('JBIG2 error: invalid segment type: ' + segmentType); + segmentHeader.type = segmentType; + segmentHeader.typeName = SegmentTypes[segmentType]; + segmentHeader.deferredNonRetain = !!(flags & 0x80); + var pageAssociationFieldSize = !!(flags & 0x40); + var referredFlags = data[start + 5]; + var referredToCount = (referredFlags >> 5) & 7; + var retainBits = [referredFlags & 31]; + var position = start + 6; + if (referredFlags == 7) { + referredToCount = readInt32(data, position - 1) & 0x1FFFFFFF; + position += 3; + var bytes = (referredToCount + 7) >> 3; + retainBits[0] = data[position++]; + while (--bytes > 0) { + retainBits.push(data[position++]); + } + } else if (referredFlags == 5 || referredFlags == 6) + error('JBIG2 error: invalid referred-to flags'); + segmentHeader.retainBits = retainBits; + var referredToSegmentNumberSize = segmentHeader.number <= 256 ? 1 : + segmentHeader.number <= 65536 ? 2 : 4; + var referredTo = []; + for (var i = 0; i < referredToCount; i++) { + var number = referredToSegmentNumberSize == 1 ? data[position] : + referredToSegmentNumberSize == 2 ? readUint16(data, position) : + readUint32(data, position); + referredTo.push(number); + position += referredToSegmentNumberSize; + } + segmentHeader.referredTo = referredTo; + if (!pageAssociationFieldSize) + segmentHeader.pageAssociation = data[position++]; + else { + segmentHeader.pageAssociation = readUint32(data, position); + position += 4; + } + segmentHeader.length = readUint32(data, position); + position += 4; + if (segmentHeader.length == 0xFFFFFFFF) { + // 7.2.7 Segment data length, unknown segment length + if (segmentType === 38) { // ImmediateGenericRegion + var genericRegionInfo = readRegionSegmentInformation(data, position); + var genericRegionSegmentFlags = data[position + + RegionSegmentInformationFieldLength]; + var genericRegionMmr = !!(genericRegionSegmentFlags & 1); + // searching for the segment end + var searchPatternLength = 6; + var searchPattern = new Uint8Array(searchPatternLength); + if (!genericRegionMmr) { + searchPattern[0] = 0xFF; + searchPattern[1] = 0xAC; + } + searchPattern[2] = (genericRegionInfo.height >>> 24) & 0xFF; + searchPattern[3] = (genericRegionInfo.height >> 16) & 0xFF; + searchPattern[4] = (genericRegionInfo.height >> 8) & 0xFF; + searchPattern[5] = genericRegionInfo.height & 0xFF; + for (var i = position, ii = data.length; i < ii; i++) { + var j = 0; + while (j < searchPatternLength && searchPattern[j] === data[i + j]) { + j++; + } + if (j == searchPatternLength) { + segmentHeader.length = i + searchPatternLength; + break; + } + } + if (segmentHeader.length == 0xFFFFFFFF) { + error('JBIG2 error: segment end was not found'); + } + } else { + error('JBIG2 error: invalid unknown segment length'); + } + } + segmentHeader.headerEnd = position; + return segmentHeader; + } + + function readSegments(header, data, start, end) { + var segments = []; + var position = start; + while (position < end) { + var segmentHeader = readSegmentHeader(data, position); + position = segmentHeader.headerEnd; + var segment = { + header: segmentHeader, + data: data + }; + if (!header.randomAccess) { + segment.start = position; + position += segmentHeader.length; + segment.end = position; + } + segments.push(segment); + if (segmentHeader.type == 51) + break; // end of file is found + } + if (header.randomAccess) { + for (var i = 0, ii = segments.length; i < ii; i++) { + segments[i].start = position; + position += segments[i].header.length; + segments[i].end = position; + } + } + return segments; + } + + // 7.4.1 Region segment information field + function readRegionSegmentInformation(data, start) { + return { + width: readUint32(data, start), + height: readUint32(data, start + 4), + x: readUint32(data, start + 8), + y: readUint32(data, start + 12), + combinationOperator: data[start + 16] & 7 + }; + } + var RegionSegmentInformationFieldLength = 17; + + function processSegment(segment, visitor) { + var header = segment.header; + + var data = segment.data, position = segment.start, end = segment.end; + var args; + switch (header.type) { + case 0: // SymbolDictionary + // 7.4.2 Symbol dictionary segment syntax + var dictionary = {}; + var dictionaryFlags = readUint16(data, position); // 7.4.2.1.1 + dictionary.huffman = !!(dictionaryFlags & 1); + dictionary.refinement = !!(dictionaryFlags & 2); + dictionary.huffmanDHSelector = (dictionaryFlags >> 2) & 3; + dictionary.huffmanDWSelector = (dictionaryFlags >> 4) & 3; + dictionary.bitmapSizeSelector = (dictionaryFlags >> 6) & 1; + dictionary.aggregationInstancesSelector = (dictionaryFlags >> 7) & 1; + dictionary.bitmapCodingContextUsed = !!(dictionaryFlags & 256); + dictionary.bitmapCodingContextRetained = !!(dictionaryFlags & 512); + dictionary.template = (dictionaryFlags >> 10) & 3; + dictionary.refinementTemplate = (dictionaryFlags >> 12) & 1; + position += 2; + if (!dictionary.huffman) { + var atLength = dictionary.template === 0 ? 4 : 1; + var at = []; + for (var i = 0; i < atLength; i++) { + at.push({ + x: readInt8(data, position), + y: readInt8(data, position + 1) + }); + position += 2; + } + dictionary.at = at; + } + if (dictionary.refinement && !dictionary.refinementTemplate) { + var at = []; + for (var i = 0; i < 2; i++) { + at.push({ + x: readInt8(data, position), + y: readInt8(data, position + 1) + }); + position += 2; + } + dictionary.refinementAt = at; + } + dictionary.numberOfExportedSymbols = readUint32(data, position); + position += 4; + dictionary.numberOfNewSymbols = readUint32(data, position); + position += 4; + args = [dictionary, header.number, header.referredTo, + data, position, end]; + break; + case 6: // ImmediateTextRegion + case 7: // ImmediateLosslessTextRegion + var textRegion = {}; + textRegion.info = readRegionSegmentInformation(data, position); + position += RegionSegmentInformationFieldLength; + var textRegionSegmentFlags = readUint16(data, position); + position += 2; + textRegion.huffman = !!(textRegionSegmentFlags & 1); + textRegion.refinement = !!(textRegionSegmentFlags & 2); + textRegion.stripSize = 1 << ((textRegionSegmentFlags >> 2) & 3); + textRegion.referenceCorner = (textRegionSegmentFlags >> 4) & 3; + textRegion.transposed = !!(textRegionSegmentFlags & 64); + textRegion.combinationOperator = (textRegionSegmentFlags >> 7) & 3; + textRegion.defaultPixelValue = (textRegionSegmentFlags >> 9) & 1; + textRegion.dsOffset = (textRegionSegmentFlags << 17) >> 27; + textRegion.refinementTemplate = (textRegionSegmentFlags >> 15) & 1; + if (textRegion.huffman) { + var textRegionHuffmanFlags = readUint16(data, position); + position += 2; + textRegion.huffmanFS = (textRegionHuffmanFlags) & 3; + textRegion.huffmanDS = (textRegionHuffmanFlags >> 2) & 3; + textRegion.huffmanDT = (textRegionHuffmanFlags >> 4) & 3; + textRegion.huffmanRefinementDW = (textRegionHuffmanFlags >> 6) & 3; + textRegion.huffmanRefinementDH = (textRegionHuffmanFlags >> 8) & 3; + textRegion.huffmanRefinementDX = (textRegionHuffmanFlags >> 10) & 3; + textRegion.huffmanRefinementDY = (textRegionHuffmanFlags >> 12) & 3; + textRegion.huffmanRefinementSizeSelector = + !!(textRegionHuffmanFlags & 14); + } + if (textRegion.refinement && !textRegion.refinementTemplate) { + var at = []; + for (var i = 0; i < 2; i++) { + at.push({ + x: readInt8(data, position), + y: readInt8(data, position + 1) + }); + position += 2; + } + textRegion.refinementAt = at; + } + textRegion.numberOfSymbolInstances = readUint32(data, position); + position += 4; + // TODO 7.4.3.1.7 Symbol ID Huffman table decoding + if (textRegion.huffman) + error('JBIG2 error: huffman is not supported'); + args = [textRegion, header.referredTo, data, position, end]; + break; + case 38: // ImmediateGenericRegion + case 39: // ImmediateLosslessGenericRegion + var genericRegion = {}; + genericRegion.info = readRegionSegmentInformation(data, position); + position += RegionSegmentInformationFieldLength; + var genericRegionSegmentFlags = data[position++]; + genericRegion.mmr = !!(genericRegionSegmentFlags & 1); + genericRegion.template = (genericRegionSegmentFlags >> 1) & 3; + genericRegion.prediction = !!(genericRegionSegmentFlags & 8); + if (!genericRegion.mmr) { + var atLength = genericRegion.template === 0 ? 4 : 1; + var at = []; + for (var i = 0; i < atLength; i++) { + at.push({ + x: readInt8(data, position), + y: readInt8(data, position + 1) + }); + position += 2; + } + genericRegion.at = at; + } + args = [genericRegion, data, position, end]; + break; + case 48: // PageInformation + var pageInfo = { + width: readUint32(data, position), + height: readUint32(data, position + 4), + resolutionX: readUint32(data, position + 8), + resolutionY: readUint32(data, position + 12) + }; + if (pageInfo.height == 0xFFFFFFFF) + delete pageInfo.height; + var pageSegmentFlags = data[position + 16]; + var pageStripingInformatiom = readUint16(data, position + 17); + pageInfo.lossless = !!(pageSegmentFlags & 1); + pageInfo.refinement = !!(pageSegmentFlags & 2); + pageInfo.defaultPixelValue = (pageSegmentFlags >> 2) & 1; + pageInfo.combinationOperator = (pageSegmentFlags >> 3) & 3; + pageInfo.requiresBuffer = !!(pageSegmentFlags & 32); + pageInfo.combinationOperatorOverride = !!(pageSegmentFlags & 64); + args = [pageInfo]; + break; + case 49: // EndOfPage + break; + case 50: // EndOfStripe + break; + case 51: // EndOfFile + break; + case 62: // 7.4.15 defines 2 extension types which + // are comments and can be ignored. + break; + default: + error('JBIG2 error: segment type ' + header.typeName + '(' + + header.type + ') is not implemented'); + } + var callbackName = 'on' + header.typeName; + if (callbackName in visitor) + visitor[callbackName].apply(visitor, args); + } + + function processSegments(segments, visitor) { + for (var i = 0, ii = segments.length; i < ii; i++) + processSegment(segments[i], visitor); + } + + function parseJbig2(data, start, end) { + var position = start; + if (data[position] != 0x97 || data[position + 1] != 0x4A || + data[position + 2] != 0x42 || data[position + 3] != 0x32 || + data[position + 4] != 0x0D || data[position + 5] != 0x0A || + data[position + 6] != 0x1A || data[position + 7] != 0x0A) + error('JBIG2 error: invalid header'); + var header = {}; + position += 8; + var flags = data[position++]; + header.randomAccess = !(flags & 1); + if (!(flags & 2)) { + header.numberOfPages = readUint32(data, position); + position += 4; + } + var segments = readSegments(header, data, position, end); + error('Not implemented'); + // processSegments(segments, new SimpleSegmentVisitor()); + } + + function parseJbig2Chunks(chunks) { + var visitor = new SimpleSegmentVisitor(); + for (var i = 0, ii = chunks.length; i < ii; i++) { + var chunk = chunks[i]; + var segments = readSegments({}, chunk.data, chunk.start, chunk.end); + processSegments(segments, visitor); + } + return visitor.buffer; + } + + function SimpleSegmentVisitor() {} + + SimpleSegmentVisitor.prototype = { + onPageInformation: function SimpleSegmentVisitor_onPageInformation(info) { + this.currentPageInfo = info; + var rowSize = (info.width + 7) >> 3; + var buffer = new Uint8Array(rowSize * info.height); + var fill = info.defaultPixelValue ? 0xFF : 0; + for (var i = 0, ii = buffer.length; i < ii; i++) + buffer[i] = fill; + this.buffer = buffer; + }, + drawBitmap: function SimpleSegmentVisitor_drawBitmap(regionInfo, bitmap) { + var pageInfo = this.currentPageInfo; + var width = regionInfo.width, height = regionInfo.height; + var rowSize = (pageInfo.width + 7) >> 3; + var combinationOperator = pageInfo.combinationOperatorOverride ? + regionInfo.combinationOperator : pageInfo.combinationOperator; + var buffer = this.buffer; + 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; + 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; + mask >>= 1; + if (!mask) { + mask = 128; + offset++; + } + } + break; + default: + error('JBIG2 error: operator ' + combinationOperator + + ' is not supported'); + } + } + }, + onImmediateGenericRegion: + function SimpleSegmentVisitor_onImmediateGenericRegion(region, data, + start, end) { + var regionInfo = region.info; + var decodingContext = new DecodingContext(data, start, end); + var bitmap = decodeBitmap(region.mmr, regionInfo.width, regionInfo.height, + region.template, region.prediction, null, + region.at, decodingContext); + this.drawBitmap(regionInfo, bitmap); + }, + onImmediateLosslessGenericRegion: + function SimpleSegmentVisitor_onImmediateLosslessGenericRegion() { + this.onImmediateGenericRegion.apply(this, arguments); + }, + onSymbolDictionary: + function SimpleSegmentVisitor_onSymbolDictionary(dictionary, + currentSegment, + referredSegments, + data, start, end) { + var huffmanTables; + if (dictionary.huffman) + error('JBIG2 error: huffman is not supported'); + + // Combines exported symbols from all referred segments + var symbols = this.symbols; + if (!symbols) + this.symbols = symbols = {}; + + var inputSymbols = []; + for (var i = 0, ii = referredSegments.length; i < ii; i++) + inputSymbols = inputSymbols.concat(symbols[referredSegments[i]]); + + var decodingContext = new DecodingContext(data, start, end); + symbols[currentSegment] = decodeSymbolDictionary(dictionary.huffman, + dictionary.refinement, inputSymbols, dictionary.numberOfNewSymbols, + dictionary.numberOfExportedSymbols, huffmanTables, + dictionary.template, dictionary.at, + dictionary.refinementTemplate, dictionary.refinementAt, + decodingContext); + }, + onImmediateTextRegion: + function SimpleSegmentVisitor_onImmediateTextRegion(region, + referredSegments, + data, start, end) { + var regionInfo = region.info; + var huffmanTables; + + // Combines exported symbols from all referred segments + var symbols = this.symbols; + var inputSymbols = []; + for (var i = 0, ii = referredSegments.length; i < ii; i++) + inputSymbols = inputSymbols.concat(symbols[referredSegments[i]]); + var symbolCodeLength = log2(inputSymbols.length); + + var decodingContext = new DecodingContext(data, start, end); + var bitmap = decodeTextRegion(region.huffman, region.refinement, + regionInfo.width, regionInfo.height, region.defaultPixelValue, + region.numberOfSymbolInstances, region.stripSize, inputSymbols, + symbolCodeLength, region.transposed, region.dsOffset, + region.referenceCorner, region.combinationOperator, huffmanTables, + region.refinementTemplate, region.refinementAt, decodingContext); + this.drawBitmap(regionInfo, bitmap); + }, + onImmediateLosslessTextRegion: + function SimpleSegmentVisitor_onImmediateLosslessTextRegion() { + this.onImmediateTextRegion.apply(this, arguments); + } + }; + + function Jbig2Image() {} + + Jbig2Image.prototype = { + parseChunks: function Jbig2Image_parseChunks(chunks) { + return parseJbig2Chunks(chunks); + } + }; + + return Jbig2Image; +})(); + + +var bidi = PDFJS.bidi = (function bidiClosure() { + // Character types for symbols from 0000 to 00FF. + var baseTypes = [ + 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'S', 'B', 'S', 'WS', + 'B', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', + 'BN', 'BN', 'B', 'B', 'B', 'S', 'WS', 'ON', 'ON', 'ET', 'ET', 'ET', 'ON', + 'ON', 'ON', 'ON', 'ON', 'ON', 'CS', 'ON', 'CS', 'ON', 'EN', 'EN', 'EN', + 'EN', 'EN', 'EN', 'EN', 'EN', 'EN', 'EN', 'ON', 'ON', 'ON', 'ON', 'ON', + 'ON', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', + 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'ON', 'ON', + 'ON', 'ON', 'ON', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', + 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', + 'L', 'ON', 'ON', 'ON', 'ON', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'B', 'BN', + 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', + 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', + 'BN', 'CS', 'ON', 'ET', 'ET', 'ET', 'ET', 'ON', 'ON', 'ON', 'ON', 'L', 'ON', + 'ON', 'ON', 'ON', 'ON', 'ET', 'ET', 'EN', 'EN', 'ON', 'L', 'ON', 'ON', 'ON', + 'EN', 'L', 'ON', 'ON', 'ON', 'ON', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', + 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', + 'L', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', + 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', + 'L', 'L', 'L', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L' + ]; + + // Character types for symbols from 0600 to 06FF + var arabicTypes = [ + 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', + 'CS', 'AL', 'ON', 'ON', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'AL', + 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', + 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', + 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', + 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', + 'AL', 'AL', 'AL', 'AL', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', + 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'AL', 'AL', 'AL', 'AL', + 'AL', 'AL', 'AL', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN', + 'AN', 'ET', 'AN', 'AN', 'AL', 'AL', 'AL', 'NSM', 'AL', 'AL', 'AL', 'AL', + 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', + 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', + 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', + 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', + 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', + 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', + 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', + 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', + 'AL', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', + 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'ON', 'NSM', + 'NSM', 'NSM', 'NSM', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', + 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL' + ]; + + function isOdd(i) { + return (i & 1) !== 0; + } + + function isEven(i) { + return (i & 1) === 0; + } + + function findUnequal(arr, start, value) { + var j; + for (var j = start, jj = arr.length; j < jj; ++j) { + if (arr[j] != value) + return j; + } + return j; + } + + function setValues(arr, start, end, value) { + for (var j = start; j < end; ++j) { + arr[j] = value; + } + } + + function reverseValues(arr, start, end) { + for (var i = start, j = end - 1; i < j; ++i, --j) { + var temp = arr[i]; + arr[i] = arr[j]; + arr[j] = temp; + } + } + + function 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 BidiResult(str, isLTR, vertical) { + this.str = str; + this.dir = vertical ? 'ttb' : isLTR ? 'ltr' : 'rtl'; + } + + function bidi(str, startLevel, vertical) { + var isLTR = true; + var strLength = str.length; + if (strLength === 0 || vertical) + return new BidiResult(str, isLTR, vertical); + + // get types, fill arrays + + var chars = []; + var types = []; + var oldtypes = []; + var numBidi = 0; + + for (var i = 0; i < strLength; ++i) { + chars[i] = str.charAt(i); + + var charCode = str.charCodeAt(i); + var charType = 'L'; + if (charCode <= 0x00ff) + charType = baseTypes[charCode]; + else if (0x0590 <= charCode && charCode <= 0x05f4) + charType = 'R'; + else if (0x0600 <= charCode && charCode <= 0x06ff) + charType = arabicTypes[charCode & 0xff]; + else if (0x0700 <= charCode && charCode <= 0x08AC) + charType = 'AL'; + + if (charType == 'R' || charType == 'AL' || charType == 'AN') + numBidi++; + + oldtypes[i] = types[i] = charType; + } + + // detect the bidi method + // if there are no rtl characters then no bidi needed + // if less than 30% chars are rtl then string is primarily ltr + // if more than 30% chars are rtl then string is primarily rtl + if (numBidi === 0) { + isLTR = true; + return new BidiResult(str, isLTR); + } + + if (startLevel == -1) { + if ((strLength / numBidi) < 0.3) { + isLTR = true; + startLevel = 0; + } else { + isLTR = false; + startLevel = 1; + } + } + + var levels = []; + + for (var i = 0; i < strLength; ++i) { + levels[i] = startLevel; + } + + /* + X1-X10: skip most of this, since we are NOT doing the embeddings. + */ + + var e = isOdd(startLevel) ? 'R' : 'L'; + var sor = e; + var eor = sor; + + /* + W1. Examine each non-spacing mark (NSM) in the level run, and change the + type of the NSM to the type of the previous character. If the NSM is at the + start of the level run, it will get the type of sor. + */ + + var lastType = sor; + for (var i = 0; i < strLength; ++i) { + if (types[i] == 'NSM') + types[i] = lastType; + else + lastType = types[i]; + } + + /* + W2. Search backwards from each instance of a European number until the + first strong type (R, L, AL, or sor) is found. If an AL is found, change + the type of the European number to Arabic number. + */ + + 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 = t; + } + + /* + W3. Change all ALs to R. + */ + + for (var i = 0; i < strLength; ++i) { + var t = types[i]; + if (t == 'AL') + types[i] = 'R'; + } + + /* + W4. A single European separator between two European numbers changes to a + European number. A single common separator between two numbers of the same + type changes to that type: + */ + + for (var i = 1; i < strLength - 1; ++i) { + if (types[i] == 'ES' && types[i - 1] == 'EN' && types[i + 1] == 'EN') + types[i] = 'EN'; + if (types[i] == 'CS' && (types[i - 1] == 'EN' || types[i - 1] == 'AN') && + types[i + 1] == types[i - 1]) + types[i] = types[i - 1]; + } + + /* + W5. A sequence of European terminators adjacent to European numbers changes + to all European numbers: + */ + + for (var i = 0; i < strLength; ++i) { + if (types[i] == 'EN') { + // do before + for (var 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') + break; + types[j] = 'EN'; + } + } + } + + /* + 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') + types[i] = 'ON'; + } + + /* + W7. Search backwards from each instance of a European number until the + first strong type (R, L, or sor) is found. If an L is found, then change + the type of the European number to L. + */ + + 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 = t; + } + + /* + N1. A sequence of neutrals takes the direction of the surrounding strong + text if the text on both sides has the same direction. European and Arabic + numbers are treated as though they were R. Start-of-level-run (sor) and + end-of-level-run (eor) are used at level run boundaries. + */ + + for (var i = 0; i < strLength; ++i) { + if (types[i] == 'ON') { + var end = findUnequal(types, i + 1, 'ON'); + var before = sor; + if (i > 0) + before = types[i - 1]; + var after = eor; + if (end + 1 < strLength) + after = types[end + 1]; + if (before != 'L') + before = 'R'; + if (after != 'L') + after = 'R'; + if (before == after) + setValues(types, i, end, before); + i = end - 1; // reset to end (-1 so next iteration is ok) + } + } + + /* + N2. Any remaining neutrals take the embedding direction. + */ + + for (var i = 0; i < strLength; ++i) { + if (types[i] == 'ON') + types[i] = e; + } + + /* + I1. For all characters with an even (left-to-right) embedding direction, + those of type R go up one level and those of type AN or EN go up two + levels. + I2. For all characters with an odd (right-to-left) embedding direction, + those of type L, EN or AN go up one level. + */ + + for (var i = 0; i < strLength; ++i) { + var t = types[i]; + if (isEven(levels[i])) { + if (t == 'R') { + levels[i] += 1; + } else if (t == 'AN' || t == 'EN') { + levels[i] += 2; + } + } else { // isOdd, so + if (t == 'L' || t == 'AN' || t == 'EN') { + levels[i] += 1; + } + } + } + + /* + L1. On each line, reset the embedding level of the following characters to + the paragraph embedding level: + + segment separators, + paragraph separators, + any sequence of whitespace characters preceding a segment separator or + paragraph separator, and any sequence of white space characters at the end + of the line. + */ + + // don't bother as text is only single line + + /* + L2. From the highest level found in the text to the lowest odd level on + each line, reverse any contiguous sequence of characters that are at that + level or higher. + */ + + // find highest level & lowest odd level + + var highestLevel = -1; + var lowestOddLevel = 99; + for (var i = 0, ii = levels.length; i < ii; ++i) { + var level = levels[i]; + if (highestLevel < level) + highestLevel = level; + if (lowestOddLevel > level && isOdd(level)) + lowestOddLevel = level; + } + + // now reverse between those limits + + for (var level = highestLevel; level >= lowestOddLevel; --level) { + // find segments to reverse + var start = -1; + for (var i = 0, ii = levels.length; i < ii; ++i) { + if (levels[i] < level) { + if (start >= 0) { + reverseValues(chars, start, i); + start = -1; + } + } else if (start < 0) { + start = i; + } + } + if (start >= 0) { + reverseValues(chars, start, levels.length); + } + } + + /* + L3. Combining marks applied to a right-to-left base character will at this + point precede their base character. If the rendering engine expects them to + follow the base characters in the final display process, then the ordering + of the marks and the base character must be reversed. + */ + + // don't bother for now + + /* + L4. A character that possesses the mirrored property as specified by + Section 4.7, Mirrored, must be depicted by a mirrored glyph if the resolved + directionality of that character is R. + */ + + // don't mirror as characters are already mirrored in the pdf + + // Finally, return string + + var result = ''; + for (var i = 0, ii = chars.length; i < ii; ++i) { + var ch = chars[i]; + if (ch != '<' && ch != '>') + result += ch; + } + + return new BidiResult(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 -*- / +/* 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 + + 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. +*/ + +// - 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 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 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; + 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; + } + } + 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; + } + } + 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(); + + 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; + 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) { + 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'; + } + } + }; + + return constructor; +})(); + + +}).call((typeof window === 'undefined') ? this : window); + +if (!PDFJS.workerSrc && typeof document !== 'undefined') { + // workerSrc is not set -- using last script url to define default location + PDFJS.workerSrc = (function () { + 'use strict'; + var scriptTagContainer = document.body || + document.getElementsByTagName('head')[0]; + var pdfjsSrc = scriptTagContainer.lastChild.src; + return pdfjsSrc && pdfjsSrc.replace(/\.js$/i, '.worker.js'); + })(); +} + + diff --git a/attachment_preview/static/lib/ViewerJS/pdf_find_bar.js b/attachment_preview/static/lib/ViewerJS/pdf_find_bar.js new file mode 100644 index 00000000000..2054c6d18b6 --- /dev/null +++ b/attachment_preview/static/lib/ViewerJS/pdf_find_bar.js @@ -0,0 +1,175 @@ +/* -*- 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 new file mode 100644 index 00000000000..e48246fa3e0 --- /dev/null +++ b/attachment_preview/static/lib/ViewerJS/pdf_find_controller.js @@ -0,0 +1,355 @@ +/* -*- 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 new file mode 100644 index 00000000000..9d3e0e4dbe6 --- /dev/null +++ b/attachment_preview/static/lib/ViewerJS/pdfjsversion.js @@ -0,0 +1 @@ +var /**@const{!string}*/pdfjs_version = "d45d7bc"; diff --git a/attachment_preview/static/lib/ViewerJS/text_layer_builder.js b/attachment_preview/static/lib/ViewerJS/text_layer_builder.js new file mode 100644 index 00000000000..c2f8043ea8d --- /dev/null +++ b/attachment_preview/static/lib/ViewerJS/text_layer_builder.js @@ -0,0 +1,385 @@ +/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* Copyright 2012 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* globals CustomStyle, PDFFindController, scrollIntoView */ + +'use strict'; + +var FIND_SCROLL_OFFSET_TOP = -50; +var FIND_SCROLL_OFFSET_LEFT = -400; + +/** + * 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. + */ +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() { + this.textDivs = []; + this.renderingDone = false; + }; + + this.endLayout = function textLayerBuilderEndLayout() { + this.layoutDone = true; + this.insertDivContent(); + }; + + 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; + } + + ctx.font = textDiv.style.fontSize + ' ' + textDiv.style.fontFamily; + var width = ctx.measureText(textDiv.textContent).width; + + 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%'); + } + } + + 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; + + 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)) { + textDiv.dataset.isWhitespace = true; + continue; + } + + 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++; + } + + // TODO: Do proper handling here if something goes wrong. + if (i == bidiTexts.length) { + console.error('Could not find matching mapping'); + } + + var match = { + begin: { + 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++; + } + + match.end = { + divIdx: i, + offset: matchIdx - iIndex + }; + ret.push(match); + } + + 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); + return; + } + div.appendChild(node); + } + + function appendText(from, to, className) { + var divIdx = from.divIdx; + var div = textDivs[divIdx]; + + 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); + return; + } + div.appendChild(node); + } + + function highlightDiv(divIdx, className) { + textDivs[divIdx].className = className; + } + + 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); + } + // 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); + } + beginText(end, 'highlight end' + highlightSuffix); + } + prevEnd = end; + } + + if (prevEnd) { + appendText(prevEnd, infty); + } + }; + + 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); + }; +}; + diff --git a/attachment_preview/static/lib/ViewerJS/ui_utils.js b/attachment_preview/static/lib/ViewerJS/ui_utils.js new file mode 100644 index 00000000000..c832dc7ad82 --- /dev/null +++ b/attachment_preview/static/lib/ViewerJS/ui_utils.js @@ -0,0 +1,270 @@ +/* -*- 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'; + +// optimised CSS custom property getter/setter +var CustomStyle = (function CustomStyleClosure() { + + // As noted on: http://www.zachstronaut.com/posts/2009/02/17/ + // animate-css-transforms-firefox-webkit.html + // in some versions of IE9 it is critical that ms appear in this list + // before Moz + var prefixes = ['ms', 'Moz', 'Webkit', 'O']; + var _cache = { }; + + function CustomStyle() { + } + + CustomStyle.getProp = function get(propName, element) { + // check cache only when no element is given + if (arguments.length == 1 && typeof _cache[propName] == 'string') { + return _cache[propName]; + } + + element = element || document.documentElement; + var style = element.style, prefixed, uPropName; + + // test standard property first + if (typeof style[propName] == 'string') { + return (_cache[propName] = propName); + } + + // capitalize + uPropName = propName.charAt(0).toUpperCase() + propName.slice(1); + + // test vendor specific properties + for (var i = 0, l = prefixes.length; i < l; i++) { + prefixed = prefixes[i] + uPropName; + if (typeof style[prefixed] == 'string') { + return (_cache[propName] = prefixed); + } + } + + //if all fails then set to undefined + return (_cache[propName] = 'undefined'); + }; + + CustomStyle.setProp = function set(propName, element, str) { + var prop = this.getProp(propName); + if (prop != 'undefined') + element.style[prop] = str; + }; + + return CustomStyle; +})(); + +function getFileName(url) { + var anchor = url.indexOf('#'); + var query = url.indexOf('?'); + var end = Math.min( + anchor > 0 ? anchor : url.length, + query > 0 ? query : url.length); + return url.substring(url.lastIndexOf('/', end) + 1, end); +} + +/** + * Returns scale factor for the canvas. It makes sense for the HiDPI displays. + * @return {Object} The object with horizontal (sx) and vertical (sy) + scales. The scaled property is set to false if scaling is + not required, true otherwise. + */ +function getOutputScale(ctx) { + var devicePixelRatio = window.devicePixelRatio || 1; + var backingStoreRatio = ctx.webkitBackingStorePixelRatio || + ctx.mozBackingStorePixelRatio || + ctx.msBackingStorePixelRatio || + ctx.oBackingStorePixelRatio || + ctx.backingStorePixelRatio || 1; + var pixelRatio = devicePixelRatio / backingStoreRatio; + return { + sx: pixelRatio, + sy: pixelRatio, + scaled: pixelRatio != 1 + }; +} + +/** + * Scrolls specified element into view of its parent. + * element {Object} The element to be visible. + * spot {Object} An object with optional top and left properties, + * specifying the offset from the top left edge. + */ +function scrollIntoView(element, spot) { + // Assuming offsetParent is available (it's not available when viewer is in + // hidden iframe or object). We have to scroll: if the offsetParent is not set + // producing the error. See also animationStartedClosure. + var parent = element.offsetParent; + var offsetY = element.offsetTop + element.clientTop; + var offsetX = element.offsetLeft + element.clientLeft; + if (!parent) { + console.error('offsetParent is not set -- cannot scroll'); + return; + } + while (parent.clientHeight === parent.scrollHeight) { + if (parent.dataset._scaleY) { + offsetY /= parent.dataset._scaleY; + offsetX /= parent.dataset._scaleX; + } + offsetY += parent.offsetTop; + offsetX += parent.offsetLeft; + parent = parent.offsetParent; + if (!parent) { + return; // no need to scroll + } + } + if (spot) { + if (spot.top !== undefined) { + offsetY += spot.top; + } + if (spot.left !== undefined) { + offsetX += spot.left; + parent.scrollLeft = offsetX; + } + } + parent.scrollTop = offsetY; +} + +/** + * Event handler to suppress context menu. + */ +function noContextMenuHandler(e) { + e.preventDefault(); +} + +/** + * Returns the filename or guessed filename from the url (see issue 3455). + * url {String} The original PDF location. + * @return {String} Guessed PDF file name. + */ +function getPDFFileNameFromURL(url) { + var reURI = /^(?:([^:]+:)?\/\/[^\/]+)?([^?#]*)(\?[^#]*)?(#.*)?$/; + // SCHEME HOST 1.PATH 2.QUERY 3.REF + // Pattern to get last matching NAME.pdf + var reFilename = /[^\/?#=]+\.pdf\b(?!.*\.pdf\b)/i; + var splitURI = reURI.exec(url); + var suggestedFilename = reFilename.exec(splitURI[1]) || + reFilename.exec(splitURI[2]) || + reFilename.exec(splitURI[3]); + if (suggestedFilename) { + suggestedFilename = suggestedFilename[0]; + if (suggestedFilename.indexOf('%') != -1) { + // URL-encoded %2Fpath%2Fto%2Ffile.pdf should be file.pdf + try { + suggestedFilename = + reFilename.exec(decodeURIComponent(suggestedFilename))[0]; + } catch(e) { // Possible (extremely rare) errors: + // URIError "Malformed URI", e.g. for "%AA.pdf" + // TypeError "null has no properties", e.g. for "%2F.pdf" + } + } + } + return suggestedFilename || 'document.pdf'; +} + +var ProgressBar = (function ProgressBarClosure() { + + function clamp(v, min, max) { + return Math.min(Math.max(v, min), max); + } + + function ProgressBar(id, opts) { + + // Fetch the sub-elements for later. + this.div = document.querySelector(id + ' .progress'); + + // Get the loading bar element, so it can be resized to fit the viewer. + this.bar = this.div.parentNode; + + // Get options, with sensible defaults. + this.height = opts.height || 100; + this.width = opts.width || 100; + this.units = opts.units || '%'; + + // Initialize heights. + this.div.style.height = this.height + this.units; + this.percent = 0; + } + + ProgressBar.prototype = { + + updateBar: function ProgressBar_updateBar() { + if (this._indeterminate) { + this.div.classList.add('indeterminate'); + this.div.style.width = this.width + this.units; + return; + } + + this.div.classList.remove('indeterminate'); + var progressSize = this.width * this._percent / 100; + this.div.style.width = progressSize + this.units; + }, + + get percent() { + return this._percent; + }, + + set percent(val) { + this._indeterminate = isNaN(val); + this._percent = clamp(val, 0, 100); + this.updateBar(); + }, + + setWidth: function ProgressBar_setWidth(viewer) { + if (viewer) { + var container = viewer.parentNode; + var scrollbarWidth = container.offsetWidth - viewer.offsetWidth; + if (scrollbarWidth > 0) { + this.bar.setAttribute('style', 'width: calc(100% - ' + + scrollbarWidth + 'px);'); + } + } + }, + + hide: function ProgressBar_hide() { + this.bar.classList.add('hidden'); + this.bar.removeAttribute('style'); + } + }; + + return ProgressBar; +})(); + +var Cache = function cacheCache(size) { + var data = []; + this.push = function cachePush(view) { + var i = data.indexOf(view); + if (i >= 0) + data.splice(i); + data.push(view); + if (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 new file mode 100644 index 00000000000..d3201ee4deb --- /dev/null +++ b/attachment_preview/static/lib/ViewerJS/viewer.css @@ -0,0 +1,801 @@ +/** + * 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' background */ -} - -.dropdownToolbarButton > select > option { - background: hsl(0,0%,24%); -} - -#pageWidthOption { - border-bottom: 1px rgba(255, 255, 255, .5) solid; -} - - -html[dir='ltr'] .dropdownToolbarButton { - background-position: 95%; -} -html[dir='rtl'] .dropdownToolbarButton { - background-position: 5%; -} - - -.toolbarButton.fullscreen::before { - display: inline-block; - content: url(images/toolbarButton-fullscreen.png); -} - -.toolbarButton.presentation::before { - display: inline-block; - content: url(images/toolbarButton-presentation.png); -} - -.toolbarButton.download::before { - display: inline-block; - content: url(images/toolbarButton-download.png); -} - -.toolbarButton.about { - color: #F2F2F2; - font-size: 14px; - font-weight: bold; - line-height: 14px; - font-family: sans-serif; -} -.toolbarButton.about::before { - display: inline-block; -} - -.toolbarButton.zoomOut::before { - display: inline-block; - content: url(images/toolbarButton-zoomOut.png); -} - -.toolbarButton.zoomIn::before { - display: inline-block; - content: url(images/toolbarButton-zoomIn.png); -} - -.toolbarButton.pageUp::before { - display: inline-block; - content: url(images/toolbarButton-pageUp.png); -} - -.toolbarButton.pageDown::before { - display: inline-block; - content: url(images/toolbarButton-pageDown.png); -} - -.toolbarField.pageNumber { - min-width: 16px; - text-align: right; - width: 40px; -} - -.toolbarField { - padding: 3px 6px; - margin: 4px 0 4px 0; - border: 1px solid transparent; - border-radius: 2px; - background-color: hsla(0,0%,100%,.09); - background-image: -moz-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%,0%,.05) inset, - 0 1px 0 hsla(0,0%,100%,.05); - color: hsl(0,0%,95%); - font-size: 12px; - line-height: 14px; - outline-style: none; - -moz-transition-property: background-color, border-color, box-shadow; - -moz-transition-duration: 150ms; - -moz-transition-timing-function: ease; -} - -.toolbarField.pageNumber::-webkit-inner-spin-button, -.toolbarField.pageNumber::-webkit-outer-spin-button { - -webkit-appearance: none; - margin: 0; -} - -.toolbarField:hover { - background-color: hsla(0,0%,100%,.11); - border-color: hsla(0,0%,0%,.4) hsla(0,0%,0%,.43) hsla(0,0%,0%,.45); -} - -.toolbarField:focus { - background-color: hsla(0,0%,100%,.15); - border-color: hsla(204,100%,65%,.8) hsla(204,100%,65%,.85) hsla(204,100%,65%,.9); -} - -.toolbarLabel { - min-width: 16px; - padding: 3px 6px 3px 2px; - margin: 4px 2px 4px 0; - border: 1px solid transparent; - border-radius: 2px; - color: hsl(0,0%,85%); - font-size: 12px; - line-height: 14px; - text-align: left; - -webkit-user-select:none; - -moz-user-select:none; - cursor: default; -} - -#canvasContainer { - overflow: auto; - - padding-top: 6px; - padding-bottom: 6px; - position: absolute; - top: 32px; - right: 0; - bottom: 32px; - left: 0; - - text-align: center; - - background-color: #888; - background-image: url(images/texture.png); -} - -#canvasContainer.slideshow { - padding: 0; - overflow: hidden; -} - -#canvasContainer.slideshow > * { - margin: auto; - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; -} - -.presentationMode { - top: 0 !important; - bottom: 0 !important; - background-color: black !important; - cursor: default !important; -} - -#canvas { - 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); - - /* - * Hide the canvas overflow because otherwise the CSS-scaled 'sizer' child - * of the canvas will still advertise the original size in Firefox, causing - * strange scrollbar behavior. - */ - overflow: hidden; -} - -#sliderContainer { - visibility: hidden; -} - -#overlayNavigator { - position: absolute; - width: 100%; - height: 0; - top: calc(50% - 50px); - background-color: rgba(0, 0, 0, 0); - z-index: 3; - opacity: 0; - -webkit-transition: opacity 1s ease-out; - -moz-transition: opacity 1s ease-out; - transition: opacity 1s ease-out; -} -#previousPage { - float: left; - margin-left: 10px; - - /* CSS triangle */ - border-top: 50px solid transparent; - border-bottom: 50px solid transparent; - border-right: 50px solid black; - - opacity: 0.5; -} -#nextPage { - float: right; - margin-right: 10px; - - /* CSS triangle */ - border-top: 50px solid transparent; - border-bottom: 50px solid transparent; - border-left: 50px solid black; - - opacity: 0.5; -} -#previousPage:active { - opacity: 0.8; -} -#nextPage:active { - opacity: 0.8; -} -#overlayCloseButton { - position: absolute; - top: 10px; - right: 10px; - z-index: 3; - font-size: 35px; - color: white; - background-color: black; - opacity: 0.5; - - width: 40px; - height: 40px; - -webkit-border-radius: 20px; - -moz-border-radius: 20px; - border-radius: 20px; - text-align: center; - cursor: pointer; - display: none; -} -#overlayCloseButton:active { - background-color: red; -} - -#aboutDialogCentererTable { - display: table; - width:100%; - height:100%; -} - -#aboutDialogCentererCell { - vertical-align: middle; - text-align:center; - display: table-cell; -} - -#aboutDialog { - width: 280px; - background-color: #666; - color: white; - text-align: center; - border-radius: 2px; - box-shadow: 0px 1px 6px black; - padding: 5px; - font-style: sans-serif; - display: inline-block; -} - -#aboutDialog h1 { - font-size: 25pt; -} - -#aboutDialog p { - font-size: 10pt; -} - -#aboutDialog > * { - margin: 10px; -} - -#dialogOverlay { - position: absolute; - left: 0px; - top: 0px; - width:100%; - height:100%; - z-index: 3; - background-color: rgba(0,0,0,.5); - overflow: auto; - display: none; -} - -#blanked { - display: none; - cursor: none; - position: absolute; - left: 0px; - top: 0px; - width:100%; - height:100%; - z-index: 3; -} - -@media only screen and (max-device-width: 800px) and (max-device-height: 800px) { - #canvasContainer { - top: 0; - bottom: 0; - } - - #overlayNavigator { - height: 100px; - pointer-events: none; - } - #nextPage, #previousPage { - pointer-events: all; - } - - #titlebar, #toolbarContainer { - background-color: rgba(0, 0, 0, 0.6); - background-image: none; - -webkit-transition: all 0.5s; - -moz-transition: all 0.5s; - transition: all 0.5s; - } - - #titlebar { - top: -32px; - } - #titlebar.viewer-touched { - top: 0px; - } - #toolbarContainer { - bottom: -32px; - } - #toolbarContainer.viewer-touched { - bottom: 0px; - } - - .viewer-touched { - display: block; - opacity: 1 !important; - } - - #next, #previous { - display: none; - } -} diff --git a/attachment_preview/static/lib/ViewerJS/viewer.js b/attachment_preview/static/lib/ViewerJS/viewer.js deleted file mode 100644 index 5dbdd653e51..00000000000 --- a/attachment_preview/static/lib/ViewerJS/viewer.js +++ /dev/null @@ -1,17 +0,0 @@ -function Viewer(c){function O(){var a,b,C,d,f;c&&(C=c.getPluginName(),d=c.getPluginVersion(),f=c.getPluginURL());a=document.createElement("div");a.id="aboutDialogCentererTable";b=document.createElement("div");b.id="aboutDialogCentererCell";q=document.createElement("div");q.id="aboutDialog";q.innerHTML='

ViewerJS

Open Source document viewer for webpages, built with HTML and JavaScript.

Learn more and get your own copy on the ViewerJS website.

'+ -(c?'

Using the '+C+' ('+d+") plugin to show you this document.

":"")+'

Supported by
NLnet Foundation

Made by
KO GmbH

'; -u.appendChild(a);a.appendChild(b);b.appendChild(q);a=document.createElement("button");a.id="about";a.className="toolbarButton textButton about";a.title="About";a.innerHTML="ViewerJS";P.appendChild(a);a.addEventListener("click",function(){u.style.display="block"});document.getElementById("aboutDialogCloseButton").addEventListener("click",function(){u.style.display="none"})}function D(a){var b=Q.options,c,d=!1,f;for(f=0;f=a?a=1:a>p.length&&(a=p.length);c.showPage(a);l=a;document.getElementById("pageNumber").value= -l};this.showNextPage=function(){b.showPage(l+1)};this.showPreviousPage=function(){b.showPage(l-1)};this.download=function(){var a=A.split("#")[0];window.open(a+"#viewer.action=download","_parent")};this.toggleFullScreen=function(){m?document.exitFullscreen?document.exitFullscreen():document.cancelFullScreen?document.cancelFullScreen():document.mozCancelFullScreen?document.mozCancelFullScreen():document.webkitExitFullscreen?document.webkitExitFullscreen():document.webkitCancelFullScreen?document.webkitCancelFullScreen(): -document.msExitFullscreen&&document.msExitFullscreen():g.requestFullscreen?g.requestFullscreen():g.mozRequestFullScreen?g.mozRequestFullScreen():g.webkitRequestFullscreen?g.webkitRequestFullscreen():g.webkitRequestFullScreen?g.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT):g.msRequestFullscreen&&g.msRequestFullscreen()};this.togglePresentationMode=function(){var a=document.getElementById("overlayCloseButton");h?("block"===blanked.style.display&&(blanked.style.display="none",z()),k.style.display= -n.style.display="block",a.style.display="none",d.classList.remove("presentationMode"),d.onmouseup=function(){},d.oncontextmenu=function(){},d.onmousedown=function(){},e("auto"),t=c.isSlideshow()):(k.style.display=n.style.display="none",a.style.display="block",d.classList.add("presentationMode"),t=!0,d.onmousedown=function(a){a.preventDefault()},d.oncontextmenu=function(a){a.preventDefault()},d.onmouseup=function(a){a.preventDefault();1===a.which?b.showNextPage():b.showPreviousPage()},e("page-fit")); -h=!h};this.getZoomLevel=function(){return c.getZoomLevel()};this.setZoomLevel=function(a){c.setZoomLevel(a)};this.zoomOut=function(){var a=(b.getZoomLevel()/1.1).toFixed(2),a=Math.max(0.25,a);e(a,!0)};this.zoomIn=function(){var a=(1.1*b.getZoomLevel()).toFixed(2),a=Math.min(4,a);e(a,!0)};(function(){O();c&&(b.initialize(),document.exitFullscreen||document.cancelFullScreen||document.mozCancelFullScreen||document.webkitExitFullscreen||document.webkitCancelFullScreen||document.msExitFullscreen||(document.getElementById("fullscreen").style.visibility= -"hidden",document.getElementById("presentation").style.visibility="hidden"),document.getElementById("overlayCloseButton").addEventListener("click",b.toggleFullScreen),document.getElementById("fullscreen").addEventListener("click",b.toggleFullScreen),document.getElementById("presentation").addEventListener("click",function(){m||b.toggleFullScreen();b.togglePresentationMode()}),document.addEventListener("fullscreenchange",s),document.addEventListener("webkitfullscreenchange",s),document.addEventListener("mozfullscreenchange", -s),document.addEventListener("MSFullscreenChange",s),document.getElementById("download").addEventListener("click",function(){b.download()}),document.getElementById("zoomOut").addEventListener("click",function(){b.zoomOut()}),document.getElementById("zoomIn").addEventListener("click",function(){b.zoomIn()}),document.getElementById("previous").addEventListener("click",function(){b.showPreviousPage()}),document.getElementById("next").addEventListener("click",function(){b.showNextPage()}),document.getElementById("previousPage").addEventListener("click", -function(){b.showPreviousPage()}),document.getElementById("nextPage").addEventListener("click",function(){b.showNextPage()}),document.getElementById("pageNumber").addEventListener("change",function(){b.showPage(this.value)}),document.getElementById("scaleSelect").addEventListener("change",function(){e(this.value)}),d.addEventListener("click",v),w.addEventListener("click",v),d.addEventListener("click",z),k.addEventListener("click",x),n.addEventListener("click",x),window.addEventListener("scalechange", -function(a){var b=document.getElementById("customScaleOption"),c=D(String(a.scale));b.selected=!1;c||(b.textContent=Math.round(1E4*a.scale)/100+"%",b.selected=!0)},!0),window.addEventListener("resize",function(a){L&&(document.getElementById("pageWidthOption").selected||document.getElementById("pageAutoOption").selected)&&e(document.getElementById("scaleSelect").value);v()}),window.addEventListener("keydown",function(a){var c=a.keyCode;a=a.shiftKey;if("block"===blanked.style.display)switch(c){case 16:case 17:case 18:case 91:case 93:case 224:case 225:break; -default:blanked.style.display="none",z()}else switch(c){case 8:case 33:case 37:case 38:case 80:b.showPreviousPage();break;case 13:case 34:case 39:case 40:case 78:b.showNextPage();break;case 32:a?b.showPreviousPage():b.showNextPage();break;case 66:case 190:h&&K("#000");break;case 87:case 188:h&&K("#FFF");break;case 36:b.showPage(0);break;case 35:b.showPage(p.length)}}))})()}; diff --git a/attachment_preview/static/lib/ViewerJS/webodf.js b/attachment_preview/static/lib/ViewerJS/webodf.js index 269d7807c66..6a07cea163a 100644 --- a/attachment_preview/static/lib/ViewerJS/webodf.js +++ b/attachment_preview/static/lib/ViewerJS/webodf.js @@ -2,634 +2,641 @@ This is a generated file. DO NOT EDIT. - Copyright (C) 2010-2014 KO GmbH + Copyright (C) 2010-2015 KO GmbH @licstart - This file is the compiled version of the WebODF library. - - WebODF is free software: you can redistribute it and/or modify it + The code in this file is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License (GNU AGPL) as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. - WebODF is distributed in the hope that it will be useful, but + The code in this file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with WebODF. If not, see . + + As additional permission under GNU AGPL version 3 section 7, you + may distribute UNMODIFIED VERSIONS OF THIS file without the copy of the GNU AGPL normally + required by section 4, provided you include this license notice and a URL + through which recipients can access the Corresponding Source. + + As a special exception to the AGPL, any HTML file which merely makes function + calls to this code, and for that purpose includes it in unmodified form by reference or in-line shall be + deemed a separate work for copyright law purposes. In addition, the copyright + holders of this code give you permission to combine this code with free + software libraries that are released under the GNU LGPL. You may copy and + distribute such a system following the terms of the GNU AGPL for this code + and the LGPL for the libraries. If you modify this code, you may extend this + exception to your version of the code, but you are not obligated to do so. + If you do not wish to do so, delete this exception statement from your + version. + + This license applies to this entire compilation. @licend @source: http://www.webodf.org/ @source: https://github.com/kogmbh/WebODF/ */ -var webodf_version="0.5.4";function Runtime(){}Runtime.prototype.getVariable=function(f){};Runtime.prototype.toJson=function(f){};Runtime.prototype.fromJson=function(f){};Runtime.prototype.byteArrayFromString=function(f,k){};Runtime.prototype.byteArrayToString=function(f,k){};Runtime.prototype.read=function(f,k,a,d){};Runtime.prototype.readFile=function(f,k,a){};Runtime.prototype.readFileSync=function(f,k){};Runtime.prototype.loadXML=function(f,k){};Runtime.prototype.writeFile=function(f,k,a){}; -Runtime.prototype.deleteFile=function(f,k){};Runtime.prototype.log=function(f,k){};Runtime.prototype.setTimeout=function(f,k){};Runtime.prototype.clearTimeout=function(f){};Runtime.prototype.libraryPaths=function(){};Runtime.prototype.currentDirectory=function(){};Runtime.prototype.setCurrentDirectory=function(f){};Runtime.prototype.type=function(){};Runtime.prototype.getDOMImplementation=function(){};Runtime.prototype.parseXML=function(f){};Runtime.prototype.exit=function(f){}; -Runtime.prototype.getWindow=function(){};Runtime.prototype.requestAnimationFrame=function(f){};Runtime.prototype.cancelAnimationFrame=function(f){};Runtime.prototype.assert=function(f,k){};var IS_COMPILED_CODE=!0; -Runtime.byteArrayToString=function(f,k){function a(d){var a="",c,m=d.length;for(c=0;cr?l.push(r):(c+=1,b=d[c],194<=r&&224>r?l.push((r&31)<<6|b&63):(c+=1,e=d[c],224<=r&&240>r?l.push((r&15)<<12|(b&63)<<6|e&63):(c+=1,n=d[c],240<=r&&245>r&&(r=(r&7)<<18|(b&63)<<12|(e&63)<<6|n&63,r-=65536,l.push((r>>10)+55296,(r&1023)+56320))))),1E3<=l.length&&(a+=String.fromCharCode.apply(null, -l),l.length=0);return a+String.fromCharCode.apply(null,l)}var c;"utf8"===k?c=d(f):("binary"!==k&&this.log("Unsupported encoding: "+k),c=a(f));return c};Runtime.getVariable=function(f){try{return eval(f)}catch(k){}};Runtime.toJson=function(f){return JSON.stringify(f)};Runtime.fromJson=function(f){return JSON.parse(f)};Runtime.getFunctionName=function(f){return void 0===f.name?(f=/function\s+(\w+)/.exec(f))&&f[1]:f.name}; -Runtime.assert=function(f,k){if(!f)throw this.log("alert","ASSERTION FAILED:\n"+k),Error(k);}; -function BrowserRuntime(f){function k(d){var a=d.length,b,e,n=0;for(b=0;be&&(n+=1,b+=1);return n}function a(d,a,b){var e=d.length,n,g;a=new Uint8Array(new ArrayBuffer(a));b?(a[0]=239,a[1]=187,a[2]=191,g=3):g=0;for(b=0;bn?(a[g]=n,g+=1):2048>n?(a[g]=192|n>>>6,a[g+1]=128|n&63,g+=2):55040>=n||57344<=n?(a[g]=224|n>>>12&15,a[g+1]=128|n>>>6&63,a[g+2]=128|n&63,g+=3):(b+=1,n=(n-55296<<10|d.charCodeAt(b)-56320)+65536, -a[g]=240|n>>>18&7,a[g+1]=128|n>>>12&63,a[g+2]=128|n>>>6&63,a[g+3]=128|n&63,g+=4);return a}function d(a){var d=a.length,b=new Uint8Array(new ArrayBuffer(d)),e;for(e=0;ee.status||0===e.status?b(null):b("Status "+String(e.status)+": "+e.responseText||e.statusText):b("File "+d+" is empty."))};n=a.buffer&&!e.sendAsBinary?a.buffer:m.byteArrayToString(a,"binary");try{e.sendAsBinary?e.sendAsBinary(n):e.send(n)}catch(g){m.log("HUH? "+g+" "+a),b(g.message)}};this.deleteFile=function(d,a){var b=new XMLHttpRequest;b.open("DELETE",d,!0);b.onreadystatechange=function(){4=== -b.readyState&&(200>b.status&&300<=b.status?a(b.responseText):a(null))};b.send(null)};this.loadXML=function(d,a){var b=new XMLHttpRequest;b.open("GET",d,!0);b.overrideMimeType&&b.overrideMimeType("text/xml");b.onreadystatechange=function(){4===b.readyState&&(0!==b.status||b.responseText?200===b.status||0===b.status?a(null,b.responseXML):a(b.responseText,null):a("File "+d+" is empty.",null))};try{b.send(null)}catch(e){a(e.message,null)}};this.log=c;this.enableAlerts=!0;this.assert=Runtime.assert;this.setTimeout= -function(d,a){return setTimeout(function(){d()},a)};this.clearTimeout=function(d){clearTimeout(d)};this.libraryPaths=function(){return["lib"]};this.setCurrentDirectory=function(){};this.currentDirectory=function(){return""};this.type=function(){return"BrowserRuntime"};this.getDOMImplementation=function(){return window.document.implementation};this.parseXML=function(d){return(new DOMParser).parseFromString(d,"text/xml")};this.exit=function(d){c("Calling exit with code "+String(d)+", but exit() is not implemented.")}; -this.getWindow=function(){return window};this.requestAnimationFrame=function(d){var a=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.msRequestAnimationFrame,b=0;if(a)a.bind(window),b=a(d);else return setTimeout(d,15);return b};this.cancelAnimationFrame=function(d){var a=window.cancelAnimationFrame||window.webkitCancelAnimationFrame||window.mozCancelAnimationFrame||window.msCancelAnimationFrame;a?(a.bind(window),a(d)):clearTimeout(d)}} -function NodeJSRuntime(){function f(d){var a=d.length,c,b=new Uint8Array(new ArrayBuffer(a));for(c=0;ch?g.push(h):(b+=1,d=a[b],194<=h&&224>h?g.push((h&31)<<6|d&63):(b+=1,e=a[b],224<=h&&240>h?g.push((h&15)<<12|(d&63)<<6|e&63):(b+=1,s=a[b],240<=h&&245>h&&(h=(h&7)<<18|(d&63)<<12|(e&63)<<6|s&63,h-=65536,g.push((h>>10)+55296,(h&1023)+56320))))),1E3<=g.length&& +(c+=String.fromCharCode.apply(null,g),g.length=0);return c+String.fromCharCode.apply(null,g)}var b;"utf8"===l?b=c(f):("binary"!==l&&this.log("Unsupported encoding: "+l),b=a(f));return b};Runtime.getVariable=function(f){try{return eval(f)}catch(l){}};Runtime.toJson=function(f){return JSON.stringify(f)};Runtime.fromJson=function(f){return JSON.parse(f)};Runtime.getFunctionName=function(f){return void 0===f.name?(f=/function\s+(\w+)/.exec(f))&&f[1]:f.name}; +Runtime.assert=function(f,l){if(!f)throw this.log("alert","ASSERTION FAILED:\n"+l),Error(l);}; +function BrowserRuntime(){function f(a){var g=a.length,h,d,e=0;for(h=0;hd&&(e+=1,h+=1);return e}function l(a,g,h){var d=a.length,e,s;g=new Uint8Array(new ArrayBuffer(g));h?(g[0]=239,g[1]=187,g[2]=191,s=3):s=0;for(h=0;he?(g[s]=e,s+=1):2048>e?(g[s]=192|e>>>6,g[s+1]=128|e&63,s+=2):55040>=e||57344<=e?(g[s]=224|e>>>12&15,g[s+1]=128|e>>>6&63,g[s+2]=128|e&63,s+=3):(h+=1,e=(e-55296<<10|a.charCodeAt(h)-56320)+65536, +g[s]=240|e>>>18&7,g[s+1]=128|e>>>12&63,g[s+2]=128|e>>>6&63,g[s+3]=128|e&63,s+=4);return g}function a(a){var g=a.length,h=new Uint8Array(new ArrayBuffer(g)),d;for(d=0;dd.status||0===d.status?h(null):h("Status "+String(d.status)+": "+d.responseText||d.statusText):h("File "+c+" is empty."))};e=a.buffer&&!d.sendAsBinary?a.buffer:p.byteArrayToString(a,"binary");try{d.sendAsBinary?d.sendAsBinary(e):d.send(e)}catch(s){p.log("HUH? "+ +s+" "+a),h(s.message)}};this.deleteFile=function(c,a){var h=new XMLHttpRequest;h.open("DELETE",c,!0);h.onreadystatechange=function(){4===h.readyState&&(200>h.status&&300<=h.status?a(h.responseText):a(null))};h.send(null)};this.loadXML=function(c,a){var h=new XMLHttpRequest;h.open("GET",c,!0);h.overrideMimeType&&h.overrideMimeType("text/xml");h.onreadystatechange=function(){4===h.readyState&&(0!==h.status||h.responseText?200===h.status||0===h.status?a(null,h.responseXML):a(h.responseText,null):a("File "+ +c+" is empty.",null))};try{h.send(null)}catch(d){a(d.message,null)}};this.log=c;this.enableAlerts=!0;this.assert=Runtime.assert;this.setTimeout=function(a,c){return setTimeout(function(){a()},c)};this.clearTimeout=function(a){clearTimeout(a)};this.libraryPaths=function(){return["lib"]};this.setCurrentDirectory=function(){};this.currentDirectory=function(){return""};this.type=function(){return"BrowserRuntime"};this.getDOMImplementation=function(){return window.document.implementation};this.parseXML= +function(a){return(new DOMParser).parseFromString(a,"text/xml")};this.exit=function(a){c("Calling exit with code "+String(a)+", but exit() is not implemented.")};this.getWindow=function(){return window};this.requestAnimationFrame=function(a){var c=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.msRequestAnimationFrame,h=0;if(c)c.bind(window),h=c(a);else return setTimeout(a,15);return h};this.cancelAnimationFrame=function(a){var c=window.cancelAnimationFrame|| +window.webkitCancelAnimationFrame||window.mozCancelAnimationFrame||window.msCancelAnimationFrame;c?(c.bind(window),c(a)):clearTimeout(a)}} +function NodeJSRuntime(){function f(a){var c=a.length,h,d=new Uint8Array(new ArrayBuffer(c));for(h=0;h").implementation} -function RhinoRuntime(){var f=this,k={},a=k.javax.xml.parsers.DocumentBuilderFactory.newInstance(),d,c,h="";a.setValidating(!1);a.setNamespaceAware(!0);a.setExpandEntityReferences(!1);a.setSchema(null);c=k.org.xml.sax.EntityResolver({resolveEntity:function(a,d){var c=new k.java.io.FileReader(d);return new k.org.xml.sax.InputSource(c)}});d=a.newDocumentBuilder();d.setEntityResolver(c);this.byteArrayFromString=function(a,d){var c,h=a.length,r=new Uint8Array(new ArrayBuffer(h));for(c=0;c>>18],n+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[b>>>12&63],n+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[b>>>6&63],n+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[b& -63];e===a+1?(b=g[e]<<4,n+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[b>>>6],n+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[b&63],n+="=="):e===a&&(b=g[e]<<10|g[e+1]<<2,n+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[b>>>12],n+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[b>>>6&63],n+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[b&63],n+="=");return n}function a(b){b=b.replace(/[^A-Za-z0-9+\/]+/g, -"");var n=b.length,e=new Uint8Array(new ArrayBuffer(3*n)),a=b.length%4,d=0,c,J;for(c=0;c>16,e[d+1]=J>>8&255,e[d+2]=J&255,d+=3;n=3*n-[0,0,2,1][a];return e.subarray(0,n)}function d(b){var g,n,e=b.length,a=0,d=new Uint8Array(new ArrayBuffer(3*e));for(g=0;gn?d[a++]=n:(2048>n?d[a++]=192|n>>>6:(d[a++]=224|n>>>12&15,d[a++]=128|n>>>6&63),d[a++]=128|n&63);return d.subarray(0, -a)}function c(b){var g,n,e,a,d=b.length,c=new Uint8Array(new ArrayBuffer(d)),h=0;for(g=0;gn?c[h++]=n:(g+=1,e=b[g],224>n?c[h++]=(n&31)<<6|e&63:(g+=1,a=b[g],c[h++]=(n&15)<<12|(e&63)<<6|a&63));return c.subarray(0,h)}function h(b){return k(f(b))}function q(b){return String.fromCharCode.apply(String,a(b))}function p(b){return c(f(b))}function m(b){b=c(b);for(var g="",n=0;ng?c+=String.fromCharCode(g):(d+=1,e=b.charCodeAt(d)&255,224>g?c+=String.fromCharCode((g&31)<<6|e&63):(d+=1,a=b.charCodeAt(d)&255,c+=String.fromCharCode((g&15)<<12|(e&63)<<6|a&63)));return c}function r(b,g){function n(){var d=a+1E5;d>b.length&&(d=b.length);e+=l(b,a,d);a=d;d=a===b.length;g(e,d)&&!d&&runtime.setTimeout(n,0)}var e="",a=0;1E5>b.length?g(l(b,0,b.length),!0):("string"!==typeof b&&(b=b.slice()),n())}function b(b){return d(f(b))}function e(b){return String.fromCharCode.apply(String, -d(b))}function n(b){return String.fromCharCode.apply(String,d(f(b)))}var g=function(b){var g={},n,e;n=0;for(e=b.length;nc-d&&(c=Math.max(2*c,d+a),a=new Uint8Array(new ArrayBuffer(c)),a.set(h),h=a)}var a=this,d=0,c=1024,h=new Uint8Array(new ArrayBuffer(c));this.appendByteArrayWriter=function(d){a.appendByteArray(d.getByteArray())};this.appendByteArray=function(a){var c=a.length;k(c);h.set(a,d);d+=c};this.appendArray=function(a){var c=a.length;k(c);h.set(a,d);d+=c};this.appendUInt16LE=function(d){a.appendArray([d&255,d>>8&255])};this.appendUInt32LE=function(d){a.appendArray([d& -255,d>>8&255,d>>16&255,d>>24&255])};this.appendString=function(d){a.appendByteArray(runtime.byteArrayFromString(d,f))};this.getLength=function(){return d};this.getByteArray=function(){var a=new Uint8Array(new ArrayBuffer(d));a.set(h.subarray(0,d));return a}};core.CSSUnits=function(){var f=this,k={"in":1,cm:2.54,mm:25.4,pt:72,pc:12,px:96};this.convert=function(a,d,c){return a*k[c]/k[d]};this.convertMeasure=function(a,d){var c,h;a&&d&&(c=parseFloat(a),h=a.replace(c.toString(),""),c=f.convert(c,h,d));return c};this.getUnits=function(a){return a.substr(a.length-2,a.length)}};(function(){function f(){var d,c,h,f,p,k,l,r,b;void 0===a&&(c=(d=runtime.getWindow())&&d.document,k=c.documentElement,l=c.body,a={rangeBCRIgnoresElementBCR:!1,unscaledRangeClientRects:!1,elementBCRIgnoresBodyScroll:!1},c&&(f=c.createElement("div"),f.style.position="absolute",f.style.left="-99999px",f.style.transform="scale(2)",f.style["-webkit-transform"]="scale(2)",p=c.createElement("div"),f.appendChild(p),l.appendChild(f),d=c.createRange(),d.selectNode(p),a.rangeBCRIgnoresElementBCR=0===d.getClientRects().length, -p.appendChild(c.createTextNode("Rect transform test")),c=p.getBoundingClientRect(),h=d.getBoundingClientRect(),a.unscaledRangeClientRects=2=b.compareBoundaryPoints(Range.START_TO_START,g)&&0<=b.compareBoundaryPoints(Range.END_TO_END,g)}function h(b,g){return 0>=b.compareBoundaryPoints(Range.END_TO_START,g)&&0<=b.compareBoundaryPoints(Range.START_TO_END,g)}function q(b,g){var e=null;b.nodeType===Node.TEXT_NODE&&(0===b.length?(b.parentNode.removeChild(b),g.nodeType===Node.TEXT_NODE&&(e=g)):(g.nodeType===Node.TEXT_NODE&&(b.appendData(g.data),g.parentNode.removeChild(g)),e=b));return e} -function p(b){for(var g=b.parentNode;b.firstChild;)g.insertBefore(b.firstChild,b);g.removeChild(b);return g}function m(b,g){for(var e=b.parentNode,a=b.firstChild,d;a;)d=a.nextSibling,m(a,g),a=d;e&&g(b)&&p(b);return e}function l(b,g){return b===g||Boolean(b.compareDocumentPosition(g)&Node.DOCUMENT_POSITION_CONTAINED_BY)}function r(b,g){return f().unscaledRangeClientRects?b:b/g}function b(n,g,e){Object.keys(g).forEach(function(a){var d=a.split(":"),c=d[1],h=e(d[0]),d=g[a],f=typeof d;"object"===f?Object.keys(d).length&& -(a=h?n.getElementsByTagNameNS(h,c)[0]||n.ownerDocument.createElementNS(h,a):n.getElementsByTagName(c)[0]||n.ownerDocument.createElement(a),n.appendChild(a),b(a,d,e)):h&&(runtime.assert("number"===f||"string"===f,"attempting to map unsupported type '"+f+"' (key: "+a+")"),n.setAttributeNS(h,a,String(d)))})}var e=null;this.splitBoundaries=function(b){var g,e=[],c,h,f;if(b.startContainer.nodeType===Node.TEXT_NODE||b.endContainer.nodeType===Node.TEXT_NODE){c=b.endContainer;h=b.endContainer.nodeType!== -Node.TEXT_NODE?b.endOffset===b.endContainer.childNodes.length:!1;f=b.endOffset;g=b.endContainer;if(ff))throw runtime.log("alert","watchdog timeout"),"timeout!";if(0k))throw runtime.log("alert","watchdog loop overflow"),"loop overflow";}};core.NodeFilterChain=function(f){var k=NodeFilter.FILTER_REJECT,a=NodeFilter.FILTER_ACCEPT;this.acceptNode=function(d){var c;for(c=0;c "+g.length),runtime.assert(0<=e,"Error in setPosition: "+e+" < 0"),e===g.length&&(r.nextSibling()?b=0:r.parentNode()?b=1:runtime.assert(!1,"Error in setUnfilteredPosition: position not valid."))):ea.windowBits&&(a.windowBits=-a.windowBits,0===a.windowBits&&(a.windowBits=-15));!(0<=a.windowBits&&16>a.windowBits)||g&&g.windowBits||(a.windowBits+=32);15a.windowBits&&0===(a.windowBits&15)&&(a.windowBits|=15);this.err=0;this.msg="";this.ended=!1;this.chunks= -[];this.strm=new b;this.strm.avail_out=0;g=f.inflateInit2(this.strm,a.windowBits);if(g!==l.Z_OK)throw Error(r[g]);this.header=new e;f.inflateGetHeader(this.strm,this.header)};n.prototype.push=function(b,e){var a=this.strm,d=this.options.chunkSize,n,c,h,r,B;if(this.ended)return!1;c=e===~~e?e:!0===e?l.Z_FINISH:l.Z_NO_FLUSH;a.input="string"===typeof b?m.binstring2buf(b):b;a.next_in=0;a.avail_in=a.input.length;do{0===a.avail_out&&(a.output=new p.Buf8(d),a.next_out=0,a.avail_out=d);n=f.inflate(a,l.Z_NO_FLUSH); -if(n!==l.Z_STREAM_END&&n!==l.Z_OK)return this.onEnd(n),this.ended=!0,!1;if(a.next_out&&(0===a.avail_out||n===l.Z_STREAM_END||0===a.avail_in&&c===l.Z_FINISH))if("string"===this.options.to)h=m.utf8border(a.output,a.next_out),r=a.next_out-h,B=m.buf2string(a.output,h),a.next_out=r,a.avail_out=d-r,r&&p.arraySet(a.output,a.output,h,r,0),this.onData(B);else this.onData(p.shrinkBuf(a.output,a.next_out))}while((0a&&(b.subarray&&m||!b.subarray&&p))return String.fromCharCode.apply(null,f.shrinkBuf(b,a));for(var g="",d=0;da;a++)b[a]=252<=a?6:248<= -a?5:240<=a?4:224<=a?3:192<=a?2:1;b[254]=b[254]=1;c.string2buf=function(b){var a,g,d,c,h,r=b.length,p=0;for(c=0;cg?1:2048>g?2:65536>g?3:4;a=new f.Buf8(p);for(c=h=0;hg?a[h++]=g:(2048>g?a[h++]=192|g>>>6:(65536>g?a[h++]=224|g>>>12:(a[h++]= -240|g>>>18,a[h++]=128|g>>>12&63),a[h++]=128|g>>>6&63),a[h++]=128|g&63);return a};c.buf2binstring=function(b){return h(b,b.length)};c.binstring2buf=function(b){for(var a=new f.Buf8(b.length),g=0,d=a.length;gf)q[c++]=f;else if(r=b[f],4f?q[c++]=f:(f-=65536,q[c++]= -55296|f>>10&1023,q[c++]=56320|f&1023)}return h(q,c)};c.utf8border=function(a,d){var g;d=d||a.length;d>a.length&&(d=a.length);for(g=d-1;0<=g&&128===(a[g]&192);)g--;return 0>g||0===g?d:g+b[a[g]]>d?g:d}},{"./common":2}],4:[function(a,d,c){d.exports=function(a,d,c,f){var l=a&65535|0;a=a>>>16&65535|0;for(var r=0;0!==c;){r=2E3c;c++){a=c;for(var h=0;8>h;h++)a=a&1?3988292384^a>>>1:a>>>1;d[c]=a}return d}();d.exports=function(a,d,c,f){c=f+c;for(a^= --1;f>>8^h[(a^d[f])&255];return a^-1}},{}],7:[function(a,d,c){d.exports=function(){this.os=this.xflags=this.time=this.text=0;this.extra=null;this.extra_len=0;this.comment=this.name="";this.hcrc=0;this.done=!1}},{}],8:[function(a,d,c){d.exports=function(a,d){var c,f,l,r,b,e,n,g,u,t,y,v,s,x,w,B,I,C,F,J,N,K,H,z;c=a.state;f=a.next_in;H=a.input;l=f+(a.avail_in-5);r=a.next_out;z=a.output;b=r-(d-a.avail_out);e=r+(a.avail_out-257);n=c.dmax;g=c.wsize;u=c.whave;t=c.wnext;y=c.window;v=c.hold;s=c.bits; -x=c.lencode;w=c.distcode;B=(1<s&&(v+=H[f++]<>>24;v>>>=F;s-=F;F=C>>>16&255;if(0===F)z[r++]=C&65535;else if(F&16){J=C&65535;if(F&=15)s>>=F,s-=F;15>s&&(v+=H[f++]<>>24;v>>>=F;s-=F;F=C>>>16&255;if(F&16){C&=65535;F&=15;sn){a.msg="invalid distance too far back"; -c.mode=30;break a}v>>>=F;s-=F;F=r-b;if(C>F){F=C-F;if(F>u&&c.sane){a.msg="invalid distance too far back";c.mode=30;break a}N=0;K=y;if(0===t){if(N+=g-F,F>3;f-=J;s-=J<<3;a.next_in=f;a.next_out=r;a.avail_in=f>>24&255)+(b>>>8&65280)+((b&65280)<<8)+((b&255)<<24)}function q(){this.mode=0;this.last=!1;this.wrap=0;this.havedict=!1;this.total=this.check=this.dmax=this.flags=0;this.head=null;this.wnext=this.whave=this.wsize=this.wbits=0;this.window=null;this.extra=this.offset=this.length=this.bits=this.hold=0;this.distcode=this.lencode=null;this.have=this.ndist=this.nlen=this.ncode=this.distbits=this.lenbits=0;this.next=null;this.lens=new b.Buf16(320);this.work= -new b.Buf16(288);this.distdyn=this.lendyn=null;this.was=this.back=this.sane=0}function p(a){var g;if(!a||!a.state)return y;g=a.state;a.total_in=a.total_out=g.total=0;a.msg="";g.wrap&&(a.adler=g.wrap&1);g.mode=v;g.last=0;g.havedict=0;g.dmax=32768;g.head=null;g.hold=0;g.bits=0;g.lencode=g.lendyn=new b.Buf32(s);g.distcode=g.distdyn=new b.Buf32(x);g.sane=1;g.back=-1;return t}function m(b){var a;if(!b||!b.state)return y;a=b.state;a.wsize=0;a.whave=0;a.wnext=0;return p(b)}function l(b,a){var g,e;if(!b|| -!b.state)return y;e=b.state;0>a?(g=0,a=-a):(g=(a>>4)+1,48>a&&(a&=15));if(a&&(8>a||15s;){if(0===l)break a;l--;m+=r[H++]<>>8&255;c.check=n(c.check,X,2,0);s=m=0;c.mode=2;break}c.flags=0;c.head&&(c.head.done=!1);if(!(c.wrap&1)||(((m&255)<<8)+(m>>8))%31){a.msg="incorrect header check";c.mode=30;break}if(8!==(m&15)){a.msg="unknown compression method";c.mode=30;break}m>>>=4;s-=4;Q=(m&15)+8;if(0===c.wbits)c.wbits=Q;else if(Q>c.wbits){a.msg="invalid window size";c.mode=30;break}c.dmax=1<s;){if(0===l)break a;l--;m+=r[H++]<>8&1);c.flags&512&&(X[0]=m&255,X[1]=m>>>8&255,c.check=n(c.check,X,2,0));s=m=0;c.mode=3;case 3:for(;32>s;){if(0===l)break a;l--;m+=r[H++]<>>8&255,X[2]=m>>>16&255,X[3]=m>>>24&255,c.check=n(c.check,X,4,0));s=m=0;c.mode=4;case 4:for(;16>s;){if(0===l)break a;l--;m+=r[H++]<>8);c.flags&512&&(X[0]=m&255,X[1]=m>>>8&255,c.check=n(c.check,X,2,0));s=m=0;c.mode=5;case 5:if(c.flags&1024){for(;16>s;){if(0===l)break a;l--;m+=r[H++]<>>8&255,c.check=n(c.check,X,2,0));s=m=0}else c.head&&(c.head.extra=null);c.mode=6;case 6:if(c.flags&1024&&(D=c.length,D>l&&(D=l),D&&(c.head&&(Q=c.head.extra_len-c.length,c.head.extra||(c.head.extra=Array(c.head.extra_len)),b.arraySet(c.head.extra, -r,H,D,Q)),c.flags&512&&(c.check=n(c.check,r,D,H)),l-=D,H+=D,c.length-=D),c.length))break a;c.length=0;c.mode=7;case 7:if(c.flags&2048){if(0===l)break a;D=0;do Q=r[H+D++],c.head&&Q&&65536>c.length&&(c.head.name+=String.fromCharCode(Q));while(Q&&Dc.length&&(c.head.comment+=String.fromCharCode(Q));while(Q&&D< -l);c.flags&512&&(c.check=n(c.check,r,D,H));l-=D;H+=D;if(Q)break a}else c.head&&(c.head.comment=null);c.mode=9;case 9:if(c.flags&512){for(;16>s;){if(0===l)break a;l--;m+=r[H++]<>9&1,c.head.done=!0);a.adler=c.check=0;c.mode=12;break;case 10:for(;32>s;){if(0===l)break a;l--;m+=r[H++]<>>=s&7;s-=s&7;c.mode=27;break}for(;3>s;){if(0===l)break a;l--;m+=r[H++]<>>=1;s-=1;switch(m&3){case 0:c.mode=14;break;case 1:D=c;if(w){Q=void 0;B=new b.Buf32(512);I=new b.Buf32(32);for(Q=0;144>Q;)D.lens[Q++]=8;for(;256>Q;)D.lens[Q++]=9;for(;280>Q;)D.lens[Q++]=7;for(;288>Q;)D.lens[Q++]=8;u(1,D.lens,0,288,B,0,D.work,{bits:9});for(Q=0;32>Q;)D.lens[Q++]=5;u(2,D.lens, -0,32,I,0,D.work,{bits:5});w=!1}D.lencode=B;D.lenbits=9;D.distcode=I;D.distbits=5;c.mode=20;if(6===d){m>>>=2;s-=2;break a}break;case 2:c.mode=17;break;case 3:a.msg="invalid block type",c.mode=30}m>>>=2;s-=2;break;case 14:m>>>=s&7;for(s-=s&7;32>s;){if(0===l)break a;l--;m+=r[H++]<>>16^65535)){a.msg="invalid stored block lengths";c.mode=30;break}c.length=m&65535;s=m=0;c.mode=15;if(6===d)break a;case 15:c.mode=16;case 16:if(D=c.length){D>l&&(D=l);D>p&&(D=p);if(0===D)break a;b.arraySet(K, -r,H,D,q);l-=D;H+=D;p-=D;q+=D;c.length-=D;break}c.mode=12;break;case 17:for(;14>s;){if(0===l)break a;l--;m+=r[H++]<>>=5;s-=5;c.ndist=(m&31)+1;m>>>=5;s-=5;c.ncode=(m&15)+4;m>>>=4;s-=4;if(286s;){if(0===l)break a;l--;m+=r[H++]<>>=3;s-=3}for(;19>c.have;)c.lens[R[c.have++]]=0;c.lencode=c.lendyn;c.lenbits=7; -D={bits:c.lenbits};E=u(0,c.lens,0,19,c.lencode,0,c.work,D);c.lenbits=D.bits;if(E){a.msg="invalid code lengths set";c.mode=30;break}c.have=0;c.mode=19;case 19:for(;c.have>>24;V=D>>>16&255;ba=D&65535;if(A<=s)break;if(0===l)break a;l--;m+=r[H++]<ba)m>>>=A,s-=A,c.lens[c.have++]=ba;else{if(16===ba){for(D=A+2;s>>=A;s-=A;if(0===c.have){a.msg="invalid bit length repeat";c.mode=30;break}Q= -c.lens[c.have-1];D=3+(m&3);m>>>=2;s-=2}else if(17===ba){for(D=A+3;s>>=A;s-=A;Q=0;D=3+(m&7);m>>>=3;s-=3}else{for(D=A+7;s>>=A;s-=A;Q=0;D=11+(m&127);m>>>=7;s-=7}if(c.have+D>c.nlen+c.ndist){a.msg="invalid bit length repeat";c.mode=30;break}for(;D--;)c.lens[c.have++]=Q}}if(30===c.mode)break;if(0===c.lens[256]){a.msg="invalid code -- missing end-of-block";c.mode=30;break}c.lenbits=9;D={bits:c.lenbits};E=u(1,c.lens, -0,c.nlen,c.lencode,0,c.work,D);c.lenbits=D.bits;if(E){a.msg="invalid literal/lengths set";c.mode=30;break}c.distbits=6;c.distcode=c.distdyn;D={bits:c.distbits};E=u(2,c.lens,c.nlen,c.ndist,c.distcode,0,c.work,D);c.distbits=D.bits;if(E){a.msg="invalid distances set";c.mode=30;break}c.mode=20;if(6===d)break a;case 20:c.mode=21;case 21:if(6<=l&&258<=p){a.next_out=q;a.avail_out=p;a.next_in=H;a.avail_in=l;c.hold=m;c.bits=s;g(a,P);q=a.next_out;K=a.output;p=a.avail_out;H=a.next_in;r=a.input;l=a.avail_in; -m=c.hold;s=c.bits;12===c.mode&&(c.back=-1);break}for(c.back=0;;){D=c.lencode[m&(1<>>24;V=D>>>16&255;ba=D&65535;if(A<=s)break;if(0===l)break a;l--;m+=r[H++]<>Q)];A=D>>>24;V=D>>>16&255;ba=D&65535;if(Q+A<=s)break;if(0===l)break a;l--;m+=r[H++]<>>=Q;s-=Q;c.back+=Q}m>>>=A;s-=A;c.back+=A;c.length=ba;if(0===V){c.mode=26;break}if(V&32){c.back=-1;c.mode=12;break}if(V&64){a.msg="invalid literal/length code"; -c.mode=30;break}c.extra=V&15;c.mode=22;case 22:if(c.extra){for(D=c.extra;s>>=c.extra;s-=c.extra;c.back+=c.extra}c.was=c.length;c.mode=23;case 23:for(;;){D=c.distcode[m&(1<>>24;V=D>>>16&255;ba=D&65535;if(A<=s)break;if(0===l)break a;l--;m+=r[H++]<>Q)];A=D>>>24;V=D>>>16&255;ba=D&65535;if(Q+A<=s)break;if(0===l)break a;l--;m+=r[H++]<>>=Q;s-=Q;c.back+=Q}m>>>=A;s-=A;c.back+=A;if(V&64){a.msg="invalid distance code";c.mode=30;break}c.offset=ba;c.extra=V&15;c.mode=24;case 24:if(c.extra){for(D=c.extra;s>>=c.extra;s-=c.extra;c.back+=c.extra}if(c.offset>c.dmax){a.msg="invalid distance too far back";c.mode=30;break}c.mode=25;case 25:if(0===p)break a;D=P-p;if(c.offset>D){D=c.offset-D;if(D>c.whave&&c.sane){a.msg="invalid distance too far back";c.mode=30;break}D> -c.wnext?(D-=c.wnext,Q=c.wsize-D):Q=c.wnext-D;D>c.length&&(D=c.length);$=c.window}else $=K,Q=q-c.offset,D=c.length;D>p&&(D=p);p-=D;c.length-=D;do K[q++]=$[Q++];while(--D);0===c.length&&(c.mode=21);break;case 26:if(0===p)break a;K[q++]=c.length;p--;c.mode=21;break;case 27:if(c.wrap){for(;32>s;){if(0===l)break a;l--;m|=r[H++]<s;){if(0===l)break a;l--;m+=r[H++]<c.mode&&(27>c.mode||4!==d))r=a.output,H=a.next_out,q=P-a.avail_out,p=a.state,null===p.window&&(p.wsize=1<=p.wsize?(b.arraySet(p.window,r,H-p.wsize,p.wsize,0),p.wnext=0,p.whave=p.wsize):(l=p.wsize-p.wnext,l>q&&(l=q),b.arraySet(p.window,r,H-q,l,p.wnext),(q-=l)?(b.arraySet(p.window,r,H-q,q,0),p.wnext=q,p.whave=p.wsize):(p.wnext+=l,p.wnext===p.wsize&&(p.wnext=0),p.whave=s;s++)U[s]=0;for(x=0;xB&&(I=B);if(0===B)return g[u++]=20971520,g[u++]=20971520,y.bits=1,0;for(w=1;w=s;s++)if(J<<=1,J-=U[s],0>J)return-1;if(0s;s++)C[s+1]=C[s]+U[s];for(x=0;xG?(Q=aa[P+t[x]],$=Z[T+t[x]]):(Q=96,$=0);J=1<>F)+H]=D<<24|Q<<16|$|0;while(0!==H);for(J=1<>=1;0!==J?(K&=J-1,K+=J):K=0;x++;if(0===--U[s]){if(s===B)break;s=b[c+t[x]]}if(s>I&&(K&d)!==z){0===F&&(F=I);v+=w;C=s-F;for(J=1<=J)break;C++;J<<=1}N+=1<";return runtime.parseXML(d)}; -core.UnitTest.createOdtDocument=function(f,k){return core.UnitTest.createXmlDocument("office:document",f,k)}; -core.UnitTestLogger=function(){var f=[],k=0,a=0,d="",c="";this.startTest=function(h,q){f=[];k=0;d=h;c=q;a=Date.now()};this.endTest=function(){var h=Date.now();return{description:c,suite:[d,c],success:0===k,log:f,time:h-a}};this.debug=function(a){f.push({category:"debug",message:a})};this.fail=function(a){k+=1;f.push({category:"fail",message:a})};this.pass=function(a){f.push({category:"pass",message:a})}}; -core.UnitTestRunner=function(f,k){function a(b){l+=1;e?k.debug(b):k.fail(b)}function d(b,c){var e;try{if(b.length!==c.length)return a("array of length "+b.length+" should be "+c.length+" long"),!1;for(e=0;e1/b)return"-0";if("object"===typeof b)try{return JSON.stringify(b)}catch(a){}return String(b)}function m(b,c,e,d){"string"===typeof c&&"string"===typeof e||k.debug("WARN: shouldBe() expects string arguments");var f,h;try{h=eval(c)}catch(m){f=m}b=eval(e);f?a(c+" should be "+b+". Threw exception "+f):q(h,b,d)?k.pass(c+" is "+e):String(typeof h)===String(typeof b)? -a(c+" should be "+p(b)+". Was "+p(h)+"."):a(c+" should be "+b+" (of type "+typeof b+"). Was "+h+" (of type "+typeof h+").")}var l=0,r,b,e=!1;this.resourcePrefix=function(){return f};this.beginExpectFail=function(){r=l;e=!0};this.endExpectFail=function(){var b=r===l;e=!1;l=r;b&&(l+=1,k.fail("Expected at least one failed test, but none registered."))};b=function(b,c){var e=Object.keys(b),f=Object.keys(c);e.sort();f.sort();return d(e,f)&&Object.keys(b).every(function(e){var d=b[e],f=c[e];return q(d, -f)?!0:(a(d+" should be "+f+" for key "+e),!1)})};this.areNodesEqual=h;this.shouldBeNull=function(b,a){m(b,a,"null")};this.shouldBeNonNull=function(b,c){var e,d;try{d=eval(c)}catch(f){e=f}e?a(c+" should be non-null. Threw exception "+e):null!==d?k.pass(c+" is non-null."):a(c+" should be non-null. Was "+d)};this.shouldBe=m;this.testFailed=a;this.countFailedTests=function(){return l};this.name=function(b){var a,c,e=[],d=b.length;e.length=d;for(a=0;a"+a+""}function k(c){a.reporter&&a.reporter(c)}var a=this,d=0,c=new core.UnitTestLogger,h={},q="BrowserRuntime"===runtime.type();this.resourcePrefix="";this.reporter=function(a){var c,d;q?runtime.log("Running "+f(a.description,'runTest("'+a.suite[0]+'","'+a.description+'")')+""):runtime.log("Running "+a.description);if(!a.success)for(c=0;cRunning "+f(b,'runSuite("'+b+'");')+": "+n.description()+""):runtime.log("Running "+b+": "+n.description);y=n.tests();for(u=0;u>>18],m+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[e>>>12&63],m+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[e>>>6&63],m+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[e& +63];a===s+1?(e=d[a]<<4,m+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[e>>>6],m+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[e&63],m+="=="):a===s&&(e=d[a]<<10|d[a+1]<<2,m+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[e>>>12],m+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[e>>>6&63],m+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[e&63],m+="=");return m}function a(e){e=e.replace(/[^A-Za-z0-9+\/]+/g, +"");var d=e.length,a=new Uint8Array(new ArrayBuffer(3*d)),s=e.length%4,c=0,b,H;for(b=0;b>16,a[c+1]=H>>8&255,a[c+2]=H&255,c+=3;d=3*d-[0,0,2,1][s];return a.subarray(0,d)}function c(e){var d,m,a=e.length,s=0,c=new Uint8Array(new ArrayBuffer(3*a));for(d=0;dm?c[s++]=m:(2048>m?c[s++]=192|m>>>6:(c[s++]=224|m>>>12&15,c[s++]=128|m>>>6&63),c[s++]=128|m&63);return c.subarray(0, +s)}function b(e){var d,m,a,s,c=e.length,H=new Uint8Array(new ArrayBuffer(c)),b=0;for(d=0;dm?H[b++]=m:(d+=1,a=e[d],224>m?H[b++]=(m&31)<<6|a&63:(d+=1,s=e[d],H[b++]=(m&15)<<12|(a&63)<<6|s&63));return H.subarray(0,b)}function k(d){return l(f(d))}function q(d){return String.fromCharCode.apply(String,a(d))}function p(d){return b(f(d))}function n(d){d=b(d);for(var e="",m=0;me?H+=String.fromCharCode(e):(c+=1,a=d.charCodeAt(c)&255,224>e?H+=String.fromCharCode((e&31)<<6|a&63):(c+=1,s=d.charCodeAt(c)&255,H+=String.fromCharCode((e&15)<<12|(a&63)<<6|s&63)));return H}function h(d,e){function m(){var c=s+1E5;c>d.length&&(c=d.length);a+=g(d,s,c);s=c;c=s===d.length;e(a,c)&&!c&&runtime.setTimeout(m,0)}var a="",s=0;1E5>d.length?e(g(d,0,d.length),!0):("string"!==typeof d&&(d=d.slice()),m())}function d(d){return c(f(d))}function e(d){return String.fromCharCode.apply(String, +c(d))}function s(d){return String.fromCharCode.apply(String,c(f(d)))}var m=function(d){var e={},m,a;m=0;for(a=d.length;mb-c&&(b=Math.max(2*b,c+a),a=new Uint8Array(new ArrayBuffer(b)),a.set(k),k=a)}var a=this,c=0,b=1024,k=new Uint8Array(new ArrayBuffer(b));this.appendByteArrayWriter=function(c){a.appendByteArray(c.getByteArray())};this.appendByteArray=function(a){var b=a.length;l(b);k.set(a,c);c+=b};this.appendArray=function(a){var b=a.length;l(b);k.set(a,c);c+=b};this.appendUInt16LE=function(c){a.appendArray([c&255,c>>8&255])};this.appendUInt32LE=function(c){a.appendArray([c& +255,c>>8&255,c>>16&255,c>>24&255])};this.appendString=function(c){a.appendByteArray(runtime.byteArrayFromString(c,f))};this.getLength=function(){return c};this.getByteArray=function(){var a=new Uint8Array(new ArrayBuffer(c));a.set(k.subarray(0,c));return a}};core.CSSUnits=function(){var f=this,l={"in":1,cm:2.54,mm:25.4,pt:72,pc:12,px:96};this.convert=function(a,c,b){return a*l[b]/l[c]};this.convertMeasure=function(a,c){var b,k;a&&c&&(b=parseFloat(a),k=a.replace(b.toString(),""),b=f.convert(b,k,c));return b};this.getUnits=function(a){return a.substr(a.length-2,a.length)}};(function(){function f(){var c,b,k,f,p,l,g,h,d;void 0===a&&(b=(c=runtime.getWindow())&&c.document,l=b.documentElement,g=b.body,a={rangeBCRIgnoresElementBCR:!1,unscaledRangeClientRects:!1,elementBCRIgnoresBodyScroll:!1},b&&(f=b.createElement("div"),f.style.position="absolute",f.style.left="-99999px",f.style.transform="scale(2)",f.style["-webkit-transform"]="scale(2)",p=b.createElement("div"),f.appendChild(p),g.appendChild(f),c=b.createRange(),c.selectNode(p),a.rangeBCRIgnoresElementBCR=0===c.getClientRects().length, +p.appendChild(b.createTextNode("Rect transform test")),b=p.getBoundingClientRect(),k=c.getBoundingClientRect(),a.unscaledRangeClientRects=2=d.compareBoundaryPoints(Range.START_TO_START,e)&&0<=d.compareBoundaryPoints(Range.END_TO_END,e)}function k(d,e){return 0>=d.compareBoundaryPoints(Range.END_TO_START,e)&&0<=d.compareBoundaryPoints(Range.START_TO_END,e)}function q(d,e){var a=null;d.nodeType===Node.TEXT_NODE&&(0===d.length?(d.parentNode.removeChild(d),e.nodeType===Node.TEXT_NODE&&(a=e)):(e.nodeType===Node.TEXT_NODE&&(d.appendData(e.data),e.parentNode.removeChild(e)),a=d));return a} +function p(d){for(var e=d.parentNode;d.firstChild;)e.insertBefore(d.firstChild,d);e.removeChild(d);return e}function n(d,e){var a=d.parentNode,c=d.firstChild,b=e(d),h;if(b===NodeFilter.FILTER_SKIP)return a;for(;c;)h=c.nextSibling,n(c,e),c=h;a&&b===NodeFilter.FILTER_REJECT&&p(d);return a}function g(d,e){return d===e||Boolean(d.compareDocumentPosition(e)&Node.DOCUMENT_POSITION_CONTAINED_BY)}function h(d,e){return f().unscaledRangeClientRects?d:d/e}function d(e,m,a){Object.keys(m).forEach(function(c){var b= +c.split(":"),h=b[1],g=a(b[0]),b=m[c],k=typeof b;"object"===k?Object.keys(b).length&&(c=g?e.getElementsByTagNameNS(g,h)[0]||e.ownerDocument.createElementNS(g,c):e.getElementsByTagName(h)[0]||e.ownerDocument.createElement(c),e.appendChild(c),d(c,b,a)):g&&(runtime.assert("number"===k||"string"===k,"attempting to map unsupported type '"+k+"' (key: "+c+")"),e.setAttributeNS(g,c,String(b)))})}var e=null;this.splitBoundaries=function(d){var e,b=[],h,g,k;if(d.startContainer.nodeType===Node.TEXT_NODE||d.endContainer.nodeType=== +Node.TEXT_NODE){h=d.endContainer;g=d.endContainer.nodeType!==Node.TEXT_NODE?d.endOffset===d.endContainer.childNodes.length:!1;k=d.endOffset;e=d.endContainer;if(kf))throw runtime.log("alert","watchdog timeout"),"timeout!";if(0l))throw runtime.log("alert","watchdog loop overflow"),"loop overflow";}};core.NodeFilterChain=function(f){var l=NodeFilter.FILTER_REJECT,a=NodeFilter.FILTER_ACCEPT;this.acceptNode=function(c){var b;for(b=0;b "+e.length),runtime.assert(0<=a,"Error in setPosition: "+a+" < 0"),a===e.length&&(h.nextSibling()?d=0:h.parentNode()?d=1:runtime.assert(!1,"Error in setUnfilteredPosition: position not valid."))):ac.windowBits&&(c.windowBits=-c.windowBits,0===c.windowBits&&(c.windowBits=-15));!(0<=c.windowBits&&16>c.windowBits)||a&&a.windowBits||(c.windowBits+=32);15c.windowBits&&0===(c.windowBits&15)&&(c.windowBits|=15);this.err=0;this.msg="";this.ended=!1;this.chunks= +[];this.strm=new d;this.strm.avail_out=0;a=f.inflateInit2(this.strm,c.windowBits);if(a!==g.Z_OK)throw Error(h[a]);this.header=new e;f.inflateGetHeader(this.strm,this.header)};s.prototype.push=function(d,e){var a=this.strm,c=this.options.chunkSize,b,h,s,k,A;if(this.ended)return!1;h=e===~~e?e:!0===e?g.Z_FINISH:g.Z_NO_FLUSH;a.input="string"===typeof d?n.binstring2buf(d):d;a.next_in=0;a.avail_in=a.input.length;do{0===a.avail_out&&(a.output=new p.Buf8(c),a.next_out=0,a.avail_out=c);b=f.inflate(a,g.Z_NO_FLUSH); +if(b!==g.Z_STREAM_END&&b!==g.Z_OK)return this.onEnd(b),this.ended=!0,!1;if(a.next_out&&(0===a.avail_out||b===g.Z_STREAM_END||0===a.avail_in&&h===g.Z_FINISH))if("string"===this.options.to)s=n.utf8border(a.output,a.next_out),k=a.next_out-s,A=n.buf2string(a.output,s),a.next_out=k,a.avail_out=c-k,k&&p.arraySet(a.output,a.output,s,k,0),this.onData(A);else this.onData(p.shrinkBuf(a.output,a.next_out))}while((0a&&(d.subarray&&n||!d.subarray&&p))return String.fromCharCode.apply(null,f.shrinkBuf(d,a));for(var c="",b=0;ba;a++)d[a]=252<=a?6:248<= +a?5:240<=a?4:224<=a?3:192<=a?2:1;d[254]=d[254]=1;b.string2buf=function(d){var a,c,b,h,k,g=d.length,p=0;for(h=0;hc?1:2048>c?2:65536>c?3:4;a=new f.Buf8(p);for(h=k=0;kc?a[k++]=c:(2048>c?a[k++]=192|c>>>6:(65536>c?a[k++]=224|c>>>12:(a[k++]= +240|c>>>18,a[k++]=128|c>>>12&63),a[k++]=128|c>>>6&63),a[k++]=128|c&63);return a};b.buf2binstring=function(d){return k(d,d.length)};b.binstring2buf=function(d){for(var a=new f.Buf8(d.length),c=0,b=a.length;cg)q[h++]=g;else if(f=d[g],4g?q[h++]=g:(g-=65536,q[h++]= +55296|g>>10&1023,q[h++]=56320|g&1023)}return k(q,h)};b.utf8border=function(a,c){var b;c=c||a.length;c>a.length&&(c=a.length);for(b=c-1;0<=b&&128===(a[b]&192);)b--;return 0>b||0===b?c:b+d[a[b]]>c?b:c}},{"./common":2}],4:[function(a,c,b){c.exports=function(a,c,b,f){var g=a&65535|0;a=a>>>16&65535|0;for(var h=0;0!==b;){h=2E3b;b++){a=b;for(var k=0;8>k;k++)a=a&1?3988292384^a>>>1:a>>>1;c[b]=a}return c}();c.exports=function(a,c,b,g){b=g+b;for(a^= +-1;g>>8^k[(a^c[g])&255];return a^-1}},{}],7:[function(a,c,b){c.exports=function(){this.os=this.xflags=this.time=this.text=0;this.extra=null;this.extra_len=0;this.comment=this.name="";this.hcrc=0;this.done=!1}},{}],8:[function(a,c,b){c.exports=function(a,c){var b,f,g,h,d,e,s,m,x,t,y,v,r,w,u,A,F,B,E,H,I,Q,N,z;b=a.state;f=a.next_in;N=a.input;g=f+(a.avail_in-5);h=a.next_out;z=a.output;d=h-(c-a.avail_out);e=h+(a.avail_out-257);s=b.dmax;m=b.wsize;x=b.whave;t=b.wnext;y=b.window;v=b.hold;r=b.bits; +w=b.lencode;u=b.distcode;A=(1<r&&(v+=N[f++]<>>24;v>>>=E;r-=E;E=B>>>16&255;if(0===E)z[h++]=B&65535;else if(E&16){H=B&65535;if(E&=15)r>>=E,r-=E;15>r&&(v+=N[f++]<>>24;v>>>=E;r-=E;E=B>>>16&255;if(E&16){B&=65535;E&=15;rs){a.msg="invalid distance too far back"; +b.mode=30;break a}v>>>=E;r-=E;E=h-d;if(B>E){E=B-E;if(E>x&&b.sane){a.msg="invalid distance too far back";b.mode=30;break a}I=0;Q=y;if(0===t){if(I+=m-E,E>3;f-=H;r-=H<<3;a.next_in=f;a.next_out=h;a.avail_in=f>>24&255)+(d>>>8&65280)+((d&65280)<<8)+((d&255)<<24)}function f(){this.mode=0;this.last=!1;this.wrap=0;this.havedict=!1;this.total=this.check=this.dmax=this.flags=0;this.head=null;this.wnext=this.whave=this.wsize=this.wbits=0;this.window=null;this.extra=this.offset=this.length=this.bits=this.hold=0;this.distcode=this.lencode=null;this.have=this.ndist=this.nlen=this.ncode=this.distbits=this.lenbits=0;this.next=null;this.lens=new d.Buf16(320);this.work= +new d.Buf16(288);this.distdyn=this.lendyn=null;this.was=this.back=this.sane=0}function p(a){var e;if(!a||!a.state)return y;e=a.state;a.total_in=a.total_out=e.total=0;a.msg="";e.wrap&&(a.adler=e.wrap&1);e.mode=v;e.last=0;e.havedict=0;e.dmax=32768;e.head=null;e.hold=0;e.bits=0;e.lencode=e.lendyn=new d.Buf32(r);e.distcode=e.distdyn=new d.Buf32(w);e.sane=1;e.back=-1;return t}function n(d){var a;if(!d||!d.state)return y;a=d.state;a.wsize=0;a.whave=0;a.wnext=0;return p(d)}function g(d,a){var e,c;if(!d|| +!d.state)return y;c=d.state;0>a?(e=0,a=-a):(e=(a>>4)+1,48>a&&(a&=15));if(a&&(8>a||15r;){if(0===p)break a;p--;n+=h[g++]<>>8&255;b.check=s(b.check,W,2,0);r=n=0;b.mode=2;break}b.flags=0;b.head&&(b.head.done=!1);if(!(b.wrap&1)||(((n&255)<<8)+(n>>8))%31){a.msg="incorrect header check";b.mode=30;break}if(8!==(n&15)){a.msg="unknown compression method";b.mode=30;break}n>>>=4;r-=4;O=(n&15)+8;if(0===b.wbits)b.wbits=O;else if(O>b.wbits){a.msg="invalid window size";b.mode=30;break}b.dmax=1<r;){if(0===p)break a;p--;n+=h[g++]<>8&1);b.flags&512&&(W[0]=n&255,W[1]=n>>>8&255,b.check=s(b.check,W,2,0));r=n=0;b.mode=3;case 3:for(;32>r;){if(0===p)break a;p--;n+=h[g++]<>>8&255,W[2]=n>>>16&255,W[3]=n>>>24&255,b.check=s(b.check,W,4,0));r=n=0;b.mode=4;case 4:for(;16>r;){if(0===p)break a;p--;n+=h[g++]<>8);b.flags&512&&(W[0]=n&255,W[1]=n>>>8&255,b.check=s(b.check,W,2,0));r=n=0;b.mode=5;case 5:if(b.flags&1024){for(;16>r;){if(0===p)break a;p--;n+=h[g++]<>>8&255,b.check=s(b.check,W,2,0));r=n=0}else b.head&&(b.head.extra=null);b.mode=6;case 6:if(b.flags&1024&&(D=b.length,D>p&&(D=p),D&&(b.head&&(O=b.head.extra_len-b.length,b.head.extra||(b.head.extra=Array(b.head.extra_len)),d.arraySet(b.head.extra, +h,g,D,O)),b.flags&512&&(b.check=s(b.check,h,D,g)),p-=D,g+=D,b.length-=D),b.length))break a;b.length=0;b.mode=7;case 7:if(b.flags&2048){if(0===p)break a;D=0;do O=h[g+D++],b.head&&O&&65536>b.length&&(b.head.name+=String.fromCharCode(O));while(O&&Db.length&&(b.head.comment+=String.fromCharCode(O));while(O&&D< +p);b.flags&512&&(b.check=s(b.check,h,D,g));p-=D;g+=D;if(O)break a}else b.head&&(b.head.comment=null);b.mode=9;case 9:if(b.flags&512){for(;16>r;){if(0===p)break a;p--;n+=h[g++]<>9&1,b.head.done=!0);a.adler=b.check=0;b.mode=12;break;case 10:for(;32>r;){if(0===p)break a;p--;n+=h[g++]<>>=r&7;r-=r&7;b.mode=27;break}for(;3>r;){if(0===p)break a;p--;n+=h[g++]<>>=1;r-=1;switch(n&3){case 0:b.mode=14;break;case 1:D=b;if(u){O=void 0;A=new d.Buf32(512);F=new d.Buf32(32);for(O=0;144>O;)D.lens[O++]=8;for(;256>O;)D.lens[O++]=9;for(;280>O;)D.lens[O++]=7;for(;288>O;)D.lens[O++]=8;x(1,D.lens,0,288,A,0,D.work,{bits:9});for(O=0;32>O;)D.lens[O++]=5;x(2,D.lens, +0,32,F,0,D.work,{bits:5});u=!1}D.lencode=A;D.lenbits=9;D.distcode=F;D.distbits=5;b.mode=20;if(6===c){n>>>=2;r-=2;break a}break;case 2:b.mode=17;break;case 3:a.msg="invalid block type",b.mode=30}n>>>=2;r-=2;break;case 14:n>>>=r&7;for(r-=r&7;32>r;){if(0===p)break a;p--;n+=h[g++]<>>16^65535)){a.msg="invalid stored block lengths";b.mode=30;break}b.length=n&65535;r=n=0;b.mode=15;if(6===c)break a;case 15:b.mode=16;case 16:if(D=b.length){D>p&&(D=p);D>q&&(D=q);if(0===D)break a;d.arraySet(f, +h,g,D,z);p-=D;g+=D;q-=D;z+=D;b.length-=D;break}b.mode=12;break;case 17:for(;14>r;){if(0===p)break a;p--;n+=h[g++]<>>=5;r-=5;b.ndist=(n&31)+1;n>>>=5;r-=5;b.ncode=(n&15)+4;n>>>=4;r-=4;if(286r;){if(0===p)break a;p--;n+=h[g++]<>>=3;r-=3}for(;19>b.have;)b.lens[P[b.have++]]=0;b.lencode=b.lendyn;b.lenbits=7; +D={bits:b.lenbits};U=x(0,b.lens,0,19,b.lencode,0,b.work,D);b.lenbits=D.bits;if(U){a.msg="invalid code lengths set";b.mode=30;break}b.have=0;b.mode=19;case 19:for(;b.have>>24;V=D>>>16&255;$=D&65535;if(C<=r)break;if(0===p)break a;p--;n+=h[g++]<$)n>>>=C,r-=C,b.lens[b.have++]=$;else{if(16===$){for(D=C+2;r>>=C;r-=C;if(0===b.have){a.msg="invalid bit length repeat";b.mode=30;break}O= +b.lens[b.have-1];D=3+(n&3);n>>>=2;r-=2}else if(17===$){for(D=C+3;r>>=C;r-=C;O=0;D=3+(n&7);n>>>=3;r-=3}else{for(D=C+7;r>>=C;r-=C;O=0;D=11+(n&127);n>>>=7;r-=7}if(b.have+D>b.nlen+b.ndist){a.msg="invalid bit length repeat";b.mode=30;break}for(;D--;)b.lens[b.have++]=O}}if(30===b.mode)break;if(0===b.lens[256]){a.msg="invalid code -- missing end-of-block";b.mode=30;break}b.lenbits=9;D={bits:b.lenbits};U=x(1,b.lens, +0,b.nlen,b.lencode,0,b.work,D);b.lenbits=D.bits;if(U){a.msg="invalid literal/lengths set";b.mode=30;break}b.distbits=6;b.distcode=b.distdyn;D={bits:b.distbits};U=x(2,b.lens,b.nlen,b.ndist,b.distcode,0,b.work,D);b.distbits=D.bits;if(U){a.msg="invalid distances set";b.mode=30;break}b.mode=20;if(6===c)break a;case 20:b.mode=21;case 21:if(6<=p&&258<=q){a.next_out=z;a.avail_out=q;a.next_in=g;a.avail_in=p;b.hold=n;b.bits=r;m(a,T);z=a.next_out;f=a.output;q=a.avail_out;g=a.next_in;h=a.input;p=a.avail_in; +n=b.hold;r=b.bits;12===b.mode&&(b.back=-1);break}for(b.back=0;;){D=b.lencode[n&(1<>>24;V=D>>>16&255;$=D&65535;if(C<=r)break;if(0===p)break a;p--;n+=h[g++]<>O)];C=D>>>24;V=D>>>16&255;$=D&65535;if(O+C<=r)break;if(0===p)break a;p--;n+=h[g++]<>>=O;r-=O;b.back+=O}n>>>=C;r-=C;b.back+=C;b.length=$;if(0===V){b.mode=26;break}if(V&32){b.back=-1;b.mode=12;break}if(V&64){a.msg="invalid literal/length code"; +b.mode=30;break}b.extra=V&15;b.mode=22;case 22:if(b.extra){for(D=b.extra;r>>=b.extra;r-=b.extra;b.back+=b.extra}b.was=b.length;b.mode=23;case 23:for(;;){D=b.distcode[n&(1<>>24;V=D>>>16&255;$=D&65535;if(C<=r)break;if(0===p)break a;p--;n+=h[g++]<>O)];C=D>>>24;V=D>>>16&255;$=D&65535;if(O+C<=r)break;if(0===p)break a;p--;n+=h[g++]<>>=O;r-=O;b.back+=O}n>>>=C;r-=C;b.back+=C;if(V&64){a.msg="invalid distance code";b.mode=30;break}b.offset=$;b.extra=V&15;b.mode=24;case 24:if(b.extra){for(D=b.extra;r>>=b.extra;r-=b.extra;b.back+=b.extra}if(b.offset>b.dmax){a.msg="invalid distance too far back";b.mode=30;break}b.mode=25;case 25:if(0===q)break a;D=T-q;if(b.offset>D){D=b.offset-D;if(D>b.whave&&b.sane){a.msg="invalid distance too far back";b.mode=30;break}D> +b.wnext?(D-=b.wnext,O=b.wsize-D):O=b.wnext-D;D>b.length&&(D=b.length);Z=b.window}else Z=f,O=z-b.offset,D=b.length;D>q&&(D=q);q-=D;b.length-=D;do f[z++]=Z[O++];while(--D);0===b.length&&(b.mode=21);break;case 26:if(0===q)break a;f[z++]=b.length;q--;b.mode=21;break;case 27:if(b.wrap){for(;32>r;){if(0===p)break a;p--;n|=h[g++]<r;){if(0===p)break a;p--;n+=h[g++]<b.mode&&(27>b.mode||4!==c))h=a.output,g=a.next_out,z=T-a.avail_out,q=a.state,null===q.window&&(q.wsize=1<=q.wsize?(d.arraySet(q.window,h,g-q.wsize,q.wsize,0),q.wnext=0,q.whave=q.wsize):(p=q.wsize-q.wnext,p>z&&(p=z),d.arraySet(q.window,h,g-z,p,q.wnext),(z-=p)?(d.arraySet(q.window,h,g-z,z,0),q.wnext=z,q.whave=q.wsize):(q.wnext+=p,q.wnext===q.wsize&&(q.wnext=0),q.whave=r;r++)G[r]=0;for(w=0;wA&&(F=A);if(0===A)return m[x++]=20971520,m[x++]=20971520,y.bits=1,0;for(u=1;u=r;r++)if(H<<=1,H-=G[r],0>H)return-1;if(0r;r++)B[r+1]=B[r]+G[r];for(w=0;wJ?(O=ba[T+t[w]],Z=Y[R+t[w]]):(O=96,Z=0);H=1<>E)+N]=D<<24|O<<16|Z|0;while(0!==N);for(H=1<>=1;0!==H?(Q&=H-1,Q+=H):Q=0;w++;if(0===--G[r]){if(r===A)break;r=d[b+t[w]]}if(r>F&&(Q&c)!==z){0===E&&(E=F);v+=u;B=r-E;for(H=1<=H)break;B++;H<<=1}I+=1<>>8^d;return c^-1}function c(b){return new Date((b>>25&127)+1980,(b>>21&15)-1,b>>16&31,b>>11&15, -b>>5&63,(b&31)<<1)}function h(b){var a=b.getFullYear();return 1980>a?0:a-1980<<25|b.getMonth()+1<<21|b.getDate()<<16|b.getHours()<<11|b.getMinutes()<<5|b.getSeconds()>>1}function q(b,e){var g,d,n,f,h,m,l,r=this;this.load=function(c){if(null!==r.data)c(null,r.data);else{var e=h+34+d+n+256;e+l>t&&(e=t-l);a(l,e,function(a,e){if(a||null===e)c(a,e);else a:{var g=e,d=new core.ByteArray(g),n=d.readUInt32LE(),l;if(67324752!==n)c("File entry signature is wrong."+n.toString()+" "+g.length.toString(),null); -else{d.pos+=22;n=d.readUInt16LE();l=d.readUInt16LE();d.pos+=n+l;if(f){g=g.subarray(d.pos,d.pos+h);if(h!==g.length){c("The amount of compressed bytes read was "+g.length.toString()+" instead of "+h.toString()+" for "+r.filename+" in "+b+".",null);break a}g=v(g,m)}else g=g.subarray(d.pos,d.pos+m);m!==g.length?c("The amount of bytes read was "+g.length.toString()+" instead of "+m.toString()+" for "+r.filename+" in "+b+".",null):(r.data=g,c(null,g))}}})}};this.set=function(b,a,c,e){r.filename=b;r.data= -a;r.compressed=c;r.date=e};this.error=null;e&&(g=e.readUInt32LE(),33639248!==g?this.error="Central directory entry has wrong signature at position "+(e.pos-4).toString()+' for file "'+b+'": '+e.data.length.toString():(e.pos+=6,f=e.readUInt16LE(),this.date=c(e.readUInt32LE()),e.readUInt32LE(),h=e.readUInt32LE(),m=e.readUInt32LE(),d=e.readUInt16LE(),n=e.readUInt16LE(),g=e.readUInt16LE(),e.pos+=8,l=e.readUInt32LE(),this.filename=runtime.byteArrayToString(e.data.subarray(e.pos,e.pos+d),"utf8"),this.data= -null,e.pos+=d+n+g))}function p(b,c){if(22!==b.length)c("Central directory length should be 22.",s);else{var e=new core.ByteArray(b),d;d=e.readUInt32LE();101010256!==d?c("Central directory signature is wrong: "+d.toString(),s):(d=e.readUInt16LE(),0!==d?c("Zip files with non-zero disk numbers are not supported.",s):(d=e.readUInt16LE(),0!==d?c("Zip files with non-zero disk numbers are not supported.",s):(d=e.readUInt16LE(),y=e.readUInt16LE(),d!==y?c("Number of entries is inconsistent.",s):(d=e.readUInt32LE(), -e=e.readUInt16LE(),e=t-22-d,a(e,t-e,function(b,a){if(b||null===a)c(b,s);else a:{var e=new core.ByteArray(a),d,n;g=[];for(d=0;d>>8^h;return b^-1}function b(a){return new Date((a>>25&127)+1980,(a>>21&15)-1,a>>16&31,a>>11&15, +a>>5&63,(a&31)<<1)}function k(a){var d=a.getFullYear();return 1980>d?0:d-1980<<25|a.getMonth()+1<<21|a.getDate()<<16|a.getHours()<<11|a.getMinutes()<<5|a.getSeconds()>>1}function q(d,e){var c,h,m,g,s,f,k,p=this;this.load=function(b){if(null!==p.data)b(null,p.data);else{var e=s+34+h+m+256;e+k>t&&(e=t-k);a(k,e,function(a,e){if(a||null===e)b(a,e);else a:{var c=e,h=new core.ByteArray(c),m=h.readUInt32LE(),k;if(67324752!==m)b("File entry signature is wrong."+m.toString()+" "+c.length.toString(),null); +else{h.pos+=22;m=h.readUInt16LE();k=h.readUInt16LE();h.pos+=m+k;if(g){c=c.subarray(h.pos,h.pos+s);if(s!==c.length){b("The amount of compressed bytes read was "+c.length.toString()+" instead of "+s.toString()+" for "+p.filename+" in "+d+".",null);break a}c=v(c,f)}else c=c.subarray(h.pos,h.pos+f);f!==c.length?b("The amount of bytes read was "+c.length.toString()+" instead of "+f.toString()+" for "+p.filename+" in "+d+".",null):(p.data=c,b(null,c))}}})}};this.set=function(a,d,b,e){p.filename=a;p.data= +d;p.compressed=b;p.date=e};this.error=null;e&&(c=e.readUInt32LE(),33639248!==c?this.error="Central directory entry has wrong signature at position "+(e.pos-4).toString()+' for file "'+d+'": '+e.data.length.toString():(e.pos+=6,g=e.readUInt16LE(),this.date=b(e.readUInt32LE()),e.readUInt32LE(),s=e.readUInt32LE(),f=e.readUInt32LE(),h=e.readUInt16LE(),m=e.readUInt16LE(),c=e.readUInt16LE(),e.pos+=8,k=e.readUInt32LE(),this.filename=runtime.byteArrayToString(e.data.subarray(e.pos,e.pos+h),"utf8"),this.data= +null,e.pos+=h+m+c))}function p(d,b){if(22!==d.length)b("Central directory length should be 22.",r);else{var e=new core.ByteArray(d),c;c=e.readUInt32LE();101010256!==c?b("Central directory signature is wrong: "+c.toString(),r):(c=e.readUInt16LE(),0!==c?b("Zip files with non-zero disk numbers are not supported.",r):(c=e.readUInt16LE(),0!==c?b("Zip files with non-zero disk numbers are not supported.",r):(c=e.readUInt16LE(),y=e.readUInt16LE(),c!==y?b("Number of entries is inconsistent.",r):(c=e.readUInt32LE(), +e=e.readUInt16LE(),e=t-22-c,a(e,t-e,function(a,d){if(a||null===d)b(a,r);else a:{var e=new core.ByteArray(d),c,h;m=[];for(c=0;cb.value||"%"===b.unit)?null:b}function F(b){return(b=I(b))&&"%"!==b.unit?null:b}function J(b){switch(b.namespaceURI){case odf.Namespaces.drawns:case odf.Namespaces.svgns:case odf.Namespaces.dr3dns:return!1;case odf.Namespaces.textns:switch(b.localName){case "note-body":case "ruby-text":return!1}break;case odf.Namespaces.officens:switch(b.localName){case "annotation":case "binary-data":case "event-listeners":return!1}break;default:switch(b.localName){case "cursor":case "editinfo":return!1}}return!0} -function N(b,a){for(;0=a.value||"%"===a.unit)?null:a;return a||F(b)};this.parseFoLineHeight= -function(b){return C(b)||F(b)};this.isTextContentContainingNode=J;this.getTextNodes=function(b,a){var c;c=U.getNodesInRange(b,function(b){var a=NodeFilter.FILTER_REJECT;b.nodeType===Node.TEXT_NODE?Boolean(h(b)&&(!p(b.textContent)||B(b,0)))&&(a=NodeFilter.FILTER_ACCEPT):J(b)&&(a=NodeFilter.FILTER_SKIP);return a},NodeFilter.SHOW_ELEMENT|NodeFilter.SHOW_TEXT);a||N(b,c);return c};this.getTextElements=K;this.getParagraphElements=function(b){var a;a=U.getNodesInRange(b,function(b){var a=NodeFilter.FILTER_REJECT; -if(c(b))a=NodeFilter.FILTER_ACCEPT;else if(J(b)||m(b))a=NodeFilter.FILTER_SKIP;return a},NodeFilter.SHOW_ELEMENT);H(b.startContainer,a,c);return a};this.getImageElements=function(b){var a;a=U.getNodesInRange(b,function(b){var a=NodeFilter.FILTER_SKIP;f(b)&&(a=NodeFilter.FILTER_ACCEPT);return a},NodeFilter.SHOW_ELEMENT);H(b.startContainer,a,f);return a};this.getHyperlinkElements=function(b){var a=[],e=b.cloneRange();b.collapsed&&b.endContainer.nodeType===Node.ELEMENT_NODE&&(b=z(b.endContainer,b.endOffset), -b.nodeType===Node.TEXT_NODE&&e.setEnd(b,1));K(e,!0,!1).forEach(function(b){for(b=b.parentNode;!c(b);){if(d(b)&&-1===a.indexOf(b)){a.push(b);break}b=b.parentNode}});e.detach();return a};this.getNormalizedFontFamilyName=function(b){/^(["'])(?:.|[\n\r])*?\1$/.test(b)||(b=b.replace(/^[ \t\r\n\f]*((?:.|[\n\r])*?)[ \t\r\n\f]*$/,"$1"),/[ \t\r\n\f]/.test(b)&&(b="'"+b.replace(/[ \t\r\n\f]+/g," ")+"'"));return b}};odf.OdfUtils=new odf.OdfUtilsImpl;gui.OdfTextBodyNodeFilter=function(){var f=odf.OdfUtils,k=Node.TEXT_NODE,a=NodeFilter.FILTER_REJECT,d=NodeFilter.FILTER_ACCEPT,c=odf.Namespaces.textns;this.acceptNode=function(h){if(h.nodeType===k){if(!f.isGroupingElement(h.parentNode))return a}else if(h.namespaceURI===c&&"tracked-changes"===h.localName)return a;return d}};xmldom.LSSerializerFilter=function(){};xmldom.LSSerializerFilter.prototype.acceptNode=function(f){};odf.OdfNodeFilter=function(){this.acceptNode=function(f){return"http://www.w3.org/1999/xhtml"===f.namespaceURI?NodeFilter.FILTER_SKIP:f.namespaceURI&&f.namespaceURI.match(/^urn:webodf:/)?NodeFilter.FILTER_REJECT:NodeFilter.FILTER_ACCEPT}};xmldom.XPathIterator=function(){};xmldom.XPathIterator.prototype.next=function(){};xmldom.XPathIterator.prototype.reset=function(){}; -function createXPathSingleton(){function f(a,b,c){return-1!==a&&(a=f&&c.push(k(a.substring(b,d)))):"["===a[d]&&(0>=f&&(b=d+1),f+=1),d+=1;return d};m=function(a,b,e){var f,g,h,m;for(f=0;fa.value||"%"===a.unit)?null:a}function E(a){return(a=F(a))&&"%"!==a.unit?null:a}function H(a){switch(a.namespaceURI){case odf.Namespaces.drawns:case odf.Namespaces.svgns:case odf.Namespaces.dr3dns:return!1;case odf.Namespaces.textns:switch(a.localName){case "note-body":case "ruby-text":return!1}break;case odf.Namespaces.officens:switch(a.localName){case "annotation":case "binary-data":case "event-listeners":return!1}break;default:switch(a.localName){case "cursor":case "editinfo":return!1}}return!0} +function I(a,d){for(;0=d.value||"%"===d.unit)?null:d;return d||E(a)};this.parseFoLineHeight= +function(a){return B(a)||E(a)};this.isTextContentContainingNode=H;this.getTextNodes=function(a,d){var b;b=G.getNodesInRange(a,function(a){var d=NodeFilter.FILTER_REJECT;a.nodeType===Node.TEXT_NODE?Boolean(k(a)&&(!p(a.textContent)||A(a,0)))&&(d=NodeFilter.FILTER_ACCEPT):H(a)&&(d=NodeFilter.FILTER_SKIP);return d},NodeFilter.SHOW_ELEMENT|NodeFilter.SHOW_TEXT);d||I(a,b);return b};this.getTextElements=Q;this.getParagraphElements=function(a){var d;d=G.getNodesInRange(a,function(a){var d=NodeFilter.FILTER_REJECT; +if(b(a))d=NodeFilter.FILTER_ACCEPT;else if(H(a)||n(a))d=NodeFilter.FILTER_SKIP;return d},NodeFilter.SHOW_ELEMENT);N(a.startContainer,d,b);return d};this.getImageElements=function(a){var d;d=G.getNodesInRange(a,function(a){var d=NodeFilter.FILTER_SKIP;f(a)&&(d=NodeFilter.FILTER_ACCEPT);return d},NodeFilter.SHOW_ELEMENT);N(a.startContainer,d,f);return d};this.getHyperlinkElements=function(a){var d=[],e=a.cloneRange();a.collapsed&&a.endContainer.nodeType===Node.ELEMENT_NODE&&(a=z(a.endContainer,a.endOffset), +a.nodeType===Node.TEXT_NODE&&e.setEnd(a,1));Q(e,!0,!1).forEach(function(a){for(a=a.parentNode;!b(a);){if(c(a)&&-1===d.indexOf(a)){d.push(a);break}a=a.parentNode}});e.detach();return d};this.getNormalizedFontFamilyName=function(a){/^(["'])(?:.|[\n\r])*?\1$/.test(a)||(a=a.replace(/^[ \t\r\n\f]*((?:.|[\n\r])*?)[ \t\r\n\f]*$/,"$1"),/[ \t\r\n\f]/.test(a)&&(a="'"+a.replace(/[ \t\r\n\f]+/g," ")+"'"));return a}};odf.OdfUtils=new odf.OdfUtilsImpl;gui.OdfTextBodyNodeFilter=function(){var f=odf.OdfUtils,l=Node.TEXT_NODE,a=NodeFilter.FILTER_REJECT,c=NodeFilter.FILTER_ACCEPT,b=odf.Namespaces.textns;this.acceptNode=function(k){if(k.nodeType===l){if(!f.isGroupingElement(k.parentNode))return a}else if(k.namespaceURI===b&&"tracked-changes"===k.localName)return a;return c}};xmldom.LSSerializerFilter=function(){};xmldom.LSSerializerFilter.prototype.acceptNode=function(f){};odf.OdfNodeFilter=function(){this.acceptNode=function(f){return"http://www.w3.org/1999/xhtml"===f.namespaceURI?NodeFilter.FILTER_SKIP:f.namespaceURI&&f.namespaceURI.match(/^urn:webodf:/)?NodeFilter.FILTER_REJECT:NodeFilter.FILTER_ACCEPT}};xmldom.XPathIterator=function(){};xmldom.XPathIterator.prototype.next=function(){};xmldom.XPathIterator.prototype.reset=function(){}; +function createXPathSingleton(){function f(a,d,b){return-1!==a&&(a=g&&b.push(l(a.substring(d,c)))):"["===a[c]&&(0>=g&&(d=c+1),g+=1),c+=1;return c};n=function(a,d,e){var g,m,f,k;for(g=0;g/g,">").replace(/'/g,"'").replace(/"/g,""")}function a(c,f){var q="",p=d.filter?d.filter.acceptNode(f):NodeFilter.FILTER_ACCEPT,m;if(p===NodeFilter.FILTER_ACCEPT&&f.nodeType===Node.ELEMENT_NODE){c.push();m=c.getQName(f);var l,r=f.attributes,b,e,n,g="",u;l="<"+m;b=r.length;for(e=0;e")}if(p===NodeFilter.FILTER_ACCEPT||p===NodeFilter.FILTER_SKIP){for(p=f.firstChild;p;)q+=a(c,p),p=p.nextSibling;f.nodeValue&&(q+=k(f.nodeValue))}m&&(q+="",c.pop());return q}var d=this;this.filter=null;this.writeToString=function(c,d){if(!c)return"";var q=new f(d);return a(q,c)}};(function(){function f(a){var b,c=p.length;for(b=0;bc)break;g=g.nextSibling}a.insertBefore(b,g)}}}var c=new odf.StyleInfo,h=core.DomUtils,q=odf.Namespaces.stylens,p="meta settings scripts font-face-decls styles automatic-styles master-styles body".split(" "), -m=Date.now()+"_webodf_",l=new core.Base64;odf.ODFElement=function(){};odf.ODFDocumentElement=function(){};odf.ODFDocumentElement.prototype=new odf.ODFElement;odf.ODFDocumentElement.prototype.constructor=odf.ODFDocumentElement;odf.ODFDocumentElement.prototype.fontFaceDecls=null;odf.ODFDocumentElement.prototype.manifest=null;odf.ODFDocumentElement.prototype.settings=null;odf.ODFDocumentElement.namespaceURI="urn:oasis:names:tc:opendocument:xmlns:office:1.0";odf.ODFDocumentElement.localName="document"; -odf.AnnotationElement=function(){};odf.OdfPart=function(a,b,c,d){var g=this;this.size=0;this.type=null;this.name=a;this.container=c;this.url=null;this.mimetype=b;this.onstatereadychange=this.document=null;this.EMPTY=0;this.LOADING=1;this.DONE=2;this.state=this.EMPTY;this.data="";this.load=function(){null!==d&&(this.mimetype=b,d.loadAsDataURL(a,b,function(b,a){b&&runtime.log(b);g.url=a;if(g.onchange)g.onchange(g);if(g.onstatereadychange)g.onstatereadychange(g)}))}};odf.OdfPart.prototype.load=function(){}; -odf.OdfPart.prototype.getUrl=function(){return this.data?"data:;base64,"+l.toBase64(this.data):null};odf.OdfContainer=function b(e,f){function g(b){for(var a=b.firstChild,c;a;)c=a.nextSibling,a.nodeType===Node.ELEMENT_NODE?g(a):a.nodeType===Node.PROCESSING_INSTRUCTION_NODE&&b.removeChild(a),a=c}function p(b){var a={},c,e,d=b.ownerDocument.createNodeIterator(b,NodeFilter.SHOW_ELEMENT,null,!1);for(b=d.nextNode();b;)"urn:oasis:names:tc:opendocument:xmlns:office:1.0"===b.namespaceURI&&("annotation"=== -b.localName?(c=b.getAttributeNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0","name"))&&(a.hasOwnProperty(c)?runtime.log("Warning: annotation name used more than once with : '"+c+"'"):a[c]=b):"annotation-end"===b.localName&&((c=b.getAttributeNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0","name"))?a.hasOwnProperty(c)?(e=a[c],e.annotationEndElement?runtime.log("Warning: annotation name used more than once with : '"+c+"'"):e.annotationEndElement= -b):runtime.log("Warning: annotation end without an annotation start, name: '"+c+"'"):runtime.log("Warning: annotation end without a name found"))),b=d.nextNode()}function t(b,a){for(var c=b&&b.firstChild;c;)c.nodeType===Node.ELEMENT_NODE&&c.setAttributeNS("urn:webodf:names:scope","scope",a),c=c.nextSibling}function y(b,a){for(var c=E.rootElement.meta,c=c&&c.firstChild;c&&(c.namespaceURI!==b||c.localName!==a);)c=c.nextSibling;for(c=c&&c.firstChild;c&&c.nodeType!==Node.TEXT_NODE;)c=c.nextSibling;return c? -c.data:null}function v(b){var a={},c;for(b=b.firstChild;b;)b.nodeType===Node.ELEMENT_NODE&&b.namespaceURI===q&&"font-face"===b.localName&&(c=b.getAttributeNS(q,"name"),a[c]=b),b=b.nextSibling;return a}function s(b,a){var c=null,e,d,g;if(b)for(c=b.cloneNode(!0),e=c.firstElementChild;e;)d=e.nextElementSibling,(g=e.getAttributeNS("urn:webodf:names:scope","scope"))&&g!==a&&c.removeChild(e),e=d;return c}function x(b,a){var e,d,g,f=null,n={};if(b)for(a.forEach(function(b){c.collectUsedFontFaces(n,b)}), -f=b.cloneNode(!0),e=f.firstElementChild;e;)d=e.nextElementSibling,g=e.getAttributeNS(q,"name"),n[g]||f.removeChild(e),e=d;return f}function w(b){var a=E.rootElement.ownerDocument,c;if(b){g(b.documentElement);try{c=a.importNode(b.documentElement,!0)}catch(e){}}return c}function B(b){E.state=b;if(E.onchange)E.onchange(E);if(E.onstatereadychange)E.onstatereadychange(E)}function I(b){da=null;E.rootElement=b;b.fontFaceDecls=h.getDirectChild(b,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","font-face-decls"); -b.styles=h.getDirectChild(b,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","styles");b.automaticStyles=h.getDirectChild(b,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","automatic-styles");b.masterStyles=h.getDirectChild(b,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","master-styles");b.body=h.getDirectChild(b,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","body");b.meta=h.getDirectChild(b,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","meta");b.settings=h.getDirectChild(b,"urn:oasis:names:tc:opendocument:xmlns:office:1.0", -"settings");b.scripts=h.getDirectChild(b,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","scripts");p(b)}function C(a){var e=w(a),g=E.rootElement,f;e&&"document-styles"===e.localName&&"urn:oasis:names:tc:opendocument:xmlns:office:1.0"===e.namespaceURI?(g.fontFaceDecls=h.getDirectChild(e,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","font-face-decls"),d(g,g.fontFaceDecls),f=h.getDirectChild(e,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","styles"),g.styles=f||a.createElementNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0", -"styles"),d(g,g.styles),f=h.getDirectChild(e,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","automatic-styles"),g.automaticStyles=f||a.createElementNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0","automatic-styles"),t(g.automaticStyles,"document-styles"),d(g,g.automaticStyles),e=h.getDirectChild(e,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","master-styles"),g.masterStyles=e||a.createElementNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0","master-styles"),d(g,g.masterStyles), -c.prefixStyleNames(g.automaticStyles,m,g.masterStyles)):B(b.INVALID)}function F(a){a=w(a);var e,g,f,n;if(a&&"document-content"===a.localName&&"urn:oasis:names:tc:opendocument:xmlns:office:1.0"===a.namespaceURI){e=E.rootElement;f=h.getDirectChild(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","font-face-decls");if(e.fontFaceDecls&&f){n=e.fontFaceDecls;var m,l,p,k,H={};g=v(n);k=v(f);for(f=f.firstElementChild;f;){m=f.nextElementSibling;if(f.namespaceURI===q&&"font-face"===f.localName)if(l=f.getAttributeNS(q, -"name"),g.hasOwnProperty(l)){if(!f.isEqualNode(g[l])){p=l;for(var K=g,s=k,u=0,z=void 0,z=p=p.replace(/\d+$/,"");K.hasOwnProperty(z)||s.hasOwnProperty(z);)u+=1,z=p+u;p=z;f.setAttributeNS(q,"style:name",p);n.appendChild(f);g[p]=f;delete k[l];H[l]=p}}else n.appendChild(f),g[l]=f,delete k[l];f=m}n=H}else f&&(e.fontFaceDecls=f,d(e,f));g=h.getDirectChild(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","automatic-styles");t(g,"document-content");n&&c.changeFontFaceNames(g,n);if(e.automaticStyles&&g)for(n= -g.firstChild;n;)e.automaticStyles.appendChild(n),n=g.firstChild;else g&&(e.automaticStyles=g,d(e,g));a=h.getDirectChild(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","body");if(null===a)throw" tag is mising.";e.body=a;d(e,e.body)}else B(b.INVALID)}function J(b){b=w(b);var a;b&&"document-meta"===b.localName&&"urn:oasis:names:tc:opendocument:xmlns:office:1.0"===b.namespaceURI&&(a=E.rootElement,a.meta=h.getDirectChild(b,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","meta"), -d(a,a.meta))}function N(b){b=w(b);var a;b&&"document-settings"===b.localName&&"urn:oasis:names:tc:opendocument:xmlns:office:1.0"===b.namespaceURI&&(a=E.rootElement,a.settings=h.getDirectChild(b,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","settings"),d(a,a.settings))}function K(b){b=w(b);var a;if(b&&"manifest"===b.localName&&"urn:oasis:names:tc:opendocument:xmlns:manifest:1.0"===b.namespaceURI)for(a=E.rootElement,a.manifest=b,b=a.manifest.firstElementChild;b;)"file-entry"===b.localName&&"urn:oasis:names:tc:opendocument:xmlns:manifest:1.0"=== -b.namespaceURI&&(R[b.getAttributeNS("urn:oasis:names:tc:opendocument:xmlns:manifest:1.0","full-path")]=b.getAttributeNS("urn:oasis:names:tc:opendocument:xmlns:manifest:1.0","media-type")),b=b.nextElementSibling}function H(b,a,c){b=h.getElementsByTagName(b,a);var e;for(e=0;e'}function U(){var b=new xmldom.LSSerializer,a=G("document-meta");b.filter=new odf.OdfNodeFilter;a+=b.writeToString(E.rootElement.meta,odf.Namespaces.namespaceMap);return a+""}function aa(b,a){var c=document.createElementNS("urn:oasis:names:tc:opendocument:xmlns:manifest:1.0","manifest:file-entry");c.setAttributeNS("urn:oasis:names:tc:opendocument:xmlns:manifest:1.0","manifest:full-path",b);c.setAttributeNS("urn:oasis:names:tc:opendocument:xmlns:manifest:1.0", -"manifest:media-type",a);return c}function P(){var b=runtime.parseXML(''),a=b.documentElement,c=new xmldom.LSSerializer,e;for(e in R)R.hasOwnProperty(e)&&a.appendChild(aa(e,R[e]));c.filter=new odf.OdfNodeFilter;return'\n'+c.writeToString(b,odf.Namespaces.namespaceMap)}function D(){var b,a,e,d=odf.Namespaces.namespaceMap, -g=new xmldom.LSSerializer,f=G("document-styles");a=s(E.rootElement.automaticStyles,"document-styles");e=E.rootElement.masterStyles.cloneNode(!0);b=x(E.rootElement.fontFaceDecls,[e,E.rootElement.styles,a]);c.removePrefixFromStyleNames(a,m,e);g.filter=new k(e,a);f+=g.writeToString(b,d);f+=g.writeToString(E.rootElement.styles,d);f+=g.writeToString(a,d);f+=g.writeToString(e,d);return f+""}function Q(){var b,c,e=odf.Namespaces.namespaceMap,d=new xmldom.LSSerializer,g=G("document-content"); -c=s(E.rootElement.automaticStyles,"document-content");b=x(E.rootElement.fontFaceDecls,[c]);d.filter=new a(E.rootElement.body,c);g+=d.writeToString(b,e);g+=d.writeToString(c,e);g+=d.writeToString(E.rootElement.body,e);return g+""}function $(a,c){runtime.loadXML(a,function(a,e){if(a)c(a);else if(e){z(e);Z(e.documentElement);var d=w(e);d&&"document"===d.localName&&"urn:oasis:names:tc:opendocument:xmlns:office:1.0"===d.namespaceURI?(I(d),B(b.DONE)):B(b.INVALID)}else c("No DOM was loaded.")})} -function A(b,a){var c;c=E.rootElement;var e=c.meta;e||(c.meta=e=document.createElementNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0","meta"),d(c,e));c=e;b&&h.mapKeyValObjOntoNode(c,b,odf.Namespaces.lookupNamespaceURI);a&&h.removeKeyElementsFromNode(c,a,odf.Namespaces.lookupNamespaceURI)}function V(a,c){function e(b,a){var c;a||(a=b);c=document.createElementNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0",a);n[b]=c;n.appendChild(c)}var d=new core.Zip("",null),g="application/vnd.oasis.opendocument."+ -a+(!0===c?"-template":""),f=runtime.byteArrayFromString(g,"utf8"),n=E.rootElement,h=document.createElementNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0",a);d.save("mimetype",f,!1,new Date);e("meta");e("settings");e("scripts");e("fontFaceDecls","font-face-decls");e("styles");e("automaticStyles","automatic-styles");e("masterStyles","master-styles");e("body");n.body.appendChild(h);R["/"]=g;R["settings.xml"]="text/xml";R["meta.xml"]="text/xml";R["styles.xml"]="text/xml";R["content.xml"]="text/xml"; -B(b.DONE);return d}function ba(){var b,a=new Date,c="";E.rootElement.settings&&E.rootElement.settings.firstElementChild&&(b=new xmldom.LSSerializer,c=G("document-settings"),b.filter=new odf.OdfNodeFilter,c+=b.writeToString(E.rootElement.settings,odf.Namespaces.namespaceMap),c+="");(b=c)?(b=runtime.byteArrayFromString(b,"utf8"),X.save("settings.xml",b,!0,a)):X.remove("settings.xml");c=runtime.getWindow();b="WebODF/"+webodf.Version;c&&(b=b+" "+c.navigator.userAgent);A({"meta:generator":b}, -null);b=runtime.byteArrayFromString(U(),"utf8");X.save("meta.xml",b,!0,a);b=runtime.byteArrayFromString(D(),"utf8");X.save("styles.xml",b,!0,a);b=runtime.byteArrayFromString(Q(),"utf8");X.save("content.xml",b,!0,a);b=runtime.byteArrayFromString(P(),"utf8");X.save("META-INF/manifest.xml",b,!0,a)}function Y(b,a){ba();X.writeAs(b,function(b){a(b)})}var E=this,X,R={},da,S="";this.onstatereadychange=f;this.state=this.onchange=null;this.getMetadata=y;this.setRootElement=I;this.getContentElement=function(){var b; -da||(b=E.rootElement.body,da=h.getDirectChild(b,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","text")||h.getDirectChild(b,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","presentation")||h.getDirectChild(b,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","spreadsheet"));if(!da)throw"Could not find content element in .";return da};this.getDocumentType=function(){var b=E.getContentElement();return b&&b.localName};this.isTemplate=function(){return"-template"===R["/"].substr(-9)}; -this.setIsTemplate=function(b){var a=R["/"],c="-template"===a.substr(-9);b!==c&&(a=b?a+"-template":a.substr(0,a.length-9),R["/"]=a,b=runtime.byteArrayFromString(a,"utf8"),X.save("mimetype",b,!1,new Date))};this.getPart=function(b){return new odf.OdfPart(b,R[b],E,X)};this.getPartData=function(b,a){X.load(b,a)};this.setMetadata=A;this.incrementEditingCycles=function(){var b=y(odf.Namespaces.metans,"editing-cycles"),b=b?parseInt(b,10):0;isNaN(b)&&(b=0);A({"meta:editing-cycles":b+1},null);return b+1}; -this.createByteArray=function(b,a){ba();X.createByteArray(b,a)};this.saveAs=Y;this.save=function(b){Y(S,b)};this.getUrl=function(){return S};this.setBlob=function(b,a,c){c=l.convertBase64ToByteArray(c);X.save(b,c,!1,new Date);R.hasOwnProperty(b)&&runtime.log(b+" has been overwritten.");R[b]=a};this.removeBlob=function(b){var a=X.remove(b);runtime.assert(a,"file is not found: "+b);delete R[b]};this.state=b.LOADING;this.rootElement=function(b){var a=document.createElementNS(b.namespaceURI,b.localName), -c;b=new b.Type;for(c in b)b.hasOwnProperty(c)&&(a[c]=b[c]);return a}({Type:odf.ODFDocumentElement,namespaceURI:odf.ODFDocumentElement.namespaceURI,localName:odf.ODFDocumentElement.localName});e===odf.OdfContainer.DocumentType.TEXT?X=V("text"):e===odf.OdfContainer.DocumentType.TEXT_TEMPLATE?X=V("text",!0):e===odf.OdfContainer.DocumentType.PRESENTATION?X=V("presentation"):e===odf.OdfContainer.DocumentType.PRESENTATION_TEMPLATE?X=V("presentation",!0):e===odf.OdfContainer.DocumentType.SPREADSHEET?X=V("spreadsheet"): -e===odf.OdfContainer.DocumentType.SPREADSHEET_TEMPLATE?X=V("spreadsheet",!0):(S=e,X=new core.Zip(S,function(a,c){X=c;a?$(S,function(c){a&&(X.error=a+"\n"+c,B(b.INVALID))}):T([{path:"styles.xml",handler:C},{path:"content.xml",handler:F},{path:"meta.xml",handler:J},{path:"settings.xml",handler:N},{path:"META-INF/manifest.xml",handler:K}])}))};odf.OdfContainer.EMPTY=0;odf.OdfContainer.LOADING=1;odf.OdfContainer.DONE=2;odf.OdfContainer.INVALID=3;odf.OdfContainer.SAVING=4;odf.OdfContainer.MODIFIED=5;odf.OdfContainer.getContainer= -function(b){return new odf.OdfContainer(b,null)}})();odf.OdfContainer.DocumentType={TEXT:1,TEXT_TEMPLATE:2,PRESENTATION:3,PRESENTATION_TEMPLATE:4,SPREADSHEET:5,SPREADSHEET_TEMPLATE:6};gui.AnnotatableCanvas=function(){};gui.AnnotatableCanvas.prototype.refreshSize=function(){};gui.AnnotatableCanvas.prototype.getZoomLevel=function(){};gui.AnnotatableCanvas.prototype.getSizer=function(){}; -gui.AnnotationViewManager=function(f,k,a,d){function c(b){var a=b.annotationEndElement,c=l.createRange(),d=b.getAttributeNS(odf.Namespaces.officens,"name");a&&(c.setStart(b,b.childNodes.length),c.setEnd(a,0),b=r.getTextNodes(c,!1),b.forEach(function(b){var a;a:{for(a=b.parentNode;a.namespaceURI!==odf.Namespaces.officens||"body"!==a.localName;){if(a.namespaceURI===e&&"webodf-annotationHighlight"===a.className&&a.getAttribute("annotation")===d){a=!0;break a}a=a.parentNode}a=!1}a||(a=l.createElement("span"), -a.className="webodf-annotationHighlight",a.setAttribute("annotation",d),b.parentNode.replaceChild(a,b),a.appendChild(b))}));c.detach()}function h(c){var e=f.getSizer();c?(a.style.display="inline-block",e.style.paddingRight=b.getComputedStyle(a).width):(a.style.display="none",e.style.paddingRight=0);f.refreshSize()}function q(){m.sort(function(b,a){return 0!==(b.compareDocumentPosition(a)&Node.DOCUMENT_POSITION_FOLLOWING)?-1:1})}function p(){var b;for(b=0;b=(l.getBoundingClientRect().top-q.bottom)/c?e.style.top=Math.abs(l.getBoundingClientRect().top-q.bottom)/c+20+"px":e.style.top="0px");h.style.left=d.getBoundingClientRect().width/ -c+"px";var d=h.style,l=h.getBoundingClientRect().left/c,p=h.getBoundingClientRect().top/c,q=e.getBoundingClientRect().left/c,k=e.getBoundingClientRect().top/c,r=0,I=0,r=q-l,r=r*r,I=k-p,I=I*I,l=Math.sqrt(r+I);d.width=l+"px";p=Math.asin((e.getBoundingClientRect().top-h.getBoundingClientRect().top)/(c*parseFloat(h.style.width)));h.style.transform="rotate("+p+"rad)";h.style.MozTransform="rotate("+p+"rad)";h.style.WebkitTransform="rotate("+p+"rad)";h.style.msTransform="rotate("+p+"rad)"}}var m=[],l=k.ownerDocument, -r=odf.OdfUtils,b=runtime.getWindow(),e="http://www.w3.org/1999/xhtml";runtime.assert(Boolean(b),"Expected to be run in an environment which has a global window, like a browser.");this.rerenderAnnotations=p;this.rehighlightAnnotations=function(){m.forEach(function(b){c(b)})};this.getMinimumHeightForAnnotationPane=function(){return"none"!==a.style.display&&0q||k.bottom>q)f.scrollTop=k.bottom-k.top<=q-c?f.scrollTop+(k.bottom-q):f.scrollTop+(k.top-c);k.lefth&&(f.scrollLeft=k.right-k.left<=h-d?f.scrollLeft+(k.right-h):f.scrollLeft-(d-k.left))}}};(function(){function f(a,h,q,p,m){var l,k=0,b;for(b in a)if(a.hasOwnProperty(b)){if(k===q){l=b;break}k+=1}l?h.getPartData(a[l].href,function(b,n){if(b)runtime.log(b);else if(n){var g="@font-face { font-family: "+(a[l].family||l)+"; src: url(data:application/x-font-ttf;charset=binary;base64,"+d.convertUTF8ArrayToBase64(n)+') format("truetype"); }';try{p.insertRule(g,p.cssRules.length)}catch(k){runtime.log("Problem inserting rule in CSS: "+runtime.toJson(k)+"\nRule: "+g)}}else runtime.log("missing font data for "+ -a[l].href);f(a,h,q+1,p,m)}):m&&m()}var k=xmldom.XPath,a=odf.OdfUtils,d=new core.Base64;odf.FontLoader=function(){this.loadFonts=function(c,d){for(var q=c.rootElement.fontFaceDecls;d.cssRules.length;)d.deleteRule(d.cssRules.length-1);if(q){var p={},m,l,r,b;if(q)for(q=k.getODFElementsWithXPath(q,"style:font-face[svg:font-face-src]",odf.Namespaces.lookupNamespaceURI),m=0;m text|list-item:first-child > :not(text|list):first-child:before',x+="{",x+="counter-increment: "+s+" 0;",x+="}",f(a,x));for(;k.counterIdStack.length>=q;)k.counterIdStack.pop();k.counterIdStack.push(s);w=k.contentRules[q.toString()]||"";for(x=1;x<=q;x+=1)w=w.replace(x+"webodf-listLevel",k.counterIdStack[x-1]);x='text|list[webodfhelper|counter-id="'+r+'"] > text|list-item > :not(text|list):first-child:before'; -x+="{";x+=w;x+="counter-increment: "+s+";";x+="}";f(a,x)}for(d=d.firstElementChild;d;)c(e,d,p,k),d=d.nextElementSibling}else k.continuedCounterIdStack=[]}var d=0,b="",e={};this.createCounterRules=function(b,a,f){var h=a.getAttributeNS(q,"id"),m=[];f&&(f=f.getAttributeNS("urn:webodf:names:helper","counter-id"),m=e[f].slice(0));b=new k(b,m);h?h="Y"+h:(d+=1,h="X"+d);c(h,a,0,b);e[h+"-level1-1"]=b.counterIdStack};this.initialiseCreatedCounters=function(){var c;c="office|document{"+("counter-reset: "+b+ -";");c+="}";f(a,c)}}var d=odf.Namespaces.fons,c=odf.Namespaces.stylens,h=odf.Namespaces.textns,q=odf.Namespaces.xmlns,p={1:"decimal",a:"lower-latin",A:"upper-latin",i:"lower-roman",I:"upper-roman"};odf.ListStyleToCss=function(){function m(b){var a=n.parseLength(b);return a?e.convert(a.value,a.unit,"px"):(runtime.log("Could not parse value '"+b+"'."),0)}function l(b){return b.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function k(b,a){var c;b&&(c=b.getAttributeNS(h,"style-name"));return c===a}function b(b, -e,d){e=e.getElementsByTagNameNS(h,"list");b=new a(b);var f,n,m,x,w,B,I={},C;for(C=0;C text|list-item > text|list",t-=1;t=u&&u.getAttributeNS(d,"text-align")||"left";switch(t){case "end":t="right";break;case "start":t="left"}"label-alignment"===N?(H=K&&K.getAttributeNS(d,"margin-left")||"0px",T=K&&K.getAttributeNS(d,"text-indent")||"0px",G=K&&K.getAttributeNS(h,"label-followed-by"),K=m(H)):(H=u&&u.getAttributeNS(h,"space-before")||"0px",z=u&&u.getAttributeNS(h,"min-label-width")||"0px", -Z=u&&u.getAttributeNS(h,"min-label-distance")||"0px",K=m(H)+m(z));u=q+" > text|list-item";u+="{";u+="margin-left: "+K+"px;";u+="}";f(n,u);u=q+" > text|list-item > text|list";u+="{";u+="margin-left: "+-K+"px;";u+="}";f(n,u);u=q+" > text|list-item > :not(text|list):first-child:before";u+="{";u+="text-align: "+t+";";u+="display: inline-block;";"label-alignment"===N?(u+="margin-left: "+T+";","listtab"===G&&(u+="padding-right: 0.2cm;")):(u+="min-width: "+z+";",u+="margin-left: "+(0===parseFloat(z)?"": -"-")+z+";",u+="padding-right: "+Z+";");u+="}";f(n,u)}e=e.nextElementSibling}});b(a,n,l)}}})();odf.LazyStyleProperties=function(f,k){var a={};this.value=function(d){var c;a.hasOwnProperty(d)?c=a[d]:(c=k[d](),void 0===c&&f&&(c=f.value(d)),a[d]=c);return c};this.reset=function(d){f=d;a={}}}; -odf.StyleParseUtils=function(){function f(a){var d,c;a=(a=/(-?[0-9]*[0-9][0-9]*(\.[0-9]*)?|0+\.[0-9]*[1-9][0-9]*|\.[0-9]*[1-9][0-9]*)((cm)|(mm)|(in)|(pt)|(pc)|(px))/.exec(a))?{value:parseFloat(a[1]),unit:a[3]}:null;c=a&&a.unit;"px"===c?d=a.value:"cm"===c?d=96*(a.value/2.54):"mm"===c?d=96*(a.value/25.4):"in"===c?d=96*a.value:"pt"===c?d=a.value/0.75:"pc"===c&&(d=16*a.value);return d}var k=odf.Namespaces.stylens;this.parseLength=f;this.parsePositiveLengthOrPercent=function(a,d,c){var h;a&&(h=parseFloat(a.substr(0, -a.indexOf("%"))),isNaN(h)&&(h=void 0));var k;void 0!==h?(c&&(k=c.value(d)),h=void 0===k?void 0:h*(k/100)):h=f(a);return h};this.getPropertiesElement=function(a,d,c){for(d=c?c.nextElementSibling:d.firstElementChild;null!==d&&(d.localName!==a||d.namespaceURI!==k);)d=d.nextElementSibling;return d};this.parseAttributeList=function(a){a&&(a=a.replace(/^\s*(.*?)\s*$/g,"$1"));return a&&0n.value&&(f="0.75pt"+g);g=f}else if(z.hasOwnProperty(d[1])){var f= -b,h=d[0],n=d[1],m=T.parseLength(g),l=void 0,p=void 0,q=void 0,K=void 0,q=void 0;if(m&&"%"===m.unit){l=m.value/100;p=k(f.parentNode);for(K="0";p;){if(q=u.getDirectChild(p,r,"paragraph-properties"))if(q=T.parseLength(q.getAttributeNS(h,n))){if("%"!==q.unit){K=q.value*l+q.unit;break}l*=q.value/100}p=k(p)}g=K}}d[2]&&(c+=d[2]+":"+g+";")}return c}function d(b,a,c,e){return a+a+c+c+e+e}function c(b,a){var e=[b],d=a.derivedStyles;Object.keys(d).forEach(function(b){b=c(b,d[b]);e=e.concat(b)});return e}function h(b, -a,e,d){function f(a,c){var e=[],d;a.forEach(function(b){h.forEach(function(a){e.push("draw|page[webodfhelper|page-style-name='"+a+"'] draw|frame[presentation|class='"+b+"']")})});0/g,">").replace(/'/g,"'").replace(/"/g,""")}function a(b,f){var q="",p=c.filter?c.filter.acceptNode(f):NodeFilter.FILTER_ACCEPT,n;if(p===NodeFilter.FILTER_ACCEPT&&f.nodeType===Node.ELEMENT_NODE){b.push();n=b.getQName(f);var g,h=f.attributes,d,e,s,m="",x;g="<"+n;d=h.length;for(e=0;e")}if(p===NodeFilter.FILTER_ACCEPT||p===NodeFilter.FILTER_SKIP){for(p=f.firstChild;p;)q+=a(b,p),p=p.nextSibling;f.nodeValue&&(q+=l(f.nodeValue))}n&&(q+="",b.pop());return q}var c=this;this.filter=null;this.writeToString=function(b,c){if(!b)return"";var q=new f(c);return a(q,b)}};(function(){function f(a){var b,e=p.length;for(b=0;be)break;m=m.nextSibling}a.insertBefore(b,m)}}}var b=new odf.StyleInfo,k=core.DomUtils,q=odf.Namespaces.stylens,p="meta settings scripts font-face-decls styles automatic-styles master-styles body".split(" "), +n=Date.now()+"_webodf_",g=new core.Base64;odf.ODFElement=function(){};odf.ODFDocumentElement=function(){};odf.ODFDocumentElement.prototype=new odf.ODFElement;odf.ODFDocumentElement.prototype.constructor=odf.ODFDocumentElement;odf.ODFDocumentElement.prototype.fontFaceDecls=null;odf.ODFDocumentElement.prototype.manifest=null;odf.ODFDocumentElement.prototype.settings=null;odf.ODFDocumentElement.namespaceURI="urn:oasis:names:tc:opendocument:xmlns:office:1.0";odf.ODFDocumentElement.localName="document"; +odf.AnnotationElement=function(){};odf.OdfPart=function(a,b,e,c){var m=this;this.size=0;this.type=null;this.name=a;this.container=e;this.url=null;this.mimetype=b;this.onstatereadychange=this.document=null;this.EMPTY=0;this.LOADING=1;this.DONE=2;this.state=this.EMPTY;this.data="";this.load=function(){null!==c&&(this.mimetype=b,c.loadAsDataURL(a,b,function(a,b){a&&runtime.log(a);m.url=b;if(m.onchange)m.onchange(m);if(m.onstatereadychange)m.onstatereadychange(m)}))}};odf.OdfPart.prototype.load=function(){}; +odf.OdfPart.prototype.getUrl=function(){return this.data?"data:;base64,"+g.toBase64(this.data):null};odf.OdfContainer=function d(e,f){function m(a){for(var b=a.firstChild,d;b;)d=b.nextSibling,b.nodeType===Node.ELEMENT_NODE?m(b):b.nodeType===Node.PROCESSING_INSTRUCTION_NODE&&a.removeChild(b),b=d}function p(a){var b={},d,e,c=a.ownerDocument.createNodeIterator(a,NodeFilter.SHOW_ELEMENT,null,!1);for(a=c.nextNode();a;)"urn:oasis:names:tc:opendocument:xmlns:office:1.0"===a.namespaceURI&&("annotation"=== +a.localName?(d=a.getAttributeNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0","name"))&&(b.hasOwnProperty(d)?runtime.log("Warning: annotation name used more than once with : '"+d+"'"):b[d]=a):"annotation-end"===a.localName&&((d=a.getAttributeNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0","name"))?b.hasOwnProperty(d)?(e=b[d],e.annotationEndElement?runtime.log("Warning: annotation name used more than once with : '"+d+"'"):e.annotationEndElement= +a):runtime.log("Warning: annotation end without an annotation start, name: '"+d+"'"):runtime.log("Warning: annotation end without a name found"))),a=c.nextNode()}function t(a,b){for(var d=a&&a.firstChild;d;)d.nodeType===Node.ELEMENT_NODE&&d.setAttributeNS("urn:webodf:names:scope","scope",b),d=d.nextSibling}function y(a,b){for(var d=U.rootElement.meta,d=d&&d.firstChild;d&&(d.namespaceURI!==a||d.localName!==b);)d=d.nextSibling;for(d=d&&d.firstChild;d&&d.nodeType!==Node.TEXT_NODE;)d=d.nextSibling;return d? +d.data:null}function v(a){var b={},d;for(a=a.firstChild;a;)a.nodeType===Node.ELEMENT_NODE&&a.namespaceURI===q&&"font-face"===a.localName&&(d=a.getAttributeNS(q,"name"),b[d]=a),a=a.nextSibling;return b}function r(a,b){var d=null,e,c,m;if(a)for(d=a.cloneNode(!0),e=d.firstElementChild;e;)c=e.nextElementSibling,(m=e.getAttributeNS("urn:webodf:names:scope","scope"))&&m!==b&&d.removeChild(e),e=c;return d}function w(a,d){var e,c,m,g=null,f={};if(a)for(d.forEach(function(a){b.collectUsedFontFaces(f,a)}), +g=a.cloneNode(!0),e=g.firstElementChild;e;)c=e.nextElementSibling,m=e.getAttributeNS(q,"name"),f[m]||g.removeChild(e),e=c;return g}function u(a){var b=U.rootElement.ownerDocument,d;if(a){m(a.documentElement);try{d=b.importNode(a.documentElement,!0)}catch(e){}}return d}function A(a){U.state=a;if(U.onchange)U.onchange(U);if(U.onstatereadychange)U.onstatereadychange(U)}function F(a){aa=null;U.rootElement=a;a.fontFaceDecls=k.getDirectChild(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","font-face-decls"); +a.styles=k.getDirectChild(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","styles");a.automaticStyles=k.getDirectChild(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","automatic-styles");a.masterStyles=k.getDirectChild(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","master-styles");a.body=k.getDirectChild(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","body");a.meta=k.getDirectChild(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","meta");a.settings=k.getDirectChild(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0", +"settings");a.scripts=k.getDirectChild(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","scripts");p(a)}function B(a){var e=u(a),m=U.rootElement,g;e&&"document-styles"===e.localName&&"urn:oasis:names:tc:opendocument:xmlns:office:1.0"===e.namespaceURI?(m.fontFaceDecls=k.getDirectChild(e,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","font-face-decls"),c(m,m.fontFaceDecls),g=k.getDirectChild(e,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","styles"),m.styles=g||a.createElementNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0", +"styles"),c(m,m.styles),g=k.getDirectChild(e,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","automatic-styles"),m.automaticStyles=g||a.createElementNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0","automatic-styles"),t(m.automaticStyles,"document-styles"),c(m,m.automaticStyles),e=k.getDirectChild(e,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","master-styles"),m.masterStyles=e||a.createElementNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0","master-styles"),c(m,m.masterStyles), +b.prefixStyleNames(m.automaticStyles,n,m.masterStyles)):A(d.INVALID)}function E(a){a=u(a);var e,m,g,f;if(a&&"document-content"===a.localName&&"urn:oasis:names:tc:opendocument:xmlns:office:1.0"===a.namespaceURI){e=U.rootElement;g=k.getDirectChild(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","font-face-decls");if(e.fontFaceDecls&&g){f=e.fontFaceDecls;var p,s,n,l,z={};m=v(f);l=v(g);for(g=g.firstElementChild;g;){p=g.nextElementSibling;if(g.namespaceURI===q&&"font-face"===g.localName)if(s=g.getAttributeNS(q, +"name"),m.hasOwnProperty(s)){if(!g.isEqualNode(m[s])){n=s;for(var r=m,Q=l,x=0,Y=void 0,Y=n=n.replace(/\d+$/,"");r.hasOwnProperty(Y)||Q.hasOwnProperty(Y);)x+=1,Y=n+x;n=Y;g.setAttributeNS(q,"style:name",n);f.appendChild(g);m[n]=g;delete l[s];z[s]=n}}else f.appendChild(g),m[s]=g,delete l[s];g=p}f=z}else g&&(e.fontFaceDecls=g,c(e,g));m=k.getDirectChild(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","automatic-styles");t(m,"document-content");f&&b.changeFontFaceNames(m,f);if(e.automaticStyles&&m)for(f= +m.firstChild;f;)e.automaticStyles.appendChild(f),f=m.firstChild;else m&&(e.automaticStyles=m,c(e,m));a=k.getDirectChild(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","body");if(null===a)throw" tag is mising.";e.body=a;c(e,e.body)}else A(d.INVALID)}function H(a){a=u(a);var b;a&&"document-meta"===a.localName&&"urn:oasis:names:tc:opendocument:xmlns:office:1.0"===a.namespaceURI&&(b=U.rootElement,b.meta=k.getDirectChild(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","meta"), +c(b,b.meta))}function I(a){a=u(a);var b;a&&"document-settings"===a.localName&&"urn:oasis:names:tc:opendocument:xmlns:office:1.0"===a.namespaceURI&&(b=U.rootElement,b.settings=k.getDirectChild(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","settings"),c(b,b.settings))}function Q(a){a=u(a);var b;if(a&&"manifest"===a.localName&&"urn:oasis:names:tc:opendocument:xmlns:manifest:1.0"===a.namespaceURI)for(b=U.rootElement,b.manifest=a,a=b.manifest.firstElementChild;a;)"file-entry"===a.localName&&"urn:oasis:names:tc:opendocument:xmlns:manifest:1.0"=== +a.namespaceURI&&(P[a.getAttributeNS("urn:oasis:names:tc:opendocument:xmlns:manifest:1.0","full-path")]=a.getAttributeNS("urn:oasis:names:tc:opendocument:xmlns:manifest:1.0","media-type")),a=a.nextElementSibling}function N(a,b,d){a=k.getElementsByTagName(a,b);var e;for(e=0;e'}function G(){var a=new xmldom.LSSerializer,b=J("document-meta");a.filter=new odf.OdfNodeFilter;b+=a.writeToString(U.rootElement.meta,odf.Namespaces.namespaceMap);return b+""}function ba(a,b){var d=document.createElementNS("urn:oasis:names:tc:opendocument:xmlns:manifest:1.0","manifest:file-entry");d.setAttributeNS("urn:oasis:names:tc:opendocument:xmlns:manifest:1.0","manifest:full-path",a);d.setAttributeNS("urn:oasis:names:tc:opendocument:xmlns:manifest:1.0", +"manifest:media-type",b);return d}function T(){var a=runtime.parseXML(''),b=a.documentElement,d=new xmldom.LSSerializer,e;for(e in P)P.hasOwnProperty(e)&&b.appendChild(ba(e,P[e]));d.filter=new odf.OdfNodeFilter;return'\n'+d.writeToString(a,odf.Namespaces.namespaceMap)}function D(){var a,d,e,c=odf.Namespaces.namespaceMap, +m=new xmldom.LSSerializer,g=J("document-styles");d=r(U.rootElement.automaticStyles,"document-styles");e=U.rootElement.masterStyles.cloneNode(!0);a=w(U.rootElement.fontFaceDecls,[e,U.rootElement.styles,d]);b.removePrefixFromStyleNames(d,n,e);m.filter=new l(e,d);g+=m.writeToString(a,c);g+=m.writeToString(U.rootElement.styles,c);g+=m.writeToString(d,c);g+=m.writeToString(e,c);return g+""}function O(){var b,d,e=odf.Namespaces.namespaceMap,c=new xmldom.LSSerializer,m=J("document-content"); +d=r(U.rootElement.automaticStyles,"document-content");b=w(U.rootElement.fontFaceDecls,[d]);c.filter=new a(U.rootElement.body,d);m+=c.writeToString(b,e);m+=c.writeToString(d,e);m+=c.writeToString(U.rootElement.body,e);return m+""}function Z(a,b){runtime.loadXML(a,function(a,e){if(a)b(a);else if(e){z(e);Y(e.documentElement);var c=u(e);c&&"document"===c.localName&&"urn:oasis:names:tc:opendocument:xmlns:office:1.0"===c.namespaceURI?(F(c),A(d.DONE)):A(d.INVALID)}else b("No DOM was loaded.")})} +function C(a,b){var d;d=U.rootElement;var e=d.meta;e||(d.meta=e=document.createElementNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0","meta"),c(d,e));d=e;a&&k.mapKeyValObjOntoNode(d,a,odf.Namespaces.lookupNamespaceURI);b&&k.removeKeyElementsFromNode(d,b,odf.Namespaces.lookupNamespaceURI)}function V(a,b){function e(a,b){var d;b||(b=a);d=document.createElementNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0",b);f[a]=d;f.appendChild(d)}var c=new core.Zip("",null),m="application/vnd.oasis.opendocument."+ +a+(!0===b?"-template":""),g=runtime.byteArrayFromString(m,"utf8"),f=U.rootElement,k=document.createElementNS("urn:oasis:names:tc:opendocument:xmlns:office:1.0",a);c.save("mimetype",g,!1,new Date);e("meta");e("settings");e("scripts");e("fontFaceDecls","font-face-decls");e("styles");e("automaticStyles","automatic-styles");e("masterStyles","master-styles");e("body");f.body.appendChild(k);P["/"]=m;P["settings.xml"]="text/xml";P["meta.xml"]="text/xml";P["styles.xml"]="text/xml";P["content.xml"]="text/xml"; +A(d.DONE);return c}function $(){var a,b=new Date,d="";U.rootElement.settings&&U.rootElement.settings.firstElementChild&&(a=new xmldom.LSSerializer,d=J("document-settings"),a.filter=new odf.OdfNodeFilter,d+=a.writeToString(U.rootElement.settings,odf.Namespaces.namespaceMap),d+="");(a=d)?(a=runtime.byteArrayFromString(a,"utf8"),W.save("settings.xml",a,!0,b)):W.remove("settings.xml");d=runtime.getWindow();a="WebODF/"+webodf.Version;d&&(a=a+" "+d.navigator.userAgent);C({"meta:generator":a}, +null);a=runtime.byteArrayFromString(G(),"utf8");W.save("meta.xml",a,!0,b);a=runtime.byteArrayFromString(D(),"utf8");W.save("styles.xml",a,!0,b);a=runtime.byteArrayFromString(O(),"utf8");W.save("content.xml",a,!0,b);a=runtime.byteArrayFromString(T(),"utf8");W.save("META-INF/manifest.xml",a,!0,b)}function ca(a,b){$();W.writeAs(a,function(a){b(a)})}var U=this,W,P={},aa,S="";this.onstatereadychange=f;this.state=this.onchange=null;this.getMetadata=y;this.setRootElement=F;this.getContentElement=function(){var a; +aa||(a=U.rootElement.body,aa=k.getDirectChild(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","text")||k.getDirectChild(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","presentation")||k.getDirectChild(a,"urn:oasis:names:tc:opendocument:xmlns:office:1.0","spreadsheet"));if(!aa)throw"Could not find content element in .";return aa};this.getDocumentType=function(){var a=U.getContentElement();return a&&a.localName};this.isTemplate=function(){return"-template"===P["/"].substr(-9)}; +this.setIsTemplate=function(a){var b=P["/"],d="-template"===b.substr(-9);a!==d&&(b=a?b+"-template":b.substr(0,b.length-9),P["/"]=b,a=runtime.byteArrayFromString(b,"utf8"),W.save("mimetype",a,!1,new Date))};this.getPart=function(a){return new odf.OdfPart(a,P[a],U,W)};this.getPartData=function(a,b){W.load(a,b)};this.setMetadata=C;this.incrementEditingCycles=function(){var a=y(odf.Namespaces.metans,"editing-cycles"),a=a?parseInt(a,10):0;isNaN(a)&&(a=0);C({"meta:editing-cycles":a+1},null);return a+1}; +this.createByteArray=function(a,b){$();W.createByteArray(a,b)};this.saveAs=ca;this.save=function(a){ca(S,a)};this.getUrl=function(){return S};this.setBlob=function(a,b,d){d=g.convertBase64ToByteArray(d);W.save(a,d,!1,new Date);P.hasOwnProperty(a)&&runtime.log(a+" has been overwritten.");P[a]=b};this.removeBlob=function(a){var b=W.remove(a);runtime.assert(b,"file is not found: "+a);delete P[a]};this.state=d.LOADING;this.rootElement=function(a){var b=document.createElementNS(a.namespaceURI,a.localName), +d;a=new a.Type;for(d in a)a.hasOwnProperty(d)&&(b[d]=a[d]);return b}({Type:odf.ODFDocumentElement,namespaceURI:odf.ODFDocumentElement.namespaceURI,localName:odf.ODFDocumentElement.localName});e===odf.OdfContainer.DocumentType.TEXT?W=V("text"):e===odf.OdfContainer.DocumentType.TEXT_TEMPLATE?W=V("text",!0):e===odf.OdfContainer.DocumentType.PRESENTATION?W=V("presentation"):e===odf.OdfContainer.DocumentType.PRESENTATION_TEMPLATE?W=V("presentation",!0):e===odf.OdfContainer.DocumentType.SPREADSHEET?W=V("spreadsheet"): +e===odf.OdfContainer.DocumentType.SPREADSHEET_TEMPLATE?W=V("spreadsheet",!0):(S=e,W=new core.Zip(S,function(a,b){W=b;a?Z(S,function(b){a&&(W.error=a+"\n"+b,A(d.INVALID))}):R([{path:"styles.xml",handler:B},{path:"content.xml",handler:E},{path:"meta.xml",handler:H},{path:"settings.xml",handler:I},{path:"META-INF/manifest.xml",handler:Q}])}))};odf.OdfContainer.EMPTY=0;odf.OdfContainer.LOADING=1;odf.OdfContainer.DONE=2;odf.OdfContainer.INVALID=3;odf.OdfContainer.SAVING=4;odf.OdfContainer.MODIFIED=5;odf.OdfContainer.getContainer= +function(a){return new odf.OdfContainer(a,null)}})();odf.OdfContainer.DocumentType={TEXT:1,TEXT_TEMPLATE:2,PRESENTATION:3,PRESENTATION_TEMPLATE:4,SPREADSHEET:5,SPREADSHEET_TEMPLATE:6};gui.AnnotatableCanvas=function(){};gui.AnnotatableCanvas.prototype.refreshSize=function(){};gui.AnnotatableCanvas.prototype.getZoomLevel=function(){};gui.AnnotatableCanvas.prototype.getSizer=function(){}; +gui.AnnotationViewManager=function(f,l,a,c){function b(a){var b=a.annotationEndElement,e=h.createRange(),c=a.getAttributeNS(odf.Namespaces.officens,"name");b&&(e.setStart(a,a.childNodes.length),e.setEnd(b,0),a=d.getTextNodes(e,!1),a.forEach(function(a){var b;a:{for(b=a.parentNode;b.namespaceURI!==odf.Namespaces.officens||"body"!==b.localName;){if(b.namespaceURI===s&&"webodf-annotationHighlight"===b.className&&b.getAttribute("annotation")===c){b=!0;break a}b=b.parentNode}b=!1}b||(b=h.createElement("span"), +b.className="webodf-annotationHighlight",b.setAttribute("annotation",c),a.parentNode.replaceChild(b,a),b.appendChild(a))}));e.detach()}function k(b){var d=f.getSizer();b?(a.style.display="inline-block",d.style.paddingRight=e.getComputedStyle(a).width):(a.style.display="none",d.style.paddingRight=0);f.refreshSize()}function q(){g.sort(function(a,b){return 0!==(a.compareDocumentPosition(b)&Node.DOCUMENT_POSITION_FOLLOWING)?-1:1})}function p(){var b;for(b=0;b=(k.getBoundingClientRect().top-s.bottom)/d?e.style.top=Math.abs(k.getBoundingClientRect().top-s.bottom)/d+20+"px":e.style.top="0px"):e.style.top="0px";h.style.left= +c.getBoundingClientRect().width/d+"px";var c=h.style,k=h.getBoundingClientRect().left/d,p=h.getBoundingClientRect().top/d,s=e.getBoundingClientRect().left/d,n=e.getBoundingClientRect().top/d,q=0,l=0,q=s-k,q=q*q,l=n-p,l=l*l,k=Math.sqrt(q+l);c.width=k+"px";p=Math.asin((e.getBoundingClientRect().top-h.getBoundingClientRect().top)/(d*parseFloat(h.style.width)));h.style.transform="rotate("+p+"rad)";h.style.MozTransform="rotate("+p+"rad)";h.style.WebkitTransform="rotate("+p+"rad)";h.style.msTransform="rotate("+ +p+"rad)"}}function n(a){var b=g.indexOf(a),d=a.parentNode.parentNode;"div"===d.localName&&(d.parentNode.insertBefore(a,d),d.parentNode.removeChild(d));a=a.getAttributeNS(odf.Namespaces.officens,"name");a=h.querySelectorAll('span.webodf-annotationHighlight[annotation="'+a+'"]');for(var e,d=0;dq||l.bottom>q)f.scrollTop=l.bottom-l.top<=q-b?f.scrollTop+(l.bottom-q):f.scrollTop+(l.top-b);l.leftk&&(f.scrollLeft=l.right-l.left<=k-c?f.scrollLeft+(l.right-k):f.scrollLeft-(c-l.left))}}};(function(){function f(a,k,q,p,n){var g,h=0,d;for(d in a)if(a.hasOwnProperty(d)){if(h===q){g=d;break}h+=1}g?k.getPartData(a[g].href,function(d,h){if(d)runtime.log(d);else if(h){var m="@font-face { font-family: "+(a[g].family||g)+"; src: url(data:application/x-font-ttf;charset=binary;base64,"+c.convertUTF8ArrayToBase64(h)+') format("truetype"); }';try{p.insertRule(m,p.cssRules.length)}catch(l){runtime.log("Problem inserting rule in CSS: "+runtime.toJson(l)+"\nRule: "+m)}}else runtime.log("missing font data for "+ +a[g].href);f(a,k,q+1,p,n)}):n&&n()}var l=xmldom.XPath,a=odf.OdfUtils,c=new core.Base64;odf.FontLoader=function(){this.loadFonts=function(b,c){for(var q=b.rootElement.fontFaceDecls;c.cssRules.length;)c.deleteRule(c.cssRules.length-1);if(q){var p={},n,g,h,d;if(q)for(q=l.getODFElementsWithXPath(q,"style:font-face[svg:font-face-src]",odf.Namespaces.lookupNamespaceURI),n=0;n text|list-item:first-child > :not(text|list):first-child:before',w+="{",w+="counter-increment: "+r+" 0;",w+="}",f(a,w));for(;p.counterIdStack.length>=q;)p.counterIdStack.pop();p.counterIdStack.push(r);u=p.contentRules[q.toString()]||"";for(w=1;w<=q;w+=1)u=u.replace(w+"webodf-listLevel",p.counterIdStack[w-1]);w='text|list[webodfhelper|counter-id="'+l+'"] > text|list-item > :not(text|list):first-child:before'; +w+="{";w+=u;w+="counter-increment: "+r+";";w+="}";f(a,w)}for(c=c.firstElementChild;c;)b(e,c,h,p),c=c.nextElementSibling}else p.continuedCounterIdStack=[]}var c=0,d="",e={};this.createCounterRules=function(a,d,f){var k=d.getAttributeNS(q,"id"),p=[];f&&(f=f.getAttributeNS("urn:webodf:names:helper","counter-id"),p=e[f].slice(0));a=new l(a,p);k?k="Y"+k:(c+=1,k="X"+c);b(k,d,0,a);e[k+"-level1-1"]=a.counterIdStack};this.initialiseCreatedCounters=function(){var b;b="office|document{"+("counter-reset: "+d+ +";");b+="}";f(a,b)}}var c=odf.Namespaces.fons,b=odf.Namespaces.stylens,k=odf.Namespaces.textns,q=odf.Namespaces.xmlns,p={1:"decimal",a:"lower-latin",A:"upper-latin",i:"lower-roman",I:"upper-roman"};odf.ListStyleToCss=function(){function n(a){var b=s.parseLength(a);return b?e.convert(b.value,b.unit,"px"):(runtime.log("Could not parse value '"+a+"'."),0)}function g(a){return a.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function h(a,b){var d;a&&(d=a.getAttributeNS(k,"style-name"));return d===b}function d(d, +e,c){e=e.getElementsByTagNameNS(k,"list");d=new a(d);var f,n,s,l,u,A,F={},B;for(B=0;B text|list-item > text|list",x-=1;x=t&&t.getAttributeNS(c,"text-align")||"left";switch(x){case "end":x="right";break;case "start":x="left"}"label-alignment"===I?(N=Q&&Q.getAttributeNS(c,"margin-left")||"0px",R=Q&&Q.getAttributeNS(c,"text-indent")||"0px",J=Q&&Q.getAttributeNS(k,"label-followed-by"),Q=n(N)):(N=t&&t.getAttributeNS(k,"space-before")||"0px",z=t&&t.getAttributeNS(k,"min-label-width")||"0px", +Y=t&&t.getAttributeNS(k,"min-label-distance")||"0px",Q=n(N)+n(z));t=q+" > text|list-item";t+="{";t+="margin-left: "+Q+"px;";t+="}";f(h,t);t=q+" > text|list-item > text|list";t+="{";t+="margin-left: "+-Q+"px;";t+="}";f(h,t);t=q+" > text|list-item > :not(text|list):first-child:before";t+="{";t+="text-align: "+x+";";t+="display: inline-block;";"label-alignment"===I?(t+="margin-left: "+R+";","listtab"===J&&(t+="padding-right: 0.2cm;")):(t+="min-width: "+z+";",t+="margin-left: "+(0===parseFloat(z)?"": +"-")+z+";",t+="padding-right: "+Y+";");t+="}";f(h,t)}e=e.nextElementSibling}});d(a,h,g)}}})();odf.LazyStyleProperties=function(f,l){var a={};this.value=function(c){var b;a.hasOwnProperty(c)?b=a[c]:(b=l[c](),void 0===b&&f&&(b=f.value(c)),a[c]=b);return b};this.reset=function(c){f=c;a={}}}; +odf.StyleParseUtils=function(){function f(a){var c,b;a=(a=/(-?[0-9]*[0-9][0-9]*(\.[0-9]*)?|0+\.[0-9]*[1-9][0-9]*|\.[0-9]*[1-9][0-9]*)((cm)|(mm)|(in)|(pt)|(pc)|(px))/.exec(a))?{value:parseFloat(a[1]),unit:a[3]}:null;b=a&&a.unit;"px"===b?c=a.value:"cm"===b?c=96*(a.value/2.54):"mm"===b?c=96*(a.value/25.4):"in"===b?c=96*a.value:"pt"===b?c=a.value/0.75:"pc"===b&&(c=16*a.value);return c}var l=odf.Namespaces.stylens;this.parseLength=f;this.parsePositiveLengthOrPercent=function(a,c,b){var k;a&&(k=parseFloat(a.substr(0, +a.indexOf("%"))),isNaN(k)&&(k=void 0));var q;void 0!==k?(b&&(q=b.value(c)),k=void 0===q?void 0:k*(q/100)):k=f(a);return k};this.getPropertiesElement=function(a,c,b){for(c=b?b.nextElementSibling:c.firstElementChild;null!==c&&(c.localName!==a||c.namespaceURI!==l);)c=c.nextElementSibling;return c};this.parseAttributeList=function(a){a&&(a=a.replace(/^\s*(.*?)\s*$/g,"$1"));return a&&0k.value&&(g="0.75pt"+m);m=g}else if(z.hasOwnProperty(c[1])){var g= +a,f=c[0],k=c[1],p=R.parseLength(m),n=void 0,s=void 0,q=void 0,r=void 0,q=void 0;if(p&&"%"===p.unit){n=p.value/100;s=l(g.parentNode);for(r="0";s;){if(q=x.getDirectChild(s,h,"paragraph-properties"))if(q=R.parseLength(q.getAttributeNS(f,k))){if("%"!==q.unit){r=q.value*n+q.unit;break}n*=q.value/100}s=l(s)}m=r}}c[2]&&(d+=c[2]+":"+m+";")}return d}function c(a,b,d,e){return b+b+d+d+e+e}function b(a,d){var e=[a],c=d.derivedStyles;Object.keys(c).forEach(function(a){a=b(a,c[a]);e=e.concat(a)});return e}function k(a, +d,e,c){function g(b,d){var e=[],c;b.forEach(function(a){h.forEach(function(b){e.push('draw|page[webodfhelper|page-style-name="'+b+'"] draw|frame[presentation|class="'+a+'"]')})});0v&&(b=v);for(c=Math.floor(b/a)*a;!e&&0<=c;)e=g[c],c-=a;for(e=e||y;e.nextBookmark&&e.nextBookmark.steps<= -b;)d.check(),e=e.nextBookmark;runtime.assert(-1===b||e.steps<=b,"Bookmark @"+q(e)+" at step "+e.steps+" exceeds requested step of "+b);return e}function b(b){b.previousBookmark&&(b.previousBookmark.nextBookmark=b.nextBookmark);b.nextBookmark&&(b.nextBookmark.previousBookmark=b.previousBookmark)}function e(b){for(var a,c=null;!c&&b&&b!==k;)(a=m(b))&&(c=u[a])&&c.node!==b&&(runtime.log("Cloned node detected. Creating new bookmark"),c=null,b.removeAttributeNS(n,"nodeId")),b=b.parentNode;return c}var n= -"urn:webodf:names:steps",g={},u={},t=core.DomUtils,y,v,s=Node.DOCUMENT_POSITION_FOLLOWING,x=Node.DOCUMENT_POSITION_PRECEDING,w;this.updateBookmark=function(e,d){var f,h=Math.ceil(e/a)*a,n,p,q;if(void 0!==v&&vn.steps)g[h]=p;w()};this.setToClosestStep=function(b,a){var c;w();c=r(b);c.setIteratorPosition(a); -return c.steps};this.setToClosestDomPoint=function(b,a,c){var d,f;w();if(b===k&&0===a)d=y;else if(b===k&&a===k.childNodes.length)for(f in d=y,g)g.hasOwnProperty(f)&&(b=g[f],b.steps>d.steps&&(d=b));else if(d=e(b.childNodes.item(a)||b),!d)for(c.setUnfilteredPosition(b,a);!d&&c.previousNode();)d=e(c.getCurrentNode());d=d||y;void 0!==v&&d.steps>v&&(d=r(v));d.setIteratorPosition(c);return d.steps};this.damageCacheAfterStep=function(b){0>b&&(b=-1);void 0===v?v=b:bb)throw new RangeError("Requested steps is negative ("+ -b+")");q();for(d=l.setToClosestStep(b,e);db.comparePoints(m,0,d,g),d=m,g=g?0:m.childNodes.length);e.setUnfilteredPosition(d,g);p(e,f)||e.setUnfilteredPosition(d,g);f=e.container();g=e.unfilteredDomOffset(); -d=l.setToClosestDomPoint(f,g,e);if(0>b.comparePoints(e.container(),e.unfilteredDomOffset(),f,g))return 0=l.textNode.length?null:l.textNode.splitText(l.offset));for(e=l.textNode;e!==b;){e=e.parentNode;n=e.cloneNode(!1);g&&n.appendChild(g);if(u)for(;u&&u.nextSibling;)n.appendChild(u.nextSibling);else for(;e.firstChild;)n.appendChild(e.firstChild);e.parentNode.insertBefore(n,e.nextSibling);u=e;g=n}q.isListItem(g)&&(g=g.childNodes.item(0));h?g.setAttributeNS(p,"text:style-name",h):g.removeAttributeNS(p,"style-name");0===l.textNode.length&& -l.textNode.parentNode.removeChild(l.textNode);a.emit(ops.OdtDocument.signalStepsInserted,{position:d});t&&c&&(a.moveCursor(f,d+1,0),a.emit(ops.Document.signalCursorMoved,t));a.fixCursorPositions();a.getOdfCanvas().refreshSize();a.emit(ops.OdtDocument.signalParagraphChanged,{paragraphElement:r,memberId:f,timeStamp:k});a.emit(ops.OdtDocument.signalParagraphChanged,{paragraphElement:g,memberId:f,timeStamp:k});a.getOdfCanvas().rerenderAnnotations();return!0};this.spec=function(){return{optype:"SplitParagraph", -memberid:f,timestamp:k,position:d,sourceParagraphPosition:a,paragraphStyleName:h,moveCursor:c}}};ops.OpUpdateMember=function(){function f(a){var c="//dc:creator[@editinfo:memberid='"+k+"']";a=xmldom.XPath.getODFElementsWithXPath(a.getRootNode(),c,function(a){return"editinfo"===a?"urn:webodf:names:editinfo":odf.Namespaces.lookupNamespaceURI(a)});for(c=0;cv&&(b=v);for(d=Math.floor(b/a)*a;!e&&0<=d;)e=m[d],d-=a;for(e=e||y;e.nextBookmark&&e.nextBookmark.steps<= +b;)c.check(),e=e.nextBookmark;runtime.assert(-1===b||e.steps<=b,"Bookmark @"+q(e)+" at step "+e.steps+" exceeds requested step of "+b);return e}function d(a){a.previousBookmark&&(a.previousBookmark.nextBookmark=a.nextBookmark);a.nextBookmark&&(a.nextBookmark.previousBookmark=a.previousBookmark)}function e(a){for(var b,d=null;!d&&a&&a!==l;)(b=n(a))&&(d=x[b])&&d.node!==a&&(runtime.log("Cloned node detected. Creating new bookmark"),d=null,a.removeAttributeNS(s,"nodeId")),a=a.parentNode;return d}var s= +"urn:webodf:names:steps",m={},x={},t=core.DomUtils,y,v,r=Node.DOCUMENT_POSITION_FOLLOWING,w=Node.DOCUMENT_POSITION_PRECEDING,u;this.updateBookmark=function(e,c){var f,k=Math.ceil(e/a)*a,p,s,q;if(void 0!==v&&vp.steps)m[k]=s;u()};this.setToClosestStep=function(a,b){var d;u();d=h(a);d.setIteratorPosition(b); +return d.steps};this.setToClosestDomPoint=function(a,b,d){var c,g;u();if(a===l&&0===b)c=y;else if(a===l&&b===l.childNodes.length)for(g in c=y,m)m.hasOwnProperty(g)&&(a=m[g],a.steps>c.steps&&(c=a));else if(c=e(a.childNodes.item(b)||a),!c)for(d.setUnfilteredPosition(a,b);!c&&d.previousNode();)c=e(d.getCurrentNode());c=c||y;void 0!==v&&c.steps>v&&(c=h(v));c.setIteratorPosition(d);return c.steps};this.damageCacheAfterStep=function(a){0>a&&(a=-1);void 0===v?v=a:ad)throw new RangeError("Requested steps is negative ("+d+")");for(c=q.setToClosestStep(d,l);cn.comparePoints(f,0,d,c),d=f,c=c?0:f.childNodes.length);l.setUnfilteredPosition(d,c);k(l,m)||l.setUnfilteredPosition(d,c);m=l.container();c=l.unfilteredDomOffset();d=q.setToClosestDomPoint(m,c,l);if(0>n.comparePoints(l.container(),l.unfilteredDomOffset(),m,c))return 0=g.textNode.length?null:g.textNode.splitText(g.offset));for(e=g.textNode;e!==d;){e=e.parentNode;s=e.cloneNode(!1);m&&s.appendChild(m);if(x)for(;x&&x.nextSibling;)s.appendChild(x.nextSibling);else for(;e.firstChild;)s.appendChild(e.firstChild);e.parentNode.insertBefore(s,e.nextSibling);x=e;m=s}q.isListItem(m)&&(m=m.childNodes.item(0));k?m.setAttributeNS(p,"text:style-name",k):m.removeAttributeNS(p,"style-name");0===g.textNode.length&& +g.textNode.parentNode.removeChild(g.textNode);a.emit(ops.OdtDocument.signalStepsInserted,{position:c});t&&b&&(a.moveCursor(f,c+1,0),a.emit(ops.Document.signalCursorMoved,t));a.fixCursorPositions();a.getOdfCanvas().refreshSize();a.emit(ops.OdtDocument.signalParagraphChanged,{paragraphElement:h,memberId:f,timeStamp:l});a.emit(ops.OdtDocument.signalParagraphChanged,{paragraphElement:m,memberId:f,timeStamp:l});a.getOdfCanvas().rerenderAnnotations();return!0};this.spec=function(){return{optype:"SplitParagraph", +memberid:f,timestamp:l,position:c,sourceParagraphPosition:a,paragraphStyleName:k,moveCursor:b}}};ops.OpUpdateMember=function(){function f(a){var b="//dc:creator[@editinfo:memberid='"+l+"']";a=xmldom.XPath.getODFElementsWithXPath(a.getRootNode(),b,function(a){return"editinfo"===a?"urn:webodf:names:editinfo":odf.Namespaces.lookupNamespaceURI(a)});for(b=0;b=h.width&&(h=null),f.detach();else if(k.isCharacterElement(c.container)||k.isCharacterFrame(c.container))h=d.getBoundingClientRect(c.container); -return h}var k=odf.OdfUtils,a=new odf.StepUtils,d=core.DomUtils,c=core.StepDirection.NEXT,h=gui.StepInfo.VisualDirection.LEFT_TO_RIGHT,q=gui.StepInfo.VisualDirection.RIGHT_TO_LEFT;this.getContentRect=f;this.moveToFilteredStep=function(a,d,k){function r(b,a){a.process(v,g,u)&&(b=!0,!t&&a.token&&(t=a.token));return b}var b=d===c,e,n,g,u,t,y=a.snapshot();e=!1;var v;do e=f(a),v={token:a.snapshot(),container:a.container,offset:a.offset,direction:d,visualDirection:d===c?h:q},n=a.nextStep()?f(a):null,a.restore(v.token), -b?(g=e,u=n):(g=n,u=e),e=k.reduce(r,!1);while(!e&&a.advanceStep(d));e||k.forEach(function(b){!t&&b.token&&(t=b.token)});a.restore(t||y);return Boolean(t)}};gui.Caret=function(f,k,a,d){function c(){r.style.opacity="0"===r.style.opacity?"1":"0";x.trigger()}function h(){g.selectNodeContents(n);return g.getBoundingClientRect()}function q(){Object.keys(C).forEach(function(b){F[b]=C[b]})}function p(){if(!1===C.isShown||f.getSelectionType()!==ops.OdtCursor.RangeSelection||!d&&!f.getSelectedRange().collapsed)C.visibility="hidden",r.style.visibility="hidden",x.cancel();else if(C.visibility="visible",r.style.visibility="visible",!1===C.isFocused)r.style.opacity= -"1",x.cancel();else{if(w||F.visibility!==C.visibility)r.style.opacity="1",x.cancel();x.trigger()}if(I||B){var a;a=f.getNode();var c,g,n=t.getBoundingClientRect(u.getSizer()),m=!1,p=0;a.removeAttributeNS("urn:webodf:names:cursor","caret-sizer-active");if(0a.height&&(a={top:a.top-(8-a.height)/2,height:8,right:a.right});l.style.height=a.height+"px";l.style.top=a.top+"px";l.style.left=a.right- -a.width+"px";l.style.width=a.width?a.width+"px":"";e&&(a=runtime.getWindow().getComputedStyle(f.getNode(),null),a.font?e.style.font=a.font:(e.style.fontStyle=a.fontStyle,e.style.fontVariant=a.fontVariant,e.style.fontWeight=a.fontWeight,e.style.fontSize=a.fontSize,e.style.lineHeight=a.lineHeight,e.style.fontFamily=a.fontFamily))}C.isShown&&B&&k.scrollIntoView(r.getBoundingClientRect());F.isFocused!==C.isFocused&&b.markAsFocussed(C.isFocused);q();I=B=w=!1}function m(b){l.parentNode.removeChild(l);n.parentNode.removeChild(n); -b()}var l,r,b,e,n,g,u=f.getDocument().getCanvas(),t=core.DomUtils,y=new gui.GuiStepUtils,v,s,x,w=!1,B=!1,I=!1,C={isFocused:!1,isShown:!0,visibility:"hidden"},F={isFocused:!C.isFocused,isShown:!C.isShown,visibility:"hidden"};this.handleUpdate=function(){I=!0;s.trigger()};this.refreshCursorBlinking=function(){w=!0;s.trigger()};this.setFocus=function(){C.isFocused=!0;s.trigger()};this.removeFocus=function(){C.isFocused=!1;s.trigger()};this.show=function(){C.isShown=!0;s.trigger()};this.hide=function(){C.isShown= -!1;s.trigger()};this.setAvatarImageUrl=function(a){b.setImageUrl(a)};this.setColor=function(a){r.style.borderColor=a;b.setColor(a)};this.getCursor=function(){return f};this.getFocusElement=function(){return r};this.toggleHandleVisibility=function(){b.isVisible()?b.hide():b.show()};this.showHandle=function(){b.show()};this.hideHandle=function(){b.hide()};this.setOverlayElement=function(b){e=b;l.appendChild(b);I=!0;s.trigger()};this.ensureVisible=function(){B=!0;s.trigger()};this.getBoundingClientRect= -function(){return t.getBoundingClientRect(l)};this.destroy=function(a){core.Async.destroyAll([s.destroy,x.destroy,b.destroy,m],a)};(function(){var e=f.getDocument(),d=[e.createRootFilter(f.getMemberId()),e.getPositionFilter()],h=e.getDOMDocument();g=h.createRange();n=h.createElement("span");n.className="webodf-caretSizer";n.textContent="|";f.getNode().appendChild(n);l=h.createElement("div");l.setAttributeNS("urn:webodf:names:editinfo","editinfo:memberid",f.getMemberId());l.className="webodf-caretOverlay"; -r=h.createElement("div");r.className="caret";l.appendChild(r);b=new gui.Avatar(l,a);u.getSizer().appendChild(l);v=e.createStepIterator(f.getNode(),0,d,e.getRootNode());s=core.Task.createRedrawTask(p);x=core.Task.createTimeoutTask(c,500);s.triggerImmediate()})()};odf.TextSerializer=function(){function f(d){var c="",h=k.filter?k.filter.acceptNode(d):NodeFilter.FILTER_ACCEPT,q=d.nodeType,p;if((h===NodeFilter.FILTER_ACCEPT||h===NodeFilter.FILTER_SKIP)&&a.isTextContentContainingNode(d))for(p=d.firstChild;p;)c+=f(p),p=p.nextSibling;h===NodeFilter.FILTER_ACCEPT&&(q===Node.ELEMENT_NODE&&a.isParagraph(d)?c+="\n":q===Node.TEXT_NODE&&d.textContent&&(c+=d.textContent));return c}var k=this,a=odf.OdfUtils;this.filter=null;this.writeToString=function(a){if(!a)return""; -a=f(a);"\n"===a[a.length-1]&&(a=a.substr(0,a.length-1));return a}};gui.MimeDataExporter=function(){var f;this.exportRangeToDataTransfer=function(k,a){var d;d=a.startContainer.ownerDocument.createElement("span");d.appendChild(a.cloneContents());d=f.writeToString(d);try{k.setData("text/plain",d)}catch(c){k.setData("Text",d)}};f=new odf.TextSerializer;f.filter=new odf.OdfNodeFilter};gui.Clipboard=function(f){this.setDataFromRange=function(k,a){var d,c=k.clipboardData;d=runtime.getWindow();!c&&d&&(c=d.clipboardData);c?(d=!0,f.exportRangeToDataTransfer(c,a),k.preventDefault()):d=!1;return d}};gui.SessionContext=function(f,k){var a=f.getOdtDocument(),d=odf.OdfUtils;this.isLocalCursorWithinOwnAnnotation=function(){var c=a.getCursor(k),f;if(!c)return!1;f=c&&c.getNode();c=a.getMember(k).getProperties().fullName;return(f=d.getParentAnnotation(f,a.getRootNode()))&&d.getAnnotationCreator(f)===c?!0:!1}};gui.StyleSummary=function(f){function k(a,d){var k=a+"|"+d,m;c.hasOwnProperty(k)||(m=[],f.forEach(function(c){c=(c=c.styleProperties[a])&&c[d];-1===m.indexOf(c)&&m.push(c)}),c[k]=m);return c[k]}function a(a,c,d){return function(){var f=k(a,c);return d.length>=f.length&&f.every(function(a){return-1!==d.indexOf(a)})}}function d(a,c){var d=k(a,c);return 1===d.length?d[0]:void 0}var c={};this.getPropertyValues=k;this.getCommonValue=d;this.isBold=a("style:text-properties","fo:font-weight",["bold"]);this.isItalic= -a("style:text-properties","fo:font-style",["italic"]);this.hasUnderline=a("style:text-properties","style:text-underline-style",["solid"]);this.hasStrikeThrough=a("style:text-properties","style:text-line-through-style",["solid"]);this.fontSize=function(){var a=d("style:text-properties","fo:font-size");return a&&parseFloat(a)};this.fontName=function(){return d("style:text-properties","style:font-name")};this.isAlignedLeft=a("style:paragraph-properties","fo:text-align",["left","start"]);this.isAlignedCenter= +RemoveHyperlink:f(ops.OpRemoveHyperlink)}};ops.OperationRouter=function(){};ops.OperationRouter.prototype.setOperationFactory=function(f){};ops.OperationRouter.prototype.setPlaybackFunction=function(f){};ops.OperationRouter.prototype.push=function(f){};ops.OperationRouter.prototype.close=function(f){};ops.OperationRouter.prototype.subscribe=function(f,l){};ops.OperationRouter.prototype.unsubscribe=function(f,l){};ops.OperationRouter.prototype.hasLocalUnsyncedOps=function(){};ops.OperationRouter.prototype.hasSessionHostConnection=function(){}; +ops.OperationRouter.signalProcessingBatchStart="router/batchstart";ops.OperationRouter.signalProcessingBatchEnd="router/batchend";ops.TrivialOperationRouter=function(){var f=new core.EventNotifier([ops.OperationRouter.signalProcessingBatchStart,ops.OperationRouter.signalProcessingBatchEnd]),l,a,c=0;this.setOperationFactory=function(a){l=a};this.setPlaybackFunction=function(b){a=b};this.push=function(b){c+=1;f.emit(ops.OperationRouter.signalProcessingBatchStart,{});b.forEach(function(b){b=b.spec();b.timestamp=Date.now();b=l.create(b);b.group="g"+c;a(b)});f.emit(ops.OperationRouter.signalProcessingBatchEnd,{})};this.close=function(a){a()}; +this.subscribe=function(a,c){f.subscribe(a,c)};this.unsubscribe=function(a,c){f.unsubscribe(a,c)};this.hasLocalUnsyncedOps=function(){return!1};this.hasSessionHostConnection=function(){return!0}};ops.Session=function(f){function l(a){b.emit(ops.OdtDocument.signalProcessingBatchStart,a)}function a(a){b.emit(ops.OdtDocument.signalProcessingBatchEnd,a)}var c=new ops.OperationFactory,b=new ops.OdtDocument(f),k=null;this.setOperationFactory=function(a){c=a;k&&k.setOperationFactory(c)};this.setOperationRouter=function(f){k&&(k.unsubscribe(ops.OperationRouter.signalProcessingBatchStart,l),k.unsubscribe(ops.OperationRouter.signalProcessingBatchEnd,a));k=f;k.subscribe(ops.OperationRouter.signalProcessingBatchStart, +l);k.subscribe(ops.OperationRouter.signalProcessingBatchEnd,a);f.setPlaybackFunction(function(a){b.emit(ops.OdtDocument.signalOperationStart,a);return a.execute(b)?(b.emit(ops.OdtDocument.signalOperationEnd,a),!0):!1});f.setOperationFactory(c)};this.getOperationFactory=function(){return c};this.getOdtDocument=function(){return b};this.enqueue=function(a){k.push(a)};this.close=function(a){k.close(function(c){c?a(c):b.close(a)})};this.destroy=function(a){b.destroy(a)};this.setOperationRouter(new ops.TrivialOperationRouter)};gui.AnnotationController=function(f,l,a){function c(){var b=p.getCursor(a),b=b&&b.getNode(),d=!1;b&&(d=!h.isWithinAnnotation(b,p.getRootNode()));d!==n&&(n=d,g.emit(gui.AnnotationController.annotatableChanged,n))}function b(b){b.getMemberId()===a&&c()}function k(b){b===a&&c()}function q(b){b.getMemberId()===a&&c()}var p=f.getOdtDocument(),n=!1,g=new core.EventNotifier([gui.AnnotationController.annotatableChanged]),h=odf.OdfUtils,d=core.StepDirection.NEXT;this.isAnnotatable=function(){return n};this.addAnnotation= +function(){var b=new ops.OpAddAnnotation,d=p.getCursorSelection(a),c=d.length,d=d.position;n&&(0===c?c=void 0:(d=0<=c?d:d+c,c=Math.abs(c)),b.init({memberid:a,position:d,length:c,name:a+Date.now()}),f.enqueue([b]))};this.removeAnnotation=function(b){var c,g;c=p.getMember(a).getProperties().fullName;if(!0!==l.getState(gui.CommonConstraints.EDIT.ANNOTATIONS.ONLY_DELETE_OWN)||c===h.getAnnotationCreator(b))c=p.convertDomPointToCursorStep(b,0,d),g=p.convertDomPointToCursorStep(b,b.childNodes.length),b= +new ops.OpRemoveAnnotation,b.init({memberid:a,position:c,length:g-c}),g=new ops.OpMoveCursor,g.init({memberid:a,position:0=g.width&&(g=null),f.detach();else if(l.isCharacterElement(b.container)||l.isCharacterFrame(b.container))g=c.getBoundingClientRect(b.container); +return g}var l=odf.OdfUtils,a=new odf.StepUtils,c=core.DomUtils,b=core.StepDirection.NEXT,k=gui.StepInfo.VisualDirection.LEFT_TO_RIGHT,q=gui.StepInfo.VisualDirection.RIGHT_TO_LEFT;this.getContentRect=f;this.moveToFilteredStep=function(a,c,g){function h(a,b){b.process(v,m,x)&&(a=!0,!t&&b.token&&(t=b.token));return a}var d=c===b,e,l,m,x,t,y=a.snapshot();e=!1;var v;do e=f(a),v={token:a.snapshot(),container:a.container,offset:a.offset,direction:c,visualDirection:c===b?k:q},l=a.nextStep()?f(a):null,a.restore(v.token), +d?(m=e,x=l):(m=l,x=e),e=g.reduce(h,!1);while(!e&&a.advanceStep(c));e||g.forEach(function(a){!t&&a.token&&(t=a.token)});a.restore(t||y);return Boolean(t)}};gui.Caret=function(f,l,a,c){function b(){h.style.opacity="0"===h.style.opacity?"1":"0";w.trigger()}function k(){m.selectNodeContents(s);return m.getBoundingClientRect()}function q(){Object.keys(B).forEach(function(a){E[a]=B[a]})}function p(){if(!1===B.isShown||f.getSelectionType()!==ops.OdtCursor.RangeSelection||!c&&!f.getSelectedRange().collapsed)B.visibility="hidden",h.style.visibility="hidden",w.cancel();else if(B.visibility="visible",h.style.visibility="visible",!1===B.isFocused)h.style.opacity= +"1",w.cancel();else{if(u||E.visibility!==B.visibility)h.style.opacity="1",w.cancel();w.trigger()}if(F||A){var a;a=f.getNode();var b,m,p=t.getBoundingClientRect(x.getSizer()),n=!1,s=0;a.removeAttributeNS("urn:webodf:names:cursor","caret-sizer-active");if(0a.height&&(a={top:a.top-(8-a.height)/2,height:8,right:a.right});g.style.height=a.height+"px";g.style.top=a.top+"px";g.style.left=a.right- +a.width+"px";g.style.width=a.width?a.width+"px":"";e&&(a=runtime.getWindow().getComputedStyle(f.getNode(),null),a.font?e.style.font=a.font:(e.style.fontStyle=a.fontStyle,e.style.fontVariant=a.fontVariant,e.style.fontWeight=a.fontWeight,e.style.fontSize=a.fontSize,e.style.lineHeight=a.lineHeight,e.style.fontFamily=a.fontFamily))}B.isShown&&A&&l.scrollIntoView(h.getBoundingClientRect());E.isFocused!==B.isFocused&&d.markAsFocussed(B.isFocused);q();F=A=u=!1}function n(a){g.parentNode.removeChild(g);s.parentNode.removeChild(s); +a()}var g,h,d,e,s,m,x=f.getDocument().getCanvas(),t=core.DomUtils,y=new gui.GuiStepUtils,v,r,w,u=!1,A=!1,F=!1,B={isFocused:!1,isShown:!0,visibility:"hidden"},E={isFocused:!B.isFocused,isShown:!B.isShown,visibility:"hidden"};this.handleUpdate=function(){F=!0;r.trigger()};this.refreshCursorBlinking=function(){u=!0;r.trigger()};this.setFocus=function(){B.isFocused=!0;r.trigger()};this.removeFocus=function(){B.isFocused=!1;r.trigger()};this.show=function(){B.isShown=!0;r.trigger()};this.hide=function(){B.isShown= +!1;r.trigger()};this.setAvatarImageUrl=function(a){d.setImageUrl(a)};this.setColor=function(a){h.style.borderColor=a;d.setColor(a)};this.getCursor=function(){return f};this.getFocusElement=function(){return h};this.toggleHandleVisibility=function(){d.isVisible()?d.hide():d.show()};this.showHandle=function(){d.show()};this.hideHandle=function(){d.hide()};this.setOverlayElement=function(a){e=a;g.appendChild(a);F=!0;r.trigger()};this.ensureVisible=function(){A=!0;r.trigger()};this.getBoundingClientRect= +function(){return t.getBoundingClientRect(g)};this.destroy=function(a){core.Async.destroyAll([r.destroy,w.destroy,d.destroy,n],a)};(function(){var e=f.getDocument(),c=[e.createRootFilter(f.getMemberId()),e.getPositionFilter()],k=e.getDOMDocument();m=k.createRange();s=k.createElement("span");s.className="webodf-caretSizer";s.textContent="|";f.getNode().appendChild(s);g=k.createElement("div");g.setAttributeNS("urn:webodf:names:editinfo","editinfo:memberid",f.getMemberId());g.className="webodf-caretOverlay"; +h=k.createElement("div");h.className="caret";g.appendChild(h);d=new gui.Avatar(g,a);x.getSizer().appendChild(g);v=e.createStepIterator(f.getNode(),0,c,e.getRootNode());r=core.Task.createRedrawTask(p);w=core.Task.createTimeoutTask(b,500);r.triggerImmediate()})()};odf.TextSerializer=function(){function f(c){var b="",k=l.filter?l.filter.acceptNode(c):NodeFilter.FILTER_ACCEPT,q=c.nodeType,p;if((k===NodeFilter.FILTER_ACCEPT||k===NodeFilter.FILTER_SKIP)&&a.isTextContentContainingNode(c))for(p=c.firstChild;p;)b+=f(p),p=p.nextSibling;k===NodeFilter.FILTER_ACCEPT&&(q===Node.ELEMENT_NODE&&a.isParagraph(c)?b+="\n":q===Node.TEXT_NODE&&c.textContent&&(b+=c.textContent));return b}var l=this,a=odf.OdfUtils;this.filter=null;this.writeToString=function(a){if(!a)return""; +a=f(a);"\n"===a[a.length-1]&&(a=a.substr(0,a.length-1));return a}};gui.MimeDataExporter=function(){var f;this.exportRangeToDataTransfer=function(l,a){var c;c=a.startContainer.ownerDocument.createElement("span");c.appendChild(a.cloneContents());c=f.writeToString(c);try{l.setData("text/plain",c)}catch(b){l.setData("Text",c)}};f=new odf.TextSerializer;f.filter=new odf.OdfNodeFilter};gui.Clipboard=function(f){this.setDataFromRange=function(l,a){var c,b=l.clipboardData;c=runtime.getWindow();!b&&c&&(b=c.clipboardData);b?(c=!0,f.exportRangeToDataTransfer(b,a),l.preventDefault()):c=!1;return c}};gui.SessionContext=function(f,l){var a=f.getOdtDocument(),c=odf.OdfUtils;this.isLocalCursorWithinOwnAnnotation=function(){var b=a.getCursor(l),f;if(!b)return!1;f=b&&b.getNode();b=a.getMember(l).getProperties().fullName;return(f=c.getParentAnnotation(f,a.getRootNode()))&&c.getAnnotationCreator(f)===b?!0:!1}};gui.StyleSummary=function(f){function l(a,c){var p=a+"|"+c,l;b.hasOwnProperty(p)||(l=[],f.forEach(function(b){b=(b=b.styleProperties[a])&&b[c];-1===l.indexOf(b)&&l.push(b)}),b[p]=l);return b[p]}function a(a,b,c){return function(){var f=l(a,b);return c.length>=f.length&&f.every(function(a){return-1!==c.indexOf(a)})}}function c(a,b){var c=l(a,b);return 1===c.length?c[0]:void 0}var b={};this.getPropertyValues=l;this.getCommonValue=c;this.isBold=a("style:text-properties","fo:font-weight",["bold"]);this.isItalic= +a("style:text-properties","fo:font-style",["italic"]);this.hasUnderline=a("style:text-properties","style:text-underline-style",["solid"]);this.hasStrikeThrough=a("style:text-properties","style:text-line-through-style",["solid"]);this.fontSize=function(){var a=c("style:text-properties","fo:font-size");return a&&parseFloat(a)};this.fontName=function(){return c("style:text-properties","style:font-name")};this.isAlignedLeft=a("style:paragraph-properties","fo:text-align",["left","start"]);this.isAlignedCenter= a("style:paragraph-properties","fo:text-align",["center"]);this.isAlignedRight=a("style:paragraph-properties","fo:text-align",["right","end"]);this.isAlignedJustified=a("style:paragraph-properties","fo:text-align",["justify"]);this.text={isBold:this.isBold,isItalic:this.isItalic,hasUnderline:this.hasUnderline,hasStrikeThrough:this.hasStrikeThrough,fontSize:this.fontSize,fontName:this.fontName};this.paragraph={isAlignedLeft:this.isAlignedLeft,isAlignedCenter:this.isAlignedCenter,isAlignedRight:this.isAlignedRight, -isAlignedJustified:this.isAlignedJustified}};gui.DirectFormattingController=function(f,k,a,d,c,h,q){function p(){return V.value().styleSummary}function m(){return V.value().enabledFeatures}function l(b){var a;b.collapsed?(a=b.startContainer,a.hasChildNodes()&&b.startOffsetb.clientWidth||b.scrollHeight>b.clientHeight)&&a.push(new r(b)),b=b.parentNode;a.push(new l(s));return a}function v(){var b; -g()||(b=y(C),t(),C.focus(),b.forEach(function(b){b.restore()}))}var s=runtime.getWindow(),x={beforecut:!0,beforepaste:!0,longpress:!0,drag:!0,dragstop:!0},w={mousedown:!0,mouseup:!0,focus:!0},B={},I={},C,F=f.getCanvas().getElement(),J=this,N={};this.addFilter=function(a,c){b(a,!0).filters.push(c)};this.removeFilter=function(a,c){var e=b(a,!0),d=e.filters.indexOf(c);-1!==d&&e.filters.splice(d,1)};this.subscribe=e;this.unsubscribe=n;this.hasFocus=g;this.focus=v;this.getEventTrap=function(){return C}; -this.setEditing=function(b){var a=g();a&&C.blur();b?C.removeAttribute("readOnly"):C.setAttribute("readOnly","true");a&&v()};this.destroy=function(b){n("touchstart",m);Object.keys(N).forEach(function(b){d(parseInt(b,10))});N.length=0;Object.keys(B).forEach(function(b){B[b].destroy()});B={};n("mousedown",u);n("mouseup",t);n("contextmenu",t);Object.keys(I).forEach(function(b){I[b].destroy()});I={};C.parentNode.removeChild(C);b()};(function(){var b=f.getOdfCanvas().getSizer(),c=b.ownerDocument;runtime.assert(Boolean(s), -"EventManager requires a window object to operate correctly");C=c.createElement("textarea");C.id="eventTrap";C.setAttribute("tabindex","-1");C.setAttribute("readOnly","true");C.setAttribute("rows","1");b.appendChild(C);e("mousedown",u);e("mouseup",t);e("contextmenu",t);B.longpress=new a("longpress",["touchstart","touchmove","touchend"],h);B.drag=new a("drag",["touchstart","touchmove","touchend"],q);B.dragstop=new a("dragstop",["drag","touchend"],p);e("touchstart",m)})()};gui.IOSSafariSupport=function(f){function k(){a.innerHeight!==a.outerHeight&&(d.style.display="none",runtime.requestAnimationFrame(function(){d.style.display="block"}))}var a=runtime.getWindow(),d=f.getEventTrap();this.destroy=function(a){f.unsubscribe("focus",k);d.removeAttribute("autocapitalize");d.style.WebkitTransform="";a()};f.subscribe("focus",k);d.setAttribute("autocapitalize","off");d.style.WebkitTransform="translateX(-10000px)"};gui.HyperlinkController=function(f,k,a,d){function c(){var c=!0;!0===k.getState(gui.CommonConstraints.EDIT.REVIEW_MODE)&&(c=a.isLocalCursorWithinOwnAnnotation());c!==l&&(l=c,m.emit(gui.HyperlinkController.enabledChanged,l))}function h(a){a.getMemberId()===d&&c()}var q=odf.OdfUtils,p=f.getOdtDocument(),m=new core.EventNotifier([gui.HyperlinkController.enabledChanged]),l=!1;this.isEnabled=function(){return l};this.subscribe=function(a,b){m.subscribe(a,b)};this.unsubscribe=function(a,b){m.unsubscribe(a, -b)};this.addHyperlink=function(a,b){if(l){var c=p.getCursorSelection(d),h=new ops.OpApplyHyperlink,g=[];if(0===c.length||b)b=b||a,h=new ops.OpInsertText,h.init({memberid:d,position:c.position,text:b}),c.length=b.length,g.push(h);h=new ops.OpApplyHyperlink;h.init({memberid:d,position:c.position,length:c.length,hyperlink:a});g.push(h);f.enqueue(g)}};this.removeHyperlinks=function(){if(l){var a=p.createPositionIterator(p.getRootNode()),b=p.getCursor(d).getSelectedRange(),c=q.getHyperlinkElements(b), -h=b.collapsed&&1===c.length,g=p.getDOMDocument().createRange(),k=[],m,y;0!==c.length&&(c.forEach(function(b){g.selectNodeContents(b);m=p.convertDomToCursorRange({anchorNode:g.startContainer,anchorOffset:g.startOffset,focusNode:g.endContainer,focusOffset:g.endOffset});y=new ops.OpRemoveHyperlink;y.init({memberid:d,position:m.position,length:m.length});k.push(y)}),h||(h=c[0],-1===b.comparePoint(h,0)&&(g.setStart(h,0),g.setEnd(b.startContainer,b.startOffset),m=p.convertDomToCursorRange({anchorNode:g.startContainer, -anchorOffset:g.startOffset,focusNode:g.endContainer,focusOffset:g.endOffset}),0h.width&&(q=h.width/k.width);k.height>h.height&&(s=h.height/k.height);h=Math.min(q,s);k={width:k.width*h,height:k.height* -h}}h=k.width+"px";k=k.height+"px";var x=l.getOdfCanvas().odfContainer().rootElement.styles,q=a.toLowerCase(),s=p.hasOwnProperty(q)?p[q]:null,w,q=[];runtime.assert(null!==s,"Image type is not supported: "+a);s="Pictures/"+c.generateImageName()+s;w=new ops.OpSetBlob;w.init({memberid:d,filename:s,mimetype:a,content:e});q.push(w);b.getStyleElement("Graphics","graphic",[x])||(a=new ops.OpAddStyle,a.init({memberid:d,styleName:"Graphics",styleFamily:"graphic",isAutomaticStyle:!1,setProperties:{"style:graphic-properties":{"text:anchor-type":"paragraph", -"svg:x":"0cm","svg:y":"0cm","style:wrap":"dynamic","style:number-wrapped-paragraphs":"no-limit","style:wrap-contour":"false","style:vertical-pos":"top","style:vertical-rel":"paragraph","style:horizontal-pos":"center","style:horizontal-rel":"paragraph"}}}),q.push(a));a=c.generateStyleName();e=new ops.OpAddStyle;e.init({memberid:d,styleName:a,styleFamily:"graphic",isAutomaticStyle:!0,setProperties:{"style:parent-style-name":"Graphics","style:graphic-properties":{"style:vertical-pos":"top","style:vertical-rel":"baseline", -"style:horizontal-pos":"center","style:horizontal-rel":"paragraph","fo:background-color":"transparent","style:background-transparency":"100%","style:shadow":"none","style:mirror":"none","fo:clip":"rect(0cm, 0cm, 0cm, 0cm)","draw:luminance":"0%","draw:contrast":"0%","draw:red":"0%","draw:green":"0%","draw:blue":"0%","draw:gamma":"100%","draw:color-inversion":"false","draw:image-opacity":"100%","draw:color-mode":"standard"}}});q.push(e);w=new ops.OpInsertImage;w.init({memberid:d,position:l.getCursorPosition(d), -filename:s,frameWidth:h,frameHeight:k,frameStyleName:a,frameName:c.generateFrameName()});q.push(w);f.enqueue(q)}};this.destroy=function(b){l.unsubscribe(ops.Document.signalCursorMoved,q);k.unsubscribe(gui.CommonConstraints.EDIT.REVIEW_MODE,h);b()};l.subscribe(ops.Document.signalCursorMoved,q);k.subscribe(gui.CommonConstraints.EDIT.REVIEW_MODE,h);h()};gui.ImageController.enabledChanged="enabled/changed";gui.ImageSelector=function(f){function k(){var a=f.getSizer(),h=c.createElement("div");h.id="imageSelector";h.style.borderWidth="1px";a.appendChild(h);d.forEach(function(a){var d=c.createElement("div");d.className=a;h.appendChild(d)});return h}var a=odf.Namespaces.svgns,d="topLeft topRight bottomRight bottomLeft topMiddle rightMiddle bottomMiddle leftMiddle".split(" "),c=f.getElement().ownerDocument,h=!1;this.select=function(d){var p,m,l=c.getElementById("imageSelector");l||(l=k());h=!0;p=l.parentNode; -m=d.getBoundingClientRect();var r=p.getBoundingClientRect(),b=f.getZoomLevel();p=(m.left-r.left)/b-1;m=(m.top-r.top)/b-1;l.style.display="block";l.style.left=p+"px";l.style.top=m+"px";l.style.width=d.getAttributeNS(a,"width");l.style.height=d.getAttributeNS(a,"height")};this.clearSelection=function(){var a;h&&(a=c.getElementById("imageSelector"))&&(a.style.display="none");h=!1};this.isSelectorElement=function(a){var d=c.getElementById("imageSelector");return d?a===d||a.parentNode===d:!1}};(function(){function f(f){function a(a){q=a.which&&String.fromCharCode(a.which)===h;h=void 0;return!1===q}function d(){q=!1}function c(a){h=a.data;q=!1}var h,q=!1;this.destroy=function(h){f.unsubscribe("textInput",d);f.unsubscribe("compositionend",c);f.removeFilter("keypress",a);h()};f.subscribe("textInput",d);f.subscribe("compositionend",c);f.addFilter("keypress",a)}gui.InputMethodEditor=function(k,a){function d(a){e&&(a?e.getNode().setAttributeNS(b,"composing","true"):(e.getNode().removeAttributeNS(b, -"composing"),u.textContent=""))}function c(){y&&(y=!1,d(!1),s.emit(gui.InputMethodEditor.signalCompositionEnd,{data:v}),v="")}function h(){C||(C=!0,c(),e&&e.getSelectedRange().collapsed?n.value="":n.value=w.writeToString(e.getSelectedRange().cloneContents()),n.setSelectionRange(0,n.value.length),C=!1)}function q(){a.hasFocus()&&t.trigger()}function p(){x=void 0;t.cancel();d(!0);y||s.emit(gui.InputMethodEditor.signalCompositionStart,{data:""})}function m(b){b=x=b.data;y=!0;v+=b;t.trigger()}function l(b){b.data!== -x&&(b=b.data,y=!0,v+=b,t.trigger());x=void 0}function r(){u.textContent=n.value}var b="urn:webodf:names:cursor",e=null,n=a.getEventTrap(),g=n.ownerDocument,u,t,y=!1,v="",s=new core.EventNotifier([gui.InputMethodEditor.signalCompositionStart,gui.InputMethodEditor.signalCompositionEnd]),x,w,B=[],I,C=!1;this.subscribe=s.subscribe;this.unsubscribe=s.unsubscribe;this.registerCursor=function(b){b.getMemberId()===k&&(e=b,e.getNode().appendChild(u),b.subscribe(ops.OdtCursor.signalCursorUpdated,q),a.subscribe("input", -r),a.subscribe("compositionupdate",r))};this.removeCursor=function(b){e&&b===k&&(e.getNode().removeChild(u),e.unsubscribe(ops.OdtCursor.signalCursorUpdated,q),a.unsubscribe("input",r),a.unsubscribe("compositionupdate",r),e=null)};this.destroy=function(b){a.unsubscribe("compositionstart",p);a.unsubscribe("compositionend",m);a.unsubscribe("textInput",l);a.unsubscribe("keypress",c);a.unsubscribe("focus",h);core.Async.destroyAll(I,b)};(function(){w=new odf.TextSerializer;w.filter=new odf.OdfNodeFilter; -a.subscribe("compositionstart",p);a.subscribe("compositionend",m);a.subscribe("textInput",l);a.subscribe("keypress",c);a.subscribe("focus",h);B.push(new f(a));I=B.map(function(b){return b.destroy});u=g.createElement("span");u.setAttribute("id","composer");t=core.Task.createTimeoutTask(h,1);I.push(t.destroy)})()};gui.InputMethodEditor.signalCompositionStart="input/compositionstart";gui.InputMethodEditor.signalCompositionEnd="input/compositionend"})();gui.MetadataController=function(f,k){function a(a){h.emit(gui.MetadataController.signalMetadataChanged,a)}function d(a){var c=-1===q.indexOf(a);c||runtime.log("Setting "+a+" is restricted.");return c}var c=f.getOdtDocument(),h=new core.EventNotifier([gui.MetadataController.signalMetadataChanged]),q=["dc:creator","dc:date","meta:editing-cycles","meta:editing-duration","meta:document-statistic"];this.setMetadata=function(a,c){var h={},q="",b;a&&Object.keys(a).filter(d).forEach(function(b){h[b]=a[b]}); -c&&(q=c.filter(d).join(","));if(0c:!1}function a(a){null!==a&&!1===k(a)&&(c=Math.abs(a-f))}var d=this,c,h=gui.StepInfo.VisualDirection.LEFT_TO_RIGHT;this.token=void 0;this.process=function(c,f,m){var l,r;c.visualDirection===h?(l=f&&f.right,r=m&&m.left):(l=f&&f.left,r=m&&m.right);if(k(l)||k(r))return!0;if(f||m)a(l),a(r),d.token=c.token;return!1}};gui.LineBoundaryScanner=function(){var f=this,k=null;this.token=void 0;this.process=function(a,d,c){var h;if(h=c)if(k){var q=k;h=Math.min(q.bottom-q.top,c.bottom-c.top);var p=Math.max(q.top,c.top),q=Math.min(q.bottom,c.bottom)-p;h=0.4>=(0a?b.previousSibling:b.nextSibling,c(h)===NodeFilter.FILTER_ACCEPT&&(e=h),b=b.parentNode;return e}function d(b,a){var e;return null===b?n.NO_NEIGHBOUR:q.isCharacterElement(b)?n.SPACE_CHAR:b.nodeType===c||q.isTextSpan(b)||q.isHyperlink(b)?(e=b.textContent.charAt(a()),m.test(e)?n.SPACE_CHAR:p.test(e)?n.PUNCTUATION_CHAR:n.WORD_CHAR):n.OTHER}var c=Node.TEXT_NODE,h=Node.ELEMENT_NODE, +isAlignedJustified:this.isAlignedJustified}};gui.DirectFormattingController=function(f,l,a,c,b,k,q){function p(){return V.value().styleSummary}function n(){return V.value().enabledFeatures}function g(a){var b;a.collapsed?(b=a.startContainer,b.hasChildNodes()&&a.startOffseta.clientWidth||a.scrollHeight>a.clientHeight)&&b.push(new h(a)),a=a.parentNode;b.push(new g(r));return b}function v(){var a; +m()||(a=y(B),t(),B.focus(),a.forEach(function(a){a.restore()}))}var r=runtime.getWindow(),w={beforecut:!0,beforepaste:!0,longpress:!0,drag:!0,dragstop:!0},u={mousedown:!0,mouseup:!0,focus:!0},A={},F={},B,E=f.getCanvas().getElement(),H=this,I={};this.addFilter=function(a,b){d(a,!0).filters.push(b)};this.removeFilter=function(a,b){var e=d(a,!0),c=e.filters.indexOf(b);-1!==c&&e.filters.splice(c,1)};this.subscribe=e;this.unsubscribe=s;this.hasFocus=m;this.focus=v;this.getEventTrap=function(){return B}; +this.setEditing=function(a){var b=m();b&&B.blur();a?B.removeAttribute("readOnly"):B.setAttribute("readOnly","true");b&&v()};this.destroy=function(a){s("touchstart",n);Object.keys(I).forEach(function(a){c(parseInt(a,10))});I.length=0;Object.keys(A).forEach(function(a){A[a].destroy()});A={};s("mousedown",x);s("mouseup",t);s("contextmenu",t);Object.keys(F).forEach(function(a){F[a].destroy()});F={};B.parentNode.removeChild(B);a()};(function(){var b=f.getOdfCanvas().getSizer(),d=b.ownerDocument;runtime.assert(Boolean(r), +"EventManager requires a window object to operate correctly");B=d.createElement("textarea");B.id="eventTrap";B.setAttribute("tabindex","-1");B.setAttribute("readOnly","true");B.setAttribute("rows","1");b.appendChild(B);e("mousedown",x);e("mouseup",t);e("contextmenu",t);A.longpress=new a("longpress",["touchstart","touchmove","touchend"],k);A.drag=new a("drag",["touchstart","touchmove","touchend"],q);A.dragstop=new a("dragstop",["drag","touchend"],p);e("touchstart",n)})()};gui.IOSSafariSupport=function(f){function l(){a.innerHeight!==a.outerHeight&&(c.style.display="none",runtime.requestAnimationFrame(function(){c.style.display="block"}))}var a=runtime.getWindow(),c=f.getEventTrap();this.destroy=function(a){f.unsubscribe("focus",l);c.removeAttribute("autocapitalize");c.style.WebkitTransform="";a()};f.subscribe("focus",l);c.setAttribute("autocapitalize","off");c.style.WebkitTransform="translateX(-10000px)"};gui.HyperlinkController=function(f,l,a,c){function b(){var b=!0;!0===l.getState(gui.CommonConstraints.EDIT.REVIEW_MODE)&&(b=a.isLocalCursorWithinOwnAnnotation());b!==g&&(g=b,n.emit(gui.HyperlinkController.enabledChanged,g))}function k(a){a.getMemberId()===c&&b()}var q=odf.OdfUtils,p=f.getOdtDocument(),n=new core.EventNotifier([gui.HyperlinkController.enabledChanged]),g=!1;this.isEnabled=function(){return g};this.subscribe=function(a,b){n.subscribe(a,b)};this.unsubscribe=function(a,b){n.unsubscribe(a, +b)};this.addHyperlink=function(a,b){if(g){var e=p.getCursorSelection(c),k=new ops.OpApplyHyperlink,m=[];if(0===e.length||b)b=b||a,k=new ops.OpInsertText,k.init({memberid:c,position:e.position,text:b}),e.length=b.length,m.push(k);k=new ops.OpApplyHyperlink;k.init({memberid:c,position:e.position,length:e.length,hyperlink:a});m.push(k);f.enqueue(m)}};this.removeHyperlinks=function(){if(g){var a=p.createPositionIterator(p.getRootNode()),b=p.getCursor(c).getSelectedRange(),e=q.getHyperlinkElements(b), +k=b.collapsed&&1===e.length,m=p.getDOMDocument().createRange(),l=[],n,y;0!==e.length&&(e.forEach(function(a){m.selectNodeContents(a);n=p.convertDomToCursorRange({anchorNode:m.startContainer,anchorOffset:m.startOffset,focusNode:m.endContainer,focusOffset:m.endOffset});y=new ops.OpRemoveHyperlink;y.init({memberid:c,position:n.position,length:n.length});l.push(y)}),k||(k=e[0],-1===b.comparePoint(k,0)&&(m.setStart(k,0),m.setEnd(b.startContainer,b.startOffset),n=p.convertDomToCursorRange({anchorNode:m.startContainer, +anchorOffset:m.startOffset,focusNode:m.endContainer,focusOffset:m.endOffset}),0k.width&&(q=k.width/l.width);l.height>k.height&&(r=k.height/l.height);k=Math.min(q,r);l={width:l.width*k,height:l.height* +k}}k=l.width+"px";l=l.height+"px";var w=g.getOdfCanvas().odfContainer().rootElement.styles,q=a.toLowerCase(),r=p.hasOwnProperty(q)?p[q]:null,u,q=[];runtime.assert(null!==r,"Image type is not supported: "+a);r="Pictures/"+b.generateImageName()+r;u=new ops.OpSetBlob;u.init({memberid:c,filename:r,mimetype:a,content:e});q.push(u);d.getStyleElement("Graphics","graphic",[w])||(a=new ops.OpAddStyle,a.init({memberid:c,styleName:"Graphics",styleFamily:"graphic",isAutomaticStyle:!1,setProperties:{"style:graphic-properties":{"text:anchor-type":"paragraph", +"svg:x":"0cm","svg:y":"0cm","style:wrap":"dynamic","style:number-wrapped-paragraphs":"no-limit","style:wrap-contour":"false","style:vertical-pos":"top","style:vertical-rel":"paragraph","style:horizontal-pos":"center","style:horizontal-rel":"paragraph"}}}),q.push(a));a=b.generateStyleName();e=new ops.OpAddStyle;e.init({memberid:c,styleName:a,styleFamily:"graphic",isAutomaticStyle:!0,setProperties:{"style:parent-style-name":"Graphics","style:graphic-properties":{"style:vertical-pos":"top","style:vertical-rel":"baseline", +"style:horizontal-pos":"center","style:horizontal-rel":"paragraph","fo:background-color":"transparent","style:background-transparency":"100%","style:shadow":"none","style:mirror":"none","fo:clip":"rect(0cm, 0cm, 0cm, 0cm)","draw:luminance":"0%","draw:contrast":"0%","draw:red":"0%","draw:green":"0%","draw:blue":"0%","draw:gamma":"100%","draw:color-inversion":"false","draw:image-opacity":"100%","draw:color-mode":"standard"}}});q.push(e);u=new ops.OpInsertImage;u.init({memberid:c,position:g.getCursorPosition(c), +filename:r,frameWidth:k,frameHeight:l,frameStyleName:a,frameName:b.generateFrameName()});q.push(u);f.enqueue(q)}};this.destroy=function(a){g.unsubscribe(ops.Document.signalCursorMoved,q);l.unsubscribe(gui.CommonConstraints.EDIT.REVIEW_MODE,k);a()};g.subscribe(ops.Document.signalCursorMoved,q);l.subscribe(gui.CommonConstraints.EDIT.REVIEW_MODE,k);k()};gui.ImageController.enabledChanged="enabled/changed";gui.ImageSelector=function(f){function l(){var a=f.getSizer(),k=b.createElement("div");k.id="imageSelector";k.style.borderWidth="1px";a.appendChild(k);c.forEach(function(a){var c=b.createElement("div");c.className=a;k.appendChild(c)});return k}var a=odf.Namespaces.svgns,c="topLeft topRight bottomRight bottomLeft topMiddle rightMiddle bottomMiddle leftMiddle".split(" "),b=f.getElement().ownerDocument,k=!1;this.select=function(c){var p,n,g=b.getElementById("imageSelector");g||(g=l());k=!0;p=g.parentNode; +n=c.getBoundingClientRect();var h=p.getBoundingClientRect(),d=f.getZoomLevel();p=(n.left-h.left)/d-1;n=(n.top-h.top)/d-1;g.style.display="block";g.style.left=p+"px";g.style.top=n+"px";g.style.width=c.getAttributeNS(a,"width");g.style.height=c.getAttributeNS(a,"height")};this.clearSelection=function(){var a;k&&(a=b.getElementById("imageSelector"))&&(a.style.display="none");k=!1};this.isSelectorElement=function(a){var c=b.getElementById("imageSelector");return c?a===c||a.parentNode===c:!1}};(function(){function f(f){function a(a){q=a.which&&String.fromCharCode(a.which)===k;k=void 0;return!1===q}function c(){q=!1}function b(a){k=a.data;q=!1}var k,q=!1;this.destroy=function(k){f.unsubscribe("textInput",c);f.unsubscribe("compositionend",b);f.removeFilter("keypress",a);k()};f.subscribe("textInput",c);f.subscribe("compositionend",b);f.addFilter("keypress",a)}gui.InputMethodEditor=function(l,a){function c(a){e&&(a?e.getNode().setAttributeNS(d,"composing","true"):(e.getNode().removeAttributeNS(d, +"composing"),x.textContent=""))}function b(){y&&(y=!1,c(!1),r.emit(gui.InputMethodEditor.signalCompositionEnd,{data:v}),v="")}function k(){B||(B=!0,b(),e&&e.getSelectedRange().collapsed?s.value="":s.value=u.writeToString(e.getSelectedRange().cloneContents()),s.setSelectionRange(0,s.value.length),B=!1)}function q(){a.hasFocus()&&t.trigger()}function p(){w=void 0;t.cancel();c(!0);y||r.emit(gui.InputMethodEditor.signalCompositionStart,{data:""})}function n(a){a=w=a.data;y=!0;v+=a;t.trigger()}function g(a){a.data!== +w&&(a=a.data,y=!0,v+=a,t.trigger());w=void 0}function h(){x.textContent=s.value}var d="urn:webodf:names:cursor",e=null,s=a.getEventTrap(),m=s.ownerDocument,x,t,y=!1,v="",r=new core.EventNotifier([gui.InputMethodEditor.signalCompositionStart,gui.InputMethodEditor.signalCompositionEnd]),w,u,A=[],F,B=!1;this.subscribe=r.subscribe;this.unsubscribe=r.unsubscribe;this.registerCursor=function(b){b.getMemberId()===l&&(e=b,e.getNode().appendChild(x),b.subscribe(ops.OdtCursor.signalCursorUpdated,q),a.subscribe("input", +h),a.subscribe("compositionupdate",h))};this.removeCursor=function(b){e&&b===l&&(e.getNode().removeChild(x),e.unsubscribe(ops.OdtCursor.signalCursorUpdated,q),a.unsubscribe("input",h),a.unsubscribe("compositionupdate",h),e=null)};this.destroy=function(d){a.unsubscribe("compositionstart",p);a.unsubscribe("compositionend",n);a.unsubscribe("textInput",g);a.unsubscribe("keypress",b);a.unsubscribe("focus",k);core.Async.destroyAll(F,d)};(function(){u=new odf.TextSerializer;u.filter=new odf.OdfNodeFilter; +a.subscribe("compositionstart",p);a.subscribe("compositionend",n);a.subscribe("textInput",g);a.subscribe("keypress",b);a.subscribe("focus",k);A.push(new f(a));F=A.map(function(a){return a.destroy});x=m.createElement("span");x.setAttribute("id","composer");t=core.Task.createTimeoutTask(k,1);F.push(t.destroy)})()};gui.InputMethodEditor.signalCompositionStart="input/compositionstart";gui.InputMethodEditor.signalCompositionEnd="input/compositionend"})();gui.MetadataController=function(f,l){function a(a){k.emit(gui.MetadataController.signalMetadataChanged,a)}function c(a){var b=-1===q.indexOf(a);b||runtime.log("Setting "+a+" is restricted.");return b}var b=f.getOdtDocument(),k=new core.EventNotifier([gui.MetadataController.signalMetadataChanged]),q=["dc:creator","dc:date","meta:editing-cycles","meta:editing-duration","meta:document-statistic"];this.setMetadata=function(a,b){var g={},h="",d;a&&Object.keys(a).filter(c).forEach(function(b){g[b]=a[b]}); +b&&(h=b.filter(c).join(","));if(0b:!1}function a(a){null!==a&&!1===l(a)&&(b=Math.abs(a-f))}var c=this,b,k=gui.StepInfo.VisualDirection.LEFT_TO_RIGHT;this.token=void 0;this.process=function(b,f,n){var g,h;b.visualDirection===k?(g=f&&f.right,h=n&&n.left):(g=f&&f.left,h=n&&n.right);if(l(g)||l(h))return!0;if(f||n)a(g),a(h),c.token=b.token;return!1}};gui.LineBoundaryScanner=function(){var f=this,l=null;this.token=void 0;this.process=function(a,c,b){var k;if(k=b)if(l){var q=l;k=Math.min(q.bottom-q.top,b.bottom-b.top);var p=Math.max(q.top,b.top),q=Math.min(q.bottom,b.bottom)-p;k=0.4>=(0b?a.previousSibling:a.nextSibling,d(g)===NodeFilter.FILTER_ACCEPT&&(e=g),a=a.parentNode;return e}function c(a,d){var e;return null===a?s.NO_NEIGHBOUR:q.isCharacterElement(a)?s.SPACE_CHAR:a.nodeType===b||q.isTextSpan(a)||q.isHyperlink(a)?(e=a.textContent.charAt(d()),n.test(e)?s.SPACE_CHAR:p.test(e)?s.PUNCTUATION_CHAR:s.WORD_CHAR):s.OTHER}var b=Node.TEXT_NODE,k=Node.ELEMENT_NODE, q=odf.OdfUtils,p=/[!-#%-*,-\/:-;?-@\[-\]_{}\u00a1\u00ab\u00b7\u00bb\u00bf;\u00b7\u055a-\u055f\u0589-\u058a\u05be\u05c0\u05c3\u05c6\u05f3-\u05f4\u0609-\u060a\u060c-\u060d\u061b\u061e-\u061f\u066a-\u066d\u06d4\u0700-\u070d\u07f7-\u07f9\u0964-\u0965\u0970\u0df4\u0e4f\u0e5a-\u0e5b\u0f04-\u0f12\u0f3a-\u0f3d\u0f85\u0fd0-\u0fd4\u104a-\u104f\u10fb\u1361-\u1368\u166d-\u166e\u169b-\u169c\u16eb-\u16ed\u1735-\u1736\u17d4-\u17d6\u17d8-\u17da\u1800-\u180a\u1944-\u1945\u19de-\u19df\u1a1e-\u1a1f\u1b5a-\u1b60\u1c3b-\u1c3f\u1c7e-\u1c7f\u2000-\u206e\u207d-\u207e\u208d-\u208e\u3008-\u3009\u2768-\u2775\u27c5-\u27c6\u27e6-\u27ef\u2983-\u2998\u29d8-\u29db\u29fc-\u29fd\u2cf9-\u2cfc\u2cfe-\u2cff\u2e00-\u2e7e\u3000-\u303f\u30a0\u30fb\ua60d-\ua60f\ua673\ua67e\ua874-\ua877\ua8ce-\ua8cf\ua92e-\ua92f\ua95f\uaa5c-\uaa5f\ufd3e-\ufd3f\ufe10-\ufe19\ufe30-\ufe52\ufe54-\ufe61\ufe63\ufe68\ufe6a-\ufe6b\uff01-\uff03\uff05-\uff0a\uff0c-\uff0f\uff1a-\uff1b\uff1f-\uff20\uff3b-\uff3d\uff3f\uff5b\uff5d\uff5f-\uff65]|\ud800[\udd00-\udd01\udf9f\udfd0]|\ud802[\udd1f\udd3f\ude50-\ude58]|\ud809[\udc00-\udc7e]/, -m=/\s/,l=core.PositionFilter.FilterResult.FILTER_ACCEPT,r=core.PositionFilter.FilterResult.FILTER_REJECT,b=odf.WordBoundaryFilter.IncludeWhitespace.TRAILING,e=odf.WordBoundaryFilter.IncludeWhitespace.LEADING,n={NO_NEIGHBOUR:0,SPACE_CHAR:1,PUNCTUATION_CHAR:2,WORD_CHAR:3,OTHER:4};this.acceptPosition=function(c){var f=c.container(),m=c.leftNode(),q=c.rightNode(),p=c.unfilteredDomOffset,s=function(){return c.unfilteredDomOffset()-1};f.nodeType===h&&(null===q&&(q=a(f,1,c.getNodeFilter())),null===m&&(m= -a(f,-1,c.getNodeFilter())));f!==q&&(p=function(){return 0});f!==m&&null!==m&&(s=function(){return m.textContent.length-1});f=d(m,s);q=d(q,p);return f===n.WORD_CHAR&&q===n.WORD_CHAR||f===n.PUNCTUATION_CHAR&&q===n.PUNCTUATION_CHAR||k===b&&f!==n.NO_NEIGHBOUR&&q===n.SPACE_CHAR||k===e&&f===n.SPACE_CHAR&&q!==n.NO_NEIGHBOUR?r:l}};odf.WordBoundaryFilter.IncludeWhitespace={None:0,TRAILING:1,LEADING:2};gui.SelectionController=function(f,k){function a(b){var a=b.spec();if(b.isEdit||a.memberid===k)I=void 0,C.cancel()}function d(){var b=t.getCursor(k).getNode();return t.createStepIterator(b,0,[s,w],t.getRootElement(b))}function c(b,a,c){c=new odf.WordBoundaryFilter(t,c);var e=t.getRootElement(b)||t.getRootNode(),d=t.createRootFilter(e);return t.createStepIterator(b,a,[s,d,c],e)}function h(b,a){return a?{anchorNode:b.startContainer,anchorOffset:b.startOffset,focusNode:b.endContainer,focusOffset:b.endOffset}: -{anchorNode:b.endContainer,anchorOffset:b.endOffset,focusNode:b.startContainer,focusOffset:b.startOffset}}function q(b,a,c){var e=new ops.OpMoveCursor;e.init({memberid:k,position:b,length:a||0,selectionType:c});return e}function p(b,a,c){var e;e=t.getCursor(k);e=h(e.getSelectedRange(),e.hasForwardSelection());e.focusNode=b;e.focusOffset=a;c||(e.anchorNode=e.focusNode,e.anchorOffset=e.focusOffset);b=t.convertDomToCursorRange(e);f.enqueue([q(b.position,b.length)])}function m(b){var a;a=c(b.startContainer, -b.startOffset,F);a.roundToPreviousStep()&&b.setStart(a.container(),a.offset());a=c(b.endContainer,b.endOffset,J);a.roundToNextStep()&&b.setEnd(a.container(),a.offset())}function l(b){var a=v.getParagraphElements(b),c=a[0],a=a[a.length-1];c&&b.setStart(c,0);a&&(v.isParagraph(b.endContainer)&&0===b.endOffset?b.setEndBefore(a):b.setEnd(a,a.childNodes.length))}function r(b,a,c,e){var d,f;e?(d=c.startContainer,f=c.startOffset):(d=c.endContainer,f=c.endOffset);y.containsNode(b,d)||(f=0>y.comparePoints(b, -0,d,f)?0:b.childNodes.length,d=b);b=t.createStepIterator(d,f,a,v.getParagraphElement(d)||b);b.roundToClosestStep()||runtime.assert(!1,"No step found in requested range");e?c.setStart(b.container(),b.offset()):c.setEnd(b.container(),b.offset())}function b(b,a){var c=d();c.advanceStep(b)&&p(c.container(),c.offset(),a)}function e(b,a){var c,e=I,f=[new gui.LineBoundaryScanner,new gui.ParagraphBoundaryScanner];void 0===e&&B&&(e=B());isNaN(e)||(c=d(),x.moveToFilteredStep(c,b,f)&&c.advanceStep(b)&&(f=[new gui.ClosestXOffsetScanner(e), -new gui.LineBoundaryScanner,new gui.ParagraphBoundaryScanner],x.moveToFilteredStep(c,b,f)&&(p(c.container(),c.offset(),a),I=e,C.restart())))}function n(b,a){var c=d(),e=[new gui.LineBoundaryScanner,new gui.ParagraphBoundaryScanner];x.moveToFilteredStep(c,b,e)&&p(c.container(),c.offset(),a)}function g(b,a){var e=t.getCursor(k),e=h(e.getSelectedRange(),e.hasForwardSelection()),e=c(e.focusNode,e.focusOffset,F);e.advanceStep(b)&&p(e.container(),e.offset(),a)}function u(b,a,c){var e=!1,d=t.getCursor(k), -d=h(d.getSelectedRange(),d.hasForwardSelection()),e=t.getRootElement(d.focusNode);runtime.assert(Boolean(e),"SelectionController: Cursor outside root");d=t.createStepIterator(d.focusNode,d.focusOffset,[s,w],e);d.roundToClosestStep();d.advanceStep(b)&&(c=c(d.container()))&&(b===N?(d.setPosition(c,0),e=d.roundToNextStep()):(d.setPosition(c,c.childNodes.length),e=d.roundToPreviousStep()),e&&p(d.container(),d.offset(),a))}var t=f.getOdtDocument(),y=core.DomUtils,v=odf.OdfUtils,s=t.getPositionFilter(), -x=new gui.GuiStepUtils,w=t.createRootFilter(k),B=null,I,C,F=odf.WordBoundaryFilter.IncludeWhitespace.TRAILING,J=odf.WordBoundaryFilter.IncludeWhitespace.LEADING,N=core.StepDirection.PREVIOUS,K=core.StepDirection.NEXT;this.selectionToRange=function(b){var a=0<=y.comparePoints(b.anchorNode,b.anchorOffset,b.focusNode,b.focusOffset),c=b.focusNode.ownerDocument.createRange();a?(c.setStart(b.anchorNode,b.anchorOffset),c.setEnd(b.focusNode,b.focusOffset)):(c.setStart(b.focusNode,b.focusOffset),c.setEnd(b.anchorNode, -b.anchorOffset));return{range:c,hasForwardSelection:a}};this.rangeToSelection=h;this.selectImage=function(b){var a=t.getRootElement(b),c=t.createRootFilter(a),a=t.createStepIterator(b,0,[c,t.getPositionFilter()],a),e;a.roundToPreviousStep()||runtime.assert(!1,"No walkable position before frame");c=a.container();e=a.offset();a.setPosition(b,b.childNodes.length);a.roundToNextStep()||runtime.assert(!1,"No walkable position after frame");b=t.convertDomToCursorRange({anchorNode:c,anchorOffset:e,focusNode:a.container(), -focusOffset:a.offset()});b=q(b.position,b.length,ops.OdtCursor.RegionSelection);f.enqueue([b])};this.expandToWordBoundaries=m;this.expandToParagraphBoundaries=l;this.selectRange=function(b,a,c){var e=t.getOdfCanvas().getElement(),d,g=[s];d=y.containsNode(e,b.startContainer);e=y.containsNode(e,b.endContainer);if(d||e)if(d&&e&&(2===c?m(b):3<=c&&l(b)),(c=a?t.getRootElement(b.startContainer):t.getRootElement(b.endContainer))||(c=t.getRootNode()),g.push(t.createRootFilter(c)),r(c,g,b,!0),r(c,g,b,!1),b= -h(b,a),a=t.convertDomToCursorRange(b),b=t.getCursorSelection(k),a.position!==b.position||a.length!==b.length)b=q(a.position,a.length,ops.OdtCursor.RangeSelection),f.enqueue([b])};this.moveCursorToLeft=function(){b(N,!1);return!0};this.moveCursorToRight=function(){b(K,!1);return!0};this.extendSelectionToLeft=function(){b(N,!0);return!0};this.extendSelectionToRight=function(){b(K,!0);return!0};this.setCaretXPositionLocator=function(b){B=b};this.moveCursorUp=function(){e(N,!1);return!0};this.moveCursorDown= -function(){e(K,!1);return!0};this.extendSelectionUp=function(){e(N,!0);return!0};this.extendSelectionDown=function(){e(K,!0);return!0};this.moveCursorBeforeWord=function(){g(N,!1);return!0};this.moveCursorPastWord=function(){g(K,!1);return!0};this.extendSelectionBeforeWord=function(){g(N,!0);return!0};this.extendSelectionPastWord=function(){g(K,!0);return!0};this.moveCursorToLineStart=function(){n(N,!1);return!0};this.moveCursorToLineEnd=function(){n(K,!1);return!0};this.extendSelectionToLineStart= -function(){n(N,!0);return!0};this.extendSelectionToLineEnd=function(){n(K,!0);return!0};this.extendSelectionToParagraphStart=function(){u(N,!0,v.getParagraphElement);return!0};this.extendSelectionToParagraphEnd=function(){u(K,!0,v.getParagraphElement);return!0};this.moveCursorToParagraphStart=function(){u(N,!1,v.getParagraphElement);return!0};this.moveCursorToParagraphEnd=function(){u(K,!1,v.getParagraphElement);return!0};this.moveCursorToDocumentStart=function(){u(N,!1,t.getRootElement);return!0}; -this.moveCursorToDocumentEnd=function(){u(K,!1,t.getRootElement);return!0};this.extendSelectionToDocumentStart=function(){u(N,!0,t.getRootElement);return!0};this.extendSelectionToDocumentEnd=function(){u(K,!0,t.getRootElement);return!0};this.extendSelectionToEntireDocument=function(){var b=t.getCursor(k),b=t.getRootElement(b.getNode()),a,c,e;runtime.assert(Boolean(b),"SelectionController: Cursor outside root");e=t.createStepIterator(b,0,[s,w],b);e.roundToClosestStep();a=e.container();c=e.offset(); -e.setPosition(b,b.childNodes.length);e.roundToClosestStep();b=t.convertDomToCursorRange({anchorNode:a,anchorOffset:c,focusNode:e.container(),focusOffset:e.offset()});f.enqueue([q(b.position,b.length)]);return!0};this.destroy=function(b){t.unsubscribe(ops.OdtDocument.signalOperationStart,a);core.Async.destroyAll([C.destroy],b)};(function(){C=core.Task.createTimeoutTask(function(){I=void 0},2E3);t.subscribe(ops.OdtDocument.signalOperationStart,a)})()};gui.TextController=function(f,k,a,d,c,h){function q(){u=!0===k.getState(gui.CommonConstraints.EDIT.REVIEW_MODE)?a.isLocalCursorWithinOwnAnnotation():!0}function p(b){b.getMemberId()===d&&q()}function m(b,a,c){var d=[e.getPositionFilter()];c&&d.push(e.createRootFilter(b.startContainer));c=e.createStepIterator(b.startContainer,b.startOffset,d,a);c.roundToClosestStep()||runtime.assert(!1,"No walkable step found in paragraph element at range start");a=e.convertDomPointToCursorStep(c.container(),c.offset()); -b.collapsed?b=a:(c.setPosition(b.endContainer,b.endOffset),c.roundToClosestStep()||runtime.assert(!1,"No walkable step found in paragraph element at range end"),b=e.convertDomPointToCursorStep(c.container(),c.offset()));return{position:a,length:b-a}}function l(b){var a,c,e,f=n.getParagraphElements(b),h=b.cloneRange(),k=[];a=f[0];1b.length&&(b.position+=b.length,b.length=-b.length);return b}function b(b){if(!u)return!1;var a,c=e.getCursor(d).getSelectedRange().cloneRange(), -g=r(e.getCursorSelection(d)),h;if(0===g.length){g=void 0;a=e.getCursor(d).getNode();h=e.getRootElement(a);var k=[e.getPositionFilter(),e.createRootFilter(h)];h=e.createStepIterator(a,0,k,h);h.roundToClosestStep()&&(b?h.nextStep():h.previousStep())&&(g=r(e.convertDomToCursorRange({anchorNode:a,anchorOffset:0,focusNode:h.container(),focusOffset:h.offset()})),b?(c.setStart(a,0),c.setEnd(h.container(),h.offset())):(c.setStart(h.container(),h.offset()),c.setEnd(a,0)))}g&&f.enqueue(l(c));return void 0!== -g}var e=f.getOdtDocument(),n=odf.OdfUtils,g=core.DomUtils,u=!1,t=odf.Namespaces.textns,y=core.StepDirection.NEXT;this.isEnabled=function(){return u};this.enqueueParagraphSplittingOps=function(){if(!u)return!1;var b=e.getCursor(d),a=b.getSelectedRange(),c=r(e.getCursorSelection(d)),g=[],b=n.getParagraphElement(b.getNode()),k=b.getAttributeNS(t,"style-name")||"";0e.left&&(e=x(d)))a.focusNode=e.container,a.focusOffset=e.offset,c&&(a.anchorNode=a.focusNode,a.anchorOffset=a.focusOffset)}else D.isImage(a.focusNode.firstChild)&&1===a.focusOffset&&D.isCharacterFrame(a.focusNode)&&(e=x(a.focusNode))&&(a.anchorNode=a.focusNode=e.container,a.anchorOffset=a.focusOffset=e.offset);a.anchorNode&&a.focusNode&&(a=W.selectionToRange(a),W.selectRange(a.range,a.hasForwardSelection,0===b.button?b.detail:0));M.focus()}function B(b){var a;if(a=q(b.clientX,b.clientY))b= -a.container,a=a.offset,b={anchorNode:b,anchorOffset:a,focusNode:b,focusOffset:a},b=W.selectionToRange(b),W.selectRange(b.range,b.hasForwardSelection,2),M.focus()}function I(b){var a=h(b),c,e,f;la.processRequests();Y&&(D.isImage(a)&&D.isCharacterFrame(a.parentNode)&&T.getSelection().isCollapsed?(W.selectImage(a.parentNode),M.focus()):ka.isSelectorElement(a)?M.focus():X?(a=d.getSelectedRange(),e=a.collapsed,D.isImage(a.endContainer)&&0===a.endOffset&&D.isCharacterFrame(a.endContainer.parentNode)&&(f= -a.endContainer.parentNode,f=x(f))&&(a.setEnd(f.container,f.offset),e&&a.collapse(!1)),W.selectRange(a,d.hasForwardSelection(),0===b.button?b.detail:0),M.focus()):ta?w(b):(c=P.cloneEvent(b),da=runtime.setTimeout(function(){w(c)},0)),na=0,X=Y=!1)}function C(b){var c=G.getCursor(a).getSelectedRange();c.collapsed||Q.exportRangeToDataTransfer(b.dataTransfer,c)}function F(){Y&&M.focus();na=0;X=Y=!1}function J(b){I(b)}function N(b){var a=h(b),c=null;"annotationRemoveButton"===a.className?(runtime.assert(ea, -"Remove buttons are displayed on annotations while annotation editing is disabled in the controller."),c=a.parentNode.getElementsByTagNameNS(odf.Namespaces.officens,"annotation").item(0),ha.removeAnnotation(c),M.focus()):"webodf-draggable"!==a.getAttribute("class")&&I(b)}function K(b){(b=b.data)&&(-1===b.indexOf("\n")?fa.insertText(b):ga.paste(b))}function H(b){return function(){b();return!0}}function z(b){return function(c){return G.getCursor(a).getSelectionType()===ops.OdtCursor.RangeSelection? -b(c):!0}}function Z(b){M.unsubscribe("keydown",A.handleEvent);M.unsubscribe("keypress",V.handleEvent);M.unsubscribe("keyup",ba.handleEvent);M.unsubscribe("copy",l);M.unsubscribe("mousedown",s);M.unsubscribe("mousemove",la.trigger);M.unsubscribe("mouseup",N);M.unsubscribe("contextmenu",J);M.unsubscribe("dragstart",C);M.unsubscribe("dragend",F);M.unsubscribe("click",oa.handleClick);M.unsubscribe("longpress",B);M.unsubscribe("drag",t);M.unsubscribe("dragstop",y);G.unsubscribe(ops.OdtDocument.signalOperationEnd, -ma.trigger);G.unsubscribe(ops.Document.signalCursorAdded,ja.registerCursor);G.unsubscribe(ops.Document.signalCursorRemoved,ja.removeCursor);G.unsubscribe(ops.OdtDocument.signalOperationEnd,e);b()}var T=runtime.getWindow(),G=k.getOdtDocument(),U=new gui.SessionConstraints,aa=new gui.SessionContext(k,a),P=core.DomUtils,D=odf.OdfUtils,Q=new gui.MimeDataExporter,$=new gui.Clipboard(Q),A=new gui.KeyboardHandler,V=new gui.KeyboardHandler,ba=new gui.KeyboardHandler,Y=!1,E=new odf.ObjectNameGenerator(G.getOdfCanvas().odfContainer(), -a),X=!1,R=null,da,S=null,M=new gui.EventManager(G),ea=c.annotationsEnabled,ha=new gui.AnnotationController(k,U,a),ca=new gui.DirectFormattingController(k,U,aa,a,E,c.directTextStylingEnabled,c.directParagraphStylingEnabled),fa=new gui.TextController(k,U,aa,a,ca.createCursorStyleOp,ca.createParagraphStyleOps),pa=new gui.ImageController(k,U,aa,a,E),ka=new gui.ImageSelector(G.getOdfCanvas()),ia=G.createPositionIterator(G.getRootNode()),la,ma,ga=new gui.PasteController(k,U,aa,a),ja=new gui.InputMethodEditor(a, -M),na=0,oa=new gui.HyperlinkClickHandler(G.getOdfCanvas().getElement,A,ba),sa=new gui.HyperlinkController(k,U,aa,a),W=new gui.SelectionController(k,a),ua=new gui.MetadataController(k,a),L=gui.KeyboardHandler.Modifier,O=gui.KeyboardHandler.KeyCode,qa=-1!==T.navigator.appVersion.toLowerCase().indexOf("mac"),ta=-1!==["iPad","iPod","iPhone"].indexOf(T.navigator.platform),ra;runtime.assert(null!==T,"Expected to be run in an environment which has a global window, like a browser.");this.undo=g;this.redo= -u;this.insertLocalCursor=function(){runtime.assert(void 0===k.getOdtDocument().getCursor(a),"Inserting local cursor a second time.");var b=new ops.OpAddCursor;b.init({memberid:a});k.enqueue([b]);M.focus()};this.removeLocalCursor=function(){runtime.assert(void 0!==k.getOdtDocument().getCursor(a),"Removing local cursor without inserting before.");var b=new ops.OpRemoveCursor;b.init({memberid:a});k.enqueue([b])};this.startEditing=function(){ja.subscribe(gui.InputMethodEditor.signalCompositionStart,fa.removeCurrentSelection); -ja.subscribe(gui.InputMethodEditor.signalCompositionEnd,K);M.subscribe("beforecut",m);M.subscribe("cut",p);M.subscribe("beforepaste",b);M.subscribe("paste",r);S&&S.initialize();M.setEditing(!0);oa.setModifier(qa?L.Meta:L.Ctrl);A.bind(O.Backspace,L.None,H(fa.removeTextByBackspaceKey),!0);A.bind(O.Delete,L.None,fa.removeTextByDeleteKey);A.bind(O.Tab,L.None,z(function(){fa.insertText("\t");return!0}));qa?(A.bind(O.Clear,L.None,fa.removeCurrentSelection),A.bind(O.B,L.Meta,z(ca.toggleBold)),A.bind(O.I, -L.Meta,z(ca.toggleItalic)),A.bind(O.U,L.Meta,z(ca.toggleUnderline)),A.bind(O.L,L.MetaShift,z(ca.alignParagraphLeft)),A.bind(O.E,L.MetaShift,z(ca.alignParagraphCenter)),A.bind(O.R,L.MetaShift,z(ca.alignParagraphRight)),A.bind(O.J,L.MetaShift,z(ca.alignParagraphJustified)),ea&&A.bind(O.C,L.MetaShift,ha.addAnnotation),A.bind(O.Z,L.Meta,g),A.bind(O.Z,L.MetaShift,u)):(A.bind(O.B,L.Ctrl,z(ca.toggleBold)),A.bind(O.I,L.Ctrl,z(ca.toggleItalic)),A.bind(O.U,L.Ctrl,z(ca.toggleUnderline)),A.bind(O.L,L.CtrlShift, -z(ca.alignParagraphLeft)),A.bind(O.E,L.CtrlShift,z(ca.alignParagraphCenter)),A.bind(O.R,L.CtrlShift,z(ca.alignParagraphRight)),A.bind(O.J,L.CtrlShift,z(ca.alignParagraphJustified)),ea&&A.bind(O.C,L.CtrlAlt,ha.addAnnotation),A.bind(O.Z,L.Ctrl,g),A.bind(O.Z,L.CtrlShift,u));V.setDefault(z(function(b){var a;a=null===b.which||void 0===b.which?String.fromCharCode(b.keyCode):0!==b.which&&0!==b.charCode?String.fromCharCode(b.which):null;return!a||b.altKey||b.ctrlKey||b.metaKey?!1:(fa.insertText(a),!0)})); -V.bind(O.Enter,L.None,z(fa.enqueueParagraphSplittingOps))};this.endEditing=function(){ja.unsubscribe(gui.InputMethodEditor.signalCompositionStart,fa.removeCurrentSelection);ja.unsubscribe(gui.InputMethodEditor.signalCompositionEnd,K);M.unsubscribe("cut",p);M.unsubscribe("beforecut",m);M.unsubscribe("paste",r);M.unsubscribe("beforepaste",b);M.setEditing(!1);oa.setModifier(L.None);A.bind(O.Backspace,L.None,function(){return!0},!0);A.unbind(O.Delete,L.None);A.unbind(O.Tab,L.None);qa?(A.unbind(O.Clear, -L.None),A.unbind(O.B,L.Meta),A.unbind(O.I,L.Meta),A.unbind(O.U,L.Meta),A.unbind(O.L,L.MetaShift),A.unbind(O.E,L.MetaShift),A.unbind(O.R,L.MetaShift),A.unbind(O.J,L.MetaShift),ea&&A.unbind(O.C,L.MetaShift),A.unbind(O.Z,L.Meta),A.unbind(O.Z,L.MetaShift)):(A.unbind(O.B,L.Ctrl),A.unbind(O.I,L.Ctrl),A.unbind(O.U,L.Ctrl),A.unbind(O.L,L.CtrlShift),A.unbind(O.E,L.CtrlShift),A.unbind(O.R,L.CtrlShift),A.unbind(O.J,L.CtrlShift),ea&&A.unbind(O.C,L.CtrlAlt),A.unbind(O.Z,L.Ctrl),A.unbind(O.Z,L.CtrlShift));V.setDefault(null); -V.unbind(O.Enter,L.None)};this.getInputMemberId=function(){return a};this.getSession=function(){return k};this.getSessionConstraints=function(){return U};this.setUndoManager=function(b){S&&S.unsubscribe(gui.UndoManager.signalUndoStackChanged,n);if(S=b)S.setDocument(G),S.setPlaybackFunction(k.enqueue),S.subscribe(gui.UndoManager.signalUndoStackChanged,n)};this.getUndoManager=function(){return S};this.getMetadataController=function(){return ua};this.getAnnotationController=function(){return ha};this.getDirectFormattingController= -function(){return ca};this.getHyperlinkClickHandler=function(){return oa};this.getHyperlinkController=function(){return sa};this.getImageController=function(){return pa};this.getSelectionController=function(){return W};this.getTextController=function(){return fa};this.getEventManager=function(){return M};this.getKeyboardHandlers=function(){return{keydown:A,keypress:V}};this.destroy=function(b){var a=[la.destroy,ma.destroy,ca.destroy,ja.destroy,M.destroy,oa.destroy,sa.destroy,ua.destroy,W.destroy, -fa.destroy,Z];ra&&a.unshift(ra.destroy);runtime.clearTimeout(da);core.Async.destroyAll(a,b)};la=core.Task.createRedrawTask(v);ma=core.Task.createRedrawTask(function(){var b=G.getCursor(a);if(b&&b.getSelectionType()===ops.OdtCursor.RegionSelection&&(b=D.getImageElements(b.getSelectedRange())[0])){ka.select(b.parentNode);return}ka.clearSelection()});A.bind(O.Left,L.None,z(W.moveCursorToLeft));A.bind(O.Right,L.None,z(W.moveCursorToRight));A.bind(O.Up,L.None,z(W.moveCursorUp));A.bind(O.Down,L.None,z(W.moveCursorDown)); -A.bind(O.Left,L.Shift,z(W.extendSelectionToLeft));A.bind(O.Right,L.Shift,z(W.extendSelectionToRight));A.bind(O.Up,L.Shift,z(W.extendSelectionUp));A.bind(O.Down,L.Shift,z(W.extendSelectionDown));A.bind(O.Home,L.None,z(W.moveCursorToLineStart));A.bind(O.End,L.None,z(W.moveCursorToLineEnd));A.bind(O.Home,L.Ctrl,z(W.moveCursorToDocumentStart));A.bind(O.End,L.Ctrl,z(W.moveCursorToDocumentEnd));A.bind(O.Home,L.Shift,z(W.extendSelectionToLineStart));A.bind(O.End,L.Shift,z(W.extendSelectionToLineEnd));A.bind(O.Up, -L.CtrlShift,z(W.extendSelectionToParagraphStart));A.bind(O.Down,L.CtrlShift,z(W.extendSelectionToParagraphEnd));A.bind(O.Home,L.CtrlShift,z(W.extendSelectionToDocumentStart));A.bind(O.End,L.CtrlShift,z(W.extendSelectionToDocumentEnd));qa?(A.bind(O.Left,L.Alt,z(W.moveCursorBeforeWord)),A.bind(O.Right,L.Alt,z(W.moveCursorPastWord)),A.bind(O.Left,L.Meta,z(W.moveCursorToLineStart)),A.bind(O.Right,L.Meta,z(W.moveCursorToLineEnd)),A.bind(O.Home,L.Meta,z(W.moveCursorToDocumentStart)),A.bind(O.End,L.Meta, -z(W.moveCursorToDocumentEnd)),A.bind(O.Left,L.AltShift,z(W.extendSelectionBeforeWord)),A.bind(O.Right,L.AltShift,z(W.extendSelectionPastWord)),A.bind(O.Left,L.MetaShift,z(W.extendSelectionToLineStart)),A.bind(O.Right,L.MetaShift,z(W.extendSelectionToLineEnd)),A.bind(O.Up,L.AltShift,z(W.extendSelectionToParagraphStart)),A.bind(O.Down,L.AltShift,z(W.extendSelectionToParagraphEnd)),A.bind(O.Up,L.MetaShift,z(W.extendSelectionToDocumentStart)),A.bind(O.Down,L.MetaShift,z(W.extendSelectionToDocumentEnd)), -A.bind(O.A,L.Meta,z(W.extendSelectionToEntireDocument))):(A.bind(O.Left,L.Ctrl,z(W.moveCursorBeforeWord)),A.bind(O.Right,L.Ctrl,z(W.moveCursorPastWord)),A.bind(O.Left,L.CtrlShift,z(W.extendSelectionBeforeWord)),A.bind(O.Right,L.CtrlShift,z(W.extendSelectionPastWord)),A.bind(O.A,L.Ctrl,z(W.extendSelectionToEntireDocument)));ta&&(ra=new gui.IOSSafariSupport(M));M.subscribe("keydown",A.handleEvent);M.subscribe("keypress",V.handleEvent);M.subscribe("keyup",ba.handleEvent);M.subscribe("copy",l);M.subscribe("mousedown", -s);M.subscribe("mousemove",la.trigger);M.subscribe("mouseup",N);M.subscribe("contextmenu",J);M.subscribe("dragstart",C);M.subscribe("dragend",F);M.subscribe("click",oa.handleClick);M.subscribe("longpress",B);M.subscribe("drag",t);M.subscribe("dragstop",y);G.subscribe(ops.OdtDocument.signalOperationEnd,ma.trigger);G.subscribe(ops.Document.signalCursorAdded,ja.registerCursor);G.subscribe(ops.Document.signalCursorRemoved,ja.removeCursor);G.subscribe(ops.OdtDocument.signalOperationEnd,e)}})();gui.CaretManager=function(f,k){function a(a){return h.hasOwnProperty(a)?h[a]:null}function d(){return Object.keys(h).map(function(a){return h[a]})}function c(a){var c=h[a];c&&(delete h[a],a===f.getInputMemberId()?(p.unsubscribe(ops.OdtDocument.signalProcessingBatchEnd,c.ensureVisible),p.unsubscribe(ops.Document.signalCursorMoved,c.refreshCursorBlinking),m.unsubscribe("compositionupdate",c.handleUpdate),m.unsubscribe("compositionend",c.handleUpdate),m.unsubscribe("focus",c.setFocus),m.unsubscribe("blur", -c.removeFocus),q.removeEventListener("focus",c.show,!1),q.removeEventListener("blur",c.hide,!1)):p.unsubscribe(ops.OdtDocument.signalProcessingBatchEnd,c.handleUpdate),c.destroy(function(){}))}var h={},q=runtime.getWindow(),p=f.getSession().getOdtDocument(),m=f.getEventManager();this.registerCursor=function(a,c,b){var e=a.getMemberId();a=new gui.Caret(a,k,c,b);h[e]=a;e===f.getInputMemberId()?(runtime.log("Starting to track input on new cursor of "+e),p.subscribe(ops.OdtDocument.signalProcessingBatchEnd, -a.ensureVisible),p.subscribe(ops.Document.signalCursorMoved,a.refreshCursorBlinking),m.subscribe("compositionupdate",a.handleUpdate),m.subscribe("compositionend",a.handleUpdate),m.subscribe("focus",a.setFocus),m.subscribe("blur",a.removeFocus),q.addEventListener("focus",a.show,!1),q.addEventListener("blur",a.hide,!1),a.setOverlayElement(m.getEventTrap())):p.subscribe(ops.OdtDocument.signalProcessingBatchEnd,a.handleUpdate);return a};this.getCaret=a;this.getCarets=d;this.destroy=function(a){var k= -d().map(function(b){return b.destroy});f.getSelectionController().setCaretXPositionLocator(null);p.unsubscribe(ops.Document.signalCursorRemoved,c);h={};core.Async.destroyAll(k,a)};f.getSelectionController().setCaretXPositionLocator(function(){var c=a(f.getInputMemberId()),d;c&&(d=c.getBoundingClientRect());return d?d.right:void 0});p.subscribe(ops.Document.signalCursorRemoved,c)};gui.EditInfoHandle=function(f){var k=[],a,d=f.ownerDocument,c=d.documentElement.namespaceURI;this.setEdits=function(f){k=f;var q,p,m,l;a.innerHTML="";for(f=0;fe?(p=a(1,0),m=a(0.5,1E4-e),l=a(0.2,2E4-e)):1E4<=e&&2E4>e?(p=a(0.5,0),l=a(0.2,2E4-e)):p=a(0.2,0)};this.getEdits=function(){return f.getEdits()};this.clearEdits= -function(){f.clearEdits();h.setEdits([]);q.hasAttributeNS("urn:webodf:names:editinfo","editinfo:memberid")&&q.removeAttributeNS("urn:webodf:names:editinfo","editinfo:memberid")};this.getEditInfo=function(){return f};this.show=function(){q.style.display="block"};this.hide=function(){d.hideHandle();q.style.display="none"};this.showHandle=function(){h.show()};this.hideHandle=function(){h.hide()};this.destroy=function(a){runtime.clearTimeout(p);runtime.clearTimeout(m);runtime.clearTimeout(l);c.removeChild(q); -h.destroy(function(b){b?a(b):f.destroy(a)})};(function(){var a=f.getOdtDocument().getDOMDocument();q=a.createElementNS(a.documentElement.namespaceURI,"div");q.setAttribute("class","editInfoMarker");q.onmouseover=function(){d.showHandle()};q.onmouseout=function(){d.hideHandle()};c=f.getNode();c.appendChild(q);h=new gui.EditInfoHandle(c);k||d.hide()})()};gui.HyperlinkTooltipView=function(f,k){var a=core.DomUtils,d=odf.OdfUtils,c=runtime.getWindow(),h,q,p;runtime.assert(null!==c,"Expected to be run in an environment which has a global window, like a browser.");this.showTooltip=function(m){var l=m.target||m.srcElement,r=f.getSizer(),b=f.getZoomLevel(),e;a:{for(;l;){if(d.isHyperlink(l))break a;if(d.isParagraph(l)||d.isInlineRoot(l))break;l=l.parentNode}l=null}if(l){a.containsNode(r,p)||r.appendChild(p);e=q;var n;switch(k()){case gui.KeyboardHandler.Modifier.Ctrl:n= -runtime.tr("Ctrl-click to follow link");break;case gui.KeyboardHandler.Modifier.Meta:n=runtime.tr("\u2318-click to follow link");break;default:n=""}e.textContent=n;h.textContent=d.getHyperlinkTarget(l);p.style.display="block";e=c.innerWidth-p.offsetWidth-15;l=m.clientX>e?e:m.clientX+15;e=c.innerHeight-p.offsetHeight-10;m=m.clientY>e?e:m.clientY+10;r=r.getBoundingClientRect();l=(l-r.left)/b;m=(m-r.top)/b;p.style.left=l+"px";p.style.top=m+"px"}};this.hideTooltip=function(){p.style.display="none"};this.destroy= -function(a){p.parentNode&&p.parentNode.removeChild(p);a()};(function(){var a=f.getElement().ownerDocument;h=a.createElement("span");q=a.createElement("span");h.className="webodf-hyperlinkTooltipLink";q.className="webodf-hyperlinkTooltipText";p=a.createElement("div");p.className="webodf-hyperlinkTooltip";p.appendChild(h);p.appendChild(q);f.getElement().appendChild(p)})()};gui.OdfFieldView=function(f){function k(){var a=odf.OdfSchema.getFields().map(function(a){return a.replace(":","|")}),d=a.join(",\n")+"\n{ background-color: #D0D0D0; }\n",a=a.map(function(a){return a+":empty::after"}).join(",\n")+"\n{ content:' '; white-space: pre; }\n";return d+"\n"+a}var a,d=f.getElement().ownerDocument;this.showFieldHighlight=function(){a.appendChild(d.createTextNode(k()))};this.hideFieldHighlight=function(){for(var c=a.sheet,d=c.cssRules;d.length;)c.deleteRule(d.length-1)};this.destroy= -function(c){a.parentNode&&a.parentNode.removeChild(a);c()};a=function(){var a=d.getElementsByTagName("head").item(0),f=d.createElement("style"),k="";f.type="text/css";f.media="screen, print, handheld, projection";odf.Namespaces.forEachPrefix(function(a,c){k+="@namespace "+a+" url("+c+");\n"});f.appendChild(d.createTextNode(k));a.appendChild(f);return f}()};gui.ShadowCursor=function(f){var k=f.getDOMDocument().createRange(),a=!0;this.removeFromDocument=function(){};this.getMemberId=function(){return gui.ShadowCursor.ShadowCursorMemberId};this.getSelectedRange=function(){return k};this.setSelectedRange=function(d,c){k=d;a=!1!==c};this.hasForwardSelection=function(){return a};this.getDocument=function(){return f};this.getSelectionType=function(){return ops.OdtCursor.RangeSelection};k.setStart(f.getRootNode(),0)};gui.ShadowCursor.ShadowCursorMemberId="";gui.SelectionView=function(f){};gui.SelectionView.prototype.rerender=function(){};gui.SelectionView.prototype.show=function(){};gui.SelectionView.prototype.hide=function(){};gui.SelectionView.prototype.destroy=function(f){};gui.SelectionViewManager=function(f){function k(){return Object.keys(a).map(function(d){return a[d]})}var a={};this.getSelectionView=function(d){return a.hasOwnProperty(d)?a[d]:null};this.getSelectionViews=k;this.removeSelectionView=function(d){a.hasOwnProperty(d)&&(a[d].destroy(function(){}),delete a[d])};this.hideSelectionView=function(d){a.hasOwnProperty(d)&&a[d].hide()};this.showSelectionView=function(d){a.hasOwnProperty(d)&&a[d].show()};this.rerenderSelectionViews=function(){Object.keys(a).forEach(function(d){a[d].rerender()})}; -this.registerCursor=function(d,c){var h=d.getMemberId(),k=new f(d);c?k.show():k.hide();return a[h]=k};this.destroy=function(a){function c(k,p){p?a(p):k .webodf-draggable"), -b=gui.ShadowCursor.ShadowCursorMemberId,e(".webodf-selectionOverlay","{ fill: "+c+"; stroke: "+c+";}",""),e(".webodf-touchEnabled .webodf-selectionOverlay","{ display: block; }"," > .webodf-draggable"))}function l(b){var a,c;for(c in w)w.hasOwnProperty(c)&&(a=w[c],b?a.show():a.hide())}function r(b){c.getCarets().forEach(function(a){b?a.showHandle():a.hideHandle()})}function b(b){var a=b.getMemberId();b=b.getProperties();m(a,b.fullName,b.color)}function e(b){var e=b.getMemberId(),d=a.getOdtDocument().getMember(e).getProperties(); -c.registerCursor(b,J,N);h.registerCursor(b,!0);if(b=c.getCaret(e))b.setAvatarImageUrl(d.imageUrl),b.setColor(d.color);runtime.log("+++ View here +++ eagerly created an Caret for '"+e+"'! +++")}function n(b){b=b.getMemberId();var a=h.getSelectionView(k),e=h.getSelectionView(gui.ShadowCursor.ShadowCursorMemberId),d=c.getCaret(k);b===k?(e.hide(),a&&a.show(),d&&d.show()):b===gui.ShadowCursor.ShadowCursorMemberId&&(e.show(),a&&a.hide(),d&&d.hide())}function g(b){h.removeSelectionView(b)}function u(b){var c= -b.paragraphElement,e=b.memberId;b=b.timeStamp;var d,f="",g=c.getElementsByTagNameNS(x,"editinfo").item(0);g?(f=g.getAttributeNS(x,"id"),d=w[f]):(f=Math.random().toString(),d=new ops.EditInfo(c,a.getOdtDocument()),d=new gui.EditInfoMarker(d,F),g=c.getElementsByTagNameNS(x,"editinfo").item(0),g.setAttributeNS(x,"id",f),w[f]=d);d.addEdit(e,new Date(b));C.trigger()}function t(){var b;""!==s.innerHTML&&(s.innerHTML="");!0===d.getState(gui.CommonConstraints.EDIT.ANNOTATIONS.ONLY_DELETE_OWN)&&(b=a.getOdtDocument().getMember(k))&& -(b=b.getProperties().fullName,s.appendChild(document.createTextNode(".annotationWrapper:not([creator = '"+b+"']) .annotationRemoveButton { display: none; }")))}function y(a){var c=Object.keys(w).map(function(b){return w[b]});B.unsubscribe(ops.Document.signalMemberAdded,b);B.unsubscribe(ops.Document.signalMemberUpdated,b);B.unsubscribe(ops.Document.signalCursorAdded,e);B.unsubscribe(ops.Document.signalCursorRemoved,g);B.unsubscribe(ops.OdtDocument.signalParagraphChanged,u);B.unsubscribe(ops.Document.signalCursorMoved, -n);B.unsubscribe(ops.OdtDocument.signalParagraphChanged,h.rerenderSelectionViews);B.unsubscribe(ops.OdtDocument.signalTableAdded,h.rerenderSelectionViews);B.unsubscribe(ops.OdtDocument.signalParagraphStyleModified,h.rerenderSelectionViews);d.unsubscribe(gui.CommonConstraints.EDIT.ANNOTATIONS.ONLY_DELETE_OWN,t);B.unsubscribe(ops.Document.signalMemberAdded,t);B.unsubscribe(ops.Document.signalMemberUpdated,t);v.parentNode.removeChild(v);s.parentNode.removeChild(s);(function Z(b,e){e?a(e):by.comparePoints(a, +0,c,f)?0:a.childNodes.length,c=a);a=t.createStepIterator(c,f,b,v.getParagraphElement(c)||a);a.roundToClosestStep()||runtime.assert(!1,"No step found in requested range");e?d.setStart(a.container(),a.offset()):d.setEnd(a.container(),a.offset())}function d(a,b){var d=c();d.advanceStep(a)&&p(d.container(),d.offset(),b)}function e(a,b){var d,e=F,f=[new gui.LineBoundaryScanner,new gui.ParagraphBoundaryScanner];void 0===e&&A&&(e=A());isNaN(e)||(d=c(),w.moveToFilteredStep(d,a,f)&&d.advanceStep(a)&&(f=[new gui.ClosestXOffsetScanner(e), +new gui.LineBoundaryScanner,new gui.ParagraphBoundaryScanner],w.moveToFilteredStep(d,a,f)&&(p(d.container(),d.offset(),b),F=e,B.restart())))}function s(a,b){var d=c(),e=[new gui.LineBoundaryScanner,new gui.ParagraphBoundaryScanner];w.moveToFilteredStep(d,a,e)&&p(d.container(),d.offset(),b)}function m(a,d){var e=t.getCursor(l),e=k(e.getSelectedRange(),e.hasForwardSelection()),e=b(e.focusNode,e.focusOffset,E);e.advanceStep(a)&&p(e.container(),e.offset(),d)}function x(a,b,d){var e=!1,c=t.getCursor(l), +c=k(c.getSelectedRange(),c.hasForwardSelection()),e=t.getRootElement(c.focusNode);runtime.assert(Boolean(e),"SelectionController: Cursor outside root");c=t.createStepIterator(c.focusNode,c.focusOffset,[r,u],e);c.roundToClosestStep();c.advanceStep(a)&&(d=d(c.container()))&&(a===I?(c.setPosition(d,0),e=c.roundToNextStep()):(c.setPosition(d,d.childNodes.length),e=c.roundToPreviousStep()),e&&p(c.container(),c.offset(),b))}var t=f.getOdtDocument(),y=core.DomUtils,v=odf.OdfUtils,r=t.getPositionFilter(), +w=new gui.GuiStepUtils,u=t.createRootFilter(l),A=null,F,B,E=odf.WordBoundaryFilter.IncludeWhitespace.TRAILING,H=odf.WordBoundaryFilter.IncludeWhitespace.LEADING,I=core.StepDirection.PREVIOUS,Q=core.StepDirection.NEXT;this.selectionToRange=function(a){var b=0<=y.comparePoints(a.anchorNode,a.anchorOffset,a.focusNode,a.focusOffset),d=a.focusNode.ownerDocument.createRange();b?(d.setStart(a.anchorNode,a.anchorOffset),d.setEnd(a.focusNode,a.focusOffset)):(d.setStart(a.focusNode,a.focusOffset),d.setEnd(a.anchorNode, +a.anchorOffset));return{range:d,hasForwardSelection:b}};this.rangeToSelection=k;this.selectImage=function(a){var b=t.getRootElement(a),d=t.createRootFilter(b),b=t.createStepIterator(a,0,[d,t.getPositionFilter()],b),e;b.roundToPreviousStep()||runtime.assert(!1,"No walkable position before frame");d=b.container();e=b.offset();b.setPosition(a,a.childNodes.length);b.roundToNextStep()||runtime.assert(!1,"No walkable position after frame");a=t.convertDomToCursorRange({anchorNode:d,anchorOffset:e,focusNode:b.container(), +focusOffset:b.offset()});a=q(a.position,a.length,ops.OdtCursor.RegionSelection);f.enqueue([a])};this.expandToWordBoundaries=n;this.expandToParagraphBoundaries=g;this.selectRange=function(a,b,d){var e=t.getOdfCanvas().getElement(),c,m=[r];c=y.containsNode(e,a.startContainer);e=y.containsNode(e,a.endContainer);if(c||e)if(c&&e&&(2===d?n(a):3<=d&&g(a)),(d=b?t.getRootElement(a.startContainer):t.getRootElement(a.endContainer))||(d=t.getRootNode()),m.push(t.createRootFilter(d)),h(d,m,a,!0),h(d,m,a,!1),a= +k(a,b),b=t.convertDomToCursorRange(a),a=t.getCursorSelection(l),b.position!==a.position||b.length!==a.length)a=q(b.position,b.length,ops.OdtCursor.RangeSelection),f.enqueue([a])};this.moveCursorToLeft=function(){d(I,!1);return!0};this.moveCursorToRight=function(){d(Q,!1);return!0};this.extendSelectionToLeft=function(){d(I,!0);return!0};this.extendSelectionToRight=function(){d(Q,!0);return!0};this.setCaretXPositionLocator=function(a){A=a};this.moveCursorUp=function(){e(I,!1);return!0};this.moveCursorDown= +function(){e(Q,!1);return!0};this.extendSelectionUp=function(){e(I,!0);return!0};this.extendSelectionDown=function(){e(Q,!0);return!0};this.moveCursorBeforeWord=function(){m(I,!1);return!0};this.moveCursorPastWord=function(){m(Q,!1);return!0};this.extendSelectionBeforeWord=function(){m(I,!0);return!0};this.extendSelectionPastWord=function(){m(Q,!0);return!0};this.moveCursorToLineStart=function(){s(I,!1);return!0};this.moveCursorToLineEnd=function(){s(Q,!1);return!0};this.extendSelectionToLineStart= +function(){s(I,!0);return!0};this.extendSelectionToLineEnd=function(){s(Q,!0);return!0};this.extendSelectionToParagraphStart=function(){x(I,!0,v.getParagraphElement);return!0};this.extendSelectionToParagraphEnd=function(){x(Q,!0,v.getParagraphElement);return!0};this.moveCursorToParagraphStart=function(){x(I,!1,v.getParagraphElement);return!0};this.moveCursorToParagraphEnd=function(){x(Q,!1,v.getParagraphElement);return!0};this.moveCursorToDocumentStart=function(){x(I,!1,t.getRootElement);return!0}; +this.moveCursorToDocumentEnd=function(){x(Q,!1,t.getRootElement);return!0};this.extendSelectionToDocumentStart=function(){x(I,!0,t.getRootElement);return!0};this.extendSelectionToDocumentEnd=function(){x(Q,!0,t.getRootElement);return!0};this.extendSelectionToEntireDocument=function(){var a=t.getCursor(l),a=t.getRootElement(a.getNode()),b,d,e;runtime.assert(Boolean(a),"SelectionController: Cursor outside root");e=t.createStepIterator(a,0,[r,u],a);e.roundToClosestStep();b=e.container();d=e.offset(); +e.setPosition(a,a.childNodes.length);e.roundToClosestStep();a=t.convertDomToCursorRange({anchorNode:b,anchorOffset:d,focusNode:e.container(),focusOffset:e.offset()});f.enqueue([q(a.position,a.length)]);return!0};this.destroy=function(b){t.unsubscribe(ops.OdtDocument.signalOperationStart,a);core.Async.destroyAll([B.destroy],b)};(function(){B=core.Task.createTimeoutTask(function(){F=void 0},2E3);t.subscribe(ops.OdtDocument.signalOperationStart,a)})()};gui.TextController=function(f,l,a,c,b,k){function q(){x=!0===l.getState(gui.CommonConstraints.EDIT.REVIEW_MODE)?a.isLocalCursorWithinOwnAnnotation():!0}function p(a){a.getMemberId()===c&&q()}function n(a,b,d){var c=[e.getPositionFilter()];d&&c.push(e.createRootFilter(a.startContainer));d=e.createStepIterator(a.startContainer,a.startOffset,c,b);d.roundToClosestStep()||runtime.assert(!1,"No walkable step found in paragraph element at range start");b=e.convertDomPointToCursorStep(d.container(),d.offset()); +a.collapsed?a=b:(d.setPosition(a.endContainer,a.endOffset),d.roundToClosestStep()||runtime.assert(!1,"No walkable step found in paragraph element at range end"),a=e.convertDomPointToCursorStep(d.container(),d.offset()));return{position:b,length:a-b}}function g(a){var b,d,e,f=s.getParagraphElements(a),g=a.cloneRange(),h=[];b=f[0];1a.length&&(a.position+=a.length,a.length=-a.length);return a}function d(a){if(!x)return!1;var b,d=e.getCursor(c).getSelectedRange().cloneRange(), +m=h(e.getCursorSelection(c)),k;if(0===m.length){m=void 0;b=e.getCursor(c).getNode();k=e.getRootElement(b);var l=[e.getPositionFilter(),e.createRootFilter(k)];k=e.createStepIterator(b,0,l,k);k.roundToClosestStep()&&(a?k.nextStep():k.previousStep())&&(m=h(e.convertDomToCursorRange({anchorNode:b,anchorOffset:0,focusNode:k.container(),focusOffset:k.offset()})),a?(d.setStart(b,0),d.setEnd(k.container(),k.offset())):(d.setStart(k.container(),k.offset()),d.setEnd(b,0)))}m&&f.enqueue(g(d));return void 0!== +m}var e=f.getOdtDocument(),s=odf.OdfUtils,m=core.DomUtils,x=!1,t=odf.Namespaces.textns,y=core.StepDirection.NEXT;this.isEnabled=function(){return x};this.enqueueParagraphSplittingOps=function(){if(!x)return!1;var a=e.getCursor(c),b=a.getSelectedRange(),d=h(e.getCursorSelection(c)),m=[],a=s.getParagraphElement(a.getNode()),l=a.getAttributeNS(t,"style-name")||"";0e.left&&(e=w(c)))b.focusNode=e.container,b.focusOffset=e.offset,d&&(b.anchorNode=b.focusNode,b.anchorOffset=b.focusOffset)}else D.isImage(b.focusNode.firstChild)&&1===b.focusOffset&&D.isCharacterFrame(b.focusNode)&&(e=w(b.focusNode))&&(b.anchorNode=b.focusNode=e.container,b.anchorOffset=b.focusOffset=e.offset);b.anchorNode&&b.focusNode&&(b=X.selectionToRange(b),X.selectRange(b.range,b.hasForwardSelection,0===a.button?a.detail:0));L.focus()}function A(a){var b;if(b=q(a.clientX,a.clientY))a= +b.container,b=b.offset,a={anchorNode:a,anchorOffset:b,focusNode:a,focusOffset:b},a=X.selectionToRange(a),X.selectRange(a.range,a.hasForwardSelection,2),L.focus()}function F(a){var b=k(a),d,e,f;ja.processRequests();ca&&(D.isImage(b)&&D.isCharacterFrame(b.parentNode)&&R.getSelection().isCollapsed?(X.selectImage(b.parentNode),L.focus()):la.isSelectorElement(b)?L.focus():W?(b=c.getSelectedRange(),e=b.collapsed,D.isImage(b.endContainer)&&0===b.endOffset&&D.isCharacterFrame(b.endContainer.parentNode)&& +(f=b.endContainer.parentNode,f=w(f))&&(b.setEnd(f.container,f.offset),e&&b.collapse(!1)),X.selectRange(b,c.hasForwardSelection(),0===a.button?a.detail:0),L.focus()):ta?u(a):(d=T.cloneEvent(a),aa=runtime.setTimeout(function(){u(d)},0)),na=0,W=ca=!1)}function B(b){var d=J.getCursor(a).getSelectedRange();d.collapsed||O.exportRangeToDataTransfer(b.dataTransfer,d)}function E(){ca&&L.focus();na=0;W=ca=!1}function H(a){F(a)}function I(a){var b=k(a),d=null;"annotationRemoveButton"===b.className?(runtime.assert(ea, +"Remove buttons are displayed on annotations while annotation editing is disabled in the controller."),d=b.parentNode.getElementsByTagNameNS(odf.Namespaces.officens,"annotation").item(0),ga.removeAnnotation(d),L.focus()):"webodf-draggable"!==b.getAttribute("class")&&F(a)}function Q(a){(a=a.data)&&(-1===a.indexOf("\n")?ha.insertText(a):pa.paste(a))}function N(a){return function(){a();return!0}}function z(b){return function(d){return J.getCursor(a).getSelectionType()===ops.OdtCursor.RangeSelection? +b(d):!0}}function Y(a){L.unsubscribe("keydown",C.handleEvent);L.unsubscribe("keypress",V.handleEvent);L.unsubscribe("keyup",$.handleEvent);L.unsubscribe("copy",g);L.unsubscribe("mousedown",r);L.unsubscribe("mousemove",ja.trigger);L.unsubscribe("mouseup",I);L.unsubscribe("contextmenu",H);L.unsubscribe("dragstart",B);L.unsubscribe("dragend",E);L.unsubscribe("click",oa.handleClick);L.unsubscribe("longpress",A);L.unsubscribe("drag",t);L.unsubscribe("dragstop",y);J.unsubscribe(ops.OdtDocument.signalOperationEnd, +fa.trigger);J.unsubscribe(ops.Document.signalCursorAdded,ka.registerCursor);J.unsubscribe(ops.Document.signalCursorRemoved,ka.removeCursor);J.unsubscribe(ops.OdtDocument.signalOperationEnd,e);a()}var R=runtime.getWindow(),J=l.getOdtDocument(),G=new gui.SessionConstraints,ba=new gui.SessionContext(l,a),T=core.DomUtils,D=odf.OdfUtils,O=new gui.MimeDataExporter,Z=new gui.Clipboard(O),C=new gui.KeyboardHandler,V=new gui.KeyboardHandler,$=new gui.KeyboardHandler,ca=!1,U=new odf.ObjectNameGenerator(J.getOdfCanvas().odfContainer(), +a),W=!1,P=null,aa,S=null,L=new gui.EventManager(J),ea=b.annotationsEnabled,ga=new gui.AnnotationController(l,G,a),da=new gui.DirectFormattingController(l,G,ba,a,U,b.directTextStylingEnabled,b.directParagraphStylingEnabled),ha=new gui.TextController(l,G,ba,a,da.createCursorStyleOp,da.createParagraphStyleOps),ma=new gui.ImageController(l,G,ba,a,U),la=new gui.ImageSelector(J.getOdfCanvas()),ia=J.createPositionIterator(J.getRootNode()),ja,fa,pa=new gui.PasteController(l,G,ba,a),ka=new gui.InputMethodEditor(a, +L),na=0,oa=new gui.HyperlinkClickHandler(J.getOdfCanvas().getElement,C,$),qa=new gui.HyperlinkController(l,G,ba,a),X=new gui.SelectionController(l,a),ua=new gui.MetadataController(l,a),K=gui.KeyboardHandler.Modifier,M=gui.KeyboardHandler.KeyCode,ra=-1!==R.navigator.appVersion.toLowerCase().indexOf("mac"),ta=-1!==["iPad","iPod","iPhone"].indexOf(R.navigator.platform),sa;runtime.assert(null!==R,"Expected to be run in an environment which has a global window, like a browser.");this.undo=m;this.redo= +x;this.insertLocalCursor=function(){runtime.assert(void 0===l.getOdtDocument().getCursor(a),"Inserting local cursor a second time.");var b=new ops.OpAddCursor;b.init({memberid:a});l.enqueue([b]);L.focus()};this.removeLocalCursor=function(){runtime.assert(void 0!==l.getOdtDocument().getCursor(a),"Removing local cursor without inserting before.");var b=new ops.OpRemoveCursor;b.init({memberid:a});l.enqueue([b])};this.startEditing=function(){ka.subscribe(gui.InputMethodEditor.signalCompositionStart,ha.removeCurrentSelection); +ka.subscribe(gui.InputMethodEditor.signalCompositionEnd,Q);L.subscribe("beforecut",n);L.subscribe("cut",p);L.subscribe("beforepaste",d);L.subscribe("paste",h);S&&S.initialize();L.setEditing(!0);oa.setModifier(ra?K.Meta:K.Ctrl);C.bind(M.Backspace,K.None,N(ha.removeTextByBackspaceKey),!0);C.bind(M.Delete,K.None,ha.removeTextByDeleteKey);C.bind(M.Tab,K.None,z(function(){ha.insertText("\t");return!0}));ra?(C.bind(M.Clear,K.None,ha.removeCurrentSelection),C.bind(M.B,K.Meta,z(da.toggleBold)),C.bind(M.I, +K.Meta,z(da.toggleItalic)),C.bind(M.U,K.Meta,z(da.toggleUnderline)),C.bind(M.L,K.MetaShift,z(da.alignParagraphLeft)),C.bind(M.E,K.MetaShift,z(da.alignParagraphCenter)),C.bind(M.R,K.MetaShift,z(da.alignParagraphRight)),C.bind(M.J,K.MetaShift,z(da.alignParagraphJustified)),ea&&C.bind(M.C,K.MetaShift,ga.addAnnotation),C.bind(M.Z,K.Meta,m),C.bind(M.Z,K.MetaShift,x)):(C.bind(M.B,K.Ctrl,z(da.toggleBold)),C.bind(M.I,K.Ctrl,z(da.toggleItalic)),C.bind(M.U,K.Ctrl,z(da.toggleUnderline)),C.bind(M.L,K.CtrlShift, +z(da.alignParagraphLeft)),C.bind(M.E,K.CtrlShift,z(da.alignParagraphCenter)),C.bind(M.R,K.CtrlShift,z(da.alignParagraphRight)),C.bind(M.J,K.CtrlShift,z(da.alignParagraphJustified)),ea&&C.bind(M.C,K.CtrlAlt,ga.addAnnotation),C.bind(M.Z,K.Ctrl,m),C.bind(M.Z,K.CtrlShift,x));V.setDefault(z(function(a){var b;b=null===a.which||void 0===a.which?String.fromCharCode(a.keyCode):0!==a.which&&0!==a.charCode?String.fromCharCode(a.which):null;return!b||a.altKey||a.ctrlKey||a.metaKey?!1:(ha.insertText(b),!0)})); +V.bind(M.Enter,K.None,z(ha.enqueueParagraphSplittingOps))};this.endEditing=function(){ka.unsubscribe(gui.InputMethodEditor.signalCompositionStart,ha.removeCurrentSelection);ka.unsubscribe(gui.InputMethodEditor.signalCompositionEnd,Q);L.unsubscribe("cut",p);L.unsubscribe("beforecut",n);L.unsubscribe("paste",h);L.unsubscribe("beforepaste",d);L.setEditing(!1);oa.setModifier(K.None);C.bind(M.Backspace,K.None,function(){return!0},!0);C.unbind(M.Delete,K.None);C.unbind(M.Tab,K.None);ra?(C.unbind(M.Clear, +K.None),C.unbind(M.B,K.Meta),C.unbind(M.I,K.Meta),C.unbind(M.U,K.Meta),C.unbind(M.L,K.MetaShift),C.unbind(M.E,K.MetaShift),C.unbind(M.R,K.MetaShift),C.unbind(M.J,K.MetaShift),ea&&C.unbind(M.C,K.MetaShift),C.unbind(M.Z,K.Meta),C.unbind(M.Z,K.MetaShift)):(C.unbind(M.B,K.Ctrl),C.unbind(M.I,K.Ctrl),C.unbind(M.U,K.Ctrl),C.unbind(M.L,K.CtrlShift),C.unbind(M.E,K.CtrlShift),C.unbind(M.R,K.CtrlShift),C.unbind(M.J,K.CtrlShift),ea&&C.unbind(M.C,K.CtrlAlt),C.unbind(M.Z,K.Ctrl),C.unbind(M.Z,K.CtrlShift));V.setDefault(null); +V.unbind(M.Enter,K.None)};this.getInputMemberId=function(){return a};this.getSession=function(){return l};this.getSessionConstraints=function(){return G};this.setUndoManager=function(a){S&&S.unsubscribe(gui.UndoManager.signalUndoStackChanged,s);if(S=a)S.setDocument(J),S.setPlaybackFunction(l.enqueue),S.subscribe(gui.UndoManager.signalUndoStackChanged,s)};this.getUndoManager=function(){return S};this.getMetadataController=function(){return ua};this.getAnnotationController=function(){return ga};this.getDirectFormattingController= +function(){return da};this.getHyperlinkClickHandler=function(){return oa};this.getHyperlinkController=function(){return qa};this.getImageController=function(){return ma};this.getSelectionController=function(){return X};this.getTextController=function(){return ha};this.getEventManager=function(){return L};this.getKeyboardHandlers=function(){return{keydown:C,keypress:V}};this.destroy=function(a){var b=[ja.destroy,fa.destroy,da.destroy,ka.destroy,L.destroy,oa.destroy,qa.destroy,ua.destroy,X.destroy, +ha.destroy,Y];sa&&b.unshift(sa.destroy);runtime.clearTimeout(aa);core.Async.destroyAll(b,a)};ja=core.Task.createRedrawTask(v);fa=core.Task.createRedrawTask(function(){var b=J.getCursor(a);if(b&&b.getSelectionType()===ops.OdtCursor.RegionSelection&&(b=D.getImageElements(b.getSelectedRange())[0])){la.select(b.parentNode);return}la.clearSelection()});C.bind(M.Left,K.None,z(X.moveCursorToLeft));C.bind(M.Right,K.None,z(X.moveCursorToRight));C.bind(M.Up,K.None,z(X.moveCursorUp));C.bind(M.Down,K.None,z(X.moveCursorDown)); +C.bind(M.Left,K.Shift,z(X.extendSelectionToLeft));C.bind(M.Right,K.Shift,z(X.extendSelectionToRight));C.bind(M.Up,K.Shift,z(X.extendSelectionUp));C.bind(M.Down,K.Shift,z(X.extendSelectionDown));C.bind(M.Home,K.None,z(X.moveCursorToLineStart));C.bind(M.End,K.None,z(X.moveCursorToLineEnd));C.bind(M.Home,K.Ctrl,z(X.moveCursorToDocumentStart));C.bind(M.End,K.Ctrl,z(X.moveCursorToDocumentEnd));C.bind(M.Home,K.Shift,z(X.extendSelectionToLineStart));C.bind(M.End,K.Shift,z(X.extendSelectionToLineEnd));C.bind(M.Up, +K.CtrlShift,z(X.extendSelectionToParagraphStart));C.bind(M.Down,K.CtrlShift,z(X.extendSelectionToParagraphEnd));C.bind(M.Home,K.CtrlShift,z(X.extendSelectionToDocumentStart));C.bind(M.End,K.CtrlShift,z(X.extendSelectionToDocumentEnd));ra?(C.bind(M.Left,K.Alt,z(X.moveCursorBeforeWord)),C.bind(M.Right,K.Alt,z(X.moveCursorPastWord)),C.bind(M.Left,K.Meta,z(X.moveCursorToLineStart)),C.bind(M.Right,K.Meta,z(X.moveCursorToLineEnd)),C.bind(M.Home,K.Meta,z(X.moveCursorToDocumentStart)),C.bind(M.End,K.Meta, +z(X.moveCursorToDocumentEnd)),C.bind(M.Left,K.AltShift,z(X.extendSelectionBeforeWord)),C.bind(M.Right,K.AltShift,z(X.extendSelectionPastWord)),C.bind(M.Left,K.MetaShift,z(X.extendSelectionToLineStart)),C.bind(M.Right,K.MetaShift,z(X.extendSelectionToLineEnd)),C.bind(M.Up,K.AltShift,z(X.extendSelectionToParagraphStart)),C.bind(M.Down,K.AltShift,z(X.extendSelectionToParagraphEnd)),C.bind(M.Up,K.MetaShift,z(X.extendSelectionToDocumentStart)),C.bind(M.Down,K.MetaShift,z(X.extendSelectionToDocumentEnd)), +C.bind(M.A,K.Meta,z(X.extendSelectionToEntireDocument))):(C.bind(M.Left,K.Ctrl,z(X.moveCursorBeforeWord)),C.bind(M.Right,K.Ctrl,z(X.moveCursorPastWord)),C.bind(M.Left,K.CtrlShift,z(X.extendSelectionBeforeWord)),C.bind(M.Right,K.CtrlShift,z(X.extendSelectionPastWord)),C.bind(M.A,K.Ctrl,z(X.extendSelectionToEntireDocument)));ta&&(sa=new gui.IOSSafariSupport(L));L.subscribe("keydown",C.handleEvent);L.subscribe("keypress",V.handleEvent);L.subscribe("keyup",$.handleEvent);L.subscribe("copy",g);L.subscribe("mousedown", +r);L.subscribe("mousemove",ja.trigger);L.subscribe("mouseup",I);L.subscribe("contextmenu",H);L.subscribe("dragstart",B);L.subscribe("dragend",E);L.subscribe("click",oa.handleClick);L.subscribe("longpress",A);L.subscribe("drag",t);L.subscribe("dragstop",y);J.subscribe(ops.OdtDocument.signalOperationEnd,fa.trigger);J.subscribe(ops.Document.signalCursorAdded,ka.registerCursor);J.subscribe(ops.Document.signalCursorRemoved,ka.removeCursor);J.subscribe(ops.OdtDocument.signalOperationEnd,e)}})();gui.CaretManager=function(f,l){function a(a){return k.hasOwnProperty(a)?k[a]:null}function c(){return Object.keys(k).map(function(a){return k[a]})}function b(a){var b=k[a];b&&(delete k[a],a===f.getInputMemberId()?(p.unsubscribe(ops.OdtDocument.signalProcessingBatchEnd,b.ensureVisible),p.unsubscribe(ops.Document.signalCursorMoved,b.refreshCursorBlinking),n.unsubscribe("compositionupdate",b.handleUpdate),n.unsubscribe("compositionend",b.handleUpdate),n.unsubscribe("focus",b.setFocus),n.unsubscribe("blur", +b.removeFocus),q.removeEventListener("focus",b.show,!1),q.removeEventListener("blur",b.hide,!1)):p.unsubscribe(ops.OdtDocument.signalProcessingBatchEnd,b.handleUpdate),b.destroy(function(){}))}var k={},q=runtime.getWindow(),p=f.getSession().getOdtDocument(),n=f.getEventManager();this.registerCursor=function(a,b,d){var e=a.getMemberId();a=new gui.Caret(a,l,b,d);k[e]=a;e===f.getInputMemberId()?(runtime.log("Starting to track input on new cursor of "+e),p.subscribe(ops.OdtDocument.signalProcessingBatchEnd, +a.ensureVisible),p.subscribe(ops.Document.signalCursorMoved,a.refreshCursorBlinking),n.subscribe("compositionupdate",a.handleUpdate),n.subscribe("compositionend",a.handleUpdate),n.subscribe("focus",a.setFocus),n.subscribe("blur",a.removeFocus),q.addEventListener("focus",a.show,!1),q.addEventListener("blur",a.hide,!1),a.setOverlayElement(n.getEventTrap())):p.subscribe(ops.OdtDocument.signalProcessingBatchEnd,a.handleUpdate);return a};this.getCaret=a;this.getCarets=c;this.destroy=function(a){var h= +c().map(function(a){return a.destroy});f.getSelectionController().setCaretXPositionLocator(null);p.unsubscribe(ops.Document.signalCursorRemoved,b);k={};core.Async.destroyAll(h,a)};f.getSelectionController().setCaretXPositionLocator(function(){var b=a(f.getInputMemberId()),c;b&&(c=b.getBoundingClientRect());return c?c.right:void 0});p.subscribe(ops.Document.signalCursorRemoved,b)};gui.EditInfoHandle=function(f){var l=[],a,c=f.ownerDocument,b=c.documentElement.namespaceURI;this.setEdits=function(f){l=f;var q,p,n,g;core.DomUtils.removeAllChildNodes(a);for(f=0;fe?(p=a(1,0),n=a(0.5,1E4-e),g=a(0.2,2E4-e)):1E4<=e&&2E4>e?(p=a(0.5,0),g=a(0.2,2E4-e)):p=a(0.2,0)};this.getEdits=function(){return f.getEdits()};this.clearEdits= +function(){f.clearEdits();k.setEdits([]);q.hasAttributeNS("urn:webodf:names:editinfo","editinfo:memberid")&&q.removeAttributeNS("urn:webodf:names:editinfo","editinfo:memberid")};this.getEditInfo=function(){return f};this.show=function(){q.style.display="block"};this.hide=function(){c.hideHandle();q.style.display="none"};this.showHandle=function(){k.show()};this.hideHandle=function(){k.hide()};this.destroy=function(a){runtime.clearTimeout(p);runtime.clearTimeout(n);runtime.clearTimeout(g);b.removeChild(q); +k.destroy(function(b){b?a(b):f.destroy(a)})};(function(){var a=f.getOdtDocument().getDOMDocument();q=a.createElementNS(a.documentElement.namespaceURI,"div");q.setAttribute("class","editInfoMarker");q.onmouseover=function(){c.showHandle()};q.onmouseout=function(){c.hideHandle()};b=f.getNode();b.appendChild(q);k=new gui.EditInfoHandle(b);l||c.hide()})()};gui.HyperlinkTooltipView=function(f,l){var a=core.DomUtils,c=odf.OdfUtils,b=runtime.getWindow(),k,q,p;runtime.assert(null!==b,"Expected to be run in an environment which has a global window, like a browser.");this.showTooltip=function(n){var g=n.target||n.srcElement,h=f.getSizer(),d=f.getZoomLevel(),e;a:{for(;g;){if(c.isHyperlink(g))break a;if(c.isParagraph(g)||c.isInlineRoot(g))break;g=g.parentNode}g=null}if(g){a.containsNode(h,p)||h.appendChild(p);e=q;var s;switch(l()){case gui.KeyboardHandler.Modifier.Ctrl:s= +runtime.tr("Ctrl-click to follow link");break;case gui.KeyboardHandler.Modifier.Meta:s=runtime.tr("\u2318-click to follow link");break;default:s=""}e.textContent=s;k.textContent=c.getHyperlinkTarget(g);p.style.display="block";e=b.innerWidth-p.offsetWidth-15;g=n.clientX>e?e:n.clientX+15;e=b.innerHeight-p.offsetHeight-10;n=n.clientY>e?e:n.clientY+10;h=h.getBoundingClientRect();g=(g-h.left)/d;n=(n-h.top)/d;p.style.left=g+"px";p.style.top=n+"px"}};this.hideTooltip=function(){p.style.display="none"};this.destroy= +function(a){p.parentNode&&p.parentNode.removeChild(p);a()};(function(){var a=f.getElement().ownerDocument;k=a.createElement("span");q=a.createElement("span");k.className="webodf-hyperlinkTooltipLink";q.className="webodf-hyperlinkTooltipText";p=a.createElement("div");p.className="webodf-hyperlinkTooltip";p.appendChild(k);p.appendChild(q);f.getElement().appendChild(p)})()};gui.OdfFieldView=function(f){function l(){var a=odf.OdfSchema.getFields().map(function(a){return a.replace(":","|")}),c=a.join(",\n")+"\n{ background-color: #D0D0D0; }\n",a=a.map(function(a){return a+":empty::after"}).join(",\n")+"\n{ content:' '; white-space: pre; }\n";return c+"\n"+a}var a,c=f.getElement().ownerDocument;this.showFieldHighlight=function(){a.appendChild(c.createTextNode(l()))};this.hideFieldHighlight=function(){for(var b=a.sheet,c=b.cssRules;c.length;)b.deleteRule(c.length-1)};this.destroy= +function(b){a.parentNode&&a.parentNode.removeChild(a);b()};a=function(){var a=c.getElementsByTagName("head").item(0),f=c.createElement("style"),l="";f.type="text/css";f.media="screen, print, handheld, projection";odf.Namespaces.forEachPrefix(function(a,b){l+="@namespace "+a+" url("+b+");\n"});f.appendChild(c.createTextNode(l));a.appendChild(f);return f}()};gui.ShadowCursor=function(f){var l=f.getDOMDocument().createRange(),a=!0;this.removeFromDocument=function(){};this.getMemberId=function(){return gui.ShadowCursor.ShadowCursorMemberId};this.getSelectedRange=function(){return l};this.setSelectedRange=function(c,b){l=c;a=!1!==b};this.hasForwardSelection=function(){return a};this.getDocument=function(){return f};this.getSelectionType=function(){return ops.OdtCursor.RangeSelection};l.setStart(f.getRootNode(),0)};gui.ShadowCursor.ShadowCursorMemberId="";gui.SelectionView=function(f){};gui.SelectionView.prototype.rerender=function(){};gui.SelectionView.prototype.show=function(){};gui.SelectionView.prototype.hide=function(){};gui.SelectionView.prototype.destroy=function(f){};gui.SelectionViewManager=function(f){function l(){return Object.keys(a).map(function(c){return a[c]})}var a={};this.getSelectionView=function(c){return a.hasOwnProperty(c)?a[c]:null};this.getSelectionViews=l;this.removeSelectionView=function(c){a.hasOwnProperty(c)&&(a[c].destroy(function(){}),delete a[c])};this.hideSelectionView=function(c){a.hasOwnProperty(c)&&a[c].hide()};this.showSelectionView=function(c){a.hasOwnProperty(c)&&a[c].show()};this.rerenderSelectionViews=function(){Object.keys(a).forEach(function(c){a[c].rerender()})}; +this.registerCursor=function(c,b){var k=c.getMemberId(),l=new f(c);b?l.show():l.hide();return a[k]=l};this.destroy=function(a){function b(l,p){p?a(p):l .webodf-draggable"), +a=gui.ShadowCursor.ShadowCursorMemberId,e(".webodf-selectionOverlay","{ fill: "+d+"; stroke: "+d+";}",""),e(".webodf-touchEnabled .webodf-selectionOverlay","{ display: block; }"," > .webodf-draggable"))}function g(a){var b,d;for(d in u)u.hasOwnProperty(d)&&(b=u[d],a?b.show():b.hide())}function h(a){b.getCarets().forEach(function(b){a?b.showHandle():b.hideHandle()})}function d(a){var b=a.getMemberId();a=a.getProperties();n(b,a.fullName,a.color)}function e(d){var e=d.getMemberId(),c=a.getOdtDocument().getMember(e).getProperties(); +b.registerCursor(d,H,I);k.registerCursor(d,!0);if(d=b.getCaret(e))d.setAvatarImageUrl(c.imageUrl),d.setColor(c.color);runtime.log("+++ View here +++ eagerly created an Caret for '"+e+"'! +++")}function s(a){a=a.getMemberId();var d=k.getSelectionView(l),e=k.getSelectionView(gui.ShadowCursor.ShadowCursorMemberId),c=b.getCaret(l);a===l?(e.hide(),d&&d.show(),c&&c.show()):a===gui.ShadowCursor.ShadowCursorMemberId&&(e.show(),d&&d.hide(),c&&c.hide())}function m(a){k.removeSelectionView(a)}function x(b){var d= +b.paragraphElement,e=b.memberId;b=b.timeStamp;var c,f="",g=d.getElementsByTagNameNS(w,"editinfo").item(0);g?(f=g.getAttributeNS(w,"id"),c=u[f]):(f=Math.random().toString(),c=new ops.EditInfo(d,a.getOdtDocument()),c=new gui.EditInfoMarker(c,E),g=d.getElementsByTagNameNS(w,"editinfo").item(0),g.setAttributeNS(w,"id",f),u[f]=c);c.addEdit(e,new Date(b));B.trigger()}function t(){var b;r.hasChildNodes()&&core.DomUtils.removeAllChildNodes(r);!0===c.getState(gui.CommonConstraints.EDIT.ANNOTATIONS.ONLY_DELETE_OWN)&& +(b=a.getOdtDocument().getMember(l))&&(b=b.getProperties().fullName,r.appendChild(document.createTextNode(".annotationWrapper:not([creator = '"+b+"']) .annotationRemoveButton { display: none; }")))}function y(a){var b=Object.keys(u).map(function(a){return u[a]});A.unsubscribe(ops.Document.signalMemberAdded,d);A.unsubscribe(ops.Document.signalMemberUpdated,d);A.unsubscribe(ops.Document.signalCursorAdded,e);A.unsubscribe(ops.Document.signalCursorRemoved,m);A.unsubscribe(ops.OdtDocument.signalParagraphChanged, +x);A.unsubscribe(ops.Document.signalCursorMoved,s);A.unsubscribe(ops.OdtDocument.signalParagraphChanged,k.rerenderSelectionViews);A.unsubscribe(ops.OdtDocument.signalTableAdded,k.rerenderSelectionViews);A.unsubscribe(ops.OdtDocument.signalParagraphStyleModified,k.rerenderSelectionViews);c.unsubscribe(gui.CommonConstraints.EDIT.ANNOTATIONS.ONLY_DELETE_OWN,t);A.unsubscribe(ops.Document.signalMemberAdded,t);A.unsubscribe(ops.Document.signalMemberUpdated,t);v.parentNode.removeChild(v);r.parentNode.removeChild(r); +(function Y(d,e){e?a(e):db.length;a&&f(b);return a}function a(b,a){function c(f){b[f]===a&&d.push(f)}var d=[];b&&["style:parent-style-name","style:next-style-name"].forEach(c);return d}function d(b,a){function c(d){b[d]===a&&delete b[d]}b&&["style:parent-style-name","style:next-style-name"].forEach(c)}function c(b){var a={};Object.keys(b).forEach(function(d){a[d]="object"===typeof b[d]?c(b[d]):b[d]});return a}function h(b, -a,c,d){var f,h=!1,k=!1,m,l=[];d&&d.attributes&&(l=d.attributes.split(","));b&&(c||0=a.position+a.length)){f=d?b:a;h=d?a:b;if(b.position!==a.position||b.length!==a.length)r=c(f),x=c(h);a=m(h.setProperties,null,f.setProperties,null,"style:text-properties");if(a.majorChanged||a.minorChanged)k=[],b=[],l=f.position+f.length,p=h.position+h.length,h.positionl?a.minorChanged&&(r=x,r.position=l,r.length=p-l,b.push(r),h.length=l-h.position):l>p&&a.majorChanged&&(r.position=p,r.length=l-p,k.push(r),f.length=p-f.position),f.setProperties&&q(f.setProperties)&&k.push(f),h.setProperties&&q(h.setProperties)&&b.push(h),d?(l=k,k=b):l=b}return{opSpecsA:l,opSpecsB:k}},InsertText:function(b,a){a.position<=b.position?b.position+=a.text.length:a.position<=b.position+b.length&& -(b.length+=a.text.length);return{opSpecsA:[b],opSpecsB:[a]}},MergeParagraph:function(b,a){var c=b.position,d=b.position+b.length;c>=a.sourceStartPosition&&(c-=1);d>=a.sourceStartPosition&&(d-=1);b.position=c;b.length=d-c;return{opSpecsA:[b],opSpecsB:[a]}},MoveCursor:l,RemoveCursor:l,RemoveMember:l,RemoveStyle:l,RemoveText:function(b,a){var c=b.position+b.length,d=a.position+a.length,f=[b],h=[a];d<=b.position?b.position-=a.length:a.positiona.position?b.position+=a.text.length:c?a.position+=b.text.length:b.position+=a.text.length; -return{opSpecsA:[b],opSpecsB:[a]}},MergeParagraph:function(b,a){b.position>=a.sourceStartPosition?b.position-=1:(b.positionb.position&&(a.position+=b.text.length);return{opSpecsA:[b], -opSpecsB:[a]}},SplitParagraph:function(b,a){b.position=b.sourceStartPosition&&(f-=1);c>=b.sourceStartPosition&& -(c-=1);0<=a.length?(a.position=f,a.length=c-f):(a.position=c,a.length=f-c);return{opSpecsA:[b],opSpecsB:[a]}},RemoveCursor:l,RemoveMember:l,RemoveStyle:l,RemoveText:function(b,a){a.position>=b.sourceStartPosition?a.position-=1:(a.positionb.sourceStartPosition)a.position-= -1;else if(a.position===b.destinationStartPosition||a.position===b.sourceStartPosition)a.position=b.destinationStartPosition,b.paragraphStyleName=a.styleName;return{opSpecsA:c,opSpecsB:d}},SplitParagraph:function(b,a){var c,d=[b],f=[a];a.position=b.destinationStartPosition&&a.position=b.sourceStartPosition&&(a.position-=1,a.sourceParagraphPosition-=1);return{opSpecsA:d,opSpecsB:f}},UpdateMember:l,UpdateMetadata:l,UpdateParagraphStyle:l},MoveCursor:{MoveCursor:l,RemoveCursor:function(b, -a){return{opSpecsA:b.memberid===a.memberid?[]:[b],opSpecsB:[a]}},RemoveMember:l,RemoveStyle:l,RemoveText:function(b,a){var c=k(b),d=b.position+b.length,h=a.position+a.length;h<=b.position?b.position-=a.length:a.positiond.position?a.position+=1:a.position===d.sourceParagraphPosition&&(d.paragraphStyleName=a.styleName,h=c(a),h.position=d.position+1,f.push(h));return{opSpecsA:f,opSpecsB:g}},UpdateMember:l,UpdateMetadata:l,UpdateParagraphStyle:l},SplitParagraph:{SplitParagraph:function(a,c,d){var f,h;a.positiona.length;b&&f(a);return b}function a(a,b){function c(g){a[g]===b&&f.push(g)}var f=[];a&&["style:parent-style-name","style:next-style-name"].forEach(c);return f}function c(a,b){function c(f){a[f]===b&&delete a[f]}a&&["style:parent-style-name","style:next-style-name"].forEach(c)}function b(a){var e={};Object.keys(a).forEach(function(c){e[c]="object"===typeof a[c]?b(a[c]):a[c]});return e}function k(a, +b,c,f){var g,h=!1,k=!1,l,n=[];f&&f.attributes&&(n=f.attributes.split(","));a&&(c||0=e.position+e.length)){f=c?a:e;g=c?e:a;if(a.position!==e.position||a.length!==e.length)p=b(f),w=b(g);e=n(g.setProperties,null,f.setProperties,null,"style:text-properties");if(e.majorChanged||e.minorChanged)h=[],a=[],k=f.position+f.length,l=g.position+g.length,g.positionk?e.minorChanged&&(p=w,p.position=k,p.length=l-k,a.push(p),g.length=k-g.position):k>l&&e.majorChanged&&(p.position=l,p.length=k-l,h.push(p),f.length=l-f.position),f.setProperties&&q(f.setProperties)&&h.push(f),g.setProperties&&q(g.setProperties)&&a.push(g),c?(k=h,h=a):k=a}return{opSpecsA:k,opSpecsB:h}},InsertText:function(a,b){b.position<=a.position?a.position+=b.text.length:b.position<=a.position+a.length&& +(a.length+=b.text.length);return{opSpecsA:[a],opSpecsB:[b]}},MergeParagraph:function(a,b){var c=a.position,f=a.position+a.length;c>=b.sourceStartPosition&&(c-=1);f>=b.sourceStartPosition&&(f-=1);a.position=c;a.length=f-c;return{opSpecsA:[a],opSpecsB:[b]}},MoveCursor:g,RemoveCursor:g,RemoveMember:g,RemoveStyle:g,RemoveText:function(a,b){var c=a.position+a.length,f=b.position+b.length,g=[a],h=[b];f<=a.position?a.position-=b.length:b.positionb.position?a.position+=b.text.length:c?b.position+=a.text.length:a.position+=b.text.length; +return{opSpecsA:[a],opSpecsB:[b]}},MergeParagraph:function(a,b){a.position>=b.sourceStartPosition?a.position-=1:(a.positiona.position&&(b.position+=a.text.length);return{opSpecsA:[a], +opSpecsB:[b]}},SplitParagraph:function(a,b){a.position=a.sourceStartPosition&&(g-=1);c>=a.sourceStartPosition&& +(c-=1);0<=b.length?(b.position=g,b.length=c-g):(b.position=c,b.length=g-c);return{opSpecsA:[a],opSpecsB:[b]}},RemoveCursor:g,RemoveMember:g,RemoveStyle:g,RemoveText:function(a,b){b.position>=a.sourceStartPosition?b.position-=1:(b.positiona.sourceStartPosition)b.position-= +1;else if(b.position===a.destinationStartPosition||b.position===a.sourceStartPosition)b.position=a.destinationStartPosition,a.paragraphStyleName=b.styleName;return{opSpecsA:c,opSpecsB:f}},SplitParagraph:function(a,b){var c,f=[a],g=[b];b.position=a.destinationStartPosition&&b.position=a.sourceStartPosition&&(b.position-=1,b.sourceParagraphPosition-=1);return{opSpecsA:f,opSpecsB:g}},UpdateMember:g,UpdateMetadata:g,UpdateParagraphStyle:g},MoveCursor:{MoveCursor:g,RemoveCursor:function(a, +b){return{opSpecsA:a.memberid===b.memberid?[]:[a],opSpecsB:[b]}},RemoveMember:g,RemoveStyle:g,RemoveText:function(a,b){var c=l(a),g=a.position+a.length,h=b.position+b.length;h<=a.position?a.position-=b.length:b.positionc.position?a.position+=1:a.position===c.sourceParagraphPosition&&(c.paragraphStyleName=a.styleName,h=b(a),h.position=c.position+1,f.push(h));return{opSpecsA:f,opSpecsB:g}},UpdateMember:g,UpdateMetadata:g,UpdateParagraphStyle:g},SplitParagraph:{SplitParagraph:function(a,b,c){var f,g;a.position 1) { - original_onload(); - var matches = (/&title=([^&]+)&/).exec(window.location.hash); - if(matches && matches.length > 1) - { - document.title = decodeURIComponent(matches[1]); - document.getElementById('documentName').innerHTML = document.title; - - } - }; + parameters.title = decodeURIComponent(matches[1]); + } + return original_Viewer(plugin, parameters); } From 5d73bc0854937fd8ea9aea796cffdf6d35f5ffd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matja=C5=BE=20Mozeti=C4=8D?= Date: Mon, 3 Aug 2015 13:38:45 +0200 Subject: [PATCH 11/41] Translations and templates sync --- attachment_preview/i18n/nl.po | 8 +++++--- attachment_preview/i18n/sl.po | 9 ++++----- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/attachment_preview/i18n/nl.po b/attachment_preview/i18n/nl.po index 8b4c3ff264a..62ab7a2ab06 100644 --- a/attachment_preview/i18n/nl.po +++ b/attachment_preview/i18n/nl.po @@ -1,19 +1,21 @@ # Translation of Odoo Server. # This file contains the translation of the following modules: -# * attachment_preview +# * attachment_preview # msgid "" msgstr "" "Project-Id-Version: Odoo Server 8.0\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-01-15 11:04+0000\n" -"PO-Revision-Date: 2015-01-15 11:04+0000\n" +"PO-Revision-Date: 2015-08-03 13:36+0200\n" "Last-Translator: <>\n" "Language-Team: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: \n" +"Content-Transfer-Encoding: 8bit\n" "Plural-Forms: \n" +"Language: nl\n" +"X-Generator: Poedit 1.8.2\n" #. module: attachment_preview #. openerp-web diff --git a/attachment_preview/i18n/sl.po b/attachment_preview/i18n/sl.po index ce57a03b892..5e646c5139c 100644 --- a/attachment_preview/i18n/sl.po +++ b/attachment_preview/i18n/sl.po @@ -1,6 +1,6 @@ # Translation of Odoo Server. # This file contains the translation of the following modules: -# * attachment_preview +# * attachment_preview # # Matjaž Mozetič , 2015. msgid "" @@ -8,15 +8,15 @@ msgstr "" "Project-Id-Version: Odoo Server 8.0\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-01-15 11:04+0000\n" -"PO-Revision-Date: 2015-04-05 09:03+0200\n" +"PO-Revision-Date: 2015-08-03 13:36+0200\n" "Last-Translator: Matjaž Mozetič \n" "Language-Team: Slovenian \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: \n" +"Content-Transfer-Encoding: 8bit\n" "Plural-Forms: \n" "Language: sl\n" -"X-Generator: Lokalize 1.5\n" +"X-Generator: Poedit 1.8.2\n" #. module: attachment_preview #. openerp-web @@ -24,4 +24,3 @@ msgstr "" #, python-format msgid "Preview %s" msgstr "Predogled %s" - From a74321600286016bb433053b00b1161475afd07c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Bidoul?= Date: Fri, 9 Oct 2015 10:00:24 +0200 Subject: [PATCH 12/41] [UPD] prefix versions with 8.0 --- attachment_preview/__openerp__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/attachment_preview/__openerp__.py b/attachment_preview/__openerp__.py index 34f2c590567..fa62e146aef 100644 --- a/attachment_preview/__openerp__.py +++ b/attachment_preview/__openerp__.py @@ -20,7 +20,7 @@ ############################################################################## { "name": "Preview attachments", - "version": "1.1", + "version": "8.0.1.1.0", "author": "Therp BV,Odoo Community Association (OCA)", "license": "AGPL-3", "complexity": "normal", From 5a6921171ea79567a0e0b7aed996892953125788 Mon Sep 17 00:00:00 2001 From: "Pedro M. Baeza" Date: Wed, 14 Oct 2015 03:16:56 +0200 Subject: [PATCH 13/41] [MIG] Make modules uninstallable --- attachment_preview/__openerp__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/attachment_preview/__openerp__.py b/attachment_preview/__openerp__.py index fa62e146aef..01012f0d542 100644 --- a/attachment_preview/__openerp__.py +++ b/attachment_preview/__openerp__.py @@ -38,7 +38,7 @@ "test": [ ], "auto_install": False, - "installable": True, + 'installable': False, "application": False, "external_dependencies": { 'python': [], From 989e5578f729a70d1ecfe2574ac64c7860cfaf35 Mon Sep 17 00:00:00 2001 From: "Pedro M. Baeza" Date: Thu, 6 Oct 2016 14:52:57 +0200 Subject: [PATCH 14/41] [MIG] Rename manifest files --- attachment_preview/{__openerp__.py => __manifest__.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename attachment_preview/{__openerp__.py => __manifest__.py} (100%) diff --git a/attachment_preview/__openerp__.py b/attachment_preview/__manifest__.py similarity index 100% rename from attachment_preview/__openerp__.py rename to attachment_preview/__manifest__.py From 463a2b5d0b791fbc986188dfcf4f287b7fa9806d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Bidoul=20=28ACSONE=29?= Date: Fri, 15 Jun 2018 23:17:26 +0200 Subject: [PATCH 15/41] remove obsolete .pot files [ci skip] --- .../i18n/attachment_preview.pot | 23 ------------------- 1 file changed, 23 deletions(-) delete mode 100644 attachment_preview/i18n/attachment_preview.pot diff --git a/attachment_preview/i18n/attachment_preview.pot b/attachment_preview/i18n/attachment_preview.pot deleted file mode 100644 index 8aa0f4dccc8..00000000000 --- a/attachment_preview/i18n/attachment_preview.pot +++ /dev/null @@ -1,23 +0,0 @@ -# Translation of Odoo Server. -# This file contains the translation of the following modules: -# * attachment_preview -# -msgid "" -msgstr "" -"Project-Id-Version: Odoo Server 8.0\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-01-15 11:04+0000\n" -"PO-Revision-Date: 2015-01-15 11:04+0000\n" -"Last-Translator: <>\n" -"Language-Team: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: \n" -"Plural-Forms: \n" - -#. module: attachment_preview -#. openerp-web -#: code:multiple:42 -#, python-format -msgid "Preview %s" -msgstr "" From e2f14827434ebfedaae745dc3aecd2a6ad50ed7d Mon Sep 17 00:00:00 2001 From: tarteo Date: Wed, 11 Jul 2018 14:13:08 +0200 Subject: [PATCH 16/41] [MIG] attachment_preview: Migration to 11.0 [FIX] Lint [FIX] lint and flake [ADD] tests [ADD] tests [ADD] tests [ADD] Tests [ADD] Package python-magic [ADD] Tests [FIX] Lint --- attachment_preview/README.rst | 75 +- attachment_preview/__init__.py | 25 +- attachment_preview/__manifest__.py | 43 +- .../i18n/attachment_preview.pot | 28 + attachment_preview/i18n/de.po | 33 + attachment_preview/i18n/es.po | 33 + attachment_preview/i18n/it.po | 33 + attachment_preview/i18n/nl.po | 29 +- attachment_preview/i18n/pt_PT.po | 33 + attachment_preview/i18n/sl.po | 30 +- attachment_preview/i18n/zh_CN.po | 33 + attachment_preview/model/__init__.py | 21 - attachment_preview/model/ir_attachment.py | 68 - attachment_preview/models/__init__.py | 4 + attachment_preview/models/ir_attachment.py | 75 + attachment_preview/readme/CONTRIBUTORS.rst | 2 + attachment_preview/readme/CREDITS.rst | 4 + attachment_preview/readme/DESCRIPTION.rst | 3 + attachment_preview/readme/INSTALL.rst | 4 + attachment_preview/readme/USAGE.rst | 2 + .../static/description/index.html | 448 +++++ .../static/lib/ViewerJS/compatibility.js | 29 +- .../static/lib/ViewerJS/index.html | 60 +- attachment_preview/static/lib/ViewerJS/pdf.js | 389 +++-- .../static/lib/ViewerJS/pdf.worker.js | 447 +++-- .../static/lib/ViewerJS/pdfjsversion.js | 2 +- .../static/lib/ViewerJS/text_layer_builder.js | 90 +- .../static/lib/ViewerJS/ui_utils.js | 99 +- .../static/lib/ViewerJS/webodf.js | 1468 ++++++++++------- .../static/src/css/attachment_preview.css | 37 +- .../static/src/js/attachment_preview.js | 340 ++-- .../static/src/js/viewerjs_tweaks.js | 41 +- .../static/src/xml/attachment_preview.xml | 15 +- attachment_preview/templates/assets.xml | 9 + attachment_preview/tests/__init__.py | 4 + .../tests/test_attachment_preview.py | 46 + .../view/attachment_preview.xml | 11 - 37 files changed, 2746 insertions(+), 1367 deletions(-) create mode 100644 attachment_preview/i18n/attachment_preview.pot create mode 100644 attachment_preview/i18n/de.po create mode 100644 attachment_preview/i18n/es.po create mode 100644 attachment_preview/i18n/it.po create mode 100644 attachment_preview/i18n/pt_PT.po create mode 100644 attachment_preview/i18n/zh_CN.po delete mode 100644 attachment_preview/model/__init__.py delete mode 100644 attachment_preview/model/ir_attachment.py create mode 100644 attachment_preview/models/__init__.py create mode 100644 attachment_preview/models/ir_attachment.py create mode 100644 attachment_preview/readme/CONTRIBUTORS.rst create mode 100644 attachment_preview/readme/CREDITS.rst create mode 100644 attachment_preview/readme/DESCRIPTION.rst create mode 100644 attachment_preview/readme/INSTALL.rst create mode 100644 attachment_preview/readme/USAGE.rst create mode 100644 attachment_preview/static/description/index.html create mode 100644 attachment_preview/templates/assets.xml create mode 100644 attachment_preview/tests/__init__.py create mode 100644 attachment_preview/tests/test_attachment_preview.py delete mode 100644 attachment_preview/view/attachment_preview.xml diff --git a/attachment_preview/README.rst b/attachment_preview/README.rst index 4f6feebeb8d..197d487f25a 100644 --- a/attachment_preview/README.rst +++ b/attachment_preview/README.rst @@ -1,15 +1,44 @@ +=================== Preview attachments =================== +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fknowledge-lightgray.png?logo=github + :target: https://github.com/OCA/knowledge/tree/11.0/attachment_preview + :alt: OCA/knowledge +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/knowledge-11-0/knowledge-11-0-attachment_preview + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png + :target: https://runbot.odoo-community.org/runbot/118/11.0 + :alt: Try me on Runbot + +|badge1| |badge2| |badge3| |badge4| |badge5| + This addon allows to preview attachments supported by http://viewerjs.org. Currently, that's most Libreoffice files and PDFs. +**Table of contents** + +.. contents:: + :local: + Installation ============ For filetype recognition, you'll get the best results by installing -``python-magic``:: +``python-magic``: sudo apt-get install python-magic @@ -19,28 +48,52 @@ Usage The module adds a little print preview icon right of download links for attachments or binary fields. +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + Credits ======= -Addon icon ----------- +Authors +~~~~~~~ -* courtesy of http://commons.wikimedia.org/wiki/Crystal_Clear +* Therp BV +* Onestein Contributors ------------- +~~~~~~~~~~~~ * Holger Brunn +* Dennis Sluijk + +Other credits +~~~~~~~~~~~~~ -Maintainer +Addon icon ---------- -.. image:: http://odoo-community.org/logo.png - :alt: Odoo Community Association - :target: http://odoo-community.org +* courtesy of http://commons.wikimedia.org/wiki/Crystal_Clear + +Maintainers +~~~~~~~~~~~ This module is maintained by the OCA. -OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use. +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +This module is part of the `OCA/knowledge `_ project on GitHub. -To contribute to this module, please visit http://odoo-community.org. +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/attachment_preview/__init__.py b/attachment_preview/__init__.py index fcf92314d85..5b89c089ef2 100644 --- a/attachment_preview/__init__.py +++ b/attachment_preview/__init__.py @@ -1,21 +1,4 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# This module copyright (C) 2014 Therp BV (). -# -# 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 . -# -############################################################################## -from . import model +# Copyright 2014 Therp BV () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import models diff --git a/attachment_preview/__manifest__.py b/attachment_preview/__manifest__.py index 01012f0d542..7020cd32f9d 100644 --- a/attachment_preview/__manifest__.py +++ b/attachment_preview/__manifest__.py @@ -1,46 +1,23 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# This module copyright (C) 2014 Therp BV (). -# -# 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 . -# -############################################################################## +# Copyright 2014 Therp BV () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + { "name": "Preview attachments", - "version": "8.0.1.1.0", - "author": "Therp BV,Odoo Community Association (OCA)", + "version": "11.0.1.2.0", + "author": "Therp BV," + "Onestein," + "Odoo Community Association (OCA)", "license": "AGPL-3", - "complexity": "normal", - 'summary': 'Preview attachments supported by Viewer.js', + "summary": 'Preview attachments supported by Viewer.js', "category": "Knowledge Management", "depends": [ 'web', ], "data": [ - "view/attachment_preview.xml", + "templates/assets.xml", ], "qweb": [ 'static/src/xml/attachment_preview.xml', ], - "test": [ - ], - "auto_install": False, - 'installable': False, - "application": False, - "external_dependencies": { - 'python': [], - }, + "installable": True, } diff --git a/attachment_preview/i18n/attachment_preview.pot b/attachment_preview/i18n/attachment_preview.pot new file mode 100644 index 00000000000..99f77a5a242 --- /dev/null +++ b/attachment_preview/i18n/attachment_preview.pot @@ -0,0 +1,28 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * attachment_preview +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 11.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: attachment_preview +#. openerp-web +#: code:addons/attachment_preview/static/src/js/attachment_preview.js:102 +#: code:addons/attachment_preview/static/src/js/attachment_preview.js:128 +#, python-format +msgid "Preview %s" +msgstr "" + +#. module: attachment_preview +#: model:ir.model,name:attachment_preview.model_ir_attachment +msgid "ir.attachment" +msgstr "" + diff --git a/attachment_preview/i18n/de.po b/attachment_preview/i18n/de.po new file mode 100644 index 00000000000..6976f4afc7f --- /dev/null +++ b/attachment_preview/i18n/de.po @@ -0,0 +1,33 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * attachment_preview +# +# Translators: +# Rudolf Schnapka , 2015 +msgid "" +msgstr "" +"Project-Id-Version: knowledge (8.0)\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-12-08 08:32+0000\n" +"PO-Revision-Date: 2015-11-25 09:41+0000\n" +"Last-Translator: Rudolf Schnapka \n" +"Language-Team: German (http://www.transifex.com/oca/OCA-knowledge-8-0/" +"language/de/)\n" +"Language: de\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: attachment_preview +#. openerp-web +#: code:addons/attachment_preview/static/src/js/attachment_preview.js:102 +#: code:addons/attachment_preview/static/src/js/attachment_preview.js:128 +#, python-format +msgid "Preview %s" +msgstr "Vorschau %s" + +#. module: attachment_preview +#: model:ir.model,name:attachment_preview.model_ir_attachment +msgid "ir.attachment" +msgstr "" diff --git a/attachment_preview/i18n/es.po b/attachment_preview/i18n/es.po new file mode 100644 index 00000000000..a2fb4966681 --- /dev/null +++ b/attachment_preview/i18n/es.po @@ -0,0 +1,33 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * attachment_preview +# +# Translators: +# Antonio Trueba, 2016 +msgid "" +msgstr "" +"Project-Id-Version: knowledge (8.0)\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-12-19 10:18+0000\n" +"PO-Revision-Date: 2016-01-25 18:15+0000\n" +"Last-Translator: Antonio Trueba\n" +"Language-Team: Spanish (http://www.transifex.com/oca/OCA-knowledge-8-0/" +"language/es/)\n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: attachment_preview +#. openerp-web +#: code:addons/attachment_preview/static/src/js/attachment_preview.js:102 +#: code:addons/attachment_preview/static/src/js/attachment_preview.js:128 +#, python-format +msgid "Preview %s" +msgstr "Previsualizar %s" + +#. module: attachment_preview +#: model:ir.model,name:attachment_preview.model_ir_attachment +msgid "ir.attachment" +msgstr "" diff --git a/attachment_preview/i18n/it.po b/attachment_preview/i18n/it.po new file mode 100644 index 00000000000..052c4212ffb --- /dev/null +++ b/attachment_preview/i18n/it.po @@ -0,0 +1,33 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * attachment_preview +# +# Translators: +# Paolo Valier, 2016 +msgid "" +msgstr "" +"Project-Id-Version: knowledge (8.0)\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-03-05 11:50+0000\n" +"PO-Revision-Date: 2016-03-13 16:56+0000\n" +"Last-Translator: Paolo Valier\n" +"Language-Team: Italian (http://www.transifex.com/oca/OCA-knowledge-8-0/" +"language/it/)\n" +"Language: it\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: attachment_preview +#. openerp-web +#: code:addons/attachment_preview/static/src/js/attachment_preview.js:102 +#: code:addons/attachment_preview/static/src/js/attachment_preview.js:128 +#, python-format +msgid "Preview %s" +msgstr "Anteprima %s" + +#. module: attachment_preview +#: model:ir.model,name:attachment_preview.model_ir_attachment +msgid "ir.attachment" +msgstr "" diff --git a/attachment_preview/i18n/nl.po b/attachment_preview/i18n/nl.po index 62ab7a2ab06..0103f90eeab 100644 --- a/attachment_preview/i18n/nl.po +++ b/attachment_preview/i18n/nl.po @@ -1,25 +1,32 @@ # Translation of Odoo Server. # This file contains the translation of the following modules: -# * attachment_preview +# * attachment_preview # +# Translators: msgid "" msgstr "" -"Project-Id-Version: Odoo Server 8.0\n" +"Project-Id-Version: knowledge (8.0)\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-01-15 11:04+0000\n" -"PO-Revision-Date: 2015-08-03 13:36+0200\n" -"Last-Translator: <>\n" -"Language-Team: \n" +"POT-Creation-Date: 2015-12-08 08:32+0000\n" +"PO-Revision-Date: 2015-11-07 12:44+0000\n" +"Last-Translator: OCA Transbot \n" +"Language-Team: Dutch (http://www.transifex.com/oca/OCA-knowledge-8-0/" +"language/nl/)\n" +"Language: nl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: \n" -"Language: nl\n" -"X-Generator: Poedit 1.8.2\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" #. module: attachment_preview #. openerp-web -#: code:multiple:42 +#: code:addons/attachment_preview/static/src/js/attachment_preview.js:102 +#: code:addons/attachment_preview/static/src/js/attachment_preview.js:128 #, python-format msgid "Preview %s" msgstr "Voorbeeld %s" + +#. module: attachment_preview +#: model:ir.model,name:attachment_preview.model_ir_attachment +msgid "ir.attachment" +msgstr "" diff --git a/attachment_preview/i18n/pt_PT.po b/attachment_preview/i18n/pt_PT.po new file mode 100644 index 00000000000..bd39299b496 --- /dev/null +++ b/attachment_preview/i18n/pt_PT.po @@ -0,0 +1,33 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * attachment_preview +# +# Translators: +# Pedro Castro Silva , 2016 +msgid "" +msgstr "" +"Project-Id-Version: knowledge (8.0)\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-05-07 16:07+0000\n" +"PO-Revision-Date: 2016-05-22 22:19+0000\n" +"Last-Translator: Pedro Castro Silva \n" +"Language-Team: Portuguese (Portugal) (http://www.transifex.com/oca/OCA-" +"knowledge-8-0/language/pt_PT/)\n" +"Language: pt_PT\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: attachment_preview +#. openerp-web +#: code:addons/attachment_preview/static/src/js/attachment_preview.js:102 +#: code:addons/attachment_preview/static/src/js/attachment_preview.js:128 +#, python-format +msgid "Preview %s" +msgstr "Antever %s" + +#. module: attachment_preview +#: model:ir.model,name:attachment_preview.model_ir_attachment +msgid "ir.attachment" +msgstr "" diff --git a/attachment_preview/i18n/sl.po b/attachment_preview/i18n/sl.po index 5e646c5139c..7bfe0a1527b 100644 --- a/attachment_preview/i18n/sl.po +++ b/attachment_preview/i18n/sl.po @@ -1,26 +1,34 @@ # Translation of Odoo Server. # This file contains the translation of the following modules: -# * attachment_preview +# * attachment_preview # -# Matjaž Mozetič , 2015. +# Translators: +# Matjaž Mozetič , 2015 msgid "" msgstr "" -"Project-Id-Version: Odoo Server 8.0\n" +"Project-Id-Version: knowledge (8.0)\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-01-15 11:04+0000\n" -"PO-Revision-Date: 2015-08-03 13:36+0200\n" +"POT-Creation-Date: 2015-12-08 08:32+0000\n" +"PO-Revision-Date: 2015-11-08 05:36+0000\n" "Last-Translator: Matjaž Mozetič \n" -"Language-Team: Slovenian \n" +"Language-Team: Slovenian (http://www.transifex.com/oca/OCA-knowledge-8-0/" +"language/sl/)\n" +"Language: sl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: \n" -"Language: sl\n" -"X-Generator: Poedit 1.8.2\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n" +"%100==4 ? 2 : 3);\n" #. module: attachment_preview #. openerp-web -#: code:multiple:42 +#: code:addons/attachment_preview/static/src/js/attachment_preview.js:102 +#: code:addons/attachment_preview/static/src/js/attachment_preview.js:128 #, python-format msgid "Preview %s" msgstr "Predogled %s" + +#. module: attachment_preview +#: model:ir.model,name:attachment_preview.model_ir_attachment +msgid "ir.attachment" +msgstr "" diff --git a/attachment_preview/i18n/zh_CN.po b/attachment_preview/i18n/zh_CN.po new file mode 100644 index 00000000000..58382e9ba40 --- /dev/null +++ b/attachment_preview/i18n/zh_CN.po @@ -0,0 +1,33 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * attachment_preview +# +# Translators: +# ITGeeker , 2017 +msgid "" +msgstr "" +"Project-Id-Version: knowledge (8.0)\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2016-07-31 02:38+0000\n" +"PO-Revision-Date: 2017-04-19 01:16+0000\n" +"Last-Translator: ITGeeker \n" +"Language-Team: Chinese (China) (http://www.transifex.com/oca/OCA-" +"knowledge-8-0/language/zh_CN/)\n" +"Language: zh_CN\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#. module: attachment_preview +#. openerp-web +#: code:addons/attachment_preview/static/src/js/attachment_preview.js:102 +#: code:addons/attachment_preview/static/src/js/attachment_preview.js:128 +#, python-format +msgid "Preview %s" +msgstr "预览 %s" + +#. module: attachment_preview +#: model:ir.model,name:attachment_preview.model_ir_attachment +msgid "ir.attachment" +msgstr "" diff --git a/attachment_preview/model/__init__.py b/attachment_preview/model/__init__.py deleted file mode 100644 index 4466fe6dfca..00000000000 --- a/attachment_preview/model/__init__.py +++ /dev/null @@ -1,21 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# This module copyright (C) 2014 Therp BV (). -# -# 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 . -# -############################################################################## -from . import ir_attachment diff --git a/attachment_preview/model/ir_attachment.py b/attachment_preview/model/ir_attachment.py deleted file mode 100644 index b00d347478e..00000000000 --- a/attachment_preview/model/ir_attachment.py +++ /dev/null @@ -1,68 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# This module copyright (C) 2014 Therp BV (). -# -# 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 . -# -############################################################################## -import collections -import os.path -import mimetypes -import base64 -from openerp.osv.orm import Model - - -class IrAttachment(Model): - _inherit = 'ir.attachment' - - def get_binary_extension( - self, cr, uid, model, ids, binary_field, filename_field=None, - context=None): - result = {} - for this in self.pool[model].browse( - cr, uid, - ids if isinstance(ids, collections.Iterable) else [ids], - context=context): - if not this.id: - result[this.id] = False - continue - extension = '' - if filename_field and this[filename_field]: - filename, extension = os.path.splitext(this[filename_field]) - if not this[binary_field]: - result[this.id] = False - continue - if not extension: - try: - import magic - ms = magic.open( - hasattr(magic, 'MAGIC_MIME_TYPE') and - magic.MAGIC_MIME_TYPE or magic.MAGIC_MIME) - ms.load() - mimetype = ms.buffer( - base64.b64decode(this[binary_field])) - except ImportError: - (mimetype, encoding) = mimetypes.guess_type( - 'data:;base64,' + this[binary_field], strict=False) - extension = mimetypes.guess_extension( - mimetype.split(';')[0], strict=False) - - result[this.id] = (extension or '').lstrip('.').lower() - return result if isinstance(ids, collections.Iterable) else result[ids] - - def get_attachment_extension(self, cr, uid, ids, context=None): - return self.get_binary_extension( - cr, uid, self._name, ids, 'datas', 'datas_fname', context=context) diff --git a/attachment_preview/models/__init__.py b/attachment_preview/models/__init__.py new file mode 100644 index 00000000000..22aa81fb4b4 --- /dev/null +++ b/attachment_preview/models/__init__.py @@ -0,0 +1,4 @@ +# Copyright 2014 Therp BV () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import ir_attachment diff --git a/attachment_preview/models/ir_attachment.py b/attachment_preview/models/ir_attachment.py new file mode 100644 index 00000000000..e1beaf555a5 --- /dev/null +++ b/attachment_preview/models/ir_attachment.py @@ -0,0 +1,75 @@ +# Copyright 2014 Therp BV () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +import collections +import logging +import mimetypes +import os.path + +from odoo import models, api + +_logger = logging.getLogger(__name__) + + +class IrAttachment(models.Model): + _inherit = 'ir.attachment' + + @api.model + def get_binary_extension(self, model, ids, binary_field, + filename_field=None): + result = {} + ids_to_browse = ids if isinstance(ids, collections.Iterable) else [ids] + + # First pass: load fields in bin_size mode to avoid loading big files + # unnecessarily. + if filename_field: + for this in self.env[model].with_context( + bin_size=True).browse(ids_to_browse): + if not this.id: + result[this.id] = False + continue + extension = '' + if this[filename_field]: + filename, extension = os.path.splitext( + this[filename_field]) + if this[binary_field] and extension: + result[this.id] = extension + _logger.debug('Got extension %s from filename %s', + extension, this[filename_field]) + # Second pass for all attachments which have to be loaded fully + # to get the extension from the content + ids_to_browse = [_id for _id in ids_to_browse if _id not in result] + for this in self.env[model].with_context( + bin_size=True).browse(ids_to_browse): + if this[binary_field] is None: + result[this.id] = False + continue + try: + import magic + if model == self._name and binary_field == 'datas'\ + and this.store_fname: + mimetype = magic.from_file( + this._full_path(this.store_fname), mime=True) + _logger.debug('Magic determined mimetype %s from file %s', + mimetype, this.store_fname) + else: + mimetype = magic.from_buffer( + this[binary_field], mime=True) + _logger.debug('Magic determined mimetype %s from buffer', + mimetype) + except ImportError: + (mimetype, encoding) = mimetypes.guess_type( + 'data:;base64,' + this[binary_field], strict=False) + _logger.debug('Mimetypes guessed type %s from buffer', + mimetype) + extension = mimetypes.guess_extension( + mimetype.split(';')[0], strict=False) + result[this.id] = extension + for _id in result: + result[_id] = (result[_id] or '').lstrip('.').lower() + return result if isinstance(ids, collections.Iterable) else result[ids] + + @api.model + def get_attachment_extension(self, ids): + return self.get_binary_extension( + self._name, ids, 'datas', 'datas_fname') diff --git a/attachment_preview/readme/CONTRIBUTORS.rst b/attachment_preview/readme/CONTRIBUTORS.rst new file mode 100644 index 00000000000..81c9fb26302 --- /dev/null +++ b/attachment_preview/readme/CONTRIBUTORS.rst @@ -0,0 +1,2 @@ +* Holger Brunn +* Dennis Sluijk diff --git a/attachment_preview/readme/CREDITS.rst b/attachment_preview/readme/CREDITS.rst new file mode 100644 index 00000000000..07bb3a4ede8 --- /dev/null +++ b/attachment_preview/readme/CREDITS.rst @@ -0,0 +1,4 @@ +Addon icon +---------- + +* courtesy of http://commons.wikimedia.org/wiki/Crystal_Clear diff --git a/attachment_preview/readme/DESCRIPTION.rst b/attachment_preview/readme/DESCRIPTION.rst new file mode 100644 index 00000000000..f1b31ab8736 --- /dev/null +++ b/attachment_preview/readme/DESCRIPTION.rst @@ -0,0 +1,3 @@ +This addon allows to preview attachments supported by http://viewerjs.org. + +Currently, that's most Libreoffice files and PDFs. diff --git a/attachment_preview/readme/INSTALL.rst b/attachment_preview/readme/INSTALL.rst new file mode 100644 index 00000000000..eb26fced31f --- /dev/null +++ b/attachment_preview/readme/INSTALL.rst @@ -0,0 +1,4 @@ +For filetype recognition, you'll get the best results by installing +``python-magic``: + +sudo apt-get install python-magic diff --git a/attachment_preview/readme/USAGE.rst b/attachment_preview/readme/USAGE.rst new file mode 100644 index 00000000000..e1783956d82 --- /dev/null +++ b/attachment_preview/readme/USAGE.rst @@ -0,0 +1,2 @@ +The module adds a little print preview icon right of download links for +attachments or binary fields. diff --git a/attachment_preview/static/description/index.html b/attachment_preview/static/description/index.html new file mode 100644 index 00000000000..988c69e652e --- /dev/null +++ b/attachment_preview/static/description/index.html @@ -0,0 +1,448 @@ + + + + + + +Preview attachments + + + +
+

Preview attachments

+ + +

Beta License: AGPL-3 OCA/knowledge Translate me on Weblate Try me on Runbot

+

This addon allows to preview attachments supported by http://viewerjs.org.

+

Currently, that’s most Libreoffice files and PDFs.

+

Table of contents

+ +
+

Installation

+

For filetype recognition, you’ll get the best results by installing +python-magic:

+

sudo apt-get install python-magic

+
+
+

Usage

+

The module adds a little print preview icon right of download links for +attachments or binary fields.

+
+
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Therp BV
  • +
  • Onestein
  • +
+
+
+

Contributors

+ +
+ +
+

Maintainers

+

This module is maintained by the OCA.

+Odoo Community Association +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

This module is part of the OCA/knowledge project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/attachment_preview/static/lib/ViewerJS/compatibility.js b/attachment_preview/static/lib/ViewerJS/compatibility.js index 967e312a998..06f54bff064 100644 --- a/attachment_preview/static/lib/ViewerJS/compatibility.js +++ b/attachment_preview/static/lib/ViewerJS/compatibility.js @@ -447,20 +447,10 @@ if (typeof PDFJS === 'undefined') { // Checks if navigator.language is supported (function checkNavigatorLanguage() { - if ('language' in navigator && - /^[a-z]+(-[A-Z]+)?$/.test(navigator.language)) { + if ('language' in navigator) { return; } - 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); + PDFJS.locale = navigator.userLanguage || 'en-US'; })(); (function checkRangeRequests() { @@ -479,7 +469,10 @@ if (typeof PDFJS === 'undefined') { var regex = /Android\s[0-2][^\d]/; var isOldAndroid = regex.test(navigator.userAgent); - if (isSafari || isOldAndroid) { + // Range requests are broken in Chrome 39 and 40, https://crbug.com/442318 + var isChromeWithRangeBug = /Chrome\/(39|40)\./.test(navigator.userAgent); + + if (isSafari || isOldAndroid || isChromeWithRangeBug) { PDFJS.disableRange = true; PDFJS.disableStream = true; } @@ -572,3 +565,13 @@ if (typeof PDFJS === 'undefined') { PDFJS.maxCanvasPixels = 5242880; } })(); + +// Disable fullscreen support for certain problematic configurations. +// Support: IE11+ (when embedded). +(function checkFullscreenSupport() { + var isEmbeddedIE = (navigator.userAgent.indexOf('Trident') >= 0 && + window.parent !== window); + if (isEmbeddedIE) { + PDFJS.disableFullscreen = true; + } +})(); diff --git a/attachment_preview/static/lib/ViewerJS/index.html b/attachment_preview/static/lib/ViewerJS/index.html index c7496cebdbf..c79df466329 100644 --- a/attachment_preview/static/lib/ViewerJS/index.html +++ b/attachment_preview/static/lib/ViewerJS/index.html @@ -39,37 +39,37 @@ + + + + diff --git a/attachment_preview/tests/__init__.py b/attachment_preview/tests/__init__.py new file mode 100644 index 00000000000..7aec7faa2d0 --- /dev/null +++ b/attachment_preview/tests/__init__.py @@ -0,0 +1,4 @@ +# Copyright 2018 Onestein +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import test_attachment_preview diff --git a/attachment_preview/tests/test_attachment_preview.py b/attachment_preview/tests/test_attachment_preview.py new file mode 100644 index 00000000000..17e731b7e67 --- /dev/null +++ b/attachment_preview/tests/test_attachment_preview.py @@ -0,0 +1,46 @@ +# Copyright 2018 Onestein +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +import base64 +from odoo.tests.common import TransactionCase + + +class TestAttachmentPreview(TransactionCase): + def test_get_extension(self): + attachment = self.env['ir.attachment'].create({ + 'datas': base64.b64encode(b'from this, to that.'), + 'name': 'doc.txt', + 'datas_fname': 'doc.txt' + }) + attachment2 = self.env['ir.attachment'].create({ + 'datas': base64.b64encode(b'Png'), + 'name': 'image.png', + 'datas_fname': 'image.png' + }) + res = self.env['ir.attachment'].get_attachment_extension( + attachment.id + ) + self.assertEqual(res, 'txt') + + res = self.env['ir.attachment'].get_attachment_extension( + [attachment.id, attachment2.id] + ) + self.assertEqual(res[attachment.id], 'txt') + self.assertEqual(res[attachment2.id], 'png') + + res2 = self.env['ir.attachment'].get_binary_extension( + 'ir.attachment', + attachment.id, + 'datas' + ) + self.assertTrue(res2) + + module = self.env['ir.module.module'].search([]).filtered( + lambda m: m.icon_image + )[0] + res3 = self.env['ir.attachment'].get_binary_extension( + 'ir.module.module', + module.id, + 'icon_image' + ) + self.assertTrue(res3) diff --git a/attachment_preview/view/attachment_preview.xml b/attachment_preview/view/attachment_preview.xml deleted file mode 100644 index a2d6dcf1264..00000000000 --- a/attachment_preview/view/attachment_preview.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - From 8c6275406825cbc63e166f6312cbcf03b37f5d0a Mon Sep 17 00:00:00 2001 From: Andrea Date: Mon, 17 Dec 2018 15:22:27 +0100 Subject: [PATCH 17/41] [FIX] Robustness when attachment not present --- attachment_preview/__manifest__.py | 2 +- attachment_preview/models/ir_attachment.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/attachment_preview/__manifest__.py b/attachment_preview/__manifest__.py index 7020cd32f9d..ee02c750c77 100644 --- a/attachment_preview/__manifest__.py +++ b/attachment_preview/__manifest__.py @@ -3,7 +3,7 @@ { "name": "Preview attachments", - "version": "11.0.1.2.0", + "version": "11.0.1.2.1", "author": "Therp BV," "Onestein," "Odoo Community Association (OCA)", diff --git a/attachment_preview/models/ir_attachment.py b/attachment_preview/models/ir_attachment.py index e1beaf555a5..0b88b0e771c 100644 --- a/attachment_preview/models/ir_attachment.py +++ b/attachment_preview/models/ir_attachment.py @@ -41,7 +41,7 @@ def get_binary_extension(self, model, ids, binary_field, ids_to_browse = [_id for _id in ids_to_browse if _id not in result] for this in self.env[model].with_context( bin_size=True).browse(ids_to_browse): - if this[binary_field] is None: + if not this[binary_field]: result[this.id] = False continue try: From 2fb664d7c44bdb59b4ced3e1e9c1ce625ee230de Mon Sep 17 00:00:00 2001 From: tarteo Date: Thu, 10 Jan 2019 09:59:39 +0100 Subject: [PATCH 18/41] [IMP] attachment_preview: Split screen --- attachment_preview/README.rst | 12 +- attachment_preview/__manifest__.py | 2 +- .../i18n/attachment_preview.pot | 4 +- attachment_preview/i18n/de.po | 4 +- attachment_preview/i18n/es.po | 4 +- attachment_preview/i18n/it.po | 4 +- attachment_preview/i18n/nl.po | 4 +- attachment_preview/i18n/pt_PT.po | 4 +- attachment_preview/i18n/sl.po | 4 +- attachment_preview/i18n/zh_CN.po | 4 +- attachment_preview/readme/DESCRIPTION.rst | 4 + attachment_preview/readme/USAGE.rst | 8 +- .../static/description/index.html | 7 +- .../description/screenshot-paginator.png | Bin 0 -> 2137 bytes .../static/description/screenshot-split.png | Bin 0 -> 162695 bytes .../static/src/css/attachment_preview.css | 15 -- .../static/src/js/attachment_preview.js | 254 ++++++++++++++++-- .../static/src/less/attachment_preview.less | 56 ++++ .../static/src/xml/attachment_preview.xml | 23 ++ attachment_preview/templates/assets.xml | 2 +- 20 files changed, 358 insertions(+), 57 deletions(-) create mode 100644 attachment_preview/static/description/screenshot-paginator.png create mode 100644 attachment_preview/static/description/screenshot-split.png delete mode 100644 attachment_preview/static/src/css/attachment_preview.css create mode 100644 attachment_preview/static/src/less/attachment_preview.less diff --git a/attachment_preview/README.rst b/attachment_preview/README.rst index 197d487f25a..c65b03492e8 100644 --- a/attachment_preview/README.rst +++ b/attachment_preview/README.rst @@ -29,6 +29,10 @@ This addon allows to preview attachments supported by http://viewerjs.org. Currently, that's most Libreoffice files and PDFs. +.. image:: https://raw.githubusercontent.com/attachment_preview/static/description/screenshot-split.png + :alt: Screenshot of split form view + :width: 100% + **Table of contents** .. contents:: @@ -46,7 +50,13 @@ Usage ===== The module adds a little print preview icon right of download links for -attachments or binary fields. +attachments or binary fields. When a preview is opened from the attachments +menu it's shown next to the form view. From this screen you can navigate +through the attachments using the arrow buttons. Using the pop-out button +next to the navigational buttons you can open the preview in a separate window. + +.. image:: https://raw.githubusercontent.com/attachment_preview/static/description/screenshot-paginator.png + :alt: Screenshot navigator Bug Tracker =========== diff --git a/attachment_preview/__manifest__.py b/attachment_preview/__manifest__.py index ee02c750c77..77da9c13888 100644 --- a/attachment_preview/__manifest__.py +++ b/attachment_preview/__manifest__.py @@ -3,7 +3,7 @@ { "name": "Preview attachments", - "version": "11.0.1.2.1", + "version": "11.0.1.3.0", "author": "Therp BV," "Onestein," "Odoo Community Association (OCA)", diff --git a/attachment_preview/i18n/attachment_preview.pot b/attachment_preview/i18n/attachment_preview.pot index 99f77a5a242..dd0ef1da6c7 100644 --- a/attachment_preview/i18n/attachment_preview.pot +++ b/attachment_preview/i18n/attachment_preview.pot @@ -15,8 +15,8 @@ msgstr "" #. module: attachment_preview #. openerp-web -#: code:addons/attachment_preview/static/src/js/attachment_preview.js:102 -#: code:addons/attachment_preview/static/src/js/attachment_preview.js:128 +#: code:addons/attachment_preview/static/src/js/attachment_preview.js:166 +#: code:addons/attachment_preview/static/src/js/attachment_preview.js:194 #, python-format msgid "Preview %s" msgstr "" diff --git a/attachment_preview/i18n/de.po b/attachment_preview/i18n/de.po index 6976f4afc7f..f0ced98223e 100644 --- a/attachment_preview/i18n/de.po +++ b/attachment_preview/i18n/de.po @@ -21,8 +21,8 @@ msgstr "" #. module: attachment_preview #. openerp-web -#: code:addons/attachment_preview/static/src/js/attachment_preview.js:102 -#: code:addons/attachment_preview/static/src/js/attachment_preview.js:128 +#: code:addons/attachment_preview/static/src/js/attachment_preview.js:166 +#: code:addons/attachment_preview/static/src/js/attachment_preview.js:194 #, python-format msgid "Preview %s" msgstr "Vorschau %s" diff --git a/attachment_preview/i18n/es.po b/attachment_preview/i18n/es.po index a2fb4966681..83b74ff4aca 100644 --- a/attachment_preview/i18n/es.po +++ b/attachment_preview/i18n/es.po @@ -21,8 +21,8 @@ msgstr "" #. module: attachment_preview #. openerp-web -#: code:addons/attachment_preview/static/src/js/attachment_preview.js:102 -#: code:addons/attachment_preview/static/src/js/attachment_preview.js:128 +#: code:addons/attachment_preview/static/src/js/attachment_preview.js:166 +#: code:addons/attachment_preview/static/src/js/attachment_preview.js:194 #, python-format msgid "Preview %s" msgstr "Previsualizar %s" diff --git a/attachment_preview/i18n/it.po b/attachment_preview/i18n/it.po index 052c4212ffb..6b45e9e348a 100644 --- a/attachment_preview/i18n/it.po +++ b/attachment_preview/i18n/it.po @@ -21,8 +21,8 @@ msgstr "" #. module: attachment_preview #. openerp-web -#: code:addons/attachment_preview/static/src/js/attachment_preview.js:102 -#: code:addons/attachment_preview/static/src/js/attachment_preview.js:128 +#: code:addons/attachment_preview/static/src/js/attachment_preview.js:166 +#: code:addons/attachment_preview/static/src/js/attachment_preview.js:194 #, python-format msgid "Preview %s" msgstr "Anteprima %s" diff --git a/attachment_preview/i18n/nl.po b/attachment_preview/i18n/nl.po index 0103f90eeab..70c32fa7e66 100644 --- a/attachment_preview/i18n/nl.po +++ b/attachment_preview/i18n/nl.po @@ -20,8 +20,8 @@ msgstr "" #. module: attachment_preview #. openerp-web -#: code:addons/attachment_preview/static/src/js/attachment_preview.js:102 -#: code:addons/attachment_preview/static/src/js/attachment_preview.js:128 +#: code:addons/attachment_preview/static/src/js/attachment_preview.js:166 +#: code:addons/attachment_preview/static/src/js/attachment_preview.js:194 #, python-format msgid "Preview %s" msgstr "Voorbeeld %s" diff --git a/attachment_preview/i18n/pt_PT.po b/attachment_preview/i18n/pt_PT.po index bd39299b496..70420cf60d1 100644 --- a/attachment_preview/i18n/pt_PT.po +++ b/attachment_preview/i18n/pt_PT.po @@ -21,8 +21,8 @@ msgstr "" #. module: attachment_preview #. openerp-web -#: code:addons/attachment_preview/static/src/js/attachment_preview.js:102 -#: code:addons/attachment_preview/static/src/js/attachment_preview.js:128 +#: code:addons/attachment_preview/static/src/js/attachment_preview.js:166 +#: code:addons/attachment_preview/static/src/js/attachment_preview.js:194 #, python-format msgid "Preview %s" msgstr "Antever %s" diff --git a/attachment_preview/i18n/sl.po b/attachment_preview/i18n/sl.po index 7bfe0a1527b..4fdc122cacc 100644 --- a/attachment_preview/i18n/sl.po +++ b/attachment_preview/i18n/sl.po @@ -22,8 +22,8 @@ msgstr "" #. module: attachment_preview #. openerp-web -#: code:addons/attachment_preview/static/src/js/attachment_preview.js:102 -#: code:addons/attachment_preview/static/src/js/attachment_preview.js:128 +#: code:addons/attachment_preview/static/src/js/attachment_preview.js:166 +#: code:addons/attachment_preview/static/src/js/attachment_preview.js:194 #, python-format msgid "Preview %s" msgstr "Predogled %s" diff --git a/attachment_preview/i18n/zh_CN.po b/attachment_preview/i18n/zh_CN.po index 58382e9ba40..3190fbc83f9 100644 --- a/attachment_preview/i18n/zh_CN.po +++ b/attachment_preview/i18n/zh_CN.po @@ -21,8 +21,8 @@ msgstr "" #. module: attachment_preview #. openerp-web -#: code:addons/attachment_preview/static/src/js/attachment_preview.js:102 -#: code:addons/attachment_preview/static/src/js/attachment_preview.js:128 +#: code:addons/attachment_preview/static/src/js/attachment_preview.js:166 +#: code:addons/attachment_preview/static/src/js/attachment_preview.js:194 #, python-format msgid "Preview %s" msgstr "预览 %s" diff --git a/attachment_preview/readme/DESCRIPTION.rst b/attachment_preview/readme/DESCRIPTION.rst index f1b31ab8736..aadfd9448b0 100644 --- a/attachment_preview/readme/DESCRIPTION.rst +++ b/attachment_preview/readme/DESCRIPTION.rst @@ -1,3 +1,7 @@ This addon allows to preview attachments supported by http://viewerjs.org. Currently, that's most Libreoffice files and PDFs. + +.. image:: /attachment_preview/static/description/screenshot-split.png + :alt: Screenshot of split form view + :width: 100% diff --git a/attachment_preview/readme/USAGE.rst b/attachment_preview/readme/USAGE.rst index e1783956d82..941a680c529 100644 --- a/attachment_preview/readme/USAGE.rst +++ b/attachment_preview/readme/USAGE.rst @@ -1,2 +1,8 @@ The module adds a little print preview icon right of download links for -attachments or binary fields. +attachments or binary fields. When a preview is opened from the attachments +menu it's shown next to the form view. From this screen you can navigate +through the attachments using the arrow buttons. Using the pop-out button +next to the navigational buttons you can open the preview in a separate window. + +.. image:: /attachment_preview/static/description/screenshot-paginator.png + :alt: Screenshot navigator diff --git a/attachment_preview/static/description/index.html b/attachment_preview/static/description/index.html index 988c69e652e..28ae93760c0 100644 --- a/attachment_preview/static/description/index.html +++ b/attachment_preview/static/description/index.html @@ -370,6 +370,7 @@

Preview attachments

Beta License: AGPL-3 OCA/knowledge Translate me on Weblate Try me on Runbot

This addon allows to preview attachments supported by http://viewerjs.org.

Currently, that’s most Libreoffice files and PDFs.

+Screenshot of split form view

Table of contents

    @@ -397,7 +398,11 @@

    Installation

    Usage

    The module adds a little print preview icon right of download links for -attachments or binary fields.

    +attachments or binary fields. When a preview is opened from the attachments +menu it’s shown next to the form view. From this screen you can navigate +through the attachments using the arrow buttons. Using the pop-out button +next to the navigational buttons you can open the preview in a separate window.

    +Screenshot navigator

    Bug Tracker

    diff --git a/attachment_preview/static/description/screenshot-paginator.png b/attachment_preview/static/description/screenshot-paginator.png new file mode 100644 index 0000000000000000000000000000000000000000..02910c83c406bf3789e9fccef4f12fc5b0a1f1b7 GIT binary patch literal 2137 zcmV-f2&VUmP)+DA`sQZ zzH+%-p-@;`TXU;JpU)Q#ha-^)Usx`eOQn)&nr>NX2~E?2!C)W|;0wJ8yaCsZwq(6Y zT$5KWms?p`>F)0K`~7b9S*=#H*(?CCP|M|VwOWltBD$`-Wu+wy!zdPuj^hM_K`ikm z@CHN}ZQgqGxVAVJ3WaDi>Ta}tzdss{777JcQYw`~p-{WD1pvCPheDxpxy(wu3A_Oj zMw_?ZJg&)WZEa0Nw0^&zpZ`tMY@@aiUDx@g*_*%{5M;DT>&+v#_7Z_ec}WD~=9Q!5 zzfLjrXR2rb0DvCpIoP>Fw86H?D|c@=KAP_x8a{tec#!SJ$o!NX8e8p8BnEoC3U)O$ zH9fyBB>(`>JNph*#z&G5@_2mU!j0sykYF#`vpDAN4PP9Y&Q}&EuZ*Vz^glN@H!?CZ zKR^H0vr|)34G;2PzI=J>)~)N;uM6-6V0CJA^wDzV$#^1hV}4bLiAIZme1CD|UdH4B zfKcDX#JMib3lG*&&Br$qWB>Gi{q2c;9+^aKEd#*LLl@#_V{Z39Gc%LPWOnb~{jLh> zbo$7VBka&HjGH%a#$vJ6RWaZFjxPp>W`~k@vy~^~i3E5shb>Oe$Igxn^fg>#8>xva zCoZRCwephfXb756SJP_YeQSTgUO*@Nac(VH*pJk zxG(0_)nn{T;^L901_1fHNw3H62I+Kq-#)LlnXi$%KODb0YXZQ|0~Zp5eV$z~7Z)F8 zI(i3_@%~PDbYo;9EBXbEsg-tW`!*+Ewy9n@?2XT9eO^Sd$ZigEatUHhhXa*YCgQr zm-1};1pw;`gP}{mWGmVER0UkVOdlH?d;a`+y8yqvdUC(d`jmzHP?6Ce%0Z{|S~u{$fHR5GgN-K%~4R0&z`VKA*2zt-944qgt){ zd_H!lX_{epc-Q%D7>1!~ub$U=6LudIZ_VOA0h28+dF z8x@9c3h^(Zc@ua8B8)a~y?I=_a>SRG78VwSzU~(Y1RTf7<#KI&&oK}P@b~?_3A_Oj zMw_?ZJn~RxAib4p%U|3ppU3VM@bA)-vIv6%4tKqxB zFGl(=&i~EaR^3i%zPf%_lOGL~QdBoTKCl`_j)pZ&W9r7hus)6hmJ8dqnF;Jc(=^+* z(GVsYyR|Hfm7obWhOl!s!r1SS@QYz?NdE=-znLpXjS%)w2K_@1nBLKKMN!a2(=;&> z%oo-)O%p$HaG>7+P_Nh7Tg8|utbhSypS4=ewr%Vj#}l??{bLi>7C{p@u+T21Qu;5> ze-~~{;5^BX8w?l?<5@gJCrr~s)#IFxXR!zLj7`XxHEheWKsa8l@swh;mSwTUf_a6* z3!7je%YyV@sQ(`;FE)!}NQB!YGIw!guqhV}<2WFMSeC`t$Cz;!2^%vu0BD+~C<<;7 z*uDY(U|GO!v9MOFu>|4pVp-F5{moTC`Y*!&kChh&gEKa4?CIFwxFi#9Q;91*Yl1_H zjY}*v3LtvOS{Mp!p(1e&Hkg^35a*ub`Dk1xa4qv88xG!P0nV;1!J4 z>Eq5o3lmlSUFSl|029*ELON4St&we&;k=LWZ(jY$!)1wdwZd0bt0<+2SR~QEUT?&G z7UORdeK|}7uXim;{{ecnx4YrEm3)_c#u2D7=*hd)bhI`)JuM8p@;~J)Ca3<@zXxzO zFOsMd{-CI2Tj4+?K=xsZ%69NOfB|2UJhxALo zRNnyG;~zGlZvlbHz%CqZ;Abpg^L>s3`l($&>iJZh06G$|X*r-5<$FGUE(7KR69rTE zm%~J+*yKkMo>KH?DYX|5)y*bQO0Vk$8)(1YUZaeHZC{<<(o^WE_r7OkocHPCo2d4e z($;)XX1f`2x_wAW$Rb&(b z`??b4u?04(+dH2H)(bdH`*cw`CrqzBSMJ!5skH9mtV=e-G@r%%TsASu(F~}jX^Lwc zkIX!e?Dw!jRSa{jEz4Ymijf>Ooh&}P&@J7EYDj>=O7iaFcNd9u?P}wxPq>5<;0`2B zn1pEL=uC6>NcQNqVEJ~Q;S?BZtDXVh&Qxt)JfV4eyr9&cWZfy9tl@tDN8+9El4tYK zavY!+=`+d8>~)3v7me)B4zjj__p z>wJ3$t3W68Xl$Xc{U~(`zGSJ+-W>u#b}mWg@I19CcpR**;^EA>3{ZkK^M58THxWZ2 zYBKm)95#naQB^ga!uPbIOK6xyK?aU0BHK0Pc030was_?9mrBCx7qiCEuzT@rfIwNM zSONP=lQ&u-u z%g{z32Yqwd-?f?kSSma|Li4kcG-cKi^+(}CY3t(3-i>51dNa4j#yy#&NBKadZWyF! z?>>RE(Zq5$i7V3s0%0wT8>JK59h%-z;-e!TuVhkGGwL+AZfcqhgqS!weBZ!6QckI@ zdYmipgowyrKAJXKbSK#cp!??t6RaJ^h#yQXXH7@3*@za>Cp6z2(n(Kinl50Wu`1+z z%f#-@5P&$uNonq2l`O%?Rl7(sCJQn z2f(8Ujm{}}9ZXNl28F$q-VV44`@u<7E2o8F5TL^-oyuCW>_0Pn17|4&I z@UFMrLh`aq^N`K-cEAvL$Zq!@sR-fMzS)!XK1-QQdXQ9(@P2&U(4wUeAZD!aQm}+J z7v6Uvh2*eHl-JLJD|E`5r=v?+{DPM>9~&0j4Kq%?vn=Ot>`HSRZ~T@f&AW>&Oijns z{4x#J2K-t4kI%uYa8C)_aa%Y^;Hs6ItxUo#%JJ&GAXNB}pxpY(IkCqvoxo2nt#aPw zRpzxE<1aHZUUh}g8$7t>eRXd-*DDw@D2sPfqf6y2!Te#ZW=*6sGyZ2}=ts%VQ%GIq zLdUf@p?nGN3t~M+hlNSWs#pkrMg}Rm7KQlU4!ZIHRb*s_CTH;T9P(T?xsBa^qRQHU zC2}_vJjMI_Bad4p>&>m=znBP0(4+EP??-W=_=2vy;*usqvR06Grj3U^GG-b;oblYa zAjYxNqhimYG{_eh$@M<_18nufonC2+gN9@OR;;?!i)KV@bm)XOWfjI_*H=GS;tua! zR{u8nT~c#+EaQBtV8CJD@Gy(%bWyCGd($*_^rZ*?HF$=$V8(*g9Thrhc4%eBskpFr zm27u5v9&n8RPPw!i>CCs@PrJ6h!Prot7&p-FaXYsqQ$cG>)LN-6=O6Tyk5D8mq12U zEebg7%8wY@>oi}2;CshD>?D0*6`$TB(i{!RsHXA=>an0lUpwO3KY#raRbU~2VqhKf z_&$|qVDzeg@u5=`1kwXTMco(w=T%z>8GZ7T3 zGpIdQqPhCE-93)jG3?*yzfT>72vmw~A^-Q==r@uG}ChRdS-cnQ@m>6IFEd#*4}eMuZ(T zIz>-4B|C-l&1z-)vqN+13YCYo43FAZs)6sCNb&GOO;aom*6Vobc$NqoF5YcSjK};V zCpda-_M}fFqxpu=vD zTX9m`iFt@(20y=os_Y+>##H}#l#}r5l^{KJ)({7ku|Y+xKdqt}fR2Kev_;m>_NfZe z@CRCEZqIM=wV5B%v=?Sd?`}$jr7Uqs&`&QG%Hf}iC>{n=_}l>t57{s`7%n;{Wa^v( z=I}S=xhG@B`X8vANJ|JMmQ^I{rtp>X-#?XGjqkZv)pLroN?Cj!%!|A#sOwCUyRsm{ z!|9_(hITSGWOVX(d|;XpgqcXC)nvpSUa#zFq?MJ@CrIerb_SA5vw@pG4z6kGP=s&Z zmN6i=+w8Ez&l?9M7#tWlV2evv-&yy%eB5F9kC1Q%cV6Qn_{Km(Z-okGKim?GdlmKW z64pu_{sgHJWJ+kkbgo%bGxAXMlNqT-k2xkjr-%)R6MV$E`4agv#@tu1nb-M5dUvZ_ zNs<9d7OYWe+}u!~r|FrgxiI0ji&D+2Ui{}Qr1sEbOyz8TQP?4`nelz=jR0k~RRYcFf zcygp3b}7BOv9=@V*`W$K&H1e)$tD=c-p~>WacOFL$(ZC8;3&?tJqQMsL0mS2rlcg4 z)!o#nw3>|@|LB#C$Y>3kRjN^UtnsW^YyBrW`<}4n;Tzh}rZ4bNT&-ov*q>LKH+)y? z=;P;(8UhBpoyLl#9OaQL2SJc;c{9@26DKE%s;}Okp`zl}xf2x;77m=HF-tPNFiM|T zI?K4#4NUM&!7=SUi$Df`a}u$a(!6~4GlR_)KfFmiTrlPJ1-M8Sh}{d%k%qN*heyKd zoh30=+jtH1JB-YzX>Lk=GPK>#E+*TboK{OeykM!SP-p$K^;B+Bxj+g*Oyb@#b-Z>q z8O@ZQN20D4h3C5!e@GBNm~~PkG(y?4DoE`xZ}$i?S*=7bt(am-C~|mQXgCWGsplKG zTOtZLy53o`ia%%mj{z+2u!ggVD^m0ca*nAKVe507lrwM3?YApo1*K|hIS60l*6Wkcq@6#IGv4E&8Y&Z_v>f?iT$zXwp z$daPH6x}Jw+DIx}6M@GCO10Fz_Tsc2_8m0)z^>ijeeqNiDm8E-7#mKfX7*Md^q}lflAo2CTP8Yx9D=(-rj7zgmGYfU{&ML6x8Ny5w;pWnwe+0U5*CT(*LBV zwnwXl@qwX9H+cJl*1EXu*zfTi@o=^3!gpucsrAbFQq?lYQ*j_y15=X;HNPl>h`O$u z;)SN2v3f;e6!o#!jUVY&;ZjdsK`laXsjT!;WNQIoDH8`GUN$WWr#_YDbnBn#h zAv;x0eY&m7bMQHhY-+I0sVvTDTIob? zCt~nweZ+6BJT<3E#=#MtxSBL})SijhI-q&~-iw04O@G}th}DiX+-0r){Di!k_s+U# zR7h))_i?4)sfmDxGWZaf^e`|F);n|qe&Kc)Pq68M*<`+ta6{LiD2KeSXw{w29tx zpk9-Lj=+e55|I${45jFJ@&5;vNdBl7^dIcP=f6=7+>dt8KvK=?L`7f&C;gYi7|Qd` zb2-C9Gx%o@z(7ifzx^kq`d=#;q$YXq^6IKKV@Ln635f#jv#e0!nKss?zR_ot?59|1aGHs?N^UqbAW} z*}S~GRtTn)5}%`#3NR7mFP`h|z@mm9Fa1-{ z>~r`NF_W_i?@vcZcf&Wb4ri6Q4^bU4^CzOu{a7M~Rz{^GVChqY5`)~VOk2MT3JS}f z5_j{@m=rMyGbtSvav3$paqQZ*k=SQ5#nqzH%9|Y=)}KXfPdMjv$miWa$3jL%=D759 zRbX$a&k`P*_Go^~g{?|nZRcBjt0VQ8z^ZSosC)8b5Js`{#rvp7GPCLNrx;5V2cz=U zC)hUC6362({QlF!jbFec167rB>fOf4dn#999=eFw0kAOZ0mG!vs+6Id)=AkI2|Nrv zmswhodqF&}h}}-e?=>y}D*9vBt?8IPmmO%EC*wu>{TQlf`Y*7euFwFxdO^Qfz7fSY zqg;-7&3THD52xKl83o1kq**MW4>bA%Bp)0vz0g)F~_9r)m zIvK^@GWsNe1P`smvUcurHr7YTLE#r_Zl#jy57KyX(1hPVKa>p`-n{9a6_Ru zbkV(NZ8&93q305gOQ}{@(NvMqm@_5T`o&1YM1nPF4hL7gCaxzJX=sY+ShvuS{{TOM zm|ewRq_81^2uqR|E60e*uV5<2DEqBeu*WPG3A1O-KSRvt46D4e3(J3{pXH)Kpe0jI zNtXf3t@3KXBgDkCuu#g7P*&2igoI&3TOY^AZ@HfaGG%Tik2bIsO;tg8m}Lc@J%F#9o#t})OAYUTZiwpv3 zUbx?MVsp|^i;w*|-w#z0m1!$h?2bs@frzGNYxl}x{|s2oAKMlEB0cmc&4k+R+?DNBny{fjYWTayzYI6fh?h$U>|qKX`O&;QxS@D|%}&Ah`CB@V{WoDSFshpF_z3um zsAwBL)RdHFWs&mr+T1rX5rVU5hxmrXIaK82lCg7WD5=L$QBC(M@a^AY681_PiAQMD z+r(wdH%Z4R|7?_1_sCUC&FiD;Q8E+jPYgni@wZln|4jtEaGx~mN8J5jw$qF<)Or|N zwvX*hV7ZvU-> z&Hg)h^K;!0uyfMhIe21DW-jJDI3$AOv)||!6r)UQ`2+B{P-_I2WzMR9;w5$|L%?e&dhceR=XJq9M{rqs$#>W8%C-JJF zfI}`HN@ig9v=-N8Nf2|17`9e-|MsoeAGL=+%{iEum~Y;^A;D@o9}`zqRi%CJ!tN+o zNl!}$fnXr?wXK?I@{h4M>jW1@@*gTwn8fgF3I)j$og@ z4jfceQA0W17%6FRM_f0BAQ;>dN#j%o;Sy%gY8U$QMS42sjKN;y!h`u#^PVuau8jJ#t3z%~;-`S=# z>tDi!qZ$pg^T*2i&M5fa1$o=Kw2dQ1#2~a1F)15Er%-f^dMYU;PYr!y&xaF4Nx2{M z+4atjz5^L0_lli6hr0b)Ai9DXy$#+!NK6u>Si4+~g#uRnKJ-8DXA${a7+<5OTb0o?%YJ_aS)IMcWuDVQ``L}j6rXf>g(L0|i8`e;w^ z4?jsRUhjc4v&^CN_o6@eLu^;korl?80}^iGNWp$OGd`*+^w=Z!hB-~>Pgl_ukM~vc zr_7s)`9|8=RlqBdvtT{=`zG`2Y6%UTJ28K*s#VD5EH3*XyWI6q>#mtZm^qW+H(*i9 zK+GM`BL)Wfd>??>$Rx-OQL)RLLxL*Vf+{inF;}CR149$&Wxj;>Q}@cTTbSg!)c;cY z-N*9@8&y3|jDo02y$t+C;gE{+L&S^-9Nc_35Ctr!H=;%;m`!_0ze#o2e}k-jhdu%L*ay5#&(}+kJz#4Rlls`hx$pEsiY`% zM}>=VB9gs#6ftH#CFRcuBA1STu>K1W+jl0;;l{JIC0NPRI=MQ3w@IXw(Q< zLISqdEx=m5FQK=?e-n&3L;J@K54~wY7Y*(z-uYYlIpGWd$qV z*PV(Hq888$_R|)!auUAsp6pUgiOC+MMlG8SZu7%j``rDbqx@~GIL(fO5C|mTxbk@4 z_a3wgFPhz!POB`G5>5vVwbHJ=Jq>q$adWETsxIitByNyPF`z^^J(4NT>97i%Bv%e} z0OGfszCU^E>c&_2&yoA`k1D>#Gxdi8zMDYXQ;j-0T1OrjabIsyGO^tLpyI*L69~2C zhAW3ZOGFxrZlxhpDq&_qs$VFij`!|7j)*0>sfuFfj;ku(9k0Z3=M@3Wj^`cQp!L4n zhNS35eGG~QUNAEUxw49!LUL4W4!Q0x4}CE!BVUJWzZFRIezdRe{sbBbjnc`G@>^|Z z!@s!z;EsqnLS@-_sFws*-ve}VjpSSv?wNAhKcTb9@{utq#e>S(MC2eXuwIuJ z_9gafxbHJ0k=?x^NS8)t3U5p^Z;i=GNo@%IH8MH9mAzs*`N7dpk7V+>7;A68?<@SS zo;ntFYY{=*TBf}vGC4fAJ2N~OW?rX2@>mlGMstiwLyKi=GL)z6})^BnTVzj8{|;hf8t1 zZp9c<10&Y0t(+V+2%Wb z+C_+^EFCXXc@S%_(vaP@@KoN^_O>k-6u0tXHeo0n6)LQ~q@Yc7GoF^5ocHDTW}0_H zyH=Ca!EBx5-aO90gl3b6>&5QmVfafpo$v(pr?fPx^t#APmEU4XYVnv%M(;z5IO1(d zL01R1n{xJTA&IL{-sc4+3Z_M4^~m_}SwNrKz*E*j6hu|N;$ zjvlbyf|JHK)eCNTbP?>1r{bavpYC^VX4W6RdhXRS0(m6)Q3^E|tD=XgN22{qnd#TR z(=2{}!$?Y{rQl;03NFlCm8m7=;lZMFeO~{6uhnB+{O7*Jq83iy_Hp|C&=lUpr#-Km z;Wp9EKmD7)@!jOgU&)EXIg^kljCEVE^2#? za+edmBBi?@TRnf{05Kw@hwop*=^U!o*sK6cec&z&gnzZ@>#AN3rEno((>nZvH$)h& zwE0(CFQuX%ob9l*aNpkE{?@wN&)J<#R2RxbPvUNRgLKWX*QPxWA}VXBufKbIxHE#e zvijKufBmFVVFGP#Zmxgz0xsU&f>qtzykOL%V#eYy{LONi2r00_kNt&?3%vJ$seOSb zZ`j*-`~Mct_Z;NUJO84n|F?qsKT7ofsv@k`Z% z{s94XT)}0)-kaC2Yq$_|9335b%HkaKq)+1joJpt2_4;@P!(0zS23*lHJ}^EGYi?dz zkY%?F4|oThvd8!bJ(7kAhG1QspFiK?=Js~6*&Ar|e2Iq-uqyuh(z&^$?zIGo&(83x z1OU*nvt!DP2WSYW96$<{ucUgiTf4t0LFU=S4L16Sc7v#=ALo70i5ZT>#mQM$S2tj! zVeE|d*XtKAUVQuZ?OD}u%eFT+H;ztDr#BvSbac+$tFO~#a;Nv+ylkCEbZ3rZJLs~= z=JvQgZuNu53h7i7wndESK07;8udzvAYn$OXK{YBS4(lR@`)*#lVXXI3inQm^?y@V# zxT#`>KChVy*KHsz^(GRs&ru#89-f+-y3rqZcYR&MQgJh6zzB#86*ci2AjfG}7Z(vy zv_>sDtdIr55Oi*CZZK%{;qGc{Rs8L~QHCj7UCin6ia=B^1_nmQ)|sXwMouYp!T8SG zw{P$7?`z0l_NycVCIWb20&sBHcKyR09mzO)s-BNj2Hi%!gRC}>9#Ib@S3{o-y61E-dtl;%1oMGVwcJN;mrqcU`4~bH z5N{eCRD@s&gO!V%w=I-4Yn1&poDFgHy~Lk~lL&8u#*v`c39a8zy_q^qwqbFDMoi`U z(ti;V5g|Lgf%~4*)#i_+8e6GW^!yb5^wR3;X-yJ%q9tUO1EC5zYOD}^nEta)uZR`>eMuHj_i5RM#m{_HUZu+f4HXfL}?FD@o`9G>0bGb!HP@CQPG z`;Q%+y@}{nFV$&Hc4r}Nr}yApvc3KYH2Mw`y27*9Se;j=envlaq|Pob4t96TRj9c? z4lk6k>jH?`JU-0=@6QjZ{B@gkMug&E@cpM+eo8xgZa_s$O($X25~Wyw5615|hNBsR z3kwT+Wq;b++kwk{@J(=WaM-KcoRowG4}CI*!Z>Q(F{M2d114iPHllIR6!MvGEK&;7 zYj1ts=y8RBV8yg>%%$N|Nq*E_gPFFiR-{2}#tXRb4(6`3 zm{7|GV`2tLhSFqZ%irI0#X z8XT~jk)hUjvS}NWuX5lJWveD!2mo3#>6Pptkf=o!r6Oybo5D-D7GxX8rk;P+FjgRt z(0cQZdXiI<-4V8T4OeG1nX3BU(gRCEcmCiHnh^O*X04r6EAEEn%Du%umBn|5GiOqV zYi0BytQ~=qlV)?8Pibz@aOcQJLd{En zU&Ht|AuI2dyZkkkjE_#0Gc2Wd{Pau|44w@pF$P7Sppv{*fcVdnkWJdoltpdnbk6|B z`F$=o;_=$%-Bmc55JsuP1`=1KUYx{=qSO@~cJtjz98VMe)%}{((q7skw4v0f*Wqx_ zpFh3VKu^_a7l5l~HzW8=mCPkQJFefrTS;it%I?m?`n$K**3On&{hFG10RiSsG|S&Q zwHgZ?xfz3Xsj3e>Xq-ZkjB2$CDQoLbio7MXI9JLOIt{ze!K6xuTtCrPb{_!gs}@WG zB#lc0Vzt$R+fH`eK9OqdLp#yq2UJvD`T>bcF^seX`LrnIMWY5+jqD87ZQ z`ed2Z2g*%_ceAm%^ouuEh!IOa?;BLUf&+@BBQ%=~ z!vCCkny!@$D>YAUf=WjiytW&G}r0)wsl0t{k};#25L5h?*y!KI8n=N>puDHD3Qs8ygRS}z2;@`J=5*Ze zlNP(l3>+rE@=>IYFu7hN1$05Cs73;HQ4~`W@{N|xD(V@gD`rA`Wr$!`ToPBue)q|6 zi%RUQZ_c4@pFq=T(W*N(gOpfMOHm_3$*6}ApQEr!@4EK&)JKOuex-G#ziO(+`5V3( zsu>9t>fZwn07kXn$s;=a^U!HFFTM=_K-pb@4e#`-MH5^uv^nh&M6uAM?b(G+L`) zhB7iE(eP?-EhIcIID9I%HfN%Y`8>4C9lXbK#k<@$FPiV*3x+|;@OwXWXUZA~4z*e; z+uGXn^z?YIm;D%~)u^!=wE*JisOC6n>Hhbq$%F|rElL1MP;XCvy6PbG#06ly^Ir*G za2pyedezo_s!oh3HUNTOxT@bWj=5seiX5DBd3uh59IhLdSo!_$C_T7bjjYy<>A!VB z{8)=FnC2hlq)8V`owk^|(3^`JbhSz!=hU67>Yw_Vkg6KdMjY>>+5#Sr4^Hx4?z%-! zord1e!d|cqKder?D){nc2VV|X{%oatZ2KMI(W7w`@pVF|a!2Bla&Z#p5@h85 zchCSUbfEfS+K|ZUO4_N4^)zDsGV<5Tv|-L%qmqaD+|Um)Wv?YQXEwJ7SVq3sD~6B^ z!-?x|T6Kuz2av^+qG1BZ_GF=?=&%;;{UD~j!T?G$DsiKWUL|s5HJ!G8J zk0@@=rMLFh+`Rwvz2oORg|bVDf-k&W!i{uk-vQ^3^ zV0bt;>B9l9hzKoaWaDa9&?;5eP*uoM+{DTj{8`0J9t94%WY>p{#VBT%-MAuE>1GTxEVVn;pBC-8wZvAevK0YnvBc&ZZrw z8{BHN5z7ltH@z_9NxFt1kLz*gq&O?&TKCE=|AA&rw~Osj7+d`SDZ<>fnOgbqPBmYR zDA*XuYyPBAx;>6FgXGCU=E_+$>ho0B>dwy2*48u-;M%OTiBeT3k5@ol=A89dgM%PS zKiqLqv`RRpZz`=X)2^#$FGWmkoZX{RJE)Wz%eW*YVq@)Dh!mH`lXyCzrz!O$zLm;e zvL4nmn=SC#6;%n1apc9`o+(S`iRnNX$)7HhGftz%-02ak(>u1&?->-!#75VwZod`Y z%dgDG?sj{t`6`G%bq;!an^66$ezN(%c)NRsjESI{B3 zn!37xfB@lmxCd|A@Yb+H8YSC$4*|PDw*rD3XvaqY0p?@_tj*xGQ$LUwaORb5@1YQi z@U`t;V1dx6qN2z9!aYwqvC)-PU`Ao$Tc1cksV?JJ%{O%U){h}((-E+#-nzYr)ZMDc z9BMb{quThpSJ28Uu>()pAKo$|UrR5%H1&y~+1aN`cgG9ylB{La{KV)8$b^Q?C3)j~ zYGmOmtKQYMV*13p)+LRTgyp2cdkagBIaV3_ICL%tu+fa-w~~C0OWgM*X{lC6r?wzyb{N;)(O4fRcDBSw0Wyge*Zbd5FqdQ&v=G`QBFNF+VFtWK&M3*DT# zoWHl`=67pj*@faox@bKH2o%{t-sd=3Ntl&qiAA*rx&}f+4PT3V-0gh zHCt^(MMYCRQD`LBz&nXUMieFo`#i7#myE7{KF|lpxU{oNtOs!z)D+it-wVS@m zbVM4iroYMfzVSFQU9>f8f>PI*DlOe7a?YetQeslBnpB*UOHV!5NMrnzIC2?)Zd|L{ zE>T@a#syog7QJh_&B`;J{lbta)?Q)^zGs12loL9s6RN zW6-W7%Uqq~jJ)UqbKEe5uE+-SaWZ2%;C$8ba z8?x~Evj<2$wzcUXxC8yK>qmU8Yj-l`-lzd1Xf?ThrH#Dx&lwAxDYzZ$o9+4DIE*AG z%NgQr^IDgSj=cA0Bb+{vVI=jKlZauvdcE8nSuoguC25cuQJUbX*{Ks9bw;A@PB~n= zDT`bWJUW*a67qo&+~FcG4UdZ3G+|aPNa@>bA@iC(aTbdzD5y{g9~(v0Vk-TwBIY4n z1|IN(Q9oGokA{%CmXrKkLTy3xoe4CWCFdaQFEQSq0>a_gM%Ye>m_a)UrVRX`d@i}K z81W!nHcew@yc_`6e*K6Vgrn(rvr>SZFaUmwF599r9>z8S(f_>^ zyLWWteZ1VNP!|zqeZ1`j)s=f8Yf#F!P(M93XE}-6>u}+mQ;ddsA%7=ePm1a)HcgGn zq}88|v>n@Nl48VF0iXjW%;7i)?CDccPq!%KK@gD-TsyPDA;e@G@wOjzhunX(s$)f=ZayL7P9{-edc}#z9fBsG0o9;j%ET`y0 zKAGahBx3R)5QhLXxz%X`BX5y565ALJ%FMvVRZ5z(9AB<;70-9epZ=2t@14eP2n(L7 z?k}4{H*i3(z?(`&#lsi1kUwIIVmHT=sA9E;BL19`R%sZaig8$Z8+pC&we^~0+TuE~ z8dCP-g$hs+XTn=0Vr7pe?Asxlc?IRcViRTZ?AZTJT-?5ZTMn{&+EnI5>-=G({}wkD zB?3Y{E$wBKZoiTGVBK?+e7#ez97K(N)G3Pck^A`MOf=W@hL0ie2QN!Ul`JUcR+h+kkli za7gFyur*dh?@sOj&+(H2Y2Gp#CL6+!uXAfGq*I5l4k&(^yK(wa_T$ z|1XV#JeN*NOQxy$kc}a0g*=b2Z&!= zdvXA+Y;YrnWXoscYzD!o`9o(`_FF}wyfH}|T0i#>MZxbBic2oY73a)XQnuC-BYK3l2Li0L_5*)2_$#RD$Z2RlquGb z1}j9T&ocV>Pmjz|AZBy@x$48h@7u1mX7d`s)j_(~b_Z$jl7npLjkEpEvq1=mTFXQf zsF8i0C6Kw9~8-4OM_g zJEgvugfT%fVwYC6?nl{TlSd_NYslYz5XRCG33+R8K<9r731y2YQ0Uy9Nrqp&JeU)Y z8=9KqBucp0kC*8=ve?6EOrA93bp5u*O$=b+&N>B1NJAC2XW<9^gQC$V5D{(f++PY@ z@`1^%qPM*^dlHuGN!k&ytXkt*4RTlwR>o6Q$Uto3bz8G&HkHN+TfeX-du*&#b}th! zcTC>z8##7$KBrQDe8en|lzcLL813>ZxDHo3*XZJ-y*@tZ&nCM2>`iWpE?{t&cUM!E zwD*nGaAA5PtZ&QfIzsmCLSsH)yPBhUy_(I`2lQ-JRrKP(^fW1z&SHS$Da1S_VH;2! zP(LcFI_K;C)GHchE~H)Vh&jof-Df**DPxgLzZJ^qsr)}NC&S?z@*6T?KRitpXWj^} zo{kH#@%To<#*$F-$Hap~3MKlbVu2}$12Oo2%N!{)RHV{L_YX#4G%Ej8oHr%4%>~i& z(9!S$OIq*=ZbG8(eW(JGIJc>WT2(Y;bxgj%9wkfhuU8wrVsEt9;$5Sx6?Tyr<&x~h z%JsS$K#|wy3)u;RT_;1GwkR_@vmT1KwxCr(QltHDXC8B~oTQ~AnEa@^J3?GmIw2*z9H*Dw+%U)PaARo?6{S~j+ zV38Yk9M!wPq{leZqpE|CkNtFVloH4#2WI`_l3u}af4lChP{^*!aGY98i%D70k8|zOWb%2*cO8wS30bO| z%z>pl+>vtpvosFJVQp^&bQu>8rFJ|H$D1f_D%(V2TRg@RfECDI+8IlsA+|x5+b70fX!uED~`Eloo+jVvU zU<&{cJU2D<rL?z>Df7{jh8fK)uok*eJ!x zG(0>!XuSkpN9X_G^gy;pe>wU@+8gSA&dbxJ{}rkKyb1QTXcxL_#@#Z-L`S!xgMa*(|X0!1R+W=4*fK2f14XFEf9XPwg zz5X|}h6$;qD}~!H@8vPWu=H;3M!!}QkalaGWBHG`v`RVzL_|H8GPnl;h7pkPmWI=S1?!nh z1IM#P0g*Q1KO{p=f>ueIy>&4u$gg#oUF#Wu*AeGt;B zl_MBnB!56;gm4X`W&iWH(M|C;p3QT&4;$vKx7)o)02)g3Grcs7=KU%?^KUM|zwHg9 z)4~~1Q@CBn#-9s7@TKX-KR$Yac8`vTaB!AST&VjQkp;jXKYnCQ8U$LjxBC?^0dibf zX?^IYS&wyhb$y5YTq41FanEuA#jMIYL!cXEDyetKGdlsreCHe9V% zbeUfG@bECt8`NV2vn4|1TNS>C5S@@b*5W@ME|fr-=wZ);2=05x4E`Q+yGoG~Xw?d* zCh6Vbp>ILEqW%0&NX^{~AWs`${eXv9TU+0KBsk)!xqAm%Mby&L0$z0f;KxH(!0;9d zGO~>`#eB*u<-q!rWh-T&c}<&YtmlV$bwpgFJ|%~zC3jG(k-DO#!qP(-`@UrU^LIKf z`x%51NWKf;HS_3p-NySGEQgDJ5DQlPh;A4k@s<@$&FwtQ;cfvkXapnjoqGkGp0Sws zsZoDpRjpJo+4O_!#{&mC{`9y`68?kUT8@UeK}-_ufdy+4Fc9GB>6zpG z-A#raUoT&_JeW70KC8w2e!mQHH8TC@; zz?o%U_QQWEjf1dRo*qck0m}CfSL84{D0g=j%qMW!~$T!)qrEf0vp$v_ptSt51j6l36k&l$*T;^gve>bL_An; z|D!Ly)wIl$s3_oZ|D`EFXZ7V0;Q51&mJzP1ny$LWm7zwT{`Pi#9g_fzL(!TCAMQZ& zy}2W@8hn(9^gMNL!ruWaSnrV=^+M}WRu1L%Bc=}6Q07rDz$M-aABzKK|Wn&~}NgOSAQ3BZj#VjUEkB zlEW(#lRqJiq5m4!Q0LOrRBTexUJWM4fQt3-psjEN04>5!VAOYKX;1T7H<=Nx(!Ek$dU|`_fT(&&*_()RK+knM_PL}b5E5UiYL)iwvq~GQM z!}w02f@{TbjNr&c#CZd2sR72`{q1>oV@IdL$*jf+}!(RGs^Ff2N~PT zsh!pR|LquU*V6PfHUU9{L-uK?KXRf*Cnti)F7_+qoB`3TQ_;)yoPS?d*ay81Y ziSq*imG|#Y+op)dt?bJQX>jS)$^3tB3|3S#ZY)=wdv<-lrV)`XC+U16Ns|6mMcCRD z?NxuhTV{CvKLfhW<{o`_adD9ox|p1teDSlad+KQEWIvh5^W)>a9-&R)-L88I&2^sV zCp9&~qRC?GM|Fp_o9pAn?|#nbmQTBF)*hBwk8|VYBez~LeqCnf5>jx&u1j&_#tmX( za$bhJcP*C((tCvoiK%Oij(6S{6cmJo;h$a;B)+V#M?gd6^|v2Bd^j({?}viEMxM@c zta^OQ{+(N3yT#)b_526+`uh4%j`8rQIsZJ@tf&x&>JSF5y+Y*b{~ujUBd4AnY;C=C z$3`x7sy(>jyyh9PJu|lrbsx%df*UusYd2qS{%(8+NN+Onk+^t$uh)fxy^^Zx-tkg$ zF>B}4*Q4X(^V7P^(^gt9kJ+XG&v%Cox%zb%7-C01dOZ({tEvPyd@j8k8y!A;xq0Vc zX;(elad)wsoSgi?Vson68KhKrqDP<0%bf$a2m4UHPJhwgI?2C0;i%QK-P|!K)U2t! zq;+4SA(g7VygcmMV2zO)N3Uf1?EUN8mrts{-qwUMfBMtj!4R=FmNhi+L@4X^>4cQf zO!7#3k4$b?q{9&Rx^I-W>unCES#%`{bdJy7_3X~$<5S1y+h(Gn1)rIqFSJ+eU>o+# zr$g+<9uK|b!_$2`qwQ3AYzefUcAeO$ zsJGj@!k5jY`e$>rmlcQ8?ijdK{O$+VYx;%;d3kxs9y{$Z`kq=!N?X(JoASw`wK+Mg zw{FcY#OP1MPbi9=H_dvjmyQ+{74;+t+;iTT94|H}B_{T{WomqJcD&S^e0j2(|JuWY zQ9h1{f&vu z!OZP5X(=frNU1wN`00;BId)9TW6=lBX=QoY73>&?lGnt{j7IPkld!Ny!<%cD$Gu)- z$4mS@mZe4I9lQFMCm-j-^K7Q7q#i!(N)##wYroj{!J7e<)tSABo!l5gusG0KdEp`dua#r{Gg6m|$ zFvunF(U5PRd&0dzDVpX-aZ%AArZ8;u51|neCmE4}eK91;Io{Srhi|V*#Z`ZRk ze#m zVPT=Lu&}+o9g@`!BEOuRoX!{y$p4OD12>HgNbpWwnpYM-?hT&w>>$3V;xeZ6{-ar(KMkuXV-r(}I$8I+`>shBQ z?60cd+9U2*@x;0AE~;s0e4rLOC>_;vhcD;r)t+>)UmTRzg;4U@3}(m!+zjEHK3XrIiRRGX*xbC_>EzI_v|nfn zAY^A}cUbD_?&&dm-FdPk#?OBQJFXc^F8yikRs$9wN$`=%NnU5b-WOhl5$JZ}4#!@AIVkm>RG)w-4Ww}dr z?$JjSZ>B(gwNDH}xdlUrkxFe)VZk0h-COn}N4p!<(cGL~R78M|8OCDD@A~9)Yimm( zQIJ~9v!;jcI6_hMQ*^Y`%}Ltf%!~=s_3h7YD#J<#Qng)K%hNhK7QPuk5F{loJQ&oDqzvwY7Zu? z?wNJPig{h+=~iDH&EX|2(YnsxSSTMD7|`?BZtm!K(iP^m*Dsyywvwfx=ZdaUc(I@F z_4;7kJX0ajXuH@0rBoY?6U3aS2kWO>jd+&_KW*3g5cL*38R_X#Qc{Whb`Ne-is6xQ z8eCqS=kx|FB`+O=IsvKBtEfnqjq$z3*JM@wXBn1}20*balM=P7+4woafQ+cg!jouuJ%WkXaqh z9%ad|d8({zSgP%HvYdHzbOh!O!nDY!sPnx+#iOO4)y|vXw;`v~)zu{=Bt&l4K1n>E zl)3JnFAOq`@9-4m<#WG&t!Mc?+Z@EAk>>%fNRtG+cel|W2l?fX^wJD6C;OxN$na#* z_Za{S=$Mc9mIv`f_V5Ss3-za9?MyqPb2ST%n%>_4FxlMPoc#KLTu(vLADdjn4P=U| zz!Pt2uMcMSX6Jvui`f7G4SdxloaGosu#{=i#x{FJjEV)( zUeXrE^yJYFB~l(=s*!wFJ|psC37#=3v>q=?|Msn8YD$+#N|{JkM@Jz^czJ#O^~z8d zq?kA89|5wM(mt~+J?Z-*2?J8k-iPb1OjRFl&$YtG`9p;~jtZKM1YCF0z%T6W$;rsr zIXQiQd!$T-CbfMroUQSKH$Fc8=VYbBcs^ff3=e@A&qwun2}Wj%Wlc<9I(WYyk&Sn; zX_EP)>|v<5H6||5V#579?ug2^P*c!p&7yc50>@iG*nesdrzyFN(1gT89s#oJ1>=aL zzMsL1hK?=*au>0SBYLJs6EAovCrS-QuTZig(hr(MXZdkaTRbV+%2Z@zWB}y+isdo} zw{_)$Q`Qqy8dQ=AGG>Q;L78Y6ZI{Ca+Lt+v5!|Su{R%O+O zLEn!M=;pu{!9-hXPmhn^zIkI%N`L20Tp`U6n4a6g+IYUcnELxSnXiDkbgR99==poz zC`H2W>iTpoCE|&!EHYF_M@P@b!M}Dyv8ZR4!UbZv-c414kH3nJZb#+3&=Cb@UbKhd z6b^n&@Z~RYK$7O>OQ1?zT3lRQTEe(`m4uWuCMxQ8i-WyAOzofb_4TEtcb(h90QD(i z<`l+h_rMxK4IIt@n~zG=gG>>tnqX|-kL7S>cy%aCWlixCLU>V<*lHjKI=ZR3dGYGf z+ITT+pvI|0LC0?z`Fd+PMQeBn*!1I2MIZEG<7EFUh+p!XL1^UBdpu0qsjLQyN^Y3DX(|Q>X|of z;(PRb?y}DMTC?JIdCw6_Jy>pdn!eZhK8M$FCk$SmQ3bq>YtrV=^34jnxwG^0sJayS zKw7p&B!uu;It~uTzVr8$v{b6i7OGZJRRv5K{6$@IVrUm^?x8YId^gCO;S?uV*W;t3 z_bF}B@!gA*Ei-*MRX4SRFvu5zl>g`JRZd4HfPZA8@hif)-bm5adqryq6~UVvut7ypBnq}uVxox0(MzS^!q(PSuhaE%2!V9Y zY%l$4talpRFl&rNIe67SNL&#ImkVl}Yh9IE5msQFbEJP$~g? z!2Ld`7|8I6OhjOA8BwO3;jpFAd~-{zRy)aexKpK88ct5Uy}Qz2Ab?mtOZY+h#%J0= zMD-Kz+O=bdh&WdpA<+QSE-or6P-$&29!InO4PHqhfuGB;;SGRQo$%FH3^IaldlsN< zH!+!q@PROZ0yhk?%6{Q`l2_S{HBmKn^$Q3Iy^w(g5Z)z$^wOK%Y!fA z!vuwdpy!`fj2I1tB^W}&qfn~j<;>(A;myTGbse29w9;?izTr{}4vAgLr9Fcj4$MsK zc%Bf!#LNses%x!w+PP&ZDZc6H25uVf;Db(Un##&Q@@RE7z}Po7^x!wHfBcr6E%fRS zUAyP>+SzUq7q5*LK3eFU$LrU$JVCUc#1LV*}31oHO!%VL(E%yyesSl{S4sw zymK;S0tLtkPlW@~ro=qOuaOF+`}$jErxp-_p|3z{tt!d^JdeXg}cQU$)GZ zw;w3FJc-(tEfN~&)(4wCAU>cCTv{@_@M881tQ&6Oz-*xZAZ-7q?`CTMpS88KAr(a+ zJ$^BKK$?S~V>nTxY&m}2qtqXlM!`=~`wKWynEao$BwGkq0Y+virbCygPsUA{^loNu zU-ZXm#*Y;!c8>Z11e{w7(CwN!BLx%C^Wn9)rJ1CCj6 z<`9Gsh|oE9{qK`mDw$s--@%y?_n4Ue_+ZeufF+KH33>AU?GtdD`TklC(V+22Rdonb z1dYk&Adc_v$@SF7{kq1-k9T{;TBol0h9xC^w;aA3cKQaa??(X$=r=2ulE89`fJUwd zP8;GX@3*RSgXY+WZ0nl^GdVH43zIg?kVG^c$b-EnAJ` zw0Cu>j$rsCT-C%-B0EIXM>4BeT3VX*BxtFq>>_PBNd%^4W^v(-s7^#gwx~d52}#VH z%&++&VjYwacZSNc_bRbZWdlvF2kYmLqKccE-d-J$ve(g|mc| zfp0*icQ#wO#3tOj`CcXMN@0%xhgFgF+m_4!+Et*@Gsi=fRY-FaU6$Mh8_CUf7liYbH6|P$+syq;ZU@eKUF;^qiY8X;B?>^A`~C(!ngk{uUMm$l zwqFE`4gmoH61|4i9@rg&t8v@=qpYG5@#)j2n3yH-rt|YqJnPfKF8AIxHpubGXN+Km zj8jzf0{EYXxzcfK05ss#Jk|nN+DkGi(viK zepNNK!g|fKwblLnOTlf~>-#$7VnUa!s2>x(YKH8twe;qBk%;;GB+oW`TQ+x}T|Nao zm>ojv)dKqowxqMp#{7I!S$!Ix1pY&1Ys)k6LGRuHQ>2mpR0Pm4&=KJbiK4Hy!xzI_z@dnYi|g>ju@Ut|h~HcTPr<~-wtsNY;sU82Ksfqbbs@(U)k%Z7 zZArrCzp=TUQZ4@s3bGX3-g}b&zxTw3{I1GA>9rU^&b z_bEn>fAqvYNq76@gE2WZ1(B0)E#%eu#6CbHI34C1E^cTL@`Z{pH#d*(b^@Xg0CHtT z#pece1i;i`4Sis}HUWDvXt`zQ<$ZVAzGZ_$)UuwV3;U2|QKd0e~@C>@?b*r7w zwYWf-!_3MW$*>GK7Fl4PcDHqLIhrW7(kf-l17@i&_Zgpz!u8$lZ7zxs-uQLMg(1|H zX|lQ>tbJry2FeP!5hApkLPGITHwup`SJz#(QXv5_ydZTNMw0+v1f5rR6cPY8i32o( z6c$K1HDQu7L7`!Ux9%h`1oQLrU~0c<-$%&WLnAKUpgME%z0W;U&& zdDzXYn{zNsu=68~D28?ePKa0cNG+YX9^0Rwo;si+*nhiTK#BqZM=&ujE$z)*1*|z` zNJ~S*gQO+9%6^M^S5XFrCKGM|fk-}wkQSo7Madn0450@`RJ)81F z-E-%S=zTgX1`fG!h6VdtJq`2M|4+6*>NHnr(A<2Rs&!a@8tD`fr-%-jir6Mp1myXH zgM>ca6p0AE`^&|V(ReSn0Co`J!n-WvtUazarhp3=z~8q6SrXC;x9 zl4=IF)7aR!?rf(Mcr{3@?Wvpr|3ZBNrWLaK9NlW*4?}^kg3aVh2hCR|CMLp{XS1i!Us^vog^0{U_yl;8G;H-y$@;(tCmrzc49(;;Hy90LhxB|UU^wr%p4r% zUayjtpxd$9X+176F{DhgQmTH3)ptZd zZh*5ff*HfWCiDK(R*o-b1=Jy6xC|b*B6-6EZC5>-N_~a77jJcS68rLwx1(cpK}>(mnt|$# zjPHo839Ec+Q4bd=M1Ykfa+^L;R_^DU@hEoQ)Js|l3JgS(5HF7blmL)rcHSRy3D&84 z%Tjf9_2{T5E*xKtBe^-|=C1{*zN-ajv`S~!#xlt+fuTT}A=KPpJj$O@O2U%Xe~iZZ(#Xl|@BFw76nBZCW^?3}ghgbWfvh{Z|X%alG>ui!>+D{(-gT zLWigm4Fve_ryJE^oCO=?8KO`Yc=z@#GWE?#CZVACHo7`DHy7nK3x*9PYvjftyrU2t z8p_Vh3Zl*sL3_?V3ajhJUYD z*iR^t%lPWX9z3OOTlOuKUk2*NvU^bjI#Yqnb;huFHcx3vYm z;tk+Lb+ohsGJ6a-!D$fWCqup$9T^Fwl;k66MQ~8SJVQC9Ct0k{R;t#lTy&9JrAMzky%r-Z4Z9D=_YS>aL z3rT6DFr^5#bTX$yJb-|B^8#m@@W1@;UyS^zY$}06;Um5O3xxwZl{~M;&FSO0 zli45+gaOof#_FCfs>#@skR9-W?{{}*;ShP92Gs%S59QTl5qBqGp;YEJ;n+Wb{)dNkms2L( z%yZ6;j=F_L%{8vOFMCu3FNwsOXRgm}4rVG^So{HI4jh-~#j$yU=X~@WA4LfKy><8V z)2#3aJTp^M`<*^j3yTl$-($S6e>4VRb{q^oqeWj$jhLK#9GHYM(#YwTw-hF|_4K9z zKiJLTG+*wIW}}Gbs-x6{C;Os&vcEcd*Q_w-!_!OSfzJ#dm`0wn#Pt2240XWjr(5ai z!*>XTdk~HS`=R#;PSB@MiZVrs!mV~)$C^)LuNOafAk$AjYvRSE{v=>ul)ozU)M%I` zL5BpbNDBAhW8c!-YENI@gO6&;c3Er8%4h2w7XZ$wgq&Cz8O`QeLgYidz_G%Hd6ddy zdd6xtDU|rPUhsB1ncr^qPk-v#`imCe91ehdNckD_DAf*pzLOJt8gS#@pO3ZfmnH2A zXVgMYCX|)ON6@?n+e`740@}DVf#P@hvbzrOc{{u3!k!kl*cK%iWu7K3geQ>tR~mFV zW5>vbH%%a*P}}ug_Qn4o!+P0ti%x;y3xytP$(h2FN@J(uDtd(rP^vmTsY5?_t9RWD@3E;e!G3$2{mWO+M9tb-3!zt(WmJc|S=>H}lar@p3j~=^l&B75x zJ1Bd^3Q^Kv{)~Z8+f(l@1m%=p8yk6}t9I0pH?~#EI2h@9fx5ks_g%>mV}i+(IcAjO ztI3t|N{6@dB6t7txR@!4H^}~kq{KpOr(myYGM7#5M`L3Mdog)Ljj;Y%h9g7}Ze0@W z-&FBtUoi5+CO>bUdiFTI=$&e}LL2{AuW=I@6peeY8>-%oVhXG=^5j`O?9xp}LD`9| zfz6s}f=zrFs&ocMthlWL`O43b%j|r0iHIkxvQL7YFZ#dStmBLpVq`Wca#*@fPk+ke z$?&&oi2qP%vEGNLRM(yDG%STge_3f#pyjWEk)Q?bx-s5ILG2U@+azgSIG#TVT{*C7a z7Z`xN)4nrWM}^k2@aJDX|A*XGf0+1AvKlWe7k^J&*@+-F6(=+d)qB`-*n)?u_4lsG zs_x^RG=m&j@1IS|&cF@6y*qaA_q_6JQ~fLR0;5~R8ucecGD*K>Z~uHO6aI#gyT)jd z0}5VHi1kF)y{fnQ0!Vi0RLX8Q3rB^o-S>AjiB);@uUz=r~BNOnlLVq4^E!7|XAP2K+UFUmbLKb@AP1BQpl~5(_s_+C;fKx{HYU1<(-~ z2e(}{X@tli8}e#ltnT_8f#vz||J=49+_p2jpWIU=^U5j5wLH21Tso2G;%$yN~jx z?}|^ZbK(^#Bnk_JvM_VmA1szy<9M1N3{<*G(D$zn+X;w%XNmEid|U5E5-%J;#{O}> zy)N?gwfK~kH;%^qt|>eUNz+)Q+Qe5|gnO}k>!S_cR20!+I-1@7zk?w2imxgWLg(1cJ^ zn0y<2nlobcvCI9=arAg)A7zrMzX8RQz*}9c4Wc>2AODZ3)5bl{-lFqcb!ZI?k_Exq znuPk~kmRj@Ha0;EDJcXms#b_hTf!e`O!jx%v;#26+tQgj%B@@6qO9))zP2W2aE^(a_KcXFGhD~I;d{!OEFIakGA@P;v2P|UT?#t z2egrXD=AE~)<3IzA$nJQkSIs zWa*JUooKdMiN(1&2Y}ew!XdTxh}fu<$M#a!JkjC6b!95xBB}Y4k@wMmi-D0brDzdY z59UW@u@}v0JdA-i!x?ZWc>ehRT;f;A9(DqdlI2tS2#>q@CkggDWZ??a*FyJmN16+Z zOfH8NHsq9s_vx7472feY2oC!AELYuwSn7uK6wXyitVasSQQ}Gg`vETj0mByZY4&ZB z_Vx_3BNB&JO~1K{u&^*n8~yaBS;LkfKw!ieDWWmynB-bMIcCwK(Ne(!`2P2bUXhVx zT+Z0L%`07|SzYvg>c1owXJ?H@vtw_E`lK8@3};X#0*4OlIUJ|+^5s^dKsxdc?Urt! z{b+BON$rOW6XE?R^|$M^QQ_BN%NoZgMTugab&IYvls-N_e8pHvOXw07mIk>@esTe6 zpVN(R{5X@gpO^Nr zL4{rPV5VG zIUM70LrcdOizLNc7_Qm~y`&ui+fe>bi`|=TMuoi01V{Z%w)U*pFx4dzMEJZm^LmX{AnmBoIRi1Df0 zOcIYfQ9+u<1o?4zKb`RlE`9a|G?a#2yy(r`(ag|luNieaFaK#)m)SkSe&ju+)cX28 z3TOC2D`pnKm5svl)WBJWci(|tEdoR;lPkm7wqgb9f(lY2#{YixjqXH;->rBTte}Tb z=6{lYr5Wv@!_IyUZ|GBR67o(aXkEM>zC($Y2{9titG~`^7j_Ltkdi{&ZKHB&Z1u%J zm2lfim;UqO@jbVxD3+*luY`X;{4oB}0o@#BTxXG*YZ&vL9FyI_xd&xbwW<%5n+OQZ zitSq!n34B2>AI!x&iFx>U-GBWFP1I-A2ok&oGWJqO?lF2v2@eX|7W4fuzKpz?J*Gh z9H0lt_|;U-Z_qQs;1~=;v^e~g`0>+Tw(4EgR`H(9M^eFB4$wSM!ur)ACMWs6Q@pE5 zZjT@KZX2g_uyEVI-@|OO;3=HsN?MAlG|uhw3;u*NM<_-T{%cocVmDRJzunYA+@JWi z$*>}fu*8-@#%MphD*$`mJ!MC|tp@XDLRJr3k(NhmWFJoKf0jFroTy=iETiDJ9n||U zuc$OVCPj{YgGRHRVdB-dVavrQEoXwttb|g^pM?CcjfSQsx`h!l^mrJW;<~d~I9~XF z4dAH5Uq(edPnJunlN4HvSm5|m-W95!H0X73f{tfe^!7)&%iU|p?Ma8(+FvHz2CJ^1 z*1jU4bj3KF+_Py1`G*6XuN_Dew3y+PRw((^bdBZH^_E~v@v^1Xh1j6=zWO2DDL1S+ z>ido!Ub!vSJ@SfjauYQ!g}p_$3q|pXgdFtJT4pH4t(P(XUFrP+W~&`!FIm^KbDD6y zn~i>au~#PQ_YTGh&K_Pr`JI3q&OCvvYW3I}kBfOz3Aa+0PF9VNpy1CcUH358cT&v{ zS5Xi~HCQS$@^`z~(YAaNn$m+T@3q;y{`t>TniA7qxQ3x10`>X%ZZolJD4|Ps5@#g- zw#4Z+oMC0UgKk`)JE|XgV`Mqxarhg_a~CB(9bEf7xUy4>v8j9_KUbPywGET%qRpT=koVUsCplrOCpD6gOZbP;%X>IDj5i5HBB0~2DlCcC*@!` zH;V)%oLo3?^Iv4gcSfQ>P)oWNey_(U+A`-;t-kp?Z}rY9m-!$6k_X7a#Gx)q z_}gxqQz018tqCZj^;^O_sicMW=_HE?%$n~Em7&*teZGA@Wn(A%pIy{B0PBoEVAQMK zCC&)vD)cwC|MI6XjdmeN&lv$&if{Y+?Yl&qD<0^MBGoHoh#`$?iVkXH^On4C!+rME z&G*0F9l^VX_vQOUGxnEte^oD1muSfUx>Lj<9O(>^Z`DU~A?mY|x9NF3{jSv<4Tku! zho#Ve{}@YIOJ+xcY}&F6yj zx&NXcz7A`ScmCQ3213=vx+_*fs``-8~@3}^*9d+ z)Tcyk_Z&yY9VG`%dAV_c!5l?%J@2-%P3eWdhUIq328YOP7E! zaNC*EYfJfIHL7yyAU1dMSb9Jq&g(IA^#`-8)-9|u!CB>D|HeXRgEjOaQhiTTxFKo3 zP@_IP4S`tYqQ)?j8fP9KANbzUCj`b1{$+elYlaQc=h5Y)7E=7GO$MZZHu zs9bh&;<>|?D)0J)AJW|;r-lPLH6C%T(ype|fJai%{EX*fAd6#z-!ur>c_D%f&8oWuj_eh*G8T zENmRH5xmx8FF`Z|ESD3om>uon@lw>q?$Iwt_XlTT9Pgi@dPR?igbO%wXQP}&shhDB zS9{NW)^|k?5jje;u~acj8O?jXN$S>uvSn8S`OS(yRo)QtJ-M9_&H(IUdRiJ3KBg^r zHfHK(dVBM$s!pI_0wWz>0X4bf`h-0G5X=RuGOv-Ey zyStQU(WxvmKTH3sdhOSnG8M9p?OATELe-5zL1L3IPX9S&&a=;`M` zHNzXvcK7aGI=au~!(3g=_1csR_KX}O8r}6tQrZsb#YoRmj@=onuCN_!Pd05aR!cC` zu+JyoDnb5V4AkHCOHx?2%*c2S;oUfgsJEjEJ<-5LgmZfzHnfqb}m#n#OFA3npoM`9333sG&{(zp#t7qrQr7i1iBxg91Ilj zMqc&H-yT3?Lobc8X?8Nbzq^3fg~#*f%!ps?Fpb+?K`F5@F>sWG+Fdmu!m~je*VzeW zVJHrx)LX+br%N%Bk(#Waqap=mKgi<`Sw9K_%Iy#SwRMg17~#72zTNQXqjs*@p>&ve z-48ZMGD@~}_f|(YNv_c2asRWx6r4T?9%ElC2BK*7$E7RK2xA^9=g^A@gq~D=0FbQ7 z3a59&VcsH8J%ml*{|dMq5D3GrT}v2J9D*_jvhsQT`gM@3!}x$7hyI60!DPSJ)`Hz- zpadi<%fiG|Fm5fF$j-yF2huZ8!SZ{axxhbx5lDwp!Pz{=KoWs$S1PrCZ*6=R`WHYz zXAIT^R1ol{Ak>6=wrlAXltw|MFl|iN3WP~ zvrX|hh(zG|Bk)KNRZypZz6x9lP<4?pF_Nf@`c$n@PhjETu!WTbmQ*84m0mg&IiWP8 zFf2aXi*d_R5Dy9n2!K)mQfPQ^A4ujR+9N@)SZFN$w}}G^tndQbub+esl;-JAiAhO8 z!UsokP7LF0NbnENrSeI&p z;VR=y7MaSLnwrA=m1wVnyMyA2Vo=n)=t0ONaE9@*w z1@GVA2Tg{oq9RDcvIw7^D?$BDI+&~dY^}i{x+0pywrY@;OQXi+>IH`a3`zT-iUsu4Nga+1mWmF?_ zlN2VStK{E}ybu}=IvC!jQp1N|%n72JjruKkdU_Owhv6}RBqBy@Hcy_1Y{HsvY~Ui` z(Kq0JzG6cKZh7Fg1b&tCCJh-Gs7~P!-0W z7us<9Ae4p9f%gNsH54s0^z>{BHCGf_Uz+cnLX6tDnxoF*X2ZRN5_T_tdm+fej`2HFRS zvP4pF+T85yEzB#uyI|hmzJC1!1r|fYn-s_NFvlc8>7d+(Oc(wiCO;}F3Q&Ho`cJi1 z;QF-XE74)_-Kf!OMU!07Dj5kgpQf~wgdASIzFo3}UDTK?=iw}k+Wg7)^RWBrG3Cj_ z=B7vFd!z0A<5qe}rOeO{{3?}%QEpYm*-9cJhV6C3<>H~I$|@>CT)`|46M^u&>O~S! z`D<%LKK?MxY>7-hg$Yxz*6XF_(AJnT9(wig&j(Tm2lDY{w2wQPb8^u7mi@5LQcAV ze~Cpon&{v?E$Li!7MAP4nXU-M4!>n=3dMq%8dZ+r+vDFJ5rF;fbK;W?7h0$-P7{|T8nCG zYa!}DP4lISFWn?KluX5BQOA`bXq?g4&=`fH6zE9+fPlnL@Vl|~DAFz+d>S9~A9x?q zMJtBvYTV6qHye(@?WL<`5ovo^Sj5SZ&B?*yC_UTq^%K^j@DK$CC^S)neA;%K`}3>xY)`8O-+k$QEE*!Y3V^Y{_0^;COzFb#5QL*u`kUgzrSj~?J z+6hHd8ZVDC&`!gCl2YE=-UhkZ$nvXjhU3#y#aPapEG*g3Z|PFMX8vC-07#61DYt^;SpY;_XVLH8wGJwZB|@7-d_0RxIDiIF!vbDHsqgMaHYorM z?CR{C<7emO+(I5e;8r>Tp)CC=ocIiF5f-4&?FEFPqB6I<45u#tnVVBFe}GufLgvSD z=uUi1Yn*?Z^gve1izv9kcn~PH5lSOd#Uk8xX1p}YW}nkGSz#gZ!0k4|JGS&rC0$uF zaZy8pj$G6(?)4E=go&+AvUa?1=KAGM!#LLu8^q!yThJn#;(ZhZ(Z*Ofi7n3$DmN1uOTO!iatPT|MUrom>1uHS8KJkyUwm!x44H(!A~C)UD*%NHf8EIJZ(4w@2`5^7eLtR?vo=-DC(EvsJ^W8d2VR)YyqxQY9Vnb2 zZ!t79g#Uud`s>%Pzxdhd=n#Bkpt=UVBoWb@`=U5nN&gauwO^aL(6&?e(}mPvaN<|5 z=!ElZe$^Dw+~R_bJh9U~VJ^`JEOqyYc?5{F#<|SR7vb=^U$$GQh&Fk7j+}E=i?g9v z?N+W3udb%Yn-dFBm99tFW(tbow{LC!-YzVi))U2RZoT^ZDVKx$%6)ST#1A2(orb8+ zr6&Jn3fy*+oJchWTgharD=A*IepEi1hEP*GXc#oU;lAs#qnSa7&+B3}m-3$fY9X`H_);HDjk)R!518GX%)erXjSK&EH z#VU)Sn#`~R2^MGsjs+iWZHd!SZh2%Asx2AIO)u=JK-LHH(3i!&bo@d>_k?(PKK~%p zlrCswbD(N{@H9)c0xLSSb@vQ9St7#2ze6V^NNZ|$doCFn83R-Pz@Zu-pb>_HY1Y@) zx*95e|FwJ@+Ozg%W%Be}{{H9Iuh24yTlNZt!VF(KyM+x)Ee-Ct$=H~^IEi!)tD{7C zJMSf!miq5%+nQd)-`b3SEx@Ltu+P1Bt*UHt#-L9k^ctcmp+xRIE(W6SfcCO(F12x$ zd~H+`p4*9dq^9*8EzFOTl4U_GV5IdlEMU*zG<%z-VI${ zS2&OOSMc);CyPByVYgW{GAf41B^S>v*1@bmgtYn$bn6$x>rVuZB73>x#nqcQ*|2a5 z#Pg`^zRHcf-xyTdAj6%)+NTj;{c6CcGu@ZhpNMn2EFL?6*nLDl`I-~rAGG`cnUK1g z8j3d^CZ6zCy^5kpb7=a z@b$cln?#F5Z5zgJwzkdD`_pc0;oLcMNH}TAKxXDO6R;=>IJ$ z`C3pgogfgD*yh|yi63Hrkc6fP*)%jgdPU2cm!mHcuoA1w{Ed9L(EmYEc4(o}x_{FU z7XlL#^F1`_2L-XPu`TfTK*P{6+h6Wa8y{FmciPT0bzFMG^Xh@n`hIpa=eHPIHnX$i z7nW1h*`){=o`)u^Ue_&^_*kge^oF@NAyLwTKhH|*B!vlX6IU3`LAzmxnh}BT)}&~K zuFdqfkmih%qm7oltkprrZdj}~n<_>T?UVCafQiA>i5QDOjjcLdg?>fzTz**bmr->E zI&sdI1spXU-n7thT~Em$d7d}%EZ;MPK@!b_)io79tYAdBRF2{r>C2|kg97!H4NJVD zj+*&5&Jld*A#SeIL+|2d&4<@w9qw5THk@Jqa2oxJ41|Uc+;V&FxB&R06Fp*l@V&N@ z0_%V^sg5U02@TPQF13fZJEBTrmch6bYadQPa{Kn9E*&1RiAzSj-|CgMlAPvwT4km9 zh&MFb#YXY!u`+*mHcJZZZ04n(Mh^B|&*j2@l>bFoBQh`hu9akCjH~^ih)JRNmSg>m z2wlGYM)lh;Bs=cT8_C}9==7reYXq!W#r>6|YXvi!U9Zeq5?vHc4oP1fys|KGZpM4v zH*YGNtn`F_G0=B%Z(iPNgkd2-=~J;|yGNfVH``?H4>tZd2Y8@QTeAUG}?{?mPV4PN5Q<3c5+`SHyoG$hQ+Vrat>NGLVoM zP%Lu&!vAv>?V^o7r|t7^34$a%mOVAkKRT|UmAd8Xymje5fCui#jZUxB#=E$nxBncp zN@uQnzx{C(O`yDOjA=8i`z?abY+Z)^eaL>H7p7Zn*@*s(j@I+5717)3%FNGptN>0o z;@%Xpdv273Nw*jK_}?9u*iA%ZkU!CVBFO^9M&WJ01bu(K{jQMaejWy?!ta5)&)YZb zyZnmdU53Mch>b<0P;eaN)V=22^qHzs#?I==TVD*lUxY<8@y|u$TQ@uzYI}Lb!b7dY z+`0ZOqLPKXjpBhVr;DT;4S=+GElf7Xum!Wl&jjgsJ9VNVxdy$n=tY8zF4A(koOfD6 z-_^DJoS_WgMIeITzBQ{*ch?H*G^;5Qx?^TcRJ7?kvUIY!l6U+k-d-LddVu#ss7>En z_y(fMx8VVTQJH*qewppdNI}=lcS>QNh*W}Nf{bRyv1hlf7O)CgP|jL7p3x{?r}(?l z-RSXQSXOsXyiFrO1JLDeL_r?kv(qC7&&L4iyUmv;uWPUU=2yU9OWWb&{%I_EKL97! z3+v`{9w%&R{!lB6QF)wzCD-cezdi}Wsk8Cf&1u@GC*-&(obNoTBn(&iL#rqJx^!YY zYfj^JYDR-q=jVTErUC#`VdXRTtTcE|&>`tNvn3E@CdEsKfBcU8Rs4<|qzP$@;%Q%; zT%Fv^*4qiO4fpK_ZM@YDdQmfcS2I8G5Es=2d?uz4Mhp3(h|gdSKsLjSA~|e7H?V}q zl}1L)Phzv;Z;=u+J4V_%51 zQIHe1DN#4p7B&h(%r0@sB0#RUH6l%^Y*C;-I{uB zmEeps`Q$$rRn$Uq2&LE(MlL6boVu%BmCp#uMkto7=u=PmhK;)GK1fuPM-?>8H#HKP zw==#Ven*JcrlmXai}Ug-9*W1U6!)C=4g!>>y?ra(!(`$-jIWPnH37AYlMqo;uT@C) zo$Ln$_KlYEpdyUT?AL2DCO%&nPG51MEZHCZS4XQ*(|n8Bwh(Qtz&>)je*5LCKdohw zgRMZC2S1t%8U0)CMJogp9(TkhDkc zshM%`q`R+gtfz>5B1#7w)Ipg>G!gUJii#Vg3$q~BGB$sU~)E6}D z3~E_%P~HnznT6^bFP*;5V0(t2i_y3D>FD8yv?#4x;-)7Z&$lVhUs0$eB`m=MeCwP% z7Q33#DF;o4+hXatuEKGj;^s zMO5W>$k<&WqglwH(yDa%K;??lp~<5NIc|p%tRH`)?T)=1j^{TViu(?F9$Vc%vED~z zTrF3Ben)rt(W<%m$aTYut8eRKHMPFP9xD^A%AsmiSNN{?-f_A}SQ7|xCJIC-J@2Si zM_s1AZ|-AH(Ca&d+MeaaYu@oh!OU(y`Q#xjW@xh5J?9@q^AB!_^O)Y=YZ%PBezo=te2pX6c;*k6~A`aJB4u^$kcNJja*b@Y;P`$JM4 z>)O^qQ|?cdd%N)Ox4hvKr{pKn9|A*g5Bn#N@Ogd|21TR4(5icGWoedINFbh#cYT$X zT8Jw{u{KUwn(E45_q6WEyCiXSCpZv6hk0eNq0b5%>yf4zdCxJXee@@KO*lIRPXE~h zrTmq8$jm`BKMq}1{%6ap1yF5-2XF!X35RS!yV&vR;QS-F=O(rW|IjV=_BWhi*&O4V zH;QTgKgQlVs_M0C!(A8{gp_nHx4fDJ7)^ z1PSRnbGhGlf8Te`KWB}x#~yn#Sp4FN`OJCW*OVdb9WYl|6A9q*9XV{#tK6vnvA+OU2+%xo7}xHz?K(U98Hi?X-pzJ)Ox#* zw^@B4I4m(%j4ca5B|ULu~a%I$rT>FCJE%k=hf+O<+lc$+HrmqC=MZ(kE&`~M|H-Ne)ZKUt ztN2`heu<4GxpplQ3>=GK^H+wFinFux=g)_r?U#Z)<>`9u?{l95u1Qu|bVj$+`f$s zLwF9)h1HQdBJ~^`p8f{j>uRr~u0DLl&U^!V(Q!upn}Opag_FY_92^_~{4AYLpB?!l zK0+0wT)!SFzF+`41qxMOV}nxm7~n$SzhNP0BMk})g4RzM^a`Y0VayGJPX7`@qTe6* zBiE#kp<+T>=!wIHZ%{ zHwj2d-Jw99+`BvJK?T^UA75fHBc+V%HGlZBc?R1EVaHv{=3%}wIP?{#2)uNz^u~n9 zm=(+}1dbGKEV-389d6~9KoOOzI;?kP;Vy7toWN58SXzXr%c6>>rzir2Le;^!`!P+< zAXJSB5a-UFgIDuO5QmmZYTI|0rUfygsRpQ1C2S?F~?j zspLF780CrsEa**r#!TG*R8gUhe-~e-31{tKz!G<`<$f0^zErr*BZh{kL+CHFDPY}( zG@6YK2Z9<3l91k!fSfcl!g0QX(C|)y&iPM(hXBA*_|+eay~(_WRbQYM*VCh-7!4KG z?|1#5Fexf2Dq=l-ay6c@CFG*#}g+tz>JDwXV*}dJ}RJXic@7{ftJYH@+1^zPtRZR?J(k*yR zO-?>(4Y>{#G;j-1i@WCO7swg#*Is`95r`$=pSl65QZUhB=rJPph5&VqjO>SGy{^>) zycft0L*aBtLtYs(Uhw%;!b>4ZM8 zdV0m`o6LjihaWz*ynXTFg)i8FzAcK{L$S3>9o&1@YNshNY$1O0SmnR}YQx>#g(4~T zQ@v7~T&L*@J1PYD%3w|wyTxj!AU1$aWM&T20`WjN8SZWj$Y%zkY?z$~@0ljq6a~~m z76WJ2h!CD>?NrQuEg?L`GhaS+{3|*+kIDDx$OlIrUB-W6u8z3WT>R`JOGH{qz7Wi& zjEoFpuZ6gH{1-5+97R1F&4bOmh?L-;Q1DV>UkE zq4<9bwYYTa#m|XiT0z}YamR0@UC3#JdR2b?6IVQD4i3z|8Ef5^=z9>*MK*QGiSG(1 zKyZU8UWthZgsnIIGfOWF^t=&g2|@ZKwa+-+A-L}k`-joROKnchib>5;a8Hl+*iuCj zdD^%xzqVziQvZC!?)56_U-?LzM8|Cno#4S?r~~4^E)C|=W4O|RZ~6DHH{4m}zu*w+ zro_&_mNX|C+IkKl8q`wqk>--+e+MjTJD{8avwKPoa+Y>}e1XDjJC0??__6m3VKIXx z9q|#CJ(vXWfk6cpw`+(+C~3m74p51Q78ZszuI!Ng)KyScHaD3DVw|fh6n!&+HWdXd z76ds|sbbEF!idJ%w@hxr9I+9N66a+h%k=hl@4!$YlRPMT+5d$jW#~V94w*cV=#Wjo-?;)-O+$e@-(iTny z0I$KYWY9#>>t6?)!Z0lS;g!nZPV$g3y!1QRv-ZVJfk?dnd4M+pB6oUTkRvwY4mLTh z${WvHGIn6B#$eJis-A~(D7aL?CRd`Cn+*18#3R8ZDB%41^$TflUdrfN8++1icR~ z0z_9pAoK)*(%!G{nYa(Z{7VP77SC+}Vj^G!Hypw`39czgkalHYEV1y&Qus`z-Q3F0 z_Y=ZUo$>tQ@-)~)<+8b-h3B4yh^ipHizhb4zbjioIwn7*zNhTnsK9qaZ3%;yKjOa{alXgQ1Ug!SVk9@Q>jjlE$da~% z85V#x1jv8{@Fn171NH|}p5x`KXQduzo2tWBXZuCMVpuA#P)yoXuP*Q-!~6K`WDVq3 z%dVpz-Lx|O%D&L>)`gR!{^iyD4>!(u)`URZ&T?E4 zycSr;uoxpM-e%5Bwn&D<{qk)bo(*V=;m0KCLP`rmy)fy?Raru_t3n@_%=fF)=}r!) zKJyJNlYzhp{I(YBOpZT3VbxAfefjc<7w76#dx!?99O{aztG&RW?pvqA0-C394Nt)N z4e0GHct)OQvSda>BO@cz)6?VQ-6oGE()!VlU=*NSJDC%pe6t55z|P)&aZde+7K8o# z_AT!o2N*OQYS(}*l!1Y%fMNm0WkRO~c7Q2VRB=eT;7=T7DaIhrfct&>!scbRw)PF4 zepE|+nr!$vT0OSM=UAlY3G2oG;)wMWV($`i%6t0z`%Cds%`7`c+l%`k7F1(v)gDtNd$sGOd=-h zE}N)on6#Z85U80IuVM$(aVK=2fA%!*9>I5m!_h{`o5VJ+tOac}0#pjp=xtu9zII%H zc0N^6@sR}vKJK{dEN;M4F9-p%B+};9&Yxq0A^L4k@4ggDiwVY(+FAn=nz_nP%x#{Z zQ})m-d(`aPz{M#7Ku;ztkkk?Vu2p3f6@FlthNI0mSXv>dgi#=O7y%r3CP0y4R`V2> zJ_vMD40)D%EU#)aps&o>U5(p{Wnw3|45A6*0eE!{hq}JMeWn>RZa<|m>uOkJ@1Xz7 zMkhBzlD2iru?h04y=9I!`)qijuWIeYk*AoN7MN>M^0XjX0;=bIOUng?Y3SS##z#wv z=_?U&#pF>Z6_ST#Z1h4v(_DL`yf+$!_qT;N`rLqaKo}>13zooD?i3QO*{gxlB==|L zECmw#mvH(;sf1#cEI}%uFb$o#Q`k``71x59>{!Wkb-`l7Os3p8Jef=@X)K7Oz@?~E2BD69d$9{`ro8wu z!Bwxn(Otg4q_}l-V#dtUpK@(n9{RcS9eZZYi7^y50p9!rOPz7<<&@1`zOcxDAE0x! zgs&cRd*i%wHCw@FUa!xF)WJWYe?*wKguvFT_Uv{PrxkxOiE(U<0qgc3O_T$!5Gd%O zN`4ikiznbWyYzwos;yCfs8UM^ks1&2#ST<&Nrx8@Cqay%f z1W)64-F6>cI!pg8L_@ zu&H4PB$$gcH=hH>=P3k9Pv8_3!=f58(GK0Mn-w7eOq4S5Q4`gKVmNm-ZfWTxC6s1> zO6H%(@QENaIC%5uL?BUx3B6g`fPNl)tLee3+?If*H-4tig1=L4jv;h>f5x}?b@Zg!?r+Wfr+J3xZts{!@ zh7}8WcpHQ)C%?~59n{qNfD@IYo^GtGE03}%$Hdj3q4HlXs6-wX!*q3=Wsav_n|&57 zUBE4?pZHq)D&6f?0#b&&e+H)peT~g4LPFi?rKwmF9p}Kz2ZqkFsIL8wraw)2A5S-& zWQ6j->mCH;1x6hN8<|BX5wZp%AczBxAby0lf+}zCZZsiz+(B8i-FGw613RDz!inQ` zk4DA}*hAsY=73AdpWKUzO-)rr4G#~G8hOwVs-}n*=j8!A7_{y$`c)Ma=#g-*Mvw$eF}L|)fsFiENOghjimLQZ=QBlDlUV}Sk9Kqtbb=^Wh5BQcI9wLOQX%b$bbOi(s zWX$LYLG>C{`bm^>|7T`op+V(3Oc+YoO7?wQQa21RKpYpB8-&1)w*nx@`3PuDt|2o- zKbK%e`XcioHO(B4$ocm>nb;Kn329=7q3@?(%aV4unOO?@dDEMH`%mrYgYB6f`dUbE zVH!`vRdrjG04u{6z7Z~=aUtG-Zq3V^0FK50*O^@_RGydWh09CDNL9 zNM<5J3}fur8C2V|$@+?D*#~+mD!6ov#&Un+@BY*K zA>+2|FntVWuiroMyL#P#aE9;dFw-J^(j%jO-j_?wP+BKv2kdqVPFr)vBW-q$D5sAq zf>rZcDD~uyJO5ojaQy$|-VOA#H}Chd@O^#XyYuL!sW;s91B+nT@|nGaEcdyhej2jN z$DfLySxRxi4-{y%5TGF3Os6K9o6)?t7Us%HHS{-{a8r?$ksKyqxC@0C;AnJQ=BgO1kMu)hR#5Z6MFwd}1ruXiE6b(;q`FJZ>V zj}J)NlY_VEqhTA^zpq_5SNHNpx2ITeo*Xp;tm=Mu?lkFAZ?sW4VDNg86L|0&=t3b0 z*%oWF4BW(hLUop4Q;o2r}qVB2iY0c1y(iK01oQw z{(M#T4TOS6Szg{FSoh%|06r|%4B*SV1Fj8RA)B7wA)%ojzw)MGS#@yWC4~JQ*2PV* z2GFKCL+>U>>{)!_x}<3NTM_7BM{5S0ICD+<=z+<1R{oV!o>duEu~ zuQA_Q4j-g@bLJ-E&_DCc9X~ZhJW`N@K%9LIrt~6dQ2J7(a|Qyvt*L#4v-Zk ze3A@T95knggpjs4vRz)oRmCD6PbSdszcDof85I?$^n;8QK7XtqZ^(6Z33=H`w5Wo7 zj=uN%xi{m9xO#XH4}gX}-E%e=ho=gVQ%Nd0n6=AnI9GJ)0UvZp@PI}xuzIHpT7SjR zQLB&V6VO}Es}Kf8$He@uSuND+$GdP2PIZkC#oF3(64sv{uJQu84D&TTJv~r6!EH{y zhB~Gq`Doqgzw!;6DSsEw-~40%KqNL4RfeQ?Bl~MNo3>hY2xjp$-HY&`1&<@M8sxL z2Rl{JIZhN)Oed|+FaFS0X%x`MzhuaU9v&VN5feiNf$z!TAHdp*f2Q6_C+^w-ZJsQuzM8&8OcG@4U3HULY;ke*zPOAWHhJf}$cr z1_+?#cU8|JJ|%{Xi*Hwet)hEj;;p9O)5T|BfA58QF{-sk{0R^5!WB?8t5LLZ6B4T6 z6{19=^CoA0F?FWI@2_Q;V{QmB{S?l19b~-MXZR93=wThqkRtPE{=x1#FeORU2Qg#q zWZyW97%}fZY=nuui$OuyPCamA(BY5C7=uKuEB4xcSiFrn^f~}8Yb%KDfG#357EoO9 z2~EYMk01gksDpqStq)P7t$j$>d6KR=(oBYzo#?!xB3^>aY$PG3=&0~MN(&B`8ogy3 zXR)!)2lU9w?qS8QmLb&jor>?Aqu-5aXwx+lVpG%8P4C`4s+qWMkp0Iubkun6*9Hf# zYCo^OxU$T=Jr{4Kn0TGi6X*CQkFCRoUF_t7k%5tAX3IK$F-{SY-ZyV}j=Hid`sP~` zX??<33(5rAH|$R3eyko^jOPy*N)Bcub73cb^D3*iYwz2Q@P~$}g1ag2beZnkH$0G_ z89(WXxOKz+_&eTQYZOg+(Y;GOfgZ+8c=#oBPP73$pJ_*tqUI6_Z6eqP@-_(jPBJ~l-nUIs!OMdXzZsA%kuu-pP+G0j8Oiw;|K20kz=P&)k_*m_avHbm zwP?|A1FL1E1~jKHdX6V9I1k^mFDLaGhPI0&M1)?cJB5FK9jj!zTSz_A=s#OdyB6!B zxy)Nz+rVci7~w%{H~mNYsLG(I@hoJMXn^c&eUsAlMmmC?bcB+g*; z>G!QaXS5C83n{j3{==5i5l`+P#n;PMI$rrZ46SbZ=;93H-a zY+>|ngfZIuEH?_GJs7B8UU%e11P9N2q6oZ7h#pQL?5C#+7wSMOm@28?yXjt?vYx`# zx$ukL&E~z{!0Mw%o6(XtZnl!kZzkp(3dqYSrv;B1QF3?RP~rHRv%G3|Nqn-temw_Y zsx_CpqDSBhm!&~Keqk~?Z&dsDuebX>btxn?16hFLC#Nc~aYm zw?EdfKi(99!`oLSx9FF9;vml};PSI;(B*a8nPZzLzDjtl;~~wSF#&l#llZRoDCM6I zcl_LZ#&hh}(rFnpiVtJ+7g^so&pv2~uye2z_Z|35J!pYyfAGld`*y;Zc#E>)yAg_* z(ga@B5XOx7tybCE*zIo41RM7cJ@0<;6@6e=vnIaT{8i6~DuhhmXcnoTI*Z48!3`3ltUdB0$|W(T!a+9XR?3Gwn~P+f6I9b!urF@ny&?-%W79>)I3TuHWBXz z2OqL`tZg0!i@)C%utlSf{W8|=uUVtfBsS$CXoYw82%;i8R(JM;1@-;91|A8aCQ+zc zleAJ%a=D8pSrJ;qZaxyM8J^K{p%cX&+ZDeg->X+YN?v6|??X9=% zDqXU7VYO$?X&sJGh|^r7+}BYN@ztO5y!9Jzk4MC=8NOvw_Zhz7@3r}8bmtK- zS~0gCNUZU^%xw6&V8hMDtw1R#H)3B@wk9C?96^EjB=U*)N5->TzaeJCNhexLJ^lmd zC$w6miQBL?VGSIyK8>=<$@JlGANV>~8%8rtu^{=Ip*QGyXH=RZWh#tRbjRzoyn^YK z$9cN0uY_;)qEI&BavAtW4;4)hgEvUoV<{tiQl;PBQ$nTL^F{@A%;D3tl5JMi2H!&s z&8;&;3ntwmj(G6%r1VK7YoGJGF!Y~ML)XW1P5y=+3xOym)tZGVs-0RX*EPT2yawKp z;i-Ugunx&9yJ{F?G&0Y+Vr*xvXrxvD`PDz7tDt?Ag>*;blp zwk4Al-H*y(M6Ng&mX5i*c`9nMzBt1R>{HqjAJxluFLym6QA#~P@vE)az2nG#^k|hq zu|ThZ*zEXjk{dUsI^_&R!eP`JxpBe*OrBLPfMgfJ>_n4WMnO7cv{GMz; zng1C78evqrLfq@Lteie?18s8`m$@3Z2>Y)r20bB7h393s_d9Q{tNTbApLHw_M?N+_ zQ8}7vPXA>s#eYfp>psP3A{lq>K|=o0*=#%ZazIYGfg}xA_M*k<{HWyWHx2(E8|}l5 zUJD+7|M_0LEOXV@>9}Q>r|vi{PGsus+2cVR?z4SwJqg70>;BbE=)S71>yw$;tE^-m zeOhaD*R(8)D%e}!&^}`~NprOj-|nH4*PZtz<_YC>4a%l{>JoGx9e+Z8AatfaC6#i5D-?c1qQlF*59Ey9Z$BiwYmO18@hq&G~CxS z(HuaZVI$PqfA6_$gi5>Z$twF?HDE$!JUkDHX9RhxC-wZjk_|LD*{`LoR20eO3vd+7 zjg%D^m&>fgrXVC-{yO-_ZJ5UIiT+sdRf(jsxIo(cUSo~2&{%zQXLomJYK^01^+;ut zsPT%NF>6liMnUd&Gn;((12p=c;z8?yl7VWyn;Xr$In{05#l_bosOeqdndD86lZErk zFF6HJoQnP9MMaa7J2K6(e&J9{Tv%A8tiHM+v%ry$~*_HqkHpGN9l zOs7eHj?^a+=QrN6YCFMp?2=-Ixm4cMnsQDf5;6KY37do#N+{r~+K7VK{Z&jPj zRq85!F-n@)L9pc@Ww?;`YhQmCA7#hu#QT+F8oyUmmF^II_sBw*lIY=e1xeT5d|YJF z!BatbTz;@yu@UfuyHD6iGwpqLmttqDwbNCk!2OaQH*LH%y?EhVgLLD^UkNk}mE66J z?#SfxvMVz5A=4!p{bkLfgV6Wd1WPNXCf8Qoe%lP|cX{Qqk7x8-J9>W=5bSy}K@{3# zG%zpvz2p1f@-C$Sksu1i5u>-1zxx?D-wy57HTO zzos$bD{vO)rhXf-B)Rtx-Tbx1`l^h+v7-Le)9IW}wo)qs)VG27-D}!0{^X=@z8V&4 z{XX1)fFS9#f49KkIQ?`#Ni2bb8QHjWCg#4Em&25&nA5O`^cwatn5H{wrdTO{mPxnf zE_V7ZZQERk@FMoDRl&ApH?7LDlZ8*N-Pz`y)1^M$m!8=YS*c&SDXp2yb$FWFFR0z< z-RD0kK^S*vif+v<>QTK%6xEoU`8KC5X?meNUavvR?qi{SWV*t;A%cTRykTK^1CPjr z7Wp_yDI`^ zvsb1}$gQ6a5)jmCi8?~JPbFZOY2xlSHc!Ge?l z&#nWAc6AV!rff~Ceva2Z`;2)RceQEJjtM&lcw+yCtB1dmz3 zYsriwr}p|qoH#Tys4y`nP)B_y%jZ_)ETsh>hnIo-nbwn5Z4-T`tm+QIcW(Vh#@lYA z6U2`utJikUeqZ!|s!&KNwX^km+GP-G3AnnG+jAppc>Z4R*SF1?Ql$r?V%hq(#xJT+^q2_Gs?7P1vxNE071@7P3H0Pri4-(!fa5%un`?zF~XK#Pb4EuVQLX zjXWVGq^0*Ar<~K4Gvrmv32PplsKNEe8Z3IV9jn_hStQ*@%z-GsB6V}6uit+O^(uOm z#v1h{9SUzzJTbLOonN&nD||P)SlIdHZt^IdJ9{+K)*ddpJk_G3uabmp!BUs~x^biM zlLco+8{AKh!I+Bgz56|WF7B@%J>WI7$e7~u*M4)?ffvpi14_6N)QpTsV-)+WNs1v$ zN#|$zuV~6i3JbnNHY?s*yWJl*c?FYQdKL#$*#-^$7BaevBqk$C0@9&5ON@$?!IQ0F z&j9wNr5s*5hT7TON+ZHu{hBX-rmx|NVn1MWtrT}>i@myaAVGtF1kdCSolWr(p6B?A z?VA3IbEUAD;bfMoQJNin`rvOyWMfhL(n`5_FvZaw*l{YC31X;}A>#aFf zQR+vR;-0#f6- zL#%qys#kO6DBMS`q{Y7%(#f^oOnM$Gij0npmf||rH>mB(MhVqdg90X>;(m9GxOYT`RKQ5Ju!y)uge}7QKIQgRoU7@@*`Y?)$J#_9RNH z(Dn=&MrCq*sHt+*O~?Q2WR^BRVK~-gi8(m&+hjIHRLa|KpCMtBJHlr4H6+`Au02^Qp46#eLpX(ecOPs>u`B()^Hq)9Fi@_B`a z<@<_Siai^KLHw#X19yQ`KBRr&m+(W%UM6Ii6hlzoSros z8a^607+cfEXD|4MN~2-zhyR^e&i$@x$V`+%UpsNIN7$hJ2EP=0-?*XWZ$3*hT%t|Q zM{fF&-2>}4$Vuj1M8s-^ywAfCGk0`)nm3{QU?z>x^0g1%&8O%){Z6 z-*15Y4w9>`ikys@oPcs}C1pm@0!6Yckovb6#Fyb4Zd=lwRCPnzHX>V7GnY(vY1y4* zQKw>Ss)S29F{|HKu(a7u<(9^_vS|-@PlXQ2(mfvqYn5K!k3Z20F?HW&xww1YZNJ|znN;wiLvrZ!7EI|9}W3XL)>WimA68_G&-KFs-WU|iYBkM>T=)#J0;SlNZwlxXyU*LJp z=HB(wqbDH9K76?_hskrBW|%TVO$bZyjDl8@s)FOf-vTqaMo4T%O{|uORqRkIaNud& z-+X?h;ix2@{`mp>`(w?Lw;b8~^Lj~P(SyQUkqiKXqg(o#?e!TUU_?EFzBb}jdAn979?(6=a#MA0%cQu+N=6^P<& z`ij16ZW$8!O=xljbp=xlxJ3U1dR5EaO5>URd|Zdt%!<^=lf#m4f8IpDlob3;?|;|D zjqn6C++N3YunncB(fz3|3t>_ORtj07CFYqt)llb(pC68ewIGxTJrI+uAH*6f>rHuu z0<%3K5HgW;KV>(RU4PBu3g9O?Eu3xyJCQ73f(2H!hp4rsrNaU;IUP;B1LZ;2=16X= zU+9f0QMeZMZ%uIpYKl=mRd^Mn(Sc3{{HK)k0^R$oSb-%y@a1xxw9Ba1Dm)2$J3E`d z2>UsLZ@*@{)n;0vaH-?fza?`XmbArchbN$Z8D+@1>qimTz`8+6Ed3Po0BSe>@be6I zGSXiQq$VMb5-6s1A&7957Elbp@c5xvE8`u2FbVA-`={J;{+tCh zbAx8F4E+=2QBK72Oyhges=o-sMVkWE2bwh zkop@js*0mMD@#iw_wSaBM-4w7GwKgI;wURdvyli8Kf7UXy1aMf^=JMd3+++-AH|F4 zHYSCGoUJfKQj=c3P^Db|?MFHh;mdxYHSs9zpGV++nV9f}?yk1wV<3-MgZA$Q1$JBW zogi1kh&7=;jmAhCe?zMTP+x(-2$XZfQ0&;QY&=eXI zo*i4DC}7nB9amdJ{1U5~J(T1V}9`+6(x3%GDLG+lMU zj7w3M4MxeA&8X|w)2?50(C@E)X!h(1a2joFZ85b~jNE^6y{4uH!vgAkh=fiNGSOKu z%KDOoLeY?4zeX+kNh%471^=iE0JQQ_jh=5-bf~qNE`k0scEGdSPtWGU!o#)MNM=HL zywLL>^-&Iw?~Tw8GUX&^>F8>iA8BSjL!-xN`qZL(tb>z&?>aqUU3uZE9IbXo(nL4e zTz7D!L?|oY&_?v6X+4Oh&|Zn>1G|DI?r%HDn;}wyF~e5<2{GZzW+*m>y6>0`WTRtc zcZn}NeN+K#wzf98Y)$CI?KN&!d9szzI05i{=$17$G0}5rqfywqe#*WQh*7_QA_9_v z+pr21K%T*LY)BQOK{P(dScuvbYprh7mQ z`#fQ_QK6b9OAgEXJjke2_pPsN?8nw*{W?Cz4R}5_x={FyBYVl9ZkN*PrLLE?x8J~5 zJxZj9xmR`Xz>M}vOewDEvhn|))VbB|U&_`h{Us^i60+{6>5hIMSY!xT95Qe&>NYAa zPexNS>lF^k+ibapYsU#iRM_)ct1NeKyF9ect1K4H{m@z_s{6jOoS8(oi0?^e<;ZwN zrn6CMe&%>C8bYUeOzIP>RoQVy^& zR5IRDiun3Z$>RIGqxggvHcfSE1imIqF7rDHyw+CX1OYe8VA=1FxZiPUtZ;0pWW7Sy z(Cm)1R?BuqgnT_Lh%0BW$X=mY7%{pOyEyS##ZKO+l?NFNVO;8nS$=c+tHku=+l5J8 z1tVrfH5m`$rIE;@(y6$#)O72iG-oZpqTKxaQ1tN>eri=jAF?}tew;3`d zI2a>EYwid43R4C&QAzdI<1xnOI~EzZs)N3-1y!Yy%-|Nouq zzcCXYzd*rq-FooPPR04u^(kWyt(WPugQNxzDIUd_6f|j%s-lKg-+S!d^?hip783C& z{(Zr_2l=H9!y?@ZC{)d#x@?M?!AUKTla=h9w`5)WEfd$j%dOanPI4E#&er9G4EGJn z*|8BJw`c*eK{Ek1mG7Nyss>a^H3DA`1QeBZ?}woR46VLYR&+09@AnugM@K~CI^_sQ z$}PLxq{QE6E@i&i`6lBR?h#M&;6R%B?H9N|!oFDco7k+1Zc1y~?zFXp{rV*suu^MS zW@lvIG_p=S8at$)$=(^AnwoX=K5lZoO+P`PSHPA@_rrNa%7Li(;@**LPiTPUL`8Jv zK`qu^)jSyCN#2QQ7V?%fcMKJ2X*DEYGsI zm~GuT_fcD1Vv|CQG&2OdHrp|c_FB}mM)Vpk&5TR>zO?e#7rQ^cF_j~8SNw4(%{7S# zHImzv=RLINEp!M74}zIIDkE|8o?$yKeqnj2uR;k6_2A5eja&6ti1N0|G{{L%o1N7Z za_PDGy$g;*aiRvK3Go(qyZ#MD)gwBSNsloxQ;-S7&Y2%A{SY1aib; zA$)0o9#vRqpY{9PkMSR0&BI={VkxtWt%NNKSi*M3&1jYP{qr&Eh*j83vOm;kl*n`etjg6MEIuqbQM)XvIxgiFJGAb;6x0 zA2d_A+yR|~!aHRJB>@8FySB=~nQbGl3{!F_=HuD81_ee(n4rc!#b@@~Em2YO|=9Q)FVEk6mO9nhKK+_(}eWLe>`cSV2hBPZ~Cu?Gzq{ zh$~x0R1}NW_GFtFYsbH3uwgebEK}xhoTwPuD8GuMRAUj!9E@gT&397u)6)tsU?^ac z861CDsWVg~?yW%Kpwi2JKM8eHXYn2_eMZ4WQr(BJLhK4=Uz-_Uwwu<_vvFZ_IdF(V zqb2&>M&287Pf7-ATHzo0LWOGEaJk}Ky{(aDTxP+zvXYUsj&Vb4N7L6SVIMtf?NG_a z9JYn|X@#F3n0_zwjE`$->kNDuk%`t%NHO>*NP@K^s2iuhIX}xJK#cBuZ}B7-VW}OUzXIIRu5xdx}4(tUQ>D84QC&qDzUQqWx0D$a>oPNYdBY zXq(YD%hvB-Fx8_{@q~R`l+ELMXBd!M#P5g(V}^$G9P(`*+uIvf_6?|xS%e;}`g7i6 z=I&E_RaeN7T)MY95zWucpH^pwpIe)o+ic3oUOeKF<~`u>XQbyH3$xp|{9nD?eH^xW zmf7`z_nZ{16O>LP+JYj|Xg##ttevclk{v!OBR*Z$>g`gBU|o6aO1H8SPE4nso|$b^BgM3ugNxUlcgnUyil#RwcZITf+|*=2NL`b0 zp|YTCvBf04X!yImips_}U)oXh_x@EQ5KJ;8A-1I<5K9w;y^b2f6fEL`8?IQ$Sd?oYFV(K`Z3(m9` z4%CrEnQzHO&Obv$rcvvJ{tORaQRFc4PD(rWYn0?(Loslxj&*%*eHfUZk@x1?$a_A$ zl9)@s2gwr}kRoDJ(`KCPl@wEpDs{0 z(W@J}omEP5{UK$2#MkG~qm$g@#5iv(*A`Bkd)lF4BLqozTuOSEn^dqD#K2zgK%uj* zYG``K_4wsw3SQQ|qdMb2$=a&AI#^4(}iSGRyqL z+dX7}kMrgrliN*7{h(d$G$9hFc%*Gq>wdPOg<^VCBT__B2E}2Xq&L2{zDr1Wpr2w_ z!xW=rS~gF{m6pwbjAIZ}Ty^r;BZ|Ug?+Xt zh00Rt;AYoL%EF^_kw~>KYD#&-fYeOv5l^q38}GNk3VTSsay2qyGd+XW-&6O<^u92> zEyu+lN$2Y#qNShl^^p)SbfOrZZ;+Itr-t(i?#Q7~PI@{%BMBbwRP zZtDl%T5GA`$$TRqLmkherbYgBOX=$t_OY<4T;i<&HTgIlu0pSsqI)Te@f{zB9-46Y zrSmWsF)egAsz+(wOW0bQPU?EZUZRgZmG=+`%O6sn`C$DBn_u4j5{!;ND!b&_=w*7x zBw<{JiCsu(#rj?4u;_S=&#@m8sfpi%PnGqD!L)i(Bo~t6Ci({IC=x3r;%#dCg#7l` zeKCx7ss&?NkMXPp*%glmjVnw0X83bh^Uw;}H}cfB(@{UUG6oGR#;0VRHs4Niq^ixW zI}%$9VxPyW)A|1-#C<+~O-9IYL%m`%rv7q>6DmyRp#)xEYBi(*VwtFN)QJ%pz2IZ{ z`1m{I750;-kD=-6g8%7~Kc>sL{X`WWRT^HA-#+)_iK^ntN@$e`P8SLNg(^d|<=c@~SgNUL<_i=w#Z&(>{_ztC-k=?Gh_-9xvUIWT zvuS6)bWKN^Fz9tr{y8jf_+HJ*PIFmSP)M z^sXkvvYrjT!eq5;3`bt2I zt~2f#{P^(s-Jk@??#>Q7$^?t(m! zG)=y(+B`*`bYSlqf=%+q**r(U?PmlEg1Nop~A(5o ze631P)uv!<9D7|(=J{1=DcvlR;p}}0JG|@J7i~NAW1SBP7BJ6QM^ou^J%*6KXqt?c zm&#EdkGU1!=xsqu*4wFyv00(k-DrVO`&XG*L9y+FjLz*a9-3X+S=1zWB_hLuP7>We z2@^VHn_hJ*BCD@q`|#|RKi&_zi|4R-41&Z@5RUIb8alDMW9;0?jJl_#RqD2?1DszJ zAT+^ZMDlVH!$MB=NYgK{x3<;;jW#IWfZz%KNnc1xfWjQwlA41T0!#y!=_UpSoZ$U| z`i)0e*d0WGAXkKDrQitA$RF+p8v_{7_JN2D4$EDTl*h-%Z>0eQ0MawW145&QS~@!J z(2*@2YzP?d-d=;paBlkPoP+<70kk)Tvo)a3VJ<*g3OZa%p8U~z+3Wl&38)Y#__awmS>Rvw*q+=^iEIXJ%Hw#Q@Z z6sVOD^`6;yb6*Gt$6frrUByaG&~UOnD=AGB3qR}4JF8CjLzPyqCtj?6SYFhr zGxPInwjR-t>x2B^kuL|~N_3wqzl<+de31H_||*3F1h*abqt4KF~srP#1o6sFFUW zlYl0`Q6i?rJfnYUu1tXTDzjq7T^`}cNNUPZ*QbwNMSGCMkRqHQ7?JC$6tGy>%8AOc;1h6iLV^Y=503iqOhH!R zzu!y;6RW6py=HN7k>UnVcSi>wWjM?XHL3pR)c0?gysbLGVv7=z$D*kq%>= z1?wLpeE=5*~W{ zW_=-#+1AZ!C-nNKI#S+M!etpPxjoQ>??mdAl50F-)2pO!{G(#*sel2SH`GVxb;rH6r)zu*M*UleCl|BBx1uN?jc;?giOg}@e zRjq!}Jn~lC+d?Y)DpUA2=sFP|8tMb7Xmy`T5Diy@BL*-L*9#l*3Di(6s8LEa0+7aK z1c#F|iye4-Qr==j13M1l`9Gd3$+~Ft%F#@ye2XcG(my^-f^0zF!>6@-aAce4S;0+= z3GU`^k|RKFgDdc9z>fFH(^N>WOYS6r--6UZ1$tsw6k&E?@uP(Cbr2MOqr$g z7}HPDcEb-YCM5#&1sg)Hx$~$^ELu+4XV1}Aum0mVNjbpeabJEC{l)y*qE71?JQTA}YPCdQ(rn?Tk{mv*!5$|%MJg89Y2FOr4K>p51AEUg+~4 z9>VHt0!P7{UK`{;&k9D@1Y+lnLpYgOS$~5E5DctUuuy^-gNka}7eX$K z?f(C5f~maERaCdth4ChV{SkU}154*;`Ka*`j3<0L$vP;DKz|1?MOdIDvB-s>+U3U% z6Kg0e(|ls#;q7w2A$pnr)Qd|fEl@3y`vQq!TAipcE^^$E-`KukuchRnuIWo-;=36L zpaNe1t-hQ7$KX!lF|OMO`wo2umB|JfV_3N3$a%#j8ZlKu<_A_lnULn;I7z zrqd3NpWUSWkD1GkP!9OlOT23R+0W~KC*p*Ms2nqRjUWWn`rv-VlIH67obldEMu>_M z5)dGK08_f~R>h~Yh2=ApS>t+u^}3%d*atpMR3JBR;1Lw8ZkT)rYXqiFd%5Zho0}yi zB)+fgG{IVOnY2F_s2&K9|21xHaXNK+Je3tG;of_#ChX%x&|skTiycr}X_AdF%#~wO zaT4#G+cSF;x(zdy=$-cuKYUMxmSFwxn1sFhgO3AASTm-b_N#wS`}yYn0VA$Gm|5-a z>iV&=atO0#k}%&4o)Pvi01Feg6ToyruhnW0l%5zH3)Jsb!Ur}sh598zFy!hq7j6j? zAxXR@9Z<QtbrCk({&-{083Z6yio6|#D0`bW2S{k+=;!}4VVF4r!_M#?PY-4I zA)KT5D|aD;a6rN2-$;Uv>Xhl}==4$oF#(5&{+`k9ln?q9-+RsrZ`5=>mHW;R zAN>3iSs>|40>Y)(+p7#%fW5lWn}{~F^Ic(>>p3q zjI>kRxC$^ux>FGn&+vQ)$BxPOL6JG7RdG)${;dVT;Ftc-F;?P=*%`I{{rejX-&+gh zVa|3SH!GS6!Ciz+iIUG;0V1xTRhfWT_I*hjNvK~oH(7#bI*_KbX-u;`ugDHvJxOkN z%9xMwsQzGaDua&*AJPGeN_s5je7vnI2;K{O=gS)}rFp9eo1P%TbFj(mxl$8~1Bd-T z`}9#3oRN?$1@>Zj4|4#BSXf#@t?S@UJ$+npT-I>Z4MY9FnEfg5F z@qo+PckpOmTw03!;o(;i@qd_XlmE}}M#jU(>XjAN*!h~d$#&}3HF?@f- zrKKsM=b@3JVjmo%9((IEFnIS)w-|Qh`N2ETQN!WRazCvB!r35m9=3gp(iL6Uu)rU0 z9TGHX;3y3RM<3w#?)c&c5!W~`J_e0#LT}xz>_mvYDYE=8P z+4NM*#N?*l%?8^`vn5z!fn4Jgz+UAyHF<+=6gt)SP(=lTxW2>92p@P;^15dWbew(W zeCPz)LrhcS!0}kNhtKb34eEMsw1Wi`S%(X96V-XtExyeayP5IPnwP>MG3+^Xm}j2( zN@tJ-k^M77E;IRe>Xj79)c-$@Ufm?Q0mH!0y9{}BJ$|ji8i3Dxi|}Io{7d;izrT5a zeSn~lQ0SbAiHZ2XtZx_`T9KUD+~O{3ViB{MwMx%&j|@@ zW-qMigAUE@{5=~R&MR~@gNJ8*`Lx~L-EC}EAw3J6VbWoS_z+r*2AGe9w?1sOfJw@! zSqd|Dq3uLhuW}Fdz&PsHu`v;s-@4%BqLL^3`wxcFtmPXRAA{jWe&)?Q6JujxJJ}3r zEaM%sHomTZ-2wfcsBg;E4H2y{27^p|jlEdmbG@|_$2{9hXMBGwIEkKHCA8;N*U}mr zA9shgv>$dv*cZ>?(=@D>_j-eO6!Bm>xad9Pt_5?X?~fimdj9bmW(v)nC%646UMT?Y z=+;KX2c}+Ik*;a?R97NheK|8V{?^5y*TSlOWH@jGk`O=Sw7IcJ9y^xWkiG51FeLfB zvIEG^U08$AtAfkGor9-{(*3ZY6l(C@0M8S~dku;*#zFUv*b*Q?C_+ErKdm|bALAOW zpIT`US>9|FEe#E!As3AG^oDyIEN^0}9!un4D;tM!&9*@E^mdk^t$K z2Kdk4fF!@3TYLQBC_N#e0Hq!LdkbsF9Bt0az&mZVhLQHO$!Pu0?u3xJHw4J2k`uS}5aOlVV|v_s3HRz=S9Fs-96DVudl%@t zlb*Zo5zo=i)smfS-z&YF@bkYMfUa)rKS)b>v0hH-J$vPzDM=6aMXWQKs;8x%De&1C z6!;70yBTefKA)fwRA&XzG{J$y}Gr3p-*@*)FkGjRQ6;k=T z|6jUAO3~2&hi-8lEX&q56jgQR)-}cze34XA6j*x2vvUenVYo%@+AI50WFb_D7DWx4gEPb z8T>VRk(Ix(c_cjh-nl8uc~qA?r6`D4r%C!UQK(^z9Q! zTNywC=ARexj6_d;@GsBZAz+RzQ@zeUbRS;3+hpGu+m?HAo& zI8T$ZU&h78e&US(`@sYFuan`m`d*1&vVg5jkp|`Ef@4*WR3CzVx$z`0q6svMD>iYF~-tO>X#%?GsH|L4v5R^=mYKCh$7w=FcR}0tw^1}?U=#WGuw>UmCM(a zdx`m993u88fc4$)k;lL=7b5DQva@^xY|u-xPU}hg;p#p_dooJ zwTk*?dZ}DKf$K6UX?$$#7n8T{nwp6U%%NdnHs9Vkdr@PeE9>s(PqkK2&mL(qDQQIB zx?9?sqG;NU{qpARK=i`Bv1}bO!AWkHy9EZM+Vs&_{!&Pb1Y>+4wWwkRwiblc4J=s$ zf~?C`(m7TR>6w_%S^(#SEVNN5Ee=F+|G9R%b~ZSO9aZpqZhJv;Jev19KDoJS3b#1V z!=2{_-yGR5qSpB6_Fm0n@35pY?Gw6Te(NZB+w3GS+#~M=1_#$Xo=~TcCLtyLdiWl_ z6$ALK!i%xVxu*3b@cywC{S#jC-C;5V??NH^|2y*RamF=Ks_gBHFE3@ceI?j^FG!dy zpBv+5lVr{kM~ef%Qxi-A)#-BKNPAs9i(Uzwyc@1M11|_LkrUIMz4nUnk@uzOm3=eQ zl7z{**M7#RkcPZEt#Htk&74j=pQlhN$j$VURo&~?rLSM}u(NM6_rLh|oFB_Z?AqU_ ztFzSfFNFV`nJiJS54+P#)Tvn_yn=AU&$VmqJDdv4-}&BDYCi`3n)ERjvOXlweUI@a z02#vv9N_FA&-fBlsk5z>mHZ(xFQcNAod;G|Z9-(qfg?f4z)4t!Uc`P@X80S(ikYMD zLKiKv(F1M|rlzLIO*glF&>M;yw)g_G3wdTnUveLSMmOAb08kQOOQ1%-!Oor!J~IGy zs#gW;sjGhlFEPNNbB7LY(t;xvH)PK8(bH!_Xx7CmTn(Q44%uGd4e|+MS9J}PmG>fj zj&5bE0C;BG6-5W0!1!mbpzaB;7?$iH2Lf4$m}4I^xdKsTe>{eo=hgr;Up&Y zbN*7EtZ{Pf;pRX1V_Av*UMo69>=mLC(F7(XJ2tKydae&DPwwbWm|lM+osnB{PejOO z6sp$6mDP1{!oqBU=hk&by9slc8T zEEicO9D$Ltw6p{>w^RXZb%<_5t>pK&mNdK)&^{d;MB>ze0gRv!u-e~TfK*-qfhxE< z5Z?zTEO949Alw!+?TP|n=UM;v53*!Y1F8&Q1OU_Vl$Zk65mso&AE)|n_!4{5&}b?$ zf1dA-fnZw5>vaeFC~XmKSYVeEMZ*>8xJntVabt{hLIU^4ZuW{M_Pn+HO3U!~Hdj=b z%a;nGo>u1d5Kk_+$j)5a>9yW;^~v!DrF1JfwtXmSJC2eQ{olFR*{$G1ffuATc*9iP zU}R)O%}xOCK%G%ty(}$%!goJxwS$Q-)}juf%r&5P-<@=f>|Jm_{8a;fuGO%TBIb~3 zz+gJzK|J7M1D6YFfyiJ~VYxBa`DC(|5CKnHxL${g$xkGs(9K%k;ide-z;mTSBP(o&Z; z_UR_>t7ngjlL;*8FY)}delFe7)Fh)MI+H0C3qYoDCRQ_LX}wROCNARq>DG6~zSJAL z@O^++pS0qQ$|qCa5ZVXbNLveO1sMAQY6mQ_Qp##ID0X4(o@s$ACl4O)a8HFrVB7># zcrdYX1Ya|%cYsD;)o=221AwYljXwI#+qV!kZGv?Hu@RgA+!|#Dz_wdmoIU6Bc?7-; z6Kfu>r+e#0)r*i%4zC5A2Bt51pMg~@D9A>n;$6q!BGd}CioM9oD$r?{RVlF zTCgssD4dRszs!|=r1CwZJ>N}lKtjf@j0c!)DIEpKSa|2+=dT>y*&%HmR z4?gynCCz>gWfO%ka&zNfJpnv3A|%8TP&M#{zJ)IiF>YgNK%^6n&_b0A7Dj8s1y=^P z(BJ??#ht@rnl>ne0Znp3jFP4F{1%h5zMP)Og-wf_o_|E(L`@dIM+*dqQNa8<_ zun!M^*oYHGV$e4Q2;+-hxD<^`X&!Al4D|E}5@~mOatxuHfL&VXKwcjlEtFxJ7%gzu zmHY$10i>WI&KM|-fdIx}YR&WetxDc#5^xN_bb>KHgdBkPoeUT~nqIGVUY~xCl)9|x zBf>CaVPupcd>Id+0bUC}$teUf{AFfgdE3w(d0NV#4At7qs289mBG~kz^&!4yK z5mtcB8r+d!Lq&w3ux(D7J39f60=RyG&9!aK4e)p#&p;1G;Cr>IZC-(4E}w-GTm{t9 z5O$xLY+?J^Ho%*U)K`Eu7lS(&485BHvqkX~gQO)n`e@Xb+My1$u1mb8HVoG)D=Vwr zLRDWsEg=Eo{IGG!TGT~T`@yU>jJ^-{%a&)D@D-Zs0674{3Q)gT=>FVr1ta?~6Q3vr z=9SShhEUXsuIkYsYS}ZJOS<*t;r(ym;`}cuHso`FhA1&D?W6@0-;fg@ZvKwWPRtg- zdVtA*ua?<65I!_!3vfL+2*6at$h2X%l}l}V7E?f!_Oq*NDtY{3VpP2s4RI87!*JOT zUXAv^C`=Got^Zdc-D*chO6&jPSqvvBu%(*ME>B8|i8Z_dvNvfs8+@{t;iEtzE`~2l zTH<6yjyr6RfZ0xEWzwUY9@wV|=Fb5qju$)!7=(qZ>mF+M1QPQfI|s02f$v4`%F6?m z0Q(!Yq_-Gl)N|CE=;-LEJ@iV&fdPD6)T0b?$KmNvt32?agezCt)ekHYn2!Ac$8xcq zFAsfAWWYU(7bbqdL8{@;xb-k;+LPh@VR-32^DQvCr*dx{ z4B$ZbfI6`v;OTzeK=L-P-Rauv2?0qk+3jDm%6 zZGOkje1m-dQ|lg%+UN?aV%7I#WG-K*AF#tgX0N(IBaN2z&XrqpyW>6cVjrRE(FpG2*ee= z0;BZilbwIJUyP@57EjHs4YAU^$CY%Ja}rYq<2_ z`31Qo;L@zAuP@=cZm90R3jEsIL=AUDTZ7UvR?|1dwVQEkICReEC+?_6#KcXT?iUsA zAy2Oxoj(=*ar0%l_W6w8_gi&KwFPkgaTR_HVsA)M9k0 zytI@j{tgsoZEmK&#&6GDKiWvEfCE>##?2J*rQ^Z%FiH$-Zy!AX)WAN47DqTBpwG>~ zB7p?Gqh^C=dDBp)oRtLp?*IZqN`VOlKjkSnmz8;wN}x2ET{;;!J;F!8au;8dEOa00 zoqFe$j&d+zhu?%FT@q=TvD1a4st^3_z82;=8G>1JNt(Q?t1DD{K)yl=q-8I~zX#tWEVOC3kQ+*<2iPgawZ8U z7micgZag|q_eR}NKG+K~L`gc^O{%0XhTPvq_ z<=uu>C^f-?zU{#WD6LTIeQ3Ag0K6wJU*J>+{)@2W#%$ie@%jOxW=`=<0!JV&{sivr zOJqDqmPsxQ&cP)bfKAB2GY<_90V?x?tqOY_9BPnsK-&DgbMD!TcP4vVaPz3SwD9~W zqCyXQQXBHIwph(VV&WdnP9mgK8mll$66Op3-Bw2r(-Kc@U?TNvofBSynOHHsni$vB zD+*^4VSEjAp6fvEicm#BF;g-4oGett`$(8MHUrMzGrrnI#oP3-+Z}`1?^!9ss&3$C z)8pg+fcWtnAmxa%y1F17kJUaf$%jTN?5wyrb~XS{2wRUB&n;c+gMBPC>T;VG~sb?@y)~UA16MXRnW(Og#{3Foz^ZewvlD3?mz?*W zDiAeT0?}QW>{b;f6{l{Bn=4I zt1qWccogCwuYa^H2i8+3Joy<)|8!Wrh3}bn~titxR>hx!WH~1WH<$? zJb``2Y;kfT5hjFX*ko5sK(tlw^s^jJe;{pu8c9@peigVP8JRZVJl}7&1J_&&`3VsE zf=j`lI}{p5ed7-tDw>uwMf!~gz(PL)5e;+{*q11_p~9vCL*K`JU0sQy&dX1lznR{5 z14+)5>s&afyg;#AzWf!K4ls58h7OHF1_Klj?HEmHN)EITf)wF4eZXfvDH*8;5;Mu6 z5FC=B6ou{Br%V7G@6BQBVQ>FtbshGA;MNVu;3^jYcDx<91#nKLL-xRpUTecUHY&;v zHhL(*=2|&4icz~w_(nRASGrt2AOeEwvR$qeqB2&YEuaBGRS@%&fA0HIx){y3F^aQc zy|ad|XmJWN0zO?)ctc?t<~e<|YrcIJVHJz6-#k@MTGJFa@h#kGAul**SF|#Zlh2gm z)LW!N?qBvFvp1-pDB z_zG{JY6yNo!FVPMj25W#FbrW6gQBKjn;te2tNN!8w2S`0a)5)QhKVTTy&=?r+#rjE zl`|HWGO`QW6m$pY;<5#6ai~;|;IZHn`3VXM@Kc52*b92fxVLjDuops^X5N>y18L{Z zKZn|F1k=G+8D7n%5cSIhk7#KBen8fj6v20>L?KWHD7D$II%0pD+d_Jl`02Lu99kr} zlAlWJ+S+(^BkM-##Ch_i)Wf@OVB`I0m`T1Eh){ER)o=Q^{PEga7!>l>zN>psvZJbO zahHlPoHwt!r#MS-rk!I|-9qT$e3^@2dNUEH?#`bQ;izCaA`TqHP$xf-pOL5?ET=gE}$7?xu4q9=(Akg!zYf3ka(V+Ho8es zPHb*(WX}3=Xk@M_q_}#lPaNG((Fn~xR5zQ7PIR(JzKZv_=Y|&-8CPJb((duVC|&Bf z`j+(H?z}HrhMo`$LmsapI&SYQEg7z{Mjf2o9^xxxSAxwcB4A(|P6o7@ilbKtoiXf{ zX!KG7w*gm7ccu2Vpm+IA(qNYE^808&p8MJ)Tx_@zi&fcCFk*Y#36}zojK>ffEl|-O zKxGAM4;}*6(&dmGqH{!F3A-(H$?1|lP0MdV>T$+I7Whhnk}0r<4nR}u-x8+ zm4~`rL$eBtO#?E59}ODAjt#rJ4wO|8!u1#^GrITL1tmW*LO<@`x zEmj~!O5SZkGZuI;!PvOc=V#%ht;_KExe@2}qCAd3a!&t`o8#7Zu4?XW{@}9v*?ZcG zj16$)BxPM`iXJ^SY?o$@%=xeoV;%2Rax{@U$i6W?L`=CUasE&Gp{s?#_lT<7<8_fP zi!YQ4^`9~dkFIY&|Dm36zr?`XHfTJlgX>WQ@|2nH^<4GST7@8Bi_u4K}0S-zaZEHF}W8vgv z{gIl3bGw4VG%)al@+&PwrUbm}p@v)A?-Hd0(z3Esp6o$&?L!mp^s#t6ok`=YMzQXB zZ2$K5c8Ezpi@}xUcSNwsIX?zj9T?s}hT9j`97I|OyM$FGBEEq*ZK+I9>wu^pv4duK zrTI1(6=Tqnah^r;_>b;OWYaxW8IEbG>18>+g2unO4cPNxKh0ZXIOEIl;qo*+M~-=5 zjb;1UMh(9>b$N!hM(%f)kxHu(hIiYp_G~06j_wTS6jr}nKx(@%b~pAt21s%1h>0+kR>WJ$=UoC*uuo z(iRqfJt9RTbJ?fL}ek- zH(cv6mF>H%{v6L{4UJAFbefy0^A*Ogmy_+X$$a1MK7=)*zniA+!T0Qo|7r+cxe^T`?4lE_0tEJd+`EAR-QI0`ydT1%;b z+WRt4dp^sgw#A<6>l!{bN6z_St{&QgAkOl`TUj1UoTq=VaBH)?@w3&ose3S|eu=Z> z$~bRur%SFAJ4HU66s8zf`7S$d`{^UyZq-5SGBHvk{LHeqno1Xs1hWzj&TCDal{Rjz z&neM$b=UD3A@3`NAU7i*aVB{i+ATPE`M*Z7l%w2_6}9@0&QD|=T|5Q~RGh7<*1EZ& z^vBS!44e6k?^s8biCzCl-6~cdmFBabt#2i@h!n zS=&qur)Wo};mpj8uxmg#FB^dA!Oo7na1TWt_-%ptxnQVGz8sZINEy$^=8p4R8*HP> zLE9~?{$b}m>z!t65UNg$D`Wc+&%hb^H=-=mdZWbu;qky{pC|Q>!H&NiJT@*rA|I>v zNcTu5|9ZLg!HarPwm&qkUO)FYe4c20tC+w`8Ev+kYZ^(ofP7LJd%T@h#XoF1G0}OS zb3E3<%gj+288KNu#^1fryitKJ4e6wF8%2_;A4db@x_BaST}*Cq+j~(vMWTh`PN-Qx zh;?{~M@XqB%k#~y(r@$9Vz!E#P%H^RGR%Vq(Xh6Yo6EtHdx-%`1ce_KWw=E_PsQMA zap=N()5QDr8{h36U(o`BubF783$7Za(xq~U4LFBDO&__tTlj~EIdq1VC@jIAN<&*) z8{mP$>D|N77cU->%EOZ=j-p{n^z>-_M7|nFh|C9j-E3{F#D_t3qod&gbtZ77VUC9C zf7w7%n-}g>isvuKIF@;M9pSZH2jlTh6Liy21W@@e7YV-Oxm_d|@$t_gM-o%LbikQ*W2f!=bJvJf#Jj<5m|DLwfzEFYXcL@GW zWVksFKIfYfrN3|RE}yDC#>3W|Bu7LpL32ft-W&*`K9~-l%`)E(o03W~q=-hgO;Z^6 zik&v)QOLKubOZm}*v(i2U#eMBTgxtaVw!AsDS`{i4v#NmjJxP-69+ZQkTIJ)zFHkw z_=BvMv%vqt@lEo7sMdfl?*MqfeKw;f;eF098SyoXFFUcDY;M9!{AZ_Rl(eSOs(5ZD z%9~9wVtB|}tU*Ap>K}$)^8o%c=pM##Ev)7w@dozg&kpw(iKwpmUF6Iu{5P+5F~_-M z0d_d($oW*u&%Z9q0KRvJ(n$1a7e42gCpZ83?2fHgZ>PhXgf|13_U)OHzrgavW!cJP zL@7l@9iXzS{R=k{)%k}e);O6bjP}|6%0kiq@h-}+$#shPZ(osT<+yfjK^QM|ckX@< zN|6lB8&M^6cAp-KFtC2bcc7ERJQ`dKyh|_)W-PasA^CZ}HaM4@PH`yPV5I~kbW&ToHNyl*R(5J%q9bl6#%}7DZE8Pd+~qR zYFwjp!pSW(8u4*)A@yzcOdPW6miZp=`QO|#E}}CJ26`PLSt91_$l2u_jeDO>#BfryeIc4U!V)p2U=U7F#lQFy|U>!uPC;0 z@S!#P!Gm8`$7aci1bUvE7N6RmoJs2DF6&M)H<66)@IErWw5&_<j)cJ-j zjYUbqT}HCAtscj)%vXslvOCu~q_nii3l#q);}AApzc?Y0Qi5Gme!+~kN5Ev|)_-48 z6B8C*`XHA-HfKC=)1T#j=kZqaeNoqlzQ)@Z0ug}reVw-0;8x%=88e-Y=YNxA{;xet zdYO>&n&0krVdaHlqYAazqGnngn^V!fGw7oK!mxUQC^EIpEM*FtJ^xba&aBAmTkeKH zlK&$fu{1^{7#p5Ckls#8!BOJ-4}@iCKqT#i0h&}-U}Dk$+621Q=Vu7e^C-kj1No1X zzrn}*suj?dqM>sqL%acZp|#&#o8pe?hW=~=+CQZ< zvHklJ_KP32peILsi}mW685vO!I_^bhTtWi3cI6M~0@d?Wt9&Nmwn|jXXYt+H%g7YP zpwtR^OmD7f(%7%eqV@3KpWW&z9-Wa|2brJ)R;z_DDx(p$)SxDzJ1J;7+Ux}h_R;<^ z5FZv5D2F5Hy!<8qygjhO+7JU)L^FNu70dxZAB;v>p~)QpbNQTv02(|6d_^gs4}cVT zLFXG+4Yv#2R9$l$UzXnkb4*MZC#UsN05RO^9G42P=f!<7W19i#3qb;Kk`_u`yL0=t zv82)60d!x5rF-G**+5sHQM=z71$rG>?K+;EA|La2OnMSsh0kLTma>y`3}0R5032)& z-puauuzZm^fWK>K#{wWa1}z`o7R-p6rsiO~XRDGDt@s1`Kwph}SP z$4&)QAA&}KqgQ7o0YdK)h#~fN0N%+Qwt_KYS7`iE7!s!NP~kB=Q;xzbG|~)S2xjiQ zpi6rXpwA#M=rBV9v)6=(zWYxmu`p3+iJU<*DFG-OkVjC!>%a_06x}Vv5F#@`l8z|< z6n+Jq;CK5@Y80;ofC1ngPhji-nW?cJQOX)b1C@a5JcE2p5vf=Xe0i4<5>s;z`G98$ z3R2VzNxcUf7G>Yih0)+PhvHj$fxg%O+5O;HC0qJX@3~5pAeRm2K2T7?vnpaH;t^Mk zw)DQfp8;OQ5& zR<;9n6SY5rYti4;RSV4_{?4s~& z@Ld7oxDL%PM_dm|^FvGuwlA>Is*TDbA|hn&4A5JI2)Jo_rC(kResPyvo~qT$j(CE_ z>A#gzNJ}Aa!&+zQm4ZHepOj_*Zc#mrS>VYt%yWO1hgX2zZgAg`i=+{E68(mb6T_$u zK&3E*`uNjpDY@)TApX3dgBx>=hgpE1I|q2wqKSRx2pRvQPe2Y*5feMYw`X;SIqk;M zSzkc^oPLc1{E|I5IEW~#sQBsVae?y~1W0poaLft+hWq{}zyJ`Fxw5!jz|PIxY&RpF zz@_JXyrThj(Q~NrSN2jGpacM zW`#DAs%>37!xRY{bX>uIYh|dSs);n70w4L7?emlaj?g|)@hS+V7qyBt?kxCyem6XG z79m*W$Wi3IR;^##EmVK6Z=OGy`-%Pm{EFFr^A-JdO_dyld)j8)c^e`pdZ9UqZ_R$c zZ^kL{Dj2@!OnLWPv|KhPSCG)IO#sfJT#MWu2ty__`Y%MOxo3g)0EU28Pz(;Bh!TAl zbVWnl)FEJwu#ldr6V?Gdfv%JRVDY=3c~CpbimjSM*VYC@_?!`uhL$bp5$O-W!(d894_nf z?%|zqis8)L7b81C1270|ArX>K!{RX;$Dskpa&&TXJzQuY;?V3%i~bZy-@6!eX6%)E zqcYrfd$8!1k7R)9$Y}XZ&-rm+*+IH}K5q608D6F7&N=BcsSYcqFN!|e*=F%K&=l^F ztu7uH+^sHY_Y>He+s=cX(||R9O0T7(?$A%2;CVeU^@{elO4L~o&*X&2EAg(gOE5lB zjWKsfn&*zTCVr@L)R2UU%-E$db!LyWSuv~}mUi_4j9^-40$u;?WEt=Q@EWiC*DN`% z-D;$et~u2;;)cF?qxAj2gj#f#Sd}0Ek2h zm_7nHDL5Z7b8xJ{Cr*PG0Ral=p+TNbKuY=tV&QCnHihA&h=F6UwsQxa{5z+gn~;(Q z%U)bU!W&Rm(5j#U5sYbgGlfnmt0C}x{(@J6V+R-uAprbQasaa2;Li5}(7Zwa32?oz zk)r93z(#1iQ-)L{*au?o$l_R5j~d>iQtVdgu#>j<>OT7>em0<7*@fZWt%GH#OqLU- zD@Bejcsck@HjG+1Vr~1+Lx$EzrT$8`xtGpqlVSS{<8)6mh%iDX;G^{R#ygfhu2`e_K+w$e|{!>n+3fCRxm`U@pI!uQ+30|gqS1)1Y zn8l4{DSC6TmD&W2T|&OLKTNSFmuJbf-AfAif-QLY3KE-;VDihTO|-S_ZCtI1nA7b8 zIF4Z40<`zKCS{s-8F1xRy+CUL1BmVSO&M6*$@L+Bb`&HU*)`K{P0JgA^P#!UvjR3` zChqQ{I{P42YlO5apPe_hXl5&WQQcg`4b($YKPD}WOF{{tN=gp(20DF5w6GC#Q)$3< z{Diz73e5L+BZDFsfGZiI5Uc{nauJTPc|pYY7qfX(nXmR;e9l6;k2?>4IY>#-^{bH# zZLtJIG5>nmx`@kKiLH3wUx}^O2Jf`$5|tf7lRRv}lbz_)F!0KxU-F_IyAa33;)Awq zb4JQ}8l9(4Pp$?Luy12uVyXS5B#HQT&TRWj3wgRqmrI>*u_XHZaBevB8~410*`hF( zqOn!}y^H+~YFhQ4PDyXR+EXD|RBlhrJmut4pY}H$cmFI;Tt)b>H1izw{i!$>Slk+OU!9k zv-@#puw2^vC4&2ye3=CYM}yBP=1VUTl28TQk$Nt?TOAzTp5*l4Fo;%W2C{3ORX^+^8qVU;1DJ2j03WP3CX zqH8x1+oDjq_`eNY5_|KvMWUOfMRFB-I&&3cULAxltYL~H0RypXplZQC<2zlopt)+B zF6p~3wAsTwrfvPDCsnDwLV3ad;AWiR5B05y!y|-hU<*O62fj_u?9h91k58n}9M4~G zwvtDx0mFCh@*c1`aCQ zzut_~o7c{Ya2b89o;-DNS>||+Tg`0qZdwB79?X3q_)Pl2eG3|o!n~|Je0AWhE-DpI ziy-N})I5J;U=+!@-V1?TVfCqC*}LKEi!}1N)5l)fQn7_wR3p?dQ45lq8c^UkYSpFql;lNqoxRe1ims+Xf5WalmNXT3CE8AB6FT4cZte?6}7E%0on*N-eoM8*m zfFIb?XaPZ0i|f;{1Tm-7Umnu{NIJi*%&T#QqsR|`j8*=K!uP7YjXF1aqga|`F$1?> z_M7YBy9pZm~GU*~DO+R=Eb$wQUd%IWJC zT)j_ml4@gP39BTIN?)ZgW4K-Y+z_i-^kJ18qiVx9@Wca-j%`*Bo7B0l>so!AWG#HosI_OyhF&02&$dUT(AC5Ky3ge_c^T|#d zK@YJsP`l0@0CV}_D!0IIXwg*D2hJfHCHjyE`#d}xZNJzoq6mg?LC-%*60b~ny*1rN zGaGu`wro}QOU^^HqwU)~6rzjJu-ZQVmc>bE|ChySzGVSbe%r!NpZ%4Xk)~lbp*E{z8|N8H zJEGkbJsL8^JyHe-i+EiMOFs=*fn@#Q$zRbo z!7{tcYR%LIL7OfNUl0~n{I&6ZkNL#L((%p%#!ugv}rL2E_QFxk^k-#K6Qx zOKa%4aoWeerN~*h0Aabbv;-DCN=f`|l9E^NS3}7)TcJ~HH`5cx0sZauN1tA!5@TQh zK?H-QKLRxje6k&Myg&{XYnDla%H>Z@b2x-ZLv<(NxELm#q1o&$j{ODlWXE9fqejd- zUgU7YE1~JcphE$w6egck@&KGGA4)0wj8h-`I`agP{p|OC8oDWrX%IV(_=G~KapoqE z<^@E>axdNUf?3qD$c4wc(#FQp(uEPbH;M|bOXjih(y0cty2Vo!R4iZe;Cub4oe3&U zGJ%Ex%Rc=E*VF=#?2o%r`m-@HiKu&}>a{hWtrO&hzvzF)$}|~asI^g&EE!}yqm-Pb zf9{6RlFu{j+qKgUo~bc$E2Jbru6i-lIqLUw*lI_(^;1&UF0eXv)Cy$TYuwHyc}sXw%Sv`TdN@`w(`lpunFijMR-kkDRUa^tw9Mm%AIe zVSf5EoY>h&Sb;rm_9l_K(%JgH4GxTpuL6G?La)dV3Jk;*ynG&4TYpXh$*UPi=ujIC zWOcHRPf$>hnb{lwAcs0C1Sn%zQ{z>k%iyd4oyr*mYP&|%tsBbpfB-Bcs@oK{8TdzP z2~S}Jmr`&Q)Z0YOXOO#$FMAWX&-uTH9%!~sh(K+ixUjJB&6{~p6$0z;`y!^u=_%am zsGE=ib3JN4K_xyJ~Uuap$*B|S7ANJ(2zeWlLDvxyYDSa4R@my!1p*JJ3~X%;u)mJGGO zQYgD{I7@CWglJy5Z{K0Ynfm(O4#&`Q*2=Onc=hL@F6P`_l?%yR#tF<$*fW0OohjBX zhi6)>!`{9*uT9fZb2{EmTx+dy{~N{YHtUK+$6vPTEo`dqTw}UFg>U`ROflbBCZ0X| zs@qKGmG|9NKakwiYGRXoOv%|M^Fyk|E}APxCo6_8`5kow`*sh+;@cOE%{hr#1+;EY#rq*%$h8Eut zCym~w4x9Tc;fj|v-05ixLyXJ?RPmlQSMwY9`hFR_mO5YSP*JY;`V%uFOMbGg{q})K zUxj+bFb6Ac9{IiTuQ0cn)0dL|>togEr7hgeB<)M@x2nccR@SG_>HckO)K2%a9E#zp z5+I(hm=lb?I}{0U^k&HEN<`KiHF-~C^$p%%P2u(0ClNsQ{x&cC_j;EuS;fv|BoAso zCdUM=U~jIo0Tx$#c?88){;cjj^Vs;e7GMnM#1?2c;UsMY-8!fd)f%p! zg5uq?RRx>SH9#c%>zgIE>sRra(damUlvm#1QmCg|MKB|?= z9tU6tq!?g(WPk@&1#qJR)FTN}JQbB8Gza+PXkRXY;@s%0M>zG3ry#|KcJ~6-8R%zA z5*(pda&LQEXw)d9%-cq!BTJd#KVKt_>YAp#|TEf$i(u6T$7lGL;|+; zTe2ZYTFOVxg3!-Q*$_d6`BdJ#I`#9bmri0xiM-tXh{qj#Syf*!JjCYX=3>$<;%}}LorU%9|e}&5Ud0yz8h0nJj~h5oors!t7@bg z=Sgkwgf~<3_uj}fy0&q2Vj#7vN@}wWVW#41&WRO8`b`~E(u&RQc*00z-!fmKih}6( zrH{Nz=|!I}J}ux9vFZ1fw*Iuu|0C9~cQH3NK(Eih^7TQSfL=ti~ebpE~5P!;u zQQ7D*sM}OV_N2DH3zT>W@d*@LJXA_AO!y45yfjE0?{94%qpYa8VjhrFu%FWzEUe_cNJOAG4@B z-xTbwo;8zEFD1D3e^w<|IEc685x<;M^ZRUEo$jE?i6?bAAvSj=|8Yjk6F!S2kGKuC zpFi`?TQz?(t_~C{%I}D@kHB0X+iE;ujM1OjowvAFv4?x_9`@~)m?vfKR<`3-vQVOw zJ)_%;S_pmih@C6owi+A`uQQ3Xp3BI}0?3Tf(jIz}n``~70ZwuNOz;p-34>unMbr7U z41U}f=ly)0Kc{&g`~*9bwaK~)(6fmRXf$lLgQ8E(JsQw&Pk_oNacY&fnODFa!p6Z-V0%A_K$-$e-O)F0Q6^EjV|m+Tg)ME2`OO`s$0J<%T!){F z4g8_cF#1il7(LwM_8lZ}fCOuo&0cEQM|=T_?N3XE42==V9Z$OHEjC0^bUpBLBhRfKghro%UgohT5qls?<125YHG zW2^elKDV=UJQ7jnP~$3j?Rz)w9;A6IO&By_NxVHLyzRzCk>RMP8sj3Z6GivkKPIA^dtxgs?(29vH&75N9uQb=}0iwe@oGH5J2 zJa*I1=0*QV9=k81UxME7FoZ6c$4E;`ayOa znz@2ZLwQ5NV~8Mte8awO907#Nglss4+D|qpdRbu@lb!tlpz+MCEODAhx$HB(uw0(5 ze0>aDPi?Y($yB39&ETUWP|d}}#Belr0p{zPhJW!QI>^(IkDWO*cHWPGh6V(Fj70ZL zP3K{A-9Xno>bnAWN^WlM-rgQK-7Nvm9CMcuiv3oU0RvZ#>GneRymlZ|dBeycIRYo( zjT6dY*@1pS(+?rG;l=8B;aonLkSNg6vmY$#Ux=ZGfl~$NPX!sdY$x10I~M7y{aPvU zj*qp9Unt6baq!JEyuc*5m2lLA_{!NA4KBH*VXhw@CDi&NuWPGmGz=mK)=s^I>Nbld zwYcl*;J=U-4p*>eLj1gjoz5X|x6kVvtcsUnxsvv%d!YR^_% zPYArjH5S$~=^M^8*BfGluS_<6*)BM@P!)XLlSRZAV%lCRckTZYOhEh|t7+dhC>b!{ zCBMU(f6DRA;9HM;H3e7y&c;X@?b19FzMM(uuq7OUNf2-oncgjl#PC6odEGw6;Qzsg zPT4bad;7dka>Hcf1Uij&+X|?;q>B0Yzgao@1Wr58Yj5i5PgQaBd9$QmvLByRi$HP& zDBfWps#DU>K0LZ!*H;&jVsj3$lhZSH*yK@TbtJJqA?xIuh5?`Hc`6-qA1eXD$0K*r zzZ;WL6JtGVZ{X4Fu&271GUI~z)u-Qn5^~XR2?cw>)EiK2bF;IMJ-!3-b&Q+d-Vzt5 zT*cDhXx8xh3MQ~%Ir;$U`uK6O`Y|P!51ifTlp3%A$kE#A$r`YoK+vJmyeXjUzyPOU z`vQudLX)pk`N$pw+B-i#v&dMuIJQ}gfG8JeD~j-r_4Rc)qP;x2b=r@nU+#N3y6|W0)LPpte5Vc7ZpKRG+2kfkql4v zS1(?6K$=H1&d8Dbf(H*^Z(?}e+puutUk`QK|6x=)w24t z*-xVu)$cc2*3NfTxIKHgQYp6QMnn6WFPo)Ybl-u-H?K2Cxg6EfV{Wpyw-GHy8%bMa}i&U97CTTP~O zfM=QWPCS0P_FUMk$|t+W>eR{lov^SR11%0xZaqN%=GDVTs+(dZ6EoZRe5#(ld%9fQ zzS7x?8A0l;uVT!c9p1gk?)E21+p!ES@}a++@%B`xx~by(>;5X?t*s+iYXXmwH|@qH z`(lz)=hm%>_~JXB{#nY-S#T|Rj6*e0CX5xRGUKwS`NuluaAP!90M4_1j|mUtrwEtLB21_nx4svE>Uy&^iYc&-OL&aio)a?2PA+Ez2kosQ z)2Nq@Yb-HhPf4IW?k+84D)2XN^@2l%? z3I9yz89^0#T-ussvZEW?J-n@xJEL*6{Gy6b1FW4W>o8fpt3}n3>JtNxzHCmHjVTSU zYiJ**+bUkUQ>@&BG5J+D_|Wxa?evO(b^qy^H?OAo%dnYnlzQ`b@a`MYD*q@e(TSVG zRwBMKQS?^*76BFpXk?pr?ex&z}C?39{4?Xu|cqap=Bj3 z>Fo{5Rs%Ymz0YgTzk13Jg$a&qYYb}VD@~UUV>{-zV>Q)UYy~GST0ep&YSHcUTMJF9 z??~6>1}fi}V19u$_p5V4P}WtQ=?ntJoqeGOmC(#{qE({KTC%VDmdXOFs0dQIrQCRd zz7Ur@G@zyF8NuHn zy3$HDW~0@%oI^OK1?npNzxgzR!;ql zT?AJv*|F?F2M-I8UzX-j6Xg?W+X;;eas(+}B)aNSE5^*LU7)U@v{I{QuvhCbYnLgI zLnk06^)+2PEjp%G&$B@_%ci(6JV7eRqMWlYxqgNf=_{+d%u=X9>f5r_2P{nWs-4P0 zQ;D{lU@mCf*%FkQlRYwrh0NR?4H$BNCVcx1O6)QLy>L+6jCV#ND`>Yuo#_Np z2!8lG#bM$IN&j@c4vNOI%Bt%$&!d+NLfCi``jG#$^_35Z8)~2@FLKqjkhFaMfuE;3 zLu2KFanQSVkAP&Eq_?7C0?qBQ1u=Y?&(&QFM>={y2{6l(ack-HWzr|_gBu&$vyH;b zPxUuP{#NS>jc6y=VNI24qm>dR+eF*%;KA|2@<tvH*s4 z2@|-M;;{7^wY8%JW-`<*xb zgtky{2_bjH{hO$6Z;H|f=6@zM7AVS@wi8VGwDLCp)AYPoSl5E6a*T3SQxal8awRzE z6*R0<8^w%tm%P{sU_`dl--`?yRJJPT5d3y4uW9iZvB}XZ_|SLQq&e9$dwrYIr`f5= zN1}+kSC@>c?2c0K6U~v!PsXf=e3#01J(bCN^qL7goGp~1a_(y<8}WVsZKAmr`L#5w z#$&;#{MOdYk>Ot9VFSe);pTq|y7PCYbTB0Rr)UPLy0PFV;;#V2sV3!Jl41M*D`m5m zQk%Hx4-5IEOyjpIk=gR}mKsgJsp(nmZ)(tkRJkRwD*c4V_W#Z(QFLDDe$o@ti5&VQ zzkRs;sn$5X$115i;rC&vbVgjJ(~|RZ+tjbn6))OLky7m?&5mViScXSGfgpdr3JKsB zee8?rG*AtS@h)TYfqM*}ne)H(eMH785#?g@I z4<37@OHG@j(xIY(a>>exasA6iU(zR%E}IUqCQIp^Kd9=nX;>2a+8$z@_d-=EN_+Z2 zbSfXOA8{=2r$u)0%6AE8<(XHu*ebiVa&S~()`d}zE=H@;GQ~*UyN5nZ*4>b>D9Eh5iFdDb~7bHVqypS4|X@7ZWucAgXbz zyQDL03Iv@{JM=)P>Sa86N29k@B>a!kCF+D`@aJ~+G6lj#`P31tPi<(@*O_ENl@Cgz z%Kxv!D^ld-Q`PzF2eD-xWpNT~%6$!;4kF_dpIh7SdswjXLi85u$Hv@eDKDg^tMCTa z7m2;Z&@Aek)H22vL!}%T$KVuQq8HxYLj(z_`xsR^yF3MINsGIFt&E*QS*D0;CQHLD zd_y-O9%p?cV*<>Okm=>aHU8?oZ|RbY2RAUKwgWkjVS}zTF1smN@G?Xl`{&Gu8a?mvw96!^iiU>jRz=pmbGhx+xF#5>g`S}L!`){t`NY=lo(T?P zB5on5CZCUWk?S$$bA3!zOM=(nr`M6;B0J^^_>m~puR`K-S#&h}#%=qN!c7wA3Kxge1r1g>OJ|sls5B!>s>Kz?mu}a4mA{evX1ZY)hr{!M zT)8|~R^5*FslOx^9*@GprR&3l8a5LY&ZZn45(2eUXgfsRBaqby`nH}OOkvaUd)6_S z%l3b>72{Bi9Th}fQrVcrZx92zS22@4a&q@$1u3r$SSYev2UL&*#L-@Q zvajo~rPOen)EA&npI;~{XwIDYuavq>AhzW^YL-`8bx}n zXkob}iSzusm#HwwT&`IqO(roGU8558_|Zv-ze=<2QYJ3_hFYR;IvdUG*aFuPmlj`` zr@rA&k`M8f6C|ig2sfDB@C=>eA~7MG{Fjg2_NB`=(KfpT?PS<~JrN?*&2zm(ZV^cX zzm9W%9W+(o;o(KLB6xNA6gg5Y(XtIUZ{GZSy3QG_4yM3QX)b+~k6+DVwLEb#H62wm zoRicH_!g;M#2SR*B$~LUP%L?%ZCOo6Gp6iydV>@K?!SaUi}` z7+c@kAnoJlZ>Cq180D{J5(IK#{lZd0#1To8sl!Q}rNd9Q>NP94jMCU4<{Aa1f6T)U zT{uSZ1HD@w*sIIq%bS~;ekdWj`vBMaTi!lV`*ddij$m_J^0xvhx$6;;i{y3~%q3@B zv3;-6?<@t#$jH2qlkpye0YH#nCCzTZ=ZNP{@X3ykFA^_{F>=p)njzpl2`i>lTzh2e zcO6Eq!_h-ulKS$j%@dk25#7sXgj}vMDfPm?Ke5l@zvOcHL^kS9-0&!_I;Y+1n_pmq z+5F*V4s}VQ->|8$5i6z{CG*Jco9{!h!8Lo5X^Vb$&7UVv2gmzGHoH z6f!uQID6!lU6uU&ID9>}+O*7PbS*}I@SC`4TiZqResRNo@!-#!CKZ*>Xzw=mkB%Cbv`X>! zU%$dQNmEvJf1eVs2Dm#29NfLaGgAlbqBvN2zl@Jdddwu=4Ko5Eb(3dNd;0~{NX}Z$ zpTpp$5laHT1so4xwIRm5$JSYgJCTl``NQK%=(wVH_g6V!_O@xT9_BKC9IJ` z(cKFK>*Ogz1qPeHD)aJa-8(m*oEgLCU;4Nimlm($FB=d&xJUfR!Q#eiY0RFX=;7>u z3UUY3azdkiiD}VxEcv&{%SP98mhaEmMWIZ;)h~K1fGHJlsZBXl8zm$gkq8nwNAygM^%1j(xt=L%q$im(PBqm3$K`t%ES40%{?^nqlTN) zJ3B*q)Yho;-RX=urr{6yWz4@Z?8yEtcLc?=hylmibk!|8EMWlGsk(ofnNi@N89dJ& z@p~=tcDic%2osNIO+>Dt1UoH0zPLfJV44HYrc&@7ATB5O>NEfgyk#ydnjcz;$%aNx z=)L|Br<24-9p+FHXW|ic8gI{c73QC^kr7_S!&B^1x*?@#BgbPx)W_|S zd2F#>Z}CU$@~sihd6$I{>f>HLchBdzpU8LE6B}(TC&M|g!=X?8?_#&Y1H$4B5@fa4Dv3S} zCwbX0>@jt71ytzIPte@t`m?yplAP4G&V z%~PqW?=lwp?-#rDabR5j(eAjqgitVq~K_8)H(BS@5IO@NDJlBY| z|9X8)HahzD(Wj<_jjp!DLh3t((;rc958q3d^9^v_@i3?sQ?@Jw{r8KAdUZbB`uE$h zGK7LYn4y-sIzrQv{PTAJT!-Q{QF}3I{6FW`2VHj)-G{ppV)tU=ei9{H4@3zw)u8TX zHfBF7A$Q`3rr6k%0Rj4AngNT??arG79^yU?~V}vo^*j01`<6pIwIlq^!cxI z2c3+jpu7zp1nK6AR@Ui zGL1E~i+o;up<0-@{PolgHebut)kpg-UG~Y7_RpthO=!C%y?4x{f0XcGanVH@xgAFn z(jg(~XD|Iemw52g6BtF~UODn5h-1=Q9<)eQw`-m1Q>}Mmk=J!+U}0&?SL@y$p~9f= z%3nd;ax7R@iRWXjyN~MY9(Z$Gdpbp)pIP%hy-eMHFY39FHJv)y-m|6#u7}Agtv>4$ zd0wv<*ByCNIA2Z%utni{ew-@idRVDa=j0e?0JmXE_s?%*+TgI}e~T&_M~X7r0|uS2 z)PeqPvCGBzCr$l#q+k(fx|)R=1##`FmX`GH1g{4%at~SyYiYR?(Imly2^N9azIF7Q z0MZwWGnZPwuYiS=?nSOQB#6u;y&d1~+YI2DxoAC0wR${Fj`;m)t(1+_x?+Z%K$$B{&uOoJ)o{N@54Uto> zd%TWS8~|b0$02rnE~l&O!KzDIn=iQEeWFE=AU1x--5pW)DWei6{Wz6(tHahZoii2_ z*c-w=-;QNqFnM$7uUmCud?_8fji*!TJ?Z{vXCpD|TRpd_YjJPg+BkDr3rfKXJY=)` zJY}q8K!Ts$fRuj8pAj|xdHS`IZnF2~$StO&9*!fv(vc{2*6OG))SEQLW3dn7d#!^DtAqdb0Ptb?>XP*8x$sMV0Rf(? zGCh9={{H;8EbaR%kSar*5IpF$C-O;`(L!YX$q6BUKXvk2^pfcNyB_UTiD?Le$3gEBKNtCZ3A`Ijf}Z+}YgnAI10x$97G z^|F@H|MF^@BE6og!It+Uj29fDkDC(5p4^kNxmSbHn=bF7d2f`WevyGwnHm`z=Ix{y zU3rPd)gYd?hmjSHNSgiHqSNbNZERLIGTJs<@HwTU zhezd?q8Xoc4@P)OA6cIUP9>sMW`#q|>t9so*Tw<&Vy^~zKEd*N~w zXI!uKv3dii86RknGTggYq^na@5%kDX>Aif0Kt<#QO_24ENCzZDnMHFUk|Oehr_ACW zfB3+{`bTKH^pVkyKlm_MJYHNp-lX|_v9_{~_xmB*a}z8qs9Q3j*e4<^+#q%_|M$WdT12UgLukaF zK}VTlffg|_af!|;V0*;mE*lsa{5krK6Y}d*(O4Sqvxk2JF9D2(uRIXM7tl206o_}C z?d;-W+T!DEZOteq4(<;`2R2SlqRz8?r;gYNV2~)Ut)ggUWPEuf04b%UnswHkw}IwG z%4G3P*OO4SGloul4qmqD8T6CeaM;n6BNk1X7G=opf9? zO|1MUt9q^%Ofi;htk&E+HJM$?^{mMENR?>n0e)x?j;=qoXg_;*|J!ppjw+JbRL64@ z6}Dd1rdDcMAFY%;ba;l|4+APc>N(7BR-4b9e3jpH|IDIk_WcqXGLba>I8yc|3u{~| z?lN!+DvF5}7-j>aMtU`LHK7WgoLq6ID(-#>qu!5XvFx6Yb!w(%_8l_Jv2rNg) zq=bLL>(p6hesBF`el4F$glGyUgN(7)mPJxKHQm_eX1kbqUrhewye!ouk=ln9s9>q|;lgoO>KC9#pM ztu0U#e+JDOsu}t0*gfFO?CdG%eL!*ReC3k}3StRvJJ0|I3Uv=4D+5=oaD9FJg&kk| z@G#0Gr>?GUls)ZX;sKufE&5t&5;{8v2M0hA!ZC+C3Ib$zO8OX^pHfqv8q=jxc3rMV znMx%#Cv@iP(+=^G1QSXQiG)x|71kTH3O_oq%({=AT%D!*8r5vwk9&}jbK+@Ve?{es%nDBZP5A*{id!3f znF?xUE*%FDf%PY1K}4neV?XZ}@)P@D1#!N9xv2&>xsL@9c_`{EJP1%C_(9X6#Ko~C z{L7-+4}^_y0tam$ba)jttKU|+48ys8%nl=t{?U~Hq zGXUQ@J3Bi%IvxS}90ZrVytOkk`p7YO1A}bc0DS*|Yi+2Wbc@R@1TGGmI`Z=J;D_+= zUg*cDC@%*p-*rk#Ap3~|;5sBE1bQv5Q3`HDM+Oi`-Q3*BMg6u*b<2?4$=?~-tR)iA zE;qWm_xjZ=XJ2I1WzRja&kMq8^V@a?=A`pnII_pWW0tSn*C;UYO5hWKBAm>t^OPz zZ(jD&;OyZYdV*bwdg;%zHLr?wpJ){Cxp0sZUbiwzV7t?PbdY1q(-rvs$@0yF!=M{C zf7xm!w2IOmX`-(~c4vs}3K|kZL47fhcmAjT?;*qRo2Gf^tKA)rFVQqgyj285eE;voa+iZM~1~^YCt-aE1ZR_WqR81TVVWv{!+Rfm~-uh`AS=#SOg*N6r>9 z@xRoIWMvv?^k%c14g40rdyN{(-L#qdHrk4*XkQo(?1t}mW73HiPqMzbY(OQ1y=%>l z8@gI~cDwfNX2_MFszKu2H4bqah(6 zCRB!v!44;@eY8k+E*_$T%+*PsMnz{hs6I63;}z4rk5=*i%7~-l3k#FD?sgK&YkdR z<}PzIso8?&=Gno)sGvkRMT4j^0LSr-JUn)RYS0e2RR9_Swii$^bQLpL zODih?Cwc}Zh$qmZvE<<|Esbhy0Vw0j}dSC#>7l1eNx3l{R{pQfDJiUeQY9xHjv`)gaLviCqg5BWC zicPY0P0ufp4)P56$d7F_GtnYqBpXJ*LP#)%LH_jl2TKRaLqOy@X2bfZ299) zzqBD^smR>Iizj}IiK95mRAlm$6eFatd3#lQ&8>^KJ|6qeTy0XXF8+hsHSNBkp6&wt zqRavebvka%WUXf^zK7QG9svn)K^uIKJVhC*&xHb!XYH z_vjH7CpX@1sqax%>KxW8PZ+8{=j>p!9d_<<#>GGg6o*fIyP0*9Ji>e4XHGw?t}yE% zmGMV!p@@I?;|cy^O+We0v9w%8{(B+aiW^};Xh;NQkj#qfY_*7ee4{WuZIh~9yHbhM zXRT6$r(>?}mmD3FKXvhX9^e{Po8R9(95>&cnEBJEd5!9ps9ajIm(piV`+r*n;y+%r zLyt&m&xRiMhEO{NN~L`G^2ON52$C$OT3XOpM4zMt?M9}Wn$_^w0DkW4d(_kwa{cK`*k@i>R=U8l3kyGr zmaC~rh_pi6J^T^1BY{Hr*B}#p1c%Jit1O(Ht_}`h&je5lU0q$6U{}SIF9aBg6u|=) z*ch}aL;UH<^2dNxd_gUC191UtMn@M4qXC^$uxr3dXJNQT+V6_X%@McMwDcAb6t%Ur z)zv#$B2?#iz`Q&IKnDsE0NB?7uB$Mh6{|s}4^(BC698Tv2J|6>J_gAs8U-+Z$)Ea1 z`%U&Of>`Qnt3NOIrafOen6a9}HU`&+OUiZ(?Mxup^xc@*fjJ2K9tyc#@o>Jm@M+dP zSc#$2yu)^knwhx>s0BqZqZd&)au9P}LV(^7v=C0FpX_|}EG4&vXpd{&Dp)cl;-|49 zn}uu=WPdOuWn@Aj2U`8!=kYUsI2g0pn7*S{@sW;Z>v&~~kz3l9+T?8MP$0>MN$?iu z)F_F;^-D(Jy*xAsb2_c9~PUqW*FUO)9qu1IQUr5SeKTHZu*TjP?i=jfH9 zBdVKe<#gdaD+{cz)gdVvKKR4qjo(6LwKCV2Pnz**0fl-Pxq>{Qq8$$O9>NNLw=tU+^*!`9jI7at;RuR|5Hx+e^cX3M_ZaMI$v<&fuIr5z&aE#4?= zxoLJ35>u@3{99dPYVm}@OcaG3FYA~s+5$y0&D0%sJLCu zhPU?Yr=Y_n($lBo{O1M_9{hzE2oRPAB{~;iND3HBfM;LCgTn=YjG-=Z4$4iaT8zL+ zXmC(C_|#Ted1zx}1Hd|hA|e1ty;66DrT zPAy=c0!{;=p%`8RW!IjF#z8Ox*4Xl(!@qtV%y{Z+YCKN&f1#wI<>i1=xA5^1K!QL= z3d0Vp+ovYy91gGwpYo!gTx6uC`UM2QHZld)+Gk8&xG=FqsX19#egWnKHT&Ay#DpGp zbiC7Z{x#px(bjej-KD>(61Q^x0{TFf?gO;nLF3kspFahy`U$9GQ4pR1s~T9P4fXYZ z7O7Uieqbppi+R}&D+D^pK=lvDN$1Zs;b9S#rftF^B7y(ecDNk;nd0Z)KykwR-oJkj zs(bMIMX|Txw81V^xgMz^Fnh5L)pm&9P#aeB`OovbDEox9gVbQnxV~aj$lh%?aVK<9qy4NY7$dHWlQh zK*;478mPA#oiZ9<90nXpcV&iPel256oN~qcvHk`8?SdNb{h`Y|>kf5HBwn$-%^w}^ zXl511hzMfJV>2-_hjo-$Jtj10xfd3YcJab=odMscVxI;&6?kdL?2|oY;`d$ zzoD|xmK>(^0+C!2lV}yD^`9&kPG+voxlY0N1PAGj^t6n*6PaYE+ev7aNuRjdGJ|yw zn}HEJn@W-P3i+Qww`%{821;OFqm7qxoMH@0Z3+mF)z;5{5VYGou45MBx&FA8M9)~4~5#kGK#-XEF!?|g?mwoNeGh8`A1M!kZcp^*A^F& zo;dYZhYS)C9?$NzaV%Pfuzz2eaCU=`+R(t@p1k~6Dz^+>{M+VcwKSe(P(1%d`Nsfs zI)++oc4$bMjr7^mrzpBVP+0kdiC%}6?we2Jw z9v;Gp<`m|7l2SoS%O7YS+43#O%Ub}@5D_V;;KwrN&Cubg-W5h3x7ysiXw;xOy zt*os4&-T#^%`;*S6Sr%Izpt(y!TD$!BF{kUxm({LyuSw%5(_I*c2k65+;tb$n1dN0 zrKVAqkW1KUON37KRa95U4=pF?GSbQCx{{!)d3y4GP@-8kIh|u_H>-$&_z#2v{CDp@ zXz^)lYBFFT0@u;$NfSp02cpO@RaI4B4p&t`X*f2S(lGD1jQA8Ax!xzhF1p_48D7`o zdD%yTqz2#Ox>O5YX7dJd^&X4K{7G=?Ed8An)9pW2;rkC=T!gQ`A4`awcF7Xnf0sh1 zpf2ftVJ6*0c(QHXLPt59t!pBh8s}H4f)=gtgOpM{lp(BQKs_=gi}gM)dUfyHT(?I! zXsCp3Lc+(<{z=jHW2}zxORhuDjzcvw6%`Y*SWB!a9`|t5@OiZ|;ydt?alTA)tTH=x z+4GfuyH=r>HJwb|yXd_^zyBVirT83IheRIUNqLR$>iidOE;^Oj_sa&JjCX`sUgs*| ziRK;jd`}ksa*tu{NI@(ohAZ3hn-jbVOC^m(sVCMQX zWLVVZY&Bomm;JUiX+EF4{|w13EPN`uvtId-xDl5~NLp;De;sY8#uto%{PzkCE4I=Z zEV70|&@e#N{XT|j?kkB@Tt_cV84&7^ab+FJK##aJJ;nFO{a2i>dk#qv3MtpX z6uE5u(pab2%uz%A%X1PHgQ`&@#Ml+{ZLZVFT+b6`!ZHJp;(tl#D_`4Pk1AhWoGo4+ zu+>2{+;6Mt(Z5icZ4-GIA1lnx(X{`r{ZKc}z4~5PE_>j$jnC~frrDWsK2QX@@?zYw zLLhM9v4C9WXu0lceS!RrAJw1RZ9APD4oB!Cy%TS}wm-l1JZj&Jf4wwNO;N#n>=2dM zSisW9HrwP19!L*|KVW`7F`YVkbn}LuV)n0rQo;DmqQP^%pIUcY82v#|oo_@g=w`-j z*awyXe=)JK0cCm%YKX6J`JctxDGA>PbwB_?o#$->T?eqceZnAMT$+^o`=AcoiyFn$ z&ZdiR8JK+KuTc%^gIZy9v}}ESY=Z8ay{6knBx#GaR@LhFOQlSN$*CUXx&*)cO<8T@ za2L~-q=-$8qqxMv!bm(y7qfJ2@I~oExYw{ngsAf1A3@@>ap! z)H56}&3i4u{WfHsL(fH3{SmWY>#M2R>458*p4ao_Ev;K$<@*Vou?Uq(Iw}MwF`TEJ5dwio^Fpw8nmp$nFqHkDH(cS0> z8av)PHft$y{88xBhtv4H8_FXsbf4DS%vLcZeZ3#vdf(&QO+EkY?dU|{NxO?Oe;7^d zW4mHTr0(@|NYr{Sdz;aHV8z8{SdsQ`q8z@nhDj7Du%YV2@pL0f7_Z+kTy4d0RgqY^ zn)SXZ{xzyd4D?iCKdq6T(pPlh^^NTKk`;O->(^u-X>ipn}CLD}r6 zqjKzzYT-k|fY)*tAsip;0v|uA&{BSHU;B2OA-T}Ip#H{q=_7~H-zF&dN-^lVxx~^2qk#h8vd)=ildThB#TLw1YPg z4;4HIu=1rR%=EuCc7dAR$%E;jDQi~D|H?=-!BldcZ}@#jsNvc%uU;a5YHcsu^i;Pt zI&O?B$b>jjDL6JbU*icDn zNMefm_zzymJw8(-x+uj0L9ld@C=W@(iRQGH+*$d6R86#OkMKbj8OeV|>HI4ChJ;Qm ze|ABrZ{1$fb%<=i9A@h+m2SG?1WBUZA&>W8w1`rczz z_`zjwlUi_2<2FbRcrP?DDH|-#U;E|TqxMVDUqmZD@@PM& zlA%22Z?gaFu<9mHy)D{zX_`t{&tcWJTgSGLbX%T1;7w_8u$r`V+TQM@xQsX5+Vy)S zj=W)nL(*SWbD1O#6w<6z-dsi|uCKiG)vC}TIkA071O zWkv*TXOffo#Xrtvva62W=03XWl=RUmwTPD?pL)l1$#I};?8O7R(Ctk^`t0JKPCjYO zx`kvuX0l*Ln)LN)mb6$8hoHU2fhgRGkhdYx9#X+(F{1~y3TqY zME7WZ^ctHGma|d$AuDIAC8igB?DqI#`cuTOYRmtT!pYLn?$DQ^BA%Go3D)o*Rcb$P zqVyKO7Tl)UTtc8AStjSGYU z!RAU&*nVqK4JFQ~U%7VL?Th>`Ex-XIhx}wynYs17*V1db$*M$W{aUs&)j{>QJ+y1+@cEPgHNt7nBGlzsxjc zxR1}p8|fJtH*egSaHuz|Xa~73`fe+J(ldWqpf9#Y{^eQXDDIxzKsD1bY3vXM1T<^-FJ&S=-3Sb zPj^g&V|ts`RSLtPFH=3}(I*!E_#CXKt}dJ0VqR+z^1D22(K(F7RbNXp{+vC$&0$?I z$n%_In#JIIhQ8n_Huj0ISESvu(tTONMUMIn%_=;o;ywGJzu%S9<|`L?g*s?6RP(&m z`5R#odq$ATtXMD$qeF(UAj@zGuXvdZt5%ogL|#jm+|NB39TJ1c%Qc_Qa%FcxORHcM zb@Y(o$msjm3s>~r~k+d63! zA^*1=-Uh?eWCeyFdnW*3(ShT?_ir?950i^=>FxFzvEVJ(>Ez56dZCcEejM z<1BJf*I0&x3`->Wo8@t|t7I=dFqjXpmm za=U9xN+Xr>+m9ZdKqf}T4Z%#0ZN=6-F(C?vEWY+RtMB(+@=Km4-o9 z=VSEoQu&aBSqQiLwdm9Zi!1f=ukM??IU*a_D_inrtyX`7pOIx?Y{YzD@$CNa5ufgI zd0L9~7H0{2xi-tX4pGj@g1C(Tr2Vb(X3Dp=k+{g^+}j5d-#OvfU8F(Aev!-P<=B5o z*WEB-!>`~5B71m|_byw;-;ITlRc}+wINM*3lJc(tQ|TzWNXNQJM>7q#@M5`f3E?cx zz0q5)*tsR*@tI!5#W7fBJuy;w=36#M_)e|X$>W$cTx;(rVa7$uR*R>JNG{V|_l$Cd zUb1xkK*O&ikEYZxST>_+ZjTl*Ff0!|=4?1fmX<5L?I9nb+7jxK)1_NrfBCZfoyVLn z-zuFTvVDfyNq3Z0?vz@ikw=PLKGR%w%1p6b83Vi+Wux7Tj$?7ly!{>PE1VN7Wou^o zW>#VQ*}j@`8?{z#jDIHz>FsD_;{I5!F*p;)Jo7@IsTRYvAfs2`1Ht1`g{?vIOt0h} z6}eF&MjlqJ|Ggsy7u!EoN^ec5B+(>PAJ^QRIJ!On2l}hXobmYbzZUVRl(30)IQJahNvWSsnRZ@*+*HPsP( z>+rjBKqZ3H)1W2zM59=osFp)uB)vF{U`<)cp?B1h&08YYcI$`zHKg>c=dH>m!yE>Z z$EAYqCdNU@-gS2|a@%zVoQzt(=xCF7aB&FS5%k%ypjW++$F-JM5|d%*46S({mFqm@ z?57dT5TM(|-RJypvwrBKYxRSNvh7C=%h~7}XPE@PFK?YKTq_}*$ew9%F)C#+e~Q=5 z74^!Z%zCc7S-BNUq@zqEr_ET4>aCq)s^o#^#>bwzE^b1#Qtbgn>nX>^s_Mm((H_nh z>LXO*4_M8}vs;T<-Oi&*&^4^sAEYL4E-no%F)*gg$hlnhB(PJ$ubdg?;Xsb;&4zFs zW+~n+Sl5J!KHNSv+4?8;xjD%d(=?we*%JOhNm;@6ykT=!Abgg%dfmZ59trt4fuDHC zgsdXAfv{LfJGqY`&Dmh1*A^LksLeLpFeHUUiR(_ij@`ocmu9)Pi-& zI+51g)Rfk@7*7$G%}9LPodP72`4p}Z!jDbw6wY5qg3-NAzwG}U>BK|g`Q+sXi2Q?+ONiumu2BO&p$=J$PQ-Hghtm~Av^tGo!#MK= z62dI7Tt?#HQPeZ}=_ydn4xhBWEq%N3?ptJSitDyBJBTFL@W7LbGRFbZu|{8CA_R%(S&6Pu zx~yT~7wPWhOMoC_?*pT;_Cm0w|Iq838W&a{Q8J<<@3M3h$!X8WgV6TM~mzDAI@UXJ8Gad!_`5~QvwS5q{Sq}xr7z*AM*ri?m5Vp6sLtQ%o z$_zzCwy1=0CY0771r~fy8T1q2(F&gv7%&8-G$He@F!;d4F);ty0Df0rG{qhucH#AE ztVs!rm?b*GfQ^S&v@|sV*1T}>P%VdA=l*@)j#|ijA3%-I(=$UXP#`kw{Lcm?m9+<@ z0&dXK(pI!9L!ARvNC5|tmrBbRzAf?aKVV^FpB^8#0>9az{uJmdQ2N;4+3|-=vp1)w zyE|Z?!RS>;h=RIO2nypgk4nLQRe8>2i53h_!6B}^vGE9qa^Jt*lKeX4g;QKz4H)~h zZ{NNFM-L}NujQp4{l_hu(#bV|BA)*F^XKFQ98cF;s(UQc-^Nz6%?(P*saP)Y{CMPS zXQvQ6xPJvoDFp3CR?n{{%egP>>^A7`yfdOR#wxv2q=moql0_f7nUoH(ND(J#J$Y)y zp_je=g9badJ94>hv6>fDYNE$h@po-wR^(S4GfCer)0@Vdt}GHV`^w8;C0v*v94%v(Me5ph0_)`}Y)&kkakh<4FU0XC1S+x!bxI~h z#XEZWZWBEx$KJYo+o7SYYm(m~D{plVD;FCHHylW2kRML6ud-H|=&3BBs=xOB$%iSN z)Rqc4SO=OzP(_f$PmLLk*>VQJjMG}>@hEi^{xmq~0E`H53I?X!e6a7#%*;=)&V&T# z=Z;5zjUd{ATqG0>v?}y)FfqY()(_AFAX0!#KlrKFg`vpz@OaSB&>CImla&fU@#FG` z1y!qFNwbBD!P@$I;O>$lLJnv*V3+*D0*Bh9tpjfEIWji=?||6c+!O;8A>_rV1>HKo zdRb?FJZVmFIgdIh^H<$KMFA=lUS?)nfWGX1he-qkg!HVeHgH)047d}NT&OlU^xx#( zT>lGcVVG&dkp4hn#t%2OOLV0EeWBQSFw%@oOwe*mN(Op*!qO{5T&SD@&*=E^Q%Bpw z^H~_JD7}nc%h##z-`<171Sob3OG|v#gD=50R8Jy=@0*5i$j48g!0-=T8YFuLgA->759T*1O3T3{rw#m!JzO~BZX03I%U=TyEirV!(#%Nu?xHo^$i#=uha;*=U|(@GIEx4qwJn8o@6&E zEY^Ngeko*nD|b7ut*dP4M59u#alc8c1RWcZm8P8+dQ+d9QMj??BX9W_br8WvQ#HSg z^aMu>KG$3z+1(%Gx?27E16gQg`4T+uJy0+azy9{teG&MDVD}5KAAXM|1?2nQ$xSe* zhQEh0z>n|WX-J>L8hdtTC`<1r`VCU`$B^+71B-jGrq;&E0iNo2V7lAb+JZgD+r`uC z*O&TwoEANr8X6ip&JT@rbS40!xd&-`u)eGcO?h>C8sNESi_kDJt-$DnJTPdJ(xI>n z8V^AF_tb2FN(lIgZ-EsLDPb^dhK3I;92|JBxuruWXM+bue7s?`#l7I*U=x$CP?qSf z*~pa&g~~kWKT(T$y&;$=_gL%z$rU^oF2){Re43jJ1d9PEYQKnxaPxp7;wQ1{>RVZ` z69D(9rn>qB%nv?&`n0*R0cdqMFtm1c{S9uwP{JXF>wK-$3=loP0cexOgFYXc-;(u!V`#Wal3dD8G`DJL?aa_`fw!u}@1`nb%(# zS}>!%Ff1|eVX~kODP#p}q6FRA8^t5D9Zgj!5eI)kz8s_g*Y? zZLV=xk(7bx!o4|nba22BktV!#y@y3#JD^!%ooX0)<3NI3+IY}VH8jem2lbCiE5?T} z4R*|?iz*S3jycV;2^y|iE_6iKJs^fse=@ktcGIkYV~|4!Eu>WNj?pN(Xz}CC7r9NL zSTC1MHPAxVEacSul@~Vgl>UTg;MI~Qude8#g%k>ll!XPcJZ%dKO!_##@}D)GitUy#k&bBGG|Q-fZvRa=HlWAKtK}H)`&>b#Y5*R z(myyDpsNfO?Xn^LWX3F}>sL_L=n!~3d4gV|qhz`|%VXY!$;nyu{rmTU#CcSHx*N*u zAi5Lg=RW`)5NcrttyLQseuqm-tp{zJtwGEJ1`zVNz`m`ksiB(-5(h2g85CBsQO@FE zZfj&@L?m|Fh0BTZ9)~IyI3`KJ>I`%)90a6Vpp*U!`5n-3xWIn`?51 zHcaZ-!!=;-xMLH9u}EezoFnzOd$FtZPq+9}nGlT)bz2z6&{PG&zQ9AAI~Hel&tp9K#+) zw&)+Yy*}R_zcWp$9$2?}o{Xh{n>aP1YJo=Hp5$rwmRQnUS!m^9ym`H1wetM^>gW>7 z?>{6n0wv_R*sKl=mDAYxR}`KkVCAK?d3M&gfsjAs|6Qc^BOl7^<*LoZzt1$yIvMRf z9>htExE(HZ`0_-W zy+twk7EA>rkq$f?%QG=G=Bg_rMClP!80Z*7i&k?MBLb&&z7_rSY;Oex?9Fe}^Hm>G zSdL|aH;MOzBynQ{{q2z4H(hV@!#xwjf0#e~xS&FcgyepedhCPShS*E%?J3r3iCFi2j07mkkrIbQMX9 z^iwf8TYA`!f-%xNvyY$0KYN%kmfdrosD*ro|1}zu$$MbFm6h=mlaMU0uBPPVsK**N zdkqYi_h!vbOn5=`0hMH{qoSOLhLAXedUlmb%L){KVH?7`=`+uw&XE!r5P%-i*x2Y2 zVSOh;A`7a~5GX~zcmXBq+FDO3sds<`J%muHu?-b4{hqGM(JG+?S}%0gT9}z}1s*zm zoCBA0aP&Sxd0(4#hQPX=xXynA&pie7uCK#WGcq6!A;5Td3%sVl2Pr8jDLgC;2`MXE zhoFZISoCacNGBAmKYmPTHA3&)gGCtRiWr^Xm*TrQ%kS}K@{*p84x3TKRmA06t72H$ zm#<%cPY31Sr6Y<2Dehh5t-Fl9mDR+K%aI-k$0Lh3s3aa5vysk&%%n2}4a6lzU~t>w z>#DC$j_B*_6DZc){pLr{&An4UZ5n9iDf_C$hxDnr;igY8Zy+aZnGk7;i;JUFCP>{W zS`g@i^F|QpfUvkk-;u_eq~x1&eaob-!9+GVZ3RWbmvBg&De3WGx0oLU|kaT-u#=J zh$I$bwnh4X@%9!_Rju8-__hNDK?Lb;B{nUoQkxWzlu%MYx{)&JZX^^50cn*6rIC`B zmX_|WI~T|Eedqh#-~Hcl?;YdMaGWs?y7yY^UGF>RGv|DsISCw=+)jF>w+p0p3`OEK zyCyld&yns=TP{~_Rlk-WD#>}_J9lp0^^T)mg~h3F4aO}eC?KwtY2b+}jpx&gVnCss z=ojAB$5A_kkR=ow*YGH~43?%SCOHs4=GB+P>svPAeEx8Z{L8yZexmS1GJxGUdTa*)*WSD>TrZp`tztUuP*ABQ&M%T8O`n2hxF9q3`NnyrP=`f%%O zUmqO(N8#?z32$X6R7=eu5>u1(_zxpZ`rYGQceTWJ* znlt}K)2J0_&+P~1pI?#LeP#n@st9wNXLyu`&p z*GCs9PAe{y7q6&Bvs$BYhp_bLi{`2-J?JK1QE~P1rAsgGj6$zNqSqmfFf~&V9Mb#t z)921X?A;mX2C5UlzsTsX6Az*DH=tYX0wYlUjU!nKGqZs&`<|YtRhI(r+G9^Ps&PaR zrvJnfV6>oaXqSXLIhC)q3P8AtefjbbY^SG7<@M~%5L>}C`p00x03X22q3o=VzLyuS zLQ(~c3_l2#-dRxw)ni?{^y$l&$fikf?0ewGAtE%3Gz7CGF02QP?Zd+`K2l^h*Ild_ zL1!Cl>lGMUa~dTtFAo7&G3*nVNd}=HIovC>dYnsb?J@)`4L<;<5d;mkPFF=`a&Arl z)BqhF2&FSMHCyvDGb7^%hy+_&0!k97++HADWq>9y9f=f@7dbhW$Sl6aAptP9*bb$I zRegPZ(`|_&uG{RWGME98shZ^iGjV`ma*uHkVrH1$kmxd-4g@@MAs4%`8XrM&qyaRz zhMBkgpU$bmfQAk`WON2fbAcMC5ky@+mV_u;&{FN5C>uc`bH%_1#Aan>`S~>g8|g#o zz#{51vGVQ=GGgwdMgiz|s@cI_niEE^`iyYF=(kLEQMw(F;R`i>sW8T1uZ*5N$Vnq2 z^64i}tI&tFw6w4w@OfDi^f5ghCV1e9F4nyCLdT0>1&O{Kb-Ki6yf0N8cCg7b4DbhE~2z9pJ+9Ti^b{bPmT$s-eZLQ zbX=7Bi(NCf8}hBZEl#ZSi1` zrk&-B*=KBYcRNr>TSV|XC!cw?O>KjGk>MwPo3L(!YvjP!AMzHR_@AVUpek~{u}_l^8MzErLz;+3+QE)jr{9v=JS6!9v2NY>5*whPk1Q6NwD^le7iEK7rx8p*aZ zPfsOhmSN`g-d-;63Rp?T+{FB#GYz)SIc|3WSM8wrtxat3_NppI?qLn9L}0MvDPpOU zy9%u-O<*ep3cmt#+TP+>)^&ax0}G369g(pRb}lZlEskV1m@(qLn0>MX*X@bt2i@x- zWN#zU#M02NKq|ErbonSsGpQP-)W6$Q980x@q2?-9_sS{YnS(hgN@{qwu1;e0H;!hO z-mJy3*xfAxextY0@v7OsOGjd3&!_t%meM&Csu#*kEWMq#dMMw!8vy-eJ7lI53n|uv zJ~%PK_vzeeV-~u}Miu*}9d7(7*VGPMJDuRA%=qq|*Gu zkr|JWUT!czj|KJ2{wf@CC!wIoX@4Bas;#M`BMin6JeK)jQTy<41?UHF+<@dv^YAb% z+9B{6!Txiwvjcat3e-}7MC*V5evGoRw+EG#Gk6vV)BYsQpxf<}hF~gir1Rec@4!2~ zg^NDbv7^Y_#EH6Md%c^HlAiNNqy2k^-PCh2pEqbkY>?h9@JGt{Hr@Tl6X*Gdfz?wb z(Xh%FG0pIZ9wmBGwgeA~+EGm)h}i&L4Ai)XAex1I5HwVP7Yev}5d0G4_`ZMt4mDv% zFh4Nak(-tlZ15!X@I?g!12raQX9?1!y|*NAPKp8}&FAXfk>S3-xd066k!~>06-g4F z!6E?fHs?j*t`49dzOTBfN&?2axViiQ)6V7VWfg)>w?t>^|4<_H8 zLgoQMzzg;hvWm!n*Ln&Me-hqoKLKd8etJf%K^iZp9w?pEwiI$Yn0%2ibJnN<;PFOW zT-T)g&pmz#B^4^IErQm=rwQ6yKS`|7nE#~rK|Meu{yGrPYiCCoLfLi7$98M6>KobjBWe-a@LIjk(0G~-Jkg)>}iE6Ezw zhV)Z}*4ydn>37~SGBfAr<~qU5T5#kIX--Z>y2Uo)S*oylCp^Q#I>8H{yG#s?<9#6} z+69dXiZVp%uOwbvd^|sCAV}?C4oqo94q`gwpIyX))*G|xa!(BGHoU7x@2$A&F?E_{ zvHQ^-zjEjrgQj&ljgsoQxmu(UV2BbWXtt+QYaqEp=%wD%)wK^?-<+~lUl1ipr`&?^ zNe>_X0zNUc7>AbdF`TsM7wYRst>*R%e;9#tP)A}JtO_pm9Bft%AjVn5tRqutAVdOP z%Nl6ADpro>hdi|I+xLqcn(eCR%p zYL*;6);@ULpWTzX=v#{QxdUe&dsb#K>vL>VxfIjDWixpZE42?K+8Sk;q=$G`@tmBl zM@4a&SA942TQ6~zC3yURo8&ac{<+t@Q8C=h?N-ul3K|6s=xvGPv3*zg)IRIcn#fUD zWF!wv?1_vdphj>9WD_Z#&gVhO&JvR1Fhj@&1##8_Ootih?6d{l4uE9Q1V$ig5t3hq zWDWkSCM>BKc@vAf6(+QOkcQLf_X-29rKCd*gRGD(C z_E>z!Y>JcRHBik7LJw3_g6h|x>n5l%UwT^rGzNSR!cT>0c96s9M8mwuBu0>at-h+U zC=`J#I0XpFRMfOpw6)#p$sE;hM1tM8Mo5U11l~&oj13u#!x=yT6%0fQsxN@qp47X; zTNPWSBL{(Mk|0GmgwaDFZEaK<9VVE z>8r|B__YvB1%`AJl;kERCcefYE5O#65Sh&#M>z#g;}hT?8s|zDEzvfr@!}Hl@RUVP zvv1VAr8eBg$8h@sTqE{Q{ise@fVn&S0WvT*w8V~yq609brR!tB0b-EhUGI5d8Glp* z;Ys7d(bmynqV+gL6CklAcm4$7JalW0!~SABEkEvOU}#9jXC=D0+9A&YL3~9X2<{+N ztG#;_(u*E+bmwWGX+AeBdx1~!D^KYnessJ+0I>mbQ&&#jfhpTwU-{H%nl)Oc4@?aP_cLQ=ulr^ToL^<1yKS~nVwstfVz4?k|F9x4^cyJzt615`2vLGf@ zTaA89dND;)q>VF1NK6lP7Wv#VC-%#Yj3PGe8z2YclB3r1_B(<4`jtwCzW7Z6m-W;@ z-NTsdIrP2IobdqXdw<>Y9nr_#l(xlMgBeOaFQh`;E1GaHKRz}2` zi=V9_`BGriQnEXn32ptuLPMR#k^b4BL$(SzWLrv!(wPM_*VME}3=b&k6y_VJ^*oG3 zRT>|8R91d#|3X{VFX`uAr!ymWiV`VMzfqFS;!Ax&&ozrpkzL>9S_0m*yv}XGDNx8G z-Two4he6nWaqJO1v(q?TB!Gf}KCq#7u0s>2L`XQevDJBNR zr}wZEzdb)gMn(paDP(*0A@VhF4cFaI1c(Z~?!or}rP`u&;S2cqr@w!^L&VhpSje3x zLZHh)V;BRBrW-pavi%KGw&pwopm~7Aanucs)op0LB#!Ne1appI#9mol>8yqhPYMY2qeH80JN2s{yS^1~J=_WVq$TRsN zDFX|`CH7|G;oSv4x>%A~QsM%h9fEd{jacgGQR512bSXOy+4myP4Y+_zz+v5` z%PAYCbf-WaUdO&$1*SHDj&RGR9Eza7A@tggs@yk(=nrn^$at`_bgvnidJWtvF4T zo>-z;n|{_zxd&2o$Y?;sC@GeaQKH2<{vPVHJxlIerAX=-!W=mn8JZ+e&ntQ>5er?UPVShPJ zM%?ZFsG+Q-<+{6WvdT^I5E`67*jfzQ8n|Ua$R2<-hnWgs@b#f-092(mHa6-c+1#B# znP+NZf{~JPf>i<$Ha_I8fD|DnF5cbSTlnS6Y{?;bh=sx8H7E@)Zm_xw%b`#Yv9p=z zYtI#Rc{X3O&TZDqTNbwI?Yeshn#aM<`4jI{UdVQG6%J(0-P-ZZlH&7s<@VwCrq7z& zv3Mv?PcaHuYM142`!IQJ3n_!N7$JtmMaab(a!|$aTQ>Md$X);!x8YC3iMTy*Ixy%O zYWjd(0lLC74U8P}aIBb)m%0`dfbC9&IVQif*vSb}R8sC!k3WpzDw;@>QXpAVcM742 z@pyOT>Q%SHO`Q|@zaPIj-H`O&oRo5Jdpx_j*-p6)K8`}I8*_8pTU#rVQqKLhlJ@-g zzS_AFrSbIXxijpdo8MU`#kx8=sw7)w#EUM86y`;pjarrS^tRJp0=o#_c77g4nq&Pi z0sY7(^FdcNn!*K zR|{dmJeTW;I??x}Q{>ZY+N!BVzAxM;W_^|}dF_V|KXP%@sb^ZdYvLj~M582SLkkXT z1g$s5Cux-epuaq&7N(atfqIOKLtHW0@v=xw7zTag`*l-9U1@ce@*K##g2J!s)rblCoSMRHE&=%``;XyPG7?boU^4SWRj42kuUOtWiT7- zG&yuesVDt)JL?|E8I{JeUG}rBZ|IHmi&6=-j7XUXKlAqMMOY^*B0?Ev-=qv?#}DCW ze+b^2En!`ghzm5|eHL?Y{B}{N0x~j`^k0QF(5}|f?Kr>Z`aHp8XJUy1;42$~@}L(= z&Ys@M*NGUyG12~h*B-}8RA9GH-Ts$}P=6t7v1Qs$cfnB0Jvu75;SSzf8y#Gk-5Ouk zrk*yf`R9nnEZ%yoFpBB0 zgFo8}m|Ys(4zDIYy4G)K9UmgkLoK+}Z3aI^AMdBCvn8!GQ$Ru3<`Jn`lU2$ZSx3dB z=U^ju!;V@xUBs0;9iWrb3m+y)xvr6;x&?pn2qST~6&o-Zw9SaED{NGY4U?2OOwVB6 z(KG$WD!|oQ{4mBY6*UYaNqE^Q)N+e-j0B$Ko5kDGrFvoCE(`zU2xAiYL zu=rNZ=$~lF#cum!Ba9G$Oem{}|B9i!F^bH{-`kozCW%o?Q@n!e^w<+Pqo*S#Q~}Fv zoJ*cZ?R*czF#JZHZeT|tXAHF+GqAuT{~7_s&sRRXLl!%VF|tE{KjQ1$hO{|&0Z%Ks z7(Mi+btSR;edh2Gs$SVIZ_fPz!lz%VUPcGHHqP_v_Q{-jik%qpZkXLeg;Lj&?f8Q) zXzClhy$Kbi_x-|}Xx}vRg~ndgzHw}n_GMN5mbrz_RTh2Cy}!tyi}RFKU83T=rd1I5 z(XaOfuNi0wG!_?@Z}@$DRsG7FGmUib^2jMFG8uid=T_;cL>WL^ zPkG&?`|7ewdED)~neP1j(0Z}f+$ooMBL)pXB*+7M9}Lu>T&i60H{PR^ZPw=qAhJ)jLtROKo!C{1ZTn)esrD4z)dEOK(xoo!3pz$Y`3p z^U58Cx_;h&j*efQ-f*uGjNv78MT_GO0_9mFk;g^3)3b;*6b>r6*fgr0v}mfmwhMnd zqYnwUsd7HgkrnC8hZL`vXi3?vj%^@xb!m3eNMIfF_!Y-iH^)e~pqZpEsAn_v*+2Q; zyPZnyh5y}$`7d9(9?a~Rp`ujVxfUSn6{=x0JLm*v)R_(Ym*ajL!%xXazU+sO-DZv` zijOEB@rBfe;*pJS6Y|MR!b$Nrx2E9Bhd-)lSMk0g#xnI^{nGqP#mabEG z|F%oWJ$ff2FBlJNTvNa7p%}VJkUWT^3G4->R$~`#P$=Gcnvq$V7?#iueNr*b(ss_I zWaLIr?se82#j(?-(puKC4#D3K#Avlku7I`nTsD%W2&*w&z5I$4KTIm-WBsKXJefb+ zU{V)nX7V(%1W$f{FX(CWJvxc8V?`q4 zYV$nfg^4FW%{kub}H^W!hk7&^|<62yN0z*I!{&UM?Dt9kn0)h{EN)`g?Y zEhP8q9}ppiE3NY3hzs^hYsG6A)-V-Xc!tpcuRHSbk$3dPCRUvIVl-EC=pvw=5JN^& zef`*C{xT-T9`_`SnvUvVuA9}5O~vH;d-J7&PqRn39T0 zL0ZT^gHjq@4;KunZRyb92OW#$_hL1+&`mla0uMU$qegu@YiL>NH@2M(CI*yhbu%KY zx!~0(%emPj%jQeDz+Rr_Kop8df`K!8<}f@>zJPF>Jcb{WN0D9#Z~#tOhshm^<1) z81zCgrY4ik85?skI41t~YYxCUV9?t5Zl%tZXtk`Z7p0o4x_NpRm0VQt2hjF98K~)= zR)!zTn5;RNZd0lV7z+E;D|b=u-QsQ#-bvnhlW_bE>~eN?-__itAss+doiA;n)+Qt6 zRHa3%@%;|ostPEUQ0FbRT>MvZf0{ATrD=mbFC35)6ZE3h_&Id}Tm=)8?oKGy@x25& znV-isiLLv_rq4sfMm{RzvD(dChX-!x{8REEulL##f@tY7+1V}IE?Lu^Hy8h9?6oeV zE551il!YtpI^g2A1vEY3U%KLXk_Eo?TS^AA0#5xsc(HaC}bXAZ9_czY+)0 z7a(!qYRGn*BhcHr;bU5wIW@!mf=^<0DO z-}_7|wWc^K<#c5cZ6$|~zvI;@vJMD!o1a>vD#tyTz6oDcehDzmZ=&PQV~EVm!1Bq* zPrdswx1pJ(x~f9^>twv3s%dO01V8;lrymku_}5Z^-^;!sQL(tuk?H4pdES{q$EQ(7 z246fRnUgbmT?k_0UzuaL_v$3|ql~G?tfFgF=u)3J@Si+w{g?Oik9v7M6T2WGfm}ne z%DilQHj#zkDlQv4{Ox&5!LStr2mUaY=B$6%jcp45uFiVA;av*6!&lT-c*4fSG4 zZPXs#4I1j4-Xt8q!YL zMk%1JFC3v{Dc}7Ach^y|V?V`EUHh+@K*aMe|DF5m-gVw=_^-LY`zqY5nG@Sl85yL+ zkdJ7(I+f3mqz}e!)5##bF5EZC%Ff?)r;8LfEGceq*q01XW zQPb1xL<~`w6Xla!f6iLc(OMY^tSwo@1y^u0~8xFU0wo&pvyU0UiUfHsDFJ=X{f-o?q9U zlfjq$;v`6(fVYLf=(9UTu*YQUWNz^H*Pf!=(R?7S8Pm*6bnc#stqI;gAK2SFbII0H z8Xc}R%6L6WD@2ND=?|R!Ry)T+$0j?bM@lpP{2)}JrLRY+eFR+Z-(UxGj&(+>F>JKs zt4{yG+NAKgrXLNUTd7L;zep1yyVf(e{(S;I{&+YCb?DpcZM4>$k70U-332a|W9bn1 zhVOsnUbcxOYap+ZJr{SQZf(?}@D1CFA&pnv@wLz5|Gy+UU{B}5lr1aP>o|TL8A{9{ z*1598TC2**X#vjv@-1~>NL7AM^K8aR)|EDP$PANv&RD|^_!a8UPEO~{onjp+bxZAg zL&JD#s>y%xXrybaF6CO*{;r1G&NOY2X0dfqhwuQInbE{#oDM%v|2}Gsn;{qEL;n*| zrPZ6|J&b>9SyvT%Xt-isIz+nJ!4)8hDI92_p*Id*;R@|5*1z-zV7S*QkGQ(AVGM+X zglw|fMlRA8_(K*T)!D`6#|hM(3xx$(n~KrYe`Bnf8LHV{z*$c7YcAy_+0fZ3lua3e z3^3pjq>d_OIK&QpKl@L6SP?rd<2-&#I^opxB&{HCYo7rr{kY{B`eLBRw1CA$d9np@ zrW(EtmyTC5_4E>V4(^V8)nt!NtC0`R|hh|0OnwxyGwHIi0wA#d5Tpt|WWSza%{XiF$S~u!`2@ zu@mh%xrQg{hiVXbUOd3hCNk*Nc67_dId%+ZS^uYGfGfvmN(uy`>?G4x<~h>^z0gYK zq^7>3qS9Ixxsb}1C-xWO{e1+1U`#l{)Gxy6z>u7qglw6#Bg`_5Ojx4NpbeSlFEnf9 zeSC2hmBo8Zm)|`N=n^Dh7inzpUmo-go$aR^6!pe zas)3s3zCzcOIbzXVmQ$9jA86Vge*U}0$jj6lEM34w9n2)74nL9 zDiO?;=fg3^=!rm#d`wh%xqLJ5B3*z z&21qa_@L-76IwXv8O&aFP9MV$BkCO5@^?GdFQNYlxmW0f8T_m#WOl8H(rWnC>sUBW z{Yb=ud;V>JONVRSCavA;TtmwB_{zwXms0{JW8)1uCFe%>i%H0`S3jhHJp#aS2GWQQ zxj5gn1W&MnJAdCh$1U%(Ccz}pli4ipsW;hO| ze{Hy=@ciY}WjToUAbTOgd@UpQb`PxZ@r;1)4Z&vg11(n*{uqPi|MR2(vtX(E@q0KO z@{wTF%mv%s`q`uOL4^wPO|4viSKLp($oXMAq&qP;6gh-i+Io>nM8-3n zb(pJ^$1*aQea9e7qc)mXZ<~`$9x=R!gXBT9&=b}hZcINFDx_j)16PFigXi^;vjYXP zM7PeXV3Hu?T|DN?QZcKHq=9g)&l2fw+5VIUP6{i-4l~~M z_xcbY*tXC*7|lKdR8|f-dZS86(xF6uUI(tqh=;> zgT3xx`(l!1d-Tsf^qCZektr~M8W!i?HcQZr|AXYf^{qS()n%@YuV=;15+N8B5=&g{ zYYmW$ZS#f5uDF6>WEZ#Yf?=riYw808!qVzCBWe6$7SXzQ9K!)?IdIIMC!`Wz;ckEi z>4DebE&;)8)4f1$!`jwmbz^qyVa$5gwCHt0m5>RvhBzF*E5lBV6I~`uToPjNn#0oR zjx?1T!Q{=z+>mqII6TFHY+BE^%lh$$SE@$Yv7M}UuQT{zMz2-u_HqS`KVGe+Eb_XH zvce$j;Z3S-ih9H6ZukeSpeoa^Ymzo2ws@3oLcDXw2#;@^AQJrI(yQq(*(E)GQ5Y7e zcbo<}F?*#XFC&rY5dkrpEr7Jzva6$vLqkBpUmoIZ<DVkq{L{ALx(8A4S0azQ!CIUe50PiB z8|9UggV`I#C)&Tz7Mp z-+{hS&$ZSANGE;Zaw*F&Ehpp&!n)X*8rygc)+YvxfHtX;*iBaj1 zXZ`I2*|F{@2=~u41mE7Y*Rrm?26zV9IoFGhQx7#|eCl=PEIT|NyuZk!_J4pFqIvNV z4(gXAsD^;#v^No^U{NxY3N7@3lAY0u4PzL}f!^h@)1V1nT8Q?Ou;nD4@?9i|ie4RaOEKLEMi3 z=qkU)6jofyfg+j6XFYc2lmR@)EfG;3(T_UiK*BxT0Imy+OtS|*KkzKVBO?Q^bLatU z5Jz~M@|=H}j-{5?AT*EOW`Z`1#K2Dl9zImMw}8MM$7fyTv^Dj{a%za&ZM_}3l6maT zFa!y%N+~L~gQyspU0@7^NwD$<@J#SsC zRgzu!=@S&f5eWeB@owO1L#YyZ+upx3GP8F(6A#72fC63yj1uIH!b5`G_-Z@Q2E88x zcLyX36#O<5P_hOY&JOYtLH2pHlXz4NY&YN>!RUp3SWKMRX{-+v2frobJd8hU0yP78 zM6uD)zio=4xjgO6eIO(5!&2H$$2$Uba0_86A_ZNbLQ%&8c@jjNE<=-Pz_$Y?#=E=v z*+6W77L&j_Uy6KSL6sC27dJa=Iy?<5H@33ns=cM&EUn^vpwM%6$xebl?Kiv>w!+7_ zf=(aFVZ5kD6>Rk5-%$gSAhujq5$4T^s?bLAm*@wr0;iFxnP(+b%@Mjp<-vkwA`n-B zOv0v-Zvf9dz2pFLY*6&*gVdpNf07O9oeaC*6wVOLf-nL(0c>5+*@Dv$0UbCnwYT8z zM)roc4xtM#l*Y?}tpxlqk)1|`lSjqR_2BDDvMqn+ew(p_9TMpclqO)M@J-bM0SU;a zCD6MXhE~Awds?oeLt|3V2Mvv2Y>L0*4in51PTd6bsC(QmQ*-lpKI^1zQ)CDLE`Pjy>CmDTA2d{D zp1#S%WC9EwF)p{=bZWB2=q4m@Uid*Zn&E;+xzz|Dnme;Yp=D$5@BUfgQ84zAk0VdLayh z$w$S@p*$_;=QY&io!qd4@%4z!LCW zoqBqJoUODiZ4Q5IbuF&lwa)J3WOJ zhGlz*H31?haClZhcM4scF=8Od^YQb014bO$?!uz(gSl!fJpy~*)Y9SxZG5@q24GVX z{@}t%lV7{{d&4D5l?Cvw`V9hdy5j^uoH%2Pc{6sf2A`K-bE1NukB_j&(;Q-h_I951 z+XQ6hHkxtlv)hcjoyD(x(AN6aZ>-uM;wLlC>+=ic_t-OO?YsIUp#! zX?oWDzhnsC+_xboYI9$U#SIK;#LmxG>a`cEhupU-GAsqc>9*utR20d$`gN~n|Cach z1b+BSQTymM%D=-7zT5uZMRNqYi!xAqf{4pF7}I#|@b%XVhOmgEzLIy5a;YMIt$M0* z>_D(3F@^_Gy{%u$2VZcKKha@@*dSE0u2?@#(r6YYx&S;4{xLjERjjY{!r!)@Rp-Tx zWhmG`Q~#c7l`E_FNHsHJ?($mHX=)|>+DRMh;xSa5EPUo+$p2fqy74{j4#7h_Tm>|f zFSW+c)PJ(4nt$dhT})q==v#CsE%p+EtVqJv34s(8O1B!AP%qrhA5Pm8e^fQg4N4ku z9`j*<5(N2-le`qOpY><=1R->)f8zqmKPaQm64_TM_8)MFL)Z>aeqCWxQQ5hZ7^SrO zZx-t*lR(^I`qzI!N!{RX;2*gSI!1fMk~IF z-V-H>Y+Hun7ygyh{$ZJ=UCQ&*3-zu=-Ab7`B*apd3;UIlpXYQ;GdVTKAMyavxhj`y zvLURI2seTrm!qZ@O4+}H>B6+&h4HPK>*vb$+7mH0_O8_ZM{?Vmp9JFL|7~)6rJr75nZ~h+5A*hgy!BhS(9{ zMMNo>6og+JAOIStkDw3%+bSb1jkd_i$w3BufC4iccx@;$mUV{zbGqld5IWS$U;yFB zlo8-)md|En3IkV81kQQ61Mn9Bby@pH_zU_x%E!1D-E_k-xeyl{v|zwT06 zC(|B4zqU8LOHTorfd3)#9EtkBOU`>n3R!hi)XqHmHGFigb|DLC}>pn#6Y&|C)u z%V4F~Sy)+-ks15p0GI;+YXj6-n`(Iq*b&y}QQ6bA7Tz@rgt`jT1OV2CNs>D! zfB5hiXp)v?D|JY76PWmM2*lz^Hy+Dj*8x}!h-l*DB-&s*&@Ffz%;`Ep-}%8}Tj)YEjzCf1xzZ+GxJpmTXZ5yM+x?=WC($jgsgk*D z7lL7^d4yi`8Q#M zQJlqD)-Lc{|3i*BE_J7x#11U<*vGrps%|qtHc$YS7J->_sUV3CyMTHK@>m>DvP1<3 zvjbNav@y~IHFUJJaUe*Aw+=Fw8PK_tbm`Bh8MVfx&+S4NjX3#f04F{TqgFT6b3OHS zppt70O-~?Az{tY#pwhj(ckXlF6ET2{{{d~)w5-pJd{MsvD7V5b31SE5J@^{0%Oqdy z=PXZdKBA$f<|Fj?5;sv{ih#Tv{bkl2rjE|Knp2S7J7C0NJ*!A6`_`2J|Y37j#~QXMlDBSeqQ1%D^v& zb^oN9RmR#qV+RZ@uWDUXirj`t&n)xlZ6^yY2Dm z>$P^D<^xm<6!cGaGaV5uY6<+d^e75dbd}TT@VC)jM86{>dpbME9ZDg1ZEm%|g3>)u zvJ3l?DrbtH`PtkOunJ|nV9ZohHM39R*AEG2StRYNuTy3tmS2}_O!v>)5#_D3C@OPU zX#^JnSDFi^42bNH;`k;Fg7zI`6Qa(}JIc`ZGk(dHL0GsVC57&%S0BYq-3nI_MuCAL z89~PCgt^*y1hF#ZMfcOfC1e!e{!}gq_649X0 zfusQh=MdSZfn@+TFmL6~Wn2iWJ=eOtA48lBXK(8=?;xnn_7JIAs)Out5o`Yhx7@g5 z2T(=5f!d?>t#f{mBlYYr$ilOd%$>x5h7vU(DngD_Po|( zH4ryplM8M`{1fJQ)Ys-736D7D$7UM)<>{7%3OBD(jea7+=@CMsLtQ6#_$PxsZ0`Ac z$q;y|@({F+Qm;*S0*R_^WH|GzhTSJQ(_nGQ0luL5@t{&PXJ=(c+MTl+sF%tXfzDQu z&spMHMbHhXhn|_~>9A$T2J-^3)1dFeZ!4Yrv&Xz;X2_28YZ zz>boQLDT(|9OZ>F9~QQi9n>vmw5xHf9c73J3@>pbyip`r@npaH-!Ot*SW@HfK&l$^ z2XrR#9g0_|@+i3gbDg#E@1h?)dGx=So*Ua%rq_v{>((_|nY7l@`KBa^0A?>5!{#ZA z4V4rM^v3WVM@wW+oIKE%-qI_2VFz58aP6-(3&xNWO$P$OGCdKp>L}EmJ5Qf_L2c_Y zx|OWd>2m(p5&G(nMS093N8w({!_s16FSF+a-v>$n7Y|Z~H*mcg4d%yJLL~3%8)=}J z*RR5xLw@!HWw2}&ukBz{;)LW(uoF#HJ0CqH0|J5QS1C1VB2q(jU<<@4wLEZgP!LN!G5dm?C)8foF@wLJi^6oSFc`L;2yw| z-t7Hc@=?)eli!a}0rRCJU5#)=*LASai-6lgywA6pO?csc%jWa3gZk1>AGRkNotunP zaHy!&Yz;?y^83TIHSfFb%DQJ^S#p&uW5?I)++=i`l*-H&56EqMkZ-W>T#4?@>&3!y z>`9oXzIn^Ozsk0Lxf>}TG2LvAI*b#LsQ98q;P*<+Z~5}S%b332-ocGj;)+nRU~Lmj zsX3JbqAAOonV&`!(WaXu>o^S3Q8`(U1uShl=3y!$=V)ey`aohYE1UT(N6CU(`jnpq z#?9BG@OR{bR`1A%AGt1&8~5Z_?RD-Ar>ATx*oSC@b-ZsZJ|gs!iS1a!iZV1cB5keR z-k?n!&tTIz6#E=T%}LIx{upOl61}@myXQqAtm(E=t#Dsb-eumW7~{6EYOO7vmEfKx z^lZKV`780jiK>MSYNX#0MJF!s(T`y(6Q!}1Ny5XAr-r}S>_7A5XN605YJOMJ;6%2A z+WO1O0+H*^DOR%^&!5xKsF{yM3n!Nwb^6MQ`@CX7dy%pX+#9@Qc(?JBfob+&k*U75 z&1hBE6qY$x!ZR#kzgdSTuCJz^FgFrO)az(`cIjkkEKiEfE~yGIB;(|bl*N2X$QaDk zQ(kEpqtoAQPv?FH9Gac66l$pN`#sgU$8=D<&GM{wZgMDC3~KeG(9_N8dGvj9N?jn0 zz9ywdI7V~OCQa20rDt#|`K-p1I{)IlA+fIe+B!qYDF$r~Qk2vWVi)Erlig;Mx!w%- z{Qh8nAHTPooAm*wNXrpN{?CttUdrn~!~N!yDl5}Il?l_BE4grqr?$CmKT5kvcYS0| zj<3HO3{4njhp_xhBmm_t4F4mDUMq7U?wyE9c~Bs&@tRSt@_~ zXwaMYy=qL2^m3NA;>xCp3_+VT*&VT#b6+fO3Okjtm`)UFG-g)>rtZK7&@?@)Y7DG> zgQH5`Bqx7Zb-VSwnq$`|C0Ce&pboxRqNNXFW#+CoBfV|wME&6gGloa zPt-qjYdzG@pjvg9ztbjduhR3Q$ezFYqgc40d8C^$Cg($HriJd!fCs#E?b2e^HmXYv zAgdI?Hw$iD(79Pc`>y#IiP!G!Fd+7la^9LyrjaZx4z2HD9HTP!Qv+33ep$S_3!Ud&UCqyVS4Y?@tT-y$^whPF?@fWx zK${=wm-&dG7KOQMw!U(STqe&0yi;30u;`Sglw=sRCD$9{FdU5cuZC*xhnn;iJBvsa z;?5kYJF7m|nBByuj+sOC;utUI7fc{&^0Z+DZ5&dgzWkRvb7E5)!)&T>#C zrNv#aFw20%I5_3LrH+MwnHwSn3FIl@_afp3Bj1jKQr3!yRf3bUG z5M10(I!QPAdE=(MufLphA{X!0X1G)aOY4YIJUjQu@Fz0`w>K6tZ$c71jD0EYJUtX? zbkY7?P4p&2L?C~H@LG4^qQ7-T_5M#qm&Gtx0A*WSh7>W}V$BR08HaA3FEg4?Lfs@R zEPA+!Lx$~gKiMgm>&x(p(HrbrBD{-(uzuY~~77E#z|;LocDH+lA;-uG!1U z=hGz{x3nDG-X$D2aw{8(5?LTT9KhN&IV!1)vOQv6%a1R0=;r_Y^5fwC$H)_Nc=faWArco5Q?o3t&pKQSqjno>{7 z@<1iGawFAwPL-|)|A|Z1Lo=J%DHHuw0tMlG7hT1bmn!K3j->BMR#ls&Q(LRg%w5D* zk~plp=3`$=;`ot8YOvx~!Q4jHnLQEj{OPP%A`e&NQTHS)`5Ds8kAm4LtgW)2>VLlH z=~*-@@_3XnN~voO4HK;G8dH0*39>C(n;#Sj<{6B)zNj?}t7pSlx*HDFk+rOhud2!h znhdFFmFer3etx+2XzIMOUu%L6PZT#q;Mc1TJnFTErIUO|5hb1dXt-weK;c zY5F9MNd}fZQrEku9OLs?-KCX%WWmVmJ&nChMg(+Y&YbHCoZP9GcerOaTQs=8$LU3s z*zNL>+f*!x?TAg7BY`=nu;jOanZHnbRP{9xbj94mwe%^hCr{GWuaC$SvliVg9UhF} zt9A6v@}U`jK%%KV(Nu0r#;T=wue1BwXYP^P2671n7PU^!wYl}Z>v1#^VuQX-Kg)Gg zRCMm(;o^Q1_kQ702GHl(*G?%Ud82|IfD!&&t2g?UXy+ns!>mjJX9IQ7S)%EXjm&|C z1v2=`~+W*EVuT5k4_%A) zj=KBntXf4St#-YF>8U<*F`lQxvHO_12!9v-nX3cLv)oS?^9^^DulAeD6ylTF;h7}k za;vC)GMp5SGb{Yu9T9c^Adx98%IzR*aPmX;T%cT=bSZ07!rNXofw*b%$IK&2_Z4&c z)*^)j1yV}C*vVL%^UiFfJn+qo)hk$woK%o|oXI+@s=1W3SY3}Q{?e|U$bP& zo~vjWH5GF?NMMc)KU$vWf?L(poSWaH_0V>6|0L`#z~FH0ni_Ady!NKLyQ+aQXdk=l z>!SQx8l*ed>-ujo;3|f_Z^h(o`dl@hHm18`Vq)8S4AK(zU)1)%y4QR2fJ6>ww-@$3z(nMrE`u_0;K_?{=6AH|NOOlX^S(bBoYqS}U&G)#t^=5GBcrz>GQxnNS zF)?A%UG4pY^7T3+j#|C*#eQi9smAh6iMC;>9?LFVu)76vg#Ey zyaHtXsj1EMOlNbc#KPT=rk=O3*u2&rvp-pDKl?TH^4{1Qfr1Z}O>J^ufw8-@8ee_A$?w*Zle6m@_&14`Wm8)@e z9y7TiCwG%oI-g#yC2>Lhf#$y7t#~CPwm0!M>3BpTc|1vx7HMIzrertqV>s+P0xodlC3Q!KQFDt_fl{)Ynz{G`Ws-KQqxc@S-F}AR0Y&Xz^Cqc6 zegVdtHysr0Bi_@n2*mytvp4t4?lW#~k?m!qqe`z34~l3L7(Yj3B8JJs1enJLl+0z2 z%1cMb3JB=)wSQ=ksApp)RoTccCKQ?QCn{Lz#g&sDQBfP}>5>>%@@Lq2Gq?6WZ_Pu1 zsc$F9@NpjIf+Bv5QRZV)6H_X5I9`FFL0SaNI_s`*?ZxeqT} z#+RecE!Y@fh9Jp0dux??qBl51B#awv)|OuNk=rj%zJ+`TO~ zR(828Dg0x4XJm51(#M_}?7p?%*8r7rK%_y3?nWAwp-V)% zq`On{Rdg6YV(3QcM!EzfheonT@7@Y%VG0Ad#{{l1y1re&Re~vx#=+fOgbx?&x=TlGWmq*n3rK z@3I&q8wy15bb8*<14T#Djbn`S(Si=kY`j2o;k6ea**&T;_FW*Sn7 z9NwTCvZ-cwy}vj9cSBaFak+~Ng@U_KcL)_MlYU}tbxq}avT{mi>^C{%LFOZFm@5Y~ zyS?K`m8JV(kHQ|5mNqE2zJ9+(x;O?QTP{T?q;$#f(@mwU zysFNCvB7Kl*QSf^RKCr0nL~J%K+f>-TLhHIzJl?-s%GWz&o_4CnbReY(;o)z(M7S3 zNsp|$8nAunt)_rTStDJqs#_h3cf;M$mjmZJ>+GW|S(Tx7{Vt4qUx`aqHzqfbZf=!s zRB}pgcF}z2Q2*+F0Y;>G`6L2SSZZZr?7i#MTz&p4r=g%Oys06C_q@Vzh~AGgk)0dOxz?X$EZ0cK zE?RnIZc6Hb=T!fFmOlJMY5cqn{kdjjdXtQ`*ymK1~h$jsgFA-sFhH6VBQi4<`HrJ zEQ}|W|2Xw#n{FkO5aLE{gO*iPy0|#dL9wxEZ6|7)>c6buifIhO(7R&VGkF^xPzVSV zMl&1}KEQcO;Ekc!ExlDyeITXkxxMu6=Fk}2=6|Y%gSZYy&ug>w+gHM3C&{2NX8 zZ6zzy&>1UP_+kQ&V>i1M2n;tB?Bh&S+;FUzk6bAxZ3WV0z0oEZLHMO`AlUh4KXH;7 zHpM@AYJ*cnV($mGZw=d|jEah?kS0kFk<%54;({r|6+x$KvOOHM5QeA!5 zf1!`_!rkzyV$1h(=k_5mOwH>CpW*?3`^$6M)~9@Je&aQkn}S+jyd;g}x{j23G-G_8 zsy^vUb}nT=CYsY*yNyuVTZ(7YBV1=k2YpUrG_C6qdPS)4%K9l*oM7vE`%e98tM=uS zG2h$mfg)Xr!p+o5MPc1_V_{)%O`I`1Ht~sPlJ?z{d4pZui<$)ER7}j`6Urm!*J{Oe zmz7j}&NCHzCR(e7$*+ofRJDgs&BTqJ`vxT}uO`M*v^(mz&6n!K=w>W&= zbA=U~e3K=_P|UfDWT=o_)upew6*Z*~bDNIiG-%BGH4-Oui>Ol5p2M&UA-B)8mXt)G_Gna7)- zS9YK)Gci&#ycUsr`7Qg+z5o@vTvD>;`+wB2AGbdhNNobp?Nibvrx&p=BRQcRx6f;R z7$LQ@_EM^XzHEPyjpdKXb9sx0x-@&)?QU#vuOcfeeOs!9JU;GsieJ@)^fnvnxXn(! zG;GSLQlg!moLH}5Z^V2u<6vL9qAwm>3REJ0_c)paCHd*PY zdgV%%mFalm(JMaHOtESE49-K}dH=>$Ir}`YK4^K%%6BsQ``+2O)ms<1Z6`97#^W>MlgM-5(sBt>A~-=NLH*_s@vMB00AtQ9d7X)0gldoG+PO zT4xxVPE1U;G8Ao5ojjV@+ze*XSLmulrHWXG$~xp1D5EjsN zi3USV*XJwhJ(4wNKLnEQTHlKusSd1Nu&mnsIOF`>4Xq|oNeKmz~ctAO#7Yj@w2yo0VK>5-ihc8*WEEu%~I zI^i_ep9+LJRnbR@@-iqVRHU}ZfZccLepaSC*dY zMQ{w|s1g!H-y3HaYR&1rsPR-TD5js|vvHdvWrfi9>mcWKYOEIe-SsIFkoCe(YD+># z7MNHI6KrXsEE|5}kBxj)ce!_Od|QKsQELtA@L}Foa3i?bl+v zNux9t&G;iAcoQMY6Vh(nOG_cl2X`1IDG@69>dbUoAp9fZmHJALSLy+Sp?f?xwBwDb zUg}35R+;+@pr-Ea)Bjx!^5}-CdDAohSROZb4HG%L(^z&nvhw|3c2d(U`N7?RnWO5} z?aDg5BJ}bK-F@yC>FJp@!e(zYO1`F4)rqaR!9V~zRJLzEKpmF}fn@di2^w-T&zJ9z zte7eQ=*r_|uz41l3u9%BCdp;`bH={dXz}v}J?{sq=2tuxPF<} zYPoJdN7+_y5w}Z)&LZW=YTrzj!lEPinTx8vHm29S(yiLw&lnk6E%wo3WiDZ#d?|%2 zW!8S+tsI$4+=}@G zVhH^6vMUuNr$?5U3)I$bXryz$>G=g!@K7gqn3Sw~UmKjFW|X7y6Q65O6$zo%i*Chr z`?@zxSMkEGG<5_i`Vu*51N(3M(N{mG6_NS%Iu7TTw8PKmQOrwU=hU=5?0Rr(~Cwtet>>~3ARmayR z)7Lc{>R)Hq3=dKE-R;*7oZ&R*#QH}~J$9NGhYFWX(;8P%R?}tg__6D3@bymK`_B)S z`ktvNt*vV@;`ij^AK-0qQc^pn@Cka!!eCPpk#BMf&%S@3`0OI_{)kHWta~!ycz%4t zE9mT!B9*g1NK~|Hq4ZZrW2rP{9YQA` zEr0ZvZntK_nfWK~=qH!_fmqUqL5Zyy6eTPK7w29b0)C&M(5sNkC+r0d#o-(&3PJmt zH0#BUKbpM06gT7)U#g3eg74N{mo=GvIC3-iN#os0b{H5oW{Cc193`LSs>?BhUV=oo z&Zrpm-RalX)g89wfkM-bvjQ^Udm(qKN|3#Lghw^5D2S=ZhflY}^dc`$`L<==oZ|AN zIpml}ocf3i${ZaGcO@qF$mly%)YR0tSd>cXi46Ph+#IZ)@jbZq-K8k;aX%8f_DMex zUsj46R@pdJGpt!V*`0U)vYTc-@#a?hfq&LijYSQ5lA zCTXruP?!d(BJ-!p{o-2Sp(xKgWyC>qP|N{1hVvdTJhZ18XJ8!Nc8f5zMb>Nm`(p@( zx5jb(5cFb$AYZYtL*WZ=Vo0irL^=_{@AnU)cvbpEk1pqho-}L~-zhMG!RTHZgz9rJ ztGHI)L2p!=;fAl<$7l(>`^M9?JsmU8$_Ryav#C#XgmL8BGfZ ze9V>oda`_sjg=OilrQe{6P<+PtSbQSla-|qm*?0|w~jF`wquO}{<)ZM*|m zvcdyrXLUxTHMKHXxYg$yuH^Mo8P@Pg=V3m(Y3UC6)RH6wf~jX_!5AnJo{a00w=T+i z5G5c?MY4x$_N4te)`mIKo@M)*u2V_UXlq>iflESJ?(BI!_eSvr;5L}V4Ls_(EJb`8 z`JnrTjriGP+g7S3)3ctJdC}5`Ys*V?;I4URzYy~C*!~sjKf6+%oOR!k!U}Vhbfs(x z=d9t4%1Zv3V<2r+5xx*+nAGkn(lcXgq5^|O%Lp$U(NJ7$6-QgyO7ssV`%#(_@B$?s z1S0pZ2O3xjh;?iE*;s}0Qz=+Zb7^RU-Lz0V#r3enu}e?8 z+_w1qVx8ULO^=kn&(7~k5AcU-K)QGSqHmrOXdYTwGYG4c!VZL7m) zU5Ax0f|n|3;+O55etU1RsV5G`G2DxzbMQkiB^upj!YF~FqYQ@7?gyw<;3eU8aP70H zmUh;q;`eK`#BbDzQfwzX$sR~$e(l}z0Ziq|pPfL7wV|u43(zWoIvr!e@_{Hs^`TMS zonb=Dys;zhF4G5}gkzO+25qt{%L@%i|9hDAuoANIGlCR(&WD$zX$D!ct%{3_tu3^x z);iRoNI+ylO-<=2DD+_XH-H=Bw?r`?A0J->NG71g59m+#tE#$T2aulgb8}Dn9Q=mA zf9C>S625-Dm@ttLP+Ho(zS<=UdOxss4rtGZvp^;fFpqw#$opSoc;QJHqK`kOE@xdv zf)EL+Nu>QT6)u46k?@M;@Vg`d8GH}amYe~S%K7&|@q-YM8z1kS4c&#OVT zNqt7f5|9Mm-`@{g@&Ssp4S?};ygj*3bG=7XvkksI-257-TDt)z9z8w%;Cce+0*TjJ zgPD0yUVXJLd|i~syvlt)_-5>RMlm|fKSKTK4>H{3p%=_ zo%UJ?_^^Q%dKl3^|D*D>2DDoVrsf5<47fYKKi*;k6+vpi2glG2#dhBe5cqLn?5!H( zx+vyPIsmOITERF7Q5?$=+h#3qN7f4O7xpq%Q}B?~uDWK7qcX+V5G;w{$$`$r5LNy6 zXYfd}$n#mEC2hP7e^6ApwY4>W+V6pxjFXu)aguNpc!!aJL3}SrMHC2fV&pS1TEq}g zyy5o?)VD}H4DnrIHGBi^4MUR$Jf?HNo0@LA)I9)0zX{mtdnMOrCEmwqD!~4OqzxPc z$;&w>6cvWfC-L(wfe(1hc5jUNp6p@#D~6>wVG@ohsBlTE*MxzQn7;&tBaI7iiaDSJ z93C1fcD`K>IC0@(M?eR006z)Pyby z;*;NZN6(z1B(4T8N`2{1j?)=lF!*RpwEKXmmRs}IYzD3H?fj)*{a$Q_pvaO)Ct3VIB2CSG_3#=P&F?I|H`OsgO zWdMft`8w(19LN4|RaP(z;;o&=Q5N6_Df=Jzw;^z;-6OTOk36cRcG=5`IL zo@&AG7yoMd3j#@@*r-r6C+(P;BFBRCvRFM<%s{nVGLNy-hJdRZK zPcUs{T<6fQ)hl}fMC##BW=??5I|SsbHaCDr|1N<8d%bg>;oT3B#YiRfXko}3urS0xS0zvk18%7g^aR}X z-SzedtXe?WyadfBnnq}z!(efX_B4`;jBrBS4@|*US&HK(tFMF1oXjH{7Vw(K5AyCq zAdta_YFcEbUPR&N-mP2_&|Qw?jiRQZin1953<_A1-~6xE{I9ywF1j$~X?ZHXn*lTz zKQtSE#TbbaN266pU_Au$QHgxNK}PfS=QuF6Q94SF=4&w}9vWsGzj+vRDOh4qpnVdB<=v;~EdLFgA{H zT!uRqN-!ANlww0;W0)My@kHR?570-Da=x;Bm6Rd~em$|8(^-ea?+20lv_ zelQZZvfx!E;BA$DJ@NCvdFTKuKT%lt=tH5VOG|f)mf?J-Z7+8NF)~&%aFZiGzk)>h z=r~-Nld=8a1I6_2q@i03&DF?AFU9=2)LS;BrvZ*>P}{yH+wb_-=&h~kvNzNjl-|zF zn5-aTTlpdtEn28h+J=T6l&Gqmn3x!#%xeUC7;lQF^Z{yf0*2ywd3kwS_YeCPX2yX$ z@X6|vCZTzf=df2l0ae+dW&vJS#?w=V+xpW}bV{)(groEw_2u~D)LC{$h9oT2b1|r= zsU4K8!02M+Ll8!u1}h(kEkKz*c-`94oq8UI5aSi#quSqTH1SueMUdUm)x4UuvoJd8 zd~G|ATnc@xow&ZSNrrn^op$_8|KL^v*(Mosb#Cc!rHpIHt;U0Hr26_RVS?E3Ja4k) zrcfiNWlDf#kZ10h^)(I%_Q(Ws;(87A0du**LF}yaetvqNSzR!lVfx@Yh}KFm z$|rBW!izSD(oWiv<_;J%PzZzo4*YqAvd#B+#3zpIa{1io&oRAKc4%Wcuz9-fbQc_f zZtLJRatqc*(X4WAeM5l=g|@P>x3;ymuV0(kpw~5B=`F45=!l);Wd&nys;Oq8hU$EW zP^7Z5wiWgCVIJ_8A7fWkq^DKFd#uoQZ|uo<=SbU3fuNDOvAlKCRu4Obb)-guFezS3 zaCdw=Vb3bhZjPh^mihJS=lAcUny7pD-9}8Fk5dgZ)MqwKvaPI36=57PE@>1<*=5j0 z0P|G)o_M;$V9q*=g`w$v>AJ(OaTN5Q<=Gk66%IL3>N{DHN>}9|gL#2UAOf*o_7LuU zuH5ck?dowm=gdpxfC}eBxPV5r8(%LqH4W+423ApFKGymv;p0H?(7A;(>eMr&POogY zvsU6I2z#T8Z^XP^UVf>Ue-S6~7|li>aDHQry5e2T+X=ni*xp6Ob47oP`Byv}V(wfl z#vc;vMYf9V4Ch+9!CuE!JknA6isgg;=HXuh!FN_WfEVCzNdv*U)@LQfE#pK~I1++N zTr9CN%gr`BY~iR4zy$`Rx_6JymAatv#^=`wo*w5aY#f|yLD6yQm2Pv~!*1z0E<>eI zs+3SICM~xg>%@`mA@6o37WpeHd$ua+HYPMhA6tnSdmX9{^R&xNLD#5D^QT29)`ZQI z&g!;;8|}7lBxWrt(+szeH9od1N#Njm46+wvCO0Ef#hl@FoK{C>D9C$Anf9VN>e`-Z zaDF5+1;$Z(q`in;XlUD^Nnd4jXF}_xz=-WW8 zZ_G_H6lk{N0#E=tte*Uz?v7B*pn9$hjpGyxGvltbTRXCNG4sL`sBnn!fOKe(}4- z$~4FZnp!)uC3F%e2kriK!V@vC&jvJioNub$1QR;Zj787&F#!Cp?u=01g#2mj4nB{0 z1enXgDif*1sUr?tDeO8g_t9!MH&1Ub6})4-oUc);^<^tBK&_V!{+zhmd|u<*#H;>9 zQ(Gq|@!I9(^RjY|nx_5Ng-zAIeCYTXZ(V|FI1ENOxNwyRmv#GIcXC&wrl_E{q^aJG ziDT~P4*BfSy@LFrf=a;kbQ5G=#ChWC`rw))HaAQtEQ6o(L673_2rx^E^^01oL=gSH ztUCUJ!3;z^er5L)e7?#G;h--^JNx=lg>aOoJk$6Es($P~;PN!h=a89-&nx#mny%f4 zpPsHHCgvBM6%YoEDxKJZ$P+isL8g)OErKa6JKNlSC*Skxl!Pw;vyt$2F7CCBbv^P1 zx(2XiuxAGJ`{lf3e%0pMhk)m=pCLy_)u*eXx|T8c38*@v3#4HO3siX))M0{t%9#2V zww^M!o&1i!ht9aY-$#25kgc4B?~9cPPur}t94q1xq0f!FUo^|FGAR> zzwU7a;9}SGprjA$9O4kK?e#2roSx&~&;X|TtA`6$5r+)^c425124|+XHL3+$`@&1- zvT!`cJn#p={gc^m@mngwT$QpoDxwwZg5k$R;BK&GslPAAJ#692p~=X>Pn#+>U*pX@sM!=F>*xJ&EK~qZsT+qw(yM$*Va`{M<<`wyh=vy-?89HAw(I(q7S&Y zjW@#7oC3cr?*wD)_D0b#={=`U`*OKqMujl0CXNc&DO*AOAGqN5Ct&swYzzsY3BbjW z%nNc!Wr@@l<+v$VfF^+HleEwm59+ts*2lnlFIbpGdW)0Mw! zo0Wm{)8-;K?$(uojR&*8T8eys{dZfal?lJKXt8_>oMrjV9wY|xavI@ain2?NG=Vq8UE$&jlQUn)9BX0g8TyAfd3Vp#c6u!N4{|v>TxSCa zK;R7}Ti0mVzMH*(mq6Ji7VzmXy75

    F=`ZofiIz;W=J}h$-=OT?$RKrULw{iSON0 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 li > a { - padding-right: 46px; -} - -.o_form_uri .fa-search { - padding-left: 5px; - padding-right: 5px; -} diff --git a/attachment_preview/static/src/js/attachment_preview.js b/attachment_preview/static/src/js/attachment_preview.js index fee97da2434..3f1f6604fa6 100644 --- a/attachment_preview/static/src/js/attachment_preview.js +++ b/attachment_preview/static/src/js/attachment_preview.js @@ -6,8 +6,12 @@ odoo.define('attachment_preview', function(require) { var core = require('web.core'); var _t = core._t; + var qweb = core.qweb; var Sidebar = require('web.Sidebar'); var basic_fields = require('web.basic_fields'); + var FormRenderer = require('web.FormRenderer'); + var FormController = require('web.FormController'); + var Widget = require('web.Widget'); var AttachmentPreviewMixin = { canPreview: function(extension) { @@ -18,68 +22,126 @@ odoo.define('attachment_preview', function(require) { 'fods', 'ots' ]) > -1; }, - showPreview: function(attachment_id, attachment_url, attachment_extension, attachment_title) { + + getUrl: function(attachment_id, attachment_url, attachment_extension, attachment_title) { var url = (window.location.origin || '') + '/attachment_preview/static/lib/ViewerJS/index.html' + '?type=' + encodeURIComponent(attachment_extension) + '&title=' + encodeURIComponent(attachment_title) + '#' + attachment_url.replace(window.location.origin, ''); - window.open(url); - } + return url; + }, + + showPreview: function(attachment_id, attachment_url, attachment_extension, attachment_title, split_screen) { + var url = this.getUrl(attachment_id, attachment_url, attachment_extension, attachment_title); + if (split_screen) { + this.trigger_up('onAttachmentPreview', {url: url}); + } else { + window.open(url); + } + }, }; Sidebar.include(AttachmentPreviewMixin); Sidebar.include({ + events: _.extend({}, Sidebar.prototype.events, { + 'click .o_sidebar_preview_attachment': '_onPreviewAttachment' + }), + + previewableAttachments: null, + _redraw: function () { this._super.apply(this, arguments); - this.$('.o_sidebar_preview_attachment') - .click(this._onPreviewAttachment.bind(this)); - this.updatePreviewButtons(); + this.getPreviewableAttachments().done(function(atts) { + this.previewableAttachments = atts; + this.updatePreviewButtons(atts); + this.trigger_up('setPreviewableAttachments', {attachments: atts}); + }.bind(this)); }, + _onPreviewAttachment: function(event) { event.preventDefault(); var self = this, $target = $(event.currentTarget), + split_screen = $target.attr('data-target') != 'new', attachment_id = parseInt($target.attr('data-id'), 10), attachment_url = $target.attr('data-url'), attachment_extension = $target.attr('data-extension'), attachment_title = $target.attr('data-original-title'); if(attachment_extension) { - this.showPreview(attachment_id, attachment_url, attachment_extension, attachment_title); + this.showPreview(attachment_id, attachment_url, attachment_extension, attachment_title, split_screen); } else { this._rpc({ model: 'ir.attachment', method: 'get_attachment_extension', args: [attachment_id] }).then(function(extension) { - self.showPreview(attachment_id, attachment_url, extension); + self.showPreview(attachment_id, attachment_url, extension, null, split_screen); }); } }, - updatePreviewButtons: function() { + + getPreviewableAttachments: function() { var self = this; - return this._rpc({ + var deferred = $.Deferred(); + + var $items = this.$el.find('.o_sidebar_preview_attachment'); + var attachments = _.object($items.map(function() { + return parseInt($(this).attr('data-id'), 10); + }), $items.map(function() { + return { + url: $(this).attr('data-url'), + extension: $(this).attr('data-extension'), + title: $(this).attr('data-original-title'), + }; + })); + + this._rpc({ model: 'ir.attachment', method: 'get_attachment_extension', args: [ - this.$el.find('.o_sidebar_preview_attachment').map(function() { - return parseInt($(this).attr('data-id'), 10); - }).get() + _.map(_.keys(attachments), function(id) { + return parseInt(id, 10); + }) ] }).then(function(extensions) { - _(extensions).each(function(extension, id) { - var $element = self.$el.find('span.o_sidebar_preview_attachment[data-id="' + id + '"]'); - if (self.canPreview(extension)) { - $element.attr('data-extension', extension); - } else { - $element.remove(); + var reviewableAttachments = _.map(_.keys(_.pick(extensions, function(extension, id) { + return self.canPreview(extension); + })), function(id) { + return { + id: id, + url: attachments[id]['url'], + extension: extensions[id], + title: attachments[id]['title'], + previewUrl: self.getUrl( + id, + attachments[id]['url'], + extensions[id], + id + ' - ' + attachments[id]['title'] + ) } }); + deferred.resolve(reviewableAttachments); + }, function() { + deferred.reject(); }); + return deferred.promise(); }, + updatePreviewButtons: function(previewableAttachments) { + this.$el.find('.o_sidebar_preview_attachment').each(function() { + var $this = $(this); + var id = $this.attr('data-id'); + var att = _.findWhere(previewableAttachments, {id: id}); + if (att) { + $this.attr('data-extension', att.extension); + } else { + $this.remove(); + } + }); + }, }); basic_fields.FieldBinaryFile.include(AttachmentPreviewMixin); @@ -87,6 +149,7 @@ odoo.define('attachment_preview', function(require) { events: _.extend({}, basic_fields.FieldBinaryFile.prototype.events, { 'click .fa-search': '_onPreview' }), + _renderReadonly: function () { var self = this; this._super.apply(this, arguments); @@ -96,6 +159,7 @@ odoo.define('attachment_preview', function(require) { } }); }, + _renderPreviewButton: function(extension) { this.$previewBtn = $(""); this.$previewBtn.addClass('fa fa-search'); @@ -103,6 +167,7 @@ odoo.define('attachment_preview', function(require) { this.$previewBtn.attr('data-extension', extension); this.$el.find('.fa-download').after(this.$previewBtn); }, + _getBinaryExtension: function () { return this._rpc({ model: 'ir.attachment', @@ -115,6 +180,7 @@ odoo.define('attachment_preview', function(require) { ] }); }, + _onPreview: function(event) { this.showPreview( null, @@ -125,12 +191,158 @@ odoo.define('attachment_preview', function(require) { this.recordData.id ), $(event.currentTarget).attr('data-extension'), - _.str.sprintf(_t('Preview %s'), this.field.string) + _.str.sprintf(_t('Preview %s'), this.field.string), + false + ); + } + }); + + var AttachmentPreviewWidget = Widget.extend({ + template: 'attachment_preview.AttachmentPreviewWidget', + activeIndex: 0, + attachments: null, + + events: { + 'click .attachment_preview_close': '_onCloseClick', + 'click .attachment_preview_previous': '_onPreviousClick', + 'click .attachment_preview_next': '_onNextClick', + 'click .attachment_preview_popout': '_onPopoutClick', + }, + + start: function () { + var res = this._super.apply(this, arguments); + this.$overlay = this.$el.find('.attachment_preview_overlay'); + this.$iframe = this.$el.find('.attachment_preview_iframe'); + this.$current = this.$el.find('.attachment_preview_current'); + return res; + }, + + _onCloseClick: function () { + this.hide(); + }, + + _onPreviousClick: function () { + this.previous(); + }, + + _onNextClick: function () { + this.next(); + }, + + _onPopoutClick: function () { + if (!this.attachments[this.activeIndex]) { + return; + } + + window.open(this.attachments[this.activeIndex].previewUrl); + }, + + next: function() { + var index = this.activeIndex + 1; + if (index >= this.attachments.length) { + index = 0; + } + this.activeIndex = index; + this.updatePaginator(); + this.loadPreview(); + }, + + previous: function() { + var index = this.activeIndex - 1; + if (index < 0) { + index = this.attachments.length - 1; + } + this.activeIndex = index; + this.updatePaginator(); + this.loadPreview(); + }, + + show: function () { + this.$el.removeClass('hidden'); + this.trigger('shown'); + }, + + hide: function () { + this.$el.addClass('hidden'); + this.trigger('hidden'); + }, + + updatePaginator: function() { + var value = _.str.sprintf('%s / %s', this.activeIndex + 1, this.attachments.length); + this.$current.html(value); + }, + + loadPreview: function() { + if (this.attachments.length == 0) { + this.$iframe.attr('src', 'about:blank'); + return; + } + + var att = this.attachments[this.activeIndex]; + this.$iframe.attr('src', att.previewUrl); + }, + + setAttachments: function(attachments) { + this.attachments = attachments; + this.activeIndex = 0; + this.updatePaginator(); + this.loadPreview(); + } + }); + + FormRenderer.include({ + attachmentPreviewWidget: null, + + init: function() { + var res = this._super.apply(this, arguments); + this.attachmentPreviewWidget = new AttachmentPreviewWidget(this); + this.attachmentPreviewWidget.on('hidden', this, this._attachmentPreviewWidgetHidden); + return res; + }, + + start: function () { + this._super.apply(this, arguments); + this.attachmentPreviewWidget.insertAfter(this.$el); + }, + + _attachmentPreviewWidgetHidden: function() { + this.$el.removeClass('attachment_preview'); + }, + + showAttachmentPreviewWidget: function () { + this.$el.addClass('attachment_preview'); + this.attachmentPreviewWidget.setAttachments( + this.getParent().sidebar.previewableAttachments + ); + this.attachmentPreviewWidget.show(); + }, + + on_detach_callback: function () { + this.attachmentPreviewWidget.hide(); + return this._super.apply(this, arguments); + } + + }); + + FormController.include({ + custom_events: _.extend({}, FormController.prototype.custom_events, { + onAttachmentPreview: '_onAttachmentPreview', + setPreviewableAttachments: '_setPreviewableAttachments' + }), + + _onAttachmentPreview: function (event) { + this.renderer.showAttachmentPreviewWidget(); + }, + + _setPreviewableAttachments: function(event) { + this.renderer.attachmentPreviewWidget.setAttachments( + event.data.attachments ); } }); return { - AttachmentPreviewMixin: AttachmentPreviewMixin + AttachmentPreviewMixin: AttachmentPreviewMixin, + AttachmentPreviewWidget: AttachmentPreviewWidget }; }); diff --git a/attachment_preview/static/src/less/attachment_preview.less b/attachment_preview/static/src/less/attachment_preview.less new file mode 100644 index 00000000000..17c42ac1665 --- /dev/null +++ b/attachment_preview/static/src/less/attachment_preview.less @@ -0,0 +1,56 @@ +.o_cp_sidebar { + li .o_sidebar_preview_attachment { + position: absolute; + top: 5px; + right: 26px; + background-color: #FFF; + + &.o_sidebar_preview_attachment_new_tab { + right: 43px; + } + } + + .open .dropdown-menu > li > a { + padding-right: 60px; + } +} + +.o_form_uri .fa-search { + padding-left: 5px; + padding-right: 5px; +} + +/* Preview widget */ + +.o_form_view.attachment_preview { + width: 60%; + float: left; +} + +.o_form_view + .attachment_preview_widget { + width: 40%; + height: 100%; + float: right; + position: relative; + + > .attachment_preview_iframe { + width: 100%; + height: calc(~"100% - 30px"); + float: left; + } + + .attachment_preview_buttons { + padding: 4px; + float: left; + width: 100%; + background-color: #FFF; + border-left: 1px solid @gray-lighter-dark; + + button { + min-width: 25px; + min-height: 25px; + padding-top: 2px; + padding-bottom: 2px; + } + } +} diff --git a/attachment_preview/static/src/xml/attachment_preview.xml b/attachment_preview/static/src/xml/attachment_preview.xml index e110f52c860..fd2a9665723 100644 --- a/attachment_preview/static/src/xml/attachment_preview.xml +++ b/attachment_preview/static/src/xml/attachment_preview.xml @@ -7,6 +7,29 @@ t-att-data-id="item.id" t-att-data-url="item.url" t-attf-title="Preview #{item.name}"/> + + + + +

    +
    diff --git a/attachment_preview/templates/assets.xml b/attachment_preview/templates/assets.xml index 1b94f3e90b4..8caf8f95382 100644 --- a/attachment_preview/templates/assets.xml +++ b/attachment_preview/templates/assets.xml @@ -3,7 +3,7 @@ From 339a461627129a65cb5c0a476007092c5a2a2e87 Mon Sep 17 00:00:00 2001 From: mreficent Date: Mon, 11 Mar 2019 17:36:40 +0100 Subject: [PATCH 19/41] [FIX] pylint/javascript-lint --- .../i18n/attachment_preview.pot | 4 +- attachment_preview/i18n/de.po | 4 +- attachment_preview/i18n/es.po | 4 +- attachment_preview/i18n/it.po | 4 +- attachment_preview/i18n/nl.po | 4 +- attachment_preview/i18n/pt_PT.po | 4 +- attachment_preview/i18n/sl.po | 4 +- attachment_preview/i18n/zh_CN.po | 4 +- .../static/description/index.html | 2 +- .../static/src/js/attachment_preview.js | 103 +++++++++--------- .../static/src/js/viewerjs_tweaks.js | 6 +- 11 files changed, 71 insertions(+), 72 deletions(-) diff --git a/attachment_preview/i18n/attachment_preview.pot b/attachment_preview/i18n/attachment_preview.pot index dd0ef1da6c7..3a310898755 100644 --- a/attachment_preview/i18n/attachment_preview.pot +++ b/attachment_preview/i18n/attachment_preview.pot @@ -15,8 +15,8 @@ msgstr "" #. module: attachment_preview #. openerp-web -#: code:addons/attachment_preview/static/src/js/attachment_preview.js:166 -#: code:addons/attachment_preview/static/src/js/attachment_preview.js:194 +#: code:addons/attachment_preview/static/src/js/attachment_preview.js:165 +#: code:addons/attachment_preview/static/src/js/attachment_preview.js:193 #, python-format msgid "Preview %s" msgstr "" diff --git a/attachment_preview/i18n/de.po b/attachment_preview/i18n/de.po index f0ced98223e..30fe2d08dba 100644 --- a/attachment_preview/i18n/de.po +++ b/attachment_preview/i18n/de.po @@ -21,8 +21,8 @@ msgstr "" #. module: attachment_preview #. openerp-web -#: code:addons/attachment_preview/static/src/js/attachment_preview.js:166 -#: code:addons/attachment_preview/static/src/js/attachment_preview.js:194 +#: code:addons/attachment_preview/static/src/js/attachment_preview.js:165 +#: code:addons/attachment_preview/static/src/js/attachment_preview.js:193 #, python-format msgid "Preview %s" msgstr "Vorschau %s" diff --git a/attachment_preview/i18n/es.po b/attachment_preview/i18n/es.po index 83b74ff4aca..aa4ee6ea0ba 100644 --- a/attachment_preview/i18n/es.po +++ b/attachment_preview/i18n/es.po @@ -21,8 +21,8 @@ msgstr "" #. module: attachment_preview #. openerp-web -#: code:addons/attachment_preview/static/src/js/attachment_preview.js:166 -#: code:addons/attachment_preview/static/src/js/attachment_preview.js:194 +#: code:addons/attachment_preview/static/src/js/attachment_preview.js:165 +#: code:addons/attachment_preview/static/src/js/attachment_preview.js:193 #, python-format msgid "Preview %s" msgstr "Previsualizar %s" diff --git a/attachment_preview/i18n/it.po b/attachment_preview/i18n/it.po index 6b45e9e348a..2d2f6552719 100644 --- a/attachment_preview/i18n/it.po +++ b/attachment_preview/i18n/it.po @@ -21,8 +21,8 @@ msgstr "" #. module: attachment_preview #. openerp-web -#: code:addons/attachment_preview/static/src/js/attachment_preview.js:166 -#: code:addons/attachment_preview/static/src/js/attachment_preview.js:194 +#: code:addons/attachment_preview/static/src/js/attachment_preview.js:165 +#: code:addons/attachment_preview/static/src/js/attachment_preview.js:193 #, python-format msgid "Preview %s" msgstr "Anteprima %s" diff --git a/attachment_preview/i18n/nl.po b/attachment_preview/i18n/nl.po index 70c32fa7e66..987639b85f9 100644 --- a/attachment_preview/i18n/nl.po +++ b/attachment_preview/i18n/nl.po @@ -20,8 +20,8 @@ msgstr "" #. module: attachment_preview #. openerp-web -#: code:addons/attachment_preview/static/src/js/attachment_preview.js:166 -#: code:addons/attachment_preview/static/src/js/attachment_preview.js:194 +#: code:addons/attachment_preview/static/src/js/attachment_preview.js:165 +#: code:addons/attachment_preview/static/src/js/attachment_preview.js:193 #, python-format msgid "Preview %s" msgstr "Voorbeeld %s" diff --git a/attachment_preview/i18n/pt_PT.po b/attachment_preview/i18n/pt_PT.po index 70420cf60d1..f41f05b0378 100644 --- a/attachment_preview/i18n/pt_PT.po +++ b/attachment_preview/i18n/pt_PT.po @@ -21,8 +21,8 @@ msgstr "" #. module: attachment_preview #. openerp-web -#: code:addons/attachment_preview/static/src/js/attachment_preview.js:166 -#: code:addons/attachment_preview/static/src/js/attachment_preview.js:194 +#: code:addons/attachment_preview/static/src/js/attachment_preview.js:165 +#: code:addons/attachment_preview/static/src/js/attachment_preview.js:193 #, python-format msgid "Preview %s" msgstr "Antever %s" diff --git a/attachment_preview/i18n/sl.po b/attachment_preview/i18n/sl.po index 4fdc122cacc..729feb18d04 100644 --- a/attachment_preview/i18n/sl.po +++ b/attachment_preview/i18n/sl.po @@ -22,8 +22,8 @@ msgstr "" #. module: attachment_preview #. openerp-web -#: code:addons/attachment_preview/static/src/js/attachment_preview.js:166 -#: code:addons/attachment_preview/static/src/js/attachment_preview.js:194 +#: code:addons/attachment_preview/static/src/js/attachment_preview.js:165 +#: code:addons/attachment_preview/static/src/js/attachment_preview.js:193 #, python-format msgid "Preview %s" msgstr "Predogled %s" diff --git a/attachment_preview/i18n/zh_CN.po b/attachment_preview/i18n/zh_CN.po index 3190fbc83f9..116fe5c3868 100644 --- a/attachment_preview/i18n/zh_CN.po +++ b/attachment_preview/i18n/zh_CN.po @@ -21,8 +21,8 @@ msgstr "" #. module: attachment_preview #. openerp-web -#: code:addons/attachment_preview/static/src/js/attachment_preview.js:166 -#: code:addons/attachment_preview/static/src/js/attachment_preview.js:194 +#: code:addons/attachment_preview/static/src/js/attachment_preview.js:165 +#: code:addons/attachment_preview/static/src/js/attachment_preview.js:193 #, python-format msgid "Preview %s" msgstr "预览 %s" diff --git a/attachment_preview/static/description/index.html b/attachment_preview/static/description/index.html index 28ae93760c0..3104fb6a5a4 100644 --- a/attachment_preview/static/description/index.html +++ b/attachment_preview/static/description/index.html @@ -3,7 +3,7 @@ - + Preview attachments -
    -

    Preview attachments

    +
    + + +Odoo Community Association + +
    +

    Preview attachments

    -

    Beta License: AGPL-3 OCA/knowledge Translate me on Weblate Try me on Runboat

    +

    Beta License: AGPL-3 OCA/knowledge Translate me on Weblate Try me on Runboat

    This addon allows to preview attachments supported by http://viewerjs.org.

    Currently, that’s most Libreoffice files and PDFs.

    @@ -389,13 +394,13 @@

    Preview attachments

-

Installation

+

Installation

For filetype recognition, you’ll get the best results by installing python-magic:

sudo apt-get install python-magic

-

Usage

+

Usage

The module adds a little print preview icon right of download links for attachments or binary fields. When a preview is opened from the attachments menu it’s shown next to the form view. From this screen you @@ -405,7 +410,7 @@

Usage

Screenshot navigator

-

Bug Tracker

+

Bug Tracker

Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us to smash it by providing a detailed and welcomed @@ -413,23 +418,23 @@

Bug Tracker

Do not contact contributors directly about support or help with technical issues.

-

Credits

+

Credits

-

Authors

+

Authors

  • Therp BV
  • Onestein
-

Maintainers

+

Maintainers

This module is maintained by the OCA.

Odoo Community Association @@ -442,5 +447,6 @@

Maintainers

+ diff --git a/setup/_metapackage/pyproject.toml b/setup/_metapackage/pyproject.toml index 0b74c813ec6..db54959e871 100644 --- a/setup/_metapackage/pyproject.toml +++ b/setup/_metapackage/pyproject.toml @@ -1,7 +1,8 @@ [project] name = "odoo-addons-oca-knowledge" -version = "18.0.20251010.0" +version = "18.0.20251231.0" dependencies = [ + "odoo-addon-attachment_preview==18.0.*", "odoo-addon-attachment_zipped_download==18.0.*", "odoo-addon-document_knowledge==18.0.*", "odoo-addon-document_page==18.0.*",