From 252e5527368a5220e7eaa42325b5302a7fbe5c32 Mon Sep 17 00:00:00 2001 From: Paul Adenot Date: Tue, 3 Sep 2013 10:52:55 +0200 Subject: [PATCH 01/64] b=907986 part 3 fold-in 1 remove normalize of unit vector r=padenot --- content/media/webaudio/PannerNode.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/content/media/webaudio/PannerNode.cpp b/content/media/webaudio/PannerNode.cpp index eda79dd31a2..3c9c3c9edcc 100644 --- a/content/media/webaudio/PannerNode.cpp +++ b/content/media/webaudio/PannerNode.cpp @@ -444,11 +444,8 @@ PannerNodeEngine::ComputeConeGain() ThreeDPoint sourceToListener = mListenerPosition - mPosition; sourceToListener.Normalize(); - ThreeDPoint normalizedSourceOrientation = mOrientation; - normalizedSourceOrientation.Normalize(); - // Angle between the source orientation vector and the source-listener vector - double dotProduct = sourceToListener.DotProduct(normalizedSourceOrientation); + double dotProduct = sourceToListener.DotProduct(mOrientation); double angle = 180 * acos(dotProduct) / M_PI; double absAngle = fabs(angle); From e87579deec559b83d4ff11c199e585c8028a0fb2 Mon Sep 17 00:00:00 2001 From: Jan de Mooij Date: Tue, 3 Sep 2013 11:12:35 +0200 Subject: [PATCH 02/64] Bug 911370 - Don't leak IonScript if IonCode allocation fails in CodeGenerator::link. r=bhackett --- js/src/jit/CodeGenerator.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp index 5e21050cdee..0affeb8c4cd 100644 --- a/js/src/jit/CodeGenerator.cpp +++ b/js/src/jit/CodeGenerator.cpp @@ -5568,8 +5568,12 @@ CodeGenerator::link() IonCode *code = (executionMode == SequentialExecution) ? linker.newCodeForIonScript(cx) : linker.newCode(cx, JSC::ION_CODE); - if (!code) + if (!code) { + // Use js_free instead of IonScript::Destroy: the cache list and + // backedge list are still uninitialized. + js_free(ionScript); return false; + } JSScript *script = gen->info().script(); JS_ASSERT(!HasIonScript(script, executionMode)); From c93024d7946c117558c73aa74569ff88d5e8021a Mon Sep 17 00:00:00 2001 From: Makoto Kato Date: Tue, 3 Sep 2013 18:39:35 +0900 Subject: [PATCH 03/64] Bug 911914 - Cannot build BionicGlue.cpp with --enable-android-libstdcxx. r=glandium --- mozglue/build/BionicGlue.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mozglue/build/BionicGlue.cpp b/mozglue/build/BionicGlue.cpp index 7ed0127ab54..7904c2a9774 100644 --- a/mozglue/build/BionicGlue.cpp +++ b/mozglue/build/BionicGlue.cpp @@ -102,7 +102,7 @@ extern "C" NS_EXPORT pid_t WRAP(fork)(void) { pid_t pid; - for (std::vector::reverse_iterator it = atfork.rbegin(); + for (auto it = atfork.rbegin(); it < atfork.rend(); ++it) if (it->prepare) it->prepare(); @@ -110,13 +110,13 @@ WRAP(fork)(void) switch ((pid = __fork())) { case 0: cpuacct_add(getuid()); - for (std::vector::iterator it = atfork.begin(); + for (auto it = atfork.begin(); it < atfork.end(); ++it) if (it->child) it->child(); break; default: - for (std::vector::iterator it = atfork.begin(); + for (auto it = atfork.begin(); it < atfork.end(); ++it) if (it->parent) it->parent(); From c9c36dc4884f9472da5629dfaaeaee03f5f75e48 Mon Sep 17 00:00:00 2001 From: Peter Van der Beken Date: Fri, 23 Aug 2013 23:11:30 +0200 Subject: [PATCH 04/64] Bug 908997 - Simplify XPathEvaluator - move files and rename class. r=bz. --HG-- rename : content/xslt/src/xpath/nsXPathEvaluator.cpp => content/xslt/src/xpath/XPathEvaluator.cpp rename : content/xslt/src/xpath/nsXPathEvaluator.h => content/xslt/src/xpath/XPathEvaluator.h extra : rebase_source : 590597171603854196bd6f6377753dbd34fd0658 --- ...sXPathEvaluator.cpp => XPathEvaluator.cpp} | 133 +++++++++--------- .../{nsXPathEvaluator.h => XPathEvaluator.h} | 34 ++--- content/xslt/src/xpath/moz.build | 6 +- dom/bindings/Bindings.conf | 2 - layout/build/nsLayoutModule.cpp | 6 +- 5 files changed, 94 insertions(+), 87 deletions(-) rename content/xslt/src/xpath/{nsXPathEvaluator.cpp => XPathEvaluator.cpp} (67%) rename content/xslt/src/xpath/{nsXPathEvaluator.h => XPathEvaluator.h} (80%) diff --git a/content/xslt/src/xpath/nsXPathEvaluator.cpp b/content/xslt/src/xpath/XPathEvaluator.cpp similarity index 67% rename from content/xslt/src/xpath/nsXPathEvaluator.cpp rename to content/xslt/src/xpath/XPathEvaluator.cpp index 86e90399031..c711fa3c4e2 100644 --- a/content/xslt/src/xpath/nsXPathEvaluator.cpp +++ b/content/xslt/src/xpath/XPathEvaluator.cpp @@ -3,7 +3,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include "nsXPathEvaluator.h" +#include "XPathEvaluator.h" #include "nsCOMPtr.h" #include "nsIAtom.h" #include "nsXPathExpression.h" @@ -21,18 +21,23 @@ #include "nsContentUtils.h" #include "mozilla/dom/XPathEvaluatorBinding.h" -using namespace mozilla; -using namespace mozilla::dom; +extern nsresult +TX_ResolveFunctionCallXPCOM(const nsCString &aContractID, int32_t aNamespaceID, + nsIAtom *aName, nsISupports *aState, + FunctionCall **aFunction); + +namespace mozilla { +namespace dom { // txIParseContext implementation -class nsXPathEvaluatorParseContext : public txIParseContext +class XPathEvaluatorParseContext : public txIParseContext { public: - nsXPathEvaluatorParseContext(nsIDOMXPathNSResolver* aResolver, - nsTArray *aNamespaceIDs, - nsTArray *aContractIDs, - nsCOMArray *aState, - bool aIsCaseSensitive) + XPathEvaluatorParseContext(nsIDOMXPathNSResolver* aResolver, + nsTArray *aNamespaceIDs, + nsTArray *aContractIDs, + nsCOMArray *aState, + bool aIsCaseSensitive) : mResolver(aResolver), mNamespaceIDs(aNamespaceIDs), mContractIDs(aContractIDs), @@ -65,19 +70,19 @@ private: bool mIsCaseSensitive; }; -NS_IMPL_AGGREGATED(nsXPathEvaluator) -NS_INTERFACE_MAP_BEGIN_AGGREGATED(nsXPathEvaluator) +NS_IMPL_AGGREGATED(XPathEvaluator) +NS_INTERFACE_MAP_BEGIN_AGGREGATED(XPathEvaluator) NS_INTERFACE_MAP_ENTRY(nsIDOMXPathEvaluator) NS_INTERFACE_MAP_ENTRY(nsIXPathEvaluatorInternal) NS_INTERFACE_MAP_END -nsXPathEvaluator::nsXPathEvaluator(nsISupports *aOuter) +XPathEvaluator::XPathEvaluator(nsISupports *aOuter) { NS_INIT_AGGREGATED(aOuter); } nsresult -nsXPathEvaluator::Init() +XPathEvaluator::Init() { nsCOMPtr document = do_QueryInterface(fOuter); @@ -85,17 +90,17 @@ nsXPathEvaluator::Init() } NS_IMETHODIMP -nsXPathEvaluator::CreateExpression(const nsAString & aExpression, - nsIDOMXPathNSResolver *aResolver, - nsIDOMXPathExpression **aResult) +XPathEvaluator::CreateExpression(const nsAString & aExpression, + nsIDOMXPathNSResolver *aResolver, + nsIDOMXPathExpression **aResult) { return CreateExpression(aExpression, aResolver, (nsTArray*)nullptr, nullptr, nullptr, aResult); } NS_IMETHODIMP -nsXPathEvaluator::CreateNSResolver(nsIDOMNode *aNodeResolver, - nsIDOMXPathNSResolver **aResult) +XPathEvaluator::CreateNSResolver(nsIDOMNode *aNodeResolver, + nsIDOMXPathNSResolver **aResult) { NS_ENSURE_ARG(aNodeResolver); if (!nsContentUtils::CanCallerAccess(aNodeResolver)) @@ -109,12 +114,12 @@ nsXPathEvaluator::CreateNSResolver(nsIDOMNode *aNodeResolver, } NS_IMETHODIMP -nsXPathEvaluator::Evaluate(const nsAString & aExpression, - nsIDOMNode *aContextNode, - nsIDOMXPathNSResolver *aResolver, - uint16_t aType, - nsISupports *aInResult, - nsISupports **aResult) +XPathEvaluator::Evaluate(const nsAString & aExpression, + nsIDOMNode *aContextNode, + nsIDOMXPathNSResolver *aResolver, + uint16_t aType, + nsISupports *aInResult, + nsISupports **aResult) { nsCOMPtr expression; nsresult rv = CreateExpression(aExpression, aResolver, @@ -126,19 +131,19 @@ nsXPathEvaluator::Evaluate(const nsAString & aExpression, NS_IMETHODIMP -nsXPathEvaluator::SetDocument(nsIDOMDocument* aDocument) +XPathEvaluator::SetDocument(nsIDOMDocument* aDocument) { mDocument = do_GetWeakReference(aDocument); return NS_OK; } NS_IMETHODIMP -nsXPathEvaluator::CreateExpression(const nsAString & aExpression, - nsIDOMXPathNSResolver *aResolver, - nsTArray *aNamespaceURIs, - nsTArray *aContractIDs, - nsCOMArray *aState, - nsIDOMXPathExpression **aResult) +XPathEvaluator::CreateExpression(const nsAString & aExpression, + nsIDOMXPathNSResolver *aResolver, + nsTArray *aNamespaceURIs, + nsTArray *aContractIDs, + nsCOMArray *aState, + nsIDOMXPathExpression **aResult) { nsTArray namespaceIDs; if (aNamespaceURIs) { @@ -168,12 +173,12 @@ nsXPathEvaluator::CreateExpression(const nsAString & aExpression, } nsresult -nsXPathEvaluator::CreateExpression(const nsAString & aExpression, - nsIDOMXPathNSResolver *aResolver, - nsTArray *aNamespaceIDs, - nsTArray *aContractIDs, - nsCOMArray *aState, - nsIDOMXPathExpression **aResult) +XPathEvaluator::CreateExpression(const nsAString & aExpression, + nsIDOMXPathNSResolver *aResolver, + nsTArray *aNamespaceIDs, + nsTArray *aContractIDs, + nsCOMArray *aState, + nsIDOMXPathExpression **aResult) { nsresult rv; if (!mRecycler) { @@ -187,9 +192,9 @@ nsXPathEvaluator::CreateExpression(const nsAString & aExpression, } nsCOMPtr doc = do_QueryReferent(mDocument); - nsXPathEvaluatorParseContext pContext(aResolver, aNamespaceIDs, - aContractIDs, aState, - !(doc && doc->IsHTML())); + XPathEvaluatorParseContext pContext(aResolver, aNamespaceIDs, + aContractIDs, aState, + !(doc && doc->IsHTML())); nsAutoPtr expression; rv = txExprParser::createExpr(PromiseFlatString(aExpression), &pContext, @@ -214,25 +219,25 @@ nsXPathEvaluator::CreateExpression(const nsAString & aExpression, } JSObject* -nsXPathEvaluator::WrapObject(JSContext* aCx, JS::Handle aScope) +XPathEvaluator::WrapObject(JSContext* aCx, JS::Handle aScope) { return dom::XPathEvaluatorBinding::Wrap(aCx, aScope, this); } /* static */ -already_AddRefed -nsXPathEvaluator::Constructor(const GlobalObject& aGlobal, - ErrorResult& rv) +already_AddRefed +XPathEvaluator::Constructor(const GlobalObject& aGlobal, + ErrorResult& rv) { - nsRefPtr newObj = new nsXPathEvaluator(nullptr); + nsRefPtr newObj = new XPathEvaluator(nullptr); newObj->Init(); return newObj.forget(); } already_AddRefed -nsXPathEvaluator::CreateExpression(const nsAString& aExpression, - nsIDOMXPathNSResolver* aResolver, - ErrorResult& rv) +XPathEvaluator::CreateExpression(const nsAString& aExpression, + nsIDOMXPathNSResolver* aResolver, + ErrorResult& rv) { nsCOMPtr expr; rv = CreateExpression(aExpression, aResolver, getter_AddRefs(expr)); @@ -240,8 +245,8 @@ nsXPathEvaluator::CreateExpression(const nsAString& aExpression, } already_AddRefed -nsXPathEvaluator::CreateNSResolver(nsINode* aNodeResolver, - ErrorResult& rv) +XPathEvaluator::CreateNSResolver(nsINode* aNodeResolver, + ErrorResult& rv) { nsCOMPtr nodeResolver = do_QueryInterface(aNodeResolver); nsCOMPtr res; @@ -250,9 +255,9 @@ nsXPathEvaluator::CreateNSResolver(nsINode* aNodeResolver, } already_AddRefed -nsXPathEvaluator::Evaluate(const nsAString& aExpression, nsINode* aContextNode, - nsIDOMXPathNSResolver* aResolver, uint16_t aType, - nsISupports* aResult, ErrorResult& rv) +XPathEvaluator::Evaluate(const nsAString& aExpression, nsINode* aContextNode, + nsIDOMXPathNSResolver* aResolver, uint16_t aType, + nsISupports* aResult, ErrorResult& rv) { nsCOMPtr contextNode = do_QueryInterface(aContextNode); nsCOMPtr res; @@ -263,11 +268,11 @@ nsXPathEvaluator::Evaluate(const nsAString& aExpression, nsINode* aContextNode, /* - * Implementation of txIParseContext private to nsXPathEvaluator, based on a + * Implementation of txIParseContext private to XPathEvaluator, based on a * nsIDOMXPathNSResolver */ -nsresult nsXPathEvaluatorParseContext::resolveNamespacePrefix +nsresult XPathEvaluatorParseContext::resolveNamespacePrefix (nsIAtom* aPrefix, int32_t& aID) { aID = kNameSpaceID_Unknown; @@ -299,15 +304,10 @@ nsresult nsXPathEvaluatorParseContext::resolveNamespacePrefix return nsContentUtils::NameSpaceManager()->RegisterNameSpace(ns, aID); } -extern nsresult -TX_ResolveFunctionCallXPCOM(const nsCString &aContractID, int32_t aNamespaceID, - nsIAtom *aName, nsISupports *aState, - FunctionCall **aFunction); - nsresult -nsXPathEvaluatorParseContext::resolveFunctionCall(nsIAtom* aName, - int32_t aID, - FunctionCall** aFn) +XPathEvaluatorParseContext::resolveFunctionCall(nsIAtom* aName, + int32_t aID, + FunctionCall** aFn) { nsresult rv = NS_ERROR_XPATH_UNKNOWN_FUNCTION; @@ -326,12 +326,15 @@ nsXPathEvaluatorParseContext::resolveFunctionCall(nsIAtom* aName, return rv; } -bool nsXPathEvaluatorParseContext::caseInsensitiveNameTests() +bool XPathEvaluatorParseContext::caseInsensitiveNameTests() { return !mIsCaseSensitive; } void -nsXPathEvaluatorParseContext::SetErrorOffset(uint32_t aOffset) +XPathEvaluatorParseContext::SetErrorOffset(uint32_t aOffset) { } + +} // namespace dom +} // namespace mozilla diff --git a/content/xslt/src/xpath/nsXPathEvaluator.h b/content/xslt/src/xpath/XPathEvaluator.h similarity index 80% rename from content/xslt/src/xpath/nsXPathEvaluator.h rename to content/xslt/src/xpath/XPathEvaluator.h index 47a82ba0390..967f434d91f 100644 --- a/content/xslt/src/xpath/nsXPathEvaluator.h +++ b/content/xslt/src/xpath/XPathEvaluator.h @@ -3,8 +3,8 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#ifndef nsXPathEvaluator_h__ -#define nsXPathEvaluator_h__ +#ifndef mozilla_dom_XPathEvaluator_h +#define mozilla_dom_XPathEvaluator_h #include "nsIDOMXPathEvaluator.h" #include "nsIXPathEvaluatorInternal.h" @@ -17,21 +17,21 @@ #include "mozilla/Attributes.h" #include "mozilla/ErrorResult.h" +class nsINode; + namespace mozilla { namespace dom { + class GlobalObject; -} -} -class nsINode; /** * A class for evaluating an XPath expression string */ -class nsXPathEvaluator MOZ_FINAL : public nsIDOMXPathEvaluator, - public nsIXPathEvaluatorInternal +class XPathEvaluator MOZ_FINAL : public nsIDOMXPathEvaluator, + public nsIXPathEvaluatorInternal { public: - nsXPathEvaluator(nsISupports *aOuter); + XPathEvaluator(nsISupports *aOuter); nsresult Init(); @@ -52,19 +52,18 @@ public: // WebIDL API JSObject* WrapObject(JSContext* aCx, JS::Handle aScope); - static already_AddRefed - Constructor(const mozilla::dom::GlobalObject& aGlobal, - mozilla::ErrorResult& rv); + static already_AddRefed + Constructor(const GlobalObject& aGlobal, ErrorResult& rv); already_AddRefed CreateExpression(const nsAString& aExpression, nsIDOMXPathNSResolver* aResolver, - mozilla::ErrorResult& rv); + ErrorResult& rv); already_AddRefed - CreateNSResolver(nsINode* aNodeResolver, mozilla::ErrorResult& rv); + CreateNSResolver(nsINode* aNodeResolver, ErrorResult& rv); already_AddRefed Evaluate(const nsAString& aExpression, nsINode* aContextNode, nsIDOMXPathNSResolver* aResolver, uint16_t aType, - nsISupports* aResult, mozilla::ErrorResult& rv); + nsISupports* aResult, ErrorResult& rv); private: nsresult CreateExpression(const nsAString & aExpression, nsIDOMXPathNSResolver *aResolver, @@ -78,7 +77,7 @@ private: }; inline nsISupports* -ToSupports(nsXPathEvaluator* e) +ToSupports(XPathEvaluator* e) { return static_cast(e); } @@ -87,4 +86,7 @@ ToSupports(nsXPathEvaluator* e) #define TRANSFORMIIX_XPATH_EVALUATOR_CID \ { 0xd0a75e02, 0xb5e7, 0x11d5, { 0xa7, 0xf2, 0xdf, 0x10, 0x9f, 0xb8, 0xa1, 0xfc } } -#endif +} // namespace dom +} // namespace mozilla + +#endif /* mozilla_dom_XPathEvaluator_h */ diff --git a/content/xslt/src/xpath/moz.build b/content/xslt/src/xpath/moz.build index 4e878fb2b4f..23e60da2f68 100644 --- a/content/xslt/src/xpath/moz.build +++ b/content/xslt/src/xpath/moz.build @@ -6,8 +6,12 @@ MODULE = 'transformiix' +EXPORTS.mozilla.dom += [ + 'XPathEvaluator.h', +] + CPP_SOURCES += [ - 'nsXPathEvaluator.cpp', + 'XPathEvaluator.cpp', 'nsXPathExpression.cpp', 'nsXPathNSResolver.cpp', 'nsXPathResult.cpp', diff --git a/dom/bindings/Bindings.conf b/dom/bindings/Bindings.conf index f884ceafd50..6497174dd43 100644 --- a/dom/bindings/Bindings.conf +++ b/dom/bindings/Bindings.conf @@ -1455,8 +1455,6 @@ DOMInterfaces = { }, 'XPathEvaluator': { - 'nativeType': 'nsXPathEvaluator', - 'headerFile': 'nsXPathEvaluator.h', 'wrapperCache': False }, diff --git a/layout/build/nsLayoutModule.cpp b/layout/build/nsLayoutModule.cpp index 4ba741b34f4..dbba656f508 100644 --- a/layout/build/nsLayoutModule.cpp +++ b/layout/build/nsLayoutModule.cpp @@ -54,7 +54,7 @@ #include "nsIMessageManager.h" // Transformiix stuff -#include "nsXPathEvaluator.h" +#include "mozilla/dom/XPathEvaluator.h" #include "txMozillaXSLTProcessor.h" #include "txNodeSetAdaptor.h" @@ -262,7 +262,7 @@ using mozilla::dom::time::TimeService; // Factory Constructor NS_GENERIC_FACTORY_CONSTRUCTOR(txMozillaXSLTProcessor) -NS_GENERIC_AGGREGATED_CONSTRUCTOR_INIT(nsXPathEvaluator, Init) +NS_GENERIC_AGGREGATED_CONSTRUCTOR_INIT(XPathEvaluator, Init) NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(txNodeSetAdaptor, Init) NS_GENERIC_FACTORY_CONSTRUCTOR(nsDOMSerializer) NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsXMLHttpRequest, Init) @@ -1019,7 +1019,7 @@ static const mozilla::Module::CIDEntry kLayoutCIDs[] = { { &kNS_VIDEODOCUMENT_CID, false, NULL, CreateVideoDocument }, { &kNS_STYLESHEETSERVICE_CID, false, NULL, nsStyleSheetServiceConstructor }, { &kTRANSFORMIIX_XSLT_PROCESSOR_CID, false, NULL, txMozillaXSLTProcessorConstructor }, - { &kTRANSFORMIIX_XPATH_EVALUATOR_CID, false, NULL, nsXPathEvaluatorConstructor }, + { &kTRANSFORMIIX_XPATH_EVALUATOR_CID, false, NULL, XPathEvaluatorConstructor }, { &kTRANSFORMIIX_NODESET_CID, false, NULL, txNodeSetAdaptorConstructor }, { &kNS_XMLSERIALIZER_CID, false, NULL, nsDOMSerializerConstructor }, { &kNS_FILEREADER_CID, false, NULL, nsDOMFileReaderConstructor }, From f2c135d0b4d11c1b9561ce382a23a0613c7bc34f Mon Sep 17 00:00:00 2001 From: Peter Van der Beken Date: Thu, 4 Jul 2013 17:29:29 +0200 Subject: [PATCH 05/64] Bug 908997 - Simplify XPathEvaluator - remove nsIXPathEvaluatorInternal. r=bz. --HG-- rename : content/xslt/src/xpath/nsXPathEvaluator.cpp => content/xslt/src/xpath/XPathEvaluator.cpp rename : content/xslt/src/xpath/nsXPathEvaluator.h => content/xslt/src/xpath/XPathEvaluator.h extra : rebase_source : 3aa2f8f50c683b641904a0653a128c06cf1afb30 --- content/base/public/moz.build | 1 - .../base/public/nsIXPathEvaluatorInternal.h | 43 -------- content/base/src/nsDocument.cpp | 4 +- content/xslt/src/xpath/XPathEvaluator.cpp | 97 +------------------ content/xslt/src/xpath/XPathEvaluator.h | 21 +--- layout/build/nsLayoutModule.cpp | 2 +- 6 files changed, 6 insertions(+), 162 deletions(-) delete mode 100644 content/base/public/nsIXPathEvaluatorInternal.h diff --git a/content/base/public/moz.build b/content/base/public/moz.build index 648473f4d88..50bee3e689c 100644 --- a/content/base/public/moz.build +++ b/content/base/public/moz.build @@ -61,7 +61,6 @@ EXPORTS += [ 'nsINodeList.h', 'nsIScriptElement.h', 'nsIStyleSheetLinkingElement.h', - 'nsIXPathEvaluatorInternal.h', 'nsLineBreaker.h', 'nsReferencedElement.h', 'nsTreeSanitizer.h', diff --git a/content/base/public/nsIXPathEvaluatorInternal.h b/content/base/public/nsIXPathEvaluatorInternal.h deleted file mode 100644 index 7c4992d41b2..00000000000 --- a/content/base/public/nsIXPathEvaluatorInternal.h +++ /dev/null @@ -1,43 +0,0 @@ -/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef nsIXPathEvaluatorInternal_h__ -#define nsIXPathEvaluatorInternal_h__ - -#include "nsCOMArray.h" -#include "nsTArray.h" -#include "nsStringGlue.h" - -class nsIDOMDocument; -class nsIDOMXPathExpression; -class nsIDOMXPathNSResolver; - -#define NS_IXPATHEVALUATORINTERNAL_IID \ - {0xb4b72daa, 0x65d6, 0x440f, \ - { 0xb6, 0x08, 0xe2, 0xee, 0x9a, 0x82, 0xf3, 0x13 }} - -class nsIXPathEvaluatorInternal : public nsISupports -{ -public: - - NS_DECLARE_STATIC_IID_ACCESSOR(NS_IXPATHEVALUATORINTERNAL_IID) - - /** - * Sets the document this evaluator corresponds to - */ - NS_IMETHOD SetDocument(nsIDOMDocument* aDocument) = 0; - - NS_IMETHOD CreateExpression(const nsAString &aExpression, - nsIDOMXPathNSResolver *aResolver, - nsTArray *aNamespaceURIs, - nsTArray *aContractIDs, - nsCOMArray *aState, - nsIDOMXPathExpression **aResult) = 0; -}; - -NS_DEFINE_STATIC_IID_ACCESSOR(nsIXPathEvaluatorInternal, - NS_IXPATHEVALUATORINTERNAL_IID) - -#endif //nsIXPathEvaluatorInternal_h__ diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index f97fc65f507..25fd3d9f99e 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -102,7 +102,6 @@ #include "nsIDOMXPathEvaluator.h" #include "nsIDOMXPathExpression.h" #include "nsIDOMXPathNSResolver.h" -#include "nsIXPathEvaluatorInternal.h" #include "nsIParserService.h" #include "nsContentCreatorFunctions.h" @@ -1586,8 +1585,7 @@ NS_INTERFACE_TABLE_HEAD(nsDocument) NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(nsDocument) NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIDOMXPathNSResolver, new nsNode3Tearoff(this)) - if (aIID.Equals(NS_GET_IID(nsIDOMXPathEvaluator)) || - aIID.Equals(NS_GET_IID(nsIXPathEvaluatorInternal))) { + if (aIID.Equals(NS_GET_IID(nsIDOMXPathEvaluator))) { if (!mXPathEvaluatorTearoff) { nsresult rv; mXPathEvaluatorTearoff = diff --git a/content/xslt/src/xpath/XPathEvaluator.cpp b/content/xslt/src/xpath/XPathEvaluator.cpp index c711fa3c4e2..c890363c64a 100644 --- a/content/xslt/src/xpath/XPathEvaluator.cpp +++ b/content/xslt/src/xpath/XPathEvaluator.cpp @@ -34,20 +34,11 @@ class XPathEvaluatorParseContext : public txIParseContext { public: XPathEvaluatorParseContext(nsIDOMXPathNSResolver* aResolver, - nsTArray *aNamespaceIDs, - nsTArray *aContractIDs, - nsCOMArray *aState, bool aIsCaseSensitive) : mResolver(aResolver), - mNamespaceIDs(aNamespaceIDs), - mContractIDs(aContractIDs), - mState(aState), mLastError(NS_OK), mIsCaseSensitive(aIsCaseSensitive) { - NS_ASSERTION(mContractIDs || - (!mNamespaceIDs || mNamespaceIDs->Length() == 0), - "Need contract IDs if there are namespaces."); } nsresult getError() @@ -63,9 +54,6 @@ public: private: nsIDOMXPathNSResolver* mResolver; - nsTArray *mNamespaceIDs; - nsTArray *mContractIDs; - nsCOMArray *mState; nsresult mLastError; bool mIsCaseSensitive; }; @@ -73,31 +61,14 @@ private: NS_IMPL_AGGREGATED(XPathEvaluator) NS_INTERFACE_MAP_BEGIN_AGGREGATED(XPathEvaluator) NS_INTERFACE_MAP_ENTRY(nsIDOMXPathEvaluator) - NS_INTERFACE_MAP_ENTRY(nsIXPathEvaluatorInternal) NS_INTERFACE_MAP_END XPathEvaluator::XPathEvaluator(nsISupports *aOuter) + : mDocument(do_GetWeakReference(aOuter)) { NS_INIT_AGGREGATED(aOuter); } -nsresult -XPathEvaluator::Init() -{ - nsCOMPtr document = do_QueryInterface(fOuter); - - return document ? SetDocument(document) : NS_OK; -} - -NS_IMETHODIMP -XPathEvaluator::CreateExpression(const nsAString & aExpression, - nsIDOMXPathNSResolver *aResolver, - nsIDOMXPathExpression **aResult) -{ - return CreateExpression(aExpression, aResolver, (nsTArray*)nullptr, - nullptr, nullptr, aResult); -} - NS_IMETHODIMP XPathEvaluator::CreateNSResolver(nsIDOMNode *aNodeResolver, nsIDOMXPathNSResolver **aResult) @@ -130,54 +101,9 @@ XPathEvaluator::Evaluate(const nsAString & aExpression, } -NS_IMETHODIMP -XPathEvaluator::SetDocument(nsIDOMDocument* aDocument) -{ - mDocument = do_GetWeakReference(aDocument); - return NS_OK; -} - NS_IMETHODIMP XPathEvaluator::CreateExpression(const nsAString & aExpression, nsIDOMXPathNSResolver *aResolver, - nsTArray *aNamespaceURIs, - nsTArray *aContractIDs, - nsCOMArray *aState, - nsIDOMXPathExpression **aResult) -{ - nsTArray namespaceIDs; - if (aNamespaceURIs) { - uint32_t count = aNamespaceURIs->Length(); - - if (!aContractIDs || aContractIDs->Length() != count) { - return NS_ERROR_FAILURE; - } - - if (!namespaceIDs.SetLength(count)) { - return NS_ERROR_OUT_OF_MEMORY; - } - - uint32_t i; - for (i = 0; i < count; ++i) { - if (aContractIDs->ElementAt(i).IsEmpty()) { - return NS_ERROR_FAILURE; - } - - nsContentUtils::NameSpaceManager()->RegisterNameSpace(aNamespaceURIs->ElementAt(i), namespaceIDs[i]); - } - } - - - return CreateExpression(aExpression, aResolver, &namespaceIDs, aContractIDs, - aState, aResult); -} - -nsresult -XPathEvaluator::CreateExpression(const nsAString & aExpression, - nsIDOMXPathNSResolver *aResolver, - nsTArray *aNamespaceIDs, - nsTArray *aContractIDs, - nsCOMArray *aState, nsIDOMXPathExpression **aResult) { nsresult rv; @@ -192,9 +118,7 @@ XPathEvaluator::CreateExpression(const nsAString & aExpression, } nsCOMPtr doc = do_QueryReferent(mDocument); - XPathEvaluatorParseContext pContext(aResolver, aNamespaceIDs, - aContractIDs, aState, - !(doc && doc->IsHTML())); + XPathEvaluatorParseContext pContext(aResolver, !(doc && doc->IsHTML())); nsAutoPtr expression; rv = txExprParser::createExpr(PromiseFlatString(aExpression), &pContext, @@ -230,7 +154,6 @@ XPathEvaluator::Constructor(const GlobalObject& aGlobal, ErrorResult& rv) { nsRefPtr newObj = new XPathEvaluator(nullptr); - newObj->Init(); return newObj.forget(); } @@ -309,21 +232,7 @@ XPathEvaluatorParseContext::resolveFunctionCall(nsIAtom* aName, int32_t aID, FunctionCall** aFn) { - nsresult rv = NS_ERROR_XPATH_UNKNOWN_FUNCTION; - - uint32_t i, count = mNamespaceIDs ? mNamespaceIDs->Length() : 0; - for (i = 0; i < count; ++i) { - if (mNamespaceIDs->ElementAt(i) == aID) { - nsISupports *state = mState ? mState->SafeObjectAt(i) : nullptr; - rv = TX_ResolveFunctionCallXPCOM(mContractIDs->ElementAt(i), aID, - aName, state, aFn); - if (NS_SUCCEEDED(rv)) { - break; - } - } - } - - return rv; + return NS_ERROR_XPATH_UNKNOWN_FUNCTION; } bool XPathEvaluatorParseContext::caseInsensitiveNameTests() diff --git a/content/xslt/src/xpath/XPathEvaluator.h b/content/xslt/src/xpath/XPathEvaluator.h index 967f434d91f..6808d6b5d83 100644 --- a/content/xslt/src/xpath/XPathEvaluator.h +++ b/content/xslt/src/xpath/XPathEvaluator.h @@ -7,13 +7,11 @@ #define mozilla_dom_XPathEvaluator_h #include "nsIDOMXPathEvaluator.h" -#include "nsIXPathEvaluatorInternal.h" #include "nsIWeakReference.h" #include "nsAutoPtr.h" #include "nsString.h" #include "txResultRecycler.h" #include "nsAgg.h" -#include "nsTArray.h" #include "mozilla/Attributes.h" #include "mozilla/ErrorResult.h" @@ -27,8 +25,7 @@ class GlobalObject; /** * A class for evaluating an XPath expression string */ -class XPathEvaluator MOZ_FINAL : public nsIDOMXPathEvaluator, - public nsIXPathEvaluatorInternal +class XPathEvaluator MOZ_FINAL : public nsIDOMXPathEvaluator { public: XPathEvaluator(nsISupports *aOuter); @@ -41,15 +38,6 @@ public: // nsIDOMXPathEvaluator interface NS_DECL_NSIDOMXPATHEVALUATOR - // nsIXPathEvaluatorInternal interface - NS_IMETHOD SetDocument(nsIDOMDocument* aDocument) MOZ_OVERRIDE; - NS_IMETHOD CreateExpression(const nsAString &aExpression, - nsIDOMXPathNSResolver *aResolver, - nsTArray *aNamespaceURIs, - nsTArray *aContractIDs, - nsCOMArray *aState, - nsIDOMXPathExpression **aResult) MOZ_OVERRIDE; - // WebIDL API JSObject* WrapObject(JSContext* aCx, JS::Handle aScope); static already_AddRefed @@ -65,13 +53,6 @@ public: nsIDOMXPathNSResolver* aResolver, uint16_t aType, nsISupports* aResult, ErrorResult& rv); private: - nsresult CreateExpression(const nsAString & aExpression, - nsIDOMXPathNSResolver *aResolver, - nsTArray *aNamespaceIDs, - nsTArray *aContractIDs, - nsCOMArray *aState, - nsIDOMXPathExpression **aResult); - nsWeakPtr mDocument; nsRefPtr mRecycler; }; diff --git a/layout/build/nsLayoutModule.cpp b/layout/build/nsLayoutModule.cpp index dbba656f508..188ef21169d 100644 --- a/layout/build/nsLayoutModule.cpp +++ b/layout/build/nsLayoutModule.cpp @@ -262,7 +262,7 @@ using mozilla::dom::time::TimeService; // Factory Constructor NS_GENERIC_FACTORY_CONSTRUCTOR(txMozillaXSLTProcessor) -NS_GENERIC_AGGREGATED_CONSTRUCTOR_INIT(XPathEvaluator, Init) +NS_GENERIC_AGGREGATED_CONSTRUCTOR(XPathEvaluator) NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(txNodeSetAdaptor, Init) NS_GENERIC_FACTORY_CONSTRUCTOR(nsDOMSerializer) NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsXMLHttpRequest, Init) From 6bdbbf553db163dab751552662d554855d74ad6f Mon Sep 17 00:00:00 2001 From: Peter Van der Beken Date: Thu, 4 Jul 2013 17:39:24 +0200 Subject: [PATCH 06/64] Bug 908997 - Simplify XPathEvaluator - remove aggregation from XPathEvaluator. r=bz. --HG-- rename : content/xslt/src/xpath/nsXPathEvaluator.cpp => content/xslt/src/xpath/XPathEvaluator.cpp rename : content/xslt/src/xpath/nsXPathEvaluator.h => content/xslt/src/xpath/XPathEvaluator.h extra : rebase_source : 163d25a36f52f8f8fa8b6952bcf1bc83de14230b --- content/base/public/nsIDocument.h | 5 ++ content/base/src/Makefile.in | 1 + content/base/src/nsDocument.cpp | 86 +++++++++++------------ content/base/src/nsDocument.h | 8 ++- content/xslt/src/xpath/XPathEvaluator.cpp | 12 ++-- content/xslt/src/xpath/XPathEvaluator.h | 16 +++-- layout/build/nsLayoutModule.cpp | 2 +- 7 files changed, 66 insertions(+), 64 deletions(-) diff --git a/content/base/public/nsIDocument.h b/content/base/public/nsIDocument.h index be1bc4339fc..baf00e96f39 100644 --- a/content/base/public/nsIDocument.h +++ b/content/base/public/nsIDocument.h @@ -108,6 +108,7 @@ class ProcessingInstruction; class Touch; class TreeWalker; class UndoManager; +class XPathEvaluator; template class OwningNonNull; template class Sequence; @@ -2171,6 +2172,8 @@ protected: return mContentType; } + mozilla::dom::XPathEvaluator* XPathEvaluator(); + nsCString mReferrer; nsString mLastModified; @@ -2426,6 +2429,8 @@ protected: uint8_t mDefaultElementType; uint32_t mInSyncOperationCount; + + nsRefPtr mXPathEvaluator; }; NS_DEFINE_STATIC_IID_ACCESSOR(nsIDocument, NS_IDOCUMENT_IID) diff --git a/content/base/src/Makefile.in b/content/base/src/Makefile.in index f931ab856eb..6822000914f 100644 --- a/content/base/src/Makefile.in +++ b/content/base/src/Makefile.in @@ -27,6 +27,7 @@ LOCAL_INCLUDES += \ -I$(topsrcdir)/content/xbl/src \ -I$(topsrcdir)/content/xml/content/src \ -I$(topsrcdir)/content/xml/document/src \ + -I$(topsrcdir)/content/xslt/src/xpath \ -I$(topsrcdir)/content/xul/content/src \ -I$(topsrcdir)/content/xul/document/src \ -I$(topsrcdir)/dom/base \ diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index 25fd3d9f99e..b5715e994c6 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -99,7 +99,6 @@ #include "nsBidiUtils.h" #include "nsIDOMUserDataHandler.h" -#include "nsIDOMXPathEvaluator.h" #include "nsIDOMXPathExpression.h" #include "nsIDOMXPathNSResolver.h" #include "nsIParserService.h" @@ -212,6 +211,7 @@ #include "nsIHttpChannelInternal.h" #include "nsISecurityConsoleMessage.h" #include "nsCharSeparatedTokenizer.h" +#include "mozilla/dom/XPathEvaluator.h" using namespace mozilla; using namespace mozilla::dom; @@ -1581,22 +1581,11 @@ NS_INTERFACE_TABLE_HEAD(nsDocument) NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIMutationObserver) NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIApplicationCacheContainer) NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIObserver) + NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIDOMXPathEvaluator) NS_INTERFACE_TABLE_END NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(nsDocument) NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIDOMXPathNSResolver, new nsNode3Tearoff(this)) - if (aIID.Equals(NS_GET_IID(nsIDOMXPathEvaluator))) { - if (!mXPathEvaluatorTearoff) { - nsresult rv; - mXPathEvaluatorTearoff = - do_CreateInstance(NS_XPATH_EVALUATOR_CONTRACTID, - static_cast(this), &rv); - NS_ENSURE_SUCCESS(rv, rv); - } - - return mXPathEvaluatorTearoff->QueryInterface(aIID, aInstancePtr); - } - else NS_INTERFACE_MAP_END @@ -1782,7 +1771,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsDocument) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChannel) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStyleAttrStyleSheet) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mXPathEvaluatorTearoff) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mXPathEvaluator) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLayoutHistoryState) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOnloadBlocker) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFirstBaseNodeWithHref) @@ -1869,7 +1858,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDocument) } tmp->mFirstChild = nullptr; - NS_IMPL_CYCLE_COLLECTION_UNLINK(mXPathEvaluatorTearoff) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mXPathEvaluator) tmp->mCachedRootElement = nullptr; // Avoid a dangling pointer NS_IMPL_CYCLE_COLLECTION_UNLINK(mDisplayDocument) NS_IMPL_CYCLE_COLLECTION_UNLINK(mFirstBaseNodeWithHref) @@ -11288,31 +11277,14 @@ nsIDocument::CreateExpression(const nsAString& aExpression, nsIDOMXPathNSResolver* aResolver, ErrorResult& rv) { - nsCOMPtr evaluator = do_QueryInterface(this); - if (!evaluator) { - rv.Throw(NS_ERROR_FAILURE); - return nullptr; - } - - nsCOMPtr expr; - rv = evaluator->CreateExpression(aExpression, aResolver, getter_AddRefs(expr)); - return expr.forget(); + return XPathEvaluator()->CreateExpression(aExpression, aResolver, rv); } already_AddRefed nsIDocument::CreateNSResolver(nsINode* aNodeResolver, ErrorResult& rv) { - nsCOMPtr evaluator = do_QueryInterface(this); - if (!evaluator) { - rv.Throw(NS_ERROR_FAILURE); - return nullptr; - } - - nsCOMPtr nodeResolver = do_QueryInterface(aNodeResolver); - nsCOMPtr res; - rv = evaluator->CreateNSResolver(nodeResolver, getter_AddRefs(res)); - return res.forget(); + return XPathEvaluator()->CreateNSResolver(aNodeResolver, rv); } already_AddRefed @@ -11320,19 +11292,34 @@ nsIDocument::Evaluate(const nsAString& aExpression, nsINode* aContextNode, nsIDOMXPathNSResolver* aResolver, uint16_t aType, nsISupports* aResult, ErrorResult& rv) { - nsCOMPtr evaluator = do_QueryInterface(this); - if (!evaluator) { - rv.Throw(NS_ERROR_FAILURE); - return nullptr; - } - - nsCOMPtr contextNode = do_QueryInterface(aContextNode); - nsCOMPtr res; - rv = evaluator->Evaluate(aExpression, contextNode, aResolver, aType, - aResult, getter_AddRefs(res)); - return res.forget(); + return XPathEvaluator()->Evaluate(aExpression, aContextNode, aResolver, aType, + aResult, rv); } +NS_IMETHODIMP +nsDocument::CreateExpression(const nsAString& aExpression, + nsIDOMXPathNSResolver* aResolver, + nsIDOMXPathExpression** aResult) +{ + return XPathEvaluator()->CreateExpression(aExpression, aResolver, aResult); +} + +NS_IMETHODIMP +nsDocument::CreateNSResolver(nsIDOMNode* aNodeResolver, + nsIDOMXPathNSResolver** aResult) +{ + return XPathEvaluator()->CreateNSResolver(aNodeResolver, aResult); +} + +NS_IMETHODIMP +nsDocument::Evaluate(const nsAString& aExpression, nsIDOMNode* aContextNode, + nsIDOMXPathNSResolver* aResolver, uint16_t aType, + nsISupports* aInResult, nsISupports** aResult) +{ + return XPathEvaluator()->Evaluate(aExpression, aContextNode, aResolver, aType, + aInResult, aResult); +} + // This is just a hack around the fact that window.document is not // [Unforgeable] yet. JSObject* @@ -11384,6 +11371,15 @@ nsIDocument::WrapObject(JSContext *aCx, JS::Handle aScope) return obj; } +XPathEvaluator* +nsIDocument::XPathEvaluator() +{ + if (!mXPathEvaluator) { + mXPathEvaluator = new dom::XPathEvaluator(this); + } + return mXPathEvaluator; +} + bool MarkDocumentTreeToBeInSyncOperation(nsIDocument* aDoc, void* aData) { diff --git a/content/base/src/nsDocument.h b/content/base/src/nsDocument.h index fdcf1ef3963..f2d2b6a1218 100644 --- a/content/base/src/nsDocument.h +++ b/content/base/src/nsDocument.h @@ -68,6 +68,7 @@ #include "nsDataHashtable.h" #include "mozilla/TimeStamp.h" #include "mozilla/Attributes.h" +#include "nsIDOMXPathEvaluator.h" #define XML_DECLARATION_BITS_DECLARATION_EXISTS (1 << 0) #define XML_DECLARATION_BITS_ENCODING_EXISTS (1 << 1) @@ -504,7 +505,8 @@ class nsDocument : public nsIDocument, public nsIRadioGroupContainer, public nsIApplicationCacheContainer, public nsStubMutationObserver, - public nsIObserver + public nsIObserver, + public nsIDOMXPathEvaluator { public: typedef mozilla::dom::Element Element; @@ -786,6 +788,8 @@ public: // nsIObserver NS_DECL_NSIOBSERVER + NS_DECL_NSIDOMXPATHEVALUATOR + virtual nsresult Init(); virtual nsresult CreateElem(const nsAString& aName, nsIAtom *aPrefix, @@ -1345,8 +1349,6 @@ private: nsDocument(const nsDocument& aOther); nsDocument& operator=(const nsDocument& aOther); - nsCOMPtr mXPathEvaluatorTearoff; - // The layout history state that should be used by nodes in this // document. We only actually store a pointer to it when: // 1) We have no script global object. diff --git a/content/xslt/src/xpath/XPathEvaluator.cpp b/content/xslt/src/xpath/XPathEvaluator.cpp index c890363c64a..a8429c820d8 100644 --- a/content/xslt/src/xpath/XPathEvaluator.cpp +++ b/content/xslt/src/xpath/XPathEvaluator.cpp @@ -3,7 +3,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include "XPathEvaluator.h" +#include "mozilla/dom/XPathEvaluator.h" #include "nsCOMPtr.h" #include "nsIAtom.h" #include "nsXPathExpression.h" @@ -58,15 +58,11 @@ private: bool mIsCaseSensitive; }; -NS_IMPL_AGGREGATED(XPathEvaluator) -NS_INTERFACE_MAP_BEGIN_AGGREGATED(XPathEvaluator) - NS_INTERFACE_MAP_ENTRY(nsIDOMXPathEvaluator) -NS_INTERFACE_MAP_END +NS_IMPL_ISUPPORTS1(XPathEvaluator, nsIDOMXPathEvaluator) -XPathEvaluator::XPathEvaluator(nsISupports *aOuter) - : mDocument(do_GetWeakReference(aOuter)) +XPathEvaluator::XPathEvaluator(nsIDocument* aDocument) + : mDocument(do_GetWeakReference(aDocument)) { - NS_INIT_AGGREGATED(aOuter); } NS_IMETHODIMP diff --git a/content/xslt/src/xpath/XPathEvaluator.h b/content/xslt/src/xpath/XPathEvaluator.h index 6808d6b5d83..9080fe2f2f7 100644 --- a/content/xslt/src/xpath/XPathEvaluator.h +++ b/content/xslt/src/xpath/XPathEvaluator.h @@ -10,12 +10,12 @@ #include "nsIWeakReference.h" #include "nsAutoPtr.h" #include "nsString.h" -#include "txResultRecycler.h" -#include "nsAgg.h" #include "mozilla/Attributes.h" #include "mozilla/ErrorResult.h" +#include "nsIDocument.h" class nsINode; +class txResultRecycler; namespace mozilla { namespace dom { @@ -28,18 +28,20 @@ class GlobalObject; class XPathEvaluator MOZ_FINAL : public nsIDOMXPathEvaluator { public: - XPathEvaluator(nsISupports *aOuter); + XPathEvaluator(nsIDocument* aDocument = nullptr); - nsresult Init(); - - // nsISupports interface (support aggregation) - NS_DECL_AGGREGATED + NS_DECL_ISUPPORTS // nsIDOMXPathEvaluator interface NS_DECL_NSIDOMXPATHEVALUATOR // WebIDL API JSObject* WrapObject(JSContext* aCx, JS::Handle aScope); + already_AddRefed GetParentObject() + { + nsCOMPtr doc = do_QueryReferent(mDocument); + return doc.forget(); + } static already_AddRefed Constructor(const GlobalObject& aGlobal, ErrorResult& rv); already_AddRefed diff --git a/layout/build/nsLayoutModule.cpp b/layout/build/nsLayoutModule.cpp index 188ef21169d..64daeff8909 100644 --- a/layout/build/nsLayoutModule.cpp +++ b/layout/build/nsLayoutModule.cpp @@ -262,7 +262,7 @@ using mozilla::dom::time::TimeService; // Factory Constructor NS_GENERIC_FACTORY_CONSTRUCTOR(txMozillaXSLTProcessor) -NS_GENERIC_AGGREGATED_CONSTRUCTOR(XPathEvaluator) +NS_GENERIC_FACTORY_CONSTRUCTOR(XPathEvaluator) NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(txNodeSetAdaptor, Init) NS_GENERIC_FACTORY_CONSTRUCTOR(nsDOMSerializer) NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsXMLHttpRequest, Init) From ebf4a21007d9a24569a1396acbbbc6d58b55c501 Mon Sep 17 00:00:00 2001 From: Jeff Walden Date: Wed, 7 Dec 2011 21:52:38 -0500 Subject: [PATCH 07/64] Bug 730805 - Import, unmodified, the Microsoft-compatible implementation from the 'msinttypes' Google Code project, r26, into mfbt. r=gerv --HG-- extra : rebase_source : 3fa8943627740fc4a4a39b173f8dd77d93f8f8e2 --- mfbt/MSIntTypes.h | 305 +++++++++++++++++++++++++++++++++++ mfbt/exported_headers.mk | 1 + toolkit/content/license.html | 40 ++++- 3 files changed, 345 insertions(+), 1 deletion(-) create mode 100644 mfbt/MSIntTypes.h diff --git a/mfbt/MSIntTypes.h b/mfbt/MSIntTypes.h new file mode 100644 index 00000000000..4b3828a2162 --- /dev/null +++ b/mfbt/MSIntTypes.h @@ -0,0 +1,305 @@ +// ISO C9x compliant inttypes.h for Microsoft Visual Studio +// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 +// +// Copyright (c) 2006 Alexander Chemeris +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. The name of the author may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _MSC_VER // [ +#error "Use this header only with Microsoft Visual C++ compilers!" +#endif // _MSC_VER ] + +#ifndef _MSC_INTTYPES_H_ // [ +#define _MSC_INTTYPES_H_ + +#if _MSC_VER > 1000 +#pragma once +#endif + +#include "stdint.h" + +// 7.8 Format conversion of integer types + +typedef struct { + intmax_t quot; + intmax_t rem; +} imaxdiv_t; + +// 7.8.1 Macros for format specifiers + +#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) // [ See footnote 185 at page 198 + +// The fprintf macros for signed integers are: +#define PRId8 "d" +#define PRIi8 "i" +#define PRIdLEAST8 "d" +#define PRIiLEAST8 "i" +#define PRIdFAST8 "d" +#define PRIiFAST8 "i" + +#define PRId16 "hd" +#define PRIi16 "hi" +#define PRIdLEAST16 "hd" +#define PRIiLEAST16 "hi" +#define PRIdFAST16 "hd" +#define PRIiFAST16 "hi" + +#define PRId32 "I32d" +#define PRIi32 "I32i" +#define PRIdLEAST32 "I32d" +#define PRIiLEAST32 "I32i" +#define PRIdFAST32 "I32d" +#define PRIiFAST32 "I32i" + +#define PRId64 "I64d" +#define PRIi64 "I64i" +#define PRIdLEAST64 "I64d" +#define PRIiLEAST64 "I64i" +#define PRIdFAST64 "I64d" +#define PRIiFAST64 "I64i" + +#define PRIdMAX "I64d" +#define PRIiMAX "I64i" + +#define PRIdPTR "Id" +#define PRIiPTR "Ii" + +// The fprintf macros for unsigned integers are: +#define PRIo8 "o" +#define PRIu8 "u" +#define PRIx8 "x" +#define PRIX8 "X" +#define PRIoLEAST8 "o" +#define PRIuLEAST8 "u" +#define PRIxLEAST8 "x" +#define PRIXLEAST8 "X" +#define PRIoFAST8 "o" +#define PRIuFAST8 "u" +#define PRIxFAST8 "x" +#define PRIXFAST8 "X" + +#define PRIo16 "ho" +#define PRIu16 "hu" +#define PRIx16 "hx" +#define PRIX16 "hX" +#define PRIoLEAST16 "ho" +#define PRIuLEAST16 "hu" +#define PRIxLEAST16 "hx" +#define PRIXLEAST16 "hX" +#define PRIoFAST16 "ho" +#define PRIuFAST16 "hu" +#define PRIxFAST16 "hx" +#define PRIXFAST16 "hX" + +#define PRIo32 "I32o" +#define PRIu32 "I32u" +#define PRIx32 "I32x" +#define PRIX32 "I32X" +#define PRIoLEAST32 "I32o" +#define PRIuLEAST32 "I32u" +#define PRIxLEAST32 "I32x" +#define PRIXLEAST32 "I32X" +#define PRIoFAST32 "I32o" +#define PRIuFAST32 "I32u" +#define PRIxFAST32 "I32x" +#define PRIXFAST32 "I32X" + +#define PRIo64 "I64o" +#define PRIu64 "I64u" +#define PRIx64 "I64x" +#define PRIX64 "I64X" +#define PRIoLEAST64 "I64o" +#define PRIuLEAST64 "I64u" +#define PRIxLEAST64 "I64x" +#define PRIXLEAST64 "I64X" +#define PRIoFAST64 "I64o" +#define PRIuFAST64 "I64u" +#define PRIxFAST64 "I64x" +#define PRIXFAST64 "I64X" + +#define PRIoMAX "I64o" +#define PRIuMAX "I64u" +#define PRIxMAX "I64x" +#define PRIXMAX "I64X" + +#define PRIoPTR "Io" +#define PRIuPTR "Iu" +#define PRIxPTR "Ix" +#define PRIXPTR "IX" + +// The fscanf macros for signed integers are: +#define SCNd8 "d" +#define SCNi8 "i" +#define SCNdLEAST8 "d" +#define SCNiLEAST8 "i" +#define SCNdFAST8 "d" +#define SCNiFAST8 "i" + +#define SCNd16 "hd" +#define SCNi16 "hi" +#define SCNdLEAST16 "hd" +#define SCNiLEAST16 "hi" +#define SCNdFAST16 "hd" +#define SCNiFAST16 "hi" + +#define SCNd32 "ld" +#define SCNi32 "li" +#define SCNdLEAST32 "ld" +#define SCNiLEAST32 "li" +#define SCNdFAST32 "ld" +#define SCNiFAST32 "li" + +#define SCNd64 "I64d" +#define SCNi64 "I64i" +#define SCNdLEAST64 "I64d" +#define SCNiLEAST64 "I64i" +#define SCNdFAST64 "I64d" +#define SCNiFAST64 "I64i" + +#define SCNdMAX "I64d" +#define SCNiMAX "I64i" + +#ifdef _WIN64 // [ +# define SCNdPTR "I64d" +# define SCNiPTR "I64i" +#else // _WIN64 ][ +# define SCNdPTR "ld" +# define SCNiPTR "li" +#endif // _WIN64 ] + +// The fscanf macros for unsigned integers are: +#define SCNo8 "o" +#define SCNu8 "u" +#define SCNx8 "x" +#define SCNX8 "X" +#define SCNoLEAST8 "o" +#define SCNuLEAST8 "u" +#define SCNxLEAST8 "x" +#define SCNXLEAST8 "X" +#define SCNoFAST8 "o" +#define SCNuFAST8 "u" +#define SCNxFAST8 "x" +#define SCNXFAST8 "X" + +#define SCNo16 "ho" +#define SCNu16 "hu" +#define SCNx16 "hx" +#define SCNX16 "hX" +#define SCNoLEAST16 "ho" +#define SCNuLEAST16 "hu" +#define SCNxLEAST16 "hx" +#define SCNXLEAST16 "hX" +#define SCNoFAST16 "ho" +#define SCNuFAST16 "hu" +#define SCNxFAST16 "hx" +#define SCNXFAST16 "hX" + +#define SCNo32 "lo" +#define SCNu32 "lu" +#define SCNx32 "lx" +#define SCNX32 "lX" +#define SCNoLEAST32 "lo" +#define SCNuLEAST32 "lu" +#define SCNxLEAST32 "lx" +#define SCNXLEAST32 "lX" +#define SCNoFAST32 "lo" +#define SCNuFAST32 "lu" +#define SCNxFAST32 "lx" +#define SCNXFAST32 "lX" + +#define SCNo64 "I64o" +#define SCNu64 "I64u" +#define SCNx64 "I64x" +#define SCNX64 "I64X" +#define SCNoLEAST64 "I64o" +#define SCNuLEAST64 "I64u" +#define SCNxLEAST64 "I64x" +#define SCNXLEAST64 "I64X" +#define SCNoFAST64 "I64o" +#define SCNuFAST64 "I64u" +#define SCNxFAST64 "I64x" +#define SCNXFAST64 "I64X" + +#define SCNoMAX "I64o" +#define SCNuMAX "I64u" +#define SCNxMAX "I64x" +#define SCNXMAX "I64X" + +#ifdef _WIN64 // [ +# define SCNoPTR "I64o" +# define SCNuPTR "I64u" +# define SCNxPTR "I64x" +# define SCNXPTR "I64X" +#else // _WIN64 ][ +# define SCNoPTR "lo" +# define SCNuPTR "lu" +# define SCNxPTR "lx" +# define SCNXPTR "lX" +#endif // _WIN64 ] + +#endif // __STDC_FORMAT_MACROS ] + +// 7.8.2 Functions for greatest-width integer types + +// 7.8.2.1 The imaxabs function +#define imaxabs _abs64 + +// 7.8.2.2 The imaxdiv function + +// This is modified version of div() function from Microsoft's div.c found +// in %MSVC.NET%\crt\src\div.c +#ifdef STATIC_IMAXDIV // [ +static +#else // STATIC_IMAXDIV ][ +_inline +#endif // STATIC_IMAXDIV ] +imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom) +{ + imaxdiv_t result; + + result.quot = numer / denom; + result.rem = numer % denom; + + if (numer < 0 && result.rem > 0) { + // did division wrong; must fix up + ++result.quot; + result.rem -= denom; + } + + return result; +} + +// 7.8.2.3 The strtoimax and strtoumax functions +#define strtoimax _strtoi64 +#define strtoumax _strtoui64 + +// 7.8.2.4 The wcstoimax and wcstoumax functions +#define wcstoimax _wcstoi64 +#define wcstoumax _wcstoui64 + + +#endif // _MSC_INTTYPES_H_ ] diff --git a/mfbt/exported_headers.mk b/mfbt/exported_headers.mk index 165e0ca241b..79e181eb067 100644 --- a/mfbt/exported_headers.mk +++ b/mfbt/exported_headers.mk @@ -34,6 +34,7 @@ EXPORTS_mozilla += \ Maybe.h \ MemoryChecking.h \ MemoryReporting.h \ + MSIntTypes.h \ Move.h \ NullPtr.h \ PodOperations.h \ diff --git a/toolkit/content/license.html b/toolkit/content/license.html index 574a069307a..5e6fa148ca1 100644 --- a/toolkit/content/license.html +++ b/toolkit/content/license.html @@ -99,7 +99,7 @@
  • libyuv License
  • Lithuanian Spellchecking Dictionary License
  • MAAttachedWindow License
  • -
  • msstdint License
  • +
  • msinttypes License
  • MySpell License
  • nICEr License
  • nrappkit License
  • @@ -2861,6 +2861,44 @@ MATT GEMMELL HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +
    + +

    msinttypes License

    + +

    This license applies to the file + mfbt/MSIntTypes.h.

    + +
    +Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 
    +
    + Copyright (c) 2006-2008 Alexander Chemeris
    +
    +Redistribution and use in source and binary forms, with or without
    +modification, are permitted provided that the following conditions are met:
    +
    +  1. Redistributions of source code must retain the above copyright notice,
    +     this list of conditions and the following disclaimer.
    +
    +  2. Redistributions in binary form must reproduce the above copyright
    +     notice, this list of conditions and the following disclaimer in the
    +     documentation and/or other materials provided with the distribution.
    +
    +  3. The name of the author may be used to endorse or promote products
    +     derived from this software without specific prior written permission.
    +
    +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
    +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
    +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
    +EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
    +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
    +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
    +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
    +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    +
    + +

    MySpell License

    From c5dd957eae562e914119adbb12b80c32a987fbb8 Mon Sep 17 00:00:00 2001 From: Jeff Walden Date: Thu, 15 Dec 2011 00:27:42 -0500 Subject: [PATCH 08/64] Bug 730805 - Provide mozilla/IntegerPrintfMacros.h to implement the PRI* macros portion of the interface. r=espindola --HG-- extra : rebase_source : be80333003c6fec659e736a77463568c836d8348 --- configure.in | 10 + ipc/chromium/src/base/basictypes.h | 7 +- js/public/RequiredDefines.h | 12 +- js/src/configure.in | 10 + mfbt/IntegerPrintfMacros.h | 40 + mfbt/MSIntTypes.h | 113 +-- mfbt/exported_headers.mk | 1 + mfbt/tests/TestIntegerPrintfMacros.cpp | 1264 ++++++++++++++++++++++++ mfbt/tests/TestPoisonArea.cpp | 13 +- mfbt/tests/moz.build | 1 + mozilla-config.h.in | 21 +- security/manager/boot/src/Makefile.in | 1 - 12 files changed, 1358 insertions(+), 135 deletions(-) create mode 100644 mfbt/IntegerPrintfMacros.h create mode 100644 mfbt/tests/TestIntegerPrintfMacros.cpp diff --git a/configure.in b/configure.in index 6385921fe37..65d450172b0 100644 --- a/configure.in +++ b/configure.in @@ -1733,6 +1733,16 @@ case "$host" in ;; esac +dnl Check for using a custom implementation +dnl ======================================================== +AC_MSG_CHECKING(for custom implementation) +if test "$MOZ_CUSTOM_INTTYPES_H"; then + AC_DEFINE_UNQUOTED(MOZ_CUSTOM_INTTYPES_H, "$MOZ_CUSTOM_INTTYPES_H") + AC_MSG_RESULT(using $MOZ_CUSTOM_INTTYPES_H) +else + AC_MSG_RESULT(none specified) +fi + dnl Get mozilla version from central milestone file MOZILLA_VERSION=`$PERL $srcdir/config/milestone.pl -topsrcdir $srcdir` MOZILLA_UAVERSION=`$PERL $srcdir/config/milestone.pl -topsrcdir $srcdir -uaversion` diff --git a/ipc/chromium/src/base/basictypes.h b/ipc/chromium/src/base/basictypes.h index f6ffc1165bc..13c60bb1e99 100644 --- a/ipc/chromium/src/base/basictypes.h +++ b/ipc/chromium/src/base/basictypes.h @@ -12,7 +12,7 @@ #include "base/port.h" // Types that only need exist on certain systems #include "mozilla/Assertions.h" -#include +#include "mozilla/IntegerPrintfMacros.h" // A type to represent a Unicode code-point value. As of Unicode 4.0, // such values require up to 21 bits. @@ -35,15 +35,10 @@ const int64_t kint64max = (( int64_t) GG_LONGLONG(0x7FFFFFFFFFFFFFFF)); // Platform- and hardware-dependent printf specifiers # if defined(OS_POSIX) -# define __STDC_FORMAT_MACROS 1 -# include // for 64-bit integer format macros # define PRId64L "I64d" # define PRIu64L "I64u" # define PRIx64L "I64x" # elif defined(OS_WIN) -# define PRId64 "I64d" -# define PRIu64 "I64u" -# define PRIx64 "I64x" # define PRId64L L"I64d" # define PRIu64L L"I64u" # define PRIx64L L"I64x" diff --git a/js/public/RequiredDefines.h b/js/public/RequiredDefines.h index 6af9ca871b5..3c8f4291321 100644 --- a/js/public/RequiredDefines.h +++ b/js/public/RequiredDefines.h @@ -15,9 +15,17 @@ /* * The c99 defining the limit macros (UINT32_MAX for example), says: - * C++ implementations should define these macros only when __STDC_LIMIT_MACROS - * is defined before is included. + * + * C++ implementations should define these macros only when + * __STDC_LIMIT_MACROS is defined before is included. + * + * The same also occurs with __STDC_CONSTANT_MACROS for the constant macros + * (INT8_C for example) used to specify a literal constant of the proper type, + * and with __STDC_FORMAT_MACROS for the format macros (PRId32 for example) used + * with the fprintf function family. */ #define __STDC_LIMIT_MACROS +#define __STDC_CONSTANT_MACROS +#define __STDC_FORMAT_MACROS #endif /* js_RequiredDefines_h */ diff --git a/js/src/configure.in b/js/src/configure.in index fc79c78a261..91e419e567e 100644 --- a/js/src/configure.in +++ b/js/src/configure.in @@ -1359,6 +1359,16 @@ case "$host" in ;; esac +dnl Check for using a custom implementation +dnl ======================================================== +AC_MSG_CHECKING(for custom implementation) +if test "$MOZ_CUSTOM_INTTYPES_H"; then + AC_DEFINE_UNQUOTED(MOZ_CUSTOM_INTTYPES_H, "$MOZ_CUSTOM_INTTYPES_H") + AC_MSG_RESULT(using $MOZ_CUSTOM_INTTYPES_H) +else + AC_MSG_RESULT(none specified) +fi + MOZ_DOING_LTO(lto_is_enabled) dnl ======================================================== diff --git a/mfbt/IntegerPrintfMacros.h b/mfbt/IntegerPrintfMacros.h new file mode 100644 index 00000000000..1ae60d618eb --- /dev/null +++ b/mfbt/IntegerPrintfMacros.h @@ -0,0 +1,40 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Implements the C99 interface, minus the SCN* format macros. */ + +#ifndef mozilla_IntegerPrintfMacros_h_ +#define mozilla_IntegerPrintfMacros_h_ + +/* + * MSVC++ doesn't include , even in versions shipping , so + * we have to reimplement it there. Note: #includes . + * + * Note that this header DOES NOT implement 's scanf macros. MSVC's + * scanf doesn't have sufficient format specifier support to implement them + * (specifically, to implement scanning into an 8-bit location). + * + * http://stackoverflow.com/questions/3036396/scanfd-char-char-as-int-format-string + * + * Moreover, scanf is a footgun: if the input number exceeds the bounds of the + * target type, behavior is undefined (in the compiler sense: that is, this code + * could overwrite your hard drive with zeroes): + * + * uint8_t u; + * sscanf("256", "%" SCNu8, &u); // BAD + * + * This header will sometimes provide SCN* macros, by dint of being implemented + * using . But for these reasons, *never* use them! + */ + +#if defined(MOZ_CUSTOM_INTTYPES_H) +# include MOZ_CUSTOM_INTTYPES_H +#elif defined(_MSC_VER) +# include "mozilla/MSIntTypes.h" +#else +# include +#endif + +#endif /* mozilla_IntegerPrintfMacros_h_ */ diff --git a/mfbt/MSIntTypes.h b/mfbt/MSIntTypes.h index 4b3828a2162..3dfba55f581 100644 --- a/mfbt/MSIntTypes.h +++ b/mfbt/MSIntTypes.h @@ -40,7 +40,7 @@ #pragma once #endif -#include "stdint.h" +#include // 7.8 Format conversion of integer types @@ -151,115 +151,8 @@ typedef struct { #define PRIxPTR "Ix" #define PRIXPTR "IX" -// The fscanf macros for signed integers are: -#define SCNd8 "d" -#define SCNi8 "i" -#define SCNdLEAST8 "d" -#define SCNiLEAST8 "i" -#define SCNdFAST8 "d" -#define SCNiFAST8 "i" - -#define SCNd16 "hd" -#define SCNi16 "hi" -#define SCNdLEAST16 "hd" -#define SCNiLEAST16 "hi" -#define SCNdFAST16 "hd" -#define SCNiFAST16 "hi" - -#define SCNd32 "ld" -#define SCNi32 "li" -#define SCNdLEAST32 "ld" -#define SCNiLEAST32 "li" -#define SCNdFAST32 "ld" -#define SCNiFAST32 "li" - -#define SCNd64 "I64d" -#define SCNi64 "I64i" -#define SCNdLEAST64 "I64d" -#define SCNiLEAST64 "I64i" -#define SCNdFAST64 "I64d" -#define SCNiFAST64 "I64i" - -#define SCNdMAX "I64d" -#define SCNiMAX "I64i" - -#ifdef _WIN64 // [ -# define SCNdPTR "I64d" -# define SCNiPTR "I64i" -#else // _WIN64 ][ -# define SCNdPTR "ld" -# define SCNiPTR "li" -#endif // _WIN64 ] - -// The fscanf macros for unsigned integers are: -#define SCNo8 "o" -#define SCNu8 "u" -#define SCNx8 "x" -#define SCNX8 "X" -#define SCNoLEAST8 "o" -#define SCNuLEAST8 "u" -#define SCNxLEAST8 "x" -#define SCNXLEAST8 "X" -#define SCNoFAST8 "o" -#define SCNuFAST8 "u" -#define SCNxFAST8 "x" -#define SCNXFAST8 "X" - -#define SCNo16 "ho" -#define SCNu16 "hu" -#define SCNx16 "hx" -#define SCNX16 "hX" -#define SCNoLEAST16 "ho" -#define SCNuLEAST16 "hu" -#define SCNxLEAST16 "hx" -#define SCNXLEAST16 "hX" -#define SCNoFAST16 "ho" -#define SCNuFAST16 "hu" -#define SCNxFAST16 "hx" -#define SCNXFAST16 "hX" - -#define SCNo32 "lo" -#define SCNu32 "lu" -#define SCNx32 "lx" -#define SCNX32 "lX" -#define SCNoLEAST32 "lo" -#define SCNuLEAST32 "lu" -#define SCNxLEAST32 "lx" -#define SCNXLEAST32 "lX" -#define SCNoFAST32 "lo" -#define SCNuFAST32 "lu" -#define SCNxFAST32 "lx" -#define SCNXFAST32 "lX" - -#define SCNo64 "I64o" -#define SCNu64 "I64u" -#define SCNx64 "I64x" -#define SCNX64 "I64X" -#define SCNoLEAST64 "I64o" -#define SCNuLEAST64 "I64u" -#define SCNxLEAST64 "I64x" -#define SCNXLEAST64 "I64X" -#define SCNoFAST64 "I64o" -#define SCNuFAST64 "I64u" -#define SCNxFAST64 "I64x" -#define SCNXFAST64 "I64X" - -#define SCNoMAX "I64o" -#define SCNuMAX "I64u" -#define SCNxMAX "I64x" -#define SCNXMAX "I64X" - -#ifdef _WIN64 // [ -# define SCNoPTR "I64o" -# define SCNuPTR "I64u" -# define SCNxPTR "I64x" -# define SCNXPTR "I64X" -#else // _WIN64 ][ -# define SCNoPTR "lo" -# define SCNuPTR "lu" -# define SCNxPTR "lx" -# define SCNXPTR "lX" -#endif // _WIN64 ] +// DO NOT SUPPORT THE scanf MACROS! See the comment at the top of +// IntegerPrintfMacros.h. #endif // __STDC_FORMAT_MACROS ] diff --git a/mfbt/exported_headers.mk b/mfbt/exported_headers.mk index 79e181eb067..295297a85fe 100644 --- a/mfbt/exported_headers.mk +++ b/mfbt/exported_headers.mk @@ -28,6 +28,7 @@ EXPORTS_mozilla += \ FloatingPoint.h \ GuardObjects.h \ HashFunctions.h \ + IntegerPrintfMacros.h \ Likely.h \ LinkedList.h \ MathAlgorithms.h \ diff --git a/mfbt/tests/TestIntegerPrintfMacros.cpp b/mfbt/tests/TestIntegerPrintfMacros.cpp new file mode 100644 index 00000000000..f5e83f31608 --- /dev/null +++ b/mfbt/tests/TestIntegerPrintfMacros.cpp @@ -0,0 +1,1264 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/Assertions.h" +#include "mozilla/IntegerPrintfMacros.h" // this must pick up + +#include +#include +#include + +/* Output array and poisoning method shared by all tests. */ +static char output[32]; + +static void +PoisonOutput() +{ + memset(output, 0xDA, sizeof(output)); +} + +/* + * The fprintf macros for signed integers are: + * + * PRIdN PRIdLEASTN PRIdFASTN PRIdMAX PRIdPTR + * PRIiN PRIiLEASTN PRIiFASTN PRIiMAX PRIiPTR + * + * In these names N is the width of the type as described in C99 7.18.1. + */ + +static void +TestPrintSigned8() +{ + PoisonOutput(); + sprintf(output, "%" PRId8, int8_t(-17)); + MOZ_ASSERT(!strcmp(output, "-17")); + + PoisonOutput(); + sprintf(output, "%" PRIi8, int8_t(42)); + MOZ_ASSERT(!strcmp(output, "42")); +} + +static void +TestPrintSigned16() +{ + PoisonOutput(); + sprintf(output, "%" PRId16, int16_t(-289)); + MOZ_ASSERT(!strcmp(output, "-289")); + + PoisonOutput(); + sprintf(output, "%" PRIi16, int16_t(728)); + MOZ_ASSERT(!strcmp(output, "728")); +} + +static void +TestPrintSigned32() +{ + PoisonOutput(); + sprintf(output, "%" PRId32, int32_t(-342178)); + MOZ_ASSERT(!strcmp(output, "-342178")); + + PoisonOutput(); + sprintf(output, "%" PRIi32, int32_t(5719283)); + MOZ_ASSERT(!strcmp(output, "5719283")); +} + +static void +TestPrintSigned64() +{ + PoisonOutput(); + sprintf(output, "%" PRId64, int64_t(-INT64_C(432157943248732))); + MOZ_ASSERT(!strcmp(output, "-432157943248732")); + + PoisonOutput(); + sprintf(output, "%" PRIi64, int64_t(INT64_C(325719232983))); + MOZ_ASSERT(!strcmp(output, "325719232983")); +} + +static void +TestPrintSignedN() +{ + TestPrintSigned8(); + TestPrintSigned16(); + TestPrintSigned32(); + TestPrintSigned64(); +} + +static void +TestPrintSignedLeast8() +{ + PoisonOutput(); + sprintf(output, "%" PRIdLEAST8, int_least8_t(-17)); + MOZ_ASSERT(!strcmp(output, "-17")); + + PoisonOutput(); + sprintf(output, "%" PRIiLEAST8, int_least8_t(42)); + MOZ_ASSERT(!strcmp(output, "42")); +} + +static void +TestPrintSignedLeast16() +{ + PoisonOutput(); + sprintf(output, "%" PRIdLEAST16, int_least16_t(-289)); + MOZ_ASSERT(!strcmp(output, "-289")); + + PoisonOutput(); + sprintf(output, "%" PRIiLEAST16, int_least16_t(728)); + MOZ_ASSERT(!strcmp(output, "728")); +} + +static void +TestPrintSignedLeast32() +{ + PoisonOutput(); + sprintf(output, "%" PRIdLEAST32, int_least32_t(-342178)); + MOZ_ASSERT(!strcmp(output, "-342178")); + + PoisonOutput(); + sprintf(output, "%" PRIiLEAST32, int_least32_t(5719283)); + MOZ_ASSERT(!strcmp(output, "5719283")); +} + +static void +TestPrintSignedLeast64() +{ + PoisonOutput(); + sprintf(output, "%" PRIdLEAST64, int_least64_t(-INT64_C(432157943248732))); + MOZ_ASSERT(!strcmp(output, "-432157943248732")); + + PoisonOutput(); + sprintf(output, "%" PRIiLEAST64, int_least64_t(INT64_C(325719232983))); + MOZ_ASSERT(!strcmp(output, "325719232983")); +} + +static void +TestPrintSignedLeastN() +{ + TestPrintSignedLeast8(); + TestPrintSignedLeast16(); + TestPrintSignedLeast32(); + TestPrintSignedLeast64(); +} + +static void +TestPrintSignedFast8() +{ + PoisonOutput(); + sprintf(output, "%" PRIdFAST8, int_fast8_t(-17)); + MOZ_ASSERT(!strcmp(output, "-17")); + + PoisonOutput(); + sprintf(output, "%" PRIiFAST8, int_fast8_t(42)); + MOZ_ASSERT(!strcmp(output, "42")); +} + +static void +TestPrintSignedFast16() +{ + PoisonOutput(); + sprintf(output, "%" PRIdFAST16, int_fast16_t(-289)); + MOZ_ASSERT(!strcmp(output, "-289")); + + PoisonOutput(); + sprintf(output, "%" PRIiFAST16, int_fast16_t(728)); + MOZ_ASSERT(!strcmp(output, "728")); +} + +static void +TestPrintSignedFast32() +{ + PoisonOutput(); + sprintf(output, "%" PRIdFAST32, int_fast32_t(-342178)); + MOZ_ASSERT(!strcmp(output, "-342178")); + + PoisonOutput(); + sprintf(output, "%" PRIiFAST32, int_fast32_t(5719283)); + MOZ_ASSERT(!strcmp(output, "5719283")); +} + +static void +TestPrintSignedFast64() +{ + PoisonOutput(); + sprintf(output, "%" PRIdFAST64, int_fast64_t(-INT64_C(432157943248732))); + MOZ_ASSERT(!strcmp(output, "-432157943248732")); + + PoisonOutput(); + sprintf(output, "%" PRIiFAST64, int_fast64_t(INT64_C(325719232983))); + MOZ_ASSERT(!strcmp(output, "325719232983")); +} + +static void +TestPrintSignedFastN() +{ + TestPrintSignedFast8(); + TestPrintSignedFast16(); + TestPrintSignedFast32(); + TestPrintSignedFast64(); +} + +static void +TestPrintSignedMax() +{ + PoisonOutput(); + sprintf(output, "%" PRIdMAX, intmax_t(-INTMAX_C(432157943248732))); + MOZ_ASSERT(!strcmp(output, "-432157943248732")); + + PoisonOutput(); + sprintf(output, "%" PRIiMAX, intmax_t(INTMAX_C(325719232983))); + MOZ_ASSERT(!strcmp(output, "325719232983")); +} + +static void +TestPrintSignedPtr() +{ + PoisonOutput(); + sprintf(output, "%" PRIdPTR, intptr_t(reinterpret_cast(12345678))); + MOZ_ASSERT(!strcmp(output, "12345678")); + + PoisonOutput(); + sprintf(output, "%" PRIiPTR, intptr_t(reinterpret_cast(87654321))); + MOZ_ASSERT(!strcmp(output, "87654321")); +} + +static void +TestPrintSigned() +{ + TestPrintSignedN(); + TestPrintSignedLeastN(); + TestPrintSignedFastN(); + TestPrintSignedMax(); + TestPrintSignedPtr(); +} + +/* + * The fprintf macros for unsigned integers are: + * + * PRIoN PRIoLEASTN PRIoFASTN PRIoMAX PRIoPTR + * PRIuN PRIuLEASTN PRIuFASTN PRIuMAX PRIuPTR + * PRIxN PRIxLEASTN PRIxFASTN PRIxMAX PRIxPTR + * PRIXN PRIXLEASTN PRIXFASTN PRIXMAX PRIXPTR + * + * In these names N is the width of the type as described in C99 7.18.1. + */ + +static void +TestPrintUnsigned8() +{ + PoisonOutput(); + sprintf(output, "%" PRIo8, uint8_t(042)); + MOZ_ASSERT(!strcmp(output, "42")); + + PoisonOutput(); + sprintf(output, "%" PRIu8, uint8_t(17)); + MOZ_ASSERT(!strcmp(output, "17")); + + PoisonOutput(); + sprintf(output, "%" PRIx8, uint8_t(0x2a)); + MOZ_ASSERT(!strcmp(output, "2a")); + + PoisonOutput(); + sprintf(output, "%" PRIX8, uint8_t(0xCD)); + MOZ_ASSERT(!strcmp(output, "CD")); +} + +static void +TestPrintUnsigned16() +{ + PoisonOutput(); + sprintf(output, "%" PRIo16, uint16_t(04242)); + MOZ_ASSERT(!strcmp(output, "4242")); + + PoisonOutput(); + sprintf(output, "%" PRIu16, uint16_t(1717)); + MOZ_ASSERT(!strcmp(output, "1717")); + + PoisonOutput(); + sprintf(output, "%" PRIx16, uint16_t(0x2a2a)); + MOZ_ASSERT(!strcmp(output, "2a2a")); + + PoisonOutput(); + sprintf(output, "%" PRIX16, uint16_t(0xCDCD)); + MOZ_ASSERT(!strcmp(output, "CDCD")); +} + +static void +TestPrintUnsigned32() +{ + PoisonOutput(); + sprintf(output, "%" PRIo32, uint32_t(0424242)); + MOZ_ASSERT(!strcmp(output, "424242")); + + PoisonOutput(); + sprintf(output, "%" PRIu32, uint32_t(171717)); + MOZ_ASSERT(!strcmp(output, "171717")); + + PoisonOutput(); + sprintf(output, "%" PRIx32, uint32_t(0x2a2a2a)); + MOZ_ASSERT(!strcmp(output, "2a2a2a")); + + PoisonOutput(); + sprintf(output, "%" PRIX32, uint32_t(0xCDCDCD)); + MOZ_ASSERT(!strcmp(output, "CDCDCD")); +} + +static void +TestPrintUnsigned64() +{ + PoisonOutput(); + sprintf(output, "%" PRIo64, uint64_t(UINT64_C(0424242424242))); + MOZ_ASSERT(!strcmp(output, "424242424242")); + + PoisonOutput(); + sprintf(output, "%" PRIu64, uint64_t(UINT64_C(17171717171717171717))); + MOZ_ASSERT(!strcmp(output, "17171717171717171717")); + + PoisonOutput(); + sprintf(output, "%" PRIx64, uint64_t(UINT64_C(0x2a2a2a2a2a2a2a))); + MOZ_ASSERT(!strcmp(output, "2a2a2a2a2a2a2a")); + + PoisonOutput(); + sprintf(output, "%" PRIX64, uint64_t(UINT64_C(0xCDCDCDCDCDCD))); + MOZ_ASSERT(!strcmp(output, "CDCDCDCDCDCD")); +} + +static void +TestPrintUnsignedN() +{ + TestPrintUnsigned8(); + TestPrintUnsigned16(); + TestPrintUnsigned32(); + TestPrintUnsigned64(); +} + +static void +TestPrintUnsignedLeast8() +{ + PoisonOutput(); + sprintf(output, "%" PRIoLEAST8, uint_least8_t(042)); + MOZ_ASSERT(!strcmp(output, "42")); + + PoisonOutput(); + sprintf(output, "%" PRIuLEAST8, uint_least8_t(17)); + MOZ_ASSERT(!strcmp(output, "17")); + + PoisonOutput(); + sprintf(output, "%" PRIxLEAST8, uint_least8_t(0x2a)); + MOZ_ASSERT(!strcmp(output, "2a")); + + PoisonOutput(); + sprintf(output, "%" PRIXLEAST8, uint_least8_t(0xCD)); + MOZ_ASSERT(!strcmp(output, "CD")); +} + +static void +TestPrintUnsignedLeast16() +{ + PoisonOutput(); + sprintf(output, "%" PRIoLEAST16, uint_least16_t(04242)); + MOZ_ASSERT(!strcmp(output, "4242")); + + PoisonOutput(); + sprintf(output, "%" PRIuLEAST16, uint_least16_t(1717)); + MOZ_ASSERT(!strcmp(output, "1717")); + + PoisonOutput(); + sprintf(output, "%" PRIxLEAST16, uint_least16_t(0x2a2a)); + MOZ_ASSERT(!strcmp(output, "2a2a")); + + PoisonOutput(); + sprintf(output, "%" PRIXLEAST16, uint_least16_t(0xCDCD)); + MOZ_ASSERT(!strcmp(output, "CDCD")); +} + +static void +TestPrintUnsignedLeast32() +{ + PoisonOutput(); + sprintf(output, "%" PRIoLEAST32, uint_least32_t(0424242)); + MOZ_ASSERT(!strcmp(output, "424242")); + + PoisonOutput(); + sprintf(output, "%" PRIuLEAST32, uint_least32_t(171717)); + MOZ_ASSERT(!strcmp(output, "171717")); + + PoisonOutput(); + sprintf(output, "%" PRIxLEAST32, uint_least32_t(0x2a2a2a)); + MOZ_ASSERT(!strcmp(output, "2a2a2a")); + + PoisonOutput(); + sprintf(output, "%" PRIXLEAST32, uint_least32_t(0xCDCDCD)); + MOZ_ASSERT(!strcmp(output, "CDCDCD")); +} + +static void +TestPrintUnsignedLeast64() +{ + PoisonOutput(); + sprintf(output, "%" PRIoLEAST64, uint_least64_t(UINT64_C(0424242424242))); + MOZ_ASSERT(!strcmp(output, "424242424242")); + + PoisonOutput(); + sprintf(output, "%" PRIuLEAST64, uint_least64_t(UINT64_C(17171717171717171717))); + MOZ_ASSERT(!strcmp(output, "17171717171717171717")); + + PoisonOutput(); + sprintf(output, "%" PRIxLEAST64, uint_least64_t(UINT64_C(0x2a2a2a2a2a2a2a))); + MOZ_ASSERT(!strcmp(output, "2a2a2a2a2a2a2a")); + + PoisonOutput(); + sprintf(output, "%" PRIXLEAST64, uint_least64_t(UINT64_C(0xCDCDCDCDCDCD))); + MOZ_ASSERT(!strcmp(output, "CDCDCDCDCDCD")); +} + +static void +TestPrintUnsignedLeastN() +{ + TestPrintUnsignedLeast8(); + TestPrintUnsignedLeast16(); + TestPrintUnsignedLeast32(); + TestPrintUnsignedLeast64(); +} + +static void +TestPrintUnsignedFast8() +{ + PoisonOutput(); + sprintf(output, "%" PRIoFAST8, uint_fast8_t(042)); + MOZ_ASSERT(!strcmp(output, "42")); + + PoisonOutput(); + sprintf(output, "%" PRIuFAST8, uint_fast8_t(17)); + MOZ_ASSERT(!strcmp(output, "17")); + + PoisonOutput(); + sprintf(output, "%" PRIxFAST8, uint_fast8_t(0x2a)); + MOZ_ASSERT(!strcmp(output, "2a")); + + PoisonOutput(); + sprintf(output, "%" PRIXFAST8, uint_fast8_t(0xCD)); + MOZ_ASSERT(!strcmp(output, "CD")); +} + +static void +TestPrintUnsignedFast16() +{ + PoisonOutput(); + sprintf(output, "%" PRIoFAST16, uint_fast16_t(04242)); + MOZ_ASSERT(!strcmp(output, "4242")); + + PoisonOutput(); + sprintf(output, "%" PRIuFAST16, uint_fast16_t(1717)); + MOZ_ASSERT(!strcmp(output, "1717")); + + PoisonOutput(); + sprintf(output, "%" PRIxFAST16, uint_fast16_t(0x2a2a)); + MOZ_ASSERT(!strcmp(output, "2a2a")); + + PoisonOutput(); + sprintf(output, "%" PRIXFAST16, uint_fast16_t(0xCDCD)); + MOZ_ASSERT(!strcmp(output, "CDCD")); +} + +static void +TestPrintUnsignedFast32() +{ + PoisonOutput(); + sprintf(output, "%" PRIoFAST32, uint_fast32_t(0424242)); + MOZ_ASSERT(!strcmp(output, "424242")); + + PoisonOutput(); + sprintf(output, "%" PRIuFAST32, uint_fast32_t(171717)); + MOZ_ASSERT(!strcmp(output, "171717")); + + PoisonOutput(); + sprintf(output, "%" PRIxFAST32, uint_fast32_t(0x2a2a2a)); + MOZ_ASSERT(!strcmp(output, "2a2a2a")); + + PoisonOutput(); + sprintf(output, "%" PRIXFAST32, uint_fast32_t(0xCDCDCD)); + MOZ_ASSERT(!strcmp(output, "CDCDCD")); +} + +static void +TestPrintUnsignedFast64() +{ + PoisonOutput(); + sprintf(output, "%" PRIoFAST64, uint_fast64_t(UINT64_C(0424242424242))); + MOZ_ASSERT(!strcmp(output, "424242424242")); + + PoisonOutput(); + sprintf(output, "%" PRIuFAST64, uint_fast64_t(UINT64_C(17171717171717171717))); + MOZ_ASSERT(!strcmp(output, "17171717171717171717")); + + PoisonOutput(); + sprintf(output, "%" PRIxFAST64, uint_fast64_t(UINT64_C(0x2a2a2a2a2a2a2a))); + MOZ_ASSERT(!strcmp(output, "2a2a2a2a2a2a2a")); + + PoisonOutput(); + sprintf(output, "%" PRIXFAST64, uint_fast64_t(UINT64_C(0xCDCDCDCDCDCD))); + MOZ_ASSERT(!strcmp(output, "CDCDCDCDCDCD")); +} + +static void +TestPrintUnsignedFastN() +{ + TestPrintUnsignedFast8(); + TestPrintUnsignedFast16(); + TestPrintUnsignedFast32(); + TestPrintUnsignedFast64(); +} + +static void +TestPrintUnsignedMax() +{ + PoisonOutput(); + sprintf(output, "%" PRIoMAX, uintmax_t(UINTMAX_C(432157943248732))); + MOZ_ASSERT(!strcmp(output, "14220563454333534")); + + PoisonOutput(); + sprintf(output, "%" PRIuMAX, uintmax_t(UINTMAX_C(325719232983))); + MOZ_ASSERT(!strcmp(output, "325719232983")); + + PoisonOutput(); + sprintf(output, "%" PRIxMAX, uintmax_t(UINTMAX_C(327281321873))); + MOZ_ASSERT(!strcmp(output, "4c337ca791")); + + PoisonOutput(); + sprintf(output, "%" PRIXMAX, uintmax_t(UINTMAX_C(912389523743523))); + MOZ_ASSERT(!strcmp(output, "33DD03D75A323")); +} + +static void +TestPrintUnsignedPtr() +{ + PoisonOutput(); + sprintf(output, "%" PRIoPTR, uintptr_t(reinterpret_cast(12345678))); + MOZ_ASSERT(!strcmp(output, "57060516")); + + PoisonOutput(); + sprintf(output, "%" PRIuPTR, uintptr_t(reinterpret_cast(87654321))); + MOZ_ASSERT(!strcmp(output, "87654321")); + + PoisonOutput(); + sprintf(output, "%" PRIxPTR, uintptr_t(reinterpret_cast(0x4c3a791))); + MOZ_ASSERT(!strcmp(output, "4c3a791")); + + PoisonOutput(); + sprintf(output, "%" PRIXPTR, uintptr_t(reinterpret_cast(0xF328DB))); + MOZ_ASSERT(!strcmp(output, "F328DB")); +} + +static void +TestPrintUnsigned() +{ + TestPrintUnsignedN(); + TestPrintUnsignedLeastN(); + TestPrintUnsignedFastN(); + TestPrintUnsignedMax(); + TestPrintUnsignedPtr(); +} + +static void +TestPrint() +{ + TestPrintSigned(); + TestPrintUnsigned(); +} + +/* + * The fscanf macros for signed integers are: + * + * SCNdN SCNdLEASTN SCNdFASTN SCNdMAX SCNdPTR + * SCNiN SCNiLEASTN SCNiFASTN SCNiMAX SCNiPTR + * + * In these names N is the width of the type as described in C99 7.18.1. + */ + +/* + * MSVC's scanf is insufficiently powerful to implement all the SCN* macros. + * Rather than support some subset of them, we instead support none of them. + * See the comment at the top of IntegerPrintfMacros.h. But in case we ever do + * support them, the following tests should adequately test implementation + * correctness. (Indeed, these tests *revealed* MSVC's limitations.) + * + * That said, even if MSVC ever picks up complete support, we still probably + * don't want to support these, because of the undefined-behavior issue noted + * further down in the comment atop IntegerPrintfMacros.h. + */ +#define SHOULD_TEST_SCANF_MACROS 0 + +#if SHOULD_TEST_SCANF_MACROS + +/* + * glibc header definitions for SCN{d,i,o,u,x}{,LEAST,FAST}8 use the "hh" length + * modifier, which is new in C99 (and C++11, by reference). We compile this + * file as C++11, so if "hh" is used in these macros, it's standard. But some + * versions of gcc wrongly think it isn't and warn about a "non-standard" + * modifier. And since these tests mostly exist to verify format-macro/type + * consistency (particularly through compiler warnings about incorrect formats), + * these warnings are unacceptable. So for now, compile tests for those macros + * only if we aren't compiling with gcc. + */ +#define SHOULD_TEST_8BIT_FORMAT_MACROS (!(MOZ_IS_GCC)) + +template +union Input +{ + T i; + unsigned char pun[16]; +}; + +template +static void +PoisonInput(Input& input) +{ + memset(input.pun, 0xDA, sizeof(input.pun)); +} + +template +static bool +ExtraBitsUntouched(const Input& input) +{ + for (size_t i = sizeof(input.i); i < sizeof(input); i++) { + if (input.pun[i] != 0xDA) + return false; + } + + return true; +} + +static void +TestScanSigned8() +{ +#if SHOULD_TEST_8BIT_FORMAT_MACROS + Input u; + + PoisonInput(u); + sscanf("-17", "%" SCNd8, &u.i); + MOZ_ASSERT(u.i == -17); + MOZ_ASSERT(ExtraBitsUntouched(u)); + + PoisonInput(u); + sscanf("042", "%" SCNi8, &u.i); + MOZ_ASSERT(u.i == 042); + MOZ_ASSERT(ExtraBitsUntouched(u)); +#endif +} + +static void +TestScanSigned16() +{ + Input u; + + PoisonInput(u); + sscanf("-1742", "%" SCNd16, &u.i); + MOZ_ASSERT(u.i == -1742); + MOZ_ASSERT(ExtraBitsUntouched(u)); + + PoisonInput(u); + sscanf("04217", "%" SCNi16, &u.i); + MOZ_ASSERT(u.i == 04217); + MOZ_ASSERT(ExtraBitsUntouched(u)); +} + +static void +TestScanSigned32() +{ + Input u; + + PoisonInput(u); + sscanf("-174257", "%" SCNd32, &u.i); + MOZ_ASSERT(u.i == -174257); + MOZ_ASSERT(ExtraBitsUntouched(u)); + + PoisonInput(u); + sscanf("0423571", "%" SCNi32, &u.i); + MOZ_ASSERT(u.i == 0423571); + MOZ_ASSERT(ExtraBitsUntouched(u)); +} + +static void +TestScanSigned64() +{ + Input u; + + PoisonInput(u); + sscanf("-17425238927232", "%" SCNd64, &u.i); + MOZ_ASSERT(u.i == -INT64_C(17425238927232)); + MOZ_ASSERT(ExtraBitsUntouched(u)); + + PoisonInput(u); + sscanf("042333576571", "%" SCNi64, &u.i); + MOZ_ASSERT(u.i == INT64_C(042333576571)); + MOZ_ASSERT(ExtraBitsUntouched(u)); +} + +static void +TestScanSignedN() +{ + TestScanSigned8(); + TestScanSigned16(); + TestScanSigned32(); + TestScanSigned64(); +} + +static void +TestScanSignedLeast8() +{ +#if SHOULD_TEST_8BIT_FORMAT_MACROS + Input u; + + PoisonInput(u); + sscanf("-17", "%" SCNdLEAST8, &u.i); + MOZ_ASSERT(u.i == -17); + MOZ_ASSERT(ExtraBitsUntouched(u)); + + PoisonInput(u); + sscanf("042", "%" SCNiLEAST8, &u.i); + MOZ_ASSERT(u.i == 042); + MOZ_ASSERT(ExtraBitsUntouched(u)); +#endif +} + +static void +TestScanSignedLeast16() +{ + Input u; + + PoisonInput(u); + sscanf("-1742", "%" SCNdLEAST16, &u.i); + MOZ_ASSERT(u.i == -1742); + MOZ_ASSERT(ExtraBitsUntouched(u)); + + PoisonInput(u); + sscanf("04217", "%" SCNiLEAST16, &u.i); + MOZ_ASSERT(u.i == 04217); + MOZ_ASSERT(ExtraBitsUntouched(u)); +} + +static void +TestScanSignedLeast32() +{ + Input u; + + PoisonInput(u); + sscanf("-174257", "%" SCNdLEAST32, &u.i); + MOZ_ASSERT(u.i == -174257); + MOZ_ASSERT(ExtraBitsUntouched(u)); + + PoisonInput(u); + sscanf("0423571", "%" SCNiLEAST32, &u.i); + MOZ_ASSERT(u.i == 0423571); + MOZ_ASSERT(ExtraBitsUntouched(u)); +} + +static void +TestScanSignedLeast64() +{ + Input u; + + PoisonInput(u); + sscanf("-17425238927232", "%" SCNdLEAST64, &u.i); + MOZ_ASSERT(u.i == -INT64_C(17425238927232)); + MOZ_ASSERT(ExtraBitsUntouched(u)); + + PoisonInput(u); + sscanf("042333576571", "%" SCNiLEAST64, &u.i); + MOZ_ASSERT(u.i == INT64_C(042333576571)); + MOZ_ASSERT(ExtraBitsUntouched(u)); +} + +static void +TestScanSignedLeastN() +{ + TestScanSignedLeast8(); + TestScanSignedLeast16(); + TestScanSignedLeast32(); + TestScanSignedLeast64(); +} + +static void +TestScanSignedFast8() +{ +#if SHOULD_TEST_8BIT_FORMAT_MACROS + Input u; + + PoisonInput(u); + sscanf("-17", "%" SCNdFAST8, &u.i); + MOZ_ASSERT(u.i == -17); + MOZ_ASSERT(ExtraBitsUntouched(u)); + + PoisonInput(u); + sscanf("042", "%" SCNiFAST8, &u.i); + MOZ_ASSERT(u.i == 042); + MOZ_ASSERT(ExtraBitsUntouched(u)); +#endif +} + +static void +TestScanSignedFast16() +{ + Input u; + + PoisonInput(u); + sscanf("-1742", "%" SCNdFAST16, &u.i); + MOZ_ASSERT(u.i == -1742); + MOZ_ASSERT(ExtraBitsUntouched(u)); + + PoisonInput(u); + sscanf("04217", "%" SCNiFAST16, &u.i); + MOZ_ASSERT(u.i == 04217); + MOZ_ASSERT(ExtraBitsUntouched(u)); +} + +static void +TestScanSignedFast32() +{ + Input u; + + PoisonInput(u); + sscanf("-174257", "%" SCNdFAST32, &u.i); + MOZ_ASSERT(u.i == -174257); + MOZ_ASSERT(ExtraBitsUntouched(u)); + + PoisonInput(u); + sscanf("0423571", "%" SCNiFAST32, &u.i); + MOZ_ASSERT(u.i == 0423571); + MOZ_ASSERT(ExtraBitsUntouched(u)); +} + +static void +TestScanSignedFast64() +{ + Input u; + + PoisonInput(u); + sscanf("-17425238927232", "%" SCNdFAST64, &u.i); + MOZ_ASSERT(u.i == -INT64_C(17425238927232)); + MOZ_ASSERT(ExtraBitsUntouched(u)); + + PoisonInput(u); + sscanf("042333576571", "%" SCNiFAST64, &u.i); + MOZ_ASSERT(u.i == INT64_C(042333576571)); + MOZ_ASSERT(ExtraBitsUntouched(u)); +} + +static void +TestScanSignedFastN() +{ + TestScanSignedFast8(); + TestScanSignedFast16(); + TestScanSignedFast32(); + TestScanSignedFast64(); +} + +static void +TestScanSignedMax() +{ + Input u; + + PoisonInput(u); + sscanf("-432157943248732", "%" SCNdMAX, &u.i); + MOZ_ASSERT(u.i == -INTMAX_C(432157943248732)); + MOZ_ASSERT(ExtraBitsUntouched(u)); + + PoisonInput(u); + sscanf("04233357236571", "%" SCNiMAX, &u.i); + MOZ_ASSERT(u.i == INTMAX_C(04233357236571)); + MOZ_ASSERT(ExtraBitsUntouched(u)); +} + +static void +TestScanSignedPtr() +{ + Input u; + + PoisonInput(u); + sscanf("12345678", "%" SCNdPTR, &u.i); + MOZ_ASSERT(u.i == intptr_t(reinterpret_cast(12345678))); + MOZ_ASSERT(ExtraBitsUntouched(u)); + + PoisonInput(u); + sscanf("04233357236", "%" SCNiPTR, &u.i); + MOZ_ASSERT(u.i == intptr_t(reinterpret_cast(04233357236))); + MOZ_ASSERT(ExtraBitsUntouched(u)); +} + +static void +TestScanSigned() +{ + TestScanSignedN(); + TestScanSignedLeastN(); + TestScanSignedFastN(); + TestScanSignedMax(); + TestScanSignedPtr(); +} + +/* + * The fscanf macros for unsigned integers are: + * + * SCNoN SCNoLEASTN SCNoFASTN SCNoMAX SCNoPTR + * SCNuN SCNuLEASTN SCNuFASTN SCNuMAX SCNuPTR + * SCNxN SCNxLEASTN SCNxFASTN SCNxMAX SCNxPTR + * + * In these names N is the width of the type as described in C99 7.18.1. + */ + +static void +TestScanUnsigned8() +{ +#if SHOULD_TEST_8BIT_FORMAT_MACROS + Input u; + + PoisonInput(u); + sscanf("17", "%" SCNo8, &u.i); + MOZ_ASSERT(u.i == 017); + MOZ_ASSERT(ExtraBitsUntouched(u)); + + PoisonInput(u); + sscanf("42", "%" SCNu8, &u.i); + MOZ_ASSERT(u.i == 42); + MOZ_ASSERT(ExtraBitsUntouched(u)); + + PoisonInput(u); + sscanf("2A", "%" SCNx8, &u.i); + MOZ_ASSERT(u.i == 0x2A); + MOZ_ASSERT(ExtraBitsUntouched(u)); +#endif +} + +static void +TestScanUnsigned16() +{ + Input u; + + PoisonInput(u); + sscanf("1742", "%" SCNo16, &u.i); + MOZ_ASSERT(u.i == 01742); + MOZ_ASSERT(ExtraBitsUntouched(u)); + + PoisonInput(u); + sscanf("4217", "%" SCNu16, &u.i); + MOZ_ASSERT(u.i == 4217); + MOZ_ASSERT(ExtraBitsUntouched(u)); + + PoisonInput(u); + sscanf("2ABC", "%" SCNx16, &u.i); + MOZ_ASSERT(u.i == 0x2ABC); + MOZ_ASSERT(ExtraBitsUntouched(u)); +} + +static void +TestScanUnsigned32() +{ + Input u; + + PoisonInput(u); + sscanf("17421742", "%" SCNo32, &u.i); + MOZ_ASSERT(u.i == 017421742); + MOZ_ASSERT(ExtraBitsUntouched(u)); + + PoisonInput(u); + sscanf("4217867", "%" SCNu32, &u.i); + MOZ_ASSERT(u.i == 4217867); + MOZ_ASSERT(ExtraBitsUntouched(u)); + + PoisonInput(u); + sscanf("2ABCBEEF", "%" SCNx32, &u.i); + MOZ_ASSERT(u.i == 0x2ABCBEEF); + MOZ_ASSERT(ExtraBitsUntouched(u)); +} + +static void +TestScanUnsigned64() +{ + Input u; + + PoisonInput(u); + sscanf("17421742173", "%" SCNo64, &u.i); + MOZ_ASSERT(u.i == UINT64_C(017421742173)); + MOZ_ASSERT(ExtraBitsUntouched(u)); + + PoisonInput(u); + sscanf("421786713579", "%" SCNu64, &u.i); + MOZ_ASSERT(u.i == UINT64_C(421786713579)); + MOZ_ASSERT(ExtraBitsUntouched(u)); + + PoisonInput(u); + sscanf("DEADBEEF7457E", "%" SCNx64, &u.i); + MOZ_ASSERT(u.i == UINT64_C(0xDEADBEEF7457E)); + MOZ_ASSERT(ExtraBitsUntouched(u)); +} + +static void +TestScanUnsignedN() +{ + TestScanUnsigned8(); + TestScanUnsigned16(); + TestScanUnsigned32(); + TestScanUnsigned64(); +} + +static void +TestScanUnsignedLeast8() +{ +#if SHOULD_TEST_8BIT_FORMAT_MACROS + Input u; + + PoisonInput(u); + sscanf("17", "%" SCNoLEAST8, &u.i); + MOZ_ASSERT(u.i == 017); + MOZ_ASSERT(ExtraBitsUntouched(u)); + + PoisonInput(u); + sscanf("42", "%" SCNuLEAST8, &u.i); + MOZ_ASSERT(u.i == 42); + MOZ_ASSERT(ExtraBitsUntouched(u)); + + PoisonInput(u); + sscanf("2A", "%" SCNxLEAST8, &u.i); + MOZ_ASSERT(u.i == 0x2A); + MOZ_ASSERT(ExtraBitsUntouched(u)); +#endif +} + +static void +TestScanUnsignedLeast16() +{ + Input u; + + PoisonInput(u); + sscanf("1742", "%" SCNoLEAST16, &u.i); + MOZ_ASSERT(u.i == 01742); + MOZ_ASSERT(ExtraBitsUntouched(u)); + + PoisonInput(u); + sscanf("4217", "%" SCNuLEAST16, &u.i); + MOZ_ASSERT(u.i == 4217); + MOZ_ASSERT(ExtraBitsUntouched(u)); + + PoisonInput(u); + sscanf("2ABC", "%" SCNxLEAST16, &u.i); + MOZ_ASSERT(u.i == 0x2ABC); + MOZ_ASSERT(ExtraBitsUntouched(u)); +} + +static void +TestScanUnsignedLeast32() +{ + Input u; + + PoisonInput(u); + sscanf("17421742", "%" SCNoLEAST32, &u.i); + MOZ_ASSERT(u.i == 017421742); + MOZ_ASSERT(ExtraBitsUntouched(u)); + + PoisonInput(u); + sscanf("4217867", "%" SCNuLEAST32, &u.i); + MOZ_ASSERT(u.i == 4217867); + MOZ_ASSERT(ExtraBitsUntouched(u)); + + PoisonInput(u); + sscanf("2ABCBEEF", "%" SCNxLEAST32, &u.i); + MOZ_ASSERT(u.i == 0x2ABCBEEF); + MOZ_ASSERT(ExtraBitsUntouched(u)); +} + +static void +TestScanUnsignedLeast64() +{ + Input u; + + PoisonInput(u); + sscanf("17421742173", "%" SCNoLEAST64, &u.i); + MOZ_ASSERT(u.i == UINT64_C(017421742173)); + MOZ_ASSERT(ExtraBitsUntouched(u)); + + PoisonInput(u); + sscanf("421786713579", "%" SCNuLEAST64, &u.i); + MOZ_ASSERT(u.i == UINT64_C(421786713579)); + MOZ_ASSERT(ExtraBitsUntouched(u)); + + PoisonInput(u); + sscanf("DEADBEEF7457E", "%" SCNxLEAST64, &u.i); + MOZ_ASSERT(u.i == UINT64_C(0xDEADBEEF7457E)); + MOZ_ASSERT(ExtraBitsUntouched(u)); +} + +static void +TestScanUnsignedLeastN() +{ + TestScanUnsignedLeast8(); + TestScanUnsignedLeast16(); + TestScanUnsignedLeast32(); + TestScanUnsignedLeast64(); +} + +static void +TestScanUnsignedFast8() +{ +#if SHOULD_TEST_8BIT_FORMAT_MACROS + Input u; + + PoisonInput(u); + sscanf("17", "%" SCNoFAST8, &u.i); + MOZ_ASSERT(u.i == 017); + MOZ_ASSERT(ExtraBitsUntouched(u)); + + PoisonInput(u); + sscanf("42", "%" SCNuFAST8, &u.i); + MOZ_ASSERT(u.i == 42); + MOZ_ASSERT(ExtraBitsUntouched(u)); + + PoisonInput(u); + sscanf("2A", "%" SCNxFAST8, &u.i); + MOZ_ASSERT(u.i == 0x2A); + MOZ_ASSERT(ExtraBitsUntouched(u)); +#endif +} + +static void +TestScanUnsignedFast16() +{ + Input u; + + PoisonInput(u); + sscanf("1742", "%" SCNoFAST16, &u.i); + MOZ_ASSERT(u.i == 01742); + MOZ_ASSERT(ExtraBitsUntouched(u)); + + PoisonInput(u); + sscanf("4217", "%" SCNuFAST16, &u.i); + MOZ_ASSERT(u.i == 4217); + MOZ_ASSERT(ExtraBitsUntouched(u)); + + PoisonInput(u); + sscanf("2ABC", "%" SCNxFAST16, &u.i); + MOZ_ASSERT(u.i == 0x2ABC); + MOZ_ASSERT(ExtraBitsUntouched(u)); +} + +static void +TestScanUnsignedFast32() +{ + Input u; + + PoisonInput(u); + sscanf("17421742", "%" SCNoFAST32, &u.i); + MOZ_ASSERT(u.i == 017421742); + MOZ_ASSERT(ExtraBitsUntouched(u)); + + PoisonInput(u); + sscanf("4217867", "%" SCNuFAST32, &u.i); + MOZ_ASSERT(u.i == 4217867); + MOZ_ASSERT(ExtraBitsUntouched(u)); + + PoisonInput(u); + sscanf("2ABCBEEF", "%" SCNxFAST32, &u.i); + MOZ_ASSERT(u.i == 0x2ABCBEEF); + MOZ_ASSERT(ExtraBitsUntouched(u)); +} + +static void +TestScanUnsignedFast64() +{ + Input u; + + PoisonInput(u); + sscanf("17421742173", "%" SCNoFAST64, &u.i); + MOZ_ASSERT(u.i == UINT64_C(017421742173)); + MOZ_ASSERT(ExtraBitsUntouched(u)); + + PoisonInput(u); + sscanf("421786713579", "%" SCNuFAST64, &u.i); + MOZ_ASSERT(u.i == UINT64_C(421786713579)); + MOZ_ASSERT(ExtraBitsUntouched(u)); + + PoisonInput(u); + sscanf("DEADBEEF7457E", "%" SCNxFAST64, &u.i); + MOZ_ASSERT(u.i == UINT64_C(0xDEADBEEF7457E)); + MOZ_ASSERT(ExtraBitsUntouched(u)); +} + +static void +TestScanUnsignedFastN() +{ + TestScanUnsignedFast8(); + TestScanUnsignedFast16(); + TestScanUnsignedFast32(); + TestScanUnsignedFast64(); +} + +static void +TestScanUnsignedMax() +{ + Input u; + + PoisonInput(u); + sscanf("14220563454333534", "%" SCNoMAX, &u.i); + MOZ_ASSERT(u.i == UINTMAX_C(432157943248732)); + MOZ_ASSERT(ExtraBitsUntouched(u)); + + PoisonInput(u); + sscanf("432157943248732", "%" SCNuMAX, &u.i); + MOZ_ASSERT(u.i == UINTMAX_C(432157943248732)); + MOZ_ASSERT(ExtraBitsUntouched(u)); + + PoisonInput(u); + sscanf("4c337ca791", "%" SCNxMAX, &u.i); + MOZ_ASSERT(u.i == UINTMAX_C(327281321873)); + MOZ_ASSERT(ExtraBitsUntouched(u)); +} + +static void +TestScanUnsignedPtr() +{ + Input u; + + PoisonInput(u); + sscanf("57060516", "%" SCNoPTR, &u.i); + MOZ_ASSERT(u.i == uintptr_t(reinterpret_cast(12345678))); + MOZ_ASSERT(ExtraBitsUntouched(u)); + + PoisonInput(u); + sscanf("87654321", "%" SCNuPTR, &u.i); + MOZ_ASSERT(u.i == uintptr_t(reinterpret_cast(87654321))); + MOZ_ASSERT(ExtraBitsUntouched(u)); + + PoisonInput(u); + sscanf("4c3a791", "%" SCNxPTR, &u.i); + MOZ_ASSERT(u.i == uintptr_t(reinterpret_cast(0x4c3a791))); + MOZ_ASSERT(ExtraBitsUntouched(u)); +} + +static void +TestScanUnsigned() +{ + TestScanUnsignedN(); + TestScanUnsignedLeastN(); + TestScanUnsignedFastN(); + TestScanUnsignedMax(); + TestScanUnsignedPtr(); +} + +static void +TestScan() +{ + TestScanSigned(); + TestScanUnsigned(); +} + +#endif /* SHOULD_TEST_SCANF_MACROS */ + +int +main() +{ + TestPrint(); +#if SHOULD_TEST_SCANF_MACROS + TestScan(); +#endif + return 0; +} diff --git a/mfbt/tests/TestPoisonArea.cpp b/mfbt/tests/TestPoisonArea.cpp index 062422dabb6..233b4a2b081 100644 --- a/mfbt/tests/TestPoisonArea.cpp +++ b/mfbt/tests/TestPoisonArea.cpp @@ -79,24 +79,15 @@ * at all. Thus, it is not used here. */ +#include "mozilla/IntegerPrintfMacros.h" #include "mozilla/NullPtr.h" -// MAP_ANON(YMOUS) is not in any standard, and the C99 PRI* macros are -// not in C++98. Add defines as necessary. -#define __STDC_FORMAT_MACROS +// MAP_ANON(YMOUS) is not in any standard. Add defines as necessary. #define _GNU_SOURCE 1 #define _DARWIN_C_SOURCE 1 #include -#ifndef _WIN32 -#include -#else -#define PRIxPTR "Ix" -typedef unsigned int uint32_t; -// MSVC defines uintptr_t in which is brought in implicitly -#endif - #include #include #include diff --git a/mfbt/tests/moz.build b/mfbt/tests/moz.build index e57d43d4f2c..1da3210d0c9 100644 --- a/mfbt/tests/moz.build +++ b/mfbt/tests/moz.build @@ -14,6 +14,7 @@ CPP_UNIT_TESTS += [ 'TestEndian.cpp', 'TestEnumSet.cpp', 'TestFloatingPoint.cpp', + 'TestIntegerPrintfMacros.cpp', 'TestSHA1.cpp', 'TestTypeTraits.cpp', 'TestWeakPtr.cpp', diff --git a/mozilla-config.h.in b/mozilla-config.h.in index 4957a260c80..295f2bfe3c8 100644 --- a/mozilla-config.h.in +++ b/mozilla-config.h.in @@ -8,13 +8,24 @@ @ALLDEFINES@ -/* The c99 defining the limit macros (UINT32_MAX for example), says: - * C++ implementations should define these macros only when __STDC_LIMIT_MACROS - * is defined before is included. */ +/* + * The c99 defining the limit macros (UINT32_MAX for example), says: + * + * C++ implementations should define these macros only when + * __STDC_LIMIT_MACROS is defined before is included. + * + * The same also occurs with __STDC_CONSTANT_MACROS for the constant macros + * (INT8_C for example) used to specify a literal constant of the proper type, + * and with __STDC_FORMAT_MACROS for the format macros (PRId32 for example) used + * with the fprintf function family. + */ #define __STDC_LIMIT_MACROS +#define __STDC_CONSTANT_MACROS +#define __STDC_FORMAT_MACROS -/* Force-include hunspell_alloc_hooks.h and hunspell_fopen_hooks.h for hunspell, - * so that we don't need to modify it directly. +/* + * Force-include hunspell_alloc_hooks.h and hunspell_fopen_hooks.h for hunspell, + * so that we don't need to modify them directly. * * HUNSPELL_STATIC is defined in extensions/spellcheck/hunspell/src/Makefile.in, * unless --enable-system-hunspell is defined. diff --git a/security/manager/boot/src/Makefile.in b/security/manager/boot/src/Makefile.in index 63ed85672c2..98ad1033e0f 100644 --- a/security/manager/boot/src/Makefile.in +++ b/security/manager/boot/src/Makefile.in @@ -10,7 +10,6 @@ VPATH = @srcdir@ include $(DEPTH)/config/autoconf.mk EXPORT_LIBRARY = 1 -DEFINES += -D__STDC_CONSTANT_MACROS include $(topsrcdir)/config/rules.mk From 7f14ff52739422af2dcef45e80c35939ea1e1ac7 Mon Sep 17 00:00:00 2001 From: "J. Ryan Stinnett" Date: Sat, 31 Aug 2013 02:34:26 +0200 Subject: [PATCH 09/64] Bug 911127 - Repair DebuggerServer loading on B2G. r=dcamp --- toolkit/devtools/server/dbg-server.jsm | 30 ++++++++++++++---- toolkit/devtools/server/main.js | 44 +++++++++++++++++++++++--- 2 files changed, 63 insertions(+), 11 deletions(-) diff --git a/toolkit/devtools/server/dbg-server.jsm b/toolkit/devtools/server/dbg-server.jsm index 55988c3295f..0fc4d1a783d 100644 --- a/toolkit/devtools/server/dbg-server.jsm +++ b/toolkit/devtools/server/dbg-server.jsm @@ -5,7 +5,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ "use strict"; - /** * Loads the remote debugging protocol code into a sandbox, in order to * shield it from the debuggee. This way, when debugging chrome globals, @@ -16,11 +15,30 @@ const Ci = Components.interfaces; const Cc = Components.classes; const Cu = Components.utils; -const { devtools } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}); - this.EXPORTED_SYMBOLS = ["DebuggerServer", "ActorPool"]; -let server = devtools.require("devtools/server/main"); +var loadSubScript = + "function loadSubScript(aURL)\n" + + "{\n" + + "const Ci = Components.interfaces;\n" + + "const Cc = Components.classes;\n" + + " try {\n" + + " let loader = Cc[\"@mozilla.org/moz/jssubscript-loader;1\"]\n" + + " .getService(Ci.mozIJSSubScriptLoader);\n" + + " loader.loadSubScript(aURL, this);\n" + + " } catch(e) {\n" + + " dump(\"Error loading: \" + aURL + \": \" + e + \" - \" + e.stack + \"\\n\");\n" + + " throw e;\n" + + " }\n" + + "}"; -this.DebuggerServer = server.DebuggerServer; -this.ActorPool = server.ActorPool; +// Load the debugging server in a sandbox with its own compartment. +var systemPrincipal = Cc["@mozilla.org/systemprincipal;1"] + .createInstance(Ci.nsIPrincipal); + +var gGlobal = Cu.Sandbox(systemPrincipal); +Cu.evalInSandbox(loadSubScript, gGlobal, "1.8"); +gGlobal.loadSubScript("resource://gre/modules/devtools/server/main.js"); + +this.DebuggerServer = gGlobal.DebuggerServer; +this.ActorPool = gGlobal.ActorPool; diff --git a/toolkit/devtools/server/main.js b/toolkit/devtools/server/main.js index f4377291f40..bc084396b91 100644 --- a/toolkit/devtools/server/main.js +++ b/toolkit/devtools/server/main.js @@ -10,7 +10,37 @@ * debugging global. */ -const { Ci, Cc, CC, Cu, Cr, components: Components } = require("chrome"); +// |this.require| is used to test if this file was loaded via the devtools +// loader (as it is in DebuggerProcess.jsm) or via loadSubScript (as it is from +// dbg-server.jsm). Note that testing |require| is not safe in either +// situation, as it causes a ReferenceError. +var Ci, Cc, CC, Cu, Cr, Components; +if (this.require) { + ({ Ci, Cc, CC, Cu, Cr, components: Components }) = require("chrome"); +} else { + ({ + interfaces: Ci, + classes: Cc, + Constructor: CC, + utils: Cu, + results: Cr + }) = Components; +} + +// On B2G, if |this.require| is undefined at this point, it remains undefined +// later on when |DebuggerServer.registerModule| is called. On desktop (and +// perhaps other places), if |this.require| starts out undefined, it ends up +// being set to some native code by the time we get to |registerModule|. Here +// we perform a test early on, and then cache the correct require function for +// later use. +var localRequire; +if (this.require) { + localRequire = id => require(id); +} else { + let { devtools } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}); + localRequire = id => devtools.require(id); +} + const DBG_STRINGS_URI = "chrome://global/locale/devtools/debugger.properties"; Cu.import("resource://gre/modules/Services.jsm"); @@ -35,7 +65,7 @@ function loadSubScript(aURL) } } -let loaderRequire = require; +let loaderRequire = this.require; this.require = null; loadSubScript.call(this, "resource://gre/modules/commonjs/sdk/core/promise.js"); this.require = loaderRequire; @@ -272,7 +302,7 @@ var DebuggerServer = { } let moduleAPI = ModuleAPI(); - let mod = require(id); + let mod = localRequire(id); mod.register(moduleAPI); gRegisteredModules[id] = { module: mod, api: moduleAPI }; }, @@ -618,7 +648,9 @@ var DebuggerServer = { } }; -exports.DebuggerServer = DebuggerServer; +if (this.exports) { + exports.DebuggerServer = DebuggerServer; +} /** * Construct an ActorPool. @@ -634,7 +666,9 @@ function ActorPool(aConnection) this._actors = {}; } -exports.ActorPool = ActorPool; +if (this.exports) { + exports.ActorPool = ActorPool; +} ActorPool.prototype = { /** From a9983278f053cc09d09377ffd27aab94d9cf463a Mon Sep 17 00:00:00 2001 From: Irving Reid Date: Tue, 3 Sep 2013 10:43:01 -0400 Subject: [PATCH 10/64] Bug 911014: Register unload handler even if dialog delay pref is zero; r=unfocused --- toolkit/mozapps/extensions/content/xpinstallConfirm.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/toolkit/mozapps/extensions/content/xpinstallConfirm.js b/toolkit/mozapps/extensions/content/xpinstallConfirm.js index c6eb799ddaf..dda761ab853 100644 --- a/toolkit/mozapps/extensions/content/xpinstallConfirm.js +++ b/toolkit/mozapps/extensions/content/xpinstallConfirm.js @@ -120,8 +120,10 @@ XPInstallConfirm.init = function XPInstallConfirm_init() } function myUnload() { - document.removeEventListener("focus", myfocus, true); - document.removeEventListener("blur", myblur, true); + if (_installCountdownLength > 0) { + document.removeEventListener("focus", myfocus, true); + document.removeEventListener("blur", myblur, true); + } window.removeEventListener("unload", myUnload, false); // Now perform the desired action - either install the @@ -136,10 +138,11 @@ XPInstallConfirm.init = function XPInstallConfirm_init() } } + window.addEventListener("unload", myUnload, false); + if (_installCountdownLength > 0) { document.addEventListener("focus", myfocus, true); document.addEventListener("blur", myblur, true); - window.addEventListener("unload", myUnload, false); okButton.disabled = true; setWidgetsAfterFocus(); From 5351218dbcb6a4f0e843628d5ca143081837f090 Mon Sep 17 00:00:00 2001 From: Alexandre Poirot Date: Tue, 3 Sep 2013 12:51:24 -0400 Subject: [PATCH 11/64] Bug 900972 - Ensure emitting appOpen event for apps being opened before the call to watchApps. r=paul.rouget --- toolkit/devtools/server/actors/webapps.js | 43 ++++++++--------------- 1 file changed, 15 insertions(+), 28 deletions(-) diff --git a/toolkit/devtools/server/actors/webapps.js b/toolkit/devtools/server/actors/webapps.js index bd8baaad4f7..660387eb763 100644 --- a/toolkit/devtools/server/actors/webapps.js +++ b/toolkit/devtools/server/actors/webapps.js @@ -573,7 +573,7 @@ WebappsActor.prototype = { }, watchApps: function () { - this._framesByOrigin = {}; + this._openedApps = new Set(); let chromeWindow = Services.wm.getMostRecentWindow('navigator:browser'); let systemAppFrame = chromeWindow.getContentWindow(); systemAppFrame.addEventListener("appwillopen", this); @@ -583,7 +583,7 @@ WebappsActor.prototype = { }, unwatchApps: function () { - this._framesByOrigin = null; + this._openedApps = null; let chromeWindow = Services.wm.getMostRecentWindow('navigator:browser'); let systemAppFrame = chromeWindow.getContentWindow(); systemAppFrame.removeEventListener("appwillopen", this); @@ -593,46 +593,33 @@ WebappsActor.prototype = { }, handleEvent: function (event) { - let frame; - let origin = event.detail.origin; + let manifestURL; switch(event.type) { case "appwillopen": - frame = event.target; + let frame = event.target; + manifestURL = frame.getAttribute("mozapp") + // Ignore the event if we already received an appwillopen for this app // (appwillopen is also fired when the app has been moved to background // and get back to foreground) - let mm = frame.QueryInterface(Ci.nsIFrameLoaderOwner) - .frameLoader - .messageManager; - if (this._appActorsMap.has(mm)) { + if (this._openedApps.has(manifestURL)) { return; } - - // Workaround to be able to get the related frame on `appterminated`. - // `appterminated` event being dispatched by gaia only comes app origin - // whereas we need to get the its manifest URL, that we can fetch - // on the app frame. - this._framesByOrigin[origin] = frame; + this._openedApps.add(manifestURL); this.conn.send({ from: this.actorID, type: "appOpen", - manifestURL: frame.getAttribute("mozapp") + manifestURL: manifestURL }); break; case "appterminated": - // Get the related app frame out of this event - // TODO: eventually fire the event on the frame or at least use - // manifestURL as key (and propagate manifestURL via event detail) - frame = this._framesByOrigin[origin]; - delete this._framesByOrigin[origin]; - if (frame) { - let manifestURL = frame.getAttribute("mozapp"); - this.conn.send({ from: this.actorID, - type: "appClose", - manifestURL: manifestURL - }); - } + manifestURL = event.detail.manifestURL; + this._openedApps.delete(manifestURL); + this.conn.send({ from: this.actorID, + type: "appClose", + manifestURL: manifestURL + }); break; } } From 0b2bcea602edcb6083278f32dd68b1e9cae4dd57 Mon Sep 17 00:00:00 2001 From: Eklavya Mirani Date: Tue, 3 Sep 2013 09:52:29 -0700 Subject: [PATCH 12/64] Bug 878691 - Use FormHistory.jsm instead of nsIFormHistory2 in metro; r=mbrubeck --- browser/metro/base/content/browser-scripts.js | 3 + browser/metro/base/content/browser-ui.js | 2 - browser/metro/base/content/sanitize.js | 76 +++++++++++-------- .../mochitest/browser_form_auto_complete.js | 3 +- 4 files changed, 47 insertions(+), 37 deletions(-) diff --git a/browser/metro/base/content/browser-scripts.js b/browser/metro/base/content/browser-scripts.js index 8d1255cbb14..d5785a59a86 100644 --- a/browser/metro/base/content/browser-scripts.js +++ b/browser/metro/base/content/browser-scripts.js @@ -10,6 +10,9 @@ Cu.import("resource://gre/modules/Services.jsm"); * JS modules */ +XPCOMUtils.defineLazyModuleGetter(this , "FormHistory", + "resource://gre/modules/FormHistory.jsm"); + XPCOMUtils.defineLazyModuleGetter(this, "PluralForm", "resource://gre/modules/PluralForm.jsm"); diff --git a/browser/metro/base/content/browser-ui.js b/browser/metro/base/content/browser-ui.js index 381736845f6..6106005e1cf 100644 --- a/browser/metro/base/content/browser-ui.js +++ b/browser/metro/base/content/browser-ui.js @@ -143,8 +143,6 @@ var BrowserUI = { // Login Manager and Form History initialization Cc["@mozilla.org/login-manager;1"].getService(Ci.nsILoginManager); - Cc["@mozilla.org/satchel/form-history;1"].getService(Ci.nsIFormHistory2); - messageManager.addMessageListener("Browser:MozApplicationManifest", OfflineApps); try { diff --git a/browser/metro/base/content/sanitize.js b/browser/metro/base/content/sanitize.js index 28ce7552747..68844950f05 100644 --- a/browser/metro/base/content/sanitize.js +++ b/browser/metro/base/content/sanitize.js @@ -3,10 +3,6 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils", - "resource://gre/modules/PlacesUtils.jsm"); - function Sanitizer() {} Sanitizer.prototype = { @@ -17,17 +13,22 @@ Sanitizer.prototype = { this.items[aItemName].clear(); }, - canClearItem: function (aItemName) + canClearItem: function (aItemName, aCallback, aArg) { - return this.items[aItemName].canClear; + let canClear = this.items[aItemName].canClear; + if (typeof canClear == "function"){ + canClear(aCallback, aArg); + } else { + aCallback(aItemName, canClear, aArg); + } }, - + _prefDomain: "privacy.item.", getNameFromPreference: function (aPreferenceName) { return aPreferenceName.substr(this._prefDomain.length); }, - + /** * Deletes privacy sensitive data in a batch, according to user preferences * @@ -39,26 +40,32 @@ Sanitizer.prototype = { var branch = Services.prefs.getBranch(this._prefDomain); var errors = null; for (var itemName in this.items) { - var item = this.items[itemName]; - if ("clear" in item && item.canClear && branch.getBoolPref(itemName)) { + if ("clear" in item && branch.getBoolPref(itemName)) { // Some of these clear() may raise exceptions (see bug #265028) // to sanitize as much as possible, we catch and store them, // rather than fail fast. // Callers should check returned errors and give user feedback // about items that could not be sanitized - try { - item.clear(); - } catch(er) { - if (!errors) - errors = {}; - errors[itemName] = er; - dump("Error sanitizing " + itemName + ": " + er + "\n"); + let clearCallback = (itemName, aCanClear) => { + let item = this.items[itemName]; + try{ + if (aCanClear){ + item.clear(); + } + } catch(er){ + if (!errors){ + errors = {}; + } + errors[itemName] = er; + dump("Error sanitizing " + itemName + ":" + er + "\n"); + } } + this.canClearItem(itemName, clearCallback); } } return errors; }, - + items: { // Clear Sync account before passwords so that Sync still has access to the // credentials to clean up device-specific records on the server. Also @@ -88,20 +95,20 @@ Sanitizer.prototype = { imageCache.clearCache(false); // true=chrome, false=content } catch(er) {} }, - + get canClear() { return true; } }, - + cookies: { clear: function () { var cookieMgr = Cc["@mozilla.org/cookiemanager;1"].getService(Ci.nsICookieManager); cookieMgr.removeAll(); }, - + get canClear() { return true; @@ -185,18 +192,21 @@ Sanitizer.prototype = { searchBar.textbox.editor.transactionManager.clear(); } } - - var formHistory = Cc["@mozilla.org/satchel/form-history;1"].getService(Ci.nsIFormHistory2); - formHistory.removeAllEntries(); + FormHistory.update({op : "remove"}); }, - - get canClear() + + canClear : function(aCallback, aArg) { - var formHistory = Cc["@mozilla.org/satchel/form-history;1"].getService(Ci.nsIFormHistory2); - return formHistory.hasEntries; + let count = 0; + let countDone = { + handleResult : function(aResult) { count = aResult; }, + handleError : function(aError) { Components.utils.reportError(aError); }, + handleCompletion : function(aReason) { aCallback("formdata", aReason == 0 && count > 0, aArg); } + }; + FormHistory.count({}, countDone); } }, - + downloads: { clear: function () { @@ -210,14 +220,14 @@ Sanitizer.prototype = { return dlMgr.canCleanUp; } }, - + passwords: { clear: function () { var pwmgr = Cc["@mozilla.org/login-manager;1"].getService(Ci.nsILoginManager); pwmgr.removeAllLogins(); }, - + get canClear() { var pwmgr = Cc["@mozilla.org/login-manager;1"].getService(Ci.nsILoginManager); @@ -225,7 +235,7 @@ Sanitizer.prototype = { return (count > 0); } }, - + sessions: { clear: function () { @@ -237,7 +247,7 @@ Sanitizer.prototype = { var authMgr = Cc['@mozilla.org/network/http-auth-manager;1'].getService(Ci.nsIHttpAuthManager); authMgr.clearAll(); }, - + get canClear() { return true; diff --git a/browser/metro/base/tests/mochitest/browser_form_auto_complete.js b/browser/metro/base/tests/mochitest/browser_form_auto_complete.js index 2be327e4a8e..f61a48f7f40 100644 --- a/browser/metro/base/tests/mochitest/browser_form_auto_complete.js +++ b/browser/metro/base/tests/mochitest/browser_form_auto_complete.js @@ -6,8 +6,7 @@ "use strict"; function clearFormHistory() { - var formHistory = Cc["@mozilla.org/satchel/form-history;1"].getService(Ci.nsIFormHistory2); - formHistory.removeAllEntries(); + FormHistory.update({ op : "remove" }); } function test() { From fa0f6309b53c90d7b682d26d2960347fc75d23db Mon Sep 17 00:00:00 2001 From: Chenxia Liu Date: Thu, 11 Apr 2013 09:53:15 +0300 Subject: [PATCH 13/64] Bug 908737 - Robocop: upgrade to robotium-solo-4.2.jar. r=gbrown --- build/mobile/robocop/Actions.java.in | 7 ---- .../robocop/FennecNativeActions.java.in | 35 ------------------ build/mobile/robocop/Makefile.in | 2 +- build/mobile/robocop/README | 2 +- build/mobile/robocop/robotium-solo-3.6.jar | Bin 59067 -> 0 bytes build/mobile/robocop/robotium-solo-4.2.jar | Bin 0 -> 104697 bytes .../android/base/tests/AboutHomeTest.java.in | 2 +- .../base/tests/testAddSearchEngine.java.in | 2 +- .../base/tests/testPermissions.java.in | 2 +- 9 files changed, 5 insertions(+), 47 deletions(-) delete mode 100644 build/mobile/robocop/robotium-solo-3.6.jar create mode 100644 build/mobile/robocop/robotium-solo-4.2.jar diff --git a/build/mobile/robocop/Actions.java.in b/build/mobile/robocop/Actions.java.in index e9642075548..6ac6bf81bcc 100644 --- a/build/mobile/robocop/Actions.java.in +++ b/build/mobile/robocop/Actions.java.in @@ -82,13 +82,6 @@ public interface Actions { void drag(int startingX, int endingX, int startingY, int endingY); - /** - * This is the implementation of clickLongOnScreen from Robotium 4.0 since this sometimes fails for Robotium 3.6 - * TODO : Remove this when Robotium is updated - */ - - void clickLongOnScreen(float x, float y); - /** * Run a sql query on the specified database */ diff --git a/build/mobile/robocop/FennecNativeActions.java.in b/build/mobile/robocop/FennecNativeActions.java.in index 9813fd8746c..0de54ca2cd3 100644 --- a/build/mobile/robocop/FennecNativeActions.java.in +++ b/build/mobile/robocop/FennecNativeActions.java.in @@ -460,41 +460,6 @@ public class FennecNativeActions implements Actions { mSolo.drag(startingX, endingX, startingY, endingY, 10); } - /** - * This is the implementation of clickLongOnScreen from Robotium 4.0 since this sometimes fails for Robotium 3.6 - * TODO : Remove this when Robotium is updated - */ - - public void clickLongOnScreen(float x, float y) { - boolean successfull = false; - int retry = 0; - long downTime = SystemClock.uptimeMillis(); - long eventTime = SystemClock.uptimeMillis(); - MotionEvent event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_DOWN, x, y, 0); - - while(!successfull && retry < 10) { - try{ - mInstr.sendPointerSync(event); - successfull = true; - }catch(SecurityException e){ - FennecNativeDriver.log(LogLevel.ERROR, e); - retry++; - } - } - - mAsserter.ok(successfull, "Trying to click on long on screen at (" + x + "," + y + ")", "Was able to click long on screen"); - - eventTime = SystemClock.uptimeMillis(); - event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_MOVE, x + 1.0f, y + 1.0f, 0); - mInstr.sendPointerSync(event); - mSolo.sleep(((int)(ViewConfiguration.getLongPressTimeout() * 2.5f))); - - eventTime = SystemClock.uptimeMillis(); - event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_UP, x, y, 0); - mInstr.sendPointerSync(event); - mSolo.sleep(500); - } - public Cursor querySql(String dbPath, String sql) { try { return (Cursor)mQuerySql.invoke(mRobocopApi, dbPath, sql); diff --git a/build/mobile/robocop/Makefile.in b/build/mobile/robocop/Makefile.in index 866701526e2..b09186a962f 100644 --- a/build/mobile/robocop/Makefile.in +++ b/build/mobile/robocop/Makefile.in @@ -15,7 +15,7 @@ include $(DEPTH)/config/autoconf.mk ANDROID_APK_NAME := robocop-debug -ROBOTIUM_PATH = $(srcdir)/robotium-solo-3.6.jar +ROBOTIUM_PATH = $(srcdir)/robotium-solo-4.2.jar JAVAFILES = \ R.java \ diff --git a/build/mobile/robocop/README b/build/mobile/robocop/README index 3de479685a1..d01691d9ca9 100644 --- a/build/mobile/robocop/README +++ b/build/mobile/robocop/README @@ -4,7 +4,7 @@ Robotium is an open source tool licensed under the Apache 2.0 license and the or source can be found here: http://code.google.com/p/robotium/ -We are including robotium-solo-3.6.jar as a binary and are not modifying it in any way +We are including robotium-solo-4.2.jar as a binary and are not modifying it in any way from the original download found at: http://code.google.com/p/robotium/ diff --git a/build/mobile/robocop/robotium-solo-3.6.jar b/build/mobile/robocop/robotium-solo-3.6.jar deleted file mode 100644 index 4280906d17cb2e2980074f3456de1098771370dc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 59067 zcmb4q1CS@d(&yON*|BZgwr$(CXLe@Cwr$UjZQHhu|CqP$d!G(*_pT$lyCN#HD?6$x zvoiCS3euopFhKvf_LH0h|E=-w59q&dSy2^1T1h!EdWC-{g96(7OO~RkSMK?@`_JDS z<-e233d%`}i7Knm$%+AFCnsd2Y3b(RrD>_ACubUz7#5j#kDO?vrblU{X@#I54~x{2 z(5QP!Jle7%m5`;ClwGo^s!?!Ye}+x?g?I8-s&kTp~y3>Q5sC$&)O)B*YrQGxzV)W6dG=LPn+Wo&QzpFi`z zQ^5W^g_WVFyP@a*g%J6FCN#7&ak95G`M)sW{GS<|?2YVQEM5P*O#kaV5dJ?no$YPx z|8wAf&d>2yo;oBb5Rf|r5D?qH!Y*j+V(Dh-;;HIlY2!@7NM~$g=Omu)~BM4DzYBprpglzI5uk0wuKhWPWndm6!Z7>Mm)YF?u zAW&LWM%B(PxBK~Fs~vD~l3EMo#h@HZB9|$#7Zt9|VNDbyS8XbL=pYvffM}OlJ!Ml2 z#Y65oUAP6ebybX%hM>c4?N_KoGl{!4JDuj%8`C?arhkc;+Vb2<1T^1Fc}j(la^FVe z@a|Hy(JYNeB@E@|`qWCRS7gHZrdwrmn`8bA+U_)vI4-6h?w`-PEq&FAj~nhhx!tFE zF4h|{5P}>Bg0LQR{mrj&C`bTxR(*fzg7{nSAe3$_DyA@IWCO1HRTe~#&b}?ai}UDr zH*tt5$__$zjcE5IWi;UmrB|Q}Y@raX2LPf*t2G1x7IM}iU())s)o?fE_Xb9t17r}y zwH8Ky-EZ&KnYeiwxA+clZ>iTo6NABiP@cxPk+MKW*n@QskU}&(!})#`vU2C8smt9U_bypF%P|*DTdoqsVRsat@C}|n53ezWotrC=C-RqPoQOp4k{jsiC`HI;$rVIPopWDiJgW_de}e@%0Daps_JM(ZcO z?~tPxp7Mjz9~G$`-ub857U-!5x5hZPz-27PhBkSFwV71_;U7y#W!@dBkQfXv`>o@cWh(8v;w~n?pqSS^~qzoo=wKb_#v14SmFQ?cg7+8Pwxn1gr+U ziw>^FLz*HW;18GU>A$vmaP?C9flH!c#Pa{Wwf=o$X~6m@uXujrOE;UmVqqI&!}Zk%f@!mjrkMu_1TzYT+v2%7$l#BO zwi^V}aH{_t9&1;(Y!F|m(OvlM5?f_`Qhf!oW)vS%ZK@5c+hTW-!FQTrch&A1Yi7IB zh5z`q)1|JSQ0>9-bd%#f?LPgwU0XTxv0EGqx?1oC$`P{@zvo`b>7x@O55^F6;rEe4 zsWe|k!|x~N&Ve8(Ghtp-qCrp^C73MJe4%->+2&!kJ(#i;HMsN0jm@a= zV9yd0^PvpQ-1;TV9%OiuHwzU?#hLE_caskWRG2eGGP(0maH$}uY_uU}1DyvV7c+&b z7IbYH{Nv2sF8vH-@J5ITBFf154Q~%ge7NJeY|5od=^k!GNphr0`G)URI@lae-^9dw z@2FT1)8{9T3PSQZ(D3Gy9`|r9*6&J(a`I+!r{Puk3cMJY5pakP&-kheNQhVX%4LYp z(IRppV#6ULAspD3=pOX+Cu?}qr*qCQ6SgpGGCW9s1V|KkarhG#nKctf5odOGvi21W%&1;PFYrE5@~qdFDW{ygKIs+#z`AtAy22GMlhLpzxktixDgfW8Z8*Du)K!r7LnzK zW6Tx~vNF@_F1~UQ_DbC+$#4dZWaS1&9#38@jQOIvS9=4N_WNrzxd$Lny5-Xw)9VU8tOyne#s)2Yr-ybIp`p70+qwkVm*U>xB%6(QNIq| zSS`y80`^?hSjUjuuIxFoNqP4V8@DJbl^i+KL?3l!QZ}!A%rhGGY${n|+&#_jGY=*C zL45Mz0O{X*9TB%4UOWknqZmWbz1S^0ZEJk>41y@$H>0iT89#9&jtilM*-wt1OxaR? zC8UWIh;eo0mzIj}#m5wz^%rw#5B<&onW7bHxN)7;(Z~W&c!Qgoj8W)w15wl2P#Ww| zt%44eS7EZI36ela-`b!Jv*`5CSb3zvQ4X^5M6p{)96)P*w+;k_i1!644zgtRmW8nI z%VKRuiL>y~L0%jm{eX|{qXE|bW$p1(-ohgk?jTRQR+9vf0I6D8ZdxH{D4I@FS?<-e zS&GHdB*bb}A<1fORcvJzLtBa?TdhRP*QBLvtzwO5XbG{jm`x--GjCIG7|F0+Qts9y zr+h(~v7V>J^1+j{yr}CTWp=Z&xMfus0!GHNM7Ze&(;~=orL3EAj^@il%+5Y`8G1*Y zv0f!aBo|xKT&9=1UQupqRVZ(}vWUQ=TF?qE8PMkKCxSmZjLaB5p2Blun`p*kN>;L= zq!w^p0>r&Um)kC`+>tDDpinWzOHE0-JX~gvy|Q3i3P;R&(=LCtwAf{p8=^lDRq_-` z^ITpRvhyRbX10l9U76I%U08p>l+#ZjgpaZJxEM2_ttQ}cw7fwqiL%)m+K`VPuugG# zZIj@e(7$!mjQ$IQ-myjBlFkx7f-5EDw?c{gx$9_aT>W}oV!~jxsIj;v6CRmEOqEJ) z9~WblrU-BXff3`g@HxSPO@6+-IkL!?$H;#4sBN(#_F7J&v~0VpOO46!I0kVEUG>0n zF}ZHWOm0jJc74@h*AlMjMiwMqoU^K1bw}!Qy!x)18cI6g_4$}RkRvw zQT?h)O`s-_lT&=7nCBX8C0tRMKGM`Mlf^he$>o%J!$bP4W#Xk=@uYLU1D9vB36cnfat6eMq?-wW-nMxUysE4>;yJ$$6l?GrJWEk}%@-`Yx^ z;5fB8s?zUjc52!kcqN-^c34IfIZba>od&WFYtTx^b_?GS#0#1g^Xf-VzAC|Mt}$}e zM*gwT-sK8&VVOWn*qOW60}1 zxy?vjC}*}IY{5)qo!-Vr>NQ|#>Wy1AbW-{A4^a>hLOY{PsEf`X!meYK;*5Ka0{# z2toFHg-Av>q@2o1yPjHUUh(!w<}0jKMDnztLY$#XL0k9(SVO~A(TUtBHHDO+O)GO; zjb{)Q9c)JqC#RE})Vk_AU(0!oKPdd7HkS%P`D0oV8d^A<*1XZTx>}ITxFj{$U~bo zJsAsP|0;`wPjyfJ6mQWvd#NMu`yo&2K%rtE={XqD~I-*U!N^cj? zQqV&0U@XaTA!3j-8D@RpFGf!7utjoRb(f-BsY9c|ceKsIzc4B&Rgj0quoc9xty!(^ zm_5kv)FjL=cfW&;YrbC1*6Vv^*cD|pAi3kQEehsR>^6Tt=fTPwB5sS@dt*ULlG^vURUB=_e7Y;dt;5tecz7bfFWpUI?99ZVDFuPtNcvWGZOq-6$=4qLd z&&eeY$}MH@oDBN{A^wb%$<#NBX&1GBg}EM4XAD-yK+!iwcxk5=Az$XGN>p5F{E%=A z_Si%!aGxTjMotL2652|(G_4b%Xz$2o0tM$@GyJq&-&56k<1QO;$E@2Sj@_YGGOMke z)cXMOo4X&;@2B7Jp{OrNJ7Cha8ObxxH4kkW+sGc6Ml=w1M^M?P7M`S-;9oe-}d<&IzfoUL8T{?Ahza=?B~* zCkzCl&#_w>e%pMV3flc}Z_VG~+w(*UB^eRLz$b>|;_gIbXaIIDD;oBVxJoNPN`llK zkDSu6SLVA^@)J>kkD-J&uD}b?igCaF#9InDQ7J5L9Jpo7`sI-lcu*`EsBf6%WjTq9 z5H;?k>V?^3WyA)a1fe#031w`+2PDZulElnUgD4U-!~Bq0xRr{+FZrj}TI? z9tIlW-}n#kUuTv6UvgBPolTuwOr8GeqZX^bsw1nTe1!zdFd=Ab5dC6Rsw5ONX0H%X z%v0(Es&*`IMHmYRN=#=+|6#1%v9^5uZuGo9)ZFuk6P@KH7t8SZ_&oRBI|Mg_T||d5eXqLFD9=B{mMHogFud6G@zplo>`(&KyYX>VpxA zT(J%gh-Z@N!n!hZhj%tsQfvs4%2Zb`#$G~7u@WKu%hM$rJe3MRh)@;AO-u$-=4mtm z`BjFa8EvD<1I-FHY8j~o6-84b2POFy%w3i47?OOX=1lWZLsrSa_47q2T^n8}fDn~^ zLtJ&@T=@xTWjQTv94s|WM+;3l{#-pcL62fbeUfGj5Xx-2dricRz?f4EMe`1`9(#NWl!`}vwJ=Nl{1cM&Txe`}|{jid;5Z5XhN%&-5 zPnr3$m?&E5m_e1W3r%7|L~5EI*2v_JAV<`CTt=j9sK~Iq$PrN_`dv{x`fv}-+OXDO zbleQyj>Kh>Rq7B=uYH(5IT+KQ_-`l-!z<@bhzmc={19F#3@%5Igg@(>Uf`&52)*OGK;e{g~Zl@!-#&!8h-koXz>_?4+)<&I=IiTAM}L_dD%mm{lf z@^dWGm*=Ks6njf2>llU>b`N{q)Y;LvW*;+|u1U5Sk94_eQcYuey2@+gpX*%kd8Bu3 zIbe-hxlWX8*NZku&^eMOs~tI34zSV!sGoXL)@XdG3l<NNL+k=rDfpA`Z&a<+LOSAntK_hpW;4}ezYb0(`0#}Ih8s}ReO4g zcr&C}J*d5AJV8t`BXzNghfy}(KvBzdZo*GNgEQX_t)<^HwTMGz!lATivEgmhT!s@h zHQJN3eptNDW>v#Bxp_un2tJX}yShUz^FbG*7!3uhOS#OaBBudyw{CiwUq&)sGi}_j z_eYVwFX7vk1~|WUHw&QQOIjY0LUmQpI7w|}v|n_l{Z`gtZxmkTcZXf?W5-eZf|K(? zYv3^3%WRC6O%Z+}0nh|I;+|n|1|!CF24fyohBBnPLCI*wT1#l{z>;dfyG2oCi7L1X z`YvUFet^t<)B=nA{h3||V;es)t32`(F z>gxkssf%NkQV{aMjnTsEuCz#yC=#GJ=GSb1f(|DHLN5s%fVI5Owz4WWZ1*DImQ)2~ z<(n!u7B1^07ts_>3Nlyp_ z$0nyluYVHX?DL}=n?|zWUMcyXw}#2)v0O~v*%J>(U0qNddi*14b5js$3@*mK6Nz}S zmg?kMEu{@3qxZ}15>gm>L~$x85GJ1q$WAF|<*+}4SP^#o|7UBH2(m2b4-N!m1P25} z_pewRVGC1Z>;Et|*=n-t*s2(QbgvlD!jjOzLa?IMq|meVsMSBQq=^?BCD*aQv@6{b zqD(B(@|ltO&c$_G0qAwEhU{A&G121aIdnR0PcM+0uf$b1UChC=!9udr>1_Z%zM1## z=jo5To7x^=j!1hU451q2pi#g?(~p{ikYGe1sJtHmFVVl-TnK{^>oNL&@}2j~ZtkbX zwyoLX?IT0yhWt22G(;is8HT?JrYOP^0uzNU{sG~jEu{Htc($p=8XJ(ITw#GWkZv=k zqpG%84eu(g82!ie+;oU3vZQcD4Rxa`V|>5HH-WG<{~X~t3jeZ=M5b*a%I;JyVo&XI z=pL6#+$X*-mu*6%j=U0EtGiiiu?oCNgH+OfnWlV6bZP#zf&76Rb<0cwCyPjTPRboT z7H_Lt#TjS8LDV$lOT$f6S3SAHiiY~E!fIno<^xT*rMayn8K;`Y1WsIg5(A`NahVNM zBZROWeSdi!Ve+&gh8Y%i48_wO?ZH&o)d~$$H%&8b`Z{1|c48u_Y}nyGzy%KXjWUFfU1n;oQYz%Fh>NVYaA%GUcRMwO zq^Rcp}*<~P4k=#+RG9tY&ejYmH%IZ%+&Un6)N1w>01jAZAEZoQw?8t4xL7y3h&vHfi&-`DS4N~i!)8hJ1Y}=SILc@|ibO#)AqZq?s!KRp~ zKc@Ch+_Z*auE)!aR6%&tG!h-;L%_9v5f=_8U#!N}htpy{-+>Q|0xsl!Th1sAr@lxH z(;S=lL_@-XzTcXJ;XX|oLftg)YB~O1m)0g2mhY$+#*21&x+V7BZZwO&H=Pn@XfAEL zPKjm58qi0ISV@>3zKxvp>F)Bl_Cai115c;kwA&Yr@#4}c7dy)^wG8Q%2sNvE)QGro zrV&{WvpjdXncQ2zvG+%NY?iVtp{~eAfA|P#eY|RAcm0(`+JBj1Xb~&eUZ4ejr6Cu&%ROhr6cW!kGhBNYK`P=WKY3k#{8I4y6H{aP zo%fAC3bzqf0>II+I=dIKp{XPzgFWQa-X$Wq559Bz$ zUsVT%MX88iJfpz{UcnKiGmuhoS|>=WMvyj?{SFN{cAw{SrvwLCk8%^^hG2KixxHqI z#Zq@)GGR)=ucfjlk+x;pY5!nqkQfU25r^?&T;6MNgp7CFP%oM*CdRwda_i#mtMa#d zjK_&1+zQl&>*O9pO&)=VyyA63FvD;6@GFMBqfSrh2Ka5wzLag~qCFdT?QeFFX%?c21AeO&BfphhhsT_!%R(a78ym-@RW0^|{+Ivy(% zuRI>$$T31eC(l_ThUNi4#HV^Pgq3@Ivfvq>>(#m}e9k{p`_Y*+z@(}^{@5vl2k)l^ zvrn*idcyo7lkb)?J@M&+P&@nLi>@x8@Twd@`<*I9&PhqIb3bvtq?FI(OyX6RUQi zRrBQ0&u$O!*%`?G=80@icLZhcXs544)}l`UXO}E)O=*8{<+t63K3=AFknPw0WBiz{ zvrQMT!=+nd8<$I;#z&6`zr%IA5K!#b9Yr7N*(xli{_-jnGoB+CPfFJ5c4jl4y~VUp z=txge>dxBivVB1w`Fw`6(k6cr>_aN5|JlE$iZzh1zI>HgV`0BNh_c$w&h^7KN*tLt z+BQ8Y`BZa=rI0jT!n`1SQgqH^dC;9Dr5>Vca<(Q4Rh~J!o;BstdJ`KLD++;C3|Y6l zXlW@;%8iU!t+|#lJBl1T6IMRJw1E-G0jY>*R#oPKY*ADQ59?xbXm9w$Wpm#{Z| zj3;EFnwT6d?_D`Ulj^lqY@^+3cV%`sFgD=?AT|#C~Pz&4?@I*)*iYy(h3mqYP*=`K#e*C+5t3aPVon;XjlZrUOfi4Lf%r z-B|wEckE!X7g7jh>(zWX2ebkaoIqQvJ9w;S8JR129PY-}N~1P$tb$?dE@;YaMi$mg zbIij@=rW>7d`uDhm+N;$DASAWK1`}8nr0cwmy33yE9fJ>Qj`Y%?8;+HKgvzy!KnW< z4V;fZFuj^~t~Gjj5z4v(=l*&;7Fmf&N|&R)CIgprh1Dhkei9;AE0_p=GvhqBXGLC< z7``;FpmNeeKrd|9Mtg`lu$1Ye%>FU25t&W}n}xPgT##NAfp}(9>ahF6S~em`ovSLG zn+*A)kTR3sy*gnCQ8RH(WipDuZ8E#n)%nkiPVSUR0z*!v+Ea(oPx1*^6N_;1g`ZH5 zUlvr%i}psGb)}}>C{w8A8pG{vW;(^@jYr2u4W zdJJiNWJI)b83z$3)O{Ku@VLWNwjD??$V`;3GIo7hSrLQOQ%a4c9J-2g+hGyToEL`+kNM#3zE!b_)6+7{n)p&w8rWj=*Ril{+=(LT^PH#3#pY zoyEp6p!xTJgm+lUipTWw=@UJS&+roT0QbNp`!rOs&x{gDCKPT$wrCj=_xOHbHhig7 zb{7iw#SqP4n`Ne61`iBRDqKKrQY@@Slyt@_T!txRCM+NHwrY;xN>*520};({bSwU< z6;zuz0(qtxbe(6Ya$F$7nKL?kKuDpf`?~>3W0dGsI$7>_{RMn?pgqeASw4V~=d|G= z?gzKQZ0zX>gujl6{_H-(COxI<-A`#U61?9E&Zg*CKFqw8cYZPvo@b~5# zYC(XrahPCN1qUZtbPC3;5~Q-Nax$bM!1=}TN3!tuiNkUzJCUlGpue*CjqZk?aYCs& zl(1)5F(Wl2GcN23e?Td(4WgLeo?t)_M&q--06xG)5(=PUUh5?gL~@fB4B4d;|1P4b%xL~W~$AS#_$|j+}{a+bo=rKP) zzw(Fau|Fa-zEycn;oqA2YR6bj^989FD)USi7+=IcjDx-;>`zd*`1T15WpK}memI42 z?f@70_pj`$Ov8w>wD42D;v@Geb-!aNVx)LXKsA)fe_92VcRb9*oXiSXBhsqH zCS2l^Pxn=yS=Jd`p-5I`Me@kjRyZ6(D{;NNT=JN^e$ckL!@s8c4H+}dTWjwsk z#7f`Tnaj3>Ae_Gf;)?Rs_8>{J4KilK_R&Ncp%%hsD`#@pYh!=RubA8g2{kQAP0$r; z9+k9#K!-0}&CXl~iTZNoI_r< zv>mAhr3HR3K;c0DE| z5F!eD9#u&3?T$_d%@2dP8v!3WtzFueNR*q`o1wIT(qiBP^2xriw<|`nymH$4S5#Id zO*z%^MeRghi|LNwUXv}9IW(O1KWR0#rI!LzImBtOlhELE-c6&%|mogp3iI?t8^TkGG7rcjDAbSolq3kp#`P^@Y8)W_?ol+E;= zdZS1nsv3Vk9B}yh+A5;wj^BYo;nn+2h1bZMl`P2tWUM1FO)8Z9`e%}jN-z&feux`8 zGE?#AdKG&)@>4RkSbSsTj5oxsA}I> zejc5p+BH{S!JeV^D3+L6>P*~iPxbPJk#lNz*QM{fBhT+q;AjVtNs$-L@UNsBc78F#|jV8u_9@Atc!zf(WAf}s zy6?fYPE7QqUzY?)eNDL_ijn4d^KD5#3;N-oZpOw#y3>?Go-)U|64K^FGR`|f_;%2; z!jcm`0>`h?BHq|M+tgZTRS^}?YBouv>>P1ELQUNb+F$Bic9LhMe*;aSEKRCsC~9#D z^X92w~NSw#i{HNN+f0 zP)&xR>pKFntv0pqc&{LUA+(&*Puc7CJntmAa_nMoYF>{JHLoB$^?_*B9BgwEu9>-C zcI zevwTFC7}n5u-%gX)Ug7jq~>kK3y8(epCtQS#Xy+%mG=nf58|@A(D_0;H=?{-a zV#}$ouQ zrO3|Nap;N+jqNGsTRBiBI0h}NAoHL!!r~2lEv*AFdLS`cRP4RP^tfQ}Jyopxq$yZz zNjjzO{jz}+qvHY>!c{Z+HPp$ab;^jkW%|IOCe84L<-3J+rj?cQ8Hsy(a74YqDJ4yy zV4bH11`@m}rLm`3$W$>3@PX+L?~Xk|WcY?r^9yTAwWRBU$z#QMs0LS>Mv9&#V^1hi{f%8 zT?)Di@h+=&5H?OkTg)k9#yGZ3m`jI?rn8*~@1W)d(c0BOx5y<`R?P_=i(8|*A?)vO z-aD9~<%XEiVw0K}IV(vx7GBS?b2Acous%J;Cz#`(mwAJ~pXN7wlD+hX<@T43Jat!* z?kQC>=|TBKdOg(NoBoEN?t-`N0!9C37WhW*eXRxB>yXOba)=R);bYCJC{`p83&myu zWt69i#F@T$aoBzf4Wx90z~4NkkZbLo6OLg{8W_4(n^u4>?GWb#U04vvj!vMJ<4{b8 z^xsz0QUtBvSz%puhQ3k&R?eL30AJBgmaf)SY-pDN*BDn@f{ZLrh z2a!VjE!Ni&$Hqhvb;Cl21Me`Z?FxEW-? zj>g^3Frr$5rb}+-01VrHm%f2|DmA>9X#%0~J@WLFnAf2LUq2wc)*KZwucUKL8mYd4HXc&whK)Oz=h-H$SH^j}fz$OvvDx7l zBZQLf|`X>|uqfUz%5 z32IA)H-+?%0cVce0<{3LH)i`|tL^@YHr2f&FO)8%U<+tOzM_~0RgYODCA11o{w_gT ztLf0FH_12XO=a|nV;!`@m8;#r_(Vy@xAJTwhBwUPO{<4G7(CR@I6s7Oy-{V+o;-aJ z>R$|?ESKr}<@?X@!9zb$fxd$6DQkDi`Grz#ktLR3i)=)ov(CX}!azaD*x5Y?r?7{5 z08e+vSB1357kxOXvGb^fE=PheV5~U6bOn%O5DTz^GmI?IOf5cXHJG6BNHvxC#nXo8 z=}!?nVCR4zvn2sQ8nI(!izio)%0z;yDVu_L-Dy;>KSg4;!f?FHQs|4}eJ~XqIIs4o zDTdV(h8RU6>99-^YmV#)@>B6lBlY%uAK0Fc76u?RUXWG=3&lqI^;YTG-M#$~ykxPTF$QPy9-h z4-Xy8Yd_g`+`fPd`H801pKE~m6H0vcuu@URw?YB0la&Gfx`K3oqgp^YPB!uDO~l~_ zLJ_@l#1ZHU;0~)%sAfsL9Ma>|_MT#mYV?=OOakeTL@%#eAR(pM?qscKFZ_byHin;& zW>zFBkCLC@OOrWfFhVx$mI&?ZBnL#*Ss|QI)3sgQ_~r zj=1bHn}f8VE%2*wTN}Sx&^-6;Z^QCco=gX}9^ACHV=jI_N<_3{k7dY+H0%vC#o0aj ze;Gp%BXH~}DV(@i95JLCydfh+n4}m^@!=n=Ny4Z?*y=5F3fpT2`xLL0-B~PEf*+ny zOYgu|=#eD(9xf)pBjrj4f$xDkeVP*eN~2?*y%+gIQ7C*wLoF(NG>jgt;=?%9~_0o zrLS=oej>ow@TVxKGMbbF{ARrc+%+T0j59uw($H2f?8+8;lkBx}E~a+5r&sp*nC7|u z$rv@#vZ;08JChP)MNSK>^%0xalpYKbD!{fhYHM6B>lWhdw8ywELtCouga~T!CSOm2 z^}WiuH%?YuGGO*t-@0KbgKM9ICu2 zd@P-jCT)mSJ)zEy{;1B36Sjs|3mJG zsr+y$ZPG?j5uazD(Ov2hV4fz~kt3Gk6cRu3!)0m4@!Ppo1QkQoTjY+gT{q^I_;6vA zJL6Bx=YPuy{9^?_{c_;#`kUU({+r&V{a047xT(v3LWz>qEZu*qWB7%T3X>Iv2M-pI z4XI%hkhHoa7S)4AiZV6>BNs{x#b^sGBmtv_Yu_*u=I;h*+c zzHeiKKou$SZMHoh>E^n(J=gmCy~6hz`q1zCWt|OC9Ira1(9S@4paJC4dg_7Qq@X1Z zvI4+qU^rr7eMfgWn|Wpqz=65%h!&g`d!^$%XrLVqqF^D5lFON8TnB}`LL)KW2ZP^CxIV!U$VYhc6g{4{JwK#;M;Eh0ldVeU_z1gR&Wn`~TlwoFEMmU`99AUop9?~}bo8qlC!a>1_U zsARWQ%Q?*Vr8r5!a4S4-ZKy0Iy?y1hHCLS>g>6*lmG6%ds?1D{oG~+!)7(U($Czj3 z3M*p|NkbOmdKOrmt3$ao)yk*H+f@Wglf4$|G7D&nAGq>3l%x!K>1QOt-GHl-PuJn; zFI*}t-ijR>HIiIml;b94wdfgZ=-imAkeca#pJvx0xi{PvM8_XJwrqmhDo-p#%N=;6 z*RZRJH!O+NtWiV>5nCteDFtNbNU?NVoR}d`e$4+UtOdo9ZDG{3-oU(VgC8oM3Yv zvDpac3Y08hn84)PIHLyh|7E=60Y8mhvNNd{OX)wlc+=2|^#&e%hCjWDJB&2%mh@zl z{d0Jr(R=XWLvdl-IEB{^k4Hyj$KXlG4bkh8n6(w{%!2%)3u$E36-sZ!777Ux-O&q| z^+D9Dlb2uk(83GPqyrbnZ)6(k=E(ZA){sDDpyndac<^xcg7vM!rD5$==8VjK0KRjif&;k;q|$qSg?OI)jor zqWy!WIR%`8njSbK6n`Xz$bV4^#SqyTG|lx|fi4v7m|dHV{>r}8A){6t-^Tc3a)NR6 zV!@l6vW;=pk3N!Ed^cQ>(7hrl(j4RyCzJu+5y`#d?{U`2so}jt%F- z6|-qkSb}q7xFWcc+r|q_aw=de^!x4d@VaFjhp}d$FZ;&)*+tCJ&8ms>1a5+7*_py^H0I1 zqL#wBr#+vHC2G2;-p=#(XO{PMm;L?1&a*$z?N7Q8#Zb_tvLV4Xm$9Qb9X$kRPtqv6 zhhRqx@uEfR-BYektYJnR_Bf~mFu4#%m{RyG#@W(7iK+E+%stC6_@d3Wm&PUzd)i@I z@~bvCuIo1B8vB#ueNFe}X!84ZUM!c5u{W${cofuX8M5sWW_osVoSl2ymHdqOY*ZrU z{AUxrR5MjT%9V6wOjGqVwW_7ds+&!Z`atU3II}0&*Epd%T!V4eCh2D5Y@K7T+n|D- zosh>#Rk&u(B4R70wcF;sO&dMV`BzeQbyyFQyh%euL`D<}wotbHgz>7172Fw!>%F%2F$CfRg>>rJ0#Ch47a&k3>5sJ*nIplXXMf zBwqOVpxQ%b*$5djyamf#@Dy3j02*?&1-rxYAkZ5;Tn2_vX1L*lbr=sZK71x}%EErD zUu6I0zI-^^GVh9&!Qh}Z#?q_`iRZSQJPg0y=!C%hAZHXN2D>93I*SN3EgYs-gr$d( zRuP9_Us+ZEI$y$&AWV6@k>AXz4!o=8UeQd%5b|{=bBZJ#7v-N?8c0skNjt6)!*G2- z6({437xSI*Pr|!kTGA|lQRttp6t3WlHv3 zH&aizX2|6kh3vlT`Cze;JZUFM#Eg2h*Jwz#$vASq;_CNJy)h2056Q(#-1#NB8%nX) zn#%b^w~~Hy%KYrA2U5+{W>+MT(1%^LFDz}dHF)6aH7b~KHubEr_5*70^*vjFtrDcF zj`rD}sLJ1hoxJRLx7iCho|#NgPkE0(i#(EW5#@xzp9%>g$SMhg#B+@W)d9y8_C+a3 zkt)>%=a#2+TzmpRkg8=Rom!Mhf)X2NB3#xp+^~!DZD0?BFMK>j?q|_nOX_78HjA0q zkL7#V?ad!E`1Rhi>X_GfznTgwHBxufD?dv<_~>bjeOvT;_+D@)B}%(b5Y~g{jSmr; zlQvisRXzRcqQJ{NutSNm3D0j-pW!=C&a_Izi>7Q{l5KLZLYEoTHV$AM%d~r>bJkxj zJTl<;28ln4(~_dLNtAmXostCLS+QQDZ^;|s&Ff%&S3~_Cc4_QGEO>hp1-k_XFh-!Z zceS113mquwZ`WGG88`PE?l|do+35DI$9Hy_t`A`R1}|RH(R%i%{6c?2CgIP&A(7o- zC|6{xgpC_SUK+r=id7g1i&E;E-~!BZQ;PJZ=Z&@8D0r7!7op{0vI&YYih*vvO~g9Z zw6M4$xAJxO+HC#@W#`ykd9-Eyik*sW+qP}nwsYc&PHfw%*sNF;+qO|L>&flz+x^^r zb$g8S{{UxdOT$B?Q4hP`s7E;8m&el|aSA?$wZh*1gu!X8l$Upd9G zJNP3M*6s}+!F)`9v%q{I#a*GCx7g-xJixZd_1jvw)aN;ioWQ`rC5_7aRPTsyg@&k2 zzAIkYd6QQDBnh{c$(18ZZEGErW23=!oxyc|;r0AF!t2|QErH^mI3fUNaNOw~s?L^5 zw&5=HH5C(<8N!`Pc!&5YQ3tFXV=D76H52a$=Q}w@;+phWmat#%h6*gd6eq7f13>=u z^7x#Tbh7nTa`nF06#o{>LFK=Y692+-NYT*sR8>d%M3i@(bD|C=gWI7Uet>WxEv5HeUE z&m|@{SS^iRG+J6r=VmxQUVN+v95a4fiC{dR34*5l$cAr2?#;)Ax`C!tRxlv}>T#U_ z;RZ+~Hnbvyk;68$hS>G7-1nJcogRxA_=ZPFNeDdmsd9HvS3}!y5wMQP`lMCBU5j8U zc#0F8Mf=j>_8H0@tY+E=cgSe>(&0*RC+oykNL)xLz}qOyn!QAfzw)ONX8hJTGAyIV zea0l6GO!(0%phB%>3qac>e`A>rY#jG)``5A(I)JkuqV-E@bp|1ii%_NeGTOE;kYe{ z^FgTvIDJ;u9y1zhQMH@ZCy^gNeuxGhGSuvyKWsH4!a3bzN&oS47n@xbQix*xiU3uH zT1AIcA&!^!ACs2`OOk#AEf&zXw1}h8#UP!+A9t(sq8!pRJ#s4qxe60nTGrn;0nqd{ zw3wU}Qw~BrACbyrxo{MbRT;IK*t(>yOJg7O5AWFwL0_q>ailjka%X{>Hw>#+naT8) z7Di5%UKq*EHqe}>*taY*v9BI!m0IlzfsA()n>2*jr_Y0)(ZVO?W}PEoGkXQGZ8DQu zQea^!&(Q>3?3`1z8uJ(6V3>F1tzrkmx~TM{m6E#=Q57JplV1pRhA4!H@lo$mhmi5b zSd#HY9aGhnz1NKV} zgaP|!18YWSS7wZwYz^BMYfnCF3O#zNXsIn$@l`X=I8{PF4(v44QCK{O^X929{j+SP zo`c>t+BbqpdK;0BjC`ZV5@GEF(I-#6Z{0lTrrFek>Ejw9z#+gvIXAhM^va|FWYkLY z=~wKB(sSntsMs#H^4Xe(#> zeK79Izu6bPuOgLqj7s;i@Kfji%EVl*m$8h+;7A2ysWQ^aQ<4*1PFL9CP=4N}&dTVh z8ZKWQwO;C+@#Hh-#NbgJni|q++ns7&<6>_RiQ}g;vdy2{Lg{6g+v~EI6`Io%_<87| z)|0-w5w(oR0~;l}dA? zA+1hW!dY@u1s~JZbEnHDOR^@c5dA&FC8$raHv8LVYIXT708j>HRcv91Rq-+3Xa(`X zd+IEfM&-vZm6}W&vC#NTAGMrs6w16I$$O3fq4GM>b{0C(xRSN?YwewfV1D- zw^?9>jsuwOYK8N_ZCPIt@P@syCw(<)dM90VzjgMIH;{^)xh3(px@-p_Vz4WR)z5@r zU4}WQG`^?5_BnXVaR_awKJbJS$rvqnsH=- z^aDeHO*k|o7D;tYO-(>Fm_Q*i7%7fjDlN(^V(f+tX-i92CEH4k^T7Ki`=+KyNxnJ^ zdN{NpZ{=zo-D;iYEx~8Q@aeaytA^hWCUtqfEY}bGdDpkyZ({)lUEn(u@3cQ8HuguL z#%F%`3>}N^x#m4@5cY=MBBK*N><4}m0LDSx5D5@-2v+Q=(g@)9n&4sPO@~iMxbTI9 z4ILw+$3fP?$3gNRGigBy}C=9it3k5D2YXj#omQi6y3wkYeU^M#> zayr;|R*rz|JqQ*@?xplvAxZgb zOm%`qM6={g-N!HI_oYRJt)r|nt}Gx%MD9A=s)2MH=dS{VYZl*U(#dm5&D|&^UlAyO zK8+yk2IJ4~`*oN`x_i$bBWA#XSvq>BfRynWYk_q}ODpCuE)XZv0>dp4H6-XxXA&+^ znN8VHr;SZnC^C`}gE*`l7flCXBSl4i*dXe(n8H()k0GPtyIeRMGp(j^4~O$xxM`VM z^dD&CSx3(Y564U96?-LUjLcHsjNyV*n@3)Iy(DYfl)m6p2^yY!%TJ1-6@@dDLm&Q&las&4k? zkRNVy5*~+ZSKJ$XADu|;cACB0(@Y39T)1M!I-4xu-6n`E$(1WDyW*PYGwSBc9YTn* z^p9v;=%kpQ<&M|MqI6^!^SRTfmV5P>%@z${;xHQo>Q)Eh1J_GB^(GbO+;FG<#ASg6 z192m8P-~JCi(-iEe_Gc5rbi#aVxu7OaZ3Z}@+VzPqPENb6w9S8&rlU`6|m0mq>PzR z5MkTQkXfCU;71Ud!yAKG40oHQ7CZF1o}hu1am<)!1KIifOIY~=4u^%=`C2!N>Iy#~ z1HU@aqf{=0cDFdb{(DYxWdfAnV=e;w0%Ol4)490{)fdM>lGl~bwQyI%ZUL#!8v)lT zYB+3mk|uZA2~rnrVaj!vs;x%8^^9)4dLNw=hf}Xep$p#5wj}b}>Y2en$yq}b_7Z0b z#ySP!Dre$q;$YE<05haQm#r&2il)14_pPmX7YY!8!1NszK@hD>us@Fd9b8b|S$kmo zIRlutkB;6mb0hm6x!6@lhQ3hy^SK$geA5Bk-f6|b>nhmu#PN@lrTNU?mG7$Ai^KUO zWBb&m+nT$n}nWzZNUW_`-3IE7Ip^hn&<^LkBUk}v>(F5rcF;>_)eABI>|}pp5Mtz5e3Ush zF}G3#qA`Ux&L0pykk_D~gu+JC9?VrgOpJCUVzBvD&8Iy!?Wdas~Q%+d1#*;tIA zjE%W83Ue}3qyrB7mv5|GDQ_W$`7I|pw8jTtwTnK;YwQbF>h$b{6?mF5%xh$Z67#7y zyoU!Z1wpp|^5gvkqQYZXFK|Y0;{~X1f9!SQX3hYzjXZA>jX8NTW?uia~n1gJwdR*4?5B(xG}$t{a}<&s<|b{-jV7JtS|cB(s}iyT0(+=b)J6_;*1rIVSK>Xr|JEP1b?@S_LS3MSVY zH(VxO$S0uZgYijpg5m&kp`cSakXun9v+VCMx$1_}o#RO7qdwBY_6O-+LtC&0?+7yg zD%V`3s~=RyJ(gnZGS9z4&)3_0XxVr$i$(i?@I=m9nbEe$n5Sr~(#!(wlS_7@8`ntxgZwd~-y8$)vDrv59_QTsf5dwbyejQd}>2wVA8hX#?XeS#7p{ zFhA+_@uEo1EsFpxIf~NqCCctkbS*zQXltsx1r35NtxHUjfnYS&_MA6YV=GZ&4{d;q zU3@F8?OMFyYmaiZTa{0HGD6>yYNLrA^u3&JJ_00NRA65i(KUfu& zeJU-uJMl5216OC0MJHFUod_22Zv6f>ztttIV?3a+D<6C;k2zAZDR1qVnaQ%n_GaUo zmSM@>jh0&Gw26knIVK)+ylN|Bxv#$6r8i&ElZTCI8V?nIPZZ2a_R$&Yt-0@gniuEc z82X|c?&_Ep3E9@v3G31&)gDjy;BuRqW2 zci4_c)?dZmTjD3}%{TnOmB}PbMuA;vdjCMMCKyQCrbyx%?$Kh(UC%p8qOEB58es?{ zYo0S$m&`pU)YQTprpYSE3jJt-j29$~II0cVC&~>Sx$%b$uK+U6pGh`=>+2VFh-A;= z%ocOV5ldpLK()Dhr!~uuP`!#-Q_dB4-kBACia^~(8tMs)rCOdP;$=DjQAO7;kh=-M zb`Lrl_Ob#GxY4Js%Iw!+&@9u|m>%j6(kp1%mjT9k!o0HZ9JP{)yIUi!8Kg+*$cK{iV{s{i3zWo?j-Clb`<= zv{A`RLb#b(_Gk5tXuQ5eM-f>F*%l8)1R_L5#|k!f ze(7FM4TdH@2vmxGEO33;pahq@Gf@x)qAyN_gvfaZ>ZSv%$Y`WsgiAWfxpRFIujX;^NAjkTo{dxWW)ND1W8exE(HLD2&cY1&SW5L$w9o$%CV>t;Oa!u-xI*nbk|{!#NET?AKMZrP0GY9SA1XIxMy1tLE1P5c0oAfBT>BCJhyqmWzj_5RAgWf{uf(8MHp@X*KTBYz;4}ML zZ5VC$V6|lVL0+#Ql8Ls9@(C&oC&+n|%q3TN*wMKel8sGbN>4jmegkvFB~3D=pHovg z+Ih`BV?5;uH8UCIzzbDbR!G$9*1QU79&Z>(NQWhPoEls!9fMai^RR#tz`>IT$Fpsl ztPesNq2ZFm&JxhUd*dRqcI*Y>9LB;nGY#CZ;r!+*S~n~akdJ=xdpl}YhGCr)rSzEQ zamKcZ`RieNehoq9MblWbFsP`FGHpA9v2arGx)5iMMuScXC6tTyo8MZD(I?`Qg+{Ge zVHSCk{|~OPEh5InbUoU|gfet@|68`E=5LJMHN9c{$o8mu;e7(V>uXcjz=z16n>gPY zpbtSq8Qa`Lm0c(s-K!eT2)TR%ReLoIUcRj#@L%i@UmbOx)RX@8|Nnf&e@Lei_biV0 zE0ogm6-wd$Kb0FXYZvn`UaX_Te@ZAv)z%hO8Ht~>^Y>A`^<8;$#e;H8W^rcoQh2-) zjh_?|n}}WU^QlGSFhZ98%7w;jtsSfeT1noA^4^AhatKDkMkw~t)Inm6< z4-NAu0BJ-N4b2Qac~7aHVz7uR(b+`+1No3@PQ(^Amnj6%fOXJAZh3}(z8-s_!yfml zWhhM4bX3XuWJ>7#Za?l_Yu{tpeWK=w2Y-b1Bap+5PSW&^Sp(i{{S*iO4q=|-@k4mTY5OKtoKxo8mhZF@BirkH zxGhGjkIuNOe5WS;lorFhlbb_xyKN-RzDmO+6!1o$MwEX^ZvCDE8>7}pnX!d>{mp0& z-h{r<(skMsMw$j%vZ+*e|3DM9y|YEId{QhR>3L8$_WEo%mpYvCFL(+>S7fwSO_dDp zlUg6-z%abJ8r^P2WL6tHhIFx7ae_&DmO~J6m2Rv&9|r7D1Y}l@fH3m%UO-xzeJ-A3 z-Tq?b=PO(A*%A*wX3AE2QwpjW$eeY7>bMEcK?3psXieZJk+!FF6e?k$pTr5?9AyJm zO;R*?H{K9qLRWY#5!wbtL%ggZl0X<8iij%AIN4$p(?+k%PT6dN9(-<(7-4?$lExGg z_lsml(0UN>6*zNcILh`Sa}xiVSoR;z(J*Xr9?^TW`rh#Izy#<3N?Dv)8iFxWGMzFb z%CwH8;ghHM@ArNaQC{(y63DK)?c4ua%kwX@h$53J-ZJh+l`lcC6K4r!Bb`i&t ztIHf{$Gm6nqA=w*HSVe~{c(FY?)i;8nKb^EC^Br6T8frRtiVJzT+(>32wVVzV2CO4 zONuSn2O7VerDR$=D1z7A@aESWU!1HEv0HS3yfd%w2VjD;ZSxO$m6cu&Blz0;Uplnc zoJW{$wx1u51V;z%oF9G4%9NX}PwP0I@ra&Y?rDpRY!JXf^0vPRgpB*toLID*b01aS z=9_wlb(zk`>>cw1Ms7%!&+bfXRyR(qUq>6W4aj={C2HgBZJS5A}%#)zk-BVw@XiEeWG~cPBf->i|QpainG7qdt2CzZ{d0VVj2I(W}oH!r&>J%8~O|M1{P7v+USLmF42bM(Iuzcm@J?wVggr+n;x zlbrNV9sbigg9D%~qJL8Ib|%SDkRfr%5_Q3kHb_H55627HfP)5t$BQAA?@?eU_D$OH zbixhVRH9p7eiczTo0t}Ml?rrPknJ@c`^$NaYDZoB>bRvA4cX@JuiLzD&`2UyoQ6la z?N1x7)BA$Q8(!~%Pki5uV)quEak`U(xt|*Vdb9+F$Z@r2E1{b_H3JVk4!z548|4FW z0=I3_1Cu=PzWP|9p+V2VIeeT)m~P&o{Z5`p z=d}DsI2$28#1pRY&PM0BSRdy+;G28$9ti&TJ!1Ut`#$Z@0tB;hUP-6}-Yz*(#H(nczj*rADZpdr<$wjH;H&qm}L ztWft*TEn+pV&H5({bn;2Ksa`x_p_Oop%CpFRHq_bnM zeY{j8o|WbfwoLn%`lUriOA!!NlQ*uN7*XjKaVt1Hw@VmlY3sglbnB7J)NSlsRS}f7 z)4wYOU1BV2%;hk|#gp%{=+^ZzP8?WsmYj4$SWPnvFLy`R>P#b^4vKNE8?X`@kh5p6 z#7L1(F`5TpJZVM|Ic}Dz5ErWyc+b-DLE&`!bq7)s>Nd4kOmy$Ctd$~-=3QM zMSpPI#?LK70I@&MjJi`{7YmD?8qR*EjFj})rUBzfo1P8xhoiD+K3da4!xq=lA%9nw zd_Tnax!gpOBFk65ba9n@!YR%+#)bb(D<>5{c1C3&r{>xthF(CY!rS4LWjWMGu^c~m z$JJAHGJjzS*KUJoINM1gvj54>SUicGW%*iyR#;7AiC3XbQ*Iuz)`*w^HqPw}XI@B} zu&|yaqH0Cu3P`P&ToPX({H<#GSgKp~6-` zAzoUe30e>t1n$Fx=|EvNEy1^zF^tmJz(Qc>=oXO-pvhqyxFTZ>sJC%c^Eohh0?aq1kr!m2ch@xX?CD#_LC2`RvV(_( zKmRRkSR!y=`HA(XD#lKtBR+MGM6!#_eMYwsrfk!$4jl4M#l-@K4o54J65bcu5~qAb z8xq5~K9Jn%%ku*3=}*GRWw~MVuinK5o8IHLcw&N>=)D8<^+o{#*2n2W<9! z_0EQFpGR5i@P9!vhz<7Y_HT^ez<>pyE#%z<0b3E?u@$MXc&(<OYRj@fqedaMD)mIedV4`&_R~6$=2QT}8D4 zeyFG%)*|+qD~MzNMBQFjtIDf{i`$n4PO{s0=3xvKt(QT@K75!)*L(G{15>>45|d>S zB}BV*)lU3t{3$7m-*Mx14NKO)iJqW^>M42W&tXg<_V?vG3V7Er;#ZT>&3Yc2Rp)u@ z)8_Tn@!*j(iiuHTCzTf|b@51-VfL&^`xohjiZxXBRz6DO+J-Fas!ClVu9L!g3gh)c zFzM+utq1I$Ri++|2b^oV)#>7wiIT}sVSGD) z5e&N)lIZY_30T{?W%s@qdC8Q>wWP!h#VlMr)+O`OG3gV448r2y#&&)$ep-@MGz^vE zh{_`7adA~4JY#OrDsV~f9P^R1Wslqj@;)EHp#|lJy+afarpD6U`q1vJw-!pZLJ+n# z8x{(^^GE})Ehn^C)pNiPfE=eFGvZm?`vx}YMv4<&sl1K&H~S;xJhTe*4$ljvJ8;mU zsz$r5u&e=(Hq~cKm7DT!`1J<7dAC}()l#4H5C`6AnVV!xnYmYj_gFH$p?~e(Lu;*tkVBUC3dLCJ@t^=g}SnS zKfAxB^%Ago#?~2crK8(<>leOu$0F_EKV>f59Z%pljJ12ibN|CI#3F$E;z9ic;Ew%{ z{{w|)J+4aW#UCJo{#F2tT>QAXN^(hqBgjQe78QqZVS+1CiV&G7g>lCV&7kB{y+EIGT&bg+$um{y@;2PzP}vERnO&}rr#@jR7Oh^P7$Y&S2P#%CF)4Z zq%5>2?;UQt^Lc@h*6!=%{t84M8(@ECdU4D3M4uu}k?r)@^HqVY?gY=0I-DIQ(EGvU zoJj8ACq4K}TpMTPs9|L1;esCbhe7LrD_5lq{c22hgu0DjG)nXLwLw72*y09Ftzq?_ zh;JKkrherU*StTvK%)Qn4B6x%6<)~)H!0w3h?CM0pcU9`s`Zw3dhd)#GJ!Z#sDjR) zG$DDz>_(>GuyV}PYbSeS@JM@6d4ecb?s^etI!KpI z_M1W01CK2uY|Z9w)DJKerr=Ui@Ps}Yo?pKcj+vz~m^!2L1De%LBFD2eNEoZd3{+r3 zOIM|Ln-4JFnrFbLzrnJ6-u$LtmQE07kku)sfS^`UV#^3ZwTh6s!@{rm35Ml|WUBFc zCAsUZNIcw9r3ts|sC`W@rYt)o3~r;=rztn=%)Vt(3vXTj^c8~_@h@L_LyDwKhBxZU zzPs)(PF&~;=m(LzxsacK@!=P-j#KN1UmMk$lM;T2r;SqK-MyI z*a|ERK&VTSC<%Jmmg4-Z1LRO%YLtQsg*DxxHC&h#eh&c13C+h= z++6RH{<>s56e5&1F;Y6|U5;xDhCJ@C+Ua*kKL*hjeV`Y6>?Qp^@XK9;qp~lIg}=QA z$@b>7pu!SzDoEekn3&Kjci5Za>(rq~R&-p=q3VPPC2kr0!MQ^ZjhNp>2%@05A;Jc^ zuyOBJx|BU80AbDon^KXi9SLiWb3`+*T$CMoI0m0x4es2{;;JNIFO$^?lh>c3))mj1 zmwGg1 z&-mJGkRFwoiZNdt{a`N{`cxXYIu&iH;Pc`>TRn6rY&zKBL=OI_BYU!=9--j7Rg>Dp z(Z{>4O7e!XIrDxPfm6g?@ED(ND)$b^GFLuv9xKG79PJ4ePAE$!y3jY)joqIAxhwx; zAcK`~kont}>38x)c>VXxVsm2`Q>*_mi>uYnRp!4Yic(v|MB+ikox#N`GE-%#wjhwJ z)S}QW>Gt41VU5cWk}NXF=pU7R;j)p<-gm*Cm0~SLLv4^xqceVAtvXI0@^<=6JrNrA zfQ;^#V|FB@4z%G>s9B|}6`0C|23k{_t4-{*MDn&(CXVq#JfZU`-NYBPTJT8k@;tDw zw{qf5^)6w1lj$_RC@eAiu=FmEOzi!{RL2(LaS&BO0Q$f`xtH+GvYAy zhy3~qiHd@IG@Cs4BTFP?<*Fa$vSl^u^QK#B&8*kyIugh0n1)*nQ7~W8uP_)^XmGT( z+5oxlF+rW+qf%6K5qh0X=r0 zx)+1Nx?Gl!uA3gSJ4g~ixTnlMK#m0z-Q$sqZ@duRURHJDT)Grmzv5 zSLXa(K5zEH*)rllF9gN9d?V!n)%MZ7j39CZZa&Q$5mAD190{jT0vX(q38cTQhCCgr zs1{gU9NZn>fD0J|bK)-r>8NC752=#N;AmiR3YHu_UER5bkr5|$3Peul>SB4^JrPRW zxXCxGQg3L>pGYkOTCsK-6#EG9lCzSoXP6@*bbC7iK zv*n>KplM9-tBvJBqhv-A<=s}R$lzwQhdWwiG1*D32XKD0t=g}iQ&y{Q5<*_&ZOCn zdm3$Jq@m+vUqGsun>Uz$T~01_;1qaY0n6oo`^x`c%jrL_{MA}8zIf``f2R!^J2TeU zCL!lIkYq}-Htjg=3#@cNt?guN5^Wmot%aN$c;!p&Eav#|!?O`vsNW4$(*m2;<0|@?nW7m#1`^GfD&1pj@_V~6- zj&f4*Yh)8P%rSNf>@HagZU(M*voooW54O{aY_%y$v)%IeYWvoUCo!IfEFH75I2OkU zem(}WR=lq8p;YPi_T$I*Ze6nDv$;ZPTejuxz7nQS6je1gjBRbAiVrsJ0O8p&3Y2Wy zgEyb1iPvh}P~`O=jwuc&?G!L+VR13rrbcc@WJ~smJJ!sqIHb!6)v9gTN05Y}rqn&ilo~ND7?}7gTM|uWHUI z&~+!f5^OktJZgKv80ok?UOKQ&E3nQmuBBGVJCjzw))ZhUt$3lD%oJqZXOQoY-*_+Y zka4&_{WQL*lB7#`TP5W#LYQf@s$6hr>rxijkkE>PL0Fh1$=5~_unR272?wYJT4%s$ z9l%PEvYNQ%kW(eh7Ze_{^CqncDR3f8RcE^^pbd+Q7l_N3`79hjpeWFdg%n$p-DN~u z9PD)ku4?_}lb1-7g5Ic%Wzgx`=)cW2OQSQ!a5PM@%FZpV$cF7ZmDWPbO}oy8rBeJ!!oheaV@*X@LoG2$iIVrj zv#@3k4;pX8yg6Gbmx=f8)U7dLEnnH5l}s(HQ&z;NVwJx%V@ZwF7{kK{ihiX`{#aAm zJe9Pno<>hZ2K}t(LM`AKV&xkL$5JyY~hyIZ8_h4yBQsfVIfrYQxv℘EQG|;})3gY;001 ze8C)-ZXF$_?cHr29MS7KV=Yr3g6o+8emIYe7daK%#dhsUniK7QG%5fs4tjPV1;qJH zQxK~&M(7cwZdMRRmwca0RUss=!uzUCOB|wDA5PO4K%&psS9iD(wtIkP3oNAuhIP2n ziaP6)VO(DhJzq?-5SCk@li1N|k1LAqJv;gs-S_);+ASEw7mFK0(e?YD3nPi>j1FD^r^JQAx;wTz%IX@&X?&u4#J z&)nv(mhH$(9amcVcZ7hn+wTy62YXIT*iF}dkG8!$@UKIsNfCBnYM_%%+I87dWzE0p z&QU!1lMD84c%GcH8A4cd>PPjn#`vD$?{zTlR++*)T~YgG`0;gfg`)alyM~nycBuu> zoeI;(D%1}B4D)z^Rs1EpC_jIY)>Tj~LSs*+Jg1*A`#LFHJ&D!CkkRt{)#((LJ7$&T zPy1?nARggWuEYKY%6#&6$EHv_{&I>#6}qbBsmn^41uyl?(5hTs* zdafq+eTcU$VtZ@%Y2jeN$$y`o@dtAJy8Ie-$uRE&I8K@O5>O`_i2lt?&1pJc8R7}zw)ByBYk`lb zAY+)Js?^bjV2bnaYRDRdUoHB!<@|SbVH{evRz$}#OI|;H1WvyDnz-mb{0vslWoW(x z*lTFtgcImusSoG_DLe3*QR3&;Xkw2Veg&04;R~>2M|yGD6W{?UKrF3Qa>p&F;KZ5#HLY5 zEU1wO6ddyXq9Se>$U+8PMm7&u!sWl7KU$HSV_@b9bL$wgf|CXemS;&AG@$jhbA1=+ z8mHKpyLC9`nkqwPcfdW8HDi~$){3!YeA#w`KGY>4=H>x%$9zgP_jH$zq5g>}Gzl=> zL856@gBnKi{-LIZGEQk+gWyJh4PNp1)x40_VYhbwMrqpl4M4!{!Ge8Oz;3~Q^evkE zn<-*%Iv5iW?YH+}c){z}H)d9ZgVTay4BtGKx)E-$i(mUNn+c(VncupaZ%DRTWzC*b ztR@)w6O5~77Bxb{N5c6X)^W5G%GE|>>lalN;3vOn`PQ^*qpbr@UU*w|tLp+~ykzfC zdg%8=#x#`IaVnhJUY3hOK&MLGjG4B3UF|Rgi6UT-u5FNtzHYjZ?jlThrIJcdF7pmH zyEzCm70-#xM|y6pC+AT&ob_I`l?3;eyD9CEPi5rYIWM?>@8P~n_}TLGk?Yedp0bpj z8HdbJPh5D2b=`Wnp+)qjbH2r+OdleZxo7aS3z5Xj-|~V8Luw@kf~`E^hDgDRjH9TC zYgQpAElQ4t>HGJ`&4)=M<#tJw)IMD%;gQ=@dD*ynZm+wK(o`M`g4whHV1qWOV8;QR zIDtx zx7~P0P8w?&k2sTCd5BHoJl3Z1scup*L}~eS`DrMs3ButB0C?05)!|=LG}yTLK7QfT zM>2>pRWzDuq~5Q)%=8{jN2g)%u@h-7rWqnq0*p*rloQPCyx1UfhIz4LxCl4#&w)D8 z^ExSR>1fzfo{Qr1x}=%`kB(R8>T*ezm!=e}zeux!xiteM(&RpuDmtBVAsG6W7X$6t z!)^nuVCNW}=3<-j>}V>xzo3+&pwSxIMO=2}e$!{yF|qTGW(|SJ9{T&j6EX%4xj&K76~JiKSg@1% zA_yppXk`X6RU6XgF7MJ8>dbCR0Dyl%|Mj3P!U&xp{?+5<{_64mTd$I+{s&0lpAn}R zRei;OJV`6ss!s)%97h5!JVRqHjDa>Iwhw2dqS6~q%zSI!!JFK73BT&l_eqi`tt0Py z1NB@K?U}0XdsCEk(avgl#s74b)4AOp@B(XuuL#BT0}2uYAsK-V+v#r9lsgWcuc_W< zpt0V6ki_H8voPr95h7{l)z`x?sDl6@pSy!x)Qs9jI}8 zy8C-QME+qdjPea=F*;P%psi!7_4Bo3H|O?|+|ftSRji}bbkznRk8g7=HRzm3@uWwC z-D9*u`-Jxp*Fl>yHpd*?Tn#2Hu33TtRV^Ve<_MrCv#9#%M?i2VmFXv=Q|biC#D!iW z)`b7ZLKUfT!&bV){WV!`K_$do^#}dAj3kK>mB#cl#FI$P+13@5VfKg$?Vl;aQ;mbD zv^g~<0DYs4Ud4s}VOR&Xx}V`-8Bg8qXrHMa7uG-<7?da?ka;iP$Y`M#{K(FZXQdw% zcq?dDtb6*Riv`OG8`jLaJF?J@d*&`%aXv-=SpJ)70qu6maiCS{^Dn)^-^JjyWggB( zJ1U$)7nDG+%)fm4`$P?)L8qufsX8euA~uq$vXjMz6>(cIXw)`|8a_?a2|1o=okmwO zn0{AwnAojW?#Asyc9_~vtS*|;2lV}T;-I$aByNche5KB~7TFfeX=mNRDQ1~2yu~ZT zeTcu^<3GUPNUP4&QMeVlKPs-6SVC|I?dSYyXY=Hyuapq?1yd}>jEF0a8LkqVmHPcA zX2$MKzWu)YUuX-_vrB2yFGWWE9~Jpu0jd~PUDf~aQGk#lKU^wZpsME}$$oeW8z7BL zB#%Q6_+-|YGjDR8LLOkgOu(y;Kn45|9J{qEU&2<-%J8+EKFYrK?L0nMe_}KQsWNHA z#JIB2no(L%YM6l<=_g60+ZbqoTpo;!P)D_;xMGFRel-@3;MvCP(T!CoPd`;0pQ!h{iYhG}j6Tx(yoHiL0ZqX<;N@Q#`=NegBY=;vG1ox)~r9 z#8`8*$I;;g!?IJ9A#e=!FY2?ltXCBeW#^HmP#`l_hGPc0^eUwY-S%;xnFLx7Z?);Ff+v><#=T_GDYIX z6~&QYHr=a_p#<3MWyHAKtpH*XfC;uVs;)c&sG>EKb(-9}frYqsj=vO&yE^(p5xKEn zarN*&IqY4B{&KjM>(3@dF1uw)yQbaz;)H)G)TH@~ER4zbscC@Ytx}&d_@yLup7EDG zcDxQi4Ssu4Eca1<08J)3R(rMsq)_T>!dgLUiNdVms`xe4FcpttCFX%=QjQZwmeG_7 zs{WK4Dz@c>Rlk!!!5hhByKs65Uhjas2(P}P5uWOdDo;!XMp3?%zUfvwS&gij0O=dD z#W<@J_TZIK+-ZJMlt6bw(e*55c( zJBSq4=E}*T_b>lnZtEY;AAZf23+$I(_rKh~|4RjB{ZFeRMpa&M{VOCIwTXqo*@pC* zAR;TPgA!(96<5uLrc9lvt0cU^`Dnu7;*oGE^dinrnxJu3Aeb-s^K7M92Js`De7eeV zyUUNY@$>d>-SgWzfEx-<(X}x(O9HzQpfT)PrE8^QrR_xDgncyawZSFpmK@IJH;xK4 z&#PpbWw~cC!-|;T#k%gcsG~&1(h4g`&KYZ}ADa0Cw)y1!{wK)LyGI*kb1?(&{+HUw z8ZVkQg-h-nZiQLPz>Kv*&I6-)&JuHQd!?wb_=`%!_h5fbGRZDnRkOZjkhnN6lDli= znF)8+ACYHN|!)Cqk^dT87H{72Y2~^?y(8)_oD#(nyF#4lX&GDDF^K~0!p&Uj8 zM=yz`PUguw703xS;QZ(6+d+kJXj$rP9Fu5mFmH%X{vx7Z)`6{q5A=}(JoA1Hym6bM zu>tytcmufz7#@3rM}3Vk%u|A4GE{k7TP(DGUFY(k3&K8}gCFqJ5FHzxr-yB?vY&{S z%0ncxFzAWl^6-_wq`jB72o=5xjfY^D*(=G$H^`@n26as2_Wgft%>It9j9g!`BK<#> zLAHO&YWr(rM*2)mCBQ37&Qp#o*DBzrgM#g{0tn0DL{Ti=bpKjUCSTTf5fmbb9v1tH zPT)&YpZUB)xI<{3{c9;d!n))4)qtU)wJPuz_*pbC9Ywo>F@^RC;MpApl+ zsJ|jqkZ}WX3LwElhs1kQmsqtIy4d^ZQ?l4}#OImL1(DwIx} z5O5khjDyO2XysXP&U$VzV!cG$Exuw;>P+19!sZ-zo7{tXDAMW?ZMRK)y+z%BW~raw z)vNpS44;4b$>}z5O3);W1)Jh7WPNIHYs}a4HQPmNtYM2nQOVu2J{q@pH3a8e`32!$ zPlr6DMSbO8bq(}udhy@FO#SES@V|0bsrITknpnVVFkB4`CIu4{H2FzcTrC~Wh*MhY zHE=d!Vw2#xmG3!t#znS9%d7lWFK{26ITgmGIj1B3Cvj)@+?}-XfhgAQ7EfJ#Pp+Fj z1~2E=+n?W@pcvUFhzLi#Hqzp15BCFsjyKhjVK^p$;({NAk?aW0Rh57$;y_9o85|YB z&%KOD7BH+t@^y|)ktCnoQ|3X~LmBt#(Owz&iXc;;p!LGxEPGZNGn7G^EL&V#acxty z{_}pG1~E%rE%~`^hUJ`8=U(2CE>ow@T^@}AryPArt;^J1Zut=aSNW)F|68hk1QdK_ zhV;-XPOyp-4#mJrgLxM2O^;*8ha>{{-3lz za>@t&8%<}9a%sCdrM^G8T5x2TgQM1d&}{0pQUF9q0oW}ETZlb1IYPe|0N6w^JD?PtxFFoepBXtJb z^dd~-!b78rjj~MVL9j?C)@Zh7r}L>j`D1GR_=GCED0!Q`vCZrLt9M-?Go!d9MNbh{h_QX-t?c|BN zXhYXgp*2eKIRbZb(R`E)y(+dnl0i3c+nCQ7GX* zMqYs1*4bRlh#z}JB}$+lGKJ7laA_oDY7oDvsHLn)Yq9`~4hI0z5y)4tXZma(Dk8-9 zZ~ltY;o7FqDI|k^Z&zKJeip-bA0x|--w29!^P?wW{~u-N6x>VHuK69?wrxAvv7PML zwr%?#+qP}nwyhmIJDHsMs;17&)tS3q-CcdrRsF8j>wTW*XT8NCKD~b!5EQo7P;X;2 zIzpfS`u^rnD@&NGz&AI~iln%JVL%P@O9z=+=X-88A$p!TDW^h$Y!))avrxVc-kA_8 z3J-03(3v;xE*>-Zs>=CMA=n3r2IaIQIje#ye;wvJT`9;=2D_ev+1t@<7E24D(M%4M>O_BJJGn8tSZ~%OxAy4 zy%wB=OQuF$ytE!Q0PEhQFc!PEdJ0CTFVX@o*h=HbQTrcF4}4TIg}zz3oy~K&OYK834mhu3#_}^Nywt&p4p~Y`8{_%K|pbt>15eId+=@W3% z=zD^Z>-Ojs+!1V+l~ZPS9Iit+vy7hX7z90qPsmEIoMUvZPG^$_yl2<9)@zd?Y%jDG zm#uM2F0Rcj_69x4w#+A|8;bvXk|_Cmi)u{x>sOt_uU|C(BjbXdwcUTFh+%CgciiFn zn!nr25|!~}m*@#~^>8UGG z_5O_($^-Yse})OZ!hU!GZS{W%jtjuS3*JU?WMO4N^zZRcyu#r_3dNl&jxf6WB1XCc znFN9}zzRWeP$?VVVhK_n4kuADy-pFT+$&8aVRi9BvZ4PD>8A-&7_FpKwzQ{ z3^~J*(Iqu0Er^Y4GE4B(>x7{nT}E7hOL0?j?d(y^*-?<`Bsrt}!*l-)Ei+aBsNevObf>AMm&FbZ3UZX2WBzDVrQ||}9i#+u zVV0_)k3@>*2N)k^NjQ2tF*9fB*O5XjRF+k5->dLp?POcW8fqP{ z@%o(K3q1t5Tf1|rO`8}jY<(qko@6dzFR4fD+q<)lj$AZP7&dq5U1-8?0FeSjbrxo(iil}djRoWrR zv#{AHmiU7Pi(AOCVIw>w5v1sb=H1YjoA#94OItl&guK+M^k*@!qQc|#oGBV*;_Aot z#0U&q&lAh)&Gmv0{ZYa@=9BZ+i+E3~7k$jAT*yEHjXqK^c&J4j5svx0MM*2TDOc(*WhvE68+9kg; z>) zgg3eb!(OQ_ynq#l(hB>Y^JWoEpHX+F)S*Y1j2L-IWRN*r+g7}ch^VJsWeWV$0+TwP zn&{0}m*izk8e z!tKM?o(&2_6OntW#3KLf@X;`b?+8};WQ`SsVsC=Dx39LA6D_(njuQm_&QSu~e{wdb zIa)B?Yt)-tNw`iBX7I726F|Db7U;XB!__01)xAO-<`YFTJE%_tV67p=#$*NmCB)*9 zJZXu*Edh%#c5k9%7ei8+i&R`0aTN`@L1amEU&gSCA$kvQEZO3Xq_glFM4X|LOs2b> zvb4WkZ{QQm%}U4DN`qdJRRx@I0?F7du*zhHl2xkHk(|v12NO#zA!HW_Pv<10vaJZ6 za{#J()a`;(_`iZ*fT&aE||m3hMMZ#vF3?691K;&DdIRG|C(UgAhK% zlvPHgBB@TIR40PdU7o(nl`3*CZ00-&6BdENundm9iXoSG=W%& ziV+~=XvE7d!e5Z=JoSU&$tEo>YWgVCTMKbrb?Sq)TVgxq^qptogiwq zCTauT*hS6Bihdp#L$yY`GJ>S6Vm=}2FKlKYce`j*+azaul?)xa<%#%Dt+(MMUQlg| z3WM|gz-CeV_DnHyald;Di%P!Np+h9FAYiLx$(f^o%VpbZt$YqRxmaWUkEoKg6X`K) zFw8`bWeL#nlp3gNeCUM>c`+y$cY8oFP5Y`QGrd?9iPLa{Wt(b~I3jU#@5@LUDkas~ zGGah_>OepS7M*A5r(c)v8GYGlvEJDK2SH5YZ63QAnEg#_7xoPv8gPJz-S zG{d65YZ87===v46tz#rc4mj7cTPL?8cSgFH_#Yuc3~g?ybnq(R{pY-ne6Oktk!&RVVaXmAR(u@cu>F2@+f`K>l0PvTaU=8X zfKADIK&4A^pA~j>WvErbr6{tLT@wJrp(Y(ma;P}B1C0)I%z`Nl&U4db{PJ*wIU0&5-2%61RE8t}wdNQ@B ziT04BdTz)RWFnKQ*L5Vc(9es3V)egaH=Am!>e4qDcgns zuaBGZ187@r9}K408`r*2H_IdU2FjTze)ZJ&H2K0p$q8jRDTwwN^|#!%7|6a|*Y*tQ zBL1DsZ#8hb_t5SfBS|r<@MaCR z4GPLv+_>Bk3i;*)yNRLPMwv5>vHWjxp7iWMDEV~jIM8dt7GY~Ma^0v7QI*4=cF-rG z-=Ud1r!7jPz@HAV{LlD8IqI*;)*FXUO*08NYDzYQ?xQ0&~-G z(5Hsy0JvwGUqr&GJ@i5?E^~}g*u}YS$J%>?I@}=aSJ!y&RPTVkYfJbfzIoyyMxtM` zUra(R3#ZDez(9~|ubILPJt7Vk8J26QPe8BveX4z1gI;*>zlEdSJoqPSm!nnn?(yF7 zUXzC1eUuNr50Ds`&v$f})?S5scJj~7Pag7b`tO{dinwcL?=II$$yg?dlV|pkj){!* z2?3i?;vj91Ky$H)6?@$PA3f{Nuqx)*`z_q5I*DE4H63Z0oh3~7^mpTtb30q~+5-8@ zO{x1#&kpiKckMB}i}~91GZm$^_Ws|dbJwFlO<@;^xUt+DN1Wo`$M-RwG|=wDH(y`U zA7hyB!)nf$zZ`El$KUgoEoddne>i?Dj2{bs{Q`Htz4RKA$@XR66a8XY4h|Hx_Yd!L zT?r3}I&Kwhb%xflCI4PE+NM+&uDc7K_;#J*WoLx?&RQ{r@A0}TB}G`&N+Na56rFB{c35;ZACd>d?+~ab*1I-s z&*h|3E4Xw>T^++>F?9e14C}MDi-Y}D_;Ba2YVBb2seL*IO%w^#DtNJL)8i@k*8A`^ z@W$!`8|@h)Pszl@Ad(U#2h*{t^(uJLsZWmY<&?1%DL3Y3^UBV$^qlQ^U}E!jnp_}z z2!uHge>YTHo}ik#0DKdN=aX-V>rZ-eSU=t^)~~W4#|`NMt=pz33SR+;T#VkAKK{E- zg1>0JFa1DwUIM&?z68NxLpPvBLpOr%>Yx0;v5~u@dk%LWpuAMRy}#rmc1!o84qmX_ z(bYQi2F&1R4Zb|czD>#kYAN4p4Zp0UzAn@J1jl>B-%^u4IT*iX$-e2P{ItgXARcyA z?{^13Uy?t6fK0+<-y~DtYs04$iLYCsvkZgsO#iUx_j+LjZ};uw4+ZsOSUSz*f7xYm z^%?_v$HWHsZ3;rl{Kn_U-poK}=LhwGAo2r-z7@5{F@=E_+6PTbqbsPgNKRt{8h))X z)Ct~ooKeK#RwFmUJ^0EN_~SN z*GKH#yVftv!Y<#J@DWn)2e9BsGT;XGU4sp&1Ct_xenJcyW`rIcSg%7ms6#=%1(Fz; zW(>`K#kH={SsUxzhr>%(V#qmQl%V1c!-rFYNm#an(u!sRZ3Wud zicW5W58HPNHzE%I1NzchN~aqBR8;Vg4*y6*?8=7Ct-De0lg8HK2?}odP;BncY78#TyVettEd^Y2N76JBcfFBldmMrYy_4 zgca}k*w&?jsTVQ=Cgy+#DMspg9q)#)G%`V7i~Sdo$PoOZiu@ygL+{+6-)RvUw(Bb$ zg;P3;pmGsM7D0MK*YQ>f4!}}f(O%Vqf1&dXP~R)rM{8|$3T;{TSFRzcU4_%Q4x#ZJ zL>6;;PM8&;7=h7JdT9{&=HIgf>l1h?`a%Cm(ALwWUy$LLgcbh_`)AC)t&Z4iZ7vhb zwbgJ~NGT%e$o4~({#ZR-eDhnrqqHF%xIsne*>LfF(I<}|Y_vlV;o%Gfz0BOB6d^9# zTS*}uQH35%hnz>tCfmpIY+Pvq~_#000S24UFFJFUqK(mv6Kd2)h}# zuW8&ScdqUNKgb0aL3xGhacojF;2J3W4gpLaT-NDXnA&-S|iH*?pua!aoW9i~JG%1e0 z@O$^xU_nNA^;Vg@PGGrctM&Ab-*;80S$o*PpVqOul0Z056NOFAC#89dvSthmT=LRp zKP#MiEl;cfA`=X{$CDXpK{sq`aI`%Pk~K1g0R~l1{|0^i8>5@n71}FI?*ja~1*Cl7#277B4L{)-~aQklCw$!;WU!w~&tZln_&a@HoEXGTFHLl&${iVw(z^d2qV5AOd*(vkKl9Dtpf<;BQOQ_@;N4)69W}1sYQg>w~nu-5N8ZW8GYtCXHbl zpPr4{k$b7#6phw*h{DnpuuQokOdK-8(R_tAE;7mc(ee(HZ76*6W{up3&=#f3x-6U6 z(^Drrze0LG8mFu&Jcx2CguP*r2xbG@reW?_@eZ8AU%kMw8xrgkC4_X@tbEf11 zrvBB51@mk-tK9xuG7{oZ{jE_My9j!8j(qR_ILe=CY?F=Pb&F-Yv`Z~pgUqWc$6sRY z2=o2ZhvZ6H9h(+{(W@$9x!rwc^v`q|i)w~nCU8fnY8Cd3TCCk$wYr^5>Ssse=hFz9 zPGI#<0B?4HX0sSu7XEaJyQzIKU#Yty;%VCVGlFjEoIeTN&n<=f4qKCpKuYXfYkFnK z=DE407PvM-Xv_c82mAdaAU8peCvs-uQ4XCOzM}PRU{4LZleEUFL)ril*;hn&D*2UL zMrHcMj7b}05A8bFr5hQ;+cYa$fF{{Q^{&G89?i|pB`CCFPWX>%t$i7d`c?k-oLt$n z8&w}0{Ox+X{gYLjt?-&J-Ksmi_CL*K+<)5Gr{Hos*@xO7aPo+ zEMR7QU_qK7I|YPlJY&lMlHFvK2EYTKMx5JeU=`bSKke8d7ttlBKqA)~ z)73K@gHXUXSuEL{N5S^lxeAth)+KFC%Q#|>)IP7d!%D;(k;=PYQMlp?#0+-L1d>zF z;ZWj21Ve4Nc#Lp8M3@n6S*!^;p)n$v!c`L-ovQ=w1 zSpi)kb?g|>btkzIj9Ib2|TQj9X3wCJRZC{PM_6sclUR0@=q&z`qum&xG z8c%Z7!>Uo-ybvE+8p?N(^HS-b=D|bvZv)k5Y=C_Sd*|aNy4ga`p+{Ri0|1f{G zgNJmHP-TcvB}T~}Z>tc~6>Qa%hN10L!CXSgxDsuMeE{BC)Q{LBe@^!5XMPl4 zpyQ%;?$OGRQp}fj{BxGFh048KJ=a_|=TbKJ#6{y=$)aVgLavl5R7^0(I$y1T)`BuJcV)w5wS4XhDV?FcmqPrKNBl8o{PDDDsDw0P`=Ys`o2Rh?4liV|w@*8{!Lw%8 z$M4*XXwmOb)~wKj7_+Zw54Pklq+`A2@76GT0ko>_Z?)ymU;@+?wOtKi-TX^y+h1S? z_?7F~gKrNEeGkmGPp$FS&fxPokbKiGd1sKGWYyz;GXqN(#iB|k9dgft99sg7SA*Nb ze_hboea#5u`j$-wj?*<>_O6s~dDea8+?w1|##+#MS#Wr2HS;q(B4xrMNDW(yE(ll7 zkr33@E@q2uTHNYBo~+fRTmJUsxEZ7W3?Ux>YlszI>16sr=mp7qvx67OcOh&$cgV+1 zPHybx8CTr5p?I!l_<7Mm?(7y^tc^Ljd4ROL`4Vw7Qs8Jr$$369Cz$k7=fvHsOxO-EDL9byH@yUT9u#yc_;6(BkD%f)Y=0XN;sgy6j$6rC-LokF*!OcsEFGfM{ zF|b1dB>6tr6FfiX$ui)N4h(OqFpM{pV(tU+t0G*#ofonAs-s^ zkQ2YA+9A)xgq8iaV%Y!gQ(j5FpXzSOEjn~k!nCS&wKbo$=_H11(&%n!I&axd4_yD} z>Sk`prXQF2s$>(r70>4cbDNZHn2}jKGLJNLO^-$}|AWFD8^`ay-r0BeZjQAm7BSv$^yg+y(iS~haNka9L`D@1tpCQjTDB(lRwl;cWjyNY6 zSEw z8IyF$t9XD5rLp&*Fx0I*aDI_qR6{$7gjya_o+K|aNVQU+%o~TxYq(RXg6VsX8P1%c zgyjnj`Uiarh^t+ArR263<6 z^!c4$Gru`liw??9i`As0-o-+%@7AURg61FwgnV1)n3PYZu~~spkiY6sFX&p-rP5FC zt%P74?ep|Qd*?yvqn%gsuQHoUej|QoQ8?$^ zA|1M3SD%2OdW~n;jdlzJIcQtiew*y0mJEA5k4~#g>Th()nO?MthvjZ2uhSk(oRyyW zC%|E+Tv|F{*O=pf0SvbV&d*BYWu@Z{O?x%|47V*q(NMU z1Bp3q0)ri)$|yM$t5o}`sbK-pyur>P`Vtr9KyOt1AA5}~O1Rl~Kb{BNS;7n}3eV9=W?DA)6OH9RwDd6=c?b{7!!BO`*W%-5r9-_xQqE4GsHRE$rYN_OGtcx-u6XKu3G6B2?mh8|lovdH zQm0>BLq!p~JB>O5gbT4IZGSObWMH;N@B-kSp|gZ4`z)HEni|i9VgXnIonug2!n%9> z_-F2vj8R+x;*{p*JXtZF@rUTe$nMb;zz^=!x3IJ2Da~MFk1u?)wYCzOIOe;Ly!TyF z^bnQ~Rr~6MgP*xGc+8e%yk>3J1ojoATscotifwJm2go>$(HLaqx*wJ-r`*q(Z8DQ8 zWL^GBkvpD6dHpcO8yy)e0*s(f zoak?x;5m7e`u$e=2j|PyXl`$>FNk|U9YDIxD%K0%vh8Lc$W@2e`EG332>d&^lrCO^ z1yv7jP%gKUbdfpYhX9F0enBr|hiQ2taZ>FQDkregXg+aT>W%;JW%f}WM`Nl$yOg_u zNXJBk{3j*(54FV(lQ-lFjLvuopJ5sPnFu56yHbSwur+N15kYCu`qgDxDM^mxhc0Dh z3Li+>QH~NZkAz1K%)(WzX!%pZg+qhTJeE58&TovL^nK~fB9Hz?mSc*nGZ)pY3+;+= zaRY$!LBa7MRL=XY{rV{Q1;4j-yZZ^r@63))d^{;j6j3U*#4~$dG^Q8_r}B3tN|&90 zZWn(n_NhF81A2vIxrPfx4Iv{ncR^{Fg8Y;aj9fu`_djB>>OVGWIHIV&>_F_aTF^kiKFXT;p`>*R&6ee=Qi2vB z=EC_g3@+=ijB!&3f5F2EKCkR<_1xv4@cBj$DFj{%d3Vxfg(&TgaUTp!T~BsCcwf>x z-5zFpd%vOdfxW=N87=mp|F$k(pm6cV4VHrQ4<_-tQ>ra8@iH?8Y2fAJob_RVpWLdC zqJU(NVW*7-ZfUUIlJ!LHmj~dcIP)gX zpzBz1H<7hUx1ikO;j83;bxD{Xp7O}Ec`1aqd}!b91%whLnmKlvA92VV8K)a(xWdQ` z9@Ao2=WA=4>?Cw+7G=AyxLh4HTsypJZ(2jKbDHqD@{b^I!kCKm@sg>9%?73eBOKAU z6OeaJ!d%kUU6>`V%X*ErM7F56ItGjmcMx0HdRd2cng~3`60|NL8pXV-$-yzOD3I6Z zHB1X#+LoTZ)1KCV$*Y?zH+KhyUY7n)c?-H!78p0`*7vPf4-7kTlho_>(a+#5_-a=k zTIyDlAwz!}doN)lqoZuRa=J2uEN>#uBgc$_m|U$_T-GU*n-`YQjO1i2=i6OI2k7_Y zHHV=Qf?KS2=sPQS%@IFB?}(e*g`t-^Nl_>!%46)KuRQx8L2_d>RND)6wtatR>`n=I zVHD(yb9I(_KunY;&4HVXJxb;pv!aM(7~{TSCbdZUH*=ESC;~aJLVgK@y)Zd&lI)ef zn(ztnl*HMfr}huy6<$@9m5QO{J4vgsM>w|GQWn5UuU1hVT{PEF2EsvW57%w%Dzx6} zqijQ(Fj{y_W^(6;c5?Sh(Yv)e zWA3|T-rb;%`oNCS9%(NzZ@MEtDRf+OK)Ty>qo}a_h#@+2he;9_a5S&xksdn!lNGRW z&Y}pp9t!#{hbV`gqc^22E`a5rWYuxyk!1Bx1YOwoXlymlS43^wYk?n)V0c{h(?8j9 zYI7f6=kIkQr>P!;67;%c4~;hJ);5`&G44jw&rN5(_+(09_F^iH_vok!iR`_Xh?!E)7|ADB1-2zBFgDL zO+{ia^Y1j*;*2szfnC49=uq>syLiTX!#?d6ZK)qeJ0*ZE$sE|46T*?26L1Tfc!Zvb z?q}zc&B*_8D4kPpRLo(R1O5d*yL&xyV3w4hfVuo4Q z^R)?k^v1H{v#F;Cr;CN!LlyTk1Sv*S`C{GAD)7G3%Zto-N#K4l!_3 zIV%E5D^m_9A_s?Dn2XT~jkJWK6 zf#td55+KNZ84NOmi=G_y0MTQ#7fjJ(z0K!RGNg<7tiJd{7WgA4dqPLTXs!uut||Euab#*Vp@A4=%uVYv)^)_|p4PFSzr)KPvXw1Y5f&;Pc8r;CnJS>+@(`SN~|gxqo&xe`c=5$`&U{0lvX}9(1lv zEU=X#OR;E^Jxsw)J;j$H0aq0JET%l)?_MI1Dp>@MR^bIN9xJk$Fu$aq2}WW$OsW#X zB`WbVu8O0%l!q-TX!jQ|5FDcE|QGQij6hnt-_0bZks9{xC{+W^SigOdLCbenb{rC4gpr<(vl#sY#+24|kI9dPG$HjwI>zqx4DA zTuPQPCJ%a9D?{UK{A+OV3Wz~hT4ZqVJc#Hg8egOj@lPBi-p=kIM}L-1JSBQKBkht} zSWB6OgxEaq-)pkuP8_8%YQU3pBTHy^H@z%7+Fp{vi7>}-brac;PPfBmx%_>8TW4XD zMQ<<;OGEcqHKbHZayD%{fj?bby!HooA!7)_T1y2je|_{+PrAWG`PK~j48(23; z5c6QEMuwLMb@rr69Xfd?eL=O1di;Qj%}+jZA1yVD#Y7-s2ggkKxHKvnbwyVzN~wYE zJjjVE7p*4I($&5sGD*V3XDHc?oZf;q2kD^RJJhD5&5n+K<3{@B)JRw- z!rd_s)5HQv%8eO|Aex+qCFsqdM3iYG0olA>oi~$CY{4UAnKrFZl!EzASW;@Mq?L37 z+H<|lWj#=%1Xi#nZwXmXoYn$?)+G^~5Rb}7(c+hM3AlnD_iFM?DLK{Ujr=LgfGW13 z>U`Tgb(riHfQ7unp)#V>3GNKYzttgH?S*a2Bm^oR?1G5^pOY=IY zIs$c(7frSWP?Q+4W^QHZPP*>7slbiaid(k?B_r%1YXUhQ9rswyto(MYSR;e-vhS;` zTDD$Np`uFei!mz8CeB~Etc`Lr&FgpP9ou1tq?z)?|LqFIuXc|nfGIv>T)9%_(HSz@U~gwi>0R907>p&C`Lsj6Vm z&(_eVV#8Tjce@eM_uB4@&6r!03L2_uQIUys*p;%4FMv8tK{47qaCN29cZ=G05Lh`h zTAj%5M!pD9C~3*UBE|8~qJquxn$$wt4AjUS*u;)M`H)f-HM+IZ1$x@f*wRc%wpuBR z7xOzru7^;);8rtJMjoRSPm`XrduiOA@GyNP2n*So+TpG|3;2MO9wnb1fh|#v^QF9^ zoDp2>Gr(KL)=`YuN}je#=t#he((?SE zbtwxpy1dzD%L&$i^vm_y=5BXb^1A&WQ#Wc8j-xhG`S0iL7nc{&HtwVub*{E6Zf?~3 zwjN9d<|Ii1G?>e8UKLq1u&8>J&R=Z`blI7e8Vf|P&(aV61Nd;Aa87MKcwTQ;6h*Oh z8s4+;*KDxt<6P&p3nv!S!xQ>Mz^dFjM03CEGdVo|taQFXb&A@e|CiaDJ0 z(`U>-y$ffo9_6x}Jtfx`H7Jr32;emNOm*1Hz5NGtAs(phNU$}r5uJ=X!vyW$T^##6 zSfctbr}&}@5avV#FM!|?#hnk_sm|HL0){1T{Kn1gX*GMjhvCJw8_mn=C-5zdTp_1E zolBkNzfjGfyr~N9d%P7RdlnqPIW)H@>;Nt|{FjRQ%3Wx-*g{Y2f>zA>W7=YKVIFqH z#!kdRq8=U1L3(VIq`ARb=nK`se_|5^Mc_6|)!E$E1);49iQB=ufS@7FIaYWg01+&4 zSa3_YLU+gw1pKkRo$d7Rcm-9^thMSr2_J8sW&sX!>9Y_E;g>!PfMNyhMV@)W~!Y$ zeQ8>V_OV8PIV~%!Mit$VkEdgR+`b)Bx&P+d^wNE$b0GOmVjUpM>Ox-(QU-ksE*;XD z?`yY1+YMt6uphKGGqIyo;&WJ%ZBv>x0p>spY)cDmOaCNvCzayQUA)%`W=buv9+o*q zpu+aFR_-)ZbBl?@xESCO9h@B>oW3WjQ{MDRE{%JA!BNN!!n%7tjsC%-V_=tGJ~8m+ z6MBzj9wR7>-;G`73}|-8#S69>4#TyvOmj(@gq^VBN@C{Pux@QmA6C}L-m>M z&ziKcpp%L3xk_4rB$@YbN$O0l6RS;eeZWoJs&v_a+j;Pf0hVq_=&o7U zKYx>xu;>hedbDnla$oJEDmM2_JSV;ls0CYM02#5SRk2#{@Kk28njuPRVQ)yXv*y-K zoy;x1srVs{D=Yr3_xSE)Zrl7J_uxw1S^kr)1(L~i4x>#2=blFZ+Vb@VOK5|CX-J%@ z+okZs7Fu~wpzGja>2V&2)&2p9Jmi?q2-M1S+0ld9(!uHDBm?Dcm$9u5S#E zd%7-Qb*=#Q4-JPaC4wt8h#M8bGfl4%#>C~?p8vM(7HvguSeP@b$gOJ)DYokYo;$@0 zc3KpIr8ITB>&Av(&Kj~7UP1StmfB-5)?i4t7^87c+b;iN=tFfeqi6$L>BeIAW<6&C z!3w*ak4AticaAFDRt35*8$zQhpRE#{`JWi|QgnkL%`5Y|q=jyAX|cZmdOQIAWixo= zn$jPOb{!ehevG*yd*tc{XsSQf7X3RkX$0`@E<`Xaf|`%w zjWc}YHaeCGP!5$kDPV_u27*t(W#YS44XK*MRC z!ejavsWDXK5O+4Q2;@C8m%Q(*A|;jcDC9rqD{Y6=ZNw(yR{CYH~3lZ{7EUtabW;`<_%i8XmO}I+YjVwNtoPWG_p`_^kwu{dkIO`s$|$V z{mQ;R^t{HrIPUg^RlT<*2$J8yyQm`H7@=s@6LJ?ah-4(@WRztM>BpwWU^5@y}m zR4m*H@b{!ZuW(~(-i<-K;A1@)R4<_oob^2L62 zuvzMc4Je+kIouNmyG)A68vujz)Ev(1iCRdooENXk! zV060+$i>Hl1LCdu)LEzeluy6Ym!Xh?mPv?KTR}3CX^J_mgc2c77jGCiSu|+EAbrB9 zoqGV4t7I7Z++!$Y_JU^}7d*AuGOv1P=v?#!cXFbjjO|~RawX9VM~K=IbThQc_y4oO znXfg1euVhzmjLkCEK1dzjLJ$~bX0Gtj{z1~ZIHQKasYS~ za@j?$C_J)PoRXVEvKe#VTj_Y{u7cq=hcnq;H(W2gUk_O3=_ zN51!-*spBeyZOpT0$U|NRj`2r2agL3Wvlo7$0qE(%wx$ z(mqQw(no7b>B$ydQ{rCj+GR9HOO6`4`-jQe=ZC6YnxSmiwae~!i@+plkTD_16fYD) z`<#m-Gy2X&Uu6#WZ4M1P;jlvm`2p|hj}oj%Qh=q=!hLfeD{fI1osdN0afg^(@KZ=e3k2wu9!IO3D$YA8nblp3>YMa`bBsGJO z$~mvEia!MUj?Ll_G9{wf`Qhu?xLk%K@6jX%Rj4jvL1M4|NHF7_-Dgs;VgBtGG`kLS zkYq`07DsLBz&4`ocIOJOl%3O;tk=#j8&YA-<^Lzs#fW>?I~rupZH#B@m5 zOoij1rl!Vu45Ya33^j1%MocUTX&o(1EM(b&s|F@{|%37NAp0=3y4J_q{odWCjrp` zj|1AKRg^02+&eO#fGcLP+uc}Q?ZVTJEParrJADcbB^D#b0=aJ1`pCeQ4i|$?nBHVr zY6-X5Zqz6izSgD_h?0_TmDtb`X|j7tH(auS|5v@fIcAV|J1b z@Q`V@cSx}@nVvEMJ1y35OB#3JMLUU5WJzO$=!jDlPaye|aE_&- znRbUYCl&InyNRjcn#45GU{}spTNE6CKMn;(l^G$C(tTeTe>)D6?=B&#WI)X$3htWu z96{|TPX5}Ev4+DG>!vQ4YnB6UuiS8z_LbOFyvMOkhFw_zUeuuQNXmd z5C&-C)>k(Q@M+ObUV!qnINfEDK(naSpH-l#QghryVhNK-q%?906R~g@z!GsGq(|%= zotd+yq!C+AWn|$w9IU+kY>y>-C_5|V#itZ7p>S$5DNnhQwi z2NnY+DG8MsERs{56`Uu?6xmBq##;~&1eK+N zR4RK22$Ve(Wm{H(B2!SNfXc88QNO1uRx9uO;rWM_!Z}ZVH_1)XB9uy@FuZWE-&c|@uD$uz{9NaLD(BoN^ruc9LKBgYwEiIsQba7w~bhvNM z_{v?K3Ywd24-q;oC-OWJJA(=_rx9Kh18-|#^WudA{+w>;bryKh6xm=Er7L`YikwOS z6PNxQ75KaHk1TE&{{t6_JmPgOdzR{`v&2sX3G|X%O$vx)FB!utmVDvn>xWq?-i|ac zO1~e6SMqUgdXF{L_(*HcT=ZjVNR;-J6$go7vg6|RmZ++V)tRf#dxkc{r7wF_bjp=@ za=vOr+8<#iWkiMW!q+^6qgBwPMgR|=B@nVSi6-kibD^6Ix3o*?&J+Q#sySH{yTU7d=9_bD(=>3- zTHdLzb4%G?hVGmGn?z(N>Sz#pQM%=Hp@$;9MwDVstgJMGs`kc2hj+O44>NueTd`abr!%?KYCpZGuGE-;AzZd%Q5@0(m68W?!Qz&y>nBu+KD%ZIt_L98zEG4^TAQsFYwUmkG;! zUB3WNId!oj2rX*t;I{9E=sA6X@EE@erzw#5$D}OFtQxfMK^BeHUJ*p6FCs9dv?#Tw zA~6IhWB#?&aepp0>TLXb=PMVags_8dz83T?sMy(igEY*g$;zMF&4Mup>}xQGs7CiZ zol*2|a91_9^#@r5l!>~uV%23;BlJYz6DSuqj^wCxbo%-St-f>_7Li-3wk>bX-*||T zB?W{huQtWmW4q>q+7#@PK3m?UQBXa8HgCP?rS+f#J9={io}fbck+*Ef*WfV{bGFE} z#9i7hbv1v$PGTX^e~K8gFCR_WxqJhxnpdZn|0yo^+U8ON`3)&yuHKMFO9twY4!mw>5f)Co0l3|Cd(SZ zgSne6;B@LkTG8Xh_4jBRqhy$FHgh#NXto&_w0&6B2*&Do>=&Q%a@H(JuIoRDnp=ZL z{(vOfdtl^D)~bBMN&_4NsD8;2$T;DDWCL-$Ujx@@m$_bcWX=vQg(DA__NH<+zS;xkSz% zJY=O5>eS@W2EUP58h=4QWQMPSc=EX)i6lz~sR?hmU%plL$CK4ZU%SAXl8+f4Xr$%B znh>4VK%zaQA0{|v#%t_L8dZ32{LVR3M#KyDiD6T2Gcc!g|9B7;Mt0S*1@i2T(1*u5 zqcM>8knqpMnOnT(8x@C+s*RtZ(iJ>w=ZqaUeG7Z>w$$XA`D<-cn`IeZO*XdFEvImb zcSLJ7*6R>t^gCF}8d1o5^4ssz=VwD7H$aELYy7MWoWj^Ud~&tz+`N|-JRTLd6gMB4 z8nKYjG)-?RS7CQCrqr!yKGMP>*!#$X3iE~9z!bC2h9T7v)T_Uz5iQAD&Pps%Rn_eg z8HO2Jy_6E*vVN&bTelOtRBI*I${JyCgiu;Yz%U*L7% zGmX8}c*&s3a)OOuxeX?F&9=i};mp)D)k|2_;o2!AmB`rnNE35uu~r^*$jD6Vcxb#% z{xMzj(cxNO*j=VE)|}kd<~gq@NTyHo#AKON8!Ae3!v9IfO5EYl4&&D^7id?jtTvLx zSJ}@eNGV)r>hHb17K21uv%i*ZM5dewp6HTcD9 z7LiRJzK~7x z%OIw&VknI=y>}?1K_ET}bp&bcd*?{W;24Qn4`XJbjge#)e=mnfU0>$C=|L?!$-HQe zg|5K`H`u&fd0)Op4U1L?h5!LXyx`V=#Z*tx3oH55Ok>s7R z(~1VqL>pBvteAFLVARxjYVCCFgx;@$N0IxQzBT zwgzVPv}^}u18YS22}$N$Hyey) zsF>H%3-)u|H|eQ_Gbjw*r+E}%U1pvW<(5fSA5&hcaCKwvNB7&H(3Kj9H4qCO{zCaOgDO;fwKQ*RR8Llq|&1{ic^;CsnW6mlH1I zs<{u&PG5Z4M;HOp6s?-gc~ErFmB_r0EWq)bFR{xKy$AphKH_=`gr}t`FlAIYf0n?QjIOu8c6c z@CLG`hOBdtn9-Zf$@6^kDS2iaKTf`NAjovQ;%S9bBu)=a9by{qshI1VVuyyr)9!QE zAG{!|B=m(twEr%m|1Ojwn1UtnFpHe3`NsWLgDwdF6Zx8T@Y_i@sd{Kw%2%~i{Y_t) zO<(>|rpw;wvk#Z2LRwkQ?D-DlpprE-q0P?F-!q>^;2|F zbJB^d)jIgRNO9!o(|tvdGhc6e2T|C3ZOxUC{sI=**P*ETNRbQhWVn}8zDld>B}af> zq&kwaTd3qoDt8V!=*iMnAOB>{T)-(kA$G%SLJq7Ssx;&Tmo%Cfw)n5FN#6c^$*kiE zOd@#xdUNE>XZAgHdRBJ5)A zYv=mYYWL5FaW2LP9=3IJ5puHjzijOOUN`h4eW3l5kOeryXxhHq+WXEu zm5uA=edQ%Oj_Sh=*!OjJV)X4)==^179$fAE3{rDhH9pDsKHp%lX0EwP`gvtqjNWxj zf(r>c>**~jO<7f5jcmB+u=!yAa5;DpHDB1fy8np)Bfr`sM~*}vLy zW}lx4)MtE9MxzGiq`_BTWN#ejNSsa!U}#oc8kwPEb4Tz-kM*y~I#er~UvZqo^74ZZUU%5D_vmdn0=kUh(h zYdPDt|MZL3iNXtW>IbPVvOcsRmtCsBenQ6bKHGC;YMt%OHQiC=Yd6eJ2+_wsBRWDI zq03ZQ)m?p}DYt9FH{I$<-LaR>%I+pxXX|Kr9(@{o{0haivB=H%IW!uUI@(_*NohH? z6iT8hQgOi*%`ebf);eMCdYo~5c*1LCf|9)ZD7DV;XVT?1a=dL0u44{1n(KN4I=l+J zRsUCAx_i0-z7f5lc3u!)-40Db4FPp+eYHHp5848n9d8UMg*qS~UI;@@B0(JdwwnCJ zwxkXN)TErmN}PoyeQB>zTe9Z1a$<$6X`nt5O zjIB5n+M=*AEe?fjoTNpF-n-}O5u|g55imO1Lqt!EGduco7y%w#e@d0iPK#9^m)SY}yJs>MCG}p^&x;o&fr0@AOM15HLi3B%EM0 z@Ha4gf$@YdD$YV``x)FP5C`l>!sS>6{>J6_KH&c|Bi(jB5H90kV1WLT@yAT@p8&Ss z06IGZwkL+)NQ6@y`){P{{}1WM6tmqV-_g{jj4R!X~j^BW9_U|&Z&zOVHQG!6Iqu&j=x5Z?@I7oMFy`Po;R^;Dgd_UR#RRXS2 zo?0?7umd&N14zNSOW#fzuor;3cF+%j1TQaOJZ&GF6T;((FbcsyL2ZC&@i^zD+bIJk z#j*>ylB1pNrJdNg9trN5H6}X*0tE^XvPq8ZhV2a9nT>0dkzjDYC*bVc7Z@Bkd%*3K z0W+4^1zQ?3$&i69ZsV=v)AL}XU71x1uz5r-s9tycEL9Iu?G0p9*=AK=F*ouc0k#m z1FFScUD!?;uqO4tmGNgSa2-d_quYE67@-Nk*u{kg-A);>0LU&RKx{qToSpHvkACg* zI6MixoX`S*PyPe{*ywNYqC1y9pY`o68K7&H16>ohV%km_u=#U;gI9)n+5t0=o9oVE zoMq%8l7N^yfSBLa5NP%{Vj$3qb~{TbOxpB02lRggGvUNTdj2mY{0YbPBEs;m_*Tk= z?gmZ}4E9$Y%@^zJbW{F_wXO#7zp8nj`i{I;E-LzcUC8%18+RqGkiDb zU)^~V7Msx3GoGDseK+i%j-Ls^gx50hVEx=(fPc9w^lu%J@QNBuaS91nD`p=CAZnOVAQG>pI z9qRjK2eG~N-(L6rnHjhF$7d$*|06T7fc%f6fPV+$zuIu6()&B`_7ZjbXkc5+&W8ir zHOPQv|1V;G92MZ3dhfS$6~gT+UYggyU$xfnmBLBGZ)Wv0Nr5Fi2*eBgm;wuVt(Um} F{tr9k8dLxP diff --git a/build/mobile/robocop/robotium-solo-4.2.jar b/build/mobile/robocop/robotium-solo-4.2.jar new file mode 100644 index 0000000000000000000000000000000000000000..349f7516a0bf0d63a845577032429047073aeb72 GIT binary patch literal 104697 zcmb5U1C%AfvhUqJZQGc(?e1yYwr$(CZS1x+ZQHhO+n8_8z31Nd&VAo{>%3Z3d)L|( zxhkuEJ0kuWnetK~pwK}7*!mM!1^?sZpC3?vzhy*}1!yH?Md{`LX$A?@_ty;j&d$*N z@8#cr57htNOh!OfLR3UanNCLZL1uD7T8fr#4o-@eYI<^}L6KpRdH2YXMsj+TMv7Jt z65_B(H5r|{m&Cm-J4z8nN>RxM0OV@Berp(7!!3va|W` zXZb%ZVE$=gY2e{z;PHPkMEO@k16yN9I}79gO9R~h{|1hBhIY;tF8_O<{_%eQ8vpl3 z`1kA|z5ZvP{_9r%-O|a<+U~z^{GWJM&G7>vL4bhVz=43+{+;FmM$Q(l7S0|j&KA~A zB#d-M)&@>aIVu~9C<2H)APFHRtO;2Z+ahogzqLCHDTpYrZ5`{!A<7M~2KayDxRDbS z7Z)RZ2YrXAL?$DgqagSuo6ML7{FtjquW)Xkk3h+QB<<}lhv zoz4_5kg=jfvB+N7?+kE7VdIikE>t4c@f2!_fN3pjk^-m0Y3-LUJ~o+M@0(3<=p(J$@KzP$lt5NQP-5PVu*(kv>{Myde z4>v2K7L9z<*ps_o!zFaVn%Qf!xR$aJ)0ZY62LiVmbqU$YI}jj%JfmWEwIVOpJ;TsR zl*kcdjZ4MKWWoXMlwWl&{5lR+d&Fa;82D_yYofm;l{JBFm7Rtu%ECjp+|FXQU+QPY zt*`s(f_~n#9E1aItJxaD3)3=Zw;LM*46E51@Vp4jFKW!)qE-CMI zI@)>=?r&NdR6^ZdZ?RgKaA)pO@|m%=oK46s@5@N9J(Tjexr_(w2`kN1G;s?cX%IAV z2fVYL0=r8xLS04@X$@)kH9Ec(Q#6BvjH%1%Q3Vy`M{ zh7nxo**ql&Rk)_AYmw~Al_KvGG1Ne`GG#6OJyvd{`bKm^8&MtE;XEW{qSpB#a1OIt zw*f6w4GVr20Cha@$X?)faZ3B=lsb0dAsvvGNQ(S^ouDeP(Z6;ip1Bu})KBKWxUhlGeTWp57mIzIf?uh!>WON#3#%Rl5YbyWqM7 z7`3Mc?lEHSLFDdHrS2H1v%2Qo=76IqtN1L@R>J5#?_;|&BLN%?%jc%sYo_aEv*Gh(^C5Jm^DaUTc@7;P zZkFLIgT+rb_PAmGQ^bFIcEaQ_jp>!z;#)IwM&iN4qMP8N=d_d_%p9tVCb{QsAq_-X zgnnXjNAkf<@Y{>ehm_yt5rOGNh40JAKXoFL>Rl78OHeQESViL&j_)gJvI`xsa+de? zI0aOlZ})b#0o)$ctt2?zQ|-9jGg@*J8UBar z2ZbqMGjp)n_a%5NH1D>gQ#?s5WHZOkbg6C0Xg6jq_%FxFnQSz}r`kCu`kHA5Qp#9F!EFT+yWIFLku}!5s<6b4@O_;O4?WO%8?V(9 z=UmzDFJEU~cjji&kBt&@f-4nQS8E>u<$h-5*=#4EfSK_AK(zP;_xQ81fI-(J4vYO= z@!$m3i=PjJ8I)O7I4)<|MroLCE)AC%i7AKgJvy4B6re6xg;@{BV?puYJXH8njBIqe zF-C{*JycCJlUT0ZA})Uz!N`+RLLS|Ubak&ixH!9>YP3MNv0UmkDU8en z`j~Cv(xR@M7ItYrU+03h+QfOmytsvY1GY-zUt$Ed+WDpqiMH$#@L+`^%EZb@Z<7+6 zUSG6ZzqWy0zc0ZLSC+Iw$cg}N?cS{P!%Z(56U8=GJ7Gi{OMWmQ>{5Hcbe0c5PIvgL zpEyV($R=7VNi=kWa0A=zpt`=P&Nnbml*jB#pEuPKl*x$|1BH&xWQF{02RiUDT$e|a_FDN9RfBBE2352;j0c{R z-l(`B+mzwYp0iVftDn{hFh>E58=1%#;WEUGLMVohB{_uF&k|{2Qr-+2Z(mVcnYH&*lzdee0EFjI5(pVlRdyJ z-BQkH+S&BWHb??)mfq|)^X}}*2RyLr5T^s!H^rsJFBjN12VdBvl*M;EL^f&SUjDq7 zCqdXd)X%T1YiqP!Eej~vKlcX;rjcR>yccIiSg!ZJe6N>U<8r5&H#@6>JIrh&Ipdj( z6rfs$qc3Sunl0Aq&(Nigl67dYf1Z4NdJ7&TZ6XjqYtU|Mjyb6R5M!~m##%t3J%J_W z4GYSHVBsAq71=?seB|x|+yPFV`4B7~8O467A5e9X&wT1G&!0xpV5c5Oa|kMp?N%kh zvH1G`G`7?eZoYjG!p=JiV_kmB9!3g{h76dBdZ1U-P+dJZnZ`*lj>T+A5INptfrlw| z&*8@!Ys{a0^hWNVdmL|j?;NKr1yp9p4Y`2lJ(VZNP`Rkn(Xy7=(7H=ADspOWj<+D< z;bx*U_#ft(FMdqp_6;R{ZA%mx>VKPG^t-Ivm{^3ZUGEJYKS~0z=PE;4^ez|wUT=QQ zreilCVlow0l4Vt_gXZ>BUQXdkA>bM&rqn@P@<+ZT0SAwqFxQ1sO>Jaq66|*CRP3`O zYaby$e14X}1h;*XY^@ZNJ4`mKZux);*%$W7dMTjeM=E&V&5{R$1R&?C)f?ASxa5C= z2k1|uC?mOSaAADX<%X&6sT7=ZKIIdWW}`MT9JAaqZ`-XVl>poa;_Bi~ zIzqLQZ6K9lA*S3HGqLOFFdfKej8(NFxoar1^Gny zs(rP105roDFfs_#C3D>1;*nzkM43}7#kH9nDHVm!llD@i|XX6^8IgiYb@ZxGB z)sM388sg7vYV>B;iR>?Qv$(yVxVhv!DCA|r8LbIkf$~M2IZ+FXOj6xgR2Km}E8PHT zC6Nj9n5Z8kRfU)_0lvV@WJ^D~CISqRT0}f-D8IPBempM=zPc^YQ_;oL?20G?I(}q> zvLgY$v9}mOTdPsLRGZUQ=HFRtCJpV%6?r6%ofhDzAga-ZR$MBA7An~LfNav37c;Whf3L3lA3$2B2&7ozc7Ti3jO1TE z>iU2C_oL<6(&`UJCe$Jp%AJ&*y#PHS z&Fo?5+i)5aTmN+-qFXiua8kWSVvR|~aFxM*D3ke+f$rSHKfb&W%Xtu~JwVxhNVeaK zv70zNZS3u_l?k;}FT2$0#FgN9MJ~J|6WQD75Jv3gJ*`(rKLjiSh-qU%`RE@G~c9K`XIOg`v za+T5cwobP*Ii=>v;kulxTj(Qx^I>%@p|pbg4JbP6RpH_&YxQGmc+{2lcT0BIz-Q>NIHzF}pgRF=nBmF1+(nMU6ndajSbp&p|-2WFXvt0nc( zIz!#KJ!pEyu24SU1w?>|)Ad9E9{a|GdqjF-wm}&3go5h14}6n-#Z(AM)4kx|8X!CJ zz@D(gQzW>iH%U$0y>&a{Pn`(!!5mm|RU;0>m*;@{xWmele>r7Wc$`>1c2HR)ACtg& zS9YYG8QD&X*Qu6JUV?@X%Cw;%i5)qPm>gaJ|A>na_tm$Gal@j_zT09r#Md16a)`Ss zH0=&scEqsR1;M{wp?ct0ktd7R8$19hMwqcCi#D*&QzT45g0fG_x~0=|z8QZ}YycHe zVUgka%MPBRM*ikNgx$=xyMig|7uI8+CSLluGP!Ls^`J?b34wUGE`_@`>Sb6L4dfBv zh{6%}PJzNbn&r9}{JIdGR~GNo?g)i{LSlUa#5r9~0U@u%w>xk87E#0_-SCq@!#kAh zl~D3t9~U2oqCA|W z+$XV0CZgg!HvlL(hZk$GM2K0ky*GO2@agAyjjPwB$|M$eefawZ3TsRFWI*WW%5_NN zi`(l#=d(jCgMyeF3y=Vvf4G)dQp^m=dV<*Q zepw*s6?nbs+-@XE9{a??<`#*aVt?f_EhD9%M=9UDsC2#?c+ClMx8?9gbTk!Jz@|+8 z+?36zW2%*Y72<@?`U7d2-qZH_%=QOL$Bq5Q@t{qauD$>R`r7q+UeT=Odp!+F-8xpUq-N$u%TFF(>r446u0CW#gGnX1zv6$nd8D2ATzAb#e}A9E z@d0!D?~s5pXh&3Yj8BCJ8*$JXpc-}FCI_Q%Q0}1)d+b@@Qz5U(*fWpGB*&=OmXHkE zXX3~VvUKDnAc_eF!Uq{mhI3H&h3!E>Sei_k2dsYOCRY$K3ibr2Sqc%xA*hb#n;zU1y zPZr)!*C|NFm0$4joL795a1r@-QrXB|$~;JJAhKkAe}bZDp~R5SKh&_JiB;|G{-aVE zGm!O5;>)t1ff*zejdA{mHn1+06e0;_%Y3OE){jG89W|L>RgyT^6xeNgb7$HaSunA| z%GgYb$3^RvciXB{d52fgD#L7#6XqiFqL4O3xoLMlbW!gTqthG|hN<0E2CbNMM@W(E zM%_{D>W4O%w);r2e%&#!L$sb5r@5JQhP{Y*6C4P6lN=a%69Kw0m9g?1CufYchtZJo zCSHH&jlV+cEilqovtjM*Y5`wd8`2(7b))QRwX1w6X>yMfiKY=;$*mH885a({K|8;i zc*p%T{tUO;{D`=&@*^@TAB$n~6%C8lyQPNGANx%RX!h5)H_WUd!&^lTi8+iWZCPP} zF`Sh@d~8bOx9(wgC}ze~N|Rd4o8iFl-EH9F;jvn+Sx%8K~dBB6mVoIQ56x)5LQje;5sso zGgk2n|7W&>i;Hd=Yj;%lTcF~gMe7DjinOql=AojRaV98ld5+pumTcxhL0M;>4~)bZ z9#Y8$)3Hc}tA)s;stTSgIv&JG28@-LJB(ax1#&6 zN)T>94boW`pn@UNdi=+}8YE_eXoZKU!$N(s@;txJ+c9d3v+WxOz!W)5?BWFPx>!3fS?K!k`(0c}3{rN_-%oP#} z%F5(qL4So6EO1R16^qD6TAb5MtLBi+Vu=*O96-Y66Zm5+yH}*Mngm*l(xiM&7p`ne z?pbb(AT*8fE0^ANb1&Dc%}@vR0`X}xnKF^^`wbIML9qdJRJC)qi}uA4Ki*)sQ~Ne8(hIX-@hgwTe4w$C14;R?jJxv%>PdE z5%eGt`o|oOtbvWmeSY-=f=Qvr?i9QKdnuC=#UZ!ZY@Kph-1OEgsZmf5|~ajORG z=UnQq$q}cL`|d{)kXCCpJZ+F)=1UUK+>CjHRwm({;6k9g;-V@Ta=fRJ4}AZ8g$*&C z7{agKD0*5Dbfh1L9j8sERE2zk#BtuZQmcF3gNY`es;8_`ptqO$avSU#fzBV!hJ#Sy zH*2FRY>15sAzQ(uXwEa>raO{se+8Iia~cpD&Dwix5>03)p5?14eE;}YMnRe0ry745 z3H)Wm`tLGwa#Av}HZgLx`=?AuQJ9b%;78?2;!P}>dpEDV2Gwaq!);g9Zj?ui%#wUw za4u7thdsjDF8syeFE`Gc1lPgIp@P}ww+A3oor_O2d3Gf+!&&BG}Kv!IhOhX zeUbSz-72Bb>OE;~nCmG0aWRLoz%wYJH)Sv?UL*5HU;GxGP(wXA5+R$iA07#lBTSvB zMtY`>>nPpSf+>3@^_Y6);rZ)v1#{!8oCrU#o_&x+65%_9dh|+^KW!%d~ zxKzio#nx9k)9`(j0F2e;(K>tN#tL>#ejVXF^Ae|H0pr6AUS|%&4*G^G0#GL4-*Rf9 zL43{(sG2qyACJc(?;xJ3lQB#|jwt9u(D}dyL9QJS(94{j0e8tx){z&BFq?{h@EmRw zNEfy1_5k3A8YScAHu_HGV@|NiTr&*#YK}*pukjNcF#U?dfW6*Ik-pe8EYhCU914x~D9VE( zd;|FAnE=74)}WtF zsyIc5WvQk(cA1%f^~dKr6!w{4EHIxlQF8M*Dnk7Fl>}W>R?Y+WUKqQRYJIIsddyDT zcUzt^0oE|LB+&BPyaJ;y8$+%WvNaN!wvb>BC1=bVsfcS?poarXlttNx?05VKCsgz2 zwVzRkQ4YD11943G0{t}HNKg<6g32PM>h2y8zMrOrW$(Uu&x&}Od z#+SwoRma_>`Xz@8_M|t7rHIGI^Vt>t0RJnKi?3=FnZHaZ{xYHaH<|pe@D?NgPsjO> z@HVHq1=TK2%+dNEjw8vQa#?Cqrj&>^Dl`^W2ID6vfTaBj?3?VKgwEa`-<#uQJAL5D z*R#zBlx?^Z8leh;)=2A2bIFu0DGWUDY)@zliV%|d;D9Z~%4bxTBSpFZ6WaXo;kH8V zpf@AFi7SZ~{o5RQP|XlI)zyY;X-M%7XDh-ZOPh6wju{&Cl5S^T`=lSlkJ(d1~!k?SALE&L0bTyPK#P_3@dqFs)< zx)VSocF@NTN9cf`JQkJh$_Q}Ia*@&kSS02->^bdXIU6J#B+lddHcqzuivd-T4>Bivlcv2c>nI}C%uJ5Jg(QSRBLuznJjKBn%OBfN1 zlqy|U>^u9vf+229+E@4shUG69#(xuxvVqzEV)H*z&(i_fY5vdCeT}>=c#=~wK zq0K~N!k?1gDS<@c&%1L!NoD6xMG(gOFFV)RZ>FX{MjnuRvEZdo%@^eb7kX;~c)*F# zuf<>C{}axO@b0|>?szYcS()}I|8N@Y)bh+p^AzA^DLeB*2#cd|Fpq0bSh`DFb}HB` zO5U`U;{2{Dder&e#8L+=0OgqnNd%rJ8`f<61SVlSGC4{gpNjJ&KeIxej5jX1)SaG( zuHB-u;$pD*7Fp4+-z}6ui^#Upgh*9_J4JOH~|4DJye@qB4MnxslJ=)lv;+r z!0j%?tAgPSnfsg&=IQl$d5z`!#m50kFPbdXXrZnsJRF7$h8V00v97cjHF2^5$0^S} zIlid2%s_WUai%Uas$EgyacchFpD$ZDtb05jB-o~0<$d0q7-8<+LUDCYp5wXrk@3(4`F6)_@D+*fG zOlamq1<3-Jo~NDjly2FB`cp}(%jT1`)PugE`mi67u;0zDux48FSdP9{;Y#iHxpcA^ zb!^I<${iF6G$`lDt`us4ZgsncU}hN(RH$wi=WL8Hx8na`JxtDH)2wm)t#?+VEf=_;~+*1+@?U7uD9;fj*XO(BMb;;h|?j5G*I}-_I zWHT*h`Q_=v^<7rf&&Xd*%<{>Z3GuZf4)m@#T9W*b6IMJJnw2hLBAb|KD|SK;^<9J$ z#{FQieG#)9t`&BrW}@qNC^}3Rvn)f-n0BxFG4yLqpj&Eg9EI;rI6l$3`s^EH8^4SN z`;Di(x?0w?j1!*bl7pgPaF_0Cq^<`vEq~UT=W@>($3WVIUROpjx+_iOS5 zhf}}cFu=auHlaAx*yB_s+3&yChyCYrj)oW=bhE!`F#nczDF40S_D?X$8@3Dlh@pR6 zvN;?C5%P~&1{t%Cl8Ah+`28Y4D_ z2QVLo-%p;$S~ERXf8IVG*!^ufl@*3jz&5BzE-6-32w{9Gh{zu^B0FbKsFd^Rm6L<7 z%hUU0@jsy9QE{0lN<01fA;5*o4K_lxT3S!A@PoW9wf{<9eZy?RxMKB}&Qt>|ogD|P z-#2^?f1(8}A2A)pN^IV1F_|=rWx!lY#lRY57T9D%gJSn`?_))nk4hGfRI@rtS`o-i z{!A8ytYqn!0rDQ^FnH(Nww&-9N;_mn?xyzmUvMYp;=~@06D44-t)`s5GcM3uK0GJf zWIFuRC7>w&=t*8_M{iKNmS)ko@5y5tLC~SLqZmcy2h}VFz|EY+eBm|U+?1&h(@w4WAh~V49ZI+;a#WXlCl4u(9DcA+8L<;YY3(O4-tcgrO4-~?oPyb_9ke?I^0L{+`?~VtoEZA#` z3?Kno+4pxt>NSNdBLg-C)n|i$#ROIc0U|cDBm|)621$F+>8|HdO$C$l_p2hhtn2Oq zL4ReRIOO3=k>u|}#eYj9 z37MN1S^ZZHGDk&54aWr4R~I>*NjfWeWtGc;Z2QWgC;<7y;&H;9FZX~QE zEG3SOGx==-=f>(yG}~;UrR9{Wr{2IFFp&|cC0m>IOY2y6-8nMX3S%KR%gv`lQ&w#= zF-v#*ArIAjjmbt&luQrTL#=HbK)F%>Wf71vII)L^L)=D#nBx+a%1>kTYuT_VyQMQb zgMMy4*8#@VV(roT?H7ya7i$MmyeH$}Wu}UI(Ruh<%7w~~TTZVs>Zzph@{|m-4pYw3 zqxD#oGTBKI^$+suE4a#CEfEtG4xe5bz?y61agD@D)Yhe*=!#Q`&SA)z1O`2L*t6p-2+?ORoy4p`Wc;56Keb(Z=vB^{AaAZ*KEp77;k zy~N3|$$d~VxNaw4`(816g90?1=RY-NQ38E#5L-;oU!6O&f1fxf&N(idW+i%c5OrCZkov1b%SZub3Aj^d~-6+z> zpVfLFQR*RZ^fktqD>dI1nJ`)>f-V&q(yf`mt38S}LaeQLae&<;a?;&jgQN|@Jf_UY zBuBHP68?hEG~}aD5ECWt5%?f$k3t#L#r;4T#>DcDJ3c)a#g7AQOElkL-<4)u@eEO- z8CN)9S2nQNoJ`*E_(EbkIoH^BX^B z{P`a#-LN1v6&D={sN=8P`uBpQwZ;Dmk|`Qc-pWf$eB=$C8EFu~5AnrO`A%c>Rq}_O)C`^VpXf^CiM(k)j)s7)L>7v#;Ei66<}0&{>>SB;W4gKBBu@s5>U(k^tU9=7WArdzS_ z&Xvxob?AzHX@aK%9O2u}zWuOWbk7;a@O1B*mgy8YiE7n2LARwnWZR}d)~>oE<*F`q zyWMp~a2vfL>mAPuu_~QTyGKW`Tk^o^nHWeLyYJxfZVRiO65qs@0f9(;@)rbIwEUmWS+?%Wvg;^ro?Q-kJJ zgF2~X^+iZp-gMnN!h6DCddqAHa}B8|$XB;h@uEVCcv@zXu?inaESINg;zY$`xx+t~ z6>$|&6v|ReFi*5FadPYIvGg)GcQY@eLWLpUPq0@Z+D4NT0sp8>yfg2t;B|vgN576t z?^wwwzvgA`Q}!?f&l)+c-@*#umo}Ng+Mn&^S3x;O4*D{sL6a2OXN+%4GNqw`p!szN zd=-hB)o8rP0%5FX58Xkd$!XxKxh9(xkhn3r|0QvV$= zqsP^28w*PtOFLWZ&Cx*__(54r?5c=CqH?a|=ldkq)3G(X@nMb{k5b!gN}NLyX?w?T z`VH7ToA59sZsts4#s-(Vo(XB^;P!%&LG8|8s9U&_!iQVA&L!_eW0Ym4X1SVoR1wOZul4V3wbD66I~`ahbjHWzH*SM&FwM%+fYh`tDp;Or5dF#Mah zbu1^HC6{rLJ5^{M*48Pk_P-;|SzT}XdR$)FLFr}SUEQ+AjA!&&A~ULYQy7$>swR~S z*hY-HjP~0JZIcA4il=i_c)$4_2w@~VOsJ+CCRxaLYN{h^*&`oNwWYzl2t@jt$tIyS z%t*4&jpj`{x1%4Q1$NdrnOxJo6rbvEhd~<^67iDAmY{Hv&IDj&i0uvZ83))Tqp)zS zB{ROHi#=Q?j=i;8#skGTY*o2F8pf|;gT1DdRl>SJr(lSpG9+p6gX}w~aMK`*_f-{f zE|HF5IncC=ABVY1BN=W`FUfpR#4elgnm^xASh>)!<1N z@9!Q^V0enP6cuN1zOx7mNsMvl2FMe!vgjMGwb0IZ3b5Dx`a9QQ@GLxat(;OJ5YcC= zl_y`&!b!vm;7F6wT5+9)#tG!qE+~Ia%;`$*S;%3b-LnwqnpIhZUgYB^@))cc9 za^!r%dcSH($}Ynz!Mo!sb?OI&+6)#?Q0=MI=(EOqBW`BD(TdG{NQT&u_bDlB4P##F zsKUZR)p;}Ch&tucPV)k#RhaE(aXXr1>|}SHo{~aSN4VI8HNynG+j%2a<@DNd9zz;G z*2rl!+h%5 z-Uq-rBa5kJeAWD0Lb!nI4zOE%B@24FuN%H$eKqxj=lEGFH~Z=XzSG|lC>eov3P1Ft z-koaJ1Uw!LyufrEmVWm23*65i-tto*$nIbxi78H43#| zumOUVazdJtwu;yIHtdZU+)w${8y2BG?Ha`tvrB+)_VoaKr?1886DsKD&MPa0Vm$imz{pwDd%27AZmmPe46S_uCqLkbIe%J2)e_s^ZUN4|(I7T?}o zh&TT}ga~hhhw$M%mRF?jz!1@h!jXLBGf~6R7Zo7 zl|`l%QGIgv0?vpig7jjz#mdrX&z)D``;AXc(*S&@TN$CAeQm4>TV6adlHr0tFoyxL-_9>@gvOs!C$O zR)Vq~ziPL^E&H1mxL=mu!fSZn&fX2tpJmWg%g^?{or4v?=RE)Db7StSJ`JqdYj@^P zBlA0ud#RL4Q%Y9ff!&|s#eNiVAFnb+PyQ8&rc8)8P!tGKR1QlSd`zz+pD00o<9y7o zC!a9R;ZpS`XP7hNz3;Ph3)n_ceLaVI5kx(vncIx9S=lc*##~YyoDwqKLp`jgHt$Zu zECwultyfo|WH?P6KgERoNtL*!n@6v!4dnhOL!d759UDd&R;} zhpKU?Vf`fKjjjNvnJ%lbCmkA>GtZKS8wVT(sMC&feqrtj$!9F!(ruf8lLUhv^yYTXEx?4o83mzCcq zoA;kMnVG_%a5j=w;_YLkZ#8!wwvEgqC7JPTo?t3wBdIYlqqjtNt9Wvn2Szu86SCe| z+oU@t8=j!sCEAW3-0{hHX%L%Krq{NLKRr5z@FpI#D;^AWlLI6*YB;x}pfS+FM+}o7 zXb-~^z16kmb|Q3%Vv`v=yaoH4(d|7QaxG4Y%7{RmLy9!rheJh`XiUjaD;&ij4^KKc z8h{}te{FMd+g7Prv4bfySJ6==dDF;a4aV+l;&`8++TFJH=N+1Cz$qt~0Y=?NFjo`; zY=@w{J&3vvEjlo0>1IwI7f9g54n_6BCSK#GzGwP>Q~KG1MIG|9BqF<7g|P`#3ky+L z$hKC>QE^RcvVcX?PF?;vzAf5cHhpX%2mbX*Q#!1}_3Z+)aQ?~Zb>YzP9HA9BnZppI z+J6~$({JOZMuH_kZc2U=xjCRxFtlFu=EYVt>KmYu7XBh6RT(`)muDUK3l)B4Vx(ZQ z6i;LhF;3EZ^o2b|#AeuBZlptQTF0b7>sUevW$U*A)sBs9xC@!^h0z|2OoxJQB!HKV z@#N#1CU<8RA_9AMUg}qhN3Go28|Mz)k*fyE(VIUH)@BG#0>z~HjgFHxkgUEP^sH zhUb6`HuY-dXfx(*O@JUy?>b~19k_bhtm15rKn~EUqNbRZIgicIcn4!g3>!!d^(oVN z$wWCs;T38Da3@qekG~JIOd-NtSUKXR<{9y$f<0eI=BW{;#cpRPudEx;Epu5UZ$JW_ zy>b4IgxfqX*q7{jTmpwd_H{uAa931;Gs5Or#FN(9)VeRV>F=zOEcq5`NU3S`2AV?Vy#}lXYY25=#xk5RJ~*J^90r-daYUhs-IU6` z1hamOnNYpuUKDzNdfo6BxZ5E%_XD!m9aZ;Tcwt>={VRdRt?=*R*yh5c(KgmXpy>_c5Ft9~clri~kCW%#uA(9)sy>E%yZa^21IA?6#|bmL~W4G^K! z7=ngT4w(n?v_7ru7no43pFns4+i-dyneEgV)-**BH!wkySkpO&KvDWI2 zicVAVfpB!vLB11os5?A`-r#CNoktqx42@(<4QWNM*zz44;Eo3E1ER5;1s%x@m==Vj ztT_e%0&Ufc7n^CgZTy+acP&5w0~`rwP@eOuci@-k??bMyyJFPsBr;L}<)|AL1!%e> zRa*nKCAaTPgYuYt5H^+yW0!azcI~T6lN2sC?=@PB9;H%o4a8Xdn&Jy^ zzu?8_T$(Db=wh|_LWKiI3V}R`MmF0(g>Vmqtlhw{AK>g!tm+F&`433@AFv}mgOQ%T zWxuePKLPKzawNHa`Kwmjx%Q)we0ZsdvC|9ph(|piyb> z^08u+aB1L~8k2c5o&yh$(a`Ahrw9gNAc{W2@TnP)fxlGhl6QT2pi>{>;q!*z;X3%F zX4bwN`eeBi%Xku>78*V2_&K_q1fln_SdyX~731ltlMsHxQuDpycEwi= z-sL!iPg~PE`o&gQW!H%^<}AT$;TARA9sKs)T#hsSa*sUAenvCw%EV5yuBvwU*ouvG z?b(3Z(FoE@yV17VZ6;^=SUIS)dg=JQX32RW%GqHO6s@f7ZFxpyb*AH!=H-|Hv#@lg z@k?FiEK`!MDWu!{F^ea8hHs3zzjnCCS@fVyweN9z%#=CvU;&jUIl;+a`tYM-FGP7J zsw@IyK~z^T>y@QFI!zHFO(|L-k3(F|39KuP`V3uHw&foB9kRCQmpdBIWGOX2eLzB# z{17j~iOZ~Y>mWwFbhbItdAz)CC>DFcuMcG8NSxmu@ygv*fxd%m0T4rfRNf=!_iT$Y zYy0^1T7*{iKVoQh>`dQ$VZ1ZCWop;RoD!s5Y(G@Qr-d?w&wJ#hpP=EUobUk;xrI+! zx%nj?7VEnm6f#o;G@$Xc7M3zfIAq>9cfFHCOrikx(sG?Z@8Id?mv=7NR=b7OZosPV zLml_8uo1MMDQ&H>rnhg({ZEG{P5#|Th_$6Yo5@o(^5hq#A7_w0Vnfru$)N^ELmy`@ zOA=GPu{U!sD&$Y#U%jD+M*gb5*O0&@GL&N#Q;6x%#JHoO&)jCHL;Pm2^2sNF<}8{s zO@7RwOO->3ciPbe;1yJ}X6m7E%s0}?+?+pJ9VD%{wMk5=#RK2{hCOjRAcVU;vS=5a z+Q)RbODN1c!KM|$ACEubrK?NWVFlY>`Xy_IBJZp1(?Dwu(6fLd0EiE%qex| z%y$Oq9;i3Vtw(JHrPS=7c2qex!QsCMp&~>5A=bE!15~L;T!=T1|5PxwFPpola7&!~ zqH;hJI{6vYpyly9AP0RXuMG5A=^cwBJR;MfIlECV!@Nz%x=4C)DRNS`jOhbXhZvx? z8vko3Pj#{Nvxa8;?|ywpK|fP)IUV&|Mk`;tZEYoIEfM1^ByrLs+}j&%YQHi;swN-0 zJ9hcuX%vNhKBrTSumc~v8saws)tB1FXgdRn(kPdTSh|4g&oA7>2JEjNm=kzUrkfF6(dcJ zqdm6F;TAI-aCx(%tlSj4_N`uH8q4Yk(B-zCkyD#wwTn%s{Cf8Yc8(Q7nffKtd`NsS7LUK>7s8-1pUr#UYso+#alod`A|^hy|J-bN5#2DL;1 z)S!7mtf!Mh_DTtC&iC{kt;pH9rBmOpI!mQ3Up(FakF$4*vgF&geyb{NuC#62wr$%s zDznn8v~Am}v?^`eTxsXceb4^RIp2Qz-`iTm!+Kh6wum-jjM-=Zb*vN}0=~$OZauY# zG)@UzCe~|_#c$=@JK_q(c%po7EH^vG6sobxKXY=Ee11>vmy{-pm&MJE#7#}B@re-n zp^=_&z7X)s@y^B_vc^R^*;KJuFwBCM0UP*hZ6lI8Rvf84F5zr7PhxD zv2?MtxBD*znKzmnK2QKv^hy|%Kim=1YG;5oby;hAg*P>h=f^EF28+!^A6P2|G0W!e zJ`4Hdt#8-&%vzbaVhzN_SyPv|f6+3_8N~VjoKHWmMpb5>cB!bge0Dr0jMI$2s zK^_m*d#zk!&Z=7QWynRV;u$^YVm>w9*RtC4AmTS7BvP>=4<1oA>}?!UJpTW!GmepJ zJA{4dj6q)v7^Z)+G!aWf8+-Hr7a#Ipi%U|KR>x6A{Ggi?7M}awN1Y}DA}MkNCai!G zkUFAF05Tx(N5E*7**TbudCsI5!sKMN3frmv-XtOVXyn*&XC@lPKg`-c;AO+J5#`Uf zP+?csjq-MVRo{i%;Vu5pAKO^jn8yPW#9R)_;ju}rMFY0Kc2PhIFqBtY1E6HEQu|84 zix~?BDg(H~&Qh7DqdY-iq+E8ZXZe^N5F)vfUDnY#j7fF9*WBE%I^4ME84%^U(w2*x zI*c!dDs8Bamdi9IB{`~fM+R=>R>Pwg#iAftY}cI3rP@c~(ol~1`Fd~sKVX+`Eh$@6 zES{dG2kYtkv5w3R&C&J}65PQCU|}%b>phpo+Q-$}34CpKas}RHxve`|K)a!`o2%!N z9G&*_OuyT%OG*YLw`L{X2FnN?CRd82CpWhyG|rBzO{!f13J&d-pHW!d`kH4ay>{WZe-1rrCA^w@x!#1<2Ap}O{TydsOu{f zU6XF$22ca3Fb02N3~!IstQWzh#ZhxwSMXGYP)&fg^Z4U=$(F3OLc&rt5iJB_LF+ErQVeik>`rXBazhqqiehtp*; zJK}vuL3fxDK^4TMCgU3hLGe9asC9L3iSubeb=aB51{W;cv#- ziaS`HQsTa?SzbwOU?xnElgk1wRvTDcNVHROJetH?@VEykTvHrP$3acvF~vKU4^h3- zfeYIcI5O+%8(R-6+HOP0@lk7(`)Bn&^`^y^;@aMwqH&<}{A}`J$YPyMnCWhE5(gnY9x6iiCbO6w5ww!zFMEpP^TIXtw zZFexi?{;v(*J`!L|G1KNR8K-UrSv}D0{exjm74d9{Cj6VKY`9a zpdB=eNz4L-fl)#L|2hys^9C-6LFLCH$bBR#@TaH;^5Fs58d6^Iwg@i=H-MunG~m4J zyF?qea^l?EO3s1GW$g=RHtqb+<9mTSHGz3=g46lO${)M*-DN&dn}@dm!+|o3)1I(m zqQ9Js`0u!IGenbrAKya`c^mKEBMuE|1wxabM{3b1^Iezmr(YsCUUAI+)FkpYih53~ ziM+Z`H>FHlQ5}n;9DuMGCEaQniz2LSit~8O_{c9Cz%0cXDU;gWHk6mAo4rDWv51uw z=akMbjqogS!1u~Dc;pC|8FyR4A97LS8eOoLTK;tg;49wFIhO{RJn8@6bqxm9pe-2e z+c$mKZ{KMDNnH~+b@^`#SCZPRGKxCt2b-pZhFV-G#Shy?mH2Coszo&cnrW#5RD2N? zD}3qtKfxv`c5DVO_4KbFFfYcRKe&|(<|glk-HQEHO13uOz7rD2nO$b{K4v?2U-4WX zZhd|{!Thm&E8M{#!=4UkIf#!RH-%GYDB8i5kv_2kU1AYoEZgC-ldvRzZhz=S^-76Mz3<*SWEBT`$ME4d6dMSDoQ#>~634BcKL z!+pj@WSv@3A$EFlVF(8CH;Q~QNWJ|eTt~3CtSl;lJ$YibU6YATM%R23D8guunwe=F zW!sb+`QobVkz7Flv{}>sP_$$rve}8Iq8NM>dFpg{fFoqA5Xf?)u>n~Ti~v;K^_{Dy;3g6u=l+L|zhHW+mT?d|Acm$1`5!h|li+J2P2iXmjy*(;CChA=r)e^xS6MPo zfi6n3Q|`{2W#(tpEo;rQf!lIX?45DMkm6#WsS%BwjPx(=7$lV~ z$GCS=IBAYYZxiFvL38n-hO;%(brz)#Fr%KCYCjH%5Snr8+4NGbuIzCwDufy64)Z1w zJ!uS+Kd}T(x%kAqa&`Z40M$SJ@^Xn^N5??S0$ZNw0cm6 zE97j%eWU}M;cT^OdF>0p^m>>A_DDI^E`YjXZUqK{H7=LHJmX);+Ak+iS5f2-sX*cm z8%hod@}*|IZ(IQO%0T`%nSLOapKgVLO6;`vV>Uz}oup|SAzBbl%q?p~BfczAFve#e z&K`aVgVsKrNSUaf&_}`}VvZ|;MdtPk@|F{%;6VfJGlo?C6_U{Chd3lT1fJk~^b4X_ zYx5j*qmt#4K*z87=3Uc|pC$&e3CCbQl0&LKl49`B@lm+NY%!p$OgA`N{XSNsTX}Bx zNs5ot!?b$~uMZ`@pLN?R3q3<&z8~Eoez4PP1g2g2l6|=@W8!|Rv5!)unLwF5J&;8EC5#&lMd|r(lxs{?~P7JtetZ5zxD!Zsl2LbtoE=2r?pgVCHB~v>SQzvyN zLkEZdJ{PC{>W(rD_)x1!T8gZL>w_fOCF2RAK~&g9mXHYiUN9hFrHqmbS6S55D7NXU zMr|{j{2O(aCzsN8mQ8jw&{5`gx6#rz_u}M){=LXw<%GQ;$-x6d`Rx2})(ZFI{f4*u zTh8alMb0<2z4j1R468n?{Xqr9Uz8z+aH5HzrchQQ3goJZtQHv2eP|5@Ml$^s4y=v2 zL>!%Fm7=P!B?AoAj`l*ZB?TU`g9u=cu>;q}aOT(TAq^hFu=Z9@P?KPe*pQot%R#pu z(*5#4H|EV=PQX>Uhx{NInBr0+OtE!4$t!kYc7yHQ1toS;gr;I`^;9iPwK1T6GSw1& zd}Xscpq$%ge?o8^M_-q}MOe^doyvn0OiE6$&_ru6zJ$OfLI+xHf?5=Z4qGofbm=Y{ zqa?~^p-d4=GZ|{-9${+8tc$w`w)e3=MK_jwLW8!+QMZzj$6t;@i z(mitzeQ|UqE2i{L?3ZU)3JF(3x7^rzKB;F}jz_`4Aqi?=pSJ9yD5XL}kOdQEVLj%y@IV zY(A8kDE|x)$**G1SVsvM9p z{zdGDaN`Z$Y_mIEHFM|Ve^tG=_EeI4 zD|lh-x_3Jb{05(%l7ip+a-$jYbBI@D+Xs%iX}UR7ZgXr=V24&#RKSIH69Ob(ebn<; z=9;K`!87^H1dv-tS3Hd0!2Sh1(ZvEhz-0+G@Z>M7&&zBIa%DvgLu=Fd&YzlPqQlM}+3OLjQfzB{9-dPVEdWzZL$#-}zmiBclDp zWOQQiyKt=J1l;JgW(GJUwj@ilM$fQIL}76Hn}Ie*l!rMIunsq6WXdH`c*PM{eDdep zu&_n{W7xc5<-j=06~*2=2<$G$Fbc+Q4c<5@hlGk(5%F_KhUb=S@Xp9Hoo!Mb7!gy? zrPxS*Ke1A|-rkKVCG37=cTmTtx zr-!M6Q{!NPt#neW7fMCo#*BfxG7T1t z?5;(vcBJK~*m$ZlZ^2U{L zNwe$mi=%Uti)$*ZXTqaL_->O_>58!!-2obX@Y4uq>Q>JYO5O7okukk6Q}`SbBGqeR zUk+&)*4VyINuQ`GjC}1{SBZB1ndn8*@*D&Fmbm}24zA|fM{M!Yg?M)EZ+g^#efo-$ z^p&NVq8QmNi!)_^;Pf?A3`0rZ-8KjgF(3~g9q4O@UPH3)8;l7c#joMy(@SYX^N=M~ zBeQlOjeivUazi4a;<&cj?SxaD{zNJ!My?qk@dDEe7ym;|xg+&A_)HDA+8QW9^lZ>b z$1J5TAzMFR!_=)D^~y5y5@q2#N#Q3*-(#}hWAwLXkM>f3`xODmD*tW@uceJ;QDvQ* zWRttFDsTpdUuEaCIPDctS5?4D${1J(?%P;QBKBRf>-_7tHOBxm{;Ne3+w`eLu4_?% z+RrS(CtCyFBfz?TB#}}anObp(zS5MZ*>2O(?kC9qJt{UJ+XyCqjf!Od^r*dplj*;R zAOGI|Qj@hoHO25Vb1xQ7DVx@>q}5P4c9Z@BN;Cx%HU5No54dawlpeddTa=tn+L)PB zvc3(3rH%;7w*F4VV5k!pHlk(}s}bAljU>0n>r72`AkCk8oUmJy5K8Iy+v2|J?3sFP zxSi{_?}4}`I)}u%)?z)Kp^o8mJVzP!bG#GxzzN%S#fjQR1Si56*ny1ME{$PlBS7k9 z#6hnKb%7OU2%LeG+b)b@#FYf|;<7H8(#{TCR#=@FJo+2#=}c(Hg*ny4>^PO>=G&1P ziN0QmjSp$^idx#Nd=0R{rGiO+_TdrCR{yIRWB<~8rXWLaLQAcmcW*)<-Bj*5_YkZ$ z{GyehlqiMG+??iWKIF@-tuWoyeYjoTdEGYUX49kJJ2f*F;9>KUWUk|wET6103<|@# zZAJr@5n?lpMR{0EOK&P?K3azDG-u}4cV`3CF)IJ4)GaO5Am^!2_}#j+55{T3IT&Pr zU_qRY7{j_Ys(}umfSR2N+NWgmPqxV5ybZ*hN}rVBu`G(rzM#kHPHnz9Xs$EIS!!US zp_-cn$Z2e*a@P=?hcml`kg-eGjCNjdB%^b%K^K+$acokcor!DIcJWzD!<=FcoHHTW z$WLjGSthbBNR(*_8~f8BfoUO<5J2m(D!`o0I31`4qFp!fM{d9+3OiLmYPc|feWrRZ zF<_3Pz*&aAY$ zHxEipTuTs44X#Pd)ZWTKi=qW0n~H#FxhYM{Ne2!psfO-o6VF6e&Uu*|#)+ETW&_T& zy~Vy#Z(#RE2{?{jKhvDVZq0(iPQS`H80Ox%nV@RgJ`y2ooTGlqEn!t2l^%va42jZu{t%xa*Z~chZm*| z7oc&IO%Hv>f`80dl%nX$m&>tqcdoqNn7xi?p#0Ge?jy9^Ys->nM-l>DH7~O(7-dOA z4!Y42;+$y(Vp*%DSrYAA-?-m6+7`wl}fMj?C zF#S#plZ{IZqa&e2($`QT5>izn5{r)Kwqy;v{$?7~iDzA=71E6*AyWT1s~YRFiW*kM zv4E)p5e;cv_eY~N&W=Su@$QO<_*Ab+vFhbVlWw$?bpaQ*m#iw<=R5ZU>%6JWHei#d zIm!xI^%3#e027;>w1Lk6e1M4Uq1=^q$J?X4Ncy7t7p|dU^8tK1h;T-s1&V0VGe5ec zBIKr+ymX4#^Tv%Y$W}r}_NiZ{+#x>F7WODENdARs$njU? z16j)X5l1k6n@JCmFM{$@K;(n?zg&u`J^cgt>uLUR-BU?V0yLt_^@T?oCRy(rqeA6( z%E7wFM6Sv2$k%pN3Oz}bGiJxhPBboUxDsF&1f?8hh+Ch(Hr_;F5?+Y)+xYoC@(l_YGx4a;{rA(K-VBoBSGQ65Z=c_I8 ztJD*~UJgFNlsKU;V8;ozDP?Z51A{d;J!!UQrFz9U`~>1a`~t9G<~>scbcnvCq^$$a zdsWdcc+oC=lYv-Ox+Pr*mKVgU9RZx(<9o(denKbmq}R$g7n8_QhG_J;EMv)KdUAT- z-jY;XPs(_F)lby>WKT_@+|e`k09H_~-utLM|2aG|X>cBwe2E;6U-o26W!|+WGT%6% z$zUdoA!(2*l;DEG!vjepy$uz&)T+W?Bd=8jsUj$-FO|rG>L8*@GAyfEo~-0}*5rVl zwTULLVCdt|N&%|@mG-KncC*cynPMi5{c%w*Bh)C^!m5-#RR=#shvgv6al&eW!OmjacX%&CjhwCW-+%KwvarI%-a<|; zPSADG8A)80o>uIh8c{Z(vbPeaUF%afF7^W3Pe~>Z$bv@p652ZMPfAV&+CQLTkbT-I z^O*JgWe{l@*9@X9HyIl9jn*3?lV~SsruY<_F6!;lqMW+|GRm!rl&X{+#2Kk#NGiqp zY=~br1)^T>0re+a6e_KyNk=-tbi*j-7O1=A<||n5FV>xCRW_m<4n9_AXo~9Vv*Noo zu&cGMM4A;w6|0$ai7C8)3i=d>RPV-)`_rTB?nYXpsF^N}goaT0V0U0JW3Npi^+%tu zV#}t_ToZwCiyAX$g^4rabeLO#1UCw%r~)os=C=gKx_>C8FkXB5B*L=4x)VvAMvFDd zgB6`}rTk~Hf^55iYweopUzk!@AR9J_rNE=v<_YTZOj_zwcTR0ZR&@`A#X*z{7av#g z6NUnyodLC{ro77tu*zMGycw~mBKC6A9Vq@Is)ypw@RT%bHIN*2&!6U7jsiMKh&`Xq zZvTVR;yD8W79e`~k?iFzFK3Uno41(v4`;Fru8qMqI!=Eg_r$J5FU9#;;5xJZOWX<=#$l`(AMCzmC3zICpGEPsN>1fKt;*huw zb5|r*u0JLT!ZbgOjxtFk9~D?7x!pzb1VCtzkjc4wxo8XjU4QOyZ;Pb*FF58;;rAO z5Z9=^)|2iu5k1!_uXhSXu*Zu{+Ik{0C>jwThiN1OqZhX@m9rE) z2SVWhKeKi*HpB@MxVC37LP{MwhGpoLzhUFJs@YCk)l1X7*fbz?*SN_B-jeV+d@JGk z!`O$saQjGhDTJ_yueStSs7FA7E0LBMSwZZqRkH)q9s)%w<~iU~M72zzE)X2xwoEN= zu~G0&$?H!-%&*v3a`%yzGeR%(Vy)UbS?-{29fV!V#IyY!zF|W=bMbM9ICRb1200J0 z29a$5vG6}FQZ3qc0UKYY^q8-Zh<{{}`giI3cXO+>W&ITl@xj)%AI~hiW?^$W)li(S zms>Ig5R42EQm`pfxHffO8G!TdaB3@kuR%@x3FeFXRxq$4UApiC(bDgRnXpPPXL3G`*ZfBS7*IJy={UZcy5^t4geZ`Xp%@C~U z9CkQ`X{oFD8!iH1ssCEkY>n`WxXkn=HE)yaYLm;v!A(}5fyTWEZHnAco}|V@9!lDr zs2bjr=)&91WtKhO34CK@U?&W}=V+L4>3v|tFEuq=@_+<>SS-y!A9lVnsPB*3?%=+i;NN?{e;tGh+sZ@P0a3DJ=R7i%J_wezLq}V_7l# z4ejgL4$5dX+e>1kLhg2UAc+$6?0Tl4a&2s9;Ex;Fq|a>p{z)2#bC)toUq=*jUs}dM z9ZO5_ChR%;ReZ5#>y^72#ln_^+($rOY$6mr?IHyRx{TW|H+vD#+OnjcUzW4%BCT=V zVX#Ry;7lvJV{5rSN!`3Qv!f3z2#=IM`quhD@}0cc3jK>yDXInm?GGkDG{@x;7wT_7 z>qMJ=oPfipl;a}Zr&?uie=EtqiKKMaYr{}G++=eLs?I;wLdLt&E`HU`mvQaN$Hps4 zCcU60imsQ5oYxpxMl3rbDHi%@C<%|_Fo0tEtmR0mCger#d99&)8T^db5%yJsGG;9H1h58H!Oou~uQdT77wBTnqW z>d?2;fVhNDx_~WZpf6aGui323BQ*s=lPm?KNEM~9pzdE8EMgevgb?0pc`}YU#D-lj zBcT>q#z|T5*#IM^hlj)W@#_7eDV^T@yv+j#lj>u^g|*_YC}=H$!NKf36XO3 zUih`t2DIqB{rog0OY1(CWQ#Ih)Q(*G)3~7Q%y8HuIPLAbX3hkd`DobX=IrpaGL~pi zw6Y=tZ<<)jAtb|yNYg`dsJ)rQ!`bACCMrUTs8-~R?|}KjqeF6?ydh+G7F#k><{a{3 zAD_(e3BKmn*4e2hH2#F=!Ba+Ova%9%oAikL=*K6}<*VVuf-7nDO_zzrv|N{%E54c} z3nBR;FMgRHSUi0N3FuL+sg;p1+f^wN;QJf>nE=j7hhJWeQ|h*K$1^{YD3! z2E`)*ANjv=q)GqUNUC*(Rytb$HK1Ha=X#8zsBn>~_i$Y^3uZ&j*wgBhaFWF|DwAR( zz5B@j^L83|3K3zG9B*@LToh!poKl9|ml9!lgWhEf@rI)M!%uyzevZkOoXIG*SeBYI z9Vc=vB+jHC($i+NGi*`4?pVdhcPD?mlY3!FFJek)oRkD?GlqzMGUCL*%wR15u-CWXQgu0~4-nm0+|p~-o3PNHz6uEI>?rur;v+^YD8KXMBb&C|xACG*#c6nh!B z5^9%&n|G~vuXq_F5T$dl@ojjv&|~d)GUfTc9^Hoo-{yC*&4umMCWB!(Jh5Hmh7+tW zWte3hu6gx>Z$fmC8q4peDu93fnpkJ%+W0MKg=*CY%a2OUKP1Q61JI)YOb=NChJ>)b zDfP}EbmELgid9RCR<(KRZYrz1N%dzuHCwQ&n5H2Dk&R51+F`GWvl0(4+i2$zMhxybjX%f}N?>{M@ttji+T*7z8V` z0*+ChtH0~4(dvP}*~_xew1t5*EpL_CSaI5+?3&FJ0!r|1L7nEA-ja$F^UIY@18hpw z^0L4XbgE=zwQ`IOp00tiou)+o@-ygSjIuN=iJ}3pnD20_i|b+)j}}tsd+ioCukW?* znRe@8+*YK>nI`$+7>FfVQ#*SbwAiks2sr{0c<9{Hs3=fIfky|$CwG=Uw%T`_bokGC zRj4XX=PX^x6R1hOIkw$zIqAed5myVnFfJ02$27Y^eDFKM>&0vGc+k27eg^Ku zV3#V?Mtp(HRId5v<0jWium0v+0TwQN)N?eoKiyxs=V? z%S8DuhrmxJ7sNR0x^&2F?-KX}1GOL=F&?L+W*d z(Z{zaseQr@jWF#}>Y`i@jiB7eG`xOH1gu#=u|w2DnkhC!ba3qpI0wFzAfGKmRs@R# z=Bm0>Cr#q!OAkZw3pgOHA_+AcvFlzK|8{jz2qMdj+2y+%_YpPyO#|BQmFYINPJmlB z)v5&Yum9x~%r^L~xPAp%hO^U=emh4Rh;#9mTxQ@IU8TC}lYCuyM#r(DqrOwyRt1|{ ze=y)MLhRl_Ue$R49I6R-Hv=^HrM|qf>eJfx-4+4C5cHWx@(Mg{8A3w}p*}3+c*z{d z$rB`w*v}bL;vjW%gVEKA&s{bnpG7CeD^UgA-BHRZqSjHiHAtWI@M3BS`61WwCOdZn z5}#(7(nIg@gd%!Cz%u|4=Q|uj=(r)KODMQILG5xKBNaofqiwvFosS>us4loH$F^5U zKH{8bh>xZ%+%b$At@Jh@G7X0gnnN}u3UvsCQUl4_G z>W!^V%wbpjy#-xm-w><#MB!Wg2gLu#3;)U`lv9@-%|fa zNHPFc9H8d-L*7jK71H)e=Hp3?3A{@e+%oSw2)z(*Y|J#~W#Z^OAUq!z#aq96I1f|` zNq}#L{&ONMggw$U&|)#qfw`qajN?$rCY67!n%&xa&&}s=Qul*&erD~ner1YO{!&c- z9h)c_AA0n~D$|kO9hdwAGZe^a7WgDQf3;DVh!iVMWnW%^rpaf+~Zv}7M3nr%;WnrvsA>(lx%#aK6EBtu5~8? z#X`$zi&Y+{hSg$g{ygqYo_?VyDZi;h^3!M0X&u5jRCRf(AhKpWcZsSf-5@R`xHP-= zSdu2qTI5--(N-15`FCmC>C(ZrU)l|qJnEg?Y|{1l%9wW@gF%L<_ksIBOg~}?+kE0 z;8642aoF(069nzT2kR{xh@I#H2YgxHSZQYj=iRmzv&c-|pNWmU8nse+FJ_O^%`%!v z_3&}j)}-jvu=>7SHqP|<-pq5TNtbp&0@+iQtakITt5AL|Ut|3F%LKRZSTe*y8!?tT z2n4`Fle1kt>o!h!%YAVxFAGG=;a}^uN_H|j_66OTOAEloghKn0c3(bAA}8LW(XjJz z@5Dk(Lm+uB33*hYDePW0sm^leM!Mm`)Yqph+G}Fc!sf4?10EJpDmW)tejV{=`<$@ymi-H*@Rjk=@ z^O7d`<>jg(quin?Fl17#*1KevmTogYZ4E{R(hPT}VWh-6717_q42SMbn4v}I2xq+W zGFwX0aYHJtB3m1WYENDamrgu}#W(Am&G3Sw6~gtF!utta;K6aSs=))Li>COIluFHE zUmqyo>3%e;n2)IRlbMgS3EeDp+5Hl??-Ub=r)0nD%Dog7x&<*5Bk%hLeiod_Qx2|& z;~Z}j{j)+PZ+=!$e%8vG#*Fq{ly3`#OJ#@tbs@(67-?Sj1j3NUFW z1JJS?^Fn^I5amX*QN-mTRjsO^Nkgoq+?q*PGYC7K`o(smXA~u06DD7sS(5j2n0jA~ zBRukipRrJj@LB#Zkw?3KoYN_6eR0_>rluoVLw_ieX+{%1`~3%08;M3{7yV0tx5fST zjpP5<8~R@xP(>QvJ~*m?53&`Lgo{ScB+@+FRU?Zz7DMgq*+r|BW)?zA>Dgih)UyZ4jSdxdeQ*Q~*y`Bt((lOq&+Bme!^vbv8mCNnxl;0jFgzW$#-wHJIrjzc05en#(F>sJI!RE z4q44aJ8w}6?0dhl8KHJ#C0UP2ZJ>#L!JC_+HFmktt ztNn5bGFuX&_mBiVPEFWgdchAio8vubEomC`p6M{E0^#0so~O-5JMRpgqwmv$LqZ^^ zL9tOI-70icx?tAoNyhrJi7$l4^YgQq84)1Cc52g^Qs0Dh-?m&L@KLsACp;?CYUrAUj*zPxws=a zy&_9Yl*rx|`)n^wf8tOZ58rJzLC4TCZA%cPsWupa?TdOU<%$5bXwoyUPHyV6?Y1sI zjX2|cHo5vWtu3Ie6U}a2i+5~XU0z`~93xvclQlWFqays2eh4?ZI&W;IRuA7lY0*|i zTg3RO4M|xG@{IoY-CtGKN~Y{lD?`BvWlYkx$?h=H`g1aPRwtfgT(|U+uWwcw3=HQOU)Fg?v~-oiyCw9Ly191s?p#% z!+GIj^Pt43+Rz3x5&MjGji}hLMT}fkntW1*XN@UH^HK&!|& zIf>hn?wr6vvWwH;+uxNkHZmIBs+sY_@*oZ!Q7&VPp084M(ZgK^=aaP&OWJi&#Oyk# ze?|DffvB&423|#;@8lHZGrbdZn7JYX3Ug>lW2f`?Y@sdAd9`SUSWY#XZPEgFCYPL- zbeN#(S|Kh;y(}c~M9<*b#6>xVBWV>JiR6?Vq3IMH>oI7Dp{R&7&<5;P-q3nrb}a!@ z+rm_SvF1?9Ui@h#bMA%4Z3G{}i2f=-avt#tbvFoLX9WLVaA$0EHtw5*gN7Z|M_>;) zkR3q3OA7EG9vA#7l>EULUB}9dVT1tfTGc^@<}wfN&Ai<#4t+?fSR@C~X5sA%^c zApm;h%0chzXHkkBO8BqateB@9Sh*EsTNH3ez zLKo&wsln0&k32wKS$lHtvI!{8YOL%hz5?#vZ2PJ)5PI~|Jh#p0@Qh>Mq#oMLKOz$u zj18Y>w%dSZh`F6I#`R?AsT-=aUrm%<`;MN)W-+p-futM4UoabYuI=M@|H4%ETb0Zl z>Kh`x96$?rf}*|3MCrNps0$VOWHP?Ysz|2S>O*R|F)A4h991qq=1$?Ao0&W7LN?Ul zHYLu&cD4`uaPo_;4j=ZGbqDb-c4!-k-Rz9mqFZ0mxE!&i&gg`W$xx~{`ktJRE%5Vm zIh>+GL_1#Ijry5KlP~sr54r=@LB?})l;iZ zqRN8wl|WTsG_N~B={6P3VXjkq`|6JtV==VTfTe82WL4?$ zKI9XTu>{M(GL9J762s`mF9DuzJECRRwoykE;YdCux%!$`H-KVMN?Lt{K-Ca;xSSnj z&?{#0x8w33q_tx7PH_w*q=eq=evYaVPcyWJ>X6mB^*;d)Lalm1oJ>5x#WnSJ4SyPe_(;Gt0Mm{NlXzu0#fo={RJ^G ziOn8?L8lk(+!$~s(OX^s8qbF{VDggM4-fuz^BIkskgDl=~0r>&vQ&2s%MMW(hN4!>%r*^2Mb=pkSuNaMUu`{xOd$hTv z9O_OsRm`e)!`{jkyuP2KZZXCR+M2v~cB9nOEAPA6&C_bDqsyx(eR=3=KBEWu1o)vh z)y4gLDKEokD?L>lM9()X`f&{27f8Z3MPJw&fC|CcT~|2KNvy)WXT9?MZ%4_LhlegUhXpWoPm-;^*56AAQMNzQD+j*Y!Z4IDW_nWAEG`^ zs$9zLN2W8HBR52vdPGCxrjv;{(hWIQ6Xz-12Wd|CCMA3ELe1(U4^+2jTc&cu%w2PF zIZ+8g6%~jt{6Qb|gnHE2)$~trS6nKri#w4|@#4t9(}Iv=&z5+tnpgRGA-Hau?-k4X z!JT-+x1KZwXo0W8ee`kVRl^-=u~$2{x1E{#%G#g)|Fb9cuW|6}c_`3)anNP|>5*3@ zdl$q1iLO!8wfR!hJ}&=yd@||PT)bzbPN%Y!T?}n3TVi?7Ekb=jS-a^jb)>#2tOL*I z(`vIe#FcHm3F-AjWkw?S>1AL}xEmfx zk<^A%#B(U>MDBY32vx&r0X$)!HDg2KP-fU|JZ5_J+OWYCZ2*`ZcpfVS+}u3f@|u;X zRn63;V47Bn4sH*Uq*MhGLEB4sxl-+FZP?gsR4>V=Rrz{c4Ar1>6{<4nQ;G;ciRd}1 zQ94N+Tr9S9LsP&SEoROt3+jtedT0%?v`RAHX^QHczn6Zwi*| zqpVvtdajjfhBMCV2AAjAFig%n*ZloYv`653BD9O9uf{)yvh6z5_9~YhX}6LmQkiMZ z##oz|5$Ko#Q_mz)hTQJ=I=Gzb+FMQ*GhOXy4#9RGT)|i4l4xHjY$cnANX2J25}}qq z8jqe`*=oIke0A_4v0Tyrdn_iR4n+0G<5_Yf4` z59yv8^Nc|uF*Up46pOB3c^=maQTb(ia8HW0>3a}o@i78k{Gmj3e%DeiHUxb>*rSFX(gT3q`bH2ej@sTcvNMOBN`ORb%Q1?%R)!%|`7*EU{6ITkzM)*;V{ zhDVi9(+2eU{Yi+qBh3l+#7~YYj_44cu_*Dk!$+!k3Hukf3ILw!V3{&JPmQ8AJEeH% z!XFo%0Bzyh+oD-x!h=7M^ht+@Qk@}>!h?VKjAO*ROgru&6f10(c3C!GJA)cXpKE~t z=GHMbO}vaExCvP2-BQ}&LB(!^7>7-(v=Gi9?{0+b~vvhuaZc(2s`g{$a^( z(Ed~{G)h>8k z?c~ip=iK+!J)h3~S9Nt&cYo_z&)&~(ueH}=L&Qz=wpPBmem&xfj}e&^C5vl05|O84 ziyi4F_iW=6ELeJEBuc&@)I7Unu*m06UK5M>lV#Hv>Fa|HjKO1?X-UwQJoMa`;?kB3 zq4p`8)?AVH5U z%O`&2HMB4`Yc4KcY(s+h^>)>ryu8>$ec}j)%lDYh@bVz?mBad7M71M7ETrsvX;}S6 z6zY3rNRsBDqj-lAE%W6H`*wTmVuj@HJN=s+-V8Y^r+Q2Di}~xr72(ZC@Nf-1)if@7 zl4s}(j03+w1@8VOh6A5WMl{l-k;tvZ&IJvxS?DxWBWvC*RICM3qE&-E;{>4x6g#K( zFNst9ZIAYF$o4@W+x$@OyN_@5Tg2_5Uha_D`cPfHoNs=J{Jreg@X8|WNg`;h4oK+z z7TRdY?kepNfCPP@ngY7Zk|A<+IKGkWnjbM=f9n(P;%6XxU-owRFC)OQkk;`4>^{ea zGE_5aR!J8z`NVed*j0jvzhj+K(-1FumiBO_>44NwCSkFVidgC=W!8A}4NE!2ja8jE zrZKLlNUS25x-23i35{3CT{$P$!>!@D)>v&_8f zn~Ti6ue*oI)!*<0Dg{_uK_K$PBRqqSkcDEW@Cib`6M_X{K8)^rKKbR->(geBcqZ><%ynpx$UJelAF zk!DKZPH$bGo@B@|9m}Zee|&uEbVQnEnk~vdbPBUEl_gEAWf`wwmo-bZvqI~q!e4}4 zPt|wF?Rh2n()mjrCuPX>#ka|wK z3072(j}Ok(0Mh)iiS#z5i)h`oRxS&$tF*`JY!uplw<;E;tG@vouG#9Ifsrk4V5jM< zFEz6!t>WhF6gK!l$!urRprIpB`AO`QT@o3A-AtJenaO0SK%EbF&xAEKH06%uCNFJw z8dX-@sAJ8 z9|_g(n0cnNgcC%);I|{$+~K!hw=P;_>lEGV5S42bmFpSjYBAE5I4-6%6PN%fYogR! zQ7aHZgSd^zQA}=gf{g76&wO0r&zo(beuYQk3AjdrC6^SxLcp*X4Sa;35lQa9b;qX? zKh0klu|U2;psp8m+&%LV+W#I|8PR-(P$?%}v$;aPkd&Z_!b%e0P7mriU>J&%sPkwy zhNcTa6Qb;-3xv!RdW9kuQrp`X>`PR<2^g(T^R<7JfRFe6F-iZwj~;vsFF)|>%9jTF z?VH&D`_Th@9YuhF>wj-Q6{?-OA&a7X%BCC7*7zXgAk`oh2&@RrmgN+wTS)&kTrtF^ zAn=bjUbRkNhiyxr`O&#a0F?*Y{Ro|ne%`-G6YwixkURY@br0gj#Pwjp=grsc zVr~8X^m5Y|d@3rttOgZ?59cp{FOcCVe_sK0hl3(mm=7zsBlO80L%eT8kTRjL7Un~}lc|M%+8V6l?0GywN@yL*Y#MsCD?=V$LjdzTJ zS1fWIBx6P#!*PECd?W|$c0^!33?6r-W~2=ad|zBJ8s09T_(?hClyX)9U@$9z(UdmZ zlN8I?BPys$Hz06+JgDVl?Sk{ijIHV_f+L5c)B8ki&)v9#2{gAB>w#C<~^1 z78$UUTh8nq$@G~jsO9~-&0;Vh53#BE zG~}yYJ(55b`PC(fXdR}-#}VPf%naj9mOP+I zf2m2xV`_f}sKu<7hs_~3<{g<3a?fFCRB9NbWXe!!Xt6r`D{_7%S=UZfSq6$m_+?~{ zFYjq?W0ks#ODtR>R7;f>#Wldjt1r;hB7zg#?F4hMYQkW0GHd*9_gu#O10{_qYo2tK z5pj6!AA#0Ru}j)cvyF;by~BuEz3qZ&w+onivbPV^>N^}70!B%VmmKF+FicK1oLtigleguX6X86&Gm3jMv4*iuLY!;cqYRsGEOA6du|e2LeXeCYM`7z;_#^-G^hJ!(vy-LROOJKS7#c*3J; z$`IQIfX2iv2=e@dh)YJ=U2qxZ3Mz*pm|0%!O-pdm{-5U!NDT+IHZX8hbFRq!8Iy>hwZR4fGPX+O*&sCY zt{sR@wL1C#w5Xs#LMrs$SMXu7rkzI!Bk>=FlAZ>9E;vLTAhR9%NJC!A7QX1MXVhm@ zno1_br1}d3IX4JYUbQFDrSYdSl&gllc z`_x<()I}4_!gIKk(Ozg+CORb+9_4paxVicIOL$aOK*OIwcyqNfT{JtOKGim3xO*oG zl9pCd9wc?PHW_Ih!kJWt0CUQq88+%<3&`aprp#7{s#_k$J)`T?(r-^R_-W<;S&q_ zvxaTKzp1=|xFkkPzz}HP$@t9ltn_rVt+3`FRl(`@;MypC$oAs`H(r#=D)lL^!RS4e z0UI+8b5L2YQ~p>1}WOXv8RB8xIJyt zD&Jf)7kb3K!UGJ!s9!XFgWBT3Ch=oH=lChHS0S!x%Ix%mx(4*Tpk2ZRHo$=b2U|wS zB__o+NwP>olz~f_4Yl>*zndmOY}|4b_;YTDKq~v+L36AS1=y$UV-xt`ZUmO$G}U7F zG0_}YKcN;Jp{a>4R^c z4av5IU1Dsf#F-%s%^mIP`aSbZ=dLcCqmOQz!wX*071P2Mbob21{0wAoiAAoyT+T8I zkrsA7)R4a2f6F^=f}_-6LWZQECv`tw87O(yi=2>Pd2~d|%bs}soob8xxPV)dT#OlL z{gM%IG6-^aH)~D(&e1qKThNtV?FRnwZ$XJJ5*@W?UsSj4*L*|%|GnA$*S!;9;_$UC zZ)Bou?r380uVC0p)%E}Khx){os58(&>?y|gE}&9&I_P!xo5W2|gk`!TY%JMJ9G_wme!leSDm| zee-#0fwE~X%)=#CdQ}c9K*?8HOCloe$F*Q8s&iGd%%*(O?&pn=X3YKaU2uqyU_>2g z!0C!H6zi@C6I+Ad9cAcLx@Mi3+4X}0aiU@x8kr6B4}m&>>~2?YwEjT~`F&I!El|R8 zTAg`^vo|d|x-H6LT#uBZ9F*9s_4Ma`Zm%i3$i$Z9eBJd^QpO?VytGio8nrr_*Ogy= zU`(6-0XK5shw^}K6g}2ybi{qLfeG&F*Z{8AgzI>ZBahwT*^~PKV$TTu(nVk`2@V`4 z77OichZsgA-kJ}6urU*6x?xPOYmy+Id}O}F_qGv=jn~Z#ewQJE!fMD&*u{s(+g~jE_ z&xKZmHFJ;?F3!kG-tk9)W?+SpY7?bFT-g|p_Rk15QOB~bKuFu{R9b{KrK84yE!P*K zpiOKCLkI1-LPQ`WbP()$^yVj9XHDX;7xx`(67D93jjpZQ#`Z4X;)dP)+Rl|{c?->E zf!T#3^e}ddQ_wQaZBVvJ8os^QtT?0Qya0RqotJ;ZMFyAleQ|xr_-nu{o|j$Yl7eRM zOwZ_AP~93>LEl~Ju!k^Y_{ujOQ(H$wQzc;MZ1)&`u5n{W&z%)Tw%Lg5dVWso>pR^M zZ0+#LFux3Kkex+)DQ7cWx0Tl7K9YowF1FkVKjLFgKI;7_-B};9^UALi%v9Af0P7j& zG{#Jd4u8-s@1@(^3p$9Hq_skr5jv4%HNL;@umb`6T8SKWExuL7YLSFzc59pFs%dQ< z#%+TAiTDjgd8lewGw3XJW9fKu@^u&V*WLis+`@?O=T`BcrwiCi{)c>9402~~3MiO=&5uWYyO?H1nP(7v)31_+>vs7CDML+|DZ6CN!RV&%Q-vT=!LPSHF1v_D%vOi?SGAodFgCCuuW{DI{ z^NE&#PJg(HK4)_<^nBfmKl3Pa11TO=vDj_SZ#tr1Td}$(aNoX_lKh98wEy$K{*MRve`+)u zHKEmU7F|B*X~vkaAR$Q*k}C8eB}a+ygy2^tl1Tjo^aY@X;$q{MdM~~a)3%+iYaqzY zgsidv*Tq-JEaqF~)(etm8-S=<;YKTc4uCcn{E1QEY=PuDn}a61&%rc{&D!S}pC4$Y zapL7Fx7)?nAo(-HX|m;UZ19%f_ay$CYuTSujP7jJnrG%?Ui$Iu(NjH%OZvh`HLkR4 zfAs9cdn2ldmf8DNmEjp{W z!MVJj=;?haCO;RhiQl4wKNAn5JKSXf1nEj?RMXQ{QiazN05K>PI;XUvb}m~b)Yh4K zC>>18LY8u>EATQUweoo^S(W2v6_wE|O`S>r>&%=~y)MK_L5my!yWKKB3eU2vYH>OQ zouyGyoL_e<$1|YnWF8hrHNC?!oX2iTIRL%b1!nhjroE!Hl1r}CCT*okffFZGL)G1# zXa^=8peoaS1RGMRZZ;G#SlKM35=J2BpDV&)9TiLybl=i#aGDi}3a3s^W|)MjtZo5@ z<2B-HYU_4}@Vxp05<9%Wd@$C)IcpglP#cPC9VseC9F>`39VsppyCD3G^NP~&VZ`f} z$uZa4|2mlhFtr+jiT(q}&B)C&ah#YLYrn?WJ0Z!OfWUA~+P&ub-0zf@!7!;=8(he; z+jF{eYm=z4-}(`8B+-6P@tQk^lS;J<4eR}6DQIG%a27_nns(8Y@i#Ekx}|+6p3{@j zfyY=w(cm84k4#j$>E_*a$rX-*XRA%=k1l4d{N@up)*k9RqPsWmN(tJO=eEPts&GS_N^BJHlx&RrOT#wF>B*5et3S^WJ^R7xN; z{Ul^iR7xf;upA1@dC{*1>I7Z)?yWauDwK?A14s{OHWni?gtokNo?g@=p4uv6B#%(z z4_a(JikB^SqbZ=N#YR~uVj#ibuIz|H zWzGzhpsbysoIBh;g>_;|3guG08fy8C>T)KL;w(mhNUTq8)8^ta1J`eOAk&45UN|B| zwkvC3wc$;GB**;6RSe0Xn3@Uq0-b4QaV)wx)ts#80Yy{)^Ck^1=P#9Qa&Hr}g;;cC zW}O%SZ6)#cu7TBa!Buk>@ap(#p7D`h19H89@~5ET80Pb(a7hxS5k!v2bf5gZqGY#} zGpcsuz1z(g6j@3+$aUBNw;DekGjGDB>PEt5(Td2J zgsM$D*prtYXbbj3m1kpWVWH~E89^mXEjkeXfNWL-fvLYF z7x4i4$f3XM1ld81AZ!yD9N{s3(n7Nyu(mYXa;%mkb|qwu!hrE$OU25uMb3K(O7@U5 zk3nQ&B)IW8@g7y5DzuX5;{2wKsKr6#X>*bR;kpgylW|XjWEb=I4XY${ku5pl#$7() z^B$kH6`K-X%j#TPWp;}bQ(>2quW#&1wC29cu3MG_6!f(@@H3w~f*0n(mG(kug>mGu z&Rdkwxd`OoFe?8!nVwS&V4vg@UN3q<^-i959m0aX9w0^n+dEjC&0dg$E!$1=%+C#; ztLZrjQX>)0RQLleeBs#8Ske}oD>t%W(Kb__o+}3|yi_3ezi-IBPzDM1j2~KQczYjG zutR%n?^kduZDTdT;<45ucqH-pZ~rZEcW_VY_kJpclShdD0I8=-d}?R(%r`=iPov(Uc>OO;T{I_PBp zn1fr@IuaKHlb98M=yoX+mf2t37tt!d*z`YH_~En~JzItKWG<3j(klWRwU;GRS`%E0 zcBq+qPqQwaFSNJ8#+Vq#t7uu|;OmpP(K^>BnseAbUlM7je(tmip)*H4>cr<0>dYjz zxDW`>P4or!L{XQHcueM-$SrT{8@EyehFTLfb~8ck7!8LAsRg)Q_fIy&^ayu)7IV_t z-+6eD-71DB6iDoo?qR2yL*SQkW9DuucwfULZIyJz3N{j;U#~I~bXusa@p7_d8djlx7lU2|$Ok)Pmz4l*&CS8gb<&uM{K%kPtRl>zJ zKx9*{1rJEn4rgx)dweubt!R`VCsxyr72Vh)msLa4HBXZc5k`Y9{O3h$!R3TCCprz4 z#(v;E7xii?Zx0!k>!JE9xk+2ol2rZ%QvFC3RyUAcbKGV4#EwlidM_1PJ)|z1K?9LL zpc?SscZ$`+3)8LcBYR_VT4^BV%X7|VK1=bdCpRqe-WU$vc^l=GFaC|0SoiE+RJUQmhhyGXwolN2f)Rr%-7RpV;c@Ca|uwd5Sh zdZ9F=U$dkM&u-fO+jgCSiRe1hicPD{6gA;zS~>aO6PLmoaVmRlt$XmIE`s3Mckq;+ z0pSF}99s_}koylmb%CqMzYB3(VkCNBRTA=PV5_}ro;ls=>i$^5B@%xe6h+pnuWw)T z`_;{mEX;Ytm5g++ifDZg8Qzf0(Ft6NR5|Jf!y&EEMPIl`xZ+U-`ai}jn@ z(;L_jJZfFDQRQ8^zKLLMd2PFxG(gZ0O=tCwa4JVDS7!FN%0C|}Fz?u{xW98v(pdIa z6i68Q!0o#zBiv<#=xPaeRpxUxO(Tr6h{732qy6KBm3!wK*P-<15pV|ClRe;L5$IEZ z_|iz}oJa}bQkCq)QKk(}YF zH{6YH{=hxREjpZ~(Vlx;OH+on z@^h{#&a<*u47*%!{noqR=ObR**RcpTgw+ZS)}I()fuA@KAXZU!hPY;l&j2EHSS z2YE#B+14xuoa?3ZnJb?YW4ojNQHpghE4jwN5He289k;|39xTZB$JPCWC;Km3(5<_+ z=PGKJn2-1}jyJK3NxgZ+4f(Xl1&OP2J|{3K%F(S#`#^KOg)NFNvI(wI&I|6Ib0VnT z1b1I37cepbUA?YX?1OcFSlcP*g>{a*!DWZkcG8})=JOra$-Fp$tI`9_i>v)s4P~SQ zUH6pqI1)W497=M{JJzx*uzDN28K@;5!7J7K?J|FKb8@5F=`^!g5q~e(JM?%5gk{-o zcCIVnaVuc$0l%ku8!<{(|CNHzAAXm}7hb;R5ylsvekVV{H})ob3krX5)E#HDhjdX; zk?S7u121Q`y`W0&F>2PNOMpDdsUN`?SSm>z9CA%P_QM3`u(6})(`u`{&o`?|CmQ_<`$^XFQQwoe_`rA665ifsYgj{$As2au0(x+HhNJn@5I4>R#A} zEpSQ$THy=fC!MMeU@N~6wi4& zkka8Wp|r`tq~gxu^6L+fm+*$0@RI)Il!4B%u{WfqU1|@BcZ~vHPsOw5uMzP zQjGS$y{1TBkezj4t_~l3);*5&L-foz} zx!v(}wQIh2N&|epl6v^qcEQJ__{T=m+m!yQdd2oxdmj7Hp=9lS6wS(XbLx!hBzY!x zkcs+}&w5%s{e*WD6_huiqb*64-=>JKudPWz39C!MVEQEdFh^vTpWI2|2g( zgfI4)@jsjh+F4tFQO=D2ZG|FhH!FbPgI(-kg@Ysn8mOd6@O!s`l^0#bAF3ed8f>pHQDf1-3@msdtU+vD}gA0;7U9-#XJ)f850&14SOsyuBg{N9>bFKzYR6* z7^m7MFcqT;!xP3Uo&!_IL7q4fPu3%5-JA+};9T*~91<=S$?imi4I@sa#;#*m18qGW z&`@VhuQ2<_xRAk`@>JJ!`0ye(vG9glZ{G60$6x$d;G!6zO|-J$Xvs1H&>wQ_}6ov6#HQP%EsD_1(o4(t73 zIOvO8ttGh@`MZYjuXD@P%ECOU%7SC_4DS3Gz!-PS3K@LILbPf-J*-3q^!DnN@tR#7 zi2?H9gJ16~F3^9InS)uYrPmCS$>zwY77XT3i;%xrSc>JA^0Lg3zF3t2=3rNFXIo@E zXD`RP-#R#@J|1wAK0)@YMV$kTgYx_^ZR4E7-^nUh85%YPoq#Ss%db@4?I<)zDlXNv z{5V8UCVyV-M z)+ND!T)wVmY3*L>^70?M&54PRm&aZ5-#TZsy*;Lec%%olku+IL6x*ed;O?f|EkSib zP`x9R$%V1z>^~R{)vKN6Azh}fDefslI}WT5K!xePJ5tJf<_!u z@!Wm*@UCmwiy>UJ2D|OIL^Ulhm*5){h)BxDMg>5x`Fh)Kew@<9FO;!hjDf5p!j#_& z0Q0wVXnT-1k`gq^t+GeK-~)`klUR_~Vf5|c5|Ot3_7q7d>U~^z3wgPKh;XROjzryj z3%yh5b^*pAYdB4_hs7Cz9g3ZEiaD*9qHD9b&{Y9cO*qZG4c<$Bx*XB!fo_#DN^=XFC5C2s{SL18pjNZSZs$nN;G<|=pmI*js550 zW|(!^9%}6i#9!|Ga=C1eK8T9&^Ac@;B)F#>t(EM|j?t10_HHE+zuzbi&H+r08EK}o z2VsRO6&vJ@;=Q{o<+|4@DU;TAP=a4!50X)Q;;n*!2W8 zVmp)zwG@&;#?W&(=VlsrqT^P%3fbvGzrt)zCc4a**eDo$MsS-^iI_<8{rop(0)8eR z5%ddGv;SvMG5v$E66=pcOH9MAJH+uauY|G{H;Z4P-l9J7;M3KXg~)uu?!|L zt@>3rIy%^UZ=6DCeWn)Yu0w+Q9QQd_RVq*<(T5ZS^OCXM>0rrC!*cw~-MhYe)!(3y z48(!s=#Pl|m{u51IqSKT%3-d|g4u*j96JccSpWgTcIS>F$xyw^y|)zo5t$eVganr) z)Iuy?V5d8EJhCJ6l52Ffqtuz~7B%j0&aG~r&N|!nN{RmLfJ?>K;+=J`*n}9~DOr=X zb#J|5Kis@)R077$ut(O8;Na`j2_%0JQbrpeoWH)N|IHVwm=rD9OaV&Hbf^7-^)f~d zuR9d1AAxRt#mJVwmR&Hp-@<^{41&o%5Z&8Dit%M9AP~r^$gs{QX7&7d z_gEvCqtftdn24ckPJ~QpZVzoGaj;LfFxjlz zn=-J*s2B;ffZ3(4@)2)xm@p~Cd?S3l1oZ~HC>(mFh?|(2^$z7erW13M?)v=S(vCoa zZtJtJ-j?=%#uUqc_qJ7AWJUyD+a&AsRuWp&sTrZ)3T)|3&`9#XsdAwTLQzPN_Scuy zONj@Q9^y)}gXVtsf#ClYCmfJ2yZO;zbw1|K!^g+Bi_hQX1Ac`QLQS#j$LwN;r@FPP z2pT03suD)&VZS5 zCi*tPj;>`hUr8aVUu!-Z1XlIm_4z^A* zu;`E23Q5?FLBw-s8a80pSl8Z#Z0GCvTq5b*X_TXa^&FWi+ySGmCHFfzugo_Y)cY*E=%93Ddv~CghiQO z#BRc9In~(ziYl~si&A<*-8jti46w$m8vkyqIHnUJi{-ZE`3qeOx*}Qme8Jsaj^dEQ zr#n(QB8)pVNZq88-~Q=Gao~C04W8?e*HXXF8lCI3(N~ZAx2;QSZUF$>S2;@hB1``x zbEU6&{y(op01M-PY40)tHg+=#D86*G3CVTWOou7ACSg!A$M!dnbvejnkPg61lJIQ0 zLPJT5_#e!#YEh&U<}9yg(M(xdjDFUPJ2sAT6Fw88PI8m)*SDi?-$)aPW3CCpLWU?M zs3}Bp4W&cH4f^tb@}c4NGsFp5K{a9SsdhL>Nd0Lg3s`Z+nO&`awl{~vY|;wmo_cxP z1L2=;p1s#DFZZw=#MRjKV{^7qn}wZhw3!_Z`-vL7b$ak2EmdN?I;m-Q!Xd3Ukg!7>MI>*Q}q}^yXa_5lOeejBC@#NO1YI*J0;$^5lLzlG6 zy-<0SwR!y@ixf(xd{CHJnNi{e3>2x(cH(If+Q(iYBV0J^9tDrK#pMdHE<&>uH=#}HJxV!Jdf zy_pr&fkc@kR$o1>SdQ9gsY)0{)$uvC369HW76WnojbF`_ViIm%Z+Aqc%Ogv$P&Mx` zX9hdY5>pU`AQOeFmJUoXGy+1^9`Sp4*yxe3N;|zmFH1E><-4;_x6K+3Nb-S z{xo(-5g?<8j1?gH5vwm010+}qlDv_?lQG>%PYrCKvr*BsYFyFOno~U^TA2w_{b6a- z7~bT%$=-I^rqf9Me(7UpiUc9OvN!5=xbAh)a`<+b;WZIt_Hlb8{+$NhDa;;m!$O~Q zgS6CbbP(jmL4gmCj|sVb_@H-l(93&4*Mx;?!xM+svv8gj*b8E znW$mQOKIVe^d1C+zb|@kH{j;FA`1WX2^f_PWvE?z{ncp=eB@djGD^a~CIdKJ_fT|IYx9makWUrsq_V z_{pRp{JtA#_`+o$*iR_o^S9%e^pghxqGR=UCN$SUF~eAQ8b$=5rVnO_SoP+r8LU?= zf%W%KI&w~D(qq@}dR!ib>~%Um*BS{@TD?~BsXvX%Yxp_Sj%q_n%9n;HtpZEDHjUm^ zNBfNwZ*Dsly{Pg0I61S2w}8&1g;1yaIQJCNlwR89Br89hZsqVAU%@M!N%&X4{@sDs zP{RsNSbUYUKe*-c7yaL`8qWL#ErQ#0w6;B|dP5@`IOVKm-~hk6j16QG<`bg*wLH}V=f@Rh`BVN+#UiN#v8 zSUX5+L3QmDyppMPKW^o!TkaZ;sn!y4Y71I5wP|@SE1FbJ>!**B0-=S>vOl2rksfm- zOZ&|nQsi|{ZS6FGu)4M=ZP}}5A9wn2h@}pyT@O>8OB{^3v{wW^Fze`W%Y7`BG5p#K)@7ug;k3yGu!~N8k9KNhr0r%U2oKBidJpp8?kXN_P z)xNH$j+8pB_VHiSBYzJ3axcl|`YXHk8(X#@hRuOjmy;G^A{hba%U=On##LVA^}c!D z*zPWa66z|0&bw&pirH@&nI+w<_<)q@`pH}8Nfr^|rGZUTa9t#qE= zSmLne=VTGU8q-9Hx+c0Nglh_JkJ#`4%XO(Lsqt#W)F7^)WJO2aAo&R<{s$6ZgC zn}4-7SRKfPMC>|JRH=8|Q<*B~QqOi63& zRxy{8$eY-cOR148vwW=m($(VPs8%QJSr!xKer`=VJdrXdF4)MKTDM*TBV}S^7M41- z-1KQ}KF1o;b~bUffwa8e7hEx2P)|NHFq##g6eNqtD;LbE$vG`J-C#rxrtL%j`s>F_ zf$9F(^&H!?Cx>)Tq61Emo~szxS)8O=%^3_Xt5=zW7)rl&J#st0b3an;ci<#vF0%F) z#cv|y!s(%^PX=05@7m9FeaFSkiW8lglcc#jE~9Lom(k$+ey``66PI4Q6OB_pS4c7k{A|4Dx6PCbl=8mJIZ(_gZ;lcR|@hb}h<1 z=??O<5fzvXvx#&p154P`5${d;d;Scwt}l%p?!UFBp1yfc!s3exF1h_A(*E_c^J<28 zs%JFnFMicR6oI|EOE)aCk$eiU>>!0BPq#fh^QaRd( zhrb#7N9wSp`@47L_n#Vq1Z~P-;b#5CTFp^mT(v19u6)2R23DV3uUGt}_!g03U2wFb zk+@1D+{XxsphLxo9hyTW8jylu`*PE}w2rgNLwjxWQi;O6INfl??FjhX^ttyh|N893 zsN)mKReI|UUn@DbDr5EV( zeryC_cp`ogL%Gq)gfx<|@A|siN`UhO$DMD# zg#A^VLUyjn;3Wt$4{`KcDTBewK@3LSkW9D=ZEWQ_Zg&ABsUM&BOa0jJ~bTv7wFfU-MR#j#3ye6cyh>p&0*K!cya-Va$61M$N z{4;v`kWZsMX|0)aA8qu-@`+v?zNh4xqL~b$k4C?in7iH)G*NrjHUWHe$Y8Ci+pzl` zV?yj5nm5=LPj-C2^6ID?e2bc7c0|Dunx}uY_xz&&(MiS+Sepb5Bw~oVZD_xBt9|i% zG>7dfhWuqb@&;^qH;eiR@_1(tyy6+1hHn1NKB4*+PI|~uwYPsk+P=En6GC$7ss@d_ z7%H?z0<%UI<`6>Btz!uG5YB{yP;al0aOl5>m4(D!y4DH2c`RKcv*#Sb@3A^E&Ml$Y zgZGHhJDt}~J~dUU2H184pfgTKfKgLj?6-m*Iq9Ag0X+}}^p>8&dApm*;&cqj5^# zaa^J4^mM(36Bj>RmE5)>b$|0qpPNve7etM{7w)P*Kw$kGK-8cOIeHj)Te?|j^{JoO zT(6kFpq6BLJ>?IC#uM;JY2-bEe;F0pRd+xTgzGx`9&DsQJpp?NKiqH4N06pSr@F&a z8|JTO6l5+M-i(n9WL+X!xngn{4rJL(t#>0IUC5kk&nSLMPwY5kEWK2EV5{ zgxC)@9boGKO1n`;v$1o+(QW9V56n0RZMf{O0Ck()QCe|{4m*ch=v*^IGM@!~XL6YDd?{$FBUhQ*#-@sK@;qKW#o`#_(umt|#?=@+W1b?9w59;r_!V z<*T4Dts$ug8&pp3QbTBuM3ye4t44o+e{Psrn^_Ip)i;L2l+H;8tu^-5qU{vhUI-1$ zU`$G4?P5T!Puqb#n5sz%%!BnWk4QqD29en%cJ2_d}k>g-hzaRd@O zuT`{{v9)8b>$!gXc9Jh#2ch!3aS&k=vWpNiph2f|-EyH>jZN6wNz@=!uK&*ZdEIP) zL?4X79CUGC*E|&YaNtQGX^}DzW7!ph?sOQhLRFtzOpXKY&kwC;%v6<;5g!v&)9y)3Lh@Amsg5MPXwuU`M$>*Yy?ga9ieT;Hff(a67A%Uhn5&Kuf%4Va-P3U zOA@j7s?FMdcUB2Cg=KTN4Q#T#MlTN%7M-DBFVTfXb2K=VD@($jI3_%*GRxUctp6ZZ znR}1Dg+haH+s2lk;(>esl!`$2AFR&aM=amJ(NHq5tm;rFSRB4HS8N-(t6otn%zb)t z$R=-NJd9)bZE5sgdz1(sI07gv*IJ9jWyZbBMEV&NakBi}Owwcp0>8m58Ro{ij z{V{@$cJeew8W?d!Ub;S6jZpFGW`wqOw1HI2Vr;OUxie+|Zk-2GPp&wY%%glqhF?(W zSw!`^lOvLyCE0vK@haN+kB&)M5u75s4xFjqRxCJzxFe}O)AH~1`cUIM14?8?5b}9r zrSSakeDUT|ymfcV|%4RUcTSIkM~^FmyHIz1pqhB`%EX{ikimhlC2pFH|U+Iwc$g zOL##?yE+XH$RR^{$U>S&E$70TB2c3wy;r*Uw$Vn7;+d znVNyh=**Lop}u*SCrjEDc2{7kz3YE9-J9eDsu2t0lySB%|1GC=VFIdB{7WDlO7x!& za{g5;{yE60REKuQQFHmY>@>wE)=Fv&TdcJvZ8EY@n;CK4A*r+8ZFbF@OZppUQ&Awh zIJ2};v*O~a)|8m^vqVeC$UFnA24E?)lGjwwPbtyFFp2h~03{C1JSRc?I6N3l3O|r9 z@8fXd%$&3`12yMzcAfhln-`xR6FjdsA$(B!`72mGw%$U){IT2ey-NY|VAqr$?qb36 zqgR+9*|5Zc@*}`Ivv%XK-7{8(>Uvoc`_)!MXue4K6C$XQx8BVT~Z>~f^^q8*p z8C18bd)&Y4LGG46SuH=O@q9$qe0cuc{L60gl;qci%GgN@{z2#8HOP8*G}D_zF#7&X zvhh=_{cA1^Jy7h^X6ska5faLWn(wE4aB@Hj9F={UvbsmYq5_}rGir{$t69COuNs*O zg*s@^5U|0;FuB-Uh z;W?Cx*QIQx1SxarS*@`iWA+5zuIqS}c9VjPNjNwlRZ-gD*qqI0vt-^blPau7*{)QU zP3k$`M>UouxAU&nx{M?3k4Tb6n~sj;&jpb+(TW z`j>qX7jy%C%GoVO1wl8f)?zTM?6|D%&4XS6;!H_P9PBA0I5PXQH)k|2VZFyEZw-@D z`?%oM^heLR&JNA|yoUQ?;a-k+9Z3gF^fTQJE}dE~@GuQ9Q}QHzcbGvYw?imz9;YcT zQU;AKC(W$t4Z#o7B*gi|yit&kg+CpTz|T^0afeysMokCcil8kj(+x~QMEEY&C3B+> z#Oj5)>y6S9@g?g>~2BMM`tkS6+)ON}yI=t|h)JWAaSh3wBA8b@|eaIoJ z^K$c;rkU#2i@_>)`<>~imvhZmll%Zl@NR`nsl=t-i<s3uv0lIlj7M}S_YodTE zde&51xxOA~!AP1Y=U^;j;G?nzc`@_@)4TK`o%eYSf;!8@1U0E3IM})3?y%1dWr1yy z@=)QXQF70%>- zVd$o))pV5MwW}S3wmSY6xc6gGiOWQi4!c%uJfOv^md>E&eRQ9ejN>yDBgJMAM&Z5X z9ZgI4B>PqJUavtPcCM*d>GMyn<3)CSua>!ZqH43zHD$9B9lGm=DQ2>%<6wq@J(X~S zhi_eNwpN7 z?T{}=A`gKpIZaG<%)}&DK+WN~!#YS?ZHq#*I@bHRD0=#9H+2kmn3t?~j%^!5JdbqG zlxxdFmiB4gms2Y^39jEXqQlQdt0tQUw;qtJcWnQu&_0ecokE zbob!Y`S*NP60@sfm?d=ckdmZwb$&{Eg$y<89n<%k(i4S61(6=@-$EO@B``(iN>rqq z5hRlB&{AlWTCl8i09Ivz=8OvIW-JQx3fPHq7J~t$%q0^f*FBpECe|_=ENRn_!|e8! z^4vd~(&XQhP(q32zjWpCy5O7zCIeAZ#cQ)gFcQECk47!W$Z{LyY_E&*^^h)ek&tb| z7euOTQ1lHL;t4H+f2=BG8ibt;?B)&A^9KfF-e*!G+ly`)wG7kCA&iZ6-wb(*o=^VF zwI4X}7^+Dp#ov2g*F`pMMwQO=^tP%w+AfO+M0>|?w2ahHj|*3|ZmQ%q*|u~~?v_NZ z1Lre2b-K{mlt@Ra=Qb*qjeXS!5nYQ{52{RXR8DkhE|`YqjhYm!Q_c^n>g=J4!MGve zEDW65x+=U&scA{>FzO&xA0mncTU8c&R#5H-%9>IQCz;ec85a{11sn0!m2&>5mnJ7l zvgPK?jVY%=ffyYs%K7^~01wO;s>!M(?1w&9kuz<}RVvk$9bj$*ku>RB<#ZqSxNi*j zFhL6s(qS)Djk#}W%mDfkV}Gxp*z(@YYLT?RdWw#)`>E&<^MvX_)*&WrlabysA+ zCK)Py)z$OoM%%&fAu^g1X2G8x2x6!zt{(t?(kGa4BI_kz9@Hk@xL-kI$ZNa+bfzse zKM}p|IDSBY?u;k#GW-x^rTUO;v;87krSZ{Y-$-_&b@@+kiGxVt_m&QuOn@YFR;ps{ ze!a`{nG-Mq&vE{P)XRv@`yP+)i@q%0to$rJ!4Sz30-bw4b z7}2447{8=<6t_#oj+YH|Wl8$3jFw=`?Fza)P->$e_K9e>#14fwzuq@ZR5z#5MKmHi zF%s3y~MKM%(C*nql>fv*K~J|Q<*ac~F8I#98XqM~C9k6HEB z=2+fyf_7TJAkX1Ok>n2$3$mM}>zeEP(O{$s_6$r(xC>(fQ;q z%%PdtN@z%pSn#$F{FQwejs8yZeGMHaNJGqJ7S;dX+LUef@*t4_f0RmMaTA5^4byc{ zvbG}&z4M^XzU1!X);t4mUa+-G@=56mRs^3uHP0TJm~3lVM3WuzN>pne#(UD`E22L~ zGzZ@<1C}%?XcV2@ zE@G}Gc%nUEVz$Ol=^bG1U8xW+#82uySLn$}dVXVl=&Ifk)aY$xd+%O_IFv5HbGFzN zC02cDlGcwdu&ZPg2fyo%WS8M-#NItaV)&> z5W2N=OGBjE`-I-EAl^E(=nOyQk}4N4>#tR0jJ=3^o*>k!H|DK0_DyN7X@Z~xH}7ooWnIC z*hPA*m(_>iiFSU4X8xdxf5&dweQ0_@3tMq~+&ICA(=96Q6^isuSMl&)^9sg&Q0~If zT@1q|%>XxhYrQK9$AMPoXAr} z6)NSOF(*3i4N~FObcV1-J84^q#O{@h?-51sofY~HY{*l;sp!D%4R6-J18{-q_{SP$jRgVZjP2kz5bzFqOkafT*d2%U(3B-{%yVzh%GMw zU6FvR%)(BCx?fY78du&Kv#U_4CYAk`+byA`GZ~jc2ieFTy{MYV)Mht*XV1nDfV<3f z7}-?2ZI)pl&hqzp4Tr>nHyg$H+LG{B=ascFz+{yK$bHp5v%u`L>KC&4OB` z!ntV(CTao(dJmPAzWTSnYM2rOAkrE}ltCkG2KHJ(JGqQU~3~P9o-A^IklpxG`uDCn986xM|5hbllw&``2VNqr!sA|dc@2y;- zmQrlB$UiW;$gjY&%j(cNRTvgaI+DYB3(`a~x|ycA$6FGRWkbj~tj)Sh9jf0b_oJ%N ze)rIH>~$pGROsluZW#MT`V8P12LE0K-L5ySNyC$l8+VApYv01J&*mpXZslPE{lM7Vx zJ3VDy*tZxTE?$1=b}RDq`g<#EBzBs#u2NJ5Mg|bZz>|h*^z{+UR~um0m};zcu>?mR zK7Dk$M>^W#tu_xbqua%4kQ)O~Zo3k-1A4F21RMhNNtH2H8`9es_c`7C~OM?^vu>gVs-)QH2?l&u&)$RcoFP z^eEVzyhDl!*n(7JjbvYqx>37%WGk8~)zjw;E$(MGZR~6L%}AAO<~;9)5waiXal&(u zi0ie_dkAvvPr?Y)7eJv~_r!_Mp&8L8F7YV-ElZGZZ6@YB3`we9+DWn*JS2 z6*5c!K1%mQ`=eb=j@_YFtS_6QPt;+!H0hT)5VvC5=s1SbjK8Ea>xkYk9aoe7C4Sd( zD&cIz`{bP;wsja^Un_7;qTBba#YBZ=H#_GYrN{YGfymE1a356DS=;DDx)F- zm-8+DzHm6-H1^K-2Pd7%7nqVZ_piJTyYM}cL^on_v01ms1=omuwgd{DV7vh@jJg)+ zU&+O~u>~QB22*;pMG$)FnopE*#-h{Iv0VK_^yAE^_|KSnBmvB%^nSCcEJCQq^|L!g zuV@#QvK5NurXPwl5-C{siMdxtYW4+A*(dZf>LEzXp!u>-P|y*K5yKbsatmF7ls{8y z0;q&dHgZmhL{{;=(!-Pp-YInLVj}`eE<7csZ3r+o$Nw>YNtr(~7ygAh`!Cf0M`1IH z#!gQE-=sELQCs#m+<{xLRhtYdDfTZ2{~U!eKPt$Q&;gX5fBgN^kjhS~bB0infyqx;E^JCR}fB@@c<<`{0N3}umP8*k39QTaPNM5ukFnaaYC||IjVmm04Cl=@fo2!BOg;k3Y!K+22g>2oZiA<_0ym4_K#4@}k zG)nBi=-5z-g_>~gO%&l9H!a1Bo!^tBmK1`F75%6$Bt-w}k*UnSg1!jUoNr%)>t>BA zP~Okrov9o~rYm2%YGjrD`E;6&+f`Uet#52D-4(a~Ax z0Xed?U~`Qih1~HP6=|NmX`(~2LWVXo?u{}CrD!Ct30R0KN=_H)md9>GAd_1psCYKb z#%H^xcIsVApm|?gp<%R|IqSC%TcN4HFgmD;A5srs3j^Vn{K+=rjy2y5!6;RqD(<+^ zBTg^bge7+os}pps!GY1-%DmpV_n{@kqMZ$eA?w`m5q#P!l_E zkMuO6PO`&eY+~p}=ez#|_}`gb5@UAphQEl6{69qGe{<-65vjPyhs8Eu1ezL%k(#OI&Mf41+_ z^amb{nPY^Oxe=BzRjDg@`rs2G#F@GCk+zt6&b z&%cc#3nhw#6kM_7(c3+>%9H3iX^P~qppOhj)qmvFXi{O(qo&Iw0>HQk-eeSNZ{2ok zgPIr*h5hkxU+d?5EEnfGF#7aTix2NiPFXRtTu?cbmDGw8jrN5QQJVo2myD1fC!BE?!)>2Hl7RWU;ADx_yD-ld~ESchy)AiyDS>3Lo_ z|2-OpnQ65 z6vuWf*C}euqSYD5k33nA-#AM%M13zUQ1_3YJTn0>D#t6wu~I)r{z_Io#px##J~4kv z`lM+%m=QplQn%WVU|bd&!C=my%aT3ikaVm;G$99fi?IxH>A)RDC&@2$f?T8);h*mq z$#Rs@IvMj4c_y4nF)h-00Y~3fm!J>Fcx-}%?#K5Mzvo`xDKWe%8oqz@PPv56pGmh& zo}QD4?2N%OfXO#^&diLm^MdN2&G@TK~UwLahziDc^r*k}>1hZh>Fr!_-;H*l!UebJS;h z+&@fAz79@WZva~E3}9h#u^xufJTMyFG)5S!IL+A1IBs#8(0}916nLebSy9xVLrS43 z2~_PXjIpyO+bHjM^}0SH`m?39~ql6~?_n^S9DCE_5f>rwze8RYwCNAd3-iz`tU|V%vs#HBB0P%wcX0t|7cn1 zXX>B9oy?Jy)cEydFd)9 zLb!;W#?5vyXWkW$5_B6YTTj1v?hXKMd_(Dga5G;yT@E(lPn{Y|x^xTDHsZzbev~QSv2foXNwXNTuVNplD>!azc67l3f#PhiHG3U_=1Ejm9ByF=fudyeQ{SW*(ng02=#Z)iIxR86 zoFygN={m#`Pnj(Y22v5|;cag>#u^o{x%yj=bzIN`bT%GFC8e^#12`Q=?iqQ}Qu%rs zAagR>60YZ1+>!L}CG>)2>I*Jsypo>t)!G5=N0L$PmZ@WHJ8|7&^TG-20>BW*VjSf< zLtHikn<=14VD&unHU&3rx^&MNXBt>WOqE&t{>B`$Uc;~Kmpv(*zgm#^ocY3F=CKYw zcYj>vr<9xv&NesM6TG_USn@>o0qatG+u|NhU>OXm5_Q`|(z1?DwE>s~D*@@p^3VSW z`L3!GD=Gaw*nobo^8bgO(0`SO|4p(^v3A5%Mi03G)?}fIGg)sk7f@K#pr*>O&a6l^*=}WPK>`dQkoW2GB&^_`v z9=I6runwQ8snaOxRj%Q*K8SOTaUb1v8Fa1++2i<#srzi%W2YW_iYcS6Ir4#QsxxV^DYS1KQbJ#AoS&ni6FlxrL-J>V>cyC~K+=He?E?;z>5HikjJiKDv?LSkEtyW4?1}j0}(#s1(;$ zXJ)2oL5FW+*W%o-a)mSHkk}(Uh*OP?{!LM`B9`xGsZM32NyTb4&M~FPA(bDVK_1{# zXyXjl(}uKA{BteQ?+VR2OO|&Q4{X@fw#7v85o)4MC&cLRxmvPO+Jt7V0NHbq(ZY76 zuQuhCdnJp_%W)oQHh`PENA<_`wA1zAlkHFS-_=&i=bC26-HfjOx;Sz;p4WEUjr*}b zGieLHu8a-LKcY49-Y)1*> zqSoeAi;lq-v}LpcH}2g~C8DzM^T|j;Pn!@)xcvcGs>$&ySn;6U4<(PcSB6ZR%r@=Y#{* z@$;U5$2Mkr$c+J5uYL=Y3!xyKb}SCQ}bAMmC z#%@8Y$>*pjA1{htQvdAS-Qrwy|ECio<7X1z@vk;asD5|7*)f$It$k z*l?uRJd2GU_6wX^jx3+r8c|qHs|}eTpF)gZoL>UVerv7Lg>V#$on;PuSDo!ejt|=n zAg9!HsER&F0%3pm%Y|q9+hpY7Yjo8X0QXlv8Z`}RwaF?vy?5XrNNu&TR)04)LX-dc z{$}4Rod=umkymK`x4;O0KnWF~gGk9Edr&6DC<-U4(223pl_z4_I97vO)~E zoKaSYze;&`*rN<7Ii|ZDws{q< zIBU!;S2HVv(lx<6wvw@Qn||2Z8SzXFEJ(wZXd99ic|LqK91&ymj3}P}qnnmAd||$) zyn19aU~$#_auRLg@!;4PH+_``wf?XGXjFI^+p^8raMmol?(GIB=>2C#NG+pY2S#*3 zwnj~~v>w?Xx;4nHZqx1@7LYi`Z>(G`3+-9t7H<2 zs;-Gfj&0U{SF}s{n+h32aezYfy4JMKKeK9R@kfMbJl;6)1H^K~UakLXO)86i!WaF* z5u=(tirJ)U*7%miVFYW2$(s`kuP5&nLFI;PlG?%LY{E$M()z)6V?2!cnWC!Ip0x7l z(8_UR%!hc-W@WZJ_kVBLXmI>amVXhW{EL|X**C)0%JzS$kuRzuFe2PnfN!9FSA3JLJTAE+wfoD< z%Phv!?62>S3s!&+H@VQjOqETCe*2AK9IIt}99Q;h`zH1lj1*a+g`Ban+QT4yMr4mT zOy)mhPF452x1Wa)fr)tKRbOHHq*2ps=;4duY%t#)r6dgP6eIj5h)9oOYGaDU%HLUg z!lwLFKLf5G(9OV%anR9n=5HnBOP@E;r2)ak6x6FbZQ%{szCVR!C$cx_J_aOn8$yo?nbI z>8o8h4YI4!%9cY`cz*3$=3x;8~f>t`M z<6qHVRW`AFZjq<;vI-CX1e}*H)Qc|=h~DD0Np+Yy2Q=G(J{zpo(-*pnY#*ijicp!B zd5Ks@NIGJ!jvVpUPxxx{DG!^RxudL_RnJ4U`!^#B2N!&P|3^c=MF~daLJ0t{84UpN z`vYKTYfWpR@9wJaPOEQY78>nRO?^E=og@wHTjUs z|*YB*f?2d*FIA7Cr+Tyu6U#e9iRA;g33$WP!~4Nq0p{*qy{2R!i5^OW^wHa zkiq|IU;qZQlb#QjHP3coO%=$9p%VkD)$FnoP+`z!c)%L-L&I;WaiiWYbmSU3?#zl6 z^?G4#3(x_%6CCQr!b;X}iXQUC{PG)seT2+Q+t3r(C`aCn&kzo5%>I&qimR%A4}jgD zxUP;CVB81!69M^EJ{spwoX9f_6<3H9-q4}FR8HUFIDlt_Hxd?i^sp(NJ8Gg}nio{! z37xx+A#EOz&eEDBrl-1LEq=7E;XMxWeP@~%T%s!d8xKiszJc!OA+4HdB(L5*0g10r`gf4l55~?nXkskg8zqVF;@T+Y2dBx8|2QxG8%UxrzpG<` zeT99AeT_Yw-YvG*`LNL7P^mpH53C-+>Z~&ln4=+mYG}I`9v=ADIFwfxd`AM>n;X3o zHtpS=LUgKsg*!VsH0|oEzFJwIK=24kvSD>ecPt;9e>o zV4RyjoW9xE0=8<;aO& z{e2;QdL&$I|0aFdEe0O%%IL}4tCv?(-)QW^T`(pu4`0p+DgMG=I3auOK5 z-7bVgV@zK818G1XL|%-^=`^a*B2X&-*1v+3a*?Ha4Ty;>QtR~U!M3V_^|#Dvnvvq* z4Xfef9OxZsUPH3OSzKGh6gnV?(&uI>}bt?Q{F0+HS>Hr z2m80pVnN0PdLfO1TsJG$$dnOt@*At)Q_3O>J&|^(X>ykyZ^XqEVnp#;kgU2Vt zZ1Y%ui>Zdd^{9@yDb6}(Dvf26c?qRqkvl!#mgse1WveD;^cd5BX3=F7Yf!_D)=MN6 z28B77Sk#PIZ!IA!l8WO3ca}!Rfx}|1D^v!`W=Y^%*pR|tEFuS2{PdWn#>*QPSV0h? zVEgs`J#rwIq}b7N3d>e4pxv`(65i39HnAcf4Tmj?N+{ak`y(FY%;kB^Oupw-1`gG>+Dor(3y6t7OkS*bAZea2m3bgyTm;2SwC-3t~d+4D_n1~~{gFvokvQEj!?M(s_&g0!hX`uR! zr%@*h@g0~-?CV0gHUuS1mX>0ISjJZX)IqGYJo#!A%&4UF;H!K`3e>3BmauWd1c@OB z&?t}R>#8Z2XrpI#P_M&54g%@R7?&~h{fCiiA`Hqid*L%ymf5=O4*ECnqWrOwkU5wN z4qvP4H{0g9tt-T$#@dD_f9YB)Vvv-L{+% zRmjeOp>D7)8Lb+f2k-Gc{>-UraBZSRzzP_8AQBtL0Az>lGOu8lfd@OBcoZ1eFfDL4 zad5$-me}0)YKR?|n-5S>ZNm65OG_6N>5DK;Lkv!}MkoA5(Rq~Wr9geMnfhCSil#5RAi9XKH(yE==z8pvF^}r`n%Z7=>gck8g1GOzIsDB9R6h$B z?l}&_$Gtrt?a<)w>TDF5+HC9qFz%<@*#fsxs&q4{is{hJpr_TSzQgM1p#@g?5FRQbT|d-H(3w z38V$-tVtIw56Y3^K5lCYg98mS(qFM10 zQ&}{Im^HW0AJ;`RxZ4omb(w8-~AN8c8pu|Pq_K~ z-Yg(gE+rbq1O_@gh!7eJAYFqlJj5nsP?-q9BodUnw|3L zhY9o!v>clNvov1)2|yv`Mn@{FSSboODc@i?_R;glq5w;AiOlNI7~c!1{u$;!We(a0 zB`6#d6GAeOXdl2UINhoAw+F9Y&5zj8PUS`F%PufY(B&7FQVPaAEMi~?-@Y%++b1}a zX)>s0EonCB@_9zv+`Y~_(ITqF9hs~Ne@_31Jj^p{BIC-nIE|dSu@WB)03Vmkc&K3G z$_=8dJkZ}_AHz52Y^oj{w8+_(QO3+>ZvjWK+kl{TQg;yeIGCAvGofFM+=9JU$puMI zm`FWD+sSw`VL(hK`sW@db}#{#yTaB|H_4V^SP&)-%Ph*4S{F?FEf#@QVd}$$Zq>P! z;jlV##hB}_PnOtV49FQwP0!~X{hCnDRU&&CWQVSfFd3eryW2WsnK}%~vomeL$AEYa zZXnEX)L_oJA#=d!1cS2}j8QL93qu^_PprAwIg+`H0AT@w9DS~Bsb1SB7J z))233FgMouJAbB@k*W;rE)6~oeZC~<*l@;tAOqg=uV4{TBSTwuR5+7CBS-qlxZz!( zN4Yd~KEf)9p4Lde(wgHf?UNfTG5MvuZaz+ihu~+TBHlg|63cp(Jf8_GJxUUtts>>j z2{Ah>d3{J2CmVHcz^VdE)yYXiD6$bjP)B8<0QfS44CeDy)KW9B@04Ere+T8aMjWr&}EfTy(0)gG!(9XG8f zdB-}&Yx$vi(23ipYL4Cj-SWk)N7!uNcwNxT_8aATFfnhuZt%np^7O>Ve-(qkeX6#$ z%uKb{kRlZabYDR%LWcS0VoW;SJWAG^7MD3?ceEFu79PDLwexSybF-fumzUj6xiT+> zJ}--+P96Y=KHYUdJy6WAY($@6**w$y`Lpw;3+&SDfORkVXH4gh#P1A5pCs8mAxk== zupWUu5I&jH+7hL8V$pLc8^CfZW~eHjC)4pWy#ux@XCCXo5WT`Dx<{=gjTQ-WZ`Pld z9A7YB)g!j6XHGt)GCL=o&KyXNy(g~n4n>Hc)foNouUn6T5*5N>&O;tAdfmkme_BTB zk}WV~vo*36a+ncUy1in9i34hKF)6kGjlY)5@al7Q3otB{Gtxp8y%ZznF8xCXo3uC* zLlDkJsr#F~Gpd(P+3e{M2|n1pAE4jEfZq~wfK}=2!~4@Q^KuXF^o_4s^bq#5SEK?jdXBz%z3IUDLT*)h+IRx#f|u= zopzWvCInfN`8sf@tojWYnpP#Vr&Y1SPA(+f^zC(0v9MCMSeRjTZ`e{4~GNE$r zfy;h;12&5Peed9EmRQ8Obw9w+wJN6h*op63+ecZA2B0ry?Rj;22PuxG)2#jzHDj1O zGWiILW(Z}i!l%lS3fGQ)3R=~JZrN-Dxp6aTCHc^tDCDxGWVn8)0c6#vHZlBY;_{U|PCns`?O6jizSoEBrFr{4!+r;aqI*`ex#s2arGk{e{Fos{+^WdK=Z)0GXBaadL_+kn9x;f@@aHO zZ6-1J_K$tH+*+@6vV`%!L!2f&O4*MZ8R7F3`UEHqk zNTBC{eG5TdD*FC{$(;iwHpA4ncmk)~O$n#rVCx3jIU;iqg|Mn{Uq`cOBX5BP`3zAv z**GUvM9YvOdxkvGWA^ws={0TcY9XkN9R(|@NhAe)5Fzj)={Fb!oDgACEi%J>4{$@= z)rHZvv|U{`J9y|yfy;n8!Sq5zY#3-ZS#T6>yv!%E6kkMUF9PEzAM!h@P2C;YUB>028GY0 zS^Fz@luFo+ga)zC=pw{^YlaMRZ|EZ7&h7Y&fDRl2qQ^*QXq;s5U6Yhj!@;wuo ztm*_~9+x6H9_W#}ggZ;p3E5F$K9?#v9`MmD*^yyBmn`{g=sge??`ZLDqTi>02Uihk zU!bBG4Pf;`==n2(hG-~6WhEX-*EPVM(i|$_*i7$hcIQtCHv!4})deRLCdx6dt$KvA{R_ zl&?t|Hq@JYS}v~?D&IHTP0dEcc&1&(u+S{A zPa?6Ags0o0$fX1uhS(r6q$Re%$GB=E!uEuqahry4E@76$R&m-l?z2K%ME`tvP^7a` z%JK9^Cd9(bF@PRG=pcv(4U;r9 zc3ca_*X8r`GoA*baR)vwo?N$aP@tBfGLr#;8NXt;Pl|pMeGDJ(vQQB9j#Yt&h?7(Z zqOCH*crxpf$$Zq7o4Bc{!I(lWe#~ck$m2Q^@`a@_gQx<)e3{G{$nj&#E9TQHMV>C&54s4h8{PhhXm= z0M$qn6is|k#AL@Zf#osbn`e*EanKN;#QC^*9mc3z43ReJ!mUyZ z!&-kF{DfHNaDQn&VejqEC|OeR_`{X{pJ0d11NXzOa z(B7!YdV>bC#(VKzYf-eD07b$D38omJ(t6qTWoH5Zvl zMc}H5*qylOxc#Gwkx-~*8rsr~?CHn%4H6E49Lt2^?CAV$LQL5M8gtQjyU7?8^yOW#r<=%fx!3Y)nno2V9(zgFqrWf|XX zUg)D(gsIZORKpC_-?d}3TZ6(DK_0AVVypV^1zowoP^BGICbjxLix zqFRull{q;Cc$J_cZ(y$?Fk8SmguX2^o6=S~L9b=BTfp8{pi`A593QMfBu{UeAsnxd z8nD2=5@nedm}MXAp)Ia`!ElgKq+q(KVLb8#(C&EVo^TrO@DB!E2&rgG=FG)-4@xZw z=+Vo=KMy%hK>pp`a!(V;I=;n@3TnKw98WPBO*jM z*t&;8ekFDuuL`s$k(nZa7THknPxH)YBj3vBjnkrYXk(4KIhgj1Q)48oX{TOdV@qVV zjm4>*{NQ|{T%aT?kW(^}(*aq>d{(Z@f+TVLlV8B1v`@lsPMEpU3WcI#k1+90L4vLP zc&ZW|T7u%D@uP#dZG1!11q#H1`377){9Qc^&EyBl0!C+okNm*2NOrniUbb@!48nyf zix3I&@J0?|o_adP#ksz%Lq&Ez&d}_POFB(2RWaOLCBZ1jJ+sYNZZn}SinDIr3jZ}J$- zqlmasO+$9IWE|rqa!B|HVvOc`=BX;th`qwB8PG5iB9R&E7O8d>#0#vMG;60ob*o@^ z65u(i==dkZf^q64%%^K-OoDgvwuLjl!^@>~oK2J`Ha$7NfOuWKntwO2UN8RJrS@>z z63&VBqoqTo59eVTzC$RH1FV%}{lhsP5!U_aw#W!JJ~s|1)=T{D0pHCU#jK%`A~-L= zI6~rc{IoU1LM9Pym*6u2^grGNpl39NQ67cM{B48(S~?AW?VLx)rme(x4rZn{8~jS> zbKWe&_98%8oxiGyzwIemoz(2go?xdG;HO-EGp_ZfoJ_~p37c(;vDiT18t)7VT4UN9REvZX$|{u%FcEoZRx(x6>*KLSo(u?p2z z@d|x{0@vk+Nv43)1{h5WlN(B+v+73w9HIa8(wFaMM?jyiobbQL#p%;}uQ}**G3@)j zVyi4wyAX5$G94m1)45W4p4Bam0gw&?*5LunI$>ZO!~RVrDax%+y>`UJFtE%5>juu7 zb-}=JF|+i9zWu;i{W|CmYyBsF34+zWG%O-TxGjrkUl)Hs*(VZm>9!geed$miKg|G! zm=`Nyjcq5oZ6n%)6zAHB?>i{qBlQ=rC|1*-aPU2s zD2%tLOlS)clOH0;S72b2=pd28H5@+LZ%bN2v_vHU7snSm>JxwbK-MpwS3G8SM`=hg zP}GFX2+>;swx*QoZoO!{6iF!d)vD8v*58jd5%JqvxKANcshoIM@i8+-5PsYlvgw7Gbb-vIGo$*`@NDRB<9Ik_Ws7V zeb6hnBx6lrW^vB7izCGf8yiXvYQly2^sW-uO^90#k^wlriwU1sKg^vM>5vT{v@xI8 zJdAxZk^wUO2P1xukgiLZ;w(rTlvStftU3+UI^{mwdYGG!CZCU}fWc5=rj&}3L*4G| zhP*3e6-I%3 zj`Jp15C2XQy1cttsC`}pA&E52({BA1+NE4=e0|Pp@>&-r)Vu#?_u)L=#FiwkHTiWpx?6GW9i_F|4>e9~jguqL&{$1a8m9%xIWTFLUF#>) z>lGVao||}=*bK|Kyu581R2MD2+&SJbzz8zE}F~%lSr+BwN}kNJT!` zfoWnUZ-jdFuTjq0K1bHGoX4p7$_E~Z!DeNQT;dY2nVl-HX{WgL%7u@;EfK;dh4o~H zy9=JFhJty!7*z?A_(0wwz{gXO4$rp+kb(x7UlcB`Bdm5Z@tAKE;i5*$mho@OsDBe@e zZfTa*vB!`$a(KRZcoH@)V}er<FcS)Teb8--bT zQgvf8dA>!yh(@Gyyn?@FoG$*T@HOGs-dn#eV_kz}1A}UVLtu8Ys9&_^gq>e&I!Gu9k#J4tsg76Okdj4ZB zMwrhq(YZa*I~ct8uZIVGSWhzZyzFT&(L7K2;{pf!u??!>waG!%De6a^CtS!@EebIw zEN7mcn_+R(MB$~v$Sp2#f{9iFZd}o%wfwL1Z{B(3Gw35>!O3TG($S~1e%_`*UY2`W zy+Eoabkgt2gr=iiBm(Bgz@cO@?o}T1p&S{vX%xSnCJ@%C-4Crmz*4+7IA(;qOW#?0 z-1B9UdtVh?C?rc1(z~`~G4BQydO=M7mEhEmcqr4UrO01nUbM!konNGN zruSx*m8WDNPhpp8()wHR&b3d{OxNR2cSS8AXE3SBvn*^{rtq;@GrFG}Dm=J4kYKb0#%`_BOQ2jI_np!vfZ zqJ;3F7E7oQlV2rx4y!!K%%1ecnsW;AIQngF)W=?ux6$%nhq@X+LEJxq{L93L>kAA3 zC-5hQ)Bn~NLo`wwxtWX`4ziwkc#ik74PtWp_`fK7#~@#VZr!tYbGL2Vwr$(?Zu{Tv z-fi2qZQHhOYqvFh=H59o=YD!8A|om)qP|pCWvv?{X5$aLlEn3#iT6q_05mR@X z=iWKGH|GA^ZYEXFcWY<=b%!3XP5-OwW>V`0nWn2I1vqKRAM5$Rol}(m265CO_pwyh zf2G&#P%HkVD>~7mM*Xy`JEyFdDM+uW$pV8}(_NQ$QU`(wxibsUswF+^8{bsC_e2;cHCgc?q5(~$Ic1PA;_ zLv=D1w`J+d!QBs4=`_;&w(o)6YDi4)7uETDxinj~Li(>EaiXjeTt#cs7!`6ZB=<;7 zg5Psg9DK#9NsGjWV2DJx~jqLzIUoc)Li4_d5SV{VPP=CQ?X8vVQ0 zZQAx)di#!i&p}{l1F2Dj$&yf|vzShv{e_p+_~DZT+eq4mYP@zwl~sw^?vsRTBXdgy zNsDFZUS(U>M0DKhL)fbe^ze6fqc9wmOu2sZs08H~IW^=zn7w{={ScY`whLw21-Q6m zsTs_Dw8txx@PF{L7vE-m3%kH72FGcI^tBl>4BnyUQ!C*W476jLfDZye?ikQU=uwTU zheCyp*hDMzxPwM%i4fPcCKn2lC?oeiQ;V#jFRlxuPcBSlxLD=Yx?2BZp+a}1!XPDf z42ZP9TY%AOJl6T@VF9*rzRZbZ?lK7OTLrPl#e#~%>THh;@}%PI8h?*#pq~oh^EKG> zHt0ns`qGmxnnh+)&_|kB!B06-8J0Sv)ix;3-Ea>)7f8f3^{Jz^WXCj~Ts<=LkzZXw zGCn8bUvw?;>i+X+;Z2QDXv&>2yfezzoFc*H0#PHip`Dcn&++Kj^Wku=TET{Man7?(`eDqwwCe+5tSLh z!Ehe4q3h~qS4MXk)aU847m_#i3#zZL)) zi+^sYnt5~`Q^d(?hpfYDkBXMXEu3Z%Oh!%=;eAleu+j0U=Iqw)#%?BVd&VUT)s7m$ z`5!#SYz1>Tau#dFHdZKJNG#bWK;w{cFInKX?o(`3yxOK+|0p2N+)6j0aLeYcfc}%K zUo7xBP){bPSxr2kmgA?7=O8DBvvTFg5>ftW#w}ex!jN7~2-Ja#rB$1J0UfH#FvEH9 z89^g|lAYLHY|?n{yt3#$aJ#a25bF*a*4hGa?}W9OVgj`HhBvgxx7V3(oBN|$n&djc zm~WTQhc{m3Iz^doUBiQ1BQjy_r5PE;@ie{VaWuRB;He$;A!F!5-hXBUp)2UO4j(b_B>%G^H|=g1wcdeqY`nplKju!Uyw9p(=omI~jT*X? ziqKptjtg74a@6O%XBGZ{h$HzVPP0U1sNAVF-b%cCOKn57Zh-@e8EQ+$@T6RI>CgWT zwK+NHNC5TfNMf|UE~3yr0>E5BSh+92-6Pz+;<=`6s!2y^9sq=uA(}pW;oJ~*H|3gY zlFPL(Ec{xDb+ZZh8>w&H(LrSLbuVWT_pORpD%o|o_WxW&M|@~ODooX&suw@JBwuNZ z?r_ub=visw?m}MF77xl54lHxJGmd&=CBf^q_AG1R%E><%sd$tCcg<+EtF!A4lRH4( z6L<7~9d(`=l}H}>E-U#YIF`Zn1WH3ZTuh^%lW5#`NQ}$1kaeQaSq2fOd@-d|<+X8g zWM%CQl2+O8JJvI&Bv)h~GI7M?ey>JfIKrk^rIf?8Z#ZBr8=>6)`o0q{7!m-#&TY8)w+2t(+j_T1_dEo+ zlF71u-oByWF~HfpSbBs_2rp}$;lsvp5jFR7GrAdeHW-qUZ2l64hYvhD~1T_lmD-G;x<(fmo0c|gEW4YTEpd)n0SGX86 z{!wb;T-ny`c$85qr^g8AlZfeEn)}6DgCbr zKI2Fk+UFupZ}z75+r7sWE9f2qw-ZjP$M^3CoLj{E82%GY%_=cNNdo4wZyf?(^f&ST z<9AZx+qc-CPy7VTubzaoFJBGyhR(v|p&@a_qQXendRhWq+PnHHf{u_$P?85<-ASX3 z!S9v69|JOOzUHm?PYlJ7*!jQkBTXtd5IOSnkqF-XSJ8AYUgSNIFKu$;uejui-|+vlyjvk+MUes= z2uKV1KP~Tev;1#8K$V)b9kwdUS2e!Fr3?~z6mJ^OdSPcgOIex!a^aEUW??IdW$4x{ zivU-1$ywucBxXzkMjjmk3M3(#1OZxaK7oI`fDnlv0Mb9!4-8wQPJreW;?nOX`XUjk zs1YgI>!jmk)AO2hhxcUiB4vb`3Z2WZ5oxPky<=o>xKU&MY)|76mI@>V&Qp;{gPFUl<{u4YY{ z(<4WshN3y$g=RRYOAfBMsjSot4K7EcYkN8;FEdLnY62$UD$9%tmx-(uY1IMv7hm*H z`APZ7!=FHL7FIMVV{2slb&KNmQUn4l8zM8|e1ndG(SBVw@Br-JsLKMnULrG*T2_4s zOI~s!o#-sL2G+$=!(E)Ij|jfmU?yq+C^x7fnLcY`?Mk-D++B6wV6C7I3)ihjUSn;r z=7^*rutYf3Vxt+D(;ZO8VWqNN%IiC-z@y{#c&*edB{8#Ea3qKSih;r`WpF1anRnpb zWc7kB`0=i`lCRJvB>tzw$nfe>g|0^6dxLI`8)swD<8>GgP8=a${i zncd~ot6`>K4yA;dss{TyzfVvTV^wPZn*2`gy<#6O1J=H#3OI?{1Z+ZO|1Iu~69%*W ztqNA5f!ulkKA}oLMJ$=$FHY?*h3RjN_>y@0>{b8&<`*$^axIKh?U6vMQ|NY#c( zY;hA>WuZqUJG?-Z6biT0yt)61`8u~e_(v6dD}v&oKE_BCnIW*2F$s1CMr1oPUK9jbnLuuS!YvB^SP z=j&cTN^BnN+4dBhHeLHICqzLU5c&#S6!Z4vzr4PK&fRUt!M-$Z$IKEwPHD}6ujfx) zlmu+hN1{DHml-xa%2eLuC!MPk|Ix<1R?%L3;@T{t`qKyp@$n8}98lLS&2W%M=X?$! z)R?KWD$uZ=lft-SZs=mJ7mNqJ=+bfCE}+X!;4(k7>%!w{tI+wrVx{i1ua0x;NHgjc z&d`uQS<3NH7K7Q8K^@F-ZR)x?@WC+{35bm+UJVFg45$2a9J`A?n?-S-an2KO&Ff}} z>vjO_#uM`i2z$~OgsM5v>kM+}6sAsbz~>wMe8GX=wbJ^43%Mi4>z|Q0K-cbdVNmMsG98u5(b8;>6psu|y9C|8-#HgJg;(NAV>xvi#{NoZxcd}Vsi z>R)h)fe)2LV}@~ek`Fr)>M?pI4+v~omS)=-Y`i2n{D(R@>&Tzx{c9x5HGapOLAo)5 zhCfI=419DlGlf}m8~rpRCTAd`lRt`)uKvQp7vz7293NlQcRDa2pt%23b*f@$|KA}e zNln%oTNLGMxI>ToqRF@;YC%>4vav8MW7x%yt(Cv9)wRR&3#%iKwDD|syBPaY*Q(3b zSU{rmHzeUN2oJ%e-M<{YMM?{5Ri#vLI0)nyHo9!WeP$@Ry*Bk?l)7< zX5H@G{2wkScz!H0n7E@&hSc{=(R%=FmPiK&B0oq>B>V(GOdzt3j3XmzZzD`l3?;|d zP-LV7iV2Ftc+9dqoB^AkI;PM=v8r2^*ix-daJIu16?e0y+*y;BlqXAmN3jjA!Kx#T zIz@K+*c3i5t5adAtn9Qr3P$QM!t}aHmG*U|o+Sn_!N+jy=+rS;#Dk~}5qpg+niF$_ z`0$wUE)YgxK(T3i2&TvTN|viZvf$*pX+WO$W@F@-m`k61_?u9W$Nqt(L38;zTtA=7p`_sKOEaZ98Nt(obyoL@Nj1(?8U1yYKT zDJlomh0ayD$%Gos^xC2gQb4O1!Wr!16<6AF%I4XLX6Y@#ZDK^1U~HL{Hr%G+_}M=7 zRTgNbDOIPB?R_iewz8evIkzM%LRBKlk9On!2t#;8>8{pV<|~H_!^PhlEhpc3JZ#VT zE5E0Ai?e-VgLd&J1a8L|J>;(ghXdSJ!3NSGXy_Zo!-O`egrKQ0nH7cH+ zaZlHHY`7>BYPiN)vL2%A5*)Nx)G=BP)GWIV5MCZ^on~#7lx~%gPcYojvPAT>idL-g z91*X~uydSGH$8W?=}@v>E~QJx%n3pWw~DbyVh|3j}~9eoSi{e!djQyV_v#4 zd*%H=X;86hK2_TjW3Hp0Uik{H%0B2IXPks`T@)VIP2u~j?3?oUpXXU&QE>T$%c5+a zChtxWGCO}#x0+tJtp?9v6VOh;Frg9ji`$;&A5yL5RsXE2_2?4|wP3fo5Z$U&A@=;k zU#^dAfuBU^^SKOOAo~)tp6}x8Ld1?1BrJfLZ?I;V@a@#guFuYAZ3)aHxR4V(B~(FJbTwFFy;j^mh04dranlIwF@WQ^U z&i=GgEL1fF#e#jP^(9xqC^WSYBfVZYRx-x`jR^r2V=zPgPU7uPPFu3UKoXd329#A&C7T&xa%36@qbAKv%CMpOsyo$Q-Ql?PI%RKsbgr#y6)y%F| z0dxrL0gGL*&M0(;pi2H;AFoJ6ouOYk1A<Os3N_#AxtlJ9R1mt)NVZtC5nLZI7F^K#e19b?c6(WkDdqy})BCmO_GG&v? ziqRjm6(RN$x~4PXB8lZssOE_oeQ$WkD~m?2m1JbxIz8lz>O04k#Sc1toQ#Tx}S^!2%1e< z3WTy~D{h#fm1QwQ$ma6Cg+eZ<9A&X;=bGCUz3H(CaUHz5*rJC5s$<%Z(iA#b&)QkIT!=@*)Pn~f%CecC;8 z3l_JyEPJP)QB-~AY<>^?b?nI#UXsc-hgWIIl0eqt@B|buFLTU~e|gO{sq7rZe`ejM zzgK7;h;Sq}_&mwoES1_xED&jd>zSC4)&wc&A zJ3Al3)mUo7jZ`^tQz(~P3HjjxMEGUI3so?_%EZ(ZTS1fp&0M zsr&Xxl!Y)o;ANT*R_Qa2YiAsaTPmj8dvZL1L^s4f^M>Lp9&J%aR&@_zH#T}=+~h<( zD-cHc9~^XyP8%nln&zu3^r;E~V4Yf{vHxj{!XmXi<=Vn4q}&Sb^$pNCWPDlB?el82 z6|(y8ze4}drBJ#H+4J0wxZ3k)RQ~@Sk^c`?T4~}(V~xU_5ZKBXTnMH$-XH)KUAEs3 zPKc24BgqdY!ZPKr6F(D~mNAXdzSopMAwly3!Vmh{9~EWL7>zlZUmt8b;ro7ly}|B+ z{ROYy&E~!CC_V6x2w8Qw9qluQkjLm$&TbYZniBA0h1ozk2#ASmeMqEg1elbe()*@WTXR+q<-6!MerZYfPZ8eFba7x)He_7tC760@UdX#JC zo&KZ!A#|f_(rim-6uOKxaPO65o<6E%p6is~i5o_{?B`w?qRaEPww@cp!ouUR;qpA} z76@lC~x6WdRFx2bwztjt`A=$i8{=y63FN1aWW%Ik5a zmXX~4_|VDdXQ7x0oU)+y>|h#&EH}s{I4D>)SxW=OFXC(ML4D#?$31dw=`D0f)noGT zLqI=GD?<9@zg0O~&s!S${jOq~+|JM#kzMWE=|9FfMs?TLCVq*QdW84`4b(CTkf7ny z2ezCPEMKMKwKL8zfpxP-XCJ2!V@=%Q|DV6e4*Y1V#g9o)*UxI1=|9m||9>X!{|!-4 z+fv#PL-|@p`yEISjZ8rKOra0}0t+555KlA)jmU^pfZyA7t^BW^ zz0Jn#?^z>r*QMxA?#!&4g@+nbu-t2yd3nTEgZa#i+jKT>1^?IA5jzmOg0&b@3yMy! zjo=pIzzNi~k;v`!*o%;Vq#~I9es?4z7!)1_#)vu;83X02GE=v$kX#>&naQCkj|osf zdV|e%bc*xL0bYQ~TK3Fr*2-1>g@&l?&icILpi_XX?R&c&=hN>1>tvb-R5wf}_l31Z zwtx50ddqN$IwSU8)T@g;C5ILVaWrL3=f!q5+CJ`cEmDUzFV;tO1z0BeciE=eUlapw zXUdGrR29EtIR-H9oYL zYJS7_P1uE{eFxusi`T!>=OMptG=^NRtsp#!UtztqSESmzs!_dG>Q{tg&yy!wXvuGh zJ`a71Fwy~2Uq{GO5x<4v$a*@5h%JXjf2fC}Q@usja+m2|6+=MZ-W9v$dAY(3;x+xoTMgiqUnAA+!Wq@dOs_r2w z;T6g@^HT&@rDEF>>k)ZO9#Xk#fGqfsMXw1)DFkHE`Rqn!U7u{ZA3zI5^8`{$>au;93(%vuju-ssN` zV{$z$Q9b+R4@^BaoGn@=9o{y2T6$=58@!eXMW2Girji(WuMshUE?sS>N7?R!)|y5} zk3=2)#_(7Tdyw`f+!2ce{K8YoPJtNHOtbb*5z?VgSo8K}7U_T6x`OOc>XxcPksQ54 zlYB;Lmw5YW{=Bu5yLg4{gE4s_!*DFKtHSY=EC*QYv(i6`52#U*x4|ngA*mNrLQaJAFd_DH90r=Q$O@2f|Pj3OUfHl97KJ@wjAu*jJ^k8oX$M=4DXd zhl;ef@u*DT^`Zn&P9V7Pp-5y-9xqQm#;22L4vy^i|KSUv^jpf*_9wKp{+OKoM@};; zmNuq#F3$gJ&Wci;kQ(?2Y750tQFF`B+V<+y7$R=r*n$)&x*F{{g~C}(V*>G1pXBW4 zLiT$QFN*tF82FUB61&@N(-z^Br5C!(oFnG>o@g!<~}U2cpE(Xu3V{7>`LANEA4F%eL%b8`L8 z457t010~6{4Shh|+2*MtPN=k{P&=m=$D!M%C~R~Dl{GqZEoS<6)buO^c=rBWZ^u&z zkwl%in{FNiMIU3bvtuOnBUI{|h)XhA3>UM-1=uAca;r)OCWkn_#q{q~@hlHmSenEA z1G~FpW~m;d5UyHbNLOg^h_x@Q90b5!sBxm zGxvCRITzZE?k~vy8F4nsMDhCIfq>2l{=Qgszxl7K z#k8VKG?PuL;5A)MMAw)0i0=ro4PRrcG~xq_RvnBY)hn71v`u=F!^b>iFxd z+Wx^pM^Ff%f{cUwb&$9Wt~3warQNSck*FkPDGe2r`u%L?+8D1Uci-T;opIxR(@}G$ zuJ?LL3S_l}#?N)X^ z!kC`qm7cqw{&w^E;Qh+`{T=Fie~@$J4Bt%|lM;SQ>(%jlr_b%^j=ula^Zun<;@(E_ zR3G{l#Q#Ghkx!F}06UXwF^_^esQw z%MS2IClEdQ?swoKJc&Is~F%Y}GL;DkAVR$g~EwbKRY9m{=kFb;!bBKkV(i6Pk7lURJ1hP8hEgj5mp zKUC4GQKpsZgt$|Qb*Vx3l2EsGW5zrI+4A!ni&{i+%lPCc6DA(I#88Xbe_3Mb0^EB4b$`1zrF<0F_z)nNO#Vu zaX(VnNST`m@OVSB0fQV?n&D2-yhL>mGcDp&?Lha+srTtFg=&M0m5WzmIT+NnjP5}j z%JIglCgil4YSBG^e_UZTYd;gz<>eC;gX^uWvBA^dnvCk+h;4EUS);v}y$@Ror=w#; zEr6Ayj#Vj067GA?5G3Qpd?s@uX3Tr}=nek_H*(~X-9rEw>*wDV@;|U}lG&~lpqn^o zXK?4~shl&i*(sBCm;h)A;}Hub4i34RnjB@>lZThTp*YW^T$LJJ>6?6X?(7}&Pmh-9 zuC`ZJQ>NXVlb6tK0|R+YrqzL*%rq^t?rK#Vi2n@9P2o$Bm8>ITEM@aSqG_cXW-~9O ztI5~SHD4aU{_U-pN3E3WiorPi5ob!r3NM~_r2%s~k-4T)!7{!}Oz)wez73a}PIKH& zS;aRMKB@?bL}Am>kI<=SJ&lN<$ib~<{^R=Tg*p~qGQS5P;c~)RUGe3?LQJ8V$wthN znOfL+7}UBrwQ0T*n1HP$z0SS-r6UXEiCC&7|5E;jF; zK2MWcpvfLTXUr(InIA*4&g8+_np764X$C8p?NLSwrcKOfZcvuV2y`ZK1}P1q!OHFD zfpiuynp{De7Qkrb zXKQ15BOlgrRSP}I)mV|_t#+0z`hHVCPYY4-$+pH0y(Y>jhJYM%;B{R;`E9zVGZS-AND|hz_QfZzU>Um-9q^ zZ1Rhjqcnt3Q_B@3iUSMvQPai~#p|dT9Z(FFX%&i!wMxfjGW&1R|HO4BS3n`(^m)Rn zT9yx$k1PCArd5=NZJJb>P;L6b?*RDmm>8p5u*!#3sF$dOw+za)2)nhG($2+H?aIMX zS>^(~FEIwV0%TB?qR853ZA!`hi@c*;r6?Fwv?2+wTs4FYwX`yW0KQyt0)c$BR6n3_ zA=~sT@-cjI`n2xW!rH8tItoBXfuC~l8MsN3$fQo?CTJZ3>|8u>$gCKOk% zmAKGIq`bgIH#7N?!2>TX8pm;#=73>2D~b~wU-0$nkd*1oEJ^F6G@ZgQ=P65-?l*4k zA`P~lZg?)wc~|hfNyv*7FCdfZ5OJ|h>BJ%)^i8}Tb5ZL@>zZkfop@E@lkEEYaLg;6 zHOnF~qdkY$r*zRd&M`D(ow~tEVI^(EV;5pVB$j8nf+mPw+ROls|s~iTpfUDsop!0P{-3?Lmz&R*GuBUkXoK<(!L0VzFFqcgW-q5;jX9|Cctau zu@e~7SP=%bgI}!FI~v@+tH4cQg$zO_8qT^KSEG7h@ov{&Kbn~VH*n~`^<6MKDEH*T z33Lre;qWX>0I%3okPqk+M%u?pM2IDeZ@=gphMPXC^HXJ_lK+WV^r>FVW zYeVv*sh8IyiNftjy}VcxJ7ecvX#`!B4$)2Z1ShH^-u&LqCoOaOueOKK%Pf_Dotp;* zaMibmGJAHS;B!VK>=Xc?Q+J8`ei5j)vl&rOS#(-IbVcc zXAj)1M!eer%x|bn!406&m(_XqI6w`=qR$f6t#yEkINltc>7HYev`nwV)Gpgo+zjGS zk6CUEXa)=D9YLTlLr7FUA6j(6Y-*45U|lHAC{xE~?Fg#XcK=3b;tv0P24es^Vqqh# zearxoA7#Z)YdlMD6~^r6wZB^HRTp4Y^^S0)i)K5`9e|M^IMkYv7_D6I$ah0DDXj_K zr0N}d7cJ?9ZI!Cw3N%vo%ba`UfgXX*%Qd9BUwlXJjmK*%n{5VMKZu?L98UFRxyfVb zQW|8NGEqJ+ztRyZVkWoL!M%6GbG$(A)neB!G^V^*xGs$hWFEyb5oVZTTr&8Cw>1B4 z34pzPaJ3q^(~s7_eg|h0%Vwl@0AA&nVpN@X3c}Us+F`a@m1Lf^J5|Ug3<*mYoG>Zd z7OqPM7H}cAq}!?s5n0;6SU4b>sY~7smnqm(DLtL5v|L1u&j-Q0d$CNv;d1I#=Ac!< z)ee)%^>7Px#xJoAKlcK!oFQKOD~8Dc&*U`6p^35t*V+vuamAJ1)Uj#p%pze#+j9RX z?wn2QGH^M#puJ#9bwrk1#qAVoU9Tf!dfHX_z#82<&<>yY4l?~8vdSs2?my72TS_Wc zNpxPxpA&G=8J!hT(!u5|0YcqJ*VgkU?r9~as*Rs28NI8`rZg6F7&Pz{S;IAx(xnX& zk3?LU+Wn+#L-!-@2N%qTCQGFiOGU#ZIyC*m2dJSQsSNKl(NnPE19eS5JrU^c;-T&_ zvqPxnWJU5Kao2b?_rh5LL(()Vz`I_R9$C<3!x@SPw(p067DMnD!u%#99$}_uBh?M%_RI~F(Yn*HE=I=P2;X?Z)6IXm-OG3|JZhVR<&_%&>K}_G7}=`D#J3w@sVSn|6(`VX!M@U zlnqV%o1mxIp~v*<$zSo2?dkfPgwi7CFsrCnsSfU127IaJvsoSf(x!8{E;?>E3?7mt zc6jvu2`GsU=Ie~$4h!CT;qA;YpGZx6wveWJrE_WgW~n1>ZVrFaTFWl3&_E;EWDdeE zR(PjTqn62w9!~AeFBa3b`J?ZYNU+qf`cA3NjXP5grHAULPb(Ux6^yM4i?t+Wt-@~5 zQ0~H7TI77Q5Fgi3F`=fOBC8d^GfjWdxQS<7Soj1xg!SZy+_S}lScBaco8BL_FqTAL zePVv|55=(68pcZiUUY$wC>Fk*@IKe@n}F0L?T?j<^5u(CvJOvYS-M@5r_yTJA{t9HzQe^}EZu7l z+##FF1-fNSqqSj<39nagp5sW4rRh*75hAfi6x)AXU2afQ`Sr%3Y-^ms48Xx~*zym? zqdBclO1%bd<^Sr{RY#kTal%?+xw%1?IkAL`a^`>%#dbw~zEfJzP&1&Vs zC43=Ps)}Q38#b2zZeId=Q%Ou?3LF@Bv_acfpk!lCh3{ybA_<6YW#isgL8Kqa;h$AZ znMrWsI)|bRa&ENDSX<<)6c)10K9q~0LRbvK@0+<`Wh@5B%!f$4 zvjp52Hdcsh{FO6~@j%Hs7iOvD#kn;9y~yPB75cd{Kz3L}$Tz-a*7c6zcICm|r(3e^ ztpl;aH*y%1DZ=kBKhJY?IpaH-xY-bNjxtkknNYy{CIclh- z(d>N#dOzWM3F`ySog+2@I{w5L5-t28vi=#=g>%QwS9T$Vn#@#bqAM%EY6Pm;nkz;z zyhRg08O{_=F*BsktdXqe-CeBb6!oD${ zUs`pod~P-hk=;MD$mN0z^?w#@$a3C>7yP7ge*F|}@ct($=>JLx$k-VhI$PS=3ftM( z8#)>~+x_p{K$gmkJhCFf*Y+0y>gca3$V|Nna6C)5 zDc6Y@{-K272y{9!;4sGFg1Z=|X;0nWRS(9g>B)?=&*OJ9{kMme6g!~f+tt5dBSP@S z?UYm!%(PRHEY(4Dlj*4mx({S{sTvG-vHlL=HXRazL44k`KaK$ zDfG-3R(;VUv)V}AKUESnfIVrwGDR|7sPay=XT-Jg_|^!NcZ5oeMzHOJzhYB4Q6Mctd%+ zg#@2^doK?G3Ru%3VbYJ5*e2!$#<^69HnC|;$1(@szGe7R*R7!bMzx^mDROW=+N|iZ zIlXcgse^r}dZwVb@a3O=>XgLdCUw^YZfF%kZWAWUKzR$@p%QbJ8!PcI8yEwPbU|!N zorXDTS^PJf!Xo!T(crIULbhvzK*KwJeq`aDoi_|{Zpgx|8;?1#{@@->Sl*eEjpPlw z}1a@;4gnS<&VC>|4-a>ukX2gER+D3C6*X9k%>?yMH60)n~V zbJv9ZmgA8`0l>BueZsW2fZ9kVmAnobb$sQQUs*l^97kTkKHv=k+XVD6|47UZHNkEe z=CeP5loJN!_Lc7Q6AP7uE@FM~r8(Oc8G#cnDL!>gEcc9CV>|(3PpD+KSe!+q8%FMB zq=jFVTGpW*D3;z8g@0(&9(mM~9E-aPDgc!8@S&5wc=PetCj`OE9W&1%L;f}&O4 zbIZ0JRW@!NTUXcXZf@E(9ZfMdE&n`yo~N@U&5-&}8ooE*Gjz{phVth_XpQLt9R_EOiKqJRa}o!Bq8V3qSF6|Mf2APN+U% z95)@&r7|Gh>4ms5DolS=lGAIlW5qG!hS0T-y>IQ6F*{>)pEMIUqrik zepKa^#M6A%sf*?|nwF(!d!UPFo8lHSoyFzm-j?C!Sr+gND9d^tZ^pxXJnx*5_H2`v zyLrC-wFXd7djmVD=<`bf7FRScC@2%3_SS&cE!R#VXF4Em=Uw6vsmP1M=y_^@xLf zKg?iN!{Z76hOwO*M8KT}3DZKrlNrt;GU5VGveOr4X2a9IhNQW+y0-jCvrR{u0epHB zE1E0`$ef8jK|E8$?nji&5ca^Fy(99%L=$@WVbCwPUkbWF9LysH)iGl~&oZTrbM-4W zP_sIZMm~eXi83h9Awq)_dHVx2d^QrQ5BC^&Dz86yo*?=q!Q9t=i)|R+!6?WiHQ|Z_ zi-W+%2{_m0kz>M(L$EJC1^`$X3NcQqm{d_Y7RW;WnE*y3i{cGXWQGpRSkg>Ymg3@Q z8F(%=q&i0;gFOcNBi$IMCW^XPkt9eGIpj3TD2wkqb^8s0B?<;Gb3YQ;?JDVMCdux` zvu_PpVr7OL>|L@MlyguhsUL#WTPxduxXuO2Y{(rHieJG-pPnbWkt9*sNUrT!Oz;M@ zMTutzJ?c>B2~xv@YoybJ=n3J9Pm2)9ZqG>?>F`5~^7E#FjD9UQuBshDZf#T$q_f`v z%--gsx~8Jlh*HCAU^DKM)FG@L*NGw zCiZS$H|o$B3p5t`0jKA=kn;}@QGbZ*2x3AT7CDlXlyMOa5$#{aRTA-3lhd^gGzl~K zt2V6!`%uAlc#eM4&dr5&GxRi9RaFz9)8ZK28)BY7+ujBWZ-IC>XKLbZ1d|_@9RuzmVn8m8#_U9Lx zbStzJc84RH=dm}hh>(R5CFl_FULhzQhhs`YKV$UcawcNcS4Up|3Q7i?;$Va5ROZ<; z;RFy^nFIMZY~3fv8$7*~LvvMCs{`wF8>n@K_m4~3(cS?J8i_MwBWr7CKiq4!d6p`X(Xi6~*n9FYSdfms z2K_K!{qs!>5ZYkLP9Tdg5sHhO+9-S2~;jjCx!RIMW_)Oqi51&5pAro z630f(9OlC6mE@>Ao0eqoBSIVd4lbILn6+bO(9;i6vC08vANj;=tCnO)<9A(gnfMJz zQZ>se97yqEBPk{IU7$uoK#+l{>G%F)m*pA9JQ>mGfyS^lTWuV-w}aZwZaio#s!>Wf z>>yH&VAFHUi@ko3UeD#Isw25|e)tf?7N&`zqD}K|r-aCFLt^Br<(T`*h=~P73Tzip zj|(0BB=4S{MrD9m5w<{uBDI8iv1x3SJarf@8N+~W0Xvpc*}yho6c!4RVnGm=Qm5Hn zgah%vV$OIBfLQno9JZI=`d0RVAwUW>bke8mr?f-Mh^;9Ej1SRZD4&d|JptR4bl@E0Fw0XyS%3$Ne-c84t&A8-LX zW9*n-%sasM?sFEmRo3TTo4amz9WLEdyBnN_x42BNcmX>T1K>R|J9f7ar;J%QEH88j z1?Hztzb7c;b7^u=9r!J7LkI|cQ~C2BAOmiWJz=_2nUTVZ-sPfn>QMgsEaIY|Ow$SP=7sZh{C)^9KKGaQ2+YJkB~+7+8&{XgpT(eLFKw*eC@2 zXalsQ%&2zO&E|T0CpJ#FOu7&f`cl8}0Aho*_hzbkMouuhOz%v(up?`YG#F8sByM+5 z^`F6MczgL{?6itzStRqV$R74S^-6hk%_BE=rl*JuH+S!bG_ zbD{2BO*cVl5+igL=)uJxtF$(-;v&Vy41P<1Q_L|-5bA3~Yd0JOl5V-GpH-=y`uT{+ z!}_pL9vEd&49(1isNh+tm&YX@0_6HR*S+iROC{uKfGGi}QMJg62Vk)tlf^puqTDXC zS0@~%f_jba)iE62@iwI`8vf9=@hh#xxK^HH4p|}?8N{%xP0L(sRbG8Xea}rj&#{>X z`}0Z0#-H9(`DNtQX-e-sCCln~Xew`2v4PfO@!ZHd8F?J>h+ZQj-fAv)wZSoe54VL< zteI&@AcD*`Ri_Kp*0E&!Msk=*v-n(s3QLYHHxZXf-002@un4TpaUB=Tx z?_#6Wp0s2|D`qN@&pKJ)`?d;886StIf9gYlqfmQoNs$FxOq!r2a!HF-GZOtwhKMSO zB)PVLM2Tt&?Og*j_TosJ5HuBpNs6PC{U+QP95Yv{2>*E;U9Pa|tLZ>2VhKo}mFIy! zf!SuC1dSn72<6SLd(d%J2hYqK`Vw08Wka+I?^OMp1&68CZq70~nRPK%d$69o$dC%* z7O)uVJVPnF2l%7dM(*}0&LVad7$a_edEK!=MS$u!llr+a9THm+>$P;JuR2c z8(7?2(j!@>%Hkq=#Y|8Biy4znb2jtozGcbvvamOA^Hk|!y%(-v+uhCcz7=(T4) z&8e-|h*m z5sWGhkE~P1R)l=4I*I%OPv<6|+h;zDYBhZ|jhd8dyWA`e4T^AHdB>P;U|PqFH?cS^ zf4<+TF2Xr4OT>1B27sUFKpZauQQHFds-;MgwRSTHoylK`!y9-SLlDeTO zSNsPKD+;|89S6Nwlgr)P2fNO?>xez+RA6kDcgHtd>)M6iL36~Po7l6U_9Y(kKT1&Nd%4N}!0I+5o3M2DQaflQ0?2CrE2iYDe z_bY(KrlbS~+;b1g%EEtspnzd4w{Ahuxa8-6#q^1Ybv(CjO{@TCjub97Vpt9$Y6^L_ z725VrP-9T&fOQi329F{}pq+E}uOO_zs@BfseOtEv4IL7FsWZQXv{&``{;=8B%|gUr z!wI#3E!ATFaNcLKTqGhJ^@;*l!8$Q*8+(dd}#* zk~RAjY=-oZJMmpMI+A5n`z(e*-9U_X2;#6wJcxR{cJz0VEnO(6DgXX_S0&EO%l4VD z@b@HR9)puX*w?Pr|Bih5g3X5NM zB}1Jc(`^YKoe|3p5SjJRt1b(0+rqfD?|jz|^B4bDX=ede)zUqDLO_sC5l|YG?iP>+ z=`N)XaNyA0CEYD4-67o|AxKJ!bPLigDDiFHd%a${`o7%nKac0xhsQI&HM3^c+Ozk} ztbxInUK*4W!z{|^iVT2Dfkov;h=_Zov_>dkT|LM(pJww$w9AKClo8|Bu^8h&Y?Otq!+Z z@vI8G9xV$Dy)9!H+h_5+G7ol9qa&{ylZovWTcDc++ z(A{m}*WQ|DwDoll-+3UX8i7g}HRgG694@I{1?h@v6~z4Xs7QM?cJP3GngX4NY;zT| z58a1U3A(6LLPL$+CS_D-OXyDFid9Hx&+5}v_{8|IBH`Vdy>I$!m)7Q6b1?Q%>PFu- zROw3E=vFOz^Qli;lfB)m+s)YBW}6F)Xqpr6@maVGLf!&V>}z;df^>H-8|%}G8`kbf zW-v@bg$R)Djanl>O}9Ej-+r8=C>_i5B$fv~=8u0<=M!FMK6dbP-*Os1ATXHxp{gxuWLCIB=&q8%R3L*{H+Y3@6iQ%D>zpAH+u&? zDS2%#c4Xgme=Ce{lE|f!=h(PrizJib;TY%;q#WclnAfQ8^fuIK8BK&5b*ti|d(alJ;$iT6@7s`}qHFR~U# zE10_5Wow?__9c&;6%w!}Q623nmGis|*w|3MH$OL6b*5P#<{?IP%EsOA zkzsW5egNkKs(1@@#oAgo&sx&mSRHq?o>q&8;~oP{pKaC`_1G|%BsUJSQWj0*d)+l- zed8CHT>_h7qmR>V;%MYmKUMVjt;P(ox{N!dXg_bK?~Ry)_4ml|sD|B@;i(&+7*EnR zOd)^3JPV$*RXK8Io_0N+eyM3yFihH?hBHZ9FHF};^6{N02IXZ_fePU9CRaH~+pbDf^ zOea=V5v5`pFXyAOn$=$Ccu8|ka0?=r`JezwbCtSgK;As1IN2}dQsy$f{KA9#0mXI& zlSTQtjY5rE6fQ6p%Gr`L@VEEK8CU7=>~-2LML1I(B;1nR2NM`)S4WyuNss24b$hjR zN4^exR!spZXOKrjKgBq|i#Y(zjep|tgue=OjzJwzq&?lOJ&lavpi-F)R$aw6;dk`o zMkTG~mQ@@FuWuLlTiLhYazSNp7#J>cez5-rhuZ2H5t#)GcOUD~iK<}5taBi53VVjy zgsEx8Gv?PHP&I8Mq&CR4r%;NI2bqiU?rr&qx>d?=-ik?&#!N}bDH*L zfbA7#x1pezZZdhH3eppSfXqPVe=bEWj-Hbpk;Cqi9Y5E}WL)lo+CvZ;D)vzpzI7{? zSuppGi|11mrn0HTiMpz84dG{pV@7UA_|IM62peVudH|>G?j<*rhgyHp(MxpQsjFFa z-C0eYy0|!4!h`B-%|w5(po0EY*VlmUg>@3Sh_(MReK((TgJ=|Goou;GIff?!v?H~^ zYZF{$O^(o9nA-_qr!3IC&Jv!j5D~ZHN6KT=G@AC>96dBJj%Hh-p+4y!Sc@L2DECep zSiMo{?SI!&Kv188Iq$St`SwyHa5a+DEY7mUQiY?ke?~*F(4x?{Ky=M9&g5C~2CD;Z z)3MYHrVhI%tEr^O%$(vEoH6P#>87mFesAzb1KV5X!km3!nj+PzM8l7cdUL5N?{s*a zKQDtvUR$Yqrk5KUrTDFc6zge^AoqoC8Qd;ft&RWKL$q0JP*qVjGkdppUF&U*)C!h_ z9&IXDT>#hPWXwKG+JOe5S7WYxZD8K5yKk<BaNb?8R$JBh$EZNPuA7u4N>J`cIxs zZR)SpB+3_ZrPJBeJR4=VHF2q(=_ePIU_`}7gr5(&js zArv&44Xz!G5kl>Dmwa4{4{@;AJPF2%Fl^)gQ&`u12<+K@Z4ETE)AYD!YH8mF;X2Ok zjAu{`;&+coCdiqEtzJFkM2p|8L$-R^d6#%>8m@u?=Cv^<_!h1R)Bfv#01;e_ig*#> zt@gf$ho;Q@orFDTRKlkOj@F0_sCp$RAKpJTER&E3!GT8y$5leL-R21OgSo#{pr71E z*t6e@^)aCOc|b8eNvE}ce9Ov;k*eS`rsnvyV-2BFTf9=iE}AfZ3+IOrR7ZTrX$CqP ze$75+g8YQ}kMrZ5bhtBboy_-;kGE~Db_bQuyfu>zM5r_)IK9&v;BbnZ#PuXxxCov=S(>5pA>X6y!?>PvBOWV+x)lNP*`x_h1@SWK{XOq!?HisB!~xl!=x6hwtcZXYsb?QH}+OuLb?3dm3>JI-%cqQ5wbb z{;$sxrktiGvx-|g#5H4b-R7oE3`nO=yDy>zaFKN##*j1wQK;yVOvHk`o5mDg+DnaO z4;RtUb{k8aT5z^*PqU>{*#OPX1{w^<3iZE1X^Sj3N8j)dxgfn+mR zAcy%ezQT@5L=Se#250$xn%d-OOTY;2ifpR-E%X`SpKotFJlNXq`a3RNwf1VFzhu{PX zA1>ismOAVkZuVIZMd7>htvZLcim>1?kb*t+5WA}(Z&!M49^BAvk_vK@>?YC;$7sDl zWZM!+IQfCrCrwhEQNpi^svhy~;C_U`70RNF12r5~4!%#w7#~&c!ZLq>l`AGg!#L^e zCZ8->d_0ovqE(`rw>BE2KQcnaZ96L76}4@a0wQ{!RboG3Yog+=+`1=2UH1*ULroJW z*eP8Usae%#1$!XOlA3oszvfbwij=ZH#Bt14xA30Y3Vv8B3VdN_Ij!a@qzhw*&(N1I z!Eq3emg=Qz)2k&--&aK8`_Txu)1_F6uw4@x=m}TDwQ0s7y0iMOaUIm9`qO+2Y@Q3t z_hSs!aOvY18W9uJ2Lm+-^a(}^JDVe%!P$)^L()r2bXln7L!u+g>khUUDHHnq@AYjLHf$&R~VE=^& zDjn@3M)mJFq%k1A$;Mwh0LQ_ygm4*4k~?CEDWR>ORoYC5$@!`GzDY;C(7Oha!b(;ReX5u!8oT^K(p zc!-7XG92Nf+Ulmmxr+yBd-}oI>POB?4U3nT%(5~ENF+y%BJ9ygC<{ICISDC(lBx4s z@Q9S**f}lJKIF~L_ZXwf&=(rgK13A}qOuR$?ob|^s0(dgOtaU|Jo(@Vp}zOH3=3_i zgY3)WL9wMWZ9>A(jRww9(lgGC#*(2vZj_0qUGPl~;&0wMoH+6M2ic}6 z)O+?UgK)DgVrSH{8-*_|oAJ-g&eG)hrux_GM2ioQn@=7Lgdkr)Yejfe820yIrD{yn0uFUbhk^(Qit%{8viA76}R=v z!8g+0O=9{FUgz;IGkzr#n|n3syy@8PMIAPL=Dk@a5?FTl{O4P!Km>_27+9QB59|@W z>G)RJ77VfZenxYwqNXgCAohhH{fq)`-b$Ffd|`~4Zfk=lZ$OlB0VOHhSDo@1BHi_J zp<|f+il?;Xi6?75{N0W`6?E}x;yTfMbA1UcHq9(^2@gD)U11r6-_qZ$E$Mr~ECQme zSo6xyj1jqK2oLgA?0IUWt1H@76h^>p&TMNj@k}>qyujOnB}54_hmvJUXYGa_c~oD= z{C= zMpLt8$2PahDakM_)Y1>LB&+TrGGr+Z-)X}eA{A{8AiE^8_vy3J<6#io1@Ht!Qv^LrnP_ozZLsre&{^nD6t`NTO%k~lcN zn?WJ4{tS0w(~bBc8bcI%;ci{gBtveUnRcJoYeDnu+jsB2N%MNVjGQbqE6~C$bl2$a zMa!Un*{;_8h;0*!r&-A?mUv%~r@NBFoM7)b3V5fa-}alf)F1X4%jT%8x1JVgwCS>d>*oS&+ zC);|1eBg#cF9(>yN1dNVj^$n*KIvVFc?w1HFjmLoj)ai&d!j=$-Ip0+#)ko)QeNmA z=0h9C5v(!h-V;yA)PPN_^B<7yPL&64ZLnt@ch$-8!xwnzpV+NYEDrMS5h-+QOq_*; z?YxxR#re$PGI)@nZ9Bv}b}Li|Z$jJl!KbzCnKuk;C!v@Z_q&zNS0op#G2P%)5!tXU zQSgjoly`1*f4LTTuA(rEycyVK#!m$W#c;!+-+%h;pPQQ1?zk$BJ6(EIZ_)(cfhU0d z6zR!CY=FOqgq9S~#2#>$rwpYt;>ElDDmTG6EeZJPn4It|r%H+EpMA_XCQI;V63xIc z$C&#j4TE$WsrcFzhFg)-(D5ceC~ykB@b6OrId2eX}U|q1QL;u{da~F8Qm&q^((mHkm#-Z zMUg}W6QASY!&!Ui?fT4XHsv3<%#?@sNkmhA;A&(Kii`bf60UY`~Chq4SQmZ4R$;nR0Npz0~ z@7|pk8RvU1CmsZJebtk&vE_^i5Yh9}pEwVNiN}{FhohMsP7)#`^CDhd%xo8B#g|Mh zqps;k@s0kZ&cbES3Kn%-?@V|Pwtj;C*89*pd}w^y5VKBaqtBR|NDc!oTP}s=s|Kkb z>1!_Y7g1%7f_cuALKtIV?i@!QOqhSuTp zEVCRja}ZxP9*Tj+1{%G)WYcvQcX4J3H#lysm>G^5KOov>S)564zHRhqQg1lQnaA?$c;}f&gyK!l+5nmB+Qpco?Z0_9VqGR-}%dg*~b|DYPPfD-KM4+$pD=489-Q zC1D+QrkSg_1Ifxp{kW2XZ*Zx$WZOf(PJmVP@V4)KU#aDXO|FK7jE#FlcNyCsC5v>{ z`{}J_a6Kuyy&Adcb@^%pO{Q>rLa%@*kbn$01MFU~1BK9@LDw7I3~4nI;+0DkWQ~{A z0pir$ch@94``6N#7ih!l_FA~R%B{yu0!%wM)0jSXEIv9O#u931iTE z`kG0PYQm|#KV3YF0sFCyCa=BwQ{QD;EwMQ;83c~A%K+6j4ueN@-)AUg7BhrWpD*m? zklf1@X`J|20i~0kY&x<&IMGM5_Xj$3ylMn84P8r8VP?7Sq2!LLuJj9`>Q2KZ&`s8{ zZbsEM!YJ5qF*gsFWzL1AcXz?y%{v^7x)KN~by&l4(#G>Wqj>WzIDA8VyV$A3gP z7@<#ipx{XlS;(NJKD+~}_BwKQWywclUPxu)qnbYH=WOhG=iKz-{$Vb=xI~ELb|H&J zVH{o#q5Tyt7>^(|pYOIO-GP2(&7nMBv%%?q(D-sBKK6j3af854tF<;vY?t~do@(v$ za3F%+=O}aOuyyOF&bD0iO^uHI-f%>!d&xQ@MWxt@$%89d)9Jk_j#}{z%Q5s06(lSq z+F!|^c2Tl~(dv{PBJvh2fwewlKL^iaKF(A;g-t|WXC|iZ-^S=bvrXX!!m}RqtDUlLl*wJwF>pu)9CgbO8xpq^=;kdR4z;` zcSp&Nmd~N>ZW_gP^6JqwgF|-$+^Yl)14+kdQ#(1F3I|>soa?u`TZGc%Ef?2M2X}pT zVY`TBJ1o7oE;5^A_yNy)eJ@hZI$*%;3r-l&r5UW?kpxGR#clB=$qF!&q7SM%yhh8? z^3CjHdbUhX&!^1@o>3vS&E}?hRbUpj$CIe^ z&d^@ZmzMQqhD2`&F1LIRB@TD|L@D={tA>b8d!031=p@hTixl2|=}%G0aZi^<_rSa* z-BWf>{*4uH()2~-?qkYYyX4 zolv@V5AsgHa#%rPOucl&-K;ztBxD@)&(7n^opEBk76G*+}rQl|e%1 z=h54#?07-F`x3DTaCye6GGe_w3p0sI7G%*mFCkAqOd=jJw)Uv!3k8}XWpNMiCmE64 zkEPRr962A%r{tJx8>t-{(B$VBd&Ea3TQAAmHNg79@hO6{ZWRWYh7tslkmeo75n`j%O!}eu?3S|?=zO-RO@qNJLo{)&z{c=g})WwRubrrq=S!P zdT>WX6y?YeM=BnM!0^kPMF;y2MQ#HnMmsb`uuaBTCMS>iy3L==;QO zji|b^PGazx*rPGo7q}!S+V>&GIjG%!L?oC)*3;I_c(+5ck*XL

    s^gkBc*=uP)AT z{ZS!jR>O*-^z4(;7~k2n`r>|x&Pl!1;gzh6j1h4)P?T~t6Ew4wbm?CHN<7Do_gg*t zZu&2yMVb;h{g1w$!D+;455&G8V-h*Uq`FH%#1kL6e%3u38XG_gm4+=+(72Q*j^nEG zJ`rs_+&6x#!o9*-#TT+FXbEira$#tB3=9Tgr(ChnUug+O0;iM)xn0m$p01asbvWQ; zH;t7b8mrEK5>vNG*+SO`Jey_gT6l#Vt4H<9u#i8~I&mB$2bf*>M`=A4BPEuvD z8djV?vWwa{k^v^zCL7ZW#hwxQAa11u3El2$2vFRGy1$&5QR~|@$u_Q} z=fW%$(4{erh!Xn2D_9|E3ziLOlZ5x_i=ArX+4ct;as)?cwHiGaqslQ~WOObfL3l&O zwM1RsR!WuQ{63PcBAZJ(>GKpyY_+aqC04Zc0Y|E3wec>&U1h@3%7upcCgOAZewZG1 z-JB|iTJ?L4&oMMNBQ)+z`3zbGFyB#l;y>i8X$50ei$#QsaP!q*98V&O+Z)Z!J6^*rBAH1TY1c?S!B z>zu>|r1gz(vVkJ}SY>4>wW}0flCP9!v|_Z}kMnKZ3unpvOfU0n&8>8r?9e*Y1C}1O zc=^s|JwziIu(Bo)t#w2rf^UJXyekK8GYdrc$V3RSctc3UcS+Ci zBidO!4On{b$5gl_+Pfs=ydiq2ljjKE?ife8OE`AH+Z=+o_lWN+d^2(ONd}~|w;XFc z3(X@Lg&I?ahe9mhGeh)MyQ0dpOX7*5Ni)ZavqFNx!8-C#4R^r6@K<5UstGf*5pz>( za~|fcYQxp)V{lCsXN}#{hOIQ4Dd2zZaM#SFdT8!pMUU=}EA?5HiDa3l9BQuDk1)S4FMC);D$<#_T4+F@SI{?^ zND*d0O3kL@k|GA1zg1v-Vt@@V+G1SU_RH6^qdpd~E~~!SY)%{~5AR23*kdR7aSN-g zA|`jdchb`NL>?8qPOMwO*HiD_=&MMk>4Z6|hbTG@p$73BD5&ix=gxSb z(A=#rJP!%rJ1Rk8JzjE9Z0vRX2HbO%=#^2K9Sq-1 zgR>uq7#2$#vLU+NXNaIpf8J;ieM;tDI3-$JlHou|751^f{0m2Ifi?q#=HaZ0hO&n8 z{=>~ed*xVj^Fi^=?(oc<$7Wa#gQx{nR?`XP2-UWmbw{7`Q@=^B42R+&R#7F{7TpOe z@}^{?j@NJm(ZQ6XZY{Q3xzAA?;VPy~uY!;-d9w@Cy;WZ^44Np(@CER<_4ZXrS$R$z zfu#KL#XhYiW|N^f%uBtX&QP`=`Fz=7y`aiGaoBLo_T^>xM8#r>RkBG#P(!y$fc4r& zQ;;PCN{$DNXaj5QyLJH!pN)IC8spxr_dVW5tkch&JdS^A-QQs+N>TDIcy#4;4;oI^ z4zbLXtA!zqFT`KWKJCdpd9sGrqV~~W_$q6fK2k|@62FKz=Opj1)z)C1DDb=V=!sD2 zJ9K5a2sx{JS<|z-dUA(Glc=KZi=3oKU`zRX_qgV~wvUBzo0srpaY}qKqU#n(eVI&k zW$|uo-zblJCpaov65Q^%WEcBvj=x4L|I$WBY7up-rz4b`3*q!yh_hUoTQCg3ERgz5 zW6*0@SeSi}HB+oI1H_=mz0~&TC}WXGt~@r_AEMMYj{Y+UeP*qMmBcV)(=aI~B5VuH z9muEOxx^}(hju%tQez8tnDoAAbm+IGb(Y4&)!OcWu7JjL6z)>AHhKC}_|2{kOGM!P~qMrkW5h0|gR z)UIm)EddLw#dH;kUg(|-zH-f{!MUC-*b+|Xm2&kw%1@9H>)f#OFnIi2Mkk8pAuGNW zU1+neQ-{7kBGGGAh2~q(O{x|ps~Zw8RssuXCObKoxj4Jv^a{8%cpHml%{KzPZ66x- ztS%O>)@eF}znIB=E|e-G@wW>)4&wD$$TFLHxGy@nx=l!fA8eZ|X*?vCaps{IUW z3ArI80V;aG5pB9Gs_YvLoH?88^E-|iC7M);Hk&~UwK>z(rrYE7dvlL_wmzqRK?-NF zp9|)N8E;zLn6YBYt=6d84{4$g|Da$O8q|o0M$7Ki80_aq993m1)B2Jb#8t^wel}Rp zTtf5F2j?mjy_SlO9@`5xI0|x{m`LPS%#R)x$&X&I6d={ktu=KO&%+rb5k4%i6v}(3 z)`jB*`$er7Mjl@xBTJJekmXc4Q(*tBz1(%N-_D*bvN$@#y50cq!%O3;ARrPw6A+0W zpED^oZCehAM2~W@0mH`wM552<6s=kZBGHezMqWjtpS+4h|7@Z5?SCTCm!iIUoYFn5 z`eeoih(xcbh<_ov9mnhD04{|Tj2T`YkD z_S<}>V>w=&a}Ms}?~*)P4N7{@?!ihevNlf%lg|iZ#KDiQHG8TD(po&W3goHuB(&`j zW5iKz&!=aLT34A;Xi%c4;yK~cpwxSn0oo&bLAfZMW@1%kdZ*ac)`FzyZ7iKI??g`i zIz3o^Y-Tva8F#Fr<4l9M@GVSYV)k=T#;PK3BJssX`LW51Ni_PEpAZmiHsl4!?q-}M9(ycMFj&0mOsjo^ z%G<~3Z*ZTZBE|StW}kH+D&{FKtLXBVK~8xn!95f*>4?mLlc+LE^d~V5gocf}9d9Z1 zWh9R~zJ>4xvTtJTFkO(hp!vVGD~}N7K@F^VClaN6LM@v}y53<0M9+#M-;fRDk4_=4 zw^Yz-XUZ_=C3{AxDWS4aSt~gZRW#vLCiqF_wHPg8QgXJFrifKwQMP&w$GdTInKFG> zVx{tzx*e|qQIjdxDRM7cD;ldFm!Gm58c>nsmg>i)BD~u)A_a}EMT+(QRuf&~6ASWBQLj%JWzC2d(BMr=337Vpgz+*M301t*S) z46DFBv;37F?sT(B)M^h4y0$##%)rJJoA*tt?oh(uIt0TdeQiV=o;meG<`C0KPXQ(Q zYFKi+zz5soj)4j>13VymR#&+iv*1b7Qq8Q-IPT9%+3Cx25b-({THk>1Q}Ja>$TQ=l z_U=@iM73c_R7~egVG~I+y*I+h2SJZv87~E`K7KXtX_KhX>r+o-O=()0n;Vykj^i8G zD4@|S-iyZ8+Vt*oe)U-_^M>35*^nag*35trHlHo;`A?gx8t$1Cc%bIo#CaB5CPCA8 z5BLi^)p0Fcb!Fe{eW`_@wAsJG@-X!fPkKp8s3RxyenF^qhmsVI8XfL-XDcT!smudL zEt`iRb-}q+#|HV=bAsp)c2Z8-i&xJA;q*P&3E5dh+#9+@E{XM*jZh^e%w`IC-6H0x zzkceKhWFJ~5ZrEF@xz;U<#9ECJiT!HD{TFUy@!|UG3w8AdP$*P$u>X>x&j}u|7%NH zT3Z08C)k2PHf%kuNNtSBP=hWlq^~PL!94GDs3Ox}M_&k3i{{q~m)j4wj0cZ*6~g1P zOA_ilVjS*VERctzSBKIxMkUfyB_os_C(xPMoaw9dgY>6=`L2>bn&G4Ieec`AT1p3Cu+IJ$4hkyEtMeu}L48}W zJ=oUir|IV(YX3t9=F|g?DYUc5K%JRAgZ1ex$5^QV$bNc@HaUE_>*=eZ=D1#RU3X0`B8MtP7#S`2B z{=|t~2%>9aBcp2u`gQ4j5?$BS0Re)50Jfh5@DSZlfQ^kJ2m;doD@TPE+``TG%?!_^;Ts0Q=`2sX%cvwwk4`t?{qn z6`|U=MgaIO(B&U~R|;^=^4g=k5&YNKJjq#)3BZ$*1HSR+rhElR`JYxKWDL?b{hbl% zWyHl1;zB_+0Lu88-2wdhzu6G*@7bGEhghLN_0xb4Bk=j2vb<3Z=iFd>3*K=CR6(P@y> zZy-a?8g%7+f313EHLkT>K=oF@XyfOb)8?}quoXatS3Z$k6bynGC>Z`)MvbPq*9>5& zVZcrB=Z?9me{&hXX78j;j0gjEY6{eW<9oXT*DNn|!<(@GeAc)M|9=&K>DNMvF{(Js zfkvJNMp0J>PJB;UUirrVLdb7==+&@EMpgPPCs2h-VCeI+F9Tcs3kkq340;or>-~pN zmvl`M(9t>|fctydfoqo6w%xyj3qioZ4v+6^;I7NTpnbZC2lP=h;Ffx|F8zDT@`?b4 zq5snXDg47|GkG~b{%*}Q6Aio)%phfWU2Le?}M1g_=9Nu3k z%WD^Ky8lygKg9f9tRhehMc{$_H->K~-c+^;bO>`mjk149ysGL<%>TE{tEwx4tn5JM z`XD7^V6VY%Ml>GtkwefCKO&|G+yG{~J8ZukkO4TOpf(auWZ6 z?=Af|c-CLzAv^+#>_F+`fDZPv!-NMOMsL!g|Ioc6*x)xN^PH^an=D{1XuzZ1&ki%J z@?S{!b@7Y+k}PKd&5!}(k)ONHqqdvCLAusgVf}ySCqE1z6^jAAA6OA^t?a6u{{sK( zvU`_V!K4AI{|Km_?kBt67`+kvYB=(1bllJiSOh?G0qCD~{$cz^=&NDW@023>&N5OT zfCv8rZajH&_;0MqGdy_b4gg;Q8ujOr-<`QR{5Q6wo8BbN3BbwzQF6<i708s#cZCJK)6Ep+_`s;wv>)w%`$a8fJU@HUc zpNoyZb`v)6p7wVgWrhZx+@1y)jD=a;I#gB z#P@Y|TtB?^2ig>PyY)Z);opyPy^g+qJmC-YGRaNQ|2(Ylx`gY;t^JT-Pw_7${Kh=5 zpVsw5LITyllkn@7y?(0B557F@P56I5W9PbduAlqzgMEko2JC;F0&|^zJ&f!RKH=jV z@_!dp_PVI+F*|>Vx+i!8QGbu%c^!RyKlu;zgvw3O*LIg*$6wzO`vY&U@vrbd?T@`K z<@%j$6^p9zV?~{YyUylDX^AB%+m6^=tADID1`Cldre-FNzF8m{1fg%46{QXV&_sPTW zVtze+_+3zzSNs1(%%78qKUDq4YyRs~TtB3Ry8SC{{amRlX+I{s?;L literal 0 HcmV?d00001 diff --git a/mobile/android/base/tests/AboutHomeTest.java.in b/mobile/android/base/tests/AboutHomeTest.java.in index f72a57b0303..2f069dcbb48 100644 --- a/mobile/android/base/tests/AboutHomeTest.java.in +++ b/mobile/android/base/tests/AboutHomeTest.java.in @@ -107,7 +107,7 @@ abstract class AboutHomeTest extends BaseTest { * This method uses the predefined tags in HomePager. */ protected final ListView findListViewWithTag(String tag) { - for (ListView listView : mSolo.getCurrentListViews()) { + for (ListView listView : mSolo.getCurrentViews(ListView.class)) { final String listTag = (String) listView.getTag(); if (TextUtils.isEmpty(listTag)) { continue; diff --git a/mobile/android/base/tests/testAddSearchEngine.java.in b/mobile/android/base/tests/testAddSearchEngine.java.in index fb4252c4d50..a2f9fadf9ab 100644 --- a/mobile/android/base/tests/testAddSearchEngine.java.in +++ b/mobile/android/base/tests/testAddSearchEngine.java.in @@ -137,7 +137,7 @@ public class testAddSearchEngine extends PixelTest { public boolean test() { ArrayList views; int searchEngineCount = 0; - views = mSolo.getCurrentListViews(); + views = mSolo.getCurrentViews(ListView.class); for (ListView view : views) { ListAdapter adapter = view.getAdapter(); if (adapter != null) { diff --git a/mobile/android/base/tests/testPermissions.java.in b/mobile/android/base/tests/testPermissions.java.in index e8ad997e17a..e2bf51b45a2 100644 --- a/mobile/android/base/tests/testPermissions.java.in +++ b/mobile/android/base/tests/testPermissions.java.in @@ -26,7 +26,7 @@ public class testPermissions extends PixelTest { waitForText("wants your location"); // Uncheck the "Don't ask again for this site" checkbox - ArrayList checkBoxes = mSolo.getCurrentCheckBoxes(); + ArrayList checkBoxes = mSolo.getCurrentViews(CheckBox.class); mAsserter.ok(checkBoxes.size() == 1, "checkbox count", "only one checkbox visible"); mAsserter.ok(mSolo.isCheckBoxChecked(0), "checkbox checked", "checkbox is checked"); mSolo.clickOnCheckBox(0); From 72b18b8b22b5bdff9c9e82937f18af093d7b1c4a Mon Sep 17 00:00:00 2001 From: Andrea Marchesini Date: Tue, 3 Sep 2013 13:22:31 +0200 Subject: [PATCH 14/64] Bug 911085 - Workers postMessage has to set its return value, r=mrbkap --- dom/workers/Worker.cpp | 7 +++++- dom/workers/WorkerScope.cpp | 7 +++++- dom/workers/test/Makefile.in | 2 ++ dom/workers/test/bug911085_worker.js | 3 +++ dom/workers/test/test_bug911085.html | 32 ++++++++++++++++++++++++++++ 5 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 dom/workers/test/bug911085_worker.js create mode 100644 dom/workers/test/test_bug911085.html diff --git a/dom/workers/Worker.cpp b/dom/workers/Worker.cpp index cb59f7a2b03..314d290899c 100644 --- a/dom/workers/Worker.cpp +++ b/dom/workers/Worker.cpp @@ -294,7 +294,12 @@ private: return false; } - return worker->PostMessage(aCx, message, transferable); + if (!worker->PostMessage(aCx, message, transferable)) { + return false; + } + + JS_RVAL(aCx, aVp).setUndefined(); + return true; } }; diff --git a/dom/workers/WorkerScope.cpp b/dom/workers/WorkerScope.cpp index e7622b7b822..7fb24186c64 100644 --- a/dom/workers/WorkerScope.cpp +++ b/dom/workers/WorkerScope.cpp @@ -853,7 +853,12 @@ private: return false; } - return scope->mWorker->PostMessageToParent(aCx, message, transferable); + if (!scope->mWorker->PostMessageToParent(aCx, message, transferable)) { + return false; + } + + JS_RVAL(aCx, aVp).setUndefined(); + return true; } }; diff --git a/dom/workers/test/Makefile.in b/dom/workers/test/Makefile.in index f62f30d1b9b..932633f4c8f 100644 --- a/dom/workers/test/Makefile.in +++ b/dom/workers/test/Makefile.in @@ -106,6 +106,8 @@ MOCHITEST_FILES = \ content_worker.js \ test_url.html \ url_worker.js \ + test_bug911085.html \ + bug911085_worker.js \ $(NULL) # Bug 842386 - Disabled on OSX due to intermittent failures. diff --git a/dom/workers/test/bug911085_worker.js b/dom/workers/test/bug911085_worker.js new file mode 100644 index 00000000000..74baeca2f85 --- /dev/null +++ b/dom/workers/test/bug911085_worker.js @@ -0,0 +1,3 @@ +onmessage = function(evt) { + postMessage(postMessage('ignore') == undefined); +} diff --git a/dom/workers/test/test_bug911085.html b/dom/workers/test/test_bug911085.html new file mode 100644 index 00000000000..7c534c1ac10 --- /dev/null +++ b/dom/workers/test/test_bug911085.html @@ -0,0 +1,32 @@ + + + + + Test for bug 911085 + + + + + + + + + + From 46eb07951c057f0ac85cfb9bf094d5d7a82fa34e Mon Sep 17 00:00:00 2001 From: Masayuki Nakano Date: Tue, 3 Sep 2013 20:45:28 +0900 Subject: [PATCH 15/64] Bug 910978 part.0 Fix wrong indent in test_assign_event_data.html r=smaug --- widget/tests/test_assign_event_data.html | 190 +++++++++++------------ 1 file changed, 95 insertions(+), 95 deletions(-) diff --git a/widget/tests/test_assign_event_data.html b/widget/tests/test_assign_event_data.html index 42e168f05e9..8f09c58e161 100644 --- a/widget/tests/test_assign_event_data.html +++ b/widget/tests/test_assign_event_data.html @@ -49,107 +49,107 @@ const NATIVE_CONTROL_RIGHT = 0x0800; const NATIVE_META_RIGHT = 0x8000; const kTests = [ - { description: "nsKeyEvent (keydown of 'a' key without modifiers)", - targetID: "input-text", eventType: "keydown", - dispatchEvent: function () { - document.getElementById(this.targetID).value = ""; - document.getElementById(this.targetID).focus(); - if (kIsWin) { - gUtils.sendNativeKeyEvent(WIN_KL_US, WIN_VK_A, 0, "a", "a"); - } else if (kIsMac) { - gUtils.sendNativeKeyEvent(MAC_KL_US, MAC_VK_ANSI_A, 0, "a", "a"); - } - }, - canRun: function () { - return (kIsMac || kIsWin); - }, - todoMismatch: [ "key" ], + { description: "nsKeyEvent (keydown of 'a' key without modifiers)", + targetID: "input-text", eventType: "keydown", + dispatchEvent: function () { + document.getElementById(this.targetID).value = ""; + document.getElementById(this.targetID).focus(); + if (kIsWin) { + gUtils.sendNativeKeyEvent(WIN_KL_US, WIN_VK_A, 0, "a", "a"); + } else if (kIsMac) { + gUtils.sendNativeKeyEvent(MAC_KL_US, MAC_VK_ANSI_A, 0, "a", "a"); + } + }, + canRun: function () { + return (kIsMac || kIsWin); + }, + todoMismatch: [ "key" ], }, - { description: "nsKeyEvent (keyup of 'a' key without modifiers)", - targetID: "input-text", eventType: "keydown", - dispatchEvent: function () { - document.getElementById(this.targetID).value = ""; - document.getElementById(this.targetID).focus(); - if (kIsWin) { - gUtils.sendNativeKeyEvent(WIN_KL_US, WIN_VK_A, 0, "a", "a"); - } else if (kIsMac) { - gUtils.sendNativeKeyEvent(MAC_KL_US, MAC_VK_ANSI_A, 0, "a", "a"); - } - }, - canRun: function () { - return (kIsMac || kIsWin); - }, - todoMismatch: [ "key" ], + { description: "nsKeyEvent (keyup of 'a' key without modifiers)", + targetID: "input-text", eventType: "keydown", + dispatchEvent: function () { + document.getElementById(this.targetID).value = ""; + document.getElementById(this.targetID).focus(); + if (kIsWin) { + gUtils.sendNativeKeyEvent(WIN_KL_US, WIN_VK_A, 0, "a", "a"); + } else if (kIsMac) { + gUtils.sendNativeKeyEvent(MAC_KL_US, MAC_VK_ANSI_A, 0, "a", "a"); + } + }, + canRun: function () { + return (kIsMac || kIsWin); + }, + todoMismatch: [ "key" ], }, - { description: "nsKeyEvent (keypress of 'b' key with Shift)", - targetID: "input-text", eventType: "keypress", - dispatchEvent: function () { - document.getElementById(this.targetID).value = ""; - document.getElementById(this.targetID).focus(); - if (kIsWin) { - gUtils.sendNativeKeyEvent(WIN_KL_US, WIN_VK_B, NATIVE_SHIFT_LEFT, "B", "B"); - } else if (kIsMac) { - gUtils.sendNativeKeyEvent(MAC_KL_US, MAC_VK_ANSI_B, NATIVE_SHIFT_LEFT, "B", "B"); - } - }, - canRun: function () { - return (kIsMac || kIsWin); - }, - // "defaultPrevented" becomes true because the editor consumes the keypress event. - todoMismatch: [ "key", "defaultPrevented" ], + { description: "nsKeyEvent (keypress of 'b' key with Shift)", + targetID: "input-text", eventType: "keypress", + dispatchEvent: function () { + document.getElementById(this.targetID).value = ""; + document.getElementById(this.targetID).focus(); + if (kIsWin) { + gUtils.sendNativeKeyEvent(WIN_KL_US, WIN_VK_B, NATIVE_SHIFT_LEFT, "B", "B"); + } else if (kIsMac) { + gUtils.sendNativeKeyEvent(MAC_KL_US, MAC_VK_ANSI_B, NATIVE_SHIFT_LEFT, "B", "B"); + } + }, + canRun: function () { + return (kIsMac || kIsWin); + }, + // "defaultPrevented" becomes true because the editor consumes the keypress event. + todoMismatch: [ "key", "defaultPrevented" ], }, - { description: "nsKeyEvent (keypress of 'c' key with Accel)", - targetID: "input-text", eventType: "keypress", - dispatchEvent: function () { - document.getElementById(this.targetID).value = ""; - document.getElementById(this.targetID).focus(); - if (kIsWin) { - gUtils.sendNativeKeyEvent(WIN_KL_US, WIN_VK_C, NATIVE_CONTROL_RIGHT, "\u0003", "c"); - } else if (kIsMac) { - gUtils.sendNativeKeyEvent(MAC_KL_US, MAC_VK_ANSI_C, NATIVE_META_RIGHT, "c", "c"); - } - }, - canRun: function () { - return (kIsMac || kIsWin); - }, - // "defaultPrevented" becomes true because the editor consumes the keypress event. - todoMismatch: [ "key", "defaultPrevented" ], + { description: "nsKeyEvent (keypress of 'c' key with Accel)", + targetID: "input-text", eventType: "keypress", + dispatchEvent: function () { + document.getElementById(this.targetID).value = ""; + document.getElementById(this.targetID).focus(); + if (kIsWin) { + gUtils.sendNativeKeyEvent(WIN_KL_US, WIN_VK_C, NATIVE_CONTROL_RIGHT, "\u0003", "c"); + } else if (kIsMac) { + gUtils.sendNativeKeyEvent(MAC_KL_US, MAC_VK_ANSI_C, NATIVE_META_RIGHT, "c", "c"); + } + }, + canRun: function () { + return (kIsMac || kIsWin); + }, + // "defaultPrevented" becomes true because the editor consumes the keypress event. + todoMismatch: [ "key", "defaultPrevented" ], }, - { description: "nsMouseEvent (mousedown of left button without modifier)", - targetID: "button", eventType: "mousedown", - dispatchEvent: function () { - synthesizeMouseAtCenter(document.getElementById(this.targetID), - { button: 0 }); - }, - canRun: function () { - return true; - }, - todoMismatch: [], + { description: "nsMouseEvent (mousedown of left button without modifier)", + targetID: "button", eventType: "mousedown", + dispatchEvent: function () { + synthesizeMouseAtCenter(document.getElementById(this.targetID), + { button: 0 }); + }, + canRun: function () { + return true; + }, + todoMismatch: [], }, - { description: "nsMouseEvent (click of middle button with Shift)", - // XXX I'm not sure why middle click event isn't fired on button element. - targetID: "input-text", eventType: "click", - dispatchEvent: function () { - document.getElementById(this.targetID).value = ""; - synthesizeMouseAtCenter(document.getElementById(this.targetID), - { button: 1, shiftKey: true, pressure: 0.5 }); - }, - canRun: function () { - return true; - }, - todoMismatch: [], + { description: "nsMouseEvent (click of middle button with Shift)", + // XXX I'm not sure why middle click event isn't fired on button element. + targetID: "input-text", eventType: "click", + dispatchEvent: function () { + document.getElementById(this.targetID).value = ""; + synthesizeMouseAtCenter(document.getElementById(this.targetID), + { button: 1, shiftKey: true, pressure: 0.5 }); + }, + canRun: function () { + return true; + }, + todoMismatch: [], }, - { description: "nsMouseEvent (mouseup of right button with Alt)", - targetID: "button", eventType: "mouseup", - dispatchEvent: function () { - document.getElementById(this.targetID).value = ""; - synthesizeMouseAtCenter(document.getElementById(this.targetID), - { button: 2, altKey: true }); - }, - canRun: function () { - return true; - }, - todoMismatch: [], + { description: "nsMouseEvent (mouseup of right button with Alt)", + targetID: "button", eventType: "mouseup", + dispatchEvent: function () { + document.getElementById(this.targetID).value = ""; + synthesizeMouseAtCenter(document.getElementById(this.targetID), + { button: 2, altKey: true }); + }, + canRun: function () { + return true; + }, + todoMismatch: [], }, ]; From 0cf5f945b09030ad2c565bca03a7342fd97a9b71 Mon Sep 17 00:00:00 2001 From: Masayuki Nakano Date: Tue, 3 Sep 2013 20:45:28 +0900 Subject: [PATCH 16/64] Bug 910978 part.1 Implement nsScriptErrorEvent::AssignScriptErrorEventData() r=smaug --- content/events/src/nsDOMEvent.cpp | 3 +-- widget/nsGUIEvent.h | 14 ++++++++++++++ widget/tests/test_assign_event_data.html | 11 +++++++++++ 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/content/events/src/nsDOMEvent.cpp b/content/events/src/nsDOMEvent.cpp index 3dee5279ee0..979bde4044f 100644 --- a/content/events/src/nsDOMEvent.cpp +++ b/content/events/src/nsDOMEvent.cpp @@ -587,8 +587,7 @@ nsDOMEvent::DuplicatePrivateData() nsScriptErrorEvent* oldScriptErrorEvent = static_cast(mEvent); nsScriptErrorEvent* scriptErrorEvent = new nsScriptErrorEvent(false, msg); - scriptErrorEvent->AssignEventData(*oldScriptErrorEvent, true); - scriptErrorEvent->lineNr = oldScriptErrorEvent->lineNr; + scriptErrorEvent->AssignScriptErrorEventData(*oldScriptErrorEvent, true); newEvent = scriptErrorEvent; break; } diff --git a/widget/nsGUIEvent.h b/widget/nsGUIEvent.h index 90b9356fb4f..6af6f6694bf 100644 --- a/widget/nsGUIEvent.h +++ b/widget/nsGUIEvent.h @@ -768,6 +768,20 @@ public: int32_t lineNr; const PRUnichar* errorMsg; const PRUnichar* fileName; + + // XXX Not tested by test_assign_event_data.html + void AssignScriptErrorEventData(const nsScriptErrorEvent& aEvent, + bool aCopyTargets) + { + AssignEventData(aEvent, aCopyTargets); + + lineNr = aEvent.lineNr; + + // We don't copy errorMsg and fileName. If it's necessary, perhaps, this + // should duplicate the characters and free them at destructing. + errorMsg = nullptr; + fileName = nullptr; + } }; /** diff --git a/widget/tests/test_assign_event_data.html b/widget/tests/test_assign_event_data.html index 8f09c58e161..6c93f301547 100644 --- a/widget/tests/test_assign_event_data.html +++ b/widget/tests/test_assign_event_data.html @@ -49,6 +49,17 @@ const NATIVE_CONTROL_RIGHT = 0x0800; const NATIVE_META_RIGHT = 0x8000; const kTests = [ + { description: "nsScriptErrorEvent", + targetID: "input-text", eventType: "error", + dispatchEvent: function () { + return; + }, + canRun: function () { + todo(false, "nsScriptErrorEvent isn't tested"); + return false; + }, + todoMismatch: [], + }, { description: "nsKeyEvent (keydown of 'a' key without modifiers)", targetID: "input-text", eventType: "keydown", dispatchEvent: function () { From 144f6d5e2667f84300f13c8476cba108ba8df519 Mon Sep 17 00:00:00 2001 From: Masayuki Nakano Date: Tue, 3 Sep 2013 20:45:28 +0900 Subject: [PATCH 17/64] Bug 910978 part.2 Remove nsScrollbarEvent because its member is never used r=smaug+roc --- content/events/src/nsDOMEvent.cpp | 11 ----------- layout/generic/nsGfxScrollFrame.cpp | 2 +- layout/xul/tree/nsTreeBodyFrame.cpp | 2 +- widget/nsGUIEvent.h | 18 ------------------ 4 files changed, 2 insertions(+), 31 deletions(-) diff --git a/content/events/src/nsDOMEvent.cpp b/content/events/src/nsDOMEvent.cpp index 979bde4044f..b0314d6b4ea 100644 --- a/content/events/src/nsDOMEvent.cpp +++ b/content/events/src/nsDOMEvent.cpp @@ -520,17 +520,6 @@ nsDOMEvent::DuplicatePrivateData() newEvent = guiEvent; break; } - case NS_SCROLLBAR_EVENT: - { - nsScrollbarEvent* oldScrollbarEvent = - static_cast(mEvent); - nsScrollbarEvent* scrollbarEvent = - new nsScrollbarEvent(false, msg, nullptr); - scrollbarEvent->AssignGUIEventData(*scrollbarEvent, true); - scrollbarEvent->position = oldScrollbarEvent->position; - newEvent = scrollbarEvent; - break; - } case NS_INPUT_EVENT: { nsInputEvent* oldInputEvent = static_cast(mEvent); diff --git a/layout/generic/nsGfxScrollFrame.cpp b/layout/generic/nsGfxScrollFrame.cpp index dcdae94ed8b..068b7c919ba 100644 --- a/layout/generic/nsGfxScrollFrame.cpp +++ b/layout/generic/nsGfxScrollFrame.cpp @@ -3079,7 +3079,7 @@ nsGfxScrollFrameInner::FireScrollEvent() { mScrollEvent.Forget(); - nsScrollbarEvent event(true, NS_SCROLL_EVENT, nullptr); + nsGUIEvent event(true, NS_SCROLL_EVENT, nullptr); nsEventStatus status = nsEventStatus_eIgnore; nsIContent* content = mOuter->GetContent(); nsPresContext* prescontext = mOuter->PresContext(); diff --git a/layout/xul/tree/nsTreeBodyFrame.cpp b/layout/xul/tree/nsTreeBodyFrame.cpp index 887dbcaec55..8e610b8b122 100644 --- a/layout/xul/tree/nsTreeBodyFrame.cpp +++ b/layout/xul/tree/nsTreeBodyFrame.cpp @@ -4453,7 +4453,7 @@ void nsTreeBodyFrame::FireScrollEvent() { mScrollEvent.Forget(); - nsScrollbarEvent event(true, NS_SCROLL_EVENT, nullptr); + nsGUIEvent event(true, NS_SCROLL_EVENT, nullptr); // scroll events fired at elements don't bubble event.mFlags.mBubbles = false; nsEventDispatcher::Dispatch(GetContent(), PresContext(), &event); diff --git a/widget/nsGUIEvent.h b/widget/nsGUIEvent.h index 6af6f6694bf..e03e2cbed2f 100644 --- a/widget/nsGUIEvent.h +++ b/widget/nsGUIEvent.h @@ -75,7 +75,6 @@ enum nsEventStructType { NS_SELECTION_EVENT, // nsSelectionEvent // Scroll related events - NS_SCROLLBAR_EVENT, // nsScrollbarEvent NS_SCROLLPORT_EVENT, // nsScrollPortEvent NS_SCROLLAREA_EVENT, // nsScrollAreaEvent @@ -784,23 +783,6 @@ public: } }; -/** - * Scrollbar event - */ - -class nsScrollbarEvent : public nsGUIEvent -{ -public: - nsScrollbarEvent(bool isTrusted, uint32_t msg, nsIWidget *w) - : nsGUIEvent(isTrusted, msg, w, NS_SCROLLBAR_EVENT), - position(0) - { - } - - /// ranges between scrollbar 0 and (maxRange - thumbSize). See nsIScrollbar - uint32_t position; -}; - class nsScrollPortEvent : public nsGUIEvent { public: From 56c41ee879cd514437c96bea24569b6e65671bf5 Mon Sep 17 00:00:00 2001 From: Masayuki Nakano Date: Tue, 3 Sep 2013 20:45:28 +0900 Subject: [PATCH 18/64] Bug 910978 part.3 Implement nsScrollPortEvent::AssignScrollPortEventData() r=smaug --- content/events/src/nsDOMEvent.cpp | 3 +-- widget/nsGUIEvent.h | 8 +++++++ widget/tests/test_assign_event_data.html | 27 ++++++++++++++++++++++-- 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/content/events/src/nsDOMEvent.cpp b/content/events/src/nsDOMEvent.cpp index b0314d6b4ea..9c99bf3efa6 100644 --- a/content/events/src/nsDOMEvent.cpp +++ b/content/events/src/nsDOMEvent.cpp @@ -649,8 +649,7 @@ nsDOMEvent::DuplicatePrivateData() static_cast(mEvent); nsScrollPortEvent* scrollPortEvent = new nsScrollPortEvent(false, msg, nullptr); - scrollPortEvent->AssignGUIEventData(*oldScrollPortEvent, true); - scrollPortEvent->orient = oldScrollPortEvent->orient; + scrollPortEvent->AssignScrollPortEventData(*oldScrollPortEvent, true); newEvent = scrollPortEvent; break; } diff --git a/widget/nsGUIEvent.h b/widget/nsGUIEvent.h index e03e2cbed2f..f4430e6cd1a 100644 --- a/widget/nsGUIEvent.h +++ b/widget/nsGUIEvent.h @@ -799,6 +799,14 @@ public: } orientType orient; + + void AssignScrollPortEventData(const nsScrollPortEvent& aEvent, + bool aCopyTargets) + { + AssignGUIEventData(aEvent, aCopyTargets); + + orient = aEvent.orient; + } }; class nsScrollAreaEvent : public nsGUIEvent diff --git a/widget/tests/test_assign_event_data.html b/widget/tests/test_assign_event_data.html index 6c93f301547..b66130d8fa0 100644 --- a/widget/tests/test_assign_event_data.html +++ b/widget/tests/test_assign_event_data.html @@ -12,6 +12,7 @@

    +
    @@ -28,6 +29,7 @@ const kIsWin = (navigator.platform.indexOf("Win") == 0); var gEvent = null; var gCopiedEvent = []; +var gCallback = null; function onEvent(aEvent) { @@ -39,6 +41,7 @@ function onEvent(aEvent) gCopiedEvent.push({ name: attr, value: aEvent[attr]}); } } + setTimeout(gCallback, 0); } const WIN_KL_US = 0x409; @@ -60,6 +63,26 @@ const kTests = [ }, todoMismatch: [], }, + { description: "nsScrollPortEvent (overflow, vertical)", + targetID: "scrollable-div", eventType: "overflow", + dispatchEvent: function () { + document.getElementById("scrolled-div").style.height = "500px"; + }, + canRun: function () { + return true; + }, + todoMismatch: [], + }, + { description: "nsScrollPortEvent (overflow, horizontal)", + targetID: "scrollable-div", eventType: "overflow", + dispatchEvent: function () { + document.getElementById("scrolled-div").style.width = "500px"; + }, + canRun: function () { + return true; + }, + todoMismatch: [], + }, { description: "nsKeyEvent (keydown of 'a' key without modifiers)", targetID: "input-text", eventType: "keydown", dispatchEvent: function () { @@ -174,7 +197,7 @@ function doTest(aTest) gCopiedEvent = []; var target = document.getElementById(aTest.targetID); target.addEventListener(aTest.eventType, onEvent, true); - setTimeout(function () { + gCallback = function () { target.removeEventListener(aTest.eventType, onEvent, true); ok(gEvent !== null, aTest.description + ": failed to get duplicated event"); ok(gCopiedEvent.length > 0, aTest.description + ": count of attribute of the event must be larger than 0"); @@ -193,7 +216,7 @@ function doTest(aTest) } } runNextTest(); - }, 0); + }; aTest.dispatchEvent(); } From 725fecdb0014dfd9831f76cae031fc96b21ca8f0 Mon Sep 17 00:00:00 2001 From: Masayuki Nakano Date: Tue, 3 Sep 2013 20:45:28 +0900 Subject: [PATCH 19/64] Bug 910978 part.4 Implement nsScrollAreaEvent::AssignScrollAreaEventData() r=smaug --- content/events/src/nsDOMEvent.cpp | 3 +-- widget/nsGUIEvent.h | 8 ++++++++ widget/tests/test_assign_event_data.html | 24 +++++++++++++++++++++++- 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/content/events/src/nsDOMEvent.cpp b/content/events/src/nsDOMEvent.cpp index 9c99bf3efa6..16731a7df7e 100644 --- a/content/events/src/nsDOMEvent.cpp +++ b/content/events/src/nsDOMEvent.cpp @@ -659,8 +659,7 @@ nsDOMEvent::DuplicatePrivateData() static_cast(mEvent); nsScrollAreaEvent* scrollAreaEvent = new nsScrollAreaEvent(false, msg, nullptr); - scrollAreaEvent->AssignGUIEventData(*oldScrollAreaEvent, true); - scrollAreaEvent->mArea = oldScrollAreaEvent->mArea; + scrollAreaEvent->AssignScrollAreaEventData(*oldScrollAreaEvent, true); newEvent = scrollAreaEvent; break; } diff --git a/widget/nsGUIEvent.h b/widget/nsGUIEvent.h index f4430e6cd1a..7c9243265ba 100644 --- a/widget/nsGUIEvent.h +++ b/widget/nsGUIEvent.h @@ -818,6 +818,14 @@ public: } nsRect mArea; + + void AssignScrollAreaEventData(const nsScrollAreaEvent& aEvent, + bool aCopyTargets) + { + AssignGUIEventData(aEvent, aCopyTargets); + + mArea = aEvent.mArea; + } }; class nsInputEvent : public nsGUIEvent diff --git a/widget/tests/test_assign_event_data.html b/widget/tests/test_assign_event_data.html index b66130d8fa0..b260b9133fd 100644 --- a/widget/tests/test_assign_event_data.html +++ b/widget/tests/test_assign_event_data.html @@ -83,6 +83,28 @@ const kTests = [ }, todoMismatch: [], }, + { description: "nsScrollAreaEvent (MozScrolledAreaChanged, spreading)", + target: function () { return document; }, eventType: "MozScrolledAreaChanged", + dispatchEvent: function () { + document.getElementById("scrollable-div").style.width = "50000px"; + document.getElementById("scrollable-div").style.height = "50000px"; + }, + canRun: function () { + return true; + }, + todoMismatch: [], + }, + { description: "nsScrollAreaEvent (MozScrolledAreaChanged, shrinking)", + target: function () { return document; }, eventType: "MozScrolledAreaChanged", + dispatchEvent: function () { + document.getElementById("scrollable-div").style.width = "30px"; + document.getElementById("scrollable-div").style.height = "30px"; + }, + canRun: function () { + return true; + }, + todoMismatch: [], + }, { description: "nsKeyEvent (keydown of 'a' key without modifiers)", targetID: "input-text", eventType: "keydown", dispatchEvent: function () { @@ -195,7 +217,7 @@ function doTest(aTest) } gEvent = null; gCopiedEvent = []; - var target = document.getElementById(aTest.targetID); + var target = aTest.target ? aTest.target() : document.getElementById(aTest.targetID); target.addEventListener(aTest.eventType, onEvent, true); gCallback = function () { target.removeEventListener(aTest.eventType, onEvent, true); From 114445c4e248dc5051dc40ca6c6c4b191144ebc9 Mon Sep 17 00:00:00 2001 From: Masayuki Nakano Date: Tue, 3 Sep 2013 20:45:28 +0900 Subject: [PATCH 20/64] Bug 910978 part.5 Implement nsDragEvent::AssignDragEventData() r=smaug --- content/events/src/nsDOMEvent.cpp | 10 +--------- widget/nsGUIEvent.h | 10 ++++++++++ widget/tests/test_assign_event_data.html | 11 +++++++++++ 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/content/events/src/nsDOMEvent.cpp b/content/events/src/nsDOMEvent.cpp index 16731a7df7e..550b349d1b1 100644 --- a/content/events/src/nsDOMEvent.cpp +++ b/content/events/src/nsDOMEvent.cpp @@ -550,15 +550,7 @@ nsDOMEvent::DuplicatePrivateData() nsDragEvent* oldDragEvent = static_cast(mEvent); nsDragEvent* dragEvent = new nsDragEvent(false, msg, nullptr); - dragEvent->AssignInputEventData(*oldDragEvent, true); - dragEvent->dataTransfer = oldDragEvent->dataTransfer; - dragEvent->clickCount = oldDragEvent->clickCount; - dragEvent->acceptActivation = oldDragEvent->acceptActivation; - dragEvent->relatedTarget = oldDragEvent->relatedTarget; - dragEvent->button = oldDragEvent->button; - dragEvent->buttons = oldDragEvent->buttons; - static_cast(dragEvent)->inputSource = - static_cast(oldDragEvent)->inputSource; + dragEvent->AssignDragEventData(*oldDragEvent, true); newEvent = dragEvent; break; } diff --git a/widget/nsGUIEvent.h b/widget/nsGUIEvent.h index 7c9243265ba..b765f88e3c8 100644 --- a/widget/nsGUIEvent.h +++ b/widget/nsGUIEvent.h @@ -1110,6 +1110,16 @@ public: nsCOMPtr dataTransfer; bool userCancelled; + + // XXX Not tested by test_assign_event_data.html + void AssignDragEventData(const nsDragEvent& aEvent, bool aCopyTargets) + { + AssignMouseEventData(aEvent, aCopyTargets); + + dataTransfer = aEvent.dataTransfer; + // XXX userCancelled isn't copied, is this instentionally? + userCancelled = false; + } }; /** diff --git a/widget/tests/test_assign_event_data.html b/widget/tests/test_assign_event_data.html index b260b9133fd..ac16a3249be 100644 --- a/widget/tests/test_assign_event_data.html +++ b/widget/tests/test_assign_event_data.html @@ -207,6 +207,17 @@ const kTests = [ }, todoMismatch: [], }, + { description: "nsDragEvent", + targetID: "input-text", eventType: "dragstart", + dispatchEvent: function () { + return; + }, + canRun: function () { + todo(false, "nsDragEvent isn't tested"); + return false; + }, + todoMismatch: [], + }, ]; function doTest(aTest) From 00a26e15e5c4af434ff50c83707a7cc105e7d2e3 Mon Sep 17 00:00:00 2001 From: Masayuki Nakano Date: Tue, 3 Sep 2013 20:45:29 +0900 Subject: [PATCH 21/64] Bug 910978 part.6 Implement nsTextEvent::AssignTextEventData() and make nsTextEvent not a derived class of nsInputEvent because nobody uses the stored data r=smaug --- content/events/src/nsDOMEvent.cpp | 2 +- content/events/src/nsDOMUIEvent.cpp | 3 +++ widget/nsGUIEvent.h | 16 +++++++++++++--- widget/nsGUIEventIPC.h | 4 ++-- widget/tests/test_assign_event_data.html | 23 +++++++++++++++++++++++ widget/windows/nsIMM32Handler.cpp | 2 -- 6 files changed, 42 insertions(+), 8 deletions(-) diff --git a/content/events/src/nsDOMEvent.cpp b/content/events/src/nsDOMEvent.cpp index 550b349d1b1..622cb6a35ab 100644 --- a/content/events/src/nsDOMEvent.cpp +++ b/content/events/src/nsDOMEvent.cpp @@ -576,7 +576,7 @@ nsDOMEvent::DuplicatePrivateData() { nsTextEvent* oldTextEvent = static_cast(mEvent); nsTextEvent* textEvent = new nsTextEvent(false, msg, nullptr); - textEvent->AssignGUIEventData(*oldTextEvent, true); + textEvent->AssignTextEventData(*oldTextEvent, true); newEvent = textEvent; break; } diff --git a/content/events/src/nsDOMUIEvent.cpp b/content/events/src/nsDOMUIEvent.cpp index 6ea59d31ecd..a52c9982997 100644 --- a/content/events/src/nsDOMUIEvent.cpp +++ b/content/events/src/nsDOMUIEvent.cpp @@ -460,6 +460,9 @@ nsDOMUIEvent::ComputeModifierState(const nsAString& aModifiersList) bool nsDOMUIEvent::GetModifierStateInternal(const nsAString& aKey) { + if (!NS_IS_INPUT_EVENT(mEvent)) { + MOZ_CRASH("mEvent must be nsInputEvent or derived class"); + } nsInputEvent* inputEvent = static_cast(mEvent); if (aKey.EqualsLiteral(NS_DOM_KEYNAME_SHIFT)) { return inputEvent->IsShift(); diff --git a/widget/nsGUIEvent.h b/widget/nsGUIEvent.h index b765f88e3c8..fc61cd8aeb2 100644 --- a/widget/nsGUIEvent.h +++ b/widget/nsGUIEvent.h @@ -1331,7 +1331,7 @@ struct nsTextRange typedef nsTextRange* nsTextRangeArray; -class nsTextEvent : public nsInputEvent +class nsTextEvent : public nsGUIEvent { private: friend class mozilla::dom::PBrowserParent; @@ -1347,7 +1347,7 @@ public: public: nsTextEvent(bool isTrusted, uint32_t msg, nsIWidget *w) - : nsInputEvent(isTrusted, msg, w, NS_TEXT_EVENT), + : nsGUIEvent(isTrusted, msg, w, NS_TEXT_EVENT), rangeCount(0), rangeArray(nullptr), isChar(false) { } @@ -1359,6 +1359,16 @@ public: // array. nsTextRangeArray rangeArray; bool isChar; + + void AssignTextEventData(const nsTextEvent& aEvent, bool aCopyTargets) + { + AssignGUIEventData(aEvent, aCopyTargets); + + isChar = aEvent.isChar; + + // Currently, we don't need to copy the other members because they are + // for internal use only (not available from JS). + } }; class nsCompositionEvent : public nsGUIEvent @@ -1924,10 +1934,10 @@ enum nsDragDropEventStatus { (((evnt)->eventStructType == NS_INPUT_EVENT) || \ ((evnt)->eventStructType == NS_MOUSE_EVENT) || \ ((evnt)->eventStructType == NS_KEY_EVENT) || \ - ((evnt)->eventStructType == NS_TEXT_EVENT) || \ ((evnt)->eventStructType == NS_TOUCH_EVENT) || \ ((evnt)->eventStructType == NS_DRAG_EVENT) || \ ((evnt)->eventStructType == NS_MOUSE_SCROLL_EVENT) || \ + ((evnt)->eventStructType == NS_WHEEL_EVENT) || \ ((evnt)->eventStructType == NS_SIMPLE_GESTURE_EVENT)) #define NS_IS_MOUSE_EVENT(evnt) \ diff --git a/widget/nsGUIEventIPC.h b/widget/nsGUIEventIPC.h index 7fe1389bce3..a27a895c7ae 100644 --- a/widget/nsGUIEventIPC.h +++ b/widget/nsGUIEventIPC.h @@ -338,7 +338,7 @@ struct ParamTraits static void Write(Message* aMsg, const paramType& aParam) { - WriteParam(aMsg, static_cast(aParam)); + WriteParam(aMsg, static_cast(aParam)); WriteParam(aMsg, aParam.seqno); WriteParam(aMsg, aParam.theText); WriteParam(aMsg, aParam.isChar); @@ -349,7 +349,7 @@ struct ParamTraits static bool Read(const Message* aMsg, void** aIter, paramType* aResult) { - if (!ReadParam(aMsg, aIter, static_cast(aResult)) || + if (!ReadParam(aMsg, aIter, static_cast(aResult)) || !ReadParam(aMsg, aIter, &aResult->seqno) || !ReadParam(aMsg, aIter, &aResult->theText) || !ReadParam(aMsg, aIter, &aResult->isChar) || diff --git a/widget/tests/test_assign_event_data.html b/widget/tests/test_assign_event_data.html index ac16a3249be..f79a18b3b16 100644 --- a/widget/tests/test_assign_event_data.html +++ b/widget/tests/test_assign_event_data.html @@ -218,6 +218,29 @@ const kTests = [ }, todoMismatch: [], }, + { description: "nsTextEvent (text)", + targetID: "input-text", eventType: "text", + dispatchEvent: function () { + document.getElementById(this.targetID).value = ""; + document.getElementById(this.targetID).focus(); + synthesizeComposition({ type: "compositionstart" }); + synthesizeComposition({ type: "compositionupdate", data: "\u306D" }); + synthesizeText({ "composition": + { "string": "\u306D", + "clauses": + [ + { "length": 0, "attr": 0 } + ] + }, + "caret": { "start": 1, "length": 0 } + }); + synthesizeComposition({ type: "compositionend", data: "\u732B" }); + }, + canRun: function () { + return true; + }, + todoMismatch: [ ], + }, ]; function doTest(aTest) diff --git a/widget/windows/nsIMM32Handler.cpp b/widget/windows/nsIMM32Handler.cpp index 978202795a0..14d96a872d1 100644 --- a/widget/windows/nsIMM32Handler.cpp +++ b/widget/windows/nsIMM32Handler.cpp @@ -1593,8 +1593,6 @@ nsIMM32Handler::DispatchTextEvent(nsWindow* aWindow, event.rangeArray = textRanges.Elements(); event.theText = mCompositionString.get(); - mozilla::widget::ModifierKeyState modKeyState; - modKeyState.InitInputEvent(event); aWindow->DispatchWindowEvent(&event); From ccd69297c4cc3f8fe9e26092beeb38579bbf6173 Mon Sep 17 00:00:00 2001 From: Masayuki Nakano Date: Tue, 3 Sep 2013 20:45:29 +0900 Subject: [PATCH 22/64] Bug 910978 part.7 Implement nsCompositionEvent::AssignCompositionEventData() r=smaug --- content/events/src/nsDOMEvent.cpp | 3 +-- widget/nsGUIEvent.h | 8 ++++++++ widget/tests/test_assign_event_data.html | 23 +++++++++++++++++++++++ 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/content/events/src/nsDOMEvent.cpp b/content/events/src/nsDOMEvent.cpp index 622cb6a35ab..4bb42baaece 100644 --- a/content/events/src/nsDOMEvent.cpp +++ b/content/events/src/nsDOMEvent.cpp @@ -586,8 +586,7 @@ nsDOMEvent::DuplicatePrivateData() new nsCompositionEvent(false, msg, nullptr); nsCompositionEvent* oldCompositionEvent = static_cast(mEvent); - compositionEvent->AssignGUIEventData(*oldCompositionEvent, true); - compositionEvent->data = oldCompositionEvent->data; + compositionEvent->AssignCompositionEventData(*oldCompositionEvent, true); newEvent = compositionEvent; break; } diff --git a/widget/nsGUIEvent.h b/widget/nsGUIEvent.h index fc61cd8aeb2..e77ee97ca07 100644 --- a/widget/nsGUIEvent.h +++ b/widget/nsGUIEvent.h @@ -1395,6 +1395,14 @@ public: } nsString data; + + void AssignCompositionEventData(const nsCompositionEvent& aEvent, + bool aCopyTargets) + { + AssignGUIEventData(aEvent, aCopyTargets); + + data = aEvent.data; + } }; /** diff --git a/widget/tests/test_assign_event_data.html b/widget/tests/test_assign_event_data.html index f79a18b3b16..f263c1646f7 100644 --- a/widget/tests/test_assign_event_data.html +++ b/widget/tests/test_assign_event_data.html @@ -241,6 +241,29 @@ const kTests = [ }, todoMismatch: [ ], }, + { description: "nsCompositionEvent (compositionupdate)", + targetID: "input-text", eventType: "compositionupdate", + dispatchEvent: function () { + document.getElementById(this.targetID).value = ""; + document.getElementById(this.targetID).focus(); + synthesizeComposition({ type: "compositionstart" }); + synthesizeComposition({ type: "compositionupdate", data: "\u30E9\u30FC\u30E1\u30F3" }); + synthesizeText({ "composition": + { "string": "\u30E9\u30FC\u30E1\u30F3", + "clauses": + [ + { "length": 0, "attr": 0 } + ] + }, + "caret": { "start": 4, "length": 0 } + }); + synthesizeComposition({ type: "compositionend", data: "\u30E9\u30FC\u30E1\u30F3" }); + }, + canRun: function () { + return true; + }, + todoMismatch: [ ], + }, ]; function doTest(aTest) From 04b32b9fa0b7ea277d03ac9fe4797d6a8c7607c2 Mon Sep 17 00:00:00 2001 From: Masayuki Nakano Date: Tue, 3 Sep 2013 20:45:29 +0900 Subject: [PATCH 23/64] Bug 910978 part.8 Implement nsMouseScrollEvent::AssignMouseScrollEventData() r=smaug --- content/events/src/nsDOMEvent.cpp | 9 +--- widget/nsGUIEvent.h | 9 ++++ widget/tests/test_assign_event_data.html | 69 ++++++++++++++++++++++++ 3 files changed, 79 insertions(+), 8 deletions(-) diff --git a/content/events/src/nsDOMEvent.cpp b/content/events/src/nsDOMEvent.cpp index 4bb42baaece..514026c0f66 100644 --- a/content/events/src/nsDOMEvent.cpp +++ b/content/events/src/nsDOMEvent.cpp @@ -596,14 +596,7 @@ nsDOMEvent::DuplicatePrivateData() static_cast(mEvent); nsMouseScrollEvent* mouseScrollEvent = new nsMouseScrollEvent(false, msg, nullptr); - mouseScrollEvent->AssignInputEventData(*oldMouseScrollEvent, true); - mouseScrollEvent->isHorizontal = oldMouseScrollEvent->isHorizontal; - mouseScrollEvent->delta = oldMouseScrollEvent->delta; - mouseScrollEvent->relatedTarget = oldMouseScrollEvent->relatedTarget; - mouseScrollEvent->button = oldMouseScrollEvent->button; - mouseScrollEvent->buttons = oldMouseScrollEvent->buttons; - static_cast(mouseScrollEvent)->inputSource = - static_cast(oldMouseScrollEvent)->inputSource; + mouseScrollEvent->AssignMouseScrollEventData(*oldMouseScrollEvent, true); newEvent = mouseScrollEvent; break; } diff --git a/widget/nsGUIEvent.h b/widget/nsGUIEvent.h index e77ee97ca07..545be8e2fa5 100644 --- a/widget/nsGUIEvent.h +++ b/widget/nsGUIEvent.h @@ -1427,6 +1427,15 @@ public: int32_t delta; bool isHorizontal; + + void AssignMouseScrollEventData(const nsMouseScrollEvent& aEvent, + bool aCopyTargets) + { + AssignMouseEventBaseData(aEvent, aCopyTargets); + + delta = aEvent.delta; + isHorizontal = aEvent.isHorizontal; + } }; /** diff --git a/widget/tests/test_assign_event_data.html b/widget/tests/test_assign_event_data.html index f263c1646f7..a91a5e1e76c 100644 --- a/widget/tests/test_assign_event_data.html +++ b/widget/tests/test_assign_event_data.html @@ -264,6 +264,54 @@ const kTests = [ }, todoMismatch: [ ], }, + { description: "nsMouseScrollEvent (DOMMouseScroll, vertical)", + targetID: "input-text", eventType: "DOMMouseScroll", + dispatchEvent: function () { + document.getElementById(this.targetID).value = ""; + synthesizeWheel(document.getElementById(this.targetID), 3, 4, + { deltaY: 30, lineOrPageDeltaY: 2 }); + }, + canRun: function () { + return true; + }, + todoMismatch: [ ], + }, + { description: "nsMouseScrollEvent (DOMMouseScroll, horizontal)", + targetID: "input-text", eventType: "DOMMouseScroll", + dispatchEvent: function () { + document.getElementById(this.targetID).value = ""; + synthesizeWheel(document.getElementById(this.targetID), 4, 5, + { deltaX: 30, lineOrPageDeltaX: 2, shiftKey: true }); + }, + canRun: function () { + return true; + }, + todoMismatch: [ ], + }, + { description: "nsMouseScrollEvent (MozMousePixelScroll, vertical)", + targetID: "input-text", eventType: "MozMousePixelScroll", + dispatchEvent: function () { + document.getElementById(this.targetID).value = ""; + synthesizeWheel(document.getElementById(this.targetID), 3, 4, + { deltaY: 20, lineOrPageDeltaY: 1, altKey: true }); + }, + canRun: function () { + return true; + }, + todoMismatch: [ ], + }, + { description: "nsMouseScrollEvent (MozMousePixelScroll, horizontal)", + targetID: "input-text", eventType: "MozMousePixelScroll", + dispatchEvent: function () { + document.getElementById(this.targetID).value = ""; + synthesizeWheel(document.getElementById(this.targetID), 4, 5, + { deltaX: 20, lineOrPageDeltaX: 1, ctrlKey: true }); + }, + canRun: function () { + return true; + }, + todoMismatch: [ ], + }, ]; function doTest(aTest) @@ -314,6 +362,16 @@ function init() SpecialPowers.setBoolPref("middlemouse.contentLoadURL", false); SpecialPowers.setBoolPref("middlemouse.paste", false); SpecialPowers.setBoolPref("general.autoScroll", false); + SpecialPowers.setIntPref("mousewheel.default.action", 0); + SpecialPowers.setIntPref("mousewheel.default.action.override_x", -1); + SpecialPowers.setIntPref("mousewheel.with_shift.action", 0); + SpecialPowers.setIntPref("mousewheel.with_shift.action.override_x", -1); + SpecialPowers.setIntPref("mousewheel.with_control.action", 0); + SpecialPowers.setIntPref("mousewheel.with_control.action.override_x", -1); + SpecialPowers.setIntPref("mousewheel.with_alt.action", 0); + SpecialPowers.setIntPref("mousewheel.with_alt.action.override_x", -1); + SpecialPowers.setIntPref("mousewheel.with_meta.action", 0); + SpecialPowers.setIntPref("mousewheel.with_meta.action.override_x", -1); runNextTest(); } @@ -323,6 +381,17 @@ function finish() SpecialPowers.clearUserPref("middlemouse.contentLoadURL"); SpecialPowers.clearUserPref("middlemouse.paste"); SpecialPowers.clearUserPref("general.autoScroll"); + SpecialPowers.clearUserPref("mousewheel.default.action"); + SpecialPowers.clearUserPref("mousewheel.default.action.override_x"); + SpecialPowers.clearUserPref("mousewheel.with_shift.action"); + SpecialPowers.clearUserPref("mousewheel.with_shift.action.override_x"); + SpecialPowers.clearUserPref("mousewheel.with_control.action"); + SpecialPowers.clearUserPref("mousewheel.with_control.action.override_x"); + SpecialPowers.clearUserPref("mousewheel.with_alt.action"); + SpecialPowers.clearUserPref("mousewheel.with_alt.action.override_x"); + SpecialPowers.clearUserPref("mousewheel.with_meta.action"); + SpecialPowers.clearUserPref("mousewheel.with_meta.action.override_x"); + SimpleTest.finish(); } From 546beaa3a9c08ad911aba5ed4419082280f11815 Mon Sep 17 00:00:00 2001 From: Masayuki Nakano Date: Tue, 3 Sep 2013 20:45:29 +0900 Subject: [PATCH 24/64] Bug 910978 part.9 Implement widget::WheelEvent::AssignWheelEventData() r=smaug --- content/events/src/nsDOMEvent.cpp | 19 +----------- widget/nsGUIEvent.h | 18 ++++++++++++ widget/tests/test_assign_event_data.html | 37 ++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 18 deletions(-) diff --git a/content/events/src/nsDOMEvent.cpp b/content/events/src/nsDOMEvent.cpp index 514026c0f66..20ab4b3656c 100644 --- a/content/events/src/nsDOMEvent.cpp +++ b/content/events/src/nsDOMEvent.cpp @@ -606,24 +606,7 @@ nsDOMEvent::DuplicatePrivateData() static_cast(mEvent); widget::WheelEvent* wheelEvent = new widget::WheelEvent(false, msg, nullptr); - wheelEvent->AssignInputEventData(*oldWheelEvent, true); - wheelEvent->deltaX = oldWheelEvent->deltaX; - wheelEvent->deltaY = oldWheelEvent->deltaY; - wheelEvent->deltaZ = oldWheelEvent->deltaZ; - wheelEvent->deltaMode = oldWheelEvent->deltaMode; - wheelEvent->relatedTarget = oldWheelEvent->relatedTarget; - wheelEvent->button = oldWheelEvent->button; - wheelEvent->buttons = oldWheelEvent->buttons; - wheelEvent->modifiers = oldWheelEvent->modifiers; - wheelEvent->inputSource = oldWheelEvent->inputSource; - wheelEvent->customizedByUserPrefs = oldWheelEvent->customizedByUserPrefs; - wheelEvent->isMomentum = oldWheelEvent->isMomentum; - wheelEvent->isPixelOnlyDevice = oldWheelEvent->isPixelOnlyDevice; - wheelEvent->lineOrPageDeltaX = oldWheelEvent->lineOrPageDeltaX; - wheelEvent->lineOrPageDeltaY = oldWheelEvent->lineOrPageDeltaY; - wheelEvent->scrollType = oldWheelEvent->scrollType; - wheelEvent->overflowDeltaX = oldWheelEvent->overflowDeltaX; - wheelEvent->overflowDeltaY = oldWheelEvent->overflowDeltaY; + wheelEvent->AssignWheelEventData(*oldWheelEvent, true); newEvent = wheelEvent; break; } diff --git a/widget/nsGUIEvent.h b/widget/nsGUIEvent.h index 545be8e2fa5..6069b3d6657 100644 --- a/widget/nsGUIEvent.h +++ b/widget/nsGUIEvent.h @@ -1541,6 +1541,24 @@ public: // it would need to check the deltaX and deltaY. double overflowDeltaX; double overflowDeltaY; + + void AssignWheelEventData(const WheelEvent& aEvent, bool aCopyTargets) + { + AssignMouseEventBaseData(aEvent, aCopyTargets); + + deltaX = aEvent.deltaX; + deltaY = aEvent.deltaY; + deltaZ = aEvent.deltaZ; + deltaMode = aEvent.deltaMode; + customizedByUserPrefs = aEvent.customizedByUserPrefs; + isMomentum = aEvent.isMomentum; + isPixelOnlyDevice = aEvent.isPixelOnlyDevice; + lineOrPageDeltaX = aEvent.lineOrPageDeltaX; + lineOrPageDeltaY = aEvent.lineOrPageDeltaY; + scrollType = aEvent.scrollType; + overflowDeltaX = aEvent.overflowDeltaX; + overflowDeltaY = aEvent.overflowDeltaY; + } }; } // namespace widget diff --git a/widget/tests/test_assign_event_data.html b/widget/tests/test_assign_event_data.html index a91a5e1e76c..37fa23dd533 100644 --- a/widget/tests/test_assign_event_data.html +++ b/widget/tests/test_assign_event_data.html @@ -312,6 +312,43 @@ const kTests = [ }, todoMismatch: [ ], }, + { description: "widget::WheelEvent (wheel, vertical)", + targetID: "input-text", eventType: "wheel", + dispatchEvent: function () { + document.getElementById(this.targetID).value = ""; + synthesizeWheel(document.getElementById(this.targetID), 3, 4, + { deltaY: 20, lineOrPageDeltaY: 1, altKey: true }); + }, + canRun: function () { + return true; + }, + todoMismatch: [ ], + }, + { description: "widget::WheelEvent (wheel, horizontal)", + targetID: "input-text", eventType: "wheel", + dispatchEvent: function () { + document.getElementById(this.targetID).value = ""; + synthesizeWheel(document.getElementById(this.targetID), 4, 5, + { deltaX: 20, lineOrPageDeltaX: 1, ctrlKey: true }); + }, + canRun: function () { + return true; + }, + todoMismatch: [ ], + }, + { description: "widget::WheelEvent (wheel, both)", + targetID: "input-text", eventType: "wheel", + dispatchEvent: function () { + document.getElementById(this.targetID).value = ""; + synthesizeWheel(document.getElementById(this.targetID), 4, 5, + { deltaX: 20, deltaY: 10, + lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 }); + }, + canRun: function () { + return true; + }, + todoMismatch: [ ], + }, ]; function doTest(aTest) From 8572bd511248fb6a9a6cade2737c47d76e567dbb Mon Sep 17 00:00:00 2001 From: Masayuki Nakano Date: Tue, 3 Sep 2013 20:45:29 +0900 Subject: [PATCH 25/64] Bug 910978 part.10 Implement nsTouchEvent::AssignTouchEventData() r=smaug --- content/events/src/nsDOMEvent.cpp | 2 +- widget/nsGUIEvent.h | 7 +++++++ widget/tests/test_assign_event_data.html | 20 ++++++++++++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/content/events/src/nsDOMEvent.cpp b/content/events/src/nsDOMEvent.cpp index 20ab4b3656c..f10ce3a75cc 100644 --- a/content/events/src/nsDOMEvent.cpp +++ b/content/events/src/nsDOMEvent.cpp @@ -741,7 +741,7 @@ nsDOMEvent::DuplicatePrivateData() { nsTouchEvent* oldTouchEvent = static_cast(mEvent); nsTouchEvent* touchEvent = new nsTouchEvent(false, oldTouchEvent); - touchEvent->AssignInputEventData(*oldTouchEvent, true); + touchEvent->AssignTouchEventData(*oldTouchEvent, true); newEvent = touchEvent; break; } diff --git a/widget/nsGUIEvent.h b/widget/nsGUIEvent.h index 6069b3d6657..211f2c8ed4a 100644 --- a/widget/nsGUIEvent.h +++ b/widget/nsGUIEvent.h @@ -1785,6 +1785,13 @@ public: } nsTArray< nsRefPtr > touches; + + void AssignTouchEventData(const nsTouchEvent& aEvent, bool aCopyTargets) + { + AssignInputEventData(aEvent, aCopyTargets); + + // Currently, we don't need to copy touches. + } }; /** diff --git a/widget/tests/test_assign_event_data.html b/widget/tests/test_assign_event_data.html index 37fa23dd533..2cf67169040 100644 --- a/widget/tests/test_assign_event_data.html +++ b/widget/tests/test_assign_event_data.html @@ -349,6 +349,26 @@ const kTests = [ }, todoMismatch: [ ], }, + { description: "nsTouchEvent (touchstart)", + target: function () { return document; }, eventType: "touchstart", + dispatchEvent: function () { + synthesizeTouchAtPoint(1, 2, { id: 10, rx: 4, ry: 3, angle: 0, force: 1, shiftKey: true}); + }, + canRun: function () { + return true; + }, + todoMismatch: [ ], + }, + { description: "nsTouchEvent (touchend)", + target: function () { return document; }, eventType: "touchend", + dispatchEvent: function () { + synthesizeTouchAtPoint(4, 6, { id: 5, rx: 1, ry: 2, angle: 0.5, force: 0.8, ctrlKey: true}); + }, + canRun: function () { + return true; + }, + todoMismatch: [ ], + }, ]; function doTest(aTest) From ffc994f8f58a4083cfaf672346ed97006acc7e18 Mon Sep 17 00:00:00 2001 From: Masayuki Nakano Date: Tue, 3 Sep 2013 20:45:29 +0900 Subject: [PATCH 26/64] Bug 910978 part.11 Implement nsFormEvent::AssignFormEventData() r=smaug --- content/events/src/nsDOMEvent.cpp | 2 +- widget/nsGUIEvent.h | 7 +++++++ widget/tests/test_assign_event_data.html | 11 +++++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/content/events/src/nsDOMEvent.cpp b/content/events/src/nsDOMEvent.cpp index f10ce3a75cc..7ffb98b55a8 100644 --- a/content/events/src/nsDOMEvent.cpp +++ b/content/events/src/nsDOMEvent.cpp @@ -648,7 +648,7 @@ nsDOMEvent::DuplicatePrivateData() { nsFormEvent* oldFormEvent = static_cast(mEvent); nsFormEvent* formEvent = new nsFormEvent(false, msg); - formEvent->AssignEventData(*oldFormEvent, true); + formEvent->AssignFormEventData(*oldFormEvent, true); newEvent = formEvent; break; } diff --git a/widget/nsGUIEvent.h b/widget/nsGUIEvent.h index 211f2c8ed4a..5fc6a20d21c 100644 --- a/widget/nsGUIEvent.h +++ b/widget/nsGUIEvent.h @@ -1811,6 +1811,13 @@ public: } nsIContent *originator; + + void AssignFormEventData(const nsFormEvent& aEvent, bool aCopyTargets) + { + AssignEventData(aEvent, aCopyTargets); + + // Don't copy originator due to a weak pointer. + } }; /** diff --git a/widget/tests/test_assign_event_data.html b/widget/tests/test_assign_event_data.html index 2cf67169040..6b478b29c95 100644 --- a/widget/tests/test_assign_event_data.html +++ b/widget/tests/test_assign_event_data.html @@ -13,6 +13,7 @@
    +
    @@ -369,6 +370,16 @@ const kTests = [ }, todoMismatch: [ ], }, + { description: "nsFormEvent (reset)", + targetID: "form", eventType: "reset", + dispatchEvent: function () { + document.getElementById("form").reset(); + }, + canRun: function () { + return true; + }, + todoMismatch: [ ], + }, ]; function doTest(aTest) From 37a09fd4f96ed4b6a83a9da5b4746e2640845551 Mon Sep 17 00:00:00 2001 From: Masayuki Nakano Date: Tue, 3 Sep 2013 20:45:29 +0900 Subject: [PATCH 27/64] Bug 910978 part.12 Implement nsCommandEvent::AssignCommandEventData() r=smaug --- content/events/src/nsDOMEvent.cpp | 2 +- widget/nsGUIEvent.h | 8 ++++++++ widget/tests/test_assign_event_data.html | 11 +++++++++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/content/events/src/nsDOMEvent.cpp b/content/events/src/nsDOMEvent.cpp index 7ffb98b55a8..f7b3957017e 100644 --- a/content/events/src/nsDOMEvent.cpp +++ b/content/events/src/nsDOMEvent.cpp @@ -668,7 +668,7 @@ nsDOMEvent::DuplicatePrivateData() nsCommandEvent* commandEvent = new nsCommandEvent(false, mEvent->userType, oldCommandEvent->command, nullptr); - commandEvent->AssignGUIEventData(*oldCommandEvent, true); + commandEvent->AssignCommandEventData(*oldCommandEvent, true); newEvent = commandEvent; break; } diff --git a/widget/nsGUIEvent.h b/widget/nsGUIEvent.h index 5fc6a20d21c..3ed561f32aa 100644 --- a/widget/nsGUIEvent.h +++ b/widget/nsGUIEvent.h @@ -1838,6 +1838,14 @@ public: } nsCOMPtr command; + + // XXX Not tested by test_assign_event_data.html + void AssignCommandEventData(const nsCommandEvent& aEvent, bool aCopyTargets) + { + AssignGUIEventData(aEvent, aCopyTargets); + + // command must have been initialized with the constructor. + } }; /** diff --git a/widget/tests/test_assign_event_data.html b/widget/tests/test_assign_event_data.html index 6b478b29c95..5cee12ff076 100644 --- a/widget/tests/test_assign_event_data.html +++ b/widget/tests/test_assign_event_data.html @@ -380,6 +380,17 @@ const kTests = [ }, todoMismatch: [ ], }, + { description: "nsCommandEvent", + targetID: "input-text", eventType: "", + dispatchEvent: function () { + return; + }, + canRun: function () { + todo(false, "nsCommandEvent isn't tested"); + return false; + }, + todoMismatch: [], + }, ]; function doTest(aTest) From 694e27ec0a8413fc5864920a6226f767e42aa2a8 Mon Sep 17 00:00:00 2001 From: Masayuki Nakano Date: Tue, 3 Sep 2013 20:45:29 +0900 Subject: [PATCH 28/64] Bug 910978 part.13 Implement nsClipboardEvent::AssignClipboardEventData() r=smaug --- content/events/src/nsDOMEvent.cpp | 3 +-- widget/nsGUIEvent.h | 8 ++++++++ widget/tests/test_assign_event_data.html | 13 +++++++++++++ 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/content/events/src/nsDOMEvent.cpp b/content/events/src/nsDOMEvent.cpp index f7b3957017e..e0f5dd9941c 100644 --- a/content/events/src/nsDOMEvent.cpp +++ b/content/events/src/nsDOMEvent.cpp @@ -558,8 +558,7 @@ nsDOMEvent::DuplicatePrivateData() { nsClipboardEvent* oldClipboardEvent = static_cast(mEvent); nsClipboardEvent* clipboardEvent = new nsClipboardEvent(false, msg); - clipboardEvent->AssignEventData(*oldClipboardEvent, true); - clipboardEvent->clipboardData = oldClipboardEvent->clipboardData; + clipboardEvent->AssignClipboardEventData(*oldClipboardEvent, true); newEvent = clipboardEvent; break; } diff --git a/widget/nsGUIEvent.h b/widget/nsGUIEvent.h index 3ed561f32aa..98e1677eff9 100644 --- a/widget/nsGUIEvent.h +++ b/widget/nsGUIEvent.h @@ -1860,6 +1860,14 @@ public: } nsCOMPtr clipboardData; + + void AssignClipboardEventData(const nsClipboardEvent& aEvent, + bool aCopyTargets) + { + AssignEventData(aEvent, aCopyTargets); + + clipboardData = aEvent.clipboardData; + } }; /** diff --git a/widget/tests/test_assign_event_data.html b/widget/tests/test_assign_event_data.html index 5cee12ff076..93c6d82388b 100644 --- a/widget/tests/test_assign_event_data.html +++ b/widget/tests/test_assign_event_data.html @@ -391,6 +391,19 @@ const kTests = [ }, todoMismatch: [], }, + { description: "nsClipboardEvent (copy)", + targetID: "input-text", eventType: "copy", + dispatchEvent: function () { + document.getElementById("input-text").value = "go to clipboard!"; + document.getElementById("input-text").focus(); + document.getElementById("input-text").select(); + synthesizeKey("c", { accelKey: true }); + }, + canRun: function () { + return true; + }, + todoMismatch: [ ], + }, ]; function doTest(aTest) From 0dec671ed9276d2b358205a0d9e75c057060bcb4 Mon Sep 17 00:00:00 2001 From: Masayuki Nakano Date: Tue, 3 Sep 2013 20:45:29 +0900 Subject: [PATCH 29/64] Bug 910978 part.14 Implement nsUIEvent::AssignUIEventData() r=smaug --- content/events/src/nsDOMEvent.cpp | 4 ++-- widget/nsGUIEvent.h | 7 +++++++ widget/tests/test_assign_event_data.html | 11 +++++++++++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/content/events/src/nsDOMEvent.cpp b/content/events/src/nsDOMEvent.cpp index e0f5dd9941c..635855b8f40 100644 --- a/content/events/src/nsDOMEvent.cpp +++ b/content/events/src/nsDOMEvent.cpp @@ -675,7 +675,7 @@ nsDOMEvent::DuplicatePrivateData() { nsUIEvent* oldUIEvent = static_cast(mEvent); nsUIEvent* uiEvent = new nsUIEvent(false, msg, oldUIEvent->detail); - uiEvent->AssignEventData(*oldUIEvent, true); + uiEvent->AssignUIEventData(*oldUIEvent, true); newEvent = uiEvent; break; } @@ -693,7 +693,7 @@ nsDOMEvent::DuplicatePrivateData() nsUIEvent* oldUIEvent = static_cast(mEvent); nsUIEvent* uiEvent = new nsUIEvent(false, msg, 0); uiEvent->eventStructType = NS_SMIL_TIME_EVENT; - uiEvent->AssignGUIEventData(*oldUIEvent, true); + uiEvent->AssignUIEventData(*oldUIEvent, true); newEvent = uiEvent; break; } diff --git a/widget/nsGUIEvent.h b/widget/nsGUIEvent.h index 98e1677eff9..858554ccbb9 100644 --- a/widget/nsGUIEvent.h +++ b/widget/nsGUIEvent.h @@ -1883,6 +1883,13 @@ public: } int32_t detail; + + void AssignUIEventData(const nsUIEvent& aEvent, bool aCopyTargets) + { + AssignGUIEventData(aEvent, aCopyTargets); + + // detail must have been initialized with the constructor. + } }; class nsFocusEvent : public nsUIEvent diff --git a/widget/tests/test_assign_event_data.html b/widget/tests/test_assign_event_data.html index 93c6d82388b..b31b31b0f1c 100644 --- a/widget/tests/test_assign_event_data.html +++ b/widget/tests/test_assign_event_data.html @@ -404,6 +404,17 @@ const kTests = [ }, todoMismatch: [ ], }, + { description: "nsUIEvent (DOMActivate)", + targetID: "button", eventType: "DOMActivate", + dispatchEvent: function () { + synthesizeMouseAtCenter(document.getElementById(this.targetID), + { button: 0, shiftKey: true }); + }, + canRun: function () { + return true; + }, + todoMismatch: [], + }, ]; function doTest(aTest) From 5bac5acde7a60b4c2b2e84fe01f82d9f48a04915 Mon Sep 17 00:00:00 2001 From: Masayuki Nakano Date: Tue, 3 Sep 2013 20:45:29 +0900 Subject: [PATCH 30/64] Bug 910978 part.15 Implement nsFocusEvent::AssignFocusEventData() r=smaug --- content/events/src/nsDOMEvent.cpp | 4 +--- widget/nsGUIEvent.h | 9 +++++++++ widget/tests/test_assign_event_data.html | 20 ++++++++++++++++++++ 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/content/events/src/nsDOMEvent.cpp b/content/events/src/nsDOMEvent.cpp index 635855b8f40..eac7a69f92d 100644 --- a/content/events/src/nsDOMEvent.cpp +++ b/content/events/src/nsDOMEvent.cpp @@ -655,9 +655,7 @@ nsDOMEvent::DuplicatePrivateData() { nsFocusEvent* newFocusEvent = new nsFocusEvent(false, msg); nsFocusEvent* oldFocusEvent = static_cast(mEvent); - newFocusEvent->AssignGUIEventData(*oldFocusEvent, true); - newFocusEvent->fromRaise = oldFocusEvent->fromRaise; - newFocusEvent->isRefocus = oldFocusEvent->isRefocus; + newFocusEvent->AssignFocusEventData(*oldFocusEvent, true); newEvent = newFocusEvent; break; } diff --git a/widget/nsGUIEvent.h b/widget/nsGUIEvent.h index 858554ccbb9..4726132668f 100644 --- a/widget/nsGUIEvent.h +++ b/widget/nsGUIEvent.h @@ -1908,6 +1908,15 @@ public: bool fromRaise; bool isRefocus; + + void AssignFocusEventData(const nsFocusEvent& aEvent, bool aCopyTargets) + { + AssignUIEventData(aEvent, aCopyTargets); + + relatedTarget = aCopyTargets ? aEvent.relatedTarget : nullptr; + fromRaise = aEvent.fromRaise; + isRefocus = aEvent.isRefocus; + } }; /** diff --git a/widget/tests/test_assign_event_data.html b/widget/tests/test_assign_event_data.html index b31b31b0f1c..a9965e846b2 100644 --- a/widget/tests/test_assign_event_data.html +++ b/widget/tests/test_assign_event_data.html @@ -415,6 +415,26 @@ const kTests = [ }, todoMismatch: [], }, + { description: "nsFocusEvent (focus)", + targetID: "input-text", eventType: "focus", + dispatchEvent: function () { + document.getElementById(this.targetID).focus(); + }, + canRun: function () { + return true; + }, + todoMismatch: [], + }, + { description: "nsFocusEvent (blur)", + targetID: "input-text", eventType: "blur", + dispatchEvent: function () { + document.getElementById(this.targetID).blur(); + }, + canRun: function () { + return true; + }, + todoMismatch: [], + }, ]; function doTest(aTest) From 1db2e51d440484db8cfab5a80a31d7fc5ddb3742 Mon Sep 17 00:00:00 2001 From: Masayuki Nakano Date: Tue, 3 Sep 2013 20:45:30 +0900 Subject: [PATCH 31/64] Bug 910978 part.16 Implement nsSimpleGestureEvent::AssignSimpleGestureEventData() r=smaug --- content/events/src/nsDOMEvent.cpp | 6 ++---- widget/nsGUIEvent.h | 12 ++++++++++++ widget/tests/test_assign_event_data.html | 13 +++++++++++++ 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/content/events/src/nsDOMEvent.cpp b/content/events/src/nsDOMEvent.cpp index eac7a69f92d..ab3285ef935 100644 --- a/content/events/src/nsDOMEvent.cpp +++ b/content/events/src/nsDOMEvent.cpp @@ -701,10 +701,8 @@ nsDOMEvent::DuplicatePrivateData() static_cast(mEvent); nsSimpleGestureEvent* simpleGestureEvent = new nsSimpleGestureEvent(false, msg, nullptr, 0, 0.0); - simpleGestureEvent->AssignInputEventData(*oldSimpleGestureEvent, true); - simpleGestureEvent->direction = oldSimpleGestureEvent->direction; - simpleGestureEvent->delta = oldSimpleGestureEvent->delta; - simpleGestureEvent->clickCount = oldSimpleGestureEvent->clickCount; + simpleGestureEvent-> + AssignSimpleGestureEventData(*oldSimpleGestureEvent, true); newEvent = simpleGestureEvent; break; } diff --git a/widget/nsGUIEvent.h b/widget/nsGUIEvent.h index 4726132668f..c122a4df128 100644 --- a/widget/nsGUIEvent.h +++ b/widget/nsGUIEvent.h @@ -1944,6 +1944,18 @@ public: uint32_t direction; // See nsIDOMSimpleGestureEvent for values double delta; // Delta for magnify and rotate events uint32_t clickCount; // The number of taps for tap events + + // XXX Not tested by test_assign_event_data.html + void AssignSimpleGestureEventData(const nsSimpleGestureEvent& aEvent, + bool aCopyTargets) + { + AssignMouseEventBaseData(aEvent, aCopyTargets); + + // allowedDirections isn't copied + direction = aEvent.direction; + delta = aEvent.delta; + clickCount = aEvent.clickCount; + } }; class nsTransitionEvent : public nsEvent diff --git a/widget/tests/test_assign_event_data.html b/widget/tests/test_assign_event_data.html index a9965e846b2..85876e9e8ae 100644 --- a/widget/tests/test_assign_event_data.html +++ b/widget/tests/test_assign_event_data.html @@ -435,6 +435,19 @@ const kTests = [ }, todoMismatch: [], }, + { description: "nsSimpleGestureEvent", + targetID: "", eventType: "", + dispatchEvent: function () { + return; + }, + canRun: function () { + // Simple gesture event may be handled before it comes content. + // So, we cannot test it in this test. + todo(false, "nsSimpleGestureEvent isn't tested"); + return false; + }, + todoMismatch: [], + }, ]; function doTest(aTest) From 1c1e1f20ff116d1c36d2236cceee327a28206b30 Mon Sep 17 00:00:00 2001 From: Masayuki Nakano Date: Tue, 3 Sep 2013 20:45:30 +0900 Subject: [PATCH 32/64] Bug 910978 part.17 Implement nsTransitionEvent::AssignTransitionEventData() r=smaug --- content/events/src/nsDOMEvent.cpp | 2 +- widget/nsGUIEvent.h | 9 +++++++++ widget/tests/test_assign_event_data.html | 20 ++++++++++++++++++++ 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/content/events/src/nsDOMEvent.cpp b/content/events/src/nsDOMEvent.cpp index ab3285ef935..7b9b847c3ef 100644 --- a/content/events/src/nsDOMEvent.cpp +++ b/content/events/src/nsDOMEvent.cpp @@ -715,7 +715,7 @@ nsDOMEvent::DuplicatePrivateData() oldTransitionEvent->propertyName, oldTransitionEvent->elapsedTime, oldTransitionEvent->pseudoElement); - transitionEvent->AssignEventData(*oldTransitionEvent, true); + transitionEvent->AssignTransitionEventData(*oldTransitionEvent, true); newEvent = transitionEvent; break; } diff --git a/widget/nsGUIEvent.h b/widget/nsGUIEvent.h index c122a4df128..7de9575dd03 100644 --- a/widget/nsGUIEvent.h +++ b/widget/nsGUIEvent.h @@ -1973,6 +1973,15 @@ public: nsString propertyName; float elapsedTime; nsString pseudoElement; + + void AssignTransitionEventData(const nsTransitionEvent& aEvent, + bool aCopyTargets) + { + AssignEventData(aEvent, aCopyTargets); + + // propertyName, elapsedTime and pseudoElement must have been initialized + // with the constructor. + } }; class nsAnimationEvent : public nsEvent diff --git a/widget/tests/test_assign_event_data.html b/widget/tests/test_assign_event_data.html index 85876e9e8ae..f7e8ab4bc07 100644 --- a/widget/tests/test_assign_event_data.html +++ b/widget/tests/test_assign_event_data.html @@ -7,11 +7,21 @@ +
    @@ -448,6 +458,16 @@ const kTests = [ }, todoMismatch: [], }, + { description: "nsTransitionEvent (transitionend)", + targetID: "a", eventType: "transitionend", + dispatchEvent: function () { + document.getElementById(this.targetID).focus(); + }, + canRun: function () { + return true; + }, + todoMismatch: [], + }, ]; function doTest(aTest) From b30c3feef640b8c47ac53b8b516ca0c47bb82e10 Mon Sep 17 00:00:00 2001 From: Masayuki Nakano Date: Tue, 3 Sep 2013 20:45:30 +0900 Subject: [PATCH 33/64] Bug 910978 part.18 Implement nsAnimationEvent::AssignAnimationEventData() r=smaug --- content/events/src/nsDOMEvent.cpp | 2 +- widget/nsGUIEvent.h | 9 ++++++++ widget/tests/test_assign_event_data.html | 26 ++++++++++++++++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/content/events/src/nsDOMEvent.cpp b/content/events/src/nsDOMEvent.cpp index 7b9b847c3ef..c668dbca8f8 100644 --- a/content/events/src/nsDOMEvent.cpp +++ b/content/events/src/nsDOMEvent.cpp @@ -728,7 +728,7 @@ nsDOMEvent::DuplicatePrivateData() oldAnimationEvent->animationName, oldAnimationEvent->elapsedTime, oldAnimationEvent->pseudoElement); - animationEvent->AssignEventData(*oldAnimationEvent, true); + animationEvent->AssignAnimationEventData(*oldAnimationEvent, true); newEvent = animationEvent; break; } diff --git a/widget/nsGUIEvent.h b/widget/nsGUIEvent.h index 7de9575dd03..591f04aed6e 100644 --- a/widget/nsGUIEvent.h +++ b/widget/nsGUIEvent.h @@ -1999,6 +1999,15 @@ public: nsString animationName; float elapsedTime; nsString pseudoElement; + + void AssignAnimationEventData(const nsAnimationEvent& aEvent, + bool aCopyTargets) + { + AssignEventData(aEvent, aCopyTargets); + + // animationName, elapsedTime and pseudoElement must have been initialized + // with the constructor. + } }; /** diff --git a/widget/tests/test_assign_event_data.html b/widget/tests/test_assign_event_data.html index f7e8ab4bc07..13a0eb5cedf 100644 --- a/widget/tests/test_assign_event_data.html +++ b/widget/tests/test_assign_event_data.html @@ -15,6 +15,21 @@ #a:focus { background-color: red; } + .slidin { + border: green 1px solid; + width: 10px; + height: 10px; + animation-name: slidein; + animation-duration: 1s; + } + @keyframes slidein { + from { + margin-left: 100%; + } + to { + margin-left: 0; + } + } @@ -24,6 +39,7 @@ hyper link
    +
    @@ -468,6 +484,16 @@ const kTests = [ }, todoMismatch: [], }, + { description: "nsAnimationEvent (animationend)", + targetID: "animated-div", eventType: "animationend", + dispatchEvent: function () { + document.getElementById(this.targetID).className = "slidin"; + }, + canRun: function () { + return true; + }, + todoMismatch: [], + }, ]; function doTest(aTest) From 64b404534a78ce31dbc2058f0573530c82036870 Mon Sep 17 00:00:00 2001 From: Masayuki Nakano Date: Tue, 3 Sep 2013 20:45:30 +0900 Subject: [PATCH 34/64] Bug 910978 part.19 Implement nsMutationEvent::AssignMutationEventData() r=smaug --- content/events/public/nsMutationEvent.h | 11 ++++++++ content/events/src/nsDOMEvent.cpp | 7 +----- widget/tests/test_assign_event_data.html | 32 ++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 6 deletions(-) diff --git a/content/events/public/nsMutationEvent.h b/content/events/public/nsMutationEvent.h index 1e2a9133fa3..97134dedd47 100644 --- a/content/events/public/nsMutationEvent.h +++ b/content/events/public/nsMutationEvent.h @@ -25,6 +25,17 @@ public: nsCOMPtr mPrevAttrValue; nsCOMPtr mNewAttrValue; unsigned short mAttrChange; + + void AssignMutationEventData(const nsMutationEvent& aEvent, bool aCopyTargets) + { + AssignEventData(aEvent, aCopyTargets); + + mRelatedNode = aEvent.mRelatedNode; + mAttrName = aEvent.mAttrName; + mPrevAttrValue = aEvent.mPrevAttrValue; + mNewAttrValue = aEvent.mNewAttrValue; + mAttrChange = aEvent.mAttrChange; + } }; #define NS_MUTATION_START 1800 diff --git a/content/events/src/nsDOMEvent.cpp b/content/events/src/nsDOMEvent.cpp index c668dbca8f8..3470fafecf0 100644 --- a/content/events/src/nsDOMEvent.cpp +++ b/content/events/src/nsDOMEvent.cpp @@ -634,12 +634,7 @@ nsDOMEvent::DuplicatePrivateData() nsMutationEvent* mutationEvent = new nsMutationEvent(false, msg); nsMutationEvent* oldMutationEvent = static_cast(mEvent); - mutationEvent->AssignEventData(*oldMutationEvent, true); - mutationEvent->mRelatedNode = oldMutationEvent->mRelatedNode; - mutationEvent->mAttrName = oldMutationEvent->mAttrName; - mutationEvent->mPrevAttrValue = oldMutationEvent->mPrevAttrValue; - mutationEvent->mNewAttrValue = oldMutationEvent->mNewAttrValue; - mutationEvent->mAttrChange = oldMutationEvent->mAttrChange; + mutationEvent->AssignMutationEventData(*oldMutationEvent, true); newEvent = mutationEvent; break; } diff --git a/widget/tests/test_assign_event_data.html b/widget/tests/test_assign_event_data.html index 13a0eb5cedf..e02ec29e37d 100644 --- a/widget/tests/test_assign_event_data.html +++ b/widget/tests/test_assign_event_data.html @@ -494,6 +494,38 @@ const kTests = [ }, todoMismatch: [], }, + { description: "nsMutationEvent (DOMAttrModified)", + targetID: "animated-div", eventType: "DOMAttrModified", + dispatchEvent: function () { + document.getElementById(this.targetID).setAttribute("x-data", "foo"); + }, + canRun: function () { + return true; + }, + todoMismatch: [], + }, + { description: "nsMutationEvent (DOMNodeInserted)", + targetID: "animated-div", eventType: "DOMNodeInserted", + dispatchEvent: function () { + var div = document.createElement("div"); + div.id = "inserted-div"; + document.getElementById("animated-div").appendChild(div); + }, + canRun: function () { + return true; + }, + todoMismatch: [], + }, + { description: "nsMutationEvent (DOMNodeRemoved)", + targetID: "animated-div", eventType: "DOMNodeRemoved", + dispatchEvent: function () { + document.getElementById("animated-div").removeChild(document.getElementById("inserted-div")); + }, + canRun: function () { + return true; + }, + todoMismatch: [], + }, ]; function doTest(aTest) From 4956384f89d91584018aafaeea523ea50d5a4760 Mon Sep 17 00:00:00 2001 From: Andrea Marchesini Date: Tue, 3 Sep 2013 14:38:49 +0200 Subject: [PATCH 35/64] Bug 677638 - Patch 1 - MessageChannel and MessagePort interfaces, r=smaug --- dom/base/MessageChannel.cpp | 62 +++++++++++++++++++ dom/base/MessageChannel.h | 70 +++++++++++++++++++++ dom/base/MessagePort.cpp | 86 ++++++++++++++++++++++++++ dom/base/MessagePort.h | 59 ++++++++++++++++++ dom/base/moz.build | 4 ++ dom/base/test/Makefile.in | 1 + dom/base/test/test_messageChannel.html | 43 +++++++++++++ dom/webidl/MessageChannel.webidl | 14 +++++ dom/webidl/MessagePort.webidl | 20 ++++++ dom/webidl/WebIDL.mk | 2 + 10 files changed, 361 insertions(+) create mode 100644 dom/base/MessageChannel.cpp create mode 100644 dom/base/MessageChannel.h create mode 100644 dom/base/MessagePort.cpp create mode 100644 dom/base/MessagePort.h create mode 100644 dom/base/test/test_messageChannel.html create mode 100644 dom/webidl/MessageChannel.webidl create mode 100644 dom/webidl/MessagePort.webidl diff --git a/dom/base/MessageChannel.cpp b/dom/base/MessageChannel.cpp new file mode 100644 index 00000000000..e759b522b9d --- /dev/null +++ b/dom/base/MessageChannel.cpp @@ -0,0 +1,62 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "MessageChannel.h" +#include "mozilla/dom/MessageChannelBinding.h" +#include "mozilla/dom/MessagePort.h" +#include "nsContentUtils.h" +#include "nsPIDOMWindow.h" + +namespace mozilla { +namespace dom { + +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_3(MessageChannel, mWindow, mPort1, mPort2) +NS_IMPL_CYCLE_COLLECTING_ADDREF(MessageChannel) +NS_IMPL_CYCLE_COLLECTING_RELEASE(MessageChannel) + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MessageChannel) + NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY + NS_INTERFACE_MAP_ENTRY(nsISupports) +NS_INTERFACE_MAP_END + +MessageChannel::MessageChannel(nsPIDOMWindow* aWindow) + : mWindow(aWindow) +{ + MOZ_COUNT_CTOR(MessageChannel); + SetIsDOMBinding(); + + mPort1 = new MessagePort(mWindow); + mPort2 = new MessagePort(mWindow); + + mPort1->Entangle(mPort2); + mPort2->Entangle(mPort1); +} + +MessageChannel::~MessageChannel() +{ + MOZ_COUNT_DTOR(MessageChannel); +} + +JSObject* +MessageChannel::WrapObject(JSContext* aCx, JS::Handle aScope) +{ + return MessageChannelBinding::Wrap(aCx, aScope, this); +} + +/* static */ already_AddRefed +MessageChannel::Constructor(const GlobalObject& aGlobal, ErrorResult& aRv) +{ + nsCOMPtr window = do_QueryInterface(aGlobal.GetAsSupports()); + if (!window) { + aRv.Throw(NS_ERROR_UNEXPECTED); + return nullptr; + } + + nsRefPtr channel = new MessageChannel(window); + return channel.forget(); +} + +} // namespace dom +} // namespace mozilla diff --git a/dom/base/MessageChannel.h b/dom/base/MessageChannel.h new file mode 100644 index 00000000000..5b945a52a22 --- /dev/null +++ b/dom/base/MessageChannel.h @@ -0,0 +1,70 @@ + +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_MessageChannel_h +#define mozilla_dom_MessageChannel_h + +#include "mozilla/Attributes.h" +#include "mozilla/ErrorResult.h" +#include "mozilla/dom/BindingDeclarations.h" +#include "nsCycleCollectionParticipant.h" +#include "nsWrapperCache.h" +#include "nsCOMPtr.h" + +class nsPIDOMWindow; + +namespace mozilla { +namespace dom { + +class MessagePort; + +class MessageChannel MOZ_FINAL : public nsISupports + , public nsWrapperCache +{ +public: + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(MessageChannel) + +public: + MessageChannel(nsPIDOMWindow* aWindow); + + ~MessageChannel(); + + nsPIDOMWindow* + GetParentObject() const + { + return mWindow; + } + + virtual JSObject* + WrapObject(JSContext* aCx, JS::Handle aScope) MOZ_OVERRIDE; + + static already_AddRefed + Constructor(const GlobalObject& aGlobal, ErrorResult& aRv); + + MessagePort* + Port1() const + { + return mPort1; + } + + MessagePort* + Port2() const + { + return mPort2; + } + +private: + nsCOMPtr mWindow; + + nsRefPtr mPort1; + nsRefPtr mPort2; +}; + +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_MessageChannel_h diff --git a/dom/base/MessagePort.cpp b/dom/base/MessagePort.cpp new file mode 100644 index 00000000000..e2aa15457ae --- /dev/null +++ b/dom/base/MessagePort.cpp @@ -0,0 +1,86 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "MessagePort.h" +#include "mozilla/dom/MessageChannel.h" +#include "mozilla/dom/MessagePortBinding.h" +#include "nsContentUtils.h" + +namespace mozilla { +namespace dom { + +NS_IMPL_CYCLE_COLLECTION_INHERITED_1(MessagePort, nsDOMEventTargetHelper, + mEntangledPort) + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(MessagePort) +NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper) + +NS_IMPL_ADDREF_INHERITED(MessagePort, nsDOMEventTargetHelper) +NS_IMPL_RELEASE_INHERITED(MessagePort, nsDOMEventTargetHelper) + +MessagePort::MessagePort(nsPIDOMWindow* aWindow) + : nsDOMEventTargetHelper(aWindow) +{ + MOZ_COUNT_CTOR(MessagePort); + SetIsDOMBinding(); +} + +MessagePort::~MessagePort() +{ + MOZ_COUNT_DTOR(MessagePort); + Close(); +} + +JSObject* +MessagePort::WrapObject(JSContext* aCx, JS::Handle aScope) +{ + return MessagePortBinding::Wrap(aCx, aScope, this); +} + +void +MessagePort::PostMessage(JSContext* aCx, JS::Handle aMessage, + const Optional >& aTransfer) +{ + if (!mEntangledPort) { + return; + } + + // TODO +} + +void +MessagePort::Start() +{ + // TODO +} + +void +MessagePort::Close() +{ + if (!mEntangledPort) { + return; + } + + // This avoids loops. + nsRefPtr port = mEntangledPort; + mEntangledPort = nullptr; + + // Let's disentangle the 2 ports symmetrically. + port->Close(); +} + +void +MessagePort::Entangle(MessagePort* aMessagePort) +{ + MOZ_ASSERT(aMessagePort); + MOZ_ASSERT(aMessagePort != this); + + Close(); + + mEntangledPort = aMessagePort; +} + +} // namespace dom +} // namespace mozilla diff --git a/dom/base/MessagePort.h b/dom/base/MessagePort.h new file mode 100644 index 00000000000..5dab2db0458 --- /dev/null +++ b/dom/base/MessagePort.h @@ -0,0 +1,59 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_MessagePort_h +#define mozilla_dom_MessagePort_h + +#include "mozilla/Attributes.h" +#include "mozilla/ErrorResult.h" +#include "nsDOMEventTargetHelper.h" + +class nsPIDOMWindow; + +namespace mozilla { +namespace dom { + +class MessagePort MOZ_FINAL : public nsDOMEventTargetHelper +{ +public: + NS_DECL_ISUPPORTS_INHERITED + NS_REALLY_FORWARD_NSIDOMEVENTTARGET(nsDOMEventTargetHelper) + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(MessagePort, + nsDOMEventTargetHelper) + + MessagePort(nsPIDOMWindow* aWindow); + ~MessagePort(); + + virtual JSObject* + WrapObject(JSContext* aCx, JS::Handle aScope) MOZ_OVERRIDE; + + void + PostMessage(JSContext* aCx, JS::Handle aMessage, + const Optional >& aTransfer); + + void + Start(); + + void + Close(); + + IMPL_EVENT_HANDLER(message) + + // Non WebIDL methods + + // This method entangles this MessagePort with another one. + // If it is already entangled, it's disentangled first and enatangle to the + // new one. + void + Entangle(MessagePort* aMessagePort); + +private: + nsRefPtr mEntangledPort; +}; + +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_MessagePort_h diff --git a/dom/base/moz.build b/dom/base/moz.build index daaca98791b..0f84ca35e42 100644 --- a/dom/base/moz.build +++ b/dom/base/moz.build @@ -55,6 +55,8 @@ EXPORTS.mozilla.dom += [ 'DOMCursor.h', 'DOMError.h', 'DOMRequest.h', + 'MessageChannel.h', + 'MessagePort.h', 'ScreenOrientation.h', 'StructuredCloneTags.h', 'URL.h', @@ -67,6 +69,8 @@ CPP_SOURCES += [ 'DOMError.cpp', 'DOMRequest.cpp', 'Navigator.cpp', + 'MessageChannel.cpp', + 'MessagePort.cpp', 'nsContentPermissionHelper.cpp', 'nsDOMClassInfo.cpp', 'nsDOMException.cpp', diff --git a/dom/base/test/Makefile.in b/dom/base/test/Makefile.in index ffbd1181078..f6974304298 100644 --- a/dom/base/test/Makefile.in +++ b/dom/base/test/Makefile.in @@ -31,6 +31,7 @@ MOCHITEST_FILES = \ test_Image_constructor.html \ test_setting_opener.html \ test_error.html \ + test_messageChannel.html \ $(NULL) MOCHITEST_CHROME_FILES = \ diff --git a/dom/base/test/test_messageChannel.html b/dom/base/test/test_messageChannel.html new file mode 100644 index 00000000000..3e761e299bf --- /dev/null +++ b/dom/base/test/test_messageChannel.html @@ -0,0 +1,43 @@ + + + + + + + Test for Bug 677638 - basic support + + + + +Mozilla Bug 677638 +

    + +
    +
    + + + diff --git a/dom/webidl/MessageChannel.webidl b/dom/webidl/MessageChannel.webidl new file mode 100644 index 00000000000..a8d46b4dddc --- /dev/null +++ b/dom/webidl/MessageChannel.webidl @@ -0,0 +1,14 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * For more information on this interface, please see + * http://www.whatwg.org/specs/web-apps/current-work/#channel-messaging + */ + +[Constructor] +interface MessageChannel { + readonly attribute MessagePort port1; + readonly attribute MessagePort port2; +}; diff --git a/dom/webidl/MessagePort.webidl b/dom/webidl/MessagePort.webidl new file mode 100644 index 00000000000..fa4f25579d8 --- /dev/null +++ b/dom/webidl/MessagePort.webidl @@ -0,0 +1,20 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * For more information on this interface, please see + * http://www.whatwg.org/specs/web-apps/current-work/#channel-messaging + */ + +interface MessagePort : EventTarget { + // TODO void postMessage(any message, optional sequence transfer); + void postMessage(any message, optional any transfer); + void start(); + void close(); + + // event handlers + [SetterThrows] + attribute EventHandler onmessage; +}; +// MessagePort implements Transferable; diff --git a/dom/webidl/WebIDL.mk b/dom/webidl/WebIDL.mk index 002d3a43208..09f93a37fc7 100644 --- a/dom/webidl/WebIDL.mk +++ b/dom/webidl/WebIDL.mk @@ -195,7 +195,9 @@ webidl_files = \ MediaStreamAudioSourceNode.webidl \ MediaStreamEvent.webidl \ MediaStreamTrack.webidl \ + MessageChannel.webidl \ MessageEvent.webidl \ + MessagePort.webidl \ MimeType.webidl \ MimeTypeArray.webidl \ MobileMessageManager.webidl \ From ab6d563731cc01f93dc550710da56469801ee931 Mon Sep 17 00:00:00 2001 From: Andrea Marchesini Date: Tue, 3 Sep 2013 14:38:51 +0200 Subject: [PATCH 36/64] Bug 677638 - MessagePorts in Structured Clone Algorithm, r=smaug --- dom/base/MessagePort.cpp | 20 ++++++ dom/base/MessagePort.h | 6 ++ dom/base/StructuredCloneTags.h | 1 + dom/base/nsGlobalWindow.cpp | 30 ++++++++ dom/base/test/Makefile.in | 2 + .../test/iframe_messageChannel_cloning.html | 22 ++++++ .../test/test_messageChannel_cloning.html | 70 +++++++++++++++++++ 7 files changed, 151 insertions(+) create mode 100644 dom/base/test/iframe_messageChannel_cloning.html create mode 100644 dom/base/test/test_messageChannel_cloning.html diff --git a/dom/base/MessagePort.cpp b/dom/base/MessagePort.cpp index e2aa15457ae..a7b593cad81 100644 --- a/dom/base/MessagePort.cpp +++ b/dom/base/MessagePort.cpp @@ -82,5 +82,25 @@ MessagePort::Entangle(MessagePort* aMessagePort) mEntangledPort = aMessagePort; } +already_AddRefed +MessagePort::Clone(nsPIDOMWindow* aWindow) +{ + nsRefPtr newPort = new MessagePort(aWindow); + + // TODO Move all the events in the port message queue of original port to the + // port message queue of new port, if any, leaving the new port's port + // message queue in its initial disabled state. + + if (mEntangledPort) { + nsRefPtr port = mEntangledPort; + mEntangledPort = nullptr; + + newPort->Entangle(port); + port->Entangle(newPort); + } + + return newPort.forget(); +} + } // namespace dom } // namespace mozilla diff --git a/dom/base/MessagePort.h b/dom/base/MessagePort.h index 5dab2db0458..84987c748f6 100644 --- a/dom/base/MessagePort.h +++ b/dom/base/MessagePort.h @@ -49,6 +49,12 @@ public: void Entangle(MessagePort* aMessagePort); + // Duplicate this message port. This method is used by the Structured Clone + // Algorithm and makes the new MessagePort active with the entangled + // MessagePort of this object. + already_AddRefed + Clone(nsPIDOMWindow* aWindow); + private: nsRefPtr mEntangledPort; }; diff --git a/dom/base/StructuredCloneTags.h b/dom/base/StructuredCloneTags.h index aa3781b2a3e..533d39f1b5e 100644 --- a/dom/base/StructuredCloneTags.h +++ b/dom/base/StructuredCloneTags.h @@ -28,6 +28,7 @@ enum StructuredCloneTags { // These tags are used for both main thread and workers. SCTAG_DOM_IMAGEDATA, + SCTAG_DOM_MESSAGEPORT, SCTAG_DOM_MAX }; diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index 752389dfcb1..31480eba8f7 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -189,6 +189,8 @@ #include "prenv.h" #include "prprf.h" +#include "mozilla/dom/MessagePort.h" +#include "mozilla/dom/MessagePortBinding.h" #include "mozilla/dom/indexedDB/IDBFactory.h" #include "mozilla/dom/quota/QuotaManager.h" @@ -6750,6 +6752,7 @@ namespace { struct StructuredCloneInfo { PostMessageEvent* event; bool subsumes; + nsPIDOMWindow* window; }; static JSObject* @@ -6779,6 +6782,21 @@ PostMessageReadStructuredClone(JSContext* cx, } } + if (tag == SCTAG_DOM_MESSAGEPORT) { + NS_ASSERTION(!data, "Data should be empty"); + + MessagePort* port; + if (JS_ReadBytes(reader, &port, sizeof(port))) { + JS::Rooted global(cx, JS::CurrentGlobalOrNull(cx)); + if (global) { + JS::Rooted obj(cx, port->WrapObject(cx, global)); + if (JS_WrapObject(cx, obj.address())) { + return obj; + } + } + } + } + const JSStructuredCloneCallbacks* runtimeCallbacks = js::GetContextStructuredCloneCallbacks(cx); @@ -6819,6 +6837,16 @@ PostMessageWriteStructuredClone(JSContext* cx, scInfo->event->StoreISupports(supports); } + MessagePort* port = nullptr; + nsresult rv = UNWRAP_OBJECT(MessagePort, cx, obj, port); + if (NS_SUCCEEDED(rv) && scInfo->subsumes) { + nsRefPtr newPort = port->Clone(scInfo->window); + + return JS_WriteUint32Pair(writer, SCTAG_DOM_MESSAGEPORT, 0) && + JS_WriteBytes(writer, &newPort, sizeof(newPort)) && + scInfo->event->StoreISupports(newPort); + } + const JSStructuredCloneCallbacks* runtimeCallbacks = js::GetContextStructuredCloneCallbacks(cx); @@ -6910,6 +6938,7 @@ PostMessageEvent::Run() { StructuredCloneInfo scInfo; scInfo.event = this; + scInfo.window = targetWindow; if (!buffer.read(cx, messageData.address(), &kPostMessageCallbacks, &scInfo)) { @@ -7056,6 +7085,7 @@ nsGlobalWindow::PostMessageMoz(const JS::Value& aMessage, JSAutoStructuredCloneBuffer buffer; StructuredCloneInfo scInfo; scInfo.event = event; + scInfo.window = this; nsIPrincipal* principal = GetPrincipal(); if (NS_FAILED(callerPrin->Subsumes(principal, &scInfo.subsumes))) diff --git a/dom/base/test/Makefile.in b/dom/base/test/Makefile.in index f6974304298..1a8f9a00904 100644 --- a/dom/base/test/Makefile.in +++ b/dom/base/test/Makefile.in @@ -32,6 +32,8 @@ MOCHITEST_FILES = \ test_setting_opener.html \ test_error.html \ test_messageChannel.html \ + test_messageChannel_cloning.html \ + iframe_messageChannel_cloning.html \ $(NULL) MOCHITEST_CHROME_FILES = \ diff --git a/dom/base/test/iframe_messageChannel_cloning.html b/dom/base/test/iframe_messageChannel_cloning.html new file mode 100644 index 00000000000..ee53e855a73 --- /dev/null +++ b/dom/base/test/iframe_messageChannel_cloning.html @@ -0,0 +1,22 @@ + + + + + + + diff --git a/dom/base/test/test_messageChannel_cloning.html b/dom/base/test/test_messageChannel_cloning.html new file mode 100644 index 00000000000..30327d5f162 --- /dev/null +++ b/dom/base/test/test_messageChannel_cloning.html @@ -0,0 +1,70 @@ + + + + + + Test for Bug 677638 - port cloning + + + + +Mozilla Bug 677638 +
    +
    +
    + + + From d6d8b274d783030907685797004a583e71e97c02 Mon Sep 17 00:00:00 2001 From: Andrea Marchesini Date: Tue, 3 Sep 2013 14:38:54 +0200 Subject: [PATCH 37/64] Bug 677638 - MessagePort.PostMessage --- dom/base/MessagePort.cpp | 259 +++++++++++++++++- dom/base/MessagePort.h | 3 +- dom/base/test/Makefile.in | 3 + dom/base/test/iframe_messageChannel_post.html | 23 ++ dom/base/test/test_messageChannel_post.html | 69 +++++ .../test_messageChannel_transferable.html | 60 ++++ dom/webidl/MessagePort.webidl | 2 + 7 files changed, 415 insertions(+), 4 deletions(-) create mode 100644 dom/base/test/iframe_messageChannel_post.html create mode 100644 dom/base/test/test_messageChannel_post.html create mode 100644 dom/base/test/test_messageChannel_transferable.html diff --git a/dom/base/MessagePort.cpp b/dom/base/MessagePort.cpp index a7b593cad81..0b68a87718e 100644 --- a/dom/base/MessagePort.cpp +++ b/dom/base/MessagePort.cpp @@ -6,11 +6,243 @@ #include "MessagePort.h" #include "mozilla/dom/MessageChannel.h" #include "mozilla/dom/MessagePortBinding.h" +#include "mozilla/dom/StructuredCloneTags.h" +#include "nsGlobalWindow.h" #include "nsContentUtils.h" +#include "nsEventDispatcher.h" +#include "nsPresContext.h" +#include "nsDOMEvent.h" + +#include "nsIDocument.h" +#include "nsIDOMFile.h" +#include "nsIDOMFileList.h" +#include "nsIDOMMessageEvent.h" +#include "nsIPresShell.h" namespace mozilla { namespace dom { +class PostMessageRunnable : public nsRunnable +{ + public: + NS_DECL_NSIRUNNABLE + + PostMessageRunnable(MessagePort* aPort) + : mPort(aPort) + , mMessage(nullptr) + , mMessageLen(0) + { + } + + ~PostMessageRunnable() + { + NS_ASSERTION(!mMessage, "Message should have been deserialized!"); + } + + void SetJSData(JSAutoStructuredCloneBuffer& aBuffer) + { + NS_ASSERTION(!mMessage && mMessageLen == 0, "Don't call twice!"); + aBuffer.steal(&mMessage, &mMessageLen); + } + + bool StoreISupports(nsISupports* aSupports) + { + mSupportsArray.AppendElement(aSupports); + return true; + } + + private: + nsRefPtr mPort; + uint64_t* mMessage; + size_t mMessageLen; + + nsTArray > mSupportsArray; +}; + +namespace { + +struct StructuredCloneInfo +{ + PostMessageRunnable* mEvent; + MessagePort* mPort; +}; + +static JSObject* +PostMessageReadStructuredClone(JSContext* cx, + JSStructuredCloneReader* reader, + uint32_t tag, + uint32_t data, + void* closure) +{ + NS_ASSERTION(closure, "Must have closure!"); + + if (tag == SCTAG_DOM_BLOB || tag == SCTAG_DOM_FILELIST) { + NS_ASSERTION(!data, "Data should be empty"); + + nsISupports* supports; + if (JS_ReadBytes(reader, &supports, sizeof(supports))) { + JS::Rooted global(cx, JS::CurrentGlobalOrNull(cx)); + if (global) { + JS::Rooted val(cx); + nsCOMPtr wrapper; + if (NS_SUCCEEDED(nsContentUtils::WrapNative(cx, global, supports, + val.address(), + getter_AddRefs(wrapper)))) { + return JSVAL_TO_OBJECT(val); + } + } + } + } + + if (tag == SCTAG_DOM_MESSAGEPORT) { + NS_ASSERTION(!data, "Data should be empty"); + + MessagePort* port; + if (JS_ReadBytes(reader, &port, sizeof(port))) { + JS::Rooted global(cx, JS::CurrentGlobalOrNull(cx)); + if (global) { + JS::Rooted obj(cx, port->WrapObject(cx, global)); + if (JS_WrapObject(cx, obj.address())) { + return obj; + } + } + } + } + + const JSStructuredCloneCallbacks* runtimeCallbacks = + js::GetContextStructuredCloneCallbacks(cx); + + if (runtimeCallbacks) { + return runtimeCallbacks->read(cx, reader, tag, data, nullptr); + } + + return nullptr; +} + +static bool +PostMessageWriteStructuredClone(JSContext* cx, + JSStructuredCloneWriter* writer, + JS::Handle obj, + void *closure) +{ + StructuredCloneInfo* scInfo = static_cast(closure); + NS_ASSERTION(scInfo, "Must have scInfo!"); + + nsCOMPtr wrappedNative; + nsContentUtils::XPConnect()-> + GetWrappedNativeOfJSObject(cx, obj, getter_AddRefs(wrappedNative)); + if (wrappedNative) { + uint32_t scTag = 0; + nsISupports* supports = wrappedNative->Native(); + + nsCOMPtr blob = do_QueryInterface(supports); + if (blob) { + scTag = SCTAG_DOM_BLOB; + } + + nsCOMPtr list = do_QueryInterface(supports); + if (list) { + scTag = SCTAG_DOM_FILELIST; + } + + if (scTag) { + return JS_WriteUint32Pair(writer, scTag, 0) && + JS_WriteBytes(writer, &supports, sizeof(supports)) && + scInfo->mEvent->StoreISupports(supports); + } + } + + MessagePort* port = nullptr; + nsresult rv = UNWRAP_OBJECT(MessagePort, cx, obj, port); + if (NS_SUCCEEDED(rv)) { + nsRefPtr newPort = port->Clone(scInfo->mPort->GetOwner()); + + return JS_WriteUint32Pair(writer, SCTAG_DOM_MESSAGEPORT, 0) && + JS_WriteBytes(writer, &newPort, sizeof(newPort)) && + scInfo->mEvent->StoreISupports(newPort); + } + + const JSStructuredCloneCallbacks* runtimeCallbacks = + js::GetContextStructuredCloneCallbacks(cx); + + if (runtimeCallbacks) { + return runtimeCallbacks->write(cx, writer, obj, nullptr); + } + + return false; +} + +JSStructuredCloneCallbacks kPostMessageCallbacks = { + PostMessageReadStructuredClone, + PostMessageWriteStructuredClone, + nullptr +}; + +} // anonymous namespace + +NS_IMETHODIMP +PostMessageRunnable::Run() +{ + // Ensure that the buffer is freed even if we fail to post the message + JSAutoStructuredCloneBuffer buffer; + buffer.adopt(mMessage, mMessageLen); + mMessage = nullptr; + mMessageLen = 0; + + // Get the JSContext for the target window + nsCOMPtr sgo = do_QueryInterface(mPort->GetOwner()); + NS_ENSURE_STATE(sgo); + nsCOMPtr scriptContext = sgo->GetContext(); + AutoPushJSContext cx(scriptContext ? scriptContext->GetNativeContext() + : nsContentUtils::GetSafeJSContext()); + + MOZ_ASSERT(cx); + + // Deserialize the structured clone data + JS::Rooted messageData(cx); + { + StructuredCloneInfo scInfo; + scInfo.mEvent = this; + scInfo.mPort = mPort; + + if (!buffer.read(cx, messageData.address(), &kPostMessageCallbacks, + &scInfo)) { + return NS_ERROR_DOM_DATA_CLONE_ERR; + } + } + + // Create the event + nsIDocument* doc = mPort->GetOwner()->GetExtantDoc(); + if (!doc) { + return NS_OK; + } + + ErrorResult error; + nsRefPtr event = + doc->CreateEvent(NS_LITERAL_STRING("MessageEvent"), error); + if (error.Failed()) { + return NS_OK; + } + + nsCOMPtr message = do_QueryInterface(event); + nsresult rv = message->InitMessageEvent(NS_LITERAL_STRING("message"), + false /* non-bubbling */, + true /* cancelable */, + messageData, + EmptyString(), + EmptyString(), + mPort->GetOwner()); + if (NS_FAILED(rv)) { + return NS_OK; + } + + message->SetTrusted(true); + + bool status; + mPort->DispatchEvent(event, &status); + return status ? NS_OK : NS_ERROR_FAILURE; +} + NS_IMPL_CYCLE_COLLECTION_INHERITED_1(MessagePort, nsDOMEventTargetHelper, mEntangledPort) @@ -41,13 +273,34 @@ MessagePort::WrapObject(JSContext* aCx, JS::Handle aScope) void MessagePort::PostMessage(JSContext* aCx, JS::Handle aMessage, - const Optional >& aTransfer) + const Optional >& aTransfer, + ErrorResult& aRv) { if (!mEntangledPort) { return; } - // TODO + nsRefPtr event = new PostMessageRunnable(mEntangledPort); + + // We *must* clone the data here, or the JS::Value could be modified + // by script + JSAutoStructuredCloneBuffer buffer; + StructuredCloneInfo scInfo; + scInfo.mEvent = event; + scInfo.mPort = this; + + JS::Handle transferable = aTransfer.WasPassed() + ? aTransfer.Value() + : JS::UndefinedHandleValue; + + if (!buffer.write(aCx, aMessage, transferable, &kPostMessageCallbacks, + &scInfo)) { + aRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR); + return; + } + + event->SetJSData(buffer); + NS_DispatchToCurrentThread(event); } void @@ -85,7 +338,7 @@ MessagePort::Entangle(MessagePort* aMessagePort) already_AddRefed MessagePort::Clone(nsPIDOMWindow* aWindow) { - nsRefPtr newPort = new MessagePort(aWindow); + nsRefPtr newPort = new MessagePort(aWindow->GetCurrentInnerWindow()); // TODO Move all the events in the port message queue of original port to the // port message queue of new port, if any, leaving the new port's port diff --git a/dom/base/MessagePort.h b/dom/base/MessagePort.h index 84987c748f6..9c993ff9a8c 100644 --- a/dom/base/MessagePort.h +++ b/dom/base/MessagePort.h @@ -31,7 +31,8 @@ public: void PostMessage(JSContext* aCx, JS::Handle aMessage, - const Optional >& aTransfer); + const Optional >& aTransfer, + ErrorResult& aRv); void Start(); diff --git a/dom/base/test/Makefile.in b/dom/base/test/Makefile.in index 1a8f9a00904..94218f6acb2 100644 --- a/dom/base/test/Makefile.in +++ b/dom/base/test/Makefile.in @@ -34,6 +34,9 @@ MOCHITEST_FILES = \ test_messageChannel.html \ test_messageChannel_cloning.html \ iframe_messageChannel_cloning.html \ + test_messageChannel_post.html \ + iframe_messageChannel_post.html \ + test_messageChannel_transferable.html \ $(NULL) MOCHITEST_CHROME_FILES = \ diff --git a/dom/base/test/iframe_messageChannel_post.html b/dom/base/test/iframe_messageChannel_post.html new file mode 100644 index 00000000000..3ad75dbdda8 --- /dev/null +++ b/dom/base/test/iframe_messageChannel_post.html @@ -0,0 +1,23 @@ + + + + + + + diff --git a/dom/base/test/test_messageChannel_post.html b/dom/base/test/test_messageChannel_post.html new file mode 100644 index 00000000000..83d7c62e276 --- /dev/null +++ b/dom/base/test/test_messageChannel_post.html @@ -0,0 +1,69 @@ + + + + + + Test for Bug 677638 - port cloning + + + + +Mozilla Bug 677638 +
    +
    +
    + + + diff --git a/dom/base/test/test_messageChannel_transferable.html b/dom/base/test/test_messageChannel_transferable.html new file mode 100644 index 00000000000..831c1632b8d --- /dev/null +++ b/dom/base/test/test_messageChannel_transferable.html @@ -0,0 +1,60 @@ + + + + + + Test for Bug 677638 - port cloning + + + + +Mozilla Bug 677638 +
    +
    +
    + + + diff --git a/dom/webidl/MessagePort.webidl b/dom/webidl/MessagePort.webidl index fa4f25579d8..64f33d7d4b0 100644 --- a/dom/webidl/MessagePort.webidl +++ b/dom/webidl/MessagePort.webidl @@ -9,7 +9,9 @@ interface MessagePort : EventTarget { // TODO void postMessage(any message, optional sequence transfer); + [Throws] void postMessage(any message, optional any transfer); + void start(); void close(); From 486c51bb1c02988fe62e035c418b22c77f275c5a Mon Sep 17 00:00:00 2001 From: Andrea Marchesini Date: Tue, 3 Sep 2013 14:38:56 +0200 Subject: [PATCH 38/64] Bug 677638 - Start() method --- dom/base/MessagePort.cpp | 82 ++++-- dom/base/MessagePort.h | 15 +- dom/base/test/Makefile.in | 1 + dom/base/test/iframe_messageChannel_post.html | 1 + dom/base/test/test_messageChannel_start.html | 234 ++++++++++++++++++ .../test_messageChannel_transferable.html | 6 +- 6 files changed, 321 insertions(+), 18 deletions(-) create mode 100644 dom/base/test/test_messageChannel_start.html diff --git a/dom/base/MessagePort.cpp b/dom/base/MessagePort.cpp index 0b68a87718e..442b78915a9 100644 --- a/dom/base/MessagePort.cpp +++ b/dom/base/MessagePort.cpp @@ -27,16 +27,19 @@ class PostMessageRunnable : public nsRunnable public: NS_DECL_NSIRUNNABLE - PostMessageRunnable(MessagePort* aPort) - : mPort(aPort) - , mMessage(nullptr) + PostMessageRunnable() + : mMessage(nullptr) , mMessageLen(0) { } ~PostMessageRunnable() { - NS_ASSERTION(!mMessage, "Message should have been deserialized!"); + // Ensure that the buffer is freed + if (mMessage) { + JSAutoStructuredCloneBuffer buffer; + buffer.adopt(mMessage, mMessageLen); + } } void SetJSData(JSAutoStructuredCloneBuffer& aBuffer) @@ -51,6 +54,12 @@ class PostMessageRunnable : public nsRunnable return true; } + void Dispatch(MessagePort* aPort) + { + mPort = aPort; + NS_DispatchToCurrentThread(this); + } + private: nsRefPtr mPort; uint64_t* mMessage; @@ -183,6 +192,8 @@ JSStructuredCloneCallbacks kPostMessageCallbacks = { NS_IMETHODIMP PostMessageRunnable::Run() { + MOZ_ASSERT(mPort); + // Ensure that the buffer is freed even if we fail to post the message JSAutoStructuredCloneBuffer buffer; buffer.adopt(mMessage, mMessageLen); @@ -243,8 +254,8 @@ PostMessageRunnable::Run() return status ? NS_OK : NS_ERROR_FAILURE; } -NS_IMPL_CYCLE_COLLECTION_INHERITED_1(MessagePort, nsDOMEventTargetHelper, - mEntangledPort) +NS_IMPL_CYCLE_COLLECTION_INHERITED_2(MessagePort, nsDOMEventTargetHelper, + mEntangledPort, mMessageQueue) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(MessagePort) NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper) @@ -254,6 +265,7 @@ NS_IMPL_RELEASE_INHERITED(MessagePort, nsDOMEventTargetHelper) MessagePort::MessagePort(nsPIDOMWindow* aWindow) : nsDOMEventTargetHelper(aWindow) + , mMessageQueueEnabled(false) { MOZ_COUNT_CTOR(MessagePort); SetIsDOMBinding(); @@ -276,11 +288,7 @@ MessagePort::PostMessage(JSContext* aCx, JS::Handle aMessage, const Optional >& aTransfer, ErrorResult& aRv) { - if (!mEntangledPort) { - return; - } - - nsRefPtr event = new PostMessageRunnable(mEntangledPort); + nsRefPtr event = new PostMessageRunnable(); // We *must* clone the data here, or the JS::Value could be modified // by script @@ -300,13 +308,34 @@ MessagePort::PostMessage(JSContext* aCx, JS::Handle aMessage, } event->SetJSData(buffer); - NS_DispatchToCurrentThread(event); + + if (!mEntangledPort) { + return; + } + + if (!mEntangledPort->mMessageQueueEnabled) { + mEntangledPort->mMessageQueue.AppendElement(event); + return; + } + + event->Dispatch(mEntangledPort); } void MessagePort::Start() { - // TODO + if (mMessageQueueEnabled) { + return; + } + + mMessageQueueEnabled = true; + + while (!mMessageQueue.IsEmpty()) { + nsRefPtr event = mMessageQueue.ElementAt(0); + mMessageQueue.RemoveElementAt(0); + + event->Dispatch(this); + } } void @@ -324,6 +353,28 @@ MessagePort::Close() port->Close(); } +EventHandlerNonNull* +MessagePort::GetOnmessage() +{ + if (NS_IsMainThread()) { + return GetEventHandler(nsGkAtoms::onmessage, EmptyString()); + } + return GetEventHandler(nullptr, NS_LITERAL_STRING("message")); +} + +void +MessagePort::SetOnmessage(EventHandlerNonNull* aCallback, ErrorResult& aRv) +{ + if (NS_IsMainThread()) { + SetEventHandler(nsGkAtoms::onmessage, EmptyString(), aCallback, aRv); + } else { + SetEventHandler(nullptr, NS_LITERAL_STRING("message"), aCallback, aRv); + } + + // When using onmessage, the call to start() is implied. + Start(); +} + void MessagePort::Entangle(MessagePort* aMessagePort) { @@ -340,9 +391,8 @@ MessagePort::Clone(nsPIDOMWindow* aWindow) { nsRefPtr newPort = new MessagePort(aWindow->GetCurrentInnerWindow()); - // TODO Move all the events in the port message queue of original port to the - // port message queue of new port, if any, leaving the new port's port - // message queue in its initial disabled state. + // Move all the events in the port message queue of original port. + newPort->mMessageQueue.SwapElements(mMessageQueue); if (mEntangledPort) { nsRefPtr port = mEntangledPort; diff --git a/dom/base/MessagePort.h b/dom/base/MessagePort.h index 9c993ff9a8c..f91122eb500 100644 --- a/dom/base/MessagePort.h +++ b/dom/base/MessagePort.h @@ -15,8 +15,12 @@ class nsPIDOMWindow; namespace mozilla { namespace dom { +class PostMessageRunnable; + class MessagePort MOZ_FINAL : public nsDOMEventTargetHelper { + friend class PostMessageRunnable; + public: NS_DECL_ISUPPORTS_INHERITED NS_REALLY_FORWARD_NSIDOMEVENTTARGET(nsDOMEventTargetHelper) @@ -40,7 +44,13 @@ public: void Close(); - IMPL_EVENT_HANDLER(message) + // The 'message' event handler has to call |Start()| method, so we + // cannot use IMPL_EVENT_HANDLER macro here. + EventHandlerNonNull* + GetOnmessage(); + + void + SetOnmessage(EventHandlerNonNull* aCallback, ErrorResult& aRv); // Non WebIDL methods @@ -58,6 +68,9 @@ public: private: nsRefPtr mEntangledPort; + + nsTArray > mMessageQueue; + bool mMessageQueueEnabled; }; } // namespace dom diff --git a/dom/base/test/Makefile.in b/dom/base/test/Makefile.in index 94218f6acb2..2031c3cb80c 100644 --- a/dom/base/test/Makefile.in +++ b/dom/base/test/Makefile.in @@ -37,6 +37,7 @@ MOCHITEST_FILES = \ test_messageChannel_post.html \ iframe_messageChannel_post.html \ test_messageChannel_transferable.html \ + test_messageChannel_start.html \ $(NULL) MOCHITEST_CHROME_FILES = \ diff --git a/dom/base/test/iframe_messageChannel_post.html b/dom/base/test/iframe_messageChannel_post.html index 3ad75dbdda8..e551dd61ca9 100644 --- a/dom/base/test/iframe_messageChannel_post.html +++ b/dom/base/test/iframe_messageChannel_post.html @@ -13,6 +13,7 @@ function receivePostMessage(evt) { port.postMessage(evt.data); } + port.start(); window.parent.postMessage({ status: "READY" }, '*'); } diff --git a/dom/base/test/test_messageChannel_start.html b/dom/base/test/test_messageChannel_start.html new file mode 100644 index 00000000000..ac5cf3122f6 --- /dev/null +++ b/dom/base/test/test_messageChannel_start.html @@ -0,0 +1,234 @@ + + + + + + Test for Bug 677638 - start/close + + + + +Mozilla Bug 677638 +
    +
    +
    + + + diff --git a/dom/base/test/test_messageChannel_transferable.html b/dom/base/test/test_messageChannel_transferable.html index 831c1632b8d..0a6c4365501 100644 --- a/dom/base/test/test_messageChannel_transferable.html +++ b/dom/base/test/test_messageChannel_transferable.html @@ -40,11 +40,15 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=677638 ifr.contentWindow.postMessage({ port: a.port2 }, '*'); } - a.port1.onmessage = function(evt) { + a.port1.addEventListener('message', receivePortMessage, false); + function receivePortMessage(evt) { is(evt.data.ab.byteLength, size, "The size is: " + size + " == " + ab.byteLength); SimpleTest.finish(); } + // Start() is not implicity invoked when addEventListener is used. + a.port1.start(); + var size = 1024 * 1024 * 32; var ab = new ArrayBuffer(size); is(ab.byteLength, size, "The size is: " + size + " == " + ab.byteLength); From 6caa11f5052bcbdf3c58fac2f6d17040d6d91b5b Mon Sep 17 00:00:00 2001 From: Andrea Marchesini Date: Tue, 3 Sep 2013 14:38:58 +0200 Subject: [PATCH 39/64] Bug 677638 - cycle collection and timeout, r=smaug --- dom/base/MessagePort.cpp | 93 ++++++++++++++++--- dom/base/MessagePort.h | 7 ++ dom/base/test/Makefile.in | 2 + .../test/iframe_messageChannel_pingpong.html | 33 +++++++ .../test/test_messageChannel_pingpong.html | 74 +++++++++++++++ 5 files changed, 196 insertions(+), 13 deletions(-) create mode 100644 dom/base/test/iframe_messageChannel_pingpong.html create mode 100644 dom/base/test/test_messageChannel_pingpong.html diff --git a/dom/base/MessagePort.cpp b/dom/base/MessagePort.cpp index 442b78915a9..95360737082 100644 --- a/dom/base/MessagePort.cpp +++ b/dom/base/MessagePort.cpp @@ -22,8 +22,35 @@ namespace mozilla { namespace dom { +class DispatchEventRunnable : public nsRunnable +{ + friend class MessagePort; + + public: + DispatchEventRunnable(MessagePort* aPort) + : mPort(aPort) + { + } + + NS_IMETHOD + Run() + { + nsRefPtr mKungFuDeathGrip(this); + + mPort->mDispatchRunnable = nullptr; + mPort->Dispatch(); + + return NS_OK; + } + + private: + nsRefPtr mPort; +}; + class PostMessageRunnable : public nsRunnable { + friend class MessagePort; + public: NS_DECL_NSIRUNNABLE @@ -254,8 +281,42 @@ PostMessageRunnable::Run() return status ? NS_OK : NS_ERROR_FAILURE; } -NS_IMPL_CYCLE_COLLECTION_INHERITED_2(MessagePort, nsDOMEventTargetHelper, - mEntangledPort, mMessageQueue) +NS_IMPL_CYCLE_COLLECTION_CLASS(MessagePort) + +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(MessagePort, + nsDOMEventTargetHelper) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mEntangledPort) + + // Custom unlink loop because this array contains nsRunnable objects + // which are not cycle colleactable. + while (!tmp->mMessageQueue.IsEmpty()) { + NS_IMPL_CYCLE_COLLECTION_UNLINK(mMessageQueue[0]->mPort); + NS_IMPL_CYCLE_COLLECTION_UNLINK(mMessageQueue[0]->mSupportsArray); + tmp->mMessageQueue.RemoveElementAt(0); + } + + if (tmp->mDispatchRunnable) { + NS_IMPL_CYCLE_COLLECTION_UNLINK(mDispatchRunnable->mPort); + } + +NS_IMPL_CYCLE_COLLECTION_UNLINK_END + +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(MessagePort, + nsDOMEventTargetHelper) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEntangledPort) + + // Custom unlink loop because this array contains nsRunnable objects + // which are not cycle colleactable. + for (uint32_t i = 0, len = tmp->mMessageQueue.Length(); i < len; ++i) { + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMessageQueue[i]->mPort); + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMessageQueue[i]->mSupportsArray); + } + + if (tmp->mDispatchRunnable) { + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDispatchRunnable->mPort); + } + +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(MessagePort) NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper) @@ -313,12 +374,8 @@ MessagePort::PostMessage(JSContext* aCx, JS::Handle aMessage, return; } - if (!mEntangledPort->mMessageQueueEnabled) { - mEntangledPort->mMessageQueue.AppendElement(event); - return; - } - - event->Dispatch(mEntangledPort); + mEntangledPort->mMessageQueue.AppendElement(event); + mEntangledPort->Dispatch(); } void @@ -329,13 +386,23 @@ MessagePort::Start() } mMessageQueueEnabled = true; + Dispatch(); +} - while (!mMessageQueue.IsEmpty()) { - nsRefPtr event = mMessageQueue.ElementAt(0); - mMessageQueue.RemoveElementAt(0); - - event->Dispatch(this); +void +MessagePort::Dispatch() +{ + if (!mMessageQueueEnabled || mMessageQueue.IsEmpty() || mDispatchRunnable) { + return; } + + nsRefPtr event = mMessageQueue.ElementAt(0); + mMessageQueue.RemoveElementAt(0); + + event->Dispatch(this); + + mDispatchRunnable = new DispatchEventRunnable(this); + NS_DispatchToCurrentThread(mDispatchRunnable); } void diff --git a/dom/base/MessagePort.h b/dom/base/MessagePort.h index f91122eb500..09afd1e3038 100644 --- a/dom/base/MessagePort.h +++ b/dom/base/MessagePort.h @@ -15,10 +15,12 @@ class nsPIDOMWindow; namespace mozilla { namespace dom { +class DispatchEventRunnable; class PostMessageRunnable; class MessagePort MOZ_FINAL : public nsDOMEventTargetHelper { + friend class DispatchEventRunnable; friend class PostMessageRunnable; public: @@ -67,6 +69,11 @@ public: Clone(nsPIDOMWindow* aWindow); private: + // Dispatch events from the Message Queue using a nsRunnable. + void Dispatch(); + + nsRefPtr mDispatchRunnable; + nsRefPtr mEntangledPort; nsTArray > mMessageQueue; diff --git a/dom/base/test/Makefile.in b/dom/base/test/Makefile.in index 2031c3cb80c..7b9f2357765 100644 --- a/dom/base/test/Makefile.in +++ b/dom/base/test/Makefile.in @@ -38,6 +38,8 @@ MOCHITEST_FILES = \ iframe_messageChannel_post.html \ test_messageChannel_transferable.html \ test_messageChannel_start.html \ + test_messageChannel_pingpong.html \ + iframe_messageChannel_pingpong.html \ $(NULL) MOCHITEST_CHROME_FILES = \ diff --git a/dom/base/test/iframe_messageChannel_pingpong.html b/dom/base/test/iframe_messageChannel_pingpong.html new file mode 100644 index 00000000000..2cd0b79da58 --- /dev/null +++ b/dom/base/test/iframe_messageChannel_pingpong.html @@ -0,0 +1,33 @@ + + + + + + + diff --git a/dom/base/test/test_messageChannel_pingpong.html b/dom/base/test/test_messageChannel_pingpong.html new file mode 100644 index 00000000000..53bdcbbab12 --- /dev/null +++ b/dom/base/test/test_messageChannel_pingpong.html @@ -0,0 +1,74 @@ + + + + + + Test for Bug 677638 - port cloning + + + + +Mozilla Bug 677638 +
    +
    +
    + + + From 3c7355153b01c3d15613242d3b531bed62d7fc6c Mon Sep 17 00:00:00 2001 From: Andrea Marchesini Date: Tue, 3 Sep 2013 14:39:01 +0200 Subject: [PATCH 40/64] Bug 677638 - unshipped message port queue, r=smaug --- dom/base/test/Makefile.in | 1 + .../test/test_messageChannel_unshipped.html | 123 ++++++++++++++++++ 2 files changed, 124 insertions(+) create mode 100644 dom/base/test/test_messageChannel_unshipped.html diff --git a/dom/base/test/Makefile.in b/dom/base/test/Makefile.in index 7b9f2357765..f0336795b45 100644 --- a/dom/base/test/Makefile.in +++ b/dom/base/test/Makefile.in @@ -40,6 +40,7 @@ MOCHITEST_FILES = \ test_messageChannel_start.html \ test_messageChannel_pingpong.html \ iframe_messageChannel_pingpong.html \ + test_messageChannel_unshipped.html \ $(NULL) MOCHITEST_CHROME_FILES = \ diff --git a/dom/base/test/test_messageChannel_unshipped.html b/dom/base/test/test_messageChannel_unshipped.html new file mode 100644 index 00000000000..6661b7d0a05 --- /dev/null +++ b/dom/base/test/test_messageChannel_unshipped.html @@ -0,0 +1,123 @@ + + + + + + Test for Bug 677638 - unshipped message port queue + + + + +Mozilla Bug 677638 +
    +
    +
    + + + From a3647d28f2e28f24381c4ea768e6342c3140190b Mon Sep 17 00:00:00 2001 From: Andrea Marchesini Date: Tue, 3 Sep 2013 14:39:03 +0200 Subject: [PATCH 41/64] Bug 677638 - MessageChannel and MessagePort disabled by pref, r=smaug --- dom/base/MessageChannel.cpp | 19 +++++ dom/base/MessageChannel.h | 2 + dom/base/nsGlobalWindow.cpp | 19 +++-- dom/base/test/Makefile.in | 1 + dom/base/test/test_messageChannel.html | 32 ++++--- .../test/test_messageChannel_cloning.html | 2 +- .../test/test_messageChannel_pingpong.html | 83 +++++++++--------- dom/base/test/test_messageChannel_post.html | 85 ++++++++++--------- dom/base/test/test_messageChannel_pref.html | 42 +++++++++ dom/base/test/test_messageChannel_start.html | 2 +- .../test_messageChannel_transferable.html | 79 ++++++++--------- .../test/test_messageChannel_unshipped.html | 2 +- dom/webidl/MessageChannel.webidl | 2 +- dom/webidl/MessagePort.webidl | 1 + 14 files changed, 227 insertions(+), 144 deletions(-) create mode 100644 dom/base/test/test_messageChannel_pref.html diff --git a/dom/base/MessageChannel.cpp b/dom/base/MessageChannel.cpp index e759b522b9d..a61d2a7e7d1 100644 --- a/dom/base/MessageChannel.cpp +++ b/dom/base/MessageChannel.cpp @@ -4,6 +4,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "MessageChannel.h" +#include "mozilla/Preferences.h" #include "mozilla/dom/MessageChannelBinding.h" #include "mozilla/dom/MessagePort.h" #include "nsContentUtils.h" @@ -21,6 +22,24 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MessageChannel) NS_INTERFACE_MAP_ENTRY(nsISupports) NS_INTERFACE_MAP_END +namespace { + bool gPrefInitialized = false; + bool gPrefEnabled = false; + +} + + +/* static */ bool +MessageChannel::PrefEnabled() +{ + if (!gPrefInitialized) { + Preferences::AddBoolVarCache(&gPrefEnabled, "dom.messageChannel.enabled"); + gPrefInitialized = true; + } + + return gPrefEnabled; +} + MessageChannel::MessageChannel(nsPIDOMWindow* aWindow) : mWindow(aWindow) { diff --git a/dom/base/MessageChannel.h b/dom/base/MessageChannel.h index 5b945a52a22..1f5a22e9ecb 100644 --- a/dom/base/MessageChannel.h +++ b/dom/base/MessageChannel.h @@ -28,6 +28,8 @@ public: NS_DECL_CYCLE_COLLECTING_ISUPPORTS NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(MessageChannel) + static bool PrefEnabled(); + public: MessageChannel(nsPIDOMWindow* aWindow); diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index 31480eba8f7..3708617d838 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -189,6 +189,7 @@ #include "prenv.h" #include "prprf.h" +#include "mozilla/dom/MessageChannel.h" #include "mozilla/dom/MessagePort.h" #include "mozilla/dom/MessagePortBinding.h" #include "mozilla/dom/indexedDB/IDBFactory.h" @@ -6782,7 +6783,7 @@ PostMessageReadStructuredClone(JSContext* cx, } } - if (tag == SCTAG_DOM_MESSAGEPORT) { + if (MessageChannel::PrefEnabled() && tag == SCTAG_DOM_MESSAGEPORT) { NS_ASSERTION(!data, "Data should be empty"); MessagePort* port; @@ -6837,14 +6838,16 @@ PostMessageWriteStructuredClone(JSContext* cx, scInfo->event->StoreISupports(supports); } - MessagePort* port = nullptr; - nsresult rv = UNWRAP_OBJECT(MessagePort, cx, obj, port); - if (NS_SUCCEEDED(rv) && scInfo->subsumes) { - nsRefPtr newPort = port->Clone(scInfo->window); + if (MessageChannel::PrefEnabled()) { + MessagePort* port = nullptr; + nsresult rv = UNWRAP_OBJECT(MessagePort, cx, obj, port); + if (NS_SUCCEEDED(rv) && scInfo->subsumes) { + nsRefPtr newPort = port->Clone(scInfo->window); - return JS_WriteUint32Pair(writer, SCTAG_DOM_MESSAGEPORT, 0) && - JS_WriteBytes(writer, &newPort, sizeof(newPort)) && - scInfo->event->StoreISupports(newPort); + return JS_WriteUint32Pair(writer, SCTAG_DOM_MESSAGEPORT, 0) && + JS_WriteBytes(writer, &newPort, sizeof(newPort)) && + scInfo->event->StoreISupports(newPort); + } } const JSStructuredCloneCallbacks* runtimeCallbacks = diff --git a/dom/base/test/Makefile.in b/dom/base/test/Makefile.in index f0336795b45..091868595c3 100644 --- a/dom/base/test/Makefile.in +++ b/dom/base/test/Makefile.in @@ -41,6 +41,7 @@ MOCHITEST_FILES = \ test_messageChannel_pingpong.html \ iframe_messageChannel_pingpong.html \ test_messageChannel_unshipped.html \ + test_messageChannel_pref.html \ $(NULL) MOCHITEST_CHROME_FILES = \ diff --git a/dom/base/test/test_messageChannel.html b/dom/base/test/test_messageChannel.html index 3e761e299bf..dbb85766043 100644 --- a/dom/base/test/test_messageChannel.html +++ b/dom/base/test/test_messageChannel.html @@ -21,23 +21,29 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=677638 diff --git a/dom/base/test/test_messageChannel_cloning.html b/dom/base/test/test_messageChannel_cloning.html index 30327d5f162..8f895830314 100644 --- a/dom/base/test/test_messageChannel_cloning.html +++ b/dom/base/test/test_messageChannel_cloning.html @@ -64,7 +64,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=677638 } SimpleTest.waitForExplicitFinish(); - runTest(); + SpecialPowers.pushPrefEnv({"set": [["dom.messageChannel.enabled", true]]}, runTest); diff --git a/dom/base/test/test_messageChannel_pingpong.html b/dom/base/test/test_messageChannel_pingpong.html index 53bdcbbab12..372e87b07e5 100644 --- a/dom/base/test/test_messageChannel_pingpong.html +++ b/dom/base/test/test_messageChannel_pingpong.html @@ -16,59 +16,62 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=677638 diff --git a/dom/base/test/test_messageChannel_post.html b/dom/base/test/test_messageChannel_post.html index 83d7c62e276..b9517c22ac8 100644 --- a/dom/base/test/test_messageChannel_post.html +++ b/dom/base/test/test_messageChannel_post.html @@ -16,54 +16,57 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=677638 diff --git a/dom/base/test/test_messageChannel_pref.html b/dom/base/test/test_messageChannel_pref.html new file mode 100644 index 00000000000..5fe30aa5200 --- /dev/null +++ b/dom/base/test/test_messageChannel_pref.html @@ -0,0 +1,42 @@ + + + + + + Test for Bug 677638 - pref + + + + +Mozilla Bug 677638 +
    +
    +
    + + + diff --git a/dom/base/test/test_messageChannel_start.html b/dom/base/test/test_messageChannel_start.html index ac5cf3122f6..b739a732a20 100644 --- a/dom/base/test/test_messageChannel_start.html +++ b/dom/base/test/test_messageChannel_start.html @@ -228,7 +228,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=677638 ]; SimpleTest.waitForExplicitFinish(); - runTests(); + SpecialPowers.pushPrefEnv({"set": [["dom.messageChannel.enabled", true]]}, runTests); diff --git a/dom/base/test/test_messageChannel_transferable.html b/dom/base/test/test_messageChannel_transferable.html index 0a6c4365501..2750d532438 100644 --- a/dom/base/test/test_messageChannel_transferable.html +++ b/dom/base/test/test_messageChannel_transferable.html @@ -16,49 +16,52 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=677638 diff --git a/dom/base/test/test_messageChannel_unshipped.html b/dom/base/test/test_messageChannel_unshipped.html index 6661b7d0a05..60c8070fa4e 100644 --- a/dom/base/test/test_messageChannel_unshipped.html +++ b/dom/base/test/test_messageChannel_unshipped.html @@ -117,7 +117,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=677638 } SimpleTest.waitForExplicitFinish(); - runTests(); + SpecialPowers.pushPrefEnv({"set": [["dom.messageChannel.enabled", true]]}, runTests); diff --git a/dom/webidl/MessageChannel.webidl b/dom/webidl/MessageChannel.webidl index a8d46b4dddc..c5ef60d07e0 100644 --- a/dom/webidl/MessageChannel.webidl +++ b/dom/webidl/MessageChannel.webidl @@ -7,7 +7,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/#channel-messaging */ -[Constructor] +[Constructor, Pref="dom.messageChannel.enabled"] interface MessageChannel { readonly attribute MessagePort port1; readonly attribute MessagePort port2; diff --git a/dom/webidl/MessagePort.webidl b/dom/webidl/MessagePort.webidl index 64f33d7d4b0..797de75bea5 100644 --- a/dom/webidl/MessagePort.webidl +++ b/dom/webidl/MessagePort.webidl @@ -7,6 +7,7 @@ * http://www.whatwg.org/specs/web-apps/current-work/#channel-messaging */ +[Pref="dom.messageChannel.enabled"] interface MessagePort : EventTarget { // TODO void postMessage(any message, optional sequence transfer); [Throws] From cd3248ea146bf4e9c3a0eb23326a313434fa77fe Mon Sep 17 00:00:00 2001 From: Po-Chun Chang Date: Tue, 3 Sep 2013 08:55:52 -0400 Subject: [PATCH 42/64] Bug 908527 - Avoid wasted work in PSM_SSL_BlacklistDigiNotar(). r=cviecoo --- security/manager/ssl/src/SSLServerCertVerification.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/security/manager/ssl/src/SSLServerCertVerification.cpp b/security/manager/ssl/src/SSLServerCertVerification.cpp index 3226aa52b62..af129538ede 100644 --- a/security/manager/ssl/src/SSLServerCertVerification.cpp +++ b/security/manager/ssl/src/SSLServerCertVerification.cpp @@ -745,6 +745,7 @@ PSM_SSL_BlacklistDigiNotar(CERTCertificate * serverCert, if (strstr(node->cert->issuerName, "CN=DigiNotar")) { isDigiNotarIssuedCert = true; + break; } } From fcf5512d6dd3d92d7c2af6f1d9217eb8504cd83d Mon Sep 17 00:00:00 2001 From: Raymond Lee Date: Tue, 3 Sep 2013 11:56:25 +0800 Subject: [PATCH 43/64] Bug 627487 - Bookmark JSON backup should contain new-style GUIDs. r=mano --- .../places/nsINavHistoryService.idl | 19 ++- toolkit/components/places/nsNavBookmarks.cpp | 24 ++-- toolkit/components/places/nsNavBookmarks.h | 1 - toolkit/components/places/nsNavHistory.cpp | 27 ++-- toolkit/components/places/nsNavHistory.h | 1 + .../components/places/nsNavHistoryResult.cpp | 13 ++ .../components/places/nsNavHistoryResult.h | 14 +- .../tests/unit/test_pageGuid_bookmarkGuid.js | 127 ++++++++++++++++++ .../components/places/tests/unit/xpcshell.ini | 1 + 9 files changed, 202 insertions(+), 25 deletions(-) create mode 100644 toolkit/components/places/tests/unit/test_pageGuid_bookmarkGuid.js diff --git a/toolkit/components/places/nsINavHistoryService.idl b/toolkit/components/places/nsINavHistoryService.idl index 26537c88d3f..1a584b8c45a 100644 --- a/toolkit/components/places/nsINavHistoryService.idl +++ b/toolkit/components/places/nsINavHistoryService.idl @@ -23,7 +23,7 @@ interface nsINavHistoryQueryOptions; interface nsINavHistoryResult; interface nsINavHistoryBatchCallback; -[scriptable, uuid(081452e5-be5c-4038-a5ea-f1f34cb6fd81)] +[scriptable, uuid(91d104bb-17ef-404b-9f9a-d9ed8de6824c)] interface nsINavHistoryResultNode : nsISupports { /** @@ -154,6 +154,19 @@ interface nsINavHistoryResultNode : nsISupports * for the uri represented by this node. Otherwise this is an empty string. */ readonly attribute AString tags; + + /** + * The unique ID associated with the page. It my return an empty string + * if the result node is a non-URI node. + */ + readonly attribute ACString pageGuid; + + /** + * The unique ID associated with the bookmark. It returns an empty string + * if the result node is not associated with a bookmark, a folder or a + * separator. + */ + readonly attribute ACString bookmarkGuid; }; @@ -162,7 +175,7 @@ interface nsINavHistoryResultNode : nsISupports * Bookmark folders and places queries will be QueryResultNodes which extends * these items. */ -[scriptable, uuid(62534d3c-1b3f-401e-b3ba-b911f57f8a29)] +[scriptable, uuid(5bac9734-c0ff-44eb-8d19-da88462ff6da)] interface nsINavHistoryContainerResultNode : nsINavHistoryResultNode { @@ -262,7 +275,7 @@ interface nsINavHistoryContainerResultNode : nsINavHistoryResultNode * generated this node, this item will report it has no children and never try * to populate itself. */ -[scriptable, uuid(ea17745a-1852-4155-a98f-d1dd1763b3df)] +[scriptable, uuid(a4144c3e-8125-46d5-a719-831bec8095f4)] interface nsINavHistoryQueryResultNode : nsINavHistoryContainerResultNode { /** diff --git a/toolkit/components/places/nsNavBookmarks.cpp b/toolkit/components/places/nsNavBookmarks.cpp index 2b584bbd4e6..0107f5c0423 100644 --- a/toolkit/components/places/nsNavBookmarks.cpp +++ b/toolkit/components/places/nsNavBookmarks.cpp @@ -50,10 +50,10 @@ using namespace mozilla; // These columns sit to the right of the kGetInfoIndex_* columns. -const int32_t nsNavBookmarks::kGetChildrenIndex_Position = 14; -const int32_t nsNavBookmarks::kGetChildrenIndex_Type = 15; -const int32_t nsNavBookmarks::kGetChildrenIndex_PlaceID = 16; -const int32_t nsNavBookmarks::kGetChildrenIndex_Guid = 17; +const int32_t nsNavBookmarks::kGetChildrenIndex_Guid = 15; +const int32_t nsNavBookmarks::kGetChildrenIndex_Position = 16; +const int32_t nsNavBookmarks::kGetChildrenIndex_Type = 17; +const int32_t nsNavBookmarks::kGetChildrenIndex_PlaceID = 18; using namespace mozilla::places; @@ -1062,8 +1062,8 @@ nsNavBookmarks::GetDescendantChildren(int64_t aFolderId, nsCOMPtr stmt = mDB->GetStatement( "SELECT h.id, h.url, IFNULL(b.title, h.title), h.rev_host, h.visit_count, " "h.last_visit_date, f.url, b.id, b.dateAdded, b.lastModified, " - "b.parent, null, h.frecency, h.hidden, b.position, b.type, b.fk, " - "b.guid " + "b.parent, null, h.frecency, h.hidden, h.guid, b.guid, " + "b.position, b.type, b.fk " "FROM moz_bookmarks b " "LEFT JOIN moz_places h ON b.fk = h.id " "LEFT JOIN moz_favicons f ON h.favicon_id = f.id " @@ -1743,6 +1743,7 @@ nsNavBookmarks::ResultNodeForContainer(int64_t aItemId, (*aNode)->mDateAdded = bookmark.dateAdded; (*aNode)->mLastModified = bookmark.lastModified; + (*aNode)->mBookmarkGuid = bookmark.guid; NS_ADDREF(*aNode); return NS_OK; @@ -1766,8 +1767,8 @@ nsNavBookmarks::QueryFolderChildren( nsCOMPtr stmt = mDB->GetStatement( "SELECT h.id, h.url, IFNULL(b.title, h.title), h.rev_host, h.visit_count, " "h.last_visit_date, f.url, b.id, b.dateAdded, b.lastModified, " - "b.parent, null, h.frecency, h.hidden, b.position, b.type, b.fk, " - "b.guid " + "b.parent, null, h.frecency, h.hidden, h.guid, b.guid, " + "b.position, b.type, b.fk " "FROM moz_bookmarks b " "LEFT JOIN moz_places h ON b.fk = h.id " "LEFT JOIN moz_favicons f ON h.favicon_id = f.id " @@ -1877,6 +1878,9 @@ nsNavBookmarks::ProcessFolderNodeRow( // moz_bookmarks.position. node->mBookmarkIndex = aCurrentIndex; + rv = aRow->GetUTF8String(kGetChildrenIndex_Guid, node->mBookmarkGuid); + NS_ENSURE_SUCCESS(rv, rv); + NS_ENSURE_TRUE(aChildren->AppendObject(node), NS_ERROR_OUT_OF_MEMORY); return NS_OK; @@ -1900,8 +1904,8 @@ nsNavBookmarks::QueryFolderChildrenAsync( nsCOMPtr stmt = mDB->GetAsyncStatement( "SELECT h.id, h.url, IFNULL(b.title, h.title), h.rev_host, h.visit_count, " "h.last_visit_date, f.url, b.id, b.dateAdded, b.lastModified, " - "b.parent, null, h.frecency, h.hidden, b.position, b.type, b.fk, " - "b.guid " + "b.parent, null, h.frecency, h.hidden, h.guid, b.guid, " + "b.position, b.type, b.fk " "FROM moz_bookmarks b " "LEFT JOIN moz_places h ON b.fk = h.id " "LEFT JOIN moz_favicons f ON h.favicon_id = f.id " diff --git a/toolkit/components/places/nsNavBookmarks.h b/toolkit/components/places/nsNavBookmarks.h index 4cf84e32837..b0e4e2319fb 100644 --- a/toolkit/components/places/nsNavBookmarks.h +++ b/toolkit/components/places/nsNavBookmarks.h @@ -368,7 +368,6 @@ private: static const int32_t kGetChildrenIndex_Position; static const int32_t kGetChildrenIndex_Type; static const int32_t kGetChildrenIndex_PlaceID; - static const int32_t kGetChildrenIndex_FolderTitle; static const int32_t kGetChildrenIndex_Guid; class RemoveFolderTransaction MOZ_FINAL : public nsITransaction { diff --git a/toolkit/components/places/nsNavHistory.cpp b/toolkit/components/places/nsNavHistory.cpp index 21c4f424176..c6ce158b865 100644 --- a/toolkit/components/places/nsNavHistory.cpp +++ b/toolkit/components/places/nsNavHistory.cpp @@ -250,6 +250,7 @@ const int32_t nsNavHistory::kGetInfoIndex_ItemParentId = 10; const int32_t nsNavHistory::kGetInfoIndex_ItemTags = 11; const int32_t nsNavHistory::kGetInfoIndex_Frecency = 12; const int32_t nsNavHistory::kGetInfoIndex_Hidden = 13; +const int32_t nsNavHistory::kGetInfoIndex_Guid = 14; PLACES_FACTORY_SINGLETON_IMPLEMENTATION(nsNavHistory, gHistoryService) @@ -1395,7 +1396,7 @@ PlacesSQLQueryBuilder::SelectAsURI() mQueryString = NS_LITERAL_CSTRING( "SELECT h.id, h.url, h.title AS page_title, h.rev_host, h.visit_count, " "h.last_visit_date, f.url, null, null, null, null, ") + - tagsSqlFragment + NS_LITERAL_CSTRING(", h.frecency, h.hidden " + tagsSqlFragment + NS_LITERAL_CSTRING(", h.frecency, h.hidden, h.guid " "FROM moz_places h " "LEFT JOIN moz_favicons f ON h.favicon_id = f.id " // WHERE 1 is a no-op since additonal conditions will start with AND. @@ -1421,7 +1422,7 @@ PlacesSQLQueryBuilder::SelectAsURI() "SELECT b2.fk, h.url, COALESCE(b2.title, h.title) AS page_title, " "h.rev_host, h.visit_count, h.last_visit_date, f.url, b2.id, " "b2.dateAdded, b2.lastModified, b2.parent, ") + - tagsSqlFragment + NS_LITERAL_CSTRING(", h.frecency, h.hidden " + tagsSqlFragment + NS_LITERAL_CSTRING(", h.frecency, h.hidden, h.guid " "FROM moz_bookmarks b2 " "JOIN (SELECT b.fk " "FROM moz_bookmarks b " @@ -1445,7 +1446,7 @@ PlacesSQLQueryBuilder::SelectAsURI() "SELECT b.fk, h.url, COALESCE(b.title, h.title) AS page_title, " "h.rev_host, h.visit_count, h.last_visit_date, f.url, b.id, " "b.dateAdded, b.lastModified, b.parent, ") + - tagsSqlFragment + NS_LITERAL_CSTRING(", h.frecency, h.hidden " + tagsSqlFragment + NS_LITERAL_CSTRING(", h.frecency, h.hidden, h.guid " "FROM moz_bookmarks b " "JOIN moz_places h ON b.fk = h.id " "LEFT OUTER JOIN moz_favicons f ON h.favicon_id = f.id " @@ -1477,7 +1478,7 @@ PlacesSQLQueryBuilder::SelectAsVisit() mQueryString = NS_LITERAL_CSTRING( "SELECT h.id, h.url, h.title AS page_title, h.rev_host, h.visit_count, " "v.visit_date, f.url, null, null, null, null, ") + - tagsSqlFragment + NS_LITERAL_CSTRING(", h.frecency, h.hidden " + tagsSqlFragment + NS_LITERAL_CSTRING(", h.frecency, h.hidden, h.guid " "FROM moz_places h " "JOIN moz_historyvisits v ON h.id = v.place_id " "LEFT JOIN moz_favicons f ON h.favicon_id = f.id " @@ -2002,7 +2003,7 @@ nsNavHistory::ConstructQueryString( queryString = NS_LITERAL_CSTRING( "SELECT h.id, h.url, h.title AS page_title, h.rev_host, h.visit_count, h.last_visit_date, " "f.url, null, null, null, null, ") + - tagsSqlFragment + NS_LITERAL_CSTRING(", h.frecency, h.hidden " + tagsSqlFragment + NS_LITERAL_CSTRING(", h.frecency, h.hidden, h.guid " "FROM moz_places h " "LEFT OUTER JOIN moz_favicons f ON h.favicon_id = f.id " "WHERE h.hidden = 0 " @@ -3800,7 +3801,7 @@ nsNavHistory::RowToResult(mozIStorageValueArray* aRow, if (IsQueryURI(url)) { // special case "place:" URIs: turn them into containers - + // We should never expose the history title for query nodes if the // bookmark-item's title is set to null (the history title may be the // query string without the place: prefix). Thus we call getItemTitle @@ -3855,6 +3856,9 @@ nsNavHistory::RowToResult(mozIStorageValueArray* aRow, resultNode->mTags.Assign(tags); } + rv = aRow->GetUTF8String(kGetInfoIndex_Guid, resultNode->mPageGuid); + NS_ENSURE_SUCCESS(rv, rv); + resultNode.forget(aResult); return NS_OK; } @@ -3868,6 +3872,9 @@ nsNavHistory::RowToResult(mozIStorageValueArray* aRow, if (!tags.IsVoid()) resultNode->mTags.Assign(tags); + rv = aRow->GetUTF8String(kGetInfoIndex_Guid, resultNode->mPageGuid); + NS_ENSURE_SUCCESS(rv, rv); + resultNode.forget(aResult); return NS_OK; } @@ -3966,7 +3973,7 @@ nsNavHistory::VisitIdToResultNode(int64_t visitId, statement = mDB->GetStatement(NS_LITERAL_CSTRING( "SELECT h.id, h.url, h.title, h.rev_host, h.visit_count, " "v.visit_date, f.url, null, null, null, null, " - ) + tagsFragment + NS_LITERAL_CSTRING(", h.frecency, h.hidden " + ) + tagsFragment + NS_LITERAL_CSTRING(", h.frecency, h.hidden, h.guid " "FROM moz_places h " "JOIN moz_historyvisits v ON h.id = v.place_id " "LEFT JOIN moz_favicons f ON h.favicon_id = f.id " @@ -3980,7 +3987,7 @@ nsNavHistory::VisitIdToResultNode(int64_t visitId, statement = mDB->GetStatement(NS_LITERAL_CSTRING( "SELECT h.id, h.url, h.title, h.rev_host, h.visit_count, " "h.last_visit_date, f.url, null, null, null, null, " - ) + tagsFragment + NS_LITERAL_CSTRING(", h.frecency, h.hidden " + ) + tagsFragment + NS_LITERAL_CSTRING(", h.frecency, h.hidden, h.guid " "FROM moz_places h " "JOIN moz_historyvisits v ON h.id = v.place_id " "LEFT JOIN moz_favicons f ON h.favicon_id = f.id " @@ -4026,7 +4033,7 @@ nsNavHistory::BookmarkIdToResultNode(int64_t aBookmarkId, nsNavHistoryQueryOptio "SELECT b.fk, h.url, COALESCE(b.title, h.title), " "h.rev_host, h.visit_count, h.last_visit_date, f.url, b.id, " "b.dateAdded, b.lastModified, b.parent, " - ) + tagsFragment + NS_LITERAL_CSTRING(", h.frecency, h.hidden " + ) + tagsFragment + NS_LITERAL_CSTRING(", h.frecency, h.hidden, h.guid " "FROM moz_bookmarks b " "JOIN moz_places h ON b.fk = h.id " "LEFT JOIN moz_favicons f ON h.favicon_id = f.id " @@ -4065,7 +4072,7 @@ nsNavHistory::URIToResultNode(nsIURI* aURI, nsCOMPtr stmt = mDB->GetStatement(NS_LITERAL_CSTRING( "SELECT h.id, :page_url, h.title, h.rev_host, h.visit_count, " "h.last_visit_date, f.url, null, null, null, null, " - ) + tagsFragment + NS_LITERAL_CSTRING(", h.frecency, h.hidden " + ) + tagsFragment + NS_LITERAL_CSTRING(", h.frecency, h.hidden, h.guid " "FROM moz_places h " "LEFT JOIN moz_favicons f ON h.favicon_id = f.id " "WHERE h.url = :page_url ") diff --git a/toolkit/components/places/nsNavHistory.h b/toolkit/components/places/nsNavHistory.h index 6c77e230321..29686651af8 100644 --- a/toolkit/components/places/nsNavHistory.h +++ b/toolkit/components/places/nsNavHistory.h @@ -217,6 +217,7 @@ public: static const int32_t kGetInfoIndex_ItemTags; static const int32_t kGetInfoIndex_Frecency; static const int32_t kGetInfoIndex_Hidden; + static const int32_t kGetInfoIndex_Guid; int64_t GetTagsFolder(); diff --git a/toolkit/components/places/nsNavHistoryResult.cpp b/toolkit/components/places/nsNavHistoryResult.cpp index 4f1d64b092e..883bc4c4b73 100644 --- a/toolkit/components/places/nsNavHistoryResult.cpp +++ b/toolkit/components/places/nsNavHistoryResult.cpp @@ -233,6 +233,19 @@ nsNavHistoryResultNode::GetTags(nsAString& aTags) { return NS_OK; } +NS_IMETHODIMP +nsNavHistoryResultNode::GetPageGuid(nsACString& aPageGuid) { + aPageGuid = mPageGuid; + return NS_OK; +} + + +NS_IMETHODIMP +nsNavHistoryResultNode::GetBookmarkGuid(nsACString& aBookmarkGuid) { + aBookmarkGuid = mBookmarkGuid; + return NS_OK; +} + void nsNavHistoryResultNode::OnRemoving() diff --git a/toolkit/components/places/nsNavHistoryResult.h b/toolkit/components/places/nsNavHistoryResult.h index b12534087a4..2ad3eb25d0c 100644 --- a/toolkit/components/places/nsNavHistoryResult.h +++ b/toolkit/components/places/nsNavHistoryResult.h @@ -245,7 +245,11 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsNavHistoryResult, NS_NAVHISTORYRESULT_IID) NS_IMETHOD GetParentResult(nsINavHistoryResult** aResult) \ { return nsNavHistoryResultNode::GetParentResult(aResult); } \ NS_IMETHOD GetTags(nsAString& aTags) \ - { return nsNavHistoryResultNode::GetTags(aTags); } + { return nsNavHistoryResultNode::GetTags(aTags); } \ + NS_IMETHOD GetPageGuid(nsACString& aPageGuid) \ + { return nsNavHistoryResultNode::GetPageGuid(aPageGuid); } \ + NS_IMETHOD GetBookmarkGuid(nsACString& aBookmarkGuid) \ + { return nsNavHistoryResultNode::GetBookmarkGuid(aBookmarkGuid); } #define NS_FORWARD_COMMON_RESULTNODE_TO_BASE \ NS_FORWARD_COMMON_RESULTNODE_TO_BASE_NO_GETITEMMID \ @@ -274,6 +278,8 @@ public: NS_IMETHOD GetUri(nsACString& aURI) { aURI = mURI; return NS_OK; } NS_IMETHOD GetTags(nsAString& aTags); + NS_IMETHOD GetPageGuid(nsACString& aPageGuid); + NS_IMETHOD GetBookmarkGuid(nsACString& aBookmarkGuid); virtual void OnRemoving(); @@ -376,6 +382,12 @@ public: // Transition type used when this node represents a single visit. uint32_t mTransitionType; + + // Unique Id of the page. + nsCString mPageGuid; + + // Unique Id of the bookmark. + nsCString mBookmarkGuid; }; NS_DEFINE_STATIC_IID_ACCESSOR(nsNavHistoryResultNode, NS_NAVHISTORYRESULTNODE_IID) diff --git a/toolkit/components/places/tests/unit/test_pageGuid_bookmarkGuid.js b/toolkit/components/places/tests/unit/test_pageGuid_bookmarkGuid.js new file mode 100644 index 00000000000..2d8f82b5bb4 --- /dev/null +++ b/toolkit/components/places/tests/unit/test_pageGuid_bookmarkGuid.js @@ -0,0 +1,127 @@ +/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const bmsvc = PlacesUtils.bookmarks; +const histsvc = PlacesUtils.history; + +function run_test() { + run_next_test(); +} + +add_task(function test_addBookmarksAndCheckGuids() { + let folder = bmsvc.createFolder(bmsvc.placesRoot, "test folder", bmsvc.DEFAULT_INDEX); + let b1 = bmsvc.insertBookmark(folder, uri("http://test1.com/"), + bmsvc.DEFAULT_INDEX, "1 title"); + let b2 = bmsvc.insertBookmark(folder, uri("http://test2.com/"), + bmsvc.DEFAULT_INDEX, "2 title"); + let b3 = bmsvc.insertBookmark(folder, uri("http://test3.com/"), + bmsvc.DEFAULT_INDEX, "3 title"); + let s1 = bmsvc.insertSeparator(folder, bmsvc.DEFAULT_INDEX); + let f1 = bmsvc.createFolder(folder, "test folder 2", bmsvc.DEFAULT_INDEX); + + let options = histsvc.getNewQueryOptions(); + options.queryType = Ci.nsINavHistoryQueryOptions.QUERY_TYPE_BOOKMARKS; + let query = histsvc.getNewQuery(); + query.setFolders([folder], 1); + let result = histsvc.executeQuery(query, options); + let root = result.root; + root.containerOpen = true; + do_check_eq(root.childCount, 5); + + // check bookmark guids + let bookmarkGuidZero = root.getChild(0).bookmarkGuid; + do_check_eq(bookmarkGuidZero.length, 12); + // bookmarks have bookmark guids + do_check_eq(root.getChild(1).bookmarkGuid.length, 12); + do_check_eq(root.getChild(2).bookmarkGuid.length, 12); + // separator has bookmark guid + do_check_eq(root.getChild(3).bookmarkGuid.length, 12); + // folder has bookmark guid + do_check_eq(root.getChild(4).bookmarkGuid.length, 12); + // all bookmark guids are different. + do_check_neq(bookmarkGuidZero, root.getChild(1).bookmarkGuid); + do_check_neq(root.getChild(1).bookmarkGuid, root.getChild(2).bookmarkGuid); + do_check_neq(root.getChild(2).bookmarkGuid, root.getChild(3).bookmarkGuid); + do_check_neq(root.getChild(3).bookmarkGuid, root.getChild(4).bookmarkGuid); + + // check page guids + let pageGuidZero = root.getChild(0).pageGuid; + do_check_eq(pageGuidZero.length, 12); + // bookmarks have page guids + do_check_eq(root.getChild(1).pageGuid.length, 12); + do_check_eq(root.getChild(2).pageGuid.length, 12); + // folder and separator don't have page guids + do_check_eq(root.getChild(3).pageGuid, ""); + do_check_eq(root.getChild(4).pageGuid, ""); + + do_check_neq(pageGuidZero, root.getChild(1).pageGuid); + do_check_neq(root.getChild(1).pageGuid, root.getChild(2).pageGuid); + + root.containerOpen = false; + + remove_all_bookmarks(); +}); + +add_task(function test_updateBookmarksAndCheckGuids() { + let folder = bmsvc.createFolder(bmsvc.placesRoot, "test folder", bmsvc.DEFAULT_INDEX); + let b1 = bmsvc.insertBookmark(folder, uri("http://test1.com/"), + bmsvc.DEFAULT_INDEX, "1 title"); + let f1 = bmsvc.createFolder(folder, "test folder 2", bmsvc.DEFAULT_INDEX); + + let options = histsvc.getNewQueryOptions(); + options.queryType = Ci.nsINavHistoryQueryOptions.QUERY_TYPE_BOOKMARKS; + let query = histsvc.getNewQuery(); + query.setFolders([folder], 1); + let result = histsvc.executeQuery(query, options); + let root = result.root; + root.containerOpen = true; + do_check_eq(root.childCount, 2); + + // ensure the bookmark and page guids remain the same after modifing other property. + let bookmarkGuidZero = root.getChild(0).bookmarkGuid; + let pageGuidZero = root.getChild(0).pageGuid; + bmsvc.setItemTitle(b1, "1 title mod"); + do_check_eq(root.getChild(0).title, "1 title mod"); + do_check_eq(root.getChild(0).bookmarkGuid, bookmarkGuidZero); + do_check_eq(root.getChild(0).pageGuid, pageGuidZero); + + let bookmarkGuidOne = root.getChild(1).bookmarkGuid; + let pageGuidOne = root.getChild(1).pageGuid; + bmsvc.setItemTitle(f1, "test foolder 234"); + do_check_eq(root.getChild(1).title, "test foolder 234"); + do_check_eq(root.getChild(1).bookmarkGuid, bookmarkGuidOne); + do_check_eq(root.getChild(1).pageGuid, pageGuidOne); + + root.containerOpen = false; + + remove_all_bookmarks(); +}); + +add_task(function test_addVisitAndCheckGuid() { + // add a visit and test page guid and non-existing bookmark guids. + let now = Date.now() * 1000; + let sourceURI = uri("http://test4.com/"); + yield promiseAddVisits({ uri: sourceURI }); + do_check_eq(bmsvc.getBookmarkedURIFor(sourceURI), null); + + let options = histsvc.getNewQueryOptions(); + let query = histsvc.getNewQuery(); + query.uri = sourceURI; + result = histsvc.executeQuery(query, options); + let root = result.root; + root.containerOpen = true; + do_check_eq(root.childCount, 1); + + pageGuidZero = root.getChild(0).pageGuid; + do_check_eq(pageGuidZero.length, 12); + + do_check_eq(root.getChild(0).bookmarkGuid, ""); + + root.containerOpen = false; + + yield promiseClearHistory(); +}); + diff --git a/toolkit/components/places/tests/unit/xpcshell.ini b/toolkit/components/places/tests/unit/xpcshell.ini index a23900db796..5bb6055b4de 100644 --- a/toolkit/components/places/tests/unit/xpcshell.ini +++ b/toolkit/components/places/tests/unit/xpcshell.ini @@ -126,3 +126,4 @@ skip-if = os == "android" [test_placesTxn.js] [test_telemetry.js] [test_getPlacesInfo.js] +[test_pageGuid_bookmarkGuid.js] From 50fee83906ddfdbb6bc159fabbdb054cb10182d0 Mon Sep 17 00:00:00 2001 From: Eitan Isaacson Date: Tue, 3 Sep 2013 16:06:22 +0300 Subject: [PATCH 44/64] Bug 795984 - Implement speech output with Web Speech API. r=yzen --- accessible/src/jsat/AccessFu.jsm | 116 ++++++++++++++++++++++++++++++- accessible/src/jsat/jar.mn | 1 + accessible/src/jsat/tick.wav | Bin 0 -> 3652 bytes 3 files changed, 115 insertions(+), 2 deletions(-) create mode 100644 accessible/src/jsat/tick.wav diff --git a/accessible/src/jsat/AccessFu.jsm b/accessible/src/jsat/AccessFu.jsm index 9527a5197c7..0edb9a24515 100644 --- a/accessible/src/jsat/AccessFu.jsm +++ b/accessible/src/jsat/AccessFu.jsm @@ -492,6 +492,119 @@ var Output = { } }, + speechHelper: { + EARCONS: ['chrome://global/content/accessibility/tick.wav'], + + delayedActions: [], + + earconsToLoad: -1, // -1: not inited, 1 or more: initing, 0: inited + + earconBuffers: {}, + + webaudioEnabled: false, + + webspeechEnabled: false, + + doDelayedActionsIfLoaded: function doDelayedActionsIfLoaded(aToLoadCount) { + if (aToLoadCount === 0) { + this.outputActions(this.delayedActions); + this.delayedActions = []; + return true; + } + + return false; + }, + + init: function init() { + if (this.earconsToLoad === 0) { + // Already inited. + return; + } + + let window = Utils.win; + this.webaudioEnabled = !!window.AudioContext; + this.webspeechEnabled = !!window.speechSynthesis; + + this.earconsToLoad = this.webaudioEnabled ? this.EARCONS.length : 0; + + if (this.doDelayedActionsIfLoaded(this.earconsToLoad)) { + // Nothing to load + return; + } + + this.audioContext = new window.AudioContext(); + + for (let earcon of this.EARCONS) { + let xhr = new window.XMLHttpRequest(); + xhr.open('GET', earcon); + xhr.responseType = 'arraybuffer'; + xhr.onerror = () => { + Logger.error('Error getting earcon:', xhr.statusText); + this.doDelayedActionsIfLoaded(--this.earconsToLoad); + }; + xhr.onload = () => { + this.audioContext.decodeAudioData( + xhr.response, + (audioBuffer) => { + try { + let earconName = /.*\/(.*)\..*$/.exec(earcon)[1]; + this.earconBuffers[earconName] = new WeakMap(); + this.earconBuffers[earconName].set(window, audioBuffer); + this.doDelayedActionsIfLoaded(--this.earconsToLoad); + } catch (x) { + Logger.logException(x); + } + }, + () => { + this.doDelayedActionsIfLoaded(--this.earconsToLoad); + Logger.error('Error decoding earcon'); + }); + }; + xhr.send(); + } + }, + + output: function output(aActions) { + if (this.earconsToLoad !== 0) { + // We did not load the earcons yet. + this.delayedActions.push.apply(this.delayedActions, aActions); + if (this.earconsToLoad < 0) { + // Loading did not start yet, start it. + this.init(); + } + return; + } + + this.outputActions(aActions); + }, + + outputActions: function outputActions(aActions) { + for (let action of aActions) { + let window = Utils.win; + Logger.info('tts.' + action.method, + '"' + action.data + '"', + JSON.stringify(action.options)); + + if (!action.options.enqueue && this.webspeechEnabled) { + window.speechSynthesis.cancel(); + } + + if (action.method === 'speak' && this.webspeechEnabled) { + window.speechSynthesis.speak( + new window.SpeechSynthesisUtterance(action.data)); + } else if (action.method === 'playEarcon' && this.webaudioEnabled) { + let audioBufferWeakMap = this.earconBuffers[action.data]; + if (audioBufferWeakMap) { + let node = this.audioContext.createBufferSource(); + node.connect(this.audioContext.destination); + node.buffer = audioBufferWeakMap.get(window); + node.start(0); + } + } + } + } + }, + start: function start() { Cu.import('resource://gre/modules/Geometry.jsm'); }, @@ -509,8 +622,7 @@ var Output = { }, Speech: function Speech(aDetails, aBrowser) { - for each (let action in aDetails.actions) - Logger.info('tts.' + action.method, '"' + action.data + '"', JSON.stringify(action.options)); + this.speechHelper.output(aDetails.actions); }, Visual: function Visual(aDetails, aBrowser) { diff --git a/accessible/src/jsat/jar.mn b/accessible/src/jsat/jar.mn index aa989ff006c..e5487fe1c17 100644 --- a/accessible/src/jsat/jar.mn +++ b/accessible/src/jsat/jar.mn @@ -5,3 +5,4 @@ toolkit.jar: content/global/accessibility/AccessFu.css (AccessFu.css) content/global/accessibility/content-script.js (content-script.js) + content/global/accessibility/tick.wav (tick.wav) diff --git a/accessible/src/jsat/tick.wav b/accessible/src/jsat/tick.wav new file mode 100644 index 0000000000000000000000000000000000000000..b40a1bbd0e85afe96f869ef38ac21d5a80344e2d GIT binary patch literal 3652 zcmXX|33yFc*M8T&LnaYZ456W>8bb|5DUF~_4Uw2*_^6l?D&{YyYDdH&}-&prE`yU$+heb>9*y`#eW_3Kd;7!f+W z@8lVC8&v~9axLpAgC&4MH4F$JGV}v^3?I}lB79Kjz+f2f@9*9on~l3y7I8cS4pw&|h^c zntHPTy`;Nk{_P_&o9{}UxV}R_{&-X9#-tG^ej0hVhFVr|p#J1H7o?p3b7k9JH1qVi z$j{Nrwxm86r>!e&(5!9Iu6t*j4(Qg-%Dx+UZ%obUL}F;y}x?t`z((y)+qBbuiCj&YfP__TX^}!hdvwpy~;fj zV72{lS&HYFJyNxT-M$K~D|WgU`4;)!ab*>Eu~h~PG4JHtT`TGgs=l{q=Cd_bS_Or< zx;)yiQOCzCuc*5#+b`U)rd+$DoVV=>rcl4*Nq2epw9g6OL|v`?o|U4O+je6$H|Are zTz8{kwi`U!{f8?CwS8CnZ1$v-BzhkBCj0EHyjd3I2=n@=vQ~xLXMI4i%m2l4^K;d& z9EHUN<=1?&{W_WrN~rhN8?3(i9t}`l=CTe`zP2j{`U3<|2$%5;yWKg*T37J~Yp-hd zpo-%1WXEB@nY^X+ushf{(66!XSP`jCdatmY6{~E+eMjm&Wna(}pZCmbWp}8cN~|rY zGKD|#PQ+`K{^p!LipG0-nYQ-VZN0gaTfow1xQdEbt!Wtb<3II!gi^4+X?0b{?728? z%|?GmHg)vmnIva5#}4z{%HWpRYG&~as^mX(0ix_H$!5k;Z^vHJ?#ei>+vldQoqtCCd?Wx_;cy9yO-|maNBC=0;{XT;h1Lz>ZLSUowXu8 z-nJ~SROGw*@I&WgW%vBoN^;bdYE)SHju6MYo+U09O?O6{tL{8LWxqsKOdam4%IUgU zW3u>LTt&8-q2E;=$8FwOIZQuruzJ%o($sVWQ?4t*%yC|$lFCvK+k+ehdbc%&PT8Ka zQ}?nQCY5p(A;dI7GuQP4jE#dFwOMA*My5pQl&b=PEMp3q-ImfwobG9Rj z&R2$8PaT)+?L42lR?u}v5|&#lObI39UzV?aT}9jH;<5Ei=TjQ?T9%be&Fvr3NIl=0 z#XZzF>L7=iF=(K=W4}IP22%`*bs*oPhd5=L;TSp4+1%wYl|c2(QQebb$fLu|eU)Yl zGGACS1)G|w7tZKHwq?r5q9 z^I+A68k*rc2i0wz=$>wAPT+u`&(YsgtXj-5dO07bOzbjwW+E*9m}l}>ZpLlUjjr+^ zW;VA*Q@KyUM5LI1n>@TtVWzEKi$c0$cIhBmrpB5mPnxMvpg@Z>(@1qo|Ln1Y><_4e zwaL>Bzo>K$(yRD=>SDHgerGS+U;LL9g(9`v+;{KO9o0B`p%0pP+QxmXO5H;ZBwt-> zW#dO$Y^G};q$AJ-n*OwjcIknZLLYUMmx?0aqf_XiC+PO*OndmQnaXYWvI*pId_?Ad zZRX-E)kl;bs$(!vrSgx~brYhhqJ`zJQ>jo*F^fGp9BD5{gs0qd0~aXKEYx)=RefvL zdhQyd!bw{>`Y3gw44rRX;+pgpicE=l$>WgD0cH>%pfR*v$6AT3R5$c9u{@P_;J$X4 zrtqdH{@e6LF23e$Gm@Y4Y~ITY5siABVL~yBf-qlS)WnU60H&Yz*(GlL+PQd;=v2#YU-3A@WUvsg31y1&w(TkEPKRE31q_8g0cpTmx=IU<}{k zGz>s>Y{U1s#x=1IComFkAe*~jBz2%-UdG39PY}%)|9n$5l@6JJ2z3}6%ncrE)MhH(qXoo5E6^%dt%| z@?J9-A@mL+*s#B3dtUl~w($6xU?^hyBnMA8;54B3Jsv zZ6=8>nn-6T_+W}zV7##%4fzx4q@(E1>&*#ni(o!!jwHsNxVg{Wd6szfM7Hw;cFS`t zf6hC&B{$^r?2ozJN;+T)=JR5cBs%PYOp|MFOCJp3LBd}%oD|nhmW+Kwxj*rL*jHHJ z!f)_X&cis^`IhO4gV@Mm=F7ruJ${#`N`(@6B@e&`)J1|+rw#&fnl;B`CF%(a^SKtL z;Grn1J{BU6len9>z;j+LIlc$C^xSivgx)BS6HgR6B9(VZNfucR`xCKzr$vrg9$GCwoC8=3yoBeG&d!B jJbsl}ZP5z9;Hm8U9mGfTWqxmol`U~YkbphtkFoeas2Q~l literal 0 HcmV?d00001 From 381a6de0cc93e53fb538b99475412cc0b72d7095 Mon Sep 17 00:00:00 2001 From: Blake Kaplan Date: Tue, 3 Sep 2013 16:59:11 +0200 Subject: [PATCH 45/64] Bug 912044 - Initialize rv so we don't use it uninitialized. r=bz --- content/xul/document/src/XULDocument.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/xul/document/src/XULDocument.cpp b/content/xul/document/src/XULDocument.cpp index 734e76920ae..8ea3408b7f9 100644 --- a/content/xul/document/src/XULDocument.cpp +++ b/content/xul/document/src/XULDocument.cpp @@ -3493,7 +3493,7 @@ XULDocument::OnStreamComplete(nsIStreamLoader* aLoader, // transcluded script completes. Compile and execute the script // if the load was successful, then continue building content // from the prototype. - nsresult rv; + nsresult rv = aStatus; NS_ASSERTION(mCurrentScriptProto && mCurrentScriptProto->mSrcLoading, "script source not loading on unichar stream complete?"); From beebe3e24e8e8c7875c5c64f606b645887989528 Mon Sep 17 00:00:00 2001 From: Ryan VanderMeulen Date: Tue, 3 Sep 2013 11:05:54 -0400 Subject: [PATCH 46/64] Bug 627487 - Touch CLOBBER. --- CLOBBER | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CLOBBER b/CLOBBER index fca4a2d6b37..d694d03373b 100644 --- a/CLOBBER +++ b/CLOBBER @@ -18,4 +18,4 @@ # Modifying this file will now automatically clobber the buildbot machines \o/ # -Bug 909870 - xpidl header generation is somehow busted so we need to clobber on windows +Bug 627487 - random test failures caused by bookmark JSON changes From aa769cb10d76e6479920c1a737f59eb084280f10 Mon Sep 17 00:00:00 2001 From: Luke Wagner Date: Mon, 2 Sep 2013 11:22:44 -0500 Subject: [PATCH 47/64] Bug 911834 - OdinMonkey: create phis with a type directly (r=jandem) --HG-- extra : rebase_source : 2b6a9168c855f9f8c028022f7fb7dbb85459ab1a --- js/src/jit/AsmJS.cpp | 29 +++++----- js/src/jit/MIR.cpp | 6 -- js/src/jit/MIR.h | 8 ++- js/src/jit/MIRGraph.cpp | 120 ++++++++++++++++++++++++++++++++++------ js/src/jit/MIRGraph.h | 3 + 5 files changed, 124 insertions(+), 42 deletions(-) diff --git a/js/src/jit/AsmJS.cpp b/js/src/jit/AsmJS.cpp index 73f29cc8815..e94b0260696 100644 --- a/js/src/jit/AsmJS.cpp +++ b/js/src/jit/AsmJS.cpp @@ -2229,7 +2229,8 @@ class FunctionCompiler *loopEntry = NULL; return true; } - *loopEntry = MBasicBlock::NewPendingLoopHeader(mirGraph(), info(), curBlock_, NULL); + *loopEntry = MBasicBlock::NewAsmJS(mirGraph(), info(), curBlock_, + MBasicBlock::PENDING_LOOP_HEADER); if (!*loopEntry) return false; mirGraph().addBlock(*loopEntry); @@ -2287,7 +2288,8 @@ class FunctionCompiler if (curBlock_) { JS_ASSERT(curBlock_->loopDepth() == loopStack_.length() + 1); curBlock_->end(MGoto::New(loopEntry)); - loopEntry->setBackedge(curBlock_); + if (!loopEntry->setBackedgeAsmJS(curBlock_)) + return false; } curBlock_ = afterLoop; if (curBlock_) @@ -2309,7 +2311,8 @@ class FunctionCompiler if (cond->isConstant()) { if (ToBoolean(cond->toConstant()->value())) { curBlock_->end(MGoto::New(loopEntry)); - loopEntry->setBackedge(curBlock_); + if (!loopEntry->setBackedgeAsmJS(curBlock_)) + return false; curBlock_ = NULL; } else { MBasicBlock *afterLoop; @@ -2323,7 +2326,8 @@ class FunctionCompiler if (!newBlock(curBlock_, &afterLoop, afterLoopStmt)) return false; curBlock_->end(MTest::New(cond, loopEntry, afterLoop)); - loopEntry->setBackedge(curBlock_); + if (!loopEntry->setBackedgeAsmJS(curBlock_)) + return false; curBlock_ = afterLoop; } } @@ -2449,7 +2453,7 @@ class FunctionCompiler bool newBlockWithDepth(MBasicBlock *pred, unsigned loopDepth, MBasicBlock **block, ParseNode *pn) { - *block = MBasicBlock::New(mirGraph(), info(), pred, /* pc = */ NULL, MBasicBlock::NORMAL); + *block = MBasicBlock::NewAsmJS(mirGraph(), info(), pred, MBasicBlock::NORMAL); if (!*block) return false; noteBasicBlockPosition(*block, pn); @@ -3782,12 +3786,6 @@ CheckConditional(FunctionCompiler &f, ParseNode *ternary, MDefinition **def, Typ f.pushPhiInput(elseDef); - // next statement is actually not the else expr, but this is the closest stmt to the next - // one that is directly reachable - if (!f.joinIfElse(thenBlocks, elseExpr)) - return false; - *def = f.popPhiOutput(); - if (thenType.isInt() && elseType.isInt()) { *type = Type::Int; } else if (thenType.isDouble() && elseType.isDouble()) { @@ -3797,6 +3795,10 @@ CheckConditional(FunctionCompiler &f, ParseNode *ternary, MDefinition **def, Typ "current types are %s and %s", thenType.toChars(), elseType.toChars()); } + if (!f.joinIfElse(thenBlocks, elseExpr)) + return false; + + *def = f.popPhiOutput(); return true; } @@ -4311,12 +4313,9 @@ CheckIf(FunctionCompiler &f, ParseNode *ifStmt) MBasicBlock *thenBlock, *elseBlock; - ParseNode *elseBlockStmt = NULL; // The second block given to branchAndStartThen contains either the else statement if // there is one, or the join block; so we need to give the next statement accordingly. - elseBlockStmt = elseStmt; - if (elseBlockStmt == NULL) - elseBlockStmt = nextStmt; + ParseNode *elseBlockStmt = elseStmt ? elseStmt : nextStmt; if (!f.branchAndStartThen(condDef, &thenBlock, &elseBlock, thenStmt, elseBlockStmt)) return false; diff --git a/js/src/jit/MIR.cpp b/js/src/jit/MIR.cpp index 38c2919f475..c27e30344a7 100644 --- a/js/src/jit/MIR.cpp +++ b/js/src/jit/MIR.cpp @@ -625,12 +625,6 @@ MUnbox::printOpcode(FILE *fp) const } } -MPhi * -MPhi::New(uint32_t slot) -{ - return new MPhi(slot); -} - void MPhi::removeOperand(size_t index) { diff --git a/js/src/jit/MIR.h b/js/src/jit/MIR.h index 9c957e37cbc..9d5c45d7b26 100644 --- a/js/src/jit/MIR.h +++ b/js/src/jit/MIR.h @@ -3845,7 +3845,7 @@ class MPhi MOZ_FINAL : public MDefinition, public InlineForwardListNode uint32_t capacity_; #endif - MPhi(uint32_t slot) + MPhi(uint32_t slot, MIRType resultType) : slot_(slot), hasBackedgeType_(false), triedToSpecialize_(false), @@ -3855,7 +3855,7 @@ class MPhi MOZ_FINAL : public MDefinition, public InlineForwardListNode , capacity_(0) #endif { - setResultType(MIRType_Value); + setResultType(resultType); } protected: @@ -3865,7 +3865,9 @@ class MPhi MOZ_FINAL : public MDefinition, public InlineForwardListNode public: INSTRUCTION_HEADER(Phi) - static MPhi *New(uint32_t slot); + static MPhi *New(uint32_t slot, MIRType resultType = MIRType_Value) { + return new MPhi(slot, resultType); + } void setOperand(size_t index, MDefinition *operand) { // Note: after the initial IonBuilder pass, it is OK to change phi diff --git a/js/src/jit/MIRGraph.cpp b/js/src/jit/MIRGraph.cpp index 26cb662290b..4c37c4f8293 100644 --- a/js/src/jit/MIRGraph.cpp +++ b/js/src/jit/MIRGraph.cpp @@ -159,6 +159,8 @@ MBasicBlock * MBasicBlock::New(MIRGraph &graph, CompileInfo &info, MBasicBlock *pred, jsbytecode *entryPc, Kind kind) { + JS_ASSERT(entryPc != NULL); + MBasicBlock *block = new MBasicBlock(graph, info, entryPc, kind); if (!block->init()) return NULL; @@ -212,7 +214,9 @@ MBasicBlock::NewPendingLoopHeader(MIRGraph &graph, CompileInfo &info, MBasicBlock * MBasicBlock::NewSplitEdge(MIRGraph &graph, CompileInfo &info, MBasicBlock *pred) { - return MBasicBlock::New(graph, info, pred, pred->pc(), SPLIT_EDGE); + return pred->pc() + ? MBasicBlock::New(graph, info, pred, pred->pc(), SPLIT_EDGE) + : MBasicBlock::NewAsmJS(graph, info, pred, SPLIT_EDGE); } MBasicBlock * @@ -235,6 +239,40 @@ MBasicBlock::NewAbortPar(MIRGraph &graph, CompileInfo &info, return block; } +MBasicBlock * +MBasicBlock::NewAsmJS(MIRGraph &graph, CompileInfo &info, MBasicBlock *pred, Kind kind) +{ + MBasicBlock *block = new MBasicBlock(graph, info, /* entryPC = */ NULL, kind); + if (!block->init()) + return NULL; + + if (pred) { + block->stackPosition_ = pred->stackPosition_; + + if (block->kind_ == PENDING_LOOP_HEADER) { + for (size_t i = 0; i < block->stackPosition_; i++) { + MDefinition *predSlot = pred->getSlot(i); + + JS_ASSERT(predSlot->type() != MIRType_Value); + MPhi *phi = MPhi::New(i, predSlot->type()); + + JS_ALWAYS_TRUE(phi->reserveLength(2)); + phi->addInput(predSlot); + + block->addPhi(phi); + block->setSlot(i, phi); + } + } else { + block->copySlots(pred); + } + + if (!block->predecessors_.append(pred)) + return NULL; + } + + return block; +} + MBasicBlock::MBasicBlock(MIRGraph &graph, CompileInfo &info, jsbytecode *pc, Kind kind) : earlyAbort_(false), graph_(graph), @@ -291,27 +329,23 @@ MBasicBlock::inherit(MBasicBlock *pred, uint32_t popped) stackPosition_ -= popped; if (kind_ != PENDING_LOOP_HEADER) copySlots(pred); - } else if (pc()) { + } else { uint32_t stackDepth = info().script()->analysis()->getCode(pc()).stackDepth; stackPosition_ = info().firstStackSlot() + stackDepth; JS_ASSERT(stackPosition_ >= popped); stackPosition_ -= popped; - } else { - stackPosition_ = info().firstStackSlot(); } JS_ASSERT(info_.nslots() >= stackPosition_); JS_ASSERT(!entryResumePoint_); - if (pc()) { - // Propagate the caller resume point from the inherited block. - MResumePoint *callerResumePoint = pred ? pred->callerResumePoint() : NULL; + // Propagate the caller resume point from the inherited block. + MResumePoint *callerResumePoint = pred ? pred->callerResumePoint() : NULL; - // Create a resume point using our initial stack state. - entryResumePoint_ = new MResumePoint(this, pc(), callerResumePoint, MResumePoint::ResumeAt); - if (!entryResumePoint_->init()) - return false; - } + // Create a resume point using our initial stack state. + entryResumePoint_ = new MResumePoint(this, pc(), callerResumePoint, MResumePoint::ResumeAt); + if (!entryResumePoint_->init()) + return false; if (pred) { if (!predecessors_.append(pred)) @@ -324,14 +358,13 @@ MBasicBlock::inherit(MBasicBlock *pred, uint32_t popped) return false; addPhi(phi); setSlot(i, phi); - if (entryResumePoint()) - entryResumePoint()->setOperand(i, phi); + entryResumePoint()->setOperand(i, phi); } - } else if (entryResumePoint()) { + } else { for (size_t i = 0; i < stackDepth(); i++) entryResumePoint()->setOperand(i, getSlot(i)); } - } else if (entryResumePoint()) { + } else { /* * Don't leave the operands uninitialized for the caller, as it may not * initialize them later on. @@ -796,7 +829,11 @@ MBasicBlock::addPredecessorPopN(MBasicBlock *pred, uint32_t popped) return false; } else { // Otherwise, create a new phi node. - MPhi *phi = MPhi::New(i); + MPhi *phi; + if (mine->type() == other->type()) + phi = MPhi::New(i, mine->type()); + else + phi = MPhi::New(i); addPhi(phi); // Prime the phi for each predecessor, so input(x) comes from @@ -859,7 +896,7 @@ MBasicBlock::setBackedge(MBasicBlock *pred) // Predecessors must be finished, and at the correct stack depth. JS_ASSERT(lastIns_); JS_ASSERT(pred->lastIns_); - JS_ASSERT_IF(entryResumePoint(), pred->stackDepth() == entryResumePoint()->stackDepth()); + JS_ASSERT(pred->stackDepth() == entryResumePoint()->stackDepth()); // We must be a pending loop header JS_ASSERT(kind_ == PENDING_LOOP_HEADER); @@ -911,6 +948,53 @@ MBasicBlock::setBackedge(MBasicBlock *pred) return AbortReason_NoAbort; } +bool +MBasicBlock::setBackedgeAsmJS(MBasicBlock *pred) +{ + // Predecessors must be finished, and at the correct stack depth. + JS_ASSERT(lastIns_); + JS_ASSERT(pred->lastIns_); + JS_ASSERT(stackDepth() == pred->stackDepth()); + + // We must be a pending loop header + JS_ASSERT(kind_ == PENDING_LOOP_HEADER); + + // Add exit definitions to each corresponding phi at the entry. + for (MPhiIterator phi = phisBegin(); phi != phisEnd(); phi++) { + MPhi *entryDef = *phi; + MDefinition *exitDef = pred->getSlot(entryDef->slot()); + + // Assert that we already placed phis for each slot. + JS_ASSERT(entryDef->block() == this); + + // Assert that the phi already has the correct type. + JS_ASSERT(entryDef->type() == exitDef->type()); + JS_ASSERT(entryDef->type() != MIRType_Value); + + if (entryDef == exitDef) { + // If the exit def is the same as the entry def, make a redundant + // phi. Since loop headers have exactly two incoming edges, we + // know that that's just the first input. + // + // Note that we eliminate later rather than now, to avoid any + // weirdness around pending continue edges which might still hold + // onto phis. + exitDef = entryDef->getOperand(0); + } + + // MBasicBlock::NewAsmJS calls reserveLength(2) for loop header phis. + entryDef->addInput(exitDef); + + JS_ASSERT(entryDef->slot() < pred->stackDepth()); + setSlot(entryDef->slot(), entryDef); + } + + // We are now a loop header proper + kind_ = LOOP_HEADER; + + return predecessors_.append(pred); +} + void MBasicBlock::clearLoopHeader() { diff --git a/js/src/jit/MIRGraph.h b/js/src/jit/MIRGraph.h index baf64fdb231..4140551c532 100644 --- a/js/src/jit/MIRGraph.h +++ b/js/src/jit/MIRGraph.h @@ -80,6 +80,8 @@ class MBasicBlock : public TempObject, public InlineListNode static MBasicBlock *NewAbortPar(MIRGraph &graph, CompileInfo &info, MBasicBlock *pred, jsbytecode *entryPc, MResumePoint *resumePoint); + static MBasicBlock *NewAsmJS(MIRGraph &graph, CompileInfo &info, + MBasicBlock *pred, Kind kind); bool dominates(MBasicBlock *other); @@ -196,6 +198,7 @@ class MBasicBlock : public TempObject, public InlineListNode // the current loop as necessary. If the backedge introduces new types for // phis at the loop header, returns a disabling abort. AbortReason setBackedge(MBasicBlock *block); + bool setBackedgeAsmJS(MBasicBlock *block); // Resets a LOOP_HEADER block to a NORMAL block. This is needed when // optimizations remove the backedge. From 60ef9585334474fb7ab3b486f587148be1a37ab5 Mon Sep 17 00:00:00 2001 From: Luke Wagner Date: Tue, 3 Sep 2013 09:56:13 -0500 Subject: [PATCH 48/64] Bug 911834 - OdinMonkey: skip ApplyTypeInformation pass (r=jandem) --HG-- extra : rebase_source : af5ae8f0bffe18672dec9dd52aa3ab6446976481 --- js/src/jit/Ion.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/js/src/jit/Ion.cpp b/js/src/jit/Ion.cpp index 7b852acbdee..08707cb7d99 100644 --- a/js/src/jit/Ion.cpp +++ b/js/src/jit/Ion.cpp @@ -1228,14 +1228,15 @@ OptimizeMIR(MIRGenerator *mir) if (mir->shouldCancel("Phi reverse mapping")) return false; - // This pass also removes copies. - if (!ApplyTypeInformation(mir, graph)) - return false; - IonSpewPass("Apply types"); - AssertExtendedGraphCoherency(graph); + if (!mir->compilingAsmJS()) { + if (!ApplyTypeInformation(mir, graph)) + return false; + IonSpewPass("Apply types"); + AssertExtendedGraphCoherency(graph); - if (mir->shouldCancel("Apply types")) - return false; + if (mir->shouldCancel("Apply types")) + return false; + } if (graph.entryBlock()->info().executionMode() == ParallelExecution) { ParallelSafetyAnalysis analysis(mir, graph); From 627caecf964a5998183206487be2b775bd000e9d Mon Sep 17 00:00:00 2001 From: Luke Wagner Date: Tue, 3 Sep 2013 11:00:24 -0500 Subject: [PATCH 49/64] Bug 911842 - OdinMonkey: disable Ion optimization passes that don't help (r=jandem) --- js/src/jit/Ion.cpp | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/js/src/jit/Ion.cpp b/js/src/jit/Ion.cpp index 08707cb7d99..f3e301b3e1b 100644 --- a/js/src/jit/Ion.cpp +++ b/js/src/jit/Ion.cpp @@ -1362,7 +1362,7 @@ OptimizeMIR(MIRGenerator *mir) // Passes after this point must not move instructions; these analyses // depend on knowing the final order in which instructions will execute. - if (js_IonOptions.edgeCaseAnalysis) { + if (js_IonOptions.edgeCaseAnalysis && !mir->compilingAsmJS()) { EdgeCaseAnalysis edgeCaseAnalysis(mir, graph); if (!edgeCaseAnalysis.analyzeLate()) return false; @@ -1373,14 +1373,16 @@ OptimizeMIR(MIRGenerator *mir) return false; } - // Note: check elimination has to run after all other passes that move - // instructions. Since check uses are replaced with the actual index, code - // motion after this pass could incorrectly move a load or store before its - // bounds check. - if (!EliminateRedundantChecks(graph)) - return false; - IonSpewPass("Bounds Check Elimination"); - AssertGraphCoherency(graph); + if (!mir->compilingAsmJS()) { + // Note: check elimination has to run after all other passes that move + // instructions. Since check uses are replaced with the actual index, + // code motion after this pass could incorrectly move a load or store + // before its bounds check. + if (!EliminateRedundantChecks(graph)) + return false; + IonSpewPass("Bounds Check Elimination"); + AssertGraphCoherency(graph); + } return true; } From 8be7d9317f01bb135364c9905e02506adc01c91a Mon Sep 17 00:00:00 2001 From: Ryan VanderMeulen Date: Tue, 3 Sep 2013 12:28:06 -0400 Subject: [PATCH 50/64] Bug 912006 - Update pdf.js to version 0.8.478. r=bdahl --- browser/extensions/pdfjs/README.mozilla | 2 +- .../pdfjs/components/PdfStreamConverter.js | 51 +- browser/extensions/pdfjs/content/PdfJs.jsm | 2 +- .../pdfjs/content/PdfJsTelemetry.jsm | 59 + browser/extensions/pdfjs/content/build/pdf.js | 43596 ++-------------- .../pdfjs/content/build/pdf.worker.js | 38469 ++++++++++++++ .../extensions/pdfjs/content/web/debugger.js | 44 +- .../extensions/pdfjs/content/web/viewer.css | 5 +- .../extensions/pdfjs/content/web/viewer.js | 115 +- browser/extensions/pdfjs/extension-files | 2 + 10 files changed, 43273 insertions(+), 39072 deletions(-) create mode 100644 browser/extensions/pdfjs/content/PdfJsTelemetry.jsm create mode 100644 browser/extensions/pdfjs/content/build/pdf.worker.js diff --git a/browser/extensions/pdfjs/README.mozilla b/browser/extensions/pdfjs/README.mozilla index ffb75edb370..df85ca6f1e4 100644 --- a/browser/extensions/pdfjs/README.mozilla +++ b/browser/extensions/pdfjs/README.mozilla @@ -1,4 +1,4 @@ This is the pdf.js project output, https://github.com/mozilla/pdf.js -Current extension version is: 0.8.423 +Current extension version is: 0.8.478 diff --git a/browser/extensions/pdfjs/components/PdfStreamConverter.js b/browser/extensions/pdfjs/components/PdfStreamConverter.js index 2427af712d9..e727864fe74 100644 --- a/browser/extensions/pdfjs/components/PdfStreamConverter.js +++ b/browser/extensions/pdfjs/components/PdfStreamConverter.js @@ -16,7 +16,7 @@ */ /* jshint esnext:true */ /* globals Components, Services, XPCOMUtils, NetUtil, PrivateBrowsingUtils, - dump, NetworkManager */ + dump, NetworkManager, PdfJsTelemetry */ 'use strict'; @@ -42,6 +42,9 @@ Cu.import('resource://pdf.js/network.js'); XPCOMUtils.defineLazyModuleGetter(this, 'PrivateBrowsingUtils', 'resource://gre/modules/PrivateBrowsingUtils.jsm'); +XPCOMUtils.defineLazyModuleGetter(this, 'PdfJsTelemetry', + 'resource://pdf.js/PdfJsTelemetry.jsm'); + var Svc = {}; XPCOMUtils.defineLazyServiceGetter(Svc, 'mime', '@mozilla.org/mime;1', @@ -194,6 +197,12 @@ PdfDataListener.prototype = { function ChromeActions(domWindow, contentDispositionFilename) { this.domWindow = domWindow; this.contentDispositionFilename = contentDispositionFilename; + this.telemetryState = { + documentInfo: false, + firstPageInfo: false, + streamTypesUsed: [], + startAt: Date.now() + }; } ChromeActions.prototype = { @@ -321,12 +330,49 @@ ChromeActions.prototype = { supportsDocumentColors: function() { return getBoolPref('browser.display.use_document_colors', true); }, + reportTelemetry: function (data) { + var probeInfo = JSON.parse(data); + switch (probeInfo.type) { + case 'documentInfo': + if (!this.telemetryState.documentInfo) { + PdfJsTelemetry.onDocumentVersion(probeInfo.version | 0); + PdfJsTelemetry.onDocumentGenerator(probeInfo.generator | 0); + if (probeInfo.formType) { + PdfJsTelemetry.onForm(probeInfo.formType === 'acroform'); + } + this.telemetryState.documentInfo = true; + } + break; + case 'pageInfo': + if (!this.telemetryState.firstPageInfo) { + var duration = Date.now() - this.telemetryState.startAt; + PdfJsTelemetry.onTimeToView(duration); + this.telemetryState.firstPageInfo = true; + } + break; + case 'streamInfo': + if (!Array.isArray(probeInfo.streamTypes)) { + break; + } + for (var i = 0; i < probeInfo.streamTypes.length; i++) { + var streamTypeId = probeInfo.streamTypes[i] | 0; + if (streamTypeId >= 0 && streamTypeId < 10 && + !this.telemetryState.streamTypesUsed[streamTypeId]) { + PdfJsTelemetry.onStreamType(streamTypeId); + this.telemetryState.streamTypesUsed[streamTypeId] = true; + } + } + break; + } + }, fallback: function(url, sendResponse) { var self = this; var domWindow = this.domWindow; var strings = getLocalizedStrings('chrome.properties'); var message = getLocalizedString(strings, 'unsupported_feature'); + PdfJsTelemetry.onFallback(); + var notificationBox = null; try { // Based on MDN's "Working with windows in chrome code" @@ -730,6 +776,9 @@ PdfStreamConverter.prototype = { false); } + PdfJsTelemetry.onViewerIsUsed(); + PdfJsTelemetry.onDocumentSize(aRequest.contentLength); + if (!rangeRequest) { // Creating storage for PDF data var contentLength = aRequest.contentLength; diff --git a/browser/extensions/pdfjs/content/PdfJs.jsm b/browser/extensions/pdfjs/content/PdfJs.jsm index 5522312d610..079e3a39e80 100644 --- a/browser/extensions/pdfjs/content/PdfJs.jsm +++ b/browser/extensions/pdfjs/content/PdfJs.jsm @@ -254,7 +254,7 @@ let PdfJs = { this._pdfStreamConverterFactory.unregister(); delete this._pdfStreamConverterFactory; - this._pdfRedirectorFactory.unregister; + this._pdfRedirectorFactory.unregister(); delete this._pdfRedirectorFactory; Svc.pluginHost.unregisterPlayPreviewMimeType(PDF_CONTENT_TYPE); diff --git a/browser/extensions/pdfjs/content/PdfJsTelemetry.jsm b/browser/extensions/pdfjs/content/PdfJsTelemetry.jsm new file mode 100644 index 00000000000..17ba05761e3 --- /dev/null +++ b/browser/extensions/pdfjs/content/PdfJsTelemetry.jsm @@ -0,0 +1,59 @@ +/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ +/* Copyright 2013 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* jshint esnext:true */ + +'use strict'; + +this.EXPORTED_SYMBOLS = ['PdfJsTelemetry']; + +const Cu = Components.utils; +Cu.import('resource://gre/modules/Services.jsm'); + +this.PdfJsTelemetry = { + onViewerIsUsed: function () { + let histogram = Services.telemetry.getHistogramById("PDF_VIEWER_USED"); + histogram.add(true); + }, + onFallback: function () { + let histogram = Services.telemetry.getHistogramById("PDF_VIEWER_FALLBACK_SHOWN"); + histogram.add(true); + }, + onDocumentSize: function (size) { + let histogram = Services.telemetry.getHistogramById("PDF_VIEWER_DOCUMENT_SIZE_KB"); + histogram.add(size / 1024); + }, + onDocumentVersion: function (versionId) { + let histogram = Services.telemetry.getHistogramById("PDF_VIEWER_DOCUMENT_VERSION"); + histogram.add(versionId); + }, + onDocumentGenerator: function (generatorId) { + let histogram = Services.telemetry.getHistogramById("PDF_VIEWER_DOCUMENT_GENERATOR"); + histogram.add(generatorId); + }, + onForm: function (isAcroform) { + let histogram = Services.telemetry.getHistogramById("PDF_VIEWER_FORM"); + histogram.add(isAcroform); + }, + onStreamType: function (streamTypeId) { + let histogram = Services.telemetry.getHistogramById("PDF_VIEWER_STREAM_TYPES"); + histogram.add(streamTypeId); + }, + onTimeToView: function (ms) { + let histogram = Services.telemetry.getHistogramById("PDF_VIEWER_TIME_TO_VIEW_MS"); + histogram.add(ms); + } +}; diff --git a/browser/extensions/pdfjs/content/build/pdf.js b/browser/extensions/pdfjs/content/build/pdf.js index 52d8b88b0a0..f1552b60bd4 100644 --- a/browser/extensions/pdfjs/content/build/pdf.js +++ b/browser/extensions/pdfjs/content/build/pdf.js @@ -20,8 +20,8 @@ if (typeof PDFJS === 'undefined') { (typeof window !== 'undefined' ? window : this).PDFJS = {}; } -PDFJS.version = '0.8.423'; -PDFJS.build = 'e2993a7'; +PDFJS.version = '0.8.478'; +PDFJS.build = '8a4a6f4'; (function pdfjsWrapper() { // Use strict in our context only - users might not want it @@ -43,642 +43,10 @@ PDFJS.build = 'e2993a7'; * See the License for the specific language governing permissions and * limitations under the License. */ -/* globals assert, MissingDataException, isInt, NetworkManager, Promise, - isEmptyObj */ +/* globals Cmd, ColorSpace, Dict, MozBlobBuilder, Name, PDFJS, Ref */ 'use strict'; -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; - } - - // 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; - } - } - }, - - ensureRange: function ChunkedStream_ensureRange(begin, end) { - if (begin >= end) { - 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 - }); - 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 Promise(); - } - - ChunkedStreamManager.prototype = { - - 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; - var prevChunk; - for (var i = 0; i < chunks.length; ++i) { - var chunk = chunks[i]; - - if (!beginChunk) { - beginChunk = chunk; - } - - if (prevChunk && 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); - }, - - 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(); - } - } - }; - - 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 Promise(); - 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 Promise(); - 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 Promise(); - promise.resolve(); - return promise; - }; - - LocalPdfManager.prototype.requestLoadedStream = - function LocalPdfManager_requestLoadedStream() { - }; - - LocalPdfManager.prototype.onLoadedStream = - function LocalPdfManager_getLoadedStream() { - return this.loadedStream; - }; - - return LocalPdfManager; -})(); - -var NetworkPdfManager = (function NetworkPdfManagerClosure() { - - var CHUNK_SIZE = 65536; - - function NetworkPdfManager(args, msgHandler) { - - this.msgHandler = msgHandler; - - var params = { - msgHandler: msgHandler, - httpHeaders: args.httpHeaders, - chunkedViewerLoading: args.chunkedViewerLoading, - disableAutoFetch: args.disableAutoFetch - }; - 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 Promise(); - 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 Promise(); - 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(); - }; - - return NetworkPdfManager; -})(); - - - var globalScope = (typeof window === 'undefined') ? this : window; var isWorker = (typeof window == 'undefined'); @@ -686,6 +54,21 @@ var isWorker = (typeof window == 'undefined'); var ERRORS = 0, WARNINGS = 1, INFOS = 5; var verbosity = WARNINGS; +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 @@ -696,483 +79,6 @@ if (!globalScope.PDFJS) { globalScope.PDFJS.pdfBug = false; -var Page = (function PageClosure() { - - function Page(pdfManager, xref, pageIndex, pageDict, ref) { - this.pdfManager = pdfManager; - this.pageIndex = pageIndex; - this.pageDict = pageDict; - this.xref = xref; - this.ref = ref; - 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 Promise(); - 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 Promise(); - - function reject(e) { - promise.reject(e); - } - - var pageListPromise = new Promise(); - - 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); - - 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) { - PartialEvaluator.optimizeQueue(pageOpList); - pageOpList.flush(true); - promise.resolve(pageOpList); - return; - } - - var annotationsReadyPromise = Annotation.appendToOperatorList( - annotations, pageOpList, pdfManager, partialEvaluator); - annotationsReadyPromise.then(function () { - PartialEvaluator.optimizeQueue(pageOpList); - 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 Promise(); - - 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); - - 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); - this.acroForm = this.catalog.catDict.get('AcroForm'); - }, - - 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 - }; - 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, fileID; - if (xref.trailer.has('ID')) { - fileID = ''; - var id = xref.trailer.get('ID')[0]; - id.split('').forEach(function(el) { - fileID += Number(el.charCodeAt(0)).toString(16); - }); - } else { - // If we got no fileID, then we generate one, - // from the first 100 bytes of PDF - var data = this.stream.bytes.subarray(0, 100); - var hash = calculateMD5(data, 0, data.length); - fileID = ''; - for (var i = 0, length = hash.length; i < length; i++) { - fileID += Number(hash[i]).toString(16); - } - } - - return shadow(this, 'fingerprint', fileID); - }, - - traversePages: function PDFDocument_traversePages() { - this.catalog.traversePages(); - }, - - getPage: function PDFDocument_getPage(pageIndex) { - return this.catalog.getPage(pageIndex); - } - }; - - return PDFDocument; -})(); - - - // Use only for debugging purposes. This should not be used in any code that is // in mozilla master. var log = (function() { @@ -1620,6 +526,21 @@ var Util = PDFJS.Util = (function UtilClosure() { } }; + 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; })(); @@ -2103,4730 +1024,1253 @@ PDFJS.createBlob = function createBlob(data, contentType) { return bb.getBlob(contentType); }; - -/** - * 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; - -/** - * 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|TypedAray|object} source Can be an url to where a PDF is - * located, a typed array (Uint8Array) already populated with data or - * and parameter object with the following possible fields: - * - url - The URL of the PDF. - * - data - A typed array with PDF data. - * - httpHeaders - Basic authentication headers. - * - password - For decrypting password-protected PDFs. - * - * @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 {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.Promise(); - workerReadyPromise = new PDFJS.Promise(); - 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. - */ -var PDFDocumentProxy = (function PDFDocumentProxyClosure() { - function PDFDocumentProxy(pdfInfo, transport) { - this.pdfInfo = pdfInfo; - this.transport = transport; - } - 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} The page number to get. The first page is 1. - * @return {Promise} A promise that is resolved with a {PDFPageProxy} - * object. - */ - getPage: function PDFDocumentProxy_getPage(number) { - return this.transport.getPage(number); - }, - /** - * @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_getDestinations() { - var promise = new PDFJS.Promise(); - 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.Promise(); - 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.Promise(); - var info = this.pdfInfo.info; - var metadata = this.pdfInfo.metadata; - promise.resolve({ - info: info, - metadata: metadata ? new PDFJS.Metadata(metadata) : null - }); - return promise; - }, - isEncrypted: function PDFDocumentProxy_isEncrypted() { - var promise = new PDFJS.Promise(); - promise.resolve(this.pdfInfo.encrypted); - 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.Promise(); - 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(); - }, - destroy: function PDFDocumentProxy_destroy() { - this.transport.destroy(); - } - }; - return PDFDocumentProxy; -})(); - -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 = { - /** - * @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.Promise(); - 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 Promise(); - 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.reject(error); - } else { - renderTask.resolve(); - } - stats.timeEnd('Rendering'); - stats.timeEnd('Overall'); - } - - return renderTask; - }, - /** - * @return {Promise} That is resolved with the a {string} that is the text - * content from the page. - */ - getTextContent: function PDFPageProxy_getTextContent() { - var promise = new PDFJS.Promise(); - this.transport.messageHandler.send('GetTextContent', { - pageIndex: this.pageNumber - 1 - }, - function textContentCallback(textContent) { - promise.resolve(textContent); - } - ); - return promise; - }, - /** - * Stub for future feature. - */ - getOperationList: function PDFPageProxy_getOperationList() { - var promise = new PDFJS.Promise(); - var operationList = { // not implemented - dependencyFontsID: null, - operatorList: null - }; - promise.resolve(operationList); - 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. - */ - _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. - */ - _startRenderPage: function PDFPageProxy_startRenderPage(transparency) { - this.displayReadyPromise.resolve(transparency); - }, - /** - * For internal use only. - */ - _renderPageChunk: function PDFPageProxy_renderPageChunk(operatorListChunk) { - // Add the new chunk to the current operator list. - Util.concatenateToArray(this.operatorList.fnArray, - operatorListChunk.fnArray); - Util.concatenateToArray(this.operatorList.argsArray, - operatorListChunk.argsArray); - 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. - */ -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 (typeof workerSrc === 'undefined') { - 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(supportTypedArray) { - if (supportTypedArray) { - this.worker = worker; - this.setupMessageHandler(messageHandler); - } else { - globalScope.PDFJS.disableWorker = true; - this.setupFakeWorker(); - } - workerInitializedPromise.resolve(); - }.bind(this)); - - var testObj = new Uint8Array(1); - // Some versions of Opera throw a DATA_CLONE_ERR on - // serializing the typed array. - 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.setupFakeWorker(); - workerInitializedPromise.resolve(); - } - WorkerTransport.prototype = { - destroy: function WorkerTransport_destroy() { - this.pageCache = []; - this.pagePromises = []; - var self = this; - this.messageHandler.send('Terminate', null, function () { - if (self.worker) { - self.worker.terminate(); - } - }); - }, - setupFakeWorker: function WorkerTransport_setupFakeWorker() { - warn('Setting up fake worker.'); - // If we don't use a worker, just post/sendMessage to the main thread. - var fakeWorker = { - postMessage: function WorkerTransport_postMessage(obj) { - fakeWorker.onmessage({data: obj}); - }, - terminate: function WorkerTransport_terminate() {} - }; - - var messageHandler = new MessageHandler('main', fakeWorker); - this.setupMessageHandler(messageHandler); - - // If the main thread is our worker, setup the handling for the messages - // the main thread sends to it self. - 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 Font(exportedData); - } - - FontLoader.bind( - [font], - function fontReady(fontObjs) { - this.commonObjs.resolve(id, font); - }.bind(this) - ); - 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, promise) { - var imageData = 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]; - } - } - promise.resolve({ data: buf, width: width, height: height}); - }).bind(this); - var src = 'data:image/jpeg;base64,' + window.btoa(imageData); - img.src = src; - }); - }, - - 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 - }); - }, - - getData: function WorkerTransport_getData(promise) { - this.messageHandler.send('GetData', null, function(data) { - promise.resolve(data); - }); - }, - - dataLoaded: function WorkerTransport_dataLoaded() { - var promise = new PDFJS.Promise(); - this.messageHandler.send('DataLoaded', null, function(args) { - promise.resolve(args); - }); - 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.Promise('Page ' + pageNumber); - this.pagePromises[pageIndex] = promise; - this.messageHandler.send('GetPageRequest', { pageIndex: pageIndex }); - return promise; - }, - - getAnnotations: function WorkerTransport_getAnnotations(pageIndex) { - this.messageHandler.send('GetAnnotationsRequest', - { pageIndex: pageIndex }); - }, - - getDestinations: function WorkerTransport_getDestinations() { - var promise = new PDFJS.Promise(); - this.messageHandler.send('GetDestinations', null, - function transportDestinations(destinations) { - promise.resolve(destinations); - } - ); - return promise; - } - }; - return WorkerTransport; - -})(); - -/** - * RenderTask is basically a promise but adds a cancel function to terminate it. - */ -var RenderTask = (function RenderTaskClosure() { - function RenderTask(internalRenderTask) { - this.internalRenderTask = internalRenderTask; - Promise.call(this); - } - - RenderTask.prototype = Object.create(Promise.prototype); - - /** - * Cancel the rendering task. If the task is curently rendering it will not be - * cancelled until graphics pauses with a timeout. The promise that this - * object extends will resolved when cancelled. - */ - RenderTask.prototype.cancel = function RenderTask_cancel() { - this.internalRenderTask.cancel(); - }; - - return RenderTask; -})(); - -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.fnArray.length) { - this.running = false; - if (this.operatorList.lastChunk) { - this.gfx.endDrawing(); - this.callback(); - } - } - } - - }; - - return InternalRenderTask; -})(); - - -// contexts store most of the state we need natively. -// However, PDF needs a bit more state, which we store here. - -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 -}; - -// 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) { - var canvas; - if (id in cache) { - canvas = cache[id]; - canvas.width = width; - canvas.height = height; - // reset canvas transform for emulated mozCurrentTransform, if needed - canvas.getContext('2d').setTransform(1, 0, 0, 1, 0, 0); - } else { - canvas = createScratchCanvas(width, height); - cache[id] = canvas; - } - return canvas; - }, - 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]); - // 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 pos = 3, data = imgData.data, lineSize = width * 4, count = 0; - if (data[3] !== 0) { - points[0] = 1; - ++count; - } - for (j = 1; j < width; j++) { - if (data[pos] !== data[pos + 4]) { - points[j] = data[pos] ? 2 : 1; - ++count; - } - pos += 4; - } - if (data[pos] !== 0) { - points[j] = 2; - ++count; - } - pos += 4; - for (i = 1; i < height; i++) { - 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 + 4] ? 4 : 0) + - (data[pos - lineSize + 4] ? 8 : 0); - if (POINT_TYPES[sum]) { - points[j0 + j] = POINT_TYPES[sum]; - ++count; - } - pos += 4; - } - if (data[pos - lineSize] !== data[pos]) { - points[j0 + j] = data[pos] ? 2 : 4; - ++count; - } - pos += 4; - - if (count > POINT_TO_PROCESS_LIMIT) { - return null; - } - } - - pos -= lineSize; - j0 = i * width1; - if (data[pos] !== 0) { - points[j0] = 8; - ++count; - } - for (j = 1; j < width; j++) { - if (data[pos] !== data[pos + 4]) { - points[j0 + j] = data[pos] ? 4 : 8; - ++count; - } - pos += 4; - } - 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.paintFormXObjectDepth = 0; - - 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 = []; - if (canvasCtx) { - addContextCurrentTransform(canvasCtx); - } - } - - function putBinaryImageData(ctx, imgData) { - if (typeof ImageData !== 'undefined' && imgData instanceof ImageData) { - ctx.putImageData(imgData, 0, 0); - return; - } - - var tmpImgData = ctx.createImageData(imgData.width, imgData.height); - - var data = imgData.data; - var tmpImgDataPixels = tmpImgData.data; - if ('set' in tmpImgDataPixels) - tmpImgDataPixels.set(data); - else { - // Copy over the imageData pixel by pixel. - for (var i = 0, ii = tmpImgDataPixels.length; i < ii; i++) - tmpImgDataPixels[i] = data[i]; - } - - 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; - } - } - - var LINE_CAP_STYLES = ['butt', 'round', 'square']; - var LINE_JOIN_STYLES = ['miter', 'round', 'bevel']; - var NORMAL_CLIP = {}; - var EO_CLIP = {}; - - CanvasGraphics.prototype = { - slowCommands: { - 'stroke': true, - 'closeStroke': true, - 'fill': true, - 'eoFill': true, - 'fillStroke': true, - 'eoFillStroke': true, - 'closeFillStroke': true, - 'closeEOFillStroke': true, - 'showText': true, - 'showSpacedText': true, - 'setStrokeColorSpace': true, - 'setFillColorSpace': true, - 'setStrokeColor': true, - 'setStrokeColorN': true, - 'setFillColor': true, - 'setFillColorN': true, - 'setStrokeGray': true, - 'setFillGray': true, - 'setStrokeRGBColor': true, - 'setFillRGBColor': true, - 'setStrokeCMYKColor': true, - 'setFillCMYKColor': true, - 'paintJpegXObject': true, - 'paintImageXObject': true, - 'paintInlineImageXObject': true, - 'paintInlineImageXObjectGroup': true, - 'paintImageMaskXObject': true, - 'paintImageMaskXObjectGroup': true, - 'shadingFill': true - }, - - 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 fnName; - var slowCommands = this.slowCommands; - - while (true) { - if (stepper && i === stepper.nextBreakPoint) { - stepper.breakIt(i, continueCallback); - return i; - } - - fnName = fnArray[i]; - - if (fnName !== 'dependency') { - this[fnName].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, shedule - // to continue exeution after a short delay. - // However, this is only possible if a 'continueCallback' is passed in. - if (continueCallback && slowCommands[fnName] && Date.now() > endTime) { - setTimeout(continueCallback, 0); - 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; - } - } - }, - save: function CanvasGraphics_save() { - this.ctx.save(); - var old = this.current; - this.stateStack.push(old); - this.current = old.clone(); - }, - restore: function CanvasGraphics_restore() { - var prev = this.stateStack.pop(); - if (prev) { - 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); - 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); - 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; - 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.renderer.getPathGenerator(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 - }); - } - }, - - 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) { - // 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 = Pattern.shadingFromIR(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 = Pattern.shadingFromIR(patternIR); - ctx.fillStyle = pattern.getPattern(ctx); - - 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.current.paintFormXObjectDepth++; - 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() { - var depth = this.current.paintFormXObjectDepth; - do { - this.restore(); - // some pdf don't close all restores inside object - // closing those for them - } while (this.current.paintFormXObjectDepth >= depth); - 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) { - TODO('Support knockout groups.'); - } - - 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); - // 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 scratchCanvas = createScratchCanvas(drawnWidth, drawnHeight); - var groupCtx = scratchCanvas.getContext('2d'); - addContextCurrentTransform(groupCtx); - // 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); - - // Setup the current ctx so when the group is popped we draw it 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([ - ['SMask', 'None'], - ['BM', 'Normal'], - ['ca', 1], - ['CA', 1] - ]); - this.groupStack.push(currentCtx); - }, - - endGroup: function CanvasGraphics_endGroup(group) { - 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; - } - 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.getContext('2d'); - maskCtx.save(); - - putBinaryImageData(maskCtx, img); - - maskCtx.globalCompositeOperation = 'source-in'; - - var fillColor = this.current.fillColor; - maskCtx.fillStyle = (fillColor && fillColor.hasOwnProperty('type') && - fillColor.type === 'Pattern') ? - fillColor.getPattern(maskCtx) : fillColor; - maskCtx.fillRect(0, 0, width, height); - - maskCtx.restore(); - - this.paintInlineImageXObject(maskCanvas); - }, - - 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.getContext('2d'); - maskCtx.save(); - - putBinaryImageData(maskCtx, image); - - maskCtx.globalCompositeOperation = 'source-in'; - - var fillColor = this.current.fillColor; - maskCtx.fillStyle = (fillColor && fillColor.hasOwnProperty('type') && - fillColor.type === 'Pattern') ? - fillColor.getPattern(maskCtx) : fillColor; - maskCtx.fillRect(0, 0, width, height); - - maskCtx.restore(); - - ctx.save(); - ctx.transform.apply(ctx, image.transform); - ctx.scale(1, -1); - ctx.drawImage(maskCanvas, 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; - if (imgData instanceof HTMLElement) { - imgToPaint = imgData; - } else { - var tmpCanvas = CachedCanvases.getCanvas('inlineImage', width, height); - var tmpCtx = tmpCanvas.getContext('2d'); - putBinaryImageData(tmpCtx, imgData); - imgToPaint = tmpCanvas; - } - - 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.getContext('2d'); - tmpCtx.clearRect(0, 0, newWidth, newHeight); - tmpCtx.drawImage(imgToPaint, 0, 0, paintWidth, paintHeight, - 0, 0, newWidth, newHeight); - imgToPaint = tmpCanvas; - 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.getContext('2d'); - 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, 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] - ]; - } - }; - - return CanvasGraphics; -})(); - - - -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 Promise(); - 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 Promise(); - promise.resolve(value); - return promise; - } - value = this.map[key3] || null; - if (xref) { - return xref.fetchIfRefAsync(value); - } - promise = new Promise(); - 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 = {}; - } - - 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; - } - }; - - return RefSetCache; -})(); - -var Catalog = (function CatalogClosure() { - function Catalog(pdfManager, xref) { - this.pdfManager = pdfManager; - this.xref = xref; - this.catDict = xref.getCatalogObj(); - assertWellFormed(isDict(this.catDict), - 'catalog object is not a dictionary'); - - // Stores state as we traverse the pages catalog so that we can resume - // parsing if an exception is thrown - this.traversePagesQueue = [{ - pagesDict: this.toplevelPagesDict, - posInKids: 0 +function MessageHandler(name, comObj) { + this.name = name; + this.comObj = comObj; + this.callbackIndex = 1; + var callbacks = this.callbacks = {}; + var ah = this.actionHandler = {}; + + ah['console_log'] = [function ahConsoleLog(data) { + log.apply(null, data); + }]; + // If there's no console available, console_error in the + // action handler will do nothing. + if ('console' in globalScope) { + ah['console_error'] = [function ahConsoleError(data) { + globalScope['console'].error.apply(null, data); }]; - this.pagePromises = []; - this.currPageIndex = 0; + } else { + ah['console_error'] = [function ahConsoleError(data) { + log.apply(null, data); + }]; + } + ah['_warn'] = [function ah_Warn(data) { + warn(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 promise = new Promise(); + promise.then(function(resolvedData) { + comObj.postMessage({ + isReply: true, + callbackId: data.callbackId, + data: resolvedData + }); + }); + action[0].call(action[1], data.data, promise); + } 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. + */ + send: function messageHandlerSend(actionName, data, callback) { + var message = { + action: actionName, + data: data + }; + if (callback) { + var callbackId = this.callbackIndex++; + this.callbacks[callbackId] = callback; + message.callbackId = callbackId; + } + this.comObj.postMessage(message); + } +}; + +function loadJpegStream(id, imageData, objs) { + var img = new Image(); + img.onload = (function loadJpegStream_onloadClosure() { + objs.resolve(id, img); + }); + img.src = 'data:image/jpeg;base64,' + window.btoa(imageData); +} + + +var ColorSpace = (function ColorSpaceClosure() { + // Constructor should define this.numComps, this.defaultColor, this.name + function ColorSpace() { + error('should not call ColorSpace constructor'); } - 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.'); - } + 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. + */ + getRgbBuffer: function ColorSpace_getRgbBuffer(src, srcOffset, count, + dest, destOffset, bits) { + error('Should not call ColorSpace.getRgbBuffer'); + }, + /** + * Determines amount of the bytes is required to store the reslut of the + * conversion that done by the getRgbBuffer method. + */ + getOutputLength: function ColorSpace_getOutputLength(inputLength) { + 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; + }, + /** + * Creates the output buffer and converts the specified number of the color + * values to the RGB colors, similar to the getRgbBuffer. + */ + createRgbBuffer: function ColorSpace_createRgbBuffer(src, srcOffset, + count, bits) { + if (this.isPassthrough(bits)) { + return src.subarray(srcOffset); + } + var dest = new Uint8Array(count * 3); + var numComponentColors = 1 << bits; + // 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. + if (this.numComps === 1 && count > numComponentColors && + this.name !== 'DeviceGray' && this.name !== 'DeviceRGB') { + // 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 = bits <= 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, bits); - 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; + var destOffset = 0; + for (var i = 0; i < count; ++i) { + var key = src[srcOffset++] * 3; + dest[destOffset++] = colorMap[key]; + dest[destOffset++] = colorMap[key + 1]; + dest[destOffset++] = colorMap[key + 2]; } - warn('Unable to read document outline'); + return dest; } - return shadow(this, 'documentOutline', obj); + this.getRgbBuffer(src, srcOffset, count, dest, 0, bits); + return dest; }, - 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); - } - } - } + /** + * 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 '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; } - return root.items.length > 0 ? root.items : null; + } + + 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': + return 'DeviceGrayCS'; + 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 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 rgb() { + return shadow(this, 'rgb', new DeviceRgbCS()); }, - 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); - }, - - getPage: function Catalog_getPage(pageIndex) { - if (!(pageIndex in this.pagePromises)) { - this.pagePromises[pageIndex] = new Promise(); - } - return this.pagePromises[pageIndex]; - }, - - // Traverses pages in DFS order so that pages are processed in increasing - // order - traversePages: function Catalog_traversePages() { - var queue = this.traversePagesQueue; - while (queue.length) { - var queueItem = queue[queue.length - 1]; - var pagesDict = queueItem.pagesDict; - - var kids = pagesDict.get('Kids'); - assert(isArray(kids), 'page dictionary kids object is not an array'); - if (queueItem.posInKids >= kids.length) { - queue.pop(); - continue; - } - var kidRef = kids[queueItem.posInKids]; - assert(isRef(kidRef), 'page dictionary kid is not a reference'); - - var kid = this.xref.fetch(kidRef); - if (isDict(kid, 'Page') || (isDict(kid) && !kid.has('Kids'))) { - var pageIndex = this.currPageIndex++; - var page = new Page(this.pdfManager, this.xref, pageIndex, kid, - kidRef); - if (!(pageIndex in this.pagePromises)) { - this.pagePromises[pageIndex] = new Promise(); - } - this.pagePromises[pageIndex].resolve(page); - - } else { // must be a child page dictionary - assert( - isDict(kid), - 'page dictionary kid reference points to wrong type of object' - ); - - queue.push({ - pagesDict: kid, - posInKids: 0 - }); - } - ++queueItem.posInKids; - } + get cmyk() { + return shadow(this, 'cmyk', new DeviceCmykCS()); } }; - return Catalog; + return ColorSpace; })(); -var XRef = (function XRefClosure() { - function XRef(stream, password) { - - this.stream = stream; - this.entries = []; - this.xrefstms = {}; - // prepare the XRef cache - this.cache = []; - this.password = password; +/** + * 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; } - 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]; + AlternateCS.prototype = { + getRgb: function AlternateCS_getRgb(src, srcOffset) { + var rgb = new Uint8Array(3); + this.getRgbItem(src, srcOffset, rgb, 0); + return rgb; }, - - 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'); - } + 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) { + 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; + var pos = isPassthrough ? destOffset : 0; + var baseBuf = isPassthrough ? dest : new Uint8Array(baseNumComps * count); + var numComps = this.numComps; - 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 scaled = new Float32Array(numComps); + for (var i = 0; i < count; i++) { + for (var j = 0; j < numComps; j++) { + scaled[j] = src[srcOffset++] * scale; } - - 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; - 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'); - } - - // 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; - } - log('(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); + var tinted = tintFn(scaled); + if (usesZeroToOneRange) { + for (var j = 0; j < baseNumComps; j++) { + baseBuf[pos++] = tinted[j] * 255; } } 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); + base.getRgbItem(tinted, 0, baseBuf, pos); + pos += baseNumComps; } } - // 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]; - } + if (!isPassthrough) { + base.getRgbBuffer(baseBuf, 0, count, dest, destOffset, 8); } - 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 Promise(); - promise.resolve(obj); - return promise; - } - return this.fetchAsync(obj); + getOutputLength: function AlternateCS_getOutputLength(inputLength) { + return this.base.getOutputLength(inputLength * + this.base.numComps / this.numComps); }, - fetchAsync: function XRef_fetchAsync(ref, suppressEncryption) { - var promise = new Promise(); - 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; + isPassthrough: ColorSpace.prototype.isPassthrough, + createRgbBuffer: ColorSpace.prototype.createRgbBuffer, + isDefaultDecode: function AlternateCS_isDefaultDecode(decodeMap) { + return ColorSpace.isDefaultDecode(decodeMap, this.numComps); }, - getCatalogObj: function XRef_getCatalogObj() { - return this.root; - } + usesZeroToOneRange: true }; - return XRef; + return AlternateCS; })(); -/** - * 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; +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; } - NameTree.prototype = { - getAll: function NameTree_getAll() { - var dict = {}; - if (!this.root) { - return dict; + 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) { + var base = this.base; + var numComps = base.numComps; + var outputDelta = base.getOutputLength(numComps); + var lookup = this.lookup; + + for (var i = 0; i < count; ++i) { + var lookupPos = src[srcOffset++] * numComps; + base.getRgbBuffer(lookup, lookupPos, 1, dest, destOffset, 8); + destOffset += outputDelta; } - 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; - } + }, + getOutputLength: function IndexedCS_getOutputLength(inputLength) { + return this.base.getOutputLength(inputLength * this.base.numComps); + }, + isPassthrough: ColorSpace.prototype.isPassthrough, + createRgbBuffer: ColorSpace.prototype.createRgbBuffer, + isDefaultDecode: function IndexedCS_isDefaultDecode(decodeMap) { + // indexed color maps shouldn't be changed + return true; + }, + usesZeroToOneRange: true }; - return NameTree; + return IndexedCS; })(); -/** - * 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. - */ -var PDFObjects = (function PDFObjectsClosure() { - function PDFObjects() { - this.objs = {}; +var DeviceGrayCS = (function DeviceGrayCSClosure() { + function DeviceGrayCS() { + this.name = 'DeviceGray'; + this.numComps = 1; + this.defaultColor = new Float32Array([0]); } - 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 Promise(objId), - data: null, - resolved: false - }; - this.objs[objId] = obj; - - return obj; + DeviceGrayCS.prototype = { + getRgb: function DeviceGrayCS_getRgb(src, srcOffset) { + var rgb = new Uint8Array(3); + this.getRgbItem(src, srcOffset, rgb, 0); + return rgb; }, - - /** - * 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; + 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; }, - - /** - * 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; + getRgbBuffer: function DeviceGrayCS_getRgbBuffer(src, srcOffset, count, + dest, destOffset, bits) { + 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; } }, - - hasData: function PDFObjects_hasData(objId) { - return this.isResolved(objId); + getOutputLength: function DeviceGrayCS_getOutputLength(inputLength) { + return inputLength * 3; }, - - /** - * 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; - } + isPassthrough: ColorSpace.prototype.isPassthrough, + createRgbBuffer: ColorSpace.prototype.createRgbBuffer, + isDefaultDecode: function DeviceGrayCS_isDefaultDecode(decodeMap) { + return ColorSpace.isDefaultDecode(decodeMap, this.numComps); }, - - clear: function PDFObjects_clear() { - this.objs = {}; - } + usesZeroToOneRange: true }; - return PDFObjects; + return DeviceGrayCS; })(); -/** - * 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); +var DeviceRgbCS = (function DeviceRgbCSClosure() { + function DeviceRgbCS() { + this.name = 'DeviceRGB'; + this.numComps = 3; + this.defaultColor = new Float32Array([0, 0, 0]); } - - 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 Promise(); - // 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; + DeviceRgbCS.prototype = { + getRgb: function DeviceRgbCS_getRgb(src, srcOffset) { + var rgb = new Uint8Array(3); + this.getRgbItem(src, srcOffset, rgb, 0); + return rgb; }, - - 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)); + 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) { + var length = count * 3; + if (bits == 8) { + dest.set(src.subarray(srcOffset, srcOffset + length), destOffset); return; } - // Everything is loaded. - this.refSet = null; - this.promise.resolve(); - } + var scale = 255 / ((1 << bits) - 1); + var j = srcOffset, q = destOffset; + for (var i = 0; i < length; ++i) { + dest[q++] = (scale * src[j++]) | 0; + } + }, + getOutputLength: function DeviceRgbCS_getOutputLength(inputLength) { + return inputLength; + }, + isPassthrough: function DeviceRgbCS_isPassthrough(bits) { + return bits == 8; + }, + createRgbBuffer: ColorSpace.prototype.createRgbBuffer, + 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) { + var scale = 1 / ((1 << bits) - 1); + for (var i = 0; i < count; i++) { + convertToRgb(src, srcOffset, scale, dest, destOffset); + srcOffset += 4; + destOffset += 3; + } + }, + getOutputLength: function DeviceCmykCS_getOutputLength(inputLength) { + return (inputLength >> 2) * 3; + }, + isPassthrough: ColorSpace.prototype.isPassthrough, + createRgbBuffer: ColorSpace.prototype.createRgbBuffer, + isDefaultDecode: function DeviceCmykCS_isDefaultDecode(decodeMap) { + return ColorSpace.isDefaultDecode(decodeMap, this.numComps); + }, + usesZeroToOneRange: true }; - return ObjectLoader; + return DeviceCmykCS; +})(); + +// +// 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) { + var maxVal = (1 << bits) - 1; + for (var i = 0; i < count; i++) { + convertToRgb(this, src, srcOffset, maxVal, dest, destOffset); + srcOffset += 3; + destOffset += 3; + } + }, + getOutputLength: function LabCS_getOutputLength(inputLength) { + return inputLength; + }, + 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 PatternType = { + AXIAL: 2, + RADIAL: 3 +}; - -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 - ]; +var Pattern = (function PatternClosure() { + // Constructor should define this.getPattern + function Pattern() { + error('should not call Pattern constructor'); } - 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; - } - - this.appearance = getDefaultAppearance(dict); - } - - 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 Promise(); - 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 Promise(); - - 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('beginAnnotation', [data.rect, transform, matrix]); - evaluator.getOperatorList(this.appearance, resources, opList); - opList.addOp('endAnnotation', []); - promise.resolve(opList); - }.bind(this)); - - return promise; + Pattern.prototype = { + // Input: current Canvas context + // Output: the appropriate fillStyle or strokeStyle + getPattern: function Pattern_getPattern(ctx) { + error('Should not call Pattern.getStyle: ' + ctx); } }; - 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; - } + Pattern.shadingFromIR = function Pattern_shadingFromIR(raw) { + return Shadings[raw[0]].fromIR(raw); }; - // 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 }); + 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: + TODO('Unsupported shading type: ' + type); + return new Shadings.Dummy(); } }; - - 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 { - TODO('unimplemented annotation type: ' + subtype); - } - }; - - Annotation.appendToOperatorList = function Annotation_appendToOperatorList( - annotations, opList, pdfManager, partialEvaluator) { - - function reject(e) { - annotationsReadyPromise.reject(e); - } - - var annotationsReadyPromise = new Promise(); - - 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('beginAnnotations', []); - for (var i = 0, n = datas.length; i < n; ++i) { - var annotOpList = datas[i]; - opList.addOpList(annotOpList); - } - opList.addOp('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') { - TODO('unimplemented annotation type: Widget signature'); - return false; - } - - return parent.isViewable.call(this); - } - }); - - return WidgetAnnotation; + return Pattern; })(); -var TextWidgetAnnotation = (function TextWidgetAnnotationClosure() { - function TextWidgetAnnotation(params) { - WidgetAnnotation.call(this, params); +var Shadings = {}; - if (params.data) { - return; +// 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, ctx) { + this.matrix = matrix; + this.coordsArr = dict.get('Coords'); + this.shadingType = dict.get('ShadingType'); + this.type = 'Pattern'; + this.ctx = ctx; + 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]; } - 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; + var extendStart = false, extendEnd = false; + if (dict.has('Extend')) { + var extendArr = dict.get('Extend'); + extendStart = extendArr[0]; + extendEnd = extendArr[1]; } - 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.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) { - - var promise = new Promise(); - 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; + 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.'); } + } - // Include any font resources found in the default appearance + this.extendStart = extendStart; + this.extendEnd = extendEnd; - var stream = new Stream(stringToBytes(defaultAppearance)); - evaluator.getOperatorList(stream, this.fieldResources, opList); - var appearanceFnArray = opList.fnArray; - var appearanceArgsArray = opList.argsArray; + var fnObj = dict.get('Function'); + var fn; + if (isArray(fnObj)) { 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 fnName = appearanceFnArray[i]; - var args = appearanceArgsArray[i]; - - if (fnName === '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 (fnName === 'setFillRGBColor') { - data.rgb = args; - } else if (fnName === 'setFillGray') { - var rgbValue = args[0] * 255; - data.rgb = [rgbValue, rgbValue, rgbValue]; + 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)); } - promise.resolve(opList); - return promise; + 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); } - }); - return TextWidgetAnnotation; -})(); + // 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 TextAnnotation = (function TextAnnotationClosure() { - function TextAnnotation(params) { - Annotation.call(this, params); + var colorStops = this.colorStops = []; - if (params.data) { + // Protect against bad domains so we don't end up in an infinte loop below. + if (t0 >= t1 || step <= 0) { + // Acrobat doesn't seem to handle these cases so we'll ignore for + // now. + info('Bad shading domain.'); return; } - var dict = params.dict; - var data = this.data; + 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 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 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; } - var ANNOT_MIN_SIZE = 10; + 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 == PatternType.AXIAL) + grad = ctx.createLinearGradient(p0[0], p0[1], p1[0], p1[1]); + else if (type == PatternType.RADIAL) + grad = ctx.createRadialGradient(p0[0], p0[1], r0, p1[0], p1[1], r1); - Util.inherit(TextAnnotation, Annotation, { - - getOperatorList: function TextAnnotation_getOperatorList(evaluator) { - var promise = new Promise(); - 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.width = container.style.width; - 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')); + for (var i = 0, ii = colorStops.length; i < ii; ++i) { + var c = colorStops[i]; + grad.addColorStop(c[0], c[1]); } - text.appendChild(e); - image.addEventListener('mouseover', function annotationImageOver() { - container.style.zIndex += 1; - content.removeAttribute('hidden'); - }, false); + return grad; + } + }; + }; - image.addEventListener('mouseout', function annotationImageOut() { - container.style.zIndex -= 1; - content.setAttribute('hidden', true); - }, false); + RadialAxial.prototype = { + getIR: function RadialAxial_getIR() { + var coordsArr = this.coordsArr; + var type = this.shadingType; + if (type == PatternType.AXIAL) { + var p0 = [coordsArr[0], coordsArr[1]]; + var p1 = [coordsArr[2], coordsArr[3]]; + var r0 = null; + var r1 = null; + } else if (type == PatternType.RADIAL) { + var p0 = [coordsArr[0], coordsArr[1]]; + var p1 = [coordsArr[3], coordsArr[4]]; + var r0 = coordsArr[2]; + var r1 = coordsArr[5]; + } else { + error('getPattern type unknown: ' + type); } - content.appendChild(title); - content.appendChild(text); - container.appendChild(image); - container.appendChild(content); + var matrix = this.matrix; + if (matrix) { + p0 = Util.applyTransform(p0, matrix); + p1 = Util.applyTransform(p1, matrix); + } - return container; + return ['RadialAxial', type, this.colorStops, p0, p1, r0, r1]; } - }); + }; - return TextAnnotation; + return RadialAxial; })(); -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'); - // 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 { - TODO('unrecognized link type: ' + linkType); - } - } else if (dict.has('Dest')) { - // simple destination link - var dest = dict.get('Dest'); - data.dest = isName(dest) ? dest.name : dest; - } +Shadings.Dummy = (function DummyClosure() { + function Dummy() { + this.type = 'Pattern'; } - 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); + Dummy.fromIR = function Dummy_fromIR() { + return { + type: 'Pattern', + getPattern: function Dummy_fromIR_getPattern() { + return 'hotpink'; } - 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; + Dummy.prototype = { + getIR: function Dummy_getIR() { + return ['Dummy']; } - }); - - return LinkAnnotation; + }; + return Dummy; })(); +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.getIR = function TilingPattern_getIR(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 + ]; + }; + + 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; + + TODO('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; +})(); + + var PDFFunction = (function PDFFunctionClosure() { var CONSTRUCT_SAMPLED = 0; @@ -7704,32629 +3148,1702 @@ var PostScriptLexer = (function PostScriptLexerClosure() { -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 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]; -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' -]; + 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 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 ColorSpace = (function ColorSpaceClosure() { - // Constructor should define this.numComps, this.defaultColor, this.name - function ColorSpace() { - error('should not call ColorSpace constructor'); + 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 + ]; } - 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'); + 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; + } + + this.appearance = getDefaultAppearance(dict); + data.hasAppearance = !!this.appearance; + } + + Annotation.prototype = { + + getData: function Annotation_getData() { + return this.data; }, - /** - * 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. - */ - getRgbBuffer: function ColorSpace_getRgbBuffer(src, srcOffset, count, - dest, destOffset, bits) { - error('Should not call ColorSpace.getRgbBuffer'); - }, - /** - * Determines amount of the bytes is required to store the reslut of the - * conversion that done by the getRgbBuffer method. - */ - getOutputLength: function ColorSpace_getOutputLength(inputLength) { - error('Should not call ColorSpace.getOutputLength'); - }, - /** - * Returns true if source data will be equal the result/output data. - */ - isPassthrough: function ColorSpace_isPassthrough(bits) { + + hasHtml: function Annotation_hasHtml() { return false; }, - /** - * Creates the output buffer and converts the specified number of the color - * values to the RGB colors, similar to the getRgbBuffer. - */ - createRgbBuffer: function ColorSpace_createRgbBuffer(src, srcOffset, - count, bits) { - if (this.isPassthrough(bits)) { - return src.subarray(srcOffset); - } - var dest = new Uint8Array(count * 3); - var numComponentColors = 1 << bits; - // 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. - if (this.numComps === 1 && count > numComponentColors && - this.name !== 'DeviceGray' && this.name !== 'DeviceRGB') { - // 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 = bits <= 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, bits); - var destOffset = 0; - for (var i = 0; i < count; ++i) { - var key = src[srcOffset++] * 3; - dest[destOffset++] = colorMap[key]; - dest[destOffset++] = colorMap[key + 1]; - dest[destOffset++] = colorMap[key + 2]; - } - return dest; - } - this.getRgbBuffer(src, srcOffset, count, dest, 0, bits); - return dest; + getHtmlElement: function Annotation_getHtmlElement(commonObjs) { + throw new NotImplementedException( + 'getHtmlElement() should be implemented in subclass'); }, - /** - * 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; + // 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'); - 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 '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': - return 'DeviceGrayCS'; - 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()); + 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; }, - 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) { - 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; - 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); - } - }, - getOutputLength: function AlternateCS_getOutputLength(inputLength) { - return this.base.getOutputLength(inputLength * - this.base.numComps / this.numComps); - }, - isPassthrough: ColorSpace.prototype.isPassthrough, - createRgbBuffer: ColorSpace.prototype.createRgbBuffer, - 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) { - var base = this.base; - var numComps = base.numComps; - var outputDelta = base.getOutputLength(numComps); - var lookup = this.lookup; - - for (var i = 0; i < count; ++i) { - var lookupPos = src[srcOffset++] * numComps; - base.getRgbBuffer(lookup, lookupPos, 1, dest, destOffset, 8); - destOffset += outputDelta; - } - }, - getOutputLength: function IndexedCS_getOutputLength(inputLength) { - return this.base.getOutputLength(inputLength * this.base.numComps); - }, - isPassthrough: ColorSpace.prototype.isPassthrough, - createRgbBuffer: ColorSpace.prototype.createRgbBuffer, - 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) { - 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; - } - }, - getOutputLength: function DeviceGrayCS_getOutputLength(inputLength) { - return inputLength * 3; - }, - isPassthrough: ColorSpace.prototype.isPassthrough, - createRgbBuffer: ColorSpace.prototype.createRgbBuffer, - 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) { - var length = count * 3; - if (bits == 8) { - dest.set(src.subarray(srcOffset, srcOffset + length), destOffset); - return; - } - var scale = 255 / ((1 << bits) - 1); - var j = srcOffset, q = destOffset; - for (var i = 0; i < length; ++i) { - dest[q++] = (scale * src[j++]) | 0; - } - }, - getOutputLength: function DeviceRgbCS_getOutputLength(inputLength) { - return inputLength; - }, - isPassthrough: function DeviceRgbCS_isPassthrough(bits) { - return bits == 8; - }, - createRgbBuffer: ColorSpace.prototype.createRgbBuffer, - 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) { - var scale = 1 / ((1 << bits) - 1); - for (var i = 0; i < count; i++) { - convertToRgb(src, srcOffset, scale, dest, destOffset); - srcOffset += 4; - destOffset += 3; - } - }, - getOutputLength: function DeviceCmykCS_getOutputLength(inputLength) { - return (inputLength >> 2) * 3; - }, - isPassthrough: ColorSpace.prototype.isPassthrough, - createRgbBuffer: ColorSpace.prototype.createRgbBuffer, - isDefaultDecode: function DeviceCmykCS_isDefaultDecode(decodeMap) { - return ColorSpace.isDefaultDecode(decodeMap, this.numComps); - }, - usesZeroToOneRange: true - }; - - return DeviceCmykCS; -})(); - -// -// 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) { - var maxVal = (1 << bits) - 1; - for (var i = 0; i < count; i++) { - convertToRgb(this, src, srcOffset, maxVal, dest, destOffset); - srcOffset += 3; - destOffset += 3; - } - }, - getOutputLength: function LabCS_getOutputLength(inputLength) { - return inputLength; - }, - 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 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); - } + isViewable: function Annotation_isViewable() { + var data = this.data; + return !!( + data && + (!data.annotationFlags || + !(data.annotationFlags & 0x22)) && // Hidden or NoView + data.rect // rectangle is nessessary ); }, - 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 hashData = new Uint8Array(100), 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')); - var userPassword = stringToBytes(dict.get('U')); - 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 PartialEvaluator = (function PartialEvaluatorClosure() { - function PartialEvaluator(pdfManager, xref, handler, pageIndex, - uniquePrefix, idCounters) { - 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 = new RefSetCache(); - } - - // Specifies properties for each command - // - // If variableArgs === true: [0, `numArgs`] expected - // If variableArgs === false: exactly `numArgs` expected - var OP_MAP = { - // Graphic state - w: { fnName: 'setLineWidth', numArgs: 1, variableArgs: false }, - J: { fnName: 'setLineCap', numArgs: 1, variableArgs: false }, - j: { fnName: 'setLineJoin', numArgs: 1, variableArgs: false }, - M: { fnName: 'setMiterLimit', numArgs: 1, variableArgs: false }, - d: { fnName: 'setDash', numArgs: 2, variableArgs: false }, - ri: { fnName: 'setRenderingIntent', numArgs: 1, variableArgs: false }, - i: { fnName: 'setFlatness', numArgs: 1, variableArgs: false }, - gs: { fnName: 'setGState', numArgs: 1, variableArgs: false }, - q: { fnName: 'save', numArgs: 0, variableArgs: false }, - Q: { fnName: 'restore', numArgs: 0, variableArgs: false }, - cm: { fnName: 'transform', numArgs: 6, variableArgs: false }, - - // Path - m: { fnName: 'moveTo', numArgs: 2, variableArgs: false }, - l: { fnName: 'lineTo', numArgs: 2, variableArgs: false }, - c: { fnName: 'curveTo', numArgs: 6, variableArgs: false }, - v: { fnName: 'curveTo2', numArgs: 4, variableArgs: false }, - y: { fnName: 'curveTo3', numArgs: 4, variableArgs: false }, - h: { fnName: 'closePath', numArgs: 0, variableArgs: false }, - re: { fnName: 'rectangle', numArgs: 4, variableArgs: false }, - S: { fnName: 'stroke', numArgs: 0, variableArgs: false }, - s: { fnName: 'closeStroke', numArgs: 0, variableArgs: false }, - f: { fnName: 'fill', numArgs: 0, variableArgs: false }, - F: { fnName: 'fill', numArgs: 0, variableArgs: false }, - 'f*': { fnName: 'eoFill', numArgs: 0, variableArgs: false }, - B: { fnName: 'fillStroke', numArgs: 0, variableArgs: false }, - 'B*': { fnName: 'eoFillStroke', numArgs: 0, variableArgs: false }, - b: { fnName: 'closeFillStroke', numArgs: 0, variableArgs: false }, - 'b*': { fnName: 'closeEOFillStroke', numArgs: 0, variableArgs: false }, - n: { fnName: 'endPath', numArgs: 0, variableArgs: false }, - - // Clipping - W: { fnName: 'clip', numArgs: 0, variableArgs: false }, - 'W*': { fnName: 'eoClip', numArgs: 0, variableArgs: false }, - - // Text - BT: { fnName: 'beginText', numArgs: 0, variableArgs: false }, - ET: { fnName: 'endText', numArgs: 0, variableArgs: false }, - Tc: { fnName: 'setCharSpacing', numArgs: 1, variableArgs: false }, - Tw: { fnName: 'setWordSpacing', numArgs: 1, variableArgs: false }, - Tz: { fnName: 'setHScale', numArgs: 1, variableArgs: false }, - TL: { fnName: 'setLeading', numArgs: 1, variableArgs: false }, - Tf: { fnName: 'setFont', numArgs: 2, variableArgs: false }, - Tr: { fnName: 'setTextRenderingMode', numArgs: 1, variableArgs: false }, - Ts: { fnName: 'setTextRise', numArgs: 1, variableArgs: false }, - Td: { fnName: 'moveText', numArgs: 2, variableArgs: false }, - TD: { fnName: 'setLeadingMoveText', numArgs: 2, variableArgs: false }, - Tm: { fnName: 'setTextMatrix', numArgs: 6, variableArgs: false }, - 'T*': { fnName: 'nextLine', numArgs: 0, variableArgs: false }, - Tj: { fnName: 'showText', numArgs: 1, variableArgs: false }, - TJ: { fnName: 'showSpacedText', numArgs: 1, variableArgs: false }, - '\'': { fnName: 'nextLineShowText', numArgs: 1, variableArgs: false }, - '"': { fnName: 'nextLineSetSpacingShowText', numArgs: 3, - variableArgs: false }, - - // Type3 fonts - d0: { fnName: 'setCharWidth', numArgs: 2, variableArgs: false }, - d1: { fnName: 'setCharWidthAndBounds', numArgs: 6, variableArgs: false }, - - // Color - CS: { fnName: 'setStrokeColorSpace', numArgs: 1, variableArgs: false }, - cs: { fnName: 'setFillColorSpace', numArgs: 1, variableArgs: false }, - SC: { fnName: 'setStrokeColor', numArgs: 4, variableArgs: true }, - SCN: { fnName: 'setStrokeColorN', numArgs: 33, variableArgs: true }, - sc: { fnName: 'setFillColor', numArgs: 4, variableArgs: true }, - scn: { fnName: 'setFillColorN', numArgs: 33, variableArgs: true }, - G: { fnName: 'setStrokeGray', numArgs: 1, variableArgs: false }, - g: { fnName: 'setFillGray', numArgs: 1, variableArgs: false }, - RG: { fnName: 'setStrokeRGBColor', numArgs: 3, variableArgs: false }, - rg: { fnName: 'setFillRGBColor', numArgs: 3, variableArgs: false }, - K: { fnName: 'setStrokeCMYKColor', numArgs: 4, variableArgs: false }, - k: { fnName: 'setFillCMYKColor', numArgs: 4, variableArgs: false }, - - // Shading - sh: { fnName: 'shadingFill', numArgs: 1, variableArgs: false }, - - // Images - BI: { fnName: 'beginInlineImage', numArgs: 0, variableArgs: false }, - ID: { fnName: 'beginImageData', numArgs: 0, variableArgs: false }, - EI: { fnName: 'endInlineImage', numArgs: 1, variableArgs: false }, - - // XObjects - Do: { fnName: 'paintXObject', numArgs: 1, variableArgs: false }, - MP: { fnName: 'markPoint', numArgs: 1, variableArgs: false }, - DP: { fnName: 'markPointProps', numArgs: 2, variableArgs: false }, - BMC: { fnName: 'beginMarkedContent', numArgs: 1, variableArgs: false }, - BDC: { fnName: 'beginMarkedContentProps', numArgs: 2, variableArgs: false }, - EMC: { fnName: 'endMarkedContent', numArgs: 0, variableArgs: false }, - - // Compatibility - BX: { fnName: 'beginCompat', numArgs: 0, variableArgs: false }, - EX: { fnName: '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 - }; - - 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; - } - } + loadResources: function(keys) { + var promise = new Promise(); + this.appearance.dict.getAsync('Resources').then(function(resources) { + if (!resources) { + promise.resolve(); + return; } - // 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; + var objectLoader = new ObjectLoader(resources.map, + keys, + resources.xref); + objectLoader.load().then(function() { + promise.resolve(resources); + }); + }.bind(this)); + + return promise; }, - buildFormXObject: function PartialEvaluator_buildFormXObject(resources, - xobj, smask, - operatorList) { - 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; - // There is also a group colorspace, but since we put everything in - // RGB I'm not sure we need it. - } - operatorList.addOp('beginGroup', [groupOptions]); - } - - operatorList.addOp('paintFormXObjectBegin', [matrix, bbox]); - - this.getOperatorList(xobj, xobj.dict.get('Resources') || resources, - operatorList); - operatorList.addOp('paintFormXObjectEnd', []); - - if (group) { - operatorList.addOp('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('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('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('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]); - }, self.handler, self.xref, resources, image, inline); - - operatorList.addOp('paintImageXObject', args); - }, - - 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, TilingPattern.getIR({ - 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; - }, - - setGState: function PartialEvaluator_setGState(resources, gState, - operatorList) { - - 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': - // We support the default so don't trigger the TODO. - if (!isName(value) || value.name != 'None') - TODO('graphic state operator ' + key); - 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('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(); - } - 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_' + fontRef.num + '_' + fontRef.gen; - - if (!font.translated) { - var translated; - try { - translated = this.translateFont(font, xref); - } catch (e) { - 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) { - - 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(); - // TODO(mduan): pass array of knownCommands rather than OP_MAP - // dictionary - var parser = new Parser(new Lexer(stream, OP_MAP), false, xref); + getOperatorList: function Annotation_getToOperatorList(evaluator) { var promise = new Promise(); - var args = []; - nextOp: - while (true) { - var obj = parser.getObj(); - - if (isEOF(obj)) { - break; - } - - if (isCmd(obj)) { - var cmd = obj.cmd; - - // Check that the command is valid - var opSpec = OP_MAP[cmd]; - if (!opSpec) { - warn('Unknown command "' + cmd + '"'); - continue; - } - - var fn = opSpec.fnName; - - // 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 - - if ((cmd == 'SCN' || cmd == 'scn') && - !args[args.length - 1].code) { - // 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); - } - } - } else if (cmd == 'Do' && !args[0].code) { - // 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); - args = []; - continue; - } else if ('Image' == type.name) { - self.buildPaintImageXObject(resources, xobj, false, - operatorList); - args = []; - continue; - } else { - error('Unhandled XObject subtype ' + type.name); - } - } - } else if (cmd == 'Tf') { // eagerly collect all fonts - var loadedName = self.handleSetFont(resources, args, null, - operatorList); - operatorList.addDependency(loadedName); - fn = 'setFont'; - args[0] = loadedName; - } else if (cmd == 'EI') { - self.buildPaintImageXObject(resources, args[0], true, operatorList); - args = []; - continue; - } else if (cmd === 'q') { // save - var old = this.state; - this.stateStack.push(this.state); - this.state = old.clone(); - } else if (cmd === 'Q') { // restore - var prev = this.stateStack.pop(); - if (prev) { - this.state = prev; - } - } else if (cmd === 'Tj') { // showText - args[0] = this.state.font.translated.charsToGlyphs(args[0]); - } else if (cmd === 'TJ') { // showSpacedText - var arr = args[0]; - var arrLength = arr.length; - for (var i = 0; i < arrLength; ++i) { - if (isString(arr[i])) { - arr[i] = this.state.font.translated.charsToGlyphs(arr[i]); - } - } - } else if (cmd === '\'') { // nextLineShowText - args[0] = this.state.font.translated.charsToGlyphs(args[0]); - } else if (cmd === '"') { // nextLineSetSpacingShowText - args[2] = this.state.font.translated.charsToGlyphs(args[2]); - } - - switch (fn) { - // Parse the ColorSpace data to a raw format. - case 'setFillColorSpace': - case 'setStrokeColorSpace': - args = [ColorSpace.parseToIR(args[0], xref, resources)]; - break; - case '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 = 'shadingFill'; - break; - case '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); - args = []; - continue nextOp; - } // switch - - operatorList.addOp(fn, args); - args = []; - parser.saveState(); - } else if (obj !== null && obj !== undefined) { - args.push(obj instanceof Dict ? obj.getAll() : obj); - assertWellFormed(args.length <= 33, 'Too many arguments'); - } + if (!this.appearance) { + promise.resolve(new OperatorList()); + return promise; } - return operatorList; - }, - - getTextContent: function PartialEvaluator_getTextContent( - stream, resources, state) { - - var bidiTexts; - var SPACE_FACTOR = 0.35; - var MULTI_SPACE_FACTOR = 1.5; - - if (!state) { - bidiTexts = []; - state = { - bidiTexts: bidiTexts - }; - } else { - bidiTexts = state.bidiTexts; - } - - 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 parser = new Parser(new Lexer(stream), false); - var res = resources; - var args = [], obj; - - var chunk = ''; - var font = null; - while (!isEOF(obj = parser.getObj())) { - if (isCmd(obj)) { - var cmd = obj.cmd; - switch (cmd) { - // TODO: Add support for SAVE/RESTORE and XFORM here. - case 'Tf': - font = handleSetFont(args[0].name).translated; - break; - case 'TJ': - 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 'Tj': - chunk += fontCharsToUnicode(args[0], font); - break; - case '\'': - // 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 '"': - // Note comment in "'" - chunk += fontCharsToUnicode(args[2], font); - break; - case 'Do': - // 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; - - state = this.getTextContent( - xobj, - xobj.dict.get('Resources') || resources, - state - ); - break; - case 'gs': - 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 bidiText = PDFJS.bidi(chunk, -1, font.vertical); - bidiTexts.push(bidiText); - - chunk = ''; - } - - args = []; - } else if (obj !== null && obj !== undefined) { - assertWellFormed(args.length <= 33, 'Too many arguments'); - args.push(obj); - } - } // while - - return state; - }, - - 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 also - if (!!(flags & FontFlags.Symbolic)) { - baseEncoding = !properties.file ? Encodings.symbolsEncoding : - 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; - baseEncoding = Encodings[encoding.name]; - } 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 tokens = []; - var token = ''; - var beginArrayToken = {}; - - var cmap = cmapObj.getBytes(cmapObj.length); - for (var i = 0, ii = cmap.length; i < ii; i++) { - var octet = cmap[i]; - if (octet == 0x20 || octet == 0x0D || octet == 0x0A || - octet == 0x3C || octet == 0x5B || octet == 0x5D) { - switch (token) { - case 'usecmap': - error('usecmap is not implemented'); - break; - - case 'beginbfchar': - case 'beginbfrange': - case 'begincidchar': - case 'begincidrange': - token = ''; - tokens = []; - break; - - case 'endcidrange': - case 'endbfrange': - for (var j = 0, jj = tokens.length; j < jj; j += 3) { - var startRange = tokens[j]; - var endRange = tokens[j + 1]; - var code = tokens[j + 2]; - if (code == 0xFFFF) { - // CMap is broken, assuming code == startRange - code = startRange; - } - if (isArray(code)) { - var codeindex = 0; - while (startRange <= endRange) { - charToUnicode[startRange] = code[codeindex++]; - ++startRange; - } - } else { - while (startRange <= endRange) { - charToUnicode[startRange] = code++; - ++startRange; - } - } - } - break; - - case 'endcidchar': - case 'endbfchar': - for (var j = 0, jj = tokens.length; j < jj; j += 2) { - var index = tokens[j]; - var code = tokens[j + 1]; - charToUnicode[index] = code; - } - break; - - case '': - break; - - default: - if (token[0] >= '0' && token[0] <= '9') - token = parseInt(token, 10); // a number - tokens.push(token); - token = ''; - } - switch (octet) { - case 0x5B: - // begin list parsing - tokens.push(beginArrayToken); - break; - case 0x5D: - // collect array items - var items = [], item; - while (tokens.length && - (item = tokens.pop()) != beginArrayToken) - items.unshift(item); - tokens.push(items); - break; - } - } else if (octet == 0x3E) { - if (token.length) { - // Heuristic: guessing chars size by checking numbers sizes - // in the CMap entries. - if (token.length == 2 && properties.composite) - properties.wideChars = false; - - if (token.length <= 4) { - // parsing hex number - tokens.push(parseInt(token, 16)); - token = ''; - } else { - // parsing hex UTF-16BE numbers - var str = []; - for (var k = 0, kk = token.length; k < kk; k += 4) { - var b = parseInt(token.substr(k, 4), 16); - if (b <= 0x10) { - k += 4; - b = (b << 16) | parseInt(token.substr(k, 4), 16); - b -= 0x10000; - str.push(0xD800 | (b >> 10)); - str.push(0xDC00 | (b & 0x3FF)); - break; - } - str.push(b); - } - tokens.push(String.fromCharCode.apply(String, str)); - token = ''; - } - } - } else { - token += String.fromCharCode(octet); - } - } - } - 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, - 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, - 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); - } - } - 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); + 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('beginAnnotation', [data.rect, transform, matrix]); + evaluator.getOperatorList(this.appearance, resources, opList); + opList.addOp('endAnnotation', []); + promise.resolve(opList); + }.bind(this)); + + return promise; } }; - PartialEvaluator.optimizeQueue = - function PartialEvaluator_optimizeQueue(queue) { + Annotation.getConstructor = + function Annotation_getConstructor(subtype, fieldType) { - 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 = fnArray.length; i < ii; i++) { - if (fnArray[i] === 'paintInlineImageXObject' && - fnArray[i - 2] === 'save' && fnArray[i - 1] === 'transform' && - fnArray[i + 1] === '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 - fnArray.splice(j, count * 4, ['paintInlineImageXObjectGroup']); - argsArray.splice(j, count * 4, - [{width: imgWidth, height: imgHeight, data: imgData}, map]); - i = j; - ii = fnArray.length; - } + if (!subtype) { + return; } - // 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 = fnArray.length; i < ii; i++) { - if (fnArray[i] === 'paintImageMaskXObject' && - fnArray[i - 2] === 'save' && fnArray[i - 1] === 'transform' && - fnArray[i + 1] === '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 - fnArray.splice(j, count * 4, ['paintImageMaskXObjectGroup']); - argsArray.splice(j, count * 4, [images]); - i = j; - ii = fnArray.length; - } - } - }; - - return PartialEvaluator; -})(); - - -var OperatorList = (function OperatorListClosure() { - var CHUNK_SIZE = 100; - - function OperatorList(messageHandler, pageIndex) { - this.messageHandler = messageHandler; - this.fnArray = []; - this.argsArray = []; - this.dependencies = {}, - this.pageIndex = pageIndex; - } - - OperatorList.prototype = { - - addOp: function(fn, args) { - this.fnArray.push(fn); - this.argsArray.push(args); - if (this.messageHandler && this.fnArray.length >= CHUNK_SIZE) { - this.flush(); - } - }, - - addDependency: function(dependency) { - if (dependency in this.dependencies) { + // TODO(mack): Implement FreeText annotations + if (subtype === 'Link') { + return LinkAnnotation; + } else if (subtype === 'Text') { + return TextAnnotation; + } else if (subtype === 'Widget') { + if (!fieldType) { return; } - this.dependencies[dependency] = true; - this.addOp('dependency', [dependency]); - }, - addDependencies: function(dependencies) { - for (var key in dependencies) { - this.addDependency(key); - } - }, - - addOpList: function(opList) { - Util.concatenateToArray(this.fnArray, opList.fnArray); - Util.concatenateToArray(this.argsArray, opList.argsArray); - Util.extendObj(this.dependencies, opList.dependencies); - }, - - getIR: function() { - return { - fnArray: this.fnArray, - argsArray: this.argsArray - }; - }, - - flush: function(lastChunk) { - PartialEvaluator.optimizeQueue(this); - this.messageHandler.send('RenderPageChunk', { - operatorList: { - fnArray: this.fnArray, - argsArray: this.argsArray, - lastChunk: lastChunk - }, - pageIndex: this.pageIndex - }); - this.dependencies = []; - this.fnArray = []; - this.argsArray = []; - } - }; - - return OperatorList; -})(); - -var EvalState = (function EvalStateClosure() { - function EvalState() { - this.font = null; - } - EvalState.prototype = { - clone: function CanvasExtraState_clone() { - return Object.create(this); - }, - }; - return EvalState; -})(); - - - -// 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 FONT_IDENTITY_MATRIX = [0.001, 0, 0, 0.001, 0, 0]; - -PDFJS.disableFontFace = 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'], - symbolsEncoding: ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', - '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', - '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, - '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 -}; - -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) { - TODO('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) { - TODO('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 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); - }, - bind: function fontLoaderBind(fonts, callback) { - assert(!isWorker, 'bind() shall be called from main thread'); - - for (var i = 0, ii = fonts.length; i < ii; i++) { - var font = fonts[i]; - if (font.attached) - continue; - - font.attached = true; - font.bindDOM() - } - - setTimeout(callback); - } -}; - -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) { - if (arguments.length === 1) { - // importing translated data - var data = arguments[0]; - for (var i in data) { - this[i] = data[i]; - } - return; - } - - 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.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, '-'); - 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; - 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]); - } + if (fieldType === 'Tx') { + return TextWidgetAnnotation; } else { - var startCode = codes[0]; - - idDeltas += string16((startCode - start) & 0xFFFF); - idRangeOffsets += string16(0); + 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; } - if (trailingRangesCount > 0) { - endCount += '\xFF\xFF'; - startCount += '\xFF\xFF'; - idDeltas += '\x00\x01'; - idRangeOffsets += '\x00\x00'; + var subtype = dict.get('Subtype'); + subtype = isName(subtype) ? subtype.name : ''; + if (!subtype) { + return; } - var format314 = '\x00\x00' + // language - string16(segCount2) + - string16(searchRange) + - string16(searchEntry) + - string16(rangeShift) + - endCount + '\x00\x00' + startCount + - idDeltas + idRangeOffsets + glyphsIds; + var fieldType = Util.getInheritableProperty(dict, 'FT'); + fieldType = isName(fieldType) ? fieldType.name : ''; - 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 + var Constructor = Annotation.getConstructor(subtype, fieldType); + if (!Constructor) { + return; } - 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 params = { + dict: dict, + ref: ref, }; - var ulUnicodeRange1 = 0; - var ulUnicodeRange2 = 0; - var ulUnicodeRange3 = 0; - var ulUnicodeRange4 = 0; + var annotation = new Constructor(params); - 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'); - } - } + if (annotation.isViewable()) { + return annotation; } 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); - } - - 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, rejecting - return 0; - } - 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; - } - } - 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; - // 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); - loca.data = new Uint8Array(locaData.length + itemSize); - loca.data.set(locaData); - itemEncode(loca.data, locaData.length, - 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]; - 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(); - 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) { - var ttContext = { - functionsDefined: [], - functionsUsed: [], - functionsStackDeltas: [], - tooComplexToFollowFunctions: false, - hintsValid: true - }; - if (fpgm) { - sanitizeTTProgram(fpgm, ttContext); - } - if (prep) { - sanitizeTTProgram(prep, ttContext); - } - if (fpgm) { - checkInvalidFunctions(ttContext, maxFunctionDefs); - } - 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 - } - 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) { - font.pos += 14; - maxFunctionDefs = int16(font.getBytes(2)); - } - - var dupFirstEntry = false; - if (properties.type == 'CIDFontType2' && properties.toUnicode && - properties.toUnicode[0] > 0) { - // 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, - maxFunctionDefs); - if (!hintsValid) { - delete tables.fpgm; - delete tables.prep; - } - - // 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.hasEncoding && (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') - 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 ? 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] = 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) { - TODO('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 = []; - } - }, - - bindDOM: function Font_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; - }, - - 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.wideChars) { - // composite fonts have multi-byte strings convert the string from - // single-byte to multi-byte - // XXX assuming CIDFonts are two-byte - later need to extract the - // correct byte encoding according to the PDF spec - var length = chars.length - 1; // looping over two bytes at a time so - // loop should never end on the last byte - for (var i = 0; i < length; i++) { - var charcode = int16([chars.charCodeAt(i++), chars.charCodeAt(i)]); - var glyph = this.charToGlyph(charcode); - glyphs.push(glyph); - // placing null after each word break charcode (ASCII SPACE) - if (charcode == 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); + TODO('unimplemented annotation type: ' + subtype); } }; - return Font; -})(); + Annotation.appendToOperatorList = function Annotation_appendToOperatorList( + annotations, opList, pdfManager, partialEvaluator) { -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}; + function reject(e) { + annotationsReadyPromise.reject(e); } + + var annotationsReadyPromise = new Promise(); + + 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('beginAnnotations', []); + for (var i = 0, n = datas.length; i < n; ++i) { + var annotOpList = datas[i]; + opList.addOpList(annotOpList); + } + opList.addOp('endAnnotations', []); + annotationsReadyPromise.resolve(); + }, reject); + + return annotationsReadyPromise; }; - return ErrorFont; + return Annotation; })(); +PDFJS.Annotation = Annotation; -/* - * 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 = []; - } +var WidgetAnnotation = (function WidgetAnnotationClosure() { - 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; - }, + function WidgetAnnotation(params) { + Annotation.call(this, params); - 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); + 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 { - this.stack = []; + // 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); } - return false; + namedItem = parent; + ref = parentRef; } - }; - - 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); + data.fullName = fieldName.join('.'); } - 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(); - if (token === 'dup') { - 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; - } - } - } - }; - - 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) { - // Get the data block containing glyphs and subrs informations - var headerBlock = new Stream(file.getBytes(properties.length1)); - var headerBlockParser = new Type1Parser(headerBlock); - headerBlockParser.extractFontHeader(properties); - - // Decrypt the data blocks and retrieve it's content - var eexecBlock = new Stream(file.getBytes(properties.length2)); - 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; - // Even though the CFF font may not actually be a CID font is could have - // CID information in the font descriptor. - if (this.properties.cidSystemInfo) { - // According to section 9.7.4.2 if the font is actually a CID font then - // we should use the charset to map CIDs to GIDs. If it is not actually - // a CID font then CIDs can be mapped directly to GIDs. - if (this.cff.isCIDFont) { - inverseEncoding = charsets; - } else { - for (var i = 0, ii = charsets.length; i < charsets.length; i++) { - inverseEncoding.push(i); - } - } - } else { - for (var charcode in encoding) - inverseEncoding[encoding[charcode]] = charcode | 0; - if (charsets[0] === '.notdef') { - gidStart = 1; - } - } - - for (var i = gidStart, ii = charsets.length; i < ii; i++) { - var glyph = charsets[i]; - - var code = inverseEncoding[i]; - if (!code || isSpecialUnicode(code)) { - unassignedUnicodeItems.push(i); - 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) { - var i = unassignedUnicodeItems[j]; - // giving unicode value anyway - while (nextUnusedUnicode in unicodeUsed) - nextUnusedUnicode++; - var unicode = nextUnusedUnicode++; - charstrings.push({ - unicode: unicode, - code: inverseEncoding[i] || 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] = properties.differences.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)) + var parent = Annotation.prototype; + Util.inherit(WidgetAnnotation, Annotation, { + isViewable: function WidgetAnnotation_isViewable() { + if (this.data.fieldType === 'Sig') { + TODO('unimplemented annotation type: Widget signature'); 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 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 Promise(); + 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 fnName = appearanceFnArray[i]; + var args = appearanceArgsArray[i]; + + if (fnName === '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 (fnName === 'setFillRGBColor') { + data.rgb = args; + } else if (fnName === '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 Promise(); + promise.resolve(new OperatorList()); + return promise; + }, + + hasHtml: function TextAnnotation_hasHtml() { return true; }, - setByName: function CFFDict_setByName(name, value) { - if (!(name in this.nameToKeyMap)) { - error('Invalid dictionary name "' + name + '"'); + + 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; } - 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); - } - } + if ((rect[2] - rect[0]) < ANNOT_MIN_SIZE) { + rect[2] = rect[0] + (rect[3] - rect[1]); // make it square } - var compiled = this.compileTopDicts([cff.topDict], - output.length, - cff.isCIDFont); - output.add(compiled.output); - var topDictTracker = compiled.trackers[0]; + var container = this.getEmptyContainer('section', rect); + container.className = 'annotText'; - var stringIndex = this.compileStringIndex(cff.strings.strings); - output.add(stringIndex); + var image = document.createElement('img'); + image.style.width = container.style.width; + 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; - 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]; + if (!item.content && !item.title) { + content.setAttribute('hidden', true); } 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 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')); } - 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); + text.appendChild(e); + image.addEventListener('mouseover', function annotationImageOver() { + container.style.zIndex += 1; + content.removeAttribute('hidden'); + }, false); - 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; + image.addEventListener('mouseout', function annotationImageOut() { + container.style.zIndex -= 1; + content.setAttribute('hidden', true); + }, 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'); + // 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') || ''; } - 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); + // 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 { + TODO('unrecognized link type: ' + linkType); } + } else if (dict.has('Dest')) { + // simple destination link + var dest = dict.get('Dest'); + data.dest = isName(dest) ? dest.name : dest; + } + } + + Util.inherit(LinkAnnotation, Annotation, { + hasOperatorList: function LinkAnnotation_hasOperatorList() { + return false; }, - 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; + hasHtml: function LinkAnnotation_hasHtml() { + return true; + }, - 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]); + 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); } - 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; + element.style.borderColor = Util.makeCssRgb(rgb); + element.style.borderStyle = 'solid'; - // 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 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'; - var data = [(count >> 8) & 0xFF, count & 0xff]; + element.href = this.data.url || ''; + return element; + } + }); - var lastOffset = 1; - for (var i = 0; i < count; ++i) - lastOffset += objects[i].length; + return LinkAnnotation; +})(); - 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); +/** + * 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; - // 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); - } +/** + * 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; - if (objects[i]) - relativeOffset += objects[i].length; - } - var offset = data.length; +/** + * 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|TypedAray|object} source Can be an url to where a PDF is + * located, a typed array (Uint8Array) already populated with data or + * and parameter object with the following possible fields: + * - url - The URL of the PDF. + * - data - A typed array with PDF data. + * - httpHeaders - Basic authentication headers. + * - password - For decrypting password-protected PDFs. + * + * @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 {PDFDocumentProxy} object. + */ +PDFJS.getDocument = function getDocument(source, + pdfDataRangeTransport, + passwordCallback, + progressCallback) { + var workerInitializedPromise, workerReadyPromise, transport; - 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; + 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.Promise(); + workerReadyPromise = new PDFJS.Promise(); + 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. + */ +var PDFDocumentProxy = (function PDFDocumentProxyClosure() { + function PDFDocumentProxy(pdfInfo, transport) { + this.pdfInfo = pdfInfo; + this.transport = transport; + } + 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} The page number to get. The first page is 1. + * @return {Promise} A promise that is resolved with a {PDFPageProxy} + * object. + */ + getPage: function PDFDocumentProxy_getPage(number) { + return this.transport.getPage(number); + }, + /** + * @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_getDestinations() { + var promise = new PDFJS.Promise(); + 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.Promise(); + 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.Promise(); + var info = this.pdfInfo.info; + var metadata = this.pdfInfo.metadata; + promise.resolve({ + info: info, + metadata: metadata ? new PDFJS.Metadata(metadata) : null + }); + return promise; + }, + isEncrypted: function PDFDocumentProxy_isEncrypted() { + var promise = new PDFJS.Promise(); + promise.resolve(this.pdfInfo.encrypted); + 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.Promise(); + 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(); + }, + destroy: function PDFDocumentProxy_destroy() { + this.transport.destroy(); } }; - return CFFCompiler; + return PDFDocumentProxy; })(); -// Workaround for seac on Windows. -(function checkSeacSupport() { - if (/Windows/.test(navigator.userAgent)) { - SEAC_ANALYSIS_ENABLED = true; +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 = { + /** + * @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; -// 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 promise = new PDFJS.Promise(); + 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; -var FontRendererFactory = (function FontRendererFactoryClosure() { - function getLong(data, offset) { - return (data[offset] << 24) | (data[offset + 1] << 16) | - (data[offset + 2] << 8) | data[offset + 3]; - } + // 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 Promise(); + this.operatorList = { + fnArray: [], + argsArray: [], + lastChunk: false + }; - 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) + this.stats.time('Page Request'); + this.transport.messageHandler.send('RenderPageRequest', { + pageIndex: this.pageNumber - 1 }); - 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); + 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); } - startPoint = endPoint + 1; + ); + + 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.reject(error); + } else { + renderTask.resolve(); + } + stats.timeEnd('Rendering'); + stats.timeEnd('Overall'); + } + + return renderTask; + }, + /** + * @return {Promise} That is resolved with the a {string} that is the text + * content from the page. + */ + getTextContent: function PDFPageProxy_getTextContent() { + var promise = new PDFJS.Promise(); + this.transport.messageHandler.send('GetTextContent', { + pageIndex: this.pageNumber - 1 + }, + function textContentCallback(textContent) { + promise.resolve(textContent); + } + ); + return promise; + }, + /** + * Stub for future feature. + */ + getOperationList: function PDFPageProxy_getOperationList() { + var promise = new PDFJS.Promise(); + var operationList = { // not implemented + dependencyFontsID: null, + operatorList: null + }; + promise.resolve(operationList); + 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. + */ + _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. + */ + _startRenderPage: function PDFPageProxy_startRenderPage(transparency) { + this.displayReadyPromise.resolve(transparency); + }, + /** + * For internal use only. + */ + _renderPageChunk: function PDFPageProxy_renderPageChunk(operatorListChunk) { + // Add the new chunk to the current operator list. + Util.concatenateToArray(this.operatorList.fnArray, + operatorListChunk.fnArray); + Util.concatenateToArray(this.operatorList.argsArray, + operatorListChunk.argsArray); + 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. + */ +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 (typeof workerSrc === 'undefined') { + 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(supportTypedArray) { + if (supportTypedArray) { + this.worker = worker; + this.setupMessageHandler(messageHandler); + } else { + globalScope.PDFJS.disableWorker = true; + this.setupFakeWorker(); + } + workerInitializedPromise.resolve(); + }.bind(this)); + + var testObj = new Uint8Array(1); + // Some versions of Opera throw a DATA_CLONE_ERR on + // serializing the typed array. + 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 () { + if (self.worker) { + self.worker.terminate(); + } + }); + }, - function compileCharString(code, js, font) { - var stack = []; - var x = 0, y = 0; - var stems = 0; + loadFakeWorkerFiles: function WorkerTransport_loadFakeWorkerFiles() { + if (!PDFJS.fakeWorkerFilesLoadedPromise) { + PDFJS.fakeWorkerFilesLoadedPromise = new Promise(); + // 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; + }, - 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 + ');'); - } + 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() {} + }; - 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();'); + var messageHandler = new MessageHandler('main', fakeWorker); + this.setupMessageHandler(messageHandler); - 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; - } + // If the main thread is our worker, setup the handling for the messages + // the main thread sends to it self. + PDFJS.WorkerMessageHandler.setup(messageHandler); + }, - 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; - } + setupMessageHandler: + function WorkerTransport_setupMessageHandler(messageHandler) { + this.messageHandler = messageHandler; - 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); + 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: - 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; + error('Got unknown object type ' + type); } - if (stackClean) { - stack.length = 0; + }, this); + + messageHandler.on('DocProgress', function transportDocProgress(data) { + if (this.progressCallback) { + this.progressCallback({ + loaded: data.loaded, + total: data.total + }); } - } - } - parse(code); - } + }, this); - function TrueTypeCompiled(glyphs, cmap, fontMatrix) { - this.glyphs = glyphs; - this.cmap = cmap; - this.fontMatrix = fontMatrix || [0.000488, 0, 0, 0.000488, 0, 0]; + messageHandler.on('DocError', function transportDocError(data) { + this.workerReadyPromise.reject(data); + }, this); - this.compiledGlyphs = []; - } - - var noop = function () {}; - - TrueTypeCompiled.prototype = { - getPathGenerator: 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);'); - - var stack = [], x = 0, y = 0; - compileGlyf(code, js, this); - - js.push('c.restore();'); - - /*jshint -W054 */ - return new Function('c', 'size', js.join('\n')); - } - }; - - function Type2Compiled(cffInfo, cmap, fontMatrix, glyphNameMap) { - this.glyphs = cffInfo.glyphs; - this.gsubrs = cffInfo.gsubrs || []; - this.subrs = cffInfo.subrs || []; - this.cmap = cmap; - this.glyphNameMap = glyphNameMap || GlyphsUnicode; - this.fontMatrix = fontMatrix || [0.001, 0, 0, 0.001, 0, 0]; - - 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; - } - - Type2Compiled.prototype = { - getPathGenerator: 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);'); - - var stack = [], x = 0, y = 0; - compileCharString(code, js, this); - - js.push('c.restore();'); - - /*jshint -W054 */ - return new Function('c', 'size', js.join('\n')); - } - }; - - 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. - TODO('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; + messageHandler.on('PageError', function transportError(data) { + var page = this.pageCache[data.pageNum - 1]; + if (page.displayReadyPromise) + page.displayReadyPromise.reject(data.error); else - error('Bits per component missing in image: ' + this.imageMask); - } - } - this.bpc = bitsPerComponent; + error(data.error); + }, this); - if (!this.imageMask) { - var colorSpace = dict.get('ColorSpace', 'CS'); - if (!colorSpace) { - TODO('JPX images (which don"t require color spaces'); - colorSpace = new Name('DeviceRGB'); - } - this.colorSpace = ColorSpace.parse(colorSpace, xref, res); - this.numComps = this.colorSpace.numComps; - } + messageHandler.on('JpegDecode', function(data, promise) { + var imageData = data[0]; + var components = data[1]; + if (components != 3 && components != 1) + error('Only 3 component or 1 component can be returned'); - 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; - } - } + 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 (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 Promise(); - var smaskPromise = new Promise(); - var maskPromise = new Promise(); - // 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) { - var buffer = new Uint8Array(width * height * 4); - var imgArrayPos = 0; - var i, j, mask, buf; - // removing making non-masked pixels transparent - var bufferPos = 3; // alpha component offset - for (i = 0; i < height; i++) { - mask = 0; - for (j = 0; j < width; j++) { - if (!mask) { - buf = imgArray[imgArrayPos++]; - mask = 128; - } - if (!(buf & mask) !== inverseDecode) { - buffer[bufferPos] = 255; - } - bufferPos += 4; - mask >>= 1; - } - } - return {data: buffer, 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; - }, - getOpacity: function PDFImage_getOpacity(width, height, image) { - var smask = this.smask; - var mask = this.mask; - var originalWidth = this.width; - var originalHeight = this.height; - var buf; - - if (smask) { - var sw = smask.width; - var sh = smask.height; - buf = new Uint8Array(sw * sh); - smask.fillGrayBuffer(buf); - if (sw != width || sh != height) - buf = PDFImage.resize(buf, smask.bpc, 1, sw, sh, width, height); - } else if (mask) { - if (mask instanceof PDFImage) { - var sw = mask.width; - var sh = mask.height; - buf = new Uint8Array(sw * sh); - mask.numComps = 1; - mask.fillGrayBuffer(buf); - - // Need to invert values in buffer - for (var i = 0, ii = sw * sh; i < ii; ++i) - buf[i] = 255 - buf[i]; - - if (sw != width || sh != height) - buf = PDFImage.resize(buf, 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. - buf = 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; - } + 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]; } - buf[i] = opacity; } - } else { - error('Unknown mask format.'); + promise.resolve({ data: buf, width: width, height: height}); + }).bind(this); + var src = 'data:image/jpeg;base64,' + window.btoa(imageData); + img.src = src; + }); + }, + + 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 + }); + }, + + getData: function WorkerTransport_getData(promise) { + this.messageHandler.send('GetData', null, function(data) { + promise.resolve(data); + }); + }, + + dataLoaded: function WorkerTransport_dataLoaded() { + var promise = new PDFJS.Promise(); + this.messageHandler.send('DataLoaded', null, function(args) { + promise.resolve(args); + }); + 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.Promise('Page ' + pageNumber); + this.pagePromises[pageIndex] = promise; + this.messageHandler.send('GetPageRequest', { pageIndex: pageIndex }); + return promise; + }, + + getAnnotations: function WorkerTransport_getAnnotations(pageIndex) { + this.messageHandler.send('GetAnnotationsRequest', + { pageIndex: pageIndex }); + }, + + getDestinations: function WorkerTransport_getDestinations() { + var promise = new PDFJS.Promise(); + this.messageHandler.send('GetDestinations', null, + function transportDestinations(destinations) { + promise.resolve(destinations); } - } else { - buf = new Uint8Array(width * height); - for (var i = 0, ii = width * height; i < ii; ++i) - buf[i] = 255; - } - return buf; - }, - 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); - // Build opacity here since color key masking needs to be perormed on - // undecoded values. - var opacity = this.getOpacity(width, height, comps); - - if (this.needsDecode) { - this.decodeBuffer(comps); - } - var rgbBuf = this.colorSpace.createRgbBuffer(comps, 0, - originalWidth * originalHeight, bpc); - if (originalWidth != width || originalHeight != height) - rgbBuf = PDFImage.resize(rgbBuf, this.bpc, 3, originalWidth, - originalHeight, width, height); - var compsPos = 0; - var opacityPos = 0; - var length = width * actualHeight * 4; - - for (var i = 0; i < length; i += 4) { - buffer[i] = rgbBuf[compsPos++]; - buffer[i + 1] = rgbBuf[compsPos++]; - buffer[i + 2] = rgbBuf[compsPos++]; - buffer[i + 3] = opacity[opacityPos++]; - } - - 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 promise; } }; - return PDFImage; + return WorkerTransport; + })(); -function loadJpegStream(id, imageData, objs) { - var img = new Image(); - img.onload = (function loadJpegStream_onloadClosure() { - objs.resolve(id, img); - }); - img.src = 'data:image/jpeg;base64,' + window.btoa(imageData); -} - - - -// 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(); +/** + * 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. + */ +var PDFObjects = (function PDFObjectsClosure() { + function PDFObjects() { + this.objs = {}; } - Parser.prototype = { - saveState: function Parser_saveState() { - this.state = { - buf1: this.buf1, - buf2: this.buf2, - streamPos: this.lexer.stream.pos + 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 Promise(objId), + data: null, + resolved: false }; - }, + this.objs[objId] = obj; - restoreState: function Parser_restoreState() { - var state = this.state; - this.buf1 = state.buf1; - this.buf2 = state.buf2; - this.lexer.stream.pos = state.streamPos; - }, - - 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)) - error('Bad ' + length + ' attribute in stream'); - - // 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') + /** + * 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; - 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; -})(); + // If there isn't a callback, the user expects to get the resolved data + // directly. + var obj = this.objs[objId]; -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; - } - } + // 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); - 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'); + return obj.data; }, - 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); + + /** + * 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); }, - 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; -})(); + isResolved: function PDFObjects_isResolved(objId) { + var objs = this.objs; - - -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.shadingFromIR = function Pattern_shadingFromIR(raw) { - return Shadings[raw[0]].fromIR(raw); - }; - - 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: - TODO('Unsupported shading type: ' + type); - 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, ctx) { - this.matrix = matrix; - this.coordsArr = dict.get('Coords'); - this.shadingType = dict.get('ShadingType'); - this.type = 'Pattern'; - this.ctx = ctx; - 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.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 == PatternType.AXIAL) - grad = ctx.createLinearGradient(p0[0], p0[1], p1[0], p1[1]); - else if (type == PatternType.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; - } - }; - }; - - RadialAxial.prototype = { - getIR: function RadialAxial_getIR() { - var coordsArr = this.coordsArr; - var type = this.shadingType; - if (type == PatternType.AXIAL) { - var p0 = [coordsArr[0], coordsArr[1]]; - var p1 = [coordsArr[2], coordsArr[3]]; - var r0 = null; - var r1 = null; - } else if (type == PatternType.RADIAL) { - var p0 = [coordsArr[0], coordsArr[1]]; - var p1 = [coordsArr[3], coordsArr[4]]; - var r0 = coordsArr[2]; - var r1 = coordsArr[5]; + if (!objs[objId]) { + return false; } else { - error('getPattern type unknown: ' + type); + return objs[objId].resolved; } + }, - var matrix = this.matrix; - if (matrix) { - p0 = Util.applyTransform(p0, matrix); - p1 = Util.applyTransform(p1, matrix); + 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; } + }, - return ['RadialAxial', type, this.colorStops, p0, p1, r0, r1]; + clear: function PDFObjects_clear() { + this.objs = {}; } }; - - return RadialAxial; + return PDFObjects; })(); - -Shadings.Dummy = (function DummyClosure() { - function Dummy() { - this.type = 'Pattern'; +/* + * RenderTask is basically a promise but adds a cancel function to terminate it. + */ +var RenderTask = (function RenderTaskClosure() { + function RenderTask(internalRenderTask) { + this.internalRenderTask = internalRenderTask; + Promise.call(this); } - Dummy.fromIR = function Dummy_fromIR() { - return { - type: 'Pattern', - getPattern: function Dummy_fromIR_getPattern() { - return 'hotpink'; - } - }; + RenderTask.prototype = Object.create(Promise.prototype); + + /** + * Cancel the rendering task. If the task is curently rendering it will not be + * cancelled until graphics pauses with a timeout. The promise that this + * object extends will resolved when cancelled. + */ + RenderTask.prototype.cancel = function RenderTask_cancel() { + this.internalRenderTask.cancel(); }; - Dummy.prototype = { - getIR: function Dummy_getIR() { - return ['Dummy']; - } - }; - return Dummy; + return RenderTask; })(); -var TilingPattern = (function TilingPatternClosure() { - var PaintType = { - COLORED: 1, - UNCOLORED: 2 - }; +var InternalRenderTask = (function InternalRenderTaskClosure() { - var MAX_PATTERN_SIZE = 8192; - - 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; + function InternalRenderTask(callback, params, objs, commonObjs, operatorList, + pageNumber) { + this.callback = callback; + this.params = params; this.objs = objs; this.commonObjs = commonObjs; - this.baseTransform = baseTransform; - this.type = 'Pattern'; - this.ctx = ctx; + this.operatorListIdx = null; + this.operatorList = operatorList; + this.pageNumber = pageNumber; + this.running = false; + this.graphicsReadyCallback = null; + this.graphicsReady = false; + this.cancelled = false; } - TilingPattern.getIR = function TilingPattern_getIR(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'); + InternalRenderTask.prototype = { - return [ - 'TilingPattern', args, operatorList, matrix, bbox, xstep, ystep, - paintType, tilingType - ]; - }; + initalizeGraphics: + function InternalRenderTask_initalizeGraphics(transparency) { - TilingPattern.prototype = { - createPatternCanvas: function TilinPattern_createPatternCanvas(tmpCanvas) { - 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; - - TODO('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); - - tmpCanvas.width = width; - tmpCanvas.height = height; - - // set the new canvas element context as the graphics context - var tmpCtx = tmpCanvas.getContext('2d'); - var graphics = new CanvasGraphics(tmpCtx, commonObjs, objs); - - 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); - }, - - 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() { - var temporaryPatternCanvas = CachedCanvases.getCanvas('pattern'); - this.createPatternCanvas(temporaryPatternCanvas); - - 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; -})(); - - - -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; - 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; + if (this.cancelled) { 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; + 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(); } - for (var k = 0; k < len; ++k, ++pos) - buffer[pos] = buffer[pos - dist]; - } - }; - return FlateStream; -})(); + var params = this.params; + this.gfx = new CanvasGraphics(params.canvasContext, this.commonObjs, + this.objs, params.textLayer, + params.imageLayer); -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; + this.gfx.beginDrawing(params.viewport, transparency); + this.operatorListIdx = 0; + this.graphicsReady = true; + if (this.graphicsReadyCallback) { + this.graphicsReadyCallback(); } - } 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; - } + }, + + 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); } - } - 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 bytesToString(this.bytes); - }; - /** - * 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'); - 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; -})(); - - -function MessageHandler(name, comObj) { - this.name = name; - this.comObj = comObj; - this.callbackIndex = 1; - var callbacks = this.callbacks = {}; - var ah = this.actionHandler = {}; - - ah['console_log'] = [function ahConsoleLog(data) { - log.apply(null, data); - }]; - // If there's no console available, console_error in the - // action handler will do nothing. - if ('console' in globalScope) { - ah['console_error'] = [function ahConsoleError(data) { - globalScope['console'].error.apply(null, data); - }]; - } else { - ah['console_error'] = [function ahConsoleError(data) { - log.apply(null, data); - }]; - } - ah['_warn'] = [function ah_Warn(data) { - warn(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 promise = new Promise(); - promise.then(function(resolvedData) { - comObj.postMessage({ - isReply: true, - callbackId: data.callbackId, - data: resolvedData - }); - }); - action[0].call(action[1], data.data, promise); - } 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. - */ - send: function messageHandlerSend(actionName, data, callback) { - var message = { - action: actionName, - data: data - }; - if (callback) { - var callbackId = this.callbackIndex++; - this.callbacks[callbackId] = callback; - message.callbackId = callbackId; - } - this.comObj.postMessage(message); - } -}; - -var WorkerMessageHandler = { - setup: function wphSetup(handler) { - var pdfManager; - - function loadDocument(recoveryMode) { - var loadDocumentPromise = new Promise(); - - 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 Promise(); - - 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 - }); - 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; } - // 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 (this.stepper) { + this.stepper.updateOperatorList(this.operatorList); } - if (!responseExists) { - handler.send('test', false); + + if (this.running) { return; } - handler.send('test', true); - }); - - handler.on('GetDocRequest', function wphSetupDoc(data) { - - var onSuccess = function(doc) { - handler.send('GetDoc', { pdfInfo: doc }); - pdfManager.ensureModel('traversePages', []).then(null, onFailure); - }; - - 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; - - 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 Promise(); - 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('GetDestinations', - function wphSetupGetDestinations(data, promise) { - pdfManager.ensureCatalog('destinations').then(function(destinations) { - promise.resolve(destinations); - }); - } - ); - - handler.on('GetData', function wphSetupGetData(data, promise) { - pdfManager.requestLoadedStream(); - pdfManager.onLoadedStream().then(function(stream) { - promise.resolve(stream.bytes); - }); - }); - - handler.on('DataLoaded', function wphSetupDataLoaded(data, promise) { - pdfManager.onLoadedStream().then(function(stream) { - promise.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) { - - log('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, promise) { - pdfManager.getPage(data.pageIndex).then(function(page) { - var pageNum = data.pageIndex + 1; - var start = Date.now(); - page.extractTextContent().then(function(textContent) { - promise.resolve(textContent); - log('text indexing: page=%d - time=%dms', pageNum, - Date.now() - start); - }, function (e) { - // Skip errored pages - promise.reject(e); - }); - }); - }); - - handler.on('Terminate', function wphTerminate(data, promise) { - pdfManager.streamManager.networkManager.abortAllRequests(); - promise.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('Unkown timer name ' + name); - } - this.log('Timer:', name, Date.now() - time); - } -}; - -// Worker thread? -if (typeof window === 'undefined') { - globalScope.console = workerConsole; - - // Add a logger so we can pass warnings on to the main thread, errors will - // throw an exception which will be forwarded on automatically. - PDFJS.LogManager.addLogger({ - warn: function(msg) { - globalScope.postMessage({ - action: '_warn', - 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); + this._continue(); }, - 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; + + _continue: function InternalRenderTask__continue() { + this.running = true; + if (this.cancelled) { + return; } - var position = 0, length = data.length; - while (position < length) { - var headerSize = 8; - var lbox = readUint(data, position, 4); - var tbox = readUint(data, position + 4, 4); - 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.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]; - - // Section F.3.7 extending... using max extension of 4 - var i1 = bufferPadding - 1, j1 = bufferPadding + 1; - var i2 = bufferPadding + width - 2, j2 = bufferPadding + width; - 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--]; - - 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]; - - // Section F.3.7 extending... using max extension of 4 - var i1 = bufferPadding - 1, j1 = bufferPadding + 1; - var i2 = bufferPadding + height - 2, j2 = bufferPadding + height; - 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--]; - - 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; - - if (transposed) - error('JBIG2 error: transposed is not supported'); - - 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); - 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'); - } + if (this.params.continueCallback) { + this.params.continueCallback(this._next.bind(this)); } 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; - 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'); - } + this._next(); } }, - 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); + _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.fnArray.length) { + this.running = false; + if (this.operatorList.lastChunk) { + this.gfx.endDrawing(); + this.callback(); + } + } } + }; - function Jbig2Image() {} - - Jbig2Image.prototype = { - parseChunks: function Jbig2Image_parseChunks(chunks) { - return parseJbig2Chunks(chunks); - } - }; - - return Jbig2Image; + return InternalRenderTask; })(); -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 Metadata = PDFJS.Metadata = (function MetadataClosure() { function fixMetadata(meta) { return meta.replace(/>\\376\\377([^<]+)/g, function(all, codes) { @@ -40404,962 +4921,1935 @@ var Metadata = PDFJS.Metadata = (function MetadataClosure() { return Metadata; })(); -/* -*- 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 +// contexts store most of the state we need natively. +// However, PDF needs a bit more state, which we store here. - 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. -*/ +// Minimal font size that would be used during canvas fillText operations. +var MIN_FONT_SIZE = 16; -// - 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 COMPILE_TYPE3_GLYPHS = true; -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 - ]); +function createScratchCanvas(width, height) { + var canvas = document.createElement('canvas'); + canvas.width = width; + canvas.height = height; + return canvas; +} - 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 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; - function constructor() { + 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); + }; } +} - 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(); +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); } - 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; + cache[id] = canvasEntry = {canvas: canvas, context: ctx}; } + return canvasEntry; + }, + clear: function () { + cache = {}; } - return code[0].children; + }; +})(); + +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]); + // 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 pos = 3, data = imgData.data, lineSize = width * 4, count = 0; + if (data[3] !== 0) { + points[0] = 1; + ++count; } - - 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; + for (j = 1; j < width; j++) { + if (data[pos] !== data[pos + 4]) { + points[j] = data[pos] ? 2 : 1; + ++count; } - 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"; + pos += 4; + } + if (data[pos] !== 0) { + points[j] = 2; + ++count; + } + pos += 4; + for (i = 1; i < height; i++) { + 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 + 4] ? 4 : 0) + + (data[pos - lineSize + 4] ? 8 : 0); + if (POINT_TYPES[sum]) { + points[j0 + j] = POINT_TYPES[sum]; + ++count; } + pos += 4; + } + if (data[pos - lineSize] !== data[pos]) { + points[j0 + j] = data[pos] ? 2 : 4; + ++count; + } + pos += 4; + + if (count > POINT_TO_PROCESS_LIMIT) { return null; } - function receive(length) { - var n = 0; - while (length > 0) { - var bit = readBit(); - if (bit === null) return; - n = (n << 1) | bit; - length--; + } + + pos -= lineSize; + j0 = i * width1; + if (data[pos] !== 0) { + points[j0] = 8; + ++count; + } + for (j = 1; j < width; j++) { + if (data[pos] !== data[pos + 4]) { + points[j0 + j] = data[pos] ? 4 : 8; + ++count; + } + pos += 4; + } + 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]); } - return n; } - function receiveAndExtend(length) { - var n = receive(length); - if (n >= 1 << (length - 1)) - return n; - return n + (-1 << length) + 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.paintFormXObjectDepth = 0; + + 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; } - 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; + }; + 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; + if (canvasCtx) { + addContextCurrentTransform(canvasCtx); + } + } + + function putBinaryImageData(ctx, imgData) { + if (typeof ImageData !== 'undefined' && imgData instanceof ImageData) { + ctx.putImageData(imgData, 0, 0); + return; + } + + var tmpImgData = ctx.createImageData(imgData.width, imgData.height); + + var data = imgData.data; + var tmpImgDataPixels = tmpImgData.data; + if ('set' in tmpImgDataPixels) + tmpImgDataPixels.set(data); + else { + // Copy over the imageData pixel by pixel. + for (var i = 0, ii = tmpImgDataPixels.length; i < ii; i++) + tmpImgDataPixels[i] = data[i]; + } + + 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; + } + } + + var LINE_CAP_STYLES = ['butt', 'round', 'square']; + var LINE_JOIN_STYLES = ['miter', 'round', 'bevel']; + var NORMAL_CLIP = {}; + var EO_CLIP = {}; + + CanvasGraphics.prototype = { + slowCommands: { + 'stroke': true, + 'closeStroke': true, + 'fill': true, + 'eoFill': true, + 'fillStroke': true, + 'eoFillStroke': true, + 'closeFillStroke': true, + 'closeEOFillStroke': true, + 'showText': true, + 'showSpacedText': true, + 'setStrokeColorSpace': true, + 'setFillColorSpace': true, + 'setStrokeColor': true, + 'setStrokeColorN': true, + 'setFillColor': true, + 'setFillColorN': true, + 'setStrokeGray': true, + 'setFillGray': true, + 'setStrokeRGBColor': true, + 'setFillRGBColor': true, + 'setStrokeCMYKColor': true, + 'setFillCMYKColor': true, + 'paintJpegXObject': true, + 'paintImageXObject': true, + 'paintInlineImageXObject': true, + 'paintInlineImageXObjectGroup': true, + 'paintImageMaskXObject': true, + 'paintImageMaskXObjectGroup': true, + 'shadingFill': true + }, + + 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 fnName; + var slowCommands = this.slowCommands; + + while (true) { + if (stepper && i === stepper.nextBreakPoint) { + stepper.breakIt(i, continueCallback); + return i; } - k += r; - var z = dctZigZag[k]; - zz[z] = receiveAndExtend(s); - k++; + + fnName = fnArray[i]; + + if (fnName !== 'dependency') { + this[fnName].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, shedule + // to continue exeution after a short delay. + // However, this is only possible if a 'continueCallback' is passed in. + if (continueCallback && slowCommands[fnName] && Date.now() > endTime) { + setTimeout(continueCallback, 0); + return i; + } + + // If the operatorList isn't executed completely yet OR the execution + // time was short enough, do another execution round. } - } - 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--; + }, + + 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; + } + } + }, + save: function CanvasGraphics_save() { + this.ctx.save(); + var old = this.current; + this.stateStack.push(old); + this.current = old.clone(); + }, + restore: function CanvasGraphics_restore() { + var prev = this.stateStack.pop(); + if (prev) { + 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 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 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); } - } - 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); + ctx.restore(); + ctx.clip(); + ctx.beginPath(); + delete this.pendingTextPaths; }, - parse: function parse(data) { - var offset = 0, length = data.length; - function readUint16() { - var value = (data[offset] << 8) | data[offset + 1]; - offset += 2; - return value; + 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); } - function readDataBlock() { - var length = readUint16(); - var array = data.subarray(offset, offset + length - 2); - offset += array.length; - return array; + + // 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; } - 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; - } + + 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; + 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(); } - 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; - } + if (fillStrokeMode === TextRenderingMode.STROKE || + fillStrokeMode === TextRenderingMode.FILL_STROKE) { + ctx.stroke(); } - 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); + 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); } - 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 + if (isAddToPathSet) { + var paths = this.pendingTextPaths || (this.pendingTextPaths = []); + paths.push({ + transform: ctx.mozCurrentTransform, + x: x, + y: y, + fontSize: fontSize, + addToPath: addToPath }); } }, - 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)]; + 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; - data[offset++] = Y; - } + // 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; } - 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 = component1.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; - } + + 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; } - 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)]; + 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; - 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)); + 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) { + // 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; } + } - data[offset++] = R; - data[offset++] = G; - data[offset++] = B; + 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); } } - 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)]; + x += charWidth; - 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; - } + canvasWidth += charWidth; + + if (restoreNeeded) { + ctx.restore(); } - break; - default: - throw 'Unsupported color mode'; + } + if (vertical) { + current.y -= x * textHScale; + } else { + current.x += x * textHScale; + } + ctx.restore(); } - return data; + + 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; }, - 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++]; + 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; - 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'; + 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 = Pattern.shadingFromIR(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 = Pattern.shadingFromIR(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.current.paintFormXObjectDepth++; + 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() { + var depth = this.current.paintFormXObjectDepth; + do { + this.restore(); + // some pdf don't close all restores inside object + // closing those for them + } while (this.current.paintFormXObjectDepth >= depth); + 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) { + TODO('Support knockout groups.'); + } + + 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); + // 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 scratchCanvas = CachedCanvases.getCanvas( + 'groupAt' + this.groupLevel, 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); + + // Setup the current ctx so when the group is popped we draw it 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([ + ['SMask', 'None'], + ['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; + } + 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(); + + putBinaryImageData(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(); + + putBinaryImageData(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; + if (imgData instanceof HTMLElement) { + 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] + ]; } }; - return constructor; + return CanvasGraphics; +})(); + + + +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); + }, + bind: function fontLoaderBind(fonts, callback) { + assert(!isWorker, 'bind() shall be called from main thread'); + + for (var i = 0, ii = fonts.length; i < ii; i++) { + var font = fonts[i]; + if (font.attached) + continue; + + font.attached = true; + font.bindDOM() + } + + setTimeout(callback); + } +}; + +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); + diff --git a/browser/extensions/pdfjs/content/build/pdf.worker.js b/browser/extensions/pdfjs/content/build/pdf.worker.js new file mode 100644 index 00000000000..c53a54185a2 --- /dev/null +++ b/browser/extensions/pdfjs/content/build/pdf.worker.js @@ -0,0 +1,38469 @@ +/* -*- 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.478'; +PDFJS.build = '8a4a6f4'; + +(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 */ + +'use strict'; + +var globalScope = (typeof window === 'undefined') ? this : window; + +var isWorker = (typeof window == 'undefined'); + +var ERRORS = 0, WARNINGS = 1, INFOS = 5; +var verbosity = WARNINGS; + +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; + + +// Use only for debugging purposes. This should not be used in any code that is +// in mozilla master. +var log = (function() { + if ('console' in globalScope && 'log' in globalScope['console']) { + return globalScope['console']['log'].bind(globalScope['console']); + } else { + return function nop() { + }; + } +})(); + +// A notice for devs that will not trigger the fallback UI. 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 (verbosity >= INFOS) { + log('Info: ' + msg); + PDFJS.LogManager.notify('info', msg); + } +} + +// Non-fatal warnings that should trigger the fallback UI. +function warn(msg) { + if (verbosity >= WARNINGS) { + log('Warning: ' + msg); + PDFJS.LogManager.notify('warn', 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); + log.apply(null, logArguments); + // Join the arguments into a single string for the lines below. + msg = [].join.call(arguments, ' '); + } else { + log('Error: ' + msg); + } + log(backtrace()); + PDFJS.LogManager.notify('error', msg); + throw new Error(msg); +} + +// Missing features that should trigger the fallback UI. +function TODO(what) { + warn('TODO: ' + what); +} + +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); +} + +// 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 (url.indexOf(':') >= 0) + 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; + } + var colon = url.indexOf(':'); + if (colon < 0) { + return allowRelative; + } + var protocol = url.substr(0, colon); + 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); +} + +var LogManager = PDFJS.LogManager = (function LogManagerClosure() { + var loggers = []; + return { + addLogger: function logManager_addLogger(logger) { + loggers.push(logger); + }, + notify: function(type, message) { + for (var i = 0, ii = loggers.length; i < ii; i++) { + var logger = loggers[i]; + if (logger[type]) + logger[type](message); + } + } + }; +})(); + +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'); +} + +/** + * 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 + */ +var Promise = PDFJS.Promise = (function PromiseClosure() { + 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() { + 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); + } + + 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() { + this._status = STATUS_PENDING; + this._handlers = []; + } + /** + * Builds a promise that is resolved when all the passed in promises are + * resolved. + * @param {Promise[]} promises Array of promises to wait for. + * @return {Promise} New dependant promise. + */ + Promise.all = function Promise_all(promises) { + var deferred = new Promise(); + var unresolved = promises.length; + var results = []; + if (unresolved === 0) { + deferred.resolve(results); + return deferred; + } + function reject(reason) { + if (deferred._status === STATUS_REJECTED) { + return; + } + results = []; + deferred.reject(reason); + } + for (var i = 0, ii = promises.length; i < ii; ++i) { + var promise = promises[i]; + promise.then((function(i) { + return function(value) { + if (deferred._status === STATUS_REJECTED) { + return; + } + results[i] = value; + unresolved--; + if (unresolved === 0) + deferred.resolve(results); + }; + })(i), reject); + } + return deferred; + }; + + 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 && + value && typeof(value.then) === 'function') { + 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); + }, + + get isResolved() { + return this._status === STATUS_RESOLVED; + }, + + get isRejected() { + return this._status === STATUS_REJECTED; + }, + + 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(); + this._handlers.push({ + thisPromise: this, + onResolve: onResolve, + onReject: onReject, + nextPromise: nextPromise + }); + HandlerManager.scheduleHandlers(this); + return nextPromise; + } + }; + + return 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 === 'function') + 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); +}; + +function MessageHandler(name, comObj) { + this.name = name; + this.comObj = comObj; + this.callbackIndex = 1; + var callbacks = this.callbacks = {}; + var ah = this.actionHandler = {}; + + ah['console_log'] = [function ahConsoleLog(data) { + log.apply(null, data); + }]; + // If there's no console available, console_error in the + // action handler will do nothing. + if ('console' in globalScope) { + ah['console_error'] = [function ahConsoleError(data) { + globalScope['console'].error.apply(null, data); + }]; + } else { + ah['console_error'] = [function ahConsoleError(data) { + log.apply(null, data); + }]; + } + ah['_warn'] = [function ah_Warn(data) { + warn(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 promise = new Promise(); + promise.then(function(resolvedData) { + comObj.postMessage({ + isReply: true, + callbackId: data.callbackId, + data: resolvedData + }); + }); + action[0].call(action[1], data.data, promise); + } 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. + */ + send: function messageHandlerSend(actionName, data, callback) { + var message = { + action: actionName, + data: data + }; + if (callback) { + var callbackId = this.callbackIndex++; + this.callbacks[callbackId] = callback; + message.callbackId = callbackId; + } + this.comObj.postMessage(message); + } +}; + +function loadJpegStream(id, imageData, objs) { + var img = new Image(); + img.onload = (function loadJpegStream_onloadClosure() { + objs.resolve(id, img); + }); + img.src = 'data:image/jpeg;base64,' + window.btoa(imageData); +} + + +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.shadingFromIR = function Pattern_shadingFromIR(raw) { + return Shadings[raw[0]].fromIR(raw); + }; + + 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: + TODO('Unsupported shading type: ' + type); + 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, ctx) { + this.matrix = matrix; + this.coordsArr = dict.get('Coords'); + this.shadingType = dict.get('ShadingType'); + this.type = 'Pattern'; + this.ctx = ctx; + 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.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 == PatternType.AXIAL) + grad = ctx.createLinearGradient(p0[0], p0[1], p1[0], p1[1]); + else if (type == PatternType.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; + } + }; + }; + + RadialAxial.prototype = { + getIR: function RadialAxial_getIR() { + var coordsArr = this.coordsArr; + var type = this.shadingType; + if (type == PatternType.AXIAL) { + var p0 = [coordsArr[0], coordsArr[1]]; + var p1 = [coordsArr[2], coordsArr[3]]; + var r0 = null; + var r1 = null; + } else if (type == PatternType.RADIAL) { + var p0 = [coordsArr[0], coordsArr[1]]; + var p1 = [coordsArr[3], coordsArr[4]]; + var r0 = coordsArr[2]; + var r1 = coordsArr[5]; + } else { + error('getPattern type unknown: ' + type); + } + + 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.fromIR = function Dummy_fromIR() { + return { + type: 'Pattern', + getPattern: function Dummy_fromIR_getPattern() { + return 'hotpink'; + } + }; + }; + + Dummy.prototype = { + getIR: function Dummy_getIR() { + return ['Dummy']; + } + }; + return Dummy; +})(); + +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.getIR = function TilingPattern_getIR(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 + ]; + }; + + 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; + + TODO('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; +})(); + + + +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 + TODO('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; + } + + 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 Promise(); + 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 Promise(); + + 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('beginAnnotation', [data.rect, transform, matrix]); + evaluator.getOperatorList(this.appearance, resources, opList); + opList.addOp('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 { + TODO('unimplemented annotation type: ' + subtype); + } + }; + + Annotation.appendToOperatorList = function Annotation_appendToOperatorList( + annotations, opList, pdfManager, partialEvaluator) { + + function reject(e) { + annotationsReadyPromise.reject(e); + } + + var annotationsReadyPromise = new Promise(); + + 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('beginAnnotations', []); + for (var i = 0, n = datas.length; i < n; ++i) { + var annotOpList = datas[i]; + opList.addOpList(annotOpList); + } + opList.addOp('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') { + TODO('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 Promise(); + 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 fnName = appearanceFnArray[i]; + var args = appearanceArgsArray[i]; + + if (fnName === '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 (fnName === 'setFillRGBColor') { + data.rgb = args; + } else if (fnName === '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 Promise(); + 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.width = container.style.width; + 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); + image.addEventListener('mouseover', function annotationImageOver() { + container.style.zIndex += 1; + content.removeAttribute('hidden'); + }, false); + + image.addEventListener('mouseout', function annotationImageOut() { + container.style.zIndex -= 1; + content.setAttribute('hidden', true); + }, 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'); + // 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 { + TODO('unrecognized link type: ' + linkType); + } + } else if (dict.has('Dest')) { + // simple destination link + var dest = dict.get('Dest'); + data.dest = isName(dest) ? dest.name : dest; + } + } + + 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 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; + } + + // 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; + } + } + }, + + ensureRange: function ChunkedStream_ensureRange(begin, end) { + if (begin >= end) { + 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 + }); + 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 Promise(); + } + + ChunkedStreamManager.prototype = { + + 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; + var prevChunk; + for (var i = 0; i < chunks.length; ++i) { + var chunk = chunks[i]; + + if (!beginChunk) { + beginChunk = chunk; + } + + if (prevChunk && 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); + }, + + 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(); + } + } + }; + + 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 Promise(); + 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 Promise(); + 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 Promise(); + promise.resolve(); + return promise; + }; + + LocalPdfManager.prototype.requestLoadedStream = + function LocalPdfManager_requestLoadedStream() { + }; + + LocalPdfManager.prototype.onLoadedStream = + function LocalPdfManager_getLoadedStream() { + return this.loadedStream; + }; + + return LocalPdfManager; +})(); + +var NetworkPdfManager = (function NetworkPdfManagerClosure() { + + var CHUNK_SIZE = 65536; + + function NetworkPdfManager(args, msgHandler) { + + this.msgHandler = msgHandler; + + var params = { + msgHandler: msgHandler, + httpHeaders: args.httpHeaders, + chunkedViewerLoading: args.chunkedViewerLoading, + disableAutoFetch: args.disableAutoFetch + }; + 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 Promise(); + 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 Promise(); + 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(); + }; + + return NetworkPdfManager; +})(); + + + +var Page = (function PageClosure() { + + function Page(pdfManager, xref, pageIndex, pageDict, ref) { + this.pdfManager = pdfManager; + this.pageIndex = pageIndex; + this.pageDict = pageDict; + this.xref = xref; + this.ref = ref; + 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 Promise(); + 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 Promise(); + + function reject(e) { + promise.reject(e); + } + + var pageListPromise = new Promise(); + + 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); + + 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) { + PartialEvaluator.optimizeQueue(pageOpList); + pageOpList.flush(true); + promise.resolve(pageOpList); + return; + } + + var annotationsReadyPromise = Annotation.appendToOperatorList( + annotations, pageOpList, pdfManager, partialEvaluator); + annotationsReadyPromise.then(function () { + PartialEvaluator.optimizeQueue(pageOpList); + 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 Promise(); + + 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); + + 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, fileID; + if (xref.trailer.has('ID')) { + fileID = ''; + var id = xref.trailer.get('ID')[0]; + id.split('').forEach(function(el) { + fileID += Number(el.charCodeAt(0)).toString(16); + }); + } else { + // If we got no fileID, then we generate one, + // from the first 100 bytes of PDF + var data = this.stream.bytes.subarray(0, 100); + var hash = calculateMD5(data, 0, data.length); + fileID = ''; + for (var i = 0, length = hash.length; i < length; i++) { + fileID += Number(hash[i]).toString(16); + } + } + + return shadow(this, 'fingerprint', fileID); + }, + + traversePages: function PDFDocument_traversePages() { + this.catalog.traversePages(); + }, + + getPage: function PDFDocument_getPage(pageIndex) { + return this.catalog.getPage(pageIndex); + } + }; + + 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 Promise(); + 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 Promise(); + promise.resolve(value); + return promise; + } + value = this.map[key3] || null; + if (xref) { + return xref.fetchIfRefAsync(value); + } + promise = new Promise(); + 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 = {}; + } + + 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; + } + }; + + return RefSetCache; +})(); + +var Catalog = (function CatalogClosure() { + function Catalog(pdfManager, xref) { + this.pdfManager = pdfManager; + this.xref = xref; + this.catDict = xref.getCatalogObj(); + assertWellFormed(isDict(this.catDict), + 'catalog object is not a dictionary'); + + // Stores state as we traverse the pages catalog so that we can resume + // parsing if an exception is thrown + this.traversePagesQueue = [{ + pagesDict: this.toplevelPagesDict, + posInKids: 0 + }]; + this.pagePromises = []; + this.currPageIndex = 0; + } + + 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); + }, + + getPage: function Catalog_getPage(pageIndex) { + if (!(pageIndex in this.pagePromises)) { + this.pagePromises[pageIndex] = new Promise(); + } + return this.pagePromises[pageIndex]; + }, + + // Traverses pages in DFS order so that pages are processed in increasing + // order + traversePages: function Catalog_traversePages() { + var queue = this.traversePagesQueue; + while (queue.length) { + var queueItem = queue[queue.length - 1]; + var pagesDict = queueItem.pagesDict; + + var kids = pagesDict.get('Kids'); + assert(isArray(kids), 'page dictionary kids object is not an array'); + if (queueItem.posInKids >= kids.length) { + queue.pop(); + continue; + } + var kidRef = kids[queueItem.posInKids]; + assert(isRef(kidRef), 'page dictionary kid is not a reference'); + + var kid = this.xref.fetch(kidRef); + if (isDict(kid, 'Page') || (isDict(kid) && !kid.has('Kids'))) { + var pageIndex = this.currPageIndex++; + var page = new Page(this.pdfManager, this.xref, pageIndex, kid, + kidRef); + if (!(pageIndex in this.pagePromises)) { + this.pagePromises[pageIndex] = new Promise(); + } + this.pagePromises[pageIndex].resolve(page); + + } else { // must be a child page dictionary + assert( + isDict(kid), + 'page dictionary kid reference points to wrong type of object' + ); + + queue.push({ + pagesDict: kid, + posInKids: 0 + }); + } + ++queueItem.posInKids; + } + } + }; + + 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'); + } + + // 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; + } + log('(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 Promise(); + promise.resolve(obj); + return promise; + } + return this.fetchAsync(obj); + }, + fetchAsync: function XRef_fetchAsync(ref, suppressEncryption) { + var promise = new Promise(); + 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 Promise(); + // 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 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. + */ + getRgbBuffer: function ColorSpace_getRgbBuffer(src, srcOffset, count, + dest, destOffset, bits) { + error('Should not call ColorSpace.getRgbBuffer'); + }, + /** + * Determines amount of the bytes is required to store the reslut of the + * conversion that done by the getRgbBuffer method. + */ + getOutputLength: function ColorSpace_getOutputLength(inputLength) { + 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; + }, + /** + * Creates the output buffer and converts the specified number of the color + * values to the RGB colors, similar to the getRgbBuffer. + */ + createRgbBuffer: function ColorSpace_createRgbBuffer(src, srcOffset, + count, bits) { + if (this.isPassthrough(bits)) { + return src.subarray(srcOffset); + } + var dest = new Uint8Array(count * 3); + var numComponentColors = 1 << bits; + // 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. + if (this.numComps === 1 && count > numComponentColors && + this.name !== 'DeviceGray' && this.name !== 'DeviceRGB') { + // 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 = bits <= 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, bits); + + var destOffset = 0; + for (var i = 0; i < count; ++i) { + var key = src[srcOffset++] * 3; + dest[destOffset++] = colorMap[key]; + dest[destOffset++] = colorMap[key + 1]; + dest[destOffset++] = colorMap[key + 2]; + } + return dest; + } + this.getRgbBuffer(src, srcOffset, count, dest, 0, bits); + return dest; + }, + /** + * 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 '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': + return 'DeviceGrayCS'; + 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) { + 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; + 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); + } + }, + getOutputLength: function AlternateCS_getOutputLength(inputLength) { + return this.base.getOutputLength(inputLength * + this.base.numComps / this.numComps); + }, + isPassthrough: ColorSpace.prototype.isPassthrough, + createRgbBuffer: ColorSpace.prototype.createRgbBuffer, + 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) { + var base = this.base; + var numComps = base.numComps; + var outputDelta = base.getOutputLength(numComps); + var lookup = this.lookup; + + for (var i = 0; i < count; ++i) { + var lookupPos = src[srcOffset++] * numComps; + base.getRgbBuffer(lookup, lookupPos, 1, dest, destOffset, 8); + destOffset += outputDelta; + } + }, + getOutputLength: function IndexedCS_getOutputLength(inputLength) { + return this.base.getOutputLength(inputLength * this.base.numComps); + }, + isPassthrough: ColorSpace.prototype.isPassthrough, + createRgbBuffer: ColorSpace.prototype.createRgbBuffer, + 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) { + 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; + } + }, + getOutputLength: function DeviceGrayCS_getOutputLength(inputLength) { + return inputLength * 3; + }, + isPassthrough: ColorSpace.prototype.isPassthrough, + createRgbBuffer: ColorSpace.prototype.createRgbBuffer, + 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) { + var length = count * 3; + if (bits == 8) { + dest.set(src.subarray(srcOffset, srcOffset + length), destOffset); + return; + } + var scale = 255 / ((1 << bits) - 1); + var j = srcOffset, q = destOffset; + for (var i = 0; i < length; ++i) { + dest[q++] = (scale * src[j++]) | 0; + } + }, + getOutputLength: function DeviceRgbCS_getOutputLength(inputLength) { + return inputLength; + }, + isPassthrough: function DeviceRgbCS_isPassthrough(bits) { + return bits == 8; + }, + createRgbBuffer: ColorSpace.prototype.createRgbBuffer, + 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) { + var scale = 1 / ((1 << bits) - 1); + for (var i = 0; i < count; i++) { + convertToRgb(src, srcOffset, scale, dest, destOffset); + srcOffset += 4; + destOffset += 3; + } + }, + getOutputLength: function DeviceCmykCS_getOutputLength(inputLength) { + return (inputLength >> 2) * 3; + }, + isPassthrough: ColorSpace.prototype.isPassthrough, + createRgbBuffer: ColorSpace.prototype.createRgbBuffer, + isDefaultDecode: function DeviceCmykCS_isDefaultDecode(decodeMap) { + return ColorSpace.isDefaultDecode(decodeMap, this.numComps); + }, + usesZeroToOneRange: true + }; + + return DeviceCmykCS; +})(); + +// +// 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) { + var maxVal = (1 << bits) - 1; + for (var i = 0; i < count; i++) { + convertToRgb(this, src, srcOffset, maxVal, dest, destOffset); + srcOffset += 3; + destOffset += 3; + } + }, + getOutputLength: function LabCS_getOutputLength(inputLength) { + return inputLength; + }, + 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 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 hashData = new Uint8Array(100), 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')); + var userPassword = stringToBytes(dict.get('U')); + 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 PartialEvaluator = (function PartialEvaluatorClosure() { + function PartialEvaluator(pdfManager, xref, handler, pageIndex, + uniquePrefix, idCounters) { + 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 = new RefSetCache(); + } + + // Specifies properties for each command + // + // If variableArgs === true: [0, `numArgs`] expected + // If variableArgs === false: exactly `numArgs` expected + var OP_MAP = { + // Graphic state + w: { fnName: 'setLineWidth', numArgs: 1, variableArgs: false }, + J: { fnName: 'setLineCap', numArgs: 1, variableArgs: false }, + j: { fnName: 'setLineJoin', numArgs: 1, variableArgs: false }, + M: { fnName: 'setMiterLimit', numArgs: 1, variableArgs: false }, + d: { fnName: 'setDash', numArgs: 2, variableArgs: false }, + ri: { fnName: 'setRenderingIntent', numArgs: 1, variableArgs: false }, + i: { fnName: 'setFlatness', numArgs: 1, variableArgs: false }, + gs: { fnName: 'setGState', numArgs: 1, variableArgs: false }, + q: { fnName: 'save', numArgs: 0, variableArgs: false }, + Q: { fnName: 'restore', numArgs: 0, variableArgs: false }, + cm: { fnName: 'transform', numArgs: 6, variableArgs: false }, + + // Path + m: { fnName: 'moveTo', numArgs: 2, variableArgs: false }, + l: { fnName: 'lineTo', numArgs: 2, variableArgs: false }, + c: { fnName: 'curveTo', numArgs: 6, variableArgs: false }, + v: { fnName: 'curveTo2', numArgs: 4, variableArgs: false }, + y: { fnName: 'curveTo3', numArgs: 4, variableArgs: false }, + h: { fnName: 'closePath', numArgs: 0, variableArgs: false }, + re: { fnName: 'rectangle', numArgs: 4, variableArgs: false }, + S: { fnName: 'stroke', numArgs: 0, variableArgs: false }, + s: { fnName: 'closeStroke', numArgs: 0, variableArgs: false }, + f: { fnName: 'fill', numArgs: 0, variableArgs: false }, + F: { fnName: 'fill', numArgs: 0, variableArgs: false }, + 'f*': { fnName: 'eoFill', numArgs: 0, variableArgs: false }, + B: { fnName: 'fillStroke', numArgs: 0, variableArgs: false }, + 'B*': { fnName: 'eoFillStroke', numArgs: 0, variableArgs: false }, + b: { fnName: 'closeFillStroke', numArgs: 0, variableArgs: false }, + 'b*': { fnName: 'closeEOFillStroke', numArgs: 0, variableArgs: false }, + n: { fnName: 'endPath', numArgs: 0, variableArgs: false }, + + // Clipping + W: { fnName: 'clip', numArgs: 0, variableArgs: false }, + 'W*': { fnName: 'eoClip', numArgs: 0, variableArgs: false }, + + // Text + BT: { fnName: 'beginText', numArgs: 0, variableArgs: false }, + ET: { fnName: 'endText', numArgs: 0, variableArgs: false }, + Tc: { fnName: 'setCharSpacing', numArgs: 1, variableArgs: false }, + Tw: { fnName: 'setWordSpacing', numArgs: 1, variableArgs: false }, + Tz: { fnName: 'setHScale', numArgs: 1, variableArgs: false }, + TL: { fnName: 'setLeading', numArgs: 1, variableArgs: false }, + Tf: { fnName: 'setFont', numArgs: 2, variableArgs: false }, + Tr: { fnName: 'setTextRenderingMode', numArgs: 1, variableArgs: false }, + Ts: { fnName: 'setTextRise', numArgs: 1, variableArgs: false }, + Td: { fnName: 'moveText', numArgs: 2, variableArgs: false }, + TD: { fnName: 'setLeadingMoveText', numArgs: 2, variableArgs: false }, + Tm: { fnName: 'setTextMatrix', numArgs: 6, variableArgs: false }, + 'T*': { fnName: 'nextLine', numArgs: 0, variableArgs: false }, + Tj: { fnName: 'showText', numArgs: 1, variableArgs: false }, + TJ: { fnName: 'showSpacedText', numArgs: 1, variableArgs: false }, + '\'': { fnName: 'nextLineShowText', numArgs: 1, variableArgs: false }, + '"': { fnName: 'nextLineSetSpacingShowText', numArgs: 3, + variableArgs: false }, + + // Type3 fonts + d0: { fnName: 'setCharWidth', numArgs: 2, variableArgs: false }, + d1: { fnName: 'setCharWidthAndBounds', numArgs: 6, variableArgs: false }, + + // Color + CS: { fnName: 'setStrokeColorSpace', numArgs: 1, variableArgs: false }, + cs: { fnName: 'setFillColorSpace', numArgs: 1, variableArgs: false }, + SC: { fnName: 'setStrokeColor', numArgs: 4, variableArgs: true }, + SCN: { fnName: 'setStrokeColorN', numArgs: 33, variableArgs: true }, + sc: { fnName: 'setFillColor', numArgs: 4, variableArgs: true }, + scn: { fnName: 'setFillColorN', numArgs: 33, variableArgs: true }, + G: { fnName: 'setStrokeGray', numArgs: 1, variableArgs: false }, + g: { fnName: 'setFillGray', numArgs: 1, variableArgs: false }, + RG: { fnName: 'setStrokeRGBColor', numArgs: 3, variableArgs: false }, + rg: { fnName: 'setFillRGBColor', numArgs: 3, variableArgs: false }, + K: { fnName: 'setStrokeCMYKColor', numArgs: 4, variableArgs: false }, + k: { fnName: 'setFillCMYKColor', numArgs: 4, variableArgs: false }, + + // Shading + sh: { fnName: 'shadingFill', numArgs: 1, variableArgs: false }, + + // Images + BI: { fnName: 'beginInlineImage', numArgs: 0, variableArgs: false }, + ID: { fnName: 'beginImageData', numArgs: 0, variableArgs: false }, + EI: { fnName: 'endInlineImage', numArgs: 1, variableArgs: false }, + + // XObjects + Do: { fnName: 'paintXObject', numArgs: 1, variableArgs: false }, + MP: { fnName: 'markPoint', numArgs: 1, variableArgs: false }, + DP: { fnName: 'markPointProps', numArgs: 2, variableArgs: false }, + BMC: { fnName: 'beginMarkedContent', numArgs: 1, variableArgs: false }, + BDC: { fnName: 'beginMarkedContentProps', numArgs: 2, variableArgs: false }, + EMC: { fnName: 'endMarkedContent', numArgs: 0, variableArgs: false }, + + // Compatibility + BX: { fnName: 'beginCompat', numArgs: 0, variableArgs: false }, + EX: { fnName: '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 + }; + + 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) { + 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; + // There is also a group colorspace, but since we put everything in + // RGB I'm not sure we need it. + } + operatorList.addOp('beginGroup', [groupOptions]); + } + + operatorList.addOp('paintFormXObjectBegin', [matrix, bbox]); + + this.getOperatorList(xobj, xobj.dict.get('Resources') || resources, + operatorList); + operatorList.addOp('paintFormXObjectEnd', []); + + if (group) { + operatorList.addOp('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('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('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('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]); + }, self.handler, self.xref, resources, image, inline); + + operatorList.addOp('paintImageXObject', args); + }, + + 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, TilingPattern.getIR({ + 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) { + + 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': + // We support the default so don't trigger the TODO. + if (!isName(value) || value.name != 'None') + TODO('graphic state operator ' + key); + 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('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(); + } + 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_' + fontRef.num + '_' + fontRef.gen; + + if (!font.translated) { + var translated; + try { + translated = this.translateFont(font, xref); + } catch (e) { + 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) { + + 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(); + // TODO(mduan): pass array of knownCommands rather than OP_MAP + // dictionary + var parser = new Parser(new Lexer(stream, OP_MAP), false, xref); + + var promise = new Promise(); + var args = []; + nextOp: + while (true) { + + var obj = parser.getObj(); + + if (isEOF(obj)) { + break; + } + + if (isCmd(obj)) { + var cmd = obj.cmd; + + // Check that the command is valid + var opSpec = OP_MAP[cmd]; + if (!opSpec) { + warn('Unknown command "' + cmd + '"'); + continue; + } + + var fn = opSpec.fnName; + + // 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 + + if ((cmd == 'SCN' || cmd == 'scn') && + !args[args.length - 1].code) { + // 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); + } + } + } else if (cmd == 'Do' && !args[0].code) { + // 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); + args = []; + continue; + } else if ('Image' == type.name) { + self.buildPaintImageXObject(resources, xobj, false, + operatorList); + args = []; + continue; + } else { + error('Unhandled XObject subtype ' + type.name); + } + } + } else if (cmd == 'Tf') { // eagerly collect all fonts + var loadedName = self.handleSetFont(resources, args, null, + operatorList); + operatorList.addDependency(loadedName); + fn = 'setFont'; + args[0] = loadedName; + } else if (cmd == 'EI') { + self.buildPaintImageXObject(resources, args[0], true, operatorList); + args = []; + continue; + } else if (cmd === 'q') { // save + var old = this.state; + this.stateStack.push(this.state); + this.state = old.clone(); + } else if (cmd === 'Q') { // restore + var prev = this.stateStack.pop(); + if (prev) { + this.state = prev; + } + } else if (cmd === 'Tj') { // showText + args[0] = this.handleText(args[0]); + } else if (cmd === 'TJ') { // 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]); + } + } + } else if (cmd === '\'') { // nextLineShowText + args[0] = this.handleText(args[0]); + } else if (cmd === '"') { // nextLineSetSpacingShowText + args[2] = this.handleText(args[2]); + } else if (cmd === 'Tr') { // setTextRenderingMode + this.state.textRenderingMode = args[0]; + } + + switch (fn) { + // Parse the ColorSpace data to a raw format. + case 'setFillColorSpace': + case 'setStrokeColorSpace': + args = [ColorSpace.parseToIR(args[0], xref, resources)]; + break; + case '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 = 'shadingFill'; + break; + case '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); + args = []; + continue nextOp; + } // switch + + operatorList.addOp(fn, args); + args = []; + parser.saveState(); + } else if (obj !== null && obj !== undefined) { + args.push(obj instanceof Dict ? obj.getAll() : obj); + assertWellFormed(args.length <= 33, 'Too many arguments'); + } + } + + return operatorList; + }, + + getTextContent: function PartialEvaluator_getTextContent( + stream, resources, state) { + + var bidiTexts; + var SPACE_FACTOR = 0.35; + var MULTI_SPACE_FACTOR = 1.5; + + if (!state) { + bidiTexts = []; + state = { + bidiTexts: bidiTexts + }; + } else { + bidiTexts = state.bidiTexts; + } + + 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 parser = new Parser(new Lexer(stream), false); + var res = resources; + var args = [], obj; + + var chunk = ''; + var font = null; + while (!isEOF(obj = parser.getObj())) { + if (isCmd(obj)) { + var cmd = obj.cmd; + switch (cmd) { + // TODO: Add support for SAVE/RESTORE and XFORM here. + case 'Tf': + font = handleSetFont(args[0].name).translated; + break; + case 'TJ': + 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 'Tj': + chunk += fontCharsToUnicode(args[0], font); + break; + case '\'': + // 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 '"': + // Note comment in "'" + chunk += fontCharsToUnicode(args[2], font); + break; + case 'Do': + // 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; + + state = this.getTextContent( + xobj, + xobj.dict.get('Resources') || resources, + state + ); + break; + case 'gs': + 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 bidiText = PDFJS.bidi(chunk, -1, font.vertical); + bidiTexts.push(bidiText); + + chunk = ''; + } + + args = []; + } else if (obj !== null && obj !== undefined) { + assertWellFormed(args.length <= 33, 'Too many arguments'); + args.push(obj); + } + } // while + + return state; + }, + + 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 also + if (!!(flags & FontFlags.Symbolic)) { + baseEncoding = !properties.file ? Encodings.symbolsEncoding : + 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; + baseEncoding = Encodings[encoding.name]; + } 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 tokens = []; + var token = ''; + var beginArrayToken = {}; + + var cmap = cmapObj.getBytes(cmapObj.length); + for (var i = 0, ii = cmap.length; i < ii; i++) { + var octet = cmap[i]; + if (octet == 0x20 || octet == 0x0D || octet == 0x0A || + octet == 0x3C || octet == 0x5B || octet == 0x5D) { + switch (token) { + case 'usecmap': + error('usecmap is not implemented'); + break; + + case 'beginbfchar': + case 'beginbfrange': + case 'begincidchar': + case 'begincidrange': + token = ''; + tokens = []; + break; + + case 'endcidrange': + case 'endbfrange': + for (var j = 0, jj = tokens.length; j < jj; j += 3) { + var startRange = tokens[j]; + var endRange = tokens[j + 1]; + var code = tokens[j + 2]; + if (code == 0xFFFF) { + // CMap is broken, assuming code == startRange + code = startRange; + } + if (isArray(code)) { + var codeindex = 0; + while (startRange <= endRange) { + charToUnicode[startRange] = code[codeindex++]; + ++startRange; + } + } else { + while (startRange <= endRange) { + charToUnicode[startRange] = code++; + ++startRange; + } + } + } + break; + + case 'endcidchar': + case 'endbfchar': + for (var j = 0, jj = tokens.length; j < jj; j += 2) { + var index = tokens[j]; + var code = tokens[j + 1]; + charToUnicode[index] = code; + } + break; + + case '': + break; + + default: + if (token[0] >= '0' && token[0] <= '9') + token = parseInt(token, 10); // a number + tokens.push(token); + token = ''; + } + switch (octet) { + case 0x5B: + // begin list parsing + tokens.push(beginArrayToken); + break; + case 0x5D: + // collect array items + var items = [], item; + while (tokens.length && + (item = tokens.pop()) != beginArrayToken) + items.unshift(item); + tokens.push(items); + break; + } + } else if (octet == 0x3E) { + if (token.length) { + // Heuristic: guessing chars size by checking numbers sizes + // in the CMap entries. + if (token.length == 2 && properties.composite) + properties.wideChars = false; + + if (token.length <= 4) { + // parsing hex number + tokens.push(parseInt(token, 16)); + token = ''; + } else { + // parsing hex UTF-16BE numbers + var str = []; + for (var k = 0, kk = token.length; k < kk; k += 4) { + var b = parseInt(token.substr(k, 4), 16); + if (b <= 0x10) { + k += 4; + b = (b << 16) | parseInt(token.substr(k, 4), 16); + b -= 0x10000; + str.push(0xD800 | (b >> 10)); + str.push(0xDC00 | (b & 0x3FF)); + break; + } + str.push(b); + } + tokens.push(String.fromCharCode.apply(String, str)); + token = ''; + } + } + } else { + token += String.fromCharCode(octet); + } + } + } + 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, + 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, + 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); + } + } + 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) { + + 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 = fnArray.length; i < ii; i++) { + if (fnArray[i] === 'paintInlineImageXObject' && + fnArray[i - 2] === 'save' && fnArray[i - 1] === 'transform' && + fnArray[i + 1] === '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 + fnArray.splice(j, count * 4, ['paintInlineImageXObjectGroup']); + argsArray.splice(j, count * 4, + [{width: imgWidth, height: imgHeight, data: imgData}, map]); + i = j; + ii = fnArray.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 = fnArray.length; i < ii; i++) { + if (fnArray[i] === 'paintImageMaskXObject' && + fnArray[i - 2] === 'save' && fnArray[i - 1] === 'transform' && + fnArray[i + 1] === '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 + fnArray.splice(j, count * 4, ['paintImageMaskXObjectGroup']); + argsArray.splice(j, count * 4, [images]); + i = j; + ii = fnArray.length; + } + } + }; + + + return PartialEvaluator; +})(); + + +var OperatorList = (function OperatorListClosure() { + var CHUNK_SIZE = 100; + + function OperatorList(messageHandler, pageIndex) { + this.messageHandler = messageHandler; + this.fnArray = []; + this.argsArray = []; + this.dependencies = {}, + this.pageIndex = pageIndex; + } + + OperatorList.prototype = { + + addOp: function(fn, args) { + this.fnArray.push(fn); + this.argsArray.push(args); + if (this.messageHandler && this.fnArray.length >= CHUNK_SIZE) { + this.flush(); + } + }, + + addDependency: function(dependency) { + if (dependency in this.dependencies) { + return; + } + this.dependencies[dependency] = true; + this.addOp('dependency', [dependency]); + }, + + addDependencies: function(dependencies) { + for (var key in dependencies) { + this.addDependency(key); + } + }, + + addOpList: function(opList) { + Util.concatenateToArray(this.fnArray, opList.fnArray); + Util.concatenateToArray(this.argsArray, opList.argsArray); + Util.extendObj(this.dependencies, opList.dependencies); + }, + + getIR: function() { + return { + fnArray: this.fnArray, + argsArray: this.argsArray + }; + }, + + flush: function(lastChunk) { + PartialEvaluator.optimizeQueue(this); + this.messageHandler.send('RenderPageChunk', { + operatorList: { + fnArray: this.fnArray, + argsArray: this.argsArray, + lastChunk: lastChunk + }, + pageIndex: this.pageIndex + }); + this.dependencies = []; + this.fnArray = []; + this.argsArray = []; + } + }; + + return OperatorList; +})(); + +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; +})(); + + + +// 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'], + symbolsEncoding: ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + '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 +}; + +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) { + TODO('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) { + TODO('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.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, '-'); + 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; + 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); + } + + 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, rejecting + return 0; + } + 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; + } + } + 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; + // 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); + loca.data = new Uint8Array(locaData.length + itemSize); + loca.data.set(locaData); + itemEncode(loca.data, locaData.length, + 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]; + 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(); + 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) { + var ttContext = { + functionsDefined: [], + functionsUsed: [], + functionsStackDeltas: [], + tooComplexToFollowFunctions: false, + hintsValid: true + }; + if (fpgm) { + sanitizeTTProgram(fpgm, ttContext); + } + if (prep) { + sanitizeTTProgram(prep, ttContext); + } + if (fpgm) { + checkInvalidFunctions(ttContext, maxFunctionDefs); + } + 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 + } + 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) { + font.pos += 14; + maxFunctionDefs = int16(font.getBytes(2)); + } + + var dupFirstEntry = false; + if (properties.type == 'CIDFontType2' && properties.toUnicode && + properties.toUnicode[0] > 0) { + // 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, + maxFunctionDefs); + if (!hintsValid) { + delete tables.fpgm; + delete tables.prep; + } + + // 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') + 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 ? 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] = 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) { + TODO('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.wideChars) { + // composite fonts have multi-byte strings convert the string from + // single-byte to multi-byte + // XXX assuming CIDFonts are two-byte - later need to extract the + // correct byte encoding according to the PDF spec + var length = chars.length - 1; // looping over two bytes at a time so + // loop should never end on the last byte + for (var i = 0; i < length; i++) { + var charcode = int16([chars.charCodeAt(i++), chars.charCodeAt(i)]); + var glyph = this.charToGlyph(charcode); + glyphs.push(glyph); + // placing null after each word break charcode (ASCII SPACE) + if (charcode == 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(); + if (token === 'dup') { + 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; + } + } + } + }; + + 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) { + // Get the data block containing glyphs and subrs informations + var headerBlock = new Stream(file.getBytes(properties.length1)); + var headerBlockParser = new Type1Parser(headerBlock); + headerBlockParser.extractFontHeader(properties); + + // Decrypt the data blocks and retrieve it's content + var eexecBlock = new Stream(file.getBytes(properties.length2)); + 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; + // Even though the CFF font may not actually be a CID font is could have + // CID information in the font descriptor. + if (this.properties.cidSystemInfo) { + // According to section 9.7.4.2 if the font is actually a CID font then + // we should use the charset to map CIDs to GIDs. If it is not actually + // a CID font then CIDs can be mapped directly to GIDs. + if (this.cff.isCIDFont) { + inverseEncoding = charsets; + } else { + for (var i = 0, ii = charsets.length; i < charsets.length; i++) { + inverseEncoding.push(i); + } + } + } 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; + } + } + if (charsets[0] === '.notdef') { + gidStart = 1; + } + } + + 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. + TODO('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) { + TODO('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 Promise(); + var smaskPromise = new Promise(); + var maskPromise = new Promise(); + // 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) { + var buffer = new Uint8Array(width * height * 4); + var imgArrayPos = 0; + var i, j, mask, buf; + // removing making non-masked pixels transparent + var bufferPos = 3; // alpha component offset + for (i = 0; i < height; i++) { + mask = 0; + for (j = 0; j < width; j++) { + if (!mask) { + buf = imgArray[imgArrayPos++]; + mask = 128; + } + if (!(buf & mask) !== inverseDecode) { + buffer[bufferPos] = 255; + } + bufferPos += 4; + mask >>= 1; + } + } + return {data: buffer, 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; + }, + getOpacity: function PDFImage_getOpacity(width, height, image) { + var smask = this.smask; + var mask = this.mask; + var originalWidth = this.width; + var originalHeight = this.height; + var buf; + + if (smask) { + var sw = smask.width; + var sh = smask.height; + buf = new Uint8Array(sw * sh); + smask.fillGrayBuffer(buf); + if (sw != width || sh != height) + buf = PDFImage.resize(buf, smask.bpc, 1, sw, sh, width, height); + } else if (mask) { + if (mask instanceof PDFImage) { + var sw = mask.width; + var sh = mask.height; + buf = new Uint8Array(sw * sh); + mask.numComps = 1; + mask.fillGrayBuffer(buf); + + // Need to invert values in buffer + for (var i = 0, ii = sw * sh; i < ii; ++i) + buf[i] = 255 - buf[i]; + + if (sw != width || sh != height) + buf = PDFImage.resize(buf, 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. + buf = 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; + } + } + buf[i] = opacity; + } + } else { + error('Unknown mask format.'); + } + } else { + buf = new Uint8Array(width * height); + for (var i = 0, ii = width * height; i < ii; ++i) + buf[i] = 255; + } + return buf; + }, + 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); + // Build opacity here since color key masking needs to be perormed on + // undecoded values. + var opacity = this.getOpacity(width, height, comps); + + if (this.needsDecode) { + this.decodeBuffer(comps); + } + var rgbBuf = this.colorSpace.createRgbBuffer(comps, 0, + originalWidth * originalHeight, bpc); + if (originalWidth != width || originalHeight != height) + rgbBuf = PDFImage.resize(rgbBuf, this.bpc, 3, originalWidth, + originalHeight, width, height); + var compsPos = 0; + var opacityPos = 0; + var length = width * actualHeight * 4; + + for (var i = 0; i < length; i += 4) { + buffer[i] = rgbBuf[compsPos++]; + buffer[i + 1] = rgbBuf[compsPos++]; + buffer[i + 2] = rgbBuf[compsPos++]; + buffer[i + 3] = opacity[opacityPos++]; + } + + 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 = { + saveState: function Parser_saveState() { + this.state = { + buf1: this.buf1, + buf2: this.buf2, + streamPos: this.lexer.stream.pos + }; + }, + + restoreState: function Parser_restoreState() { + var state = this.state; + this.buf1 = state.buf1; + this.buf2 = state.buf2; + this.lexer.stream.pos = state.streamPos; + }, + + 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; + 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 bytesToString(this.bytes); + }; + /** + * 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'); + 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 Promise(); + + 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 Promise(); + + 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 + }); + 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; + } + // 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', true); + }); + + handler.on('GetDocRequest', function wphSetupDoc(data) { + + var onSuccess = function(doc) { + handler.send('GetDoc', { pdfInfo: doc }); + pdfManager.ensureModel('traversePages', []).then(null, onFailure); + }; + + 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; + + 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 Promise(); + 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('GetDestinations', + function wphSetupGetDestinations(data, promise) { + pdfManager.ensureCatalog('destinations').then(function(destinations) { + promise.resolve(destinations); + }); + } + ); + + handler.on('GetData', function wphSetupGetData(data, promise) { + pdfManager.requestLoadedStream(); + pdfManager.onLoadedStream().then(function(stream) { + promise.resolve(stream.bytes); + }); + }); + + handler.on('DataLoaded', function wphSetupDataLoaded(data, promise) { + pdfManager.onLoadedStream().then(function(stream) { + promise.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) { + + log('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, promise) { + pdfManager.getPage(data.pageIndex).then(function(page) { + var pageNum = data.pageIndex + 1; + var start = Date.now(); + page.extractTextContent().then(function(textContent) { + promise.resolve(textContent); + log('text indexing: page=%d - time=%dms', pageNum, + Date.now() - start); + }, function (e) { + // Skip errored pages + promise.reject(e); + }); + }); + }); + + handler.on('Terminate', function wphTerminate(data, promise) { + pdfManager.streamManager.networkManager.abortAllRequests(); + promise.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('Unkown timer name ' + name); + } + this.log('Timer:', name, Date.now() - time); + } +}; + +// Worker thread? +if (typeof window === 'undefined') { + globalScope.console = workerConsole; + + // Add a logger so we can pass warnings on to the main thread, errors will + // throw an exception which will be forwarded on automatically. + PDFJS.LogManager.addLogger({ + warn: function(msg) { + globalScope.postMessage({ + action: '_warn', + 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.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]; + + // Section F.3.7 extending... using max extension of 4 + var i1 = bufferPadding - 1, j1 = bufferPadding + 1; + var i2 = bufferPadding + width - 2, j2 = bufferPadding + width; + 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--]; + + 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]; + + // Section F.3.7 extending... using max extension of 4 + var i1 = bufferPadding - 1, j1 = bufferPadding + 1; + var i2 = bufferPadding + height - 2, j2 = bufferPadding + height; + 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--]; + + 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; + + if (transposed) + error('JBIG2 error: transposed is not supported'); + + 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); + 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; +})(); + +/* -*- 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); + + + diff --git a/browser/extensions/pdfjs/content/web/debugger.js b/browser/extensions/pdfjs/content/web/debugger.js index ceefd19e137..da57fc3dd56 100644 --- a/browser/extensions/pdfjs/content/web/debugger.js +++ b/browser/extensions/pdfjs/content/web/debugger.js @@ -228,6 +228,25 @@ var Stepper = (function StepperClosure() { return d; } + function glyphsToString(glyphs) { + var out = ''; + for (var i = 0; i < glyphs.length; i++) { + if (glyphs[i] === null) { + out += ' '; + } else { + out += glyphs[i].fontChar; + } + } + return out; + } + + var glyphCommands = { + 'showText': 0, + 'showSpacedText': 0, + 'nextLineShowText': 0, + 'nextLineSetSpacingShowText': 2 + }; + function Stepper(panel, pageIndex, initialBreakPoints) { this.panel = panel; this.breakPoint = 0; @@ -281,8 +300,29 @@ var Stepper = (function StepperClosure() { breakCell.appendChild(cbox); line.appendChild(breakCell); line.appendChild(c('td', i.toString())); - line.appendChild(c('td', operatorList.fnArray[i])); - line.appendChild(c('td', args.join(', '))); + var fn = operatorList.fnArray[i]; + var decArgs = args; + if (fn in glyphCommands) { + var glyphIndex = glyphCommands[fn]; + var glyphs = args[glyphIndex]; + var decArgs = args.slice(); + var newArg; + if (fn === 'showSpacedText') { + newArg = []; + for (var j = 0; j < glyphs.length; j++) { + if (typeof glyphs[j] === 'number') { + newArg.push(glyphs[j]); + } else { + newArg.push(glyphsToString(glyphs[j])); + } + } + } else { + newArg = glyphsToString(glyphs); + } + decArgs[glyphIndex] = newArg; + } + line.appendChild(c('td', fn)); + line.appendChild(c('td', JSON.stringify(decArgs))); } }, getNextBreakPoint: function getNextBreakPoint() { diff --git a/browser/extensions/pdfjs/content/web/viewer.css b/browser/extensions/pdfjs/content/web/viewer.css index 56286eade5f..71aea43708d 100644 --- a/browser/extensions/pdfjs/content/web/viewer.css +++ b/browser/extensions/pdfjs/content/web/viewer.css @@ -982,7 +982,7 @@ html[dir='rtl'] .outlineItem > a { } canvas { - margin: auto; + margin: 0; display: block; } @@ -1105,6 +1105,9 @@ canvas { padding: 3px; font-size: 0.8em; } +.loadingInProgress #errorWrapper { + top: 39px; +} #errorMessageLeft { float: left; diff --git a/browser/extensions/pdfjs/content/web/viewer.js b/browser/extensions/pdfjs/content/web/viewer.js index 126583e4d64..80d1927f555 100644 --- a/browser/extensions/pdfjs/content/web/viewer.js +++ b/browser/extensions/pdfjs/content/web/viewer.js @@ -17,7 +17,7 @@ /* globals PDFJS, PDFBug, FirefoxCom, Stats, Cache, PDFFindBar, CustomStyle, PDFFindController, ProgressBar, TextLayerBuilder, DownloadManager, getFileName, getOutputScale, scrollIntoView, getPDFFileNameFromURL, - PDFHistory, noContextMenuHandler */ + PDFHistory, ThumbnailView, noContextMenuHandler */ 'use strict'; @@ -48,7 +48,7 @@ var FindStates = { }; PDFJS.imageResourcesPath = './images/'; - PDFJS.workerSrc = '../build/pdf.js'; + PDFJS.workerSrc = '../build/pdf.worker.js'; var mozL10n = document.mozL10n || document.webL10n; @@ -662,6 +662,12 @@ var PDFFindController = { } }, + reset: function pdfFindControllerReset() { + this.startedTextExtraction = false; + this.extractTextPromises = []; + this.active = false; + }, + calcFindMatch: function(pageIndex) { var pageContent = this.pageContents[pageIndex]; var query = this.state.query; @@ -969,7 +975,7 @@ var PDFHistory = { // is opened in the web viewer. this.reInitialized = true; } - window.history.replaceState({ fingerprint: this.fingerprint }, '', ''); + window.history.replaceState({ fingerprint: this.fingerprint }, ''); } var self = this; @@ -1174,9 +1180,9 @@ var PDFHistory = { } } if (overwrite || this.uid === 0) { - window.history.replaceState(this._stateObj(params), '', ''); + window.history.replaceState(this._stateObj(params), ''); } else { - window.history.pushState(this._stateObj(params), '', ''); + window.history.pushState(this._stateObj(params), ''); } this.currentUid = this.uid++; this.current = params; @@ -1248,8 +1254,6 @@ var PDFView = { currentScale: UNKNOWN_SCALE, currentScaleValue: null, initialBookmark: document.location.hash.substring(1), - startedTextExtraction: false, - pageText: [], container: null, thumbnailContainer: null, initialized: false, @@ -1839,6 +1843,8 @@ var PDFView = { }; } + PDFFindController.reset(); + this.pdfDocument = pdfDocument; var errorWrapper = document.getElementById('errorWrapper'); @@ -1876,8 +1882,6 @@ var PDFView = { this.pageRotation = 0; var pages = this.pages = []; - this.pageText = []; - this.startedTextExtraction = false; var pagesRefMap = this.pagesRefMap = {}; var thumbnails = this.thumbnails = []; @@ -2030,6 +2034,32 @@ var PDFView = { console.warn('Warning: AcroForm/XFA is not supported'); PDFView.fallback(); } + + var versionId = String(info.PDFFormatVersion).slice(-1) | 0; + var generatorId = 0; + var KNOWN_GENERATORS = ["acrobat distiller", "acrobat pdfwritter", + "adobe livecycle", "adobe pdf library", "adobe photoshop", "ghostscript", + "tcpdf", "cairo", "dvipdfm", "dvips", "pdftex", "pdfkit", "itext", + "prince", "quarkxpress", "mac os x", "microsoft", "openoffice", "oracle", + "luradocument", "pdf-xchange", "antenna house", "aspose.cells", "fpdf"]; + var generatorId = 0; + if (info.Producer) { + KNOWN_GENERATORS.some(function (generator, s, i) { + if (generator.indexOf(s) < 0) { + return false; + } + generatorId = i + 1; + return true; + }.bind(null, info.Producer.toLowerCase())); + } + var formType = !info.IsAcroFormPresent ? null : info.IsXFAPresent ? + 'xfa' : 'acroform'; + FirefoxCom.request('reportTelemetry', JSON.stringify({ + type: 'documentInfo', + version: versionId, + generator: generatorId, + formType: formType + })); }); }, @@ -2624,6 +2654,52 @@ var PageView = function pageView(container, id, scale, link.className = 'internalLink'; } + function bindNamedAction(link, action) { + link.onclick = function pageViewSetupNamedActionOnClick() { + // See PDF reference, table 8.45 - Named action + switch (action) { + case 'GoToPage': + document.getElementById('pageNumber').focus(); + break; + + case 'GoBack': + PDFHistory.back(); + break; + + case 'GoForward': + PDFHistory.forward(); + break; + + case 'Find': + if (!PDFView.supportsIntegratedFind) { + PDFFindBar.toggle(); + } + break; + + case 'NextPage': + PDFView.page++; + break; + + case 'PrevPage': + PDFView.page--; + break; + + case 'LastPage': + PDFView.page = PDFView.pages.length; + break; + + case 'FirstPage': + PDFView.page = 1; + break; + + default: + break; // No action according to spec + } + return false; + }; + link.className = 'internalLink'; + } + pdfPage.getAnnotations().then(function(annotationsData) { viewport = viewport.clone({ dontFlip: true }); for (var i = 0; i < annotationsData.length; i++) { @@ -2656,7 +2732,11 @@ var PageView = function pageView(container, id, scale, CustomStyle.setProp('transformOrigin', element, transformOriginStr); if (data.subtype === 'Link' && !data.url) { - bindLink(element, ('dest' in data) ? data.dest : null); + if (data.action) { + bindNamedAction(element, data.action); + } else { + bindLink(element, ('dest' in data) ? data.dest : null); + } } annotationsDiv.appendChild(element); @@ -2884,6 +2964,10 @@ var PageView = function pageView(container, id, scale, }); div.dispatchEvent(event); + FirefoxCom.request('reportTelemetry', JSON.stringify({ + type: 'pageInfo' + })); + // TODO add stream types report here callback(); } @@ -2990,6 +3074,7 @@ var PageView = function pageView(container, id, scale, }; }; + var ThumbnailView = function thumbnailView(container, id, defaultViewport) { var anchor = document.createElement('a'); anchor.href = PDFView.getAnchorUrl('#page=' + id); @@ -2999,7 +3084,6 @@ var ThumbnailView = function thumbnailView(container, id, defaultViewport) { return false; }; - this.pdfPage = undefined; this.viewport = defaultViewport; this.pdfPageRotate = defaultViewport.rotate; @@ -3574,6 +3658,7 @@ document.addEventListener('DOMContentLoaded', function webViewerLoad(evt) { var file = window.location.href.split('#')[0]; + document.getElementById('openFile').setAttribute('hidden', 'true'); // Special debugging flags in the hash section of the URL. @@ -4034,8 +4119,12 @@ window.addEventListener('keydown', function keydown(evt) { break; case 48: // '0' case 96: // '0' on Numpad of Swedish keyboard - PDFView.parseScale(DEFAULT_SCALE, true); - handled = false; // keeping it unhandled (to restore page zoom to 100%) + // keeping it unhandled (to restore page zoom to 100%) + setTimeout(function () { + // ... and resetting the scale after browser adjusts its scale + PDFView.parseScale(DEFAULT_SCALE, true); + }); + handled = false; break; } } diff --git a/browser/extensions/pdfjs/extension-files b/browser/extensions/pdfjs/extension-files index 1d44e55ae3d..40ccb871322 100644 --- a/browser/extensions/pdfjs/extension-files +++ b/browser/extensions/pdfjs/extension-files @@ -2,8 +2,10 @@ chrome.manifest components/PdfRedirector.js components/PdfStreamConverter.js content/build/pdf.js +content/build/pdf.worker.js content/network.js content/PdfJs.jsm +content/PdfJsTelemetry.jsm content/web/debugger.js content/web/images/annotation-check.svg content/web/images/annotation-comment.svg From 95dc91cfd369661c19d4770181dd19fdea6d8a51 Mon Sep 17 00:00:00 2001 From: Mihnea Dobrescu-Balaur Date: Sun, 1 Sep 2013 13:02:51 -0700 Subject: [PATCH 51/64] Bug 911249 - Don't block XPCShell test harness on hangs caused by os.kill on Windows. r=ted --- testing/xpcshell/runxpcshelltests.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/testing/xpcshell/runxpcshelltests.py b/testing/xpcshell/runxpcshelltests.py index 3f4b68693ff..d58ff34b450 100644 --- a/testing/xpcshell/runxpcshelltests.py +++ b/testing/xpcshell/runxpcshelltests.py @@ -135,6 +135,7 @@ class XPCShellTestThread(Thread): # event from main thread to signal work done self.event = event + self.done = False # explicitly set flag so we don't rely on thread.isAlive def run(self): try: @@ -148,6 +149,7 @@ class XPCShellTestThread(Thread): if self.retry: self.log.info("TEST-INFO | %s | Test failed or timed out, will retry." % self.test_object['name']) + self.done = True self.event.set() def kill(self, proc): @@ -218,6 +220,7 @@ class XPCShellTestThread(Thread): def testTimeout(self, test_file, processPID): if not self.retry: self.log.error("TEST-UNEXPECTED-FAIL | %s | Test timed out" % test_file) + self.done = True Automation().killAndGetStackNoScreenshot(processPID, self.appPath, self.debuggerInfo) def buildCmdTestFile(self, name): @@ -1347,7 +1350,7 @@ class XPCShellTests(object): # find what tests are done (might be more than 1) done_tests = set() for test in running_tests: - if not test.is_alive(): + if test.done: done_tests.add(test) test.join() # if the test had trouble, we will try running it again From 60440e2aa6ce66bfd0aa06935442f4df4ac6b399 Mon Sep 17 00:00:00 2001 From: Mihnea Dobrescu-Balaur Date: Tue, 3 Sep 2013 10:00:11 -0700 Subject: [PATCH 52/64] Bug 911347 - Fix xpcshell static file cleanup on Windows. r=ted --- testing/xpcshell/runxpcshelltests.py | 27 +++------------------------ 1 file changed, 3 insertions(+), 24 deletions(-) diff --git a/testing/xpcshell/runxpcshelltests.py b/testing/xpcshell/runxpcshelltests.py index d58ff34b450..539c3a4ce6a 100644 --- a/testing/xpcshell/runxpcshelltests.py +++ b/testing/xpcshell/runxpcshelltests.py @@ -379,29 +379,8 @@ class XPCShellTestThread(Thread): # removed fine return - # we try again later at the end of the run for plugin dirs (because windows!) - if directory == self.pluginsDir: - self.cleanup_dir_list.append(directory) - return - - # we couldn't clean up the directory, and it's not the plugins dir, - # which means that something wrong has probably happened - if self.retry: - return - - with LOG_MUTEX: - message = "TEST-UNEXPECTED-FAIL | %s | Failed to clean up directory: %s" % (name, sys.exc_info()[1]) - self.log.error(message) - self.log_output(self.output_lines) - self.log_output(traceback.format_exc()) - - self.failCount += 1 - xunit_result["passed"] = False - xunit_result["failure"] = { - "type": "TEST-UNEXPECTED-FAIL", - "message": message, - "text": "%s\n%s" % ("\n".join(self.output_lines), traceback.format_exc()) - } + # we try cleaning up again later at the end of the run + self.cleanup_dir_list.append(directory) def clean_temp_dirs(self, name, stdout): # We don't want to delete the profile when running check-interactive @@ -1414,7 +1393,7 @@ class XPCShellTests(object): signal.signal(signal.SIGINT, signal.SIG_DFL) self.shutdownNode() - # Clean up any slacker directories that might be lying around (Windows). + # Clean up any slacker directories that might be lying around # Some might fail because of windows taking too long to unlock them. # We don't do anything if this fails because the test slaves will have # their $TEMP dirs cleaned up on reboot anyway. From 64d3cff62b91c9c06f3813e049b9c16962d816e2 Mon Sep 17 00:00:00 2001 From: Neil Deakin Date: Tue, 3 Sep 2013 13:23:37 -0400 Subject: [PATCH 53/64] Bug 853901 - Add platform-specific completion operations for downloads. r=paolo --- b2g/installer/package-manifest.in | 1 + browser/installer/package-manifest.in | 1 + mobile/android/installer/package-manifest.in | 1 + toolkit/components/build/Makefile.in | 2 + toolkit/components/build/nsToolkitCompsCID.h | 6 + .../components/build/nsToolkitCompsModule.cpp | 5 + toolkit/components/jsdownloads/moz.build | 2 +- .../components/jsdownloads/public/moz.build | 9 ++ .../public/mozIDownloadPlatform.idl | 39 +++++ .../jsdownloads/src/DownloadCore.jsm | 2 + .../jsdownloads/src/DownloadIntegration.jsm | 28 +++- .../jsdownloads/src/DownloadPlatform.cpp | 148 ++++++++++++++++++ .../jsdownloads/src/DownloadPlatform.h | 30 ++++ .../components/jsdownloads/src/Makefile.in | 14 ++ toolkit/components/jsdownloads/src/moz.build | 10 ++ .../test/unit/common_test_Download.js | 44 ++++++ 16 files changed, 340 insertions(+), 2 deletions(-) create mode 100644 toolkit/components/jsdownloads/public/moz.build create mode 100644 toolkit/components/jsdownloads/public/mozIDownloadPlatform.idl create mode 100644 toolkit/components/jsdownloads/src/DownloadPlatform.cpp create mode 100644 toolkit/components/jsdownloads/src/DownloadPlatform.h create mode 100644 toolkit/components/jsdownloads/src/Makefile.in diff --git a/b2g/installer/package-manifest.in b/b2g/installer/package-manifest.in index 8b03419aef1..9d40e379b44 100644 --- a/b2g/installer/package-manifest.in +++ b/b2g/installer/package-manifest.in @@ -240,6 +240,7 @@ @BINPATH@/components/intl.xpt @BINPATH@/components/jar.xpt @BINPATH@/components/jsdebugger.xpt +@BINPATH@/components/jsdownloads.xpt @BINPATH@/components/jsdservice.xpt @BINPATH@/components/jsinspector.xpt @BINPATH@/components/layout_base.xpt diff --git a/browser/installer/package-manifest.in b/browser/installer/package-manifest.in index d253f7acf19..7842047d3bc 100644 --- a/browser/installer/package-manifest.in +++ b/browser/installer/package-manifest.in @@ -248,6 +248,7 @@ @BINPATH@/components/jsdservice.xpt #endif @BINPATH@/components/jsdebugger.xpt +@BINPATH@/components/jsdownloads.xpt @BINPATH@/components/jsinspector.xpt @BINPATH@/components/layout_base.xpt #ifdef NS_PRINTING diff --git a/mobile/android/installer/package-manifest.in b/mobile/android/installer/package-manifest.in index a1d49c02bb1..82094f67b4c 100644 --- a/mobile/android/installer/package-manifest.in +++ b/mobile/android/installer/package-manifest.in @@ -188,6 +188,7 @@ @BINPATH@/components/jar.xpt @BINPATH@/components/jsdservice.xpt @BINPATH@/components/jsdebugger.xpt +@BINPATH@/components/jsdownloads.xpt @BINPATH@/components/jsinspector.xpt @BINPATH@/components/layout_base.xpt #ifdef NS_PRINTING diff --git a/toolkit/components/build/Makefile.in b/toolkit/components/build/Makefile.in index ab78ab56650..abf6dfd7854 100644 --- a/toolkit/components/build/Makefile.in +++ b/toolkit/components/build/Makefile.in @@ -17,6 +17,7 @@ LOCAL_INCLUDES = \ -I$(srcdir)/../feeds \ -I$(srcdir)/../find \ -I$(srcdir)/../intl \ + -I$(srcdir)/../jsdownloads/src \ -I$(srcdir)/../protobuf \ -I$(srcdir)/../startup \ -I$(srcdir)/../statusfilter \ @@ -32,6 +33,7 @@ SHARED_LIBRARY_LIBS = \ ../startup/$(LIB_PREFIX)appstartup_s.$(LIB_SUFFIX) \ ../statusfilter/$(LIB_PREFIX)mozbrwsr_s.$(LIB_SUFFIX) \ ../downloads/$(LIB_PREFIX)download_s.$(LIB_SUFFIX) \ + ../jsdownloads/src/$(LIB_PREFIX)jsdownloads_s.$(LIB_SUFFIX) \ ../protobuf/$(LIB_PREFIX)protobuf_s.$(LIB_SUFFIX) \ ../intl/$(LIB_PREFIX)intl_s.$(LIB_SUFFIX) \ $(NULL) diff --git a/toolkit/components/build/nsToolkitCompsCID.h b/toolkit/components/build/nsToolkitCompsCID.h index e9a7cc1ac5e..9b25877e58f 100644 --- a/toolkit/components/build/nsToolkitCompsCID.h +++ b/toolkit/components/build/nsToolkitCompsCID.h @@ -30,6 +30,9 @@ #define NS_DOWNLOADMANAGER_CONTRACTID \ "@mozilla.org/download-manager;1" +#define NS_DOWNLOADPLATFORM_CONTRACTID \ + "@mozilla.org/toolkit/download-platform;1" + #define NS_FORMHISTORY_CONTRACTID \ "@mozilla.org/satchel/form-history;1" @@ -117,6 +120,9 @@ #define NS_DOWNLOADMANAGER_CID \ { 0xedb0490e, 0x1dd1, 0x11b2, { 0x83, 0xb8, 0xdb, 0xf8, 0xd8, 0x59, 0x06, 0xa6 } } +#define NS_DOWNLOADPLATFORM_CID \ + { 0x649a14c9, 0xfe5c, 0x48ec, { 0x9c, 0x85, 0x00, 0xca, 0xd9, 0xcc, 0xf3, 0x2e } } + // {895DB6C7-DBDF-40ea-9F64-B175033243DC} #define NS_FORMFILLCONTROLLER_CID \ { 0x895db6c7, 0xdbdf, 0x40ea, { 0x9f, 0x64, 0xb1, 0x75, 0x3, 0x32, 0x43, 0xdc } } diff --git a/toolkit/components/build/nsToolkitCompsModule.cpp b/toolkit/components/build/nsToolkitCompsModule.cpp index 46ef7bb6600..eb77441573f 100644 --- a/toolkit/components/build/nsToolkitCompsModule.cpp +++ b/toolkit/components/build/nsToolkitCompsModule.cpp @@ -18,6 +18,7 @@ #include "nsAlertsService.h" #include "nsDownloadManager.h" +#include "DownloadPlatform.h" #include "nsDownloadProxy.h" #include "nsCharsetMenu.h" #include "rdf.h" @@ -48,6 +49,7 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsAlertsService) NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsDownloadManager, nsDownloadManager::GetSingleton) +NS_GENERIC_FACTORY_CONSTRUCTOR(DownloadPlatform) NS_GENERIC_FACTORY_CONSTRUCTOR(nsDownloadProxy) NS_GENERIC_FACTORY_CONSTRUCTOR(nsTypeAheadFind) @@ -94,6 +96,7 @@ NS_DEFINE_NAMED_CID(NS_ALERTSSERVICE_CID); NS_DEFINE_NAMED_CID(NS_PARENTALCONTROLSSERVICE_CID); #endif NS_DEFINE_NAMED_CID(NS_DOWNLOADMANAGER_CID); +NS_DEFINE_NAMED_CID(NS_DOWNLOADPLATFORM_CID); NS_DEFINE_NAMED_CID(NS_DOWNLOAD_CID); NS_DEFINE_NAMED_CID(NS_FIND_SERVICE_CID); NS_DEFINE_NAMED_CID(NS_TYPEAHEADFIND_CID); @@ -119,6 +122,7 @@ static const mozilla::Module::CIDEntry kToolkitCIDs[] = { { &kNS_PARENTALCONTROLSSERVICE_CID, false, NULL, nsParentalControlsServiceWinConstructor }, #endif { &kNS_DOWNLOADMANAGER_CID, false, NULL, nsDownloadManagerConstructor }, + { &kNS_DOWNLOADPLATFORM_CID, false, NULL, DownloadPlatformConstructor }, { &kNS_DOWNLOAD_CID, false, NULL, nsDownloadProxyConstructor }, { &kNS_FIND_SERVICE_CID, false, NULL, nsFindServiceConstructor }, { &kNS_TYPEAHEADFIND_CID, false, NULL, nsTypeAheadFindConstructor }, @@ -146,6 +150,7 @@ static const mozilla::Module::ContractIDEntry kToolkitContracts[] = { { NS_PARENTALCONTROLSSERVICE_CONTRACTID, &kNS_PARENTALCONTROLSSERVICE_CID }, #endif { NS_DOWNLOADMANAGER_CONTRACTID, &kNS_DOWNLOADMANAGER_CID }, + { NS_DOWNLOADPLATFORM_CONTRACTID, &kNS_DOWNLOADPLATFORM_CID }, { NS_TRANSFER_CONTRACTID, &kNS_DOWNLOAD_CID }, { NS_FIND_SERVICE_CONTRACTID, &kNS_FIND_SERVICE_CID }, { NS_TYPEAHEADFIND_CONTRACTID, &kNS_TYPEAHEADFIND_CID }, diff --git a/toolkit/components/jsdownloads/moz.build b/toolkit/components/jsdownloads/moz.build index 98c21858da8..47e64e62391 100644 --- a/toolkit/components/jsdownloads/moz.build +++ b/toolkit/components/jsdownloads/moz.build @@ -4,6 +4,6 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. -DIRS += ['src'] +DIRS += ['public', 'src'] TEST_DIRS += ['test'] diff --git a/toolkit/components/jsdownloads/public/moz.build b/toolkit/components/jsdownloads/public/moz.build new file mode 100644 index 00000000000..44a54264c40 --- /dev/null +++ b/toolkit/components/jsdownloads/public/moz.build @@ -0,0 +1,9 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +MODULE = 'jsdownloads' + +XPIDL_SOURCES += [ + 'mozIDownloadPlatform.idl', +] diff --git a/toolkit/components/jsdownloads/public/mozIDownloadPlatform.idl b/toolkit/components/jsdownloads/public/mozIDownloadPlatform.idl new file mode 100644 index 00000000000..3815d4ca71d --- /dev/null +++ b/toolkit/components/jsdownloads/public/mozIDownloadPlatform.idl @@ -0,0 +1,39 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsISupports.idl" + +interface nsIURI; +interface nsIFile; + +[scriptable, uuid(314A0972-E6E3-413A-8BD4-2C052BCB2C74)] +interface mozIDownloadPlatform : nsISupports +{ + /** + * Perform platform specific operations when a download is done. + * + * Windows: + * Add the download to the recent documents list + * Set the file to be indexed for searching + * Mac: + * Bounce the downloads dock icon + * GTK: + * Add the download to the recent documents list + * Save the source uri in the downloaded file's metadata + * Android: + * Scan media + * + * @param aSource + * Source URI of the download + * @param aTarget + * Downloaded file + * @param aContentType + * The source's content type + * @param aIsPrivate + * True for private downloads + * @return none + */ + void downloadDone(in nsIURI aSource, in nsIFile aTarget, + in ACString aContentType, in boolean aIsPrivate); +}; diff --git a/toolkit/components/jsdownloads/src/DownloadCore.jsm b/toolkit/components/jsdownloads/src/DownloadCore.jsm index fa118c43971..7a1280fe4b4 100644 --- a/toolkit/components/jsdownloads/src/DownloadCore.jsm +++ b/toolkit/components/jsdownloads/src/DownloadCore.jsm @@ -412,6 +412,8 @@ Download.prototype = { this.speed = 0; this._notifyChange(); if (this.succeeded) { + yield DownloadIntegration.downloadDone(this); + this._deferSucceeded.resolve(); if (this.launchWhenSucceeded) { diff --git a/toolkit/components/jsdownloads/src/DownloadIntegration.jsm b/toolkit/components/jsdownloads/src/DownloadIntegration.jsm index 179f1cedb5f..8e28acb387f 100644 --- a/toolkit/components/jsdownloads/src/DownloadIntegration.jsm +++ b/toolkit/components/jsdownloads/src/DownloadIntegration.jsm @@ -45,6 +45,9 @@ XPCOMUtils.defineLazyModuleGetter(this, "Task", "resource://gre/modules/Task.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "NetUtil", "resource://gre/modules/NetUtil.jsm"); +XPCOMUtils.defineLazyServiceGetter(this, "gDownloadPlatform", + "@mozilla.org/toolkit/download-platform;1", + "mozIDownloadPlatform"); XPCOMUtils.defineLazyServiceGetter(this, "gEnvironment", "@mozilla.org/process/environment;1", "nsIEnvironment"); @@ -54,7 +57,7 @@ XPCOMUtils.defineLazyServiceGetter(this, "gMIMEService", XPCOMUtils.defineLazyServiceGetter(this, "gExternalProtocolService", "@mozilla.org/uriloader/external-protocol-service;1", "nsIExternalProtocolService"); - + XPCOMUtils.defineLazyGetter(this, "gParentalControlsService", function() { if ("@mozilla.org/parental-controls-service;1" in Cc) { return Cc["@mozilla.org/parental-controls-service;1"] @@ -116,6 +119,7 @@ this.DownloadIntegration = { dontCheckParentalControls: false, shouldBlockInTest: false, dontOpenFileAndFolder: false, + downloadDoneCalled: false, _deferTestOpenFile: null, _deferTestShowDir: null, @@ -380,6 +384,28 @@ this.DownloadIntegration = { return Promise.resolve(shouldBlock); }, + /** + * Performs platform-specific operations when a download is done. + * + * aParam aDownload + * The Download object. + * + * @return {Promise} + * @resolves When all the operations completed successfully. + * @rejects JavaScript exception if any of the operations failed. + */ + downloadDone: function(aDownload) { + try { + gDownloadPlatform.downloadDone(NetUtil.newURI(aDownload.source.url), + new FileUtils.File(aDownload.target.path), + aDownload.contentType, aDownload.source.isPrivate); + this.downloadDoneCalled = true; + return Promise.resolve(); + } catch(ex) { + return Promise.reject(ex); + } + }, + /** * Determines whether it's a Windows Metro app. */ diff --git a/toolkit/components/jsdownloads/src/DownloadPlatform.cpp b/toolkit/components/jsdownloads/src/DownloadPlatform.cpp new file mode 100644 index 00000000000..e4675ad0273 --- /dev/null +++ b/toolkit/components/jsdownloads/src/DownloadPlatform.cpp @@ -0,0 +1,148 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "DownloadPlatform.h" +#include "nsString.h" +#include "nsIURI.h" +#include "nsIFile.h" +#include "nsDirectoryServiceDefs.h" + +#include "mozilla/Preferences.h" + +#define PREF_BDM_ADDTORECENTDOCS "browser.download.manager.addToRecentDocs" + +#ifdef XP_WIN +#include +#include "nsILocalFileWin.h" +#endif + +#ifdef XP_MACOSX +#include +#endif + +#ifdef MOZ_WIDGET_ANDROID +#include "AndroidBridge.h" +#endif + +#ifdef MOZ_WIDGET_GTK2 +#include +#endif + +using namespace mozilla; + +DownloadPlatform *DownloadPlatform::gDownloadPlatformService = nullptr; + +NS_IMPL_ISUPPORTS1(DownloadPlatform, mozIDownloadPlatform); + +DownloadPlatform* DownloadPlatform::GetDownloadPlatform() +{ + if (!gDownloadPlatformService) { + gDownloadPlatformService = new DownloadPlatform(); + } + + NS_ADDREF(gDownloadPlatformService); + +#if defined(MOZ_WIDGET_GTK2) + g_type_init(); +#endif + + return gDownloadPlatformService; +} + +#ifdef MOZ_ENABLE_GIO +static void gio_set_metadata_done(GObject *source_obj, GAsyncResult *res, gpointer user_data) +{ + GError *err = NULL; + g_file_set_attributes_finish(G_FILE(source_obj), res, NULL, &err); + if (err) { +#ifdef DEBUG + NS_DebugBreak(NS_DEBUG_WARNING, "Set file metadata failed: ", err->message, __FILE__, __LINE__); +#endif + g_error_free(err); + } +} +#endif + +nsresult DownloadPlatform::DownloadDone(nsIURI* aSource, nsIFile* aTarget, + const nsACString& aContentType, bool aIsPrivate) +{ +#if defined(XP_WIN) || defined(XP_MACOSX) || defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GTK2) + nsAutoString path; + if (aTarget && NS_SUCCEEDED(aTarget->GetPath(path))) { +#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK2) + // On Windows and Gtk, add the download to the system's "recent documents" + // list, with a pref to disable. + { + bool addToRecentDocs = Preferences::GetBool(PREF_BDM_ADDTORECENTDOCS); + if (addToRecentDocs && !aIsPrivate) { +#ifdef XP_WIN + ::SHAddToRecentDocs(SHARD_PATHW, path.get()); +#elif defined(MOZ_WIDGET_GTK2) + GtkRecentManager* manager = gtk_recent_manager_get_default(); + + gchar* uri = g_filename_to_uri(NS_ConvertUTF16toUTF8(path).get(), + NULL, NULL); + if (uri) { + gtk_recent_manager_add_item(manager, uri); + g_free(uri); + } +#endif + } +#ifdef MOZ_ENABLE_GIO + // Use GIO to store the source URI for later display in the file manager. + GFile* gio_file = g_file_new_for_path(NS_ConvertUTF16toUTF8(path).get()); + nsCString source_uri; + aSource->GetSpec(source_uri); + GFileInfo *file_info = g_file_info_new(); + g_file_info_set_attribute_string(file_info, "metadata::download-uri", source_uri.get()); + g_file_set_attributes_async(gio_file, + file_info, + G_FILE_QUERY_INFO_NONE, + G_PRIORITY_DEFAULT, + NULL, gio_set_metadata_done, NULL); + g_object_unref(file_info); + g_object_unref(gio_file); +#endif + } +#endif +#ifdef XP_MACOSX + // On OS X, make the downloads stack bounce. + CFStringRef observedObject = ::CFStringCreateWithCString(kCFAllocatorDefault, + NS_ConvertUTF16toUTF8(path).get(), + kCFStringEncodingUTF8); + CFNotificationCenterRef center = ::CFNotificationCenterGetDistributedCenter(); + ::CFNotificationCenterPostNotification(center, CFSTR("com.apple.DownloadFileFinished"), + observedObject, NULL, TRUE); + ::CFRelease(observedObject); +#endif +#ifdef MOZ_WIDGET_ANDROID + if (!aContentType.IsEmpty()) { + mozilla::AndroidBridge::Bridge()->ScanMedia(path, aContentType); + } +#endif + } + +#ifdef XP_WIN + // Adjust file attributes so that by default, new files are indexed by + // desktop search services. Skip off those that land in the temp folder. + nsCOMPtr tempDir, fileDir; + nsresult rv = NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(tempDir)); + NS_ENSURE_SUCCESS(rv, rv); + aTarget->GetParent(getter_AddRefs(fileDir)); + + bool isTemp = false; + if (fileDir) { + fileDir->Equals(tempDir, &isTemp); + } + + nsCOMPtr localFileWin(do_QueryInterface(aTarget)); + if (!isTemp && localFileWin) { + localFileWin->SetFileAttributesWin(nsILocalFileWin::WFA_SEARCH_INDEXED); + } +#endif + +#endif + + return NS_OK; +} diff --git a/toolkit/components/jsdownloads/src/DownloadPlatform.h b/toolkit/components/jsdownloads/src/DownloadPlatform.h new file mode 100644 index 00000000000..b7eb283ee0e --- /dev/null +++ b/toolkit/components/jsdownloads/src/DownloadPlatform.h @@ -0,0 +1,30 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef __DownloadPlatform_h__ +#define __DownloadPlatform_h__ + +#include "mozIDownloadPlatform.h" + +#include "nsCOMPtr.h" + +class nsIURI; +class nsIFile; + +class DownloadPlatform : public mozIDownloadPlatform +{ +public: + + NS_DECL_ISUPPORTS + NS_DECL_MOZIDOWNLOADPLATFORM + + DownloadPlatform() { } + virtual ~DownloadPlatform() { } + + static DownloadPlatform *gDownloadPlatformService; + + static DownloadPlatform* GetDownloadPlatform(); +}; + +#endif diff --git a/toolkit/components/jsdownloads/src/Makefile.in b/toolkit/components/jsdownloads/src/Makefile.in new file mode 100644 index 00000000000..09f092d08e0 --- /dev/null +++ b/toolkit/components/jsdownloads/src/Makefile.in @@ -0,0 +1,14 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +DEPTH = @DEPTH@ +topsrcdir = @top_srcdir@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +include $(DEPTH)/config/autoconf.mk + +include $(topsrcdir)/config/rules.mk + +CXXFLAGS += $(TK_CFLAGS) diff --git a/toolkit/components/jsdownloads/src/moz.build b/toolkit/components/jsdownloads/src/moz.build index 48df46343f8..6416d1d853c 100644 --- a/toolkit/components/jsdownloads/src/moz.build +++ b/toolkit/components/jsdownloads/src/moz.build @@ -4,6 +4,16 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. +MODULE = 'jsdownloads' + +CPP_SOURCES += [ + 'DownloadPlatform.cpp', +] + +LIBRARY_NAME = 'jsdownloads_s' + +LIBXUL_LIBRARY = True + EXTRA_COMPONENTS += [ 'DownloadLegacy.js', 'Downloads.manifest', diff --git a/toolkit/components/jsdownloads/test/unit/common_test_Download.js b/toolkit/components/jsdownloads/test/unit/common_test_Download.js index 23148106212..11595fe3718 100644 --- a/toolkit/components/jsdownloads/test/unit/common_test_Download.js +++ b/toolkit/components/jsdownloads/test/unit/common_test_Download.js @@ -1623,3 +1623,47 @@ add_task(function test_contentType() { do_check_eq("text/plain", download.contentType); }); + +/** + * This test will call the platform specific operations within + * DownloadPlatform::DownloadDone. While there is no test to verify the + * specific behaviours, this at least ensures that there is no error or crash. + */ +add_task(function test_platform_integration() +{ + for (let isPrivate of [false, true]) { + DownloadIntegration.downloadDoneCalled = false; + + // Some platform specific operations only operate on files outside the + // temporary directory or in the Downloads directory (such as setting + // the Windows searchable attribute, and the Mac Downloads icon bouncing), + // so use the system Downloads directory for the target file. + let targetFile = yield DownloadIntegration.getSystemDownloadsDirectory(); + targetFile = targetFile.clone(); + targetFile.append("test" + (Math.floor(Math.random() * 1000000))); + + let download; + if (gUseLegacySaver) { + download = yield promiseStartLegacyDownload(httpUrl("source.txt"), + { targetFile: targetFile }); + } + else { + download = yield Downloads.createDownload({ + source: httpUrl("source.txt"), + target: targetFile, + }); + download.start(); + } + + // Wait for the whenSucceeded promise to be resolved first. + // downloadDone should be called before the whenSucceeded promise is resolved. + yield download.whenSucceeded().then(function () { + do_check_true(DownloadIntegration.downloadDoneCalled); + }); + + // Then, wait for the promise returned by "start" to be resolved. + yield promiseDownloadStopped(download); + + yield promiseVerifyContents(download.target.path, TEST_DATA_SHORT); + } +}); From a59078b2abea64f432437cdef46c482bd92f3257 Mon Sep 17 00:00:00 2001 From: Neil Deakin Date: Tue, 3 Sep 2013 13:24:25 -0400 Subject: [PATCH 54/64] Bug 896142, Entries appearing twice in form-fill autocomplete menus, r=mhammond --- toolkit/components/satchel/FormHistory.jsm | 5 ++-- .../satchel/test/unit/test_history_api.js | 28 ++++++++++++++++--- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/toolkit/components/satchel/FormHistory.jsm b/toolkit/components/satchel/FormHistory.jsm index f53a8f3299d..eb696fbd4fd 100644 --- a/toolkit/components/satchel/FormHistory.jsm +++ b/toolkit/components/satchel/FormHistory.jsm @@ -18,7 +18,7 @@ * callback - callback that is called when results are available or an error occurs. * The callback is passed a result array containing each found entry. Each element in * the array is an object containing a property for each search term specified by 'terms'. - * count(terms, queryData, callback) + * count(queryData, callback) * Find the number of stored entries that match the given criteria. * queryData - array of objects that indicate the query. See the search method for details. * callback - callback that is called when results are available or an error occurs. @@ -903,6 +903,7 @@ this.FormHistory = { } numSearches++; + let changeToUpdate = change; FormHistory.search( [ "guid" ], { @@ -926,7 +927,7 @@ this.FormHistory = { } this.foundResult = true; - change.guid = aResult["guid"]; + changeToUpdate.guid = aResult["guid"]; }, handleError : function(aError) { diff --git a/toolkit/components/satchel/test/unit/test_history_api.js b/toolkit/components/satchel/test/unit/test_history_api.js index 294a9989a3e..2233ce8959c 100644 --- a/toolkit/components/satchel/test/unit/test_history_api.js +++ b/toolkit/components/satchel/test/unit/test_history_api.js @@ -373,10 +373,6 @@ add_task(function () // ===== 19 ===== // Remove an entry by time testnum++; - results = yield promiseSearchEntries(["timesUsed", "firstUsed", "lastUsed"], - { fieldname: "field1", value: "modifiedValue" }); - [timesUsed, firstUsed, lastUsed] = processFirstResult(results); - yield promiseUpdate({ op : "remove", firstUsedStart: 60, firstUsedEnd: 250 }); yield promiseCountEntries("field1", "modifiedValue", checkExists); yield promiseCountEntries("field2", "value2", checkNotExists); @@ -385,6 +381,30 @@ add_task(function () yield promiseCountEntries(null, null, function(num) do_check_eq(num, 2)); yield countDeletedEntries(10); + // ===== 20 ===== + // Bump multiple existing entries at once + testnum++; + + yield promiseUpdate([{ op : "add", fieldname: "field5", value: "value5", + timesUsed: 5, firstUsed: 230, lastUsed: 600 }, + { op : "add", fieldname: "field6", value: "value6", + timesUsed: 12, firstUsed: 430, lastUsed: 700 }]); + yield promiseCountEntries(null, null, function(num) do_check_eq(num, 4)); + + yield promiseUpdate([ + { op : "bump", fieldname: "field5", value: "value5" }, + { op : "bump", fieldname: "field6", value: "value6" }]); + results = yield promiseSearchEntries(["fieldname", "timesUsed", "firstUsed", "lastUsed"], { }); + + do_check_eq(6, results[2].timesUsed); + do_check_eq(13, results[3].timesUsed); + do_check_eq(230, results[2].firstUsed); + do_check_eq(430, results[3].firstUsed); + do_check_true(results[2].lastUsed > 600); + do_check_true(results[3].lastUsed > 700); + + yield promiseCountEntries(null, null, function(num) do_check_eq(num, 4)); + } catch (e) { throw "FAILED in test #" + testnum + " -- " + e; } From d767fac3355e1cd8ce8691f3f82f76e0be16929f Mon Sep 17 00:00:00 2001 From: Nathan Froyd Date: Tue, 3 Sep 2013 10:44:34 -0400 Subject: [PATCH 55/64] Bug 912054 - don't re-initialize mBoundRect in nsRegion::Init; r=BenWa --- gfx/src/nsRegion.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gfx/src/nsRegion.cpp b/gfx/src/nsRegion.cpp index c984de9e908..cbf937be726 100644 --- a/gfx/src/nsRegion.cpp +++ b/gfx/src/nsRegion.cpp @@ -246,7 +246,9 @@ void nsRegion::Init() mRectListHead.prev = mRectListHead.next = &mRectListHead; mCurRect = &mRectListHead; mRectCount = 0; - mBoundRect.SetRect (0, 0, 0, 0); + MOZ_ASSERT(mBoundRect.x == 0 && mBoundRect.y == 0 && + mBoundRect.width == 0 && mBoundRect.height == 0, + "Caller must have initialized mBoundRect"); } inline void nsRegion::InsertBefore (RgnRect* aNewRect, RgnRect* aRelativeRect) From 1a4998dc2a664633533a437e8a97035f320c89b8 Mon Sep 17 00:00:00 2001 From: Joel Maher Date: Tue, 3 Sep 2013 14:08:07 -0400 Subject: [PATCH 56/64] Bug 912009 - update talos.json to remove "suite" specific filters as they are now in test.py. r=jhammel --- testing/talos/talos.json | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/testing/talos/talos.json b/testing/talos/talos.json index 60efbc7140d..6fed4f67fac 100644 --- a/testing/talos/talos.json +++ b/testing/talos/talos.json @@ -5,7 +5,7 @@ }, "global": { "talos_repo": "http://hg.mozilla.org/build/talos", - "talos_revision": "1817a7d17991" + "talos_revision": "63e4fcd8784d" }, "suites": { "chromez": { @@ -34,14 +34,10 @@ ] }, "dromaeojs": { - "tests": [ - "dromaeo_css", - "dromaeo_dom", - "kraken:v8_7" - ] + "tests": ["dromaeo_css", "dromaeo_dom", "kraken", "v8_7"] }, "other": { - "tests": ["tscrollx", "a11yr", "ts_paint", "tpaint"], + "tests": ["a11yr", "ts_paint", "tpaint"], "talos_options": [ "--mozAfterPaint", "--filter", @@ -51,13 +47,7 @@ ] }, "svgr": { - "tests": ["tsvgx", "tsvgr_opacity", "tart"], - "talos_options": [ - "--filter", - "ignore_first:5", - "--filter", - "median" - ] + "tests": ["tsvgx", "tsvgr_opacity", "tart", "tscrollx"] }, "rafx": { "tests": ["tscrollr", "tsvgr"], From 642920499dab2e9b7e816041bfe470c5dd290de4 Mon Sep 17 00:00:00 2001 From: Kannan Vijayan Date: Tue, 3 Sep 2013 14:35:18 -0400 Subject: [PATCH 57/64] Bug 909764 - Fix syntax parsing error that allows let bindings of eval in strict mode. r=jwalden r=jorendorff --- js/src/frontend/Parser.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index 983116cc4e8..7233321a128 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -2796,6 +2796,9 @@ template <> Parser::bindLet(BindData *data, HandlePropertyName name, Parser *parser) { + if (!parser->checkStrictBinding(name, data->pn)) + return false; + return true; } From 3388e7fa7124fc60a6232aba6060950109723b19 Mon Sep 17 00:00:00 2001 From: Blake Kaplan Date: Thu, 29 Aug 2013 10:14:15 -0400 Subject: [PATCH 58/64] Bug 860123 - Part 1: Disallow extending or collapsing selections across documents; r=ehsan --- layout/generic/nsSelection.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/layout/generic/nsSelection.cpp b/layout/generic/nsSelection.cpp index 889f00d4f23..46926d061f8 100644 --- a/layout/generic/nsSelection.cpp +++ b/layout/generic/nsSelection.cpp @@ -4382,8 +4382,12 @@ Selection::Collapse(nsINode* aParentNode, int32_t aOffset) if (!IsValidSelectionPoint(mFrameSelection, aParentNode)) return NS_ERROR_FAILURE; nsresult result; + + nsRefPtr presContext = GetPresContext(); + if (presContext->Document() != aParentNode->OwnerDoc()) + return NS_ERROR_FAILURE; + // Delete all of the current ranges - nsRefPtr presContext = GetPresContext(); Clear(presContext); // Turn off signal for table selection @@ -4620,6 +4624,10 @@ Selection::Extend(nsINode* aParentNode, int32_t aOffset) if (!IsValidSelectionPoint(mFrameSelection, aParentNode)) return NS_ERROR_FAILURE; + nsRefPtr presContext = GetPresContext(); + if (presContext->Document() != aParentNode->OwnerDoc()) + return NS_ERROR_FAILURE; + //mFrameSelection->InvalidateDesiredX(); nsINode* anchorNode = GetAnchorNode(); @@ -4654,7 +4662,6 @@ Selection::Extend(nsINode* aParentNode, int32_t aOffset) aParentNode, aOffset, &disconnected); - nsRefPtr presContext = GetPresContext(); nsRefPtr difRange = new nsRange(aParentNode); if ((result1 == 0 && result3 < 0) || (result1 <= 0 && result2 < 0)){//a1,2 a,1,2 //select from 1 to 2 unless they are collapsed From c0d9c60ecadaff624c6ef2330ccea1599539f33f Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Tue, 3 Sep 2013 15:00:27 -0400 Subject: [PATCH 59/64] Bug 860123 - Make mochitests expect the new behavior. r=ehsan --- .../editing/conformancetest/moz.build | 1 - .../failures/editing/selecttest/Makefile.in | 5 + .../failures/editing/selecttest/moz.build | 1 - .../selecttest/test_collapse.html.json | 2008 +++++++++ .../test_collapseToStartEnd.html.json | 44 + .../editing/selecttest/test_extend.html.json | 3928 +++++++++++++++++ .../selecttest/test_removeAllRanges.html.json | 23 + .../test_selectAllChildren.html.json | 1241 ++++++ 8 files changed, 7249 insertions(+), 2 deletions(-) create mode 100644 dom/imptests/failures/editing/selecttest/test_collapse.html.json create mode 100644 dom/imptests/failures/editing/selecttest/test_collapseToStartEnd.html.json create mode 100644 dom/imptests/failures/editing/selecttest/test_extend.html.json create mode 100644 dom/imptests/failures/editing/selecttest/test_removeAllRanges.html.json create mode 100644 dom/imptests/failures/editing/selecttest/test_selectAllChildren.html.json diff --git a/dom/imptests/failures/editing/conformancetest/moz.build b/dom/imptests/failures/editing/conformancetest/moz.build index d3ca36bedcb..16e83110bc1 100644 --- a/dom/imptests/failures/editing/conformancetest/moz.build +++ b/dom/imptests/failures/editing/conformancetest/moz.build @@ -1,4 +1,3 @@ -# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- # THIS FILE IS AUTOGENERATED BY parseFailures.py - DO NOT EDIT DIRS += [ diff --git a/dom/imptests/failures/editing/selecttest/Makefile.in b/dom/imptests/failures/editing/selecttest/Makefile.in index 1e81c4421c7..49b8cc388c6 100644 --- a/dom/imptests/failures/editing/selecttest/Makefile.in +++ b/dom/imptests/failures/editing/selecttest/Makefile.in @@ -12,8 +12,13 @@ include $(DEPTH)/config/autoconf.mk MOCHITEST_FILES := \ test_Document-open.html.json \ test_addRange.html.json \ + test_collapse.html.json \ + test_collapseToStartEnd.html.json \ + test_extend.html.json \ test_getSelection.html.json \ test_interfaces.html.json \ + test_removeAllRanges.html.json \ + test_selectAllChildren.html.json \ $(NULL) include $(topsrcdir)/config/rules.mk diff --git a/dom/imptests/failures/editing/selecttest/moz.build b/dom/imptests/failures/editing/selecttest/moz.build index d3ca36bedcb..16e83110bc1 100644 --- a/dom/imptests/failures/editing/selecttest/moz.build +++ b/dom/imptests/failures/editing/selecttest/moz.build @@ -1,4 +1,3 @@ -# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- # THIS FILE IS AUTOGENERATED BY parseFailures.py - DO NOT EDIT DIRS += [ diff --git a/dom/imptests/failures/editing/selecttest/test_collapse.html.json b/dom/imptests/failures/editing/selecttest/test_collapse.html.json new file mode 100644 index 00000000000..d866852814c --- /dev/null +++ b/dom/imptests/failures/editing/selecttest/test_collapse.html.json @@ -0,0 +1,2008 @@ +{ + "Range 0 [], point 20 [foreignPara1.firstChild, 0]":true, + "Range 0 [], point 21 [foreignPara1.firstChild, 1]":true, + "Range 0 [], point 22 [foreignPara1.firstChild, 8]":true, + "Range 0 [], point 23 [foreignPara1.firstChild, 9]":true, + "Range 0 [], point 31 [foreignDoc.documentElement, 0]":true, + "Range 0 [], point 32 [foreignDoc.documentElement, 1]":true, + "Range 0 [], point 33 [foreignDoc.head, 0]":true, + "Range 0 [], point 34 [foreignDoc.body, 1]":true, + "Range 0 [], point 54 [foreignDoc, 0]":true, + "Range 0 [], point 55 [foreignDoc, 1]":true, + "Range 0 [], point 56 [foreignComment, 2]":true, + "Range 0 [], point 57 [foreignTextNode, 0]":true, + "Range 0 [], point 58 [foreignTextNode, 36]":true, + "Range 0 [], point 59 [xmlDoc, -1]":true, + "Range 0 [], point 60 [xmlDoc, 0]":true, + "Range 0 [], point 61 [xmlDoc, 1]":true, + "Range 0 [], point 62 [xmlDoc, 5]":true, + "Range 0 [], point 63 [xmlComment, 0]":true, + "Range 0 [], point 64 [xmlComment, 4]":true, + "Range 0 [], point 65 [processingInstruction, 0]":true, + "Range 0 [], point 66 [processingInstruction, 5]":true, + "Range 0 [], point 67 [processingInstruction, 9]":true, + "Range 0 [], point 70 [detachedForeignTextNode, 0]":true, + "Range 0 [], point 71 [detachedForeignTextNode, 8]":true, + "Range 0 [], point 72 [detachedXmlTextNode, 0]":true, + "Range 0 [], point 73 [detachedXmlTextNode, 8]":true, + "Range 0 [], point 74 [detachedProcessingInstruction, 12]":true, + "Range 0 [], point 77 [detachedForeignComment, 0]":true, + "Range 0 [], point 78 [detachedForeignComment, 4]":true, + "Range 0 [], point 79 [detachedXmlComment, 2]":true, + "Range 0 [], point 81 [foreignDocfrag, 0]":true, + "Range 0 [], point 82 [xmlDocfrag, 0]":true, + "Range 0 [], point 86 [foreignDoctype, 0]":true, + "Range 0 [], point 87 [xmlDoctype, 0]":true, + "Range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0], point 20 [foreignPara1.firstChild, 0]":true, + "Range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0], point 21 [foreignPara1.firstChild, 1]":true, + "Range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0], point 22 [foreignPara1.firstChild, 8]":true, + "Range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0], point 23 [foreignPara1.firstChild, 9]":true, + "Range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0], point 31 [foreignDoc.documentElement, 0]":true, + "Range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0], point 32 [foreignDoc.documentElement, 1]":true, + "Range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0], point 33 [foreignDoc.head, 0]":true, + "Range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0], point 34 [foreignDoc.body, 1]":true, + "Range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0], point 54 [foreignDoc, 0]":true, + "Range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0], point 55 [foreignDoc, 1]":true, + "Range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0], point 56 [foreignComment, 2]":true, + "Range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0], point 57 [foreignTextNode, 0]":true, + "Range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0], point 58 [foreignTextNode, 36]":true, + "Range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0], point 59 [xmlDoc, -1]":true, + "Range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0], point 60 [xmlDoc, 0]":true, + "Range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0], point 61 [xmlDoc, 1]":true, + "Range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0], point 62 [xmlDoc, 5]":true, + "Range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0], point 63 [xmlComment, 0]":true, + "Range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0], point 64 [xmlComment, 4]":true, + "Range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0], point 65 [processingInstruction, 0]":true, + "Range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0], point 66 [processingInstruction, 5]":true, + "Range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0], point 67 [processingInstruction, 9]":true, + "Range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0], point 70 [detachedForeignTextNode, 0]":true, + "Range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0], point 71 [detachedForeignTextNode, 8]":true, + "Range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0], point 72 [detachedXmlTextNode, 0]":true, + "Range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0], point 73 [detachedXmlTextNode, 8]":true, + "Range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0], point 74 [detachedProcessingInstruction, 12]":true, + "Range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0], point 77 [detachedForeignComment, 0]":true, + "Range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0], point 78 [detachedForeignComment, 4]":true, + "Range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0], point 79 [detachedXmlComment, 2]":true, + "Range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0], point 81 [foreignDocfrag, 0]":true, + "Range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0], point 82 [xmlDocfrag, 0]":true, + "Range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0], point 86 [foreignDoctype, 0]":true, + "Range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0], point 87 [xmlDoctype, 0]":true, + "Range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1], point 20 [foreignPara1.firstChild, 0]":true, + "Range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1], point 21 [foreignPara1.firstChild, 1]":true, + "Range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1], point 22 [foreignPara1.firstChild, 8]":true, + "Range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1], point 23 [foreignPara1.firstChild, 9]":true, + "Range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1], point 31 [foreignDoc.documentElement, 0]":true, + "Range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1], point 32 [foreignDoc.documentElement, 1]":true, + "Range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1], point 33 [foreignDoc.head, 0]":true, + "Range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1], point 34 [foreignDoc.body, 1]":true, + "Range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1], point 54 [foreignDoc, 0]":true, + "Range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1], point 55 [foreignDoc, 1]":true, + "Range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1], point 56 [foreignComment, 2]":true, + "Range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1], point 57 [foreignTextNode, 0]":true, + "Range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1], point 58 [foreignTextNode, 36]":true, + "Range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1], point 59 [xmlDoc, -1]":true, + "Range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1], point 60 [xmlDoc, 0]":true, + "Range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1], point 61 [xmlDoc, 1]":true, + "Range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1], point 62 [xmlDoc, 5]":true, + "Range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1], point 63 [xmlComment, 0]":true, + "Range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1], point 64 [xmlComment, 4]":true, + "Range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1], point 65 [processingInstruction, 0]":true, + "Range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1], point 66 [processingInstruction, 5]":true, + "Range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1], point 67 [processingInstruction, 9]":true, + "Range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1], point 70 [detachedForeignTextNode, 0]":true, + "Range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1], point 71 [detachedForeignTextNode, 8]":true, + "Range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1], point 72 [detachedXmlTextNode, 0]":true, + "Range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1], point 73 [detachedXmlTextNode, 8]":true, + "Range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1], point 74 [detachedProcessingInstruction, 12]":true, + "Range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1], point 77 [detachedForeignComment, 0]":true, + "Range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1], point 78 [detachedForeignComment, 4]":true, + "Range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1], point 79 [detachedXmlComment, 2]":true, + "Range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1], point 81 [foreignDocfrag, 0]":true, + "Range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1], point 82 [xmlDocfrag, 0]":true, + "Range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1], point 86 [foreignDoctype, 0]":true, + "Range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1], point 87 [xmlDoctype, 0]":true, + "Range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8], point 20 [foreignPara1.firstChild, 0]":true, + "Range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8], point 21 [foreignPara1.firstChild, 1]":true, + "Range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8], point 22 [foreignPara1.firstChild, 8]":true, + "Range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8], point 23 [foreignPara1.firstChild, 9]":true, + "Range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8], point 31 [foreignDoc.documentElement, 0]":true, + "Range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8], point 32 [foreignDoc.documentElement, 1]":true, + "Range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8], point 33 [foreignDoc.head, 0]":true, + "Range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8], point 34 [foreignDoc.body, 1]":true, + "Range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8], point 54 [foreignDoc, 0]":true, + "Range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8], point 55 [foreignDoc, 1]":true, + "Range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8], point 56 [foreignComment, 2]":true, + "Range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8], point 57 [foreignTextNode, 0]":true, + "Range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8], point 58 [foreignTextNode, 36]":true, + "Range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8], point 59 [xmlDoc, -1]":true, + "Range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8], point 60 [xmlDoc, 0]":true, + "Range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8], point 61 [xmlDoc, 1]":true, + "Range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8], point 62 [xmlDoc, 5]":true, + "Range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8], point 63 [xmlComment, 0]":true, + "Range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8], point 64 [xmlComment, 4]":true, + "Range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8], point 65 [processingInstruction, 0]":true, + "Range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8], point 66 [processingInstruction, 5]":true, + "Range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8], point 67 [processingInstruction, 9]":true, + "Range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8], point 70 [detachedForeignTextNode, 0]":true, + "Range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8], point 71 [detachedForeignTextNode, 8]":true, + "Range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8], point 72 [detachedXmlTextNode, 0]":true, + "Range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8], point 73 [detachedXmlTextNode, 8]":true, + "Range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8], point 74 [detachedProcessingInstruction, 12]":true, + "Range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8], point 77 [detachedForeignComment, 0]":true, + "Range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8], point 78 [detachedForeignComment, 4]":true, + "Range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8], point 79 [detachedXmlComment, 2]":true, + "Range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8], point 81 [foreignDocfrag, 0]":true, + "Range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8], point 82 [xmlDocfrag, 0]":true, + "Range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8], point 86 [foreignDoctype, 0]":true, + "Range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8], point 87 [xmlDoctype, 0]":true, + "Range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9], point 20 [foreignPara1.firstChild, 0]":true, + "Range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9], point 21 [foreignPara1.firstChild, 1]":true, + "Range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9], point 22 [foreignPara1.firstChild, 8]":true, + "Range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9], point 23 [foreignPara1.firstChild, 9]":true, + "Range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9], point 31 [foreignDoc.documentElement, 0]":true, + "Range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9], point 32 [foreignDoc.documentElement, 1]":true, + "Range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9], point 33 [foreignDoc.head, 0]":true, + "Range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9], point 34 [foreignDoc.body, 1]":true, + "Range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9], point 54 [foreignDoc, 0]":true, + "Range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9], point 55 [foreignDoc, 1]":true, + "Range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9], point 56 [foreignComment, 2]":true, + "Range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9], point 57 [foreignTextNode, 0]":true, + "Range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9], point 58 [foreignTextNode, 36]":true, + "Range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9], point 59 [xmlDoc, -1]":true, + "Range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9], point 60 [xmlDoc, 0]":true, + "Range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9], point 61 [xmlDoc, 1]":true, + "Range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9], point 62 [xmlDoc, 5]":true, + "Range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9], point 63 [xmlComment, 0]":true, + "Range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9], point 64 [xmlComment, 4]":true, + "Range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9], point 65 [processingInstruction, 0]":true, + "Range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9], point 66 [processingInstruction, 5]":true, + "Range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9], point 67 [processingInstruction, 9]":true, + "Range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9], point 70 [detachedForeignTextNode, 0]":true, + "Range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9], point 71 [detachedForeignTextNode, 8]":true, + "Range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9], point 72 [detachedXmlTextNode, 0]":true, + "Range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9], point 73 [detachedXmlTextNode, 8]":true, + "Range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9], point 74 [detachedProcessingInstruction, 12]":true, + "Range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9], point 77 [detachedForeignComment, 0]":true, + "Range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9], point 78 [detachedForeignComment, 4]":true, + "Range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9], point 79 [detachedXmlComment, 2]":true, + "Range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9], point 81 [foreignDocfrag, 0]":true, + "Range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9], point 82 [xmlDocfrag, 0]":true, + "Range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9], point 86 [foreignDoctype, 0]":true, + "Range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9], point 87 [xmlDoctype, 0]":true, + "Range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0], point 20 [foreignPara1.firstChild, 0]":true, + "Range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0], point 21 [foreignPara1.firstChild, 1]":true, + "Range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0], point 22 [foreignPara1.firstChild, 8]":true, + "Range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0], point 23 [foreignPara1.firstChild, 9]":true, + "Range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0], point 31 [foreignDoc.documentElement, 0]":true, + "Range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0], point 32 [foreignDoc.documentElement, 1]":true, + "Range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0], point 33 [foreignDoc.head, 0]":true, + "Range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0], point 34 [foreignDoc.body, 1]":true, + "Range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0], point 54 [foreignDoc, 0]":true, + "Range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0], point 55 [foreignDoc, 1]":true, + "Range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0], point 56 [foreignComment, 2]":true, + "Range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0], point 57 [foreignTextNode, 0]":true, + "Range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0], point 58 [foreignTextNode, 36]":true, + "Range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0], point 59 [xmlDoc, -1]":true, + "Range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0], point 60 [xmlDoc, 0]":true, + "Range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0], point 61 [xmlDoc, 1]":true, + "Range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0], point 62 [xmlDoc, 5]":true, + "Range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0], point 63 [xmlComment, 0]":true, + "Range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0], point 64 [xmlComment, 4]":true, + "Range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0], point 65 [processingInstruction, 0]":true, + "Range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0], point 66 [processingInstruction, 5]":true, + "Range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0], point 67 [processingInstruction, 9]":true, + "Range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0], point 70 [detachedForeignTextNode, 0]":true, + "Range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0], point 71 [detachedForeignTextNode, 8]":true, + "Range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0], point 72 [detachedXmlTextNode, 0]":true, + "Range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0], point 73 [detachedXmlTextNode, 8]":true, + "Range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0], point 74 [detachedProcessingInstruction, 12]":true, + "Range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0], point 77 [detachedForeignComment, 0]":true, + "Range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0], point 78 [detachedForeignComment, 4]":true, + "Range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0], point 79 [detachedXmlComment, 2]":true, + "Range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0], point 81 [foreignDocfrag, 0]":true, + "Range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0], point 82 [xmlDocfrag, 0]":true, + "Range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0], point 86 [foreignDoctype, 0]":true, + "Range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0], point 87 [xmlDoctype, 0]":true, + "Range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1], point 20 [foreignPara1.firstChild, 0]":true, + "Range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1], point 21 [foreignPara1.firstChild, 1]":true, + "Range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1], point 22 [foreignPara1.firstChild, 8]":true, + "Range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1], point 23 [foreignPara1.firstChild, 9]":true, + "Range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1], point 31 [foreignDoc.documentElement, 0]":true, + "Range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1], point 32 [foreignDoc.documentElement, 1]":true, + "Range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1], point 33 [foreignDoc.head, 0]":true, + "Range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1], point 34 [foreignDoc.body, 1]":true, + "Range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1], point 54 [foreignDoc, 0]":true, + "Range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1], point 55 [foreignDoc, 1]":true, + "Range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1], point 56 [foreignComment, 2]":true, + "Range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1], point 57 [foreignTextNode, 0]":true, + "Range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1], point 58 [foreignTextNode, 36]":true, + "Range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1], point 59 [xmlDoc, -1]":true, + "Range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1], point 60 [xmlDoc, 0]":true, + "Range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1], point 61 [xmlDoc, 1]":true, + "Range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1], point 62 [xmlDoc, 5]":true, + "Range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1], point 63 [xmlComment, 0]":true, + "Range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1], point 64 [xmlComment, 4]":true, + "Range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1], point 65 [processingInstruction, 0]":true, + "Range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1], point 66 [processingInstruction, 5]":true, + "Range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1], point 67 [processingInstruction, 9]":true, + "Range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1], point 70 [detachedForeignTextNode, 0]":true, + "Range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1], point 71 [detachedForeignTextNode, 8]":true, + "Range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1], point 72 [detachedXmlTextNode, 0]":true, + "Range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1], point 73 [detachedXmlTextNode, 8]":true, + "Range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1], point 74 [detachedProcessingInstruction, 12]":true, + "Range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1], point 77 [detachedForeignComment, 0]":true, + "Range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1], point 78 [detachedForeignComment, 4]":true, + "Range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1], point 79 [detachedXmlComment, 2]":true, + "Range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1], point 81 [foreignDocfrag, 0]":true, + "Range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1], point 82 [xmlDocfrag, 0]":true, + "Range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1], point 86 [foreignDoctype, 0]":true, + "Range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1], point 87 [xmlDoctype, 0]":true, + "Range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8], point 20 [foreignPara1.firstChild, 0]":true, + "Range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8], point 21 [foreignPara1.firstChild, 1]":true, + "Range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8], point 22 [foreignPara1.firstChild, 8]":true, + "Range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8], point 23 [foreignPara1.firstChild, 9]":true, + "Range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8], point 31 [foreignDoc.documentElement, 0]":true, + "Range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8], point 32 [foreignDoc.documentElement, 1]":true, + "Range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8], point 33 [foreignDoc.head, 0]":true, + "Range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8], point 34 [foreignDoc.body, 1]":true, + "Range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8], point 54 [foreignDoc, 0]":true, + "Range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8], point 55 [foreignDoc, 1]":true, + "Range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8], point 56 [foreignComment, 2]":true, + "Range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8], point 57 [foreignTextNode, 0]":true, + "Range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8], point 58 [foreignTextNode, 36]":true, + "Range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8], point 59 [xmlDoc, -1]":true, + "Range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8], point 60 [xmlDoc, 0]":true, + "Range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8], point 61 [xmlDoc, 1]":true, + "Range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8], point 62 [xmlDoc, 5]":true, + "Range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8], point 63 [xmlComment, 0]":true, + "Range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8], point 64 [xmlComment, 4]":true, + "Range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8], point 65 [processingInstruction, 0]":true, + "Range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8], point 66 [processingInstruction, 5]":true, + "Range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8], point 67 [processingInstruction, 9]":true, + "Range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8], point 70 [detachedForeignTextNode, 0]":true, + "Range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8], point 71 [detachedForeignTextNode, 8]":true, + "Range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8], point 72 [detachedXmlTextNode, 0]":true, + "Range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8], point 73 [detachedXmlTextNode, 8]":true, + "Range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8], point 74 [detachedProcessingInstruction, 12]":true, + "Range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8], point 77 [detachedForeignComment, 0]":true, + "Range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8], point 78 [detachedForeignComment, 4]":true, + "Range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8], point 79 [detachedXmlComment, 2]":true, + "Range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8], point 81 [foreignDocfrag, 0]":true, + "Range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8], point 82 [xmlDocfrag, 0]":true, + "Range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8], point 86 [foreignDoctype, 0]":true, + "Range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8], point 87 [xmlDoctype, 0]":true, + "Range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9], point 20 [foreignPara1.firstChild, 0]":true, + "Range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9], point 21 [foreignPara1.firstChild, 1]":true, + "Range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9], point 22 [foreignPara1.firstChild, 8]":true, + "Range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9], point 23 [foreignPara1.firstChild, 9]":true, + "Range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9], point 31 [foreignDoc.documentElement, 0]":true, + "Range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9], point 32 [foreignDoc.documentElement, 1]":true, + "Range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9], point 33 [foreignDoc.head, 0]":true, + "Range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9], point 34 [foreignDoc.body, 1]":true, + "Range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9], point 54 [foreignDoc, 0]":true, + "Range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9], point 55 [foreignDoc, 1]":true, + "Range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9], point 56 [foreignComment, 2]":true, + "Range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9], point 57 [foreignTextNode, 0]":true, + "Range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9], point 58 [foreignTextNode, 36]":true, + "Range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9], point 59 [xmlDoc, -1]":true, + "Range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9], point 60 [xmlDoc, 0]":true, + "Range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9], point 61 [xmlDoc, 1]":true, + "Range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9], point 62 [xmlDoc, 5]":true, + "Range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9], point 63 [xmlComment, 0]":true, + "Range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9], point 64 [xmlComment, 4]":true, + "Range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9], point 65 [processingInstruction, 0]":true, + "Range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9], point 66 [processingInstruction, 5]":true, + "Range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9], point 67 [processingInstruction, 9]":true, + "Range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9], point 70 [detachedForeignTextNode, 0]":true, + "Range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9], point 71 [detachedForeignTextNode, 8]":true, + "Range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9], point 72 [detachedXmlTextNode, 0]":true, + "Range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9], point 73 [detachedXmlTextNode, 8]":true, + "Range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9], point 74 [detachedProcessingInstruction, 12]":true, + "Range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9], point 77 [detachedForeignComment, 0]":true, + "Range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9], point 78 [detachedForeignComment, 4]":true, + "Range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9], point 79 [detachedXmlComment, 2]":true, + "Range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9], point 81 [foreignDocfrag, 0]":true, + "Range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9], point 82 [xmlDocfrag, 0]":true, + "Range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9], point 86 [foreignDoctype, 0]":true, + "Range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9], point 87 [xmlDoctype, 0]":true, + "Range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], point 20 [foreignPara1.firstChild, 0]":true, + "Range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], point 21 [foreignPara1.firstChild, 1]":true, + "Range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], point 22 [foreignPara1.firstChild, 8]":true, + "Range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], point 23 [foreignPara1.firstChild, 9]":true, + "Range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], point 31 [foreignDoc.documentElement, 0]":true, + "Range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], point 32 [foreignDoc.documentElement, 1]":true, + "Range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], point 33 [foreignDoc.head, 0]":true, + "Range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], point 34 [foreignDoc.body, 1]":true, + "Range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], point 54 [foreignDoc, 0]":true, + "Range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], point 55 [foreignDoc, 1]":true, + "Range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], point 56 [foreignComment, 2]":true, + "Range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], point 57 [foreignTextNode, 0]":true, + "Range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], point 58 [foreignTextNode, 36]":true, + "Range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], point 59 [xmlDoc, -1]":true, + "Range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], point 60 [xmlDoc, 0]":true, + "Range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], point 61 [xmlDoc, 1]":true, + "Range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], point 62 [xmlDoc, 5]":true, + "Range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], point 63 [xmlComment, 0]":true, + "Range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], point 64 [xmlComment, 4]":true, + "Range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], point 65 [processingInstruction, 0]":true, + "Range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], point 66 [processingInstruction, 5]":true, + "Range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], point 67 [processingInstruction, 9]":true, + "Range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], point 70 [detachedForeignTextNode, 0]":true, + "Range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], point 71 [detachedForeignTextNode, 8]":true, + "Range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], point 72 [detachedXmlTextNode, 0]":true, + "Range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], point 73 [detachedXmlTextNode, 8]":true, + "Range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], point 74 [detachedProcessingInstruction, 12]":true, + "Range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], point 77 [detachedForeignComment, 0]":true, + "Range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], point 78 [detachedForeignComment, 4]":true, + "Range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], point 79 [detachedXmlComment, 2]":true, + "Range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], point 81 [foreignDocfrag, 0]":true, + "Range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], point 82 [xmlDocfrag, 0]":true, + "Range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], point 86 [foreignDoctype, 0]":true, + "Range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], point 87 [xmlDoctype, 0]":true, + "Range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1], point 20 [foreignPara1.firstChild, 0]":true, + "Range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1], point 21 [foreignPara1.firstChild, 1]":true, + "Range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1], point 22 [foreignPara1.firstChild, 8]":true, + "Range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1], point 23 [foreignPara1.firstChild, 9]":true, + "Range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1], point 31 [foreignDoc.documentElement, 0]":true, + "Range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1], point 32 [foreignDoc.documentElement, 1]":true, + "Range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1], point 33 [foreignDoc.head, 0]":true, + "Range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1], point 34 [foreignDoc.body, 1]":true, + "Range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1], point 54 [foreignDoc, 0]":true, + "Range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1], point 55 [foreignDoc, 1]":true, + "Range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1], point 56 [foreignComment, 2]":true, + "Range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1], point 57 [foreignTextNode, 0]":true, + "Range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1], point 58 [foreignTextNode, 36]":true, + "Range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1], point 59 [xmlDoc, -1]":true, + "Range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1], point 60 [xmlDoc, 0]":true, + "Range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1], point 61 [xmlDoc, 1]":true, + "Range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1], point 62 [xmlDoc, 5]":true, + "Range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1], point 63 [xmlComment, 0]":true, + "Range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1], point 64 [xmlComment, 4]":true, + "Range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1], point 65 [processingInstruction, 0]":true, + "Range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1], point 66 [processingInstruction, 5]":true, + "Range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1], point 67 [processingInstruction, 9]":true, + "Range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1], point 70 [detachedForeignTextNode, 0]":true, + "Range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1], point 71 [detachedForeignTextNode, 8]":true, + "Range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1], point 72 [detachedXmlTextNode, 0]":true, + "Range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1], point 73 [detachedXmlTextNode, 8]":true, + "Range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1], point 74 [detachedProcessingInstruction, 12]":true, + "Range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1], point 77 [detachedForeignComment, 0]":true, + "Range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1], point 78 [detachedForeignComment, 4]":true, + "Range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1], point 79 [detachedXmlComment, 2]":true, + "Range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1], point 81 [foreignDocfrag, 0]":true, + "Range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1], point 82 [xmlDocfrag, 0]":true, + "Range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1], point 86 [foreignDoctype, 0]":true, + "Range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1], point 87 [xmlDoctype, 0]":true, + "Range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], point 20 [foreignPara1.firstChild, 0]":true, + "Range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], point 21 [foreignPara1.firstChild, 1]":true, + "Range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], point 22 [foreignPara1.firstChild, 8]":true, + "Range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], point 23 [foreignPara1.firstChild, 9]":true, + "Range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], point 31 [foreignDoc.documentElement, 0]":true, + "Range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], point 32 [foreignDoc.documentElement, 1]":true, + "Range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], point 33 [foreignDoc.head, 0]":true, + "Range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], point 34 [foreignDoc.body, 1]":true, + "Range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], point 54 [foreignDoc, 0]":true, + "Range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], point 55 [foreignDoc, 1]":true, + "Range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], point 56 [foreignComment, 2]":true, + "Range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], point 57 [foreignTextNode, 0]":true, + "Range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], point 58 [foreignTextNode, 36]":true, + "Range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], point 59 [xmlDoc, -1]":true, + "Range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], point 60 [xmlDoc, 0]":true, + "Range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], point 61 [xmlDoc, 1]":true, + "Range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], point 62 [xmlDoc, 5]":true, + "Range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], point 63 [xmlComment, 0]":true, + "Range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], point 64 [xmlComment, 4]":true, + "Range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], point 65 [processingInstruction, 0]":true, + "Range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], point 66 [processingInstruction, 5]":true, + "Range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], point 67 [processingInstruction, 9]":true, + "Range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], point 70 [detachedForeignTextNode, 0]":true, + "Range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], point 71 [detachedForeignTextNode, 8]":true, + "Range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], point 72 [detachedXmlTextNode, 0]":true, + "Range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], point 73 [detachedXmlTextNode, 8]":true, + "Range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], point 74 [detachedProcessingInstruction, 12]":true, + "Range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], point 77 [detachedForeignComment, 0]":true, + "Range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], point 78 [detachedForeignComment, 4]":true, + "Range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], point 79 [detachedXmlComment, 2]":true, + "Range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], point 81 [foreignDocfrag, 0]":true, + "Range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], point 82 [xmlDocfrag, 0]":true, + "Range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], point 86 [foreignDoctype, 0]":true, + "Range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], point 87 [xmlDoctype, 0]":true, + "Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], point 20 [foreignPara1.firstChild, 0]":true, + "Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], point 21 [foreignPara1.firstChild, 1]":true, + "Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], point 22 [foreignPara1.firstChild, 8]":true, + "Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], point 23 [foreignPara1.firstChild, 9]":true, + "Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], point 31 [foreignDoc.documentElement, 0]":true, + "Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], point 32 [foreignDoc.documentElement, 1]":true, + "Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], point 33 [foreignDoc.head, 0]":true, + "Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], point 34 [foreignDoc.body, 1]":true, + "Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], point 54 [foreignDoc, 0]":true, + "Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], point 55 [foreignDoc, 1]":true, + "Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], point 56 [foreignComment, 2]":true, + "Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], point 57 [foreignTextNode, 0]":true, + "Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], point 58 [foreignTextNode, 36]":true, + "Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], point 59 [xmlDoc, -1]":true, + "Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], point 60 [xmlDoc, 0]":true, + "Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], point 61 [xmlDoc, 1]":true, + "Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], point 62 [xmlDoc, 5]":true, + "Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], point 63 [xmlComment, 0]":true, + "Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], point 64 [xmlComment, 4]":true, + "Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], point 65 [processingInstruction, 0]":true, + "Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], point 66 [processingInstruction, 5]":true, + "Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], point 67 [processingInstruction, 9]":true, + "Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], point 70 [detachedForeignTextNode, 0]":true, + "Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], point 71 [detachedForeignTextNode, 8]":true, + "Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], point 72 [detachedXmlTextNode, 0]":true, + "Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], point 73 [detachedXmlTextNode, 8]":true, + "Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], point 74 [detachedProcessingInstruction, 12]":true, + "Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], point 77 [detachedForeignComment, 0]":true, + "Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], point 78 [detachedForeignComment, 4]":true, + "Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], point 79 [detachedXmlComment, 2]":true, + "Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], point 81 [foreignDocfrag, 0]":true, + "Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], point 82 [xmlDocfrag, 0]":true, + "Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], point 86 [foreignDoctype, 0]":true, + "Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], point 87 [xmlDoctype, 0]":true, + "Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1], point 20 [foreignPara1.firstChild, 0]":true, + "Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1], point 21 [foreignPara1.firstChild, 1]":true, + "Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1], point 22 [foreignPara1.firstChild, 8]":true, + "Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1], point 23 [foreignPara1.firstChild, 9]":true, + "Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1], point 31 [foreignDoc.documentElement, 0]":true, + "Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1], point 32 [foreignDoc.documentElement, 1]":true, + "Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1], point 33 [foreignDoc.head, 0]":true, + "Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1], point 34 [foreignDoc.body, 1]":true, + "Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1], point 54 [foreignDoc, 0]":true, + "Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1], point 55 [foreignDoc, 1]":true, + "Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1], point 56 [foreignComment, 2]":true, + "Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1], point 57 [foreignTextNode, 0]":true, + "Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1], point 58 [foreignTextNode, 36]":true, + "Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1], point 59 [xmlDoc, -1]":true, + "Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1], point 60 [xmlDoc, 0]":true, + "Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1], point 61 [xmlDoc, 1]":true, + "Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1], point 62 [xmlDoc, 5]":true, + "Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1], point 63 [xmlComment, 0]":true, + "Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1], point 64 [xmlComment, 4]":true, + "Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1], point 65 [processingInstruction, 0]":true, + "Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1], point 66 [processingInstruction, 5]":true, + "Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1], point 67 [processingInstruction, 9]":true, + "Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1], point 70 [detachedForeignTextNode, 0]":true, + "Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1], point 71 [detachedForeignTextNode, 8]":true, + "Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1], point 72 [detachedXmlTextNode, 0]":true, + "Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1], point 73 [detachedXmlTextNode, 8]":true, + "Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1], point 74 [detachedProcessingInstruction, 12]":true, + "Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1], point 77 [detachedForeignComment, 0]":true, + "Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1], point 78 [detachedForeignComment, 4]":true, + "Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1], point 79 [detachedXmlComment, 2]":true, + "Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1], point 81 [foreignDocfrag, 0]":true, + "Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1], point 82 [xmlDocfrag, 0]":true, + "Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1], point 86 [foreignDoctype, 0]":true, + "Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1], point 87 [xmlDoctype, 0]":true, + "Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], point 20 [foreignPara1.firstChild, 0]":true, + "Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], point 21 [foreignPara1.firstChild, 1]":true, + "Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], point 22 [foreignPara1.firstChild, 8]":true, + "Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], point 23 [foreignPara1.firstChild, 9]":true, + "Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], point 31 [foreignDoc.documentElement, 0]":true, + "Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], point 32 [foreignDoc.documentElement, 1]":true, + "Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], point 33 [foreignDoc.head, 0]":true, + "Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], point 34 [foreignDoc.body, 1]":true, + "Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], point 54 [foreignDoc, 0]":true, + "Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], point 55 [foreignDoc, 1]":true, + "Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], point 56 [foreignComment, 2]":true, + "Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], point 57 [foreignTextNode, 0]":true, + "Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], point 58 [foreignTextNode, 36]":true, + "Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], point 59 [xmlDoc, -1]":true, + "Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], point 60 [xmlDoc, 0]":true, + "Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], point 61 [xmlDoc, 1]":true, + "Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], point 62 [xmlDoc, 5]":true, + "Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], point 63 [xmlComment, 0]":true, + "Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], point 64 [xmlComment, 4]":true, + "Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], point 65 [processingInstruction, 0]":true, + "Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], point 66 [processingInstruction, 5]":true, + "Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], point 67 [processingInstruction, 9]":true, + "Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], point 70 [detachedForeignTextNode, 0]":true, + "Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], point 71 [detachedForeignTextNode, 8]":true, + "Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], point 72 [detachedXmlTextNode, 0]":true, + "Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], point 73 [detachedXmlTextNode, 8]":true, + "Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], point 74 [detachedProcessingInstruction, 12]":true, + "Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], point 77 [detachedForeignComment, 0]":true, + "Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], point 78 [detachedForeignComment, 4]":true, + "Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], point 79 [detachedXmlComment, 2]":true, + "Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], point 81 [foreignDocfrag, 0]":true, + "Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], point 82 [xmlDocfrag, 0]":true, + "Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], point 86 [foreignDoctype, 0]":true, + "Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], point 87 [xmlDoctype, 0]":true, + "Range 15 [document.documentElement, 0, document.documentElement, 1], point 20 [foreignPara1.firstChild, 0]":true, + "Range 15 [document.documentElement, 0, document.documentElement, 1], point 21 [foreignPara1.firstChild, 1]":true, + "Range 15 [document.documentElement, 0, document.documentElement, 1], point 22 [foreignPara1.firstChild, 8]":true, + "Range 15 [document.documentElement, 0, document.documentElement, 1], point 23 [foreignPara1.firstChild, 9]":true, + "Range 15 [document.documentElement, 0, document.documentElement, 1], point 31 [foreignDoc.documentElement, 0]":true, + "Range 15 [document.documentElement, 0, document.documentElement, 1], point 32 [foreignDoc.documentElement, 1]":true, + "Range 15 [document.documentElement, 0, document.documentElement, 1], point 33 [foreignDoc.head, 0]":true, + "Range 15 [document.documentElement, 0, document.documentElement, 1], point 34 [foreignDoc.body, 1]":true, + "Range 15 [document.documentElement, 0, document.documentElement, 1], point 54 [foreignDoc, 0]":true, + "Range 15 [document.documentElement, 0, document.documentElement, 1], point 55 [foreignDoc, 1]":true, + "Range 15 [document.documentElement, 0, document.documentElement, 1], point 56 [foreignComment, 2]":true, + "Range 15 [document.documentElement, 0, document.documentElement, 1], point 57 [foreignTextNode, 0]":true, + "Range 15 [document.documentElement, 0, document.documentElement, 1], point 58 [foreignTextNode, 36]":true, + "Range 15 [document.documentElement, 0, document.documentElement, 1], point 59 [xmlDoc, -1]":true, + "Range 15 [document.documentElement, 0, document.documentElement, 1], point 60 [xmlDoc, 0]":true, + "Range 15 [document.documentElement, 0, document.documentElement, 1], point 61 [xmlDoc, 1]":true, + "Range 15 [document.documentElement, 0, document.documentElement, 1], point 62 [xmlDoc, 5]":true, + "Range 15 [document.documentElement, 0, document.documentElement, 1], point 63 [xmlComment, 0]":true, + "Range 15 [document.documentElement, 0, document.documentElement, 1], point 64 [xmlComment, 4]":true, + "Range 15 [document.documentElement, 0, document.documentElement, 1], point 65 [processingInstruction, 0]":true, + "Range 15 [document.documentElement, 0, document.documentElement, 1], point 66 [processingInstruction, 5]":true, + "Range 15 [document.documentElement, 0, document.documentElement, 1], point 67 [processingInstruction, 9]":true, + "Range 15 [document.documentElement, 0, document.documentElement, 1], point 70 [detachedForeignTextNode, 0]":true, + "Range 15 [document.documentElement, 0, document.documentElement, 1], point 71 [detachedForeignTextNode, 8]":true, + "Range 15 [document.documentElement, 0, document.documentElement, 1], point 72 [detachedXmlTextNode, 0]":true, + "Range 15 [document.documentElement, 0, document.documentElement, 1], point 73 [detachedXmlTextNode, 8]":true, + "Range 15 [document.documentElement, 0, document.documentElement, 1], point 74 [detachedProcessingInstruction, 12]":true, + "Range 15 [document.documentElement, 0, document.documentElement, 1], point 77 [detachedForeignComment, 0]":true, + "Range 15 [document.documentElement, 0, document.documentElement, 1], point 78 [detachedForeignComment, 4]":true, + "Range 15 [document.documentElement, 0, document.documentElement, 1], point 79 [detachedXmlComment, 2]":true, + "Range 15 [document.documentElement, 0, document.documentElement, 1], point 81 [foreignDocfrag, 0]":true, + "Range 15 [document.documentElement, 0, document.documentElement, 1], point 82 [xmlDocfrag, 0]":true, + "Range 15 [document.documentElement, 0, document.documentElement, 1], point 86 [foreignDoctype, 0]":true, + "Range 15 [document.documentElement, 0, document.documentElement, 1], point 87 [xmlDoctype, 0]":true, + "Range 16 [document.documentElement, 0, document.documentElement, 2], point 20 [foreignPara1.firstChild, 0]":true, + "Range 16 [document.documentElement, 0, document.documentElement, 2], point 21 [foreignPara1.firstChild, 1]":true, + "Range 16 [document.documentElement, 0, document.documentElement, 2], point 22 [foreignPara1.firstChild, 8]":true, + "Range 16 [document.documentElement, 0, document.documentElement, 2], point 23 [foreignPara1.firstChild, 9]":true, + "Range 16 [document.documentElement, 0, document.documentElement, 2], point 31 [foreignDoc.documentElement, 0]":true, + "Range 16 [document.documentElement, 0, document.documentElement, 2], point 32 [foreignDoc.documentElement, 1]":true, + "Range 16 [document.documentElement, 0, document.documentElement, 2], point 33 [foreignDoc.head, 0]":true, + "Range 16 [document.documentElement, 0, document.documentElement, 2], point 34 [foreignDoc.body, 1]":true, + "Range 16 [document.documentElement, 0, document.documentElement, 2], point 54 [foreignDoc, 0]":true, + "Range 16 [document.documentElement, 0, document.documentElement, 2], point 55 [foreignDoc, 1]":true, + "Range 16 [document.documentElement, 0, document.documentElement, 2], point 56 [foreignComment, 2]":true, + "Range 16 [document.documentElement, 0, document.documentElement, 2], point 57 [foreignTextNode, 0]":true, + "Range 16 [document.documentElement, 0, document.documentElement, 2], point 58 [foreignTextNode, 36]":true, + "Range 16 [document.documentElement, 0, document.documentElement, 2], point 59 [xmlDoc, -1]":true, + "Range 16 [document.documentElement, 0, document.documentElement, 2], point 60 [xmlDoc, 0]":true, + "Range 16 [document.documentElement, 0, document.documentElement, 2], point 61 [xmlDoc, 1]":true, + "Range 16 [document.documentElement, 0, document.documentElement, 2], point 62 [xmlDoc, 5]":true, + "Range 16 [document.documentElement, 0, document.documentElement, 2], point 63 [xmlComment, 0]":true, + "Range 16 [document.documentElement, 0, document.documentElement, 2], point 64 [xmlComment, 4]":true, + "Range 16 [document.documentElement, 0, document.documentElement, 2], point 65 [processingInstruction, 0]":true, + "Range 16 [document.documentElement, 0, document.documentElement, 2], point 66 [processingInstruction, 5]":true, + "Range 16 [document.documentElement, 0, document.documentElement, 2], point 67 [processingInstruction, 9]":true, + "Range 16 [document.documentElement, 0, document.documentElement, 2], point 70 [detachedForeignTextNode, 0]":true, + "Range 16 [document.documentElement, 0, document.documentElement, 2], point 71 [detachedForeignTextNode, 8]":true, + "Range 16 [document.documentElement, 0, document.documentElement, 2], point 72 [detachedXmlTextNode, 0]":true, + "Range 16 [document.documentElement, 0, document.documentElement, 2], point 73 [detachedXmlTextNode, 8]":true, + "Range 16 [document.documentElement, 0, document.documentElement, 2], point 74 [detachedProcessingInstruction, 12]":true, + "Range 16 [document.documentElement, 0, document.documentElement, 2], point 77 [detachedForeignComment, 0]":true, + "Range 16 [document.documentElement, 0, document.documentElement, 2], point 78 [detachedForeignComment, 4]":true, + "Range 16 [document.documentElement, 0, document.documentElement, 2], point 79 [detachedXmlComment, 2]":true, + "Range 16 [document.documentElement, 0, document.documentElement, 2], point 81 [foreignDocfrag, 0]":true, + "Range 16 [document.documentElement, 0, document.documentElement, 2], point 82 [xmlDocfrag, 0]":true, + "Range 16 [document.documentElement, 0, document.documentElement, 2], point 86 [foreignDoctype, 0]":true, + "Range 16 [document.documentElement, 0, document.documentElement, 2], point 87 [xmlDoctype, 0]":true, + "Range 17 [document.documentElement, 1, document.documentElement, 2], point 20 [foreignPara1.firstChild, 0]":true, + "Range 17 [document.documentElement, 1, document.documentElement, 2], point 21 [foreignPara1.firstChild, 1]":true, + "Range 17 [document.documentElement, 1, document.documentElement, 2], point 22 [foreignPara1.firstChild, 8]":true, + "Range 17 [document.documentElement, 1, document.documentElement, 2], point 23 [foreignPara1.firstChild, 9]":true, + "Range 17 [document.documentElement, 1, document.documentElement, 2], point 31 [foreignDoc.documentElement, 0]":true, + "Range 17 [document.documentElement, 1, document.documentElement, 2], point 32 [foreignDoc.documentElement, 1]":true, + "Range 17 [document.documentElement, 1, document.documentElement, 2], point 33 [foreignDoc.head, 0]":true, + "Range 17 [document.documentElement, 1, document.documentElement, 2], point 34 [foreignDoc.body, 1]":true, + "Range 17 [document.documentElement, 1, document.documentElement, 2], point 54 [foreignDoc, 0]":true, + "Range 17 [document.documentElement, 1, document.documentElement, 2], point 55 [foreignDoc, 1]":true, + "Range 17 [document.documentElement, 1, document.documentElement, 2], point 56 [foreignComment, 2]":true, + "Range 17 [document.documentElement, 1, document.documentElement, 2], point 57 [foreignTextNode, 0]":true, + "Range 17 [document.documentElement, 1, document.documentElement, 2], point 58 [foreignTextNode, 36]":true, + "Range 17 [document.documentElement, 1, document.documentElement, 2], point 59 [xmlDoc, -1]":true, + "Range 17 [document.documentElement, 1, document.documentElement, 2], point 60 [xmlDoc, 0]":true, + "Range 17 [document.documentElement, 1, document.documentElement, 2], point 61 [xmlDoc, 1]":true, + "Range 17 [document.documentElement, 1, document.documentElement, 2], point 62 [xmlDoc, 5]":true, + "Range 17 [document.documentElement, 1, document.documentElement, 2], point 63 [xmlComment, 0]":true, + "Range 17 [document.documentElement, 1, document.documentElement, 2], point 64 [xmlComment, 4]":true, + "Range 17 [document.documentElement, 1, document.documentElement, 2], point 65 [processingInstruction, 0]":true, + "Range 17 [document.documentElement, 1, document.documentElement, 2], point 66 [processingInstruction, 5]":true, + "Range 17 [document.documentElement, 1, document.documentElement, 2], point 67 [processingInstruction, 9]":true, + "Range 17 [document.documentElement, 1, document.documentElement, 2], point 70 [detachedForeignTextNode, 0]":true, + "Range 17 [document.documentElement, 1, document.documentElement, 2], point 71 [detachedForeignTextNode, 8]":true, + "Range 17 [document.documentElement, 1, document.documentElement, 2], point 72 [detachedXmlTextNode, 0]":true, + "Range 17 [document.documentElement, 1, document.documentElement, 2], point 73 [detachedXmlTextNode, 8]":true, + "Range 17 [document.documentElement, 1, document.documentElement, 2], point 74 [detachedProcessingInstruction, 12]":true, + "Range 17 [document.documentElement, 1, document.documentElement, 2], point 77 [detachedForeignComment, 0]":true, + "Range 17 [document.documentElement, 1, document.documentElement, 2], point 78 [detachedForeignComment, 4]":true, + "Range 17 [document.documentElement, 1, document.documentElement, 2], point 79 [detachedXmlComment, 2]":true, + "Range 17 [document.documentElement, 1, document.documentElement, 2], point 81 [foreignDocfrag, 0]":true, + "Range 17 [document.documentElement, 1, document.documentElement, 2], point 82 [xmlDocfrag, 0]":true, + "Range 17 [document.documentElement, 1, document.documentElement, 2], point 86 [foreignDoctype, 0]":true, + "Range 17 [document.documentElement, 1, document.documentElement, 2], point 87 [xmlDoctype, 0]":true, + "Range 18 [document.head, 1, document.head, 1], point 20 [foreignPara1.firstChild, 0]":true, + "Range 18 [document.head, 1, document.head, 1], point 21 [foreignPara1.firstChild, 1]":true, + "Range 18 [document.head, 1, document.head, 1], point 22 [foreignPara1.firstChild, 8]":true, + "Range 18 [document.head, 1, document.head, 1], point 23 [foreignPara1.firstChild, 9]":true, + "Range 18 [document.head, 1, document.head, 1], point 31 [foreignDoc.documentElement, 0]":true, + "Range 18 [document.head, 1, document.head, 1], point 32 [foreignDoc.documentElement, 1]":true, + "Range 18 [document.head, 1, document.head, 1], point 33 [foreignDoc.head, 0]":true, + "Range 18 [document.head, 1, document.head, 1], point 34 [foreignDoc.body, 1]":true, + "Range 18 [document.head, 1, document.head, 1], point 54 [foreignDoc, 0]":true, + "Range 18 [document.head, 1, document.head, 1], point 55 [foreignDoc, 1]":true, + "Range 18 [document.head, 1, document.head, 1], point 56 [foreignComment, 2]":true, + "Range 18 [document.head, 1, document.head, 1], point 57 [foreignTextNode, 0]":true, + "Range 18 [document.head, 1, document.head, 1], point 58 [foreignTextNode, 36]":true, + "Range 18 [document.head, 1, document.head, 1], point 59 [xmlDoc, -1]":true, + "Range 18 [document.head, 1, document.head, 1], point 60 [xmlDoc, 0]":true, + "Range 18 [document.head, 1, document.head, 1], point 61 [xmlDoc, 1]":true, + "Range 18 [document.head, 1, document.head, 1], point 62 [xmlDoc, 5]":true, + "Range 18 [document.head, 1, document.head, 1], point 63 [xmlComment, 0]":true, + "Range 18 [document.head, 1, document.head, 1], point 64 [xmlComment, 4]":true, + "Range 18 [document.head, 1, document.head, 1], point 65 [processingInstruction, 0]":true, + "Range 18 [document.head, 1, document.head, 1], point 66 [processingInstruction, 5]":true, + "Range 18 [document.head, 1, document.head, 1], point 67 [processingInstruction, 9]":true, + "Range 18 [document.head, 1, document.head, 1], point 70 [detachedForeignTextNode, 0]":true, + "Range 18 [document.head, 1, document.head, 1], point 71 [detachedForeignTextNode, 8]":true, + "Range 18 [document.head, 1, document.head, 1], point 72 [detachedXmlTextNode, 0]":true, + "Range 18 [document.head, 1, document.head, 1], point 73 [detachedXmlTextNode, 8]":true, + "Range 18 [document.head, 1, document.head, 1], point 74 [detachedProcessingInstruction, 12]":true, + "Range 18 [document.head, 1, document.head, 1], point 77 [detachedForeignComment, 0]":true, + "Range 18 [document.head, 1, document.head, 1], point 78 [detachedForeignComment, 4]":true, + "Range 18 [document.head, 1, document.head, 1], point 79 [detachedXmlComment, 2]":true, + "Range 18 [document.head, 1, document.head, 1], point 81 [foreignDocfrag, 0]":true, + "Range 18 [document.head, 1, document.head, 1], point 82 [xmlDocfrag, 0]":true, + "Range 18 [document.head, 1, document.head, 1], point 86 [foreignDoctype, 0]":true, + "Range 18 [document.head, 1, document.head, 1], point 87 [xmlDoctype, 0]":true, + "Range 19 [document.body, 0, document.body, 1], point 20 [foreignPara1.firstChild, 0]":true, + "Range 19 [document.body, 0, document.body, 1], point 21 [foreignPara1.firstChild, 1]":true, + "Range 19 [document.body, 0, document.body, 1], point 22 [foreignPara1.firstChild, 8]":true, + "Range 19 [document.body, 0, document.body, 1], point 23 [foreignPara1.firstChild, 9]":true, + "Range 19 [document.body, 0, document.body, 1], point 31 [foreignDoc.documentElement, 0]":true, + "Range 19 [document.body, 0, document.body, 1], point 32 [foreignDoc.documentElement, 1]":true, + "Range 19 [document.body, 0, document.body, 1], point 33 [foreignDoc.head, 0]":true, + "Range 19 [document.body, 0, document.body, 1], point 34 [foreignDoc.body, 1]":true, + "Range 19 [document.body, 0, document.body, 1], point 54 [foreignDoc, 0]":true, + "Range 19 [document.body, 0, document.body, 1], point 55 [foreignDoc, 1]":true, + "Range 19 [document.body, 0, document.body, 1], point 56 [foreignComment, 2]":true, + "Range 19 [document.body, 0, document.body, 1], point 57 [foreignTextNode, 0]":true, + "Range 19 [document.body, 0, document.body, 1], point 58 [foreignTextNode, 36]":true, + "Range 19 [document.body, 0, document.body, 1], point 59 [xmlDoc, -1]":true, + "Range 19 [document.body, 0, document.body, 1], point 60 [xmlDoc, 0]":true, + "Range 19 [document.body, 0, document.body, 1], point 61 [xmlDoc, 1]":true, + "Range 19 [document.body, 0, document.body, 1], point 62 [xmlDoc, 5]":true, + "Range 19 [document.body, 0, document.body, 1], point 63 [xmlComment, 0]":true, + "Range 19 [document.body, 0, document.body, 1], point 64 [xmlComment, 4]":true, + "Range 19 [document.body, 0, document.body, 1], point 65 [processingInstruction, 0]":true, + "Range 19 [document.body, 0, document.body, 1], point 66 [processingInstruction, 5]":true, + "Range 19 [document.body, 0, document.body, 1], point 67 [processingInstruction, 9]":true, + "Range 19 [document.body, 0, document.body, 1], point 70 [detachedForeignTextNode, 0]":true, + "Range 19 [document.body, 0, document.body, 1], point 71 [detachedForeignTextNode, 8]":true, + "Range 19 [document.body, 0, document.body, 1], point 72 [detachedXmlTextNode, 0]":true, + "Range 19 [document.body, 0, document.body, 1], point 73 [detachedXmlTextNode, 8]":true, + "Range 19 [document.body, 0, document.body, 1], point 74 [detachedProcessingInstruction, 12]":true, + "Range 19 [document.body, 0, document.body, 1], point 77 [detachedForeignComment, 0]":true, + "Range 19 [document.body, 0, document.body, 1], point 78 [detachedForeignComment, 4]":true, + "Range 19 [document.body, 0, document.body, 1], point 79 [detachedXmlComment, 2]":true, + "Range 19 [document.body, 0, document.body, 1], point 81 [foreignDocfrag, 0]":true, + "Range 19 [document.body, 0, document.body, 1], point 82 [xmlDocfrag, 0]":true, + "Range 19 [document.body, 0, document.body, 1], point 86 [foreignDoctype, 0]":true, + "Range 19 [document.body, 0, document.body, 1], point 87 [xmlDoctype, 0]":true, + "Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], point 20 [foreignPara1.firstChild, 0]":true, + "Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], point 21 [foreignPara1.firstChild, 1]":true, + "Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], point 22 [foreignPara1.firstChild, 8]":true, + "Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], point 23 [foreignPara1.firstChild, 9]":true, + "Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], point 31 [foreignDoc.documentElement, 0]":true, + "Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], point 32 [foreignDoc.documentElement, 1]":true, + "Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], point 33 [foreignDoc.head, 0]":true, + "Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], point 34 [foreignDoc.body, 1]":true, + "Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], point 54 [foreignDoc, 0]":true, + "Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], point 55 [foreignDoc, 1]":true, + "Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], point 56 [foreignComment, 2]":true, + "Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], point 57 [foreignTextNode, 0]":true, + "Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], point 58 [foreignTextNode, 36]":true, + "Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], point 59 [xmlDoc, -1]":true, + "Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], point 60 [xmlDoc, 0]":true, + "Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], point 61 [xmlDoc, 1]":true, + "Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], point 62 [xmlDoc, 5]":true, + "Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], point 63 [xmlComment, 0]":true, + "Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], point 64 [xmlComment, 4]":true, + "Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], point 65 [processingInstruction, 0]":true, + "Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], point 66 [processingInstruction, 5]":true, + "Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], point 67 [processingInstruction, 9]":true, + "Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], point 70 [detachedForeignTextNode, 0]":true, + "Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], point 71 [detachedForeignTextNode, 8]":true, + "Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], point 72 [detachedXmlTextNode, 0]":true, + "Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], point 73 [detachedXmlTextNode, 8]":true, + "Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], point 74 [detachedProcessingInstruction, 12]":true, + "Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], point 77 [detachedForeignComment, 0]":true, + "Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], point 78 [detachedForeignComment, 4]":true, + "Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], point 79 [detachedXmlComment, 2]":true, + "Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], point 81 [foreignDocfrag, 0]":true, + "Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], point 82 [xmlDocfrag, 0]":true, + "Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], point 86 [foreignDoctype, 0]":true, + "Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], point 87 [xmlDoctype, 0]":true, + "Range 21 [foreignDoc.head, 1, foreignDoc.head, 1], point 20 [foreignPara1.firstChild, 0]":true, + "Range 21 [foreignDoc.head, 1, foreignDoc.head, 1], point 21 [foreignPara1.firstChild, 1]":true, + "Range 21 [foreignDoc.head, 1, foreignDoc.head, 1], point 22 [foreignPara1.firstChild, 8]":true, + "Range 21 [foreignDoc.head, 1, foreignDoc.head, 1], point 23 [foreignPara1.firstChild, 9]":true, + "Range 21 [foreignDoc.head, 1, foreignDoc.head, 1], point 31 [foreignDoc.documentElement, 0]":true, + "Range 21 [foreignDoc.head, 1, foreignDoc.head, 1], point 32 [foreignDoc.documentElement, 1]":true, + "Range 21 [foreignDoc.head, 1, foreignDoc.head, 1], point 33 [foreignDoc.head, 0]":true, + "Range 21 [foreignDoc.head, 1, foreignDoc.head, 1], point 34 [foreignDoc.body, 1]":true, + "Range 21 [foreignDoc.head, 1, foreignDoc.head, 1], point 54 [foreignDoc, 0]":true, + "Range 21 [foreignDoc.head, 1, foreignDoc.head, 1], point 55 [foreignDoc, 1]":true, + "Range 21 [foreignDoc.head, 1, foreignDoc.head, 1], point 56 [foreignComment, 2]":true, + "Range 21 [foreignDoc.head, 1, foreignDoc.head, 1], point 57 [foreignTextNode, 0]":true, + "Range 21 [foreignDoc.head, 1, foreignDoc.head, 1], point 58 [foreignTextNode, 36]":true, + "Range 21 [foreignDoc.head, 1, foreignDoc.head, 1], point 59 [xmlDoc, -1]":true, + "Range 21 [foreignDoc.head, 1, foreignDoc.head, 1], point 60 [xmlDoc, 0]":true, + "Range 21 [foreignDoc.head, 1, foreignDoc.head, 1], point 61 [xmlDoc, 1]":true, + "Range 21 [foreignDoc.head, 1, foreignDoc.head, 1], point 62 [xmlDoc, 5]":true, + "Range 21 [foreignDoc.head, 1, foreignDoc.head, 1], point 63 [xmlComment, 0]":true, + "Range 21 [foreignDoc.head, 1, foreignDoc.head, 1], point 64 [xmlComment, 4]":true, + "Range 21 [foreignDoc.head, 1, foreignDoc.head, 1], point 65 [processingInstruction, 0]":true, + "Range 21 [foreignDoc.head, 1, foreignDoc.head, 1], point 66 [processingInstruction, 5]":true, + "Range 21 [foreignDoc.head, 1, foreignDoc.head, 1], point 67 [processingInstruction, 9]":true, + "Range 21 [foreignDoc.head, 1, foreignDoc.head, 1], point 70 [detachedForeignTextNode, 0]":true, + "Range 21 [foreignDoc.head, 1, foreignDoc.head, 1], point 71 [detachedForeignTextNode, 8]":true, + "Range 21 [foreignDoc.head, 1, foreignDoc.head, 1], point 72 [detachedXmlTextNode, 0]":true, + "Range 21 [foreignDoc.head, 1, foreignDoc.head, 1], point 73 [detachedXmlTextNode, 8]":true, + "Range 21 [foreignDoc.head, 1, foreignDoc.head, 1], point 74 [detachedProcessingInstruction, 12]":true, + "Range 21 [foreignDoc.head, 1, foreignDoc.head, 1], point 77 [detachedForeignComment, 0]":true, + "Range 21 [foreignDoc.head, 1, foreignDoc.head, 1], point 78 [detachedForeignComment, 4]":true, + "Range 21 [foreignDoc.head, 1, foreignDoc.head, 1], point 79 [detachedXmlComment, 2]":true, + "Range 21 [foreignDoc.head, 1, foreignDoc.head, 1], point 81 [foreignDocfrag, 0]":true, + "Range 21 [foreignDoc.head, 1, foreignDoc.head, 1], point 82 [xmlDocfrag, 0]":true, + "Range 21 [foreignDoc.head, 1, foreignDoc.head, 1], point 86 [foreignDoctype, 0]":true, + "Range 21 [foreignDoc.head, 1, foreignDoc.head, 1], point 87 [xmlDoctype, 0]":true, + "Range 22 [foreignDoc.body, 0, foreignDoc.body, 0], point 20 [foreignPara1.firstChild, 0]":true, + "Range 22 [foreignDoc.body, 0, foreignDoc.body, 0], point 21 [foreignPara1.firstChild, 1]":true, + "Range 22 [foreignDoc.body, 0, foreignDoc.body, 0], point 22 [foreignPara1.firstChild, 8]":true, + "Range 22 [foreignDoc.body, 0, foreignDoc.body, 0], point 23 [foreignPara1.firstChild, 9]":true, + "Range 22 [foreignDoc.body, 0, foreignDoc.body, 0], point 31 [foreignDoc.documentElement, 0]":true, + "Range 22 [foreignDoc.body, 0, foreignDoc.body, 0], point 32 [foreignDoc.documentElement, 1]":true, + "Range 22 [foreignDoc.body, 0, foreignDoc.body, 0], point 33 [foreignDoc.head, 0]":true, + "Range 22 [foreignDoc.body, 0, foreignDoc.body, 0], point 34 [foreignDoc.body, 1]":true, + "Range 22 [foreignDoc.body, 0, foreignDoc.body, 0], point 54 [foreignDoc, 0]":true, + "Range 22 [foreignDoc.body, 0, foreignDoc.body, 0], point 55 [foreignDoc, 1]":true, + "Range 22 [foreignDoc.body, 0, foreignDoc.body, 0], point 56 [foreignComment, 2]":true, + "Range 22 [foreignDoc.body, 0, foreignDoc.body, 0], point 57 [foreignTextNode, 0]":true, + "Range 22 [foreignDoc.body, 0, foreignDoc.body, 0], point 58 [foreignTextNode, 36]":true, + "Range 22 [foreignDoc.body, 0, foreignDoc.body, 0], point 59 [xmlDoc, -1]":true, + "Range 22 [foreignDoc.body, 0, foreignDoc.body, 0], point 60 [xmlDoc, 0]":true, + "Range 22 [foreignDoc.body, 0, foreignDoc.body, 0], point 61 [xmlDoc, 1]":true, + "Range 22 [foreignDoc.body, 0, foreignDoc.body, 0], point 62 [xmlDoc, 5]":true, + "Range 22 [foreignDoc.body, 0, foreignDoc.body, 0], point 63 [xmlComment, 0]":true, + "Range 22 [foreignDoc.body, 0, foreignDoc.body, 0], point 64 [xmlComment, 4]":true, + "Range 22 [foreignDoc.body, 0, foreignDoc.body, 0], point 65 [processingInstruction, 0]":true, + "Range 22 [foreignDoc.body, 0, foreignDoc.body, 0], point 66 [processingInstruction, 5]":true, + "Range 22 [foreignDoc.body, 0, foreignDoc.body, 0], point 67 [processingInstruction, 9]":true, + "Range 22 [foreignDoc.body, 0, foreignDoc.body, 0], point 70 [detachedForeignTextNode, 0]":true, + "Range 22 [foreignDoc.body, 0, foreignDoc.body, 0], point 71 [detachedForeignTextNode, 8]":true, + "Range 22 [foreignDoc.body, 0, foreignDoc.body, 0], point 72 [detachedXmlTextNode, 0]":true, + "Range 22 [foreignDoc.body, 0, foreignDoc.body, 0], point 73 [detachedXmlTextNode, 8]":true, + "Range 22 [foreignDoc.body, 0, foreignDoc.body, 0], point 74 [detachedProcessingInstruction, 12]":true, + "Range 22 [foreignDoc.body, 0, foreignDoc.body, 0], point 77 [detachedForeignComment, 0]":true, + "Range 22 [foreignDoc.body, 0, foreignDoc.body, 0], point 78 [detachedForeignComment, 4]":true, + "Range 22 [foreignDoc.body, 0, foreignDoc.body, 0], point 79 [detachedXmlComment, 2]":true, + "Range 22 [foreignDoc.body, 0, foreignDoc.body, 0], point 81 [foreignDocfrag, 0]":true, + "Range 22 [foreignDoc.body, 0, foreignDoc.body, 0], point 82 [xmlDocfrag, 0]":true, + "Range 22 [foreignDoc.body, 0, foreignDoc.body, 0], point 86 [foreignDoctype, 0]":true, + "Range 22 [foreignDoc.body, 0, foreignDoc.body, 0], point 87 [xmlDoctype, 0]":true, + "Range 23 [paras[0], 0, paras[0], 0], point 20 [foreignPara1.firstChild, 0]":true, + "Range 23 [paras[0], 0, paras[0], 0], point 21 [foreignPara1.firstChild, 1]":true, + "Range 23 [paras[0], 0, paras[0], 0], point 22 [foreignPara1.firstChild, 8]":true, + "Range 23 [paras[0], 0, paras[0], 0], point 23 [foreignPara1.firstChild, 9]":true, + "Range 23 [paras[0], 0, paras[0], 0], point 31 [foreignDoc.documentElement, 0]":true, + "Range 23 [paras[0], 0, paras[0], 0], point 32 [foreignDoc.documentElement, 1]":true, + "Range 23 [paras[0], 0, paras[0], 0], point 33 [foreignDoc.head, 0]":true, + "Range 23 [paras[0], 0, paras[0], 0], point 34 [foreignDoc.body, 1]":true, + "Range 23 [paras[0], 0, paras[0], 0], point 54 [foreignDoc, 0]":true, + "Range 23 [paras[0], 0, paras[0], 0], point 55 [foreignDoc, 1]":true, + "Range 23 [paras[0], 0, paras[0], 0], point 56 [foreignComment, 2]":true, + "Range 23 [paras[0], 0, paras[0], 0], point 57 [foreignTextNode, 0]":true, + "Range 23 [paras[0], 0, paras[0], 0], point 58 [foreignTextNode, 36]":true, + "Range 23 [paras[0], 0, paras[0], 0], point 59 [xmlDoc, -1]":true, + "Range 23 [paras[0], 0, paras[0], 0], point 60 [xmlDoc, 0]":true, + "Range 23 [paras[0], 0, paras[0], 0], point 61 [xmlDoc, 1]":true, + "Range 23 [paras[0], 0, paras[0], 0], point 62 [xmlDoc, 5]":true, + "Range 23 [paras[0], 0, paras[0], 0], point 63 [xmlComment, 0]":true, + "Range 23 [paras[0], 0, paras[0], 0], point 64 [xmlComment, 4]":true, + "Range 23 [paras[0], 0, paras[0], 0], point 65 [processingInstruction, 0]":true, + "Range 23 [paras[0], 0, paras[0], 0], point 66 [processingInstruction, 5]":true, + "Range 23 [paras[0], 0, paras[0], 0], point 67 [processingInstruction, 9]":true, + "Range 23 [paras[0], 0, paras[0], 0], point 70 [detachedForeignTextNode, 0]":true, + "Range 23 [paras[0], 0, paras[0], 0], point 71 [detachedForeignTextNode, 8]":true, + "Range 23 [paras[0], 0, paras[0], 0], point 72 [detachedXmlTextNode, 0]":true, + "Range 23 [paras[0], 0, paras[0], 0], point 73 [detachedXmlTextNode, 8]":true, + "Range 23 [paras[0], 0, paras[0], 0], point 74 [detachedProcessingInstruction, 12]":true, + "Range 23 [paras[0], 0, paras[0], 0], point 77 [detachedForeignComment, 0]":true, + "Range 23 [paras[0], 0, paras[0], 0], point 78 [detachedForeignComment, 4]":true, + "Range 23 [paras[0], 0, paras[0], 0], point 79 [detachedXmlComment, 2]":true, + "Range 23 [paras[0], 0, paras[0], 0], point 81 [foreignDocfrag, 0]":true, + "Range 23 [paras[0], 0, paras[0], 0], point 82 [xmlDocfrag, 0]":true, + "Range 23 [paras[0], 0, paras[0], 0], point 86 [foreignDoctype, 0]":true, + "Range 23 [paras[0], 0, paras[0], 0], point 87 [xmlDoctype, 0]":true, + "Range 24 [paras[0], 0, paras[0], 1], point 20 [foreignPara1.firstChild, 0]":true, + "Range 24 [paras[0], 0, paras[0], 1], point 21 [foreignPara1.firstChild, 1]":true, + "Range 24 [paras[0], 0, paras[0], 1], point 22 [foreignPara1.firstChild, 8]":true, + "Range 24 [paras[0], 0, paras[0], 1], point 23 [foreignPara1.firstChild, 9]":true, + "Range 24 [paras[0], 0, paras[0], 1], point 31 [foreignDoc.documentElement, 0]":true, + "Range 24 [paras[0], 0, paras[0], 1], point 32 [foreignDoc.documentElement, 1]":true, + "Range 24 [paras[0], 0, paras[0], 1], point 33 [foreignDoc.head, 0]":true, + "Range 24 [paras[0], 0, paras[0], 1], point 34 [foreignDoc.body, 1]":true, + "Range 24 [paras[0], 0, paras[0], 1], point 54 [foreignDoc, 0]":true, + "Range 24 [paras[0], 0, paras[0], 1], point 55 [foreignDoc, 1]":true, + "Range 24 [paras[0], 0, paras[0], 1], point 56 [foreignComment, 2]":true, + "Range 24 [paras[0], 0, paras[0], 1], point 57 [foreignTextNode, 0]":true, + "Range 24 [paras[0], 0, paras[0], 1], point 58 [foreignTextNode, 36]":true, + "Range 24 [paras[0], 0, paras[0], 1], point 59 [xmlDoc, -1]":true, + "Range 24 [paras[0], 0, paras[0], 1], point 60 [xmlDoc, 0]":true, + "Range 24 [paras[0], 0, paras[0], 1], point 61 [xmlDoc, 1]":true, + "Range 24 [paras[0], 0, paras[0], 1], point 62 [xmlDoc, 5]":true, + "Range 24 [paras[0], 0, paras[0], 1], point 63 [xmlComment, 0]":true, + "Range 24 [paras[0], 0, paras[0], 1], point 64 [xmlComment, 4]":true, + "Range 24 [paras[0], 0, paras[0], 1], point 65 [processingInstruction, 0]":true, + "Range 24 [paras[0], 0, paras[0], 1], point 66 [processingInstruction, 5]":true, + "Range 24 [paras[0], 0, paras[0], 1], point 67 [processingInstruction, 9]":true, + "Range 24 [paras[0], 0, paras[0], 1], point 70 [detachedForeignTextNode, 0]":true, + "Range 24 [paras[0], 0, paras[0], 1], point 71 [detachedForeignTextNode, 8]":true, + "Range 24 [paras[0], 0, paras[0], 1], point 72 [detachedXmlTextNode, 0]":true, + "Range 24 [paras[0], 0, paras[0], 1], point 73 [detachedXmlTextNode, 8]":true, + "Range 24 [paras[0], 0, paras[0], 1], point 74 [detachedProcessingInstruction, 12]":true, + "Range 24 [paras[0], 0, paras[0], 1], point 77 [detachedForeignComment, 0]":true, + "Range 24 [paras[0], 0, paras[0], 1], point 78 [detachedForeignComment, 4]":true, + "Range 24 [paras[0], 0, paras[0], 1], point 79 [detachedXmlComment, 2]":true, + "Range 24 [paras[0], 0, paras[0], 1], point 81 [foreignDocfrag, 0]":true, + "Range 24 [paras[0], 0, paras[0], 1], point 82 [xmlDocfrag, 0]":true, + "Range 24 [paras[0], 0, paras[0], 1], point 86 [foreignDoctype, 0]":true, + "Range 24 [paras[0], 0, paras[0], 1], point 87 [xmlDoctype, 0]":true, + "Range 25 [detachedPara1, 0, detachedPara1, 0], point 20 [foreignPara1.firstChild, 0]":true, + "Range 25 [detachedPara1, 0, detachedPara1, 0], point 21 [foreignPara1.firstChild, 1]":true, + "Range 25 [detachedPara1, 0, detachedPara1, 0], point 22 [foreignPara1.firstChild, 8]":true, + "Range 25 [detachedPara1, 0, detachedPara1, 0], point 23 [foreignPara1.firstChild, 9]":true, + "Range 25 [detachedPara1, 0, detachedPara1, 0], point 31 [foreignDoc.documentElement, 0]":true, + "Range 25 [detachedPara1, 0, detachedPara1, 0], point 32 [foreignDoc.documentElement, 1]":true, + "Range 25 [detachedPara1, 0, detachedPara1, 0], point 33 [foreignDoc.head, 0]":true, + "Range 25 [detachedPara1, 0, detachedPara1, 0], point 34 [foreignDoc.body, 1]":true, + "Range 25 [detachedPara1, 0, detachedPara1, 0], point 54 [foreignDoc, 0]":true, + "Range 25 [detachedPara1, 0, detachedPara1, 0], point 55 [foreignDoc, 1]":true, + "Range 25 [detachedPara1, 0, detachedPara1, 0], point 56 [foreignComment, 2]":true, + "Range 25 [detachedPara1, 0, detachedPara1, 0], point 57 [foreignTextNode, 0]":true, + "Range 25 [detachedPara1, 0, detachedPara1, 0], point 58 [foreignTextNode, 36]":true, + "Range 25 [detachedPara1, 0, detachedPara1, 0], point 59 [xmlDoc, -1]":true, + "Range 25 [detachedPara1, 0, detachedPara1, 0], point 60 [xmlDoc, 0]":true, + "Range 25 [detachedPara1, 0, detachedPara1, 0], point 61 [xmlDoc, 1]":true, + "Range 25 [detachedPara1, 0, detachedPara1, 0], point 62 [xmlDoc, 5]":true, + "Range 25 [detachedPara1, 0, detachedPara1, 0], point 63 [xmlComment, 0]":true, + "Range 25 [detachedPara1, 0, detachedPara1, 0], point 64 [xmlComment, 4]":true, + "Range 25 [detachedPara1, 0, detachedPara1, 0], point 65 [processingInstruction, 0]":true, + "Range 25 [detachedPara1, 0, detachedPara1, 0], point 66 [processingInstruction, 5]":true, + "Range 25 [detachedPara1, 0, detachedPara1, 0], point 67 [processingInstruction, 9]":true, + "Range 25 [detachedPara1, 0, detachedPara1, 0], point 70 [detachedForeignTextNode, 0]":true, + "Range 25 [detachedPara1, 0, detachedPara1, 0], point 71 [detachedForeignTextNode, 8]":true, + "Range 25 [detachedPara1, 0, detachedPara1, 0], point 72 [detachedXmlTextNode, 0]":true, + "Range 25 [detachedPara1, 0, detachedPara1, 0], point 73 [detachedXmlTextNode, 8]":true, + "Range 25 [detachedPara1, 0, detachedPara1, 0], point 74 [detachedProcessingInstruction, 12]":true, + "Range 25 [detachedPara1, 0, detachedPara1, 0], point 77 [detachedForeignComment, 0]":true, + "Range 25 [detachedPara1, 0, detachedPara1, 0], point 78 [detachedForeignComment, 4]":true, + "Range 25 [detachedPara1, 0, detachedPara1, 0], point 79 [detachedXmlComment, 2]":true, + "Range 25 [detachedPara1, 0, detachedPara1, 0], point 81 [foreignDocfrag, 0]":true, + "Range 25 [detachedPara1, 0, detachedPara1, 0], point 82 [xmlDocfrag, 0]":true, + "Range 25 [detachedPara1, 0, detachedPara1, 0], point 86 [foreignDoctype, 0]":true, + "Range 25 [detachedPara1, 0, detachedPara1, 0], point 87 [xmlDoctype, 0]":true, + "Range 26 [detachedPara1, 0, detachedPara1, 1], point 20 [foreignPara1.firstChild, 0]":true, + "Range 26 [detachedPara1, 0, detachedPara1, 1], point 21 [foreignPara1.firstChild, 1]":true, + "Range 26 [detachedPara1, 0, detachedPara1, 1], point 22 [foreignPara1.firstChild, 8]":true, + "Range 26 [detachedPara1, 0, detachedPara1, 1], point 23 [foreignPara1.firstChild, 9]":true, + "Range 26 [detachedPara1, 0, detachedPara1, 1], point 31 [foreignDoc.documentElement, 0]":true, + "Range 26 [detachedPara1, 0, detachedPara1, 1], point 32 [foreignDoc.documentElement, 1]":true, + "Range 26 [detachedPara1, 0, detachedPara1, 1], point 33 [foreignDoc.head, 0]":true, + "Range 26 [detachedPara1, 0, detachedPara1, 1], point 34 [foreignDoc.body, 1]":true, + "Range 26 [detachedPara1, 0, detachedPara1, 1], point 54 [foreignDoc, 0]":true, + "Range 26 [detachedPara1, 0, detachedPara1, 1], point 55 [foreignDoc, 1]":true, + "Range 26 [detachedPara1, 0, detachedPara1, 1], point 56 [foreignComment, 2]":true, + "Range 26 [detachedPara1, 0, detachedPara1, 1], point 57 [foreignTextNode, 0]":true, + "Range 26 [detachedPara1, 0, detachedPara1, 1], point 58 [foreignTextNode, 36]":true, + "Range 26 [detachedPara1, 0, detachedPara1, 1], point 59 [xmlDoc, -1]":true, + "Range 26 [detachedPara1, 0, detachedPara1, 1], point 60 [xmlDoc, 0]":true, + "Range 26 [detachedPara1, 0, detachedPara1, 1], point 61 [xmlDoc, 1]":true, + "Range 26 [detachedPara1, 0, detachedPara1, 1], point 62 [xmlDoc, 5]":true, + "Range 26 [detachedPara1, 0, detachedPara1, 1], point 63 [xmlComment, 0]":true, + "Range 26 [detachedPara1, 0, detachedPara1, 1], point 64 [xmlComment, 4]":true, + "Range 26 [detachedPara1, 0, detachedPara1, 1], point 65 [processingInstruction, 0]":true, + "Range 26 [detachedPara1, 0, detachedPara1, 1], point 66 [processingInstruction, 5]":true, + "Range 26 [detachedPara1, 0, detachedPara1, 1], point 67 [processingInstruction, 9]":true, + "Range 26 [detachedPara1, 0, detachedPara1, 1], point 70 [detachedForeignTextNode, 0]":true, + "Range 26 [detachedPara1, 0, detachedPara1, 1], point 71 [detachedForeignTextNode, 8]":true, + "Range 26 [detachedPara1, 0, detachedPara1, 1], point 72 [detachedXmlTextNode, 0]":true, + "Range 26 [detachedPara1, 0, detachedPara1, 1], point 73 [detachedXmlTextNode, 8]":true, + "Range 26 [detachedPara1, 0, detachedPara1, 1], point 74 [detachedProcessingInstruction, 12]":true, + "Range 26 [detachedPara1, 0, detachedPara1, 1], point 77 [detachedForeignComment, 0]":true, + "Range 26 [detachedPara1, 0, detachedPara1, 1], point 78 [detachedForeignComment, 4]":true, + "Range 26 [detachedPara1, 0, detachedPara1, 1], point 79 [detachedXmlComment, 2]":true, + "Range 26 [detachedPara1, 0, detachedPara1, 1], point 81 [foreignDocfrag, 0]":true, + "Range 26 [detachedPara1, 0, detachedPara1, 1], point 82 [xmlDocfrag, 0]":true, + "Range 26 [detachedPara1, 0, detachedPara1, 1], point 86 [foreignDoctype, 0]":true, + "Range 26 [detachedPara1, 0, detachedPara1, 1], point 87 [xmlDoctype, 0]":true, + "Range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0], point 20 [foreignPara1.firstChild, 0]":true, + "Range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0], point 21 [foreignPara1.firstChild, 1]":true, + "Range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0], point 22 [foreignPara1.firstChild, 8]":true, + "Range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0], point 23 [foreignPara1.firstChild, 9]":true, + "Range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0], point 31 [foreignDoc.documentElement, 0]":true, + "Range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0], point 32 [foreignDoc.documentElement, 1]":true, + "Range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0], point 33 [foreignDoc.head, 0]":true, + "Range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0], point 34 [foreignDoc.body, 1]":true, + "Range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0], point 54 [foreignDoc, 0]":true, + "Range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0], point 55 [foreignDoc, 1]":true, + "Range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0], point 56 [foreignComment, 2]":true, + "Range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0], point 57 [foreignTextNode, 0]":true, + "Range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0], point 58 [foreignTextNode, 36]":true, + "Range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0], point 59 [xmlDoc, -1]":true, + "Range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0], point 60 [xmlDoc, 0]":true, + "Range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0], point 61 [xmlDoc, 1]":true, + "Range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0], point 62 [xmlDoc, 5]":true, + "Range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0], point 63 [xmlComment, 0]":true, + "Range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0], point 64 [xmlComment, 4]":true, + "Range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0], point 65 [processingInstruction, 0]":true, + "Range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0], point 66 [processingInstruction, 5]":true, + "Range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0], point 67 [processingInstruction, 9]":true, + "Range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0], point 70 [detachedForeignTextNode, 0]":true, + "Range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0], point 71 [detachedForeignTextNode, 8]":true, + "Range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0], point 72 [detachedXmlTextNode, 0]":true, + "Range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0], point 73 [detachedXmlTextNode, 8]":true, + "Range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0], point 74 [detachedProcessingInstruction, 12]":true, + "Range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0], point 77 [detachedForeignComment, 0]":true, + "Range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0], point 78 [detachedForeignComment, 4]":true, + "Range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0], point 79 [detachedXmlComment, 2]":true, + "Range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0], point 81 [foreignDocfrag, 0]":true, + "Range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0], point 82 [xmlDocfrag, 0]":true, + "Range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0], point 86 [foreignDoctype, 0]":true, + "Range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0], point 87 [xmlDoctype, 0]":true, + "Range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8], point 20 [foreignPara1.firstChild, 0]":true, + "Range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8], point 21 [foreignPara1.firstChild, 1]":true, + "Range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8], point 22 [foreignPara1.firstChild, 8]":true, + "Range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8], point 23 [foreignPara1.firstChild, 9]":true, + "Range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8], point 31 [foreignDoc.documentElement, 0]":true, + "Range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8], point 32 [foreignDoc.documentElement, 1]":true, + "Range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8], point 33 [foreignDoc.head, 0]":true, + "Range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8], point 34 [foreignDoc.body, 1]":true, + "Range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8], point 54 [foreignDoc, 0]":true, + "Range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8], point 55 [foreignDoc, 1]":true, + "Range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8], point 56 [foreignComment, 2]":true, + "Range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8], point 57 [foreignTextNode, 0]":true, + "Range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8], point 58 [foreignTextNode, 36]":true, + "Range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8], point 59 [xmlDoc, -1]":true, + "Range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8], point 60 [xmlDoc, 0]":true, + "Range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8], point 61 [xmlDoc, 1]":true, + "Range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8], point 62 [xmlDoc, 5]":true, + "Range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8], point 63 [xmlComment, 0]":true, + "Range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8], point 64 [xmlComment, 4]":true, + "Range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8], point 65 [processingInstruction, 0]":true, + "Range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8], point 66 [processingInstruction, 5]":true, + "Range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8], point 67 [processingInstruction, 9]":true, + "Range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8], point 70 [detachedForeignTextNode, 0]":true, + "Range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8], point 71 [detachedForeignTextNode, 8]":true, + "Range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8], point 72 [detachedXmlTextNode, 0]":true, + "Range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8], point 73 [detachedXmlTextNode, 8]":true, + "Range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8], point 74 [detachedProcessingInstruction, 12]":true, + "Range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8], point 77 [detachedForeignComment, 0]":true, + "Range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8], point 78 [detachedForeignComment, 4]":true, + "Range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8], point 79 [detachedXmlComment, 2]":true, + "Range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8], point 81 [foreignDocfrag, 0]":true, + "Range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8], point 82 [xmlDocfrag, 0]":true, + "Range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8], point 86 [foreignDoctype, 0]":true, + "Range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8], point 87 [xmlDoctype, 0]":true, + "Range 29 [paras[0].firstChild, 3, paras[3], 1], point 20 [foreignPara1.firstChild, 0]":true, + "Range 29 [paras[0].firstChild, 3, paras[3], 1], point 21 [foreignPara1.firstChild, 1]":true, + "Range 29 [paras[0].firstChild, 3, paras[3], 1], point 22 [foreignPara1.firstChild, 8]":true, + "Range 29 [paras[0].firstChild, 3, paras[3], 1], point 23 [foreignPara1.firstChild, 9]":true, + "Range 29 [paras[0].firstChild, 3, paras[3], 1], point 31 [foreignDoc.documentElement, 0]":true, + "Range 29 [paras[0].firstChild, 3, paras[3], 1], point 32 [foreignDoc.documentElement, 1]":true, + "Range 29 [paras[0].firstChild, 3, paras[3], 1], point 33 [foreignDoc.head, 0]":true, + "Range 29 [paras[0].firstChild, 3, paras[3], 1], point 34 [foreignDoc.body, 1]":true, + "Range 29 [paras[0].firstChild, 3, paras[3], 1], point 54 [foreignDoc, 0]":true, + "Range 29 [paras[0].firstChild, 3, paras[3], 1], point 55 [foreignDoc, 1]":true, + "Range 29 [paras[0].firstChild, 3, paras[3], 1], point 56 [foreignComment, 2]":true, + "Range 29 [paras[0].firstChild, 3, paras[3], 1], point 57 [foreignTextNode, 0]":true, + "Range 29 [paras[0].firstChild, 3, paras[3], 1], point 58 [foreignTextNode, 36]":true, + "Range 29 [paras[0].firstChild, 3, paras[3], 1], point 59 [xmlDoc, -1]":true, + "Range 29 [paras[0].firstChild, 3, paras[3], 1], point 60 [xmlDoc, 0]":true, + "Range 29 [paras[0].firstChild, 3, paras[3], 1], point 61 [xmlDoc, 1]":true, + "Range 29 [paras[0].firstChild, 3, paras[3], 1], point 62 [xmlDoc, 5]":true, + "Range 29 [paras[0].firstChild, 3, paras[3], 1], point 63 [xmlComment, 0]":true, + "Range 29 [paras[0].firstChild, 3, paras[3], 1], point 64 [xmlComment, 4]":true, + "Range 29 [paras[0].firstChild, 3, paras[3], 1], point 65 [processingInstruction, 0]":true, + "Range 29 [paras[0].firstChild, 3, paras[3], 1], point 66 [processingInstruction, 5]":true, + "Range 29 [paras[0].firstChild, 3, paras[3], 1], point 67 [processingInstruction, 9]":true, + "Range 29 [paras[0].firstChild, 3, paras[3], 1], point 70 [detachedForeignTextNode, 0]":true, + "Range 29 [paras[0].firstChild, 3, paras[3], 1], point 71 [detachedForeignTextNode, 8]":true, + "Range 29 [paras[0].firstChild, 3, paras[3], 1], point 72 [detachedXmlTextNode, 0]":true, + "Range 29 [paras[0].firstChild, 3, paras[3], 1], point 73 [detachedXmlTextNode, 8]":true, + "Range 29 [paras[0].firstChild, 3, paras[3], 1], point 74 [detachedProcessingInstruction, 12]":true, + "Range 29 [paras[0].firstChild, 3, paras[3], 1], point 77 [detachedForeignComment, 0]":true, + "Range 29 [paras[0].firstChild, 3, paras[3], 1], point 78 [detachedForeignComment, 4]":true, + "Range 29 [paras[0].firstChild, 3, paras[3], 1], point 79 [detachedXmlComment, 2]":true, + "Range 29 [paras[0].firstChild, 3, paras[3], 1], point 81 [foreignDocfrag, 0]":true, + "Range 29 [paras[0].firstChild, 3, paras[3], 1], point 82 [xmlDocfrag, 0]":true, + "Range 29 [paras[0].firstChild, 3, paras[3], 1], point 86 [foreignDoctype, 0]":true, + "Range 29 [paras[0].firstChild, 3, paras[3], 1], point 87 [xmlDoctype, 0]":true, + "Range 30 [paras[0], 0, paras[0].firstChild, 7], point 20 [foreignPara1.firstChild, 0]":true, + "Range 30 [paras[0], 0, paras[0].firstChild, 7], point 21 [foreignPara1.firstChild, 1]":true, + "Range 30 [paras[0], 0, paras[0].firstChild, 7], point 22 [foreignPara1.firstChild, 8]":true, + "Range 30 [paras[0], 0, paras[0].firstChild, 7], point 23 [foreignPara1.firstChild, 9]":true, + "Range 30 [paras[0], 0, paras[0].firstChild, 7], point 31 [foreignDoc.documentElement, 0]":true, + "Range 30 [paras[0], 0, paras[0].firstChild, 7], point 32 [foreignDoc.documentElement, 1]":true, + "Range 30 [paras[0], 0, paras[0].firstChild, 7], point 33 [foreignDoc.head, 0]":true, + "Range 30 [paras[0], 0, paras[0].firstChild, 7], point 34 [foreignDoc.body, 1]":true, + "Range 30 [paras[0], 0, paras[0].firstChild, 7], point 54 [foreignDoc, 0]":true, + "Range 30 [paras[0], 0, paras[0].firstChild, 7], point 55 [foreignDoc, 1]":true, + "Range 30 [paras[0], 0, paras[0].firstChild, 7], point 56 [foreignComment, 2]":true, + "Range 30 [paras[0], 0, paras[0].firstChild, 7], point 57 [foreignTextNode, 0]":true, + "Range 30 [paras[0], 0, paras[0].firstChild, 7], point 58 [foreignTextNode, 36]":true, + "Range 30 [paras[0], 0, paras[0].firstChild, 7], point 59 [xmlDoc, -1]":true, + "Range 30 [paras[0], 0, paras[0].firstChild, 7], point 60 [xmlDoc, 0]":true, + "Range 30 [paras[0], 0, paras[0].firstChild, 7], point 61 [xmlDoc, 1]":true, + "Range 30 [paras[0], 0, paras[0].firstChild, 7], point 62 [xmlDoc, 5]":true, + "Range 30 [paras[0], 0, paras[0].firstChild, 7], point 63 [xmlComment, 0]":true, + "Range 30 [paras[0], 0, paras[0].firstChild, 7], point 64 [xmlComment, 4]":true, + "Range 30 [paras[0], 0, paras[0].firstChild, 7], point 65 [processingInstruction, 0]":true, + "Range 30 [paras[0], 0, paras[0].firstChild, 7], point 66 [processingInstruction, 5]":true, + "Range 30 [paras[0], 0, paras[0].firstChild, 7], point 67 [processingInstruction, 9]":true, + "Range 30 [paras[0], 0, paras[0].firstChild, 7], point 70 [detachedForeignTextNode, 0]":true, + "Range 30 [paras[0], 0, paras[0].firstChild, 7], point 71 [detachedForeignTextNode, 8]":true, + "Range 30 [paras[0], 0, paras[0].firstChild, 7], point 72 [detachedXmlTextNode, 0]":true, + "Range 30 [paras[0], 0, paras[0].firstChild, 7], point 73 [detachedXmlTextNode, 8]":true, + "Range 30 [paras[0], 0, paras[0].firstChild, 7], point 74 [detachedProcessingInstruction, 12]":true, + "Range 30 [paras[0], 0, paras[0].firstChild, 7], point 77 [detachedForeignComment, 0]":true, + "Range 30 [paras[0], 0, paras[0].firstChild, 7], point 78 [detachedForeignComment, 4]":true, + "Range 30 [paras[0], 0, paras[0].firstChild, 7], point 79 [detachedXmlComment, 2]":true, + "Range 30 [paras[0], 0, paras[0].firstChild, 7], point 81 [foreignDocfrag, 0]":true, + "Range 30 [paras[0], 0, paras[0].firstChild, 7], point 82 [xmlDocfrag, 0]":true, + "Range 30 [paras[0], 0, paras[0].firstChild, 7], point 86 [foreignDoctype, 0]":true, + "Range 30 [paras[0], 0, paras[0].firstChild, 7], point 87 [xmlDoctype, 0]":true, + "Range 31 [testDiv, 2, paras[4], 1], point 20 [foreignPara1.firstChild, 0]":true, + "Range 31 [testDiv, 2, paras[4], 1], point 21 [foreignPara1.firstChild, 1]":true, + "Range 31 [testDiv, 2, paras[4], 1], point 22 [foreignPara1.firstChild, 8]":true, + "Range 31 [testDiv, 2, paras[4], 1], point 23 [foreignPara1.firstChild, 9]":true, + "Range 31 [testDiv, 2, paras[4], 1], point 31 [foreignDoc.documentElement, 0]":true, + "Range 31 [testDiv, 2, paras[4], 1], point 32 [foreignDoc.documentElement, 1]":true, + "Range 31 [testDiv, 2, paras[4], 1], point 33 [foreignDoc.head, 0]":true, + "Range 31 [testDiv, 2, paras[4], 1], point 34 [foreignDoc.body, 1]":true, + "Range 31 [testDiv, 2, paras[4], 1], point 54 [foreignDoc, 0]":true, + "Range 31 [testDiv, 2, paras[4], 1], point 55 [foreignDoc, 1]":true, + "Range 31 [testDiv, 2, paras[4], 1], point 56 [foreignComment, 2]":true, + "Range 31 [testDiv, 2, paras[4], 1], point 57 [foreignTextNode, 0]":true, + "Range 31 [testDiv, 2, paras[4], 1], point 58 [foreignTextNode, 36]":true, + "Range 31 [testDiv, 2, paras[4], 1], point 59 [xmlDoc, -1]":true, + "Range 31 [testDiv, 2, paras[4], 1], point 60 [xmlDoc, 0]":true, + "Range 31 [testDiv, 2, paras[4], 1], point 61 [xmlDoc, 1]":true, + "Range 31 [testDiv, 2, paras[4], 1], point 62 [xmlDoc, 5]":true, + "Range 31 [testDiv, 2, paras[4], 1], point 63 [xmlComment, 0]":true, + "Range 31 [testDiv, 2, paras[4], 1], point 64 [xmlComment, 4]":true, + "Range 31 [testDiv, 2, paras[4], 1], point 65 [processingInstruction, 0]":true, + "Range 31 [testDiv, 2, paras[4], 1], point 66 [processingInstruction, 5]":true, + "Range 31 [testDiv, 2, paras[4], 1], point 67 [processingInstruction, 9]":true, + "Range 31 [testDiv, 2, paras[4], 1], point 70 [detachedForeignTextNode, 0]":true, + "Range 31 [testDiv, 2, paras[4], 1], point 71 [detachedForeignTextNode, 8]":true, + "Range 31 [testDiv, 2, paras[4], 1], point 72 [detachedXmlTextNode, 0]":true, + "Range 31 [testDiv, 2, paras[4], 1], point 73 [detachedXmlTextNode, 8]":true, + "Range 31 [testDiv, 2, paras[4], 1], point 74 [detachedProcessingInstruction, 12]":true, + "Range 31 [testDiv, 2, paras[4], 1], point 77 [detachedForeignComment, 0]":true, + "Range 31 [testDiv, 2, paras[4], 1], point 78 [detachedForeignComment, 4]":true, + "Range 31 [testDiv, 2, paras[4], 1], point 79 [detachedXmlComment, 2]":true, + "Range 31 [testDiv, 2, paras[4], 1], point 81 [foreignDocfrag, 0]":true, + "Range 31 [testDiv, 2, paras[4], 1], point 82 [xmlDocfrag, 0]":true, + "Range 31 [testDiv, 2, paras[4], 1], point 86 [foreignDoctype, 0]":true, + "Range 31 [testDiv, 2, paras[4], 1], point 87 [xmlDoctype, 0]":true, + "Range 32 [testDiv, 1, paras[2].firstChild, 5], point 20 [foreignPara1.firstChild, 0]":true, + "Range 32 [testDiv, 1, paras[2].firstChild, 5], point 21 [foreignPara1.firstChild, 1]":true, + "Range 32 [testDiv, 1, paras[2].firstChild, 5], point 22 [foreignPara1.firstChild, 8]":true, + "Range 32 [testDiv, 1, paras[2].firstChild, 5], point 23 [foreignPara1.firstChild, 9]":true, + "Range 32 [testDiv, 1, paras[2].firstChild, 5], point 31 [foreignDoc.documentElement, 0]":true, + "Range 32 [testDiv, 1, paras[2].firstChild, 5], point 32 [foreignDoc.documentElement, 1]":true, + "Range 32 [testDiv, 1, paras[2].firstChild, 5], point 33 [foreignDoc.head, 0]":true, + "Range 32 [testDiv, 1, paras[2].firstChild, 5], point 34 [foreignDoc.body, 1]":true, + "Range 32 [testDiv, 1, paras[2].firstChild, 5], point 54 [foreignDoc, 0]":true, + "Range 32 [testDiv, 1, paras[2].firstChild, 5], point 55 [foreignDoc, 1]":true, + "Range 32 [testDiv, 1, paras[2].firstChild, 5], point 56 [foreignComment, 2]":true, + "Range 32 [testDiv, 1, paras[2].firstChild, 5], point 57 [foreignTextNode, 0]":true, + "Range 32 [testDiv, 1, paras[2].firstChild, 5], point 58 [foreignTextNode, 36]":true, + "Range 32 [testDiv, 1, paras[2].firstChild, 5], point 59 [xmlDoc, -1]":true, + "Range 32 [testDiv, 1, paras[2].firstChild, 5], point 60 [xmlDoc, 0]":true, + "Range 32 [testDiv, 1, paras[2].firstChild, 5], point 61 [xmlDoc, 1]":true, + "Range 32 [testDiv, 1, paras[2].firstChild, 5], point 62 [xmlDoc, 5]":true, + "Range 32 [testDiv, 1, paras[2].firstChild, 5], point 63 [xmlComment, 0]":true, + "Range 32 [testDiv, 1, paras[2].firstChild, 5], point 64 [xmlComment, 4]":true, + "Range 32 [testDiv, 1, paras[2].firstChild, 5], point 65 [processingInstruction, 0]":true, + "Range 32 [testDiv, 1, paras[2].firstChild, 5], point 66 [processingInstruction, 5]":true, + "Range 32 [testDiv, 1, paras[2].firstChild, 5], point 67 [processingInstruction, 9]":true, + "Range 32 [testDiv, 1, paras[2].firstChild, 5], point 70 [detachedForeignTextNode, 0]":true, + "Range 32 [testDiv, 1, paras[2].firstChild, 5], point 71 [detachedForeignTextNode, 8]":true, + "Range 32 [testDiv, 1, paras[2].firstChild, 5], point 72 [detachedXmlTextNode, 0]":true, + "Range 32 [testDiv, 1, paras[2].firstChild, 5], point 73 [detachedXmlTextNode, 8]":true, + "Range 32 [testDiv, 1, paras[2].firstChild, 5], point 74 [detachedProcessingInstruction, 12]":true, + "Range 32 [testDiv, 1, paras[2].firstChild, 5], point 77 [detachedForeignComment, 0]":true, + "Range 32 [testDiv, 1, paras[2].firstChild, 5], point 78 [detachedForeignComment, 4]":true, + "Range 32 [testDiv, 1, paras[2].firstChild, 5], point 79 [detachedXmlComment, 2]":true, + "Range 32 [testDiv, 1, paras[2].firstChild, 5], point 81 [foreignDocfrag, 0]":true, + "Range 32 [testDiv, 1, paras[2].firstChild, 5], point 82 [xmlDocfrag, 0]":true, + "Range 32 [testDiv, 1, paras[2].firstChild, 5], point 86 [foreignDoctype, 0]":true, + "Range 32 [testDiv, 1, paras[2].firstChild, 5], point 87 [xmlDoctype, 0]":true, + "Range 33 [document.documentElement, 1, document.body, 0], point 20 [foreignPara1.firstChild, 0]":true, + "Range 33 [document.documentElement, 1, document.body, 0], point 21 [foreignPara1.firstChild, 1]":true, + "Range 33 [document.documentElement, 1, document.body, 0], point 22 [foreignPara1.firstChild, 8]":true, + "Range 33 [document.documentElement, 1, document.body, 0], point 23 [foreignPara1.firstChild, 9]":true, + "Range 33 [document.documentElement, 1, document.body, 0], point 31 [foreignDoc.documentElement, 0]":true, + "Range 33 [document.documentElement, 1, document.body, 0], point 32 [foreignDoc.documentElement, 1]":true, + "Range 33 [document.documentElement, 1, document.body, 0], point 33 [foreignDoc.head, 0]":true, + "Range 33 [document.documentElement, 1, document.body, 0], point 34 [foreignDoc.body, 1]":true, + "Range 33 [document.documentElement, 1, document.body, 0], point 54 [foreignDoc, 0]":true, + "Range 33 [document.documentElement, 1, document.body, 0], point 55 [foreignDoc, 1]":true, + "Range 33 [document.documentElement, 1, document.body, 0], point 56 [foreignComment, 2]":true, + "Range 33 [document.documentElement, 1, document.body, 0], point 57 [foreignTextNode, 0]":true, + "Range 33 [document.documentElement, 1, document.body, 0], point 58 [foreignTextNode, 36]":true, + "Range 33 [document.documentElement, 1, document.body, 0], point 59 [xmlDoc, -1]":true, + "Range 33 [document.documentElement, 1, document.body, 0], point 60 [xmlDoc, 0]":true, + "Range 33 [document.documentElement, 1, document.body, 0], point 61 [xmlDoc, 1]":true, + "Range 33 [document.documentElement, 1, document.body, 0], point 62 [xmlDoc, 5]":true, + "Range 33 [document.documentElement, 1, document.body, 0], point 63 [xmlComment, 0]":true, + "Range 33 [document.documentElement, 1, document.body, 0], point 64 [xmlComment, 4]":true, + "Range 33 [document.documentElement, 1, document.body, 0], point 65 [processingInstruction, 0]":true, + "Range 33 [document.documentElement, 1, document.body, 0], point 66 [processingInstruction, 5]":true, + "Range 33 [document.documentElement, 1, document.body, 0], point 67 [processingInstruction, 9]":true, + "Range 33 [document.documentElement, 1, document.body, 0], point 70 [detachedForeignTextNode, 0]":true, + "Range 33 [document.documentElement, 1, document.body, 0], point 71 [detachedForeignTextNode, 8]":true, + "Range 33 [document.documentElement, 1, document.body, 0], point 72 [detachedXmlTextNode, 0]":true, + "Range 33 [document.documentElement, 1, document.body, 0], point 73 [detachedXmlTextNode, 8]":true, + "Range 33 [document.documentElement, 1, document.body, 0], point 74 [detachedProcessingInstruction, 12]":true, + "Range 33 [document.documentElement, 1, document.body, 0], point 77 [detachedForeignComment, 0]":true, + "Range 33 [document.documentElement, 1, document.body, 0], point 78 [detachedForeignComment, 4]":true, + "Range 33 [document.documentElement, 1, document.body, 0], point 79 [detachedXmlComment, 2]":true, + "Range 33 [document.documentElement, 1, document.body, 0], point 81 [foreignDocfrag, 0]":true, + "Range 33 [document.documentElement, 1, document.body, 0], point 82 [xmlDocfrag, 0]":true, + "Range 33 [document.documentElement, 1, document.body, 0], point 86 [foreignDoctype, 0]":true, + "Range 33 [document.documentElement, 1, document.body, 0], point 87 [xmlDoctype, 0]":true, + "Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0], point 20 [foreignPara1.firstChild, 0]":true, + "Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0], point 21 [foreignPara1.firstChild, 1]":true, + "Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0], point 22 [foreignPara1.firstChild, 8]":true, + "Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0], point 23 [foreignPara1.firstChild, 9]":true, + "Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0], point 31 [foreignDoc.documentElement, 0]":true, + "Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0], point 32 [foreignDoc.documentElement, 1]":true, + "Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0], point 33 [foreignDoc.head, 0]":true, + "Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0], point 34 [foreignDoc.body, 1]":true, + "Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0], point 54 [foreignDoc, 0]":true, + "Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0], point 55 [foreignDoc, 1]":true, + "Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0], point 56 [foreignComment, 2]":true, + "Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0], point 57 [foreignTextNode, 0]":true, + "Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0], point 58 [foreignTextNode, 36]":true, + "Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0], point 59 [xmlDoc, -1]":true, + "Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0], point 60 [xmlDoc, 0]":true, + "Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0], point 61 [xmlDoc, 1]":true, + "Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0], point 62 [xmlDoc, 5]":true, + "Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0], point 63 [xmlComment, 0]":true, + "Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0], point 64 [xmlComment, 4]":true, + "Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0], point 65 [processingInstruction, 0]":true, + "Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0], point 66 [processingInstruction, 5]":true, + "Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0], point 67 [processingInstruction, 9]":true, + "Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0], point 70 [detachedForeignTextNode, 0]":true, + "Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0], point 71 [detachedForeignTextNode, 8]":true, + "Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0], point 72 [detachedXmlTextNode, 0]":true, + "Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0], point 73 [detachedXmlTextNode, 8]":true, + "Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0], point 74 [detachedProcessingInstruction, 12]":true, + "Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0], point 77 [detachedForeignComment, 0]":true, + "Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0], point 78 [detachedForeignComment, 4]":true, + "Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0], point 79 [detachedXmlComment, 2]":true, + "Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0], point 81 [foreignDocfrag, 0]":true, + "Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0], point 82 [xmlDocfrag, 0]":true, + "Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0], point 86 [foreignDoctype, 0]":true, + "Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0], point 87 [xmlDoctype, 0]":true, + "Range 35 [document, 0, document, 1], point 20 [foreignPara1.firstChild, 0]":true, + "Range 35 [document, 0, document, 1], point 21 [foreignPara1.firstChild, 1]":true, + "Range 35 [document, 0, document, 1], point 22 [foreignPara1.firstChild, 8]":true, + "Range 35 [document, 0, document, 1], point 23 [foreignPara1.firstChild, 9]":true, + "Range 35 [document, 0, document, 1], point 31 [foreignDoc.documentElement, 0]":true, + "Range 35 [document, 0, document, 1], point 32 [foreignDoc.documentElement, 1]":true, + "Range 35 [document, 0, document, 1], point 33 [foreignDoc.head, 0]":true, + "Range 35 [document, 0, document, 1], point 34 [foreignDoc.body, 1]":true, + "Range 35 [document, 0, document, 1], point 54 [foreignDoc, 0]":true, + "Range 35 [document, 0, document, 1], point 55 [foreignDoc, 1]":true, + "Range 35 [document, 0, document, 1], point 56 [foreignComment, 2]":true, + "Range 35 [document, 0, document, 1], point 57 [foreignTextNode, 0]":true, + "Range 35 [document, 0, document, 1], point 58 [foreignTextNode, 36]":true, + "Range 35 [document, 0, document, 1], point 59 [xmlDoc, -1]":true, + "Range 35 [document, 0, document, 1], point 60 [xmlDoc, 0]":true, + "Range 35 [document, 0, document, 1], point 61 [xmlDoc, 1]":true, + "Range 35 [document, 0, document, 1], point 62 [xmlDoc, 5]":true, + "Range 35 [document, 0, document, 1], point 63 [xmlComment, 0]":true, + "Range 35 [document, 0, document, 1], point 64 [xmlComment, 4]":true, + "Range 35 [document, 0, document, 1], point 65 [processingInstruction, 0]":true, + "Range 35 [document, 0, document, 1], point 66 [processingInstruction, 5]":true, + "Range 35 [document, 0, document, 1], point 67 [processingInstruction, 9]":true, + "Range 35 [document, 0, document, 1], point 70 [detachedForeignTextNode, 0]":true, + "Range 35 [document, 0, document, 1], point 71 [detachedForeignTextNode, 8]":true, + "Range 35 [document, 0, document, 1], point 72 [detachedXmlTextNode, 0]":true, + "Range 35 [document, 0, document, 1], point 73 [detachedXmlTextNode, 8]":true, + "Range 35 [document, 0, document, 1], point 74 [detachedProcessingInstruction, 12]":true, + "Range 35 [document, 0, document, 1], point 77 [detachedForeignComment, 0]":true, + "Range 35 [document, 0, document, 1], point 78 [detachedForeignComment, 4]":true, + "Range 35 [document, 0, document, 1], point 79 [detachedXmlComment, 2]":true, + "Range 35 [document, 0, document, 1], point 81 [foreignDocfrag, 0]":true, + "Range 35 [document, 0, document, 1], point 82 [xmlDocfrag, 0]":true, + "Range 35 [document, 0, document, 1], point 86 [foreignDoctype, 0]":true, + "Range 35 [document, 0, document, 1], point 87 [xmlDoctype, 0]":true, + "Range 36 [document, 0, document, 2], point 20 [foreignPara1.firstChild, 0]":true, + "Range 36 [document, 0, document, 2], point 21 [foreignPara1.firstChild, 1]":true, + "Range 36 [document, 0, document, 2], point 22 [foreignPara1.firstChild, 8]":true, + "Range 36 [document, 0, document, 2], point 23 [foreignPara1.firstChild, 9]":true, + "Range 36 [document, 0, document, 2], point 31 [foreignDoc.documentElement, 0]":true, + "Range 36 [document, 0, document, 2], point 32 [foreignDoc.documentElement, 1]":true, + "Range 36 [document, 0, document, 2], point 33 [foreignDoc.head, 0]":true, + "Range 36 [document, 0, document, 2], point 34 [foreignDoc.body, 1]":true, + "Range 36 [document, 0, document, 2], point 54 [foreignDoc, 0]":true, + "Range 36 [document, 0, document, 2], point 55 [foreignDoc, 1]":true, + "Range 36 [document, 0, document, 2], point 56 [foreignComment, 2]":true, + "Range 36 [document, 0, document, 2], point 57 [foreignTextNode, 0]":true, + "Range 36 [document, 0, document, 2], point 58 [foreignTextNode, 36]":true, + "Range 36 [document, 0, document, 2], point 59 [xmlDoc, -1]":true, + "Range 36 [document, 0, document, 2], point 60 [xmlDoc, 0]":true, + "Range 36 [document, 0, document, 2], point 61 [xmlDoc, 1]":true, + "Range 36 [document, 0, document, 2], point 62 [xmlDoc, 5]":true, + "Range 36 [document, 0, document, 2], point 63 [xmlComment, 0]":true, + "Range 36 [document, 0, document, 2], point 64 [xmlComment, 4]":true, + "Range 36 [document, 0, document, 2], point 65 [processingInstruction, 0]":true, + "Range 36 [document, 0, document, 2], point 66 [processingInstruction, 5]":true, + "Range 36 [document, 0, document, 2], point 67 [processingInstruction, 9]":true, + "Range 36 [document, 0, document, 2], point 70 [detachedForeignTextNode, 0]":true, + "Range 36 [document, 0, document, 2], point 71 [detachedForeignTextNode, 8]":true, + "Range 36 [document, 0, document, 2], point 72 [detachedXmlTextNode, 0]":true, + "Range 36 [document, 0, document, 2], point 73 [detachedXmlTextNode, 8]":true, + "Range 36 [document, 0, document, 2], point 74 [detachedProcessingInstruction, 12]":true, + "Range 36 [document, 0, document, 2], point 77 [detachedForeignComment, 0]":true, + "Range 36 [document, 0, document, 2], point 78 [detachedForeignComment, 4]":true, + "Range 36 [document, 0, document, 2], point 79 [detachedXmlComment, 2]":true, + "Range 36 [document, 0, document, 2], point 81 [foreignDocfrag, 0]":true, + "Range 36 [document, 0, document, 2], point 82 [xmlDocfrag, 0]":true, + "Range 36 [document, 0, document, 2], point 86 [foreignDoctype, 0]":true, + "Range 36 [document, 0, document, 2], point 87 [xmlDoctype, 0]":true, + "Range 37 [document, 1, document, 2], point 20 [foreignPara1.firstChild, 0]":true, + "Range 37 [document, 1, document, 2], point 21 [foreignPara1.firstChild, 1]":true, + "Range 37 [document, 1, document, 2], point 22 [foreignPara1.firstChild, 8]":true, + "Range 37 [document, 1, document, 2], point 23 [foreignPara1.firstChild, 9]":true, + "Range 37 [document, 1, document, 2], point 31 [foreignDoc.documentElement, 0]":true, + "Range 37 [document, 1, document, 2], point 32 [foreignDoc.documentElement, 1]":true, + "Range 37 [document, 1, document, 2], point 33 [foreignDoc.head, 0]":true, + "Range 37 [document, 1, document, 2], point 34 [foreignDoc.body, 1]":true, + "Range 37 [document, 1, document, 2], point 54 [foreignDoc, 0]":true, + "Range 37 [document, 1, document, 2], point 55 [foreignDoc, 1]":true, + "Range 37 [document, 1, document, 2], point 56 [foreignComment, 2]":true, + "Range 37 [document, 1, document, 2], point 57 [foreignTextNode, 0]":true, + "Range 37 [document, 1, document, 2], point 58 [foreignTextNode, 36]":true, + "Range 37 [document, 1, document, 2], point 59 [xmlDoc, -1]":true, + "Range 37 [document, 1, document, 2], point 60 [xmlDoc, 0]":true, + "Range 37 [document, 1, document, 2], point 61 [xmlDoc, 1]":true, + "Range 37 [document, 1, document, 2], point 62 [xmlDoc, 5]":true, + "Range 37 [document, 1, document, 2], point 63 [xmlComment, 0]":true, + "Range 37 [document, 1, document, 2], point 64 [xmlComment, 4]":true, + "Range 37 [document, 1, document, 2], point 65 [processingInstruction, 0]":true, + "Range 37 [document, 1, document, 2], point 66 [processingInstruction, 5]":true, + "Range 37 [document, 1, document, 2], point 67 [processingInstruction, 9]":true, + "Range 37 [document, 1, document, 2], point 70 [detachedForeignTextNode, 0]":true, + "Range 37 [document, 1, document, 2], point 71 [detachedForeignTextNode, 8]":true, + "Range 37 [document, 1, document, 2], point 72 [detachedXmlTextNode, 0]":true, + "Range 37 [document, 1, document, 2], point 73 [detachedXmlTextNode, 8]":true, + "Range 37 [document, 1, document, 2], point 74 [detachedProcessingInstruction, 12]":true, + "Range 37 [document, 1, document, 2], point 77 [detachedForeignComment, 0]":true, + "Range 37 [document, 1, document, 2], point 78 [detachedForeignComment, 4]":true, + "Range 37 [document, 1, document, 2], point 79 [detachedXmlComment, 2]":true, + "Range 37 [document, 1, document, 2], point 81 [foreignDocfrag, 0]":true, + "Range 37 [document, 1, document, 2], point 82 [xmlDocfrag, 0]":true, + "Range 37 [document, 1, document, 2], point 86 [foreignDoctype, 0]":true, + "Range 37 [document, 1, document, 2], point 87 [xmlDoctype, 0]":true, + "Range 38 [testDiv, 0, comment, 5], point 20 [foreignPara1.firstChild, 0]":true, + "Range 38 [testDiv, 0, comment, 5], point 21 [foreignPara1.firstChild, 1]":true, + "Range 38 [testDiv, 0, comment, 5], point 22 [foreignPara1.firstChild, 8]":true, + "Range 38 [testDiv, 0, comment, 5], point 23 [foreignPara1.firstChild, 9]":true, + "Range 38 [testDiv, 0, comment, 5], point 31 [foreignDoc.documentElement, 0]":true, + "Range 38 [testDiv, 0, comment, 5], point 32 [foreignDoc.documentElement, 1]":true, + "Range 38 [testDiv, 0, comment, 5], point 33 [foreignDoc.head, 0]":true, + "Range 38 [testDiv, 0, comment, 5], point 34 [foreignDoc.body, 1]":true, + "Range 38 [testDiv, 0, comment, 5], point 54 [foreignDoc, 0]":true, + "Range 38 [testDiv, 0, comment, 5], point 55 [foreignDoc, 1]":true, + "Range 38 [testDiv, 0, comment, 5], point 56 [foreignComment, 2]":true, + "Range 38 [testDiv, 0, comment, 5], point 57 [foreignTextNode, 0]":true, + "Range 38 [testDiv, 0, comment, 5], point 58 [foreignTextNode, 36]":true, + "Range 38 [testDiv, 0, comment, 5], point 59 [xmlDoc, -1]":true, + "Range 38 [testDiv, 0, comment, 5], point 60 [xmlDoc, 0]":true, + "Range 38 [testDiv, 0, comment, 5], point 61 [xmlDoc, 1]":true, + "Range 38 [testDiv, 0, comment, 5], point 62 [xmlDoc, 5]":true, + "Range 38 [testDiv, 0, comment, 5], point 63 [xmlComment, 0]":true, + "Range 38 [testDiv, 0, comment, 5], point 64 [xmlComment, 4]":true, + "Range 38 [testDiv, 0, comment, 5], point 65 [processingInstruction, 0]":true, + "Range 38 [testDiv, 0, comment, 5], point 66 [processingInstruction, 5]":true, + "Range 38 [testDiv, 0, comment, 5], point 67 [processingInstruction, 9]":true, + "Range 38 [testDiv, 0, comment, 5], point 70 [detachedForeignTextNode, 0]":true, + "Range 38 [testDiv, 0, comment, 5], point 71 [detachedForeignTextNode, 8]":true, + "Range 38 [testDiv, 0, comment, 5], point 72 [detachedXmlTextNode, 0]":true, + "Range 38 [testDiv, 0, comment, 5], point 73 [detachedXmlTextNode, 8]":true, + "Range 38 [testDiv, 0, comment, 5], point 74 [detachedProcessingInstruction, 12]":true, + "Range 38 [testDiv, 0, comment, 5], point 77 [detachedForeignComment, 0]":true, + "Range 38 [testDiv, 0, comment, 5], point 78 [detachedForeignComment, 4]":true, + "Range 38 [testDiv, 0, comment, 5], point 79 [detachedXmlComment, 2]":true, + "Range 38 [testDiv, 0, comment, 5], point 81 [foreignDocfrag, 0]":true, + "Range 38 [testDiv, 0, comment, 5], point 82 [xmlDocfrag, 0]":true, + "Range 38 [testDiv, 0, comment, 5], point 86 [foreignDoctype, 0]":true, + "Range 38 [testDiv, 0, comment, 5], point 87 [xmlDoctype, 0]":true, + "Range 39 [paras[2].firstChild, 4, comment, 2], point 20 [foreignPara1.firstChild, 0]":true, + "Range 39 [paras[2].firstChild, 4, comment, 2], point 21 [foreignPara1.firstChild, 1]":true, + "Range 39 [paras[2].firstChild, 4, comment, 2], point 22 [foreignPara1.firstChild, 8]":true, + "Range 39 [paras[2].firstChild, 4, comment, 2], point 23 [foreignPara1.firstChild, 9]":true, + "Range 39 [paras[2].firstChild, 4, comment, 2], point 31 [foreignDoc.documentElement, 0]":true, + "Range 39 [paras[2].firstChild, 4, comment, 2], point 32 [foreignDoc.documentElement, 1]":true, + "Range 39 [paras[2].firstChild, 4, comment, 2], point 33 [foreignDoc.head, 0]":true, + "Range 39 [paras[2].firstChild, 4, comment, 2], point 34 [foreignDoc.body, 1]":true, + "Range 39 [paras[2].firstChild, 4, comment, 2], point 54 [foreignDoc, 0]":true, + "Range 39 [paras[2].firstChild, 4, comment, 2], point 55 [foreignDoc, 1]":true, + "Range 39 [paras[2].firstChild, 4, comment, 2], point 56 [foreignComment, 2]":true, + "Range 39 [paras[2].firstChild, 4, comment, 2], point 57 [foreignTextNode, 0]":true, + "Range 39 [paras[2].firstChild, 4, comment, 2], point 58 [foreignTextNode, 36]":true, + "Range 39 [paras[2].firstChild, 4, comment, 2], point 59 [xmlDoc, -1]":true, + "Range 39 [paras[2].firstChild, 4, comment, 2], point 60 [xmlDoc, 0]":true, + "Range 39 [paras[2].firstChild, 4, comment, 2], point 61 [xmlDoc, 1]":true, + "Range 39 [paras[2].firstChild, 4, comment, 2], point 62 [xmlDoc, 5]":true, + "Range 39 [paras[2].firstChild, 4, comment, 2], point 63 [xmlComment, 0]":true, + "Range 39 [paras[2].firstChild, 4, comment, 2], point 64 [xmlComment, 4]":true, + "Range 39 [paras[2].firstChild, 4, comment, 2], point 65 [processingInstruction, 0]":true, + "Range 39 [paras[2].firstChild, 4, comment, 2], point 66 [processingInstruction, 5]":true, + "Range 39 [paras[2].firstChild, 4, comment, 2], point 67 [processingInstruction, 9]":true, + "Range 39 [paras[2].firstChild, 4, comment, 2], point 70 [detachedForeignTextNode, 0]":true, + "Range 39 [paras[2].firstChild, 4, comment, 2], point 71 [detachedForeignTextNode, 8]":true, + "Range 39 [paras[2].firstChild, 4, comment, 2], point 72 [detachedXmlTextNode, 0]":true, + "Range 39 [paras[2].firstChild, 4, comment, 2], point 73 [detachedXmlTextNode, 8]":true, + "Range 39 [paras[2].firstChild, 4, comment, 2], point 74 [detachedProcessingInstruction, 12]":true, + "Range 39 [paras[2].firstChild, 4, comment, 2], point 77 [detachedForeignComment, 0]":true, + "Range 39 [paras[2].firstChild, 4, comment, 2], point 78 [detachedForeignComment, 4]":true, + "Range 39 [paras[2].firstChild, 4, comment, 2], point 79 [detachedXmlComment, 2]":true, + "Range 39 [paras[2].firstChild, 4, comment, 2], point 81 [foreignDocfrag, 0]":true, + "Range 39 [paras[2].firstChild, 4, comment, 2], point 82 [xmlDocfrag, 0]":true, + "Range 39 [paras[2].firstChild, 4, comment, 2], point 86 [foreignDoctype, 0]":true, + "Range 39 [paras[2].firstChild, 4, comment, 2], point 87 [xmlDoctype, 0]":true, + "Range 40 [paras[3], 1, comment, 8], point 20 [foreignPara1.firstChild, 0]":true, + "Range 40 [paras[3], 1, comment, 8], point 21 [foreignPara1.firstChild, 1]":true, + "Range 40 [paras[3], 1, comment, 8], point 22 [foreignPara1.firstChild, 8]":true, + "Range 40 [paras[3], 1, comment, 8], point 23 [foreignPara1.firstChild, 9]":true, + "Range 40 [paras[3], 1, comment, 8], point 31 [foreignDoc.documentElement, 0]":true, + "Range 40 [paras[3], 1, comment, 8], point 32 [foreignDoc.documentElement, 1]":true, + "Range 40 [paras[3], 1, comment, 8], point 33 [foreignDoc.head, 0]":true, + "Range 40 [paras[3], 1, comment, 8], point 34 [foreignDoc.body, 1]":true, + "Range 40 [paras[3], 1, comment, 8], point 54 [foreignDoc, 0]":true, + "Range 40 [paras[3], 1, comment, 8], point 55 [foreignDoc, 1]":true, + "Range 40 [paras[3], 1, comment, 8], point 56 [foreignComment, 2]":true, + "Range 40 [paras[3], 1, comment, 8], point 57 [foreignTextNode, 0]":true, + "Range 40 [paras[3], 1, comment, 8], point 58 [foreignTextNode, 36]":true, + "Range 40 [paras[3], 1, comment, 8], point 59 [xmlDoc, -1]":true, + "Range 40 [paras[3], 1, comment, 8], point 60 [xmlDoc, 0]":true, + "Range 40 [paras[3], 1, comment, 8], point 61 [xmlDoc, 1]":true, + "Range 40 [paras[3], 1, comment, 8], point 62 [xmlDoc, 5]":true, + "Range 40 [paras[3], 1, comment, 8], point 63 [xmlComment, 0]":true, + "Range 40 [paras[3], 1, comment, 8], point 64 [xmlComment, 4]":true, + "Range 40 [paras[3], 1, comment, 8], point 65 [processingInstruction, 0]":true, + "Range 40 [paras[3], 1, comment, 8], point 66 [processingInstruction, 5]":true, + "Range 40 [paras[3], 1, comment, 8], point 67 [processingInstruction, 9]":true, + "Range 40 [paras[3], 1, comment, 8], point 70 [detachedForeignTextNode, 0]":true, + "Range 40 [paras[3], 1, comment, 8], point 71 [detachedForeignTextNode, 8]":true, + "Range 40 [paras[3], 1, comment, 8], point 72 [detachedXmlTextNode, 0]":true, + "Range 40 [paras[3], 1, comment, 8], point 73 [detachedXmlTextNode, 8]":true, + "Range 40 [paras[3], 1, comment, 8], point 74 [detachedProcessingInstruction, 12]":true, + "Range 40 [paras[3], 1, comment, 8], point 77 [detachedForeignComment, 0]":true, + "Range 40 [paras[3], 1, comment, 8], point 78 [detachedForeignComment, 4]":true, + "Range 40 [paras[3], 1, comment, 8], point 79 [detachedXmlComment, 2]":true, + "Range 40 [paras[3], 1, comment, 8], point 81 [foreignDocfrag, 0]":true, + "Range 40 [paras[3], 1, comment, 8], point 82 [xmlDocfrag, 0]":true, + "Range 40 [paras[3], 1, comment, 8], point 86 [foreignDoctype, 0]":true, + "Range 40 [paras[3], 1, comment, 8], point 87 [xmlDoctype, 0]":true, + "Range 41 [foreignDoc, 0, foreignDoc, 0], point 20 [foreignPara1.firstChild, 0]":true, + "Range 41 [foreignDoc, 0, foreignDoc, 0], point 21 [foreignPara1.firstChild, 1]":true, + "Range 41 [foreignDoc, 0, foreignDoc, 0], point 22 [foreignPara1.firstChild, 8]":true, + "Range 41 [foreignDoc, 0, foreignDoc, 0], point 23 [foreignPara1.firstChild, 9]":true, + "Range 41 [foreignDoc, 0, foreignDoc, 0], point 31 [foreignDoc.documentElement, 0]":true, + "Range 41 [foreignDoc, 0, foreignDoc, 0], point 32 [foreignDoc.documentElement, 1]":true, + "Range 41 [foreignDoc, 0, foreignDoc, 0], point 33 [foreignDoc.head, 0]":true, + "Range 41 [foreignDoc, 0, foreignDoc, 0], point 34 [foreignDoc.body, 1]":true, + "Range 41 [foreignDoc, 0, foreignDoc, 0], point 54 [foreignDoc, 0]":true, + "Range 41 [foreignDoc, 0, foreignDoc, 0], point 55 [foreignDoc, 1]":true, + "Range 41 [foreignDoc, 0, foreignDoc, 0], point 56 [foreignComment, 2]":true, + "Range 41 [foreignDoc, 0, foreignDoc, 0], point 57 [foreignTextNode, 0]":true, + "Range 41 [foreignDoc, 0, foreignDoc, 0], point 58 [foreignTextNode, 36]":true, + "Range 41 [foreignDoc, 0, foreignDoc, 0], point 59 [xmlDoc, -1]":true, + "Range 41 [foreignDoc, 0, foreignDoc, 0], point 60 [xmlDoc, 0]":true, + "Range 41 [foreignDoc, 0, foreignDoc, 0], point 61 [xmlDoc, 1]":true, + "Range 41 [foreignDoc, 0, foreignDoc, 0], point 62 [xmlDoc, 5]":true, + "Range 41 [foreignDoc, 0, foreignDoc, 0], point 63 [xmlComment, 0]":true, + "Range 41 [foreignDoc, 0, foreignDoc, 0], point 64 [xmlComment, 4]":true, + "Range 41 [foreignDoc, 0, foreignDoc, 0], point 65 [processingInstruction, 0]":true, + "Range 41 [foreignDoc, 0, foreignDoc, 0], point 66 [processingInstruction, 5]":true, + "Range 41 [foreignDoc, 0, foreignDoc, 0], point 67 [processingInstruction, 9]":true, + "Range 41 [foreignDoc, 0, foreignDoc, 0], point 70 [detachedForeignTextNode, 0]":true, + "Range 41 [foreignDoc, 0, foreignDoc, 0], point 71 [detachedForeignTextNode, 8]":true, + "Range 41 [foreignDoc, 0, foreignDoc, 0], point 72 [detachedXmlTextNode, 0]":true, + "Range 41 [foreignDoc, 0, foreignDoc, 0], point 73 [detachedXmlTextNode, 8]":true, + "Range 41 [foreignDoc, 0, foreignDoc, 0], point 74 [detachedProcessingInstruction, 12]":true, + "Range 41 [foreignDoc, 0, foreignDoc, 0], point 77 [detachedForeignComment, 0]":true, + "Range 41 [foreignDoc, 0, foreignDoc, 0], point 78 [detachedForeignComment, 4]":true, + "Range 41 [foreignDoc, 0, foreignDoc, 0], point 79 [detachedXmlComment, 2]":true, + "Range 41 [foreignDoc, 0, foreignDoc, 0], point 81 [foreignDocfrag, 0]":true, + "Range 41 [foreignDoc, 0, foreignDoc, 0], point 82 [xmlDocfrag, 0]":true, + "Range 41 [foreignDoc, 0, foreignDoc, 0], point 86 [foreignDoctype, 0]":true, + "Range 41 [foreignDoc, 0, foreignDoc, 0], point 87 [xmlDoctype, 0]":true, + "Range 42 [foreignDoc, 1, foreignComment, 2], point 20 [foreignPara1.firstChild, 0]":true, + "Range 42 [foreignDoc, 1, foreignComment, 2], point 21 [foreignPara1.firstChild, 1]":true, + "Range 42 [foreignDoc, 1, foreignComment, 2], point 22 [foreignPara1.firstChild, 8]":true, + "Range 42 [foreignDoc, 1, foreignComment, 2], point 23 [foreignPara1.firstChild, 9]":true, + "Range 42 [foreignDoc, 1, foreignComment, 2], point 31 [foreignDoc.documentElement, 0]":true, + "Range 42 [foreignDoc, 1, foreignComment, 2], point 32 [foreignDoc.documentElement, 1]":true, + "Range 42 [foreignDoc, 1, foreignComment, 2], point 33 [foreignDoc.head, 0]":true, + "Range 42 [foreignDoc, 1, foreignComment, 2], point 34 [foreignDoc.body, 1]":true, + "Range 42 [foreignDoc, 1, foreignComment, 2], point 54 [foreignDoc, 0]":true, + "Range 42 [foreignDoc, 1, foreignComment, 2], point 55 [foreignDoc, 1]":true, + "Range 42 [foreignDoc, 1, foreignComment, 2], point 56 [foreignComment, 2]":true, + "Range 42 [foreignDoc, 1, foreignComment, 2], point 57 [foreignTextNode, 0]":true, + "Range 42 [foreignDoc, 1, foreignComment, 2], point 58 [foreignTextNode, 36]":true, + "Range 42 [foreignDoc, 1, foreignComment, 2], point 59 [xmlDoc, -1]":true, + "Range 42 [foreignDoc, 1, foreignComment, 2], point 60 [xmlDoc, 0]":true, + "Range 42 [foreignDoc, 1, foreignComment, 2], point 61 [xmlDoc, 1]":true, + "Range 42 [foreignDoc, 1, foreignComment, 2], point 62 [xmlDoc, 5]":true, + "Range 42 [foreignDoc, 1, foreignComment, 2], point 63 [xmlComment, 0]":true, + "Range 42 [foreignDoc, 1, foreignComment, 2], point 64 [xmlComment, 4]":true, + "Range 42 [foreignDoc, 1, foreignComment, 2], point 65 [processingInstruction, 0]":true, + "Range 42 [foreignDoc, 1, foreignComment, 2], point 66 [processingInstruction, 5]":true, + "Range 42 [foreignDoc, 1, foreignComment, 2], point 67 [processingInstruction, 9]":true, + "Range 42 [foreignDoc, 1, foreignComment, 2], point 70 [detachedForeignTextNode, 0]":true, + "Range 42 [foreignDoc, 1, foreignComment, 2], point 71 [detachedForeignTextNode, 8]":true, + "Range 42 [foreignDoc, 1, foreignComment, 2], point 72 [detachedXmlTextNode, 0]":true, + "Range 42 [foreignDoc, 1, foreignComment, 2], point 73 [detachedXmlTextNode, 8]":true, + "Range 42 [foreignDoc, 1, foreignComment, 2], point 74 [detachedProcessingInstruction, 12]":true, + "Range 42 [foreignDoc, 1, foreignComment, 2], point 77 [detachedForeignComment, 0]":true, + "Range 42 [foreignDoc, 1, foreignComment, 2], point 78 [detachedForeignComment, 4]":true, + "Range 42 [foreignDoc, 1, foreignComment, 2], point 79 [detachedXmlComment, 2]":true, + "Range 42 [foreignDoc, 1, foreignComment, 2], point 81 [foreignDocfrag, 0]":true, + "Range 42 [foreignDoc, 1, foreignComment, 2], point 82 [xmlDocfrag, 0]":true, + "Range 42 [foreignDoc, 1, foreignComment, 2], point 86 [foreignDoctype, 0]":true, + "Range 42 [foreignDoc, 1, foreignComment, 2], point 87 [xmlDoctype, 0]":true, + "Range 43 [foreignDoc.body, 0, foreignTextNode, 36], point 20 [foreignPara1.firstChild, 0]":true, + "Range 43 [foreignDoc.body, 0, foreignTextNode, 36], point 21 [foreignPara1.firstChild, 1]":true, + "Range 43 [foreignDoc.body, 0, foreignTextNode, 36], point 22 [foreignPara1.firstChild, 8]":true, + "Range 43 [foreignDoc.body, 0, foreignTextNode, 36], point 23 [foreignPara1.firstChild, 9]":true, + "Range 43 [foreignDoc.body, 0, foreignTextNode, 36], point 31 [foreignDoc.documentElement, 0]":true, + "Range 43 [foreignDoc.body, 0, foreignTextNode, 36], point 32 [foreignDoc.documentElement, 1]":true, + "Range 43 [foreignDoc.body, 0, foreignTextNode, 36], point 33 [foreignDoc.head, 0]":true, + "Range 43 [foreignDoc.body, 0, foreignTextNode, 36], point 34 [foreignDoc.body, 1]":true, + "Range 43 [foreignDoc.body, 0, foreignTextNode, 36], point 54 [foreignDoc, 0]":true, + "Range 43 [foreignDoc.body, 0, foreignTextNode, 36], point 55 [foreignDoc, 1]":true, + "Range 43 [foreignDoc.body, 0, foreignTextNode, 36], point 56 [foreignComment, 2]":true, + "Range 43 [foreignDoc.body, 0, foreignTextNode, 36], point 57 [foreignTextNode, 0]":true, + "Range 43 [foreignDoc.body, 0, foreignTextNode, 36], point 58 [foreignTextNode, 36]":true, + "Range 43 [foreignDoc.body, 0, foreignTextNode, 36], point 59 [xmlDoc, -1]":true, + "Range 43 [foreignDoc.body, 0, foreignTextNode, 36], point 60 [xmlDoc, 0]":true, + "Range 43 [foreignDoc.body, 0, foreignTextNode, 36], point 61 [xmlDoc, 1]":true, + "Range 43 [foreignDoc.body, 0, foreignTextNode, 36], point 62 [xmlDoc, 5]":true, + "Range 43 [foreignDoc.body, 0, foreignTextNode, 36], point 63 [xmlComment, 0]":true, + "Range 43 [foreignDoc.body, 0, foreignTextNode, 36], point 64 [xmlComment, 4]":true, + "Range 43 [foreignDoc.body, 0, foreignTextNode, 36], point 65 [processingInstruction, 0]":true, + "Range 43 [foreignDoc.body, 0, foreignTextNode, 36], point 66 [processingInstruction, 5]":true, + "Range 43 [foreignDoc.body, 0, foreignTextNode, 36], point 67 [processingInstruction, 9]":true, + "Range 43 [foreignDoc.body, 0, foreignTextNode, 36], point 70 [detachedForeignTextNode, 0]":true, + "Range 43 [foreignDoc.body, 0, foreignTextNode, 36], point 71 [detachedForeignTextNode, 8]":true, + "Range 43 [foreignDoc.body, 0, foreignTextNode, 36], point 72 [detachedXmlTextNode, 0]":true, + "Range 43 [foreignDoc.body, 0, foreignTextNode, 36], point 73 [detachedXmlTextNode, 8]":true, + "Range 43 [foreignDoc.body, 0, foreignTextNode, 36], point 74 [detachedProcessingInstruction, 12]":true, + "Range 43 [foreignDoc.body, 0, foreignTextNode, 36], point 77 [detachedForeignComment, 0]":true, + "Range 43 [foreignDoc.body, 0, foreignTextNode, 36], point 78 [detachedForeignComment, 4]":true, + "Range 43 [foreignDoc.body, 0, foreignTextNode, 36], point 79 [detachedXmlComment, 2]":true, + "Range 43 [foreignDoc.body, 0, foreignTextNode, 36], point 81 [foreignDocfrag, 0]":true, + "Range 43 [foreignDoc.body, 0, foreignTextNode, 36], point 82 [xmlDocfrag, 0]":true, + "Range 43 [foreignDoc.body, 0, foreignTextNode, 36], point 86 [foreignDoctype, 0]":true, + "Range 43 [foreignDoc.body, 0, foreignTextNode, 36], point 87 [xmlDoctype, 0]":true, + "Range 44 [xmlDoc, 0, xmlDoc, 0], point 20 [foreignPara1.firstChild, 0]":true, + "Range 44 [xmlDoc, 0, xmlDoc, 0], point 21 [foreignPara1.firstChild, 1]":true, + "Range 44 [xmlDoc, 0, xmlDoc, 0], point 22 [foreignPara1.firstChild, 8]":true, + "Range 44 [xmlDoc, 0, xmlDoc, 0], point 23 [foreignPara1.firstChild, 9]":true, + "Range 44 [xmlDoc, 0, xmlDoc, 0], point 31 [foreignDoc.documentElement, 0]":true, + "Range 44 [xmlDoc, 0, xmlDoc, 0], point 32 [foreignDoc.documentElement, 1]":true, + "Range 44 [xmlDoc, 0, xmlDoc, 0], point 33 [foreignDoc.head, 0]":true, + "Range 44 [xmlDoc, 0, xmlDoc, 0], point 34 [foreignDoc.body, 1]":true, + "Range 44 [xmlDoc, 0, xmlDoc, 0], point 54 [foreignDoc, 0]":true, + "Range 44 [xmlDoc, 0, xmlDoc, 0], point 55 [foreignDoc, 1]":true, + "Range 44 [xmlDoc, 0, xmlDoc, 0], point 56 [foreignComment, 2]":true, + "Range 44 [xmlDoc, 0, xmlDoc, 0], point 57 [foreignTextNode, 0]":true, + "Range 44 [xmlDoc, 0, xmlDoc, 0], point 58 [foreignTextNode, 36]":true, + "Range 44 [xmlDoc, 0, xmlDoc, 0], point 59 [xmlDoc, -1]":true, + "Range 44 [xmlDoc, 0, xmlDoc, 0], point 60 [xmlDoc, 0]":true, + "Range 44 [xmlDoc, 0, xmlDoc, 0], point 61 [xmlDoc, 1]":true, + "Range 44 [xmlDoc, 0, xmlDoc, 0], point 62 [xmlDoc, 5]":true, + "Range 44 [xmlDoc, 0, xmlDoc, 0], point 63 [xmlComment, 0]":true, + "Range 44 [xmlDoc, 0, xmlDoc, 0], point 64 [xmlComment, 4]":true, + "Range 44 [xmlDoc, 0, xmlDoc, 0], point 65 [processingInstruction, 0]":true, + "Range 44 [xmlDoc, 0, xmlDoc, 0], point 66 [processingInstruction, 5]":true, + "Range 44 [xmlDoc, 0, xmlDoc, 0], point 67 [processingInstruction, 9]":true, + "Range 44 [xmlDoc, 0, xmlDoc, 0], point 70 [detachedForeignTextNode, 0]":true, + "Range 44 [xmlDoc, 0, xmlDoc, 0], point 71 [detachedForeignTextNode, 8]":true, + "Range 44 [xmlDoc, 0, xmlDoc, 0], point 72 [detachedXmlTextNode, 0]":true, + "Range 44 [xmlDoc, 0, xmlDoc, 0], point 73 [detachedXmlTextNode, 8]":true, + "Range 44 [xmlDoc, 0, xmlDoc, 0], point 74 [detachedProcessingInstruction, 12]":true, + "Range 44 [xmlDoc, 0, xmlDoc, 0], point 77 [detachedForeignComment, 0]":true, + "Range 44 [xmlDoc, 0, xmlDoc, 0], point 78 [detachedForeignComment, 4]":true, + "Range 44 [xmlDoc, 0, xmlDoc, 0], point 79 [detachedXmlComment, 2]":true, + "Range 44 [xmlDoc, 0, xmlDoc, 0], point 81 [foreignDocfrag, 0]":true, + "Range 44 [xmlDoc, 0, xmlDoc, 0], point 82 [xmlDocfrag, 0]":true, + "Range 44 [xmlDoc, 0, xmlDoc, 0], point 86 [foreignDoctype, 0]":true, + "Range 44 [xmlDoc, 0, xmlDoc, 0], point 87 [xmlDoctype, 0]":true, + "Range 45 [xmlDoc, 1, xmlComment, 0], point 20 [foreignPara1.firstChild, 0]":true, + "Range 45 [xmlDoc, 1, xmlComment, 0], point 21 [foreignPara1.firstChild, 1]":true, + "Range 45 [xmlDoc, 1, xmlComment, 0], point 22 [foreignPara1.firstChild, 8]":true, + "Range 45 [xmlDoc, 1, xmlComment, 0], point 23 [foreignPara1.firstChild, 9]":true, + "Range 45 [xmlDoc, 1, xmlComment, 0], point 31 [foreignDoc.documentElement, 0]":true, + "Range 45 [xmlDoc, 1, xmlComment, 0], point 32 [foreignDoc.documentElement, 1]":true, + "Range 45 [xmlDoc, 1, xmlComment, 0], point 33 [foreignDoc.head, 0]":true, + "Range 45 [xmlDoc, 1, xmlComment, 0], point 34 [foreignDoc.body, 1]":true, + "Range 45 [xmlDoc, 1, xmlComment, 0], point 54 [foreignDoc, 0]":true, + "Range 45 [xmlDoc, 1, xmlComment, 0], point 55 [foreignDoc, 1]":true, + "Range 45 [xmlDoc, 1, xmlComment, 0], point 56 [foreignComment, 2]":true, + "Range 45 [xmlDoc, 1, xmlComment, 0], point 57 [foreignTextNode, 0]":true, + "Range 45 [xmlDoc, 1, xmlComment, 0], point 58 [foreignTextNode, 36]":true, + "Range 45 [xmlDoc, 1, xmlComment, 0], point 59 [xmlDoc, -1]":true, + "Range 45 [xmlDoc, 1, xmlComment, 0], point 60 [xmlDoc, 0]":true, + "Range 45 [xmlDoc, 1, xmlComment, 0], point 61 [xmlDoc, 1]":true, + "Range 45 [xmlDoc, 1, xmlComment, 0], point 62 [xmlDoc, 5]":true, + "Range 45 [xmlDoc, 1, xmlComment, 0], point 63 [xmlComment, 0]":true, + "Range 45 [xmlDoc, 1, xmlComment, 0], point 64 [xmlComment, 4]":true, + "Range 45 [xmlDoc, 1, xmlComment, 0], point 65 [processingInstruction, 0]":true, + "Range 45 [xmlDoc, 1, xmlComment, 0], point 66 [processingInstruction, 5]":true, + "Range 45 [xmlDoc, 1, xmlComment, 0], point 67 [processingInstruction, 9]":true, + "Range 45 [xmlDoc, 1, xmlComment, 0], point 70 [detachedForeignTextNode, 0]":true, + "Range 45 [xmlDoc, 1, xmlComment, 0], point 71 [detachedForeignTextNode, 8]":true, + "Range 45 [xmlDoc, 1, xmlComment, 0], point 72 [detachedXmlTextNode, 0]":true, + "Range 45 [xmlDoc, 1, xmlComment, 0], point 73 [detachedXmlTextNode, 8]":true, + "Range 45 [xmlDoc, 1, xmlComment, 0], point 74 [detachedProcessingInstruction, 12]":true, + "Range 45 [xmlDoc, 1, xmlComment, 0], point 77 [detachedForeignComment, 0]":true, + "Range 45 [xmlDoc, 1, xmlComment, 0], point 78 [detachedForeignComment, 4]":true, + "Range 45 [xmlDoc, 1, xmlComment, 0], point 79 [detachedXmlComment, 2]":true, + "Range 45 [xmlDoc, 1, xmlComment, 0], point 81 [foreignDocfrag, 0]":true, + "Range 45 [xmlDoc, 1, xmlComment, 0], point 82 [xmlDocfrag, 0]":true, + "Range 45 [xmlDoc, 1, xmlComment, 0], point 86 [foreignDoctype, 0]":true, + "Range 45 [xmlDoc, 1, xmlComment, 0], point 87 [xmlDoctype, 0]":true, + "Range 46 [detachedTextNode, 0, detachedTextNode, 8], point 20 [foreignPara1.firstChild, 0]":true, + "Range 46 [detachedTextNode, 0, detachedTextNode, 8], point 21 [foreignPara1.firstChild, 1]":true, + "Range 46 [detachedTextNode, 0, detachedTextNode, 8], point 22 [foreignPara1.firstChild, 8]":true, + "Range 46 [detachedTextNode, 0, detachedTextNode, 8], point 23 [foreignPara1.firstChild, 9]":true, + "Range 46 [detachedTextNode, 0, detachedTextNode, 8], point 31 [foreignDoc.documentElement, 0]":true, + "Range 46 [detachedTextNode, 0, detachedTextNode, 8], point 32 [foreignDoc.documentElement, 1]":true, + "Range 46 [detachedTextNode, 0, detachedTextNode, 8], point 33 [foreignDoc.head, 0]":true, + "Range 46 [detachedTextNode, 0, detachedTextNode, 8], point 34 [foreignDoc.body, 1]":true, + "Range 46 [detachedTextNode, 0, detachedTextNode, 8], point 54 [foreignDoc, 0]":true, + "Range 46 [detachedTextNode, 0, detachedTextNode, 8], point 55 [foreignDoc, 1]":true, + "Range 46 [detachedTextNode, 0, detachedTextNode, 8], point 56 [foreignComment, 2]":true, + "Range 46 [detachedTextNode, 0, detachedTextNode, 8], point 57 [foreignTextNode, 0]":true, + "Range 46 [detachedTextNode, 0, detachedTextNode, 8], point 58 [foreignTextNode, 36]":true, + "Range 46 [detachedTextNode, 0, detachedTextNode, 8], point 59 [xmlDoc, -1]":true, + "Range 46 [detachedTextNode, 0, detachedTextNode, 8], point 60 [xmlDoc, 0]":true, + "Range 46 [detachedTextNode, 0, detachedTextNode, 8], point 61 [xmlDoc, 1]":true, + "Range 46 [detachedTextNode, 0, detachedTextNode, 8], point 62 [xmlDoc, 5]":true, + "Range 46 [detachedTextNode, 0, detachedTextNode, 8], point 63 [xmlComment, 0]":true, + "Range 46 [detachedTextNode, 0, detachedTextNode, 8], point 64 [xmlComment, 4]":true, + "Range 46 [detachedTextNode, 0, detachedTextNode, 8], point 65 [processingInstruction, 0]":true, + "Range 46 [detachedTextNode, 0, detachedTextNode, 8], point 66 [processingInstruction, 5]":true, + "Range 46 [detachedTextNode, 0, detachedTextNode, 8], point 67 [processingInstruction, 9]":true, + "Range 46 [detachedTextNode, 0, detachedTextNode, 8], point 70 [detachedForeignTextNode, 0]":true, + "Range 46 [detachedTextNode, 0, detachedTextNode, 8], point 71 [detachedForeignTextNode, 8]":true, + "Range 46 [detachedTextNode, 0, detachedTextNode, 8], point 72 [detachedXmlTextNode, 0]":true, + "Range 46 [detachedTextNode, 0, detachedTextNode, 8], point 73 [detachedXmlTextNode, 8]":true, + "Range 46 [detachedTextNode, 0, detachedTextNode, 8], point 74 [detachedProcessingInstruction, 12]":true, + "Range 46 [detachedTextNode, 0, detachedTextNode, 8], point 77 [detachedForeignComment, 0]":true, + "Range 46 [detachedTextNode, 0, detachedTextNode, 8], point 78 [detachedForeignComment, 4]":true, + "Range 46 [detachedTextNode, 0, detachedTextNode, 8], point 79 [detachedXmlComment, 2]":true, + "Range 46 [detachedTextNode, 0, detachedTextNode, 8], point 81 [foreignDocfrag, 0]":true, + "Range 46 [detachedTextNode, 0, detachedTextNode, 8], point 82 [xmlDocfrag, 0]":true, + "Range 46 [detachedTextNode, 0, detachedTextNode, 8], point 86 [foreignDoctype, 0]":true, + "Range 46 [detachedTextNode, 0, detachedTextNode, 8], point 87 [xmlDoctype, 0]":true, + "Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7], point 20 [foreignPara1.firstChild, 0]":true, + "Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7], point 21 [foreignPara1.firstChild, 1]":true, + "Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7], point 22 [foreignPara1.firstChild, 8]":true, + "Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7], point 23 [foreignPara1.firstChild, 9]":true, + "Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7], point 31 [foreignDoc.documentElement, 0]":true, + "Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7], point 32 [foreignDoc.documentElement, 1]":true, + "Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7], point 33 [foreignDoc.head, 0]":true, + "Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7], point 34 [foreignDoc.body, 1]":true, + "Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7], point 54 [foreignDoc, 0]":true, + "Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7], point 55 [foreignDoc, 1]":true, + "Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7], point 56 [foreignComment, 2]":true, + "Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7], point 57 [foreignTextNode, 0]":true, + "Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7], point 58 [foreignTextNode, 36]":true, + "Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7], point 59 [xmlDoc, -1]":true, + "Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7], point 60 [xmlDoc, 0]":true, + "Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7], point 61 [xmlDoc, 1]":true, + "Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7], point 62 [xmlDoc, 5]":true, + "Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7], point 63 [xmlComment, 0]":true, + "Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7], point 64 [xmlComment, 4]":true, + "Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7], point 65 [processingInstruction, 0]":true, + "Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7], point 66 [processingInstruction, 5]":true, + "Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7], point 67 [processingInstruction, 9]":true, + "Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7], point 70 [detachedForeignTextNode, 0]":true, + "Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7], point 71 [detachedForeignTextNode, 8]":true, + "Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7], point 72 [detachedXmlTextNode, 0]":true, + "Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7], point 73 [detachedXmlTextNode, 8]":true, + "Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7], point 74 [detachedProcessingInstruction, 12]":true, + "Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7], point 77 [detachedForeignComment, 0]":true, + "Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7], point 78 [detachedForeignComment, 4]":true, + "Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7], point 79 [detachedXmlComment, 2]":true, + "Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7], point 81 [foreignDocfrag, 0]":true, + "Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7], point 82 [xmlDocfrag, 0]":true, + "Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7], point 86 [foreignDoctype, 0]":true, + "Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7], point 87 [xmlDoctype, 0]":true, + "Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8], point 20 [foreignPara1.firstChild, 0]":true, + "Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8], point 21 [foreignPara1.firstChild, 1]":true, + "Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8], point 22 [foreignPara1.firstChild, 8]":true, + "Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8], point 23 [foreignPara1.firstChild, 9]":true, + "Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8], point 31 [foreignDoc.documentElement, 0]":true, + "Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8], point 32 [foreignDoc.documentElement, 1]":true, + "Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8], point 33 [foreignDoc.head, 0]":true, + "Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8], point 34 [foreignDoc.body, 1]":true, + "Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8], point 54 [foreignDoc, 0]":true, + "Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8], point 55 [foreignDoc, 1]":true, + "Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8], point 56 [foreignComment, 2]":true, + "Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8], point 57 [foreignTextNode, 0]":true, + "Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8], point 58 [foreignTextNode, 36]":true, + "Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8], point 59 [xmlDoc, -1]":true, + "Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8], point 60 [xmlDoc, 0]":true, + "Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8], point 61 [xmlDoc, 1]":true, + "Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8], point 62 [xmlDoc, 5]":true, + "Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8], point 63 [xmlComment, 0]":true, + "Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8], point 64 [xmlComment, 4]":true, + "Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8], point 65 [processingInstruction, 0]":true, + "Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8], point 66 [processingInstruction, 5]":true, + "Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8], point 67 [processingInstruction, 9]":true, + "Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8], point 70 [detachedForeignTextNode, 0]":true, + "Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8], point 71 [detachedForeignTextNode, 8]":true, + "Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8], point 72 [detachedXmlTextNode, 0]":true, + "Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8], point 73 [detachedXmlTextNode, 8]":true, + "Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8], point 74 [detachedProcessingInstruction, 12]":true, + "Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8], point 77 [detachedForeignComment, 0]":true, + "Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8], point 78 [detachedForeignComment, 4]":true, + "Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8], point 79 [detachedXmlComment, 2]":true, + "Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8], point 81 [foreignDocfrag, 0]":true, + "Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8], point 82 [xmlDocfrag, 0]":true, + "Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8], point 86 [foreignDoctype, 0]":true, + "Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8], point 87 [xmlDoctype, 0]":true, + "Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7], point 20 [foreignPara1.firstChild, 0]":true, + "Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7], point 21 [foreignPara1.firstChild, 1]":true, + "Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7], point 22 [foreignPara1.firstChild, 8]":true, + "Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7], point 23 [foreignPara1.firstChild, 9]":true, + "Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7], point 31 [foreignDoc.documentElement, 0]":true, + "Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7], point 32 [foreignDoc.documentElement, 1]":true, + "Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7], point 33 [foreignDoc.head, 0]":true, + "Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7], point 34 [foreignDoc.body, 1]":true, + "Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7], point 54 [foreignDoc, 0]":true, + "Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7], point 55 [foreignDoc, 1]":true, + "Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7], point 56 [foreignComment, 2]":true, + "Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7], point 57 [foreignTextNode, 0]":true, + "Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7], point 58 [foreignTextNode, 36]":true, + "Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7], point 59 [xmlDoc, -1]":true, + "Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7], point 60 [xmlDoc, 0]":true, + "Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7], point 61 [xmlDoc, 1]":true, + "Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7], point 62 [xmlDoc, 5]":true, + "Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7], point 63 [xmlComment, 0]":true, + "Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7], point 64 [xmlComment, 4]":true, + "Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7], point 65 [processingInstruction, 0]":true, + "Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7], point 66 [processingInstruction, 5]":true, + "Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7], point 67 [processingInstruction, 9]":true, + "Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7], point 70 [detachedForeignTextNode, 0]":true, + "Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7], point 71 [detachedForeignTextNode, 8]":true, + "Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7], point 72 [detachedXmlTextNode, 0]":true, + "Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7], point 73 [detachedXmlTextNode, 8]":true, + "Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7], point 74 [detachedProcessingInstruction, 12]":true, + "Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7], point 77 [detachedForeignComment, 0]":true, + "Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7], point 78 [detachedForeignComment, 4]":true, + "Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7], point 79 [detachedXmlComment, 2]":true, + "Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7], point 81 [foreignDocfrag, 0]":true, + "Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7], point 82 [xmlDocfrag, 0]":true, + "Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7], point 86 [foreignDoctype, 0]":true, + "Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7], point 87 [xmlDoctype, 0]":true, + "Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8], point 20 [foreignPara1.firstChild, 0]":true, + "Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8], point 21 [foreignPara1.firstChild, 1]":true, + "Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8], point 22 [foreignPara1.firstChild, 8]":true, + "Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8], point 23 [foreignPara1.firstChild, 9]":true, + "Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8], point 31 [foreignDoc.documentElement, 0]":true, + "Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8], point 32 [foreignDoc.documentElement, 1]":true, + "Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8], point 33 [foreignDoc.head, 0]":true, + "Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8], point 34 [foreignDoc.body, 1]":true, + "Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8], point 54 [foreignDoc, 0]":true, + "Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8], point 55 [foreignDoc, 1]":true, + "Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8], point 56 [foreignComment, 2]":true, + "Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8], point 57 [foreignTextNode, 0]":true, + "Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8], point 58 [foreignTextNode, 36]":true, + "Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8], point 59 [xmlDoc, -1]":true, + "Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8], point 60 [xmlDoc, 0]":true, + "Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8], point 61 [xmlDoc, 1]":true, + "Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8], point 62 [xmlDoc, 5]":true, + "Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8], point 63 [xmlComment, 0]":true, + "Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8], point 64 [xmlComment, 4]":true, + "Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8], point 65 [processingInstruction, 0]":true, + "Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8], point 66 [processingInstruction, 5]":true, + "Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8], point 67 [processingInstruction, 9]":true, + "Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8], point 70 [detachedForeignTextNode, 0]":true, + "Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8], point 71 [detachedForeignTextNode, 8]":true, + "Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8], point 72 [detachedXmlTextNode, 0]":true, + "Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8], point 73 [detachedXmlTextNode, 8]":true, + "Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8], point 74 [detachedProcessingInstruction, 12]":true, + "Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8], point 77 [detachedForeignComment, 0]":true, + "Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8], point 78 [detachedForeignComment, 4]":true, + "Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8], point 79 [detachedXmlComment, 2]":true, + "Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8], point 81 [foreignDocfrag, 0]":true, + "Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8], point 82 [xmlDocfrag, 0]":true, + "Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8], point 86 [foreignDoctype, 0]":true, + "Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8], point 87 [xmlDoctype, 0]":true, + "Range 51 [detachedComment, 3, detachedComment, 4], point 20 [foreignPara1.firstChild, 0]":true, + "Range 51 [detachedComment, 3, detachedComment, 4], point 21 [foreignPara1.firstChild, 1]":true, + "Range 51 [detachedComment, 3, detachedComment, 4], point 22 [foreignPara1.firstChild, 8]":true, + "Range 51 [detachedComment, 3, detachedComment, 4], point 23 [foreignPara1.firstChild, 9]":true, + "Range 51 [detachedComment, 3, detachedComment, 4], point 31 [foreignDoc.documentElement, 0]":true, + "Range 51 [detachedComment, 3, detachedComment, 4], point 32 [foreignDoc.documentElement, 1]":true, + "Range 51 [detachedComment, 3, detachedComment, 4], point 33 [foreignDoc.head, 0]":true, + "Range 51 [detachedComment, 3, detachedComment, 4], point 34 [foreignDoc.body, 1]":true, + "Range 51 [detachedComment, 3, detachedComment, 4], point 54 [foreignDoc, 0]":true, + "Range 51 [detachedComment, 3, detachedComment, 4], point 55 [foreignDoc, 1]":true, + "Range 51 [detachedComment, 3, detachedComment, 4], point 56 [foreignComment, 2]":true, + "Range 51 [detachedComment, 3, detachedComment, 4], point 57 [foreignTextNode, 0]":true, + "Range 51 [detachedComment, 3, detachedComment, 4], point 58 [foreignTextNode, 36]":true, + "Range 51 [detachedComment, 3, detachedComment, 4], point 59 [xmlDoc, -1]":true, + "Range 51 [detachedComment, 3, detachedComment, 4], point 60 [xmlDoc, 0]":true, + "Range 51 [detachedComment, 3, detachedComment, 4], point 61 [xmlDoc, 1]":true, + "Range 51 [detachedComment, 3, detachedComment, 4], point 62 [xmlDoc, 5]":true, + "Range 51 [detachedComment, 3, detachedComment, 4], point 63 [xmlComment, 0]":true, + "Range 51 [detachedComment, 3, detachedComment, 4], point 64 [xmlComment, 4]":true, + "Range 51 [detachedComment, 3, detachedComment, 4], point 65 [processingInstruction, 0]":true, + "Range 51 [detachedComment, 3, detachedComment, 4], point 66 [processingInstruction, 5]":true, + "Range 51 [detachedComment, 3, detachedComment, 4], point 67 [processingInstruction, 9]":true, + "Range 51 [detachedComment, 3, detachedComment, 4], point 70 [detachedForeignTextNode, 0]":true, + "Range 51 [detachedComment, 3, detachedComment, 4], point 71 [detachedForeignTextNode, 8]":true, + "Range 51 [detachedComment, 3, detachedComment, 4], point 72 [detachedXmlTextNode, 0]":true, + "Range 51 [detachedComment, 3, detachedComment, 4], point 73 [detachedXmlTextNode, 8]":true, + "Range 51 [detachedComment, 3, detachedComment, 4], point 74 [detachedProcessingInstruction, 12]":true, + "Range 51 [detachedComment, 3, detachedComment, 4], point 77 [detachedForeignComment, 0]":true, + "Range 51 [detachedComment, 3, detachedComment, 4], point 78 [detachedForeignComment, 4]":true, + "Range 51 [detachedComment, 3, detachedComment, 4], point 79 [detachedXmlComment, 2]":true, + "Range 51 [detachedComment, 3, detachedComment, 4], point 81 [foreignDocfrag, 0]":true, + "Range 51 [detachedComment, 3, detachedComment, 4], point 82 [xmlDocfrag, 0]":true, + "Range 51 [detachedComment, 3, detachedComment, 4], point 86 [foreignDoctype, 0]":true, + "Range 51 [detachedComment, 3, detachedComment, 4], point 87 [xmlDoctype, 0]":true, + "Range 52 [detachedComment, 5, detachedComment, 5], point 20 [foreignPara1.firstChild, 0]":true, + "Range 52 [detachedComment, 5, detachedComment, 5], point 21 [foreignPara1.firstChild, 1]":true, + "Range 52 [detachedComment, 5, detachedComment, 5], point 22 [foreignPara1.firstChild, 8]":true, + "Range 52 [detachedComment, 5, detachedComment, 5], point 23 [foreignPara1.firstChild, 9]":true, + "Range 52 [detachedComment, 5, detachedComment, 5], point 31 [foreignDoc.documentElement, 0]":true, + "Range 52 [detachedComment, 5, detachedComment, 5], point 32 [foreignDoc.documentElement, 1]":true, + "Range 52 [detachedComment, 5, detachedComment, 5], point 33 [foreignDoc.head, 0]":true, + "Range 52 [detachedComment, 5, detachedComment, 5], point 34 [foreignDoc.body, 1]":true, + "Range 52 [detachedComment, 5, detachedComment, 5], point 54 [foreignDoc, 0]":true, + "Range 52 [detachedComment, 5, detachedComment, 5], point 55 [foreignDoc, 1]":true, + "Range 52 [detachedComment, 5, detachedComment, 5], point 56 [foreignComment, 2]":true, + "Range 52 [detachedComment, 5, detachedComment, 5], point 57 [foreignTextNode, 0]":true, + "Range 52 [detachedComment, 5, detachedComment, 5], point 58 [foreignTextNode, 36]":true, + "Range 52 [detachedComment, 5, detachedComment, 5], point 59 [xmlDoc, -1]":true, + "Range 52 [detachedComment, 5, detachedComment, 5], point 60 [xmlDoc, 0]":true, + "Range 52 [detachedComment, 5, detachedComment, 5], point 61 [xmlDoc, 1]":true, + "Range 52 [detachedComment, 5, detachedComment, 5], point 62 [xmlDoc, 5]":true, + "Range 52 [detachedComment, 5, detachedComment, 5], point 63 [xmlComment, 0]":true, + "Range 52 [detachedComment, 5, detachedComment, 5], point 64 [xmlComment, 4]":true, + "Range 52 [detachedComment, 5, detachedComment, 5], point 65 [processingInstruction, 0]":true, + "Range 52 [detachedComment, 5, detachedComment, 5], point 66 [processingInstruction, 5]":true, + "Range 52 [detachedComment, 5, detachedComment, 5], point 67 [processingInstruction, 9]":true, + "Range 52 [detachedComment, 5, detachedComment, 5], point 70 [detachedForeignTextNode, 0]":true, + "Range 52 [detachedComment, 5, detachedComment, 5], point 71 [detachedForeignTextNode, 8]":true, + "Range 52 [detachedComment, 5, detachedComment, 5], point 72 [detachedXmlTextNode, 0]":true, + "Range 52 [detachedComment, 5, detachedComment, 5], point 73 [detachedXmlTextNode, 8]":true, + "Range 52 [detachedComment, 5, detachedComment, 5], point 74 [detachedProcessingInstruction, 12]":true, + "Range 52 [detachedComment, 5, detachedComment, 5], point 77 [detachedForeignComment, 0]":true, + "Range 52 [detachedComment, 5, detachedComment, 5], point 78 [detachedForeignComment, 4]":true, + "Range 52 [detachedComment, 5, detachedComment, 5], point 79 [detachedXmlComment, 2]":true, + "Range 52 [detachedComment, 5, detachedComment, 5], point 81 [foreignDocfrag, 0]":true, + "Range 52 [detachedComment, 5, detachedComment, 5], point 82 [xmlDocfrag, 0]":true, + "Range 52 [detachedComment, 5, detachedComment, 5], point 86 [foreignDoctype, 0]":true, + "Range 52 [detachedComment, 5, detachedComment, 5], point 87 [xmlDoctype, 0]":true, + "Range 53 [detachedForeignComment, 0, detachedForeignComment, 1], point 20 [foreignPara1.firstChild, 0]":true, + "Range 53 [detachedForeignComment, 0, detachedForeignComment, 1], point 21 [foreignPara1.firstChild, 1]":true, + "Range 53 [detachedForeignComment, 0, detachedForeignComment, 1], point 22 [foreignPara1.firstChild, 8]":true, + "Range 53 [detachedForeignComment, 0, detachedForeignComment, 1], point 23 [foreignPara1.firstChild, 9]":true, + "Range 53 [detachedForeignComment, 0, detachedForeignComment, 1], point 31 [foreignDoc.documentElement, 0]":true, + "Range 53 [detachedForeignComment, 0, detachedForeignComment, 1], point 32 [foreignDoc.documentElement, 1]":true, + "Range 53 [detachedForeignComment, 0, detachedForeignComment, 1], point 33 [foreignDoc.head, 0]":true, + "Range 53 [detachedForeignComment, 0, detachedForeignComment, 1], point 34 [foreignDoc.body, 1]":true, + "Range 53 [detachedForeignComment, 0, detachedForeignComment, 1], point 54 [foreignDoc, 0]":true, + "Range 53 [detachedForeignComment, 0, detachedForeignComment, 1], point 55 [foreignDoc, 1]":true, + "Range 53 [detachedForeignComment, 0, detachedForeignComment, 1], point 56 [foreignComment, 2]":true, + "Range 53 [detachedForeignComment, 0, detachedForeignComment, 1], point 57 [foreignTextNode, 0]":true, + "Range 53 [detachedForeignComment, 0, detachedForeignComment, 1], point 58 [foreignTextNode, 36]":true, + "Range 53 [detachedForeignComment, 0, detachedForeignComment, 1], point 59 [xmlDoc, -1]":true, + "Range 53 [detachedForeignComment, 0, detachedForeignComment, 1], point 60 [xmlDoc, 0]":true, + "Range 53 [detachedForeignComment, 0, detachedForeignComment, 1], point 61 [xmlDoc, 1]":true, + "Range 53 [detachedForeignComment, 0, detachedForeignComment, 1], point 62 [xmlDoc, 5]":true, + "Range 53 [detachedForeignComment, 0, detachedForeignComment, 1], point 63 [xmlComment, 0]":true, + "Range 53 [detachedForeignComment, 0, detachedForeignComment, 1], point 64 [xmlComment, 4]":true, + "Range 53 [detachedForeignComment, 0, detachedForeignComment, 1], point 65 [processingInstruction, 0]":true, + "Range 53 [detachedForeignComment, 0, detachedForeignComment, 1], point 66 [processingInstruction, 5]":true, + "Range 53 [detachedForeignComment, 0, detachedForeignComment, 1], point 67 [processingInstruction, 9]":true, + "Range 53 [detachedForeignComment, 0, detachedForeignComment, 1], point 70 [detachedForeignTextNode, 0]":true, + "Range 53 [detachedForeignComment, 0, detachedForeignComment, 1], point 71 [detachedForeignTextNode, 8]":true, + "Range 53 [detachedForeignComment, 0, detachedForeignComment, 1], point 72 [detachedXmlTextNode, 0]":true, + "Range 53 [detachedForeignComment, 0, detachedForeignComment, 1], point 73 [detachedXmlTextNode, 8]":true, + "Range 53 [detachedForeignComment, 0, detachedForeignComment, 1], point 74 [detachedProcessingInstruction, 12]":true, + "Range 53 [detachedForeignComment, 0, detachedForeignComment, 1], point 77 [detachedForeignComment, 0]":true, + "Range 53 [detachedForeignComment, 0, detachedForeignComment, 1], point 78 [detachedForeignComment, 4]":true, + "Range 53 [detachedForeignComment, 0, detachedForeignComment, 1], point 79 [detachedXmlComment, 2]":true, + "Range 53 [detachedForeignComment, 0, detachedForeignComment, 1], point 81 [foreignDocfrag, 0]":true, + "Range 53 [detachedForeignComment, 0, detachedForeignComment, 1], point 82 [xmlDocfrag, 0]":true, + "Range 53 [detachedForeignComment, 0, detachedForeignComment, 1], point 86 [foreignDoctype, 0]":true, + "Range 53 [detachedForeignComment, 0, detachedForeignComment, 1], point 87 [xmlDoctype, 0]":true, + "Range 54 [detachedForeignComment, 4, detachedForeignComment, 4], point 20 [foreignPara1.firstChild, 0]":true, + "Range 54 [detachedForeignComment, 4, detachedForeignComment, 4], point 21 [foreignPara1.firstChild, 1]":true, + "Range 54 [detachedForeignComment, 4, detachedForeignComment, 4], point 22 [foreignPara1.firstChild, 8]":true, + "Range 54 [detachedForeignComment, 4, detachedForeignComment, 4], point 23 [foreignPara1.firstChild, 9]":true, + "Range 54 [detachedForeignComment, 4, detachedForeignComment, 4], point 31 [foreignDoc.documentElement, 0]":true, + "Range 54 [detachedForeignComment, 4, detachedForeignComment, 4], point 32 [foreignDoc.documentElement, 1]":true, + "Range 54 [detachedForeignComment, 4, detachedForeignComment, 4], point 33 [foreignDoc.head, 0]":true, + "Range 54 [detachedForeignComment, 4, detachedForeignComment, 4], point 34 [foreignDoc.body, 1]":true, + "Range 54 [detachedForeignComment, 4, detachedForeignComment, 4], point 54 [foreignDoc, 0]":true, + "Range 54 [detachedForeignComment, 4, detachedForeignComment, 4], point 55 [foreignDoc, 1]":true, + "Range 54 [detachedForeignComment, 4, detachedForeignComment, 4], point 56 [foreignComment, 2]":true, + "Range 54 [detachedForeignComment, 4, detachedForeignComment, 4], point 57 [foreignTextNode, 0]":true, + "Range 54 [detachedForeignComment, 4, detachedForeignComment, 4], point 58 [foreignTextNode, 36]":true, + "Range 54 [detachedForeignComment, 4, detachedForeignComment, 4], point 59 [xmlDoc, -1]":true, + "Range 54 [detachedForeignComment, 4, detachedForeignComment, 4], point 60 [xmlDoc, 0]":true, + "Range 54 [detachedForeignComment, 4, detachedForeignComment, 4], point 61 [xmlDoc, 1]":true, + "Range 54 [detachedForeignComment, 4, detachedForeignComment, 4], point 62 [xmlDoc, 5]":true, + "Range 54 [detachedForeignComment, 4, detachedForeignComment, 4], point 63 [xmlComment, 0]":true, + "Range 54 [detachedForeignComment, 4, detachedForeignComment, 4], point 64 [xmlComment, 4]":true, + "Range 54 [detachedForeignComment, 4, detachedForeignComment, 4], point 65 [processingInstruction, 0]":true, + "Range 54 [detachedForeignComment, 4, detachedForeignComment, 4], point 66 [processingInstruction, 5]":true, + "Range 54 [detachedForeignComment, 4, detachedForeignComment, 4], point 67 [processingInstruction, 9]":true, + "Range 54 [detachedForeignComment, 4, detachedForeignComment, 4], point 70 [detachedForeignTextNode, 0]":true, + "Range 54 [detachedForeignComment, 4, detachedForeignComment, 4], point 71 [detachedForeignTextNode, 8]":true, + "Range 54 [detachedForeignComment, 4, detachedForeignComment, 4], point 72 [detachedXmlTextNode, 0]":true, + "Range 54 [detachedForeignComment, 4, detachedForeignComment, 4], point 73 [detachedXmlTextNode, 8]":true, + "Range 54 [detachedForeignComment, 4, detachedForeignComment, 4], point 74 [detachedProcessingInstruction, 12]":true, + "Range 54 [detachedForeignComment, 4, detachedForeignComment, 4], point 77 [detachedForeignComment, 0]":true, + "Range 54 [detachedForeignComment, 4, detachedForeignComment, 4], point 78 [detachedForeignComment, 4]":true, + "Range 54 [detachedForeignComment, 4, detachedForeignComment, 4], point 79 [detachedXmlComment, 2]":true, + "Range 54 [detachedForeignComment, 4, detachedForeignComment, 4], point 81 [foreignDocfrag, 0]":true, + "Range 54 [detachedForeignComment, 4, detachedForeignComment, 4], point 82 [xmlDocfrag, 0]":true, + "Range 54 [detachedForeignComment, 4, detachedForeignComment, 4], point 86 [foreignDoctype, 0]":true, + "Range 54 [detachedForeignComment, 4, detachedForeignComment, 4], point 87 [xmlDoctype, 0]":true, + "Range 55 [detachedXmlComment, 2, detachedXmlComment, 6], point 20 [foreignPara1.firstChild, 0]":true, + "Range 55 [detachedXmlComment, 2, detachedXmlComment, 6], point 21 [foreignPara1.firstChild, 1]":true, + "Range 55 [detachedXmlComment, 2, detachedXmlComment, 6], point 22 [foreignPara1.firstChild, 8]":true, + "Range 55 [detachedXmlComment, 2, detachedXmlComment, 6], point 23 [foreignPara1.firstChild, 9]":true, + "Range 55 [detachedXmlComment, 2, detachedXmlComment, 6], point 31 [foreignDoc.documentElement, 0]":true, + "Range 55 [detachedXmlComment, 2, detachedXmlComment, 6], point 32 [foreignDoc.documentElement, 1]":true, + "Range 55 [detachedXmlComment, 2, detachedXmlComment, 6], point 33 [foreignDoc.head, 0]":true, + "Range 55 [detachedXmlComment, 2, detachedXmlComment, 6], point 34 [foreignDoc.body, 1]":true, + "Range 55 [detachedXmlComment, 2, detachedXmlComment, 6], point 54 [foreignDoc, 0]":true, + "Range 55 [detachedXmlComment, 2, detachedXmlComment, 6], point 55 [foreignDoc, 1]":true, + "Range 55 [detachedXmlComment, 2, detachedXmlComment, 6], point 56 [foreignComment, 2]":true, + "Range 55 [detachedXmlComment, 2, detachedXmlComment, 6], point 57 [foreignTextNode, 0]":true, + "Range 55 [detachedXmlComment, 2, detachedXmlComment, 6], point 58 [foreignTextNode, 36]":true, + "Range 55 [detachedXmlComment, 2, detachedXmlComment, 6], point 59 [xmlDoc, -1]":true, + "Range 55 [detachedXmlComment, 2, detachedXmlComment, 6], point 60 [xmlDoc, 0]":true, + "Range 55 [detachedXmlComment, 2, detachedXmlComment, 6], point 61 [xmlDoc, 1]":true, + "Range 55 [detachedXmlComment, 2, detachedXmlComment, 6], point 62 [xmlDoc, 5]":true, + "Range 55 [detachedXmlComment, 2, detachedXmlComment, 6], point 63 [xmlComment, 0]":true, + "Range 55 [detachedXmlComment, 2, detachedXmlComment, 6], point 64 [xmlComment, 4]":true, + "Range 55 [detachedXmlComment, 2, detachedXmlComment, 6], point 65 [processingInstruction, 0]":true, + "Range 55 [detachedXmlComment, 2, detachedXmlComment, 6], point 66 [processingInstruction, 5]":true, + "Range 55 [detachedXmlComment, 2, detachedXmlComment, 6], point 67 [processingInstruction, 9]":true, + "Range 55 [detachedXmlComment, 2, detachedXmlComment, 6], point 70 [detachedForeignTextNode, 0]":true, + "Range 55 [detachedXmlComment, 2, detachedXmlComment, 6], point 71 [detachedForeignTextNode, 8]":true, + "Range 55 [detachedXmlComment, 2, detachedXmlComment, 6], point 72 [detachedXmlTextNode, 0]":true, + "Range 55 [detachedXmlComment, 2, detachedXmlComment, 6], point 73 [detachedXmlTextNode, 8]":true, + "Range 55 [detachedXmlComment, 2, detachedXmlComment, 6], point 74 [detachedProcessingInstruction, 12]":true, + "Range 55 [detachedXmlComment, 2, detachedXmlComment, 6], point 77 [detachedForeignComment, 0]":true, + "Range 55 [detachedXmlComment, 2, detachedXmlComment, 6], point 78 [detachedForeignComment, 4]":true, + "Range 55 [detachedXmlComment, 2, detachedXmlComment, 6], point 79 [detachedXmlComment, 2]":true, + "Range 55 [detachedXmlComment, 2, detachedXmlComment, 6], point 81 [foreignDocfrag, 0]":true, + "Range 55 [detachedXmlComment, 2, detachedXmlComment, 6], point 82 [xmlDocfrag, 0]":true, + "Range 55 [detachedXmlComment, 2, detachedXmlComment, 6], point 86 [foreignDoctype, 0]":true, + "Range 55 [detachedXmlComment, 2, detachedXmlComment, 6], point 87 [xmlDoctype, 0]":true, + "Range 56 [docfrag, 0, docfrag, 0], point 20 [foreignPara1.firstChild, 0]":true, + "Range 56 [docfrag, 0, docfrag, 0], point 21 [foreignPara1.firstChild, 1]":true, + "Range 56 [docfrag, 0, docfrag, 0], point 22 [foreignPara1.firstChild, 8]":true, + "Range 56 [docfrag, 0, docfrag, 0], point 23 [foreignPara1.firstChild, 9]":true, + "Range 56 [docfrag, 0, docfrag, 0], point 31 [foreignDoc.documentElement, 0]":true, + "Range 56 [docfrag, 0, docfrag, 0], point 32 [foreignDoc.documentElement, 1]":true, + "Range 56 [docfrag, 0, docfrag, 0], point 33 [foreignDoc.head, 0]":true, + "Range 56 [docfrag, 0, docfrag, 0], point 34 [foreignDoc.body, 1]":true, + "Range 56 [docfrag, 0, docfrag, 0], point 54 [foreignDoc, 0]":true, + "Range 56 [docfrag, 0, docfrag, 0], point 55 [foreignDoc, 1]":true, + "Range 56 [docfrag, 0, docfrag, 0], point 56 [foreignComment, 2]":true, + "Range 56 [docfrag, 0, docfrag, 0], point 57 [foreignTextNode, 0]":true, + "Range 56 [docfrag, 0, docfrag, 0], point 58 [foreignTextNode, 36]":true, + "Range 56 [docfrag, 0, docfrag, 0], point 59 [xmlDoc, -1]":true, + "Range 56 [docfrag, 0, docfrag, 0], point 60 [xmlDoc, 0]":true, + "Range 56 [docfrag, 0, docfrag, 0], point 61 [xmlDoc, 1]":true, + "Range 56 [docfrag, 0, docfrag, 0], point 62 [xmlDoc, 5]":true, + "Range 56 [docfrag, 0, docfrag, 0], point 63 [xmlComment, 0]":true, + "Range 56 [docfrag, 0, docfrag, 0], point 64 [xmlComment, 4]":true, + "Range 56 [docfrag, 0, docfrag, 0], point 65 [processingInstruction, 0]":true, + "Range 56 [docfrag, 0, docfrag, 0], point 66 [processingInstruction, 5]":true, + "Range 56 [docfrag, 0, docfrag, 0], point 67 [processingInstruction, 9]":true, + "Range 56 [docfrag, 0, docfrag, 0], point 70 [detachedForeignTextNode, 0]":true, + "Range 56 [docfrag, 0, docfrag, 0], point 71 [detachedForeignTextNode, 8]":true, + "Range 56 [docfrag, 0, docfrag, 0], point 72 [detachedXmlTextNode, 0]":true, + "Range 56 [docfrag, 0, docfrag, 0], point 73 [detachedXmlTextNode, 8]":true, + "Range 56 [docfrag, 0, docfrag, 0], point 74 [detachedProcessingInstruction, 12]":true, + "Range 56 [docfrag, 0, docfrag, 0], point 77 [detachedForeignComment, 0]":true, + "Range 56 [docfrag, 0, docfrag, 0], point 78 [detachedForeignComment, 4]":true, + "Range 56 [docfrag, 0, docfrag, 0], point 79 [detachedXmlComment, 2]":true, + "Range 56 [docfrag, 0, docfrag, 0], point 81 [foreignDocfrag, 0]":true, + "Range 56 [docfrag, 0, docfrag, 0], point 82 [xmlDocfrag, 0]":true, + "Range 56 [docfrag, 0, docfrag, 0], point 86 [foreignDoctype, 0]":true, + "Range 56 [docfrag, 0, docfrag, 0], point 87 [xmlDoctype, 0]":true, + "Range 57 [foreignDocfrag, 0, foreignDocfrag, 0], point 20 [foreignPara1.firstChild, 0]":true, + "Range 57 [foreignDocfrag, 0, foreignDocfrag, 0], point 21 [foreignPara1.firstChild, 1]":true, + "Range 57 [foreignDocfrag, 0, foreignDocfrag, 0], point 22 [foreignPara1.firstChild, 8]":true, + "Range 57 [foreignDocfrag, 0, foreignDocfrag, 0], point 23 [foreignPara1.firstChild, 9]":true, + "Range 57 [foreignDocfrag, 0, foreignDocfrag, 0], point 31 [foreignDoc.documentElement, 0]":true, + "Range 57 [foreignDocfrag, 0, foreignDocfrag, 0], point 32 [foreignDoc.documentElement, 1]":true, + "Range 57 [foreignDocfrag, 0, foreignDocfrag, 0], point 33 [foreignDoc.head, 0]":true, + "Range 57 [foreignDocfrag, 0, foreignDocfrag, 0], point 34 [foreignDoc.body, 1]":true, + "Range 57 [foreignDocfrag, 0, foreignDocfrag, 0], point 54 [foreignDoc, 0]":true, + "Range 57 [foreignDocfrag, 0, foreignDocfrag, 0], point 55 [foreignDoc, 1]":true, + "Range 57 [foreignDocfrag, 0, foreignDocfrag, 0], point 56 [foreignComment, 2]":true, + "Range 57 [foreignDocfrag, 0, foreignDocfrag, 0], point 57 [foreignTextNode, 0]":true, + "Range 57 [foreignDocfrag, 0, foreignDocfrag, 0], point 58 [foreignTextNode, 36]":true, + "Range 57 [foreignDocfrag, 0, foreignDocfrag, 0], point 59 [xmlDoc, -1]":true, + "Range 57 [foreignDocfrag, 0, foreignDocfrag, 0], point 60 [xmlDoc, 0]":true, + "Range 57 [foreignDocfrag, 0, foreignDocfrag, 0], point 61 [xmlDoc, 1]":true, + "Range 57 [foreignDocfrag, 0, foreignDocfrag, 0], point 62 [xmlDoc, 5]":true, + "Range 57 [foreignDocfrag, 0, foreignDocfrag, 0], point 63 [xmlComment, 0]":true, + "Range 57 [foreignDocfrag, 0, foreignDocfrag, 0], point 64 [xmlComment, 4]":true, + "Range 57 [foreignDocfrag, 0, foreignDocfrag, 0], point 65 [processingInstruction, 0]":true, + "Range 57 [foreignDocfrag, 0, foreignDocfrag, 0], point 66 [processingInstruction, 5]":true, + "Range 57 [foreignDocfrag, 0, foreignDocfrag, 0], point 67 [processingInstruction, 9]":true, + "Range 57 [foreignDocfrag, 0, foreignDocfrag, 0], point 70 [detachedForeignTextNode, 0]":true, + "Range 57 [foreignDocfrag, 0, foreignDocfrag, 0], point 71 [detachedForeignTextNode, 8]":true, + "Range 57 [foreignDocfrag, 0, foreignDocfrag, 0], point 72 [detachedXmlTextNode, 0]":true, + "Range 57 [foreignDocfrag, 0, foreignDocfrag, 0], point 73 [detachedXmlTextNode, 8]":true, + "Range 57 [foreignDocfrag, 0, foreignDocfrag, 0], point 74 [detachedProcessingInstruction, 12]":true, + "Range 57 [foreignDocfrag, 0, foreignDocfrag, 0], point 77 [detachedForeignComment, 0]":true, + "Range 57 [foreignDocfrag, 0, foreignDocfrag, 0], point 78 [detachedForeignComment, 4]":true, + "Range 57 [foreignDocfrag, 0, foreignDocfrag, 0], point 79 [detachedXmlComment, 2]":true, + "Range 57 [foreignDocfrag, 0, foreignDocfrag, 0], point 81 [foreignDocfrag, 0]":true, + "Range 57 [foreignDocfrag, 0, foreignDocfrag, 0], point 82 [xmlDocfrag, 0]":true, + "Range 57 [foreignDocfrag, 0, foreignDocfrag, 0], point 86 [foreignDoctype, 0]":true, + "Range 57 [foreignDocfrag, 0, foreignDocfrag, 0], point 87 [xmlDoctype, 0]":true, + "Range 58 [xmlDocfrag, 0, xmlDocfrag, 0], point 20 [foreignPara1.firstChild, 0]":true, + "Range 58 [xmlDocfrag, 0, xmlDocfrag, 0], point 21 [foreignPara1.firstChild, 1]":true, + "Range 58 [xmlDocfrag, 0, xmlDocfrag, 0], point 22 [foreignPara1.firstChild, 8]":true, + "Range 58 [xmlDocfrag, 0, xmlDocfrag, 0], point 23 [foreignPara1.firstChild, 9]":true, + "Range 58 [xmlDocfrag, 0, xmlDocfrag, 0], point 31 [foreignDoc.documentElement, 0]":true, + "Range 58 [xmlDocfrag, 0, xmlDocfrag, 0], point 32 [foreignDoc.documentElement, 1]":true, + "Range 58 [xmlDocfrag, 0, xmlDocfrag, 0], point 33 [foreignDoc.head, 0]":true, + "Range 58 [xmlDocfrag, 0, xmlDocfrag, 0], point 34 [foreignDoc.body, 1]":true, + "Range 58 [xmlDocfrag, 0, xmlDocfrag, 0], point 54 [foreignDoc, 0]":true, + "Range 58 [xmlDocfrag, 0, xmlDocfrag, 0], point 55 [foreignDoc, 1]":true, + "Range 58 [xmlDocfrag, 0, xmlDocfrag, 0], point 56 [foreignComment, 2]":true, + "Range 58 [xmlDocfrag, 0, xmlDocfrag, 0], point 57 [foreignTextNode, 0]":true, + "Range 58 [xmlDocfrag, 0, xmlDocfrag, 0], point 58 [foreignTextNode, 36]":true, + "Range 58 [xmlDocfrag, 0, xmlDocfrag, 0], point 59 [xmlDoc, -1]":true, + "Range 58 [xmlDocfrag, 0, xmlDocfrag, 0], point 60 [xmlDoc, 0]":true, + "Range 58 [xmlDocfrag, 0, xmlDocfrag, 0], point 61 [xmlDoc, 1]":true, + "Range 58 [xmlDocfrag, 0, xmlDocfrag, 0], point 62 [xmlDoc, 5]":true, + "Range 58 [xmlDocfrag, 0, xmlDocfrag, 0], point 63 [xmlComment, 0]":true, + "Range 58 [xmlDocfrag, 0, xmlDocfrag, 0], point 64 [xmlComment, 4]":true, + "Range 58 [xmlDocfrag, 0, xmlDocfrag, 0], point 65 [processingInstruction, 0]":true, + "Range 58 [xmlDocfrag, 0, xmlDocfrag, 0], point 66 [processingInstruction, 5]":true, + "Range 58 [xmlDocfrag, 0, xmlDocfrag, 0], point 67 [processingInstruction, 9]":true, + "Range 58 [xmlDocfrag, 0, xmlDocfrag, 0], point 70 [detachedForeignTextNode, 0]":true, + "Range 58 [xmlDocfrag, 0, xmlDocfrag, 0], point 71 [detachedForeignTextNode, 8]":true, + "Range 58 [xmlDocfrag, 0, xmlDocfrag, 0], point 72 [detachedXmlTextNode, 0]":true, + "Range 58 [xmlDocfrag, 0, xmlDocfrag, 0], point 73 [detachedXmlTextNode, 8]":true, + "Range 58 [xmlDocfrag, 0, xmlDocfrag, 0], point 74 [detachedProcessingInstruction, 12]":true, + "Range 58 [xmlDocfrag, 0, xmlDocfrag, 0], point 77 [detachedForeignComment, 0]":true, + "Range 58 [xmlDocfrag, 0, xmlDocfrag, 0], point 78 [detachedForeignComment, 4]":true, + "Range 58 [xmlDocfrag, 0, xmlDocfrag, 0], point 79 [detachedXmlComment, 2]":true, + "Range 58 [xmlDocfrag, 0, xmlDocfrag, 0], point 81 [foreignDocfrag, 0]":true, + "Range 58 [xmlDocfrag, 0, xmlDocfrag, 0], point 82 [xmlDocfrag, 0]":true, + "Range 58 [xmlDocfrag, 0, xmlDocfrag, 0], point 86 [foreignDoctype, 0]":true, + "Range 58 [xmlDocfrag, 0, xmlDocfrag, 0], point 87 [xmlDoctype, 0]":true +} diff --git a/dom/imptests/failures/editing/selecttest/test_collapseToStartEnd.html.json b/dom/imptests/failures/editing/selecttest/test_collapseToStartEnd.html.json new file mode 100644 index 00000000000..6375d859c5d --- /dev/null +++ b/dom/imptests/failures/editing/selecttest/test_collapseToStartEnd.html.json @@ -0,0 +1,44 @@ +{ + "Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0] collapseToStart()":true, + "Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0] collapseToEnd()":true, + "Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] collapseToStart()":true, + "Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] collapseToEnd()":true, + "Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] collapseToStart()":true, + "Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] collapseToEnd()":true, + "Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] collapseToStart()":true, + "Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] collapseToEnd()":true, + "Range 21 [foreignDoc.head, 1, foreignDoc.head, 1] collapseToStart()":true, + "Range 21 [foreignDoc.head, 1, foreignDoc.head, 1] collapseToEnd()":true, + "Range 22 [foreignDoc.body, 0, foreignDoc.body, 0] collapseToStart()":true, + "Range 22 [foreignDoc.body, 0, foreignDoc.body, 0] collapseToEnd()":true, + "Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] collapseToStart()":true, + "Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] collapseToEnd()":true, + "Range 41 [foreignDoc, 0, foreignDoc, 0] collapseToStart()":true, + "Range 41 [foreignDoc, 0, foreignDoc, 0] collapseToEnd()":true, + "Range 42 [foreignDoc, 1, foreignComment, 2] collapseToStart()":true, + "Range 42 [foreignDoc, 1, foreignComment, 2] collapseToEnd()":true, + "Range 43 [foreignDoc.body, 0, foreignTextNode, 36] collapseToStart()":true, + "Range 43 [foreignDoc.body, 0, foreignTextNode, 36] collapseToEnd()":true, + "Range 44 [xmlDoc, 0, xmlDoc, 0] collapseToStart()":true, + "Range 44 [xmlDoc, 0, xmlDoc, 0] collapseToEnd()":true, + "Range 45 [xmlDoc, 1, xmlComment, 0] collapseToStart()":true, + "Range 45 [xmlDoc, 1, xmlComment, 0] collapseToEnd()":true, + "Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7] collapseToStart()":true, + "Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7] collapseToEnd()":true, + "Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] collapseToStart()":true, + "Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] collapseToEnd()":true, + "Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7] collapseToStart()":true, + "Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7] collapseToEnd()":true, + "Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] collapseToStart()":true, + "Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] collapseToEnd()":true, + "Range 53 [detachedForeignComment, 0, detachedForeignComment, 1] collapseToStart()":true, + "Range 53 [detachedForeignComment, 0, detachedForeignComment, 1] collapseToEnd()":true, + "Range 54 [detachedForeignComment, 4, detachedForeignComment, 4] collapseToStart()":true, + "Range 54 [detachedForeignComment, 4, detachedForeignComment, 4] collapseToEnd()":true, + "Range 55 [detachedXmlComment, 2, detachedXmlComment, 6] collapseToStart()":true, + "Range 55 [detachedXmlComment, 2, detachedXmlComment, 6] collapseToEnd()":true, + "Range 57 [foreignDocfrag, 0, foreignDocfrag, 0] collapseToStart()":true, + "Range 57 [foreignDocfrag, 0, foreignDocfrag, 0] collapseToEnd()":true, + "Range 58 [xmlDocfrag, 0, xmlDocfrag, 0] collapseToStart()":true, + "Range 58 [xmlDocfrag, 0, xmlDocfrag, 0] collapseToEnd()":true +} diff --git a/dom/imptests/failures/editing/selecttest/test_extend.html.json b/dom/imptests/failures/editing/selecttest/test_extend.html.json new file mode 100644 index 00000000000..400ba7a281f --- /dev/null +++ b/dom/imptests/failures/editing/selecttest/test_extend.html.json @@ -0,0 +1,3928 @@ +{ + "extend() with range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() with range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() with range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() with range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() with range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() with range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() with range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0] and point 33 [foreignDoc.head, 0]":true, + "extend() with range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0] and point 34 [foreignDoc.body, 1]":true, + "extend() with range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0] and point 54 [foreignDoc, 0]":true, + "extend() with range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0] and point 55 [foreignDoc, 1]":true, + "extend() with range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0] and point 56 [foreignComment, 2]":true, + "extend() with range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0] and point 57 [foreignTextNode, 0]":true, + "extend() with range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0] and point 58 [foreignTextNode, 36]":true, + "extend() with range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0] and point 59 [xmlDoc, -1]":true, + "extend() with range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0] and point 60 [xmlDoc, 0]":true, + "extend() with range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0] and point 61 [xmlDoc, 1]":true, + "extend() with range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0] and point 62 [xmlDoc, 5]":true, + "extend() with range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0] and point 63 [xmlComment, 0]":true, + "extend() with range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0] and point 64 [xmlComment, 4]":true, + "extend() with range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0] and point 65 [processingInstruction, 0]":true, + "extend() with range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0] and point 66 [processingInstruction, 5]":true, + "extend() with range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0] and point 67 [processingInstruction, 9]":true, + "extend() with range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0] and point 70 [detachedForeignTextNode, 0]":true, + "extend() with range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0] and point 71 [detachedForeignTextNode, 8]":true, + "extend() with range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0] and point 72 [detachedXmlTextNode, 0]":true, + "extend() with range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0] and point 73 [detachedXmlTextNode, 8]":true, + "extend() with range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() with range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0] and point 77 [detachedForeignComment, 0]":true, + "extend() with range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0] and point 78 [detachedForeignComment, 4]":true, + "extend() with range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0] and point 79 [detachedXmlComment, 2]":true, + "extend() with range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0] and point 81 [foreignDocfrag, 0]":true, + "extend() with range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0] and point 82 [xmlDocfrag, 0]":true, + "extend() with range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0] and point 86 [foreignDoctype, 0]":true, + "extend() with range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0] and point 87 [xmlDoctype, 0]":true, + "extend() forwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() backwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() forwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() backwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() forwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() backwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() forwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() backwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() forwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() backwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() forwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() backwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() forwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 33 [foreignDoc.head, 0]":true, + "extend() backwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 33 [foreignDoc.head, 0]":true, + "extend() forwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 34 [foreignDoc.body, 1]":true, + "extend() backwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 34 [foreignDoc.body, 1]":true, + "extend() forwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 54 [foreignDoc, 0]":true, + "extend() backwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 54 [foreignDoc, 0]":true, + "extend() forwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 55 [foreignDoc, 1]":true, + "extend() backwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 55 [foreignDoc, 1]":true, + "extend() forwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 56 [foreignComment, 2]":true, + "extend() backwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 56 [foreignComment, 2]":true, + "extend() forwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 57 [foreignTextNode, 0]":true, + "extend() backwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 57 [foreignTextNode, 0]":true, + "extend() forwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 58 [foreignTextNode, 36]":true, + "extend() backwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 58 [foreignTextNode, 36]":true, + "extend() forwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 59 [xmlDoc, -1]":true, + "extend() backwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 59 [xmlDoc, -1]":true, + "extend() forwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 60 [xmlDoc, 0]":true, + "extend() backwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 60 [xmlDoc, 0]":true, + "extend() forwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 61 [xmlDoc, 1]":true, + "extend() backwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 61 [xmlDoc, 1]":true, + "extend() forwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 62 [xmlDoc, 5]":true, + "extend() backwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 62 [xmlDoc, 5]":true, + "extend() forwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 63 [xmlComment, 0]":true, + "extend() backwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 63 [xmlComment, 0]":true, + "extend() forwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 64 [xmlComment, 4]":true, + "extend() backwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 64 [xmlComment, 4]":true, + "extend() forwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 65 [processingInstruction, 0]":true, + "extend() backwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 65 [processingInstruction, 0]":true, + "extend() forwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 66 [processingInstruction, 5]":true, + "extend() backwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 66 [processingInstruction, 5]":true, + "extend() forwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 67 [processingInstruction, 9]":true, + "extend() backwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 67 [processingInstruction, 9]":true, + "extend() forwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 70 [detachedForeignTextNode, 0]":true, + "extend() backwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 70 [detachedForeignTextNode, 0]":true, + "extend() forwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 71 [detachedForeignTextNode, 8]":true, + "extend() backwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 71 [detachedForeignTextNode, 8]":true, + "extend() forwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 72 [detachedXmlTextNode, 0]":true, + "extend() backwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 72 [detachedXmlTextNode, 0]":true, + "extend() forwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 73 [detachedXmlTextNode, 8]":true, + "extend() backwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 73 [detachedXmlTextNode, 8]":true, + "extend() forwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() backwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() forwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 77 [detachedForeignComment, 0]":true, + "extend() backwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 77 [detachedForeignComment, 0]":true, + "extend() forwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 78 [detachedForeignComment, 4]":true, + "extend() backwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 78 [detachedForeignComment, 4]":true, + "extend() forwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 79 [detachedXmlComment, 2]":true, + "extend() backwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 79 [detachedXmlComment, 2]":true, + "extend() forwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 81 [foreignDocfrag, 0]":true, + "extend() backwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 81 [foreignDocfrag, 0]":true, + "extend() forwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 82 [xmlDocfrag, 0]":true, + "extend() backwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 82 [xmlDocfrag, 0]":true, + "extend() forwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 86 [foreignDoctype, 0]":true, + "extend() backwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 86 [foreignDoctype, 0]":true, + "extend() forwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 87 [xmlDoctype, 0]":true, + "extend() backwards with range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1] and point 87 [xmlDoctype, 0]":true, + "extend() forwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() backwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() forwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() backwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() forwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() backwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() forwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() backwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() forwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() backwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() forwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() backwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() forwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 33 [foreignDoc.head, 0]":true, + "extend() backwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 33 [foreignDoc.head, 0]":true, + "extend() forwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 34 [foreignDoc.body, 1]":true, + "extend() backwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 34 [foreignDoc.body, 1]":true, + "extend() forwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 54 [foreignDoc, 0]":true, + "extend() backwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 54 [foreignDoc, 0]":true, + "extend() forwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 55 [foreignDoc, 1]":true, + "extend() backwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 55 [foreignDoc, 1]":true, + "extend() forwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 56 [foreignComment, 2]":true, + "extend() backwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 56 [foreignComment, 2]":true, + "extend() forwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 57 [foreignTextNode, 0]":true, + "extend() backwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 57 [foreignTextNode, 0]":true, + "extend() forwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 58 [foreignTextNode, 36]":true, + "extend() backwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 58 [foreignTextNode, 36]":true, + "extend() forwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 59 [xmlDoc, -1]":true, + "extend() backwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 59 [xmlDoc, -1]":true, + "extend() forwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 60 [xmlDoc, 0]":true, + "extend() backwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 60 [xmlDoc, 0]":true, + "extend() forwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 61 [xmlDoc, 1]":true, + "extend() backwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 61 [xmlDoc, 1]":true, + "extend() forwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 62 [xmlDoc, 5]":true, + "extend() backwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 62 [xmlDoc, 5]":true, + "extend() forwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 63 [xmlComment, 0]":true, + "extend() backwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 63 [xmlComment, 0]":true, + "extend() forwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 64 [xmlComment, 4]":true, + "extend() backwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 64 [xmlComment, 4]":true, + "extend() forwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 65 [processingInstruction, 0]":true, + "extend() backwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 65 [processingInstruction, 0]":true, + "extend() forwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 66 [processingInstruction, 5]":true, + "extend() backwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 66 [processingInstruction, 5]":true, + "extend() forwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 67 [processingInstruction, 9]":true, + "extend() backwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 67 [processingInstruction, 9]":true, + "extend() forwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 70 [detachedForeignTextNode, 0]":true, + "extend() backwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 70 [detachedForeignTextNode, 0]":true, + "extend() forwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 71 [detachedForeignTextNode, 8]":true, + "extend() backwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 71 [detachedForeignTextNode, 8]":true, + "extend() forwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 72 [detachedXmlTextNode, 0]":true, + "extend() backwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 72 [detachedXmlTextNode, 0]":true, + "extend() forwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 73 [detachedXmlTextNode, 8]":true, + "extend() backwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 73 [detachedXmlTextNode, 8]":true, + "extend() forwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() backwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() forwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 77 [detachedForeignComment, 0]":true, + "extend() backwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 77 [detachedForeignComment, 0]":true, + "extend() forwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 78 [detachedForeignComment, 4]":true, + "extend() backwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 78 [detachedForeignComment, 4]":true, + "extend() forwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 79 [detachedXmlComment, 2]":true, + "extend() backwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 79 [detachedXmlComment, 2]":true, + "extend() forwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 81 [foreignDocfrag, 0]":true, + "extend() backwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 81 [foreignDocfrag, 0]":true, + "extend() forwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 82 [xmlDocfrag, 0]":true, + "extend() backwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 82 [xmlDocfrag, 0]":true, + "extend() forwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 86 [foreignDoctype, 0]":true, + "extend() backwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 86 [foreignDoctype, 0]":true, + "extend() forwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 87 [xmlDoctype, 0]":true, + "extend() backwards with range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8] and point 87 [xmlDoctype, 0]":true, + "extend() forwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() backwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() forwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() backwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() forwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() backwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() forwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() backwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() forwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() backwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() forwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() backwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() forwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 33 [foreignDoc.head, 0]":true, + "extend() backwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 33 [foreignDoc.head, 0]":true, + "extend() forwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 34 [foreignDoc.body, 1]":true, + "extend() backwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 34 [foreignDoc.body, 1]":true, + "extend() forwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 54 [foreignDoc, 0]":true, + "extend() backwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 54 [foreignDoc, 0]":true, + "extend() forwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 55 [foreignDoc, 1]":true, + "extend() backwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 55 [foreignDoc, 1]":true, + "extend() forwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 56 [foreignComment, 2]":true, + "extend() backwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 56 [foreignComment, 2]":true, + "extend() forwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 57 [foreignTextNode, 0]":true, + "extend() backwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 57 [foreignTextNode, 0]":true, + "extend() forwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 58 [foreignTextNode, 36]":true, + "extend() backwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 58 [foreignTextNode, 36]":true, + "extend() forwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 59 [xmlDoc, -1]":true, + "extend() backwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 59 [xmlDoc, -1]":true, + "extend() forwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 60 [xmlDoc, 0]":true, + "extend() backwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 60 [xmlDoc, 0]":true, + "extend() forwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 61 [xmlDoc, 1]":true, + "extend() backwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 61 [xmlDoc, 1]":true, + "extend() forwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 62 [xmlDoc, 5]":true, + "extend() backwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 62 [xmlDoc, 5]":true, + "extend() forwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 63 [xmlComment, 0]":true, + "extend() backwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 63 [xmlComment, 0]":true, + "extend() forwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 64 [xmlComment, 4]":true, + "extend() backwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 64 [xmlComment, 4]":true, + "extend() forwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 65 [processingInstruction, 0]":true, + "extend() backwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 65 [processingInstruction, 0]":true, + "extend() forwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 66 [processingInstruction, 5]":true, + "extend() backwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 66 [processingInstruction, 5]":true, + "extend() forwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 67 [processingInstruction, 9]":true, + "extend() backwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 67 [processingInstruction, 9]":true, + "extend() forwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 70 [detachedForeignTextNode, 0]":true, + "extend() backwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 70 [detachedForeignTextNode, 0]":true, + "extend() forwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 71 [detachedForeignTextNode, 8]":true, + "extend() backwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 71 [detachedForeignTextNode, 8]":true, + "extend() forwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 72 [detachedXmlTextNode, 0]":true, + "extend() backwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 72 [detachedXmlTextNode, 0]":true, + "extend() forwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 73 [detachedXmlTextNode, 8]":true, + "extend() backwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 73 [detachedXmlTextNode, 8]":true, + "extend() forwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() backwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() forwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 77 [detachedForeignComment, 0]":true, + "extend() backwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 77 [detachedForeignComment, 0]":true, + "extend() forwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 78 [detachedForeignComment, 4]":true, + "extend() backwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 78 [detachedForeignComment, 4]":true, + "extend() forwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 79 [detachedXmlComment, 2]":true, + "extend() backwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 79 [detachedXmlComment, 2]":true, + "extend() forwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 81 [foreignDocfrag, 0]":true, + "extend() backwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 81 [foreignDocfrag, 0]":true, + "extend() forwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 82 [xmlDocfrag, 0]":true, + "extend() backwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 82 [xmlDocfrag, 0]":true, + "extend() forwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 86 [foreignDoctype, 0]":true, + "extend() backwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 86 [foreignDoctype, 0]":true, + "extend() forwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 87 [xmlDoctype, 0]":true, + "extend() backwards with range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9] and point 87 [xmlDoctype, 0]":true, + "extend() with range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() with range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() with range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() with range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() with range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() with range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() with range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0] and point 33 [foreignDoc.head, 0]":true, + "extend() with range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0] and point 34 [foreignDoc.body, 1]":true, + "extend() with range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0] and point 54 [foreignDoc, 0]":true, + "extend() with range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0] and point 55 [foreignDoc, 1]":true, + "extend() with range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0] and point 56 [foreignComment, 2]":true, + "extend() with range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0] and point 57 [foreignTextNode, 0]":true, + "extend() with range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0] and point 58 [foreignTextNode, 36]":true, + "extend() with range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0] and point 59 [xmlDoc, -1]":true, + "extend() with range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0] and point 60 [xmlDoc, 0]":true, + "extend() with range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0] and point 61 [xmlDoc, 1]":true, + "extend() with range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0] and point 62 [xmlDoc, 5]":true, + "extend() with range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0] and point 63 [xmlComment, 0]":true, + "extend() with range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0] and point 64 [xmlComment, 4]":true, + "extend() with range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0] and point 65 [processingInstruction, 0]":true, + "extend() with range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0] and point 66 [processingInstruction, 5]":true, + "extend() with range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0] and point 67 [processingInstruction, 9]":true, + "extend() with range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0] and point 70 [detachedForeignTextNode, 0]":true, + "extend() with range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0] and point 71 [detachedForeignTextNode, 8]":true, + "extend() with range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0] and point 72 [detachedXmlTextNode, 0]":true, + "extend() with range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0] and point 73 [detachedXmlTextNode, 8]":true, + "extend() with range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() with range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0] and point 77 [detachedForeignComment, 0]":true, + "extend() with range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0] and point 78 [detachedForeignComment, 4]":true, + "extend() with range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0] and point 79 [detachedXmlComment, 2]":true, + "extend() with range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0] and point 81 [foreignDocfrag, 0]":true, + "extend() with range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0] and point 82 [xmlDocfrag, 0]":true, + "extend() with range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0] and point 86 [foreignDoctype, 0]":true, + "extend() with range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0] and point 87 [xmlDoctype, 0]":true, + "extend() forwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() backwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() forwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() backwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() forwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() backwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() forwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() backwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() forwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() backwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() forwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() backwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() forwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 33 [foreignDoc.head, 0]":true, + "extend() backwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 33 [foreignDoc.head, 0]":true, + "extend() forwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 34 [foreignDoc.body, 1]":true, + "extend() backwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 34 [foreignDoc.body, 1]":true, + "extend() forwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 54 [foreignDoc, 0]":true, + "extend() backwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 54 [foreignDoc, 0]":true, + "extend() forwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 55 [foreignDoc, 1]":true, + "extend() backwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 55 [foreignDoc, 1]":true, + "extend() forwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 56 [foreignComment, 2]":true, + "extend() backwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 56 [foreignComment, 2]":true, + "extend() forwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 57 [foreignTextNode, 0]":true, + "extend() backwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 57 [foreignTextNode, 0]":true, + "extend() forwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 58 [foreignTextNode, 36]":true, + "extend() backwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 58 [foreignTextNode, 36]":true, + "extend() forwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 59 [xmlDoc, -1]":true, + "extend() backwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 59 [xmlDoc, -1]":true, + "extend() forwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 60 [xmlDoc, 0]":true, + "extend() backwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 60 [xmlDoc, 0]":true, + "extend() forwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 61 [xmlDoc, 1]":true, + "extend() backwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 61 [xmlDoc, 1]":true, + "extend() forwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 62 [xmlDoc, 5]":true, + "extend() backwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 62 [xmlDoc, 5]":true, + "extend() forwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 63 [xmlComment, 0]":true, + "extend() backwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 63 [xmlComment, 0]":true, + "extend() forwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 64 [xmlComment, 4]":true, + "extend() backwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 64 [xmlComment, 4]":true, + "extend() forwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 65 [processingInstruction, 0]":true, + "extend() backwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 65 [processingInstruction, 0]":true, + "extend() forwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 66 [processingInstruction, 5]":true, + "extend() backwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 66 [processingInstruction, 5]":true, + "extend() forwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 67 [processingInstruction, 9]":true, + "extend() backwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 67 [processingInstruction, 9]":true, + "extend() forwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 70 [detachedForeignTextNode, 0]":true, + "extend() backwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 70 [detachedForeignTextNode, 0]":true, + "extend() forwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 71 [detachedForeignTextNode, 8]":true, + "extend() backwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 71 [detachedForeignTextNode, 8]":true, + "extend() forwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 72 [detachedXmlTextNode, 0]":true, + "extend() backwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 72 [detachedXmlTextNode, 0]":true, + "extend() forwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 73 [detachedXmlTextNode, 8]":true, + "extend() backwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 73 [detachedXmlTextNode, 8]":true, + "extend() forwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() backwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() forwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 77 [detachedForeignComment, 0]":true, + "extend() backwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 77 [detachedForeignComment, 0]":true, + "extend() forwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 78 [detachedForeignComment, 4]":true, + "extend() backwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 78 [detachedForeignComment, 4]":true, + "extend() forwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 79 [detachedXmlComment, 2]":true, + "extend() backwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 79 [detachedXmlComment, 2]":true, + "extend() forwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 81 [foreignDocfrag, 0]":true, + "extend() backwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 81 [foreignDocfrag, 0]":true, + "extend() forwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 82 [xmlDocfrag, 0]":true, + "extend() backwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 82 [xmlDocfrag, 0]":true, + "extend() forwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 86 [foreignDoctype, 0]":true, + "extend() backwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 86 [foreignDoctype, 0]":true, + "extend() forwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 87 [xmlDoctype, 0]":true, + "extend() backwards with range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1] and point 87 [xmlDoctype, 0]":true, + "extend() forwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() backwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() forwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() backwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() forwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() backwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() forwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() backwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() forwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() backwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() forwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() backwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() forwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 33 [foreignDoc.head, 0]":true, + "extend() backwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 33 [foreignDoc.head, 0]":true, + "extend() forwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 34 [foreignDoc.body, 1]":true, + "extend() backwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 34 [foreignDoc.body, 1]":true, + "extend() forwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 54 [foreignDoc, 0]":true, + "extend() backwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 54 [foreignDoc, 0]":true, + "extend() forwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 55 [foreignDoc, 1]":true, + "extend() backwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 55 [foreignDoc, 1]":true, + "extend() forwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 56 [foreignComment, 2]":true, + "extend() backwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 56 [foreignComment, 2]":true, + "extend() forwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 57 [foreignTextNode, 0]":true, + "extend() backwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 57 [foreignTextNode, 0]":true, + "extend() forwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 58 [foreignTextNode, 36]":true, + "extend() backwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 58 [foreignTextNode, 36]":true, + "extend() forwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 59 [xmlDoc, -1]":true, + "extend() backwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 59 [xmlDoc, -1]":true, + "extend() forwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 60 [xmlDoc, 0]":true, + "extend() backwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 60 [xmlDoc, 0]":true, + "extend() forwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 61 [xmlDoc, 1]":true, + "extend() backwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 61 [xmlDoc, 1]":true, + "extend() forwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 62 [xmlDoc, 5]":true, + "extend() backwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 62 [xmlDoc, 5]":true, + "extend() forwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 63 [xmlComment, 0]":true, + "extend() backwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 63 [xmlComment, 0]":true, + "extend() forwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 64 [xmlComment, 4]":true, + "extend() backwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 64 [xmlComment, 4]":true, + "extend() forwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 65 [processingInstruction, 0]":true, + "extend() backwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 65 [processingInstruction, 0]":true, + "extend() forwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 66 [processingInstruction, 5]":true, + "extend() backwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 66 [processingInstruction, 5]":true, + "extend() forwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 67 [processingInstruction, 9]":true, + "extend() backwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 67 [processingInstruction, 9]":true, + "extend() forwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 70 [detachedForeignTextNode, 0]":true, + "extend() backwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 70 [detachedForeignTextNode, 0]":true, + "extend() forwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 71 [detachedForeignTextNode, 8]":true, + "extend() backwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 71 [detachedForeignTextNode, 8]":true, + "extend() forwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 72 [detachedXmlTextNode, 0]":true, + "extend() backwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 72 [detachedXmlTextNode, 0]":true, + "extend() forwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 73 [detachedXmlTextNode, 8]":true, + "extend() backwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 73 [detachedXmlTextNode, 8]":true, + "extend() forwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() backwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() forwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 77 [detachedForeignComment, 0]":true, + "extend() backwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 77 [detachedForeignComment, 0]":true, + "extend() forwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 78 [detachedForeignComment, 4]":true, + "extend() backwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 78 [detachedForeignComment, 4]":true, + "extend() forwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 79 [detachedXmlComment, 2]":true, + "extend() backwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 79 [detachedXmlComment, 2]":true, + "extend() forwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 81 [foreignDocfrag, 0]":true, + "extend() backwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 81 [foreignDocfrag, 0]":true, + "extend() forwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 82 [xmlDocfrag, 0]":true, + "extend() backwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 82 [xmlDocfrag, 0]":true, + "extend() forwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 86 [foreignDoctype, 0]":true, + "extend() backwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 86 [foreignDoctype, 0]":true, + "extend() forwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 87 [xmlDoctype, 0]":true, + "extend() backwards with range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8] and point 87 [xmlDoctype, 0]":true, + "extend() forwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() backwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() forwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() backwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() forwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() backwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() forwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() backwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() forwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() backwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() forwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() backwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() forwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 33 [foreignDoc.head, 0]":true, + "extend() backwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 33 [foreignDoc.head, 0]":true, + "extend() forwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 34 [foreignDoc.body, 1]":true, + "extend() backwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 34 [foreignDoc.body, 1]":true, + "extend() forwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 54 [foreignDoc, 0]":true, + "extend() backwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 54 [foreignDoc, 0]":true, + "extend() forwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 55 [foreignDoc, 1]":true, + "extend() backwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 55 [foreignDoc, 1]":true, + "extend() forwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 56 [foreignComment, 2]":true, + "extend() backwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 56 [foreignComment, 2]":true, + "extend() forwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 57 [foreignTextNode, 0]":true, + "extend() backwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 57 [foreignTextNode, 0]":true, + "extend() forwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 58 [foreignTextNode, 36]":true, + "extend() backwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 58 [foreignTextNode, 36]":true, + "extend() forwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 59 [xmlDoc, -1]":true, + "extend() backwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 59 [xmlDoc, -1]":true, + "extend() forwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 60 [xmlDoc, 0]":true, + "extend() backwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 60 [xmlDoc, 0]":true, + "extend() forwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 61 [xmlDoc, 1]":true, + "extend() backwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 61 [xmlDoc, 1]":true, + "extend() forwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 62 [xmlDoc, 5]":true, + "extend() backwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 62 [xmlDoc, 5]":true, + "extend() forwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 63 [xmlComment, 0]":true, + "extend() backwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 63 [xmlComment, 0]":true, + "extend() forwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 64 [xmlComment, 4]":true, + "extend() backwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 64 [xmlComment, 4]":true, + "extend() forwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 65 [processingInstruction, 0]":true, + "extend() backwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 65 [processingInstruction, 0]":true, + "extend() forwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 66 [processingInstruction, 5]":true, + "extend() backwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 66 [processingInstruction, 5]":true, + "extend() forwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 67 [processingInstruction, 9]":true, + "extend() backwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 67 [processingInstruction, 9]":true, + "extend() forwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 70 [detachedForeignTextNode, 0]":true, + "extend() backwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 70 [detachedForeignTextNode, 0]":true, + "extend() forwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 71 [detachedForeignTextNode, 8]":true, + "extend() backwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 71 [detachedForeignTextNode, 8]":true, + "extend() forwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 72 [detachedXmlTextNode, 0]":true, + "extend() backwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 72 [detachedXmlTextNode, 0]":true, + "extend() forwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 73 [detachedXmlTextNode, 8]":true, + "extend() backwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 73 [detachedXmlTextNode, 8]":true, + "extend() forwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() backwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() forwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 77 [detachedForeignComment, 0]":true, + "extend() backwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 77 [detachedForeignComment, 0]":true, + "extend() forwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 78 [detachedForeignComment, 4]":true, + "extend() backwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 78 [detachedForeignComment, 4]":true, + "extend() forwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 79 [detachedXmlComment, 2]":true, + "extend() backwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 79 [detachedXmlComment, 2]":true, + "extend() forwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 81 [foreignDocfrag, 0]":true, + "extend() backwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 81 [foreignDocfrag, 0]":true, + "extend() forwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 82 [xmlDocfrag, 0]":true, + "extend() backwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 82 [xmlDocfrag, 0]":true, + "extend() forwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 86 [foreignDoctype, 0]":true, + "extend() backwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 86 [foreignDoctype, 0]":true, + "extend() forwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 87 [xmlDoctype, 0]":true, + "extend() backwards with range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9] and point 87 [xmlDoctype, 0]":true, + "extend() with range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() with range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() with range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() with range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() with range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() with range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() with range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0] and point 33 [foreignDoc.head, 0]":true, + "extend() with range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0] and point 34 [foreignDoc.body, 1]":true, + "extend() with range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0] and point 54 [foreignDoc, 0]":true, + "extend() with range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0] and point 55 [foreignDoc, 1]":true, + "extend() with range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0] and point 56 [foreignComment, 2]":true, + "extend() with range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0] and point 57 [foreignTextNode, 0]":true, + "extend() with range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0] and point 58 [foreignTextNode, 36]":true, + "extend() with range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0] and point 59 [xmlDoc, -1]":true, + "extend() with range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0] and point 60 [xmlDoc, 0]":true, + "extend() with range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0] and point 61 [xmlDoc, 1]":true, + "extend() with range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0] and point 62 [xmlDoc, 5]":true, + "extend() with range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0] and point 63 [xmlComment, 0]":true, + "extend() with range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0] and point 64 [xmlComment, 4]":true, + "extend() with range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0] and point 65 [processingInstruction, 0]":true, + "extend() with range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0] and point 66 [processingInstruction, 5]":true, + "extend() with range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0] and point 67 [processingInstruction, 9]":true, + "extend() with range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0] and point 70 [detachedForeignTextNode, 0]":true, + "extend() with range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0] and point 71 [detachedForeignTextNode, 8]":true, + "extend() with range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0] and point 72 [detachedXmlTextNode, 0]":true, + "extend() with range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0] and point 73 [detachedXmlTextNode, 8]":true, + "extend() with range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() with range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0] and point 77 [detachedForeignComment, 0]":true, + "extend() with range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0] and point 78 [detachedForeignComment, 4]":true, + "extend() with range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0] and point 79 [detachedXmlComment, 2]":true, + "extend() with range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0] and point 81 [foreignDocfrag, 0]":true, + "extend() with range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0] and point 82 [xmlDocfrag, 0]":true, + "extend() with range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0] and point 86 [foreignDoctype, 0]":true, + "extend() with range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0] and point 87 [xmlDoctype, 0]":true, + "extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 33 [foreignDoc.head, 0]":true, + "extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 33 [foreignDoc.head, 0]":true, + "extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 34 [foreignDoc.body, 1]":true, + "extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 34 [foreignDoc.body, 1]":true, + "extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 54 [foreignDoc, 0]":true, + "extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 54 [foreignDoc, 0]":true, + "extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 55 [foreignDoc, 1]":true, + "extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 55 [foreignDoc, 1]":true, + "extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 56 [foreignComment, 2]":true, + "extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 56 [foreignComment, 2]":true, + "extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 57 [foreignTextNode, 0]":true, + "extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 57 [foreignTextNode, 0]":true, + "extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 58 [foreignTextNode, 36]":true, + "extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 58 [foreignTextNode, 36]":true, + "extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 59 [xmlDoc, -1]":true, + "extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 59 [xmlDoc, -1]":true, + "extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 60 [xmlDoc, 0]":true, + "extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 60 [xmlDoc, 0]":true, + "extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 61 [xmlDoc, 1]":true, + "extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 61 [xmlDoc, 1]":true, + "extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 62 [xmlDoc, 5]":true, + "extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 62 [xmlDoc, 5]":true, + "extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 63 [xmlComment, 0]":true, + "extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 63 [xmlComment, 0]":true, + "extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 64 [xmlComment, 4]":true, + "extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 64 [xmlComment, 4]":true, + "extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 65 [processingInstruction, 0]":true, + "extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 65 [processingInstruction, 0]":true, + "extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 66 [processingInstruction, 5]":true, + "extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 66 [processingInstruction, 5]":true, + "extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 67 [processingInstruction, 9]":true, + "extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 67 [processingInstruction, 9]":true, + "extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 70 [detachedForeignTextNode, 0]":true, + "extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 70 [detachedForeignTextNode, 0]":true, + "extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 71 [detachedForeignTextNode, 8]":true, + "extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 71 [detachedForeignTextNode, 8]":true, + "extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 72 [detachedXmlTextNode, 0]":true, + "extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 72 [detachedXmlTextNode, 0]":true, + "extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 73 [detachedXmlTextNode, 8]":true, + "extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 73 [detachedXmlTextNode, 8]":true, + "extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 77 [detachedForeignComment, 0]":true, + "extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 77 [detachedForeignComment, 0]":true, + "extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 78 [detachedForeignComment, 4]":true, + "extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 78 [detachedForeignComment, 4]":true, + "extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 79 [detachedXmlComment, 2]":true, + "extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 79 [detachedXmlComment, 2]":true, + "extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 81 [foreignDocfrag, 0]":true, + "extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 81 [foreignDocfrag, 0]":true, + "extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 82 [xmlDocfrag, 0]":true, + "extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 82 [xmlDocfrag, 0]":true, + "extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 86 [foreignDoctype, 0]":true, + "extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 86 [foreignDoctype, 0]":true, + "extend() forwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 87 [xmlDoctype, 0]":true, + "extend() backwards with range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1] and point 87 [xmlDoctype, 0]":true, + "extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 33 [foreignDoc.head, 0]":true, + "extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 33 [foreignDoc.head, 0]":true, + "extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 34 [foreignDoc.body, 1]":true, + "extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 34 [foreignDoc.body, 1]":true, + "extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 54 [foreignDoc, 0]":true, + "extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 54 [foreignDoc, 0]":true, + "extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 55 [foreignDoc, 1]":true, + "extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 55 [foreignDoc, 1]":true, + "extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 56 [foreignComment, 2]":true, + "extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 56 [foreignComment, 2]":true, + "extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 57 [foreignTextNode, 0]":true, + "extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 57 [foreignTextNode, 0]":true, + "extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 58 [foreignTextNode, 36]":true, + "extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 58 [foreignTextNode, 36]":true, + "extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 59 [xmlDoc, -1]":true, + "extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 59 [xmlDoc, -1]":true, + "extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 60 [xmlDoc, 0]":true, + "extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 60 [xmlDoc, 0]":true, + "extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 61 [xmlDoc, 1]":true, + "extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 61 [xmlDoc, 1]":true, + "extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 62 [xmlDoc, 5]":true, + "extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 62 [xmlDoc, 5]":true, + "extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 63 [xmlComment, 0]":true, + "extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 63 [xmlComment, 0]":true, + "extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 64 [xmlComment, 4]":true, + "extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 64 [xmlComment, 4]":true, + "extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 65 [processingInstruction, 0]":true, + "extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 65 [processingInstruction, 0]":true, + "extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 66 [processingInstruction, 5]":true, + "extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 66 [processingInstruction, 5]":true, + "extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 67 [processingInstruction, 9]":true, + "extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 67 [processingInstruction, 9]":true, + "extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 70 [detachedForeignTextNode, 0]":true, + "extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 70 [detachedForeignTextNode, 0]":true, + "extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 71 [detachedForeignTextNode, 8]":true, + "extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 71 [detachedForeignTextNode, 8]":true, + "extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 72 [detachedXmlTextNode, 0]":true, + "extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 72 [detachedXmlTextNode, 0]":true, + "extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 73 [detachedXmlTextNode, 8]":true, + "extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 73 [detachedXmlTextNode, 8]":true, + "extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 77 [detachedForeignComment, 0]":true, + "extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 77 [detachedForeignComment, 0]":true, + "extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 78 [detachedForeignComment, 4]":true, + "extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 78 [detachedForeignComment, 4]":true, + "extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 79 [detachedXmlComment, 2]":true, + "extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 79 [detachedXmlComment, 2]":true, + "extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 81 [foreignDocfrag, 0]":true, + "extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 81 [foreignDocfrag, 0]":true, + "extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 82 [xmlDocfrag, 0]":true, + "extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 82 [xmlDocfrag, 0]":true, + "extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 86 [foreignDoctype, 0]":true, + "extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 86 [foreignDoctype, 0]":true, + "extend() forwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 87 [xmlDoctype, 0]":true, + "extend() backwards with range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8] and point 87 [xmlDoctype, 0]":true, + "extend() with range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() with range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() with range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() with range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() with range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() with range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() with range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0] and point 33 [foreignDoc.head, 0]":true, + "extend() with range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0] and point 34 [foreignDoc.body, 1]":true, + "extend() with range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0] and point 54 [foreignDoc, 0]":true, + "extend() with range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0] and point 55 [foreignDoc, 1]":true, + "extend() with range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0] and point 56 [foreignComment, 2]":true, + "extend() with range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0] and point 57 [foreignTextNode, 0]":true, + "extend() with range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0] and point 58 [foreignTextNode, 36]":true, + "extend() with range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0] and point 59 [xmlDoc, -1]":true, + "extend() with range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0] and point 60 [xmlDoc, 0]":true, + "extend() with range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0] and point 61 [xmlDoc, 1]":true, + "extend() with range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0] and point 62 [xmlDoc, 5]":true, + "extend() with range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0] and point 63 [xmlComment, 0]":true, + "extend() with range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0] and point 64 [xmlComment, 4]":true, + "extend() with range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0] and point 65 [processingInstruction, 0]":true, + "extend() with range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0] and point 66 [processingInstruction, 5]":true, + "extend() with range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0] and point 67 [processingInstruction, 9]":true, + "extend() with range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0] and point 70 [detachedForeignTextNode, 0]":true, + "extend() with range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0] and point 71 [detachedForeignTextNode, 8]":true, + "extend() with range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0] and point 72 [detachedXmlTextNode, 0]":true, + "extend() with range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0] and point 73 [detachedXmlTextNode, 8]":true, + "extend() with range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() with range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0] and point 77 [detachedForeignComment, 0]":true, + "extend() with range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0] and point 78 [detachedForeignComment, 4]":true, + "extend() with range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0] and point 79 [detachedXmlComment, 2]":true, + "extend() with range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0] and point 81 [foreignDocfrag, 0]":true, + "extend() with range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0] and point 82 [xmlDocfrag, 0]":true, + "extend() with range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0] and point 86 [foreignDoctype, 0]":true, + "extend() with range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0] and point 87 [xmlDoctype, 0]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 0 [paras[0].firstChild, -1]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 1 [paras[0].firstChild, 0]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 2 [paras[0].firstChild, 1]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 3 [paras[0].firstChild, 2]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 4 [paras[0].firstChild, 8]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 5 [paras[0].firstChild, 9]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 6 [paras[0].firstChild, 10]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 7 [paras[0].firstChild, 65535]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 8 [paras[1].firstChild, -1]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 9 [paras[1].firstChild, 0]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 10 [paras[1].firstChild, 1]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 11 [paras[1].firstChild, 2]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 12 [paras[1].firstChild, 8]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 13 [paras[1].firstChild, 9]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 14 [paras[1].firstChild, 10]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 15 [paras[1].firstChild, 65535]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 16 [detachedPara1.firstChild, 0]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 17 [detachedPara1.firstChild, 1]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 18 [detachedPara1.firstChild, 8]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 19 [detachedPara1.firstChild, 9]":true, + "extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 24 [document.documentElement, -1]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 25 [document.documentElement, 0]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 26 [document.documentElement, 1]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 27 [document.documentElement, 2]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 28 [document.documentElement, 7]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 29 [document.head, 1]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 30 [document.body, 3]":true, + "extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 33 [foreignDoc.head, 0]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 33 [foreignDoc.head, 0]":true, + "extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 34 [foreignDoc.body, 1]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 34 [foreignDoc.body, 1]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 35 [paras[0], 0]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 36 [paras[0], 1]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 37 [paras[0], 2]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 38 [paras[1], 0]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 39 [paras[1], 1]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 40 [paras[1], 2]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 41 [detachedPara1, 0]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 42 [detachedPara1, 1]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 43 [testDiv, 0]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 44 [testDiv, 3]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 45 [document, -1]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 46 [document, 0]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 47 [document, 1]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 48 [document, 2]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 49 [document, 3]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 50 [comment, -1]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 51 [comment, 0]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 52 [comment, 4]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 53 [comment, 96]":true, + "extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 54 [foreignDoc, 0]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 54 [foreignDoc, 0]":true, + "extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 55 [foreignDoc, 1]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 55 [foreignDoc, 1]":true, + "extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 56 [foreignComment, 2]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 56 [foreignComment, 2]":true, + "extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 57 [foreignTextNode, 0]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 57 [foreignTextNode, 0]":true, + "extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 58 [foreignTextNode, 36]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 58 [foreignTextNode, 36]":true, + "extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 59 [xmlDoc, -1]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 59 [xmlDoc, -1]":true, + "extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 60 [xmlDoc, 0]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 60 [xmlDoc, 0]":true, + "extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 61 [xmlDoc, 1]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 61 [xmlDoc, 1]":true, + "extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 62 [xmlDoc, 5]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 62 [xmlDoc, 5]":true, + "extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 63 [xmlComment, 0]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 63 [xmlComment, 0]":true, + "extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 64 [xmlComment, 4]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 64 [xmlComment, 4]":true, + "extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 65 [processingInstruction, 0]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 65 [processingInstruction, 0]":true, + "extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 66 [processingInstruction, 5]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 66 [processingInstruction, 5]":true, + "extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 67 [processingInstruction, 9]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 67 [processingInstruction, 9]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 68 [detachedTextNode, 0]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 69 [detachedTextNode, 8]":true, + "extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 70 [detachedForeignTextNode, 0]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 70 [detachedForeignTextNode, 0]":true, + "extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 71 [detachedForeignTextNode, 8]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 71 [detachedForeignTextNode, 8]":true, + "extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 72 [detachedXmlTextNode, 0]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 72 [detachedXmlTextNode, 0]":true, + "extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 73 [detachedXmlTextNode, 8]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 73 [detachedXmlTextNode, 8]":true, + "extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 75 [detachedComment, 3]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 76 [detachedComment, 5]":true, + "extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 77 [detachedForeignComment, 0]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 77 [detachedForeignComment, 0]":true, + "extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 78 [detachedForeignComment, 4]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 78 [detachedForeignComment, 4]":true, + "extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 79 [detachedXmlComment, 2]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 79 [detachedXmlComment, 2]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 80 [docfrag, 0]":true, + "extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 81 [foreignDocfrag, 0]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 81 [foreignDocfrag, 0]":true, + "extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 82 [xmlDocfrag, 0]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 82 [xmlDocfrag, 0]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 83 [doctype, 0]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 84 [doctype, -17]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 85 [doctype, 1]":true, + "extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 86 [foreignDoctype, 0]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 86 [foreignDoctype, 0]":true, + "extend() forwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 87 [xmlDoctype, 0]":true, + "extend() backwards with range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] and point 87 [xmlDoctype, 0]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 0 [paras[0].firstChild, -1]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 1 [paras[0].firstChild, 0]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 2 [paras[0].firstChild, 1]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 3 [paras[0].firstChild, 2]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 4 [paras[0].firstChild, 8]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 5 [paras[0].firstChild, 9]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 6 [paras[0].firstChild, 10]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 7 [paras[0].firstChild, 65535]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 8 [paras[1].firstChild, -1]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 9 [paras[1].firstChild, 0]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 10 [paras[1].firstChild, 1]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 11 [paras[1].firstChild, 2]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 12 [paras[1].firstChild, 8]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 13 [paras[1].firstChild, 9]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 14 [paras[1].firstChild, 10]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 15 [paras[1].firstChild, 65535]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 16 [detachedPara1.firstChild, 0]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 17 [detachedPara1.firstChild, 1]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 18 [detachedPara1.firstChild, 8]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 19 [detachedPara1.firstChild, 9]":true, + "extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 24 [document.documentElement, -1]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 25 [document.documentElement, 0]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 26 [document.documentElement, 1]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 27 [document.documentElement, 2]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 28 [document.documentElement, 7]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 29 [document.head, 1]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 30 [document.body, 3]":true, + "extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 33 [foreignDoc.head, 0]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 33 [foreignDoc.head, 0]":true, + "extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 34 [foreignDoc.body, 1]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 34 [foreignDoc.body, 1]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 35 [paras[0], 0]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 36 [paras[0], 1]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 37 [paras[0], 2]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 38 [paras[1], 0]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 39 [paras[1], 1]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 40 [paras[1], 2]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 41 [detachedPara1, 0]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 42 [detachedPara1, 1]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 43 [testDiv, 0]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 44 [testDiv, 3]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 45 [document, -1]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 46 [document, 0]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 47 [document, 1]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 48 [document, 2]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 49 [document, 3]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 50 [comment, -1]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 51 [comment, 0]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 52 [comment, 4]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 53 [comment, 96]":true, + "extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 54 [foreignDoc, 0]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 54 [foreignDoc, 0]":true, + "extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 55 [foreignDoc, 1]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 55 [foreignDoc, 1]":true, + "extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 56 [foreignComment, 2]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 56 [foreignComment, 2]":true, + "extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 57 [foreignTextNode, 0]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 57 [foreignTextNode, 0]":true, + "extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 58 [foreignTextNode, 36]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 58 [foreignTextNode, 36]":true, + "extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 59 [xmlDoc, -1]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 59 [xmlDoc, -1]":true, + "extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 60 [xmlDoc, 0]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 60 [xmlDoc, 0]":true, + "extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 61 [xmlDoc, 1]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 61 [xmlDoc, 1]":true, + "extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 62 [xmlDoc, 5]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 62 [xmlDoc, 5]":true, + "extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 63 [xmlComment, 0]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 63 [xmlComment, 0]":true, + "extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 64 [xmlComment, 4]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 64 [xmlComment, 4]":true, + "extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 65 [processingInstruction, 0]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 65 [processingInstruction, 0]":true, + "extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 66 [processingInstruction, 5]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 66 [processingInstruction, 5]":true, + "extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 67 [processingInstruction, 9]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 67 [processingInstruction, 9]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 68 [detachedTextNode, 0]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 69 [detachedTextNode, 8]":true, + "extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 70 [detachedForeignTextNode, 0]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 70 [detachedForeignTextNode, 0]":true, + "extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 71 [detachedForeignTextNode, 8]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 71 [detachedForeignTextNode, 8]":true, + "extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 72 [detachedXmlTextNode, 0]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 72 [detachedXmlTextNode, 0]":true, + "extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 73 [detachedXmlTextNode, 8]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 73 [detachedXmlTextNode, 8]":true, + "extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 75 [detachedComment, 3]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 76 [detachedComment, 5]":true, + "extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 77 [detachedForeignComment, 0]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 77 [detachedForeignComment, 0]":true, + "extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 78 [detachedForeignComment, 4]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 78 [detachedForeignComment, 4]":true, + "extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 79 [detachedXmlComment, 2]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 79 [detachedXmlComment, 2]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 80 [docfrag, 0]":true, + "extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 81 [foreignDocfrag, 0]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 81 [foreignDocfrag, 0]":true, + "extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 82 [xmlDocfrag, 0]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 82 [xmlDocfrag, 0]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 83 [doctype, 0]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 84 [doctype, -17]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 85 [doctype, 1]":true, + "extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 86 [foreignDoctype, 0]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 86 [foreignDoctype, 0]":true, + "extend() forwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 87 [xmlDoctype, 0]":true, + "extend() backwards with range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] and point 87 [xmlDoctype, 0]":true, + "extend() forwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() backwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() forwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() backwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() forwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() backwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() forwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() backwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() forwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() backwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() forwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() backwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() forwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 33 [foreignDoc.head, 0]":true, + "extend() backwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 33 [foreignDoc.head, 0]":true, + "extend() forwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 34 [foreignDoc.body, 1]":true, + "extend() backwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 34 [foreignDoc.body, 1]":true, + "extend() forwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 54 [foreignDoc, 0]":true, + "extend() backwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 54 [foreignDoc, 0]":true, + "extend() forwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 55 [foreignDoc, 1]":true, + "extend() backwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 55 [foreignDoc, 1]":true, + "extend() forwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 56 [foreignComment, 2]":true, + "extend() backwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 56 [foreignComment, 2]":true, + "extend() forwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 57 [foreignTextNode, 0]":true, + "extend() backwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 57 [foreignTextNode, 0]":true, + "extend() forwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 58 [foreignTextNode, 36]":true, + "extend() backwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 58 [foreignTextNode, 36]":true, + "extend() forwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 59 [xmlDoc, -1]":true, + "extend() backwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 59 [xmlDoc, -1]":true, + "extend() forwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 60 [xmlDoc, 0]":true, + "extend() backwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 60 [xmlDoc, 0]":true, + "extend() forwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 61 [xmlDoc, 1]":true, + "extend() backwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 61 [xmlDoc, 1]":true, + "extend() forwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 62 [xmlDoc, 5]":true, + "extend() backwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 62 [xmlDoc, 5]":true, + "extend() forwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 63 [xmlComment, 0]":true, + "extend() backwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 63 [xmlComment, 0]":true, + "extend() forwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 64 [xmlComment, 4]":true, + "extend() backwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 64 [xmlComment, 4]":true, + "extend() forwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 65 [processingInstruction, 0]":true, + "extend() backwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 65 [processingInstruction, 0]":true, + "extend() forwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 66 [processingInstruction, 5]":true, + "extend() backwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 66 [processingInstruction, 5]":true, + "extend() forwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 67 [processingInstruction, 9]":true, + "extend() backwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 67 [processingInstruction, 9]":true, + "extend() forwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 70 [detachedForeignTextNode, 0]":true, + "extend() backwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 70 [detachedForeignTextNode, 0]":true, + "extend() forwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 71 [detachedForeignTextNode, 8]":true, + "extend() backwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 71 [detachedForeignTextNode, 8]":true, + "extend() forwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 72 [detachedXmlTextNode, 0]":true, + "extend() backwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 72 [detachedXmlTextNode, 0]":true, + "extend() forwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 73 [detachedXmlTextNode, 8]":true, + "extend() backwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 73 [detachedXmlTextNode, 8]":true, + "extend() forwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() backwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() forwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 77 [detachedForeignComment, 0]":true, + "extend() backwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 77 [detachedForeignComment, 0]":true, + "extend() forwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 78 [detachedForeignComment, 4]":true, + "extend() backwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 78 [detachedForeignComment, 4]":true, + "extend() forwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 79 [detachedXmlComment, 2]":true, + "extend() backwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 79 [detachedXmlComment, 2]":true, + "extend() forwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 81 [foreignDocfrag, 0]":true, + "extend() backwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 81 [foreignDocfrag, 0]":true, + "extend() forwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 82 [xmlDocfrag, 0]":true, + "extend() backwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 82 [xmlDocfrag, 0]":true, + "extend() forwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 86 [foreignDoctype, 0]":true, + "extend() backwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 86 [foreignDoctype, 0]":true, + "extend() forwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 87 [xmlDoctype, 0]":true, + "extend() backwards with range 15 [document.documentElement, 0, document.documentElement, 1] and point 87 [xmlDoctype, 0]":true, + "extend() forwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() backwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() forwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() backwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() forwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() backwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() forwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() backwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() forwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() backwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() forwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() backwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() forwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 33 [foreignDoc.head, 0]":true, + "extend() backwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 33 [foreignDoc.head, 0]":true, + "extend() forwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 34 [foreignDoc.body, 1]":true, + "extend() backwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 34 [foreignDoc.body, 1]":true, + "extend() forwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 54 [foreignDoc, 0]":true, + "extend() backwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 54 [foreignDoc, 0]":true, + "extend() forwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 55 [foreignDoc, 1]":true, + "extend() backwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 55 [foreignDoc, 1]":true, + "extend() forwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 56 [foreignComment, 2]":true, + "extend() backwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 56 [foreignComment, 2]":true, + "extend() forwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 57 [foreignTextNode, 0]":true, + "extend() backwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 57 [foreignTextNode, 0]":true, + "extend() forwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 58 [foreignTextNode, 36]":true, + "extend() backwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 58 [foreignTextNode, 36]":true, + "extend() forwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 59 [xmlDoc, -1]":true, + "extend() backwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 59 [xmlDoc, -1]":true, + "extend() forwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 60 [xmlDoc, 0]":true, + "extend() backwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 60 [xmlDoc, 0]":true, + "extend() forwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 61 [xmlDoc, 1]":true, + "extend() backwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 61 [xmlDoc, 1]":true, + "extend() forwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 62 [xmlDoc, 5]":true, + "extend() backwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 62 [xmlDoc, 5]":true, + "extend() forwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 63 [xmlComment, 0]":true, + "extend() backwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 63 [xmlComment, 0]":true, + "extend() forwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 64 [xmlComment, 4]":true, + "extend() backwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 64 [xmlComment, 4]":true, + "extend() forwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 65 [processingInstruction, 0]":true, + "extend() backwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 65 [processingInstruction, 0]":true, + "extend() forwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 66 [processingInstruction, 5]":true, + "extend() backwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 66 [processingInstruction, 5]":true, + "extend() forwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 67 [processingInstruction, 9]":true, + "extend() backwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 67 [processingInstruction, 9]":true, + "extend() forwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 70 [detachedForeignTextNode, 0]":true, + "extend() backwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 70 [detachedForeignTextNode, 0]":true, + "extend() forwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 71 [detachedForeignTextNode, 8]":true, + "extend() backwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 71 [detachedForeignTextNode, 8]":true, + "extend() forwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 72 [detachedXmlTextNode, 0]":true, + "extend() backwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 72 [detachedXmlTextNode, 0]":true, + "extend() forwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 73 [detachedXmlTextNode, 8]":true, + "extend() backwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 73 [detachedXmlTextNode, 8]":true, + "extend() forwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() backwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() forwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 77 [detachedForeignComment, 0]":true, + "extend() backwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 77 [detachedForeignComment, 0]":true, + "extend() forwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 78 [detachedForeignComment, 4]":true, + "extend() backwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 78 [detachedForeignComment, 4]":true, + "extend() forwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 79 [detachedXmlComment, 2]":true, + "extend() backwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 79 [detachedXmlComment, 2]":true, + "extend() forwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 81 [foreignDocfrag, 0]":true, + "extend() backwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 81 [foreignDocfrag, 0]":true, + "extend() forwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 82 [xmlDocfrag, 0]":true, + "extend() backwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 82 [xmlDocfrag, 0]":true, + "extend() forwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 86 [foreignDoctype, 0]":true, + "extend() backwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 86 [foreignDoctype, 0]":true, + "extend() forwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 87 [xmlDoctype, 0]":true, + "extend() backwards with range 16 [document.documentElement, 0, document.documentElement, 2] and point 87 [xmlDoctype, 0]":true, + "extend() forwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() backwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() forwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() backwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() forwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() backwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() forwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() backwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() forwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() backwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() forwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() backwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() forwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 33 [foreignDoc.head, 0]":true, + "extend() backwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 33 [foreignDoc.head, 0]":true, + "extend() forwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 34 [foreignDoc.body, 1]":true, + "extend() backwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 34 [foreignDoc.body, 1]":true, + "extend() forwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 54 [foreignDoc, 0]":true, + "extend() backwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 54 [foreignDoc, 0]":true, + "extend() forwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 55 [foreignDoc, 1]":true, + "extend() backwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 55 [foreignDoc, 1]":true, + "extend() forwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 56 [foreignComment, 2]":true, + "extend() backwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 56 [foreignComment, 2]":true, + "extend() forwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 57 [foreignTextNode, 0]":true, + "extend() backwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 57 [foreignTextNode, 0]":true, + "extend() forwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 58 [foreignTextNode, 36]":true, + "extend() backwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 58 [foreignTextNode, 36]":true, + "extend() forwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 59 [xmlDoc, -1]":true, + "extend() backwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 59 [xmlDoc, -1]":true, + "extend() forwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 60 [xmlDoc, 0]":true, + "extend() backwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 60 [xmlDoc, 0]":true, + "extend() forwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 61 [xmlDoc, 1]":true, + "extend() backwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 61 [xmlDoc, 1]":true, + "extend() forwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 62 [xmlDoc, 5]":true, + "extend() backwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 62 [xmlDoc, 5]":true, + "extend() forwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 63 [xmlComment, 0]":true, + "extend() backwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 63 [xmlComment, 0]":true, + "extend() forwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 64 [xmlComment, 4]":true, + "extend() backwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 64 [xmlComment, 4]":true, + "extend() forwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 65 [processingInstruction, 0]":true, + "extend() backwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 65 [processingInstruction, 0]":true, + "extend() forwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 66 [processingInstruction, 5]":true, + "extend() backwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 66 [processingInstruction, 5]":true, + "extend() forwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 67 [processingInstruction, 9]":true, + "extend() backwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 67 [processingInstruction, 9]":true, + "extend() forwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 70 [detachedForeignTextNode, 0]":true, + "extend() backwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 70 [detachedForeignTextNode, 0]":true, + "extend() forwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 71 [detachedForeignTextNode, 8]":true, + "extend() backwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 71 [detachedForeignTextNode, 8]":true, + "extend() forwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 72 [detachedXmlTextNode, 0]":true, + "extend() backwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 72 [detachedXmlTextNode, 0]":true, + "extend() forwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 73 [detachedXmlTextNode, 8]":true, + "extend() backwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 73 [detachedXmlTextNode, 8]":true, + "extend() forwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() backwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() forwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 77 [detachedForeignComment, 0]":true, + "extend() backwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 77 [detachedForeignComment, 0]":true, + "extend() forwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 78 [detachedForeignComment, 4]":true, + "extend() backwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 78 [detachedForeignComment, 4]":true, + "extend() forwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 79 [detachedXmlComment, 2]":true, + "extend() backwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 79 [detachedXmlComment, 2]":true, + "extend() forwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 81 [foreignDocfrag, 0]":true, + "extend() backwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 81 [foreignDocfrag, 0]":true, + "extend() forwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 82 [xmlDocfrag, 0]":true, + "extend() backwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 82 [xmlDocfrag, 0]":true, + "extend() forwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 86 [foreignDoctype, 0]":true, + "extend() backwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 86 [foreignDoctype, 0]":true, + "extend() forwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 87 [xmlDoctype, 0]":true, + "extend() backwards with range 17 [document.documentElement, 1, document.documentElement, 2] and point 87 [xmlDoctype, 0]":true, + "extend() with range 18 [document.head, 1, document.head, 1] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() with range 18 [document.head, 1, document.head, 1] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() with range 18 [document.head, 1, document.head, 1] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() with range 18 [document.head, 1, document.head, 1] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() with range 18 [document.head, 1, document.head, 1] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() with range 18 [document.head, 1, document.head, 1] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() with range 18 [document.head, 1, document.head, 1] and point 33 [foreignDoc.head, 0]":true, + "extend() with range 18 [document.head, 1, document.head, 1] and point 34 [foreignDoc.body, 1]":true, + "extend() with range 18 [document.head, 1, document.head, 1] and point 54 [foreignDoc, 0]":true, + "extend() with range 18 [document.head, 1, document.head, 1] and point 55 [foreignDoc, 1]":true, + "extend() with range 18 [document.head, 1, document.head, 1] and point 56 [foreignComment, 2]":true, + "extend() with range 18 [document.head, 1, document.head, 1] and point 57 [foreignTextNode, 0]":true, + "extend() with range 18 [document.head, 1, document.head, 1] and point 58 [foreignTextNode, 36]":true, + "extend() with range 18 [document.head, 1, document.head, 1] and point 59 [xmlDoc, -1]":true, + "extend() with range 18 [document.head, 1, document.head, 1] and point 60 [xmlDoc, 0]":true, + "extend() with range 18 [document.head, 1, document.head, 1] and point 61 [xmlDoc, 1]":true, + "extend() with range 18 [document.head, 1, document.head, 1] and point 62 [xmlDoc, 5]":true, + "extend() with range 18 [document.head, 1, document.head, 1] and point 63 [xmlComment, 0]":true, + "extend() with range 18 [document.head, 1, document.head, 1] and point 64 [xmlComment, 4]":true, + "extend() with range 18 [document.head, 1, document.head, 1] and point 65 [processingInstruction, 0]":true, + "extend() with range 18 [document.head, 1, document.head, 1] and point 66 [processingInstruction, 5]":true, + "extend() with range 18 [document.head, 1, document.head, 1] and point 67 [processingInstruction, 9]":true, + "extend() with range 18 [document.head, 1, document.head, 1] and point 70 [detachedForeignTextNode, 0]":true, + "extend() with range 18 [document.head, 1, document.head, 1] and point 71 [detachedForeignTextNode, 8]":true, + "extend() with range 18 [document.head, 1, document.head, 1] and point 72 [detachedXmlTextNode, 0]":true, + "extend() with range 18 [document.head, 1, document.head, 1] and point 73 [detachedXmlTextNode, 8]":true, + "extend() with range 18 [document.head, 1, document.head, 1] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() with range 18 [document.head, 1, document.head, 1] and point 77 [detachedForeignComment, 0]":true, + "extend() with range 18 [document.head, 1, document.head, 1] and point 78 [detachedForeignComment, 4]":true, + "extend() with range 18 [document.head, 1, document.head, 1] and point 79 [detachedXmlComment, 2]":true, + "extend() with range 18 [document.head, 1, document.head, 1] and point 81 [foreignDocfrag, 0]":true, + "extend() with range 18 [document.head, 1, document.head, 1] and point 82 [xmlDocfrag, 0]":true, + "extend() with range 18 [document.head, 1, document.head, 1] and point 86 [foreignDoctype, 0]":true, + "extend() with range 18 [document.head, 1, document.head, 1] and point 87 [xmlDoctype, 0]":true, + "extend() forwards with range 19 [document.body, 0, document.body, 1] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() backwards with range 19 [document.body, 0, document.body, 1] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() forwards with range 19 [document.body, 0, document.body, 1] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() backwards with range 19 [document.body, 0, document.body, 1] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() forwards with range 19 [document.body, 0, document.body, 1] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() backwards with range 19 [document.body, 0, document.body, 1] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() forwards with range 19 [document.body, 0, document.body, 1] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() backwards with range 19 [document.body, 0, document.body, 1] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() forwards with range 19 [document.body, 0, document.body, 1] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() backwards with range 19 [document.body, 0, document.body, 1] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() forwards with range 19 [document.body, 0, document.body, 1] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() backwards with range 19 [document.body, 0, document.body, 1] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() forwards with range 19 [document.body, 0, document.body, 1] and point 33 [foreignDoc.head, 0]":true, + "extend() backwards with range 19 [document.body, 0, document.body, 1] and point 33 [foreignDoc.head, 0]":true, + "extend() forwards with range 19 [document.body, 0, document.body, 1] and point 34 [foreignDoc.body, 1]":true, + "extend() backwards with range 19 [document.body, 0, document.body, 1] and point 34 [foreignDoc.body, 1]":true, + "extend() forwards with range 19 [document.body, 0, document.body, 1] and point 54 [foreignDoc, 0]":true, + "extend() backwards with range 19 [document.body, 0, document.body, 1] and point 54 [foreignDoc, 0]":true, + "extend() forwards with range 19 [document.body, 0, document.body, 1] and point 55 [foreignDoc, 1]":true, + "extend() backwards with range 19 [document.body, 0, document.body, 1] and point 55 [foreignDoc, 1]":true, + "extend() forwards with range 19 [document.body, 0, document.body, 1] and point 56 [foreignComment, 2]":true, + "extend() backwards with range 19 [document.body, 0, document.body, 1] and point 56 [foreignComment, 2]":true, + "extend() forwards with range 19 [document.body, 0, document.body, 1] and point 57 [foreignTextNode, 0]":true, + "extend() backwards with range 19 [document.body, 0, document.body, 1] and point 57 [foreignTextNode, 0]":true, + "extend() forwards with range 19 [document.body, 0, document.body, 1] and point 58 [foreignTextNode, 36]":true, + "extend() backwards with range 19 [document.body, 0, document.body, 1] and point 58 [foreignTextNode, 36]":true, + "extend() forwards with range 19 [document.body, 0, document.body, 1] and point 59 [xmlDoc, -1]":true, + "extend() backwards with range 19 [document.body, 0, document.body, 1] and point 59 [xmlDoc, -1]":true, + "extend() forwards with range 19 [document.body, 0, document.body, 1] and point 60 [xmlDoc, 0]":true, + "extend() backwards with range 19 [document.body, 0, document.body, 1] and point 60 [xmlDoc, 0]":true, + "extend() forwards with range 19 [document.body, 0, document.body, 1] and point 61 [xmlDoc, 1]":true, + "extend() backwards with range 19 [document.body, 0, document.body, 1] and point 61 [xmlDoc, 1]":true, + "extend() forwards with range 19 [document.body, 0, document.body, 1] and point 62 [xmlDoc, 5]":true, + "extend() backwards with range 19 [document.body, 0, document.body, 1] and point 62 [xmlDoc, 5]":true, + "extend() forwards with range 19 [document.body, 0, document.body, 1] and point 63 [xmlComment, 0]":true, + "extend() backwards with range 19 [document.body, 0, document.body, 1] and point 63 [xmlComment, 0]":true, + "extend() forwards with range 19 [document.body, 0, document.body, 1] and point 64 [xmlComment, 4]":true, + "extend() backwards with range 19 [document.body, 0, document.body, 1] and point 64 [xmlComment, 4]":true, + "extend() forwards with range 19 [document.body, 0, document.body, 1] and point 65 [processingInstruction, 0]":true, + "extend() backwards with range 19 [document.body, 0, document.body, 1] and point 65 [processingInstruction, 0]":true, + "extend() forwards with range 19 [document.body, 0, document.body, 1] and point 66 [processingInstruction, 5]":true, + "extend() backwards with range 19 [document.body, 0, document.body, 1] and point 66 [processingInstruction, 5]":true, + "extend() forwards with range 19 [document.body, 0, document.body, 1] and point 67 [processingInstruction, 9]":true, + "extend() backwards with range 19 [document.body, 0, document.body, 1] and point 67 [processingInstruction, 9]":true, + "extend() forwards with range 19 [document.body, 0, document.body, 1] and point 70 [detachedForeignTextNode, 0]":true, + "extend() backwards with range 19 [document.body, 0, document.body, 1] and point 70 [detachedForeignTextNode, 0]":true, + "extend() forwards with range 19 [document.body, 0, document.body, 1] and point 71 [detachedForeignTextNode, 8]":true, + "extend() backwards with range 19 [document.body, 0, document.body, 1] and point 71 [detachedForeignTextNode, 8]":true, + "extend() forwards with range 19 [document.body, 0, document.body, 1] and point 72 [detachedXmlTextNode, 0]":true, + "extend() backwards with range 19 [document.body, 0, document.body, 1] and point 72 [detachedXmlTextNode, 0]":true, + "extend() forwards with range 19 [document.body, 0, document.body, 1] and point 73 [detachedXmlTextNode, 8]":true, + "extend() backwards with range 19 [document.body, 0, document.body, 1] and point 73 [detachedXmlTextNode, 8]":true, + "extend() forwards with range 19 [document.body, 0, document.body, 1] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() backwards with range 19 [document.body, 0, document.body, 1] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() forwards with range 19 [document.body, 0, document.body, 1] and point 77 [detachedForeignComment, 0]":true, + "extend() backwards with range 19 [document.body, 0, document.body, 1] and point 77 [detachedForeignComment, 0]":true, + "extend() forwards with range 19 [document.body, 0, document.body, 1] and point 78 [detachedForeignComment, 4]":true, + "extend() backwards with range 19 [document.body, 0, document.body, 1] and point 78 [detachedForeignComment, 4]":true, + "extend() forwards with range 19 [document.body, 0, document.body, 1] and point 79 [detachedXmlComment, 2]":true, + "extend() backwards with range 19 [document.body, 0, document.body, 1] and point 79 [detachedXmlComment, 2]":true, + "extend() forwards with range 19 [document.body, 0, document.body, 1] and point 81 [foreignDocfrag, 0]":true, + "extend() backwards with range 19 [document.body, 0, document.body, 1] and point 81 [foreignDocfrag, 0]":true, + "extend() forwards with range 19 [document.body, 0, document.body, 1] and point 82 [xmlDocfrag, 0]":true, + "extend() backwards with range 19 [document.body, 0, document.body, 1] and point 82 [xmlDocfrag, 0]":true, + "extend() forwards with range 19 [document.body, 0, document.body, 1] and point 86 [foreignDoctype, 0]":true, + "extend() backwards with range 19 [document.body, 0, document.body, 1] and point 86 [foreignDoctype, 0]":true, + "extend() forwards with range 19 [document.body, 0, document.body, 1] and point 87 [xmlDoctype, 0]":true, + "extend() backwards with range 19 [document.body, 0, document.body, 1] and point 87 [xmlDoctype, 0]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 0 [paras[0].firstChild, -1]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 1 [paras[0].firstChild, 0]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 2 [paras[0].firstChild, 1]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 3 [paras[0].firstChild, 2]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 4 [paras[0].firstChild, 8]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 5 [paras[0].firstChild, 9]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 6 [paras[0].firstChild, 10]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 7 [paras[0].firstChild, 65535]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 8 [paras[1].firstChild, -1]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 9 [paras[1].firstChild, 0]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 10 [paras[1].firstChild, 1]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 11 [paras[1].firstChild, 2]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 12 [paras[1].firstChild, 8]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 13 [paras[1].firstChild, 9]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 14 [paras[1].firstChild, 10]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 15 [paras[1].firstChild, 65535]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 16 [detachedPara1.firstChild, 0]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 17 [detachedPara1.firstChild, 1]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 18 [detachedPara1.firstChild, 8]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 19 [detachedPara1.firstChild, 9]":true, + "extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 24 [document.documentElement, -1]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 25 [document.documentElement, 0]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 26 [document.documentElement, 1]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 27 [document.documentElement, 2]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 28 [document.documentElement, 7]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 29 [document.head, 1]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 30 [document.body, 3]":true, + "extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 33 [foreignDoc.head, 0]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 33 [foreignDoc.head, 0]":true, + "extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 34 [foreignDoc.body, 1]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 34 [foreignDoc.body, 1]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 35 [paras[0], 0]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 36 [paras[0], 1]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 37 [paras[0], 2]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 38 [paras[1], 0]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 39 [paras[1], 1]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 40 [paras[1], 2]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 41 [detachedPara1, 0]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 42 [detachedPara1, 1]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 43 [testDiv, 0]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 44 [testDiv, 3]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 45 [document, -1]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 46 [document, 0]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 47 [document, 1]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 48 [document, 2]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 49 [document, 3]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 50 [comment, -1]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 51 [comment, 0]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 52 [comment, 4]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 53 [comment, 96]":true, + "extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 54 [foreignDoc, 0]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 54 [foreignDoc, 0]":true, + "extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 55 [foreignDoc, 1]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 55 [foreignDoc, 1]":true, + "extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 56 [foreignComment, 2]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 56 [foreignComment, 2]":true, + "extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 57 [foreignTextNode, 0]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 57 [foreignTextNode, 0]":true, + "extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 58 [foreignTextNode, 36]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 58 [foreignTextNode, 36]":true, + "extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 59 [xmlDoc, -1]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 59 [xmlDoc, -1]":true, + "extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 60 [xmlDoc, 0]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 60 [xmlDoc, 0]":true, + "extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 61 [xmlDoc, 1]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 61 [xmlDoc, 1]":true, + "extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 62 [xmlDoc, 5]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 62 [xmlDoc, 5]":true, + "extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 63 [xmlComment, 0]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 63 [xmlComment, 0]":true, + "extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 64 [xmlComment, 4]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 64 [xmlComment, 4]":true, + "extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 65 [processingInstruction, 0]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 65 [processingInstruction, 0]":true, + "extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 66 [processingInstruction, 5]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 66 [processingInstruction, 5]":true, + "extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 67 [processingInstruction, 9]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 67 [processingInstruction, 9]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 68 [detachedTextNode, 0]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 69 [detachedTextNode, 8]":true, + "extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 70 [detachedForeignTextNode, 0]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 70 [detachedForeignTextNode, 0]":true, + "extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 71 [detachedForeignTextNode, 8]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 71 [detachedForeignTextNode, 8]":true, + "extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 72 [detachedXmlTextNode, 0]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 72 [detachedXmlTextNode, 0]":true, + "extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 73 [detachedXmlTextNode, 8]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 73 [detachedXmlTextNode, 8]":true, + "extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 75 [detachedComment, 3]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 76 [detachedComment, 5]":true, + "extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 77 [detachedForeignComment, 0]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 77 [detachedForeignComment, 0]":true, + "extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 78 [detachedForeignComment, 4]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 78 [detachedForeignComment, 4]":true, + "extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 79 [detachedXmlComment, 2]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 79 [detachedXmlComment, 2]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 80 [docfrag, 0]":true, + "extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 81 [foreignDocfrag, 0]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 81 [foreignDocfrag, 0]":true, + "extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 82 [xmlDocfrag, 0]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 82 [xmlDocfrag, 0]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 83 [doctype, 0]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 84 [doctype, -17]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 85 [doctype, 1]":true, + "extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 86 [foreignDoctype, 0]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 86 [foreignDoctype, 0]":true, + "extend() forwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 87 [xmlDoctype, 0]":true, + "extend() backwards with range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] and point 87 [xmlDoctype, 0]":true, + "extend() with range 21 [foreignDoc.head, 1, foreignDoc.head, 1] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() with range 21 [foreignDoc.head, 1, foreignDoc.head, 1] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() with range 21 [foreignDoc.head, 1, foreignDoc.head, 1] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() with range 21 [foreignDoc.head, 1, foreignDoc.head, 1] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() with range 21 [foreignDoc.head, 1, foreignDoc.head, 1] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() with range 21 [foreignDoc.head, 1, foreignDoc.head, 1] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() with range 21 [foreignDoc.head, 1, foreignDoc.head, 1] and point 33 [foreignDoc.head, 0]":true, + "extend() with range 21 [foreignDoc.head, 1, foreignDoc.head, 1] and point 34 [foreignDoc.body, 1]":true, + "extend() with range 21 [foreignDoc.head, 1, foreignDoc.head, 1] and point 54 [foreignDoc, 0]":true, + "extend() with range 21 [foreignDoc.head, 1, foreignDoc.head, 1] and point 55 [foreignDoc, 1]":true, + "extend() with range 21 [foreignDoc.head, 1, foreignDoc.head, 1] and point 56 [foreignComment, 2]":true, + "extend() with range 21 [foreignDoc.head, 1, foreignDoc.head, 1] and point 57 [foreignTextNode, 0]":true, + "extend() with range 21 [foreignDoc.head, 1, foreignDoc.head, 1] and point 58 [foreignTextNode, 36]":true, + "extend() with range 21 [foreignDoc.head, 1, foreignDoc.head, 1] and point 59 [xmlDoc, -1]":true, + "extend() with range 21 [foreignDoc.head, 1, foreignDoc.head, 1] and point 60 [xmlDoc, 0]":true, + "extend() with range 21 [foreignDoc.head, 1, foreignDoc.head, 1] and point 61 [xmlDoc, 1]":true, + "extend() with range 21 [foreignDoc.head, 1, foreignDoc.head, 1] and point 62 [xmlDoc, 5]":true, + "extend() with range 21 [foreignDoc.head, 1, foreignDoc.head, 1] and point 63 [xmlComment, 0]":true, + "extend() with range 21 [foreignDoc.head, 1, foreignDoc.head, 1] and point 64 [xmlComment, 4]":true, + "extend() with range 21 [foreignDoc.head, 1, foreignDoc.head, 1] and point 65 [processingInstruction, 0]":true, + "extend() with range 21 [foreignDoc.head, 1, foreignDoc.head, 1] and point 66 [processingInstruction, 5]":true, + "extend() with range 21 [foreignDoc.head, 1, foreignDoc.head, 1] and point 67 [processingInstruction, 9]":true, + "extend() with range 21 [foreignDoc.head, 1, foreignDoc.head, 1] and point 70 [detachedForeignTextNode, 0]":true, + "extend() with range 21 [foreignDoc.head, 1, foreignDoc.head, 1] and point 71 [detachedForeignTextNode, 8]":true, + "extend() with range 21 [foreignDoc.head, 1, foreignDoc.head, 1] and point 72 [detachedXmlTextNode, 0]":true, + "extend() with range 21 [foreignDoc.head, 1, foreignDoc.head, 1] and point 73 [detachedXmlTextNode, 8]":true, + "extend() with range 21 [foreignDoc.head, 1, foreignDoc.head, 1] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() with range 21 [foreignDoc.head, 1, foreignDoc.head, 1] and point 77 [detachedForeignComment, 0]":true, + "extend() with range 21 [foreignDoc.head, 1, foreignDoc.head, 1] and point 78 [detachedForeignComment, 4]":true, + "extend() with range 21 [foreignDoc.head, 1, foreignDoc.head, 1] and point 79 [detachedXmlComment, 2]":true, + "extend() with range 21 [foreignDoc.head, 1, foreignDoc.head, 1] and point 81 [foreignDocfrag, 0]":true, + "extend() with range 21 [foreignDoc.head, 1, foreignDoc.head, 1] and point 82 [xmlDocfrag, 0]":true, + "extend() with range 21 [foreignDoc.head, 1, foreignDoc.head, 1] and point 86 [foreignDoctype, 0]":true, + "extend() with range 21 [foreignDoc.head, 1, foreignDoc.head, 1] and point 87 [xmlDoctype, 0]":true, + "extend() with range 22 [foreignDoc.body, 0, foreignDoc.body, 0] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() with range 22 [foreignDoc.body, 0, foreignDoc.body, 0] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() with range 22 [foreignDoc.body, 0, foreignDoc.body, 0] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() with range 22 [foreignDoc.body, 0, foreignDoc.body, 0] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() with range 22 [foreignDoc.body, 0, foreignDoc.body, 0] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() with range 22 [foreignDoc.body, 0, foreignDoc.body, 0] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() with range 22 [foreignDoc.body, 0, foreignDoc.body, 0] and point 33 [foreignDoc.head, 0]":true, + "extend() with range 22 [foreignDoc.body, 0, foreignDoc.body, 0] and point 34 [foreignDoc.body, 1]":true, + "extend() with range 22 [foreignDoc.body, 0, foreignDoc.body, 0] and point 54 [foreignDoc, 0]":true, + "extend() with range 22 [foreignDoc.body, 0, foreignDoc.body, 0] and point 55 [foreignDoc, 1]":true, + "extend() with range 22 [foreignDoc.body, 0, foreignDoc.body, 0] and point 56 [foreignComment, 2]":true, + "extend() with range 22 [foreignDoc.body, 0, foreignDoc.body, 0] and point 57 [foreignTextNode, 0]":true, + "extend() with range 22 [foreignDoc.body, 0, foreignDoc.body, 0] and point 58 [foreignTextNode, 36]":true, + "extend() with range 22 [foreignDoc.body, 0, foreignDoc.body, 0] and point 59 [xmlDoc, -1]":true, + "extend() with range 22 [foreignDoc.body, 0, foreignDoc.body, 0] and point 60 [xmlDoc, 0]":true, + "extend() with range 22 [foreignDoc.body, 0, foreignDoc.body, 0] and point 61 [xmlDoc, 1]":true, + "extend() with range 22 [foreignDoc.body, 0, foreignDoc.body, 0] and point 62 [xmlDoc, 5]":true, + "extend() with range 22 [foreignDoc.body, 0, foreignDoc.body, 0] and point 63 [xmlComment, 0]":true, + "extend() with range 22 [foreignDoc.body, 0, foreignDoc.body, 0] and point 64 [xmlComment, 4]":true, + "extend() with range 22 [foreignDoc.body, 0, foreignDoc.body, 0] and point 65 [processingInstruction, 0]":true, + "extend() with range 22 [foreignDoc.body, 0, foreignDoc.body, 0] and point 66 [processingInstruction, 5]":true, + "extend() with range 22 [foreignDoc.body, 0, foreignDoc.body, 0] and point 67 [processingInstruction, 9]":true, + "extend() with range 22 [foreignDoc.body, 0, foreignDoc.body, 0] and point 70 [detachedForeignTextNode, 0]":true, + "extend() with range 22 [foreignDoc.body, 0, foreignDoc.body, 0] and point 71 [detachedForeignTextNode, 8]":true, + "extend() with range 22 [foreignDoc.body, 0, foreignDoc.body, 0] and point 72 [detachedXmlTextNode, 0]":true, + "extend() with range 22 [foreignDoc.body, 0, foreignDoc.body, 0] and point 73 [detachedXmlTextNode, 8]":true, + "extend() with range 22 [foreignDoc.body, 0, foreignDoc.body, 0] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() with range 22 [foreignDoc.body, 0, foreignDoc.body, 0] and point 77 [detachedForeignComment, 0]":true, + "extend() with range 22 [foreignDoc.body, 0, foreignDoc.body, 0] and point 78 [detachedForeignComment, 4]":true, + "extend() with range 22 [foreignDoc.body, 0, foreignDoc.body, 0] and point 79 [detachedXmlComment, 2]":true, + "extend() with range 22 [foreignDoc.body, 0, foreignDoc.body, 0] and point 81 [foreignDocfrag, 0]":true, + "extend() with range 22 [foreignDoc.body, 0, foreignDoc.body, 0] and point 82 [xmlDocfrag, 0]":true, + "extend() with range 22 [foreignDoc.body, 0, foreignDoc.body, 0] and point 86 [foreignDoctype, 0]":true, + "extend() with range 22 [foreignDoc.body, 0, foreignDoc.body, 0] and point 87 [xmlDoctype, 0]":true, + "extend() with range 23 [paras[0], 0, paras[0], 0] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() with range 23 [paras[0], 0, paras[0], 0] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() with range 23 [paras[0], 0, paras[0], 0] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() with range 23 [paras[0], 0, paras[0], 0] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() with range 23 [paras[0], 0, paras[0], 0] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() with range 23 [paras[0], 0, paras[0], 0] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() with range 23 [paras[0], 0, paras[0], 0] and point 33 [foreignDoc.head, 0]":true, + "extend() with range 23 [paras[0], 0, paras[0], 0] and point 34 [foreignDoc.body, 1]":true, + "extend() with range 23 [paras[0], 0, paras[0], 0] and point 54 [foreignDoc, 0]":true, + "extend() with range 23 [paras[0], 0, paras[0], 0] and point 55 [foreignDoc, 1]":true, + "extend() with range 23 [paras[0], 0, paras[0], 0] and point 56 [foreignComment, 2]":true, + "extend() with range 23 [paras[0], 0, paras[0], 0] and point 57 [foreignTextNode, 0]":true, + "extend() with range 23 [paras[0], 0, paras[0], 0] and point 58 [foreignTextNode, 36]":true, + "extend() with range 23 [paras[0], 0, paras[0], 0] and point 59 [xmlDoc, -1]":true, + "extend() with range 23 [paras[0], 0, paras[0], 0] and point 60 [xmlDoc, 0]":true, + "extend() with range 23 [paras[0], 0, paras[0], 0] and point 61 [xmlDoc, 1]":true, + "extend() with range 23 [paras[0], 0, paras[0], 0] and point 62 [xmlDoc, 5]":true, + "extend() with range 23 [paras[0], 0, paras[0], 0] and point 63 [xmlComment, 0]":true, + "extend() with range 23 [paras[0], 0, paras[0], 0] and point 64 [xmlComment, 4]":true, + "extend() with range 23 [paras[0], 0, paras[0], 0] and point 65 [processingInstruction, 0]":true, + "extend() with range 23 [paras[0], 0, paras[0], 0] and point 66 [processingInstruction, 5]":true, + "extend() with range 23 [paras[0], 0, paras[0], 0] and point 67 [processingInstruction, 9]":true, + "extend() with range 23 [paras[0], 0, paras[0], 0] and point 70 [detachedForeignTextNode, 0]":true, + "extend() with range 23 [paras[0], 0, paras[0], 0] and point 71 [detachedForeignTextNode, 8]":true, + "extend() with range 23 [paras[0], 0, paras[0], 0] and point 72 [detachedXmlTextNode, 0]":true, + "extend() with range 23 [paras[0], 0, paras[0], 0] and point 73 [detachedXmlTextNode, 8]":true, + "extend() with range 23 [paras[0], 0, paras[0], 0] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() with range 23 [paras[0], 0, paras[0], 0] and point 77 [detachedForeignComment, 0]":true, + "extend() with range 23 [paras[0], 0, paras[0], 0] and point 78 [detachedForeignComment, 4]":true, + "extend() with range 23 [paras[0], 0, paras[0], 0] and point 79 [detachedXmlComment, 2]":true, + "extend() with range 23 [paras[0], 0, paras[0], 0] and point 81 [foreignDocfrag, 0]":true, + "extend() with range 23 [paras[0], 0, paras[0], 0] and point 82 [xmlDocfrag, 0]":true, + "extend() with range 23 [paras[0], 0, paras[0], 0] and point 86 [foreignDoctype, 0]":true, + "extend() with range 23 [paras[0], 0, paras[0], 0] and point 87 [xmlDoctype, 0]":true, + "extend() forwards with range 24 [paras[0], 0, paras[0], 1] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() backwards with range 24 [paras[0], 0, paras[0], 1] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() forwards with range 24 [paras[0], 0, paras[0], 1] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() backwards with range 24 [paras[0], 0, paras[0], 1] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() forwards with range 24 [paras[0], 0, paras[0], 1] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() backwards with range 24 [paras[0], 0, paras[0], 1] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() forwards with range 24 [paras[0], 0, paras[0], 1] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() backwards with range 24 [paras[0], 0, paras[0], 1] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() forwards with range 24 [paras[0], 0, paras[0], 1] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() backwards with range 24 [paras[0], 0, paras[0], 1] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() forwards with range 24 [paras[0], 0, paras[0], 1] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() backwards with range 24 [paras[0], 0, paras[0], 1] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() forwards with range 24 [paras[0], 0, paras[0], 1] and point 33 [foreignDoc.head, 0]":true, + "extend() backwards with range 24 [paras[0], 0, paras[0], 1] and point 33 [foreignDoc.head, 0]":true, + "extend() forwards with range 24 [paras[0], 0, paras[0], 1] and point 34 [foreignDoc.body, 1]":true, + "extend() backwards with range 24 [paras[0], 0, paras[0], 1] and point 34 [foreignDoc.body, 1]":true, + "extend() forwards with range 24 [paras[0], 0, paras[0], 1] and point 54 [foreignDoc, 0]":true, + "extend() backwards with range 24 [paras[0], 0, paras[0], 1] and point 54 [foreignDoc, 0]":true, + "extend() forwards with range 24 [paras[0], 0, paras[0], 1] and point 55 [foreignDoc, 1]":true, + "extend() backwards with range 24 [paras[0], 0, paras[0], 1] and point 55 [foreignDoc, 1]":true, + "extend() forwards with range 24 [paras[0], 0, paras[0], 1] and point 56 [foreignComment, 2]":true, + "extend() backwards with range 24 [paras[0], 0, paras[0], 1] and point 56 [foreignComment, 2]":true, + "extend() forwards with range 24 [paras[0], 0, paras[0], 1] and point 57 [foreignTextNode, 0]":true, + "extend() backwards with range 24 [paras[0], 0, paras[0], 1] and point 57 [foreignTextNode, 0]":true, + "extend() forwards with range 24 [paras[0], 0, paras[0], 1] and point 58 [foreignTextNode, 36]":true, + "extend() backwards with range 24 [paras[0], 0, paras[0], 1] and point 58 [foreignTextNode, 36]":true, + "extend() forwards with range 24 [paras[0], 0, paras[0], 1] and point 59 [xmlDoc, -1]":true, + "extend() backwards with range 24 [paras[0], 0, paras[0], 1] and point 59 [xmlDoc, -1]":true, + "extend() forwards with range 24 [paras[0], 0, paras[0], 1] and point 60 [xmlDoc, 0]":true, + "extend() backwards with range 24 [paras[0], 0, paras[0], 1] and point 60 [xmlDoc, 0]":true, + "extend() forwards with range 24 [paras[0], 0, paras[0], 1] and point 61 [xmlDoc, 1]":true, + "extend() backwards with range 24 [paras[0], 0, paras[0], 1] and point 61 [xmlDoc, 1]":true, + "extend() forwards with range 24 [paras[0], 0, paras[0], 1] and point 62 [xmlDoc, 5]":true, + "extend() backwards with range 24 [paras[0], 0, paras[0], 1] and point 62 [xmlDoc, 5]":true, + "extend() forwards with range 24 [paras[0], 0, paras[0], 1] and point 63 [xmlComment, 0]":true, + "extend() backwards with range 24 [paras[0], 0, paras[0], 1] and point 63 [xmlComment, 0]":true, + "extend() forwards with range 24 [paras[0], 0, paras[0], 1] and point 64 [xmlComment, 4]":true, + "extend() backwards with range 24 [paras[0], 0, paras[0], 1] and point 64 [xmlComment, 4]":true, + "extend() forwards with range 24 [paras[0], 0, paras[0], 1] and point 65 [processingInstruction, 0]":true, + "extend() backwards with range 24 [paras[0], 0, paras[0], 1] and point 65 [processingInstruction, 0]":true, + "extend() forwards with range 24 [paras[0], 0, paras[0], 1] and point 66 [processingInstruction, 5]":true, + "extend() backwards with range 24 [paras[0], 0, paras[0], 1] and point 66 [processingInstruction, 5]":true, + "extend() forwards with range 24 [paras[0], 0, paras[0], 1] and point 67 [processingInstruction, 9]":true, + "extend() backwards with range 24 [paras[0], 0, paras[0], 1] and point 67 [processingInstruction, 9]":true, + "extend() forwards with range 24 [paras[0], 0, paras[0], 1] and point 70 [detachedForeignTextNode, 0]":true, + "extend() backwards with range 24 [paras[0], 0, paras[0], 1] and point 70 [detachedForeignTextNode, 0]":true, + "extend() forwards with range 24 [paras[0], 0, paras[0], 1] and point 71 [detachedForeignTextNode, 8]":true, + "extend() backwards with range 24 [paras[0], 0, paras[0], 1] and point 71 [detachedForeignTextNode, 8]":true, + "extend() forwards with range 24 [paras[0], 0, paras[0], 1] and point 72 [detachedXmlTextNode, 0]":true, + "extend() backwards with range 24 [paras[0], 0, paras[0], 1] and point 72 [detachedXmlTextNode, 0]":true, + "extend() forwards with range 24 [paras[0], 0, paras[0], 1] and point 73 [detachedXmlTextNode, 8]":true, + "extend() backwards with range 24 [paras[0], 0, paras[0], 1] and point 73 [detachedXmlTextNode, 8]":true, + "extend() forwards with range 24 [paras[0], 0, paras[0], 1] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() backwards with range 24 [paras[0], 0, paras[0], 1] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() forwards with range 24 [paras[0], 0, paras[0], 1] and point 77 [detachedForeignComment, 0]":true, + "extend() backwards with range 24 [paras[0], 0, paras[0], 1] and point 77 [detachedForeignComment, 0]":true, + "extend() forwards with range 24 [paras[0], 0, paras[0], 1] and point 78 [detachedForeignComment, 4]":true, + "extend() backwards with range 24 [paras[0], 0, paras[0], 1] and point 78 [detachedForeignComment, 4]":true, + "extend() forwards with range 24 [paras[0], 0, paras[0], 1] and point 79 [detachedXmlComment, 2]":true, + "extend() backwards with range 24 [paras[0], 0, paras[0], 1] and point 79 [detachedXmlComment, 2]":true, + "extend() forwards with range 24 [paras[0], 0, paras[0], 1] and point 81 [foreignDocfrag, 0]":true, + "extend() backwards with range 24 [paras[0], 0, paras[0], 1] and point 81 [foreignDocfrag, 0]":true, + "extend() forwards with range 24 [paras[0], 0, paras[0], 1] and point 82 [xmlDocfrag, 0]":true, + "extend() backwards with range 24 [paras[0], 0, paras[0], 1] and point 82 [xmlDocfrag, 0]":true, + "extend() forwards with range 24 [paras[0], 0, paras[0], 1] and point 86 [foreignDoctype, 0]":true, + "extend() backwards with range 24 [paras[0], 0, paras[0], 1] and point 86 [foreignDoctype, 0]":true, + "extend() forwards with range 24 [paras[0], 0, paras[0], 1] and point 87 [xmlDoctype, 0]":true, + "extend() backwards with range 24 [paras[0], 0, paras[0], 1] and point 87 [xmlDoctype, 0]":true, + "extend() with range 25 [detachedPara1, 0, detachedPara1, 0] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() with range 25 [detachedPara1, 0, detachedPara1, 0] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() with range 25 [detachedPara1, 0, detachedPara1, 0] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() with range 25 [detachedPara1, 0, detachedPara1, 0] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() with range 25 [detachedPara1, 0, detachedPara1, 0] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() with range 25 [detachedPara1, 0, detachedPara1, 0] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() with range 25 [detachedPara1, 0, detachedPara1, 0] and point 33 [foreignDoc.head, 0]":true, + "extend() with range 25 [detachedPara1, 0, detachedPara1, 0] and point 34 [foreignDoc.body, 1]":true, + "extend() with range 25 [detachedPara1, 0, detachedPara1, 0] and point 54 [foreignDoc, 0]":true, + "extend() with range 25 [detachedPara1, 0, detachedPara1, 0] and point 55 [foreignDoc, 1]":true, + "extend() with range 25 [detachedPara1, 0, detachedPara1, 0] and point 56 [foreignComment, 2]":true, + "extend() with range 25 [detachedPara1, 0, detachedPara1, 0] and point 57 [foreignTextNode, 0]":true, + "extend() with range 25 [detachedPara1, 0, detachedPara1, 0] and point 58 [foreignTextNode, 36]":true, + "extend() with range 25 [detachedPara1, 0, detachedPara1, 0] and point 59 [xmlDoc, -1]":true, + "extend() with range 25 [detachedPara1, 0, detachedPara1, 0] and point 60 [xmlDoc, 0]":true, + "extend() with range 25 [detachedPara1, 0, detachedPara1, 0] and point 61 [xmlDoc, 1]":true, + "extend() with range 25 [detachedPara1, 0, detachedPara1, 0] and point 62 [xmlDoc, 5]":true, + "extend() with range 25 [detachedPara1, 0, detachedPara1, 0] and point 63 [xmlComment, 0]":true, + "extend() with range 25 [detachedPara1, 0, detachedPara1, 0] and point 64 [xmlComment, 4]":true, + "extend() with range 25 [detachedPara1, 0, detachedPara1, 0] and point 65 [processingInstruction, 0]":true, + "extend() with range 25 [detachedPara1, 0, detachedPara1, 0] and point 66 [processingInstruction, 5]":true, + "extend() with range 25 [detachedPara1, 0, detachedPara1, 0] and point 67 [processingInstruction, 9]":true, + "extend() with range 25 [detachedPara1, 0, detachedPara1, 0] and point 70 [detachedForeignTextNode, 0]":true, + "extend() with range 25 [detachedPara1, 0, detachedPara1, 0] and point 71 [detachedForeignTextNode, 8]":true, + "extend() with range 25 [detachedPara1, 0, detachedPara1, 0] and point 72 [detachedXmlTextNode, 0]":true, + "extend() with range 25 [detachedPara1, 0, detachedPara1, 0] and point 73 [detachedXmlTextNode, 8]":true, + "extend() with range 25 [detachedPara1, 0, detachedPara1, 0] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() with range 25 [detachedPara1, 0, detachedPara1, 0] and point 77 [detachedForeignComment, 0]":true, + "extend() with range 25 [detachedPara1, 0, detachedPara1, 0] and point 78 [detachedForeignComment, 4]":true, + "extend() with range 25 [detachedPara1, 0, detachedPara1, 0] and point 79 [detachedXmlComment, 2]":true, + "extend() with range 25 [detachedPara1, 0, detachedPara1, 0] and point 81 [foreignDocfrag, 0]":true, + "extend() with range 25 [detachedPara1, 0, detachedPara1, 0] and point 82 [xmlDocfrag, 0]":true, + "extend() with range 25 [detachedPara1, 0, detachedPara1, 0] and point 86 [foreignDoctype, 0]":true, + "extend() with range 25 [detachedPara1, 0, detachedPara1, 0] and point 87 [xmlDoctype, 0]":true, + "extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 33 [foreignDoc.head, 0]":true, + "extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 33 [foreignDoc.head, 0]":true, + "extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 34 [foreignDoc.body, 1]":true, + "extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 34 [foreignDoc.body, 1]":true, + "extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 54 [foreignDoc, 0]":true, + "extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 54 [foreignDoc, 0]":true, + "extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 55 [foreignDoc, 1]":true, + "extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 55 [foreignDoc, 1]":true, + "extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 56 [foreignComment, 2]":true, + "extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 56 [foreignComment, 2]":true, + "extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 57 [foreignTextNode, 0]":true, + "extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 57 [foreignTextNode, 0]":true, + "extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 58 [foreignTextNode, 36]":true, + "extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 58 [foreignTextNode, 36]":true, + "extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 59 [xmlDoc, -1]":true, + "extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 59 [xmlDoc, -1]":true, + "extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 60 [xmlDoc, 0]":true, + "extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 60 [xmlDoc, 0]":true, + "extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 61 [xmlDoc, 1]":true, + "extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 61 [xmlDoc, 1]":true, + "extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 62 [xmlDoc, 5]":true, + "extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 62 [xmlDoc, 5]":true, + "extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 63 [xmlComment, 0]":true, + "extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 63 [xmlComment, 0]":true, + "extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 64 [xmlComment, 4]":true, + "extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 64 [xmlComment, 4]":true, + "extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 65 [processingInstruction, 0]":true, + "extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 65 [processingInstruction, 0]":true, + "extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 66 [processingInstruction, 5]":true, + "extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 66 [processingInstruction, 5]":true, + "extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 67 [processingInstruction, 9]":true, + "extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 67 [processingInstruction, 9]":true, + "extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 70 [detachedForeignTextNode, 0]":true, + "extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 70 [detachedForeignTextNode, 0]":true, + "extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 71 [detachedForeignTextNode, 8]":true, + "extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 71 [detachedForeignTextNode, 8]":true, + "extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 72 [detachedXmlTextNode, 0]":true, + "extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 72 [detachedXmlTextNode, 0]":true, + "extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 73 [detachedXmlTextNode, 8]":true, + "extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 73 [detachedXmlTextNode, 8]":true, + "extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 77 [detachedForeignComment, 0]":true, + "extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 77 [detachedForeignComment, 0]":true, + "extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 78 [detachedForeignComment, 4]":true, + "extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 78 [detachedForeignComment, 4]":true, + "extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 79 [detachedXmlComment, 2]":true, + "extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 79 [detachedXmlComment, 2]":true, + "extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 81 [foreignDocfrag, 0]":true, + "extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 81 [foreignDocfrag, 0]":true, + "extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 82 [xmlDocfrag, 0]":true, + "extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 82 [xmlDocfrag, 0]":true, + "extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 86 [foreignDoctype, 0]":true, + "extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 86 [foreignDoctype, 0]":true, + "extend() forwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 87 [xmlDoctype, 0]":true, + "extend() backwards with range 26 [detachedPara1, 0, detachedPara1, 1] and point 87 [xmlDoctype, 0]":true, + "extend() forwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() backwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() forwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() backwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() forwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() backwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() forwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() backwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() forwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() backwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() forwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() backwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() forwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 33 [foreignDoc.head, 0]":true, + "extend() backwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 33 [foreignDoc.head, 0]":true, + "extend() forwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 34 [foreignDoc.body, 1]":true, + "extend() backwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 34 [foreignDoc.body, 1]":true, + "extend() forwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 54 [foreignDoc, 0]":true, + "extend() backwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 54 [foreignDoc, 0]":true, + "extend() forwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 55 [foreignDoc, 1]":true, + "extend() backwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 55 [foreignDoc, 1]":true, + "extend() forwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 56 [foreignComment, 2]":true, + "extend() backwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 56 [foreignComment, 2]":true, + "extend() forwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 57 [foreignTextNode, 0]":true, + "extend() backwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 57 [foreignTextNode, 0]":true, + "extend() forwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 58 [foreignTextNode, 36]":true, + "extend() backwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 58 [foreignTextNode, 36]":true, + "extend() forwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 59 [xmlDoc, -1]":true, + "extend() backwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 59 [xmlDoc, -1]":true, + "extend() forwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 60 [xmlDoc, 0]":true, + "extend() backwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 60 [xmlDoc, 0]":true, + "extend() forwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 61 [xmlDoc, 1]":true, + "extend() backwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 61 [xmlDoc, 1]":true, + "extend() forwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 62 [xmlDoc, 5]":true, + "extend() backwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 62 [xmlDoc, 5]":true, + "extend() forwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 63 [xmlComment, 0]":true, + "extend() backwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 63 [xmlComment, 0]":true, + "extend() forwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 64 [xmlComment, 4]":true, + "extend() backwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 64 [xmlComment, 4]":true, + "extend() forwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 65 [processingInstruction, 0]":true, + "extend() backwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 65 [processingInstruction, 0]":true, + "extend() forwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 66 [processingInstruction, 5]":true, + "extend() backwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 66 [processingInstruction, 5]":true, + "extend() forwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 67 [processingInstruction, 9]":true, + "extend() backwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 67 [processingInstruction, 9]":true, + "extend() forwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 70 [detachedForeignTextNode, 0]":true, + "extend() backwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 70 [detachedForeignTextNode, 0]":true, + "extend() forwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 71 [detachedForeignTextNode, 8]":true, + "extend() backwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 71 [detachedForeignTextNode, 8]":true, + "extend() forwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 72 [detachedXmlTextNode, 0]":true, + "extend() backwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 72 [detachedXmlTextNode, 0]":true, + "extend() forwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 73 [detachedXmlTextNode, 8]":true, + "extend() backwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 73 [detachedXmlTextNode, 8]":true, + "extend() forwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() backwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() forwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 77 [detachedForeignComment, 0]":true, + "extend() backwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 77 [detachedForeignComment, 0]":true, + "extend() forwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 78 [detachedForeignComment, 4]":true, + "extend() backwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 78 [detachedForeignComment, 4]":true, + "extend() forwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 79 [detachedXmlComment, 2]":true, + "extend() backwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 79 [detachedXmlComment, 2]":true, + "extend() forwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 81 [foreignDocfrag, 0]":true, + "extend() backwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 81 [foreignDocfrag, 0]":true, + "extend() forwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 82 [xmlDocfrag, 0]":true, + "extend() backwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 82 [xmlDocfrag, 0]":true, + "extend() forwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 86 [foreignDoctype, 0]":true, + "extend() backwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 86 [foreignDoctype, 0]":true, + "extend() forwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 87 [xmlDoctype, 0]":true, + "extend() backwards with range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0] and point 87 [xmlDoctype, 0]":true, + "extend() forwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() backwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() forwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() backwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() forwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() backwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() forwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() backwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() forwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() backwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() forwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() backwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() forwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 33 [foreignDoc.head, 0]":true, + "extend() backwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 33 [foreignDoc.head, 0]":true, + "extend() forwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 34 [foreignDoc.body, 1]":true, + "extend() backwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 34 [foreignDoc.body, 1]":true, + "extend() forwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 54 [foreignDoc, 0]":true, + "extend() backwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 54 [foreignDoc, 0]":true, + "extend() forwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 55 [foreignDoc, 1]":true, + "extend() backwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 55 [foreignDoc, 1]":true, + "extend() forwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 56 [foreignComment, 2]":true, + "extend() backwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 56 [foreignComment, 2]":true, + "extend() forwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 57 [foreignTextNode, 0]":true, + "extend() backwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 57 [foreignTextNode, 0]":true, + "extend() forwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 58 [foreignTextNode, 36]":true, + "extend() backwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 58 [foreignTextNode, 36]":true, + "extend() forwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 59 [xmlDoc, -1]":true, + "extend() backwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 59 [xmlDoc, -1]":true, + "extend() forwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 60 [xmlDoc, 0]":true, + "extend() backwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 60 [xmlDoc, 0]":true, + "extend() forwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 61 [xmlDoc, 1]":true, + "extend() backwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 61 [xmlDoc, 1]":true, + "extend() forwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 62 [xmlDoc, 5]":true, + "extend() backwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 62 [xmlDoc, 5]":true, + "extend() forwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 63 [xmlComment, 0]":true, + "extend() backwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 63 [xmlComment, 0]":true, + "extend() forwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 64 [xmlComment, 4]":true, + "extend() backwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 64 [xmlComment, 4]":true, + "extend() forwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 65 [processingInstruction, 0]":true, + "extend() backwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 65 [processingInstruction, 0]":true, + "extend() forwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 66 [processingInstruction, 5]":true, + "extend() backwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 66 [processingInstruction, 5]":true, + "extend() forwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 67 [processingInstruction, 9]":true, + "extend() backwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 67 [processingInstruction, 9]":true, + "extend() forwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 70 [detachedForeignTextNode, 0]":true, + "extend() backwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 70 [detachedForeignTextNode, 0]":true, + "extend() forwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 71 [detachedForeignTextNode, 8]":true, + "extend() backwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 71 [detachedForeignTextNode, 8]":true, + "extend() forwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 72 [detachedXmlTextNode, 0]":true, + "extend() backwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 72 [detachedXmlTextNode, 0]":true, + "extend() forwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 73 [detachedXmlTextNode, 8]":true, + "extend() backwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 73 [detachedXmlTextNode, 8]":true, + "extend() forwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() backwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() forwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 77 [detachedForeignComment, 0]":true, + "extend() backwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 77 [detachedForeignComment, 0]":true, + "extend() forwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 78 [detachedForeignComment, 4]":true, + "extend() backwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 78 [detachedForeignComment, 4]":true, + "extend() forwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 79 [detachedXmlComment, 2]":true, + "extend() backwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 79 [detachedXmlComment, 2]":true, + "extend() forwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 81 [foreignDocfrag, 0]":true, + "extend() backwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 81 [foreignDocfrag, 0]":true, + "extend() forwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 82 [xmlDocfrag, 0]":true, + "extend() backwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 82 [xmlDocfrag, 0]":true, + "extend() forwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 86 [foreignDoctype, 0]":true, + "extend() backwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 86 [foreignDoctype, 0]":true, + "extend() forwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 87 [xmlDoctype, 0]":true, + "extend() backwards with range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8] and point 87 [xmlDoctype, 0]":true, + "extend() forwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() backwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() forwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() backwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() forwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() backwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() forwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() backwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() forwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() backwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() forwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() backwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() forwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 33 [foreignDoc.head, 0]":true, + "extend() backwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 33 [foreignDoc.head, 0]":true, + "extend() forwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 34 [foreignDoc.body, 1]":true, + "extend() backwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 34 [foreignDoc.body, 1]":true, + "extend() forwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 54 [foreignDoc, 0]":true, + "extend() backwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 54 [foreignDoc, 0]":true, + "extend() forwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 55 [foreignDoc, 1]":true, + "extend() backwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 55 [foreignDoc, 1]":true, + "extend() forwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 56 [foreignComment, 2]":true, + "extend() backwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 56 [foreignComment, 2]":true, + "extend() forwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 57 [foreignTextNode, 0]":true, + "extend() backwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 57 [foreignTextNode, 0]":true, + "extend() forwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 58 [foreignTextNode, 36]":true, + "extend() backwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 58 [foreignTextNode, 36]":true, + "extend() forwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 59 [xmlDoc, -1]":true, + "extend() backwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 59 [xmlDoc, -1]":true, + "extend() forwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 60 [xmlDoc, 0]":true, + "extend() backwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 60 [xmlDoc, 0]":true, + "extend() forwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 61 [xmlDoc, 1]":true, + "extend() backwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 61 [xmlDoc, 1]":true, + "extend() forwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 62 [xmlDoc, 5]":true, + "extend() backwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 62 [xmlDoc, 5]":true, + "extend() forwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 63 [xmlComment, 0]":true, + "extend() backwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 63 [xmlComment, 0]":true, + "extend() forwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 64 [xmlComment, 4]":true, + "extend() backwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 64 [xmlComment, 4]":true, + "extend() forwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 65 [processingInstruction, 0]":true, + "extend() backwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 65 [processingInstruction, 0]":true, + "extend() forwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 66 [processingInstruction, 5]":true, + "extend() backwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 66 [processingInstruction, 5]":true, + "extend() forwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 67 [processingInstruction, 9]":true, + "extend() backwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 67 [processingInstruction, 9]":true, + "extend() forwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 70 [detachedForeignTextNode, 0]":true, + "extend() backwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 70 [detachedForeignTextNode, 0]":true, + "extend() forwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 71 [detachedForeignTextNode, 8]":true, + "extend() backwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 71 [detachedForeignTextNode, 8]":true, + "extend() forwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 72 [detachedXmlTextNode, 0]":true, + "extend() backwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 72 [detachedXmlTextNode, 0]":true, + "extend() forwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 73 [detachedXmlTextNode, 8]":true, + "extend() backwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 73 [detachedXmlTextNode, 8]":true, + "extend() forwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() backwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() forwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 77 [detachedForeignComment, 0]":true, + "extend() backwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 77 [detachedForeignComment, 0]":true, + "extend() forwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 78 [detachedForeignComment, 4]":true, + "extend() backwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 78 [detachedForeignComment, 4]":true, + "extend() forwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 79 [detachedXmlComment, 2]":true, + "extend() backwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 79 [detachedXmlComment, 2]":true, + "extend() forwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 81 [foreignDocfrag, 0]":true, + "extend() backwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 81 [foreignDocfrag, 0]":true, + "extend() forwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 82 [xmlDocfrag, 0]":true, + "extend() backwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 82 [xmlDocfrag, 0]":true, + "extend() forwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 86 [foreignDoctype, 0]":true, + "extend() backwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 86 [foreignDoctype, 0]":true, + "extend() forwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 87 [xmlDoctype, 0]":true, + "extend() backwards with range 29 [paras[0].firstChild, 3, paras[3], 1] and point 87 [xmlDoctype, 0]":true, + "extend() forwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() backwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() forwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() backwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() forwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() backwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() forwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() backwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() forwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() backwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() forwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() backwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() forwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 33 [foreignDoc.head, 0]":true, + "extend() backwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 33 [foreignDoc.head, 0]":true, + "extend() forwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 34 [foreignDoc.body, 1]":true, + "extend() backwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 34 [foreignDoc.body, 1]":true, + "extend() forwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 54 [foreignDoc, 0]":true, + "extend() backwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 54 [foreignDoc, 0]":true, + "extend() forwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 55 [foreignDoc, 1]":true, + "extend() backwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 55 [foreignDoc, 1]":true, + "extend() forwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 56 [foreignComment, 2]":true, + "extend() backwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 56 [foreignComment, 2]":true, + "extend() forwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 57 [foreignTextNode, 0]":true, + "extend() backwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 57 [foreignTextNode, 0]":true, + "extend() forwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 58 [foreignTextNode, 36]":true, + "extend() backwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 58 [foreignTextNode, 36]":true, + "extend() forwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 59 [xmlDoc, -1]":true, + "extend() backwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 59 [xmlDoc, -1]":true, + "extend() forwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 60 [xmlDoc, 0]":true, + "extend() backwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 60 [xmlDoc, 0]":true, + "extend() forwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 61 [xmlDoc, 1]":true, + "extend() backwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 61 [xmlDoc, 1]":true, + "extend() forwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 62 [xmlDoc, 5]":true, + "extend() backwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 62 [xmlDoc, 5]":true, + "extend() forwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 63 [xmlComment, 0]":true, + "extend() backwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 63 [xmlComment, 0]":true, + "extend() forwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 64 [xmlComment, 4]":true, + "extend() backwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 64 [xmlComment, 4]":true, + "extend() forwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 65 [processingInstruction, 0]":true, + "extend() backwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 65 [processingInstruction, 0]":true, + "extend() forwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 66 [processingInstruction, 5]":true, + "extend() backwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 66 [processingInstruction, 5]":true, + "extend() forwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 67 [processingInstruction, 9]":true, + "extend() backwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 67 [processingInstruction, 9]":true, + "extend() forwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 70 [detachedForeignTextNode, 0]":true, + "extend() backwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 70 [detachedForeignTextNode, 0]":true, + "extend() forwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 71 [detachedForeignTextNode, 8]":true, + "extend() backwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 71 [detachedForeignTextNode, 8]":true, + "extend() forwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 72 [detachedXmlTextNode, 0]":true, + "extend() backwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 72 [detachedXmlTextNode, 0]":true, + "extend() forwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 73 [detachedXmlTextNode, 8]":true, + "extend() backwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 73 [detachedXmlTextNode, 8]":true, + "extend() forwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() backwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() forwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 77 [detachedForeignComment, 0]":true, + "extend() backwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 77 [detachedForeignComment, 0]":true, + "extend() forwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 78 [detachedForeignComment, 4]":true, + "extend() backwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 78 [detachedForeignComment, 4]":true, + "extend() forwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 79 [detachedXmlComment, 2]":true, + "extend() backwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 79 [detachedXmlComment, 2]":true, + "extend() forwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 81 [foreignDocfrag, 0]":true, + "extend() backwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 81 [foreignDocfrag, 0]":true, + "extend() forwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 82 [xmlDocfrag, 0]":true, + "extend() backwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 82 [xmlDocfrag, 0]":true, + "extend() forwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 86 [foreignDoctype, 0]":true, + "extend() backwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 86 [foreignDoctype, 0]":true, + "extend() forwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 87 [xmlDoctype, 0]":true, + "extend() backwards with range 30 [paras[0], 0, paras[0].firstChild, 7] and point 87 [xmlDoctype, 0]":true, + "extend() forwards with range 31 [testDiv, 2, paras[4], 1] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() backwards with range 31 [testDiv, 2, paras[4], 1] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() forwards with range 31 [testDiv, 2, paras[4], 1] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() backwards with range 31 [testDiv, 2, paras[4], 1] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() forwards with range 31 [testDiv, 2, paras[4], 1] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() backwards with range 31 [testDiv, 2, paras[4], 1] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() forwards with range 31 [testDiv, 2, paras[4], 1] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() backwards with range 31 [testDiv, 2, paras[4], 1] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() forwards with range 31 [testDiv, 2, paras[4], 1] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() backwards with range 31 [testDiv, 2, paras[4], 1] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() forwards with range 31 [testDiv, 2, paras[4], 1] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() backwards with range 31 [testDiv, 2, paras[4], 1] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() forwards with range 31 [testDiv, 2, paras[4], 1] and point 33 [foreignDoc.head, 0]":true, + "extend() backwards with range 31 [testDiv, 2, paras[4], 1] and point 33 [foreignDoc.head, 0]":true, + "extend() forwards with range 31 [testDiv, 2, paras[4], 1] and point 34 [foreignDoc.body, 1]":true, + "extend() backwards with range 31 [testDiv, 2, paras[4], 1] and point 34 [foreignDoc.body, 1]":true, + "extend() forwards with range 31 [testDiv, 2, paras[4], 1] and point 54 [foreignDoc, 0]":true, + "extend() backwards with range 31 [testDiv, 2, paras[4], 1] and point 54 [foreignDoc, 0]":true, + "extend() forwards with range 31 [testDiv, 2, paras[4], 1] and point 55 [foreignDoc, 1]":true, + "extend() backwards with range 31 [testDiv, 2, paras[4], 1] and point 55 [foreignDoc, 1]":true, + "extend() forwards with range 31 [testDiv, 2, paras[4], 1] and point 56 [foreignComment, 2]":true, + "extend() backwards with range 31 [testDiv, 2, paras[4], 1] and point 56 [foreignComment, 2]":true, + "extend() forwards with range 31 [testDiv, 2, paras[4], 1] and point 57 [foreignTextNode, 0]":true, + "extend() backwards with range 31 [testDiv, 2, paras[4], 1] and point 57 [foreignTextNode, 0]":true, + "extend() forwards with range 31 [testDiv, 2, paras[4], 1] and point 58 [foreignTextNode, 36]":true, + "extend() backwards with range 31 [testDiv, 2, paras[4], 1] and point 58 [foreignTextNode, 36]":true, + "extend() forwards with range 31 [testDiv, 2, paras[4], 1] and point 59 [xmlDoc, -1]":true, + "extend() backwards with range 31 [testDiv, 2, paras[4], 1] and point 59 [xmlDoc, -1]":true, + "extend() forwards with range 31 [testDiv, 2, paras[4], 1] and point 60 [xmlDoc, 0]":true, + "extend() backwards with range 31 [testDiv, 2, paras[4], 1] and point 60 [xmlDoc, 0]":true, + "extend() forwards with range 31 [testDiv, 2, paras[4], 1] and point 61 [xmlDoc, 1]":true, + "extend() backwards with range 31 [testDiv, 2, paras[4], 1] and point 61 [xmlDoc, 1]":true, + "extend() forwards with range 31 [testDiv, 2, paras[4], 1] and point 62 [xmlDoc, 5]":true, + "extend() backwards with range 31 [testDiv, 2, paras[4], 1] and point 62 [xmlDoc, 5]":true, + "extend() forwards with range 31 [testDiv, 2, paras[4], 1] and point 63 [xmlComment, 0]":true, + "extend() backwards with range 31 [testDiv, 2, paras[4], 1] and point 63 [xmlComment, 0]":true, + "extend() forwards with range 31 [testDiv, 2, paras[4], 1] and point 64 [xmlComment, 4]":true, + "extend() backwards with range 31 [testDiv, 2, paras[4], 1] and point 64 [xmlComment, 4]":true, + "extend() forwards with range 31 [testDiv, 2, paras[4], 1] and point 65 [processingInstruction, 0]":true, + "extend() backwards with range 31 [testDiv, 2, paras[4], 1] and point 65 [processingInstruction, 0]":true, + "extend() forwards with range 31 [testDiv, 2, paras[4], 1] and point 66 [processingInstruction, 5]":true, + "extend() backwards with range 31 [testDiv, 2, paras[4], 1] and point 66 [processingInstruction, 5]":true, + "extend() forwards with range 31 [testDiv, 2, paras[4], 1] and point 67 [processingInstruction, 9]":true, + "extend() backwards with range 31 [testDiv, 2, paras[4], 1] and point 67 [processingInstruction, 9]":true, + "extend() forwards with range 31 [testDiv, 2, paras[4], 1] and point 70 [detachedForeignTextNode, 0]":true, + "extend() backwards with range 31 [testDiv, 2, paras[4], 1] and point 70 [detachedForeignTextNode, 0]":true, + "extend() forwards with range 31 [testDiv, 2, paras[4], 1] and point 71 [detachedForeignTextNode, 8]":true, + "extend() backwards with range 31 [testDiv, 2, paras[4], 1] and point 71 [detachedForeignTextNode, 8]":true, + "extend() forwards with range 31 [testDiv, 2, paras[4], 1] and point 72 [detachedXmlTextNode, 0]":true, + "extend() backwards with range 31 [testDiv, 2, paras[4], 1] and point 72 [detachedXmlTextNode, 0]":true, + "extend() forwards with range 31 [testDiv, 2, paras[4], 1] and point 73 [detachedXmlTextNode, 8]":true, + "extend() backwards with range 31 [testDiv, 2, paras[4], 1] and point 73 [detachedXmlTextNode, 8]":true, + "extend() forwards with range 31 [testDiv, 2, paras[4], 1] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() backwards with range 31 [testDiv, 2, paras[4], 1] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() forwards with range 31 [testDiv, 2, paras[4], 1] and point 77 [detachedForeignComment, 0]":true, + "extend() backwards with range 31 [testDiv, 2, paras[4], 1] and point 77 [detachedForeignComment, 0]":true, + "extend() forwards with range 31 [testDiv, 2, paras[4], 1] and point 78 [detachedForeignComment, 4]":true, + "extend() backwards with range 31 [testDiv, 2, paras[4], 1] and point 78 [detachedForeignComment, 4]":true, + "extend() forwards with range 31 [testDiv, 2, paras[4], 1] and point 79 [detachedXmlComment, 2]":true, + "extend() backwards with range 31 [testDiv, 2, paras[4], 1] and point 79 [detachedXmlComment, 2]":true, + "extend() forwards with range 31 [testDiv, 2, paras[4], 1] and point 81 [foreignDocfrag, 0]":true, + "extend() backwards with range 31 [testDiv, 2, paras[4], 1] and point 81 [foreignDocfrag, 0]":true, + "extend() forwards with range 31 [testDiv, 2, paras[4], 1] and point 82 [xmlDocfrag, 0]":true, + "extend() backwards with range 31 [testDiv, 2, paras[4], 1] and point 82 [xmlDocfrag, 0]":true, + "extend() forwards with range 31 [testDiv, 2, paras[4], 1] and point 86 [foreignDoctype, 0]":true, + "extend() backwards with range 31 [testDiv, 2, paras[4], 1] and point 86 [foreignDoctype, 0]":true, + "extend() forwards with range 31 [testDiv, 2, paras[4], 1] and point 87 [xmlDoctype, 0]":true, + "extend() backwards with range 31 [testDiv, 2, paras[4], 1] and point 87 [xmlDoctype, 0]":true, + "extend() forwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() backwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() forwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() backwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() forwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() backwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() forwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() backwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() forwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() backwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() forwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() backwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() forwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 33 [foreignDoc.head, 0]":true, + "extend() backwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 33 [foreignDoc.head, 0]":true, + "extend() forwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 34 [foreignDoc.body, 1]":true, + "extend() backwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 34 [foreignDoc.body, 1]":true, + "extend() forwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 54 [foreignDoc, 0]":true, + "extend() backwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 54 [foreignDoc, 0]":true, + "extend() forwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 55 [foreignDoc, 1]":true, + "extend() backwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 55 [foreignDoc, 1]":true, + "extend() forwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 56 [foreignComment, 2]":true, + "extend() backwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 56 [foreignComment, 2]":true, + "extend() forwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 57 [foreignTextNode, 0]":true, + "extend() backwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 57 [foreignTextNode, 0]":true, + "extend() forwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 58 [foreignTextNode, 36]":true, + "extend() backwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 58 [foreignTextNode, 36]":true, + "extend() forwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 59 [xmlDoc, -1]":true, + "extend() backwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 59 [xmlDoc, -1]":true, + "extend() forwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 60 [xmlDoc, 0]":true, + "extend() backwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 60 [xmlDoc, 0]":true, + "extend() forwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 61 [xmlDoc, 1]":true, + "extend() backwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 61 [xmlDoc, 1]":true, + "extend() forwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 62 [xmlDoc, 5]":true, + "extend() backwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 62 [xmlDoc, 5]":true, + "extend() forwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 63 [xmlComment, 0]":true, + "extend() backwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 63 [xmlComment, 0]":true, + "extend() forwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 64 [xmlComment, 4]":true, + "extend() backwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 64 [xmlComment, 4]":true, + "extend() forwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 65 [processingInstruction, 0]":true, + "extend() backwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 65 [processingInstruction, 0]":true, + "extend() forwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 66 [processingInstruction, 5]":true, + "extend() backwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 66 [processingInstruction, 5]":true, + "extend() forwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 67 [processingInstruction, 9]":true, + "extend() backwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 67 [processingInstruction, 9]":true, + "extend() forwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 70 [detachedForeignTextNode, 0]":true, + "extend() backwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 70 [detachedForeignTextNode, 0]":true, + "extend() forwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 71 [detachedForeignTextNode, 8]":true, + "extend() backwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 71 [detachedForeignTextNode, 8]":true, + "extend() forwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 72 [detachedXmlTextNode, 0]":true, + "extend() backwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 72 [detachedXmlTextNode, 0]":true, + "extend() forwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 73 [detachedXmlTextNode, 8]":true, + "extend() backwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 73 [detachedXmlTextNode, 8]":true, + "extend() forwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() backwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() forwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 77 [detachedForeignComment, 0]":true, + "extend() backwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 77 [detachedForeignComment, 0]":true, + "extend() forwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 78 [detachedForeignComment, 4]":true, + "extend() backwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 78 [detachedForeignComment, 4]":true, + "extend() forwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 79 [detachedXmlComment, 2]":true, + "extend() backwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 79 [detachedXmlComment, 2]":true, + "extend() forwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 81 [foreignDocfrag, 0]":true, + "extend() backwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 81 [foreignDocfrag, 0]":true, + "extend() forwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 82 [xmlDocfrag, 0]":true, + "extend() backwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 82 [xmlDocfrag, 0]":true, + "extend() forwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 86 [foreignDoctype, 0]":true, + "extend() backwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 86 [foreignDoctype, 0]":true, + "extend() forwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 87 [xmlDoctype, 0]":true, + "extend() backwards with range 32 [testDiv, 1, paras[2].firstChild, 5] and point 87 [xmlDoctype, 0]":true, + "extend() forwards with range 33 [document.documentElement, 1, document.body, 0] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() backwards with range 33 [document.documentElement, 1, document.body, 0] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() forwards with range 33 [document.documentElement, 1, document.body, 0] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() backwards with range 33 [document.documentElement, 1, document.body, 0] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() forwards with range 33 [document.documentElement, 1, document.body, 0] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() backwards with range 33 [document.documentElement, 1, document.body, 0] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() forwards with range 33 [document.documentElement, 1, document.body, 0] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() backwards with range 33 [document.documentElement, 1, document.body, 0] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() forwards with range 33 [document.documentElement, 1, document.body, 0] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() backwards with range 33 [document.documentElement, 1, document.body, 0] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() forwards with range 33 [document.documentElement, 1, document.body, 0] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() backwards with range 33 [document.documentElement, 1, document.body, 0] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() forwards with range 33 [document.documentElement, 1, document.body, 0] and point 33 [foreignDoc.head, 0]":true, + "extend() backwards with range 33 [document.documentElement, 1, document.body, 0] and point 33 [foreignDoc.head, 0]":true, + "extend() forwards with range 33 [document.documentElement, 1, document.body, 0] and point 34 [foreignDoc.body, 1]":true, + "extend() backwards with range 33 [document.documentElement, 1, document.body, 0] and point 34 [foreignDoc.body, 1]":true, + "extend() forwards with range 33 [document.documentElement, 1, document.body, 0] and point 54 [foreignDoc, 0]":true, + "extend() backwards with range 33 [document.documentElement, 1, document.body, 0] and point 54 [foreignDoc, 0]":true, + "extend() forwards with range 33 [document.documentElement, 1, document.body, 0] and point 55 [foreignDoc, 1]":true, + "extend() backwards with range 33 [document.documentElement, 1, document.body, 0] and point 55 [foreignDoc, 1]":true, + "extend() forwards with range 33 [document.documentElement, 1, document.body, 0] and point 56 [foreignComment, 2]":true, + "extend() backwards with range 33 [document.documentElement, 1, document.body, 0] and point 56 [foreignComment, 2]":true, + "extend() forwards with range 33 [document.documentElement, 1, document.body, 0] and point 57 [foreignTextNode, 0]":true, + "extend() backwards with range 33 [document.documentElement, 1, document.body, 0] and point 57 [foreignTextNode, 0]":true, + "extend() forwards with range 33 [document.documentElement, 1, document.body, 0] and point 58 [foreignTextNode, 36]":true, + "extend() backwards with range 33 [document.documentElement, 1, document.body, 0] and point 58 [foreignTextNode, 36]":true, + "extend() forwards with range 33 [document.documentElement, 1, document.body, 0] and point 59 [xmlDoc, -1]":true, + "extend() backwards with range 33 [document.documentElement, 1, document.body, 0] and point 59 [xmlDoc, -1]":true, + "extend() forwards with range 33 [document.documentElement, 1, document.body, 0] and point 60 [xmlDoc, 0]":true, + "extend() backwards with range 33 [document.documentElement, 1, document.body, 0] and point 60 [xmlDoc, 0]":true, + "extend() forwards with range 33 [document.documentElement, 1, document.body, 0] and point 61 [xmlDoc, 1]":true, + "extend() backwards with range 33 [document.documentElement, 1, document.body, 0] and point 61 [xmlDoc, 1]":true, + "extend() forwards with range 33 [document.documentElement, 1, document.body, 0] and point 62 [xmlDoc, 5]":true, + "extend() backwards with range 33 [document.documentElement, 1, document.body, 0] and point 62 [xmlDoc, 5]":true, + "extend() forwards with range 33 [document.documentElement, 1, document.body, 0] and point 63 [xmlComment, 0]":true, + "extend() backwards with range 33 [document.documentElement, 1, document.body, 0] and point 63 [xmlComment, 0]":true, + "extend() forwards with range 33 [document.documentElement, 1, document.body, 0] and point 64 [xmlComment, 4]":true, + "extend() backwards with range 33 [document.documentElement, 1, document.body, 0] and point 64 [xmlComment, 4]":true, + "extend() forwards with range 33 [document.documentElement, 1, document.body, 0] and point 65 [processingInstruction, 0]":true, + "extend() backwards with range 33 [document.documentElement, 1, document.body, 0] and point 65 [processingInstruction, 0]":true, + "extend() forwards with range 33 [document.documentElement, 1, document.body, 0] and point 66 [processingInstruction, 5]":true, + "extend() backwards with range 33 [document.documentElement, 1, document.body, 0] and point 66 [processingInstruction, 5]":true, + "extend() forwards with range 33 [document.documentElement, 1, document.body, 0] and point 67 [processingInstruction, 9]":true, + "extend() backwards with range 33 [document.documentElement, 1, document.body, 0] and point 67 [processingInstruction, 9]":true, + "extend() forwards with range 33 [document.documentElement, 1, document.body, 0] and point 70 [detachedForeignTextNode, 0]":true, + "extend() backwards with range 33 [document.documentElement, 1, document.body, 0] and point 70 [detachedForeignTextNode, 0]":true, + "extend() forwards with range 33 [document.documentElement, 1, document.body, 0] and point 71 [detachedForeignTextNode, 8]":true, + "extend() backwards with range 33 [document.documentElement, 1, document.body, 0] and point 71 [detachedForeignTextNode, 8]":true, + "extend() forwards with range 33 [document.documentElement, 1, document.body, 0] and point 72 [detachedXmlTextNode, 0]":true, + "extend() backwards with range 33 [document.documentElement, 1, document.body, 0] and point 72 [detachedXmlTextNode, 0]":true, + "extend() forwards with range 33 [document.documentElement, 1, document.body, 0] and point 73 [detachedXmlTextNode, 8]":true, + "extend() backwards with range 33 [document.documentElement, 1, document.body, 0] and point 73 [detachedXmlTextNode, 8]":true, + "extend() forwards with range 33 [document.documentElement, 1, document.body, 0] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() backwards with range 33 [document.documentElement, 1, document.body, 0] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() forwards with range 33 [document.documentElement, 1, document.body, 0] and point 77 [detachedForeignComment, 0]":true, + "extend() backwards with range 33 [document.documentElement, 1, document.body, 0] and point 77 [detachedForeignComment, 0]":true, + "extend() forwards with range 33 [document.documentElement, 1, document.body, 0] and point 78 [detachedForeignComment, 4]":true, + "extend() backwards with range 33 [document.documentElement, 1, document.body, 0] and point 78 [detachedForeignComment, 4]":true, + "extend() forwards with range 33 [document.documentElement, 1, document.body, 0] and point 79 [detachedXmlComment, 2]":true, + "extend() backwards with range 33 [document.documentElement, 1, document.body, 0] and point 79 [detachedXmlComment, 2]":true, + "extend() forwards with range 33 [document.documentElement, 1, document.body, 0] and point 81 [foreignDocfrag, 0]":true, + "extend() backwards with range 33 [document.documentElement, 1, document.body, 0] and point 81 [foreignDocfrag, 0]":true, + "extend() forwards with range 33 [document.documentElement, 1, document.body, 0] and point 82 [xmlDocfrag, 0]":true, + "extend() backwards with range 33 [document.documentElement, 1, document.body, 0] and point 82 [xmlDocfrag, 0]":true, + "extend() forwards with range 33 [document.documentElement, 1, document.body, 0] and point 86 [foreignDoctype, 0]":true, + "extend() backwards with range 33 [document.documentElement, 1, document.body, 0] and point 86 [foreignDoctype, 0]":true, + "extend() forwards with range 33 [document.documentElement, 1, document.body, 0] and point 87 [xmlDoctype, 0]":true, + "extend() backwards with range 33 [document.documentElement, 1, document.body, 0] and point 87 [xmlDoctype, 0]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 0 [paras[0].firstChild, -1]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 1 [paras[0].firstChild, 0]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 2 [paras[0].firstChild, 1]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 3 [paras[0].firstChild, 2]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 4 [paras[0].firstChild, 8]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 5 [paras[0].firstChild, 9]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 6 [paras[0].firstChild, 10]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 7 [paras[0].firstChild, 65535]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 8 [paras[1].firstChild, -1]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 9 [paras[1].firstChild, 0]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 10 [paras[1].firstChild, 1]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 11 [paras[1].firstChild, 2]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 12 [paras[1].firstChild, 8]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 13 [paras[1].firstChild, 9]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 14 [paras[1].firstChild, 10]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 15 [paras[1].firstChild, 65535]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 16 [detachedPara1.firstChild, 0]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 17 [detachedPara1.firstChild, 1]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 18 [detachedPara1.firstChild, 8]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 19 [detachedPara1.firstChild, 9]":true, + "extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 24 [document.documentElement, -1]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 25 [document.documentElement, 0]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 26 [document.documentElement, 1]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 27 [document.documentElement, 2]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 28 [document.documentElement, 7]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 29 [document.head, 1]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 30 [document.body, 3]":true, + "extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 33 [foreignDoc.head, 0]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 33 [foreignDoc.head, 0]":true, + "extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 34 [foreignDoc.body, 1]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 34 [foreignDoc.body, 1]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 35 [paras[0], 0]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 36 [paras[0], 1]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 37 [paras[0], 2]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 38 [paras[1], 0]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 39 [paras[1], 1]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 40 [paras[1], 2]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 41 [detachedPara1, 0]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 42 [detachedPara1, 1]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 43 [testDiv, 0]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 44 [testDiv, 3]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 45 [document, -1]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 46 [document, 0]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 47 [document, 1]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 48 [document, 2]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 49 [document, 3]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 50 [comment, -1]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 51 [comment, 0]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 52 [comment, 4]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 53 [comment, 96]":true, + "extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 54 [foreignDoc, 0]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 54 [foreignDoc, 0]":true, + "extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 55 [foreignDoc, 1]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 55 [foreignDoc, 1]":true, + "extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 56 [foreignComment, 2]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 56 [foreignComment, 2]":true, + "extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 57 [foreignTextNode, 0]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 57 [foreignTextNode, 0]":true, + "extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 58 [foreignTextNode, 36]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 58 [foreignTextNode, 36]":true, + "extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 59 [xmlDoc, -1]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 59 [xmlDoc, -1]":true, + "extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 60 [xmlDoc, 0]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 60 [xmlDoc, 0]":true, + "extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 61 [xmlDoc, 1]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 61 [xmlDoc, 1]":true, + "extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 62 [xmlDoc, 5]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 62 [xmlDoc, 5]":true, + "extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 63 [xmlComment, 0]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 63 [xmlComment, 0]":true, + "extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 64 [xmlComment, 4]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 64 [xmlComment, 4]":true, + "extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 65 [processingInstruction, 0]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 65 [processingInstruction, 0]":true, + "extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 66 [processingInstruction, 5]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 66 [processingInstruction, 5]":true, + "extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 67 [processingInstruction, 9]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 67 [processingInstruction, 9]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 68 [detachedTextNode, 0]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 69 [detachedTextNode, 8]":true, + "extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 70 [detachedForeignTextNode, 0]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 70 [detachedForeignTextNode, 0]":true, + "extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 71 [detachedForeignTextNode, 8]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 71 [detachedForeignTextNode, 8]":true, + "extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 72 [detachedXmlTextNode, 0]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 72 [detachedXmlTextNode, 0]":true, + "extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 73 [detachedXmlTextNode, 8]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 73 [detachedXmlTextNode, 8]":true, + "extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 75 [detachedComment, 3]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 76 [detachedComment, 5]":true, + "extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 77 [detachedForeignComment, 0]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 77 [detachedForeignComment, 0]":true, + "extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 78 [detachedForeignComment, 4]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 78 [detachedForeignComment, 4]":true, + "extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 79 [detachedXmlComment, 2]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 79 [detachedXmlComment, 2]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 80 [docfrag, 0]":true, + "extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 81 [foreignDocfrag, 0]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 81 [foreignDocfrag, 0]":true, + "extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 82 [xmlDocfrag, 0]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 82 [xmlDocfrag, 0]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 83 [doctype, 0]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 84 [doctype, -17]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 85 [doctype, 1]":true, + "extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 86 [foreignDoctype, 0]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 86 [foreignDoctype, 0]":true, + "extend() forwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 87 [xmlDoctype, 0]":true, + "extend() backwards with range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] and point 87 [xmlDoctype, 0]":true, + "extend() forwards with range 35 [document, 0, document, 1] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() backwards with range 35 [document, 0, document, 1] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() forwards with range 35 [document, 0, document, 1] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() backwards with range 35 [document, 0, document, 1] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() forwards with range 35 [document, 0, document, 1] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() backwards with range 35 [document, 0, document, 1] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() forwards with range 35 [document, 0, document, 1] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() backwards with range 35 [document, 0, document, 1] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() forwards with range 35 [document, 0, document, 1] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() backwards with range 35 [document, 0, document, 1] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() forwards with range 35 [document, 0, document, 1] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() backwards with range 35 [document, 0, document, 1] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() forwards with range 35 [document, 0, document, 1] and point 33 [foreignDoc.head, 0]":true, + "extend() backwards with range 35 [document, 0, document, 1] and point 33 [foreignDoc.head, 0]":true, + "extend() forwards with range 35 [document, 0, document, 1] and point 34 [foreignDoc.body, 1]":true, + "extend() backwards with range 35 [document, 0, document, 1] and point 34 [foreignDoc.body, 1]":true, + "extend() forwards with range 35 [document, 0, document, 1] and point 54 [foreignDoc, 0]":true, + "extend() backwards with range 35 [document, 0, document, 1] and point 54 [foreignDoc, 0]":true, + "extend() forwards with range 35 [document, 0, document, 1] and point 55 [foreignDoc, 1]":true, + "extend() backwards with range 35 [document, 0, document, 1] and point 55 [foreignDoc, 1]":true, + "extend() forwards with range 35 [document, 0, document, 1] and point 56 [foreignComment, 2]":true, + "extend() backwards with range 35 [document, 0, document, 1] and point 56 [foreignComment, 2]":true, + "extend() forwards with range 35 [document, 0, document, 1] and point 57 [foreignTextNode, 0]":true, + "extend() backwards with range 35 [document, 0, document, 1] and point 57 [foreignTextNode, 0]":true, + "extend() forwards with range 35 [document, 0, document, 1] and point 58 [foreignTextNode, 36]":true, + "extend() backwards with range 35 [document, 0, document, 1] and point 58 [foreignTextNode, 36]":true, + "extend() forwards with range 35 [document, 0, document, 1] and point 59 [xmlDoc, -1]":true, + "extend() backwards with range 35 [document, 0, document, 1] and point 59 [xmlDoc, -1]":true, + "extend() forwards with range 35 [document, 0, document, 1] and point 60 [xmlDoc, 0]":true, + "extend() backwards with range 35 [document, 0, document, 1] and point 60 [xmlDoc, 0]":true, + "extend() forwards with range 35 [document, 0, document, 1] and point 61 [xmlDoc, 1]":true, + "extend() backwards with range 35 [document, 0, document, 1] and point 61 [xmlDoc, 1]":true, + "extend() forwards with range 35 [document, 0, document, 1] and point 62 [xmlDoc, 5]":true, + "extend() backwards with range 35 [document, 0, document, 1] and point 62 [xmlDoc, 5]":true, + "extend() forwards with range 35 [document, 0, document, 1] and point 63 [xmlComment, 0]":true, + "extend() backwards with range 35 [document, 0, document, 1] and point 63 [xmlComment, 0]":true, + "extend() forwards with range 35 [document, 0, document, 1] and point 64 [xmlComment, 4]":true, + "extend() backwards with range 35 [document, 0, document, 1] and point 64 [xmlComment, 4]":true, + "extend() forwards with range 35 [document, 0, document, 1] and point 65 [processingInstruction, 0]":true, + "extend() backwards with range 35 [document, 0, document, 1] and point 65 [processingInstruction, 0]":true, + "extend() forwards with range 35 [document, 0, document, 1] and point 66 [processingInstruction, 5]":true, + "extend() backwards with range 35 [document, 0, document, 1] and point 66 [processingInstruction, 5]":true, + "extend() forwards with range 35 [document, 0, document, 1] and point 67 [processingInstruction, 9]":true, + "extend() backwards with range 35 [document, 0, document, 1] and point 67 [processingInstruction, 9]":true, + "extend() forwards with range 35 [document, 0, document, 1] and point 70 [detachedForeignTextNode, 0]":true, + "extend() backwards with range 35 [document, 0, document, 1] and point 70 [detachedForeignTextNode, 0]":true, + "extend() forwards with range 35 [document, 0, document, 1] and point 71 [detachedForeignTextNode, 8]":true, + "extend() backwards with range 35 [document, 0, document, 1] and point 71 [detachedForeignTextNode, 8]":true, + "extend() forwards with range 35 [document, 0, document, 1] and point 72 [detachedXmlTextNode, 0]":true, + "extend() backwards with range 35 [document, 0, document, 1] and point 72 [detachedXmlTextNode, 0]":true, + "extend() forwards with range 35 [document, 0, document, 1] and point 73 [detachedXmlTextNode, 8]":true, + "extend() backwards with range 35 [document, 0, document, 1] and point 73 [detachedXmlTextNode, 8]":true, + "extend() forwards with range 35 [document, 0, document, 1] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() backwards with range 35 [document, 0, document, 1] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() forwards with range 35 [document, 0, document, 1] and point 77 [detachedForeignComment, 0]":true, + "extend() backwards with range 35 [document, 0, document, 1] and point 77 [detachedForeignComment, 0]":true, + "extend() forwards with range 35 [document, 0, document, 1] and point 78 [detachedForeignComment, 4]":true, + "extend() backwards with range 35 [document, 0, document, 1] and point 78 [detachedForeignComment, 4]":true, + "extend() forwards with range 35 [document, 0, document, 1] and point 79 [detachedXmlComment, 2]":true, + "extend() backwards with range 35 [document, 0, document, 1] and point 79 [detachedXmlComment, 2]":true, + "extend() forwards with range 35 [document, 0, document, 1] and point 81 [foreignDocfrag, 0]":true, + "extend() backwards with range 35 [document, 0, document, 1] and point 81 [foreignDocfrag, 0]":true, + "extend() forwards with range 35 [document, 0, document, 1] and point 82 [xmlDocfrag, 0]":true, + "extend() backwards with range 35 [document, 0, document, 1] and point 82 [xmlDocfrag, 0]":true, + "extend() forwards with range 35 [document, 0, document, 1] and point 86 [foreignDoctype, 0]":true, + "extend() backwards with range 35 [document, 0, document, 1] and point 86 [foreignDoctype, 0]":true, + "extend() forwards with range 35 [document, 0, document, 1] and point 87 [xmlDoctype, 0]":true, + "extend() backwards with range 35 [document, 0, document, 1] and point 87 [xmlDoctype, 0]":true, + "extend() forwards with range 36 [document, 0, document, 2] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() backwards with range 36 [document, 0, document, 2] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() forwards with range 36 [document, 0, document, 2] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() backwards with range 36 [document, 0, document, 2] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() forwards with range 36 [document, 0, document, 2] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() backwards with range 36 [document, 0, document, 2] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() forwards with range 36 [document, 0, document, 2] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() backwards with range 36 [document, 0, document, 2] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() forwards with range 36 [document, 0, document, 2] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() backwards with range 36 [document, 0, document, 2] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() forwards with range 36 [document, 0, document, 2] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() backwards with range 36 [document, 0, document, 2] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() forwards with range 36 [document, 0, document, 2] and point 33 [foreignDoc.head, 0]":true, + "extend() backwards with range 36 [document, 0, document, 2] and point 33 [foreignDoc.head, 0]":true, + "extend() forwards with range 36 [document, 0, document, 2] and point 34 [foreignDoc.body, 1]":true, + "extend() backwards with range 36 [document, 0, document, 2] and point 34 [foreignDoc.body, 1]":true, + "extend() forwards with range 36 [document, 0, document, 2] and point 54 [foreignDoc, 0]":true, + "extend() backwards with range 36 [document, 0, document, 2] and point 54 [foreignDoc, 0]":true, + "extend() forwards with range 36 [document, 0, document, 2] and point 55 [foreignDoc, 1]":true, + "extend() backwards with range 36 [document, 0, document, 2] and point 55 [foreignDoc, 1]":true, + "extend() forwards with range 36 [document, 0, document, 2] and point 56 [foreignComment, 2]":true, + "extend() backwards with range 36 [document, 0, document, 2] and point 56 [foreignComment, 2]":true, + "extend() forwards with range 36 [document, 0, document, 2] and point 57 [foreignTextNode, 0]":true, + "extend() backwards with range 36 [document, 0, document, 2] and point 57 [foreignTextNode, 0]":true, + "extend() forwards with range 36 [document, 0, document, 2] and point 58 [foreignTextNode, 36]":true, + "extend() backwards with range 36 [document, 0, document, 2] and point 58 [foreignTextNode, 36]":true, + "extend() forwards with range 36 [document, 0, document, 2] and point 59 [xmlDoc, -1]":true, + "extend() backwards with range 36 [document, 0, document, 2] and point 59 [xmlDoc, -1]":true, + "extend() forwards with range 36 [document, 0, document, 2] and point 60 [xmlDoc, 0]":true, + "extend() backwards with range 36 [document, 0, document, 2] and point 60 [xmlDoc, 0]":true, + "extend() forwards with range 36 [document, 0, document, 2] and point 61 [xmlDoc, 1]":true, + "extend() backwards with range 36 [document, 0, document, 2] and point 61 [xmlDoc, 1]":true, + "extend() forwards with range 36 [document, 0, document, 2] and point 62 [xmlDoc, 5]":true, + "extend() backwards with range 36 [document, 0, document, 2] and point 62 [xmlDoc, 5]":true, + "extend() forwards with range 36 [document, 0, document, 2] and point 63 [xmlComment, 0]":true, + "extend() backwards with range 36 [document, 0, document, 2] and point 63 [xmlComment, 0]":true, + "extend() forwards with range 36 [document, 0, document, 2] and point 64 [xmlComment, 4]":true, + "extend() backwards with range 36 [document, 0, document, 2] and point 64 [xmlComment, 4]":true, + "extend() forwards with range 36 [document, 0, document, 2] and point 65 [processingInstruction, 0]":true, + "extend() backwards with range 36 [document, 0, document, 2] and point 65 [processingInstruction, 0]":true, + "extend() forwards with range 36 [document, 0, document, 2] and point 66 [processingInstruction, 5]":true, + "extend() backwards with range 36 [document, 0, document, 2] and point 66 [processingInstruction, 5]":true, + "extend() forwards with range 36 [document, 0, document, 2] and point 67 [processingInstruction, 9]":true, + "extend() backwards with range 36 [document, 0, document, 2] and point 67 [processingInstruction, 9]":true, + "extend() forwards with range 36 [document, 0, document, 2] and point 70 [detachedForeignTextNode, 0]":true, + "extend() backwards with range 36 [document, 0, document, 2] and point 70 [detachedForeignTextNode, 0]":true, + "extend() forwards with range 36 [document, 0, document, 2] and point 71 [detachedForeignTextNode, 8]":true, + "extend() backwards with range 36 [document, 0, document, 2] and point 71 [detachedForeignTextNode, 8]":true, + "extend() forwards with range 36 [document, 0, document, 2] and point 72 [detachedXmlTextNode, 0]":true, + "extend() backwards with range 36 [document, 0, document, 2] and point 72 [detachedXmlTextNode, 0]":true, + "extend() forwards with range 36 [document, 0, document, 2] and point 73 [detachedXmlTextNode, 8]":true, + "extend() backwards with range 36 [document, 0, document, 2] and point 73 [detachedXmlTextNode, 8]":true, + "extend() forwards with range 36 [document, 0, document, 2] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() backwards with range 36 [document, 0, document, 2] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() forwards with range 36 [document, 0, document, 2] and point 77 [detachedForeignComment, 0]":true, + "extend() backwards with range 36 [document, 0, document, 2] and point 77 [detachedForeignComment, 0]":true, + "extend() forwards with range 36 [document, 0, document, 2] and point 78 [detachedForeignComment, 4]":true, + "extend() backwards with range 36 [document, 0, document, 2] and point 78 [detachedForeignComment, 4]":true, + "extend() forwards with range 36 [document, 0, document, 2] and point 79 [detachedXmlComment, 2]":true, + "extend() backwards with range 36 [document, 0, document, 2] and point 79 [detachedXmlComment, 2]":true, + "extend() forwards with range 36 [document, 0, document, 2] and point 81 [foreignDocfrag, 0]":true, + "extend() backwards with range 36 [document, 0, document, 2] and point 81 [foreignDocfrag, 0]":true, + "extend() forwards with range 36 [document, 0, document, 2] and point 82 [xmlDocfrag, 0]":true, + "extend() backwards with range 36 [document, 0, document, 2] and point 82 [xmlDocfrag, 0]":true, + "extend() forwards with range 36 [document, 0, document, 2] and point 86 [foreignDoctype, 0]":true, + "extend() backwards with range 36 [document, 0, document, 2] and point 86 [foreignDoctype, 0]":true, + "extend() forwards with range 36 [document, 0, document, 2] and point 87 [xmlDoctype, 0]":true, + "extend() backwards with range 36 [document, 0, document, 2] and point 87 [xmlDoctype, 0]":true, + "extend() forwards with range 37 [document, 1, document, 2] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() backwards with range 37 [document, 1, document, 2] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() forwards with range 37 [document, 1, document, 2] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() backwards with range 37 [document, 1, document, 2] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() forwards with range 37 [document, 1, document, 2] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() backwards with range 37 [document, 1, document, 2] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() forwards with range 37 [document, 1, document, 2] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() backwards with range 37 [document, 1, document, 2] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() forwards with range 37 [document, 1, document, 2] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() backwards with range 37 [document, 1, document, 2] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() forwards with range 37 [document, 1, document, 2] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() backwards with range 37 [document, 1, document, 2] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() forwards with range 37 [document, 1, document, 2] and point 33 [foreignDoc.head, 0]":true, + "extend() backwards with range 37 [document, 1, document, 2] and point 33 [foreignDoc.head, 0]":true, + "extend() forwards with range 37 [document, 1, document, 2] and point 34 [foreignDoc.body, 1]":true, + "extend() backwards with range 37 [document, 1, document, 2] and point 34 [foreignDoc.body, 1]":true, + "extend() forwards with range 37 [document, 1, document, 2] and point 54 [foreignDoc, 0]":true, + "extend() backwards with range 37 [document, 1, document, 2] and point 54 [foreignDoc, 0]":true, + "extend() forwards with range 37 [document, 1, document, 2] and point 55 [foreignDoc, 1]":true, + "extend() backwards with range 37 [document, 1, document, 2] and point 55 [foreignDoc, 1]":true, + "extend() forwards with range 37 [document, 1, document, 2] and point 56 [foreignComment, 2]":true, + "extend() backwards with range 37 [document, 1, document, 2] and point 56 [foreignComment, 2]":true, + "extend() forwards with range 37 [document, 1, document, 2] and point 57 [foreignTextNode, 0]":true, + "extend() backwards with range 37 [document, 1, document, 2] and point 57 [foreignTextNode, 0]":true, + "extend() forwards with range 37 [document, 1, document, 2] and point 58 [foreignTextNode, 36]":true, + "extend() backwards with range 37 [document, 1, document, 2] and point 58 [foreignTextNode, 36]":true, + "extend() forwards with range 37 [document, 1, document, 2] and point 59 [xmlDoc, -1]":true, + "extend() backwards with range 37 [document, 1, document, 2] and point 59 [xmlDoc, -1]":true, + "extend() forwards with range 37 [document, 1, document, 2] and point 60 [xmlDoc, 0]":true, + "extend() backwards with range 37 [document, 1, document, 2] and point 60 [xmlDoc, 0]":true, + "extend() forwards with range 37 [document, 1, document, 2] and point 61 [xmlDoc, 1]":true, + "extend() backwards with range 37 [document, 1, document, 2] and point 61 [xmlDoc, 1]":true, + "extend() forwards with range 37 [document, 1, document, 2] and point 62 [xmlDoc, 5]":true, + "extend() backwards with range 37 [document, 1, document, 2] and point 62 [xmlDoc, 5]":true, + "extend() forwards with range 37 [document, 1, document, 2] and point 63 [xmlComment, 0]":true, + "extend() backwards with range 37 [document, 1, document, 2] and point 63 [xmlComment, 0]":true, + "extend() forwards with range 37 [document, 1, document, 2] and point 64 [xmlComment, 4]":true, + "extend() backwards with range 37 [document, 1, document, 2] and point 64 [xmlComment, 4]":true, + "extend() forwards with range 37 [document, 1, document, 2] and point 65 [processingInstruction, 0]":true, + "extend() backwards with range 37 [document, 1, document, 2] and point 65 [processingInstruction, 0]":true, + "extend() forwards with range 37 [document, 1, document, 2] and point 66 [processingInstruction, 5]":true, + "extend() backwards with range 37 [document, 1, document, 2] and point 66 [processingInstruction, 5]":true, + "extend() forwards with range 37 [document, 1, document, 2] and point 67 [processingInstruction, 9]":true, + "extend() backwards with range 37 [document, 1, document, 2] and point 67 [processingInstruction, 9]":true, + "extend() forwards with range 37 [document, 1, document, 2] and point 70 [detachedForeignTextNode, 0]":true, + "extend() backwards with range 37 [document, 1, document, 2] and point 70 [detachedForeignTextNode, 0]":true, + "extend() forwards with range 37 [document, 1, document, 2] and point 71 [detachedForeignTextNode, 8]":true, + "extend() backwards with range 37 [document, 1, document, 2] and point 71 [detachedForeignTextNode, 8]":true, + "extend() forwards with range 37 [document, 1, document, 2] and point 72 [detachedXmlTextNode, 0]":true, + "extend() backwards with range 37 [document, 1, document, 2] and point 72 [detachedXmlTextNode, 0]":true, + "extend() forwards with range 37 [document, 1, document, 2] and point 73 [detachedXmlTextNode, 8]":true, + "extend() backwards with range 37 [document, 1, document, 2] and point 73 [detachedXmlTextNode, 8]":true, + "extend() forwards with range 37 [document, 1, document, 2] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() backwards with range 37 [document, 1, document, 2] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() forwards with range 37 [document, 1, document, 2] and point 77 [detachedForeignComment, 0]":true, + "extend() backwards with range 37 [document, 1, document, 2] and point 77 [detachedForeignComment, 0]":true, + "extend() forwards with range 37 [document, 1, document, 2] and point 78 [detachedForeignComment, 4]":true, + "extend() backwards with range 37 [document, 1, document, 2] and point 78 [detachedForeignComment, 4]":true, + "extend() forwards with range 37 [document, 1, document, 2] and point 79 [detachedXmlComment, 2]":true, + "extend() backwards with range 37 [document, 1, document, 2] and point 79 [detachedXmlComment, 2]":true, + "extend() forwards with range 37 [document, 1, document, 2] and point 81 [foreignDocfrag, 0]":true, + "extend() backwards with range 37 [document, 1, document, 2] and point 81 [foreignDocfrag, 0]":true, + "extend() forwards with range 37 [document, 1, document, 2] and point 82 [xmlDocfrag, 0]":true, + "extend() backwards with range 37 [document, 1, document, 2] and point 82 [xmlDocfrag, 0]":true, + "extend() forwards with range 37 [document, 1, document, 2] and point 86 [foreignDoctype, 0]":true, + "extend() backwards with range 37 [document, 1, document, 2] and point 86 [foreignDoctype, 0]":true, + "extend() forwards with range 37 [document, 1, document, 2] and point 87 [xmlDoctype, 0]":true, + "extend() backwards with range 37 [document, 1, document, 2] and point 87 [xmlDoctype, 0]":true, + "extend() forwards with range 38 [testDiv, 0, comment, 5] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() backwards with range 38 [testDiv, 0, comment, 5] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() forwards with range 38 [testDiv, 0, comment, 5] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() backwards with range 38 [testDiv, 0, comment, 5] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() forwards with range 38 [testDiv, 0, comment, 5] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() backwards with range 38 [testDiv, 0, comment, 5] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() forwards with range 38 [testDiv, 0, comment, 5] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() backwards with range 38 [testDiv, 0, comment, 5] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() forwards with range 38 [testDiv, 0, comment, 5] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() backwards with range 38 [testDiv, 0, comment, 5] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() forwards with range 38 [testDiv, 0, comment, 5] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() backwards with range 38 [testDiv, 0, comment, 5] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() forwards with range 38 [testDiv, 0, comment, 5] and point 33 [foreignDoc.head, 0]":true, + "extend() backwards with range 38 [testDiv, 0, comment, 5] and point 33 [foreignDoc.head, 0]":true, + "extend() forwards with range 38 [testDiv, 0, comment, 5] and point 34 [foreignDoc.body, 1]":true, + "extend() backwards with range 38 [testDiv, 0, comment, 5] and point 34 [foreignDoc.body, 1]":true, + "extend() forwards with range 38 [testDiv, 0, comment, 5] and point 54 [foreignDoc, 0]":true, + "extend() backwards with range 38 [testDiv, 0, comment, 5] and point 54 [foreignDoc, 0]":true, + "extend() forwards with range 38 [testDiv, 0, comment, 5] and point 55 [foreignDoc, 1]":true, + "extend() backwards with range 38 [testDiv, 0, comment, 5] and point 55 [foreignDoc, 1]":true, + "extend() forwards with range 38 [testDiv, 0, comment, 5] and point 56 [foreignComment, 2]":true, + "extend() backwards with range 38 [testDiv, 0, comment, 5] and point 56 [foreignComment, 2]":true, + "extend() forwards with range 38 [testDiv, 0, comment, 5] and point 57 [foreignTextNode, 0]":true, + "extend() backwards with range 38 [testDiv, 0, comment, 5] and point 57 [foreignTextNode, 0]":true, + "extend() forwards with range 38 [testDiv, 0, comment, 5] and point 58 [foreignTextNode, 36]":true, + "extend() backwards with range 38 [testDiv, 0, comment, 5] and point 58 [foreignTextNode, 36]":true, + "extend() forwards with range 38 [testDiv, 0, comment, 5] and point 59 [xmlDoc, -1]":true, + "extend() backwards with range 38 [testDiv, 0, comment, 5] and point 59 [xmlDoc, -1]":true, + "extend() forwards with range 38 [testDiv, 0, comment, 5] and point 60 [xmlDoc, 0]":true, + "extend() backwards with range 38 [testDiv, 0, comment, 5] and point 60 [xmlDoc, 0]":true, + "extend() forwards with range 38 [testDiv, 0, comment, 5] and point 61 [xmlDoc, 1]":true, + "extend() backwards with range 38 [testDiv, 0, comment, 5] and point 61 [xmlDoc, 1]":true, + "extend() forwards with range 38 [testDiv, 0, comment, 5] and point 62 [xmlDoc, 5]":true, + "extend() backwards with range 38 [testDiv, 0, comment, 5] and point 62 [xmlDoc, 5]":true, + "extend() forwards with range 38 [testDiv, 0, comment, 5] and point 63 [xmlComment, 0]":true, + "extend() backwards with range 38 [testDiv, 0, comment, 5] and point 63 [xmlComment, 0]":true, + "extend() forwards with range 38 [testDiv, 0, comment, 5] and point 64 [xmlComment, 4]":true, + "extend() backwards with range 38 [testDiv, 0, comment, 5] and point 64 [xmlComment, 4]":true, + "extend() forwards with range 38 [testDiv, 0, comment, 5] and point 65 [processingInstruction, 0]":true, + "extend() backwards with range 38 [testDiv, 0, comment, 5] and point 65 [processingInstruction, 0]":true, + "extend() forwards with range 38 [testDiv, 0, comment, 5] and point 66 [processingInstruction, 5]":true, + "extend() backwards with range 38 [testDiv, 0, comment, 5] and point 66 [processingInstruction, 5]":true, + "extend() forwards with range 38 [testDiv, 0, comment, 5] and point 67 [processingInstruction, 9]":true, + "extend() backwards with range 38 [testDiv, 0, comment, 5] and point 67 [processingInstruction, 9]":true, + "extend() forwards with range 38 [testDiv, 0, comment, 5] and point 70 [detachedForeignTextNode, 0]":true, + "extend() backwards with range 38 [testDiv, 0, comment, 5] and point 70 [detachedForeignTextNode, 0]":true, + "extend() forwards with range 38 [testDiv, 0, comment, 5] and point 71 [detachedForeignTextNode, 8]":true, + "extend() backwards with range 38 [testDiv, 0, comment, 5] and point 71 [detachedForeignTextNode, 8]":true, + "extend() forwards with range 38 [testDiv, 0, comment, 5] and point 72 [detachedXmlTextNode, 0]":true, + "extend() backwards with range 38 [testDiv, 0, comment, 5] and point 72 [detachedXmlTextNode, 0]":true, + "extend() forwards with range 38 [testDiv, 0, comment, 5] and point 73 [detachedXmlTextNode, 8]":true, + "extend() backwards with range 38 [testDiv, 0, comment, 5] and point 73 [detachedXmlTextNode, 8]":true, + "extend() forwards with range 38 [testDiv, 0, comment, 5] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() backwards with range 38 [testDiv, 0, comment, 5] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() forwards with range 38 [testDiv, 0, comment, 5] and point 77 [detachedForeignComment, 0]":true, + "extend() backwards with range 38 [testDiv, 0, comment, 5] and point 77 [detachedForeignComment, 0]":true, + "extend() forwards with range 38 [testDiv, 0, comment, 5] and point 78 [detachedForeignComment, 4]":true, + "extend() backwards with range 38 [testDiv, 0, comment, 5] and point 78 [detachedForeignComment, 4]":true, + "extend() forwards with range 38 [testDiv, 0, comment, 5] and point 79 [detachedXmlComment, 2]":true, + "extend() backwards with range 38 [testDiv, 0, comment, 5] and point 79 [detachedXmlComment, 2]":true, + "extend() forwards with range 38 [testDiv, 0, comment, 5] and point 81 [foreignDocfrag, 0]":true, + "extend() backwards with range 38 [testDiv, 0, comment, 5] and point 81 [foreignDocfrag, 0]":true, + "extend() forwards with range 38 [testDiv, 0, comment, 5] and point 82 [xmlDocfrag, 0]":true, + "extend() backwards with range 38 [testDiv, 0, comment, 5] and point 82 [xmlDocfrag, 0]":true, + "extend() forwards with range 38 [testDiv, 0, comment, 5] and point 86 [foreignDoctype, 0]":true, + "extend() backwards with range 38 [testDiv, 0, comment, 5] and point 86 [foreignDoctype, 0]":true, + "extend() forwards with range 38 [testDiv, 0, comment, 5] and point 87 [xmlDoctype, 0]":true, + "extend() backwards with range 38 [testDiv, 0, comment, 5] and point 87 [xmlDoctype, 0]":true, + "extend() forwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() backwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() forwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() backwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() forwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() backwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() forwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() backwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() forwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() backwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() forwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() backwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() forwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 33 [foreignDoc.head, 0]":true, + "extend() backwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 33 [foreignDoc.head, 0]":true, + "extend() forwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 34 [foreignDoc.body, 1]":true, + "extend() backwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 34 [foreignDoc.body, 1]":true, + "extend() forwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 54 [foreignDoc, 0]":true, + "extend() backwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 54 [foreignDoc, 0]":true, + "extend() forwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 55 [foreignDoc, 1]":true, + "extend() backwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 55 [foreignDoc, 1]":true, + "extend() forwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 56 [foreignComment, 2]":true, + "extend() backwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 56 [foreignComment, 2]":true, + "extend() forwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 57 [foreignTextNode, 0]":true, + "extend() backwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 57 [foreignTextNode, 0]":true, + "extend() forwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 58 [foreignTextNode, 36]":true, + "extend() backwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 58 [foreignTextNode, 36]":true, + "extend() forwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 59 [xmlDoc, -1]":true, + "extend() backwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 59 [xmlDoc, -1]":true, + "extend() forwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 60 [xmlDoc, 0]":true, + "extend() backwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 60 [xmlDoc, 0]":true, + "extend() forwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 61 [xmlDoc, 1]":true, + "extend() backwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 61 [xmlDoc, 1]":true, + "extend() forwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 62 [xmlDoc, 5]":true, + "extend() backwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 62 [xmlDoc, 5]":true, + "extend() forwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 63 [xmlComment, 0]":true, + "extend() backwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 63 [xmlComment, 0]":true, + "extend() forwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 64 [xmlComment, 4]":true, + "extend() backwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 64 [xmlComment, 4]":true, + "extend() forwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 65 [processingInstruction, 0]":true, + "extend() backwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 65 [processingInstruction, 0]":true, + "extend() forwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 66 [processingInstruction, 5]":true, + "extend() backwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 66 [processingInstruction, 5]":true, + "extend() forwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 67 [processingInstruction, 9]":true, + "extend() backwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 67 [processingInstruction, 9]":true, + "extend() forwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 70 [detachedForeignTextNode, 0]":true, + "extend() backwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 70 [detachedForeignTextNode, 0]":true, + "extend() forwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 71 [detachedForeignTextNode, 8]":true, + "extend() backwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 71 [detachedForeignTextNode, 8]":true, + "extend() forwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 72 [detachedXmlTextNode, 0]":true, + "extend() backwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 72 [detachedXmlTextNode, 0]":true, + "extend() forwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 73 [detachedXmlTextNode, 8]":true, + "extend() backwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 73 [detachedXmlTextNode, 8]":true, + "extend() forwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() backwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() forwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 77 [detachedForeignComment, 0]":true, + "extend() backwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 77 [detachedForeignComment, 0]":true, + "extend() forwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 78 [detachedForeignComment, 4]":true, + "extend() backwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 78 [detachedForeignComment, 4]":true, + "extend() forwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 79 [detachedXmlComment, 2]":true, + "extend() backwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 79 [detachedXmlComment, 2]":true, + "extend() forwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 81 [foreignDocfrag, 0]":true, + "extend() backwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 81 [foreignDocfrag, 0]":true, + "extend() forwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 82 [xmlDocfrag, 0]":true, + "extend() backwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 82 [xmlDocfrag, 0]":true, + "extend() forwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 86 [foreignDoctype, 0]":true, + "extend() backwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 86 [foreignDoctype, 0]":true, + "extend() forwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 87 [xmlDoctype, 0]":true, + "extend() backwards with range 39 [paras[2].firstChild, 4, comment, 2] and point 87 [xmlDoctype, 0]":true, + "extend() forwards with range 40 [paras[3], 1, comment, 8] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() backwards with range 40 [paras[3], 1, comment, 8] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() forwards with range 40 [paras[3], 1, comment, 8] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() backwards with range 40 [paras[3], 1, comment, 8] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() forwards with range 40 [paras[3], 1, comment, 8] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() backwards with range 40 [paras[3], 1, comment, 8] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() forwards with range 40 [paras[3], 1, comment, 8] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() backwards with range 40 [paras[3], 1, comment, 8] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() forwards with range 40 [paras[3], 1, comment, 8] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() backwards with range 40 [paras[3], 1, comment, 8] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() forwards with range 40 [paras[3], 1, comment, 8] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() backwards with range 40 [paras[3], 1, comment, 8] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() forwards with range 40 [paras[3], 1, comment, 8] and point 33 [foreignDoc.head, 0]":true, + "extend() backwards with range 40 [paras[3], 1, comment, 8] and point 33 [foreignDoc.head, 0]":true, + "extend() forwards with range 40 [paras[3], 1, comment, 8] and point 34 [foreignDoc.body, 1]":true, + "extend() backwards with range 40 [paras[3], 1, comment, 8] and point 34 [foreignDoc.body, 1]":true, + "extend() forwards with range 40 [paras[3], 1, comment, 8] and point 54 [foreignDoc, 0]":true, + "extend() backwards with range 40 [paras[3], 1, comment, 8] and point 54 [foreignDoc, 0]":true, + "extend() forwards with range 40 [paras[3], 1, comment, 8] and point 55 [foreignDoc, 1]":true, + "extend() backwards with range 40 [paras[3], 1, comment, 8] and point 55 [foreignDoc, 1]":true, + "extend() forwards with range 40 [paras[3], 1, comment, 8] and point 56 [foreignComment, 2]":true, + "extend() backwards with range 40 [paras[3], 1, comment, 8] and point 56 [foreignComment, 2]":true, + "extend() forwards with range 40 [paras[3], 1, comment, 8] and point 57 [foreignTextNode, 0]":true, + "extend() backwards with range 40 [paras[3], 1, comment, 8] and point 57 [foreignTextNode, 0]":true, + "extend() forwards with range 40 [paras[3], 1, comment, 8] and point 58 [foreignTextNode, 36]":true, + "extend() backwards with range 40 [paras[3], 1, comment, 8] and point 58 [foreignTextNode, 36]":true, + "extend() forwards with range 40 [paras[3], 1, comment, 8] and point 59 [xmlDoc, -1]":true, + "extend() backwards with range 40 [paras[3], 1, comment, 8] and point 59 [xmlDoc, -1]":true, + "extend() forwards with range 40 [paras[3], 1, comment, 8] and point 60 [xmlDoc, 0]":true, + "extend() backwards with range 40 [paras[3], 1, comment, 8] and point 60 [xmlDoc, 0]":true, + "extend() forwards with range 40 [paras[3], 1, comment, 8] and point 61 [xmlDoc, 1]":true, + "extend() backwards with range 40 [paras[3], 1, comment, 8] and point 61 [xmlDoc, 1]":true, + "extend() forwards with range 40 [paras[3], 1, comment, 8] and point 62 [xmlDoc, 5]":true, + "extend() backwards with range 40 [paras[3], 1, comment, 8] and point 62 [xmlDoc, 5]":true, + "extend() forwards with range 40 [paras[3], 1, comment, 8] and point 63 [xmlComment, 0]":true, + "extend() backwards with range 40 [paras[3], 1, comment, 8] and point 63 [xmlComment, 0]":true, + "extend() forwards with range 40 [paras[3], 1, comment, 8] and point 64 [xmlComment, 4]":true, + "extend() backwards with range 40 [paras[3], 1, comment, 8] and point 64 [xmlComment, 4]":true, + "extend() forwards with range 40 [paras[3], 1, comment, 8] and point 65 [processingInstruction, 0]":true, + "extend() backwards with range 40 [paras[3], 1, comment, 8] and point 65 [processingInstruction, 0]":true, + "extend() forwards with range 40 [paras[3], 1, comment, 8] and point 66 [processingInstruction, 5]":true, + "extend() backwards with range 40 [paras[3], 1, comment, 8] and point 66 [processingInstruction, 5]":true, + "extend() forwards with range 40 [paras[3], 1, comment, 8] and point 67 [processingInstruction, 9]":true, + "extend() backwards with range 40 [paras[3], 1, comment, 8] and point 67 [processingInstruction, 9]":true, + "extend() forwards with range 40 [paras[3], 1, comment, 8] and point 70 [detachedForeignTextNode, 0]":true, + "extend() backwards with range 40 [paras[3], 1, comment, 8] and point 70 [detachedForeignTextNode, 0]":true, + "extend() forwards with range 40 [paras[3], 1, comment, 8] and point 71 [detachedForeignTextNode, 8]":true, + "extend() backwards with range 40 [paras[3], 1, comment, 8] and point 71 [detachedForeignTextNode, 8]":true, + "extend() forwards with range 40 [paras[3], 1, comment, 8] and point 72 [detachedXmlTextNode, 0]":true, + "extend() backwards with range 40 [paras[3], 1, comment, 8] and point 72 [detachedXmlTextNode, 0]":true, + "extend() forwards with range 40 [paras[3], 1, comment, 8] and point 73 [detachedXmlTextNode, 8]":true, + "extend() backwards with range 40 [paras[3], 1, comment, 8] and point 73 [detachedXmlTextNode, 8]":true, + "extend() forwards with range 40 [paras[3], 1, comment, 8] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() backwards with range 40 [paras[3], 1, comment, 8] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() forwards with range 40 [paras[3], 1, comment, 8] and point 77 [detachedForeignComment, 0]":true, + "extend() backwards with range 40 [paras[3], 1, comment, 8] and point 77 [detachedForeignComment, 0]":true, + "extend() forwards with range 40 [paras[3], 1, comment, 8] and point 78 [detachedForeignComment, 4]":true, + "extend() backwards with range 40 [paras[3], 1, comment, 8] and point 78 [detachedForeignComment, 4]":true, + "extend() forwards with range 40 [paras[3], 1, comment, 8] and point 79 [detachedXmlComment, 2]":true, + "extend() backwards with range 40 [paras[3], 1, comment, 8] and point 79 [detachedXmlComment, 2]":true, + "extend() forwards with range 40 [paras[3], 1, comment, 8] and point 81 [foreignDocfrag, 0]":true, + "extend() backwards with range 40 [paras[3], 1, comment, 8] and point 81 [foreignDocfrag, 0]":true, + "extend() forwards with range 40 [paras[3], 1, comment, 8] and point 82 [xmlDocfrag, 0]":true, + "extend() backwards with range 40 [paras[3], 1, comment, 8] and point 82 [xmlDocfrag, 0]":true, + "extend() forwards with range 40 [paras[3], 1, comment, 8] and point 86 [foreignDoctype, 0]":true, + "extend() backwards with range 40 [paras[3], 1, comment, 8] and point 86 [foreignDoctype, 0]":true, + "extend() forwards with range 40 [paras[3], 1, comment, 8] and point 87 [xmlDoctype, 0]":true, + "extend() backwards with range 40 [paras[3], 1, comment, 8] and point 87 [xmlDoctype, 0]":true, + "extend() with range 41 [foreignDoc, 0, foreignDoc, 0] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() with range 41 [foreignDoc, 0, foreignDoc, 0] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() with range 41 [foreignDoc, 0, foreignDoc, 0] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() with range 41 [foreignDoc, 0, foreignDoc, 0] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() with range 41 [foreignDoc, 0, foreignDoc, 0] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() with range 41 [foreignDoc, 0, foreignDoc, 0] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() with range 41 [foreignDoc, 0, foreignDoc, 0] and point 33 [foreignDoc.head, 0]":true, + "extend() with range 41 [foreignDoc, 0, foreignDoc, 0] and point 34 [foreignDoc.body, 1]":true, + "extend() with range 41 [foreignDoc, 0, foreignDoc, 0] and point 54 [foreignDoc, 0]":true, + "extend() with range 41 [foreignDoc, 0, foreignDoc, 0] and point 55 [foreignDoc, 1]":true, + "extend() with range 41 [foreignDoc, 0, foreignDoc, 0] and point 56 [foreignComment, 2]":true, + "extend() with range 41 [foreignDoc, 0, foreignDoc, 0] and point 57 [foreignTextNode, 0]":true, + "extend() with range 41 [foreignDoc, 0, foreignDoc, 0] and point 58 [foreignTextNode, 36]":true, + "extend() with range 41 [foreignDoc, 0, foreignDoc, 0] and point 59 [xmlDoc, -1]":true, + "extend() with range 41 [foreignDoc, 0, foreignDoc, 0] and point 60 [xmlDoc, 0]":true, + "extend() with range 41 [foreignDoc, 0, foreignDoc, 0] and point 61 [xmlDoc, 1]":true, + "extend() with range 41 [foreignDoc, 0, foreignDoc, 0] and point 62 [xmlDoc, 5]":true, + "extend() with range 41 [foreignDoc, 0, foreignDoc, 0] and point 63 [xmlComment, 0]":true, + "extend() with range 41 [foreignDoc, 0, foreignDoc, 0] and point 64 [xmlComment, 4]":true, + "extend() with range 41 [foreignDoc, 0, foreignDoc, 0] and point 65 [processingInstruction, 0]":true, + "extend() with range 41 [foreignDoc, 0, foreignDoc, 0] and point 66 [processingInstruction, 5]":true, + "extend() with range 41 [foreignDoc, 0, foreignDoc, 0] and point 67 [processingInstruction, 9]":true, + "extend() with range 41 [foreignDoc, 0, foreignDoc, 0] and point 70 [detachedForeignTextNode, 0]":true, + "extend() with range 41 [foreignDoc, 0, foreignDoc, 0] and point 71 [detachedForeignTextNode, 8]":true, + "extend() with range 41 [foreignDoc, 0, foreignDoc, 0] and point 72 [detachedXmlTextNode, 0]":true, + "extend() with range 41 [foreignDoc, 0, foreignDoc, 0] and point 73 [detachedXmlTextNode, 8]":true, + "extend() with range 41 [foreignDoc, 0, foreignDoc, 0] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() with range 41 [foreignDoc, 0, foreignDoc, 0] and point 77 [detachedForeignComment, 0]":true, + "extend() with range 41 [foreignDoc, 0, foreignDoc, 0] and point 78 [detachedForeignComment, 4]":true, + "extend() with range 41 [foreignDoc, 0, foreignDoc, 0] and point 79 [detachedXmlComment, 2]":true, + "extend() with range 41 [foreignDoc, 0, foreignDoc, 0] and point 81 [foreignDocfrag, 0]":true, + "extend() with range 41 [foreignDoc, 0, foreignDoc, 0] and point 82 [xmlDocfrag, 0]":true, + "extend() with range 41 [foreignDoc, 0, foreignDoc, 0] and point 86 [foreignDoctype, 0]":true, + "extend() with range 41 [foreignDoc, 0, foreignDoc, 0] and point 87 [xmlDoctype, 0]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 0 [paras[0].firstChild, -1]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 1 [paras[0].firstChild, 0]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 2 [paras[0].firstChild, 1]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 3 [paras[0].firstChild, 2]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 4 [paras[0].firstChild, 8]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 5 [paras[0].firstChild, 9]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 6 [paras[0].firstChild, 10]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 7 [paras[0].firstChild, 65535]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 8 [paras[1].firstChild, -1]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 9 [paras[1].firstChild, 0]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 10 [paras[1].firstChild, 1]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 11 [paras[1].firstChild, 2]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 12 [paras[1].firstChild, 8]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 13 [paras[1].firstChild, 9]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 14 [paras[1].firstChild, 10]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 15 [paras[1].firstChild, 65535]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 16 [detachedPara1.firstChild, 0]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 17 [detachedPara1.firstChild, 1]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 18 [detachedPara1.firstChild, 8]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 19 [detachedPara1.firstChild, 9]":true, + "extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 24 [document.documentElement, -1]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 25 [document.documentElement, 0]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 26 [document.documentElement, 1]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 27 [document.documentElement, 2]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 28 [document.documentElement, 7]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 29 [document.head, 1]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 30 [document.body, 3]":true, + "extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 33 [foreignDoc.head, 0]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 33 [foreignDoc.head, 0]":true, + "extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 34 [foreignDoc.body, 1]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 34 [foreignDoc.body, 1]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 35 [paras[0], 0]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 36 [paras[0], 1]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 37 [paras[0], 2]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 38 [paras[1], 0]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 39 [paras[1], 1]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 40 [paras[1], 2]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 41 [detachedPara1, 0]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 42 [detachedPara1, 1]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 43 [testDiv, 0]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 44 [testDiv, 3]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 45 [document, -1]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 46 [document, 0]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 47 [document, 1]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 48 [document, 2]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 49 [document, 3]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 50 [comment, -1]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 51 [comment, 0]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 52 [comment, 4]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 53 [comment, 96]":true, + "extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 54 [foreignDoc, 0]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 54 [foreignDoc, 0]":true, + "extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 55 [foreignDoc, 1]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 55 [foreignDoc, 1]":true, + "extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 56 [foreignComment, 2]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 56 [foreignComment, 2]":true, + "extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 57 [foreignTextNode, 0]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 57 [foreignTextNode, 0]":true, + "extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 58 [foreignTextNode, 36]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 58 [foreignTextNode, 36]":true, + "extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 59 [xmlDoc, -1]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 59 [xmlDoc, -1]":true, + "extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 60 [xmlDoc, 0]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 60 [xmlDoc, 0]":true, + "extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 61 [xmlDoc, 1]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 61 [xmlDoc, 1]":true, + "extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 62 [xmlDoc, 5]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 62 [xmlDoc, 5]":true, + "extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 63 [xmlComment, 0]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 63 [xmlComment, 0]":true, + "extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 64 [xmlComment, 4]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 64 [xmlComment, 4]":true, + "extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 65 [processingInstruction, 0]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 65 [processingInstruction, 0]":true, + "extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 66 [processingInstruction, 5]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 66 [processingInstruction, 5]":true, + "extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 67 [processingInstruction, 9]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 67 [processingInstruction, 9]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 68 [detachedTextNode, 0]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 69 [detachedTextNode, 8]":true, + "extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 70 [detachedForeignTextNode, 0]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 70 [detachedForeignTextNode, 0]":true, + "extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 71 [detachedForeignTextNode, 8]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 71 [detachedForeignTextNode, 8]":true, + "extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 72 [detachedXmlTextNode, 0]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 72 [detachedXmlTextNode, 0]":true, + "extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 73 [detachedXmlTextNode, 8]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 73 [detachedXmlTextNode, 8]":true, + "extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 75 [detachedComment, 3]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 76 [detachedComment, 5]":true, + "extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 77 [detachedForeignComment, 0]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 77 [detachedForeignComment, 0]":true, + "extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 78 [detachedForeignComment, 4]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 78 [detachedForeignComment, 4]":true, + "extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 79 [detachedXmlComment, 2]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 79 [detachedXmlComment, 2]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 80 [docfrag, 0]":true, + "extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 81 [foreignDocfrag, 0]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 81 [foreignDocfrag, 0]":true, + "extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 82 [xmlDocfrag, 0]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 82 [xmlDocfrag, 0]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 83 [doctype, 0]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 84 [doctype, -17]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 85 [doctype, 1]":true, + "extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 86 [foreignDoctype, 0]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 86 [foreignDoctype, 0]":true, + "extend() forwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 87 [xmlDoctype, 0]":true, + "extend() backwards with range 42 [foreignDoc, 1, foreignComment, 2] and point 87 [xmlDoctype, 0]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 0 [paras[0].firstChild, -1]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 1 [paras[0].firstChild, 0]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 2 [paras[0].firstChild, 1]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 3 [paras[0].firstChild, 2]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 4 [paras[0].firstChild, 8]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 5 [paras[0].firstChild, 9]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 6 [paras[0].firstChild, 10]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 7 [paras[0].firstChild, 65535]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 8 [paras[1].firstChild, -1]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 9 [paras[1].firstChild, 0]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 10 [paras[1].firstChild, 1]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 11 [paras[1].firstChild, 2]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 12 [paras[1].firstChild, 8]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 13 [paras[1].firstChild, 9]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 14 [paras[1].firstChild, 10]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 15 [paras[1].firstChild, 65535]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 16 [detachedPara1.firstChild, 0]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 17 [detachedPara1.firstChild, 1]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 18 [detachedPara1.firstChild, 8]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 19 [detachedPara1.firstChild, 9]":true, + "extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 24 [document.documentElement, -1]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 25 [document.documentElement, 0]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 26 [document.documentElement, 1]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 27 [document.documentElement, 2]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 28 [document.documentElement, 7]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 29 [document.head, 1]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 30 [document.body, 3]":true, + "extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 33 [foreignDoc.head, 0]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 33 [foreignDoc.head, 0]":true, + "extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 34 [foreignDoc.body, 1]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 34 [foreignDoc.body, 1]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 35 [paras[0], 0]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 36 [paras[0], 1]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 37 [paras[0], 2]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 38 [paras[1], 0]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 39 [paras[1], 1]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 40 [paras[1], 2]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 41 [detachedPara1, 0]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 42 [detachedPara1, 1]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 43 [testDiv, 0]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 44 [testDiv, 3]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 45 [document, -1]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 46 [document, 0]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 47 [document, 1]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 48 [document, 2]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 49 [document, 3]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 50 [comment, -1]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 51 [comment, 0]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 52 [comment, 4]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 53 [comment, 96]":true, + "extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 54 [foreignDoc, 0]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 54 [foreignDoc, 0]":true, + "extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 55 [foreignDoc, 1]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 55 [foreignDoc, 1]":true, + "extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 56 [foreignComment, 2]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 56 [foreignComment, 2]":true, + "extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 57 [foreignTextNode, 0]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 57 [foreignTextNode, 0]":true, + "extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 58 [foreignTextNode, 36]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 58 [foreignTextNode, 36]":true, + "extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 59 [xmlDoc, -1]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 59 [xmlDoc, -1]":true, + "extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 60 [xmlDoc, 0]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 60 [xmlDoc, 0]":true, + "extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 61 [xmlDoc, 1]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 61 [xmlDoc, 1]":true, + "extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 62 [xmlDoc, 5]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 62 [xmlDoc, 5]":true, + "extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 63 [xmlComment, 0]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 63 [xmlComment, 0]":true, + "extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 64 [xmlComment, 4]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 64 [xmlComment, 4]":true, + "extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 65 [processingInstruction, 0]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 65 [processingInstruction, 0]":true, + "extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 66 [processingInstruction, 5]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 66 [processingInstruction, 5]":true, + "extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 67 [processingInstruction, 9]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 67 [processingInstruction, 9]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 68 [detachedTextNode, 0]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 69 [detachedTextNode, 8]":true, + "extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 70 [detachedForeignTextNode, 0]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 70 [detachedForeignTextNode, 0]":true, + "extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 71 [detachedForeignTextNode, 8]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 71 [detachedForeignTextNode, 8]":true, + "extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 72 [detachedXmlTextNode, 0]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 72 [detachedXmlTextNode, 0]":true, + "extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 73 [detachedXmlTextNode, 8]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 73 [detachedXmlTextNode, 8]":true, + "extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 75 [detachedComment, 3]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 76 [detachedComment, 5]":true, + "extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 77 [detachedForeignComment, 0]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 77 [detachedForeignComment, 0]":true, + "extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 78 [detachedForeignComment, 4]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 78 [detachedForeignComment, 4]":true, + "extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 79 [detachedXmlComment, 2]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 79 [detachedXmlComment, 2]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 80 [docfrag, 0]":true, + "extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 81 [foreignDocfrag, 0]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 81 [foreignDocfrag, 0]":true, + "extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 82 [xmlDocfrag, 0]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 82 [xmlDocfrag, 0]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 83 [doctype, 0]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 84 [doctype, -17]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 85 [doctype, 1]":true, + "extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 86 [foreignDoctype, 0]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 86 [foreignDoctype, 0]":true, + "extend() forwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 87 [xmlDoctype, 0]":true, + "extend() backwards with range 43 [foreignDoc.body, 0, foreignTextNode, 36] and point 87 [xmlDoctype, 0]":true, + "extend() with range 44 [xmlDoc, 0, xmlDoc, 0] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() with range 44 [xmlDoc, 0, xmlDoc, 0] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() with range 44 [xmlDoc, 0, xmlDoc, 0] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() with range 44 [xmlDoc, 0, xmlDoc, 0] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() with range 44 [xmlDoc, 0, xmlDoc, 0] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() with range 44 [xmlDoc, 0, xmlDoc, 0] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() with range 44 [xmlDoc, 0, xmlDoc, 0] and point 33 [foreignDoc.head, 0]":true, + "extend() with range 44 [xmlDoc, 0, xmlDoc, 0] and point 34 [foreignDoc.body, 1]":true, + "extend() with range 44 [xmlDoc, 0, xmlDoc, 0] and point 54 [foreignDoc, 0]":true, + "extend() with range 44 [xmlDoc, 0, xmlDoc, 0] and point 55 [foreignDoc, 1]":true, + "extend() with range 44 [xmlDoc, 0, xmlDoc, 0] and point 56 [foreignComment, 2]":true, + "extend() with range 44 [xmlDoc, 0, xmlDoc, 0] and point 57 [foreignTextNode, 0]":true, + "extend() with range 44 [xmlDoc, 0, xmlDoc, 0] and point 58 [foreignTextNode, 36]":true, + "extend() with range 44 [xmlDoc, 0, xmlDoc, 0] and point 59 [xmlDoc, -1]":true, + "extend() with range 44 [xmlDoc, 0, xmlDoc, 0] and point 60 [xmlDoc, 0]":true, + "extend() with range 44 [xmlDoc, 0, xmlDoc, 0] and point 61 [xmlDoc, 1]":true, + "extend() with range 44 [xmlDoc, 0, xmlDoc, 0] and point 62 [xmlDoc, 5]":true, + "extend() with range 44 [xmlDoc, 0, xmlDoc, 0] and point 63 [xmlComment, 0]":true, + "extend() with range 44 [xmlDoc, 0, xmlDoc, 0] and point 64 [xmlComment, 4]":true, + "extend() with range 44 [xmlDoc, 0, xmlDoc, 0] and point 65 [processingInstruction, 0]":true, + "extend() with range 44 [xmlDoc, 0, xmlDoc, 0] and point 66 [processingInstruction, 5]":true, + "extend() with range 44 [xmlDoc, 0, xmlDoc, 0] and point 67 [processingInstruction, 9]":true, + "extend() with range 44 [xmlDoc, 0, xmlDoc, 0] and point 70 [detachedForeignTextNode, 0]":true, + "extend() with range 44 [xmlDoc, 0, xmlDoc, 0] and point 71 [detachedForeignTextNode, 8]":true, + "extend() with range 44 [xmlDoc, 0, xmlDoc, 0] and point 72 [detachedXmlTextNode, 0]":true, + "extend() with range 44 [xmlDoc, 0, xmlDoc, 0] and point 73 [detachedXmlTextNode, 8]":true, + "extend() with range 44 [xmlDoc, 0, xmlDoc, 0] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() with range 44 [xmlDoc, 0, xmlDoc, 0] and point 77 [detachedForeignComment, 0]":true, + "extend() with range 44 [xmlDoc, 0, xmlDoc, 0] and point 78 [detachedForeignComment, 4]":true, + "extend() with range 44 [xmlDoc, 0, xmlDoc, 0] and point 79 [detachedXmlComment, 2]":true, + "extend() with range 44 [xmlDoc, 0, xmlDoc, 0] and point 81 [foreignDocfrag, 0]":true, + "extend() with range 44 [xmlDoc, 0, xmlDoc, 0] and point 82 [xmlDocfrag, 0]":true, + "extend() with range 44 [xmlDoc, 0, xmlDoc, 0] and point 86 [foreignDoctype, 0]":true, + "extend() with range 44 [xmlDoc, 0, xmlDoc, 0] and point 87 [xmlDoctype, 0]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 0 [paras[0].firstChild, -1]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 1 [paras[0].firstChild, 0]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 2 [paras[0].firstChild, 1]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 3 [paras[0].firstChild, 2]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 4 [paras[0].firstChild, 8]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 5 [paras[0].firstChild, 9]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 6 [paras[0].firstChild, 10]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 7 [paras[0].firstChild, 65535]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 8 [paras[1].firstChild, -1]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 9 [paras[1].firstChild, 0]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 10 [paras[1].firstChild, 1]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 11 [paras[1].firstChild, 2]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 12 [paras[1].firstChild, 8]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 13 [paras[1].firstChild, 9]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 14 [paras[1].firstChild, 10]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 15 [paras[1].firstChild, 65535]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 16 [detachedPara1.firstChild, 0]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 17 [detachedPara1.firstChild, 1]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 18 [detachedPara1.firstChild, 8]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 19 [detachedPara1.firstChild, 9]":true, + "extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 24 [document.documentElement, -1]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 25 [document.documentElement, 0]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 26 [document.documentElement, 1]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 27 [document.documentElement, 2]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 28 [document.documentElement, 7]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 29 [document.head, 1]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 30 [document.body, 3]":true, + "extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 33 [foreignDoc.head, 0]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 33 [foreignDoc.head, 0]":true, + "extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 34 [foreignDoc.body, 1]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 34 [foreignDoc.body, 1]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 35 [paras[0], 0]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 36 [paras[0], 1]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 37 [paras[0], 2]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 38 [paras[1], 0]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 39 [paras[1], 1]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 40 [paras[1], 2]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 41 [detachedPara1, 0]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 42 [detachedPara1, 1]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 43 [testDiv, 0]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 44 [testDiv, 3]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 45 [document, -1]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 46 [document, 0]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 47 [document, 1]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 48 [document, 2]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 49 [document, 3]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 50 [comment, -1]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 51 [comment, 0]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 52 [comment, 4]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 53 [comment, 96]":true, + "extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 54 [foreignDoc, 0]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 54 [foreignDoc, 0]":true, + "extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 55 [foreignDoc, 1]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 55 [foreignDoc, 1]":true, + "extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 56 [foreignComment, 2]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 56 [foreignComment, 2]":true, + "extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 57 [foreignTextNode, 0]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 57 [foreignTextNode, 0]":true, + "extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 58 [foreignTextNode, 36]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 58 [foreignTextNode, 36]":true, + "extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 59 [xmlDoc, -1]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 59 [xmlDoc, -1]":true, + "extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 60 [xmlDoc, 0]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 60 [xmlDoc, 0]":true, + "extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 61 [xmlDoc, 1]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 61 [xmlDoc, 1]":true, + "extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 62 [xmlDoc, 5]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 62 [xmlDoc, 5]":true, + "extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 63 [xmlComment, 0]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 63 [xmlComment, 0]":true, + "extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 64 [xmlComment, 4]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 64 [xmlComment, 4]":true, + "extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 65 [processingInstruction, 0]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 65 [processingInstruction, 0]":true, + "extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 66 [processingInstruction, 5]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 66 [processingInstruction, 5]":true, + "extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 67 [processingInstruction, 9]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 67 [processingInstruction, 9]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 68 [detachedTextNode, 0]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 69 [detachedTextNode, 8]":true, + "extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 70 [detachedForeignTextNode, 0]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 70 [detachedForeignTextNode, 0]":true, + "extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 71 [detachedForeignTextNode, 8]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 71 [detachedForeignTextNode, 8]":true, + "extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 72 [detachedXmlTextNode, 0]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 72 [detachedXmlTextNode, 0]":true, + "extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 73 [detachedXmlTextNode, 8]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 73 [detachedXmlTextNode, 8]":true, + "extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 75 [detachedComment, 3]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 76 [detachedComment, 5]":true, + "extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 77 [detachedForeignComment, 0]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 77 [detachedForeignComment, 0]":true, + "extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 78 [detachedForeignComment, 4]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 78 [detachedForeignComment, 4]":true, + "extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 79 [detachedXmlComment, 2]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 79 [detachedXmlComment, 2]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 80 [docfrag, 0]":true, + "extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 81 [foreignDocfrag, 0]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 81 [foreignDocfrag, 0]":true, + "extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 82 [xmlDocfrag, 0]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 82 [xmlDocfrag, 0]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 83 [doctype, 0]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 84 [doctype, -17]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 85 [doctype, 1]":true, + "extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 86 [foreignDoctype, 0]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 86 [foreignDoctype, 0]":true, + "extend() forwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 87 [xmlDoctype, 0]":true, + "extend() backwards with range 45 [xmlDoc, 1, xmlComment, 0] and point 87 [xmlDoctype, 0]":true, + "extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 33 [foreignDoc.head, 0]":true, + "extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 33 [foreignDoc.head, 0]":true, + "extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 34 [foreignDoc.body, 1]":true, + "extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 34 [foreignDoc.body, 1]":true, + "extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 54 [foreignDoc, 0]":true, + "extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 54 [foreignDoc, 0]":true, + "extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 55 [foreignDoc, 1]":true, + "extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 55 [foreignDoc, 1]":true, + "extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 56 [foreignComment, 2]":true, + "extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 56 [foreignComment, 2]":true, + "extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 57 [foreignTextNode, 0]":true, + "extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 57 [foreignTextNode, 0]":true, + "extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 58 [foreignTextNode, 36]":true, + "extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 58 [foreignTextNode, 36]":true, + "extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 59 [xmlDoc, -1]":true, + "extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 59 [xmlDoc, -1]":true, + "extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 60 [xmlDoc, 0]":true, + "extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 60 [xmlDoc, 0]":true, + "extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 61 [xmlDoc, 1]":true, + "extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 61 [xmlDoc, 1]":true, + "extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 62 [xmlDoc, 5]":true, + "extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 62 [xmlDoc, 5]":true, + "extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 63 [xmlComment, 0]":true, + "extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 63 [xmlComment, 0]":true, + "extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 64 [xmlComment, 4]":true, + "extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 64 [xmlComment, 4]":true, + "extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 65 [processingInstruction, 0]":true, + "extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 65 [processingInstruction, 0]":true, + "extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 66 [processingInstruction, 5]":true, + "extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 66 [processingInstruction, 5]":true, + "extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 67 [processingInstruction, 9]":true, + "extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 67 [processingInstruction, 9]":true, + "extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 70 [detachedForeignTextNode, 0]":true, + "extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 70 [detachedForeignTextNode, 0]":true, + "extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 71 [detachedForeignTextNode, 8]":true, + "extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 71 [detachedForeignTextNode, 8]":true, + "extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 72 [detachedXmlTextNode, 0]":true, + "extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 72 [detachedXmlTextNode, 0]":true, + "extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 73 [detachedXmlTextNode, 8]":true, + "extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 73 [detachedXmlTextNode, 8]":true, + "extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 77 [detachedForeignComment, 0]":true, + "extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 77 [detachedForeignComment, 0]":true, + "extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 78 [detachedForeignComment, 4]":true, + "extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 78 [detachedForeignComment, 4]":true, + "extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 79 [detachedXmlComment, 2]":true, + "extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 79 [detachedXmlComment, 2]":true, + "extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 81 [foreignDocfrag, 0]":true, + "extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 81 [foreignDocfrag, 0]":true, + "extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 82 [xmlDocfrag, 0]":true, + "extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 82 [xmlDocfrag, 0]":true, + "extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 86 [foreignDoctype, 0]":true, + "extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 86 [foreignDoctype, 0]":true, + "extend() forwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 87 [xmlDoctype, 0]":true, + "extend() backwards with range 46 [detachedTextNode, 0, detachedTextNode, 8] and point 87 [xmlDoctype, 0]":true, + "extend() with range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() with range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() with range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() with range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() with range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() with range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() with range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7] and point 33 [foreignDoc.head, 0]":true, + "extend() with range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7] and point 34 [foreignDoc.body, 1]":true, + "extend() with range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7] and point 54 [foreignDoc, 0]":true, + "extend() with range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7] and point 55 [foreignDoc, 1]":true, + "extend() with range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7] and point 56 [foreignComment, 2]":true, + "extend() with range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7] and point 57 [foreignTextNode, 0]":true, + "extend() with range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7] and point 58 [foreignTextNode, 36]":true, + "extend() with range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7] and point 59 [xmlDoc, -1]":true, + "extend() with range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7] and point 60 [xmlDoc, 0]":true, + "extend() with range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7] and point 61 [xmlDoc, 1]":true, + "extend() with range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7] and point 62 [xmlDoc, 5]":true, + "extend() with range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7] and point 63 [xmlComment, 0]":true, + "extend() with range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7] and point 64 [xmlComment, 4]":true, + "extend() with range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7] and point 65 [processingInstruction, 0]":true, + "extend() with range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7] and point 66 [processingInstruction, 5]":true, + "extend() with range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7] and point 67 [processingInstruction, 9]":true, + "extend() with range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7] and point 70 [detachedForeignTextNode, 0]":true, + "extend() with range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7] and point 71 [detachedForeignTextNode, 8]":true, + "extend() with range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7] and point 72 [detachedXmlTextNode, 0]":true, + "extend() with range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7] and point 73 [detachedXmlTextNode, 8]":true, + "extend() with range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() with range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7] and point 77 [detachedForeignComment, 0]":true, + "extend() with range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7] and point 78 [detachedForeignComment, 4]":true, + "extend() with range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7] and point 79 [detachedXmlComment, 2]":true, + "extend() with range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7] and point 81 [foreignDocfrag, 0]":true, + "extend() with range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7] and point 82 [xmlDocfrag, 0]":true, + "extend() with range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7] and point 86 [foreignDoctype, 0]":true, + "extend() with range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7] and point 87 [xmlDoctype, 0]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 0 [paras[0].firstChild, -1]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 1 [paras[0].firstChild, 0]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 2 [paras[0].firstChild, 1]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 3 [paras[0].firstChild, 2]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 4 [paras[0].firstChild, 8]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 5 [paras[0].firstChild, 9]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 6 [paras[0].firstChild, 10]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 7 [paras[0].firstChild, 65535]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 8 [paras[1].firstChild, -1]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 9 [paras[1].firstChild, 0]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 10 [paras[1].firstChild, 1]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 11 [paras[1].firstChild, 2]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 12 [paras[1].firstChild, 8]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 13 [paras[1].firstChild, 9]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 14 [paras[1].firstChild, 10]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 15 [paras[1].firstChild, 65535]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 16 [detachedPara1.firstChild, 0]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 17 [detachedPara1.firstChild, 1]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 18 [detachedPara1.firstChild, 8]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 19 [detachedPara1.firstChild, 9]":true, + "extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 24 [document.documentElement, -1]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 25 [document.documentElement, 0]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 26 [document.documentElement, 1]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 27 [document.documentElement, 2]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 28 [document.documentElement, 7]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 29 [document.head, 1]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 30 [document.body, 3]":true, + "extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 33 [foreignDoc.head, 0]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 33 [foreignDoc.head, 0]":true, + "extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 34 [foreignDoc.body, 1]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 34 [foreignDoc.body, 1]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 35 [paras[0], 0]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 36 [paras[0], 1]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 37 [paras[0], 2]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 38 [paras[1], 0]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 39 [paras[1], 1]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 40 [paras[1], 2]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 41 [detachedPara1, 0]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 42 [detachedPara1, 1]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 43 [testDiv, 0]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 44 [testDiv, 3]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 45 [document, -1]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 46 [document, 0]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 47 [document, 1]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 48 [document, 2]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 49 [document, 3]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 50 [comment, -1]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 51 [comment, 0]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 52 [comment, 4]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 53 [comment, 96]":true, + "extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 54 [foreignDoc, 0]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 54 [foreignDoc, 0]":true, + "extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 55 [foreignDoc, 1]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 55 [foreignDoc, 1]":true, + "extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 56 [foreignComment, 2]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 56 [foreignComment, 2]":true, + "extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 57 [foreignTextNode, 0]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 57 [foreignTextNode, 0]":true, + "extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 58 [foreignTextNode, 36]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 58 [foreignTextNode, 36]":true, + "extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 59 [xmlDoc, -1]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 59 [xmlDoc, -1]":true, + "extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 60 [xmlDoc, 0]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 60 [xmlDoc, 0]":true, + "extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 61 [xmlDoc, 1]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 61 [xmlDoc, 1]":true, + "extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 62 [xmlDoc, 5]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 62 [xmlDoc, 5]":true, + "extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 63 [xmlComment, 0]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 63 [xmlComment, 0]":true, + "extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 64 [xmlComment, 4]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 64 [xmlComment, 4]":true, + "extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 65 [processingInstruction, 0]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 65 [processingInstruction, 0]":true, + "extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 66 [processingInstruction, 5]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 66 [processingInstruction, 5]":true, + "extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 67 [processingInstruction, 9]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 67 [processingInstruction, 9]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 68 [detachedTextNode, 0]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 69 [detachedTextNode, 8]":true, + "extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 70 [detachedForeignTextNode, 0]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 70 [detachedForeignTextNode, 0]":true, + "extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 71 [detachedForeignTextNode, 8]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 71 [detachedForeignTextNode, 8]":true, + "extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 72 [detachedXmlTextNode, 0]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 72 [detachedXmlTextNode, 0]":true, + "extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 73 [detachedXmlTextNode, 8]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 73 [detachedXmlTextNode, 8]":true, + "extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 75 [detachedComment, 3]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 76 [detachedComment, 5]":true, + "extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 77 [detachedForeignComment, 0]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 77 [detachedForeignComment, 0]":true, + "extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 78 [detachedForeignComment, 4]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 78 [detachedForeignComment, 4]":true, + "extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 79 [detachedXmlComment, 2]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 79 [detachedXmlComment, 2]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 80 [docfrag, 0]":true, + "extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 81 [foreignDocfrag, 0]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 81 [foreignDocfrag, 0]":true, + "extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 82 [xmlDocfrag, 0]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 82 [xmlDocfrag, 0]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 83 [doctype, 0]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 84 [doctype, -17]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 85 [doctype, 1]":true, + "extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 86 [foreignDoctype, 0]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 86 [foreignDoctype, 0]":true, + "extend() forwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 87 [xmlDoctype, 0]":true, + "extend() backwards with range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] and point 87 [xmlDoctype, 0]":true, + "extend() with range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() with range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() with range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() with range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() with range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() with range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() with range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7] and point 33 [foreignDoc.head, 0]":true, + "extend() with range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7] and point 34 [foreignDoc.body, 1]":true, + "extend() with range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7] and point 54 [foreignDoc, 0]":true, + "extend() with range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7] and point 55 [foreignDoc, 1]":true, + "extend() with range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7] and point 56 [foreignComment, 2]":true, + "extend() with range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7] and point 57 [foreignTextNode, 0]":true, + "extend() with range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7] and point 58 [foreignTextNode, 36]":true, + "extend() with range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7] and point 59 [xmlDoc, -1]":true, + "extend() with range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7] and point 60 [xmlDoc, 0]":true, + "extend() with range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7] and point 61 [xmlDoc, 1]":true, + "extend() with range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7] and point 62 [xmlDoc, 5]":true, + "extend() with range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7] and point 63 [xmlComment, 0]":true, + "extend() with range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7] and point 64 [xmlComment, 4]":true, + "extend() with range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7] and point 65 [processingInstruction, 0]":true, + "extend() with range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7] and point 66 [processingInstruction, 5]":true, + "extend() with range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7] and point 67 [processingInstruction, 9]":true, + "extend() with range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7] and point 70 [detachedForeignTextNode, 0]":true, + "extend() with range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7] and point 71 [detachedForeignTextNode, 8]":true, + "extend() with range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7] and point 72 [detachedXmlTextNode, 0]":true, + "extend() with range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7] and point 73 [detachedXmlTextNode, 8]":true, + "extend() with range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() with range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7] and point 77 [detachedForeignComment, 0]":true, + "extend() with range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7] and point 78 [detachedForeignComment, 4]":true, + "extend() with range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7] and point 79 [detachedXmlComment, 2]":true, + "extend() with range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7] and point 81 [foreignDocfrag, 0]":true, + "extend() with range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7] and point 82 [xmlDocfrag, 0]":true, + "extend() with range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7] and point 86 [foreignDoctype, 0]":true, + "extend() with range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7] and point 87 [xmlDoctype, 0]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 0 [paras[0].firstChild, -1]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 1 [paras[0].firstChild, 0]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 2 [paras[0].firstChild, 1]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 3 [paras[0].firstChild, 2]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 4 [paras[0].firstChild, 8]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 5 [paras[0].firstChild, 9]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 6 [paras[0].firstChild, 10]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 7 [paras[0].firstChild, 65535]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 8 [paras[1].firstChild, -1]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 9 [paras[1].firstChild, 0]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 10 [paras[1].firstChild, 1]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 11 [paras[1].firstChild, 2]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 12 [paras[1].firstChild, 8]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 13 [paras[1].firstChild, 9]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 14 [paras[1].firstChild, 10]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 15 [paras[1].firstChild, 65535]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 16 [detachedPara1.firstChild, 0]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 17 [detachedPara1.firstChild, 1]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 18 [detachedPara1.firstChild, 8]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 19 [detachedPara1.firstChild, 9]":true, + "extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 24 [document.documentElement, -1]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 25 [document.documentElement, 0]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 26 [document.documentElement, 1]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 27 [document.documentElement, 2]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 28 [document.documentElement, 7]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 29 [document.head, 1]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 30 [document.body, 3]":true, + "extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 33 [foreignDoc.head, 0]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 33 [foreignDoc.head, 0]":true, + "extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 34 [foreignDoc.body, 1]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 34 [foreignDoc.body, 1]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 35 [paras[0], 0]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 36 [paras[0], 1]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 37 [paras[0], 2]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 38 [paras[1], 0]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 39 [paras[1], 1]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 40 [paras[1], 2]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 41 [detachedPara1, 0]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 42 [detachedPara1, 1]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 43 [testDiv, 0]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 44 [testDiv, 3]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 45 [document, -1]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 46 [document, 0]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 47 [document, 1]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 48 [document, 2]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 49 [document, 3]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 50 [comment, -1]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 51 [comment, 0]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 52 [comment, 4]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 53 [comment, 96]":true, + "extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 54 [foreignDoc, 0]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 54 [foreignDoc, 0]":true, + "extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 55 [foreignDoc, 1]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 55 [foreignDoc, 1]":true, + "extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 56 [foreignComment, 2]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 56 [foreignComment, 2]":true, + "extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 57 [foreignTextNode, 0]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 57 [foreignTextNode, 0]":true, + "extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 58 [foreignTextNode, 36]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 58 [foreignTextNode, 36]":true, + "extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 59 [xmlDoc, -1]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 59 [xmlDoc, -1]":true, + "extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 60 [xmlDoc, 0]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 60 [xmlDoc, 0]":true, + "extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 61 [xmlDoc, 1]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 61 [xmlDoc, 1]":true, + "extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 62 [xmlDoc, 5]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 62 [xmlDoc, 5]":true, + "extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 63 [xmlComment, 0]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 63 [xmlComment, 0]":true, + "extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 64 [xmlComment, 4]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 64 [xmlComment, 4]":true, + "extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 65 [processingInstruction, 0]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 65 [processingInstruction, 0]":true, + "extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 66 [processingInstruction, 5]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 66 [processingInstruction, 5]":true, + "extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 67 [processingInstruction, 9]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 67 [processingInstruction, 9]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 68 [detachedTextNode, 0]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 69 [detachedTextNode, 8]":true, + "extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 70 [detachedForeignTextNode, 0]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 70 [detachedForeignTextNode, 0]":true, + "extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 71 [detachedForeignTextNode, 8]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 71 [detachedForeignTextNode, 8]":true, + "extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 72 [detachedXmlTextNode, 0]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 72 [detachedXmlTextNode, 0]":true, + "extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 73 [detachedXmlTextNode, 8]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 73 [detachedXmlTextNode, 8]":true, + "extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 75 [detachedComment, 3]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 76 [detachedComment, 5]":true, + "extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 77 [detachedForeignComment, 0]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 77 [detachedForeignComment, 0]":true, + "extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 78 [detachedForeignComment, 4]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 78 [detachedForeignComment, 4]":true, + "extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 79 [detachedXmlComment, 2]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 79 [detachedXmlComment, 2]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 80 [docfrag, 0]":true, + "extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 81 [foreignDocfrag, 0]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 81 [foreignDocfrag, 0]":true, + "extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 82 [xmlDocfrag, 0]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 82 [xmlDocfrag, 0]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 83 [doctype, 0]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 84 [doctype, -17]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 85 [doctype, 1]":true, + "extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 86 [foreignDoctype, 0]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 86 [foreignDoctype, 0]":true, + "extend() forwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 87 [xmlDoctype, 0]":true, + "extend() backwards with range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] and point 87 [xmlDoctype, 0]":true, + "extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 33 [foreignDoc.head, 0]":true, + "extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 33 [foreignDoc.head, 0]":true, + "extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 34 [foreignDoc.body, 1]":true, + "extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 34 [foreignDoc.body, 1]":true, + "extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 54 [foreignDoc, 0]":true, + "extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 54 [foreignDoc, 0]":true, + "extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 55 [foreignDoc, 1]":true, + "extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 55 [foreignDoc, 1]":true, + "extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 56 [foreignComment, 2]":true, + "extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 56 [foreignComment, 2]":true, + "extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 57 [foreignTextNode, 0]":true, + "extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 57 [foreignTextNode, 0]":true, + "extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 58 [foreignTextNode, 36]":true, + "extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 58 [foreignTextNode, 36]":true, + "extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 59 [xmlDoc, -1]":true, + "extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 59 [xmlDoc, -1]":true, + "extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 60 [xmlDoc, 0]":true, + "extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 60 [xmlDoc, 0]":true, + "extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 61 [xmlDoc, 1]":true, + "extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 61 [xmlDoc, 1]":true, + "extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 62 [xmlDoc, 5]":true, + "extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 62 [xmlDoc, 5]":true, + "extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 63 [xmlComment, 0]":true, + "extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 63 [xmlComment, 0]":true, + "extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 64 [xmlComment, 4]":true, + "extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 64 [xmlComment, 4]":true, + "extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 65 [processingInstruction, 0]":true, + "extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 65 [processingInstruction, 0]":true, + "extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 66 [processingInstruction, 5]":true, + "extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 66 [processingInstruction, 5]":true, + "extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 67 [processingInstruction, 9]":true, + "extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 67 [processingInstruction, 9]":true, + "extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 70 [detachedForeignTextNode, 0]":true, + "extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 70 [detachedForeignTextNode, 0]":true, + "extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 71 [detachedForeignTextNode, 8]":true, + "extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 71 [detachedForeignTextNode, 8]":true, + "extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 72 [detachedXmlTextNode, 0]":true, + "extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 72 [detachedXmlTextNode, 0]":true, + "extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 73 [detachedXmlTextNode, 8]":true, + "extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 73 [detachedXmlTextNode, 8]":true, + "extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 77 [detachedForeignComment, 0]":true, + "extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 77 [detachedForeignComment, 0]":true, + "extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 78 [detachedForeignComment, 4]":true, + "extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 78 [detachedForeignComment, 4]":true, + "extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 79 [detachedXmlComment, 2]":true, + "extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 79 [detachedXmlComment, 2]":true, + "extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 81 [foreignDocfrag, 0]":true, + "extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 81 [foreignDocfrag, 0]":true, + "extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 82 [xmlDocfrag, 0]":true, + "extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 82 [xmlDocfrag, 0]":true, + "extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 86 [foreignDoctype, 0]":true, + "extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 86 [foreignDoctype, 0]":true, + "extend() forwards with range 51 [detachedComment, 3, detachedComment, 4] and point 87 [xmlDoctype, 0]":true, + "extend() backwards with range 51 [detachedComment, 3, detachedComment, 4] and point 87 [xmlDoctype, 0]":true, + "extend() with range 52 [detachedComment, 5, detachedComment, 5] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() with range 52 [detachedComment, 5, detachedComment, 5] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() with range 52 [detachedComment, 5, detachedComment, 5] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() with range 52 [detachedComment, 5, detachedComment, 5] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() with range 52 [detachedComment, 5, detachedComment, 5] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() with range 52 [detachedComment, 5, detachedComment, 5] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() with range 52 [detachedComment, 5, detachedComment, 5] and point 33 [foreignDoc.head, 0]":true, + "extend() with range 52 [detachedComment, 5, detachedComment, 5] and point 34 [foreignDoc.body, 1]":true, + "extend() with range 52 [detachedComment, 5, detachedComment, 5] and point 54 [foreignDoc, 0]":true, + "extend() with range 52 [detachedComment, 5, detachedComment, 5] and point 55 [foreignDoc, 1]":true, + "extend() with range 52 [detachedComment, 5, detachedComment, 5] and point 56 [foreignComment, 2]":true, + "extend() with range 52 [detachedComment, 5, detachedComment, 5] and point 57 [foreignTextNode, 0]":true, + "extend() with range 52 [detachedComment, 5, detachedComment, 5] and point 58 [foreignTextNode, 36]":true, + "extend() with range 52 [detachedComment, 5, detachedComment, 5] and point 59 [xmlDoc, -1]":true, + "extend() with range 52 [detachedComment, 5, detachedComment, 5] and point 60 [xmlDoc, 0]":true, + "extend() with range 52 [detachedComment, 5, detachedComment, 5] and point 61 [xmlDoc, 1]":true, + "extend() with range 52 [detachedComment, 5, detachedComment, 5] and point 62 [xmlDoc, 5]":true, + "extend() with range 52 [detachedComment, 5, detachedComment, 5] and point 63 [xmlComment, 0]":true, + "extend() with range 52 [detachedComment, 5, detachedComment, 5] and point 64 [xmlComment, 4]":true, + "extend() with range 52 [detachedComment, 5, detachedComment, 5] and point 65 [processingInstruction, 0]":true, + "extend() with range 52 [detachedComment, 5, detachedComment, 5] and point 66 [processingInstruction, 5]":true, + "extend() with range 52 [detachedComment, 5, detachedComment, 5] and point 67 [processingInstruction, 9]":true, + "extend() with range 52 [detachedComment, 5, detachedComment, 5] and point 70 [detachedForeignTextNode, 0]":true, + "extend() with range 52 [detachedComment, 5, detachedComment, 5] and point 71 [detachedForeignTextNode, 8]":true, + "extend() with range 52 [detachedComment, 5, detachedComment, 5] and point 72 [detachedXmlTextNode, 0]":true, + "extend() with range 52 [detachedComment, 5, detachedComment, 5] and point 73 [detachedXmlTextNode, 8]":true, + "extend() with range 52 [detachedComment, 5, detachedComment, 5] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() with range 52 [detachedComment, 5, detachedComment, 5] and point 77 [detachedForeignComment, 0]":true, + "extend() with range 52 [detachedComment, 5, detachedComment, 5] and point 78 [detachedForeignComment, 4]":true, + "extend() with range 52 [detachedComment, 5, detachedComment, 5] and point 79 [detachedXmlComment, 2]":true, + "extend() with range 52 [detachedComment, 5, detachedComment, 5] and point 81 [foreignDocfrag, 0]":true, + "extend() with range 52 [detachedComment, 5, detachedComment, 5] and point 82 [xmlDocfrag, 0]":true, + "extend() with range 52 [detachedComment, 5, detachedComment, 5] and point 86 [foreignDoctype, 0]":true, + "extend() with range 52 [detachedComment, 5, detachedComment, 5] and point 87 [xmlDoctype, 0]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 0 [paras[0].firstChild, -1]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 1 [paras[0].firstChild, 0]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 2 [paras[0].firstChild, 1]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 3 [paras[0].firstChild, 2]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 4 [paras[0].firstChild, 8]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 5 [paras[0].firstChild, 9]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 6 [paras[0].firstChild, 10]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 7 [paras[0].firstChild, 65535]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 8 [paras[1].firstChild, -1]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 9 [paras[1].firstChild, 0]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 10 [paras[1].firstChild, 1]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 11 [paras[1].firstChild, 2]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 12 [paras[1].firstChild, 8]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 13 [paras[1].firstChild, 9]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 14 [paras[1].firstChild, 10]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 15 [paras[1].firstChild, 65535]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 16 [detachedPara1.firstChild, 0]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 17 [detachedPara1.firstChild, 1]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 18 [detachedPara1.firstChild, 8]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 19 [detachedPara1.firstChild, 9]":true, + "extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 24 [document.documentElement, -1]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 25 [document.documentElement, 0]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 26 [document.documentElement, 1]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 27 [document.documentElement, 2]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 28 [document.documentElement, 7]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 29 [document.head, 1]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 30 [document.body, 3]":true, + "extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 33 [foreignDoc.head, 0]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 33 [foreignDoc.head, 0]":true, + "extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 34 [foreignDoc.body, 1]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 34 [foreignDoc.body, 1]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 35 [paras[0], 0]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 36 [paras[0], 1]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 37 [paras[0], 2]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 38 [paras[1], 0]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 39 [paras[1], 1]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 40 [paras[1], 2]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 41 [detachedPara1, 0]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 42 [detachedPara1, 1]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 43 [testDiv, 0]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 44 [testDiv, 3]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 45 [document, -1]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 46 [document, 0]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 47 [document, 1]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 48 [document, 2]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 49 [document, 3]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 50 [comment, -1]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 51 [comment, 0]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 52 [comment, 4]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 53 [comment, 96]":true, + "extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 54 [foreignDoc, 0]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 54 [foreignDoc, 0]":true, + "extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 55 [foreignDoc, 1]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 55 [foreignDoc, 1]":true, + "extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 56 [foreignComment, 2]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 56 [foreignComment, 2]":true, + "extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 57 [foreignTextNode, 0]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 57 [foreignTextNode, 0]":true, + "extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 58 [foreignTextNode, 36]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 58 [foreignTextNode, 36]":true, + "extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 59 [xmlDoc, -1]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 59 [xmlDoc, -1]":true, + "extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 60 [xmlDoc, 0]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 60 [xmlDoc, 0]":true, + "extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 61 [xmlDoc, 1]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 61 [xmlDoc, 1]":true, + "extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 62 [xmlDoc, 5]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 62 [xmlDoc, 5]":true, + "extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 63 [xmlComment, 0]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 63 [xmlComment, 0]":true, + "extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 64 [xmlComment, 4]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 64 [xmlComment, 4]":true, + "extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 65 [processingInstruction, 0]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 65 [processingInstruction, 0]":true, + "extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 66 [processingInstruction, 5]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 66 [processingInstruction, 5]":true, + "extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 67 [processingInstruction, 9]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 67 [processingInstruction, 9]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 68 [detachedTextNode, 0]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 69 [detachedTextNode, 8]":true, + "extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 70 [detachedForeignTextNode, 0]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 70 [detachedForeignTextNode, 0]":true, + "extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 71 [detachedForeignTextNode, 8]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 71 [detachedForeignTextNode, 8]":true, + "extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 72 [detachedXmlTextNode, 0]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 72 [detachedXmlTextNode, 0]":true, + "extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 73 [detachedXmlTextNode, 8]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 73 [detachedXmlTextNode, 8]":true, + "extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 75 [detachedComment, 3]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 76 [detachedComment, 5]":true, + "extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 77 [detachedForeignComment, 0]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 77 [detachedForeignComment, 0]":true, + "extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 78 [detachedForeignComment, 4]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 78 [detachedForeignComment, 4]":true, + "extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 79 [detachedXmlComment, 2]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 79 [detachedXmlComment, 2]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 80 [docfrag, 0]":true, + "extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 81 [foreignDocfrag, 0]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 81 [foreignDocfrag, 0]":true, + "extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 82 [xmlDocfrag, 0]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 82 [xmlDocfrag, 0]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 83 [doctype, 0]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 84 [doctype, -17]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 85 [doctype, 1]":true, + "extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 86 [foreignDoctype, 0]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 86 [foreignDoctype, 0]":true, + "extend() forwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 87 [xmlDoctype, 0]":true, + "extend() backwards with range 53 [detachedForeignComment, 0, detachedForeignComment, 1] and point 87 [xmlDoctype, 0]":true, + "extend() with range 54 [detachedForeignComment, 4, detachedForeignComment, 4] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() with range 54 [detachedForeignComment, 4, detachedForeignComment, 4] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() with range 54 [detachedForeignComment, 4, detachedForeignComment, 4] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() with range 54 [detachedForeignComment, 4, detachedForeignComment, 4] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() with range 54 [detachedForeignComment, 4, detachedForeignComment, 4] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() with range 54 [detachedForeignComment, 4, detachedForeignComment, 4] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() with range 54 [detachedForeignComment, 4, detachedForeignComment, 4] and point 33 [foreignDoc.head, 0]":true, + "extend() with range 54 [detachedForeignComment, 4, detachedForeignComment, 4] and point 34 [foreignDoc.body, 1]":true, + "extend() with range 54 [detachedForeignComment, 4, detachedForeignComment, 4] and point 54 [foreignDoc, 0]":true, + "extend() with range 54 [detachedForeignComment, 4, detachedForeignComment, 4] and point 55 [foreignDoc, 1]":true, + "extend() with range 54 [detachedForeignComment, 4, detachedForeignComment, 4] and point 56 [foreignComment, 2]":true, + "extend() with range 54 [detachedForeignComment, 4, detachedForeignComment, 4] and point 57 [foreignTextNode, 0]":true, + "extend() with range 54 [detachedForeignComment, 4, detachedForeignComment, 4] and point 58 [foreignTextNode, 36]":true, + "extend() with range 54 [detachedForeignComment, 4, detachedForeignComment, 4] and point 59 [xmlDoc, -1]":true, + "extend() with range 54 [detachedForeignComment, 4, detachedForeignComment, 4] and point 60 [xmlDoc, 0]":true, + "extend() with range 54 [detachedForeignComment, 4, detachedForeignComment, 4] and point 61 [xmlDoc, 1]":true, + "extend() with range 54 [detachedForeignComment, 4, detachedForeignComment, 4] and point 62 [xmlDoc, 5]":true, + "extend() with range 54 [detachedForeignComment, 4, detachedForeignComment, 4] and point 63 [xmlComment, 0]":true, + "extend() with range 54 [detachedForeignComment, 4, detachedForeignComment, 4] and point 64 [xmlComment, 4]":true, + "extend() with range 54 [detachedForeignComment, 4, detachedForeignComment, 4] and point 65 [processingInstruction, 0]":true, + "extend() with range 54 [detachedForeignComment, 4, detachedForeignComment, 4] and point 66 [processingInstruction, 5]":true, + "extend() with range 54 [detachedForeignComment, 4, detachedForeignComment, 4] and point 67 [processingInstruction, 9]":true, + "extend() with range 54 [detachedForeignComment, 4, detachedForeignComment, 4] and point 70 [detachedForeignTextNode, 0]":true, + "extend() with range 54 [detachedForeignComment, 4, detachedForeignComment, 4] and point 71 [detachedForeignTextNode, 8]":true, + "extend() with range 54 [detachedForeignComment, 4, detachedForeignComment, 4] and point 72 [detachedXmlTextNode, 0]":true, + "extend() with range 54 [detachedForeignComment, 4, detachedForeignComment, 4] and point 73 [detachedXmlTextNode, 8]":true, + "extend() with range 54 [detachedForeignComment, 4, detachedForeignComment, 4] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() with range 54 [detachedForeignComment, 4, detachedForeignComment, 4] and point 77 [detachedForeignComment, 0]":true, + "extend() with range 54 [detachedForeignComment, 4, detachedForeignComment, 4] and point 78 [detachedForeignComment, 4]":true, + "extend() with range 54 [detachedForeignComment, 4, detachedForeignComment, 4] and point 79 [detachedXmlComment, 2]":true, + "extend() with range 54 [detachedForeignComment, 4, detachedForeignComment, 4] and point 81 [foreignDocfrag, 0]":true, + "extend() with range 54 [detachedForeignComment, 4, detachedForeignComment, 4] and point 82 [xmlDocfrag, 0]":true, + "extend() with range 54 [detachedForeignComment, 4, detachedForeignComment, 4] and point 86 [foreignDoctype, 0]":true, + "extend() with range 54 [detachedForeignComment, 4, detachedForeignComment, 4] and point 87 [xmlDoctype, 0]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 0 [paras[0].firstChild, -1]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 1 [paras[0].firstChild, 0]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 2 [paras[0].firstChild, 1]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 3 [paras[0].firstChild, 2]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 4 [paras[0].firstChild, 8]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 5 [paras[0].firstChild, 9]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 6 [paras[0].firstChild, 10]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 7 [paras[0].firstChild, 65535]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 8 [paras[1].firstChild, -1]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 9 [paras[1].firstChild, 0]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 10 [paras[1].firstChild, 1]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 11 [paras[1].firstChild, 2]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 12 [paras[1].firstChild, 8]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 13 [paras[1].firstChild, 9]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 14 [paras[1].firstChild, 10]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 15 [paras[1].firstChild, 65535]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 16 [detachedPara1.firstChild, 0]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 17 [detachedPara1.firstChild, 1]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 18 [detachedPara1.firstChild, 8]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 19 [detachedPara1.firstChild, 9]":true, + "extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 24 [document.documentElement, -1]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 25 [document.documentElement, 0]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 26 [document.documentElement, 1]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 27 [document.documentElement, 2]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 28 [document.documentElement, 7]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 29 [document.head, 1]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 30 [document.body, 3]":true, + "extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 33 [foreignDoc.head, 0]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 33 [foreignDoc.head, 0]":true, + "extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 34 [foreignDoc.body, 1]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 34 [foreignDoc.body, 1]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 35 [paras[0], 0]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 36 [paras[0], 1]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 37 [paras[0], 2]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 38 [paras[1], 0]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 39 [paras[1], 1]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 40 [paras[1], 2]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 41 [detachedPara1, 0]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 42 [detachedPara1, 1]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 43 [testDiv, 0]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 44 [testDiv, 3]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 45 [document, -1]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 46 [document, 0]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 47 [document, 1]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 48 [document, 2]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 49 [document, 3]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 50 [comment, -1]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 51 [comment, 0]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 52 [comment, 4]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 53 [comment, 96]":true, + "extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 54 [foreignDoc, 0]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 54 [foreignDoc, 0]":true, + "extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 55 [foreignDoc, 1]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 55 [foreignDoc, 1]":true, + "extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 56 [foreignComment, 2]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 56 [foreignComment, 2]":true, + "extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 57 [foreignTextNode, 0]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 57 [foreignTextNode, 0]":true, + "extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 58 [foreignTextNode, 36]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 58 [foreignTextNode, 36]":true, + "extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 59 [xmlDoc, -1]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 59 [xmlDoc, -1]":true, + "extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 60 [xmlDoc, 0]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 60 [xmlDoc, 0]":true, + "extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 61 [xmlDoc, 1]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 61 [xmlDoc, 1]":true, + "extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 62 [xmlDoc, 5]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 62 [xmlDoc, 5]":true, + "extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 63 [xmlComment, 0]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 63 [xmlComment, 0]":true, + "extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 64 [xmlComment, 4]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 64 [xmlComment, 4]":true, + "extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 65 [processingInstruction, 0]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 65 [processingInstruction, 0]":true, + "extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 66 [processingInstruction, 5]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 66 [processingInstruction, 5]":true, + "extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 67 [processingInstruction, 9]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 67 [processingInstruction, 9]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 68 [detachedTextNode, 0]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 69 [detachedTextNode, 8]":true, + "extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 70 [detachedForeignTextNode, 0]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 70 [detachedForeignTextNode, 0]":true, + "extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 71 [detachedForeignTextNode, 8]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 71 [detachedForeignTextNode, 8]":true, + "extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 72 [detachedXmlTextNode, 0]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 72 [detachedXmlTextNode, 0]":true, + "extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 73 [detachedXmlTextNode, 8]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 73 [detachedXmlTextNode, 8]":true, + "extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 75 [detachedComment, 3]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 76 [detachedComment, 5]":true, + "extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 77 [detachedForeignComment, 0]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 77 [detachedForeignComment, 0]":true, + "extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 78 [detachedForeignComment, 4]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 78 [detachedForeignComment, 4]":true, + "extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 79 [detachedXmlComment, 2]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 79 [detachedXmlComment, 2]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 80 [docfrag, 0]":true, + "extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 81 [foreignDocfrag, 0]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 81 [foreignDocfrag, 0]":true, + "extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 82 [xmlDocfrag, 0]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 82 [xmlDocfrag, 0]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 83 [doctype, 0]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 84 [doctype, -17]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 85 [doctype, 1]":true, + "extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 86 [foreignDoctype, 0]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 86 [foreignDoctype, 0]":true, + "extend() forwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 87 [xmlDoctype, 0]":true, + "extend() backwards with range 55 [detachedXmlComment, 2, detachedXmlComment, 6] and point 87 [xmlDoctype, 0]":true, + "extend() with range 56 [docfrag, 0, docfrag, 0] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() with range 56 [docfrag, 0, docfrag, 0] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() with range 56 [docfrag, 0, docfrag, 0] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() with range 56 [docfrag, 0, docfrag, 0] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() with range 56 [docfrag, 0, docfrag, 0] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() with range 56 [docfrag, 0, docfrag, 0] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() with range 56 [docfrag, 0, docfrag, 0] and point 33 [foreignDoc.head, 0]":true, + "extend() with range 56 [docfrag, 0, docfrag, 0] and point 34 [foreignDoc.body, 1]":true, + "extend() with range 56 [docfrag, 0, docfrag, 0] and point 54 [foreignDoc, 0]":true, + "extend() with range 56 [docfrag, 0, docfrag, 0] and point 55 [foreignDoc, 1]":true, + "extend() with range 56 [docfrag, 0, docfrag, 0] and point 56 [foreignComment, 2]":true, + "extend() with range 56 [docfrag, 0, docfrag, 0] and point 57 [foreignTextNode, 0]":true, + "extend() with range 56 [docfrag, 0, docfrag, 0] and point 58 [foreignTextNode, 36]":true, + "extend() with range 56 [docfrag, 0, docfrag, 0] and point 59 [xmlDoc, -1]":true, + "extend() with range 56 [docfrag, 0, docfrag, 0] and point 60 [xmlDoc, 0]":true, + "extend() with range 56 [docfrag, 0, docfrag, 0] and point 61 [xmlDoc, 1]":true, + "extend() with range 56 [docfrag, 0, docfrag, 0] and point 62 [xmlDoc, 5]":true, + "extend() with range 56 [docfrag, 0, docfrag, 0] and point 63 [xmlComment, 0]":true, + "extend() with range 56 [docfrag, 0, docfrag, 0] and point 64 [xmlComment, 4]":true, + "extend() with range 56 [docfrag, 0, docfrag, 0] and point 65 [processingInstruction, 0]":true, + "extend() with range 56 [docfrag, 0, docfrag, 0] and point 66 [processingInstruction, 5]":true, + "extend() with range 56 [docfrag, 0, docfrag, 0] and point 67 [processingInstruction, 9]":true, + "extend() with range 56 [docfrag, 0, docfrag, 0] and point 70 [detachedForeignTextNode, 0]":true, + "extend() with range 56 [docfrag, 0, docfrag, 0] and point 71 [detachedForeignTextNode, 8]":true, + "extend() with range 56 [docfrag, 0, docfrag, 0] and point 72 [detachedXmlTextNode, 0]":true, + "extend() with range 56 [docfrag, 0, docfrag, 0] and point 73 [detachedXmlTextNode, 8]":true, + "extend() with range 56 [docfrag, 0, docfrag, 0] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() with range 56 [docfrag, 0, docfrag, 0] and point 77 [detachedForeignComment, 0]":true, + "extend() with range 56 [docfrag, 0, docfrag, 0] and point 78 [detachedForeignComment, 4]":true, + "extend() with range 56 [docfrag, 0, docfrag, 0] and point 79 [detachedXmlComment, 2]":true, + "extend() with range 56 [docfrag, 0, docfrag, 0] and point 81 [foreignDocfrag, 0]":true, + "extend() with range 56 [docfrag, 0, docfrag, 0] and point 82 [xmlDocfrag, 0]":true, + "extend() with range 56 [docfrag, 0, docfrag, 0] and point 86 [foreignDoctype, 0]":true, + "extend() with range 56 [docfrag, 0, docfrag, 0] and point 87 [xmlDoctype, 0]":true, + "extend() with range 57 [foreignDocfrag, 0, foreignDocfrag, 0] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() with range 57 [foreignDocfrag, 0, foreignDocfrag, 0] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() with range 57 [foreignDocfrag, 0, foreignDocfrag, 0] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() with range 57 [foreignDocfrag, 0, foreignDocfrag, 0] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() with range 57 [foreignDocfrag, 0, foreignDocfrag, 0] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() with range 57 [foreignDocfrag, 0, foreignDocfrag, 0] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() with range 57 [foreignDocfrag, 0, foreignDocfrag, 0] and point 33 [foreignDoc.head, 0]":true, + "extend() with range 57 [foreignDocfrag, 0, foreignDocfrag, 0] and point 34 [foreignDoc.body, 1]":true, + "extend() with range 57 [foreignDocfrag, 0, foreignDocfrag, 0] and point 54 [foreignDoc, 0]":true, + "extend() with range 57 [foreignDocfrag, 0, foreignDocfrag, 0] and point 55 [foreignDoc, 1]":true, + "extend() with range 57 [foreignDocfrag, 0, foreignDocfrag, 0] and point 56 [foreignComment, 2]":true, + "extend() with range 57 [foreignDocfrag, 0, foreignDocfrag, 0] and point 57 [foreignTextNode, 0]":true, + "extend() with range 57 [foreignDocfrag, 0, foreignDocfrag, 0] and point 58 [foreignTextNode, 36]":true, + "extend() with range 57 [foreignDocfrag, 0, foreignDocfrag, 0] and point 59 [xmlDoc, -1]":true, + "extend() with range 57 [foreignDocfrag, 0, foreignDocfrag, 0] and point 60 [xmlDoc, 0]":true, + "extend() with range 57 [foreignDocfrag, 0, foreignDocfrag, 0] and point 61 [xmlDoc, 1]":true, + "extend() with range 57 [foreignDocfrag, 0, foreignDocfrag, 0] and point 62 [xmlDoc, 5]":true, + "extend() with range 57 [foreignDocfrag, 0, foreignDocfrag, 0] and point 63 [xmlComment, 0]":true, + "extend() with range 57 [foreignDocfrag, 0, foreignDocfrag, 0] and point 64 [xmlComment, 4]":true, + "extend() with range 57 [foreignDocfrag, 0, foreignDocfrag, 0] and point 65 [processingInstruction, 0]":true, + "extend() with range 57 [foreignDocfrag, 0, foreignDocfrag, 0] and point 66 [processingInstruction, 5]":true, + "extend() with range 57 [foreignDocfrag, 0, foreignDocfrag, 0] and point 67 [processingInstruction, 9]":true, + "extend() with range 57 [foreignDocfrag, 0, foreignDocfrag, 0] and point 70 [detachedForeignTextNode, 0]":true, + "extend() with range 57 [foreignDocfrag, 0, foreignDocfrag, 0] and point 71 [detachedForeignTextNode, 8]":true, + "extend() with range 57 [foreignDocfrag, 0, foreignDocfrag, 0] and point 72 [detachedXmlTextNode, 0]":true, + "extend() with range 57 [foreignDocfrag, 0, foreignDocfrag, 0] and point 73 [detachedXmlTextNode, 8]":true, + "extend() with range 57 [foreignDocfrag, 0, foreignDocfrag, 0] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() with range 57 [foreignDocfrag, 0, foreignDocfrag, 0] and point 77 [detachedForeignComment, 0]":true, + "extend() with range 57 [foreignDocfrag, 0, foreignDocfrag, 0] and point 78 [detachedForeignComment, 4]":true, + "extend() with range 57 [foreignDocfrag, 0, foreignDocfrag, 0] and point 79 [detachedXmlComment, 2]":true, + "extend() with range 57 [foreignDocfrag, 0, foreignDocfrag, 0] and point 81 [foreignDocfrag, 0]":true, + "extend() with range 57 [foreignDocfrag, 0, foreignDocfrag, 0] and point 82 [xmlDocfrag, 0]":true, + "extend() with range 57 [foreignDocfrag, 0, foreignDocfrag, 0] and point 86 [foreignDoctype, 0]":true, + "extend() with range 57 [foreignDocfrag, 0, foreignDocfrag, 0] and point 87 [xmlDoctype, 0]":true, + "extend() with range 58 [xmlDocfrag, 0, xmlDocfrag, 0] and point 20 [foreignPara1.firstChild, 0]":true, + "extend() with range 58 [xmlDocfrag, 0, xmlDocfrag, 0] and point 21 [foreignPara1.firstChild, 1]":true, + "extend() with range 58 [xmlDocfrag, 0, xmlDocfrag, 0] and point 22 [foreignPara1.firstChild, 8]":true, + "extend() with range 58 [xmlDocfrag, 0, xmlDocfrag, 0] and point 23 [foreignPara1.firstChild, 9]":true, + "extend() with range 58 [xmlDocfrag, 0, xmlDocfrag, 0] and point 31 [foreignDoc.documentElement, 0]":true, + "extend() with range 58 [xmlDocfrag, 0, xmlDocfrag, 0] and point 32 [foreignDoc.documentElement, 1]":true, + "extend() with range 58 [xmlDocfrag, 0, xmlDocfrag, 0] and point 33 [foreignDoc.head, 0]":true, + "extend() with range 58 [xmlDocfrag, 0, xmlDocfrag, 0] and point 34 [foreignDoc.body, 1]":true, + "extend() with range 58 [xmlDocfrag, 0, xmlDocfrag, 0] and point 54 [foreignDoc, 0]":true, + "extend() with range 58 [xmlDocfrag, 0, xmlDocfrag, 0] and point 55 [foreignDoc, 1]":true, + "extend() with range 58 [xmlDocfrag, 0, xmlDocfrag, 0] and point 56 [foreignComment, 2]":true, + "extend() with range 58 [xmlDocfrag, 0, xmlDocfrag, 0] and point 57 [foreignTextNode, 0]":true, + "extend() with range 58 [xmlDocfrag, 0, xmlDocfrag, 0] and point 58 [foreignTextNode, 36]":true, + "extend() with range 58 [xmlDocfrag, 0, xmlDocfrag, 0] and point 59 [xmlDoc, -1]":true, + "extend() with range 58 [xmlDocfrag, 0, xmlDocfrag, 0] and point 60 [xmlDoc, 0]":true, + "extend() with range 58 [xmlDocfrag, 0, xmlDocfrag, 0] and point 61 [xmlDoc, 1]":true, + "extend() with range 58 [xmlDocfrag, 0, xmlDocfrag, 0] and point 62 [xmlDoc, 5]":true, + "extend() with range 58 [xmlDocfrag, 0, xmlDocfrag, 0] and point 63 [xmlComment, 0]":true, + "extend() with range 58 [xmlDocfrag, 0, xmlDocfrag, 0] and point 64 [xmlComment, 4]":true, + "extend() with range 58 [xmlDocfrag, 0, xmlDocfrag, 0] and point 65 [processingInstruction, 0]":true, + "extend() with range 58 [xmlDocfrag, 0, xmlDocfrag, 0] and point 66 [processingInstruction, 5]":true, + "extend() with range 58 [xmlDocfrag, 0, xmlDocfrag, 0] and point 67 [processingInstruction, 9]":true, + "extend() with range 58 [xmlDocfrag, 0, xmlDocfrag, 0] and point 70 [detachedForeignTextNode, 0]":true, + "extend() with range 58 [xmlDocfrag, 0, xmlDocfrag, 0] and point 71 [detachedForeignTextNode, 8]":true, + "extend() with range 58 [xmlDocfrag, 0, xmlDocfrag, 0] and point 72 [detachedXmlTextNode, 0]":true, + "extend() with range 58 [xmlDocfrag, 0, xmlDocfrag, 0] and point 73 [detachedXmlTextNode, 8]":true, + "extend() with range 58 [xmlDocfrag, 0, xmlDocfrag, 0] and point 74 [detachedProcessingInstruction, 12]":true, + "extend() with range 58 [xmlDocfrag, 0, xmlDocfrag, 0] and point 77 [detachedForeignComment, 0]":true, + "extend() with range 58 [xmlDocfrag, 0, xmlDocfrag, 0] and point 78 [detachedForeignComment, 4]":true, + "extend() with range 58 [xmlDocfrag, 0, xmlDocfrag, 0] and point 79 [detachedXmlComment, 2]":true, + "extend() with range 58 [xmlDocfrag, 0, xmlDocfrag, 0] and point 81 [foreignDocfrag, 0]":true, + "extend() with range 58 [xmlDocfrag, 0, xmlDocfrag, 0] and point 82 [xmlDocfrag, 0]":true, + "extend() with range 58 [xmlDocfrag, 0, xmlDocfrag, 0] and point 86 [foreignDoctype, 0]":true, + "extend() with range 58 [xmlDocfrag, 0, xmlDocfrag, 0] and point 87 [xmlDoctype, 0]":true +} diff --git a/dom/imptests/failures/editing/selecttest/test_removeAllRanges.html.json b/dom/imptests/failures/editing/selecttest/test_removeAllRanges.html.json new file mode 100644 index 00000000000..421796e25c8 --- /dev/null +++ b/dom/imptests/failures/editing/selecttest/test_removeAllRanges.html.json @@ -0,0 +1,23 @@ +{ + "Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0] backwards":true, + "Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1] backwards":true, + "Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8] backwards":true, + "Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1] backwards":true, + "Range 21 [foreignDoc.head, 1, foreignDoc.head, 1] backwards":true, + "Range 22 [foreignDoc.body, 0, foreignDoc.body, 0] backwards":true, + "Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0] backwards":true, + "Range 41 [foreignDoc, 0, foreignDoc, 0] backwards":true, + "Range 42 [foreignDoc, 1, foreignComment, 2] backwards":true, + "Range 43 [foreignDoc.body, 0, foreignTextNode, 36] backwards":true, + "Range 44 [xmlDoc, 0, xmlDoc, 0] backwards":true, + "Range 45 [xmlDoc, 1, xmlComment, 0] backwards":true, + "Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7] backwards":true, + "Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8] backwards":true, + "Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7] backwards":true, + "Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8] backwards":true, + "Range 53 [detachedForeignComment, 0, detachedForeignComment, 1] backwards":true, + "Range 54 [detachedForeignComment, 4, detachedForeignComment, 4] backwards":true, + "Range 55 [detachedXmlComment, 2, detachedXmlComment, 6] backwards":true, + "Range 57 [foreignDocfrag, 0, foreignDocfrag, 0] backwards":true, + "Range 58 [xmlDocfrag, 0, xmlDocfrag, 0] backwards":true +} diff --git a/dom/imptests/failures/editing/selecttest/test_selectAllChildren.html.json b/dom/imptests/failures/editing/selecttest/test_selectAllChildren.html.json new file mode 100644 index 00000000000..b22cdea858d --- /dev/null +++ b/dom/imptests/failures/editing/selecttest/test_selectAllChildren.html.json @@ -0,0 +1,1241 @@ +{ + "Range 0 [], node 4 foreignPara1":true, + "Range 0 [], node 5 foreignPara1.firstChild":true, + "Range 0 [], node 14 foreignDoc":true, + "Range 0 [], node 15 foreignPara2":true, + "Range 0 [], node 16 xmlDoc":true, + "Range 0 [], node 17 xmlElement":true, + "Range 0 [], node 18 detachedXmlElement":true, + "Range 0 [], node 20 foreignTextNode":true, + "Range 0 [], node 21 detachedForeignTextNode":true, + "Range 0 [], node 22 xmlTextNode":true, + "Range 0 [], node 23 detachedXmlTextNode":true, + "Range 0 [], node 24 processingInstruction":true, + "Range 0 [], node 25 detachedProcessingInstruction":true, + "Range 0 [], node 28 foreignComment":true, + "Range 0 [], node 29 detachedForeignComment":true, + "Range 0 [], node 30 xmlComment":true, + "Range 0 [], node 31 detachedXmlComment":true, + "Range 0 [], node 33 foreignDocfrag":true, + "Range 0 [], node 34 xmlDocfrag":true, + "Range 0 [], node 36 foreignDoctype":true, + "Range 0 [], node 37 xmlDoctype":true, + "Range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0], node 4 foreignPara1":true, + "Range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0], node 5 foreignPara1.firstChild":true, + "Range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0], node 14 foreignDoc":true, + "Range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0], node 15 foreignPara2":true, + "Range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0], node 16 xmlDoc":true, + "Range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0], node 17 xmlElement":true, + "Range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0], node 18 detachedXmlElement":true, + "Range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0], node 20 foreignTextNode":true, + "Range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0], node 21 detachedForeignTextNode":true, + "Range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0], node 22 xmlTextNode":true, + "Range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0], node 23 detachedXmlTextNode":true, + "Range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0], node 24 processingInstruction":true, + "Range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0], node 25 detachedProcessingInstruction":true, + "Range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0], node 28 foreignComment":true, + "Range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0], node 29 detachedForeignComment":true, + "Range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0], node 30 xmlComment":true, + "Range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0], node 31 detachedXmlComment":true, + "Range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0], node 33 foreignDocfrag":true, + "Range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0], node 34 xmlDocfrag":true, + "Range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0], node 36 foreignDoctype":true, + "Range 1 [paras[0].firstChild, 0, paras[0].firstChild, 0], node 37 xmlDoctype":true, + "Range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1], node 4 foreignPara1":true, + "Range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1], node 5 foreignPara1.firstChild":true, + "Range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1], node 14 foreignDoc":true, + "Range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1], node 15 foreignPara2":true, + "Range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1], node 16 xmlDoc":true, + "Range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1], node 17 xmlElement":true, + "Range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1], node 18 detachedXmlElement":true, + "Range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1], node 20 foreignTextNode":true, + "Range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1], node 21 detachedForeignTextNode":true, + "Range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1], node 22 xmlTextNode":true, + "Range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1], node 23 detachedXmlTextNode":true, + "Range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1], node 24 processingInstruction":true, + "Range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1], node 25 detachedProcessingInstruction":true, + "Range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1], node 28 foreignComment":true, + "Range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1], node 29 detachedForeignComment":true, + "Range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1], node 30 xmlComment":true, + "Range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1], node 31 detachedXmlComment":true, + "Range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1], node 33 foreignDocfrag":true, + "Range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1], node 34 xmlDocfrag":true, + "Range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1], node 36 foreignDoctype":true, + "Range 2 [paras[0].firstChild, 0, paras[0].firstChild, 1], node 37 xmlDoctype":true, + "Range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8], node 4 foreignPara1":true, + "Range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8], node 5 foreignPara1.firstChild":true, + "Range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8], node 14 foreignDoc":true, + "Range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8], node 15 foreignPara2":true, + "Range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8], node 16 xmlDoc":true, + "Range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8], node 17 xmlElement":true, + "Range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8], node 18 detachedXmlElement":true, + "Range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8], node 20 foreignTextNode":true, + "Range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8], node 21 detachedForeignTextNode":true, + "Range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8], node 22 xmlTextNode":true, + "Range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8], node 23 detachedXmlTextNode":true, + "Range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8], node 24 processingInstruction":true, + "Range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8], node 25 detachedProcessingInstruction":true, + "Range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8], node 28 foreignComment":true, + "Range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8], node 29 detachedForeignComment":true, + "Range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8], node 30 xmlComment":true, + "Range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8], node 31 detachedXmlComment":true, + "Range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8], node 33 foreignDocfrag":true, + "Range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8], node 34 xmlDocfrag":true, + "Range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8], node 36 foreignDoctype":true, + "Range 3 [paras[0].firstChild, 2, paras[0].firstChild, 8], node 37 xmlDoctype":true, + "Range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9], node 4 foreignPara1":true, + "Range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9], node 5 foreignPara1.firstChild":true, + "Range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9], node 14 foreignDoc":true, + "Range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9], node 15 foreignPara2":true, + "Range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9], node 16 xmlDoc":true, + "Range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9], node 17 xmlElement":true, + "Range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9], node 18 detachedXmlElement":true, + "Range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9], node 20 foreignTextNode":true, + "Range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9], node 21 detachedForeignTextNode":true, + "Range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9], node 22 xmlTextNode":true, + "Range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9], node 23 detachedXmlTextNode":true, + "Range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9], node 24 processingInstruction":true, + "Range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9], node 25 detachedProcessingInstruction":true, + "Range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9], node 28 foreignComment":true, + "Range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9], node 29 detachedForeignComment":true, + "Range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9], node 30 xmlComment":true, + "Range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9], node 31 detachedXmlComment":true, + "Range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9], node 33 foreignDocfrag":true, + "Range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9], node 34 xmlDocfrag":true, + "Range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9], node 36 foreignDoctype":true, + "Range 4 [paras[0].firstChild, 2, paras[0].firstChild, 9], node 37 xmlDoctype":true, + "Range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0], node 4 foreignPara1":true, + "Range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0], node 5 foreignPara1.firstChild":true, + "Range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0], node 14 foreignDoc":true, + "Range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0], node 15 foreignPara2":true, + "Range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0], node 16 xmlDoc":true, + "Range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0], node 17 xmlElement":true, + "Range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0], node 18 detachedXmlElement":true, + "Range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0], node 20 foreignTextNode":true, + "Range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0], node 21 detachedForeignTextNode":true, + "Range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0], node 22 xmlTextNode":true, + "Range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0], node 23 detachedXmlTextNode":true, + "Range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0], node 24 processingInstruction":true, + "Range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0], node 25 detachedProcessingInstruction":true, + "Range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0], node 28 foreignComment":true, + "Range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0], node 29 detachedForeignComment":true, + "Range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0], node 30 xmlComment":true, + "Range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0], node 31 detachedXmlComment":true, + "Range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0], node 33 foreignDocfrag":true, + "Range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0], node 34 xmlDocfrag":true, + "Range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0], node 36 foreignDoctype":true, + "Range 5 [paras[1].firstChild, 0, paras[1].firstChild, 0], node 37 xmlDoctype":true, + "Range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1], node 4 foreignPara1":true, + "Range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1], node 5 foreignPara1.firstChild":true, + "Range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1], node 14 foreignDoc":true, + "Range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1], node 15 foreignPara2":true, + "Range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1], node 16 xmlDoc":true, + "Range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1], node 17 xmlElement":true, + "Range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1], node 18 detachedXmlElement":true, + "Range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1], node 20 foreignTextNode":true, + "Range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1], node 21 detachedForeignTextNode":true, + "Range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1], node 22 xmlTextNode":true, + "Range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1], node 23 detachedXmlTextNode":true, + "Range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1], node 24 processingInstruction":true, + "Range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1], node 25 detachedProcessingInstruction":true, + "Range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1], node 28 foreignComment":true, + "Range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1], node 29 detachedForeignComment":true, + "Range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1], node 30 xmlComment":true, + "Range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1], node 31 detachedXmlComment":true, + "Range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1], node 33 foreignDocfrag":true, + "Range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1], node 34 xmlDocfrag":true, + "Range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1], node 36 foreignDoctype":true, + "Range 6 [paras[1].firstChild, 0, paras[1].firstChild, 1], node 37 xmlDoctype":true, + "Range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8], node 4 foreignPara1":true, + "Range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8], node 5 foreignPara1.firstChild":true, + "Range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8], node 14 foreignDoc":true, + "Range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8], node 15 foreignPara2":true, + "Range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8], node 16 xmlDoc":true, + "Range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8], node 17 xmlElement":true, + "Range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8], node 18 detachedXmlElement":true, + "Range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8], node 20 foreignTextNode":true, + "Range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8], node 21 detachedForeignTextNode":true, + "Range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8], node 22 xmlTextNode":true, + "Range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8], node 23 detachedXmlTextNode":true, + "Range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8], node 24 processingInstruction":true, + "Range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8], node 25 detachedProcessingInstruction":true, + "Range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8], node 28 foreignComment":true, + "Range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8], node 29 detachedForeignComment":true, + "Range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8], node 30 xmlComment":true, + "Range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8], node 31 detachedXmlComment":true, + "Range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8], node 33 foreignDocfrag":true, + "Range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8], node 34 xmlDocfrag":true, + "Range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8], node 36 foreignDoctype":true, + "Range 7 [paras[1].firstChild, 2, paras[1].firstChild, 8], node 37 xmlDoctype":true, + "Range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9], node 4 foreignPara1":true, + "Range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9], node 5 foreignPara1.firstChild":true, + "Range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9], node 14 foreignDoc":true, + "Range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9], node 15 foreignPara2":true, + "Range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9], node 16 xmlDoc":true, + "Range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9], node 17 xmlElement":true, + "Range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9], node 18 detachedXmlElement":true, + "Range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9], node 20 foreignTextNode":true, + "Range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9], node 21 detachedForeignTextNode":true, + "Range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9], node 22 xmlTextNode":true, + "Range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9], node 23 detachedXmlTextNode":true, + "Range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9], node 24 processingInstruction":true, + "Range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9], node 25 detachedProcessingInstruction":true, + "Range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9], node 28 foreignComment":true, + "Range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9], node 29 detachedForeignComment":true, + "Range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9], node 30 xmlComment":true, + "Range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9], node 31 detachedXmlComment":true, + "Range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9], node 33 foreignDocfrag":true, + "Range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9], node 34 xmlDocfrag":true, + "Range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9], node 36 foreignDoctype":true, + "Range 8 [paras[1].firstChild, 2, paras[1].firstChild, 9], node 37 xmlDoctype":true, + "Range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node 4 foreignPara1":true, + "Range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node 5 foreignPara1.firstChild":true, + "Range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node 14 foreignDoc":true, + "Range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node 15 foreignPara2":true, + "Range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node 16 xmlDoc":true, + "Range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node 17 xmlElement":true, + "Range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node 18 detachedXmlElement":true, + "Range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node 20 foreignTextNode":true, + "Range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node 21 detachedForeignTextNode":true, + "Range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node 22 xmlTextNode":true, + "Range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node 23 detachedXmlTextNode":true, + "Range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node 24 processingInstruction":true, + "Range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node 25 detachedProcessingInstruction":true, + "Range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node 28 foreignComment":true, + "Range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node 29 detachedForeignComment":true, + "Range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node 30 xmlComment":true, + "Range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node 31 detachedXmlComment":true, + "Range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node 33 foreignDocfrag":true, + "Range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node 34 xmlDocfrag":true, + "Range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node 36 foreignDoctype":true, + "Range 9 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node 37 xmlDoctype":true, + "Range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1], node 4 foreignPara1":true, + "Range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1], node 5 foreignPara1.firstChild":true, + "Range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1], node 14 foreignDoc":true, + "Range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1], node 15 foreignPara2":true, + "Range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1], node 16 xmlDoc":true, + "Range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1], node 17 xmlElement":true, + "Range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1], node 18 detachedXmlElement":true, + "Range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1], node 20 foreignTextNode":true, + "Range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1], node 21 detachedForeignTextNode":true, + "Range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1], node 22 xmlTextNode":true, + "Range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1], node 23 detachedXmlTextNode":true, + "Range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1], node 24 processingInstruction":true, + "Range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1], node 25 detachedProcessingInstruction":true, + "Range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1], node 28 foreignComment":true, + "Range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1], node 29 detachedForeignComment":true, + "Range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1], node 30 xmlComment":true, + "Range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1], node 31 detachedXmlComment":true, + "Range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1], node 33 foreignDocfrag":true, + "Range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1], node 34 xmlDocfrag":true, + "Range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1], node 36 foreignDoctype":true, + "Range 10 [detachedPara1.firstChild, 0, detachedPara1.firstChild, 1], node 37 xmlDoctype":true, + "Range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node 4 foreignPara1":true, + "Range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node 5 foreignPara1.firstChild":true, + "Range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node 14 foreignDoc":true, + "Range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node 15 foreignPara2":true, + "Range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node 16 xmlDoc":true, + "Range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node 17 xmlElement":true, + "Range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node 18 detachedXmlElement":true, + "Range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node 20 foreignTextNode":true, + "Range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node 21 detachedForeignTextNode":true, + "Range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node 22 xmlTextNode":true, + "Range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node 23 detachedXmlTextNode":true, + "Range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node 24 processingInstruction":true, + "Range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node 25 detachedProcessingInstruction":true, + "Range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node 28 foreignComment":true, + "Range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node 29 detachedForeignComment":true, + "Range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node 30 xmlComment":true, + "Range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node 31 detachedXmlComment":true, + "Range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node 33 foreignDocfrag":true, + "Range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node 34 xmlDocfrag":true, + "Range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node 36 foreignDoctype":true, + "Range 11 [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node 37 xmlDoctype":true, + "Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node 4 foreignPara1":true, + "Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node 5 foreignPara1.firstChild":true, + "Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node 14 foreignDoc":true, + "Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node 15 foreignPara2":true, + "Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node 16 xmlDoc":true, + "Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node 17 xmlElement":true, + "Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node 18 detachedXmlElement":true, + "Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node 20 foreignTextNode":true, + "Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node 21 detachedForeignTextNode":true, + "Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node 22 xmlTextNode":true, + "Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node 23 detachedXmlTextNode":true, + "Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node 24 processingInstruction":true, + "Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node 25 detachedProcessingInstruction":true, + "Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node 28 foreignComment":true, + "Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node 29 detachedForeignComment":true, + "Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node 30 xmlComment":true, + "Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node 31 detachedXmlComment":true, + "Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node 33 foreignDocfrag":true, + "Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node 34 xmlDocfrag":true, + "Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node 36 foreignDoctype":true, + "Range 12 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node 37 xmlDoctype":true, + "Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1], node 4 foreignPara1":true, + "Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1], node 5 foreignPara1.firstChild":true, + "Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1], node 14 foreignDoc":true, + "Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1], node 15 foreignPara2":true, + "Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1], node 16 xmlDoc":true, + "Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1], node 17 xmlElement":true, + "Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1], node 18 detachedXmlElement":true, + "Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1], node 20 foreignTextNode":true, + "Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1], node 21 detachedForeignTextNode":true, + "Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1], node 22 xmlTextNode":true, + "Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1], node 23 detachedXmlTextNode":true, + "Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1], node 24 processingInstruction":true, + "Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1], node 25 detachedProcessingInstruction":true, + "Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1], node 28 foreignComment":true, + "Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1], node 29 detachedForeignComment":true, + "Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1], node 30 xmlComment":true, + "Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1], node 31 detachedXmlComment":true, + "Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1], node 33 foreignDocfrag":true, + "Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1], node 34 xmlDocfrag":true, + "Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1], node 36 foreignDoctype":true, + "Range 13 [foreignPara1.firstChild, 0, foreignPara1.firstChild, 1], node 37 xmlDoctype":true, + "Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node 4 foreignPara1":true, + "Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node 5 foreignPara1.firstChild":true, + "Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node 14 foreignDoc":true, + "Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node 15 foreignPara2":true, + "Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node 16 xmlDoc":true, + "Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node 17 xmlElement":true, + "Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node 18 detachedXmlElement":true, + "Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node 20 foreignTextNode":true, + "Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node 21 detachedForeignTextNode":true, + "Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node 22 xmlTextNode":true, + "Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node 23 detachedXmlTextNode":true, + "Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node 24 processingInstruction":true, + "Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node 25 detachedProcessingInstruction":true, + "Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node 28 foreignComment":true, + "Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node 29 detachedForeignComment":true, + "Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node 30 xmlComment":true, + "Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node 31 detachedXmlComment":true, + "Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node 33 foreignDocfrag":true, + "Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node 34 xmlDocfrag":true, + "Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node 36 foreignDoctype":true, + "Range 14 [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node 37 xmlDoctype":true, + "Range 15 [document.documentElement, 0, document.documentElement, 1], node 4 foreignPara1":true, + "Range 15 [document.documentElement, 0, document.documentElement, 1], node 5 foreignPara1.firstChild":true, + "Range 15 [document.documentElement, 0, document.documentElement, 1], node 14 foreignDoc":true, + "Range 15 [document.documentElement, 0, document.documentElement, 1], node 15 foreignPara2":true, + "Range 15 [document.documentElement, 0, document.documentElement, 1], node 16 xmlDoc":true, + "Range 15 [document.documentElement, 0, document.documentElement, 1], node 17 xmlElement":true, + "Range 15 [document.documentElement, 0, document.documentElement, 1], node 18 detachedXmlElement":true, + "Range 15 [document.documentElement, 0, document.documentElement, 1], node 20 foreignTextNode":true, + "Range 15 [document.documentElement, 0, document.documentElement, 1], node 21 detachedForeignTextNode":true, + "Range 15 [document.documentElement, 0, document.documentElement, 1], node 22 xmlTextNode":true, + "Range 15 [document.documentElement, 0, document.documentElement, 1], node 23 detachedXmlTextNode":true, + "Range 15 [document.documentElement, 0, document.documentElement, 1], node 24 processingInstruction":true, + "Range 15 [document.documentElement, 0, document.documentElement, 1], node 25 detachedProcessingInstruction":true, + "Range 15 [document.documentElement, 0, document.documentElement, 1], node 28 foreignComment":true, + "Range 15 [document.documentElement, 0, document.documentElement, 1], node 29 detachedForeignComment":true, + "Range 15 [document.documentElement, 0, document.documentElement, 1], node 30 xmlComment":true, + "Range 15 [document.documentElement, 0, document.documentElement, 1], node 31 detachedXmlComment":true, + "Range 15 [document.documentElement, 0, document.documentElement, 1], node 33 foreignDocfrag":true, + "Range 15 [document.documentElement, 0, document.documentElement, 1], node 34 xmlDocfrag":true, + "Range 15 [document.documentElement, 0, document.documentElement, 1], node 36 foreignDoctype":true, + "Range 15 [document.documentElement, 0, document.documentElement, 1], node 37 xmlDoctype":true, + "Range 16 [document.documentElement, 0, document.documentElement, 2], node 4 foreignPara1":true, + "Range 16 [document.documentElement, 0, document.documentElement, 2], node 5 foreignPara1.firstChild":true, + "Range 16 [document.documentElement, 0, document.documentElement, 2], node 14 foreignDoc":true, + "Range 16 [document.documentElement, 0, document.documentElement, 2], node 15 foreignPara2":true, + "Range 16 [document.documentElement, 0, document.documentElement, 2], node 16 xmlDoc":true, + "Range 16 [document.documentElement, 0, document.documentElement, 2], node 17 xmlElement":true, + "Range 16 [document.documentElement, 0, document.documentElement, 2], node 18 detachedXmlElement":true, + "Range 16 [document.documentElement, 0, document.documentElement, 2], node 20 foreignTextNode":true, + "Range 16 [document.documentElement, 0, document.documentElement, 2], node 21 detachedForeignTextNode":true, + "Range 16 [document.documentElement, 0, document.documentElement, 2], node 22 xmlTextNode":true, + "Range 16 [document.documentElement, 0, document.documentElement, 2], node 23 detachedXmlTextNode":true, + "Range 16 [document.documentElement, 0, document.documentElement, 2], node 24 processingInstruction":true, + "Range 16 [document.documentElement, 0, document.documentElement, 2], node 25 detachedProcessingInstruction":true, + "Range 16 [document.documentElement, 0, document.documentElement, 2], node 28 foreignComment":true, + "Range 16 [document.documentElement, 0, document.documentElement, 2], node 29 detachedForeignComment":true, + "Range 16 [document.documentElement, 0, document.documentElement, 2], node 30 xmlComment":true, + "Range 16 [document.documentElement, 0, document.documentElement, 2], node 31 detachedXmlComment":true, + "Range 16 [document.documentElement, 0, document.documentElement, 2], node 33 foreignDocfrag":true, + "Range 16 [document.documentElement, 0, document.documentElement, 2], node 34 xmlDocfrag":true, + "Range 16 [document.documentElement, 0, document.documentElement, 2], node 36 foreignDoctype":true, + "Range 16 [document.documentElement, 0, document.documentElement, 2], node 37 xmlDoctype":true, + "Range 17 [document.documentElement, 1, document.documentElement, 2], node 4 foreignPara1":true, + "Range 17 [document.documentElement, 1, document.documentElement, 2], node 5 foreignPara1.firstChild":true, + "Range 17 [document.documentElement, 1, document.documentElement, 2], node 14 foreignDoc":true, + "Range 17 [document.documentElement, 1, document.documentElement, 2], node 15 foreignPara2":true, + "Range 17 [document.documentElement, 1, document.documentElement, 2], node 16 xmlDoc":true, + "Range 17 [document.documentElement, 1, document.documentElement, 2], node 17 xmlElement":true, + "Range 17 [document.documentElement, 1, document.documentElement, 2], node 18 detachedXmlElement":true, + "Range 17 [document.documentElement, 1, document.documentElement, 2], node 20 foreignTextNode":true, + "Range 17 [document.documentElement, 1, document.documentElement, 2], node 21 detachedForeignTextNode":true, + "Range 17 [document.documentElement, 1, document.documentElement, 2], node 22 xmlTextNode":true, + "Range 17 [document.documentElement, 1, document.documentElement, 2], node 23 detachedXmlTextNode":true, + "Range 17 [document.documentElement, 1, document.documentElement, 2], node 24 processingInstruction":true, + "Range 17 [document.documentElement, 1, document.documentElement, 2], node 25 detachedProcessingInstruction":true, + "Range 17 [document.documentElement, 1, document.documentElement, 2], node 28 foreignComment":true, + "Range 17 [document.documentElement, 1, document.documentElement, 2], node 29 detachedForeignComment":true, + "Range 17 [document.documentElement, 1, document.documentElement, 2], node 30 xmlComment":true, + "Range 17 [document.documentElement, 1, document.documentElement, 2], node 31 detachedXmlComment":true, + "Range 17 [document.documentElement, 1, document.documentElement, 2], node 33 foreignDocfrag":true, + "Range 17 [document.documentElement, 1, document.documentElement, 2], node 34 xmlDocfrag":true, + "Range 17 [document.documentElement, 1, document.documentElement, 2], node 36 foreignDoctype":true, + "Range 17 [document.documentElement, 1, document.documentElement, 2], node 37 xmlDoctype":true, + "Range 18 [document.head, 1, document.head, 1], node 4 foreignPara1":true, + "Range 18 [document.head, 1, document.head, 1], node 5 foreignPara1.firstChild":true, + "Range 18 [document.head, 1, document.head, 1], node 14 foreignDoc":true, + "Range 18 [document.head, 1, document.head, 1], node 15 foreignPara2":true, + "Range 18 [document.head, 1, document.head, 1], node 16 xmlDoc":true, + "Range 18 [document.head, 1, document.head, 1], node 17 xmlElement":true, + "Range 18 [document.head, 1, document.head, 1], node 18 detachedXmlElement":true, + "Range 18 [document.head, 1, document.head, 1], node 20 foreignTextNode":true, + "Range 18 [document.head, 1, document.head, 1], node 21 detachedForeignTextNode":true, + "Range 18 [document.head, 1, document.head, 1], node 22 xmlTextNode":true, + "Range 18 [document.head, 1, document.head, 1], node 23 detachedXmlTextNode":true, + "Range 18 [document.head, 1, document.head, 1], node 24 processingInstruction":true, + "Range 18 [document.head, 1, document.head, 1], node 25 detachedProcessingInstruction":true, + "Range 18 [document.head, 1, document.head, 1], node 28 foreignComment":true, + "Range 18 [document.head, 1, document.head, 1], node 29 detachedForeignComment":true, + "Range 18 [document.head, 1, document.head, 1], node 30 xmlComment":true, + "Range 18 [document.head, 1, document.head, 1], node 31 detachedXmlComment":true, + "Range 18 [document.head, 1, document.head, 1], node 33 foreignDocfrag":true, + "Range 18 [document.head, 1, document.head, 1], node 34 xmlDocfrag":true, + "Range 18 [document.head, 1, document.head, 1], node 36 foreignDoctype":true, + "Range 18 [document.head, 1, document.head, 1], node 37 xmlDoctype":true, + "Range 19 [document.body, 0, document.body, 1], node 4 foreignPara1":true, + "Range 19 [document.body, 0, document.body, 1], node 5 foreignPara1.firstChild":true, + "Range 19 [document.body, 0, document.body, 1], node 14 foreignDoc":true, + "Range 19 [document.body, 0, document.body, 1], node 15 foreignPara2":true, + "Range 19 [document.body, 0, document.body, 1], node 16 xmlDoc":true, + "Range 19 [document.body, 0, document.body, 1], node 17 xmlElement":true, + "Range 19 [document.body, 0, document.body, 1], node 18 detachedXmlElement":true, + "Range 19 [document.body, 0, document.body, 1], node 20 foreignTextNode":true, + "Range 19 [document.body, 0, document.body, 1], node 21 detachedForeignTextNode":true, + "Range 19 [document.body, 0, document.body, 1], node 22 xmlTextNode":true, + "Range 19 [document.body, 0, document.body, 1], node 23 detachedXmlTextNode":true, + "Range 19 [document.body, 0, document.body, 1], node 24 processingInstruction":true, + "Range 19 [document.body, 0, document.body, 1], node 25 detachedProcessingInstruction":true, + "Range 19 [document.body, 0, document.body, 1], node 28 foreignComment":true, + "Range 19 [document.body, 0, document.body, 1], node 29 detachedForeignComment":true, + "Range 19 [document.body, 0, document.body, 1], node 30 xmlComment":true, + "Range 19 [document.body, 0, document.body, 1], node 31 detachedXmlComment":true, + "Range 19 [document.body, 0, document.body, 1], node 33 foreignDocfrag":true, + "Range 19 [document.body, 0, document.body, 1], node 34 xmlDocfrag":true, + "Range 19 [document.body, 0, document.body, 1], node 36 foreignDoctype":true, + "Range 19 [document.body, 0, document.body, 1], node 37 xmlDoctype":true, + "Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node 4 foreignPara1":true, + "Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node 5 foreignPara1.firstChild":true, + "Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node 14 foreignDoc":true, + "Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node 15 foreignPara2":true, + "Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node 16 xmlDoc":true, + "Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node 17 xmlElement":true, + "Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node 18 detachedXmlElement":true, + "Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node 20 foreignTextNode":true, + "Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node 21 detachedForeignTextNode":true, + "Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node 22 xmlTextNode":true, + "Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node 23 detachedXmlTextNode":true, + "Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node 24 processingInstruction":true, + "Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node 25 detachedProcessingInstruction":true, + "Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node 28 foreignComment":true, + "Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node 29 detachedForeignComment":true, + "Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node 30 xmlComment":true, + "Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node 31 detachedXmlComment":true, + "Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node 33 foreignDocfrag":true, + "Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node 34 xmlDocfrag":true, + "Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node 36 foreignDoctype":true, + "Range 20 [foreignDoc.documentElement, 0, foreignDoc.documentElement, 1], node 37 xmlDoctype":true, + "Range 21 [foreignDoc.head, 1, foreignDoc.head, 1], node 4 foreignPara1":true, + "Range 21 [foreignDoc.head, 1, foreignDoc.head, 1], node 5 foreignPara1.firstChild":true, + "Range 21 [foreignDoc.head, 1, foreignDoc.head, 1], node 14 foreignDoc":true, + "Range 21 [foreignDoc.head, 1, foreignDoc.head, 1], node 15 foreignPara2":true, + "Range 21 [foreignDoc.head, 1, foreignDoc.head, 1], node 16 xmlDoc":true, + "Range 21 [foreignDoc.head, 1, foreignDoc.head, 1], node 17 xmlElement":true, + "Range 21 [foreignDoc.head, 1, foreignDoc.head, 1], node 18 detachedXmlElement":true, + "Range 21 [foreignDoc.head, 1, foreignDoc.head, 1], node 20 foreignTextNode":true, + "Range 21 [foreignDoc.head, 1, foreignDoc.head, 1], node 21 detachedForeignTextNode":true, + "Range 21 [foreignDoc.head, 1, foreignDoc.head, 1], node 22 xmlTextNode":true, + "Range 21 [foreignDoc.head, 1, foreignDoc.head, 1], node 23 detachedXmlTextNode":true, + "Range 21 [foreignDoc.head, 1, foreignDoc.head, 1], node 24 processingInstruction":true, + "Range 21 [foreignDoc.head, 1, foreignDoc.head, 1], node 25 detachedProcessingInstruction":true, + "Range 21 [foreignDoc.head, 1, foreignDoc.head, 1], node 28 foreignComment":true, + "Range 21 [foreignDoc.head, 1, foreignDoc.head, 1], node 29 detachedForeignComment":true, + "Range 21 [foreignDoc.head, 1, foreignDoc.head, 1], node 30 xmlComment":true, + "Range 21 [foreignDoc.head, 1, foreignDoc.head, 1], node 31 detachedXmlComment":true, + "Range 21 [foreignDoc.head, 1, foreignDoc.head, 1], node 33 foreignDocfrag":true, + "Range 21 [foreignDoc.head, 1, foreignDoc.head, 1], node 34 xmlDocfrag":true, + "Range 21 [foreignDoc.head, 1, foreignDoc.head, 1], node 36 foreignDoctype":true, + "Range 21 [foreignDoc.head, 1, foreignDoc.head, 1], node 37 xmlDoctype":true, + "Range 22 [foreignDoc.body, 0, foreignDoc.body, 0], node 4 foreignPara1":true, + "Range 22 [foreignDoc.body, 0, foreignDoc.body, 0], node 5 foreignPara1.firstChild":true, + "Range 22 [foreignDoc.body, 0, foreignDoc.body, 0], node 14 foreignDoc":true, + "Range 22 [foreignDoc.body, 0, foreignDoc.body, 0], node 15 foreignPara2":true, + "Range 22 [foreignDoc.body, 0, foreignDoc.body, 0], node 16 xmlDoc":true, + "Range 22 [foreignDoc.body, 0, foreignDoc.body, 0], node 17 xmlElement":true, + "Range 22 [foreignDoc.body, 0, foreignDoc.body, 0], node 18 detachedXmlElement":true, + "Range 22 [foreignDoc.body, 0, foreignDoc.body, 0], node 20 foreignTextNode":true, + "Range 22 [foreignDoc.body, 0, foreignDoc.body, 0], node 21 detachedForeignTextNode":true, + "Range 22 [foreignDoc.body, 0, foreignDoc.body, 0], node 22 xmlTextNode":true, + "Range 22 [foreignDoc.body, 0, foreignDoc.body, 0], node 23 detachedXmlTextNode":true, + "Range 22 [foreignDoc.body, 0, foreignDoc.body, 0], node 24 processingInstruction":true, + "Range 22 [foreignDoc.body, 0, foreignDoc.body, 0], node 25 detachedProcessingInstruction":true, + "Range 22 [foreignDoc.body, 0, foreignDoc.body, 0], node 28 foreignComment":true, + "Range 22 [foreignDoc.body, 0, foreignDoc.body, 0], node 29 detachedForeignComment":true, + "Range 22 [foreignDoc.body, 0, foreignDoc.body, 0], node 30 xmlComment":true, + "Range 22 [foreignDoc.body, 0, foreignDoc.body, 0], node 31 detachedXmlComment":true, + "Range 22 [foreignDoc.body, 0, foreignDoc.body, 0], node 33 foreignDocfrag":true, + "Range 22 [foreignDoc.body, 0, foreignDoc.body, 0], node 34 xmlDocfrag":true, + "Range 22 [foreignDoc.body, 0, foreignDoc.body, 0], node 36 foreignDoctype":true, + "Range 22 [foreignDoc.body, 0, foreignDoc.body, 0], node 37 xmlDoctype":true, + "Range 23 [paras[0], 0, paras[0], 0], node 4 foreignPara1":true, + "Range 23 [paras[0], 0, paras[0], 0], node 5 foreignPara1.firstChild":true, + "Range 23 [paras[0], 0, paras[0], 0], node 14 foreignDoc":true, + "Range 23 [paras[0], 0, paras[0], 0], node 15 foreignPara2":true, + "Range 23 [paras[0], 0, paras[0], 0], node 16 xmlDoc":true, + "Range 23 [paras[0], 0, paras[0], 0], node 17 xmlElement":true, + "Range 23 [paras[0], 0, paras[0], 0], node 18 detachedXmlElement":true, + "Range 23 [paras[0], 0, paras[0], 0], node 20 foreignTextNode":true, + "Range 23 [paras[0], 0, paras[0], 0], node 21 detachedForeignTextNode":true, + "Range 23 [paras[0], 0, paras[0], 0], node 22 xmlTextNode":true, + "Range 23 [paras[0], 0, paras[0], 0], node 23 detachedXmlTextNode":true, + "Range 23 [paras[0], 0, paras[0], 0], node 24 processingInstruction":true, + "Range 23 [paras[0], 0, paras[0], 0], node 25 detachedProcessingInstruction":true, + "Range 23 [paras[0], 0, paras[0], 0], node 28 foreignComment":true, + "Range 23 [paras[0], 0, paras[0], 0], node 29 detachedForeignComment":true, + "Range 23 [paras[0], 0, paras[0], 0], node 30 xmlComment":true, + "Range 23 [paras[0], 0, paras[0], 0], node 31 detachedXmlComment":true, + "Range 23 [paras[0], 0, paras[0], 0], node 33 foreignDocfrag":true, + "Range 23 [paras[0], 0, paras[0], 0], node 34 xmlDocfrag":true, + "Range 23 [paras[0], 0, paras[0], 0], node 36 foreignDoctype":true, + "Range 23 [paras[0], 0, paras[0], 0], node 37 xmlDoctype":true, + "Range 24 [paras[0], 0, paras[0], 1], node 4 foreignPara1":true, + "Range 24 [paras[0], 0, paras[0], 1], node 5 foreignPara1.firstChild":true, + "Range 24 [paras[0], 0, paras[0], 1], node 14 foreignDoc":true, + "Range 24 [paras[0], 0, paras[0], 1], node 15 foreignPara2":true, + "Range 24 [paras[0], 0, paras[0], 1], node 16 xmlDoc":true, + "Range 24 [paras[0], 0, paras[0], 1], node 17 xmlElement":true, + "Range 24 [paras[0], 0, paras[0], 1], node 18 detachedXmlElement":true, + "Range 24 [paras[0], 0, paras[0], 1], node 20 foreignTextNode":true, + "Range 24 [paras[0], 0, paras[0], 1], node 21 detachedForeignTextNode":true, + "Range 24 [paras[0], 0, paras[0], 1], node 22 xmlTextNode":true, + "Range 24 [paras[0], 0, paras[0], 1], node 23 detachedXmlTextNode":true, + "Range 24 [paras[0], 0, paras[0], 1], node 24 processingInstruction":true, + "Range 24 [paras[0], 0, paras[0], 1], node 25 detachedProcessingInstruction":true, + "Range 24 [paras[0], 0, paras[0], 1], node 28 foreignComment":true, + "Range 24 [paras[0], 0, paras[0], 1], node 29 detachedForeignComment":true, + "Range 24 [paras[0], 0, paras[0], 1], node 30 xmlComment":true, + "Range 24 [paras[0], 0, paras[0], 1], node 31 detachedXmlComment":true, + "Range 24 [paras[0], 0, paras[0], 1], node 33 foreignDocfrag":true, + "Range 24 [paras[0], 0, paras[0], 1], node 34 xmlDocfrag":true, + "Range 24 [paras[0], 0, paras[0], 1], node 36 foreignDoctype":true, + "Range 24 [paras[0], 0, paras[0], 1], node 37 xmlDoctype":true, + "Range 25 [detachedPara1, 0, detachedPara1, 0], node 4 foreignPara1":true, + "Range 25 [detachedPara1, 0, detachedPara1, 0], node 5 foreignPara1.firstChild":true, + "Range 25 [detachedPara1, 0, detachedPara1, 0], node 14 foreignDoc":true, + "Range 25 [detachedPara1, 0, detachedPara1, 0], node 15 foreignPara2":true, + "Range 25 [detachedPara1, 0, detachedPara1, 0], node 16 xmlDoc":true, + "Range 25 [detachedPara1, 0, detachedPara1, 0], node 17 xmlElement":true, + "Range 25 [detachedPara1, 0, detachedPara1, 0], node 18 detachedXmlElement":true, + "Range 25 [detachedPara1, 0, detachedPara1, 0], node 20 foreignTextNode":true, + "Range 25 [detachedPara1, 0, detachedPara1, 0], node 21 detachedForeignTextNode":true, + "Range 25 [detachedPara1, 0, detachedPara1, 0], node 22 xmlTextNode":true, + "Range 25 [detachedPara1, 0, detachedPara1, 0], node 23 detachedXmlTextNode":true, + "Range 25 [detachedPara1, 0, detachedPara1, 0], node 24 processingInstruction":true, + "Range 25 [detachedPara1, 0, detachedPara1, 0], node 25 detachedProcessingInstruction":true, + "Range 25 [detachedPara1, 0, detachedPara1, 0], node 28 foreignComment":true, + "Range 25 [detachedPara1, 0, detachedPara1, 0], node 29 detachedForeignComment":true, + "Range 25 [detachedPara1, 0, detachedPara1, 0], node 30 xmlComment":true, + "Range 25 [detachedPara1, 0, detachedPara1, 0], node 31 detachedXmlComment":true, + "Range 25 [detachedPara1, 0, detachedPara1, 0], node 33 foreignDocfrag":true, + "Range 25 [detachedPara1, 0, detachedPara1, 0], node 34 xmlDocfrag":true, + "Range 25 [detachedPara1, 0, detachedPara1, 0], node 36 foreignDoctype":true, + "Range 25 [detachedPara1, 0, detachedPara1, 0], node 37 xmlDoctype":true, + "Range 26 [detachedPara1, 0, detachedPara1, 1], node 4 foreignPara1":true, + "Range 26 [detachedPara1, 0, detachedPara1, 1], node 5 foreignPara1.firstChild":true, + "Range 26 [detachedPara1, 0, detachedPara1, 1], node 14 foreignDoc":true, + "Range 26 [detachedPara1, 0, detachedPara1, 1], node 15 foreignPara2":true, + "Range 26 [detachedPara1, 0, detachedPara1, 1], node 16 xmlDoc":true, + "Range 26 [detachedPara1, 0, detachedPara1, 1], node 17 xmlElement":true, + "Range 26 [detachedPara1, 0, detachedPara1, 1], node 18 detachedXmlElement":true, + "Range 26 [detachedPara1, 0, detachedPara1, 1], node 20 foreignTextNode":true, + "Range 26 [detachedPara1, 0, detachedPara1, 1], node 21 detachedForeignTextNode":true, + "Range 26 [detachedPara1, 0, detachedPara1, 1], node 22 xmlTextNode":true, + "Range 26 [detachedPara1, 0, detachedPara1, 1], node 23 detachedXmlTextNode":true, + "Range 26 [detachedPara1, 0, detachedPara1, 1], node 24 processingInstruction":true, + "Range 26 [detachedPara1, 0, detachedPara1, 1], node 25 detachedProcessingInstruction":true, + "Range 26 [detachedPara1, 0, detachedPara1, 1], node 28 foreignComment":true, + "Range 26 [detachedPara1, 0, detachedPara1, 1], node 29 detachedForeignComment":true, + "Range 26 [detachedPara1, 0, detachedPara1, 1], node 30 xmlComment":true, + "Range 26 [detachedPara1, 0, detachedPara1, 1], node 31 detachedXmlComment":true, + "Range 26 [detachedPara1, 0, detachedPara1, 1], node 33 foreignDocfrag":true, + "Range 26 [detachedPara1, 0, detachedPara1, 1], node 34 xmlDocfrag":true, + "Range 26 [detachedPara1, 0, detachedPara1, 1], node 36 foreignDoctype":true, + "Range 26 [detachedPara1, 0, detachedPara1, 1], node 37 xmlDoctype":true, + "Range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0], node 4 foreignPara1":true, + "Range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0], node 5 foreignPara1.firstChild":true, + "Range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0], node 14 foreignDoc":true, + "Range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0], node 15 foreignPara2":true, + "Range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0], node 16 xmlDoc":true, + "Range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0], node 17 xmlElement":true, + "Range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0], node 18 detachedXmlElement":true, + "Range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0], node 20 foreignTextNode":true, + "Range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0], node 21 detachedForeignTextNode":true, + "Range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0], node 22 xmlTextNode":true, + "Range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0], node 23 detachedXmlTextNode":true, + "Range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0], node 24 processingInstruction":true, + "Range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0], node 25 detachedProcessingInstruction":true, + "Range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0], node 28 foreignComment":true, + "Range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0], node 29 detachedForeignComment":true, + "Range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0], node 30 xmlComment":true, + "Range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0], node 31 detachedXmlComment":true, + "Range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0], node 33 foreignDocfrag":true, + "Range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0], node 34 xmlDocfrag":true, + "Range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0], node 36 foreignDoctype":true, + "Range 27 [paras[0].firstChild, 0, paras[1].firstChild, 0], node 37 xmlDoctype":true, + "Range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8], node 4 foreignPara1":true, + "Range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8], node 5 foreignPara1.firstChild":true, + "Range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8], node 14 foreignDoc":true, + "Range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8], node 15 foreignPara2":true, + "Range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8], node 16 xmlDoc":true, + "Range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8], node 17 xmlElement":true, + "Range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8], node 18 detachedXmlElement":true, + "Range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8], node 20 foreignTextNode":true, + "Range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8], node 21 detachedForeignTextNode":true, + "Range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8], node 22 xmlTextNode":true, + "Range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8], node 23 detachedXmlTextNode":true, + "Range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8], node 24 processingInstruction":true, + "Range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8], node 25 detachedProcessingInstruction":true, + "Range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8], node 28 foreignComment":true, + "Range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8], node 29 detachedForeignComment":true, + "Range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8], node 30 xmlComment":true, + "Range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8], node 31 detachedXmlComment":true, + "Range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8], node 33 foreignDocfrag":true, + "Range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8], node 34 xmlDocfrag":true, + "Range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8], node 36 foreignDoctype":true, + "Range 28 [paras[0].firstChild, 0, paras[1].firstChild, 8], node 37 xmlDoctype":true, + "Range 29 [paras[0].firstChild, 3, paras[3], 1], node 4 foreignPara1":true, + "Range 29 [paras[0].firstChild, 3, paras[3], 1], node 5 foreignPara1.firstChild":true, + "Range 29 [paras[0].firstChild, 3, paras[3], 1], node 14 foreignDoc":true, + "Range 29 [paras[0].firstChild, 3, paras[3], 1], node 15 foreignPara2":true, + "Range 29 [paras[0].firstChild, 3, paras[3], 1], node 16 xmlDoc":true, + "Range 29 [paras[0].firstChild, 3, paras[3], 1], node 17 xmlElement":true, + "Range 29 [paras[0].firstChild, 3, paras[3], 1], node 18 detachedXmlElement":true, + "Range 29 [paras[0].firstChild, 3, paras[3], 1], node 20 foreignTextNode":true, + "Range 29 [paras[0].firstChild, 3, paras[3], 1], node 21 detachedForeignTextNode":true, + "Range 29 [paras[0].firstChild, 3, paras[3], 1], node 22 xmlTextNode":true, + "Range 29 [paras[0].firstChild, 3, paras[3], 1], node 23 detachedXmlTextNode":true, + "Range 29 [paras[0].firstChild, 3, paras[3], 1], node 24 processingInstruction":true, + "Range 29 [paras[0].firstChild, 3, paras[3], 1], node 25 detachedProcessingInstruction":true, + "Range 29 [paras[0].firstChild, 3, paras[3], 1], node 28 foreignComment":true, + "Range 29 [paras[0].firstChild, 3, paras[3], 1], node 29 detachedForeignComment":true, + "Range 29 [paras[0].firstChild, 3, paras[3], 1], node 30 xmlComment":true, + "Range 29 [paras[0].firstChild, 3, paras[3], 1], node 31 detachedXmlComment":true, + "Range 29 [paras[0].firstChild, 3, paras[3], 1], node 33 foreignDocfrag":true, + "Range 29 [paras[0].firstChild, 3, paras[3], 1], node 34 xmlDocfrag":true, + "Range 29 [paras[0].firstChild, 3, paras[3], 1], node 36 foreignDoctype":true, + "Range 29 [paras[0].firstChild, 3, paras[3], 1], node 37 xmlDoctype":true, + "Range 30 [paras[0], 0, paras[0].firstChild, 7], node 4 foreignPara1":true, + "Range 30 [paras[0], 0, paras[0].firstChild, 7], node 5 foreignPara1.firstChild":true, + "Range 30 [paras[0], 0, paras[0].firstChild, 7], node 14 foreignDoc":true, + "Range 30 [paras[0], 0, paras[0].firstChild, 7], node 15 foreignPara2":true, + "Range 30 [paras[0], 0, paras[0].firstChild, 7], node 16 xmlDoc":true, + "Range 30 [paras[0], 0, paras[0].firstChild, 7], node 17 xmlElement":true, + "Range 30 [paras[0], 0, paras[0].firstChild, 7], node 18 detachedXmlElement":true, + "Range 30 [paras[0], 0, paras[0].firstChild, 7], node 20 foreignTextNode":true, + "Range 30 [paras[0], 0, paras[0].firstChild, 7], node 21 detachedForeignTextNode":true, + "Range 30 [paras[0], 0, paras[0].firstChild, 7], node 22 xmlTextNode":true, + "Range 30 [paras[0], 0, paras[0].firstChild, 7], node 23 detachedXmlTextNode":true, + "Range 30 [paras[0], 0, paras[0].firstChild, 7], node 24 processingInstruction":true, + "Range 30 [paras[0], 0, paras[0].firstChild, 7], node 25 detachedProcessingInstruction":true, + "Range 30 [paras[0], 0, paras[0].firstChild, 7], node 28 foreignComment":true, + "Range 30 [paras[0], 0, paras[0].firstChild, 7], node 29 detachedForeignComment":true, + "Range 30 [paras[0], 0, paras[0].firstChild, 7], node 30 xmlComment":true, + "Range 30 [paras[0], 0, paras[0].firstChild, 7], node 31 detachedXmlComment":true, + "Range 30 [paras[0], 0, paras[0].firstChild, 7], node 33 foreignDocfrag":true, + "Range 30 [paras[0], 0, paras[0].firstChild, 7], node 34 xmlDocfrag":true, + "Range 30 [paras[0], 0, paras[0].firstChild, 7], node 36 foreignDoctype":true, + "Range 30 [paras[0], 0, paras[0].firstChild, 7], node 37 xmlDoctype":true, + "Range 31 [testDiv, 2, paras[4], 1], node 4 foreignPara1":true, + "Range 31 [testDiv, 2, paras[4], 1], node 5 foreignPara1.firstChild":true, + "Range 31 [testDiv, 2, paras[4], 1], node 14 foreignDoc":true, + "Range 31 [testDiv, 2, paras[4], 1], node 15 foreignPara2":true, + "Range 31 [testDiv, 2, paras[4], 1], node 16 xmlDoc":true, + "Range 31 [testDiv, 2, paras[4], 1], node 17 xmlElement":true, + "Range 31 [testDiv, 2, paras[4], 1], node 18 detachedXmlElement":true, + "Range 31 [testDiv, 2, paras[4], 1], node 20 foreignTextNode":true, + "Range 31 [testDiv, 2, paras[4], 1], node 21 detachedForeignTextNode":true, + "Range 31 [testDiv, 2, paras[4], 1], node 22 xmlTextNode":true, + "Range 31 [testDiv, 2, paras[4], 1], node 23 detachedXmlTextNode":true, + "Range 31 [testDiv, 2, paras[4], 1], node 24 processingInstruction":true, + "Range 31 [testDiv, 2, paras[4], 1], node 25 detachedProcessingInstruction":true, + "Range 31 [testDiv, 2, paras[4], 1], node 28 foreignComment":true, + "Range 31 [testDiv, 2, paras[4], 1], node 29 detachedForeignComment":true, + "Range 31 [testDiv, 2, paras[4], 1], node 30 xmlComment":true, + "Range 31 [testDiv, 2, paras[4], 1], node 31 detachedXmlComment":true, + "Range 31 [testDiv, 2, paras[4], 1], node 33 foreignDocfrag":true, + "Range 31 [testDiv, 2, paras[4], 1], node 34 xmlDocfrag":true, + "Range 31 [testDiv, 2, paras[4], 1], node 36 foreignDoctype":true, + "Range 31 [testDiv, 2, paras[4], 1], node 37 xmlDoctype":true, + "Range 32 [testDiv, 1, paras[2].firstChild, 5], node 4 foreignPara1":true, + "Range 32 [testDiv, 1, paras[2].firstChild, 5], node 5 foreignPara1.firstChild":true, + "Range 32 [testDiv, 1, paras[2].firstChild, 5], node 14 foreignDoc":true, + "Range 32 [testDiv, 1, paras[2].firstChild, 5], node 15 foreignPara2":true, + "Range 32 [testDiv, 1, paras[2].firstChild, 5], node 16 xmlDoc":true, + "Range 32 [testDiv, 1, paras[2].firstChild, 5], node 17 xmlElement":true, + "Range 32 [testDiv, 1, paras[2].firstChild, 5], node 18 detachedXmlElement":true, + "Range 32 [testDiv, 1, paras[2].firstChild, 5], node 20 foreignTextNode":true, + "Range 32 [testDiv, 1, paras[2].firstChild, 5], node 21 detachedForeignTextNode":true, + "Range 32 [testDiv, 1, paras[2].firstChild, 5], node 22 xmlTextNode":true, + "Range 32 [testDiv, 1, paras[2].firstChild, 5], node 23 detachedXmlTextNode":true, + "Range 32 [testDiv, 1, paras[2].firstChild, 5], node 24 processingInstruction":true, + "Range 32 [testDiv, 1, paras[2].firstChild, 5], node 25 detachedProcessingInstruction":true, + "Range 32 [testDiv, 1, paras[2].firstChild, 5], node 28 foreignComment":true, + "Range 32 [testDiv, 1, paras[2].firstChild, 5], node 29 detachedForeignComment":true, + "Range 32 [testDiv, 1, paras[2].firstChild, 5], node 30 xmlComment":true, + "Range 32 [testDiv, 1, paras[2].firstChild, 5], node 31 detachedXmlComment":true, + "Range 32 [testDiv, 1, paras[2].firstChild, 5], node 33 foreignDocfrag":true, + "Range 32 [testDiv, 1, paras[2].firstChild, 5], node 34 xmlDocfrag":true, + "Range 32 [testDiv, 1, paras[2].firstChild, 5], node 36 foreignDoctype":true, + "Range 32 [testDiv, 1, paras[2].firstChild, 5], node 37 xmlDoctype":true, + "Range 33 [document.documentElement, 1, document.body, 0], node 4 foreignPara1":true, + "Range 33 [document.documentElement, 1, document.body, 0], node 5 foreignPara1.firstChild":true, + "Range 33 [document.documentElement, 1, document.body, 0], node 14 foreignDoc":true, + "Range 33 [document.documentElement, 1, document.body, 0], node 15 foreignPara2":true, + "Range 33 [document.documentElement, 1, document.body, 0], node 16 xmlDoc":true, + "Range 33 [document.documentElement, 1, document.body, 0], node 17 xmlElement":true, + "Range 33 [document.documentElement, 1, document.body, 0], node 18 detachedXmlElement":true, + "Range 33 [document.documentElement, 1, document.body, 0], node 20 foreignTextNode":true, + "Range 33 [document.documentElement, 1, document.body, 0], node 21 detachedForeignTextNode":true, + "Range 33 [document.documentElement, 1, document.body, 0], node 22 xmlTextNode":true, + "Range 33 [document.documentElement, 1, document.body, 0], node 23 detachedXmlTextNode":true, + "Range 33 [document.documentElement, 1, document.body, 0], node 24 processingInstruction":true, + "Range 33 [document.documentElement, 1, document.body, 0], node 25 detachedProcessingInstruction":true, + "Range 33 [document.documentElement, 1, document.body, 0], node 28 foreignComment":true, + "Range 33 [document.documentElement, 1, document.body, 0], node 29 detachedForeignComment":true, + "Range 33 [document.documentElement, 1, document.body, 0], node 30 xmlComment":true, + "Range 33 [document.documentElement, 1, document.body, 0], node 31 detachedXmlComment":true, + "Range 33 [document.documentElement, 1, document.body, 0], node 33 foreignDocfrag":true, + "Range 33 [document.documentElement, 1, document.body, 0], node 34 xmlDocfrag":true, + "Range 33 [document.documentElement, 1, document.body, 0], node 36 foreignDoctype":true, + "Range 33 [document.documentElement, 1, document.body, 0], node 37 xmlDoctype":true, + "Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0], node 4 foreignPara1":true, + "Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0], node 5 foreignPara1.firstChild":true, + "Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0], node 14 foreignDoc":true, + "Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0], node 15 foreignPara2":true, + "Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0], node 16 xmlDoc":true, + "Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0], node 17 xmlElement":true, + "Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0], node 18 detachedXmlElement":true, + "Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0], node 20 foreignTextNode":true, + "Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0], node 21 detachedForeignTextNode":true, + "Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0], node 22 xmlTextNode":true, + "Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0], node 23 detachedXmlTextNode":true, + "Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0], node 24 processingInstruction":true, + "Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0], node 25 detachedProcessingInstruction":true, + "Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0], node 28 foreignComment":true, + "Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0], node 29 detachedForeignComment":true, + "Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0], node 30 xmlComment":true, + "Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0], node 31 detachedXmlComment":true, + "Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0], node 33 foreignDocfrag":true, + "Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0], node 34 xmlDocfrag":true, + "Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0], node 36 foreignDoctype":true, + "Range 34 [foreignDoc.documentElement, 1, foreignDoc.body, 0], node 37 xmlDoctype":true, + "Range 35 [document, 0, document, 1], node 4 foreignPara1":true, + "Range 35 [document, 0, document, 1], node 5 foreignPara1.firstChild":true, + "Range 35 [document, 0, document, 1], node 14 foreignDoc":true, + "Range 35 [document, 0, document, 1], node 15 foreignPara2":true, + "Range 35 [document, 0, document, 1], node 16 xmlDoc":true, + "Range 35 [document, 0, document, 1], node 17 xmlElement":true, + "Range 35 [document, 0, document, 1], node 18 detachedXmlElement":true, + "Range 35 [document, 0, document, 1], node 20 foreignTextNode":true, + "Range 35 [document, 0, document, 1], node 21 detachedForeignTextNode":true, + "Range 35 [document, 0, document, 1], node 22 xmlTextNode":true, + "Range 35 [document, 0, document, 1], node 23 detachedXmlTextNode":true, + "Range 35 [document, 0, document, 1], node 24 processingInstruction":true, + "Range 35 [document, 0, document, 1], node 25 detachedProcessingInstruction":true, + "Range 35 [document, 0, document, 1], node 28 foreignComment":true, + "Range 35 [document, 0, document, 1], node 29 detachedForeignComment":true, + "Range 35 [document, 0, document, 1], node 30 xmlComment":true, + "Range 35 [document, 0, document, 1], node 31 detachedXmlComment":true, + "Range 35 [document, 0, document, 1], node 33 foreignDocfrag":true, + "Range 35 [document, 0, document, 1], node 34 xmlDocfrag":true, + "Range 35 [document, 0, document, 1], node 36 foreignDoctype":true, + "Range 35 [document, 0, document, 1], node 37 xmlDoctype":true, + "Range 36 [document, 0, document, 2], node 4 foreignPara1":true, + "Range 36 [document, 0, document, 2], node 5 foreignPara1.firstChild":true, + "Range 36 [document, 0, document, 2], node 14 foreignDoc":true, + "Range 36 [document, 0, document, 2], node 15 foreignPara2":true, + "Range 36 [document, 0, document, 2], node 16 xmlDoc":true, + "Range 36 [document, 0, document, 2], node 17 xmlElement":true, + "Range 36 [document, 0, document, 2], node 18 detachedXmlElement":true, + "Range 36 [document, 0, document, 2], node 20 foreignTextNode":true, + "Range 36 [document, 0, document, 2], node 21 detachedForeignTextNode":true, + "Range 36 [document, 0, document, 2], node 22 xmlTextNode":true, + "Range 36 [document, 0, document, 2], node 23 detachedXmlTextNode":true, + "Range 36 [document, 0, document, 2], node 24 processingInstruction":true, + "Range 36 [document, 0, document, 2], node 25 detachedProcessingInstruction":true, + "Range 36 [document, 0, document, 2], node 28 foreignComment":true, + "Range 36 [document, 0, document, 2], node 29 detachedForeignComment":true, + "Range 36 [document, 0, document, 2], node 30 xmlComment":true, + "Range 36 [document, 0, document, 2], node 31 detachedXmlComment":true, + "Range 36 [document, 0, document, 2], node 33 foreignDocfrag":true, + "Range 36 [document, 0, document, 2], node 34 xmlDocfrag":true, + "Range 36 [document, 0, document, 2], node 36 foreignDoctype":true, + "Range 36 [document, 0, document, 2], node 37 xmlDoctype":true, + "Range 37 [document, 1, document, 2], node 4 foreignPara1":true, + "Range 37 [document, 1, document, 2], node 5 foreignPara1.firstChild":true, + "Range 37 [document, 1, document, 2], node 14 foreignDoc":true, + "Range 37 [document, 1, document, 2], node 15 foreignPara2":true, + "Range 37 [document, 1, document, 2], node 16 xmlDoc":true, + "Range 37 [document, 1, document, 2], node 17 xmlElement":true, + "Range 37 [document, 1, document, 2], node 18 detachedXmlElement":true, + "Range 37 [document, 1, document, 2], node 20 foreignTextNode":true, + "Range 37 [document, 1, document, 2], node 21 detachedForeignTextNode":true, + "Range 37 [document, 1, document, 2], node 22 xmlTextNode":true, + "Range 37 [document, 1, document, 2], node 23 detachedXmlTextNode":true, + "Range 37 [document, 1, document, 2], node 24 processingInstruction":true, + "Range 37 [document, 1, document, 2], node 25 detachedProcessingInstruction":true, + "Range 37 [document, 1, document, 2], node 28 foreignComment":true, + "Range 37 [document, 1, document, 2], node 29 detachedForeignComment":true, + "Range 37 [document, 1, document, 2], node 30 xmlComment":true, + "Range 37 [document, 1, document, 2], node 31 detachedXmlComment":true, + "Range 37 [document, 1, document, 2], node 33 foreignDocfrag":true, + "Range 37 [document, 1, document, 2], node 34 xmlDocfrag":true, + "Range 37 [document, 1, document, 2], node 36 foreignDoctype":true, + "Range 37 [document, 1, document, 2], node 37 xmlDoctype":true, + "Range 38 [testDiv, 0, comment, 5], node 4 foreignPara1":true, + "Range 38 [testDiv, 0, comment, 5], node 5 foreignPara1.firstChild":true, + "Range 38 [testDiv, 0, comment, 5], node 14 foreignDoc":true, + "Range 38 [testDiv, 0, comment, 5], node 15 foreignPara2":true, + "Range 38 [testDiv, 0, comment, 5], node 16 xmlDoc":true, + "Range 38 [testDiv, 0, comment, 5], node 17 xmlElement":true, + "Range 38 [testDiv, 0, comment, 5], node 18 detachedXmlElement":true, + "Range 38 [testDiv, 0, comment, 5], node 20 foreignTextNode":true, + "Range 38 [testDiv, 0, comment, 5], node 21 detachedForeignTextNode":true, + "Range 38 [testDiv, 0, comment, 5], node 22 xmlTextNode":true, + "Range 38 [testDiv, 0, comment, 5], node 23 detachedXmlTextNode":true, + "Range 38 [testDiv, 0, comment, 5], node 24 processingInstruction":true, + "Range 38 [testDiv, 0, comment, 5], node 25 detachedProcessingInstruction":true, + "Range 38 [testDiv, 0, comment, 5], node 28 foreignComment":true, + "Range 38 [testDiv, 0, comment, 5], node 29 detachedForeignComment":true, + "Range 38 [testDiv, 0, comment, 5], node 30 xmlComment":true, + "Range 38 [testDiv, 0, comment, 5], node 31 detachedXmlComment":true, + "Range 38 [testDiv, 0, comment, 5], node 33 foreignDocfrag":true, + "Range 38 [testDiv, 0, comment, 5], node 34 xmlDocfrag":true, + "Range 38 [testDiv, 0, comment, 5], node 36 foreignDoctype":true, + "Range 38 [testDiv, 0, comment, 5], node 37 xmlDoctype":true, + "Range 39 [paras[2].firstChild, 4, comment, 2], node 4 foreignPara1":true, + "Range 39 [paras[2].firstChild, 4, comment, 2], node 5 foreignPara1.firstChild":true, + "Range 39 [paras[2].firstChild, 4, comment, 2], node 14 foreignDoc":true, + "Range 39 [paras[2].firstChild, 4, comment, 2], node 15 foreignPara2":true, + "Range 39 [paras[2].firstChild, 4, comment, 2], node 16 xmlDoc":true, + "Range 39 [paras[2].firstChild, 4, comment, 2], node 17 xmlElement":true, + "Range 39 [paras[2].firstChild, 4, comment, 2], node 18 detachedXmlElement":true, + "Range 39 [paras[2].firstChild, 4, comment, 2], node 20 foreignTextNode":true, + "Range 39 [paras[2].firstChild, 4, comment, 2], node 21 detachedForeignTextNode":true, + "Range 39 [paras[2].firstChild, 4, comment, 2], node 22 xmlTextNode":true, + "Range 39 [paras[2].firstChild, 4, comment, 2], node 23 detachedXmlTextNode":true, + "Range 39 [paras[2].firstChild, 4, comment, 2], node 24 processingInstruction":true, + "Range 39 [paras[2].firstChild, 4, comment, 2], node 25 detachedProcessingInstruction":true, + "Range 39 [paras[2].firstChild, 4, comment, 2], node 28 foreignComment":true, + "Range 39 [paras[2].firstChild, 4, comment, 2], node 29 detachedForeignComment":true, + "Range 39 [paras[2].firstChild, 4, comment, 2], node 30 xmlComment":true, + "Range 39 [paras[2].firstChild, 4, comment, 2], node 31 detachedXmlComment":true, + "Range 39 [paras[2].firstChild, 4, comment, 2], node 33 foreignDocfrag":true, + "Range 39 [paras[2].firstChild, 4, comment, 2], node 34 xmlDocfrag":true, + "Range 39 [paras[2].firstChild, 4, comment, 2], node 36 foreignDoctype":true, + "Range 39 [paras[2].firstChild, 4, comment, 2], node 37 xmlDoctype":true, + "Range 40 [paras[3], 1, comment, 8], node 4 foreignPara1":true, + "Range 40 [paras[3], 1, comment, 8], node 5 foreignPara1.firstChild":true, + "Range 40 [paras[3], 1, comment, 8], node 14 foreignDoc":true, + "Range 40 [paras[3], 1, comment, 8], node 15 foreignPara2":true, + "Range 40 [paras[3], 1, comment, 8], node 16 xmlDoc":true, + "Range 40 [paras[3], 1, comment, 8], node 17 xmlElement":true, + "Range 40 [paras[3], 1, comment, 8], node 18 detachedXmlElement":true, + "Range 40 [paras[3], 1, comment, 8], node 20 foreignTextNode":true, + "Range 40 [paras[3], 1, comment, 8], node 21 detachedForeignTextNode":true, + "Range 40 [paras[3], 1, comment, 8], node 22 xmlTextNode":true, + "Range 40 [paras[3], 1, comment, 8], node 23 detachedXmlTextNode":true, + "Range 40 [paras[3], 1, comment, 8], node 24 processingInstruction":true, + "Range 40 [paras[3], 1, comment, 8], node 25 detachedProcessingInstruction":true, + "Range 40 [paras[3], 1, comment, 8], node 28 foreignComment":true, + "Range 40 [paras[3], 1, comment, 8], node 29 detachedForeignComment":true, + "Range 40 [paras[3], 1, comment, 8], node 30 xmlComment":true, + "Range 40 [paras[3], 1, comment, 8], node 31 detachedXmlComment":true, + "Range 40 [paras[3], 1, comment, 8], node 33 foreignDocfrag":true, + "Range 40 [paras[3], 1, comment, 8], node 34 xmlDocfrag":true, + "Range 40 [paras[3], 1, comment, 8], node 36 foreignDoctype":true, + "Range 40 [paras[3], 1, comment, 8], node 37 xmlDoctype":true, + "Range 41 [foreignDoc, 0, foreignDoc, 0], node 4 foreignPara1":true, + "Range 41 [foreignDoc, 0, foreignDoc, 0], node 5 foreignPara1.firstChild":true, + "Range 41 [foreignDoc, 0, foreignDoc, 0], node 14 foreignDoc":true, + "Range 41 [foreignDoc, 0, foreignDoc, 0], node 15 foreignPara2":true, + "Range 41 [foreignDoc, 0, foreignDoc, 0], node 16 xmlDoc":true, + "Range 41 [foreignDoc, 0, foreignDoc, 0], node 17 xmlElement":true, + "Range 41 [foreignDoc, 0, foreignDoc, 0], node 18 detachedXmlElement":true, + "Range 41 [foreignDoc, 0, foreignDoc, 0], node 20 foreignTextNode":true, + "Range 41 [foreignDoc, 0, foreignDoc, 0], node 21 detachedForeignTextNode":true, + "Range 41 [foreignDoc, 0, foreignDoc, 0], node 22 xmlTextNode":true, + "Range 41 [foreignDoc, 0, foreignDoc, 0], node 23 detachedXmlTextNode":true, + "Range 41 [foreignDoc, 0, foreignDoc, 0], node 24 processingInstruction":true, + "Range 41 [foreignDoc, 0, foreignDoc, 0], node 25 detachedProcessingInstruction":true, + "Range 41 [foreignDoc, 0, foreignDoc, 0], node 28 foreignComment":true, + "Range 41 [foreignDoc, 0, foreignDoc, 0], node 29 detachedForeignComment":true, + "Range 41 [foreignDoc, 0, foreignDoc, 0], node 30 xmlComment":true, + "Range 41 [foreignDoc, 0, foreignDoc, 0], node 31 detachedXmlComment":true, + "Range 41 [foreignDoc, 0, foreignDoc, 0], node 33 foreignDocfrag":true, + "Range 41 [foreignDoc, 0, foreignDoc, 0], node 34 xmlDocfrag":true, + "Range 41 [foreignDoc, 0, foreignDoc, 0], node 36 foreignDoctype":true, + "Range 41 [foreignDoc, 0, foreignDoc, 0], node 37 xmlDoctype":true, + "Range 42 [foreignDoc, 1, foreignComment, 2], node 4 foreignPara1":true, + "Range 42 [foreignDoc, 1, foreignComment, 2], node 5 foreignPara1.firstChild":true, + "Range 42 [foreignDoc, 1, foreignComment, 2], node 14 foreignDoc":true, + "Range 42 [foreignDoc, 1, foreignComment, 2], node 15 foreignPara2":true, + "Range 42 [foreignDoc, 1, foreignComment, 2], node 16 xmlDoc":true, + "Range 42 [foreignDoc, 1, foreignComment, 2], node 17 xmlElement":true, + "Range 42 [foreignDoc, 1, foreignComment, 2], node 18 detachedXmlElement":true, + "Range 42 [foreignDoc, 1, foreignComment, 2], node 20 foreignTextNode":true, + "Range 42 [foreignDoc, 1, foreignComment, 2], node 21 detachedForeignTextNode":true, + "Range 42 [foreignDoc, 1, foreignComment, 2], node 22 xmlTextNode":true, + "Range 42 [foreignDoc, 1, foreignComment, 2], node 23 detachedXmlTextNode":true, + "Range 42 [foreignDoc, 1, foreignComment, 2], node 24 processingInstruction":true, + "Range 42 [foreignDoc, 1, foreignComment, 2], node 25 detachedProcessingInstruction":true, + "Range 42 [foreignDoc, 1, foreignComment, 2], node 28 foreignComment":true, + "Range 42 [foreignDoc, 1, foreignComment, 2], node 29 detachedForeignComment":true, + "Range 42 [foreignDoc, 1, foreignComment, 2], node 30 xmlComment":true, + "Range 42 [foreignDoc, 1, foreignComment, 2], node 31 detachedXmlComment":true, + "Range 42 [foreignDoc, 1, foreignComment, 2], node 33 foreignDocfrag":true, + "Range 42 [foreignDoc, 1, foreignComment, 2], node 34 xmlDocfrag":true, + "Range 42 [foreignDoc, 1, foreignComment, 2], node 36 foreignDoctype":true, + "Range 42 [foreignDoc, 1, foreignComment, 2], node 37 xmlDoctype":true, + "Range 43 [foreignDoc.body, 0, foreignTextNode, 36], node 4 foreignPara1":true, + "Range 43 [foreignDoc.body, 0, foreignTextNode, 36], node 5 foreignPara1.firstChild":true, + "Range 43 [foreignDoc.body, 0, foreignTextNode, 36], node 14 foreignDoc":true, + "Range 43 [foreignDoc.body, 0, foreignTextNode, 36], node 15 foreignPara2":true, + "Range 43 [foreignDoc.body, 0, foreignTextNode, 36], node 16 xmlDoc":true, + "Range 43 [foreignDoc.body, 0, foreignTextNode, 36], node 17 xmlElement":true, + "Range 43 [foreignDoc.body, 0, foreignTextNode, 36], node 18 detachedXmlElement":true, + "Range 43 [foreignDoc.body, 0, foreignTextNode, 36], node 20 foreignTextNode":true, + "Range 43 [foreignDoc.body, 0, foreignTextNode, 36], node 21 detachedForeignTextNode":true, + "Range 43 [foreignDoc.body, 0, foreignTextNode, 36], node 22 xmlTextNode":true, + "Range 43 [foreignDoc.body, 0, foreignTextNode, 36], node 23 detachedXmlTextNode":true, + "Range 43 [foreignDoc.body, 0, foreignTextNode, 36], node 24 processingInstruction":true, + "Range 43 [foreignDoc.body, 0, foreignTextNode, 36], node 25 detachedProcessingInstruction":true, + "Range 43 [foreignDoc.body, 0, foreignTextNode, 36], node 28 foreignComment":true, + "Range 43 [foreignDoc.body, 0, foreignTextNode, 36], node 29 detachedForeignComment":true, + "Range 43 [foreignDoc.body, 0, foreignTextNode, 36], node 30 xmlComment":true, + "Range 43 [foreignDoc.body, 0, foreignTextNode, 36], node 31 detachedXmlComment":true, + "Range 43 [foreignDoc.body, 0, foreignTextNode, 36], node 33 foreignDocfrag":true, + "Range 43 [foreignDoc.body, 0, foreignTextNode, 36], node 34 xmlDocfrag":true, + "Range 43 [foreignDoc.body, 0, foreignTextNode, 36], node 36 foreignDoctype":true, + "Range 43 [foreignDoc.body, 0, foreignTextNode, 36], node 37 xmlDoctype":true, + "Range 44 [xmlDoc, 0, xmlDoc, 0], node 4 foreignPara1":true, + "Range 44 [xmlDoc, 0, xmlDoc, 0], node 5 foreignPara1.firstChild":true, + "Range 44 [xmlDoc, 0, xmlDoc, 0], node 14 foreignDoc":true, + "Range 44 [xmlDoc, 0, xmlDoc, 0], node 15 foreignPara2":true, + "Range 44 [xmlDoc, 0, xmlDoc, 0], node 16 xmlDoc":true, + "Range 44 [xmlDoc, 0, xmlDoc, 0], node 17 xmlElement":true, + "Range 44 [xmlDoc, 0, xmlDoc, 0], node 18 detachedXmlElement":true, + "Range 44 [xmlDoc, 0, xmlDoc, 0], node 20 foreignTextNode":true, + "Range 44 [xmlDoc, 0, xmlDoc, 0], node 21 detachedForeignTextNode":true, + "Range 44 [xmlDoc, 0, xmlDoc, 0], node 22 xmlTextNode":true, + "Range 44 [xmlDoc, 0, xmlDoc, 0], node 23 detachedXmlTextNode":true, + "Range 44 [xmlDoc, 0, xmlDoc, 0], node 24 processingInstruction":true, + "Range 44 [xmlDoc, 0, xmlDoc, 0], node 25 detachedProcessingInstruction":true, + "Range 44 [xmlDoc, 0, xmlDoc, 0], node 28 foreignComment":true, + "Range 44 [xmlDoc, 0, xmlDoc, 0], node 29 detachedForeignComment":true, + "Range 44 [xmlDoc, 0, xmlDoc, 0], node 30 xmlComment":true, + "Range 44 [xmlDoc, 0, xmlDoc, 0], node 31 detachedXmlComment":true, + "Range 44 [xmlDoc, 0, xmlDoc, 0], node 33 foreignDocfrag":true, + "Range 44 [xmlDoc, 0, xmlDoc, 0], node 34 xmlDocfrag":true, + "Range 44 [xmlDoc, 0, xmlDoc, 0], node 36 foreignDoctype":true, + "Range 44 [xmlDoc, 0, xmlDoc, 0], node 37 xmlDoctype":true, + "Range 45 [xmlDoc, 1, xmlComment, 0], node 4 foreignPara1":true, + "Range 45 [xmlDoc, 1, xmlComment, 0], node 5 foreignPara1.firstChild":true, + "Range 45 [xmlDoc, 1, xmlComment, 0], node 14 foreignDoc":true, + "Range 45 [xmlDoc, 1, xmlComment, 0], node 15 foreignPara2":true, + "Range 45 [xmlDoc, 1, xmlComment, 0], node 16 xmlDoc":true, + "Range 45 [xmlDoc, 1, xmlComment, 0], node 17 xmlElement":true, + "Range 45 [xmlDoc, 1, xmlComment, 0], node 18 detachedXmlElement":true, + "Range 45 [xmlDoc, 1, xmlComment, 0], node 20 foreignTextNode":true, + "Range 45 [xmlDoc, 1, xmlComment, 0], node 21 detachedForeignTextNode":true, + "Range 45 [xmlDoc, 1, xmlComment, 0], node 22 xmlTextNode":true, + "Range 45 [xmlDoc, 1, xmlComment, 0], node 23 detachedXmlTextNode":true, + "Range 45 [xmlDoc, 1, xmlComment, 0], node 24 processingInstruction":true, + "Range 45 [xmlDoc, 1, xmlComment, 0], node 25 detachedProcessingInstruction":true, + "Range 45 [xmlDoc, 1, xmlComment, 0], node 28 foreignComment":true, + "Range 45 [xmlDoc, 1, xmlComment, 0], node 29 detachedForeignComment":true, + "Range 45 [xmlDoc, 1, xmlComment, 0], node 30 xmlComment":true, + "Range 45 [xmlDoc, 1, xmlComment, 0], node 31 detachedXmlComment":true, + "Range 45 [xmlDoc, 1, xmlComment, 0], node 33 foreignDocfrag":true, + "Range 45 [xmlDoc, 1, xmlComment, 0], node 34 xmlDocfrag":true, + "Range 45 [xmlDoc, 1, xmlComment, 0], node 36 foreignDoctype":true, + "Range 45 [xmlDoc, 1, xmlComment, 0], node 37 xmlDoctype":true, + "Range 46 [detachedTextNode, 0, detachedTextNode, 8], node 4 foreignPara1":true, + "Range 46 [detachedTextNode, 0, detachedTextNode, 8], node 5 foreignPara1.firstChild":true, + "Range 46 [detachedTextNode, 0, detachedTextNode, 8], node 14 foreignDoc":true, + "Range 46 [detachedTextNode, 0, detachedTextNode, 8], node 15 foreignPara2":true, + "Range 46 [detachedTextNode, 0, detachedTextNode, 8], node 16 xmlDoc":true, + "Range 46 [detachedTextNode, 0, detachedTextNode, 8], node 17 xmlElement":true, + "Range 46 [detachedTextNode, 0, detachedTextNode, 8], node 18 detachedXmlElement":true, + "Range 46 [detachedTextNode, 0, detachedTextNode, 8], node 20 foreignTextNode":true, + "Range 46 [detachedTextNode, 0, detachedTextNode, 8], node 21 detachedForeignTextNode":true, + "Range 46 [detachedTextNode, 0, detachedTextNode, 8], node 22 xmlTextNode":true, + "Range 46 [detachedTextNode, 0, detachedTextNode, 8], node 23 detachedXmlTextNode":true, + "Range 46 [detachedTextNode, 0, detachedTextNode, 8], node 24 processingInstruction":true, + "Range 46 [detachedTextNode, 0, detachedTextNode, 8], node 25 detachedProcessingInstruction":true, + "Range 46 [detachedTextNode, 0, detachedTextNode, 8], node 28 foreignComment":true, + "Range 46 [detachedTextNode, 0, detachedTextNode, 8], node 29 detachedForeignComment":true, + "Range 46 [detachedTextNode, 0, detachedTextNode, 8], node 30 xmlComment":true, + "Range 46 [detachedTextNode, 0, detachedTextNode, 8], node 31 detachedXmlComment":true, + "Range 46 [detachedTextNode, 0, detachedTextNode, 8], node 33 foreignDocfrag":true, + "Range 46 [detachedTextNode, 0, detachedTextNode, 8], node 34 xmlDocfrag":true, + "Range 46 [detachedTextNode, 0, detachedTextNode, 8], node 36 foreignDoctype":true, + "Range 46 [detachedTextNode, 0, detachedTextNode, 8], node 37 xmlDoctype":true, + "Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7], node 4 foreignPara1":true, + "Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7], node 5 foreignPara1.firstChild":true, + "Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7], node 14 foreignDoc":true, + "Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7], node 15 foreignPara2":true, + "Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7], node 16 xmlDoc":true, + "Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7], node 17 xmlElement":true, + "Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7], node 18 detachedXmlElement":true, + "Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7], node 20 foreignTextNode":true, + "Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7], node 21 detachedForeignTextNode":true, + "Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7], node 22 xmlTextNode":true, + "Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7], node 23 detachedXmlTextNode":true, + "Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7], node 24 processingInstruction":true, + "Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7], node 25 detachedProcessingInstruction":true, + "Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7], node 28 foreignComment":true, + "Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7], node 29 detachedForeignComment":true, + "Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7], node 30 xmlComment":true, + "Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7], node 31 detachedXmlComment":true, + "Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7], node 33 foreignDocfrag":true, + "Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7], node 34 xmlDocfrag":true, + "Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7], node 36 foreignDoctype":true, + "Range 47 [detachedForeignTextNode, 7, detachedForeignTextNode, 7], node 37 xmlDoctype":true, + "Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node 4 foreignPara1":true, + "Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node 5 foreignPara1.firstChild":true, + "Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node 14 foreignDoc":true, + "Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node 15 foreignPara2":true, + "Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node 16 xmlDoc":true, + "Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node 17 xmlElement":true, + "Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node 18 detachedXmlElement":true, + "Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node 20 foreignTextNode":true, + "Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node 21 detachedForeignTextNode":true, + "Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node 22 xmlTextNode":true, + "Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node 23 detachedXmlTextNode":true, + "Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node 24 processingInstruction":true, + "Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node 25 detachedProcessingInstruction":true, + "Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node 28 foreignComment":true, + "Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node 29 detachedForeignComment":true, + "Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node 30 xmlComment":true, + "Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node 31 detachedXmlComment":true, + "Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node 33 foreignDocfrag":true, + "Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node 34 xmlDocfrag":true, + "Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node 36 foreignDoctype":true, + "Range 48 [detachedForeignTextNode, 0, detachedForeignTextNode, 8], node 37 xmlDoctype":true, + "Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7], node 4 foreignPara1":true, + "Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7], node 5 foreignPara1.firstChild":true, + "Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7], node 14 foreignDoc":true, + "Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7], node 15 foreignPara2":true, + "Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7], node 16 xmlDoc":true, + "Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7], node 17 xmlElement":true, + "Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7], node 18 detachedXmlElement":true, + "Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7], node 20 foreignTextNode":true, + "Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7], node 21 detachedForeignTextNode":true, + "Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7], node 22 xmlTextNode":true, + "Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7], node 23 detachedXmlTextNode":true, + "Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7], node 24 processingInstruction":true, + "Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7], node 25 detachedProcessingInstruction":true, + "Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7], node 28 foreignComment":true, + "Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7], node 29 detachedForeignComment":true, + "Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7], node 30 xmlComment":true, + "Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7], node 31 detachedXmlComment":true, + "Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7], node 33 foreignDocfrag":true, + "Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7], node 34 xmlDocfrag":true, + "Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7], node 36 foreignDoctype":true, + "Range 49 [detachedXmlTextNode, 7, detachedXmlTextNode, 7], node 37 xmlDoctype":true, + "Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node 4 foreignPara1":true, + "Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node 5 foreignPara1.firstChild":true, + "Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node 14 foreignDoc":true, + "Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node 15 foreignPara2":true, + "Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node 16 xmlDoc":true, + "Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node 17 xmlElement":true, + "Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node 18 detachedXmlElement":true, + "Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node 20 foreignTextNode":true, + "Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node 21 detachedForeignTextNode":true, + "Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node 22 xmlTextNode":true, + "Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node 23 detachedXmlTextNode":true, + "Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node 24 processingInstruction":true, + "Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node 25 detachedProcessingInstruction":true, + "Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node 28 foreignComment":true, + "Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node 29 detachedForeignComment":true, + "Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node 30 xmlComment":true, + "Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node 31 detachedXmlComment":true, + "Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node 33 foreignDocfrag":true, + "Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node 34 xmlDocfrag":true, + "Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node 36 foreignDoctype":true, + "Range 50 [detachedXmlTextNode, 0, detachedXmlTextNode, 8], node 37 xmlDoctype":true, + "Range 51 [detachedComment, 3, detachedComment, 4], node 4 foreignPara1":true, + "Range 51 [detachedComment, 3, detachedComment, 4], node 5 foreignPara1.firstChild":true, + "Range 51 [detachedComment, 3, detachedComment, 4], node 14 foreignDoc":true, + "Range 51 [detachedComment, 3, detachedComment, 4], node 15 foreignPara2":true, + "Range 51 [detachedComment, 3, detachedComment, 4], node 16 xmlDoc":true, + "Range 51 [detachedComment, 3, detachedComment, 4], node 17 xmlElement":true, + "Range 51 [detachedComment, 3, detachedComment, 4], node 18 detachedXmlElement":true, + "Range 51 [detachedComment, 3, detachedComment, 4], node 20 foreignTextNode":true, + "Range 51 [detachedComment, 3, detachedComment, 4], node 21 detachedForeignTextNode":true, + "Range 51 [detachedComment, 3, detachedComment, 4], node 22 xmlTextNode":true, + "Range 51 [detachedComment, 3, detachedComment, 4], node 23 detachedXmlTextNode":true, + "Range 51 [detachedComment, 3, detachedComment, 4], node 24 processingInstruction":true, + "Range 51 [detachedComment, 3, detachedComment, 4], node 25 detachedProcessingInstruction":true, + "Range 51 [detachedComment, 3, detachedComment, 4], node 28 foreignComment":true, + "Range 51 [detachedComment, 3, detachedComment, 4], node 29 detachedForeignComment":true, + "Range 51 [detachedComment, 3, detachedComment, 4], node 30 xmlComment":true, + "Range 51 [detachedComment, 3, detachedComment, 4], node 31 detachedXmlComment":true, + "Range 51 [detachedComment, 3, detachedComment, 4], node 33 foreignDocfrag":true, + "Range 51 [detachedComment, 3, detachedComment, 4], node 34 xmlDocfrag":true, + "Range 51 [detachedComment, 3, detachedComment, 4], node 36 foreignDoctype":true, + "Range 51 [detachedComment, 3, detachedComment, 4], node 37 xmlDoctype":true, + "Range 52 [detachedComment, 5, detachedComment, 5], node 4 foreignPara1":true, + "Range 52 [detachedComment, 5, detachedComment, 5], node 5 foreignPara1.firstChild":true, + "Range 52 [detachedComment, 5, detachedComment, 5], node 14 foreignDoc":true, + "Range 52 [detachedComment, 5, detachedComment, 5], node 15 foreignPara2":true, + "Range 52 [detachedComment, 5, detachedComment, 5], node 16 xmlDoc":true, + "Range 52 [detachedComment, 5, detachedComment, 5], node 17 xmlElement":true, + "Range 52 [detachedComment, 5, detachedComment, 5], node 18 detachedXmlElement":true, + "Range 52 [detachedComment, 5, detachedComment, 5], node 20 foreignTextNode":true, + "Range 52 [detachedComment, 5, detachedComment, 5], node 21 detachedForeignTextNode":true, + "Range 52 [detachedComment, 5, detachedComment, 5], node 22 xmlTextNode":true, + "Range 52 [detachedComment, 5, detachedComment, 5], node 23 detachedXmlTextNode":true, + "Range 52 [detachedComment, 5, detachedComment, 5], node 24 processingInstruction":true, + "Range 52 [detachedComment, 5, detachedComment, 5], node 25 detachedProcessingInstruction":true, + "Range 52 [detachedComment, 5, detachedComment, 5], node 28 foreignComment":true, + "Range 52 [detachedComment, 5, detachedComment, 5], node 29 detachedForeignComment":true, + "Range 52 [detachedComment, 5, detachedComment, 5], node 30 xmlComment":true, + "Range 52 [detachedComment, 5, detachedComment, 5], node 31 detachedXmlComment":true, + "Range 52 [detachedComment, 5, detachedComment, 5], node 33 foreignDocfrag":true, + "Range 52 [detachedComment, 5, detachedComment, 5], node 34 xmlDocfrag":true, + "Range 52 [detachedComment, 5, detachedComment, 5], node 36 foreignDoctype":true, + "Range 52 [detachedComment, 5, detachedComment, 5], node 37 xmlDoctype":true, + "Range 53 [detachedForeignComment, 0, detachedForeignComment, 1], node 4 foreignPara1":true, + "Range 53 [detachedForeignComment, 0, detachedForeignComment, 1], node 5 foreignPara1.firstChild":true, + "Range 53 [detachedForeignComment, 0, detachedForeignComment, 1], node 14 foreignDoc":true, + "Range 53 [detachedForeignComment, 0, detachedForeignComment, 1], node 15 foreignPara2":true, + "Range 53 [detachedForeignComment, 0, detachedForeignComment, 1], node 16 xmlDoc":true, + "Range 53 [detachedForeignComment, 0, detachedForeignComment, 1], node 17 xmlElement":true, + "Range 53 [detachedForeignComment, 0, detachedForeignComment, 1], node 18 detachedXmlElement":true, + "Range 53 [detachedForeignComment, 0, detachedForeignComment, 1], node 20 foreignTextNode":true, + "Range 53 [detachedForeignComment, 0, detachedForeignComment, 1], node 21 detachedForeignTextNode":true, + "Range 53 [detachedForeignComment, 0, detachedForeignComment, 1], node 22 xmlTextNode":true, + "Range 53 [detachedForeignComment, 0, detachedForeignComment, 1], node 23 detachedXmlTextNode":true, + "Range 53 [detachedForeignComment, 0, detachedForeignComment, 1], node 24 processingInstruction":true, + "Range 53 [detachedForeignComment, 0, detachedForeignComment, 1], node 25 detachedProcessingInstruction":true, + "Range 53 [detachedForeignComment, 0, detachedForeignComment, 1], node 28 foreignComment":true, + "Range 53 [detachedForeignComment, 0, detachedForeignComment, 1], node 29 detachedForeignComment":true, + "Range 53 [detachedForeignComment, 0, detachedForeignComment, 1], node 30 xmlComment":true, + "Range 53 [detachedForeignComment, 0, detachedForeignComment, 1], node 31 detachedXmlComment":true, + "Range 53 [detachedForeignComment, 0, detachedForeignComment, 1], node 33 foreignDocfrag":true, + "Range 53 [detachedForeignComment, 0, detachedForeignComment, 1], node 34 xmlDocfrag":true, + "Range 53 [detachedForeignComment, 0, detachedForeignComment, 1], node 36 foreignDoctype":true, + "Range 53 [detachedForeignComment, 0, detachedForeignComment, 1], node 37 xmlDoctype":true, + "Range 54 [detachedForeignComment, 4, detachedForeignComment, 4], node 4 foreignPara1":true, + "Range 54 [detachedForeignComment, 4, detachedForeignComment, 4], node 5 foreignPara1.firstChild":true, + "Range 54 [detachedForeignComment, 4, detachedForeignComment, 4], node 14 foreignDoc":true, + "Range 54 [detachedForeignComment, 4, detachedForeignComment, 4], node 15 foreignPara2":true, + "Range 54 [detachedForeignComment, 4, detachedForeignComment, 4], node 16 xmlDoc":true, + "Range 54 [detachedForeignComment, 4, detachedForeignComment, 4], node 17 xmlElement":true, + "Range 54 [detachedForeignComment, 4, detachedForeignComment, 4], node 18 detachedXmlElement":true, + "Range 54 [detachedForeignComment, 4, detachedForeignComment, 4], node 20 foreignTextNode":true, + "Range 54 [detachedForeignComment, 4, detachedForeignComment, 4], node 21 detachedForeignTextNode":true, + "Range 54 [detachedForeignComment, 4, detachedForeignComment, 4], node 22 xmlTextNode":true, + "Range 54 [detachedForeignComment, 4, detachedForeignComment, 4], node 23 detachedXmlTextNode":true, + "Range 54 [detachedForeignComment, 4, detachedForeignComment, 4], node 24 processingInstruction":true, + "Range 54 [detachedForeignComment, 4, detachedForeignComment, 4], node 25 detachedProcessingInstruction":true, + "Range 54 [detachedForeignComment, 4, detachedForeignComment, 4], node 28 foreignComment":true, + "Range 54 [detachedForeignComment, 4, detachedForeignComment, 4], node 29 detachedForeignComment":true, + "Range 54 [detachedForeignComment, 4, detachedForeignComment, 4], node 30 xmlComment":true, + "Range 54 [detachedForeignComment, 4, detachedForeignComment, 4], node 31 detachedXmlComment":true, + "Range 54 [detachedForeignComment, 4, detachedForeignComment, 4], node 33 foreignDocfrag":true, + "Range 54 [detachedForeignComment, 4, detachedForeignComment, 4], node 34 xmlDocfrag":true, + "Range 54 [detachedForeignComment, 4, detachedForeignComment, 4], node 36 foreignDoctype":true, + "Range 54 [detachedForeignComment, 4, detachedForeignComment, 4], node 37 xmlDoctype":true, + "Range 55 [detachedXmlComment, 2, detachedXmlComment, 6], node 4 foreignPara1":true, + "Range 55 [detachedXmlComment, 2, detachedXmlComment, 6], node 5 foreignPara1.firstChild":true, + "Range 55 [detachedXmlComment, 2, detachedXmlComment, 6], node 14 foreignDoc":true, + "Range 55 [detachedXmlComment, 2, detachedXmlComment, 6], node 15 foreignPara2":true, + "Range 55 [detachedXmlComment, 2, detachedXmlComment, 6], node 16 xmlDoc":true, + "Range 55 [detachedXmlComment, 2, detachedXmlComment, 6], node 17 xmlElement":true, + "Range 55 [detachedXmlComment, 2, detachedXmlComment, 6], node 18 detachedXmlElement":true, + "Range 55 [detachedXmlComment, 2, detachedXmlComment, 6], node 20 foreignTextNode":true, + "Range 55 [detachedXmlComment, 2, detachedXmlComment, 6], node 21 detachedForeignTextNode":true, + "Range 55 [detachedXmlComment, 2, detachedXmlComment, 6], node 22 xmlTextNode":true, + "Range 55 [detachedXmlComment, 2, detachedXmlComment, 6], node 23 detachedXmlTextNode":true, + "Range 55 [detachedXmlComment, 2, detachedXmlComment, 6], node 24 processingInstruction":true, + "Range 55 [detachedXmlComment, 2, detachedXmlComment, 6], node 25 detachedProcessingInstruction":true, + "Range 55 [detachedXmlComment, 2, detachedXmlComment, 6], node 28 foreignComment":true, + "Range 55 [detachedXmlComment, 2, detachedXmlComment, 6], node 29 detachedForeignComment":true, + "Range 55 [detachedXmlComment, 2, detachedXmlComment, 6], node 30 xmlComment":true, + "Range 55 [detachedXmlComment, 2, detachedXmlComment, 6], node 31 detachedXmlComment":true, + "Range 55 [detachedXmlComment, 2, detachedXmlComment, 6], node 33 foreignDocfrag":true, + "Range 55 [detachedXmlComment, 2, detachedXmlComment, 6], node 34 xmlDocfrag":true, + "Range 55 [detachedXmlComment, 2, detachedXmlComment, 6], node 36 foreignDoctype":true, + "Range 55 [detachedXmlComment, 2, detachedXmlComment, 6], node 37 xmlDoctype":true, + "Range 56 [docfrag, 0, docfrag, 0], node 4 foreignPara1":true, + "Range 56 [docfrag, 0, docfrag, 0], node 5 foreignPara1.firstChild":true, + "Range 56 [docfrag, 0, docfrag, 0], node 14 foreignDoc":true, + "Range 56 [docfrag, 0, docfrag, 0], node 15 foreignPara2":true, + "Range 56 [docfrag, 0, docfrag, 0], node 16 xmlDoc":true, + "Range 56 [docfrag, 0, docfrag, 0], node 17 xmlElement":true, + "Range 56 [docfrag, 0, docfrag, 0], node 18 detachedXmlElement":true, + "Range 56 [docfrag, 0, docfrag, 0], node 20 foreignTextNode":true, + "Range 56 [docfrag, 0, docfrag, 0], node 21 detachedForeignTextNode":true, + "Range 56 [docfrag, 0, docfrag, 0], node 22 xmlTextNode":true, + "Range 56 [docfrag, 0, docfrag, 0], node 23 detachedXmlTextNode":true, + "Range 56 [docfrag, 0, docfrag, 0], node 24 processingInstruction":true, + "Range 56 [docfrag, 0, docfrag, 0], node 25 detachedProcessingInstruction":true, + "Range 56 [docfrag, 0, docfrag, 0], node 28 foreignComment":true, + "Range 56 [docfrag, 0, docfrag, 0], node 29 detachedForeignComment":true, + "Range 56 [docfrag, 0, docfrag, 0], node 30 xmlComment":true, + "Range 56 [docfrag, 0, docfrag, 0], node 31 detachedXmlComment":true, + "Range 56 [docfrag, 0, docfrag, 0], node 33 foreignDocfrag":true, + "Range 56 [docfrag, 0, docfrag, 0], node 34 xmlDocfrag":true, + "Range 56 [docfrag, 0, docfrag, 0], node 36 foreignDoctype":true, + "Range 56 [docfrag, 0, docfrag, 0], node 37 xmlDoctype":true, + "Range 57 [foreignDocfrag, 0, foreignDocfrag, 0], node 4 foreignPara1":true, + "Range 57 [foreignDocfrag, 0, foreignDocfrag, 0], node 5 foreignPara1.firstChild":true, + "Range 57 [foreignDocfrag, 0, foreignDocfrag, 0], node 14 foreignDoc":true, + "Range 57 [foreignDocfrag, 0, foreignDocfrag, 0], node 15 foreignPara2":true, + "Range 57 [foreignDocfrag, 0, foreignDocfrag, 0], node 16 xmlDoc":true, + "Range 57 [foreignDocfrag, 0, foreignDocfrag, 0], node 17 xmlElement":true, + "Range 57 [foreignDocfrag, 0, foreignDocfrag, 0], node 18 detachedXmlElement":true, + "Range 57 [foreignDocfrag, 0, foreignDocfrag, 0], node 20 foreignTextNode":true, + "Range 57 [foreignDocfrag, 0, foreignDocfrag, 0], node 21 detachedForeignTextNode":true, + "Range 57 [foreignDocfrag, 0, foreignDocfrag, 0], node 22 xmlTextNode":true, + "Range 57 [foreignDocfrag, 0, foreignDocfrag, 0], node 23 detachedXmlTextNode":true, + "Range 57 [foreignDocfrag, 0, foreignDocfrag, 0], node 24 processingInstruction":true, + "Range 57 [foreignDocfrag, 0, foreignDocfrag, 0], node 25 detachedProcessingInstruction":true, + "Range 57 [foreignDocfrag, 0, foreignDocfrag, 0], node 28 foreignComment":true, + "Range 57 [foreignDocfrag, 0, foreignDocfrag, 0], node 29 detachedForeignComment":true, + "Range 57 [foreignDocfrag, 0, foreignDocfrag, 0], node 30 xmlComment":true, + "Range 57 [foreignDocfrag, 0, foreignDocfrag, 0], node 31 detachedXmlComment":true, + "Range 57 [foreignDocfrag, 0, foreignDocfrag, 0], node 33 foreignDocfrag":true, + "Range 57 [foreignDocfrag, 0, foreignDocfrag, 0], node 34 xmlDocfrag":true, + "Range 57 [foreignDocfrag, 0, foreignDocfrag, 0], node 36 foreignDoctype":true, + "Range 57 [foreignDocfrag, 0, foreignDocfrag, 0], node 37 xmlDoctype":true, + "Range 58 [xmlDocfrag, 0, xmlDocfrag, 0], node 4 foreignPara1":true, + "Range 58 [xmlDocfrag, 0, xmlDocfrag, 0], node 5 foreignPara1.firstChild":true, + "Range 58 [xmlDocfrag, 0, xmlDocfrag, 0], node 14 foreignDoc":true, + "Range 58 [xmlDocfrag, 0, xmlDocfrag, 0], node 15 foreignPara2":true, + "Range 58 [xmlDocfrag, 0, xmlDocfrag, 0], node 16 xmlDoc":true, + "Range 58 [xmlDocfrag, 0, xmlDocfrag, 0], node 17 xmlElement":true, + "Range 58 [xmlDocfrag, 0, xmlDocfrag, 0], node 18 detachedXmlElement":true, + "Range 58 [xmlDocfrag, 0, xmlDocfrag, 0], node 20 foreignTextNode":true, + "Range 58 [xmlDocfrag, 0, xmlDocfrag, 0], node 21 detachedForeignTextNode":true, + "Range 58 [xmlDocfrag, 0, xmlDocfrag, 0], node 22 xmlTextNode":true, + "Range 58 [xmlDocfrag, 0, xmlDocfrag, 0], node 23 detachedXmlTextNode":true, + "Range 58 [xmlDocfrag, 0, xmlDocfrag, 0], node 24 processingInstruction":true, + "Range 58 [xmlDocfrag, 0, xmlDocfrag, 0], node 25 detachedProcessingInstruction":true, + "Range 58 [xmlDocfrag, 0, xmlDocfrag, 0], node 28 foreignComment":true, + "Range 58 [xmlDocfrag, 0, xmlDocfrag, 0], node 29 detachedForeignComment":true, + "Range 58 [xmlDocfrag, 0, xmlDocfrag, 0], node 30 xmlComment":true, + "Range 58 [xmlDocfrag, 0, xmlDocfrag, 0], node 31 detachedXmlComment":true, + "Range 58 [xmlDocfrag, 0, xmlDocfrag, 0], node 33 foreignDocfrag":true, + "Range 58 [xmlDocfrag, 0, xmlDocfrag, 0], node 34 xmlDocfrag":true, + "Range 58 [xmlDocfrag, 0, xmlDocfrag, 0], node 36 foreignDoctype":true, + "Range 58 [xmlDocfrag, 0, xmlDocfrag, 0], node 37 xmlDoctype":true +} From 9225fd4fbb6d070079806b73844093694fe5fdba Mon Sep 17 00:00:00 2001 From: Blake Kaplan Date: Tue, 3 Sep 2013 15:01:00 -0400 Subject: [PATCH 60/64] Bug 860123 - Use the right window's selection in some tests; r=ehsan --- editor/libeditor/base/tests/test_bug646194.xul | 3 ++- layout/base/tests/test_scroll_selection_into_view.html | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/editor/libeditor/base/tests/test_bug646194.xul b/editor/libeditor/base/tests/test_bug646194.xul index f3d6e854564..73532c1ce8b 100644 --- a/editor/libeditor/base/tests/test_bug646194.xul +++ b/editor/libeditor/base/tests/test_bug646194.xul @@ -35,11 +35,12 @@ function runTest() { var i = document.getElementById("i"); i.focus(); + var win = i.contentWindow; var doc = i.contentDocument; var t = doc.getElementById("t"); t.focus(); // put the caret at the end - getSelection().collapse(t.firstChild, 11); + win.getSelection().collapse(t.firstChild, 11); // Simulate pression Option+Delete on Mac // We do things this way because not every platform can invoke this diff --git a/layout/base/tests/test_scroll_selection_into_view.html b/layout/base/tests/test_scroll_selection_into_view.html index 75ac009dd42..760a08e760a 100644 --- a/layout/base/tests/test_scroll_selection_into_view.html +++ b/layout/base/tests/test_scroll_selection_into_view.html @@ -77,6 +77,7 @@ function testCollapsed(id, vPercent, startAt, expected) { var c = document.getElementById("c" + id); var target = document.getElementById("target" + id); if (target.contentDocument) { + selection = target.contentWindow.getSelection().QueryInterface(Components.interfaces.nsISelectionPrivate); target = target.contentDocument.getElementById("target" + id); } selection.collapse(target.parentNode, 0); From 1f3fb1cd20a35e80224a63fe97a7eb1ab8d86150 Mon Sep 17 00:00:00 2001 From: Dan Minor Date: Tue, 3 Sep 2013 15:13:38 -0400 Subject: [PATCH 61/64] Bug 912004 - DeviceManager pushDir should take a timeout parameter; r=wlach --- testing/mozbase/mozdevice/mozdevice/devicemanager.py | 2 +- testing/mozbase/mozdevice/mozdevice/devicemanagerSUT.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/testing/mozbase/mozdevice/mozdevice/devicemanager.py b/testing/mozbase/mozdevice/mozdevice/devicemanager.py index 47adcda6704..41facb6ba9c 100644 --- a/testing/mozbase/mozdevice/mozdevice/devicemanager.py +++ b/testing/mozbase/mozdevice/mozdevice/devicemanager.py @@ -175,7 +175,7 @@ class DeviceManager(object): """ @abstractmethod - def pushDir(self, localDirname, remoteDirname, retryLimit=1): + def pushDir(self, localDirname, remoteDirname, retryLimit=1, timeout=None): """ Push local directory from host to remote directory on the device, """ diff --git a/testing/mozbase/mozdevice/mozdevice/devicemanagerSUT.py b/testing/mozbase/mozdevice/mozdevice/devicemanagerSUT.py index 0d2995346fa..30291f54613 100644 --- a/testing/mozbase/mozdevice/mozdevice/devicemanagerSUT.py +++ b/testing/mozbase/mozdevice/mozdevice/devicemanagerSUT.py @@ -363,7 +363,7 @@ class DeviceManagerSUT(DeviceManager): if not self.dirExists(name): self._runCmds([{ 'cmd': 'mkdr ' + name }]) - def pushDir(self, localDir, remoteDir, retryLimit = None): + def pushDir(self, localDir, remoteDir, retryLimit=None, timeout=None): retryLimit = retryLimit or self.retryLimit self._logger.info("pushing directory: %s to %s" % (localDir, remoteDir)) From 46f281edd72fc50671422b6347f5623e48d66646 Mon Sep 17 00:00:00 2001 From: Ryan VanderMeulen Date: Tue, 3 Sep 2013 15:26:56 -0400 Subject: [PATCH 62/64] Bug 902248 - Disable test_nsINavHistoryViewer.js on OSX. --- toolkit/components/places/tests/unit/xpcshell.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/toolkit/components/places/tests/unit/xpcshell.ini b/toolkit/components/places/tests/unit/xpcshell.ini index 5bb6055b4de..aef823347aa 100644 --- a/toolkit/components/places/tests/unit/xpcshell.ini +++ b/toolkit/components/places/tests/unit/xpcshell.ini @@ -96,7 +96,7 @@ skip-if = os == "android" fail-if = os == "android" [test_multi_word_tags.js] [test_nsINavHistoryViewer.js] -skip-if = os == "win" +skip-if = os == "win" || os == "mac" [test_null_interfaces.js] [test_onItemChanged_tags.js] [test_placeURIs.js] From 4e713063a223a11b7e3c68209dd0c6e0fed0e2bf Mon Sep 17 00:00:00 2001 From: Steve Fink Date: Tue, 3 Sep 2013 12:25:05 -0700 Subject: [PATCH 63/64] Bug 912171 - Static rooting analysis: ignore ~AutoCompartment. r=NPOTB DONTBUILD --HG-- extra : rebase_source : 6e29cf2f844b76db662c35d4e4077d82622f48a1 --- js/src/devtools/rootAnalysis/annotations.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/js/src/devtools/rootAnalysis/annotations.js b/js/src/devtools/rootAnalysis/annotations.js index 9a118b6c582..b830a2817a1 100644 --- a/js/src/devtools/rootAnalysis/annotations.js +++ b/js/src/devtools/rootAnalysis/annotations.js @@ -138,6 +138,11 @@ var ignoreFunctions = { "PR_ErrorInstallTable" : true, "PR_SetThreadPrivate" : true, "JSObject* js::GetWeakmapKeyDelegate(JSObject*)" : true, // FIXME: mark with AutoAssertNoGC instead + + // These are a little overzealous -- these destructors *can* GC if they end + // up wrapping a pending exception. See bug 898815 for the heavyweight fix. + "void js::AutoCompartment::~AutoCompartment(int32)" : true, + "void JSAutoCompartment::~JSAutoCompartment(int32)" : true, }; function ignoreGCFunction(fun) From cf3b6bd95fbe348d061ca3acc020038079ec9e67 Mon Sep 17 00:00:00 2001 From: Ryan VanderMeulen Date: Tue, 3 Sep 2013 17:22:14 -0400 Subject: [PATCH 64/64] Backed out changeset 669d3fd3ea2b (bug 906877) for Mnw failures. --- dom/browser-element/BrowserElementPanning.js | 59 ++++++++++++++++++-- dom/ipc/TabChild.cpp | 24 +++++++- gfx/layers/composite/APZCTreeManager.cpp | 18 ++++++ gfx/layers/composite/APZCTreeManager.h | 16 ++++++ gfx/layers/ipc/AsyncPanZoomController.cpp | 57 +++++++++++++++++-- gfx/layers/ipc/AsyncPanZoomController.h | 26 +++++++++ layout/ipc/PRenderFrame.ipdl | 3 + layout/ipc/RenderFrameChild.cpp | 12 ++++ layout/ipc/RenderFrameChild.h | 3 + layout/ipc/RenderFrameParent.cpp | 18 ++++++ layout/ipc/RenderFrameParent.h | 3 + 11 files changed, 230 insertions(+), 9 deletions(-) diff --git a/dom/browser-element/BrowserElementPanning.js b/dom/browser-element/BrowserElementPanning.js index b74ddf7b1f1..4068e158fab 100644 --- a/dom/browser-element/BrowserElementPanning.js +++ b/dom/browser-element/BrowserElementPanning.js @@ -48,7 +48,7 @@ const ContentPanning = { // If we are using an AsyncPanZoomController for the parent frame, // it will handle subframe scrolling too. We don't need to listen for // these events. - if (!docShell.asyncPanZoomEnabled) { + if (!this._asyncPanZoomForViewportFrame) { let els = Cc["@mozilla.org/eventlistenerservice;1"] .getService(Ci.nsIEventListenerService); @@ -140,11 +140,23 @@ const ContentPanning = { let oldTarget = this.target; [this.target, this.scrollCallback] = this.getPannable(this.pointerDownTarget); - // If we have a pointer down target, we may need to fill in for EventStateManager - // in setting the active state on the target element. Set a timer to + // If we found a target, that means we have found a scrollable subframe. In + // this case, and if we are using async panning and zooming on the parent + // frame, inform the pan/zoom controller that it should not attempt to + // handle any touch events it gets until the next batch (meaning the next + // time we get a touch end). + if (this.target != null && this._asyncPanZoomForViewportFrame) { + this.detectingScrolling = true; + var os = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService); + os.notifyObservers(docShell, 'detect-scrollable-subframe', null); + } + + // If we have a pointer down target and we're not async + // pan/zooming, we may need to fill in for EventStateManager in + // setting the active state on the target element. Set a timer to // ensure the pointer-down target is active. (If it's already // active, the timer is a no-op.) - if (this.pointerDownTarget !== null) { + if (this.pointerDownTarget !== null && !this.detectingScrolling) { // If there's no possibility this is a drag/pan, activate now. // Otherwise wait a little bit to see if the gesture isn't a // tap. @@ -214,6 +226,12 @@ const ContentPanning = { this.pointerDownTarget = null; }, + // True when there's an async pan-zoom controll watching the + // outermost scrollable frame, and we're waiting to see whether + // we're going to take over from it and synchronously scroll an + // inner scrollable frame. + detectingScrolling: false, + onTouchMove: function cp_onTouchMove(evt) { if (!this.dragging) return; @@ -242,6 +260,27 @@ const ContentPanning = { } let isPan = KineticPanning.isPan(); + if (!isPan && this.detectingScrolling) { + // If panning distance is not large enough and we're waiting to + // see whether we should use the sync scroll fallback or not, + // don't attempt scrolling. + return; + } + + let isScroll = this.scrollCallback(delta.scale(-1)); + + if (this.detectingScrolling) { + this.detectingScrolling = false; + // Stop async-pan-zooming if the user is panning the subframe. + if (isScroll) { + // We're going to drive synchronously scrolling an inner frame. + Services.obs.notifyObservers(docShell, 'cancel-default-pan-zoom', null); + } else { + // Let AsyncPanZoomController handle the scrolling gesture. + this.scrollCallback = null; + return; + } + } // If we've detected a pan gesture, cancel the active state of the // current target. @@ -317,6 +356,13 @@ const ContentPanning = { node = node.parentNode; } + if (ContentPanning._asyncPanZoomForViewportFrame && + nodeContent === content) { + // The parent context is asynchronously panning and zooming our + // root scrollable frame, so don't use our synchronous fallback. + return null; + } + if (nodeContent.scrollMaxX || nodeContent.scrollMaxY) { return nodeContent; } @@ -438,6 +484,10 @@ const ContentPanning = { this._domUtils.setContentState(elt, kStateActive); }, + get _asyncPanZoomForViewportFrame() { + return docShell.asyncPanZoomEnabled; + }, + _recvViewportChange: function(data) { let metrics = data.json; this._viewport = new Rect(metrics.x, metrics.y, @@ -549,6 +599,7 @@ const ContentPanning = { _finishPanning: function() { this._resetActive(); this.dragging = false; + this.detectingScrolling = false; delete this.primaryPointerId; this._activationTimer.cancel(); diff --git a/dom/ipc/TabChild.cpp b/dom/ipc/TabChild.cpp index e6ec9fe67f2..2d0fe89a6c1 100644 --- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -105,8 +105,10 @@ NS_IMPL_ISUPPORTS1(ContentListener, nsIDOMEventListener) static const CSSSize kDefaultViewportSize(980, 480); +static const char CANCEL_DEFAULT_PAN_ZOOM[] = "cancel-default-pan-zoom"; static const char BROWSER_ZOOM_TO_RECT[] = "browser-zoom-to-rect"; static const char BEFORE_FIRST_PAINT[] = "before-first-paint"; +static const char DETECT_SCROLLABLE_SUBFRAME[] = "detect-scrollable-subframe"; static bool sCpowsEnabled = false; @@ -383,7 +385,13 @@ TabChild::Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *aData) { - if (!strcmp(aTopic, BROWSER_ZOOM_TO_RECT)) { + if (!strcmp(aTopic, CANCEL_DEFAULT_PAN_ZOOM)) { + nsCOMPtr docShell(do_QueryInterface(aSubject)); + nsCOMPtr tabChild(GetTabChildFrom(docShell)); + if (tabChild == this) { + mRemoteFrame->CancelDefaultPanZoom(); + } + } else if (!strcmp(aTopic, BROWSER_ZOOM_TO_RECT)) { nsCOMPtr docShell(do_QueryInterface(aSubject)); nsCOMPtr tabChild(GetTabChildFrom(docShell)); if (tabChild == this) { @@ -428,6 +436,12 @@ TabChild::Observe(nsISupports *aSubject, HandlePossibleViewportChange(); } } + } else if (!strcmp(aTopic, DETECT_SCROLLABLE_SUBFRAME)) { + nsCOMPtr docShell(do_QueryInterface(aSubject)); + nsCOMPtr tabChild(GetTabChildFrom(docShell)); + if (tabChild == this) { + mRemoteFrame->DetectScrollableSubframe(); + } } return NS_OK; @@ -2169,8 +2183,10 @@ TabChild::RecvDestroy() nsCOMPtr observerService = do_GetService(NS_OBSERVERSERVICE_CONTRACTID); + observerService->RemoveObserver(this, CANCEL_DEFAULT_PAN_ZOOM); observerService->RemoveObserver(this, BROWSER_ZOOM_TO_RECT); observerService->RemoveObserver(this, BEFORE_FIRST_PAINT); + observerService->RemoveObserver(this, DETECT_SCROLLABLE_SUBFRAME); const InfallibleTArray& idbActors = ManagedPIndexedDBChild(); @@ -2305,12 +2321,18 @@ TabChild::InitRenderingState() do_GetService(NS_OBSERVERSERVICE_CONTRACTID); if (observerService) { + observerService->AddObserver(this, + CANCEL_DEFAULT_PAN_ZOOM, + false); observerService->AddObserver(this, BROWSER_ZOOM_TO_RECT, false); observerService->AddObserver(this, BEFORE_FIRST_PAINT, false); + observerService->AddObserver(this, + DETECT_SCROLLABLE_SUBFRAME, + false); } // This state can't really change during the lifetime of the child. diff --git a/gfx/layers/composite/APZCTreeManager.cpp b/gfx/layers/composite/APZCTreeManager.cpp index f93bf2b792e..11fd90aba66 100644 --- a/gfx/layers/composite/APZCTreeManager.cpp +++ b/gfx/layers/composite/APZCTreeManager.cpp @@ -360,6 +360,24 @@ APZCTreeManager::UpdateCompositionBounds(const ScrollableLayerGuid& aGuid, } } +void +APZCTreeManager::CancelDefaultPanZoom(const ScrollableLayerGuid& aGuid) +{ + nsRefPtr apzc = GetTargetAPZC(aGuid); + if (apzc) { + apzc->CancelDefaultPanZoom(); + } +} + +void +APZCTreeManager::DetectScrollableSubframe(const ScrollableLayerGuid& aGuid) +{ + nsRefPtr apzc = GetTargetAPZC(aGuid); + if (apzc) { + apzc->DetectScrollableSubframe(); + } +} + void APZCTreeManager::ZoomToRect(const ScrollableLayerGuid& aGuid, const CSSRect& aRect) diff --git a/gfx/layers/composite/APZCTreeManager.h b/gfx/layers/composite/APZCTreeManager.h index 2021a6809bf..23e414bef56 100644 --- a/gfx/layers/composite/APZCTreeManager.h +++ b/gfx/layers/composite/APZCTreeManager.h @@ -168,6 +168,22 @@ public: void UpdateCompositionBounds(const ScrollableLayerGuid& aGuid, const ScreenIntRect& aCompositionBounds); + /** + * We are scrolling a subframe, so disable our machinery until we hit + * a touch end or a new touch start. This prevents us from accidentally + * panning both the subframe and the parent frame. + * + * XXX/bug 775452: We should eventually be supporting async scrollable + * subframes. + */ + void CancelDefaultPanZoom(const ScrollableLayerGuid& aGuid); + + /** + * We have found a scrollable subframe, so we need to delay the scrolling + * gesture executed and let subframe do the scrolling first. + */ + void DetectScrollableSubframe(const ScrollableLayerGuid& aGuid); + /** * Kicks an animation to zoom to a rect. This may be either a zoom out or zoom * in. The actual animation is done on the compositor thread after being set diff --git a/gfx/layers/ipc/AsyncPanZoomController.cpp b/gfx/layers/ipc/AsyncPanZoomController.cpp index ca3d74d1552..4ca926ef10f 100644 --- a/gfx/layers/ipc/AsyncPanZoomController.cpp +++ b/gfx/layers/ipc/AsyncPanZoomController.cpp @@ -212,7 +212,9 @@ AsyncPanZoomController::AsyncPanZoomController(uint64_t aLayersId, mLastAsyncScrollOffset(0, 0), mCurrentAsyncScrollOffset(0, 0), mAsyncScrollTimeoutTask(nullptr), - mHandlingTouchQueue(false) + mDisableNextTouchBatch(false), + mHandlingTouchQueue(false), + mDelayPanning(false) { MOZ_COUNT_CTOR(AsyncPanZoomController); @@ -310,12 +312,29 @@ nsEventStatus AsyncPanZoomController::HandleInputEvent(const InputData& aEvent) nsEventStatus rv = nsEventStatus_eIgnore; nsRefPtr listener = GetGestureEventListener(); - if (listener) { + if (listener && !mDisableNextTouchBatch) { rv = listener->HandleInputEvent(aEvent); if (rv == nsEventStatus_eConsumeNoDefault) return rv; } + if (mDelayPanning && aEvent.mInputType == MULTITOUCH_INPUT) { + const MultiTouchInput& multiTouchInput = aEvent.AsMultiTouchInput(); + if (multiTouchInput.mType == MultiTouchInput::MULTITOUCH_MOVE) { + // Let BrowserElementScrolling perform panning gesture first. + SetState(WAITING_LISTENERS); + mTouchQueue.AppendElement(multiTouchInput); + + if (!mTouchListenerTimeoutTask) { + mTouchListenerTimeoutTask = + NewRunnableMethod(this, &AsyncPanZoomController::TimeoutTouchListeners); + + PostDelayedTask(mTouchListenerTimeoutTask, gTouchListenerTimeout); + } + return nsEventStatus_eConsumeNoDefault; + } + } + switch (aEvent.mInputType) { case MULTITOUCH_INPUT: { const MultiTouchInput& multiTouchInput = aEvent.AsMultiTouchInput(); @@ -397,6 +416,10 @@ nsEventStatus AsyncPanZoomController::OnTouchStart(const MultiTouchInput& aEvent } nsEventStatus AsyncPanZoomController::OnTouchMove(const MultiTouchInput& aEvent) { + if (mDisableNextTouchBatch) { + return nsEventStatus_eIgnore; + } + switch (mState) { case FLING: case NOTHING: @@ -436,6 +459,11 @@ nsEventStatus AsyncPanZoomController::OnTouchMove(const MultiTouchInput& aEvent) } nsEventStatus AsyncPanZoomController::OnTouchEnd(const MultiTouchInput& aEvent) { + if (mDisableNextTouchBatch) { + mDisableNextTouchBatch = false; + return nsEventStatus_eIgnore; + } + { ReentrantMonitorAutoEnter lock(mMonitor); SendAsyncScrollEvent(); @@ -1157,6 +1185,18 @@ void AsyncPanZoomController::UpdateCompositionBounds(const ScreenIntRect& aCompo } } +void AsyncPanZoomController::CancelDefaultPanZoom() { + mDisableNextTouchBatch = true; + nsRefPtr listener = GetGestureEventListener(); + if (listener) { + listener->CancelGesture(); + } +} + +void AsyncPanZoomController::DetectScrollableSubframe() { + mDelayPanning = true; +} + void AsyncPanZoomController::ZoomToRect(CSSRect aRect) { SetState(ANIMATING_ZOOM); @@ -1236,7 +1276,7 @@ void AsyncPanZoomController::ZoomToRect(CSSRect aRect) { } void AsyncPanZoomController::ContentReceivedTouch(bool aPreventDefault) { - if (!mFrameMetrics.mMayHaveTouchListeners) { + if (!mFrameMetrics.mMayHaveTouchListeners && !mDelayPanning) { mTouchQueue.Clear(); return; } @@ -1248,12 +1288,21 @@ void AsyncPanZoomController::ContentReceivedTouch(bool aPreventDefault) { if (mState == WAITING_LISTENERS) { if (!aPreventDefault) { - SetState(NOTHING); + // Delayed scrolling gesture is pending at TOUCHING state. + if (mDelayPanning) { + SetState(TOUCHING); + } else { + SetState(NOTHING); + } } mHandlingTouchQueue = true; while (!mTouchQueue.IsEmpty()) { + // we need to reset mDelayPanning before handling scrolling gesture. + if (!aPreventDefault && mTouchQueue[0].mType == MultiTouchInput::MULTITOUCH_MOVE) { + mDelayPanning = false; + } if (!aPreventDefault) { HandleInputEvent(mTouchQueue[0]); } diff --git a/gfx/layers/ipc/AsyncPanZoomController.h b/gfx/layers/ipc/AsyncPanZoomController.h index f89be4cd043..ccbe13beab8 100644 --- a/gfx/layers/ipc/AsyncPanZoomController.h +++ b/gfx/layers/ipc/AsyncPanZoomController.h @@ -109,6 +109,22 @@ public: */ void UpdateCompositionBounds(const ScreenIntRect& aCompositionBounds); + /** + * We are scrolling a subframe, so disable our machinery until we hit + * a touch end or a new touch start. This prevents us from accidentally + * panning both the subframe and the parent frame. + * + * XXX/bug 775452: We should eventually be supporting async scrollable + * subframes. + */ + void CancelDefaultPanZoom(); + + /** + * We have found a scrollable subframe, so we need to delay the scrolling + * gesture executed and let subframe do the scrolling first. + */ + void DetectScrollableSubframe(); + /** * Kicks an animation to zoom to a rect. This may be either a zoom out or zoom * in. The actual animation is done on the compositor thread after being set @@ -564,12 +580,22 @@ private: // ensures the last mozbrowserasyncscroll event is always been fired. CancelableTask* mAsyncScrollTimeoutTask; + // Flag used to determine whether or not we should disable handling of the + // next batch of touch events. This is used for sync scrolling of subframes. + bool mDisableNextTouchBatch; + // Flag used to determine whether or not we should try to enter the // WAITING_LISTENERS state. This is used in the case that we are processing a // queued up event block. If set, this means that we are handling this queue // and we don't want to queue the events back up again. bool mHandlingTouchQueue; + // Flag used to determine whether or not we should try scrolling by + // BrowserElementScrolling first. If set, we delay delivering + // touchmove events to GestureListener until BrowserElementScrolling + // decides whether it wants to handle panning for this touch series. + bool mDelayPanning; + friend class Axis; /* The functions and members in this section are used to build a tree diff --git a/layout/ipc/PRenderFrame.ipdl b/layout/ipc/PRenderFrame.ipdl index cc6e57a24c3..f0f5ce6b2c8 100644 --- a/layout/ipc/PRenderFrame.ipdl +++ b/layout/ipc/PRenderFrame.ipdl @@ -45,6 +45,9 @@ parent: async NotifyCompositorTransaction(); + async CancelDefaultPanZoom(); + async DetectScrollableSubframe(); + async UpdateHitRegion(nsRegion aRegion); async __delete__(); diff --git a/layout/ipc/RenderFrameChild.cpp b/layout/ipc/RenderFrameChild.cpp index 7e091338b05..5130fcc4f6e 100644 --- a/layout/ipc/RenderFrameChild.cpp +++ b/layout/ipc/RenderFrameChild.cpp @@ -32,6 +32,18 @@ RenderFrameChild::Destroy() // WARNING: |this| is dead, hands off } +void +RenderFrameChild::CancelDefaultPanZoom() +{ + SendCancelDefaultPanZoom(); +} + +void +RenderFrameChild::DetectScrollableSubframe() +{ + SendDetectScrollableSubframe(); +} + PLayerTransactionChild* RenderFrameChild::AllocPLayerTransactionChild() { diff --git a/layout/ipc/RenderFrameChild.h b/layout/ipc/RenderFrameChild.h index aa63b32bfd8..55cd1fd80a4 100644 --- a/layout/ipc/RenderFrameChild.h +++ b/layout/ipc/RenderFrameChild.h @@ -19,6 +19,9 @@ public: RenderFrameChild() {} virtual ~RenderFrameChild() {} + void CancelDefaultPanZoom(); + void DetectScrollableSubframe(); + void Destroy(); protected: diff --git a/layout/ipc/RenderFrameParent.cpp b/layout/ipc/RenderFrameParent.cpp index a916b3801ba..b9ff7690759 100644 --- a/layout/ipc/RenderFrameParent.cpp +++ b/layout/ipc/RenderFrameParent.cpp @@ -846,6 +846,24 @@ RenderFrameParent::RecvNotifyCompositorTransaction() return true; } +bool +RenderFrameParent::RecvCancelDefaultPanZoom() +{ + if (GetApzcTreeManager()) { + GetApzcTreeManager()->CancelDefaultPanZoom(ScrollableLayerGuid(mLayersId)); + } + return true; +} + +bool +RenderFrameParent::RecvDetectScrollableSubframe() +{ + if (GetApzcTreeManager()) { + GetApzcTreeManager()->DetectScrollableSubframe(ScrollableLayerGuid(mLayersId)); + } + return true; +} + bool RenderFrameParent::RecvUpdateHitRegion(const nsRegion& aRegion) { diff --git a/layout/ipc/RenderFrameParent.h b/layout/ipc/RenderFrameParent.h index c0678bf2404..b83bf2ebc34 100644 --- a/layout/ipc/RenderFrameParent.h +++ b/layout/ipc/RenderFrameParent.h @@ -117,6 +117,9 @@ protected: virtual bool RecvNotifyCompositorTransaction() MOZ_OVERRIDE; + virtual bool RecvCancelDefaultPanZoom() MOZ_OVERRIDE; + virtual bool RecvDetectScrollableSubframe() MOZ_OVERRIDE; + virtual bool RecvUpdateHitRegion(const nsRegion& aRegion) MOZ_OVERRIDE; virtual PLayerTransactionParent* AllocPLayerTransactionParent() MOZ_OVERRIDE;