diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 51979e86..875684e4 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -22,25 +22,11 @@ jobs: go-version: ^1.23 id: go - - uses: pnpm/action-setup@v4 - name: Install pnpm - with: - version: 9 - run_install: false - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: '21' - cache: 'pnpm' - cache-dependency-path: ui/pnpm-lock.yaml + - name: Install XSLT tools + run: sudo apt-get update && sudo apt-get install -y python3-lxml - name: Build run: make build - - name: Test UI - run: make testui - - name: TestGO run: make testgo - diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index bc7d26f0..06c5c3e1 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -20,11 +20,8 @@ jobs: go-version: ^1.23 id: go - - uses: pnpm/action-setup@v4 - name: Install pnpm - with: - version: 9 - run_install: false + - name: Install XSLT tools + run: sudo apt-get update && sudo apt-get install -y python3-lxml - name: Build run: make all diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..3cb2c2ed --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "third_party/librm_lines"] + path = third_party/librm_lines + url = https://github.com/RedTTGMoss/librm_lines.git diff --git a/Dockerfile b/Dockerfile index 2ae0b5ae..8fd36442 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,22 +1,8 @@ ARG VERSION=0.0.0 -FROM --platform=$BUILDPLATFORM node:lts AS uibuilder -ENV PNPM_HOME="/pnpm" -ENV PATH="$PNPM_HOME:$PATH" -RUN corepack enable pnpm && corepack install -g pnpm@latest-9 - -WORKDIR /src -#COPY ui/package.json ui/pnpm-lock.yaml /src -#RUN pnpm fetch - -COPY ui . -RUN pnpm install && pnpm build - FROM golang:bookworm AS gobuilder ARG VERSION WORKDIR /src COPY . . -COPY --from=uibuilder /src/dist ./ui/dist -#RUN apk add git RUN go generate ./... && CGO_ENABLED=0 go build -ldflags "-s -w -X main.version=${VERSION}" -o rmfakecloud-docker ./cmd/rmfakecloud/ FROM scratch diff --git a/Makefile b/Makefile index 5bacdfab..30808b02 100644 --- a/Makefile +++ b/Makefile @@ -1,19 +1,17 @@ -VERSION :=$(shell git describe --tags --always) +VERSION := $(shell date +%Y.%m.%d.%H%M%S) LDFLAGS := "-s -w -X main.version=$(VERSION)" OUT_DIR := dist CMD := ./cmd/rmfakecloud BINARY := rmfakecloud -BUILD = go build -ldflags $(LDFLAGS) -o $(@) $(CMD) -ASSETS = ui/dist +BUILD = go build -ldflags $(LDFLAGS) -o $(@) $(CMD) GOFILES := $(shell find . -iname '*.go' ! -iname "*_test.go") -GOFILES += $(ASSETS) -UIFILES := $(shell find ui/src) -UIFILES += $(shell find ui/public) -UIFILES += ui/package.json +STATICFILES := $(shell find internal/ui/static -type f 2>/dev/null) +THEMEFILES := $(shell find internal/ui/themes -type f 2>/dev/null) +GOFILES += $(STATICFILES) +GOFILES += $(THEMEFILES) TARGETS := $(addprefix $(OUT_DIR)/$(BINARY)-, x64 armv6 armv7 arm64 win64 docker) -PNPM = cd ui; pnpm -.PHONY: all run runui clean test testgo testui +.PHONY: all run clean test testgo build build: $(OUT_DIR)/$(BINARY)-x64 @@ -39,36 +37,14 @@ $(OUT_DIR)/$(BINARY)-docker:$(GOFILES) container: $(OUT_DIR)/$(BINARY)-docker docker build -t rmfakecloud -f Dockerfile.make . - -run: $(ASSETS) - go run $(CMD) $(ARG) - -$(ASSETS): $(UIFILES) ui/pnpm-lock.yaml - #@cp ui/node_modules/pdfjs-dist/build/pdf.worker.js ui/public/ - $(PNPM) build - @#remove unneeded stuff, todo: eject - @rm ui/build/service-worker.js ui/build/precache-manifest* ui/build/asset-manifest.json 2> /dev/null || true - -ui/pnpm-lock.yaml: ui/node_modules ui/package.json - $(PNPM) i - @touch -mr $(shell ls -Atd $? | head -1) $@ - -ui/node_modules: - mkdir -p $@ -runui: ui/pnpm-lock.yaml - $(PNPM) run dev +run: + go run $(CMD) $(ARG) clean: rm -f $(OUT_DIR)/* - rm -fr $(ASSETS) - -test: testui testgo -testui: - echo "TODO: fix this" - #CI=true $(PNPM) test +test: testgo testgo: go test ./... - diff --git a/docs/install/configuration.md b/docs/install/configuration.md index f90466a8..697d6194 100644 --- a/docs/install/configuration.md +++ b/docs/install/configuration.md @@ -12,6 +12,11 @@ The configuration is made through environment variables. | `RM_HTTPS_COOKIE` | For the UI, force cookies to be available only via https | | `RM_TRUST_PROXY` | Trust the proxy for client ip addresses (X-Forwarded-For/X-Real-IP) default false | | `HASH_SCHEMA_VERSION` | Hash tree schema version: "3" or "4" (default: 3) | +| `RMFAKECLOUD_WEBAUTHN` | Enable **passkeys** (WebAuthn) for the web UI (default: `false`). Additive to password login. Requires a real HTTPS browser origin (not `http://hostname:port` or raw IPs). | +| `RMFAKECLOUD_WEBAUTHN_RPID` | Relying Party ID — hostname without scheme or port (e.g. `www.example.com`). If empty and `STORAGE_URL` is `https://…`, derived from that host. | +| `RMFAKECLOUD_WEBAUTHN_ORIGINS` | Comma-separated allowed origins (e.g. `https://www.example.com:3000`). If empty and `STORAGE_URL` is `https://…`, derived as a single origin from it. | + +Manual verification steps: [passkeys checklist](passkeys-checklist.md). ## Handwriting recognition diff --git a/docs/install/passkeys-checklist.md b/docs/install/passkeys-checklist.md new file mode 100644 index 00000000..9b5f5491 --- /dev/null +++ b/docs/install/passkeys-checklist.md @@ -0,0 +1,11 @@ +# Passkeys (WebAuthn) — manual checklist + +Requires `RMFAKECLOUD_WEBAUTHN=true` and HTTPS origin matching `RMFAKECLOUD_WEBAUTHN_RPID` / `ORIGINS` (or derived from https `STORAGE_URL`). + +1. Open the web UI over HTTPS (not `http://acorn:3000` / raw IP). +2. Sign in with email/password. +3. Profile → **Passkeys** → Add passkey (optional label). Complete browser/OS prompt. +4. Sign out. Login page should show **Sign in with passkey**. +5. Use passkey to sign in; land on Documents; cookie/JWT works as usual. +6. Confirm password login still works. +7. Profile → remove passkey; optional: set `RMFAKECLOUD_WEBAUTHN=false` and restart → status/`Passkeys` UI hidden, login button gone. diff --git a/go.mod b/go.mod index 65d8dffa..74bd1628 100644 --- a/go.mod +++ b/go.mod @@ -5,13 +5,17 @@ go 1.23.3 toolchain go1.24.1 require ( + github.com/antchfx/xmlquery v1.4.4 github.com/apognu/gocal v0.9.1 github.com/danjacques/gofslock v0.0.0-20240212154529-d899e02bfe22 github.com/dropbox/dropbox-sdk-go-unofficial/v6 v6.0.5 + github.com/fogleman/gg v1.3.0 github.com/gin-gonic/gin v1.9.1 + github.com/go-webauthn/webauthn v0.11.2 github.com/golang-jwt/jwt/v4 v4.5.2 github.com/google/uuid v1.6.0 github.com/gorilla/websocket v1.5.1 + github.com/jung-kurt/gofpdf v1.16.2 github.com/juruen/rmapi v0.0.25 github.com/mochi-mqtt/server/v2 v2.7.9 github.com/poundifdef/go-remarkable2pdf v0.2.0 @@ -30,24 +34,30 @@ require ( github.com/adrg/strutil v0.3.1 // indirect github.com/adrg/sysfont v0.1.2 // indirect github.com/adrg/xdg v0.4.0 // indirect + github.com/antchfx/xpath v1.3.4 // indirect github.com/bytedance/sonic v1.11.3 // indirect github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect github.com/chenzhuoyu/iasm v0.9.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/gabriel-vasile/mimetype v1.4.3 // indirect github.com/gin-contrib/sse v0.1.0 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/validator/v10 v10.19.0 // indirect + github.com/go-webauthn/x v0.1.14 // indirect github.com/goccy/go-json v0.10.2 // indirect + github.com/golang-jwt/jwt/v5 v5.2.1 // indirect + github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.4 // indirect - github.com/google/go-cmp v0.6.0 // indirect + github.com/google/go-tpm v0.9.1 // indirect github.com/gorilla/i18n v0.0.0-20150820051429-8b358169da46 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/jung-kurt/gofpdf v1.16.2 // indirect github.com/klauspost/cpuid/v2 v2.2.7 // indirect github.com/leodido/go-urn v1.4.0 // indirect github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect @@ -62,6 +72,7 @@ require ( github.com/unidoc/timestamp v0.0.0-20200412005513-91597fd3793a // indirect github.com/unidoc/unichart v0.3.0 // indirect github.com/unidoc/unitype v0.4.0 // indirect + github.com/x448/float16 v0.8.4 // indirect golang.org/x/arch v0.7.0 // indirect golang.org/x/image v0.18.0 // indirect golang.org/x/net v0.38.0 // indirect diff --git a/go.sum b/go.sum index c3e2fdd0..7c8d416a 100644 --- a/go.sum +++ b/go.sum @@ -43,6 +43,11 @@ github.com/adrg/sysfont v0.1.2/go.mod h1:6d3l7/BSjX9VaeXWJt9fcrftFaD/t7l11xgSywC github.com/adrg/xdg v0.3.0/go.mod h1:7I2hH/IT30IsupOpKZ5ue7/qNi3CoKzD6tL3HwpaRMQ= github.com/adrg/xdg v0.4.0 h1:RzRqFcjH4nE5C6oTAxhBtoE2IRyjBSa62SCbyPidvls= github.com/adrg/xdg v0.4.0/go.mod h1:N6ag73EX4wyxeaoeHctc1mas01KZgsj5tYiAIwqJE/E= +github.com/antchfx/xmlquery v1.4.4 h1:mxMEkdYP3pjKSftxss4nUHfjBhnMk4imGoR96FRY2dg= +github.com/antchfx/xmlquery v1.4.4/go.mod h1:AEPEEPYE9GnA2mj5Ur2L5Q5/2PycJ0N9Fusrx9b12fc= +github.com/antchfx/xpath v1.3.3/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs= +github.com/antchfx/xpath v1.3.4 h1:1ixrW1VnXd4HurCj7qnqnR0jo14g8JMe20Fshg1Vgz4= +github.com/antchfx/xpath v1.3.4/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs= github.com/apognu/gocal v0.9.1 h1:e3vlb+YV5wXvqBxYsC6GvkuUAEnRipkvoA1P79gwspM= github.com/apognu/gocal v0.9.1/go.mod h1:5tNvJsQGJHwS3KqWxHAFZzavC4k42jrJ3ouVmOzS/AM= github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= @@ -76,6 +81,10 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/fogleman/gg v1.3.0 h1:/7zJX8F6AaYQc57WQCyN9cAIz+4bCJGO9B+dyW29am8= +github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= +github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= +github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= @@ -93,14 +102,24 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= github.com/go-playground/validator/v10 v10.19.0 h1:ol+5Fu+cSq9JD7SoSqe04GMI92cbn0+wvQ3bZ8b/AU4= github.com/go-playground/validator/v10 v10.19.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= +github.com/go-webauthn/webauthn v0.11.2 h1:Fgx0/wlmkClTKlnOsdOQ+K5HcHDsDcYIvtYmfhEOSUc= +github.com/go-webauthn/webauthn v0.11.2/go.mod h1:aOtudaF94pM71g3jRwTYYwQTG1KyTILTcZqN1srkmD0= +github.com/go-webauthn/x v0.1.14 h1:1wrB8jzXAofojJPAaRxnZhRgagvLGnLjhCAwg3kTpT0= +github.com/go-webauthn/x v0.1.14/go.mod h1:UuVvFZ8/NbOnkDz3y1NaxtUN87pmtpC1PQ+/5BBQRdc= github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/golang-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXeUI= github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= +github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g= +github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= @@ -137,6 +156,8 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-tpm v0.9.1 h1:0pGc4X//bAlmZzMKf8iz6IsDo1nYTbYJ6FZN/rg4zdM= +github.com/google/go-tpm v0.9.1/go.mod h1:h9jEsEECg7gtLis0upRBQU+GhYVH6jMjrFxI8u6bVUY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= @@ -186,6 +207,8 @@ github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mochi-mqtt/server/v2 v2.7.9 h1:y0g4vrSLAag7T07l2oCzOa/+nKVLoazKEWAArwqBNYI= github.com/mochi-mqtt/server/v2 v2.7.9/go.mod h1:lZD3j35AVNqJL5cezlnSkuG05c0FCHSsfAKSPBOSbqc= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -251,6 +274,8 @@ github.com/unidoc/unipdf/v3 v3.56.0 h1:15Lt+AZvELP03PH23ypV0y5reKZxCRKSq46SZg+vx github.com/unidoc/unipdf/v3 v3.56.0/go.mod h1:iBr/OsbLnJ49WhJlpfpYS3VmXrkTG05O7rKe9crppmc= github.com/unidoc/unitype v0.4.0 h1:/TMZ3wgwfWWX64mU5x2O9no9UmoBqYCB089LYYqHyQQ= github.com/unidoc/unitype v0.4.0/go.mod h1:HV5zuUeqMKA4QgYQq3KDlJY/P96XF90BQB+6czK6LVA= +github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= +github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -270,6 +295,10 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= +golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -308,6 +337,10 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -337,6 +370,12 @@ golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -357,6 +396,11 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -394,10 +438,22 @@ golang.org/x/sys v0.0.0-20220731174439-a90be440212d/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= +golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= +golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -406,6 +462,12 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -453,6 +515,9 @@ golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20201223200349-f6952e403d3f/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/internal/app/app.go b/internal/app/app.go index d1fbeb92..d1525643 100644 --- a/internal/app/app.go +++ b/internal/app/app.go @@ -140,6 +140,7 @@ func NewApp(cfg *config.Config) App { pcStore := passcodestore.NewInMemory() codeConnector := NewCodeConnector() router := gin.Default() + router.Use(compressionMiddleware()) // corsConfig := cors.DefaultConfig() diff --git a/internal/app/codeconnector.go b/internal/app/codeconnector.go index 0a782225..ba4d12ed 100644 --- a/internal/app/codeconnector.go +++ b/internal/app/codeconnector.go @@ -22,6 +22,9 @@ type CodeConnector interface { //NewCode generates one time code for a user NewCode(uid string) (code string, err error) + //CurrentCode returns the outstanding pairing code for a user, if any. + CurrentCode(uid string) (code string, ok bool) + //ConsumeCode a code and returns the uid if ofound ConsumeCode(code string) (uid string, err error) } @@ -50,14 +53,24 @@ func (conn *inMemoryCodeConnector) NewCode(uid string) (string, error) { conn.lock.Unlock() go func() { <-time.After(conn.codeValidity) - if _, err := conn.ConsumeCode(code); err == nil { + conn.lock.Lock() + defer conn.lock.Unlock() + if cur, ok := conn.uids[uid]; ok && cur == code { + delete(conn.dict, code) + delete(conn.uids, uid) log.Infof("removed unused code: %s for uid: %s ", code, uid) } - }() return code, nil } +func (conn *inMemoryCodeConnector) CurrentCode(uid string) (string, bool) { + conn.lock.Lock() + defer conn.lock.Unlock() + code, ok := conn.uids[uid] + return code, ok +} + var letters = []rune("abcdefghijklmnopqrstuvwxyz") func randSeq(n int) (string, error) { diff --git a/internal/app/codeconnector_test.go b/internal/app/codeconnector_test.go index 7c83f886..5910f1b2 100644 --- a/internal/app/codeconnector_test.go +++ b/internal/app/codeconnector_test.go @@ -13,6 +13,11 @@ func TestGenerateCode(t *testing.T) { t.Error(err) } + cur, ok := u.CurrentCode("test") + if !ok || cur != code { + t.Fatalf("CurrentCode = %q,%v want %q,true", cur, ok, code) + } + uid, err := u.ConsumeCode(code) if err != nil { t.Error(err) @@ -22,4 +27,7 @@ func TestGenerateCode(t *testing.T) { t.Fail() } + if _, ok := u.CurrentCode("test"); ok { + t.Fatal("CurrentCode should be empty after consume") + } } diff --git a/internal/app/compression.go b/internal/app/compression.go new file mode 100644 index 00000000..16255aee --- /dev/null +++ b/internal/app/compression.go @@ -0,0 +1,132 @@ +package app + +import ( + "compress/gzip" + "compress/zlib" + "io" + "net/http" + "path/filepath" + "strings" + "sync" + + "github.com/gin-gonic/gin" +) + +// HTTP uses gzip Content-Encoding (DEFLATE / zlib). Request bodies may also +// arrive as Content-Encoding: gzip, deflate, or zlib. + +var gzipWriterPool = sync.Pool{ + New: func() any { + w, err := gzip.NewWriterLevel(io.Discard, gzip.DefaultCompression) + if err != nil { + panic(err) + } + return w + }, +} + +var compressedExt = map[string]bool{ + ".png": true, ".jpg": true, ".jpeg": true, ".gif": true, + ".webp": true, ".ico": true, ".wasm": true, ".zip": true, + ".gz": true, ".br": true, ".pdf": true, ".mp4": true, + ".woff": true, ".woff2": true, +} + +type gzipResponseWriter struct { + gin.ResponseWriter + writer *gzip.Writer +} + +func (w *gzipResponseWriter) Write(data []byte) (int, error) { + w.Header().Del("Content-Length") + return w.writer.Write(data) +} + +func (w *gzipResponseWriter) WriteString(s string) (int, error) { + w.Header().Del("Content-Length") + return w.writer.Write([]byte(s)) +} + +func (w *gzipResponseWriter) WriteHeader(code int) { + w.Header().Del("Content-Length") + w.ResponseWriter.WriteHeader(code) +} + +func (w *gzipResponseWriter) Flush() { + _ = w.writer.Flush() + if f, ok := w.ResponseWriter.(http.Flusher); ok { + f.Flush() + } +} + +// compressionMiddleware compresses responses with gzip (zlib DEFLATE) when the +// client advertises Accept-Encoding: gzip, and decompresses gzip/deflate/zlib +// request bodies. Always continues the handler chain. +func compressionMiddleware() gin.HandlerFunc { + return func(c *gin.Context) { + if err := decompressRequestBody(c); err != nil { + c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "invalid compressed request body"}) + return + } + + if shouldGzipResponse(c.Request) { + gz := gzipWriterPool.Get().(*gzip.Writer) + defer gzipWriterPool.Put(gz) + defer gz.Reset(io.Discard) + + gz.Reset(c.Writer) + c.Header("Content-Encoding", "gzip") + c.Writer.Header().Add("Vary", "Accept-Encoding") + c.Writer = &gzipResponseWriter{ResponseWriter: c.Writer, writer: gz} + defer func() { _ = gz.Close() }() + } + + c.Next() + } +} + +func shouldGzipResponse(req *http.Request) bool { + if !strings.Contains(req.Header.Get("Accept-Encoding"), "gzip") { + return false + } + if strings.Contains(strings.ToLower(req.Header.Get("Connection")), "upgrade") { + return false + } + if strings.Contains(req.Header.Get("Accept"), "text/event-stream") { + return false + } + ext := strings.ToLower(filepath.Ext(req.URL.Path)) + return !compressedExt[ext] +} + +func decompressRequestBody(c *gin.Context) error { + if c.Request.Body == nil { + return nil + } + enc := strings.ToLower(strings.TrimSpace(c.GetHeader("Content-Encoding"))) + if enc == "" || enc == "identity" { + return nil + } + + var ( + r io.ReadCloser + err error + ) + switch enc { + case "gzip": + r, err = gzip.NewReader(c.Request.Body) + case "deflate", "zlib": + r, err = zlib.NewReader(c.Request.Body) + default: + // Leave unknown encodings (e.g. br) for handlers / proxies. + return nil + } + if err != nil { + return err + } + + c.Request.Body = r + c.Request.Header.Del("Content-Encoding") + c.Request.Header.Del("Content-Length") + return nil +} diff --git a/internal/app/compression_test.go b/internal/app/compression_test.go new file mode 100644 index 00000000..805f6233 --- /dev/null +++ b/internal/app/compression_test.go @@ -0,0 +1,105 @@ +package app + +import ( + "bytes" + "compress/gzip" + "compress/zlib" + "io" + "net/http" + "net/http/httptest" + "testing" + + "github.com/gin-gonic/gin" + "github.com/stretchr/testify/require" +) + +func TestCompressionMiddlewareGzipResponse(t *testing.T) { + gin.SetMode(gin.TestMode) + r := gin.New() + r.Use(compressionMiddleware()) + r.GET("/ping", func(c *gin.Context) { + c.String(http.StatusOK, "hello-compression") + }) + + req := httptest.NewRequest(http.MethodGet, "/ping", nil) + req.Header.Set("Accept-Encoding", "gzip") + w := httptest.NewRecorder() + r.ServeHTTP(w, req) + + require.Equal(t, http.StatusOK, w.Code) + require.Equal(t, "gzip", w.Header().Get("Content-Encoding")) + + gr, err := gzip.NewReader(w.Body) + require.NoError(t, err) + defer gr.Close() + body, err := io.ReadAll(gr) + require.NoError(t, err) + require.Equal(t, "hello-compression", string(body)) +} + +func TestCompressionMiddlewarePassthroughWithoutAccept(t *testing.T) { + gin.SetMode(gin.TestMode) + r := gin.New() + r.Use(compressionMiddleware()) + r.GET("/ping", func(c *gin.Context) { + c.String(http.StatusOK, "plain") + }) + + req := httptest.NewRequest(http.MethodGet, "/ping", nil) + w := httptest.NewRecorder() + r.ServeHTTP(w, req) + + require.Equal(t, http.StatusOK, w.Code) + require.Empty(t, w.Header().Get("Content-Encoding")) + require.Equal(t, "plain", w.Body.String()) +} + +func TestDecompressRequestGzip(t *testing.T) { + gin.SetMode(gin.TestMode) + r := gin.New() + r.Use(compressionMiddleware()) + r.POST("/echo", func(c *gin.Context) { + b, err := io.ReadAll(c.Request.Body) + require.NoError(t, err) + c.String(http.StatusOK, string(b)) + }) + + var buf bytes.Buffer + zw := gzip.NewWriter(&buf) + _, err := zw.Write([]byte("gzip-body")) + require.NoError(t, err) + require.NoError(t, zw.Close()) + + req := httptest.NewRequest(http.MethodPost, "/echo", &buf) + req.Header.Set("Content-Encoding", "gzip") + w := httptest.NewRecorder() + r.ServeHTTP(w, req) + + require.Equal(t, http.StatusOK, w.Code) + require.Equal(t, "gzip-body", w.Body.String()) +} + +func TestDecompressRequestZlib(t *testing.T) { + gin.SetMode(gin.TestMode) + r := gin.New() + r.Use(compressionMiddleware()) + r.POST("/echo", func(c *gin.Context) { + b, err := io.ReadAll(c.Request.Body) + require.NoError(t, err) + c.String(http.StatusOK, string(b)) + }) + + var buf bytes.Buffer + zw := zlib.NewWriter(&buf) + _, err := zw.Write([]byte("zlib-body")) + require.NoError(t, err) + require.NoError(t, zw.Close()) + + req := httptest.NewRequest(http.MethodPost, "/echo", &buf) + req.Header.Set("Content-Encoding", "zlib") + w := httptest.NewRecorder() + r.ServeHTTP(w, req) + + require.Equal(t, http.StatusOK, w.Code) + require.Equal(t, "zlib-body", w.Body.String()) +} diff --git a/internal/common/entrytype.go b/internal/common/entrytype.go index 372e7aae..0cbee95c 100644 --- a/internal/common/entrytype.go +++ b/internal/common/entrytype.go @@ -5,4 +5,5 @@ type EntryType string const ( DocumentType EntryType = "DocumentType" CollectionType EntryType = "CollectionType" + TemplateType EntryType = "TemplateType" ) diff --git a/internal/config/config.go b/internal/config/config.go index d4979076..364ca19b 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -11,6 +11,7 @@ import ( "os" "path/filepath" "strconv" + "strings" "github.com/ddvk/rmfakecloud/internal/email" log "github.com/sirupsen/logrus" @@ -81,6 +82,10 @@ const ( envMQTTPort = "MQTT_PORT" envICEServers = "ICE_SERVERS" envHashSchemaVersion = "HASH_SCHEMA_VERSION" + + envWebAuthn = "RMFAKECLOUD_WEBAUTHN" + envWebAuthnRPID = "RMFAKECLOUD_WEBAUTHN_RPID" + envWebAuthnOrigins = "RMFAKECLOUD_WEBAUTHN_ORIGINS" ) // Config config @@ -106,6 +111,12 @@ type Config struct { MQTTPort string ICEServers []interface{} HashSchemaVersion string + // WebAuthn enables passkey login for the web UI (RMFAKECLOUD_WEBAUTHN). Default false. + WebAuthn bool + // WebAuthnRPID is the Relying Party ID (hostname without scheme/port). + WebAuthnRPID string + // WebAuthnOrigins are allowed browser origins for WebAuthn ceremonies. + WebAuthnOrigins []string } // Verify verify @@ -142,6 +153,9 @@ func (cfg *Config) Verify() { } else { log.Info("No ICE servers configured - screenshare will only work on local networks") } + if cfg.WebAuthn { + log.Infof("web UI passkeys enabled (rpid=%q origins=%v)", cfg.WebAuthnRPID, cfg.WebAuthnOrigins) + } } // FromEnv config from environment values @@ -265,6 +279,29 @@ func FromEnv() *Config { log.Fatalf("%s must be either '3' or '4', got: %s", envHashSchemaVersion, hashSchemaVersion) } + webAuthnWanted, _ := strconv.ParseBool(os.Getenv(envWebAuthn)) + webAuthnRPID := strings.TrimSpace(os.Getenv(envWebAuthnRPID)) + webAuthnOrigins := splitCSV(os.Getenv(envWebAuthnOrigins)) + webAuthnEnabled := false + if webAuthnWanted { + if webAuthnRPID == "" || len(webAuthnOrigins) == 0 { + if derivedRPID, derivedOrigins, ok := deriveWebAuthnFromStorageURL(uploadURL); ok { + if webAuthnRPID == "" { + webAuthnRPID = derivedRPID + } + if len(webAuthnOrigins) == 0 { + webAuthnOrigins = derivedOrigins + } + } + } + if webAuthnRPID == "" || len(webAuthnOrigins) == 0 { + log.Errorf("%s=true but %s / %s not set and could not derive from https %s; passkeys disabled", + envWebAuthn, envWebAuthnRPID, envWebAuthnOrigins, EnvStorageURL) + } else { + webAuthnEnabled = true + } + } + cfg := Config{ Port: port, StorageURL: uploadURL, @@ -284,10 +321,36 @@ func FromEnv() *Config { MQTTPort: mqttPort, ICEServers: iceServers, HashSchemaVersion: hashSchemaVersion, + WebAuthn: webAuthnEnabled, + WebAuthnRPID: webAuthnRPID, + WebAuthnOrigins: webAuthnOrigins, } return &cfg } +func splitCSV(s string) []string { + parts := strings.Split(s, ",") + out := make([]string, 0, len(parts)) + for _, p := range parts { + p = strings.TrimSpace(p) + if p != "" { + out = append(out, p) + } + } + return out +} + +// deriveWebAuthnFromStorageURL returns RPID (hostname without port) and a single origin +// when STORAGE_URL is https with a host. http / empty host returns ok=false. +func deriveWebAuthnFromStorageURL(storageURL string) (rpid string, origins []string, ok bool) { + u, err := url.Parse(storageURL) + if err != nil || u.Scheme != "https" || u.Hostname() == "" { + return "", nil, false + } + origin := "https://" + u.Host + return u.Hostname(), []string{origin}, true +} + // normalizeICEServers expands "urls" arrays into singular "url" entries; xochitl rejects anything else func normalizeICEServers(servers []interface{}) []interface{} { normalized := make([]interface{}, 0, len(servers)) @@ -378,6 +441,12 @@ General: %s Trust the proxy for X-Forwarded-For/X-Real-IP (set only if behind a proxy) %s Hash tree schema version: "3" or "4" (default: 3) +Web UI passkeys (WebAuthn): + %s Enable passkey register/login for the web UI (default: false). Requires HTTPS browser origin. + %s Relying Party ID (hostname without scheme/port). If empty, derived from https STORAGE_URL. + %s Comma-separated allowed origins (e.g. https://example.com:3000). If empty, derived from https STORAGE_URL. + http://hostname, LAN names, and raw IPs do not work for real passkeys. + MQTT (for screenshare): %s MQTT TCP port (default: 8883) %s ICE servers for WebRTC (JSON array format) @@ -415,6 +484,10 @@ myScript hwr (needs a developer account): envTrustProxy, envHashSchemaVersion, + envWebAuthn, + envWebAuthnRPID, + envWebAuthnOrigins, + envMQTTPort, envICEServers, diff --git a/internal/config/webauthn_config_test.go b/internal/config/webauthn_config_test.go new file mode 100644 index 00000000..8472f40a --- /dev/null +++ b/internal/config/webauthn_config_test.go @@ -0,0 +1,23 @@ +package config + +import "testing" + +func TestDeriveWebAuthnFromStorageURL(t *testing.T) { + rpid, origins, ok := deriveWebAuthnFromStorageURL("https://www.example.com:3000") + if !ok || rpid != "www.example.com" || len(origins) != 1 || origins[0] != "https://www.example.com:3000" { + t.Fatalf("got rpid=%q origins=%v ok=%v", rpid, origins, ok) + } + if _, _, ok := deriveWebAuthnFromStorageURL("http://acorn:3000"); ok { + t.Fatal("http should not derive") + } + if _, _, ok := deriveWebAuthnFromStorageURL("not-a-url"); ok { + t.Fatal("invalid should not derive") + } +} + +func TestSplitCSV(t *testing.T) { + got := splitCSV(" https://a.com ,https://b.com, ") + if len(got) != 2 || got[0] != "https://a.com" || got[1] != "https://b.com" { + t.Fatalf("%v", got) + } +} diff --git a/internal/model/user.go b/internal/model/user.go index 62ab58e7..4620526b 100644 --- a/internal/model/user.go +++ b/internal/model/user.go @@ -55,6 +55,12 @@ type User struct { AdditionalScopes []string // Integrations stores the list of "Integrations" as shown on the tablet. Integrations []IntegrationConfig + // WebAuthnCredentials are passkeys registered for the web UI. + WebAuthnCredentials []WebAuthnCredential `yaml:"webauthncredentials,omitempty"` + // ThemeID is the selected shell theme (XML/XSLT). Empty means "default". + ThemeID string `yaml:"themeid,omitempty"` + // ThemeColorOverrides are optional per-user color tweaks (CSS hex) applied on top of the theme. + ThemeColorOverrides map[string]string `yaml:"themecoloroverrides,omitempty"` } // IntegrationConfig config for various integrations diff --git a/internal/model/webauthn.go b/internal/model/webauthn.go new file mode 100644 index 00000000..0ed30e01 --- /dev/null +++ b/internal/model/webauthn.go @@ -0,0 +1,169 @@ +package model + +import ( + "bytes" + "encoding/base64" + "time" + + "github.com/go-webauthn/webauthn/protocol" + "github.com/go-webauthn/webauthn/webauthn" +) + +// WebAuthnCredential is a stored passkey / WebAuthn public-key credential. +type WebAuthnCredential struct { + ID []byte `yaml:"id"` + PublicKey []byte `yaml:"publickey"` + AttestationType string `yaml:"attestationtype,omitempty"` + Transport []string `yaml:"transport,omitempty"` + UserPresent bool `yaml:"userpresent,omitempty"` + UserVerified bool `yaml:"userverified,omitempty"` + BackupEligible bool `yaml:"backupeligible,omitempty"` + BackupState bool `yaml:"backupstate,omitempty"` + AAGUID []byte `yaml:"aaguid,omitempty"` + SignCount uint32 `yaml:"signcount"` + Attachment string `yaml:"attachment,omitempty"` + Name string `yaml:"name,omitempty"` + CreatedAt time.Time `yaml:"createdat,omitempty"` +} + +// WebAuthnUser adapts *User to webauthn.User. +type WebAuthnUser struct { + *User +} + +func (u WebAuthnUser) WebAuthnID() []byte { + if u.User == nil { + return nil + } + return []byte(u.ID) +} + +func (u WebAuthnUser) WebAuthnName() string { + if u.User == nil { + return "" + } + return u.Email +} + +func (u WebAuthnUser) WebAuthnDisplayName() string { + if u.User == nil { + return "" + } + if u.Name != "" { + return u.Name + } + return u.Email +} + +func (u WebAuthnUser) WebAuthnCredentials() []webauthn.Credential { + if u.User == nil { + return nil + } + out := make([]webauthn.Credential, 0, len(u.User.WebAuthnCredentials)) + for _, c := range u.User.WebAuthnCredentials { + out = append(out, c.ToLibrary()) + } + return out +} + +// ToLibrary converts a stored credential to the go-webauthn type. +func (c WebAuthnCredential) ToLibrary() webauthn.Credential { + transports := make([]protocol.AuthenticatorTransport, 0, len(c.Transport)) + for _, t := range c.Transport { + transports = append(transports, protocol.AuthenticatorTransport(t)) + } + return webauthn.Credential{ + ID: c.ID, + PublicKey: c.PublicKey, + AttestationType: c.AttestationType, + Transport: transports, + Flags: webauthn.CredentialFlags{ + UserPresent: c.UserPresent, + UserVerified: c.UserVerified, + BackupEligible: c.BackupEligible, + BackupState: c.BackupState, + }, + Authenticator: webauthn.Authenticator{ + AAGUID: c.AAGUID, + SignCount: c.SignCount, + Attachment: protocol.AuthenticatorAttachment(c.Attachment), + }, + } +} + +// FromLibraryCredential builds a stored credential from a successful registration. +func FromLibraryCredential(cred *webauthn.Credential, name string) WebAuthnCredential { + if cred == nil { + return WebAuthnCredential{} + } + transports := make([]string, 0, len(cred.Transport)) + for _, t := range cred.Transport { + transports = append(transports, string(t)) + } + return WebAuthnCredential{ + ID: append([]byte(nil), cred.ID...), + PublicKey: append([]byte(nil), cred.PublicKey...), + AttestationType: cred.AttestationType, + Transport: transports, + UserPresent: cred.Flags.UserPresent, + UserVerified: cred.Flags.UserVerified, + BackupEligible: cred.Flags.BackupEligible, + BackupState: cred.Flags.BackupState, + AAGUID: append([]byte(nil), cred.Authenticator.AAGUID...), + SignCount: cred.Authenticator.SignCount, + Attachment: string(cred.Authenticator.Attachment), + Name: name, + CreatedAt: time.Now().UTC(), + } +} + +// UpdateWebAuthnCredentialSignCount updates sign count / backup flags after login. +func (u *User) UpdateWebAuthnCredentialSignCount(credID []byte, cred *webauthn.Credential) bool { + if u == nil || cred == nil { + return false + } + for i := range u.WebAuthnCredentials { + if bytes.Equal(u.WebAuthnCredentials[i].ID, credID) { + u.WebAuthnCredentials[i].SignCount = cred.Authenticator.SignCount + u.WebAuthnCredentials[i].BackupState = cred.Flags.BackupState + u.WebAuthnCredentials[i].UserPresent = cred.Flags.UserPresent + u.WebAuthnCredentials[i].UserVerified = cred.Flags.UserVerified + return true + } + } + return false +} + +// RemoveWebAuthnCredential deletes a credential by raw id. Returns true if removed. +func (u *User) RemoveWebAuthnCredential(credID []byte) bool { + if u == nil { + return false + } + for i := range u.WebAuthnCredentials { + if bytes.Equal(u.WebAuthnCredentials[i].ID, credID) { + u.WebAuthnCredentials = append(u.WebAuthnCredentials[:i], u.WebAuthnCredentials[i+1:]...) + return true + } + } + return false +} + +// FindUserByWebAuthnHandle finds a user whose WebAuthnID matches userHandle. +func FindUserByWebAuthnHandle(users []*User, userHandle []byte) *User { + for _, u := range users { + if u != nil && bytes.Equal([]byte(u.ID), userHandle) { + return u + } + } + return nil +} + +// CredentialIDBase64 returns URL-safe base64 without padding for API paths. +func CredentialIDBase64(id []byte) string { + return base64.RawURLEncoding.EncodeToString(id) +} + +// ParseCredentialIDBase64 decodes a URL-safe credential id. +func ParseCredentialIDBase64(s string) ([]byte, error) { + return base64.RawURLEncoding.DecodeString(s) +} diff --git a/internal/model/webauthn_test.go b/internal/model/webauthn_test.go new file mode 100644 index 00000000..1924f3df --- /dev/null +++ b/internal/model/webauthn_test.go @@ -0,0 +1,94 @@ +package model + +import ( + "testing" + "time" + + "github.com/go-webauthn/webauthn/webauthn" +) + +func TestWebAuthnCredentialRoundTrip(t *testing.T) { + cred := &webauthn.Credential{ + ID: []byte{1, 2, 3, 4}, + PublicKey: []byte{9, 8, 7}, + AttestationType: "none", + Flags: webauthn.CredentialFlags{ + UserPresent: true, + UserVerified: true, + }, + Authenticator: webauthn.Authenticator{ + AAGUID: []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + SignCount: 3, + }, + } + stored := FromLibraryCredential(cred, "Laptop") + if stored.Name != "Laptop" || stored.SignCount != 3 { + t.Fatalf("unexpected stored credential: %+v", stored) + } + if stored.CreatedAt.IsZero() { + t.Fatal("CreatedAt should be set") + } + lib := stored.ToLibrary() + if string(lib.ID) != string(cred.ID) || string(lib.PublicKey) != string(cred.PublicKey) { + t.Fatalf("round-trip mismatch: %+v vs %+v", lib, cred) + } +} + +func TestUpdateAndRemoveWebAuthnCredential(t *testing.T) { + u := &User{ + ID: "alice@example.com", + WebAuthnCredentials: []WebAuthnCredential{ + {ID: []byte("abc"), SignCount: 1, Name: "a", CreatedAt: time.Now()}, + }, + } + updated := u.UpdateWebAuthnCredentialSignCount([]byte("abc"), &webauthn.Credential{ + Authenticator: webauthn.Authenticator{SignCount: 5}, + Flags: webauthn.CredentialFlags{BackupState: true}, + }) + if !updated || u.WebAuthnCredentials[0].SignCount != 5 { + t.Fatalf("sign count not updated: %+v", u.WebAuthnCredentials[0]) + } + if !u.RemoveWebAuthnCredential([]byte("abc")) || len(u.WebAuthnCredentials) != 0 { + t.Fatal("remove failed") + } +} + +func TestFindUserByWebAuthnHandle(t *testing.T) { + users := []*User{ + {ID: "a@example.com"}, + {ID: "b@example.com"}, + } + found := FindUserByWebAuthnHandle(users, []byte("b@example.com")) + if found == nil || found.ID != "b@example.com" { + t.Fatalf("expected b, got %#v", found) + } + if FindUserByWebAuthnHandle(users, []byte("missing")) != nil { + t.Fatal("expected nil") + } +} + +func TestCredentialIDBase64(t *testing.T) { + id := []byte{0xff, 0x00, 0x01} + s := CredentialIDBase64(id) + got, err := ParseCredentialIDBase64(s) + if err != nil { + t.Fatal(err) + } + if string(got) != string(id) { + t.Fatalf("got %v want %v", got, id) + } +} + +func TestWebAuthnUserInterface(t *testing.T) { + u := &User{ID: "u1", Email: "u1@example.com", Name: "User One"} + wu := WebAuthnUser{User: u} + if string(wu.WebAuthnID()) != "u1" { + t.Fatal(wu.WebAuthnID()) + } + if wu.WebAuthnName() != "u1@example.com" || wu.WebAuthnDisplayName() != "User One" { + t.Fatalf("%s / %s", wu.WebAuthnName(), wu.WebAuthnDisplayName()) + } + if len(wu.WebAuthnCredentials()) != 0 { + t.Fatal("expected empty credentials") + } +} diff --git a/internal/pdfraster/pdfraster.go b/internal/pdfraster/pdfraster.go new file mode 100644 index 00000000..a7862e8d --- /dev/null +++ b/internal/pdfraster/pdfraster.go @@ -0,0 +1,163 @@ +package pdfraster + +import ( + "bytes" + "fmt" + "os" + "os/exec" + "path/filepath" + "strconv" + "strings" +) + +const ( + // EnvPDFRenderer selects the PDF→PNG backend. + // Values: "auto" (default), "pdftoppm", "mutool", "unipdf". + // Out-of-process tools mirror xochitl_pdf_renderer (crash-isolated PDF engine). + EnvPDFRenderer = "RMFAKECLOUD_PDF_RENDERER" + + // DevicePortraitWidth is the reMarkable portrait page width used for raster targets. + // Height follows the PDF page aspect (scale-to-y -1) so Letter stays undistorted. + DevicePortraitWidth = 1404 +) + +// RenderFunc optionally overrides the final unipdf fallback (injected by exporter to +// avoid an import cycle with unidoc). +var UnipdfFallback func(pdfBytes []byte, pageNum int) ([]byte, error) + +// RenderPage rasters one PDF page (1-based) to PNG. +func RenderPage(pdfBytes []byte, pageNum int) ([]byte, error) { + if len(pdfBytes) == 0 { + return nil, fmt.Errorf("empty pdf") + } + if pageNum < 1 { + return nil, fmt.Errorf("page %d out of range", pageNum) + } + + prefer := strings.ToLower(strings.TrimSpace(os.Getenv(EnvPDFRenderer))) + if prefer == "" { + prefer = "auto" + } + + var errs []string + try := func(name string, fn func() ([]byte, error)) ([]byte, error) { + b, err := fn() + if err == nil { + return b, nil + } + errs = append(errs, name+": "+err.Error()) + return nil, err + } + + runAuto := func() ([]byte, error) { + if b, err := try("pdftoppm", func() ([]byte, error) { return withPdftoppm(pdfBytes, pageNum) }); err == nil { + return b, nil + } + if b, err := try("mutool", func() ([]byte, error) { return withMutool(pdfBytes, pageNum) }); err == nil { + return b, nil + } + if UnipdfFallback != nil { + if b, err := try("unipdf", func() ([]byte, error) { return UnipdfFallback(pdfBytes, pageNum) }); err == nil { + return b, nil + } + } + return nil, fmt.Errorf("pdf raster failed: %s", strings.Join(errs, " | ")) + } + + switch prefer { + case "pdftoppm": + if b, err := try("pdftoppm", func() ([]byte, error) { return withPdftoppm(pdfBytes, pageNum) }); err == nil { + return b, nil + } + case "mutool": + if b, err := try("mutool", func() ([]byte, error) { return withMutool(pdfBytes, pageNum) }); err == nil { + return b, nil + } + case "unipdf": + if UnipdfFallback == nil { + return nil, fmt.Errorf("unipdf fallback not registered") + } + return UnipdfFallback(pdfBytes, pageNum) + default: + return runAuto() + } + + // Preferred tool failed — still try the rest. + return runAuto() +} + +func withPdftoppm(pdfBytes []byte, pageNum int) ([]byte, error) { + bin, err := exec.LookPath("pdftoppm") + if err != nil { + return nil, err + } + tmpDir, err := os.MkdirTemp("", "pdftoppm-*") + if err != nil { + return nil, err + } + defer os.RemoveAll(tmpDir) + + inPath := filepath.Join(tmpDir, "in.pdf") + if err := os.WriteFile(inPath, pdfBytes, 0600); err != nil { + return nil, err + } + outPrefix := filepath.Join(tmpDir, "page") + page := strconv.Itoa(pageNum) + cmd := exec.Command(bin, + "-png", + "-f", page, + "-l", page, + "-singlefile", + "-cropbox", + "-scale-to-x", strconv.Itoa(DevicePortraitWidth), + "-scale-to-y", "-1", + inPath, + outPrefix, + ) + var stderr bytes.Buffer + cmd.Stderr = &stderr + if err := cmd.Run(); err != nil { + msg := strings.TrimSpace(stderr.String()) + if msg != "" { + return nil, fmt.Errorf("%w: %s", err, msg) + } + return nil, err + } + return os.ReadFile(outPrefix + ".png") +} + +func withMutool(pdfBytes []byte, pageNum int) ([]byte, error) { + bin, err := exec.LookPath("mutool") + if err != nil { + return nil, err + } + tmpDir, err := os.MkdirTemp("", "mutool-*") + if err != nil { + return nil, err + } + defer os.RemoveAll(tmpDir) + + inPath := filepath.Join(tmpDir, "in.pdf") + outPath := filepath.Join(tmpDir, "page.png") + if err := os.WriteFile(inPath, pdfBytes, 0600); err != nil { + return nil, err + } + cmd := exec.Command(bin, "draw", + "-o", outPath, + "-F", "png", + "-w", strconv.Itoa(DevicePortraitWidth), + "-b", "CropBox", + inPath, + strconv.Itoa(pageNum), + ) + var stderr bytes.Buffer + cmd.Stderr = &stderr + if err := cmd.Run(); err != nil { + msg := strings.TrimSpace(stderr.String()) + if msg != "" { + return nil, fmt.Errorf("%w: %s", err, msg) + } + return nil, err + } + return os.ReadFile(outPath) +} diff --git a/internal/pdfraster/pdfraster_test.go b/internal/pdfraster/pdfraster_test.go new file mode 100644 index 00000000..309503d0 --- /dev/null +++ b/internal/pdfraster/pdfraster_test.go @@ -0,0 +1,22 @@ +package pdfraster + +import ( + "os" + "testing" +) + +func TestRenderPagePdftoppm(t *testing.T) { + pdfPath := "../../../test/test.pdf" + b, err := os.ReadFile(pdfPath) + if err != nil { + t.Skip("test.pdf missing:", err) + } + t.Setenv(EnvPDFRenderer, "pdftoppm") + out, err := RenderPage(b, 1) + if err != nil { + t.Fatal(err) + } + if len(out) < 100 || out[0] != 0x89 { + t.Fatalf("expected PNG output, got %d bytes", len(out)) + } +} diff --git a/internal/rmdecode/encode_page_png.go b/internal/rmdecode/encode_page_png.go new file mode 100644 index 00000000..58cd26e1 --- /dev/null +++ b/internal/rmdecode/encode_page_png.go @@ -0,0 +1,159 @@ +package rmdecode + +import ( + "bytes" + "fmt" + "os" + "os/exec" + "path/filepath" + "strconv" +) + +// EnvV6PNGScript is the full path to scripts/rmscene_v6_to_png.py (optional). +const EnvV6PNGScript = "RMFAKECLOUD_V6_PNG_SCRIPT" + +// ScreenDPI is the reMarkable display density used for inch→pixel mapping. +const ScreenDPI = 226 + +// EncodeRmPageToPNG converts raw .rm page bytes to a device-canvas PNG (notebooks). +func EncodeRmPageToPNG(data []byte) ([]byte, error) { + return encodeRmPageToPNG(data, nil, 0, 0) +} + +// EncodeRmPageToPNGWithImages is EncodeRmPageToPNG with inserted page image blobs +// (basename → PNG/JPEG bytes), used for reMarkable v6 image items. +func EncodeRmPageToPNGWithImages(data []byte, images map[string][]byte) ([]byte, error) { + return encodeRmPageToPNG(data, images, 0, 0) +} + +// EncodeRmPageToPNGForPDF renders .rm ink in PDF-page coordinates scaled to the +// same width-fitted raster used for the PDF background (1404 × aspect height). +// widthPt/heightPt are the PDF page size in points (e.g. 612×792 for Letter). +func EncodeRmPageToPNGForPDF(data []byte, widthPt, heightPt float64) ([]byte, error) { + if widthPt < 1 || heightPt < 1 { + return nil, fmt.Errorf("invalid pdf page size %gx%g", widthPt, heightPt) + } + return encodeRmPageToPNG(data, nil, widthPt, heightPt) +} + +// EncodeRmPageToPNGForPDFWithImages is EncodeRmPageToPNGForPDF with page images. +func EncodeRmPageToPNGForPDFWithImages(data []byte, images map[string][]byte, widthPt, heightPt float64) ([]byte, error) { + if widthPt < 1 || heightPt < 1 { + return nil, fmt.Errorf("invalid pdf page size %gx%g", widthPt, heightPt) + } + return encodeRmPageToPNG(data, images, widthPt, heightPt) +} + +func encodeRmPageToPNG(data []byte, images map[string][]byte, pdfWPt, pdfHPt float64) ([]byte, error) { + if len(data) == 0 { + return nil, fmt.Errorf("empty .rm data") + } + ver, err := ParseVersion(data) + if err != nil { + return nil, err + } + var ink []byte + switch ver { + case 3: + if b, err := RenderV3PNGWithLines2PNG(data); err == nil { + ink = b + } else if Lines2PNGAvailable() { + return nil, fmt.Errorf("lines2png available but failed: %w", err) + } else { + page, err := DecodeLegacy(data) + if err != nil { + return nil, err + } + ink, err = RenderWritingsPNG(page) + if err != nil { + return nil, err + } + } + case 5: + page, err := DecodeLegacy(data) + if err != nil { + return nil, err + } + ink, err = RenderWritingsPNG(page) + if err != nil { + return nil, err + } + case 6: + ink, err = encodeV6RmToPNG(data, images, pdfWPt, pdfHPt) + if err != nil { + return nil, err + } + default: + return nil, fmt.Errorf("unsupported .rm version %d", ver) + } + + meta := ReadInkDeviceMeta(ink) + if meta.ViewW < 1 || meta.ViewH < 1 { + meta = DefaultInkDeviceMeta() + } + out, err := WriteInkDeviceMeta(ink, meta) + if err != nil { + return ink, nil + } + return out, nil +} + +func encodeV6RmToPNG(data []byte, images map[string][]byte, pdfWPt, pdfHPt float64) ([]byte, error) { + // Prefer rmc SVG→PNG so inserted images (and full scene items) render. + if png, err := RenderV6PNGWithRMC(data, images); err == nil { + return png, nil + } else { + rmcErr := err + if len(images) > 0 { + return nil, fmt.Errorf("v6 png rmc (required for page images): %v", rmcErr) + } + if png, err := renderV6PNGWithScript(data, pdfWPt, pdfHPt); err == nil { + return png, nil + } else { + return nil, fmt.Errorf("v6 png: rmc: %v; script: %v", rmcErr, err) + } + } +} + +func renderV6PNGWithScript(data []byte, pdfWPt, pdfHPt float64) ([]byte, error) { + script := os.Getenv(EnvV6PNGScript) + if script == "" { + if root := os.Getenv(EnvRepoRoot); root != "" { + script = filepath.Join(root, "scripts", "rmscene_v6_to_png.py") + } else if root := FindRepoRoot(); root != "" { + script = filepath.Join(root, "scripts", "rmscene_v6_to_png.py") + } + } + if script == "" { + return nil, fmt.Errorf("no %s / %s for scripts/rmscene_v6_to_png.py", EnvV6PNGScript, EnvRepoRoot) + } + if st, err := os.Stat(script); err != nil || st.IsDir() { + return nil, fmt.Errorf("v6 PNG script %q: %w", script, err) + } + + args := []string{script} + if pdfWPt >= 1 && pdfHPt >= 1 { + args = append(args, + "--pdf-pts", + strconv.FormatFloat(pdfWPt, 'f', -1, 64), + strconv.FormatFloat(pdfHPt, 'f', -1, 64), + ) + } + args = append(args, "-") + cmd := exec.Command("python3", args...) + cmd.Stdin = bytes.NewReader(data) + if py := buildPythonPathForV6(""); py != "" { + cmd.Env = append(os.Environ(), "PYTHONPATH="+py) + } + out, err := cmd.Output() + if err != nil { + if x, ok := err.(*exec.ExitError); ok && len(x.Stderr) > 0 { + return nil, fmt.Errorf("v6 python: %w: %s", err, string(x.Stderr)) + } + return nil, fmt.Errorf("v6 python: %w", err) + } + if len(out) < 32 { + return nil, fmt.Errorf("v6 python: empty png") + } + return out, nil +} diff --git a/internal/rmdecode/encode_page_svg.go b/internal/rmdecode/encode_page_svg.go new file mode 100644 index 00000000..1af07cfb --- /dev/null +++ b/internal/rmdecode/encode_page_svg.go @@ -0,0 +1,40 @@ +package rmdecode + +import "fmt" + +// EncodeRmPageToSVG converts raw .rm page bytes to a standalone SVG (1404×1872). +// v3/v5: Go stroke renderer. v6: rmc (+ vendored rmscene via PYTHONPATH). +func EncodeRmPageToSVG(data []byte) ([]byte, error) { + return EncodeRmPageToSVGWithImages(data, nil) +} + +// EncodeRmPageToSVGWithImages is EncodeRmPageToSVG with inserted page image blobs. +func EncodeRmPageToSVGWithImages(data []byte, images map[string][]byte) ([]byte, error) { + if len(data) == 0 { + return nil, fmt.Errorf("empty .rm data") + } + ver, err := ParseVersion(data) + if err != nil { + return nil, err + } + switch ver { + case 3, 5: + page, err := DecodeLegacy(data) + if err != nil { + return nil, err + } + s, err := RenderWritingsSVG(page) + if err != nil { + return nil, err + } + return []byte(s), nil + case 6: + s, err := RenderV6SVGWithRMC(data, images) + if err != nil { + return nil, err + } + return []byte(s), nil + default: + return nil, fmt.Errorf("unsupported .rm version %d", ver) + } +} diff --git a/internal/rmdecode/encode_page_svg_test.go b/internal/rmdecode/encode_page_svg_test.go new file mode 100644 index 00000000..d74253d2 --- /dev/null +++ b/internal/rmdecode/encode_page_svg_test.go @@ -0,0 +1,35 @@ +package rmdecode + +import ( + "strings" + "testing" + + "github.com/juruen/rmapi/encoding/rm" +) + +func TestRenderWritingsSVG_Empty(t *testing.T) { + page := &rm.Rm{Layers: []rm.Layer{}} + s, err := RenderWritingsSVG(page) + if err != nil { + t.Fatal(err) + } + if !strings.HasPrefix(s, " 0 && h > 0 { + m.ViewW, m.ViewH = w, h + } + } + if v, ok := texts["rmDeviceOrigin"]; ok { + if x, y, err := parseTwoInts(v); err == nil { + m.OriginX, m.OriginY = x, y + } + } + return m +} + +// WriteInkDeviceMeta returns pngBytes with rmDeviceOrigin / rmDeviceSize tEXt set. +func WriteInkDeviceMeta(pngBytes []byte, m InkDeviceMeta) ([]byte, error) { + if len(pngBytes) < 8 || !bytes.Equal(pngBytes[:8], []byte{137, 80, 78, 71, 13, 10, 26, 10}) { + return nil, fmt.Errorf("not a png") + } + out := make([]byte, 0, len(pngBytes)+128) + out = append(out, pngBytes[:8]...) + rest := pngBytes[8:] + inserted := false + for len(rest) >= 12 { + length := int(binary.BigEndian.Uint32(rest[0:4])) + if length < 0 || 8+length+4 > len(rest) { + return nil, fmt.Errorf("png chunk truncated") + } + ctype := string(rest[4:8]) + chunk := rest[:8+length+4] + rest = rest[8+length+4:] + if ctype == "IHDR" { + out = append(out, chunk...) + out = append(out, pngTextChunk("rmDeviceOrigin", fmt.Sprintf("%d,%d", m.OriginX, m.OriginY))...) + out = append(out, pngTextChunk("rmDeviceSize", fmt.Sprintf("%d,%d", m.ViewW, m.ViewH))...) + inserted = true + continue + } + if ctype == "tEXt" { + key, _, _ := bytes.Cut(chunk[8:8+length], []byte{0}) + ks := string(key) + if ks == "rmDeviceOrigin" || ks == "rmDeviceSize" { + continue // replace below via inserted headers + } + } + out = append(out, chunk...) + if ctype == "IEND" { + break + } + } + if !inserted { + return nil, fmt.Errorf("png missing IHDR") + } + return out, nil +} + +func parseTwoInts(s string) (int, int, error) { + parts := strings.Split(strings.TrimSpace(s), ",") + if len(parts) != 2 { + return 0, 0, fmt.Errorf("want a,b") + } + a, err := strconv.Atoi(strings.TrimSpace(parts[0])) + if err != nil { + return 0, 0, err + } + b, err := strconv.Atoi(strings.TrimSpace(parts[1])) + if err != nil { + return 0, 0, err + } + return a, b, nil +} + +func readPNGTextChunks(pngBytes []byte) map[string]string { + out := map[string]string{} + if len(pngBytes) < 8 || !bytes.Equal(pngBytes[:8], []byte{137, 80, 78, 71, 13, 10, 26, 10}) { + return out + } + rest := pngBytes[8:] + for len(rest) >= 12 { + length := int(binary.BigEndian.Uint32(rest[0:4])) + if length < 0 || 8+length+4 > len(rest) { + break + } + ctype := string(rest[4:8]) + data := rest[8 : 8+length] + rest = rest[8+length+4:] + if ctype == "tEXt" { + key, val, ok := bytes.Cut(data, []byte{0}) + if ok { + out[string(key)] = string(val) + } + } + if ctype == "IEND" { + break + } + } + return out +} + +func pngTextChunk(key, val string) []byte { + payload := append(append([]byte(key), 0), []byte(val)...) + length := len(payload) + chunk := make([]byte, 0, 12+length) + var hdr [8]byte + binary.BigEndian.PutUint32(hdr[0:4], uint32(length)) + copy(hdr[4:8], []byte("tEXt")) + chunk = append(chunk, hdr[:]...) + chunk = append(chunk, payload...) + crc := crc32.NewIEEE() + _, _ = crc.Write(hdr[4:8]) + _, _ = crc.Write(payload) + var cbuf [4]byte + binary.BigEndian.PutUint32(cbuf[:], crc.Sum32()) + chunk = append(chunk, cbuf[:]...) + return chunk +} diff --git a/internal/rmdecode/lines2tools.go b/internal/rmdecode/lines2tools.go new file mode 100644 index 00000000..cbb4e8eb --- /dev/null +++ b/internal/rmdecode/lines2tools.go @@ -0,0 +1,96 @@ +package rmdecode + +import ( + "bytes" + "fmt" + "os" + "os/exec" + "path/filepath" + "strings" +) + +const ( + // EnvLines2SVGBin points to a lines-are-beautiful lines2svg executable. + EnvLines2SVGBin = "RMFAKECLOUD_LINES2SVG_BIN" + // EnvLines2PNGBin points to a lines-are-beautiful lines2png executable. + EnvLines2PNGBin = "RMFAKECLOUD_LINES2PNG_BIN" +) + +func renderV3WithLinesTool(data []byte, envVar, fallbackBin, outName string) ([]byte, error) { + ver, err := ParseVersion(data) + if err != nil { + return nil, err + } + if ver != 3 { + return nil, fmt.Errorf("%s renderer supports v3 only, got v%d", fallbackBin, ver) + } + + bin := strings.TrimSpace(os.Getenv(envVar)) + if bin == "" { + bin, err = exec.LookPath(fallbackBin) + if err != nil { + return nil, fmt.Errorf("%s not found (set %s): %w", fallbackBin, envVar, err) + } + } + + tmpDir, err := os.MkdirTemp("", fallbackBin+"-*") + if err != nil { + return nil, err + } + defer os.RemoveAll(tmpDir) + + // lines-are-beautiful expects notebook pages as 0.rm, 1.rm... + inPath := filepath.Join(tmpDir, "0.rm") + if err := os.WriteFile(inPath, data, 0600); err != nil { + return nil, err + } + + cmd := exec.Command(bin, tmpDir) + cmd.Dir = tmpDir + var stderr bytes.Buffer + cmd.Stderr = &stderr + if err := cmd.Run(); err != nil { + msg := strings.TrimSpace(stderr.String()) + if msg != "" { + return nil, fmt.Errorf("%s: %w: %s", fallbackBin, err, msg) + } + return nil, fmt.Errorf("%s: %w", fallbackBin, err) + } + + outPath := filepath.Join(tmpDir, outName) + out, err := os.ReadFile(outPath) + if err != nil { + return nil, fmt.Errorf("%s output not found: %w", fallbackBin, err) + } + return out, nil +} + +func RenderV3SVGWithLines2SVG(data []byte) (string, error) { + b, err := renderV3WithLinesTool(data, EnvLines2SVGBin, "lines2svg", "test-0.svg") + if err != nil { + return "", err + } + return string(b), nil +} + +func RenderV3PNGWithLines2PNG(data []byte) ([]byte, error) { + return renderV3WithLinesTool(data, EnvLines2PNGBin, "lines2png", "test.png") +} + +// Lines2SVGAvailable reports whether lines2svg is configured or on PATH. +func Lines2SVGAvailable() bool { + if strings.TrimSpace(os.Getenv(EnvLines2SVGBin)) != "" { + return true + } + _, err := exec.LookPath("lines2svg") + return err == nil +} + +// Lines2PNGAvailable reports whether lines2png is configured or on PATH. +func Lines2PNGAvailable() bool { + if strings.TrimSpace(os.Getenv(EnvLines2PNGBin)) != "" { + return true + } + _, err := exec.LookPath("lines2png") + return err == nil +} diff --git a/internal/rmdecode/overlay_svg.go b/internal/rmdecode/overlay_svg.go new file mode 100644 index 00000000..2d131e98 --- /dev/null +++ b/internal/rmdecode/overlay_svg.go @@ -0,0 +1,78 @@ +package rmdecode + +import ( + "fmt" + "regexp" + "strings" +) + +// opaquePageBackground matches full-page white/light rects that some exporters +// embed (breaks transparent overlay on PDF/EPUB backgrounds). +var opaquePageBackground = regexp.MustCompile( + `(?i)]*\b(?:width\s*=\s*["'](?:100%|1404)["'][^>]*height\s*=\s*["'](?:100%|1872)["']|height\s*=\s*["'](?:100%|1872)["'][^>]*width\s*=\s*["'](?:100%|1404)["'])[^>]*\bfill\s*=\s*["'](?:#?fff(?:fff)?|white|rgb\(\s*255\s*,\s*255\s*,\s*255\s*\))["'][^>]*/>`, +) + +// EnsureTransparentOverlaySVG strips opaque full-page backgrounds so the SVG +// can sit on PDF/EPUB (or blank paper) as a transparent ink layer. +func EnsureTransparentOverlaySVG(svg string) string { + s := opaquePageBackground.ReplaceAllString(svg, "") + // Also drop a leading white rect with no size attrs that fills via CSS. + s = regexp.MustCompile(`(?i)]*\bfill\s*=\s*["'](?:#?fff(?:fff)?|white)["'][^>]*\bwidth\s*=\s*["']100%["'][^>]*/>`).ReplaceAllString(s, "") + return strings.TrimSpace(s) +} + +// RenderRmOverlaySVG renders raw .rm bytes to a transparent SVG overlay. +// This is the app’s primary ink path for PDF/EPUB overlays and standalone notebooks. +// +// v6 → rmc (RMFAKECLOUD_RMC_SRC / rmc binary) +// v3 → lines2svg when available, else embedded eraser-aware SVG +// v5 → Go polyline overlay +func RenderRmOverlaySVG(data []byte) (string, error) { + return RenderRmOverlaySVGWithImages(data, nil) +} + +// RenderRmOverlaySVGWithImages is RenderRmOverlaySVG with inserted page images. +func RenderRmOverlaySVGWithImages(data []byte, images map[string][]byte) (string, error) { + if len(data) == 0 { + return "", fmt.Errorf("empty .rm data") + } + ver, err := ParseVersion(data) + if err != nil { + return "", err + } + switch ver { + case 6: + s, err := RenderV6SVGWithRMC(data, images) + if err != nil { + return "", err + } + return EnsureTransparentOverlaySVG(s), nil + case 3: + if s, err := RenderV3SVGWithLines2SVG(data); err == nil { + return EnsureTransparentOverlaySVG(s), nil + } else if Lines2SVGAvailable() { + return "", fmt.Errorf("lines2svg available but failed: %w", err) + } + page, err := DecodeLegacy(data) + if err != nil { + return "", err + } + s, err := RenderV3SVGOverlayEmbedded(page) + if err != nil { + return "", err + } + return EnsureTransparentOverlaySVG(s), nil + case 5: + page, err := DecodeLegacy(data) + if err != nil { + return "", err + } + s, err := RenderV3SVGOverlayEmbedded(page) + if err != nil { + return "", err + } + return EnsureTransparentOverlaySVG(s), nil + default: + return "", fmt.Errorf("unsupported .rm version %d", ver) + } +} diff --git a/internal/rmdecode/placeholder_png.go b/internal/rmdecode/placeholder_png.go new file mode 100644 index 00000000..79da114c --- /dev/null +++ b/internal/rmdecode/placeholder_png.go @@ -0,0 +1,36 @@ +package rmdecode + +import ( + "bytes" + "image/png" + + "github.com/fogleman/gg" +) + +const ( + thumbWidth = 180 + thumbHeight = 240 +) + +// RenderNotebookPlaceholderPNG is a ruled-paper thumbnail used when a page +// cannot be decoded (missing .rm, unsupported v6, etc.). +func RenderNotebookPlaceholderPNG() ([]byte, error) { + dc := gg.NewContext(thumbWidth, thumbHeight) + dc.SetRGB(0.953, 0.937, 0.894) + dc.Clear() + dc.SetRGB(0.851, 0.639, 0.604) + dc.SetLineWidth(1.2) + dc.DrawLine(thumbWidth*0.12, 0, thumbWidth*0.12, thumbHeight) + dc.Stroke() + dc.SetRGB(0.851, 0.824, 0.769) + dc.SetLineWidth(1) + for y := 18.0; y < thumbHeight; y += 18 { + dc.DrawLine(0, y, thumbWidth, y) + dc.Stroke() + } + var buf bytes.Buffer + if err := png.Encode(&buf, dc.Image()); err != nil { + return nil, err + } + return buf.Bytes(), nil +} diff --git a/internal/rmdecode/placeholder_png_test.go b/internal/rmdecode/placeholder_png_test.go new file mode 100644 index 00000000..4e179dbf --- /dev/null +++ b/internal/rmdecode/placeholder_png_test.go @@ -0,0 +1,21 @@ +package rmdecode + +import ( + "bytes" + "image/png" + "testing" +) + +func TestRenderNotebookPlaceholderPNG(t *testing.T) { + b, err := RenderNotebookPlaceholderPNG() + if err != nil { + t.Fatal(err) + } + img, err := png.Decode(bytes.NewReader(b)) + if err != nil { + t.Fatal(err) + } + if img.Bounds().Dx() != 180 || img.Bounds().Dy() != 240 { + t.Fatalf("size %v", img.Bounds()) + } +} diff --git a/internal/rmdecode/placeholder_svg.go b/internal/rmdecode/placeholder_svg.go new file mode 100644 index 00000000..61d73112 --- /dev/null +++ b/internal/rmdecode/placeholder_svg.go @@ -0,0 +1,28 @@ +package rmdecode + +import ( + "fmt" + "strings" +) + +// RenderNotebookPlaceholderSVG is a ruled-paper page used when a .rm page +// cannot be decoded (missing file, unsupported v6, etc.). +func RenderNotebookPlaceholderSVG() string { + var b strings.Builder + b.WriteString(fmt.Sprintf( + ``, + PageWidthPt, PageHeightPt, PageWidthPt, PageHeightPt, + )) + b.WriteString(``) + marginX := float64(PageWidthPt) * 0.12 + b.WriteString(fmt.Sprintf( + ``, + marginX, PageHeightPt, + )) + b.WriteString(``) + for y := 80; y < PageHeightPt; y += 48 { + b.WriteString(fmt.Sprintf(``, y, PageWidthPt)) + } + b.WriteString(``) + return b.String() +} diff --git a/internal/rmdecode/python_env.go b/internal/rmdecode/python_env.go new file mode 100644 index 00000000..dbf1e7e1 --- /dev/null +++ b/internal/rmdecode/python_env.go @@ -0,0 +1,151 @@ +package rmdecode + +import ( + "os" + "path/filepath" + "strings" + "sync" +) + +// EnvRepoRoot is the repository root containing scripts/ and third_party/ (optional). +const EnvRepoRoot = "RMFAKECLOUD_ROOT" + +func normalizePythonImportRoot(p string) string { + p = strings.TrimSpace(p) + if p == "" { + return "" + } + // If user passes ".../src/rmscene" or ".../src/rmc", use ".../src" as PYTHONPATH root. + base := filepath.Base(p) + if base == "rmscene" || base == "rmc" { + return filepath.Dir(p) + } + return p +} + +var ( + repoRootOnce sync.Once + repoRootVal string +) + +// FindRepoRoot walks up from cwd (and optionally RMFAKECLOUD_ROOT) looking for go.mod +// plus third_party/rmscene (vendored tooling). +func FindRepoRoot() string { + repoRootOnce.Do(func() { + if e := strings.TrimSpace(os.Getenv(EnvRepoRoot)); e != "" { + if isRepoRoot(e) { + repoRootVal = e + return + } + } + dir, err := os.Getwd() + if err != nil { + return + } + for i := 0; i < 32; i++ { + if isRepoRoot(dir) { + repoRootVal = dir + return + } + parent := filepath.Dir(dir) + if parent == dir { + break + } + dir = parent + } + }) + return repoRootVal +} + +func isRepoRoot(dir string) bool { + if st, err := os.Stat(filepath.Join(dir, "go.mod")); err != nil || st.IsDir() { + return false + } + // Prefer layout that includes vendored Python tooling. + if st, err := os.Stat(filepath.Join(dir, "third_party", "rmscene", "src")); err == nil && st.IsDir() { + return true + } + if st, err := os.Stat(filepath.Join(dir, "scripts", "rmscene_v6_to_png.py")); err == nil && !st.IsDir() { + return true + } + return false +} + +// VendoredRMCSrc returns third_party/rmc/src when present in the repo. +func VendoredRMCSrc() string { + root := FindRepoRoot() + if root == "" { + return "" + } + p := filepath.Join(root, "third_party", "rmc", "src") + if st, err := os.Stat(filepath.Join(p, "rmc")); err == nil && st.IsDir() { + return p + } + return "" +} + +// VendoredRMSceneSrc returns third_party/rmscene/src when present. +func VendoredRMSceneSrc() string { + root := FindRepoRoot() + if root == "" { + return "" + } + p := filepath.Join(root, "third_party", "rmscene", "src") + if st, err := os.Stat(filepath.Join(p, "rmscene")); err == nil && st.IsDir() { + return p + } + return "" +} + +// EffectiveRMCSrc returns RMFAKECLOUD_RMC_SRC if set, else the vendored third_party/rmc/src. +func EffectiveRMCSrc() string { + if s := strings.TrimSpace(os.Getenv(EnvRMCSrc)); s != "" { + return normalizePythonImportRoot(s) + } + return VendoredRMCSrc() +} + +// buildPythonPathForV6 builds a PYTHONPATH that can import rmc + rmscene from: +// - optional extra path (usually rmc src) +// - RMFAKECLOUD_RMSCENE_SRC / vendored third_party/rmscene/src +// - RMFAKECLOUD_ROOT / discovered repo root +func buildPythonPathForV6(extra string) string { + parts := make([]string, 0, 6) + if e := normalizePythonImportRoot(extra); e != "" { + parts = append(parts, e) + } + if s := EffectiveRMCSrc(); s != "" && s != normalizePythonImportRoot(extra) { + parts = append(parts, s) + } + if s := normalizePythonImportRoot(os.Getenv(EnvRMSSceneSrc)); s != "" { + parts = append(parts, s) + } + if s := VendoredRMSceneSrc(); s != "" { + parts = append(parts, s) + } + if root := FindRepoRoot(); root != "" { + parts = append(parts, filepath.Join(root, "third_party", "rmscene", "src")) + parts = append(parts, filepath.Join(root, "third_party", "rmc", "src")) + } + if existing := strings.TrimSpace(os.Getenv("PYTHONPATH")); existing != "" { + parts = append(parts, existing) + } + // Dedupe while preserving order. + seen := map[string]struct{}{} + out := make([]string, 0, len(parts)) + for _, p := range parts { + p = strings.TrimSpace(p) + if p == "" { + continue + } + if _, ok := seen[p]; ok { + continue + } + seen[p] = struct{}{} + out = append(out, p) + } + if len(out) == 0 { + return "" + } + return strings.Join(out, string(os.PathListSeparator)) +} diff --git a/internal/rmdecode/render.go b/internal/rmdecode/render.go new file mode 100644 index 00000000..e5f5cafc --- /dev/null +++ b/internal/rmdecode/render.go @@ -0,0 +1,105 @@ +package rmdecode + +import ( + "bytes" + "fmt" + + "github.com/jung-kurt/gofpdf" + "github.com/juruen/rmapi/encoding/rm" +) + +// Nominal reMarkable 2 page size in points (matches exporter). +const ( + PageWidthPt = 1404 + PageHeightPt = 1872 +) + +// RenderWritingsSVG returns a standalone SVG document with a paper background and all +// non-eraser strokes from a v3/v5 decoded page. +func RenderWritingsSVG(page *rm.Rm) (string, error) { + if page == nil { + return "", fmt.Errorf("page is nil") + } + var buf bytes.Buffer + buf.WriteString(fmt.Sprintf( + ``, + PageWidthPt, PageHeightPt, PageWidthPt, PageHeightPt, + )) + buf.WriteString(``) + + for _, layer := range page.Layers { + for _, line := range layer.Lines { + if len(line.Points) < 2 { + continue + } + if line.BrushType == rm.Eraser || line.BrushType == rm.EraseArea { + continue + } + w := float64(line.BrushSize) / 10.0 + if w <= 0 { + w = 1 + } + buf.WriteString(``) + } + } + buf.WriteString(``) + return buf.String(), nil +} + +// RenderWritingsPDF returns a single-page PDF with a white background and all +// non-eraser strokes (v3/v5 only). +func RenderWritingsPDF(page *rm.Rm) ([]byte, error) { + if page == nil { + return nil, fmt.Errorf("page is nil") + } + pdf := gofpdf.NewCustom(&gofpdf.InitType{ + OrientationStr: "P", + UnitStr: "pt", + Size: gofpdf.SizeType{Wd: float64(PageWidthPt), Ht: float64(PageHeightPt)}, + }) + pdf.AddPage() + pdf.SetMargins(0, 0, 0) + pdf.SetAutoPageBreak(false, 0) + // White page + pdf.SetFillColor(255, 255, 255) + pdf.Rect(0, 0, float64(PageWidthPt), float64(PageHeightPt), "F") + + pdf.SetDrawColor(0, 0, 0) + pdf.SetLineCapStyle("round") + pdf.SetLineJoinStyle("round") + + for _, layer := range page.Layers { + for _, line := range layer.Lines { + if len(line.Points) < 2 { + continue + } + if line.BrushType == rm.Eraser || line.BrushType == rm.EraseArea { + continue + } + w := float64(line.BrushSize) / 10.0 + if w <= 0 { + w = 1 + } + pdf.SetLineWidth(w) + for i := 1; i < len(line.Points); i++ { + a, b := line.Points[i-1], line.Points[i] + pdf.Line(float64(a.X), float64(a.Y), float64(b.X), float64(b.Y)) + } + } + } + + var buf bytes.Buffer + if err := pdf.Output(&buf); err != nil { + return nil, err + } + return buf.Bytes(), nil +} diff --git a/internal/rmdecode/render_png.go b/internal/rmdecode/render_png.go new file mode 100644 index 00000000..490e8137 --- /dev/null +++ b/internal/rmdecode/render_png.go @@ -0,0 +1,64 @@ +package rmdecode + +import ( + "bytes" + "fmt" + "image/png" + + "github.com/fogleman/gg" + "github.com/juruen/rmapi/encoding/rm" +) + +// RenderWritingsPNG renders all non-eraser strokes to a white RGBA page and encodes PNG. +func RenderWritingsPNG(page *rm.Rm) ([]byte, error) { + if page == nil { + return nil, fmt.Errorf("page is nil") + } + dc := gg.NewContext(PageWidthPt, PageHeightPt) + dc.SetRGB(1, 1, 1) + dc.Clear() + dc.SetRGB(0, 0, 0) + + for _, layer := range page.Layers { + for _, line := range layer.Lines { + if len(line.Points) < 2 { + continue + } + if line.BrushType == rm.Eraser || line.BrushType == rm.EraseArea { + continue + } + w := float64(line.BrushSize) / 10.0 + if w <= 0 { + w = 1 + } + dc.SetLineWidth(w) + dc.SetLineCap(gg.LineCapRound) + dc.SetLineJoin(gg.LineJoinRound) + p0 := line.Points[0] + dc.MoveTo(float64(p0.X), float64(p0.Y)) + for i := 1; i < len(line.Points); i++ { + p := line.Points[i] + dc.LineTo(float64(p.X), float64(p.Y)) + } + dc.Stroke() + } + } + + var buf bytes.Buffer + if err := png.Encode(&buf, dc.Image()); err != nil { + return nil, err + } + return buf.Bytes(), nil +} + +// RenderBlankNotebookPNG returns a white PNG at the standard notebook size (no strokes). +func RenderBlankNotebookPNG() ([]byte, error) { + dc := gg.NewContext(PageWidthPt, PageHeightPt) + dc.SetRGB(1, 1, 1) + dc.Clear() + var buf bytes.Buffer + if err := png.Encode(&buf, dc.Image()); err != nil { + return nil, err + } + return buf.Bytes(), nil +} diff --git a/internal/rmdecode/render_png_test.go b/internal/rmdecode/render_png_test.go new file mode 100644 index 00000000..ca8d7654 --- /dev/null +++ b/internal/rmdecode/render_png_test.go @@ -0,0 +1,19 @@ +package rmdecode + +import ( + "bytes" + "testing" + + "github.com/juruen/rmapi/encoding/rm" +) + +func TestRenderWritingsPNG_Empty(t *testing.T) { + page := &rm.Rm{Layers: []rm.Layer{}} + b, err := RenderWritingsPNG(page) + if err != nil { + t.Fatal(err) + } + if len(b) < 100 || !bytes.HasPrefix(b, []byte{0x89, 0x50, 0x4e, 0x47}) { + t.Fatalf("expected PNG signature, got %d bytes", len(b)) + } +} diff --git a/internal/rmdecode/render_v3_embedded.go b/internal/rmdecode/render_v3_embedded.go new file mode 100644 index 00000000..774b4922 --- /dev/null +++ b/internal/rmdecode/render_v3_embedded.go @@ -0,0 +1,149 @@ +package rmdecode + +import ( + "bytes" + "fmt" + + "github.com/juruen/rmapi/encoding/rm" +) + +type v3RenderGroup struct { + strokes []rm.Line + erasures []rm.Line +} + +// RenderV3SVGOverlayEmbedded renders a v3 page to transparent SVG. +// It mirrors lines-are-beautiful layering semantics by applying erasures +// as nested masks that only affect prior strokes in the same layer. +func RenderV3SVGOverlayEmbedded(page *rm.Rm) (string, error) { + if page == nil { + return "", fmt.Errorf("page is nil") + } + var out bytes.Buffer + out.WriteString(fmt.Sprintf( + ``, + PageWidthPt, PageHeightPt, PageWidthPt, PageHeightPt, + )) + maskID := 0 + for layerID, layer := range page.Layers { + maskID = renderV3Layer(layerID, layer, maskID, &out) + } + out.WriteString(``) + return out.String(), nil +} + +func renderV3Layer(layerID int, layer rm.Layer, maskSeed int, out *bytes.Buffer) int { + groups := make([]v3RenderGroup, 0) + cur := v3RenderGroup{} + for _, ln := range layer.Lines { + if isEraserBrush(ln.BrushType) { + if len(cur.strokes) > 0 { + cur.erasures = append(cur.erasures, ln) + } + continue + } + if len(cur.erasures) > 0 { + groups = append(groups, cur) + cur = v3RenderGroup{} + } + cur.strokes = append(cur.strokes, ln) + } + groups = append(groups, cur) + + layerLabel := fmt.Sprintf("layer-%d", layerID) + for i := len(groups) - 1; i >= 0; i-- { + g := groups[i] + if len(g.erasures) > 0 { + maskLabel := fmt.Sprintf("%s-mask-%d", layerLabel, maskSeed) + maskSeed++ + out.WriteString(``) + out.WriteString(``) + for _, e := range g.erasures { + renderV3ErasePath(e, out) + } + out.WriteString(``) + out.WriteString(``) + } + for _, g := range groups { + for _, s := range g.strokes { + renderV3StrokePath(s, out) + } + out.WriteString(``) + } + return maskSeed +} + +func renderV3ErasePath(line rm.Line, out *bytes.Buffer) { + if len(line.Points) < 2 { + return + } + out.WriteString(``) +} + +func renderV3StrokePath(line rm.Line, out *bytes.Buffer) { + if len(line.Points) < 2 { + return + } + out.WriteString(``) +} + +func renderPathData(line rm.Line, out *bytes.Buffer) { + for i, p := range line.Points { + if i == 0 { + out.WriteString(fmt.Sprintf("M%g,%g", p.X, p.Y)) + } else { + out.WriteString(fmt.Sprintf("L%g,%g", p.X, p.Y)) + } + } +} + +func legacyStrokeWidth(line rm.Line) float64 { + base := float64(line.BrushSize) + if base > 10 { + base = base / 10 + } + if base <= 0 { + base = 1 + } + if isHighlighterBrush(line.BrushType) || isEraserBrush(line.BrushType) { + return 20*base + 0.01 + } + w := 18*base - 32 + if w <= 0 { + return base + } + return w +} + +func isEraserBrush(bt rm.BrushType) bool { + return bt == rm.Eraser || bt == rm.EraseArea +} + +func isHighlighterBrush(bt rm.BrushType) bool { + return bt == rm.Highlighter || bt == rm.HighlighterV5 || int(bt) == 5 || int(bt) == 18 +} diff --git a/internal/rmdecode/render_v3_embedded_test.go b/internal/rmdecode/render_v3_embedded_test.go new file mode 100644 index 00000000..440af90a --- /dev/null +++ b/internal/rmdecode/render_v3_embedded_test.go @@ -0,0 +1,62 @@ +package rmdecode + +import ( + "strings" + "testing" + + "github.com/juruen/rmapi/encoding/rm" +) + +func TestRenderV3SVGOverlayEmbedded_Nil(t *testing.T) { + _, err := RenderV3SVGOverlayEmbedded(nil) + if err == nil { + t.Fatal("expected error for nil page") + } +} + +func TestRenderV3SVGOverlayEmbedded_EraserMask(t *testing.T) { + page := &rm.Rm{ + Layers: []rm.Layer{ + { + Lines: []rm.Line{ + { + BrushType: rm.TiltPencil, + BrushSize: 20, + BrushColor: rm.Black, + Points: []rm.Point{ + {X: 10, Y: 10}, + {X: 20, Y: 20}, + }, + }, + { + BrushType: rm.EraseArea, + BrushSize: 20, + Points: []rm.Point{ + {X: 11, Y: 11}, + {X: 12, Y: 12}, + }, + }, + { + BrushType: rm.TiltPencil, + BrushSize: 20, + BrushColor: rm.Black, + Points: []rm.Point{ + {X: 30, Y: 30}, + {X: 40, Y: 40}, + }, + }, + }, + }, + }, + } + s, err := RenderV3SVGOverlayEmbedded(page) + if err != nil { + t.Fatal(err) + } + if !strings.Contains(s, "]*>`) +) + +// RenderV6PNGWithRMC renders a v6 .rm page to a fixed 1404×1872 device PNG. +// SVG is produced via rmc (with optional inserted page images), then rasterized. +// rmc's default SVG page is the stroke bounding box; we force the device +// viewport (centered X, Y from 0) before rasterizing so PDF composites align. +func RenderV6PNGWithRMC(data []byte, images map[string][]byte) ([]byte, error) { + ver, err := ParseVersion(data) + if err != nil { + return nil, err + } + if ver != 6 { + return nil, fmt.Errorf("rmc rendering expects v6 .rm, got v%d", ver) + } + + svg, err := RenderV6SVGWithRMC(data, images) + if err != nil { + return nil, err + } + svg = ForceDeviceViewportSVG(svg) + + tmpDir, err := os.MkdirTemp("", "rmc-png-*") + if err != nil { + return nil, err + } + defer os.RemoveAll(tmpDir) + + svgPath := filepath.Join(tmpDir, "page.svg") + pngPath := filepath.Join(tmpDir, "page.png") + if err := os.WriteFile(svgPath, []byte(svg), 0600); err != nil { + return nil, err + } + + if err := rasterSVGToPNG(svgPath, pngPath, PageWidthPt, PageHeightPt); err != nil { + // Fallback: SVG → PDF (inkscape) → pdfraster at device width. + pdfPath := filepath.Join(tmpDir, "page.pdf") + if err2 := svgToPDFInkscape(svgPath, pdfPath); err2 != nil { + return nil, fmt.Errorf("raster svg: %v; svg→pdf: %v", err, err2) + } + pdfBytes, err2 := os.ReadFile(pdfPath) + if err2 != nil { + return nil, err2 + } + return pdfraster.RenderPage(pdfBytes, 1) + } + return os.ReadFile(pngPath) +} + +// ForceDeviceViewportSVG rewrites the root to the reMarkable device +// viewport used for PDF/notebook compositing (1404×1872 screen units). +func ForceDeviceViewportSVG(svg string) string { + viewBox := fmt.Sprintf("%.6f 0 %.6f %.6f", rmcXMinPt, rmcPageWidthPt, rmcPageHeightPt) + repl := fmt.Sprintf( + ``, + rmcPageWidthPt, rmcPageHeightPt, viewBox, + ) + if reSVGOpen.MatchString(svg) { + return reSVGOpen.ReplaceAllString(svg, repl) + } + return repl + "\n" + svg + "\n\n" +} + +func rasterSVGToPNG(svgPath, pngPath string, width, height int) error { + var errs []string + if bin, err := exec.LookPath("rsvg-convert"); err == nil { + cmd := exec.Command(bin, "-w", fmt.Sprintf("%d", width), "-h", fmt.Sprintf("%d", height), "-o", pngPath, svgPath) + var stderr bytes.Buffer + cmd.Stderr = &stderr + if err := cmd.Run(); err == nil { + return nil + } else { + errs = append(errs, fmt.Sprintf("rsvg-convert: %v %s", err, strings.TrimSpace(stderr.String()))) + } + } + if bin, err := exec.LookPath("inkscape"); err == nil { + cmd := exec.Command(bin, svgPath, + "--export-type=png", + "--export-filename="+pngPath, + fmt.Sprintf("--export-width=%d", width), + fmt.Sprintf("--export-height=%d", height), + ) + var stderr bytes.Buffer + cmd.Stderr = &stderr + if err := cmd.Run(); err == nil { + return nil + } else { + errs = append(errs, fmt.Sprintf("inkscape: %v %s", err, strings.TrimSpace(stderr.String()))) + } + } + if len(errs) == 0 { + return fmt.Errorf("no rsvg-convert or inkscape") + } + return fmt.Errorf("%s", strings.Join(errs, " | ")) +} + +func svgToPDFInkscape(svgPath, pdfPath string) error { + bin, err := exec.LookPath("inkscape") + if err != nil { + return err + } + cmd := exec.Command(bin, svgPath, "--export-type=pdf", "--export-filename="+pdfPath) + var stderr bytes.Buffer + cmd.Stderr = &stderr + if err := cmd.Run(); err != nil { + msg := strings.TrimSpace(stderr.String()) + if msg != "" { + return fmt.Errorf("%w: %s", err, msg) + } + return err + } + return nil +} + +func runRMCBinaryFmt(inPath, outPath, format string) error { + rmcBin := strings.TrimSpace(os.Getenv(EnvRMCBin)) + if rmcBin == "" { + var err error + rmcBin, err = exec.LookPath("rmc") + if err != nil { + return fmt.Errorf("rmc binary not found (set %s or install rmc): %w", EnvRMCBin, err) + } + } + cmd := exec.Command(rmcBin, "-t", format, "-o", outPath, inPath) + var stderr bytes.Buffer + cmd.Stderr = &stderr + if err := cmd.Run(); err != nil { + msg := strings.TrimSpace(stderr.String()) + if msg != "" { + return fmt.Errorf("rmc binary: %w: %s", err, msg) + } + return fmt.Errorf("rmc binary: %w", err) + } + return nil +} + +func runRMCModuleFmt(inPath, outPath, format string) error { + rmcSrc := EffectiveRMCSrc() + if rmcSrc == "" { + return fmt.Errorf("no rmc source (vendored third_party/rmc missing; set %s)", EnvRMCSrc) + } + python, err := exec.LookPath("python3") + if err != nil { + return fmt.Errorf("python3 not found: %w", err) + } + cmd := exec.Command(python, "-m", "rmc.cli", "-t", format, "-o", outPath, inPath) + if py := buildPythonPathForV6(rmcSrc); py != "" { + cmd.Env = append(os.Environ(), "PYTHONPATH="+py) + } + var stderr bytes.Buffer + cmd.Stderr = &stderr + if err := cmd.Run(); err != nil { + msg := strings.TrimSpace(stderr.String()) + if msg != "" { + return fmt.Errorf("python -m rmc.cli: %w: %s", err, msg) + } + return fmt.Errorf("python -m rmc.cli: %w", err) + } + return nil +} diff --git a/internal/rmdecode/rmc_svg.go b/internal/rmdecode/rmc_svg.go new file mode 100644 index 00000000..a125fbca --- /dev/null +++ b/internal/rmdecode/rmc_svg.go @@ -0,0 +1,149 @@ +package rmdecode + +import ( + "bytes" + "fmt" + "os" + "os/exec" + "path/filepath" + "strings" +) + +const ( + // EnvRMCBin points to an rmc executable (optional). If unset, PATH then vendored module is used. + EnvRMCBin = "RMFAKECLOUD_RMC_BIN" + // EnvRMCSrc optionally overrides the vendored third_party/rmc/src directory. + EnvRMCSrc = "RMFAKECLOUD_RMC_SRC" + // EnvRMSSceneSrc optionally overrides vendored third_party/rmscene/src. + EnvRMSSceneSrc = "RMFAKECLOUD_RMSCENE_SRC" +) + +// RenderV6SVGWithRMC renders a v6 .rm page to SVG by invoking rmc. +// Order: rmc binary (PATH/env) → python3 -m rmc.cli with vendored (or overridden) sources. +// images maps basename → bytes for files under {page}/ beside page.rm (inserted images). +func RenderV6SVGWithRMC(data []byte, images map[string][]byte) (string, error) { + ver, err := ParseVersion(data) + if err != nil { + return "", err + } + if ver != 6 { + return "", fmt.Errorf("rmc rendering expects v6 .rm, got v%d", ver) + } + + tmpDir, err := os.MkdirTemp("", "rmc-svg-*") + if err != nil { + return "", err + } + defer os.RemoveAll(tmpDir) + + inPath := filepath.Join(tmpDir, "page.rm") + outPath := filepath.Join(tmpDir, "page.svg") + if err := os.WriteFile(inPath, data, 0600); err != nil { + return "", err + } + if err := stagePageImages(tmpDir, "page", images); err != nil { + return "", err + } + + var errs []string + if err := runRMCBinary(inPath, outPath); err == nil { + return readSVG(outPath) + } else { + errs = append(errs, err.Error()) + } + if err := runRMCModule(inPath, outPath); err == nil { + return readSVG(outPath) + } else { + errs = append(errs, err.Error()) + } + + return "", fmt.Errorf("rmc svg failed: %s", strings.Join(errs, " | ")) +} + +// stagePageImages writes image blobs under tmpDir/pageName/ so rmc can find them +// via Path(page.rm).with_suffix(""). +func stagePageImages(tmpDir, pageName string, images map[string][]byte) error { + if len(images) == 0 { + return nil + } + dir := filepath.Join(tmpDir, pageName) + if err := os.MkdirAll(dir, 0700); err != nil { + return err + } + for name, b := range images { + name = filepath.Base(strings.ReplaceAll(name, "\\", "/")) + if name == "" || name == "." || name == ".." { + continue + } + if err := os.WriteFile(filepath.Join(dir, name), b, 0600); err != nil { + return err + } + } + return nil +} + +func runRMCBinary(inPath, outPath string) error { + rmcBin := strings.TrimSpace(os.Getenv(EnvRMCBin)) + if rmcBin == "" { + var err error + rmcBin, err = exec.LookPath("rmc") + if err != nil { + return fmt.Errorf("rmc binary not found: %w", err) + } + } + cmd := exec.Command(rmcBin, "-t", "svg", "-o", outPath, inPath) + var stderr bytes.Buffer + cmd.Stderr = &stderr + if err := cmd.Run(); err != nil { + msg := strings.TrimSpace(stderr.String()) + if msg != "" { + return fmt.Errorf("rmc binary: %w: %s", err, msg) + } + return fmt.Errorf("rmc binary: %w", err) + } + return nil +} + +func runRMCModule(inPath, outPath string) error { + rmcSrc := EffectiveRMCSrc() + if rmcSrc == "" { + return fmt.Errorf("no rmc source (vendored third_party/rmc missing; set %s)", EnvRMCSrc) + } + python, err := exec.LookPath("python3") + if err != nil { + return fmt.Errorf("python3 not found: %w", err) + } + cmd := exec.Command(python, "-m", "rmc.cli", "-t", "svg", "-o", outPath, inPath) + if py := buildPythonPathForV6(rmcSrc); py != "" { + cmd.Env = append(os.Environ(), "PYTHONPATH="+py) + } + var stderr bytes.Buffer + cmd.Stderr = &stderr + if err := cmd.Run(); err != nil { + msg := strings.TrimSpace(stderr.String()) + if msg != "" { + return fmt.Errorf("python -m rmc.cli: %w: %s", err, msg) + } + return fmt.Errorf("python -m rmc.cli: %w", err) + } + return nil +} + +func readSVG(outPath string) (string, error) { + b, err := os.ReadFile(outPath) + if err != nil { + return "", err + } + return string(b), nil +} + +// RMCAvailable reports whether rmc can be invoked (binary, override, or vendored source). +func RMCAvailable() bool { + if strings.TrimSpace(os.Getenv(EnvRMCBin)) != "" { + return true + } + if _, err := exec.LookPath("rmc"); err == nil { + return true + } + return EffectiveRMCSrc() != "" +} diff --git a/internal/rmdecode/rmdecode.go b/internal/rmdecode/rmdecode.go new file mode 100644 index 00000000..5dbdca64 --- /dev/null +++ b/internal/rmdecode/rmdecode.go @@ -0,0 +1,64 @@ +// Package rmdecode decodes reMarkable page files (.rm / "lines" format). +// +// Version 3 and 5 use the linear format implemented in github.com/juruen/rmapi/encoding/rm. +// Version 6 uses a tagged block / scene tree format; use DecodeV6Summary with Python +// and the rmscene library, or see scripts/rmdecode_v6_summary.py. +// +// References: +// - https://plasma.ninja/blog/devices/remarkable/binary/format/2017/12/26/reMarkable-lines-file-format.html +// - https://github.com/chemag/maxio/blob/master/version6.md +// - https://github.com/ricklupton/rmscene +package rmdecode + +import ( + "errors" + "fmt" + "strconv" + "strings" + + "github.com/juruen/rmapi/encoding/rm" +) + +// HeaderLen is the fixed size of the ASCII header prefix (v3/v5/v6). +const HeaderLen = 43 + +const headerPrefix = "reMarkable .lines file, version=" + +// ErrShortFile is returned when data is shorter than HeaderLen. +var ErrShortFile = errors.New("rm file too short for header") + +// ParseVersion reads the version digit(s) from the first 43 bytes of a .rm file. +func ParseVersion(data []byte) (int, error) { + if len(data) < HeaderLen { + return 0, ErrShortFile + } + s := string(data[:HeaderLen]) + if !strings.HasPrefix(s, headerPrefix) { + return 0, fmt.Errorf("not a reMarkable .lines file (expected header %q)", headerPrefix) + } + rest := strings.TrimPrefix(s, headerPrefix) + i := 0 + for i < len(rest) && rest[i] >= '0' && rest[i] <= '9' { + i++ + } + if i == 0 { + return 0, fmt.Errorf("no version number in header") + } + return strconv.Atoi(rest[:i]) +} + +// DecodeLegacy parses v3 or v5 .rm bytes into rmapi's Rm struct. +func DecodeLegacy(data []byte) (*rm.Rm, error) { + v, err := ParseVersion(data) + if err != nil { + return nil, err + } + if v != 3 && v != 5 { + return nil, fmt.Errorf("DecodeLegacy: expected version 3 or 5, got %d (use rmscene for v6)", v) + } + var page rm.Rm + if err := page.UnmarshalBinary(data); err != nil { + return nil, err + } + return &page, nil +} diff --git a/internal/rmdecode/rmdecode_test.go b/internal/rmdecode/rmdecode_test.go new file mode 100644 index 00000000..ebcbd865 --- /dev/null +++ b/internal/rmdecode/rmdecode_test.go @@ -0,0 +1,35 @@ +package rmdecode + +import ( + "strings" + "testing" +) + +func TestParseVersion_V6SampleHeader(t *testing.T) { + // v6 header is exactly 43 bytes: prefix + "6" + spaces + hdr := []byte("reMarkable .lines file, version=6" + strings.Repeat(" ", 10)) + if len(hdr) != HeaderLen { + t.Fatalf("test header length %d, want %d", len(hdr), HeaderLen) + } + v, err := ParseVersion(hdr) + if err != nil { + t.Fatal(err) + } + if v != 6 { + t.Fatalf("version %d, want 6", v) + } +} + +func TestParseVersion_V5(t *testing.T) { + hdr := []byte("reMarkable .lines file, version=5 ") + if len(hdr) != HeaderLen { + t.Fatal("bad test header length") + } + v, err := ParseVersion(hdr) + if err != nil { + t.Fatal(err) + } + if v != 5 { + t.Fatalf("version %d, want 5", v) + } +} diff --git a/internal/rmdecode/zoom_png.go b/internal/rmdecode/zoom_png.go new file mode 100644 index 00000000..525b1169 --- /dev/null +++ b/internal/rmdecode/zoom_png.go @@ -0,0 +1,244 @@ +package rmdecode + +import ( + "bytes" + "image" + "image/draw" + "image/png" + "math" +) + +// ZoomPNGAboutCenter scales image content about its center by factor (<1 zooms out), +// filling new margins with white. Factor <=0 or ~1 is a no-op. +func ZoomPNGAboutCenter(pngBytes []byte, factor float64) ([]byte, error) { + img, err := png.Decode(bytes.NewReader(pngBytes)) + if err != nil { + return nil, err + } + src := toNRGBAImg(img) + w, h := src.Bounds().Dx(), src.Bounds().Dy() + return zoomPNGAbout(src, float64(w)/2, float64(h)/2, factor) +} + +// ZoomPNGAboutPoint scales about (cx, cy) in image pixel coordinates. +func ZoomPNGAboutPoint(pngBytes []byte, cx, cy, factor float64) ([]byte, error) { + img, err := png.Decode(bytes.NewReader(pngBytes)) + if err != nil { + return nil, err + } + return zoomPNGAbout(toNRGBAImg(img), cx, cy, factor) +} + +func zoomPNGAbout(src *image.NRGBA, cx, cy, factor float64) ([]byte, error) { + if factor <= 0 || math.Abs(factor-1) < 1e-6 { + var buf bytes.Buffer + if err := png.Encode(&buf, src); err != nil { + return nil, err + } + return buf.Bytes(), nil + } + w, h := src.Bounds().Dx(), src.Bounds().Dy() + if w < 1 || h < 1 { + var buf bytes.Buffer + if err := png.Encode(&buf, src); err != nil { + return nil, err + } + return buf.Bytes(), nil + } + dst := image.NewNRGBA(image.Rect(0, 0, w, h)) + for i := 0; i < len(dst.Pix); i += 4 { + dst.Pix[i+0] = 255 + dst.Pix[i+1] = 255 + dst.Pix[i+2] = 255 + dst.Pix[i+3] = 255 + } + inv := 1 / factor + for y := 0; y < h; y++ { + sy := cy + (float64(y)-cy)*inv + siy := int(math.Floor(sy)) + if siy < 0 || siy >= h { + continue + } + for x := 0; x < w; x++ { + sx := cx + (float64(x)-cx)*inv + six := int(math.Floor(sx)) + if six < 0 || six >= w { + continue + } + si := src.PixOffset(six, siy) + di := dst.PixOffset(x, y) + copy(dst.Pix[di:di+4], src.Pix[si:si+4]) + } + } + var buf bytes.Buffer + if err := png.Encode(&buf, dst); err != nil { + return nil, err + } + return buf.Bytes(), nil +} + +// SquishPNG scales content about the image center. Positive shrink compresses; +// negative stretch (edges clip on the fixed canvas). +func SquishPNG(pngBytes []byte, shrinkXPx, shrinkYPx int) ([]byte, error) { + img, err := png.Decode(bytes.NewReader(pngBytes)) + if err != nil { + return nil, err + } + src := toNRGBAImg(img) + w, h := src.Bounds().Dx(), src.Bounds().Dy() + return squishPNGAbout(src, float64(w)/2, float64(h)/2, shrinkXPx, shrinkYPx) +} + +// SquishPNGAboutPoint scales about (cx, cy). +func SquishPNGAboutPoint(pngBytes []byte, cx, cy float64, shrinkXPx, shrinkYPx int) ([]byte, error) { + img, err := png.Decode(bytes.NewReader(pngBytes)) + if err != nil { + return nil, err + } + return squishPNGAbout(toNRGBAImg(img), cx, cy, shrinkXPx, shrinkYPx) +} + +func squishPNGAbout(src *image.NRGBA, cx, cy float64, shrinkXPx, shrinkYPx int) ([]byte, error) { + if shrinkXPx == 0 && shrinkYPx == 0 { + var buf bytes.Buffer + if err := png.Encode(&buf, src); err != nil { + return nil, err + } + return buf.Bytes(), nil + } + w, h := src.Bounds().Dx(), src.Bounds().Dy() + sx := 1.0 + sy := 1.0 + if shrinkXPx > 0 { + if w <= shrinkXPx { + var buf bytes.Buffer + if err := png.Encode(&buf, src); err != nil { + return nil, err + } + return buf.Bytes(), nil + } + sx = float64(w-shrinkXPx) / float64(w) + } else if shrinkXPx < 0 { + sx = float64(w-shrinkXPx) / float64(w) + } + if shrinkYPx > 0 { + if h <= shrinkYPx { + var buf bytes.Buffer + if err := png.Encode(&buf, src); err != nil { + return nil, err + } + return buf.Bytes(), nil + } + sy = float64(h-shrinkYPx) / float64(h) + } else if shrinkYPx < 0 { + sy = float64(h-shrinkYPx) / float64(h) + } + return scalePNGXYAbout(src, cx, cy, sx, sy) +} + +func scalePNGXYAbout(src *image.NRGBA, cx, cy, sx, sy float64) ([]byte, error) { + if sx <= 0 || sy <= 0 { + return nil, nil + } + w, h := src.Bounds().Dx(), src.Bounds().Dy() + dst := image.NewNRGBA(image.Rect(0, 0, w, h)) + for i := 0; i < len(dst.Pix); i += 4 { + dst.Pix[i+0] = 255 + dst.Pix[i+1] = 255 + dst.Pix[i+2] = 255 + dst.Pix[i+3] = 255 + } + invX := 1 / sx + invY := 1 / sy + for y := 0; y < h; y++ { + sySrc := cy + (float64(y)-cy)*invY + siy := int(math.Floor(sySrc)) + if siy < 0 || siy >= h { + continue + } + for x := 0; x < w; x++ { + sxSrc := cx + (float64(x)-cx)*invX + six := int(math.Floor(sxSrc)) + if six < 0 || six >= w { + continue + } + si := src.PixOffset(six, siy) + di := dst.PixOffset(x, y) + copy(dst.Pix[di:di+4], src.Pix[si:si+4]) + } + } + var buf bytes.Buffer + if err := png.Encode(&buf, dst); err != nil { + return nil, err + } + return buf.Bytes(), nil +} + +// NudgePNG translates image content by (dx, dy) pixels (dy negative = up). +// Expands the canvas so no ink is cropped; vacated areas are white. +// Returns the new PNG and how much the top-left of the previous image shifted +// into the new canvas (always >= 0). +func NudgePNG(pngBytes []byte, dx, dy int) ([]byte, error) { + out, _, _, err := NudgePNGExt(pngBytes, dx, dy) + return out, err +} + +// NudgePNGExt is NudgePNG plus the draw offset of the old image in the new canvas. +func NudgePNGExt(pngBytes []byte, dx, dy int) ([]byte, int, int, error) { + if dx == 0 && dy == 0 { + return pngBytes, 0, 0, nil + } + img, err := png.Decode(bytes.NewReader(pngBytes)) + if err != nil { + return nil, 0, 0, err + } + src := toNRGBAImg(img) + w, h := src.Bounds().Dx(), src.Bounds().Dy() + minX := 0 + if dx < 0 { + minX = dx + } + minY := 0 + if dy < 0 { + minY = dy + } + maxX := w + if dx+w > maxX { + maxX = dx + w + } + maxY := h + if dy+h > maxY { + maxY = dy + h + } + nw, nh := maxX-minX, maxY-minY + if nw < 1 { + nw = 1 + } + if nh < 1 { + nh = 1 + } + dst := image.NewNRGBA(image.Rect(0, 0, nw, nh)) + for i := 0; i < len(dst.Pix); i += 4 { + dst.Pix[i+0] = 255 + dst.Pix[i+1] = 255 + dst.Pix[i+2] = 255 + dst.Pix[i+3] = 255 + } + ox, oy := dx-minX, dy-minY + draw.Draw(dst, image.Rect(ox, oy, ox+w, oy+h), src, image.Point{}, draw.Src) + var buf bytes.Buffer + if err := png.Encode(&buf, dst); err != nil { + return nil, 0, 0, err + } + return buf.Bytes(), ox, oy, nil +} + +func toNRGBAImg(src image.Image) *image.NRGBA { + if n, ok := src.(*image.NRGBA); ok { + return n + } + b := src.Bounds() + dst := image.NewNRGBA(b) + draw.Draw(dst, b, src, b.Min, draw.Src) + return dst +} diff --git a/internal/rmdecode/zoom_png_test.go b/internal/rmdecode/zoom_png_test.go new file mode 100644 index 00000000..b84fbd61 --- /dev/null +++ b/internal/rmdecode/zoom_png_test.go @@ -0,0 +1,67 @@ +package rmdecode + +import ( + "bytes" + "image" + "image/color" + "image/png" + "testing" +) + +func TestInkDeviceMetaRoundTrip(t *testing.T) { + img := image.NewNRGBA(image.Rect(0, 0, 8, 8)) + for i := range img.Pix { + img.Pix[i] = 255 + } + var buf bytes.Buffer + if err := png.Encode(&buf, img); err != nil { + t.Fatal(err) + } + meta := InkDeviceMeta{OriginX: 12, OriginY: 34, ViewW: 1404, ViewH: 1872} + out, err := WriteInkDeviceMeta(buf.Bytes(), meta) + if err != nil { + t.Fatal(err) + } + got := ReadInkDeviceMeta(out) + if got != meta { + t.Fatalf("got %+v want %+v", got, meta) + } +} + +func TestNudgePNGNoCropUp(t *testing.T) { + const w, h, n = 40, 60, 15 + src := image.NewNRGBA(image.Rect(0, 0, w, h)) + for y := 0; y < h; y++ { + for x := 0; x < w; x++ { + src.SetNRGBA(x, y, color.NRGBA{R: 255, G: 255, B: 255, A: 255}) + } + } + src.SetNRGBA(3, 0, color.NRGBA{R: 0, G: 0, B: 0, A: 255}) + src.SetNRGBA(5, h-1, color.NRGBA{R: 10, G: 20, B: 30, A: 255}) + + var buf bytes.Buffer + if err := png.Encode(&buf, src); err != nil { + t.Fatal(err) + } + out, err := NudgePNG(buf.Bytes(), 0, -n) + if err != nil { + t.Fatal(err) + } + img, err := png.Decode(bytes.NewReader(out)) + if err != nil { + t.Fatal(err) + } + b := img.Bounds() + if b.Dx() != w || b.Dy() != h+n { + t.Fatalf("size %dx%d, want %dx%d", b.Dx(), b.Dy(), w, h+n) + } + got := toNRGBAImg(img) + r, g, bl, _ := got.At(3, 0).RGBA() + if r>>8 != 0 || g>>8 != 0 || bl>>8 != 0 { + t.Fatalf("top ink must be preserved, got %d,%d,%d", r>>8, g>>8, bl>>8) + } + r, g, bl, _ = got.At(5, h-1).RGBA() + if r>>8 != 10 || g>>8 != 20 || bl>>8 != 30 { + t.Fatalf("bottom ink misplaced, got %d,%d,%d", r>>8, g>>8, bl>>8) + } +} diff --git a/internal/storage/epub/cover.go b/internal/storage/epub/cover.go new file mode 100644 index 00000000..95769cdd --- /dev/null +++ b/internal/storage/epub/cover.go @@ -0,0 +1,153 @@ +package epub + +import ( + "archive/zip" + "errors" + "io" + "path" + "regexp" + "sort" + "strings" +) + +var ( + imgSrcRE = regexp.MustCompile(`(?i)]+src\s*=\s*["']([^"']+)["']`) + // SVG (some EPUBs) + imageHrefRE = regexp.MustCompile(`(?i)]+href\s*=\s*["']([^"']+)["']`) +) + +// FindCoverImagePath returns a zip-relative path to an image file suitable for a thumbnail. +// It scans for these XHTML/HTML files (case-insensitive basename, any directory): +// cover.xhtml, cover.html, cover.htm, then any *0000.xhtml (e.g. part0000.xhtml) — in that priority order. +// The first (or ) pointing to a raster or SVG inside the zip wins. +func FindCoverImagePath(zr *zip.Reader) (string, error) { + type cand struct { + path string + pri int + } + var cands []cand + for _, f := range zr.File { + if f.FileInfo().IsDir() { + continue + } + base := strings.ToLower(path.Base(f.Name)) + var pri int + switch base { + case "cover.xhtml": + pri = 1 + case "cover.html": + pri = 2 + case "cover.htm": + pri = 3 + default: + if strings.HasSuffix(base, "0000.xhtml") { + pri = 4 + } else { + continue + } + } + cands = append(cands, cand{f.Name, pri}) + } + sort.Slice(cands, func(i, j int) bool { + if cands[i].pri != cands[j].pri { + return cands[i].pri < cands[j].pri + } + return cands[i].path < cands[j].path + }) + + for _, c := range cands { + rc, err := OpenZipFile(zr, c.path) + if err != nil { + continue + } + b, err := io.ReadAll(rc) + _ = rc.Close() + if err != nil { + continue + } + var src string + if m := imgSrcRE.FindSubmatch(b); len(m) >= 2 { + src = strings.TrimSpace(string(m[1])) + } else if m := imageHrefRE.FindSubmatch(b); len(m) >= 2 { + src = strings.TrimSpace(string(m[1])) + } + if src == "" { + continue + } + imgPath := resolveImgHref(c.path, src) + if imgPath == "" { + continue + } + if _, err := OpenZipFile(zr, imgPath); err != nil { + continue + } + ext := strings.ToLower(path.Ext(imgPath)) + switch ext { + case ".jpg", ".jpeg", ".png", ".gif", ".webp", ".svg": + return imgPath, nil + } + } + return "", errors.New("no cover image found") +} + +// FindFirstImageInFile returns the first raster/SVG image referenced by an HTML/XHTML zip entry. +func FindFirstImageInFile(zr *zip.Reader, htmlPath string) (string, error) { + rc, err := OpenZipFile(zr, htmlPath) + if err != nil { + return "", err + } + b, err := io.ReadAll(rc) + _ = rc.Close() + if err != nil { + return "", err + } + var src string + if m := imgSrcRE.FindSubmatch(b); len(m) >= 2 { + src = strings.TrimSpace(string(m[1])) + } else if m := imageHrefRE.FindSubmatch(b); len(m) >= 2 { + src = strings.TrimSpace(string(m[1])) + } + if src == "" { + return "", errors.New("no image in file") + } + imgPath := resolveImgHref(htmlPath, src) + if imgPath == "" { + return "", errors.New("no image in file") + } + if _, err := OpenZipFile(zr, imgPath); err != nil { + return "", err + } + ext := strings.ToLower(path.Ext(imgPath)) + switch ext { + case ".jpg", ".jpeg", ".png", ".gif", ".webp", ".svg": + return imgPath, nil + } + return "", errors.New("no image in file") +} + +func resolveImgHref(htmlPath, src string) string { + src = strings.TrimSpace(src) + if i := strings.IndexByte(src, '?'); i >= 0 { + src = src[:i] + } + if src == "" { + return "" + } + if strings.HasPrefix(src, "http://") || strings.HasPrefix(src, "https://") { + return "" + } + if strings.HasPrefix(src, "mailto:") { + return "" + } + htmlDir := path.Dir(htmlPath) + if strings.HasPrefix(src, "/") { + src = strings.TrimPrefix(path.Clean(src), "/") + return src + } + out := path.Join(htmlDir, src) + out = path.Clean(out) + if strings.HasPrefix(out, "..") { + return "" + } + return out +} diff --git a/internal/storage/epub/cover_test.go b/internal/storage/epub/cover_test.go new file mode 100644 index 00000000..e380e247 --- /dev/null +++ b/internal/storage/epub/cover_test.go @@ -0,0 +1,63 @@ +package epub + +import ( + "archive/zip" + "bytes" + "testing" +) + +func TestFindCoverImagePath(t *testing.T) { + buf := new(bytes.Buffer) + zw := zip.NewWriter(buf) + must := func(err error) { + t.Helper() + if err != nil { + t.Fatal(err) + } + } + w, err := zw.Create("OEBPS/cover.xhtml") + must(err) + _, err = w.Write([]byte(``)) + must(err) + w, err = zw.Create("OEBPS/images/c.jpg") + must(err) + _, err = w.Write([]byte{0xff, 0xd8, 0xff, 0xe0}) // fake JPEG header + must(err) + must(zw.Close()) + + zr, err := zip.NewReader(bytes.NewReader(buf.Bytes()), int64(buf.Len())) + must(err) + p, err := FindCoverImagePath(zr) + must(err) + if p != "OEBPS/images/c.jpg" { + t.Fatalf("got %q", p) + } +} + +func TestFindFirstImageInFile(t *testing.T) { + buf := new(bytes.Buffer) + zw := zip.NewWriter(buf) + must := func(err error) { + t.Helper() + if err != nil { + t.Fatal(err) + } + } + w, err := zw.Create("OEBPS/ch1.xhtml") + must(err) + _, err = w.Write([]byte(`

x

`)) + must(err) + w, err = zw.Create("OEBPS/images/p.png") + must(err) + _, err = w.Write([]byte{0x89, 0x50, 0x4e, 0x47}) + must(err) + must(zw.Close()) + + zr, err := zip.NewReader(bytes.NewReader(buf.Bytes()), int64(buf.Len())) + must(err) + p, err := FindFirstImageInFile(zr, "OEBPS/ch1.xhtml") + must(err) + if p != "OEBPS/images/p.png" { + t.Fatalf("got %q", p) + } +} diff --git a/internal/storage/epub/manifest.go b/internal/storage/epub/manifest.go new file mode 100644 index 00000000..ee45c3b2 --- /dev/null +++ b/internal/storage/epub/manifest.go @@ -0,0 +1,172 @@ +package epub + +import ( + "archive/zip" + "encoding/xml" + "errors" + "io" + "path" + "strings" +) + +// ErrNotEpub is returned when the archive does not appear to be a valid EPUB. +var ErrNotEpub = errors.New("not a valid EPUB") + +// Manifest holds the reading order (spine) and base path for resolving relative URLs. +type Manifest struct { + Spine []string `json:"spine"` // paths relative to zip root (e.g. OEBPS/ch1.xhtml) + BasePath string `json:"basePath"` // directory of the OPF, for relative resolution +} + +type containerRoot struct { + XMLName xml.Name `xml:"container"` + RootFiles struct { + Rootfile []struct { + FullPath string `xml:"full-path,attr"` + MediaType string `xml:"media-type,attr"` + } `xml:"rootfile"` + } `xml:"rootfiles"` +} + +type opfPackage struct { + XMLName xml.Name `xml:"http://www.idpf.org/2007/opf package"` + Manifest struct { + Items []struct { + ID string `xml:"id,attr"` + Href string `xml:"href,attr"` + MediaType string `xml:"media-type,attr"` + } `xml:"item"` + } `xml:"manifest"` + Spine struct { + Itemrefs []struct { + IDRef string `xml:"idref,attr"` + } `xml:"itemref"` + } `xml:"spine"` +} + +// ReadManifest parses the EPUB zip and returns the spine (ordered content paths) and OPF base path. +func ReadManifest(zr *zip.Reader) (*Manifest, error) { + // 1. Find and parse META-INF/container.xml + containerFile, err := openZipFile(zr, "META-INF/container.xml") + if err != nil { + return nil, err + } + defer containerFile.Close() + containerBytes, err := io.ReadAll(containerFile) + if err != nil { + return nil, err + } + var c containerRoot + if err := xml.Unmarshal(containerBytes, &c); err != nil { + return nil, err + } + if len(c.RootFiles.Rootfile) == 0 { + return nil, ErrNotEpub + } + rootPath := c.RootFiles.Rootfile[0].FullPath + rootPath = strings.TrimPrefix(path.Clean("/"+rootPath), "/") + + // 2. Parse OPF + opfFile, err := openZipFile(zr, rootPath) + if err != nil { + return nil, err + } + defer opfFile.Close() + opfBytes, err := io.ReadAll(opfFile) + if err != nil { + return nil, err + } + var pkg opfPackage + if err := xml.Unmarshal(opfBytes, &pkg); err != nil { + return nil, err + } + opfDir := path.Dir(rootPath) + if opfDir == "." { + opfDir = "" + } + idToHref := make(map[string]string) + for _, it := range pkg.Manifest.Items { + idToHref[it.ID] = it.Href + } + var spine []string + for _, ref := range pkg.Spine.Itemrefs { + href, ok := idToHref[ref.IDRef] + if !ok { + continue + } + // Resolve href relative to OPF directory + fullPath := path.Join(opfDir, href) + fullPath = path.Clean(fullPath) + if strings.HasPrefix(fullPath, "..") { + continue + } + spine = append(spine, fullPath) + } + if len(spine) == 0 { + return nil, ErrNotEpub + } + return &Manifest{ + Spine: spine, + BasePath: opfDir, + }, nil +} + +func openZipFile(zr *zip.Reader, name string) (io.ReadCloser, error) { + name = zipEntryName(name) + if name == "" || name == "." || strings.HasPrefix(name, "..") { + return nil, errors.New("invalid path") + } + for _, f := range zr.File { + if zipEntryName(f.Name) == name { + return f.Open() + } + } + return nil, errors.New("file not found") +} + +func zipEntryName(name string) string { + name = strings.ReplaceAll(name, "\\", "/") + name = path.Clean(name) + return strings.TrimPrefix(name, "/") +} + +// OpenZipFile returns a reader for a file inside the zip by path (relative to zip root). +// Path must not contain "..". +func OpenZipFile(zr *zip.Reader, filePath string) (io.ReadCloser, error) { + return openZipFile(zr, filePath) +} + +// ContentType returns a suitable Content-Type for an EPUB resource by extension. +func ContentType(filePath string) string { + ext := strings.ToLower(path.Ext(filePath)) + switch ext { + case ".xhtml", ".html", ".htm": + return "text/html; charset=utf-8" + case ".xml", ".ncx": + return "application/xml" + case ".opf": + return "application/oebps-package+xml" + case ".css": + return "text/css; charset=utf-8" + case ".jpg", ".jpeg": + return "image/jpeg" + case ".png": + return "image/png" + case ".gif": + return "image/gif" + case ".webp": + return "image/webp" + case ".svg": + return "image/svg+xml" + case ".woff": + return "font/woff" + case ".woff2": + return "font/woff2" + case ".ttf": + return "font/ttf" + case ".otf": + return "font/otf" + default: + return "application/octet-stream" + } +} diff --git a/internal/storage/exporter/background_png.go b/internal/storage/exporter/background_png.go new file mode 100644 index 00000000..fa807e52 --- /dev/null +++ b/internal/storage/exporter/background_png.go @@ -0,0 +1,107 @@ +package exporter + +import ( + "bytes" + "fmt" + "image/png" + "io" + + "github.com/ddvk/rmfakecloud/internal/pdfraster" + pdf "github.com/unidoc/unipdf/v3/model" + "github.com/unidoc/unipdf/v3/render" +) + +func init() { + pdfraster.UnipdfFallback = renderPayloadPDFBytesUnipdf +} + +// PDFPageSizePts returns MediaBox width/height in points for a 1-based page. +func PDFPageSizePts(pdfBytes []byte, pageNum int) (widthPt, heightPt float64, err error) { + if len(pdfBytes) == 0 { + return 0, 0, fmt.Errorf("empty pdf") + } + pdfReader, err := pdf.NewPdfReader(bytes.NewReader(pdfBytes)) + if err != nil { + return 0, 0, fmt.Errorf("open pdf: %w", err) + } + numPages, err := pdfReader.GetNumPages() + if err != nil { + return 0, 0, err + } + if pageNum < 1 || pageNum > numPages { + return 0, 0, fmt.Errorf("page %d out of range (1-%d)", pageNum, numPages) + } + page, err := pdfReader.GetPage(pageNum) + if err != nil { + return 0, 0, err + } + mbox, err := page.GetMediaBox() + if err != nil { + return 0, 0, err + } + w := mbox.Urx - mbox.Llx + h := mbox.Ury - mbox.Lly + if w < 1 || h < 1 { + return 0, 0, fmt.Errorf("invalid media box %gx%g", w, h) + } + return w, h, nil +} + +// RenderPDFBytesToPNG rasters one PDF page (1-based) to PNG via pdfraster. +func RenderPDFBytesToPNG(pdfBytes []byte, pageNum int) ([]byte, error) { + return pdfraster.RenderPage(pdfBytes, pageNum) +} + +// RenderPayloadPagePNG renders a single page of the *payload* PDF to PNG. +// pageNum is 1-based. Returns PNG bytes. +func RenderPayloadPagePNG(a *MyArchive, pageNum int) ([]byte, error) { + if a == nil || a.PayloadReader == nil { + return nil, fmt.Errorf("no payload reader") + } + if _, err := a.PayloadReader.Seek(0, io.SeekStart); err != nil { + return nil, err + } + b, err := io.ReadAll(a.PayloadReader) + if err != nil { + return nil, err + } + return pdfraster.RenderPage(b, pageNum) +} + +// RenderPayloadPagePNGReader is like RenderPayloadPagePNG but returns a ReadCloser. +func RenderPayloadPagePNGReader(a *MyArchive, pageNum int) (io.ReadCloser, error) { + b, err := RenderPayloadPagePNG(a, pageNum) + if err != nil { + return nil, err + } + return NewSeekCloser(b), nil +} + +func renderPayloadPDFBytesUnipdf(pdfBytes []byte, pageNum int) ([]byte, error) { + pdfReader, err := pdf.NewPdfReader(bytes.NewReader(pdfBytes)) + if err != nil { + return nil, fmt.Errorf("open pdf: %w", err) + } + numPages, err := pdfReader.GetNumPages() + if err != nil { + return nil, err + } + if pageNum < 1 || pageNum > numPages { + return nil, fmt.Errorf("page %d out of range (1-%d)", pageNum, numPages) + } + page, err := pdfReader.GetPage(pageNum) + if err != nil { + return nil, err + } + device := render.NewImageDevice() + device.OutputWidth = pdfraster.DevicePortraitWidth + img, err := device.Render(page) + if err != nil { + return nil, fmt.Errorf("render page: %w", err) + } + var out bytes.Buffer + if err := png.Encode(&out, img); err != nil { + return nil, err + } + return out.Bytes(), nil +} diff --git a/internal/storage/exporter/composite_png.go b/internal/storage/exporter/composite_png.go new file mode 100644 index 00000000..1dd792e3 --- /dev/null +++ b/internal/storage/exporter/composite_png.go @@ -0,0 +1,318 @@ +package exporter + +import ( + "bytes" + "fmt" + "image" + "image/draw" + "image/png" + "math" + + "github.com/ddvk/rmfakecloud/internal/rmdecode" +) + +// DeviceThumbSize matches on-device thumbnail storage (~384×512 portrait). +var ( + DeviceThumbPortrait = image.Pt(384, 512) + DeviceThumbLandscape = image.Pt(512, 384) +) + +// MultiplyBlendPNGs composites a white-backed ink PNG over a background PNG using +// multiply blending. The PDF/EPUB background is placed with rmapi-style width- or +// height-fit (top-left, natural aspect) into the ink page viewport. The returned +// image is cropped to that viewport — for PDF annotations this is the full PDF +// page raster (correct Letter aspect, no device letterbox squish). +// +// Both inputs are PNG bytes. target (if set) scales the final viewport. +func MultiplyBlendPNGs(bgPNG, inkPNG []byte, target *image.Point) ([]byte, error) { + bgImg, err := png.Decode(bytes.NewReader(bgPNG)) + if err != nil { + return nil, fmt.Errorf("decode background: %w", err) + } + inkImg, err := png.Decode(bytes.NewReader(inkPNG)) + if err != nil { + return nil, fmt.Errorf("decode ink: %w", err) + } + + ink := toNRGBA(inkImg) + meta := rmdecode.ReadInkDeviceMeta(inkPNG) + if meta.ViewW < 1 { + meta.ViewW = rmdecode.PageWidthPt + } + if meta.ViewH < 1 { + meta.ViewH = rmdecode.PageHeightPt + } + bg := placeBackgroundOnInkCanvas(toNRGBA(bgImg), ink.Bounds().Dx(), ink.Bounds().Dy(), meta) + + full := image.NewNRGBA(ink.Bounds()) + w, h := ink.Bounds().Dx(), ink.Bounds().Dy() + for y := 0; y < h; y++ { + for x := 0; x < w; x++ { + bi := bg.PixOffset(x, y) + ii := ink.PixOffset(x, y) + full.Pix[ii+0] = mul8(bg.Pix[bi+0], ink.Pix[ii+0]) + full.Pix[ii+1] = mul8(bg.Pix[bi+1], ink.Pix[ii+1]) + full.Pix[ii+2] = mul8(bg.Pix[bi+2], ink.Pix[ii+2]) + full.Pix[ii+3] = 255 + } + } + + ox, oy := meta.OriginX, meta.OriginY + vw, vh := meta.ViewW, meta.ViewH + if ox < 0 { + ox = 0 + } + if oy < 0 { + oy = 0 + } + if ox+vw > w { + vw = w - ox + } + if oy+vh > h { + vh = h - oy + } + if vw < 1 { + vw = 1 + } + if vh < 1 { + vh = 1 + } + out := cropNRGBA(full, ox, oy, vw, vh) + + if target != nil && target.X > 0 && target.Y > 0 { + out = scaleNRGBA(out, target.X, target.Y) + } + + var buf bytes.Buffer + if err := png.Encode(&buf, out); err != nil { + return nil, err + } + return buf.Bytes(), nil +} + +// placeBackgroundOnInkCanvas draws the PDF/EPUB background into a white ink +// canvas using rmapi fit (width- or height-fill, top-left, natural aspect) +// inside the device viewport at meta.Origin. +func placeBackgroundOnInkCanvas(bg *image.NRGBA, iw, ih int, meta rmdecode.InkDeviceMeta) *image.NRGBA { + if iw < 1 { + iw = 1 + } + if ih < 1 { + ih = 1 + } + viewW, viewH := meta.ViewW, meta.ViewH + if viewW < 1 { + viewW = rmdecode.PageWidthPt + } + if viewH < 1 { + viewH = rmdecode.PageHeightPt + } + if viewW > iw { + viewW = iw + } + if viewH > ih { + viewH = ih + } + ox, oy := meta.OriginX, meta.OriginY + if ox < 0 { + ox = 0 + } + if oy < 0 { + oy = 0 + } + if ox+viewW > iw { + ox = iw - viewW + if ox < 0 { + ox = 0 + } + } + if oy+viewH > ih { + oy = ih - viewH + if oy < 0 { + oy = 0 + } + } + + bw, bh := bg.Bounds().Dx(), bg.Bounds().Dy() + canvas := image.NewNRGBA(image.Rect(0, 0, iw, ih)) + for i := 0; i < len(canvas.Pix); i += 4 { + canvas.Pix[i+0] = 255 + canvas.Pix[i+1] = 255 + canvas.Pix[i+2] = 255 + canvas.Pix[i+3] = 255 + } + if bw < 1 || bh < 1 { + return canvas + } + if bw == viewW && bh == viewH && ox == 0 && oy == 0 && iw == viewW && ih == viewH { + return bg + } + + deviceAspect := float64(viewH) / float64(viewW) + pageAspect := float64(bh) / float64(bw) + + var dw, dh int + if pageAspect < deviceAspect { + dw = viewW + dh = int(math.Round(float64(bh) * float64(viewW) / float64(bw))) + } else { + dh = viewH + dw = int(math.Round(float64(bw) * float64(viewH) / float64(bh))) + } + if dw < 1 { + dw = 1 + } + if dh < 1 { + dh = 1 + } + scaled := bg + if dw != bw || dh != bh { + scaled = scaleNRGBA(bg, dw, dh) + } + draw.Draw(canvas, image.Rect(ox, oy, ox+dw, oy+dh), scaled, image.Point{}, draw.Src) + return canvas +} + +// fitInkToBackground samples the ink device canvas onto a background-sized image. +// Kept for tests/thumbs that still want a page-cropped blend. +func fitInkToBackground(ink *image.NRGBA, bw, bh int) *image.NRGBA { + if bw < 1 { + bw = 1 + } + if bh < 1 { + bh = 1 + } + iw, ih := ink.Bounds().Dx(), ink.Bounds().Dy() + if iw == bw && ih == bh { + return ink + } + + deviceAspect := float64(ih) / float64(iw) + pageAspect := float64(bh) / float64(bw) + + var dispW, dispH, ox, oy int + if pageAspect < deviceAspect { + dispW = iw + dispH = int(math.Round(float64(bh) * float64(iw) / float64(bw))) + if dispH > ih { + dispH = ih + } + ox, oy = 0, 0 + } else { + dispH = ih + dispW = int(math.Round(float64(bw) * float64(ih) / float64(bh))) + if dispW > iw { + dispW = iw + } + ox, oy = 0, 0 + } + if dispW < 1 { + dispW = 1 + } + if dispH < 1 { + dispH = 1 + } + + cropped := cropNRGBA(ink, ox, oy, dispW, dispH) + if dispW == bw && dispH == bh { + return cropped + } + return scaleNRGBA(cropped, bw, bh) +} + +func cropNRGBA(src *image.NRGBA, x, y, w, h int) *image.NRGBA { + sw, sh := src.Bounds().Dx(), src.Bounds().Dy() + if x < 0 { + x = 0 + } + if y < 0 { + y = 0 + } + if w < 1 { + w = 1 + } + if h < 1 { + h = 1 + } + if x+w > sw { + w = sw - x + } + if y+h > sh { + h = sh - y + } + if w < 1 { + w = 1 + } + if h < 1 { + h = 1 + } + dst := image.NewNRGBA(image.Rect(0, 0, w, h)) + for row := 0; row < h; row++ { + si := src.PixOffset(x, y+row) + di := dst.PixOffset(0, row) + copy(dst.Pix[di:di+4*w], src.Pix[si:si+4*w]) + } + return dst +} + +// ScalePNGToThumb scales a PNG to device thumbnail size, preserving orientation. +func ScalePNGToThumb(pngBytes []byte) ([]byte, error) { + img, err := png.Decode(bytes.NewReader(pngBytes)) + if err != nil { + return nil, err + } + b := img.Bounds() + var target image.Point + if b.Dx() >= b.Dy() { + target = DeviceThumbLandscape + } else { + target = DeviceThumbPortrait + } + scaled := scaleNRGBA(toNRGBA(img), target.X, target.Y) + var buf bytes.Buffer + if err := png.Encode(&buf, scaled); err != nil { + return nil, err + } + return buf.Bytes(), nil +} + +func mul8(a, b uint8) uint8 { + return uint8((uint16(a) * uint16(b)) / 255) +} + +func toNRGBA(src image.Image) *image.NRGBA { + if n, ok := src.(*image.NRGBA); ok { + return n + } + b := src.Bounds() + dst := image.NewNRGBA(b) + draw.Draw(dst, b, src, b.Min, draw.Src) + return dst +} + +func scaleNRGBA(src *image.NRGBA, tw, th int) *image.NRGBA { + if tw < 1 { + tw = 1 + } + if th < 1 { + th = 1 + } + dst := image.NewNRGBA(image.Rect(0, 0, tw, th)) + sw, sh := src.Bounds().Dx(), src.Bounds().Dy() + for y := 0; y < th; y++ { + sy := int(math.Floor(float64(y) * float64(sh) / float64(th))) + if sy >= sh { + sy = sh - 1 + } + for x := 0; x < tw; x++ { + sx := int(math.Floor(float64(x) * float64(sw) / float64(tw))) + if sx >= sw { + sx = sw - 1 + } + si := src.PixOffset(sx, sy) + di := dst.PixOffset(x, y) + copy(dst.Pix[di:di+4], src.Pix[si:si+4]) + } + } + return dst +} diff --git a/internal/storage/exporter/composite_png_test.go b/internal/storage/exporter/composite_png_test.go new file mode 100644 index 00000000..a7e8bc97 --- /dev/null +++ b/internal/storage/exporter/composite_png_test.go @@ -0,0 +1,164 @@ +package exporter + +import ( + "bytes" + "image" + "image/color" + "image/png" + "testing" +) + +func TestMultiplyBlendPNGs(t *testing.T) { + bg := image.NewNRGBA(image.Rect(0, 0, 2, 2)) + ink := image.NewNRGBA(image.Rect(0, 0, 2, 2)) + for y := 0; y < 2; y++ { + for x := 0; x < 2; x++ { + bg.SetNRGBA(x, y, color.NRGBA{R: 200, G: 200, B: 200, A: 255}) + ink.SetNRGBA(x, y, color.NRGBA{R: 255, G: 255, B: 255, A: 255}) + } + } + ink.SetNRGBA(0, 0, color.NRGBA{R: 0, G: 0, B: 0, A: 255}) + + var bgBuf, inkBuf bytes.Buffer + if err := png.Encode(&bgBuf, bg); err != nil { + t.Fatal(err) + } + if err := png.Encode(&inkBuf, ink); err != nil { + t.Fatal(err) + } + + out, err := MultiplyBlendPNGs(bgBuf.Bytes(), inkBuf.Bytes(), nil) + if err != nil { + t.Fatal(err) + } + img, err := png.Decode(bytes.NewReader(out)) + if err != nil { + t.Fatal(err) + } + n := toNRGBA(img) + // Black ink × gray bg → black + r, g, b, _ := n.At(0, 0).RGBA() + if r>>8 != 0 || g>>8 != 0 || b>>8 != 0 { + t.Fatalf("expected black at ink pixel, got %d,%d,%d", r>>8, g>>8, b>>8) + } + // White ink × gray bg → gray unchanged + r, g, b, _ = n.At(1, 1).RGBA() + if r>>8 != 200 || g>>8 != 200 || b>>8 != 200 { + t.Fatalf("expected gray where ink white, got %d,%d,%d", r>>8, g>>8, b>>8) + } +} + +func TestMultiplyBlendFullOverlayNoCrop(t *testing.T) { + // Device ink 1404×1872; PDF raster same width, shorter height (US Letter). + const iw, ih = 1404, 1872 + const bw, bh = 1404, 1817 + ink := image.NewNRGBA(image.Rect(0, 0, iw, ih)) + bg := image.NewNRGBA(image.Rect(0, 0, bw, bh)) + for y := 0; y < ih; y++ { + for x := 0; x < iw; x++ { + ink.SetNRGBA(x, y, color.NRGBA{R: 255, G: 255, B: 255, A: 255}) + } + } + for y := 0; y < bh; y++ { + for x := 0; x < bw; x++ { + bg.SetNRGBA(x, y, color.NRGBA{R: 180, G: 180, B: 180, A: 255}) + } + } + ink.SetNRGBA(99, 0, color.NRGBA{R: 0, G: 0, B: 0, A: 255}) + // Stroke below the PDF page must remain visible on the full canvas. + ink.SetNRGBA(42, bh+10, color.NRGBA{R: 0, G: 0, B: 0, A: 255}) + + var bgBuf, inkBuf bytes.Buffer + if err := png.Encode(&bgBuf, bg); err != nil { + t.Fatal(err) + } + if err := png.Encode(&inkBuf, ink); err != nil { + t.Fatal(err) + } + out, err := MultiplyBlendPNGs(bgBuf.Bytes(), inkBuf.Bytes(), nil) + if err != nil { + t.Fatal(err) + } + img, err := png.Decode(bytes.NewReader(out)) + if err != nil { + t.Fatal(err) + } + b := img.Bounds() + if b.Dx() != iw || b.Dy() != ih { + t.Fatalf("expected device viewport %dx%d, got %dx%d", iw, ih, b.Dx(), b.Dy()) + } + n := toNRGBA(img) + r, g, bl, _ := n.At(99, 0).RGBA() + if r>>8 != 0 || g>>8 != 0 || bl>>8 != 0 { + t.Fatalf("expected black at top-aligned edge, got %d,%d,%d", r>>8, g>>8, bl>>8) + } + r, g, bl, _ = n.At(42, bh+10).RGBA() + if r>>8 != 0 || g>>8 != 0 || bl>>8 != 0 { + t.Fatalf("expected below-page ink preserved (no crop), got %d,%d,%d", r>>8, g>>8, bl>>8) + } +} + +func TestMultiplyBlendExpandedInkKeepsTopStroke(t *testing.T) { + // Expanded ink taller than device; without metadata origin, viewport is top-left. + viewH := 1872 + pad := 50 + iw, ih := 1404, viewH+pad + ink := image.NewNRGBA(image.Rect(0, 0, iw, ih)) + bg := image.NewNRGBA(image.Rect(0, 0, 100, 100)) + for y := 0; y < ih; y++ { + for x := 0; x < iw; x++ { + ink.SetNRGBA(x, y, color.NRGBA{R: 255, G: 255, B: 255, A: 255}) + } + } + for y := 0; y < 100; y++ { + for x := 0; x < 100; x++ { + bg.SetNRGBA(x, y, color.NRGBA{R: 200, G: 200, B: 200, A: 255}) + } + } + ink.SetNRGBA(10, 0, color.NRGBA{R: 0, G: 0, B: 0, A: 255}) + + var bgBuf, inkBuf bytes.Buffer + if err := png.Encode(&bgBuf, bg); err != nil { + t.Fatal(err) + } + if err := png.Encode(&inkBuf, ink); err != nil { + t.Fatal(err) + } + out, err := MultiplyBlendPNGs(bgBuf.Bytes(), inkBuf.Bytes(), nil) + if err != nil { + t.Fatal(err) + } + img, err := png.Decode(bytes.NewReader(out)) + if err != nil { + t.Fatal(err) + } + if img.Bounds().Dx() != iw || img.Bounds().Dy() != viewH { + t.Fatalf("expected device crop %dx%d, got %dx%d", iw, viewH, img.Bounds().Dx(), img.Bounds().Dy()) + } + n := toNRGBA(img) + r, g, b, _ := n.At(10, 0).RGBA() + if r>>8 != 0 || g>>8 != 0 || b>>8 != 0 { + t.Fatalf("top ink in device viewport must remain, got %d,%d,%d", r>>8, g>>8, b>>8) + } +} + +func TestScalePNGToThumb(t *testing.T) { + src := image.NewNRGBA(image.Rect(0, 0, 1404, 1872)) + src.SetNRGBA(0, 0, color.NRGBA{R: 10, G: 20, B: 30, A: 255}) + var buf bytes.Buffer + if err := png.Encode(&buf, src); err != nil { + t.Fatal(err) + } + out, err := ScalePNGToThumb(buf.Bytes()) + if err != nil { + t.Fatal(err) + } + img, err := png.Decode(bytes.NewReader(out)) + if err != nil { + t.Fatal(err) + } + b := img.Bounds() + if b.Dx() != DeviceThumbPortrait.X || b.Dy() != DeviceThumbPortrait.Y { + t.Fatalf("thumb size %dx%d, want %dx%d", b.Dx(), b.Dy(), DeviceThumbPortrait.X, DeviceThumbPortrait.Y) + } +} diff --git a/internal/storage/filetypes.go b/internal/storage/filetypes.go index e1bf49e7..62716f66 100644 --- a/internal/storage/filetypes.go +++ b/internal/storage/filetypes.go @@ -5,6 +5,7 @@ const ( PageFileExt = ".pagedata" ContentFileExt = ".content" RmFileExt = ".rm" + TemplateFileExt = ".template" //ZipFileExt zip file extension ZipFileExt = ".zip" diff --git a/internal/storage/fs/blobstore.go b/internal/storage/fs/blobstore.go index cffa85f0..5751a2d1 100644 --- a/internal/storage/fs/blobstore.go +++ b/internal/storage/fs/blobstore.go @@ -53,6 +53,11 @@ func (fs *FileSystemStorage) GetCachedTree(uid string) (t *models.HashTree, err return nil, err } } + metaChanged := fs.ensureTemplateMetadata(tree, blobStorage) + labelChanged := fs.ensureFormatLabels(tree, blobStorage) + if metaChanged || labelChanged { + _ = tree.Save(cachePath) + } return tree, nil } @@ -128,6 +133,17 @@ func (fs *FileSystemStorage) Export(uid, docid string) (r io.ReadCloser, err err } ls := fs.BlobStorage(uid) + // PDF viewers / Download PDF need the source payload. Baking annotations via + // rmapi fails on v6 .rm ("Unknown header"); ink is served separately as page PNGs. + for _, f := range doc.Files { + if f == nil { + continue + } + if strings.HasSuffix(strings.ToLower(f.EntryName), storage.PdfFileExt) { + return ls.GetReader(f.Hash) + } + } + archive, err := models.ArchiveFromHashDoc(doc, ls) if err != nil { return nil, err @@ -137,22 +153,38 @@ func (fs *FileSystemStorage) Export(uid, docid string) (r io.ReadCloser, err err err = exporter.RenderRmapi(archive, writer) if err != nil { log.Error(err) - writer.Close() + writer.CloseWithError(err) return } writer.Close() }() - return reader, err + return reader, nil } // UpdateBlobDocument updates metadata func (fs *FileSystemStorage) UpdateBlobDocument(uid, docID, name, parent string) (err error) { + return fs.updateBlobDocumentMeta(uid, docID, func(doc *models.HashDoc) error { + log.Info("updateBlobDocument: ", doc.DocumentName, " new name:", name) + doc.DocumentName = name + doc.Parent = parent + return nil + }) +} + +// SetBlobDocumentPinned sets the favorite (★) flag in document metadata. +func (fs *FileSystemStorage) SetBlobDocumentPinned(uid, docID string, pinned bool) error { + return fs.updateBlobDocumentMeta(uid, docID, func(doc *models.HashDoc) error { + doc.Pinned = pinned + return nil + }) +} + +func (fs *FileSystemStorage) updateBlobDocumentMeta(uid, docID string, mut func(*models.HashDoc) error) (err error) { tree, err := fs.GetCachedTree(uid) if err != nil { - return nil + return err } - log.Info("updateBlobDocument: ", docID, "new name:", name) blobStorage := fs.BlobStorage(uid) err = updateTree(tree, blobStorage, func(t *models.HashTree) error { @@ -160,11 +192,12 @@ func (fs *FileSystemStorage) UpdateBlobDocument(uid, docID, name, parent string) if err != nil { return err } - log.Info("updateBlobDocument: ", hashDoc.DocumentName) - - hashDoc.DocumentName = name - hashDoc.Parent = parent + if err := mut(hashDoc); err != nil { + return err + } hashDoc.Version++ + hashDoc.MetadataModified = true + hashDoc.LastModified = models.FromTime(time.Now()) metadataHash, metadataReader, err := hashDoc.MetadataReader() if err != nil { @@ -176,7 +209,6 @@ func (fs *FileSystemStorage) UpdateBlobDocument(uid, docID, name, parent string) return err } - //update the metadata hash for _, hashEntry := range hashDoc.Files { if hashEntry.IsMetadata() { hashEntry.Hash = metadataHash @@ -323,11 +355,30 @@ func updateTree(tree *models.HashTree, storage *LocalBlobStorage, treeMutation f return errors.New("could not update") } +// GetTemplate returns the raw .template file for a given entry (if present). +func (fs *FileSystemStorage) GetTemplate(uid, docid string) (r io.ReadCloser, err error) { + tree, err := fs.GetCachedTree(uid) + if err != nil { + return nil, err + } + doc, err := tree.FindDoc(docid) + if err != nil { + return nil, err + } + ls := fs.BlobStorage(uid) + for _, f := range doc.Files { + if strings.HasSuffix(strings.ToLower(f.EntryName), storage.TemplateFileExt) { + return ls.GetReader(f.Hash) + } + } + return nil, errors.New("template not found") +} + // CreateBlobDocument creates a new document func (fs *FileSystemStorage) CreateBlobDocument(uid, filename, parent string, stream io.Reader) (doc *storage.Document, err error) { - ext := path.Ext(filename) + ext := strings.ToLower(path.Ext(filename)) switch ext { - case storage.EpubFileExt, storage.PdfFileExt, storage.RmDocFileExt: + case storage.EpubFileExt, storage.PdfFileExt, storage.RmDocFileExt, storage.TemplateFileExt: default: return nil, errors.New("unsupported extension: " + ext) } @@ -338,7 +389,7 @@ func (fs *FileSystemStorage) CreateBlobDocument(uid, filename, parent string, st blobPath := fs.getUserBlobPath(uid) docid := uuid.New().String() - docName := strings.TrimSuffix(filename, ext) + docName := strings.TrimSuffix(filename, path.Ext(filename)) tree, err := fs.GetCachedTree(uid) if err != nil { @@ -347,9 +398,13 @@ func (fs *FileSystemStorage) CreateBlobDocument(uid, filename, parent string, st log.Info("Creating metadata... parent: ", parent) + collectionType := common.DocumentType + if ext == storage.TemplateFileExt { + collectionType = common.TemplateType + } metadata := models.MetadataFile{ DocumentName: docName, - CollectionType: common.DocumentType, + CollectionType: collectionType, Parent: parent, Version: 1, CreatedTime: models.FromTime(time.Now()), @@ -371,14 +426,21 @@ func (fs *FileSystemStorage) CreateBlobDocument(uid, filename, parent string, st } hashDoc := models.NewHashDocWithMeta(docid, metadata) - hashDoc.PayloadType = docName + if ext == storage.TemplateFileExt { + hashDoc.PayloadType = "template" + } else { + hashDoc.PayloadType = strings.TrimPrefix(ext, ".") + } err = hashDoc.AddFile(payloadEntry) if err != nil { return } - content := createContent(ext) + content := "{}" + if ext != storage.TemplateFileExt { + content = createContent(ext) + } contentReader := strings.NewReader(content) contentHash, size, err := models.Hash(contentReader) @@ -448,7 +510,7 @@ func (fs *FileSystemStorage) CreateBlobDocument(uid, filename, parent string, st doc = &storage.Document{ ID: docid, - Type: common.DocumentType, + Type: collectionType, Parent: "", Name: docName, } @@ -513,7 +575,7 @@ func (fs *FileSystemStorage) createFromRmDoc(uid, parent string, stream io.Reade } hashDoc := models.NewHashDocWithMeta(docid, metadata) - hashDoc.PayloadType = metadata.DocumentName + hashDoc.PayloadType = "notebook" for _, f := range zr.File { if strings.HasSuffix(f.Name, storage.ContentFileExt) { diff --git a/internal/storage/fs/device_thumb.go b/internal/storage/fs/device_thumb.go new file mode 100644 index 00000000..fabd330f --- /dev/null +++ b/internal/storage/fs/device_thumb.go @@ -0,0 +1,53 @@ +package fs + +import ( + "path" + "strings" + + "github.com/ddvk/rmfakecloud/internal/storage/models" +) + +func isDeviceThumbExt(name string) bool { + switch path.Ext(name) { + case ".jpg", ".jpeg", ".png", ".webp": + return true + } + return false +} + +func matchDeviceThumb(entryName, pageID string) bool { + pageID = strings.ToLower(strings.TrimSpace(pageID)) + if pageID == "" { + return false + } + n := strings.ToLower(strings.ReplaceAll(entryName, "\\", "/")) + n = strings.TrimPrefix(n, "./") + base := path.Base(n) + ext := path.Ext(base) + stem := strings.TrimSuffix(base, ext) + if stem == pageID && isDeviceThumbExt(base) { + return true + } + if stem == pageID+".thumb" && isDeviceThumbExt(base) { + return true + } + if strings.Contains(n, "thumbnail") && stem == pageID { + return true + } + return false +} + +func findDeviceThumbEntry(doc *models.HashDoc, pageID string) *models.HashEntry { + if doc == nil { + return nil + } + for _, f := range doc.Files { + if f == nil { + continue + } + if matchDeviceThumb(f.EntryName, pageID) { + return f + } + } + return nil +} diff --git a/internal/storage/fs/device_thumb_test.go b/internal/storage/fs/device_thumb_test.go new file mode 100644 index 00000000..2a12bbdb --- /dev/null +++ b/internal/storage/fs/device_thumb_test.go @@ -0,0 +1,24 @@ +package fs + +import "testing" + +func TestMatchDeviceThumb(t *testing.T) { + page := "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee" + cases := []struct { + name string + want bool + }{ + {page + ".jpg", true}, + {page + ".png", true}, + {"thumbnails/" + page + ".jpg", true}, + {page + ".rm", false}, + {page + ".content", false}, + {"other.jpg", false}, + {"", false}, + } + for _, tc := range cases { + if got := matchDeviceThumb(tc.name, page); got != tc.want { + t.Fatalf("%q: got %v want %v", tc.name, got, tc.want) + } + } +} diff --git a/internal/storage/fs/epub.go b/internal/storage/fs/epub.go new file mode 100644 index 00000000..036ce52b --- /dev/null +++ b/internal/storage/fs/epub.go @@ -0,0 +1,117 @@ +package fs + +import ( + "archive/zip" + "bytes" + "errors" + "io" + "strings" + + "github.com/ddvk/rmfakecloud/internal/storage" + "github.com/ddvk/rmfakecloud/internal/storage/epub" +) + +func (fs *FileSystemStorage) openEpubZip(uid, docid string) (*zip.Reader, []byte, error) { + rc, err := fs.GetEpub(uid, docid) + if err != nil { + return nil, nil, err + } + defer rc.Close() + body, err := io.ReadAll(rc) + if err != nil { + return nil, nil, err + } + zr, err := zip.NewReader(bytes.NewReader(body), int64(len(body))) + if err != nil { + return nil, nil, err + } + return zr, body, nil +} + +// GetEpub returns the raw .epub payload for a document. +func (fs *FileSystemStorage) GetEpub(uid, docid string) (io.ReadCloser, error) { + tree, err := fs.GetCachedTree(uid) + if err != nil { + return nil, err + } + doc, err := tree.FindDoc(docid) + if err != nil { + return nil, err + } + ls := fs.BlobStorage(uid) + for _, f := range doc.Files { + if f == nil { + continue + } + if strings.HasSuffix(strings.ToLower(f.EntryName), storage.EpubFileExt) { + return ls.GetReader(f.Hash) + } + } + return nil, errors.New("epub not found") +} + +// GetEpubManifest parses the EPUB spine. +func (fs *FileSystemStorage) GetEpubManifest(uid, docid string) (*epub.Manifest, error) { + zr, _, err := fs.openEpubZip(uid, docid) + if err != nil { + return nil, err + } + return epub.ReadManifest(zr) +} + +// GetEpubFile returns a file from inside the EPUB zip. +func (fs *FileSystemStorage) GetEpubFile(uid, docid, filePath string) (io.ReadCloser, string, error) { + zr, _, err := fs.openEpubZip(uid, docid) + if err != nil { + return nil, "", err + } + f, err := epub.OpenZipFile(zr, filePath) + if err != nil { + return nil, "", err + } + data, err := io.ReadAll(f) + _ = f.Close() + if err != nil { + return nil, "", err + } + return io.NopCloser(bytes.NewReader(data)), epub.ContentType(filePath), nil +} + +// GetEpubCoverThumb returns a cover image from the EPUB. +func (fs *FileSystemStorage) GetEpubCoverThumb(uid, docid string) (io.ReadCloser, string, error) { + zr, _, err := fs.openEpubZip(uid, docid) + if err != nil { + return nil, "", err + } + imgPath, err := epub.FindCoverImagePath(zr) + if err != nil { + return nil, "", err + } + return fs.GetEpubFile(uid, docid, imgPath) +} + +// GetEpubPageThumb returns an image from the last-opened spine item, else the cover. +func (fs *FileSystemStorage) GetEpubPageThumb(uid, docid string, pageIndex0 int) (io.ReadCloser, string, error) { + zr, _, err := fs.openEpubZip(uid, docid) + if err != nil { + return nil, "", err + } + man, err := epub.ReadManifest(zr) + if err == nil && man != nil && len(man.Spine) > 0 { + idx := pageIndex0 + if idx < 0 { + idx = 0 + } + if idx >= len(man.Spine) { + idx = len(man.Spine) - 1 + } + if imgPath, e := epub.FindFirstImageInFile(zr, man.Spine[idx]); e == nil { + return fs.GetEpubFile(uid, docid, imgPath) + } + } + imgPath, err := epub.FindCoverImagePath(zr) + if err != nil { + return nil, "", err + } + return fs.GetEpubFile(uid, docid, imgPath) +} diff --git a/internal/storage/fs/format_label.go b/internal/storage/fs/format_label.go new file mode 100644 index 00000000..a96eb487 --- /dev/null +++ b/internal/storage/fs/format_label.go @@ -0,0 +1,182 @@ +package fs + +import ( + "bytes" + "fmt" + "io" + "strings" + + "github.com/ddvk/rmfakecloud/internal/common" + "github.com/ddvk/rmfakecloud/internal/rmdecode" + "github.com/ddvk/rmfakecloud/internal/storage" + "github.com/ddvk/rmfakecloud/internal/storage/models" +) + +func peekBlob(ls *LocalBlobStorage, hash string, n int) []byte { + if ls == nil || hash == "" || n < 1 { + return nil + } + rc, err := ls.GetReader(hash) + if err != nil { + return nil + } + defer rc.Close() + buf := make([]byte, n) + got, _ := io.ReadFull(rc, buf) + if got < 1 { + return nil + } + return buf[:got] +} + +func firstFileByExt(doc *models.HashDoc, ext string) *models.HashEntry { + ext = strings.ToLower(ext) + if doc == nil { + return nil + } + for _, f := range doc.Files { + if f == nil { + continue + } + if strings.HasSuffix(strings.ToLower(f.EntryName), ext) { + return f + } + } + return nil +} + +func firstRmFile(doc *models.HashDoc) *models.HashEntry { + return firstFileByExt(doc, storage.RmFileExt) +} + +// ParsePDFVersion reads the %PDF-x.y header from the start of a PDF. +func ParsePDFVersion(b []byte) string { + if len(b) < 8 { + return "" + } + i := bytes.Index(b, []byte("%PDF-")) + if i < 0 || i > 16 { + return "" + } + rest := b[i+5:] + n := 0 + for n < len(rest) { + c := rest[n] + if c == '.' || (c >= '0' && c <= '9') { + n++ + continue + } + break + } + if n == 0 { + return "" + } + return string(rest[:n]) +} + +func sniffRmVersion(ls *LocalBlobStorage, doc *models.HashDoc) int { + ent := firstRmFile(doc) + if ent == nil { + return 0 + } + hdr := peekBlob(ls, ent.Hash, rmdecode.HeaderLen) + v, err := rmdecode.ParseVersion(hdr) + if err != nil { + return 0 + } + return v +} + +func sniffFormatLabel(ls *LocalBlobStorage, doc *models.HashDoc) string { + if doc == nil { + return "" + } + if doc.CollectionType == common.CollectionType { + return "" + } + kind := doc.EffectivePayloadType() + rmVer := sniffRmVersion(ls, doc) + switch kind { + case "pdf": + label := "PDF" + if ent := firstFileByExt(doc, storage.PdfFileExt); ent != nil { + if ver := ParsePDFVersion(peekBlob(ls, ent.Hash, 64)); ver != "" { + label = "PDF " + ver + } + } + if rmVer > 0 { + return fmt.Sprintf("%s · v%d", label, rmVer) + } + return label + case "epub": + label := "EPUB" + if rmVer > 0 { + return fmt.Sprintf("%s · v%d", label, rmVer) + } + return label + default: + if rmVer > 0 { + return fmt.Sprintf("RM v%d", rmVer) + } + return "RM" + } +} + +func (fs *FileSystemStorage) ensureFormatLabels(tree *models.HashTree, ls *LocalBlobStorage) bool { + if tree == nil { + return false + } + changed := false + for _, d := range tree.Docs { + if d == nil || d.Deleted { + continue + } + if d.CollectionType == common.CollectionType { + continue + } + if d.FormatLabel != "" { + continue + } + if lab := sniffFormatLabel(ls, d); lab != "" { + d.FormatLabel = lab + changed = true + } + } + return changed +} + +// ensureTemplateMetadata re-reads .metadata for TemplateType entries when Source is +// missing from the cached tree (older caches predate the Source field). Needed so +// com.remarkable.methods + TemplateType classifies as Methods. +func (fs *FileSystemStorage) ensureTemplateMetadata(tree *models.HashTree, ls *LocalBlobStorage) bool { + if tree == nil || ls == nil { + return false + } + changed := false + for _, d := range tree.Docs { + if d == nil || d.Deleted { + continue + } + if d.CollectionType != common.TemplateType { + continue + } + if d.Source != "" { + continue + } + var metaEnt *models.HashEntry + for _, f := range d.Files { + if f != nil && f.IsMetadata() { + metaEnt = f + break + } + } + if metaEnt == nil { + continue + } + if err := d.ReadMetadata(metaEnt, ls); err != nil { + continue + } + changed = true + } + return changed +} diff --git a/internal/storage/fs/format_label_test.go b/internal/storage/fs/format_label_test.go new file mode 100644 index 00000000..739aa73e --- /dev/null +++ b/internal/storage/fs/format_label_test.go @@ -0,0 +1,39 @@ +package fs + +import ( + "testing" + + "github.com/ddvk/rmfakecloud/internal/storage/models" +) + +func TestParsePDFVersion(t *testing.T) { + cases := []struct { + in string + want string + }{ + {"%PDF-1.7\n", "1.7"}, + {"%PDF-1.7\n%\xe2\xe3\xcf\xd3", "1.7"}, + {"%PDF-1.4\r\n", "1.4"}, + {"%PDF-2.0\n", "2.0"}, + {"\xef\xbb\xbf%PDF-1.5\n", "1.5"}, + {"not a pdf", ""}, + {"%PDF-", ""}, + } + for _, tc := range cases { + if got := ParsePDFVersion([]byte(tc.in)); got != tc.want { + t.Fatalf("%q: got %q want %q", tc.in, got, tc.want) + } + } +} + +func TestSniffFormatLabelFallbacks(t *testing.T) { + if got := sniffFormatLabel(nil, &models.HashDoc{}); got != "RM" { + t.Fatalf("empty notebook: %q", got) + } + if got := sniffFormatLabel(nil, &models.HashDoc{PayloadType: "pdf"}); got != "PDF" { + t.Fatalf("pdf: %q", got) + } + if got := sniffFormatLabel(nil, &models.HashDoc{PayloadType: "epub"}); got != "EPUB" { + t.Fatalf("epub: %q", got) + } +} diff --git a/internal/storage/fs/notebook_page_png.go b/internal/storage/fs/notebook_page_png.go new file mode 100644 index 00000000..a3afff23 --- /dev/null +++ b/internal/storage/fs/notebook_page_png.go @@ -0,0 +1,216 @@ +package fs + +import ( + "encoding/json" + "fmt" + "io" + "path" + "strings" + + "github.com/ddvk/rmfakecloud/internal/rmdecode" + "github.com/ddvk/rmfakecloud/internal/storage" + "github.com/ddvk/rmfakecloud/internal/storage/exporter" + "github.com/ddvk/rmfakecloud/internal/storage/models" + log "github.com/sirupsen/logrus" +) + +func loadContentFile(doc *models.HashDoc, ls *LocalBlobStorage, docid string) (models.ContentFile, error) { + var cf models.ContentFile + want := strings.ToLower(docid + storage.ContentFileExt) + for _, f := range doc.Files { + if f == nil { + continue + } + if strings.ToLower(f.EntryName) != want && !strings.HasSuffix(strings.ToLower(f.EntryName), storage.ContentFileExt) { + continue + } + rc, err := ls.GetReader(f.Hash) + if err != nil { + return cf, err + } + err = json.NewDecoder(rc).Decode(&cf) + _ = rc.Close() + return cf, err + } + return cf, fmt.Errorf("missing .content for document") +} + +func pageIDsFromDoc(doc *models.HashDoc, ls *LocalBlobStorage, docid string) []string { + cf, err := loadContentFile(doc, ls, docid) + if err != nil { + return nil + } + return cf.PageIDs() +} + +func readPageRmBlob(doc *models.HashDoc, ls *LocalBlobStorage, docid string, pageNum int) (data []byte, err error) { + ids := pageIDsFromDoc(doc, ls, docid) + if pageNum < 1 { + return nil, fmt.Errorf("page %d out of range", pageNum) + } + var pageID string + if pageNum <= len(ids) { + pageID = ids[pageNum-1] + } else { + var rms []string + for _, f := range doc.Files { + if f != nil && strings.HasSuffix(strings.ToLower(f.EntryName), storage.RmFileExt) { + rms = append(rms, f.EntryName) + } + } + if pageNum > len(rms) { + if len(rms) == 0 { + return nil, nil + } + pageNum = len(rms) + } + pageID = strings.TrimSuffix(path.Base(rms[pageNum-1]), storage.RmFileExt) + } + if pageID == "" { + return nil, nil + } + want := strings.ToLower(pageID + storage.RmFileExt) + for _, f := range doc.Files { + if f == nil { + continue + } + name := strings.ToLower(f.EntryName) + if name != want && !strings.HasSuffix(name, "/"+want) { + continue + } + rc, e := ls.GetReader(f.Hash) + if e != nil { + return nil, e + } + data, e = io.ReadAll(rc) + _ = rc.Close() + return data, e + } + return nil, nil +} + +func readDeviceThumbBytes(doc *models.HashDoc, ls *LocalBlobStorage, pageID string) []byte { + ent := findDeviceThumbEntry(doc, pageID) + if ent == nil { + return nil + } + rc, err := ls.GetReader(ent.Hash) + if err != nil { + return nil + } + b, err := io.ReadAll(rc) + _ = rc.Close() + if err != nil || len(b) < 32 { + return nil + } + return b +} + +func pageIDForNum(doc *models.HashDoc, ls *LocalBlobStorage, docid string, pageNum int) string { + ids := pageIDsFromDoc(doc, ls, docid) + if pageNum >= 1 && pageNum <= len(ids) { + return ids[pageNum-1] + } + return "" +} + +// pageIDFromRmBlob resolves the page UUID used for sibling image paths. +func pageIDFromRmBlob(doc *models.HashDoc, ls *LocalBlobStorage, docid string, pageNum int) string { + if id := pageIDForNum(doc, ls, docid, pageNum); id != "" { + return id + } + var rms []string + for _, f := range doc.Files { + if f != nil && strings.HasSuffix(strings.ToLower(f.EntryName), storage.RmFileExt) { + rms = append(rms, f.EntryName) + } + } + if pageNum < 1 || pageNum > len(rms) { + return "" + } + return strings.TrimSuffix(path.Base(rms[pageNum-1]), storage.RmFileExt) +} + +func isPageImageExt(name string) bool { + switch strings.ToLower(path.Ext(name)) { + case ".png", ".jpg", ".jpeg", ".webp", ".gif": + return true + } + return false +} + +// readPageImages loads inserted image blobs stored beside a page as +// {docid}/{pageID}/{filename}.png (basename → bytes for rmc staging). +func readPageImages(doc *models.HashDoc, ls *LocalBlobStorage, pageID string) map[string][]byte { + pageID = strings.ToLower(strings.TrimSpace(pageID)) + if doc == nil || ls == nil || pageID == "" { + return nil + } + prefix := pageID + "/" + out := make(map[string][]byte) + for _, f := range doc.Files { + if f == nil { + continue + } + name := strings.ToLower(strings.ReplaceAll(f.EntryName, "\\", "/")) + idx := strings.Index(name, prefix) + if idx < 0 { + continue + } + // Only accept .../{pageID}/{file} — not deeper nests or the page .rm. + rel := name[idx+len(prefix):] + if rel == "" || strings.Contains(rel, "/") || !isPageImageExt(rel) { + continue + } + rc, err := ls.GetReader(f.Hash) + if err != nil { + continue + } + b, err := io.ReadAll(rc) + _ = rc.Close() + if err != nil || len(b) == 0 { + continue + } + out[path.Base(rel)] = b + } + if len(out) == 0 { + return nil + } + return out +} + +func exportNotebookPagePNGWithRmdecode(doc *models.HashDoc, ls *LocalBlobStorage, docid string, pageNum int) (png []byte, cacheable bool, err error) { + if pageID := pageIDForNum(doc, ls, docid, pageNum); pageID != "" { + if b := readDeviceThumbBytes(doc, ls, pageID); len(b) > 0 { + return b, true, nil + } + } + rmData, err := readPageRmBlob(doc, ls, docid, pageNum) + if err != nil { + return nil, false, err + } + if len(rmData) == 0 { + b, e := rmdecode.RenderNotebookPlaceholderPNG() + return b, false, e + } + pageID := pageIDFromRmBlob(doc, ls, docid, pageNum) + images := readPageImages(doc, ls, pageID) + b, err := rmdecode.EncodeRmPageToPNGWithImages(rmData, images) + if err != nil { + log.Warn("notebook page png: ", err) + ph, e := rmdecode.RenderNotebookPlaceholderPNG() + if e != nil { + return nil, false, err + } + return ph, false, nil + } + return b, true, nil +} + +func notebookPlaceholderReader() (io.ReadCloser, error) { + b, err := rmdecode.RenderNotebookPlaceholderPNG() + if err != nil { + return nil, err + } + return exporter.NewSeekCloser(b), nil +} diff --git a/internal/storage/fs/page_composite.go b/internal/storage/fs/page_composite.go new file mode 100644 index 00000000..99b85f10 --- /dev/null +++ b/internal/storage/fs/page_composite.go @@ -0,0 +1,243 @@ +package fs + +import ( + "bytes" + "fmt" + "image" + _ "image/jpeg" + "image/png" + "io" + "os" + "path" + "strings" + + "github.com/ddvk/rmfakecloud/internal/common" + "github.com/ddvk/rmfakecloud/internal/rmdecode" + "github.com/ddvk/rmfakecloud/internal/storage" + "github.com/ddvk/rmfakecloud/internal/storage/exporter" + "github.com/ddvk/rmfakecloud/internal/storage/models" + log "github.com/sirupsen/logrus" +) + +func docHasRm(doc *models.HashDoc) bool { + if doc == nil { + return false + } + for _, f := range doc.Files { + if f != nil && strings.HasSuffix(strings.ToLower(f.EntryName), storage.RmFileExt) { + return true + } + } + return false +} + +// exportInkLayerPNG renders .rm ink on a white page for multiply compositing. +// Missing/failed pages become blank white (multiply leaves the background unchanged). +func exportInkLayerPNG(doc *models.HashDoc, ls *LocalBlobStorage, docid string, pageNum int) ([]byte, error) { + return exportInkLayerPNGSized(doc, ls, docid, pageNum, 0, 0) +} + +func exportInkLayerPNGSized(doc *models.HashDoc, ls *LocalBlobStorage, docid string, pageNum int, pdfWPt, pdfHPt float64) ([]byte, error) { + rmData, err := readPageRmBlob(doc, ls, docid, pageNum) + if err != nil || len(rmData) == 0 { + return rmdecode.RenderBlankNotebookPNG() + } + images := readPageImages(doc, ls, pageIDFromRmBlob(doc, ls, docid, pageNum)) + var b []byte + if pdfWPt >= 1 && pdfHPt >= 1 { + b, err = rmdecode.EncodeRmPageToPNGForPDFWithImages(rmData, images, pdfWPt, pdfHPt) + } else { + b, err = rmdecode.EncodeRmPageToPNGWithImages(rmData, images) + } + if err != nil { + log.Warn("ink layer png: ", err) + return rmdecode.RenderBlankNotebookPNG() + } + return b, nil +} + +func imageBytesToPNG(raw []byte) ([]byte, error) { + img, _, err := image.Decode(bytes.NewReader(raw)) + if err != nil { + return nil, err + } + var out bytes.Buffer + if err := png.Encode(&out, img); err != nil { + return nil, err + } + return out.Bytes(), nil +} + +// exportPDFPageCompositePNG: PDF page background × .rm ink (multiply). +func exportPDFPageCompositePNG(doc *models.HashDoc, ls *LocalBlobStorage, docid string, pageNum int) ([]byte, error) { + archive, err := models.ArchiveFromHashDoc(doc, ls) + if err != nil { + return nil, err + } + if archive.PayloadReader == nil { + return nil, fmt.Errorf("no payload reader") + } + if _, err := archive.PayloadReader.Seek(0, io.SeekStart); err != nil { + return nil, err + } + pdfBytes, err := io.ReadAll(archive.PayloadReader) + if err != nil { + return nil, err + } + bg, err := exporter.RenderPDFBytesToPNG(pdfBytes, pageNum) + if err != nil { + return nil, err + } + if !docHasRm(doc) { + return bg, nil + } + pdfW, pdfH, err := exporter.PDFPageSizePts(pdfBytes, pageNum) + if err != nil { + log.Warn("pdf page size: ", err) + pdfW, pdfH = 0, 0 + } + ink, err := exportInkLayerPNGSized(doc, ls, docid, pageNum, pdfW, pdfH) + if err != nil || len(ink) == 0 { + return bg, nil + } + comp, err := exporter.MultiplyBlendPNGs(bg, ink, nil) + if err != nil { + log.Warn("pdf composite blend failed, returning background: ", err) + return bg, nil + } + return comp, nil +} + +// exportEpubPageCompositePNG: EPUB cover/page image × .rm ink (multiply). +func exportEpubPageCompositePNG(fs *FileSystemStorage, uid string, doc *models.HashDoc, ls *LocalBlobStorage, docid string, pageNum int) ([]byte, error) { + bgPNG, err := epubBackgroundPNG(fs, uid, docid, pageNum) + if err != nil || len(bgPNG) == 0 { + blank, e2 := rmdecode.RenderBlankNotebookPNG() + if e2 != nil { + return nil, err + } + bgPNG = blank + } + if !docHasRm(doc) { + return bgPNG, nil + } + ink, err := exportInkLayerPNG(doc, ls, docid, pageNum) + if err != nil || len(ink) == 0 { + return bgPNG, nil + } + comp, err := exporter.MultiplyBlendPNGs(bgPNG, ink, nil) + if err != nil { + log.Warn("epub composite blend failed, returning background: ", err) + return bgPNG, nil + } + return comp, nil +} + +func epubBackgroundPNG(fs *FileSystemStorage, uid, docid string, pageNum int) ([]byte, error) { + idx0 := pageNum - 1 + if idx0 < 0 { + idx0 = 0 + } + rc, _, err := fs.GetEpubPageThumb(uid, docid, idx0) + if err != nil || rc == nil { + return nil, fmt.Errorf("epub background: %w", err) + } + defer rc.Close() + raw, err := io.ReadAll(rc) + if err != nil { + return nil, err + } + if len(raw) == 0 { + return nil, fmt.Errorf("empty epub background") + } + if png, err := imageBytesToPNG(raw); err == nil { + return png, nil + } + // Already PNG or exotic — try as-is for blend decode. + if _, err := png.Decode(bytes.NewReader(raw)); err == nil { + return raw, nil + } + return imageBytesToPNG(raw) +} + +// ExportPagePNG renders one document page as PNG (1-based). +// PDF/EPUB with .rm: payload/cover background × ink multiply. +// Notebooks: ink (or device thumb / placeholder). +func (fs *FileSystemStorage) ExportPagePNG(uid, docid string, pageNum int) (io.ReadCloser, error) { + if pageNum < 1 { + pageNum = 1 + } + tree, err := fs.GetCachedTree(uid) + if err != nil { + return notebookPlaceholderReader() + } + doc, err := tree.FindDoc(docid) + if err != nil { + return notebookPlaceholderReader() + } + docHash := doc.Hash + ls := fs.BlobStorage(uid) + ids := pageIDsFromDoc(doc, ls, docid) + if len(ids) > 0 && pageNum > len(ids) { + pageNum = len(ids) + } + kind := doc.EffectivePayloadType() + cacheDir := fs.getPathFromUser(uid, CacheDir) + _ = os.MkdirAll(cacheDir, 0700) + safeDoc := common.Sanitize(docid) + + var cachePath string + var gen func() ([]byte, error) + switch kind { + case "pdf": + cachePath = path.Join(cacheDir, "renders", safeDoc, fmt.Sprintf("page-%d-composite-v32-%s.png", pageNum, docHash)) + gen = func() ([]byte, error) { + return exportPDFPageCompositePNG(doc, ls, docid, pageNum) + } + case "epub": + cachePath = path.Join(cacheDir, "renders", safeDoc, fmt.Sprintf("page-%d-epub-composite-v30-%s.png", pageNum, docHash)) + gen = func() ([]byte, error) { + return exportEpubPageCompositePNG(fs, uid, doc, ls, docid, pageNum) + } + default: + cachePath = path.Join(cacheDir, "renders", safeDoc, fmt.Sprintf("page-%d-thumb-v6-%s.bin", pageNum, docHash)) + gen = func() ([]byte, error) { + b, _, e := exportNotebookPagePNGWithRmdecode(doc, ls, docid, pageNum) + return b, e + } + } + + if docHash != "" { + if r, err := os.Open(cachePath); err == nil { + return r, nil + } + } + b, err := gen() + if err != nil || len(b) == 0 { + log.Warn("ExportPagePNG: ", err) + return notebookPlaceholderReader() + } + if docHash != "" { + _ = os.MkdirAll(path.Dir(cachePath), 0700) + _ = os.WriteFile(cachePath, b, 0600) + } + return exporter.NewSeekCloser(b), nil +} + +// ExportPageThumbPNG returns a device-sized (~384×512) composite thumbnail. +func (fs *FileSystemStorage) ExportPageThumbPNG(uid, docid string, pageNum int) (io.ReadCloser, error) { + rc, err := fs.ExportPagePNG(uid, docid, pageNum) + if err != nil { + return nil, err + } + defer rc.Close() + full, err := io.ReadAll(rc) + if err != nil { + return nil, err + } + thumb, err := exporter.ScalePNGToThumb(full) + if err != nil { + return exporter.NewSeekCloser(full), nil + } + return exporter.NewSeekCloser(thumb), nil +} diff --git a/internal/storage/fs/page_images_test.go b/internal/storage/fs/page_images_test.go new file mode 100644 index 00000000..8e2520f5 --- /dev/null +++ b/internal/storage/fs/page_images_test.go @@ -0,0 +1,26 @@ +package fs + +import ( + "testing" + + "github.com/ddvk/rmfakecloud/internal/storage/models" +) + +func TestIsPageImageExt(t *testing.T) { + if !isPageImageExt("a.png") || !isPageImageExt("b.JPEG") { + t.Fatal("expected image extensions") + } + if isPageImageExt("x.rm") || isPageImageExt("y") { + t.Fatal("unexpected image extension") + } +} + +func TestReadPageImagesNil(t *testing.T) { + if readPageImages(nil, nil, "abc") != nil { + t.Fatal("expected nil") + } + doc := &models.HashDoc{} + if readPageImages(doc, nil, "") != nil { + t.Fatal("expected nil for empty page") + } +} diff --git a/internal/storage/models/archive.go b/internal/storage/models/archive.go index d244db6d..119c625d 100644 --- a/internal/storage/models/archive.go +++ b/internal/storage/models/archive.go @@ -65,7 +65,16 @@ func ArchiveFromHashDoc(doc *HashDoc, rs RemoteStorage) (*exporter.MyArchive, er } } - for _, p := range a.Content.Pages { + pageIDs := a.Content.Pages + if len(pageIDs) == 0 { + // Newer tablets store page UUIDs under cPages; rmapi's Content.Pages stays empty. + // Fall back to whatever .rm blobs we found so notebook PDF export can still run. + for name := range pageMap { + pageIDs = append(pageIDs, name) + } + } + + for _, p := range pageIDs { if hash, ok := pageMap[p]; ok { log.Debug("page ", hash) reader, err := rs.GetReader(hash) @@ -73,13 +82,18 @@ func ArchiveFromHashDoc(doc *HashDoc, rs RemoteStorage) (*exporter.MyArchive, er return nil, err } pageBin, err := io.ReadAll(reader) + _ = reader.Close() if err != nil { return nil, err } rmpage := rm.New() err = rmpage.UnmarshalBinary(pageBin) if err != nil { - return nil, err + // v6 (and other) pages are not understood by rmapi; keep the + // page slot so PDF export can still emit the background. + log.Warn("skipping unreadable .rm page ", p, ": ", err) + a.Pages = append(a.Pages, archive.Page{Pagedata: "Blank"}) + continue } page := archive.Page{ diff --git a/internal/storage/models/content_pages.go b/internal/storage/models/content_pages.go new file mode 100644 index 00000000..bdf2fa3d --- /dev/null +++ b/internal/storage/models/content_pages.go @@ -0,0 +1,136 @@ +package models + +import ( + "encoding/json" + "strings" +) + +// CPages is the software 3+ page tree in a .content file. +type CPages struct { + LastOpened *CPageValue `json:"lastOpened"` + Pages []CPage `json:"pages"` +} + +// CPageValue is cPages.lastOpened.value (page UUID or index). +type CPageValue struct { + Value json.RawMessage `json:"value"` +} + +// CPage is one page in cPages.pages. +type CPage struct { + ID string `json:"id"` +} + +// PageIDs returns page UUIDs from cPages.pages or the legacy pages array. +func (c ContentFile) PageIDs() []string { + if len(c.CPages.Pages) > 0 { + out := make([]string, 0, len(c.CPages.Pages)) + for _, p := range c.CPages.Pages { + if id := strings.TrimSpace(p.ID); id != "" { + out = append(out, id) + } + } + if len(out) > 0 { + return out + } + } + out := make([]string, 0, len(c.Pages)) + for _, p := range c.Pages { + switch v := p.(type) { + case string: + if id := strings.TrimSpace(v); id != "" { + out = append(out, id) + } + case map[string]interface{}: + if id, ok := v["id"].(string); ok { + if id = strings.TrimSpace(id); id != "" { + out = append(out, id) + } + } + } + } + return out +} + +func (c ContentFile) lastOpenedFromCPages() (int, bool) { + if c.CPages.LastOpened == nil { + return 0, false + } + raw := strings.TrimSpace(string(c.CPages.LastOpened.Value)) + if raw == "" || raw == "null" { + return 0, false + } + ids := c.PageIDs() + if strings.HasPrefix(raw, "\"") { + var id string + if json.Unmarshal(c.CPages.LastOpened.Value, &id) != nil { + return 0, false + } + id = strings.TrimSpace(id) + if id == "" { + return 0, false + } + for i, p := range ids { + if p == id { + return i, true + } + } + return 0, false + } + var n int + if json.Unmarshal(c.CPages.LastOpened.Value, &n) != nil || n < 0 { + return 0, false + } + if len(ids) > 0 && n >= len(ids) { + n = len(ids) - 1 + } + return n, true +} + +// ResolvedLastOpenedIndex is the 0-based page the tablet last had open: +// cPages.lastOpened, then lastOpenedPage, clamped to the page list. +func (c ContentFile) ResolvedLastOpenedIndex() int { + if idx, ok := c.lastOpenedFromCPages(); ok { + return idx + } + ids := c.PageIDs() + idx := c.LastOpenedPage + if idx < 0 { + idx = 0 + } + if len(ids) > 0 && idx >= len(ids) { + idx = len(ids) - 1 + } + return idx +} + +// MergeLastOpenedIndex prefers the per-file .content pref over metadata. +func (c ContentFile) MergeLastOpenedIndex(metaIndex int) int { + if idx, ok := c.lastOpenedFromCPages(); ok { + return idx + } + idx := metaIndex + if c.LastOpenedPage > idx { + idx = c.LastOpenedPage + } + if idx < 0 { + idx = 0 + } + ids := c.PageIDs() + if len(ids) > 0 && idx >= len(ids) { + idx = len(ids) - 1 + } + return idx +} + +// ThumbPage1 is the 1-based page to render as a thumbnail. +func ThumbPage1(opened0, pageCount int) int { + n := opened0 + 1 + if n < 1 { + n = 1 + } + if pageCount > 0 && n > pageCount { + n = pageCount + } + return n +} diff --git a/internal/storage/models/content_pages_test.go b/internal/storage/models/content_pages_test.go new file mode 100644 index 00000000..11f213bf --- /dev/null +++ b/internal/storage/models/content_pages_test.go @@ -0,0 +1,58 @@ +package models + +import ( + "encoding/json" + "testing" +) + +func TestResolvedLastOpenedIndexFromCPagesUUID(t *testing.T) { + c := ContentFile{ + LastOpenedPage: 0, + CPages: CPages{ + LastOpened: &CPageValue{Value: json.RawMessage(`"page-b"`)}, + Pages: []CPage{ + {ID: "page-a"}, + {ID: "page-b"}, + {ID: "page-c"}, + }, + }, + } + if got := c.ResolvedLastOpenedIndex(); got != 1 { + t.Fatalf("got %d want 1", got) + } + if ids := c.PageIDs(); len(ids) != 3 || ids[1] != "page-b" { + t.Fatalf("page ids %v", ids) + } +} + +func TestMergeLastOpenedPrefersCPages(t *testing.T) { + c := ContentFile{ + LastOpenedPage: 0, + CPages: CPages{ + LastOpened: &CPageValue{Value: json.RawMessage(`"p2"`)}, + Pages: []CPage{{ID: "p1"}, {ID: "p2"}}, + }, + } + if got := c.MergeLastOpenedIndex(9); got != 1 { + t.Fatalf("got %d want 1", got) + } +} + +func TestMergeLastOpenedUsesMetadataWhenNoCPages(t *testing.T) { + c := ContentFile{LastOpenedPage: 0, Pages: []interface{}{"a", "b", "c"}} + if got := c.MergeLastOpenedIndex(2); got != 2 { + t.Fatalf("got %d want 2", got) + } +} + +func TestThumbPage1(t *testing.T) { + if got := ThumbPage1(0, 3); got != 1 { + t.Fatalf("first page: %d", got) + } + if got := ThumbPage1(4, 3); got != 3 { + t.Fatalf("clamp: %d", got) + } + if got := ThumbPage1(-1, 0); got != 1 { + t.Fatalf("empty: %d", got) + } +} diff --git a/internal/storage/models/hashdoc.go b/internal/storage/models/hashdoc.go index b46a9cf0..1a31dcd4 100644 --- a/internal/storage/models/hashdoc.go +++ b/internal/storage/models/hashdoc.go @@ -26,6 +26,56 @@ type HashDoc struct { MetadataFile //PayloadType PayloadType string + PageCount int + // FormatLabel is a short encoding badge, e.g. "RM v6", "PDF 1.7". + FormatLabel string `json:"formatLabel,omitempty"` +} + +// EffectivePayloadType is pdf, epub, or notebook. Ignores leftover names +// stored in PayloadType and falls back to the payload filename suffix. +func (d *HashDoc) EffectivePayloadType() string { + t := strings.ToLower(strings.TrimSpace(d.PayloadType)) + t = strings.TrimPrefix(t, ".") + switch t { + case "pdf": + return "pdf" + case "epub": + return "epub" + case "template": + return "template" + case "notebook", "rm": + return "notebook" + } + for _, f := range d.Files { + if f == nil { + continue + } + n := strings.ToLower(f.EntryName) + if strings.HasSuffix(n, ".pdf") { + return "pdf" + } + if strings.HasSuffix(n, ".epub") { + return "epub" + } + if strings.HasSuffix(n, ".template") { + return "template" + } + } + return "notebook" +} + +// LibraryFileType is the UI/library kind: method, template, pdf, epub, or notebook. +func (d *HashDoc) LibraryFileType() string { + if d == nil { + return "notebook" + } + if d.MetadataFile.IsMethod() { + return "method" + } + if d.MetadataFile.IsTemplate() { + return "template" + } + return d.EffectivePayloadType() } func NewHashDocWithMeta(documentID string, meta MetadataFile) *HashDoc { @@ -181,6 +231,11 @@ func (d *HashDoc) readContent(hash string, r RemoteStorage) error { log.Printf("cannot read content %s %v", hash, err) } d.PayloadType = contentFile.FileType + d.PageCount = contentFile.PageCount + if d.PageCount == 0 { + d.PageCount = len(contentFile.PageIDs()) + } + d.LastOpenedPage = contentFile.MergeLastOpenedIndex(d.LastOpenedPage) if len(contentFile.SizeInBytes) > 0 { d.Size, err = strconv.ParseInt(contentFile.SizeInBytes, 10, 64) @@ -277,6 +332,7 @@ func (d *HashDoc) Mirror(e *HashEntry, r RemoteStorage) error { } sort.Slice(head, func(i, j int) bool { return head[i].EntryName < head[j].EntryName }) d.Files = head + d.FormatLabel = "" return nil } diff --git a/internal/storage/models/hashdoc_payload_test.go b/internal/storage/models/hashdoc_payload_test.go new file mode 100644 index 00000000..88b99c72 --- /dev/null +++ b/internal/storage/models/hashdoc_payload_test.go @@ -0,0 +1,29 @@ +package models + +import "testing" + +func TestEffectivePayloadType(t *testing.T) { + cases := []struct { + name string + payload string + files []string + want string + }{ + {name: "pdf content", payload: "pdf", want: "pdf"}, + {name: "epub dotted", payload: ".epub", want: "epub"}, + {name: "notebook", payload: "notebook", want: "notebook"}, + {name: "visible name with pdf file", payload: "Quarterly Report", files: []string{"abc.metadata", "abc.content", "abc.pdf"}, want: "pdf"}, + {name: "visible name with epub file", payload: "A Novel", files: []string{"abc.epub"}, want: "epub"}, + {name: "visible name notebook", payload: "Quick Notes", files: []string{"abc.metadata", "abc.content", "p1.rm"}, want: "notebook"}, + {name: "empty", payload: "", want: "notebook"}, + } + for _, tc := range cases { + d := &HashDoc{PayloadType: tc.payload} + for _, n := range tc.files { + d.Files = append(d.Files, &HashEntry{EntryName: n}) + } + if got := d.EffectivePayloadType(); got != tc.want { + t.Fatalf("%s: got %q want %q", tc.name, got, tc.want) + } + } +} diff --git a/internal/storage/models/metadatafile.go b/internal/storage/models/metadatafile.go index 72c25082..e726c9eb 100644 --- a/internal/storage/models/metadatafile.go +++ b/internal/storage/models/metadatafile.go @@ -12,6 +12,7 @@ import ( type MetadataFile struct { DocumentName string `json:"visibleName"` CollectionType common.EntryType `json:"type"` + Source string `json:"source,omitempty"` // e.g. "com.remarkable.methods" Parent string `json:"parent"` CreatedTime string `json:"createdTime"` LastModified string `json:"lastModified"` @@ -25,6 +26,20 @@ type MetadataFile struct { MetadataModified bool `json:"metadatamodified"` } +// MethodsSource is the reMarkable metadata source for Methods library items. +const MethodsSource = "com.remarkable.methods" + +// IsMethod reports whether this entry is an rm Method +// (type TemplateType + source com.remarkable.methods). +func (m MetadataFile) IsMethod() bool { + return m.CollectionType == common.TemplateType && m.Source == MethodsSource +} + +// IsTemplate reports whether this entry is a page template (TemplateType, not a Method). +func (m MetadataFile) IsTemplate() bool { + return m.CollectionType == common.TemplateType && m.Source != MethodsSource +} + func ToTime(timeStamp string) (t time.Time, err error) { t = time.Time{} lastMod, err := strconv.ParseInt(timeStamp, 10, 64) @@ -57,6 +72,7 @@ type ContentFile struct { Orientation string `json:"orientation"` PageCount int `json:"pageCount"` Pages []interface{} `json:"pages"` + CPages CPages `json:"cPages"` TextScale int `json:"textScale"` Transform Transform `json:"transform"` SizeInBytes string `json:"sizeInBytes"` diff --git a/internal/ui/backend15.go b/internal/ui/backend15.go index 135df89d..a1febab5 100644 --- a/internal/ui/backend15.go +++ b/internal/ui/backend15.go @@ -5,6 +5,7 @@ import ( "github.com/ddvk/rmfakecloud/internal/app/hub" "github.com/ddvk/rmfakecloud/internal/storage" + "github.com/ddvk/rmfakecloud/internal/storage/epub" "github.com/ddvk/rmfakecloud/internal/ui/viewmodel" "github.com/google/uuid" ) @@ -26,6 +27,9 @@ func (b *backend15) Export(uid, docid, exporttype string, opt storage.ExportOpti if exporttype == "rmdoc" { return b.blobHandler.ExportRmDoc(uid, docid) } + if exporttype == "epub" { + return b.blobHandler.GetEpub(uid, docid) + } r, err = b.blobHandler.Export(uid, docid) return } @@ -46,6 +50,26 @@ func (b *backend15) DeleteDocument(uid, docID string) (err error) { return b.blobHandler.DeleteBlobDocument(uid, docID) } +func (b *backend15) ExportPagePNG(uid, docid string, pageNum int) (io.ReadCloser, error) { + return b.blobHandler.ExportPagePNG(uid, docid, pageNum) +} + +func (b *backend15) GetEpubManifest(uid, docid string) (*epub.Manifest, error) { + return b.blobHandler.GetEpubManifest(uid, docid) +} + +func (b *backend15) GetEpubFile(uid, docid, filePath string) (io.ReadCloser, string, error) { + return b.blobHandler.GetEpubFile(uid, docid, filePath) +} + +func (b *backend15) GetEpubCoverThumb(uid, docid string) (io.ReadCloser, string, error) { + return b.blobHandler.GetEpubCoverThumb(uid, docid) +} + +func (b *backend15) GetEpubPageThumb(uid, docid string, pageIndex0 int) (io.ReadCloser, string, error) { + return b.blobHandler.GetEpubPageThumb(uid, docid, pageIndex0) +} + func (b *backend15) Sync(uid string) { b.h.NotifySync(uid, uuid.NewString()) } diff --git a/internal/ui/client_form_factor.go b/internal/ui/client_form_factor.go new file mode 100644 index 00000000..169e9ea4 --- /dev/null +++ b/internal/ui/client_form_factor.go @@ -0,0 +1,38 @@ +package ui + +import ( + "net/http" + "regexp" + "strings" + + "github.com/gin-gonic/gin" +) + +var mobileUA = regexp.MustCompile(`(?i)(android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini|mobile|silk|kindle|fennec)`) + +// clientFormFactor returns "mobile" or "desktop" from request headers. +// Prefers the Sec-CH-UA-Mobile client hint (?1 / ?0), then User-Agent. +func clientFormFactor(r *http.Request) string { + if r == nil { + return "desktop" + } + if ch := strings.TrimSpace(r.Header.Get("Sec-CH-UA-Mobile")); ch != "" { + if ch == "?1" || strings.EqualFold(ch, "1") || strings.EqualFold(ch, "true") { + return "mobile" + } + if ch == "?0" || strings.EqualFold(ch, "0") || strings.EqualFold(ch, "false") { + return "desktop" + } + } + ua := r.Header.Get("User-Agent") + if ua != "" && mobileUA.MatchString(ua) { + return "mobile" + } + return "desktop" +} + +func setFormFactorHeaders(c *gin.Context) { + c.Header("Accept-CH", "Sec-CH-UA-Mobile") + c.Header("Vary", "User-Agent, Sec-CH-UA-Mobile") + c.Header("Critical-CH", "Sec-CH-UA-Mobile") +} diff --git a/internal/ui/client_form_factor_test.go b/internal/ui/client_form_factor_test.go new file mode 100644 index 00000000..5f93dc41 --- /dev/null +++ b/internal/ui/client_form_factor_test.go @@ -0,0 +1,37 @@ +package ui + +import ( + "net/http" + "net/http/httptest" + "testing" +) + +func TestClientFormFactor(t *testing.T) { + cases := []struct { + name string + ch string + ua string + want string + }{ + {"desktop empty", "", "", "desktop"}, + {"ch mobile", "?1", "Mozilla/5.0", "mobile"}, + {"ch desktop", "?0", "Mozilla/5.0 (iPhone)", "desktop"}, + {"ua iphone", "", "Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X)", "mobile"}, + {"ua android", "", "Mozilla/5.0 (Linux; Android 14)", "mobile"}, + {"ua desktop chrome", "", "Mozilla/5.0 (X11; Linux x86_64) Chrome/120.0.0.0", "desktop"}, + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + r := httptest.NewRequest(http.MethodGet, "/", nil) + if tc.ch != "" { + r.Header.Set("Sec-CH-UA-Mobile", tc.ch) + } + if tc.ua != "" { + r.Header.Set("User-Agent", tc.ua) + } + if got := clientFormFactor(r); got != tc.want { + t.Fatalf("got %q want %q", got, tc.want) + } + }) + } +} diff --git a/internal/ui/epub_website.go b/internal/ui/epub_website.go new file mode 100644 index 00000000..ae349c6f --- /dev/null +++ b/internal/ui/epub_website.go @@ -0,0 +1,224 @@ +package ui + +import ( + "bytes" + "html" + "io" + "net/http" + "net/url" + "path" + "strconv" + "strings" + + "github.com/ddvk/rmfakecloud/internal/common" + "github.com/ddvk/rmfakecloud/internal/storage/epub" + "github.com/gin-gonic/gin" + log "github.com/sirupsen/logrus" +) + +func epubAssetURL(docID, zipPath string) string { + zipPath = strings.TrimPrefix(path.Clean("/"+strings.ReplaceAll(zipPath, "\\", "/")), "/") + if zipPath == "" || zipPath == "." { + return "" + } + segs := strings.Split(zipPath, "/") + for i, s := range segs { + segs[i] = url.PathEscape(s) + } + return "/ui/api/documents/" + url.PathEscape(docID) + "/epub/" + strings.Join(segs, "/") +} + +func epubSpineLabel(zipPath string, index int) string { + base := path.Base(zipPath) + base = strings.TrimSuffix(base, path.Ext(base)) + base = strings.ReplaceAll(base, "_", " ") + base = strings.TrimSpace(base) + if base == "" { + return "Chapter " + strconv.Itoa(index+1) + } + return base +} + +func (app *ReactAppWrapper) getEpubPath(c *gin.Context) { + uid := userID(c) + docid := common.ParamS(docIDParam, c) + pathParam := c.Param("path") + pathParam = strings.TrimPrefix(path.Clean("/"+pathParam), "/") + if pathParam == ".." || strings.HasPrefix(pathParam, "../") { + c.AbortWithStatus(http.StatusBadRequest) + return + } + + type epubBackend interface { + GetEpubManifest(uid, docid string) (*epub.Manifest, error) + GetEpubFile(uid, docid, filePath string) (io.ReadCloser, string, error) + GetEpubCoverThumb(uid, docid string) (io.ReadCloser, string, error) + GetEpubPageThumb(uid, docid string, pageIndex0 int) (io.ReadCloser, string, error) + } + backend := app.getBackend(c) + eb, ok := backend.(epubBackend) + if !ok { + c.AbortWithStatus(http.StatusNotFound) + return + } + + switch pathParam { + case "cover-thumb": + reader, contentType, err := eb.GetEpubCoverThumb(uid, docid) + if err != nil { + log.Debug("epub cover-thumb: ", err) + c.AbortWithStatus(http.StatusNotFound) + return + } + defer reader.Close() + c.Header("Cache-Control", "private, max-age=3600") + c.Header("X-Content-Type-Options", "nosniff") + c.DataFromReader(http.StatusOK, -1, contentType, reader, nil) + return + case "thumb": + idx := 0 + if tree, err := backend.GetDocumentTree(uid); err == nil && tree != nil { + if d := findDocument(tree.Entries, docid); d != nil { + idx = d.CurrentPage + } else if d := findDocument(tree.Trash, docid); d != nil { + idx = d.CurrentPage + } + } + reader, contentType, err := eb.GetEpubPageThumb(uid, docid, idx) + if err != nil { + log.Debug("epub thumb: ", err) + c.AbortWithStatus(http.StatusNotFound) + return + } + defer reader.Close() + c.Header("Cache-Control", "private, max-age=3600") + c.Header("X-Content-Type-Options", "nosniff") + c.DataFromReader(http.StatusOK, -1, contentType, reader, nil) + return + case "manifest": + manifest, err := eb.GetEpubManifest(uid, docid) + if err != nil { + log.Error(err) + c.AbortWithStatus(http.StatusInternalServerError) + return + } + c.JSON(http.StatusOK, manifest) + return + case "", ".": + c.AbortWithStatus(http.StatusBadRequest) + return + } + + reader, contentType, err := eb.GetEpubFile(uid, docid, pathParam) + if err != nil { + log.Error(err) + c.AbortWithStatus(http.StatusNotFound) + return + } + defer reader.Close() + + if strings.Contains(contentType, "html") { + body, err := io.ReadAll(reader) + if err != nil { + log.Error(err) + c.AbortWithStatus(http.StatusInternalServerError) + return + } + dir := path.Dir("/ui/api/documents/" + docid + "/epub/" + pathParam) + if !strings.HasSuffix(dir, "/") { + dir += "/" + } + root := "/ui/api/documents/" + docid + "/epub" + body = prepareEpubHTML(body, dir, root) + c.Header("Content-Type", contentType) + c.Header("X-Content-Type-Options", "nosniff") + c.Header("Cache-Control", "private, max-age=300") + c.Data(http.StatusOK, contentType, body) + return + } + + c.Header("Content-Type", contentType) + c.Header("X-Content-Type-Options", "nosniff") + c.Header("Cache-Control", "private, max-age=300") + c.DataFromReader(http.StatusOK, -1, contentType, reader, nil) +} + +func prepareEpubHTML(htmlBytes []byte, baseURL, epubRoot string) []byte { + htmlBytes = injectHTMLBase(htmlBytes, baseURL) + return rewriteRootRelative(htmlBytes, epubRoot) +} + +func injectHTMLBase(htmlBytes []byte, baseURL string) []byte { + lower := bytes.ToLower(htmlBytes) + if bytes.Contains(lower, []byte("`) + head := bytes.Index(lower, []byte("= 0 { + gt := bytes.IndexByte(htmlBytes[head:], '>') + if gt < 0 { + return htmlBytes + } + at := head + gt + 1 + out := make([]byte, 0, len(htmlBytes)+len(tag)) + out = append(out, htmlBytes[:at]...) + out = append(out, tag...) + out = append(out, htmlBytes[at:]...) + return out + } + htmlTag := bytes.Index(lower, []byte("= 0 { + gt := bytes.IndexByte(htmlBytes[htmlTag:], '>') + if gt < 0 { + return htmlBytes + } + at := htmlTag + gt + 1 + headWrap := append([]byte(""), tag...) + headWrap = append(headWrap, []byte("")...) + out := make([]byte, 0, len(htmlBytes)+len(headWrap)) + out = append(out, htmlBytes[:at]...) + out = append(out, headWrap...) + out = append(out, htmlBytes[at:]...) + return out + } + return htmlBytes +} + +func rewriteRootRelative(htmlBytes []byte, epubRoot string) []byte { + epubRoot = strings.TrimSuffix(epubRoot, "/") + if epubRoot == "" { + return htmlBytes + } + lower := bytes.ToLower(htmlBytes) + keys := [][]byte{ + []byte(`href="`), []byte(`href='`), + []byte(`src="`), []byte(`src='`), + []byte(`poster="`), []byte(`poster='`), + } + var out []byte + i := 0 + for i < len(htmlBytes) { + hit := -1 + for _, k := range keys { + end := i + len(k) + if end <= len(lower) && bytes.Equal(lower[i:end], k) { + hit = end + break + } + } + if hit < 0 { + out = append(out, htmlBytes[i]) + i++ + continue + } + out = append(out, htmlBytes[i:hit]...) + i = hit + if i < len(htmlBytes) && htmlBytes[i] == '/' && (i+1 >= len(htmlBytes) || htmlBytes[i+1] != '/') { + out = append(out, epubRoot...) + out = append(out, '/') + i++ + } + } + return out +} diff --git a/internal/ui/epub_website_test.go b/internal/ui/epub_website_test.go new file mode 100644 index 00000000..cb1c7ded --- /dev/null +++ b/internal/ui/epub_website_test.go @@ -0,0 +1,63 @@ +package ui + +import ( + "bytes" + "strings" + "testing" +) + +func TestInjectHTMLBase(t *testing.T) { + in := []byte(`Ch

Hi

`) + out := injectHTMLBase(in, "/ui/api/documents/d/epub/OEBPS/") + if !bytes.Contains(out, []byte(``)) { + t.Fatalf("missing base: %s", out) + } + if bytes.Count(bytes.ToLower(out), []byte("x`) + out := injectHTMLBase(in, "/epub/") + if !bytes.Contains(out, []byte(``)) { + t.Fatalf("expected wrapped head: %s", out) + } +} + +func TestRewriteRootRelative(t *testing.T) { + in := []byte(`ne`) + out := rewriteRootRelative(in, "/ui/api/documents/d/epub") + s := string(out) + if !strings.Contains(s, `src="/ui/api/documents/d/epub/images/c.jpg"`) { + t.Fatalf("img: %s", s) + } + if !strings.Contains(s, `href="/ui/api/documents/d/epub/ch2.xhtml"`) { + t.Fatalf("a: %s", s) + } + if !strings.Contains(s, `href="https://ex"`) { + t.Fatal("should leave absolute URLs") + } + proto := rewriteRootRelative([]byte(``), "/epub") + if !strings.Contains(string(proto), `src="//cdn.example/x.js"`) { + t.Fatalf("protocol-relative: %s", proto) + } +} + +func TestEpubAssetURL(t *testing.T) { + got := epubAssetURL("doc id", "OEBPS/My File.xhtml") + want := "/ui/api/documents/doc%20id/epub/OEBPS/My%20File.xhtml" + if got != want { + t.Fatalf("got %q want %q", got, want) + } +} + +func TestEpubSpineLabel(t *testing.T) { + if g := epubSpineLabel("OEBPS/part0001.xhtml", 0); g != "part0001" { + t.Fatalf("got %q", g) + } +} diff --git a/internal/ui/form_handlers.go b/internal/ui/form_handlers.go new file mode 100644 index 00000000..a001cdea --- /dev/null +++ b/internal/ui/form_handlers.go @@ -0,0 +1,403 @@ +package ui + +import ( + "errors" + "net/http" + "net/url" + "strings" + + "github.com/ddvk/rmfakecloud/internal/integrations" + "github.com/ddvk/rmfakecloud/internal/model" + "github.com/gin-gonic/gin" + "github.com/google/uuid" + log "github.com/sirupsen/logrus" +) + +var errEmptyLogin = errors.New("user not found") + +func (app *ReactAppWrapper) findUserForLogin(idOrEmail string) (*model.User, error) { + idOrEmail = strings.TrimSpace(idOrEmail) + if idOrEmail == "" { + return nil, errEmptyLogin + } + if user, err := app.userStorer.GetUser(idOrEmail); err == nil && user != nil { + return user, nil + } + users, err := app.userStorer.GetUsers() + if err != nil { + return nil, err + } + for _, u := range users { + if u == nil { + continue + } + if strings.EqualFold(u.ID, idOrEmail) || strings.EqualFold(u.Email, idOrEmail) { + return u, nil + } + } + return nil, errEmptyLogin +} + +func (app *ReactAppWrapper) formLogin(c *gin.Context) { + email := strings.TrimSpace(c.PostForm("email")) + password := c.PostForm("password") + next := c.Query("next") + if next == "" { + next = c.PostForm("next") + } + if next == "" || !strings.HasPrefix(next, "/") { + next = "/" + } + + if app.cfg.CreateFirstUser { + user, err := model.NewUser(email, password) + if err == nil { + user.IsAdmin = true + if err := app.userStorer.RegisterUser(user); err == nil { + app.cfg.CreateFirstUser = false + } + } + } + + user, err := app.findUserForLogin(email) + if err != nil { + c.Redirect(http.StatusSeeOther, "/login?error="+urlQuery("Invalid email or password")+"&email="+urlQuery(email)) + return + } + ok, err := user.CheckPassword(password) + if err != nil || !ok { + c.Redirect(http.StatusSeeOther, "/login?error="+urlQuery("Invalid email or password")+"&email="+urlQuery(email)) + return + } + tokenString, expiresAfter, err := app.issueWebTokenForUser(user, uuid.NewString()) + if err != nil { + c.Redirect(http.StatusSeeOther, "/login?error="+urlQuery("Login failed")) + return + } + c.SetSameSite(http.SameSiteStrictMode) + c.SetCookie(cookieName, tokenString, int(expiresAfter.Seconds()), "/", "", app.cfg.HTTPSCookie, true) + c.Redirect(http.StatusSeeOther, next) +} + +func urlQuery(s string) string { + return url.QueryEscape(s) +} + +func (app *ReactAppWrapper) formLogout(c *gin.Context) { + c.SetCookie(cookieName, "/", -1, "", "", false, true) + c.Redirect(http.StatusSeeOther, "/login") +} + +func (app *ReactAppWrapper) formProfileTheme(c *gin.Context) { + u := app.requirePageUser(c) + if u == nil { + return + } + user := app.getModelUser(u.ID) + if user == nil { + redirectFlash(c, "/profile", "error", "User not found") + return + } + themeID := c.PostForm("themeId") + if themeID == "" { + themeID = "default" + } + if _, _, err := app.themes.getXML(themeID); err != nil { + redirectFlash(c, "/profile", "error", "Unknown theme") + return + } + overrides := map[string]string{} + for k, vals := range c.Request.PostForm { + if strings.HasPrefix(k, "override-") && len(vals) > 0 && vals[0] != "" { + overrides[strings.TrimPrefix(k, "override-")] = vals[0] + } + } + user.ThemeID = themeID + user.ThemeColorOverrides = overrides + if err := app.userStorer.UpdateUser(user); err != nil { + redirectFlash(c, "/profile", "error", "Failed to save theme") + return + } + redirectFlash(c, "/profile", "success", "Theme deployed") +} + +func (app *ReactAppWrapper) formProfilePassword(c *gin.Context) { + u := app.requirePageUser(c) + if u == nil { + return + } + user := app.getModelUser(u.ID) + if user == nil { + redirectFlash(c, "/profile", "error", "User not found") + return + } + cur := c.PostForm("currentPassword") + neu := c.PostForm("newPassword") + ok, err := user.CheckPassword(cur) + if err != nil || !ok { + redirectFlash(c, "/profile", "error", "Current password incorrect") + return + } + if neu == "" { + redirectFlash(c, "/profile", "error", "New password required") + return + } + user.SetPassword(neu) + if err := app.userStorer.UpdateUser(user); err != nil { + redirectFlash(c, "/profile", "error", "Failed to update password") + return + } + redirectFlash(c, "/profile", "success", "Password updated") +} + +func (app *ReactAppWrapper) formPasskeyDelete(c *gin.Context) { + u := app.requirePageUser(c) + if u == nil { + return + } + raw, err := model.ParseCredentialIDBase64(c.Param("id")) + if err != nil { + redirectFlash(c, "/profile", "error", "Invalid passkey id") + return + } + user := app.getModelUser(u.ID) + if user == nil { + redirectFlash(c, "/profile", "error", "User not found") + return + } + if !user.RemoveWebAuthnCredential(raw) { + redirectFlash(c, "/profile", "error", "Passkey not found") + return + } + if err := app.userStorer.UpdateUser(user); err != nil { + redirectFlash(c, "/profile", "error", "Failed to delete passkey") + return + } + redirectFlash(c, "/profile", "success", "Passkey deleted") +} + +func (app *ReactAppWrapper) formUploadDocument(c *gin.Context) { + u := app.requirePageUser(c) + if u == nil { + return + } + backend := app.getBackend(c) + parentID := c.PostForm("parent") + if parentID == "root" { + parentID = "" + } + file, err := c.FormFile("file") + if err != nil { + redirectFlash(c, documentsRedirect(parentID), "error", "No file uploaded") + return + } + f, err := file.Open() + if err != nil { + redirectFlash(c, documentsRedirect(parentID), "error", "Cannot open upload") + return + } + defer f.Close() + if _, err := backend.CreateDocument(u.ID, file.Filename, parentID, f); err != nil { + log.Error(err) + redirectFlash(c, documentsRedirect(parentID), "error", err.Error()) + return + } + backend.Sync(u.ID) + redirectFlash(c, documentsRedirect(parentID), "success", "Uploaded") +} + +func (app *ReactAppWrapper) formCreateFolder(c *gin.Context) { + u := app.requirePageUser(c) + if u == nil { + return + } + backend := app.getBackend(c) + parentID := c.PostForm("parent") + name := strings.TrimSpace(c.PostForm("name")) + if name == "" { + redirectFlash(c, documentsRedirect(parentID), "error", "Folder name required") + return + } + if _, err := backend.CreateFolder(u.ID, name, parentID); err != nil { + redirectFlash(c, documentsRedirect(parentID), "error", err.Error()) + return + } + backend.Sync(u.ID) + redirectFlash(c, documentsRedirect(parentID), "success", "Folder created") +} + +func (app *ReactAppWrapper) formDeleteDocument(c *gin.Context) { + u := app.requirePageUser(c) + if u == nil { + return + } + docid := c.Param("docid") + parentID := c.PostForm("parent") + backend := app.getBackend(c) + if err := backend.DeleteDocument(u.ID, docid); err != nil { + redirectFlash(c, documentsRedirect(parentID), "error", err.Error()) + return + } + redirectFlash(c, documentsRedirect(parentID), "success", "Deleted") +} + +func documentsRedirect(parentID string) string { + if parentID == "" { + return "/documents" + } + return "/documents?folder=" + parentID +} + +func (app *ReactAppWrapper) formCreateUser(c *gin.Context) { + u := app.requirePageUser(c) + if u == nil || !u.Admin { + c.AbortWithStatus(http.StatusForbidden) + return + } + id := strings.TrimSpace(c.PostForm("userid")) + email := strings.TrimSpace(c.PostForm("email")) + pass := c.PostForm("password") + if pass == "" { + pass = c.PostForm("newPassword") + } + if id == "" || pass == "" { + redirectFlash(c, "/admin", "error", "User ID and password required") + return + } + user, err := model.NewUser(id, pass) + if err != nil { + redirectFlash(c, "/admin", "error", err.Error()) + return + } + user.Email = email + if err := app.userStorer.UpdateUser(user); err != nil { + redirectFlash(c, "/admin", "error", err.Error()) + return + } + redirectFlash(c, "/admin", "success", "User created") +} + +func (app *ReactAppWrapper) formDeleteUser(c *gin.Context) { + u := app.requirePageUser(c) + if u == nil || !u.Admin { + c.AbortWithStatus(http.StatusForbidden) + return + } + uid := c.Param("userid") + if uid == u.ID { + redirectFlash(c, "/admin", "error", "Cannot delete yourself") + return + } + if err := app.userStorer.RemoveUser(uid); err != nil { + redirectFlash(c, "/admin", "error", err.Error()) + return + } + redirectFlash(c, "/admin", "success", "User deleted") +} + +func (app *ReactAppWrapper) formCreateIntegration(c *gin.Context) { + u := app.requirePageUser(c) + if u == nil { + return + } + user := app.getModelUser(u.ID) + if user == nil { + redirectFlash(c, "/integrations", "error", "User not found") + return + } + intg := model.IntegrationConfig{ + ID: uuid.NewString(), + Name: strings.TrimSpace(c.PostForm("name")), + Provider: strings.TrimSpace(c.PostForm("provider")), + Username: c.PostForm("username"), + Password: c.PostForm("password"), + Address: c.PostForm("address"), + Path: c.PostForm("path"), + Endpoint: c.PostForm("endpoint"), + } + if intg.Provider == integrations.LocalfsProvider { + redirectFlash(c, "/integrations", "error", "Local filesystem integrations must be edited in the user profile file on the server") + return + } + user.Integrations = append(user.Integrations, intg) + if err := app.userStorer.UpdateUser(user); err != nil { + redirectFlash(c, "/integrations", "error", err.Error()) + return + } + redirectFlash(c, "/integrations", "success", "Integration created") +} + +func (app *ReactAppWrapper) formDeleteIntegration(c *gin.Context) { + u := app.requirePageUser(c) + if u == nil { + return + } + user := app.getModelUser(u.ID) + if user == nil { + redirectFlash(c, "/integrations", "error", "User not found") + return + } + id := c.Param("intid") + out := user.Integrations[:0] + for _, i := range user.Integrations { + if i.ID != id { + out = append(out, i) + } + } + user.Integrations = out + if err := app.userStorer.UpdateUser(user); err != nil { + redirectFlash(c, "/integrations", "error", err.Error()) + return + } + redirectFlash(c, "/integrations", "success", "Integration deleted") +} + +func (app *ReactAppWrapper) formSaveTheme(c *gin.Context) { + u := app.requirePageUser(c) + if u == nil || !u.Admin { + c.AbortWithStatus(http.StatusForbidden) + return + } + id := strings.TrimSpace(c.PostForm("id")) + name := strings.TrimSpace(c.PostForm("name")) + xmlBody := c.PostForm("xml") + published := c.PostForm("published") == "true" || c.PostForm("published") == "on" + if id == "" || xmlBody == "" { + redirectFlash(c, "/admin/themes", "error", "ID and XML required") + return + } + if err := app.themes.save(id, name, published, []byte(xmlBody)); err != nil { + redirectFlash(c, "/admin/themes?id="+id, "error", err.Error()) + return + } + redirectFlash(c, "/admin/themes?id="+id, "success", "Theme saved") +} + +func (app *ReactAppWrapper) formPublishTheme(c *gin.Context) { + u := app.requirePageUser(c) + if u == nil || !u.Admin { + c.AbortWithStatus(http.StatusForbidden) + return + } + id := c.Param("id") + published := c.PostForm("published") != "false" + if err := app.themes.setPublished(id, published); err != nil { + redirectFlash(c, "/admin/themes?id="+id, "error", err.Error()) + return + } + redirectFlash(c, "/admin/themes?id="+id, "success", "Publish state updated") +} + +func (app *ReactAppWrapper) formDeleteTheme(c *gin.Context) { + u := app.requirePageUser(c) + if u == nil || !u.Admin { + c.AbortWithStatus(http.StatusForbidden) + return + } + id := c.Param("id") + if err := app.themes.delete(id); err != nil { + redirectFlash(c, "/admin/themes", "error", err.Error()) + return + } + redirectFlash(c, "/admin/themes", "success", "Theme deleted") +} diff --git a/internal/ui/handlers.go b/internal/ui/handlers.go index 54c5b579..ee90f923 100644 --- a/internal/ui/handlers.go +++ b/internal/ui/handlers.go @@ -4,7 +4,9 @@ import ( "encoding/json" "errors" "fmt" + "io" "net/http" + "strconv" "time" "github.com/ddvk/rmfakecloud/internal/common" @@ -113,7 +115,7 @@ func (app *ReactAppWrapper) login(c *gin.Context) { } // Try to find the user - user, err := app.userStorer.GetUser(form.Email) + user, err := app.findUserForLogin(form.Email) if err != nil { log.Error(uiLogger, err, " cannot load user, login failed ip: ", c.ClientIP()) c.AbortWithStatus(http.StatusUnauthorized) @@ -130,6 +132,23 @@ func (app *ReactAppWrapper) login(c *gin.Context) { return } + tokenString, expiresAfter, err := app.issueWebTokenForUser(user, uuid.NewString()) + if err != nil { + log.Error(err) + c.AbortWithStatus(http.StatusInternalServerError) + return + } + log.Debug("cookie expires after: ", expiresAfter) + c.SetSameSite(http.SameSiteStrictMode) + c.SetCookie(cookieName, tokenString, int(expiresAfter.Seconds()), "/", "", app.cfg.HTTPSCookie, true) + + c.String(http.StatusOK, tokenString) +} + +func (app *ReactAppWrapper) issueWebTokenForUser(user *model.User, browserID string) (string, time.Duration, error) { + if user == nil { + return "", 0, fmt.Errorf("user is nil") + } scopes := "" if user.Sync15 { scopes = isSync15Key @@ -138,7 +157,7 @@ func (app *ReactAppWrapper) login(c *gin.Context) { expires := time.Now().Add(expiresAfter) claims := &WebUserClaims{ UserID: user.ID, - BrowserID: uuid.NewString(), + BrowserID: browserID, Email: user.Email, Scopes: scopes, RegisteredClaims: jwt.RegisteredClaims{ @@ -154,17 +173,10 @@ func (app *ReactAppWrapper) login(c *gin.Context) { } tokenString, err := common.SignClaims(claims, app.cfg.JWTSecretKey) - if err != nil { - log.Error(err) - c.AbortWithStatus(http.StatusInternalServerError) - return + return "", 0, err } - log.Debug("cookie expires after: ", expiresAfter) - c.SetSameSite(http.SameSiteStrictMode) - c.SetCookie(cookieName, tokenString, int(expiresAfter.Seconds()), "/", "", app.cfg.HTTPSCookie, true) - - c.String(http.StatusOK, tokenString) + return tokenString, expiresAfter, nil } func (app *ReactAppWrapper) changePassword(c *gin.Context) { @@ -236,6 +248,21 @@ func (app *ReactAppWrapper) newCode(c *gin.Context) { c.JSON(http.StatusOK, code) } +func (app *ReactAppWrapper) codeStatus(c *gin.Context) { + uid := userID(c) + user, err := app.userStorer.GetUser(uid) + if err != nil { + log.Error("Unable to find user: ", err) + c.AbortWithStatusJSON(http.StatusInternalServerError, viewmodel.NewErrorResponse(err.Error())) + return + } + code, ok := app.codeConnector.CurrentCode(user.ID) + if !ok { + code = "" + } + c.JSON(http.StatusOK, gin.H{"code": code, "active": ok}) +} + func (app *ReactAppWrapper) getBackend(c *gin.Context) backend { s, ok := c.Get(backendVersionKey) if !ok { @@ -284,10 +311,53 @@ func (app *ReactAppWrapper) getDocument(c *gin.Context) { if exportType == "rmdoc" { c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s.rmdoc\"", docid)) } + if exportType == "epub" { + c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s.epub\"", docid)) + c.Header("Content-Type", "application/epub+zip") + c.Header("X-Content-Type-Options", "nosniff") + c.DataFromReader(http.StatusOK, -1, "application/epub+zip", reader, nil) + return + } + + if exportType == "pdf" { + c.Header("Content-Type", "application/pdf") + c.Header("X-Content-Type-Options", "nosniff") + c.DataFromReader(http.StatusOK, -1, "application/pdf", reader, nil) + return + } c.DataFromReader(http.StatusOK, -1, "application/octet-stream", reader, nil) } +func (app *ReactAppWrapper) getDocumentPage(c *gin.Context) { + uid := userID(c) + docid := common.ParamS(docIDParam, c) + pagenum, err := strconv.Atoi(c.Param("pagenum")) + if err != nil || pagenum < 1 { + c.AbortWithStatus(http.StatusBadRequest) + return + } + type pagePNGExporter interface { + ExportPagePNG(uid, docid string, pageNum int) (io.ReadCloser, error) + } + backend := app.getBackend(c) + pe, ok := backend.(pagePNGExporter) + if !ok { + c.AbortWithStatus(http.StatusNotFound) + return + } + reader, err := pe.ExportPagePNG(uid, docid, pagenum) + if err != nil { + log.Error(err) + c.AbortWithStatus(http.StatusInternalServerError) + return + } + defer reader.Close() + c.Header("Content-Type", "image/png") + c.Header("X-Content-Type-Options", "nosniff") + c.DataFromReader(http.StatusOK, -1, "image/png", reader, nil) +} + func (app *ReactAppWrapper) getDocumentMetadata(c *gin.Context) { uid := userID(c) docid := common.ParamS(docIDParam, c) @@ -893,4 +963,3 @@ func (app *ReactAppWrapper) screenshareDeleteRoom(c *gin.Context) { app.roomManager.DeleteAllForUser(uid) c.Status(http.StatusNoContent) } - diff --git a/internal/ui/page_context.go b/internal/ui/page_context.go new file mode 100644 index 00000000..7ea404c4 --- /dev/null +++ b/internal/ui/page_context.go @@ -0,0 +1,214 @@ +package ui + +import ( + "bytes" + "fmt" + "html" + "net/http" + "net/url" + "strings" + + "github.com/ddvk/rmfakecloud/internal/common" + "github.com/ddvk/rmfakecloud/internal/model" + "github.com/gin-gonic/gin" + log "github.com/sirupsen/logrus" +) + +type pageUser struct { + ID string + Email string + Admin bool +} + +func (app *ReactAppWrapper) optionalUser(c *gin.Context) *pageUser { + token, err := c.Cookie(cookieName) + if err != nil || token == "" { + return nil + } + claims := &WebUserClaims{} + if err := common.ClaimsFromToken(claims, token, app.cfg.JWTSecretKey); err != nil { + return nil + } + admin := false + for _, r := range claims.Roles { + if r == AdminRole { + admin = true + break + } + } + return &pageUser{ID: claims.UserID, Email: claims.Email, Admin: admin} +} + +func (app *ReactAppWrapper) requirePageUser(c *gin.Context) *pageUser { + u := app.optionalUser(c) + if u == nil { + next := url.QueryEscape(c.Request.URL.RequestURI()) + c.Redirect(http.StatusFound, "/login?next="+next) + c.Abort() + return nil + } + // Populate gin context for backends that expect auth middleware keys + app.hydrateAuthContext(c, u) + return u +} + +func (app *ReactAppWrapper) hydrateAuthContext(c *gin.Context, u *pageUser) { + token, _ := c.Cookie(cookieName) + claims := &WebUserClaims{} + _ = common.ClaimsFromToken(claims, token, app.cfg.JWTSecretKey) + uid := common.SanitizeUid(claims.UserID) + c.Set(userIDContextKey, uid) + c.Set(browserIDContextKey, claims.BrowserID) + c.Set(backendVersionKey, common.Sync10) + for _, s := range strings.Fields(claims.Scopes) { + if s == isSync15Key { + c.Set(backendVersionKey, common.Sync15) + } + } + if u.Admin { + c.Set(AdminRole, true) + } +} + +func (app *ReactAppWrapper) loadUserTheme(c *gin.Context, u *pageUser) (themeXML []byte, css string, chrome string, formFactor string) { + formFactor = clientFormFactor(c.Request) + themeID := "default" + var overrides map[string]string + if u != nil { + user, err := app.userStorer.GetUser(u.ID) + if err == nil && user != nil { + if user.ThemeID != "" { + themeID = user.ThemeID + } + overrides = user.ThemeColorOverrides + } + } + xmlBytes, _, err := app.themes.getXML(themeID) + if err != nil { + xmlBytes, _, _ = app.themes.getXML("default") + } + xmlBytes = applyColorOverridesXML(xmlBytes, overrides) + css, err = themeToCSS(xmlBytes, formFactor) + if err != nil { + log.Warn("theme css: ", err) + css = "" + } + chrome = chromeStyleFromTheme(xmlBytes, formFactor) + return xmlBytes, css, chrome, formFactor +} + +func defaultNav(path string, admin bool) []navItem { + items := []navItem{ + {ID: "documents", Href: "/documents", Label: "Documents", Icon: "folder"}, + {ID: "integrations", Href: "/integrations", Label: "Integrations", Icon: "puzzle"}, + {ID: "connect", Href: "/connect", Label: "Connect", Icon: "link"}, + {ID: "screenshare", Href: "/screenshare", Label: "Screen share", Icon: "display"}, + {ID: "admin", Href: "/admin", Label: "Admin", Icon: "gear", AdminOnly: true}, + {ID: "help", Href: "/help", Label: "Help", Icon: "book"}, + {ID: "profile", Href: "/profile", Label: "Profile", Icon: "person"}, + } + for i := range items { + if items[i].Href == path || (items[i].Href != "/" && strings.HasPrefix(path, items[i].Href)) { + items[i].Active = true + } + if path == "/" && items[i].ID == "documents" { + // home is not documents + items[i].Active = false + } + } + _ = admin + return items +} + +type navItem struct { + ID, Href, Label, Icon string + AdminOnly, Active bool +} + +func (app *ReactAppWrapper) renderPage(c *gin.Context, pageXML []byte) { + setFormFactorHeaders(c) + html, ok, err := app.transformPageXML(pageXML) + if err != nil { + log.Warn("server xslt failed, using browser bootstrap: ", err) + } + if ok && len(html) > 0 { + c.Data(http.StatusOK, "text/html; charset=utf-8", html) + return + } + c.Data(http.StatusOK, "text/html; charset=utf-8", bootstrapXSLTHTML(pageXML)) +} + +func (app *ReactAppWrapper) flashFromQuery(c *gin.Context) (ftype, msg string) { + ftype = c.Query("flash") + msg = c.Query("msg") + return +} + +func redirectFlash(c *gin.Context, path, ftype, msg string) { + u := path + sep := "?" + if strings.Contains(path, "?") { + sep = "&" + } + c.Redirect(http.StatusSeeOther, u+sep+"flash="+url.QueryEscape(ftype)+"&msg="+url.QueryEscape(msg)) +} + +func xmlCDATA(s string) string { + return "", "]]]]>") + "]]>" +} + +func writePageOpen(b *bytes.Buffer, kind, title, path, chrome, css string, u *pageUser, flashType, flashMsg string, nav []navItem) { + fmt.Fprintf(b, ``) + fmt.Fprintf(b, ``, + xmlAttr(kind), xmlAttr(title), xmlAttr(path), xmlAttr(chrome)) + if u != nil { + admin := "false" + if u.Admin { + admin = "true" + } + fmt.Fprintf(b, ``, xmlAttr(u.ID), xmlAttr(u.Email), admin) + } + if flashMsg != "" { + if flashType == "" { + flashType = "info" + } + fmt.Fprintf(b, `%s`, xmlAttr(flashType), esc(flashMsg)) + } + if css != "" { + fmt.Fprintf(b, `%s`, xmlCDATA(css)) + } + b.WriteString(``) +} + +func writePageClose(b *bytes.Buffer) { + b.WriteString(``) +} + +func esc(s string) string { + return html.EscapeString(s) +} + +func xmlAttr(s string) string { + return html.EscapeString(s) +} + +func (app *ReactAppWrapper) getModelUser(id string) *model.User { + u, err := app.userStorer.GetUser(id) + if err != nil { + return nil + } + return u +} diff --git a/internal/ui/page_handlers.go b/internal/ui/page_handlers.go new file mode 100644 index 00000000..91b0feff --- /dev/null +++ b/internal/ui/page_handlers.go @@ -0,0 +1,614 @@ +package ui + +import ( + "bytes" + "fmt" + "net/http" + "sort" + "strings" + "time" + + "github.com/ddvk/rmfakecloud/internal/model" + "github.com/ddvk/rmfakecloud/internal/storage/epub" + "github.com/ddvk/rmfakecloud/internal/storage/models" + "github.com/ddvk/rmfakecloud/internal/ui/viewmodel" + "github.com/gin-gonic/gin" + log "github.com/sirupsen/logrus" +) + +func (app *ReactAppWrapper) pageHome(c *gin.Context) { + u := app.optionalUser(c) + if u == nil { + c.Redirect(http.StatusFound, "/login") + return + } + _, css, chrome, _ := app.loadUserTheme(c, u) + ft, fm := app.flashFromQuery(c) + var b bytes.Buffer + writePageOpen(&b, "home", "rmfakecloud", "/", chrome, css, u, ft, fm, defaultNav("/", u.Admin)) + b.WriteString(``) + b.WriteString(`

Self-hosted reMarkable cloud. Use Documents to browse notebooks, Connect to pair a tablet, and Profile to deploy a theme.

`) + b.WriteString(`

Help · Documents · Connect

`) + b.WriteString(`
`) + writePageClose(&b) + app.renderPage(c, b.Bytes()) +} + +func (app *ReactAppWrapper) pageHelp(c *gin.Context) { + u := app.requirePageUser(c) + if u == nil { + return + } + _, css, chrome, _ := app.loadUserTheme(c, u) + ft, fm := app.flashFromQuery(c) + var b bytes.Buffer + writePageOpen(&b, "help", "Help — rmfakecloud", "/help", chrome, css, u, ft, fm, defaultNav("/help", u.Admin)) + b.WriteString(``) + writeHelpSections(&b) + b.WriteString(``) + writePageClose(&b) + app.renderPage(c, b.Bytes()) +} + +func writeHelpSections(b *bytes.Buffer) { + type link struct { + href, label, note string + internal bool + } + type section struct { + id, title, intro string + links []link + } + docs := "https://ddvk.github.io/rmfakecloud" + hc := "https://support.remarkable.com/hc/en-us" + sections := []section{ + {id: "this-instance", title: "This cloud (quick start)", intro: "Day-to-day pages on this instance.", links: []link{ + {"/connect", "Connect / pair a tablet", "One-time code for Account → Connect", true}, + {"/documents", "Documents", "Browse, upload, download", true}, + {"/integrations", "Integrations", "WebDAV, FTP, local folders", true}, + {"/screenshare", "Screen share", "Live view when MQTT/WebRTC is configured", true}, + {"/profile", "Profile", "Password, passkeys, deploy a theme", true}, + }}, + {id: "official", title: "Official reMarkable help", intro: "From reMarkable Support.", links: []link{ + {"https://support.remarkable.com/s/", "reMarkable Support home", "Search official articles", false}, + {hc + "/categories/360000160977-Getting-Started", "Getting started", "Setup and first steps", false}, + {hc + "/categories/360000161018-My-reMarkable", "My reMarkable", "Device settings and care", false}, + {hc + "/categories/360000160997-Software", "Software", "Updates and apps", false}, + }}, + {id: "rmfakecloud", title: "rmfakecloud documentation", intro: "Project docs for self-hosted sync.", links: []link{ + {docs + "/", "Documentation home", "Overview", false}, + {docs + "/remarkable/setup/", "Tablet setup", "Proxy, hosts, pairing", false}, + {docs + "/install/configuration/", "Server configuration", "Environment variables", false}, + {docs + "/usage/integrations/", "Integrations usage", "WebDAV, FTP, webhooks", false}, + {"https://github.com/ddvk/rmfakecloud", "GitHub repository", "Source and issues", false}, + }}, + } + for _, s := range sections { + fmt.Fprintf(b, `
%s`, xmlAttr(s.id), xmlAttr(s.title), esc(s.intro)) + for _, l := range s.links { + internal := "false" + if l.internal { + internal = "true" + } + fmt.Fprintf(b, `%s`, + xmlAttr(l.href), internal, xmlAttr(l.note), esc(l.label)) + } + b.WriteString(`
`) + } +} + +func (app *ReactAppWrapper) pageLogin(c *gin.Context) { + if u := app.optionalUser(c); u != nil { + c.Redirect(http.StatusFound, "/") + return + } + _, css, chrome, _ := app.loadUserTheme(c, nil) + errMsg := c.Query("error") + email := c.Query("email") + passkey := "false" + if app.webAuthnEnabled() { + passkey = "true" + } + reg := "false" + if app.cfg.RegistrationOpen { + reg = "true" + } + var b bytes.Buffer + writePageOpen(&b, "login", "Login — rmfakecloud", "/login", chrome, css, nil, "", "", nil) + fmt.Fprintf(&b, ``, + passkey, reg, xmlAttr(email), xmlAttr(errMsg)) + writePageClose(&b) + app.renderPage(c, b.Bytes()) +} + +func (app *ReactAppWrapper) pageConnect(c *gin.Context) { + u := app.requirePageUser(c) + if u == nil { + return + } + themeXML, css, chrome, ff := app.loadUserTheme(c, u) + gauge, ploc, pstyle, prompt := connectAttrsFromTheme(themeXML, ff) + ft, fm := app.flashFromQuery(c) + var b bytes.Buffer + writePageOpen(&b, "connect", "Connect — rmfakecloud", "/connect", chrome, css, u, ft, fm, defaultNav("/connect", u.Admin)) + fmt.Fprintf(&b, ``, + xmlAttr(gauge), xmlAttr(ploc), xmlAttr(pstyle), xmlAttr(prompt)) + writePageClose(&b) + app.renderPage(c, b.Bytes()) +} + +func (app *ReactAppWrapper) pageProfile(c *gin.Context) { + u := app.requirePageUser(c) + if u == nil { + return + } + user := app.getModelUser(u.ID) + _, css, chrome, _ := app.loadUserTheme(c, u) + ft, fm := app.flashFromQuery(c) + themes, _ := app.themes.list(u.Admin) + selected := "default" + if user != nil && user.ThemeID != "" { + selected = user.ThemeID + } + if selected == "default" { + selected = "dark" + } + var b bytes.Buffer + writePageOpen(&b, "profile", "Profile — rmfakecloud", "/profile", chrome, css, u, ft, fm, defaultNav("/profile", u.Admin)) + b.WriteString(``) + b.WriteString(``) + for _, t := range themes { + if !t.Published && !u.Admin { + continue + } + sel := "" + if t.ID == selected { + sel = ` selected="true"` + } + fmt.Fprintf(&b, ``, xmlAttr(t.ID), xmlAttr(t.Name), sel) + } + b.WriteString(``) + b.WriteString(``) + keys := []string{"background1", "background2", "foreground1", "foreground2", "action"} + overrides := map[string]string{} + if user != nil { + overrides = user.ThemeColorOverrides + } + for _, k := range keys { + v := "#212529" + if overrides != nil && overrides[k] != "" { + v = overrides[k] + } else { + switch k { + case "background2": + v = "#0f0f0f" + case "foreground1": + v = "#f8f7f6" + case "foreground2": + v = "#e8e3d9" + case "action": + v = "#EE7B30" + } + } + fmt.Fprintf(&b, ``, xmlAttr(k), xmlAttr(v)) + } + b.WriteString(``) + enabled := "false" + if app.webAuthnEnabled() { + enabled = "true" + } + fmt.Fprintf(&b, ``, enabled) + if user != nil { + for _, cred := range user.WebAuthnCredentials { + name := cred.Name + cid := model.CredentialIDBase64(cred.ID) + if name == "" { + name = cid + } + created := "" + if !cred.CreatedAt.IsZero() { + created = cred.CreatedAt.Format(time.RFC3339) + } + fmt.Fprintf(&b, ``, xmlAttr(cid), xmlAttr(name), xmlAttr(created)) + } + } + b.WriteString(``) + b.WriteString(``) + writePageClose(&b) + app.renderPage(c, b.Bytes()) +} + +func (app *ReactAppWrapper) pageDocuments(c *gin.Context) { + u := app.requirePageUser(c) + if u == nil { + return + } + _, css, chrome, _ := app.loadUserTheme(c, u) + ft, fm := app.flashFromQuery(c) + folderID := c.Query("folder") + backend := app.getBackend(c) + tree, err := backend.GetDocumentTree(u.ID) + if err != nil { + log.Error(err) + redirectFlash(c, "/documents", "error", "Unable to load documents") + return + } + folderName := "My Files" + parentID := "" + entries := tree.Entries + if folderID != "" { + if found := findFolderEntries(tree.Entries, folderID); found != nil { + entries = found + folderName = findFolderName(tree.Entries, folderID) + if folderName == "" { + folderName = "My Files" + } + parentID = findFolderParent(tree.Entries, folderID) + } else { + entries = nil + } + } + folders, files := splitDocEntries(entries) + sort.SliceStable(folders, func(i, j int) bool { + if folders[i].Pinned != folders[j].Pinned { + return folders[i].Pinned + } + return folders[i].Name < folders[j].Name + }) + sort.SliceStable(files, func(i, j int) bool { + if files[i].Pinned != files[j].Pinned { + return files[i].Pinned + } + return files[i].LastModified.After(files[j].LastModified) + }) + + var b bytes.Buffer + writePageOpen(&b, "documents", folderName+" — rmfakecloud", "/documents", chrome, css, u, ft, fm, defaultNav("/documents", u.Admin)) + fmt.Fprintf(&b, ``, + xmlAttr(folderID), xmlAttr(folderName), xmlAttr(parentID)) + b.WriteString(``) + for _, d := range folders { + pin := "false" + if d.Pinned { + pin = "true" + } + fmt.Fprintf(&b, ``, + xmlAttr(d.ID), xmlAttr(d.Name), pin, xmlAttr(d.LastModified.Format(time.RFC3339))) + } + b.WriteString(``) + for _, d := range files { + pin := "false" + if d.Pinned { + pin = "true" + } + fmt.Fprintf(&b, ``, + xmlAttr(d.ID), xmlAttr(d.Name), xmlAttr(normalizeDocType(d.DocumentType)), + d.PageCount, d.CurrentPage, models.ThumbPage1(d.CurrentPage, d.PageCount), pin, xmlAttr(d.LastModified.Format(time.RFC3339))) + } + b.WriteString(``) + writePageClose(&b) + app.renderPage(c, b.Bytes()) +} + +func normalizeDocType(t string) string { + t = strings.ToLower(strings.TrimSpace(t)) + t = strings.TrimPrefix(t, ".") + switch t { + case "pdf", "application/pdf": + return "pdf" + case "epub", "application/epub+zip": + return "epub" + case "folder", "collection": + return "folder" + default: + return "notebook" + } +} + +func splitDocEntries(entries []viewmodel.Entry) (folders []viewmodel.Directory, files []viewmodel.Document) { + for _, e := range entries { + switch d := e.(type) { + case *viewmodel.Directory: + folders = append(folders, *d) + case *viewmodel.Document: + files = append(files, *d) + } + } + return +} + +func findFolderParent(entries []viewmodel.Entry, id string) string { + var walk func(list []viewmodel.Entry, parent string) (string, bool) + walk = func(list []viewmodel.Entry, parent string) (string, bool) { + for _, e := range list { + d, ok := e.(*viewmodel.Directory) + if !ok { + continue + } + if d.ID == id { + return parent, true + } + if p, found := walk(d.Entries, d.ID); found { + return p, true + } + } + return "", false + } + p, _ := walk(entries, "") + return p +} + +func findFolderEntries(entries []viewmodel.Entry, id string) []viewmodel.Entry { + for _, e := range entries { + d, ok := e.(*viewmodel.Directory) + if !ok { + continue + } + if d.ID == id { + return d.Entries + } + if nested := findFolderEntries(d.Entries, id); nested != nil { + return nested + } + } + return nil +} + +func findFolderName(entries []viewmodel.Entry, id string) string { + for _, e := range entries { + d, ok := e.(*viewmodel.Directory) + if !ok { + continue + } + if d.ID == id { + return d.Name + } + if n := findFolderName(d.Entries, id); n != "" { + return n + } + } + return "" +} + +func findDocument(entries []viewmodel.Entry, id string) *viewmodel.Document { + for _, e := range entries { + switch d := e.(type) { + case *viewmodel.Document: + if d.ID == id { + return d + } + case *viewmodel.Directory: + if found := findDocument(d.Entries, id); found != nil { + return found + } + } + } + return nil +} + +func (app *ReactAppWrapper) pagePDF(c *gin.Context) { + u := app.requirePageUser(c) + if u == nil { + return + } + docID := c.Param("docid") + _, css, chrome, _ := app.loadUserTheme(c, u) + ft, fm := app.flashFromQuery(c) + name := docID + kind := "pdf" + pages := 0 + page := 0 + backend := app.getBackend(c) + if tree, err := backend.GetDocumentTree(u.ID); err == nil && tree != nil { + d := findDocument(tree.Entries, docID) + if d == nil { + d = findDocument(tree.Trash, docID) + } + if d != nil { + name = d.Name + kind = normalizeDocType(d.DocumentType) + pages = d.PageCount + page = d.CurrentPage + } + } + if kind == "epub" { + app.pageEpub(c, u, css, chrome, ft, fm, docID, name, page, pages) + return + } + var b bytes.Buffer + writePageOpen(&b, "pdf", name+" — rmfakecloud", "/documents/"+docID, chrome, css, u, ft, fm, defaultNav("/documents", u.Admin)) + fmt.Fprintf(&b, ``, + xmlAttr(docID), xmlAttr(name), xmlAttr(docID)) + writePageClose(&b) + app.renderPage(c, b.Bytes()) +} + +func (app *ReactAppWrapper) pageEpub(c *gin.Context, u *pageUser, css, chrome, ft, fm, docID, name string, page, pages int) { + type epubManifestBackend interface { + GetEpubManifest(uid, docid string) (*epub.Manifest, error) + } + var spine []string + backend := app.getBackend(c) + if eb, ok := backend.(epubManifestBackend); ok { + if man, err := eb.GetEpubManifest(u.ID, docID); err == nil && man != nil { + spine = man.Spine + } + } + if pages == 0 { + pages = len(spine) + } + start := models.ThumbPage1(page, pages) + if start < 1 { + start = 1 + } + startPath := "" + if len(spine) > 0 { + idx := start - 1 + if idx < 0 { + idx = 0 + } + if idx >= len(spine) { + idx = len(spine) - 1 + } + startPath = spine[idx] + } + + startHref := "" + if startPath != "" { + startHref = epubAssetURL(docID, startPath) + } + var b bytes.Buffer + writePageOpen(&b, "epub", name+" — rmfakecloud", "/documents/"+docID, chrome, css, u, ft, fm, defaultNav("/documents", u.Admin)) + fmt.Fprintf(&b, ``, + xmlAttr(docID), xmlAttr(name), xmlAttr(startPath), xmlAttr(startHref), + xmlAttr("/ui/api/documents/"+docID+"?type=epub"), page, pages) + b.WriteString(``) + for i, p := range spine { + label := epubSpineLabel(p, i) + fmt.Fprintf(&b, ``, xmlAttr(p), xmlAttr(label), xmlAttr(epubAssetURL(docID, p))) + } + b.WriteString(``) + writePageClose(&b) + app.renderPage(c, b.Bytes()) +} + +func (app *ReactAppWrapper) pageIntegrations(c *gin.Context) { + u := app.requirePageUser(c) + if u == nil { + return + } + user := app.getModelUser(u.ID) + _, css, chrome, _ := app.loadUserTheme(c, u) + ft, fm := app.flashFromQuery(c) + var b bytes.Buffer + writePageOpen(&b, "integrations", "Integrations — rmfakecloud", "/integrations", chrome, css, u, ft, fm, defaultNav("/integrations", u.Admin)) + b.WriteString(``) + if user != nil { + for _, i := range user.Integrations { + fmt.Fprintf(&b, ``, + xmlAttr(i.ID), xmlAttr(i.Name), xmlAttr(i.Provider)) + } + } + b.WriteString(``) + writePageClose(&b) + app.renderPage(c, b.Bytes()) +} + +func (app *ReactAppWrapper) pageAdmin(c *gin.Context) { + u := app.requirePageUser(c) + if u == nil { + return + } + if !u.Admin { + c.AbortWithStatus(http.StatusForbidden) + return + } + _, css, chrome, _ := app.loadUserTheme(c, u) + ft, fm := app.flashFromQuery(c) + users, err := app.userStorer.GetUsers() + if err != nil { + redirectFlash(c, "/", "error", "Unable to load users") + return + } + var b bytes.Buffer + writePageOpen(&b, "admin", "Admin — rmfakecloud", "/admin", chrome, css, u, ft, fm, defaultNav("/admin", u.Admin)) + b.WriteString(``) + for _, usr := range users { + admin := "false" + if usr.IsAdmin { + admin = "true" + } + fmt.Fprintf(&b, ``, + xmlAttr(usr.ID), xmlAttr(usr.Email), xmlAttr(usr.Name), admin) + } + b.WriteString(``) + writePageClose(&b) + app.renderPage(c, b.Bytes()) +} + +func (app *ReactAppWrapper) pageThemeStudio(c *gin.Context) { + u := app.requirePageUser(c) + if u == nil { + return + } + if !u.Admin { + c.AbortWithStatus(http.StatusForbidden) + return + } + _, css, chrome, _ := app.loadUserTheme(c, u) + ft, fm := app.flashFromQuery(c) + themes, _ := app.themes.list(true) + editID := c.Query("id") + if editID == "" && len(themes) > 0 { + editID = themes[0].ID + } + var editXML []byte + var editName string + var published bool + if editID != "" { + editXML, _, _ = app.themes.getXML(editID) + root, err := parseThemeRoot(editXML) + if err == nil { + editName = root.Name + published = strings.EqualFold(root.Published, "true") || root.Published == "" + } + } + var b bytes.Buffer + writePageOpen(&b, "themes", "Theme studio — rmfakecloud", "/admin/themes", chrome, css, u, ft, fm, defaultNav("/admin", u.Admin)) + b.WriteString(``) + for _, t := range themes { + pub := "false" + if t.Published { + pub = "true" + } + builtin := "false" + if t.Builtin { + builtin = "true" + } + fmt.Fprintf(&b, ``, + xmlAttr(t.ID), xmlAttr(t.Name), pub, builtin) + } + pub := "false" + if published { + pub = "true" + } + fmt.Fprintf(&b, `%s`, + xmlAttr(editID), xmlAttr(editName), pub, xmlCDATA(string(editXML))) + b.WriteString(``) + writePageClose(&b) + app.renderPage(c, b.Bytes()) +} + +func (app *ReactAppWrapper) pageScreenShare(c *gin.Context) { + u := app.requirePageUser(c) + if u == nil { + return + } + _, css, chrome, _ := app.loadUserTheme(c, u) + ft, fm := app.flashFromQuery(c) + var b bytes.Buffer + writePageOpen(&b, "screenshare", "Screen share — rmfakecloud", "/screenshare", chrome, css, u, ft, fm, defaultNav("/screenshare", u.Admin)) + b.WriteString(``) + writePageClose(&b) + app.renderPage(c, b.Bytes()) +} + +func (app *ReactAppWrapper) page404(c *gin.Context) { + u := app.optionalUser(c) + _, css, chrome, _ := app.loadUserTheme(c, u) + admin := u != nil && u.Admin + var b bytes.Buffer + writePageOpen(&b, "error", "Not found — rmfakecloud", c.Request.URL.Path, chrome, css, u, "", "", defaultNav("", admin)) + b.WriteString(``) + writePageClose(&b) + setFormFactorHeaders(c) + html, ok, err := app.transformPageXML(b.Bytes()) + if err != nil { + log.Warn("server xslt failed, using browser bootstrap: ", err) + } + payload := bootstrapXSLTHTML(b.Bytes()) + if ok && len(html) > 0 { + payload = html + } + c.Data(http.StatusNotFound, "text/html; charset=utf-8", payload) +} diff --git a/internal/ui/page_handlers_doctype_test.go b/internal/ui/page_handlers_doctype_test.go new file mode 100644 index 00000000..a303a40f --- /dev/null +++ b/internal/ui/page_handlers_doctype_test.go @@ -0,0 +1,21 @@ +package ui + +import "testing" + +func TestNormalizeDocType(t *testing.T) { + cases := map[string]string{ + "pdf": "pdf", + ".PDF": "pdf", + "application/pdf": "pdf", + "epub": "epub", + "application/epub+zip": "epub", + "notebook": "notebook", + "Quick Notes": "notebook", + "": "notebook", + } + for in, want := range cases { + if got := normalizeDocType(in); got != want { + t.Fatalf("%q: got %q want %q", in, got, want) + } + } +} diff --git a/internal/ui/routes.go b/internal/ui/routes.go index a463f7f2..da13ab13 100644 --- a/internal/ui/routes.go +++ b/internal/ui/routes.go @@ -10,7 +10,7 @@ import ( // RegisterRoutes the apps routes func (app *ReactAppWrapper) RegisterRoutes(router *gin.Engine) { - router.StaticFS(app.prefix, app) + router.StaticFS(app.prefix, app.fs) router.GET("/favicon.ico", func(c *gin.Context) { c.FileFromFS("/favicon.ico", app.fs) @@ -19,24 +19,55 @@ func (app *ReactAppWrapper) RegisterRoutes(router *gin.Engine) { c.FileFromFS("/robots.txt", app.fs) }) - //hack for index.html + // HTML pages (XML → XSLT) + router.GET("/", app.pageHome) + router.GET("/help", app.pageHelp) + router.GET("/login", app.pageLogin) + router.POST("/login", app.formLogin) + router.POST("/logout", app.formLogout) + router.GET("/logout", app.formLogout) + router.GET("/connect", app.pageConnect) + router.GET("/profile", app.pageProfile) + router.POST("/profile/theme", app.formProfileTheme) + router.POST("/profile/password", app.formProfilePassword) + router.POST("/profile/passkeys/:id/delete", app.formPasskeyDelete) + router.GET("/documents", app.pageDocuments) + router.GET("/documents/:docid", app.pagePDF) + router.POST("/documents/upload", app.formUploadDocument) + router.POST("/documents/folder", app.formCreateFolder) + router.POST("/documents/:docid/delete", app.formDeleteDocument) + router.GET("/integrations", app.pageIntegrations) + router.POST("/integrations", app.formCreateIntegration) + router.POST("/integrations/:intid/delete", app.formDeleteIntegration) + router.GET("/admin", app.pageAdmin) + router.POST("/admin/users", app.formCreateUser) + router.POST("/admin/users/:userid/delete", app.formDeleteUser) + router.GET("/admin/themes", app.pageThemeStudio) + router.POST("/admin/themes/save", app.formSaveTheme) + router.POST("/admin/themes/:id/publish", app.formPublishTheme) + router.POST("/admin/themes/:id/delete", app.formDeleteTheme) + router.GET("/screenshare", app.pageScreenShare) + router.NoRoute(func(c *gin.Context) { uri := c.Request.RequestURI log.Info(uri) if strings.HasPrefix(uri, "/api") || strings.HasPrefix(uri, "/ui/api") || c.Request.Method != http.MethodGet { - c.AbortWithStatus(http.StatusNotFound) return } - - c.FileFromFS(indexReplacement, app) + app.page404(c) }) r := router.Group("/ui/api") r.POST("register", app.register) r.POST("login", app.login) + r.GET("webauthn/status", app.webAuthnStatus) + r.POST("webauthn/login/begin", app.webAuthnLoginBegin) + r.POST("webauthn/login/finish", app.webAuthnLoginFinish) + r.GET("themes/assets/:name", app.getThemeAsset) + r.GET("themes/:id", app.getThemePublic) r.GET("logout", func(c *gin.Context) { c.SetCookie(cookieName, "/", -1, "", "", false, true) c.Status(http.StatusOK) @@ -55,27 +86,34 @@ func (app *ReactAppWrapper) RegisterRoutes(router *gin.Engine) { }) auth.GET("newcode", app.newCode) + auth.GET("code", app.codeStatus) - // passcode (PIN) reset approval auth.GET("passcode/resets", app.listPasscodeResets) auth.POST("passcode/resets/:uuid/approve", app.approvePasscodeReset) auth.DELETE("passcode/resets/:uuid", app.dismissPasscodeReset) - // auth.GET("profile", app.newCode) auth.POST("profile", app.changePassword) - // auth.POST("changeEmail", app.changePassword) + auth.GET("profile/theme", app.getProfileTheme) + auth.PUT("profile/theme", app.putProfileTheme) + + auth.POST("webauthn/register/begin", app.webAuthnRegisterBegin) + auth.POST("webauthn/register/finish", app.webAuthnRegisterFinish) + auth.GET("webauthn/credentials", app.webAuthnListCredentials) + auth.DELETE("webauthn/credentials/:id", app.webAuthnDeleteCredential) + + auth.GET("themes", app.listThemes) auth.GET("documents", app.listDocuments) auth.GET("documents/:docid", app.getDocument) + auth.GET("documents/:docid/epub/*path", app.getEpubPath) + auth.GET("documents/:docid/page/:pagenum", app.getDocumentPage) auth.POST("documents/upload", app.createDocument) - //move, rename auth.DELETE("documents/:docid", app.deleteDocument) auth.PUT("documents", app.updateDocument) auth.POST("folders", app.createFolder) auth.GET("documents/:docid/metadata", app.getDocumentMetadata) - // integrations auth.GET("integrations", app.listIntegrations) auth.POST("integrations", app.createIntegration) auth.GET("integrations/:intid", app.getIntegration) @@ -93,7 +131,6 @@ func (app *ReactAppWrapper) RegisterRoutes(router *gin.Engine) { ss.POST("room/:roomId/answer", app.screenshareSendAnswer) ss.DELETE("room/:roomId", app.screenshareDeleteRoom) - //admin admin := auth.Group("") admin.Use(app.adminMiddleware()) admin.GET("users/:userid", app.getUser) @@ -101,4 +138,8 @@ func (app *ReactAppWrapper) RegisterRoutes(router *gin.Engine) { admin.PUT("users", app.updateUser) admin.POST("users", app.createUser) admin.GET("users", app.getAppUsers) + admin.POST("themes", app.saveTheme) + admin.PUT("themes/:id", app.updateTheme) + admin.POST("themes/:id/publish", app.publishTheme) + admin.DELETE("themes/:id", app.deleteTheme) } diff --git a/internal/ui/static/app.css b/internal/ui/static/app.css new file mode 100644 index 00000000..e740d0f8 --- /dev/null +++ b/internal/ui/static/app.css @@ -0,0 +1,1873 @@ +/* rmfakecloud shell — theme vars come from #rm-shell-theme (:root) */ +:root { + --rm-color-scheme: dark; + --rm-bg-1: #212529; + --rm-bg-2: #0f0f0f; + --rm-fg-1: #f8f7f6; + --rm-fg-2: #e8e3d9; + --rm-fg-3: #e4dbaf; + --rm-action: #ee7b30; + --rm-on-action: #111111; + --rm-accept: #00e676; + --rm-reject: #ff1744; + --rm-connect-gauge-track: #3a3f44; + --rm-connect-gauge-fill: #ee7b30; + --rm-connect-gauge-text: #f8f7f6; + --rm-connect-prompt-bg: #212529; + --rm-connect-prompt-fg: #e8e3d9; + --rm-connect-prompt-border: #e8e3d9; + --rm-connect-code-color: #f8f7f6; + --rm-connect-font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; + --rm-connect-font-size: 2.75rem; + --rm-chrome-folder: #d4b483; + --rm-chrome-tab: #c4a574; + --rm-chrome-outline: #e8e3d9; + --rm-chrome-drawer: #4a4035; + --rm-chrome-label: #f8f7f6; + --rm-radius: 0.35rem; + --rm-space: 1rem; + --rm-font: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; + --rm-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; + --rm-max: 72rem; +} + +*, +*::before, +*::after { + box-sizing: border-box; +} + +html { + -webkit-text-size-adjust: 100%; + color-scheme: var(--rm-color-scheme, dark); +} + +body, +.shell, +.shell-content, +#rm-main-host, +#main, +.page-main { + color: var(--rm-fg-1); +} + +body { + margin: 0; + min-height: 100vh; + font-family: var(--rm-font); + font-size: 1rem; + line-height: 1.5; + color: var(--rm-fg-1); + background: + radial-gradient(120% 80% at 10% -10%, color-mix(in srgb, var(--rm-action) 14%, transparent), transparent 55%), + linear-gradient(180deg, var(--rm-bg-1), var(--rm-bg-2)); + background-attachment: fixed; +} + +img, +svg, +canvas { + max-width: 100%; + height: auto; +} + +a { + color: var(--rm-action); + text-decoration-thickness: 0.08em; + text-underline-offset: 0.15em; +} + +a:hover, +a:focus-visible { + color: color-mix(in srgb, var(--rm-action) 75%, var(--rm-fg-1)); +} + +:focus-visible { + outline: 2px solid var(--rm-action); + outline-offset: 2px; +} + +.visually-hidden { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border: 0; +} + +.skip-link { + position: absolute; + left: -999px; + top: 0; + z-index: 1000; + padding: 0.5rem 0.75rem; + background: var(--rm-bg-2); + color: var(--rm-fg-1); +} + +.skip-link:focus { + left: 0.5rem; + top: 0.5rem; +} + +.muted { + color: var(--rm-fg-2); +} + +/* ----- Layout ----- */ +.page-main { + width: min(100% - 2 * var(--rm-space), var(--rm-max)); + margin: 0 auto; + padding: 1.25rem var(--rm-space) 3rem; +} + +.panel { + padding: 1.25rem 0; +} + +.panel h1 { + margin: 0 0 1rem; + font-size: clamp(1.5rem, 2.5vw, 2rem); + font-weight: 650; + letter-spacing: -0.02em; + color: var(--rm-fg-1); +} + +.panel h2 { + margin: 1.75rem 0 0.75rem; + font-size: 1.15rem; + font-weight: 600; + color: var(--rm-fg-2); +} + +/* ----- Flash ----- */ +.flash { + width: min(100% - 2 * var(--rm-space), var(--rm-max)); + margin: 0.75rem auto 0; + padding: 0.75rem 1rem; + border-left: 4px solid var(--rm-fg-3); + background: color-mix(in srgb, var(--rm-bg-2) 70%, var(--rm-bg-1)); + color: var(--rm-fg-1); +} + +.flash-error { + border-left-color: var(--rm-reject); +} + +.flash-success { + border-left-color: var(--rm-accept); +} + +.flash-info { + border-left-color: var(--rm-action); +} + +/* ----- Icons (simple CSS shapes) ----- */ +.icon { + display: inline-block; + width: 1em; + height: 1em; + margin-right: 0.35em; + vertical-align: -0.1em; + background: currentColor; + mask-size: contain; + mask-repeat: no-repeat; + mask-position: center; + -webkit-mask-size: contain; + -webkit-mask-repeat: no-repeat; + -webkit-mask-position: center; +} + +.icon-lg { + width: 2.5rem; + height: 2.5rem; + margin-right: 0; +} + +.icon-cloud { + mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='black' d='M19.35 10.04A7.49 7.49 0 0 0 12 4C9.11 4 6.6 5.64 5.35 8.04A5.994 5.994 0 0 0 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96z'/%3E%3C/svg%3E"); + -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='black' d='M19.35 10.04A7.49 7.49 0 0 0 12 4C9.11 4 6.6 5.64 5.35 8.04A5.994 5.994 0 0 0 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96z'/%3E%3C/svg%3E"); +} + +.icon-folder { + mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='black' d='M10 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2h-8l-2-2z'/%3E%3C/svg%3E"); + -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='black' d='M10 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2h-8l-2-2z'/%3E%3C/svg%3E"); +} + +.icon-file { + mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='black' d='M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8l-6-6zm1 7V3.5L19.5 9H15z'/%3E%3C/svg%3E"); + -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='black' d='M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8l-6-6zm1 7V3.5L19.5 9H15z'/%3E%3C/svg%3E"); +} + +.icon-person { + mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='black' d='M12 12c2.7 0 4.8-2.1 4.8-4.8S14.7 2.4 12 2.4 7.2 4.5 7.2 7.2 9.3 12 12 12zm0 2.4c-3.2 0-9.6 1.6-9.6 4.8v2.4h19.2v-2.4c0-3.2-6.4-4.8-9.6-4.8z'/%3E%3C/svg%3E"); + -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='black' d='M12 12c2.7 0 4.8-2.1 4.8-4.8S14.7 2.4 12 2.4 7.2 4.5 7.2 7.2 9.3 12 12 12zm0 2.4c-3.2 0-9.6 1.6-9.6 4.8v2.4h19.2v-2.4c0-3.2-6.4-4.8-9.6-4.8z'/%3E%3C/svg%3E"); +} + +.icon-puzzle, +.icon-link, +.icon-display, +.icon-gear, +.icon-book { + mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Ccircle cx='12' cy='12' r='8' fill='black'/%3E%3C/svg%3E"); + -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Ccircle cx='12' cy='12' r='8' fill='black'/%3E%3C/svg%3E"); +} + +/* ----- Nav (fallback header; JS shells hide .site-header) ----- */ +.site-header { + position: sticky; + top: 0; + z-index: 50; + backdrop-filter: blur(8px); + background: color-mix(in srgb, var(--rm-bg-1) 88%, transparent); + border-bottom: 1px solid color-mix(in srgb, var(--rm-fg-2) 22%, transparent); +} + +.nav-bar { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 0.5rem 1rem; + width: min(100% - 2 * var(--rm-space), var(--rm-max)); + margin: 0 auto; + padding: 0.65rem var(--rm-space); +} + +.nav-brand { + display: inline-flex; + align-items: center; + gap: 0.35rem; + font-weight: 700; + color: var(--rm-fg-1); + text-decoration: none; + margin-right: 0.5rem; +} + +.nav-brand:hover { + color: var(--rm-fg-3); +} + +.nav-links, +.nav-tabs { + display: flex; + flex-wrap: wrap; + align-items: flex-end; + gap: 0.35rem; + flex: 1 1 auto; + list-style: none; + margin: 0; + padding: 0; +} + +.nav-links .nav-link { + display: inline-flex; + align-items: center; + padding: 0.4rem 0.65rem; + color: var(--rm-fg-2); + text-decoration: none; + border-radius: var(--rm-radius); +} + +.nav-links .nav-link:hover, +.nav-links .nav-link.is-active { + color: var(--rm-fg-1); + background: color-mix(in srgb, var(--rm-fg-2) 12%, transparent); +} + +.nav-user-slot { + margin-left: auto; +} + +.user-menu { + position: relative; +} + +.shell-user-slot { + position: relative; + z-index: 70; +} + +.user-menu > summary, +.user-menu-toggle { + list-style: none; + cursor: pointer; + display: inline-flex; + align-items: center; + gap: 0.35rem; + padding: 0.35rem 0.6rem; + color: inherit; + border-radius: var(--rm-radius); + border: 1px solid color-mix(in srgb, currentColor 22%, transparent); + background: transparent; + font: inherit; + max-width: 16rem; +} + +.user-menu-name { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.user-menu > summary::-webkit-details-marker { + display: none; +} + +.user-menu-list { + position: absolute; + right: 0; + top: calc(100% + 0.25rem); + min-width: 11rem; + margin: 0; + padding: 0.35rem; + list-style: none; + background: var(--rm-bg-2); + border: 1px solid color-mix(in srgb, var(--rm-fg-2) 35%, transparent); + border-radius: var(--rm-radius); + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35); + z-index: 80; +} + +.user-menu-list a, +.user-menu-list .btn-link { + display: block; + width: 100%; + text-align: left; + padding: 0.4rem 0.55rem; + color: var(--rm-fg-1); + text-decoration: none; + background: transparent; + border: 0; + border-radius: 0.25rem; + font: inherit; + cursor: pointer; +} + +.user-menu-list a:hover, +.user-menu-list .btn-link:hover { + background: color-mix(in srgb, var(--rm-fg-2) 14%, transparent); +} + +/* ----- Forms / buttons / tables ----- */ +.field { + display: flex; + flex-direction: column; + gap: 0.35rem; + margin-bottom: 0.9rem; +} + +.field-inline { + flex-direction: row; + align-items: center; + flex-wrap: wrap; + gap: 0.5rem 0.75rem; +} + +.field-checkbox { + flex-direction: row; + align-items: center; + gap: 0.5rem; +} + +label, +legend { + color: var(--rm-fg-2); + font-size: 0.92rem; + font-weight: 550; +} + +input[type="text"], +input[type="email"], +input[type="password"], +input[type="file"], +input[type="color"], +select, +textarea { + font: inherit; + color: var(--rm-fg-1); + background: color-mix(in srgb, var(--rm-bg-2) 85%, #000); + border: 1px solid color-mix(in srgb, var(--rm-fg-2) 35%, transparent); + border-radius: var(--rm-radius); + padding: 0.5rem 0.65rem; + max-width: 100%; +} + +input[type="color"] { + width: 3rem; + height: 2.25rem; + padding: 0.15rem; +} + +textarea { + width: 100%; + font-family: var(--rm-mono); + font-size: 0.85rem; + line-height: 1.4; + resize: vertical; +} + +.form-actions { + display: flex; + flex-wrap: wrap; + gap: 0.5rem; + margin-top: 0.75rem; +} + +.inline-form { + display: inline; +} + +.btn { + display: inline-flex; + align-items: center; + justify-content: center; + gap: 0.35rem; + font: inherit; + font-weight: 600; + line-height: 1.2; + border-radius: var(--rm-radius); + border: 1px solid transparent; + padding: 0.5rem 0.9rem; + cursor: pointer; + text-decoration: none; + color: var(--rm-fg-1); + background: color-mix(in srgb, var(--rm-fg-2) 16%, transparent); +} + +.btn:hover { + filter: brightness(1.08); +} + +.btn-primary { + background: var(--rm-action); + color: var(--rm-on-action, #111111); + border-color: color-mix(in srgb, var(--rm-action) 60%, var(--rm-fg-1)); +} + +.btn-secondary { + background: color-mix(in srgb, var(--rm-bg-2) 70%, var(--rm-fg-2)); + border-color: color-mix(in srgb, var(--rm-fg-2) 30%, transparent); +} + +.btn-danger { + background: color-mix(in srgb, var(--rm-reject) 85%, #000); + border-color: color-mix(in srgb, var(--rm-reject) 55%, #000); +} + +.btn-sm { + padding: 0.3rem 0.55rem; + font-size: 0.85rem; +} + +.btn-link { + background: transparent; + color: var(--rm-action); + padding: 0.35rem 0.25rem; +} + +.data-table { + width: 100%; + border-collapse: collapse; + margin: 0.75rem 0 1.25rem; + font-size: 0.95rem; +} + +.data-table th, +.data-table td { + text-align: left; + padding: 0.55rem 0.65rem; + border-bottom: 1px solid color-mix(in srgb, var(--rm-fg-2) 22%, transparent); + vertical-align: middle; +} + +.data-table th { + color: var(--rm-fg-3); + font-weight: 600; + font-size: 0.82rem; + text-transform: uppercase; + letter-spacing: 0.04em; +} + +.data-table .actions { + display: flex; + flex-wrap: wrap; + gap: 0.35rem; + align-items: center; +} + +.color-overrides { + border: 1px solid color-mix(in srgb, var(--rm-fg-2) 25%, transparent); + border-radius: var(--rm-radius); + padding: 0.75rem 1rem; + margin: 0.75rem 0; +} + +/* ----- Login ----- */ +.login-panel { + max-width: 24rem; + margin: 2rem auto; +} + +.login-brand { + display: flex; + flex-direction: column; + align-items: center; + gap: 0.5rem; + margin-bottom: 1.5rem; + text-align: center; +} + +.login-brand h1 { + margin: 0; +} + +.login-register { + margin-top: 1.25rem; + text-align: center; +} + +/* ----- Connect ----- */ +.connect-panel { + display: flex; + justify-content: center; +} + +.connect-stack { + display: flex; + flex-direction: column; + align-items: center; + gap: 1.5rem; + width: min(100%, 28rem); + text-align: center; +} + +.connect-main { + display: flex; + flex-direction: column; + align-items: center; + gap: 1rem; + width: 100%; +} + +.connect-prompt { + margin: 0; + color: var(--rm-connect-prompt-fg); + max-width: 22rem; +} + +.connect-prompt.prompt-boxed, +.connect-prompt.prompt-banner, +.connect-prompt.prompt-pill { + background: var(--rm-connect-prompt-bg); + border: 1px solid var(--rm-connect-prompt-border); + padding: 0.65rem 0.9rem; +} + +.connect-prompt.prompt-pill { + border-radius: 999px; +} + +.connect-prompt.prompt-boxed { + border-radius: var(--rm-radius); +} + +.connect-code { + font-family: var(--rm-connect-font-family); + font-size: var(--rm-connect-font-size); + font-weight: 650; + letter-spacing: 0.12em; + color: var(--rm-connect-code-color); + line-height: 1.1; + word-break: break-all; +} + +.connect-status { + margin: 0; + max-width: 22rem; + color: var(--rm-fg-2); + font-size: 0.95rem; +} + +.connect-status.is-paired { + color: var(--rm-accept); +} + +.connect-gauge { + color: var(--rm-connect-gauge-text); +} + +.connect-gauge-track { + stroke: var(--rm-connect-gauge-track); +} + +.connect-gauge-fill { + stroke: var(--rm-connect-gauge-fill); +} + +.connect-gauge-text { + fill: var(--rm-connect-gauge-text); + font-size: 0.9rem; + font-family: var(--rm-font); +} + +.connect-gauge-bar-track { + width: min(100%, 16rem); + height: 0.65rem; + border-radius: 999px; + background: var(--rm-connect-gauge-track); + overflow: hidden; +} + +.connect-gauge-bar-fill { + height: 100%; + background: var(--rm-connect-gauge-fill); + border-radius: inherit; + transition: width 0.2s linear; +} + +.connect-gauge-label { + margin-top: 0.5rem; + color: var(--rm-connect-gauge-text); + font-variant-numeric: tabular-nums; +} + +/* ----- Documents (reMarkable My Files) ----- */ +.page-documents .page-main, +.page-documents .panel { + width: min(100% - 1.5rem, 68rem); + max-width: none; +} +.rm-files { + padding-bottom: 5rem; + font-family: system-ui, -apple-system, "Segoe UI", sans-serif; +} +.rm-files-header { + display: flex; + align-items: flex-end; + justify-content: space-between; + gap: 1rem; + margin-bottom: 0.75rem; +} +.rm-files-title-row h1 { + margin: 0; + font-size: clamp(1.75rem, 3vw, 2.25rem); + font-weight: 700; + letter-spacing: -0.03em; +} +.rm-files-crumb { + margin: 0 0 0.35rem; + font-size: 0.85rem; + color: var(--rm-fg-2); +} +.rm-files-crumb a { + color: inherit; +} +.rm-files-sort label { + position: absolute; + width: 1px; + height: 1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); +} +.rm-files-sort select { + appearance: none; + border: 0; + background: transparent; + color: var(--rm-fg-2); + font: inherit; + font-size: 0.95rem; + padding: 0.35rem 1.4rem 0.35rem 0; + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath fill='%23666' d='M6 8 0 0h12z'/%3E%3C/svg%3E"); + background-repeat: no-repeat; + background-position: right 0.2rem center; + background-size: 0.55rem; + cursor: pointer; +} +.rm-search-bar { + margin: 0 0 1rem; +} +.rm-search-bar input { + width: 100%; + max-width: 24rem; +} +.rm-folder-grid, +.rm-file-grid { + list-style: none; + margin: 0; + padding: 0; +} +.rm-folder-grid { + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + gap: 0.45rem 1.1rem; + margin: 0.15rem 0 1.35rem; +} +.rm-folder-item a { + display: flex; + align-items: center; + gap: 0.4rem; + min-height: 2rem; + color: var(--rm-fg-1); + text-decoration: none; + font-size: 0.92rem; +} +.rm-folder-item a:hover .rm-folder-name { + text-decoration: underline; +} +.rm-folder-icon { + width: 1.15rem; + height: 1rem; + flex: 0 0 auto; + background: currentColor; + mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 20'%3E%3Cpath fill='black' d='M2 4h8l2 2h10v12H2z'/%3E%3C/svg%3E") center / contain no-repeat; + -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 20'%3E%3Cpath fill='black' d='M2 4h8l2 2h10v12H2z'/%3E%3C/svg%3E") center / contain no-repeat; +} +.rm-folder-name { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} +.rm-star { + color: var(--rm-fg-2); + font-size: 0.75rem; +} +.rm-file-grid { + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + gap: 1.5rem 1.15rem; +} +.rm-file-link { + display: flex; + flex-direction: column; + gap: 0.45rem; + color: var(--rm-fg-1); + text-decoration: none; +} +.rm-page-frame { + position: relative; + display: block; + aspect-ratio: 3 / 4; + width: 100%; + overflow: hidden; + isolation: isolate; + border: 1px solid #c5bfb4; + background: #f7f4ef; + box-shadow: 0 1px 0 color-mix(in srgb, var(--rm-fg-1) 8%, transparent); +} +.rm-page-ear { + position: absolute; + top: 0; + right: 0; + width: 1.15rem; + height: 1.15rem; + background: + linear-gradient(225deg, transparent 49%, #d8d2c6 50%), + linear-gradient(225deg, #ece8df 50%, transparent 51%); + pointer-events: none; + z-index: 3; +} +.rm-page-frame.is-notebook { + background-color: #f3efe4; + background-image: + linear-gradient(to right, transparent 12%, #d9a39a 12% 12.45%, transparent 12.45%), + repeating-linear-gradient( + to bottom, + transparent 0 1.28rem, + #d9d2c4 1.28rem 1.34rem + ); + background-position: 0 0, 0 0.7rem; + border-color: #c4bbaa; +} +.rm-page-frame.is-pdf { + background: #fff; + border-color: #9a9a9a; +} +.rm-page-frame.is-pdf::before { + content: "PDF"; + position: absolute; + top: 0.4rem; + left: 0.4rem; + z-index: 3; + font-size: 0.58rem; + font-weight: 700; + letter-spacing: 0.06em; + color: #fff; + background: #c0392b; + padding: 0.12rem 0.28rem; + border-radius: 0.12rem; +} +.rm-page-frame.is-pdf .rm-page-placeholder { + background-image: repeating-linear-gradient( + to bottom, + transparent 0 0.42rem, + #ececec 0.42rem 0.5rem + ); + background-size: 76% 62%; + background-repeat: no-repeat; + background-position: 14% 28%; +} +.rm-page-frame.is-epub { + background: + linear-gradient(90deg, #2c2824 0 0.55rem, transparent 0.55rem), + linear-gradient(180deg, #f6f0e2, #e4d8c2); + border: 1px solid #8d846f; + border-left-width: 0; + box-shadow: inset 0.7rem 0 0 #2c2824, inset 0.82rem 0 0 #5a5348; +} +.rm-page-frame.is-epub::before { + content: "EPUB"; + position: absolute; + top: 0.45rem; + right: 0.4rem; + z-index: 3; + font-size: 0.52rem; + font-weight: 700; + letter-spacing: 0.08em; + color: #f6f0e2; + background: #3f3b36; + padding: 0.12rem 0.28rem; +} +.rm-page-frame.is-epub .rm-page-ear { + display: none; +} +.rm-page-frame.has-preview { + background-image: none; +} +.rm-page-frame.is-epub.has-preview { + background-image: linear-gradient(90deg, #2c2824 0 0.55rem, transparent 0.55rem); + background-color: #fff; +} +.rm-page-frame.is-pdf.has-preview, +.rm-page-frame.is-notebook.has-preview { + background-color: #fff; +} +.rm-thumb-canvas, +.rm-page-placeholder { + display: block; + width: 100%; + height: 100%; + max-width: none; +} +.rm-page-frame .rm-thumb-canvas, +.rm-page-frame .rm-thumb-img { + position: absolute; + inset: 0; + width: 100%; + height: 100%; + max-width: none; + object-fit: cover; + object-position: top center; +} +.rm-page-frame.is-epub .rm-thumb-img { + left: 0.85rem; + width: calc(100% - 0.85rem); +} +.rm-file-meta { + display: flex; + flex-direction: column; + gap: 0.1rem; + min-width: 0; +} +.rm-file-name { + font-weight: 650; + font-size: 0.95rem; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} +.rm-file-sub { + font-size: 0.8rem; + color: var(--rm-fg-2); +} +.rm-files-empty { + color: var(--rm-fg-2); +} +.rm-dock { + position: fixed; + left: 50%; + bottom: calc(1rem + env(safe-area-inset-bottom, 0px)); + transform: translateX(-50%); + z-index: 30; + display: flex; + align-items: center; + gap: 0; + padding: 0.2rem; + background: color-mix(in srgb, var(--rm-bg-1) 88%, transparent); + border: 1px solid color-mix(in srgb, var(--rm-fg-2) 35%, transparent); + border-radius: 999px; + box-shadow: 0 6px 20px rgba(0, 0, 0, 0.18); + backdrop-filter: blur(8px); +} +.rm-dock button { + width: 2.75rem; + height: 2.5rem; + border: 0; + background: transparent; + color: var(--rm-fg-1); + cursor: pointer; + display: inline-flex; + align-items: center; + justify-content: center; +} +.rm-dock button + button { + border-left: 1px solid color-mix(in srgb, var(--rm-fg-2) 30%, transparent); +} +.rm-dock-icon { + width: 1.2rem; + height: 1.2rem; + background: currentColor; +} +.rm-dock-search { + mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Ccircle cx='10' cy='10' r='6' fill='none' stroke='black' stroke-width='2'/%3E%3Cpath stroke='black' stroke-width='2' d='M15 15l6 6'/%3E%3C/svg%3E") center / contain no-repeat; + -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Ccircle cx='10' cy='10' r='6' fill='none' stroke='black' stroke-width='2'/%3E%3Cpath stroke='black' stroke-width='2' d='M15 15l6 6'/%3E%3C/svg%3E") center / contain no-repeat; +} +.rm-dock-plus { + mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='black' d='M11 5h2v14h-2z'/%3E%3Cpath fill='black' d='M5 11h14v2H5z'/%3E%3C/svg%3E") center / contain no-repeat; + -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='black' d='M11 5h2v14h-2z'/%3E%3Cpath fill='black' d='M5 11h14v2H5z'/%3E%3C/svg%3E") center / contain no-repeat; +} +.rm-dock-folder { + mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='black' d='M2 6h8l2 2h10v12H2z'/%3E%3Cpath fill='white' d='M14 11h2v2h2v2h-2v2h-2v-2h-2v-2h2z'/%3E%3C/svg%3E") center / contain no-repeat; + -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='black' d='M2 6h8l2 2h10v12H2z'/%3E%3Cpath fill='white' d='M14 11h2v2h2v2h-2v2h-2v-2h-2v-2h2z'/%3E%3C/svg%3E") center / contain no-repeat; +} +.rm-folder-dialog { + border: 1px solid color-mix(in srgb, var(--rm-fg-2) 35%, transparent); + border-radius: var(--rm-radius); + background: var(--rm-bg-1); + color: var(--rm-fg-1); + padding: 1rem 1.15rem; + max-width: 22rem; +} +.rm-folder-dialog::backdrop { + background: rgba(0, 0, 0, 0.35); +} +.rm-folder-item.is-hidden, +.rm-file-item.is-hidden { + display: none; +} +@media (max-width: 900px) { + .rm-folder-grid, + .rm-file-grid { + grid-template-columns: repeat(3, minmax(0, 1fr)); + } +} +@media (max-width: 640px) { + .rm-folder-grid, + .rm-file-grid { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } +} + +/* ----- Help ----- */ +.help-section { + margin-bottom: 1.5rem; + padding-bottom: 1rem; + border-bottom: 1px solid color-mix(in srgb, var(--rm-fg-2) 18%, transparent); +} + +.help-intro { + color: var(--rm-fg-2); +} + +.help-links { + margin: 0.5rem 0 0; + padding-left: 1.15rem; +} + +.help-links li { + margin: 0.35rem 0; +} + +.help-note { + color: var(--rm-fg-2); + font-size: 0.92rem; +} + +/* ----- Screenshare / PDF ----- */ +.screenshare-layout { + display: flex; + flex-direction: column; + align-items: center; + gap: 0.75rem; +} + +#screenshare-canvas, +#pdf-canvas { + width: min(100%, 32rem); + background: #111; + border: 1px solid color-mix(in srgb, var(--rm-fg-2) 25%, transparent); + border-radius: var(--rm-radius); +} + +.pdf-viewer { + display: flex; + flex-direction: column; + align-items: center; + gap: 0.75rem; +} + +.pdf-toolbar { + display: flex; + align-items: center; + gap: 0.75rem; +} + +/* ----- EPUB website ----- */ +.page-epub .page-main { + width: 100%; + max-width: none; + margin: 0; + padding: 0 0 1rem; + display: flex; + flex-direction: column; + min-height: calc(100vh - 8rem); +} +.epub-panel { + flex: 1; + display: flex; + flex-direction: column; + min-height: 0; + padding: 0; +} +.epub-header { + padding: 1rem var(--rm-space) 0.5rem; +} +.epub-header h1 { + margin-bottom: 0.35rem; +} +.epub-header p { + margin: 0 0 0.75rem; +} +.epub-layout { + flex: 1; + display: flex; + min-height: 24rem; + min-width: 0; + border-top: 1px solid color-mix(in srgb, var(--rm-fg-2) 22%, transparent); + background: #fff; + color: #111; +} +.epub-toc { + width: min(18rem, 36vw); + overflow: auto; + border-right: 1px solid #d8d5d0; + background: #f6f4f0; + color: #111; +} +.epub-toc h2 { + margin: 0; + padding: 0.75rem 1rem; + font-size: 0.75rem; + font-weight: 700; + letter-spacing: 0.06em; + text-transform: uppercase; + border-bottom: 1px solid #d8d5d0; + color: #333; +} +.epub-toc ol { + list-style: none; + margin: 0; + padding: 0.35rem 0; +} +.epub-toc a { + display: block; + padding: 0.55rem 1rem; + color: #111; + text-decoration: none; + font-size: 0.88rem; +} +.epub-toc a:hover, +.epub-toc a:focus-visible { + background: #ece8e0; +} +.epub-toc a[aria-current="page"] { + background: #e2ddd4; + font-weight: 650; +} +.epub-stage { + flex: 1; + min-width: 0; + min-height: 0; + display: flex; + flex-direction: column; + background: #fff; +} +.epub-frame { + flex: 1; + width: 100%; + min-height: 70vh; + border: 0; + background: #fff; +} +.epub-stage > p { + margin: 1.5rem; + color: #444; +} + +@media (max-width: 720px) { + .epub-layout { + flex-direction: column; + } + .epub-toc { + width: 100%; + max-height: 10rem; + border-right: 0; + border-bottom: 1px solid #d8d5d0; + } + .epub-frame { + min-height: 60vh; + } +} + +/* ----- Theme studio ----- */ +.theme-editor textarea { + min-height: 20rem; +} + +/* ----- Error ----- */ +.error-panel { + text-align: center; + padding-top: 3rem; +} + +.error-panel h1 { + font-size: 3rem; + color: var(--rm-fg-3); +} + +/* ----- Mobile ----- */ +@media (max-width: 720px) { + .nav-bar, + .nav-drawer { + align-items: stretch; + } + + .nav-user-slot { + margin-left: 0; + width: 100%; + } + + .user-menu-list { + left: 0; + right: auto; + } + + .connect-code { + font-size: clamp(1.5rem, 8vw, 2.25rem); + } + + .data-table { + display: block; + overflow-x: auto; + } +} + +@media (prefers-reduced-motion: reduce) { + *, + *::before, + *::after { + animation: none !important; + transition: none !important; + } +} + +/* ===== Full-screen chrome shells ===== */ +html, body { + height: 100%; + margin: 0; +} +#rm-shell-root { + height: 100%; + min-height: 100%; +} +#rm-main-host, +.shell-content { + flex: 1 1 auto; + min-height: 0; + overflow: auto; +} +.shell { + display: flex; + height: 100%; + min-height: 100vh; + background: var(--rm-bg-1); + color: var(--rm-fg-1); +} +.shell-brand { + font-weight: 700; + text-decoration: none; + color: inherit; +} +.shell-nav-link { + display: inline-flex; + align-items: center; + gap: 0.4rem; + text-decoration: none; + color: inherit; +} +.shell-nav-list, +.shell-rm-nav-list, +.shell-gd-rail-list, +.shell-gd-drawer-list, +.shell-ic-nav-list, +.shell-ic-drawer-list, +.shell-os-fav-list { + list-style: none; + margin: 0; + padding: 0; +} +.shell-drawer-scrim { + position: fixed; + inset: 0; + background: rgba(0, 0, 0, 0.45); + z-index: 45; +} +.shell-hamburger { + min-width: 2.75rem; + min-height: 2.75rem; + font-size: 1.35rem; + border: 1px solid color-mix(in srgb, currentColor 30%, transparent); + border-radius: 0.35rem; + background: transparent; + color: inherit; + cursor: pointer; +} + +/* Contrast: page text always uses theme fg on theme bg (no light canvas + light text). */ +.shell-content, +#rm-main-host, +.shell #main, +.shell .page-main { + color: var(--rm-fg-1); + background: var(--rm-bg-1); +} +.shell .panel h1, +.shell .panel h2, +.shell .data-table, +.shell th, +.shell td, +.shell p, +.shell li, +.shell .field, +.shell .user-menu-name { + color: var(--rm-fg-1); +} +.shell .panel h2, +.shell .muted, +.shell label, +.shell legend, +.shell .rm-pager-status { + color: var(--rm-fg-2); +} +.shell input[type="text"], +.shell input[type="email"], +.shell input[type="password"], +.shell input[type="file"], +.shell select, +.shell textarea { + color: var(--rm-fg-1); + background: var(--rm-bg-2); + border-color: color-mix(in srgb, var(--rm-fg-2) 45%, transparent); +} +.shell .user-menu-list { + background: var(--rm-bg-2); + color: var(--rm-fg-1); + border-color: color-mix(in srgb, var(--rm-fg-2) 40%, transparent); +} +.shell .user-menu-list a, +.shell .user-menu-list .btn-link, +.shell .user-menu-toggle { + color: var(--rm-fg-1); +} + +/* ----- remarkable ----- */ +.shell-remarkable { + flex-direction: column; + background: var(--rm-bg-1); + color: var(--rm-fg-1); + font-family: "Iowan Old Style", "Palatino Linotype", Palatino, Georgia, serif; +} +.shell-remarkable .shell-rm-bar, +.shell-remarkable .shell-nav-label, +.shell-remarkable .user-menu, +.shell-remarkable .user-menu-toggle { + font-family: system-ui, -apple-system, "Segoe UI", sans-serif; +} +.shell-rm-bar { + display: flex; + align-items: center; + gap: 0.75rem; + min-height: 3.25rem; + padding: 0.35rem 0.85rem; + border-bottom: 1px solid color-mix(in srgb, var(--rm-fg-2) 28%, transparent); + background: var(--rm-bg-2); + color: var(--rm-fg-1); + z-index: 40; + overflow: visible; +} +.shell-rm-top-list { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 0.15rem 0.25rem; + list-style: none; + margin: 0; + padding: 0; + flex: 1 1 auto; +} +.shell-rm-top-list .shell-nav-link { + min-height: 2.5rem; + padding: 0.35rem 0.65rem; + border-radius: 0.35rem; + color: var(--rm-fg-1); + font-size: 0.95rem; +} +.shell-rm-top-list .shell-nav-link.is-active, +.shell-rm-top-list .shell-nav-link:hover { + background: color-mix(in srgb, var(--rm-action) 22%, transparent); + color: var(--rm-action); +} +.shell-rm-brand { + font-family: Georgia, "Iowan Old Style", serif; + font-weight: 700; + letter-spacing: 0.02em; + color: var(--rm-fg-1); +} +.shell-rm-bar .shell-user-slot { + margin-left: auto; +} +.shell-rm-hamburger { + border-color: color-mix(in srgb, var(--rm-fg-1) 35%, transparent); + color: var(--rm-fg-1); +} +.shell-rm-drawer { + position: fixed; + top: 0; + left: 0; + bottom: 0; + width: min(18rem, 88vw); + background: var(--rm-bg-2); + color: var(--rm-fg-1); + border-right: 1px solid color-mix(in srgb, var(--rm-fg-2) 30%, transparent); + transform: translateX(-105%); + transition: transform 0.2s ease; + z-index: 50; + padding: 1.25rem 0.85rem; + overflow: auto; + box-shadow: 4px 0 24px rgba(0, 0, 0, 0.35); + pointer-events: none; +} +.shell-rm-drawer.is-open { + transform: translateX(0); + pointer-events: auto; +} +.shell-rm-drawer-title { + font-family: Georgia, serif; + font-size: 1.35rem; + margin: 0 0 1rem; + color: var(--rm-fg-1); +} +.shell-rm-nav-list .shell-nav-link { + min-height: 2.75rem; + padding: 0.65rem 0.75rem; + width: 100%; + border-radius: 0.35rem; + color: var(--rm-fg-1); + font-size: 1rem; +} +.shell-rm-nav-list .shell-nav-link.is-active, +.shell-rm-nav-list .shell-nav-link:hover { + background: color-mix(in srgb, var(--rm-action) 22%, transparent); + color: var(--rm-action); +} +.shell-rm-content { + padding: 1rem 1.25rem 1.5rem; + background: var(--rm-bg-1); + color: var(--rm-fg-1); +} + +/* ----- googledocs ----- */ +.shell-googledocs { + flex-direction: column; + background: var(--rm-bg-2); + color: var(--rm-fg-1); + font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; +} +.shell-gd-appbar { + display: flex; + align-items: center; + gap: 0.75rem 1rem; + min-height: 4rem; + padding: 0.5rem 1rem; + background: var(--rm-bg-1); + color: var(--rm-fg-1); + border-bottom: 1px solid color-mix(in srgb, var(--rm-fg-2) 28%, transparent); + z-index: 40; +} +.shell-gd-mark { + color: var(--rm-fg-1); + font-size: 1.15rem; + font-weight: 500; +} +.shell-gd-title { + font-size: 1.125rem; + font-weight: 400; + color: var(--rm-fg-1); + flex: 1; + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} +.shell-gd-actions { + margin-left: auto; +} +.shell-gd-body { + display: flex; + flex: 1; + min-height: 0; +} +.shell-gd-rail { + width: 14rem; + flex: 0 0 14rem; + padding: 0.75rem 0.5rem; + background: var(--rm-bg-2); + color: var(--rm-fg-1); + border-right: 1px solid color-mix(in srgb, var(--rm-fg-2) 28%, transparent); + overflow: auto; +} +.shell-gd-rail-list .shell-nav-link { + width: 100%; + padding: 0.55rem 0.85rem; + border-radius: 0 1.5rem 1.5rem 0; + color: var(--rm-fg-1); + font-size: 0.9rem; +} +.shell-gd-rail-list .shell-nav-link.is-active, +.shell-gd-rail-list .shell-nav-link:hover { + background: color-mix(in srgb, var(--rm-action) 22%, transparent); + color: var(--rm-action); +} +.shell-gd-content { + padding: 1.25rem 1.5rem; + background: var(--rm-bg-1); + color: var(--rm-fg-1); + margin: 0.75rem 1rem 1rem 0; + border-radius: 0.5rem; + box-shadow: 0 1px 2px color-mix(in srgb, var(--rm-fg-1) 12%, transparent); +} +.shell-googledocs.is-mobile .shell-gd-content { + margin: 0; + border-radius: 0; + box-shadow: none; + padding: 0.85rem; + padding-bottom: calc(0.85rem + env(safe-area-inset-bottom, 0px)); +} +.shell-gd-drawer { + position: fixed; + top: 0; + left: 0; + bottom: 0; + width: min(18rem, 86vw); + background: var(--rm-bg-1); + color: var(--rm-fg-1); + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35); + transform: translateX(-105%); + transition: transform 0.2s ease; + z-index: 50; + padding: 1rem 0.5rem; + overflow: auto; + pointer-events: none; +} +.shell-gd-drawer.is-open { + transform: translateX(0); + pointer-events: auto; +} +.shell-gd-drawer-brand { + display: block; + padding: 0.75rem 1rem 1rem; + color: var(--rm-fg-1); +} +.shell-gd-drawer-list .shell-nav-link { + width: 100%; + min-height: 3rem; + padding: 0.75rem 1rem; + border-radius: 0 1.5rem 1.5rem 0; + font-size: 1rem; + color: var(--rm-fg-1); +} +.shell-gd-drawer-list .shell-nav-link.is-active { + background: color-mix(in srgb, var(--rm-action) 22%, transparent); + color: var(--rm-action); +} + +/* ----- icloud ----- */ +.shell-icloud { + flex-direction: row; + background: var(--rm-bg-2); + color: var(--rm-fg-1); + font-family: system-ui, -apple-system, "Segoe UI", sans-serif; +} +.shell-ic-sidebar { + width: 15rem; + flex: 0 0 15rem; + display: flex; + flex-direction: column; + gap: 0.75rem; + padding: 1.25rem 0.85rem; + background: color-mix(in srgb, var(--rm-bg-1) 85%, transparent); + border-right: 1px solid color-mix(in srgb, var(--rm-fg-2) 28%, transparent); + color: var(--rm-fg-1); +} +.shell-ic-brand { + font-weight: 600; + font-size: 1.05rem; + color: var(--rm-fg-1); + padding: 0.35rem 0.65rem; +} +.shell-ic-nav-list .shell-nav-link { + width: 100%; + padding: 0.55rem 0.75rem; + border-radius: 0.65rem; + color: var(--rm-fg-1); + font-size: 0.95rem; +} +.shell-ic-nav-list .shell-nav-link.is-active, +.shell-ic-nav-list .shell-nav-link:hover { + background: color-mix(in srgb, var(--rm-action) 22%, transparent); + color: var(--rm-action); +} +.shell-ic-account { + margin-top: auto; +} +.shell-ic-main { + flex: 1; + display: flex; + flex-direction: column; + min-width: 0; + padding: 1.25rem 1.5rem 1.5rem; +} +.shell-ic-heading { + margin-bottom: 0.85rem; +} +.shell-ic-page-title { + margin: 0; + font-size: 1.75rem; + font-weight: 700; + letter-spacing: -0.02em; + color: var(--rm-fg-1); +} +.shell-ic-canvas { + flex: 1; + min-height: 0; + display: flex; +} +.shell-ic-panel { + flex: 1; + background: var(--rm-bg-1); + color: var(--rm-fg-1); + border-radius: 1rem; + box-shadow: 0 8px 28px rgba(0, 0, 0, 0.18); + padding: 1.25rem; +} +.shell-icloud.is-mobile { + flex-direction: column; +} +.shell-ic-top { + display: flex; + align-items: center; + gap: 0.65rem; + min-height: 3.25rem; + padding: 0.5rem 0.75rem; + padding-top: calc(0.5rem + env(safe-area-inset-top, 0px)); + background: var(--rm-bg-1); + color: var(--rm-fg-1); + border-bottom: 1px solid color-mix(in srgb, var(--rm-fg-2) 28%, transparent); + z-index: 40; +} +.shell-ic-top .shell-ic-page-title { + font-size: 1.15rem; + flex: 1; +} +.shell-ic-drawer { + position: fixed; + top: 0; + left: 0; + bottom: 0; + width: min(18rem, 88vw); + background: var(--rm-bg-1); + color: var(--rm-fg-1); + transform: translateX(-105%); + transition: transform 0.22s ease; + z-index: 50; + padding: 1.25rem 0.85rem; + padding-top: calc(1.25rem + env(safe-area-inset-top, 0px)); + overflow: auto; + pointer-events: none; +} +.shell-ic-drawer.is-open { + transform: translateX(0); + pointer-events: auto; +} +.shell-ic-drawer-list .shell-nav-link { + width: 100%; + min-height: 2.75rem; + padding: 0.75rem 0.85rem; + border-radius: 0.75rem; + font-size: 1.05rem; + margin-bottom: 0.25rem; + color: var(--rm-fg-1); + background: color-mix(in srgb, var(--rm-fg-2) 10%, transparent); +} +.shell-ic-drawer-list .shell-nav-link.is-active { + color: var(--rm-action); + background: color-mix(in srgb, var(--rm-action) 18%, transparent); +} +.shell-icloud.is-mobile .shell-ic-canvas { + padding: 0.75rem; + padding-bottom: calc(0.75rem + env(safe-area-inset-bottom, 0px)); +} +.shell-icloud.is-mobile .shell-ic-panel { + border-radius: 0.85rem; +} + +/* ----- os ----- */ +.shell-os { + flex-direction: column; + background: + radial-gradient(ellipse at 30% 20%, color-mix(in srgb, var(--rm-action) 28%, transparent), transparent 50%), + linear-gradient(160deg, var(--rm-bg-2), var(--rm-bg-1)); + color: var(--rm-fg-1); + font-family: system-ui, -apple-system, "Segoe UI", sans-serif; +} +.shell-os-desktop { + flex: 1; + display: flex; + align-items: stretch; + justify-content: center; + padding: 1.25rem; + min-height: 0; +} +.shell-os-window { + flex: 1; + max-width: 72rem; + display: flex; + flex-direction: column; + background: var(--rm-bg-2); + color: var(--rm-fg-1); + border-radius: 0.65rem; + overflow: visible; + box-shadow: 0 18px 48px rgba(0, 0, 0, 0.45); + min-height: 0; + border: 1px solid color-mix(in srgb, var(--rm-fg-2) 30%, transparent); +} +.shell-os-titlebar { + display: flex; + align-items: center; + gap: 0.75rem; + padding: 0.45rem 0.75rem; + background: var(--rm-bg-1); + color: var(--rm-fg-1); + border-bottom: 1px solid color-mix(in srgb, var(--rm-fg-2) 28%, transparent); + overflow: visible; + position: relative; + z-index: 50; +} +.shell-os-traffic { + display: inline-flex; + gap: 0.35rem; +} +.shell-os-dot { + width: 0.75rem; + height: 0.75rem; + border-radius: 50%; + display: inline-block; +} +.shell-os-dot-close { background: var(--rm-reject); } +.shell-os-dot-min { background: var(--rm-fg-3); } +.shell-os-dot-max { background: var(--rm-accept); } +.shell-os-window-title { + flex: 1; + text-align: center; + font-size: 0.85rem; + font-weight: 600; + color: var(--rm-fg-1); +} +.shell-os-toolbar { + padding: 0.4rem 0.75rem; + background: var(--rm-bg-2); + border-bottom: 1px solid color-mix(in srgb, var(--rm-fg-2) 28%, transparent); + font-size: 0.85rem; + color: var(--rm-fg-2); +} +.shell-os-path a { + color: var(--rm-action); + text-decoration: none; +} +.shell-os-body { + flex: 1; + display: flex; + min-height: 0; + background: var(--rm-bg-1); + overflow: hidden; + border-radius: 0 0 0.65rem 0.65rem; +} +.shell-os-sidebar { + width: 11.5rem; + flex: 0 0 11.5rem; + background: var(--rm-bg-2); + color: var(--rm-fg-1); + border-right: 1px solid color-mix(in srgb, var(--rm-fg-2) 28%, transparent); + padding: 0.65rem 0.45rem; + overflow: auto; +} +.shell-os-sidebar-label { + font-size: 0.7rem; + text-transform: uppercase; + letter-spacing: 0.06em; + color: var(--rm-fg-2); + font-weight: 700; + padding: 0.25rem 0.55rem 0.45rem; +} +.shell-os-fav-list .shell-nav-link { + width: 100%; + padding: 0.4rem 0.55rem; + border-radius: 0.35rem; + font-size: 0.85rem; + color: var(--rm-fg-1); +} +.shell-os-fav-list .shell-nav-link.is-active, +.shell-os-fav-list .shell-nav-link:hover { + background: color-mix(in srgb, var(--rm-action) 22%, transparent); + color: var(--rm-action); +} +.shell-os-pane { + padding: 1rem; + background: var(--rm-bg-1); + color: var(--rm-fg-1); +} +.shell-os-drives { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(7.5rem, 1fr)); + gap: 1.25rem; + padding: 1rem; + align-content: start; +} +.shell-os-drive { + display: flex; + flex-direction: column; + align-items: center; + gap: 0.5rem; + text-decoration: none; + color: var(--rm-fg-1); + padding: 0.75rem 0.5rem; + border-radius: 0.5rem; + min-height: 6.5rem; +} +.shell-os-drive:hover, +.shell-os-drive:focus-visible { + background: color-mix(in srgb, var(--rm-action) 16%, transparent); + outline: none; +} +.shell-os-drive-icon { + width: 3.5rem !important; + height: 3.5rem !important; + margin: 0 !important; + background: var(--rm-action) !important; + border-radius: 0.55rem; + box-shadow: 0 4px 10px rgba(0, 0, 0, 0.25); +} +.shell-os-drive-label { + font-size: 0.8rem; + text-align: center; + word-break: break-word; + color: var(--rm-fg-1); +} +.shell-os.is-mobile { + background: var(--rm-bg-2); + color: var(--rm-fg-1); +} +.shell-os-mobile-bar { + display: flex; + align-items: center; + gap: 0.65rem; + min-height: 3.25rem; + padding: 0.5rem 0.85rem; + padding-top: calc(0.5rem + env(safe-area-inset-top, 0px)); + background: var(--rm-bg-1); + color: var(--rm-fg-1); + border-bottom: 1px solid color-mix(in srgb, var(--rm-fg-2) 28%, transparent); + z-index: 40; +} +.shell-os-mobile-title { + margin: 0; + font-size: 1.15rem; + font-weight: 700; + flex: 1; + color: var(--rm-fg-1); +} +.shell-os-back { + color: var(--rm-action); + text-decoration: none; + font-weight: 600; + min-height: 2.75rem; + display: inline-flex; + align-items: center; + padding: 0 0.35rem; +} +.shell-os.is-mobile .shell-os-drives { + padding: 1.25rem 1rem calc(1.25rem + env(safe-area-inset-bottom, 0px)); + grid-template-columns: repeat(auto-fill, minmax(6.5rem, 1fr)); + gap: 1rem; +} +.shell-os-mobile-content { + padding: 0.85rem; + padding-bottom: calc(0.85rem + env(safe-area-inset-bottom, 0px)); + background: var(--rm-bg-1); + color: var(--rm-fg-1); +} + +@media (prefers-reduced-motion: reduce) { + .shell-rm-drawer, + .shell-gd-drawer, + .shell-ic-drawer { + transition: none; + } +} + +/* connect gauge live */ +.connect-gauge-circle-fill, +.connect-gauge-fill { + stroke: var(--rm-connect-gauge-fill); + transition: stroke-dashoffset 0.1s linear; +} +.connect-gauge-track { + stroke: var(--rm-connect-gauge-track); +} +.connect-gauge-bar-fill { + transition: width 0.1s linear; +} + +/* pager */ +.rm-pager { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 0.5rem 0.75rem; + margin: 0.75rem 0; +} +.rm-pager-status { + font-variant-numeric: tabular-nums; + color: var(--rm-fg-2); +} +.rm-pager-size select { + margin-left: 0.35rem; +} + +body.has-js-shell .site-header, +.site-header[hidden] { + display: none !important; +} diff --git a/internal/ui/static/favicon.ico b/internal/ui/static/favicon.ico new file mode 100644 index 00000000..baea61a5 Binary files /dev/null and b/internal/ui/static/favicon.ico differ diff --git a/internal/ui/static/js/.gitkeep b/internal/ui/static/js/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/internal/ui/static/js/bootstrap-xslt.js b/internal/ui/static/js/bootstrap-xslt.js new file mode 100644 index 00000000..8a577590 --- /dev/null +++ b/internal/ui/static/js/bootstrap-xslt.js @@ -0,0 +1,36 @@ +(async function () { + const el = document.getElementById("page-xml"); + if (!el) return; + const status = document.getElementById("xslt-status"); + try { + const xmlText = el.textContent; + const xml = new DOMParser().parseFromString(xmlText, "application/xml"); + if (xml.querySelector("parsererror")) { + throw new Error("Invalid page XML"); + } + const xslText = await fetch("/assets/xslt/shell.xsl", { credentials: "same-origin" }).then((r) => { + if (!r.ok) throw new Error("Failed to load shell.xsl"); + return r.text(); + }); + const xsl = new DOMParser().parseFromString(xslText, "application/xml"); + if (xsl.querySelector("parsererror")) { + throw new Error("Invalid shell.xsl"); + } + const proc = new XSLTProcessor(); + proc.importStylesheet(xsl); + const out = proc.transformToDocument(xml); + let html = new XMLSerializer().serializeToString(out); + html = html.replace(/<\?xml[^?]*\?>\s*/i, ""); + if (!/^\s*\n" + html; + } + document.open(); + document.write(html); + document.close(); + } catch (err) { + if (status) { + status.textContent = "UI render failed: " + (err && err.message ? err.message : String(err)); + } + console.error("[xslt]", err); + } +})(); diff --git a/internal/ui/static/js/chrome.js b/internal/ui/static/js/chrome.js new file mode 100644 index 00000000..f45f318c --- /dev/null +++ b/internal/ui/static/js/chrome.js @@ -0,0 +1,181 @@ +(function (global) { + "use strict"; + var RM = global.RM; + var h = RM.h; + + function readNav() { + var el = document.getElementById("rm-nav"); + if (!el) return []; + try { + return JSON.parse(el.textContent || "[]"); + } catch (_) { + return []; + } + } + + var NAV_LABELS = { + documents: "Documents", + integrations: "Integrations", + connect: "Connect", + screenshare: "Screen share", + admin: "Admin", + help: "Help", + profile: "Settings", + }; + + function navFromTheme(layout) { + var server = readNav(); + var byId = {}; + server.forEach(function (it) { + byId[it.id] = it; + }); + var items = (layout && layout.nav && layout.nav.items) || []; + if (!items.length) return server; + + var seen = {}; + var out = items + .filter(function (it) { + return it && it.id && it.visible !== false && String(it.visible) !== "false"; + }) + .map(function (it) { + var src = byId[it.id] || {}; + seen[it.id] = true; + return { + id: it.id, + href: src.href || it.href || "/" + it.id, + label: it.label || src.label || NAV_LABELS[it.id] || it.id, + icon: it.icon || src.icon || it.id, + adminOnly: it.adminOnly != null ? !!it.adminOnly : !!src.adminOnly, + }; + }); + + server.forEach(function (it) { + if (seen[it.id]) return; + out.push(it); + }); + return out.length ? out : server; + } + + function resolveChromeStyle(explicit, layout) { + var normalize = global.RMShells && global.RMShells.normalizeChromeStyle; + var fromLayout = layout && layout.chrome && layout.chrome.style; + var style = explicit || fromLayout || "remarkable"; + return normalize ? normalize(style) : style; + } + + function ShellChrome(props) { + var theme = global.useShellTheme ? global.useShellTheme() : { layout: {}, formFactor: "desktop" }; + var formFactor = + props.forceMobile || theme.formFactor === "mobile" || (global.detectFormFactor && global.detectFormFactor() === "mobile") + ? "mobile" + : "desktop"; + var chromeStyle = resolveChromeStyle(props.chromeStyle, theme.layout); + var nav = navFromTheme(theme.layout); + if (!nav.length) nav = readNav(); + + var Shell = (global.RMShells && global.RMShells[chromeStyle]) || global.RMShells.remarkable; + return h(Shell, { + nav: nav, + mainSlot: props.mainSlot, + layout: theme.layout, + formFactor: formFactor, + }); + } + + function mount() { + if (document.body.classList.contains("page-login") || document.body.classList.contains("page-error")) { + return; + } + var main = document.getElementById("main"); + if (!main) return; + + var root = document.getElementById("rm-shell-root"); + if (!root) { + root = document.createElement("div"); + root.id = "rm-shell-root"; + document.body.insertBefore(root, document.body.firstChild); + } + + var flashes = Array.prototype.slice.call(root.querySelectorAll(".flash")); + flashes.forEach(function (f) { + document.body.insertBefore(f, root); + }); + + var mainHost = document.createElement("div"); + mainHost.id = "rm-main-host"; + mainHost.appendChild(main); + + var chromeMatch = (document.body.className || "").match(/chrome-([a-z]+)/); + var chromeStyle = + global.RMShells && global.RMShells.normalizeChromeStyle + ? global.RMShells.normalizeChromeStyle(chromeMatch ? chromeMatch[1] : "remarkable") + : chromeMatch + ? chromeMatch[1] + : "remarkable"; + + function Root() { + var theme = global.useShellTheme + ? global.useShellTheme() + : { formFactor: global.detectFormFactor && global.detectFormFactor() }; + RM.useEffect(function () { + if (global.reloadShellTheme) global.reloadShellTheme(); + if (global.enhanceTablePagination) { + global.enhanceTablePagination(".profile-panel .data-table"); + global.enhanceTablePagination(".admin-panel .data-table"); + global.enhanceTablePagination(".integrations-panel .data-table"); + global.enhanceTablePagination(".themes-panel .data-table"); + } + }, []); + return h(ShellChrome, { + chromeStyle: chromeStyle, + forceMobile: theme.formFactor === "mobile", + mainSlot: mainHost, + }); + } + + try { + RM.render(Root, root); + document.body.classList.add("has-js-shell"); + } catch (err) { + console.error("[chrome] shell mount failed", err); + } + + if (global.apiService && global.apiService.listPasscodeResets) { + mountPasscodeResets(); + } + } + + function mountPasscodeResets() { + var host = document.createElement("div"); + host.id = "rm-passcode-resets"; + document.body.appendChild(host); + async function tick() { + try { + var list = await global.apiService.listPasscodeResets(); + if (!list || !list.length) { + host.innerHTML = ""; + return; + } + host.innerHTML = + '
Passcode reset request(s) pending.
'; + var btn = document.getElementById("rm-approve-passcode"); + if (btn && list[0].uuid) { + btn.onclick = async function () { + await global.apiService.approvePasscodeReset(list[0].uuid); + tick(); + }; + } + } catch (_) {} + } + tick(); + setInterval(tick, 10000); + } + + global.RMChrome = { mount: mount, readNav: readNav, navFromTheme: navFromTheme }; + + if (document.readyState === "loading") { + document.addEventListener("DOMContentLoaded", mount); + } else { + mount(); + } +})(typeof window !== "undefined" ? window : globalThis); diff --git a/internal/ui/static/js/connect.js b/internal/ui/static/js/connect.js new file mode 100644 index 00000000..6a49472d --- /dev/null +++ b/internal/ui/static/js/connect.js @@ -0,0 +1,255 @@ +/** + * Connect pairing code + live draining gauge (5 minute TTL). + * Polls whether the displayed code is still active; after a successful + * tablet pair the code is consumed and a new one is issued automatically. + */ +(function () { + "use strict"; + + var CODE_TTL_MS = 5 * 60 * 1000; + var POLL_MS = 2000; + + function $(id) { + return document.getElementById(id); + } + + function formatLabel(secs) { + var s = Math.max(0, Math.ceil(secs)); + var m = Math.floor(s / 60); + var r = s % 60; + return m + ":" + String(r).padStart(2, "0"); + } + + function buildGauge(el, type) { + el.innerHTML = ""; + el.classList.add("connect-gauge", "connect-gauge-" + type); + el.setAttribute("role", "progressbar"); + el.setAttribute("aria-valuemin", "0"); + el.setAttribute("aria-valuemax", "100"); + el.setAttribute("data-ttl", "300"); + + if (type === "bar") { + var track = document.createElement("div"); + track.className = "connect-gauge-bar-track"; + var fill = document.createElement("div"); + fill.className = "connect-gauge-bar-fill"; + fill.style.width = "100%"; + track.appendChild(fill); + el.appendChild(track); + var label = document.createElement("div"); + label.className = "connect-gauge-label"; + label.id = "connect-gauge-label"; + el.appendChild(label); + return; + } + + var size = 160; + var stroke = 10; + var r = (size - stroke) / 2; + var c = 2 * Math.PI * r; + var ns = "http://www.w3.org/2000/svg"; + var svg = document.createElementNS(ns, "svg"); + svg.setAttribute("width", String(size)); + svg.setAttribute("height", String(size)); + svg.setAttribute("viewBox", "0 0 " + size + " " + size); + svg.setAttribute("aria-hidden", "true"); + svg.classList.add("connect-gauge-inner"); + + var g = document.createElementNS(ns, "g"); + g.setAttribute("transform", "rotate(-90 " + size / 2 + " " + size / 2 + ")"); + + var trackCircle = document.createElementNS(ns, "circle"); + trackCircle.setAttribute("cx", String(size / 2)); + trackCircle.setAttribute("cy", String(size / 2)); + trackCircle.setAttribute("r", String(r)); + trackCircle.setAttribute("fill", "none"); + trackCircle.setAttribute("stroke-width", String(stroke)); + trackCircle.setAttribute("class", "connect-gauge-track"); + g.appendChild(trackCircle); + + var fillCircle = document.createElementNS(ns, "circle"); + fillCircle.setAttribute("cx", String(size / 2)); + fillCircle.setAttribute("cy", String(size / 2)); + fillCircle.setAttribute("r", String(r)); + fillCircle.setAttribute("fill", "none"); + fillCircle.setAttribute("stroke-width", String(stroke)); + fillCircle.setAttribute("stroke-dasharray", String(c)); + fillCircle.setAttribute("stroke-dashoffset", "0"); + fillCircle.setAttribute("stroke-linecap", "round"); + fillCircle.setAttribute("class", "connect-gauge-circle-fill connect-gauge-fill"); + fillCircle.dataset.circumference = String(c); + g.appendChild(fillCircle); + svg.appendChild(g); + + var text = document.createElementNS(ns, "text"); + text.setAttribute("x", "50%"); + text.setAttribute("y", "50%"); + text.setAttribute("dominant-baseline", "middle"); + text.setAttribute("text-anchor", "middle"); + text.setAttribute("class", "connect-gauge-text connect-gauge-label"); + text.id = "connect-gauge-label"; + svg.appendChild(text); + el.appendChild(svg); + } + + function setProgress(el, type, progress, label) { + var p = Math.max(0, Math.min(1, progress)); + el.setAttribute("aria-valuenow", String(Math.round(p * 100))); + if (type === "bar") { + var fill = el.querySelector(".connect-gauge-bar-fill"); + if (fill) fill.style.width = p * 100 + "%"; + var lab = el.querySelector(".connect-gauge-label"); + if (lab) lab.textContent = label; + return; + } + var circle = el.querySelector(".connect-gauge-circle-fill"); + if (circle) { + var circ = parseFloat(circle.dataset.circumference || "0"); + circle.style.strokeDashoffset = String(circ * (1 - p)); + circle.setAttribute("stroke-dashoffset", String(circ * (1 - p))); + } + var text = el.querySelector(".connect-gauge-label"); + if (text) text.textContent = label; + } + + async function fetchCode() { + if (window.apiService && typeof window.apiService.getCode === "function") { + return window.apiService.getCode(); + } + var r = await fetch("/ui/api/newcode", { + method: "GET", + credentials: "same-origin", + headers: { "Content-Type": "application/json" }, + }); + if (!r.ok) throw new Error(r.statusText || "Failed to fetch code"); + return r.json(); + } + + async function fetchCodeStatus() { + if (window.apiService && typeof window.apiService.getCodeStatus === "function") { + return window.apiService.getCodeStatus(); + } + var r = await fetch("/ui/api/code", { + method: "GET", + credentials: "same-origin", + headers: { Accept: "application/json" }, + }); + if (!r.ok) throw new Error(r.statusText || "Failed to check code"); + return r.json(); + } + + function init() { + var codeEl = $("connect-code"); + var gaugeEl = $("connect-gauge"); + if (!codeEl || !gaugeEl) return; + + var statusEl = $("connect-status"); + var gaugeType = (gaugeEl.getAttribute("data-gauge-type") || "circle").toLowerCase(); + if (gaugeType !== "bar") gaugeType = "circle"; + buildGauge(gaugeEl, gaugeType); + + var issuedAt = 0; + var activeCode = ""; + var busy = false; + var raf = 0; + var pollTimer = 0; + var statusClearTimer = 0; + + function setStatus(msg, paired) { + if (!statusEl) return; + statusEl.textContent = msg || ""; + statusEl.hidden = !msg; + statusEl.classList.toggle("is-paired", !!paired); + if (statusClearTimer) clearTimeout(statusClearTimer); + if (msg && paired) { + statusClearTimer = setTimeout(function () { + statusEl.textContent = ""; + statusEl.hidden = true; + statusEl.classList.remove("is-paired"); + }, 8000); + } + } + + async function refresh(opts) { + if (busy) return; + busy = true; + var paired = opts && opts.paired; + try { + var code = await fetchCode(); + activeCode = typeof code === "string" ? code : String(code); + codeEl.textContent = activeCode; + issuedAt = Date.now(); + if (paired) { + setStatus("Device paired. New code ready for another tablet.", true); + } + } catch (e) { + activeCode = ""; + codeEl.textContent = "········"; + console.error("[connect]", e); + } finally { + busy = false; + } + } + + async function pollActive() { + if (busy || !activeCode || document.hidden) return; + try { + var st = await fetchCodeStatus(); + var serverCode = st && st.code ? String(st.code) : ""; + var active = !!(st && st.active && serverCode); + if (!active || serverCode !== activeCode) { + var remaining = issuedAt ? CODE_TTL_MS - (Date.now() - issuedAt) : 0; + // Still within TTL → code was consumed by a successful pair (or replaced elsewhere). + var paired = remaining > 2000; + await refresh({ paired: paired }); + } + } catch (e) { + console.error("[connect] status", e); + } + } + + function frame() { + if (!issuedAt) { + setProgress(gaugeEl, gaugeType, 1, ""); + } else { + var remaining = Math.max(0, CODE_TTL_MS - (Date.now() - issuedAt)); + var progress = remaining / CODE_TTL_MS; + setProgress(gaugeEl, gaugeType, progress, formatLabel(remaining / 1000)); + if (remaining <= 0 && !busy) refresh(); + } + raf = requestAnimationFrame(frame); + } + + refresh(); + raf = requestAnimationFrame(frame); + pollTimer = setInterval(pollActive, POLL_MS); + + var refreshBtn = document.getElementById("connect-refresh"); + if (refreshBtn) { + refreshBtn.addEventListener("click", function () { + setStatus(""); + refresh(); + }); + } + + document.addEventListener("visibilitychange", function () { + if (!document.hidden) pollActive(); + }); + + window.addEventListener( + "pagehide", + function () { + cancelAnimationFrame(raf); + if (pollTimer) clearInterval(pollTimer); + if (statusClearTimer) clearTimeout(statusClearTimer); + }, + { once: true } + ); + } + + if (document.readyState === "loading") { + document.addEventListener("DOMContentLoaded", init); + } else { + init(); + } +})(); diff --git a/internal/ui/static/js/documents-refresh.js b/internal/ui/static/js/documents-refresh.js new file mode 100644 index 00000000..7d4ec3cf --- /dev/null +++ b/internal/ui/static/js/documents-refresh.js @@ -0,0 +1,410 @@ +/** + * reMarkable-style documents browser: folder cluster, framed thumbs, dock. + */ +(function () { + "use strict"; + + var INTERVAL_MS = 15000; + var lastSnap = ""; + var PDFJS_CDN = "https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.min.js"; + var WORKER_CDN = "https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.worker.min.js"; + var pdfjsReady = null; + var thumbObserver = null; + + function activeFolderId() { + var params = new URLSearchParams(window.location.search); + return params.get("folder") || ""; + } + + function findFolder(entries, id) { + if (!id) return entries || []; + entries = entries || []; + for (var i = 0; i < entries.length; i++) { + var e = entries[i]; + if (e.isFolder && e.id === id) return e.children || []; + if (e.isFolder && e.children) { + var found = findFolder(e.children, id); + if (found) return found; + } + } + return null; + } + + function walkSnap(entries, acc) { + (entries || []).forEach(function (e) { + acc.push((e.isFolder ? "F:" : "D:") + e.id + ":" + (e.name || "") + ":" + (e.size || 0)); + if (e.isFolder && e.children) walkSnap(e.children, acc); + }); + } + + function snapshot(tree) { + var acc = []; + var entries = (tree && (tree.Entries || tree.entries)) || []; + var trash = (tree && (tree.Trash || tree.trash)) || []; + walkSnap(entries, acc); + walkSnap(trash, acc); + return acc.join("|"); + } + + function docType(e) { + var t = String(e.type || e.DocumentType || "").toLowerCase().replace(/^\./, ""); + if (t === "pdf" || t === "application/pdf") return "pdf"; + if (t === "epub" || t === "application/epub+zip") return "epub"; + return "notebook"; + } + + function thumbPage(e) { + var pages = e.pageCount || e.PageCount || 0; + var page = e.currentPage || e.CurrentPage || 0; + var n = page + 1; + if (n < 1) n = 1; + if (pages > 0 && n > pages) n = pages; + return n; + } + + function pageLabel(e) { + var pages = e.pageCount || e.PageCount || 0; + var n = thumbPage(e); + if (pages > 0) return "Page " + n + " of " + pages; + var t = docType(e); + if (t === "pdf") return "PDF"; + if (t === "epub") return "EPUB"; + return "Notebook"; + } + + function renderFolders(ul, folders) { + ul.innerHTML = ""; + folders.forEach(function (e) { + var li = document.createElement("li"); + li.className = "rm-folder-item"; + li.setAttribute("data-name", e.name || ""); + li.setAttribute("data-modified", e.lastModified || ""); + var a = document.createElement("a"); + a.href = "/documents?folder=" + encodeURIComponent(e.id); + a.innerHTML = + '' + + ''; + a.querySelector(".rm-folder-name").textContent = e.name || e.id; + if (e.pinned) { + var star = document.createElement("span"); + star.className = "rm-star"; + star.setAttribute("aria-label", "Favorite"); + star.textContent = "★"; + a.appendChild(star); + } + li.appendChild(a); + ul.appendChild(li); + }); + } + + function renderFiles(ul, files) { + ul.innerHTML = ""; + files.forEach(function (e) { + var t = docType(e); + var li = document.createElement("li"); + li.className = "rm-file-item"; + li.setAttribute("data-name", e.name || ""); + li.setAttribute("data-modified", e.lastModified || ""); + li.setAttribute("data-type", t); + var a = document.createElement("a"); + a.href = "/documents/" + encodeURIComponent(e.id); + a.className = "rm-file-link"; + var frame = document.createElement("span"); + frame.className = "rm-page-frame is-" + t; + var page = thumbPage(e); + if (t === "pdf") { + var canvas = document.createElement("canvas"); + canvas.className = "rm-thumb-canvas"; + canvas.width = 180; + canvas.height = 240; + canvas.setAttribute("data-pdf-url", "/ui/api/documents/" + encodeURIComponent(e.id) + "?type=pdf"); + canvas.setAttribute("data-pdf-page", String(page)); + canvas.setAttribute("aria-hidden", "true"); + frame.appendChild(canvas); + } else if (t === "notebook") { + var img = document.createElement("img"); + img.className = "rm-thumb-img"; + img.width = 180; + img.height = 240; + img.alt = ""; + img.loading = "lazy"; + img.decoding = "async"; + img.src = "/ui/api/documents/" + encodeURIComponent(e.id) + "/page/" + page; + img.addEventListener("load", function () { + frame.classList.add("has-preview"); + }); + frame.appendChild(img); + } else if (t === "epub") { + var epubImg = document.createElement("img"); + epubImg.className = "rm-thumb-img"; + epubImg.width = 180; + epubImg.height = 240; + epubImg.alt = ""; + epubImg.loading = "lazy"; + epubImg.decoding = "async"; + epubImg.src = "/ui/api/documents/" + encodeURIComponent(e.id) + "/epub/thumb"; + epubImg.addEventListener("load", function () { + frame.classList.add("has-preview"); + }); + frame.appendChild(epubImg); + } else { + var ph = document.createElement("span"); + ph.className = "rm-page-placeholder"; + ph.setAttribute("aria-hidden", "true"); + frame.appendChild(ph); + } + if (t !== "epub") { + var ear = document.createElement("span"); + ear.className = "rm-page-ear"; + ear.setAttribute("aria-hidden", "true"); + frame.appendChild(ear); + } + var meta = document.createElement("span"); + meta.className = "rm-file-meta"; + var name = document.createElement("span"); + name.className = "rm-file-name"; + name.textContent = e.name || e.id; + if (e.pinned) { + var star = document.createElement("span"); + star.className = "rm-star"; + star.setAttribute("aria-label", "Favorite"); + star.textContent = " ★"; + name.appendChild(star); + } + var sub = document.createElement("span"); + sub.className = "rm-file-sub"; + sub.textContent = pageLabel(e); + meta.appendChild(name); + meta.appendChild(sub); + a.appendChild(frame); + a.appendChild(meta); + li.appendChild(a); + ul.appendChild(li); + }); + } + + function splitEntries(entries) { + var folders = []; + var files = []; + (entries || []).forEach(function (e) { + if (e.isFolder) folders.push(e); + else files.push(e); + }); + return { folders: folders, files: files }; + } + + function applySort() { + var sel = document.getElementById("rm-sort"); + var mode = sel ? sel.value : "modified"; + function cmp(a, b) { + if (mode === "name") { + return (a.getAttribute("data-name") || "").localeCompare(b.getAttribute("data-name") || "", undefined, { + sensitivity: "base", + }); + } + return String(b.getAttribute("data-modified") || "").localeCompare(String(a.getAttribute("data-modified") || "")); + } + [".rm-folder-grid", ".rm-file-grid"].forEach(function (selGrid) { + var ul = document.querySelector(selGrid); + if (!ul) return; + var items = Array.prototype.slice.call(ul.children); + items.sort(cmp); + items.forEach(function (it) { + ul.appendChild(it); + }); + }); + } + + function applySearch() { + var q = (document.getElementById("rm-search") && document.getElementById("rm-search").value) || ""; + q = q.trim().toLowerCase(); + document.querySelectorAll(".rm-folder-item, .rm-file-item").forEach(function (el) { + var name = (el.getAttribute("data-name") || "").toLowerCase(); + el.classList.toggle("is-hidden", q && name.indexOf(q) < 0); + }); + } + + function loadPdfJs() { + if (window.pdfjsLib) return Promise.resolve(window.pdfjsLib); + if (pdfjsReady) return pdfjsReady; + pdfjsReady = new Promise(function (resolve, reject) { + var s = document.createElement("script"); + s.src = PDFJS_CDN; + s.async = true; + s.onload = function () { + if (!window.pdfjsLib) { + reject(new Error("pdfjsLib missing")); + return; + } + window.pdfjsLib.GlobalWorkerOptions.workerSrc = WORKER_CDN; + resolve(window.pdfjsLib); + }; + s.onerror = function () { + reject(new Error("pdf.js failed to load")); + }; + document.head.appendChild(s); + }); + return pdfjsReady; + } + + async function renderPdfThumb(canvas) { + var url = canvas.getAttribute("data-pdf-url"); + if (!url || canvas.getAttribute("data-rendered") === "1") return; + canvas.setAttribute("data-rendered", "1"); + try { + var pdfjsLib = await loadPdfJs(); + var pdf = await pdfjsLib.getDocument({ url: url, withCredentials: true }).promise; + var pageNum = parseInt(canvas.getAttribute("data-pdf-page") || "1", 10); + if (!pageNum || pageNum < 1) pageNum = 1; + if (pageNum > pdf.numPages) pageNum = pdf.numPages; + var page = await pdf.getPage(pageNum); + var viewport = page.getViewport({ scale: 1 }); + var scale = canvas.width / viewport.width; + var vp = page.getViewport({ scale: scale }); + canvas.height = vp.height; + var ctx = canvas.getContext("2d"); + await page.render({ canvasContext: ctx, viewport: vp }).promise; + var frame = canvas.closest(".rm-page-frame"); + if (frame) frame.classList.add("has-preview"); + } catch (err) { + console.warn("[documents] pdf thumb", err); + } + } + + function observeThumbs() { + document.querySelectorAll(".rm-page-frame .rm-thumb-img").forEach(function (img) { + function mark() { + if (img.naturalWidth) { + var frame = img.closest(".rm-page-frame"); + if (frame) frame.classList.add("has-preview"); + } + } + if (img.complete) mark(); + else img.addEventListener("load", mark, { once: true }); + }); + if (thumbObserver) thumbObserver.disconnect(); + var canvases = document.querySelectorAll(".rm-thumb-canvas[data-pdf-url]"); + if (!canvases.length) return; + thumbObserver = new IntersectionObserver( + function (entries) { + entries.forEach(function (en) { + if (!en.isIntersecting) return; + thumbObserver.unobserve(en.target); + renderPdfThumb(en.target); + }); + }, + { rootMargin: "120px" } + ); + canvases.forEach(function (c) { + thumbObserver.observe(c); + }); + } + + function wireChrome() { + var searchBtn = document.getElementById("rm-search-toggle"); + var searchBar = document.getElementById("rm-search-bar"); + var searchInput = document.getElementById("rm-search"); + if (searchBtn && searchBar) { + searchBtn.addEventListener("click", function () { + var on = searchBar.hasAttribute("hidden"); + if (on) searchBar.removeAttribute("hidden"); + else searchBar.setAttribute("hidden", "hidden"); + searchBtn.setAttribute("aria-expanded", on ? "true" : "false"); + if (on && searchInput) searchInput.focus(); + }); + } + if (searchInput) searchInput.addEventListener("input", applySearch); + + var uploadBtn = document.getElementById("rm-upload-toggle"); + var fileInput = document.getElementById("doc-upload"); + var uploadForm = document.getElementById("rm-upload-form"); + if (uploadBtn && fileInput) { + uploadBtn.addEventListener("click", function () { + fileInput.click(); + }); + fileInput.addEventListener("change", function () { + if (fileInput.files && fileInput.files.length && uploadForm) uploadForm.submit(); + }); + } + + var folderBtn = document.getElementById("rm-folder-toggle"); + var dialog = document.getElementById("rm-folder-dialog"); + var cancel = document.getElementById("rm-folder-cancel"); + if (folderBtn && dialog && dialog.showModal) { + folderBtn.addEventListener("click", function () { + dialog.showModal(); + var name = document.getElementById("folder-name"); + if (name) name.focus(); + }); + } + if (cancel && dialog) { + cancel.addEventListener("click", function () { + dialog.close(); + }); + } + + var sort = document.getElementById("rm-sort"); + if (sort) sort.addEventListener("change", applySort); + } + + function shouldSkip() { + var ae = document.activeElement; + if (!ae) return false; + if (ae.closest && ae.closest("#rm-upload-form, #rm-folder-dialog, .rm-search-bar")) return true; + if (ae.tagName === "INPUT" && ae.type === "file") return true; + return false; + } + + async function poll() { + if (document.hidden || shouldSkip()) return; + if (!window.apiService || typeof window.apiService.listDocument !== "function") return; + try { + var tree = await window.apiService.listDocument(); + var snap = snapshot(tree); + var folderUl = document.querySelector(".rm-folder-grid"); + var fileUl = document.querySelector(".rm-file-grid"); + var hasItems = !!(folderUl && folderUl.children.length) || !!(fileUl && fileUl.children.length); + if (lastSnap === "") { + lastSnap = snap; + if (hasItems) { + observeThumbs(); + return; + } + } + if (snap === lastSnap) return; + lastSnap = snap; + var folderId = activeFolderId(); + var rootEntries = tree.Entries || tree.entries || []; + var entries = folderId ? findFolder(rootEntries, folderId) : rootEntries; + if (entries === null) entries = []; + var parts = splitEntries(entries); + if (folderUl) renderFolders(folderUl, parts.folders); + if (fileUl) renderFiles(fileUl, parts.files); + applySort(); + applySearch(); + observeThumbs(); + } catch (e) { + console.warn("[documents]", e); + } + } + + function init() { + if (!document.body.classList.contains("page-documents") && !document.querySelector(".rm-files")) { + return; + } + wireChrome(); + applySort(); + observeThumbs(); + poll(); + setInterval(poll, INTERVAL_MS); + document.addEventListener("visibilitychange", function () { + if (!document.hidden) poll(); + }); + } + + if (document.readyState === "loading") { + document.addEventListener("DOMContentLoaded", init); + } else { + init(); + } +})(); diff --git a/internal/ui/static/js/epubview.js b/internal/ui/static/js/epubview.js new file mode 100644 index 00000000..58d6197e --- /dev/null +++ b/internal/ui/static/js/epubview.js @@ -0,0 +1,50 @@ +/** + * EPUB website viewer: keep the contents list in sync with the iframe. + */ +(function () { + "use strict"; + + function currentPath(frame) { + try { + if (frame.contentWindow && frame.contentWindow.location) { + return frame.contentWindow.location.pathname; + } + } catch (_) {} + try { + return new URL(frame.getAttribute("src") || "", window.location.href).pathname; + } catch (_) { + return ""; + } + } + + function markToc(frame, toc) { + var path = currentPath(frame); + toc.querySelectorAll("a[href]").forEach(function (a) { + var hrefPath = ""; + try { + hrefPath = new URL(a.getAttribute("href"), window.location.href).pathname; + } catch (_) {} + if (hrefPath && path && hrefPath === path) { + a.setAttribute("aria-current", "page"); + } else { + a.removeAttribute("aria-current"); + } + }); + } + + function init() { + var frame = document.getElementById("epub-frame"); + var toc = document.querySelector(".epub-toc"); + if (!frame || !toc) return; + markToc(frame, toc); + frame.addEventListener("load", function () { + markToc(frame, toc); + }); + } + + if (document.readyState === "loading") { + document.addEventListener("DOMContentLoaded", init); + } else { + init(); + } +})(); diff --git a/internal/ui/static/js/legacy/api.service.js b/internal/ui/static/js/legacy/api.service.js new file mode 100644 index 00000000..e1b4c7c7 --- /dev/null +++ b/internal/ui/static/js/legacy/api.service.js @@ -0,0 +1,426 @@ +(function (global) { + "use strict"; + var constants = global.constants || { ROOT_URL: "/ui/api" }; + function jwtDecode(token) { + var parts = String(token).split("."); + if (parts.length < 2) throw new Error("invalid jwt"); + var json = parts[1].replace(/-/g, "+").replace(/_/g, "/"); + while (json.length % 4) json += "="; + return JSON.parse(atob(json)); + } + + +class ApiServices { + header() { + return { + "Content-Type": "application/json", + }; + } + checkLogin() { + if (localStorage.getItem("currentUser")) { + return fetch(`${constants.ROOT_URL}/`, { credentials: "same-origin", + method: "HEAD", + }).then(handleError); + } + } + login(loginData) { + return fetch(`${constants.ROOT_URL}/login`, { credentials: "same-origin", + method: "POST", + headers: this.header(), + body: JSON.stringify(loginData), + }) + .then((r) => { + if (!r.ok) { + throw new Error(r.statusText); + } + return r.text(); + }) + .then((text) => { + let user = jwtDecode(text); + localStorage.setItem("currentUser", JSON.stringify(user)); + localStorage.setItem("authToken", text); + return user; + }); + } + webAuthnStatus() { + return fetch(`${constants.ROOT_URL}/webauthn/status`, { + method: "GET", + headers: this.header(), + credentials: "same-origin", + }).then(async (r) => { + if (!r.ok) return { enabled: false }; + return r.json(); + }).catch(() => ({ enabled: false })); + } + webAuthnRegisterBegin() { + return fetch(`${constants.ROOT_URL}/webauthn/register/begin`, { + method: "POST", + headers: this.header(), + credentials: "same-origin", + }).then(async (r) => { + handleError(r); + return r.json(); + }); + } + webAuthnRegisterFinish(sessionId, credential, name) { + return fetch(`${constants.ROOT_URL}/webauthn/register/finish`, { + method: "POST", + headers: this.header(), + credentials: "same-origin", + body: JSON.stringify({ sessionId, credential, name }), + }).then(async (r) => { + handleError(r); + return r.json(); + }); + } + listWebAuthnCredentials() { + return fetch(`${constants.ROOT_URL}/webauthn/credentials`, { + method: "GET", + headers: this.header(), + credentials: "same-origin", + }).then(async (r) => { + handleError(r); + return r.json(); + }); + } + deleteWebAuthnCredential(id) { + return fetch(`${constants.ROOT_URL}/webauthn/credentials/${encodeURIComponent(id)}`, { + method: "DELETE", + headers: this.header(), + credentials: "same-origin", + }).then((r) => handleError(r)); + } + webAuthnLoginBegin() { + return fetch(`${constants.ROOT_URL}/webauthn/login/begin`, { + method: "POST", + headers: this.header(), + credentials: "same-origin", + }).then(async (r) => { + handleError(r); + return r.json(); + }); + } + webAuthnLoginFinish(sessionId, credential) { + return fetch(`${constants.ROOT_URL}/webauthn/login/finish`, { + method: "POST", + headers: this.header(), + credentials: "same-origin", + body: JSON.stringify({ sessionId, credential }), + }) + .then(async (r) => { + const text = await r.text(); + if (!r.ok) { + let msg = r.statusText; + try { + if (text && text.startsWith("{")) { + const j = JSON.parse(text); + if (j.error) msg = j.error; + } + } catch (_) {} + throw new Error(msg); + } + return text; + }) + .then((text) => { + let user = jwtDecode(text); + localStorage.setItem("currentUser", JSON.stringify(user)); + localStorage.setItem("authToken", text); + return user; + }); + } + logout() { + removeUser(); + fetch(`${constants.ROOT_URL}/logout`); + } + + upload(parent, files) { + const formData = new FormData(); + formData.append("parent", parent); + files.forEach((f) => { + // file extensions which are not lowecase break the upload + + // set the file extension to be lower case + let sub = f.name.split(".") + const ext = sub[sub.length - 1].toLowerCase() + sub.pop() + sub.push(ext) + + // copy file data to new (lowecase) file + const newFile = new File([f], sub.join("."), {type: f.type}); + formData.append("file", newFile); + }); + + return fetch(`${constants.ROOT_URL}/documents/upload`, { credentials: "same-origin", + method: "POST", + body: formData, + }).then(async (r) => { + if (r.status === 409) { + const body = await r.json(); + const err = new Error(body.error); + err.status = 409; + err.docId = body.docId; + throw err; + } + if (!r.ok) { + const body = await r.json(); + throw new Error(body.error || r.statusText); + } + return r.json(); + }); + } + + listPasscodeResets() { + return fetch(`${constants.ROOT_URL}/passcode/resets`, { credentials: "same-origin", + method: "GET", + headers: this.header(), + }).then((r) => { + handleError(r); + return r.json(); + }); + } + approvePasscodeReset(uuid) { + return fetch(`${constants.ROOT_URL}/passcode/resets/${uuid}/approve`, { credentials: "same-origin", + method: "POST", + headers: this.header(), + }).then((r) => handleError(r)); + } + dismissPasscodeReset(uuid) { + return fetch(`${constants.ROOT_URL}/passcode/resets/${uuid}`, { credentials: "same-origin", + method: "DELETE", + headers: this.header(), + }).then((r) => handleError(r)); + } + + resetPassword(resetPasswordForm) { + return fetch(`${constants.ROOT_URL}/profile`, { credentials: "same-origin", + method: "POST", + headers: this.header(), + body: JSON.stringify({ + ...resetPasswordForm, + }), + }); + } + + listDocument() { + return fetch(`${constants.ROOT_URL}/documents`, { credentials: "same-origin", + method: "GET", + headers: this.header(), + }).then((r) => { + handleError(r); + return r.json(); + }); + } + getCode() { + return fetch(`${constants.ROOT_URL}/newcode`, { credentials: "same-origin", + method: "GET", + headers: this.header(), + }).then((r) => { + handleError(r); + return r.json(); + }); + } + getCodeStatus() { + return fetch(`${constants.ROOT_URL}/code`, { credentials: "same-origin", + method: "GET", + headers: this.header(), + }).then((r) => { + handleError(r); + return r.json(); + }); + } + + deleteDocument(id) { + return fetch(`${constants.ROOT_URL}/documents/${id}`, { credentials: "same-origin", + method: "DELETE", + headers: this.header(), + }).then((r) => handleError(r)); + } + updateDocument(data) { + return fetch(`${constants.ROOT_URL}/documents`, { + credentials: "same-origin", + method: "PUT", + headers: this.header(), + body: JSON.stringify(data), + }).then((r) => handleError(r)); + } + download(id, exportType) { + let url = `${constants.ROOT_URL}/documents/${id}`; + if (exportType) url += `?type=${exportType}`; + return fetch(url, { + method: "GET", + }).then((r) => { + handleError(r); + return r.blob(); + }); + } + + createFolder(data) { + return fetch(`${constants.ROOT_URL}/folders`, { credentials: "same-origin", + method: "POST", + headers: this.header(), + body: JSON.stringify(data), + }).then((r) => { + handleError(r); + return r.json(); + }); + } + updateuser(usr) { + return fetch(`${constants.ROOT_URL}/users`, { credentials: "same-origin", + method: "PUT", + headers: this.header(), + body: JSON.stringify(usr), + }).then((r) => handleError(r)); + } + createuser(usr) { + return fetch(`${constants.ROOT_URL}/users`, { credentials: "same-origin", + method: "POST", + headers: this.header(), + body: JSON.stringify(usr), + }).then((r) => handleError(r)); + } + deleteuser(userid) { + return fetch(`${constants.ROOT_URL}/users/${userid}`, { credentials: "same-origin", + method: "DELETE", + headers: this.header(), + }).then((r) => handleError(r)); + } + + listintegration() { + return fetch(`${constants.ROOT_URL}/integrations`, { credentials: "same-origin", + method: "GET", + headers: this.header(), + }).then((r) => { + handleError(r); + return r.json(); + }); + } + updateintegration(integration) { + return fetch(`${constants.ROOT_URL}/integrations/${integration.id}`, { credentials: "same-origin", + method: "PUT", + headers: this.header(), + body: JSON.stringify(integration), + }).then((r) => handleError(r)); + } + createintegration(integration) { + return fetch(`${constants.ROOT_URL}/integrations`, { credentials: "same-origin", + method: "POST", + headers: this.header(), + body: JSON.stringify(integration), + }).then((r) => handleError(r)); + } + deleteintegration(integrationid) { + return fetch(`${constants.ROOT_URL}/integrations/${integrationid}`, { credentials: "same-origin", + method: "DELETE", + headers: this.header(), + }).then((r) => handleError(r)); + } + + listThemes() { + return fetch(`${constants.ROOT_URL}/themes`, { + method: "GET", + headers: this.header(), + credentials: "same-origin", + }).then(async (r) => { + handleError(r); + return r.json(); + }); + } + getTheme(id) { + return fetch(`${constants.ROOT_URL}/themes/${encodeURIComponent(id)}`, { + method: "GET", + headers: this.header(), + credentials: "same-origin", + }).then(async (r) => { + handleError(r); + return r.json(); + }); + } + getProfileTheme() { + return fetch(`${constants.ROOT_URL}/profile/theme`, { + method: "GET", + headers: this.header(), + credentials: "same-origin", + }).then(async (r) => { + handleError(r); + return r.json(); + }); + } + putProfileTheme(body) { + return fetch(`${constants.ROOT_URL}/profile/theme`, { + method: "PUT", + headers: this.header(), + credentials: "same-origin", + body: JSON.stringify(body), + }).then(async (r) => { + handleError(r); + return r.json(); + }); + } + saveTheme(body) { + return fetch(`${constants.ROOT_URL}/themes`, { + method: "POST", + headers: this.header(), + credentials: "same-origin", + body: JSON.stringify(body), + }).then(async (r) => { + handleError(r); + return r.json(); + }); + } + updateTheme(id, body) { + return fetch(`${constants.ROOT_URL}/themes/${encodeURIComponent(id)}`, { + method: "PUT", + headers: this.header(), + credentials: "same-origin", + body: JSON.stringify(body), + }).then(async (r) => { + handleError(r); + return r.json(); + }); + } + publishTheme(id, published = true) { + return fetch(`${constants.ROOT_URL}/themes/${encodeURIComponent(id)}/publish`, { + method: "POST", + headers: this.header(), + credentials: "same-origin", + body: JSON.stringify({ published }), + }).then(async (r) => { + handleError(r); + return r.json(); + }); + } + deleteTheme(id) { + return fetch(`${constants.ROOT_URL}/themes/${encodeURIComponent(id)}`, { + method: "DELETE", + headers: this.header(), + credentials: "same-origin", + }).then((r) => handleError(r)); + } +} + +function removeUser(){ + localStorage.removeItem("currentUser"); + localStorage.removeItem("authToken"); +} +function handleError(r) { + if (!r.ok) { + if (r.status === 401) { + removeUser(); + window.location.reload(true); + return + } + if (r.headers.get("Content-Type").startsWith("application/json")) { + return r.json().then(d => {throw new Error(d.error)}); + } + if (r.status === 400) { + return r.text().then(text => {throw new Error(text)}) + } + return Promise.reject(r.status) + } +} + +var apiServices = new ApiServices(); + + global.apiService = apiServices; + global.ApiServices = ApiServices; +})(typeof window !== "undefined" ? window : globalThis); diff --git a/internal/ui/static/js/legacy/auth.js b/internal/ui/static/js/legacy/auth.js new file mode 100644 index 00000000..ccd64f15 --- /dev/null +++ b/internal/ui/static/js/legacy/auth.js @@ -0,0 +1,98 @@ +(function (global) { + "use strict"; + var RM = global.RM; + if (!RM) throw new Error("rm.js must load before auth.js"); + + var user = null; + try { + user = localStorage.getItem("currentUser") + ? JSON.parse(localStorage.getItem("currentUser")) + : null; + } catch (_) { + user = null; + } + + var store = { + state: { + user: user || "", + loading: false, + errorMessage: null, + }, + listeners: [], + }; + + function emit() { + store.listeners.slice().forEach(function (fn) { + try { + fn(); + } catch (e) { + console.error(e); + } + }); + } + + function authReducer(state, action) { + switch (action.type) { + case "REQUEST_LOGIN": + return Object.assign({}, state, { loading: true }); + case "LOGIN_SUCCESS": + return Object.assign({}, state, { user: action.payload.user, loading: false, errorMessage: null }); + case "LOGOUT": + return Object.assign({}, state, { user: "" }); + case "LOGIN_ERROR": + return Object.assign({}, state, { loading: false, errorMessage: action.error }); + default: + throw new Error("Unhandled action type: " + action.type); + } + } + + function dispatch(action) { + store.state = authReducer(store.state, action); + emit(); + } + + function useAuthState() { + var tick = RM.useState(0); + var setTick = tick[1]; + RM.useEffect(function () { + var sub = function () { + setTick(function (n) { + return n + 1; + }); + }; + store.listeners.push(sub); + return function () { + store.listeners = store.listeners.filter(function (x) { + return x !== sub; + }); + }; + }, []); + return { state: store.state, dispatch: dispatch }; + } + + function AuthProvider(props) { + return RM.h("div", { className: "rm-auth-provider", style: { display: "contents" } }, props.children); + } + + async function loginUser(dispatchFn, loginPayload) { + var d = dispatchFn || dispatch; + try { + d({ type: "REQUEST_LOGIN" }); + var u = await global.apiService.login(loginPayload); + d({ type: "LOGIN_SUCCESS", payload: { user: u } }); + } catch (error) { + d({ type: "LOGIN_ERROR", error: "Can't login: " + error.message }); + } + } + + async function logout(dispatchFn) { + var d = dispatchFn || dispatch; + await global.apiService.logout(); + d({ type: "LOGOUT" }); + } + + global.useAuthState = useAuthState; + global.AuthProvider = AuthProvider; + global.loginUser = loginUser; + global.logoutAction = logout; +})(typeof window !== "undefined" ? window : globalThis); diff --git a/internal/ui/static/js/legacy/constants.js b/internal/ui/static/js/legacy/constants.js new file mode 100644 index 00000000..1b4badb5 --- /dev/null +++ b/internal/ui/static/js/legacy/constants.js @@ -0,0 +1,5 @@ +(function (global) { + "use strict"; + var constants = { ROOT_URL: "/ui/api" }; + global.constants = constants; +})(typeof window !== "undefined" ? window : globalThis); diff --git a/internal/ui/static/js/legacy/index.js b/internal/ui/static/js/legacy/index.js new file mode 100644 index 00000000..9f9a0f4f --- /dev/null +++ b/internal/ui/static/js/legacy/index.js @@ -0,0 +1,8 @@ +(function (global) { + "use strict"; + // Load order documented in chrome.js / shell.xsl: + // constants → api.service → xslt → auth → theme → useFetch → toast → link → pagination + global.RMLegacy = { + ready: true, + }; +})(typeof window !== "undefined" ? window : globalThis); diff --git a/internal/ui/static/js/legacy/link.js b/internal/ui/static/js/legacy/link.js new file mode 100644 index 00000000..b7b9bb3e --- /dev/null +++ b/internal/ui/static/js/legacy/link.js @@ -0,0 +1,18 @@ +(function (global) { + "use strict"; + var RM = global.RM; + function Link(props) { + props = props || {}; + return RM.h( + "a", + { + href: props.to || props.href || "#", + className: props.className, + "aria-current": props["aria-current"], + onClick: props.onClick, + }, + props.children + ); + } + global.Link = Link; +})(typeof window !== "undefined" ? window : globalThis); diff --git a/internal/ui/static/js/legacy/pagination.js b/internal/ui/static/js/legacy/pagination.js new file mode 100644 index 00000000..be6f77ba --- /dev/null +++ b/internal/ui/static/js/legacy/pagination.js @@ -0,0 +1,183 @@ +(function (global) { + "use strict"; + var RM = global.RM; + var STORAGE_KEY = "rm-settings-page-size"; + + function usePagination(items, opts) { + opts = opts || {}; + var defaultSize = opts.pageSize || 10; + try { + var stored = parseInt(localStorage.getItem(STORAGE_KEY) || "", 10); + if (stored === 5 || stored === 10 || stored === 25) defaultSize = stored; + } catch (_) {} + var pageState = RM.useState(0); + var page = pageState[0]; + var setPage = pageState[1]; + var sizeState = RM.useState(defaultSize); + var pageSize = sizeState[0]; + var setPageSizeRaw = sizeState[1]; + var list = items || []; + var pageCount = Math.max(1, Math.ceil(list.length / pageSize) || 1); + if (page > pageCount - 1) { + // clamp on next render + } + var safePage = Math.min(page, pageCount - 1); + var start = safePage * pageSize; + var pageItems = list.slice(start, start + pageSize); + + function setPageSize(n) { + setPageSizeRaw(n); + setPage(0); + try { + localStorage.setItem(STORAGE_KEY, String(n)); + } catch (_) {} + } + + function Pager() { + if (list.length <= pageSize && pageSize === defaultSize && list.length <= 10) { + // still show pager if more than page size + } + if (list.length === 0) return null; + return RM.h( + "div", + { className: "rm-pager", role: "navigation", "aria-label": "Pagination" }, + RM.h( + "button", + { + type: "button", + className: "btn btn-secondary btn-sm", + disabled: safePage <= 0, + onClick: function () { + setPage(Math.max(0, safePage - 1)); + }, + }, + "Previous" + ), + RM.h( + "span", + { className: "rm-pager-status" }, + "Page " + (safePage + 1) + " of " + pageCount + ), + RM.h( + "button", + { + type: "button", + className: "btn btn-secondary btn-sm", + disabled: safePage >= pageCount - 1, + onClick: function () { + setPage(Math.min(pageCount - 1, safePage + 1)); + }, + }, + "Next" + ), + RM.h( + "label", + { className: "rm-pager-size" }, + "Per page ", + RM.h( + "select", + { + value: String(pageSize), + "aria-label": "Page size", + onChange: function (e) { + setPageSize(parseInt(e.target.value, 10)); + }, + }, + RM.h("option", { value: "5" }, "5"), + RM.h("option", { value: "10" }, "10"), + RM.h("option", { value: "25" }, "25") + ) + ) + ); + } + + return { + page: safePage, + pageSize: pageSize, + pageCount: pageCount, + pageItems: pageItems, + setPage: setPage, + setPageSize: setPageSize, + Pager: Pager, + }; + } + + /** Enhance a static HTML table: hide rows not on current page. */ + function enhanceTable(tableSelector, opts) { + opts = opts || {}; + var table = document.querySelector(tableSelector); + if (!table || !table.tBodies || !table.tBodies[0]) return; + var tbody = table.tBodies[0]; + var rows = Array.prototype.slice.call(tbody.rows); + if (!rows.length) return; + var pageSize = opts.pageSize || 10; + try { + var stored = parseInt(localStorage.getItem(STORAGE_KEY) || "", 10); + if (stored === 5 || stored === 10 || stored === 25) pageSize = stored; + } catch (_) {} + var page = 0; + var host = document.createElement("div"); + host.className = "rm-pager"; + table.parentNode.insertBefore(host, table.nextSibling); + + function render() { + var pageCount = Math.max(1, Math.ceil(rows.length / pageSize)); + if (page >= pageCount) page = pageCount - 1; + rows.forEach(function (row, i) { + var show = i >= page * pageSize && i < (page + 1) * pageSize; + row.hidden = !show; + }); + host.innerHTML = ""; + var prev = document.createElement("button"); + prev.type = "button"; + prev.className = "btn btn-secondary btn-sm"; + prev.textContent = "Previous"; + prev.disabled = page <= 0; + prev.onclick = function () { + page--; + render(); + }; + var status = document.createElement("span"); + status.className = "rm-pager-status"; + status.textContent = "Page " + (page + 1) + " of " + pageCount; + var next = document.createElement("button"); + next.type = "button"; + next.className = "btn btn-secondary btn-sm"; + next.textContent = "Next"; + next.disabled = page >= pageCount - 1; + next.onclick = function () { + page++; + render(); + }; + var label = document.createElement("label"); + label.className = "rm-pager-size"; + label.appendChild(document.createTextNode("Per page ")); + var sel = document.createElement("select"); + sel.setAttribute("aria-label", "Page size"); + [5, 10, 25].forEach(function (n) { + var o = document.createElement("option"); + o.value = String(n); + o.textContent = String(n); + if (n === pageSize) o.selected = true; + sel.appendChild(o); + }); + sel.onchange = function () { + pageSize = parseInt(sel.value, 10); + page = 0; + try { + localStorage.setItem(STORAGE_KEY, String(pageSize)); + } catch (_) {} + render(); + }; + label.appendChild(sel); + host.appendChild(prev); + host.appendChild(status); + host.appendChild(next); + host.appendChild(label); + } + render(); + } + + global.usePagination = usePagination; + global.enhanceTablePagination = enhanceTable; +})(typeof window !== "undefined" ? window : globalThis); diff --git a/internal/ui/static/js/legacy/theme.js b/internal/ui/static/js/legacy/theme.js new file mode 100644 index 00000000..ef3f3d64 --- /dev/null +++ b/internal/ui/static/js/legacy/theme.js @@ -0,0 +1,153 @@ +(function (global) { + "use strict"; + var RM = global.RM; + var X = global.RMXslt; + if (!RM || !X) throw new Error("rm.js and xslt.js required for theme.js"); + + function detectFormFactor() { + try { + if (window.matchMedia && window.matchMedia("(max-width: 768px)").matches) return "mobile"; + } catch (_) {} + return "desktop"; + } + + var store = { + layout: X.defaultLayout(), + themeId: "default", + formFactor: detectFormFactor(), + colorOverrides: {}, + loading: true, + listeners: [], + }; + + function emit() { + store.listeners.slice().forEach(function (fn) { + try { + fn(); + } catch (e) { + console.error(e); + } + }); + } + + function patch(partial) { + Object.assign(store, partial); + emit(); + } + + var xslCache = null; + + async function loadXsl() { + if (xslCache) return xslCache; + var pair = await Promise.all([ + X.fetchXML("/ui/api/themes/assets/theme-to-css.xsl"), + X.fetchXML("/ui/api/themes/assets/theme-to-layout.xsl"), + ]); + xslCache = { cssXsl: pair[0], layoutXsl: pair[1] }; + return xslCache; + } + + async function applyThemeXML(xmlString, overrides, factor) { + overrides = overrides || {}; + factor = factor || detectFormFactor(); + try { + var cache = await loadXsl(); + var themeDoc = X.parseXMLString(xmlString); + themeDoc = X.applyColorOverrides(themeDoc, overrides); + themeDoc = X.applyFormFactor(themeDoc, factor); + var css = X.transformToText(themeDoc, cache.cssXsl); + X.injectThemeCSS(css); + var layoutDoc = X.transformWithXSLT(themeDoc, cache.layoutXsl); + var parsed = X.parseLayoutDocument(layoutDoc); + parsed.formFactor = factor; + patch({ layout: parsed, formFactor: factor }); + } catch (e) { + console.warn("theme apply failed", e); + patch({ layout: X.defaultLayout() }); + } + } + + async function reload() { + patch({ loading: true }); + try { + var tid = "default"; + var overrides = {}; + var factor = detectFormFactor(); + var auth = global.useAuthState ? global.useAuthState() : null; + var user = auth && auth.state && auth.state.user; + if (user) { + try { + var pref = await global.apiService.getProfileTheme(); + tid = pref.themeId || "default"; + overrides = pref.themeColorOverrides || {}; + if (pref.formFactor) factor = pref.formFactor; + } catch (_) {} + } + var theme = await global.apiService.getTheme(tid); + if (detectFormFactor() === "mobile") factor = "mobile"; + patch({ themeId: tid, colorOverrides: overrides }); + await applyThemeXML(theme.xml, overrides, factor); + } catch (e) { + console.warn(e); + patch({ themeId: "default", layout: X.defaultLayout() }); + } finally { + patch({ loading: false }); + } + } + + async function applyThemeId(id, overrides) { + var theme = await global.apiService.getTheme(id); + patch({ themeId: id, colorOverrides: overrides || store.colorOverrides }); + await applyThemeXML(theme.xml, overrides || store.colorOverrides, store.formFactor); + } + + function useShellTheme() { + var tick = RM.useState(0); + var setTick = tick[1]; + RM.useEffect(function () { + var sub = function () { + setTick(function (n) { + return n + 1; + }); + }; + store.listeners.push(sub); + return function () { + store.listeners = store.listeners.filter(function (x) { + return x !== sub; + }); + }; + }, []); + return { + layout: store.layout, + themeId: store.themeId, + formFactor: store.formFactor, + colorOverrides: store.colorOverrides, + loading: store.loading, + reload: reload, + applyThemeId: applyThemeId, + }; + } + + function ThemeProvider(props) { + RM.useEffect(function () { + reload(); + var onResize = function () { + var f = detectFormFactor(); + if (f !== store.formFactor) { + patch({ formFactor: f }); + reload(); + } + }; + window.addEventListener("resize", onResize); + return function () { + window.removeEventListener("resize", onResize); + }; + }, []); + return RM.h("div", { className: "rm-theme-provider", style: { display: "contents" } }, props.children); + } + + global.useShellTheme = useShellTheme; + global.ThemeProvider = ThemeProvider; + global.detectFormFactor = detectFormFactor; + global.reloadShellTheme = reload; +})(typeof window !== "undefined" ? window : globalThis); diff --git a/internal/ui/static/js/legacy/toast.js b/internal/ui/static/js/legacy/toast.js new file mode 100644 index 00000000..7c7289c9 --- /dev/null +++ b/internal/ui/static/js/legacy/toast.js @@ -0,0 +1,39 @@ +(function (global) { + "use strict"; + function ensureHost() { + var el = document.getElementById("rm-toast-host"); + if (el) return el; + el = document.createElement("div"); + el.id = "rm-toast-host"; + el.setAttribute("aria-live", "polite"); + el.style.cssText = + "position:fixed;z-index:99999;right:1rem;bottom:1rem;display:flex;flex-direction:column;gap:0.5rem;max-width:20rem;"; + document.body.appendChild(el); + return el; + } + function show(type, msg) { + var host = ensureHost(); + var item = document.createElement("div"); + item.className = "rm-toast rm-toast-" + type; + item.textContent = String(msg); + item.style.cssText = + "padding:0.65rem 0.85rem;border-radius:0.35rem;background:#211e1c;color:#f8f7f6;border:1px solid rgba(255,255,255,0.15);box-shadow:0 8px 24px rgba(0,0,0,0.35);font:inherit;"; + if (type === "error") item.style.borderColor = "#ff1744"; + if (type === "success") item.style.borderColor = "#00e676"; + host.appendChild(item); + setTimeout(function () { + if (item.parentNode) item.parentNode.removeChild(item); + }, 4000); + } + global.toast = { + success: function (m) { + show("success", m); + }, + error: function (m) { + show("error", m); + }, + info: function (m) { + show("info", m); + }, + }; +})(typeof window !== "undefined" ? window : globalThis); diff --git a/internal/ui/static/js/legacy/useFetch.js b/internal/ui/static/js/legacy/useFetch.js new file mode 100644 index 00000000..8aea8ad0 --- /dev/null +++ b/internal/ui/static/js/legacy/useFetch.js @@ -0,0 +1,53 @@ +(function (global) { + "use strict"; + var RM = global.RM; + function useFetch(url, options) { + var loadingState = RM.useState(true); + var loading = loadingState[0]; + var setLoading = loadingState[1]; + var dataState = RM.useState(null); + var data = dataState[0]; + var setData = dataState[1]; + var errState = RM.useState(null); + var error = errState[0]; + var setError = errState[1]; + var constants = global.constants || { ROOT_URL: "/ui/api" }; + + RM.useEffect( + function () { + var cancelled = false; + (async function () { + try { + var response = await fetch(constants.ROOT_URL + "/" + url, { + method: "GET", + credentials: "same-origin", + }); + if (cancelled) return; + if (response.ok) { + setData(await response.json()); + } else if (response.status === 401) { + localStorage.removeItem("currentUser"); + window.location.replace("/"); + } else { + throw response; + } + } catch (e) { + if (!cancelled) { + console.error("fetch failed: ", e); + setError(e); + } + } finally { + if (!cancelled) setLoading(false); + } + })(); + return function () { + cancelled = true; + }; + }, + [url, options] + ); + + return { data: data, error: error, loading: loading }; + } + global.useFetch = useFetch; +})(typeof window !== "undefined" ? window : globalThis); diff --git a/internal/ui/static/js/legacy/xslt.js b/internal/ui/static/js/legacy/xslt.js new file mode 100644 index 00000000..103eecad --- /dev/null +++ b/internal/ui/static/js/legacy/xslt.js @@ -0,0 +1,464 @@ +(function (global) { +"use strict"; +/** Apply XSLT 1.0 in the browser; returns a Document or text depending on stylesheet output. */ +async function fetchXML(url) { + const r = await fetch(url, { credentials: "same-origin" }); + if (!r.ok) throw new Error(`Failed to fetch ${url}`); + const text = await r.text(); + return new DOMParser().parseFromString(text, "application/xml"); +} + +function parseXMLString(xmlString) { + return new DOMParser().parseFromString(xmlString, "application/xml"); +} + +function applyColorOverrides(themeDoc, overrides) { + if (!overrides || !Object.keys(overrides).length) return themeDoc; + const colors = themeDoc.querySelector("colors"); + if (!colors) return themeDoc; + const clone = themeDoc.cloneNode(true); + const c = clone.querySelector("colors"); + Object.entries(overrides).forEach(([key, val]) => { + if (val) c.setAttribute(key, val); + }); + return clone; +} + +function transformWithXSLT(xmlDoc, xslDoc) { + if (typeof XSLTProcessor === "undefined") { + throw new Error("XSLTProcessor not supported"); + } + const proc = new XSLTProcessor(); + proc.importStylesheet(xslDoc); + return proc.transformToDocument(xmlDoc); +} + +function transformToText(xmlDoc, xslDoc) { + if (typeof XSLTProcessor === "undefined") { + throw new Error("XSLTProcessor not supported"); + } + const proc = new XSLTProcessor(); + proc.importStylesheet(xslDoc); + const frag = proc.transformToFragment(xmlDoc, document); + return frag?.textContent || ""; +} + +const STYLE_ID = "rm-shell-theme"; + +function injectThemeCSS(cssText) { + let el = document.getElementById(STYLE_ID); + if (!el) { + el = document.createElement("style"); + el.id = STYLE_ID; + document.head.appendChild(el); + } + el.textContent = cssText || ""; +} + +function defaultChromePrefs() { + return { + style: "remarkable", + folderColor: "#d4b483", + tabColor: "#c4a574", + outlineColor: "#e8e3d9", + drawerColor: "#4a4035", + labelColor: "#f8f7f6", + }; +} + +function normalizeChromeStyle(style) { + if (style === "remarkable" || style === "googledocs" || style === "icloud" || style === "os") { + return style; + } + return "remarkable"; +} + +function chromeFromElement(el) { + const d = defaultChromePrefs(); + if (!el) return d; + return { + style: normalizeChromeStyle(el.getAttribute("style") || d.style), + folderColor: el.getAttribute("folder-color") || d.folderColor, + tabColor: el.getAttribute("tab-color") || d.tabColor, + outlineColor: el.getAttribute("outline-color") || d.outlineColor, + drawerColor: el.getAttribute("drawer-color") || d.drawerColor, + labelColor: el.getAttribute("label-color") || d.labelColor, + }; +} + +function chromeXML(chrome, indent) { + const c = { ...defaultChromePrefs(), ...(chrome || {}) }; + c.style = normalizeChromeStyle(c.style); + return `${indent}`; +} + +function defaultConnectPrefs() { + return { + gaugeType: "circle", + trackColor: "#3a3f44", + fillColor: "#EE7B30", + textColor: "#f8f7f6", + promptLocation: "above", + promptStyle: "plain", + promptBg: "#212529", + promptFg: "#e8e3d9", + promptBorder: "#e8e3d9", + fontFamily: "system", + fontSize: "lg", + codeColor: "#f8f7f6", + }; +} + +function connectFromElement(el) { + const d = defaultConnectPrefs(); + if (!el) return d; + return { + gaugeType: el.getAttribute("gauge-type") || d.gaugeType, + trackColor: el.getAttribute("track-color") || d.trackColor, + fillColor: el.getAttribute("fill-color") || d.fillColor, + textColor: el.getAttribute("text-color") || d.textColor, + promptLocation: el.getAttribute("prompt-location") || d.promptLocation, + promptStyle: el.getAttribute("prompt-style") || d.promptStyle, + promptBg: el.getAttribute("prompt-bg") || d.promptBg, + promptFg: el.getAttribute("prompt-fg") || d.promptFg, + promptBorder: el.getAttribute("prompt-border") || d.promptBorder, + fontFamily: el.getAttribute("font-family") || d.fontFamily, + fontSize: el.getAttribute("font-size") || d.fontSize, + codeColor: el.getAttribute("code-color") || d.codeColor, + }; +} + +function parseLayoutDocument(layoutDoc) { + const root = layoutDoc.documentElement; + if (!root || root.nodeName.toLowerCase() !== "layout") { + return defaultLayout(); + } + const iconsEl = root.querySelector("icons"); + const navEl = root.querySelector("nav"); + const loginEl = root.querySelector("login"); + const connectEl = root.querySelector("connect"); + const chromeEl = root.querySelector("chrome"); + const icons = {}; + if (iconsEl) { + ["brand", "documents", "integrations", "connect", "screenshare", "admin", "profile"].forEach((k) => { + icons[k] = iconsEl.getAttribute(k) || k; + }); + } + const items = []; + if (navEl) { + navEl.querySelectorAll("item").forEach((item) => { + items.push({ + id: item.getAttribute("id"), + href: item.getAttribute("href") || "/" + item.getAttribute("id"), + visible: item.getAttribute("visible") !== "false", + adminOnly: item.getAttribute("admin-only") === "true", + icon: item.getAttribute("icon") || icons[item.getAttribute("id")] || item.getAttribute("id"), + }); + }); + } + return { + id: root.getAttribute("id") || "default", + name: root.getAttribute("name") || "Default", + icons, + chrome: chromeFromElement(chromeEl), + nav: { + brandPosition: (navEl && navEl.getAttribute("brand-position")) || "start", + userMenu: (navEl && navEl.getAttribute("user-menu")) || "end", + items: items.length > 0 ? items : defaultLayout().nav.items, + }, + login: { + primaryButton: (loginEl && loginEl.getAttribute("primary-button")) || "end", + passkeyButton: (loginEl && loginEl.getAttribute("passkey-button")) || "start", + showBrand: !loginEl || loginEl.getAttribute("show-brand") !== "false", + }, + connect: connectFromElement(connectEl), + }; +} + +function defaultLayout() { + return { + id: "default", + name: "Default", + icons: { + brand: "cloud", + documents: "folder", + integrations: "puzzle", + connect: "link", + screenshare: "display", + admin: "gear", + profile: "person", + }, + chrome: defaultChromePrefs(), + nav: { + brandPosition: "start", + userMenu: "end", + items: [ + { id: "documents", visible: true, adminOnly: false, icon: "folder" }, + { id: "integrations", visible: true, adminOnly: false, icon: "puzzle" }, + { id: "connect", visible: true, adminOnly: false, icon: "link" }, + { id: "screenshare", visible: true, adminOnly: false, icon: "display" }, + { id: "admin", visible: true, adminOnly: true, icon: "gear" }, + { id: "help", visible: true, adminOnly: false, icon: "book" }, + { id: "profile", visible: true, adminOnly: false, icon: "person" }, + ], + }, + login: { + primaryButton: "end", + passkeyButton: "start", + showBrand: true, + }, + connect: defaultConnectPrefs(), + mobile: defaultMobileLayout(), + }; +} + +function defaultMobileLayout() { + return { + chrome: { + ...defaultChromePrefs(), + style: "remarkable", + }, + nav: { + brandPosition: "start", + userMenu: "end", + items: [ + { id: "documents", visible: true, adminOnly: false }, + { id: "integrations", visible: true, adminOnly: false }, + { id: "connect", visible: true, adminOnly: false }, + { id: "screenshare", visible: true, adminOnly: false }, + { id: "admin", visible: true, adminOnly: true }, + { id: "help", visible: true, adminOnly: false }, + { id: "profile", visible: true, adminOnly: false }, + ], + }, + login: { + primaryButton: "end", + passkeyButton: "start", + showBrand: true, + }, + connect: { + ...defaultConnectPrefs(), + gaugeType: "bar", + promptStyle: "boxed", + fontSize: "md", + promptBorder: "#EE7B30", + }, + }; +} + +function navItemsXML(items, indent) { + return (items || []) + .map( + (it) => + `${indent}` + ) + .join("\n"); +} + +function connectXML(connect, indent) { + const c = { ...defaultConnectPrefs(), ...(connect || {}) }; + return `${indent}`; +} + +function parseNav(navEl, fallbackItems) { + const items = []; + if (navEl) { + navEl.querySelectorAll(":scope > item").forEach((item) => { + items.push({ + id: item.getAttribute("id"), + href: item.getAttribute("href") || "/" + item.getAttribute("id"), + visible: item.getAttribute("visible") !== "false", + adminOnly: item.getAttribute("admin-only") === "true", + }); + }); + } + return { + brandPosition: (navEl && navEl.getAttribute("brand-position")) || "start", + userMenu: (navEl && navEl.getAttribute("user-menu")) || "end", + items: items.length > 0 ? items : fallbackItems, + }; +} + +function parseLogin(loginEl) { + return { + primaryButton: (loginEl && loginEl.getAttribute("primary-button")) || "end", + passkeyButton: (loginEl && loginEl.getAttribute("passkey-button")) || "start", + showBrand: !loginEl || loginEl.getAttribute("show-brand") !== "false", + }; +} + +/** Promote layout/mobile/* over desktop layout nodes when formFactor is mobile. */ +function applyFormFactor(themeDoc, formFactor) { + if (formFactor !== "mobile") return themeDoc; + const mobile = themeDoc.querySelector("layout > mobile"); + if (!mobile) return themeDoc; + const clone = themeDoc.cloneNode(true); + const layout = clone.querySelector("layout"); + const mob = clone.querySelector("layout > mobile"); + if (!layout || !mob) return themeDoc; + ["nav", "login", "connect", "chrome"].forEach((tag) => { + const src = mob.querySelector(`:scope > ${tag}`); + if (!src) return; + const existing = Array.from(layout.children).find((n) => n.nodeName.toLowerCase() === tag); + if (existing) { + layout.replaceChild(src.cloneNode(true), existing); + } else { + layout.insertBefore(src.cloneNode(true), mob); + } + }); + return clone; +} + +function themeXMLFromEditor(state) { + const { id, name, published, colors, icons, nav, login, connect, chrome, mobile } = state; + const colorAttrs = Object.entries(colors) + .map(([k, v]) => `${k}="${v}"`) + .join(" "); + const iconAttrs = Object.entries(icons) + .map(([k, v]) => `${k}="${v}"`) + .join(" "); + const mob = { ...defaultMobileLayout(), ...(mobile || {}) }; + mob.chrome = { ...defaultMobileLayout().chrome, ...(mobile?.chrome || {}) }; + mob.nav = { ...defaultMobileLayout().nav, ...(mobile?.nav || {}) }; + mob.login = { ...defaultMobileLayout().login, ...(mobile?.login || {}) }; + mob.connect = { ...defaultMobileLayout().connect, ...(mobile?.connect || {}) }; + + return ` + + + + +${chromeXML(chrome, " ")} + + +${connectXML(connect, " ")} + +${chromeXML(mob.chrome, " ")} + + +${connectXML(mob.connect, " ")} + + + +`; +} + +function escapeXml(s) { + return String(s) + .replace(/&/g, "&") + .replace(/"/g, """) + .replace(/ nav"); + const loginEl = doc.querySelector("layout > login"); + const connectEl = doc.querySelector("layout > connect"); + const chromeEl = doc.querySelector("layout > chrome"); + const mobileEl = doc.querySelector("layout > mobile"); + const colors = {}; + const icons = {}; + if (colorsEl) { + [...colorsEl.attributes].forEach((a) => { + colors[a.name] = a.value; + }); + } + if (iconsEl) { + [...iconsEl.attributes].forEach((a) => { + icons[a.name] = a.value; + }); + } + const fallbackItems = defaultLayout().nav.items.map(({ id, visible, adminOnly }) => ({ + id, + visible, + adminOnly, + })); + const mobileFallback = defaultMobileLayout(); + return { + id: theme.getAttribute("id") || "untitled", + name: theme.getAttribute("name") || "Untitled", + published: theme.getAttribute("published") !== "false", + colors: { + background1: "#212529", + background2: "#0f0f0f", + foreground1: "#f8f7f6", + foreground2: "#e8e3d9", + foreground3: "#e4dbaf", + action: "#EE7B30", + accept: "#00e676", + reject: "#ff1744", + ...colors, + }, + icons: { + brand: "cloud", + documents: "folder", + integrations: "puzzle", + connect: "link", + screenshare: "display", + admin: "gear", + profile: "person", + ...icons, + }, + chrome: chromeFromElement(chromeEl), + nav: parseNav(navEl, fallbackItems), + login: parseLogin(loginEl), + connect: connectFromElement(connectEl), + mobile: { + chrome: chromeFromElement(mobileEl && mobileEl.querySelector(":scope > chrome")), + nav: parseNav(mobileEl && mobileEl.querySelector(":scope > nav"), mobileFallback.nav.items), + login: parseLogin(mobileEl && mobileEl.querySelector(":scope > login")), + connect: connectFromElement(mobileEl && mobileEl.querySelector(":scope > connect")), + }, + }; +} + +global.RMXslt = { + fetchXML: fetchXML, + parseXMLString: parseXMLString, + applyColorOverrides: applyColorOverrides, + applyFormFactor: applyFormFactor, + transformToText: transformToText, + transformWithXSLT: transformWithXSLT, + injectThemeCSS: injectThemeCSS, + parseLayoutDocument: parseLayoutDocument, + defaultLayout: defaultLayout, + normalizeChromeStyle: normalizeChromeStyle, + chromeStyles: ["remarkable", "googledocs", "icloud", "os"], + themeXMLFromEditor: typeof themeXMLFromEditor !== "undefined" ? themeXMLFromEditor : null, + editorStateFromXML: typeof editorStateFromXML !== "undefined" ? editorStateFromXML : null, +}; +})(typeof window !== "undefined" ? window : globalThis); diff --git a/internal/ui/static/js/pdfview.js b/internal/ui/static/js/pdfview.js new file mode 100644 index 00000000..a68aaa10 --- /dev/null +++ b/internal/ui/static/js/pdfview.js @@ -0,0 +1,99 @@ +(function () { + "use strict"; + + var PDFJS_CDN = "https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.min.js"; + var WORKER_CDN = "https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.worker.min.js"; + + function loadScript(src) { + return new Promise(function (resolve, reject) { + var existing = document.querySelector('script[src="' + src + '"]'); + if (existing && window.pdfjsLib) { + resolve(); + return; + } + var s = document.createElement("script"); + s.src = src; + s.async = true; + s.onload = function () { + resolve(); + }; + s.onerror = function () { + reject(new Error("Failed to load " + src)); + }; + document.head.appendChild(s); + }); + } + + async function ensurePdfJs() { + if (window.pdfjsLib) return window.pdfjsLib; + await loadScript(PDFJS_CDN); + if (!window.pdfjsLib) throw new Error("pdfjsLib not available after CDN load"); + window.pdfjsLib.GlobalWorkerOptions.workerSrc = WORKER_CDN; + return window.pdfjsLib; + } + + async function renderPdf(url, container) { + var pdfjsLib = await ensurePdfJs(); + container.textContent = "Loading PDF…"; + + var loadingTask = pdfjsLib.getDocument({ + url: url, + withCredentials: true, + }); + var pdf = await loadingTask.promise; + container.textContent = ""; + + var scale = parseFloat(container.getAttribute("data-scale") || "1.25"); + if (!Number.isFinite(scale) || scale <= 0) scale = 1.25; + + for (var pageNum = 1; pageNum <= pdf.numPages; pageNum++) { + var page = await pdf.getPage(pageNum); + var viewport = page.getViewport({ scale: scale }); + + var wrap = document.createElement("div"); + wrap.className = "pdf-page"; + wrap.setAttribute("data-page", String(pageNum)); + + var canvas = document.createElement("canvas"); + canvas.width = viewport.width; + canvas.height = viewport.height; + canvas.setAttribute("aria-label", "Page " + pageNum); + wrap.appendChild(canvas); + container.appendChild(wrap); + + var ctx = canvas.getContext("2d"); + await page.render({ canvasContext: ctx, viewport: viewport }).promise; + } + } + + async function init() { + var viewer = document.getElementById("pdf-viewer"); + if (!viewer) return; + + var url = viewer.getAttribute("data-doc-url"); + if (!url) { + console.error("[pdfview] missing data-doc-url on #pdf-viewer"); + return; + } + + var container = document.getElementById("pdf-canvas-container"); + if (!container) { + container = document.createElement("div"); + container.id = "pdf-canvas-container"; + viewer.appendChild(container); + } + + try { + await renderPdf(url, container); + } catch (e) { + console.error("[pdfview]", e); + container.textContent = "Failed to load PDF: " + (e.message || String(e)); + } + } + + if (document.readyState === "loading") { + document.addEventListener("DOMContentLoaded", init); + } else { + init(); + } +})(); diff --git a/internal/ui/static/js/rm.js b/internal/ui/static/js/rm.js new file mode 100644 index 00000000..3e39ab2d --- /dev/null +++ b/internal/ui/static/js/rm.js @@ -0,0 +1,410 @@ +/** + * Minimal React-like runtime (no JSX). Function components + hooks. + * Exposed as window.RM + */ +(function (global) { + "use strict"; + + var hookIndex = 0; + var hooks = []; + var effects = []; + var pendingEffects = []; + var currentComponent = null; + var renderScheduled = false; + var rootContainer = null; + var rootVNode = null; + var contextStack = []; + + function scheduleRender() { + if (renderScheduled || !rootContainer || !rootVNode) return; + renderScheduled = true; + Promise.resolve().then(function () { + renderScheduled = false; + flushRender(); + }); + } + + function flushRender() { + if (!rootContainer || !rootVNode) return; + hookIndex = 0; + effects = []; + hooks = rootContainer.__rmRootHooks || (rootContainer.__rmRootHooks = []); + currentComponent = rootContainer; + var vnode; + if (rootVNode && rootVNode.__isComponentRoot) { + vnode = rootVNode.type(rootVNode.props || {}); + } else if (typeof rootVNode === "function") { + vnode = rootVNode(); + } else { + vnode = rootVNode; + } + pendingEffects = pendingEffects.concat(effects); + effects = []; + if (rootContainer.__rmVNode) { + diff(rootContainer, vnode, rootContainer.__rmVNode, 0); + } else { + while (rootContainer.firstChild) rootContainer.removeChild(rootContainer.firstChild); + rootContainer.appendChild(createNode(vnode)); + } + rootContainer.__rmVNode = vnode; + runEffects(); + } + + function runEffects() { + var list = pendingEffects.slice(); + pendingEffects = []; + list.forEach(function (fx) { + if (fx.cleanup) { + try { + fx.cleanup(); + } catch (e) { + console.error(e); + } + } + var cleanup = fx.fn(); + if (typeof cleanup === "function") fx.cleanup = cleanup; + }); + } + + function h(type, props) { + var children = []; + for (var i = 2; i < arguments.length; i++) { + var c = arguments[i]; + if (c == null || c === false) continue; + if (Array.isArray(c)) children = children.concat(c); + else children.push(c); + } + props = props || {}; + if (children.length) props.children = children.length === 1 ? children[0] : children; + return { type: type, props: props, key: props.key }; + } + + function normalizeChildren(ch) { + if (ch == null || ch === false) return []; + if (!Array.isArray(ch)) return [ch]; + var out = []; + ch.forEach(function (c) { + if (c == null || c === false) return; + if (Array.isArray(c)) out = out.concat(normalizeChildren(c)); + else out.push(c); + }); + return out; + } + + function createNode(vnode) { + if (vnode == null || vnode === false) return document.createComment(""); + if (typeof vnode === "string" || typeof vnode === "number") { + return document.createTextNode(String(vnode)); + } + if (typeof vnode.type === "function") { + return mountComponent(vnode); + } + var el = document.createElement(vnode.type); + applyProps(el, {}, vnode.props || {}); + var kids = normalizeChildren(vnode.props && vnode.props.children); + kids.forEach(function (kid) { + el.appendChild(createNode(kid)); + }); + el.__rmVNode = vnode; + return el; + } + + function mountComponent(vnode) { + var holder = document.createDocumentFragment(); + var wrap = document.createElement("div"); + wrap.style.display = "contents"; + wrap.__rmComponent = vnode.type; + wrap.__rmProps = vnode.props || {}; + wrap.__rmHooks = []; + var prevHooks = hooks; + var prevIndex = hookIndex; + var prevComp = currentComponent; + hooks = wrap.__rmHooks; + hookIndex = 0; + currentComponent = wrap; + var rendered = vnode.type(wrap.__rmProps); + currentComponent = prevComp; + hookIndex = prevIndex; + hooks = prevHooks; + var node = createNode(rendered); + wrap.appendChild(node); + wrap.__rmChildVNode = rendered; + // Return wrap so we have a stable DOM anchor + // effects collected during render are queued + pendingEffects = pendingEffects.concat(effects); + effects = []; + return wrap; + } + + function applyProps(el, oldProps, newProps) { + oldProps = oldProps || {}; + newProps = newProps || {}; + var key; + for (key in oldProps) { + if (key === "children" || key === "key") continue; + if (!(key in newProps)) { + if (key === "className") el.removeAttribute("class"); + else if (key.startsWith("on") && typeof oldProps[key] === "function") { + el.removeEventListener(key.slice(2).toLowerCase(), oldProps[key]); + } else if (key === "style") el.removeAttribute("style"); + else if (key === "ref") { + /* noop */ + } else el.removeAttribute(key); + } + } + for (key in newProps) { + if (key === "children" || key === "key") continue; + var val = newProps[key]; + if (oldProps[key] === val) continue; + if (key === "className") { + el.setAttribute("class", val || ""); + } else if (key === "style" && val && typeof val === "object") { + Object.keys(val).forEach(function (k) { + el.style[k] = val[k]; + }); + } else if (key === "dangerouslySetInnerHTML" && val) { + el.innerHTML = val.__html || ""; + } else if (key === "ref") { + if (typeof val === "function") val(el); + else if (val && typeof val === "object") val.current = el; + } else if (key.startsWith("on") && typeof val === "function") { + var ev = key.slice(2).toLowerCase(); + if (typeof oldProps[key] === "function") el.removeEventListener(ev, oldProps[key]); + el.addEventListener(ev, val); + } else if (key === "checked" || key === "value" || key === "selected") { + el[key] = val; + } else if (val === false || val == null) { + el.removeAttribute(key); + } else if (val === true) { + el.setAttribute(key, ""); + } else { + el.setAttribute(key, String(val)); + } + } + } + + function diff(parent, newVNode, oldVNode, index) { + index = index || 0; + // Simplified: replace children of parent for shell roots + if (!oldVNode) { + parent.appendChild(createNode(newVNode)); + return; + } + if (!newVNode) { + if (parent.childNodes[index]) parent.removeChild(parent.childNodes[index]); + return; + } + if (typeof newVNode === "string" || typeof newVNode === "number") { + var text = String(newVNode); + var cur = parent.childNodes[index]; + if (cur && cur.nodeType === 3) cur.nodeValue = text; + else { + var tn = document.createTextNode(text); + if (cur) parent.replaceChild(tn, cur); + else parent.appendChild(tn); + } + return; + } + if (typeof newVNode.type === "function") { + var host = parent.childNodes[index]; + if (!host || host.__rmComponent !== newVNode.type) { + var created = createNode(newVNode); + if (host) parent.replaceChild(created, host); + else parent.appendChild(created); + return; + } + host.__rmProps = newVNode.props || {}; + var prevH = hooks; + var prevI = hookIndex; + var prevC = currentComponent; + hooks = host.__rmHooks; + hookIndex = 0; + currentComponent = host; + effects = []; + var rendered = newVNode.type(host.__rmProps); + currentComponent = prevC; + hookIndex = prevI; + hooks = prevH; + pendingEffects = pendingEffects.concat(effects); + effects = []; + if (host.__rmChildVNode) { + diff(host, rendered, host.__rmChildVNode, 0); + } else { + while (host.firstChild) host.removeChild(host.firstChild); + host.appendChild(createNode(rendered)); + } + host.__rmChildVNode = rendered; + return; + } + var el = parent.childNodes[index]; + if (!el || el.nodeType !== 1 || el.tagName.toLowerCase() !== String(newVNode.type).toLowerCase()) { + var fresh = createNode(newVNode); + if (el) parent.replaceChild(fresh, el); + else parent.appendChild(fresh); + return; + } + applyProps(el, (oldVNode && oldVNode.props) || {}, newVNode.props || {}); + var newKids = normalizeChildren(newVNode.props && newVNode.props.children); + var oldKids = normalizeChildren(oldVNode && oldVNode.props && oldVNode.props.children); + var max = Math.max(newKids.length, oldKids.length); + for (var i = 0; i < max; i++) { + if (i >= newKids.length) { + while (el.childNodes.length > newKids.length) el.removeChild(el.lastChild); + break; + } + if (i >= oldKids.length) el.appendChild(createNode(newKids[i])); + else diff(el, newKids[i], oldKids[i], i); + } + el.__rmVNode = newVNode; + } + + function useState(initial) { + var i = hookIndex++; + if (hooks[i] === undefined) { + hooks[i] = typeof initial === "function" ? initial() : initial; + } + var setState = (function (idx) { + return function (next) { + var cur = hooks[idx]; + var val = typeof next === "function" ? next(cur) : next; + if (Object.is(val, cur)) return; + hooks[idx] = val; + scheduleRender(); + }; + })(i); + return [hooks[i], setState]; + } + + function useReducer(reducer, initialArg, init) { + var i = hookIndex++; + if (hooks[i] === undefined) { + hooks[i] = init ? init(initialArg) : initialArg; + } + var dispatch = (function (idx) { + return function (action) { + var next = reducer(hooks[idx], action); + if (Object.is(next, hooks[idx])) return; + hooks[idx] = next; + scheduleRender(); + }; + })(i); + return [hooks[i], dispatch]; + } + + function useRef(initial) { + var i = hookIndex++; + if (hooks[i] === undefined) hooks[i] = { current: initial }; + return hooks[i]; + } + + function depsChanged(a, b) { + if (!a || !b || a.length !== b.length) return true; + for (var i = 0; i < a.length; i++) if (!Object.is(a[i], b[i])) return true; + return false; + } + + function useEffect(fn, deps) { + var i = hookIndex++; + var prev = hooks[i]; + if (!prev || depsChanged(prev.deps, deps)) { + var entry = { fn: fn, deps: deps, cleanup: prev && prev.cleanup }; + hooks[i] = entry; + effects.push(entry); + } + } + + function useMemo(fn, deps) { + var i = hookIndex++; + var prev = hooks[i]; + if (!prev || depsChanged(prev.deps, deps)) { + hooks[i] = { deps: deps, value: fn() }; + } + return hooks[i].value; + } + + function useCallback(fn, deps) { + return useMemo(function () { + return fn; + }, deps); + } + + function createContext(defaultValue) { + var ctx = { _default: defaultValue, _id: Math.random() }; + ctx.Provider = function Provider(props) { + var value = props.value !== undefined ? props.value : defaultValue; + contextStack.push({ ctx: ctx, value: value }); + try { + var kids = props.children; + if (Array.isArray(kids)) return h("div", { style: { display: "contents" } }, kids); + return kids || null; + } finally { + contextStack.pop(); + } + }; + return ctx; + } + + function useContext(ctx) { + for (var i = contextStack.length - 1; i >= 0; i--) { + if (contextStack[i].ctx === ctx) return contextStack[i].value; + } + return ctx._default; + } + + function render(vnode, container) { + if (typeof container === "string") container = document.querySelector(container); + rootContainer = container; + if (typeof vnode === "function") { + rootVNode = { type: vnode, props: {}, __isComponentRoot: true }; + } else if (vnode && typeof vnode.type === "function") { + rootVNode = Object.assign({ __isComponentRoot: true }, vnode); + } else { + rootVNode = vnode; + } + // Clear and mount + while (container.firstChild) container.removeChild(container.firstChild); + hookIndex = 0; + hooks = container.__rmRootHooks || (container.__rmRootHooks = []); + currentComponent = container; + effects = []; + var tree; + if (rootVNode.__isComponentRoot) { + hookIndex = 0; + hooks = container.__rmRootHooks; + tree = rootVNode.type(rootVNode.props || {}); + } else { + tree = rootVNode; + } + pendingEffects = pendingEffects.concat(effects); + container.appendChild(createNode(tree)); + container.__rmVNode = tree; + runEffects(); + } + + function createRoot(container) { + return { + render: function (vnode) { + render(vnode, container); + }, + }; + } + + var api = { + h: h, + useState: useState, + useEffect: useEffect, + useReducer: useReducer, + useRef: useRef, + useMemo: useMemo, + useCallback: useCallback, + createContext: createContext, + useContext: useContext, + render: render, + createRoot: createRoot, + Fragment: function Fragment(props) { + return h("div", { style: { display: "contents" } }, props && props.children); + }, + }; + + global.RM = api; +})(typeof window !== "undefined" ? window : globalThis); diff --git a/internal/ui/static/js/screenshare.js b/internal/ui/static/js/screenshare.js new file mode 100644 index 00000000..9c84950f --- /dev/null +++ b/internal/ui/static/js/screenshare.js @@ -0,0 +1,676 @@ +(function () { + "use strict"; + + var API_BASE = "/ui/api/screenshare/"; + var STATUS = { + WAITING: "waiting", + CONNECTING: "connecting", + STREAMING: "streaming", + ERROR: "error", + }; + var BACKDROP_PRESETS = { + white: "#FFFFFF", + "off-white": "#F9F6F1", + gray: "#2D2D2D", + black: "#000000", + }; + + var status = STATUS.WAITING; + var errorMsg = ""; + var poppedOut = false; + var manualRotation = 0; + var backdrop = localStorage.getItem("screenshare-backdrop") || "black"; + var customColor = localStorage.getItem("screenshare-custom-color") || "#808080"; + var showControls = false; + var pinnedPosition = null; + var controlsPosition = "right"; + + var pc = null; + var dc = null; + var roomId = null; + var tabletClientId = null; + var disconnected = false; + var pollTimer = null; + var canvas = null; + var statusEl = null; + var controlsEl = null; + var optionsPanel = null; + var stageEl = null; + + function setBackdropPref(val) { + localStorage.setItem("screenshare-backdrop", val); + } + function setCustomColorPref(val) { + localStorage.setItem("screenshare-custom-color", val); + } + function resolveBackdrop(pref) { + return BACKDROP_PRESETS[pref] || pref; + } + function isLightColor(hex) { + var c = String(hex || "").replace("#", ""); + if (c.length !== 6) return false; + var r = parseInt(c.substring(0, 2), 16); + var g = parseInt(c.substring(2, 4), 16); + var b = parseInt(c.substring(4, 6), 16); + return (r * 299 + g * 587 + b * 114) / 1000 > 128; + } + + function api(path, opts) { + opts = opts || {}; + var headers = Object.assign({ "Content-Type": "application/json" }, opts.headers || {}); + return fetch(API_BASE + path, Object.assign({ credentials: "same-origin", headers: headers }, opts)); + } + + function setStatus(next, msg) { + status = next; + if (typeof msg === "string") errorMsg = msg; + renderUI(); + if (status === STATUS.WAITING) startPolling(); + } + + function cleanup() { + dc = null; + if (pc) { + pc.close(); + pc = null; + } + roomId = null; + } + + function updateCursor(lastPenX, lastPenY) { + var cursor = document.getElementById("pen-cursor"); + if (!cursor || !canvas) return; + if (lastPenX === 0 && lastPenY === 0) { + cursor.style.display = "none"; + return; + } + var rect = canvas.getBoundingClientRect(); + var cw = canvas.width; + var ch = canvas.height; + var rot = ((manualRotation % 360) + 360) % 360; + var isLandscape = rot === 90 || rot === 270; + var renderedW = isLandscape ? rect.height : rect.width; + var renderedH = isLandscape ? rect.width : rect.height; + var scaleX = renderedW / cw; + var scaleY = renderedH / ch; + + var cx = (lastPenX - cw / 2) * scaleX; + var cy = (lastPenY - ch / 2) * scaleY; + + var rad = (rot * Math.PI) / 180; + var rx = cx * Math.cos(rad) - cy * Math.sin(rad); + var ry = cx * Math.sin(rad) + cy * Math.cos(rad); + + var screenX = rect.left + rect.width / 2 + rx; + var screenY = rect.top + rect.height / 2 + ry; + + cursor.style.display = "block"; + cursor.style.left = screenX - 4 + "px"; + cursor.style.top = screenY - 4 + "px"; + } + + function setupPeerConnection(iceServers) { + if (pc) pc.close(); + + var config = {}; + if (iceServers && iceServers.length) { + config.iceServers = iceServers.map(function (s) { + return { + urls: s.url || s.urls, + username: s.username, + credential: s.credential, + }; + }); + } + + pc = new RTCPeerConnection(config); + + pc.ondatachannel = function (event) { + var channel = event.channel; + channel.binaryType = "arraybuffer"; + dc = channel; + + var screenWidth = 0; + var screenHeight = 0; + var ctx = null; + var lastPenX = 0; + var lastPenY = 0; + var rotation = 0; + var frameQueue = []; + var rafPending = false; + var pendingBuffer = null; + var pendingExpected = 0; + var pendingReceived = 0; + + channel.onopen = function () { + var header = new TextEncoder().encode("reMarkable"); + var buf = new ArrayBuffer(header.length + 2); + new Uint8Array(buf).set(header); + channel.send(buf); + pc.getStats().then(function (stats) { + stats.forEach(function (s) { + if (s.type === "candidate-pair" && s.state === "succeeded") { + var remote = stats.get(s.remoteCandidateId); + console.log("[screenshare] peer:", remote && remote.address, s.nominated ? "(active)" : ""); + } + }); + }); + }; + + channel.onmessage = function (e) { + var data = e.data; + if (!(data instanceof ArrayBuffer)) return; + var bytes = new Uint8Array(data); + if (bytes.length === 0) return; + var pako = window.pako; + if (!pako) { + console.error("[screenshare] window.pako is required"); + return; + } + + if (pendingBuffer && pendingExpected > 0) { + var chunk = new Uint8Array(data); + var remaining = pendingExpected - pendingReceived; + var take = Math.min(chunk.byteLength, remaining); + pendingBuffer.set(chunk.subarray(0, take), pendingReceived); + pendingReceived += take; + if (pendingReceived < pendingExpected) return; + } + + var msgType = pendingBuffer ? 0x00 : bytes[0]; + + if (msgType === 0x68 && bytes.length >= 7) { + var view = new DataView(data); + screenWidth = view.getUint16(3, false); + screenHeight = view.getUint16(5, false); + if (canvas) { + canvas.width = screenWidth; + canvas.height = screenHeight; + ctx = canvas.getContext("2d", { willReadFrequently: true }); + } + setStatus(STATUS.STREAMING); + return; + } + + if (msgType === 0x67) return; + + if (msgType === 0x66 && bytes.length >= 5) { + var rv = new DataView(data, 1); + var rawDeg = rv.getUint32(0, false); + var newRotation = (360 - rawDeg) % 360; + if (newRotation !== rotation) { + var prev = rotation; + rotation = newRotation; + var delta = ((newRotation - prev + 540) % 360) - 180; + manualRotation = manualRotation + delta; + renderUI(); + } + return; + } + + if (msgType === 0x64 && bytes.length === 5 && ctx) { + lastPenX = (bytes[1] << 8) | bytes[2]; + lastPenY = (bytes[3] << 8) | bytes[4]; + updateCursor(lastPenX, lastPenY); + return; + } + + if ((pendingBuffer && pendingReceived >= pendingExpected) || (msgType === 0x00 && bytes.length > 7 && ctx)) { + var frameBytes; + if (pendingBuffer && pendingReceived >= pendingExpected) { + frameBytes = pendingBuffer; + pendingBuffer = null; + pendingExpected = 0; + pendingReceived = 0; + } else { + var declaredSize = new DataView(data, 3, 4).getUint32(0, false); + var expectedLen = 7 + declaredSize; + if (bytes.length < expectedLen) { + pendingBuffer = new Uint8Array(expectedLen); + pendingBuffer.set(new Uint8Array(data), 0); + pendingExpected = expectedLen; + pendingReceived = bytes.length; + return; + } + frameBytes = new Uint8Array(bytes); + } + + frameQueue.push(frameBytes); + if (!rafPending) { + rafPending = true; + requestAnimationFrame(function () { + rafPending = false; + while (frameQueue.length > 0) { + var frame = frameQueue.shift(); + try { + var fv = new DataView(frame.buffer, frame.byteOffset, frame.byteLength); + var rectCount = fv.getUint16(1, false); + var deflatedSize = fv.getUint32(3, false); + if (7 + deflatedSize > frame.byteLength) continue; + var compressed = new Uint8Array( + frame.buffer.slice(frame.byteOffset + 7, frame.byteOffset + 7 + deflatedSize) + ); + var raw = pako.inflate(compressed); + if (!raw || raw.length < 12) continue; + + var rawView = new DataView(raw.buffer); + var pos = 0; + for (var ri = 0; ri < rectCount; ri++) { + if (pos + 12 > raw.byteLength) break; + var regionX = rawView.getUint16(pos, false); + var regionY = rawView.getUint16(pos + 2, false); + var regionW = rawView.getUint16(pos + 4, false); + var regionH = rawView.getUint16(pos + 6, false); + var pxDataLen = rawView.getUint32(pos + 8, false); + if (pos + 12 + pxDataLen > raw.byteLength) break; + + var pxView = new DataView(raw.buffer, pos + 12, pxDataLen); + var imgData = new ImageData(regionW, regionH); + var out = imgData.data; + var pixels = regionW * regionH; + for (var i = 0; i < pixels; i++) { + var val = pxView.getUint16(i * 2, true); + var r5 = (val >> 11) & 0x1f; + var g6 = (val >> 5) & 0x3f; + var b5 = val & 0x1f; + out[i * 4] = (r5 << 3) | (r5 >> 2); + out[i * 4 + 1] = (g6 << 2) | (g6 >> 4); + out[i * 4 + 2] = (b5 << 3) | (b5 >> 2); + out[i * 4 + 3] = 255; + } + pos += 12 + pxDataLen; + + if ( + regionX === 0 && + regionY === 0 && + regionW >= screenWidth * 0.9 && + regionH >= screenHeight * 0.9 + ) { + screenWidth = regionW; + screenHeight = regionH; + canvas.width = screenWidth; + canvas.height = screenHeight; + } + ctx.putImageData(imgData, regionX, regionY); + } + } catch (err) { + console.error("[screenshare] frame error:", err); + pendingBuffer = null; + pendingExpected = 0; + pendingReceived = 0; + } + } + updateCursor(lastPenX, lastPenY); + }); + } + } + }; + + channel.onclose = function () { + if (!disconnected) setStatus(STATUS.WAITING); + }; + }; + + // Don't trickle ICE candidates. The tablet crashes on mDNS candidates. + pc.onicecandidate = function () {}; + + pc.onconnectionstatechange = function () { + if (pc.connectionState === "failed" || pc.connectionState === "disconnected") { + cleanup(); + if (!disconnected) setStatus(STATUS.WAITING); + } + }; + + return pc; + } + + async function joinRoom() { + try { + setStatus(STATUS.CONNECTING); + + var offerRes = await api("offer"); + if (!offerRes.ok) throw new Error("Failed to get offer from device"); + + var data = await offerRes.json(); + roomId = data.roomId; + + var peer = setupPeerConnection(data.iceServers); + + var msgs = data.messages || []; + var offerMsg = msgs.find(function (m) { + var p = m.payload; + if (p && p.type === "webtrc" && p.payload) p = p.payload; + return p && p.type === "offer"; + }); + + if (!offerMsg) throw new Error("No offer received from device"); + + if (offerMsg.clientId) tabletClientId = offerMsg.clientId; + var offerPayload = offerMsg.payload; + if (offerPayload.type === "webtrc") offerPayload = offerPayload.payload; + + var sdp = offerPayload.description || offerPayload.sdp; + await peer.setRemoteDescription(new RTCSessionDescription({ type: "offer", sdp: sdp })); + + for (var mi = 0; mi < msgs.length; mi++) { + var msg = msgs[mi]; + var inner = msg.payload; + if (!inner) continue; + if (inner.type === "webtrc" && inner.payload) inner = inner.payload; + if (inner.type === "candidate") { + await peer.addIceCandidate( + new RTCIceCandidate({ + candidate: inner.candidate, + sdpMid: inner.mid || "0", + }) + ); + } + } + + var answer = await peer.createAnswer(); + await peer.setLocalDescription(answer); + + if (peer.iceGatheringState !== "complete") { + await new Promise(function (resolve) { + function check() { + if (peer.iceGatheringState === "complete") { + peer.removeEventListener("icegatheringstatechange", check); + resolve(); + } + } + peer.addEventListener("icegatheringstatechange", check); + setTimeout(resolve, 5000); + }); + } + + await api("room/" + data.roomId + "/answer", { + method: "POST", + body: JSON.stringify({ + targetClientId: offerMsg.clientId, + payload: { + type: "webtrc", + payload: { type: "answer", description: peer.localDescription.sdp }, + }, + }), + }); + } catch (e) { + setStatus(STATUS.ERROR, e.message || String(e)); + } + } + + function startPolling() { + if (pollTimer) clearInterval(pollTimer); + if (status !== STATUS.WAITING) return; + pollTimer = setInterval(async function () { + if (status !== STATUS.WAITING) { + clearInterval(pollTimer); + pollTimer = null; + return; + } + var r = await api("room").catch(function () { + return null; + }); + if (r && r.ok) { + clearInterval(pollTimer); + pollTimer = null; + joinRoom(); + } + }, 2000); + } + + function disconnect() { + if (dc && dc.readyState === "open") { + var buf = new ArrayBuffer(4); + new DataView(buf).setInt32(0, 0x65, false); + dc.send(buf); + } + cleanup(); + poppedOut = false; + showControls = false; + disconnected = true; + setStatus(STATUS.ERROR, "Disconnected. Start a new screenshare session from the tablet to reconnect."); + } + + function reconnect() { + disconnected = false; + errorMsg = ""; + setStatus(STATUS.WAITING); + } + + function updateControlsPosition() { + if (!poppedOut || !canvas || !canvas.width || !canvas.height) return; + var rot = ((manualRotation % 360) + 360) % 360; + var isRotated = rot % 180 !== 0; + var aspect = isRotated ? canvas.height / canvas.width : canvas.width / canvas.height; + var vpAspect = (window.innerWidth - 50) / window.innerHeight; + controlsPosition = aspect < vpAspect ? "right" : "top"; + renderUI(); + } + + function applyCanvasStyle() { + if (!canvas) return; + var rot = ((manualRotation % 360) + 360) % 360; + var isRotated = rot % 180 !== 0; + canvas.style.background = "#000"; + canvas.style.borderRadius = poppedOut ? "0" : "4px"; + canvas.style.transform = "rotate(" + manualRotation + "deg)"; + canvas.style.transition = "transform 0.3s ease"; + canvas.style.display = status === STATUS.STREAMING ? "block" : "none"; + + if (poppedOut) { + var pad = controlsPosition === "right" ? 56 : 0; + var topPad = controlsPosition === "top" ? 48 : 0; + if (isRotated) { + canvas.style.maxWidth = "calc(100vh - " + topPad + "px)"; + canvas.style.maxHeight = "calc(100vw - " + pad + "px)"; + } else { + canvas.style.maxWidth = "calc(100vw - " + pad + "px)"; + canvas.style.maxHeight = "calc(100vh - " + topPad + "px)"; + } + canvas.style.width = "auto"; + canvas.style.height = "auto"; + } else if (isRotated) { + canvas.style.height = "70vh"; + canvas.style.width = "auto"; + canvas.style.maxWidth = ""; + canvas.style.maxHeight = ""; + } else { + canvas.style.width = "100%"; + canvas.style.maxWidth = "min(600px, 100%)"; + canvas.style.height = "auto"; + canvas.style.maxHeight = ""; + } + } + + function renderUI() { + if (statusEl) { + if (status === STATUS.WAITING) { + statusEl.textContent = "Waiting for reMarkable to start screen sharing..."; + statusEl.hidden = false; + } else if (status === STATUS.CONNECTING) { + statusEl.textContent = "Connecting to reMarkable..."; + statusEl.hidden = false; + } else if (status === STATUS.ERROR) { + statusEl.textContent = errorMsg || "Error"; + statusEl.hidden = false; + } else { + statusEl.hidden = true; + statusEl.textContent = ""; + } + } + + applyCanvasStyle(); + + if (stageEl) { + if (poppedOut) { + stageEl.style.position = "fixed"; + stageEl.style.inset = "0"; + stageEl.style.zIndex = "9999"; + stageEl.style.background = resolveBackdrop(backdrop); + stageEl.style.display = status === STATUS.STREAMING ? "flex" : "none"; + stageEl.style.flexDirection = "column"; + stageEl.style.alignItems = "center"; + stageEl.style.justifyContent = "center"; + stageEl.style.paddingTop = controlsPosition === "top" ? "40px" : "0"; + stageEl.style.paddingRight = controlsPosition === "right" ? "50px" : "0"; + } else { + stageEl.style.position = ""; + stageEl.style.inset = ""; + stageEl.style.zIndex = ""; + stageEl.style.background = ""; + stageEl.style.display = status === STATUS.STREAMING ? "flex" : "none"; + stageEl.style.flexDirection = "column"; + stageEl.style.alignItems = "center"; + stageEl.style.justifyContent = ""; + stageEl.style.paddingTop = ""; + stageEl.style.paddingRight = ""; + } + } + + var light = poppedOut && isLightColor(resolveBackdrop(backdrop)); + if (controlsEl) { + controlsEl.classList.toggle("ss-fullscreen", poppedOut); + controlsEl.classList.toggle("ss-light", light); + controlsEl.classList.toggle("ss-pos-right", controlsPosition === "right"); + controlsEl.classList.toggle("ss-pos-top", controlsPosition === "top"); + controlsEl.style.display = status === STATUS.STREAMING || (status === STATUS.ERROR && disconnected) ? "" : "none"; + } + + function show(id, on) { + var el = document.getElementById(id); + if (el) el.hidden = !on; + } + + var streaming = status === STATUS.STREAMING; + show("ss-rotate-l", streaming && (!poppedOut || showControls)); + show("ss-rotate-r", streaming && (!poppedOut || showControls)); + show("ss-fullscreen", streaming && !poppedOut); + show("ss-exit-fs", streaming && poppedOut); + show("ss-options", streaming && poppedOut); + show("ss-disconnect", streaming && (!poppedOut || showControls)); + show("ss-reconnect", status === STATUS.ERROR && disconnected); + + if (optionsPanel) { + optionsPanel.hidden = !(poppedOut && showControls); + if (pinnedPosition || controlsPosition) { + optionsPanel.dataset.position = pinnedPosition || controlsPosition; + } + } + + document.querySelectorAll("[data-backdrop]").forEach(function (btn) { + var name = btn.getAttribute("data-backdrop"); + var selected = backdrop === name; + btn.setAttribute("aria-pressed", selected ? "true" : "false"); + btn.classList.toggle("is-selected", selected); + }); + + var customInput = document.getElementById("ss-custom-color"); + if (customInput) { + customInput.value = customColor; + var customSelected = !BACKDROP_PRESETS[backdrop]; + customInput.classList.toggle("is-selected", customSelected); + } + } + + function bindUI() { + statusEl = document.getElementById("ss-status"); + canvas = document.getElementById("ss-canvas"); + controlsEl = document.getElementById("ss-controls"); + optionsPanel = document.getElementById("ss-options-panel"); + stageEl = document.getElementById("ss-stage") || (canvas && canvas.parentElement); + + var rotateL = document.getElementById("ss-rotate-l"); + var rotateR = document.getElementById("ss-rotate-r"); + var fullscreen = document.getElementById("ss-fullscreen"); + var exitFs = document.getElementById("ss-exit-fs"); + var disconnectBtn = document.getElementById("ss-disconnect"); + var reconnectBtn = document.getElementById("ss-reconnect"); + var optionsBtn = document.getElementById("ss-options"); + var customInput = document.getElementById("ss-custom-color"); + + if (rotateL) { + rotateL.addEventListener("click", function () { + manualRotation -= 90; + renderUI(); + }); + } + if (rotateR) { + rotateR.addEventListener("click", function () { + manualRotation += 90; + renderUI(); + }); + } + if (fullscreen) { + fullscreen.addEventListener("click", function () { + poppedOut = true; + updateControlsPosition(); + renderUI(); + }); + } + if (exitFs) { + exitFs.addEventListener("click", function () { + poppedOut = false; + showControls = false; + renderUI(); + }); + } + if (disconnectBtn) disconnectBtn.addEventListener("click", disconnect); + if (reconnectBtn) reconnectBtn.addEventListener("click", reconnect); + if (optionsBtn) { + optionsBtn.addEventListener("click", function () { + if (!showControls) pinnedPosition = controlsPosition; + showControls = !showControls; + renderUI(); + }); + } + + document.querySelectorAll("[data-backdrop]").forEach(function (btn) { + btn.addEventListener("click", function () { + var name = btn.getAttribute("data-backdrop"); + backdrop = name; + setBackdropPref(name); + renderUI(); + }); + }); + + if (customInput) { + customInput.addEventListener("click", function () { + backdrop = customColor; + setBackdropPref(customColor); + renderUI(); + }); + customInput.addEventListener("input", function (e) { + customColor = e.target.value; + setCustomColorPref(customColor); + backdrop = customColor; + setBackdropPref(customColor); + renderUI(); + }); + } + + document.addEventListener("mousedown", function (e) { + if (!showControls) return; + if (controlsEl && controlsEl.contains(e.target)) return; + if (optionsPanel && optionsPanel.contains(e.target)) return; + showControls = false; + renderUI(); + }); + + window.addEventListener("resize", function () { + if (poppedOut) updateControlsPosition(); + }); + } + + function init() { + if (!document.getElementById("ss-canvas")) return; + bindUI(); + renderUI(); + startPolling(); + } + + if (document.readyState === "loading") { + document.addEventListener("DOMContentLoaded", init); + } else { + init(); + } +})(); diff --git a/internal/ui/static/js/shells/all.js b/internal/ui/static/js/shells/all.js new file mode 100644 index 00000000..be8dc4e4 --- /dev/null +++ b/internal/ui/static/js/shells/all.js @@ -0,0 +1,588 @@ +(function (global) { + "use strict"; + var h = global.RM.h; + var useState = global.RM.useState; + var useEffect = global.RM.useEffect; + var useRef = global.RM.useRef; + global.RMShells = global.RMShells || {}; + + var KNOWN = { remarkable: 1, googledocs: 1, icloud: 1, os: 1 }; + + function normalizeChromeStyle(style) { + if (style && KNOWN[style]) return style; + return "remarkable"; + } + + function isMobile(props) { + if (props && props.formFactor === "mobile") return true; + if (props && props.forceMobile) return true; + return global.detectFormFactor && global.detectFormFactor() === "mobile"; + } + + function filterNav(nav) { + var auth = global.useAuthState ? global.useAuthState() : { state: { user: null } }; + var user = auth.state && auth.state.user; + var isAdmin = document.body.dataset.admin === "true"; + if (!isAdmin && user) { + var roles = user.Roles || user.roles || []; + if (roles.indexOf && roles.indexOf("Admin") >= 0) isAdmin = true; + if (user.isAdmin) isAdmin = true; + } + return (nav || []).filter(function (it) { + return !it.adminOnly || isAdmin; + }); + } + + function pathActive(href) { + var path = location.pathname; + return path === href || (href !== "/" && path.indexOf(href) === 0); + } + + function currentLabel(nav) { + var items = filterNav(nav); + for (var i = 0; i < items.length; i++) { + if (pathActive(items[i].href)) return items[i].label || items[i].id; + } + if (location.pathname === "/profile") return "Account"; + if (location.pathname === "/help") return "Help"; + if (location.pathname === "/" || location.pathname === "") return "Home"; + return document.title || "rmfakecloud"; + } + + function NavLinks(props) { + var nav = filterNav(props.nav); + return h( + "ul", + { className: props.className || "shell-nav-list" }, + nav.map(function (it) { + var active = pathActive(it.href); + return h( + "li", + { key: it.id, className: "shell-nav-item" + (active ? " is-active" : "") }, + h( + "a", + { + href: it.href, + className: "shell-nav-link" + (active ? " is-active" : ""), + "aria-current": active ? "page" : undefined, + onClick: props.onNavigate, + }, + h("span", { className: "icon icon-" + (it.icon || "file"), "aria-hidden": "true" }), + h("span", { className: "shell-nav-label" }, it.label || it.id) + ) + ); + }) + ); + } + + function accountLabel() { + var auth = global.useAuthState ? global.useAuthState() : { state: { user: null } }; + var user = auth.state && auth.state.user; + if (user && typeof user === "object") { + return user.Email || user.email || user.UserID || user.userId || user.Name || user.name || ""; + } + return document.body.dataset.email || document.body.dataset.user || "Account"; + } + + function UserSlot(props) { + var openState = useState(false); + var open = openState[0]; + var setOpen = openState[1]; + useEscClose(open, setOpen); + useEffect( + function () { + if (!open) return; + function onDoc(e) { + var t = e.target; + if (t && t.closest && t.closest(".shell-user-slot")) return; + setOpen(false); + } + document.addEventListener("click", onDoc); + return function () { + document.removeEventListener("click", onDoc); + }; + }, + [open] + ); + var email = accountLabel() || "Account"; + return h( + "div", + { className: "shell-user-slot" + (props.className ? " " + props.className : "") + (open ? " is-open" : "") }, + h( + "button", + { + type: "button", + className: "user-menu-toggle", + "aria-haspopup": "menu", + "aria-expanded": open ? "true" : "false", + onClick: function (e) { + if (e && e.stopPropagation) e.stopPropagation(); + setOpen(!open); + }, + }, + h("span", { className: "icon icon-person", "aria-hidden": "true" }), + h("span", { className: "user-menu-name" }, String(email)) + ), + open + ? h( + "ul", + { className: "user-menu-list", role: "menu" }, + h("li", { role: "none" }, h("a", { href: "/profile", role: "menuitem" }, "Settings")), + h("li", { role: "none" }, h("a", { href: "/help", role: "menuitem" }, "Help")), + h( + "li", + { role: "none" }, + h( + "form", + { className: "inline-form", method: "post", action: "/logout" }, + h("button", { type: "submit", className: "btn btn-link", role: "menuitem" }, "Log out") + ) + ) + ) + : null + ); + } + + function attachMain(el, mainSlot) { + if (!el || !mainSlot) return; + if (mainSlot.parentNode !== el) { + el.appendChild(mainSlot); + } + } + + function useEscClose(open, setOpen) { + useEffect( + function () { + if (!open) return; + function onKey(e) { + if (e.key === "Escape") setOpen(false); + } + document.addEventListener("keydown", onKey); + return function () { + document.removeEventListener("keydown", onKey); + }; + }, + [open] + ); + } + + function useChromeMobileClass(on) { + useEffect( + function () { + if (!on) return; + document.body.classList.add("chrome-mobile"); + return function () { + document.body.classList.remove("chrome-mobile"); + }; + }, + [on] + ); + } + + /* ----- Layout 1: remarkable ----- */ + function Remarkable(props) { + var mobile = isMobile(props); + useChromeMobileClass(mobile); + var openState = useState(false); + var open = openState[0]; + var setOpen = openState[1]; + useEscClose(open, setOpen); + var close = function () { + setOpen(false); + }; + var bar = h( + "header", + { className: "shell-rm-bar" }, + mobile + ? h( + "button", + { + type: "button", + className: "shell-hamburger shell-rm-hamburger", + "aria-label": open ? "Close menu" : "Open menu", + "aria-expanded": open ? "true" : "false", + onClick: function () { + setOpen(!open); + }, + }, + "☰" + ) + : null, + h("a", { className: "shell-brand shell-rm-brand", href: "/" }, "rmfakecloud"), + !mobile + ? h(NavLinks, { nav: props.nav, className: "shell-rm-top-list" }) + : null, + h(UserSlot) + ); + var content = h("div", { + className: "shell-content shell-rm-content", + ref: function (el) { + attachMain(el, props.mainSlot); + }, + }); + + if (!mobile) { + return h("div", { className: "shell shell-remarkable" }, bar, content); + } + + return h( + "div", + { className: "shell shell-remarkable is-mobile" }, + bar, + open + ? h("div", { + className: "shell-drawer-scrim", + onClick: close, + }) + : null, + h( + "nav", + { + className: "shell-rm-drawer" + (open ? " is-open" : ""), + "aria-modal": open ? "true" : undefined, + "aria-hidden": open ? "false" : "true", + "aria-label": "Library", + }, + h("div", { className: "shell-rm-drawer-title" }, "Library"), + h(NavLinks, { + nav: props.nav, + className: "shell-rm-nav-list", + onNavigate: close, + }) + ), + content + ); + } + + /* ----- Layout 2: googledocs ----- */ + function GoogleDocs(props) { + var mobile = isMobile(props); + useChromeMobileClass(mobile); + var title = currentLabel(props.nav); + var openState = useState(false); + var open = openState[0]; + var setOpen = openState[1]; + useEscClose(open, setOpen); + var close = function () { + setOpen(false); + }; + + if (mobile) { + return h( + "div", + { className: "shell shell-googledocs is-mobile" }, + h( + "header", + { className: "shell-gd-appbar" }, + h( + "button", + { + type: "button", + className: "shell-hamburger shell-gd-hamburger", + "aria-label": open ? "Close menu" : "Open menu", + "aria-expanded": open ? "true" : "false", + onClick: function () { + setOpen(!open); + }, + }, + "☰" + ), + h("span", { className: "shell-gd-title" }, title), + h(UserSlot) + ), + open + ? h("div", { + className: "shell-drawer-scrim", + onClick: close, + }) + : null, + h( + "nav", + { + className: "shell-gd-drawer" + (open ? " is-open" : ""), + "aria-modal": open ? "true" : undefined, + "aria-hidden": open ? "false" : "true", + "aria-label": "Main", + }, + h("a", { className: "shell-brand shell-gd-drawer-brand", href: "/", onClick: close }, "rmfakecloud"), + h(NavLinks, { + nav: props.nav, + className: "shell-gd-drawer-list", + onNavigate: close, + }) + ), + h("div", { + className: "shell-content shell-gd-content", + ref: function (el) { + attachMain(el, props.mainSlot); + }, + }) + ); + } + + return h( + "div", + { className: "shell shell-googledocs" }, + h( + "header", + { className: "shell-gd-appbar" }, + h("a", { className: "shell-brand shell-gd-mark", href: "/" }, "rmfakecloud"), + h("span", { className: "shell-gd-title" }, title), + h("div", { className: "shell-gd-actions" }, h(UserSlot)) + ), + h( + "div", + { className: "shell-gd-body" }, + h( + "aside", + { className: "shell-gd-rail", "aria-label": "Main" }, + h(NavLinks, { nav: props.nav, className: "shell-gd-rail-list" }) + ), + h("div", { + className: "shell-content shell-gd-content", + ref: function (el) { + attachMain(el, props.mainSlot); + }, + }) + ) + ); + } + + /* ----- Layout 3: icloud ----- */ + function ICloud(props) { + var mobile = isMobile(props); + useChromeMobileClass(mobile); + var title = currentLabel(props.nav); + var openState = useState(false); + var open = openState[0]; + var setOpen = openState[1]; + useEscClose(open, setOpen); + var close = function () { + setOpen(false); + }; + + if (mobile) { + return h( + "div", + { className: "shell shell-icloud is-mobile" }, + h( + "header", + { className: "shell-ic-top" }, + h( + "button", + { + type: "button", + className: "shell-hamburger shell-ic-hamburger", + "aria-label": open ? "Close menu" : "Open menu", + "aria-expanded": open ? "true" : "false", + onClick: function () { + setOpen(!open); + }, + }, + "☰" + ), + h("h1", { className: "shell-ic-page-title" }, title), + h(UserSlot, { className: "shell-ic-account" }) + ), + open + ? h("div", { + className: "shell-drawer-scrim shell-ic-scrim", + onClick: close, + }) + : null, + h( + "nav", + { + className: "shell-ic-drawer" + (open ? " is-open" : ""), + "aria-modal": open ? "true" : undefined, + "aria-hidden": open ? "false" : "true", + "aria-label": "Main", + }, + h(NavLinks, { + nav: props.nav, + className: "shell-ic-drawer-list", + onNavigate: close, + }) + ), + h( + "div", + { className: "shell-ic-canvas" }, + h("div", { + className: "shell-content shell-ic-panel", + ref: function (el) { + attachMain(el, props.mainSlot); + }, + }) + ) + ); + } + + return h( + "div", + { className: "shell shell-icloud" }, + h( + "aside", + { className: "shell-ic-sidebar", "aria-label": "Main" }, + h("a", { className: "shell-brand shell-ic-brand", href: "/" }, "rmfakecloud"), + h(NavLinks, { nav: props.nav, className: "shell-ic-nav-list" }), + h(UserSlot, { className: "shell-ic-account" }) + ), + h( + "div", + { className: "shell-ic-main" }, + h("header", { className: "shell-ic-heading" }, h("h1", { className: "shell-ic-page-title" }, title)), + h( + "div", + { className: "shell-ic-canvas" }, + h("div", { + className: "shell-content shell-ic-panel", + ref: function (el) { + attachMain(el, props.mainSlot); + }, + }) + ) + ) + ); + } + + /* ----- Layout 4: os (folder window + Drive icons) ----- */ + function isDriveRoot() { + var p = location.pathname; + return p === "/" || p === ""; + } + + function DriveGrid(props) { + var items = filterNav(props.nav); + return h( + "div", + { className: "shell-os-drives", role: "list" }, + items.map(function (it) { + return h( + "a", + { + key: it.id, + href: it.href, + className: "shell-os-drive", + role: "listitem", + }, + h("span", { className: "shell-os-drive-icon icon icon-lg icon-" + (it.icon || "folder"), "aria-hidden": "true" }), + h("span", { className: "shell-os-drive-label" }, it.label || it.id) + ); + }) + ); + } + + function OS(props) { + var mobile = isMobile(props); + useChromeMobileClass(mobile); + var atRoot = isDriveRoot(); + var title = atRoot ? "Drive" : currentLabel(props.nav); + var contentRef = useRef(null); + + useEffect( + function () { + if (atRoot) return; + attachMain(contentRef.current, props.mainSlot); + }, + [props.mainSlot, atRoot] + ); + + if (mobile) { + if (atRoot) { + return h( + "div", + { className: "shell shell-os is-mobile" }, + h( + "header", + { className: "shell-os-mobile-bar" }, + h("h1", { className: "shell-os-mobile-title" }, "Drive"), + h(UserSlot) + ), + h(DriveGrid, { nav: props.nav }) + ); + } + return h( + "div", + { className: "shell shell-os is-mobile" }, + h( + "header", + { className: "shell-os-mobile-bar" }, + h("a", { className: "shell-os-back", href: "/" }, "← Drives"), + h("span", { className: "shell-os-mobile-title" }, title), + h(UserSlot) + ), + h("div", { + className: "shell-content shell-os-mobile-content", + ref: function (el) { + contentRef.current = el; + attachMain(el, props.mainSlot); + }, + }) + ); + } + + return h( + "div", + { className: "shell shell-os" }, + h( + "div", + { className: "shell-os-desktop" }, + h( + "div", + { className: "shell-os-window", role: "region", "aria-label": "Folder window" }, + h( + "div", + { className: "shell-os-titlebar" }, + h( + "div", + { className: "shell-os-traffic", "aria-hidden": "true" }, + h("span", { className: "shell-os-dot shell-os-dot-close" }), + h("span", { className: "shell-os-dot shell-os-dot-min" }), + h("span", { className: "shell-os-dot shell-os-dot-max" }) + ), + h("span", { className: "shell-os-window-title" }, title), + h(UserSlot, { className: "shell-os-title-user" }) + ), + h( + "div", + { className: "shell-os-toolbar" }, + atRoot + ? h("span", { className: "shell-os-path" }, "Drive") + : h( + "span", + { className: "shell-os-path" }, + h("a", { href: "/" }, "Drive"), + h("span", { "aria-hidden": "true" }, " / "), + h("span", null, title) + ) + ), + h( + "div", + { className: "shell-os-body" }, + h( + "aside", + { className: "shell-os-sidebar", "aria-label": "Favorites" }, + h("div", { className: "shell-os-sidebar-label" }, "Favorites"), + h(NavLinks, { nav: props.nav, className: "shell-os-fav-list" }) + ), + atRoot + ? h("div", { className: "shell-content shell-os-pane" }, h(DriveGrid, { nav: props.nav })) + : h("div", { + className: "shell-content shell-os-pane", + ref: function (el) { + contentRef.current = el; + attachMain(el, props.mainSlot); + }, + }) + ) + ) + ) + ); + } + + global.RMShells.normalizeChromeStyle = normalizeChromeStyle; + global.RMShells.remarkable = Remarkable; + global.RMShells.googledocs = GoogleDocs; + global.RMShells.icloud = ICloud; + global.RMShells.os = OS; +})(typeof window !== "undefined" ? window : globalThis); diff --git a/internal/ui/static/js/theme-studio.js b/internal/ui/static/js/theme-studio.js new file mode 100644 index 00000000..e6d6fa7f --- /dev/null +++ b/internal/ui/static/js/theme-studio.js @@ -0,0 +1,82 @@ +(function () { + "use strict"; + + var XSL_URL = "/ui/api/themes/assets/theme-to-css.xsl"; + var DEBOUNCE_MS = 400; + var cssXsl = null; + var timer = null; + + function parseXMLString(xmlString) { + return new DOMParser().parseFromString(xmlString, "application/xml"); + } + + async function fetchXML(url) { + var r = await fetch(url, { credentials: "same-origin" }); + if (!r.ok) throw new Error("Failed to fetch " + url); + var text = await r.text(); + return parseXMLString(text); + } + + function transformToText(xmlDoc, xslDoc) { + if (typeof XSLTProcessor === "undefined") { + throw new Error("XSLTProcessor not supported"); + } + var proc = new XSLTProcessor(); + proc.importStylesheet(xslDoc); + var frag = proc.transformToFragment(xmlDoc, document); + return (frag && frag.textContent) || ""; + } + + function injectPreview(cssText) { + var el = document.getElementById("theme-preview-style"); + if (!el) { + el = document.createElement("style"); + el.id = "theme-preview-style"; + document.head.appendChild(el); + } + el.textContent = cssText || ""; + } + + function previewFromTextarea() { + var ta = document.getElementById("theme-xml"); + if (!ta || !cssXsl) return; + try { + var doc = parseXMLString(ta.value); + var parseErr = doc.querySelector("parsererror"); + if (parseErr) { + console.warn("[theme-studio] XML parse error"); + return; + } + var css = transformToText(doc, cssXsl); + injectPreview(css); + } catch (e) { + console.error("[theme-studio]", e); + } + } + + function schedulePreview() { + if (timer) clearTimeout(timer); + timer = setTimeout(previewFromTextarea, DEBOUNCE_MS); + } + + async function init() { + var ta = document.getElementById("theme-xml"); + if (!ta) return; + + try { + cssXsl = await fetchXML(XSL_URL); + } catch (e) { + console.error("[theme-studio] failed to load XSL:", e); + return; + } + + ta.addEventListener("input", schedulePreview); + previewFromTextarea(); + } + + if (document.readyState === "loading") { + document.addEventListener("DOMContentLoaded", init); + } else { + init(); + } +})(); diff --git a/internal/ui/static/js/vendor/simplewebauthn-browser.umd.min.js b/internal/ui/static/js/vendor/simplewebauthn-browser.umd.min.js new file mode 100644 index 00000000..60923ef4 --- /dev/null +++ b/internal/ui/static/js/vendor/simplewebauthn-browser.umd.min.js @@ -0,0 +1,2 @@ +/* [@simplewebauthn/browser@13.2.2] */ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).SimpleWebAuthnBrowser={})}(this,(function(e){"use strict";function t(e){const t=new Uint8Array(e);let r="";for(const e of t)r+=String.fromCharCode(e);return btoa(r).replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}function r(e){const t=e.replace(/-/g,"+").replace(/_/g,"/"),r=(4-t.length%4)%4,n=t.padEnd(t.length+r,"="),o=atob(n),i=new ArrayBuffer(o.length),a=new Uint8Array(i);for(let e=0;ee};function i(e){const{id:t}=e;return{...e,id:r(t),transports:e.transports}}function a(e){return"localhost"===e||/^([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}$/i.test(e)}class s extends Error{constructor({message:e,code:t,cause:r,name:n}){super(e,{cause:r}),Object.defineProperty(this,"code",{enumerable:!0,configurable:!0,writable:!0,value:void 0}),this.name=n??r.name,this.code=t}}const l=new class{constructor(){Object.defineProperty(this,"controller",{enumerable:!0,configurable:!0,writable:!0,value:void 0})}createNewAbortSignal(){if(this.controller){const e=new Error("Cancelling existing WebAuthn API call for new one");e.name="AbortError",this.controller.abort(e)}const e=new AbortController;return this.controller=e,e.signal}cancelCeremony(){if(this.controller){const e=new Error("Manually cancelling existing WebAuthn API call");e.name="AbortError",this.controller.abort(e),this.controller=void 0}}},c=["cross-platform","platform"];function u(e){if(e&&!(c.indexOf(e)<0))return e}function d(e,t){console.warn(`The browser extension that intercepted this WebAuthn API call incorrectly implemented ${e}. You should report this error to them.\n`,t)}function h(){if(!n())return p.stubThis(new Promise((e=>e(!1))));const e=globalThis.PublicKeyCredential;return void 0===e?.isConditionalMediationAvailable?p.stubThis(new Promise((e=>e(!1)))):p.stubThis(e.isConditionalMediationAvailable())}const p={stubThis:e=>e};e.WebAuthnAbortService=l,e.WebAuthnError=s,e._browserSupportsWebAuthnAutofillInternals=p,e._browserSupportsWebAuthnInternals=o,e.base64URLStringToBuffer=r,e.browserSupportsWebAuthn=n,e.browserSupportsWebAuthnAutofill=h,e.bufferToBase64URLString=t,e.platformAuthenticatorIsAvailable=function(){return n()?PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable():new Promise((e=>e(!1)))},e.startAuthentication=async function(e){!e.optionsJSON&&e.challenge&&(console.warn("startAuthentication() was not called correctly. It will try to continue with the provided options, but this call should be refactored to use the expected call structure instead. See https://simplewebauthn.dev/docs/packages/browser#typeerror-cannot-read-properties-of-undefined-reading-challenge for more information."),e={optionsJSON:e});const{optionsJSON:o,useBrowserAutofill:c=!1,verifyBrowserAutofillInput:d=!0}=e;if(!n())throw new Error("WebAuthn is not supported in this browser");let p;0!==o.allowCredentials?.length&&(p=o.allowCredentials?.map(i));const f={...o,challenge:r(o.challenge),allowCredentials:p},b={};if(c){if(!await h())throw Error("Browser does not support WebAuthn autofill");if(document.querySelectorAll("input[autocomplete$='webauthn']").length<1&&d)throw Error('No with "webauthn" as the only or last value in its `autocomplete` attribute was detected');b.mediation="conditional",f.allowCredentials=[]}let R;b.publicKey=f,b.signal=l.createNewAbortSignal();try{R=await navigator.credentials.get(b)}catch(e){throw function({error:e,options:t}){const{publicKey:r}=t;if(!r)throw Error("options was missing required publicKey property");if("AbortError"===e.name){if(t.signal instanceof AbortSignal)return new s({message:"Authentication ceremony was sent an abort signal",code:"ERROR_CEREMONY_ABORTED",cause:e})}else{if("NotAllowedError"===e.name)return new s({message:e.message,code:"ERROR_PASSTHROUGH_SEE_CAUSE_PROPERTY",cause:e});if("SecurityError"===e.name){const t=globalThis.location.hostname;if(!a(t))return new s({message:`${globalThis.location.hostname} is an invalid domain`,code:"ERROR_INVALID_DOMAIN",cause:e});if(r.rpId!==t)return new s({message:`The RP ID "${r.rpId}" is invalid for this domain`,code:"ERROR_INVALID_RP_ID",cause:e})}else if("UnknownError"===e.name)return new s({message:"The authenticator was unable to process the specified options, or could not create a new assertion signature",code:"ERROR_AUTHENTICATOR_GENERAL_ERROR",cause:e})}return e}({error:e,options:b})}if(!R)throw new Error("Authentication was not completed");const{id:g,rawId:w,response:A,type:E}=R;let m;return A.userHandle&&(m=t(A.userHandle)),{id:g,rawId:t(w),response:{authenticatorData:t(A.authenticatorData),clientDataJSON:t(A.clientDataJSON),signature:t(A.signature),userHandle:m},type:E,clientExtensionResults:R.getClientExtensionResults(),authenticatorAttachment:u(R.authenticatorAttachment)}},e.startRegistration=async function(e){!e.optionsJSON&&e.challenge&&(console.warn("startRegistration() was not called correctly. It will try to continue with the provided options, but this call should be refactored to use the expected call structure instead. See https://simplewebauthn.dev/docs/packages/browser#typeerror-cannot-read-properties-of-undefined-reading-challenge for more information."),e={optionsJSON:e});const{optionsJSON:o,useAutoRegister:c=!1}=e;if(!n())throw new Error("WebAuthn is not supported in this browser");const h={...o,challenge:r(o.challenge),user:{...o.user,id:r(o.user.id)},excludeCredentials:o.excludeCredentials?.map(i)},p={};let f;c&&(p.mediation="conditional"),p.publicKey=h,p.signal=l.createNewAbortSignal();try{f=await navigator.credentials.create(p)}catch(e){throw function({error:e,options:t}){const{publicKey:r}=t;if(!r)throw Error("options was missing required publicKey property");if("AbortError"===e.name){if(t.signal instanceof AbortSignal)return new s({message:"Registration ceremony was sent an abort signal",code:"ERROR_CEREMONY_ABORTED",cause:e})}else if("ConstraintError"===e.name){if(!0===r.authenticatorSelection?.requireResidentKey)return new s({message:"Discoverable credentials were required but no available authenticator supported it",code:"ERROR_AUTHENTICATOR_MISSING_DISCOVERABLE_CREDENTIAL_SUPPORT",cause:e});if("conditional"===t.mediation&&"required"===r.authenticatorSelection?.userVerification)return new s({message:"User verification was required during automatic registration but it could not be performed",code:"ERROR_AUTO_REGISTER_USER_VERIFICATION_FAILURE",cause:e});if("required"===r.authenticatorSelection?.userVerification)return new s({message:"User verification was required but no available authenticator supported it",code:"ERROR_AUTHENTICATOR_MISSING_USER_VERIFICATION_SUPPORT",cause:e})}else{if("InvalidStateError"===e.name)return new s({message:"The authenticator was previously registered",code:"ERROR_AUTHENTICATOR_PREVIOUSLY_REGISTERED",cause:e});if("NotAllowedError"===e.name)return new s({message:e.message,code:"ERROR_PASSTHROUGH_SEE_CAUSE_PROPERTY",cause:e});if("NotSupportedError"===e.name)return 0===r.pubKeyCredParams.filter((e=>"public-key"===e.type)).length?new s({message:'No entry in pubKeyCredParams was of type "public-key"',code:"ERROR_MALFORMED_PUBKEYCREDPARAMS",cause:e}):new s({message:"No available authenticator supported any of the specified pubKeyCredParams algorithms",code:"ERROR_AUTHENTICATOR_NO_SUPPORTED_PUBKEYCREDPARAMS_ALG",cause:e});if("SecurityError"===e.name){const t=globalThis.location.hostname;if(!a(t))return new s({message:`${globalThis.location.hostname} is an invalid domain`,code:"ERROR_INVALID_DOMAIN",cause:e});if(r.rp.id!==t)return new s({message:`The RP ID "${r.rp.id}" is invalid for this domain`,code:"ERROR_INVALID_RP_ID",cause:e})}else if("TypeError"===e.name){if(r.user.id.byteLength<1||r.user.id.byteLength>64)return new s({message:"User ID was not between 1 and 64 characters",code:"ERROR_INVALID_USER_ID_LENGTH",cause:e})}else if("UnknownError"===e.name)return new s({message:"The authenticator was unable to process the specified options, or could not create a new credential",code:"ERROR_AUTHENTICATOR_GENERAL_ERROR",cause:e})}return e}({error:e,options:p})}if(!f)throw new Error("Registration was not completed");const{id:b,rawId:R,response:g,type:w}=f;let A,E,m,y;if("function"==typeof g.getTransports&&(A=g.getTransports()),"function"==typeof g.getPublicKeyAlgorithm)try{E=g.getPublicKeyAlgorithm()}catch(e){d("getPublicKeyAlgorithm()",e)}if("function"==typeof g.getPublicKey)try{const e=g.getPublicKey();null!==e&&(m=t(e))}catch(e){d("getPublicKey()",e)}if("function"==typeof g.getAuthenticatorData)try{y=t(g.getAuthenticatorData())}catch(e){d("getAuthenticatorData()",e)}return{id:b,rawId:t(R),response:{attestationObject:t(g.attestationObject),clientDataJSON:t(g.clientDataJSON),transports:A,publicKeyAlgorithm:E,publicKey:m,authenticatorData:y},type:w,clientExtensionResults:f.getClientExtensionResults(),authenticatorAttachment:u(f.authenticatorAttachment)}}})); diff --git a/internal/ui/static/js/webauthn.js b/internal/ui/static/js/webauthn.js new file mode 100644 index 00000000..a8753d90 --- /dev/null +++ b/internal/ui/static/js/webauthn.js @@ -0,0 +1,276 @@ +(function () { + "use strict"; + + var API = "/ui/api/webauthn"; + + function b64urlToBuf(val) { + if (!val) return new ArrayBuffer(0); + if (val instanceof ArrayBuffer) return val; + if (ArrayBuffer.isView(val)) return val.buffer.slice(val.byteOffset, val.byteOffset + val.byteLength); + var s = String(val).replace(/-/g, "+").replace(/_/g, "/"); + var pad = (4 - (s.length % 4)) % 4; + if (pad) s += "====".slice(0, pad); + var bin = atob(s); + var out = new Uint8Array(bin.length); + for (var i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i); + return out.buffer; + } + + function bufToB64url(buf) { + var bytes = buf instanceof ArrayBuffer ? new Uint8Array(buf) : new Uint8Array(buf.buffer || buf); + var s = ""; + for (var i = 0; i < bytes.length; i++) s += String.fromCharCode(bytes[i]); + return btoa(s).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, ""); + } + + function copyCreds(list) { + if (!list || !list.length) return list; + return list.map(function (c) { + var o = {}; + Object.keys(c).forEach(function (k) { + o[k] = c[k]; + }); + if (c.id) o.id = b64urlToBuf(c.id); + return o; + }); + } + + function nativeLib() { + return { + browserSupportsWebAuthn: function () { + return typeof window.PublicKeyCredential === "function"; + }, + startRegistration: async function (opts) { + var json = opts && opts.optionsJSON ? opts.optionsJSON : opts; + if (!json || !json.challenge || !json.user) { + throw new Error("Invalid registration options"); + } + var publicKey = {}; + Object.keys(json).forEach(function (k) { + publicKey[k] = json[k]; + }); + publicKey.challenge = b64urlToBuf(json.challenge); + publicKey.user = {}; + Object.keys(json.user).forEach(function (k) { + publicKey.user[k] = json.user[k]; + }); + publicKey.user.id = b64urlToBuf(json.user.id); + publicKey.excludeCredentials = copyCreds(json.excludeCredentials); + var cred = await navigator.credentials.create({ publicKey: publicKey }); + if (!cred) throw new Error("Registration was not completed"); + var resp = cred.response; + var out = { + id: cred.id, + rawId: bufToB64url(cred.rawId), + type: cred.type, + clientExtensionResults: cred.getClientExtensionResults ? cred.getClientExtensionResults() : {}, + response: { + clientDataJSON: bufToB64url(resp.clientDataJSON), + attestationObject: bufToB64url(resp.attestationObject), + }, + }; + if (cred.authenticatorAttachment) out.authenticatorAttachment = cred.authenticatorAttachment; + if (resp.getTransports) out.response.transports = resp.getTransports(); + return out; + }, + startAuthentication: async function (opts) { + var json = opts && opts.optionsJSON ? opts.optionsJSON : opts; + if (!json || !json.challenge) { + throw new Error("Invalid authentication options"); + } + var publicKey = {}; + Object.keys(json).forEach(function (k) { + publicKey[k] = json[k]; + }); + publicKey.challenge = b64urlToBuf(json.challenge); + publicKey.allowCredentials = copyCreds(json.allowCredentials); + var cred = await navigator.credentials.get({ publicKey: publicKey }); + if (!cred) throw new Error("Authentication was not completed"); + var resp = cred.response; + var out = { + id: cred.id, + rawId: bufToB64url(cred.rawId), + type: cred.type, + clientExtensionResults: cred.getClientExtensionResults ? cred.getClientExtensionResults() : {}, + response: { + authenticatorData: bufToB64url(resp.authenticatorData), + clientDataJSON: bufToB64url(resp.clientDataJSON), + signature: bufToB64url(resp.signature), + userHandle: resp.userHandle ? bufToB64url(resp.userHandle) : undefined, + }, + }; + if (cred.authenticatorAttachment) out.authenticatorAttachment = cred.authenticatorAttachment; + return out; + }, + }; + } + + function swa() { + var lib = window.SimpleWebAuthnBrowser; + if (lib && typeof lib.startAuthentication === "function") return lib; + return nativeLib(); + } + + function jsonHeaders() { + return { "Content-Type": "application/json" }; + } + + async function readError(r) { + var text = await r.text(); + var msg = r.statusText || "Request failed"; + try { + if (text && text.charAt(0) === "{") { + var j = JSON.parse(text); + if (j.error) msg = j.error; + } else if (text) { + msg = text; + } + } catch (_) {} + throw new Error(msg); + } + + async function postJSON(url, body) { + var r = await fetch(url, { + method: "POST", + headers: jsonHeaders(), + credentials: "same-origin", + body: body ? JSON.stringify(body) : undefined, + }); + if (!r.ok) await readError(r); + var ct = r.headers.get("content-type") || ""; + if (ct.indexOf("application/json") !== -1) return r.json(); + return r.text(); + } + + async function del(url) { + var r = await fetch(url, { + method: "DELETE", + headers: jsonHeaders(), + credentials: "same-origin", + }); + if (!r.ok) await readError(r); + } + + function setBusy(btn, busy) { + if (!btn) return; + btn.disabled = !!busy; + btn.setAttribute("aria-busy", busy ? "true" : "false"); + } + + function showError(msg) { + var el = document.getElementById("passkey-error") || document.getElementById("flash") || document.querySelector("[data-passkey-error]"); + if (el) { + el.textContent = msg; + el.hidden = false; + } else { + console.error("[webauthn]", msg); + window.alert(msg); + } + } + + async function handleLogin(e) { + if (e) e.preventDefault(); + var lib = swa(); + if (!lib || typeof lib.startAuthentication !== "function") { + showError("WebAuthn library not loaded"); + return; + } + if (typeof lib.browserSupportsWebAuthn === "function" && !lib.browserSupportsWebAuthn()) { + showError("Passkeys are not supported in this browser"); + return; + } + + var btn = document.getElementById("passkey-login"); + setBusy(btn, true); + try { + var begin = await postJSON(API + "/login/begin"); + var credential = await lib.startAuthentication({ optionsJSON: begin.publicKey }); + await postJSON(API + "/login/finish", { + sessionId: begin.sessionId, + credential: credential, + }); + var next = (btn && btn.getAttribute("data-redirect")) || "/documents"; + window.location.href = next; + } catch (err) { + showError("Passkey login failed: " + (err.message || String(err))); + } finally { + setBusy(btn, false); + } + } + + async function handleRegister(e) { + if (e) e.preventDefault(); + var lib = swa(); + if (!lib || typeof lib.startRegistration !== "function") { + showError("WebAuthn library not loaded"); + return; + } + + var btn = document.getElementById("passkey-register"); + var nameInput = document.getElementById("passkey-name"); + var name = nameInput && nameInput.value ? nameInput.value.trim() : ""; + setBusy(btn, true); + try { + var begin = await postJSON(API + "/register/begin"); + var credential = await lib.startRegistration({ optionsJSON: begin.publicKey }); + await postJSON(API + "/register/finish", { + sessionId: begin.sessionId, + credential: credential, + name: name || "Passkey", + }); + if (nameInput) nameInput.value = ""; + window.location.reload(); + } catch (err) { + showError(err.message || String(err)); + } finally { + setBusy(btn, false); + } + } + + async function handleDelete(btn) { + var id = btn.getAttribute("data-cred-delete"); + if (!id) return; + if (!window.confirm("Remove this passkey?")) return; + setBusy(btn, true); + try { + await del(API + "/credentials/" + encodeURIComponent(id)); + var row = btn.closest("tr") || btn.closest("li") || btn.parentElement; + if (row) row.remove(); + } catch (err) { + showError(err.message || String(err)); + setBusy(btn, false); + } + } + + function init() { + var loginBtn = document.getElementById("passkey-login"); + if (loginBtn) { + loginBtn.addEventListener("click", handleLogin); + } + + var registerBtn = document.getElementById("passkey-register"); + if (registerBtn) { + registerBtn.addEventListener("click", handleRegister); + var form = registerBtn.closest("form"); + if (form) { + form.addEventListener("submit", function (e) { + e.preventDefault(); + handleRegister(e); + }); + } + } + + document.querySelectorAll("[data-cred-delete]").forEach(function (btn) { + btn.addEventListener("click", function (e) { + e.preventDefault(); + handleDelete(btn); + }); + }); + } + + if (document.readyState === "loading") { + document.addEventListener("DOMContentLoaded", init); + } else { + init(); + } +})(); diff --git a/internal/ui/static/robots.txt b/internal/ui/static/robots.txt new file mode 100644 index 00000000..1f53798b --- /dev/null +++ b/internal/ui/static/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Disallow: / diff --git a/internal/ui/static/xslt/shell.xsl b/internal/ui/static/xslt/shell.xsl new file mode 100644 index 00000000..2b5e14bb --- /dev/null +++ b/internal/ui/static/xslt/shell.xsl @@ -0,0 +1,1116 @@ + + + + + + + + + + + + remarkable + + + + + + + + + + + + + <xsl:choose> + <xsl:when test="@title != ''"><xsl:value-of select="@title"/></xsl:when> + <xsl:otherwise>rmfakecloud</xsl:otherwise> + </xsl:choose> + + + + + + + + + chrome- + + page- + + + + + + + true + + + + + + + + + + + + + + +
+ + +
+ +
+
+ + + + + + + + +
+ + + +
+ + flash flash- + + + + + info + + + +
+
+ + + + + + + + + + + + + +
  • + + nav-item + nav-item-active + + + + + nav-link + is-active + + + page + + + + + + +
  • +
    +
    + + +
    + + + +
    +
    + + + + + + + + +
    +

    rmfakecloud

    + +
    +
    + + +

    +
    + + + +
    +

    Help

    + +
    +
    + + +
    + +

    + +

    +
    + +
    +
    + + +
  • + + + + noopener noreferrer + _blank + + + + + + +
  • +
    + + + + + + + + +
    +

    Connect

    +
    + + + + + + above + + + + + + plain + + + + + + Enter this code on your tablet + + + +
    + + + +

    + + connect-prompt prompt- + + + +

    +
    + +
    + + + · · · · · · · · + +
    +

    + + connect-prompt prompt- + + + +

    + +
    + + + + + circle + + + +
    + + +
    +
    +
    +
    + + + +
    +

    Profile

    + + +
    +

    Deploy theme

    +
    +
    + + +
    + +
    + Personal color overrides + +
    + + + + override- + + + +
    +
    +
    +
    +
    + +
    +
    +
    +
    + + +
    +

    Passkeys

    + + + + + + + + + + + + + + + + + + + + + + +
    NameCreatedActions
    +
    + +
    +
    No passkeys registered.
    + + +
    + +

    Passkeys are not enabled on this server.

    +
    +
    +
    +
    + +
    +

    Change password

    +
    +
    + + +
    +
    + + +
    +
    + +
    +
    +
    +
    +
    + + + + + + + +
  • + + + +
      + +
    +
    +
  • +
    + + +
  • + + +
  • +
    + + + + + + + + + + + + + + + + + + + PDF + +
    + +
    + + +
    + + + +
    +

    Integrations

    + + + + + + + + + + + + + + + + + + + + +
    NameProviderActions
    +
    + +
    +
    No integrations yet.
    + +
    +

    Add integration

    +
    +
    + + +
    +
    + + +
    +
    + +
    +
    +
    +
    +
    + + + +
    +

    Admin

    +

    Open Theme studio

    + + + + + + + + + + + + + + + + + + + + + + + + +
    User IDEmailNameAdminActions
    + + yes + no + + +
    + +
    +
    No users.
    + +
    +

    Create user

    +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + +
    +
    +
    +
    +
    + + + +
    +

    Theme studio

    +

    Back to admin

    + +
    +

    Themes

    + + + + + + + + + + + + + + + + + + + + + +
    IDNamePublishedBuilt-inActions
    + + yes + no + + + + yes + no + + + Edit + +
    + + + + + + + + + + +
    +
    + +
    +
    +
    +
    + + +
    +

    + + Edit theme + New theme + +

    +
    +
    + + +
    +
    + + +
    +
    + + + checked + + + +
    +
    + +

    + Chrome layout styles for layout/chrome/@style and + layout/mobile/chrome/@style: + remarkable, googledocs, icloud, or os. + Unknown values fall back to remarkable. +

    + +
    +
    + +
    +
    +
    +
    +
    +
    + + + +
    +

    Screen share

    +

    Waiting for reMarkable to start screen sharing…

    +
    + + +
    +
    + + + + + + + +
    + +
    +
    + + + + + + + + +
    +
    +

    + + + EPUB + +

    +

    + Back to documents + + · + + + + Download EPUB + + +

    +
    +
    + +
    + + + + + +

    This EPUB could not be opened as a website.

    +
    +
    +
    +
    +
    +
    + + + +
    +

    + + + Error + +

    +

    + + + Something went wrong. + +

    +

    Home

    +
    +
    + + + +
    +

    Unsupported page content.

    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/internal/ui/static_embed.go b/internal/ui/static_embed.go new file mode 100644 index 00000000..da69a963 --- /dev/null +++ b/internal/ui/static_embed.go @@ -0,0 +1,29 @@ +package ui + +import ( + "embed" + "io/fs" + "net/http" + "path" + "strings" + "time" + + "github.com/ddvk/rmfakecloud/internal/common" +) + +//go:embed static/* +var staticEmbed embed.FS + +func (app *ReactAppWrapper) initStatic() { + sub, err := fs.Sub(staticEmbed, "static") + if err != nil { + panic("static embed missing: " + err.Error()) + } + app.fs = common.NewLastModifiedFS(http.FS(sub), time.Now()) + app.prefix = "/assets" +} + +func (app *ReactAppWrapper) readStatic(name string) ([]byte, error) { + name = strings.TrimPrefix(name, "/") + return staticEmbed.ReadFile(path.Join("static", name)) +} diff --git a/internal/ui/theme_css.go b/internal/ui/theme_css.go new file mode 100644 index 00000000..2c96e297 --- /dev/null +++ b/internal/ui/theme_css.go @@ -0,0 +1,248 @@ +package ui + +import ( + "bytes" + "fmt" + "regexp" + "strconv" + "strings" + + "github.com/antchfx/xmlquery" +) + +// themeToCSS ports theme-to-css.xsl in pure Go (server-side, no CGO). +func themeToCSS(themeXML []byte, formFactor string) (string, error) { + doc, err := xmlquery.Parse(bytes.NewReader(themeXML)) + if err != nil { + return "", err + } + theme := xmlquery.FindOne(doc, "/theme") + if theme == nil { + return "", fmt.Errorf("missing theme root") + } + + colors := xmlquery.FindOne(theme, "colors") + layoutPath := "layout" + if formFactor == "mobile" { + if xmlquery.FindOne(theme, "layout/mobile") != nil { + layoutPath = "layout/mobile" + } + } + chrome := xmlquery.FindOne(theme, layoutPath+"/chrome") + if chrome == nil { + chrome = xmlquery.FindOne(theme, "layout/chrome") + } + connect := xmlquery.FindOne(theme, layoutPath+"/connect") + if connect == nil { + connect = xmlquery.FindOne(theme, "layout/connect") + } + + var b strings.Builder + b.WriteString(":root {\n") + writePaletteVars(&b, colors, chrome, connect, true) + b.WriteString("}\n") + + if dark := xmlquery.FindOne(theme, "colors-dark"); dark != nil { + b.WriteString("@media (prefers-color-scheme: dark) {\n:root {\n") + writePaletteVars(&b, dark, chrome, connect, false) + b.WriteString("}\n}\n") + } + return b.String(), nil +} + +func writePaletteVars(b *strings.Builder, colors, chrome, connect *xmlquery.Node, useConnectColors bool) { + bg1 := nodeAttr(colors, "background1", "#212529") + bg2 := nodeAttr(colors, "background2", "#0f0f0f") + fg1 := nodeAttr(colors, "foreground1", "#f8f7f6") + fg2 := nodeAttr(colors, "foreground2", "#e8e3d9") + fg3 := nodeAttr(colors, "foreground3", "#e4dbaf") + action := nodeAttr(colors, "action", "#EE7B30") + accept := nodeAttr(colors, "accept", "#00e676") + reject := nodeAttr(colors, "reject", "#ff1744") + scheme := "dark" + if hexLuminance(bg1) > 0.5 { + scheme = "light" + } + + track, fill, text, pbg, pfg, pborder, code := bg2, action, fg1, bg1, fg2, fg2, fg1 + if useConnectColors { + track = nodeAttr(connect, "track-color", track) + fill = nodeAttr(connect, "fill-color", fill) + text = nodeAttr(connect, "text-color", text) + pbg = nodeAttr(connect, "prompt-bg", pbg) + pfg = nodeAttr(connect, "prompt-fg", pfg) + pborder = nodeAttr(connect, "prompt-border", pborder) + code = nodeAttr(connect, "code-color", code) + } + + fontFamily := nodeAttr(connect, "font-family", "system") + fontSize := nodeAttr(connect, "font-size", "lg") + ffCSS := `system-ui, -apple-system, "Segoe UI", Roboto, sans-serif` + switch fontFamily { + case "serif": + ffCSS = `Georgia, "Times New Roman", Times, serif` + case "mono": + ffCSS = `ui-monospace, SFMono-Regular, Menlo, Consolas, monospace` + case "rounded": + ffCSS = `"Trebuchet MS", "Segoe UI", sans-serif` + } + fsCSS := "2.75rem" + switch fontSize { + case "sm": + fsCSS = "1.5rem" + case "md": + fsCSS = "2rem" + case "xl": + fsCSS = "3.5rem" + } + + fmt.Fprintf(b, " color-scheme: %s;\n", scheme) + fmt.Fprintf(b, " --rm-color-scheme: %s;\n", scheme) + fmt.Fprintf(b, " --rm-bg-1: %s;\n", bg1) + fmt.Fprintf(b, " --rm-bg-2: %s;\n", bg2) + fmt.Fprintf(b, " --rm-fg-1: %s;\n", fg1) + fmt.Fprintf(b, " --rm-fg-2: %s;\n", fg2) + fmt.Fprintf(b, " --rm-fg-3: %s;\n", fg3) + fmt.Fprintf(b, " --rm-action: %s;\n", action) + fmt.Fprintf(b, " --rm-on-action: %s;\n", contrastOn(action)) + fmt.Fprintf(b, " --rm-accept: %s;\n", accept) + fmt.Fprintf(b, " --rm-reject: %s;\n", reject) + fmt.Fprintf(b, " --rm-connect-gauge-track: %s;\n", track) + fmt.Fprintf(b, " --rm-connect-gauge-fill: %s;\n", fill) + fmt.Fprintf(b, " --rm-connect-gauge-text: %s;\n", text) + fmt.Fprintf(b, " --rm-connect-prompt-bg: %s;\n", pbg) + fmt.Fprintf(b, " --rm-connect-prompt-fg: %s;\n", pfg) + fmt.Fprintf(b, " --rm-connect-prompt-border: %s;\n", pborder) + fmt.Fprintf(b, " --rm-connect-code-color: %s;\n", code) + fmt.Fprintf(b, " --rm-connect-font-family: %s;\n", ffCSS) + fmt.Fprintf(b, " --rm-connect-font-size: %s;\n", fsCSS) + fmt.Fprintf(b, " --rm-chrome-folder: %s;\n", nodeAttr(chrome, "folder-color", action)) + fmt.Fprintf(b, " --rm-chrome-tab: %s;\n", nodeAttr(chrome, "tab-color", action)) + fmt.Fprintf(b, " --rm-chrome-outline: %s;\n", nodeAttr(chrome, "outline-color", fg2)) + fmt.Fprintf(b, " --rm-chrome-drawer: %s;\n", nodeAttr(chrome, "drawer-color", bg2)) + fmt.Fprintf(b, " --rm-chrome-label: %s;\n", nodeAttr(chrome, "label-color", fg1)) + fmt.Fprintf(b, " --bs-body-bg: %s !important;\n", bg1) + fmt.Fprintf(b, " --bs-body-color: %s !important;\n", fg1) + fmt.Fprintf(b, " --bs-border-color: %s !important;\n", fg2) + fmt.Fprintf(b, " --bs-tertiary-bg: %s !important;\n", bg1) + fmt.Fprintf(b, " --bs-code-color: %s !important;\n", action) +} + +func nodeAttr(n *xmlquery.Node, name, fallback string) string { + if n == nil { + return fallback + } + v := strings.TrimSpace(n.SelectAttr(name)) + if v == "" { + return fallback + } + return v +} + +func hexLuminance(s string) float64 { + s = strings.TrimPrefix(strings.TrimSpace(s), "#") + if len(s) == 3 { + s = string([]byte{s[0], s[0], s[1], s[1], s[2], s[2]}) + } + if len(s) < 6 { + return 0 + } + r, err1 := strconv.ParseUint(s[0:2], 16, 8) + g, err2 := strconv.ParseUint(s[2:4], 16, 8) + b, err3 := strconv.ParseUint(s[4:6], 16, 8) + if err1 != nil || err2 != nil || err3 != nil { + return 0 + } + return (0.2126*float64(r) + 0.7152*float64(g) + 0.0722*float64(b)) / 255 +} + +func contrastOn(bg string) string { + if hexLuminance(bg) > 0.55 { + return "#111111" + } + return "#ffffff" +} + +func applyColorOverridesXML(themeXML []byte, overrides map[string]string) []byte { + if len(overrides) == 0 { + return themeXML + } + s := string(themeXML) + idx := strings.Index(s, "") + if end < 0 { + end = strings.Index(s[idx:], ">") + } + if end < 0 { + return themeXML + } + end += idx + seg := s[idx:end] + for k, v := range overrides { + if strings.TrimSpace(v) == "" { + continue + } + re := regexp.MustCompile(`\b` + regexp.QuoteMeta(k) + `="[^"]*"`) + if re.MatchString(seg) { + seg = re.ReplaceAllString(seg, k+`="`+v+`"`) + } else { + seg = strings.TrimRight(seg, " \t") + ` ` + k + `="` + v + `"` + } + } + return []byte(s[:idx] + seg + s[end:]) +} + +func normalizeChromeStyle(style string) string { + switch strings.TrimSpace(strings.ToLower(style)) { + case "remarkable", "googledocs", "icloud", "os": + return strings.ToLower(style) + default: + return "remarkable" + } +} + +func chromeStyleFromTheme(themeXML []byte, formFactor string) string { + doc, err := xmlquery.Parse(bytes.NewReader(themeXML)) + if err != nil { + return "remarkable" + } + path := "layout/chrome" + if formFactor == "mobile" && xmlquery.FindOne(doc, "/theme/layout/mobile/chrome") != nil { + path = "layout/mobile/chrome" + } + n := xmlquery.FindOne(doc, "/theme/"+path) + if n == nil { + return "remarkable" + } + return normalizeChromeStyle(n.SelectAttr("style")) +} + +func connectAttrsFromTheme(themeXML []byte, formFactor string) (gaugeType, promptLoc, promptStyle, prompt string) { + gaugeType, promptLoc, promptStyle = "circle", "above", "plain" + prompt = "Enter this one-time code on your tablet under Account → Connect." + doc, err := xmlquery.Parse(bytes.NewReader(themeXML)) + if err != nil { + return + } + path := "layout/connect" + if formFactor == "mobile" && xmlquery.FindOne(doc, "/theme/layout/mobile/connect") != nil { + path = "layout/mobile/connect" + } + n := xmlquery.FindOne(doc, "/theme/"+path) + if n == nil { + return + } + if v := n.SelectAttr("gauge-type"); v != "" { + gaugeType = v + } + if v := n.SelectAttr("prompt-location"); v != "" { + promptLoc = v + } + if v := n.SelectAttr("prompt-style"); v != "" { + promptStyle = v + } + return +} diff --git a/internal/ui/theme_css_test.go b/internal/ui/theme_css_test.go new file mode 100644 index 00000000..add4d30b --- /dev/null +++ b/internal/ui/theme_css_test.go @@ -0,0 +1,68 @@ +package ui + +import ( + "strings" + "testing" +) + +func TestThemeToCSSPalettes(t *testing.T) { + cases := []struct { + id string + want string + scheme string + }{ + {"light", "--rm-bg-1: #f7f4ef", "color-scheme: light"}, + {"dark", "--rm-bg-1: #212529", "color-scheme: dark"}, + {"hicontrast", "--rm-fg-1: #ffffff", "color-scheme: dark"}, + } + s := newThemeStore(t.TempDir()) + for _, tc := range cases { + xml, _, err := s.getXML(tc.id) + if err != nil { + t.Fatal(err) + } + css, err := themeToCSS(xml, "desktop") + if err != nil { + t.Fatal(err) + } + if !strings.Contains(css, tc.want) { + t.Fatalf("%s missing %q in %s", tc.id, tc.want, css) + } + if !strings.Contains(css, tc.scheme) { + t.Fatalf("%s missing %q", tc.id, tc.scheme) + } + if !strings.Contains(css, "--rm-on-action:") { + t.Fatalf("%s missing on-action", tc.id) + } + } +} + +func TestThemeToCSSSystemFollowsPrefersColorScheme(t *testing.T) { + s := newThemeStore(t.TempDir()) + xml, _, err := s.getXML("system") + if err != nil { + t.Fatal(err) + } + css, err := themeToCSS(xml, "desktop") + if err != nil { + t.Fatal(err) + } + if !strings.Contains(css, "@media (prefers-color-scheme: dark)") { + t.Fatalf("system theme should emit dark media query:\n%s", css) + } + if !strings.Contains(css, "--rm-bg-1: #f7f4ef") || !strings.Contains(css, "--rm-bg-1: #212529") { + t.Fatalf("system theme should include light and dark backgrounds:\n%s", css) + } +} + +func TestHexLuminance(t *testing.T) { + if hexLuminance("#ffffff") < 0.9 { + t.Fatal("white should be light") + } + if hexLuminance("#000000") > 0.1 { + t.Fatal("black should be dark") + } + if contrastOn("#ffff00") != "#111111" { + t.Fatal("yellow needs dark text") + } +} diff --git a/internal/ui/theme_handlers.go b/internal/ui/theme_handlers.go new file mode 100644 index 00000000..59cf8002 --- /dev/null +++ b/internal/ui/theme_handlers.go @@ -0,0 +1,260 @@ +package ui + +import ( + "net/http" + "strings" + + "github.com/ddvk/rmfakecloud/internal/common" + "github.com/gin-gonic/gin" +) + +type profileThemeRequest struct { + ThemeID string `json:"themeId"` + ThemeColorOverrides map[string]string `json:"themeColorOverrides"` +} + +type saveThemeRequest struct { + ID string `json:"id"` + Name string `json:"name"` + Published bool `json:"published"` + XML string `json:"xml"` +} + +func (app *ReactAppWrapper) listThemes(c *gin.Context) { + admin := IsAdmin(c) + list, err := app.themes.list(admin) + if err != nil { + c.AbortWithStatus(http.StatusInternalServerError) + return + } + c.JSON(http.StatusOK, list) +} + +func isAdminContext(c *gin.Context) bool { + return IsAdmin(c) +} + +func (app *ReactAppWrapper) getThemePublic(c *gin.Context) { + id := c.Param("id") + xmlBytes, builtin, err := app.themes.getXML(id) + if err != nil { + c.AbortWithStatus(http.StatusNotFound) + return + } + root, err := parseThemeRoot(xmlBytes) + if err != nil { + c.AbortWithStatus(http.StatusInternalServerError) + return + } + published := strings.EqualFold(root.Published, "true") || root.Published == "" + if !published && !app.tryIsAdmin(c) { + c.AbortWithStatus(http.StatusNotFound) + return + } + setFormFactorHeaders(c) + c.JSON(http.StatusOK, gin.H{ + "id": id, + "name": root.Name, + "published": published, + "builtin": builtin, + "xml": string(xmlBytes), + "formFactor": clientFormFactor(c.Request), + "assets": gin.H{ + "cssXsl": "/ui/api/themes/assets/theme-to-css.xsl", + "layoutXsl": "/ui/api/themes/assets/theme-to-layout.xsl", + }, + }) +} + +func (app *ReactAppWrapper) tryIsAdmin(c *gin.Context) bool { + token, err := c.Cookie(cookieName) + if err != nil { + token, err = common.GetToken(c) + } + if err != nil || token == "" { + return false + } + claims := &WebUserClaims{} + if err := common.ClaimsFromToken(claims, token, app.cfg.JWTSecretKey); err != nil { + return false + } + for _, r := range claims.Roles { + if r == AdminRole { + return true + } + } + return false +} + +func (app *ReactAppWrapper) updateTheme(c *gin.Context) { + id := c.Param("id") + var req saveThemeRequest + if err := c.ShouldBindJSON(&req); err != nil || req.XML == "" { + c.AbortWithStatus(http.StatusBadRequest) + return + } + if req.ID == "" { + req.ID = id + } + if req.ID != id { + c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "id mismatch"}) + return + } + if err := app.themes.save(req.ID, req.Name, req.Published, []byte(req.XML)); err != nil { + c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + c.JSON(http.StatusOK, gin.H{"ok": true, "id": req.ID}) +} + +func (app *ReactAppWrapper) getThemeAsset(c *gin.Context) { + name := c.Param("name") + b, err := app.themes.asset(name) + if err != nil { + c.AbortWithStatus(http.StatusNotFound) + return + } + ct := "application/xslt+xml" + if strings.HasSuffix(name, ".xml") { + ct = "application/xml" + } + c.Data(http.StatusOK, ct, b) +} + +func (app *ReactAppWrapper) saveTheme(c *gin.Context) { + var req saveThemeRequest + if err := c.ShouldBindJSON(&req); err != nil || req.ID == "" || req.XML == "" { + c.AbortWithStatus(http.StatusBadRequest) + return + } + if err := app.themes.save(req.ID, req.Name, req.Published, []byte(req.XML)); err != nil { + c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + c.JSON(http.StatusOK, gin.H{"ok": true, "id": req.ID}) +} + +func (app *ReactAppWrapper) publishTheme(c *gin.Context) { + id := c.Param("id") + var body struct { + Published bool `json:"published"` + } + body.Published = true + _ = c.ShouldBindJSON(&body) + if err := app.themes.setPublished(id, body.Published); err != nil { + c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + c.JSON(http.StatusOK, gin.H{"ok": true}) +} + +func (app *ReactAppWrapper) deleteTheme(c *gin.Context) { + id := c.Param("id") + if err := app.themes.delete(id); err != nil { + c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + c.Status(http.StatusNoContent) +} + +func (app *ReactAppWrapper) getProfileTheme(c *gin.Context) { + uid := userID(c) + user, err := app.userStorer.GetUser(uid) + if err != nil || user == nil { + c.AbortWithStatus(http.StatusUnauthorized) + return + } + themeID := user.ThemeID + if themeID == "" { + themeID = "default" + } + c.JSON(http.StatusOK, gin.H{ + "themeId": themeID, + "themeColorOverrides": user.ThemeColorOverrides, + "formFactor": clientFormFactor(c.Request), + }) +} + +func (app *ReactAppWrapper) putProfileTheme(c *gin.Context) { + var req profileThemeRequest + if err := c.ShouldBindJSON(&req); err != nil { + c.AbortWithStatus(http.StatusBadRequest) + return + } + if req.ThemeID == "" { + req.ThemeID = "default" + } + xmlBytes, _, err := app.themes.getXML(req.ThemeID) + if err != nil { + c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "unknown theme"}) + return + } + root, err := parseThemeRoot(xmlBytes) + if err != nil { + c.AbortWithStatus(http.StatusInternalServerError) + return + } + published := strings.EqualFold(root.Published, "true") || root.Published == "" + if !published && !isAdminContext(c) { + c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "theme is not published"}) + return + } + uid := userID(c) + user, err := app.userStorer.GetUser(uid) + if err != nil || user == nil { + c.AbortWithStatus(http.StatusUnauthorized) + return + } + user.ThemeID = req.ThemeID + user.ThemeColorOverrides = sanitizeColorOverrides(req.ThemeColorOverrides) + if err := app.userStorer.UpdateUser(user); err != nil { + c.AbortWithStatus(http.StatusInternalServerError) + return + } + c.JSON(http.StatusOK, gin.H{ + "themeId": user.ThemeID, + "themeColorOverrides": user.ThemeColorOverrides, + }) +} + +func sanitizeColorOverrides(in map[string]string) map[string]string { + if len(in) == 0 { + return nil + } + allowed := map[string]bool{ + "background1": true, "background2": true, + "foreground1": true, "foreground2": true, "foreground3": true, + "action": true, "accept": true, "reject": true, + } + out := make(map[string]string) + for k, v := range in { + if !allowed[k] { + continue + } + v = strings.TrimSpace(v) + if v == "" || !isSafeCSSColor(v) { + continue + } + out[k] = v + } + if len(out) == 0 { + return nil + } + return out +} + +func isSafeCSSColor(v string) bool { + if len(v) > 32 { + return false + } + // #rgb, #rrggbb, or simple rgb()/named short + if strings.HasPrefix(v, "#") { + for _, ch := range v[1:] { + if !((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F')) { + return false + } + } + return len(v) == 4 || len(v) == 7 + } + return false +} diff --git a/internal/ui/theme_store.go b/internal/ui/theme_store.go new file mode 100644 index 00000000..5184159e --- /dev/null +++ b/internal/ui/theme_store.go @@ -0,0 +1,300 @@ +package ui + +import ( + "embed" + "encoding/xml" + "errors" + "fmt" + "io/fs" + "os" + "path/filepath" + "regexp" + "sort" + "strings" + "sync" +) + +//go:embed themes/* +var builtinThemesFS embed.FS + +var themeIDPattern = regexp.MustCompile(`^[a-zA-Z0-9][a-zA-Z0-9_-]{0,63}$`) + +// ThemeMeta is list metadata for a shell theme. +type ThemeMeta struct { + ID string `json:"id"` + Name string `json:"name"` + Published bool `json:"published"` + Builtin bool `json:"builtin"` +} + +type themeXMLRoot struct { + XMLName xml.Name `xml:"theme"` + ID string `xml:"id,attr"` + Name string `xml:"name,attr"` + Published string `xml:"published,attr"` +} + +type themeStore struct { + dir string + mu sync.RWMutex +} + +func newThemeStore(dataDir string) *themeStore { + dir := filepath.Join(dataDir, "themes") + _ = os.MkdirAll(dir, 0o755) + return &themeStore{dir: dir} +} + +func (s *themeStore) list(includeUnpublished bool) ([]ThemeMeta, error) { + s.mu.RLock() + defer s.mu.RUnlock() + + byID := map[string]ThemeMeta{} + + for _, id := range s.builtinIDs() { + meta, err := s.readBuiltinMeta(id) + if err != nil { + continue + } + byID[meta.ID] = meta + } + + entries, err := os.ReadDir(s.dir) + if err != nil && !os.IsNotExist(err) { + return nil, err + } + for _, e := range entries { + if !e.IsDir() { + continue + } + id := e.Name() + if !themeIDPattern.MatchString(id) { + continue + } + meta, err := s.readDiskMeta(id) + if err != nil { + continue + } + byID[id] = meta + } + + _, hasDark := byID["dark"] + out := make([]ThemeMeta, 0, len(byID)) + for _, m := range byID { + if !includeUnpublished && !m.Published { + continue + } + if m.ID == "default" && hasDark { + continue + } + out = append(out, m) + } + sortThemes(out) + return out, nil +} + +func (s *themeStore) builtinIDs() []string { + entries, err := fs.ReadDir(builtinThemesFS, "themes") + if err != nil { + return []string{"default"} + } + ids := make([]string, 0, len(entries)) + for _, e := range entries { + name := e.Name() + if e.IsDir() || !strings.HasSuffix(name, ".xml") { + continue + } + id := strings.TrimSuffix(name, ".xml") + if themeIDPattern.MatchString(id) { + ids = append(ids, id) + } + } + return ids +} + +func sortThemes(out []ThemeMeta) { + rank := map[string]int{"light": 0, "dark": 1, "system": 2, "hicontrast": 3} + sort.Slice(out, func(i, j int) bool { + ri, iok := rank[out[i].ID] + rj, jok := rank[out[j].ID] + if iok && jok { + return ri < rj + } + if iok { + return true + } + if jok { + return false + } + return strings.ToLower(out[i].Name) < strings.ToLower(out[j].Name) + }) +} + +func (s *themeStore) getXML(id string) ([]byte, bool, error) { + s.mu.RLock() + defer s.mu.RUnlock() + if !themeIDPattern.MatchString(id) { + return nil, false, errors.New("invalid theme id") + } + path := filepath.Join(s.dir, id, "theme.xml") + if b, err := os.ReadFile(path); err == nil { + return b, false, nil + } + b, err := builtinThemesFS.ReadFile("themes/" + id + ".xml") + if err != nil { + return nil, false, fs.ErrNotExist + } + return b, true, nil +} + +func (s *themeStore) asset(name string) ([]byte, error) { + name = filepath.Base(name) + return builtinThemesFS.ReadFile("themes/" + name) +} + +func (s *themeStore) save(id, name string, published bool, xmlBytes []byte) error { + if !themeIDPattern.MatchString(id) { + return errors.New("invalid theme id") + } + if err := validateThemeXML(xmlBytes); err != nil { + return err + } + // Ensure id/name/published attrs match + xmlBytes, err := ensureThemeAttrs(xmlBytes, id, name, published) + if err != nil { + return err + } + + s.mu.Lock() + defer s.mu.Unlock() + dir := filepath.Join(s.dir, id) + if err := os.MkdirAll(dir, 0o755); err != nil { + return err + } + return os.WriteFile(filepath.Join(dir, "theme.xml"), xmlBytes, 0o644) +} + +func (s *themeStore) setPublished(id string, published bool) error { + b, builtin, err := s.getXML(id) + if err != nil { + return err + } + root, err := parseThemeRoot(b) + if err != nil { + return err + } + if builtin { + // Materialize builtin to disk before changing publish state + return s.save(id, root.Name, published, b) + } + return s.save(id, root.Name, published, b) +} + +func (s *themeStore) delete(id string) error { + if id == "default" || id == "light" || id == "dark" || id == "system" || id == "hicontrast" { + return errors.New("cannot delete a built-in theme") + } + if !themeIDPattern.MatchString(id) { + return errors.New("invalid theme id") + } + s.mu.Lock() + defer s.mu.Unlock() + path := filepath.Join(s.dir, id) + if _, err := os.Stat(path); err != nil { + return fs.ErrNotExist + } + return os.RemoveAll(path) +} + +func (s *themeStore) readDiskMeta(id string) (ThemeMeta, error) { + b, err := os.ReadFile(filepath.Join(s.dir, id, "theme.xml")) + if err != nil { + return ThemeMeta{}, err + } + root, err := parseThemeRoot(b) + if err != nil { + return ThemeMeta{}, err + } + return ThemeMeta{ + ID: id, + Name: root.Name, + Published: strings.EqualFold(root.Published, "true") || root.Published == "", + Builtin: false, + }, nil +} + +func (s *themeStore) readBuiltinMeta(id string) (ThemeMeta, error) { + b, err := builtinThemesFS.ReadFile("themes/" + id + ".xml") + if err != nil { + return ThemeMeta{}, err + } + root, err := parseThemeRoot(b) + if err != nil { + return ThemeMeta{}, err + } + name := root.Name + if name == "" { + name = id + } + return ThemeMeta{ + ID: id, + Name: name, + Published: strings.EqualFold(root.Published, "true") || root.Published == "", + Builtin: true, + }, nil +} + +func parseThemeRoot(b []byte) (themeXMLRoot, error) { + var root themeXMLRoot + if err := xml.Unmarshal(b, &root); err != nil { + return root, fmt.Errorf("invalid theme xml: %w", err) + } + if root.ID == "" { + return root, errors.New("theme id attribute required") + } + return root, nil +} + +func validateThemeXML(b []byte) error { + root, err := parseThemeRoot(b) + if err != nil { + return err + } + if !themeIDPattern.MatchString(root.ID) { + return errors.New("invalid theme id in xml") + } + // Must have colors and layout elements + if !strings.Contains(string(b), "]*>`) + s = re.ReplaceAllString(s, fmt.Sprintf(``, xmlEscapeAttr(id), xmlEscapeAttr(name), pub)) + return []byte(s), nil +} + +func xmlEscapeAttr(v string) string { + v = strings.ReplaceAll(v, `&`, `&`) + v = strings.ReplaceAll(v, `"`, `"`) + v = strings.ReplaceAll(v, `<`, `<`) + return v +} diff --git a/internal/ui/theme_store_test.go b/internal/ui/theme_store_test.go new file mode 100644 index 00000000..60f152be --- /dev/null +++ b/internal/ui/theme_store_test.go @@ -0,0 +1,89 @@ +package ui + +import ( + "os" + "path/filepath" + "testing" +) + +func TestValidateAndSaveTheme(t *testing.T) { + dir := t.TempDir() + s := newThemeStore(dir) + xml := []byte(` + + + + + + + +`) + if err := s.save("ocean", "Ocean", false, xml); err != nil { + t.Fatal(err) + } + list, err := s.list(false) + if err != nil { + t.Fatal(err) + } + for _, m := range list { + if m.ID == "ocean" { + t.Fatal("unpublished should be hidden from public list") + } + } + list, err = s.list(true) + if err != nil { + t.Fatal(err) + } + found := false + for _, m := range list { + if m.ID == "ocean" { + found = true + } + } + if !found { + t.Fatal("admin list should include ocean") + } + if _, err := os.Stat(filepath.Join(dir, "themes", "ocean", "theme.xml")); err != nil { + t.Fatal(err) + } +} + +func TestBuiltinDefault(t *testing.T) { + s := newThemeStore(t.TempDir()) + b, builtin, err := s.getXML("default") + if err != nil || !builtin || len(b) == 0 { + t.Fatalf("builtin default: err=%v builtin=%v len=%d", err, builtin, len(b)) + } +} + +func TestBuiltinPalettesListed(t *testing.T) { + s := newThemeStore(t.TempDir()) + list, err := s.list(false) + if err != nil { + t.Fatal(err) + } + want := []string{"light", "dark", "system", "hicontrast"} + got := map[string]bool{} + order := make([]string, 0, len(list)) + for _, m := range list { + got[m.ID] = true + order = append(order, m.ID) + if m.ID == "default" { + t.Fatal("default should be hidden when dark exists") + } + } + for _, id := range want { + if !got[id] { + t.Fatalf("missing builtin %s in %v", id, order) + } + xml, builtin, err := s.getXML(id) + if err != nil || !builtin || len(xml) == 0 { + t.Fatalf("%s: err=%v builtin=%v len=%d", id, err, builtin, len(xml)) + } + } + if len(order) < 4 || order[0] != "light" || order[1] != "dark" || order[2] != "system" || order[3] != "hicontrast" { + t.Fatalf("unexpected order %v", order) + } +} diff --git a/internal/ui/themes/dark.xml b/internal/ui/themes/dark.xml new file mode 100644 index 00000000..132016c7 --- /dev/null +++ b/internal/ui/themes/dark.xml @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + diff --git a/internal/ui/themes/default.xml b/internal/ui/themes/default.xml new file mode 100644 index 00000000..6b7f466a --- /dev/null +++ b/internal/ui/themes/default.xml @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + diff --git a/internal/ui/themes/hicontrast.xml b/internal/ui/themes/hicontrast.xml new file mode 100644 index 00000000..3bd6e3f4 --- /dev/null +++ b/internal/ui/themes/hicontrast.xml @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + diff --git a/internal/ui/themes/light.xml b/internal/ui/themes/light.xml new file mode 100644 index 00000000..a9d9a07d --- /dev/null +++ b/internal/ui/themes/light.xml @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + diff --git a/internal/ui/themes/system.xml b/internal/ui/themes/system.xml new file mode 100644 index 00000000..757640a4 --- /dev/null +++ b/internal/ui/themes/system.xml @@ -0,0 +1,100 @@ + + + + + + + + + + + + + + + + + + diff --git a/internal/ui/themes/theme-to-css.xsl b/internal/ui/themes/theme-to-css.xsl new file mode 100644 index 00000000..863e72ad --- /dev/null +++ b/internal/ui/themes/theme-to-css.xsl @@ -0,0 +1,172 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + color-scheme: ; + --rm-color-scheme: ; + --rm-bg-1: ; + --rm-bg-2: ; + --rm-fg-1: ; + --rm-fg-2: ; + --rm-fg-3: ; + --rm-action: ; + --rm-on-action: #111111; + --rm-accept: ; + --rm-reject: ; + --rm-connect-gauge-track: + + + + + + + ; + --rm-connect-gauge-fill: + + + + + + + ; + --rm-connect-gauge-text: + + + + + + + ; + --rm-connect-prompt-bg: + + + + + + + ; + --rm-connect-prompt-fg: + + + + + + + ; + --rm-connect-prompt-border: + + + + + + + ; + --rm-connect-code-color: + + + + + + + ; + --rm-connect-font-family: + + Georgia, "Times New Roman", Times, serif + ui-monospace, SFMono-Regular, Menlo, Consolas, monospace + "Trebuchet MS", "Segoe UI", sans-serif + system-ui, -apple-system, "Segoe UI", Roboto, sans-serif + + ; + --rm-connect-font-size: + + 1.5rem + 2rem + 3.5rem + 2.75rem + + ; + --rm-chrome-folder: + + ; + --rm-chrome-tab: + + ; + --rm-chrome-outline: + + ; + --rm-chrome-drawer: + + ; + --rm-chrome-label: + + ; + --bs-body-bg: !important; + --bs-body-color: !important; + --bs-border-color: !important; + --bs-tertiary-bg: !important; + --bs-code-color: !important; + + + + + + + light + dark + + + :root { + + + + + + + + + } + + + @media (prefers-color-scheme: dark) { +:root { + + + + + + + + + } +} + + + + diff --git a/internal/ui/themes/theme-to-layout.xsl b/internal/ui/themes/theme-to-layout.xsl new file mode 100644 index 00000000..f3204054 --- /dev/null +++ b/internal/ui/themes/theme-to-layout.xsl @@ -0,0 +1,55 @@ + + + + + + + + + + + + + diff --git a/internal/ui/ui.go b/internal/ui/ui.go index 6a7d6c98..ea069c4c 100644 --- a/internal/ui/ui.go +++ b/internal/ui/ui.go @@ -2,10 +2,7 @@ package ui import ( "io" - "io/fs" "net/http" - "path" - "time" "github.com/ddvk/rmfakecloud/internal/app/hub" "github.com/ddvk/rmfakecloud/internal/app/passcodestore" @@ -14,10 +11,12 @@ import ( "github.com/ddvk/rmfakecloud/internal/messages" "github.com/ddvk/rmfakecloud/internal/screenshare" "github.com/ddvk/rmfakecloud/internal/storage" + "github.com/ddvk/rmfakecloud/internal/storage/epub" "github.com/ddvk/rmfakecloud/internal/storage/models" "github.com/ddvk/rmfakecloud/internal/ui/viewmodel" - webui "github.com/ddvk/rmfakecloud/ui" "github.com/gin-gonic/gin" + "github.com/go-webauthn/webauthn/webauthn" + log "github.com/sirupsen/logrus" ) type backend interface { @@ -31,6 +30,7 @@ type backend interface { } type codeGenerator interface { NewCode(string) (string, error) + CurrentCode(string) (string, bool) } type documentHandler interface { @@ -51,6 +51,12 @@ type blobHandler interface { CreateBlobFolder(uid, name, parent string) (doc *storage.Document, err error) Export(uid, docid string) (io.ReadCloser, error) ExportRmDoc(uid, docid string) (io.ReadCloser, error) + ExportPagePNG(uid, docid string, pageNum int) (io.ReadCloser, error) + GetEpub(uid, docid string) (io.ReadCloser, error) + GetEpubManifest(uid, docid string) (*epub.Manifest, error) + GetEpubFile(uid, docid, filePath string) (io.ReadCloser, string, error) + GetEpubCoverThumb(uid, docid string) (io.ReadCloser, string, error) + GetEpubPageThumb(uid, docid string, pageIndex0 int) (io.ReadCloser, string, error) } type notificationHub interface { @@ -65,25 +71,24 @@ type mqttBridge interface { HasConnectedClient(userID string) bool } -// ReactAppWrapper encapsulates an app +// ReactAppWrapper encapsulates the web UI (XML/XSLT pages + JSON APIs). type ReactAppWrapper struct { - fs http.FileSystem - prefix string - cfg *config.Config - userStorer storage.UserStorer - codeConnector codeGenerator - h *hub.Hub - passcodeStore passcodestore.Store - backends map[common.SyncVersion]backend - roomManager *screenshare.RoomManager - mqtt mqttBridge + fs http.FileSystem + prefix string + cfg *config.Config + userStorer storage.UserStorer + codeConnector codeGenerator + h *hub.Hub + passcodeStore passcodestore.Store + backends map[common.SyncVersion]backend + roomManager *screenshare.RoomManager + mqtt mqttBridge + webAuthn *webauthn.WebAuthn + webAuthnSessions *webAuthnSessionStore + themes *themeStore } -// hack for serving index.html on / -const indexReplacement = "/default" -const jsBuildFolder = "dist" - -// New Create a React app +// New creates the web UI app. func New(cfg *config.Config, userStorer storage.UserStorer, codeConnector codeGenerator, @@ -94,10 +99,6 @@ func New(cfg *config.Config, roomManager *screenshare.RoomManager, mqttBroker mqttBridge) *ReactAppWrapper { - sub, err := fs.Sub(webui.Assets, jsBuildFolder) - if err != nil { - panic("not embedded?") - } backend15 := &backend15{ blobHandler: blobHandler, h: h, @@ -106,8 +107,7 @@ func New(cfg *config.Config, documentHandler: docHandler, hub: h, } - staticWrapper := ReactAppWrapper{ - fs: common.NewLastModifiedFS(http.FS(sub), time.Now()), + staticWrapper := &ReactAppWrapper{ prefix: "/assets", cfg: cfg, userStorer: userStorer, @@ -120,22 +120,25 @@ func New(cfg *config.Config, }, roomManager: roomManager, mqtt: mqttBroker, + themes: newThemeStore(cfg.DataDir), } - return &staticWrapper -} - -// Open opens a file from the fs (virtual) -func (w ReactAppWrapper) Open(filepath string) (http.File, error) { - fullpath := filepath - //index.html hack - if filepath != indexReplacement { - fullpath = path.Join(w.prefix, filepath) - } else { - fullpath = "/index.html" + staticWrapper.initStatic() + if cfg != nil && cfg.WebAuthn { + wa, err := webauthn.New(&webauthn.Config{ + RPDisplayName: "rmfakecloud", + RPID: cfg.WebAuthnRPID, + RPOrigins: cfg.WebAuthnOrigins, + }) + if err != nil { + log.Errorf("webauthn init failed, passkeys disabled: %v", err) + } else { + staticWrapper.webAuthn = wa + staticWrapper.webAuthnSessions = newWebAuthnSessionStore() + } } - f, err := w.fs.Open(fullpath) - return f, err + return staticWrapper } + func badReq(c *gin.Context, message string) { c.AbortWithStatusJSON(http.StatusBadRequest, viewmodel.NewErrorResponse(message)) } diff --git a/internal/ui/viewmodel/models.go b/internal/ui/viewmodel/models.go index d58ed65f..228ac101 100644 --- a/internal/ui/viewmodel/models.go +++ b/internal/ui/viewmodel/models.go @@ -35,8 +35,9 @@ type ChangeEmailForm struct { type ErrorResponse struct { Error string `json:"error"` } + func NewErrorResponse(errormsg string) ErrorResponse { - return ErrorResponse { + return ErrorResponse{ Error: errormsg, } } @@ -57,6 +58,8 @@ type InternalDoc struct { CurrentPage int Parent string Size int64 + PageCount int + Pinned bool } func makeFolder(d *InternalDoc) (entry *Directory) { @@ -66,6 +69,7 @@ func makeFolder(d *InternalDoc) (entry *Directory) { LastModified: d.LastModified, Entries: make([]Entry, 0), IsFolder: true, + Pinned: d.Pinned, } return } @@ -76,6 +80,9 @@ func makeDocument(d *InternalDoc) (entry Entry) { LastModified: d.LastModified, DocumentType: d.FileType, Size: d.Size, + CurrentPage: d.CurrentPage, + PageCount: d.PageCount, + Pinned: d.Pinned, } return } @@ -98,8 +105,11 @@ func DocTreeFromHashTree(tree *models.HashTree) *DocumentTree { Name: d.MetadataFile.DocumentName, Type: d.MetadataFile.CollectionType, LastModified: lastModified, - FileType: d.PayloadType, + FileType: d.EffectivePayloadType(), Size: d.Size, + CurrentPage: d.LastOpenedPage, + PageCount: d.PageCount, + Pinned: d.Pinned, }) } @@ -194,6 +204,7 @@ type Directory struct { Entries []Entry `json:"children"` LastModified time.Time `json:"lastModified"` IsFolder bool `json:"isFolder"` + Pinned bool `json:"pinned"` } // Document is a single document @@ -203,6 +214,9 @@ type Document struct { DocumentType string `json:"type"` //notebook, pdf, epub LastModified time.Time `json:"lastModified"` Size int64 `json:"size"` + CurrentPage int `json:"currentPage"` + PageCount int `json:"pageCount"` + Pinned bool `json:"pinned"` } // DocumentList is a list of documents @@ -216,7 +230,7 @@ type User struct { Email string `json:"email"` Name string `json:"name"` NewPassword string `json:"newpassword,omitempty"` - IsAdmin bool `json:"isAdmin"` + IsAdmin bool `json:"isAdmin"` CreatedAt time.Time Integrations []string `json:"integrations,omitempty"` } diff --git a/internal/ui/webauthn_handlers.go b/internal/ui/webauthn_handlers.go new file mode 100644 index 00000000..aad46e26 --- /dev/null +++ b/internal/ui/webauthn_handlers.go @@ -0,0 +1,257 @@ +package ui + +import ( + "bytes" + "encoding/json" + "net/http" + "strings" + "time" + + "github.com/ddvk/rmfakecloud/internal/model" + "github.com/gin-gonic/gin" + "github.com/go-webauthn/webauthn/protocol" + "github.com/go-webauthn/webauthn/webauthn" + "github.com/google/uuid" + log "github.com/sirupsen/logrus" +) + +type webAuthnCeremonyResponse struct { + SessionID string `json:"sessionId"` + Options interface{} `json:"publicKey"` +} + +type webAuthnFinishRequest struct { + SessionID string `json:"sessionId"` + Credential json.RawMessage `json:"credential"` + Name string `json:"name,omitempty"` +} + +type webAuthnCredentialView struct { + ID string `json:"id"` + Name string `json:"name"` + CreatedAt time.Time `json:"createdAt"` +} + +func (app *ReactAppWrapper) webAuthnEnabled() bool { + return app.cfg != nil && app.cfg.WebAuthn && app.webAuthn != nil && app.webAuthnSessions != nil +} + +func (app *ReactAppWrapper) webAuthnStatus(c *gin.Context) { + c.JSON(http.StatusOK, gin.H{"enabled": app.webAuthnEnabled()}) +} + +func (app *ReactAppWrapper) webAuthnRegisterBegin(c *gin.Context) { + if !app.webAuthnEnabled() { + c.AbortWithStatus(http.StatusNotFound) + return + } + uid := userID(c) + user, err := app.userStorer.GetUser(uid) + if err != nil || user == nil { + log.Error(uiLogger, "webauthn register begin: ", err) + c.AbortWithStatus(http.StatusUnauthorized) + return + } + waUser := model.WebAuthnUser{User: user} + opts := []webauthn.RegistrationOption{ + webauthn.WithResidentKeyRequirement(protocol.ResidentKeyRequirementPreferred), + webauthn.WithAuthenticatorSelection(protocol.AuthenticatorSelection{ + ResidentKey: protocol.ResidentKeyRequirementPreferred, + UserVerification: protocol.VerificationPreferred, + }), + } + creation, session, err := app.webAuthn.BeginRegistration(waUser, opts...) + if err != nil { + log.Error(uiLogger, "webauthn BeginRegistration: ", err) + c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + sid := app.webAuthnSessions.Put(session) + c.JSON(http.StatusOK, webAuthnCeremonyResponse{ + SessionID: sid, + Options: creation.Response, + }) +} + +func (app *ReactAppWrapper) webAuthnRegisterFinish(c *gin.Context) { + if !app.webAuthnEnabled() { + c.AbortWithStatus(http.StatusNotFound) + return + } + var req webAuthnFinishRequest + if err := c.ShouldBindJSON(&req); err != nil || req.SessionID == "" || len(req.Credential) == 0 { + c.AbortWithStatus(http.StatusBadRequest) + return + } + session, ok := app.webAuthnSessions.Take(req.SessionID) + if !ok { + c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "invalid or expired session"}) + return + } + uid := userID(c) + user, err := app.userStorer.GetUser(uid) + if err != nil || user == nil { + c.AbortWithStatus(http.StatusUnauthorized) + return + } + parsed, err := protocol.ParseCredentialCreationResponseBody(bytes.NewReader(req.Credential)) + if err != nil { + log.Error(uiLogger, "webauthn parse register: ", err) + c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "invalid credential"}) + return + } + cred, err := app.webAuthn.CreateCredential(model.WebAuthnUser{User: user}, session, parsed) + if err != nil { + log.Error(uiLogger, "webauthn CreateCredential: ", err) + c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + name := strings.TrimSpace(req.Name) + if name == "" { + name = "Passkey" + } + user.WebAuthnCredentials = append(user.WebAuthnCredentials, model.FromLibraryCredential(cred, name)) + user.UpdatedAt = time.Now() + if err := app.userStorer.UpdateUser(user); err != nil { + log.Error(uiLogger, "webauthn save credential: ", err) + c.AbortWithStatus(http.StatusInternalServerError) + return + } + c.JSON(http.StatusOK, gin.H{ + "id": model.CredentialIDBase64(cred.ID), + "name": name, + }) +} + +func (app *ReactAppWrapper) webAuthnListCredentials(c *gin.Context) { + if !app.webAuthnEnabled() { + c.AbortWithStatus(http.StatusNotFound) + return + } + uid := userID(c) + user, err := app.userStorer.GetUser(uid) + if err != nil || user == nil { + c.AbortWithStatus(http.StatusUnauthorized) + return + } + out := make([]webAuthnCredentialView, 0, len(user.WebAuthnCredentials)) + for _, cred := range user.WebAuthnCredentials { + out = append(out, webAuthnCredentialView{ + ID: model.CredentialIDBase64(cred.ID), + Name: cred.Name, + CreatedAt: cred.CreatedAt, + }) + } + c.JSON(http.StatusOK, out) +} + +func (app *ReactAppWrapper) webAuthnDeleteCredential(c *gin.Context) { + if !app.webAuthnEnabled() { + c.AbortWithStatus(http.StatusNotFound) + return + } + credID, err := model.ParseCredentialIDBase64(c.Param("id")) + if err != nil || len(credID) == 0 { + c.AbortWithStatus(http.StatusBadRequest) + return + } + uid := userID(c) + user, err := app.userStorer.GetUser(uid) + if err != nil || user == nil { + c.AbortWithStatus(http.StatusUnauthorized) + return + } + if !user.RemoveWebAuthnCredential(credID) { + c.AbortWithStatus(http.StatusNotFound) + return + } + user.UpdatedAt = time.Now() + if err := app.userStorer.UpdateUser(user); err != nil { + log.Error(uiLogger, "webauthn delete credential: ", err) + c.AbortWithStatus(http.StatusInternalServerError) + return + } + c.Status(http.StatusNoContent) +} + +func (app *ReactAppWrapper) webAuthnLoginBegin(c *gin.Context) { + if !app.webAuthnEnabled() { + c.AbortWithStatus(http.StatusNotFound) + return + } + assertion, session, err := app.webAuthn.BeginDiscoverableLogin( + webauthn.WithUserVerification(protocol.VerificationPreferred), + ) + if err != nil { + log.Error(uiLogger, "webauthn BeginDiscoverableLogin: ", err) + c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + sid := app.webAuthnSessions.Put(session) + c.JSON(http.StatusOK, webAuthnCeremonyResponse{ + SessionID: sid, + Options: assertion.Response, + }) +} + +func (app *ReactAppWrapper) webAuthnLoginFinish(c *gin.Context) { + if !app.webAuthnEnabled() { + c.AbortWithStatus(http.StatusNotFound) + return + } + var req webAuthnFinishRequest + if err := c.ShouldBindJSON(&req); err != nil || req.SessionID == "" || len(req.Credential) == 0 { + c.AbortWithStatus(http.StatusBadRequest) + return + } + session, ok := app.webAuthnSessions.Take(req.SessionID) + if !ok { + c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "invalid or expired session"}) + return + } + parsed, err := protocol.ParseCredentialRequestResponseBody(bytes.NewReader(req.Credential)) + if err != nil { + log.Error(uiLogger, "webauthn parse login: ", err) + c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "invalid credential"}) + return + } + handler := func(rawID, userHandle []byte) (webauthn.User, error) { + users, err := app.userStorer.GetUsers() + if err != nil { + return nil, err + } + u := model.FindUserByWebAuthnHandle(users, userHandle) + if u == nil { + return nil, protocol.ErrBadRequest.WithDetails("user not found") + } + return model.WebAuthnUser{User: u}, nil + } + waUser, cred, err := app.webAuthn.ValidatePasskeyLogin(handler, session, parsed) + if err != nil { + log.Warn(uiLogger, "webauthn login failed: ", err) + c.AbortWithStatus(http.StatusUnauthorized) + return + } + wrapped, ok := waUser.(model.WebAuthnUser) + if !ok || wrapped.User == nil { + c.AbortWithStatus(http.StatusUnauthorized) + return + } + user := wrapped.User + if user.UpdateWebAuthnCredentialSignCount(cred.ID, cred) { + user.UpdatedAt = time.Now() + if err := app.userStorer.UpdateUser(user); err != nil { + log.Warn(uiLogger, "webauthn persist sign count: ", err) + } + } + + tokenString, expiresAfter, err := app.issueWebTokenForUser(user, uuid.NewString()) + if err != nil { + log.Error(err) + c.AbortWithStatus(http.StatusInternalServerError) + return + } + c.SetSameSite(http.SameSiteStrictMode) + c.SetCookie(cookieName, tokenString, int(expiresAfter.Seconds()), "/", "", app.cfg.HTTPSCookie, true) + c.String(http.StatusOK, tokenString) +} diff --git a/internal/ui/webauthn_session.go b/internal/ui/webauthn_session.go new file mode 100644 index 00000000..61d836e3 --- /dev/null +++ b/internal/ui/webauthn_session.go @@ -0,0 +1,69 @@ +package ui + +import ( + "sync" + "time" + + "github.com/go-webauthn/webauthn/webauthn" + "github.com/google/uuid" +) + +const webAuthnSessionTTL = 2 * time.Minute + +type webAuthnSessionStore struct { + mu sync.Mutex + data map[string]webAuthnSessionEntry +} + +type webAuthnSessionEntry struct { + Data webauthn.SessionData + Expires time.Time +} + +func newWebAuthnSessionStore() *webAuthnSessionStore { + return &webAuthnSessionStore{data: make(map[string]webAuthnSessionEntry)} +} + +func (s *webAuthnSessionStore) Put(session *webauthn.SessionData) string { + id := uuid.NewString() + s.mu.Lock() + defer s.mu.Unlock() + s.purgeLocked(time.Now()) + s.data[id] = webAuthnSessionEntry{ + Data: *session, + Expires: time.Now().Add(webAuthnSessionTTL), + } + return id +} + +func (s *webAuthnSessionStore) Take(id string) (webauthn.SessionData, bool) { + s.mu.Lock() + defer s.mu.Unlock() + now := time.Now() + s.purgeLocked(now) + entry, ok := s.data[id] + if !ok { + return webauthn.SessionData{}, false + } + delete(s.data, id) + if now.After(entry.Expires) { + return webauthn.SessionData{}, false + } + return entry.Data, true +} + +func (s *webAuthnSessionStore) purgeLocked(now time.Time) { + for k, v := range s.data { + if now.After(v.Expires) { + delete(s.data, k) + } + } +} + +// LenForTest returns current session count (tests only). +func (s *webAuthnSessionStore) LenForTest() int { + s.mu.Lock() + defer s.mu.Unlock() + s.purgeLocked(time.Now()) + return len(s.data) +} diff --git a/internal/ui/webauthn_session_test.go b/internal/ui/webauthn_session_test.go new file mode 100644 index 00000000..44ea76e2 --- /dev/null +++ b/internal/ui/webauthn_session_test.go @@ -0,0 +1,40 @@ +package ui + +import ( + "testing" + "time" + + "github.com/go-webauthn/webauthn/webauthn" +) + +func TestWebAuthnSessionStorePutTake(t *testing.T) { + s := newWebAuthnSessionStore() + id := s.Put(&webauthn.SessionData{Challenge: "abc"}) + if id == "" { + t.Fatal("empty session id") + } + data, ok := s.Take(id) + if !ok || data.Challenge != "abc" { + t.Fatalf("take failed: ok=%v data=%+v", ok, data) + } + if _, ok := s.Take(id); ok { + t.Fatal("session should be single-use") + } +} + +func TestWebAuthnSessionStoreExpiry(t *testing.T) { + s := newWebAuthnSessionStore() + id := "expired" + s.mu.Lock() + s.data[id] = webAuthnSessionEntry{ + Data: webauthn.SessionData{Challenge: "x"}, + Expires: time.Now().Add(-time.Second), + } + s.mu.Unlock() + if _, ok := s.Take(id); ok { + t.Fatal("expired session should not be returned") + } + if s.LenForTest() != 0 { + t.Fatalf("expected purged store, len=%d", s.LenForTest()) + } +} diff --git a/internal/ui/xslt_transform.go b/internal/ui/xslt_transform.go new file mode 100644 index 00000000..2c601787 --- /dev/null +++ b/internal/ui/xslt_transform.go @@ -0,0 +1,103 @@ +package ui + +import ( + "bytes" + "fmt" + "os" + "os/exec" + "strings" + "sync" +) + +var ( + xsltOnce sync.Once + xsltMethod string // "python" or "" +) + +func detectXSLT() { + xsltOnce.Do(func() { + if _, err := exec.LookPath("python3"); err != nil { + return + } + cmd := exec.Command("python3", "-c", "from lxml import etree") + if err := cmd.Run(); err != nil { + return + } + xsltMethod = "python" + }) +} + +// transformPageXML applies shell.xsl to page XML. +// ok=false means caller should use the browser XSLT bootstrap. +func (app *ReactAppWrapper) transformPageXML(pageXML []byte) (html []byte, ok bool, err error) { + detectXSLT() + if xsltMethod != "python" { + return nil, false, nil + } + xsl, err := app.readStatic("xslt/shell.xsl") + if err != nil { + return nil, false, err + } + + tmpXML, err := os.CreateTemp("", "rmfc-page-*.xml") + if err != nil { + return nil, false, err + } + defer os.Remove(tmpXML.Name()) + if _, err := tmpXML.Write(pageXML); err != nil { + _ = tmpXML.Close() + return nil, false, err + } + _ = tmpXML.Close() + + tmpXSL, err := os.CreateTemp("", "rmfc-shell-*.xsl") + if err != nil { + return nil, false, err + } + defer os.Remove(tmpXSL.Name()) + if _, err := tmpXSL.Write(xsl); err != nil { + _ = tmpXSL.Close() + return nil, false, err + } + _ = tmpXSL.Close() + + script := fmt.Sprintf(` +from lxml import etree +import sys +xsl = etree.parse(%q) +transform = etree.XSLT(xsl) +page = etree.parse(%q) +result = transform(page) +html = etree.tostring(result, pretty_print=False, method="html", encoding="unicode") +if not html.lstrip().lower().startswith("\n" + html +sys.stdout.write(html) +`, tmpXSL.Name(), tmpXML.Name()) + + cmd := exec.Command("python3", "-c", script) + var stdout, stderr bytes.Buffer + cmd.Stdout = &stdout + cmd.Stderr = &stderr + if err := cmd.Run(); err != nil { + return nil, false, fmt.Errorf("xslt python: %w: %s", err, strings.TrimSpace(stderr.String())) + } + return stdout.Bytes(), true, nil +} + +func bootstrapXSLTHTML(pageXML []byte) []byte { + escaped := strings.ReplaceAll(string(pageXML), "", "<\\/script>") + var b strings.Builder + b.WriteString("\n") + b.WriteString("") + b.WriteString("") + b.WriteString("rmfakecloud") + b.WriteString("") + b.WriteString("") + b.WriteString("

    Loading…

    ") + b.WriteString("") + b.WriteString("") + b.WriteString("") + return []byte(b.String()) +} diff --git a/other/rmfakecloud.env b/other/rmfakecloud.env index 6aeff3f8..5dade240 100644 --- a/other/rmfakecloud.env +++ b/other/rmfakecloud.env @@ -3,3 +3,6 @@ JWT_SECRET_KEY=tbd DATADIR=/var/rmfakecloud/ #RM_SMTP_USER= #RM_SMTP_ADDRESS= +#RMFAKECLOUD_WEBAUTHN=true +#RMFAKECLOUD_WEBAUTHN_RPID=www.example.com +#RMFAKECLOUD_WEBAUTHN_ORIGINS=https://www.example.com:3000 diff --git a/scripts/rmdecode_v6_summary.py b/scripts/rmdecode_v6_summary.py new file mode 100644 index 00000000..1acf93d5 --- /dev/null +++ b/scripts/rmdecode_v6_summary.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python3 +""" +Summarize a version-6 reMarkable .rm file using rmscene. + + pip install 'rmscene>=0.6' + +Usage: + python3 scripts/rmdecode_v6_summary.py /path/to/page.rm +""" + +from __future__ import annotations + +import json +import sys + + +def main() -> int: + if len(sys.argv) < 2: + print("usage: rmdecode_v6_summary.py ", file=sys.stderr) + return 1 + path = sys.argv[1] + try: + from rmscene import read_tree + from rmscene.scene_items import GlyphRange, Line, Text + except ImportError as e: + json.dump( + { + "error": "rmscene not installed", + "hint": "pip install 'rmscene>=0.6'", + "detail": str(e), + }, + sys.stdout, + indent=2, + ) + print() + return 2 + + with open(path, "rb") as f: + tree = read_tree(f) + + n_lines = 0 + n_points = 0 + n_text = 0 + n_glyph = 0 + tools: dict[str, int] = {} + colors: dict[str, int] = {} + + for item in tree.walk(): + if isinstance(item, Line): + n_lines += 1 + n_points += len(item.points) + tname = item.tool.name if hasattr(item.tool, "name") else str(item.tool) + cname = item.color.name if hasattr(item.color, "name") else str(item.color) + tools[tname] = tools.get(tname, 0) + 1 + colors[cname] = colors.get(cname, 0) + 1 + elif isinstance(item, Text): + n_text += 1 + elif isinstance(item, GlyphRange): + n_glyph += 1 + + out = { + "version": 6, + "lines": n_lines, + "points": n_points, + "text_blocks": n_text, + "glyph_ranges": n_glyph, + "tools": tools, + "colors": colors, + } + json.dump(out, sys.stdout, indent=2) + print() + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/scripts/rmscene_v6_to_png.py b/scripts/rmscene_v6_to_png.py new file mode 100644 index 00000000..4fd7b3f7 --- /dev/null +++ b/scripts/rmscene_v6_to_png.py @@ -0,0 +1,155 @@ +#!/usr/bin/env python3 +""" +Render a single v6 .rm page to PNG. + +reMarkable v6 scene coordinates are centered on X (0 = page center) with Y=0 at +the top of the page. For notebooks that page is the device viewport (1404×1872). +For PDF annotations the page is the PDF page in screen pixels: + + doc_w = page_width_pt * (226/72) + doc_h = page_height_pt * (226/72) + px = (x + doc_w/2) * (fit_width / doc_w) + py = y * (fit_width / doc_w) + +When PDF page size in points is passed, output is width-fitted to 1404 (natural +aspect) so it multiplies cleanly onto a pdftoppm raster of the same size. + +Usage: + python3 scripts/rmscene_v6_to_png.py page.rm > page.png + python3 scripts/rmscene_v6_to_png.py - < page.rm > page.png + python3 scripts/rmscene_v6_to_png.py --pdf-pts 612 792 page.rm > page.png + python3 scripts/rmscene_v6_to_png.py --pdf-pts 612 792 - < page.rm > page.png +""" + +from __future__ import annotations + +import math +import pathlib +import sys +from io import BytesIO + +_REPO_ROOT = pathlib.Path(__file__).resolve().parents[1] +sys.path.insert(0, str(_REPO_ROOT / "third_party" / "rmscene" / "src")) + +from rmscene import read_tree # noqa: E402 +from rmscene.scene_items import Line # noqa: E402 +from rmscene.scene_items import Pen # noqa: E402 + +DEVICE_W, DEVICE_H = 1404, 1872 +SCREEN_DPI = 226.0 +FIT_WIDTH = 1404 + + +def parse_args(argv: list[str]) -> tuple[str, float | None, float | None]: + pdf_w = pdf_h = None + args = list(argv[1:]) + if args and args[0] == "--pdf-pts": + if len(args) < 4: + raise SystemExit("usage: --pdf-pts WIDTH_PT HEIGHT_PT ") + pdf_w = float(args[1]) + pdf_h = float(args[2]) + path = args[3] + elif len(args) >= 1: + path = args[0] + else: + raise SystemExit( + "usage: rmscene_v6_to_png.py [--pdf-pts W H] " + ) + return path, pdf_w, pdf_h + + +def main() -> int: + try: + from PIL import Image, ImageDraw, PngImagePlugin + except ImportError as e: + print("Pillow required: pip install Pillow", file=sys.stderr) + print(str(e), file=sys.stderr) + return 2 + + try: + path, pdf_w_pt, pdf_h_pt = parse_args(sys.argv) + except SystemExit as e: + print(str(e), file=sys.stderr) + return 1 + + if path == "-": + data = sys.stdin.buffer.read() + else: + with open(path, "rb") as f: + data = f.read() + + if pdf_w_pt and pdf_h_pt and pdf_w_pt > 0 and pdf_h_pt > 0: + doc_w = pdf_w_pt * SCREEN_DPI / 72.0 + doc_h = pdf_h_pt * SCREEN_DPI / 72.0 + scale = FIT_WIDTH / doc_w + out_w = FIT_WIDTH + out_h = max(int(round(doc_h * scale)), 1) + x0 = doc_w / 2.0 + map_pt = lambda x, y: ((x + x0) * scale, y * scale) + view_w, view_h = out_w, out_h + origin_x = origin_y = 0 + else: + out_w, out_h = DEVICE_W, DEVICE_H + scale = 1.0 + x0 = DEVICE_W / 2.0 + map_pt = lambda x, y: (x + x0, y) + view_w, view_h = DEVICE_W, DEVICE_H + origin_x = origin_y = 0 + doc_w, doc_h = float(DEVICE_W), float(DEVICE_H) + + tree = read_tree(BytesIO(data)) + + strokes: list[tuple[list[tuple[float, float]], int]] = [] + min_x, min_y = 0.0, 0.0 + max_x, max_y = float(out_w), float(out_h) + + for item in tree.walk(): + if not isinstance(item, Line): + continue + if item.tool in (Pen.ERASER, Pen.ERASER_AREA): + continue + if len(item.points) < 2: + continue + sw = max(int(round((item.points[0].width * scale) / 4)), 1) + pad = sw / 2.0 + 1.0 + pts = [map_pt(float(p.x), float(p.y)) for p in item.points] + strokes.append((pts, sw)) + for x, y in pts: + if x - pad < min_x: + min_x = x - pad + if y - pad < min_y: + min_y = y - pad + if x + pad > max_x: + max_x = x + pad + if y + pad > max_y: + max_y = y + pad + + min_x = math.floor(min_x) + min_y = math.floor(min_y) + max_x = math.ceil(max_x) + max_y = math.ceil(max_y) + width = max(int(max_x - min_x), 1) + height = max(int(max_y - min_y), 1) + origin_x = int(-min_x) + origin_y = int(-min_y) + + img = Image.new("RGB", (width, height), "white") + draw = ImageDraw.Draw(img) + for pts, sw in strokes: + shifted = [(x - min_x, y - min_y) for x, y in pts] + for i in range(len(shifted) - 1): + draw.line([shifted[i], shifted[i + 1]], fill="black", width=sw) + + meta = PngImagePlugin.PngInfo() + # Device/page viewport inside this (possibly expanded) PNG. + meta.add_text("rmDeviceOrigin", f"{origin_x},{origin_y}") + meta.add_text("rmDeviceSize", f"{view_w},{view_h}") + + buf = BytesIO() + img.save(buf, format="PNG", pnginfo=meta) + sys.stdout.buffer.write(buf.getvalue()) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/third_party/rmc/.github/workflows/release.yml b/third_party/rmc/.github/workflows/release.yml new file mode 100644 index 00000000..0f7c8aae --- /dev/null +++ b/third_party/rmc/.github/workflows/release.yml @@ -0,0 +1,115 @@ +# Based on https://packaging.python.org/en/latest/guides/publishing-package-distribution-releases-using-github-actions-ci-cd-workflows/ + +name: Publish Python distribution to PyPI + +on: push + +jobs: + build: + name: Build distribution + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.x" + - name: Install pypa/build + run: python3 -m pip install build --user + - name: Build a binary wheel and a source tarball + run: python3 -m build + - name: Store the distribution packages + uses: actions/upload-artifact@v4 + with: + name: python-package-distributions + path: dist/ + + publish-to-pypi: + name: Publish Python distribution to PyPI + if: startsWith(github.ref, 'refs/tags/') # only publish to PyPI on tag pushes + needs: + - build + runs-on: ubuntu-latest + environment: + name: pypi + url: https://pypi.org/p/rmc + permissions: + id-token: write # IMPORTANT: mandatory for trusted publishing + + steps: + - name: Download all the dists + uses: actions/download-artifact@v4 + with: + name: python-package-distributions + path: dist/ + - name: Publish distribution 📦 to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 + + github-release: + name: Sign Python distribution and upload to Github Release + needs: + - publish-to-pypi + runs-on: ubuntu-latest + + permissions: + contents: write # IMPORTANT: mandatory for making GitHub Releases + id-token: write # IMPORTANT: mandatory for sigstore + + steps: + - name: Download all the dists + uses: actions/download-artifact@v4 + with: + name: python-package-distributions + path: dist/ + - name: Sign the dists with Sigstore + uses: sigstore/gh-action-sigstore-python@v3.0.0 + with: + inputs: >- + ./dist/*.tar.gz + ./dist/*.whl + - name: Create GitHub Release + env: + GITHUB_TOKEN: ${{ github.token }} + run: >- + gh release create + '${{ github.ref_name }}' + --repo '${{ github.repository }}' + --notes "" + - name: Upload artifact signatures to GitHub Release + env: + GITHUB_TOKEN: ${{ github.token }} + # Upload to GitHub Release using the `gh` CLI. + # `dist/` contains the built packages, and the + # sigstore-produced signatures and certificates. + run: >- + gh release upload + '${{ github.ref_name }}' dist/** + --repo '${{ github.repository }}' + + publish-to-testpypi: + name: Publish Python distribution to TestPyPI + needs: + - build + runs-on: ubuntu-latest + + environment: + name: testpypi + url: https://test.pypi.org/p/rmc + + permissions: + id-token: write # IMPORTANT: mandatory for trusted publishing + + steps: + - name: Download all the dists + uses: actions/download-artifact@v4 + with: + name: python-package-distributions + path: dist/ + - name: Publish distribution 📦 to TestPyPI + uses: pypa/gh-action-pypi-publish@release/v1 + with: + repository-url: https://test.pypi.org/legacy/ + # Don't fail when this is another push to the same version. If we put + # the git hash in the version string, this could be removed. + skip-existing: true diff --git a/third_party/rmc/.github/workflows/test.yml b/third_party/rmc/.github/workflows/test.yml new file mode 100644 index 00000000..a511b13a --- /dev/null +++ b/third_party/rmc/.github/workflows/test.yml @@ -0,0 +1,28 @@ +# This workflow will install Python dependencies and run the tests + +name: Test + +on: + push: + branches: [ main, github_actions ] + pull_request: + branches: [ main ] + +jobs: + tests: + runs-on: ${{ matrix.os }} + strategy: + matrix: + python-version: ["3.10", "3.11"] + os: [ubuntu-latest, windows-latest, macos-latest] + steps: + - uses: actions/checkout@v3 + - name: Install poetry + run: pipx install poetry + - name: Setup Python ${{ matrix.python-version }} + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + cache: 'poetry' + - run: poetry install + - run: poetry run bash convert_test_files.sh diff --git a/third_party/rmc/.gitignore b/third_party/rmc/.gitignore new file mode 100644 index 00000000..259ed2a5 --- /dev/null +++ b/third_party/rmc/.gitignore @@ -0,0 +1,2 @@ +__pycache__/ +.idea diff --git a/third_party/rmc/LICENSE b/third_party/rmc/LICENSE new file mode 100644 index 00000000..672f11c9 --- /dev/null +++ b/third_party/rmc/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 Rick Lupton + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/third_party/rmc/README.md b/third_party/rmc/README.md new file mode 100644 index 00000000..c348a646 --- /dev/null +++ b/third_party/rmc/README.md @@ -0,0 +1,57 @@ +# rmc + +Command line tool for converting to/from remarkable `.rm` version 6 (software version 3) files. + +## Installation + +To install in your current Python environment: + + pip install rmc + +Or use [pipx](https://pypa.github.io/pipx/) to install in an isolated environment (recommended): + + pipx install rmc + +## Usage + +Convert a remarkable v6 file to other formats, specified by `-t FORMAT`: + + $ rmc -t markdown file.rm + Text in the file is printed to standard output. + +Specify the filename to write the output to with `-o`: + + $ rmc -t svg -o file.svg file.rm + +The format is guessed based on the filename if not specified: + + $ rmc file.rm -o file.pdf + +Create a `.rm` file containing the text in `text.md`: + + $ rmc -t rm text.md -o text.rm + +## SVG/PDF Conversion Status + +Right now the converter works well while there are no text boxes. If you add text boxes, there are x issues: + +1. if the text box contains multiple lines, the lines are actually printed in the same line, and +2. the position of the strokes gets corrupted. + +# Acknowledgements + +`rmc` uses [rmscene](https://github.com/ricklupton/rmscene) to read the `.rm` files, for which https://github.com/ddvk/reader helped a lot in figuring out the structure and meaning of the files. + +[@chemag](https://github.com/chemag) added initial support for converting to svg and pdf. + +[@Seb-sti1](https://github.com/Seb-sti1) made lots of improvements to svg export and updating to newer `rmscene` versions. + +[@ChenghaoMou](https://github.com/ChenghaoMou) added support for new pen types/colours. + +[@EelcovanVeldhuizen](https://github.com/EelcovanVeldhuizen) for code updates/fixes. + +[@p4xel](https://github.com/p4xel) for code fixes. + +[@Azeirah](https://github.com/Azeirah) + +[@darobin](https://github.com/darobin) diff --git a/third_party/rmc/convert_test_files.sh b/third_party/rmc/convert_test_files.sh new file mode 100755 index 00000000..ceec7830 --- /dev/null +++ b/third_party/rmc/convert_test_files.sh @@ -0,0 +1,45 @@ +#!/bin/bash + +set -euo pipefail + +# Directory containing .rm files +TEST_DIR="tests/rm" +OUTPUT_DIR="test_output" + +# Check if directory exists +if [ ! -d "$TEST_DIR" ]; then + echo "Error: Directory $TEST_DIR does not exist" + exit 1 +fi + +if [ ! -d "$OUTPUT_DIR" ]; then + mkdir -p "$OUTPUT_DIR" + mkdir -p "$OUTPUT_DIR/markdown" + mkdir -p "$OUTPUT_DIR/svg" + mkdir -p "$OUTPUT_DIR/pdf" +fi + +# Iterate through all .rm files in the directory +for file in "$TEST_DIR"/*.rm; do + # Check if files exist (in case directory is empty) + if [ -f "$file" ]; then + echo "Testing file: $file" + file_name=$(basename "$file") + + # Run first test command + echo "Running test markdown..." + rmc -t markdown "$file" -o "$OUTPUT_DIR/markdown/$file_name.md" + + # Run second test command + echo "Running test svg..." + rmc -t svg "$file" -o "$OUTPUT_DIR/svg/$file_name.svg" + + # Run third test command + echo "Running test pdf..." + rmc -t pdf "$file" -o "$OUTPUT_DIR/pdf/$file_name.pdf" + + echo "----------------------------------------" + fi +done + +echo "All tests completed" diff --git a/third_party/rmc/flake.lock b/third_party/rmc/flake.lock new file mode 100644 index 00000000..803acceb --- /dev/null +++ b/third_party/rmc/flake.lock @@ -0,0 +1,60 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1733686850, + "narHash": "sha256-NQEO/nZWWGTGlkBWtCs/1iF1yl2lmQ1oY/8YZrumn3I=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "dd51f52372a20a93c219e8216fe528a648ffcbf4", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "ref": "nixpkgs-unstable", + "type": "indirect" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/third_party/rmc/flake.nix b/third_party/rmc/flake.nix new file mode 100644 index 00000000..9993f1c5 --- /dev/null +++ b/third_party/rmc/flake.nix @@ -0,0 +1,30 @@ +{ + description = "Nix flakes"; + + inputs = { + nixpkgs.url = "nixpkgs/nixpkgs-unstable"; + flake-utils.url = "github:numtide/flake-utils"; + }; + + outputs = { self, nixpkgs, flake-utils }: + flake-utils.lib.eachDefaultSystem (system: + let + pythonEnv = pkgs.python312.withPackages (ps: []); + pkgs = import nixpkgs { + inherit system; + }; + in + { + devShells.default = pkgs.mkShell { + buildInputs = with pkgs; [ + sqlite.dev + poetry + inkscape + ]; + + LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath [ + pkgs.sqlite.out + ]; + }; + }); +} diff --git a/third_party/rmc/poetry.lock b/third_party/rmc/poetry.lock new file mode 100644 index 00000000..17059df0 --- /dev/null +++ b/third_party/rmc/poetry.lock @@ -0,0 +1,159 @@ +# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. + +[[package]] +name = "click" +version = "8.1.7" +description = "Composable command line interface toolkit" +optional = false +python-versions = ">=3.7" +files = [ + {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, + {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + +[[package]] +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] + +[[package]] +name = "exceptiongroup" +version = "1.2.2" +description = "Backport of PEP 654 (exception groups)" +optional = false +python-versions = ">=3.7" +files = [ + {file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"}, + {file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"}, +] + +[package.extras] +test = ["pytest (>=6)"] + +[[package]] +name = "iniconfig" +version = "2.0.0" +description = "brain-dead simple config-ini parsing" +optional = false +python-versions = ">=3.7" +files = [ + {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, + {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, +] + +[[package]] +name = "packaging" +version = "23.2" +description = "Core utilities for Python packages" +optional = false +python-versions = ">=3.7" +files = [ + {file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"}, + {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, +] + +[[package]] +name = "pluggy" +version = "1.5.0" +description = "plugin and hook calling mechanisms for python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, + {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, +] + +[package.extras] +dev = ["pre-commit", "tox"] +testing = ["pytest", "pytest-benchmark"] + +[[package]] +name = "pytest" +version = "7.4.4" +description = "pytest: simple powerful testing with Python" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pytest-7.4.4-py3-none-any.whl", hash = "sha256:b090cdf5ed60bf4c45261be03239c2c1c22df034fbffe691abe93cd80cea01d8"}, + {file = "pytest-7.4.4.tar.gz", hash = "sha256:2cf0005922c6ace4a3e2ec8b4080eb0d9753fdc93107415332f50ce9e7994280"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "sys_platform == \"win32\""} +exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} +iniconfig = "*" +packaging = "*" +pluggy = ">=0.12,<2.0" +tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} + +[package.extras] +testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] + +[[package]] +name = "rmscene" +version = "0.6.0" +description = "Read v6 .rm files from the reMarkable tablet" +optional = false +python-versions = "<4.0,>=3.10" +files = [ + {file = "rmscene-0.6.0-py3-none-any.whl", hash = "sha256:30a4c8590e8edb4567698adb96dc31004c6d41d752ad04e6c92ab985d0a64c7c"}, + {file = "rmscene-0.6.0.tar.gz", hash = "sha256:c3d89a026ca2b98cfca3b6bcb4c6132ebe5e86b12192de14b119f286c5de39cd"}, +] + +[package.dependencies] +packaging = ">=23.0,<24.0" + +[[package]] +name = "tomli" +version = "2.2.1" +description = "A lil' TOML parser" +optional = false +python-versions = ">=3.8" +files = [ + {file = "tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249"}, + {file = "tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6"}, + {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a"}, + {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee"}, + {file = "tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e"}, + {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4"}, + {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106"}, + {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8"}, + {file = "tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff"}, + {file = "tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b"}, + {file = "tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea"}, + {file = "tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8"}, + {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192"}, + {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222"}, + {file = "tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77"}, + {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6"}, + {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd"}, + {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e"}, + {file = "tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98"}, + {file = "tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4"}, + {file = "tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7"}, + {file = "tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c"}, + {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13"}, + {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281"}, + {file = "tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272"}, + {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140"}, + {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2"}, + {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744"}, + {file = "tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec"}, + {file = "tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69"}, + {file = "tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc"}, + {file = "tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff"}, +] + +[metadata] +lock-version = "2.0" +python-versions = "^3.10" +content-hash = "89300f7c0755c959ecf73ddc93b01d4528f11a86a072e4f384e9626329136aee" diff --git a/third_party/rmc/pyproject.toml b/third_party/rmc/pyproject.toml new file mode 100644 index 00000000..88b3d2af --- /dev/null +++ b/third_party/rmc/pyproject.toml @@ -0,0 +1,22 @@ +[tool.poetry] +name = "rmc" +version = "0.3.1-dev" +description = "Convert to/from v6 .rm files from the reMarkable tablet" +authors = ["Rick Lupton "] +license = "MIT" +readme = "README.md" + +[tool.poetry.dependencies] +python = "^3.10" +rmscene = ">=0.8.0, <0.9.0" +click = "^8.0" + +[tool.poetry.dev-dependencies] +pytest = "^7.2.0" + +[tool.poetry.scripts] +rmc = 'rmc.cli:cli' + +[build-system] +requires = ["poetry-core>=1.0.0"] +build-backend = "poetry.core.masonry.api" diff --git a/third_party/rmc/src/rmc/__init__.py b/third_party/rmc/src/rmc/__init__.py new file mode 100644 index 00000000..2e55d0a6 --- /dev/null +++ b/third_party/rmc/src/rmc/__init__.py @@ -0,0 +1,2 @@ +from .exporters.svg import tree_to_svg, rm_to_svg +from .exporters.pdf import rm_to_pdf diff --git a/third_party/rmc/src/rmc/cli.py b/third_party/rmc/src/rmc/cli.py new file mode 100644 index 00000000..661a3107 --- /dev/null +++ b/third_party/rmc/src/rmc/cli.py @@ -0,0 +1,185 @@ +"""CLI for converting rm files.""" + +import os +import sys +import io +from pathlib import Path +from contextlib import contextmanager +import click +from rmscene import read_tree, read_blocks, write_blocks, simple_text_document +from .exporters.svg import tree_to_svg +from .exporters.pdf import svg_to_pdf +from .exporters.markdown import print_text + +import logging + + +@click.command +@click.version_option() +@click.option('-v', '--verbose', count=True) +@click.option("-f", "--from", "from_", metavar="FORMAT", help="Format to convert from (default: guess from filename)") +@click.option("-t", "--to", metavar="FORMAT", help="Format to convert to (default: guess from filename)") +@click.option("-o", "--output", type=click.Path(), help="Output filename (default: write to standard out)") +@click.argument("input", nargs=-1, type=click.Path(exists=True)) +def cli(verbose, from_, to, output, input): + """Convert to/from reMarkable v6 files. + + Available FORMATs are: `rm` (reMarkable file), `markdown`, `svg`, `pdf`, + `blocks`, `blocks-data`. + + Formats `blocks` and `blocks-data` dump the internal structure of the `rm` + file, with and without detailed data values respectively. + + """ + + if verbose >= 2: + logging.basicConfig(level=logging.DEBUG) + elif verbose >= 1: + logging.basicConfig(level=logging.INFO) + else: + logging.basicConfig(level=logging.WARNING) + + input = [Path(p) for p in input] + if output is not None: + output = Path(output) + + if from_ is None: + if not input: + raise click.UsageError("Must specify input filename or --from") + from_ = guess_format(input[0]) + if to is None: + if output is None: + raise click.UsageError("Must specify --output or --to") + to = guess_format(output) + + if from_ == "rm": + with open_output(to, output) as fout: + for fn in input: + convert_rm(Path(fn), to, fout) + elif from_ == "markdown": + text = "".join( + Path(fn).read_text() for fn in input + ) + with open_output(to, output) as fout: + convert_text(text, fout) + else: + raise click.UsageError("source format %s not implemented yet" % from_) + + +@contextmanager +def open_output(to, output): + to_binary = to in ("pdf", "rm") + if output is None: + # Write to stdout + if to_binary: + with os.fdopen(sys.stdout.fileno(), "wb", closefd=False) as f: + yield f + else: + yield sys.stdout + else: + with open(output, "w" + ("b" if to_binary else "t")) as f: + yield f + + +def guess_format(p: Path): + # XXX could be neater + if p.suffix == ".rm": + return "rm" + if p.suffix == ".svg": + return "svg" + elif p.suffix == ".pdf": + return "pdf" + elif p.suffix == ".md" or p.suffix == ".markdown": + return "markdown" + else: + return "blocks" + + +from rmscene import scene_items as si +def tree_structure(item): + if isinstance(item, si.Group): + return ( + item.node_id, + ( + item.label.value, + item.visible.value, + ( + item.anchor_id.value if item.anchor_id else None, + item.anchor_type.value if item.anchor_type else None, + item.anchor_threshold.value if item.anchor_threshold else None, + item.anchor_origin_x.value if item.anchor_origin_x else None, + ) + ), + [tree_structure(child) for child in item.children.values() if child], + ) + else: + return item + + +def convert_rm(filename: Path, to, fout): + image_path = filename.with_suffix("") + with open(filename, "rb") as f: + if to == "blocks": + pprint_blocks(f, fout) + elif to == "blocks-data": + pprint_blocks(f, fout, data=False) + elif to == "tree": + # Experimental dumping of tree structure + pprint_tree(f, fout, data=True) + elif to == "tree-data": + # Experimental dumping of tree structure + pprint_tree(f, fout, data=False) + elif to == "markdown": + print_text(f, fout) + elif to == "svg": + tree = read_tree(f) + tree_to_svg(tree, fout, image_path=image_path) + elif to == "pdf": + buf = io.StringIO() + tree = read_tree(f) + tree_to_svg(tree, buf, image_path=image_path) + buf.seek(0) + svg_to_pdf(buf, fout) + else: + raise click.UsageError("Unknown format %s" % to) + + +def pprint_blocks(f, fout, data=True) -> None: + import pprint + depth = None if data else 1 + result = read_blocks(f) + for el in result: + print(file=fout) + pprint.pprint(el, depth=depth, stream=fout) + + +def pprint_tree(f, fout, data=True) -> None: + tree = read_tree(f) + + import pprint + import re + + def pprint_Line(self, object, stream, indent, allowance, context, level): + min_x = min(p.x for p in object.points) + min_y = min(p.y for p in object.points) + max_x = max(p.x for p in object.points) + max_y = max(p.y for p in object.points) + rep = re.sub(r"points=\[.*\]", + f"points=[({min_x: 4.0f},{min_y: 4.0f})-({max_x: 4.0f},{max_y: 4.0f})]", + repr(object)) + stream.write(rep) + + pprint.PrettyPrinter._dispatch[si.Line.__repr__] = pprint_Line + + depth = None if data else 1 + pprint.pprint(tree_structure(tree.root), stream=fout) + pprint.pprint(tree_structure(tree.root_text), depth=depth, stream=fout) + + + +def convert_text(text, fout): + write_blocks(fout, simple_text_document(text)) + + +if __name__ == "__main__": + cli() diff --git a/third_party/rmc/src/rmc/exporters/markdown.py b/third_party/rmc/src/rmc/exporters/markdown.py new file mode 100644 index 00000000..b2aa61ca --- /dev/null +++ b/third_party/rmc/src/rmc/exporters/markdown.py @@ -0,0 +1,65 @@ +"""Export text content of rm files as Markdown.""" + +from rmscene import read_tree +from rmscene import scene_items as si + +from rmscene.text import TextDocument + + +def print_text(f, fout): + tree = read_tree(f) + + # Find out what anchor characters are used + anchor_ids = set(collect_anchor_ids(tree.root)) + + if tree.root_text: + print_root_text(tree.root_text, fout, anchor_ids) + + JOIN_TOLERANCE = 2 + print("\n\n# Highlights", file=fout) + last_pos = 0 + for item in tree.walk(): + if isinstance(item, si.GlyphRange): + if item.start > last_pos + JOIN_TOLERANCE: + print(file=fout) + print(">", item.text, file=fout) + last_pos = item.start + len(item.text) + print(file=fout) + + +def print_root_text(root_text: si.Text, fout, anchor_ids): + doc = TextDocument.from_scene_item(root_text) + for p in doc.contents: + annotated_line = annotate_anchor_ids(anchor_ids, + str(p), + [char_id for s in p.contents for char_id in s.i]) + if p.style.value == si.ParagraphStyle.BULLET: + fout.write("- " + annotated_line + "\n") + elif p.style.value == si.ParagraphStyle.BULLET2: + fout.write(" + " + annotated_line + "\n") + elif p.style.value == si.ParagraphStyle.BOLD: + fout.write("> " + annotated_line + "\n") + elif p.style.value == si.ParagraphStyle.HEADING: + fout.write("# " + annotated_line + "\n") + elif p.style.value == si.ParagraphStyle.PLAIN: + fout.write(annotated_line + "\n") + else: + fout.write(("[unknown format %s] " % p.style.value) + annotated_line + "\n") + + +def annotate_anchor_ids(anchor_ids, line, ids): + """Annotate appearances of `anchor_ids` in `line`.""" + result = "" + for char, char_id in zip(line, ids): + if char_id in anchor_ids: + result += f"<<{char_id.part1},{char_id.part2}>>" + result += char + return result + + +def collect_anchor_ids(item): + if isinstance(item, si.Group): + if item.anchor_id is not None: + yield item.anchor_id.value + for child in item.children.values(): + yield from collect_anchor_ids(child) diff --git a/third_party/rmc/src/rmc/exporters/pdf.py b/third_party/rmc/src/rmc/exporters/pdf.py new file mode 100644 index 00000000..bf5843ab --- /dev/null +++ b/third_party/rmc/src/rmc/exporters/pdf.py @@ -0,0 +1,46 @@ +"""Convert blocks to pdf file. + +Code originally from https://github.com/lschwetlick/maxio through +https://github.com/chemag/maxio . +""" + +import logging +from tempfile import NamedTemporaryFile +from subprocess import check_call + +from .svg import rm_to_svg + +_logger = logging.getLogger(__name__) + + +def rm_to_pdf(rm_path, pdf_path, debug=0): + """Convert `rm_path` to PDF at `pdf_path`.""" + with NamedTemporaryFile(suffix=".svg") as f_temp: + rm_to_svg(rm_path, f_temp.name) + + # use inkscape to convert svg to pdf + check_call(["inkscape", f_temp.name, "--export-filename", pdf_path]) + + +def svg_to_pdf(svg_file, pdf_file): + """Read svg data from `svg_file` and write PDF data to `pdf_file`.""" + + with NamedTemporaryFile("w", suffix=".svg") as fsvg, NamedTemporaryFile("rb", suffix=".pdf") as fpdf: + fsvg.write(svg_file.read()) + fsvg.flush() # Make sure content is writen to the file + + # use inkscape to convert svg to pdf + try: + print("Convert SVG to PDF using Inkscape") + check_call(["inkscape", fsvg.name, "--export-filename", fpdf.name]) + except FileNotFoundError: + print("Inkscape not found in path") + + try: + print("Convert SVG to PDF using Inkscape (default MacOS path)") + check_call(["/Applications/Inkscape.app/Contents/MacOS/inkscape", fsvg.name, "--export-filename", fpdf.name]) + except FileNotFoundError: + pass + + pdf_file.write(fpdf.read()) + pdf_file.flush() diff --git a/third_party/rmc/src/rmc/exporters/svg.py b/third_party/rmc/src/rmc/exporters/svg.py new file mode 100644 index 00000000..dd329862 --- /dev/null +++ b/third_party/rmc/src/rmc/exporters/svg.py @@ -0,0 +1,341 @@ +"""Convert blocks to svg file. + +Code originally from https://github.com/lschwetlick/maxio through +https://github.com/chemag/maxio . +""" + +import base64 +import logging +import string +import typing as tp +from pathlib import Path + +from rmscene import CrdtId, SceneTree, read_tree +from rmscene import scene_items as si +from rmscene.text import TextDocument + +from .writing_tools import Pen, lookup_pen_color + +_logger = logging.getLogger(__name__) + +SCREEN_WIDTH = 1404 +SCREEN_HEIGHT = 1872 +SCREEN_DPI = 226 + +SCALE = 72.0 / SCREEN_DPI + +PAGE_WIDTH_PT = SCREEN_WIDTH * SCALE +PAGE_HEIGHT_PT = SCREEN_HEIGHT * SCALE +X_SHIFT = PAGE_WIDTH_PT // 2 + + +def scale(screen_unit: float) -> float: + return screen_unit * SCALE + + +# For now, at least, the xx and yy function are identical to scale +xx = scale +yy = scale + +TEXT_TOP_Y = -88 +LINE_HEIGHTS = { + # Based on a rm file having 4 anchors based on the line height I was able to find a value of + # 69.5, but decided on 70 (to keep integer values) + si.ParagraphStyle.PLAIN: 70, + si.ParagraphStyle.BULLET: 35, + si.ParagraphStyle.BULLET2: 35, + si.ParagraphStyle.BOLD: 70, + si.ParagraphStyle.HEADING: 150, + si.ParagraphStyle.CHECKBOX: 35, + si.ParagraphStyle.CHECKBOX_CHECKED: 35, + + # There appears to be another format code (value 0) which is used when the + # text starts far down the page, which case it has a negative offset (line + # height) of about -20? + # + # Probably, actually, the line height should be added *after* the first + # line, but there is still something a bit odd going on here. +} + +SVG_HEADER = string.Template(""" +""") + + +def rm_to_svg(rm_path, svg_path): + """Convert `rm_path` to SVG at `svg_path`.""" + image_path = Path(rm_path).with_suffix("") + with open(rm_path, "rb") as infile, open(svg_path, "wt") as outfile: + tree = read_tree(infile) + tree_to_svg(tree, outfile, image_path=image_path) + + +def read_template_svg(template_path: Path) -> str: + lines = template_path.read_text().splitlines() + return "\n".join(lines[2:-2]) + + +def tree_to_svg(tree: SceneTree, output, include_template: Path | None = None, image_path: Path | None = None): + """Convert Blocks to SVG.""" + + # find the anchor pos for further use + anchor_pos = build_anchor_pos(tree.root_text) + _logger.debug("anchor_pos: %s", anchor_pos) + + # find the extremum along x and y + x_min, x_max, y_min, y_max = get_bounding_box(tree.root, anchor_pos) + width_pt = xx(x_max - x_min + 1) + height_pt = yy(y_max - y_min + 1) + _logger.debug("x_min, x_max, y_min, y_max: %.1f, %.1f, %.1f, %.1f ; scalded %.1f, %.1f, %.1f, %.1f", + x_min, x_max, y_min, y_max, xx(x_min), xx(x_max), yy(y_min), yy(y_max)) + + # add svg header + output.write(SVG_HEADER.substitute(width=width_pt, + height=height_pt, + viewbox=f"{xx(x_min)} {yy(y_min)} {width_pt} {height_pt}") + "\n") + + if include_template is not None: + output.write(read_template_svg(include_template)) + output.write(f'\n\t\n') + + output.write(f'\t\n') + + if tree.root_text is not None: + draw_text(tree.root_text, output) + + draw_group(tree.root, output, anchor_pos, image_path=image_path) + + # Closing page group + output.write('\t\n') + # END notebook + output.write('\n') + + +def build_anchor_pos(text: tp.Optional[si.Text]) -> tp.Dict[CrdtId, int]: + """ + Find the anchor pos + + :param text: the root text of the remarkable file + """ + anchor_pos = {} + + if text is not None: + # Save anchor from text + doc = TextDocument.from_scene_item(text) + ypos = text.pos_y + TEXT_TOP_Y + top_of_text = ypos + for i, p in enumerate(doc.contents): + anchor_pos[p.start_id] = ypos + for subp in p.contents: + for k in subp.i: + anchor_pos[k] = ypos # TODO check these anchor are used + ypos += LINE_HEIGHTS.get(p.style.value, 70) + bottom_of_text = ypos + + # Special anchors: groups drawn at the top/bottom of the page, + # not anchored to any specific paragraph. + anchor_pos[CrdtId(0, 281474976710654)] = top_of_text + anchor_pos[CrdtId(0, 281474976710655)] = bottom_of_text + else: + # No text: fall back to fixed positions at top/bottom of screen + anchor_pos[CrdtId(0, 281474976710654)] = 0 + anchor_pos[CrdtId(0, 281474976710655)] = SCREEN_HEIGHT + + return anchor_pos + + +def get_anchor(item: si.Group, anchor_pos): + anchor_x = 0.0 + anchor_y = 0.0 + if item.anchor_id is not None: + assert item.anchor_origin_x is not None + anchor_x = item.anchor_origin_x.value + if item.anchor_id.value in anchor_pos: + anchor_y = anchor_pos[item.anchor_id.value] + _logger.debug("Group anchor: %s -> y=%.1f (scalded y=%.1f)", + item.anchor_id.value, + anchor_y, + yy(anchor_y)) + else: + _logger.warning("Group anchor: %s is unknown!", item.anchor_id.value) + + return anchor_x, anchor_y + + +def get_bounding_box(item: si.Group, + anchor_pos: tp.Dict[CrdtId, int], + default: tp.Tuple[int, int, int, int] = (- SCREEN_WIDTH // 2, SCREEN_WIDTH // 2, 0, SCREEN_HEIGHT)) \ + -> tp.Tuple[int, int, int, int]: + """ + Get the bounding box of the given item. + The minimum size is the default size of the screen. + + :return: x_min, x_max, y_min, y_max: the bounding box in screen units (need to be scalded using xx and yy functions) + """ + x_min, x_max, y_min, y_max = default + + for child_id in item.children: + child = item.children[child_id] + if isinstance(child, si.Group): + anchor_x, anchor_y = get_anchor(child, anchor_pos) + x_min_t, x_max_t, y_min_t, y_max_t = get_bounding_box(child, anchor_pos, (0, 0, 0, 0)) + x_min = min(x_min, x_min_t + anchor_x) + x_max = max(x_max, x_max_t + anchor_x) + y_min = min(y_min, y_min_t + anchor_y) + y_max = max(y_max, y_max_t + anchor_y) + elif isinstance(child, si.Line): + x_min = min([x_min] + [p.x for p in child.points]) + x_max = max([x_max] + [p.x for p in child.points]) + y_min = min([y_min] + [p.y for p in child.points]) + y_max = max([y_max] + [p.y for p in child.points]) + elif isinstance(child, si.Image) and child.vertices: + xs = child.vertices[0::2] + ys = child.vertices[1::2] + x_min = min([x_min] + xs) + x_max = max([x_max] + xs) + y_min = min([y_min] + ys) + y_max = max([y_max] + ys) + + return x_min, x_max, y_min, y_max + + +def draw_group(item: si.Group, output, anchor_pos, image_path: Path | None = None): + anchor_x, anchor_y = get_anchor(item, anchor_pos) + output.write(f'\t\t\n') + for child_id in item.children: + child = item.children[child_id] + _logger.debug("Group child: %s %s", child_id, type(child)) + if _logger.root.level == logging.DEBUG: + output.write(f'\t\t\n') + if isinstance(child, si.Group): + draw_group(child, output, anchor_pos, image_path=image_path) + elif isinstance(child, si.Line): + draw_stroke(child, output) + elif isinstance(child, si.Image): + draw_image(child, output, image_path=image_path) + output.write(f'\t\t\n') + + +def draw_stroke(item: si.Line, output): + # print debug infos + if _logger.root.level == logging.DEBUG: + _logger.debug("Writing line: %s", item) + output.write(f'\t\t\t\n') + + # initiate the pen + pen_color = lookup_pen_color(item.color.value, item.color_rgba) + pen = Pen.create(item.tool.value, pen_color, item.thickness_scale) + + last_xpos = -1. + last_ypos = -1. + last_segment_width = segment_width = 0 + # Iterate through the point to form a polyline + for point_id, point in enumerate(item.points): + # align the original position + xpos = point.x + ypos = point.y + if point_id % pen.segment_length == 0: + # if there was a previous segment, end it + if last_xpos != -1.: + output.write('"/>\n') + + segment_color = pen.get_segment_color(point.speed, point.direction, point.width, point.pressure, + last_segment_width) + segment_width = pen.get_segment_width(point.speed, point.direction, point.width, point.pressure, + last_segment_width) + segment_opacity = pen.get_segment_opacity(point.speed, point.direction, point.width, point.pressure, + last_segment_width) + # create the next segment of the stroke + output.write('\t\t\t\n') + + +def draw_text(text: si.Text, output): + output.write('\t\t') + + # add some style to get readable text + output.write(''' + +''') + + y_offset = TEXT_TOP_Y + + doc = TextDocument.from_scene_item(text) + for p in doc.contents: + y_offset += LINE_HEIGHTS.get(p.style.value, 70) + + xpos = text.pos_x + ypos = text.pos_y + y_offset + cls = p.style.value.name.lower() + if str(p): + # TODO: this doesn't take into account the CrdtStr.properties (font-weight/font-style) + if _logger.root.level == logging.DEBUG: + output.write(f'\t\t\t\n') + output.write(f'\t\t\t{str(p).strip()}\n') + output.write('\t\t\n') + + +def _image_mime(data: bytes) -> str: + if data.startswith(b"\x89PNG\r\n\x1a\n"): + return "image/png" + if data[:3] == b"\xff\xd8\xff": + return "image/jpeg" + if data[:6] in (b"GIF87a", b"GIF89a"): + return "image/gif" + if data.startswith(b"RIFF") and data[8:12] == b"WEBP": + return "image/webp" + return "image/png" + + +def draw_image(image: si.Image, output, image_path: Path | None = None): + if not image.filename or image_path is None: + _logger.warning("Skipping image without filename/path: %s", image.filename) + return + path = image_path / image.filename + if not path.is_file(): + _logger.warning("Missing page image file: %s", path) + return + if len(image.vertices) < 10: + _logger.warning("Image vertices too short: %s", len(image.vertices)) + return + + left = image.vertices[0] + top = image.vertices[1] + right = image.vertices[4] + bottom = image.vertices[9] + + height = bottom - top + width = right - left + data = path.read_bytes() + mime = _image_mime(data) + href = base64.b64encode(data).decode() + output.write(f'\t\t\t\n') + output.write(f'\t\t\t\t\n') + output.write('\t\t\t\n') diff --git a/third_party/rmc/src/rmc/exporters/writing_tools.py b/third_party/rmc/src/rmc/exporters/writing_tools.py new file mode 100644 index 00000000..c862184e --- /dev/null +++ b/third_party/rmc/src/rmc/exporters/writing_tools.py @@ -0,0 +1,264 @@ +""" +Common code for writing tools. + +Code originally from https://github.com/lschwetlick/maxio through https://github.com/chemag/maxio +""" + +import logging +import math + +from rmscene.scene_items import Pen as PenType +from rmscene.scene_items import PenColor + +_logger = logging.getLogger(__name__) + +# color_id to RGB conversion +# 1. we use "color_id" for a unique, proprietary ID for colors, +# (see scene_stream.py): +RM_PALETTE = { + # Color code can be obtained from extraMetadata in the .content file + PenColor.BLACK: (0, 0, 0), + PenColor.GRAY: (144, 144, 144), + PenColor.WHITE: (255, 255, 255), + PenColor.YELLOW: (251, 247, 25), + PenColor.GREEN: (0, 255, 0), + PenColor.PINK: (255, 192, 203), + PenColor.BLUE: (78, 105, 201), + PenColor.RED: (179, 62, 57), + PenColor.GRAY_OVERLAP: (125, 125, 125), + #! Skipped as different colors are used for highlights + #! PenColor.HIGHLIGHT = ... + PenColor.GREEN_2: (161, 216, 125), + PenColor.CYAN: (139, 208, 229), + PenColor.MAGENTA: (183, 130, 205), + PenColor.YELLOW_2: (247, 232, 81), +} + + +def clamp(value): + """ + Clamp value between 0 and 1. + """ + return min(max(value, 0), 1) + + +def lookup_pen_color(pen_color_value, explicit_color_rgba): + if explicit_color_rgba is not None: + return explicit_color_rgba + if pen_color_value in RM_PALETTE: + color = RM_PALETTE[pen_color_value] + else: + _logger.warning("Unknown pen color: %s", pen_color_value) + color = RM_PALETTE[PenColor.BLACK] + if len(color) == 3: + return (*color, 255) + else: + return color + + +class Pen: + def __init__(self, name, base_width, base_color): + self.base_width = base_width + self.base_color = base_color # rgba + self.name = name + self.segment_length = 1000 + self.base_opacity = 1 + # initial stroke values + self.stroke_linecap = "round" + self.stroke_opacity = 1 + + # note that the units of the points have had their units converted + # in scene_stream.py + # speed = d.read_float32() * 4 + # ---> replace speed with speed / 4 [input] + # direction = 255 * d.read_float32() / (math.pi * 2) + # ---> replace tilt with direction_to_tilt() [input] + @classmethod + def direction_to_tilt(cls, direction): + return direction * (math.pi * 2) / 255 + + # width = int(round(d.read_float32() * 4)) + # ---> replace width with width / 4 [input] + # ---> replace width with 4 * width [output] + # pressure = d.read_float32() * 255 + # ---> replace pressure with pressure / 255 [input] + + def get_segment_width(self, speed, direction, width, pressure, last_width): + return self.base_width + + def get_segment_color(self, speed, direction, width, pressure, last_width): + return "rgba" + str(tuple(self.base_color)) + + def get_segment_opacity(self, speed, direction, width, pressure, last_width): + return self.base_opacity + + @classmethod + def create(cls, pen_nr, color_id, width): + # Brush + if pen_nr in (PenType.PAINTBRUSH_1, PenType.PAINTBRUSH_2): + return Brush(width, color_id) + # Calligraphy (spelling mistake in rmscene will eventually be fixed) + elif pen_nr == PenType.CALIGRAPHY: + return Calligraphy(width, color_id) + # Marker + elif pen_nr in (PenType.MARKER_1, PenType.MARKER_2): + return Marker(width, color_id) + # BallPoint + elif pen_nr in (PenType.BALLPOINT_1, PenType.BALLPOINT_2): + return Ballpoint(width, color_id) + # Fineliner + elif pen_nr in (PenType.FINELINER_1, PenType.FINELINER_2): + return Fineliner(width, color_id) + # Pencil + elif pen_nr in (PenType.PENCIL_1, PenType.PENCIL_2): + return Pencil(width, color_id) + # Mechanical Pencil + elif pen_nr in (PenType.MECHANICAL_PENCIL_1, PenType.MECHANICAL_PENCIL_2): + return MechanicalPencil(width, color_id) + # Highlighter + elif pen_nr in (PenType.HIGHLIGHTER_1, PenType.HIGHLIGHTER_2): + width = 15 + return Highlighter(width, color_id) + elif pen_nr == PenType.SHADER: + # TODO: check if this is correct + width = 12 + return Shader(width, color_id) + # Erase area + elif pen_nr == PenType.ERASER_AREA: + return EraseArea(width, color_id) + # Eraser + elif pen_nr == PenType.ERASER: + color_id = 2 + return Eraser(width, color_id) + raise Exception(f'Unknown pen_nr: {pen_nr}') + + +class Fineliner(Pen): + def __init__(self, base_width, base_color): + super().__init__("Fineliner", base_width * 1.8, base_color) + + +class Ballpoint(Pen): + def __init__(self, base_width, base_color): + super().__init__("Ballpoint", base_width, base_color) + self.segment_length = 5 + + def get_segment_width(self, speed, direction, width, pressure, last_width): + segment_width = (0.5 + pressure / 255) + (width / 4) - 0.5 * ((speed / 4) / 50) + return segment_width + + def get_segment_color(self, speed, direction, width, pressure, last_width): + intensity = (0.1 * - ((speed / 4) / 35)) + (1.2 * pressure / 255) + 0.5 + intensity = clamp(intensity) + # using segment color not opacity because the dots interfere with each other. + # Color must be 255 rgb + segment_color = [min(int(abs(intensity - 1) * 255), 60)] * 3 + return "rgb" + str(tuple(segment_color)) + + # def get_segment_opacity(self, speed, direction, width, pressure, last_width): + # segment_opacity = (0.2 * - ((speed / 4) / 35)) + (0.8 * pressure / 255) + # segment_opacity *= segment_opacity + # segment_opacity = self.clamp(segment_opacity) + # return segment_opacity + + +class Marker(Pen): + def __init__(self, base_width, base_color): + super().__init__("Marker", base_width, base_color) + self.segment_length = 3 + + def get_segment_width(self, speed, direction, width, pressure, last_width): + segment_width = 0.9 * ((width / 4) - 0.4 * self.direction_to_tilt(direction)) + (0.1 * last_width) + return segment_width + + +class Pencil(Pen): + def __init__(self, base_width, base_color): + super().__init__("Pencil", base_width, base_color) + self.segment_length = 2 + + def get_segment_width(self, speed, direction, width, pressure, last_width): + segment_width = 0.7 * ((((0.8 * self.base_width) + (0.5 * pressure / 255)) * (width / 4)) + - (0.25 * self.direction_to_tilt(direction) ** 1.8) - (0.6 * (speed / 4) / 50)) + # segment_width = 1.3*(((self.base_width * 0.4) * pressure) - 0.5 * ((self.direction_to_tilt(direction) ** 0.5)) + (0.5 * last_width)) + max_width = self.base_width * 10 + segment_width = segment_width if segment_width < max_width else max_width + return segment_width + + def get_segment_opacity(self, speed, direction, width, pressure, last_width): + segment_opacity = (0.1 * - ((speed / 4) / 35)) + (1 * pressure / 255) + segment_opacity = clamp(segment_opacity) - 0.1 + return segment_opacity + + +class MechanicalPencil(Pen): + def __init__(self, base_width, base_color): + super().__init__("Mechanical Pencil", base_width ** 2, base_color) + self.base_opacity = 0.7 + + +class Brush(Pen): + def __init__(self, base_width, base_color): + super().__init__("Brush", base_width, base_color) + self.segment_length = 2 + self.stroke_linecap = "round" + self.opacity = 1 + + def get_segment_width(self, speed, direction, width, pressure, last_width): + segment_width = 0.7 * (((1 + (1.4 * pressure / 255)) * (width / 4)) + - (0.5 * self.direction_to_tilt(direction)) - ((speed / 4) / 50)) # + (0.2 * last_width) + return segment_width + + def get_segment_color(self, speed, direction, width, pressure, last_width): + intensity = ((pressure / 255) ** 1.5 - 0.2 * ((speed / 4) / 50)) * 1.5 + intensity = clamp(intensity) + # using segment color not opacity because the dots interfere with each other. + # Color must be 255 rgb + rev_intensity = abs(intensity - 1) + segment_color = [int(rev_intensity * (255 - self.base_color[0])), + int(rev_intensity * (255 - self.base_color[1])), + int(rev_intensity * (255 - self.base_color[2])), + self.base_color[3]] + + return "rgba" + str(tuple(segment_color)) + + +class Highlighter(Pen): + def __init__(self, base_width, base_color): + super().__init__("Highlighter", base_width, base_color) + self.stroke_linecap = "square" + self.base_opacity = 0.3 + self.stroke_opacity = 0.2 + + +class Shader(Pen): + + def __init__(self, base_width, base_color): + super().__init__("Shader", base_width, base_color) + self.stroke_linecap = "round" + self.base_opacity = 0.1 + # self.stroke_opacity = 0.2 + self.name = "Shader" + +class Eraser(Pen): + def __init__(self, base_width, base_color): + super().__init__("Eraser", base_width * 2, base_color) + self.stroke_linecap = "square" + + +class EraseArea(Pen): + def __init__(self, base_width, base_color): + super().__init__("Erase Area", base_width, base_color) + self.stroke_linecap = "square" + self.base_opacity = 0 + + +class Calligraphy(Pen): + def __init__(self, base_width, base_color): + super().__init__("Calligraphy", base_width, base_color) + self.segment_length = 2 + + def get_segment_width(self, speed, direction, width, pressure, last_width): + segment_width = 0.9 * (((1 + pressure / 255) * (width / 4)) + - 0.3 * self.direction_to_tilt(direction)) + (0.1 * last_width) + return segment_width diff --git a/third_party/rmc/src/rmc/py.typed b/third_party/rmc/src/rmc/py.typed new file mode 100644 index 00000000..e69de29b diff --git a/third_party/rmc/test.py b/third_party/rmc/test.py new file mode 100644 index 00000000..fe019235 --- /dev/null +++ b/third_party/rmc/test.py @@ -0,0 +1,16 @@ +import glob +import os + +this_branch = "test_output" +main_branch = "test_output_main" + +for file in glob.glob(f"{this_branch}/**/*"): + reference = file.replace(this_branch, main_branch) + + # if this is a md file with actual text content, compare the text + if (file.endswith(".md") or file.endswith(".svg")) and os.path.exists(reference): + with open(file, "r") as f1, open(reference, "r") as f2: + if f1.read().strip() != f2.read().strip(): + print(f"{file} and {reference} are different") + +print("All tests completed") \ No newline at end of file diff --git a/third_party/rmc/tests/rm/Bold_Heading_Bullet_Normal.rm b/third_party/rmc/tests/rm/Bold_Heading_Bullet_Normal.rm new file mode 100644 index 00000000..740bf9b4 Binary files /dev/null and b/third_party/rmc/tests/rm/Bold_Heading_Bullet_Normal.rm differ diff --git a/third_party/rmc/tests/rm/Highlighter.rm b/third_party/rmc/tests/rm/Highlighter.rm new file mode 100644 index 00000000..39207072 Binary files /dev/null and b/third_party/rmc/tests/rm/Highlighter.rm differ diff --git a/third_party/rmc/tests/rm/Lines_v2.rm b/third_party/rmc/tests/rm/Lines_v2.rm new file mode 100644 index 00000000..25ac5224 Binary files /dev/null and b/third_party/rmc/tests/rm/Lines_v2.rm differ diff --git a/third_party/rmc/tests/rm/Normal_AB.rm b/third_party/rmc/tests/rm/Normal_AB.rm new file mode 100644 index 00000000..6092ec94 Binary files /dev/null and b/third_party/rmc/tests/rm/Normal_AB.rm differ diff --git a/third_party/rmc/tests/rm/Normal_A_stroke_2_layers.rm b/third_party/rmc/tests/rm/Normal_A_stroke_2_layers.rm new file mode 100644 index 00000000..ef5a02af Binary files /dev/null and b/third_party/rmc/tests/rm/Normal_A_stroke_2_layers.rm differ diff --git a/third_party/rmc/tests/rm/abcd.strokes.rm b/third_party/rmc/tests/rm/abcd.strokes.rm new file mode 100644 index 00000000..633397b0 Binary files /dev/null and b/third_party/rmc/tests/rm/abcd.strokes.rm differ diff --git a/third_party/rmc/tests/rm/abcd.text.rm b/third_party/rmc/tests/rm/abcd.text.rm new file mode 100644 index 00000000..1834d3ab Binary files /dev/null and b/third_party/rmc/tests/rm/abcd.text.rm differ diff --git a/third_party/rmc/tests/rm/dot.stroke.rm b/third_party/rmc/tests/rm/dot.stroke.rm new file mode 100644 index 00000000..8a36ee64 Binary files /dev/null and b/third_party/rmc/tests/rm/dot.stroke.rm differ diff --git a/third_party/rmc/tests/rm/edc580a6-1c32-471e-823c-678f975eaf81.rm b/third_party/rmc/tests/rm/edc580a6-1c32-471e-823c-678f975eaf81.rm new file mode 100644 index 00000000..18267e43 Binary files /dev/null and b/third_party/rmc/tests/rm/edc580a6-1c32-471e-823c-678f975eaf81.rm differ diff --git a/third_party/rmc/tests/rm/erasers.rm b/third_party/rmc/tests/rm/erasers.rm new file mode 100644 index 00000000..18267e43 Binary files /dev/null and b/third_party/rmc/tests/rm/erasers.rm differ diff --git a/third_party/rmc/tests/rm/extended.stroke.rm b/third_party/rmc/tests/rm/extended.stroke.rm new file mode 100644 index 00000000..a6817fee Binary files /dev/null and b/third_party/rmc/tests/rm/extended.stroke.rm differ diff --git a/third_party/rmc/tests/rm/fullpage.rm b/third_party/rmc/tests/rm/fullpage.rm new file mode 100644 index 00000000..7f5bb301 Binary files /dev/null and b/third_party/rmc/tests/rm/fullpage.rm differ diff --git a/third_party/rmc/tests/rm/keyboard-checkboxes-and-bullets.rm b/third_party/rmc/tests/rm/keyboard-checkboxes-and-bullets.rm new file mode 100644 index 00000000..1ad455af Binary files /dev/null and b/third_party/rmc/tests/rm/keyboard-checkboxes-and-bullets.rm differ diff --git a/third_party/rmc/tests/rm/layers.stroke.rm b/third_party/rmc/tests/rm/layers.stroke.rm new file mode 100644 index 00000000..da4e44ba Binary files /dev/null and b/third_party/rmc/tests/rm/layers.stroke.rm differ diff --git a/third_party/rmc/tests/rm/page_limits.rm b/third_party/rmc/tests/rm/page_limits.rm new file mode 100644 index 00000000..7f5bb301 Binary files /dev/null and b/third_party/rmc/tests/rm/page_limits.rm differ diff --git a/third_party/rmc/tests/rm/pen_size_test.strokes.rm b/third_party/rmc/tests/rm/pen_size_test.strokes.rm new file mode 100644 index 00000000..13de6ed2 Binary files /dev/null and b/third_party/rmc/tests/rm/pen_size_test.strokes.rm differ diff --git a/third_party/rmc/tests/rm/text_and_strokes.rm b/third_party/rmc/tests/rm/text_and_strokes.rm new file mode 100644 index 00000000..3e537cde Binary files /dev/null and b/third_party/rmc/tests/rm/text_and_strokes.rm differ diff --git a/third_party/rmc/tests/rm/text_multiple_lines.rm b/third_party/rmc/tests/rm/text_multiple_lines.rm new file mode 100644 index 00000000..1fad2cb4 Binary files /dev/null and b/third_party/rmc/tests/rm/text_multiple_lines.rm differ diff --git a/third_party/rmc/tests/rm/writing_tools.rm b/third_party/rmc/tests/rm/writing_tools.rm new file mode 100644 index 00000000..9011abb2 Binary files /dev/null and b/third_party/rmc/tests/rm/writing_tools.rm differ diff --git a/third_party/rmc/tests/rm/writing_tools_with_text.rm b/third_party/rmc/tests/rm/writing_tools_with_text.rm new file mode 100644 index 00000000..ee627a55 Binary files /dev/null and b/third_party/rmc/tests/rm/writing_tools_with_text.rm differ diff --git a/third_party/rmscene/.github/workflows/release.yml b/third_party/rmscene/.github/workflows/release.yml new file mode 100644 index 00000000..e3ecdc26 --- /dev/null +++ b/third_party/rmscene/.github/workflows/release.yml @@ -0,0 +1,116 @@ +# Based on https://packaging.python.org/en/latest/guides/publishing-package-distribution-releases-using-github-actions-ci-cd-workflows/ + +name: Publish Python distribution to PyPI + +on: push + +jobs: + build: + name: Build distribution + runs-on: ubuntu-latest + if: startsWith(github.ref, 'refs/tags/') || github.ref == 'refs/heads/main' + steps: + - uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.x" + - name: Install pypa/build + run: python3 -m pip install build --user + - name: Build a binary wheel and a source tarball + run: python3 -m build + - name: Store the distribution packages + uses: actions/upload-artifact@v4 + with: + name: python-package-distributions + path: dist/ + + publish-to-pypi: + name: Publish Python distribution to PyPI + if: startsWith(github.ref, 'refs/tags/') # only publish to PyPI on tag pushes + needs: + - build + runs-on: ubuntu-latest + environment: + name: pypi + url: https://pypi.org/p/rmscene + permissions: + id-token: write # IMPORTANT: mandatory for trusted publishing + + steps: + - name: Download all the dists + uses: actions/download-artifact@v4 + with: + name: python-package-distributions + path: dist/ + - name: Publish distribution 📦 to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 + + github-release: + name: Sign Python distribution and upload to Github Release + needs: + - publish-to-pypi + runs-on: ubuntu-latest + + permissions: + contents: write # IMPORTANT: mandatory for making GitHub Releases + id-token: write # IMPORTANT: mandatory for sigstore + + steps: + - name: Download all the dists + uses: actions/download-artifact@v4 + with: + name: python-package-distributions + path: dist/ + - name: Sign the dists with Sigstore + uses: sigstore/gh-action-sigstore-python@v3.0.0 + with: + inputs: >- + ./dist/*.tar.gz + ./dist/*.whl + - name: Create GitHub Release + env: + GITHUB_TOKEN: ${{ github.token }} + run: >- + gh release create + '${{ github.ref_name }}' + --repo '${{ github.repository }}' + --notes "" + - name: Upload artifact signatures to GitHub Release + env: + GITHUB_TOKEN: ${{ github.token }} + # Upload to GitHub Release using the `gh` CLI. + # `dist/` contains the built packages, and the + # sigstore-produced signatures and certificates. + run: >- + gh release upload + '${{ github.ref_name }}' dist/** + --repo '${{ github.repository }}' + + publish-to-testpypi: + name: Publish Python distribution to TestPyPI + if: github.repository == 'ricklupton/rmscene' # publish to testpypi only on the original repo + needs: + - build + runs-on: ubuntu-latest + + environment: + name: testpypi + url: https://test.pypi.org/p/rmscene + + permissions: + id-token: write # IMPORTANT: mandatory for trusted publishing + + steps: + - name: Download all the dists + uses: actions/download-artifact@v4 + with: + name: python-package-distributions + path: dist/ + - name: Publish distribution 📦 to TestPyPI + uses: pypa/gh-action-pypi-publish@release/v1 + with: + repository-url: https://test.pypi.org/legacy/ + # Don't fail when this is another push to the same version. If we put + # the git hash in the version string, this could be removed. + skip-existing: true diff --git a/third_party/rmscene/.github/workflows/test.yml b/third_party/rmscene/.github/workflows/test.yml new file mode 100644 index 00000000..d0e34d80 --- /dev/null +++ b/third_party/rmscene/.github/workflows/test.yml @@ -0,0 +1,28 @@ +# This workflow will install Python dependencies and run the tests + +name: Test + +on: + push: + branches: [ main, github_actions ] + pull_request: + branches: [ main ] + +jobs: + tests: + runs-on: ${{ matrix.os }} + strategy: + matrix: + python-version: ["3.10", "3.11"] + os: [ubuntu-latest, windows-latest, macos-latest] + steps: + - uses: actions/checkout@v3 + - name: Install poetry + run: pipx install poetry + - name: Setup Python ${{ matrix.python-version }} + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + cache: 'poetry' + - run: poetry install + - run: poetry run pytest tests diff --git a/third_party/rmscene/.gitignore b/third_party/rmscene/.gitignore new file mode 100644 index 00000000..61ca704a --- /dev/null +++ b/third_party/rmscene/.gitignore @@ -0,0 +1,2 @@ +__pycache__/ +/.hypothesis/ diff --git a/third_party/rmscene/LICENSE b/third_party/rmscene/LICENSE new file mode 100644 index 00000000..672f11c9 --- /dev/null +++ b/third_party/rmscene/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 Rick Lupton + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/third_party/rmscene/README.md b/third_party/rmscene/README.md new file mode 100644 index 00000000..e4c08e11 --- /dev/null +++ b/third_party/rmscene/README.md @@ -0,0 +1,145 @@ +# rmscene + +Python library to read v6 files from reMarkable tables (software version 3). + +In particular, this version introduces the ability to include text as well as drawn lines. Extracting this text is the original motivation to develop this library, but it also can read much of the other types of data in the reMarkable files. + +To convert rm files to other formats, you can use [rmc](https://github.com/ricklupton/rmc), which combines this library with code for converting lines to SVG, PDF, and simple Markdown. + +## Changelog + +### Unreleased + +### v0.8.0 + +New features: + +- Store highlighter colour in `color_rgba` field on `GlyphRange` ([#50](https://github.com/ricklupton/rmscene/pull/50)) +- Store `SceneInfo` on `SceneTree` for convenient access + +Performance improvements: + +- Use Kahn's algorithm for CRDT topological sort -- thanks to @andymatuschak ([#49](https://github.com/ricklupton/rmscene/pull/49)) + +Fixes: + +- Fix author sort order for concurrent CRDT inserts + + +### v0.7.0 + +Change in block properties: + +- Some SceneInfo values are now optional ([#40](https://github.com/ricklupton/rmscene/issues/40)) + +New feature: + +- Add support for `paper_size` field on some SceneInfo blocks + +### v0.6.1 + +Fixes: + +- Fix AssertionError when some ids are missing in a `CrdtSequence` ([#36](https://github.com/ricklupton/rmscene/pull/36)) +- Fix ValueError when the node_id is missing in a `SceneGroupItemBlock` ([#16](https://github.com/ricklupton/rmscene/issues/16)) +- Store any unparsed data in blocks as raw bytes to allow for round-trip saving of files written in a newer format than the parsing code knows about. + +### v0.6.0 + +New features: + +- Add support for new blocks: `0x0D` (SceneInfo) and `0x08` (SceneTombstoneItemBlock) ([#24](https://github.com/ricklupton/rmscene/pull/24/)) +- Add support for `move_id` field on some SceneLineItems ([#24](https://github.com/ricklupton/rmscene/pull/24/)) +- Add support for new pen types and colours ([#31](https://github.com/ricklupton/rmscene/pull/31)) + +### v0.5.0 + +Breaking changes: + +- The `start` property of `GlyphRange` items is now optional + ([#15](https://github.com/ricklupton/rmscene/pull/15/)). +- The representation of formatted text spans has changed. Rather than + using nested structures like `BoldSpan` and `ItalicSpan`, the + `CrdtStr` objects now have optional text properties like + `font-weight` and `font-style`. This simplifies the parsing code and + the resulting data structure. + +New features: + +- Improved error recovery. An error during parsing, or an unknown block type, + results in an `UnreadableBlock` containing the data that could not be read, so + that parsing of other blocks can continue. +- Compatible with new reMarkable software version 3.6 format for + highlighted text + ([#15](https://github.com/ricklupton/rmscene/pull/15/)). +- New methods `read_bool_optional` and similar of `TaggedBlockReader` + which return a default value if no matching tagged value is present + in the block. + +Other changes and fixes: + +- The `value` attribute of scene item blocks, which was not being used, has been + removed. +- Check more carefully for sub-blocks + ([#17](https://github.com/ricklupton/rmscene/issues/17#issuecomment-1701071477)). +- Type hints fixed for `expand_text_items`. + +### v0.4.0 + +Breaking changes: + +- Rename `scene_items.TextFormat` to `ParagraphStyle` to better describe its + meaning, now that we have inline bold/italic text styles. +- Remove methods from `scene_items.Text` object; use `text.TextDocument` + instead. +- Writer: experimental change to emulate different reMarkable software versions + by passing `{"version": "3.2.2"}` options to `write_blocks`. This allows us to + continue to test round-trip reading and writing of old test files as new data + values are added. Replaces `"line_version"` option. + +New features: + +- Parse text formatting information (bold and italic) introduced in reMarkable + software version 3.3. + +Other changes: + +- Allow empty text items and unknown text formats without throwing exceptions. +- When extra data is present in the file, log the unrecognised bytes at DEBUG + logging level along with the call stack, to make it easier to figure out where + the code needs to be modified to read new data. +- Parse new data values (with unknown meaning) in PageInfoBlock and + MigrationInfoBlock. + +### v0.3.0 + +- Introduce `CrdtSequence` type to handle the different places that CRDT + sequences are used, not just for text. +- Introduce `scene_items` module with data structures representing the data, + independently from the `Block`s used to serialize them to `.rm` files. +- Introduce a `SceneTree` structure which holds the `SceneItem`s in + groups/layers. +- Move Text data from `RootTextBlock` to `scene_items.Text` class, which + includes methods for extracting lines of text and formatting. +- Text lines now include the trailing newline character. +- Read `GlyphRange` scene items, representing highlighted text in PDFs. + +### v0.2.0 + +- Try to be more robust to unexpected data introduced by newer reMarkable software versions. +- Only warn once if unknown data is present, rather than for every block. +- Small API change to return type of `read_block` and `read_subblock` methods. + +### v0.1.0 + +- Initial release + +## Acknowledgements + +https://github.com/ddvk/reader helped a lot in figuring out the structure and meaning of the files. [@adq](https://github.com/adq) discovered a means to get debug output (see [issue 25](https://github.com/ricklupton/rmscene/issues/25)) which is very helpful for understanding the format. + +Contributors: +- [@Azeirah](https://github.com/Azeirah) -- code and reporting issues +- [@adq](https://github.com/adq) -- code and reporting issues +- [@dotlambda](https://github.com/dotlambda) -- packaging +- [@ChenghaoMou](https://github.com/ChenghaoMou) diff --git a/third_party/rmscene/poetry.lock b/third_party/rmscene/poetry.lock new file mode 100644 index 00000000..055aba40 --- /dev/null +++ b/third_party/rmscene/poetry.lock @@ -0,0 +1,177 @@ +# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. + +[[package]] +name = "attrs" +version = "22.2.0" +description = "Classes Without Boilerplate" +optional = false +python-versions = ">=3.6" +files = [ + {file = "attrs-22.2.0-py3-none-any.whl", hash = "sha256:29e95c7f6778868dbd49170f98f8818f78f3dc5e0e37c0b1f474e3561b240836"}, + {file = "attrs-22.2.0.tar.gz", hash = "sha256:c9227bfc2f01993c03f68db37d1d15c9690188323c067c641f1a35ca58185f99"}, +] + +[package.extras] +cov = ["attrs[tests]", "coverage-enable-subprocess", "coverage[toml] (>=5.3)"] +dev = ["attrs[docs,tests]"] +docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope.interface"] +tests = ["attrs[tests-no-zope]", "zope.interface"] +tests-no-zope = ["cloudpickle", "cloudpickle", "hypothesis", "hypothesis", "mypy (>=0.971,<0.990)", "mypy (>=0.971,<0.990)", "pympler", "pympler", "pytest (>=4.3.0)", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-mypy-plugins", "pytest-xdist[psutil]", "pytest-xdist[psutil]"] + +[[package]] +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] + +[[package]] +name = "exceptiongroup" +version = "1.1.0" +description = "Backport of PEP 654 (exception groups)" +optional = false +python-versions = ">=3.7" +files = [ + {file = "exceptiongroup-1.1.0-py3-none-any.whl", hash = "sha256:327cbda3da756e2de031a3107b81ab7b3770a602c4d16ca618298c526f4bec1e"}, + {file = "exceptiongroup-1.1.0.tar.gz", hash = "sha256:bcb67d800a4497e1b404c2dd44fca47d3b7a5e5433dbab67f96c1a685cdfdf23"}, +] + +[package.extras] +test = ["pytest (>=6)"] + +[[package]] +name = "hypothesis" +version = "6.68.2" +description = "A library for property-based testing" +optional = false +python-versions = ">=3.7" +files = [ + {file = "hypothesis-6.68.2-py3-none-any.whl", hash = "sha256:2a41cc766cde52705895e54547374af89c617e8ec7bc4186cb7f03884a667d4e"}, + {file = "hypothesis-6.68.2.tar.gz", hash = "sha256:a7eb2b0c9a18560d8197fe35047ceb58e7e8ab7623a3e5a82613f6a2cd71cffa"}, +] + +[package.dependencies] +attrs = ">=19.2.0" +exceptiongroup = {version = ">=1.0.0", markers = "python_version < \"3.11\""} +sortedcontainers = ">=2.1.0,<3.0.0" + +[package.extras] +all = ["backports.zoneinfo (>=0.2.1)", "black (>=19.10b0)", "click (>=7.0)", "django (>=3.2)", "dpcontracts (>=0.4)", "importlib-metadata (>=3.6)", "lark (>=0.10.1)", "libcst (>=0.3.16)", "numpy (>=1.9.0)", "pandas (>=1.0)", "pytest (>=4.6)", "python-dateutil (>=1.4)", "pytz (>=2014.1)", "redis (>=3.0.0)", "rich (>=9.0.0)", "tzdata (>=2022.7)"] +cli = ["black (>=19.10b0)", "click (>=7.0)", "rich (>=9.0.0)"] +codemods = ["libcst (>=0.3.16)"] +dateutil = ["python-dateutil (>=1.4)"] +django = ["django (>=3.2)"] +dpcontracts = ["dpcontracts (>=0.4)"] +ghostwriter = ["black (>=19.10b0)"] +lark = ["lark (>=0.10.1)"] +numpy = ["numpy (>=1.9.0)"] +pandas = ["pandas (>=1.0)"] +pytest = ["pytest (>=4.6)"] +pytz = ["pytz (>=2014.1)"] +redis = ["redis (>=3.0.0)"] +zoneinfo = ["backports.zoneinfo (>=0.2.1)", "tzdata (>=2022.7)"] + +[[package]] +name = "iniconfig" +version = "1.1.1" +description = "iniconfig: brain-dead simple config-ini parsing" +optional = false +python-versions = "*" +files = [ + {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, + {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, +] + +[[package]] +name = "packaging" +version = "23.0" +description = "Core utilities for Python packages" +optional = false +python-versions = ">=3.7" +files = [ + {file = "packaging-23.0-py3-none-any.whl", hash = "sha256:714ac14496c3e68c99c29b00845f7a2b85f3bb6f1078fd9f72fd20f0570002b2"}, + {file = "packaging-23.0.tar.gz", hash = "sha256:b6ad297f8907de0fa2fe1ccbd26fdaf387f5f47c7275fedf8cce89f99446cf97"}, +] + +[[package]] +name = "pluggy" +version = "1.6.0" +description = "plugin and hook calling mechanisms for python" +optional = false +python-versions = ">=3.9" +files = [ + {file = "pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746"}, + {file = "pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3"}, +] + +[package.extras] +dev = ["pre-commit", "tox"] +testing = ["coverage", "pytest", "pytest-benchmark"] + +[[package]] +name = "pygments" +version = "2.20.0" +description = "Pygments is a syntax highlighting package written in Python." +optional = false +python-versions = ">=3.9" +files = [ + {file = "pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176"}, + {file = "pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f"}, +] + +[package.extras] +windows-terminal = ["colorama (>=0.4.6)"] + +[[package]] +name = "pytest" +version = "9.0.2" +description = "pytest: simple powerful testing with Python" +optional = false +python-versions = ">=3.10" +files = [ + {file = "pytest-9.0.2-py3-none-any.whl", hash = "sha256:711ffd45bf766d5264d487b917733b453d917afd2b0ad65223959f59089f875b"}, + {file = "pytest-9.0.2.tar.gz", hash = "sha256:75186651a92bd89611d1d9fc20f0b4345fd827c41ccd5c299a868a05d70edf11"}, +] + +[package.dependencies] +colorama = {version = ">=0.4", markers = "sys_platform == \"win32\""} +exceptiongroup = {version = ">=1", markers = "python_version < \"3.11\""} +iniconfig = ">=1.0.1" +packaging = ">=22" +pluggy = ">=1.5,<2" +pygments = ">=2.7.2" +tomli = {version = ">=1", markers = "python_version < \"3.11\""} + +[package.extras] +dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "requests", "setuptools", "xmlschema"] + +[[package]] +name = "sortedcontainers" +version = "2.4.0" +description = "Sorted Containers -- Sorted List, Sorted Dict, Sorted Set" +optional = false +python-versions = "*" +files = [ + {file = "sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0"}, + {file = "sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88"}, +] + +[[package]] +name = "tomli" +version = "2.0.1" +description = "A lil' TOML parser" +optional = false +python-versions = ">=3.7" +files = [ + {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, + {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, +] + +[metadata] +lock-version = "2.0" +python-versions = "^3.10" +content-hash = "07affcdf634dfb56694d6f5b07b9c5747c248d566a90e78c80e71f356a679c01" diff --git a/third_party/rmscene/pyproject.toml b/third_party/rmscene/pyproject.toml new file mode 100644 index 00000000..5f3421e4 --- /dev/null +++ b/third_party/rmscene/pyproject.toml @@ -0,0 +1,20 @@ +[tool.poetry] +name = "rmscene" +version = "0.8.1-dev" +description = "Read v6 .rm files from the reMarkable tablet" +authors = ["Rick Lupton "] +license = "MIT" +repository = "https://github.com/ricklupton/rmscene" +readme = "README.md" + +[tool.poetry.dependencies] +python = "^3.10" +packaging = "^23.0" + +[tool.poetry.group.dev.dependencies] +pytest = ">=7.4" +hypothesis = "^6.68.2" + +[build-system] +requires = ["poetry-core>=1.0.0"] +build-backend = "poetry.core.masonry.api" diff --git a/third_party/rmscene/src/rmscene/__init__.py b/third_party/rmscene/src/rmscene/__init__.py new file mode 100644 index 00000000..24a2107f --- /dev/null +++ b/third_party/rmscene/src/rmscene/__init__.py @@ -0,0 +1,4 @@ +from .tagged_block_common import * +from .tagged_block_reader import * +from .tagged_block_writer import * +from .scene_stream import * diff --git a/third_party/rmscene/src/rmscene/__main__.py b/third_party/rmscene/src/rmscene/__main__.py new file mode 100644 index 00000000..474fd638 --- /dev/null +++ b/third_party/rmscene/src/rmscene/__main__.py @@ -0,0 +1,27 @@ +"""Experimental cli helpers.""" + +import argparse +import logging +import sys +from . import read_blocks + + +def parse_args(args): + parser = argparse.ArgumentParser(prog="rmscene") + parser.add_argument("file", type=argparse.FileType("rb"), help="filename to read") + return parser.parse_args(args) + + +def pprint_file(args) -> None: + import pprint + + result = read_blocks(args.file) + for el in result: + print() + pprint.pprint(el) + + +if __name__ == "__main__": + args = parse_args(sys.argv[1:]) + logging.basicConfig(level=logging.INFO) + pprint_file(args) diff --git a/third_party/rmscene/src/rmscene/crdt_sequence.py b/third_party/rmscene/src/rmscene/crdt_sequence.py new file mode 100644 index 00000000..a55892df --- /dev/null +++ b/third_party/rmscene/src/rmscene/crdt_sequence.py @@ -0,0 +1,199 @@ +"""Data structure representing CRDT sequence. + +""" + +import logging +import typing as tp +from typing import Iterable +from collections import defaultdict +from dataclasses import dataclass + +from .tagged_block_common import CrdtId + +_logger = logging.getLogger(__name__) + + +# If the type constraint is for a CrdtSequenceItem[Superclass], then a +# CrdtSequenceItem[Subclass] would do, so it is covariant. + +_T = tp.TypeVar("_T", covariant=True) + + +@dataclass +class CrdtSequenceItem(tp.Generic[_T]): + item_id: CrdtId + left_id: CrdtId + right_id: CrdtId + deleted_length: int + value: _T + + +# As a mutable container, CrdtSequence is invariant. +_Ti = tp.TypeVar("_Ti", covariant=False) + + +class CrdtSequence(tp.Generic[_Ti]): + """Ordered CRDT Sequence container. + + The Sequence contains `CrdtSequenceItem`s, each of which has an ID and + left/right IDs establishing a partial order. + + Iterating through the `CrdtSequence` yields IDs following this order. + + """ + + def __init__(self, items=None): + if items is None: + items = [] + self._items = {item.item_id: item for item in items} + + def __eq__(self, other): + if isinstance(other, CrdtSequence): + return self._items == other._items + if isinstance(other, (list, tuple)): + return self == CrdtSequence(other) + raise NotImplemented + + def __repr__(self): + return "CrdtSequence(%s)" % (", ".join(str(i) for i in self._items.values())) + + ## Access values, in order + + def __iter__(self) -> tp.Iterator[CrdtId]: + """Return ids in order""" + yield from toposort_items(self._items.values()) + + def keys(self) -> list[CrdtId]: + """Return CrdtIds in order.""" + return list(self) + + def values(self) -> list[_Ti]: + """Return list of sorted values.""" + return [self[item_id] for item_id in self] + + def items(self) -> Iterable[tuple[CrdtId, _Ti]]: + """Return list of sorted key, value pairs.""" + return [(item_id, self[item_id]) for item_id in self] + + def __getitem__(self, key: CrdtId) -> _Ti: + """Return item with key""" + return self._items[key].value + + ## Access SequenceItems + + def sequence_items(self) -> list[CrdtSequenceItem[_Ti]]: + """Iterate through CrdtSequenceItems.""" + return list(self._items.values()) + + ## Modify sequence + + def add(self, item: CrdtSequenceItem[_Ti]): + if item.item_id in self._items: + raise ValueError("Already have item %s" % item.item_id) + self._items[item.item_id] = item + + +END_MARKER = CrdtId(0, 0) + + +def toposort_items(items: Iterable[CrdtSequenceItem]) -> Iterable[CrdtId]: + """Sort SequenceItems based on left and right ids. + + Returns `CrdtId`s in the sorted order. + + This uses Kahn's algorithm for topological sorting. Standard Kahn's + algorithm is O(V + E), i.e. linear. We use a heap to maintain + deterministic ordering when multiple items become ready simultaneously + (matching the previous implementation's use of sorted()). This adds + a log factor, making the overall complexity O(V log V + E), which + simplifies to O(V log V) since each item has exactly 2 edges. + """ + import heapq + + item_dict = {} + for item in items: + item_dict[item.item_id] = item + if not item_dict: + return # nothing to do + + def _side_id(item, side): + side_id = getattr(item, f"{side}_id") + if side_id == END_MARKER or side_id not in item_dict: + if side_id != END_MARKER: + _logger.debug("Ignoring unknown %s_id %s of %s", side, side_id, item) + return "__start" if side == "left" else "__end" + else: + return side_id + + # Build dependency graph with O(1) lookups + # in_degree[item] = number of unprocessed dependencies + # dependents[item] = list of items that depend on this item + in_degree = defaultdict(int) + dependents = defaultdict(list) + + # Track all nodes we need to process + all_nodes = set() + all_nodes.add("__start") + all_nodes.add("__end") + + for item in item_dict.values(): + item_id = item.item_id + left_id = _side_id(item, "left") + right_id = _side_id(item, "right") + + all_nodes.add(item_id) + all_nodes.add(left_id) + all_nodes.add(right_id) + + # item depends on left_id (item comes after left_id) + in_degree[item_id] += 1 + dependents[left_id].append(item_id) + + # right_id depends on item (right_id comes after item) + in_degree[right_id] += 1 + dependents[item_id].append(right_id) + + # Initialize in_degree for nodes with no incoming edges + for node in all_nodes: + if node not in in_degree: + in_degree[node] = 0 + + # Use a heap to yield items in deterministic order when multiple items + # become ready simultaneously (i.e. concurrent inserts at the same + # position). For concurrent items with the same left_id/right_id, the + # reMarkable places higher author IDs first. + def sort_key(node): + if node == "__start": + return (0, 0, 0) + elif node == "__end": + return (2, 0, 0) + else: + return (1, -node.part1, node.part2) + + # Start with nodes that have no dependencies + ready = [] + for node in all_nodes: + if in_degree[node] == 0: + heapq.heappush(ready, (sort_key(node), node)) + + while ready: + _, node = heapq.heappop(ready) + + # Yield if it's an actual item (not __start or __end) + if node in item_dict: + yield node + + # Stop if we've reached __end + if node == "__end": + break + + # Process dependents + for dependent in dependents[node]: + in_degree[dependent] -= 1 + if in_degree[dependent] == 0: + heapq.heappush(ready, (sort_key(dependent), dependent)) + + # Check for cycles (items with remaining dependencies) + remaining = [n for n in all_nodes if in_degree[n] > 0 and n != "__end"] + if remaining: + raise ValueError("cyclic dependency") diff --git a/third_party/rmscene/src/rmscene/py.typed b/third_party/rmscene/src/rmscene/py.typed new file mode 100644 index 00000000..e69de29b diff --git a/third_party/rmscene/src/rmscene/scene_items.py b/third_party/rmscene/src/rmscene/scene_items.py new file mode 100644 index 00000000..b6e88a9f --- /dev/null +++ b/third_party/rmscene/src/rmscene/scene_items.py @@ -0,0 +1,239 @@ +"""Data structures for the contents of a scene.""" + +import enum +import logging +import typing as tp +from dataclasses import dataclass, field + +from .crdt_sequence import CrdtSequence +from .tagged_block_common import CrdtId, LwwValue +from .text import expand_text_items + +_logger = logging.getLogger(__name__) + + +## Base class + + +@dataclass +class SceneItem: + """Base class for items stored in scene tree.""" + + +## Image + + +@dataclass +class ImageInfo(SceneItem): + filename: LwwValue[str] + flags: LwwValue[bytes] + + +@dataclass +class Image(SceneItem): + uuid: LwwValue[bytes] + vertices: list[float] + move_id: tp.Optional[CrdtId] = None + filename: tp.Optional[str] = None + + +## Group + + +@dataclass +class Group(SceneItem): + """A Group represents a group of nested items. + + Groups are used to represent layers. + + node_id is the id that this sub-tree is stored as a "SceneTreeBlock". + + children is a sequence of other SceneItems. + + `anchor_id` refers to a text character which provides the anchor y-position + for this group. There are two values that seem to be special: + - `0xfffffffffffe` seems to be used for lines right at the top of the page? + - `0xffffffffffff` seems to be used for lines right at the bottom of the page? + + """ + + node_id: CrdtId + children: CrdtSequence[SceneItem] = field(default_factory=CrdtSequence) + label: LwwValue[str] = LwwValue(CrdtId(0, 0), "") + visible: LwwValue[bool] = LwwValue(CrdtId(0, 0), True) + + anchor_id: tp.Optional[LwwValue[CrdtId]] = None + anchor_type: tp.Optional[LwwValue[int]] = None + anchor_threshold: tp.Optional[LwwValue[float]] = None + anchor_origin_x: tp.Optional[LwwValue[float]] = None + + +## Strokes + + +@enum.unique +class PenColor(enum.IntEnum): + """ + Color index value. + """ + + # XXX list from remt pre-v6 + + BLACK = 0 + GRAY = 1 + WHITE = 2 + + YELLOW = 3 + GREEN = 4 + PINK = 5 + + BLUE = 6 + RED = 7 + + GRAY_OVERLAP = 8 + + # All highlight colors share the same value. + # The actual color is stored in the optional `color_rgba` field of Line. + HIGHLIGHT = 9 + + GREEN_2 = 10 + CYAN = 11 + MAGENTA = 12 + + YELLOW_2 = 13 + + +@enum.unique +class Pen(enum.IntEnum): + """ + Stroke pen id representing reMarkable tablet tools. + + Tool examples: ballpoint, fineliner, highlighter or eraser. + """ + + # XXX this list is from remt pre-v6 + + BALLPOINT_1 = 2 + BALLPOINT_2 = 15 + CALIGRAPHY = 21 + ERASER = 6 + ERASER_AREA = 8 + FINELINER_1 = 4 + FINELINER_2 = 17 + HIGHLIGHTER_1 = 5 + HIGHLIGHTER_2 = 18 + MARKER_1 = 3 + MARKER_2 = 16 + MECHANICAL_PENCIL_1 = 7 + MECHANICAL_PENCIL_2 = 13 + PAINTBRUSH_1 = 0 + PAINTBRUSH_2 = 12 + PENCIL_1 = 1 + PENCIL_2 = 14 + SHADER = 23 + + @classmethod + def is_highlighter(cls, value: int) -> bool: + return value in (cls.HIGHLIGHTER_1, cls.HIGHLIGHTER_2) + + +@dataclass +class Point: + x: float + y: float + speed: int + direction: int + width: int + pressure: int + + +@dataclass +class Line(SceneItem): + color: PenColor + tool: Pen + points: list[Point] + thickness_scale: float + starting_length: float + move_id: tp.Optional[CrdtId] = None + color_rgba: tp.Optional[tuple[int, int, int, int]] = None + + +## Text + + +@enum.unique +class ParagraphStyle(enum.IntEnum): + """ + Text paragraph style. + """ + + BASIC = 0 + PLAIN = 1 + HEADING = 2 + BOLD = 3 + BULLET = 4 + BULLET2 = 5 + CHECKBOX = 6 + CHECKBOX_CHECKED = 7 + + +END_MARKER = CrdtId(0, 0) + + +@dataclass +class Text(SceneItem): + """Block of text. + + `items` are a CRDT sequence of strings. The `item_id` for each string refers + to its first character; subsequent characters implicitly have sequential + ids. + + When formatting is present, some of `items` have a value of an integer + formatting code instead of a string. + + `styles` are LWW values representing a mapping of character IDs to + `ParagraphStyle` values. These formats apply to each line of text (until the + next newline). + + `pos_x`, `pos_y` and `width` are dimensions for the text block. + + """ + + items: CrdtSequence[str | int] + styles: dict[CrdtId, LwwValue[ParagraphStyle]] + pos_x: float + pos_y: float + width: float + + +## Glyph range + + +@dataclass +class Rectangle: + x: float + y: float + w: float + h: float + + +@dataclass +class GlyphRange(SceneItem): + """Highlighted text + + `start` is only available in SceneGlyphItemBlock version=0, prior to ReMarkable v3.6 + + `length` is the length of the text + + `text` is the highlighted text itself + + `color` represents the highlight color + + `rectangles` represent the locations of the highlight. + """ + start: tp.Optional[int] + length: int + text: str + color: PenColor + rectangles: list[Rectangle] + color_rgba: tp.Optional[tuple[int, int, int, int]] = None diff --git a/third_party/rmscene/src/rmscene/scene_stream.py b/third_party/rmscene/src/rmscene/scene_stream.py new file mode 100644 index 00000000..cf7e1180 --- /dev/null +++ b/third_party/rmscene/src/rmscene/scene_stream.py @@ -0,0 +1,1107 @@ +"""Read structure of reMarkable tablet lines format v6 + +With help from ddvk's v6 reader, and enum values from remt. + +""" + +from __future__ import annotations + +import logging +import math +import typing as tp +from abc import ABC, abstractmethod +from collections.abc import Iterable, Iterator +from dataclasses import KW_ONLY, dataclass, replace +from uuid import UUID, uuid4 + +from packaging.version import Version + +from . import scene_items as si +from .crdt_sequence import CrdtSequence, CrdtSequenceItem +from .scene_tree import SceneTree +from .tagged_block_common import CrdtId, LwwValue, TagType, UnexpectedBlockError +from .tagged_block_reader import MainBlockInfo, TaggedBlockReader +from .tagged_block_writer import TaggedBlockWriter + +_logger = logging.getLogger(__name__) + + +############################################################ +# Top-level block types +############################################################ + + +@dataclass +class Block(ABC): + BLOCK_TYPE: tp.ClassVar + + # Store any unrecognised data we can't understand + _: KW_ONLY + extra_data: bytes = b"" + + def version_info(self, writer: TaggedBlockWriter) -> tuple[int, int]: + """Return (min_version, current_version) to use when writing.""" + return (1, 1) + + def get_block_type(self) -> int: + """Return block type for this block. + + By default, returns the block's BLOCK_TYPE attribute, but this method + can be overriden if a single block subclass can handle multiple block + types. + + """ + return self.BLOCK_TYPE + + @classmethod + def lookup(cls, block_type: int) -> tp.Optional[tp.Type[Block]]: + if getattr(cls, "BLOCK_TYPE", None) == block_type: + return cls + for subclass in cls.__subclasses__(): + if match := subclass.lookup(block_type): + return match + return None + + @classmethod + def read(self, reader: TaggedBlockReader) -> Optional[Block]: + """ + Maybe parse a block from the reader stream. + """ + with reader.read_block() as block_info: + if block_info is None: + return + + block_type = Block.lookup(block_info.block_type) + if block_type: + try: + block = block_type.from_stream(reader) + except Exception as e: + _logger.warning("Error reading block: %s", e) + reader.data.data.seek(block_info.offset) + data = reader.data.read_bytes(block_info.size) + block = UnreadableBlock(str(e), data, block_info) + else: + msg = ( + f"Unknown block type {block_info.block_type}. " + f"Skipping {block_info.size} bytes." + ) + _logger.warning(msg) + data = reader.data.read_bytes(block_info.size) + block = UnreadableBlock(msg, data, block_info) + + # Keep any unparsed extra data + block.extra_data = block_info.extra_data + return block + + def write(self, writer: TaggedBlockWriter): + """Write the block header and content to the stream.""" + min_version, current_version = self.version_info(writer) + with writer.write_block(self.get_block_type(), min_version, current_version): + self.to_stream(writer) + # Write any leftover extra data that wasn't parsed + writer.data.write_bytes(self.extra_data) + + @classmethod + @abstractmethod + def from_stream(cls, reader: TaggedBlockReader) -> Block: + """Read content of block from stream.""" + raise NotImplementedError() + + @abstractmethod + def to_stream(self, writer: TaggedBlockWriter): + """Write content of block to stream.""" + raise NotImplementedError() + + +@dataclass +class UnreadableBlock(Block): + """Represent a block which could not be read for some reason.""" + + error: str + data: bytes + info: MainBlockInfo + + def get_block_type(self) -> int: + return self.info.block_type + + @classmethod + def from_stream(cls, reader: TaggedBlockReader) -> Block: + raise NotImplementedError() + + def to_stream(self, writer: TaggedBlockWriter): + writer.data.write_bytes(self.data) + + +@dataclass +class SceneInfo(Block): + BLOCK_TYPE: tp.ClassVar = 0x0D + + def version_info(self, _) -> tuple[int, int]: + """Return (min_version, current_version) to use when writing.""" + return (0, 1) + + current_layer: LwwValue[CrdtId] + background_visible: tp.Optional[LwwValue[bool]] + root_document_visible: tp.Optional[LwwValue[bool]] + paper_size: tp.Optional[tuple[int, int]] + + @classmethod + def from_stream(cls, stream: TaggedBlockReader) -> SceneInfo: + current_layer = stream.read_lww_id(1) + background_visible = stream.read_lww_bool(2) if stream.bytes_remaining_in_block() > 0 else None + root_document_visible = stream.read_lww_bool(3) if stream.bytes_remaining_in_block() > 0 else None + paper_size = stream.read_int_pair(5) if stream.bytes_remaining_in_block() > 0 else None + + return SceneInfo(current_layer=current_layer, + background_visible=background_visible, + root_document_visible=root_document_visible, + paper_size=paper_size) + + def to_stream(self, writer: TaggedBlockWriter): + writer.write_lww_id(1, self.current_layer) + if self.background_visible: + writer.write_lww_bool(2, self.background_visible) + if self.root_document_visible: + writer.write_lww_bool(3, self.root_document_visible) + if self.paper_size: + writer.write_int_pair(5, self.paper_size) + + +@dataclass +class SceneImageInfoBlock(Block): + BLOCK_TYPE: tp.ClassVar = 0x0E + images: dict[UUID, si.ImageInfo] + + def version_info(self, _) -> tuple[int, int]: + return (3, 3) + + @classmethod + def from_stream(cls, stream: TaggedBlockReader) -> SceneImageInfoBlock: + with stream.read_subblock(1): + images = {} + num_images = stream.data.read_varuint() + for _ in range(num_images): + with stream.read_subblock(0): + uuid = UUID(bytes_le=stream.data.read_bytes(16)) + filename = stream.read_lww_string(1) + flags = stream.read_lww_bytes(2) + images[uuid] = si.ImageInfo(filename=filename, flags=flags) + return SceneImageInfoBlock(images=images) + + def to_stream(self, writer: TaggedBlockWriter): + with writer.write_subblock(1): + writer.data.write_varuint(len(self.images)) + for uuid, image in self.images.items(): + with writer.write_subblock(0): + writer.data.write_bytes(uuid.bytes_le) + writer.write_lww_string(1, image.filename) + writer.write_lww_bytes(2, image.flags) + + +@dataclass +class AuthorIdsBlock(Block): + BLOCK_TYPE: tp.ClassVar = 0x09 + + author_uuids: dict[int, UUID] + + @classmethod + def from_stream(cls, stream: TaggedBlockReader) -> AuthorIdsBlock: + _logger.debug("Reading %s", cls.__name__) + num_subblocks = stream.data.read_varuint() + author_ids = {} + for _ in range(num_subblocks): + with stream.read_subblock(0): + uuid_length = stream.data.read_varuint() + if uuid_length != 16: + raise ValueError("Expected UUID length to be 16 bytes") + uuid = UUID(bytes_le=stream.data.read_bytes(uuid_length)) + author_id = stream.data.read_uint16() + author_ids[author_id] = uuid + return AuthorIdsBlock(author_ids) + + def to_stream(self, writer: TaggedBlockWriter): + _logger.debug("Writing %s", type(self).__name__) + num_subblocks = len(self.author_uuids) + writer.data.write_varuint(num_subblocks) + for author_id, uuid in self.author_uuids.items(): + with writer.write_subblock(0): + writer.data.write_varuint(len(uuid.bytes_le)) + writer.data.write_bytes(uuid.bytes_le) + writer.data.write_uint16(author_id) + + +@dataclass +class MigrationInfoBlock(Block): + BLOCK_TYPE: tp.ClassVar = 0x00 + + migration_id: CrdtId + is_device: bool + _unknown: bool = False + + @classmethod + def from_stream(cls, stream: TaggedBlockReader) -> MigrationInfoBlock: + "Parse migration info" + _logger.debug("Reading %s", cls.__name__) + migration_id = stream.read_id(1) + is_device = stream.read_bool(2) + if stream.bytes_remaining_in_block(): + unknown = stream.read_bool(3) + else: + unknown = False + return MigrationInfoBlock(migration_id, is_device, unknown) + + def to_stream(self, writer: TaggedBlockWriter): + _logger.debug("Writing %s", type(self).__name__) + version = writer.options.get("version", Version("9.9.9")) + writer.write_id(1, self.migration_id) + writer.write_bool(2, self.is_device) + if version >= Version("3.2.2"): + writer.write_bool(3, self._unknown) + + +@dataclass +class TreeNodeBlock(Block): + BLOCK_TYPE: tp.ClassVar = 0x02 + + def version_info(self, writer: TaggedBlockWriter) -> tuple[int, int]: + """Return (min_version, current_version) to use when writing.""" + version = writer.options.get("version", Version("9999")) + # XXX this is a guess about which version this changed in + return (1, 2) if (version >= Version("3.4")) else (1, 1) + + group: si.Group + + @classmethod + def from_stream(cls, stream: TaggedBlockReader) -> TreeNodeBlock: + "Parse tree node block." + _logger.debug("Reading %s", cls.__name__) + + group = si.Group( + node_id=stream.read_id(1), + label=stream.read_lww_string(2), + visible=stream.read_lww_bool(3), + ) + + # XXX this may need to be generalised for other examples + if stream.bytes_remaining_in_block() > 0: + group.anchor_id = stream.read_lww_id(7) + group.anchor_type = stream.read_lww_byte(8) + group.anchor_threshold = stream.read_lww_float(9) + group.anchor_origin_x = stream.read_lww_float(10) + + return cls(group) + + def to_stream(self, writer: TaggedBlockWriter): + _logger.debug("Writing %s", type(self).__name__) + group = self.group + writer.write_id(1, group.node_id) + writer.write_lww_string(2, group.label) + writer.write_lww_bool(3, group.visible) + if group.anchor_id is not None: + # FIXME group together in an anchor type? + assert ( + group.anchor_type is not None + and group.anchor_threshold is not None + and group.anchor_origin_x is not None + ) + writer.write_lww_id(7, group.anchor_id) + writer.write_lww_byte(8, group.anchor_type) + writer.write_lww_float(9, group.anchor_threshold) + writer.write_lww_float(10, group.anchor_origin_x) + + +@dataclass +class PageInfoBlock(Block): + BLOCK_TYPE: tp.ClassVar = 0x0A + + def version_info(self, _) -> tuple[int, int]: + """Return (min_version, current_version) to use when writing.""" + return (0, 1) + + loads_count: int + merges_count: int + text_chars_count: int + text_lines_count: int + type_folio_use_count: int = 0 + + @classmethod + def from_stream(cls, stream: TaggedBlockReader) -> PageInfoBlock: + "Parse page info block" + _logger.debug("Reading %s", cls.__name__) + info = PageInfoBlock( + loads_count=stream.read_int(1), + merges_count=stream.read_int(2), + text_chars_count=stream.read_int(3), + text_lines_count=stream.read_int(4), + ) + if stream.bytes_remaining_in_block(): + info.type_folio_use_count = stream.read_int(5) + return info + + def to_stream(self, writer: TaggedBlockWriter): + _logger.debug("Writing %s", type(self).__name__) + writer.write_int(1, self.loads_count) + writer.write_int(2, self.merges_count) + writer.write_int(3, self.text_chars_count) + writer.write_int(4, self.text_lines_count) + version = writer.options.get("version", Version("9999")) + if version >= Version("3.2.2"): + writer.write_int(5, self.type_folio_use_count) + + +@dataclass +class SceneTreeBlock(Block): + BLOCK_TYPE: tp.ClassVar = 0x01 + + # XXX not sure what the difference is + tree_id: CrdtId + node_id: CrdtId + is_update: bool + parent_id: CrdtId + + @classmethod + def from_stream(cls, stream: TaggedBlockReader) -> SceneTreeBlock: + "Parse scene tree block" + _logger.debug("Reading %s", cls.__name__) + + # XXX not sure what the difference is. This "tree_id" is used as the + # plain "Id" in the SceneTree.NodeMap in ddvk's reader. If the parent_id + # is equal to the root_id (1, 1), this node represents a layer. + tree_id = stream.read_id(1) + node_id = stream.read_id(2) + is_update = stream.read_bool(3) + with stream.read_subblock(4): + parent_id = stream.read_id(1) + # XXX can there sometimes be something else here? + + return SceneTreeBlock(tree_id, node_id, is_update, parent_id) + + def to_stream(self, writer: TaggedBlockWriter): + _logger.debug("Writing %s", type(self).__name__) + writer.write_id(1, self.tree_id) + writer.write_id(2, self.node_id) + writer.write_bool(3, self.is_update) + with writer.write_subblock(4): + writer.write_id(1, self.parent_id) + + +def point_from_stream(stream: TaggedBlockReader, version: int = 2) -> si.Point: + if version not in (1, 2): + raise ValueError("Unknown version %s" % version) + d = stream.data + x = d.read_float32() + y = d.read_float32() + if version == 1: + # calculation based on ddvk's reader + # XXX removed rounding so that can round-trip correctly? + speed = d.read_float32() * 4 + # speed = int(round(d.read_float32() * 4)) + direction = 255 * d.read_float32() / (math.pi * 2) + # direction = int(round(255 * d.read_float32() / (math.pi * 2))) + width = int(round(d.read_float32() * 4)) + pressure = d.read_float32() * 255 + # pressure = int(round(d.read_float32() * 255)) + else: + speed = d.read_uint16() + width = d.read_uint16() + direction = d.read_uint8() + pressure = d.read_uint8() + return si.Point(x, y, speed, direction, width, pressure) + + +def point_serialized_size(version: int = 2) -> int: + if version == 1: + return 0x18 + elif version == 2: + return 0x0E + else: + raise ValueError("Unknown version %s" % version) + + +def point_to_stream(point: si.Point, writer: TaggedBlockWriter, version: int = 2): + if version not in (1, 2): + raise ValueError("Unknown version %s" % version) + d = writer.data + d.write_float32(point.x) + d.write_float32(point.y) + _logger.debug("Writing Point v%d: %s", version, point) + if version == 1: + # calculation based on ddvk's reader + d.write_float32(point.speed / 4) + d.write_float32(point.direction * (2 * math.pi) / 255) + d.write_float32(point.width / 4) + d.write_float32(point.pressure / 255) + else: + d.write_uint16(point.speed) + d.write_uint16(point.width) + d.write_uint8(point.direction) + d.write_uint8(point.pressure) + + +def line_from_stream(stream: TaggedBlockReader, version: int = 2) -> si.Line: + _logger.debug("Reading Line version %d", version) + tool_id = stream.read_int(1) + tool = si.Pen(tool_id) + color_id = stream.read_int(2) + color = si.PenColor(color_id) + thickness_scale = stream.read_double(3) + starting_length = stream.read_float(4) + with stream.read_subblock(5) as block_info: + data_length = block_info.size + point_size = point_serialized_size(version) + if data_length % point_size != 0: + raise ValueError( + "Point data size mismatch: %d is not multiple of point_size" + % data_length + ) + num_points = data_length // point_size + points = [point_from_stream(stream, version=version) for _ in range(num_points)] + + # XXX unused + timestamp = stream.read_id(6) + + if stream.bytes_remaining_in_block() >= 3: + try: + move_id = stream.read_id(7) + except UnexpectedBlockError as _: + move_id = None + else: + move_id = None + + color_rgba = stream.read_color_optional(8) + + return si.Line(color, tool, points, thickness_scale, starting_length, move_id, color_rgba) + + +def line_to_stream(line: si.Line, writer: TaggedBlockWriter, version: int = 2): + _logger.debug("Writing Line version %d", version) + writer.write_int(1, line.tool) + writer.write_int(2, line.color) + writer.write_double(3, line.thickness_scale) + writer.write_float(4, line.starting_length) + with writer.write_subblock(5): + for point in line.points: + point_to_stream(point, writer, version) + + # XXX didn't save + timestamp = CrdtId(0, 1) + writer.write_id(6, timestamp) + if line.move_id is not None: + writer.write_id(7, line.move_id) + if line.color_rgba is not None: + writer.write_color(8, line.color_rgba) + + +@dataclass +class SceneItemBlock(Block): + parent_id: CrdtId + item: CrdtSequenceItem + extra_value_data: bytes = b"" + + ITEM_TYPE: tp.ClassVar[int] = 0 + + @classmethod + def from_stream(cls, stream: TaggedBlockReader) -> SceneItemBlock: + "Group item block?" + _logger.debug("Reading %s", cls.__name__) + + assert stream.current_block + block_type = stream.current_block.block_type + if block_type == SceneGlyphItemBlock.BLOCK_TYPE: + subclass = SceneGlyphItemBlock + elif block_type == SceneGroupItemBlock.BLOCK_TYPE: + subclass = SceneGroupItemBlock + elif block_type == SceneLineItemBlock.BLOCK_TYPE: + subclass = SceneLineItemBlock + elif block_type == SceneTextItemBlock.BLOCK_TYPE: + subclass = SceneTextItemBlock + elif block_type == SceneTombstoneItemBlock.BLOCK_TYPE: + subclass = SceneTombstoneItemBlock + elif block_type == SceneImageItemBlock.BLOCK_TYPE: + subclass = SceneImageItemBlock + else: + raise ValueError( + "unknown scene type %d in %s" % (block_type, stream.current_block) + ) + + parent_id = stream.read_id(1) + item_id = stream.read_id(2) + left_id = stream.read_id(3) + right_id = stream.read_id(4) + deleted_length = stream.read_int(5) + + if stream.has_subblock(6): + with stream.read_subblock(6) as block_info: + item_type = stream.data.read_uint8() + assert item_type == subclass.ITEM_TYPE + value = subclass.value_from_stream(stream) + # Keep known extra data from within the value subblock + extra_value_data = block_info.extra_data + else: + value = None + extra_value_data = b"" + + return subclass( + parent_id, + CrdtSequenceItem(item_id, left_id, right_id, deleted_length, value), + extra_value_data=extra_value_data, + ) + + def to_stream(self, writer: TaggedBlockWriter): + _logger.debug("Writing %s", type(self).__name__) + writer.write_id(1, self.parent_id) + writer.write_id(2, self.item.item_id) + writer.write_id(3, self.item.left_id) + writer.write_id(4, self.item.right_id) + writer.write_int(5, self.item.deleted_length) + + if self.item.value is not None: + with writer.write_subblock(6): + writer.data.write_uint8(self.ITEM_TYPE) + self.value_to_stream(writer, self.item.value) + + writer.data.write_bytes(self.extra_value_data) + + @classmethod + @abstractmethod + def value_from_stream(cls, reader: TaggedBlockReader) -> tp.Any: + """Read the specific content of this block""" + raise NotImplementedError() + + @abstractmethod + def value_to_stream(self, writer: TaggedBlockWriter, value: tp.Any): + """Write the specific content of this block""" + raise NotImplementedError() + + +# These share the same structure so can share the same implementation? + + +def glyph_range_from_stream(stream: TaggedBlockReader) -> si.GlyphRange: + # Since reMarkable version 3.6, the start and length are optional + start = stream.read_int_optional(2) + length = stream.read_int_optional(3) + + color_id = stream.read_int(4) + color = si.PenColor(color_id) + text = stream.read_string(5) + + if length is None: + length = len(text) + + # Note: the decoded text length is not always the same as the length in the + # glyph range... + if len(text) != length: + _logger.debug( + "GlyphRange text length %d != length value %d: %r", + len(text), + length, + text, + ) + + with stream.read_subblock(6): + num_rects = stream.data.read_varuint() + rectangles = [ + si.Rectangle(*[stream.data.read_float64() for _ in range(4)]) + for _ in range(num_rects) + ] + + color_rgba = stream.read_color_optional(10) + + return si.GlyphRange(start, length, text, color, rectangles, color_rgba) + + +def glyph_range_to_stream(stream: TaggedBlockWriter, item: si.GlyphRange): + if item.start is not None: + stream.write_int(2, item.start) + stream.write_int(3, item.length) + stream.write_int(4, item.color) + stream.write_string(5, item.text) + with stream.write_subblock(6): + stream.data.write_varuint(len(item.rectangles)) + for rect in item.rectangles: + stream.data.write_float64(rect.x) + stream.data.write_float64(rect.y) + stream.data.write_float64(rect.w) + stream.data.write_float64(rect.h) + if item.color_rgba is not None: + stream.write_color(10, item.color_rgba) + + +class SceneTombstoneItemBlock(SceneItemBlock): + BLOCK_TYPE: tp.ClassVar = 0x08 + + @classmethod + def value_from_stream(cls, reader: TaggedBlockReader): + pass + + def value_to_stream(self, writer: TaggedBlockWriter, value): + pass + + +class SceneGlyphItemBlock(SceneItemBlock): + BLOCK_TYPE: tp.ClassVar = 0x03 + ITEM_TYPE: tp.ClassVar = 0x01 + + @classmethod + def value_from_stream(cls, reader: TaggedBlockReader) -> si.GlyphRange: + value = glyph_range_from_stream(reader) + return value + + def value_to_stream(self, writer: TaggedBlockWriter, value): + glyph_range_to_stream(writer, value) + + +class SceneGroupItemBlock(SceneItemBlock): + BLOCK_TYPE: tp.ClassVar = 0x04 + ITEM_TYPE: tp.ClassVar = 0x02 + + @classmethod + def value_from_stream(cls, reader: TaggedBlockReader) -> CrdtId: + # XXX don't know what this means + value = reader.read_id(2) + return value + + def value_to_stream(self, writer: TaggedBlockWriter, value: CrdtId): + writer.write_id(2, value) + + +class SceneLineItemBlock(SceneItemBlock): + BLOCK_TYPE: tp.ClassVar = 0x05 + ITEM_TYPE: tp.ClassVar = 0x03 + + def version_info(self, writer: TaggedBlockWriter) -> tuple[int, int]: + """Return (min_version, current_version) to use when writing.""" + version = writer.options.get("version", Version("9999")) + return (2, 2) if (version > Version("3.0")) else (1, 1) + + @classmethod + def value_from_stream(cls, reader: TaggedBlockReader) -> si.Line: + assert reader.current_block is not None + version = reader.current_block.current_version + value = line_from_stream(reader, version) + return value + + def value_to_stream(self, writer: TaggedBlockWriter, value: si.Line): + # XXX make sure this version ends up in block header + version = writer.options.get("version", Version("9999")) + line_version = 2 if (version > Version("3.0")) else 1 + line_to_stream(value, writer, version=line_version) + + +# XXX missing "PathItemBlock"? with ITEM_TYPE 0x04 + + +class SceneImageItemBlock(SceneItemBlock): + BLOCK_TYPE: tp.ClassVar = 0x0F + ITEM_TYPE: tp.ClassVar = 0x07 + + _ints = [0, 1, 2, 2, 3, 0] + + def version_info(self, writer: TaggedBlockWriter) -> tuple[int, int]: + return (2, 2) + + @classmethod + def value_from_stream(cls, reader: TaggedBlockReader) -> si.Image: + uuid = reader.read_lww_bytes(1) + timestamp = reader.read_id(2) + + with reader.read_subblock(3): + length = reader.data.read_varuint() + if length != 16: + raise ValueError("unexpected image vertex length %s" % length) + vertices = [reader.data.read_float32() for _ in range(16)] + + with reader.read_subblock(4): + length = reader.data.read_varuint() + if length != len(cls._ints): + raise ValueError("unexpected image ints length %s" % length) + ints = [reader.data.read_uint32() for _ in range(len(cls._ints))] + if ints != cls._ints: + _logger.debug("image magic ints differ: %s", ints) + + return si.Image(uuid=uuid, vertices=vertices, move_id=timestamp) + + def value_to_stream(self, writer: TaggedBlockWriter, value: si.Image): + writer.write_lww_bytes(1, value.uuid) + writer.write_id(2, value.move_id) + + with writer.write_subblock(3): + writer.data.write_varuint(len(value.vertices)) + for v in value.vertices: + writer.data.write_float32(v) + + with writer.write_subblock(4): + writer.data.write_varuint(len(self._ints)) + for v in self._ints: + writer.data.write_uint32(v) + + +class SceneTextItemBlock(SceneItemBlock): + BLOCK_TYPE: tp.ClassVar = 0x06 + ITEM_TYPE: tp.ClassVar = 0x05 + + @classmethod + def value_from_stream(cls, reader: TaggedBlockReader) -> tp.Any: + return None + + def value_to_stream(self, writer: TaggedBlockWriter, value): + pass + + +def text_item_from_stream(stream: TaggedBlockReader) -> CrdtSequenceItem[str | int]: + with stream.read_subblock(0): + item_id = stream.read_id(2) + left_id = stream.read_id(3) + right_id = stream.read_id(4) + deleted_length = stream.read_int(5) + + if stream.has_subblock(6): + text, fmt = stream.read_string_with_format(6) + # It seems that formats are stored on empty strings, so it's one or the other + if fmt is not None: + if text: + _logger.error( + "Unhandled combined text and format: %s, %s", text, fmt + ) + value = fmt + else: + value = text + else: + value = "" + + return CrdtSequenceItem(item_id, left_id, right_id, deleted_length, value) + + +def text_item_to_stream(item: CrdtSequenceItem[str | int], writer: TaggedBlockWriter): + with writer.write_subblock(0): + writer.write_id(2, item.item_id) + writer.write_id(3, item.left_id) + writer.write_id(4, item.right_id) + writer.write_int(5, item.deleted_length) + + if item.value: + if isinstance(item.value, str): + writer.write_string(6, item.value) + elif isinstance(item.value, int): + writer.write_string_with_format(6, "", item.value) + + +def text_format_from_stream( + stream: TaggedBlockReader, +) -> tuple[CrdtId, LwwValue[si.ParagraphStyle]]: + # These are character ids, but not with an initial tag like other ids have. + char_id = stream.data.read_crdt_id() + + # This seems to be the item ID for this format data? It doesn't appear + # elsewhere in the file. Sometimes coincides with a character id but I don't + # think it is referring to it. + timestamp = stream.read_id(1) + + with stream.read_subblock(2): + # XXX not sure what this is format? + c = stream.data.read_uint8() + assert c == 17 + format_code = stream.data.read_uint8() + try: + format_type = si.ParagraphStyle(format_code) + except ValueError: + _logger.warning("Unrecognised text format code %d.", format_code) + _logger.debug( + "Unrecognised text format code %d at position %d.", + format_code, + stream.data.tell(), + ) + format_type = si.ParagraphStyle.PLAIN # fallback + + return (char_id, LwwValue(timestamp, format_type)) + + +def text_format_to_stream( + char_id: CrdtId, value: LwwValue[si.ParagraphStyle], writer: TaggedBlockWriter +): + format_type = value.value + + writer.data.write_crdt_id(char_id) + writer.write_id(1, value.timestamp) + with writer.write_subblock(2): + # XXX not sure what this is format? + c = 17 + writer.data.write_uint8(c) + writer.data.write_uint8(format_type) + + +@dataclass +class RootTextBlock(Block): + BLOCK_TYPE: tp.ClassVar = 0x07 + + block_id: CrdtId + value: si.Text + + @classmethod + def from_stream(cls, stream: TaggedBlockReader) -> RootTextBlock: + "Parse root text block." + _logger.debug("Reading %s", cls.__name__) + + block_id = stream.read_id(1) + assert block_id == CrdtId(0, 0) + + with stream.read_subblock(2): + + # Text items + with stream.read_subblock(1): + with stream.read_subblock(1): + num_subblocks = stream.data.read_varuint() + text_items = [ + text_item_from_stream(stream) for _ in range(num_subblocks) + ] + + # Formatting + with stream.read_subblock(2): + with stream.read_subblock(1): + num_subblocks = stream.data.read_varuint() + text_formats = dict( + text_format_from_stream(stream) for _ in range(num_subblocks) + ) + + # Last section + with stream.read_subblock(3): + # "pos_x" and "pos_y" from ddvk? Gives negative number -- possibly could + # be bounding box? + pos_x = stream.data.read_float64() + pos_y = stream.data.read_float64() + + # "width" from ddvk + width = stream.read_float(4) + + value = si.Text( + items=CrdtSequence(text_items), + styles=text_formats, + pos_x=pos_x, + pos_y=pos_y, + width=width, + ) + return RootTextBlock(block_id, value) + + def to_stream(self, writer: TaggedBlockWriter): + _logger.debug("Writing %s", type(self).__name__) + writer.write_id(1, self.block_id) + + with writer.write_subblock(2): + + # Text items + text_items = self.value.items.sequence_items() + with writer.write_subblock(1): + with writer.write_subblock(1): + writer.data.write_varuint(len(text_items)) + for item in text_items: + text_item_to_stream(item, writer) + + # Formatting + text_formats = self.value.styles + with writer.write_subblock(2): + with writer.write_subblock(1): + writer.data.write_varuint(len(text_formats)) + for key, item in text_formats.items(): + text_format_to_stream(key, item, writer) + + # Last section + with writer.write_subblock(3): + writer.data.write_float64(self.value.pos_x) + writer.data.write_float64(self.value.pos_y) + + # "width" from ddvk + writer.write_float(4, self.value.width) + + +## Functions to read and write streams of blocks + + +def _read_blocks(stream: TaggedBlockReader) -> Iterator[Block]: + """ + Parse blocks from reMarkable v6 file. + """ + while True: + maybe_block = Block.read(stream) + if maybe_block: + yield maybe_block + else: + # no more blocks + return + + +def read_blocks(data: tp.BinaryIO) -> Iterator[Block]: + """ + Parse reMarkable file and return iterator of document items. + + :param data: reMarkable file data. + """ + stream = TaggedBlockReader(data) + stream.read_header() + yield from _read_blocks(stream) + + +def write_blocks( + data: tp.BinaryIO, blocks: Iterable[Block], options: tp.Optional[dict] = None +): + """ + Write blocks to file. + """ + if options is not None and "version" in options: + options["version"] = Version(options["version"]) + stream = TaggedBlockWriter(data, options=options) + stream.write_header() + for block in blocks: + block.write(stream) + + +def build_tree(tree: SceneTree, blocks: Iterable[Block]): + """Read `blocks` and add contents to `tree`.""" + for b in blocks: + if isinstance(b, SceneTreeBlock): + # XXX check node_id and is_update + # pending_tree_nodes[b.tree_id] = b + tree.add_node(b.tree_id, parent_id=b.parent_id) + elif isinstance(b, TreeNodeBlock): + # Expect this node to already exist; adding information + # if b.node_id not in pending_tree_nodes: + if b.group.node_id not in tree: + raise ValueError( + "Node does not exist for TreeNodeBlock: %s" % b.group.node_id + ) + node = tree[b.group.node_id] + node.label = b.group.label + node.visible = b.group.visible + node.anchor_id = b.group.anchor_id + node.anchor_type = b.group.anchor_type + node.anchor_threshold = b.group.anchor_threshold + node.anchor_origin_x = b.group.anchor_origin_x + elif isinstance(b, SceneGroupItemBlock): + # Add this entry to children of parent_id + node_id = b.item.value + if node_id is None: + continue + if node_id not in tree: + raise ValueError( + "Node does not exist for SceneGroupItemBlock: %s" % node_id + ) + item = replace(b.item, value=tree[node_id]) + tree.add_item(item, b.parent_id) + elif isinstance(b, (SceneLineItemBlock, SceneGlyphItemBlock)): + # Add this entry to children of parent_id + tree.add_item(b.item, b.parent_id) + elif isinstance(b, SceneImageItemBlock): + node = b.item.value + if node is None: + continue + if tree.image_info is not None: + try: + info = tree.image_info.images[UUID(bytes_le=node.uuid.value)] + node.filename = info.filename.value + except Exception as e: + _logger.warning("Could not resolve image filename: %s", e) + tree.add_item(b.item, b.parent_id) + elif isinstance(b, SceneInfo): + tree.scene_info = b + elif isinstance(b, SceneImageInfoBlock): + tree.image_info = b + elif isinstance(b, RootTextBlock): + if tree.root_text is not None: + _logger.error( + "Overwriting root text\n Old: %s\n New: %s", + tree.root_text, + b.value, + ) + tree.root_text = b.value + + pass + + +def read_tree(data: tp.BinaryIO) -> SceneTree: + """ + Parse reMarkable file and return `SceneTree`. + + :param data: reMarkable file data. + """ + tree = SceneTree() + build_tree(tree, read_blocks(data)) + return tree + + +def simple_text_document(text: str, author_uuid=None) -> Iterator[Block]: + """Return the basic blocks to represent `text` as plain text. + + TODO: replace this with a way to generate the tree with given text, and a + function to write a tree to blocks. + + """ + + if author_uuid is None: + author_uuid = uuid4() + + yield AuthorIdsBlock(author_uuids={1: author_uuid}) + + yield MigrationInfoBlock(migration_id=CrdtId(1, 1), is_device=True) + + yield PageInfoBlock( + loads_count=1, + merges_count=0, + text_chars_count=len(text) + 1, + text_lines_count=text.count("\n") + 1, + ) + + yield SceneTreeBlock( + tree_id=CrdtId(0, 11), + node_id=CrdtId(0, 0), + is_update=True, + parent_id=CrdtId(0, 1), + ) + + yield RootTextBlock( + block_id=CrdtId(0, 0), + value=si.Text( + items=CrdtSequence( + [ + CrdtSequenceItem( + item_id=CrdtId(1, 16), + left_id=CrdtId(0, 0), + right_id=CrdtId(0, 0), + deleted_length=0, + value=text, + ) + ] + ), + styles={ + CrdtId(0, 0): LwwValue( + timestamp=CrdtId(1, 15), value=si.ParagraphStyle.PLAIN + ), + }, + pos_x=-468.0, + pos_y=234.0, + width=936.0, + ), + ) + + yield TreeNodeBlock( + si.Group( + node_id=CrdtId(0, 1), + ) + ) + + yield TreeNodeBlock( + si.Group( + node_id=CrdtId(0, 11), + label=LwwValue(timestamp=CrdtId(0, 12), value="Layer 1"), + ) + ) + + yield SceneGroupItemBlock( + parent_id=CrdtId(0, 1), + item=CrdtSequenceItem( + item_id=CrdtId(0, 13), + left_id=CrdtId(0, 0), + right_id=CrdtId(0, 0), + deleted_length=0, + value=CrdtId(0, 11), + ), + ) diff --git a/third_party/rmscene/src/rmscene/scene_tree.py b/third_party/rmscene/src/rmscene/scene_tree.py new file mode 100644 index 00000000..c125b5df --- /dev/null +++ b/third_party/rmscene/src/rmscene/scene_tree.py @@ -0,0 +1,61 @@ +"""Build scene tree structure from block data. + +""" + +from __future__ import annotations + +import logging +import typing as tp + +from .tagged_block_common import CrdtId +from .crdt_sequence import CrdtSequenceItem +from . import scene_items as si + +if tp.TYPE_CHECKING: + from .scene_stream import SceneInfo, SceneImageInfoBlock + +_logger = logging.getLogger(__name__) + + +ROOT_ID = CrdtId(0, 1) + + +class SceneTree: + def __init__(self): + self.root = si.Group(ROOT_ID) + self._node_ids = {self.root.node_id: self.root} + self.scene_info: tp.Optional["SceneInfo"] = None + self.root_text: tp.Optional[si.Text] = None + self.image_info: tp.Optional["SceneImageInfoBlock"] = None + + def __contains__(self, node_id: CrdtId): + return node_id in self._node_ids + + def __getitem__(self, node_id: CrdtId): + return self._node_ids[node_id] + + def add_node(self, node_id: CrdtId, parent_id: CrdtId): + if node_id in self._node_ids: + raise ValueError("Node %s already in tree" % node_id) + node = si.Group(node_id) + self._node_ids[node_id] = node + # parent = self._node_ids[parent_id] + # parent.children.add(item) + + def add_item(self, item: CrdtSequenceItem[si.SceneItem], parent_id: CrdtId): + if parent_id not in self._node_ids: + raise ValueError("Parent id not known: %s" % parent_id) + parent = self._node_ids[parent_id] + parent.children.add(item) + + def walk(self) -> tp.Iterator[si.SceneItem]: + """Iterate through all leaf items (not groups).""" + yield from _walk_items(self.root) + + +def _walk_items(item): + if isinstance(item, si.Group): + for child in item.children.values(): + yield from _walk_items(child) + else: + yield item diff --git a/third_party/rmscene/src/rmscene/tagged_block_common.py b/third_party/rmscene/src/rmscene/tagged_block_common.py new file mode 100644 index 00000000..c106c76d --- /dev/null +++ b/third_party/rmscene/src/rmscene/tagged_block_common.py @@ -0,0 +1,269 @@ +"""Helpers for reading/writing tagged block files. + +""" + +from __future__ import annotations + +from collections.abc import Iterator +from contextlib import contextmanager +from dataclasses import dataclass +from io import BytesIO +import enum +import logging +import struct +import typing as tp + + +_logger = logging.getLogger(__name__) + + +HEADER_V6 = b"reMarkable .lines file, version=6 " + + +class TagType(enum.IntEnum): + "Tag type representing the type of following data." + ID = 0xF + Length4 = 0xC + Byte8 = 0x8 + Byte4 = 0x4 + Byte1 = 0x1 + + +class UnexpectedBlockError(Exception): + """Unexpected tag or index in block stream.""" + + +@dataclass(eq=True, order=True, frozen=True) +class CrdtId: + "An identifier or timestamp." + part1: int + part2: int + + def __repr__(self) -> str: + return f"CrdtId({self.part1}, {self.part2})" + + +class DataStream: + """Read basic values from a remarkable v6 file stream.""" + + def __init__(self, data: tp.BinaryIO): + self.data = data + + def tell(self) -> int: + return self.data.tell() + + def read_header(self) -> None: + """Read the file header. + + This should be the first call when starting to read a new file. + + """ + header = self.read_bytes(len(HEADER_V6)) + if header != HEADER_V6: + raise ValueError("Wrong header: %r" % header) + + def write_header(self) -> None: + """Write the file header. + + This should be the first call when starting to read a new file. + + """ + self.write_bytes(HEADER_V6) + + def check_tag(self, expected_index: int, expected_type: TagType) -> bool: + """Check that INDEX and TAG_TYPE are next. + + Returns True if the expected index and tag type are found. Does not + advance the stream. + + """ + pos = self.data.tell() + try: + index, tag_type = self._read_tag_values() + return (index == expected_index) and (tag_type == expected_type) + except (ValueError, EOFError): + return False + finally: + self.data.seek(pos) # Go back + + def read_tag( + self, expected_index: int, expected_type: TagType + ) -> tuple[int, TagType]: + """Read a tag from the stream. + + Raise an error if the expected index and tag type are not found, and + rewind the stream. + + """ + pos = self.data.tell() + index, tag_type = self._read_tag_values() + + if index != expected_index: + self.data.seek(pos) # Go back + raise UnexpectedBlockError( + "Expected index %d, got %d, at position %d" + % (expected_index, index, self.data.tell()) + ) + + if tag_type != expected_type: + self.data.seek(pos) # Go back + raise UnexpectedBlockError( + "Expected tag type %s (0x%X), got 0x%X at position %d" + % ( + expected_type.name, + expected_type.value, + tag_type, + self.data.tell(), + ) + ) + + return index, tag_type + + def _read_tag_values(self) -> tuple[int, TagType]: + """Read tag values from the stream.""" + + x = self.read_varuint() + + # First part is an index number that identifies if this is the right + # data we're expecting + index = x >> 4 + + # Second part is a tag type that identifies what kind of data it is + tag_type = x & 0xF + try: + tag_type = TagType(tag_type) + except ValueError as e: + raise ValueError( + "Bad tag type 0x%X at position %d" % (tag_type, self.data.tell()) + ) + + return index, tag_type + + def write_tag(self, index: int, tag_type: TagType): + """Write a tag to the stream.""" + x = index << 4 | int(tag_type) + self.write_varuint(x) + + def read_bytes(self, n: int) -> bytes: + "Read `n` bytes, raising `EOFError` if there are not enough." + result = self.data.read(n) + if len(result) != n: + raise EOFError() + return result + + def write_bytes(self, b: bytes): + "Write bytes to underlying stream." + self.data.write(b) + + def _read_struct(self, pattern: str): + pattern = "<" + pattern + n = struct.calcsize(pattern) + return struct.unpack(pattern, self.read_bytes(n))[0] + + def _write_struct(self, pattern: str, value): + pattern = "<" + pattern + self.data.write(struct.pack(pattern, value)) + + def read_bool(self) -> bool: + """Read a bool from the data stream.""" + return self._read_struct("?") + + def read_uint8(self) -> int: + """Read a uint8 from the data stream.""" + return self._read_struct("B") + + def read_uint16(self) -> int: + """Read a uint16 from the data stream.""" + return self._read_struct("H") + + def read_uint32(self) -> int: + """Read a uint32 from the data stream.""" + return self._read_struct("I") + + def read_float32(self) -> float: + """Read a float32 from the data stream.""" + return self._read_struct("f") + + def read_float64(self) -> float: + """Read a float64 (double) from the data stream.""" + return self._read_struct("d") + + def read_varuint(self) -> int: + """Read a varuint from the data stream.""" + shift = 0 + result = 0 + while True: + i = ord(self.read_bytes(1)) + result |= (i & 0x7F) << shift + shift += 7 + if not (i & 0x80): + break + return result + + def read_crdt_id(self) -> CrdtId: + # Based on ddvk's reader.go + # TODO: should be var unit? + part1 = self.read_uint8() + part2 = self.read_varuint() + # result = (part1 << 48) | part2 + return CrdtId(part1, part2) + + def write_bool(self, value: bool): + """Write a bool to the data stream.""" + self._write_struct("?", value) + + def write_uint8(self, value: int): + """Write a uint8 to the data stream.""" + return self._write_struct("B", value) + + def write_uint16(self, value: int): + """Write a uint16 to the data stream.""" + return self._write_struct("H", value) + + def write_uint32(self, value: int): + """Write a uint32 to the data stream.""" + return self._write_struct("I", value) + + def write_float32(self, value: float): + """Write a float32 to the data stream.""" + return self._write_struct("f", value) + + def write_float64(self, value: float): + """Write a float64 (double) to the data stream.""" + return self._write_struct("d", value) + + def write_varuint(self, value: int): + """Write a varuint to the data stream.""" + if value < 0: + raise ValueError("value is negative") + b = bytearray() + while True: + to_write = value & 0x7F + value >>= 7 + if value: + b.append(to_write | 0x80) + else: + b.append(to_write) + break + self.data.write(b) + + def write_crdt_id(self, value: CrdtId): + """Write a `CrdtId` to the data stream.""" + # Based on ddvk's reader.go + # TODO: should be var unit? + if value.part1 >= 2**8 or value.part2 >= 2**64: + raise ValueError("CrdtId too large: %s" % value) + self.write_uint8(value.part1) + self.write_varuint(value.part2) + # result = (part1 << 48) | part2 + + +_T = tp.TypeVar("_T") + +# This makes sense to be frozen, since the value should not be changed without +# updating the timestamp. +@dataclass(eq=True, frozen=True) +class LwwValue(tp.Generic[_T]): + "Container for a last-write-wins value." + timestamp: CrdtId + value: _T diff --git a/third_party/rmscene/src/rmscene/tagged_block_reader.py b/third_party/rmscene/src/rmscene/tagged_block_reader.py new file mode 100644 index 00000000..8927c49a --- /dev/null +++ b/third_party/rmscene/src/rmscene/tagged_block_reader.py @@ -0,0 +1,382 @@ +"""Read structure of remarkable .rm files version 6. + +Based on my investigation of the format with lots of help from ddvk's v6 reader +code. + +""" + +from __future__ import annotations + +from collections.abc import Iterator +from contextlib import contextmanager +from dataclasses import dataclass, KW_ONLY +import logging +import typing as tp + +from .tagged_block_common import ( + DataStream, + TagType, + CrdtId, + UnexpectedBlockError, + LwwValue, +) + + +_logger = logging.getLogger(__name__) + + +@dataclass +class BlockInfo: + "Base class for block/subblock info." + offset: int + size: int + + _: KW_ONLY + extra_data: bytes = b"" + + +@dataclass +class MainBlockInfo(BlockInfo): + "Top-level block info." + block_type: int + min_version: int + current_version: int + + +@dataclass +class SubBlockInfo(BlockInfo): + "Sub-block info." + + +class BlockOverflowError(Exception): + """Read past end of block.""" + + +class TaggedBlockReader: + """Read blocks and values from a remarkable v6 file stream.""" + + def __init__(self, data: tp.BinaryIO): + rm_data = DataStream(data) + self.data = rm_data + self.current_block: tp.Optional[MainBlockInfo] = None + self._warned_about_extra_data = False + + def read_header(self) -> None: + """Read the file header. + + This should be the first call when starting to read a new file. + + """ + self.data.read_header() + + ## Read simple values + + def read_id(self, index: int) -> CrdtId: + """Read a tagged CRDT ID.""" + self.data.read_tag(index, TagType.ID) + result = self.data.read_crdt_id() + return result + + def read_bool(self, index: int) -> bool: + """Read a tagged bool.""" + self.data.read_tag(index, TagType.Byte1) + result = self.data.read_bool() + return result + + def read_byte(self, index: int) -> int: + """Read a tagged byte as an unsigned integer.""" + self.data.read_tag(index, TagType.Byte1) + result = self.data.read_uint8() + return result + + def read_int(self, index: int) -> int: + """Read a tagged 4-byte unsigned integer.""" + self.data.read_tag(index, TagType.Byte4) + # TODO: is this supposed to be signed or unsigned? + result = self.data.read_uint32() + return result + + def read_float(self, index: int) -> float: + """Read a tagged 4-byte float.""" + self.data.read_tag(index, TagType.Byte4) + result = self.data.read_float32() + return result + + def read_double(self, index: int) -> float: + """Read a tagged 8-byte double.""" + self.data.read_tag(index, TagType.Byte8) + result = self.data.read_float64() + return result + + ## Read simple values -- optional variants + + def _read_optional(self, func, index, default): + try: + return func(index) + except (UnexpectedBlockError, EOFError): + return default + + def read_id_optional( + self, index: int, default: tp.Optional[CrdtId] = None + ) -> tp.Optional[CrdtId]: + """Read a tagged CRDT ID, return `default` if not present.""" + return self._read_optional(self.read_id, index, default) + + def read_bool_optional( + self, index: int, default: tp.Optional[bool] = None + ) -> tp.Optional[bool]: + """Read a tagged bool, return `default` if not present.""" + return self._read_optional(self.read_bool, index, default) + + def read_byte_optional( + self, index: int, default: tp.Optional[int] = None + ) -> tp.Optional[int]: + """Read a tagged byte as an unsigned integer, return `default` if not present.""" + return self._read_optional(self.read_byte, index, default) + + def read_int_optional( + self, index: int, default: tp.Optional[int] = None + ) -> tp.Optional[int]: + """Read a tagged 4-byte unsigned integer, return `default` if not present.""" + return self._read_optional(self.read_int, index, default) + + def read_float_optional( + self, index: int, default: tp.Optional[float] = None + ) -> tp.Optional[float]: + """Read a tagged 4-byte float, return `default` if not present.""" + return self._read_optional(self.read_float, index, default) + + def read_double_optional( + self, index: int, default: tp.Optional[float] = None + ) -> tp.Optional[float]: + """Read a tagged 8-byte double, return `default` if not present.""" + return self._read_optional(self.read_double, index, default) + + def read_color_optional( + self, index: int + ) -> tp.Optional[tuple[int, int, int, int]]: + """Read a tagged RGBA color packed as a little-endian uint32 (stored BGRA), return None if not present.""" + if not self.data.check_tag(index, TagType.Byte4): + return None + packed = self.read_int(index) + return ( + (packed >> 16) & 0xFF, + (packed >> 8) & 0xFF, + packed & 0xFF, + (packed >> 24) & 0xFF, + ) + + ## Blocks + + @contextmanager + def read_block(self) -> Iterator[tp.Optional[MainBlockInfo]]: + """Read a top-level block header. + + This acts as a context manager. Upon exiting the with-block, the amount + of data read is checked and an error raised if it has not reached the + end of the block. + + Returns the `BlockInfo` if successfully read. If no block can be read, + None is returned. + + """ + if self.current_block is not None: + raise UnexpectedBlockError("Already in a block") + + try: + block_length = self.data.read_uint32() + except EOFError: + yield None # no more blocks to read + return + + unknown = self.data.read_uint8() + min_version = self.data.read_uint8() + current_version = self.data.read_uint8() + block_type = self.data.read_uint8() + _logger.debug( + "Block header: %d %d %d", min_version, current_version, block_type + ) + assert unknown == 0 + assert current_version >= 0 + assert min_version >= 0 + assert min_version <= current_version + + i0 = self.data.tell() + self.current_block = MainBlockInfo( + offset=i0, + size=block_length, + block_type=block_type, + min_version=min_version, + current_version=current_version, + ) + + yield self.current_block + + assert self.current_block is not None + self._check_position(self.current_block) + self.current_block = None + + def bytes_remaining_in_block(self) -> int: + """Return the number of bytes remaining in the current block.""" + block_info = self.current_block + if block_info is None: + raise ValueError("Not in a block") + return block_info.offset + block_info.size - self.data.tell() + + @contextmanager + def read_subblock(self, index: int) -> Iterator[SubBlockInfo]: + """Read a subblock length and return `SubBlockInfo` as context object. + + Checks that the correct length has been read at the end of the with + block. + """ + self.data.read_tag(index, TagType.Length4) + subblock_length = self.data.read_uint32() + i0 = self.data.tell() + + subblock = SubBlockInfo(i0, subblock_length) + yield subblock + + self._check_position(subblock) + + def has_subblock(self, index: int) -> bool: + """Check if a subblock with the given index is next.""" + # It's possible that if we are at the end of the block, the next bytes + # (the size of the next block) could happen to match the tag and index + # of what we are looking for -- so check explicitly for end of block. + if self.current_block: + if self.bytes_remaining_in_block() <= 0: + return False + return self.data.check_tag(index, TagType.Length4) + + def _check_position(self, block_info: BlockInfo): + length = block_info.size + i0 = block_info.offset + i1 = self.data.tell() + if i1 > i0 + length: + raise BlockOverflowError( + "%s starting at %d, length %d, read up to %d (overflow by %d)" + % (type(block_info), i0, length, i1, i1 - (i0 + length)) + ) + if i1 < i0 + length: + if not self._warned_about_extra_data: + _logger.warning( + "Some data has not been read. The data may have been written using " + "a newer format than this reader supports." + ) + self._warned_about_extra_data = True + _logger.info("In %s only read %d bytes", block_info, i1 - i0) + # Discard the rest + remaining = i0 + length - i1 + excess = self.data.read_bytes(remaining) + block_info.extra_data = excess + _logger.debug( + "Excess bytes:\n %s", + "\n".join(excess[i : i + 32].hex() for i in range(0, len(excess), 32)), + stack_info=True, + stacklevel=4, + ) + + ## Higher level constructs + + def read_lww_bool(self, index: int) -> LwwValue[bool]: + "Read a LWW bool." + with self.read_subblock(index): + timestamp = self.read_id(1) + value = self.read_bool(2) + return LwwValue(timestamp, value) + + def read_lww_byte(self, index: int) -> LwwValue[int]: + "Read a LWW byte." + with self.read_subblock(index): + timestamp = self.read_id(1) + value = self.read_byte(2) + return LwwValue(timestamp, value) + + def read_lww_float(self, index: int) -> LwwValue[float]: + "Read a LWW float." + with self.read_subblock(index): + timestamp = self.read_id(1) + value = self.read_float(2) + return LwwValue(timestamp, value) + + def read_lww_id(self, index: int) -> LwwValue[CrdtId]: + "Read a LWW ID." + with self.read_subblock(index): + # XXX ddvk has these the other way round? + timestamp = self.read_id(1) + value = self.read_id(2) + return LwwValue(timestamp, value) + + def read_lww_bytes(self, index: int) -> LwwValue[bytes]: + "Read a LWW bytes value." + with self.read_subblock(index): + timestamp = self.read_id(1) + data = self.read_bytes(2) + return LwwValue(timestamp, data) + + def read_lww_string(self, index: int) -> LwwValue[str]: + "Read a LWW string." + with self.read_subblock(index): + timestamp = self.read_id(1) + string = self.read_string(2) + return LwwValue(timestamp, string) + + def read_bytes(self, index: int) -> bytes: + """Read a standard bytes block.""" + with self.read_subblock(index) as block_info: + return self.data.read_bytes(block_info.size) + + def read_string(self, index: int) -> str: + """Read a standard string block.""" + with self.read_subblock(index) as block_info: + string_length = self.data.read_varuint() + # XXX not sure if this is right meaning? + is_ascii = self.data.read_bool() + assert is_ascii == 1 + assert string_length + 2 <= block_info.size + b = self.data.read_bytes(string_length) + string = b.decode() + if len(b) != len(string): + _logger.debug( + "read_string: decoded %r (%d) to %r (%d)", + b, + len(b), + string, + len(string), + ) + return string + + def read_string_with_format(self, index: int) -> tuple[str, tp.Optional[int]]: + """Read a string block with formatting.""" + with self.read_subblock(index) as block_info: + string_length = self.data.read_varuint() + # XXX not sure if this is right meaning? + is_ascii = self.data.read_bool() + assert is_ascii == 1 + assert string_length + 2 <= block_info.size + b = self.data.read_bytes(string_length) + string = b.decode() + if len(b) != len(string): + _logger.debug( + "read_string: decoded %r (%d) to %r (%d)", + b, + len(b), + string, + len(string), + ) + + if self.data.check_tag(2, TagType.Byte4): + # We have a format code + fmt = self.read_int(2) + else: + fmt = None + + return string, fmt + + def read_int_pair(self, index: int) -> tp.Optional[tuple[int, int]]: + """Read a sub block containing two uint32""" + with self.read_subblock(index): + first = self.data.read_uint32() + second = self.data.read_uint32() + return first, second diff --git a/third_party/rmscene/src/rmscene/tagged_block_writer.py b/third_party/rmscene/src/rmscene/tagged_block_writer.py new file mode 100644 index 00000000..df8134b8 --- /dev/null +++ b/third_party/rmscene/src/rmscene/tagged_block_writer.py @@ -0,0 +1,210 @@ +"""Read structure of remarkable .rm files version 6. + +Based on my investigation of the format with lots of help from ddvk's v6 reader +code. + +""" + +from __future__ import annotations + +from collections.abc import Iterator +from contextlib import contextmanager +from io import BytesIO +import logging +import typing as tp + +from .tagged_block_common import ( + TagType, + DataStream, + CrdtId, + LwwValue, + UnexpectedBlockError, +) + + +_logger = logging.getLogger(__name__) + + +class TaggedBlockWriter: + """Write blocks and values to a remarkable v6 file stream.""" + + def __init__(self, data: tp.BinaryIO, options: tp.Optional[dict] = None): + if options is None: + options = {} + self.options = options + rm_data = DataStream(data) + self.data = rm_data + self._in_block: bool = False + + def write_header(self) -> None: + """Write the file header. + + This should be the first call when starting to write a new file. + + """ + self.data.write_header() + + ## Write simple values + + def write_id(self, index: int, value: CrdtId): + """Write a tagged CRDT ID.""" + self.data.write_tag(index, TagType.ID) + self.data.write_crdt_id(value) + + def write_bool(self, index: int, value: bool): + """Write a tagged bool.""" + self.data.write_tag(index, TagType.Byte1) + self.data.write_bool(value) + + def write_byte(self, index: int, value: int): + """Write a tagged byte as an unsigned integer.""" + self.data.write_tag(index, TagType.Byte1) + self.data.write_uint8(value) + + def write_int(self, index: int, value: int): + """Write a tagged 4-byte unsigned integer.""" + self.data.write_tag(index, TagType.Byte4) + # TODO: is this supposed to be signed or unsigned? + self.data.write_uint32(value) + + def write_float(self, index: int, value: float): + """Write a tagged 4-byte float.""" + self.data.write_tag(index, TagType.Byte4) + self.data.write_float32(value) + + def write_double(self, index: int, value: float): + """Write a tagged 8-byte double.""" + self.data.write_tag(index, TagType.Byte8) + self.data.write_float64(value) + + def write_color(self, index: int, value: tuple[int, int, int, int]): + """Write a tagged RGBA color packed as a little-endian uint32 (stored BGRA).""" + r, g, b, a = value + self.write_int(index, b | (g << 8) | (r << 16) | (a << 24)) + + ## Blocks + + @contextmanager + def write_block( + self, block_type: int, min_version: int, current_version: int + ) -> Iterator[None]: + """Write a top-level block header. + + Within this block, other writes are accumulated, so that the + whole block can be written out with its length at the end. + + """ + if self._in_block: + raise UnexpectedBlockError("Already in a block") + + previous_data = self.data + block_buf = BytesIO() + block_data = DataStream(block_buf) + try: + self.data = block_data + self._in_block = True + yield + finally: + self.data = previous_data + + assert self._in_block + self._in_block = False + + self.data.write_uint32(len(block_buf.getbuffer())) + self.data.write_uint8(0) + self.data.write_uint8(min_version) + self.data.write_uint8(current_version) + self.data.write_uint8(block_type) + self.data.write_bytes(block_buf.getbuffer()) + + @contextmanager + def write_subblock(self, index: int) -> Iterator[None]: + """Write a subblock tag and length once the with-block has exited. + + Within this block, other writes are accumulated, so that the + whole block can be written out with its length at the end. + """ + previous_data = self.data + subblock_buf = BytesIO() + subblock_data = DataStream(subblock_buf) + try: + self.data = subblock_data + yield + finally: + self.data = previous_data + + self.data.write_tag(index, TagType.Length4) + self.data.write_uint32(len(subblock_buf.getbuffer())) + self.data.write_bytes(subblock_buf.getbuffer()) + _logger.debug("Wrote subblock %d: %s", index, subblock_buf.getvalue().hex()) + + ## Higher level constructs + + def write_lww_bool(self, index: int, value: LwwValue[bool]): + "Write a LWW bool." + with self.write_subblock(index): + self.write_id(1, value.timestamp) + self.write_bool(2, value.value) + + def write_lww_byte(self, index: int, value: LwwValue[int]): + "Write a LWW byte." + with self.write_subblock(index): + self.write_id(1, value.timestamp) + self.write_byte(2, value.value) + + def write_lww_float(self, index: int, value: LwwValue[float]): + "Write a LWW float." + with self.write_subblock(index): + self.write_id(1, value.timestamp) + self.write_float(2, value.value) + + def write_lww_id(self, index: int, value: LwwValue[CrdtId]): + "Write a LWW ID." + with self.write_subblock(index): + # XXX ddvk has these the other way round? + self.write_id(1, value.timestamp) + self.write_id(2, value.value) + + def write_lww_bytes(self, index: int, value: LwwValue[bytes]): + "Write a LWW bytes value." + with self.write_subblock(index): + self.write_id(1, value.timestamp) + self.write_bytes(2, value.value) + + def write_lww_string(self, index: int, value: LwwValue[str]): + "Write a LWW string." + with self.write_subblock(index): + self.write_id(1, value.timestamp) + self.write_string(2, value.value) + + def write_bytes(self, index: int, value: bytes): + """Write a standard bytes block.""" + with self.write_subblock(index): + self.data.write_bytes(value) + + def write_string(self, index: int, value: str): + """Write a standard string block.""" + with self.write_subblock(index): + b = value.encode() + bytes_length = len(b) + is_ascii = True # XXX not sure if this is right meaning? + self.data.write_varuint(bytes_length) + self.data.write_bool(is_ascii) + self.data.write_bytes(b) + + def write_string_with_format(self, index: int, text: str, fmt: int): + """Write a string block with formatting.""" + with self.write_subblock(index): + b = text.encode() + bytes_length = len(b) + is_ascii = True # XXX not sure if this is right meaning? + self.data.write_varuint(bytes_length) + self.data.write_bool(is_ascii) + self.data.write_bytes(b) + self.write_int(2, fmt) + + def write_int_pair(self, index: int, value: tuple[int, int]): + """Read a sub block containing two uint32""" + with self.write_subblock(index): + self.data.write_uint32(value[0]) + self.data.write_uint32(value[1]) diff --git a/third_party/rmscene/src/rmscene/text.py b/third_party/rmscene/src/rmscene/text.py new file mode 100644 index 00000000..4ee2984a --- /dev/null +++ b/third_party/rmscene/src/rmscene/text.py @@ -0,0 +1,168 @@ +"""Process text from remarkable scene files. + +""" + +from __future__ import annotations + +from collections.abc import Iterable +from collections import defaultdict +from dataclasses import dataclass, field +import logging +import typing as tp + +from . import scene_items as si +from .tagged_block_common import CrdtId, LwwValue +from .crdt_sequence import CrdtSequence, CrdtSequenceItem + +_logger = logging.getLogger(__name__) + + +def expand_text_item( + item: CrdtSequenceItem[str | int], +) -> tp.Iterator[CrdtSequenceItem[str | int]]: + """Expand TextItem into single-character TextItems. + + Text is stored as strings in TextItems, each with an associated ID for the + block. This ID identifies the character at the start of the block. The + subsequent characters' IDs are implicit. + + This function expands a TextItem into multiple single-character TextItems, + so that each character has an explicit ID. + + """ + + if item.deleted_length > 0: + assert item.value == "" + chars = [""] * item.deleted_length + deleted_length = 1 + elif isinstance(item.value, int): + yield item + return + else: + # Actually the value can be empty + # assert len(item.value) > 0 + chars = item.value + deleted_length = 0 + + if not chars: + _logger.warning("Unexpected empty text item: %s", item) + return + + item_id = item.item_id + left_id = item.left_id + for c in chars[:-1]: + right_id = CrdtId(item_id.part1, item_id.part2 + 1) + yield CrdtSequenceItem(item_id, left_id, right_id, deleted_length, c) + left_id = item_id + item_id = right_id + yield CrdtSequenceItem(item_id, left_id, item.right_id, deleted_length, chars[-1]) + + +def expand_text_items( + items: Iterable[CrdtSequenceItem[str | int]], +) -> tp.Iterator[CrdtSequenceItem[str | int]]: + """Expand a sequence of TextItems into single-character TextItems.""" + for item in items: + yield from expand_text_item(item) + + +@dataclass +class CrdtStr: + """String with CrdtIds for chars and optional properties. + + The properties apply to the whole `CrdtStr`. Use a list of + `CrdtStr`s to represent a sequence of spans of text with different + properties. + + """ + + s: str = "" + i: list[CrdtId] = field(default_factory=list) + properties: dict = field(default_factory=dict) + + def __str__(self): + return self.s + + +@dataclass +class Paragraph: + """Paragraph of text.""" + + contents: list[CrdtStr] + start_id: CrdtId + style: LwwValue[si.ParagraphStyle] = field( + default_factory=lambda: LwwValue(CrdtId(0, 0), si.ParagraphStyle.PLAIN) + ) + + def __str__(self): + return "".join(str(s) for s in self.contents) + + +@dataclass +class TextDocument: + contents: list[Paragraph] + + @classmethod + def from_scene_item(cls, text: si.Text): + """Extract spans of text with associated formatting and char ids. + + This uses the inline formatting introduced in v3.3.2. + """ + + char_formats = {k: lww.value for k, lww in text.styles.items()} + if si.END_MARKER not in char_formats: + char_formats[si.END_MARKER] = si.ParagraphStyle.PLAIN + + # Expand from strings to characters + char_items = CrdtSequence(expand_text_items(text.items.sequence_items())) + keys = list(char_items) + properties = {"font-weight": "normal", "font-style": "normal"} + + def handle_formatting_code(code): + if code == 1: + properties["font-weight"] = "bold" + elif code == 2: + properties["font-weight"] = "normal" + if code == 3: + properties["font-style"] = "italic" + elif code == 4: + properties["font-style"] = "normal" + else: + _logger.warning("Unknown formatting code in text: %d", code) + return properties + + def parse_paragraph_contents(): + if keys and char_items[keys[0]] == "\n": + start_id = keys.pop(0) + else: + start_id = si.END_MARKER + contents = [] + while keys: + char = char_items[keys[0]] + if isinstance(char, int): + handle_formatting_code(char) + elif char == "\n": + # End of paragraph + break + else: + assert len(char) <= 1 + # Start a new string if text properties have changed + if not contents or contents[-1].properties != properties: + contents += [CrdtStr(properties=properties.copy())] + contents[-1].s += char + contents[-1].i += [keys[0]] + keys.pop(0) + + return start_id, contents + + paragraphs = [] + while keys: + start_id, contents = parse_paragraph_contents() + if start_id in text.styles: + p = Paragraph(contents, start_id, text.styles[start_id]) + else: + p = Paragraph(contents, start_id) + paragraphs += [p] + + doc = cls(paragraphs) + return doc diff --git a/third_party/rmscene/tests/test_basic_data_stream.py b/third_party/rmscene/tests/test_basic_data_stream.py new file mode 100644 index 00000000..34555dec --- /dev/null +++ b/third_party/rmscene/tests/test_basic_data_stream.py @@ -0,0 +1,39 @@ +import pytest +from io import BytesIO +from rmscene.tagged_block_common import ( + DataStream +) + + +@pytest.mark.parametrize( + "value,hexstr", + [ + (0, "00"), + (3, "03"), + ], +) +def test_write_uint8(value, hexstr): + buf = BytesIO() + s = DataStream(buf) + s.write_uint8(value) + assert buf.getvalue().hex() == hexstr + + +@pytest.mark.parametrize( + "value,hexstr", + [ + (0x00, "00"), + (0x03, "03"), + (0x7f, "7f"), + (0x8c, "8c01"), + (0x9c, "9c01"), + (0x3fff, "ff7f"), + ], +) +def test_write_varuint(value, hexstr): + buf = BytesIO() + s = DataStream(buf) + s.write_varuint(value) + assert buf.getvalue().hex() == hexstr + buf.seek(0) + assert s.read_varuint() == value diff --git a/third_party/rmscene/tests/test_color_tool.py b/third_party/rmscene/tests/test_color_tool.py new file mode 100644 index 00000000..864493f0 --- /dev/null +++ b/third_party/rmscene/tests/test_color_tool.py @@ -0,0 +1,43 @@ +import logging +import os +from pathlib import Path + +import pytest + +from rmscene import SceneGlyphItemBlock, SceneLineItemBlock, read_blocks +from rmscene.scene_items import Pen, PenColor + +logger = logging.getLogger(__name__) + + +DATA_PATH = Path(__file__).parent / "data" + + +def _hex_lines(b, n=32): + return [b[i * n : (i + 1) * n].hex() for i in range(len(b) // n + 1)] + + +FILE_NAME = os.path.join(DATA_PATH, "Color_and_tool_v3.14.4.rm") + + +@pytest.mark.parametrize( + "block_type,colors,tools", + [ + (SceneGlyphItemBlock, {PenColor.HIGHLIGHT}, None), + (SceneLineItemBlock, {PenColor.HIGHLIGHT}, {Pen.SHADER}), + (SceneLineItemBlock, {PenColor.GREEN_2, PenColor.CYAN, PenColor.MAGENTA}, {Pen.BALLPOINT_2}), + ], +) +def test_color_tool_parsing(block_type, colors, tools): + + with open(FILE_NAME, "rb") as f: + result = read_blocks(f) + for el in result: + if not getattr(el, "item", None): + continue + if not getattr(el.item, "value", None): + continue + if isinstance(el, block_type) and el.item.value.color in colors: + if tools is None: + continue + assert el.item.value.tool in tools, "Tool and colors don't match" \ No newline at end of file diff --git a/third_party/rmscene/tests/test_crdt_sequence.py b/third_party/rmscene/tests/test_crdt_sequence.py new file mode 100644 index 00000000..e1b2566d --- /dev/null +++ b/third_party/rmscene/tests/test_crdt_sequence.py @@ -0,0 +1,174 @@ +from rmscene.crdt_sequence import CrdtSequenceItem, CrdtSequence +from rmscene import CrdtId + + +def cid(k): + "Shorthand for making end-markers or IDs with author-id = 1." + return CrdtId(0 if k == 0 else 1, k) + + +def make_item(item_id, left_id, right_id, *args): + "Shorthand for creating ids." + return CrdtSequenceItem(cid(item_id), cid(left_id), cid(right_id), *args) + + +def test_empty(): + assert list(CrdtSequence([])) == [] + + +def test_just_one(): + items = [ + make_item(1, 0, 0, 0, "A"), + ] + result = list(CrdtSequence(items)) + assert result == [cid(1)] + + +def test_two(): + items = [ + make_item(1, 0, 0, 0, "A"), + make_item(2, 1, 0, 0, "B"), + ] + result1 = list(CrdtSequence(items)) + result2 = list(CrdtSequence(reversed(items))) + assert result1 == result2 + + +def test_overlapping(): + # Test concurrent-insert: two different authors insert at the same position + # (identical left_id and right_id) without knowledge of each other. The + # higher author ID should come first, matching observed reMarkable device + # behaviour (verified with test-crdt-ordering.rm: "A12_Z" not "A_12Z"). + A = CrdtSequenceItem(CrdtId(1, 1), CrdtId(0, 0), CrdtId(0, 0), 0, "A") + Z = CrdtSequenceItem(CrdtId(1, 2), CrdtId(1, 1), CrdtId(0, 0), 0, "Z") + author2 = CrdtSequenceItem(CrdtId(2, 1), CrdtId(1, 1), CrdtId(1, 2), 0, "12") + author1 = CrdtSequenceItem(CrdtId(1, 3), CrdtId(1, 1), CrdtId(1, 2), 0, "_") + items = [A, Z, author2, author1] + seq = CrdtSequence(items) + result1 = list(seq) + result2 = list(CrdtSequence(reversed(items))) + assert result1 == result2 + assert result1 == [CrdtId(1, 1), CrdtId(2, 1), CrdtId(1, 3), CrdtId(1, 2)] + assert "".join(seq.values()) == "A12_Z" + + +def test_overlapping_sorted_by_id(): + items = [ + make_item(8, 0, 0, 0, "A"), + make_item(9, 8, 0, 0, "B"), + make_item(3, 0, 0, 0, "C"), + ] + result1 = list(CrdtSequence(items)) + result2 = list(CrdtSequence(reversed(items))) + assert result1 == result2 + assert result1 == [cid(3), cid(8), cid(9)] + + +def test_unknown_id(): + items = [ + make_item(28, 0, 15, 0, "A"), + make_item(31, 30, 15, 2, ""), + make_item(33, 32, 15, 0, "B"), + make_item(15, 0, 0, 0, "C"), + ] + result1 = list(CrdtSequence(items)) + result2 = list(CrdtSequence(reversed(items))) + assert result1 == result2 + assert result1 == [cid(28), cid(31), cid(33), cid(15)] + + +def test_unknown_id_at_right(): + items = [ + make_item(14, 0, 0, 0, "A"), + make_item(19, 14, 15, 0, "V"), + # item 15 is not defined -- this shouldn't happen, as there should be a + # tombstone, but don't want to raise errors in this case + ] + result = list(CrdtSequence(items)) + assert result == [cid(14), cid(19)] + + +def test_iterates_in_order(): + # Order should be "AB" + items = [ + make_item(1, 0, 0, 0, "A"), + make_item(2, 1, 0, 0, "B"), + ] + + for test_items in (items, reversed(items)): + seq = CrdtSequence(test_items) + assert list(seq.keys()) == [cid(1), cid(2)] + assert list(seq.values()) == ["A", "B"] + assert list(seq.items()) == list(zip(seq.keys(), seq.values())) + + +from hypothesis import given, note, strategies as st +from hypothesis.stateful import Bundle, RuleBasedStateMachine, rule, precondition, invariant + + +class CrdtSequenceComparison(RuleBasedStateMachine): + """State machine that adds and deletes text in the sequence""" + def __init__(self): + super().__init__() + # All items, even deleted ones + self.items: dict[CrdtId, CrdtSequenceItem] = {} + # List of items corresponding to string + self.string_items: list[CrdtSequenceItem] = [] + self.string = "" + self.last_id = 1 + + # keys = Bundle("keys") + # values = Bundle("values") + + # @rule(target=keys, k=st.binary()) + # def add_key(self, k): + # return k + + @rule(data=st.data(), c=st.characters()) + def add_char(self, data, c): + i = data.draw(st.integers(min_value=0, max_value=len(self.string))) + new_item = CrdtSequenceItem( + item_id=cid(self.last_id), + left_id=self.string_items[i-1].item_id if i >= 1 else cid(0), + right_id=self.string_items[i].item_id if i < len(self.string_items) else cid(0), + deleted_length=0, + value=c + ) + note(f"new_item: {new_item}") + self.last_id += 1 + self.string = self.string[:i] + c + self.string[i:] + self.string_items = self.string_items[:i] + [new_item] + self.string_items[i:] + self.items[new_item.item_id] = new_item + + @rule(data=st.data()) + def add_empty_item(self, data): + i = data.draw(st.integers(min_value=0, max_value=len(self.string))) + new_item = CrdtSequenceItem( + item_id=cid(self.last_id), + left_id=self.string_items[i-1].item_id if i >= 1 else cid(0), + right_id=self.string_items[i].item_id if i < len(self.string_items) else cid(0), + deleted_length=0, + value="" + ) + note(f"new_item: {new_item}") + self.last_id += 1 + self.items[new_item.item_id] = new_item + + @precondition(lambda self: len(self.string) > 0) + @rule(data=st.data()) + def delete_char(self, data): + i = data.draw(st.integers(min_value=0, max_value=len(self.string) - 1)) + item_id = self.string_items[i].item_id + note(f"deleting_item: {item_id}") + self.string = self.string[:i] + self.string[i+1:] + self.string_items = self.string_items[:i] + self.string_items[i+1:] + self.items[item_id].value = "" + self.items[item_id].deleted_length = 1 + + @invariant() + def values_agree(self): + seq = CrdtSequence(self.items.values()) + assert "".join(seq.values()) == self.string + + +TestCrdtSequenceComparison = CrdtSequenceComparison.TestCase diff --git a/third_party/rmscene/tests/test_scene_stream.py b/third_party/rmscene/tests/test_scene_stream.py new file mode 100644 index 00000000..0db3f6b6 --- /dev/null +++ b/third_party/rmscene/tests/test_scene_stream.py @@ -0,0 +1,419 @@ +import pytest +from io import BytesIO +from pathlib import Path +from uuid import UUID +from rmscene import ( + read_blocks, + write_blocks, + LwwValue, + TaggedBlockWriter, + TaggedBlockReader, +) +from rmscene.scene_stream import * +from rmscene.tagged_block_common import HEADER_V6 +from rmscene.tagged_block_reader import MainBlockInfo +from rmscene.crdt_sequence import CrdtSequenceItem +from rmscene.scene_items import ParagraphStyle + +import logging + +logger = logging.getLogger(__name__) + + +DATA_PATH = Path(__file__).parent / "data" + + +def _hex_lines(b, n=32): + return [b[i * n : (i + 1) * n].hex() for i in range(len(b) // n + 1)] + + +LINES_V2_FILES = [ + "Lines_v2.rm", + "Wikipedia_highlighted_p2.rm", +] + + +TEST_FILES_AND_VERSIONS = [ + ("Normal_AB.rm", "3.0"), + ("Normal_A_stroke_2_layers.rm", "3.0"), + ("Normal_A_stroke_2_layers_v3.2.2.rm", "3.2.2"), + ("Normal_A_stroke_2_layers_v3.3.2.rm", "3.3.2"), + ("Bold_Heading_Bullet_Normal.rm", "3.0"), + ("Lines_v2.rm", "3.1"), + ("Lines_v2_updated.rm", "3.2"), # extra 7fXXXX part of Line data was added + ("Wikipedia_highlighted_p1.rm", "3.1"), + ("Wikipedia_highlighted_p2.rm", "3.1"), + ("With_SceneInfo_Block.rm", "3.4"), # XXX version? + ("Color_and_tool_v3.14.4.rm", "3.14"), + ("More_color_highlight_shader_v3.15.4.2.rm", "3.15"), +] + + +@pytest.mark.parametrize("test_file,version", TEST_FILES_AND_VERSIONS) +def test_full_roundtrip(test_file, version): + with open(DATA_PATH / test_file, "rb") as f: + data = f.read() + + # XXX not sure why this is a problem -- reMarkable seems to be inconsistent + # about the min version written to line block headers? + if version in ("3.2.2", "3.3.2"): + # This is not a very good way of doing it... + data = data.replace(bytes.fromhex("010205"), bytes.fromhex("020205")) + + input_buf = BytesIO(data) + output_buf = BytesIO() + options = {"version": version} + + write_blocks(output_buf, read_blocks(input_buf), options) + + assert _hex_lines(input_buf.getvalue()) == _hex_lines(output_buf.getvalue()) + + +# Temporarily add test files here that add new data fields before updating the +# parsing code properly. +FULL_PARSING_XFAILS = [] + +TEST_FILES_FOR_FULL_PARSING = [ + pytest.param( + filename, + marks=pytest.mark.xfail if filename in FULL_PARSING_XFAILS else [], + ) + for filename, _ in TEST_FILES_AND_VERSIONS +] + + +@pytest.mark.parametrize("test_file", TEST_FILES_FOR_FULL_PARSING) +def test_files_fully_parsed(test_file): + with open(DATA_PATH / test_file, "rb") as f: + result = list(read_blocks(f)) + + # Check none of the blocks were unreadable and do not have extra data + for block in result: + assert not isinstance(block, UnreadableBlock) + assert not block.extra_data + if isinstance(block, SceneItemBlock): + assert not block.extra_value_data + + +def test_normal_ab(): + with open(DATA_PATH / "Normal_AB.rm", "rb") as f: + result = list(read_blocks(f)) + + assert result == [ + AuthorIdsBlock(author_uuids={1: UUID("495ba59f-c943-2b5c-b455-3682f6948906")}), + MigrationInfoBlock(migration_id=CrdtId(1, 1), is_device=True), + PageInfoBlock( + loads_count=1, merges_count=0, text_chars_count=3, text_lines_count=1 + ), + SceneTreeBlock( + tree_id=CrdtId(0, 11), + node_id=CrdtId(0, 0), + is_update=True, + parent_id=CrdtId(0, 1), + ), + RootTextBlock( + block_id=CrdtId(0, 0), + value=si.Text( + items=CrdtSequence( + [ + CrdtSequenceItem( + item_id=CrdtId(1, 16), + left_id=CrdtId(0, 0), + right_id=CrdtId(0, 0), + deleted_length=0, + value="AB", + ) + ] + ), + styles={ + CrdtId(0, 0): LwwValue( + timestamp=CrdtId(1, 15), value=si.ParagraphStyle.PLAIN + ), + }, + pos_x=-468.0, + pos_y=234.0, + width=936.0, + ), + ), + TreeNodeBlock( + group=si.Group(node_id=CrdtId(0, 1)), + ), + TreeNodeBlock( + group=si.Group( + node_id=CrdtId(0, 11), + label=LwwValue(CrdtId(0, 12), "Layer 1"), + ), + ), + SceneGroupItemBlock( + parent_id=CrdtId(0, 1), + item=CrdtSequenceItem( + item_id=CrdtId(0, 13), + left_id=CrdtId(0, 0), + right_id=CrdtId(0, 0), + deleted_length=0, + value=CrdtId(0, 11), + ), + ), + ] + + +def test_read_glyph_range(): + with open(DATA_PATH / "Wikipedia_highlighted_p1.rm", "rb") as f: + result = [ + block for block in read_blocks(f) if isinstance(block, SceneGlyphItemBlock) + ] + + assert result[0].item.value.text == "The reMarkable uses electronic paper" + + +@pytest.mark.parametrize( + "block", + [ + AuthorIdsBlock(author_uuids={1: UUID("495ba59f-c943-2b5c-b455-3682f6948906")}), + AuthorIdsBlock( + author_uuids={ + 1: UUID("495ba59f-c943-2b5c-b455-3682f6948906"), + 2: UUID("cd83324a-917f-11ed-bb7b-3c0754484e34"), + } + ), + MigrationInfoBlock(migration_id=CrdtId(1, 1), is_device=True), + PageInfoBlock( + loads_count=3, merges_count=2, text_chars_count=3, text_lines_count=1 + ), + SceneTreeBlock( + tree_id=CrdtId(0, 11), + node_id=CrdtId(0, 0), + is_update=True, + parent_id=CrdtId(0, 1), + ), + RootTextBlock( + block_id=CrdtId(0, 0), + value=si.Text( + items=CrdtSequence( + [ + CrdtSequenceItem( + item_id=CrdtId(1, 16), + left_id=CrdtId(0, 0), + right_id=CrdtId(0, 0), + deleted_length=0, + value="AB", + ) + ] + ), + styles={ + CrdtId(0, 0): LwwValue( + timestamp=CrdtId(1, 15), value=si.ParagraphStyle.PLAIN + ), + }, + pos_x=-468.0, + pos_y=234.0, + width=936.0, + ), + ), + TreeNodeBlock( + group=si.Group( + node_id=CrdtId(0, 11), + label=LwwValue(CrdtId(0, 12), "Layer 1"), + ), + ), + SceneGroupItemBlock( + parent_id=CrdtId(0, 1), + item=CrdtSequenceItem( + item_id=CrdtId(0, 13), + left_id=CrdtId(0, 0), + right_id=CrdtId(0, 0), + deleted_length=0, + value=CrdtId(0, 11), + ), + ), + SceneGlyphItemBlock( + parent_id=CrdtId(0, 11), + item=CrdtSequenceItem( + item_id=CrdtId(1, 17), + left_id=CrdtId(1, 16), + right_id=CrdtId(0, 0), + deleted_length=0, + value=si.GlyphRange( + start=1536, + length=23, + text="display technology.[13]", + color=si.PenColor.YELLOW, + rectangles=[ + si.Rectangle( + x=-809.061564750815, + y=1724.1146737357485, + w=333.5427440226558, + h=56.30432956921868, + ), + si.Rectangle( + x=-485.51105154941456, + y=1730.4364894378523, + w=58.22011730763188, + h=33.42225280328421, + ), + ], + ), + ), + ), + ], +) +def test_blocks_roundtrip(block): + buf = BytesIO() + writer = TaggedBlockWriter(buf) + reader = TaggedBlockReader(buf) + + block.write(writer) + buf.seek(0) + logger.info("After writing block %s", type(block)) + logger.info("Buffer: %s", buf.getvalue().hex()) + + block2 = Block.read(reader) + + assert block2 == block + + +def test_write_blocks(): + blocks = [ + MigrationInfoBlock(migration_id=CrdtId(1, 1), is_device=True), + ] + + buf = BytesIO() + write_blocks(buf, blocks, options={"version": "3.1"}) + + assert buf.getvalue()[:43] == b"reMarkable .lines file, version=6 " + assert buf.getvalue()[43:].hex() == "05000000000101001f01012101" + + +def test_blocks_keep_unknown_data_in_main_block(): + # The "E1 FF" represents new, unknown data -- note that this might need + # to be changed in future if the next id starts to actually be used in a + # future update! + data_hex = """ + 2E000000 0000010D + 1C 06000000 + 1F 0000 + 2F 0000 + 2C 05000000 + 1F 0000 21 01 + 3C 05000000 + 1F 0000 21 01 + 5C 08000000 + 7C050000 50070000 + E1 FF + """ + buf = BytesIO(HEADER_V6 + bytes.fromhex(data_hex)) + block = next(read_blocks(buf)) + assert isinstance(block, SceneInfo) + assert block.extra_data == bytes.fromhex("E1 FF") + + +def test_blocks_keep_unknown_data_in_value_subblock(): + # The "8f 010f" is represents new, unknown data -- note that this might need + # to be changed in future if the next id starts to actually be used in a + # future update! + data_hex = """ + 59000000 00020205 + 1f 0219 + 2f 021e + 3f 0000 + 4f 0000 + 54 0000 0000 + 6c 4300 0000 + 03 + 14 0f000000 + 24 00000000 + 38 00000000 0000f03f + 44 00000000 + 5c 1c000000 + f8fe82c2 f42a30c3 03000800 0000b869 + 83c2622d 30c30000 08000000 + 6f 0001 + 7f 010f + 8f 0101 + """ + buf = BytesIO(HEADER_V6 + bytes.fromhex(data_hex)) + block = next(read_blocks(buf)) + assert isinstance(block, SceneLineItemBlock) + assert block.extra_value_data == bytes.fromhex("8f 0101") + + +def test_error_in_block_contained(): + # First block will cause a parsing error at `0xff`. Second block should + # still be parsed. + data_hex = """ + 06000000 00010103 + 1f 0219 + aa bbcc + 05000000 00010100 + 1f 0219 + 21 01 + """ + buf = BytesIO(HEADER_V6 + bytes.fromhex(data_hex)) + blocks = list(read_blocks(buf)) + assert blocks == [ + UnreadableBlock( + error="Bad tag type 0xA at position 58", + data=bytes.fromhex("1f0219aabbcc"), + info=MainBlockInfo( + offset=51, + size=6, + extra_data=b"", + block_type=3, + min_version=1, + current_version=1, + ), + ), + MigrationInfoBlock(migration_id=CrdtId(0x02, 0x19), is_device=True), + ] + + # Check all data is preserved + buf2 = BytesIO() + # Version 3 to be consistent with the input data used here + write_blocks(buf2, blocks, options={"version": "3.0"}) + + assert buf2.getvalue() == buf.getvalue() + + +from hypothesis import given, strategies as st + + +crdt_id_strategy = st.builds( + CrdtId, + st.integers(min_value=0, max_value=2**8 - 1), + st.integers(min_value=0, max_value=2**64 - 1), +) +st.register_type_strategy(CrdtId, crdt_id_strategy) + +author_ids_block_strategy = st.builds( + AuthorIdsBlock, + st.dictionaries(st.integers(min_value=0, max_value=65535), st.uuids()), + extra_data=st.binary(), +) + +block_strategy = st.one_of( + [ + author_ids_block_strategy, + st.builds(MigrationInfoBlock), + ] +) + + +@given(block_strategy) +def test_blocks_roundtrip_2(block): + buf = BytesIO() + writer = TaggedBlockWriter(buf) + reader = TaggedBlockReader(buf) + + block.write(writer) + buf.seek(0) + logger.info("After writing block %s", type(block)) + logger.info("Buffer: %s", buf.getvalue().hex()) + block2 = Block.read(reader) + assert block2 == block + + +@given(...) +def test_write_id(crdt_id: CrdtId): + buf = BytesIO() + s = TaggedBlockWriter(buf) + s.write_id(3, crdt_id) diff --git a/third_party/rmscene/tests/test_scene_tree.py b/third_party/rmscene/tests/test_scene_tree.py new file mode 100644 index 00000000..62a45dbc --- /dev/null +++ b/third_party/rmscene/tests/test_scene_tree.py @@ -0,0 +1,376 @@ +import pytest +from io import BytesIO +from pathlib import Path +from uuid import UUID +from rmscene import ( + read_blocks, + write_blocks, + LwwValue, + TaggedBlockWriter, + TaggedBlockReader, +) +from rmscene.scene_tree import * +from rmscene.scene_stream import * +from rmscene import scene_items as si +from rmscene.crdt_sequence import CrdtSequenceItem + +import logging + +logger = logging.getLogger(__name__) + + +DATA_PATH = Path(__file__).parent / "data" + + +# @pytest.mark.parametrize( +# "test_file", +# [ +# "Normal_AB.rm", +# "Normal_A_stroke_2_layers.rm", +# "Bold_Heading_Bullet_Normal.rm", +# "Lines_v2.rm" +# ] +# ) +# def test_full_roundtrip(test_file): +# with open(DATA_PATH / test_file, "rb") as f: +# data = f.read() + +# input_buf = BytesIO(data) +# output_buf = BytesIO() +# options = { +# "line_version": (2 if test_file == "Lines_v2.rm" else 1) +# } + +# write_blocks(output_buf, read_blocks(input_buf), options) + +# assert _hex_lines(input_buf.getvalue()) == _hex_lines(output_buf.getvalue()) + + +def tree_structure(item): + if isinstance(item, si.Group): + return ( + item.node_id, + item.label.value, + [tree_structure(child) for child in item.children.values()], + ) + else: + return item + + +def test_basic_tree_structure(): + # this is the bare minimum structure + blocks = [ + SceneTreeBlock( + tree_id=CrdtId(0, 11), + node_id=CrdtId(0, 0), + is_update=True, + parent_id=CrdtId(0, 1), + ), + TreeNodeBlock( + si.Group(CrdtId(0, 1)), + ), + TreeNodeBlock( + si.Group( + node_id=CrdtId(0, 11), + label=LwwValue(CrdtId(0, 12), "Layer 1"), + ) + ), + SceneGroupItemBlock( + parent_id=CrdtId(0, 1), + item=CrdtSequenceItem( + item_id=CrdtId(0, 13), + left_id=CrdtId(0, 0), + right_id=CrdtId(0, 0), + deleted_length=0, + value=CrdtId(0, 11), + ), + ), + ] + + tree = SceneTree() + build_tree(tree, blocks) + + assert tree_structure(tree.root) == ( + CrdtId(0, 1), + "", + [(CrdtId(0, 11), "Layer 1", [])], + ) + + assert list(tree.root.children.values()) == [ + si.Group( + node_id=CrdtId(0, 11), children=[], label=LwwValue(CrdtId(0, 12), "Layer 1") + ) + ] + + +# Example file layers.stroke.rm +# +# SceneTreeBlocks -- all have parent (0, 1) +# +# (0, 11) update=True +# (1, 27) update=True +# (1, 30) update=True +# (1, 40) update=False --> "node_id" (1, 27), parent (0, 0) +# (1, 41) update=True +# +# In ddvk's reader this is described as a "node move" info? +# +# TreeNodeBlock +# +# (0, 1) +# (0, 11) Layer 1 +# (1, 27) Layer 2 +# (1, 30) Layer 3 +# (1, 41) Layer 4 +# +# These don't have any structure (parents etc), just information -- they are +# giving data about a node in the tree? ddvk's reader says it's an error if the +# node here has not already been seen, and if it's not marked as a layer (i.e. +# its parent is the root node). It doesn't add anything new to the tree, just +# attaches the info. +# +# All of the following are "items", so are expected to be added with a parent +# which is an already defined node. Items have left/right IDs, so are ordered, +# and leave tombstones. +# +# SceneGroupItemBlock +# +# Parent: (0, 1) +# (0, 13) -> (0, 11) +# (0, 13) (1, 29) -> (1, 27) +# (0, 29) (1, 32) -> (1, 30) +# (0, 32) (1, 43) -> (1, 41) +# +# The values refer to the "tree blocks" above, with new IDs -- like the Groups +# have their own identity and order (amongst what?), but are referring to nodes +# (layers). +# +# Is this because this defines the order of the layers? Otherwise it's not yet +# specified. So a "GroupItem" defines the order of further nested nodes. +# +# Line, parent: (0, 11) +# +# (1, 14) -> [line data] +# (1, 14) (1, 15) -> DELETED +# ... +# (1, 19) (1, 20) -> DELETED +# (1, 20) (1, 21) -> [line data] +# ... +# (1, 25) (1, 26) -> [line data] at this point, the next layer must have been added +# (1, 26) (1, 46) -> [line data] +# ... +# (1, 51) (1, 52) -> [line data] +# +# Line, parent: (1, 30) +# +# (1, 33) -> [line data] +# (1, 33) (1, 34) -> [line data] +# ... +# (1, 38) (1, 39) -> [line data] +# +# +# So the actual line data has a parent which is a layer. (0, 11) or (1, 30) + + +def test_text_and_strokes(): + line1 = si.Line( + color=si.PenColor.RED, + tool=si.Pen.PENCIL_2, + points=[], + thickness_scale=2.0, + starting_length=0.0, + ) + line2 = si.Line( + color=si.PenColor.BLACK, + tool=si.Pen.FINELINER_2, + points=[], + thickness_scale=2.0, + starting_length=0.0, + ) + blocks = [ + SceneTreeBlock( + tree_id=CrdtId(0, 13), + node_id=CrdtId(0, 0), + is_update=True, + parent_id=CrdtId(0, 1), + ), + SceneTreeBlock( + tree_id=CrdtId(1, 17), + node_id=CrdtId(0, 0), + is_update=True, + parent_id=CrdtId(0, 1), + ), + SceneTreeBlock( + tree_id=CrdtId(1, 20), + node_id=CrdtId(0, 0), + is_update=True, + parent_id=CrdtId(0, 13), + ), + SceneTreeBlock( + tree_id=CrdtId(1, 26), + node_id=CrdtId(0, 0), + is_update=True, + parent_id=CrdtId(1, 17), + ), + RootTextBlock( + block_id=CrdtId(0, 0), + value=si.Text( + items=CrdtSequence([ + CrdtSequenceItem( + item_id=CrdtId(1, 14), + left_id=CrdtId(0, 0), + right_id=CrdtId(0, 0), + deleted_length=0, + value="A", + ) + ]), + styles={}, + pos_x=-468.0, + pos_y=234.0, + width=936.0, + ) + ), + TreeNodeBlock( + si.Group(node_id=CrdtId(0, 1)), + ), + TreeNodeBlock( + si.Group( + node_id=CrdtId(0, 13), + label=LwwValue(timestamp=CrdtId(0, 15), value="Layer 1"), + visible=LwwValue(timestamp=CrdtId(0, 16), value=True), + ) + ), + TreeNodeBlock( + si.Group( + node_id=CrdtId(1, 17), + label=LwwValue(timestamp=CrdtId(1, 18), value="Layer 2"), + visible=LwwValue(timestamp=CrdtId(0, 0), value=True), + ) + ), + TreeNodeBlock( + si.Group( + node_id=CrdtId(1, 20), + label=LwwValue(timestamp=CrdtId(0, 0), value=""), + visible=LwwValue(timestamp=CrdtId(0, 0), value=True), + anchor_id=LwwValue(timestamp=CrdtId(1, 22), value=CrdtId(1, 14)), + anchor_type=LwwValue(timestamp=CrdtId(1, 23), value=2), + anchor_threshold=LwwValue(timestamp=CrdtId(1, 24), value=67.02755737304688), + anchor_origin_x=LwwValue(timestamp=CrdtId(1, 20), value=-464.0), + ) + ), + TreeNodeBlock( + si.Group( + node_id=CrdtId(1, 26), + label=LwwValue(timestamp=CrdtId(0, 0), value=""), + visible=LwwValue(timestamp=CrdtId(0, 0), value=True), + anchor_id=LwwValue(timestamp=CrdtId(1, 28), value=CrdtId(1, 14)), + anchor_type=LwwValue(timestamp=CrdtId(1, 29), value=2), + anchor_threshold=LwwValue(timestamp=CrdtId(1, 30), value=67.02755737304688), + anchor_origin_x=LwwValue(timestamp=CrdtId(1, 26), value=-464.0), + ) + ), + SceneGroupItemBlock( + parent_id=CrdtId(0, 1), + item=CrdtSequenceItem( + item_id=CrdtId(0, 14), + left_id=CrdtId(0, 0), + right_id=CrdtId(0, 0), + deleted_length=0, + value=CrdtId(0, 13), + ), + ), + SceneGroupItemBlock( + parent_id=CrdtId(0, 1), + item=CrdtSequenceItem( + item_id=CrdtId(1, 19), + left_id=CrdtId(0, 14), + right_id=CrdtId(0, 0), + deleted_length=0, + value=CrdtId(1, 17), + ), + ), + SceneGroupItemBlock( + parent_id=CrdtId(0, 13), + item=CrdtSequenceItem( + item_id=CrdtId(1, 21), + left_id=CrdtId(0, 0), + right_id=CrdtId(0, 0), + deleted_length=0, + value=CrdtId(1, 20), + ), + ), + SceneGroupItemBlock( + parent_id=CrdtId(1, 17), + item=CrdtSequenceItem( + item_id=CrdtId(1, 27), + left_id=CrdtId(0, 0), + right_id=CrdtId(0, 0), + deleted_length=0, + value=CrdtId(1, 26), + ), + ), + SceneLineItemBlock( + parent_id=CrdtId(1, 20), + item=CrdtSequenceItem( + item_id=CrdtId(1, 25), + left_id=CrdtId(0, 0), + right_id=CrdtId(0, 0), + deleted_length=0, + value=line1, + ), + ), + SceneLineItemBlock( + parent_id=CrdtId(1, 26), + item=CrdtSequenceItem( + item_id=CrdtId(1, 31), + left_id=CrdtId(0, 0), + right_id=CrdtId(0, 0), + deleted_length=0, + value=line2, + ), + ), + ] + + tree = SceneTree() + build_tree(tree, blocks) + + assert tree_structure(tree.root) == ( + CrdtId(0, 1), + "", + [ + ( + CrdtId(0, 13), + "Layer 1", + [ + (CrdtId(1, 20), "", [line1]), + ], + ), + ( + CrdtId(1, 17), + "Layer 2", + [ + (CrdtId(1, 26), "", [line2]), + ], + ), + ], + ) + + # TODO should also include the text items, and anchor reference + # + # Does this mean the tree should also be able to look up items by ID? And + # maybe actually children list should just contain item ids? + # + # Otherwise how do you make use of the "anchor id" value? Could set the + # explicit reference. + # + # When writing back to blocks, need to be able to flatten the structure + # again (i.e. find out the item id for the anchor, if referenced directly). + # + # Currently the item id is held in the CrdtSequenceItem, not in its value. + + +def test_scene_info_paper_size(): + with open(DATA_PATH / "Color_and_tool_v3.14.4.rm", "rb") as f: + tree = read_tree(f) + assert tree.scene_info is not None + assert tree.scene_info.paper_size == (1620, 2160) diff --git a/third_party/rmscene/tests/test_tagged_block_reader.py b/third_party/rmscene/tests/test_tagged_block_reader.py new file mode 100644 index 00000000..dfcec599 --- /dev/null +++ b/third_party/rmscene/tests/test_tagged_block_reader.py @@ -0,0 +1,186 @@ +import pytest +from io import BytesIO +from rmscene import TaggedBlockReader, UnexpectedBlockError, BlockOverflowError, CrdtId + + +def stream(hex_string: str) -> TaggedBlockReader: + data = bytes.fromhex(hex_string) + return TaggedBlockReader(BytesIO(data)) + + +class TestBlock: + TEST_DATA = ( + "04000000" # length + "00010205" # header + "ff000000" # data + "00000000" # more data to test overflow + ) + + def test_read_block(self): + s = stream(self.TEST_DATA) + with s.read_block() as block_info: + assert block_info is not None + assert block_info.size == 4 + assert block_info.block_type == 5 + assert block_info.min_version == 1 + assert block_info.current_version == 2 + assert block_info.offset == 8 + + value = s.data.read_uint32() + assert value == 0xFF + + def test_bytes_remaining(self): + s = stream(self.TEST_DATA) + with s.read_block(): + assert s.bytes_remaining_in_block() == 4 + s.data.read_uint32() + assert s.bytes_remaining_in_block() == 0 + + def test_error_on_overflow(self): + s = stream(self.TEST_DATA) + with pytest.raises(BlockOverflowError): + with s.read_block(): + s.data.read_uint32() + s.data.read_uint32() + + def test_warns_if_incomplete(self, caplog): + s = stream(self.TEST_DATA) + with s.read_block(): + pass # not reading anything + assert "not been read" in caplog.records[0].message + + def test_skips_to_end_of_block_if_not_all_read(self): + s = stream(self.TEST_DATA) + with s.read_block(): + assert s.data.tell() == 8 + # not reading anything + assert s.data.tell() == 12 + + def test_error_if_already_in_block(self): + s = stream(self.TEST_DATA) + with s.read_block(): + with pytest.raises(UnexpectedBlockError): + with s.read_block(): + pass + + +class TestSubblock: + TEST_DATA = ( + "5c" "04000000" "ff000000" "00000000" # tag # length # data + ) # more data to test overflow + + def test_read_subblock(self): + s = stream(self.TEST_DATA) + with s.read_subblock(5) as block_info: + assert block_info.size == 4 + value = s.data.read_uint32() + assert value == 0xFF + + def test_has_subblock(self): + s = stream(self.TEST_DATA) + # Rewinds so can be called repeatedly + assert s.has_subblock(5) == True + assert s.has_subblock(5) == True + assert s.has_subblock(4) == False + assert s.has_subblock(5) == True + + def test_error_on_wrong_index(self): + s = stream(self.TEST_DATA) + with pytest.raises(UnexpectedBlockError): + with s.read_subblock(3): + pass + + def test_error_on_wrong_tag(self): + s = stream(self.TEST_DATA) + with pytest.raises(UnexpectedBlockError): + s.read_int(5) + + def test_error_on_wrong_index_does_not_consume_tag(self): + s = stream(self.TEST_DATA) + with pytest.raises(UnexpectedBlockError): + with s.read_subblock(3): + pass + + # We can still read the next block after catching the error. + with s.read_subblock(5) as block_info: + assert block_info.size == 4 + + def test_error_on_overflow(self): + s = stream(self.TEST_DATA) + with pytest.raises(BlockOverflowError): + with s.read_subblock(5): + s.data.read_uint32() + s.data.read_uint32() + + def test_warns_if_incomplete(self, caplog): + s = stream(self.TEST_DATA) + with s.read_subblock(5): + pass # not reading anything + assert "not been read" in caplog.records[0].message + + +def test_has_subblock_returns_False_with_bad_data(): + s = stream("1d000000") + assert s.has_subblock(1) == False + assert s.has_subblock(6) == False + assert s.data.tell() == 0 + + +def test_has_subblock_returns_False_at_end_of_file(): + s = stream("") + assert s.has_subblock(2) == False + + +def test_has_subblock_checks_for_end_of_block(): + # See https://github.com/ricklupton/rmscene/issues/17#issuecomment-1701071477 + # + # Construct some potentially confusing data -- the 0x2c is the start of the + # next block, but if we don't take care, `has_subblock(2)` could see it as a + # subblock instead. + data_hex = """ + 03000000 00010103 + 1f 0219 + 2c000000 00010100 + """ + + s = stream(data_hex) + with s.read_block(): + assert s.read_id(1) + assert s.has_subblock(2) == False + + +def test_read_int(): + s = stream("34abcd0000") + assert s.read_int(3) == 0xCDAB + + +def test_read_int_wrong_index(): + s = stream("34abcd0000") + with pytest.raises(UnexpectedBlockError): + s.read_int(2) + + +def test_read_int_default_value(): + s = stream("34abcd0000") + assert s.read_int_optional(2, -1) == -1 + assert s.read_int_optional(3) == 0xCDAB + assert s.read_int_optional(4) == None + + +def test_read_lww_string(): + s = stream("1c0d000000" "1f0101" "2c05000000" "0301616263") + lww = s.read_lww_string(1) + assert lww.timestamp == CrdtId(1, 1) + assert lww.value == "abc" + + +def test_read_string_ascii(): + s = stream("1c05000000" "0301616263") + result = s.read_string(1) + assert result == "abc" + + +def test_read_string_utf(): + s = stream("1c05000000" "030161c397") + result = s.read_string(1) + assert result == "a×" diff --git a/third_party/rmscene/tests/test_tagged_block_writer.py b/third_party/rmscene/tests/test_tagged_block_writer.py new file mode 100644 index 00000000..4fd756b3 --- /dev/null +++ b/third_party/rmscene/tests/test_tagged_block_writer.py @@ -0,0 +1,119 @@ +import pytest +from io import BytesIO +from rmscene import ( + TaggedBlockReader, + TaggedBlockWriter, + CrdtId, + LwwValue, + UnexpectedBlockError, +) + + +def test_write_id_zero(): + buf = BytesIO() + s = TaggedBlockWriter(buf) + s.write_id(3, CrdtId(0, 0)) + assert buf.getvalue().hex() == "3f0000" + + +def test_write_int(): + buf = BytesIO() + s = TaggedBlockWriter(buf) + s.write_int(3, 0xCDAB) + assert buf.getvalue().hex() == "34abcd0000" + + +def test_write_block(): + buf = BytesIO() + s = TaggedBlockWriter(buf) + with s.write_block(5, 1, 2): + s.write_int(3, 0x1234) + assert buf.getvalue().hex() == "05000000000102053434120000" + + +def test_write_block_error_if_nested(): + buf = BytesIO() + s = TaggedBlockWriter(buf) + with pytest.raises(UnexpectedBlockError): + with s.write_block(5, 1, 2): + with s.write_block(4, 1, 1): + s.write_int(3, 0x1234) + + +def test_write_block_error_recovery(): + buf = BytesIO() + s = TaggedBlockWriter(buf) + try: + with s.write_block(5, 1, 2): + s.write_int(3, 0x1234) + raise Exception + except: + pass + + # The subblock redirection should have recovered + s.write_bool(7, True) + assert buf.getvalue().hex() == "7101" + + +def test_write_subblock(): + buf = BytesIO() + s = TaggedBlockWriter(buf) + with s.write_subblock(2): + s.write_int(3, 0x1234) + assert buf.getvalue().hex() == "2c050000003434120000" + + +def test_write_subblock_nested(): + buf = BytesIO() + s = TaggedBlockWriter(buf) + with s.write_subblock(1): + with s.write_subblock(2): + s.write_int(3, 0x1234) + assert buf.getvalue().hex() == "1c0a0000002c050000003434120000" + + +def test_write_subblock_error_recovery(): + buf = BytesIO() + s = TaggedBlockWriter(buf) + try: + with s.write_subblock(2): + s.write_int(3, 0x1234) + raise Exception + except: + pass + + # The subblock redirection should have recovered + s.write_bool(7, True) + assert buf.getvalue().hex() == "7101" + + +@pytest.mark.parametrize( + "data_type,value", + [ + ("id", CrdtId(1, 5)), + ("id", CrdtId(0, 0)), + ("bool", True), + ("bool", False), + ("byte", 7), + ("int", 45), + ("float", 8.0), + ("double", 5.4), + ("lww_bool", LwwValue(CrdtId(1, 4), True)), + ("lww_byte", LwwValue(CrdtId(1, 4), 7)), + ("lww_float", LwwValue(CrdtId(1, 4), 8.0)), + ("lww_id", LwwValue(CrdtId(1, 4), CrdtId(1, 5))), + ("lww_string", LwwValue(CrdtId(1, 4), "hello")), + ("string", "abc"), + ("string", "a×"), + ], +) +@pytest.mark.parametrize("index", [0, 3, 20]) +def test_values_roundtrip(data_type, value, index): + buf = BytesIO() + writer = TaggedBlockWriter(buf) + reader = TaggedBlockReader(buf) + write = getattr(writer, f"write_{data_type}") + read = getattr(reader, f"read_{data_type}") + write(index, value) + buf.seek(0) + assert read(index) == value diff --git a/third_party/rmscene/tests/test_text.py b/third_party/rmscene/tests/test_text.py new file mode 100644 index 00000000..30b8b1cb --- /dev/null +++ b/third_party/rmscene/tests/test_text.py @@ -0,0 +1,225 @@ +import pytest +from rmscene.text import ( + expand_text_item, + expand_text_items, + TextDocument, + CrdtStr, + Paragraph, +) +from rmscene import scene_items as si +from rmscene import CrdtId, CrdtSequenceItem, CrdtSequence + + +def cid(k): + "Shorthand for making end-markers or IDs with author-id = 1." + return CrdtId(0 if k == 0 else 1, k) + + +def make_item(item_id, left_id, right_id, *args): + "Shorthand for creating ids." + return CrdtSequenceItem(cid(item_id), cid(left_id), cid(right_id), *args) + + +def test_expand_text_1(): + result = expand_text_item(make_item(17, 0, 0, 0, "AAAA")) + assert list(result) == [ + make_item(17, 0, 18, 0, "A"), + make_item(18, 17, 19, 0, "A"), + make_item(19, 18, 20, 0, "A"), + make_item(20, 19, 0, 0, "A"), + ] + + +def test_expand_text_2(): + result = expand_text_item(make_item(34, 20, 21, 0, "x")) + assert list(result) == [ + make_item(34, 20, 21, 0, "x"), + ] + + +def test_expand_text_3(): + result = expand_text_item(make_item(21, 20, 0, 0, "A\nB")) + assert list(result) == [ + make_item(21, 20, 22, 0, "A"), + make_item(22, 21, 23, 0, "\n"), + make_item(23, 22, 0, 0, "B"), + ] + + +def test_expand_text_empty(): + result = expand_text_item(make_item(21, 20, 0, 2, "")) + assert list(result) == [ + make_item(21, 20, 22, 1, ""), + make_item(22, 21, 0, 1, ""), + ] + + +START_BOLD = 1 +END_BOLD = 2 +START_ITALIC = 3 +END_ITALIC = 4 + + +def doc_from_items(items): + root_text = si.Text( + items=CrdtSequence(items), + styles={}, + pos_x=-468.0, + pos_y=234.0, + width=936.0, + ) + doc = TextDocument.from_scene_item(root_text) + return doc + + +def test_inline_formatting_italic_over_paragraphs(): + doc = doc_from_items( + [ + make_item(20, 0, 0, 0, "A"), + make_item(21, 20, 0, 0, "B\nC"), + make_item(24, 23, 0, 0, "D"), + # Start italic between A and B + make_item(30, 20, 21, 0, START_ITALIC), + # End italic between C and D + make_item(31, 23, 24, 0, END_ITALIC), + ] + ) + + assert doc.contents == [ + Paragraph( + contents=[ + CrdtStr( + "A", + [CrdtId(1, 20)], + {"font-weight": "normal", "font-style": "normal"}, + ), + CrdtStr( + "B", + [CrdtId(1, 21)], + {"font-weight": "normal", "font-style": "italic"}, + ), + ], + start_id=CrdtId(0, 0), + ), + Paragraph( + contents=[ + CrdtStr( + "C", + [CrdtId(1, 23)], + {"font-weight": "normal", "font-style": "italic"}, + ), + CrdtStr( + "D", + [CrdtId(1, 24)], + {"font-weight": "normal", "font-style": "normal"}, + ), + ], + start_id=CrdtId(1, 22), + ), + ] + + +def test_inline_formatting_italic_over_paragraphs(): + doc = doc_from_items( + [ + make_item(20, 0, 0, 0, "A"), + make_item(21, 20, 0, 0, "B\nC"), + make_item(24, 23, 0, 0, "D"), + # Start italic between A and B + make_item(30, 20, 21, 0, START_ITALIC), + # End italic between C and D + make_item(31, 23, 24, 0, END_ITALIC), + ] + ) + + assert doc.contents == [ + Paragraph( + contents=[ + CrdtStr( + "A", + [CrdtId(1, 20)], + {"font-weight": "normal", "font-style": "normal"}, + ), + CrdtStr( + "B", + [CrdtId(1, 21)], + {"font-weight": "normal", "font-style": "italic"}, + ), + ], + start_id=CrdtId(0, 0), + ), + Paragraph( + contents=[ + CrdtStr( + "C", + [CrdtId(1, 23)], + {"font-weight": "normal", "font-style": "italic"}, + ), + CrdtStr( + "D", + [CrdtId(1, 24)], + {"font-weight": "normal", "font-style": "normal"}, + ), + ], + start_id=CrdtId(1, 22), + ), + ] + + +def test_inline_formatting_bold_italic_interleaved_over_paragraphs(): + doc = doc_from_items( + [ + make_item(20, 0, 0, 0, "ABC\nDEF"), + # Start italic between A and B + make_item(30, 20, 21, 0, START_ITALIC), + # Start bold between B and C + make_item(31, 21, 22, 0, START_BOLD), + # End italic between D and E + make_item(32, 24, 25, 0, END_ITALIC), + # End bold between E and F + make_item(33, 25, 26, 0, END_BOLD), + ] + ) + + assert doc.contents == [ + Paragraph( + contents=[ + CrdtStr( + "A", + [CrdtId(1, 20)], + {"font-weight": "normal", "font-style": "normal"}, + ), + CrdtStr( + "B", + [CrdtId(1, 21)], + {"font-weight": "normal", "font-style": "italic"}, + ), + CrdtStr( + "C", + [CrdtId(1, 22)], + {"font-weight": "bold", "font-style": "italic"}, + ), + ], + start_id=CrdtId(0, 0), + ), + Paragraph( + contents=[ + CrdtStr( + "D", + [CrdtId(1, 24)], + {"font-weight": "bold", "font-style": "italic"}, + ), + CrdtStr( + "E", + [CrdtId(1, 25)], + {"font-weight": "bold", "font-style": "normal"}, + ), + CrdtStr( + "F", + [CrdtId(1, 26)], + {"font-weight": "normal", "font-style": "normal"}, + ), + ], + start_id=CrdtId(1, 23), + ), + ] diff --git a/third_party/rmscene/tests/test_text_files.py b/third_party/rmscene/tests/test_text_files.py new file mode 100644 index 00000000..6ee2c628 --- /dev/null +++ b/third_party/rmscene/tests/test_text_files.py @@ -0,0 +1,101 @@ +from uuid import UUID +from io import BytesIO +from pathlib import Path +from rmscene.scene_stream import * +from rmscene.scene_items import Text, ParagraphStyle +from rmscene.text import TextDocument, CrdtStr + +DATA_PATH = Path(__file__).parent / "data" + + +def _hex_lines(b, n=32): + return [b[i * n : (i + 1) * n].hex() for i in range(len(b) // n + 1)] + + +def extract_doc(filename): + with open(filename, "rb") as f: + tree = read_tree(f) + assert tree.root_text + doc = TextDocument.from_scene_item(tree.root_text) + return doc + + +def show_str_formatting(x): + # Basic logic -- could be smarter about removing adjacent + # unnecessary opening/closing tags + s = x.s + if x.properties.get("font-weight") == "bold": + s = f"{s}" + if x.properties.get("font-style") == "italic": + s = f"{s}" + return s + + +def formatted_lines(doc): + return [ + (p.style.value, "".join(show_str_formatting(s) for s in p.contents)) + for p in doc.contents + ] + + +def extract_paragraphs(filename): + with open(filename, "rb") as f: + tree = read_tree(f) + assert tree.root_text + + +def test_normal_ab(): + lines = formatted_lines(extract_doc(DATA_PATH / "Normal_AB.rm")) + assert lines == [(ParagraphStyle.PLAIN, "AB")] + + +def test_list(): + lines = formatted_lines(extract_doc(DATA_PATH / "Bold_Heading_Bullet_Normal.rm")) + assert lines == [ + (ParagraphStyle.BOLD, "A"), + (ParagraphStyle.HEADING, "new line"), + (ParagraphStyle.BULLET, "B is a letter of the alphabet"), + (ParagraphStyle.PLAIN, "C"), + ] + + +def test_inline_formats(): + doc = extract_doc(DATA_PATH / "Normal_A_stroke_2_layers_v3.3.2.rm") + lines = formatted_lines(doc) + assert lines == [ + (ParagraphStyle.PLAIN, "A"), + (ParagraphStyle.PLAIN, "v3.2.2"), + ( + ParagraphStyle.PLAIN, + "Normal bold italic", + ), + ( + ParagraphStyle.PLAIN, + "Bold italic normal", + ), + (ParagraphStyle.BOLD, "Bold line"), + (ParagraphStyle.PLAIN, "Normal line"), + (ParagraphStyle.HEADING, "Heading line"), + ] + + +def test_crdt_concurrent_author_ordering(): + # Two authors concurrently inserted between 'A' and 'Z'; the higher author + # ID (tablet, author 2) should appear before the lower (desktop, author 1), + # giving "A12_Z" not "A_12Z". + lines = formatted_lines(extract_doc(DATA_PATH / "test-crdt-ordering.rm")) + assert lines == [(ParagraphStyle.HEADING, "A12_Z")] + + +def test_simple_text_document(): + test_file = "Normal_AB.rm" + with open(DATA_PATH / test_file, "rb") as f: + expected = f.read() + + output_buf = BytesIO() + author_id = UUID("495ba59f-c943-2b5c-b455-3682f6948906") + write_blocks( + output_buf, simple_text_document("AB", author_id), options={"version": "3.0"} + ) + + assert _hex_lines(output_buf.getvalue()) == _hex_lines(expected) diff --git a/ui/.env b/ui/.env deleted file mode 100644 index 5ae7057f..00000000 --- a/ui/.env +++ /dev/null @@ -1,3 +0,0 @@ -PORT=3001 -REACT_APP_ROOT_URL=http://localhost:3000/ui/api -DANGEROUSLY_DISABLE_HOST_CHECK=true diff --git a/ui/.gitignore b/ui/.gitignore deleted file mode 100644 index 4d29575d..00000000 --- a/ui/.gitignore +++ /dev/null @@ -1,23 +0,0 @@ -# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. - -# dependencies -/node_modules -/.pnp -.pnp.js - -# testing -/coverage - -# production -/build - -# misc -.DS_Store -.env.local -.env.development.local -.env.test.local -.env.production.local - -npm-debug.log* -yarn-debug.log* -yarn-error.log* diff --git a/ui/.npmrc b/ui/.npmrc deleted file mode 100644 index 150cdf72..00000000 --- a/ui/.npmrc +++ /dev/null @@ -1 +0,0 @@ -public-hoist-pattern[]=pdfjs-dist diff --git a/ui/README.md b/ui/README.md deleted file mode 100644 index 125c4ac0..00000000 --- a/ui/README.md +++ /dev/null @@ -1 +0,0 @@ -# UI for rmfakecloud diff --git a/ui/assets.go b/ui/assets.go deleted file mode 100644 index 99fa0128..00000000 --- a/ui/assets.go +++ /dev/null @@ -1,8 +0,0 @@ -//go:build !ci - -package rmfakecloud - -import "embed" - -//go:embed dist/* -var Assets embed.FS diff --git a/ui/config/index.js b/ui/config/index.js deleted file mode 100644 index db81b2e5..00000000 --- a/ui/config/index.js +++ /dev/null @@ -1,4 +0,0 @@ -export default { - Doc: '/document-storage/json/2/docs', - GetDocument: '/document-storage/json/2/docs', -} diff --git a/ui/eslint.config.js b/ui/eslint.config.js deleted file mode 100644 index 092408a9..00000000 --- a/ui/eslint.config.js +++ /dev/null @@ -1,28 +0,0 @@ -import js from '@eslint/js' -import globals from 'globals' -import reactHooks from 'eslint-plugin-react-hooks' -import reactRefresh from 'eslint-plugin-react-refresh' -import tseslint from 'typescript-eslint' - -export default tseslint.config( - { ignores: ['dist'] }, - { - extends: [js.configs.recommended, ...tseslint.configs.recommended], - files: ['**/*.{ts,tsx}'], - languageOptions: { - ecmaVersion: 2020, - globals: globals.browser, - }, - plugins: { - 'react-hooks': reactHooks, - 'react-refresh': reactRefresh, - }, - rules: { - ...reactHooks.configs.recommended.rules, - 'react-refresh/only-export-components': [ - 'warn', - { allowConstantExport: true }, - ], - }, - }, -) diff --git a/ui/index.html b/ui/index.html deleted file mode 100644 index 1eb06d6c..00000000 --- a/ui/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - rmfakecloud - - - -
    - - - diff --git a/ui/package.json b/ui/package.json deleted file mode 100644 index 8b7ebde9..00000000 --- a/ui/package.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "name": "ui", - "license": "AGPL-3.0", - "version": "0.1.0", - "private": true, - "type": "module", - "scripts": { - "dev": "vite", - "build": "tsc -b && vite build", - "lint": "eslint .", - "preview": "vite preview" - }, - "dependencies": { - "@tanstack/react-table": "^8.21.3", - "bootstrap": "^5.3.3", - "jwt-decode": "^4.0.0", - "moment": "^2.30.1", - "mqtt": "^5.15.1", - "pako": "^1.0.11", - "react": "^18.3.1", - "react-arborist": "^3.4.0", - "react-bootstrap": "^2.10.5", - "react-dom": "^18.3.1", - "react-dropzone": "^14.3.5", - "react-icons": "^5.3.0", - "react-pdf": "^9.1.1", - "react-router-dom": "^5.3.3", - "react-toastify": "^10.0.6" - }, - "devDependencies": { - "@eslint/js": "^9.15.0", - "@types/react": "^18.3.12", - "@types/react-dom": "^18.3.1", - "@vitejs/plugin-react-swc": "^3.7.1", - "eslint": "^9.15.0", - "eslint-plugin-react-hooks": "^5.0.0", - "eslint-plugin-react-refresh": "^0.4.14", - "globals": "^15.12.0", - "sass-embedded": "^1.81.0", - "typescript": "~5.6.3", - "typescript-eslint": "^8.15.0", - "vite": "^5.4.19" - }, - "proxy": "http://localhost:3000" -} diff --git a/ui/pnpm-lock.yaml b/ui/pnpm-lock.yaml deleted file mode 100644 index 760748a5..00000000 --- a/ui/pnpm-lock.yaml +++ /dev/null @@ -1,3545 +0,0 @@ -lockfileVersion: '9.0' - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -importers: - - .: - dependencies: - '@tanstack/react-table': - specifier: ^8.21.3 - version: 8.21.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - bootstrap: - specifier: ^5.3.3 - version: 5.3.3(@popperjs/core@2.11.8) - jwt-decode: - specifier: ^4.0.0 - version: 4.0.0 - moment: - specifier: ^2.30.1 - version: 2.30.1 - mqtt: - specifier: ^5.15.1 - version: 5.15.1 - pako: - specifier: ^1.0.11 - version: 1.0.11 - react: - specifier: ^18.3.1 - version: 18.3.1 - react-arborist: - specifier: ^3.4.0 - version: 3.4.0(@types/node@25.5.0)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react-bootstrap: - specifier: ^2.10.5 - version: 2.10.5(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react-dom: - specifier: ^18.3.1 - version: 18.3.1(react@18.3.1) - react-dropzone: - specifier: ^14.3.5 - version: 14.3.5(react@18.3.1) - react-icons: - specifier: ^5.3.0 - version: 5.3.0(react@18.3.1) - react-pdf: - specifier: ^9.1.1 - version: 9.1.1(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react-router-dom: - specifier: ^5.3.3 - version: 5.3.4(react@18.3.1) - react-toastify: - specifier: ^10.0.6 - version: 10.0.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - devDependencies: - '@eslint/js': - specifier: ^9.15.0 - version: 9.15.0 - '@types/react': - specifier: ^18.3.12 - version: 18.3.12 - '@types/react-dom': - specifier: ^18.3.1 - version: 18.3.1 - '@vitejs/plugin-react-swc': - specifier: ^3.7.1 - version: 3.7.1(@swc/helpers@0.5.15)(vite@5.4.19(@types/node@25.5.0)(sass-embedded@1.81.0)(sass@1.77.6)) - eslint: - specifier: ^9.15.0 - version: 9.15.0 - eslint-plugin-react-hooks: - specifier: ^5.0.0 - version: 5.0.0(eslint@9.15.0) - eslint-plugin-react-refresh: - specifier: ^0.4.14 - version: 0.4.14(eslint@9.15.0) - globals: - specifier: ^15.12.0 - version: 15.12.0 - sass-embedded: - specifier: ^1.81.0 - version: 1.81.0 - typescript: - specifier: ~5.6.3 - version: 5.6.3 - typescript-eslint: - specifier: ^8.15.0 - version: 8.15.0(eslint@9.15.0)(typescript@5.6.3) - vite: - specifier: ^5.4.19 - version: 5.4.19(@types/node@25.5.0)(sass-embedded@1.81.0)(sass@1.77.6) - -packages: - - '@babel/runtime@7.26.0': - resolution: {integrity: sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==} - engines: {node: '>=6.9.0'} - - '@babel/runtime@7.29.2': - resolution: {integrity: sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==} - engines: {node: '>=6.9.0'} - - '@bufbuild/protobuf@2.2.2': - resolution: {integrity: sha512-UNtPCbrwrenpmrXuRwn9jYpPoweNXj8X5sMvYgsqYyaH8jQ6LfUJSk3dJLnBK+6sfYPrF4iAIo5sd5HQ+tg75A==} - - '@esbuild/aix-ppc64@0.21.5': - resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [aix] - - '@esbuild/android-arm64@0.21.5': - resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} - engines: {node: '>=12'} - cpu: [arm64] - os: [android] - - '@esbuild/android-arm@0.21.5': - resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} - engines: {node: '>=12'} - cpu: [arm] - os: [android] - - '@esbuild/android-x64@0.21.5': - resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} - engines: {node: '>=12'} - cpu: [x64] - os: [android] - - '@esbuild/darwin-arm64@0.21.5': - resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} - engines: {node: '>=12'} - cpu: [arm64] - os: [darwin] - - '@esbuild/darwin-x64@0.21.5': - resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} - engines: {node: '>=12'} - cpu: [x64] - os: [darwin] - - '@esbuild/freebsd-arm64@0.21.5': - resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} - engines: {node: '>=12'} - cpu: [arm64] - os: [freebsd] - - '@esbuild/freebsd-x64@0.21.5': - resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [freebsd] - - '@esbuild/linux-arm64@0.21.5': - resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} - engines: {node: '>=12'} - cpu: [arm64] - os: [linux] - - '@esbuild/linux-arm@0.21.5': - resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} - engines: {node: '>=12'} - cpu: [arm] - os: [linux] - - '@esbuild/linux-ia32@0.21.5': - resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} - engines: {node: '>=12'} - cpu: [ia32] - os: [linux] - - '@esbuild/linux-loong64@0.21.5': - resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} - engines: {node: '>=12'} - cpu: [loong64] - os: [linux] - - '@esbuild/linux-mips64el@0.21.5': - resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} - engines: {node: '>=12'} - cpu: [mips64el] - os: [linux] - - '@esbuild/linux-ppc64@0.21.5': - resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [linux] - - '@esbuild/linux-riscv64@0.21.5': - resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} - engines: {node: '>=12'} - cpu: [riscv64] - os: [linux] - - '@esbuild/linux-s390x@0.21.5': - resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} - engines: {node: '>=12'} - cpu: [s390x] - os: [linux] - - '@esbuild/linux-x64@0.21.5': - resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [linux] - - '@esbuild/netbsd-x64@0.21.5': - resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} - engines: {node: '>=12'} - cpu: [x64] - os: [netbsd] - - '@esbuild/openbsd-x64@0.21.5': - resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} - engines: {node: '>=12'} - cpu: [x64] - os: [openbsd] - - '@esbuild/sunos-x64@0.21.5': - resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} - engines: {node: '>=12'} - cpu: [x64] - os: [sunos] - - '@esbuild/win32-arm64@0.21.5': - resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} - engines: {node: '>=12'} - cpu: [arm64] - os: [win32] - - '@esbuild/win32-ia32@0.21.5': - resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} - engines: {node: '>=12'} - cpu: [ia32] - os: [win32] - - '@esbuild/win32-x64@0.21.5': - resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} - engines: {node: '>=12'} - cpu: [x64] - os: [win32] - - '@eslint-community/eslint-utils@4.4.1': - resolution: {integrity: sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - - '@eslint-community/regexpp@4.12.1': - resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} - engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - - '@eslint/config-array@0.19.0': - resolution: {integrity: sha512-zdHg2FPIFNKPdcHWtiNT+jEFCHYVplAXRDlQDyqy0zGx/q2parwh7brGJSiTxRk/TSMkbM//zt/f5CHgyTyaSQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/core@0.9.0': - resolution: {integrity: sha512-7ATR9F0e4W85D/0w7cU0SNj7qkAexMG+bAHEZOjo9akvGuhHE2m7umzWzfnpa0XAg5Kxc1BWmtPMV67jJ+9VUg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/eslintrc@3.2.0': - resolution: {integrity: sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/js@9.15.0': - resolution: {integrity: sha512-tMTqrY+EzbXmKJR5ToI8lxu7jaN5EdmrBFJpQk5JmSlyLsx6o4t27r883K5xsLuCYCpfKBCGswMSWXsM+jB7lg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/object-schema@2.1.4': - resolution: {integrity: sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/plugin-kit@0.2.3': - resolution: {integrity: sha512-2b/g5hRmpbb1o4GnTZax9N9m0FXzz9OV42ZzI4rDDMDuHUqigAiQCEWChBWCY4ztAGVRjoWT19v0yMmc5/L5kA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@humanfs/core@0.19.1': - resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} - engines: {node: '>=18.18.0'} - - '@humanfs/node@0.16.6': - resolution: {integrity: sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==} - engines: {node: '>=18.18.0'} - - '@humanwhocodes/module-importer@1.0.1': - resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} - engines: {node: '>=12.22'} - - '@humanwhocodes/retry@0.3.1': - resolution: {integrity: sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==} - engines: {node: '>=18.18'} - - '@humanwhocodes/retry@0.4.1': - resolution: {integrity: sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==} - engines: {node: '>=18.18'} - - '@mapbox/node-pre-gyp@1.0.11': - resolution: {integrity: sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==} - hasBin: true - - '@nodelib/fs.scandir@2.1.5': - resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} - engines: {node: '>= 8'} - - '@nodelib/fs.stat@2.0.5': - resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} - engines: {node: '>= 8'} - - '@nodelib/fs.walk@1.2.8': - resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} - engines: {node: '>= 8'} - - '@popperjs/core@2.11.8': - resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==} - - '@react-aria/ssr@3.9.6': - resolution: {integrity: sha512-iLo82l82ilMiVGy342SELjshuWottlb5+VefO3jOQqQRNYnJBFpUSadswDPbRimSgJUZuFwIEYs6AabkP038fA==} - engines: {node: '>= 12'} - peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 - - '@react-dnd/asap@4.0.1': - resolution: {integrity: sha512-kLy0PJDDwvwwTXxqTFNAAllPHD73AycE9ypWeln/IguoGBEbvFcPDbCV03G52bEcC5E+YgupBE0VzHGdC8SIXg==} - - '@react-dnd/invariant@2.0.0': - resolution: {integrity: sha512-xL4RCQBCBDJ+GRwKTFhGUW8GXa4yoDfJrPbLblc3U09ciS+9ZJXJ3Qrcs/x2IODOdIE5kQxvMmE2UKyqUictUw==} - - '@react-dnd/shallowequal@2.0.0': - resolution: {integrity: sha512-Pc/AFTdwZwEKJxFJvlxrSmGe/di+aAOBn60sremrpLo6VI/6cmiUYNNwlI5KNYttg7uypzA3ILPMPgxB2GYZEg==} - - '@restart/hooks@0.4.16': - resolution: {integrity: sha512-f7aCv7c+nU/3mF7NWLtVVr0Ra80RqsO89hO72r+Y/nvQr5+q0UFGkocElTH6MJApvReVh6JHUFYn2cw1WdHF3w==} - peerDependencies: - react: '>=16.8.0' - - '@restart/ui@1.8.0': - resolution: {integrity: sha512-xJEOXUOTmT4FngTmhdjKFRrVVF0hwCLNPdatLCHkyS4dkiSK12cEu1Y0fjxktjJrdst9jJIc5J6ihMJCoWEN/g==} - peerDependencies: - react: '>=16.14.0' - react-dom: '>=16.14.0' - - '@rollup/rollup-android-arm-eabi@4.44.1': - resolution: {integrity: sha512-JAcBr1+fgqx20m7Fwe1DxPUl/hPkee6jA6Pl7n1v2EFiktAHenTaXl5aIFjUIEsfn9w3HE4gK1lEgNGMzBDs1w==} - cpu: [arm] - os: [android] - - '@rollup/rollup-android-arm64@4.44.1': - resolution: {integrity: sha512-RurZetXqTu4p+G0ChbnkwBuAtwAbIwJkycw1n6GvlGlBuS4u5qlr5opix8cBAYFJgaY05TWtM+LaoFggUmbZEQ==} - cpu: [arm64] - os: [android] - - '@rollup/rollup-darwin-arm64@4.44.1': - resolution: {integrity: sha512-fM/xPesi7g2M7chk37LOnmnSTHLG/v2ggWqKj3CCA1rMA4mm5KVBT1fNoswbo1JhPuNNZrVwpTvlCVggv8A2zg==} - cpu: [arm64] - os: [darwin] - - '@rollup/rollup-darwin-x64@4.44.1': - resolution: {integrity: sha512-gDnWk57urJrkrHQ2WVx9TSVTH7lSlU7E3AFqiko+bgjlh78aJ88/3nycMax52VIVjIm3ObXnDL2H00e/xzoipw==} - cpu: [x64] - os: [darwin] - - '@rollup/rollup-freebsd-arm64@4.44.1': - resolution: {integrity: sha512-wnFQmJ/zPThM5zEGcnDcCJeYJgtSLjh1d//WuHzhf6zT3Md1BvvhJnWoy+HECKu2bMxaIcfWiu3bJgx6z4g2XA==} - cpu: [arm64] - os: [freebsd] - - '@rollup/rollup-freebsd-x64@4.44.1': - resolution: {integrity: sha512-uBmIxoJ4493YATvU2c0upGz87f99e3wop7TJgOA/bXMFd2SvKCI7xkxY/5k50bv7J6dw1SXT4MQBQSLn8Bb/Uw==} - cpu: [x64] - os: [freebsd] - - '@rollup/rollup-linux-arm-gnueabihf@4.44.1': - resolution: {integrity: sha512-n0edDmSHlXFhrlmTK7XBuwKlG5MbS7yleS1cQ9nn4kIeW+dJH+ExqNgQ0RrFRew8Y+0V/x6C5IjsHrJmiHtkxQ==} - cpu: [arm] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-arm-musleabihf@4.44.1': - resolution: {integrity: sha512-8WVUPy3FtAsKSpyk21kV52HCxB+me6YkbkFHATzC2Yd3yuqHwy2lbFL4alJOLXKljoRw08Zk8/xEj89cLQ/4Nw==} - cpu: [arm] - os: [linux] - libc: [musl] - - '@rollup/rollup-linux-arm64-gnu@4.44.1': - resolution: {integrity: sha512-yuktAOaeOgorWDeFJggjuCkMGeITfqvPgkIXhDqsfKX8J3jGyxdDZgBV/2kj/2DyPaLiX6bPdjJDTu9RB8lUPQ==} - cpu: [arm64] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-arm64-musl@4.44.1': - resolution: {integrity: sha512-W+GBM4ifET1Plw8pdVaecwUgxmiH23CfAUj32u8knq0JPFyK4weRy6H7ooxYFD19YxBulL0Ktsflg5XS7+7u9g==} - cpu: [arm64] - os: [linux] - libc: [musl] - - '@rollup/rollup-linux-loongarch64-gnu@4.44.1': - resolution: {integrity: sha512-1zqnUEMWp9WrGVuVak6jWTl4fEtrVKfZY7CvcBmUUpxAJ7WcSowPSAWIKa/0o5mBL/Ij50SIf9tuirGx63Ovew==} - cpu: [loong64] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-powerpc64le-gnu@4.44.1': - resolution: {integrity: sha512-Rl3JKaRu0LHIx7ExBAAnf0JcOQetQffaw34T8vLlg9b1IhzcBgaIdnvEbbsZq9uZp3uAH+JkHd20Nwn0h9zPjA==} - cpu: [ppc64] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-riscv64-gnu@4.44.1': - resolution: {integrity: sha512-j5akelU3snyL6K3N/iX7otLBIl347fGwmd95U5gS/7z6T4ftK288jKq3A5lcFKcx7wwzb5rgNvAg3ZbV4BqUSw==} - cpu: [riscv64] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-riscv64-musl@4.44.1': - resolution: {integrity: sha512-ppn5llVGgrZw7yxbIm8TTvtj1EoPgYUAbfw0uDjIOzzoqlZlZrLJ/KuiE7uf5EpTpCTrNt1EdtzF0naMm0wGYg==} - cpu: [riscv64] - os: [linux] - libc: [musl] - - '@rollup/rollup-linux-s390x-gnu@4.44.1': - resolution: {integrity: sha512-Hu6hEdix0oxtUma99jSP7xbvjkUM/ycke/AQQ4EC5g7jNRLLIwjcNwaUy95ZKBJJwg1ZowsclNnjYqzN4zwkAw==} - cpu: [s390x] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-x64-gnu@4.44.1': - resolution: {integrity: sha512-EtnsrmZGomz9WxK1bR5079zee3+7a+AdFlghyd6VbAjgRJDbTANJ9dcPIPAi76uG05micpEL+gPGmAKYTschQw==} - cpu: [x64] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-x64-musl@4.44.1': - resolution: {integrity: sha512-iAS4p+J1az6Usn0f8xhgL4PaU878KEtutP4hqw52I4IO6AGoyOkHCxcc4bqufv1tQLdDWFx8lR9YlwxKuv3/3g==} - cpu: [x64] - os: [linux] - libc: [musl] - - '@rollup/rollup-win32-arm64-msvc@4.44.1': - resolution: {integrity: sha512-NtSJVKcXwcqozOl+FwI41OH3OApDyLk3kqTJgx8+gp6On9ZEt5mYhIsKNPGuaZr3p9T6NWPKGU/03Vw4CNU9qg==} - cpu: [arm64] - os: [win32] - - '@rollup/rollup-win32-ia32-msvc@4.44.1': - resolution: {integrity: sha512-JYA3qvCOLXSsnTR3oiyGws1Dm0YTuxAAeaYGVlGpUsHqloPcFjPg+X0Fj2qODGLNwQOAcCiQmHub/V007kiH5A==} - cpu: [ia32] - os: [win32] - - '@rollup/rollup-win32-x64-msvc@4.44.1': - resolution: {integrity: sha512-J8o22LuF0kTe7m+8PvW9wk3/bRq5+mRo5Dqo6+vXb7otCm3TPhYOJqOaQtGU9YMWQSL3krMnoOxMr0+9E6F3Ug==} - cpu: [x64] - os: [win32] - - '@swc/core-darwin-arm64@1.9.2': - resolution: {integrity: sha512-nETmsCoY29krTF2PtspEgicb3tqw7Ci5sInTI03EU5zpqYbPjoPH99BVTjj0OsF53jP5MxwnLI5Hm21lUn1d6A==} - engines: {node: '>=10'} - cpu: [arm64] - os: [darwin] - - '@swc/core-darwin-x64@1.9.2': - resolution: {integrity: sha512-9gD+bwBz8ZByjP6nZTXe/hzd0tySIAjpDHgkFiUrc+5zGF+rdTwhcNrzxNHJmy6mw+PW38jqII4uspFHUqqxuQ==} - engines: {node: '>=10'} - cpu: [x64] - os: [darwin] - - '@swc/core-linux-arm-gnueabihf@1.9.2': - resolution: {integrity: sha512-kYq8ief1Qrn+WmsTWAYo4r+Coul4dXN6cLFjiPZ29Cv5pyU+GFvSPAB4bEdMzwy99rCR0u2P10UExaeCjurjvg==} - engines: {node: '>=10'} - cpu: [arm] - os: [linux] - - '@swc/core-linux-arm64-gnu@1.9.2': - resolution: {integrity: sha512-n0W4XiXlmEIVqxt+rD3ZpkogsEWUk1jJ+i5bQNgB+1JuWh0fBE8c/blDgTQXa0GB5lTPVDZQussgdNOCnAZwiA==} - engines: {node: '>=10'} - cpu: [arm64] - os: [linux] - libc: [glibc] - - '@swc/core-linux-arm64-musl@1.9.2': - resolution: {integrity: sha512-8xzrOmsyCC1zrx2Wzx/h8dVsdewO1oMCwBTLc1gSJ/YllZYTb04pNm6NsVbzUX2tKddJVRgSJXV10j/NECLwpA==} - engines: {node: '>=10'} - cpu: [arm64] - os: [linux] - libc: [musl] - - '@swc/core-linux-x64-gnu@1.9.2': - resolution: {integrity: sha512-kZrNz/PjRQKcchWF6W292jk3K44EoVu1ad5w+zbS4jekIAxsM8WwQ1kd+yjUlN9jFcF8XBat5NKIs9WphJCVXg==} - engines: {node: '>=10'} - cpu: [x64] - os: [linux] - libc: [glibc] - - '@swc/core-linux-x64-musl@1.9.2': - resolution: {integrity: sha512-TTIpR4rjMkhX1lnFR+PSXpaL83TrQzp9znRdp2TzYrODlUd/R20zOwSo9vFLCyH6ZoD47bccY7QeGZDYT3nlRg==} - engines: {node: '>=10'} - cpu: [x64] - os: [linux] - libc: [musl] - - '@swc/core-win32-arm64-msvc@1.9.2': - resolution: {integrity: sha512-+Eg2d4icItKC0PMjZxH7cSYFLWk0aIp94LNmOw6tPq0e69ax6oh10upeq0D1fjWsKLmOJAWEvnXlayZcijEXDw==} - engines: {node: '>=10'} - cpu: [arm64] - os: [win32] - - '@swc/core-win32-ia32-msvc@1.9.2': - resolution: {integrity: sha512-nLWBi4vZDdM/LkiQmPCakof8Dh1/t5EM7eudue04V1lIcqx9YHVRS3KMwEaCoHLGg0c312Wm4YgrWQd9vwZ5zQ==} - engines: {node: '>=10'} - cpu: [ia32] - os: [win32] - - '@swc/core-win32-x64-msvc@1.9.2': - resolution: {integrity: sha512-ik/k+JjRJBFkXARukdU82tSVx0CbExFQoQ78qTO682esbYXzjdB5eLVkoUbwen299pnfr88Kn4kyIqFPTje8Xw==} - engines: {node: '>=10'} - cpu: [x64] - os: [win32] - - '@swc/core@1.9.2': - resolution: {integrity: sha512-dYyEkO6mRYtZFpnOsnYzv9rY69fHAHoawYOjGOEcxk9WYtaJhowMdP/w6NcOKnz2G7GlZaenjkzkMa6ZeQeMsg==} - engines: {node: '>=10'} - peerDependencies: - '@swc/helpers': '*' - peerDependenciesMeta: - '@swc/helpers': - optional: true - - '@swc/counter@0.1.3': - resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==} - - '@swc/helpers@0.5.15': - resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==} - - '@swc/types@0.1.15': - resolution: {integrity: sha512-XKaZ+dzDIQ9Ot9o89oJQ/aluI17+VvUnIpYJTcZtvv1iYX6MzHh3Ik2CSR7MdPKpPwfZXHBeCingb2b4PoDVdw==} - - '@tanstack/react-table@8.21.3': - resolution: {integrity: sha512-5nNMTSETP4ykGegmVkhjcS8tTLW6Vl4axfEGQN3v0zdHYbK4UfoqfPChclTrJ4EoK9QynqAu9oUf8VEmrpZ5Ww==} - engines: {node: '>=12'} - peerDependencies: - react: '>=16.8' - react-dom: '>=16.8' - - '@tanstack/table-core@8.21.3': - resolution: {integrity: sha512-ldZXEhOBb8Is7xLs01fR3YEc3DERiz5silj8tnGkFZytt1abEvl/GhUmCE0PMLaMPTa3Jk4HbKmRlHmu+gCftg==} - engines: {node: '>=12'} - - '@types/estree@1.0.6': - resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} - - '@types/estree@1.0.8': - resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} - - '@types/json-schema@7.0.15': - resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - - '@types/node@25.5.0': - resolution: {integrity: sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw==} - - '@types/prop-types@15.7.13': - resolution: {integrity: sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==} - - '@types/react-dom@18.3.1': - resolution: {integrity: sha512-qW1Mfv8taImTthu4KoXgDfLuk4bydU6Q/TkADnDWWHwi4NX4BR+LWfTp2sVmTqRrsHvyDDTelgelxJ+SsejKKQ==} - - '@types/react-transition-group@4.4.11': - resolution: {integrity: sha512-RM05tAniPZ5DZPzzNFP+DmrcOdD0efDUxMy3145oljWSl3x9ZV5vhme98gTxFrj2lhXvmGNnUiuDyJgY9IKkNA==} - - '@types/react@18.3.12': - resolution: {integrity: sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw==} - - '@types/readable-stream@4.0.23': - resolution: {integrity: sha512-wwXrtQvbMHxCbBgjHaMGEmImFTQxxpfMOR/ZoQnXxB1woqkUbdLGFDgauo00Py9IudiaqSeiBiulSV9i6XIPig==} - - '@types/warning@3.0.3': - resolution: {integrity: sha512-D1XC7WK8K+zZEveUPY+cf4+kgauk8N4eHr/XIHXGlGYkHLud6hK9lYfZk1ry1TNh798cZUCgb6MqGEG8DkJt6Q==} - - '@types/ws@8.18.1': - resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==} - - '@typescript-eslint/eslint-plugin@8.15.0': - resolution: {integrity: sha512-+zkm9AR1Ds9uLWN3fkoeXgFppaQ+uEVtfOV62dDmsy9QCNqlRHWNEck4yarvRNrvRcHQLGfqBNui3cimoz8XAg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 - eslint: ^8.57.0 || ^9.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - - '@typescript-eslint/parser@8.15.0': - resolution: {integrity: sha512-7n59qFpghG4uazrF9qtGKBZXn7Oz4sOMm8dwNWDQY96Xlm2oX67eipqcblDj+oY1lLCbf1oltMZFpUso66Kl1A==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - - '@typescript-eslint/scope-manager@8.15.0': - resolution: {integrity: sha512-QRGy8ADi4J7ii95xz4UoiymmmMd/zuy9azCaamnZ3FM8T5fZcex8UfJcjkiEZjJSztKfEBe3dZ5T/5RHAmw2mA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@typescript-eslint/type-utils@8.15.0': - resolution: {integrity: sha512-UU6uwXDoI3JGSXmcdnP5d8Fffa2KayOhUUqr/AiBnG1Gl7+7ut/oyagVeSkh7bxQ0zSXV9ptRh/4N15nkCqnpw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - - '@typescript-eslint/types@8.15.0': - resolution: {integrity: sha512-n3Gt8Y/KyJNe0S3yDCD2RVKrHBC4gTUcLTebVBXacPy091E6tNspFLKRXlk3hwT4G55nfr1n2AdFqi/XMxzmPQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@typescript-eslint/typescript-estree@8.15.0': - resolution: {integrity: sha512-1eMp2JgNec/niZsR7ioFBlsh/Fk0oJbhaqO0jRyQBMgkz7RrFfkqF9lYYmBoGBaSiLnu8TAPQTwoTUiSTUW9dg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - - '@typescript-eslint/utils@8.15.0': - resolution: {integrity: sha512-k82RI9yGhr0QM3Dnq+egEpz9qB6Un+WLYhmoNcvl8ltMEededhh7otBVVIDDsEEttauwdY/hQoSsOv13lxrFzQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - - '@typescript-eslint/visitor-keys@8.15.0': - resolution: {integrity: sha512-h8vYOulWec9LhpwfAdZf2bjr8xIp0KNKnpgqSz0qqYYKAW/QZKw3ktRndbiAtUz4acH4QLQavwZBYCc0wulA/Q==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@vitejs/plugin-react-swc@3.7.1': - resolution: {integrity: sha512-vgWOY0i1EROUK0Ctg1hwhtC3SdcDjZcdit4Ups4aPkDcB1jYhmo+RMYWY87cmXMhvtD5uf8lV89j2w16vkdSVg==} - peerDependencies: - vite: ^4 || ^5 - - abbrev@1.1.1: - resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} - - abort-controller@3.0.0: - resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} - engines: {node: '>=6.5'} - - acorn-jsx@5.3.2: - resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - - acorn@8.14.0: - resolution: {integrity: sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==} - engines: {node: '>=0.4.0'} - hasBin: true - - agent-base@6.0.2: - resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} - engines: {node: '>= 6.0.0'} - - ajv@6.12.6: - resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} - - ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} - - ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} - - anymatch@3.1.3: - resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} - engines: {node: '>= 8'} - - aproba@2.0.0: - resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==} - - are-we-there-yet@2.0.0: - resolution: {integrity: sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==} - engines: {node: '>=10'} - deprecated: This package is no longer supported. - - argparse@2.0.1: - resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - - attr-accept@2.2.5: - resolution: {integrity: sha512-0bDNnY/u6pPwHDMoF0FieU354oBi0a8rD9FcsLwzcGWbc8KS8KPIi7y+s13OlVY+gMWc/9xEMUgNE6Qm8ZllYQ==} - engines: {node: '>=4'} - - balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - - base64-js@1.5.1: - resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - - binary-extensions@2.3.0: - resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} - engines: {node: '>=8'} - - bl@6.1.6: - resolution: {integrity: sha512-jLsPgN/YSvPUg9UX0Kd73CXpm2Psg9FxMeCSXnk3WBO3CMT10JMwijubhGfHCnFu6TPn1ei3b975dxv7K2pWVg==} - - bootstrap@5.3.3: - resolution: {integrity: sha512-8HLCdWgyoMguSO9o+aH+iuZ+aht+mzW0u3HIMzVu7Srrpv7EBBxTnrFlSCskwdY1+EOFQSm7uMJhNQHkdPcmjg==} - peerDependencies: - '@popperjs/core': ^2.11.8 - - brace-expansion@1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - - brace-expansion@2.0.1: - resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} - - braces@3.0.3: - resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} - engines: {node: '>=8'} - - broker-factory@3.1.14: - resolution: {integrity: sha512-L45k5HMbPIrMid0nTOZ/UPXG/c0aRuQKVrSDFIb1zOkvfiyHgYmIjc3cSiN1KwQIvRDOtKE0tfb3I9EZ3CmpQQ==} - - buffer-builder@0.2.0: - resolution: {integrity: sha512-7VPMEPuYznPSoR21NE1zvd2Xna6c/CloiZCfcMXR1Jny6PjX0N4Nsa38zcBFo/FMK+BlA+FLKbJCQ0i2yxp+Xg==} - - buffer-from@1.1.2: - resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} - - buffer@6.0.3: - resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} - - callsites@3.1.0: - resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} - engines: {node: '>=6'} - - canvas@2.11.2: - resolution: {integrity: sha512-ItanGBMrmRV7Py2Z+Xhs7cT+FNt5K0vPL4p9EZ/UX/Mu7hFbkxSjKF2KVtPwX7UYWp7dRKnrTvReflgrItJbdw==} - engines: {node: '>=6'} - - chalk@4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} - engines: {node: '>=10'} - - chokidar@3.6.0: - resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} - engines: {node: '>= 8.10.0'} - - chownr@2.0.0: - resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} - engines: {node: '>=10'} - - classnames@2.5.1: - resolution: {integrity: sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==} - - clsx@2.1.1: - resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} - engines: {node: '>=6'} - - color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} - - color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - - color-support@1.1.3: - resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} - hasBin: true - - colorjs.io@0.5.2: - resolution: {integrity: sha512-twmVoizEW7ylZSN32OgKdXRmo1qg+wT5/6C3xu5b9QsWzSFAhHLn2xd8ro0diCsKfCj1RdaTP/nrcW+vAoQPIw==} - - commist@3.2.0: - resolution: {integrity: sha512-4PIMoPniho+LqXmpS5d3NuGYncG6XWlkBSVGiWycL22dd42OYdUGil2CWuzklaJoNxyxUSpO4MKIBU94viWNAw==} - - concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - - concat-stream@2.0.0: - resolution: {integrity: sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==} - engines: {'0': node >= 6.0} - - console-control-strings@1.1.0: - resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==} - - cross-spawn@7.0.6: - resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} - engines: {node: '>= 8'} - - csstype@3.1.3: - resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} - - debug@4.3.7: - resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - - debug@4.4.3: - resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - - decompress-response@4.2.1: - resolution: {integrity: sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==} - engines: {node: '>=8'} - - deep-is@0.1.4: - resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} - - delegates@1.0.0: - resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==} - - dequal@2.0.3: - resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} - engines: {node: '>=6'} - - detect-libc@2.0.3: - resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} - engines: {node: '>=8'} - - dnd-core@14.0.1: - resolution: {integrity: sha512-+PVS2VPTgKFPYWo3vAFEA8WPbTf7/xo43TifH9G8S1KqnrQu0o77A3unrF5yOugy4mIz7K5wAVFHUcha7wsz6A==} - - dom-helpers@5.2.1: - resolution: {integrity: sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==} - - emoji-regex@8.0.0: - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - - esbuild@0.21.5: - resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} - engines: {node: '>=12'} - hasBin: true - - escape-string-regexp@4.0.0: - resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} - engines: {node: '>=10'} - - eslint-plugin-react-hooks@5.0.0: - resolution: {integrity: sha512-hIOwI+5hYGpJEc4uPRmz2ulCjAGD/N13Lukkh8cLV0i2IRk/bdZDYjgLVHj+U9Z704kLIdIO6iueGvxNur0sgw==} - engines: {node: '>=10'} - peerDependencies: - eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 - - eslint-plugin-react-refresh@0.4.14: - resolution: {integrity: sha512-aXvzCTK7ZBv1e7fahFuR3Z/fyQQSIQ711yPgYRj+Oj64tyTgO4iQIDmYXDBqvSWQ/FA4OSCsXOStlF+noU0/NA==} - peerDependencies: - eslint: '>=7' - - eslint-scope@8.2.0: - resolution: {integrity: sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - eslint-visitor-keys@3.4.3: - resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - - eslint-visitor-keys@4.2.0: - resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - eslint@9.15.0: - resolution: {integrity: sha512-7CrWySmIibCgT1Os28lUU6upBshZ+GxybLOrmRzi08kS8MBuO8QA7pXEgYgY5W8vK3e74xv0lpjo9DbaGU9Rkw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - hasBin: true - peerDependencies: - jiti: '*' - peerDependenciesMeta: - jiti: - optional: true - - espree@10.3.0: - resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - esquery@1.6.0: - resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} - engines: {node: '>=0.10'} - - esrecurse@4.3.0: - resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} - engines: {node: '>=4.0'} - - estraverse@5.3.0: - resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} - engines: {node: '>=4.0'} - - esutils@2.0.3: - resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} - engines: {node: '>=0.10.0'} - - event-target-shim@5.0.1: - resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} - engines: {node: '>=6'} - - events@3.3.0: - resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} - engines: {node: '>=0.8.x'} - - fast-deep-equal@3.1.3: - resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - - fast-glob@3.3.2: - resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} - engines: {node: '>=8.6.0'} - - fast-json-stable-stringify@2.1.0: - resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - - fast-levenshtein@2.0.6: - resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} - - fast-unique-numbers@9.0.27: - resolution: {integrity: sha512-nDA9ADeINN8SA2u2wCtU+siWFTTDqQR37XvgPIDDmboWQeExz7X0mImxuaN+kJddliIqy2FpVRmnvRZ+j8i1/A==} - engines: {node: '>=18.2.0'} - - fastq@1.17.1: - resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} - - file-entry-cache@8.0.0: - resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} - engines: {node: '>=16.0.0'} - - file-selector@2.1.0: - resolution: {integrity: sha512-ZuXAqGePcSPz4JuerOY06Dzzq0hrmQ6VGoXVzGyFI1npeOfBgqGIKKpznfYWRkSLJlXutkqVC5WvGZtkFVhu9Q==} - engines: {node: '>= 12'} - - fill-range@7.1.1: - resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} - engines: {node: '>=8'} - - find-up@5.0.0: - resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} - engines: {node: '>=10'} - - flat-cache@4.0.1: - resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} - engines: {node: '>=16'} - - flatted@3.3.2: - resolution: {integrity: sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==} - - fs-minipass@2.1.0: - resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} - engines: {node: '>= 8'} - - fs.realpath@1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - - fsevents@2.3.3: - resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - - gauge@3.0.2: - resolution: {integrity: sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==} - engines: {node: '>=10'} - deprecated: This package is no longer supported. - - glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} - - glob-parent@6.0.2: - resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} - engines: {node: '>=10.13.0'} - - glob@7.2.3: - resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - deprecated: Glob versions prior to v9 are no longer supported - - globals@14.0.0: - resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} - engines: {node: '>=18'} - - globals@15.12.0: - resolution: {integrity: sha512-1+gLErljJFhbOVyaetcwJiJ4+eLe45S2E7P5UiZ9xGfeq3ATQf5DOv9G7MH3gGbKQLkzmNh2DxfZwLdw+j6oTQ==} - engines: {node: '>=18'} - - graphemer@1.4.0: - resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} - - has-flag@4.0.0: - resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} - engines: {node: '>=8'} - - has-unicode@2.0.1: - resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==} - - help-me@5.0.0: - resolution: {integrity: sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==} - - history@4.10.1: - resolution: {integrity: sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==} - - hoist-non-react-statics@3.3.2: - resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} - - https-proxy-agent@5.0.1: - resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} - engines: {node: '>= 6'} - - ieee754@1.2.1: - resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} - - ignore@5.3.2: - resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} - engines: {node: '>= 4'} - - immutable@4.3.7: - resolution: {integrity: sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw==} - - immutable@5.0.3: - resolution: {integrity: sha512-P8IdPQHq3lA1xVeBRi5VPqUm5HDgKnx0Ru51wZz5mjxHr5n3RWhjIpOFU7ybkUxfB+5IToy+OLaHYDBIWsv+uw==} - - import-fresh@3.3.0: - resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} - engines: {node: '>=6'} - - imurmurhash@0.1.4: - resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} - engines: {node: '>=0.8.19'} - - inflight@1.0.6: - resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} - deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. - - inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - - invariant@2.2.4: - resolution: {integrity: sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==} - - ip-address@10.1.0: - resolution: {integrity: sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==} - engines: {node: '>= 12'} - - is-binary-path@2.1.0: - resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} - engines: {node: '>=8'} - - is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} - - is-fullwidth-code-point@3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} - - is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} - - is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - - isarray@0.0.1: - resolution: {integrity: sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==} - - isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - - js-sdsl@4.3.0: - resolution: {integrity: sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==} - - js-tokens@4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - - js-yaml@4.1.0: - resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} - hasBin: true - - json-buffer@3.0.1: - resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} - - json-schema-traverse@0.4.1: - resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} - - json-stable-stringify-without-jsonify@1.0.1: - resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} - - jwt-decode@4.0.0: - resolution: {integrity: sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==} - engines: {node: '>=18'} - - keyv@4.5.4: - resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} - - levn@0.4.1: - resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} - engines: {node: '>= 0.8.0'} - - locate-path@6.0.0: - resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} - engines: {node: '>=10'} - - lodash.merge@4.6.2: - resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - - loose-envify@1.4.0: - resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} - hasBin: true - - lru-cache@10.4.3: - resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} - - make-cancellable-promise@1.3.2: - resolution: {integrity: sha512-GCXh3bq/WuMbS+Ky4JBPW1hYTOU+znU+Q5m9Pu+pI8EoUqIHk9+tviOKC6/qhHh8C4/As3tzJ69IF32kdz85ww==} - - make-dir@3.1.0: - resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} - engines: {node: '>=8'} - - make-event-props@1.6.2: - resolution: {integrity: sha512-iDwf7mA03WPiR8QxvcVHmVWEPfMY1RZXerDVNCRYW7dUr2ppH3J58Rwb39/WG39yTZdRSxr3x+2v22tvI0VEvA==} - - memoize-one@5.2.1: - resolution: {integrity: sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==} - - merge-refs@1.3.0: - resolution: {integrity: sha512-nqXPXbso+1dcKDpPCXvwZyJILz+vSLqGGOnDrYHQYE+B8n9JTCekVLC65AfCpR4ggVyA/45Y0iR9LDyS2iI+zA==} - peerDependencies: - '@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - peerDependenciesMeta: - '@types/react': - optional: true - - merge2@1.4.1: - resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} - engines: {node: '>= 8'} - - micromatch@4.0.8: - resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} - engines: {node: '>=8.6'} - - mimic-response@2.1.0: - resolution: {integrity: sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==} - engines: {node: '>=8'} - - minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - - minimatch@9.0.5: - resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} - engines: {node: '>=16 || 14 >=14.17'} - - minimist@1.2.8: - resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - - minipass@3.3.6: - resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} - engines: {node: '>=8'} - - minipass@5.0.0: - resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} - engines: {node: '>=8'} - - minizlib@2.1.2: - resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} - engines: {node: '>= 8'} - - mkdirp@1.0.4: - resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} - engines: {node: '>=10'} - hasBin: true - - moment@2.30.1: - resolution: {integrity: sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==} - - mqtt-packet@9.0.2: - resolution: {integrity: sha512-MvIY0B8/qjq7bKxdN1eD+nrljoeaai+qjLJgfRn3TiMuz0pamsIWY2bFODPZMSNmabsLANXsLl4EMoWvlaTZWA==} - - mqtt@5.15.1: - resolution: {integrity: sha512-V1WnkGuJh3ec9QXzy5Iylw8OOBK+Xu1WhxcQ9mMpLThG+/JZIMV1PgLNRgIiqXhZnvnVLsuyxHl5A/3bHHbcAA==} - engines: {node: '>=16.0.0'} - hasBin: true - - ms@2.1.3: - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - - nan@2.22.0: - resolution: {integrity: sha512-nbajikzWTMwsW+eSsNm3QwlOs7het9gGJU5dDZzRTQGk03vyBOauxgI4VakDzE0PtsGTmXPsXTbbjVhRwR5mpw==} - - nanoid@3.3.11: - resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} - hasBin: true - - natural-compare@1.4.0: - resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - - node-fetch@2.7.0: - resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} - engines: {node: 4.x || >=6.0.0} - peerDependencies: - encoding: ^0.1.0 - peerDependenciesMeta: - encoding: - optional: true - - nopt@5.0.0: - resolution: {integrity: sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==} - engines: {node: '>=6'} - hasBin: true - - normalize-path@3.0.0: - resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} - engines: {node: '>=0.10.0'} - - npmlog@5.0.1: - resolution: {integrity: sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==} - deprecated: This package is no longer supported. - - number-allocator@1.0.14: - resolution: {integrity: sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==} - - object-assign@4.1.1: - resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} - engines: {node: '>=0.10.0'} - - once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - - optionator@0.9.4: - resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} - engines: {node: '>= 0.8.0'} - - p-limit@3.1.0: - resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} - engines: {node: '>=10'} - - p-locate@5.0.0: - resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} - engines: {node: '>=10'} - - pako@1.0.11: - resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} - - parent-module@1.0.1: - resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} - engines: {node: '>=6'} - - path-exists@4.0.0: - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} - engines: {node: '>=8'} - - path-is-absolute@1.0.1: - resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} - engines: {node: '>=0.10.0'} - - path-key@3.1.1: - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} - engines: {node: '>=8'} - - path-to-regexp@1.9.0: - resolution: {integrity: sha512-xIp7/apCFJuUHdDLWe8O1HIkb0kQrOMb/0u6FXQjemHn/ii5LrIzU6bdECnsiTF/GjZkMEKg1xdiZwNqDYlZ6g==} - - path2d@0.2.2: - resolution: {integrity: sha512-+vnG6S4dYcYxZd+CZxzXCNKdELYZSKfohrk98yajCo1PtRoDgCTrrwOvK1GT0UoAdVszagDVllQc0U1vaX4NUQ==} - engines: {node: '>=6'} - - pdfjs-dist@4.4.168: - resolution: {integrity: sha512-MbkAjpwka/dMHaCfQ75RY1FXX3IewBVu6NGZOcxerRFlaBiIkZmUoR0jotX5VUzYZEXAGzSFtknWs5xRKliXPA==} - engines: {node: '>=18'} - - picocolors@1.1.1: - resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} - - picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - - postcss@8.5.6: - resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} - engines: {node: ^10 || ^12 || >=14} - - prelude-ls@1.2.1: - resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} - engines: {node: '>= 0.8.0'} - - process-nextick-args@2.0.1: - resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} - - process@0.11.10: - resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} - engines: {node: '>= 0.6.0'} - - prop-types-extra@1.1.1: - resolution: {integrity: sha512-59+AHNnHYCdiC+vMwY52WmvP5dM3QLeoumYuEyceQDi9aEhtwN9zIQ2ZNo25sMyXnbh32h+P1ezDsUpUH3JAew==} - peerDependencies: - react: '>=0.14.0' - - prop-types@15.8.1: - resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} - - punycode@2.3.1: - resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} - engines: {node: '>=6'} - - queue-microtask@1.2.3: - resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - - react-arborist@3.4.0: - resolution: {integrity: sha512-QI46oRGXJr0oaQfqqVobIiIoqPp5Y5gM69D2A2P7uHVif+X75XWnScR5drC7YDKgJ4CXVaDeFwnYKOWRRfncMg==} - peerDependencies: - react: '>= 16.14' - react-dom: '>= 16.14' - - react-bootstrap@2.10.5: - resolution: {integrity: sha512-XueAOEn64RRkZ0s6yzUTdpFtdUXs5L5491QU//8ZcODKJNDLt/r01tNyriZccjgRImH1REynUc9pqjiRMpDLWQ==} - peerDependencies: - '@types/react': '>=16.14.8' - react: '>=16.14.0' - react-dom: '>=16.14.0' - peerDependenciesMeta: - '@types/react': - optional: true - - react-dnd-html5-backend@14.1.0: - resolution: {integrity: sha512-6ONeqEC3XKVf4eVmMTe0oPds+c5B9Foyj8p/ZKLb7kL2qh9COYxiBHv3szd6gztqi/efkmriywLUVlPotqoJyw==} - - react-dnd@14.0.5: - resolution: {integrity: sha512-9i1jSgbyVw0ELlEVt/NkCUkxy1hmhJOkePoCH713u75vzHGyXhPDm28oLfc2NMSBjZRM1Y+wRjHXJT3sPrTy+A==} - peerDependencies: - '@types/hoist-non-react-statics': '>= 3.3.1' - '@types/node': '>= 12' - '@types/react': '>= 16' - react: '>= 16.14' - peerDependenciesMeta: - '@types/hoist-non-react-statics': - optional: true - '@types/node': - optional: true - '@types/react': - optional: true - - react-dom@18.3.1: - resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==} - peerDependencies: - react: ^18.3.1 - - react-dropzone@14.3.5: - resolution: {integrity: sha512-9nDUaEEpqZLOz5v5SUcFA0CjM4vq8YbqO0WRls+EYT7+DvxUdzDPKNCPLqGfj3YL9MsniCLCD4RFA6M95V6KMQ==} - engines: {node: '>= 10.13'} - peerDependencies: - react: '>= 16.8 || 18.0.0' - - react-icons@5.3.0: - resolution: {integrity: sha512-DnUk8aFbTyQPSkCfF8dbX6kQjXA9DktMeJqfjrg6cK9vwQVMxmcA3BfP4QoiztVmEHtwlTgLFsPuH2NskKT6eg==} - peerDependencies: - react: '*' - - react-is@16.13.1: - resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} - - react-lifecycles-compat@3.0.4: - resolution: {integrity: sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==} - - react-pdf@9.1.1: - resolution: {integrity: sha512-Cn3RTJZMqVOOCgLMRXDamLk4LPGfyB2Np3OwQAUjmHIh47EpuGW1OpAA1Z1GVDLoHx4d5duEDo/YbUkDbr4QFQ==} - peerDependencies: - '@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - peerDependenciesMeta: - '@types/react': - optional: true - - react-router-dom@5.3.4: - resolution: {integrity: sha512-m4EqFMHv/Ih4kpcBCONHbkT68KoAeHN4p3lAGoNryfHi0dMy0kCzEZakiKRsvg5wHZ/JLrLW8o8KomWiz/qbYQ==} - peerDependencies: - react: '>=15' - - react-router@5.3.4: - resolution: {integrity: sha512-Ys9K+ppnJah3QuaRiLxk+jDWOR1MekYQrlytiXxC1RyfbdsZkS5pvKAzCCr031xHixZwpnsYNT5xysdFHQaYsA==} - peerDependencies: - react: '>=15' - - react-toastify@10.0.6: - resolution: {integrity: sha512-yYjp+omCDf9lhZcrZHKbSq7YMuK0zcYkDFTzfRFgTXkTFHZ1ToxwAonzA4JI5CxA91JpjFLmwEsZEgfYfOqI1A==} - peerDependencies: - react: '>=18' - react-dom: '>=18' - - react-transition-group@4.4.5: - resolution: {integrity: sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==} - peerDependencies: - react: '>=16.6.0' - react-dom: '>=16.6.0' - - react-window@1.8.10: - resolution: {integrity: sha512-Y0Cx+dnU6NLa5/EvoHukUD0BklJ8qITCtVEPY1C/nL8wwoZ0b5aEw8Ff1dOVHw7fCzMt55XfJDd8S8W8LCaUCg==} - engines: {node: '>8.0.0'} - peerDependencies: - react: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 - react-dom: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 - - react@18.3.1: - resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} - engines: {node: '>=0.10.0'} - - readable-stream@3.6.2: - resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} - engines: {node: '>= 6'} - - readable-stream@4.7.0: - resolution: {integrity: sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - - readdirp@3.6.0: - resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} - engines: {node: '>=8.10.0'} - - redux@4.2.1: - resolution: {integrity: sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==} - - redux@5.0.1: - resolution: {integrity: sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==} - - regenerator-runtime@0.14.1: - resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} - - resolve-from@4.0.0: - resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} - engines: {node: '>=4'} - - resolve-pathname@3.0.0: - resolution: {integrity: sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==} - - reusify@1.0.4: - resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} - engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - - rfdc@1.4.1: - resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} - - rimraf@3.0.2: - resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} - deprecated: Rimraf versions prior to v4 are no longer supported - hasBin: true - - rollup@4.44.1: - resolution: {integrity: sha512-x8H8aPvD+xbl0Do8oez5f5o8eMS3trfCghc4HhLAnCkj7Vl0d1JWGs0UF/D886zLW2rOj2QymV/JcSSsw+XDNg==} - engines: {node: '>=18.0.0', npm: '>=8.0.0'} - hasBin: true - - run-parallel@1.2.0: - resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} - - rxjs@7.8.1: - resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==} - - safe-buffer@5.2.1: - resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - - sass-embedded-android-arm64@1.81.0: - resolution: {integrity: sha512-I36P77/PKAHx6sqOmexO2iEY5kpsmQ1VxcgITZSOxPMQhdB6m4t3bTabfDuWQQmCrqqiNFtLQHeytB65bUqwiw==} - engines: {node: '>=14.0.0'} - cpu: [arm64] - os: [android] - - sass-embedded-android-arm@1.81.0: - resolution: {integrity: sha512-NWEmIuaIEsGFNsIRa+5JpIpPJyZ32H15E85CNZqEIhhwWlk9UNw7vlOCmTH8MtabtnACwC/2NG8VyNa3nxKzUQ==} - engines: {node: '>=14.0.0'} - cpu: [arm] - os: [android] - - sass-embedded-android-ia32@1.81.0: - resolution: {integrity: sha512-k8V1usXw30w1GVxvrteG1RzgYJzYQ9PfL2aeOqGdroBN7zYTD9VGJXTGcxA4IeeRxmRd7szVW2mKXXS472fh8g==} - engines: {node: '>=14.0.0'} - cpu: [ia32] - os: [android] - - sass-embedded-android-riscv64@1.81.0: - resolution: {integrity: sha512-RXlanyLXEpN/DEehXgLuKPsqT//GYlsGFxKXgRiCc8hIPAueFLQXKJmLWlL3BEtHgmFdbsStIu4aZCcb1hOFlQ==} - engines: {node: '>=14.0.0'} - cpu: [riscv64] - os: [android] - - sass-embedded-android-x64@1.81.0: - resolution: {integrity: sha512-RQG0FxGQ1DERNyUDED8+BDVaLIjI+BNg8lVcyqlLZUrWY6NhzjwYEeiN/DNZmMmHtqDucAPNDcsdVUNQqsBy2A==} - engines: {node: '>=14.0.0'} - cpu: [x64] - os: [android] - - sass-embedded-darwin-arm64@1.81.0: - resolution: {integrity: sha512-gLKbsfII9Ppua76N41ODFnKGutla9qv0OGAas8gxe0jYBeAQFi/1iKQYdNtQtKi4mA9n5TQTqz+HHCKszZCoyA==} - engines: {node: '>=14.0.0'} - cpu: [arm64] - os: [darwin] - - sass-embedded-darwin-x64@1.81.0: - resolution: {integrity: sha512-7uMOlT9hD2KUJCbTN2XcfghDxt/rc50ujjfSjSHjX1SYj7mGplkINUXvVbbvvaV2wt6t9vkGkCo5qNbeBhfwBg==} - engines: {node: '>=14.0.0'} - cpu: [x64] - os: [darwin] - - sass-embedded-linux-arm64@1.81.0: - resolution: {integrity: sha512-jy4bvhdUmqbyw1jv1f3Uxl+MF8EU/Y/GDx4w6XPJm4Ds+mwH/TwnyAwsxxoBhWfnBnW8q2ADy039DlS5p+9csQ==} - engines: {node: '>=14.0.0'} - cpu: [arm64] - os: [linux] - - sass-embedded-linux-arm@1.81.0: - resolution: {integrity: sha512-REqR9qM4RchCE3cKqzRy9Q4zigIV82SbSpCi/O4O3oK3pg2I1z7vkb3TiJsivusG/li7aqKZGmYOtAXjruGQDA==} - engines: {node: '>=14.0.0'} - cpu: [arm] - os: [linux] - - sass-embedded-linux-ia32@1.81.0: - resolution: {integrity: sha512-ga/Jk4q5Bn1aC+iHJteDZuLSKnmBUiS3dEg1fnl/Z7GaHIChceKDJOw0zNaILRXI0qT2E1at9MwzoRaRA5Nn/g==} - engines: {node: '>=14.0.0'} - cpu: [ia32] - os: [linux] - - sass-embedded-linux-musl-arm64@1.81.0: - resolution: {integrity: sha512-hpntWf5kjkoxncA1Vh8vhsUOquZ8AROZKx0rQh7ZjSRs4JrYZASz1cfevPKaEM3wIim/nYa6TJqm0VqWsrERlA==} - engines: {node: '>=14.0.0'} - cpu: [arm64] - os: [linux] - - sass-embedded-linux-musl-arm@1.81.0: - resolution: {integrity: sha512-oWVUvQ4d5Kx1Md75YXZl5z1WBjc+uOhfRRqzkJ3nWc8tjszxJN+y/5EOJavhsNI3/2yoTt6eMXRTqDD9b0tWSQ==} - engines: {node: '>=14.0.0'} - cpu: [arm] - os: [linux] - - sass-embedded-linux-musl-ia32@1.81.0: - resolution: {integrity: sha512-UEXUYkBuqTSwg5JNWiNlfMZ1Jx6SJkaEdx+fsL3Tk099L8cKSoJWH2EPz4ZJjNbyIMymrSdVfymheTeZ8u24xA==} - engines: {node: '>=14.0.0'} - cpu: [ia32] - os: [linux] - - sass-embedded-linux-musl-riscv64@1.81.0: - resolution: {integrity: sha512-1D7OznytbIhx2XDHWi1nuQ8d/uCVR7FGGzELgaU//T8A9DapVTUgPKvB70AF1k4GzChR9IXU/WvFZs2hDTbaJg==} - engines: {node: '>=14.0.0'} - cpu: [riscv64] - os: [linux] - - sass-embedded-linux-musl-x64@1.81.0: - resolution: {integrity: sha512-ia6VCTeVDQtBSMktXRFza1AZCt8/6aUoujot6Ugf4KmdytQqPJIHxkHaGftm5xwi9WdrMGYS7zgolToPijR11A==} - engines: {node: '>=14.0.0'} - cpu: [x64] - os: [linux] - - sass-embedded-linux-riscv64@1.81.0: - resolution: {integrity: sha512-KbxSsqu4tT1XbhZfJV/5NfW0VtJIGlD58RjqJqJBi8Rnjrx29/upBsuwoDWtsPV/LhoGwwU1XkSa9Q1ifCz4fQ==} - engines: {node: '>=14.0.0'} - cpu: [riscv64] - os: [linux] - - sass-embedded-linux-x64@1.81.0: - resolution: {integrity: sha512-AMDeVY2T9WAnSFkuQcsOn5c29GRs/TuqnCiblKeXfxCSKym5uKdBl/N7GnTV6OjzoxiJBbkYKdVIaS5By7Gj4g==} - engines: {node: '>=14.0.0'} - cpu: [x64] - os: [linux] - - sass-embedded-win32-arm64@1.81.0: - resolution: {integrity: sha512-YOmBRYnygwWUmCoH14QbMRHjcvCJufeJBAp0m61tOJXIQh64ziwV4mjdqjS/Rx3zhTT4T+nulDUw4d3kLiMncA==} - engines: {node: '>=14.0.0'} - cpu: [arm64] - os: [win32] - - sass-embedded-win32-ia32@1.81.0: - resolution: {integrity: sha512-HFfr/C+uLJGGTENdnssuNTmXI/xnIasUuEHEKqI+2J0FHCWT5cpz3PGAOHymPyJcZVYGUG/7gIxIx/d7t0LFYw==} - engines: {node: '>=14.0.0'} - cpu: [ia32] - os: [win32] - - sass-embedded-win32-x64@1.81.0: - resolution: {integrity: sha512-wxj52jDcIAwWcXb7ShZ7vQYKcVUkJ+04YM9l46jDY+qwHzliGuorAUyujLyKTE9heGD3gShJ3wPPC1lXzq6v9A==} - engines: {node: '>=14.0.0'} - cpu: [x64] - os: [win32] - - sass-embedded@1.81.0: - resolution: {integrity: sha512-uZQ2Faxb1oWBHpeSSzjxnhClbMb3QadN0ql0ZFNuqWOLUxwaVhrMlMhPq6TDPbbfDUjihuwrMCuy695Bgna5RA==} - engines: {node: '>=16.0.0'} - hasBin: true - - sass@1.77.6: - resolution: {integrity: sha512-ByXE1oLD79GVq9Ht1PeHWCPMPB8XHpBuz1r85oByKHjZY6qV6rWnQovQzXJXuQ/XyE1Oj3iPk3lo28uzaRA2/Q==} - engines: {node: '>=14.0.0'} - hasBin: true - - scheduler@0.23.2: - resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==} - - semver@6.3.1: - resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} - hasBin: true - - semver@7.6.3: - resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} - engines: {node: '>=10'} - hasBin: true - - set-blocking@2.0.0: - resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} - - shebang-command@2.0.0: - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} - engines: {node: '>=8'} - - shebang-regex@3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} - - signal-exit@3.0.7: - resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} - - simple-concat@1.0.1: - resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==} - - simple-get@3.1.1: - resolution: {integrity: sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==} - - smart-buffer@4.2.0: - resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} - engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} - - socks@2.8.7: - resolution: {integrity: sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==} - engines: {node: '>= 10.0.0', npm: '>= 3.0.0'} - - source-map-js@1.2.1: - resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} - engines: {node: '>=0.10.0'} - - split2@4.2.0: - resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} - engines: {node: '>= 10.x'} - - string-width@4.2.3: - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} - engines: {node: '>=8'} - - string_decoder@1.3.0: - resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} - - strip-ansi@6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} - - strip-json-comments@3.1.1: - resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} - engines: {node: '>=8'} - - supports-color@7.2.0: - resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} - engines: {node: '>=8'} - - supports-color@8.1.1: - resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} - engines: {node: '>=10'} - - sync-child-process@1.0.2: - resolution: {integrity: sha512-8lD+t2KrrScJ/7KXCSyfhT3/hRq78rC0wBFqNJXv3mZyn6hW2ypM05JmlSvtqRbeq6jqA94oHbxAr2vYsJ8vDA==} - engines: {node: '>=16.0.0'} - - sync-message-port@1.1.3: - resolution: {integrity: sha512-GTt8rSKje5FilG+wEdfCkOcLL7LWqpMlr2c3LRuKt/YXxcJ52aGSbGBAdI4L3aaqfrBt6y711El53ItyH1NWzg==} - engines: {node: '>=16.0.0'} - - tar@6.2.1: - resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} - engines: {node: '>=10'} - - tiny-invariant@1.3.3: - resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} - - tiny-warning@1.0.3: - resolution: {integrity: sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==} - - to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} - - tr46@0.0.3: - resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} - - ts-api-utils@1.4.0: - resolution: {integrity: sha512-032cPxaEKwM+GT3vA5JXNzIaizx388rhsSW79vGRNGXfRRAdEAn2mvk36PvK5HnOchyWZ7afLEXqYCvPCrzuzQ==} - engines: {node: '>=16'} - peerDependencies: - typescript: '>=4.2.0' - - tslib@2.8.1: - resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} - - type-check@0.4.0: - resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} - engines: {node: '>= 0.8.0'} - - typedarray@0.0.6: - resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} - - typescript-eslint@8.15.0: - resolution: {integrity: sha512-wY4FRGl0ZI+ZU4Jo/yjdBu0lVTSML58pu6PgGtJmCufvzfV565pUF6iACQt092uFOd49iLOTX/sEVmHtbSrS+w==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - - typescript@5.6.3: - resolution: {integrity: sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==} - engines: {node: '>=14.17'} - hasBin: true - - uncontrollable@7.2.1: - resolution: {integrity: sha512-svtcfoTADIB0nT9nltgjujTi7BzVmwjZClOmskKu/E8FW9BXzg9os8OLr4f8Dlnk0rYWJIWr4wv9eKUXiQvQwQ==} - peerDependencies: - react: '>=15.0.0' - - uncontrollable@8.0.4: - resolution: {integrity: sha512-ulRWYWHvscPFc0QQXvyJjY6LIXU56f0h8pQFvhxiKk5V1fcI8gp9Ht9leVAhrVjzqMw0BgjspBINx9r6oyJUvQ==} - peerDependencies: - react: '>=16.14.0' - - undici-types@7.18.2: - resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==} - - uri-js@4.4.1: - resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - - use-sync-external-store@1.2.2: - resolution: {integrity: sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - - util-deprecate@1.0.2: - resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - - value-equal@1.0.1: - resolution: {integrity: sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==} - - varint@6.0.0: - resolution: {integrity: sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==} - - vite@5.4.19: - resolution: {integrity: sha512-qO3aKv3HoQC8QKiNSTuUM1l9o/XX3+c+VTgLHbJWHZGeTPVAg2XwazI9UWzoxjIJCGCV2zU60uqMzjeLZuULqA==} - engines: {node: ^18.0.0 || >=20.0.0} - hasBin: true - peerDependencies: - '@types/node': ^18.0.0 || >=20.0.0 - less: '*' - lightningcss: ^1.21.0 - sass: '*' - sass-embedded: '*' - stylus: '*' - sugarss: '*' - terser: ^5.4.0 - peerDependenciesMeta: - '@types/node': - optional: true - less: - optional: true - lightningcss: - optional: true - sass: - optional: true - sass-embedded: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true - - warning@4.0.3: - resolution: {integrity: sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==} - - webidl-conversions@3.0.1: - resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} - - whatwg-url@5.0.0: - resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} - - which@2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true - - wide-align@1.1.5: - resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} - - word-wrap@1.2.5: - resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} - engines: {node: '>=0.10.0'} - - worker-factory@7.0.49: - resolution: {integrity: sha512-lW7tpgy6aUv2dFsQhv1yv+XFzdkCf/leoKRTGMPVK5/die6RrUjqgJHJf556qO+ZfytNG6wPXc17E8zzsOLUDw==} - - worker-timers-broker@8.0.16: - resolution: {integrity: sha512-JyP3AvUGyPGbBGW7XiUewm2+0pN/aYo1QpVf5kdXAfkDZcN3p7NbWrG6XnyDEpDIvfHk/+LCnOW/NsuiU9riYA==} - - worker-timers-worker@9.0.14: - resolution: {integrity: sha512-/qF06C60sXmSLfUl7WglvrDIbspmPOM8UrG63Dnn4bi2x4/DfqHS/+dxF5B+MdHnYO5tVuZYLHdAodrKdabTIg==} - - worker-timers@8.0.31: - resolution: {integrity: sha512-ngkq5S6JuZyztom8tDgBzorLo9byhBMko/sXfgiUD945AuzKGg1GCgDMCC3NaYkicLpGKXutONM36wEX8UbBCA==} - - wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - - ws@8.20.0: - resolution: {integrity: sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==} - engines: {node: '>=10.0.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: '>=5.0.2' - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - - yallist@4.0.0: - resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - - yocto-queue@0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} - engines: {node: '>=10'} - -snapshots: - - '@babel/runtime@7.26.0': - dependencies: - regenerator-runtime: 0.14.1 - - '@babel/runtime@7.29.2': {} - - '@bufbuild/protobuf@2.2.2': {} - - '@esbuild/aix-ppc64@0.21.5': - optional: true - - '@esbuild/android-arm64@0.21.5': - optional: true - - '@esbuild/android-arm@0.21.5': - optional: true - - '@esbuild/android-x64@0.21.5': - optional: true - - '@esbuild/darwin-arm64@0.21.5': - optional: true - - '@esbuild/darwin-x64@0.21.5': - optional: true - - '@esbuild/freebsd-arm64@0.21.5': - optional: true - - '@esbuild/freebsd-x64@0.21.5': - optional: true - - '@esbuild/linux-arm64@0.21.5': - optional: true - - '@esbuild/linux-arm@0.21.5': - optional: true - - '@esbuild/linux-ia32@0.21.5': - optional: true - - '@esbuild/linux-loong64@0.21.5': - optional: true - - '@esbuild/linux-mips64el@0.21.5': - optional: true - - '@esbuild/linux-ppc64@0.21.5': - optional: true - - '@esbuild/linux-riscv64@0.21.5': - optional: true - - '@esbuild/linux-s390x@0.21.5': - optional: true - - '@esbuild/linux-x64@0.21.5': - optional: true - - '@esbuild/netbsd-x64@0.21.5': - optional: true - - '@esbuild/openbsd-x64@0.21.5': - optional: true - - '@esbuild/sunos-x64@0.21.5': - optional: true - - '@esbuild/win32-arm64@0.21.5': - optional: true - - '@esbuild/win32-ia32@0.21.5': - optional: true - - '@esbuild/win32-x64@0.21.5': - optional: true - - '@eslint-community/eslint-utils@4.4.1(eslint@9.15.0)': - dependencies: - eslint: 9.15.0 - eslint-visitor-keys: 3.4.3 - - '@eslint-community/regexpp@4.12.1': {} - - '@eslint/config-array@0.19.0': - dependencies: - '@eslint/object-schema': 2.1.4 - debug: 4.3.7 - minimatch: 3.1.2 - transitivePeerDependencies: - - supports-color - - '@eslint/core@0.9.0': {} - - '@eslint/eslintrc@3.2.0': - dependencies: - ajv: 6.12.6 - debug: 4.3.7 - espree: 10.3.0 - globals: 14.0.0 - ignore: 5.3.2 - import-fresh: 3.3.0 - js-yaml: 4.1.0 - minimatch: 3.1.2 - strip-json-comments: 3.1.1 - transitivePeerDependencies: - - supports-color - - '@eslint/js@9.15.0': {} - - '@eslint/object-schema@2.1.4': {} - - '@eslint/plugin-kit@0.2.3': - dependencies: - levn: 0.4.1 - - '@humanfs/core@0.19.1': {} - - '@humanfs/node@0.16.6': - dependencies: - '@humanfs/core': 0.19.1 - '@humanwhocodes/retry': 0.3.1 - - '@humanwhocodes/module-importer@1.0.1': {} - - '@humanwhocodes/retry@0.3.1': {} - - '@humanwhocodes/retry@0.4.1': {} - - '@mapbox/node-pre-gyp@1.0.11': - dependencies: - detect-libc: 2.0.3 - https-proxy-agent: 5.0.1 - make-dir: 3.1.0 - node-fetch: 2.7.0 - nopt: 5.0.0 - npmlog: 5.0.1 - rimraf: 3.0.2 - semver: 7.6.3 - tar: 6.2.1 - transitivePeerDependencies: - - encoding - - supports-color - optional: true - - '@nodelib/fs.scandir@2.1.5': - dependencies: - '@nodelib/fs.stat': 2.0.5 - run-parallel: 1.2.0 - - '@nodelib/fs.stat@2.0.5': {} - - '@nodelib/fs.walk@1.2.8': - dependencies: - '@nodelib/fs.scandir': 2.1.5 - fastq: 1.17.1 - - '@popperjs/core@2.11.8': {} - - '@react-aria/ssr@3.9.6(react@18.3.1)': - dependencies: - '@swc/helpers': 0.5.15 - react: 18.3.1 - - '@react-dnd/asap@4.0.1': {} - - '@react-dnd/invariant@2.0.0': {} - - '@react-dnd/shallowequal@2.0.0': {} - - '@restart/hooks@0.4.16(react@18.3.1)': - dependencies: - dequal: 2.0.3 - react: 18.3.1 - - '@restart/ui@1.8.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@babel/runtime': 7.26.0 - '@popperjs/core': 2.11.8 - '@react-aria/ssr': 3.9.6(react@18.3.1) - '@restart/hooks': 0.4.16(react@18.3.1) - '@types/warning': 3.0.3 - dequal: 2.0.3 - dom-helpers: 5.2.1 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - uncontrollable: 8.0.4(react@18.3.1) - warning: 4.0.3 - - '@rollup/rollup-android-arm-eabi@4.44.1': - optional: true - - '@rollup/rollup-android-arm64@4.44.1': - optional: true - - '@rollup/rollup-darwin-arm64@4.44.1': - optional: true - - '@rollup/rollup-darwin-x64@4.44.1': - optional: true - - '@rollup/rollup-freebsd-arm64@4.44.1': - optional: true - - '@rollup/rollup-freebsd-x64@4.44.1': - optional: true - - '@rollup/rollup-linux-arm-gnueabihf@4.44.1': - optional: true - - '@rollup/rollup-linux-arm-musleabihf@4.44.1': - optional: true - - '@rollup/rollup-linux-arm64-gnu@4.44.1': - optional: true - - '@rollup/rollup-linux-arm64-musl@4.44.1': - optional: true - - '@rollup/rollup-linux-loongarch64-gnu@4.44.1': - optional: true - - '@rollup/rollup-linux-powerpc64le-gnu@4.44.1': - optional: true - - '@rollup/rollup-linux-riscv64-gnu@4.44.1': - optional: true - - '@rollup/rollup-linux-riscv64-musl@4.44.1': - optional: true - - '@rollup/rollup-linux-s390x-gnu@4.44.1': - optional: true - - '@rollup/rollup-linux-x64-gnu@4.44.1': - optional: true - - '@rollup/rollup-linux-x64-musl@4.44.1': - optional: true - - '@rollup/rollup-win32-arm64-msvc@4.44.1': - optional: true - - '@rollup/rollup-win32-ia32-msvc@4.44.1': - optional: true - - '@rollup/rollup-win32-x64-msvc@4.44.1': - optional: true - - '@swc/core-darwin-arm64@1.9.2': - optional: true - - '@swc/core-darwin-x64@1.9.2': - optional: true - - '@swc/core-linux-arm-gnueabihf@1.9.2': - optional: true - - '@swc/core-linux-arm64-gnu@1.9.2': - optional: true - - '@swc/core-linux-arm64-musl@1.9.2': - optional: true - - '@swc/core-linux-x64-gnu@1.9.2': - optional: true - - '@swc/core-linux-x64-musl@1.9.2': - optional: true - - '@swc/core-win32-arm64-msvc@1.9.2': - optional: true - - '@swc/core-win32-ia32-msvc@1.9.2': - optional: true - - '@swc/core-win32-x64-msvc@1.9.2': - optional: true - - '@swc/core@1.9.2(@swc/helpers@0.5.15)': - dependencies: - '@swc/counter': 0.1.3 - '@swc/types': 0.1.15 - optionalDependencies: - '@swc/core-darwin-arm64': 1.9.2 - '@swc/core-darwin-x64': 1.9.2 - '@swc/core-linux-arm-gnueabihf': 1.9.2 - '@swc/core-linux-arm64-gnu': 1.9.2 - '@swc/core-linux-arm64-musl': 1.9.2 - '@swc/core-linux-x64-gnu': 1.9.2 - '@swc/core-linux-x64-musl': 1.9.2 - '@swc/core-win32-arm64-msvc': 1.9.2 - '@swc/core-win32-ia32-msvc': 1.9.2 - '@swc/core-win32-x64-msvc': 1.9.2 - '@swc/helpers': 0.5.15 - - '@swc/counter@0.1.3': {} - - '@swc/helpers@0.5.15': - dependencies: - tslib: 2.8.1 - - '@swc/types@0.1.15': - dependencies: - '@swc/counter': 0.1.3 - - '@tanstack/react-table@8.21.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@tanstack/table-core': 8.21.3 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - - '@tanstack/table-core@8.21.3': {} - - '@types/estree@1.0.6': {} - - '@types/estree@1.0.8': {} - - '@types/json-schema@7.0.15': {} - - '@types/node@25.5.0': - dependencies: - undici-types: 7.18.2 - - '@types/prop-types@15.7.13': {} - - '@types/react-dom@18.3.1': - dependencies: - '@types/react': 18.3.12 - - '@types/react-transition-group@4.4.11': - dependencies: - '@types/react': 18.3.12 - - '@types/react@18.3.12': - dependencies: - '@types/prop-types': 15.7.13 - csstype: 3.1.3 - - '@types/readable-stream@4.0.23': - dependencies: - '@types/node': 25.5.0 - - '@types/warning@3.0.3': {} - - '@types/ws@8.18.1': - dependencies: - '@types/node': 25.5.0 - - '@typescript-eslint/eslint-plugin@8.15.0(@typescript-eslint/parser@8.15.0(eslint@9.15.0)(typescript@5.6.3))(eslint@9.15.0)(typescript@5.6.3)': - dependencies: - '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 8.15.0(eslint@9.15.0)(typescript@5.6.3) - '@typescript-eslint/scope-manager': 8.15.0 - '@typescript-eslint/type-utils': 8.15.0(eslint@9.15.0)(typescript@5.6.3) - '@typescript-eslint/utils': 8.15.0(eslint@9.15.0)(typescript@5.6.3) - '@typescript-eslint/visitor-keys': 8.15.0 - eslint: 9.15.0 - graphemer: 1.4.0 - ignore: 5.3.2 - natural-compare: 1.4.0 - ts-api-utils: 1.4.0(typescript@5.6.3) - optionalDependencies: - typescript: 5.6.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/parser@8.15.0(eslint@9.15.0)(typescript@5.6.3)': - dependencies: - '@typescript-eslint/scope-manager': 8.15.0 - '@typescript-eslint/types': 8.15.0 - '@typescript-eslint/typescript-estree': 8.15.0(typescript@5.6.3) - '@typescript-eslint/visitor-keys': 8.15.0 - debug: 4.3.7 - eslint: 9.15.0 - optionalDependencies: - typescript: 5.6.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/scope-manager@8.15.0': - dependencies: - '@typescript-eslint/types': 8.15.0 - '@typescript-eslint/visitor-keys': 8.15.0 - - '@typescript-eslint/type-utils@8.15.0(eslint@9.15.0)(typescript@5.6.3)': - dependencies: - '@typescript-eslint/typescript-estree': 8.15.0(typescript@5.6.3) - '@typescript-eslint/utils': 8.15.0(eslint@9.15.0)(typescript@5.6.3) - debug: 4.3.7 - eslint: 9.15.0 - ts-api-utils: 1.4.0(typescript@5.6.3) - optionalDependencies: - typescript: 5.6.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/types@8.15.0': {} - - '@typescript-eslint/typescript-estree@8.15.0(typescript@5.6.3)': - dependencies: - '@typescript-eslint/types': 8.15.0 - '@typescript-eslint/visitor-keys': 8.15.0 - debug: 4.3.7 - fast-glob: 3.3.2 - is-glob: 4.0.3 - minimatch: 9.0.5 - semver: 7.6.3 - ts-api-utils: 1.4.0(typescript@5.6.3) - optionalDependencies: - typescript: 5.6.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/utils@8.15.0(eslint@9.15.0)(typescript@5.6.3)': - dependencies: - '@eslint-community/eslint-utils': 4.4.1(eslint@9.15.0) - '@typescript-eslint/scope-manager': 8.15.0 - '@typescript-eslint/types': 8.15.0 - '@typescript-eslint/typescript-estree': 8.15.0(typescript@5.6.3) - eslint: 9.15.0 - optionalDependencies: - typescript: 5.6.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/visitor-keys@8.15.0': - dependencies: - '@typescript-eslint/types': 8.15.0 - eslint-visitor-keys: 4.2.0 - - '@vitejs/plugin-react-swc@3.7.1(@swc/helpers@0.5.15)(vite@5.4.19(@types/node@25.5.0)(sass-embedded@1.81.0)(sass@1.77.6))': - dependencies: - '@swc/core': 1.9.2(@swc/helpers@0.5.15) - vite: 5.4.19(@types/node@25.5.0)(sass-embedded@1.81.0)(sass@1.77.6) - transitivePeerDependencies: - - '@swc/helpers' - - abbrev@1.1.1: - optional: true - - abort-controller@3.0.0: - dependencies: - event-target-shim: 5.0.1 - - acorn-jsx@5.3.2(acorn@8.14.0): - dependencies: - acorn: 8.14.0 - - acorn@8.14.0: {} - - agent-base@6.0.2: - dependencies: - debug: 4.3.7 - transitivePeerDependencies: - - supports-color - optional: true - - ajv@6.12.6: - dependencies: - fast-deep-equal: 3.1.3 - fast-json-stable-stringify: 2.1.0 - json-schema-traverse: 0.4.1 - uri-js: 4.4.1 - - ansi-regex@5.0.1: - optional: true - - ansi-styles@4.3.0: - dependencies: - color-convert: 2.0.1 - - anymatch@3.1.3: - dependencies: - normalize-path: 3.0.0 - picomatch: 2.3.1 - optional: true - - aproba@2.0.0: - optional: true - - are-we-there-yet@2.0.0: - dependencies: - delegates: 1.0.0 - readable-stream: 3.6.2 - optional: true - - argparse@2.0.1: {} - - attr-accept@2.2.5: {} - - balanced-match@1.0.2: {} - - base64-js@1.5.1: {} - - binary-extensions@2.3.0: - optional: true - - bl@6.1.6: - dependencies: - '@types/readable-stream': 4.0.23 - buffer: 6.0.3 - inherits: 2.0.4 - readable-stream: 4.7.0 - - bootstrap@5.3.3(@popperjs/core@2.11.8): - dependencies: - '@popperjs/core': 2.11.8 - - brace-expansion@1.1.11: - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - - brace-expansion@2.0.1: - dependencies: - balanced-match: 1.0.2 - - braces@3.0.3: - dependencies: - fill-range: 7.1.1 - - broker-factory@3.1.14: - dependencies: - '@babel/runtime': 7.29.2 - fast-unique-numbers: 9.0.27 - tslib: 2.8.1 - worker-factory: 7.0.49 - - buffer-builder@0.2.0: {} - - buffer-from@1.1.2: {} - - buffer@6.0.3: - dependencies: - base64-js: 1.5.1 - ieee754: 1.2.1 - - callsites@3.1.0: {} - - canvas@2.11.2: - dependencies: - '@mapbox/node-pre-gyp': 1.0.11 - nan: 2.22.0 - simple-get: 3.1.1 - transitivePeerDependencies: - - encoding - - supports-color - optional: true - - chalk@4.1.2: - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - - chokidar@3.6.0: - dependencies: - anymatch: 3.1.3 - braces: 3.0.3 - glob-parent: 5.1.2 - is-binary-path: 2.1.0 - is-glob: 4.0.3 - normalize-path: 3.0.0 - readdirp: 3.6.0 - optionalDependencies: - fsevents: 2.3.3 - optional: true - - chownr@2.0.0: - optional: true - - classnames@2.5.1: {} - - clsx@2.1.1: {} - - color-convert@2.0.1: - dependencies: - color-name: 1.1.4 - - color-name@1.1.4: {} - - color-support@1.1.3: - optional: true - - colorjs.io@0.5.2: {} - - commist@3.2.0: {} - - concat-map@0.0.1: {} - - concat-stream@2.0.0: - dependencies: - buffer-from: 1.1.2 - inherits: 2.0.4 - readable-stream: 3.6.2 - typedarray: 0.0.6 - - console-control-strings@1.1.0: - optional: true - - cross-spawn@7.0.6: - dependencies: - path-key: 3.1.1 - shebang-command: 2.0.0 - which: 2.0.2 - - csstype@3.1.3: {} - - debug@4.3.7: - dependencies: - ms: 2.1.3 - - debug@4.4.3: - dependencies: - ms: 2.1.3 - - decompress-response@4.2.1: - dependencies: - mimic-response: 2.1.0 - optional: true - - deep-is@0.1.4: {} - - delegates@1.0.0: - optional: true - - dequal@2.0.3: {} - - detect-libc@2.0.3: - optional: true - - dnd-core@14.0.1: - dependencies: - '@react-dnd/asap': 4.0.1 - '@react-dnd/invariant': 2.0.0 - redux: 4.2.1 - - dom-helpers@5.2.1: - dependencies: - '@babel/runtime': 7.26.0 - csstype: 3.1.3 - - emoji-regex@8.0.0: - optional: true - - esbuild@0.21.5: - optionalDependencies: - '@esbuild/aix-ppc64': 0.21.5 - '@esbuild/android-arm': 0.21.5 - '@esbuild/android-arm64': 0.21.5 - '@esbuild/android-x64': 0.21.5 - '@esbuild/darwin-arm64': 0.21.5 - '@esbuild/darwin-x64': 0.21.5 - '@esbuild/freebsd-arm64': 0.21.5 - '@esbuild/freebsd-x64': 0.21.5 - '@esbuild/linux-arm': 0.21.5 - '@esbuild/linux-arm64': 0.21.5 - '@esbuild/linux-ia32': 0.21.5 - '@esbuild/linux-loong64': 0.21.5 - '@esbuild/linux-mips64el': 0.21.5 - '@esbuild/linux-ppc64': 0.21.5 - '@esbuild/linux-riscv64': 0.21.5 - '@esbuild/linux-s390x': 0.21.5 - '@esbuild/linux-x64': 0.21.5 - '@esbuild/netbsd-x64': 0.21.5 - '@esbuild/openbsd-x64': 0.21.5 - '@esbuild/sunos-x64': 0.21.5 - '@esbuild/win32-arm64': 0.21.5 - '@esbuild/win32-ia32': 0.21.5 - '@esbuild/win32-x64': 0.21.5 - - escape-string-regexp@4.0.0: {} - - eslint-plugin-react-hooks@5.0.0(eslint@9.15.0): - dependencies: - eslint: 9.15.0 - - eslint-plugin-react-refresh@0.4.14(eslint@9.15.0): - dependencies: - eslint: 9.15.0 - - eslint-scope@8.2.0: - dependencies: - esrecurse: 4.3.0 - estraverse: 5.3.0 - - eslint-visitor-keys@3.4.3: {} - - eslint-visitor-keys@4.2.0: {} - - eslint@9.15.0: - dependencies: - '@eslint-community/eslint-utils': 4.4.1(eslint@9.15.0) - '@eslint-community/regexpp': 4.12.1 - '@eslint/config-array': 0.19.0 - '@eslint/core': 0.9.0 - '@eslint/eslintrc': 3.2.0 - '@eslint/js': 9.15.0 - '@eslint/plugin-kit': 0.2.3 - '@humanfs/node': 0.16.6 - '@humanwhocodes/module-importer': 1.0.1 - '@humanwhocodes/retry': 0.4.1 - '@types/estree': 1.0.6 - '@types/json-schema': 7.0.15 - ajv: 6.12.6 - chalk: 4.1.2 - cross-spawn: 7.0.6 - debug: 4.3.7 - escape-string-regexp: 4.0.0 - eslint-scope: 8.2.0 - eslint-visitor-keys: 4.2.0 - espree: 10.3.0 - esquery: 1.6.0 - esutils: 2.0.3 - fast-deep-equal: 3.1.3 - file-entry-cache: 8.0.0 - find-up: 5.0.0 - glob-parent: 6.0.2 - ignore: 5.3.2 - imurmurhash: 0.1.4 - is-glob: 4.0.3 - json-stable-stringify-without-jsonify: 1.0.1 - lodash.merge: 4.6.2 - minimatch: 3.1.2 - natural-compare: 1.4.0 - optionator: 0.9.4 - transitivePeerDependencies: - - supports-color - - espree@10.3.0: - dependencies: - acorn: 8.14.0 - acorn-jsx: 5.3.2(acorn@8.14.0) - eslint-visitor-keys: 4.2.0 - - esquery@1.6.0: - dependencies: - estraverse: 5.3.0 - - esrecurse@4.3.0: - dependencies: - estraverse: 5.3.0 - - estraverse@5.3.0: {} - - esutils@2.0.3: {} - - event-target-shim@5.0.1: {} - - events@3.3.0: {} - - fast-deep-equal@3.1.3: {} - - fast-glob@3.3.2: - dependencies: - '@nodelib/fs.stat': 2.0.5 - '@nodelib/fs.walk': 1.2.8 - glob-parent: 5.1.2 - merge2: 1.4.1 - micromatch: 4.0.8 - - fast-json-stable-stringify@2.1.0: {} - - fast-levenshtein@2.0.6: {} - - fast-unique-numbers@9.0.27: - dependencies: - '@babel/runtime': 7.29.2 - tslib: 2.8.1 - - fastq@1.17.1: - dependencies: - reusify: 1.0.4 - - file-entry-cache@8.0.0: - dependencies: - flat-cache: 4.0.1 - - file-selector@2.1.0: - dependencies: - tslib: 2.8.1 - - fill-range@7.1.1: - dependencies: - to-regex-range: 5.0.1 - - find-up@5.0.0: - dependencies: - locate-path: 6.0.0 - path-exists: 4.0.0 - - flat-cache@4.0.1: - dependencies: - flatted: 3.3.2 - keyv: 4.5.4 - - flatted@3.3.2: {} - - fs-minipass@2.1.0: - dependencies: - minipass: 3.3.6 - optional: true - - fs.realpath@1.0.0: - optional: true - - fsevents@2.3.3: - optional: true - - gauge@3.0.2: - dependencies: - aproba: 2.0.0 - color-support: 1.1.3 - console-control-strings: 1.1.0 - has-unicode: 2.0.1 - object-assign: 4.1.1 - signal-exit: 3.0.7 - string-width: 4.2.3 - strip-ansi: 6.0.1 - wide-align: 1.1.5 - optional: true - - glob-parent@5.1.2: - dependencies: - is-glob: 4.0.3 - - glob-parent@6.0.2: - dependencies: - is-glob: 4.0.3 - - glob@7.2.3: - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - optional: true - - globals@14.0.0: {} - - globals@15.12.0: {} - - graphemer@1.4.0: {} - - has-flag@4.0.0: {} - - has-unicode@2.0.1: - optional: true - - help-me@5.0.0: {} - - history@4.10.1: - dependencies: - '@babel/runtime': 7.26.0 - loose-envify: 1.4.0 - resolve-pathname: 3.0.0 - tiny-invariant: 1.3.3 - tiny-warning: 1.0.3 - value-equal: 1.0.1 - - hoist-non-react-statics@3.3.2: - dependencies: - react-is: 16.13.1 - - https-proxy-agent@5.0.1: - dependencies: - agent-base: 6.0.2 - debug: 4.3.7 - transitivePeerDependencies: - - supports-color - optional: true - - ieee754@1.2.1: {} - - ignore@5.3.2: {} - - immutable@4.3.7: - optional: true - - immutable@5.0.3: {} - - import-fresh@3.3.0: - dependencies: - parent-module: 1.0.1 - resolve-from: 4.0.0 - - imurmurhash@0.1.4: {} - - inflight@1.0.6: - dependencies: - once: 1.4.0 - wrappy: 1.0.2 - optional: true - - inherits@2.0.4: {} - - invariant@2.2.4: - dependencies: - loose-envify: 1.4.0 - - ip-address@10.1.0: {} - - is-binary-path@2.1.0: - dependencies: - binary-extensions: 2.3.0 - optional: true - - is-extglob@2.1.1: {} - - is-fullwidth-code-point@3.0.0: - optional: true - - is-glob@4.0.3: - dependencies: - is-extglob: 2.1.1 - - is-number@7.0.0: {} - - isarray@0.0.1: {} - - isexe@2.0.0: {} - - js-sdsl@4.3.0: {} - - js-tokens@4.0.0: {} - - js-yaml@4.1.0: - dependencies: - argparse: 2.0.1 - - json-buffer@3.0.1: {} - - json-schema-traverse@0.4.1: {} - - json-stable-stringify-without-jsonify@1.0.1: {} - - jwt-decode@4.0.0: {} - - keyv@4.5.4: - dependencies: - json-buffer: 3.0.1 - - levn@0.4.1: - dependencies: - prelude-ls: 1.2.1 - type-check: 0.4.0 - - locate-path@6.0.0: - dependencies: - p-locate: 5.0.0 - - lodash.merge@4.6.2: {} - - loose-envify@1.4.0: - dependencies: - js-tokens: 4.0.0 - - lru-cache@10.4.3: {} - - make-cancellable-promise@1.3.2: {} - - make-dir@3.1.0: - dependencies: - semver: 6.3.1 - optional: true - - make-event-props@1.6.2: {} - - memoize-one@5.2.1: {} - - merge-refs@1.3.0(@types/react@18.3.12): - optionalDependencies: - '@types/react': 18.3.12 - - merge2@1.4.1: {} - - micromatch@4.0.8: - dependencies: - braces: 3.0.3 - picomatch: 2.3.1 - - mimic-response@2.1.0: - optional: true - - minimatch@3.1.2: - dependencies: - brace-expansion: 1.1.11 - - minimatch@9.0.5: - dependencies: - brace-expansion: 2.0.1 - - minimist@1.2.8: {} - - minipass@3.3.6: - dependencies: - yallist: 4.0.0 - optional: true - - minipass@5.0.0: - optional: true - - minizlib@2.1.2: - dependencies: - minipass: 3.3.6 - yallist: 4.0.0 - optional: true - - mkdirp@1.0.4: - optional: true - - moment@2.30.1: {} - - mqtt-packet@9.0.2: - dependencies: - bl: 6.1.6 - debug: 4.4.3 - process-nextick-args: 2.0.1 - transitivePeerDependencies: - - supports-color - - mqtt@5.15.1: - dependencies: - '@types/readable-stream': 4.0.23 - '@types/ws': 8.18.1 - commist: 3.2.0 - concat-stream: 2.0.0 - debug: 4.4.3 - help-me: 5.0.0 - lru-cache: 10.4.3 - minimist: 1.2.8 - mqtt-packet: 9.0.2 - number-allocator: 1.0.14 - readable-stream: 4.7.0 - rfdc: 1.4.1 - socks: 2.8.7 - split2: 4.2.0 - worker-timers: 8.0.31 - ws: 8.20.0 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - - ms@2.1.3: {} - - nan@2.22.0: - optional: true - - nanoid@3.3.11: {} - - natural-compare@1.4.0: {} - - node-fetch@2.7.0: - dependencies: - whatwg-url: 5.0.0 - optional: true - - nopt@5.0.0: - dependencies: - abbrev: 1.1.1 - optional: true - - normalize-path@3.0.0: - optional: true - - npmlog@5.0.1: - dependencies: - are-we-there-yet: 2.0.0 - console-control-strings: 1.1.0 - gauge: 3.0.2 - set-blocking: 2.0.0 - optional: true - - number-allocator@1.0.14: - dependencies: - debug: 4.4.3 - js-sdsl: 4.3.0 - transitivePeerDependencies: - - supports-color - - object-assign@4.1.1: {} - - once@1.4.0: - dependencies: - wrappy: 1.0.2 - optional: true - - optionator@0.9.4: - dependencies: - deep-is: 0.1.4 - fast-levenshtein: 2.0.6 - levn: 0.4.1 - prelude-ls: 1.2.1 - type-check: 0.4.0 - word-wrap: 1.2.5 - - p-limit@3.1.0: - dependencies: - yocto-queue: 0.1.0 - - p-locate@5.0.0: - dependencies: - p-limit: 3.1.0 - - pako@1.0.11: {} - - parent-module@1.0.1: - dependencies: - callsites: 3.1.0 - - path-exists@4.0.0: {} - - path-is-absolute@1.0.1: - optional: true - - path-key@3.1.1: {} - - path-to-regexp@1.9.0: - dependencies: - isarray: 0.0.1 - - path2d@0.2.2: - optional: true - - pdfjs-dist@4.4.168: - optionalDependencies: - canvas: 2.11.2 - path2d: 0.2.2 - transitivePeerDependencies: - - encoding - - supports-color - - picocolors@1.1.1: {} - - picomatch@2.3.1: {} - - postcss@8.5.6: - dependencies: - nanoid: 3.3.11 - picocolors: 1.1.1 - source-map-js: 1.2.1 - - prelude-ls@1.2.1: {} - - process-nextick-args@2.0.1: {} - - process@0.11.10: {} - - prop-types-extra@1.1.1(react@18.3.1): - dependencies: - react: 18.3.1 - react-is: 16.13.1 - warning: 4.0.3 - - prop-types@15.8.1: - dependencies: - loose-envify: 1.4.0 - object-assign: 4.1.1 - react-is: 16.13.1 - - punycode@2.3.1: {} - - queue-microtask@1.2.3: {} - - react-arborist@3.4.0(@types/node@25.5.0)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - react: 18.3.1 - react-dnd: 14.0.5(@types/node@25.5.0)(@types/react@18.3.12)(react@18.3.1) - react-dnd-html5-backend: 14.1.0 - react-dom: 18.3.1(react@18.3.1) - react-window: 1.8.10(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - redux: 5.0.1 - use-sync-external-store: 1.2.2(react@18.3.1) - transitivePeerDependencies: - - '@types/hoist-non-react-statics' - - '@types/node' - - '@types/react' - - react-bootstrap@2.10.5(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - '@babel/runtime': 7.26.0 - '@restart/hooks': 0.4.16(react@18.3.1) - '@restart/ui': 1.8.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@types/react-transition-group': 4.4.11 - classnames: 2.5.1 - dom-helpers: 5.2.1 - invariant: 2.2.4 - prop-types: 15.8.1 - prop-types-extra: 1.1.1(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - react-transition-group: 4.4.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - uncontrollable: 7.2.1(react@18.3.1) - warning: 4.0.3 - optionalDependencies: - '@types/react': 18.3.12 - - react-dnd-html5-backend@14.1.0: - dependencies: - dnd-core: 14.0.1 - - react-dnd@14.0.5(@types/node@25.5.0)(@types/react@18.3.12)(react@18.3.1): - dependencies: - '@react-dnd/invariant': 2.0.0 - '@react-dnd/shallowequal': 2.0.0 - dnd-core: 14.0.1 - fast-deep-equal: 3.1.3 - hoist-non-react-statics: 3.3.2 - react: 18.3.1 - optionalDependencies: - '@types/node': 25.5.0 - '@types/react': 18.3.12 - - react-dom@18.3.1(react@18.3.1): - dependencies: - loose-envify: 1.4.0 - react: 18.3.1 - scheduler: 0.23.2 - - react-dropzone@14.3.5(react@18.3.1): - dependencies: - attr-accept: 2.2.5 - file-selector: 2.1.0 - prop-types: 15.8.1 - react: 18.3.1 - - react-icons@5.3.0(react@18.3.1): - dependencies: - react: 18.3.1 - - react-is@16.13.1: {} - - react-lifecycles-compat@3.0.4: {} - - react-pdf@9.1.1(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - clsx: 2.1.1 - dequal: 2.0.3 - make-cancellable-promise: 1.3.2 - make-event-props: 1.6.2 - merge-refs: 1.3.0(@types/react@18.3.12) - pdfjs-dist: 4.4.168 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - tiny-invariant: 1.3.3 - warning: 4.0.3 - optionalDependencies: - '@types/react': 18.3.12 - transitivePeerDependencies: - - encoding - - supports-color - - react-router-dom@5.3.4(react@18.3.1): - dependencies: - '@babel/runtime': 7.26.0 - history: 4.10.1 - loose-envify: 1.4.0 - prop-types: 15.8.1 - react: 18.3.1 - react-router: 5.3.4(react@18.3.1) - tiny-invariant: 1.3.3 - tiny-warning: 1.0.3 - - react-router@5.3.4(react@18.3.1): - dependencies: - '@babel/runtime': 7.26.0 - history: 4.10.1 - hoist-non-react-statics: 3.3.2 - loose-envify: 1.4.0 - path-to-regexp: 1.9.0 - prop-types: 15.8.1 - react: 18.3.1 - react-is: 16.13.1 - tiny-invariant: 1.3.3 - tiny-warning: 1.0.3 - - react-toastify@10.0.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - clsx: 2.1.1 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - - react-transition-group@4.4.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - '@babel/runtime': 7.26.0 - dom-helpers: 5.2.1 - loose-envify: 1.4.0 - prop-types: 15.8.1 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - - react-window@1.8.10(react-dom@18.3.1(react@18.3.1))(react@18.3.1): - dependencies: - '@babel/runtime': 7.26.0 - memoize-one: 5.2.1 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - - react@18.3.1: - dependencies: - loose-envify: 1.4.0 - - readable-stream@3.6.2: - dependencies: - inherits: 2.0.4 - string_decoder: 1.3.0 - util-deprecate: 1.0.2 - - readable-stream@4.7.0: - dependencies: - abort-controller: 3.0.0 - buffer: 6.0.3 - events: 3.3.0 - process: 0.11.10 - string_decoder: 1.3.0 - - readdirp@3.6.0: - dependencies: - picomatch: 2.3.1 - optional: true - - redux@4.2.1: - dependencies: - '@babel/runtime': 7.26.0 - - redux@5.0.1: {} - - regenerator-runtime@0.14.1: {} - - resolve-from@4.0.0: {} - - resolve-pathname@3.0.0: {} - - reusify@1.0.4: {} - - rfdc@1.4.1: {} - - rimraf@3.0.2: - dependencies: - glob: 7.2.3 - optional: true - - rollup@4.44.1: - dependencies: - '@types/estree': 1.0.8 - optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.44.1 - '@rollup/rollup-android-arm64': 4.44.1 - '@rollup/rollup-darwin-arm64': 4.44.1 - '@rollup/rollup-darwin-x64': 4.44.1 - '@rollup/rollup-freebsd-arm64': 4.44.1 - '@rollup/rollup-freebsd-x64': 4.44.1 - '@rollup/rollup-linux-arm-gnueabihf': 4.44.1 - '@rollup/rollup-linux-arm-musleabihf': 4.44.1 - '@rollup/rollup-linux-arm64-gnu': 4.44.1 - '@rollup/rollup-linux-arm64-musl': 4.44.1 - '@rollup/rollup-linux-loongarch64-gnu': 4.44.1 - '@rollup/rollup-linux-powerpc64le-gnu': 4.44.1 - '@rollup/rollup-linux-riscv64-gnu': 4.44.1 - '@rollup/rollup-linux-riscv64-musl': 4.44.1 - '@rollup/rollup-linux-s390x-gnu': 4.44.1 - '@rollup/rollup-linux-x64-gnu': 4.44.1 - '@rollup/rollup-linux-x64-musl': 4.44.1 - '@rollup/rollup-win32-arm64-msvc': 4.44.1 - '@rollup/rollup-win32-ia32-msvc': 4.44.1 - '@rollup/rollup-win32-x64-msvc': 4.44.1 - fsevents: 2.3.3 - - run-parallel@1.2.0: - dependencies: - queue-microtask: 1.2.3 - - rxjs@7.8.1: - dependencies: - tslib: 2.8.1 - - safe-buffer@5.2.1: {} - - sass-embedded-android-arm64@1.81.0: - optional: true - - sass-embedded-android-arm@1.81.0: - optional: true - - sass-embedded-android-ia32@1.81.0: - optional: true - - sass-embedded-android-riscv64@1.81.0: - optional: true - - sass-embedded-android-x64@1.81.0: - optional: true - - sass-embedded-darwin-arm64@1.81.0: - optional: true - - sass-embedded-darwin-x64@1.81.0: - optional: true - - sass-embedded-linux-arm64@1.81.0: - optional: true - - sass-embedded-linux-arm@1.81.0: - optional: true - - sass-embedded-linux-ia32@1.81.0: - optional: true - - sass-embedded-linux-musl-arm64@1.81.0: - optional: true - - sass-embedded-linux-musl-arm@1.81.0: - optional: true - - sass-embedded-linux-musl-ia32@1.81.0: - optional: true - - sass-embedded-linux-musl-riscv64@1.81.0: - optional: true - - sass-embedded-linux-musl-x64@1.81.0: - optional: true - - sass-embedded-linux-riscv64@1.81.0: - optional: true - - sass-embedded-linux-x64@1.81.0: - optional: true - - sass-embedded-win32-arm64@1.81.0: - optional: true - - sass-embedded-win32-ia32@1.81.0: - optional: true - - sass-embedded-win32-x64@1.81.0: - optional: true - - sass-embedded@1.81.0: - dependencies: - '@bufbuild/protobuf': 2.2.2 - buffer-builder: 0.2.0 - colorjs.io: 0.5.2 - immutable: 5.0.3 - rxjs: 7.8.1 - supports-color: 8.1.1 - sync-child-process: 1.0.2 - varint: 6.0.0 - optionalDependencies: - sass-embedded-android-arm: 1.81.0 - sass-embedded-android-arm64: 1.81.0 - sass-embedded-android-ia32: 1.81.0 - sass-embedded-android-riscv64: 1.81.0 - sass-embedded-android-x64: 1.81.0 - sass-embedded-darwin-arm64: 1.81.0 - sass-embedded-darwin-x64: 1.81.0 - sass-embedded-linux-arm: 1.81.0 - sass-embedded-linux-arm64: 1.81.0 - sass-embedded-linux-ia32: 1.81.0 - sass-embedded-linux-musl-arm: 1.81.0 - sass-embedded-linux-musl-arm64: 1.81.0 - sass-embedded-linux-musl-ia32: 1.81.0 - sass-embedded-linux-musl-riscv64: 1.81.0 - sass-embedded-linux-musl-x64: 1.81.0 - sass-embedded-linux-riscv64: 1.81.0 - sass-embedded-linux-x64: 1.81.0 - sass-embedded-win32-arm64: 1.81.0 - sass-embedded-win32-ia32: 1.81.0 - sass-embedded-win32-x64: 1.81.0 - - sass@1.77.6: - dependencies: - chokidar: 3.6.0 - immutable: 4.3.7 - source-map-js: 1.2.1 - optional: true - - scheduler@0.23.2: - dependencies: - loose-envify: 1.4.0 - - semver@6.3.1: - optional: true - - semver@7.6.3: {} - - set-blocking@2.0.0: - optional: true - - shebang-command@2.0.0: - dependencies: - shebang-regex: 3.0.0 - - shebang-regex@3.0.0: {} - - signal-exit@3.0.7: - optional: true - - simple-concat@1.0.1: - optional: true - - simple-get@3.1.1: - dependencies: - decompress-response: 4.2.1 - once: 1.4.0 - simple-concat: 1.0.1 - optional: true - - smart-buffer@4.2.0: {} - - socks@2.8.7: - dependencies: - ip-address: 10.1.0 - smart-buffer: 4.2.0 - - source-map-js@1.2.1: {} - - split2@4.2.0: {} - - string-width@4.2.3: - dependencies: - emoji-regex: 8.0.0 - is-fullwidth-code-point: 3.0.0 - strip-ansi: 6.0.1 - optional: true - - string_decoder@1.3.0: - dependencies: - safe-buffer: 5.2.1 - - strip-ansi@6.0.1: - dependencies: - ansi-regex: 5.0.1 - optional: true - - strip-json-comments@3.1.1: {} - - supports-color@7.2.0: - dependencies: - has-flag: 4.0.0 - - supports-color@8.1.1: - dependencies: - has-flag: 4.0.0 - - sync-child-process@1.0.2: - dependencies: - sync-message-port: 1.1.3 - - sync-message-port@1.1.3: {} - - tar@6.2.1: - dependencies: - chownr: 2.0.0 - fs-minipass: 2.1.0 - minipass: 5.0.0 - minizlib: 2.1.2 - mkdirp: 1.0.4 - yallist: 4.0.0 - optional: true - - tiny-invariant@1.3.3: {} - - tiny-warning@1.0.3: {} - - to-regex-range@5.0.1: - dependencies: - is-number: 7.0.0 - - tr46@0.0.3: - optional: true - - ts-api-utils@1.4.0(typescript@5.6.3): - dependencies: - typescript: 5.6.3 - - tslib@2.8.1: {} - - type-check@0.4.0: - dependencies: - prelude-ls: 1.2.1 - - typedarray@0.0.6: {} - - typescript-eslint@8.15.0(eslint@9.15.0)(typescript@5.6.3): - dependencies: - '@typescript-eslint/eslint-plugin': 8.15.0(@typescript-eslint/parser@8.15.0(eslint@9.15.0)(typescript@5.6.3))(eslint@9.15.0)(typescript@5.6.3) - '@typescript-eslint/parser': 8.15.0(eslint@9.15.0)(typescript@5.6.3) - '@typescript-eslint/utils': 8.15.0(eslint@9.15.0)(typescript@5.6.3) - eslint: 9.15.0 - optionalDependencies: - typescript: 5.6.3 - transitivePeerDependencies: - - supports-color - - typescript@5.6.3: {} - - uncontrollable@7.2.1(react@18.3.1): - dependencies: - '@babel/runtime': 7.26.0 - '@types/react': 18.3.12 - invariant: 2.2.4 - react: 18.3.1 - react-lifecycles-compat: 3.0.4 - - uncontrollable@8.0.4(react@18.3.1): - dependencies: - react: 18.3.1 - - undici-types@7.18.2: {} - - uri-js@4.4.1: - dependencies: - punycode: 2.3.1 - - use-sync-external-store@1.2.2(react@18.3.1): - dependencies: - react: 18.3.1 - - util-deprecate@1.0.2: {} - - value-equal@1.0.1: {} - - varint@6.0.0: {} - - vite@5.4.19(@types/node@25.5.0)(sass-embedded@1.81.0)(sass@1.77.6): - dependencies: - esbuild: 0.21.5 - postcss: 8.5.6 - rollup: 4.44.1 - optionalDependencies: - '@types/node': 25.5.0 - fsevents: 2.3.3 - sass: 1.77.6 - sass-embedded: 1.81.0 - - warning@4.0.3: - dependencies: - loose-envify: 1.4.0 - - webidl-conversions@3.0.1: - optional: true - - whatwg-url@5.0.0: - dependencies: - tr46: 0.0.3 - webidl-conversions: 3.0.1 - optional: true - - which@2.0.2: - dependencies: - isexe: 2.0.0 - - wide-align@1.1.5: - dependencies: - string-width: 4.2.3 - optional: true - - word-wrap@1.2.5: {} - - worker-factory@7.0.49: - dependencies: - '@babel/runtime': 7.29.2 - fast-unique-numbers: 9.0.27 - tslib: 2.8.1 - - worker-timers-broker@8.0.16: - dependencies: - '@babel/runtime': 7.29.2 - broker-factory: 3.1.14 - fast-unique-numbers: 9.0.27 - tslib: 2.8.1 - worker-timers-worker: 9.0.14 - - worker-timers-worker@9.0.14: - dependencies: - '@babel/runtime': 7.29.2 - tslib: 2.8.1 - worker-factory: 7.0.49 - - worker-timers@8.0.31: - dependencies: - '@babel/runtime': 7.29.2 - tslib: 2.8.1 - worker-timers-broker: 8.0.16 - worker-timers-worker: 9.0.14 - - wrappy@1.0.2: - optional: true - - ws@8.20.0: {} - - yallist@4.0.0: - optional: true - - yocto-queue@0.1.0: {} diff --git a/ui/public/favicon.ico b/ui/public/favicon.ico deleted file mode 100755 index cb8b69cb..00000000 Binary files a/ui/public/favicon.ico and /dev/null differ diff --git a/ui/public/pdf.worker.js b/ui/public/pdf.worker.js deleted file mode 100644 index b5849573..00000000 --- a/ui/public/pdf.worker.js +++ /dev/null @@ -1,73561 +0,0 @@ -/** - * @licstart The following is the entire license notice for the - * Javascript code in this page - * - * Copyright 2021 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. - * - * @licend The above is the entire license notice for the - * Javascript code in this page - */ - -(function webpackUniversalModuleDefinition(root, factory) { - if(typeof exports === 'object' && typeof module === 'object') - module.exports = factory(); - else if(typeof define === 'function' && define.amd) - define("pdfjs-dist/build/pdf.worker", [], factory); - else if(typeof exports === 'object') - exports["pdfjs-dist/build/pdf.worker"] = factory(); - else - root["pdfjs-dist/build/pdf.worker"] = root.pdfjsWorker = factory(); -})(this, function() { -return /******/ (() => { // webpackBootstrap -/******/ "use strict"; -/******/ var __webpack_modules__ = ([ -/* 0 */, -/* 1 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.WorkerTask = exports.WorkerMessageHandler = void 0; - -var _util = __w_pdfjs_require__(2); - -var _primitives = __w_pdfjs_require__(5); - -var _pdf_manager = __w_pdfjs_require__(7); - -var _writer = __w_pdfjs_require__(71); - -var _is_node = __w_pdfjs_require__(4); - -var _message_handler = __w_pdfjs_require__(99); - -var _worker_stream = __w_pdfjs_require__(100); - -var _core_utils = __w_pdfjs_require__(9); - -class WorkerTask { - constructor(name) { - this.name = name; - this.terminated = false; - this._capability = (0, _util.createPromiseCapability)(); - } - - get finished() { - return this._capability.promise; - } - - finish() { - this._capability.resolve(); - } - - terminate() { - this.terminated = true; - } - - ensureNotTerminated() { - if (this.terminated) { - throw new Error("Worker task was terminated"); - } - } - -} - -exports.WorkerTask = WorkerTask; - -class WorkerMessageHandler { - static setup(handler, port) { - let testMessageProcessed = false; - handler.on("test", function wphSetupTest(data) { - if (testMessageProcessed) { - return; - } - - testMessageProcessed = true; - handler.send("test", data instanceof Uint8Array && data[0] === 255); - }); - handler.on("configure", function wphConfigure(data) { - (0, _util.setVerbosityLevel)(data.verbosity); - }); - handler.on("GetDocRequest", function wphSetupDoc(data) { - return WorkerMessageHandler.createDocumentHandler(data, port); - }); - } - - static createDocumentHandler(docParams, port) { - let pdfManager; - let terminated = false; - let cancelXHRs = null; - const WorkerTasks = []; - const verbosity = (0, _util.getVerbosityLevel)(); - const apiVersion = docParams.apiVersion; - const workerVersion = '2.12.313'; - - if (apiVersion !== workerVersion) { - throw new Error(`The API version "${apiVersion}" does not match ` + `the Worker version "${workerVersion}".`); - } - - const enumerableProperties = []; - - for (const property in []) { - enumerableProperties.push(property); - } - - if (enumerableProperties.length) { - throw new Error("The `Array.prototype` contains unexpected enumerable properties: " + enumerableProperties.join(", ") + "; thus breaking e.g. `for...in` iteration of `Array`s."); - } - - if (typeof ReadableStream === "undefined") { - throw new Error("The browser/environment lacks native support for critical " + "functionality used by the PDF.js library (e.g. `ReadableStream`); " + "please use a `legacy`-build instead."); - } - - const docId = docParams.docId; - const docBaseUrl = docParams.docBaseUrl; - const workerHandlerName = docParams.docId + "_worker"; - let handler = new _message_handler.MessageHandler(workerHandlerName, docId, port); - - function ensureNotTerminated() { - if (terminated) { - throw new Error("Worker was terminated"); - } - } - - function startWorkerTask(task) { - WorkerTasks.push(task); - } - - function finishWorkerTask(task) { - task.finish(); - const i = WorkerTasks.indexOf(task); - WorkerTasks.splice(i, 1); - } - - async function loadDocument(recoveryMode) { - await pdfManager.ensureDoc("checkHeader"); - await pdfManager.ensureDoc("parseStartXRef"); - await pdfManager.ensureDoc("parse", [recoveryMode]); - await pdfManager.ensureDoc("checkFirstPage", [recoveryMode]); - await pdfManager.ensureDoc("checkLastPage", [recoveryMode]); - const isPureXfa = await pdfManager.ensureDoc("isPureXfa"); - - if (isPureXfa) { - const task = new WorkerTask("loadXfaFonts"); - startWorkerTask(task); - await Promise.all([pdfManager.loadXfaFonts(handler, task).catch(reason => {}).then(() => finishWorkerTask(task)), pdfManager.loadXfaImages()]); - } - - const [numPages, fingerprints] = await Promise.all([pdfManager.ensureDoc("numPages"), pdfManager.ensureDoc("fingerprints")]); - const htmlForXfa = isPureXfa ? await pdfManager.ensureDoc("htmlForXfa") : null; - return { - numPages, - fingerprints, - htmlForXfa - }; - } - - function getPdfManager(data, evaluatorOptions, enableXfa) { - const pdfManagerCapability = (0, _util.createPromiseCapability)(); - let newPdfManager; - const source = data.source; - - if (source.data) { - try { - newPdfManager = new _pdf_manager.LocalPdfManager(docId, source.data, source.password, handler, evaluatorOptions, enableXfa, docBaseUrl); - pdfManagerCapability.resolve(newPdfManager); - } catch (ex) { - pdfManagerCapability.reject(ex); - } - - return pdfManagerCapability.promise; - } - - let pdfStream, - cachedChunks = []; - - try { - pdfStream = new _worker_stream.PDFWorkerStream(handler); - } catch (ex) { - pdfManagerCapability.reject(ex); - return pdfManagerCapability.promise; - } - - const fullRequest = pdfStream.getFullReader(); - fullRequest.headersReady.then(function () { - if (!fullRequest.isRangeSupported) { - return; - } - - const disableAutoFetch = source.disableAutoFetch || fullRequest.isStreamingSupported; - newPdfManager = new _pdf_manager.NetworkPdfManager(docId, pdfStream, { - msgHandler: handler, - password: source.password, - length: fullRequest.contentLength, - disableAutoFetch, - rangeChunkSize: source.rangeChunkSize - }, evaluatorOptions, enableXfa, docBaseUrl); - - for (let i = 0; i < cachedChunks.length; i++) { - newPdfManager.sendProgressiveData(cachedChunks[i]); - } - - cachedChunks = []; - pdfManagerCapability.resolve(newPdfManager); - cancelXHRs = null; - }).catch(function (reason) { - pdfManagerCapability.reject(reason); - cancelXHRs = null; - }); - let loaded = 0; - - const flushChunks = function () { - const pdfFile = (0, _util.arraysToBytes)(cachedChunks); - - if (source.length && pdfFile.length !== source.length) { - (0, _util.warn)("reported HTTP length is different from actual"); - } - - try { - newPdfManager = new _pdf_manager.LocalPdfManager(docId, pdfFile, source.password, handler, evaluatorOptions, enableXfa, docBaseUrl); - pdfManagerCapability.resolve(newPdfManager); - } catch (ex) { - pdfManagerCapability.reject(ex); - } - - cachedChunks = []; - }; - - const readPromise = new Promise(function (resolve, reject) { - const readChunk = function ({ - value, - done - }) { - try { - ensureNotTerminated(); - - if (done) { - if (!newPdfManager) { - flushChunks(); - } - - cancelXHRs = null; - return; - } - - loaded += (0, _util.arrayByteLength)(value); - - if (!fullRequest.isStreamingSupported) { - handler.send("DocProgress", { - loaded, - total: Math.max(loaded, fullRequest.contentLength || 0) - }); - } - - if (newPdfManager) { - newPdfManager.sendProgressiveData(value); - } else { - cachedChunks.push(value); - } - - fullRequest.read().then(readChunk, reject); - } catch (e) { - reject(e); - } - }; - - fullRequest.read().then(readChunk, reject); - }); - readPromise.catch(function (e) { - pdfManagerCapability.reject(e); - cancelXHRs = null; - }); - - cancelXHRs = function (reason) { - pdfStream.cancelAllRequests(reason); - }; - - return pdfManagerCapability.promise; - } - - function setupDoc(data) { - function onSuccess(doc) { - ensureNotTerminated(); - handler.send("GetDoc", { - pdfInfo: doc - }); - } - - function onFailure(ex) { - ensureNotTerminated(); - - if (ex instanceof _util.PasswordException) { - const task = new WorkerTask(`PasswordException: response ${ex.code}`); - startWorkerTask(task); - handler.sendWithPromise("PasswordRequest", ex).then(function ({ - password - }) { - finishWorkerTask(task); - pdfManager.updatePassword(password); - pdfManagerReady(); - }).catch(function () { - finishWorkerTask(task); - handler.send("DocException", ex); - }); - } else if (ex instanceof _util.InvalidPDFException || ex instanceof _util.MissingPDFException || ex instanceof _util.UnexpectedResponseException || ex instanceof _util.UnknownErrorException) { - handler.send("DocException", ex); - } else { - handler.send("DocException", new _util.UnknownErrorException(ex.message, ex.toString())); - } - } - - function pdfManagerReady() { - ensureNotTerminated(); - loadDocument(false).then(onSuccess, function (reason) { - ensureNotTerminated(); - - if (!(reason instanceof _core_utils.XRefParseException)) { - onFailure(reason); - return; - } - - pdfManager.requestLoadedStream(); - pdfManager.onLoadedStream().then(function () { - ensureNotTerminated(); - loadDocument(true).then(onSuccess, onFailure); - }); - }); - } - - ensureNotTerminated(); - const evaluatorOptions = { - maxImageSize: data.maxImageSize, - disableFontFace: data.disableFontFace, - ignoreErrors: data.ignoreErrors, - isEvalSupported: data.isEvalSupported, - fontExtraProperties: data.fontExtraProperties, - useSystemFonts: data.useSystemFonts, - cMapUrl: data.cMapUrl, - standardFontDataUrl: data.standardFontDataUrl - }; - getPdfManager(data, evaluatorOptions, data.enableXfa).then(function (newPdfManager) { - if (terminated) { - newPdfManager.terminate(new _util.AbortException("Worker was terminated.")); - throw new Error("Worker was terminated"); - } - - pdfManager = newPdfManager; - pdfManager.onLoadedStream().then(function (stream) { - handler.send("DataLoaded", { - length: stream.bytes.byteLength - }); - }); - }).then(pdfManagerReady, onFailure); - } - - handler.on("GetPage", function wphSetupGetPage(data) { - return pdfManager.getPage(data.pageIndex).then(function (page) { - return Promise.all([pdfManager.ensure(page, "rotate"), pdfManager.ensure(page, "ref"), pdfManager.ensure(page, "userUnit"), pdfManager.ensure(page, "view")]).then(function ([rotate, ref, userUnit, view]) { - return { - rotate, - ref, - userUnit, - view - }; - }); - }); - }); - handler.on("GetPageIndex", function wphSetupGetPageIndex({ - ref - }) { - const pageRef = _primitives.Ref.get(ref.num, ref.gen); - - return pdfManager.ensureCatalog("getPageIndex", [pageRef]); - }); - handler.on("GetDestinations", function wphSetupGetDestinations(data) { - return pdfManager.ensureCatalog("destinations"); - }); - handler.on("GetDestination", function wphSetupGetDestination(data) { - return pdfManager.ensureCatalog("getDestination", [data.id]); - }); - handler.on("GetPageLabels", function wphSetupGetPageLabels(data) { - return pdfManager.ensureCatalog("pageLabels"); - }); - handler.on("GetPageLayout", function wphSetupGetPageLayout(data) { - return pdfManager.ensureCatalog("pageLayout"); - }); - handler.on("GetPageMode", function wphSetupGetPageMode(data) { - return pdfManager.ensureCatalog("pageMode"); - }); - handler.on("GetViewerPreferences", function (data) { - return pdfManager.ensureCatalog("viewerPreferences"); - }); - handler.on("GetOpenAction", function (data) { - return pdfManager.ensureCatalog("openAction"); - }); - handler.on("GetAttachments", function wphSetupGetAttachments(data) { - return pdfManager.ensureCatalog("attachments"); - }); - handler.on("GetJavaScript", function wphSetupGetJavaScript(data) { - return pdfManager.ensureCatalog("javaScript"); - }); - handler.on("GetDocJSActions", function wphSetupGetDocJSActions(data) { - return pdfManager.ensureCatalog("jsActions"); - }); - handler.on("GetPageJSActions", function ({ - pageIndex - }) { - return pdfManager.getPage(pageIndex).then(function (page) { - return pdfManager.ensure(page, "jsActions"); - }); - }); - handler.on("GetOutline", function wphSetupGetOutline(data) { - return pdfManager.ensureCatalog("documentOutline"); - }); - handler.on("GetOptionalContentConfig", function (data) { - return pdfManager.ensureCatalog("optionalContentConfig"); - }); - handler.on("GetPermissions", function (data) { - return pdfManager.ensureCatalog("permissions"); - }); - handler.on("GetMetadata", function wphSetupGetMetadata(data) { - return Promise.all([pdfManager.ensureDoc("documentInfo"), pdfManager.ensureCatalog("metadata")]); - }); - handler.on("GetMarkInfo", function wphSetupGetMarkInfo(data) { - return pdfManager.ensureCatalog("markInfo"); - }); - handler.on("GetData", function wphSetupGetData(data) { - pdfManager.requestLoadedStream(); - return pdfManager.onLoadedStream().then(function (stream) { - return stream.bytes; - }); - }); - handler.on("GetAnnotations", function ({ - pageIndex, - intent - }) { - return pdfManager.getPage(pageIndex).then(function (page) { - return page.getAnnotationsData(intent); - }); - }); - handler.on("GetFieldObjects", function (data) { - return pdfManager.ensureDoc("fieldObjects"); - }); - handler.on("HasJSActions", function (data) { - return pdfManager.ensureDoc("hasJSActions"); - }); - handler.on("GetCalculationOrderIds", function (data) { - return pdfManager.ensureDoc("calculationOrderIds"); - }); - handler.on("SaveDocument", function ({ - isPureXfa, - numPages, - annotationStorage, - filename - }) { - pdfManager.requestLoadedStream(); - const promises = [pdfManager.onLoadedStream(), pdfManager.ensureCatalog("acroForm"), pdfManager.ensureCatalog("acroFormRef"), pdfManager.ensureDoc("xref"), pdfManager.ensureDoc("startXRef")]; - - if (isPureXfa) { - promises.push(pdfManager.serializeXfaData(annotationStorage)); - } else { - for (let pageIndex = 0; pageIndex < numPages; pageIndex++) { - promises.push(pdfManager.getPage(pageIndex).then(function (page) { - const task = new WorkerTask(`Save: page ${pageIndex}`); - return page.save(handler, task, annotationStorage).finally(function () { - finishWorkerTask(task); - }); - })); - } - } - - return Promise.all(promises).then(function ([stream, acroForm, acroFormRef, xref, startXRef, ...refs]) { - let newRefs = []; - let xfaData = null; - - if (isPureXfa) { - xfaData = refs[0]; - - if (!xfaData) { - return stream.bytes; - } - } else { - for (const ref of refs) { - newRefs = ref.filter(x => x !== null).reduce((a, b) => a.concat(b), newRefs); - } - - if (newRefs.length === 0) { - return stream.bytes; - } - } - - const xfa = acroForm instanceof _primitives.Dict && acroForm.get("XFA") || null; - let xfaDatasetsRef = null; - let hasXfaDatasetsEntry = false; - - if (Array.isArray(xfa)) { - for (let i = 0, ii = xfa.length; i < ii; i += 2) { - if (xfa[i] === "datasets") { - xfaDatasetsRef = xfa[i + 1]; - acroFormRef = null; - hasXfaDatasetsEntry = true; - } - } - - if (xfaDatasetsRef === null) { - xfaDatasetsRef = xref.getNewRef(); - } - } else if (xfa) { - acroFormRef = null; - (0, _util.warn)("Unsupported XFA type."); - } - - let newXrefInfo = Object.create(null); - - if (xref.trailer) { - const infoObj = Object.create(null); - const xrefInfo = xref.trailer.get("Info") || null; - - if (xrefInfo instanceof _primitives.Dict) { - xrefInfo.forEach((key, value) => { - if ((0, _util.isString)(key) && (0, _util.isString)(value)) { - infoObj[key] = (0, _util.stringToPDFString)(value); - } - }); - } - - newXrefInfo = { - rootRef: xref.trailer.getRaw("Root") || null, - encryptRef: xref.trailer.getRaw("Encrypt") || null, - newRef: xref.getNewRef(), - infoRef: xref.trailer.getRaw("Info") || null, - info: infoObj, - fileIds: xref.trailer.get("ID") || null, - startXRef, - filename - }; - } - - xref.resetNewRef(); - return (0, _writer.incrementalUpdate)({ - originalData: stream.bytes, - xrefInfo: newXrefInfo, - newRefs, - xref, - hasXfa: !!xfa, - xfaDatasetsRef, - hasXfaDatasetsEntry, - acroFormRef, - acroForm, - xfaData - }); - }); - }); - handler.on("GetOperatorList", function wphSetupRenderPage(data, sink) { - const pageIndex = data.pageIndex; - pdfManager.getPage(pageIndex).then(function (page) { - const task = new WorkerTask(`GetOperatorList: page ${pageIndex}`); - startWorkerTask(task); - const start = verbosity >= _util.VerbosityLevel.INFOS ? Date.now() : 0; - page.getOperatorList({ - handler, - sink, - task, - intent: data.intent, - cacheKey: data.cacheKey, - annotationStorage: data.annotationStorage - }).then(function (operatorListInfo) { - finishWorkerTask(task); - - if (start) { - (0, _util.info)(`page=${pageIndex + 1} - getOperatorList: time=` + `${Date.now() - start}ms, len=${operatorListInfo.length}`); - } - - sink.close(); - }, function (reason) { - finishWorkerTask(task); - - if (task.terminated) { - return; - } - - handler.send("UnsupportedFeature", { - featureId: _util.UNSUPPORTED_FEATURES.errorOperatorList - }); - sink.error(reason); - }); - }); - }); - handler.on("GetTextContent", function wphExtractText(data, sink) { - const pageIndex = data.pageIndex; - pdfManager.getPage(pageIndex).then(function (page) { - const task = new WorkerTask("GetTextContent: page " + pageIndex); - startWorkerTask(task); - const start = verbosity >= _util.VerbosityLevel.INFOS ? Date.now() : 0; - page.extractTextContent({ - handler, - task, - sink, - normalizeWhitespace: data.normalizeWhitespace, - includeMarkedContent: data.includeMarkedContent, - combineTextItems: data.combineTextItems - }).then(function () { - finishWorkerTask(task); - - if (start) { - (0, _util.info)(`page=${pageIndex + 1} - getTextContent: time=` + `${Date.now() - start}ms`); - } - - sink.close(); - }, function (reason) { - finishWorkerTask(task); - - if (task.terminated) { - return; - } - - sink.error(reason); - }); - }); - }); - handler.on("GetStructTree", function wphGetStructTree(data) { - return pdfManager.getPage(data.pageIndex).then(function (page) { - return pdfManager.ensure(page, "getStructTree"); - }); - }); - handler.on("FontFallback", function (data) { - return pdfManager.fontFallback(data.id, handler); - }); - handler.on("Cleanup", function wphCleanup(data) { - return pdfManager.cleanup(true); - }); - handler.on("Terminate", function wphTerminate(data) { - terminated = true; - const waitOn = []; - - if (pdfManager) { - pdfManager.terminate(new _util.AbortException("Worker was terminated.")); - const cleanupPromise = pdfManager.cleanup(); - waitOn.push(cleanupPromise); - pdfManager = null; - } else { - (0, _primitives.clearPrimitiveCaches)(); - } - - if (cancelXHRs) { - cancelXHRs(new _util.AbortException("Worker was terminated.")); - } - - for (const task of WorkerTasks) { - waitOn.push(task.finished); - task.terminate(); - } - - return Promise.all(waitOn).then(function () { - handler.destroy(); - handler = null; - }); - }); - handler.on("Ready", function wphReady(data) { - setupDoc(docParams); - docParams = null; - }); - return workerHandlerName; - } - - static initializeFromPort(port) { - const handler = new _message_handler.MessageHandler("worker", "main", port); - WorkerMessageHandler.setup(handler, port); - handler.send("ready", null); - } - -} - -exports.WorkerMessageHandler = WorkerMessageHandler; - -function isMessagePort(maybePort) { - return typeof maybePort.postMessage === "function" && "onmessage" in maybePort; -} - -if (typeof window === "undefined" && !_is_node.isNodeJS && typeof self !== "undefined" && isMessagePort(self)) { - WorkerMessageHandler.initializeFromPort(self); -} - -/***/ }), -/* 2 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.VerbosityLevel = exports.Util = exports.UnknownErrorException = exports.UnexpectedResponseException = exports.UNSUPPORTED_FEATURES = exports.TextRenderingMode = exports.StreamType = exports.RenderingIntentFlag = exports.PermissionFlag = exports.PasswordResponses = exports.PasswordException = exports.PageActionEventType = exports.OPS = exports.MissingPDFException = exports.IsLittleEndianCached = exports.IsEvalSupportedCached = exports.InvalidPDFException = exports.ImageKind = exports.IDENTITY_MATRIX = exports.FormatError = exports.FontType = exports.FONT_IDENTITY_MATRIX = exports.DocumentActionEventType = exports.CMapCompressionType = exports.BaseException = exports.AnnotationType = exports.AnnotationStateModelType = exports.AnnotationReviewState = exports.AnnotationReplyType = exports.AnnotationMode = exports.AnnotationMarkedState = exports.AnnotationFlag = exports.AnnotationFieldFlag = exports.AnnotationBorderStyleType = exports.AnnotationActionEventType = exports.AbortException = void 0; -exports.arrayByteLength = arrayByteLength; -exports.arraysToBytes = arraysToBytes; -exports.assert = assert; -exports.bytesToString = bytesToString; -exports.createObjectURL = createObjectURL; -exports.createPromiseCapability = createPromiseCapability; -exports.createValidAbsoluteUrl = createValidAbsoluteUrl; -exports.escapeString = escapeString; -exports.getModificationDate = getModificationDate; -exports.getVerbosityLevel = getVerbosityLevel; -exports.info = info; -exports.isArrayBuffer = isArrayBuffer; -exports.isArrayEqual = isArrayEqual; -exports.isAscii = isAscii; -exports.isBool = isBool; -exports.isNum = isNum; -exports.isSameOrigin = isSameOrigin; -exports.isString = isString; -exports.objectFromMap = objectFromMap; -exports.objectSize = objectSize; -exports.removeNullCharacters = removeNullCharacters; -exports.setVerbosityLevel = setVerbosityLevel; -exports.shadow = shadow; -exports.string32 = string32; -exports.stringToBytes = stringToBytes; -exports.stringToPDFString = stringToPDFString; -exports.stringToUTF16BEString = stringToUTF16BEString; -exports.stringToUTF8String = stringToUTF8String; -exports.unreachable = unreachable; -exports.utf8StringToString = utf8StringToString; -exports.warn = warn; - -__w_pdfjs_require__(3); - -const IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0]; -exports.IDENTITY_MATRIX = IDENTITY_MATRIX; -const FONT_IDENTITY_MATRIX = [0.001, 0, 0, 0.001, 0, 0]; -exports.FONT_IDENTITY_MATRIX = FONT_IDENTITY_MATRIX; -const RenderingIntentFlag = { - ANY: 0x01, - DISPLAY: 0x02, - PRINT: 0x04, - ANNOTATIONS_FORMS: 0x10, - ANNOTATIONS_STORAGE: 0x20, - ANNOTATIONS_DISABLE: 0x40, - OPLIST: 0x100 -}; -exports.RenderingIntentFlag = RenderingIntentFlag; -const AnnotationMode = { - DISABLE: 0, - ENABLE: 1, - ENABLE_FORMS: 2, - ENABLE_STORAGE: 3 -}; -exports.AnnotationMode = AnnotationMode; -const PermissionFlag = { - PRINT: 0x04, - MODIFY_CONTENTS: 0x08, - COPY: 0x10, - MODIFY_ANNOTATIONS: 0x20, - FILL_INTERACTIVE_FORMS: 0x100, - COPY_FOR_ACCESSIBILITY: 0x200, - ASSEMBLE: 0x400, - PRINT_HIGH_QUALITY: 0x800 -}; -exports.PermissionFlag = PermissionFlag; -const 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 -}; -exports.TextRenderingMode = TextRenderingMode; -const ImageKind = { - GRAYSCALE_1BPP: 1, - RGB_24BPP: 2, - RGBA_32BPP: 3 -}; -exports.ImageKind = ImageKind; -const AnnotationType = { - TEXT: 1, - LINK: 2, - FREETEXT: 3, - LINE: 4, - SQUARE: 5, - CIRCLE: 6, - POLYGON: 7, - POLYLINE: 8, - HIGHLIGHT: 9, - UNDERLINE: 10, - SQUIGGLY: 11, - STRIKEOUT: 12, - STAMP: 13, - CARET: 14, - INK: 15, - POPUP: 16, - FILEATTACHMENT: 17, - SOUND: 18, - MOVIE: 19, - WIDGET: 20, - SCREEN: 21, - PRINTERMARK: 22, - TRAPNET: 23, - WATERMARK: 24, - THREED: 25, - REDACT: 26 -}; -exports.AnnotationType = AnnotationType; -const AnnotationStateModelType = { - MARKED: "Marked", - REVIEW: "Review" -}; -exports.AnnotationStateModelType = AnnotationStateModelType; -const AnnotationMarkedState = { - MARKED: "Marked", - UNMARKED: "Unmarked" -}; -exports.AnnotationMarkedState = AnnotationMarkedState; -const AnnotationReviewState = { - ACCEPTED: "Accepted", - REJECTED: "Rejected", - CANCELLED: "Cancelled", - COMPLETED: "Completed", - NONE: "None" -}; -exports.AnnotationReviewState = AnnotationReviewState; -const AnnotationReplyType = { - GROUP: "Group", - REPLY: "R" -}; -exports.AnnotationReplyType = AnnotationReplyType; -const AnnotationFlag = { - INVISIBLE: 0x01, - HIDDEN: 0x02, - PRINT: 0x04, - NOZOOM: 0x08, - NOROTATE: 0x10, - NOVIEW: 0x20, - READONLY: 0x40, - LOCKED: 0x80, - TOGGLENOVIEW: 0x100, - LOCKEDCONTENTS: 0x200 -}; -exports.AnnotationFlag = AnnotationFlag; -const AnnotationFieldFlag = { - READONLY: 0x0000001, - REQUIRED: 0x0000002, - NOEXPORT: 0x0000004, - MULTILINE: 0x0001000, - PASSWORD: 0x0002000, - NOTOGGLETOOFF: 0x0004000, - RADIO: 0x0008000, - PUSHBUTTON: 0x0010000, - COMBO: 0x0020000, - EDIT: 0x0040000, - SORT: 0x0080000, - FILESELECT: 0x0100000, - MULTISELECT: 0x0200000, - DONOTSPELLCHECK: 0x0400000, - DONOTSCROLL: 0x0800000, - COMB: 0x1000000, - RICHTEXT: 0x2000000, - RADIOSINUNISON: 0x2000000, - COMMITONSELCHANGE: 0x4000000 -}; -exports.AnnotationFieldFlag = AnnotationFieldFlag; -const AnnotationBorderStyleType = { - SOLID: 1, - DASHED: 2, - BEVELED: 3, - INSET: 4, - UNDERLINE: 5 -}; -exports.AnnotationBorderStyleType = AnnotationBorderStyleType; -const AnnotationActionEventType = { - E: "Mouse Enter", - X: "Mouse Exit", - D: "Mouse Down", - U: "Mouse Up", - Fo: "Focus", - Bl: "Blur", - PO: "PageOpen", - PC: "PageClose", - PV: "PageVisible", - PI: "PageInvisible", - K: "Keystroke", - F: "Format", - V: "Validate", - C: "Calculate" -}; -exports.AnnotationActionEventType = AnnotationActionEventType; -const DocumentActionEventType = { - WC: "WillClose", - WS: "WillSave", - DS: "DidSave", - WP: "WillPrint", - DP: "DidPrint" -}; -exports.DocumentActionEventType = DocumentActionEventType; -const PageActionEventType = { - O: "PageOpen", - C: "PageClose" -}; -exports.PageActionEventType = PageActionEventType; -const StreamType = { - UNKNOWN: "UNKNOWN", - FLATE: "FLATE", - LZW: "LZW", - DCT: "DCT", - JPX: "JPX", - JBIG: "JBIG", - A85: "A85", - AHX: "AHX", - CCF: "CCF", - RLX: "RLX" -}; -exports.StreamType = StreamType; -const FontType = { - UNKNOWN: "UNKNOWN", - TYPE1: "TYPE1", - TYPE1STANDARD: "TYPE1STANDARD", - TYPE1C: "TYPE1C", - CIDFONTTYPE0: "CIDFONTTYPE0", - CIDFONTTYPE0C: "CIDFONTTYPE0C", - TRUETYPE: "TRUETYPE", - CIDFONTTYPE2: "CIDFONTTYPE2", - TYPE3: "TYPE3", - OPENTYPE: "OPENTYPE", - TYPE0: "TYPE0", - MMTYPE1: "MMTYPE1" -}; -exports.FontType = FontType; -const VerbosityLevel = { - ERRORS: 0, - WARNINGS: 1, - INFOS: 5 -}; -exports.VerbosityLevel = VerbosityLevel; -const CMapCompressionType = { - NONE: 0, - BINARY: 1, - STREAM: 2 -}; -exports.CMapCompressionType = CMapCompressionType; -const OPS = { - dependency: 1, - setLineWidth: 2, - setLineCap: 3, - setLineJoin: 4, - setMiterLimit: 5, - setDash: 6, - setRenderingIntent: 7, - setFlatness: 8, - setGState: 9, - save: 10, - restore: 11, - transform: 12, - moveTo: 13, - lineTo: 14, - curveTo: 15, - curveTo2: 16, - curveTo3: 17, - closePath: 18, - rectangle: 19, - stroke: 20, - closeStroke: 21, - fill: 22, - eoFill: 23, - fillStroke: 24, - eoFillStroke: 25, - closeFillStroke: 26, - closeEOFillStroke: 27, - endPath: 28, - clip: 29, - eoClip: 30, - beginText: 31, - endText: 32, - setCharSpacing: 33, - setWordSpacing: 34, - setHScale: 35, - setLeading: 36, - setFont: 37, - setTextRenderingMode: 38, - setTextRise: 39, - moveText: 40, - setLeadingMoveText: 41, - setTextMatrix: 42, - nextLine: 43, - showText: 44, - showSpacedText: 45, - nextLineShowText: 46, - nextLineSetSpacingShowText: 47, - setCharWidth: 48, - setCharWidthAndBounds: 49, - setStrokeColorSpace: 50, - setFillColorSpace: 51, - setStrokeColor: 52, - setStrokeColorN: 53, - setFillColor: 54, - setFillColorN: 55, - setStrokeGray: 56, - setFillGray: 57, - setStrokeRGBColor: 58, - setFillRGBColor: 59, - setStrokeCMYKColor: 60, - setFillCMYKColor: 61, - shadingFill: 62, - beginInlineImage: 63, - beginImageData: 64, - endInlineImage: 65, - paintXObject: 66, - markPoint: 67, - markPointProps: 68, - beginMarkedContent: 69, - beginMarkedContentProps: 70, - endMarkedContent: 71, - beginCompat: 72, - endCompat: 73, - paintFormXObjectBegin: 74, - paintFormXObjectEnd: 75, - beginGroup: 76, - endGroup: 77, - beginAnnotations: 78, - endAnnotations: 79, - beginAnnotation: 80, - endAnnotation: 81, - paintJpegXObject: 82, - paintImageMaskXObject: 83, - paintImageMaskXObjectGroup: 84, - paintImageXObject: 85, - paintInlineImageXObject: 86, - paintInlineImageXObjectGroup: 87, - paintImageXObjectRepeat: 88, - paintImageMaskXObjectRepeat: 89, - paintSolidColorImageMask: 90, - constructPath: 91 -}; -exports.OPS = OPS; -const UNSUPPORTED_FEATURES = { - unknown: "unknown", - forms: "forms", - javaScript: "javaScript", - signatures: "signatures", - smask: "smask", - shadingPattern: "shadingPattern", - font: "font", - errorTilingPattern: "errorTilingPattern", - errorExtGState: "errorExtGState", - errorXObject: "errorXObject", - errorFontLoadType3: "errorFontLoadType3", - errorFontState: "errorFontState", - errorFontMissing: "errorFontMissing", - errorFontTranslate: "errorFontTranslate", - errorColorSpace: "errorColorSpace", - errorOperatorList: "errorOperatorList", - errorFontToUnicode: "errorFontToUnicode", - errorFontLoadNative: "errorFontLoadNative", - errorFontBuildPath: "errorFontBuildPath", - errorFontGetPath: "errorFontGetPath", - errorMarkedContent: "errorMarkedContent", - errorContentSubStream: "errorContentSubStream" -}; -exports.UNSUPPORTED_FEATURES = UNSUPPORTED_FEATURES; -const PasswordResponses = { - NEED_PASSWORD: 1, - INCORRECT_PASSWORD: 2 -}; -exports.PasswordResponses = PasswordResponses; -let verbosity = VerbosityLevel.WARNINGS; - -function setVerbosityLevel(level) { - if (Number.isInteger(level)) { - verbosity = level; - } -} - -function getVerbosityLevel() { - return verbosity; -} - -function info(msg) { - if (verbosity >= VerbosityLevel.INFOS) { - console.log(`Info: ${msg}`); - } -} - -function warn(msg) { - if (verbosity >= VerbosityLevel.WARNINGS) { - console.log(`Warning: ${msg}`); - } -} - -function unreachable(msg) { - throw new Error(msg); -} - -function assert(cond, msg) { - if (!cond) { - unreachable(msg); - } -} - -function isSameOrigin(baseUrl, otherUrl) { - let base; - - try { - base = new URL(baseUrl); - - if (!base.origin || base.origin === "null") { - return false; - } - } catch (e) { - return false; - } - - const other = new URL(otherUrl, base); - return base.origin === other.origin; -} - -function _isValidProtocol(url) { - if (!url) { - return false; - } - - switch (url.protocol) { - case "http:": - case "https:": - case "ftp:": - case "mailto:": - case "tel:": - return true; - - default: - return false; - } -} - -function createValidAbsoluteUrl(url, baseUrl = null, options = null) { - if (!url) { - return null; - } - - try { - if (options && typeof url === "string") { - if (options.addDefaultProtocol && url.startsWith("www.")) { - const dots = url.match(/\./g); - - if (dots && dots.length >= 2) { - url = `http://${url}`; - } - } - - if (options.tryConvertEncoding) { - try { - url = stringToUTF8String(url); - } catch (ex) {} - } - } - - const absoluteUrl = baseUrl ? new URL(url, baseUrl) : new URL(url); - - if (_isValidProtocol(absoluteUrl)) { - return absoluteUrl; - } - } catch (ex) {} - - return null; -} - -function shadow(obj, prop, value) { - Object.defineProperty(obj, prop, { - value, - enumerable: true, - configurable: true, - writable: false - }); - return value; -} - -const BaseException = function BaseExceptionClosure() { - function BaseException(message, name) { - if (this.constructor === BaseException) { - unreachable("Cannot initialize BaseException."); - } - - this.message = message; - this.name = name; - } - - BaseException.prototype = new Error(); - BaseException.constructor = BaseException; - return BaseException; -}(); - -exports.BaseException = BaseException; - -class PasswordException extends BaseException { - constructor(msg, code) { - super(msg, "PasswordException"); - this.code = code; - } - -} - -exports.PasswordException = PasswordException; - -class UnknownErrorException extends BaseException { - constructor(msg, details) { - super(msg, "UnknownErrorException"); - this.details = details; - } - -} - -exports.UnknownErrorException = UnknownErrorException; - -class InvalidPDFException extends BaseException { - constructor(msg) { - super(msg, "InvalidPDFException"); - } - -} - -exports.InvalidPDFException = InvalidPDFException; - -class MissingPDFException extends BaseException { - constructor(msg) { - super(msg, "MissingPDFException"); - } - -} - -exports.MissingPDFException = MissingPDFException; - -class UnexpectedResponseException extends BaseException { - constructor(msg, status) { - super(msg, "UnexpectedResponseException"); - this.status = status; - } - -} - -exports.UnexpectedResponseException = UnexpectedResponseException; - -class FormatError extends BaseException { - constructor(msg) { - super(msg, "FormatError"); - } - -} - -exports.FormatError = FormatError; - -class AbortException extends BaseException { - constructor(msg) { - super(msg, "AbortException"); - } - -} - -exports.AbortException = AbortException; -const NullCharactersRegExp = /\x00+/g; -const InvisibleCharactersRegExp = /[\x01-\x1F]/g; - -function removeNullCharacters(str, replaceInvisible = false) { - if (typeof str !== "string") { - warn("The argument for removeNullCharacters must be a string."); - return str; - } - - if (replaceInvisible) { - str = str.replace(InvisibleCharactersRegExp, " "); - } - - return str.replace(NullCharactersRegExp, ""); -} - -function bytesToString(bytes) { - assert(bytes !== null && typeof bytes === "object" && bytes.length !== undefined, "Invalid argument for bytesToString"); - const length = bytes.length; - const MAX_ARGUMENT_COUNT = 8192; - - if (length < MAX_ARGUMENT_COUNT) { - return String.fromCharCode.apply(null, bytes); - } - - const strBuf = []; - - for (let i = 0; i < length; i += MAX_ARGUMENT_COUNT) { - const chunkEnd = Math.min(i + MAX_ARGUMENT_COUNT, length); - const chunk = bytes.subarray(i, chunkEnd); - strBuf.push(String.fromCharCode.apply(null, chunk)); - } - - return strBuf.join(""); -} - -function stringToBytes(str) { - assert(typeof str === "string", "Invalid argument for stringToBytes"); - const length = str.length; - const bytes = new Uint8Array(length); - - for (let i = 0; i < length; ++i) { - bytes[i] = str.charCodeAt(i) & 0xff; - } - - return bytes; -} - -function arrayByteLength(arr) { - if (arr.length !== undefined) { - return arr.length; - } - - assert(arr.byteLength !== undefined, "arrayByteLength - invalid argument."); - return arr.byteLength; -} - -function arraysToBytes(arr) { - const length = arr.length; - - if (length === 1 && arr[0] instanceof Uint8Array) { - return arr[0]; - } - - let resultLength = 0; - - for (let i = 0; i < length; i++) { - resultLength += arrayByteLength(arr[i]); - } - - let pos = 0; - const data = new Uint8Array(resultLength); - - for (let i = 0; i < length; i++) { - let item = arr[i]; - - if (!(item instanceof Uint8Array)) { - if (typeof item === "string") { - item = stringToBytes(item); - } else { - item = new Uint8Array(item); - } - } - - const itemLength = item.byteLength; - data.set(item, pos); - pos += itemLength; - } - - return data; -} - -function string32(value) { - return String.fromCharCode(value >> 24 & 0xff, value >> 16 & 0xff, value >> 8 & 0xff, value & 0xff); -} - -function objectSize(obj) { - return Object.keys(obj).length; -} - -function objectFromMap(map) { - const obj = Object.create(null); - - for (const [key, value] of map) { - obj[key] = value; - } - - return obj; -} - -function isLittleEndian() { - const buffer8 = new Uint8Array(4); - buffer8[0] = 1; - const view32 = new Uint32Array(buffer8.buffer, 0, 1); - return view32[0] === 1; -} - -const IsLittleEndianCached = { - get value() { - return shadow(this, "value", isLittleEndian()); - } - -}; -exports.IsLittleEndianCached = IsLittleEndianCached; - -function isEvalSupported() { - try { - new Function(""); - return true; - } catch (e) { - return false; - } -} - -const IsEvalSupportedCached = { - get value() { - return shadow(this, "value", isEvalSupported()); - } - -}; -exports.IsEvalSupportedCached = IsEvalSupportedCached; -const hexNumbers = [...Array(256).keys()].map(n => n.toString(16).padStart(2, "0")); - -class Util { - static makeHexColor(r, g, b) { - return `#${hexNumbers[r]}${hexNumbers[g]}${hexNumbers[b]}`; - } - - static 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]]; - } - - static applyTransform(p, m) { - const xt = p[0] * m[0] + p[1] * m[2] + m[4]; - const yt = p[0] * m[1] + p[1] * m[3] + m[5]; - return [xt, yt]; - } - - static applyInverseTransform(p, m) { - const d = m[0] * m[3] - m[1] * m[2]; - const xt = (p[0] * m[3] - p[1] * m[2] + m[2] * m[5] - m[4] * m[3]) / d; - const yt = (-p[0] * m[1] + p[1] * m[0] + m[4] * m[1] - m[5] * m[0]) / d; - return [xt, yt]; - } - - static getAxialAlignedBoundingBox(r, m) { - const p1 = Util.applyTransform(r, m); - const p2 = Util.applyTransform(r.slice(2, 4), m); - const p3 = Util.applyTransform([r[0], r[3]], m); - const 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])]; - } - - static inverseTransform(m) { - const 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]; - } - - static 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]]; - } - - static singularValueDecompose2dScale(m) { - const transpose = [m[0], m[2], m[1], m[3]]; - const a = m[0] * transpose[0] + m[1] * transpose[2]; - const b = m[0] * transpose[1] + m[1] * transpose[3]; - const c = m[2] * transpose[0] + m[3] * transpose[2]; - const d = m[2] * transpose[1] + m[3] * transpose[3]; - const first = (a + d) / 2; - const second = Math.sqrt((a + d) ** 2 - 4 * (a * d - c * b)) / 2; - const sx = first + second || 1; - const sy = first - second || 1; - return [Math.sqrt(sx), Math.sqrt(sy)]; - } - - static normalizeRect(rect) { - const r = rect.slice(0); - - 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; - } - - static intersect(rect1, rect2) { - function compare(a, b) { - return a - b; - } - - const orderedX = [rect1[0], rect1[2], rect2[0], rect2[2]].sort(compare); - const orderedY = [rect1[1], rect1[3], rect2[1], rect2[3]].sort(compare); - const result = []; - rect1 = Util.normalizeRect(rect1); - rect2 = Util.normalizeRect(rect2); - - if (orderedX[0] === rect1[0] && orderedX[1] === rect2[0] || orderedX[0] === rect2[0] && orderedX[1] === rect1[0]) { - result[0] = orderedX[1]; - result[2] = orderedX[2]; - } else { - return null; - } - - if (orderedY[0] === rect1[1] && orderedY[1] === rect2[1] || orderedY[0] === rect2[1] && orderedY[1] === rect1[1]) { - result[1] = orderedY[1]; - result[3] = orderedY[2]; - } else { - return null; - } - - return result; - } - - static bezierBoundingBox(x0, y0, x1, y1, x2, y2, x3, y3) { - const tvalues = [], - bounds = [[], []]; - let a, b, c, t, t1, t2, b2ac, sqrtb2ac; - - for (let i = 0; i < 2; ++i) { - if (i === 0) { - b = 6 * x0 - 12 * x1 + 6 * x2; - a = -3 * x0 + 9 * x1 - 9 * x2 + 3 * x3; - c = 3 * x1 - 3 * x0; - } else { - b = 6 * y0 - 12 * y1 + 6 * y2; - a = -3 * y0 + 9 * y1 - 9 * y2 + 3 * y3; - c = 3 * y1 - 3 * y0; - } - - if (Math.abs(a) < 1e-12) { - if (Math.abs(b) < 1e-12) { - continue; - } - - t = -c / b; - - if (0 < t && t < 1) { - tvalues.push(t); - } - - continue; - } - - b2ac = b * b - 4 * c * a; - sqrtb2ac = Math.sqrt(b2ac); - - if (b2ac < 0) { - continue; - } - - t1 = (-b + sqrtb2ac) / (2 * a); - - if (0 < t1 && t1 < 1) { - tvalues.push(t1); - } - - t2 = (-b - sqrtb2ac) / (2 * a); - - if (0 < t2 && t2 < 1) { - tvalues.push(t2); - } - } - - let j = tvalues.length, - mt; - const jlen = j; - - while (j--) { - t = tvalues[j]; - mt = 1 - t; - bounds[0][j] = mt * mt * mt * x0 + 3 * mt * mt * t * x1 + 3 * mt * t * t * x2 + t * t * t * x3; - bounds[1][j] = mt * mt * mt * y0 + 3 * mt * mt * t * y1 + 3 * mt * t * t * y2 + t * t * t * y3; - } - - bounds[0][jlen] = x0; - bounds[1][jlen] = y0; - bounds[0][jlen + 1] = x3; - bounds[1][jlen + 1] = y3; - bounds[0].length = bounds[1].length = jlen + 2; - return [Math.min(...bounds[0]), Math.min(...bounds[1]), Math.max(...bounds[0]), Math.max(...bounds[1])]; - } - -} - -exports.Util = Util; -const 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) { - const length = str.length, - strBuf = []; - - if (str[0] === "\xFE" && str[1] === "\xFF") { - for (let i = 2; i < length; i += 2) { - strBuf.push(String.fromCharCode(str.charCodeAt(i) << 8 | str.charCodeAt(i + 1))); - } - } else if (str[0] === "\xFF" && str[1] === "\xFE") { - for (let i = 2; i < length; i += 2) { - strBuf.push(String.fromCharCode(str.charCodeAt(i + 1) << 8 | str.charCodeAt(i))); - } - } else { - for (let i = 0; i < length; ++i) { - const code = PDFStringTranslateTable[str.charCodeAt(i)]; - strBuf.push(code ? String.fromCharCode(code) : str.charAt(i)); - } - } - - return strBuf.join(""); -} - -function escapeString(str) { - return str.replace(/([()\\\n\r])/g, match => { - if (match === "\n") { - return "\\n"; - } else if (match === "\r") { - return "\\r"; - } - - return `\\${match}`; - }); -} - -function isAscii(str) { - return /^[\x00-\x7F]*$/.test(str); -} - -function stringToUTF16BEString(str) { - const buf = ["\xFE\xFF"]; - - for (let i = 0, ii = str.length; i < ii; i++) { - const char = str.charCodeAt(i); - buf.push(String.fromCharCode(char >> 8 & 0xff), String.fromCharCode(char & 0xff)); - } - - return buf.join(""); -} - -function stringToUTF8String(str) { - return decodeURIComponent(escape(str)); -} - -function utf8StringToString(str) { - return unescape(encodeURIComponent(str)); -} - -function isBool(v) { - return typeof v === "boolean"; -} - -function isNum(v) { - return typeof v === "number"; -} - -function isString(v) { - return typeof v === "string"; -} - -function isArrayBuffer(v) { - return typeof v === "object" && v !== null && v.byteLength !== undefined; -} - -function isArrayEqual(arr1, arr2) { - if (arr1.length !== arr2.length) { - return false; - } - - for (let i = 0, ii = arr1.length; i < ii; i++) { - if (arr1[i] !== arr2[i]) { - return false; - } - } - - return true; -} - -function getModificationDate(date = new Date()) { - const buffer = [date.getUTCFullYear().toString(), (date.getUTCMonth() + 1).toString().padStart(2, "0"), date.getUTCDate().toString().padStart(2, "0"), date.getUTCHours().toString().padStart(2, "0"), date.getUTCMinutes().toString().padStart(2, "0"), date.getUTCSeconds().toString().padStart(2, "0")]; - return buffer.join(""); -} - -function createPromiseCapability() { - const capability = Object.create(null); - let isSettled = false; - Object.defineProperty(capability, "settled", { - get() { - return isSettled; - } - - }); - capability.promise = new Promise(function (resolve, reject) { - capability.resolve = function (data) { - isSettled = true; - resolve(data); - }; - - capability.reject = function (reason) { - isSettled = true; - reject(reason); - }; - }); - return capability; -} - -function createObjectURL(data, contentType = "", forceDataSchema = false) { - if (URL.createObjectURL && typeof Blob !== "undefined" && !forceDataSchema) { - return URL.createObjectURL(new Blob([data], { - type: contentType - })); - } - - const digits = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; - let buffer = `data:${contentType};base64,`; - - for (let i = 0, ii = data.length; i < ii; i += 3) { - const b1 = data[i] & 0xff; - const b2 = data[i + 1] & 0xff; - const b3 = data[i + 2] & 0xff; - const d1 = b1 >> 2, - d2 = (b1 & 3) << 4 | b2 >> 4; - const d3 = i + 1 < ii ? (b2 & 0xf) << 2 | b3 >> 6 : 64; - const d4 = i + 2 < ii ? b3 & 0x3f : 64; - buffer += digits[d1] + digits[d2] + digits[d3] + digits[d4]; - } - - return buffer; -} - -/***/ }), -/* 3 */ -/***/ ((__unused_webpack_module, __unused_webpack_exports, __w_pdfjs_require__) => { - - - -var _is_node = __w_pdfjs_require__(4); - -; - -/***/ }), -/* 4 */ -/***/ ((__unused_webpack_module, exports) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.isNodeJS = void 0; -const isNodeJS = typeof process === "object" && process + "" === "[object process]" && !process.versions.nw && !(process.versions.electron && process.type && process.type !== "browser"); -exports.isNodeJS = isNodeJS; - -/***/ }), -/* 5 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.RefSetCache = exports.RefSet = exports.Ref = exports.Name = exports.EOF = exports.Dict = exports.Cmd = exports.CIRCULAR_REF = void 0; -exports.clearPrimitiveCaches = clearPrimitiveCaches; -exports.isCmd = isCmd; -exports.isDict = isDict; -exports.isName = isName; -exports.isRef = isRef; -exports.isRefsEqual = isRefsEqual; -exports.isStream = isStream; - -var _util = __w_pdfjs_require__(2); - -var _base_stream = __w_pdfjs_require__(6); - -const CIRCULAR_REF = Symbol("CIRCULAR_REF"); -exports.CIRCULAR_REF = CIRCULAR_REF; -const EOF = Symbol("EOF"); -exports.EOF = EOF; - -const Name = function NameClosure() { - let nameCache = Object.create(null); - - class Name { - constructor(name) { - this.name = name; - } - - static get(name) { - const nameValue = nameCache[name]; - return nameValue ? nameValue : nameCache[name] = new Name(name); - } - - static _clearCache() { - nameCache = Object.create(null); - } - - } - - return Name; -}(); - -exports.Name = Name; - -const Cmd = function CmdClosure() { - let cmdCache = Object.create(null); - - class Cmd { - constructor(cmd) { - this.cmd = cmd; - } - - static get(cmd) { - const cmdValue = cmdCache[cmd]; - return cmdValue ? cmdValue : cmdCache[cmd] = new Cmd(cmd); - } - - static _clearCache() { - cmdCache = Object.create(null); - } - - } - - return Cmd; -}(); - -exports.Cmd = Cmd; - -const nonSerializable = function nonSerializableClosure() { - return nonSerializable; -}; - -class Dict { - constructor(xref = null) { - this._map = Object.create(null); - this.xref = xref; - this.objId = null; - this.suppressEncryption = false; - this.__nonSerializable__ = nonSerializable; - } - - assignXref(newXref) { - this.xref = newXref; - } - - get size() { - return Object.keys(this._map).length; - } - - get(key1, key2, key3) { - let value = this._map[key1]; - - if (value === undefined && key2 !== undefined) { - value = this._map[key2]; - - if (value === undefined && key3 !== undefined) { - value = this._map[key3]; - } - } - - if (value instanceof Ref && this.xref) { - return this.xref.fetch(value, this.suppressEncryption); - } - - return value; - } - - async getAsync(key1, key2, key3) { - let value = this._map[key1]; - - if (value === undefined && key2 !== undefined) { - value = this._map[key2]; - - if (value === undefined && key3 !== undefined) { - value = this._map[key3]; - } - } - - if (value instanceof Ref && this.xref) { - return this.xref.fetchAsync(value, this.suppressEncryption); - } - - return value; - } - - getArray(key1, key2, key3) { - let value = this._map[key1]; - - if (value === undefined && key2 !== undefined) { - value = this._map[key2]; - - if (value === undefined && key3 !== undefined) { - value = this._map[key3]; - } - } - - if (value instanceof Ref && this.xref) { - value = this.xref.fetch(value, this.suppressEncryption); - } - - if (Array.isArray(value)) { - value = value.slice(); - - for (let i = 0, ii = value.length; i < ii; i++) { - if (value[i] instanceof Ref && this.xref) { - value[i] = this.xref.fetch(value[i], this.suppressEncryption); - } - } - } - - return value; - } - - getRaw(key) { - return this._map[key]; - } - - getKeys() { - return Object.keys(this._map); - } - - getRawValues() { - return Object.values(this._map); - } - - set(key, value) { - this._map[key] = value; - } - - has(key) { - return this._map[key] !== undefined; - } - - forEach(callback) { - for (const key in this._map) { - callback(key, this.get(key)); - } - } - - static get empty() { - const emptyDict = new Dict(null); - - emptyDict.set = (key, value) => { - (0, _util.unreachable)("Should not call `set` on the empty dictionary."); - }; - - return (0, _util.shadow)(this, "empty", emptyDict); - } - - static merge({ - xref, - dictArray, - mergeSubDicts = false - }) { - const mergedDict = new Dict(xref), - properties = new Map(); - - for (const dict of dictArray) { - if (!(dict instanceof Dict)) { - continue; - } - - for (const [key, value] of Object.entries(dict._map)) { - let property = properties.get(key); - - if (property === undefined) { - property = []; - properties.set(key, property); - } else if (!mergeSubDicts || !(value instanceof Dict)) { - continue; - } - - property.push(value); - } - } - - for (const [name, values] of properties) { - if (values.length === 1 || !(values[0] instanceof Dict)) { - mergedDict._map[name] = values[0]; - continue; - } - - const subDict = new Dict(xref); - - for (const dict of values) { - for (const [key, value] of Object.entries(dict._map)) { - if (subDict._map[key] === undefined) { - subDict._map[key] = value; - } - } - } - - if (subDict.size > 0) { - mergedDict._map[name] = subDict; - } - } - - properties.clear(); - return mergedDict.size > 0 ? mergedDict : Dict.empty; - } - -} - -exports.Dict = Dict; - -const Ref = function RefClosure() { - let refCache = Object.create(null); - - class Ref { - constructor(num, gen) { - this.num = num; - this.gen = gen; - } - - toString() { - if (this.gen === 0) { - return `${this.num}R`; - } - - return `${this.num}R${this.gen}`; - } - - static get(num, gen) { - const key = gen === 0 ? `${num}R` : `${num}R${gen}`; - const refValue = refCache[key]; - return refValue ? refValue : refCache[key] = new Ref(num, gen); - } - - static _clearCache() { - refCache = Object.create(null); - } - - } - - return Ref; -}(); - -exports.Ref = Ref; - -class RefSet { - constructor(parent = null) { - this._set = new Set(parent && parent._set); - } - - has(ref) { - return this._set.has(ref.toString()); - } - - put(ref) { - this._set.add(ref.toString()); - } - - remove(ref) { - this._set.delete(ref.toString()); - } - - forEach(callback) { - for (const ref of this._set.values()) { - callback(ref); - } - } - - clear() { - this._set.clear(); - } - -} - -exports.RefSet = RefSet; - -class RefSetCache { - constructor() { - this._map = new Map(); - } - - get size() { - return this._map.size; - } - - get(ref) { - return this._map.get(ref.toString()); - } - - has(ref) { - return this._map.has(ref.toString()); - } - - put(ref, obj) { - this._map.set(ref.toString(), obj); - } - - putAlias(ref, aliasRef) { - this._map.set(ref.toString(), this.get(aliasRef)); - } - - forEach(callback) { - for (const value of this._map.values()) { - callback(value); - } - } - - clear() { - this._map.clear(); - } - -} - -exports.RefSetCache = RefSetCache; - -function isName(v, name) { - return v instanceof Name && (name === undefined || v.name === name); -} - -function isCmd(v, cmd) { - return v instanceof Cmd && (cmd === undefined || v.cmd === cmd); -} - -function isDict(v, type) { - return v instanceof Dict && (type === undefined || isName(v.get("Type"), type)); -} - -function isRef(v) { - return v instanceof Ref; -} - -function isRefsEqual(v1, v2) { - return v1.num === v2.num && v1.gen === v2.gen; -} - -function isStream(v) { - return v instanceof _base_stream.BaseStream; -} - -function clearPrimitiveCaches() { - Cmd._clearCache(); - - Name._clearCache(); - - Ref._clearCache(); -} - -/***/ }), -/* 6 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.BaseStream = void 0; - -var _util = __w_pdfjs_require__(2); - -class BaseStream { - constructor() { - if (this.constructor === BaseStream) { - (0, _util.unreachable)("Cannot initialize BaseStream."); - } - } - - get length() { - (0, _util.unreachable)("Abstract getter `length` accessed"); - } - - get isEmpty() { - (0, _util.unreachable)("Abstract getter `isEmpty` accessed"); - } - - get isDataLoaded() { - return (0, _util.shadow)(this, "isDataLoaded", true); - } - - getByte() { - (0, _util.unreachable)("Abstract method `getByte` called"); - } - - getBytes(length, forceClamped = false) { - (0, _util.unreachable)("Abstract method `getBytes` called"); - } - - peekByte() { - const peekedByte = this.getByte(); - - if (peekedByte !== -1) { - this.pos--; - } - - return peekedByte; - } - - peekBytes(length, forceClamped = false) { - const bytes = this.getBytes(length, forceClamped); - this.pos -= bytes.length; - return bytes; - } - - getUint16() { - const b0 = this.getByte(); - const b1 = this.getByte(); - - if (b0 === -1 || b1 === -1) { - return -1; - } - - return (b0 << 8) + b1; - } - - getInt32() { - const b0 = this.getByte(); - const b1 = this.getByte(); - const b2 = this.getByte(); - const b3 = this.getByte(); - return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3; - } - - getByteRange(begin, end) { - (0, _util.unreachable)("Abstract method `getByteRange` called"); - } - - getString(length) { - return (0, _util.bytesToString)(this.getBytes(length, false)); - } - - skip(n) { - this.pos += n || 1; - } - - reset() { - (0, _util.unreachable)("Abstract method `reset` called"); - } - - moveStart() { - (0, _util.unreachable)("Abstract method `moveStart` called"); - } - - makeSubStream(start, length, dict = null) { - (0, _util.unreachable)("Abstract method `makeSubStream` called"); - } - - getBaseStreams() { - return null; - } - -} - -exports.BaseStream = BaseStream; - -/***/ }), -/* 7 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.NetworkPdfManager = exports.LocalPdfManager = void 0; - -var _util = __w_pdfjs_require__(2); - -var _chunked_stream = __w_pdfjs_require__(8); - -var _core_utils = __w_pdfjs_require__(9); - -var _document = __w_pdfjs_require__(11); - -var _stream = __w_pdfjs_require__(10); - -function parseDocBaseUrl(url) { - if (url) { - const absoluteUrl = (0, _util.createValidAbsoluteUrl)(url); - - if (absoluteUrl) { - return absoluteUrl.href; - } - - (0, _util.warn)(`Invalid absolute docBaseUrl: "${url}".`); - } - - return null; -} - -class BasePdfManager { - constructor() { - if (this.constructor === BasePdfManager) { - (0, _util.unreachable)("Cannot initialize BasePdfManager."); - } - } - - get docId() { - return this._docId; - } - - get password() { - return this._password; - } - - get docBaseUrl() { - return this._docBaseUrl; - } - - onLoadedStream() { - (0, _util.unreachable)("Abstract method `onLoadedStream` called"); - } - - ensureDoc(prop, args) { - return this.ensure(this.pdfDocument, prop, args); - } - - ensureXRef(prop, args) { - return this.ensure(this.pdfDocument.xref, prop, args); - } - - ensureCatalog(prop, args) { - return this.ensure(this.pdfDocument.catalog, prop, args); - } - - getPage(pageIndex) { - return this.pdfDocument.getPage(pageIndex); - } - - fontFallback(id, handler) { - return this.pdfDocument.fontFallback(id, handler); - } - - loadXfaFonts(handler, task) { - return this.pdfDocument.loadXfaFonts(handler, task); - } - - loadXfaImages() { - return this.pdfDocument.loadXfaImages(); - } - - serializeXfaData(annotationStorage) { - return this.pdfDocument.serializeXfaData(annotationStorage); - } - - cleanup(manuallyTriggered = false) { - return this.pdfDocument.cleanup(manuallyTriggered); - } - - async ensure(obj, prop, args) { - (0, _util.unreachable)("Abstract method `ensure` called"); - } - - requestRange(begin, end) { - (0, _util.unreachable)("Abstract method `requestRange` called"); - } - - requestLoadedStream() { - (0, _util.unreachable)("Abstract method `requestLoadedStream` called"); - } - - sendProgressiveData(chunk) { - (0, _util.unreachable)("Abstract method `sendProgressiveData` called"); - } - - updatePassword(password) { - this._password = password; - } - - terminate(reason) { - (0, _util.unreachable)("Abstract method `terminate` called"); - } - -} - -class LocalPdfManager extends BasePdfManager { - constructor(docId, data, password, msgHandler, evaluatorOptions, enableXfa, docBaseUrl) { - super(); - this._docId = docId; - this._password = password; - this._docBaseUrl = parseDocBaseUrl(docBaseUrl); - this.msgHandler = msgHandler; - this.evaluatorOptions = evaluatorOptions; - this.enableXfa = enableXfa; - const stream = new _stream.Stream(data); - this.pdfDocument = new _document.PDFDocument(this, stream); - this._loadedStreamPromise = Promise.resolve(stream); - } - - async ensure(obj, prop, args) { - const value = obj[prop]; - - if (typeof value === "function") { - return value.apply(obj, args); - } - - return value; - } - - requestRange(begin, end) { - return Promise.resolve(); - } - - requestLoadedStream() {} - - onLoadedStream() { - return this._loadedStreamPromise; - } - - terminate(reason) {} - -} - -exports.LocalPdfManager = LocalPdfManager; - -class NetworkPdfManager extends BasePdfManager { - constructor(docId, pdfNetworkStream, args, evaluatorOptions, enableXfa, docBaseUrl) { - super(); - this._docId = docId; - this._password = args.password; - this._docBaseUrl = parseDocBaseUrl(docBaseUrl); - this.msgHandler = args.msgHandler; - this.evaluatorOptions = evaluatorOptions; - this.enableXfa = enableXfa; - this.streamManager = new _chunked_stream.ChunkedStreamManager(pdfNetworkStream, { - msgHandler: args.msgHandler, - length: args.length, - disableAutoFetch: args.disableAutoFetch, - rangeChunkSize: args.rangeChunkSize - }); - this.pdfDocument = new _document.PDFDocument(this, this.streamManager.getStream()); - } - - async ensure(obj, prop, args) { - try { - const value = obj[prop]; - - if (typeof value === "function") { - return value.apply(obj, args); - } - - return value; - } catch (ex) { - if (!(ex instanceof _core_utils.MissingDataException)) { - throw ex; - } - - await this.requestRange(ex.begin, ex.end); - return this.ensure(obj, prop, args); - } - } - - requestRange(begin, end) { - return this.streamManager.requestRange(begin, end); - } - - requestLoadedStream() { - this.streamManager.requestAllChunks(); - } - - sendProgressiveData(chunk) { - this.streamManager.onReceiveData({ - chunk - }); - } - - onLoadedStream() { - return this.streamManager.onLoadedStream(); - } - - terminate(reason) { - this.streamManager.abort(reason); - } - -} - -exports.NetworkPdfManager = NetworkPdfManager; - -/***/ }), -/* 8 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.ChunkedStreamManager = exports.ChunkedStream = void 0; - -var _util = __w_pdfjs_require__(2); - -var _core_utils = __w_pdfjs_require__(9); - -var _stream = __w_pdfjs_require__(10); - -class ChunkedStream extends _stream.Stream { - constructor(length, chunkSize, manager) { - super(new Uint8Array(length), 0, length, null); - this.chunkSize = chunkSize; - this._loadedChunks = new Set(); - this.numChunks = Math.ceil(length / chunkSize); - this.manager = manager; - this.progressiveDataLength = 0; - this.lastSuccessfulEnsureByteChunk = -1; - } - - getMissingChunks() { - const chunks = []; - - for (let chunk = 0, n = this.numChunks; chunk < n; ++chunk) { - if (!this._loadedChunks.has(chunk)) { - chunks.push(chunk); - } - } - - return chunks; - } - - get numChunksLoaded() { - return this._loadedChunks.size; - } - - get isDataLoaded() { - return this.numChunksLoaded === this.numChunks; - } - - onReceiveData(begin, chunk) { - const chunkSize = this.chunkSize; - - if (begin % chunkSize !== 0) { - throw new Error(`Bad begin offset: ${begin}`); - } - - const end = begin + chunk.byteLength; - - if (end % chunkSize !== 0 && end !== this.bytes.length) { - throw new Error(`Bad end offset: ${end}`); - } - - this.bytes.set(new Uint8Array(chunk), begin); - const beginChunk = Math.floor(begin / chunkSize); - const endChunk = Math.floor((end - 1) / chunkSize) + 1; - - for (let curChunk = beginChunk; curChunk < endChunk; ++curChunk) { - this._loadedChunks.add(curChunk); - } - } - - onReceiveProgressiveData(data) { - let position = this.progressiveDataLength; - const beginChunk = Math.floor(position / this.chunkSize); - this.bytes.set(new Uint8Array(data), position); - position += data.byteLength; - this.progressiveDataLength = position; - const endChunk = position >= this.end ? this.numChunks : Math.floor(position / this.chunkSize); - - for (let curChunk = beginChunk; curChunk < endChunk; ++curChunk) { - this._loadedChunks.add(curChunk); - } - } - - ensureByte(pos) { - if (pos < this.progressiveDataLength) { - return; - } - - const chunk = Math.floor(pos / this.chunkSize); - - if (chunk > this.numChunks) { - return; - } - - if (chunk === this.lastSuccessfulEnsureByteChunk) { - return; - } - - if (!this._loadedChunks.has(chunk)) { - throw new _core_utils.MissingDataException(pos, pos + 1); - } - - this.lastSuccessfulEnsureByteChunk = chunk; - } - - ensureRange(begin, end) { - if (begin >= end) { - return; - } - - if (end <= this.progressiveDataLength) { - return; - } - - const beginChunk = Math.floor(begin / this.chunkSize); - - if (beginChunk > this.numChunks) { - return; - } - - const endChunk = Math.min(Math.floor((end - 1) / this.chunkSize) + 1, this.numChunks); - - for (let chunk = beginChunk; chunk < endChunk; ++chunk) { - if (!this._loadedChunks.has(chunk)) { - throw new _core_utils.MissingDataException(begin, end); - } - } - } - - nextEmptyChunk(beginChunk) { - const numChunks = this.numChunks; - - for (let i = 0; i < numChunks; ++i) { - const chunk = (beginChunk + i) % numChunks; - - if (!this._loadedChunks.has(chunk)) { - return chunk; - } - } - - return null; - } - - hasChunk(chunk) { - return this._loadedChunks.has(chunk); - } - - getByte() { - const pos = this.pos; - - if (pos >= this.end) { - return -1; - } - - if (pos >= this.progressiveDataLength) { - this.ensureByte(pos); - } - - return this.bytes[this.pos++]; - } - - getBytes(length, forceClamped = false) { - const bytes = this.bytes; - const pos = this.pos; - const strEnd = this.end; - - if (!length) { - if (strEnd > this.progressiveDataLength) { - this.ensureRange(pos, strEnd); - } - - const subarray = bytes.subarray(pos, strEnd); - return forceClamped ? new Uint8ClampedArray(subarray) : subarray; - } - - let end = pos + length; - - if (end > strEnd) { - end = strEnd; - } - - if (end > this.progressiveDataLength) { - this.ensureRange(pos, end); - } - - this.pos = end; - const subarray = bytes.subarray(pos, end); - return forceClamped ? new Uint8ClampedArray(subarray) : subarray; - } - - getByteRange(begin, end) { - if (begin < 0) { - begin = 0; - } - - if (end > this.end) { - end = this.end; - } - - if (end > this.progressiveDataLength) { - this.ensureRange(begin, end); - } - - return this.bytes.subarray(begin, end); - } - - makeSubStream(start, length, dict = null) { - if (length) { - if (start + length > this.progressiveDataLength) { - this.ensureRange(start, start + length); - } - } else { - if (start >= this.progressiveDataLength) { - this.ensureByte(start); - } - } - - function ChunkedStreamSubstream() {} - - ChunkedStreamSubstream.prototype = Object.create(this); - - ChunkedStreamSubstream.prototype.getMissingChunks = function () { - const chunkSize = this.chunkSize; - const beginChunk = Math.floor(this.start / chunkSize); - const endChunk = Math.floor((this.end - 1) / chunkSize) + 1; - const missingChunks = []; - - for (let chunk = beginChunk; chunk < endChunk; ++chunk) { - if (!this._loadedChunks.has(chunk)) { - missingChunks.push(chunk); - } - } - - return missingChunks; - }; - - Object.defineProperty(ChunkedStreamSubstream.prototype, "isDataLoaded", { - get() { - if (this.numChunksLoaded === this.numChunks) { - return true; - } - - return this.getMissingChunks().length === 0; - }, - - configurable: true - }); - const subStream = new ChunkedStreamSubstream(); - subStream.pos = subStream.start = start; - subStream.end = start + length || this.end; - subStream.dict = dict; - return subStream; - } - - getBaseStreams() { - return [this]; - } - -} - -exports.ChunkedStream = ChunkedStream; - -class ChunkedStreamManager { - constructor(pdfNetworkStream, args) { - this.length = args.length; - this.chunkSize = args.rangeChunkSize; - this.stream = new ChunkedStream(this.length, this.chunkSize, this); - this.pdfNetworkStream = pdfNetworkStream; - this.disableAutoFetch = args.disableAutoFetch; - this.msgHandler = args.msgHandler; - this.currRequestId = 0; - this._chunksNeededByRequest = new Map(); - this._requestsByChunk = new Map(); - this._promisesByRequest = new Map(); - this.progressiveDataLength = 0; - this.aborted = false; - this._loadedStreamCapability = (0, _util.createPromiseCapability)(); - } - - onLoadedStream() { - return this._loadedStreamCapability.promise; - } - - sendRequest(begin, end) { - const rangeReader = this.pdfNetworkStream.getRangeReader(begin, end); - - if (!rangeReader.isStreamingSupported) { - rangeReader.onProgress = this.onProgress.bind(this); - } - - let chunks = [], - loaded = 0; - return new Promise((resolve, reject) => { - const readChunk = chunk => { - try { - if (!chunk.done) { - const data = chunk.value; - chunks.push(data); - loaded += (0, _util.arrayByteLength)(data); - - if (rangeReader.isStreamingSupported) { - this.onProgress({ - loaded - }); - } - - rangeReader.read().then(readChunk, reject); - return; - } - - const chunkData = (0, _util.arraysToBytes)(chunks); - chunks = null; - resolve(chunkData); - } catch (e) { - reject(e); - } - }; - - rangeReader.read().then(readChunk, reject); - }).then(data => { - if (this.aborted) { - return; - } - - this.onReceiveData({ - chunk: data, - begin - }); - }); - } - - requestAllChunks() { - const missingChunks = this.stream.getMissingChunks(); - - this._requestChunks(missingChunks); - - return this._loadedStreamCapability.promise; - } - - _requestChunks(chunks) { - const requestId = this.currRequestId++; - const chunksNeeded = new Set(); - - this._chunksNeededByRequest.set(requestId, chunksNeeded); - - for (const chunk of chunks) { - if (!this.stream.hasChunk(chunk)) { - chunksNeeded.add(chunk); - } - } - - if (chunksNeeded.size === 0) { - return Promise.resolve(); - } - - const capability = (0, _util.createPromiseCapability)(); - - this._promisesByRequest.set(requestId, capability); - - const chunksToRequest = []; - - for (const chunk of chunksNeeded) { - let requestIds = this._requestsByChunk.get(chunk); - - if (!requestIds) { - requestIds = []; - - this._requestsByChunk.set(chunk, requestIds); - - chunksToRequest.push(chunk); - } - - requestIds.push(requestId); - } - - if (chunksToRequest.length > 0) { - const groupedChunksToRequest = this.groupChunks(chunksToRequest); - - for (const groupedChunk of groupedChunksToRequest) { - const begin = groupedChunk.beginChunk * this.chunkSize; - const end = Math.min(groupedChunk.endChunk * this.chunkSize, this.length); - this.sendRequest(begin, end).catch(capability.reject); - } - } - - return capability.promise.catch(reason => { - if (this.aborted) { - return; - } - - throw reason; - }); - } - - getStream() { - return this.stream; - } - - requestRange(begin, end) { - end = Math.min(end, this.length); - const beginChunk = this.getBeginChunk(begin); - const endChunk = this.getEndChunk(end); - const chunks = []; - - for (let chunk = beginChunk; chunk < endChunk; ++chunk) { - chunks.push(chunk); - } - - return this._requestChunks(chunks); - } - - requestRanges(ranges = []) { - const chunksToRequest = []; - - for (const range of ranges) { - const beginChunk = this.getBeginChunk(range.begin); - const endChunk = this.getEndChunk(range.end); - - for (let chunk = beginChunk; chunk < endChunk; ++chunk) { - if (!chunksToRequest.includes(chunk)) { - chunksToRequest.push(chunk); - } - } - } - - chunksToRequest.sort(function (a, b) { - return a - b; - }); - return this._requestChunks(chunksToRequest); - } - - groupChunks(chunks) { - const groupedChunks = []; - let beginChunk = -1; - let prevChunk = -1; - - for (let i = 0, ii = chunks.length; i < ii; ++i) { - const chunk = chunks[i]; - - if (beginChunk < 0) { - beginChunk = chunk; - } - - if (prevChunk >= 0 && prevChunk + 1 !== chunk) { - groupedChunks.push({ - beginChunk, - endChunk: prevChunk + 1 - }); - beginChunk = chunk; - } - - if (i + 1 === chunks.length) { - groupedChunks.push({ - beginChunk, - endChunk: chunk + 1 - }); - } - - prevChunk = chunk; - } - - return groupedChunks; - } - - onProgress(args) { - this.msgHandler.send("DocProgress", { - loaded: this.stream.numChunksLoaded * this.chunkSize + args.loaded, - total: this.length - }); - } - - onReceiveData(args) { - const chunk = args.chunk; - const isProgressive = args.begin === undefined; - const begin = isProgressive ? this.progressiveDataLength : args.begin; - const end = begin + chunk.byteLength; - const beginChunk = Math.floor(begin / this.chunkSize); - const endChunk = end < this.length ? Math.floor(end / this.chunkSize) : Math.ceil(end / this.chunkSize); - - if (isProgressive) { - this.stream.onReceiveProgressiveData(chunk); - this.progressiveDataLength = end; - } else { - this.stream.onReceiveData(begin, chunk); - } - - if (this.stream.isDataLoaded) { - this._loadedStreamCapability.resolve(this.stream); - } - - const loadedRequests = []; - - for (let curChunk = beginChunk; curChunk < endChunk; ++curChunk) { - const requestIds = this._requestsByChunk.get(curChunk); - - if (!requestIds) { - continue; - } - - this._requestsByChunk.delete(curChunk); - - for (const requestId of requestIds) { - const chunksNeeded = this._chunksNeededByRequest.get(requestId); - - if (chunksNeeded.has(curChunk)) { - chunksNeeded.delete(curChunk); - } - - if (chunksNeeded.size > 0) { - continue; - } - - loadedRequests.push(requestId); - } - } - - if (!this.disableAutoFetch && this._requestsByChunk.size === 0) { - let nextEmptyChunk; - - if (this.stream.numChunksLoaded === 1) { - const lastChunk = this.stream.numChunks - 1; - - if (!this.stream.hasChunk(lastChunk)) { - nextEmptyChunk = lastChunk; - } - } else { - nextEmptyChunk = this.stream.nextEmptyChunk(endChunk); - } - - if (Number.isInteger(nextEmptyChunk)) { - this._requestChunks([nextEmptyChunk]); - } - } - - for (const requestId of loadedRequests) { - const capability = this._promisesByRequest.get(requestId); - - this._promisesByRequest.delete(requestId); - - capability.resolve(); - } - - this.msgHandler.send("DocProgress", { - loaded: this.stream.numChunksLoaded * this.chunkSize, - total: this.length - }); - } - - onError(err) { - this._loadedStreamCapability.reject(err); - } - - getBeginChunk(begin) { - return Math.floor(begin / this.chunkSize); - } - - getEndChunk(end) { - return Math.floor((end - 1) / this.chunkSize) + 1; - } - - abort(reason) { - this.aborted = true; - - if (this.pdfNetworkStream) { - this.pdfNetworkStream.cancelAllRequests(reason); - } - - for (const capability of this._promisesByRequest.values()) { - capability.reject(reason); - } - } - -} - -exports.ChunkedStreamManager = ChunkedStreamManager; - -/***/ }), -/* 9 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.XRefParseException = exports.XRefEntryException = exports.ParserEOFException = exports.MissingDataException = exports.DocStats = void 0; -exports.collectActions = collectActions; -exports.encodeToXmlString = encodeToXmlString; -exports.escapePDFName = escapePDFName; -exports.getArrayLookupTableFactory = getArrayLookupTableFactory; -exports.getInheritableProperty = getInheritableProperty; -exports.getLookupTableFactory = getLookupTableFactory; -exports.isWhiteSpace = isWhiteSpace; -exports.log2 = log2; -exports.parseXFAPath = parseXFAPath; -exports.readInt8 = readInt8; -exports.readUint16 = readUint16; -exports.readUint32 = readUint32; -exports.recoverJsURL = recoverJsURL; -exports.toRomanNumerals = toRomanNumerals; -exports.validateCSSFont = validateCSSFont; - -var _util = __w_pdfjs_require__(2); - -var _primitives = __w_pdfjs_require__(5); - -function getLookupTableFactory(initializer) { - let lookup; - return function () { - if (initializer) { - lookup = Object.create(null); - initializer(lookup); - initializer = null; - } - - return lookup; - }; -} - -function getArrayLookupTableFactory(initializer) { - let lookup; - return function () { - if (initializer) { - let arr = initializer(); - initializer = null; - lookup = Object.create(null); - - for (let i = 0, ii = arr.length; i < ii; i += 2) { - lookup[arr[i]] = arr[i + 1]; - } - - arr = null; - } - - return lookup; - }; -} - -class MissingDataException extends _util.BaseException { - constructor(begin, end) { - super(`Missing data [${begin}, ${end})`, "MissingDataException"); - this.begin = begin; - this.end = end; - } - -} - -exports.MissingDataException = MissingDataException; - -class ParserEOFException extends _util.BaseException { - constructor(msg) { - super(msg, "ParserEOFException"); - } - -} - -exports.ParserEOFException = ParserEOFException; - -class XRefEntryException extends _util.BaseException { - constructor(msg) { - super(msg, "XRefEntryException"); - } - -} - -exports.XRefEntryException = XRefEntryException; - -class XRefParseException extends _util.BaseException { - constructor(msg) { - super(msg, "XRefParseException"); - } - -} - -exports.XRefParseException = XRefParseException; - -class DocStats { - constructor(handler) { - this._handler = handler; - this._streamTypes = new Set(); - this._fontTypes = new Set(); - } - - _send() { - const streamTypes = Object.create(null), - fontTypes = Object.create(null); - - for (const type of this._streamTypes) { - streamTypes[type] = true; - } - - for (const type of this._fontTypes) { - fontTypes[type] = true; - } - - this._handler.send("DocStats", { - streamTypes, - fontTypes - }); - } - - addStreamType(type) { - if (this._streamTypes.has(type)) { - return; - } - - this._streamTypes.add(type); - - this._send(); - } - - addFontType(type) { - if (this._fontTypes.has(type)) { - return; - } - - this._fontTypes.add(type); - - this._send(); - } - -} - -exports.DocStats = DocStats; - -function getInheritableProperty({ - dict, - key, - getArray = false, - stopWhenFound = true -}) { - let values; - const visited = new _primitives.RefSet(); - - while (dict instanceof _primitives.Dict && !(dict.objId && visited.has(dict.objId))) { - if (dict.objId) { - visited.put(dict.objId); - } - - const value = getArray ? dict.getArray(key) : dict.get(key); - - if (value !== undefined) { - if (stopWhenFound) { - return value; - } - - if (!values) { - values = []; - } - - values.push(value); - } - - dict = dict.get("Parent"); - } - - return values; -} - -const ROMAN_NUMBER_MAP = ["", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM", "", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC", "", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"]; - -function toRomanNumerals(number, lowerCase = false) { - (0, _util.assert)(Number.isInteger(number) && number > 0, "The number should be a positive integer."); - const romanBuf = []; - let pos; - - while (number >= 1000) { - number -= 1000; - romanBuf.push("M"); - } - - pos = number / 100 | 0; - number %= 100; - romanBuf.push(ROMAN_NUMBER_MAP[pos]); - pos = number / 10 | 0; - number %= 10; - romanBuf.push(ROMAN_NUMBER_MAP[10 + pos]); - romanBuf.push(ROMAN_NUMBER_MAP[20 + number]); - const romanStr = romanBuf.join(""); - return lowerCase ? romanStr.toLowerCase() : romanStr; -} - -function log2(x) { - if (x <= 0) { - return 0; - } - - return Math.ceil(Math.log2(x)); -} - -function readInt8(data, offset) { - return data[offset] << 24 >> 24; -} - -function readUint16(data, offset) { - return data[offset] << 8 | data[offset + 1]; -} - -function readUint32(data, offset) { - return (data[offset] << 24 | data[offset + 1] << 16 | data[offset + 2] << 8 | data[offset + 3]) >>> 0; -} - -function isWhiteSpace(ch) { - return ch === 0x20 || ch === 0x09 || ch === 0x0d || ch === 0x0a; -} - -function parseXFAPath(path) { - const positionPattern = /(.+)\[(\d+)\]$/; - return path.split(".").map(component => { - const m = component.match(positionPattern); - - if (m) { - return { - name: m[1], - pos: parseInt(m[2], 10) - }; - } - - return { - name: component, - pos: 0 - }; - }); -} - -function escapePDFName(str) { - const buffer = []; - let start = 0; - - for (let i = 0, ii = str.length; i < ii; i++) { - const char = str.charCodeAt(i); - - if (char < 0x21 || char > 0x7e || char === 0x23 || char === 0x28 || char === 0x29 || char === 0x3c || char === 0x3e || char === 0x5b || char === 0x5d || char === 0x7b || char === 0x7d || char === 0x2f || char === 0x25) { - if (start < i) { - buffer.push(str.substring(start, i)); - } - - buffer.push(`#${char.toString(16)}`); - start = i + 1; - } - } - - if (buffer.length === 0) { - return str; - } - - if (start < str.length) { - buffer.push(str.substring(start, str.length)); - } - - return buffer.join(""); -} - -function _collectJS(entry, xref, list, parents) { - if (!entry) { - return; - } - - let parent = null; - - if ((0, _primitives.isRef)(entry)) { - if (parents.has(entry)) { - return; - } - - parent = entry; - parents.put(parent); - entry = xref.fetch(entry); - } - - if (Array.isArray(entry)) { - for (const element of entry) { - _collectJS(element, xref, list, parents); - } - } else if (entry instanceof _primitives.Dict) { - if ((0, _primitives.isName)(entry.get("S"), "JavaScript") && entry.has("JS")) { - const js = entry.get("JS"); - let code; - - if ((0, _primitives.isStream)(js)) { - code = js.getString(); - } else { - code = js; - } - - code = (0, _util.stringToPDFString)(code); - - if (code) { - list.push(code); - } - } - - _collectJS(entry.getRaw("Next"), xref, list, parents); - } - - if (parent) { - parents.remove(parent); - } -} - -function collectActions(xref, dict, eventType) { - const actions = Object.create(null); - const additionalActionsDicts = getInheritableProperty({ - dict, - key: "AA", - stopWhenFound: false - }); - - if (additionalActionsDicts) { - for (let i = additionalActionsDicts.length - 1; i >= 0; i--) { - const additionalActions = additionalActionsDicts[i]; - - if (!(additionalActions instanceof _primitives.Dict)) { - continue; - } - - for (const key of additionalActions.getKeys()) { - const action = eventType[key]; - - if (!action) { - continue; - } - - const actionDict = additionalActions.getRaw(key); - const parents = new _primitives.RefSet(); - const list = []; - - _collectJS(actionDict, xref, list, parents); - - if (list.length > 0) { - actions[action] = list; - } - } - } - } - - if (dict.has("A")) { - const actionDict = dict.get("A"); - const parents = new _primitives.RefSet(); - const list = []; - - _collectJS(actionDict, xref, list, parents); - - if (list.length > 0) { - actions.Action = list; - } - } - - return (0, _util.objectSize)(actions) > 0 ? actions : null; -} - -const XMLEntities = { - 0x3c: "<", - 0x3e: ">", - 0x26: "&", - 0x22: """, - 0x27: "'" -}; - -function encodeToXmlString(str) { - const buffer = []; - let start = 0; - - for (let i = 0, ii = str.length; i < ii; i++) { - const char = str.codePointAt(i); - - if (0x20 <= char && char <= 0x7e) { - const entity = XMLEntities[char]; - - if (entity) { - if (start < i) { - buffer.push(str.substring(start, i)); - } - - buffer.push(entity); - start = i + 1; - } - } else { - if (start < i) { - buffer.push(str.substring(start, i)); - } - - buffer.push(`&#x${char.toString(16).toUpperCase()};`); - - if (char > 0xd7ff && (char < 0xe000 || char > 0xfffd)) { - i++; - } - - start = i + 1; - } - } - - if (buffer.length === 0) { - return str; - } - - if (start < str.length) { - buffer.push(str.substring(start, str.length)); - } - - return buffer.join(""); -} - -function validateCSSFont(cssFontInfo) { - const DEFAULT_CSS_FONT_OBLIQUE = "14"; - const DEFAULT_CSS_FONT_WEIGHT = "400"; - const CSS_FONT_WEIGHT_VALUES = new Set(["100", "200", "300", "400", "500", "600", "700", "800", "900", "1000", "normal", "bold", "bolder", "lighter"]); - const { - fontFamily, - fontWeight, - italicAngle - } = cssFontInfo; - - if (/^".*"$/.test(fontFamily)) { - if (/[^\\]"/.test(fontFamily.slice(1, fontFamily.length - 1))) { - (0, _util.warn)(`XFA - FontFamily contains some unescaped ": ${fontFamily}.`); - return false; - } - } else if (/^'.*'$/.test(fontFamily)) { - if (/[^\\]'/.test(fontFamily.slice(1, fontFamily.length - 1))) { - (0, _util.warn)(`XFA - FontFamily contains some unescaped ': ${fontFamily}.`); - return false; - } - } else { - for (const ident of fontFamily.split(/[ \t]+/)) { - if (/^(\d|(-(\d|-)))/.test(ident) || !/^[\w-\\]+$/.test(ident)) { - (0, _util.warn)(`XFA - FontFamily contains some invalid : ${fontFamily}.`); - return false; - } - } - } - - const weight = fontWeight ? fontWeight.toString() : ""; - cssFontInfo.fontWeight = CSS_FONT_WEIGHT_VALUES.has(weight) ? weight : DEFAULT_CSS_FONT_WEIGHT; - const angle = parseFloat(italicAngle); - cssFontInfo.italicAngle = isNaN(angle) || angle < -90 || angle > 90 ? DEFAULT_CSS_FONT_OBLIQUE : italicAngle.toString(); - return true; -} - -function recoverJsURL(str) { - const URL_OPEN_METHODS = ["app.launchURL", "window.open", "xfa.host.gotoURL"]; - const regex = new RegExp("^\\s*(" + URL_OPEN_METHODS.join("|").split(".").join("\\.") + ")\\((?:'|\")([^'\"]*)(?:'|\")(?:,\\s*(\\w+)\\)|\\))", "i"); - const jsUrl = regex.exec(str); - - if (jsUrl && jsUrl[2]) { - const url = jsUrl[2]; - let newWindow = false; - - if (jsUrl[3] === "true" && jsUrl[1] === "app.launchURL") { - newWindow = true; - } - - return { - url, - newWindow - }; - } - - return null; -} - -/***/ }), -/* 10 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.StringStream = exports.Stream = exports.NullStream = void 0; - -var _base_stream = __w_pdfjs_require__(6); - -var _util = __w_pdfjs_require__(2); - -class Stream extends _base_stream.BaseStream { - constructor(arrayBuffer, start, length, dict) { - super(); - 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; - } - - get length() { - return this.end - this.start; - } - - get isEmpty() { - return this.length === 0; - } - - getByte() { - if (this.pos >= this.end) { - return -1; - } - - return this.bytes[this.pos++]; - } - - getBytes(length, forceClamped = false) { - const bytes = this.bytes; - const pos = this.pos; - const strEnd = this.end; - - if (!length) { - const subarray = bytes.subarray(pos, strEnd); - return forceClamped ? new Uint8ClampedArray(subarray) : subarray; - } - - let end = pos + length; - - if (end > strEnd) { - end = strEnd; - } - - this.pos = end; - const subarray = bytes.subarray(pos, end); - return forceClamped ? new Uint8ClampedArray(subarray) : subarray; - } - - getByteRange(begin, end) { - if (begin < 0) { - begin = 0; - } - - if (end > this.end) { - end = this.end; - } - - return this.bytes.subarray(begin, end); - } - - reset() { - this.pos = this.start; - } - - moveStart() { - this.start = this.pos; - } - - makeSubStream(start, length, dict = null) { - return new Stream(this.bytes.buffer, start, length, dict); - } - -} - -exports.Stream = Stream; - -class StringStream extends Stream { - constructor(str) { - super((0, _util.stringToBytes)(str)); - } - -} - -exports.StringStream = StringStream; - -class NullStream extends Stream { - constructor() { - super(new Uint8Array(0)); - } - -} - -exports.NullStream = NullStream; - -/***/ }), -/* 11 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.Page = exports.PDFDocument = void 0; - -var _util = __w_pdfjs_require__(2); - -var _primitives = __w_pdfjs_require__(5); - -var _core_utils = __w_pdfjs_require__(9); - -var _xfa_fonts = __w_pdfjs_require__(12); - -var _stream = __w_pdfjs_require__(10); - -var _annotation = __w_pdfjs_require__(22); - -var _base_stream = __w_pdfjs_require__(6); - -var _crypto = __w_pdfjs_require__(72); - -var _catalog = __w_pdfjs_require__(64); - -var _parser = __w_pdfjs_require__(27); - -var _object_loader = __w_pdfjs_require__(70); - -var _operator_list = __w_pdfjs_require__(62); - -var _evaluator = __w_pdfjs_require__(25); - -var _decode_stream = __w_pdfjs_require__(29); - -var _struct_tree = __w_pdfjs_require__(69); - -var _factory = __w_pdfjs_require__(74); - -var _xref = __w_pdfjs_require__(98); - -const DEFAULT_USER_UNIT = 1.0; -const LETTER_SIZE_MEDIABOX = [0, 0, 612, 792]; - -class Page { - constructor({ - pdfManager, - xref, - pageIndex, - pageDict, - ref, - globalIdFactory, - fontCache, - builtInCMapCache, - standardFontDataCache, - globalImageCache, - nonBlendModesSet, - xfaFactory - }) { - this.pdfManager = pdfManager; - this.pageIndex = pageIndex; - this.pageDict = pageDict; - this.xref = xref; - this.ref = ref; - this.fontCache = fontCache; - this.builtInCMapCache = builtInCMapCache; - this.standardFontDataCache = standardFontDataCache; - this.globalImageCache = globalImageCache; - this.nonBlendModesSet = nonBlendModesSet; - this.evaluatorOptions = pdfManager.evaluatorOptions; - this.resourcesPromise = null; - this.xfaFactory = xfaFactory; - const idCounters = { - obj: 0 - }; - this._localIdFactory = class extends globalIdFactory { - static createObjId() { - return `p${pageIndex}_${++idCounters.obj}`; - } - - static getPageObjId() { - return `page${ref.toString()}`; - } - - }; - } - - _getInheritableProperty(key, getArray = false) { - const value = (0, _core_utils.getInheritableProperty)({ - dict: this.pageDict, - key, - getArray, - stopWhenFound: false - }); - - if (!Array.isArray(value)) { - return value; - } - - if (value.length === 1 || !(0, _primitives.isDict)(value[0])) { - return value[0]; - } - - return _primitives.Dict.merge({ - xref: this.xref, - dictArray: value - }); - } - - get content() { - return this.pageDict.getArray("Contents"); - } - - get resources() { - return (0, _util.shadow)(this, "resources", this._getInheritableProperty("Resources") || _primitives.Dict.empty); - } - - _getBoundingBox(name) { - if (this.xfaData) { - return this.xfaData.bbox; - } - - const box = this._getInheritableProperty(name, true); - - if (Array.isArray(box) && box.length === 4) { - if (box[2] - box[0] !== 0 && box[3] - box[1] !== 0) { - return box; - } - - (0, _util.warn)(`Empty /${name} entry.`); - } - - return null; - } - - get mediaBox() { - return (0, _util.shadow)(this, "mediaBox", this._getBoundingBox("MediaBox") || LETTER_SIZE_MEDIABOX); - } - - get cropBox() { - return (0, _util.shadow)(this, "cropBox", this._getBoundingBox("CropBox") || this.mediaBox); - } - - get userUnit() { - let obj = this.pageDict.get("UserUnit"); - - if (!(0, _util.isNum)(obj) || obj <= 0) { - obj = DEFAULT_USER_UNIT; - } - - return (0, _util.shadow)(this, "userUnit", obj); - } - - get view() { - const { - cropBox, - mediaBox - } = this; - let view; - - if (cropBox === mediaBox || (0, _util.isArrayEqual)(cropBox, mediaBox)) { - view = mediaBox; - } else { - const box = _util.Util.intersect(cropBox, mediaBox); - - if (box && box[2] - box[0] !== 0 && box[3] - box[1] !== 0) { - view = box; - } else { - (0, _util.warn)("Empty /CropBox and /MediaBox intersection."); - } - } - - return (0, _util.shadow)(this, "view", view || mediaBox); - } - - get rotate() { - let rotate = this._getInheritableProperty("Rotate") || 0; - - if (rotate % 90 !== 0) { - rotate = 0; - } else if (rotate >= 360) { - rotate %= 360; - } else if (rotate < 0) { - rotate = (rotate % 360 + 360) % 360; - } - - return (0, _util.shadow)(this, "rotate", rotate); - } - - _onSubStreamError(handler, reason, objId) { - if (this.evaluatorOptions.ignoreErrors) { - handler.send("UnsupportedFeature", { - featureId: _util.UNSUPPORTED_FEATURES.errorContentSubStream - }); - (0, _util.warn)(`getContentStream - ignoring sub-stream (${objId}): "${reason}".`); - return; - } - - throw reason; - } - - getContentStream(handler) { - return this.pdfManager.ensure(this, "content").then(content => { - if (content instanceof _base_stream.BaseStream) { - return content; - } - - if (Array.isArray(content)) { - return new _decode_stream.StreamsSequenceStream(content, this._onSubStreamError.bind(this, handler)); - } - - return new _stream.NullStream(); - }); - } - - get xfaData() { - return (0, _util.shadow)(this, "xfaData", this.xfaFactory ? { - bbox: this.xfaFactory.getBoundingBox(this.pageIndex) - } : null); - } - - save(handler, task, annotationStorage) { - const partialEvaluator = new _evaluator.PartialEvaluator({ - xref: this.xref, - handler, - pageIndex: this.pageIndex, - idFactory: this._localIdFactory, - fontCache: this.fontCache, - builtInCMapCache: this.builtInCMapCache, - standardFontDataCache: this.standardFontDataCache, - globalImageCache: this.globalImageCache, - options: this.evaluatorOptions - }); - return this._parsedAnnotations.then(function (annotations) { - const newRefsPromises = []; - - for (const annotation of annotations) { - if (!annotation.mustBePrinted(annotationStorage)) { - continue; - } - - newRefsPromises.push(annotation.save(partialEvaluator, task, annotationStorage).catch(function (reason) { - (0, _util.warn)("save - ignoring annotation data during " + `"${task.name}" task: "${reason}".`); - return null; - })); - } - - return Promise.all(newRefsPromises); - }); - } - - loadResources(keys) { - if (!this.resourcesPromise) { - this.resourcesPromise = this.pdfManager.ensure(this, "resources"); - } - - return this.resourcesPromise.then(() => { - const objectLoader = new _object_loader.ObjectLoader(this.resources, keys, this.xref); - return objectLoader.load(); - }); - } - - getOperatorList({ - handler, - sink, - task, - intent, - cacheKey, - annotationStorage = null - }) { - const contentStreamPromise = this.getContentStream(handler); - const resourcesPromise = this.loadResources(["ColorSpace", "ExtGState", "Font", "Pattern", "Properties", "Shading", "XObject"]); - const partialEvaluator = new _evaluator.PartialEvaluator({ - xref: this.xref, - handler, - pageIndex: this.pageIndex, - idFactory: this._localIdFactory, - fontCache: this.fontCache, - builtInCMapCache: this.builtInCMapCache, - standardFontDataCache: this.standardFontDataCache, - globalImageCache: this.globalImageCache, - options: this.evaluatorOptions - }); - const dataPromises = Promise.all([contentStreamPromise, resourcesPromise]); - const pageListPromise = dataPromises.then(([contentStream]) => { - const opList = new _operator_list.OperatorList(intent, sink); - handler.send("StartRenderPage", { - transparency: partialEvaluator.hasBlendModes(this.resources, this.nonBlendModesSet), - pageIndex: this.pageIndex, - cacheKey - }); - return partialEvaluator.getOperatorList({ - stream: contentStream, - task, - resources: this.resources, - operatorList: opList - }).then(function () { - return opList; - }); - }); - return Promise.all([pageListPromise, this._parsedAnnotations]).then(function ([pageOpList, annotations]) { - if (annotations.length === 0 || intent & _util.RenderingIntentFlag.ANNOTATIONS_DISABLE) { - pageOpList.flush(true); - return { - length: pageOpList.totalLength - }; - } - - const renderForms = !!(intent & _util.RenderingIntentFlag.ANNOTATIONS_FORMS), - intentAny = !!(intent & _util.RenderingIntentFlag.ANY), - intentDisplay = !!(intent & _util.RenderingIntentFlag.DISPLAY), - intentPrint = !!(intent & _util.RenderingIntentFlag.PRINT); - const opListPromises = []; - - for (const annotation of annotations) { - if (intentAny || intentDisplay && annotation.mustBeViewed(annotationStorage) || intentPrint && annotation.mustBePrinted(annotationStorage)) { - opListPromises.push(annotation.getOperatorList(partialEvaluator, task, intent, renderForms, annotationStorage).catch(function (reason) { - (0, _util.warn)("getOperatorList - ignoring annotation data during " + `"${task.name}" task: "${reason}".`); - return null; - })); - } - } - - return Promise.all(opListPromises).then(function (opLists) { - pageOpList.addOp(_util.OPS.beginAnnotations, []); - - for (const opList of opLists) { - pageOpList.addOpList(opList); - } - - pageOpList.addOp(_util.OPS.endAnnotations, []); - pageOpList.flush(true); - return { - length: pageOpList.totalLength - }; - }); - }); - } - - extractTextContent({ - handler, - task, - normalizeWhitespace, - includeMarkedContent, - sink, - combineTextItems - }) { - const contentStreamPromise = this.getContentStream(handler); - const resourcesPromise = this.loadResources(["ExtGState", "Font", "Properties", "XObject"]); - const dataPromises = Promise.all([contentStreamPromise, resourcesPromise]); - return dataPromises.then(([contentStream]) => { - const partialEvaluator = new _evaluator.PartialEvaluator({ - xref: this.xref, - handler, - pageIndex: this.pageIndex, - idFactory: this._localIdFactory, - fontCache: this.fontCache, - builtInCMapCache: this.builtInCMapCache, - standardFontDataCache: this.standardFontDataCache, - globalImageCache: this.globalImageCache, - options: this.evaluatorOptions - }); - return partialEvaluator.getTextContent({ - stream: contentStream, - task, - resources: this.resources, - normalizeWhitespace, - includeMarkedContent, - combineTextItems, - sink - }); - }); - } - - async getStructTree() { - const structTreeRoot = await this.pdfManager.ensureCatalog("structTreeRoot"); - - if (!structTreeRoot) { - return null; - } - - const structTree = await this.pdfManager.ensure(this, "_parseStructTree", [structTreeRoot]); - return structTree.serializable; - } - - _parseStructTree(structTreeRoot) { - const tree = new _struct_tree.StructTreePage(structTreeRoot, this.pageDict); - tree.parse(); - return tree; - } - - getAnnotationsData(intent) { - return this._parsedAnnotations.then(function (annotations) { - const annotationsData = []; - - if (annotations.length === 0) { - return annotationsData; - } - - const intentAny = !!(intent & _util.RenderingIntentFlag.ANY), - intentDisplay = !!(intent & _util.RenderingIntentFlag.DISPLAY), - intentPrint = !!(intent & _util.RenderingIntentFlag.PRINT); - - for (const annotation of annotations) { - if (intentAny || intentDisplay && annotation.viewable || intentPrint && annotation.printable) { - annotationsData.push(annotation.data); - } - } - - return annotationsData; - }); - } - - get annotations() { - const annots = this._getInheritableProperty("Annots"); - - return (0, _util.shadow)(this, "annotations", Array.isArray(annots) ? annots : []); - } - - get _parsedAnnotations() { - const parsedAnnotations = this.pdfManager.ensure(this, "annotations").then(() => { - const annotationPromises = []; - - for (const annotationRef of this.annotations) { - annotationPromises.push(_annotation.AnnotationFactory.create(this.xref, annotationRef, this.pdfManager, this._localIdFactory, false).catch(function (reason) { - (0, _util.warn)(`_parsedAnnotations: "${reason}".`); - return null; - })); - } - - return Promise.all(annotationPromises).then(function (annotations) { - return annotations.filter(annotation => !!annotation); - }); - }); - return (0, _util.shadow)(this, "_parsedAnnotations", parsedAnnotations); - } - - get jsActions() { - const actions = (0, _core_utils.collectActions)(this.xref, this.pageDict, _util.PageActionEventType); - return (0, _util.shadow)(this, "jsActions", actions); - } - -} - -exports.Page = Page; -const PDF_HEADER_SIGNATURE = new Uint8Array([0x25, 0x50, 0x44, 0x46, 0x2d]); -const STARTXREF_SIGNATURE = new Uint8Array([0x73, 0x74, 0x61, 0x72, 0x74, 0x78, 0x72, 0x65, 0x66]); -const ENDOBJ_SIGNATURE = new Uint8Array([0x65, 0x6e, 0x64, 0x6f, 0x62, 0x6a]); -const FINGERPRINT_FIRST_BYTES = 1024; -const EMPTY_FINGERPRINT = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"; -const PDF_HEADER_VERSION_REGEXP = /^[1-9]\.\d$/; - -function find(stream, signature, limit = 1024, backwards = false) { - const signatureLength = signature.length; - const scanBytes = stream.peekBytes(limit); - const scanLength = scanBytes.length - signatureLength; - - if (scanLength <= 0) { - return false; - } - - if (backwards) { - const signatureEnd = signatureLength - 1; - let pos = scanBytes.length - 1; - - while (pos >= signatureEnd) { - let j = 0; - - while (j < signatureLength && scanBytes[pos - j] === signature[signatureEnd - j]) { - j++; - } - - if (j >= signatureLength) { - stream.pos += pos - signatureEnd; - return true; - } - - pos--; - } - } else { - let pos = 0; - - while (pos <= scanLength) { - let j = 0; - - while (j < signatureLength && scanBytes[pos + j] === signature[j]) { - j++; - } - - if (j >= signatureLength) { - stream.pos += pos; - return true; - } - - pos++; - } - } - - return false; -} - -class PDFDocument { - constructor(pdfManager, arg) { - let stream; - - if ((0, _primitives.isStream)(arg)) { - stream = arg; - } else if ((0, _util.isArrayBuffer)(arg)) { - stream = new _stream.Stream(arg); - } else { - throw new Error("PDFDocument: Unknown argument type"); - } - - if (stream.length <= 0) { - throw new _util.InvalidPDFException("The PDF file is empty, i.e. its size is zero bytes."); - } - - this.pdfManager = pdfManager; - this.stream = stream; - this.xref = new _xref.XRef(stream, pdfManager); - this._pagePromises = new Map(); - this._version = null; - const idCounters = { - font: 0 - }; - this._globalIdFactory = class { - static getDocId() { - return `g_${pdfManager.docId}`; - } - - static createFontId() { - return `f${++idCounters.font}`; - } - - static createObjId() { - (0, _util.unreachable)("Abstract method `createObjId` called."); - } - - static getPageObjId() { - (0, _util.unreachable)("Abstract method `getPageObjId` called."); - } - - }; - } - - parse(recoveryMode) { - this.xref.parse(recoveryMode); - this.catalog = new _catalog.Catalog(this.pdfManager, this.xref); - - if (this.catalog.version) { - this._version = this.catalog.version; - } - } - - get linearization() { - let linearization = null; - - try { - linearization = _parser.Linearization.create(this.stream); - } catch (err) { - if (err instanceof _core_utils.MissingDataException) { - throw err; - } - - (0, _util.info)(err); - } - - return (0, _util.shadow)(this, "linearization", linearization); - } - - get startXRef() { - const stream = this.stream; - let startXRef = 0; - - if (this.linearization) { - stream.reset(); - - if (find(stream, ENDOBJ_SIGNATURE)) { - startXRef = stream.pos + 6 - stream.start; - } - } else { - const step = 1024; - const startXRefLength = STARTXREF_SIGNATURE.length; - let found = false, - pos = stream.end; - - while (!found && pos > 0) { - pos -= step - startXRefLength; - - if (pos < 0) { - pos = 0; - } - - stream.pos = pos; - found = find(stream, STARTXREF_SIGNATURE, step, true); - } - - if (found) { - stream.skip(9); - let ch; - - do { - ch = stream.getByte(); - } while ((0, _core_utils.isWhiteSpace)(ch)); - - let str = ""; - - while (ch >= 0x20 && ch <= 0x39) { - str += String.fromCharCode(ch); - ch = stream.getByte(); - } - - startXRef = parseInt(str, 10); - - if (isNaN(startXRef)) { - startXRef = 0; - } - } - } - - return (0, _util.shadow)(this, "startXRef", startXRef); - } - - checkHeader() { - const stream = this.stream; - stream.reset(); - - if (!find(stream, PDF_HEADER_SIGNATURE)) { - return; - } - - stream.moveStart(); - const MAX_PDF_VERSION_LENGTH = 12; - let version = "", - ch; - - while ((ch = stream.getByte()) > 0x20) { - if (version.length >= MAX_PDF_VERSION_LENGTH) { - break; - } - - version += String.fromCharCode(ch); - } - - if (!this._version) { - this._version = version.substring(5); - } - } - - parseStartXRef() { - this.xref.setStartXRef(this.startXRef); - } - - get numPages() { - let num = 0; - - if (this.catalog.hasActualNumPages) { - num = this.catalog.numPages; - } else if (this.xfaFactory) { - num = this.xfaFactory.getNumPages(); - } else if (this.linearization) { - num = this.linearization.numPages; - } else { - num = this.catalog.numPages; - } - - return (0, _util.shadow)(this, "numPages", num); - } - - _hasOnlyDocumentSignatures(fields, recursionDepth = 0) { - const RECURSION_LIMIT = 10; - - if (!Array.isArray(fields)) { - return false; - } - - return fields.every(field => { - field = this.xref.fetchIfRef(field); - - if (!(field instanceof _primitives.Dict)) { - return false; - } - - if (field.has("Kids")) { - if (++recursionDepth > RECURSION_LIMIT) { - (0, _util.warn)("_hasOnlyDocumentSignatures: maximum recursion depth reached"); - return false; - } - - return this._hasOnlyDocumentSignatures(field.get("Kids"), recursionDepth); - } - - const isSignature = (0, _primitives.isName)(field.get("FT"), "Sig"); - const rectangle = field.get("Rect"); - const isInvisible = Array.isArray(rectangle) && rectangle.every(value => value === 0); - return isSignature && isInvisible; - }); - } - - get xfaData() { - const acroForm = this.catalog.acroForm; - - if (!acroForm) { - return null; - } - - const xfa = acroForm.get("XFA"); - const entries = { - "xdp:xdp": "", - template: "", - datasets: "", - config: "", - connectionSet: "", - localeSet: "", - stylesheet: "", - "/xdp:xdp": "" - }; - - if ((0, _primitives.isStream)(xfa) && !xfa.isEmpty) { - try { - entries["xdp:xdp"] = (0, _util.stringToUTF8String)(xfa.getString()); - return entries; - } catch (_) { - (0, _util.warn)("XFA - Invalid utf-8 string."); - return null; - } - } - - if (!Array.isArray(xfa) || xfa.length === 0) { - return null; - } - - for (let i = 0, ii = xfa.length; i < ii; i += 2) { - let name; - - if (i === 0) { - name = "xdp:xdp"; - } else if (i === ii - 2) { - name = "/xdp:xdp"; - } else { - name = xfa[i]; - } - - if (!entries.hasOwnProperty(name)) { - continue; - } - - const data = this.xref.fetchIfRef(xfa[i + 1]); - - if (!(0, _primitives.isStream)(data) || data.isEmpty) { - continue; - } - - try { - entries[name] = (0, _util.stringToUTF8String)(data.getString()); - } catch (_) { - (0, _util.warn)("XFA - Invalid utf-8 string."); - return null; - } - } - - return entries; - } - - get xfaFactory() { - let data; - - if (this.pdfManager.enableXfa && this.catalog.needsRendering && this.formInfo.hasXfa && !this.formInfo.hasAcroForm) { - data = this.xfaData; - } - - return (0, _util.shadow)(this, "xfaFactory", data ? new _factory.XFAFactory(data) : null); - } - - get isPureXfa() { - return this.xfaFactory ? this.xfaFactory.isValid() : false; - } - - get htmlForXfa() { - return this.xfaFactory ? this.xfaFactory.getPages() : null; - } - - async loadXfaImages() { - const xfaImagesDict = await this.pdfManager.ensureCatalog("xfaImages"); - - if (!xfaImagesDict) { - return; - } - - const keys = xfaImagesDict.getKeys(); - const objectLoader = new _object_loader.ObjectLoader(xfaImagesDict, keys, this.xref); - await objectLoader.load(); - const xfaImages = new Map(); - - for (const key of keys) { - const stream = xfaImagesDict.get(key); - - if (!(0, _primitives.isStream)(stream)) { - continue; - } - - xfaImages.set(key, stream.getBytes()); - } - - this.xfaFactory.setImages(xfaImages); - } - - async loadXfaFonts(handler, task) { - const acroForm = await this.pdfManager.ensureCatalog("acroForm"); - - if (!acroForm) { - return; - } - - const resources = await acroForm.getAsync("DR"); - - if (!(resources instanceof _primitives.Dict)) { - return; - } - - const objectLoader = new _object_loader.ObjectLoader(resources, ["Font"], this.xref); - await objectLoader.load(); - const fontRes = resources.get("Font"); - - if (!(fontRes instanceof _primitives.Dict)) { - return; - } - - const options = Object.assign(Object.create(null), this.pdfManager.evaluatorOptions); - options.useSystemFonts = false; - const partialEvaluator = new _evaluator.PartialEvaluator({ - xref: this.xref, - handler, - pageIndex: -1, - idFactory: this._globalIdFactory, - fontCache: this.catalog.fontCache, - builtInCMapCache: this.catalog.builtInCMapCache, - standardFontDataCache: this.catalog.standardFontDataCache, - options - }); - const operatorList = new _operator_list.OperatorList(); - const pdfFonts = []; - const initialState = { - get font() { - return pdfFonts[pdfFonts.length - 1]; - }, - - set font(font) { - pdfFonts.push(font); - }, - - clone() { - return this; - } - - }; - const fonts = new Map(); - fontRes.forEach((fontName, font) => { - fonts.set(fontName, font); - }); - const promises = []; - - for (const [fontName, font] of fonts) { - const descriptor = font.get("FontDescriptor"); - - if (!(descriptor instanceof _primitives.Dict)) { - continue; - } - - let fontFamily = descriptor.get("FontFamily"); - fontFamily = fontFamily.replace(/[ ]+(\d)/g, "$1"); - const fontWeight = descriptor.get("FontWeight"); - const italicAngle = -descriptor.get("ItalicAngle"); - const cssFontInfo = { - fontFamily, - fontWeight, - italicAngle - }; - - if (!(0, _core_utils.validateCSSFont)(cssFontInfo)) { - continue; - } - - promises.push(partialEvaluator.handleSetFont(resources, [_primitives.Name.get(fontName), 1], null, operatorList, task, initialState, null, cssFontInfo).catch(function (reason) { - (0, _util.warn)(`loadXfaFonts: "${reason}".`); - return null; - })); - } - - await Promise.all(promises); - const missingFonts = this.xfaFactory.setFonts(pdfFonts); - - if (!missingFonts) { - return; - } - - options.ignoreErrors = true; - promises.length = 0; - pdfFonts.length = 0; - const reallyMissingFonts = new Set(); - - for (const missing of missingFonts) { - if (!(0, _xfa_fonts.getXfaFontName)(`${missing}-Regular`)) { - reallyMissingFonts.add(missing); - } - } - - if (reallyMissingFonts.size) { - missingFonts.push("PdfJS-Fallback"); - } - - for (const missing of missingFonts) { - if (reallyMissingFonts.has(missing)) { - continue; - } - - for (const fontInfo of [{ - name: "Regular", - fontWeight: 400, - italicAngle: 0 - }, { - name: "Bold", - fontWeight: 700, - italicAngle: 0 - }, { - name: "Italic", - fontWeight: 400, - italicAngle: 12 - }, { - name: "BoldItalic", - fontWeight: 700, - italicAngle: 12 - }]) { - const name = `${missing}-${fontInfo.name}`; - const dict = (0, _xfa_fonts.getXfaFontDict)(name); - promises.push(partialEvaluator.handleSetFont(resources, [_primitives.Name.get(name), 1], null, operatorList, task, initialState, dict, { - fontFamily: missing, - fontWeight: fontInfo.fontWeight, - italicAngle: fontInfo.italicAngle - }).catch(function (reason) { - (0, _util.warn)(`loadXfaFonts: "${reason}".`); - return null; - })); - } - } - - await Promise.all(promises); - this.xfaFactory.appendFonts(pdfFonts, reallyMissingFonts); - } - - async serializeXfaData(annotationStorage) { - return this.xfaFactory ? this.xfaFactory.serializeData(annotationStorage) : null; - } - - get formInfo() { - const formInfo = { - hasFields: false, - hasAcroForm: false, - hasXfa: false, - hasSignatures: false - }; - const acroForm = this.catalog.acroForm; - - if (!acroForm) { - return (0, _util.shadow)(this, "formInfo", formInfo); - } - - try { - const fields = acroForm.get("Fields"); - const hasFields = Array.isArray(fields) && fields.length > 0; - formInfo.hasFields = hasFields; - const xfa = acroForm.get("XFA"); - formInfo.hasXfa = Array.isArray(xfa) && xfa.length > 0 || (0, _primitives.isStream)(xfa) && !xfa.isEmpty; - const sigFlags = acroForm.get("SigFlags"); - const hasSignatures = !!(sigFlags & 0x1); - - const hasOnlyDocumentSignatures = hasSignatures && this._hasOnlyDocumentSignatures(fields); - - formInfo.hasAcroForm = hasFields && !hasOnlyDocumentSignatures; - formInfo.hasSignatures = hasSignatures; - } catch (ex) { - if (ex instanceof _core_utils.MissingDataException) { - throw ex; - } - - (0, _util.warn)(`Cannot fetch form information: "${ex}".`); - } - - return (0, _util.shadow)(this, "formInfo", formInfo); - } - - get documentInfo() { - const DocumentInfoValidators = { - Title: _util.isString, - Author: _util.isString, - Subject: _util.isString, - Keywords: _util.isString, - Creator: _util.isString, - Producer: _util.isString, - CreationDate: _util.isString, - ModDate: _util.isString, - Trapped: _primitives.isName - }; - let version = this._version; - - if (typeof version !== "string" || !PDF_HEADER_VERSION_REGEXP.test(version)) { - (0, _util.warn)(`Invalid PDF header version number: ${version}`); - version = null; - } - - const docInfo = { - PDFFormatVersion: version, - Language: this.catalog.lang, - EncryptFilterName: this.xref.encrypt ? this.xref.encrypt.filterName : null, - IsLinearized: !!this.linearization, - IsAcroFormPresent: this.formInfo.hasAcroForm, - IsXFAPresent: this.formInfo.hasXfa, - IsCollectionPresent: !!this.catalog.collection, - IsSignaturesPresent: this.formInfo.hasSignatures - }; - let infoDict; - - try { - infoDict = this.xref.trailer.get("Info"); - } catch (err) { - if (err instanceof _core_utils.MissingDataException) { - throw err; - } - - (0, _util.info)("The document information dictionary is invalid."); - } - - if ((0, _primitives.isDict)(infoDict)) { - for (const key of infoDict.getKeys()) { - const value = infoDict.get(key); - - if (DocumentInfoValidators[key]) { - if (DocumentInfoValidators[key](value)) { - docInfo[key] = typeof value !== "string" ? value : (0, _util.stringToPDFString)(value); - } else { - (0, _util.info)(`Bad value in document info for "${key}".`); - } - } else if (typeof key === "string") { - let customValue; - - if ((0, _util.isString)(value)) { - customValue = (0, _util.stringToPDFString)(value); - } else if ((0, _primitives.isName)(value) || (0, _util.isNum)(value) || (0, _util.isBool)(value)) { - customValue = value; - } else { - (0, _util.info)(`Unsupported value in document info for (custom) "${key}".`); - continue; - } - - if (!docInfo.Custom) { - docInfo.Custom = Object.create(null); - } - - docInfo.Custom[key] = customValue; - } - } - } - - return (0, _util.shadow)(this, "documentInfo", docInfo); - } - - get fingerprints() { - function validate(data) { - return typeof data === "string" && data.length > 0 && data !== EMPTY_FINGERPRINT; - } - - function hexString(hash) { - const buf = []; - - for (let i = 0, ii = hash.length; i < ii; i++) { - const hex = hash[i].toString(16); - buf.push(hex.padStart(2, "0")); - } - - return buf.join(""); - } - - const idArray = this.xref.trailer.get("ID"); - let hashOriginal, hashModified; - - if (Array.isArray(idArray) && validate(idArray[0])) { - hashOriginal = (0, _util.stringToBytes)(idArray[0]); - - if (idArray[1] !== idArray[0] && validate(idArray[1])) { - hashModified = (0, _util.stringToBytes)(idArray[1]); - } - } else { - hashOriginal = (0, _crypto.calculateMD5)(this.stream.getByteRange(0, FINGERPRINT_FIRST_BYTES), 0, FINGERPRINT_FIRST_BYTES); - } - - return (0, _util.shadow)(this, "fingerprints", [hexString(hashOriginal), hashModified ? hexString(hashModified) : null]); - } - - async _getLinearizationPage(pageIndex) { - const { - catalog, - linearization - } = this; - - const ref = _primitives.Ref.get(linearization.objectNumberFirst, 0); - - try { - const obj = await this.xref.fetchAsync(ref); - - if ((0, _primitives.isDict)(obj, "Page") || (0, _primitives.isDict)(obj) && !obj.has("Type") && obj.has("Contents")) { - if (ref && !catalog.pageKidsCountCache.has(ref)) { - catalog.pageKidsCountCache.put(ref, 1); - } - - return [obj, ref]; - } - - throw new _util.FormatError("The Linearization dictionary doesn't point to a valid Page dictionary."); - } catch (reason) { - (0, _util.info)(reason); - return catalog.getPageDict(pageIndex); - } - } - - getPage(pageIndex) { - const cachedPromise = this._pagePromises.get(pageIndex); - - if (cachedPromise) { - return cachedPromise; - } - - const { - catalog, - linearization, - xfaFactory - } = this; - let promise; - - if (xfaFactory) { - promise = Promise.resolve([_primitives.Dict.empty, null]); - } else if (linearization && linearization.pageFirst === pageIndex) { - promise = this._getLinearizationPage(pageIndex); - } else { - promise = catalog.getPageDict(pageIndex); - } - - promise = promise.then(([pageDict, ref]) => { - return new Page({ - pdfManager: this.pdfManager, - xref: this.xref, - pageIndex, - pageDict, - ref, - globalIdFactory: this._globalIdFactory, - fontCache: catalog.fontCache, - builtInCMapCache: catalog.builtInCMapCache, - standardFontDataCache: catalog.standardFontDataCache, - globalImageCache: catalog.globalImageCache, - nonBlendModesSet: catalog.nonBlendModesSet, - xfaFactory - }); - }); - - this._pagePromises.set(pageIndex, promise); - - return promise; - } - - async checkFirstPage(recoveryMode = false) { - if (recoveryMode) { - return; - } - - try { - await this.getPage(0); - } catch (reason) { - if (reason instanceof _core_utils.XRefEntryException) { - this._pagePromises.delete(0); - - await this.cleanup(); - throw new _core_utils.XRefParseException(); - } - } - } - - async checkLastPage(recoveryMode = false) { - const { - catalog, - pdfManager - } = this; - catalog.setActualNumPages(); - let numPages; - - try { - await Promise.all([pdfManager.ensureDoc("xfaFactory"), pdfManager.ensureDoc("linearization"), pdfManager.ensureCatalog("numPages")]); - - if (this.xfaFactory) { - return; - } else if (this.linearization) { - numPages = this.linearization.numPages; - } else { - numPages = catalog.numPages; - } - - if (!Number.isInteger(numPages)) { - throw new _util.FormatError("Page count is not an integer."); - } else if (numPages <= 1) { - return; - } - - await this.getPage(numPages - 1); - } catch (reason) { - this._pagePromises.delete(numPages - 1); - - await this.cleanup(); - - if (reason instanceof _core_utils.XRefEntryException && !recoveryMode) { - throw new _core_utils.XRefParseException(); - } - - (0, _util.warn)(`checkLastPage - invalid /Pages tree /Count: ${numPages}.`); - let pagesTree; - - try { - pagesTree = await pdfManager.ensureCatalog("getAllPageDicts", [recoveryMode]); - } catch (reasonAll) { - if (reasonAll instanceof _core_utils.XRefEntryException && !recoveryMode) { - throw new _core_utils.XRefParseException(); - } - - catalog.setActualNumPages(1); - return; - } - - for (const [pageIndex, [pageDict, ref]] of pagesTree) { - let promise; - - if (pageDict instanceof Error) { - promise = Promise.reject(pageDict); - promise.catch(() => {}); - } else { - promise = Promise.resolve(new Page({ - pdfManager, - xref: this.xref, - pageIndex, - pageDict, - ref, - globalIdFactory: this._globalIdFactory, - fontCache: catalog.fontCache, - builtInCMapCache: catalog.builtInCMapCache, - standardFontDataCache: catalog.standardFontDataCache, - globalImageCache: catalog.globalImageCache, - nonBlendModesSet: catalog.nonBlendModesSet, - xfaFactory: null - })); - } - - this._pagePromises.set(pageIndex, promise); - } - - catalog.setActualNumPages(pagesTree.size); - } - } - - fontFallback(id, handler) { - return this.catalog.fontFallback(id, handler); - } - - async cleanup(manuallyTriggered = false) { - return this.catalog ? this.catalog.cleanup(manuallyTriggered) : (0, _primitives.clearPrimitiveCaches)(); - } - - _collectFieldObjects(name, fieldRef, promises) { - const field = this.xref.fetchIfRef(fieldRef); - - if (field.has("T")) { - const partName = (0, _util.stringToPDFString)(field.get("T")); - - if (name === "") { - name = partName; - } else { - name = `${name}.${partName}`; - } - } - - if (!promises.has(name)) { - promises.set(name, []); - } - - promises.get(name).push(_annotation.AnnotationFactory.create(this.xref, fieldRef, this.pdfManager, this._localIdFactory, true).then(annotation => annotation && annotation.getFieldObject()).catch(function (reason) { - (0, _util.warn)(`_collectFieldObjects: "${reason}".`); - return null; - })); - - if (field.has("Kids")) { - const kids = field.get("Kids"); - - for (const kid of kids) { - this._collectFieldObjects(name, kid, promises); - } - } - } - - get fieldObjects() { - if (!this.formInfo.hasFields) { - return (0, _util.shadow)(this, "fieldObjects", Promise.resolve(null)); - } - - const allFields = Object.create(null); - const fieldPromises = new Map(); - - for (const fieldRef of this.catalog.acroForm.get("Fields")) { - this._collectFieldObjects("", fieldRef, fieldPromises); - } - - const allPromises = []; - - for (const [name, promises] of fieldPromises) { - allPromises.push(Promise.all(promises).then(fields => { - fields = fields.filter(field => !!field); - - if (fields.length > 0) { - allFields[name] = fields; - } - })); - } - - return (0, _util.shadow)(this, "fieldObjects", Promise.all(allPromises).then(() => allFields)); - } - - get hasJSActions() { - const promise = this.pdfManager.ensureDoc("_parseHasJSActions"); - return (0, _util.shadow)(this, "hasJSActions", promise); - } - - async _parseHasJSActions() { - const [catalogJsActions, fieldObjects] = await Promise.all([this.pdfManager.ensureCatalog("jsActions"), this.pdfManager.ensureDoc("fieldObjects")]); - - if (catalogJsActions) { - return true; - } - - if (fieldObjects) { - return Object.values(fieldObjects).some(fieldObject => fieldObject.some(object => object.actions !== null)); - } - - return false; - } - - get calculationOrderIds() { - const acroForm = this.catalog.acroForm; - - if (!acroForm || !acroForm.has("CO")) { - return (0, _util.shadow)(this, "calculationOrderIds", null); - } - - const calculationOrder = acroForm.get("CO"); - - if (!Array.isArray(calculationOrder) || calculationOrder.length === 0) { - return (0, _util.shadow)(this, "calculationOrderIds", null); - } - - const ids = calculationOrder.filter(_primitives.isRef).map(ref => ref.toString()); - - if (ids.length === 0) { - return (0, _util.shadow)(this, "calculationOrderIds", null); - } - - return (0, _util.shadow)(this, "calculationOrderIds", ids); - } - -} - -exports.PDFDocument = PDFDocument; - -/***/ }), -/* 12 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.getXfaFontDict = getXfaFontDict; -exports.getXfaFontName = getXfaFontName; - -var _calibri_factors = __w_pdfjs_require__(13); - -var _primitives = __w_pdfjs_require__(5); - -var _helvetica_factors = __w_pdfjs_require__(14); - -var _liberationsans_widths = __w_pdfjs_require__(15); - -var _myriadpro_factors = __w_pdfjs_require__(16); - -var _segoeui_factors = __w_pdfjs_require__(17); - -var _core_utils = __w_pdfjs_require__(9); - -var _fonts_utils = __w_pdfjs_require__(18); - -const getXFAFontMap = (0, _core_utils.getLookupTableFactory)(function (t) { - t["MyriadPro-Regular"] = t["PdfJS-Fallback-Regular"] = { - name: "LiberationSans-Regular", - factors: _myriadpro_factors.MyriadProRegularFactors, - baseWidths: _liberationsans_widths.LiberationSansRegularWidths, - baseMapping: _liberationsans_widths.LiberationSansRegularMapping, - metrics: _myriadpro_factors.MyriadProRegularMetrics - }; - t["MyriadPro-Bold"] = t["PdfJS-Fallback-Bold"] = { - name: "LiberationSans-Bold", - factors: _myriadpro_factors.MyriadProBoldFactors, - baseWidths: _liberationsans_widths.LiberationSansBoldWidths, - baseMapping: _liberationsans_widths.LiberationSansBoldMapping, - metrics: _myriadpro_factors.MyriadProBoldMetrics - }; - t["MyriadPro-It"] = t["MyriadPro-Italic"] = t["PdfJS-Fallback-Italic"] = { - name: "LiberationSans-Italic", - factors: _myriadpro_factors.MyriadProItalicFactors, - baseWidths: _liberationsans_widths.LiberationSansItalicWidths, - baseMapping: _liberationsans_widths.LiberationSansItalicMapping, - metrics: _myriadpro_factors.MyriadProItalicMetrics - }; - t["MyriadPro-BoldIt"] = t["MyriadPro-BoldItalic"] = t["PdfJS-Fallback-BoldItalic"] = { - name: "LiberationSans-BoldItalic", - factors: _myriadpro_factors.MyriadProBoldItalicFactors, - baseWidths: _liberationsans_widths.LiberationSansBoldItalicWidths, - baseMapping: _liberationsans_widths.LiberationSansBoldItalicMapping, - metrics: _myriadpro_factors.MyriadProBoldItalicMetrics - }; - t.ArialMT = t.Arial = t["Arial-Regular"] = { - name: "LiberationSans-Regular", - baseWidths: _liberationsans_widths.LiberationSansRegularWidths, - baseMapping: _liberationsans_widths.LiberationSansRegularMapping - }; - t["Arial-BoldMT"] = t["Arial-Bold"] = { - name: "LiberationSans-Bold", - baseWidths: _liberationsans_widths.LiberationSansBoldWidths, - baseMapping: _liberationsans_widths.LiberationSansBoldMapping - }; - t["Arial-ItalicMT"] = t["Arial-Italic"] = { - name: "LiberationSans-Italic", - baseWidths: _liberationsans_widths.LiberationSansItalicWidths, - baseMapping: _liberationsans_widths.LiberationSansItalicMapping - }; - t["Arial-BoldItalicMT"] = t["Arial-BoldItalic"] = { - name: "LiberationSans-BoldItalic", - baseWidths: _liberationsans_widths.LiberationSansBoldItalicWidths, - baseMapping: _liberationsans_widths.LiberationSansBoldItalicMapping - }; - t["Calibri-Regular"] = { - name: "LiberationSans-Regular", - factors: _calibri_factors.CalibriRegularFactors, - baseWidths: _liberationsans_widths.LiberationSansRegularWidths, - baseMapping: _liberationsans_widths.LiberationSansRegularMapping, - metrics: _calibri_factors.CalibriRegularMetrics - }; - t["Calibri-Bold"] = { - name: "LiberationSans-Bold", - factors: _calibri_factors.CalibriBoldFactors, - baseWidths: _liberationsans_widths.LiberationSansBoldWidths, - baseMapping: _liberationsans_widths.LiberationSansBoldMapping, - metrics: _calibri_factors.CalibriBoldMetrics - }; - t["Calibri-Italic"] = { - name: "LiberationSans-Italic", - factors: _calibri_factors.CalibriItalicFactors, - baseWidths: _liberationsans_widths.LiberationSansItalicWidths, - baseMapping: _liberationsans_widths.LiberationSansItalicMapping, - metrics: _calibri_factors.CalibriItalicMetrics - }; - t["Calibri-BoldItalic"] = { - name: "LiberationSans-BoldItalic", - factors: _calibri_factors.CalibriBoldItalicFactors, - baseWidths: _liberationsans_widths.LiberationSansBoldItalicWidths, - baseMapping: _liberationsans_widths.LiberationSansBoldItalicMapping, - metrics: _calibri_factors.CalibriBoldItalicMetrics - }; - t["Segoeui-Regular"] = { - name: "LiberationSans-Regular", - factors: _segoeui_factors.SegoeuiRegularFactors, - baseWidths: _liberationsans_widths.LiberationSansRegularWidths, - baseMapping: _liberationsans_widths.LiberationSansRegularMapping, - metrics: _segoeui_factors.SegoeuiRegularMetrics - }; - t["Segoeui-Bold"] = { - name: "LiberationSans-Bold", - factors: _segoeui_factors.SegoeuiBoldFactors, - baseWidths: _liberationsans_widths.LiberationSansBoldWidths, - baseMapping: _liberationsans_widths.LiberationSansBoldMapping, - metrics: _segoeui_factors.SegoeuiBoldMetrics - }; - t["Segoeui-Italic"] = { - name: "LiberationSans-Italic", - factors: _segoeui_factors.SegoeuiItalicFactors, - baseWidths: _liberationsans_widths.LiberationSansItalicWidths, - baseMapping: _liberationsans_widths.LiberationSansItalicMapping, - metrics: _segoeui_factors.SegoeuiItalicMetrics - }; - t["Segoeui-BoldItalic"] = { - name: "LiberationSans-BoldItalic", - factors: _segoeui_factors.SegoeuiBoldItalicFactors, - baseWidths: _liberationsans_widths.LiberationSansBoldItalicWidths, - baseMapping: _liberationsans_widths.LiberationSansBoldItalicMapping, - metrics: _segoeui_factors.SegoeuiBoldItalicMetrics - }; - t["Helvetica-Regular"] = t.Helvetica = { - name: "LiberationSans-Regular", - factors: _helvetica_factors.HelveticaRegularFactors, - baseWidths: _liberationsans_widths.LiberationSansRegularWidths, - baseMapping: _liberationsans_widths.LiberationSansRegularMapping, - metrics: _helvetica_factors.HelveticaRegularMetrics - }; - t["Helvetica-Bold"] = { - name: "LiberationSans-Bold", - factors: _helvetica_factors.HelveticaBoldFactors, - baseWidths: _liberationsans_widths.LiberationSansBoldWidths, - baseMapping: _liberationsans_widths.LiberationSansBoldMapping, - metrics: _helvetica_factors.HelveticaBoldMetrics - }; - t["Helvetica-Italic"] = { - name: "LiberationSans-Italic", - factors: _helvetica_factors.HelveticaItalicFactors, - baseWidths: _liberationsans_widths.LiberationSansItalicWidths, - baseMapping: _liberationsans_widths.LiberationSansItalicMapping, - metrics: _helvetica_factors.HelveticaItalicMetrics - }; - t["Helvetica-BoldItalic"] = { - name: "LiberationSans-BoldItalic", - factors: _helvetica_factors.HelveticaBoldItalicFactors, - baseWidths: _liberationsans_widths.LiberationSansBoldItalicWidths, - baseMapping: _liberationsans_widths.LiberationSansBoldItalicMapping, - metrics: _helvetica_factors.HelveticaBoldItalicMetrics - }; -}); - -function getXfaFontName(name) { - const fontName = (0, _fonts_utils.normalizeFontName)(name); - const fontMap = getXFAFontMap(); - return fontMap[fontName]; -} - -function getXfaFontWidths(name) { - const info = getXfaFontName(name); - - if (!info) { - return null; - } - - const { - baseWidths, - baseMapping, - factors - } = info; - let rescaledBaseWidths; - - if (!factors) { - rescaledBaseWidths = baseWidths; - } else { - rescaledBaseWidths = baseWidths.map((w, i) => w * factors[i]); - } - - let currentCode = -2; - let currentArray; - const newWidths = []; - - for (const [unicode, glyphIndex] of baseMapping.map((charUnicode, index) => [charUnicode, index]).sort(([unicode1], [unicode2]) => unicode1 - unicode2)) { - if (unicode === -1) { - continue; - } - - if (unicode === currentCode + 1) { - currentArray.push(rescaledBaseWidths[glyphIndex]); - currentCode += 1; - } else { - currentCode = unicode; - currentArray = [rescaledBaseWidths[glyphIndex]]; - newWidths.push(unicode, currentArray); - } - } - - return newWidths; -} - -function getXfaFontDict(name) { - const widths = getXfaFontWidths(name); - const dict = new _primitives.Dict(null); - dict.set("BaseFont", _primitives.Name.get(name)); - dict.set("Type", _primitives.Name.get("Font")); - dict.set("Subtype", _primitives.Name.get("CIDFontType2")); - dict.set("Encoding", _primitives.Name.get("Identity-H")); - dict.set("CIDToGIDMap", _primitives.Name.get("Identity")); - dict.set("W", widths); - dict.set("FirstChar", widths[0]); - dict.set("LastChar", widths[widths.length - 2] + widths[widths.length - 1].length - 1); - const descriptor = new _primitives.Dict(null); - dict.set("FontDescriptor", descriptor); - const systemInfo = new _primitives.Dict(null); - systemInfo.set("Ordering", "Identity"); - systemInfo.set("Registry", "Adobe"); - systemInfo.set("Supplement", 0); - dict.set("CIDSystemInfo", systemInfo); - return dict; -} - -/***/ }), -/* 13 */ -/***/ ((__unused_webpack_module, exports) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.CalibriRegularMetrics = exports.CalibriRegularFactors = exports.CalibriItalicMetrics = exports.CalibriItalicFactors = exports.CalibriBoldMetrics = exports.CalibriBoldItalicMetrics = exports.CalibriBoldItalicFactors = exports.CalibriBoldFactors = void 0; -const CalibriBoldFactors = [1.3877, 1, 1, 1, 0.97801, 0.92482, 0.89552, 0.91133, 0.81988, 0.97566, 0.98152, 0.93548, 0.93548, 1.2798, 0.85284, 0.92794, 1, 0.96134, 1.54657, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.82845, 0.82845, 0.85284, 0.85284, 0.85284, 0.75859, 0.92138, 0.83908, 0.7762, 0.73293, 0.87289, 0.73133, 0.7514, 0.81921, 0.87356, 0.95958, 0.59526, 0.75727, 0.69225, 1.04924, 0.9121, 0.86943, 0.79795, 0.88198, 0.77958, 0.70864, 0.81055, 0.90399, 0.88653, 0.96017, 0.82577, 0.77892, 0.78257, 0.97507, 1.54657, 0.97507, 0.85284, 0.89552, 0.90176, 0.88762, 0.8785, 0.75241, 0.8785, 0.90518, 0.95015, 0.77618, 0.8785, 0.88401, 0.91916, 0.86304, 0.88401, 0.91488, 0.8785, 0.8801, 0.8785, 0.8785, 0.91343, 0.7173, 1.04106, 0.8785, 0.85075, 0.95794, 0.82616, 0.85162, 0.79492, 0.88331, 1.69808, 0.88331, 0.85284, 0.97801, 0.89552, 0.91133, 0.89552, 0.91133, 1.7801, 0.89552, 1.24487, 1.13254, 1.12401, 0.96839, 0.85284, 0.68787, 0.70645, 0.85592, 0.90747, 1.01466, 1.0088, 0.90323, 1, 1.07463, 1, 0.91056, 0.75806, 1.19118, 0.96839, 0.78864, 0.82845, 0.84133, 0.75859, 0.83908, 0.83908, 0.83908, 0.83908, 0.83908, 0.83908, 0.77539, 0.73293, 0.73133, 0.73133, 0.73133, 0.73133, 0.95958, 0.95958, 0.95958, 0.95958, 0.88506, 0.9121, 0.86943, 0.86943, 0.86943, 0.86943, 0.86943, 0.85284, 0.87508, 0.90399, 0.90399, 0.90399, 0.90399, 0.77892, 0.79795, 0.90807, 0.88762, 0.88762, 0.88762, 0.88762, 0.88762, 0.88762, 0.8715, 0.75241, 0.90518, 0.90518, 0.90518, 0.90518, 0.88401, 0.88401, 0.88401, 0.88401, 0.8785, 0.8785, 0.8801, 0.8801, 0.8801, 0.8801, 0.8801, 0.90747, 0.89049, 0.8785, 0.8785, 0.8785, 0.8785, 0.85162, 0.8785, 0.85162, 0.83908, 0.88762, 0.83908, 0.88762, 0.83908, 0.88762, 0.73293, 0.75241, 0.73293, 0.75241, 0.73293, 0.75241, 0.73293, 0.75241, 0.87289, 0.83016, 0.88506, 0.93125, 0.73133, 0.90518, 0.73133, 0.90518, 0.73133, 0.90518, 0.73133, 0.90518, 0.73133, 0.90518, 0.81921, 0.77618, 0.81921, 0.77618, 0.81921, 0.77618, 1, 1, 0.87356, 0.8785, 0.91075, 0.89608, 0.95958, 0.88401, 0.95958, 0.88401, 0.95958, 0.88401, 0.95958, 0.88401, 0.95958, 0.88401, 0.76229, 0.90167, 0.59526, 0.91916, 1, 1, 0.86304, 0.69225, 0.88401, 1, 1, 0.70424, 0.79468, 0.91926, 0.88175, 0.70823, 0.94903, 0.9121, 0.8785, 1, 1, 0.9121, 0.8785, 0.87802, 0.88656, 0.8785, 0.86943, 0.8801, 0.86943, 0.8801, 0.86943, 0.8801, 0.87402, 0.89291, 0.77958, 0.91343, 1, 1, 0.77958, 0.91343, 0.70864, 0.7173, 0.70864, 0.7173, 0.70864, 0.7173, 0.70864, 0.7173, 1, 1, 0.81055, 0.75841, 0.81055, 1.06452, 0.90399, 0.8785, 0.90399, 0.8785, 0.90399, 0.8785, 0.90399, 0.8785, 0.90399, 0.8785, 0.90399, 0.8785, 0.96017, 0.95794, 0.77892, 0.85162, 0.77892, 0.78257, 0.79492, 0.78257, 0.79492, 0.78257, 0.79492, 0.9297, 0.56892, 0.83908, 0.88762, 0.77539, 0.8715, 0.87508, 0.89049, 1, 1, 0.81055, 1.04106, 1.20528, 1.20528, 1, 1.15543, 0.70674, 0.98387, 0.94721, 1.33431, 1.45894, 0.95161, 1.06303, 0.83908, 0.80352, 0.57184, 0.6965, 0.56289, 0.82001, 0.56029, 0.81235, 1.02988, 0.83908, 0.7762, 0.68156, 0.80367, 0.73133, 0.78257, 0.87356, 0.86943, 0.95958, 0.75727, 0.89019, 1.04924, 0.9121, 0.7648, 0.86943, 0.87356, 0.79795, 0.78275, 0.81055, 0.77892, 0.9762, 0.82577, 0.99819, 0.84896, 0.95958, 0.77892, 0.96108, 1.01407, 0.89049, 1.02988, 0.94211, 0.96108, 0.8936, 0.84021, 0.87842, 0.96399, 0.79109, 0.89049, 1.00813, 1.02988, 0.86077, 0.87445, 0.92099, 0.84723, 0.86513, 0.8801, 0.75638, 0.85714, 0.78216, 0.79586, 0.87965, 0.94211, 0.97747, 0.78287, 0.97926, 0.84971, 1.02988, 0.94211, 0.8801, 0.94211, 0.84971, 0.73133, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.90264, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.90518, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.90548, 1, 1, 1, 1, 1, 1, 0.96017, 0.95794, 0.96017, 0.95794, 0.96017, 0.95794, 0.77892, 0.85162, 1, 1, 0.89552, 0.90527, 1, 0.90363, 0.92794, 0.92794, 0.92794, 0.92794, 0.87012, 0.87012, 0.87012, 0.89552, 0.89552, 1.42259, 0.71143, 1.06152, 1, 1, 1.03372, 1.03372, 0.97171, 1.4956, 2.2807, 0.93835, 0.83406, 0.91133, 0.84107, 0.91133, 1, 1, 1, 0.72021, 1, 1.23108, 0.83489, 0.88525, 0.88525, 0.81499, 0.90527, 1.81055, 0.90527, 1.81055, 1.31006, 1.53711, 0.94434, 1.08696, 1, 0.95018, 0.77192, 0.85284, 0.90747, 1.17534, 0.69825, 0.9716, 1.37077, 0.90747, 0.90747, 0.85356, 0.90747, 0.90747, 1.44947, 0.85284, 0.8941, 0.8941, 0.70572, 0.8, 0.70572, 0.70572, 0.70572, 0.70572, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.99862, 0.99862, 1, 1, 1, 1, 1, 1.08004, 0.91027, 1, 1, 1, 0.99862, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.90727, 0.90727, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; -exports.CalibriBoldFactors = CalibriBoldFactors; -const CalibriBoldMetrics = { - lineHeight: 1.2207, - lineGap: 0.2207 -}; -exports.CalibriBoldMetrics = CalibriBoldMetrics; -const CalibriBoldItalicFactors = [1.3877, 1, 1, 1, 0.97801, 0.92482, 0.89552, 0.91133, 0.81988, 0.97566, 0.98152, 0.93548, 0.93548, 1.2798, 0.85284, 0.92794, 1, 0.96134, 1.56239, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.82845, 0.82845, 0.85284, 0.85284, 0.85284, 0.75859, 0.92138, 0.83908, 0.7762, 0.71805, 0.87289, 0.73133, 0.7514, 0.81921, 0.87356, 0.95958, 0.59526, 0.75727, 0.69225, 1.04924, 0.90872, 0.85938, 0.79795, 0.87068, 0.77958, 0.69766, 0.81055, 0.90399, 0.88653, 0.96068, 0.82577, 0.77892, 0.78257, 0.97507, 1.529, 0.97507, 0.85284, 0.89552, 0.90176, 0.94908, 0.86411, 0.74012, 0.86411, 0.88323, 0.95015, 0.86411, 0.86331, 0.88401, 0.91916, 0.86304, 0.88401, 0.9039, 0.86331, 0.86331, 0.86411, 0.86411, 0.90464, 0.70852, 1.04106, 0.86331, 0.84372, 0.95794, 0.82616, 0.84548, 0.79492, 0.88331, 1.69808, 0.88331, 0.85284, 0.97801, 0.89552, 0.91133, 0.89552, 0.91133, 1.7801, 0.89552, 1.24487, 1.13254, 1.19129, 0.96839, 0.85284, 0.68787, 0.70645, 0.85592, 0.90747, 1.01466, 1.0088, 0.90323, 1, 1.07463, 1, 0.91056, 0.75806, 1.19118, 0.96839, 0.78864, 0.82845, 0.84133, 0.75859, 0.83908, 0.83908, 0.83908, 0.83908, 0.83908, 0.83908, 0.77539, 0.71805, 0.73133, 0.73133, 0.73133, 0.73133, 0.95958, 0.95958, 0.95958, 0.95958, 0.88506, 0.90872, 0.85938, 0.85938, 0.85938, 0.85938, 0.85938, 0.85284, 0.87068, 0.90399, 0.90399, 0.90399, 0.90399, 0.77892, 0.79795, 0.90807, 0.94908, 0.94908, 0.94908, 0.94908, 0.94908, 0.94908, 0.85887, 0.74012, 0.88323, 0.88323, 0.88323, 0.88323, 0.88401, 0.88401, 0.88401, 0.88401, 0.8785, 0.86331, 0.86331, 0.86331, 0.86331, 0.86331, 0.86331, 0.90747, 0.89049, 0.86331, 0.86331, 0.86331, 0.86331, 0.84548, 0.86411, 0.84548, 0.83908, 0.94908, 0.83908, 0.94908, 0.83908, 0.94908, 0.71805, 0.74012, 0.71805, 0.74012, 0.71805, 0.74012, 0.71805, 0.74012, 0.87289, 0.79538, 0.88506, 0.92726, 0.73133, 0.88323, 0.73133, 0.88323, 0.73133, 0.88323, 0.73133, 0.88323, 0.73133, 0.88323, 0.81921, 0.86411, 0.81921, 0.86411, 0.81921, 0.86411, 1, 1, 0.87356, 0.86331, 0.91075, 0.8777, 0.95958, 0.88401, 0.95958, 0.88401, 0.95958, 0.88401, 0.95958, 0.88401, 0.95958, 0.88401, 0.76467, 0.90167, 0.59526, 0.91916, 1, 1, 0.86304, 0.69225, 0.88401, 1, 1, 0.70424, 0.77312, 0.91926, 0.88175, 0.70823, 0.94903, 0.90872, 0.86331, 1, 1, 0.90872, 0.86331, 0.86906, 0.88116, 0.86331, 0.85938, 0.86331, 0.85938, 0.86331, 0.85938, 0.86331, 0.87402, 0.86549, 0.77958, 0.90464, 1, 1, 0.77958, 0.90464, 0.69766, 0.70852, 0.69766, 0.70852, 0.69766, 0.70852, 0.69766, 0.70852, 1, 1, 0.81055, 0.75841, 0.81055, 1.06452, 0.90399, 0.86331, 0.90399, 0.86331, 0.90399, 0.86331, 0.90399, 0.86331, 0.90399, 0.86331, 0.90399, 0.86331, 0.96068, 0.95794, 0.77892, 0.84548, 0.77892, 0.78257, 0.79492, 0.78257, 0.79492, 0.78257, 0.79492, 0.9297, 0.56892, 0.83908, 0.94908, 0.77539, 0.85887, 0.87068, 0.89049, 1, 1, 0.81055, 1.04106, 1.20528, 1.20528, 1, 1.15543, 0.70088, 0.98387, 0.94721, 1.33431, 1.45894, 0.95161, 1.48387, 0.83908, 0.80352, 0.57118, 0.6965, 0.56347, 0.79179, 0.55853, 0.80346, 1.02988, 0.83908, 0.7762, 0.67174, 0.86036, 0.73133, 0.78257, 0.87356, 0.86441, 0.95958, 0.75727, 0.89019, 1.04924, 0.90872, 0.74889, 0.85938, 0.87891, 0.79795, 0.7957, 0.81055, 0.77892, 0.97447, 0.82577, 0.97466, 0.87179, 0.95958, 0.77892, 0.94252, 0.95612, 0.8753, 1.02988, 0.92733, 0.94252, 0.87411, 0.84021, 0.8728, 0.95612, 0.74081, 0.8753, 1.02189, 1.02988, 0.84814, 0.87445, 0.91822, 0.84723, 0.85668, 0.86331, 0.81344, 0.87581, 0.76422, 0.82046, 0.96057, 0.92733, 0.99375, 0.78022, 0.95452, 0.86015, 1.02988, 0.92733, 0.86331, 0.92733, 0.86015, 0.73133, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.90631, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.88323, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.85174, 1, 1, 1, 1, 1, 1, 0.96068, 0.95794, 0.96068, 0.95794, 0.96068, 0.95794, 0.77892, 0.84548, 1, 1, 0.89552, 0.90527, 1, 0.90363, 0.92794, 0.92794, 0.92794, 0.89807, 0.87012, 0.87012, 0.87012, 0.89552, 0.89552, 1.42259, 0.71094, 1.06152, 1, 1, 1.03372, 1.03372, 0.97171, 1.4956, 2.2807, 0.92972, 0.83406, 0.91133, 0.83326, 0.91133, 1, 1, 1, 0.72021, 1, 1.23108, 0.83489, 0.88525, 0.88525, 0.81499, 0.90616, 1.81055, 0.90527, 1.81055, 1.3107, 1.53711, 0.94434, 1.08696, 1, 0.95018, 0.77192, 0.85284, 0.90747, 1.17534, 0.69825, 0.9716, 1.37077, 0.90747, 0.90747, 0.85356, 0.90747, 0.90747, 1.44947, 0.85284, 0.8941, 0.8941, 0.70572, 0.8, 0.70572, 0.70572, 0.70572, 0.70572, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.99862, 0.99862, 1, 1, 1, 1, 1, 1.08004, 0.91027, 1, 1, 1, 0.99862, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.90727, 0.90727, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; -exports.CalibriBoldItalicFactors = CalibriBoldItalicFactors; -const CalibriBoldItalicMetrics = { - lineHeight: 1.2207, - lineGap: 0.2207 -}; -exports.CalibriBoldItalicMetrics = CalibriBoldItalicMetrics; -const CalibriItalicFactors = [1.3877, 1, 1, 1, 1.17223, 1.1293, 0.89552, 0.91133, 0.80395, 1.02269, 1.15601, 0.91056, 0.91056, 1.2798, 0.85284, 0.89807, 1, 0.90861, 1.39543, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.96309, 0.96309, 0.85284, 0.85284, 0.85284, 0.83319, 0.88071, 0.8675, 0.81552, 0.72346, 0.85193, 0.73206, 0.7522, 0.81105, 0.86275, 0.90685, 0.6377, 0.77892, 0.75593, 1.02638, 0.89249, 0.84118, 0.77452, 0.85374, 0.75186, 0.67789, 0.79776, 0.88844, 0.85066, 0.94309, 0.77818, 0.7306, 0.76659, 1.10369, 1.38313, 1.10369, 1.06139, 0.89552, 0.8739, 0.9245, 0.9245, 0.83203, 0.9245, 0.85865, 1.09842, 0.9245, 0.9245, 1.03297, 1.07692, 0.90918, 1.03297, 0.94959, 0.9245, 0.92274, 0.9245, 0.9245, 1.02933, 0.77832, 1.20562, 0.9245, 0.8916, 0.98986, 0.86621, 0.89453, 0.79004, 0.94152, 1.77256, 0.94152, 0.85284, 0.97801, 0.89552, 0.91133, 0.89552, 0.91133, 1.91729, 0.89552, 1.17889, 1.13254, 1.16359, 0.92098, 0.85284, 0.68787, 0.71353, 0.84737, 0.90747, 1.0088, 1.0044, 0.87683, 1, 1.09091, 1, 0.92229, 0.739, 1.15642, 0.92098, 0.76288, 0.80504, 0.80972, 0.75859, 0.8675, 0.8675, 0.8675, 0.8675, 0.8675, 0.8675, 0.76318, 0.72346, 0.73206, 0.73206, 0.73206, 0.73206, 0.90685, 0.90685, 0.90685, 0.90685, 0.86477, 0.89249, 0.84118, 0.84118, 0.84118, 0.84118, 0.84118, 0.85284, 0.84557, 0.88844, 0.88844, 0.88844, 0.88844, 0.7306, 0.77452, 0.86331, 0.9245, 0.9245, 0.9245, 0.9245, 0.9245, 0.9245, 0.84843, 0.83203, 0.85865, 0.85865, 0.85865, 0.85865, 0.82601, 0.82601, 0.82601, 0.82601, 0.94469, 0.9245, 0.92274, 0.92274, 0.92274, 0.92274, 0.92274, 0.90747, 0.86651, 0.9245, 0.9245, 0.9245, 0.9245, 0.89453, 0.9245, 0.89453, 0.8675, 0.9245, 0.8675, 0.9245, 0.8675, 0.9245, 0.72346, 0.83203, 0.72346, 0.83203, 0.72346, 0.83203, 0.72346, 0.83203, 0.85193, 0.8875, 0.86477, 0.99034, 0.73206, 0.85865, 0.73206, 0.85865, 0.73206, 0.85865, 0.73206, 0.85865, 0.73206, 0.85865, 0.81105, 0.9245, 0.81105, 0.9245, 0.81105, 0.9245, 1, 1, 0.86275, 0.9245, 0.90872, 0.93591, 0.90685, 0.82601, 0.90685, 0.82601, 0.90685, 0.82601, 0.90685, 1.03297, 0.90685, 0.82601, 0.77896, 1.05611, 0.6377, 1.07692, 1, 1, 0.90918, 0.75593, 1.03297, 1, 1, 0.76032, 0.9375, 0.98156, 0.93407, 0.77261, 1.11429, 0.89249, 0.9245, 1, 1, 0.89249, 0.9245, 0.92534, 0.86698, 0.9245, 0.84118, 0.92274, 0.84118, 0.92274, 0.84118, 0.92274, 0.8667, 0.86291, 0.75186, 1.02933, 1, 1, 0.75186, 1.02933, 0.67789, 0.77832, 0.67789, 0.77832, 0.67789, 0.77832, 0.67789, 0.77832, 1, 1, 0.79776, 0.97655, 0.79776, 1.23023, 0.88844, 0.9245, 0.88844, 0.9245, 0.88844, 0.9245, 0.88844, 0.9245, 0.88844, 0.9245, 0.88844, 0.9245, 0.94309, 0.98986, 0.7306, 0.89453, 0.7306, 0.76659, 0.79004, 0.76659, 0.79004, 0.76659, 0.79004, 1.09231, 0.54873, 0.8675, 0.9245, 0.76318, 0.84843, 0.84557, 0.86651, 1, 1, 0.79776, 1.20562, 1.18622, 1.18622, 1, 1.1437, 0.67009, 0.96334, 0.93695, 1.35191, 1.40909, 0.95161, 1.48387, 0.8675, 0.90861, 0.6192, 0.7363, 0.64824, 0.82411, 0.56321, 0.85696, 1.23516, 0.8675, 0.81552, 0.7286, 0.84134, 0.73206, 0.76659, 0.86275, 0.84369, 0.90685, 0.77892, 0.85871, 1.02638, 0.89249, 0.75828, 0.84118, 0.85984, 0.77452, 0.76466, 0.79776, 0.7306, 0.90782, 0.77818, 0.903, 0.87291, 0.90685, 0.7306, 0.99058, 1.03667, 0.94635, 1.23516, 0.9849, 0.99058, 0.92393, 0.8916, 0.942, 1.03667, 0.75026, 0.94635, 1.0297, 1.23516, 0.90918, 0.94048, 0.98217, 0.89746, 0.84153, 0.92274, 0.82507, 0.88832, 0.84438, 0.88178, 1.03525, 0.9849, 1.00225, 0.78086, 0.97248, 0.89404, 1.23516, 0.9849, 0.92274, 0.9849, 0.89404, 0.73206, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.89693, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.85865, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.90933, 1, 1, 1, 1, 1, 1, 0.94309, 0.98986, 0.94309, 0.98986, 0.94309, 0.98986, 0.7306, 0.89453, 1, 1, 0.89552, 0.90527, 1, 0.90186, 1.12308, 1.12308, 1.12308, 1.12308, 1.2566, 1.2566, 1.2566, 0.89552, 0.89552, 1.42259, 0.68994, 1.03809, 1, 1, 1.0176, 1.0176, 1.11523, 1.4956, 2.01462, 0.97858, 0.82616, 0.91133, 0.83437, 0.91133, 1, 1, 1, 0.70508, 1, 1.23108, 0.79801, 0.84426, 0.84426, 0.774, 0.90572, 1.81055, 0.90749, 1.81055, 1.28809, 1.55469, 0.94434, 1.07806, 1, 0.97094, 0.7589, 0.85284, 0.90747, 1.19658, 0.69825, 0.97622, 1.33512, 0.90747, 0.90747, 0.85284, 0.90747, 0.90747, 1.44947, 0.85284, 0.8941, 0.8941, 0.70572, 0.8, 0.70572, 0.70572, 0.70572, 0.70572, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.99862, 0.99862, 1, 1, 1, 1, 1, 1.0336, 0.91027, 1, 1, 1, 0.99862, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.05859, 1.05859, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; -exports.CalibriItalicFactors = CalibriItalicFactors; -const CalibriItalicMetrics = { - lineHeight: 1.2207, - lineGap: 0.2207 -}; -exports.CalibriItalicMetrics = CalibriItalicMetrics; -const CalibriRegularFactors = [1.3877, 1, 1, 1, 1.17223, 1.1293, 0.89552, 0.91133, 0.80395, 1.02269, 1.15601, 0.91056, 0.91056, 1.2798, 0.85284, 0.89807, 1, 0.90861, 1.39016, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.96309, 0.96309, 0.85284, 0.85284, 0.85284, 0.83319, 0.88071, 0.8675, 0.81552, 0.73834, 0.85193, 0.73206, 0.7522, 0.81105, 0.86275, 0.90685, 0.6377, 0.77892, 0.75593, 1.02638, 0.89385, 0.85122, 0.77452, 0.86503, 0.75186, 0.68887, 0.79776, 0.88844, 0.85066, 0.94258, 0.77818, 0.7306, 0.76659, 1.10369, 1.39016, 1.10369, 1.06139, 0.89552, 0.8739, 0.86128, 0.94469, 0.8457, 0.94469, 0.89464, 1.09842, 0.84636, 0.94469, 1.03297, 1.07692, 0.90918, 1.03297, 0.95897, 0.94469, 0.9482, 0.94469, 0.94469, 1.04692, 0.78223, 1.20562, 0.94469, 0.90332, 0.98986, 0.86621, 0.90527, 0.79004, 0.94152, 1.77256, 0.94152, 0.85284, 0.97801, 0.89552, 0.91133, 0.89552, 0.91133, 1.91729, 0.89552, 1.17889, 1.13254, 1.08707, 0.92098, 0.85284, 0.68787, 0.71353, 0.84737, 0.90747, 1.0088, 1.0044, 0.87683, 1, 1.09091, 1, 0.92229, 0.739, 1.15642, 0.92098, 0.76288, 0.80504, 0.80972, 0.75859, 0.8675, 0.8675, 0.8675, 0.8675, 0.8675, 0.8675, 0.76318, 0.73834, 0.73206, 0.73206, 0.73206, 0.73206, 0.90685, 0.90685, 0.90685, 0.90685, 0.86477, 0.89385, 0.85122, 0.85122, 0.85122, 0.85122, 0.85122, 0.85284, 0.85311, 0.88844, 0.88844, 0.88844, 0.88844, 0.7306, 0.77452, 0.86331, 0.86128, 0.86128, 0.86128, 0.86128, 0.86128, 0.86128, 0.8693, 0.8457, 0.89464, 0.89464, 0.89464, 0.89464, 0.82601, 0.82601, 0.82601, 0.82601, 0.94469, 0.94469, 0.9482, 0.9482, 0.9482, 0.9482, 0.9482, 0.90747, 0.86651, 0.94469, 0.94469, 0.94469, 0.94469, 0.90527, 0.94469, 0.90527, 0.8675, 0.86128, 0.8675, 0.86128, 0.8675, 0.86128, 0.73834, 0.8457, 0.73834, 0.8457, 0.73834, 0.8457, 0.73834, 0.8457, 0.85193, 0.92454, 0.86477, 0.9921, 0.73206, 0.89464, 0.73206, 0.89464, 0.73206, 0.89464, 0.73206, 0.89464, 0.73206, 0.89464, 0.81105, 0.84636, 0.81105, 0.84636, 0.81105, 0.84636, 1, 1, 0.86275, 0.94469, 0.90872, 0.95786, 0.90685, 0.82601, 0.90685, 0.82601, 0.90685, 0.82601, 0.90685, 1.03297, 0.90685, 0.82601, 0.77741, 1.05611, 0.6377, 1.07692, 1, 1, 0.90918, 0.75593, 1.03297, 1, 1, 0.76032, 0.90452, 0.98156, 1.11842, 0.77261, 1.11429, 0.89385, 0.94469, 1, 1, 0.89385, 0.94469, 0.95877, 0.86901, 0.94469, 0.85122, 0.9482, 0.85122, 0.9482, 0.85122, 0.9482, 0.8667, 0.90016, 0.75186, 1.04692, 1, 1, 0.75186, 1.04692, 0.68887, 0.78223, 0.68887, 0.78223, 0.68887, 0.78223, 0.68887, 0.78223, 1, 1, 0.79776, 0.92188, 0.79776, 1.23023, 0.88844, 0.94469, 0.88844, 0.94469, 0.88844, 0.94469, 0.88844, 0.94469, 0.88844, 0.94469, 0.88844, 0.94469, 0.94258, 0.98986, 0.7306, 0.90527, 0.7306, 0.76659, 0.79004, 0.76659, 0.79004, 0.76659, 0.79004, 1.09231, 0.54873, 0.8675, 0.86128, 0.76318, 0.8693, 0.85311, 0.86651, 1, 1, 0.79776, 1.20562, 1.18622, 1.18622, 1, 1.1437, 0.67742, 0.96334, 0.93695, 1.35191, 1.40909, 0.95161, 1.48387, 0.86686, 0.90861, 0.62267, 0.74359, 0.65649, 0.85498, 0.56963, 0.88254, 1.23516, 0.8675, 0.81552, 0.75443, 0.84503, 0.73206, 0.76659, 0.86275, 0.85122, 0.90685, 0.77892, 0.85746, 1.02638, 0.89385, 0.75657, 0.85122, 0.86275, 0.77452, 0.74171, 0.79776, 0.7306, 0.95165, 0.77818, 0.89772, 0.88831, 0.90685, 0.7306, 0.98142, 1.02191, 0.96576, 1.23516, 0.99018, 0.98142, 0.9236, 0.89258, 0.94035, 1.02191, 0.78848, 0.96576, 0.9561, 1.23516, 0.90918, 0.92578, 0.95424, 0.89746, 0.83969, 0.9482, 0.80113, 0.89442, 0.85208, 0.86155, 0.98022, 0.99018, 1.00452, 0.81209, 0.99247, 0.89181, 1.23516, 0.99018, 0.9482, 0.99018, 0.89181, 0.73206, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.88844, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.89464, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.96766, 1, 1, 1, 1, 1, 1, 0.94258, 0.98986, 0.94258, 0.98986, 0.94258, 0.98986, 0.7306, 0.90527, 1, 1, 0.89552, 0.90527, 1, 0.90186, 1.12308, 1.12308, 1.12308, 1.12308, 1.2566, 1.2566, 1.2566, 0.89552, 0.89552, 1.42259, 0.69043, 1.03809, 1, 1, 1.0176, 1.0176, 1.11523, 1.4956, 2.01462, 0.99331, 0.82616, 0.91133, 0.84286, 0.91133, 1, 1, 1, 0.70508, 1, 1.23108, 0.79801, 0.84426, 0.84426, 0.774, 0.90527, 1.81055, 0.90527, 1.81055, 1.28809, 1.55469, 0.94434, 1.07806, 1, 0.97094, 0.7589, 0.85284, 0.90747, 1.19658, 0.69825, 0.97622, 1.33512, 0.90747, 0.90747, 0.85356, 0.90747, 0.90747, 1.44947, 0.85284, 0.8941, 0.8941, 0.70572, 0.8, 0.70572, 0.70572, 0.70572, 0.70572, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.99862, 0.99862, 1, 1, 1, 1, 1, 1.0336, 0.91027, 1, 1, 1, 0.99862, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.05859, 1.05859, 1, 1, 1, 1.07185, 0.99413, 0.96334, 1.08065, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; -exports.CalibriRegularFactors = CalibriRegularFactors; -const CalibriRegularMetrics = { - lineHeight: 1.2207, - lineGap: 0.2207 -}; -exports.CalibriRegularMetrics = CalibriRegularMetrics; - -/***/ }), -/* 14 */ -/***/ ((__unused_webpack_module, exports) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.HelveticaRegularMetrics = exports.HelveticaRegularFactors = exports.HelveticaItalicMetrics = exports.HelveticaItalicFactors = exports.HelveticaBoldMetrics = exports.HelveticaBoldItalicMetrics = exports.HelveticaBoldItalicFactors = exports.HelveticaBoldFactors = void 0; -const HelveticaBoldFactors = [0.76116, 1, 1, 1.0006, 0.99998, 0.99974, 0.99973, 0.99973, 0.99982, 0.99977, 1.00087, 0.99998, 0.99998, 0.99959, 1.00003, 1.0006, 0.99998, 1.0006, 1.0006, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99998, 1, 1.00003, 1.00003, 1.00003, 1.00026, 0.9999, 0.99977, 0.99977, 0.99977, 0.99977, 1.00001, 1.00026, 1.00022, 0.99977, 1.0006, 0.99973, 0.99977, 1.00026, 0.99999, 0.99977, 1.00022, 1.00001, 1.00022, 0.99977, 1.00001, 1.00026, 0.99977, 1.00001, 1.00016, 1.00001, 1.00001, 1.00026, 0.99998, 1.0006, 0.99998, 1.00003, 0.99973, 0.99998, 0.99973, 1.00026, 0.99973, 1.00026, 0.99973, 0.99998, 1.00026, 1.00026, 1.0006, 1.0006, 0.99973, 1.0006, 0.99982, 1.00026, 1.00026, 1.00026, 1.00026, 0.99959, 0.99973, 0.99998, 1.00026, 0.99973, 1.00022, 0.99973, 0.99973, 1, 0.99959, 1.00077, 0.99959, 1.00003, 0.99998, 0.99973, 0.99973, 0.99973, 0.99973, 1.00077, 0.99973, 0.99998, 1.00025, 0.99968, 0.99973, 1.00003, 1.00025, 0.60299, 1.00024, 1.06409, 1, 1, 0.99998, 1, 0.99973, 1.0006, 0.99998, 1, 0.99936, 0.99973, 1.00002, 1.00002, 1.00002, 1.00026, 0.99977, 0.99977, 0.99977, 0.99977, 0.99977, 0.99977, 1, 0.99977, 1.00001, 1.00001, 1.00001, 1.00001, 1.0006, 1.0006, 1.0006, 1.0006, 0.99977, 0.99977, 1.00022, 1.00022, 1.00022, 1.00022, 1.00022, 1.00003, 1.00022, 0.99977, 0.99977, 0.99977, 0.99977, 1.00001, 1.00001, 1.00026, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99982, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 1.0006, 1.0006, 1.0006, 1.0006, 1.00026, 1.00026, 1.00026, 1.00026, 1.00026, 1.00026, 1.00026, 1.06409, 1.00026, 1.00026, 1.00026, 1.00026, 1.00026, 0.99973, 1.00026, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 1.03374, 0.99977, 1.00026, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00022, 1.00026, 1.00022, 1.00026, 1.00022, 1.00026, 1.00022, 1.00026, 0.99977, 1.00026, 0.99977, 1.00026, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.00042, 0.99973, 0.99973, 1.0006, 0.99977, 0.99973, 0.99973, 1.00026, 1.0006, 1.00026, 1.0006, 1.00026, 1.03828, 1.00026, 0.99999, 1.00026, 1.0006, 0.99977, 1.00026, 0.99977, 1.00026, 0.99977, 1.00026, 0.9993, 0.9998, 1.00026, 1.00022, 1.00026, 1.00022, 1.00026, 1.00022, 1.00026, 1, 1.00016, 0.99977, 0.99959, 0.99977, 0.99959, 0.99977, 0.99959, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00026, 0.99998, 1.00026, 0.8121, 1.00026, 0.99998, 0.99977, 1.00026, 0.99977, 1.00026, 0.99977, 1.00026, 0.99977, 1.00026, 0.99977, 1.00026, 0.99977, 1.00026, 1.00016, 1.00022, 1.00001, 0.99973, 1.00001, 1.00026, 1, 1.00026, 1, 1.00026, 1, 1.0006, 0.99973, 0.99977, 0.99973, 1, 0.99982, 1.00022, 1.00026, 1.00001, 0.99973, 1.00026, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 1.00034, 0.99977, 1, 0.99997, 1.00026, 1.00078, 1.00036, 0.99973, 1.00013, 1.0006, 0.99977, 0.99977, 0.99988, 0.85148, 1.00001, 1.00026, 0.99977, 1.00022, 1.0006, 0.99977, 1.00001, 0.99999, 0.99977, 1.00069, 1.00022, 0.99977, 1.00001, 0.99984, 1.00026, 1.00001, 1.00024, 1.00001, 0.9999, 1, 1.0006, 1.00001, 1.00041, 0.99962, 1.00026, 1.0006, 0.99995, 1.00041, 0.99942, 0.99973, 0.99927, 1.00082, 0.99902, 1.00026, 1.00087, 1.0006, 1.00069, 0.99973, 0.99867, 0.99973, 0.9993, 1.00026, 1.00049, 1.00056, 1, 0.99988, 0.99935, 0.99995, 0.99954, 1.00055, 0.99945, 1.00032, 1.0006, 0.99995, 1.00026, 0.99995, 1.00032, 1.00001, 1.00008, 0.99971, 1.00019, 0.9994, 1.00001, 1.0006, 1.00044, 0.99973, 1.00023, 1.00047, 1, 0.99942, 0.99561, 0.99989, 1.00035, 0.99977, 1.00035, 0.99977, 1.00019, 0.99944, 1.00001, 1.00021, 0.99926, 1.00035, 1.00035, 0.99942, 1.00048, 0.99999, 0.99977, 1.00022, 1.00035, 1.00001, 0.99977, 1.00026, 0.99989, 1.00057, 1.00001, 0.99936, 1.00052, 1.00012, 0.99996, 1.00043, 1, 1.00035, 0.9994, 0.99976, 1.00035, 0.99973, 1.00052, 1.00041, 1.00119, 1.00037, 0.99973, 1.00002, 0.99986, 1.00041, 1.00041, 0.99902, 0.9996, 1.00034, 0.99999, 1.00026, 0.99999, 1.00026, 0.99973, 1.00052, 0.99973, 1, 0.99973, 1.00041, 1.00075, 0.9994, 1.0003, 0.99999, 1, 1.00041, 0.99955, 1, 0.99915, 0.99973, 0.99973, 1.00026, 1.00119, 0.99955, 0.99973, 1.0006, 0.99911, 1.0006, 1.00026, 0.99972, 1.00026, 0.99902, 1.00041, 0.99973, 0.99999, 1, 1, 1.00038, 1.0005, 1.00016, 1.00022, 1.00016, 1.00022, 1.00016, 1.00022, 1.00001, 0.99973, 1, 1, 0.99973, 1, 1, 0.99955, 1.0006, 1.0006, 1.0006, 1.0006, 1, 1, 1, 0.99973, 0.99973, 0.99972, 1, 1, 1.00106, 0.99999, 0.99998, 0.99998, 0.99999, 0.99998, 1.66475, 1, 0.99973, 0.99973, 1.00023, 0.99973, 0.99971, 1.00047, 1.00023, 1, 0.99991, 0.99984, 1.00002, 1.00002, 1.00002, 1.00002, 1, 1, 1, 1, 1, 1, 1, 0.99972, 1, 1.20985, 1.39713, 1.00003, 1.00031, 1.00015, 1, 0.99561, 1.00027, 1.00031, 1.00031, 0.99915, 1.00031, 1.00031, 0.99999, 1.00003, 0.99999, 0.99999, 1.41144, 1.6, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.40579, 1.40579, 1.36625, 0.99999, 1, 0.99861, 0.99861, 1, 1.00026, 1.00026, 1.00026, 1.00026, 0.99972, 0.99999, 0.99999, 0.99999, 0.99999, 1.40483, 1, 0.99977, 1.00054, 1, 1, 0.99953, 0.99962, 1.00042, 0.9995, 1, 1, 1, 1, 1, 1, 1, 1, 0.99998, 0.99998, 0.99998, 0.99998, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; -exports.HelveticaBoldFactors = HelveticaBoldFactors; -const HelveticaBoldMetrics = { - lineHeight: 1.2, - lineGap: 0.2 -}; -exports.HelveticaBoldMetrics = HelveticaBoldMetrics; -const HelveticaBoldItalicFactors = [0.76116, 1, 1, 1.0006, 0.99998, 0.99974, 0.99973, 0.99973, 0.99982, 0.99977, 1.00087, 0.99998, 0.99998, 0.99959, 1.00003, 1.0006, 0.99998, 1.0006, 1.0006, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99998, 1, 1.00003, 1.00003, 1.00003, 1.00026, 0.9999, 0.99977, 0.99977, 0.99977, 0.99977, 1.00001, 1.00026, 1.00022, 0.99977, 1.0006, 0.99973, 0.99977, 1.00026, 0.99999, 0.99977, 1.00022, 1.00001, 1.00022, 0.99977, 1.00001, 1.00026, 0.99977, 1.00001, 1.00016, 1.00001, 1.00001, 1.00026, 0.99998, 1.0006, 0.99998, 1.00003, 0.99973, 0.99998, 0.99973, 1.00026, 0.99973, 1.00026, 0.99973, 0.99998, 1.00026, 1.00026, 1.0006, 1.0006, 0.99973, 1.0006, 0.99982, 1.00026, 1.00026, 1.00026, 1.00026, 0.99959, 0.99973, 0.99998, 1.00026, 0.99973, 1.00022, 0.99973, 0.99973, 1, 0.99959, 1.00077, 0.99959, 1.00003, 0.99998, 0.99973, 0.99973, 0.99973, 0.99973, 1.00077, 0.99973, 0.99998, 1.00025, 0.99968, 0.99973, 1.00003, 1.00025, 0.60299, 1.00024, 1.06409, 1, 1, 0.99998, 1, 0.99973, 1.0006, 0.99998, 1, 0.99936, 0.99973, 1.00002, 1.00002, 1.00002, 1.00026, 0.99977, 0.99977, 0.99977, 0.99977, 0.99977, 0.99977, 1, 0.99977, 1.00001, 1.00001, 1.00001, 1.00001, 1.0006, 1.0006, 1.0006, 1.0006, 0.99977, 0.99977, 1.00022, 1.00022, 1.00022, 1.00022, 1.00022, 1.00003, 1.00022, 0.99977, 0.99977, 0.99977, 0.99977, 1.00001, 1.00001, 1.00026, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99982, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 1.0006, 1.0006, 1.0006, 1.0006, 1.00026, 1.00026, 1.00026, 1.00026, 1.00026, 1.00026, 1.00026, 1.06409, 1.00026, 1.00026, 1.00026, 1.00026, 1.00026, 0.99973, 1.00026, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 1.0044, 0.99977, 1.00026, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00022, 1.00026, 1.00022, 1.00026, 1.00022, 1.00026, 1.00022, 1.00026, 0.99977, 1.00026, 0.99977, 1.00026, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 0.99971, 0.99973, 0.99973, 1.0006, 0.99977, 0.99973, 0.99973, 1.00026, 1.0006, 1.00026, 1.0006, 1.00026, 1.01011, 1.00026, 0.99999, 1.00026, 1.0006, 0.99977, 1.00026, 0.99977, 1.00026, 0.99977, 1.00026, 0.9993, 0.9998, 1.00026, 1.00022, 1.00026, 1.00022, 1.00026, 1.00022, 1.00026, 1, 1.00016, 0.99977, 0.99959, 0.99977, 0.99959, 0.99977, 0.99959, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00026, 0.99998, 1.00026, 0.8121, 1.00026, 0.99998, 0.99977, 1.00026, 0.99977, 1.00026, 0.99977, 1.00026, 0.99977, 1.00026, 0.99977, 1.00026, 0.99977, 1.00026, 1.00016, 1.00022, 1.00001, 0.99973, 1.00001, 1.00026, 1, 1.00026, 1, 1.00026, 1, 1.0006, 0.99973, 0.99977, 0.99973, 1, 0.99982, 1.00022, 1.00026, 1.00001, 0.99973, 1.00026, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99977, 1, 1, 1.00026, 0.99969, 0.99972, 0.99981, 0.9998, 1.0006, 0.99977, 0.99977, 1.00022, 0.91155, 1.00001, 1.00026, 0.99977, 1.00022, 1.0006, 0.99977, 1.00001, 0.99999, 0.99977, 0.99966, 1.00022, 1.00032, 1.00001, 0.99944, 1.00026, 1.00001, 0.99968, 1.00001, 1.00047, 1, 1.0006, 1.00001, 0.99981, 1.00101, 1.00026, 1.0006, 0.99948, 0.99981, 1.00064, 0.99973, 0.99942, 1.00101, 1.00061, 1.00026, 1.00069, 1.0006, 1.00014, 0.99973, 1.01322, 0.99973, 1.00065, 1.00026, 1.00012, 0.99923, 1, 1.00064, 1.00076, 0.99948, 1.00055, 1.00063, 1.00007, 0.99943, 1.0006, 0.99948, 1.00026, 0.99948, 0.99943, 1.00001, 1.00001, 1.00029, 1.00038, 1.00035, 1.00001, 1.0006, 1.0006, 0.99973, 0.99978, 1.00001, 1.00057, 0.99989, 0.99967, 0.99964, 0.99967, 0.99977, 0.99999, 0.99977, 1.00038, 0.99977, 1.00001, 0.99973, 1.00066, 0.99967, 0.99967, 1.00041, 0.99998, 0.99999, 0.99977, 1.00022, 0.99967, 1.00001, 0.99977, 1.00026, 0.99964, 1.00031, 1.00001, 0.99999, 0.99999, 1, 1.00023, 1, 1, 0.99999, 1.00035, 1.00001, 0.99999, 0.99973, 0.99977, 0.99999, 1.00058, 0.99973, 0.99973, 0.99955, 0.9995, 1.00026, 1.00026, 1.00032, 0.99989, 1.00034, 0.99999, 1.00026, 1.00026, 1.00026, 0.99973, 0.45998, 0.99973, 1.00026, 0.99973, 1.00001, 0.99999, 0.99982, 0.99994, 0.99996, 1, 1.00042, 1.00044, 1.00029, 1.00023, 0.99973, 0.99973, 1.00026, 0.99949, 1.00002, 0.99973, 1.0006, 1.0006, 1.0006, 0.99975, 1.00026, 1.00026, 1.00032, 0.98685, 0.99973, 1.00026, 1, 1, 0.99966, 1.00044, 1.00016, 1.00022, 1.00016, 1.00022, 1.00016, 1.00022, 1.00001, 0.99973, 1, 1, 0.99973, 1, 1, 0.99955, 1.0006, 1.0006, 1.0006, 1.0006, 1, 1, 1, 0.99973, 0.99973, 0.99972, 1, 1, 1.00106, 0.99999, 0.99998, 0.99998, 0.99999, 0.99998, 1.66475, 1, 0.99973, 0.99973, 1, 0.99973, 0.99971, 0.99978, 1, 1, 0.99991, 0.99984, 1.00002, 1.00002, 1.00002, 1.00002, 1.00098, 1, 1, 1, 1.00049, 1, 1, 0.99972, 1, 1.20985, 1.39713, 1.00003, 1.00031, 1.00015, 1, 0.99561, 1.00027, 1.00031, 1.00031, 0.99915, 1.00031, 1.00031, 0.99999, 1.00003, 0.99999, 0.99999, 1.41144, 1.6, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.40579, 1.40579, 1.36625, 0.99999, 1, 0.99861, 0.99861, 1, 1.00026, 1.00026, 1.00026, 1.00026, 0.99972, 0.99999, 0.99999, 0.99999, 0.99999, 1.40483, 1, 0.99977, 1.00054, 1, 1, 0.99953, 0.99962, 1.00042, 0.9995, 1, 1, 1, 1, 1, 1, 1, 1, 0.99998, 0.99998, 0.99998, 0.99998, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; -exports.HelveticaBoldItalicFactors = HelveticaBoldItalicFactors; -const HelveticaBoldItalicMetrics = { - lineHeight: 1.35, - lineGap: 0.2 -}; -exports.HelveticaBoldItalicMetrics = HelveticaBoldItalicMetrics; -const HelveticaItalicFactors = [0.76116, 1, 1, 1.0006, 1.0006, 1.00006, 0.99973, 0.99973, 0.99982, 1.00001, 1.00043, 0.99998, 0.99998, 0.99959, 1.00003, 1.0006, 0.99998, 1.0006, 1.0006, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 1.0006, 1, 1.00003, 1.00003, 1.00003, 0.99973, 0.99987, 1.00001, 1.00001, 0.99977, 0.99977, 1.00001, 1.00026, 1.00022, 0.99977, 1.0006, 1, 1.00001, 0.99973, 0.99999, 0.99977, 1.00022, 1.00001, 1.00022, 0.99977, 1.00001, 1.00026, 0.99977, 1.00001, 1.00016, 1.00001, 1.00001, 1.00026, 1.0006, 1.0006, 1.0006, 0.99949, 0.99973, 0.99998, 0.99973, 0.99973, 1, 0.99973, 0.99973, 1.0006, 0.99973, 0.99973, 0.99924, 0.99924, 1, 0.99924, 0.99999, 0.99973, 0.99973, 0.99973, 0.99973, 0.99998, 1, 1.0006, 0.99973, 1, 0.99977, 1, 1, 1, 1.00005, 1.0009, 1.00005, 1.00003, 0.99998, 0.99973, 0.99973, 0.99973, 0.99973, 1.0009, 0.99973, 0.99998, 1.00025, 0.99968, 0.99973, 1.00003, 1.00025, 0.60299, 1.00024, 1.06409, 1, 1, 0.99998, 1, 0.9998, 1.0006, 0.99998, 1, 0.99936, 0.99973, 1.00002, 1.00002, 1.00002, 1.00026, 1.00001, 1.00001, 1.00001, 1.00001, 1.00001, 1.00001, 1, 0.99977, 1.00001, 1.00001, 1.00001, 1.00001, 1.0006, 1.0006, 1.0006, 1.0006, 0.99977, 0.99977, 1.00022, 1.00022, 1.00022, 1.00022, 1.00022, 1.00003, 1.00022, 0.99977, 0.99977, 0.99977, 0.99977, 1.00001, 1.00001, 1.00026, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99982, 1, 0.99973, 0.99973, 0.99973, 0.99973, 1.0006, 1.0006, 1.0006, 1.0006, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 1.06409, 1.00026, 0.99973, 0.99973, 0.99973, 0.99973, 1, 0.99973, 1, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 0.99977, 1, 0.99977, 1, 0.99977, 1, 0.99977, 1, 0.99977, 1.0288, 0.99977, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00022, 0.99973, 1.00022, 0.99973, 1.00022, 0.99973, 1.00022, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 0.99924, 1.0006, 1.0006, 0.99946, 1.00034, 1, 0.99924, 1.00001, 1, 1, 0.99973, 0.99924, 0.99973, 0.99924, 0.99973, 1.06311, 0.99973, 1.00024, 0.99973, 0.99924, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 1.00041, 0.9998, 0.99973, 1.00022, 0.99973, 1.00022, 0.99973, 1.00022, 0.99973, 1, 1.00016, 0.99977, 0.99998, 0.99977, 0.99998, 0.99977, 0.99998, 1.00001, 1, 1.00001, 1, 1.00001, 1, 1.00001, 1, 1.00026, 1.0006, 1.00026, 0.89547, 1.00026, 1.0006, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 1.00016, 0.99977, 1.00001, 1, 1.00001, 1.00026, 1, 1.00026, 1, 1.00026, 1, 0.99924, 0.99973, 1.00001, 0.99973, 1, 0.99982, 1.00022, 1.00026, 1.00001, 1, 1.00026, 1.0006, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 1.00001, 1, 1.00054, 0.99977, 1.00084, 1.00007, 0.99973, 1.00013, 0.99924, 1.00001, 1.00001, 0.99945, 0.91221, 1.00001, 1.00026, 0.99977, 1.00022, 1.0006, 1.00001, 1.00001, 0.99999, 0.99977, 0.99933, 1.00022, 1.00054, 1.00001, 1.00065, 1.00026, 1.00001, 1.0001, 1.00001, 1.00052, 1, 1.0006, 1.00001, 0.99945, 0.99897, 0.99968, 0.99924, 1.00036, 0.99945, 0.99949, 1, 1.0006, 0.99897, 0.99918, 0.99968, 0.99911, 0.99924, 1, 0.99962, 1.01487, 1, 1.0005, 0.99973, 1.00012, 1.00043, 1, 0.99995, 0.99994, 1.00036, 0.99947, 1.00019, 1.00063, 1.00025, 0.99924, 1.00036, 0.99973, 1.00036, 1.00025, 1.00001, 1.00001, 1.00027, 1.0001, 1.00068, 1.00001, 1.0006, 1.0006, 1, 1.00008, 0.99957, 0.99972, 0.9994, 0.99954, 0.99975, 1.00051, 1.00001, 1.00019, 1.00001, 1.0001, 0.99986, 1.00001, 1.00001, 1.00038, 0.99954, 0.99954, 0.9994, 1.00066, 0.99999, 0.99977, 1.00022, 1.00054, 1.00001, 0.99977, 1.00026, 0.99975, 1.0001, 1.00001, 0.99993, 0.9995, 0.99955, 1.00016, 0.99978, 0.99974, 1.00019, 1.00022, 0.99955, 1.00053, 0.99973, 1.00089, 1.00005, 0.99967, 1.00048, 0.99973, 1.00002, 1.00034, 0.99973, 0.99973, 0.99964, 1.00006, 1.00066, 0.99947, 0.99973, 0.98894, 0.99973, 1, 0.44898, 1, 0.99946, 1, 1.00039, 1.00082, 0.99991, 0.99991, 0.99985, 1.00022, 1.00023, 1.00061, 1.00006, 0.99966, 0.99973, 0.99973, 0.99973, 1.00019, 1.0008, 1, 0.99924, 0.99924, 0.99924, 0.99983, 1.00044, 0.99973, 0.99964, 0.98332, 1, 0.99973, 1, 1, 0.99962, 0.99895, 1.00016, 0.99977, 1.00016, 0.99977, 1.00016, 0.99977, 1.00001, 1, 1, 1, 0.99973, 1, 1, 0.99955, 0.99924, 0.99924, 0.99924, 0.99924, 0.99998, 0.99998, 0.99998, 0.99973, 0.99973, 0.99972, 1, 1, 1.00267, 0.99999, 0.99998, 0.99998, 1, 0.99998, 1.66475, 1, 0.99973, 0.99973, 1.00023, 0.99973, 1.00423, 0.99925, 0.99999, 1, 0.99991, 0.99984, 1.00002, 1.00002, 1.00002, 1.00002, 1.00049, 1, 1.00245, 1, 1, 1, 1, 0.96329, 1, 1.20985, 1.39713, 1.00003, 0.8254, 1.00015, 1, 1.00035, 1.00027, 1.00031, 1.00031, 1.00003, 1.00031, 1.00031, 0.99999, 1.00003, 0.99999, 0.99999, 1.41144, 1.6, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.40579, 1.40579, 1.36625, 0.99999, 1, 0.99861, 0.99861, 1, 1.00026, 1.00026, 1.00026, 1.00026, 0.95317, 0.99999, 0.99999, 0.99999, 0.99999, 1.40483, 1, 0.99977, 1.00054, 1, 1, 0.99953, 0.99962, 1.00042, 0.9995, 1, 1, 1, 1, 1, 1, 1, 1, 0.99998, 0.99998, 0.99998, 0.99998, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; -exports.HelveticaItalicFactors = HelveticaItalicFactors; -const HelveticaItalicMetrics = { - lineHeight: 1.35, - lineGap: 0.2 -}; -exports.HelveticaItalicMetrics = HelveticaItalicMetrics; -const HelveticaRegularFactors = [0.76116, 1, 1, 1.0006, 1.0006, 1.00006, 0.99973, 0.99973, 0.99982, 1.00001, 1.00043, 0.99998, 0.99998, 0.99959, 1.00003, 1.0006, 0.99998, 1.0006, 1.0006, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 1.0006, 1, 1.00003, 1.00003, 1.00003, 0.99973, 0.99987, 1.00001, 1.00001, 0.99977, 0.99977, 1.00001, 1.00026, 1.00022, 0.99977, 1.0006, 1, 1.00001, 0.99973, 0.99999, 0.99977, 1.00022, 1.00001, 1.00022, 0.99977, 1.00001, 1.00026, 0.99977, 1.00001, 1.00016, 1.00001, 1.00001, 1.00026, 1.0006, 1.0006, 1.0006, 0.99949, 0.99973, 0.99998, 0.99973, 0.99973, 1, 0.99973, 0.99973, 1.0006, 0.99973, 0.99973, 0.99924, 0.99924, 1, 0.99924, 0.99999, 0.99973, 0.99973, 0.99973, 0.99973, 0.99998, 1, 1.0006, 0.99973, 1, 0.99977, 1, 1, 1, 1.00005, 1.0009, 1.00005, 1.00003, 0.99998, 0.99973, 0.99973, 0.99973, 0.99973, 1.0009, 0.99973, 0.99998, 1.00025, 0.99968, 0.99973, 1.00003, 1.00025, 0.60299, 1.00024, 1.06409, 1, 1, 0.99998, 1, 0.9998, 1.0006, 0.99998, 1, 0.99936, 0.99973, 1.00002, 1.00002, 1.00002, 1.00026, 1.00001, 1.00001, 1.00001, 1.00001, 1.00001, 1.00001, 1, 0.99977, 1.00001, 1.00001, 1.00001, 1.00001, 1.0006, 1.0006, 1.0006, 1.0006, 0.99977, 0.99977, 1.00022, 1.00022, 1.00022, 1.00022, 1.00022, 1.00003, 1.00022, 0.99977, 0.99977, 0.99977, 0.99977, 1.00001, 1.00001, 1.00026, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99982, 1, 0.99973, 0.99973, 0.99973, 0.99973, 1.0006, 1.0006, 1.0006, 1.0006, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 1.06409, 1.00026, 0.99973, 0.99973, 0.99973, 0.99973, 1, 0.99973, 1, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 0.99977, 1, 0.99977, 1, 0.99977, 1, 0.99977, 1, 0.99977, 1.04596, 0.99977, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00022, 0.99973, 1.00022, 0.99973, 1.00022, 0.99973, 1.00022, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 0.99924, 1.0006, 1.0006, 1.00019, 1.00034, 1, 0.99924, 1.00001, 1, 1, 0.99973, 0.99924, 0.99973, 0.99924, 0.99973, 1.02572, 0.99973, 1.00005, 0.99973, 0.99924, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99999, 0.9998, 0.99973, 1.00022, 0.99973, 1.00022, 0.99973, 1.00022, 0.99973, 1, 1.00016, 0.99977, 0.99998, 0.99977, 0.99998, 0.99977, 0.99998, 1.00001, 1, 1.00001, 1, 1.00001, 1, 1.00001, 1, 1.00026, 1.0006, 1.00026, 0.84533, 1.00026, 1.0006, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 1.00016, 0.99977, 1.00001, 1, 1.00001, 1.00026, 1, 1.00026, 1, 1.00026, 1, 0.99924, 0.99973, 1.00001, 0.99973, 1, 0.99982, 1.00022, 1.00026, 1.00001, 1, 1.00026, 1.0006, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99928, 1, 0.99977, 1.00013, 1.00055, 0.99947, 0.99945, 0.99941, 0.99924, 1.00001, 1.00001, 1.0004, 0.91621, 1.00001, 1.00026, 0.99977, 1.00022, 1.0006, 1.00001, 1.00005, 0.99999, 0.99977, 1.00015, 1.00022, 0.99977, 1.00001, 0.99973, 1.00026, 1.00001, 1.00019, 1.00001, 0.99946, 1, 1.0006, 1.00001, 0.99978, 1.00045, 0.99973, 0.99924, 1.00023, 0.99978, 0.99966, 1, 1.00065, 1.00045, 1.00019, 0.99973, 0.99973, 0.99924, 1, 1, 0.96499, 1, 1.00055, 0.99973, 1.00008, 1.00027, 1, 0.9997, 0.99995, 1.00023, 0.99933, 1.00019, 1.00015, 1.00031, 0.99924, 1.00023, 0.99973, 1.00023, 1.00031, 1.00001, 0.99928, 1.00029, 1.00092, 1.00035, 1.00001, 1.0006, 1.0006, 1, 0.99988, 0.99975, 1, 1.00082, 0.99561, 0.9996, 1.00035, 1.00001, 0.99962, 1.00001, 1.00092, 0.99964, 1.00001, 0.99963, 0.99999, 1.00035, 1.00035, 1.00082, 0.99962, 0.99999, 0.99977, 1.00022, 1.00035, 1.00001, 0.99977, 1.00026, 0.9996, 0.99967, 1.00001, 1.00034, 1.00074, 1.00054, 1.00053, 1.00063, 0.99971, 0.99962, 1.00035, 0.99975, 0.99977, 0.99973, 1.00043, 0.99953, 1.0007, 0.99915, 0.99973, 1.00008, 0.99892, 1.00073, 1.00073, 1.00114, 0.99915, 1.00073, 0.99955, 0.99973, 1.00092, 0.99973, 1, 0.99998, 1, 1.0003, 1, 1.00043, 1.00001, 0.99969, 1.0003, 1, 1.00035, 1.00001, 0.9995, 1, 1.00092, 0.99973, 0.99973, 0.99973, 1.0007, 0.9995, 1, 0.99924, 1.0006, 0.99924, 0.99972, 1.00062, 0.99973, 1.00114, 1.00073, 1, 0.99955, 1, 1, 1.00047, 0.99968, 1.00016, 0.99977, 1.00016, 0.99977, 1.00016, 0.99977, 1.00001, 1, 1, 1, 0.99973, 1, 1, 0.99955, 0.99924, 0.99924, 0.99924, 0.99924, 0.99998, 0.99998, 0.99998, 0.99973, 0.99973, 0.99972, 1, 1, 1.00267, 0.99999, 0.99998, 0.99998, 1, 0.99998, 1.66475, 1, 0.99973, 0.99973, 1.00023, 0.99973, 0.99971, 0.99925, 1.00023, 1, 0.99991, 0.99984, 1.00002, 1.00002, 1.00002, 1.00002, 1, 1, 1, 1, 1, 1, 1, 0.96329, 1, 1.20985, 1.39713, 1.00003, 0.8254, 1.00015, 1, 1.00035, 1.00027, 1.00031, 1.00031, 0.99915, 1.00031, 1.00031, 0.99999, 1.00003, 0.99999, 0.99999, 1.41144, 1.6, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.40579, 1.40579, 1.36625, 0.99999, 1, 0.99861, 0.99861, 1, 1.00026, 1.00026, 1.00026, 1.00026, 0.95317, 0.99999, 0.99999, 0.99999, 0.99999, 1.40483, 1, 0.99977, 1.00054, 1, 1, 0.99953, 0.99962, 1.00042, 0.9995, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; -exports.HelveticaRegularFactors = HelveticaRegularFactors; -const HelveticaRegularMetrics = { - lineHeight: 1.2, - lineGap: 0.2 -}; -exports.HelveticaRegularMetrics = HelveticaRegularMetrics; - -/***/ }), -/* 15 */ -/***/ ((__unused_webpack_module, exports) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.LiberationSansRegularWidths = exports.LiberationSansRegularMapping = exports.LiberationSansItalicWidths = exports.LiberationSansItalicMapping = exports.LiberationSansBoldWidths = exports.LiberationSansBoldMapping = exports.LiberationSansBoldItalicWidths = exports.LiberationSansBoldItalicMapping = void 0; -const LiberationSansBoldWidths = [365, 0, 333, 278, 333, 474, 556, 556, 889, 722, 238, 333, 333, 389, 584, 278, 333, 278, 278, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 333, 333, 584, 584, 584, 611, 975, 722, 722, 722, 722, 667, 611, 778, 722, 278, 556, 722, 611, 833, 722, 778, 667, 778, 722, 667, 611, 722, 667, 944, 667, 667, 611, 333, 278, 333, 584, 556, 333, 556, 611, 556, 611, 556, 333, 611, 611, 278, 278, 556, 278, 889, 611, 611, 611, 611, 389, 556, 333, 611, 556, 778, 556, 556, 500, 389, 280, 389, 584, 333, 556, 556, 556, 556, 280, 556, 333, 737, 370, 556, 584, 737, 552, 400, 549, 333, 333, 333, 576, 556, 278, 333, 333, 365, 556, 834, 834, 834, 611, 722, 722, 722, 722, 722, 722, 1000, 722, 667, 667, 667, 667, 278, 278, 278, 278, 722, 722, 778, 778, 778, 778, 778, 584, 778, 722, 722, 722, 722, 667, 667, 611, 556, 556, 556, 556, 556, 556, 889, 556, 556, 556, 556, 556, 278, 278, 278, 278, 611, 611, 611, 611, 611, 611, 611, 549, 611, 611, 611, 611, 611, 556, 611, 556, 722, 556, 722, 556, 722, 556, 722, 556, 722, 556, 722, 556, 722, 556, 722, 719, 722, 611, 667, 556, 667, 556, 667, 556, 667, 556, 667, 556, 778, 611, 778, 611, 778, 611, 778, 611, 722, 611, 722, 611, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 785, 556, 556, 278, 722, 556, 556, 611, 278, 611, 278, 611, 385, 611, 479, 611, 278, 722, 611, 722, 611, 722, 611, 708, 723, 611, 778, 611, 778, 611, 778, 611, 1000, 944, 722, 389, 722, 389, 722, 389, 667, 556, 667, 556, 667, 556, 667, 556, 611, 333, 611, 479, 611, 333, 722, 611, 722, 611, 722, 611, 722, 611, 722, 611, 722, 611, 944, 778, 667, 556, 667, 611, 500, 611, 500, 611, 500, 278, 556, 722, 556, 1000, 889, 778, 611, 667, 556, 611, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 465, 722, 333, 853, 906, 474, 825, 927, 838, 278, 722, 722, 601, 719, 667, 611, 722, 778, 278, 722, 667, 833, 722, 644, 778, 722, 667, 600, 611, 667, 821, 667, 809, 802, 278, 667, 615, 451, 611, 278, 582, 615, 610, 556, 606, 475, 460, 611, 541, 278, 558, 556, 612, 556, 445, 611, 766, 619, 520, 684, 446, 582, 715, 576, 753, 845, 278, 582, 611, 582, 845, 667, 669, 885, 567, 711, 667, 278, 276, 556, 1094, 1062, 875, 610, 722, 622, 719, 722, 719, 722, 567, 712, 667, 904, 626, 719, 719, 610, 702, 833, 722, 778, 719, 667, 722, 611, 622, 854, 667, 730, 703, 1005, 1019, 870, 979, 719, 711, 1031, 719, 556, 618, 615, 417, 635, 556, 709, 497, 615, 615, 500, 635, 740, 604, 611, 604, 611, 556, 490, 556, 875, 556, 615, 581, 833, 844, 729, 854, 615, 552, 854, 583, 556, 556, 611, 417, 552, 556, 278, 281, 278, 969, 906, 611, 500, 615, 556, 604, 778, 611, 487, 447, 944, 778, 944, 778, 944, 778, 667, 556, 333, 333, 556, 1000, 1000, 552, 278, 278, 278, 278, 500, 500, 500, 556, 556, 350, 1000, 1000, 240, 479, 333, 333, 604, 333, 167, 396, 556, 556, 1094, 556, 885, 489, 1115, 1000, 768, 600, 834, 834, 834, 834, 1000, 500, 1000, 500, 1000, 500, 500, 494, 612, 823, 713, 584, 549, 713, 979, 722, 274, 549, 549, 583, 549, 549, 604, 584, 604, 604, 708, 625, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 729, 604, 604, 354, 354, 1000, 990, 990, 990, 990, 494, 604, 604, 604, 604, 354, 1021, 1052, 917, 750, 750, 531, 656, 594, 510, 500, 750, 750, 611, 611, 333, 333, 333, 333, 333, 333, 333, 333, 222, 222, 333, 333, 333, 333, 333, 333, 333, 333]; -exports.LiberationSansBoldWidths = LiberationSansBoldWidths; -const LiberationSansBoldMapping = [-1, -1, -1, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 402, 506, 507, 508, 509, 510, 511, 536, 537, 538, 539, 710, 711, 713, 728, 729, 730, 731, 732, 733, 900, 901, 902, 903, 904, 905, 906, 908, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076, 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1138, 1139, 1168, 1169, 7808, 7809, 7810, 7811, 7812, 7813, 7922, 7923, 8208, 8209, 8211, 8212, 8213, 8215, 8216, 8217, 8218, 8219, 8220, 8221, 8222, 8224, 8225, 8226, 8230, 8240, 8242, 8243, 8249, 8250, 8252, 8254, 8260, 8319, 8355, 8356, 8359, 8364, 8453, 8467, 8470, 8482, 8486, 8494, 8539, 8540, 8541, 8542, 8592, 8593, 8594, 8595, 8596, 8597, 8616, 8706, 8710, 8719, 8721, 8722, 8730, 8734, 8735, 8745, 8747, 8776, 8800, 8801, 8804, 8805, 8962, 8976, 8992, 8993, 9472, 9474, 9484, 9488, 9492, 9496, 9500, 9508, 9516, 9524, 9532, 9552, 9553, 9554, 9555, 9556, 9557, 9558, 9559, 9560, 9561, 9562, 9563, 9564, 9565, 9566, 9567, 9568, 9569, 9570, 9571, 9572, 9573, 9574, 9575, 9576, 9577, 9578, 9579, 9580, 9600, 9604, 9608, 9612, 9616, 9617, 9618, 9619, 9632, 9633, 9642, 9643, 9644, 9650, 9658, 9660, 9668, 9674, 9675, 9679, 9688, 9689, 9702, 9786, 9787, 9788, 9792, 9794, 9824, 9827, 9829, 9830, 9834, 9835, 9836, 61441, 61442, 61445, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]; -exports.LiberationSansBoldMapping = LiberationSansBoldMapping; -const LiberationSansBoldItalicWidths = [365, 0, 333, 278, 333, 474, 556, 556, 889, 722, 238, 333, 333, 389, 584, 278, 333, 278, 278, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 333, 333, 584, 584, 584, 611, 975, 722, 722, 722, 722, 667, 611, 778, 722, 278, 556, 722, 611, 833, 722, 778, 667, 778, 722, 667, 611, 722, 667, 944, 667, 667, 611, 333, 278, 333, 584, 556, 333, 556, 611, 556, 611, 556, 333, 611, 611, 278, 278, 556, 278, 889, 611, 611, 611, 611, 389, 556, 333, 611, 556, 778, 556, 556, 500, 389, 280, 389, 584, 333, 556, 556, 556, 556, 280, 556, 333, 737, 370, 556, 584, 737, 552, 400, 549, 333, 333, 333, 576, 556, 278, 333, 333, 365, 556, 834, 834, 834, 611, 722, 722, 722, 722, 722, 722, 1000, 722, 667, 667, 667, 667, 278, 278, 278, 278, 722, 722, 778, 778, 778, 778, 778, 584, 778, 722, 722, 722, 722, 667, 667, 611, 556, 556, 556, 556, 556, 556, 889, 556, 556, 556, 556, 556, 278, 278, 278, 278, 611, 611, 611, 611, 611, 611, 611, 549, 611, 611, 611, 611, 611, 556, 611, 556, 722, 556, 722, 556, 722, 556, 722, 556, 722, 556, 722, 556, 722, 556, 722, 740, 722, 611, 667, 556, 667, 556, 667, 556, 667, 556, 667, 556, 778, 611, 778, 611, 778, 611, 778, 611, 722, 611, 722, 611, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 782, 556, 556, 278, 722, 556, 556, 611, 278, 611, 278, 611, 396, 611, 479, 611, 278, 722, 611, 722, 611, 722, 611, 708, 723, 611, 778, 611, 778, 611, 778, 611, 1000, 944, 722, 389, 722, 389, 722, 389, 667, 556, 667, 556, 667, 556, 667, 556, 611, 333, 611, 479, 611, 333, 722, 611, 722, 611, 722, 611, 722, 611, 722, 611, 722, 611, 944, 778, 667, 556, 667, 611, 500, 611, 500, 611, 500, 278, 556, 722, 556, 1000, 889, 778, 611, 667, 556, 611, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 722, 333, 854, 906, 473, 844, 930, 847, 278, 722, 722, 610, 671, 667, 611, 722, 778, 278, 722, 667, 833, 722, 657, 778, 718, 667, 590, 611, 667, 822, 667, 829, 781, 278, 667, 620, 479, 611, 278, 591, 620, 621, 556, 610, 479, 492, 611, 558, 278, 566, 556, 603, 556, 450, 611, 712, 605, 532, 664, 409, 591, 704, 578, 773, 834, 278, 591, 611, 591, 834, 667, 667, 886, 614, 719, 667, 278, 278, 556, 1094, 1042, 854, 622, 719, 677, 719, 722, 708, 722, 614, 722, 667, 927, 643, 719, 719, 615, 687, 833, 722, 778, 719, 667, 722, 611, 677, 781, 667, 729, 708, 979, 989, 854, 1000, 708, 719, 1042, 729, 556, 619, 604, 534, 618, 556, 736, 510, 611, 611, 507, 622, 740, 604, 611, 611, 611, 556, 889, 556, 885, 556, 646, 583, 889, 935, 707, 854, 594, 552, 865, 589, 556, 556, 611, 469, 563, 556, 278, 278, 278, 969, 906, 611, 507, 619, 556, 611, 778, 611, 575, 467, 944, 778, 944, 778, 944, 778, 667, 556, 333, 333, 556, 1000, 1000, 552, 278, 278, 278, 278, 500, 500, 500, 556, 556, 350, 1000, 1000, 240, 479, 333, 333, 604, 333, 167, 396, 556, 556, 1104, 556, 885, 516, 1146, 1000, 768, 600, 834, 834, 834, 834, 999, 500, 1000, 500, 1000, 500, 500, 494, 612, 823, 713, 584, 549, 713, 979, 722, 274, 549, 549, 583, 549, 549, 604, 584, 604, 604, 708, 625, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 729, 604, 604, 354, 354, 1000, 990, 990, 990, 990, 494, 604, 604, 604, 604, 354, 1021, 1052, 917, 750, 750, 531, 656, 594, 510, 500, 750, 750, 611, 611, 333, 333, 333, 333, 333, 333, 333, 333, 222, 222, 333, 333, 333, 333, 333, 333, 333, 333]; -exports.LiberationSansBoldItalicWidths = LiberationSansBoldItalicWidths; -const LiberationSansBoldItalicMapping = [-1, -1, -1, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 402, 506, 507, 508, 509, 510, 511, 536, 537, 538, 539, 710, 711, 713, 728, 729, 730, 731, 732, 733, 900, 901, 902, 903, 904, 905, 906, 908, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076, 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1138, 1139, 1168, 1169, 7808, 7809, 7810, 7811, 7812, 7813, 7922, 7923, 8208, 8209, 8211, 8212, 8213, 8215, 8216, 8217, 8218, 8219, 8220, 8221, 8222, 8224, 8225, 8226, 8230, 8240, 8242, 8243, 8249, 8250, 8252, 8254, 8260, 8319, 8355, 8356, 8359, 8364, 8453, 8467, 8470, 8482, 8486, 8494, 8539, 8540, 8541, 8542, 8592, 8593, 8594, 8595, 8596, 8597, 8616, 8706, 8710, 8719, 8721, 8722, 8730, 8734, 8735, 8745, 8747, 8776, 8800, 8801, 8804, 8805, 8962, 8976, 8992, 8993, 9472, 9474, 9484, 9488, 9492, 9496, 9500, 9508, 9516, 9524, 9532, 9552, 9553, 9554, 9555, 9556, 9557, 9558, 9559, 9560, 9561, 9562, 9563, 9564, 9565, 9566, 9567, 9568, 9569, 9570, 9571, 9572, 9573, 9574, 9575, 9576, 9577, 9578, 9579, 9580, 9600, 9604, 9608, 9612, 9616, 9617, 9618, 9619, 9632, 9633, 9642, 9643, 9644, 9650, 9658, 9660, 9668, 9674, 9675, 9679, 9688, 9689, 9702, 9786, 9787, 9788, 9792, 9794, 9824, 9827, 9829, 9830, 9834, 9835, 9836, 61441, 61442, 61445, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]; -exports.LiberationSansBoldItalicMapping = LiberationSansBoldItalicMapping; -const LiberationSansItalicWidths = [365, 0, 333, 278, 278, 355, 556, 556, 889, 667, 191, 333, 333, 389, 584, 278, 333, 278, 278, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 278, 278, 584, 584, 584, 556, 1015, 667, 667, 722, 722, 667, 611, 778, 722, 278, 500, 667, 556, 833, 722, 778, 667, 778, 722, 667, 611, 722, 667, 944, 667, 667, 611, 278, 278, 278, 469, 556, 333, 556, 556, 500, 556, 556, 278, 556, 556, 222, 222, 500, 222, 833, 556, 556, 556, 556, 333, 500, 278, 556, 500, 722, 500, 500, 500, 334, 260, 334, 584, 333, 556, 556, 556, 556, 260, 556, 333, 737, 370, 556, 584, 737, 552, 400, 549, 333, 333, 333, 576, 537, 278, 333, 333, 365, 556, 834, 834, 834, 611, 667, 667, 667, 667, 667, 667, 1000, 722, 667, 667, 667, 667, 278, 278, 278, 278, 722, 722, 778, 778, 778, 778, 778, 584, 778, 722, 722, 722, 722, 667, 667, 611, 556, 556, 556, 556, 556, 556, 889, 500, 556, 556, 556, 556, 278, 278, 278, 278, 556, 556, 556, 556, 556, 556, 556, 549, 611, 556, 556, 556, 556, 500, 556, 500, 667, 556, 667, 556, 667, 556, 722, 500, 722, 500, 722, 500, 722, 500, 722, 625, 722, 556, 667, 556, 667, 556, 667, 556, 667, 556, 667, 556, 778, 556, 778, 556, 778, 556, 778, 556, 722, 556, 722, 556, 278, 278, 278, 278, 278, 278, 278, 222, 278, 278, 733, 444, 500, 222, 667, 500, 500, 556, 222, 556, 222, 556, 281, 556, 400, 556, 222, 722, 556, 722, 556, 722, 556, 615, 723, 556, 778, 556, 778, 556, 778, 556, 1000, 944, 722, 333, 722, 333, 722, 333, 667, 500, 667, 500, 667, 500, 667, 500, 611, 278, 611, 354, 611, 278, 722, 556, 722, 556, 722, 556, 722, 556, 722, 556, 722, 556, 944, 722, 667, 500, 667, 611, 500, 611, 500, 611, 500, 222, 556, 667, 556, 1000, 889, 778, 611, 667, 500, 611, 278, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 667, 278, 789, 846, 389, 794, 865, 775, 222, 667, 667, 570, 671, 667, 611, 722, 778, 278, 667, 667, 833, 722, 648, 778, 725, 667, 600, 611, 667, 837, 667, 831, 761, 278, 667, 570, 439, 555, 222, 550, 570, 571, 500, 556, 439, 463, 555, 542, 222, 500, 492, 548, 500, 447, 556, 670, 573, 486, 603, 374, 550, 652, 546, 728, 779, 222, 550, 556, 550, 779, 667, 667, 843, 544, 708, 667, 278, 278, 500, 1066, 982, 844, 589, 715, 639, 724, 667, 651, 667, 544, 704, 667, 917, 614, 715, 715, 589, 686, 833, 722, 778, 725, 667, 722, 611, 639, 795, 667, 727, 673, 920, 923, 805, 886, 651, 694, 1022, 682, 556, 562, 522, 493, 553, 556, 688, 465, 556, 556, 472, 564, 686, 550, 556, 556, 556, 500, 833, 500, 835, 500, 572, 518, 830, 851, 621, 736, 526, 492, 752, 534, 556, 556, 556, 378, 496, 500, 222, 222, 222, 910, 828, 556, 472, 565, 500, 556, 778, 556, 492, 339, 944, 722, 944, 722, 944, 722, 667, 500, 333, 333, 556, 1000, 1000, 552, 222, 222, 222, 222, 333, 333, 333, 556, 556, 350, 1000, 1000, 188, 354, 333, 333, 500, 333, 167, 365, 556, 556, 1094, 556, 885, 323, 1083, 1000, 768, 600, 834, 834, 834, 834, 1000, 500, 998, 500, 1000, 500, 500, 494, 612, 823, 713, 584, 549, 713, 979, 719, 274, 549, 549, 584, 549, 549, 604, 584, 604, 604, 708, 625, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 729, 604, 604, 354, 354, 1000, 990, 990, 990, 990, 494, 604, 604, 604, 604, 354, 1021, 1052, 917, 750, 750, 531, 656, 594, 510, 500, 750, 750, 500, 500, 333, 333, 333, 333, 333, 333, 333, 333, 222, 222, 294, 294, 324, 324, 316, 328, 398, 285]; -exports.LiberationSansItalicWidths = LiberationSansItalicWidths; -const LiberationSansItalicMapping = [-1, -1, -1, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 402, 506, 507, 508, 509, 510, 511, 536, 537, 538, 539, 710, 711, 713, 728, 729, 730, 731, 732, 733, 900, 901, 902, 903, 904, 905, 906, 908, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076, 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1138, 1139, 1168, 1169, 7808, 7809, 7810, 7811, 7812, 7813, 7922, 7923, 8208, 8209, 8211, 8212, 8213, 8215, 8216, 8217, 8218, 8219, 8220, 8221, 8222, 8224, 8225, 8226, 8230, 8240, 8242, 8243, 8249, 8250, 8252, 8254, 8260, 8319, 8355, 8356, 8359, 8364, 8453, 8467, 8470, 8482, 8486, 8494, 8539, 8540, 8541, 8542, 8592, 8593, 8594, 8595, 8596, 8597, 8616, 8706, 8710, 8719, 8721, 8722, 8730, 8734, 8735, 8745, 8747, 8776, 8800, 8801, 8804, 8805, 8962, 8976, 8992, 8993, 9472, 9474, 9484, 9488, 9492, 9496, 9500, 9508, 9516, 9524, 9532, 9552, 9553, 9554, 9555, 9556, 9557, 9558, 9559, 9560, 9561, 9562, 9563, 9564, 9565, 9566, 9567, 9568, 9569, 9570, 9571, 9572, 9573, 9574, 9575, 9576, 9577, 9578, 9579, 9580, 9600, 9604, 9608, 9612, 9616, 9617, 9618, 9619, 9632, 9633, 9642, 9643, 9644, 9650, 9658, 9660, 9668, 9674, 9675, 9679, 9688, 9689, 9702, 9786, 9787, 9788, 9792, 9794, 9824, 9827, 9829, 9830, 9834, 9835, 9836, 61441, 61442, 61445, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]; -exports.LiberationSansItalicMapping = LiberationSansItalicMapping; -const LiberationSansRegularWidths = [365, 0, 333, 278, 278, 355, 556, 556, 889, 667, 191, 333, 333, 389, 584, 278, 333, 278, 278, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 278, 278, 584, 584, 584, 556, 1015, 667, 667, 722, 722, 667, 611, 778, 722, 278, 500, 667, 556, 833, 722, 778, 667, 778, 722, 667, 611, 722, 667, 944, 667, 667, 611, 278, 278, 278, 469, 556, 333, 556, 556, 500, 556, 556, 278, 556, 556, 222, 222, 500, 222, 833, 556, 556, 556, 556, 333, 500, 278, 556, 500, 722, 500, 500, 500, 334, 260, 334, 584, 333, 556, 556, 556, 556, 260, 556, 333, 737, 370, 556, 584, 737, 552, 400, 549, 333, 333, 333, 576, 537, 278, 333, 333, 365, 556, 834, 834, 834, 611, 667, 667, 667, 667, 667, 667, 1000, 722, 667, 667, 667, 667, 278, 278, 278, 278, 722, 722, 778, 778, 778, 778, 778, 584, 778, 722, 722, 722, 722, 667, 667, 611, 556, 556, 556, 556, 556, 556, 889, 500, 556, 556, 556, 556, 278, 278, 278, 278, 556, 556, 556, 556, 556, 556, 556, 549, 611, 556, 556, 556, 556, 500, 556, 500, 667, 556, 667, 556, 667, 556, 722, 500, 722, 500, 722, 500, 722, 500, 722, 615, 722, 556, 667, 556, 667, 556, 667, 556, 667, 556, 667, 556, 778, 556, 778, 556, 778, 556, 778, 556, 722, 556, 722, 556, 278, 278, 278, 278, 278, 278, 278, 222, 278, 278, 735, 444, 500, 222, 667, 500, 500, 556, 222, 556, 222, 556, 292, 556, 334, 556, 222, 722, 556, 722, 556, 722, 556, 604, 723, 556, 778, 556, 778, 556, 778, 556, 1000, 944, 722, 333, 722, 333, 722, 333, 667, 500, 667, 500, 667, 500, 667, 500, 611, 278, 611, 375, 611, 278, 722, 556, 722, 556, 722, 556, 722, 556, 722, 556, 722, 556, 944, 722, 667, 500, 667, 611, 500, 611, 500, 611, 500, 222, 556, 667, 556, 1000, 889, 778, 611, 667, 500, 611, 278, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 667, 278, 784, 838, 384, 774, 855, 752, 222, 667, 667, 551, 668, 667, 611, 722, 778, 278, 667, 668, 833, 722, 650, 778, 722, 667, 618, 611, 667, 798, 667, 835, 748, 278, 667, 578, 446, 556, 222, 547, 578, 575, 500, 557, 446, 441, 556, 556, 222, 500, 500, 576, 500, 448, 556, 690, 569, 482, 617, 395, 547, 648, 525, 713, 781, 222, 547, 556, 547, 781, 667, 667, 865, 542, 719, 667, 278, 278, 500, 1057, 1010, 854, 583, 722, 635, 719, 667, 656, 667, 542, 677, 667, 923, 604, 719, 719, 583, 656, 833, 722, 778, 719, 667, 722, 611, 635, 760, 667, 740, 667, 917, 938, 792, 885, 656, 719, 1010, 722, 556, 573, 531, 365, 583, 556, 669, 458, 559, 559, 438, 583, 688, 552, 556, 542, 556, 500, 458, 500, 823, 500, 573, 521, 802, 823, 625, 719, 521, 510, 750, 542, 556, 556, 556, 365, 510, 500, 222, 278, 222, 906, 812, 556, 438, 559, 500, 552, 778, 556, 489, 411, 944, 722, 944, 722, 944, 722, 667, 500, 333, 333, 556, 1000, 1000, 552, 222, 222, 222, 222, 333, 333, 333, 556, 556, 350, 1000, 1000, 188, 354, 333, 333, 500, 333, 167, 365, 556, 556, 1094, 556, 885, 323, 1073, 1000, 768, 600, 834, 834, 834, 834, 1000, 500, 1000, 500, 1000, 500, 500, 494, 612, 823, 713, 584, 549, 713, 979, 719, 274, 549, 549, 583, 549, 549, 604, 584, 604, 604, 708, 625, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 729, 604, 604, 354, 354, 1000, 990, 990, 990, 990, 494, 604, 604, 604, 604, 354, 1021, 1052, 917, 750, 750, 531, 656, 594, 510, 500, 750, 750, 500, 500, 333, 333, 333, 333, 333, 333, 333, 333, 222, 222, 294, 294, 324, 324, 316, 328, 398, 285]; -exports.LiberationSansRegularWidths = LiberationSansRegularWidths; -const LiberationSansRegularMapping = [-1, -1, -1, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 402, 506, 507, 508, 509, 510, 511, 536, 537, 538, 539, 710, 711, 713, 728, 729, 730, 731, 732, 733, 900, 901, 902, 903, 904, 905, 906, 908, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076, 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1138, 1139, 1168, 1169, 7808, 7809, 7810, 7811, 7812, 7813, 7922, 7923, 8208, 8209, 8211, 8212, 8213, 8215, 8216, 8217, 8218, 8219, 8220, 8221, 8222, 8224, 8225, 8226, 8230, 8240, 8242, 8243, 8249, 8250, 8252, 8254, 8260, 8319, 8355, 8356, 8359, 8364, 8453, 8467, 8470, 8482, 8486, 8494, 8539, 8540, 8541, 8542, 8592, 8593, 8594, 8595, 8596, 8597, 8616, 8706, 8710, 8719, 8721, 8722, 8730, 8734, 8735, 8745, 8747, 8776, 8800, 8801, 8804, 8805, 8962, 8976, 8992, 8993, 9472, 9474, 9484, 9488, 9492, 9496, 9500, 9508, 9516, 9524, 9532, 9552, 9553, 9554, 9555, 9556, 9557, 9558, 9559, 9560, 9561, 9562, 9563, 9564, 9565, 9566, 9567, 9568, 9569, 9570, 9571, 9572, 9573, 9574, 9575, 9576, 9577, 9578, 9579, 9580, 9600, 9604, 9608, 9612, 9616, 9617, 9618, 9619, 9632, 9633, 9642, 9643, 9644, 9650, 9658, 9660, 9668, 9674, 9675, 9679, 9688, 9689, 9702, 9786, 9787, 9788, 9792, 9794, 9824, 9827, 9829, 9830, 9834, 9835, 9836, 61441, 61442, 61445, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]; -exports.LiberationSansRegularMapping = LiberationSansRegularMapping; - -/***/ }), -/* 16 */ -/***/ ((__unused_webpack_module, exports) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.MyriadProRegularMetrics = exports.MyriadProRegularFactors = exports.MyriadProItalicMetrics = exports.MyriadProItalicFactors = exports.MyriadProBoldMetrics = exports.MyriadProBoldItalicMetrics = exports.MyriadProBoldItalicFactors = exports.MyriadProBoldFactors = void 0; -const MyriadProBoldFactors = [1.36898, 1, 1, 0.72706, 0.80479, 0.83734, 0.98894, 0.99793, 0.9897, 0.93884, 0.86209, 0.94292, 0.94292, 1.16661, 1.02058, 0.93582, 0.96694, 0.93582, 1.19137, 0.99793, 0.99793, 0.99793, 0.99793, 0.99793, 0.99793, 0.99793, 0.99793, 0.99793, 0.99793, 0.78076, 0.78076, 1.02058, 1.02058, 1.02058, 0.72851, 0.78966, 0.90838, 0.83637, 0.82391, 0.96376, 0.80061, 0.86275, 0.8768, 0.95407, 1.0258, 0.73901, 0.85022, 0.83655, 1.0156, 0.95546, 0.92179, 0.87107, 0.92179, 0.82114, 0.8096, 0.89713, 0.94438, 0.95353, 0.94083, 0.91905, 0.90406, 0.9446, 0.94292, 1.18777, 0.94292, 1.02058, 0.89903, 0.90088, 0.94938, 0.97898, 0.81093, 0.97571, 0.94938, 1.024, 0.9577, 0.95933, 0.98621, 1.0474, 0.97455, 0.98981, 0.9672, 0.95933, 0.9446, 0.97898, 0.97407, 0.97646, 0.78036, 1.10208, 0.95442, 0.95298, 0.97579, 0.9332, 0.94039, 0.938, 0.80687, 1.01149, 0.80687, 1.02058, 0.80479, 0.99793, 0.99793, 0.99793, 0.99793, 1.01149, 1.00872, 0.90088, 0.91882, 1.0213, 0.8361, 1.02058, 0.62295, 0.54324, 0.89022, 1.08595, 1, 1, 0.90088, 1, 0.97455, 0.93582, 0.90088, 1, 1.05686, 0.8361, 0.99642, 0.99642, 0.99642, 0.72851, 0.90838, 0.90838, 0.90838, 0.90838, 0.90838, 0.90838, 0.868, 0.82391, 0.80061, 0.80061, 0.80061, 0.80061, 1.0258, 1.0258, 1.0258, 1.0258, 0.97484, 0.95546, 0.92179, 0.92179, 0.92179, 0.92179, 0.92179, 1.02058, 0.92179, 0.94438, 0.94438, 0.94438, 0.94438, 0.90406, 0.86958, 0.98225, 0.94938, 0.94938, 0.94938, 0.94938, 0.94938, 0.94938, 0.9031, 0.81093, 0.94938, 0.94938, 0.94938, 0.94938, 0.98621, 0.98621, 0.98621, 0.98621, 0.93969, 0.95933, 0.9446, 0.9446, 0.9446, 0.9446, 0.9446, 1.08595, 0.9446, 0.95442, 0.95442, 0.95442, 0.95442, 0.94039, 0.97898, 0.94039, 0.90838, 0.94938, 0.90838, 0.94938, 0.90838, 0.94938, 0.82391, 0.81093, 0.82391, 0.81093, 0.82391, 0.81093, 0.82391, 0.81093, 0.96376, 0.84313, 0.97484, 0.97571, 0.80061, 0.94938, 0.80061, 0.94938, 0.80061, 0.94938, 0.80061, 0.94938, 0.80061, 0.94938, 0.8768, 0.9577, 0.8768, 0.9577, 0.8768, 0.9577, 1, 1, 0.95407, 0.95933, 0.97069, 0.95933, 1.0258, 0.98621, 1.0258, 0.98621, 1.0258, 0.98621, 1.0258, 0.98621, 1.0258, 0.98621, 0.887, 1.01591, 0.73901, 1.0474, 1, 1, 0.97455, 0.83655, 0.98981, 1, 1, 0.83655, 0.73977, 0.83655, 0.73903, 0.84638, 1.033, 0.95546, 0.95933, 1, 1, 0.95546, 0.95933, 0.8271, 0.95417, 0.95933, 0.92179, 0.9446, 0.92179, 0.9446, 0.92179, 0.9446, 0.936, 0.91964, 0.82114, 0.97646, 1, 1, 0.82114, 0.97646, 0.8096, 0.78036, 0.8096, 0.78036, 1, 1, 0.8096, 0.78036, 1, 1, 0.89713, 0.77452, 0.89713, 1.10208, 0.94438, 0.95442, 0.94438, 0.95442, 0.94438, 0.95442, 0.94438, 0.95442, 0.94438, 0.95442, 0.94438, 0.95442, 0.94083, 0.97579, 0.90406, 0.94039, 0.90406, 0.9446, 0.938, 0.9446, 0.938, 0.9446, 0.938, 1, 0.99793, 0.90838, 0.94938, 0.868, 0.9031, 0.92179, 0.9446, 1, 1, 0.89713, 1.10208, 0.90088, 0.90088, 0.90088, 0.90088, 0.90088, 0.90088, 0.90088, 0.90088, 0.90088, 0.90989, 0.9358, 0.91945, 0.83181, 0.75261, 0.87992, 0.82976, 0.96034, 0.83689, 0.97268, 1.0078, 0.90838, 0.83637, 0.8019, 0.90157, 0.80061, 0.9446, 0.95407, 0.92436, 1.0258, 0.85022, 0.97153, 1.0156, 0.95546, 0.89192, 0.92179, 0.92361, 0.87107, 0.96318, 0.89713, 0.93704, 0.95638, 0.91905, 0.91709, 0.92796, 1.0258, 0.93704, 0.94836, 1.0373, 0.95933, 1.0078, 0.95871, 0.94836, 0.96174, 0.92601, 0.9498, 0.98607, 0.95776, 0.95933, 1.05453, 1.0078, 0.98275, 0.9314, 0.95617, 0.91701, 1.05993, 0.9446, 0.78367, 0.9553, 1, 0.86832, 1.0128, 0.95871, 0.99394, 0.87548, 0.96361, 0.86774, 1.0078, 0.95871, 0.9446, 0.95871, 0.86774, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.94083, 0.97579, 0.94083, 0.97579, 0.94083, 0.97579, 0.90406, 0.94039, 0.96694, 1, 0.89903, 1, 1, 1, 0.93582, 0.93582, 0.93582, 1, 0.908, 0.908, 0.918, 0.94219, 0.94219, 0.96544, 1, 1.285, 1, 1, 0.81079, 0.81079, 1, 1, 0.74854, 1, 1, 1, 1, 0.99793, 1, 1, 1, 0.65, 1, 1.36145, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.17173, 1, 0.80535, 0.76169, 1.02058, 1.0732, 1.05486, 1, 1, 1.30692, 1.08595, 1.08595, 1, 1.08595, 1.08595, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.16161, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; -exports.MyriadProBoldFactors = MyriadProBoldFactors; -const MyriadProBoldMetrics = { - lineHeight: 1.2, - lineGap: 0.2 -}; -exports.MyriadProBoldMetrics = MyriadProBoldMetrics; -const MyriadProBoldItalicFactors = [1.36898, 1, 1, 0.66227, 0.80779, 0.81625, 0.97276, 0.97276, 0.97733, 0.92222, 0.83266, 0.94292, 0.94292, 1.16148, 1.02058, 0.93582, 0.96694, 0.93582, 1.17337, 0.97276, 0.97276, 0.97276, 0.97276, 0.97276, 0.97276, 0.97276, 0.97276, 0.97276, 0.97276, 0.78076, 0.78076, 1.02058, 1.02058, 1.02058, 0.71541, 0.76813, 0.85576, 0.80591, 0.80729, 0.94299, 0.77512, 0.83655, 0.86523, 0.92222, 0.98621, 0.71743, 0.81698, 0.79726, 0.98558, 0.92222, 0.90637, 0.83809, 0.90637, 0.80729, 0.76463, 0.86275, 0.90699, 0.91605, 0.9154, 0.85308, 0.85458, 0.90531, 0.94292, 1.21296, 0.94292, 1.02058, 0.89903, 1.18616, 0.99613, 0.91677, 0.78216, 0.91677, 0.90083, 0.98796, 0.9135, 0.92168, 0.95381, 0.98981, 0.95298, 0.95381, 0.93459, 0.92168, 0.91513, 0.92004, 0.91677, 0.95077, 0.748, 1.04502, 0.91677, 0.92061, 0.94236, 0.89544, 0.89364, 0.9, 0.80687, 0.8578, 0.80687, 1.02058, 0.80779, 0.97276, 0.97276, 0.97276, 0.97276, 0.8578, 0.99973, 1.18616, 0.91339, 1.08074, 0.82891, 1.02058, 0.55509, 0.71526, 0.89022, 1.08595, 1, 1, 1.18616, 1, 0.96736, 0.93582, 1.18616, 1, 1.04864, 0.82711, 0.99043, 0.99043, 0.99043, 0.71541, 0.85576, 0.85576, 0.85576, 0.85576, 0.85576, 0.85576, 0.845, 0.80729, 0.77512, 0.77512, 0.77512, 0.77512, 0.98621, 0.98621, 0.98621, 0.98621, 0.95961, 0.92222, 0.90637, 0.90637, 0.90637, 0.90637, 0.90637, 1.02058, 0.90251, 0.90699, 0.90699, 0.90699, 0.90699, 0.85458, 0.83659, 0.94951, 0.99613, 0.99613, 0.99613, 0.99613, 0.99613, 0.99613, 0.85811, 0.78216, 0.90083, 0.90083, 0.90083, 0.90083, 0.95381, 0.95381, 0.95381, 0.95381, 0.9135, 0.92168, 0.91513, 0.91513, 0.91513, 0.91513, 0.91513, 1.08595, 0.91677, 0.91677, 0.91677, 0.91677, 0.91677, 0.89364, 0.92332, 0.89364, 0.85576, 0.99613, 0.85576, 0.99613, 0.85576, 0.99613, 0.80729, 0.78216, 0.80729, 0.78216, 0.80729, 0.78216, 0.80729, 0.78216, 0.94299, 0.76783, 0.95961, 0.91677, 0.77512, 0.90083, 0.77512, 0.90083, 0.77512, 0.90083, 0.77512, 0.90083, 0.77512, 0.90083, 0.86523, 0.9135, 0.86523, 0.9135, 0.86523, 0.9135, 1, 1, 0.92222, 0.92168, 0.92222, 0.92168, 0.98621, 0.95381, 0.98621, 0.95381, 0.98621, 0.95381, 0.98621, 0.95381, 0.98621, 0.95381, 0.86036, 0.97096, 0.71743, 0.98981, 1, 1, 0.95298, 0.79726, 0.95381, 1, 1, 0.79726, 0.6894, 0.79726, 0.74321, 0.81691, 1.0006, 0.92222, 0.92168, 1, 1, 0.92222, 0.92168, 0.79464, 0.92098, 0.92168, 0.90637, 0.91513, 0.90637, 0.91513, 0.90637, 0.91513, 0.909, 0.87514, 0.80729, 0.95077, 1, 1, 0.80729, 0.95077, 0.76463, 0.748, 0.76463, 0.748, 1, 1, 0.76463, 0.748, 1, 1, 0.86275, 0.72651, 0.86275, 1.04502, 0.90699, 0.91677, 0.90699, 0.91677, 0.90699, 0.91677, 0.90699, 0.91677, 0.90699, 0.91677, 0.90699, 0.91677, 0.9154, 0.94236, 0.85458, 0.89364, 0.85458, 0.90531, 0.9, 0.90531, 0.9, 0.90531, 0.9, 1, 0.97276, 0.85576, 0.99613, 0.845, 0.85811, 0.90251, 0.91677, 1, 1, 0.86275, 1.04502, 1.18616, 1.18616, 1.18616, 1.18616, 1.18616, 1.18616, 1.18616, 1.18616, 1.18616, 1.00899, 1.30628, 0.85576, 0.80178, 0.66862, 0.7927, 0.69323, 0.88127, 0.72459, 0.89711, 0.95381, 0.85576, 0.80591, 0.7805, 0.94729, 0.77512, 0.90531, 0.92222, 0.90637, 0.98621, 0.81698, 0.92655, 0.98558, 0.92222, 0.85359, 0.90637, 0.90976, 0.83809, 0.94523, 0.86275, 0.83509, 0.93157, 0.85308, 0.83392, 0.92346, 0.98621, 0.83509, 0.92886, 0.91324, 0.92168, 0.95381, 0.90646, 0.92886, 0.90557, 0.86847, 0.90276, 0.91324, 0.86842, 0.92168, 0.99531, 0.95381, 0.9224, 0.85408, 0.92699, 0.86847, 1.0051, 0.91513, 0.80487, 0.93481, 1, 0.88159, 1.05214, 0.90646, 0.97355, 0.81539, 0.89398, 0.85923, 0.95381, 0.90646, 0.91513, 0.90646, 0.85923, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.9154, 0.94236, 0.9154, 0.94236, 0.9154, 0.94236, 0.85458, 0.89364, 0.96694, 1, 0.89903, 1, 1, 1, 0.91782, 0.91782, 0.91782, 1, 0.896, 0.896, 0.896, 0.9332, 0.9332, 0.95973, 1, 1.26, 1, 1, 0.80479, 0.80178, 1, 1, 0.85633, 1, 1, 1, 1, 0.97276, 1, 1, 1, 0.698, 1, 1.36145, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.14542, 1, 0.79199, 0.78694, 1.02058, 1.03493, 1.05486, 1, 1, 1.23026, 1.08595, 1.08595, 1, 1.08595, 1.08595, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.20006, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; -exports.MyriadProBoldItalicFactors = MyriadProBoldItalicFactors; -const MyriadProBoldItalicMetrics = { - lineHeight: 1.2, - lineGap: 0.2 -}; -exports.MyriadProBoldItalicMetrics = MyriadProBoldItalicMetrics; -const MyriadProItalicFactors = [1.36898, 1, 1, 0.65507, 0.84943, 0.85639, 0.88465, 0.88465, 0.86936, 0.88307, 0.86948, 0.85283, 0.85283, 1.06383, 1.02058, 0.75945, 0.9219, 0.75945, 1.17337, 0.88465, 0.88465, 0.88465, 0.88465, 0.88465, 0.88465, 0.88465, 0.88465, 0.88465, 0.88465, 0.75945, 0.75945, 1.02058, 1.02058, 1.02058, 0.69046, 0.70926, 0.85158, 0.77812, 0.76852, 0.89591, 0.70466, 0.76125, 0.80094, 0.86822, 0.83864, 0.728, 0.77212, 0.79475, 0.93637, 0.87514, 0.8588, 0.76013, 0.8588, 0.72421, 0.69866, 0.77598, 0.85991, 0.80811, 0.87832, 0.78112, 0.77512, 0.8562, 1.0222, 1.18417, 1.0222, 1.27014, 0.89903, 1.15012, 0.93859, 0.94399, 0.846, 0.94399, 0.81453, 1.0186, 0.94219, 0.96017, 1.03075, 1.02175, 0.912, 1.03075, 0.96998, 0.96017, 0.93859, 0.94399, 0.94399, 0.95493, 0.746, 1.12658, 0.94578, 0.91, 0.979, 0.882, 0.882, 0.83, 0.85034, 0.83537, 0.85034, 1.02058, 0.70869, 0.88465, 0.88465, 0.88465, 0.88465, 0.83537, 0.90083, 1.15012, 0.9161, 0.94565, 0.73541, 1.02058, 0.53609, 0.69353, 0.79519, 1.08595, 1, 1, 1.15012, 1, 0.91974, 0.75945, 1.15012, 1, 0.9446, 0.73361, 0.9005, 0.9005, 0.9005, 0.62864, 0.85158, 0.85158, 0.85158, 0.85158, 0.85158, 0.85158, 0.773, 0.76852, 0.70466, 0.70466, 0.70466, 0.70466, 0.83864, 0.83864, 0.83864, 0.83864, 0.90561, 0.87514, 0.8588, 0.8588, 0.8588, 0.8588, 0.8588, 1.02058, 0.85751, 0.85991, 0.85991, 0.85991, 0.85991, 0.77512, 0.76013, 0.88075, 0.93859, 0.93859, 0.93859, 0.93859, 0.93859, 0.93859, 0.8075, 0.846, 0.81453, 0.81453, 0.81453, 0.81453, 0.82424, 0.82424, 0.82424, 0.82424, 0.9278, 0.96017, 0.93859, 0.93859, 0.93859, 0.93859, 0.93859, 1.08595, 0.8562, 0.94578, 0.94578, 0.94578, 0.94578, 0.882, 0.94578, 0.882, 0.85158, 0.93859, 0.85158, 0.93859, 0.85158, 0.93859, 0.76852, 0.846, 0.76852, 0.846, 0.76852, 0.846, 0.76852, 0.846, 0.89591, 0.8544, 0.90561, 0.94399, 0.70466, 0.81453, 0.70466, 0.81453, 0.70466, 0.81453, 0.70466, 0.81453, 0.70466, 0.81453, 0.80094, 0.94219, 0.80094, 0.94219, 0.80094, 0.94219, 1, 1, 0.86822, 0.96017, 0.86822, 0.96017, 0.83864, 0.82424, 0.83864, 0.82424, 0.83864, 0.82424, 0.83864, 1.03075, 0.83864, 0.82424, 0.81402, 1.02738, 0.728, 1.02175, 1, 1, 0.912, 0.79475, 1.03075, 1, 1, 0.79475, 0.83911, 0.79475, 0.66266, 0.80553, 1.06676, 0.87514, 0.96017, 1, 1, 0.87514, 0.96017, 0.86865, 0.87396, 0.96017, 0.8588, 0.93859, 0.8588, 0.93859, 0.8588, 0.93859, 0.867, 0.84759, 0.72421, 0.95493, 1, 1, 0.72421, 0.95493, 0.69866, 0.746, 0.69866, 0.746, 1, 1, 0.69866, 0.746, 1, 1, 0.77598, 0.88417, 0.77598, 1.12658, 0.85991, 0.94578, 0.85991, 0.94578, 0.85991, 0.94578, 0.85991, 0.94578, 0.85991, 0.94578, 0.85991, 0.94578, 0.87832, 0.979, 0.77512, 0.882, 0.77512, 0.8562, 0.83, 0.8562, 0.83, 0.8562, 0.83, 1, 0.88465, 0.85158, 0.93859, 0.773, 0.8075, 0.85751, 0.8562, 1, 1, 0.77598, 1.12658, 1.15012, 1.15012, 1.15012, 1.15012, 1.15012, 1.15313, 1.15012, 1.15012, 1.15012, 1.08106, 1.03901, 0.85158, 0.77025, 0.62264, 0.7646, 0.65351, 0.86026, 0.69461, 0.89947, 1.03075, 0.85158, 0.77812, 0.76449, 0.88836, 0.70466, 0.8562, 0.86822, 0.8588, 0.83864, 0.77212, 0.85308, 0.93637, 0.87514, 0.82352, 0.8588, 0.85701, 0.76013, 0.89058, 0.77598, 0.8156, 0.82565, 0.78112, 0.77899, 0.89386, 0.83864, 0.8156, 0.9486, 0.92388, 0.96186, 1.03075, 0.91123, 0.9486, 0.93298, 0.878, 0.93942, 0.92388, 0.84596, 0.96186, 0.95119, 1.03075, 0.922, 0.88787, 0.95829, 0.88, 0.93559, 0.93859, 0.78815, 0.93758, 1, 0.89217, 1.03737, 0.91123, 0.93969, 0.77487, 0.85769, 0.86799, 1.03075, 0.91123, 0.93859, 0.91123, 0.86799, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.87832, 0.979, 0.87832, 0.979, 0.87832, 0.979, 0.77512, 0.882, 0.9219, 1, 0.89903, 1, 1, 1, 0.87321, 0.87321, 0.87321, 1, 1.027, 1.027, 1.027, 0.86847, 0.86847, 0.79121, 1, 1.124, 1, 1, 0.73572, 0.73572, 1, 1, 0.85034, 1, 1, 1, 1, 0.88465, 1, 1, 1, 0.669, 1, 1.36145, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.04828, 1, 0.74948, 0.75187, 1.02058, 0.98391, 1.02119, 1, 1, 1.06233, 1.08595, 1.08595, 1, 1.08595, 1.08595, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.05233, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; -exports.MyriadProItalicFactors = MyriadProItalicFactors; -const MyriadProItalicMetrics = { - lineHeight: 1.2, - lineGap: 0.2 -}; -exports.MyriadProItalicMetrics = MyriadProItalicMetrics; -const MyriadProRegularFactors = [1.36898, 1, 1, 0.76305, 0.82784, 0.94935, 0.89364, 0.92241, 0.89073, 0.90706, 0.98472, 0.85283, 0.85283, 1.0664, 1.02058, 0.74505, 0.9219, 0.74505, 1.23456, 0.92241, 0.92241, 0.92241, 0.92241, 0.92241, 0.92241, 0.92241, 0.92241, 0.92241, 0.92241, 0.74505, 0.74505, 1.02058, 1.02058, 1.02058, 0.73002, 0.72601, 0.91755, 0.8126, 0.80314, 0.92222, 0.73764, 0.79726, 0.83051, 0.90284, 0.86023, 0.74, 0.8126, 0.84869, 0.96518, 0.91115, 0.8858, 0.79761, 0.8858, 0.74498, 0.73914, 0.81363, 0.89591, 0.83659, 0.89633, 0.85608, 0.8111, 0.90531, 1.0222, 1.22736, 1.0222, 1.27014, 0.89903, 0.90088, 0.86667, 1.0231, 0.896, 1.01411, 0.90083, 1.05099, 1.00512, 0.99793, 1.05326, 1.09377, 0.938, 1.06226, 1.00119, 0.99793, 0.98714, 1.0231, 1.01231, 0.98196, 0.792, 1.19137, 0.99074, 0.962, 1.01915, 0.926, 0.942, 0.856, 0.85034, 0.92006, 0.85034, 1.02058, 0.69067, 0.92241, 0.92241, 0.92241, 0.92241, 0.92006, 0.9332, 0.90088, 0.91882, 0.93484, 0.75339, 1.02058, 0.56866, 0.54324, 0.79519, 1.08595, 1, 1, 0.90088, 1, 0.95325, 0.74505, 0.90088, 1, 0.97198, 0.75339, 0.91009, 0.91009, 0.91009, 0.66466, 0.91755, 0.91755, 0.91755, 0.91755, 0.91755, 0.91755, 0.788, 0.80314, 0.73764, 0.73764, 0.73764, 0.73764, 0.86023, 0.86023, 0.86023, 0.86023, 0.92915, 0.91115, 0.8858, 0.8858, 0.8858, 0.8858, 0.8858, 1.02058, 0.8858, 0.89591, 0.89591, 0.89591, 0.89591, 0.8111, 0.79611, 0.89713, 0.86667, 0.86667, 0.86667, 0.86667, 0.86667, 0.86667, 0.86936, 0.896, 0.90083, 0.90083, 0.90083, 0.90083, 0.84224, 0.84224, 0.84224, 0.84224, 0.97276, 0.99793, 0.98714, 0.98714, 0.98714, 0.98714, 0.98714, 1.08595, 0.89876, 0.99074, 0.99074, 0.99074, 0.99074, 0.942, 1.0231, 0.942, 0.91755, 0.86667, 0.91755, 0.86667, 0.91755, 0.86667, 0.80314, 0.896, 0.80314, 0.896, 0.80314, 0.896, 0.80314, 0.896, 0.92222, 0.93372, 0.92915, 1.01411, 0.73764, 0.90083, 0.73764, 0.90083, 0.73764, 0.90083, 0.73764, 0.90083, 0.73764, 0.90083, 0.83051, 1.00512, 0.83051, 1.00512, 0.83051, 1.00512, 1, 1, 0.90284, 0.99793, 0.90976, 0.99793, 0.86023, 0.84224, 0.86023, 0.84224, 0.86023, 0.84224, 0.86023, 1.05326, 0.86023, 0.84224, 0.82873, 1.07469, 0.74, 1.09377, 1, 1, 0.938, 0.84869, 1.06226, 1, 1, 0.84869, 0.83704, 0.84869, 0.81441, 0.85588, 1.08927, 0.91115, 0.99793, 1, 1, 0.91115, 0.99793, 0.91887, 0.90991, 0.99793, 0.8858, 0.98714, 0.8858, 0.98714, 0.8858, 0.98714, 0.894, 0.91434, 0.74498, 0.98196, 1, 1, 0.74498, 0.98196, 0.73914, 0.792, 0.73914, 0.792, 1, 1, 0.73914, 0.792, 1, 1, 0.81363, 0.904, 0.81363, 1.19137, 0.89591, 0.99074, 0.89591, 0.99074, 0.89591, 0.99074, 0.89591, 0.99074, 0.89591, 0.99074, 0.89591, 0.99074, 0.89633, 1.01915, 0.8111, 0.942, 0.8111, 0.90531, 0.856, 0.90531, 0.856, 0.90531, 0.856, 1, 0.92241, 0.91755, 0.86667, 0.788, 0.86936, 0.8858, 0.89876, 1, 1, 0.81363, 1.19137, 0.90088, 0.90088, 0.90088, 0.90088, 0.90088, 0.90088, 0.90088, 0.90088, 0.90088, 0.90388, 1.03901, 0.92138, 0.78105, 0.7154, 0.86169, 0.80513, 0.94007, 0.82528, 0.98612, 1.06226, 0.91755, 0.8126, 0.81884, 0.92819, 0.73764, 0.90531, 0.90284, 0.8858, 0.86023, 0.8126, 0.91172, 0.96518, 0.91115, 0.83089, 0.8858, 0.87791, 0.79761, 0.89297, 0.81363, 0.88157, 0.89992, 0.85608, 0.81992, 0.94307, 0.86023, 0.88157, 0.95308, 0.98699, 0.99793, 1.06226, 0.95817, 0.95308, 0.97358, 0.928, 0.98088, 0.98699, 0.92761, 0.99793, 0.96017, 1.06226, 0.986, 0.944, 0.95978, 0.938, 0.96705, 0.98714, 0.80442, 0.98972, 1, 0.89762, 1.04552, 0.95817, 0.99007, 0.87064, 0.91879, 0.88888, 1.06226, 0.95817, 0.98714, 0.95817, 0.88888, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.89633, 1.01915, 0.89633, 1.01915, 0.89633, 1.01915, 0.8111, 0.942, 0.9219, 1, 0.89903, 1, 1, 1, 0.93173, 0.93173, 0.93173, 1, 1.06304, 1.06304, 1.06904, 0.89903, 0.89903, 0.80549, 1, 1.156, 1, 1, 0.76575, 0.76575, 1, 1, 0.72458, 1, 1, 1, 1, 0.92241, 1, 1, 1, 0.619, 1, 1.36145, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.07257, 1, 0.74705, 0.71119, 1.02058, 1.024, 1.02119, 1, 1, 1.1536, 1.08595, 1.08595, 1, 1.08595, 1.08595, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.05638, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; -exports.MyriadProRegularFactors = MyriadProRegularFactors; -const MyriadProRegularMetrics = { - lineHeight: 1.2, - lineGap: 0.2 -}; -exports.MyriadProRegularMetrics = MyriadProRegularMetrics; - -/***/ }), -/* 17 */ -/***/ ((__unused_webpack_module, exports) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.SegoeuiRegularMetrics = exports.SegoeuiRegularFactors = exports.SegoeuiItalicMetrics = exports.SegoeuiItalicFactors = exports.SegoeuiBoldMetrics = exports.SegoeuiBoldItalicMetrics = exports.SegoeuiBoldItalicFactors = exports.SegoeuiBoldFactors = void 0; -const SegoeuiBoldFactors = [1.76738, 1, 1, 0.99297, 0.9824, 1.04016, 1.06497, 1.03424, 0.97529, 1.17647, 1.23203, 1.1085, 1.1085, 1.16939, 1.2107, 0.9754, 1.21408, 0.9754, 1.59578, 1.03424, 1.03424, 1.03424, 1.03424, 1.03424, 1.03424, 1.03424, 1.03424, 1.03424, 1.03424, 0.81378, 0.81378, 1.2107, 1.2107, 1.2107, 0.71703, 0.97847, 0.97363, 0.88776, 0.8641, 1.02096, 0.79795, 0.85132, 0.914, 1.06085, 1.1406, 0.8007, 0.89858, 0.83693, 1.14889, 1.09398, 0.97489, 0.92094, 0.97489, 0.90399, 0.84041, 0.95923, 1.00135, 1, 1.06467, 0.98243, 0.90996, 0.99361, 1.1085, 1.56942, 1.1085, 1.2107, 0.74627, 0.94282, 0.96752, 1.01519, 0.86304, 1.01359, 0.97278, 1.15103, 1.01359, 0.98561, 1.02285, 1.02285, 1.00527, 1.02285, 1.0302, 0.99041, 1.0008, 1.01519, 1.01359, 1.02258, 0.79104, 1.16862, 0.99041, 0.97454, 1.02511, 0.99298, 0.96752, 0.95801, 0.94856, 1.16579, 0.94856, 1.2107, 0.9824, 1.03424, 1.03424, 1, 1.03424, 1.16579, 0.8727, 1.3871, 1.18622, 1.10818, 1.04478, 1.2107, 1.18622, 0.75155, 0.94994, 1.28826, 1.21408, 1.21408, 0.91056, 1, 0.91572, 0.9754, 0.64663, 1.18328, 1.24866, 1.04478, 1.14169, 1.15749, 1.17389, 0.71703, 0.97363, 0.97363, 0.97363, 0.97363, 0.97363, 0.97363, 0.93506, 0.8641, 0.79795, 0.79795, 0.79795, 0.79795, 1.1406, 1.1406, 1.1406, 1.1406, 1.02096, 1.09398, 0.97426, 0.97426, 0.97426, 0.97426, 0.97426, 1.2107, 0.97489, 1.00135, 1.00135, 1.00135, 1.00135, 0.90996, 0.92094, 1.02798, 0.96752, 0.96752, 0.96752, 0.96752, 0.96752, 0.96752, 0.93136, 0.86304, 0.97278, 0.97278, 0.97278, 0.97278, 1.02285, 1.02285, 1.02285, 1.02285, 0.97122, 0.99041, 1, 1, 1, 1, 1, 1.28826, 1.0008, 0.99041, 0.99041, 0.99041, 0.99041, 0.96752, 1.01519, 0.96752, 0.97363, 0.96752, 0.97363, 0.96752, 0.97363, 0.96752, 0.8641, 0.86304, 0.8641, 0.86304, 0.8641, 0.86304, 0.8641, 0.86304, 1.02096, 1.03057, 1.02096, 1.03517, 0.79795, 0.97278, 0.79795, 0.97278, 0.79795, 0.97278, 0.79795, 0.97278, 0.79795, 0.97278, 0.914, 1.01359, 0.914, 1.01359, 0.914, 1.01359, 1, 1, 1.06085, 0.98561, 1.06085, 1.00879, 1.1406, 1.02285, 1.1406, 1.02285, 1.1406, 1.02285, 1.1406, 1.02285, 1.1406, 1.02285, 0.97138, 1.08692, 0.8007, 1.02285, 1, 1, 1.00527, 0.83693, 1.02285, 1, 1, 0.83693, 0.9455, 0.83693, 0.90418, 0.83693, 1.13005, 1.09398, 0.99041, 1, 1, 1.09398, 0.99041, 0.96692, 1.09251, 0.99041, 0.97489, 1.0008, 0.97489, 1.0008, 0.97489, 1.0008, 0.93994, 0.97931, 0.90399, 1.02258, 1, 1, 0.90399, 1.02258, 0.84041, 0.79104, 0.84041, 0.79104, 0.84041, 0.79104, 0.84041, 0.79104, 1, 1, 0.95923, 1.07034, 0.95923, 1.16862, 1.00135, 0.99041, 1.00135, 0.99041, 1.00135, 0.99041, 1.00135, 0.99041, 1.00135, 0.99041, 1.00135, 0.99041, 1.06467, 1.02511, 0.90996, 0.96752, 0.90996, 0.99361, 0.95801, 0.99361, 0.95801, 0.99361, 0.95801, 1.07733, 1.03424, 0.97363, 0.96752, 0.93506, 0.93136, 0.97489, 1.0008, 1, 1, 0.95923, 1.16862, 1.15103, 1.15103, 1.01173, 1.03959, 0.75953, 0.81378, 0.79912, 1.15103, 1.21994, 0.95161, 0.87815, 1.01149, 0.81525, 0.7676, 0.98167, 1.01134, 1.02546, 0.84097, 1.03089, 1.18102, 0.97363, 0.88776, 0.85134, 0.97826, 0.79795, 0.99361, 1.06085, 0.97489, 1.1406, 0.89858, 1.0388, 1.14889, 1.09398, 0.86039, 0.97489, 1.0595, 0.92094, 0.94793, 0.95923, 0.90996, 0.99346, 0.98243, 1.02112, 0.95493, 1.1406, 0.90996, 1.03574, 1.02597, 1.0008, 1.18102, 1.06628, 1.03574, 1.0192, 1.01932, 1.00886, 0.97531, 1.0106, 1.0008, 1.13189, 1.18102, 1.02277, 0.98683, 1.0016, 0.99561, 1.07237, 1.0008, 0.90434, 0.99921, 0.93803, 0.8965, 1.23085, 1.06628, 1.04983, 0.96268, 1.0499, 0.98439, 1.18102, 1.06628, 1.0008, 1.06628, 0.98439, 0.79795, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.09466, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.97278, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.02065, 1, 1, 1, 1, 1, 1, 1.06467, 1.02511, 1.06467, 1.02511, 1.06467, 1.02511, 0.90996, 0.96752, 1, 1.21408, 0.89903, 1, 1, 0.75155, 1.04394, 1.04394, 1.04394, 1.04394, 0.98633, 0.98633, 0.98633, 0.73047, 0.73047, 1.20642, 0.91211, 1.25635, 1.222, 1.02956, 1.03372, 1.03372, 0.96039, 1.24633, 1, 1.12454, 0.93503, 1.03424, 1.19687, 1.03424, 1, 1, 1, 0.771, 1, 1, 1.15749, 1.15749, 1.15749, 1.10948, 0.86279, 0.94434, 0.86279, 0.94434, 0.86182, 1, 1, 1.16897, 1, 0.96085, 0.90137, 1.2107, 1.18416, 1.13973, 0.69825, 0.9716, 2.10339, 1.29004, 1.29004, 1.21172, 1.29004, 1.29004, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.42603, 1, 0.99862, 0.99862, 1, 0.87025, 0.87025, 0.87025, 0.87025, 1.18874, 1.42603, 1, 1.42603, 1.42603, 0.99862, 1, 1, 1, 1, 1, 1.2886, 1.04315, 1.15296, 1.34163, 1, 1, 1, 1.09193, 1.09193, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; -exports.SegoeuiBoldFactors = SegoeuiBoldFactors; -const SegoeuiBoldMetrics = { - lineHeight: 1.33008, - lineGap: 0 -}; -exports.SegoeuiBoldMetrics = SegoeuiBoldMetrics; -const SegoeuiBoldItalicFactors = [1.76738, 1, 1, 0.98946, 1.03959, 1.04016, 1.02809, 1.036, 0.97639, 1.10953, 1.23203, 1.11144, 1.11144, 1.16939, 1.21237, 0.9754, 1.21261, 0.9754, 1.59754, 1.036, 1.036, 1.036, 1.036, 1.036, 1.036, 1.036, 1.036, 1.036, 1.036, 0.81378, 0.81378, 1.21237, 1.21237, 1.21237, 0.73541, 0.97847, 0.97363, 0.89723, 0.87897, 1.0426, 0.79429, 0.85292, 0.91149, 1.05815, 1.1406, 0.79631, 0.90128, 0.83853, 1.04396, 1.10615, 0.97552, 0.94436, 0.97552, 0.88641, 0.80527, 0.96083, 1.00135, 1, 1.06777, 0.9817, 0.91142, 0.99361, 1.11144, 1.57293, 1.11144, 1.21237, 0.74627, 1.31818, 1.06585, 0.97042, 0.83055, 0.97042, 0.93503, 1.1261, 0.97042, 0.97922, 1.14236, 0.94552, 1.01054, 1.14236, 1.02471, 0.97922, 0.94165, 0.97042, 0.97042, 1.0276, 0.78929, 1.1261, 0.97922, 0.95874, 1.02197, 0.98507, 0.96752, 0.97168, 0.95107, 1.16579, 0.95107, 1.21237, 1.03959, 1.036, 1.036, 1, 1.036, 1.16579, 0.87357, 1.31818, 1.18754, 1.26781, 1.05356, 1.21237, 1.18622, 0.79487, 0.94994, 1.29004, 1.24047, 1.24047, 1.31818, 1, 0.91484, 0.9754, 1.31818, 1.1349, 1.24866, 1.05356, 1.13934, 1.15574, 1.17389, 0.73541, 0.97363, 0.97363, 0.97363, 0.97363, 0.97363, 0.97363, 0.94385, 0.87897, 0.79429, 0.79429, 0.79429, 0.79429, 1.1406, 1.1406, 1.1406, 1.1406, 1.0426, 1.10615, 0.97552, 0.97552, 0.97552, 0.97552, 0.97552, 1.21237, 0.97552, 1.00135, 1.00135, 1.00135, 1.00135, 0.91142, 0.94436, 0.98721, 1.06585, 1.06585, 1.06585, 1.06585, 1.06585, 1.06585, 0.96705, 0.83055, 0.93503, 0.93503, 0.93503, 0.93503, 1.14236, 1.14236, 1.14236, 1.14236, 0.93125, 0.97922, 0.94165, 0.94165, 0.94165, 0.94165, 0.94165, 1.29004, 0.94165, 0.97922, 0.97922, 0.97922, 0.97922, 0.96752, 0.97042, 0.96752, 0.97363, 1.06585, 0.97363, 1.06585, 0.97363, 1.06585, 0.87897, 0.83055, 0.87897, 0.83055, 0.87897, 0.83055, 0.87897, 0.83055, 1.0426, 1.0033, 1.0426, 0.97042, 0.79429, 0.93503, 0.79429, 0.93503, 0.79429, 0.93503, 0.79429, 0.93503, 0.79429, 0.93503, 0.91149, 0.97042, 0.91149, 0.97042, 0.91149, 0.97042, 1, 1, 1.05815, 0.97922, 1.05815, 0.97922, 1.1406, 1.14236, 1.1406, 1.14236, 1.1406, 1.14236, 1.1406, 1.14236, 1.1406, 1.14236, 0.97441, 1.04302, 0.79631, 1.01582, 1, 1, 1.01054, 0.83853, 1.14236, 1, 1, 0.83853, 1.09125, 0.83853, 0.90418, 0.83853, 1.19508, 1.10615, 0.97922, 1, 1, 1.10615, 0.97922, 1.01034, 1.10466, 0.97922, 0.97552, 0.94165, 0.97552, 0.94165, 0.97552, 0.94165, 0.91602, 0.91981, 0.88641, 1.0276, 1, 1, 0.88641, 1.0276, 0.80527, 0.78929, 0.80527, 0.78929, 0.80527, 0.78929, 0.80527, 0.78929, 1, 1, 0.96083, 1.05403, 0.95923, 1.16862, 1.00135, 0.97922, 1.00135, 0.97922, 1.00135, 0.97922, 1.00135, 0.97922, 1.00135, 0.97922, 1.00135, 0.97922, 1.06777, 1.02197, 0.91142, 0.96752, 0.91142, 0.99361, 0.97168, 0.99361, 0.97168, 0.99361, 0.97168, 1.23199, 1.036, 0.97363, 1.06585, 0.94385, 0.96705, 0.97552, 0.94165, 1, 1, 0.96083, 1.1261, 1.31818, 1.31818, 1.31818, 1.31818, 1.31818, 1.31818, 1.31818, 1.31818, 1.31818, 0.95161, 1.27126, 1.00811, 0.83284, 0.77702, 0.99137, 0.95253, 1.0347, 0.86142, 1.07205, 1.14236, 0.97363, 0.89723, 0.86869, 1.09818, 0.79429, 0.99361, 1.05815, 0.97552, 1.1406, 0.90128, 1.06662, 1.04396, 1.10615, 0.84918, 0.97552, 1.04694, 0.94436, 0.98015, 0.96083, 0.91142, 1.00356, 0.9817, 1.01945, 0.98999, 1.1406, 0.91142, 1.04961, 0.9898, 1.00639, 1.14236, 1.07514, 1.04961, 0.99607, 1.02897, 1.008, 0.9898, 0.95134, 1.00639, 1.11121, 1.14236, 1.00518, 0.97981, 1.02186, 1, 1.08578, 0.94165, 0.99314, 0.98387, 0.93028, 0.93377, 1.35125, 1.07514, 1.10687, 0.93491, 1.04232, 1.00351, 1.14236, 1.07514, 0.94165, 1.07514, 1.00351, 0.79429, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.09097, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.93503, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.96609, 1, 1, 1, 1, 1, 1, 1.06777, 1.02197, 1.06777, 1.02197, 1.06777, 1.02197, 0.91142, 0.96752, 1, 1.21261, 0.89903, 1, 1, 0.75155, 1.04745, 1.04745, 1.04745, 1.04394, 0.98633, 0.98633, 0.98633, 0.72959, 0.72959, 1.20502, 0.91406, 1.26514, 1.222, 1.02956, 1.03372, 1.03372, 0.96039, 1.24633, 1, 1.09125, 0.93327, 1.03336, 1.16541, 1.036, 1, 1, 1, 0.771, 1, 1, 1.15574, 1.15574, 1.15574, 1.15574, 0.86364, 0.94434, 0.86279, 0.94434, 0.86224, 1, 1, 1.16798, 1, 0.96085, 0.90068, 1.21237, 1.18416, 1.13904, 0.69825, 0.9716, 2.10339, 1.29004, 1.29004, 1.21339, 1.29004, 1.29004, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.42603, 1, 0.99862, 0.99862, 1, 0.87025, 0.87025, 0.87025, 0.87025, 1.18775, 1.42603, 1, 1.42603, 1.42603, 0.99862, 1, 1, 1, 1, 1, 1.2886, 1.04315, 1.15296, 1.34163, 1, 1, 1, 1.13269, 1.13269, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; -exports.SegoeuiBoldItalicFactors = SegoeuiBoldItalicFactors; -const SegoeuiBoldItalicMetrics = { - lineHeight: 1.33008, - lineGap: 0 -}; -exports.SegoeuiBoldItalicMetrics = SegoeuiBoldItalicMetrics; -const SegoeuiItalicFactors = [1.76738, 1, 1, 0.98946, 1.14763, 1.05365, 1.06234, 0.96927, 0.92586, 1.15373, 1.18414, 0.91349, 0.91349, 1.07403, 1.17308, 0.78383, 1.20088, 0.78383, 1.42531, 0.96927, 0.96927, 0.96927, 0.96927, 0.96927, 0.96927, 0.96927, 0.96927, 0.96927, 0.96927, 0.78383, 0.78383, 1.17308, 1.17308, 1.17308, 0.77349, 0.94565, 0.94729, 0.85944, 0.88506, 0.9858, 0.74817, 0.80016, 0.88449, 0.98039, 0.95782, 0.69238, 0.89898, 0.83231, 0.98183, 1.03989, 0.96924, 0.86237, 0.96924, 0.80595, 0.74524, 0.86091, 0.95402, 0.94143, 0.98448, 0.8858, 0.83089, 0.93285, 1.0949, 1.39016, 1.0949, 1.45994, 0.74627, 1.04839, 0.97454, 0.97454, 0.87207, 0.97454, 0.87533, 1.06151, 0.97454, 1.00176, 1.16484, 1.08132, 0.98047, 1.16484, 1.02989, 1.01054, 0.96225, 0.97454, 0.97454, 1.06598, 0.79004, 1.16344, 1.00351, 0.94629, 0.9973, 0.91016, 0.96777, 0.9043, 0.91082, 0.92481, 0.91082, 1.17308, 0.95748, 0.96927, 0.96927, 1, 0.96927, 0.92481, 0.80597, 1.04839, 1.23393, 1.1781, 0.9245, 1.17308, 1.20808, 0.63218, 0.94261, 1.24822, 1.09971, 1.09971, 1.04839, 1, 0.85273, 0.78032, 1.04839, 1.09971, 1.22326, 0.9245, 1.09836, 1.13525, 1.15222, 0.70424, 0.94729, 0.94729, 0.94729, 0.94729, 0.94729, 0.94729, 0.85498, 0.88506, 0.74817, 0.74817, 0.74817, 0.74817, 0.95782, 0.95782, 0.95782, 0.95782, 0.9858, 1.03989, 0.96924, 0.96924, 0.96924, 0.96924, 0.96924, 1.17308, 0.96924, 0.95402, 0.95402, 0.95402, 0.95402, 0.83089, 0.86237, 0.88409, 0.97454, 0.97454, 0.97454, 0.97454, 0.97454, 0.97454, 0.92916, 0.87207, 0.87533, 0.87533, 0.87533, 0.87533, 0.93146, 0.93146, 0.93146, 0.93146, 0.93854, 1.01054, 0.96225, 0.96225, 0.96225, 0.96225, 0.96225, 1.24822, 0.8761, 1.00351, 1.00351, 1.00351, 1.00351, 0.96777, 0.97454, 0.96777, 0.94729, 0.97454, 0.94729, 0.97454, 0.94729, 0.97454, 0.88506, 0.87207, 0.88506, 0.87207, 0.88506, 0.87207, 0.88506, 0.87207, 0.9858, 0.95391, 0.9858, 0.97454, 0.74817, 0.87533, 0.74817, 0.87533, 0.74817, 0.87533, 0.74817, 0.87533, 0.74817, 0.87533, 0.88449, 0.97454, 0.88449, 0.97454, 0.88449, 0.97454, 1, 1, 0.98039, 1.00176, 0.98039, 1.00176, 0.95782, 0.93146, 0.95782, 0.93146, 0.95782, 0.93146, 0.95782, 1.16484, 0.95782, 0.93146, 0.84421, 1.12761, 0.69238, 1.08132, 1, 1, 0.98047, 0.83231, 1.16484, 1, 1, 0.84723, 1.04861, 0.84723, 0.78755, 0.83231, 1.23736, 1.03989, 1.01054, 1, 1, 1.03989, 1.01054, 0.9857, 1.03849, 1.01054, 0.96924, 0.96225, 0.96924, 0.96225, 0.96924, 0.96225, 0.92383, 0.90171, 0.80595, 1.06598, 1, 1, 0.80595, 1.06598, 0.74524, 0.79004, 0.74524, 0.79004, 0.74524, 0.79004, 0.74524, 0.79004, 1, 1, 0.86091, 1.02759, 0.85771, 1.16344, 0.95402, 1.00351, 0.95402, 1.00351, 0.95402, 1.00351, 0.95402, 1.00351, 0.95402, 1.00351, 0.95402, 1.00351, 0.98448, 0.9973, 0.83089, 0.96777, 0.83089, 0.93285, 0.9043, 0.93285, 0.9043, 0.93285, 0.9043, 1.31868, 0.96927, 0.94729, 0.97454, 0.85498, 0.92916, 0.96924, 0.8761, 1, 1, 0.86091, 1.16344, 1.04839, 1.04839, 1.04839, 1.04839, 1.04839, 1.04839, 1.04839, 1.04839, 1.04839, 0.81965, 0.81965, 0.94729, 0.78032, 0.71022, 0.90883, 0.84171, 0.99877, 0.77596, 1.05734, 1.2, 0.94729, 0.85944, 0.82791, 0.9607, 0.74817, 0.93285, 0.98039, 0.96924, 0.95782, 0.89898, 0.98316, 0.98183, 1.03989, 0.78614, 0.96924, 0.97642, 0.86237, 0.86075, 0.86091, 0.83089, 0.90082, 0.8858, 0.97296, 1.01284, 0.95782, 0.83089, 1.0976, 1.04, 1.03342, 1.2, 1.0675, 1.0976, 0.98205, 1.03809, 1.05097, 1.04, 0.95364, 1.03342, 1.05401, 1.2, 1.02148, 1.0119, 1.04724, 1.0127, 1.02732, 0.96225, 0.8965, 0.97783, 0.93574, 0.94818, 1.30679, 1.0675, 1.11826, 0.99821, 1.0557, 1.0326, 1.2, 1.0675, 0.96225, 1.0675, 1.0326, 0.74817, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.03754, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.87533, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.98705, 1, 1, 1, 1, 1, 1, 0.98448, 0.9973, 0.98448, 0.9973, 0.98448, 0.9973, 0.83089, 0.96777, 1, 1.20088, 0.89903, 1, 1, 0.75155, 0.94945, 0.94945, 0.94945, 0.94945, 1.12317, 1.12317, 1.12317, 0.67603, 0.67603, 1.15621, 0.73584, 1.21191, 1.22135, 1.06483, 0.94868, 0.94868, 0.95996, 1.24633, 1, 1.07497, 0.87709, 0.96927, 1.01473, 0.96927, 1, 1, 1, 0.77295, 1, 1, 1.09836, 1.09836, 1.09836, 1.01522, 0.86321, 0.94434, 0.8649, 0.94434, 0.86182, 1, 1, 1.083, 1, 0.91578, 0.86438, 1.17308, 1.18416, 1.14589, 0.69825, 0.97622, 1.96791, 1.24822, 1.24822, 1.17308, 1.24822, 1.24822, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.42603, 1, 0.99862, 0.99862, 1, 0.87025, 0.87025, 0.87025, 0.87025, 1.17984, 1.42603, 1, 1.42603, 1.42603, 0.99862, 1, 1, 1, 1, 1, 1.2886, 1.04315, 1.15296, 1.34163, 1, 1, 1, 1.10742, 1.10742, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; -exports.SegoeuiItalicFactors = SegoeuiItalicFactors; -const SegoeuiItalicMetrics = { - lineHeight: 1.33008, - lineGap: 0 -}; -exports.SegoeuiItalicMetrics = SegoeuiItalicMetrics; -const SegoeuiRegularFactors = [1.76738, 1, 1, 0.98594, 1.02285, 1.10454, 1.06234, 0.96927, 0.92037, 1.19985, 1.2046, 0.90616, 0.90616, 1.07152, 1.1714, 0.78032, 1.20088, 0.78032, 1.40246, 0.96927, 0.96927, 0.96927, 0.96927, 0.96927, 0.96927, 0.96927, 0.96927, 0.96927, 0.96927, 0.78032, 0.78032, 1.1714, 1.1714, 1.1714, 0.80597, 0.94084, 0.96706, 0.85944, 0.85734, 0.97093, 0.75842, 0.79936, 0.88198, 0.9831, 0.95782, 0.71387, 0.86969, 0.84636, 1.07796, 1.03584, 0.96924, 0.83968, 0.96924, 0.82826, 0.79649, 0.85771, 0.95132, 0.93119, 0.98965, 0.88433, 0.8287, 0.93365, 1.08612, 1.3638, 1.08612, 1.45786, 0.74627, 0.80499, 0.91484, 1.05707, 0.92383, 1.05882, 0.9403, 1.12654, 1.05882, 1.01756, 1.09011, 1.09011, 0.99414, 1.09011, 1.034, 1.01756, 1.05356, 1.05707, 1.05882, 1.04399, 0.84863, 1.21968, 1.01756, 0.95801, 1.00068, 0.91797, 0.96777, 0.9043, 0.90351, 0.92105, 0.90351, 1.1714, 0.85337, 0.96927, 0.96927, 0.99912, 0.96927, 0.92105, 0.80597, 1.2434, 1.20808, 1.05937, 0.90957, 1.1714, 1.20808, 0.75155, 0.94261, 1.24644, 1.09971, 1.09971, 0.84751, 1, 0.85273, 0.78032, 0.61584, 1.05425, 1.17914, 0.90957, 1.08665, 1.11593, 1.14169, 0.73381, 0.96706, 0.96706, 0.96706, 0.96706, 0.96706, 0.96706, 0.86035, 0.85734, 0.75842, 0.75842, 0.75842, 0.75842, 0.95782, 0.95782, 0.95782, 0.95782, 0.97093, 1.03584, 0.96924, 0.96924, 0.96924, 0.96924, 0.96924, 1.1714, 0.96924, 0.95132, 0.95132, 0.95132, 0.95132, 0.8287, 0.83968, 0.89049, 0.91484, 0.91484, 0.91484, 0.91484, 0.91484, 0.91484, 0.93575, 0.92383, 0.9403, 0.9403, 0.9403, 0.9403, 0.8717, 0.8717, 0.8717, 0.8717, 1.00527, 1.01756, 1.05356, 1.05356, 1.05356, 1.05356, 1.05356, 1.24644, 0.95923, 1.01756, 1.01756, 1.01756, 1.01756, 0.96777, 1.05707, 0.96777, 0.96706, 0.91484, 0.96706, 0.91484, 0.96706, 0.91484, 0.85734, 0.92383, 0.85734, 0.92383, 0.85734, 0.92383, 0.85734, 0.92383, 0.97093, 1.0969, 0.97093, 1.05882, 0.75842, 0.9403, 0.75842, 0.9403, 0.75842, 0.9403, 0.75842, 0.9403, 0.75842, 0.9403, 0.88198, 1.05882, 0.88198, 1.05882, 0.88198, 1.05882, 1, 1, 0.9831, 1.01756, 0.9831, 1.01756, 0.95782, 0.8717, 0.95782, 0.8717, 0.95782, 0.8717, 0.95782, 1.09011, 0.95782, 0.8717, 0.84784, 1.11551, 0.71387, 1.09011, 1, 1, 0.99414, 0.84636, 1.09011, 1, 1, 0.84636, 1.0536, 0.84636, 0.94298, 0.84636, 1.23297, 1.03584, 1.01756, 1, 1, 1.03584, 1.01756, 1.00323, 1.03444, 1.01756, 0.96924, 1.05356, 0.96924, 1.05356, 0.96924, 1.05356, 0.93066, 0.98293, 0.82826, 1.04399, 1, 1, 0.82826, 1.04399, 0.79649, 0.84863, 0.79649, 0.84863, 0.79649, 0.84863, 0.79649, 0.84863, 1, 1, 0.85771, 1.17318, 0.85771, 1.21968, 0.95132, 1.01756, 0.95132, 1.01756, 0.95132, 1.01756, 0.95132, 1.01756, 0.95132, 1.01756, 0.95132, 1.01756, 0.98965, 1.00068, 0.8287, 0.96777, 0.8287, 0.93365, 0.9043, 0.93365, 0.9043, 0.93365, 0.9043, 1.08571, 0.96927, 0.96706, 0.91484, 0.86035, 0.93575, 0.96924, 0.95923, 1, 1, 0.85771, 1.21968, 1.11437, 1.11437, 0.93109, 0.91202, 0.60411, 0.84164, 0.55572, 1.01173, 0.97361, 0.81818, 0.81818, 0.96635, 0.78032, 0.72727, 0.92366, 0.98601, 1.03405, 0.77968, 1.09799, 1.2, 0.96706, 0.85944, 0.85638, 0.96491, 0.75842, 0.93365, 0.9831, 0.96924, 0.95782, 0.86969, 0.94152, 1.07796, 1.03584, 0.78437, 0.96924, 0.98715, 0.83968, 0.83491, 0.85771, 0.8287, 0.94492, 0.88433, 0.9287, 1.0098, 0.95782, 0.8287, 1.0625, 0.98248, 1.03424, 1.2, 1.01071, 1.0625, 0.95246, 1.03809, 1.04912, 0.98248, 1.00221, 1.03424, 1.05443, 1.2, 1.04785, 0.99609, 1.00169, 1.05176, 0.99346, 1.05356, 0.9087, 1.03004, 0.95542, 0.93117, 1.23362, 1.01071, 1.07831, 1.02512, 1.05205, 1.03502, 1.2, 1.01071, 1.05356, 1.01071, 1.03502, 0.75842, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.03719, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.9403, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.04021, 1, 1, 1, 1, 1, 1, 0.98965, 1.00068, 0.98965, 1.00068, 0.98965, 1.00068, 0.8287, 0.96777, 1, 1.20088, 0.89903, 1, 1, 0.75155, 1.03077, 1.03077, 1.03077, 1.03077, 1.13196, 1.13196, 1.13196, 0.67428, 0.67428, 1.16039, 0.73291, 1.20996, 1.22135, 1.06483, 0.94868, 0.94868, 0.95996, 1.24633, 1, 1.07497, 0.87796, 0.96927, 1.01518, 0.96927, 1, 1, 1, 0.77295, 1, 1, 1.10539, 1.10539, 1.11358, 1.06967, 0.86279, 0.94434, 0.86279, 0.94434, 0.86182, 1, 1, 1.083, 1, 0.91578, 0.86507, 1.1714, 1.18416, 1.14589, 0.69825, 0.97622, 1.9697, 1.24822, 1.24822, 1.17238, 1.24822, 1.24822, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.42603, 1, 0.99862, 0.99862, 1, 0.87025, 0.87025, 0.87025, 0.87025, 1.18083, 1.42603, 1, 1.42603, 1.42603, 0.99862, 1, 1, 1, 1, 1, 1.2886, 1.04315, 1.15296, 1.34163, 1, 1, 1, 1.10938, 1.10938, 1, 1, 1, 1.05425, 1.09971, 1.09971, 1.09971, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; -exports.SegoeuiRegularFactors = SegoeuiRegularFactors; -const SegoeuiRegularMetrics = { - lineHeight: 1.33008, - lineGap: 0 -}; -exports.SegoeuiRegularMetrics = SegoeuiRegularMetrics; - -/***/ }), -/* 18 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.SEAC_ANALYSIS_ENABLED = exports.MacStandardGlyphOrdering = exports.FontFlags = void 0; -exports.getFontType = getFontType; -exports.normalizeFontName = normalizeFontName; -exports.recoverGlyphName = recoverGlyphName; -exports.type1FontGlyphMapping = type1FontGlyphMapping; - -var _util = __w_pdfjs_require__(2); - -var _encodings = __w_pdfjs_require__(19); - -var _glyphlist = __w_pdfjs_require__(20); - -var _unicode = __w_pdfjs_require__(21); - -const SEAC_ANALYSIS_ENABLED = true; -exports.SEAC_ANALYSIS_ENABLED = SEAC_ANALYSIS_ENABLED; -const FontFlags = { - FixedPitch: 1, - Serif: 2, - Symbolic: 4, - Script: 8, - Nonsymbolic: 32, - Italic: 64, - AllCap: 65536, - SmallCap: 131072, - ForceBold: 262144 -}; -exports.FontFlags = FontFlags; -const 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"]; -exports.MacStandardGlyphOrdering = MacStandardGlyphOrdering; - -function getFontType(type, subtype, isStandardFont = false) { - switch (type) { - case "Type1": - if (isStandardFont) { - return _util.FontType.TYPE1STANDARD; - } - - return subtype === "Type1C" ? _util.FontType.TYPE1C : _util.FontType.TYPE1; - - case "CIDFontType0": - return subtype === "CIDFontType0C" ? _util.FontType.CIDFONTTYPE0C : _util.FontType.CIDFONTTYPE0; - - case "OpenType": - return _util.FontType.OPENTYPE; - - case "TrueType": - return _util.FontType.TRUETYPE; - - case "CIDFontType2": - return _util.FontType.CIDFONTTYPE2; - - case "MMType1": - return _util.FontType.MMTYPE1; - - case "Type0": - return _util.FontType.TYPE0; - - default: - return _util.FontType.UNKNOWN; - } -} - -function recoverGlyphName(name, glyphsUnicodeMap) { - if (glyphsUnicodeMap[name] !== undefined) { - return name; - } - - const unicode = (0, _unicode.getUnicodeForGlyph)(name, glyphsUnicodeMap); - - if (unicode !== -1) { - for (const key in glyphsUnicodeMap) { - if (glyphsUnicodeMap[key] === unicode) { - return key; - } - } - } - - (0, _util.info)("Unable to recover a standard glyph name for: " + name); - return name; -} - -function type1FontGlyphMapping(properties, builtInEncoding, glyphNames) { - const charCodeToGlyphId = Object.create(null); - let glyphId, charCode, baseEncoding; - const isSymbolicFont = !!(properties.flags & FontFlags.Symbolic); - - if (properties.isInternalFont) { - baseEncoding = builtInEncoding; - - for (charCode = 0; charCode < baseEncoding.length; charCode++) { - glyphId = glyphNames.indexOf(baseEncoding[charCode]); - - if (glyphId >= 0) { - charCodeToGlyphId[charCode] = glyphId; - } else { - charCodeToGlyphId[charCode] = 0; - } - } - } else if (properties.baseEncodingName) { - baseEncoding = (0, _encodings.getEncoding)(properties.baseEncodingName); - - for (charCode = 0; charCode < baseEncoding.length; charCode++) { - glyphId = glyphNames.indexOf(baseEncoding[charCode]); - - if (glyphId >= 0) { - charCodeToGlyphId[charCode] = glyphId; - } else { - charCodeToGlyphId[charCode] = 0; - } - } - } else if (isSymbolicFont) { - for (charCode in builtInEncoding) { - charCodeToGlyphId[charCode] = builtInEncoding[charCode]; - } - } else { - baseEncoding = _encodings.StandardEncoding; - - for (charCode = 0; charCode < baseEncoding.length; charCode++) { - glyphId = glyphNames.indexOf(baseEncoding[charCode]); - - if (glyphId >= 0) { - charCodeToGlyphId[charCode] = glyphId; - } else { - charCodeToGlyphId[charCode] = 0; - } - } - } - - const differences = properties.differences; - let glyphsUnicodeMap; - - if (differences) { - for (charCode in differences) { - const glyphName = differences[charCode]; - glyphId = glyphNames.indexOf(glyphName); - - if (glyphId === -1) { - if (!glyphsUnicodeMap) { - glyphsUnicodeMap = (0, _glyphlist.getGlyphsUnicode)(); - } - - const standardGlyphName = recoverGlyphName(glyphName, glyphsUnicodeMap); - - if (standardGlyphName !== glyphName) { - glyphId = glyphNames.indexOf(standardGlyphName); - } - } - - if (glyphId >= 0) { - charCodeToGlyphId[charCode] = glyphId; - } else { - charCodeToGlyphId[charCode] = 0; - } - } - } - - return charCodeToGlyphId; -} - -function normalizeFontName(name) { - return name.replace(/[,_]/g, "-").replace(/\s/g, ""); -} - -/***/ }), -/* 19 */ -/***/ ((__unused_webpack_module, exports) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.ZapfDingbatsEncoding = exports.WinAnsiEncoding = exports.SymbolSetEncoding = exports.StandardEncoding = exports.MacRomanEncoding = exports.ExpertEncoding = void 0; -exports.getEncoding = getEncoding; -const 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"]; -exports.ExpertEncoding = ExpertEncoding; -const 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", "", "", "", ""]; -const MacRomanEncoding = ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "space", "exclam", "quotedbl", "numbersign", "dollar", "percent", "ampersand", "quotesingle", "parenleft", "parenright", "asterisk", "plus", "comma", "hyphen", "period", "slash", "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "colon", "semicolon", "less", "equal", "greater", "question", "at", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "bracketleft", "backslash", "bracketright", "asciicircum", "underscore", "grave", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "braceleft", "bar", "braceright", "asciitilde", "", "Adieresis", "Aring", "Ccedilla", "Eacute", "Ntilde", "Odieresis", "Udieresis", "aacute", "agrave", "acircumflex", "adieresis", "atilde", "aring", "ccedilla", "eacute", "egrave", "ecircumflex", "edieresis", "iacute", "igrave", "icircumflex", "idieresis", "ntilde", "oacute", "ograve", "ocircumflex", "odieresis", "otilde", "uacute", "ugrave", "ucircumflex", "udieresis", "dagger", "degree", "cent", "sterling", "section", "bullet", "paragraph", "germandbls", "registered", "copyright", "trademark", "acute", "dieresis", "notequal", "AE", "Oslash", "infinity", "plusminus", "lessequal", "greaterequal", "yen", "mu", "partialdiff", "summation", "product", "pi", "integral", "ordfeminine", "ordmasculine", "Omega", "ae", "oslash", "questiondown", "exclamdown", "logicalnot", "radical", "florin", "approxequal", "Delta", "guillemotleft", "guillemotright", "ellipsis", "space", "Agrave", "Atilde", "Otilde", "OE", "oe", "endash", "emdash", "quotedblleft", "quotedblright", "quoteleft", "quoteright", "divide", "lozenge", "ydieresis", "Ydieresis", "fraction", "currency", "guilsinglleft", "guilsinglright", "fi", "fl", "daggerdbl", "periodcentered", "quotesinglbase", "quotedblbase", "perthousand", "Acircumflex", "Ecircumflex", "Aacute", "Edieresis", "Egrave", "Iacute", "Icircumflex", "Idieresis", "Igrave", "Oacute", "Ocircumflex", "apple", "Ograve", "Uacute", "Ucircumflex", "Ugrave", "dotlessi", "circumflex", "tilde", "macron", "breve", "dotaccent", "ring", "cedilla", "hungarumlaut", "ogonek", "caron"]; -exports.MacRomanEncoding = MacRomanEncoding; -const 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", "", "", "", ""]; -exports.StandardEncoding = StandardEncoding; -const WinAnsiEncoding = ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "space", "exclam", "quotedbl", "numbersign", "dollar", "percent", "ampersand", "quotesingle", "parenleft", "parenright", "asterisk", "plus", "comma", "hyphen", "period", "slash", "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "colon", "semicolon", "less", "equal", "greater", "question", "at", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "bracketleft", "backslash", "bracketright", "asciicircum", "underscore", "grave", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "braceleft", "bar", "braceright", "asciitilde", "bullet", "Euro", "bullet", "quotesinglbase", "florin", "quotedblbase", "ellipsis", "dagger", "daggerdbl", "circumflex", "perthousand", "Scaron", "guilsinglleft", "OE", "bullet", "Zcaron", "bullet", "bullet", "quoteleft", "quoteright", "quotedblleft", "quotedblright", "bullet", "endash", "emdash", "tilde", "trademark", "scaron", "guilsinglright", "oe", "bullet", "zcaron", "Ydieresis", "space", "exclamdown", "cent", "sterling", "currency", "yen", "brokenbar", "section", "dieresis", "copyright", "ordfeminine", "guillemotleft", "logicalnot", "hyphen", "registered", "macron", "degree", "plusminus", "twosuperior", "threesuperior", "acute", "mu", "paragraph", "periodcentered", "cedilla", "onesuperior", "ordmasculine", "guillemotright", "onequarter", "onehalf", "threequarters", "questiondown", "Agrave", "Aacute", "Acircumflex", "Atilde", "Adieresis", "Aring", "AE", "Ccedilla", "Egrave", "Eacute", "Ecircumflex", "Edieresis", "Igrave", "Iacute", "Icircumflex", "Idieresis", "Eth", "Ntilde", "Ograve", "Oacute", "Ocircumflex", "Otilde", "Odieresis", "multiply", "Oslash", "Ugrave", "Uacute", "Ucircumflex", "Udieresis", "Yacute", "Thorn", "germandbls", "agrave", "aacute", "acircumflex", "atilde", "adieresis", "aring", "ae", "ccedilla", "egrave", "eacute", "ecircumflex", "edieresis", "igrave", "iacute", "icircumflex", "idieresis", "eth", "ntilde", "ograve", "oacute", "ocircumflex", "otilde", "odieresis", "divide", "oslash", "ugrave", "uacute", "ucircumflex", "udieresis", "yacute", "thorn", "ydieresis"]; -exports.WinAnsiEncoding = WinAnsiEncoding; -const SymbolSetEncoding = ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "space", "exclam", "universal", "numbersign", "existential", "percent", "ampersand", "suchthat", "parenleft", "parenright", "asteriskmath", "plus", "comma", "minus", "period", "slash", "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "colon", "semicolon", "less", "equal", "greater", "question", "congruent", "Alpha", "Beta", "Chi", "Delta", "Epsilon", "Phi", "Gamma", "Eta", "Iota", "theta1", "Kappa", "Lambda", "Mu", "Nu", "Omicron", "Pi", "Theta", "Rho", "Sigma", "Tau", "Upsilon", "sigma1", "Omega", "Xi", "Psi", "Zeta", "bracketleft", "therefore", "bracketright", "perpendicular", "underscore", "radicalex", "alpha", "beta", "chi", "delta", "epsilon", "phi", "gamma", "eta", "iota", "phi1", "kappa", "lambda", "mu", "nu", "omicron", "pi", "theta", "rho", "sigma", "tau", "upsilon", "omega1", "omega", "xi", "psi", "zeta", "braceleft", "bar", "braceright", "similar", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "Euro", "Upsilon1", "minute", "lessequal", "fraction", "infinity", "florin", "club", "diamond", "heart", "spade", "arrowboth", "arrowleft", "arrowup", "arrowright", "arrowdown", "degree", "plusminus", "second", "greaterequal", "multiply", "proportional", "partialdiff", "bullet", "divide", "notequal", "equivalence", "approxequal", "ellipsis", "arrowvertex", "arrowhorizex", "carriagereturn", "aleph", "Ifraktur", "Rfraktur", "weierstrass", "circlemultiply", "circleplus", "emptyset", "intersection", "union", "propersuperset", "reflexsuperset", "notsubset", "propersubset", "reflexsubset", "element", "notelement", "angle", "gradient", "registerserif", "copyrightserif", "trademarkserif", "product", "radical", "dotmath", "logicalnot", "logicaland", "logicalor", "arrowdblboth", "arrowdblleft", "arrowdblup", "arrowdblright", "arrowdbldown", "lozenge", "angleleft", "registersans", "copyrightsans", "trademarksans", "summation", "parenlefttp", "parenleftex", "parenleftbt", "bracketlefttp", "bracketleftex", "bracketleftbt", "bracelefttp", "braceleftmid", "braceleftbt", "braceex", "", "angleright", "integral", "integraltp", "integralex", "integralbt", "parenrighttp", "parenrightex", "parenrightbt", "bracketrighttp", "bracketrightex", "bracketrightbt", "bracerighttp", "bracerightmid", "bracerightbt", ""]; -exports.SymbolSetEncoding = SymbolSetEncoding; -const ZapfDingbatsEncoding = ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "space", "a1", "a2", "a202", "a3", "a4", "a5", "a119", "a118", "a117", "a11", "a12", "a13", "a14", "a15", "a16", "a105", "a17", "a18", "a19", "a20", "a21", "a22", "a23", "a24", "a25", "a26", "a27", "a28", "a6", "a7", "a8", "a9", "a10", "a29", "a30", "a31", "a32", "a33", "a34", "a35", "a36", "a37", "a38", "a39", "a40", "a41", "a42", "a43", "a44", "a45", "a46", "a47", "a48", "a49", "a50", "a51", "a52", "a53", "a54", "a55", "a56", "a57", "a58", "a59", "a60", "a61", "a62", "a63", "a64", "a65", "a66", "a67", "a68", "a69", "a70", "a71", "a72", "a73", "a74", "a203", "a75", "a204", "a76", "a77", "a78", "a79", "a81", "a82", "a83", "a84", "a97", "a98", "a99", "a100", "", "a89", "a90", "a93", "a94", "a91", "a92", "a205", "a85", "a206", "a86", "a87", "a88", "a95", "a96", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "a101", "a102", "a103", "a104", "a106", "a107", "a108", "a112", "a111", "a110", "a109", "a120", "a121", "a122", "a123", "a124", "a125", "a126", "a127", "a128", "a129", "a130", "a131", "a132", "a133", "a134", "a135", "a136", "a137", "a138", "a139", "a140", "a141", "a142", "a143", "a144", "a145", "a146", "a147", "a148", "a149", "a150", "a151", "a152", "a153", "a154", "a155", "a156", "a157", "a158", "a159", "a160", "a161", "a163", "a164", "a196", "a165", "a192", "a166", "a167", "a168", "a169", "a170", "a171", "a172", "a173", "a162", "a174", "a175", "a176", "a177", "a178", "a179", "a193", "a180", "a199", "a181", "a200", "a182", "", "a201", "a183", "a184", "a197", "a185", "a194", "a198", "a186", "a195", "a187", "a188", "a189", "a190", "a191", ""]; -exports.ZapfDingbatsEncoding = ZapfDingbatsEncoding; - -function getEncoding(encodingName) { - switch (encodingName) { - case "WinAnsiEncoding": - return WinAnsiEncoding; - - case "StandardEncoding": - return StandardEncoding; - - case "MacRomanEncoding": - return MacRomanEncoding; - - case "SymbolSetEncoding": - return SymbolSetEncoding; - - case "ZapfDingbatsEncoding": - return ZapfDingbatsEncoding; - - case "ExpertEncoding": - return ExpertEncoding; - - case "MacExpertEncoding": - return MacExpertEncoding; - - default: - return null; - } -} - -/***/ }), -/* 20 */ -/***/ ((__unused_webpack_module, __webpack_exports__, __w_pdfjs_require__) => { - -__w_pdfjs_require__.r(__webpack_exports__); -/* harmony export */ __w_pdfjs_require__.d(__webpack_exports__, { -/* harmony export */ "getDingbatsGlyphsUnicode": () => (/* binding */ getDingbatsGlyphsUnicode), -/* harmony export */ "getGlyphsUnicode": () => (/* binding */ getGlyphsUnicode) -/* harmony export */ }); -/* harmony import */ var _core_utils_js__WEBPACK_IMPORTED_MODULE_0__ = __w_pdfjs_require__(9); - -const getGlyphsUnicode = (0,_core_utils_js__WEBPACK_IMPORTED_MODULE_0__.getArrayLookupTableFactory)(function () { - return [ - "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, - "angbracketright", - 0x3009, - "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, - "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, - "controlNULL", - 0x0000, - "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, - "f_f", - 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, - "angbracketleftbig", - 0x2329, - "angbracketleftBig", - 0x2329, - "angbracketleftbigg", - 0x2329, - "angbracketleftBigg", - 0x2329, - "angbracketrightBig", - 0x232a, - "angbracketrightbig", - 0x232a, - "angbracketrightBigg", - 0x232a, - "angbracketrightbigg", - 0x232a, - "arrowhookleft", - 0x21aa, - "arrowhookright", - 0x21a9, - "arrowlefttophalf", - 0x21bc, - "arrowleftbothalf", - 0x21bd, - "arrownortheast", - 0x2197, - "arrownorthwest", - 0x2196, - "arrowrighttophalf", - 0x21c0, - "arrowrightbothalf", - 0x21c1, - "arrowsoutheast", - 0x2198, - "arrowsouthwest", - 0x2199, - "backslashbig", - 0x2216, - "backslashBig", - 0x2216, - "backslashBigg", - 0x2216, - "backslashbigg", - 0x2216, - "bardbl", - 0x2016, - "bracehtipdownleft", - 0xfe37, - "bracehtipdownright", - 0xfe37, - "bracehtipupleft", - 0xfe38, - "bracehtipupright", - 0xfe38, - "braceleftBig", - 0x007b, - "braceleftbig", - 0x007b, - "braceleftbigg", - 0x007b, - "braceleftBigg", - 0x007b, - "bracerightBig", - 0x007d, - "bracerightbig", - 0x007d, - "bracerightbigg", - 0x007d, - "bracerightBigg", - 0x007d, - "bracketleftbig", - 0x005b, - "bracketleftBig", - 0x005b, - "bracketleftbigg", - 0x005b, - "bracketleftBigg", - 0x005b, - "bracketrightBig", - 0x005d, - "bracketrightbig", - 0x005d, - "bracketrightbigg", - 0x005d, - "bracketrightBigg", - 0x005d, - "ceilingleftbig", - 0x2308, - "ceilingleftBig", - 0x2308, - "ceilingleftBigg", - 0x2308, - "ceilingleftbigg", - 0x2308, - "ceilingrightbig", - 0x2309, - "ceilingrightBig", - 0x2309, - "ceilingrightbigg", - 0x2309, - "ceilingrightBigg", - 0x2309, - "circledotdisplay", - 0x2299, - "circledottext", - 0x2299, - "circlemultiplydisplay", - 0x2297, - "circlemultiplytext", - 0x2297, - "circleplusdisplay", - 0x2295, - "circleplustext", - 0x2295, - "contintegraldisplay", - 0x222e, - "contintegraltext", - 0x222e, - "coproductdisplay", - 0x2210, - "coproducttext", - 0x2210, - "floorleftBig", - 0x230a, - "floorleftbig", - 0x230a, - "floorleftbigg", - 0x230a, - "floorleftBigg", - 0x230a, - "floorrightbig", - 0x230b, - "floorrightBig", - 0x230b, - "floorrightBigg", - 0x230b, - "floorrightbigg", - 0x230b, - "hatwide", - 0x0302, - "hatwider", - 0x0302, - "hatwidest", - 0x0302, - "intercal", - 0x1d40, - "integraldisplay", - 0x222b, - "integraltext", - 0x222b, - "intersectiondisplay", - 0x22c2, - "intersectiontext", - 0x22c2, - "logicalanddisplay", - 0x2227, - "logicalandtext", - 0x2227, - "logicalordisplay", - 0x2228, - "logicalortext", - 0x2228, - "parenleftBig", - 0x0028, - "parenleftbig", - 0x0028, - "parenleftBigg", - 0x0028, - "parenleftbigg", - 0x0028, - "parenrightBig", - 0x0029, - "parenrightbig", - 0x0029, - "parenrightBigg", - 0x0029, - "parenrightbigg", - 0x0029, - "prime", - 0x2032, - "productdisplay", - 0x220f, - "producttext", - 0x220f, - "radicalbig", - 0x221a, - "radicalBig", - 0x221a, - "radicalBigg", - 0x221a, - "radicalbigg", - 0x221a, - "radicalbt", - 0x221a, - "radicaltp", - 0x221a, - "radicalvertex", - 0x221a, - "slashbig", - 0x002f, - "slashBig", - 0x002f, - "slashBigg", - 0x002f, - "slashbigg", - 0x002f, - "summationdisplay", - 0x2211, - "summationtext", - 0x2211, - "tildewide", - 0x02dc, - "tildewider", - 0x02dc, - "tildewidest", - 0x02dc, - "uniondisplay", - 0x22c3, - "unionmultidisplay", - 0x228e, - "unionmultitext", - 0x228e, - "unionsqdisplay", - 0x2294, - "unionsqtext", - 0x2294, - "uniontext", - 0x22c3, - "vextenddouble", - 0x2225, - "vextendsingle", - 0x2223 - ]; -}); -const getDingbatsGlyphsUnicode = (0,_core_utils_js__WEBPACK_IMPORTED_MODULE_0__.getArrayLookupTableFactory)(function () { - return [ - "space", - 0x0020, - "a1", - 0x2701, - "a2", - 0x2702, - "a202", - 0x2703, - "a3", - 0x2704, - "a4", - 0x260e, - "a5", - 0x2706, - "a119", - 0x2707, - "a118", - 0x2708, - "a117", - 0x2709, - "a11", - 0x261b, - "a12", - 0x261e, - "a13", - 0x270c, - "a14", - 0x270d, - "a15", - 0x270e, - "a16", - 0x270f, - "a105", - 0x2710, - "a17", - 0x2711, - "a18", - 0x2712, - "a19", - 0x2713, - "a20", - 0x2714, - "a21", - 0x2715, - "a22", - 0x2716, - "a23", - 0x2717, - "a24", - 0x2718, - "a25", - 0x2719, - "a26", - 0x271a, - "a27", - 0x271b, - "a28", - 0x271c, - "a6", - 0x271d, - "a7", - 0x271e, - "a8", - 0x271f, - "a9", - 0x2720, - "a10", - 0x2721, - "a29", - 0x2722, - "a30", - 0x2723, - "a31", - 0x2724, - "a32", - 0x2725, - "a33", - 0x2726, - "a34", - 0x2727, - "a35", - 0x2605, - "a36", - 0x2729, - "a37", - 0x272a, - "a38", - 0x272b, - "a39", - 0x272c, - "a40", - 0x272d, - "a41", - 0x272e, - "a42", - 0x272f, - "a43", - 0x2730, - "a44", - 0x2731, - "a45", - 0x2732, - "a46", - 0x2733, - "a47", - 0x2734, - "a48", - 0x2735, - "a49", - 0x2736, - "a50", - 0x2737, - "a51", - 0x2738, - "a52", - 0x2739, - "a53", - 0x273a, - "a54", - 0x273b, - "a55", - 0x273c, - "a56", - 0x273d, - "a57", - 0x273e, - "a58", - 0x273f, - "a59", - 0x2740, - "a60", - 0x2741, - "a61", - 0x2742, - "a62", - 0x2743, - "a63", - 0x2744, - "a64", - 0x2745, - "a65", - 0x2746, - "a66", - 0x2747, - "a67", - 0x2748, - "a68", - 0x2749, - "a69", - 0x274a, - "a70", - 0x274b, - "a71", - 0x25cf, - "a72", - 0x274d, - "a73", - 0x25a0, - "a74", - 0x274f, - "a203", - 0x2750, - "a75", - 0x2751, - "a204", - 0x2752, - "a76", - 0x25b2, - "a77", - 0x25bc, - "a78", - 0x25c6, - "a79", - 0x2756, - "a81", - 0x25d7, - "a82", - 0x2758, - "a83", - 0x2759, - "a84", - 0x275a, - "a97", - 0x275b, - "a98", - 0x275c, - "a99", - 0x275d, - "a100", - 0x275e, - "a101", - 0x2761, - "a102", - 0x2762, - "a103", - 0x2763, - "a104", - 0x2764, - "a106", - 0x2765, - "a107", - 0x2766, - "a108", - 0x2767, - "a112", - 0x2663, - "a111", - 0x2666, - "a110", - 0x2665, - "a109", - 0x2660, - "a120", - 0x2460, - "a121", - 0x2461, - "a122", - 0x2462, - "a123", - 0x2463, - "a124", - 0x2464, - "a125", - 0x2465, - "a126", - 0x2466, - "a127", - 0x2467, - "a128", - 0x2468, - "a129", - 0x2469, - "a130", - 0x2776, - "a131", - 0x2777, - "a132", - 0x2778, - "a133", - 0x2779, - "a134", - 0x277a, - "a135", - 0x277b, - "a136", - 0x277c, - "a137", - 0x277d, - "a138", - 0x277e, - "a139", - 0x277f, - "a140", - 0x2780, - "a141", - 0x2781, - "a142", - 0x2782, - "a143", - 0x2783, - "a144", - 0x2784, - "a145", - 0x2785, - "a146", - 0x2786, - "a147", - 0x2787, - "a148", - 0x2788, - "a149", - 0x2789, - "a150", - 0x278a, - "a151", - 0x278b, - "a152", - 0x278c, - "a153", - 0x278d, - "a154", - 0x278e, - "a155", - 0x278f, - "a156", - 0x2790, - "a157", - 0x2791, - "a158", - 0x2792, - "a159", - 0x2793, - "a160", - 0x2794, - "a161", - 0x2192, - "a163", - 0x2194, - "a164", - 0x2195, - "a196", - 0x2798, - "a165", - 0x2799, - "a192", - 0x279a, - "a166", - 0x279b, - "a167", - 0x279c, - "a168", - 0x279d, - "a169", - 0x279e, - "a170", - 0x279f, - "a171", - 0x27a0, - "a172", - 0x27a1, - "a173", - 0x27a2, - "a162", - 0x27a3, - "a174", - 0x27a4, - "a175", - 0x27a5, - "a176", - 0x27a6, - "a177", - 0x27a7, - "a178", - 0x27a8, - "a179", - 0x27a9, - "a193", - 0x27aa, - "a180", - 0x27ab, - "a199", - 0x27ac, - "a181", - 0x27ad, - "a200", - 0x27ae, - "a182", - 0x27af, - "a201", - 0x27b1, - "a183", - 0x27b2, - "a184", - 0x27b3, - "a197", - 0x27b4, - "a185", - 0x27b5, - "a194", - 0x27b6, - "a198", - 0x27b7, - "a186", - 0x27b8, - "a195", - 0x27b9, - "a187", - 0x27ba, - "a188", - 0x27bb, - "a189", - 0x27bc, - "a190", - 0x27bd, - "a191", - 0x27be, - "a89", - 0x2768, - "a90", - 0x2769, - "a93", - 0x276a, - "a94", - 0x276b, - "a91", - 0x276c, - "a92", - 0x276d, - "a205", - 0x276e, - "a85", - 0x276f, - "a206", - 0x2770, - "a86", - 0x2771, - "a87", - 0x2772, - "a88", - 0x2773, - "a95", - 0x2774, - "a96", - 0x2775, - ".notdef", - 0x0000 - ]; -}); - - -/***/ }), -/* 21 */ -/***/ ((__unused_webpack_module, __webpack_exports__, __w_pdfjs_require__) => { - -__w_pdfjs_require__.r(__webpack_exports__); -/* harmony export */ __w_pdfjs_require__.d(__webpack_exports__, { -/* harmony export */ "getNormalizedUnicodes": () => (/* binding */ getNormalizedUnicodes), -/* harmony export */ "getUnicodeForGlyph": () => (/* binding */ getUnicodeForGlyph), -/* harmony export */ "getUnicodeRangeFor": () => (/* binding */ getUnicodeRangeFor), -/* harmony export */ "mapSpecialUnicodeValues": () => (/* binding */ mapSpecialUnicodeValues), -/* harmony export */ "reverseIfRtl": () => (/* binding */ reverseIfRtl) -/* harmony export */ }); -/* harmony import */ var _core_utils_js__WEBPACK_IMPORTED_MODULE_0__ = __w_pdfjs_require__(9); - -const getSpecialPUASymbols = (0,_core_utils_js__WEBPACK_IMPORTED_MODULE_0__.getLookupTableFactory)(function (t) { - t[63721] = 0x00a9; - t[63193] = 0x00a9; - t[63720] = 0x00ae; - t[63194] = 0x00ae; - t[63722] = 0x2122; - t[63195] = 0x2122; - t[63729] = 0x23a7; - t[63730] = 0x23a8; - t[63731] = 0x23a9; - t[63740] = 0x23ab; - t[63741] = 0x23ac; - t[63742] = 0x23ad; - t[63726] = 0x23a1; - t[63727] = 0x23a2; - t[63728] = 0x23a3; - t[63737] = 0x23a4; - t[63738] = 0x23a5; - t[63739] = 0x23a6; - t[63723] = 0x239b; - t[63724] = 0x239c; - t[63725] = 0x239d; - t[63734] = 0x239e; - t[63735] = 0x239f; - t[63736] = 0x23a0; -}); -function mapSpecialUnicodeValues(code) { - if (code >= 0xfff0 && code <= 0xffff) { - return 0; - } else if (code >= 0xf600 && code <= 0xf8ff) { - return getSpecialPUASymbols()[code] || code; - } else if (code === 0x00ad) { - return 0x002d; - } - return code; -} -function getUnicodeForGlyph(name, glyphsUnicodeMap) { - let unicode = glyphsUnicodeMap[name]; - if (unicode !== undefined) { - return unicode; - } - if (!name) { - return -1; - } - if (name[0] === "u") { - const nameLen = name.length; - let hexStr; - if (nameLen === 7 && name[1] === "n" && name[2] === "i") { - hexStr = name.substring(3); - } else if (nameLen >= 5 && nameLen <= 7) { - hexStr = name.substring(1); - } else { - return -1; - } - if (hexStr === hexStr.toUpperCase()) { - unicode = parseInt(hexStr, 16); - if (unicode >= 0) { - return unicode; - } - } - } - return -1; -} -const UnicodeRanges = [ - { - begin: 0x0000, - end: 0x007f - }, - { - begin: 0x0080, - end: 0x00ff - }, - { - begin: 0x0100, - end: 0x017f - }, - { - begin: 0x0180, - end: 0x024f - }, - { - begin: 0x0250, - end: 0x02af - }, - { - begin: 0x02b0, - end: 0x02ff - }, - { - begin: 0x0300, - end: 0x036f - }, - { - begin: 0x0370, - end: 0x03ff - }, - { - begin: 0x2c80, - end: 0x2cff - }, - { - begin: 0x0400, - end: 0x04ff - }, - { - begin: 0x0530, - end: 0x058f - }, - { - begin: 0x0590, - end: 0x05ff - }, - { - begin: 0xa500, - end: 0xa63f - }, - { - begin: 0x0600, - end: 0x06ff - }, - { - begin: 0x07c0, - end: 0x07ff - }, - { - begin: 0x0900, - end: 0x097f - }, - { - begin: 0x0980, - end: 0x09ff - }, - { - begin: 0x0a00, - end: 0x0a7f - }, - { - begin: 0x0a80, - end: 0x0aff - }, - { - begin: 0x0b00, - end: 0x0b7f - }, - { - begin: 0x0b80, - end: 0x0bff - }, - { - begin: 0x0c00, - end: 0x0c7f - }, - { - begin: 0x0c80, - end: 0x0cff - }, - { - begin: 0x0d00, - end: 0x0d7f - }, - { - begin: 0x0e00, - end: 0x0e7f - }, - { - begin: 0x0e80, - end: 0x0eff - }, - { - begin: 0x10a0, - end: 0x10ff - }, - { - begin: 0x1b00, - end: 0x1b7f - }, - { - begin: 0x1100, - end: 0x11ff - }, - { - begin: 0x1e00, - end: 0x1eff - }, - { - begin: 0x1f00, - end: 0x1fff - }, - { - begin: 0x2000, - end: 0x206f - }, - { - begin: 0x2070, - end: 0x209f - }, - { - begin: 0x20a0, - end: 0x20cf - }, - { - begin: 0x20d0, - end: 0x20ff - }, - { - begin: 0x2100, - end: 0x214f - }, - { - begin: 0x2150, - end: 0x218f - }, - { - begin: 0x2190, - end: 0x21ff - }, - { - begin: 0x2200, - end: 0x22ff - }, - { - begin: 0x2300, - end: 0x23ff - }, - { - begin: 0x2400, - end: 0x243f - }, - { - begin: 0x2440, - end: 0x245f - }, - { - begin: 0x2460, - end: 0x24ff - }, - { - begin: 0x2500, - end: 0x257f - }, - { - begin: 0x2580, - end: 0x259f - }, - { - begin: 0x25a0, - end: 0x25ff - }, - { - begin: 0x2600, - end: 0x26ff - }, - { - begin: 0x2700, - end: 0x27bf - }, - { - begin: 0x3000, - end: 0x303f - }, - { - begin: 0x3040, - end: 0x309f - }, - { - begin: 0x30a0, - end: 0x30ff - }, - { - begin: 0x3100, - end: 0x312f - }, - { - begin: 0x3130, - end: 0x318f - }, - { - begin: 0xa840, - end: 0xa87f - }, - { - begin: 0x3200, - end: 0x32ff - }, - { - begin: 0x3300, - end: 0x33ff - }, - { - begin: 0xac00, - end: 0xd7af - }, - { - begin: 0xd800, - end: 0xdfff - }, - { - begin: 0x10900, - end: 0x1091f - }, - { - begin: 0x4e00, - end: 0x9fff - }, - { - begin: 0xe000, - end: 0xf8ff - }, - { - begin: 0x31c0, - end: 0x31ef - }, - { - begin: 0xfb00, - end: 0xfb4f - }, - { - begin: 0xfb50, - end: 0xfdff - }, - { - begin: 0xfe20, - end: 0xfe2f - }, - { - begin: 0xfe10, - end: 0xfe1f - }, - { - begin: 0xfe50, - end: 0xfe6f - }, - { - begin: 0xfe70, - end: 0xfeff - }, - { - begin: 0xff00, - end: 0xffef - }, - { - begin: 0xfff0, - end: 0xffff - }, - { - begin: 0x0f00, - end: 0x0fff - }, - { - begin: 0x0700, - end: 0x074f - }, - { - begin: 0x0780, - end: 0x07bf - }, - { - begin: 0x0d80, - end: 0x0dff - }, - { - begin: 0x1000, - end: 0x109f - }, - { - begin: 0x1200, - end: 0x137f - }, - { - begin: 0x13a0, - end: 0x13ff - }, - { - begin: 0x1400, - end: 0x167f - }, - { - begin: 0x1680, - end: 0x169f - }, - { - begin: 0x16a0, - end: 0x16ff - }, - { - begin: 0x1780, - end: 0x17ff - }, - { - begin: 0x1800, - end: 0x18af - }, - { - begin: 0x2800, - end: 0x28ff - }, - { - begin: 0xa000, - end: 0xa48f - }, - { - begin: 0x1700, - end: 0x171f - }, - { - begin: 0x10300, - end: 0x1032f - }, - { - begin: 0x10330, - end: 0x1034f - }, - { - begin: 0x10400, - end: 0x1044f - }, - { - begin: 0x1d000, - end: 0x1d0ff - }, - { - begin: 0x1d400, - end: 0x1d7ff - }, - { - begin: 0xff000, - end: 0xffffd - }, - { - begin: 0xfe00, - end: 0xfe0f - }, - { - begin: 0xe0000, - end: 0xe007f - }, - { - begin: 0x1900, - end: 0x194f - }, - { - begin: 0x1950, - end: 0x197f - }, - { - begin: 0x1980, - end: 0x19df - }, - { - begin: 0x1a00, - end: 0x1a1f - }, - { - begin: 0x2c00, - end: 0x2c5f - }, - { - begin: 0x2d30, - end: 0x2d7f - }, - { - begin: 0x4dc0, - end: 0x4dff - }, - { - begin: 0xa800, - end: 0xa82f - }, - { - begin: 0x10000, - end: 0x1007f - }, - { - begin: 0x10140, - end: 0x1018f - }, - { - begin: 0x10380, - end: 0x1039f - }, - { - begin: 0x103a0, - end: 0x103df - }, - { - begin: 0x10450, - end: 0x1047f - }, - { - begin: 0x10480, - end: 0x104af - }, - { - begin: 0x10800, - end: 0x1083f - }, - { - begin: 0x10a00, - end: 0x10a5f - }, - { - begin: 0x1d300, - end: 0x1d35f - }, - { - begin: 0x12000, - end: 0x123ff - }, - { - begin: 0x1d360, - end: 0x1d37f - }, - { - begin: 0x1b80, - end: 0x1bbf - }, - { - begin: 0x1c00, - end: 0x1c4f - }, - { - begin: 0x1c50, - end: 0x1c7f - }, - { - begin: 0xa880, - end: 0xa8df - }, - { - begin: 0xa900, - end: 0xa92f - }, - { - begin: 0xa930, - end: 0xa95f - }, - { - begin: 0xaa00, - end: 0xaa5f - }, - { - begin: 0x10190, - end: 0x101cf - }, - { - begin: 0x101d0, - end: 0x101ff - }, - { - begin: 0x102a0, - end: 0x102df - }, - { - begin: 0x1f030, - end: 0x1f09f - } -]; -function getUnicodeRangeFor(value) { - for (let i = 0, ii = UnicodeRanges.length; i < ii; i++) { - const range = UnicodeRanges[i]; - if (value >= range.begin && value < range.end) { - return i; - } - } - return -1; -} -function isRTLRangeFor(value) { - let 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; -} -const getNormalizedUnicodes = (0,_core_utils_js__WEBPACK_IMPORTED_MODULE_0__.getArrayLookupTableFactory)(function () { - return [ - "\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) { - const charsLength = chars.length; - if (charsLength <= 1 || !isRTLRangeFor(chars.charCodeAt(0))) { - return chars; - } - const buf = []; - for (let ii = charsLength - 1; ii >= 0; ii--) { - buf.push(chars[ii]); - } - return buf.join(""); -} - - -/***/ }), -/* 22 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.MarkupAnnotation = exports.AnnotationFactory = exports.AnnotationBorderStyle = exports.Annotation = void 0; -exports.getQuadPoints = getQuadPoints; - -var _util = __w_pdfjs_require__(2); - -var _core_utils = __w_pdfjs_require__(9); - -var _default_appearance = __w_pdfjs_require__(23); - -var _primitives = __w_pdfjs_require__(5); - -var _bidi = __w_pdfjs_require__(59); - -var _catalog = __w_pdfjs_require__(64); - -var _colorspace = __w_pdfjs_require__(24); - -var _file_spec = __w_pdfjs_require__(66); - -var _object_loader = __w_pdfjs_require__(70); - -var _operator_list = __w_pdfjs_require__(62); - -var _stream = __w_pdfjs_require__(10); - -var _writer = __w_pdfjs_require__(71); - -var _factory = __w_pdfjs_require__(74); - -class AnnotationFactory { - static create(xref, ref, pdfManager, idFactory, collectFields) { - return Promise.all([pdfManager.ensureCatalog("acroForm"), collectFields ? this._getPageIndex(xref, ref, pdfManager) : -1]).then(([acroForm, pageIndex]) => pdfManager.ensure(this, "_create", [xref, ref, pdfManager, idFactory, acroForm, collectFields, pageIndex])); - } - - static _create(xref, ref, pdfManager, idFactory, acroForm, collectFields, pageIndex = -1) { - const dict = xref.fetchIfRef(ref); - - if (!(0, _primitives.isDict)(dict)) { - return undefined; - } - - const id = (0, _primitives.isRef)(ref) ? ref.toString() : `annot_${idFactory.createObjId()}`; - let subtype = dict.get("Subtype"); - subtype = (0, _primitives.isName)(subtype) ? subtype.name : null; - const parameters = { - xref, - ref, - dict, - subtype, - id, - pdfManager, - acroForm: acroForm instanceof _primitives.Dict ? acroForm : _primitives.Dict.empty, - collectFields, - pageIndex - }; - - switch (subtype) { - case "Link": - return new LinkAnnotation(parameters); - - case "Text": - return new TextAnnotation(parameters); - - case "Widget": - let fieldType = (0, _core_utils.getInheritableProperty)({ - dict, - key: "FT" - }); - fieldType = (0, _primitives.isName)(fieldType) ? fieldType.name : null; - - switch (fieldType) { - case "Tx": - return new TextWidgetAnnotation(parameters); - - case "Btn": - return new ButtonWidgetAnnotation(parameters); - - case "Ch": - return new ChoiceWidgetAnnotation(parameters); - - case "Sig": - return new SignatureWidgetAnnotation(parameters); - } - - (0, _util.warn)(`Unimplemented widget field type "${fieldType}", ` + "falling back to base field type."); - return new WidgetAnnotation(parameters); - - case "Popup": - return new PopupAnnotation(parameters); - - case "FreeText": - return new FreeTextAnnotation(parameters); - - case "Line": - return new LineAnnotation(parameters); - - case "Square": - return new SquareAnnotation(parameters); - - case "Circle": - return new CircleAnnotation(parameters); - - case "PolyLine": - return new PolylineAnnotation(parameters); - - case "Polygon": - return new PolygonAnnotation(parameters); - - case "Caret": - return new CaretAnnotation(parameters); - - case "Ink": - return new InkAnnotation(parameters); - - case "Highlight": - return new HighlightAnnotation(parameters); - - case "Underline": - return new UnderlineAnnotation(parameters); - - case "Squiggly": - return new SquigglyAnnotation(parameters); - - case "StrikeOut": - return new StrikeOutAnnotation(parameters); - - case "Stamp": - return new StampAnnotation(parameters); - - case "FileAttachment": - return new FileAttachmentAnnotation(parameters); - - default: - if (!collectFields) { - if (!subtype) { - (0, _util.warn)("Annotation is missing the required /Subtype."); - } else { - (0, _util.warn)(`Unimplemented annotation type "${subtype}", ` + "falling back to base annotation."); - } - } - - return new Annotation(parameters); - } - } - - static async _getPageIndex(xref, ref, pdfManager) { - try { - const annotDict = await xref.fetchIfRefAsync(ref); - - if (!(0, _primitives.isDict)(annotDict)) { - return -1; - } - - const pageRef = annotDict.getRaw("P"); - - if (!(0, _primitives.isRef)(pageRef)) { - return -1; - } - - const pageIndex = await pdfManager.ensureCatalog("getPageIndex", [pageRef]); - return pageIndex; - } catch (ex) { - (0, _util.warn)(`_getPageIndex: "${ex}".`); - return -1; - } - } - -} - -exports.AnnotationFactory = AnnotationFactory; - -function getRgbColor(color, defaultColor = new Uint8ClampedArray(3)) { - if (!Array.isArray(color)) { - return defaultColor; - } - - const rgbColor = defaultColor || new Uint8ClampedArray(3); - - switch (color.length) { - case 0: - return null; - - case 1: - _colorspace.ColorSpace.singletons.gray.getRgbItem(color, 0, rgbColor, 0); - - return rgbColor; - - case 3: - _colorspace.ColorSpace.singletons.rgb.getRgbItem(color, 0, rgbColor, 0); - - return rgbColor; - - case 4: - _colorspace.ColorSpace.singletons.cmyk.getRgbItem(color, 0, rgbColor, 0); - - return rgbColor; - - default: - return defaultColor; - } -} - -function getQuadPoints(dict, rect) { - if (!dict.has("QuadPoints")) { - return null; - } - - const quadPoints = dict.getArray("QuadPoints"); - - if (!Array.isArray(quadPoints) || quadPoints.length === 0 || quadPoints.length % 8 > 0) { - return null; - } - - const quadPointsLists = []; - - for (let i = 0, ii = quadPoints.length / 8; i < ii; i++) { - quadPointsLists.push([]); - - for (let j = i * 8, jj = i * 8 + 8; j < jj; j += 2) { - const x = quadPoints[j]; - const y = quadPoints[j + 1]; - - if (rect !== null && (x < rect[0] || x > rect[2] || y < rect[1] || y > rect[3])) { - return null; - } - - quadPointsLists[i].push({ - x, - y - }); - } - } - - return quadPointsLists.map(quadPointsList => { - const [minX, maxX, minY, maxY] = quadPointsList.reduce(([mX, MX, mY, MY], quadPoint) => [Math.min(mX, quadPoint.x), Math.max(MX, quadPoint.x), Math.min(mY, quadPoint.y), Math.max(MY, quadPoint.y)], [Number.MAX_VALUE, Number.MIN_VALUE, Number.MAX_VALUE, Number.MIN_VALUE]); - return [{ - x: minX, - y: maxY - }, { - x: maxX, - y: maxY - }, { - x: minX, - y: minY - }, { - x: maxX, - y: minY - }]; - }); -} - -function getTransformMatrix(rect, bbox, matrix) { - const [minX, minY, maxX, maxY] = _util.Util.getAxialAlignedBoundingBox(bbox, matrix); - - if (minX === maxX || minY === maxY) { - return [1, 0, 0, 1, rect[0], rect[1]]; - } - - const xRatio = (rect[2] - rect[0]) / (maxX - minX); - const yRatio = (rect[3] - rect[1]) / (maxY - minY); - return [xRatio, 0, 0, yRatio, rect[0] - minX * xRatio, rect[1] - minY * yRatio]; -} - -class Annotation { - constructor(params) { - const dict = params.dict; - this.setTitle(dict.get("T")); - this.setContents(dict.get("Contents")); - this.setModificationDate(dict.get("M")); - this.setFlags(dict.get("F")); - this.setRectangle(dict.getArray("Rect")); - this.setColor(dict.getArray("C")); - this.setBorderStyle(dict); - this.setAppearance(dict); - this.setBorderAndBackgroundColors(dict.get("MK")); - this._streams = []; - - if (this.appearance) { - this._streams.push(this.appearance); - } - - this.data = { - annotationFlags: this.flags, - borderStyle: this.borderStyle, - color: this.color, - backgroundColor: this.backgroundColor, - borderColor: this.borderColor, - contentsObj: this._contents, - hasAppearance: !!this.appearance, - id: params.id, - modificationDate: this.modificationDate, - rect: this.rectangle, - subtype: params.subtype, - hasOwnCanvas: false - }; - - if (params.collectFields) { - const kids = dict.get("Kids"); - - if (Array.isArray(kids)) { - const kidIds = []; - - for (const kid of kids) { - if ((0, _primitives.isRef)(kid)) { - kidIds.push(kid.toString()); - } - } - - if (kidIds.length !== 0) { - this.data.kidIds = kidIds; - } - } - - this.data.actions = (0, _core_utils.collectActions)(params.xref, dict, _util.AnnotationActionEventType); - this.data.fieldName = this._constructFieldName(dict); - this.data.pageIndex = params.pageIndex; - } - - this._fallbackFontDict = null; - } - - _hasFlag(flags, flag) { - return !!(flags & flag); - } - - _isViewable(flags) { - return !this._hasFlag(flags, _util.AnnotationFlag.INVISIBLE) && !this._hasFlag(flags, _util.AnnotationFlag.NOVIEW); - } - - _isPrintable(flags) { - return this._hasFlag(flags, _util.AnnotationFlag.PRINT) && !this._hasFlag(flags, _util.AnnotationFlag.INVISIBLE); - } - - mustBeViewed(annotationStorage) { - const storageEntry = annotationStorage && annotationStorage.get(this.data.id); - - if (storageEntry && storageEntry.hidden !== undefined) { - return !storageEntry.hidden; - } - - return this.viewable && !this._hasFlag(this.flags, _util.AnnotationFlag.HIDDEN); - } - - mustBePrinted(annotationStorage) { - const storageEntry = annotationStorage && annotationStorage.get(this.data.id); - - if (storageEntry && storageEntry.print !== undefined) { - return storageEntry.print; - } - - return this.printable; - } - - get viewable() { - if (this.data.quadPoints === null) { - return false; - } - - if (this.flags === 0) { - return true; - } - - return this._isViewable(this.flags); - } - - get printable() { - if (this.data.quadPoints === null) { - return false; - } - - if (this.flags === 0) { - return false; - } - - return this._isPrintable(this.flags); - } - - _parseStringHelper(data) { - const str = typeof data === "string" ? (0, _util.stringToPDFString)(data) : ""; - const dir = str && (0, _bidi.bidi)(str).dir === "rtl" ? "rtl" : "ltr"; - return { - str, - dir - }; - } - - setTitle(title) { - this._title = this._parseStringHelper(title); - } - - setContents(contents) { - this._contents = this._parseStringHelper(contents); - } - - setModificationDate(modificationDate) { - this.modificationDate = (0, _util.isString)(modificationDate) ? modificationDate : null; - } - - setFlags(flags) { - this.flags = Number.isInteger(flags) && flags > 0 ? flags : 0; - } - - hasFlag(flag) { - return this._hasFlag(this.flags, flag); - } - - setRectangle(rectangle) { - if (Array.isArray(rectangle) && rectangle.length === 4) { - this.rectangle = _util.Util.normalizeRect(rectangle); - } else { - this.rectangle = [0, 0, 0, 0]; - } - } - - setColor(color) { - this.color = getRgbColor(color); - } - - setBorderAndBackgroundColors(mk) { - if (mk instanceof _primitives.Dict) { - this.borderColor = getRgbColor(mk.getArray("BC"), null); - this.backgroundColor = getRgbColor(mk.getArray("BG"), null); - } else { - this.borderColor = this.backgroundColor = null; - } - } - - setBorderStyle(borderStyle) { - this.borderStyle = new AnnotationBorderStyle(); - - if (!(0, _primitives.isDict)(borderStyle)) { - return; - } - - if (borderStyle.has("BS")) { - const dict = borderStyle.get("BS"); - const dictType = dict.get("Type"); - - if (!dictType || (0, _primitives.isName)(dictType, "Border")) { - this.borderStyle.setWidth(dict.get("W"), this.rectangle); - this.borderStyle.setStyle(dict.get("S")); - this.borderStyle.setDashArray(dict.getArray("D")); - } - } else if (borderStyle.has("Border")) { - const array = borderStyle.getArray("Border"); - - if (Array.isArray(array) && array.length >= 3) { - this.borderStyle.setHorizontalCornerRadius(array[0]); - this.borderStyle.setVerticalCornerRadius(array[1]); - this.borderStyle.setWidth(array[2], this.rectangle); - - if (array.length === 4) { - this.borderStyle.setDashArray(array[3], true); - } - } - } else { - this.borderStyle.setWidth(0); - } - } - - setAppearance(dict) { - this.appearance = null; - const appearanceStates = dict.get("AP"); - - if (!(0, _primitives.isDict)(appearanceStates)) { - return; - } - - const normalAppearanceState = appearanceStates.get("N"); - - if ((0, _primitives.isStream)(normalAppearanceState)) { - this.appearance = normalAppearanceState; - return; - } - - if (!(0, _primitives.isDict)(normalAppearanceState)) { - return; - } - - const as = dict.get("AS"); - - if (!(0, _primitives.isName)(as) || !normalAppearanceState.has(as.name)) { - return; - } - - this.appearance = normalAppearanceState.get(as.name); - } - - loadResources(keys, appearance) { - return appearance.dict.getAsync("Resources").then(resources => { - if (!resources) { - return undefined; - } - - const objectLoader = new _object_loader.ObjectLoader(resources, keys, resources.xref); - return objectLoader.load().then(function () { - return resources; - }); - }); - } - - getOperatorList(evaluator, task, intent, renderForms, annotationStorage) { - const data = this.data; - let appearance = this.appearance; - const isUsingOwnCanvas = data.hasOwnCanvas && intent & _util.RenderingIntentFlag.DISPLAY; - - if (!appearance) { - if (!isUsingOwnCanvas) { - return Promise.resolve(new _operator_list.OperatorList()); - } - - appearance = new _stream.StringStream(""); - appearance.dict = new _primitives.Dict(); - } - - const appearanceDict = appearance.dict; - const resourcesPromise = this.loadResources(["ExtGState", "ColorSpace", "Pattern", "Shading", "XObject", "Font"], appearance); - const bbox = appearanceDict.getArray("BBox") || [0, 0, 1, 1]; - const matrix = appearanceDict.getArray("Matrix") || [1, 0, 0, 1, 0, 0]; - const transform = getTransformMatrix(data.rect, bbox, matrix); - return resourcesPromise.then(resources => { - const opList = new _operator_list.OperatorList(); - opList.addOp(_util.OPS.beginAnnotation, [data.id, data.rect, transform, matrix, isUsingOwnCanvas]); - return evaluator.getOperatorList({ - stream: appearance, - task, - resources, - operatorList: opList, - fallbackFontDict: this._fallbackFontDict - }).then(() => { - opList.addOp(_util.OPS.endAnnotation, []); - this.reset(); - return opList; - }); - }); - } - - async save(evaluator, task, annotationStorage) { - return null; - } - - getFieldObject() { - if (this.data.kidIds) { - return { - id: this.data.id, - actions: this.data.actions, - name: this.data.fieldName, - strokeColor: this.data.borderColor, - fillColor: this.data.backgroundColor, - type: "", - kidIds: this.data.kidIds, - page: this.data.pageIndex - }; - } - - return null; - } - - reset() { - for (const stream of this._streams) { - stream.reset(); - } - } - - _constructFieldName(dict) { - if (!dict.has("T") && !dict.has("Parent")) { - (0, _util.warn)("Unknown field name, falling back to empty field name."); - return ""; - } - - if (!dict.has("Parent")) { - return (0, _util.stringToPDFString)(dict.get("T")); - } - - const fieldName = []; - - if (dict.has("T")) { - fieldName.unshift((0, _util.stringToPDFString)(dict.get("T"))); - } - - let loopDict = dict; - const visited = new _primitives.RefSet(); - - if (dict.objId) { - visited.put(dict.objId); - } - - while (loopDict.has("Parent")) { - loopDict = loopDict.get("Parent"); - - if (!(loopDict instanceof _primitives.Dict) || loopDict.objId && visited.has(loopDict.objId)) { - break; - } - - if (loopDict.objId) { - visited.put(loopDict.objId); - } - - if (loopDict.has("T")) { - fieldName.unshift((0, _util.stringToPDFString)(loopDict.get("T"))); - } - } - - return fieldName.join("."); - } - -} - -exports.Annotation = Annotation; - -class AnnotationBorderStyle { - constructor() { - this.width = 1; - this.style = _util.AnnotationBorderStyleType.SOLID; - this.dashArray = [3]; - this.horizontalCornerRadius = 0; - this.verticalCornerRadius = 0; - } - - setWidth(width, rect = [0, 0, 0, 0]) { - if ((0, _primitives.isName)(width)) { - this.width = 0; - return; - } - - if (Number.isInteger(width)) { - if (width > 0) { - const maxWidth = (rect[2] - rect[0]) / 2; - const maxHeight = (rect[3] - rect[1]) / 2; - - if (maxWidth > 0 && maxHeight > 0 && (width > maxWidth || width > maxHeight)) { - (0, _util.warn)(`AnnotationBorderStyle.setWidth - ignoring width: ${width}`); - width = 1; - } - } - - this.width = width; - } - } - - setStyle(style) { - if (!(0, _primitives.isName)(style)) { - return; - } - - switch (style.name) { - case "S": - this.style = _util.AnnotationBorderStyleType.SOLID; - break; - - case "D": - this.style = _util.AnnotationBorderStyleType.DASHED; - break; - - case "B": - this.style = _util.AnnotationBorderStyleType.BEVELED; - break; - - case "I": - this.style = _util.AnnotationBorderStyleType.INSET; - break; - - case "U": - this.style = _util.AnnotationBorderStyleType.UNDERLINE; - break; - - default: - break; - } - } - - setDashArray(dashArray, forceStyle = false) { - if (Array.isArray(dashArray) && dashArray.length > 0) { - let isValid = true; - let allZeros = true; - - for (const element of dashArray) { - const validNumber = +element >= 0; - - if (!validNumber) { - isValid = false; - break; - } else if (element > 0) { - allZeros = false; - } - } - - if (isValid && !allZeros) { - this.dashArray = dashArray; - - if (forceStyle) { - this.setStyle(_primitives.Name.get("D")); - } - } else { - this.width = 0; - } - } else if (dashArray) { - this.width = 0; - } - } - - setHorizontalCornerRadius(radius) { - if (Number.isInteger(radius)) { - this.horizontalCornerRadius = radius; - } - } - - setVerticalCornerRadius(radius) { - if (Number.isInteger(radius)) { - this.verticalCornerRadius = radius; - } - } - -} - -exports.AnnotationBorderStyle = AnnotationBorderStyle; - -class MarkupAnnotation extends Annotation { - constructor(parameters) { - super(parameters); - const dict = parameters.dict; - - if (dict.has("IRT")) { - const rawIRT = dict.getRaw("IRT"); - this.data.inReplyTo = (0, _primitives.isRef)(rawIRT) ? rawIRT.toString() : null; - const rt = dict.get("RT"); - this.data.replyType = (0, _primitives.isName)(rt) ? rt.name : _util.AnnotationReplyType.REPLY; - } - - if (this.data.replyType === _util.AnnotationReplyType.GROUP) { - const parent = dict.get("IRT"); - this.setTitle(parent.get("T")); - this.data.titleObj = this._title; - this.setContents(parent.get("Contents")); - this.data.contentsObj = this._contents; - - if (!parent.has("CreationDate")) { - this.data.creationDate = null; - } else { - this.setCreationDate(parent.get("CreationDate")); - this.data.creationDate = this.creationDate; - } - - if (!parent.has("M")) { - this.data.modificationDate = null; - } else { - this.setModificationDate(parent.get("M")); - this.data.modificationDate = this.modificationDate; - } - - this.data.hasPopup = parent.has("Popup"); - - if (!parent.has("C")) { - this.data.color = null; - } else { - this.setColor(parent.getArray("C")); - this.data.color = this.color; - } - } else { - this.data.titleObj = this._title; - this.setCreationDate(dict.get("CreationDate")); - this.data.creationDate = this.creationDate; - this.data.hasPopup = dict.has("Popup"); - - if (!dict.has("C")) { - this.data.color = null; - } - } - - if (dict.has("RC")) { - this.data.richText = _factory.XFAFactory.getRichTextAsHtml(dict.get("RC")); - } - } - - setCreationDate(creationDate) { - this.creationDate = (0, _util.isString)(creationDate) ? creationDate : null; - } - - _setDefaultAppearance({ - xref, - extra, - strokeColor, - fillColor, - blendMode, - strokeAlpha, - fillAlpha, - pointsCallback - }) { - let minX = Number.MAX_VALUE; - let minY = Number.MAX_VALUE; - let maxX = Number.MIN_VALUE; - let maxY = Number.MIN_VALUE; - const buffer = ["q"]; - - if (extra) { - buffer.push(extra); - } - - if (strokeColor) { - buffer.push(`${strokeColor[0]} ${strokeColor[1]} ${strokeColor[2]} RG`); - } - - if (fillColor) { - buffer.push(`${fillColor[0]} ${fillColor[1]} ${fillColor[2]} rg`); - } - - let pointsArray = this.data.quadPoints; - - if (!pointsArray) { - pointsArray = [[{ - x: this.rectangle[0], - y: this.rectangle[3] - }, { - x: this.rectangle[2], - y: this.rectangle[3] - }, { - x: this.rectangle[0], - y: this.rectangle[1] - }, { - x: this.rectangle[2], - y: this.rectangle[1] - }]]; - } - - for (const points of pointsArray) { - const [mX, MX, mY, MY] = pointsCallback(buffer, points); - minX = Math.min(minX, mX); - maxX = Math.max(maxX, MX); - minY = Math.min(minY, mY); - maxY = Math.max(maxY, MY); - } - - buffer.push("Q"); - const formDict = new _primitives.Dict(xref); - const appearanceStreamDict = new _primitives.Dict(xref); - appearanceStreamDict.set("Subtype", _primitives.Name.get("Form")); - const appearanceStream = new _stream.StringStream(buffer.join(" ")); - appearanceStream.dict = appearanceStreamDict; - formDict.set("Fm0", appearanceStream); - const gsDict = new _primitives.Dict(xref); - - if (blendMode) { - gsDict.set("BM", _primitives.Name.get(blendMode)); - } - - if (typeof strokeAlpha === "number") { - gsDict.set("CA", strokeAlpha); - } - - if (typeof fillAlpha === "number") { - gsDict.set("ca", fillAlpha); - } - - const stateDict = new _primitives.Dict(xref); - stateDict.set("GS0", gsDict); - const resources = new _primitives.Dict(xref); - resources.set("ExtGState", stateDict); - resources.set("XObject", formDict); - const appearanceDict = new _primitives.Dict(xref); - appearanceDict.set("Resources", resources); - const bbox = this.data.rect = [minX, minY, maxX, maxY]; - appearanceDict.set("BBox", bbox); - this.appearance = new _stream.StringStream("/GS0 gs /Fm0 Do"); - this.appearance.dict = appearanceDict; - - this._streams.push(this.appearance, appearanceStream); - } - -} - -exports.MarkupAnnotation = MarkupAnnotation; - -class WidgetAnnotation extends Annotation { - constructor(params) { - super(params); - const dict = params.dict; - const data = this.data; - this.ref = params.ref; - data.annotationType = _util.AnnotationType.WIDGET; - - if (data.fieldName === undefined) { - data.fieldName = this._constructFieldName(dict); - } - - if (data.actions === undefined) { - data.actions = (0, _core_utils.collectActions)(params.xref, dict, _util.AnnotationActionEventType); - } - - const fieldValue = (0, _core_utils.getInheritableProperty)({ - dict, - key: "V", - getArray: true - }); - data.fieldValue = this._decodeFormValue(fieldValue); - const defaultFieldValue = (0, _core_utils.getInheritableProperty)({ - dict, - key: "DV", - getArray: true - }); - data.defaultFieldValue = this._decodeFormValue(defaultFieldValue); - - if (fieldValue === undefined && data.defaultFieldValue !== null) { - data.fieldValue = data.defaultFieldValue; - } - - data.alternativeText = (0, _util.stringToPDFString)(dict.get("TU") || ""); - const defaultAppearance = (0, _core_utils.getInheritableProperty)({ - dict, - key: "DA" - }) || params.acroForm.get("DA"); - this._defaultAppearance = (0, _util.isString)(defaultAppearance) ? defaultAppearance : ""; - data.defaultAppearanceData = (0, _default_appearance.parseDefaultAppearance)(this._defaultAppearance); - const fieldType = (0, _core_utils.getInheritableProperty)({ - dict, - key: "FT" - }); - data.fieldType = (0, _primitives.isName)(fieldType) ? fieldType.name : null; - const localResources = (0, _core_utils.getInheritableProperty)({ - dict, - key: "DR" - }); - const acroFormResources = params.acroForm.get("DR"); - const appearanceResources = this.appearance && this.appearance.dict.get("Resources"); - this._fieldResources = { - localResources, - acroFormResources, - appearanceResources, - mergedResources: _primitives.Dict.merge({ - xref: params.xref, - dictArray: [localResources, appearanceResources, acroFormResources], - mergeSubDicts: true - }) - }; - data.fieldFlags = (0, _core_utils.getInheritableProperty)({ - dict, - key: "Ff" - }); - - if (!Number.isInteger(data.fieldFlags) || data.fieldFlags < 0) { - data.fieldFlags = 0; - } - - data.readOnly = this.hasFieldFlag(_util.AnnotationFieldFlag.READONLY); - data.hidden = this._hasFlag(data.annotationFlags, _util.AnnotationFlag.HIDDEN); - } - - _decodeFormValue(formValue) { - if (Array.isArray(formValue)) { - return formValue.filter(item => (0, _util.isString)(item)).map(item => (0, _util.stringToPDFString)(item)); - } else if ((0, _primitives.isName)(formValue)) { - return (0, _util.stringToPDFString)(formValue.name); - } else if ((0, _util.isString)(formValue)) { - return (0, _util.stringToPDFString)(formValue); - } - - return null; - } - - hasFieldFlag(flag) { - return !!(this.data.fieldFlags & flag); - } - - getOperatorList(evaluator, task, intent, renderForms, annotationStorage) { - if (renderForms && !(this instanceof SignatureWidgetAnnotation)) { - return Promise.resolve(new _operator_list.OperatorList()); - } - - if (!this._hasText) { - return super.getOperatorList(evaluator, task, intent, renderForms, annotationStorage); - } - - return this._getAppearance(evaluator, task, annotationStorage).then(content => { - if (this.appearance && content === null) { - return super.getOperatorList(evaluator, task, intent, renderForms, annotationStorage); - } - - const operatorList = new _operator_list.OperatorList(); - - if (!this._defaultAppearance || content === null) { - return operatorList; - } - - const matrix = [1, 0, 0, 1, 0, 0]; - const bbox = [0, 0, this.data.rect[2] - this.data.rect[0], this.data.rect[3] - this.data.rect[1]]; - const transform = getTransformMatrix(this.data.rect, bbox, matrix); - operatorList.addOp(_util.OPS.beginAnnotation, [this.data.id, this.data.rect, transform, matrix]); - const stream = new _stream.StringStream(content); - return evaluator.getOperatorList({ - stream, - task, - resources: this._fieldResources.mergedResources, - operatorList - }).then(function () { - operatorList.addOp(_util.OPS.endAnnotation, []); - return operatorList; - }); - }); - } - - async save(evaluator, task, annotationStorage) { - if (!annotationStorage) { - return null; - } - - const storageEntry = annotationStorage.get(this.data.id); - const value = storageEntry && storageEntry.value; - - if (value === this.data.fieldValue || value === undefined) { - return null; - } - - let appearance = await this._getAppearance(evaluator, task, annotationStorage); - - if (appearance === null) { - return null; - } - - const { - xref - } = evaluator; - const dict = xref.fetchIfRef(this.ref); - - if (!(0, _primitives.isDict)(dict)) { - return null; - } - - const bbox = [0, 0, this.data.rect[2] - this.data.rect[0], this.data.rect[3] - this.data.rect[1]]; - const xfa = { - path: (0, _util.stringToPDFString)(dict.get("T") || ""), - value - }; - const newRef = xref.getNewRef(); - const AP = new _primitives.Dict(xref); - AP.set("N", newRef); - const encrypt = xref.encrypt; - let originalTransform = null; - let newTransform = null; - - if (encrypt) { - originalTransform = encrypt.createCipherTransform(this.ref.num, this.ref.gen); - newTransform = encrypt.createCipherTransform(newRef.num, newRef.gen); - appearance = newTransform.encryptString(appearance); - } - - dict.set("V", (0, _util.isAscii)(value) ? value : (0, _util.stringToUTF16BEString)(value)); - dict.set("AP", AP); - dict.set("M", `D:${(0, _util.getModificationDate)()}`); - const appearanceDict = new _primitives.Dict(xref); - appearanceDict.set("Length", appearance.length); - appearanceDict.set("Subtype", _primitives.Name.get("Form")); - appearanceDict.set("Resources", this._getSaveFieldResources(xref)); - appearanceDict.set("BBox", bbox); - const bufferOriginal = [`${this.ref.num} ${this.ref.gen} obj\n`]; - (0, _writer.writeDict)(dict, bufferOriginal, originalTransform); - bufferOriginal.push("\nendobj\n"); - const bufferNew = [`${newRef.num} ${newRef.gen} obj\n`]; - (0, _writer.writeDict)(appearanceDict, bufferNew, newTransform); - bufferNew.push(" stream\n", appearance, "\nendstream\nendobj\n"); - return [{ - ref: this.ref, - data: bufferOriginal.join(""), - xfa - }, { - ref: newRef, - data: bufferNew.join(""), - xfa: null - }]; - } - - async _getAppearance(evaluator, task, annotationStorage) { - const isPassword = this.hasFieldFlag(_util.AnnotationFieldFlag.PASSWORD); - - if (!annotationStorage || isPassword) { - return null; - } - - const storageEntry = annotationStorage.get(this.data.id); - let value = storageEntry && storageEntry.value; - - if (value === undefined) { - return null; - } - - value = value.trim(); - - if (value === "") { - return ""; - } - - let lineCount = -1; - - if (this.data.multiLine) { - lineCount = value.split(/\r\n|\r|\n/).length; - } - - const defaultPadding = 2; - const hPadding = defaultPadding; - const totalHeight = this.data.rect[3] - this.data.rect[1]; - const totalWidth = this.data.rect[2] - this.data.rect[0]; - - if (!this._defaultAppearance) { - this.data.defaultAppearanceData = (0, _default_appearance.parseDefaultAppearance)(this._defaultAppearance = "/Helvetica 0 Tf 0 g"); - } - - const [defaultAppearance, fontSize] = this._computeFontSize(totalHeight, lineCount); - - const font = await this._getFontData(evaluator, task); - let descent = font.descent; - - if (isNaN(descent)) { - descent = 0; - } - - const vPadding = defaultPadding + Math.abs(descent) * fontSize; - const alignment = this.data.textAlignment; - - if (this.data.multiLine) { - return this._getMultilineAppearance(defaultAppearance, value, font, fontSize, totalWidth, totalHeight, alignment, hPadding, vPadding); - } - - const encodedString = font.encodeString(value).join(""); - - if (this.data.comb) { - return this._getCombAppearance(defaultAppearance, font, encodedString, totalWidth, hPadding, vPadding); - } - - if (alignment === 0 || alignment > 2) { - return "/Tx BMC q BT " + defaultAppearance + ` 1 0 0 1 ${hPadding} ${vPadding} Tm (${(0, _util.escapeString)(encodedString)}) Tj` + " ET Q EMC"; - } - - const renderedText = this._renderText(encodedString, font, fontSize, totalWidth, alignment, hPadding, vPadding); - - return "/Tx BMC q BT " + defaultAppearance + ` 1 0 0 1 0 0 Tm ${renderedText}` + " ET Q EMC"; - } - - async _getFontData(evaluator, task) { - const operatorList = new _operator_list.OperatorList(); - const initialState = { - font: null, - - clone() { - return this; - } - - }; - const { - fontName, - fontSize - } = this.data.defaultAppearanceData; - await evaluator.handleSetFont(this._fieldResources.mergedResources, [fontName && _primitives.Name.get(fontName), fontSize], null, operatorList, task, initialState, null); - return initialState.font; - } - - _computeFontSize(height, lineCount) { - let { - fontSize - } = this.data.defaultAppearanceData; - - if (!fontSize) { - const roundWithOneDigit = x => Math.round(x * 10) / 10; - - const FONT_FACTOR = 0.8; - - if (lineCount === -1) { - fontSize = roundWithOneDigit(FONT_FACTOR * height); - } else { - fontSize = 10; - let lineHeight = fontSize / FONT_FACTOR; - let numberOfLines = Math.round(height / lineHeight); - numberOfLines = Math.max(numberOfLines, lineCount); - lineHeight = height / numberOfLines; - fontSize = roundWithOneDigit(FONT_FACTOR * lineHeight); - } - - const { - fontName, - fontColor - } = this.data.defaultAppearanceData; - this._defaultAppearance = (0, _default_appearance.createDefaultAppearance)({ - fontSize, - fontName, - fontColor - }); - } - - return [this._defaultAppearance, fontSize]; - } - - _renderText(text, font, fontSize, totalWidth, alignment, hPadding, vPadding) { - const glyphs = font.charsToGlyphs(text); - const scale = fontSize / 1000; - let width = 0; - - for (const glyph of glyphs) { - width += glyph.width * scale; - } - - let shift; - - if (alignment === 1) { - shift = (totalWidth - width) / 2; - } else if (alignment === 2) { - shift = totalWidth - width - hPadding; - } else { - shift = hPadding; - } - - shift = shift.toFixed(2); - vPadding = vPadding.toFixed(2); - return `${shift} ${vPadding} Td (${(0, _util.escapeString)(text)}) Tj`; - } - - _getSaveFieldResources(xref) { - const { - localResources, - appearanceResources, - acroFormResources - } = this._fieldResources; - const fontName = this.data.defaultAppearanceData && this.data.defaultAppearanceData.fontName; - - if (!fontName) { - return localResources || _primitives.Dict.empty; - } - - for (const resources of [localResources, appearanceResources]) { - if (resources instanceof _primitives.Dict) { - const localFont = resources.get("Font"); - - if (localFont instanceof _primitives.Dict && localFont.has(fontName)) { - return resources; - } - } - } - - if (acroFormResources instanceof _primitives.Dict) { - const acroFormFont = acroFormResources.get("Font"); - - if (acroFormFont instanceof _primitives.Dict && acroFormFont.has(fontName)) { - const subFontDict = new _primitives.Dict(xref); - subFontDict.set(fontName, acroFormFont.getRaw(fontName)); - const subResourcesDict = new _primitives.Dict(xref); - subResourcesDict.set("Font", subFontDict); - return _primitives.Dict.merge({ - xref, - dictArray: [subResourcesDict, localResources], - mergeSubDicts: true - }); - } - } - - return localResources || _primitives.Dict.empty; - } - - getFieldObject() { - return null; - } - -} - -class TextWidgetAnnotation extends WidgetAnnotation { - constructor(params) { - super(params); - this._hasText = true; - const dict = params.dict; - - if (!(0, _util.isString)(this.data.fieldValue)) { - this.data.fieldValue = ""; - } - - let alignment = (0, _core_utils.getInheritableProperty)({ - dict, - key: "Q" - }); - - if (!Number.isInteger(alignment) || alignment < 0 || alignment > 2) { - alignment = null; - } - - this.data.textAlignment = alignment; - let maximumLength = (0, _core_utils.getInheritableProperty)({ - dict, - key: "MaxLen" - }); - - if (!Number.isInteger(maximumLength) || maximumLength < 0) { - maximumLength = null; - } - - this.data.maxLen = maximumLength; - this.data.multiLine = this.hasFieldFlag(_util.AnnotationFieldFlag.MULTILINE); - this.data.comb = this.hasFieldFlag(_util.AnnotationFieldFlag.COMB) && !this.hasFieldFlag(_util.AnnotationFieldFlag.MULTILINE) && !this.hasFieldFlag(_util.AnnotationFieldFlag.PASSWORD) && !this.hasFieldFlag(_util.AnnotationFieldFlag.FILESELECT) && this.data.maxLen !== null; - } - - _getCombAppearance(defaultAppearance, font, text, width, hPadding, vPadding) { - const combWidth = (width / this.data.maxLen).toFixed(2); - const buf = []; - const positions = font.getCharPositions(text); - - for (const [start, end] of positions) { - buf.push(`(${(0, _util.escapeString)(text.substring(start, end))}) Tj`); - } - - const renderedComb = buf.join(` ${combWidth} 0 Td `); - return "/Tx BMC q BT " + defaultAppearance + ` 1 0 0 1 ${hPadding} ${vPadding} Tm ${renderedComb}` + " ET Q EMC"; - } - - _getMultilineAppearance(defaultAppearance, text, font, fontSize, width, height, alignment, hPadding, vPadding) { - const lines = text.split(/\r\n|\r|\n/); - const buf = []; - const totalWidth = width - 2 * hPadding; - - for (const line of lines) { - const chunks = this._splitLine(line, font, fontSize, totalWidth); - - for (const chunk of chunks) { - const padding = buf.length === 0 ? hPadding : 0; - buf.push(this._renderText(chunk, font, fontSize, width, alignment, padding, -fontSize)); - } - } - - const renderedText = buf.join("\n"); - return "/Tx BMC q BT " + defaultAppearance + ` 1 0 0 1 0 ${height} Tm ${renderedText}` + " ET Q EMC"; - } - - _splitLine(line, font, fontSize, width) { - line = font.encodeString(line).join(""); - const glyphs = font.charsToGlyphs(line); - - if (glyphs.length <= 1) { - return [line]; - } - - const positions = font.getCharPositions(line); - const scale = fontSize / 1000; - const chunks = []; - let lastSpacePosInStringStart = -1, - lastSpacePosInStringEnd = -1, - lastSpacePos = -1, - startChunk = 0, - currentWidth = 0; - - for (let i = 0, ii = glyphs.length; i < ii; i++) { - const [start, end] = positions[i]; - const glyph = glyphs[i]; - const glyphWidth = glyph.width * scale; - - if (glyph.unicode === " ") { - if (currentWidth + glyphWidth > width) { - chunks.push(line.substring(startChunk, start)); - startChunk = start; - currentWidth = glyphWidth; - lastSpacePosInStringStart = -1; - lastSpacePos = -1; - } else { - currentWidth += glyphWidth; - lastSpacePosInStringStart = start; - lastSpacePosInStringEnd = end; - lastSpacePos = i; - } - } else { - if (currentWidth + glyphWidth > width) { - if (lastSpacePosInStringStart !== -1) { - chunks.push(line.substring(startChunk, lastSpacePosInStringEnd)); - startChunk = lastSpacePosInStringEnd; - i = lastSpacePos + 1; - lastSpacePosInStringStart = -1; - currentWidth = 0; - } else { - chunks.push(line.substring(startChunk, start)); - startChunk = start; - currentWidth = glyphWidth; - } - } else { - currentWidth += glyphWidth; - } - } - } - - if (startChunk < line.length) { - chunks.push(line.substring(startChunk, line.length)); - } - - return chunks; - } - - getFieldObject() { - return { - id: this.data.id, - value: this.data.fieldValue, - defaultValue: this.data.defaultFieldValue, - multiline: this.data.multiLine, - password: this.hasFieldFlag(_util.AnnotationFieldFlag.PASSWORD), - charLimit: this.data.maxLen, - comb: this.data.comb, - editable: !this.data.readOnly, - hidden: this.data.hidden, - name: this.data.fieldName, - rect: this.data.rect, - actions: this.data.actions, - page: this.data.pageIndex, - strokeColor: this.data.borderColor, - fillColor: this.data.backgroundColor, - type: "text" - }; - } - -} - -class ButtonWidgetAnnotation extends WidgetAnnotation { - constructor(params) { - super(params); - this.checkedAppearance = null; - this.uncheckedAppearance = null; - this.data.checkBox = !this.hasFieldFlag(_util.AnnotationFieldFlag.RADIO) && !this.hasFieldFlag(_util.AnnotationFieldFlag.PUSHBUTTON); - this.data.radioButton = this.hasFieldFlag(_util.AnnotationFieldFlag.RADIO) && !this.hasFieldFlag(_util.AnnotationFieldFlag.PUSHBUTTON); - this.data.pushButton = this.hasFieldFlag(_util.AnnotationFieldFlag.PUSHBUTTON); - this.data.isTooltipOnly = false; - - if (this.data.checkBox) { - this._processCheckBox(params); - } else if (this.data.radioButton) { - this._processRadioButton(params); - } else if (this.data.pushButton) { - this.data.hasOwnCanvas = true; - - this._processPushButton(params); - } else { - (0, _util.warn)("Invalid field flags for button widget annotation"); - } - } - - async getOperatorList(evaluator, task, intent, renderForms, annotationStorage) { - if (this.data.pushButton) { - return super.getOperatorList(evaluator, task, intent, false, annotationStorage); - } - - let value = null; - - if (annotationStorage) { - const storageEntry = annotationStorage.get(this.data.id); - value = storageEntry ? storageEntry.value : null; - } - - if (value === null) { - if (this.appearance) { - return super.getOperatorList(evaluator, task, intent, renderForms, annotationStorage); - } - - if (this.data.checkBox) { - value = this.data.fieldValue === this.data.exportValue; - } else { - value = this.data.fieldValue === this.data.buttonValue; - } - } - - const appearance = value ? this.checkedAppearance : this.uncheckedAppearance; - - if (appearance) { - const savedAppearance = this.appearance; - this.appearance = appearance; - const operatorList = super.getOperatorList(evaluator, task, intent, renderForms, annotationStorage); - this.appearance = savedAppearance; - return operatorList; - } - - return new _operator_list.OperatorList(); - } - - async save(evaluator, task, annotationStorage) { - if (this.data.checkBox) { - return this._saveCheckbox(evaluator, task, annotationStorage); - } - - if (this.data.radioButton) { - return this._saveRadioButton(evaluator, task, annotationStorage); - } - - return null; - } - - async _saveCheckbox(evaluator, task, annotationStorage) { - if (!annotationStorage) { - return null; - } - - const storageEntry = annotationStorage.get(this.data.id); - const value = storageEntry && storageEntry.value; - - if (value === undefined) { - return null; - } - - const defaultValue = this.data.fieldValue === this.data.exportValue; - - if (defaultValue === value) { - return null; - } - - const dict = evaluator.xref.fetchIfRef(this.ref); - - if (!(0, _primitives.isDict)(dict)) { - return null; - } - - const xfa = { - path: (0, _util.stringToPDFString)(dict.get("T") || ""), - value: value ? this.data.exportValue : "" - }; - - const name = _primitives.Name.get(value ? this.data.exportValue : "Off"); - - dict.set("V", name); - dict.set("AS", name); - dict.set("M", `D:${(0, _util.getModificationDate)()}`); - const encrypt = evaluator.xref.encrypt; - let originalTransform = null; - - if (encrypt) { - originalTransform = encrypt.createCipherTransform(this.ref.num, this.ref.gen); - } - - const buffer = [`${this.ref.num} ${this.ref.gen} obj\n`]; - (0, _writer.writeDict)(dict, buffer, originalTransform); - buffer.push("\nendobj\n"); - return [{ - ref: this.ref, - data: buffer.join(""), - xfa - }]; - } - - async _saveRadioButton(evaluator, task, annotationStorage) { - if (!annotationStorage) { - return null; - } - - const storageEntry = annotationStorage.get(this.data.id); - const value = storageEntry && storageEntry.value; - - if (value === undefined) { - return null; - } - - const defaultValue = this.data.fieldValue === this.data.buttonValue; - - if (defaultValue === value) { - return null; - } - - const dict = evaluator.xref.fetchIfRef(this.ref); - - if (!(0, _primitives.isDict)(dict)) { - return null; - } - - const xfa = { - path: (0, _util.stringToPDFString)(dict.get("T") || ""), - value: value ? this.data.buttonValue : "" - }; - - const name = _primitives.Name.get(value ? this.data.buttonValue : "Off"); - - let parentBuffer = null; - const encrypt = evaluator.xref.encrypt; - - if (value) { - if ((0, _primitives.isRef)(this.parent)) { - const parent = evaluator.xref.fetch(this.parent); - let parentTransform = null; - - if (encrypt) { - parentTransform = encrypt.createCipherTransform(this.parent.num, this.parent.gen); - } - - parent.set("V", name); - parentBuffer = [`${this.parent.num} ${this.parent.gen} obj\n`]; - (0, _writer.writeDict)(parent, parentBuffer, parentTransform); - parentBuffer.push("\nendobj\n"); - } else if ((0, _primitives.isDict)(this.parent)) { - this.parent.set("V", name); - } - } - - dict.set("AS", name); - dict.set("M", `D:${(0, _util.getModificationDate)()}`); - let originalTransform = null; - - if (encrypt) { - originalTransform = encrypt.createCipherTransform(this.ref.num, this.ref.gen); - } - - const buffer = [`${this.ref.num} ${this.ref.gen} obj\n`]; - (0, _writer.writeDict)(dict, buffer, originalTransform); - buffer.push("\nendobj\n"); - const newRefs = [{ - ref: this.ref, - data: buffer.join(""), - xfa - }]; - - if (parentBuffer !== null) { - newRefs.push({ - ref: this.parent, - data: parentBuffer.join(""), - xfa: null - }); - } - - return newRefs; - } - - _getDefaultCheckedAppearance(params, type) { - const width = this.data.rect[2] - this.data.rect[0]; - const height = this.data.rect[3] - this.data.rect[1]; - const bbox = [0, 0, width, height]; - const FONT_RATIO = 0.8; - const fontSize = Math.min(width, height) * FONT_RATIO; - let metrics, char; - - if (type === "check") { - metrics = { - width: 0.755 * fontSize, - height: 0.705 * fontSize - }; - char = "\x33"; - } else if (type === "disc") { - metrics = { - width: 0.791 * fontSize, - height: 0.705 * fontSize - }; - char = "\x6C"; - } else { - (0, _util.unreachable)(`_getDefaultCheckedAppearance - unsupported type: ${type}`); - } - - const xShift = (width - metrics.width) / 2; - const yShift = (height - metrics.height) / 2; - const appearance = `q BT /PdfJsZaDb ${fontSize} Tf 0 g ${xShift} ${yShift} Td (${char}) Tj ET Q`; - const appearanceStreamDict = new _primitives.Dict(params.xref); - appearanceStreamDict.set("FormType", 1); - appearanceStreamDict.set("Subtype", _primitives.Name.get("Form")); - appearanceStreamDict.set("Type", _primitives.Name.get("XObject")); - appearanceStreamDict.set("BBox", bbox); - appearanceStreamDict.set("Matrix", [1, 0, 0, 1, 0, 0]); - appearanceStreamDict.set("Length", appearance.length); - const resources = new _primitives.Dict(params.xref); - const font = new _primitives.Dict(params.xref); - font.set("PdfJsZaDb", this.fallbackFontDict); - resources.set("Font", font); - appearanceStreamDict.set("Resources", resources); - this.checkedAppearance = new _stream.StringStream(appearance); - this.checkedAppearance.dict = appearanceStreamDict; - - this._streams.push(this.checkedAppearance); - } - - _processCheckBox(params) { - const customAppearance = params.dict.get("AP"); - - if (!(0, _primitives.isDict)(customAppearance)) { - return; - } - - const normalAppearance = customAppearance.get("N"); - - if (!(0, _primitives.isDict)(normalAppearance)) { - return; - } - - const asValue = this._decodeFormValue(params.dict.get("AS")); - - if (typeof asValue === "string") { - this.data.fieldValue = asValue; - } - - const yes = this.data.fieldValue !== null && this.data.fieldValue !== "Off" ? this.data.fieldValue : "Yes"; - const exportValues = normalAppearance.getKeys(); - - if (exportValues.length === 0) { - exportValues.push("Off", yes); - } else if (exportValues.length === 1) { - if (exportValues[0] === "Off") { - exportValues.push(yes); - } else { - exportValues.unshift("Off"); - } - } else if (exportValues.includes(yes)) { - exportValues.length = 0; - exportValues.push("Off", yes); - } else { - const otherYes = exportValues.find(v => v !== "Off"); - exportValues.length = 0; - exportValues.push("Off", otherYes); - } - - if (!exportValues.includes(this.data.fieldValue)) { - this.data.fieldValue = "Off"; - } - - this.data.exportValue = exportValues[1]; - this.checkedAppearance = normalAppearance.get(this.data.exportValue) || null; - this.uncheckedAppearance = normalAppearance.get("Off") || null; - - if (this.checkedAppearance) { - this._streams.push(this.checkedAppearance); - } else { - this._getDefaultCheckedAppearance(params, "check"); - } - - if (this.uncheckedAppearance) { - this._streams.push(this.uncheckedAppearance); - } - - this._fallbackFontDict = this.fallbackFontDict; - } - - _processRadioButton(params) { - this.data.fieldValue = this.data.buttonValue = null; - const fieldParent = params.dict.get("Parent"); - - if ((0, _primitives.isDict)(fieldParent)) { - this.parent = params.dict.getRaw("Parent"); - const fieldParentValue = fieldParent.get("V"); - - if ((0, _primitives.isName)(fieldParentValue)) { - this.data.fieldValue = this._decodeFormValue(fieldParentValue); - } - } - - const appearanceStates = params.dict.get("AP"); - - if (!(0, _primitives.isDict)(appearanceStates)) { - return; - } - - const normalAppearance = appearanceStates.get("N"); - - if (!(0, _primitives.isDict)(normalAppearance)) { - return; - } - - for (const key of normalAppearance.getKeys()) { - if (key !== "Off") { - this.data.buttonValue = this._decodeFormValue(key); - break; - } - } - - this.checkedAppearance = normalAppearance.get(this.data.buttonValue) || null; - this.uncheckedAppearance = normalAppearance.get("Off") || null; - - if (this.checkedAppearance) { - this._streams.push(this.checkedAppearance); - } else { - this._getDefaultCheckedAppearance(params, "disc"); - } - - if (this.uncheckedAppearance) { - this._streams.push(this.uncheckedAppearance); - } - - this._fallbackFontDict = this.fallbackFontDict; - } - - _processPushButton(params) { - if (!params.dict.has("A") && !params.dict.has("AA") && !this.data.alternativeText) { - (0, _util.warn)("Push buttons without action dictionaries are not supported"); - return; - } - - this.data.isTooltipOnly = !params.dict.has("A") && !params.dict.has("AA"); - - _catalog.Catalog.parseDestDictionary({ - destDict: params.dict, - resultObj: this.data, - docBaseUrl: params.pdfManager.docBaseUrl - }); - } - - getFieldObject() { - let type = "button"; - let exportValues; - - if (this.data.checkBox) { - type = "checkbox"; - exportValues = this.data.exportValue; - } else if (this.data.radioButton) { - type = "radiobutton"; - exportValues = this.data.buttonValue; - } - - return { - id: this.data.id, - value: this.data.fieldValue || "Off", - defaultValue: this.data.defaultFieldValue, - exportValues, - editable: !this.data.readOnly, - name: this.data.fieldName, - rect: this.data.rect, - hidden: this.data.hidden, - actions: this.data.actions, - page: this.data.pageIndex, - strokeColor: this.data.borderColor, - fillColor: this.data.backgroundColor, - type - }; - } - - get fallbackFontDict() { - const dict = new _primitives.Dict(); - dict.set("BaseFont", _primitives.Name.get("ZapfDingbats")); - dict.set("Type", _primitives.Name.get("FallbackType")); - dict.set("Subtype", _primitives.Name.get("FallbackType")); - dict.set("Encoding", _primitives.Name.get("ZapfDingbatsEncoding")); - return (0, _util.shadow)(this, "fallbackFontDict", dict); - } - -} - -class ChoiceWidgetAnnotation extends WidgetAnnotation { - constructor(params) { - super(params); - this.data.options = []; - const options = (0, _core_utils.getInheritableProperty)({ - dict: params.dict, - key: "Opt" - }); - - if (Array.isArray(options)) { - const xref = params.xref; - - for (let i = 0, ii = options.length; i < ii; i++) { - const option = xref.fetchIfRef(options[i]); - const isOptionArray = Array.isArray(option); - this.data.options[i] = { - exportValue: this._decodeFormValue(isOptionArray ? xref.fetchIfRef(option[0]) : option), - displayValue: this._decodeFormValue(isOptionArray ? xref.fetchIfRef(option[1]) : option) - }; - } - } - - if ((0, _util.isString)(this.data.fieldValue)) { - this.data.fieldValue = [this.data.fieldValue]; - } else if (!this.data.fieldValue) { - this.data.fieldValue = []; - } - - this.data.combo = this.hasFieldFlag(_util.AnnotationFieldFlag.COMBO); - this.data.multiSelect = this.hasFieldFlag(_util.AnnotationFieldFlag.MULTISELECT); - this._hasText = true; - } - - getFieldObject() { - const type = this.data.combo ? "combobox" : "listbox"; - const value = this.data.fieldValue.length > 0 ? this.data.fieldValue[0] : null; - return { - id: this.data.id, - value, - defaultValue: this.data.defaultFieldValue, - editable: !this.data.readOnly, - name: this.data.fieldName, - rect: this.data.rect, - numItems: this.data.fieldValue.length, - multipleSelection: this.data.multiSelect, - hidden: this.data.hidden, - actions: this.data.actions, - items: this.data.options, - page: this.data.pageIndex, - strokeColor: this.data.borderColor, - fillColor: this.data.backgroundColor, - type - }; - } - -} - -class SignatureWidgetAnnotation extends WidgetAnnotation { - constructor(params) { - super(params); - this.data.fieldValue = null; - } - - getFieldObject() { - return { - id: this.data.id, - value: null, - page: this.data.pageIndex, - type: "signature" - }; - } - -} - -class TextAnnotation extends MarkupAnnotation { - constructor(parameters) { - const DEFAULT_ICON_SIZE = 22; - super(parameters); - const dict = parameters.dict; - this.data.annotationType = _util.AnnotationType.TEXT; - - if (this.data.hasAppearance) { - this.data.name = "NoIcon"; - } else { - this.data.rect[1] = this.data.rect[3] - DEFAULT_ICON_SIZE; - this.data.rect[2] = this.data.rect[0] + DEFAULT_ICON_SIZE; - this.data.name = dict.has("Name") ? dict.get("Name").name : "Note"; - } - - if (dict.has("State")) { - this.data.state = dict.get("State") || null; - this.data.stateModel = dict.get("StateModel") || null; - } else { - this.data.state = null; - this.data.stateModel = null; - } - } - -} - -class LinkAnnotation extends Annotation { - constructor(params) { - super(params); - this.data.annotationType = _util.AnnotationType.LINK; - const quadPoints = getQuadPoints(params.dict, this.rectangle); - - if (quadPoints) { - this.data.quadPoints = quadPoints; - } - - _catalog.Catalog.parseDestDictionary({ - destDict: params.dict, - resultObj: this.data, - docBaseUrl: params.pdfManager.docBaseUrl - }); - } - -} - -class PopupAnnotation extends Annotation { - constructor(parameters) { - super(parameters); - this.data.annotationType = _util.AnnotationType.POPUP; - let parentItem = parameters.dict.get("Parent"); - - if (!parentItem) { - (0, _util.warn)("Popup annotation has a missing or invalid parent annotation."); - return; - } - - const parentSubtype = parentItem.get("Subtype"); - this.data.parentType = (0, _primitives.isName)(parentSubtype) ? parentSubtype.name : null; - const rawParent = parameters.dict.getRaw("Parent"); - this.data.parentId = (0, _primitives.isRef)(rawParent) ? rawParent.toString() : null; - const parentRect = parentItem.getArray("Rect"); - - if (Array.isArray(parentRect) && parentRect.length === 4) { - this.data.parentRect = _util.Util.normalizeRect(parentRect); - } else { - this.data.parentRect = [0, 0, 0, 0]; - } - - const rt = parentItem.get("RT"); - - if ((0, _primitives.isName)(rt, _util.AnnotationReplyType.GROUP)) { - parentItem = parentItem.get("IRT"); - } - - if (!parentItem.has("M")) { - this.data.modificationDate = null; - } else { - this.setModificationDate(parentItem.get("M")); - this.data.modificationDate = this.modificationDate; - } - - if (!parentItem.has("C")) { - this.data.color = null; - } else { - this.setColor(parentItem.getArray("C")); - this.data.color = this.color; - } - - if (!this.viewable) { - const parentFlags = parentItem.get("F"); - - if (this._isViewable(parentFlags)) { - this.setFlags(parentFlags); - } - } - - this.setTitle(parentItem.get("T")); - this.data.titleObj = this._title; - this.setContents(parentItem.get("Contents")); - this.data.contentsObj = this._contents; - - if (parentItem.has("RC")) { - this.data.richText = _factory.XFAFactory.getRichTextAsHtml(parentItem.get("RC")); - } - } - -} - -class FreeTextAnnotation extends MarkupAnnotation { - constructor(parameters) { - super(parameters); - this.data.annotationType = _util.AnnotationType.FREETEXT; - } - -} - -class LineAnnotation extends MarkupAnnotation { - constructor(parameters) { - super(parameters); - this.data.annotationType = _util.AnnotationType.LINE; - const lineCoordinates = parameters.dict.getArray("L"); - this.data.lineCoordinates = _util.Util.normalizeRect(lineCoordinates); - - if (!this.appearance) { - const strokeColor = this.color ? Array.from(this.color).map(c => c / 255) : [0, 0, 0]; - const strokeAlpha = parameters.dict.get("CA"); - let fillColor = null, - interiorColor = parameters.dict.getArray("IC"); - - if (interiorColor) { - interiorColor = getRgbColor(interiorColor, null); - fillColor = interiorColor ? Array.from(interiorColor).map(c => c / 255) : null; - } - - const fillAlpha = fillColor ? strokeAlpha : null; - const borderWidth = this.borderStyle.width || 1, - borderAdjust = 2 * borderWidth; - const bbox = [this.data.lineCoordinates[0] - borderAdjust, this.data.lineCoordinates[1] - borderAdjust, this.data.lineCoordinates[2] + borderAdjust, this.data.lineCoordinates[3] + borderAdjust]; - - if (!_util.Util.intersect(this.rectangle, bbox)) { - this.rectangle = bbox; - } - - this._setDefaultAppearance({ - xref: parameters.xref, - extra: `${borderWidth} w`, - strokeColor, - fillColor, - strokeAlpha, - fillAlpha, - pointsCallback: (buffer, points) => { - buffer.push(`${lineCoordinates[0]} ${lineCoordinates[1]} m`, `${lineCoordinates[2]} ${lineCoordinates[3]} l`, "S"); - return [points[0].x - borderWidth, points[1].x + borderWidth, points[3].y - borderWidth, points[1].y + borderWidth]; - } - }); - } - } - -} - -class SquareAnnotation extends MarkupAnnotation { - constructor(parameters) { - super(parameters); - this.data.annotationType = _util.AnnotationType.SQUARE; - - if (!this.appearance) { - const strokeColor = this.color ? Array.from(this.color).map(c => c / 255) : [0, 0, 0]; - const strokeAlpha = parameters.dict.get("CA"); - let fillColor = null, - interiorColor = parameters.dict.getArray("IC"); - - if (interiorColor) { - interiorColor = getRgbColor(interiorColor, null); - fillColor = interiorColor ? Array.from(interiorColor).map(c => c / 255) : null; - } - - const fillAlpha = fillColor ? strokeAlpha : null; - - if (this.borderStyle.width === 0 && !fillColor) { - return; - } - - this._setDefaultAppearance({ - xref: parameters.xref, - extra: `${this.borderStyle.width} w`, - strokeColor, - fillColor, - strokeAlpha, - fillAlpha, - pointsCallback: (buffer, points) => { - const x = points[2].x + this.borderStyle.width / 2; - const y = points[2].y + this.borderStyle.width / 2; - const width = points[3].x - points[2].x - this.borderStyle.width; - const height = points[1].y - points[3].y - this.borderStyle.width; - buffer.push(`${x} ${y} ${width} ${height} re`); - - if (fillColor) { - buffer.push("B"); - } else { - buffer.push("S"); - } - - return [points[0].x, points[1].x, points[3].y, points[1].y]; - } - }); - } - } - -} - -class CircleAnnotation extends MarkupAnnotation { - constructor(parameters) { - super(parameters); - this.data.annotationType = _util.AnnotationType.CIRCLE; - - if (!this.appearance) { - const strokeColor = this.color ? Array.from(this.color).map(c => c / 255) : [0, 0, 0]; - const strokeAlpha = parameters.dict.get("CA"); - let fillColor = null; - let interiorColor = parameters.dict.getArray("IC"); - - if (interiorColor) { - interiorColor = getRgbColor(interiorColor, null); - fillColor = interiorColor ? Array.from(interiorColor).map(c => c / 255) : null; - } - - const fillAlpha = fillColor ? strokeAlpha : null; - - if (this.borderStyle.width === 0 && !fillColor) { - return; - } - - const controlPointsDistance = 4 / 3 * Math.tan(Math.PI / (2 * 4)); - - this._setDefaultAppearance({ - xref: parameters.xref, - extra: `${this.borderStyle.width} w`, - strokeColor, - fillColor, - strokeAlpha, - fillAlpha, - pointsCallback: (buffer, points) => { - const x0 = points[0].x + this.borderStyle.width / 2; - const y0 = points[0].y - this.borderStyle.width / 2; - const x1 = points[3].x - this.borderStyle.width / 2; - const y1 = points[3].y + this.borderStyle.width / 2; - const xMid = x0 + (x1 - x0) / 2; - const yMid = y0 + (y1 - y0) / 2; - const xOffset = (x1 - x0) / 2 * controlPointsDistance; - const yOffset = (y1 - y0) / 2 * controlPointsDistance; - buffer.push(`${xMid} ${y1} m`, `${xMid + xOffset} ${y1} ${x1} ${yMid + yOffset} ${x1} ${yMid} c`, `${x1} ${yMid - yOffset} ${xMid + xOffset} ${y0} ${xMid} ${y0} c`, `${xMid - xOffset} ${y0} ${x0} ${yMid - yOffset} ${x0} ${yMid} c`, `${x0} ${yMid + yOffset} ${xMid - xOffset} ${y1} ${xMid} ${y1} c`, "h"); - - if (fillColor) { - buffer.push("B"); - } else { - buffer.push("S"); - } - - return [points[0].x, points[1].x, points[3].y, points[1].y]; - } - }); - } - } - -} - -class PolylineAnnotation extends MarkupAnnotation { - constructor(parameters) { - super(parameters); - this.data.annotationType = _util.AnnotationType.POLYLINE; - this.data.vertices = []; - const rawVertices = parameters.dict.getArray("Vertices"); - - if (!Array.isArray(rawVertices)) { - return; - } - - for (let i = 0, ii = rawVertices.length; i < ii; i += 2) { - this.data.vertices.push({ - x: rawVertices[i], - y: rawVertices[i + 1] - }); - } - - if (!this.appearance) { - const strokeColor = this.color ? Array.from(this.color).map(c => c / 255) : [0, 0, 0]; - const strokeAlpha = parameters.dict.get("CA"); - const borderWidth = this.borderStyle.width || 1, - borderAdjust = 2 * borderWidth; - const bbox = [Infinity, Infinity, -Infinity, -Infinity]; - - for (const vertex of this.data.vertices) { - bbox[0] = Math.min(bbox[0], vertex.x - borderAdjust); - bbox[1] = Math.min(bbox[1], vertex.y - borderAdjust); - bbox[2] = Math.max(bbox[2], vertex.x + borderAdjust); - bbox[3] = Math.max(bbox[3], vertex.y + borderAdjust); - } - - if (!_util.Util.intersect(this.rectangle, bbox)) { - this.rectangle = bbox; - } - - this._setDefaultAppearance({ - xref: parameters.xref, - extra: `${borderWidth} w`, - strokeColor, - strokeAlpha, - pointsCallback: (buffer, points) => { - const vertices = this.data.vertices; - - for (let i = 0, ii = vertices.length; i < ii; i++) { - buffer.push(`${vertices[i].x} ${vertices[i].y} ${i === 0 ? "m" : "l"}`); - } - - buffer.push("S"); - return [points[0].x, points[1].x, points[3].y, points[1].y]; - } - }); - } - } - -} - -class PolygonAnnotation extends PolylineAnnotation { - constructor(parameters) { - super(parameters); - this.data.annotationType = _util.AnnotationType.POLYGON; - } - -} - -class CaretAnnotation extends MarkupAnnotation { - constructor(parameters) { - super(parameters); - this.data.annotationType = _util.AnnotationType.CARET; - } - -} - -class InkAnnotation extends MarkupAnnotation { - constructor(parameters) { - super(parameters); - this.data.annotationType = _util.AnnotationType.INK; - this.data.inkLists = []; - const rawInkLists = parameters.dict.getArray("InkList"); - - if (!Array.isArray(rawInkLists)) { - return; - } - - const xref = parameters.xref; - - for (let i = 0, ii = rawInkLists.length; i < ii; ++i) { - this.data.inkLists.push([]); - - for (let j = 0, jj = rawInkLists[i].length; j < jj; j += 2) { - this.data.inkLists[i].push({ - x: xref.fetchIfRef(rawInkLists[i][j]), - y: xref.fetchIfRef(rawInkLists[i][j + 1]) - }); - } - } - - if (!this.appearance) { - const strokeColor = this.color ? Array.from(this.color).map(c => c / 255) : [0, 0, 0]; - const strokeAlpha = parameters.dict.get("CA"); - const borderWidth = this.borderStyle.width || 1, - borderAdjust = 2 * borderWidth; - const bbox = [Infinity, Infinity, -Infinity, -Infinity]; - - for (const inkLists of this.data.inkLists) { - for (const vertex of inkLists) { - bbox[0] = Math.min(bbox[0], vertex.x - borderAdjust); - bbox[1] = Math.min(bbox[1], vertex.y - borderAdjust); - bbox[2] = Math.max(bbox[2], vertex.x + borderAdjust); - bbox[3] = Math.max(bbox[3], vertex.y + borderAdjust); - } - } - - if (!_util.Util.intersect(this.rectangle, bbox)) { - this.rectangle = bbox; - } - - this._setDefaultAppearance({ - xref: parameters.xref, - extra: `${borderWidth} w`, - strokeColor, - strokeAlpha, - pointsCallback: (buffer, points) => { - for (const inkList of this.data.inkLists) { - for (let i = 0, ii = inkList.length; i < ii; i++) { - buffer.push(`${inkList[i].x} ${inkList[i].y} ${i === 0 ? "m" : "l"}`); - } - - buffer.push("S"); - } - - return [points[0].x, points[1].x, points[3].y, points[1].y]; - } - }); - } - } - -} - -class HighlightAnnotation extends MarkupAnnotation { - constructor(parameters) { - super(parameters); - this.data.annotationType = _util.AnnotationType.HIGHLIGHT; - const quadPoints = this.data.quadPoints = getQuadPoints(parameters.dict, null); - - if (quadPoints) { - const resources = this.appearance && this.appearance.dict.get("Resources"); - - if (!this.appearance || !(resources && resources.has("ExtGState"))) { - if (this.appearance) { - (0, _util.warn)("HighlightAnnotation - ignoring built-in appearance stream."); - } - - const fillColor = this.color ? Array.from(this.color).map(c => c / 255) : [1, 1, 0]; - const fillAlpha = parameters.dict.get("CA"); - - this._setDefaultAppearance({ - xref: parameters.xref, - fillColor, - blendMode: "Multiply", - fillAlpha, - pointsCallback: (buffer, points) => { - buffer.push(`${points[0].x} ${points[0].y} m`, `${points[1].x} ${points[1].y} l`, `${points[3].x} ${points[3].y} l`, `${points[2].x} ${points[2].y} l`, "f"); - return [points[0].x, points[1].x, points[3].y, points[1].y]; - } - }); - } - } else { - this.data.hasPopup = false; - } - } - -} - -class UnderlineAnnotation extends MarkupAnnotation { - constructor(parameters) { - super(parameters); - this.data.annotationType = _util.AnnotationType.UNDERLINE; - const quadPoints = this.data.quadPoints = getQuadPoints(parameters.dict, null); - - if (quadPoints) { - if (!this.appearance) { - const strokeColor = this.color ? Array.from(this.color).map(c => c / 255) : [0, 0, 0]; - const strokeAlpha = parameters.dict.get("CA"); - - this._setDefaultAppearance({ - xref: parameters.xref, - extra: "[] 0 d 1 w", - strokeColor, - strokeAlpha, - pointsCallback: (buffer, points) => { - buffer.push(`${points[2].x} ${points[2].y} m`, `${points[3].x} ${points[3].y} l`, "S"); - return [points[0].x, points[1].x, points[3].y, points[1].y]; - } - }); - } - } else { - this.data.hasPopup = false; - } - } - -} - -class SquigglyAnnotation extends MarkupAnnotation { - constructor(parameters) { - super(parameters); - this.data.annotationType = _util.AnnotationType.SQUIGGLY; - const quadPoints = this.data.quadPoints = getQuadPoints(parameters.dict, null); - - if (quadPoints) { - if (!this.appearance) { - const strokeColor = this.color ? Array.from(this.color).map(c => c / 255) : [0, 0, 0]; - const strokeAlpha = parameters.dict.get("CA"); - - this._setDefaultAppearance({ - xref: parameters.xref, - extra: "[] 0 d 1 w", - strokeColor, - strokeAlpha, - pointsCallback: (buffer, points) => { - const dy = (points[0].y - points[2].y) / 6; - let shift = dy; - let x = points[2].x; - const y = points[2].y; - const xEnd = points[3].x; - buffer.push(`${x} ${y + shift} m`); - - do { - x += 2; - shift = shift === 0 ? dy : 0; - buffer.push(`${x} ${y + shift} l`); - } while (x < xEnd); - - buffer.push("S"); - return [points[2].x, xEnd, y - 2 * dy, y + 2 * dy]; - } - }); - } - } else { - this.data.hasPopup = false; - } - } - -} - -class StrikeOutAnnotation extends MarkupAnnotation { - constructor(parameters) { - super(parameters); - this.data.annotationType = _util.AnnotationType.STRIKEOUT; - const quadPoints = this.data.quadPoints = getQuadPoints(parameters.dict, null); - - if (quadPoints) { - if (!this.appearance) { - const strokeColor = this.color ? Array.from(this.color).map(c => c / 255) : [0, 0, 0]; - const strokeAlpha = parameters.dict.get("CA"); - - this._setDefaultAppearance({ - xref: parameters.xref, - extra: "[] 0 d 1 w", - strokeColor, - strokeAlpha, - pointsCallback: (buffer, points) => { - buffer.push(`${(points[0].x + points[2].x) / 2} ` + `${(points[0].y + points[2].y) / 2} m`, `${(points[1].x + points[3].x) / 2} ` + `${(points[1].y + points[3].y) / 2} l`, "S"); - return [points[0].x, points[1].x, points[3].y, points[1].y]; - } - }); - } - } else { - this.data.hasPopup = false; - } - } - -} - -class StampAnnotation extends MarkupAnnotation { - constructor(parameters) { - super(parameters); - this.data.annotationType = _util.AnnotationType.STAMP; - } - -} - -class FileAttachmentAnnotation extends MarkupAnnotation { - constructor(parameters) { - super(parameters); - const file = new _file_spec.FileSpec(parameters.dict.get("FS"), parameters.xref); - this.data.annotationType = _util.AnnotationType.FILEATTACHMENT; - this.data.file = file.serializable; - } - -} - -/***/ }), -/* 23 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.createDefaultAppearance = createDefaultAppearance; -exports.parseDefaultAppearance = parseDefaultAppearance; - -var _util = __w_pdfjs_require__(2); - -var _colorspace = __w_pdfjs_require__(24); - -var _core_utils = __w_pdfjs_require__(9); - -var _evaluator = __w_pdfjs_require__(25); - -var _primitives = __w_pdfjs_require__(5); - -var _stream = __w_pdfjs_require__(10); - -class DefaultAppearanceEvaluator extends _evaluator.EvaluatorPreprocessor { - constructor(str) { - super(new _stream.StringStream(str)); - } - - parse() { - const operation = { - fn: 0, - args: [] - }; - const result = { - fontSize: 0, - fontName: "", - fontColor: new Uint8ClampedArray(3) - }; - - try { - while (true) { - operation.args.length = 0; - - if (!this.read(operation)) { - break; - } - - if (this.savedStatesDepth !== 0) { - continue; - } - - const { - fn, - args - } = operation; - - switch (fn | 0) { - case _util.OPS.setFont: - const [fontName, fontSize] = args; - - if (fontName instanceof _primitives.Name) { - result.fontName = fontName.name; - } - - if (typeof fontSize === "number" && fontSize > 0) { - result.fontSize = fontSize; - } - - break; - - case _util.OPS.setFillRGBColor: - _colorspace.ColorSpace.singletons.rgb.getRgbItem(args, 0, result.fontColor, 0); - - break; - - case _util.OPS.setFillGray: - _colorspace.ColorSpace.singletons.gray.getRgbItem(args, 0, result.fontColor, 0); - - break; - - case _util.OPS.setFillColorSpace: - _colorspace.ColorSpace.singletons.cmyk.getRgbItem(args, 0, result.fontColor, 0); - - break; - } - } - } catch (reason) { - (0, _util.warn)(`parseDefaultAppearance - ignoring errors: "${reason}".`); - } - - return result; - } - -} - -function parseDefaultAppearance(str) { - return new DefaultAppearanceEvaluator(str).parse(); -} - -function createDefaultAppearance({ - fontSize, - fontName, - fontColor -}) { - let colorCmd; - - if (fontColor.every(c => c === 0)) { - colorCmd = "0 g"; - } else { - colorCmd = Array.from(fontColor).map(c => (c / 255).toFixed(2)).join(" ") + " rg"; - } - - return `/${(0, _core_utils.escapePDFName)(fontName)} ${fontSize} Tf ${colorCmd}`; -} - -/***/ }), -/* 24 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.ColorSpace = void 0; - -var _util = __w_pdfjs_require__(2); - -var _primitives = __w_pdfjs_require__(5); - -var _core_utils = __w_pdfjs_require__(9); - -function resizeRgbImage(src, dest, w1, h1, w2, h2, alpha01) { - const COMPONENTS = 3; - alpha01 = alpha01 !== 1 ? 0 : alpha01; - const xRatio = w1 / w2; - const yRatio = h1 / h2; - let newIndex = 0, - oldIndex; - const xScaled = new Uint16Array(w2); - const w1Scanline = w1 * COMPONENTS; - - for (let i = 0; i < w2; i++) { - xScaled[i] = Math.floor(i * xRatio) * COMPONENTS; - } - - for (let i = 0; i < h2; i++) { - const py = Math.floor(i * yRatio) * w1Scanline; - - for (let j = 0; j < w2; j++) { - oldIndex = py + xScaled[j]; - dest[newIndex++] = src[oldIndex++]; - dest[newIndex++] = src[oldIndex++]; - dest[newIndex++] = src[oldIndex++]; - newIndex += alpha01; - } - } -} - -class ColorSpace { - constructor(name, numComps) { - if (this.constructor === ColorSpace) { - (0, _util.unreachable)("Cannot initialize ColorSpace."); - } - - this.name = name; - this.numComps = numComps; - } - - getRgb(src, srcOffset) { - const rgb = new Uint8ClampedArray(3); - this.getRgbItem(src, srcOffset, rgb, 0); - return rgb; - } - - getRgbItem(src, srcOffset, dest, destOffset) { - (0, _util.unreachable)("Should not call ColorSpace.getRgbItem"); - } - - getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) { - (0, _util.unreachable)("Should not call ColorSpace.getRgbBuffer"); - } - - getOutputLength(inputLength, alpha01) { - (0, _util.unreachable)("Should not call ColorSpace.getOutputLength"); - } - - isPassthrough(bits) { - return false; - } - - isDefaultDecode(decodeMap, bpc) { - return ColorSpace.isDefaultDecode(decodeMap, this.numComps); - } - - fillRgb(dest, originalWidth, originalHeight, width, height, actualHeight, bpc, comps, alpha01) { - const count = originalWidth * originalHeight; - let rgbBuf = null; - const numComponentColors = 1 << bpc; - const needsResizing = originalHeight !== height || originalWidth !== width; - - if (this.isPassthrough(bpc)) { - rgbBuf = comps; - } else if (this.numComps === 1 && count > numComponentColors && this.name !== "DeviceGray" && this.name !== "DeviceRGB") { - const allColors = bpc <= 8 ? new Uint8Array(numComponentColors) : new Uint16Array(numComponentColors); - - for (let i = 0; i < numComponentColors; i++) { - allColors[i] = i; - } - - const colorMap = new Uint8ClampedArray(numComponentColors * 3); - this.getRgbBuffer(allColors, 0, numComponentColors, colorMap, 0, bpc, 0); - - if (!needsResizing) { - let destPos = 0; - - for (let i = 0; i < count; ++i) { - const key = comps[i] * 3; - dest[destPos++] = colorMap[key]; - dest[destPos++] = colorMap[key + 1]; - dest[destPos++] = colorMap[key + 2]; - destPos += alpha01; - } - } else { - rgbBuf = new Uint8Array(count * 3); - let rgbPos = 0; - - for (let i = 0; i < count; ++i) { - const key = comps[i] * 3; - rgbBuf[rgbPos++] = colorMap[key]; - rgbBuf[rgbPos++] = colorMap[key + 1]; - rgbBuf[rgbPos++] = colorMap[key + 2]; - } - } - } else { - if (!needsResizing) { - this.getRgbBuffer(comps, 0, width * actualHeight, dest, 0, bpc, alpha01); - } else { - rgbBuf = new Uint8ClampedArray(count * 3); - this.getRgbBuffer(comps, 0, count, rgbBuf, 0, bpc, 0); - } - } - - if (rgbBuf) { - if (needsResizing) { - resizeRgbImage(rgbBuf, dest, originalWidth, originalHeight, width, height, alpha01); - } else { - let destPos = 0, - rgbPos = 0; - - for (let i = 0, ii = width * actualHeight; i < ii; i++) { - dest[destPos++] = rgbBuf[rgbPos++]; - dest[destPos++] = rgbBuf[rgbPos++]; - dest[destPos++] = rgbBuf[rgbPos++]; - destPos += alpha01; - } - } - } - } - - get usesZeroToOneRange() { - return (0, _util.shadow)(this, "usesZeroToOneRange", true); - } - - static _cache(cacheKey, xref, localColorSpaceCache, parsedColorSpace) { - if (!localColorSpaceCache) { - throw new Error('ColorSpace._cache - expected "localColorSpaceCache" argument.'); - } - - if (!parsedColorSpace) { - throw new Error('ColorSpace._cache - expected "parsedColorSpace" argument.'); - } - - let csName, csRef; - - if (cacheKey instanceof _primitives.Ref) { - csRef = cacheKey; - cacheKey = xref.fetch(cacheKey); - } - - if (cacheKey instanceof _primitives.Name) { - csName = cacheKey.name; - } - - if (csName || csRef) { - localColorSpaceCache.set(csName, csRef, parsedColorSpace); - } - } - - static getCached(cacheKey, xref, localColorSpaceCache) { - if (!localColorSpaceCache) { - throw new Error('ColorSpace.getCached - expected "localColorSpaceCache" argument.'); - } - - if (cacheKey instanceof _primitives.Ref) { - const localColorSpace = localColorSpaceCache.getByRef(cacheKey); - - if (localColorSpace) { - return localColorSpace; - } - - try { - cacheKey = xref.fetch(cacheKey); - } catch (ex) { - if (ex instanceof _core_utils.MissingDataException) { - throw ex; - } - } - } - - if (cacheKey instanceof _primitives.Name) { - const localColorSpace = localColorSpaceCache.getByName(cacheKey.name); - - if (localColorSpace) { - return localColorSpace; - } - } - - return null; - } - - static async parseAsync({ - cs, - xref, - resources = null, - pdfFunctionFactory, - localColorSpaceCache - }) { - const parsedColorSpace = this._parse(cs, xref, resources, pdfFunctionFactory); - - this._cache(cs, xref, localColorSpaceCache, parsedColorSpace); - - return parsedColorSpace; - } - - static parse({ - cs, - xref, - resources = null, - pdfFunctionFactory, - localColorSpaceCache - }) { - const cachedColorSpace = this.getCached(cs, xref, localColorSpaceCache); - - if (cachedColorSpace) { - return cachedColorSpace; - } - - const parsedColorSpace = this._parse(cs, xref, resources, pdfFunctionFactory); - - this._cache(cs, xref, localColorSpaceCache, parsedColorSpace); - - return parsedColorSpace; - } - - static _parse(cs, xref, resources = null, pdfFunctionFactory) { - cs = xref.fetchIfRef(cs); - - if ((0, _primitives.isName)(cs)) { - switch (cs.name) { - case "G": - case "DeviceGray": - return this.singletons.gray; - - case "RGB": - case "DeviceRGB": - return this.singletons.rgb; - - case "CMYK": - case "DeviceCMYK": - return this.singletons.cmyk; - - case "Pattern": - return new PatternCS(null); - - default: - if ((0, _primitives.isDict)(resources)) { - const colorSpaces = resources.get("ColorSpace"); - - if ((0, _primitives.isDict)(colorSpaces)) { - const resourcesCS = colorSpaces.get(cs.name); - - if (resourcesCS) { - if ((0, _primitives.isName)(resourcesCS)) { - return this._parse(resourcesCS, xref, resources, pdfFunctionFactory); - } - - cs = resourcesCS; - break; - } - } - } - - throw new _util.FormatError(`Unrecognized ColorSpace: ${cs.name}`); - } - } - - if (Array.isArray(cs)) { - const mode = xref.fetchIfRef(cs[0]).name; - let params, numComps, baseCS, whitePoint, blackPoint, gamma; - - switch (mode) { - case "G": - case "DeviceGray": - return this.singletons.gray; - - case "RGB": - case "DeviceRGB": - return this.singletons.rgb; - - case "CMYK": - case "DeviceCMYK": - return this.singletons.cmyk; - - case "CalGray": - params = xref.fetchIfRef(cs[1]); - whitePoint = params.getArray("WhitePoint"); - blackPoint = params.getArray("BlackPoint"); - gamma = params.get("Gamma"); - return new CalGrayCS(whitePoint, blackPoint, gamma); - - case "CalRGB": - params = xref.fetchIfRef(cs[1]); - whitePoint = params.getArray("WhitePoint"); - blackPoint = params.getArray("BlackPoint"); - gamma = params.getArray("Gamma"); - const matrix = params.getArray("Matrix"); - return new CalRGBCS(whitePoint, blackPoint, gamma, matrix); - - case "ICCBased": - const stream = xref.fetchIfRef(cs[1]); - const dict = stream.dict; - numComps = dict.get("N"); - const alt = dict.get("Alternate"); - - if (alt) { - const altCS = this._parse(alt, xref, resources, pdfFunctionFactory); - - if (altCS.numComps === numComps) { - return altCS; - } - - (0, _util.warn)("ICCBased color space: Ignoring incorrect /Alternate entry."); - } - - if (numComps === 1) { - return this.singletons.gray; - } else if (numComps === 3) { - return this.singletons.rgb; - } else if (numComps === 4) { - return this.singletons.cmyk; - } - - break; - - case "Pattern": - baseCS = cs[1] || null; - - if (baseCS) { - baseCS = this._parse(baseCS, xref, resources, pdfFunctionFactory); - } - - return new PatternCS(baseCS); - - case "I": - case "Indexed": - baseCS = this._parse(cs[1], xref, resources, pdfFunctionFactory); - const hiVal = xref.fetchIfRef(cs[2]) + 1; - const lookup = xref.fetchIfRef(cs[3]); - return new IndexedCS(baseCS, hiVal, lookup); - - case "Separation": - case "DeviceN": - const name = xref.fetchIfRef(cs[1]); - numComps = Array.isArray(name) ? name.length : 1; - baseCS = this._parse(cs[2], xref, resources, pdfFunctionFactory); - const tintFn = pdfFunctionFactory.create(cs[3]); - return new AlternateCS(numComps, baseCS, tintFn); - - case "Lab": - params = xref.fetchIfRef(cs[1]); - whitePoint = params.getArray("WhitePoint"); - blackPoint = params.getArray("BlackPoint"); - const range = params.getArray("Range"); - return new LabCS(whitePoint, blackPoint, range); - - default: - throw new _util.FormatError(`Unimplemented ColorSpace object: ${mode}`); - } - } - - throw new _util.FormatError(`Unrecognized ColorSpace object: ${cs}`); - } - - static isDefaultDecode(decode, numComps) { - if (!Array.isArray(decode)) { - return true; - } - - if (numComps * 2 !== decode.length) { - (0, _util.warn)("The decode map is not the correct length"); - return true; - } - - for (let i = 0, ii = decode.length; i < ii; i += 2) { - if (decode[i] !== 0 || decode[i + 1] !== 1) { - return false; - } - } - - return true; - } - - static get singletons() { - return (0, _util.shadow)(this, "singletons", { - get gray() { - return (0, _util.shadow)(this, "gray", new DeviceGrayCS()); - }, - - get rgb() { - return (0, _util.shadow)(this, "rgb", new DeviceRgbCS()); - }, - - get cmyk() { - return (0, _util.shadow)(this, "cmyk", new DeviceCmykCS()); - } - - }); - } - -} - -exports.ColorSpace = ColorSpace; - -class AlternateCS extends ColorSpace { - constructor(numComps, base, tintFn) { - super("Alternate", numComps); - this.base = base; - this.tintFn = tintFn; - this.tmpBuf = new Float32Array(base.numComps); - } - - getRgbItem(src, srcOffset, dest, destOffset) { - const tmpBuf = this.tmpBuf; - this.tintFn(src, srcOffset, tmpBuf, 0); - this.base.getRgbItem(tmpBuf, 0, dest, destOffset); - } - - getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) { - const tintFn = this.tintFn; - const base = this.base; - const scale = 1 / ((1 << bits) - 1); - const baseNumComps = base.numComps; - const usesZeroToOneRange = base.usesZeroToOneRange; - const isPassthrough = (base.isPassthrough(8) || !usesZeroToOneRange) && alpha01 === 0; - let pos = isPassthrough ? destOffset : 0; - const baseBuf = isPassthrough ? dest : new Uint8ClampedArray(baseNumComps * count); - const numComps = this.numComps; - const scaled = new Float32Array(numComps); - const tinted = new Float32Array(baseNumComps); - let i, j; - - for (i = 0; i < count; i++) { - for (j = 0; j < numComps; j++) { - scaled[j] = src[srcOffset++] * scale; - } - - tintFn(scaled, 0, tinted, 0); - - if (usesZeroToOneRange) { - for (j = 0; j < baseNumComps; j++) { - baseBuf[pos++] = tinted[j] * 255; - } - } else { - base.getRgbItem(tinted, 0, baseBuf, pos); - pos += baseNumComps; - } - } - - if (!isPassthrough) { - base.getRgbBuffer(baseBuf, 0, count, dest, destOffset, 8, alpha01); - } - } - - getOutputLength(inputLength, alpha01) { - return this.base.getOutputLength(inputLength * this.base.numComps / this.numComps, alpha01); - } - -} - -class PatternCS extends ColorSpace { - constructor(baseCS) { - super("Pattern", null); - this.base = baseCS; - } - - isDefaultDecode(decodeMap, bpc) { - (0, _util.unreachable)("Should not call PatternCS.isDefaultDecode"); - } - -} - -class IndexedCS extends ColorSpace { - constructor(base, highVal, lookup) { - super("Indexed", 1); - this.base = base; - this.highVal = highVal; - const length = base.numComps * highVal; - this.lookup = new Uint8Array(length); - - if ((0, _primitives.isStream)(lookup)) { - const bytes = lookup.getBytes(length); - this.lookup.set(bytes); - } else if (typeof lookup === "string") { - for (let i = 0; i < length; ++i) { - this.lookup[i] = lookup.charCodeAt(i) & 0xff; - } - } else { - throw new _util.FormatError(`IndexedCS - unrecognized lookup table: ${lookup}`); - } - } - - getRgbItem(src, srcOffset, dest, destOffset) { - const numComps = this.base.numComps; - const start = src[srcOffset] * numComps; - this.base.getRgbBuffer(this.lookup, start, 1, dest, destOffset, 8, 0); - } - - getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) { - const base = this.base; - const numComps = base.numComps; - const outputDelta = base.getOutputLength(numComps, alpha01); - const lookup = this.lookup; - - for (let i = 0; i < count; ++i) { - const lookupPos = src[srcOffset++] * numComps; - base.getRgbBuffer(lookup, lookupPos, 1, dest, destOffset, 8, alpha01); - destOffset += outputDelta; - } - } - - getOutputLength(inputLength, alpha01) { - return this.base.getOutputLength(inputLength * this.base.numComps, alpha01); - } - - isDefaultDecode(decodeMap, bpc) { - if (!Array.isArray(decodeMap)) { - return true; - } - - if (decodeMap.length !== 2) { - (0, _util.warn)("Decode map length is not correct"); - return true; - } - - if (!Number.isInteger(bpc) || bpc < 1) { - (0, _util.warn)("Bits per component is not correct"); - return true; - } - - return decodeMap[0] === 0 && decodeMap[1] === (1 << bpc) - 1; - } - -} - -class DeviceGrayCS extends ColorSpace { - constructor() { - super("DeviceGray", 1); - } - - getRgbItem(src, srcOffset, dest, destOffset) { - const c = src[srcOffset] * 255; - dest[destOffset] = dest[destOffset + 1] = dest[destOffset + 2] = c; - } - - getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) { - const scale = 255 / ((1 << bits) - 1); - let j = srcOffset, - q = destOffset; - - for (let i = 0; i < count; ++i) { - const c = scale * src[j++]; - dest[q++] = c; - dest[q++] = c; - dest[q++] = c; - q += alpha01; - } - } - - getOutputLength(inputLength, alpha01) { - return inputLength * (3 + alpha01); - } - -} - -class DeviceRgbCS extends ColorSpace { - constructor() { - super("DeviceRGB", 3); - } - - getRgbItem(src, srcOffset, dest, destOffset) { - dest[destOffset] = src[srcOffset] * 255; - dest[destOffset + 1] = src[srcOffset + 1] * 255; - dest[destOffset + 2] = src[srcOffset + 2] * 255; - } - - getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) { - if (bits === 8 && alpha01 === 0) { - dest.set(src.subarray(srcOffset, srcOffset + count * 3), destOffset); - return; - } - - const scale = 255 / ((1 << bits) - 1); - let j = srcOffset, - q = destOffset; - - for (let i = 0; i < count; ++i) { - dest[q++] = scale * src[j++]; - dest[q++] = scale * src[j++]; - dest[q++] = scale * src[j++]; - q += alpha01; - } - } - - getOutputLength(inputLength, alpha01) { - return inputLength * (3 + alpha01) / 3 | 0; - } - - isPassthrough(bits) { - return bits === 8; - } - -} - -const DeviceCmykCS = function DeviceCmykCSClosure() { - function convertToRgb(src, srcOffset, srcScale, dest, destOffset) { - const c = src[srcOffset] * srcScale; - const m = src[srcOffset + 1] * srcScale; - const y = src[srcOffset + 2] * srcScale; - const k = src[srcOffset + 3] * srcScale; - dest[destOffset] = 255 + 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); - dest[destOffset + 1] = 255 + 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); - dest[destOffset + 2] = 255 + 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); - } - - class DeviceCmykCS extends ColorSpace { - constructor() { - super("DeviceCMYK", 4); - } - - getRgbItem(src, srcOffset, dest, destOffset) { - convertToRgb(src, srcOffset, 1, dest, destOffset); - } - - getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) { - const scale = 1 / ((1 << bits) - 1); - - for (let i = 0; i < count; i++) { - convertToRgb(src, srcOffset, scale, dest, destOffset); - srcOffset += 4; - destOffset += 3 + alpha01; - } - } - - getOutputLength(inputLength, alpha01) { - return inputLength / 4 * (3 + alpha01) | 0; - } - - } - - return DeviceCmykCS; -}(); - -const CalGrayCS = function CalGrayCSClosure() { - function convertToRgb(cs, src, srcOffset, dest, destOffset, scale) { - const A = src[srcOffset] * scale; - const AG = A ** cs.G; - const L = cs.YW * AG; - const val = Math.max(295.8 * L ** 0.3333333333333333 - 40.8, 0); - dest[destOffset] = val; - dest[destOffset + 1] = val; - dest[destOffset + 2] = val; - } - - class CalGrayCS extends ColorSpace { - constructor(whitePoint, blackPoint, gamma) { - super("CalGray", 1); - - if (!whitePoint) { - throw new _util.FormatError("WhitePoint missing - required for color space CalGray"); - } - - blackPoint = blackPoint || [0, 0, 0]; - gamma = gamma || 1; - this.XW = whitePoint[0]; - this.YW = whitePoint[1]; - this.ZW = whitePoint[2]; - this.XB = blackPoint[0]; - this.YB = blackPoint[1]; - this.ZB = blackPoint[2]; - this.G = gamma; - - if (this.XW < 0 || this.ZW < 0 || this.YW !== 1) { - throw new _util.FormatError(`Invalid WhitePoint components for ${this.name}` + ", no fallback available"); - } - - if (this.XB < 0 || this.YB < 0 || this.ZB < 0) { - (0, _util.info)(`Invalid BlackPoint for ${this.name}, falling back to default.`); - this.XB = this.YB = this.ZB = 0; - } - - if (this.XB !== 0 || this.YB !== 0 || this.ZB !== 0) { - (0, _util.warn)(`${this.name}, BlackPoint: XB: ${this.XB}, YB: ${this.YB}, ` + `ZB: ${this.ZB}, only default values are supported.`); - } - - if (this.G < 1) { - (0, _util.info)(`Invalid Gamma: ${this.G} for ${this.name}, ` + "falling back to default."); - this.G = 1; - } - } - - getRgbItem(src, srcOffset, dest, destOffset) { - convertToRgb(this, src, srcOffset, dest, destOffset, 1); - } - - getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) { - const scale = 1 / ((1 << bits) - 1); - - for (let i = 0; i < count; ++i) { - convertToRgb(this, src, srcOffset, dest, destOffset, scale); - srcOffset += 1; - destOffset += 3 + alpha01; - } - } - - getOutputLength(inputLength, alpha01) { - return inputLength * (3 + alpha01); - } - - } - - return CalGrayCS; -}(); - -const CalRGBCS = function CalRGBCSClosure() { - const BRADFORD_SCALE_MATRIX = new Float32Array([0.8951, 0.2664, -0.1614, -0.7502, 1.7135, 0.0367, 0.0389, -0.0685, 1.0296]); - const BRADFORD_SCALE_INVERSE_MATRIX = new Float32Array([0.9869929, -0.1470543, 0.1599627, 0.4323053, 0.5183603, 0.0492912, -0.0085287, 0.0400428, 0.9684867]); - const SRGB_D65_XYZ_TO_RGB_MATRIX = new Float32Array([3.2404542, -1.5371385, -0.4985314, -0.9692660, 1.8760108, 0.0415560, 0.0556434, -0.2040259, 1.0572252]); - const FLAT_WHITEPOINT_MATRIX = new Float32Array([1, 1, 1]); - const tempNormalizeMatrix = new Float32Array(3); - const tempConvertMatrix1 = new Float32Array(3); - const tempConvertMatrix2 = new Float32Array(3); - const DECODE_L_CONSTANT = ((8 + 16) / 116) ** 3 / 8.0; - - function matrixProduct(a, b, result) { - result[0] = a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; - result[1] = a[3] * b[0] + a[4] * b[1] + a[5] * b[2]; - result[2] = a[6] * b[0] + a[7] * b[1] + a[8] * b[2]; - } - - function convertToFlat(sourceWhitePoint, LMS, result) { - result[0] = LMS[0] * 1 / sourceWhitePoint[0]; - result[1] = LMS[1] * 1 / sourceWhitePoint[1]; - result[2] = LMS[2] * 1 / sourceWhitePoint[2]; - } - - function convertToD65(sourceWhitePoint, LMS, result) { - const D65X = 0.95047; - const D65Y = 1; - const D65Z = 1.08883; - result[0] = LMS[0] * D65X / sourceWhitePoint[0]; - result[1] = LMS[1] * D65Y / sourceWhitePoint[1]; - result[2] = LMS[2] * D65Z / sourceWhitePoint[2]; - } - - function sRGBTransferFunction(color) { - if (color <= 0.0031308) { - return adjustToRange(0, 1, 12.92 * color); - } - - if (color >= 0.99554525) { - return 1; - } - - return adjustToRange(0, 1, (1 + 0.055) * color ** (1 / 2.4) - 0.055); - } - - function adjustToRange(min, max, value) { - return Math.max(min, Math.min(max, value)); - } - - function decodeL(L) { - if (L < 0) { - return -decodeL(-L); - } - - if (L > 8.0) { - return ((L + 16) / 116) ** 3; - } - - return L * DECODE_L_CONSTANT; - } - - function compensateBlackPoint(sourceBlackPoint, XYZ_Flat, result) { - if (sourceBlackPoint[0] === 0 && sourceBlackPoint[1] === 0 && sourceBlackPoint[2] === 0) { - result[0] = XYZ_Flat[0]; - result[1] = XYZ_Flat[1]; - result[2] = XYZ_Flat[2]; - return; - } - - const zeroDecodeL = decodeL(0); - const X_DST = zeroDecodeL; - const X_SRC = decodeL(sourceBlackPoint[0]); - const Y_DST = zeroDecodeL; - const Y_SRC = decodeL(sourceBlackPoint[1]); - const Z_DST = zeroDecodeL; - const Z_SRC = decodeL(sourceBlackPoint[2]); - const X_Scale = (1 - X_DST) / (1 - X_SRC); - const X_Offset = 1 - X_Scale; - const Y_Scale = (1 - Y_DST) / (1 - Y_SRC); - const Y_Offset = 1 - Y_Scale; - const Z_Scale = (1 - Z_DST) / (1 - Z_SRC); - const Z_Offset = 1 - Z_Scale; - result[0] = XYZ_Flat[0] * X_Scale + X_Offset; - result[1] = XYZ_Flat[1] * Y_Scale + Y_Offset; - result[2] = XYZ_Flat[2] * Z_Scale + Z_Offset; - } - - function normalizeWhitePointToFlat(sourceWhitePoint, XYZ_In, result) { - if (sourceWhitePoint[0] === 1 && sourceWhitePoint[2] === 1) { - result[0] = XYZ_In[0]; - result[1] = XYZ_In[1]; - result[2] = XYZ_In[2]; - return; - } - - const LMS = result; - matrixProduct(BRADFORD_SCALE_MATRIX, XYZ_In, LMS); - const LMS_Flat = tempNormalizeMatrix; - convertToFlat(sourceWhitePoint, LMS, LMS_Flat); - matrixProduct(BRADFORD_SCALE_INVERSE_MATRIX, LMS_Flat, result); - } - - function normalizeWhitePointToD65(sourceWhitePoint, XYZ_In, result) { - const LMS = result; - matrixProduct(BRADFORD_SCALE_MATRIX, XYZ_In, LMS); - const LMS_D65 = tempNormalizeMatrix; - convertToD65(sourceWhitePoint, LMS, LMS_D65); - matrixProduct(BRADFORD_SCALE_INVERSE_MATRIX, LMS_D65, result); - } - - function convertToRgb(cs, src, srcOffset, dest, destOffset, scale) { - const A = adjustToRange(0, 1, src[srcOffset] * scale); - const B = adjustToRange(0, 1, src[srcOffset + 1] * scale); - const C = adjustToRange(0, 1, src[srcOffset + 2] * scale); - const AGR = A === 1 ? 1 : A ** cs.GR; - const BGG = B === 1 ? 1 : B ** cs.GG; - const CGB = C === 1 ? 1 : C ** cs.GB; - const X = cs.MXA * AGR + cs.MXB * BGG + cs.MXC * CGB; - const Y = cs.MYA * AGR + cs.MYB * BGG + cs.MYC * CGB; - const Z = cs.MZA * AGR + cs.MZB * BGG + cs.MZC * CGB; - const XYZ = tempConvertMatrix1; - XYZ[0] = X; - XYZ[1] = Y; - XYZ[2] = Z; - const XYZ_Flat = tempConvertMatrix2; - normalizeWhitePointToFlat(cs.whitePoint, XYZ, XYZ_Flat); - const XYZ_Black = tempConvertMatrix1; - compensateBlackPoint(cs.blackPoint, XYZ_Flat, XYZ_Black); - const XYZ_D65 = tempConvertMatrix2; - normalizeWhitePointToD65(FLAT_WHITEPOINT_MATRIX, XYZ_Black, XYZ_D65); - const SRGB = tempConvertMatrix1; - matrixProduct(SRGB_D65_XYZ_TO_RGB_MATRIX, XYZ_D65, SRGB); - dest[destOffset] = sRGBTransferFunction(SRGB[0]) * 255; - dest[destOffset + 1] = sRGBTransferFunction(SRGB[1]) * 255; - dest[destOffset + 2] = sRGBTransferFunction(SRGB[2]) * 255; - } - - class CalRGBCS extends ColorSpace { - constructor(whitePoint, blackPoint, gamma, matrix) { - super("CalRGB", 3); - - if (!whitePoint) { - throw new _util.FormatError("WhitePoint missing - required for color space CalRGB"); - } - - blackPoint = blackPoint || new Float32Array(3); - gamma = gamma || new Float32Array([1, 1, 1]); - matrix = matrix || new Float32Array([1, 0, 0, 0, 1, 0, 0, 0, 1]); - const XW = whitePoint[0]; - const YW = whitePoint[1]; - const ZW = whitePoint[2]; - this.whitePoint = whitePoint; - const XB = blackPoint[0]; - const YB = blackPoint[1]; - const ZB = blackPoint[2]; - this.blackPoint = blackPoint; - this.GR = gamma[0]; - this.GG = gamma[1]; - this.GB = gamma[2]; - this.MXA = matrix[0]; - this.MYA = matrix[1]; - this.MZA = matrix[2]; - this.MXB = matrix[3]; - this.MYB = matrix[4]; - this.MZB = matrix[5]; - this.MXC = matrix[6]; - this.MYC = matrix[7]; - this.MZC = matrix[8]; - - if (XW < 0 || ZW < 0 || YW !== 1) { - throw new _util.FormatError(`Invalid WhitePoint components for ${this.name}` + ", no fallback available"); - } - - if (XB < 0 || YB < 0 || ZB < 0) { - (0, _util.info)(`Invalid BlackPoint for ${this.name} [${XB}, ${YB}, ${ZB}], ` + "falling back to default."); - this.blackPoint = new Float32Array(3); - } - - if (this.GR < 0 || this.GG < 0 || this.GB < 0) { - (0, _util.info)(`Invalid Gamma [${this.GR}, ${this.GG}, ${this.GB}] for ` + `${this.name}, falling back to default.`); - this.GR = this.GG = this.GB = 1; - } - } - - getRgbItem(src, srcOffset, dest, destOffset) { - convertToRgb(this, src, srcOffset, dest, destOffset, 1); - } - - getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) { - const scale = 1 / ((1 << bits) - 1); - - for (let i = 0; i < count; ++i) { - convertToRgb(this, src, srcOffset, dest, destOffset, scale); - srcOffset += 3; - destOffset += 3 + alpha01; - } - } - - getOutputLength(inputLength, alpha01) { - return inputLength * (3 + alpha01) / 3 | 0; - } - - } - - return CalRGBCS; -}(); - -const LabCS = function LabCSClosure() { - function fn_g(x) { - let result; - - if (x >= 6 / 29) { - result = x ** 3; - } else { - result = 108 / 841 * (x - 4 / 29); - } - - return result; - } - - function decode(value, high1, low2, high2) { - return low2 + value * (high2 - low2) / high1; - } - - function convertToRgb(cs, src, srcOffset, maxVal, dest, destOffset) { - let Ls = src[srcOffset]; - let as = src[srcOffset + 1]; - let 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); - } - - if (as > cs.amax) { - as = cs.amax; - } else if (as < cs.amin) { - as = cs.amin; - } - - if (bs > cs.bmax) { - bs = cs.bmax; - } else if (bs < cs.bmin) { - bs = cs.bmin; - } - - const M = (Ls + 16) / 116; - const L = M + as / 500; - const N = M - bs / 200; - const X = cs.XW * fn_g(L); - const Y = cs.YW * fn_g(M); - const Z = cs.ZW * fn_g(N); - let r, g, b; - - if (cs.ZW < 1) { - r = X * 3.1339 + Y * -1.617 + Z * -0.4906; - g = X * -0.9785 + Y * 1.916 + Z * 0.0333; - b = X * 0.072 + Y * -0.229 + Z * 1.4057; - } else { - 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.204 + Z * 1.057; - } - - dest[destOffset] = Math.sqrt(r) * 255; - dest[destOffset + 1] = Math.sqrt(g) * 255; - dest[destOffset + 2] = Math.sqrt(b) * 255; - } - - class LabCS extends ColorSpace { - constructor(whitePoint, blackPoint, range) { - super("Lab", 3); - - if (!whitePoint) { - throw new _util.FormatError("WhitePoint missing - required for color space Lab"); - } - - blackPoint = blackPoint || [0, 0, 0]; - range = range || [-100, 100, -100, 100]; - 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]; - this.XB = blackPoint[0]; - this.YB = blackPoint[1]; - this.ZB = blackPoint[2]; - - if (this.XW < 0 || this.ZW < 0 || this.YW !== 1) { - throw new _util.FormatError("Invalid WhitePoint components, no fallback available"); - } - - if (this.XB < 0 || this.YB < 0 || this.ZB < 0) { - (0, _util.info)("Invalid BlackPoint, falling back to default"); - this.XB = this.YB = this.ZB = 0; - } - - if (this.amin > this.amax || this.bmin > this.bmax) { - (0, _util.info)("Invalid Range, falling back to defaults"); - this.amin = -100; - this.amax = 100; - this.bmin = -100; - this.bmax = 100; - } - } - - getRgbItem(src, srcOffset, dest, destOffset) { - convertToRgb(this, src, srcOffset, false, dest, destOffset); - } - - getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) { - const maxVal = (1 << bits) - 1; - - for (let i = 0; i < count; i++) { - convertToRgb(this, src, srcOffset, maxVal, dest, destOffset); - srcOffset += 3; - destOffset += 3 + alpha01; - } - } - - getOutputLength(inputLength, alpha01) { - return inputLength * (3 + alpha01) / 3 | 0; - } - - isDefaultDecode(decodeMap, bpc) { - return true; - } - - get usesZeroToOneRange() { - return (0, _util.shadow)(this, "usesZeroToOneRange", false); - } - - } - - return LabCS; -}(); - -/***/ }), -/* 25 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.PartialEvaluator = exports.EvaluatorPreprocessor = void 0; - -var _util = __w_pdfjs_require__(2); - -var _cmap = __w_pdfjs_require__(26); - -var _primitives = __w_pdfjs_require__(5); - -var _fonts = __w_pdfjs_require__(44); - -var _fonts_utils = __w_pdfjs_require__(18); - -var _encodings = __w_pdfjs_require__(19); - -var _standard_fonts = __w_pdfjs_require__(47); - -var _unicode = __w_pdfjs_require__(21); - -var _pattern = __w_pdfjs_require__(55); - -var _xfa_fonts = __w_pdfjs_require__(12); - -var _to_unicode_map = __w_pdfjs_require__(48); - -var _function = __w_pdfjs_require__(56); - -var _parser = __w_pdfjs_require__(27); - -var _image_utils = __w_pdfjs_require__(58); - -var _stream = __w_pdfjs_require__(10); - -var _base_stream = __w_pdfjs_require__(6); - -var _bidi = __w_pdfjs_require__(59); - -var _colorspace = __w_pdfjs_require__(24); - -var _decode_stream = __w_pdfjs_require__(29); - -var _glyphlist = __w_pdfjs_require__(20); - -var _core_utils = __w_pdfjs_require__(9); - -var _metrics = __w_pdfjs_require__(60); - -var _murmurhash = __w_pdfjs_require__(61); - -var _operator_list = __w_pdfjs_require__(62); - -var _image = __w_pdfjs_require__(63); - -const DefaultPartialEvaluatorOptions = Object.freeze({ - maxImageSize: -1, - disableFontFace: false, - ignoreErrors: false, - isEvalSupported: true, - fontExtraProperties: false, - useSystemFonts: true, - cMapUrl: null, - standardFontDataUrl: null -}); -const PatternType = { - TILING: 1, - SHADING: 2 -}; -const TEXT_CHUNK_BATCH_SIZE = 10; -const deferred = Promise.resolve(); - -function normalizeBlendMode(value, parsingArray = false) { - if (Array.isArray(value)) { - for (let i = 0, ii = value.length; i < ii; i++) { - const maybeBM = normalizeBlendMode(value[i], true); - - if (maybeBM) { - return maybeBM; - } - } - - (0, _util.warn)(`Unsupported blend mode Array: ${value}`); - return "source-over"; - } - - if (!(0, _primitives.isName)(value)) { - if (parsingArray) { - return null; - } - - return "source-over"; - } - - switch (value.name) { - case "Normal": - case "Compatible": - return "source-over"; - - case "Multiply": - return "multiply"; - - case "Screen": - return "screen"; - - case "Overlay": - return "overlay"; - - case "Darken": - return "darken"; - - case "Lighten": - return "lighten"; - - case "ColorDodge": - return "color-dodge"; - - case "ColorBurn": - return "color-burn"; - - case "HardLight": - return "hard-light"; - - case "SoftLight": - return "soft-light"; - - case "Difference": - return "difference"; - - case "Exclusion": - return "exclusion"; - - case "Hue": - return "hue"; - - case "Saturation": - return "saturation"; - - case "Color": - return "color"; - - case "Luminosity": - return "luminosity"; - } - - if (parsingArray) { - return null; - } - - (0, _util.warn)(`Unsupported blend mode: ${value.name}`); - return "source-over"; -} - -class TimeSlotManager { - static get TIME_SLOT_DURATION_MS() { - return (0, _util.shadow)(this, "TIME_SLOT_DURATION_MS", 20); - } - - static get CHECK_TIME_EVERY() { - return (0, _util.shadow)(this, "CHECK_TIME_EVERY", 100); - } - - constructor() { - this.reset(); - } - - check() { - if (++this.checked < TimeSlotManager.CHECK_TIME_EVERY) { - return false; - } - - this.checked = 0; - return this.endTime <= Date.now(); - } - - reset() { - this.endTime = Date.now() + TimeSlotManager.TIME_SLOT_DURATION_MS; - this.checked = 0; - } - -} - -class PartialEvaluator { - constructor({ - xref, - handler, - pageIndex, - idFactory, - fontCache, - builtInCMapCache, - standardFontDataCache, - globalImageCache, - options = null - }) { - this.xref = xref; - this.handler = handler; - this.pageIndex = pageIndex; - this.idFactory = idFactory; - this.fontCache = fontCache; - this.builtInCMapCache = builtInCMapCache; - this.standardFontDataCache = standardFontDataCache; - this.globalImageCache = globalImageCache; - this.options = options || DefaultPartialEvaluatorOptions; - this.parsingType3Font = false; - this._fetchBuiltInCMapBound = this.fetchBuiltInCMap.bind(this); - } - - get _pdfFunctionFactory() { - const pdfFunctionFactory = new _function.PDFFunctionFactory({ - xref: this.xref, - isEvalSupported: this.options.isEvalSupported - }); - return (0, _util.shadow)(this, "_pdfFunctionFactory", pdfFunctionFactory); - } - - clone(newOptions = null) { - const newEvaluator = Object.create(this); - newEvaluator.options = Object.assign(Object.create(null), this.options, newOptions); - return newEvaluator; - } - - hasBlendModes(resources, nonBlendModesSet) { - if (!(resources instanceof _primitives.Dict)) { - return false; - } - - if (resources.objId && nonBlendModesSet.has(resources.objId)) { - return false; - } - - const processed = new _primitives.RefSet(nonBlendModesSet); - - if (resources.objId) { - processed.put(resources.objId); - } - - const nodes = [resources], - xref = this.xref; - - while (nodes.length) { - const node = nodes.shift(); - const graphicStates = node.get("ExtGState"); - - if (graphicStates instanceof _primitives.Dict) { - for (let graphicState of graphicStates.getRawValues()) { - if (graphicState instanceof _primitives.Ref) { - if (processed.has(graphicState)) { - continue; - } - - try { - graphicState = xref.fetch(graphicState); - } catch (ex) { - processed.put(graphicState); - (0, _util.info)(`hasBlendModes - ignoring ExtGState: "${ex}".`); - continue; - } - } - - if (!(graphicState instanceof _primitives.Dict)) { - continue; - } - - if (graphicState.objId) { - processed.put(graphicState.objId); - } - - const bm = graphicState.get("BM"); - - if (bm instanceof _primitives.Name) { - if (bm.name !== "Normal") { - return true; - } - - continue; - } - - if (bm !== undefined && Array.isArray(bm)) { - for (const element of bm) { - if (element instanceof _primitives.Name && element.name !== "Normal") { - return true; - } - } - } - } - } - - const xObjects = node.get("XObject"); - - if (!(xObjects instanceof _primitives.Dict)) { - continue; - } - - for (let xObject of xObjects.getRawValues()) { - if (xObject instanceof _primitives.Ref) { - if (processed.has(xObject)) { - continue; - } - - try { - xObject = xref.fetch(xObject); - } catch (ex) { - processed.put(xObject); - (0, _util.info)(`hasBlendModes - ignoring XObject: "${ex}".`); - continue; - } - } - - if (!(0, _primitives.isStream)(xObject)) { - continue; - } - - if (xObject.dict.objId) { - processed.put(xObject.dict.objId); - } - - const xResources = xObject.dict.get("Resources"); - - if (!(xResources instanceof _primitives.Dict)) { - continue; - } - - if (xResources.objId && processed.has(xResources.objId)) { - continue; - } - - nodes.push(xResources); - - if (xResources.objId) { - processed.put(xResources.objId); - } - } - } - - processed.forEach(ref => { - nonBlendModesSet.put(ref); - }); - return false; - } - - async fetchBuiltInCMap(name) { - const cachedData = this.builtInCMapCache.get(name); - - if (cachedData) { - return cachedData; - } - - let data; - - if (this.options.cMapUrl !== null) { - const url = `${this.options.cMapUrl}${name}.bcmap`; - const response = await fetch(url); - - if (!response.ok) { - throw new Error(`fetchBuiltInCMap: failed to fetch file "${url}" with "${response.statusText}".`); - } - - data = { - cMapData: new Uint8Array(await response.arrayBuffer()), - compressionType: _util.CMapCompressionType.BINARY - }; - } else { - data = await this.handler.sendWithPromise("FetchBuiltInCMap", { - name - }); - } - - if (data.compressionType !== _util.CMapCompressionType.NONE) { - this.builtInCMapCache.set(name, data); - } - - return data; - } - - async fetchStandardFontData(name) { - const cachedData = this.standardFontDataCache.get(name); - - if (cachedData) { - return new _stream.Stream(cachedData); - } - - if (this.options.useSystemFonts && name !== "Symbol" && name !== "ZapfDingbats") { - return null; - } - - const standardFontNameToFileName = (0, _standard_fonts.getFontNameToFileMap)(), - filename = standardFontNameToFileName[name]; - let data; - - if (this.options.standardFontDataUrl !== null) { - const url = `${this.options.standardFontDataUrl}${filename}`; - const response = await fetch(url); - - if (!response.ok) { - (0, _util.warn)(`fetchStandardFontData: failed to fetch file "${url}" with "${response.statusText}".`); - } else { - data = await response.arrayBuffer(); - } - } else { - try { - data = await this.handler.sendWithPromise("FetchStandardFontData", { - filename - }); - } catch (e) { - (0, _util.warn)(`fetchStandardFontData: failed to fetch file "${filename}" with "${e}".`); - } - } - - if (!data) { - return null; - } - - this.standardFontDataCache.set(name, data); - return new _stream.Stream(data); - } - - async buildFormXObject(resources, xobj, smask, operatorList, task, initialState, localColorSpaceCache) { - const dict = xobj.dict; - const matrix = dict.getArray("Matrix"); - let bbox = dict.getArray("BBox"); - - if (Array.isArray(bbox) && bbox.length === 4) { - bbox = _util.Util.normalizeRect(bbox); - } else { - bbox = null; - } - - let optionalContent, groupOptions; - - if (dict.has("OC")) { - optionalContent = await this.parseMarkedContentProps(dict.get("OC"), resources); - } - - if (optionalContent !== undefined) { - operatorList.addOp(_util.OPS.beginMarkedContentProps, ["OC", optionalContent]); - } - - const group = dict.get("Group"); - - if (group) { - groupOptions = { - matrix, - bbox, - smask, - isolated: false, - knockout: false - }; - const groupSubtype = group.get("S"); - let colorSpace = null; - - if ((0, _primitives.isName)(groupSubtype, "Transparency")) { - groupOptions.isolated = group.get("I") || false; - groupOptions.knockout = group.get("K") || false; - - if (group.has("CS")) { - const cs = group.getRaw("CS"); - - const cachedColorSpace = _colorspace.ColorSpace.getCached(cs, this.xref, localColorSpaceCache); - - if (cachedColorSpace) { - colorSpace = cachedColorSpace; - } else { - colorSpace = await this.parseColorSpace({ - cs, - resources, - localColorSpaceCache - }); - } - } - } - - if (smask && smask.backdrop) { - colorSpace = colorSpace || _colorspace.ColorSpace.singletons.rgb; - smask.backdrop = colorSpace.getRgb(smask.backdrop, 0); - } - - operatorList.addOp(_util.OPS.beginGroup, [groupOptions]); - } - - const args = group ? [matrix, null] : [matrix, bbox]; - operatorList.addOp(_util.OPS.paintFormXObjectBegin, args); - return this.getOperatorList({ - stream: xobj, - task, - resources: dict.get("Resources") || resources, - operatorList, - initialState - }).then(function () { - operatorList.addOp(_util.OPS.paintFormXObjectEnd, []); - - if (group) { - operatorList.addOp(_util.OPS.endGroup, [groupOptions]); - } - - if (optionalContent !== undefined) { - operatorList.addOp(_util.OPS.endMarkedContent, []); - } - }); - } - - _sendImgData(objId, imgData, cacheGlobally = false) { - const transfers = imgData ? [imgData.data.buffer] : null; - - if (this.parsingType3Font || cacheGlobally) { - return this.handler.send("commonobj", [objId, "Image", imgData], transfers); - } - - return this.handler.send("obj", [objId, this.pageIndex, "Image", imgData], transfers); - } - - async buildPaintImageXObject({ - resources, - image, - isInline = false, - operatorList, - cacheKey, - localImageCache, - localColorSpaceCache - }) { - const dict = image.dict; - const imageRef = dict.objId; - const w = dict.get("W", "Width"); - const h = dict.get("H", "Height"); - - if (!(w && (0, _util.isNum)(w)) || !(h && (0, _util.isNum)(h))) { - (0, _util.warn)("Image dimensions are missing, or not numbers."); - return; - } - - const maxImageSize = this.options.maxImageSize; - - if (maxImageSize !== -1 && w * h > maxImageSize) { - (0, _util.warn)("Image exceeded maximum allowed size and was removed."); - return; - } - - let optionalContent; - - if (dict.has("OC")) { - optionalContent = await this.parseMarkedContentProps(dict.get("OC"), resources); - } - - if (optionalContent !== undefined) { - operatorList.addOp(_util.OPS.beginMarkedContentProps, ["OC", optionalContent]); - } - - const imageMask = dict.get("IM", "ImageMask") || false; - const interpolate = dict.get("I", "Interpolate"); - let imgData, args; - - if (imageMask) { - const bitStrideLength = w + 7 >> 3; - const imgArray = image.getBytes(bitStrideLength * h, true); - const decode = dict.getArray("D", "Decode"); - imgData = _image.PDFImage.createMask({ - imgArray, - width: w, - height: h, - imageIsFromDecodeStream: image instanceof _decode_stream.DecodeStream, - inverseDecode: !!decode && decode[0] > 0, - interpolate - }); - imgData.cached = !!cacheKey; - args = [imgData]; - operatorList.addOp(_util.OPS.paintImageMaskXObject, args); - - if (cacheKey) { - localImageCache.set(cacheKey, imageRef, { - fn: _util.OPS.paintImageMaskXObject, - args - }); - } - - if (optionalContent !== undefined) { - operatorList.addOp(_util.OPS.endMarkedContent, []); - } - - return; - } - - const softMask = dict.get("SM", "SMask") || false; - const mask = dict.get("Mask") || false; - const SMALL_IMAGE_DIMENSIONS = 200; - - if (isInline && !softMask && !mask && w + h < SMALL_IMAGE_DIMENSIONS) { - const imageObj = new _image.PDFImage({ - xref: this.xref, - res: resources, - image, - isInline, - pdfFunctionFactory: this._pdfFunctionFactory, - localColorSpaceCache - }); - imgData = imageObj.createImageData(true); - operatorList.addOp(_util.OPS.paintInlineImageXObject, [imgData]); - - if (optionalContent !== undefined) { - operatorList.addOp(_util.OPS.endMarkedContent, []); - } - - return; - } - - let objId = `img_${this.idFactory.createObjId()}`, - cacheGlobally = false; - - if (this.parsingType3Font) { - objId = `${this.idFactory.getDocId()}_type3_${objId}`; - } else if (imageRef) { - cacheGlobally = this.globalImageCache.shouldCache(imageRef, this.pageIndex); - - if (cacheGlobally) { - objId = `${this.idFactory.getDocId()}_${objId}`; - } - } - - operatorList.addDependency(objId); - args = [objId, w, h]; - - _image.PDFImage.buildImage({ - xref: this.xref, - res: resources, - image, - isInline, - pdfFunctionFactory: this._pdfFunctionFactory, - localColorSpaceCache - }).then(imageObj => { - imgData = imageObj.createImageData(false); - - if (cacheKey && imageRef && cacheGlobally) { - this.globalImageCache.addByteSize(imageRef, imgData.data.length); - } - - return this._sendImgData(objId, imgData, cacheGlobally); - }).catch(reason => { - (0, _util.warn)(`Unable to decode image "${objId}": "${reason}".`); - return this._sendImgData(objId, null, cacheGlobally); - }); - - operatorList.addOp(_util.OPS.paintImageXObject, args); - - if (cacheKey) { - localImageCache.set(cacheKey, imageRef, { - fn: _util.OPS.paintImageXObject, - args - }); - - if (imageRef) { - (0, _util.assert)(!isInline, "Cannot cache an inline image globally."); - this.globalImageCache.addPageIndex(imageRef, this.pageIndex); - - if (cacheGlobally) { - this.globalImageCache.setData(imageRef, { - objId, - fn: _util.OPS.paintImageXObject, - args, - byteSize: 0 - }); - } - } - } - - if (optionalContent !== undefined) { - operatorList.addOp(_util.OPS.endMarkedContent, []); - } - } - - handleSMask(smask, resources, operatorList, task, stateManager, localColorSpaceCache) { - const smaskContent = smask.get("G"); - const smaskOptions = { - subtype: smask.get("S").name, - backdrop: smask.get("BC") - }; - const transferObj = smask.get("TR"); - - if ((0, _function.isPDFFunction)(transferObj)) { - const transferFn = this._pdfFunctionFactory.create(transferObj); - - const transferMap = new Uint8Array(256); - const tmp = new Float32Array(1); - - for (let i = 0; i < 256; i++) { - tmp[0] = i / 255; - transferFn(tmp, 0, tmp, 0); - transferMap[i] = tmp[0] * 255 | 0; - } - - smaskOptions.transferMap = transferMap; - } - - return this.buildFormXObject(resources, smaskContent, smaskOptions, operatorList, task, stateManager.state.clone(), localColorSpaceCache); - } - - handleTransferFunction(tr) { - let transferArray; - - if (Array.isArray(tr)) { - transferArray = tr; - } else if ((0, _function.isPDFFunction)(tr)) { - transferArray = [tr]; - } else { - return null; - } - - const transferMaps = []; - let numFns = 0, - numEffectfulFns = 0; - - for (const entry of transferArray) { - const transferObj = this.xref.fetchIfRef(entry); - numFns++; - - if ((0, _primitives.isName)(transferObj, "Identity")) { - transferMaps.push(null); - continue; - } else if (!(0, _function.isPDFFunction)(transferObj)) { - return null; - } - - const transferFn = this._pdfFunctionFactory.create(transferObj); - - const transferMap = new Uint8Array(256), - tmp = new Float32Array(1); - - for (let j = 0; j < 256; j++) { - tmp[0] = j / 255; - transferFn(tmp, 0, tmp, 0); - transferMap[j] = tmp[0] * 255 | 0; - } - - transferMaps.push(transferMap); - numEffectfulFns++; - } - - if (!(numFns === 1 || numFns === 4)) { - return null; - } - - if (numEffectfulFns === 0) { - return null; - } - - return transferMaps; - } - - handleTilingType(fn, color, resources, pattern, patternDict, operatorList, task, localTilingPatternCache) { - const tilingOpList = new _operator_list.OperatorList(); - - const patternResources = _primitives.Dict.merge({ - xref: this.xref, - dictArray: [patternDict.get("Resources"), resources] - }); - - return this.getOperatorList({ - stream: pattern, - task, - resources: patternResources, - operatorList: tilingOpList - }).then(function () { - const operatorListIR = tilingOpList.getIR(); - const tilingPatternIR = (0, _pattern.getTilingPatternIR)(operatorListIR, patternDict, color); - operatorList.addDependencies(tilingOpList.dependencies); - operatorList.addOp(fn, tilingPatternIR); - - if (patternDict.objId) { - localTilingPatternCache.set(null, patternDict.objId, { - operatorListIR, - dict: patternDict - }); - } - }).catch(reason => { - if (reason instanceof _util.AbortException) { - return; - } - - if (this.options.ignoreErrors) { - this.handler.send("UnsupportedFeature", { - featureId: _util.UNSUPPORTED_FEATURES.errorTilingPattern - }); - (0, _util.warn)(`handleTilingType - ignoring pattern: "${reason}".`); - return; - } - - throw reason; - }); - } - - handleSetFont(resources, fontArgs, fontRef, operatorList, task, state, fallbackFontDict = null, cssFontInfo = null) { - const fontName = fontArgs && fontArgs[0] instanceof _primitives.Name ? fontArgs[0].name : null; - return this.loadFont(fontName, fontRef, resources, fallbackFontDict, cssFontInfo).then(translated => { - if (!translated.font.isType3Font) { - return translated; - } - - return translated.loadType3Data(this, resources, task).then(function () { - operatorList.addDependencies(translated.type3Dependencies); - return translated; - }).catch(reason => { - this.handler.send("UnsupportedFeature", { - featureId: _util.UNSUPPORTED_FEATURES.errorFontLoadType3 - }); - return new TranslatedFont({ - loadedName: "g_font_error", - font: new _fonts.ErrorFont(`Type3 font load error: ${reason}`), - dict: translated.font, - evaluatorOptions: this.options - }); - }); - }).then(translated => { - state.font = translated.font; - translated.send(this.handler); - return translated.loadedName; - }); - } - - handleText(chars, state) { - const font = state.font; - const glyphs = font.charsToGlyphs(chars); - - if (font.data) { - const isAddToPathSet = !!(state.textRenderingMode & _util.TextRenderingMode.ADD_TO_PATH_FLAG); - - if (isAddToPathSet || state.fillColorSpace.name === "Pattern" || font.disableFontFace || this.options.disableFontFace) { - PartialEvaluator.buildFontPaths(font, glyphs, this.handler, this.options); - } - } - - return glyphs; - } - - ensureStateFont(state) { - if (state.font) { - return; - } - - const reason = new _util.FormatError("Missing setFont (Tf) operator before text rendering operator."); - - if (this.options.ignoreErrors) { - this.handler.send("UnsupportedFeature", { - featureId: _util.UNSUPPORTED_FEATURES.errorFontState - }); - (0, _util.warn)(`ensureStateFont: "${reason}".`); - return; - } - - throw reason; - } - - async setGState({ - resources, - gState, - operatorList, - cacheKey, - task, - stateManager, - localGStateCache, - localColorSpaceCache - }) { - const gStateRef = gState.objId; - let isSimpleGState = true; - const gStateObj = []; - const gStateKeys = gState.getKeys(); - let promise = Promise.resolve(); - - for (let i = 0, ii = gStateKeys.length; i < ii; i++) { - const key = gStateKeys[i]; - const value = gState.get(key); - - switch (key) { - case "Type": - break; - - case "LW": - case "LC": - case "LJ": - case "ML": - case "D": - case "RI": - case "FL": - case "CA": - case "ca": - gStateObj.push([key, value]); - break; - - case "Font": - isSimpleGState = false; - promise = promise.then(() => { - return this.handleSetFont(resources, null, value[0], operatorList, task, stateManager.state).then(function (loadedName) { - operatorList.addDependency(loadedName); - gStateObj.push([key, [loadedName, value[1]]]); - }); - }); - break; - - case "BM": - gStateObj.push([key, normalizeBlendMode(value)]); - break; - - case "SMask": - if ((0, _primitives.isName)(value, "None")) { - gStateObj.push([key, false]); - break; - } - - if ((0, _primitives.isDict)(value)) { - isSimpleGState = false; - promise = promise.then(() => { - return this.handleSMask(value, resources, operatorList, task, stateManager, localColorSpaceCache); - }); - gStateObj.push([key, true]); - } else { - (0, _util.warn)("Unsupported SMask type"); - } - - break; - - case "TR": - const transferMaps = this.handleTransferFunction(value); - gStateObj.push([key, transferMaps]); - break; - - case "OP": - case "op": - case "OPM": - case "BG": - case "BG2": - case "UCR": - case "UCR2": - case "TR2": - case "HT": - case "SM": - case "SA": - case "AIS": - case "TK": - (0, _util.info)("graphic state operator " + key); - break; - - default: - (0, _util.info)("Unknown graphic state operator " + key); - break; - } - } - - return promise.then(function () { - if (gStateObj.length > 0) { - operatorList.addOp(_util.OPS.setGState, [gStateObj]); - } - - if (isSimpleGState) { - localGStateCache.set(cacheKey, gStateRef, gStateObj); - } - }); - } - - loadFont(fontName, font, resources, fallbackFontDict = null, cssFontInfo = null) { - const errorFont = async () => { - return new TranslatedFont({ - loadedName: "g_font_error", - font: new _fonts.ErrorFont(`Font "${fontName}" is not available.`), - dict: font, - evaluatorOptions: this.options - }); - }; - - const xref = this.xref; - let fontRef; - - if (font) { - if (!(0, _primitives.isRef)(font)) { - throw new _util.FormatError('The "font" object should be a reference.'); - } - - fontRef = font; - } else { - const fontRes = resources.get("Font"); - - if (fontRes) { - fontRef = fontRes.getRaw(fontName); - } - } - - if (!fontRef) { - const partialMsg = `Font "${fontName || font && font.toString()}" is not available`; - - if (!this.options.ignoreErrors && !this.parsingType3Font) { - (0, _util.warn)(`${partialMsg}.`); - return errorFont(); - } - - this.handler.send("UnsupportedFeature", { - featureId: _util.UNSUPPORTED_FEATURES.errorFontMissing - }); - (0, _util.warn)(`${partialMsg} -- attempting to fallback to a default font.`); - - if (fallbackFontDict) { - fontRef = fallbackFontDict; - } else { - fontRef = PartialEvaluator.fallbackFontDict; - } - } - - if (this.fontCache.has(fontRef)) { - return this.fontCache.get(fontRef); - } - - font = xref.fetchIfRef(fontRef); - - if (!(0, _primitives.isDict)(font)) { - return errorFont(); - } - - if (font.cacheKey && this.fontCache.has(font.cacheKey)) { - return this.fontCache.get(font.cacheKey); - } - - const fontCapability = (0, _util.createPromiseCapability)(); - let preEvaluatedFont; - - try { - preEvaluatedFont = this.preEvaluateFont(font); - preEvaluatedFont.cssFontInfo = cssFontInfo; - } catch (reason) { - (0, _util.warn)(`loadFont - preEvaluateFont failed: "${reason}".`); - return errorFont(); - } - - const { - descriptor, - hash - } = preEvaluatedFont; - const fontRefIsRef = (0, _primitives.isRef)(fontRef); - let fontID; - - if (fontRefIsRef) { - fontID = `f${fontRef.toString()}`; - } - - if (hash && (0, _primitives.isDict)(descriptor)) { - if (!descriptor.fontAliases) { - descriptor.fontAliases = Object.create(null); - } - - const fontAliases = descriptor.fontAliases; - - if (fontAliases[hash]) { - const aliasFontRef = fontAliases[hash].aliasRef; - - if (fontRefIsRef && aliasFontRef && this.fontCache.has(aliasFontRef)) { - this.fontCache.putAlias(fontRef, aliasFontRef); - return this.fontCache.get(fontRef); - } - } else { - fontAliases[hash] = { - fontID: this.idFactory.createFontId() - }; - } - - if (fontRefIsRef) { - fontAliases[hash].aliasRef = fontRef; - } - - fontID = fontAliases[hash].fontID; - } - - if (fontRefIsRef) { - this.fontCache.put(fontRef, fontCapability.promise); - } else { - if (!fontID) { - fontID = this.idFactory.createFontId(); - } - - font.cacheKey = `cacheKey_${fontID}`; - this.fontCache.put(font.cacheKey, fontCapability.promise); - } - - (0, _util.assert)(fontID && fontID.startsWith("f"), 'The "fontID" must be (correctly) defined.'); - font.loadedName = `${this.idFactory.getDocId()}_${fontID}`; - this.translateFont(preEvaluatedFont).then(translatedFont => { - if (translatedFont.fontType !== undefined) { - xref.stats.addFontType(translatedFont.fontType); - } - - fontCapability.resolve(new TranslatedFont({ - loadedName: font.loadedName, - font: translatedFont, - dict: font, - evaluatorOptions: this.options - })); - }).catch(reason => { - this.handler.send("UnsupportedFeature", { - featureId: _util.UNSUPPORTED_FEATURES.errorFontTranslate - }); - (0, _util.warn)(`loadFont - translateFont failed: "${reason}".`); - - try { - const fontFile3 = descriptor && descriptor.get("FontFile3"); - const subtype = fontFile3 && fontFile3.get("Subtype"); - const fontType = (0, _fonts_utils.getFontType)(preEvaluatedFont.type, subtype && subtype.name); - - if (fontType !== undefined) { - xref.stats.addFontType(fontType); - } - } catch (ex) {} - - fontCapability.resolve(new TranslatedFont({ - loadedName: font.loadedName, - font: new _fonts.ErrorFont(reason instanceof Error ? reason.message : reason), - dict: font, - evaluatorOptions: this.options - })); - }); - return fontCapability.promise; - } - - buildPath(operatorList, fn, args, parsingText = false) { - const lastIndex = operatorList.length - 1; - - if (!args) { - args = []; - } - - if (lastIndex < 0 || operatorList.fnArray[lastIndex] !== _util.OPS.constructPath) { - if (parsingText) { - (0, _util.warn)(`Encountered path operator "${fn}" inside of a text object.`); - operatorList.addOp(_util.OPS.save, null); - } - - operatorList.addOp(_util.OPS.constructPath, [[fn], args]); - - if (parsingText) { - operatorList.addOp(_util.OPS.restore, null); - } - } else { - const opArgs = operatorList.argsArray[lastIndex]; - opArgs[0].push(fn); - Array.prototype.push.apply(opArgs[1], args); - } - } - - parseColorSpace({ - cs, - resources, - localColorSpaceCache - }) { - return _colorspace.ColorSpace.parseAsync({ - cs, - xref: this.xref, - resources, - pdfFunctionFactory: this._pdfFunctionFactory, - localColorSpaceCache - }).catch(reason => { - if (reason instanceof _util.AbortException) { - return null; - } - - if (this.options.ignoreErrors) { - this.handler.send("UnsupportedFeature", { - featureId: _util.UNSUPPORTED_FEATURES.errorColorSpace - }); - (0, _util.warn)(`parseColorSpace - ignoring ColorSpace: "${reason}".`); - return null; - } - - throw reason; - }); - } - - parseShading({ - shading, - resources, - localColorSpaceCache, - localShadingPatternCache - }) { - let id = localShadingPatternCache.get(shading); - - if (!id) { - var shadingFill = _pattern.Pattern.parseShading(shading, this.xref, resources, this.handler, this._pdfFunctionFactory, localColorSpaceCache); - - const patternIR = shadingFill.getIR(); - id = `pattern_${this.idFactory.createObjId()}`; - localShadingPatternCache.set(shading, id); - this.handler.send("obj", [id, this.pageIndex, "Pattern", patternIR]); - } - - return id; - } - - handleColorN(operatorList, fn, args, cs, patterns, resources, task, localColorSpaceCache, localTilingPatternCache, localShadingPatternCache) { - const patternName = args.pop(); - - if (patternName instanceof _primitives.Name) { - const rawPattern = patterns.getRaw(patternName.name); - const localTilingPattern = rawPattern instanceof _primitives.Ref && localTilingPatternCache.getByRef(rawPattern); - - if (localTilingPattern) { - try { - const color = cs.base ? cs.base.getRgb(args, 0) : null; - const tilingPatternIR = (0, _pattern.getTilingPatternIR)(localTilingPattern.operatorListIR, localTilingPattern.dict, color); - operatorList.addOp(fn, tilingPatternIR); - return undefined; - } catch (ex) {} - } - - const pattern = this.xref.fetchIfRef(rawPattern); - - if (pattern) { - const dict = (0, _primitives.isStream)(pattern) ? pattern.dict : pattern; - const typeNum = dict.get("PatternType"); - - if (typeNum === PatternType.TILING) { - const color = cs.base ? cs.base.getRgb(args, 0) : null; - return this.handleTilingType(fn, color, resources, pattern, dict, operatorList, task, localTilingPatternCache); - } else if (typeNum === PatternType.SHADING) { - const shading = dict.get("Shading"); - const matrix = dict.getArray("Matrix"); - const objId = this.parseShading({ - shading, - resources, - localColorSpaceCache, - localShadingPatternCache - }); - operatorList.addOp(fn, ["Shading", objId, matrix]); - return undefined; - } - - throw new _util.FormatError(`Unknown PatternType: ${typeNum}`); - } - } - - throw new _util.FormatError(`Unknown PatternName: ${patternName}`); - } - - _parseVisibilityExpression(array, nestingCounter, currentResult) { - const MAX_NESTING = 10; - - if (++nestingCounter > MAX_NESTING) { - (0, _util.warn)("Visibility expression is too deeply nested"); - return; - } - - const length = array.length; - const operator = this.xref.fetchIfRef(array[0]); - - if (length < 2 || !(0, _primitives.isName)(operator)) { - (0, _util.warn)("Invalid visibility expression"); - return; - } - - switch (operator.name) { - case "And": - case "Or": - case "Not": - currentResult.push(operator.name); - break; - - default: - (0, _util.warn)(`Invalid operator ${operator.name} in visibility expression`); - return; - } - - for (let i = 1; i < length; i++) { - const raw = array[i]; - const object = this.xref.fetchIfRef(raw); - - if (Array.isArray(object)) { - const nestedResult = []; - currentResult.push(nestedResult); - - this._parseVisibilityExpression(object, nestingCounter, nestedResult); - } else if ((0, _primitives.isRef)(raw)) { - currentResult.push(raw.toString()); - } - } - } - - async parseMarkedContentProps(contentProperties, resources) { - let optionalContent; - - if ((0, _primitives.isName)(contentProperties)) { - const properties = resources.get("Properties"); - optionalContent = properties.get(contentProperties.name); - } else if ((0, _primitives.isDict)(contentProperties)) { - optionalContent = contentProperties; - } else { - throw new _util.FormatError("Optional content properties malformed."); - } - - const optionalContentType = optionalContent.get("Type").name; - - if (optionalContentType === "OCG") { - return { - type: optionalContentType, - id: optionalContent.objId - }; - } else if (optionalContentType === "OCMD") { - const expression = optionalContent.get("VE"); - - if (Array.isArray(expression)) { - const result = []; - - this._parseVisibilityExpression(expression, 0, result); - - if (result.length > 0) { - return { - type: "OCMD", - expression: result - }; - } - } - - const optionalContentGroups = optionalContent.get("OCGs"); - - if (Array.isArray(optionalContentGroups) || (0, _primitives.isDict)(optionalContentGroups)) { - const groupIds = []; - - if (Array.isArray(optionalContentGroups)) { - for (const ocg of optionalContentGroups) { - groupIds.push(ocg.toString()); - } - } else { - groupIds.push(optionalContentGroups.objId); - } - - return { - type: optionalContentType, - ids: groupIds, - policy: (0, _primitives.isName)(optionalContent.get("P")) ? optionalContent.get("P").name : null, - expression: null - }; - } else if ((0, _primitives.isRef)(optionalContentGroups)) { - return { - type: optionalContentType, - id: optionalContentGroups.toString() - }; - } - } - - return null; - } - - getOperatorList({ - stream, - task, - resources, - operatorList, - initialState = null, - fallbackFontDict = null - }) { - resources = resources || _primitives.Dict.empty; - initialState = initialState || new EvalState(); - - if (!operatorList) { - throw new Error('getOperatorList: missing "operatorList" parameter'); - } - - const self = this; - const xref = this.xref; - let parsingText = false; - const localImageCache = new _image_utils.LocalImageCache(); - const localColorSpaceCache = new _image_utils.LocalColorSpaceCache(); - const localGStateCache = new _image_utils.LocalGStateCache(); - const localTilingPatternCache = new _image_utils.LocalTilingPatternCache(); - const localShadingPatternCache = new Map(); - - const xobjs = resources.get("XObject") || _primitives.Dict.empty; - - const patterns = resources.get("Pattern") || _primitives.Dict.empty; - - const stateManager = new StateManager(initialState); - const preprocessor = new EvaluatorPreprocessor(stream, xref, stateManager); - const timeSlotManager = new TimeSlotManager(); - - function closePendingRestoreOPS(argument) { - for (let i = 0, ii = preprocessor.savedStatesDepth; i < ii; i++) { - operatorList.addOp(_util.OPS.restore, []); - } - } - - return new Promise(function promiseBody(resolve, reject) { - const next = function (promise) { - Promise.all([promise, operatorList.ready]).then(function () { - try { - promiseBody(resolve, reject); - } catch (ex) { - reject(ex); - } - }, reject); - }; - - task.ensureNotTerminated(); - timeSlotManager.reset(); - const operation = {}; - let stop, i, ii, cs, name, isValidName; - - while (!(stop = timeSlotManager.check())) { - operation.args = null; - - if (!preprocessor.read(operation)) { - break; - } - - let args = operation.args; - let fn = operation.fn; - - switch (fn | 0) { - case _util.OPS.paintXObject: - isValidName = args[0] instanceof _primitives.Name; - name = args[0].name; - - if (isValidName) { - const localImage = localImageCache.getByName(name); - - if (localImage) { - operatorList.addOp(localImage.fn, localImage.args); - args = null; - continue; - } - } - - next(new Promise(function (resolveXObject, rejectXObject) { - if (!isValidName) { - throw new _util.FormatError("XObject must be referred to by name."); - } - - let xobj = xobjs.getRaw(name); - - if (xobj instanceof _primitives.Ref) { - const localImage = localImageCache.getByRef(xobj); - - if (localImage) { - operatorList.addOp(localImage.fn, localImage.args); - resolveXObject(); - return; - } - - const globalImage = self.globalImageCache.getData(xobj, self.pageIndex); - - if (globalImage) { - operatorList.addDependency(globalImage.objId); - operatorList.addOp(globalImage.fn, globalImage.args); - resolveXObject(); - return; - } - - xobj = xref.fetch(xobj); - } - - if (!(0, _primitives.isStream)(xobj)) { - throw new _util.FormatError("XObject should be a stream"); - } - - const type = xobj.dict.get("Subtype"); - - if (!(0, _primitives.isName)(type)) { - throw new _util.FormatError("XObject should have a Name subtype"); - } - - if (type.name === "Form") { - stateManager.save(); - self.buildFormXObject(resources, xobj, null, operatorList, task, stateManager.state.clone(), localColorSpaceCache).then(function () { - stateManager.restore(); - resolveXObject(); - }, rejectXObject); - return; - } else if (type.name === "Image") { - self.buildPaintImageXObject({ - resources, - image: xobj, - operatorList, - cacheKey: name, - localImageCache, - localColorSpaceCache - }).then(resolveXObject, rejectXObject); - return; - } else if (type.name === "PS") { - (0, _util.info)("Ignored XObject subtype PS"); - } else { - throw new _util.FormatError(`Unhandled XObject subtype ${type.name}`); - } - - resolveXObject(); - }).catch(function (reason) { - if (reason instanceof _util.AbortException) { - return; - } - - if (self.options.ignoreErrors) { - self.handler.send("UnsupportedFeature", { - featureId: _util.UNSUPPORTED_FEATURES.errorXObject - }); - (0, _util.warn)(`getOperatorList - ignoring XObject: "${reason}".`); - return; - } - - throw reason; - })); - return; - - case _util.OPS.setFont: - var fontSize = args[1]; - next(self.handleSetFont(resources, args, null, operatorList, task, stateManager.state, fallbackFontDict).then(function (loadedName) { - operatorList.addDependency(loadedName); - operatorList.addOp(_util.OPS.setFont, [loadedName, fontSize]); - })); - return; - - case _util.OPS.beginText: - parsingText = true; - break; - - case _util.OPS.endText: - parsingText = false; - break; - - case _util.OPS.endInlineImage: - var cacheKey = args[0].cacheKey; - - if (cacheKey) { - const localImage = localImageCache.getByName(cacheKey); - - if (localImage) { - operatorList.addOp(localImage.fn, localImage.args); - args = null; - continue; - } - } - - next(self.buildPaintImageXObject({ - resources, - image: args[0], - isInline: true, - operatorList, - cacheKey, - localImageCache, - localColorSpaceCache - })); - return; - - case _util.OPS.showText: - if (!stateManager.state.font) { - self.ensureStateFont(stateManager.state); - continue; - } - - args[0] = self.handleText(args[0], stateManager.state); - break; - - case _util.OPS.showSpacedText: - if (!stateManager.state.font) { - self.ensureStateFont(stateManager.state); - continue; - } - - var arr = args[0]; - var combinedGlyphs = []; - var arrLength = arr.length; - var state = stateManager.state; - - for (i = 0; i < arrLength; ++i) { - const arrItem = arr[i]; - - if ((0, _util.isString)(arrItem)) { - Array.prototype.push.apply(combinedGlyphs, self.handleText(arrItem, state)); - } else if ((0, _util.isNum)(arrItem)) { - combinedGlyphs.push(arrItem); - } - } - - args[0] = combinedGlyphs; - fn = _util.OPS.showText; - break; - - case _util.OPS.nextLineShowText: - if (!stateManager.state.font) { - self.ensureStateFont(stateManager.state); - continue; - } - - operatorList.addOp(_util.OPS.nextLine); - args[0] = self.handleText(args[0], stateManager.state); - fn = _util.OPS.showText; - break; - - case _util.OPS.nextLineSetSpacingShowText: - if (!stateManager.state.font) { - self.ensureStateFont(stateManager.state); - continue; - } - - operatorList.addOp(_util.OPS.nextLine); - operatorList.addOp(_util.OPS.setWordSpacing, [args.shift()]); - operatorList.addOp(_util.OPS.setCharSpacing, [args.shift()]); - args[0] = self.handleText(args[0], stateManager.state); - fn = _util.OPS.showText; - break; - - case _util.OPS.setTextRenderingMode: - stateManager.state.textRenderingMode = args[0]; - break; - - case _util.OPS.setFillColorSpace: - { - const cachedColorSpace = _colorspace.ColorSpace.getCached(args[0], xref, localColorSpaceCache); - - if (cachedColorSpace) { - stateManager.state.fillColorSpace = cachedColorSpace; - continue; - } - - next(self.parseColorSpace({ - cs: args[0], - resources, - localColorSpaceCache - }).then(function (colorSpace) { - if (colorSpace) { - stateManager.state.fillColorSpace = colorSpace; - } - })); - return; - } - - case _util.OPS.setStrokeColorSpace: - { - const cachedColorSpace = _colorspace.ColorSpace.getCached(args[0], xref, localColorSpaceCache); - - if (cachedColorSpace) { - stateManager.state.strokeColorSpace = cachedColorSpace; - continue; - } - - next(self.parseColorSpace({ - cs: args[0], - resources, - localColorSpaceCache - }).then(function (colorSpace) { - if (colorSpace) { - stateManager.state.strokeColorSpace = colorSpace; - } - })); - return; - } - - case _util.OPS.setFillColor: - cs = stateManager.state.fillColorSpace; - args = cs.getRgb(args, 0); - fn = _util.OPS.setFillRGBColor; - break; - - case _util.OPS.setStrokeColor: - cs = stateManager.state.strokeColorSpace; - args = cs.getRgb(args, 0); - fn = _util.OPS.setStrokeRGBColor; - break; - - case _util.OPS.setFillGray: - stateManager.state.fillColorSpace = _colorspace.ColorSpace.singletons.gray; - args = _colorspace.ColorSpace.singletons.gray.getRgb(args, 0); - fn = _util.OPS.setFillRGBColor; - break; - - case _util.OPS.setStrokeGray: - stateManager.state.strokeColorSpace = _colorspace.ColorSpace.singletons.gray; - args = _colorspace.ColorSpace.singletons.gray.getRgb(args, 0); - fn = _util.OPS.setStrokeRGBColor; - break; - - case _util.OPS.setFillCMYKColor: - stateManager.state.fillColorSpace = _colorspace.ColorSpace.singletons.cmyk; - args = _colorspace.ColorSpace.singletons.cmyk.getRgb(args, 0); - fn = _util.OPS.setFillRGBColor; - break; - - case _util.OPS.setStrokeCMYKColor: - stateManager.state.strokeColorSpace = _colorspace.ColorSpace.singletons.cmyk; - args = _colorspace.ColorSpace.singletons.cmyk.getRgb(args, 0); - fn = _util.OPS.setStrokeRGBColor; - break; - - case _util.OPS.setFillRGBColor: - stateManager.state.fillColorSpace = _colorspace.ColorSpace.singletons.rgb; - args = _colorspace.ColorSpace.singletons.rgb.getRgb(args, 0); - break; - - case _util.OPS.setStrokeRGBColor: - stateManager.state.strokeColorSpace = _colorspace.ColorSpace.singletons.rgb; - args = _colorspace.ColorSpace.singletons.rgb.getRgb(args, 0); - break; - - case _util.OPS.setFillColorN: - cs = stateManager.state.fillColorSpace; - - if (cs.name === "Pattern") { - next(self.handleColorN(operatorList, _util.OPS.setFillColorN, args, cs, patterns, resources, task, localColorSpaceCache, localTilingPatternCache, localShadingPatternCache)); - return; - } - - args = cs.getRgb(args, 0); - fn = _util.OPS.setFillRGBColor; - break; - - case _util.OPS.setStrokeColorN: - cs = stateManager.state.strokeColorSpace; - - if (cs.name === "Pattern") { - next(self.handleColorN(operatorList, _util.OPS.setStrokeColorN, args, cs, patterns, resources, task, localColorSpaceCache, localTilingPatternCache, localShadingPatternCache)); - return; - } - - args = cs.getRgb(args, 0); - fn = _util.OPS.setStrokeRGBColor; - break; - - case _util.OPS.shadingFill: - var shadingRes = resources.get("Shading"); - - if (!shadingRes) { - throw new _util.FormatError("No shading resource found"); - } - - var shading = shadingRes.get(args[0].name); - - if (!shading) { - throw new _util.FormatError("No shading object found"); - } - - const patternId = self.parseShading({ - shading, - resources, - localColorSpaceCache, - localShadingPatternCache - }); - args = [patternId]; - fn = _util.OPS.shadingFill; - break; - - case _util.OPS.setGState: - isValidName = args[0] instanceof _primitives.Name; - name = args[0].name; - - if (isValidName) { - const localGStateObj = localGStateCache.getByName(name); - - if (localGStateObj) { - if (localGStateObj.length > 0) { - operatorList.addOp(_util.OPS.setGState, [localGStateObj]); - } - - args = null; - continue; - } - } - - next(new Promise(function (resolveGState, rejectGState) { - if (!isValidName) { - throw new _util.FormatError("GState must be referred to by name."); - } - - const extGState = resources.get("ExtGState"); - - if (!(extGState instanceof _primitives.Dict)) { - throw new _util.FormatError("ExtGState should be a dictionary."); - } - - const gState = extGState.get(name); - - if (!(gState instanceof _primitives.Dict)) { - throw new _util.FormatError("GState should be a dictionary."); - } - - self.setGState({ - resources, - gState, - operatorList, - cacheKey: name, - task, - stateManager, - localGStateCache, - localColorSpaceCache - }).then(resolveGState, rejectGState); - }).catch(function (reason) { - if (reason instanceof _util.AbortException) { - return; - } - - if (self.options.ignoreErrors) { - self.handler.send("UnsupportedFeature", { - featureId: _util.UNSUPPORTED_FEATURES.errorExtGState - }); - (0, _util.warn)(`getOperatorList - ignoring ExtGState: "${reason}".`); - return; - } - - throw reason; - })); - return; - - case _util.OPS.moveTo: - case _util.OPS.lineTo: - case _util.OPS.curveTo: - case _util.OPS.curveTo2: - case _util.OPS.curveTo3: - case _util.OPS.closePath: - case _util.OPS.rectangle: - self.buildPath(operatorList, fn, args, parsingText); - continue; - - case _util.OPS.markPoint: - case _util.OPS.markPointProps: - case _util.OPS.beginCompat: - case _util.OPS.endCompat: - continue; - - case _util.OPS.beginMarkedContentProps: - if (!(0, _primitives.isName)(args[0])) { - (0, _util.warn)(`Expected name for beginMarkedContentProps arg0=${args[0]}`); - continue; - } - - if (args[0].name === "OC") { - next(self.parseMarkedContentProps(args[1], resources).then(data => { - operatorList.addOp(_util.OPS.beginMarkedContentProps, ["OC", data]); - }).catch(reason => { - if (reason instanceof _util.AbortException) { - return; - } - - if (self.options.ignoreErrors) { - self.handler.send("UnsupportedFeature", { - featureId: _util.UNSUPPORTED_FEATURES.errorMarkedContent - }); - (0, _util.warn)(`getOperatorList - ignoring beginMarkedContentProps: "${reason}".`); - return; - } - - throw reason; - })); - return; - } - - args = [args[0].name, args[1] instanceof _primitives.Dict ? args[1].get("MCID") : null]; - break; - - case _util.OPS.beginMarkedContent: - case _util.OPS.endMarkedContent: - default: - if (args !== null) { - for (i = 0, ii = args.length; i < ii; i++) { - if (args[i] instanceof _primitives.Dict) { - break; - } - } - - if (i < ii) { - (0, _util.warn)("getOperatorList - ignoring operator: " + fn); - continue; - } - } - - } - - operatorList.addOp(fn, args); - } - - if (stop) { - next(deferred); - return; - } - - closePendingRestoreOPS(); - resolve(); - }).catch(reason => { - if (reason instanceof _util.AbortException) { - return; - } - - if (this.options.ignoreErrors) { - this.handler.send("UnsupportedFeature", { - featureId: _util.UNSUPPORTED_FEATURES.errorOperatorList - }); - (0, _util.warn)(`getOperatorList - ignoring errors during "${task.name}" ` + `task: "${reason}".`); - closePendingRestoreOPS(); - return; - } - - throw reason; - }); - } - - getTextContent({ - stream, - task, - resources, - stateManager = null, - normalizeWhitespace = false, - combineTextItems = false, - includeMarkedContent = false, - sink, - seenStyles = new Set() - }) { - resources = resources || _primitives.Dict.empty; - stateManager = stateManager || new StateManager(new TextState()); - const WhitespaceRegexp = /\s/g; - const DiacriticRegExp = new RegExp("^\\p{Mn}$", "u"); - const NormalizedUnicodes = (0, _unicode.getNormalizedUnicodes)(); - const textContent = { - items: [], - styles: Object.create(null) - }; - const textContentItem = { - initialized: false, - str: [], - totalWidth: 0, - totalHeight: 0, - width: 0, - height: 0, - vertical: false, - prevTransform: null, - textAdvanceScale: 0, - spaceInFlowMin: 0, - spaceInFlowMax: 0, - trackingSpaceMin: Infinity, - negativeSpaceMax: -Infinity, - transform: null, - fontName: null, - hasEOL: false - }; - const TRACKING_SPACE_FACTOR = 0.1; - const NEGATIVE_SPACE_FACTOR = -0.2; - const SPACE_IN_FLOW_MIN_FACTOR = 0.1; - const SPACE_IN_FLOW_MAX_FACTOR = 0.6; - const self = this; - const xref = this.xref; - const showSpacedTextBuffer = []; - let xobjs = null; - const emptyXObjectCache = new _image_utils.LocalImageCache(); - const emptyGStateCache = new _image_utils.LocalGStateCache(); - const preprocessor = new EvaluatorPreprocessor(stream, xref, stateManager); - let textState; - - function getCurrentTextTransform() { - const font = textState.font; - const tsm = [textState.fontSize * textState.textHScale, 0, 0, textState.fontSize, 0, textState.textRise]; - - if (font.isType3Font && (textState.fontSize <= 1 || font.isCharBBox) && !(0, _util.isArrayEqual)(textState.fontMatrix, _util.FONT_IDENTITY_MATRIX)) { - const glyphHeight = font.bbox[3] - font.bbox[1]; - - if (glyphHeight > 0) { - tsm[3] *= glyphHeight * textState.fontMatrix[3]; - } - } - - return _util.Util.transform(textState.ctm, _util.Util.transform(textState.textMatrix, tsm)); - } - - function ensureTextContentItem() { - if (textContentItem.initialized) { - return textContentItem; - } - - const font = textState.font, - loadedName = font.loadedName; - - if (!seenStyles.has(loadedName)) { - seenStyles.add(loadedName); - textContent.styles[loadedName] = { - fontFamily: font.fallbackName, - ascent: font.ascent, - descent: font.descent, - vertical: font.vertical - }; - } - - textContentItem.fontName = loadedName; - const trm = textContentItem.transform = getCurrentTextTransform(); - - if (!font.vertical) { - textContentItem.width = textContentItem.totalWidth = 0; - textContentItem.height = textContentItem.totalHeight = Math.hypot(trm[2], trm[3]); - textContentItem.vertical = false; - } else { - textContentItem.width = textContentItem.totalWidth = Math.hypot(trm[0], trm[1]); - textContentItem.height = textContentItem.totalHeight = 0; - textContentItem.vertical = true; - } - - const scaleLineX = Math.hypot(textState.textLineMatrix[0], textState.textLineMatrix[1]); - const scaleCtmX = Math.hypot(textState.ctm[0], textState.ctm[1]); - textContentItem.textAdvanceScale = scaleCtmX * scaleLineX; - textContentItem.trackingSpaceMin = textState.fontSize * TRACKING_SPACE_FACTOR; - textContentItem.negativeSpaceMax = textState.fontSize * NEGATIVE_SPACE_FACTOR; - textContentItem.spaceInFlowMin = textState.fontSize * SPACE_IN_FLOW_MIN_FACTOR; - textContentItem.spaceInFlowMax = textState.fontSize * SPACE_IN_FLOW_MAX_FACTOR; - textContentItem.hasEOL = false; - textContentItem.initialized = true; - return textContentItem; - } - - function updateAdvanceScale() { - if (!textContentItem.initialized) { - return; - } - - const scaleLineX = Math.hypot(textState.textLineMatrix[0], textState.textLineMatrix[1]); - const scaleCtmX = Math.hypot(textState.ctm[0], textState.ctm[1]); - const scaleFactor = scaleCtmX * scaleLineX; - - if (scaleFactor === textContentItem.textAdvanceScale) { - return; - } - - if (!textContentItem.vertical) { - textContentItem.totalWidth += textContentItem.width * textContentItem.textAdvanceScale; - textContentItem.width = 0; - } else { - textContentItem.totalHeight += textContentItem.height * textContentItem.textAdvanceScale; - textContentItem.height = 0; - } - - textContentItem.textAdvanceScale = scaleFactor; - } - - function replaceWhitespace(str) { - const ii = str.length; - let i = 0, - code; - - while (i < ii && (code = str.charCodeAt(i)) >= 0x20 && code <= 0x7f) { - i++; - } - - return i < ii ? str.replace(WhitespaceRegexp, " ") : str; - } - - function runBidiTransform(textChunk) { - const text = textChunk.str.join(""); - const bidiResult = (0, _bidi.bidi)(text, -1, textChunk.vertical); - const str = normalizeWhitespace ? replaceWhitespace(bidiResult.str) : bidiResult.str; - return { - str, - dir: bidiResult.dir, - width: textChunk.totalWidth, - height: textChunk.totalHeight, - transform: textChunk.transform, - fontName: textChunk.fontName, - hasEOL: textChunk.hasEOL - }; - } - - function handleSetFont(fontName, fontRef) { - return self.loadFont(fontName, fontRef, resources).then(function (translated) { - if (!translated.font.isType3Font) { - return translated; - } - - return translated.loadType3Data(self, resources, task).catch(function () {}).then(function () { - return translated; - }); - }).then(function (translated) { - textState.font = translated.font; - textState.fontMatrix = translated.font.fontMatrix || _util.FONT_IDENTITY_MATRIX; - }); - } - - function compareWithLastPosition() { - if (!combineTextItems || !textState.font || !textContentItem.prevTransform) { - return; - } - - const currentTransform = getCurrentTextTransform(); - let posX = currentTransform[4]; - let posY = currentTransform[5]; - let lastPosX = textContentItem.prevTransform[4]; - let lastPosY = textContentItem.prevTransform[5]; - - if (lastPosX === posX && lastPosY === posY) { - return; - } - - let rotate = 0; - - if (currentTransform[0] && currentTransform[1] === 0 && currentTransform[2] === 0) { - rotate = currentTransform[0] > 0 ? 0 : 180; - } else if (currentTransform[1] && currentTransform[0] === 0 && currentTransform[3] === 0) { - rotate += currentTransform[1] > 0 ? 90 : 270; - } - - if (rotate !== 0) { - switch (rotate) { - case 90: - [posX, posY] = [posY, posX]; - [lastPosX, lastPosY] = [lastPosY, lastPosX]; - break; - - case 180: - [posX, posY, lastPosX, lastPosY] = [-posX, -posY, -lastPosX, -lastPosY]; - break; - - case 270: - [posX, posY] = [-posY, -posX]; - [lastPosX, lastPosY] = [-lastPosY, -lastPosX]; - break; - } - } - - if (textState.font.vertical) { - const advanceY = (lastPosY - posY) / textContentItem.textAdvanceScale; - const advanceX = posX - lastPosX; - - if (advanceY < textContentItem.negativeSpaceMax) { - if (Math.abs(advanceX) > 0.5 * textContentItem.width) { - appendEOL(); - return; - } - - flushTextContentItem(); - return; - } - - if (Math.abs(advanceX) > textContentItem.height) { - appendEOL(); - return; - } - - if (advanceY <= textContentItem.trackingSpaceMin) { - textContentItem.height += advanceY; - } else if (!addFakeSpaces(advanceY, textContentItem.prevTransform)) { - if (textContentItem.str.length === 0) { - textContent.items.push({ - str: " ", - dir: "ltr", - width: 0, - height: advanceY, - transform: textContentItem.prevTransform, - fontName: textContentItem.fontName, - hasEOL: false - }); - } else { - textContentItem.height += advanceY; - } - } - - return; - } - - const advanceX = (posX - lastPosX) / textContentItem.textAdvanceScale; - const advanceY = posY - lastPosY; - - if (advanceX < textContentItem.negativeSpaceMax) { - if (Math.abs(advanceY) > 0.5 * textContentItem.height) { - appendEOL(); - return; - } - - flushTextContentItem(); - return; - } - - if (Math.abs(advanceY) > textContentItem.height) { - appendEOL(); - return; - } - - if (advanceX <= textContentItem.trackingSpaceMin) { - textContentItem.width += advanceX; - } else if (!addFakeSpaces(advanceX, textContentItem.prevTransform)) { - if (textContentItem.str.length === 0) { - textContent.items.push({ - str: " ", - dir: "ltr", - width: advanceX, - height: 0, - transform: textContentItem.prevTransform, - fontName: textContentItem.fontName, - hasEOL: false - }); - } else { - textContentItem.width += advanceX; - } - } - } - - function buildTextContentItem({ - chars, - extraSpacing - }) { - const font = textState.font; - - if (!chars) { - const charSpacing = textState.charSpacing + extraSpacing; - - if (charSpacing) { - if (!font.vertical) { - textState.translateTextMatrix(charSpacing * textState.textHScale, 0); - } else { - textState.translateTextMatrix(0, -charSpacing); - } - } - - return; - } - - const glyphs = font.charsToGlyphs(chars); - const scale = textState.fontMatrix[0] * textState.fontSize; - - for (let i = 0, ii = glyphs.length; i < ii; i++) { - const glyph = glyphs[i]; - let charSpacing = textState.charSpacing + (i + 1 === ii ? extraSpacing : 0); - let glyphWidth = glyph.width; - - if (font.vertical) { - glyphWidth = glyph.vmetric ? glyph.vmetric[0] : -glyphWidth; - } - - let scaledDim = glyphWidth * scale; - let glyphUnicode = glyph.unicode; - - if (glyphUnicode === " " && (i === 0 || i + 1 === ii || glyphs[i - 1].unicode === " " || glyphs[i + 1].unicode === " " || extraSpacing)) { - if (!font.vertical) { - charSpacing += scaledDim + textState.wordSpacing; - textState.translateTextMatrix(charSpacing * textState.textHScale, 0); - } else { - charSpacing += -scaledDim + textState.wordSpacing; - textState.translateTextMatrix(0, -charSpacing); - } - - continue; - } - - compareWithLastPosition(); - const textChunk = ensureTextContentItem(); - - if (DiacriticRegExp.test(glyph.unicode)) { - scaledDim = 0; - } - - if (!font.vertical) { - scaledDim *= textState.textHScale; - textState.translateTextMatrix(scaledDim, 0); - textChunk.width += scaledDim; - } else { - textState.translateTextMatrix(0, scaledDim); - scaledDim = Math.abs(scaledDim); - textChunk.height += scaledDim; - } - - if (scaledDim) { - textChunk.prevTransform = getCurrentTextTransform(); - } - - glyphUnicode = NormalizedUnicodes[glyphUnicode] || glyphUnicode; - glyphUnicode = (0, _unicode.reverseIfRtl)(glyphUnicode); - textChunk.str.push(glyphUnicode); - - if (charSpacing) { - if (!font.vertical) { - textState.translateTextMatrix(charSpacing * textState.textHScale, 0); - } else { - textState.translateTextMatrix(0, -charSpacing); - } - } - } - } - - function appendEOL() { - if (textContentItem.initialized) { - textContentItem.hasEOL = true; - flushTextContentItem(); - } else { - textContent.items.push({ - str: "", - dir: "ltr", - width: 0, - height: 0, - transform: getCurrentTextTransform(), - fontName: textState.font.loadedName, - hasEOL: true - }); - } - } - - function addFakeSpaces(width, transf) { - if (textContentItem.spaceInFlowMin <= width && width <= textContentItem.spaceInFlowMax) { - if (textContentItem.initialized) { - textContentItem.str.push(" "); - } - - return false; - } - - const fontName = textContentItem.fontName; - let height = 0; - - if (textContentItem.vertical) { - height = width; - width = 0; - } - - flushTextContentItem(); - textContent.items.push({ - str: " ", - dir: "ltr", - width, - height, - transform: transf || getCurrentTextTransform(), - fontName, - hasEOL: false - }); - return true; - } - - function flushTextContentItem() { - if (!textContentItem.initialized || !textContentItem.str) { - return; - } - - if (!textContentItem.vertical) { - textContentItem.totalWidth += textContentItem.width * textContentItem.textAdvanceScale; - } else { - textContentItem.totalHeight += textContentItem.height * textContentItem.textAdvanceScale; - } - - textContent.items.push(runBidiTransform(textContentItem)); - textContentItem.initialized = false; - textContentItem.str.length = 0; - } - - function enqueueChunk(batch = false) { - const length = textContent.items.length; - - if (length === 0) { - return; - } - - if (batch && length < TEXT_CHUNK_BATCH_SIZE) { - return; - } - - sink.enqueue(textContent, length); - textContent.items = []; - textContent.styles = Object.create(null); - } - - const timeSlotManager = new TimeSlotManager(); - return new Promise(function promiseBody(resolve, reject) { - const next = function (promise) { - enqueueChunk(true); - Promise.all([promise, sink.ready]).then(function () { - try { - promiseBody(resolve, reject); - } catch (ex) { - reject(ex); - } - }, reject); - }; - - task.ensureNotTerminated(); - timeSlotManager.reset(); - const operation = {}; - let stop, - args = []; - - while (!(stop = timeSlotManager.check())) { - args.length = 0; - operation.args = args; - - if (!preprocessor.read(operation)) { - break; - } - - textState = stateManager.state; - const fn = operation.fn; - args = operation.args; - - switch (fn | 0) { - case _util.OPS.setFont: - var fontNameArg = args[0].name, - fontSizeArg = args[1]; - - if (textState.font && fontNameArg === textState.fontName && fontSizeArg === textState.fontSize) { - break; - } - - flushTextContentItem(); - textState.fontName = fontNameArg; - textState.fontSize = fontSizeArg; - next(handleSetFont(fontNameArg, null)); - return; - - case _util.OPS.setTextRise: - textState.textRise = args[0]; - break; - - case _util.OPS.setHScale: - textState.textHScale = args[0] / 100; - break; - - case _util.OPS.setLeading: - textState.leading = args[0]; - break; - - case _util.OPS.moveText: - textState.translateTextLineMatrix(args[0], args[1]); - textState.textMatrix = textState.textLineMatrix.slice(); - break; - - case _util.OPS.setLeadingMoveText: - textState.leading = -args[1]; - textState.translateTextLineMatrix(args[0], args[1]); - textState.textMatrix = textState.textLineMatrix.slice(); - break; - - case _util.OPS.nextLine: - textState.carriageReturn(); - break; - - case _util.OPS.setTextMatrix: - textState.setTextMatrix(args[0], args[1], args[2], args[3], args[4], args[5]); - textState.setTextLineMatrix(args[0], args[1], args[2], args[3], args[4], args[5]); - updateAdvanceScale(); - break; - - case _util.OPS.setCharSpacing: - textState.charSpacing = args[0]; - break; - - case _util.OPS.setWordSpacing: - textState.wordSpacing = args[0]; - break; - - case _util.OPS.beginText: - textState.textMatrix = _util.IDENTITY_MATRIX.slice(); - textState.textLineMatrix = _util.IDENTITY_MATRIX.slice(); - break; - - case _util.OPS.showSpacedText: - if (!stateManager.state.font) { - self.ensureStateFont(stateManager.state); - continue; - } - - const spaceFactor = (textState.font.vertical ? 1 : -1) * textState.fontSize / 1000; - const elements = args[0]; - - for (let i = 0, ii = elements.length; i < ii - 1; i++) { - const item = elements[i]; - - if (typeof item === "string") { - showSpacedTextBuffer.push(item); - } else if (typeof item === "number" && item !== 0) { - const str = showSpacedTextBuffer.join(""); - showSpacedTextBuffer.length = 0; - buildTextContentItem({ - chars: str, - extraSpacing: item * spaceFactor - }); - } - } - - const item = elements[elements.length - 1]; - - if (typeof item === "string") { - showSpacedTextBuffer.push(item); - } - - if (showSpacedTextBuffer.length > 0) { - const str = showSpacedTextBuffer.join(""); - showSpacedTextBuffer.length = 0; - buildTextContentItem({ - chars: str, - extraSpacing: 0 - }); - } - - break; - - case _util.OPS.showText: - if (!stateManager.state.font) { - self.ensureStateFont(stateManager.state); - continue; - } - - buildTextContentItem({ - chars: args[0], - extraSpacing: 0 - }); - break; - - case _util.OPS.nextLineShowText: - if (!stateManager.state.font) { - self.ensureStateFont(stateManager.state); - continue; - } - - textState.carriageReturn(); - buildTextContentItem({ - chars: args[0], - extraSpacing: 0 - }); - break; - - case _util.OPS.nextLineSetSpacingShowText: - if (!stateManager.state.font) { - self.ensureStateFont(stateManager.state); - continue; - } - - textState.wordSpacing = args[0]; - textState.charSpacing = args[1]; - textState.carriageReturn(); - buildTextContentItem({ - chars: args[2], - extraSpacing: 0 - }); - break; - - case _util.OPS.paintXObject: - flushTextContentItem(); - - if (!xobjs) { - xobjs = resources.get("XObject") || _primitives.Dict.empty; - } - - var isValidName = args[0] instanceof _primitives.Name; - var name = args[0].name; - - if (isValidName && emptyXObjectCache.getByName(name)) { - break; - } - - next(new Promise(function (resolveXObject, rejectXObject) { - if (!isValidName) { - throw new _util.FormatError("XObject must be referred to by name."); - } - - let xobj = xobjs.getRaw(name); - - if (xobj instanceof _primitives.Ref) { - if (emptyXObjectCache.getByRef(xobj)) { - resolveXObject(); - return; - } - - const globalImage = self.globalImageCache.getData(xobj, self.pageIndex); - - if (globalImage) { - resolveXObject(); - return; - } - - xobj = xref.fetch(xobj); - } - - if (!(0, _primitives.isStream)(xobj)) { - throw new _util.FormatError("XObject should be a stream"); - } - - const type = xobj.dict.get("Subtype"); - - if (!(0, _primitives.isName)(type)) { - throw new _util.FormatError("XObject should have a Name subtype"); - } - - if (type.name !== "Form") { - emptyXObjectCache.set(name, xobj.dict.objId, true); - resolveXObject(); - return; - } - - const currentState = stateManager.state.clone(); - const xObjStateManager = new StateManager(currentState); - const matrix = xobj.dict.getArray("Matrix"); - - if (Array.isArray(matrix) && matrix.length === 6) { - xObjStateManager.transform(matrix); - } - - enqueueChunk(); - const sinkWrapper = { - enqueueInvoked: false, - - enqueue(chunk, size) { - this.enqueueInvoked = true; - sink.enqueue(chunk, size); - }, - - get desiredSize() { - return sink.desiredSize; - }, - - get ready() { - return sink.ready; - } - - }; - self.getTextContent({ - stream: xobj, - task, - resources: xobj.dict.get("Resources") || resources, - stateManager: xObjStateManager, - normalizeWhitespace, - combineTextItems, - includeMarkedContent, - sink: sinkWrapper, - seenStyles - }).then(function () { - if (!sinkWrapper.enqueueInvoked) { - emptyXObjectCache.set(name, xobj.dict.objId, true); - } - - resolveXObject(); - }, rejectXObject); - }).catch(function (reason) { - if (reason instanceof _util.AbortException) { - return; - } - - if (self.options.ignoreErrors) { - (0, _util.warn)(`getTextContent - ignoring XObject: "${reason}".`); - return; - } - - throw reason; - })); - return; - - case _util.OPS.setGState: - isValidName = args[0] instanceof _primitives.Name; - name = args[0].name; - - if (isValidName && emptyGStateCache.getByName(name)) { - break; - } - - next(new Promise(function (resolveGState, rejectGState) { - if (!isValidName) { - throw new _util.FormatError("GState must be referred to by name."); - } - - const extGState = resources.get("ExtGState"); - - if (!(extGState instanceof _primitives.Dict)) { - throw new _util.FormatError("ExtGState should be a dictionary."); - } - - const gState = extGState.get(name); - - if (!(gState instanceof _primitives.Dict)) { - throw new _util.FormatError("GState should be a dictionary."); - } - - const gStateFont = gState.get("Font"); - - if (!gStateFont) { - emptyGStateCache.set(name, gState.objId, true); - resolveGState(); - return; - } - - flushTextContentItem(); - textState.fontName = null; - textState.fontSize = gStateFont[1]; - handleSetFont(null, gStateFont[0]).then(resolveGState, rejectGState); - }).catch(function (reason) { - if (reason instanceof _util.AbortException) { - return; - } - - if (self.options.ignoreErrors) { - (0, _util.warn)(`getTextContent - ignoring ExtGState: "${reason}".`); - return; - } - - throw reason; - })); - return; - - case _util.OPS.beginMarkedContent: - if (includeMarkedContent) { - textContent.items.push({ - type: "beginMarkedContent", - tag: (0, _primitives.isName)(args[0]) ? args[0].name : null - }); - } - - break; - - case _util.OPS.beginMarkedContentProps: - if (includeMarkedContent) { - flushTextContentItem(); - let mcid = null; - - if ((0, _primitives.isDict)(args[1])) { - mcid = args[1].get("MCID"); - } - - textContent.items.push({ - type: "beginMarkedContentProps", - id: Number.isInteger(mcid) ? `${self.idFactory.getPageObjId()}_mcid${mcid}` : null, - tag: (0, _primitives.isName)(args[0]) ? args[0].name : null - }); - } - - break; - - case _util.OPS.endMarkedContent: - if (includeMarkedContent) { - flushTextContentItem(); - textContent.items.push({ - type: "endMarkedContent" - }); - } - - break; - } - - if (textContent.items.length >= sink.desiredSize) { - stop = true; - break; - } - } - - if (stop) { - next(deferred); - return; - } - - flushTextContentItem(); - enqueueChunk(); - resolve(); - }).catch(reason => { - if (reason instanceof _util.AbortException) { - return; - } - - if (this.options.ignoreErrors) { - (0, _util.warn)(`getTextContent - ignoring errors during "${task.name}" ` + `task: "${reason}".`); - flushTextContentItem(); - enqueueChunk(); - return; - } - - throw reason; - }); - } - - extractDataStructures(dict, baseDict, properties) { - const xref = this.xref; - let cidToGidBytes; - const toUnicodePromise = this.readToUnicode(properties.toUnicode || dict.get("ToUnicode") || baseDict.get("ToUnicode")); - - if (properties.composite) { - const cidSystemInfo = dict.get("CIDSystemInfo"); - - if ((0, _primitives.isDict)(cidSystemInfo)) { - properties.cidSystemInfo = { - registry: (0, _util.stringToPDFString)(cidSystemInfo.get("Registry")), - ordering: (0, _util.stringToPDFString)(cidSystemInfo.get("Ordering")), - supplement: cidSystemInfo.get("Supplement") - }; - } - - const cidToGidMap = dict.get("CIDToGIDMap"); - - if (cidToGidMap instanceof _base_stream.BaseStream) { - cidToGidBytes = cidToGidMap.getBytes(); - } - } - - const differences = []; - let baseEncodingName = null; - let encoding; - - if (dict.has("Encoding")) { - encoding = dict.get("Encoding"); - - if ((0, _primitives.isDict)(encoding)) { - baseEncodingName = encoding.get("BaseEncoding"); - baseEncodingName = (0, _primitives.isName)(baseEncodingName) ? baseEncodingName.name : null; - - if (encoding.has("Differences")) { - const diffEncoding = encoding.get("Differences"); - let index = 0; - - for (let j = 0, jj = diffEncoding.length; j < jj; j++) { - const data = xref.fetchIfRef(diffEncoding[j]); - - if ((0, _util.isNum)(data)) { - index = data; - } else if ((0, _primitives.isName)(data)) { - differences[index++] = data.name; - } else { - throw new _util.FormatError(`Invalid entry in 'Differences' array: ${data}`); - } - } - } - } else if ((0, _primitives.isName)(encoding)) { - baseEncodingName = encoding.name; - } else { - throw new _util.FormatError("Encoding is not a Name nor a Dict"); - } - - if (baseEncodingName !== "MacRomanEncoding" && baseEncodingName !== "MacExpertEncoding" && baseEncodingName !== "WinAnsiEncoding") { - baseEncodingName = null; - } - } - - if (baseEncodingName) { - properties.defaultEncoding = (0, _encodings.getEncoding)(baseEncodingName); - } else { - const isSymbolicFont = !!(properties.flags & _fonts_utils.FontFlags.Symbolic); - const isNonsymbolicFont = !!(properties.flags & _fonts_utils.FontFlags.Nonsymbolic); - encoding = _encodings.StandardEncoding; - - if (properties.type === "TrueType" && !isNonsymbolicFont) { - encoding = _encodings.WinAnsiEncoding; - } - - if (isSymbolicFont) { - encoding = _encodings.MacRomanEncoding; - - if (!properties.file || properties.isInternalFont) { - if (/Symbol/i.test(properties.name)) { - encoding = _encodings.SymbolSetEncoding; - } else if (/Dingbats|Wingdings/i.test(properties.name)) { - encoding = _encodings.ZapfDingbatsEncoding; - } - } - } - - properties.defaultEncoding = encoding; - } - - properties.differences = differences; - properties.baseEncodingName = baseEncodingName; - properties.hasEncoding = !!baseEncodingName || differences.length > 0; - properties.dict = dict; - return toUnicodePromise.then(readToUnicode => { - properties.toUnicode = readToUnicode; - return this.buildToUnicode(properties); - }).then(builtToUnicode => { - properties.toUnicode = builtToUnicode; - - if (cidToGidBytes) { - properties.cidToGidMap = this.readCidToGidMap(cidToGidBytes, builtToUnicode); - } - - return properties; - }); - } - - _simpleFontToUnicode(properties, forceGlyphs = false) { - (0, _util.assert)(!properties.composite, "Must be a simple font."); - const toUnicode = []; - const encoding = properties.defaultEncoding.slice(); - const baseEncodingName = properties.baseEncodingName; - const differences = properties.differences; - - for (const charcode in differences) { - const glyphName = differences[charcode]; - - if (glyphName === ".notdef") { - continue; - } - - encoding[charcode] = glyphName; - } - - const glyphsUnicodeMap = (0, _glyphlist.getGlyphsUnicode)(); - - for (const charcode in encoding) { - let glyphName = encoding[charcode]; - - if (glyphName === "") { - continue; - } else if (glyphsUnicodeMap[glyphName] === undefined) { - let code = 0; - - switch (glyphName[0]) { - case "G": - if (glyphName.length === 3) { - code = parseInt(glyphName.substring(1), 16); - } - - break; - - case "g": - if (glyphName.length === 5) { - code = parseInt(glyphName.substring(1), 16); - } - - break; - - case "C": - case "c": - if (glyphName.length >= 3 && glyphName.length <= 4) { - const codeStr = glyphName.substring(1); - - if (forceGlyphs) { - code = parseInt(codeStr, 16); - break; - } - - code = +codeStr; - - if (Number.isNaN(code) && Number.isInteger(parseInt(codeStr, 16))) { - return this._simpleFontToUnicode(properties, true); - } - } - - break; - - default: - const unicode = (0, _unicode.getUnicodeForGlyph)(glyphName, glyphsUnicodeMap); - - if (unicode !== -1) { - code = unicode; - } - - } - - if (code > 0 && code <= 0x10ffff && Number.isInteger(code)) { - if (baseEncodingName && code === +charcode) { - const baseEncoding = (0, _encodings.getEncoding)(baseEncodingName); - - if (baseEncoding && (glyphName = baseEncoding[charcode])) { - toUnicode[charcode] = String.fromCharCode(glyphsUnicodeMap[glyphName]); - continue; - } - } - - toUnicode[charcode] = String.fromCodePoint(code); - } - - continue; - } - - toUnicode[charcode] = String.fromCharCode(glyphsUnicodeMap[glyphName]); - } - - return toUnicode; - } - - async buildToUnicode(properties) { - properties.hasIncludedToUnicodeMap = !!properties.toUnicode && properties.toUnicode.length > 0; - - if (properties.hasIncludedToUnicodeMap) { - if (!properties.composite && properties.hasEncoding) { - properties.fallbackToUnicode = this._simpleFontToUnicode(properties); - } - - return properties.toUnicode; - } - - if (!properties.composite) { - return new _to_unicode_map.ToUnicodeMap(this._simpleFontToUnicode(properties)); - } - - if (properties.composite && (properties.cMap.builtInCMap && !(properties.cMap instanceof _cmap.IdentityCMap) || properties.cidSystemInfo.registry === "Adobe" && (properties.cidSystemInfo.ordering === "GB1" || properties.cidSystemInfo.ordering === "CNS1" || properties.cidSystemInfo.ordering === "Japan1" || properties.cidSystemInfo.ordering === "Korea1"))) { - const { - registry, - ordering - } = properties.cidSystemInfo; - - const ucs2CMapName = _primitives.Name.get(`${registry}-${ordering}-UCS2`); - - const ucs2CMap = await _cmap.CMapFactory.create({ - encoding: ucs2CMapName, - fetchBuiltInCMap: this._fetchBuiltInCMapBound, - useCMap: null - }); - const toUnicode = []; - properties.cMap.forEach(function (charcode, cid) { - if (cid > 0xffff) { - throw new _util.FormatError("Max size of CID is 65,535"); - } - - const ucs2 = ucs2CMap.lookup(cid); - - if (ucs2) { - toUnicode[charcode] = String.fromCharCode((ucs2.charCodeAt(0) << 8) + ucs2.charCodeAt(1)); - } - }); - return new _to_unicode_map.ToUnicodeMap(toUnicode); - } - - return new _to_unicode_map.IdentityToUnicodeMap(properties.firstChar, properties.lastChar); - } - - readToUnicode(cmapObj) { - if (!cmapObj) { - return Promise.resolve(null); - } - - if ((0, _primitives.isName)(cmapObj)) { - return _cmap.CMapFactory.create({ - encoding: cmapObj, - fetchBuiltInCMap: this._fetchBuiltInCMapBound, - useCMap: null - }).then(function (cmap) { - if (cmap instanceof _cmap.IdentityCMap) { - return new _to_unicode_map.IdentityToUnicodeMap(0, 0xffff); - } - - return new _to_unicode_map.ToUnicodeMap(cmap.getMap()); - }); - } else if ((0, _primitives.isStream)(cmapObj)) { - return _cmap.CMapFactory.create({ - encoding: cmapObj, - fetchBuiltInCMap: this._fetchBuiltInCMapBound, - useCMap: null - }).then(function (cmap) { - if (cmap instanceof _cmap.IdentityCMap) { - return new _to_unicode_map.IdentityToUnicodeMap(0, 0xffff); - } - - const map = new Array(cmap.length); - cmap.forEach(function (charCode, token) { - if (typeof token === "number") { - map[charCode] = String.fromCodePoint(token); - return; - } - - const str = []; - - for (let k = 0; k < token.length; k += 2) { - const w1 = token.charCodeAt(k) << 8 | token.charCodeAt(k + 1); - - if ((w1 & 0xf800) !== 0xd800) { - str.push(w1); - continue; - } - - k += 2; - const w2 = token.charCodeAt(k) << 8 | token.charCodeAt(k + 1); - str.push(((w1 & 0x3ff) << 10) + (w2 & 0x3ff) + 0x10000); - } - - map[charCode] = String.fromCodePoint.apply(String, str); - }); - return new _to_unicode_map.ToUnicodeMap(map); - }, reason => { - if (reason instanceof _util.AbortException) { - return null; - } - - if (this.options.ignoreErrors) { - this.handler.send("UnsupportedFeature", { - featureId: _util.UNSUPPORTED_FEATURES.errorFontToUnicode - }); - (0, _util.warn)(`readToUnicode - ignoring ToUnicode data: "${reason}".`); - return null; - } - - throw reason; - }); - } - - return Promise.resolve(null); - } - - readCidToGidMap(glyphsData, toUnicode) { - const result = []; - - for (let j = 0, jj = glyphsData.length; j < jj; j++) { - const glyphID = glyphsData[j++] << 8 | glyphsData[j]; - const code = j >> 1; - - if (glyphID === 0 && !toUnicode.has(code)) { - continue; - } - - result[code] = glyphID; - } - - return result; - } - - extractWidths(dict, descriptor, properties) { - const xref = this.xref; - let glyphsWidths = []; - let defaultWidth = 0; - const glyphsVMetrics = []; - let defaultVMetrics; - let i, ii, j, jj, start, code, widths; - - if (properties.composite) { - defaultWidth = dict.has("DW") ? dict.get("DW") : 1000; - widths = dict.get("W"); - - if (widths) { - for (i = 0, ii = widths.length; i < ii; i++) { - start = xref.fetchIfRef(widths[i++]); - code = xref.fetchIfRef(widths[i]); - - if (Array.isArray(code)) { - for (j = 0, jj = code.length; j < jj; j++) { - glyphsWidths[start++] = xref.fetchIfRef(code[j]); - } - } else { - const width = xref.fetchIfRef(widths[++i]); - - for (j = start; j <= code; j++) { - glyphsWidths[j] = width; - } - } - } - } - - if (properties.vertical) { - let vmetrics = dict.getArray("DW2") || [880, -1000]; - defaultVMetrics = [vmetrics[1], defaultWidth * 0.5, vmetrics[0]]; - vmetrics = dict.get("W2"); - - if (vmetrics) { - for (i = 0, ii = vmetrics.length; i < ii; i++) { - start = xref.fetchIfRef(vmetrics[i++]); - code = xref.fetchIfRef(vmetrics[i]); - - if (Array.isArray(code)) { - for (j = 0, jj = code.length; j < jj; j++) { - glyphsVMetrics[start++] = [xref.fetchIfRef(code[j++]), xref.fetchIfRef(code[j++]), xref.fetchIfRef(code[j])]; - } - } else { - const vmetric = [xref.fetchIfRef(vmetrics[++i]), xref.fetchIfRef(vmetrics[++i]), xref.fetchIfRef(vmetrics[++i])]; - - for (j = start; j <= code; j++) { - glyphsVMetrics[j] = vmetric; - } - } - } - } - } - } else { - const firstChar = properties.firstChar; - widths = dict.get("Widths"); - - if (widths) { - j = firstChar; - - for (i = 0, ii = widths.length; i < ii; i++) { - glyphsWidths[j++] = xref.fetchIfRef(widths[i]); - } - - defaultWidth = parseFloat(descriptor.get("MissingWidth")) || 0; - } else { - const baseFontName = dict.get("BaseFont"); - - if ((0, _primitives.isName)(baseFontName)) { - const metrics = this.getBaseFontMetrics(baseFontName.name); - glyphsWidths = this.buildCharCodeToWidth(metrics.widths, properties); - defaultWidth = metrics.defaultWidth; - } - } - } - - let isMonospace = true; - let firstWidth = defaultWidth; - - for (const glyph in glyphsWidths) { - const glyphWidth = glyphsWidths[glyph]; - - if (!glyphWidth) { - continue; - } - - if (!firstWidth) { - firstWidth = glyphWidth; - continue; - } - - if (firstWidth !== glyphWidth) { - isMonospace = false; - break; - } - } - - if (isMonospace) { - properties.flags |= _fonts_utils.FontFlags.FixedPitch; - } - - properties.defaultWidth = defaultWidth; - properties.widths = glyphsWidths; - properties.defaultVMetrics = defaultVMetrics; - properties.vmetrics = glyphsVMetrics; - } - - isSerifFont(baseFontName) { - const fontNameWoStyle = baseFontName.split("-")[0]; - return fontNameWoStyle in (0, _standard_fonts.getSerifFonts)() || fontNameWoStyle.search(/serif/gi) !== -1; - } - - getBaseFontMetrics(name) { - let defaultWidth = 0; - let widths = Object.create(null); - let monospace = false; - const stdFontMap = (0, _standard_fonts.getStdFontMap)(); - let lookupName = stdFontMap[name] || name; - const Metrics = (0, _metrics.getMetrics)(); - - if (!(lookupName in Metrics)) { - if (this.isSerifFont(name)) { - lookupName = "Times-Roman"; - } else { - lookupName = "Helvetica"; - } - } - - const glyphWidths = Metrics[lookupName]; - - if ((0, _util.isNum)(glyphWidths)) { - defaultWidth = glyphWidths; - monospace = true; - } else { - widths = glyphWidths(); - } - - return { - defaultWidth, - monospace, - widths - }; - } - - buildCharCodeToWidth(widthsByGlyphName, properties) { - const widths = Object.create(null); - const differences = properties.differences; - const encoding = properties.defaultEncoding; - - for (let charCode = 0; charCode < 256; charCode++) { - if (charCode in differences && widthsByGlyphName[differences[charCode]]) { - widths[charCode] = widthsByGlyphName[differences[charCode]]; - continue; - } - - if (charCode in encoding && widthsByGlyphName[encoding[charCode]]) { - widths[charCode] = widthsByGlyphName[encoding[charCode]]; - continue; - } - } - - return widths; - } - - preEvaluateFont(dict) { - const baseDict = dict; - let type = dict.get("Subtype"); - - if (!(0, _primitives.isName)(type)) { - throw new _util.FormatError("invalid font Subtype"); - } - - let composite = false; - let hash, toUnicode; - - if (type.name === "Type0") { - const df = dict.get("DescendantFonts"); - - if (!df) { - throw new _util.FormatError("Descendant fonts are not specified"); - } - - dict = Array.isArray(df) ? this.xref.fetchIfRef(df[0]) : df; - - if (!(dict instanceof _primitives.Dict)) { - throw new _util.FormatError("Descendant font is not a dictionary."); - } - - type = dict.get("Subtype"); - - if (!(0, _primitives.isName)(type)) { - throw new _util.FormatError("invalid font Subtype"); - } - - composite = true; - } - - const firstChar = dict.get("FirstChar") || 0, - lastChar = dict.get("LastChar") || (composite ? 0xffff : 0xff); - const descriptor = dict.get("FontDescriptor"); - - if (descriptor) { - hash = new _murmurhash.MurmurHash3_64(); - const encoding = baseDict.getRaw("Encoding"); - - if ((0, _primitives.isName)(encoding)) { - hash.update(encoding.name); - } else if ((0, _primitives.isRef)(encoding)) { - hash.update(encoding.toString()); - } else if ((0, _primitives.isDict)(encoding)) { - for (const entry of encoding.getRawValues()) { - if ((0, _primitives.isName)(entry)) { - hash.update(entry.name); - } else if ((0, _primitives.isRef)(entry)) { - hash.update(entry.toString()); - } else if (Array.isArray(entry)) { - const diffLength = entry.length, - diffBuf = new Array(diffLength); - - for (let j = 0; j < diffLength; j++) { - const diffEntry = entry[j]; - - if ((0, _primitives.isName)(diffEntry)) { - diffBuf[j] = diffEntry.name; - } else if ((0, _util.isNum)(diffEntry) || (0, _primitives.isRef)(diffEntry)) { - diffBuf[j] = diffEntry.toString(); - } - } - - hash.update(diffBuf.join()); - } - } - } - - hash.update(`${firstChar}-${lastChar}`); - toUnicode = dict.get("ToUnicode") || baseDict.get("ToUnicode"); - - if ((0, _primitives.isStream)(toUnicode)) { - const stream = toUnicode.str || toUnicode; - const uint8array = stream.buffer ? new Uint8Array(stream.buffer.buffer, 0, stream.bufferLength) : new Uint8Array(stream.bytes.buffer, stream.start, stream.end - stream.start); - hash.update(uint8array); - } else if ((0, _primitives.isName)(toUnicode)) { - hash.update(toUnicode.name); - } - - const widths = dict.get("Widths") || baseDict.get("Widths"); - - if (Array.isArray(widths)) { - const widthsBuf = []; - - for (const entry of widths) { - if ((0, _util.isNum)(entry) || (0, _primitives.isRef)(entry)) { - widthsBuf.push(entry.toString()); - } - } - - hash.update(widthsBuf.join()); - } - - if (composite) { - hash.update("compositeFont"); - const compositeWidths = dict.get("W") || baseDict.get("W"); - - if (Array.isArray(compositeWidths)) { - const widthsBuf = []; - - for (const entry of compositeWidths) { - if ((0, _util.isNum)(entry) || (0, _primitives.isRef)(entry)) { - widthsBuf.push(entry.toString()); - } else if (Array.isArray(entry)) { - const subWidthsBuf = []; - - for (const element of entry) { - if ((0, _util.isNum)(element) || (0, _primitives.isRef)(element)) { - subWidthsBuf.push(element.toString()); - } - } - - widthsBuf.push(`[${subWidthsBuf.join()}]`); - } - } - - hash.update(widthsBuf.join()); - } - - const cidToGidMap = dict.getRaw("CIDToGIDMap") || baseDict.getRaw("CIDToGIDMap"); - - if (cidToGidMap instanceof _primitives.Name) { - hash.update(cidToGidMap.name); - } else if (cidToGidMap instanceof _primitives.Ref) { - hash.update(cidToGidMap.toString()); - } else if (cidToGidMap instanceof _base_stream.BaseStream) { - hash.update(cidToGidMap.peekBytes()); - } - } - } - - return { - descriptor, - dict, - baseDict, - composite, - type: type.name, - firstChar, - lastChar, - toUnicode, - hash: hash ? hash.hexdigest() : "" - }; - } - - async translateFont({ - descriptor, - dict, - baseDict, - composite, - type, - firstChar, - lastChar, - toUnicode, - cssFontInfo - }) { - const isType3Font = type === "Type3"; - let properties; - - if (!descriptor) { - if (isType3Font) { - descriptor = new _primitives.Dict(null); - descriptor.set("FontName", _primitives.Name.get(type)); - descriptor.set("FontBBox", dict.getArray("FontBBox") || [0, 0, 0, 0]); - } else { - let baseFontName = dict.get("BaseFont"); - - if (!(0, _primitives.isName)(baseFontName)) { - throw new _util.FormatError("Base font is not specified"); - } - - baseFontName = baseFontName.name.replace(/[,_]/g, "-"); - const metrics = this.getBaseFontMetrics(baseFontName); - const fontNameWoStyle = baseFontName.split("-")[0]; - const flags = (this.isSerifFont(fontNameWoStyle) ? _fonts_utils.FontFlags.Serif : 0) | (metrics.monospace ? _fonts_utils.FontFlags.FixedPitch : 0) | ((0, _standard_fonts.getSymbolsFonts)()[fontNameWoStyle] ? _fonts_utils.FontFlags.Symbolic : _fonts_utils.FontFlags.Nonsymbolic); - properties = { - type, - name: baseFontName, - loadedName: baseDict.loadedName, - widths: metrics.widths, - defaultWidth: metrics.defaultWidth, - isSimulatedFlags: true, - flags, - firstChar, - lastChar, - toUnicode, - xHeight: 0, - capHeight: 0, - italicAngle: 0, - isType3Font - }; - const widths = dict.get("Widths"); - const standardFontName = (0, _standard_fonts.getStandardFontName)(baseFontName); - let file = null; - - if (standardFontName) { - properties.isStandardFont = true; - file = await this.fetchStandardFontData(standardFontName); - properties.isInternalFont = !!file; - } - - return this.extractDataStructures(dict, dict, properties).then(newProperties => { - if (widths) { - const glyphWidths = []; - let j = firstChar; - - for (let i = 0, ii = widths.length; i < ii; i++) { - glyphWidths[j++] = this.xref.fetchIfRef(widths[i]); - } - - newProperties.widths = glyphWidths; - } else { - newProperties.widths = this.buildCharCodeToWidth(metrics.widths, newProperties); - } - - return new _fonts.Font(baseFontName, file, newProperties); - }); - } - } - - let fontName = descriptor.get("FontName"); - let baseFont = dict.get("BaseFont"); - - if ((0, _util.isString)(fontName)) { - fontName = _primitives.Name.get(fontName); - } - - if ((0, _util.isString)(baseFont)) { - baseFont = _primitives.Name.get(baseFont); - } - - if (!isType3Font) { - const fontNameStr = fontName && fontName.name; - const baseFontStr = baseFont && baseFont.name; - - if (fontNameStr !== baseFontStr) { - (0, _util.info)(`The FontDescriptor's FontName is "${fontNameStr}" but ` + `should be the same as the Font's BaseFont "${baseFontStr}".`); - - if (fontNameStr && baseFontStr && baseFontStr.startsWith(fontNameStr)) { - fontName = baseFont; - } - } - } - - fontName = fontName || baseFont; - - if (!(0, _primitives.isName)(fontName)) { - throw new _util.FormatError("invalid font name"); - } - - let fontFile, subtype, length1, length2, length3; - - try { - fontFile = descriptor.get("FontFile", "FontFile2", "FontFile3"); - } catch (ex) { - if (!this.options.ignoreErrors) { - throw ex; - } - - (0, _util.warn)(`translateFont - fetching "${fontName.name}" font file: "${ex}".`); - fontFile = new _stream.NullStream(); - } - - let isStandardFont = false; - let isInternalFont = false; - let glyphScaleFactors = null; - - if (fontFile) { - if (fontFile.dict) { - const subtypeEntry = fontFile.dict.get("Subtype"); - - if (subtypeEntry instanceof _primitives.Name) { - subtype = subtypeEntry.name; - } - - length1 = fontFile.dict.get("Length1"); - length2 = fontFile.dict.get("Length2"); - length3 = fontFile.dict.get("Length3"); - } - } else if (cssFontInfo) { - const standardFontName = (0, _xfa_fonts.getXfaFontName)(fontName.name); - - if (standardFontName) { - cssFontInfo.fontFamily = `${cssFontInfo.fontFamily}-PdfJS-XFA`; - cssFontInfo.metrics = standardFontName.metrics || null; - glyphScaleFactors = standardFontName.factors || null; - fontFile = await this.fetchStandardFontData(standardFontName.name); - isInternalFont = !!fontFile; - baseDict = dict = (0, _xfa_fonts.getXfaFontDict)(fontName.name); - composite = true; - } - } else if (!isType3Font) { - const standardFontName = (0, _standard_fonts.getStandardFontName)(fontName.name); - - if (standardFontName) { - isStandardFont = true; - fontFile = await this.fetchStandardFontData(standardFontName); - isInternalFont = !!fontFile; - } - } - - properties = { - type, - name: fontName.name, - subtype, - file: fontFile, - length1, - length2, - length3, - isStandardFont, - isInternalFont, - loadedName: baseDict.loadedName, - composite, - fixedPitch: false, - fontMatrix: dict.getArray("FontMatrix") || _util.FONT_IDENTITY_MATRIX, - firstChar, - lastChar, - toUnicode, - bbox: descriptor.getArray("FontBBox") || dict.getArray("FontBBox"), - ascent: descriptor.get("Ascent"), - descent: descriptor.get("Descent"), - xHeight: descriptor.get("XHeight") || 0, - capHeight: descriptor.get("CapHeight") || 0, - flags: descriptor.get("Flags"), - italicAngle: descriptor.get("ItalicAngle") || 0, - isType3Font, - cssFontInfo, - scaleFactors: glyphScaleFactors - }; - - if (composite) { - const cidEncoding = baseDict.get("Encoding"); - - if ((0, _primitives.isName)(cidEncoding)) { - properties.cidEncoding = cidEncoding.name; - } - - const cMap = await _cmap.CMapFactory.create({ - encoding: cidEncoding, - fetchBuiltInCMap: this._fetchBuiltInCMapBound, - useCMap: null - }); - properties.cMap = cMap; - properties.vertical = properties.cMap.vertical; - } - - return this.extractDataStructures(dict, baseDict, properties).then(newProperties => { - this.extractWidths(dict, descriptor, newProperties); - return new _fonts.Font(fontName.name, fontFile, newProperties); - }); - } - - static buildFontPaths(font, glyphs, handler, evaluatorOptions) { - function buildPath(fontChar) { - const glyphName = `${font.loadedName}_path_${fontChar}`; - - try { - if (font.renderer.hasBuiltPath(fontChar)) { - return; - } - - handler.send("commonobj", [glyphName, "FontPath", font.renderer.getPathJs(fontChar)]); - } catch (reason) { - if (evaluatorOptions.ignoreErrors) { - handler.send("UnsupportedFeature", { - featureId: _util.UNSUPPORTED_FEATURES.errorFontBuildPath - }); - (0, _util.warn)(`buildFontPaths - ignoring ${glyphName} glyph: "${reason}".`); - return; - } - - throw reason; - } - } - - for (const glyph of glyphs) { - buildPath(glyph.fontChar); - const accent = glyph.accent; - - if (accent && accent.fontChar) { - buildPath(accent.fontChar); - } - } - } - - static get fallbackFontDict() { - const dict = new _primitives.Dict(); - dict.set("BaseFont", _primitives.Name.get("PDFJS-FallbackFont")); - dict.set("Type", _primitives.Name.get("FallbackType")); - dict.set("Subtype", _primitives.Name.get("FallbackType")); - dict.set("Encoding", _primitives.Name.get("WinAnsiEncoding")); - return (0, _util.shadow)(this, "fallbackFontDict", dict); - } - -} - -exports.PartialEvaluator = PartialEvaluator; - -class TranslatedFont { - constructor({ - loadedName, - font, - dict, - evaluatorOptions - }) { - this.loadedName = loadedName; - this.font = font; - this.dict = dict; - this._evaluatorOptions = evaluatorOptions || DefaultPartialEvaluatorOptions; - this.type3Loaded = null; - this.type3Dependencies = font.isType3Font ? new Set() : null; - this.sent = false; - } - - send(handler) { - if (this.sent) { - return; - } - - this.sent = true; - handler.send("commonobj", [this.loadedName, "Font", this.font.exportData(this._evaluatorOptions.fontExtraProperties)]); - } - - fallback(handler) { - if (!this.font.data) { - return; - } - - this.font.disableFontFace = true; - PartialEvaluator.buildFontPaths(this.font, this.font.glyphCacheValues, handler, this._evaluatorOptions); - } - - loadType3Data(evaluator, resources, task) { - if (this.type3Loaded) { - return this.type3Loaded; - } - - if (!this.font.isType3Font) { - throw new Error("Must be a Type3 font."); - } - - const type3Evaluator = evaluator.clone({ - ignoreErrors: false - }); - type3Evaluator.parsingType3Font = true; - const translatedFont = this.font, - type3Dependencies = this.type3Dependencies; - let loadCharProcsPromise = Promise.resolve(); - const charProcs = this.dict.get("CharProcs"); - const fontResources = this.dict.get("Resources") || resources; - const charProcOperatorList = Object.create(null); - const isEmptyBBox = !translatedFont.bbox || (0, _util.isArrayEqual)(translatedFont.bbox, [0, 0, 0, 0]); - - for (const key of charProcs.getKeys()) { - loadCharProcsPromise = loadCharProcsPromise.then(() => { - const glyphStream = charProcs.get(key); - const operatorList = new _operator_list.OperatorList(); - return type3Evaluator.getOperatorList({ - stream: glyphStream, - task, - resources: fontResources, - operatorList - }).then(() => { - if (operatorList.fnArray[0] === _util.OPS.setCharWidthAndBounds) { - this._removeType3ColorOperators(operatorList, isEmptyBBox); - } - - charProcOperatorList[key] = operatorList.getIR(); - - for (const dependency of operatorList.dependencies) { - type3Dependencies.add(dependency); - } - }).catch(function (reason) { - (0, _util.warn)(`Type3 font resource "${key}" is not available.`); - const dummyOperatorList = new _operator_list.OperatorList(); - charProcOperatorList[key] = dummyOperatorList.getIR(); - }); - }); - } - - this.type3Loaded = loadCharProcsPromise.then(() => { - translatedFont.charProcOperatorList = charProcOperatorList; - - if (this._bbox) { - translatedFont.isCharBBox = true; - translatedFont.bbox = this._bbox; - } - }); - return this.type3Loaded; - } - - _removeType3ColorOperators(operatorList, isEmptyBBox = false) { - if (isEmptyBBox) { - if (!this._bbox) { - this._bbox = [Infinity, Infinity, -Infinity, -Infinity]; - } - - const charBBox = _util.Util.normalizeRect(operatorList.argsArray[0].slice(2)); - - this._bbox[0] = Math.min(this._bbox[0], charBBox[0]); - this._bbox[1] = Math.min(this._bbox[1], charBBox[1]); - this._bbox[2] = Math.max(this._bbox[2], charBBox[2]); - this._bbox[3] = Math.max(this._bbox[3], charBBox[3]); - } - - let i = 1, - ii = operatorList.length; - - while (i < ii) { - switch (operatorList.fnArray[i]) { - case _util.OPS.setStrokeColorSpace: - case _util.OPS.setFillColorSpace: - case _util.OPS.setStrokeColor: - case _util.OPS.setStrokeColorN: - case _util.OPS.setFillColor: - case _util.OPS.setFillColorN: - case _util.OPS.setStrokeGray: - case _util.OPS.setFillGray: - case _util.OPS.setStrokeRGBColor: - case _util.OPS.setFillRGBColor: - case _util.OPS.setStrokeCMYKColor: - case _util.OPS.setFillCMYKColor: - case _util.OPS.shadingFill: - case _util.OPS.setRenderingIntent: - operatorList.fnArray.splice(i, 1); - operatorList.argsArray.splice(i, 1); - ii--; - continue; - - case _util.OPS.setGState: - const [gStateObj] = operatorList.argsArray[i]; - let j = 0, - jj = gStateObj.length; - - while (j < jj) { - const [gStateKey] = gStateObj[j]; - - switch (gStateKey) { - case "TR": - case "TR2": - case "HT": - case "BG": - case "BG2": - case "UCR": - case "UCR2": - gStateObj.splice(j, 1); - jj--; - continue; - } - - j++; - } - - break; - } - - i++; - } - } - -} - -class StateManager { - constructor(initialState = new EvalState()) { - this.state = initialState; - this.stateStack = []; - } - - save() { - const old = this.state; - this.stateStack.push(this.state); - this.state = old.clone(); - } - - restore() { - const prev = this.stateStack.pop(); - - if (prev) { - this.state = prev; - } - } - - transform(args) { - this.state.ctm = _util.Util.transform(this.state.ctm, args); - } - -} - -class TextState { - constructor() { - this.ctm = new Float32Array(_util.IDENTITY_MATRIX); - this.fontName = null; - this.fontSize = 0; - this.font = null; - this.fontMatrix = _util.FONT_IDENTITY_MATRIX; - this.textMatrix = _util.IDENTITY_MATRIX.slice(); - this.textLineMatrix = _util.IDENTITY_MATRIX.slice(); - this.charSpacing = 0; - this.wordSpacing = 0; - this.leading = 0; - this.textHScale = 1; - this.textRise = 0; - } - - setTextMatrix(a, b, c, d, e, f) { - const m = this.textMatrix; - m[0] = a; - m[1] = b; - m[2] = c; - m[3] = d; - m[4] = e; - m[5] = f; - } - - setTextLineMatrix(a, b, c, d, e, f) { - const m = this.textLineMatrix; - m[0] = a; - m[1] = b; - m[2] = c; - m[3] = d; - m[4] = e; - m[5] = f; - } - - translateTextMatrix(x, y) { - const m = this.textMatrix; - m[4] = m[0] * x + m[2] * y + m[4]; - m[5] = m[1] * x + m[3] * y + m[5]; - } - - translateTextLineMatrix(x, y) { - const m = this.textLineMatrix; - m[4] = m[0] * x + m[2] * y + m[4]; - m[5] = m[1] * x + m[3] * y + m[5]; - } - - carriageReturn() { - this.translateTextLineMatrix(0, -this.leading); - this.textMatrix = this.textLineMatrix.slice(); - } - - clone() { - const clone = Object.create(this); - clone.textMatrix = this.textMatrix.slice(); - clone.textLineMatrix = this.textLineMatrix.slice(); - clone.fontMatrix = this.fontMatrix.slice(); - return clone; - } - -} - -class EvalState { - constructor() { - this.ctm = new Float32Array(_util.IDENTITY_MATRIX); - this.font = null; - this.textRenderingMode = _util.TextRenderingMode.FILL; - this.fillColorSpace = _colorspace.ColorSpace.singletons.gray; - this.strokeColorSpace = _colorspace.ColorSpace.singletons.gray; - } - - clone() { - return Object.create(this); - } - -} - -class EvaluatorPreprocessor { - static get opMap() { - const getOPMap = (0, _core_utils.getLookupTableFactory)(function (t) { - t.w = { - id: _util.OPS.setLineWidth, - numArgs: 1, - variableArgs: false - }; - t.J = { - id: _util.OPS.setLineCap, - numArgs: 1, - variableArgs: false - }; - t.j = { - id: _util.OPS.setLineJoin, - numArgs: 1, - variableArgs: false - }; - t.M = { - id: _util.OPS.setMiterLimit, - numArgs: 1, - variableArgs: false - }; - t.d = { - id: _util.OPS.setDash, - numArgs: 2, - variableArgs: false - }; - t.ri = { - id: _util.OPS.setRenderingIntent, - numArgs: 1, - variableArgs: false - }; - t.i = { - id: _util.OPS.setFlatness, - numArgs: 1, - variableArgs: false - }; - t.gs = { - id: _util.OPS.setGState, - numArgs: 1, - variableArgs: false - }; - t.q = { - id: _util.OPS.save, - numArgs: 0, - variableArgs: false - }; - t.Q = { - id: _util.OPS.restore, - numArgs: 0, - variableArgs: false - }; - t.cm = { - id: _util.OPS.transform, - numArgs: 6, - variableArgs: false - }; - t.m = { - id: _util.OPS.moveTo, - numArgs: 2, - variableArgs: false - }; - t.l = { - id: _util.OPS.lineTo, - numArgs: 2, - variableArgs: false - }; - t.c = { - id: _util.OPS.curveTo, - numArgs: 6, - variableArgs: false - }; - t.v = { - id: _util.OPS.curveTo2, - numArgs: 4, - variableArgs: false - }; - t.y = { - id: _util.OPS.curveTo3, - numArgs: 4, - variableArgs: false - }; - t.h = { - id: _util.OPS.closePath, - numArgs: 0, - variableArgs: false - }; - t.re = { - id: _util.OPS.rectangle, - numArgs: 4, - variableArgs: false - }; - t.S = { - id: _util.OPS.stroke, - numArgs: 0, - variableArgs: false - }; - t.s = { - id: _util.OPS.closeStroke, - numArgs: 0, - variableArgs: false - }; - t.f = { - id: _util.OPS.fill, - numArgs: 0, - variableArgs: false - }; - t.F = { - id: _util.OPS.fill, - numArgs: 0, - variableArgs: false - }; - t["f*"] = { - id: _util.OPS.eoFill, - numArgs: 0, - variableArgs: false - }; - t.B = { - id: _util.OPS.fillStroke, - numArgs: 0, - variableArgs: false - }; - t["B*"] = { - id: _util.OPS.eoFillStroke, - numArgs: 0, - variableArgs: false - }; - t.b = { - id: _util.OPS.closeFillStroke, - numArgs: 0, - variableArgs: false - }; - t["b*"] = { - id: _util.OPS.closeEOFillStroke, - numArgs: 0, - variableArgs: false - }; - t.n = { - id: _util.OPS.endPath, - numArgs: 0, - variableArgs: false - }; - t.W = { - id: _util.OPS.clip, - numArgs: 0, - variableArgs: false - }; - t["W*"] = { - id: _util.OPS.eoClip, - numArgs: 0, - variableArgs: false - }; - t.BT = { - id: _util.OPS.beginText, - numArgs: 0, - variableArgs: false - }; - t.ET = { - id: _util.OPS.endText, - numArgs: 0, - variableArgs: false - }; - t.Tc = { - id: _util.OPS.setCharSpacing, - numArgs: 1, - variableArgs: false - }; - t.Tw = { - id: _util.OPS.setWordSpacing, - numArgs: 1, - variableArgs: false - }; - t.Tz = { - id: _util.OPS.setHScale, - numArgs: 1, - variableArgs: false - }; - t.TL = { - id: _util.OPS.setLeading, - numArgs: 1, - variableArgs: false - }; - t.Tf = { - id: _util.OPS.setFont, - numArgs: 2, - variableArgs: false - }; - t.Tr = { - id: _util.OPS.setTextRenderingMode, - numArgs: 1, - variableArgs: false - }; - t.Ts = { - id: _util.OPS.setTextRise, - numArgs: 1, - variableArgs: false - }; - t.Td = { - id: _util.OPS.moveText, - numArgs: 2, - variableArgs: false - }; - t.TD = { - id: _util.OPS.setLeadingMoveText, - numArgs: 2, - variableArgs: false - }; - t.Tm = { - id: _util.OPS.setTextMatrix, - numArgs: 6, - variableArgs: false - }; - t["T*"] = { - id: _util.OPS.nextLine, - numArgs: 0, - variableArgs: false - }; - t.Tj = { - id: _util.OPS.showText, - numArgs: 1, - variableArgs: false - }; - t.TJ = { - id: _util.OPS.showSpacedText, - numArgs: 1, - variableArgs: false - }; - t["'"] = { - id: _util.OPS.nextLineShowText, - numArgs: 1, - variableArgs: false - }; - t['"'] = { - id: _util.OPS.nextLineSetSpacingShowText, - numArgs: 3, - variableArgs: false - }; - t.d0 = { - id: _util.OPS.setCharWidth, - numArgs: 2, - variableArgs: false - }; - t.d1 = { - id: _util.OPS.setCharWidthAndBounds, - numArgs: 6, - variableArgs: false - }; - t.CS = { - id: _util.OPS.setStrokeColorSpace, - numArgs: 1, - variableArgs: false - }; - t.cs = { - id: _util.OPS.setFillColorSpace, - numArgs: 1, - variableArgs: false - }; - t.SC = { - id: _util.OPS.setStrokeColor, - numArgs: 4, - variableArgs: true - }; - t.SCN = { - id: _util.OPS.setStrokeColorN, - numArgs: 33, - variableArgs: true - }; - t.sc = { - id: _util.OPS.setFillColor, - numArgs: 4, - variableArgs: true - }; - t.scn = { - id: _util.OPS.setFillColorN, - numArgs: 33, - variableArgs: true - }; - t.G = { - id: _util.OPS.setStrokeGray, - numArgs: 1, - variableArgs: false - }; - t.g = { - id: _util.OPS.setFillGray, - numArgs: 1, - variableArgs: false - }; - t.RG = { - id: _util.OPS.setStrokeRGBColor, - numArgs: 3, - variableArgs: false - }; - t.rg = { - id: _util.OPS.setFillRGBColor, - numArgs: 3, - variableArgs: false - }; - t.K = { - id: _util.OPS.setStrokeCMYKColor, - numArgs: 4, - variableArgs: false - }; - t.k = { - id: _util.OPS.setFillCMYKColor, - numArgs: 4, - variableArgs: false - }; - t.sh = { - id: _util.OPS.shadingFill, - numArgs: 1, - variableArgs: false - }; - t.BI = { - id: _util.OPS.beginInlineImage, - numArgs: 0, - variableArgs: false - }; - t.ID = { - id: _util.OPS.beginImageData, - numArgs: 0, - variableArgs: false - }; - t.EI = { - id: _util.OPS.endInlineImage, - numArgs: 1, - variableArgs: false - }; - t.Do = { - id: _util.OPS.paintXObject, - numArgs: 1, - variableArgs: false - }; - t.MP = { - id: _util.OPS.markPoint, - numArgs: 1, - variableArgs: false - }; - t.DP = { - id: _util.OPS.markPointProps, - numArgs: 2, - variableArgs: false - }; - t.BMC = { - id: _util.OPS.beginMarkedContent, - numArgs: 1, - variableArgs: false - }; - t.BDC = { - id: _util.OPS.beginMarkedContentProps, - numArgs: 2, - variableArgs: false - }; - t.EMC = { - id: _util.OPS.endMarkedContent, - numArgs: 0, - variableArgs: false - }; - t.BX = { - id: _util.OPS.beginCompat, - numArgs: 0, - variableArgs: false - }; - t.EX = { - id: _util.OPS.endCompat, - numArgs: 0, - variableArgs: false - }; - t.BM = null; - t.BD = null; - t.true = null; - t.fa = null; - t.fal = null; - t.fals = null; - t.false = null; - t.nu = null; - t.nul = null; - t.null = null; - }); - return (0, _util.shadow)(this, "opMap", getOPMap()); - } - - static get MAX_INVALID_PATH_OPS() { - return (0, _util.shadow)(this, "MAX_INVALID_PATH_OPS", 20); - } - - constructor(stream, xref, stateManager = new StateManager()) { - this.parser = new _parser.Parser({ - lexer: new _parser.Lexer(stream, EvaluatorPreprocessor.opMap), - xref - }); - this.stateManager = stateManager; - this.nonProcessedArgs = []; - this._numInvalidPathOPS = 0; - } - - get savedStatesDepth() { - return this.stateManager.stateStack.length; - } - - read(operation) { - let args = operation.args; - - while (true) { - const obj = this.parser.getObj(); - - if (obj instanceof _primitives.Cmd) { - const cmd = obj.cmd; - const opSpec = EvaluatorPreprocessor.opMap[cmd]; - - if (!opSpec) { - (0, _util.warn)(`Unknown command "${cmd}".`); - continue; - } - - const fn = opSpec.id; - const numArgs = opSpec.numArgs; - let argsLength = args !== null ? args.length : 0; - - if (!opSpec.variableArgs) { - if (argsLength !== numArgs) { - const nonProcessedArgs = this.nonProcessedArgs; - - while (argsLength > numArgs) { - nonProcessedArgs.push(args.shift()); - argsLength--; - } - - while (argsLength < numArgs && nonProcessedArgs.length !== 0) { - if (args === null) { - args = []; - } - - args.unshift(nonProcessedArgs.pop()); - argsLength++; - } - } - - if (argsLength < numArgs) { - const partialMsg = `command ${cmd}: expected ${numArgs} args, ` + `but received ${argsLength} args.`; - - if (fn >= _util.OPS.moveTo && fn <= _util.OPS.endPath && ++this._numInvalidPathOPS > EvaluatorPreprocessor.MAX_INVALID_PATH_OPS) { - throw new _util.FormatError(`Invalid ${partialMsg}`); - } - - (0, _util.warn)(`Skipping ${partialMsg}`); - - if (args !== null) { - args.length = 0; - } - - continue; - } - } else if (argsLength > numArgs) { - (0, _util.info)(`Command ${cmd}: expected [0, ${numArgs}] args, ` + `but received ${argsLength} args.`); - } - - this.preprocessCommand(fn, args); - operation.fn = fn; - operation.args = args; - return true; - } - - if (obj === _primitives.EOF) { - return false; - } - - if (obj !== null) { - if (args === null) { - args = []; - } - - args.push(obj); - - if (args.length > 33) { - throw new _util.FormatError("Too many arguments"); - } - } - } - } - - preprocessCommand(fn, args) { - switch (fn | 0) { - case _util.OPS.save: - this.stateManager.save(); - break; - - case _util.OPS.restore: - this.stateManager.restore(); - break; - - case _util.OPS.transform: - this.stateManager.transform(args); - break; - } - } - -} - -exports.EvaluatorPreprocessor = EvaluatorPreprocessor; - -/***/ }), -/* 26 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.IdentityCMap = exports.CMapFactory = exports.CMap = void 0; - -var _util = __w_pdfjs_require__(2); - -var _primitives = __w_pdfjs_require__(5); - -var _parser = __w_pdfjs_require__(27); - -var _core_utils = __w_pdfjs_require__(9); - -var _stream = __w_pdfjs_require__(10); - -const BUILT_IN_CMAPS = ["Adobe-GB1-UCS2", "Adobe-CNS1-UCS2", "Adobe-Japan1-UCS2", "Adobe-Korea1-UCS2", "78-EUC-H", "78-EUC-V", "78-H", "78-RKSJ-H", "78-RKSJ-V", "78-V", "78ms-RKSJ-H", "78ms-RKSJ-V", "83pv-RKSJ-H", "90ms-RKSJ-H", "90ms-RKSJ-V", "90msp-RKSJ-H", "90msp-RKSJ-V", "90pv-RKSJ-H", "90pv-RKSJ-V", "Add-H", "Add-RKSJ-H", "Add-RKSJ-V", "Add-V", "Adobe-CNS1-0", "Adobe-CNS1-1", "Adobe-CNS1-2", "Adobe-CNS1-3", "Adobe-CNS1-4", "Adobe-CNS1-5", "Adobe-CNS1-6", "Adobe-GB1-0", "Adobe-GB1-1", "Adobe-GB1-2", "Adobe-GB1-3", "Adobe-GB1-4", "Adobe-GB1-5", "Adobe-Japan1-0", "Adobe-Japan1-1", "Adobe-Japan1-2", "Adobe-Japan1-3", "Adobe-Japan1-4", "Adobe-Japan1-5", "Adobe-Japan1-6", "Adobe-Korea1-0", "Adobe-Korea1-1", "Adobe-Korea1-2", "B5-H", "B5-V", "B5pc-H", "B5pc-V", "CNS-EUC-H", "CNS-EUC-V", "CNS1-H", "CNS1-V", "CNS2-H", "CNS2-V", "ETHK-B5-H", "ETHK-B5-V", "ETen-B5-H", "ETen-B5-V", "ETenms-B5-H", "ETenms-B5-V", "EUC-H", "EUC-V", "Ext-H", "Ext-RKSJ-H", "Ext-RKSJ-V", "Ext-V", "GB-EUC-H", "GB-EUC-V", "GB-H", "GB-V", "GBK-EUC-H", "GBK-EUC-V", "GBK2K-H", "GBK2K-V", "GBKp-EUC-H", "GBKp-EUC-V", "GBT-EUC-H", "GBT-EUC-V", "GBT-H", "GBT-V", "GBTpc-EUC-H", "GBTpc-EUC-V", "GBpc-EUC-H", "GBpc-EUC-V", "H", "HKdla-B5-H", "HKdla-B5-V", "HKdlb-B5-H", "HKdlb-B5-V", "HKgccs-B5-H", "HKgccs-B5-V", "HKm314-B5-H", "HKm314-B5-V", "HKm471-B5-H", "HKm471-B5-V", "HKscs-B5-H", "HKscs-B5-V", "Hankaku", "Hiragana", "KSC-EUC-H", "KSC-EUC-V", "KSC-H", "KSC-Johab-H", "KSC-Johab-V", "KSC-V", "KSCms-UHC-H", "KSCms-UHC-HW-H", "KSCms-UHC-HW-V", "KSCms-UHC-V", "KSCpc-EUC-H", "KSCpc-EUC-V", "Katakana", "NWP-H", "NWP-V", "RKSJ-H", "RKSJ-V", "Roman", "UniCNS-UCS2-H", "UniCNS-UCS2-V", "UniCNS-UTF16-H", "UniCNS-UTF16-V", "UniCNS-UTF32-H", "UniCNS-UTF32-V", "UniCNS-UTF8-H", "UniCNS-UTF8-V", "UniGB-UCS2-H", "UniGB-UCS2-V", "UniGB-UTF16-H", "UniGB-UTF16-V", "UniGB-UTF32-H", "UniGB-UTF32-V", "UniGB-UTF8-H", "UniGB-UTF8-V", "UniJIS-UCS2-H", "UniJIS-UCS2-HW-H", "UniJIS-UCS2-HW-V", "UniJIS-UCS2-V", "UniJIS-UTF16-H", "UniJIS-UTF16-V", "UniJIS-UTF32-H", "UniJIS-UTF32-V", "UniJIS-UTF8-H", "UniJIS-UTF8-V", "UniJIS2004-UTF16-H", "UniJIS2004-UTF16-V", "UniJIS2004-UTF32-H", "UniJIS2004-UTF32-V", "UniJIS2004-UTF8-H", "UniJIS2004-UTF8-V", "UniJISPro-UCS2-HW-V", "UniJISPro-UCS2-V", "UniJISPro-UTF8-V", "UniJISX0213-UTF32-H", "UniJISX0213-UTF32-V", "UniJISX02132004-UTF32-H", "UniJISX02132004-UTF32-V", "UniKS-UCS2-H", "UniKS-UCS2-V", "UniKS-UTF16-H", "UniKS-UTF16-V", "UniKS-UTF32-H", "UniKS-UTF32-V", "UniKS-UTF8-H", "UniKS-UTF8-V", "V", "WP-Symbol"]; -const MAX_MAP_RANGE = 2 ** 24 - 1; - -class CMap { - constructor(builtInCMap = false) { - this.codespaceRanges = [[], [], [], []]; - this.numCodespaceRanges = 0; - this._map = []; - this.name = ""; - this.vertical = false; - this.useCMap = null; - this.builtInCMap = builtInCMap; - } - - addCodespaceRange(n, low, high) { - this.codespaceRanges[n - 1].push(low, high); - this.numCodespaceRanges++; - } - - mapCidRange(low, high, dstLow) { - if (high - low > MAX_MAP_RANGE) { - throw new Error("mapCidRange - ignoring data above MAX_MAP_RANGE."); - } - - while (low <= high) { - this._map[low++] = dstLow++; - } - } - - mapBfRange(low, high, dstLow) { - if (high - low > MAX_MAP_RANGE) { - throw new Error("mapBfRange - ignoring data above MAX_MAP_RANGE."); - } - - const lastByte = dstLow.length - 1; - - while (low <= high) { - this._map[low++] = dstLow; - const nextCharCode = dstLow.charCodeAt(lastByte) + 1; - - if (nextCharCode > 0xff) { - dstLow = dstLow.substring(0, lastByte - 1) + String.fromCharCode(dstLow.charCodeAt(lastByte - 1) + 1) + "\x00"; - continue; - } - - dstLow = dstLow.substring(0, lastByte) + String.fromCharCode(nextCharCode); - } - } - - mapBfRangeToArray(low, high, array) { - if (high - low > MAX_MAP_RANGE) { - throw new Error("mapBfRangeToArray - ignoring data above MAX_MAP_RANGE."); - } - - const ii = array.length; - let i = 0; - - while (low <= high && i < ii) { - this._map[low] = array[i++]; - ++low; - } - } - - mapOne(src, dst) { - this._map[src] = dst; - } - - lookup(code) { - return this._map[code]; - } - - contains(code) { - return this._map[code] !== undefined; - } - - forEach(callback) { - const map = this._map; - const length = map.length; - - if (length <= 0x10000) { - for (let i = 0; i < length; i++) { - if (map[i] !== undefined) { - callback(i, map[i]); - } - } - } else { - for (const i in map) { - callback(i, map[i]); - } - } - } - - charCodeOf(value) { - const map = this._map; - - if (map.length <= 0x10000) { - return map.indexOf(value); - } - - for (const charCode in map) { - if (map[charCode] === value) { - return charCode | 0; - } - } - - return -1; - } - - getMap() { - return this._map; - } - - readCharCode(str, offset, out) { - let c = 0; - const codespaceRanges = this.codespaceRanges; - - for (let n = 0, nn = codespaceRanges.length; n < nn; n++) { - c = (c << 8 | str.charCodeAt(offset + n)) >>> 0; - const codespaceRange = codespaceRanges[n]; - - for (let k = 0, kk = codespaceRange.length; k < kk;) { - const low = codespaceRange[k++]; - const high = codespaceRange[k++]; - - if (c >= low && c <= high) { - out.charcode = c; - out.length = n + 1; - return; - } - } - } - - out.charcode = 0; - out.length = 1; - } - - getCharCodeLength(charCode) { - const codespaceRanges = this.codespaceRanges; - - for (let n = 0, nn = codespaceRanges.length; n < nn; n++) { - const codespaceRange = codespaceRanges[n]; - - for (let k = 0, kk = codespaceRange.length; k < kk;) { - const low = codespaceRange[k++]; - const high = codespaceRange[k++]; - - if (charCode >= low && charCode <= high) { - return n + 1; - } - } - } - - return 1; - } - - get length() { - return this._map.length; - } - - get isIdentityCMap() { - if (!(this.name === "Identity-H" || this.name === "Identity-V")) { - return false; - } - - if (this._map.length !== 0x10000) { - return false; - } - - for (let i = 0; i < 0x10000; i++) { - if (this._map[i] !== i) { - return false; - } - } - - return true; - } - -} - -exports.CMap = CMap; - -class IdentityCMap extends CMap { - constructor(vertical, n) { - super(); - this.vertical = vertical; - this.addCodespaceRange(n, 0, 0xffff); - } - - mapCidRange(low, high, dstLow) { - (0, _util.unreachable)("should not call mapCidRange"); - } - - mapBfRange(low, high, dstLow) { - (0, _util.unreachable)("should not call mapBfRange"); - } - - mapBfRangeToArray(low, high, array) { - (0, _util.unreachable)("should not call mapBfRangeToArray"); - } - - mapOne(src, dst) { - (0, _util.unreachable)("should not call mapCidOne"); - } - - lookup(code) { - return Number.isInteger(code) && code <= 0xffff ? code : undefined; - } - - contains(code) { - return Number.isInteger(code) && code <= 0xffff; - } - - forEach(callback) { - for (let i = 0; i <= 0xffff; i++) { - callback(i, i); - } - } - - charCodeOf(value) { - return Number.isInteger(value) && value <= 0xffff ? value : -1; - } - - getMap() { - const map = new Array(0x10000); - - for (let i = 0; i <= 0xffff; i++) { - map[i] = i; - } - - return map; - } - - get length() { - return 0x10000; - } - - get isIdentityCMap() { - (0, _util.unreachable)("should not access .isIdentityCMap"); - } - -} - -exports.IdentityCMap = IdentityCMap; - -const BinaryCMapReader = function BinaryCMapReaderClosure() { - function hexToInt(a, size) { - let n = 0; - - for (let i = 0; i <= size; i++) { - n = n << 8 | a[i]; - } - - return n >>> 0; - } - - function hexToStr(a, size) { - if (size === 1) { - return String.fromCharCode(a[0], a[1]); - } - - if (size === 3) { - return String.fromCharCode(a[0], a[1], a[2], a[3]); - } - - return String.fromCharCode.apply(null, a.subarray(0, size + 1)); - } - - function addHex(a, b, size) { - let c = 0; - - for (let i = size; i >= 0; i--) { - c += a[i] + b[i]; - a[i] = c & 255; - c >>= 8; - } - } - - function incHex(a, size) { - let c = 1; - - for (let i = size; i >= 0 && c > 0; i--) { - c += a[i]; - a[i] = c & 255; - c >>= 8; - } - } - - const MAX_NUM_SIZE = 16; - const MAX_ENCODED_NUM_SIZE = 19; - - class BinaryCMapStream { - constructor(data) { - this.buffer = data; - this.pos = 0; - this.end = data.length; - this.tmpBuf = new Uint8Array(MAX_ENCODED_NUM_SIZE); - } - - readByte() { - if (this.pos >= this.end) { - return -1; - } - - return this.buffer[this.pos++]; - } - - readNumber() { - let n = 0; - let last; - - do { - const b = this.readByte(); - - if (b < 0) { - throw new _util.FormatError("unexpected EOF in bcmap"); - } - - last = !(b & 0x80); - n = n << 7 | b & 0x7f; - } while (!last); - - return n; - } - - readSigned() { - const n = this.readNumber(); - return n & 1 ? ~(n >>> 1) : n >>> 1; - } - - readHex(num, size) { - num.set(this.buffer.subarray(this.pos, this.pos + size + 1)); - this.pos += size + 1; - } - - readHexNumber(num, size) { - let last; - const stack = this.tmpBuf; - let sp = 0; - - do { - const b = this.readByte(); - - if (b < 0) { - throw new _util.FormatError("unexpected EOF in bcmap"); - } - - last = !(b & 0x80); - stack[sp++] = b & 0x7f; - } while (!last); - - let i = size, - buffer = 0, - bufferSize = 0; - - while (i >= 0) { - while (bufferSize < 8 && stack.length > 0) { - buffer |= stack[--sp] << bufferSize; - bufferSize += 7; - } - - num[i] = buffer & 255; - i--; - buffer >>= 8; - bufferSize -= 8; - } - } - - readHexSigned(num, size) { - this.readHexNumber(num, size); - const sign = num[size] & 1 ? 255 : 0; - let c = 0; - - for (let i = 0; i <= size; i++) { - c = (c & 1) << 8 | num[i]; - num[i] = c >> 1 ^ sign; - } - } - - readString() { - const len = this.readNumber(); - let s = ""; - - for (let i = 0; i < len; i++) { - s += String.fromCharCode(this.readNumber()); - } - - return s; - } - - } - - class BinaryCMapReader { - async process(data, cMap, extend) { - const stream = new BinaryCMapStream(data); - const header = stream.readByte(); - cMap.vertical = !!(header & 1); - let useCMap = null; - const start = new Uint8Array(MAX_NUM_SIZE); - const end = new Uint8Array(MAX_NUM_SIZE); - const char = new Uint8Array(MAX_NUM_SIZE); - const charCode = new Uint8Array(MAX_NUM_SIZE); - const tmp = new Uint8Array(MAX_NUM_SIZE); - let code; - let b; - - while ((b = stream.readByte()) >= 0) { - const type = b >> 5; - - if (type === 7) { - switch (b & 0x1f) { - case 0: - stream.readString(); - break; - - case 1: - useCMap = stream.readString(); - break; - } - - continue; - } - - const sequence = !!(b & 0x10); - const dataSize = b & 15; - - if (dataSize + 1 > MAX_NUM_SIZE) { - throw new Error("BinaryCMapReader.process: Invalid dataSize."); - } - - const ucs2DataSize = 1; - const subitemsCount = stream.readNumber(); - - switch (type) { - case 0: - stream.readHex(start, dataSize); - stream.readHexNumber(end, dataSize); - addHex(end, start, dataSize); - cMap.addCodespaceRange(dataSize + 1, hexToInt(start, dataSize), hexToInt(end, dataSize)); - - for (let i = 1; i < subitemsCount; i++) { - incHex(end, dataSize); - stream.readHexNumber(start, dataSize); - addHex(start, end, dataSize); - stream.readHexNumber(end, dataSize); - addHex(end, start, dataSize); - cMap.addCodespaceRange(dataSize + 1, hexToInt(start, dataSize), hexToInt(end, dataSize)); - } - - break; - - case 1: - stream.readHex(start, dataSize); - stream.readHexNumber(end, dataSize); - addHex(end, start, dataSize); - stream.readNumber(); - - for (let i = 1; i < subitemsCount; i++) { - incHex(end, dataSize); - stream.readHexNumber(start, dataSize); - addHex(start, end, dataSize); - stream.readHexNumber(end, dataSize); - addHex(end, start, dataSize); - stream.readNumber(); - } - - break; - - case 2: - stream.readHex(char, dataSize); - code = stream.readNumber(); - cMap.mapOne(hexToInt(char, dataSize), code); - - for (let i = 1; i < subitemsCount; i++) { - incHex(char, dataSize); - - if (!sequence) { - stream.readHexNumber(tmp, dataSize); - addHex(char, tmp, dataSize); - } - - code = stream.readSigned() + (code + 1); - cMap.mapOne(hexToInt(char, dataSize), code); - } - - break; - - case 3: - stream.readHex(start, dataSize); - stream.readHexNumber(end, dataSize); - addHex(end, start, dataSize); - code = stream.readNumber(); - cMap.mapCidRange(hexToInt(start, dataSize), hexToInt(end, dataSize), code); - - for (let i = 1; i < subitemsCount; i++) { - incHex(end, dataSize); - - if (!sequence) { - stream.readHexNumber(start, dataSize); - addHex(start, end, dataSize); - } else { - start.set(end); - } - - stream.readHexNumber(end, dataSize); - addHex(end, start, dataSize); - code = stream.readNumber(); - cMap.mapCidRange(hexToInt(start, dataSize), hexToInt(end, dataSize), code); - } - - break; - - case 4: - stream.readHex(char, ucs2DataSize); - stream.readHex(charCode, dataSize); - cMap.mapOne(hexToInt(char, ucs2DataSize), hexToStr(charCode, dataSize)); - - for (let i = 1; i < subitemsCount; i++) { - incHex(char, ucs2DataSize); - - if (!sequence) { - stream.readHexNumber(tmp, ucs2DataSize); - addHex(char, tmp, ucs2DataSize); - } - - incHex(charCode, dataSize); - stream.readHexSigned(tmp, dataSize); - addHex(charCode, tmp, dataSize); - cMap.mapOne(hexToInt(char, ucs2DataSize), hexToStr(charCode, dataSize)); - } - - break; - - case 5: - stream.readHex(start, ucs2DataSize); - stream.readHexNumber(end, ucs2DataSize); - addHex(end, start, ucs2DataSize); - stream.readHex(charCode, dataSize); - cMap.mapBfRange(hexToInt(start, ucs2DataSize), hexToInt(end, ucs2DataSize), hexToStr(charCode, dataSize)); - - for (let i = 1; i < subitemsCount; i++) { - incHex(end, ucs2DataSize); - - if (!sequence) { - stream.readHexNumber(start, ucs2DataSize); - addHex(start, end, ucs2DataSize); - } else { - start.set(end); - } - - stream.readHexNumber(end, ucs2DataSize); - addHex(end, start, ucs2DataSize); - stream.readHex(charCode, dataSize); - cMap.mapBfRange(hexToInt(start, ucs2DataSize), hexToInt(end, ucs2DataSize), hexToStr(charCode, dataSize)); - } - - break; - - default: - throw new Error(`BinaryCMapReader.process - unknown type: ${type}`); - } - } - - if (useCMap) { - return extend(useCMap); - } - - return cMap; - } - - } - - return BinaryCMapReader; -}(); - -const CMapFactory = function CMapFactoryClosure() { - function strToInt(str) { - let a = 0; - - for (let i = 0; i < str.length; i++) { - a = a << 8 | str.charCodeAt(i); - } - - return a >>> 0; - } - - function expectString(obj) { - if (!(0, _util.isString)(obj)) { - throw new _util.FormatError("Malformed CMap: expected string."); - } - } - - function expectInt(obj) { - if (!Number.isInteger(obj)) { - throw new _util.FormatError("Malformed CMap: expected int."); - } - } - - function parseBfChar(cMap, lexer) { - while (true) { - let obj = lexer.getObj(); - - if (obj === _primitives.EOF) { - break; - } - - if ((0, _primitives.isCmd)(obj, "endbfchar")) { - return; - } - - expectString(obj); - const src = strToInt(obj); - obj = lexer.getObj(); - expectString(obj); - const dst = obj; - cMap.mapOne(src, dst); - } - } - - function parseBfRange(cMap, lexer) { - while (true) { - let obj = lexer.getObj(); - - if (obj === _primitives.EOF) { - break; - } - - if ((0, _primitives.isCmd)(obj, "endbfrange")) { - return; - } - - expectString(obj); - const low = strToInt(obj); - obj = lexer.getObj(); - expectString(obj); - const high = strToInt(obj); - obj = lexer.getObj(); - - if (Number.isInteger(obj) || (0, _util.isString)(obj)) { - const dstLow = Number.isInteger(obj) ? String.fromCharCode(obj) : obj; - cMap.mapBfRange(low, high, dstLow); - } else if ((0, _primitives.isCmd)(obj, "[")) { - obj = lexer.getObj(); - const array = []; - - while (!(0, _primitives.isCmd)(obj, "]") && obj !== _primitives.EOF) { - array.push(obj); - obj = lexer.getObj(); - } - - cMap.mapBfRangeToArray(low, high, array); - } else { - break; - } - } - - throw new _util.FormatError("Invalid bf range."); - } - - function parseCidChar(cMap, lexer) { - while (true) { - let obj = lexer.getObj(); - - if (obj === _primitives.EOF) { - break; - } - - if ((0, _primitives.isCmd)(obj, "endcidchar")) { - return; - } - - expectString(obj); - const src = strToInt(obj); - obj = lexer.getObj(); - expectInt(obj); - const dst = obj; - cMap.mapOne(src, dst); - } - } - - function parseCidRange(cMap, lexer) { - while (true) { - let obj = lexer.getObj(); - - if (obj === _primitives.EOF) { - break; - } - - if ((0, _primitives.isCmd)(obj, "endcidrange")) { - return; - } - - expectString(obj); - const low = strToInt(obj); - obj = lexer.getObj(); - expectString(obj); - const high = strToInt(obj); - obj = lexer.getObj(); - expectInt(obj); - const dstLow = obj; - cMap.mapCidRange(low, high, dstLow); - } - } - - function parseCodespaceRange(cMap, lexer) { - while (true) { - let obj = lexer.getObj(); - - if (obj === _primitives.EOF) { - break; - } - - if ((0, _primitives.isCmd)(obj, "endcodespacerange")) { - return; - } - - if (!(0, _util.isString)(obj)) { - break; - } - - const low = strToInt(obj); - obj = lexer.getObj(); - - if (!(0, _util.isString)(obj)) { - break; - } - - const high = strToInt(obj); - cMap.addCodespaceRange(obj.length, low, high); - } - - throw new _util.FormatError("Invalid codespace range."); - } - - function parseWMode(cMap, lexer) { - const obj = lexer.getObj(); - - if (Number.isInteger(obj)) { - cMap.vertical = !!obj; - } - } - - function parseCMapName(cMap, lexer) { - const obj = lexer.getObj(); - - if ((0, _primitives.isName)(obj) && (0, _util.isString)(obj.name)) { - cMap.name = obj.name; - } - } - - async function parseCMap(cMap, lexer, fetchBuiltInCMap, useCMap) { - let previous, embeddedUseCMap; - - objLoop: while (true) { - try { - const obj = lexer.getObj(); - - if (obj === _primitives.EOF) { - break; - } else if ((0, _primitives.isName)(obj)) { - if (obj.name === "WMode") { - parseWMode(cMap, lexer); - } else if (obj.name === "CMapName") { - parseCMapName(cMap, lexer); - } - - previous = obj; - } else if ((0, _primitives.isCmd)(obj)) { - switch (obj.cmd) { - case "endcmap": - break objLoop; - - case "usecmap": - if ((0, _primitives.isName)(previous)) { - embeddedUseCMap = previous.name; - } - - break; - - case "begincodespacerange": - parseCodespaceRange(cMap, lexer); - break; - - case "beginbfchar": - parseBfChar(cMap, lexer); - break; - - case "begincidchar": - parseCidChar(cMap, lexer); - break; - - case "beginbfrange": - parseBfRange(cMap, lexer); - break; - - case "begincidrange": - parseCidRange(cMap, lexer); - break; - } - } - } catch (ex) { - if (ex instanceof _core_utils.MissingDataException) { - throw ex; - } - - (0, _util.warn)("Invalid cMap data: " + ex); - continue; - } - } - - if (!useCMap && embeddedUseCMap) { - useCMap = embeddedUseCMap; - } - - if (useCMap) { - return extendCMap(cMap, fetchBuiltInCMap, useCMap); - } - - return cMap; - } - - async function extendCMap(cMap, fetchBuiltInCMap, useCMap) { - cMap.useCMap = await createBuiltInCMap(useCMap, fetchBuiltInCMap); - - if (cMap.numCodespaceRanges === 0) { - const useCodespaceRanges = cMap.useCMap.codespaceRanges; - - for (let i = 0; i < useCodespaceRanges.length; i++) { - cMap.codespaceRanges[i] = useCodespaceRanges[i].slice(); - } - - cMap.numCodespaceRanges = cMap.useCMap.numCodespaceRanges; - } - - cMap.useCMap.forEach(function (key, value) { - if (!cMap.contains(key)) { - cMap.mapOne(key, cMap.useCMap.lookup(key)); - } - }); - return cMap; - } - - async function createBuiltInCMap(name, fetchBuiltInCMap) { - if (name === "Identity-H") { - return new IdentityCMap(false, 2); - } else if (name === "Identity-V") { - return new IdentityCMap(true, 2); - } - - if (!BUILT_IN_CMAPS.includes(name)) { - throw new Error("Unknown CMap name: " + name); - } - - if (!fetchBuiltInCMap) { - throw new Error("Built-in CMap parameters are not provided."); - } - - const { - cMapData, - compressionType - } = await fetchBuiltInCMap(name); - const cMap = new CMap(true); - - if (compressionType === _util.CMapCompressionType.BINARY) { - return new BinaryCMapReader().process(cMapData, cMap, useCMap => { - return extendCMap(cMap, fetchBuiltInCMap, useCMap); - }); - } - - if (compressionType === _util.CMapCompressionType.NONE) { - const lexer = new _parser.Lexer(new _stream.Stream(cMapData)); - return parseCMap(cMap, lexer, fetchBuiltInCMap, null); - } - - throw new Error("TODO: Only BINARY/NONE CMap compression is currently supported."); - } - - return { - async create(params) { - const encoding = params.encoding; - const fetchBuiltInCMap = params.fetchBuiltInCMap; - const useCMap = params.useCMap; - - if ((0, _primitives.isName)(encoding)) { - return createBuiltInCMap(encoding.name, fetchBuiltInCMap); - } else if ((0, _primitives.isStream)(encoding)) { - const parsedCMap = await parseCMap(new CMap(), new _parser.Lexer(encoding), fetchBuiltInCMap, useCMap); - - if (parsedCMap.isIdentityCMap) { - return createBuiltInCMap(parsedCMap.name, fetchBuiltInCMap); - } - - return parsedCMap; - } - - throw new Error("Encoding required."); - } - - }; -}(); - -exports.CMapFactory = CMapFactory; - -/***/ }), -/* 27 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.Parser = exports.Linearization = exports.Lexer = void 0; - -var _util = __w_pdfjs_require__(2); - -var _primitives = __w_pdfjs_require__(5); - -var _core_utils = __w_pdfjs_require__(9); - -var _ascii_85_stream = __w_pdfjs_require__(28); - -var _ascii_hex_stream = __w_pdfjs_require__(30); - -var _ccitt_stream = __w_pdfjs_require__(31); - -var _flate_stream = __w_pdfjs_require__(33); - -var _jbig2_stream = __w_pdfjs_require__(34); - -var _jpeg_stream = __w_pdfjs_require__(37); - -var _jpx_stream = __w_pdfjs_require__(39); - -var _lzw_stream = __w_pdfjs_require__(41); - -var _stream = __w_pdfjs_require__(10); - -var _predictor_stream = __w_pdfjs_require__(42); - -var _run_length_stream = __w_pdfjs_require__(43); - -const MAX_LENGTH_TO_CACHE = 1000; -const MAX_ADLER32_LENGTH = 5552; - -function computeAdler32(bytes) { - const bytesLength = bytes.length; - let a = 1, - b = 0; - - for (let i = 0; i < bytesLength; ++i) { - a += bytes[i] & 0xff; - b += a; - } - - return b % 65521 << 16 | a % 65521; -} - -class Parser { - constructor({ - lexer, - xref, - allowStreams = false, - recoveryMode = false - }) { - this.lexer = lexer; - this.xref = xref; - this.allowStreams = allowStreams; - this.recoveryMode = recoveryMode; - this.imageCache = Object.create(null); - this.refill(); - } - - refill() { - this.buf1 = this.lexer.getObj(); - this.buf2 = this.lexer.getObj(); - } - - shift() { - if (this.buf2 instanceof _primitives.Cmd && this.buf2.cmd === "ID") { - this.buf1 = this.buf2; - this.buf2 = null; - } else { - this.buf1 = this.buf2; - this.buf2 = this.lexer.getObj(); - } - } - - tryShift() { - try { - this.shift(); - return true; - } catch (e) { - if (e instanceof _core_utils.MissingDataException) { - throw e; - } - - return false; - } - } - - getObj(cipherTransform = null) { - const buf1 = this.buf1; - this.shift(); - - if (buf1 instanceof _primitives.Cmd) { - switch (buf1.cmd) { - case "BI": - return this.makeInlineImage(cipherTransform); - - case "[": - const array = []; - - while (!(0, _primitives.isCmd)(this.buf1, "]") && this.buf1 !== _primitives.EOF) { - array.push(this.getObj(cipherTransform)); - } - - if (this.buf1 === _primitives.EOF) { - if (this.recoveryMode) { - return array; - } - - throw new _core_utils.ParserEOFException("End of file inside array."); - } - - this.shift(); - return array; - - case "<<": - const dict = new _primitives.Dict(this.xref); - - while (!(0, _primitives.isCmd)(this.buf1, ">>") && this.buf1 !== _primitives.EOF) { - if (!(0, _primitives.isName)(this.buf1)) { - (0, _util.info)("Malformed dictionary: key must be a name object"); - this.shift(); - continue; - } - - const key = this.buf1.name; - this.shift(); - - if (this.buf1 === _primitives.EOF) { - break; - } - - dict.set(key, this.getObj(cipherTransform)); - } - - if (this.buf1 === _primitives.EOF) { - if (this.recoveryMode) { - return dict; - } - - throw new _core_utils.ParserEOFException("End of file inside dictionary."); - } - - if ((0, _primitives.isCmd)(this.buf2, "stream")) { - return this.allowStreams ? this.makeStream(dict, cipherTransform) : dict; - } - - this.shift(); - return dict; - - default: - return buf1; - } - } - - if (Number.isInteger(buf1)) { - if (Number.isInteger(this.buf1) && (0, _primitives.isCmd)(this.buf2, "R")) { - const ref = _primitives.Ref.get(buf1, this.buf1); - - this.shift(); - this.shift(); - return ref; - } - - return buf1; - } - - if (typeof buf1 === "string") { - if (cipherTransform) { - return cipherTransform.decryptString(buf1); - } - - return buf1; - } - - return buf1; - } - - findDefaultInlineStreamEnd(stream) { - const E = 0x45, - I = 0x49, - SPACE = 0x20, - LF = 0xa, - CR = 0xd, - NUL = 0x0; - const lexer = this.lexer, - startPos = stream.pos, - n = 10; - let state = 0, - ch, - maybeEIPos; - - while ((ch = stream.getByte()) !== -1) { - if (state === 0) { - state = ch === E ? 1 : 0; - } else if (state === 1) { - state = ch === I ? 2 : 0; - } else { - (0, _util.assert)(state === 2, "findDefaultInlineStreamEnd - invalid state."); - - if (ch === SPACE || ch === LF || ch === CR) { - maybeEIPos = stream.pos; - const followingBytes = stream.peekBytes(n); - - for (let i = 0, ii = followingBytes.length; i < ii; i++) { - ch = followingBytes[i]; - - if (ch === NUL && followingBytes[i + 1] !== NUL) { - continue; - } - - if (ch !== LF && ch !== CR && (ch < SPACE || ch > 0x7f)) { - state = 0; - break; - } - } - - if (state !== 2) { - continue; - } - - if (lexer.knownCommands) { - const nextObj = lexer.peekObj(); - - if (nextObj instanceof _primitives.Cmd && !lexer.knownCommands[nextObj.cmd]) { - state = 0; - } - } else { - (0, _util.warn)("findDefaultInlineStreamEnd - `lexer.knownCommands` is undefined."); - } - - if (state === 2) { - break; - } - } else { - state = 0; - } - } - } - - if (ch === -1) { - (0, _util.warn)("findDefaultInlineStreamEnd: " + "Reached the end of the stream without finding a valid EI marker"); - - if (maybeEIPos) { - (0, _util.warn)('... trying to recover by using the last "EI" occurrence.'); - stream.skip(-(stream.pos - maybeEIPos)); - } - } - - let endOffset = 4; - stream.skip(-endOffset); - ch = stream.peekByte(); - stream.skip(endOffset); - - if (!(0, _core_utils.isWhiteSpace)(ch)) { - endOffset--; - } - - return stream.pos - endOffset - startPos; - } - - findDCTDecodeInlineStreamEnd(stream) { - const startPos = stream.pos; - let foundEOI = false, - b, - markerLength; - - while ((b = stream.getByte()) !== -1) { - if (b !== 0xff) { - continue; - } - - switch (stream.getByte()) { - case 0x00: - break; - - case 0xff: - stream.skip(-1); - break; - - case 0xd9: - foundEOI = true; - break; - - case 0xc0: - case 0xc1: - case 0xc2: - case 0xc3: - case 0xc5: - case 0xc6: - case 0xc7: - case 0xc9: - case 0xca: - case 0xcb: - case 0xcd: - case 0xce: - case 0xcf: - case 0xc4: - case 0xcc: - case 0xda: - case 0xdb: - case 0xdc: - case 0xdd: - case 0xde: - case 0xdf: - case 0xe0: - case 0xe1: - case 0xe2: - case 0xe3: - case 0xe4: - case 0xe5: - case 0xe6: - case 0xe7: - case 0xe8: - case 0xe9: - case 0xea: - case 0xeb: - case 0xec: - case 0xed: - case 0xee: - case 0xef: - case 0xfe: - markerLength = stream.getUint16(); - - if (markerLength > 2) { - stream.skip(markerLength - 2); - } else { - stream.skip(-2); - } - - break; - } - - if (foundEOI) { - break; - } - } - - const length = stream.pos - startPos; - - if (b === -1) { - (0, _util.warn)("Inline DCTDecode image stream: " + "EOI marker not found, searching for /EI/ instead."); - stream.skip(-length); - return this.findDefaultInlineStreamEnd(stream); - } - - this.inlineStreamSkipEI(stream); - return length; - } - - findASCII85DecodeInlineStreamEnd(stream) { - const TILDE = 0x7e, - GT = 0x3e; - const startPos = stream.pos; - let ch; - - while ((ch = stream.getByte()) !== -1) { - if (ch === TILDE) { - const tildePos = stream.pos; - ch = stream.peekByte(); - - while ((0, _core_utils.isWhiteSpace)(ch)) { - stream.skip(); - ch = stream.peekByte(); - } - - if (ch === GT) { - stream.skip(); - break; - } - - if (stream.pos > tildePos) { - const maybeEI = stream.peekBytes(2); - - if (maybeEI[0] === 0x45 && maybeEI[1] === 0x49) { - break; - } - } - } - } - - const length = stream.pos - startPos; - - if (ch === -1) { - (0, _util.warn)("Inline ASCII85Decode image stream: " + "EOD marker not found, searching for /EI/ instead."); - stream.skip(-length); - return this.findDefaultInlineStreamEnd(stream); - } - - this.inlineStreamSkipEI(stream); - return length; - } - - findASCIIHexDecodeInlineStreamEnd(stream) { - const GT = 0x3e; - const startPos = stream.pos; - let ch; - - while ((ch = stream.getByte()) !== -1) { - if (ch === GT) { - break; - } - } - - const length = stream.pos - startPos; - - if (ch === -1) { - (0, _util.warn)("Inline ASCIIHexDecode image stream: " + "EOD marker not found, searching for /EI/ instead."); - stream.skip(-length); - return this.findDefaultInlineStreamEnd(stream); - } - - this.inlineStreamSkipEI(stream); - return length; - } - - inlineStreamSkipEI(stream) { - const E = 0x45, - I = 0x49; - let state = 0, - ch; - - while ((ch = stream.getByte()) !== -1) { - if (state === 0) { - state = ch === E ? 1 : 0; - } else if (state === 1) { - state = ch === I ? 2 : 0; - } else if (state === 2) { - break; - } - } - } - - makeInlineImage(cipherTransform) { - const lexer = this.lexer; - const stream = lexer.stream; - const dict = new _primitives.Dict(this.xref); - let dictLength; - - while (!(0, _primitives.isCmd)(this.buf1, "ID") && this.buf1 !== _primitives.EOF) { - if (!(0, _primitives.isName)(this.buf1)) { - throw new _util.FormatError("Dictionary key must be a name object"); - } - - const key = this.buf1.name; - this.shift(); - - if (this.buf1 === _primitives.EOF) { - break; - } - - dict.set(key, this.getObj(cipherTransform)); - } - - if (lexer.beginInlineImagePos !== -1) { - dictLength = stream.pos - lexer.beginInlineImagePos; - } - - const filter = dict.get("F", "Filter"); - let filterName; - - if ((0, _primitives.isName)(filter)) { - filterName = filter.name; - } else if (Array.isArray(filter)) { - const filterZero = this.xref.fetchIfRef(filter[0]); - - if ((0, _primitives.isName)(filterZero)) { - filterName = filterZero.name; - } - } - - const startPos = stream.pos; - let length; - - switch (filterName) { - case "DCT": - case "DCTDecode": - length = this.findDCTDecodeInlineStreamEnd(stream); - break; - - case "A85": - case "ASCII85Decode": - length = this.findASCII85DecodeInlineStreamEnd(stream); - break; - - case "AHx": - case "ASCIIHexDecode": - length = this.findASCIIHexDecodeInlineStreamEnd(stream); - break; - - default: - length = this.findDefaultInlineStreamEnd(stream); - } - - let imageStream = stream.makeSubStream(startPos, length, dict); - let cacheKey; - - if (length < MAX_LENGTH_TO_CACHE && dictLength < MAX_ADLER32_LENGTH) { - const imageBytes = imageStream.getBytes(); - imageStream.reset(); - const initialStreamPos = stream.pos; - stream.pos = lexer.beginInlineImagePos; - const dictBytes = stream.getBytes(dictLength); - stream.pos = initialStreamPos; - cacheKey = computeAdler32(imageBytes) + "_" + computeAdler32(dictBytes); - const cacheEntry = this.imageCache[cacheKey]; - - if (cacheEntry !== undefined) { - this.buf2 = _primitives.Cmd.get("EI"); - this.shift(); - cacheEntry.reset(); - return cacheEntry; - } - } - - if (cipherTransform) { - imageStream = cipherTransform.createStream(imageStream, length); - } - - imageStream = this.filter(imageStream, dict, length); - imageStream.dict = dict; - - if (cacheKey !== undefined) { - imageStream.cacheKey = `inline_${length}_${cacheKey}`; - this.imageCache[cacheKey] = imageStream; - } - - this.buf2 = _primitives.Cmd.get("EI"); - this.shift(); - return imageStream; - } - - _findStreamLength(startPos, signature) { - const { - stream - } = this.lexer; - stream.pos = startPos; - const SCAN_BLOCK_LENGTH = 2048; - const signatureLength = signature.length; - - while (stream.pos < stream.end) { - const scanBytes = stream.peekBytes(SCAN_BLOCK_LENGTH); - const scanLength = scanBytes.length - signatureLength; - - if (scanLength <= 0) { - break; - } - - let pos = 0; - - while (pos < scanLength) { - let j = 0; - - while (j < signatureLength && scanBytes[pos + j] === signature[j]) { - j++; - } - - if (j >= signatureLength) { - stream.pos += pos; - return stream.pos - startPos; - } - - pos++; - } - - stream.pos += scanLength; - } - - return -1; - } - - makeStream(dict, cipherTransform) { - const lexer = this.lexer; - let stream = lexer.stream; - lexer.skipToNextLine(); - const startPos = stream.pos - 1; - let length = dict.get("Length"); - - if (!Number.isInteger(length)) { - (0, _util.info)(`Bad length "${length && length.toString()}" in stream.`); - length = 0; - } - - stream.pos = startPos + length; - lexer.nextChar(); - - if (this.tryShift() && (0, _primitives.isCmd)(this.buf2, "endstream")) { - this.shift(); - } else { - const ENDSTREAM_SIGNATURE = new Uint8Array([0x65, 0x6e, 0x64, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d]); - - let actualLength = this._findStreamLength(startPos, ENDSTREAM_SIGNATURE); - - if (actualLength < 0) { - const MAX_TRUNCATION = 1; - - for (let i = 1; i <= MAX_TRUNCATION; i++) { - const end = ENDSTREAM_SIGNATURE.length - i; - const TRUNCATED_SIGNATURE = ENDSTREAM_SIGNATURE.slice(0, end); - - const maybeLength = this._findStreamLength(startPos, TRUNCATED_SIGNATURE); - - if (maybeLength >= 0) { - const lastByte = stream.peekBytes(end + 1)[end]; - - if (!(0, _core_utils.isWhiteSpace)(lastByte)) { - break; - } - - (0, _util.info)(`Found "${(0, _util.bytesToString)(TRUNCATED_SIGNATURE)}" when ` + "searching for endstream command."); - actualLength = maybeLength; - break; - } - } - - if (actualLength < 0) { - throw new _util.FormatError("Missing endstream command."); - } - } - - length = actualLength; - lexer.nextChar(); - this.shift(); - this.shift(); - } - - this.shift(); - stream = stream.makeSubStream(startPos, length, dict); - - if (cipherTransform) { - stream = cipherTransform.createStream(stream, length); - } - - stream = this.filter(stream, dict, length); - stream.dict = dict; - return stream; - } - - filter(stream, dict, length) { - let filter = dict.get("F", "Filter"); - let params = dict.get("DP", "DecodeParms"); - - if ((0, _primitives.isName)(filter)) { - if (Array.isArray(params)) { - (0, _util.warn)("/DecodeParms should not be an Array, when /Filter is a Name."); - } - - return this.makeFilter(stream, filter.name, length, params); - } - - let maybeLength = length; - - if (Array.isArray(filter)) { - const filterArray = filter; - const paramsArray = params; - - for (let i = 0, ii = filterArray.length; i < ii; ++i) { - filter = this.xref.fetchIfRef(filterArray[i]); - - if (!(0, _primitives.isName)(filter)) { - throw new _util.FormatError(`Bad filter name "${filter}"`); - } - - params = null; - - if (Array.isArray(paramsArray) && i in paramsArray) { - params = this.xref.fetchIfRef(paramsArray[i]); - } - - stream = this.makeFilter(stream, filter.name, maybeLength, params); - maybeLength = null; - } - } - - return stream; - } - - makeFilter(stream, name, maybeLength, params) { - if (maybeLength === 0) { - (0, _util.warn)(`Empty "${name}" stream.`); - return new _stream.NullStream(); - } - - const xrefStats = this.xref.stats; - - try { - switch (name) { - case "Fl": - case "FlateDecode": - xrefStats.addStreamType(_util.StreamType.FLATE); - - if (params) { - return new _predictor_stream.PredictorStream(new _flate_stream.FlateStream(stream, maybeLength), maybeLength, params); - } - - return new _flate_stream.FlateStream(stream, maybeLength); - - case "LZW": - case "LZWDecode": - xrefStats.addStreamType(_util.StreamType.LZW); - let earlyChange = 1; - - if (params) { - if (params.has("EarlyChange")) { - earlyChange = params.get("EarlyChange"); - } - - return new _predictor_stream.PredictorStream(new _lzw_stream.LZWStream(stream, maybeLength, earlyChange), maybeLength, params); - } - - return new _lzw_stream.LZWStream(stream, maybeLength, earlyChange); - - case "DCT": - case "DCTDecode": - xrefStats.addStreamType(_util.StreamType.DCT); - return new _jpeg_stream.JpegStream(stream, maybeLength, params); - - case "JPX": - case "JPXDecode": - xrefStats.addStreamType(_util.StreamType.JPX); - return new _jpx_stream.JpxStream(stream, maybeLength, params); - - case "A85": - case "ASCII85Decode": - xrefStats.addStreamType(_util.StreamType.A85); - return new _ascii_85_stream.Ascii85Stream(stream, maybeLength); - - case "AHx": - case "ASCIIHexDecode": - xrefStats.addStreamType(_util.StreamType.AHX); - return new _ascii_hex_stream.AsciiHexStream(stream, maybeLength); - - case "CCF": - case "CCITTFaxDecode": - xrefStats.addStreamType(_util.StreamType.CCF); - return new _ccitt_stream.CCITTFaxStream(stream, maybeLength, params); - - case "RL": - case "RunLengthDecode": - xrefStats.addStreamType(_util.StreamType.RLX); - return new _run_length_stream.RunLengthStream(stream, maybeLength); - - case "JBIG2Decode": - xrefStats.addStreamType(_util.StreamType.JBIG); - return new _jbig2_stream.Jbig2Stream(stream, maybeLength, params); - } - - (0, _util.warn)(`Filter "${name}" is not supported.`); - return stream; - } catch (ex) { - if (ex instanceof _core_utils.MissingDataException) { - throw ex; - } - - (0, _util.warn)(`Invalid stream: "${ex}"`); - return new _stream.NullStream(); - } - } - -} - -exports.Parser = Parser; -const specialChars = [1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; - -function toHexDigit(ch) { - if (ch >= 0x30 && ch <= 0x39) { - return ch & 0x0f; - } - - if (ch >= 0x41 && ch <= 0x46 || ch >= 0x61 && ch <= 0x66) { - return (ch & 0x0f) + 9; - } - - return -1; -} - -class Lexer { - constructor(stream, knownCommands = null) { - this.stream = stream; - this.nextChar(); - this.strBuf = []; - this.knownCommands = knownCommands; - this._hexStringNumWarn = 0; - this.beginInlineImagePos = -1; - } - - nextChar() { - return this.currentChar = this.stream.getByte(); - } - - peekChar() { - return this.stream.peekByte(); - } - - getNumber() { - let ch = this.currentChar; - let eNotation = false; - let divideBy = 0; - let sign = 0; - - if (ch === 0x2d) { - sign = -1; - ch = this.nextChar(); - - if (ch === 0x2d) { - ch = this.nextChar(); - } - } else if (ch === 0x2b) { - sign = 1; - ch = this.nextChar(); - } - - if (ch === 0x0a || ch === 0x0d) { - do { - ch = this.nextChar(); - } while (ch === 0x0a || ch === 0x0d); - } - - if (ch === 0x2e) { - divideBy = 10; - ch = this.nextChar(); - } - - if (ch < 0x30 || ch > 0x39) { - if (divideBy === 10 && sign === 0 && ((0, _core_utils.isWhiteSpace)(ch) || ch === -1)) { - (0, _util.warn)("Lexer.getNumber - treating a single decimal point as zero."); - return 0; - } - - throw new _util.FormatError(`Invalid number: ${String.fromCharCode(ch)} (charCode ${ch})`); - } - - sign = sign || 1; - let baseValue = ch - 0x30; - let powerValue = 0; - let powerValueSign = 1; - - while ((ch = this.nextChar()) >= 0) { - if (ch >= 0x30 && ch <= 0x39) { - const currentDigit = ch - 0x30; - - if (eNotation) { - powerValue = powerValue * 10 + currentDigit; - } else { - if (divideBy !== 0) { - divideBy *= 10; - } - - baseValue = baseValue * 10 + currentDigit; - } - } else if (ch === 0x2e) { - if (divideBy === 0) { - divideBy = 1; - } else { - break; - } - } else if (ch === 0x2d) { - (0, _util.warn)("Badly formatted number: minus sign in the middle"); - } else if (ch === 0x45 || ch === 0x65) { - ch = this.peekChar(); - - if (ch === 0x2b || ch === 0x2d) { - powerValueSign = ch === 0x2d ? -1 : 1; - this.nextChar(); - } else if (ch < 0x30 || ch > 0x39) { - break; - } - - eNotation = true; - } else { - break; - } - } - - if (divideBy !== 0) { - baseValue /= divideBy; - } - - if (eNotation) { - baseValue *= 10 ** (powerValueSign * powerValue); - } - - return sign * baseValue; - } - - getString() { - let numParen = 1; - let done = false; - const strBuf = this.strBuf; - strBuf.length = 0; - let ch = this.nextChar(); - - while (true) { - let charBuffered = false; - - switch (ch | 0) { - case -1: - (0, _util.warn)("Unterminated string"); - done = true; - break; - - case 0x28: - ++numParen; - strBuf.push("("); - break; - - case 0x29: - if (--numParen === 0) { - this.nextChar(); - done = true; - } else { - strBuf.push(")"); - } - - break; - - case 0x5c: - ch = this.nextChar(); - - switch (ch) { - case -1: - (0, _util.warn)("Unterminated string"); - done = true; - break; - - case 0x6e: - strBuf.push("\n"); - break; - - case 0x72: - strBuf.push("\r"); - break; - - case 0x74: - strBuf.push("\t"); - break; - - case 0x62: - strBuf.push("\b"); - break; - - case 0x66: - strBuf.push("\f"); - break; - - case 0x5c: - case 0x28: - case 0x29: - strBuf.push(String.fromCharCode(ch)); - break; - - case 0x30: - case 0x31: - case 0x32: - case 0x33: - case 0x34: - case 0x35: - case 0x36: - case 0x37: - let x = ch & 0x0f; - ch = this.nextChar(); - charBuffered = true; - - if (ch >= 0x30 && ch <= 0x37) { - x = (x << 3) + (ch & 0x0f); - ch = this.nextChar(); - - if (ch >= 0x30 && ch <= 0x37) { - charBuffered = false; - x = (x << 3) + (ch & 0x0f); - } - } - - strBuf.push(String.fromCharCode(x)); - break; - - case 0x0d: - if (this.peekChar() === 0x0a) { - this.nextChar(); - } - - break; - - case 0x0a: - break; - - default: - strBuf.push(String.fromCharCode(ch)); - break; - } - - break; - - default: - strBuf.push(String.fromCharCode(ch)); - break; - } - - if (done) { - break; - } - - if (!charBuffered) { - ch = this.nextChar(); - } - } - - return strBuf.join(""); - } - - getName() { - let ch, previousCh; - const strBuf = this.strBuf; - strBuf.length = 0; - - while ((ch = this.nextChar()) >= 0 && !specialChars[ch]) { - if (ch === 0x23) { - ch = this.nextChar(); - - if (specialChars[ch]) { - (0, _util.warn)("Lexer_getName: " + "NUMBER SIGN (#) should be followed by a hexadecimal number."); - strBuf.push("#"); - break; - } - - const x = toHexDigit(ch); - - if (x !== -1) { - previousCh = ch; - ch = this.nextChar(); - const x2 = toHexDigit(ch); - - if (x2 === -1) { - (0, _util.warn)(`Lexer_getName: Illegal digit (${String.fromCharCode(ch)}) ` + "in hexadecimal number."); - strBuf.push("#", String.fromCharCode(previousCh)); - - if (specialChars[ch]) { - break; - } - - strBuf.push(String.fromCharCode(ch)); - continue; - } - - strBuf.push(String.fromCharCode(x << 4 | x2)); - } else { - strBuf.push("#", String.fromCharCode(ch)); - } - } else { - strBuf.push(String.fromCharCode(ch)); - } - } - - if (strBuf.length > 127) { - (0, _util.warn)(`Name token is longer than allowed by the spec: ${strBuf.length}`); - } - - return _primitives.Name.get(strBuf.join("")); - } - - _hexStringWarn(ch) { - const MAX_HEX_STRING_NUM_WARN = 5; - - if (this._hexStringNumWarn++ === MAX_HEX_STRING_NUM_WARN) { - (0, _util.warn)("getHexString - ignoring additional invalid characters."); - return; - } - - if (this._hexStringNumWarn > MAX_HEX_STRING_NUM_WARN) { - return; - } - - (0, _util.warn)(`getHexString - ignoring invalid character: ${ch}`); - } - - getHexString() { - const strBuf = this.strBuf; - strBuf.length = 0; - let ch = this.currentChar; - let isFirstHex = true; - let firstDigit, secondDigit; - this._hexStringNumWarn = 0; - - while (true) { - if (ch < 0) { - (0, _util.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) { - this._hexStringWarn(ch); - - ch = this.nextChar(); - continue; - } - } else { - secondDigit = toHexDigit(ch); - - if (secondDigit === -1) { - this._hexStringWarn(ch); - - ch = this.nextChar(); - continue; - } - - strBuf.push(String.fromCharCode(firstDigit << 4 | secondDigit)); - } - - isFirstHex = !isFirstHex; - ch = this.nextChar(); - } - } - - return strBuf.join(""); - } - - getObj() { - let comment = false; - let ch = this.currentChar; - - while (true) { - if (ch < 0) { - return _primitives.EOF; - } - - if (comment) { - if (ch === 0x0a || ch === 0x0d) { - comment = false; - } - } else if (ch === 0x25) { - comment = true; - } else if (specialChars[ch] !== 1) { - break; - } - - ch = this.nextChar(); - } - - switch (ch | 0) { - case 0x30: - case 0x31: - case 0x32: - case 0x33: - case 0x34: - case 0x35: - case 0x36: - case 0x37: - case 0x38: - case 0x39: - case 0x2b: - case 0x2d: - case 0x2e: - return this.getNumber(); - - case 0x28: - return this.getString(); - - case 0x2f: - return this.getName(); - - case 0x5b: - this.nextChar(); - return _primitives.Cmd.get("["); - - case 0x5d: - this.nextChar(); - return _primitives.Cmd.get("]"); - - case 0x3c: - ch = this.nextChar(); - - if (ch === 0x3c) { - this.nextChar(); - return _primitives.Cmd.get("<<"); - } - - return this.getHexString(); - - case 0x3e: - ch = this.nextChar(); - - if (ch === 0x3e) { - this.nextChar(); - return _primitives.Cmd.get(">>"); - } - - return _primitives.Cmd.get(">"); - - case 0x7b: - this.nextChar(); - return _primitives.Cmd.get("{"); - - case 0x7d: - this.nextChar(); - return _primitives.Cmd.get("}"); - - case 0x29: - this.nextChar(); - throw new _util.FormatError(`Illegal character: ${ch}`); - } - - let str = String.fromCharCode(ch); - - if (ch < 0x20 || ch > 0x7f) { - const nextCh = this.peekChar(); - - if (nextCh >= 0x20 && nextCh <= 0x7f) { - this.nextChar(); - return _primitives.Cmd.get(str); - } - } - - const knownCommands = this.knownCommands; - let knownCommandFound = knownCommands && knownCommands[str] !== undefined; - - while ((ch = this.nextChar()) >= 0 && !specialChars[ch]) { - const possibleCommand = str + String.fromCharCode(ch); - - if (knownCommandFound && knownCommands[possibleCommand] === undefined) { - break; - } - - if (str.length === 128) { - throw new _util.FormatError(`Command token too long: ${str.length}`); - } - - str = possibleCommand; - knownCommandFound = knownCommands && knownCommands[str] !== undefined; - } - - if (str === "true") { - return true; - } - - if (str === "false") { - return false; - } - - if (str === "null") { - return null; - } - - if (str === "BI") { - this.beginInlineImagePos = this.stream.pos; - } - - return _primitives.Cmd.get(str); - } - - peekObj() { - const streamPos = this.stream.pos, - currentChar = this.currentChar, - beginInlineImagePos = this.beginInlineImagePos; - let nextObj; - - try { - nextObj = this.getObj(); - } catch (ex) { - if (ex instanceof _core_utils.MissingDataException) { - throw ex; - } - - (0, _util.warn)(`peekObj: ${ex}`); - } - - this.stream.pos = streamPos; - this.currentChar = currentChar; - this.beginInlineImagePos = beginInlineImagePos; - return nextObj; - } - - skipToNextLine() { - let ch = this.currentChar; - - while (ch >= 0) { - if (ch === 0x0d) { - ch = this.nextChar(); - - if (ch === 0x0a) { - this.nextChar(); - } - - break; - } else if (ch === 0x0a) { - this.nextChar(); - break; - } - - ch = this.nextChar(); - } - } - -} - -exports.Lexer = Lexer; - -class Linearization { - static create(stream) { - function getInt(linDict, name, allowZeroValue = false) { - const obj = linDict.get(name); - - if (Number.isInteger(obj) && (allowZeroValue ? obj >= 0 : obj > 0)) { - return obj; - } - - throw new Error(`The "${name}" parameter in the linearization ` + "dictionary is invalid."); - } - - function getHints(linDict) { - const hints = linDict.get("H"); - let hintsLength; - - if (Array.isArray(hints) && ((hintsLength = hints.length) === 2 || hintsLength === 4)) { - for (let index = 0; index < hintsLength; index++) { - const hint = hints[index]; - - if (!(Number.isInteger(hint) && hint > 0)) { - throw new Error(`Hint (${index}) in the linearization dictionary is invalid.`); - } - } - - return hints; - } - - throw new Error("Hint array in the linearization dictionary is invalid."); - } - - const parser = new Parser({ - lexer: new Lexer(stream), - xref: null - }); - const obj1 = parser.getObj(); - const obj2 = parser.getObj(); - const obj3 = parser.getObj(); - const linDict = parser.getObj(); - let obj, length; - - if (!(Number.isInteger(obj1) && Number.isInteger(obj2) && (0, _primitives.isCmd)(obj3, "obj") && (0, _primitives.isDict)(linDict) && (0, _util.isNum)(obj = linDict.get("Linearized")) && obj > 0)) { - return null; - } else if ((length = getInt(linDict, "L")) !== stream.length) { - throw new Error('The "L" parameter in the linearization dictionary ' + "does not equal the stream length."); - } - - return { - length, - hints: getHints(linDict), - objectNumberFirst: getInt(linDict, "O"), - endFirst: getInt(linDict, "E"), - numPages: getInt(linDict, "N"), - mainXRefEntriesOffset: getInt(linDict, "T"), - pageFirst: linDict.has("P") ? getInt(linDict, "P", true) : 0 - }; - } - -} - -exports.Linearization = Linearization; - -/***/ }), -/* 28 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.Ascii85Stream = void 0; - -var _decode_stream = __w_pdfjs_require__(29); - -var _core_utils = __w_pdfjs_require__(9); - -class Ascii85Stream extends _decode_stream.DecodeStream { - constructor(str, maybeLength) { - if (maybeLength) { - maybeLength *= 0.8; - } - - super(maybeLength); - this.str = str; - this.dict = str.dict; - this.input = new Uint8Array(5); - } - - readBlock() { - const TILDA_CHAR = 0x7e; - const Z_LOWER_CHAR = 0x7a; - const EOF = -1; - const str = this.str; - let c = str.getByte(); - - while ((0, _core_utils.isWhiteSpace)(c)) { - c = str.getByte(); - } - - if (c === EOF || c === TILDA_CHAR) { - this.eof = true; - return; - } - - const bufferLength = this.bufferLength; - let buffer, i; - - if (c === Z_LOWER_CHAR) { - buffer = this.ensureBuffer(bufferLength + 4); - - for (i = 0; i < 4; ++i) { - buffer[bufferLength + i] = 0; - } - - this.bufferLength += 4; - } else { - const input = this.input; - input[0] = c; - - for (i = 1; i < 5; ++i) { - c = str.getByte(); - - while ((0, _core_utils.isWhiteSpace)(c)) { - c = str.getByte(); - } - - input[i] = c; - - if (c === EOF || c === TILDA_CHAR) { - break; - } - } - - buffer = this.ensureBuffer(bufferLength + i - 1); - this.bufferLength += i - 1; - - if (i < 5) { - for (; i < 5; ++i) { - input[i] = 0x21 + 84; - } - - this.eof = true; - } - - let t = 0; - - for (i = 0; i < 5; ++i) { - t = t * 85 + (input[i] - 0x21); - } - - for (i = 3; i >= 0; --i) { - buffer[bufferLength + i] = t & 0xff; - t >>= 8; - } - } - } - -} - -exports.Ascii85Stream = Ascii85Stream; - -/***/ }), -/* 29 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.StreamsSequenceStream = exports.DecodeStream = void 0; - -var _base_stream = __w_pdfjs_require__(6); - -var _stream = __w_pdfjs_require__(10); - -const emptyBuffer = new Uint8Array(0); - -class DecodeStream extends _base_stream.BaseStream { - constructor(maybeMinBufferLength) { - super(); - this._rawMinBufferLength = maybeMinBufferLength || 0; - this.pos = 0; - this.bufferLength = 0; - this.eof = false; - this.buffer = emptyBuffer; - this.minBufferLength = 512; - - if (maybeMinBufferLength) { - while (this.minBufferLength < maybeMinBufferLength) { - this.minBufferLength *= 2; - } - } - } - - get isEmpty() { - while (!this.eof && this.bufferLength === 0) { - this.readBlock(); - } - - return this.bufferLength === 0; - } - - ensureBuffer(requested) { - const buffer = this.buffer; - - if (requested <= buffer.byteLength) { - return buffer; - } - - let size = this.minBufferLength; - - while (size < requested) { - size *= 2; - } - - const buffer2 = new Uint8Array(size); - buffer2.set(buffer); - return this.buffer = buffer2; - } - - getByte() { - const pos = this.pos; - - while (this.bufferLength <= pos) { - if (this.eof) { - return -1; - } - - this.readBlock(); - } - - return this.buffer[this.pos++]; - } - - getBytes(length, forceClamped = false) { - const pos = this.pos; - let end; - - if (length) { - this.ensureBuffer(pos + length); - end = pos + length; - - while (!this.eof && this.bufferLength < end) { - this.readBlock(); - } - - const bufEnd = this.bufferLength; - - if (end > bufEnd) { - end = bufEnd; - } - } else { - while (!this.eof) { - this.readBlock(); - } - - end = this.bufferLength; - } - - this.pos = end; - const subarray = this.buffer.subarray(pos, end); - return forceClamped && !(subarray instanceof Uint8ClampedArray) ? new Uint8ClampedArray(subarray) : subarray; - } - - reset() { - this.pos = 0; - } - - makeSubStream(start, length, dict = null) { - if (length === undefined) { - while (!this.eof) { - this.readBlock(); - } - } else { - const end = start + length; - - while (this.bufferLength <= end && !this.eof) { - this.readBlock(); - } - } - - return new _stream.Stream(this.buffer, start, length, dict); - } - - getBaseStreams() { - return this.str ? this.str.getBaseStreams() : null; - } - -} - -exports.DecodeStream = DecodeStream; - -class StreamsSequenceStream extends DecodeStream { - constructor(streams, onError = null) { - let maybeLength = 0; - - for (const stream of streams) { - maybeLength += stream instanceof DecodeStream ? stream._rawMinBufferLength : stream.length; - } - - super(maybeLength); - this.streams = streams; - this._onError = onError; - } - - readBlock() { - const streams = this.streams; - - if (streams.length === 0) { - this.eof = true; - return; - } - - const stream = streams.shift(); - let chunk; - - try { - chunk = stream.getBytes(); - } catch (reason) { - if (this._onError) { - this._onError(reason, stream.dict && stream.dict.objId); - - return; - } - - throw reason; - } - - const bufferLength = this.bufferLength; - const newLength = bufferLength + chunk.length; - const buffer = this.ensureBuffer(newLength); - buffer.set(chunk, bufferLength); - this.bufferLength = newLength; - } - - getBaseStreams() { - const baseStreamsBuf = []; - - for (const stream of this.streams) { - const baseStreams = stream.getBaseStreams(); - - if (baseStreams) { - baseStreamsBuf.push(...baseStreams); - } - } - - return baseStreamsBuf.length > 0 ? baseStreamsBuf : null; - } - -} - -exports.StreamsSequenceStream = StreamsSequenceStream; - -/***/ }), -/* 30 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.AsciiHexStream = void 0; - -var _decode_stream = __w_pdfjs_require__(29); - -class AsciiHexStream extends _decode_stream.DecodeStream { - constructor(str, maybeLength) { - if (maybeLength) { - maybeLength *= 0.5; - } - - super(maybeLength); - this.str = str; - this.dict = str.dict; - this.firstDigit = -1; - } - - readBlock() { - const UPSTREAM_BLOCK_SIZE = 8000; - const bytes = this.str.getBytes(UPSTREAM_BLOCK_SIZE); - - if (!bytes.length) { - this.eof = true; - return; - } - - const maxDecodeLength = bytes.length + 1 >> 1; - const buffer = this.ensureBuffer(this.bufferLength + maxDecodeLength); - let bufferLength = this.bufferLength; - let firstDigit = this.firstDigit; - - for (const ch of bytes) { - let digit; - - if (ch >= 0x30 && ch <= 0x39) { - digit = ch & 0x0f; - } else if (ch >= 0x41 && ch <= 0x46 || ch >= 0x61 && ch <= 0x66) { - digit = (ch & 0x0f) + 9; - } else if (ch === 0x3e) { - this.eof = true; - break; - } else { - continue; - } - - if (firstDigit < 0) { - firstDigit = digit; - } else { - buffer[bufferLength++] = firstDigit << 4 | digit; - firstDigit = -1; - } - } - - if (firstDigit >= 0 && this.eof) { - buffer[bufferLength++] = firstDigit << 4; - firstDigit = -1; - } - - this.firstDigit = firstDigit; - this.bufferLength = bufferLength; - } - -} - -exports.AsciiHexStream = AsciiHexStream; - -/***/ }), -/* 31 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.CCITTFaxStream = void 0; - -var _primitives = __w_pdfjs_require__(5); - -var _ccitt = __w_pdfjs_require__(32); - -var _decode_stream = __w_pdfjs_require__(29); - -class CCITTFaxStream extends _decode_stream.DecodeStream { - constructor(str, maybeLength, params) { - super(maybeLength); - this.str = str; - this.dict = str.dict; - - if (!(0, _primitives.isDict)(params)) { - params = _primitives.Dict.empty; - } - - const source = { - next() { - return str.getByte(); - } - - }; - this.ccittFaxDecoder = new _ccitt.CCITTFaxDecoder(source, { - K: params.get("K"), - EndOfLine: params.get("EndOfLine"), - EncodedByteAlign: params.get("EncodedByteAlign"), - Columns: params.get("Columns"), - Rows: params.get("Rows"), - EndOfBlock: params.get("EndOfBlock"), - BlackIs1: params.get("BlackIs1") - }); - } - - readBlock() { - while (!this.eof) { - const c = this.ccittFaxDecoder.readNextChar(); - - if (c === -1) { - this.eof = true; - return; - } - - this.ensureBuffer(this.bufferLength + 1); - this.buffer[this.bufferLength++] = c; - } - } - -} - -exports.CCITTFaxStream = CCITTFaxStream; - -/***/ }), -/* 32 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.CCITTFaxDecoder = void 0; - -var _util = __w_pdfjs_require__(2); - -const ccittEOL = -2; -const ccittEOF = -1; -const twoDimPass = 0; -const twoDimHoriz = 1; -const twoDimVert0 = 2; -const twoDimVertR1 = 3; -const twoDimVertL1 = 4; -const twoDimVertR2 = 5; -const twoDimVertL2 = 6; -const twoDimVertR3 = 7; -const twoDimVertL3 = 8; -const twoDimTable = [[-1, -1], [-1, -1], [7, twoDimVertL3], [7, twoDimVertR3], [6, twoDimVertL2], [6, twoDimVertL2], [6, twoDimVertR2], [6, twoDimVertR2], [4, twoDimPass], [4, twoDimPass], [4, twoDimPass], [4, twoDimPass], [4, twoDimPass], [4, twoDimPass], [4, twoDimPass], [4, twoDimPass], [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, twoDimHoriz], [3, twoDimHoriz], [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, twoDimVertL1], [3, twoDimVertL1], [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], [3, twoDimVertR1], [3, twoDimVertR1], [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], [1, twoDimVert0], [1, twoDimVert0]]; -const whiteTable1 = [[-1, -1], [12, ccittEOL], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [11, 1792], [11, 1792], [12, 1984], [12, 2048], [12, 2112], [12, 2176], [12, 2240], [12, 2304], [11, 1856], [11, 1856], [11, 1920], [11, 1920], [12, 2368], [12, 2432], [12, 2496], [12, 2560]]; -const whiteTable2 = [[-1, -1], [-1, -1], [-1, -1], [-1, -1], [8, 29], [8, 29], [8, 30], [8, 30], [8, 45], [8, 45], [8, 46], [8, 46], [7, 22], [7, 22], [7, 22], [7, 22], [7, 23], [7, 23], [7, 23], [7, 23], [8, 47], [8, 47], [8, 48], [8, 48], [6, 13], [6, 13], [6, 13], [6, 13], [6, 13], [6, 13], [6, 13], [6, 13], [7, 20], [7, 20], [7, 20], [7, 20], [8, 33], [8, 33], [8, 34], [8, 34], [8, 35], [8, 35], [8, 36], [8, 36], [8, 37], [8, 37], [8, 38], [8, 38], [7, 19], [7, 19], [7, 19], [7, 19], [8, 31], [8, 31], [8, 32], [8, 32], [6, 1], [6, 1], [6, 1], [6, 1], [6, 1], [6, 1], [6, 1], [6, 1], [6, 12], [6, 12], [6, 12], [6, 12], [6, 12], [6, 12], [6, 12], [6, 12], [8, 53], [8, 53], [8, 54], [8, 54], [7, 26], [7, 26], [7, 26], [7, 26], [8, 39], [8, 39], [8, 40], [8, 40], [8, 41], [8, 41], [8, 42], [8, 42], [8, 43], [8, 43], [8, 44], [8, 44], [7, 21], [7, 21], [7, 21], [7, 21], [7, 28], [7, 28], [7, 28], [7, 28], [8, 61], [8, 61], [8, 62], [8, 62], [8, 63], [8, 63], [8, 0], [8, 0], [8, 320], [8, 320], [8, 384], [8, 384], [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, 10], [5, 10], [5, 10], [5, 10], [5, 11], [5, 11], [5, 11], [5, 11], [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], [8, 59], [8, 59], [8, 60], [8, 60], [9, 1472], [9, 1536], [9, 1600], [9, 1728], [7, 18], [7, 18], [7, 18], [7, 18], [7, 24], [7, 24], [7, 24], [7, 24], [8, 49], [8, 49], [8, 50], [8, 50], [8, 51], [8, 51], [8, 52], [8, 52], [7, 25], [7, 25], [7, 25], [7, 25], [8, 55], [8, 55], [8, 56], [8, 56], [8, 57], [8, 57], [8, 58], [8, 58], [6, 192], [6, 192], [6, 192], [6, 192], [6, 192], [6, 192], [6, 192], [6, 192], [6, 1664], [6, 1664], [6, 1664], [6, 1664], [6, 1664], [6, 1664], [6, 1664], [6, 1664], [8, 448], [8, 448], [8, 512], [8, 512], [9, 704], [9, 768], [8, 640], [8, 640], [8, 576], [8, 576], [9, 832], [9, 896], [9, 960], [9, 1024], [9, 1088], [9, 1152], [9, 1216], [9, 1280], [9, 1344], [9, 1408], [7, 256], [7, 256], [7, 256], [7, 256], [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, 2], [4, 2], [4, 2], [4, 2], [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], [4, 3], [4, 3], [4, 3], [4, 3], [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, 128], [5, 128], [5, 128], [5, 128], [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, 8], [5, 8], [5, 8], [5, 8], [5, 9], [5, 9], [5, 9], [5, 9], [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], [6, 16], [6, 16], [6, 16], [6, 16], [6, 17], [6, 17], [6, 17], [6, 17], [6, 17], [6, 17], [6, 17], [6, 17], [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, 4], [4, 4], [4, 4], [4, 4], [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], [4, 5], [4, 5], [4, 5], [4, 5], [6, 14], [6, 14], [6, 14], [6, 14], [6, 14], [6, 14], [6, 14], [6, 14], [6, 15], [6, 15], [6, 15], [6, 15], [6, 15], [6, 15], [6, 15], [6, 15], [5, 64], [5, 64], [5, 64], [5, 64], [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], [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], [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]]; -const blackTable1 = [[-1, -1], [-1, -1], [12, ccittEOL], [12, ccittEOL], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [11, 1792], [11, 1792], [11, 1792], [11, 1792], [12, 1984], [12, 1984], [12, 2048], [12, 2048], [12, 2112], [12, 2112], [12, 2176], [12, 2176], [12, 2240], [12, 2240], [12, 2304], [12, 2304], [11, 1856], [11, 1856], [11, 1856], [11, 1856], [11, 1920], [11, 1920], [11, 1920], [11, 1920], [12, 2368], [12, 2368], [12, 2432], [12, 2432], [12, 2496], [12, 2496], [12, 2560], [12, 2560], [10, 18], [10, 18], [10, 18], [10, 18], [10, 18], [10, 18], [10, 18], [10, 18], [12, 52], [12, 52], [13, 640], [13, 704], [13, 768], [13, 832], [12, 55], [12, 55], [12, 56], [12, 56], [13, 1280], [13, 1344], [13, 1408], [13, 1472], [12, 59], [12, 59], [12, 60], [12, 60], [13, 1536], [13, 1600], [11, 24], [11, 24], [11, 24], [11, 24], [11, 25], [11, 25], [11, 25], [11, 25], [13, 1664], [13, 1728], [12, 320], [12, 320], [12, 384], [12, 384], [12, 448], [12, 448], [13, 512], [13, 576], [12, 53], [12, 53], [12, 54], [12, 54], [13, 896], [13, 960], [13, 1024], [13, 1088], [13, 1152], [13, 1216], [10, 64], [10, 64], [10, 64], [10, 64], [10, 64], [10, 64], [10, 64], [10, 64]]; -const blackTable2 = [[8, 13], [8, 13], [8, 13], [8, 13], [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], [12, 50], [12, 51], [12, 44], [12, 45], [12, 46], [12, 47], [12, 57], [12, 58], [12, 61], [12, 256], [10, 16], [10, 16], [10, 16], [10, 16], [10, 17], [10, 17], [10, 17], [10, 17], [12, 48], [12, 49], [12, 62], [12, 63], [12, 30], [12, 31], [12, 32], [12, 33], [12, 40], [12, 41], [11, 22], [11, 22], [8, 14], [8, 14], [8, 14], [8, 14], [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], [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], [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], [9, 15], [9, 15], [9, 15], [9, 15], [12, 128], [12, 192], [12, 26], [12, 27], [12, 28], [12, 29], [11, 19], [11, 19], [11, 20], [11, 20], [12, 34], [12, 35], [12, 36], [12, 37], [12, 38], [12, 39], [11, 21], [11, 21], [12, 42], [12, 43], [10, 0], [10, 0], [10, 0], [10, 0], [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], [7, 12], [7, 12], [7, 12], [7, 12]]; -const blackTable3 = [[-1, -1], [-1, -1], [-1, -1], [-1, -1], [6, 9], [6, 8], [5, 7], [5, 7], [4, 6], [4, 6], [4, 6], [4, 6], [4, 5], [4, 5], [4, 5], [4, 5], [3, 1], [3, 1], [3, 1], [3, 1], [3, 1], [3, 1], [3, 1], [3, 1], [3, 4], [3, 4], [3, 4], [3, 4], [3, 4], [3, 4], [3, 4], [3, 4], [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, 3], [2, 3], [2, 3], [2, 3], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2]]; - -class CCITTFaxDecoder { - constructor(source, options = {}) { - if (!source || typeof source.next !== "function") { - throw new Error('CCITTFaxDecoder - invalid "source" parameter.'); - } - - this.source = source; - this.eof = false; - this.encoding = options.K || 0; - this.eoline = options.EndOfLine || false; - this.byteAlign = options.EncodedByteAlign || false; - this.columns = options.Columns || 1728; - this.rows = options.Rows || 0; - let eoblock = options.EndOfBlock; - - if (eoblock === null || eoblock === undefined) { - eoblock = true; - } - - this.eoblock = eoblock; - this.black = options.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.rowsDone = false; - let 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); - } - } - - readNextChar() { - if (this.eof) { - return -1; - } - - const refLine = this.refLine; - const codingLine = this.codingLine; - const columns = this.columns; - let refPos, blackPixels, bits, i; - - if (this.outputBits === 0) { - if (this.rowsDone) { - this.eof = true; - } - - if (this.eof) { - return -1; - } - - this.err = false; - let code1, code2, code3; - - if (this.nextLine2D) { - for (i = 0; codingLine[i] < columns; ++i) { - refLine[i] = codingLine[i]; - } - - refLine[i++] = columns; - refLine[i] = columns; - codingLine[0] = 0; - this.codingPos = 0; - refPos = 0; - blackPixels = 0; - - while (codingLine[this.codingPos] < columns) { - code1 = this._getTwoDimCode(); - - switch (code1) { - case twoDimPass: - this._addPixels(refLine[refPos + 1], blackPixels); - - if (refLine[refPos + 1] < columns) { - refPos += 2; - } - - break; - - case twoDimHoriz: - code1 = code2 = 0; - - if (blackPixels) { - do { - code1 += code3 = this._getBlackCode(); - } while (code3 >= 64); - - do { - code2 += code3 = this._getWhiteCode(); - } while (code3 >= 64); - } else { - do { - code1 += code3 = this._getWhiteCode(); - } while (code3 >= 64); - - do { - code2 += code3 = this._getBlackCode(); - } while (code3 >= 64); - } - - this._addPixels(codingLine[this.codingPos] + code1, blackPixels); - - if (codingLine[this.codingPos] < columns) { - this._addPixels(codingLine[this.codingPos] + code2, blackPixels ^ 1); - } - - while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) { - refPos += 2; - } - - break; - - case twoDimVertR3: - this._addPixels(refLine[refPos] + 3, blackPixels); - - blackPixels ^= 1; - - if (codingLine[this.codingPos] < columns) { - ++refPos; - - while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) { - refPos += 2; - } - } - - break; - - case twoDimVertR2: - this._addPixels(refLine[refPos] + 2, blackPixels); - - blackPixels ^= 1; - - if (codingLine[this.codingPos] < columns) { - ++refPos; - - while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) { - refPos += 2; - } - } - - break; - - case twoDimVertR1: - this._addPixels(refLine[refPos] + 1, blackPixels); - - blackPixels ^= 1; - - if (codingLine[this.codingPos] < columns) { - ++refPos; - - while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) { - refPos += 2; - } - } - - break; - - case twoDimVert0: - this._addPixels(refLine[refPos], blackPixels); - - blackPixels ^= 1; - - if (codingLine[this.codingPos] < columns) { - ++refPos; - - while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) { - refPos += 2; - } - } - - break; - - case twoDimVertL3: - this._addPixelsNeg(refLine[refPos] - 3, blackPixels); - - blackPixels ^= 1; - - if (codingLine[this.codingPos] < columns) { - if (refPos > 0) { - --refPos; - } else { - ++refPos; - } - - while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) { - refPos += 2; - } - } - - break; - - case twoDimVertL2: - this._addPixelsNeg(refLine[refPos] - 2, blackPixels); - - blackPixels ^= 1; - - if (codingLine[this.codingPos] < columns) { - if (refPos > 0) { - --refPos; - } else { - ++refPos; - } - - while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) { - refPos += 2; - } - } - - break; - - case twoDimVertL1: - this._addPixelsNeg(refLine[refPos] - 1, blackPixels); - - blackPixels ^= 1; - - if (codingLine[this.codingPos] < columns) { - if (refPos > 0) { - --refPos; - } else { - ++refPos; - } - - while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) { - refPos += 2; - } - } - - break; - - case ccittEOF: - this._addPixels(columns, 0); - - this.eof = true; - break; - - default: - (0, _util.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; - } - } - - let gotEOL = false; - - if (this.byteAlign) { - this.inputBits &= ~7; - } - - if (!this.eoblock && this.row === this.rows - 1) { - this.rowsDone = true; - } else { - code1 = this._lookBits(12); - - if (this.eoline) { - while (code1 !== ccittEOF && code1 !== 1) { - this._eatBits(1); - - code1 = this._lookBits(12); - } - } else { - while (code1 === 0) { - this._eatBits(1); - - code1 = this._lookBits(12); - } - } - - if (code1 === 1) { - this._eatBits(12); - - gotEOL = true; - } else if (code1 === ccittEOF) { - this.eof = true; - } - } - - if (!this.eof && this.encoding > 0 && !this.rowsDone) { - this.nextLine2D = !this._lookBits(1); - - this._eatBits(1); - } - - if (this.eoblock && gotEOL && this.byteAlign) { - code1 = this._lookBits(12); - - if (code1 === 1) { - this._eatBits(12); - - if (this.encoding > 0) { - this._lookBits(1); - - this._eatBits(1); - } - - if (this.encoding >= 0) { - for (i = 0; i < 4; ++i) { - code1 = this._lookBits(12); - - if (code1 !== 1) { - (0, _util.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 === ccittEOF) { - this.eof = true; - return -1; - } - - 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++; - } - - let c; - - if (this.outputBits >= 8) { - c = this.codingPos & 1 ? 0 : 0xff; - this.outputBits -= 8; - - if (this.outputBits === 0 && codingLine[this.codingPos] < columns) { - this.codingPos++; - this.outputBits = codingLine[this.codingPos] - codingLine[this.codingPos - 1]; - } - } else { - bits = 8; - c = 0; - - do { - if (typeof this.outputBits !== "number") { - throw new _util.FormatError('Invalid /CCITTFaxDecode data, "outputBits" must be a number.'); - } - - if (this.outputBits > bits) { - c <<= bits; - - if (!(this.codingPos & 1)) { - c |= 0xff >> 8 - bits; - } - - this.outputBits -= bits; - bits = 0; - } else { - c <<= this.outputBits; - - if (!(this.codingPos & 1)) { - c |= 0xff >> 8 - this.outputBits; - } - - bits -= this.outputBits; - this.outputBits = 0; - - if (codingLine[this.codingPos] < columns) { - this.codingPos++; - this.outputBits = codingLine[this.codingPos] - codingLine[this.codingPos - 1]; - } else if (bits > 0) { - c <<= bits; - bits = 0; - } - } - } while (bits); - } - - if (this.black) { - c ^= 0xff; - } - - return c; - } - - _addPixels(a1, blackPixels) { - const codingLine = this.codingLine; - let codingPos = this.codingPos; - - if (a1 > codingLine[codingPos]) { - if (a1 > this.columns) { - (0, _util.info)("row is wrong length"); - this.err = true; - a1 = this.columns; - } - - if (codingPos & 1 ^ blackPixels) { - ++codingPos; - } - - codingLine[codingPos] = a1; - } - - this.codingPos = codingPos; - } - - _addPixelsNeg(a1, blackPixels) { - const codingLine = this.codingLine; - let codingPos = this.codingPos; - - if (a1 > codingLine[codingPos]) { - if (a1 > this.columns) { - (0, _util.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) { - (0, _util.info)("invalid code"); - this.err = true; - a1 = 0; - } - - while (codingPos > 0 && a1 < codingLine[codingPos - 1]) { - --codingPos; - } - - codingLine[codingPos] = a1; - } - - this.codingPos = codingPos; - } - - _findTableCode(start, end, table, limit) { - const limitValue = limit || 0; - - for (let i = start; i <= end; ++i) { - let code = this._lookBits(i); - - if (code === ccittEOF) { - return [true, 1, false]; - } - - if (i < end) { - code <<= end - i; - } - - if (!limitValue || code >= limitValue) { - const p = table[code - limitValue]; - - if (p[0] === i) { - this._eatBits(i); - - return [true, p[1], true]; - } - } - } - - return [false, 0, false]; - } - - _getTwoDimCode() { - let code = 0; - let p; - - if (this.eoblock) { - code = this._lookBits(7); - p = twoDimTable[code]; - - if (p && p[0] > 0) { - this._eatBits(p[0]); - - return p[1]; - } - } else { - const result = this._findTableCode(1, 7, twoDimTable); - - if (result[0] && result[2]) { - return result[1]; - } - } - - (0, _util.info)("Bad two dim code"); - return ccittEOF; - } - - _getWhiteCode() { - let code = 0; - let p; - - if (this.eoblock) { - code = this._lookBits(12); - - if (code === ccittEOF) { - 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 { - let result = this._findTableCode(1, 9, whiteTable2); - - if (result[0]) { - return result[1]; - } - - result = this._findTableCode(11, 12, whiteTable1); - - if (result[0]) { - return result[1]; - } - } - - (0, _util.info)("bad white code"); - - this._eatBits(1); - - return 1; - } - - _getBlackCode() { - let code, p; - - if (this.eoblock) { - code = this._lookBits(13); - - if (code === ccittEOF) { - 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 { - let 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]; - } - } - - (0, _util.info)("bad black code"); - - this._eatBits(1); - - return 1; - } - - _lookBits(n) { - let c; - - while (this.inputBits < n) { - if ((c = this.source.next()) === -1) { - if (this.inputBits === 0) { - return ccittEOF; - } - - 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; - } - - _eatBits(n) { - if ((this.inputBits -= n) < 0) { - this.inputBits = 0; - } - } - -} - -exports.CCITTFaxDecoder = CCITTFaxDecoder; - -/***/ }), -/* 33 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.FlateStream = void 0; - -var _decode_stream = __w_pdfjs_require__(29); - -var _util = __w_pdfjs_require__(2); - -const codeLenCodeMap = new Int32Array([16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]); -const lengthDecode = new Int32Array([0x00003, 0x00004, 0x00005, 0x00006, 0x00007, 0x00008, 0x00009, 0x0000a, 0x1000b, 0x1000d, 0x1000f, 0x10011, 0x20013, 0x20017, 0x2001b, 0x2001f, 0x30023, 0x3002b, 0x30033, 0x3003b, 0x40043, 0x40053, 0x40063, 0x40073, 0x50083, 0x500a3, 0x500c3, 0x500e3, 0x00102, 0x00102, 0x00102]); -const distDecode = new Int32Array([0x00001, 0x00002, 0x00003, 0x00004, 0x10005, 0x10007, 0x20009, 0x2000d, 0x30011, 0x30019, 0x40021, 0x40031, 0x50041, 0x50061, 0x60081, 0x600c1, 0x70101, 0x70181, 0x80201, 0x80301, 0x90401, 0x90601, 0xa0801, 0xa0c01, 0xb1001, 0xb1801, 0xc2001, 0xc3001, 0xd4001, 0xd6001]); -const fixedLitCodeTab = [new Int32Array([0x70100, 0x80050, 0x80010, 0x80118, 0x70110, 0x80070, 0x80030, 0x900c0, 0x70108, 0x80060, 0x80020, 0x900a0, 0x80000, 0x80080, 0x80040, 0x900e0, 0x70104, 0x80058, 0x80018, 0x90090, 0x70114, 0x80078, 0x80038, 0x900d0, 0x7010c, 0x80068, 0x80028, 0x900b0, 0x80008, 0x80088, 0x80048, 0x900f0, 0x70102, 0x80054, 0x80014, 0x8011c, 0x70112, 0x80074, 0x80034, 0x900c8, 0x7010a, 0x80064, 0x80024, 0x900a8, 0x80004, 0x80084, 0x80044, 0x900e8, 0x70106, 0x8005c, 0x8001c, 0x90098, 0x70116, 0x8007c, 0x8003c, 0x900d8, 0x7010e, 0x8006c, 0x8002c, 0x900b8, 0x8000c, 0x8008c, 0x8004c, 0x900f8, 0x70101, 0x80052, 0x80012, 0x8011a, 0x70111, 0x80072, 0x80032, 0x900c4, 0x70109, 0x80062, 0x80022, 0x900a4, 0x80002, 0x80082, 0x80042, 0x900e4, 0x70105, 0x8005a, 0x8001a, 0x90094, 0x70115, 0x8007a, 0x8003a, 0x900d4, 0x7010d, 0x8006a, 0x8002a, 0x900b4, 0x8000a, 0x8008a, 0x8004a, 0x900f4, 0x70103, 0x80056, 0x80016, 0x8011e, 0x70113, 0x80076, 0x80036, 0x900cc, 0x7010b, 0x80066, 0x80026, 0x900ac, 0x80006, 0x80086, 0x80046, 0x900ec, 0x70107, 0x8005e, 0x8001e, 0x9009c, 0x70117, 0x8007e, 0x8003e, 0x900dc, 0x7010f, 0x8006e, 0x8002e, 0x900bc, 0x8000e, 0x8008e, 0x8004e, 0x900fc, 0x70100, 0x80051, 0x80011, 0x80119, 0x70110, 0x80071, 0x80031, 0x900c2, 0x70108, 0x80061, 0x80021, 0x900a2, 0x80001, 0x80081, 0x80041, 0x900e2, 0x70104, 0x80059, 0x80019, 0x90092, 0x70114, 0x80079, 0x80039, 0x900d2, 0x7010c, 0x80069, 0x80029, 0x900b2, 0x80009, 0x80089, 0x80049, 0x900f2, 0x70102, 0x80055, 0x80015, 0x8011d, 0x70112, 0x80075, 0x80035, 0x900ca, 0x7010a, 0x80065, 0x80025, 0x900aa, 0x80005, 0x80085, 0x80045, 0x900ea, 0x70106, 0x8005d, 0x8001d, 0x9009a, 0x70116, 0x8007d, 0x8003d, 0x900da, 0x7010e, 0x8006d, 0x8002d, 0x900ba, 0x8000d, 0x8008d, 0x8004d, 0x900fa, 0x70101, 0x80053, 0x80013, 0x8011b, 0x70111, 0x80073, 0x80033, 0x900c6, 0x70109, 0x80063, 0x80023, 0x900a6, 0x80003, 0x80083, 0x80043, 0x900e6, 0x70105, 0x8005b, 0x8001b, 0x90096, 0x70115, 0x8007b, 0x8003b, 0x900d6, 0x7010d, 0x8006b, 0x8002b, 0x900b6, 0x8000b, 0x8008b, 0x8004b, 0x900f6, 0x70103, 0x80057, 0x80017, 0x8011f, 0x70113, 0x80077, 0x80037, 0x900ce, 0x7010b, 0x80067, 0x80027, 0x900ae, 0x80007, 0x80087, 0x80047, 0x900ee, 0x70107, 0x8005f, 0x8001f, 0x9009e, 0x70117, 0x8007f, 0x8003f, 0x900de, 0x7010f, 0x8006f, 0x8002f, 0x900be, 0x8000f, 0x8008f, 0x8004f, 0x900fe, 0x70100, 0x80050, 0x80010, 0x80118, 0x70110, 0x80070, 0x80030, 0x900c1, 0x70108, 0x80060, 0x80020, 0x900a1, 0x80000, 0x80080, 0x80040, 0x900e1, 0x70104, 0x80058, 0x80018, 0x90091, 0x70114, 0x80078, 0x80038, 0x900d1, 0x7010c, 0x80068, 0x80028, 0x900b1, 0x80008, 0x80088, 0x80048, 0x900f1, 0x70102, 0x80054, 0x80014, 0x8011c, 0x70112, 0x80074, 0x80034, 0x900c9, 0x7010a, 0x80064, 0x80024, 0x900a9, 0x80004, 0x80084, 0x80044, 0x900e9, 0x70106, 0x8005c, 0x8001c, 0x90099, 0x70116, 0x8007c, 0x8003c, 0x900d9, 0x7010e, 0x8006c, 0x8002c, 0x900b9, 0x8000c, 0x8008c, 0x8004c, 0x900f9, 0x70101, 0x80052, 0x80012, 0x8011a, 0x70111, 0x80072, 0x80032, 0x900c5, 0x70109, 0x80062, 0x80022, 0x900a5, 0x80002, 0x80082, 0x80042, 0x900e5, 0x70105, 0x8005a, 0x8001a, 0x90095, 0x70115, 0x8007a, 0x8003a, 0x900d5, 0x7010d, 0x8006a, 0x8002a, 0x900b5, 0x8000a, 0x8008a, 0x8004a, 0x900f5, 0x70103, 0x80056, 0x80016, 0x8011e, 0x70113, 0x80076, 0x80036, 0x900cd, 0x7010b, 0x80066, 0x80026, 0x900ad, 0x80006, 0x80086, 0x80046, 0x900ed, 0x70107, 0x8005e, 0x8001e, 0x9009d, 0x70117, 0x8007e, 0x8003e, 0x900dd, 0x7010f, 0x8006e, 0x8002e, 0x900bd, 0x8000e, 0x8008e, 0x8004e, 0x900fd, 0x70100, 0x80051, 0x80011, 0x80119, 0x70110, 0x80071, 0x80031, 0x900c3, 0x70108, 0x80061, 0x80021, 0x900a3, 0x80001, 0x80081, 0x80041, 0x900e3, 0x70104, 0x80059, 0x80019, 0x90093, 0x70114, 0x80079, 0x80039, 0x900d3, 0x7010c, 0x80069, 0x80029, 0x900b3, 0x80009, 0x80089, 0x80049, 0x900f3, 0x70102, 0x80055, 0x80015, 0x8011d, 0x70112, 0x80075, 0x80035, 0x900cb, 0x7010a, 0x80065, 0x80025, 0x900ab, 0x80005, 0x80085, 0x80045, 0x900eb, 0x70106, 0x8005d, 0x8001d, 0x9009b, 0x70116, 0x8007d, 0x8003d, 0x900db, 0x7010e, 0x8006d, 0x8002d, 0x900bb, 0x8000d, 0x8008d, 0x8004d, 0x900fb, 0x70101, 0x80053, 0x80013, 0x8011b, 0x70111, 0x80073, 0x80033, 0x900c7, 0x70109, 0x80063, 0x80023, 0x900a7, 0x80003, 0x80083, 0x80043, 0x900e7, 0x70105, 0x8005b, 0x8001b, 0x90097, 0x70115, 0x8007b, 0x8003b, 0x900d7, 0x7010d, 0x8006b, 0x8002b, 0x900b7, 0x8000b, 0x8008b, 0x8004b, 0x900f7, 0x70103, 0x80057, 0x80017, 0x8011f, 0x70113, 0x80077, 0x80037, 0x900cf, 0x7010b, 0x80067, 0x80027, 0x900af, 0x80007, 0x80087, 0x80047, 0x900ef, 0x70107, 0x8005f, 0x8001f, 0x9009f, 0x70117, 0x8007f, 0x8003f, 0x900df, 0x7010f, 0x8006f, 0x8002f, 0x900bf, 0x8000f, 0x8008f, 0x8004f, 0x900ff]), 9]; -const fixedDistCodeTab = [new Int32Array([0x50000, 0x50010, 0x50008, 0x50018, 0x50004, 0x50014, 0x5000c, 0x5001c, 0x50002, 0x50012, 0x5000a, 0x5001a, 0x50006, 0x50016, 0x5000e, 0x00000, 0x50001, 0x50011, 0x50009, 0x50019, 0x50005, 0x50015, 0x5000d, 0x5001d, 0x50003, 0x50013, 0x5000b, 0x5001b, 0x50007, 0x50017, 0x5000f, 0x00000]), 5]; - -class FlateStream extends _decode_stream.DecodeStream { - constructor(str, maybeLength) { - super(maybeLength); - this.str = str; - this.dict = str.dict; - const cmf = str.getByte(); - const flg = str.getByte(); - - if (cmf === -1 || flg === -1) { - throw new _util.FormatError(`Invalid header in flate stream: ${cmf}, ${flg}`); - } - - if ((cmf & 0x0f) !== 0x08) { - throw new _util.FormatError(`Unknown compression method in flate stream: ${cmf}, ${flg}`); - } - - if (((cmf << 8) + flg) % 31 !== 0) { - throw new _util.FormatError(`Bad FCHECK in flate stream: ${cmf}, ${flg}`); - } - - if (flg & 0x20) { - throw new _util.FormatError(`FDICT bit set in flate stream: ${cmf}, ${flg}`); - } - - this.codeSize = 0; - this.codeBuf = 0; - } - - getBits(bits) { - const str = this.str; - let codeSize = this.codeSize; - let codeBuf = this.codeBuf; - let b; - - while (codeSize < bits) { - if ((b = str.getByte()) === -1) { - throw new _util.FormatError("Bad encoding in flate stream"); - } - - codeBuf |= b << codeSize; - codeSize += 8; - } - - b = codeBuf & (1 << bits) - 1; - this.codeBuf = codeBuf >> bits; - this.codeSize = codeSize -= bits; - return b; - } - - getCode(table) { - const str = this.str; - const codes = table[0]; - const maxLen = table[1]; - let codeSize = this.codeSize; - let codeBuf = this.codeBuf; - let b; - - while (codeSize < maxLen) { - if ((b = str.getByte()) === -1) { - break; - } - - codeBuf |= b << codeSize; - codeSize += 8; - } - - const code = codes[codeBuf & (1 << maxLen) - 1]; - const codeLen = code >> 16; - const codeVal = code & 0xffff; - - if (codeLen < 1 || codeSize < codeLen) { - throw new _util.FormatError("Bad encoding in flate stream"); - } - - this.codeBuf = codeBuf >> codeLen; - this.codeSize = codeSize - codeLen; - return codeVal; - } - - generateHuffmanTable(lengths) { - const n = lengths.length; - let maxLen = 0; - let i; - - for (i = 0; i < n; ++i) { - if (lengths[i] > maxLen) { - maxLen = lengths[i]; - } - } - - const size = 1 << maxLen; - const codes = new Int32Array(size); - - for (let len = 1, code = 0, skip = 2; len <= maxLen; ++len, code <<= 1, skip <<= 1) { - for (let val = 0; val < n; ++val) { - if (lengths[val] === len) { - let code2 = 0; - let t = code; - - for (i = 0; i < len; ++i) { - code2 = code2 << 1 | t & 1; - t >>= 1; - } - - for (i = code2; i < size; i += skip) { - codes[i] = len << 16 | val; - } - - ++code; - } - } - } - - return [codes, maxLen]; - } - - readBlock() { - let buffer, len; - const str = this.str; - let hdr = this.getBits(3); - - if (hdr & 1) { - this.eof = true; - } - - hdr >>= 1; - - if (hdr === 0) { - let b; - - if ((b = str.getByte()) === -1) { - throw new _util.FormatError("Bad block header in flate stream"); - } - - let blockLen = b; - - if ((b = str.getByte()) === -1) { - throw new _util.FormatError("Bad block header in flate stream"); - } - - blockLen |= b << 8; - - if ((b = str.getByte()) === -1) { - throw new _util.FormatError("Bad block header in flate stream"); - } - - let check = b; - - if ((b = str.getByte()) === -1) { - throw new _util.FormatError("Bad block header in flate stream"); - } - - check |= b << 8; - - if (check !== (~blockLen & 0xffff) && (blockLen !== 0 || check !== 0)) { - throw new _util.FormatError("Bad uncompressed block length in flate stream"); - } - - this.codeBuf = 0; - this.codeSize = 0; - const bufferLength = this.bufferLength, - end = bufferLength + blockLen; - buffer = this.ensureBuffer(end); - this.bufferLength = end; - - if (blockLen === 0) { - if (str.peekByte() === -1) { - this.eof = true; - } - } else { - const block = str.getBytes(blockLen); - buffer.set(block, bufferLength); - - if (block.length < blockLen) { - this.eof = true; - } - } - - return; - } - - let litCodeTable; - let distCodeTable; - - if (hdr === 1) { - litCodeTable = fixedLitCodeTab; - distCodeTable = fixedDistCodeTab; - } else if (hdr === 2) { - const numLitCodes = this.getBits(5) + 257; - const numDistCodes = this.getBits(5) + 1; - const numCodeLenCodes = this.getBits(4) + 4; - const codeLenCodeLengths = new Uint8Array(codeLenCodeMap.length); - let i; - - for (i = 0; i < numCodeLenCodes; ++i) { - codeLenCodeLengths[codeLenCodeMap[i]] = this.getBits(3); - } - - const codeLenCodeTab = this.generateHuffmanTable(codeLenCodeLengths); - len = 0; - i = 0; - const codes = numLitCodes + numDistCodes; - const codeLengths = new Uint8Array(codes); - let bitsLength, bitsOffset, what; - - while (i < codes) { - const code = this.getCode(codeLenCodeTab); - - if (code === 16) { - bitsLength = 2; - bitsOffset = 3; - what = len; - } else if (code === 17) { - bitsLength = 3; - bitsOffset = 3; - what = len = 0; - } else if (code === 18) { - bitsLength = 7; - bitsOffset = 11; - what = len = 0; - } else { - codeLengths[i++] = len = code; - continue; - } - - let 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 { - throw new _util.FormatError("Unknown block type in flate stream"); - } - - buffer = this.buffer; - let limit = buffer ? buffer.length : 0; - let pos = this.bufferLength; - - while (true) { - let 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]; - let code2 = code1 >> 16; - - if (code2 > 0) { - code2 = this.getBits(code2); - } - - len = (code1 & 0xffff) + code2; - code1 = this.getCode(distCodeTable); - code1 = distDecode[code1]; - code2 = code1 >> 16; - - if (code2 > 0) { - code2 = this.getBits(code2); - } - - const dist = (code1 & 0xffff) + code2; - - if (pos + len >= limit) { - buffer = this.ensureBuffer(pos + len); - limit = buffer.length; - } - - for (let k = 0; k < len; ++k, ++pos) { - buffer[pos] = buffer[pos - dist]; - } - } - } - -} - -exports.FlateStream = FlateStream; - -/***/ }), -/* 34 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.Jbig2Stream = void 0; - -var _primitives = __w_pdfjs_require__(5); - -var _decode_stream = __w_pdfjs_require__(29); - -var _jbig = __w_pdfjs_require__(35); - -var _util = __w_pdfjs_require__(2); - -class Jbig2Stream extends _decode_stream.DecodeStream { - constructor(stream, maybeLength, params) { - super(maybeLength); - this.stream = stream; - this.dict = stream.dict; - this.maybeLength = maybeLength; - this.params = params; - } - - get bytes() { - return (0, _util.shadow)(this, "bytes", this.stream.getBytes(this.maybeLength)); - } - - ensureBuffer(requested) {} - - readBlock() { - if (this.eof) { - return; - } - - const jbig2Image = new _jbig.Jbig2Image(); - const chunks = []; - - if ((0, _primitives.isDict)(this.params)) { - const globalsStream = this.params.get("JBIG2Globals"); - - if ((0, _primitives.isStream)(globalsStream)) { - const globals = globalsStream.getBytes(); - chunks.push({ - data: globals, - start: 0, - end: globals.length - }); - } - } - - chunks.push({ - data: this.bytes, - start: 0, - end: this.bytes.length - }); - const data = jbig2Image.parseChunks(chunks); - const dataLength = data.length; - - for (let i = 0; i < dataLength; i++) { - data[i] ^= 0xff; - } - - this.buffer = data; - this.bufferLength = dataLength; - this.eof = true; - } - -} - -exports.Jbig2Stream = Jbig2Stream; - -/***/ }), -/* 35 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.Jbig2Image = void 0; - -var _util = __w_pdfjs_require__(2); - -var _core_utils = __w_pdfjs_require__(9); - -var _arithmetic_decoder = __w_pdfjs_require__(36); - -var _ccitt = __w_pdfjs_require__(32); - -class Jbig2Error extends _util.BaseException { - constructor(msg) { - super(`JBIG2 error: ${msg}`, "Jbig2Error"); - } - -} - -class ContextCache { - getContexts(id) { - if (id in this) { - return this[id]; - } - - return this[id] = new Int8Array(1 << 16); - } - -} - -class DecodingContext { - constructor(data, start, end) { - this.data = data; - this.start = start; - this.end = end; - } - - get decoder() { - const decoder = new _arithmetic_decoder.ArithmeticDecoder(this.data, this.start, this.end); - return (0, _util.shadow)(this, "decoder", decoder); - } - - get contextCache() { - const cache = new ContextCache(); - return (0, _util.shadow)(this, "contextCache", cache); - } - -} - -function decodeInteger(contextCache, procedure, decoder) { - const contexts = contextCache.getContexts(procedure); - let prev = 1; - - function readBits(length) { - let v = 0; - - for (let i = 0; i < length; i++) { - const bit = decoder.readBit(contexts, prev); - prev = prev < 256 ? prev << 1 | bit : (prev << 1 | bit) & 511 | 256; - v = v << 1 | bit; - } - - return v >>> 0; - } - - const sign = readBits(1); - const value = readBits(1) ? readBits(1) ? readBits(1) ? readBits(1) ? readBits(1) ? readBits(32) + 4436 : readBits(12) + 340 : readBits(8) + 84 : readBits(6) + 20 : readBits(4) + 4 : readBits(2); - - if (sign === 0) { - return value; - } else if (value > 0) { - return -value; - } - - return null; -} - -function decodeIAID(contextCache, decoder, codeLength) { - const contexts = contextCache.getContexts("IAID"); - let prev = 1; - - for (let i = 0; i < codeLength; i++) { - const bit = decoder.readBit(contexts, prev); - prev = prev << 1 | bit; - } - - if (codeLength < 31) { - return prev & (1 << codeLength) - 1; - } - - return prev & 0x7fffffff; -} - -const 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"]; -const 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 -}]]; -const 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 - }] -}]; -const ReusedContexts = [0x9b25, 0x0795, 0x00e5, 0x0195]; -const RefinementReusedContexts = [0x0020, 0x0008]; - -function decodeBitmapTemplate0(width, height, decodingContext) { - const decoder = decodingContext.decoder; - const contexts = decodingContext.contextCache.getContexts("GB"); - const bitmap = []; - let contextLabel, i, j, pixel, row, row1, row2; - const OLD_PIXEL_MASK = 0x7bf7; - - for (i = 0; i < height; i++) { - row = bitmap[i] = new Uint8Array(width); - row1 = i < 1 ? row : bitmap[i - 1]; - row2 = i < 2 ? row : bitmap[i - 2]; - contextLabel = row2[0] << 13 | row2[1] << 12 | row2[2] << 11 | row1[0] << 7 | row1[1] << 6 | row1[2] << 5 | row1[3] << 4; - - for (j = 0; j < width; j++) { - row[j] = pixel = decoder.readBit(contexts, contextLabel); - contextLabel = (contextLabel & OLD_PIXEL_MASK) << 1 | (j + 3 < width ? row2[j + 3] << 11 : 0) | (j + 4 < width ? row1[j + 4] << 4 : 0) | pixel; - } - } - - return bitmap; -} - -function decodeBitmap(mmr, width, height, templateIndex, prediction, skip, at, decodingContext) { - if (mmr) { - const input = new Reader(decodingContext.data, decodingContext.start, decodingContext.end); - return decodeMMRBitmap(input, width, height, false); - } - - if (templateIndex === 0 && !skip && !prediction && at.length === 4 && at[0].x === 3 && at[0].y === -1 && at[1].x === -3 && at[1].y === -1 && at[2].x === 2 && at[2].y === -2 && at[3].x === -2 && at[3].y === -2) { - return decodeBitmapTemplate0(width, height, decodingContext); - } - - const useskip = !!skip; - const template = CodingTemplates[templateIndex].concat(at); - template.sort(function (a, b) { - return a.y - b.y || a.x - b.x; - }); - const templateLength = template.length; - const templateX = new Int8Array(templateLength); - const templateY = new Int8Array(templateLength); - const changingTemplateEntries = []; - let reuseMask = 0, - minX = 0, - maxX = 0, - minY = 0; - let c, k; - - for (k = 0; k < templateLength; k++) { - templateX[k] = template[k].x; - templateY[k] = template[k].y; - minX = Math.min(minX, template[k].x); - maxX = Math.max(maxX, template[k].x); - minY = Math.min(minY, template[k].y); - - if (k < templateLength - 1 && template[k].y === template[k + 1].y && template[k].x === template[k + 1].x - 1) { - reuseMask |= 1 << templateLength - 1 - k; - } else { - changingTemplateEntries.push(k); - } - } - - const changingEntriesLength = changingTemplateEntries.length; - const changingTemplateX = new Int8Array(changingEntriesLength); - const changingTemplateY = new Int8Array(changingEntriesLength); - const changingTemplateBit = new Uint16Array(changingEntriesLength); - - for (c = 0; c < changingEntriesLength; c++) { - k = changingTemplateEntries[c]; - changingTemplateX[c] = template[k].x; - changingTemplateY[c] = template[k].y; - changingTemplateBit[c] = 1 << templateLength - 1 - k; - } - - const sbb_left = -minX; - const sbb_top = -minY; - const sbb_right = width - maxX; - const pseudoPixelContext = ReusedContexts[templateIndex]; - let row = new Uint8Array(width); - const bitmap = []; - const decoder = decodingContext.decoder; - const contexts = decodingContext.contextCache.getContexts("GB"); - let ltp = 0, - j, - i0, - j0, - contextLabel = 0, - bit, - shift; - - for (let i = 0; i < height; i++) { - if (prediction) { - const sltp = decoder.readBit(contexts, pseudoPixelContext); - ltp ^= sltp; - - if (ltp) { - bitmap.push(row); - continue; - } - } - - row = new Uint8Array(row); - bitmap.push(row); - - for (j = 0; j < width; j++) { - if (useskip && skip[i][j]) { - row[j] = 0; - continue; - } - - if (j >= sbb_left && j < sbb_right && i >= sbb_top) { - contextLabel = contextLabel << 1 & reuseMask; - - for (k = 0; k < changingEntriesLength; k++) { - i0 = i + changingTemplateY[k]; - j0 = j + changingTemplateX[k]; - bit = bitmap[i0][j0]; - - if (bit) { - bit = changingTemplateBit[k]; - contextLabel |= bit; - } - } - } else { - contextLabel = 0; - shift = templateLength - 1; - - for (k = 0; k < templateLength; k++, shift--) { - j0 = j + templateX[k]; - - if (j0 >= 0 && j0 < width) { - i0 = i + templateY[k]; - - if (i0 >= 0) { - bit = bitmap[i0][j0]; - - if (bit) { - contextLabel |= bit << shift; - } - } - } - } - } - - const pixel = decoder.readBit(contexts, contextLabel); - row[j] = pixel; - } - } - - return bitmap; -} - -function decodeRefinement(width, height, templateIndex, referenceBitmap, offsetX, offsetY, prediction, at, decodingContext) { - let codingTemplate = RefinementTemplates[templateIndex].coding; - - if (templateIndex === 0) { - codingTemplate = codingTemplate.concat([at[0]]); - } - - const codingTemplateLength = codingTemplate.length; - const codingTemplateX = new Int32Array(codingTemplateLength); - const codingTemplateY = new Int32Array(codingTemplateLength); - let k; - - for (k = 0; k < codingTemplateLength; k++) { - codingTemplateX[k] = codingTemplate[k].x; - codingTemplateY[k] = codingTemplate[k].y; - } - - let referenceTemplate = RefinementTemplates[templateIndex].reference; - - if (templateIndex === 0) { - referenceTemplate = referenceTemplate.concat([at[1]]); - } - - const referenceTemplateLength = referenceTemplate.length; - const referenceTemplateX = new Int32Array(referenceTemplateLength); - const referenceTemplateY = new Int32Array(referenceTemplateLength); - - for (k = 0; k < referenceTemplateLength; k++) { - referenceTemplateX[k] = referenceTemplate[k].x; - referenceTemplateY[k] = referenceTemplate[k].y; - } - - const referenceWidth = referenceBitmap[0].length; - const referenceHeight = referenceBitmap.length; - const pseudoPixelContext = RefinementReusedContexts[templateIndex]; - const bitmap = []; - const decoder = decodingContext.decoder; - const contexts = decodingContext.contextCache.getContexts("GR"); - let ltp = 0; - - for (let i = 0; i < height; i++) { - if (prediction) { - const sltp = decoder.readBit(contexts, pseudoPixelContext); - ltp ^= sltp; - - if (ltp) { - throw new Jbig2Error("prediction is not supported"); - } - } - - const row = new Uint8Array(width); - bitmap.push(row); - - for (let j = 0; j < width; j++) { - let i0, j0; - let contextLabel = 0; - - for (k = 0; k < codingTemplateLength; k++) { - i0 = i + codingTemplateY[k]; - j0 = j + codingTemplateX[k]; - - if (i0 < 0 || j0 < 0 || j0 >= width) { - contextLabel <<= 1; - } else { - contextLabel = contextLabel << 1 | bitmap[i0][j0]; - } - } - - for (k = 0; k < referenceTemplateLength; k++) { - i0 = i + referenceTemplateY[k] - offsetY; - j0 = j + referenceTemplateX[k] - offsetX; - - if (i0 < 0 || i0 >= referenceHeight || j0 < 0 || j0 >= referenceWidth) { - contextLabel <<= 1; - } else { - contextLabel = contextLabel << 1 | referenceBitmap[i0][j0]; - } - } - - const pixel = decoder.readBit(contexts, contextLabel); - row[j] = pixel; - } - } - - return bitmap; -} - -function decodeSymbolDictionary(huffman, refinement, symbols, numberOfNewSymbols, numberOfExportedSymbols, huffmanTables, templateIndex, at, refinementTemplateIndex, refinementAt, decodingContext, huffmanInput) { - if (huffman && refinement) { - throw new Jbig2Error("symbol refinement with Huffman is not supported"); - } - - const newSymbols = []; - let currentHeight = 0; - let symbolCodeLength = (0, _core_utils.log2)(symbols.length + numberOfNewSymbols); - const decoder = decodingContext.decoder; - const contextCache = decodingContext.contextCache; - let tableB1, symbolWidths; - - if (huffman) { - tableB1 = getStandardTable(1); - symbolWidths = []; - symbolCodeLength = Math.max(symbolCodeLength, 1); - } - - while (newSymbols.length < numberOfNewSymbols) { - const deltaHeight = huffman ? huffmanTables.tableDeltaHeight.decode(huffmanInput) : decodeInteger(contextCache, "IADH", decoder); - currentHeight += deltaHeight; - let currentWidth = 0, - totalWidth = 0; - const firstSymbol = huffman ? symbolWidths.length : 0; - - while (true) { - const deltaWidth = huffman ? huffmanTables.tableDeltaWidth.decode(huffmanInput) : decodeInteger(contextCache, "IADW", decoder); - - if (deltaWidth === null) { - break; - } - - currentWidth += deltaWidth; - totalWidth += currentWidth; - let bitmap; - - if (refinement) { - const numberOfInstances = decodeInteger(contextCache, "IAAI", decoder); - - if (numberOfInstances > 1) { - bitmap = decodeTextRegion(huffman, refinement, currentWidth, currentHeight, 0, numberOfInstances, 1, symbols.concat(newSymbols), symbolCodeLength, 0, 0, 1, 0, huffmanTables, refinementTemplateIndex, refinementAt, decodingContext, 0, huffmanInput); - } else { - const symbolId = decodeIAID(contextCache, decoder, symbolCodeLength); - const rdx = decodeInteger(contextCache, "IARDX", decoder); - const rdy = decodeInteger(contextCache, "IARDY", decoder); - const symbol = symbolId < symbols.length ? symbols[symbolId] : newSymbols[symbolId - symbols.length]; - bitmap = decodeRefinement(currentWidth, currentHeight, refinementTemplateIndex, symbol, rdx, rdy, false, refinementAt, decodingContext); - } - - newSymbols.push(bitmap); - } else if (huffman) { - symbolWidths.push(currentWidth); - } else { - bitmap = decodeBitmap(false, currentWidth, currentHeight, templateIndex, false, null, at, decodingContext); - newSymbols.push(bitmap); - } - } - - if (huffman && !refinement) { - const bitmapSize = huffmanTables.tableBitmapSize.decode(huffmanInput); - huffmanInput.byteAlign(); - let collectiveBitmap; - - if (bitmapSize === 0) { - collectiveBitmap = readUncompressedBitmap(huffmanInput, totalWidth, currentHeight); - } else { - const originalEnd = huffmanInput.end; - const bitmapEnd = huffmanInput.position + bitmapSize; - huffmanInput.end = bitmapEnd; - collectiveBitmap = decodeMMRBitmap(huffmanInput, totalWidth, currentHeight, false); - huffmanInput.end = originalEnd; - huffmanInput.position = bitmapEnd; - } - - const numberOfSymbolsDecoded = symbolWidths.length; - - if (firstSymbol === numberOfSymbolsDecoded - 1) { - newSymbols.push(collectiveBitmap); - } else { - let i, - y, - xMin = 0, - xMax, - bitmapWidth, - symbolBitmap; - - for (i = firstSymbol; i < numberOfSymbolsDecoded; i++) { - bitmapWidth = symbolWidths[i]; - xMax = xMin + bitmapWidth; - symbolBitmap = []; - - for (y = 0; y < currentHeight; y++) { - symbolBitmap.push(collectiveBitmap[y].subarray(xMin, xMax)); - } - - newSymbols.push(symbolBitmap); - xMin = xMax; - } - } - } - } - - const exportedSymbols = [], - flags = []; - let currentFlag = false, - i, - ii; - const totalSymbolsLength = symbols.length + numberOfNewSymbols; - - while (flags.length < totalSymbolsLength) { - let runLength = huffman ? tableB1.decode(huffmanInput) : decodeInteger(contextCache, "IAEX", decoder); - - while (runLength--) { - flags.push(currentFlag); - } - - currentFlag = !currentFlag; - } - - for (i = 0, ii = symbols.length; i < ii; i++) { - if (flags[i]) { - exportedSymbols.push(symbols[i]); - } - } - - for (let 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, logStripSize, huffmanInput) { - if (huffman && refinement) { - throw new Jbig2Error("refinement with Huffman is not supported"); - } - - const bitmap = []; - let i, row; - - for (i = 0; i < height; i++) { - row = new Uint8Array(width); - - if (defaultPixelValue) { - for (let j = 0; j < width; j++) { - row[j] = defaultPixelValue; - } - } - - bitmap.push(row); - } - - const decoder = decodingContext.decoder; - const contextCache = decodingContext.contextCache; - let stripT = huffman ? -huffmanTables.tableDeltaT.decode(huffmanInput) : -decodeInteger(contextCache, "IADT", decoder); - let firstS = 0; - i = 0; - - while (i < numberOfSymbolInstances) { - const deltaT = huffman ? huffmanTables.tableDeltaT.decode(huffmanInput) : decodeInteger(contextCache, "IADT", decoder); - stripT += deltaT; - const deltaFirstS = huffman ? huffmanTables.tableFirstS.decode(huffmanInput) : decodeInteger(contextCache, "IAFS", decoder); - firstS += deltaFirstS; - let currentS = firstS; - - do { - let currentT = 0; - - if (stripSize > 1) { - currentT = huffman ? huffmanInput.readBits(logStripSize) : decodeInteger(contextCache, "IAIT", decoder); - } - - const t = stripSize * stripT + currentT; - const symbolId = huffman ? huffmanTables.symbolIDTable.decode(huffmanInput) : decodeIAID(contextCache, decoder, symbolCodeLength); - const applyRefinement = refinement && (huffman ? huffmanInput.readBit() : decodeInteger(contextCache, "IARI", decoder)); - let symbolBitmap = inputSymbols[symbolId]; - let symbolWidth = symbolBitmap[0].length; - let symbolHeight = symbolBitmap.length; - - if (applyRefinement) { - const rdw = decodeInteger(contextCache, "IARDW", decoder); - const rdh = decodeInteger(contextCache, "IARDH", decoder); - const rdx = decodeInteger(contextCache, "IARDX", decoder); - const rdy = decodeInteger(contextCache, "IARDY", decoder); - symbolWidth += rdw; - symbolHeight += rdh; - symbolBitmap = decodeRefinement(symbolWidth, symbolHeight, refinementTemplateIndex, symbolBitmap, (rdw >> 1) + rdx, (rdh >> 1) + rdy, false, refinementAt, decodingContext); - } - - const offsetT = t - (referenceCorner & 1 ? 0 : symbolHeight - 1); - const offsetS = currentS - (referenceCorner & 2 ? symbolWidth - 1 : 0); - let s2, t2, symbolRow; - - if (transposed) { - for (s2 = 0; s2 < symbolHeight; s2++) { - row = bitmap[offsetS + s2]; - - if (!row) { - continue; - } - - symbolRow = symbolBitmap[s2]; - const maxWidth = Math.min(width - offsetT, symbolWidth); - - switch (combinationOperator) { - case 0: - for (t2 = 0; t2 < maxWidth; t2++) { - row[offsetT + t2] |= symbolRow[t2]; - } - - break; - - case 2: - for (t2 = 0; t2 < maxWidth; t2++) { - row[offsetT + t2] ^= symbolRow[t2]; - } - - break; - - default: - throw new Jbig2Error(`operator ${combinationOperator} is not supported`); - } - } - - currentS += symbolHeight - 1; - } else { - for (t2 = 0; t2 < symbolHeight; t2++) { - row = bitmap[offsetT + t2]; - - if (!row) { - continue; - } - - symbolRow = symbolBitmap[t2]; - - switch (combinationOperator) { - case 0: - for (s2 = 0; s2 < symbolWidth; s2++) { - row[offsetS + s2] |= symbolRow[s2]; - } - - break; - - case 2: - for (s2 = 0; s2 < symbolWidth; s2++) { - row[offsetS + s2] ^= symbolRow[s2]; - } - - break; - - default: - throw new Jbig2Error(`operator ${combinationOperator} is not supported`); - } - } - - currentS += symbolWidth - 1; - } - - i++; - const deltaS = huffman ? huffmanTables.tableDeltaS.decode(huffmanInput) : decodeInteger(contextCache, "IADS", decoder); - - if (deltaS === null) { - break; - } - - currentS += deltaS + dsOffset; - } while (true); - } - - return bitmap; -} - -function decodePatternDictionary(mmr, patternWidth, patternHeight, maxPatternIndex, template, decodingContext) { - const at = []; - - if (!mmr) { - at.push({ - x: -patternWidth, - y: 0 - }); - - if (template === 0) { - at.push({ - x: -3, - y: -1 - }, { - x: 2, - y: -2 - }, { - x: -2, - y: -2 - }); - } - } - - const collectiveWidth = (maxPatternIndex + 1) * patternWidth; - const collectiveBitmap = decodeBitmap(mmr, collectiveWidth, patternHeight, template, false, null, at, decodingContext); - const patterns = []; - - for (let i = 0; i <= maxPatternIndex; i++) { - const patternBitmap = []; - const xMin = patternWidth * i; - const xMax = xMin + patternWidth; - - for (let y = 0; y < patternHeight; y++) { - patternBitmap.push(collectiveBitmap[y].subarray(xMin, xMax)); - } - - patterns.push(patternBitmap); - } - - return patterns; -} - -function decodeHalftoneRegion(mmr, patterns, template, regionWidth, regionHeight, defaultPixelValue, enableSkip, combinationOperator, gridWidth, gridHeight, gridOffsetX, gridOffsetY, gridVectorX, gridVectorY, decodingContext) { - const skip = null; - - if (enableSkip) { - throw new Jbig2Error("skip is not supported"); - } - - if (combinationOperator !== 0) { - throw new Jbig2Error(`operator "${combinationOperator}" is not supported in halftone region`); - } - - const regionBitmap = []; - let i, j, row; - - for (i = 0; i < regionHeight; i++) { - row = new Uint8Array(regionWidth); - - if (defaultPixelValue) { - for (j = 0; j < regionWidth; j++) { - row[j] = defaultPixelValue; - } - } - - regionBitmap.push(row); - } - - const numberOfPatterns = patterns.length; - const pattern0 = patterns[0]; - const patternWidth = pattern0[0].length, - patternHeight = pattern0.length; - const bitsPerValue = (0, _core_utils.log2)(numberOfPatterns); - const at = []; - - if (!mmr) { - at.push({ - x: template <= 1 ? 3 : 2, - y: -1 - }); - - if (template === 0) { - at.push({ - x: -3, - y: -1 - }, { - x: 2, - y: -2 - }, { - x: -2, - y: -2 - }); - } - } - - const grayScaleBitPlanes = []; - let mmrInput, bitmap; - - if (mmr) { - mmrInput = new Reader(decodingContext.data, decodingContext.start, decodingContext.end); - } - - for (i = bitsPerValue - 1; i >= 0; i--) { - if (mmr) { - bitmap = decodeMMRBitmap(mmrInput, gridWidth, gridHeight, true); - } else { - bitmap = decodeBitmap(false, gridWidth, gridHeight, template, false, skip, at, decodingContext); - } - - grayScaleBitPlanes[i] = bitmap; - } - - let mg, ng, bit, patternIndex, patternBitmap, x, y, patternRow, regionRow; - - for (mg = 0; mg < gridHeight; mg++) { - for (ng = 0; ng < gridWidth; ng++) { - bit = 0; - patternIndex = 0; - - for (j = bitsPerValue - 1; j >= 0; j--) { - bit ^= grayScaleBitPlanes[j][mg][ng]; - patternIndex |= bit << j; - } - - patternBitmap = patterns[patternIndex]; - x = gridOffsetX + mg * gridVectorY + ng * gridVectorX >> 8; - y = gridOffsetY + mg * gridVectorX - ng * gridVectorY >> 8; - - if (x >= 0 && x + patternWidth <= regionWidth && y >= 0 && y + patternHeight <= regionHeight) { - for (i = 0; i < patternHeight; i++) { - regionRow = regionBitmap[y + i]; - patternRow = patternBitmap[i]; - - for (j = 0; j < patternWidth; j++) { - regionRow[x + j] |= patternRow[j]; - } - } - } else { - let regionX, regionY; - - for (i = 0; i < patternHeight; i++) { - regionY = y + i; - - if (regionY < 0 || regionY >= regionHeight) { - continue; - } - - regionRow = regionBitmap[regionY]; - patternRow = patternBitmap[i]; - - for (j = 0; j < patternWidth; j++) { - regionX = x + j; - - if (regionX >= 0 && regionX < regionWidth) { - regionRow[regionX] |= patternRow[j]; - } - } - } - } - } - } - - return regionBitmap; -} - -function readSegmentHeader(data, start) { - const segmentHeader = {}; - segmentHeader.number = (0, _core_utils.readUint32)(data, start); - const flags = data[start + 4]; - const segmentType = flags & 0x3f; - - if (!SegmentTypes[segmentType]) { - throw new Jbig2Error("invalid segment type: " + segmentType); - } - - segmentHeader.type = segmentType; - segmentHeader.typeName = SegmentTypes[segmentType]; - segmentHeader.deferredNonRetain = !!(flags & 0x80); - const pageAssociationFieldSize = !!(flags & 0x40); - const referredFlags = data[start + 5]; - let referredToCount = referredFlags >> 5 & 7; - const retainBits = [referredFlags & 31]; - let position = start + 6; - - if (referredFlags === 7) { - referredToCount = (0, _core_utils.readUint32)(data, position - 1) & 0x1fffffff; - position += 3; - let bytes = referredToCount + 7 >> 3; - retainBits[0] = data[position++]; - - while (--bytes > 0) { - retainBits.push(data[position++]); - } - } else if (referredFlags === 5 || referredFlags === 6) { - throw new Jbig2Error("invalid referred-to flags"); - } - - segmentHeader.retainBits = retainBits; - let referredToSegmentNumberSize = 4; - - if (segmentHeader.number <= 256) { - referredToSegmentNumberSize = 1; - } else if (segmentHeader.number <= 65536) { - referredToSegmentNumberSize = 2; - } - - const referredTo = []; - let i, ii; - - for (i = 0; i < referredToCount; i++) { - let number; - - if (referredToSegmentNumberSize === 1) { - number = data[position]; - } else if (referredToSegmentNumberSize === 2) { - number = (0, _core_utils.readUint16)(data, position); - } else { - number = (0, _core_utils.readUint32)(data, position); - } - - referredTo.push(number); - position += referredToSegmentNumberSize; - } - - segmentHeader.referredTo = referredTo; - - if (!pageAssociationFieldSize) { - segmentHeader.pageAssociation = data[position++]; - } else { - segmentHeader.pageAssociation = (0, _core_utils.readUint32)(data, position); - position += 4; - } - - segmentHeader.length = (0, _core_utils.readUint32)(data, position); - position += 4; - - if (segmentHeader.length === 0xffffffff) { - if (segmentType === 38) { - const genericRegionInfo = readRegionSegmentInformation(data, position); - const genericRegionSegmentFlags = data[position + RegionSegmentInformationFieldLength]; - const genericRegionMmr = !!(genericRegionSegmentFlags & 1); - const searchPatternLength = 6; - const searchPattern = new Uint8Array(searchPatternLength); - - if (!genericRegionMmr) { - searchPattern[0] = 0xff; - searchPattern[1] = 0xac; - } - - searchPattern[2] = genericRegionInfo.height >>> 24 & 0xff; - searchPattern[3] = genericRegionInfo.height >> 16 & 0xff; - searchPattern[4] = genericRegionInfo.height >> 8 & 0xff; - searchPattern[5] = genericRegionInfo.height & 0xff; - - for (i = position, ii = data.length; i < ii; i++) { - let j = 0; - - while (j < searchPatternLength && searchPattern[j] === data[i + j]) { - j++; - } - - if (j === searchPatternLength) { - segmentHeader.length = i + searchPatternLength; - break; - } - } - - if (segmentHeader.length === 0xffffffff) { - throw new Jbig2Error("segment end was not found"); - } - } else { - throw new Jbig2Error("invalid unknown segment length"); - } - } - - segmentHeader.headerEnd = position; - return segmentHeader; -} - -function readSegments(header, data, start, end) { - const segments = []; - let position = start; - - while (position < end) { - const segmentHeader = readSegmentHeader(data, position); - position = segmentHeader.headerEnd; - const segment = { - header: segmentHeader, - data - }; - - if (!header.randomAccess) { - segment.start = position; - position += segmentHeader.length; - segment.end = position; - } - - segments.push(segment); - - if (segmentHeader.type === 51) { - break; - } - } - - if (header.randomAccess) { - for (let i = 0, ii = segments.length; i < ii; i++) { - segments[i].start = position; - position += segments[i].header.length; - segments[i].end = position; - } - } - - return segments; -} - -function readRegionSegmentInformation(data, start) { - return { - width: (0, _core_utils.readUint32)(data, start), - height: (0, _core_utils.readUint32)(data, start + 4), - x: (0, _core_utils.readUint32)(data, start + 8), - y: (0, _core_utils.readUint32)(data, start + 12), - combinationOperator: data[start + 16] & 7 - }; -} - -const RegionSegmentInformationFieldLength = 17; - -function processSegment(segment, visitor) { - const header = segment.header; - const data = segment.data, - end = segment.end; - let position = segment.start; - let args, at, i, atLength; - - switch (header.type) { - case 0: - const dictionary = {}; - const dictionaryFlags = (0, _core_utils.readUint16)(data, position); - dictionary.huffman = !!(dictionaryFlags & 1); - dictionary.refinement = !!(dictionaryFlags & 2); - dictionary.huffmanDHSelector = dictionaryFlags >> 2 & 3; - dictionary.huffmanDWSelector = dictionaryFlags >> 4 & 3; - dictionary.bitmapSizeSelector = dictionaryFlags >> 6 & 1; - dictionary.aggregationInstancesSelector = dictionaryFlags >> 7 & 1; - dictionary.bitmapCodingContextUsed = !!(dictionaryFlags & 256); - dictionary.bitmapCodingContextRetained = !!(dictionaryFlags & 512); - dictionary.template = dictionaryFlags >> 10 & 3; - dictionary.refinementTemplate = dictionaryFlags >> 12 & 1; - position += 2; - - if (!dictionary.huffman) { - atLength = dictionary.template === 0 ? 4 : 1; - at = []; - - for (i = 0; i < atLength; i++) { - at.push({ - x: (0, _core_utils.readInt8)(data, position), - y: (0, _core_utils.readInt8)(data, position + 1) - }); - position += 2; - } - - dictionary.at = at; - } - - if (dictionary.refinement && !dictionary.refinementTemplate) { - at = []; - - for (i = 0; i < 2; i++) { - at.push({ - x: (0, _core_utils.readInt8)(data, position), - y: (0, _core_utils.readInt8)(data, position + 1) - }); - position += 2; - } - - dictionary.refinementAt = at; - } - - dictionary.numberOfExportedSymbols = (0, _core_utils.readUint32)(data, position); - position += 4; - dictionary.numberOfNewSymbols = (0, _core_utils.readUint32)(data, position); - position += 4; - args = [dictionary, header.number, header.referredTo, data, position, end]; - break; - - case 6: - case 7: - const textRegion = {}; - textRegion.info = readRegionSegmentInformation(data, position); - position += RegionSegmentInformationFieldLength; - const textRegionSegmentFlags = (0, _core_utils.readUint16)(data, position); - position += 2; - textRegion.huffman = !!(textRegionSegmentFlags & 1); - textRegion.refinement = !!(textRegionSegmentFlags & 2); - textRegion.logStripSize = textRegionSegmentFlags >> 2 & 3; - textRegion.stripSize = 1 << textRegion.logStripSize; - 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) { - const textRegionHuffmanFlags = (0, _core_utils.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 & 0x4000); - } - - if (textRegion.refinement && !textRegion.refinementTemplate) { - at = []; - - for (i = 0; i < 2; i++) { - at.push({ - x: (0, _core_utils.readInt8)(data, position), - y: (0, _core_utils.readInt8)(data, position + 1) - }); - position += 2; - } - - textRegion.refinementAt = at; - } - - textRegion.numberOfSymbolInstances = (0, _core_utils.readUint32)(data, position); - position += 4; - args = [textRegion, header.referredTo, data, position, end]; - break; - - case 16: - const patternDictionary = {}; - const patternDictionaryFlags = data[position++]; - patternDictionary.mmr = !!(patternDictionaryFlags & 1); - patternDictionary.template = patternDictionaryFlags >> 1 & 3; - patternDictionary.patternWidth = data[position++]; - patternDictionary.patternHeight = data[position++]; - patternDictionary.maxPatternIndex = (0, _core_utils.readUint32)(data, position); - position += 4; - args = [patternDictionary, header.number, data, position, end]; - break; - - case 22: - case 23: - const halftoneRegion = {}; - halftoneRegion.info = readRegionSegmentInformation(data, position); - position += RegionSegmentInformationFieldLength; - const halftoneRegionFlags = data[position++]; - halftoneRegion.mmr = !!(halftoneRegionFlags & 1); - halftoneRegion.template = halftoneRegionFlags >> 1 & 3; - halftoneRegion.enableSkip = !!(halftoneRegionFlags & 8); - halftoneRegion.combinationOperator = halftoneRegionFlags >> 4 & 7; - halftoneRegion.defaultPixelValue = halftoneRegionFlags >> 7 & 1; - halftoneRegion.gridWidth = (0, _core_utils.readUint32)(data, position); - position += 4; - halftoneRegion.gridHeight = (0, _core_utils.readUint32)(data, position); - position += 4; - halftoneRegion.gridOffsetX = (0, _core_utils.readUint32)(data, position) & 0xffffffff; - position += 4; - halftoneRegion.gridOffsetY = (0, _core_utils.readUint32)(data, position) & 0xffffffff; - position += 4; - halftoneRegion.gridVectorX = (0, _core_utils.readUint16)(data, position); - position += 2; - halftoneRegion.gridVectorY = (0, _core_utils.readUint16)(data, position); - position += 2; - args = [halftoneRegion, header.referredTo, data, position, end]; - break; - - case 38: - case 39: - const genericRegion = {}; - genericRegion.info = readRegionSegmentInformation(data, position); - position += RegionSegmentInformationFieldLength; - const genericRegionSegmentFlags = data[position++]; - genericRegion.mmr = !!(genericRegionSegmentFlags & 1); - genericRegion.template = genericRegionSegmentFlags >> 1 & 3; - genericRegion.prediction = !!(genericRegionSegmentFlags & 8); - - if (!genericRegion.mmr) { - atLength = genericRegion.template === 0 ? 4 : 1; - at = []; - - for (i = 0; i < atLength; i++) { - at.push({ - x: (0, _core_utils.readInt8)(data, position), - y: (0, _core_utils.readInt8)(data, position + 1) - }); - position += 2; - } - - genericRegion.at = at; - } - - args = [genericRegion, data, position, end]; - break; - - case 48: - const pageInfo = { - width: (0, _core_utils.readUint32)(data, position), - height: (0, _core_utils.readUint32)(data, position + 4), - resolutionX: (0, _core_utils.readUint32)(data, position + 8), - resolutionY: (0, _core_utils.readUint32)(data, position + 12) - }; - - if (pageInfo.height === 0xffffffff) { - delete pageInfo.height; - } - - const pageSegmentFlags = data[position + 16]; - (0, _core_utils.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: - break; - - case 50: - break; - - case 51: - break; - - case 53: - args = [header.number, data, position, end]; - break; - - case 62: - break; - - default: - throw new Jbig2Error(`segment type ${header.typeName}(${header.type})` + " is not implemented"); - } - - const callbackName = "on" + header.typeName; - - if (callbackName in visitor) { - visitor[callbackName].apply(visitor, args); - } -} - -function processSegments(segments, visitor) { - for (let i = 0, ii = segments.length; i < ii; i++) { - processSegment(segments[i], visitor); - } -} - -function parseJbig2Chunks(chunks) { - const visitor = new SimpleSegmentVisitor(); - - for (let i = 0, ii = chunks.length; i < ii; i++) { - const chunk = chunks[i]; - const segments = readSegments({}, chunk.data, chunk.start, chunk.end); - processSegments(segments, visitor); - } - - return visitor.buffer; -} - -function parseJbig2(data) { - const end = data.length; - let position = 0; - - 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) { - throw new Jbig2Error("parseJbig2 - invalid header."); - } - - const header = Object.create(null); - position += 8; - const flags = data[position++]; - header.randomAccess = !(flags & 1); - - if (!(flags & 2)) { - header.numberOfPages = (0, _core_utils.readUint32)(data, position); - position += 4; - } - - const segments = readSegments(header, data, position, end); - const visitor = new SimpleSegmentVisitor(); - processSegments(segments, visitor); - const { - width, - height - } = visitor.currentPageInfo; - const bitPacked = visitor.buffer; - const imgData = new Uint8ClampedArray(width * height); - let q = 0, - k = 0; - - for (let i = 0; i < height; i++) { - let mask = 0, - buffer; - - for (let j = 0; j < width; j++) { - if (!mask) { - mask = 128; - buffer = bitPacked[k++]; - } - - imgData[q++] = buffer & mask ? 0 : 255; - mask >>= 1; - } - } - - return { - imgData, - width, - height - }; -} - -class SimpleSegmentVisitor { - onPageInformation(info) { - this.currentPageInfo = info; - const rowSize = info.width + 7 >> 3; - const buffer = new Uint8ClampedArray(rowSize * info.height); - - if (info.defaultPixelValue) { - for (let i = 0, ii = buffer.length; i < ii; i++) { - buffer[i] = 0xff; - } - } - - this.buffer = buffer; - } - - drawBitmap(regionInfo, bitmap) { - const pageInfo = this.currentPageInfo; - const width = regionInfo.width, - height = regionInfo.height; - const rowSize = pageInfo.width + 7 >> 3; - const combinationOperator = pageInfo.combinationOperatorOverride ? regionInfo.combinationOperator : pageInfo.combinationOperator; - const buffer = this.buffer; - const mask0 = 128 >> (regionInfo.x & 7); - let offset0 = regionInfo.y * rowSize + (regionInfo.x >> 3); - let i, j, mask, offset; - - switch (combinationOperator) { - case 0: - for (i = 0; i < height; i++) { - mask = mask0; - offset = offset0; - - for (j = 0; j < width; j++) { - if (bitmap[i][j]) { - buffer[offset] |= mask; - } - - mask >>= 1; - - if (!mask) { - mask = 128; - offset++; - } - } - - offset0 += rowSize; - } - - break; - - case 2: - for (i = 0; i < height; i++) { - mask = mask0; - offset = offset0; - - for (j = 0; j < width; j++) { - if (bitmap[i][j]) { - buffer[offset] ^= mask; - } - - mask >>= 1; - - if (!mask) { - mask = 128; - offset++; - } - } - - offset0 += rowSize; - } - - break; - - default: - throw new Jbig2Error(`operator ${combinationOperator} is not supported`); - } - } - - onImmediateGenericRegion(region, data, start, end) { - const regionInfo = region.info; - const decodingContext = new DecodingContext(data, start, end); - const bitmap = decodeBitmap(region.mmr, regionInfo.width, regionInfo.height, region.template, region.prediction, null, region.at, decodingContext); - this.drawBitmap(regionInfo, bitmap); - } - - onImmediateLosslessGenericRegion() { - this.onImmediateGenericRegion.apply(this, arguments); - } - - onSymbolDictionary(dictionary, currentSegment, referredSegments, data, start, end) { - let huffmanTables, huffmanInput; - - if (dictionary.huffman) { - huffmanTables = getSymbolDictionaryHuffmanTables(dictionary, referredSegments, this.customTables); - huffmanInput = new Reader(data, start, end); - } - - let symbols = this.symbols; - - if (!symbols) { - this.symbols = symbols = {}; - } - - let inputSymbols = []; - - for (let i = 0, ii = referredSegments.length; i < ii; i++) { - const referredSymbols = symbols[referredSegments[i]]; - - if (referredSymbols) { - inputSymbols = inputSymbols.concat(referredSymbols); - } - } - - const 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, huffmanInput); - } - - onImmediateTextRegion(region, referredSegments, data, start, end) { - const regionInfo = region.info; - let huffmanTables, huffmanInput; - const symbols = this.symbols; - let inputSymbols = []; - - for (let i = 0, ii = referredSegments.length; i < ii; i++) { - const referredSymbols = symbols[referredSegments[i]]; - - if (referredSymbols) { - inputSymbols = inputSymbols.concat(referredSymbols); - } - } - - const symbolCodeLength = (0, _core_utils.log2)(inputSymbols.length); - - if (region.huffman) { - huffmanInput = new Reader(data, start, end); - huffmanTables = getTextRegionHuffmanTables(region, referredSegments, this.customTables, inputSymbols.length, huffmanInput); - } - - const decodingContext = new DecodingContext(data, start, end); - const 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, region.logStripSize, huffmanInput); - this.drawBitmap(regionInfo, bitmap); - } - - onImmediateLosslessTextRegion() { - this.onImmediateTextRegion.apply(this, arguments); - } - - onPatternDictionary(dictionary, currentSegment, data, start, end) { - let patterns = this.patterns; - - if (!patterns) { - this.patterns = patterns = {}; - } - - const decodingContext = new DecodingContext(data, start, end); - patterns[currentSegment] = decodePatternDictionary(dictionary.mmr, dictionary.patternWidth, dictionary.patternHeight, dictionary.maxPatternIndex, dictionary.template, decodingContext); - } - - onImmediateHalftoneRegion(region, referredSegments, data, start, end) { - const patterns = this.patterns[referredSegments[0]]; - const regionInfo = region.info; - const decodingContext = new DecodingContext(data, start, end); - const bitmap = decodeHalftoneRegion(region.mmr, patterns, region.template, regionInfo.width, regionInfo.height, region.defaultPixelValue, region.enableSkip, region.combinationOperator, region.gridWidth, region.gridHeight, region.gridOffsetX, region.gridOffsetY, region.gridVectorX, region.gridVectorY, decodingContext); - this.drawBitmap(regionInfo, bitmap); - } - - onImmediateLosslessHalftoneRegion() { - this.onImmediateHalftoneRegion.apply(this, arguments); - } - - onTables(currentSegment, data, start, end) { - let customTables = this.customTables; - - if (!customTables) { - this.customTables = customTables = {}; - } - - customTables[currentSegment] = decodeTablesSegment(data, start, end); - } - -} - -class HuffmanLine { - constructor(lineData) { - if (lineData.length === 2) { - this.isOOB = true; - this.rangeLow = 0; - this.prefixLength = lineData[0]; - this.rangeLength = 0; - this.prefixCode = lineData[1]; - this.isLowerRange = false; - } else { - this.isOOB = false; - this.rangeLow = lineData[0]; - this.prefixLength = lineData[1]; - this.rangeLength = lineData[2]; - this.prefixCode = lineData[3]; - this.isLowerRange = lineData[4] === "lower"; - } - } - -} - -class HuffmanTreeNode { - constructor(line) { - this.children = []; - - if (line) { - this.isLeaf = true; - this.rangeLength = line.rangeLength; - this.rangeLow = line.rangeLow; - this.isLowerRange = line.isLowerRange; - this.isOOB = line.isOOB; - } else { - this.isLeaf = false; - } - } - - buildTree(line, shift) { - const bit = line.prefixCode >> shift & 1; - - if (shift <= 0) { - this.children[bit] = new HuffmanTreeNode(line); - } else { - let node = this.children[bit]; - - if (!node) { - this.children[bit] = node = new HuffmanTreeNode(null); - } - - node.buildTree(line, shift - 1); - } - } - - decodeNode(reader) { - if (this.isLeaf) { - if (this.isOOB) { - return null; - } - - const htOffset = reader.readBits(this.rangeLength); - return this.rangeLow + (this.isLowerRange ? -htOffset : htOffset); - } - - const node = this.children[reader.readBit()]; - - if (!node) { - throw new Jbig2Error("invalid Huffman data"); - } - - return node.decodeNode(reader); - } - -} - -class HuffmanTable { - constructor(lines, prefixCodesDone) { - if (!prefixCodesDone) { - this.assignPrefixCodes(lines); - } - - this.rootNode = new HuffmanTreeNode(null); - - for (let i = 0, ii = lines.length; i < ii; i++) { - const line = lines[i]; - - if (line.prefixLength > 0) { - this.rootNode.buildTree(line, line.prefixLength - 1); - } - } - } - - decode(reader) { - return this.rootNode.decodeNode(reader); - } - - assignPrefixCodes(lines) { - const linesLength = lines.length; - let prefixLengthMax = 0; - - for (let i = 0; i < linesLength; i++) { - prefixLengthMax = Math.max(prefixLengthMax, lines[i].prefixLength); - } - - const histogram = new Uint32Array(prefixLengthMax + 1); - - for (let i = 0; i < linesLength; i++) { - histogram[lines[i].prefixLength]++; - } - - let currentLength = 1, - firstCode = 0, - currentCode, - currentTemp, - line; - histogram[0] = 0; - - while (currentLength <= prefixLengthMax) { - firstCode = firstCode + histogram[currentLength - 1] << 1; - currentCode = firstCode; - currentTemp = 0; - - while (currentTemp < linesLength) { - line = lines[currentTemp]; - - if (line.prefixLength === currentLength) { - line.prefixCode = currentCode; - currentCode++; - } - - currentTemp++; - } - - currentLength++; - } - } - -} - -function decodeTablesSegment(data, start, end) { - const flags = data[start]; - const lowestValue = (0, _core_utils.readUint32)(data, start + 1) & 0xffffffff; - const highestValue = (0, _core_utils.readUint32)(data, start + 5) & 0xffffffff; - const reader = new Reader(data, start + 9, end); - const prefixSizeBits = (flags >> 1 & 7) + 1; - const rangeSizeBits = (flags >> 4 & 7) + 1; - const lines = []; - let prefixLength, - rangeLength, - currentRangeLow = lowestValue; - - do { - prefixLength = reader.readBits(prefixSizeBits); - rangeLength = reader.readBits(rangeSizeBits); - lines.push(new HuffmanLine([currentRangeLow, prefixLength, rangeLength, 0])); - currentRangeLow += 1 << rangeLength; - } while (currentRangeLow < highestValue); - - prefixLength = reader.readBits(prefixSizeBits); - lines.push(new HuffmanLine([lowestValue - 1, prefixLength, 32, 0, "lower"])); - prefixLength = reader.readBits(prefixSizeBits); - lines.push(new HuffmanLine([highestValue, prefixLength, 32, 0])); - - if (flags & 1) { - prefixLength = reader.readBits(prefixSizeBits); - lines.push(new HuffmanLine([prefixLength, 0])); - } - - return new HuffmanTable(lines, false); -} - -const standardTablesCache = {}; - -function getStandardTable(number) { - let table = standardTablesCache[number]; - - if (table) { - return table; - } - - let lines; - - switch (number) { - case 1: - lines = [[0, 1, 4, 0x0], [16, 2, 8, 0x2], [272, 3, 16, 0x6], [65808, 3, 32, 0x7]]; - break; - - case 2: - lines = [[0, 1, 0, 0x0], [1, 2, 0, 0x2], [2, 3, 0, 0x6], [3, 4, 3, 0xe], [11, 5, 6, 0x1e], [75, 6, 32, 0x3e], [6, 0x3f]]; - break; - - case 3: - lines = [[-256, 8, 8, 0xfe], [0, 1, 0, 0x0], [1, 2, 0, 0x2], [2, 3, 0, 0x6], [3, 4, 3, 0xe], [11, 5, 6, 0x1e], [-257, 8, 32, 0xff, "lower"], [75, 7, 32, 0x7e], [6, 0x3e]]; - break; - - case 4: - lines = [[1, 1, 0, 0x0], [2, 2, 0, 0x2], [3, 3, 0, 0x6], [4, 4, 3, 0xe], [12, 5, 6, 0x1e], [76, 5, 32, 0x1f]]; - break; - - case 5: - lines = [[-255, 7, 8, 0x7e], [1, 1, 0, 0x0], [2, 2, 0, 0x2], [3, 3, 0, 0x6], [4, 4, 3, 0xe], [12, 5, 6, 0x1e], [-256, 7, 32, 0x7f, "lower"], [76, 6, 32, 0x3e]]; - break; - - case 6: - lines = [[-2048, 5, 10, 0x1c], [-1024, 4, 9, 0x8], [-512, 4, 8, 0x9], [-256, 4, 7, 0xa], [-128, 5, 6, 0x1d], [-64, 5, 5, 0x1e], [-32, 4, 5, 0xb], [0, 2, 7, 0x0], [128, 3, 7, 0x2], [256, 3, 8, 0x3], [512, 4, 9, 0xc], [1024, 4, 10, 0xd], [-2049, 6, 32, 0x3e, "lower"], [2048, 6, 32, 0x3f]]; - break; - - case 7: - lines = [[-1024, 4, 9, 0x8], [-512, 3, 8, 0x0], [-256, 4, 7, 0x9], [-128, 5, 6, 0x1a], [-64, 5, 5, 0x1b], [-32, 4, 5, 0xa], [0, 4, 5, 0xb], [32, 5, 5, 0x1c], [64, 5, 6, 0x1d], [128, 4, 7, 0xc], [256, 3, 8, 0x1], [512, 3, 9, 0x2], [1024, 3, 10, 0x3], [-1025, 5, 32, 0x1e, "lower"], [2048, 5, 32, 0x1f]]; - break; - - case 8: - lines = [[-15, 8, 3, 0xfc], [-7, 9, 1, 0x1fc], [-5, 8, 1, 0xfd], [-3, 9, 0, 0x1fd], [-2, 7, 0, 0x7c], [-1, 4, 0, 0xa], [0, 2, 1, 0x0], [2, 5, 0, 0x1a], [3, 6, 0, 0x3a], [4, 3, 4, 0x4], [20, 6, 1, 0x3b], [22, 4, 4, 0xb], [38, 4, 5, 0xc], [70, 5, 6, 0x1b], [134, 5, 7, 0x1c], [262, 6, 7, 0x3c], [390, 7, 8, 0x7d], [646, 6, 10, 0x3d], [-16, 9, 32, 0x1fe, "lower"], [1670, 9, 32, 0x1ff], [2, 0x1]]; - break; - - case 9: - lines = [[-31, 8, 4, 0xfc], [-15, 9, 2, 0x1fc], [-11, 8, 2, 0xfd], [-7, 9, 1, 0x1fd], [-5, 7, 1, 0x7c], [-3, 4, 1, 0xa], [-1, 3, 1, 0x2], [1, 3, 1, 0x3], [3, 5, 1, 0x1a], [5, 6, 1, 0x3a], [7, 3, 5, 0x4], [39, 6, 2, 0x3b], [43, 4, 5, 0xb], [75, 4, 6, 0xc], [139, 5, 7, 0x1b], [267, 5, 8, 0x1c], [523, 6, 8, 0x3c], [779, 7, 9, 0x7d], [1291, 6, 11, 0x3d], [-32, 9, 32, 0x1fe, "lower"], [3339, 9, 32, 0x1ff], [2, 0x0]]; - break; - - case 10: - lines = [[-21, 7, 4, 0x7a], [-5, 8, 0, 0xfc], [-4, 7, 0, 0x7b], [-3, 5, 0, 0x18], [-2, 2, 2, 0x0], [2, 5, 0, 0x19], [3, 6, 0, 0x36], [4, 7, 0, 0x7c], [5, 8, 0, 0xfd], [6, 2, 6, 0x1], [70, 5, 5, 0x1a], [102, 6, 5, 0x37], [134, 6, 6, 0x38], [198, 6, 7, 0x39], [326, 6, 8, 0x3a], [582, 6, 9, 0x3b], [1094, 6, 10, 0x3c], [2118, 7, 11, 0x7d], [-22, 8, 32, 0xfe, "lower"], [4166, 8, 32, 0xff], [2, 0x2]]; - break; - - case 11: - lines = [[1, 1, 0, 0x0], [2, 2, 1, 0x2], [4, 4, 0, 0xc], [5, 4, 1, 0xd], [7, 5, 1, 0x1c], [9, 5, 2, 0x1d], [13, 6, 2, 0x3c], [17, 7, 2, 0x7a], [21, 7, 3, 0x7b], [29, 7, 4, 0x7c], [45, 7, 5, 0x7d], [77, 7, 6, 0x7e], [141, 7, 32, 0x7f]]; - break; - - case 12: - lines = [[1, 1, 0, 0x0], [2, 2, 0, 0x2], [3, 3, 1, 0x6], [5, 5, 0, 0x1c], [6, 5, 1, 0x1d], [8, 6, 1, 0x3c], [10, 7, 0, 0x7a], [11, 7, 1, 0x7b], [13, 7, 2, 0x7c], [17, 7, 3, 0x7d], [25, 7, 4, 0x7e], [41, 8, 5, 0xfe], [73, 8, 32, 0xff]]; - break; - - case 13: - lines = [[1, 1, 0, 0x0], [2, 3, 0, 0x4], [3, 4, 0, 0xc], [4, 5, 0, 0x1c], [5, 4, 1, 0xd], [7, 3, 3, 0x5], [15, 6, 1, 0x3a], [17, 6, 2, 0x3b], [21, 6, 3, 0x3c], [29, 6, 4, 0x3d], [45, 6, 5, 0x3e], [77, 7, 6, 0x7e], [141, 7, 32, 0x7f]]; - break; - - case 14: - lines = [[-2, 3, 0, 0x4], [-1, 3, 0, 0x5], [0, 1, 0, 0x0], [1, 3, 0, 0x6], [2, 3, 0, 0x7]]; - break; - - case 15: - lines = [[-24, 7, 4, 0x7c], [-8, 6, 2, 0x3c], [-4, 5, 1, 0x1c], [-2, 4, 0, 0xc], [-1, 3, 0, 0x4], [0, 1, 0, 0x0], [1, 3, 0, 0x5], [2, 4, 0, 0xd], [3, 5, 1, 0x1d], [5, 6, 2, 0x3d], [9, 7, 4, 0x7d], [-25, 7, 32, 0x7e, "lower"], [25, 7, 32, 0x7f]]; - break; - - default: - throw new Jbig2Error(`standard table B.${number} does not exist`); - } - - for (let i = 0, ii = lines.length; i < ii; i++) { - lines[i] = new HuffmanLine(lines[i]); - } - - table = new HuffmanTable(lines, true); - standardTablesCache[number] = table; - return table; -} - -class Reader { - constructor(data, start, end) { - this.data = data; - this.start = start; - this.end = end; - this.position = start; - this.shift = -1; - this.currentByte = 0; - } - - readBit() { - if (this.shift < 0) { - if (this.position >= this.end) { - throw new Jbig2Error("end of data while reading bit"); - } - - this.currentByte = this.data[this.position++]; - this.shift = 7; - } - - const bit = this.currentByte >> this.shift & 1; - this.shift--; - return bit; - } - - readBits(numBits) { - let result = 0, - i; - - for (i = numBits - 1; i >= 0; i--) { - result |= this.readBit() << i; - } - - return result; - } - - byteAlign() { - this.shift = -1; - } - - next() { - if (this.position >= this.end) { - return -1; - } - - return this.data[this.position++]; - } - -} - -function getCustomHuffmanTable(index, referredTo, customTables) { - let currentIndex = 0; - - for (let i = 0, ii = referredTo.length; i < ii; i++) { - const table = customTables[referredTo[i]]; - - if (table) { - if (index === currentIndex) { - return table; - } - - currentIndex++; - } - } - - throw new Jbig2Error("can't find custom Huffman table"); -} - -function getTextRegionHuffmanTables(textRegion, referredTo, customTables, numberOfSymbols, reader) { - const codes = []; - - for (let i = 0; i <= 34; i++) { - const codeLength = reader.readBits(4); - codes.push(new HuffmanLine([i, codeLength, 0, 0])); - } - - const runCodesTable = new HuffmanTable(codes, false); - codes.length = 0; - - for (let i = 0; i < numberOfSymbols;) { - const codeLength = runCodesTable.decode(reader); - - if (codeLength >= 32) { - let repeatedLength, numberOfRepeats, j; - - switch (codeLength) { - case 32: - if (i === 0) { - throw new Jbig2Error("no previous value in symbol ID table"); - } - - numberOfRepeats = reader.readBits(2) + 3; - repeatedLength = codes[i - 1].prefixLength; - break; - - case 33: - numberOfRepeats = reader.readBits(3) + 3; - repeatedLength = 0; - break; - - case 34: - numberOfRepeats = reader.readBits(7) + 11; - repeatedLength = 0; - break; - - default: - throw new Jbig2Error("invalid code length in symbol ID table"); - } - - for (j = 0; j < numberOfRepeats; j++) { - codes.push(new HuffmanLine([i, repeatedLength, 0, 0])); - i++; - } - } else { - codes.push(new HuffmanLine([i, codeLength, 0, 0])); - i++; - } - } - - reader.byteAlign(); - const symbolIDTable = new HuffmanTable(codes, false); - let customIndex = 0, - tableFirstS, - tableDeltaS, - tableDeltaT; - - switch (textRegion.huffmanFS) { - case 0: - case 1: - tableFirstS = getStandardTable(textRegion.huffmanFS + 6); - break; - - case 3: - tableFirstS = getCustomHuffmanTable(customIndex, referredTo, customTables); - customIndex++; - break; - - default: - throw new Jbig2Error("invalid Huffman FS selector"); - } - - switch (textRegion.huffmanDS) { - case 0: - case 1: - case 2: - tableDeltaS = getStandardTable(textRegion.huffmanDS + 8); - break; - - case 3: - tableDeltaS = getCustomHuffmanTable(customIndex, referredTo, customTables); - customIndex++; - break; - - default: - throw new Jbig2Error("invalid Huffman DS selector"); - } - - switch (textRegion.huffmanDT) { - case 0: - case 1: - case 2: - tableDeltaT = getStandardTable(textRegion.huffmanDT + 11); - break; - - case 3: - tableDeltaT = getCustomHuffmanTable(customIndex, referredTo, customTables); - customIndex++; - break; - - default: - throw new Jbig2Error("invalid Huffman DT selector"); - } - - if (textRegion.refinement) { - throw new Jbig2Error("refinement with Huffman is not supported"); - } - - return { - symbolIDTable, - tableFirstS, - tableDeltaS, - tableDeltaT - }; -} - -function getSymbolDictionaryHuffmanTables(dictionary, referredTo, customTables) { - let customIndex = 0, - tableDeltaHeight, - tableDeltaWidth; - - switch (dictionary.huffmanDHSelector) { - case 0: - case 1: - tableDeltaHeight = getStandardTable(dictionary.huffmanDHSelector + 4); - break; - - case 3: - tableDeltaHeight = getCustomHuffmanTable(customIndex, referredTo, customTables); - customIndex++; - break; - - default: - throw new Jbig2Error("invalid Huffman DH selector"); - } - - switch (dictionary.huffmanDWSelector) { - case 0: - case 1: - tableDeltaWidth = getStandardTable(dictionary.huffmanDWSelector + 2); - break; - - case 3: - tableDeltaWidth = getCustomHuffmanTable(customIndex, referredTo, customTables); - customIndex++; - break; - - default: - throw new Jbig2Error("invalid Huffman DW selector"); - } - - let tableBitmapSize, tableAggregateInstances; - - if (dictionary.bitmapSizeSelector) { - tableBitmapSize = getCustomHuffmanTable(customIndex, referredTo, customTables); - customIndex++; - } else { - tableBitmapSize = getStandardTable(1); - } - - if (dictionary.aggregationInstancesSelector) { - tableAggregateInstances = getCustomHuffmanTable(customIndex, referredTo, customTables); - } else { - tableAggregateInstances = getStandardTable(1); - } - - return { - tableDeltaHeight, - tableDeltaWidth, - tableBitmapSize, - tableAggregateInstances - }; -} - -function readUncompressedBitmap(reader, width, height) { - const bitmap = []; - - for (let y = 0; y < height; y++) { - const row = new Uint8Array(width); - bitmap.push(row); - - for (let x = 0; x < width; x++) { - row[x] = reader.readBit(); - } - - reader.byteAlign(); - } - - return bitmap; -} - -function decodeMMRBitmap(input, width, height, endOfBlock) { - const params = { - K: -1, - Columns: width, - Rows: height, - BlackIs1: true, - EndOfBlock: endOfBlock - }; - const decoder = new _ccitt.CCITTFaxDecoder(input, params); - const bitmap = []; - let currentByte, - eof = false; - - for (let y = 0; y < height; y++) { - const row = new Uint8Array(width); - bitmap.push(row); - let shift = -1; - - for (let x = 0; x < width; x++) { - if (shift < 0) { - currentByte = decoder.readNextChar(); - - if (currentByte === -1) { - currentByte = 0; - eof = true; - } - - shift = 7; - } - - row[x] = currentByte >> shift & 1; - shift--; - } - } - - if (endOfBlock && !eof) { - const lookForEOFLimit = 5; - - for (let i = 0; i < lookForEOFLimit; i++) { - if (decoder.readNextChar() === -1) { - break; - } - } - } - - return bitmap; -} - -class Jbig2Image { - parseChunks(chunks) { - return parseJbig2Chunks(chunks); - } - - parse(data) { - const { - imgData, - width, - height - } = parseJbig2(data); - this.width = width; - this.height = height; - return imgData; - } - -} - -exports.Jbig2Image = Jbig2Image; - -/***/ }), -/* 36 */ -/***/ ((__unused_webpack_module, exports) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.ArithmeticDecoder = void 0; -const 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 -}]; - -class ArithmeticDecoder { - constructor(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; - } - - byteIn() { - const data = this.data; - let bp = this.bp; - - if (data[bp] === 0xff) { - if (data[bp + 1] > 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(contexts, pos) { - let cx_index = contexts[pos] >> 1, - cx_mps = contexts[pos] & 1; - const qeTableIcx = QeTable[cx_index]; - const qeIcx = qeTableIcx.qe; - let d; - let a = this.a - qeIcx; - - if (this.chigh < qeIcx) { - if (a < qeIcx) { - a = qeIcx; - d = cx_mps; - cx_index = qeTableIcx.nmps; - } else { - a = qeIcx; - d = 1 ^ cx_mps; - - if (qeTableIcx.switchFlag === 1) { - cx_mps = d; - } - - cx_index = qeTableIcx.nlps; - } - } else { - this.chigh -= qeIcx; - - if ((a & 0x8000) !== 0) { - this.a = a; - return cx_mps; - } - - if (a < qeIcx) { - d = 1 ^ cx_mps; - - if (qeTableIcx.switchFlag === 1) { - cx_mps = d; - } - - cx_index = qeTableIcx.nlps; - } else { - d = cx_mps; - cx_index = qeTableIcx.nmps; - } - } - - do { - if (this.ct === 0) { - this.byteIn(); - } - - a <<= 1; - this.chigh = this.chigh << 1 & 0xffff | this.clow >> 15 & 1; - this.clow = this.clow << 1 & 0xffff; - this.ct--; - } while ((a & 0x8000) === 0); - - this.a = a; - contexts[pos] = cx_index << 1 | cx_mps; - return d; - } - -} - -exports.ArithmeticDecoder = ArithmeticDecoder; - -/***/ }), -/* 37 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.JpegStream = void 0; - -var _decode_stream = __w_pdfjs_require__(29); - -var _primitives = __w_pdfjs_require__(5); - -var _jpg = __w_pdfjs_require__(38); - -var _util = __w_pdfjs_require__(2); - -class JpegStream extends _decode_stream.DecodeStream { - constructor(stream, maybeLength, params) { - let ch; - - while ((ch = stream.getByte()) !== -1) { - if (ch === 0xff) { - stream.skip(-1); - break; - } - } - - super(maybeLength); - this.stream = stream; - this.dict = stream.dict; - this.maybeLength = maybeLength; - this.params = params; - } - - get bytes() { - return (0, _util.shadow)(this, "bytes", this.stream.getBytes(this.maybeLength)); - } - - ensureBuffer(requested) {} - - readBlock() { - if (this.eof) { - return; - } - - const jpegOptions = { - decodeTransform: undefined, - colorTransform: undefined - }; - const decodeArr = this.dict.getArray("D", "Decode"); - - if (this.forceRGB && Array.isArray(decodeArr)) { - const bitsPerComponent = this.dict.get("BPC", "BitsPerComponent") || 8; - const decodeArrLength = decodeArr.length; - const transform = new Int32Array(decodeArrLength); - let transformNeeded = false; - const maxValue = (1 << bitsPerComponent) - 1; - - for (let i = 0; i < decodeArrLength; i += 2) { - transform[i] = (decodeArr[i + 1] - decodeArr[i]) * 256 | 0; - transform[i + 1] = decodeArr[i] * maxValue | 0; - - if (transform[i] !== 256 || transform[i + 1] !== 0) { - transformNeeded = true; - } - } - - if (transformNeeded) { - jpegOptions.decodeTransform = transform; - } - } - - if ((0, _primitives.isDict)(this.params)) { - const colorTransform = this.params.get("ColorTransform"); - - if (Number.isInteger(colorTransform)) { - jpegOptions.colorTransform = colorTransform; - } - } - - const jpegImage = new _jpg.JpegImage(jpegOptions); - jpegImage.parse(this.bytes); - const data = jpegImage.getData({ - width: this.drawWidth, - height: this.drawHeight, - forceRGB: this.forceRGB, - isSourcePDF: true - }); - this.buffer = data; - this.bufferLength = data.length; - this.eof = true; - } - -} - -exports.JpegStream = JpegStream; - -/***/ }), -/* 38 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.JpegImage = void 0; - -var _util = __w_pdfjs_require__(2); - -var _core_utils = __w_pdfjs_require__(9); - -class JpegError extends _util.BaseException { - constructor(msg) { - super(`JPEG error: ${msg}`, "JpegError"); - } - -} - -class DNLMarkerError extends _util.BaseException { - constructor(message, scanLines) { - super(message, "DNLMarkerError"); - this.scanLines = scanLines; - } - -} - -class EOIMarkerError extends _util.BaseException { - constructor(msg) { - super(msg, "EOIMarkerError"); - } - -} - -const dctZigZag = new Uint8Array([0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63]); -const dctCos1 = 4017; -const dctSin1 = 799; -const dctCos3 = 3406; -const dctSin3 = 2276; -const dctCos6 = 1567; -const dctSin6 = 3784; -const dctSqrt2 = 5793; -const dctSqrt1d2 = 2896; - -function buildHuffmanTable(codeLengths, values) { - let k = 0, - i, - j, - length = 16; - - while (length > 0 && !codeLengths[length - 1]) { - length--; - } - - const code = [{ - children: [], - index: 0 - }]; - let 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) { - code.push(q = { - children: [], - index: 0 - }); - p.children[p.index] = q.children; - p = q; - } - } - - return code[0].children; -} - -function getBlockBufferOffset(component, row, col) { - return 64 * ((component.blocksPerLine + 1) * row + col); -} - -function decodeScan(data, offset, frame, components, resetInterval, spectralStart, spectralEnd, successivePrev, successive, parseDNLMarker = false) { - const mcusPerLine = frame.mcusPerLine; - const progressive = frame.progressive; - const startOffset = offset; - let bitsData = 0, - bitsCount = 0; - - function readBit() { - if (bitsCount > 0) { - bitsCount--; - return bitsData >> bitsCount & 1; - } - - bitsData = data[offset++]; - - if (bitsData === 0xff) { - const nextByte = data[offset++]; - - if (nextByte) { - if (nextByte === 0xdc && parseDNLMarker) { - offset += 2; - const scanLines = (0, _core_utils.readUint16)(data, offset); - offset += 2; - - if (scanLines > 0 && scanLines !== frame.scanLines) { - throw new DNLMarkerError("Found DNL marker (0xFFDC) while parsing scan data", scanLines); - } - } else if (nextByte === 0xd9) { - if (parseDNLMarker) { - const maybeScanLines = blockRow * (frame.precision === 8 ? 8 : 0); - - if (maybeScanLines > 0 && Math.round(frame.scanLines / maybeScanLines) >= 10) { - throw new DNLMarkerError("Found EOI marker (0xFFD9) while parsing scan data, " + "possibly caused by incorrect `scanLines` parameter", maybeScanLines); - } - } - - throw new EOIMarkerError("Found EOI marker (0xFFD9) while parsing scan data"); - } - - throw new JpegError(`unexpected marker ${(bitsData << 8 | nextByte).toString(16)}`); - } - } - - bitsCount = 7; - return bitsData >>> 7; - } - - function decodeHuffman(tree) { - let node = tree; - - while (true) { - node = node[readBit()]; - - switch (typeof node) { - case "number": - return node; - - case "object": - continue; - } - - throw new JpegError("invalid huffman sequence"); - } - } - - function receive(length) { - let n = 0; - - while (length > 0) { - n = n << 1 | readBit(); - length--; - } - - return n; - } - - function receiveAndExtend(length) { - if (length === 1) { - return readBit() === 1 ? 1 : -1; - } - - const n = receive(length); - - if (n >= 1 << length - 1) { - return n; - } - - return n + (-1 << length) + 1; - } - - function decodeBaseline(component, blockOffset) { - const t = decodeHuffman(component.huffmanTableDC); - const diff = t === 0 ? 0 : receiveAndExtend(t); - component.blockData[blockOffset] = component.pred += diff; - let k = 1; - - while (k < 64) { - const rs = decodeHuffman(component.huffmanTableAC); - const s = rs & 15, - r = rs >> 4; - - if (s === 0) { - if (r < 15) { - break; - } - - k += 16; - continue; - } - - k += r; - const z = dctZigZag[k]; - component.blockData[blockOffset + z] = receiveAndExtend(s); - k++; - } - } - - function decodeDCFirst(component, blockOffset) { - const t = decodeHuffman(component.huffmanTableDC); - const diff = t === 0 ? 0 : receiveAndExtend(t) << successive; - component.blockData[blockOffset] = component.pred += diff; - } - - function decodeDCSuccessive(component, blockOffset) { - component.blockData[blockOffset] |= readBit() << successive; - } - - let eobrun = 0; - - function decodeACFirst(component, blockOffset) { - if (eobrun > 0) { - eobrun--; - return; - } - - let k = spectralStart; - const e = spectralEnd; - - while (k <= e) { - const rs = decodeHuffman(component.huffmanTableAC); - const s = rs & 15, - r = rs >> 4; - - if (s === 0) { - if (r < 15) { - eobrun = receive(r) + (1 << r) - 1; - break; - } - - k += 16; - continue; - } - - k += r; - const z = dctZigZag[k]; - component.blockData[blockOffset + z] = receiveAndExtend(s) * (1 << successive); - k++; - } - } - - let successiveACState = 0, - successiveACNextValue; - - function decodeACSuccessive(component, blockOffset) { - let k = spectralStart; - const e = spectralEnd; - let r = 0; - let s; - let rs; - - while (k <= e) { - const offsetZ = blockOffset + dctZigZag[k]; - const sign = component.blockData[offsetZ] < 0 ? -1 : 1; - - switch (successiveACState) { - case 0: - rs = decodeHuffman(component.huffmanTableAC); - s = rs & 15; - r = rs >> 4; - - if (s === 0) { - if (r < 15) { - eobrun = receive(r) + (1 << r); - successiveACState = 4; - } else { - r = 16; - successiveACState = 1; - } - } else { - if (s !== 1) { - throw new JpegError("invalid ACn encoding"); - } - - successiveACNextValue = receiveAndExtend(s); - successiveACState = r ? 2 : 3; - } - - continue; - - case 1: - case 2: - if (component.blockData[offsetZ]) { - component.blockData[offsetZ] += sign * (readBit() << successive); - } else { - r--; - - if (r === 0) { - successiveACState = successiveACState === 2 ? 3 : 0; - } - } - - break; - - case 3: - if (component.blockData[offsetZ]) { - component.blockData[offsetZ] += sign * (readBit() << successive); - } else { - component.blockData[offsetZ] = successiveACNextValue << successive; - successiveACState = 0; - } - - break; - - case 4: - if (component.blockData[offsetZ]) { - component.blockData[offsetZ] += sign * (readBit() << successive); - } - - break; - } - - k++; - } - - if (successiveACState === 4) { - eobrun--; - - if (eobrun === 0) { - successiveACState = 0; - } - } - } - - let blockRow = 0; - - function decodeMcu(component, decode, mcu, row, col) { - const mcuRow = mcu / mcusPerLine | 0; - const mcuCol = mcu % mcusPerLine; - blockRow = mcuRow * component.v + row; - const blockCol = mcuCol * component.h + col; - const blockOffset = getBlockBufferOffset(component, blockRow, blockCol); - decode(component, blockOffset); - } - - function decodeBlock(component, decode, mcu) { - blockRow = mcu / component.blocksPerLine | 0; - const blockCol = mcu % component.blocksPerLine; - const blockOffset = getBlockBufferOffset(component, blockRow, blockCol); - decode(component, blockOffset); - } - - const componentsLength = components.length; - let component, i, j, k, n; - let decodeFn; - - if (progressive) { - if (spectralStart === 0) { - decodeFn = successivePrev === 0 ? decodeDCFirst : decodeDCSuccessive; - } else { - decodeFn = successivePrev === 0 ? decodeACFirst : decodeACSuccessive; - } - } else { - decodeFn = decodeBaseline; - } - - let mcu = 0, - fileMarker; - let mcuExpected; - - if (componentsLength === 1) { - mcuExpected = components[0].blocksPerLine * components[0].blocksPerColumn; - } else { - mcuExpected = mcusPerLine * frame.mcusPerColumn; - } - - let h, v; - - while (mcu <= mcuExpected) { - const mcuToRead = resetInterval ? Math.min(mcuExpected - mcu, resetInterval) : mcuExpected; - - if (mcuToRead > 0) { - for (i = 0; i < componentsLength; i++) { - components[i].pred = 0; - } - - eobrun = 0; - - if (componentsLength === 1) { - component = components[0]; - - for (n = 0; n < mcuToRead; n++) { - decodeBlock(component, decodeFn, mcu); - mcu++; - } - } else { - for (n = 0; n < mcuToRead; 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++; - } - } - } - - bitsCount = 0; - fileMarker = findNextFileMarker(data, offset); - - if (!fileMarker) { - break; - } - - if (fileMarker.invalid) { - const partialMsg = mcuToRead > 0 ? "unexpected" : "excessive"; - (0, _util.warn)(`decodeScan - ${partialMsg} MCU data, current marker is: ${fileMarker.invalid}`); - offset = fileMarker.offset; - } - - if (fileMarker.marker >= 0xffd0 && fileMarker.marker <= 0xffd7) { - offset += 2; - } else { - break; - } - } - - return offset - startOffset; -} - -function quantizeAndInverse(component, blockBufferOffset, p) { - const qt = component.quantizationTable, - blockData = component.blockData; - let v0, v1, v2, v3, v4, v5, v6, v7; - let p0, p1, p2, p3, p4, p5, p6, p7; - let t; - - if (!qt) { - throw new JpegError("missing required Quantization Table."); - } - - for (let row = 0; row < 64; row += 8) { - p0 = blockData[blockBufferOffset + row]; - p1 = blockData[blockBufferOffset + row + 1]; - p2 = blockData[blockBufferOffset + row + 2]; - p3 = blockData[blockBufferOffset + row + 3]; - p4 = blockData[blockBufferOffset + row + 4]; - p5 = blockData[blockBufferOffset + row + 5]; - p6 = blockData[blockBufferOffset + row + 6]; - p7 = blockData[blockBufferOffset + row + 7]; - p0 *= qt[row]; - - if ((p1 | p2 | p3 | p4 | p5 | p6 | p7) === 0) { - t = dctSqrt2 * p0 + 512 >> 10; - p[row] = t; - p[row + 1] = t; - p[row + 2] = t; - p[row + 3] = t; - p[row + 4] = t; - p[row + 5] = t; - p[row + 6] = t; - p[row + 7] = t; - continue; - } - - p1 *= qt[row + 1]; - p2 *= qt[row + 2]; - p3 *= qt[row + 3]; - p4 *= qt[row + 4]; - p5 *= qt[row + 5]; - p6 *= qt[row + 6]; - p7 *= qt[row + 7]; - v0 = dctSqrt2 * p0 + 128 >> 8; - v1 = dctSqrt2 * p4 + 128 >> 8; - v2 = p2; - v3 = p6; - v4 = dctSqrt1d2 * (p1 - p7) + 128 >> 8; - v7 = dctSqrt1d2 * (p1 + p7) + 128 >> 8; - v5 = p3 << 4; - v6 = p5 << 4; - v0 = v0 + v1 + 1 >> 1; - v1 = v0 - v1; - t = v2 * dctSin6 + v3 * dctCos6 + 128 >> 8; - v2 = v2 * dctCos6 - v3 * dctSin6 + 128 >> 8; - v3 = t; - v4 = v4 + v6 + 1 >> 1; - v6 = v4 - v6; - v7 = v7 + v5 + 1 >> 1; - v5 = v7 - v5; - v0 = v0 + v3 + 1 >> 1; - v3 = v0 - v3; - v1 = v1 + v2 + 1 >> 1; - v2 = v1 - v2; - t = v4 * dctSin3 + v7 * dctCos3 + 2048 >> 12; - v4 = v4 * dctCos3 - v7 * dctSin3 + 2048 >> 12; - v7 = t; - t = v5 * dctSin1 + v6 * dctCos1 + 2048 >> 12; - v5 = v5 * dctCos1 - v6 * dctSin1 + 2048 >> 12; - v6 = t; - p[row] = v0 + v7; - p[row + 7] = v0 - v7; - p[row + 1] = v1 + v6; - p[row + 6] = v1 - v6; - p[row + 2] = v2 + v5; - p[row + 5] = v2 - v5; - p[row + 3] = v3 + v4; - p[row + 4] = v3 - v4; - } - - for (let col = 0; col < 8; ++col) { - p0 = p[col]; - p1 = p[col + 8]; - p2 = p[col + 16]; - p3 = p[col + 24]; - p4 = p[col + 32]; - p5 = p[col + 40]; - p6 = p[col + 48]; - p7 = p[col + 56]; - - if ((p1 | p2 | p3 | p4 | p5 | p6 | p7) === 0) { - t = dctSqrt2 * p0 + 8192 >> 14; - - if (t < -2040) { - t = 0; - } else if (t >= 2024) { - t = 255; - } else { - t = t + 2056 >> 4; - } - - blockData[blockBufferOffset + col] = t; - blockData[blockBufferOffset + col + 8] = t; - blockData[blockBufferOffset + col + 16] = t; - blockData[blockBufferOffset + col + 24] = t; - blockData[blockBufferOffset + col + 32] = t; - blockData[blockBufferOffset + col + 40] = t; - blockData[blockBufferOffset + col + 48] = t; - blockData[blockBufferOffset + col + 56] = t; - continue; - } - - v0 = dctSqrt2 * p0 + 2048 >> 12; - v1 = dctSqrt2 * p4 + 2048 >> 12; - v2 = p2; - v3 = p6; - v4 = dctSqrt1d2 * (p1 - p7) + 2048 >> 12; - v7 = dctSqrt1d2 * (p1 + p7) + 2048 >> 12; - v5 = p3; - v6 = p5; - v0 = (v0 + v1 + 1 >> 1) + 4112; - v1 = v0 - v1; - t = v2 * dctSin6 + v3 * dctCos6 + 2048 >> 12; - v2 = v2 * dctCos6 - v3 * dctSin6 + 2048 >> 12; - v3 = t; - v4 = v4 + v6 + 1 >> 1; - v6 = v4 - v6; - v7 = v7 + v5 + 1 >> 1; - v5 = v7 - v5; - v0 = v0 + v3 + 1 >> 1; - v3 = v0 - v3; - v1 = v1 + v2 + 1 >> 1; - v2 = v1 - v2; - t = v4 * dctSin3 + v7 * dctCos3 + 2048 >> 12; - v4 = v4 * dctCos3 - v7 * dctSin3 + 2048 >> 12; - v7 = t; - t = v5 * dctSin1 + v6 * dctCos1 + 2048 >> 12; - v5 = v5 * dctCos1 - v6 * dctSin1 + 2048 >> 12; - v6 = t; - p0 = v0 + v7; - p7 = v0 - v7; - p1 = v1 + v6; - p6 = v1 - v6; - p2 = v2 + v5; - p5 = v2 - v5; - p3 = v3 + v4; - p4 = v3 - v4; - - if (p0 < 16) { - p0 = 0; - } else if (p0 >= 4080) { - p0 = 255; - } else { - p0 >>= 4; - } - - if (p1 < 16) { - p1 = 0; - } else if (p1 >= 4080) { - p1 = 255; - } else { - p1 >>= 4; - } - - if (p2 < 16) { - p2 = 0; - } else if (p2 >= 4080) { - p2 = 255; - } else { - p2 >>= 4; - } - - if (p3 < 16) { - p3 = 0; - } else if (p3 >= 4080) { - p3 = 255; - } else { - p3 >>= 4; - } - - if (p4 < 16) { - p4 = 0; - } else if (p4 >= 4080) { - p4 = 255; - } else { - p4 >>= 4; - } - - if (p5 < 16) { - p5 = 0; - } else if (p5 >= 4080) { - p5 = 255; - } else { - p5 >>= 4; - } - - if (p6 < 16) { - p6 = 0; - } else if (p6 >= 4080) { - p6 = 255; - } else { - p6 >>= 4; - } - - if (p7 < 16) { - p7 = 0; - } else if (p7 >= 4080) { - p7 = 255; - } else { - p7 >>= 4; - } - - blockData[blockBufferOffset + col] = p0; - blockData[blockBufferOffset + col + 8] = p1; - blockData[blockBufferOffset + col + 16] = p2; - blockData[blockBufferOffset + col + 24] = p3; - blockData[blockBufferOffset + col + 32] = p4; - blockData[blockBufferOffset + col + 40] = p5; - blockData[blockBufferOffset + col + 48] = p6; - blockData[blockBufferOffset + col + 56] = p7; - } -} - -function buildComponentData(frame, component) { - const blocksPerLine = component.blocksPerLine; - const blocksPerColumn = component.blocksPerColumn; - const computationBuffer = new Int16Array(64); - - for (let blockRow = 0; blockRow < blocksPerColumn; blockRow++) { - for (let blockCol = 0; blockCol < blocksPerLine; blockCol++) { - const offset = getBlockBufferOffset(component, blockRow, blockCol); - quantizeAndInverse(component, offset, computationBuffer); - } - } - - return component.blockData; -} - -function findNextFileMarker(data, currentPos, startPos = currentPos) { - const maxPos = data.length - 1; - let newPos = startPos < currentPos ? startPos : currentPos; - - if (currentPos >= maxPos) { - return null; - } - - const currentMarker = (0, _core_utils.readUint16)(data, currentPos); - - if (currentMarker >= 0xffc0 && currentMarker <= 0xfffe) { - return { - invalid: null, - marker: currentMarker, - offset: currentPos - }; - } - - let newMarker = (0, _core_utils.readUint16)(data, newPos); - - while (!(newMarker >= 0xffc0 && newMarker <= 0xfffe)) { - if (++newPos >= maxPos) { - return null; - } - - newMarker = (0, _core_utils.readUint16)(data, newPos); - } - - return { - invalid: currentMarker.toString(16), - marker: newMarker, - offset: newPos - }; -} - -class JpegImage { - constructor({ - decodeTransform = null, - colorTransform = -1 - } = {}) { - this._decodeTransform = decodeTransform; - this._colorTransform = colorTransform; - } - - parse(data, { - dnlScanLines = null - } = {}) { - function readDataBlock() { - const length = (0, _core_utils.readUint16)(data, offset); - offset += 2; - let endOffset = offset + length - 2; - const fileMarker = findNextFileMarker(data, endOffset, offset); - - if (fileMarker && fileMarker.invalid) { - (0, _util.warn)("readDataBlock - incorrect length, current marker is: " + fileMarker.invalid); - endOffset = fileMarker.offset; - } - - const array = data.subarray(offset, endOffset); - offset += array.length; - return array; - } - - function prepareComponents(frame) { - const mcusPerLine = Math.ceil(frame.samplesPerLine / 8 / frame.maxH); - const mcusPerColumn = Math.ceil(frame.scanLines / 8 / frame.maxV); - - for (let i = 0, ii = frame.components.length; i < ii; i++) { - const component = frame.components[i]; - const blocksPerLine = Math.ceil(Math.ceil(frame.samplesPerLine / 8) * component.h / frame.maxH); - const blocksPerColumn = Math.ceil(Math.ceil(frame.scanLines / 8) * component.v / frame.maxV); - const blocksPerLineForMcu = mcusPerLine * component.h; - const blocksPerColumnForMcu = mcusPerColumn * component.v; - const blocksBufferSize = 64 * blocksPerColumnForMcu * (blocksPerLineForMcu + 1); - component.blockData = new Int16Array(blocksBufferSize); - component.blocksPerLine = blocksPerLine; - component.blocksPerColumn = blocksPerColumn; - } - - frame.mcusPerLine = mcusPerLine; - frame.mcusPerColumn = mcusPerColumn; - } - - let offset = 0; - let jfif = null; - let adobe = null; - let frame, resetInterval; - let numSOSMarkers = 0; - const quantizationTables = []; - const huffmanTablesAC = [], - huffmanTablesDC = []; - let fileMarker = (0, _core_utils.readUint16)(data, offset); - offset += 2; - - if (fileMarker !== 0xffd8) { - throw new JpegError("SOI not found"); - } - - fileMarker = (0, _core_utils.readUint16)(data, offset); - offset += 2; - - markerLoop: while (fileMarker !== 0xffd9) { - let i, j, l; - - switch (fileMarker) { - case 0xffe0: - case 0xffe1: - case 0xffe2: - case 0xffe3: - case 0xffe4: - case 0xffe5: - case 0xffe6: - case 0xffe7: - case 0xffe8: - case 0xffe9: - case 0xffea: - case 0xffeb: - case 0xffec: - case 0xffed: - case 0xffee: - case 0xffef: - case 0xfffe: - const appData = readDataBlock(); - - if (fileMarker === 0xffe0) { - if (appData[0] === 0x4a && appData[1] === 0x46 && appData[2] === 0x49 && appData[3] === 0x46 && appData[4] === 0) { - 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]) - }; - } - } - - if (fileMarker === 0xffee) { - if (appData[0] === 0x41 && appData[1] === 0x64 && appData[2] === 0x6f && appData[3] === 0x62 && appData[4] === 0x65) { - adobe = { - version: appData[5] << 8 | appData[6], - flags0: appData[7] << 8 | appData[8], - flags1: appData[9] << 8 | appData[10], - transformCode: appData[11] - }; - } - } - - break; - - case 0xffdb: - const quantizationTablesLength = (0, _core_utils.readUint16)(data, offset); - offset += 2; - const quantizationTablesEnd = quantizationTablesLength + offset - 2; - let z; - - while (offset < quantizationTablesEnd) { - const quantizationTableSpec = data[offset++]; - const tableData = new Uint16Array(64); - - if (quantizationTableSpec >> 4 === 0) { - for (j = 0; j < 64; j++) { - z = dctZigZag[j]; - tableData[z] = data[offset++]; - } - } else if (quantizationTableSpec >> 4 === 1) { - for (j = 0; j < 64; j++) { - z = dctZigZag[j]; - tableData[z] = (0, _core_utils.readUint16)(data, offset); - offset += 2; - } - } else { - throw new JpegError("DQT - invalid table spec"); - } - - quantizationTables[quantizationTableSpec & 15] = tableData; - } - - break; - - case 0xffc0: - case 0xffc1: - case 0xffc2: - if (frame) { - throw new JpegError("Only single frame JPEGs supported"); - } - - offset += 2; - frame = {}; - frame.extended = fileMarker === 0xffc1; - frame.progressive = fileMarker === 0xffc2; - frame.precision = data[offset++]; - const sofScanLines = (0, _core_utils.readUint16)(data, offset); - offset += 2; - frame.scanLines = dnlScanLines || sofScanLines; - frame.samplesPerLine = (0, _core_utils.readUint16)(data, offset); - offset += 2; - frame.components = []; - frame.componentIds = {}; - const componentsCount = data[offset++]; - let maxH = 0, - maxV = 0; - - for (i = 0; i < componentsCount; i++) { - const componentId = data[offset]; - const h = data[offset + 1] >> 4; - const v = data[offset + 1] & 15; - - if (maxH < h) { - maxH = h; - } - - if (maxV < v) { - maxV = v; - } - - const qId = data[offset + 2]; - l = frame.components.push({ - h, - v, - quantizationId: qId, - quantizationTable: null - }); - frame.componentIds[componentId] = l - 1; - offset += 3; - } - - frame.maxH = maxH; - frame.maxV = maxV; - prepareComponents(frame); - break; - - case 0xffc4: - const huffmanLength = (0, _core_utils.readUint16)(data, offset); - offset += 2; - - for (i = 2; i < huffmanLength;) { - const huffmanTableSpec = data[offset++]; - const codeLengths = new Uint8Array(16); - let codeLengthSum = 0; - - for (j = 0; j < 16; j++, offset++) { - codeLengthSum += codeLengths[j] = data[offset]; - } - - const 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: - offset += 2; - resetInterval = (0, _core_utils.readUint16)(data, offset); - offset += 2; - break; - - case 0xffda: - const parseDNLMarker = ++numSOSMarkers === 1 && !dnlScanLines; - offset += 2; - const selectorsCount = data[offset++], - components = []; - - for (i = 0; i < selectorsCount; i++) { - const index = data[offset++]; - const componentIndex = frame.componentIds[index]; - const component = frame.components[componentIndex]; - component.index = index; - const tableSpec = data[offset++]; - component.huffmanTableDC = huffmanTablesDC[tableSpec >> 4]; - component.huffmanTableAC = huffmanTablesAC[tableSpec & 15]; - components.push(component); - } - - const spectralStart = data[offset++], - spectralEnd = data[offset++], - successiveApproximation = data[offset++]; - - try { - const processed = decodeScan(data, offset, frame, components, resetInterval, spectralStart, spectralEnd, successiveApproximation >> 4, successiveApproximation & 15, parseDNLMarker); - offset += processed; - } catch (ex) { - if (ex instanceof DNLMarkerError) { - (0, _util.warn)(`${ex.message} -- attempting to re-parse the JPEG image.`); - return this.parse(data, { - dnlScanLines: ex.scanLines - }); - } else if (ex instanceof EOIMarkerError) { - (0, _util.warn)(`${ex.message} -- ignoring the rest of the image data.`); - break markerLoop; - } - - throw ex; - } - - break; - - case 0xffdc: - offset += 4; - break; - - case 0xffff: - if (data[offset] !== 0xff) { - offset--; - } - - break; - - default: - const nextFileMarker = findNextFileMarker(data, offset - 2, offset - 3); - - if (nextFileMarker && nextFileMarker.invalid) { - (0, _util.warn)("JpegImage.parse - unexpected data, current marker is: " + nextFileMarker.invalid); - offset = nextFileMarker.offset; - break; - } - - if (!nextFileMarker || offset >= data.length - 1) { - (0, _util.warn)("JpegImage.parse - reached the end of the image data " + "without finding an EOI marker (0xFFD9)."); - break markerLoop; - } - - throw new JpegError("JpegImage.parse - unknown marker: " + fileMarker.toString(16)); - } - - fileMarker = (0, _core_utils.readUint16)(data, offset); - offset += 2; - } - - this.width = frame.samplesPerLine; - this.height = frame.scanLines; - this.jfif = jfif; - this.adobe = adobe; - this.components = []; - - for (let i = 0, ii = frame.components.length; i < ii; i++) { - const component = frame.components[i]; - const quantizationTable = quantizationTables[component.quantizationId]; - - if (quantizationTable) { - component.quantizationTable = quantizationTable; - } - - this.components.push({ - index: component.index, - output: buildComponentData(frame, component), - scaleX: component.h / frame.maxH, - scaleY: component.v / frame.maxV, - blocksPerLine: component.blocksPerLine, - blocksPerColumn: component.blocksPerColumn - }); - } - - this.numComponents = this.components.length; - return undefined; - } - - _getLinearizedBlockData(width, height, isSourcePDF = false) { - const scaleX = this.width / width, - scaleY = this.height / height; - let component, componentScaleX, componentScaleY, blocksPerScanline; - let x, y, i, j, k; - let index; - let offset = 0; - let output; - const numComponents = this.components.length; - const dataLength = width * height * numComponents; - const data = new Uint8ClampedArray(dataLength); - const xScaleBlockOffset = new Uint32Array(width); - const mask3LSB = 0xfffffff8; - let lastComponentScaleX; - - for (i = 0; i < numComponents; i++) { - component = this.components[i]; - componentScaleX = component.scaleX * scaleX; - componentScaleY = component.scaleY * scaleY; - offset = i; - output = component.output; - blocksPerScanline = component.blocksPerLine + 1 << 3; - - if (componentScaleX !== lastComponentScaleX) { - for (x = 0; x < width; x++) { - j = 0 | x * componentScaleX; - xScaleBlockOffset[x] = (j & mask3LSB) << 3 | j & 7; - } - - lastComponentScaleX = componentScaleX; - } - - for (y = 0; y < height; y++) { - j = 0 | y * componentScaleY; - index = blocksPerScanline * (j & mask3LSB) | (j & 7) << 3; - - for (x = 0; x < width; x++) { - data[offset] = output[index + xScaleBlockOffset[x]]; - offset += numComponents; - } - } - } - - let transform = this._decodeTransform; - - if (!isSourcePDF && numComponents === 4 && !transform) { - transform = new Int32Array([-256, 255, -256, 255, -256, 255, -256, 255]); - } - - if (transform) { - for (i = 0; i < dataLength;) { - for (j = 0, k = 0; j < numComponents; j++, i++, k += 2) { - data[i] = (data[i] * transform[k] >> 8) + transform[k + 1]; - } - } - } - - return data; - } - - get _isColorConversionNeeded() { - if (this.adobe) { - return !!this.adobe.transformCode; - } - - if (this.numComponents === 3) { - if (this._colorTransform === 0) { - return false; - } else if (this.components[0].index === 0x52 && this.components[1].index === 0x47 && this.components[2].index === 0x42) { - return false; - } - - return true; - } - - if (this._colorTransform === 1) { - return true; - } - - return false; - } - - _convertYccToRgb(data) { - let Y, Cb, Cr; - - for (let i = 0, length = data.length; i < length; i += 3) { - Y = data[i]; - Cb = data[i + 1]; - Cr = data[i + 2]; - data[i] = Y - 179.456 + 1.402 * Cr; - data[i + 1] = Y + 135.459 - 0.344 * Cb - 0.714 * Cr; - data[i + 2] = Y - 226.816 + 1.772 * Cb; - } - - return data; - } - - _convertYcckToRgb(data) { - let Y, Cb, Cr, k; - let offset = 0; - - for (let i = 0, length = data.length; i < length; i += 4) { - Y = data[i]; - Cb = data[i + 1]; - Cr = data[i + 2]; - k = data[i + 3]; - data[offset++] = -122.67195406894 + Cb * (-6.60635669420364e-5 * Cb + 0.000437130475926232 * Cr - 5.4080610064599e-5 * Y + 0.00048449797120281 * k - 0.154362151871126) + Cr * (-0.000957964378445773 * Cr + 0.000817076911346625 * Y - 0.00477271405408747 * k + 1.53380253221734) + Y * (0.000961250184130688 * Y - 0.00266257332283933 * k + 0.48357088451265) + k * (-0.000336197177618394 * k + 0.484791561490776); - data[offset++] = 107.268039397724 + Cb * (2.19927104525741e-5 * Cb - 0.000640992018297945 * Cr + 0.000659397001245577 * Y + 0.000426105652938837 * k - 0.176491792462875) + Cr * (-0.000778269941513683 * Cr + 0.00130872261408275 * Y + 0.000770482631801132 * k - 0.151051492775562) + Y * (0.00126935368114843 * Y - 0.00265090189010898 * k + 0.25802910206845) + k * (-0.000318913117588328 * k - 0.213742400323665); - data[offset++] = -20.810012546947 + Cb * (-0.000570115196973677 * Cb - 2.63409051004589e-5 * Cr + 0.0020741088115012 * Y - 0.00288260236853442 * k + 0.814272968359295) + Cr * (-1.53496057440975e-5 * Cr - 0.000132689043961446 * Y + 0.000560833691242812 * k - 0.195152027534049) + Y * (0.00174418132927582 * Y - 0.00255243321439347 * k + 0.116935020465145) + k * (-0.000343531996510555 * k + 0.24165260232407); - } - - return data.subarray(0, offset); - } - - _convertYcckToCmyk(data) { - let Y, Cb, Cr; - - for (let i = 0, length = data.length; i < length; i += 4) { - Y = data[i]; - Cb = data[i + 1]; - Cr = data[i + 2]; - data[i] = 434.456 - Y - 1.402 * Cr; - data[i + 1] = 119.541 - Y + 0.344 * Cb + 0.714 * Cr; - data[i + 2] = 481.816 - Y - 1.772 * Cb; - } - - return data; - } - - _convertCmykToRgb(data) { - let c, m, y, k; - let offset = 0; - - for (let i = 0, length = data.length; i < length; i += 4) { - c = data[i]; - m = data[i + 1]; - y = data[i + 2]; - k = data[i + 3]; - data[offset++] = 255 + c * (-0.00006747147073602441 * c + 0.0008379262121013727 * m + 0.0002894718188643294 * y + 0.003264231057537806 * k - 1.1185611867203937) + m * (0.000026374107616089405 * m - 0.00008626949158638572 * y - 0.0002748769067499491 * k - 0.02155688794978967) + y * (-0.00003878099212869363 * y - 0.0003267808279485286 * k + 0.0686742238595345) - k * (0.0003361971776183937 * k + 0.7430659151342254); - data[offset++] = 255 + c * (0.00013596372813588848 * c + 0.000924537132573585 * m + 0.00010567359618683593 * y + 0.0004791864687436512 * k - 0.3109689587515875) + m * (-0.00023545346108370344 * m + 0.0002702845253534714 * y + 0.0020200308977307156 * k - 0.7488052167015494) + y * (0.00006834815998235662 * y + 0.00015168452363460973 * k - 0.09751927774728933) - k * (0.0003189131175883281 * k + 0.7364883807733168); - data[offset++] = 255 + c * (0.000013598650411385307 * c + 0.00012423956175490851 * m + 0.0004751985097583589 * y - 0.0000036729317476630422 * k - 0.05562186980264034) + m * (0.00016141380598724676 * m + 0.0009692239130725186 * y + 0.0007782692450036253 * k - 0.44015232367526463) + y * (5.068882914068769e-7 * y + 0.0017778369011375071 * k - 0.7591454649749609) - k * (0.0003435319965105553 * k + 0.7063770186160144); - } - - return data.subarray(0, offset); - } - - getData({ - width, - height, - forceRGB = false, - isSourcePDF = false - }) { - if (this.numComponents > 4) { - throw new JpegError("Unsupported color mode"); - } - - const data = this._getLinearizedBlockData(width, height, isSourcePDF); - - if (this.numComponents === 1 && forceRGB) { - const dataLength = data.length; - const rgbData = new Uint8ClampedArray(dataLength * 3); - let offset = 0; - - for (let i = 0; i < dataLength; i++) { - const grayColor = data[i]; - rgbData[offset++] = grayColor; - rgbData[offset++] = grayColor; - rgbData[offset++] = grayColor; - } - - return rgbData; - } else if (this.numComponents === 3 && this._isColorConversionNeeded) { - return this._convertYccToRgb(data); - } else if (this.numComponents === 4) { - if (this._isColorConversionNeeded) { - if (forceRGB) { - return this._convertYcckToRgb(data); - } - - return this._convertYcckToCmyk(data); - } else if (forceRGB) { - return this._convertCmykToRgb(data); - } - } - - return data; - } - -} - -exports.JpegImage = JpegImage; - -/***/ }), -/* 39 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.JpxStream = void 0; - -var _decode_stream = __w_pdfjs_require__(29); - -var _jpx = __w_pdfjs_require__(40); - -var _util = __w_pdfjs_require__(2); - -class JpxStream extends _decode_stream.DecodeStream { - constructor(stream, maybeLength, params) { - super(maybeLength); - this.stream = stream; - this.dict = stream.dict; - this.maybeLength = maybeLength; - this.params = params; - } - - get bytes() { - return (0, _util.shadow)(this, "bytes", this.stream.getBytes(this.maybeLength)); - } - - ensureBuffer(requested) {} - - readBlock() { - if (this.eof) { - return; - } - - const jpxImage = new _jpx.JpxImage(); - jpxImage.parse(this.bytes); - const width = jpxImage.width; - const height = jpxImage.height; - const componentsCount = jpxImage.componentsCount; - const tileCount = jpxImage.tiles.length; - - if (tileCount === 1) { - this.buffer = jpxImage.tiles[0].items; - } else { - const data = new Uint8ClampedArray(width * height * componentsCount); - - for (let k = 0; k < tileCount; k++) { - const tileComponents = jpxImage.tiles[k]; - const tileWidth = tileComponents.width; - const tileHeight = tileComponents.height; - const tileLeft = tileComponents.left; - const tileTop = tileComponents.top; - const src = tileComponents.items; - let srcPosition = 0; - let dataPosition = (width * tileTop + tileLeft) * componentsCount; - const imgRowSize = width * componentsCount; - const tileRowSize = tileWidth * componentsCount; - - for (let j = 0; j < tileHeight; j++) { - const rowBytes = src.subarray(srcPosition, srcPosition + tileRowSize); - data.set(rowBytes, dataPosition); - srcPosition += tileRowSize; - dataPosition += imgRowSize; - } - } - - this.buffer = data; - } - - this.bufferLength = this.buffer.length; - this.eof = true; - } - -} - -exports.JpxStream = JpxStream; - -/***/ }), -/* 40 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.JpxImage = void 0; - -var _util = __w_pdfjs_require__(2); - -var _core_utils = __w_pdfjs_require__(9); - -var _arithmetic_decoder = __w_pdfjs_require__(36); - -class JpxError extends _util.BaseException { - constructor(msg) { - super(`JPX error: ${msg}`, "JpxError"); - } - -} - -const SubbandsGainLog2 = { - LL: 0, - LH: 1, - HL: 1, - HH: 2 -}; - -class JpxImage { - constructor() { - this.failOnCorruptedImage = false; - } - - parse(data) { - const head = (0, _core_utils.readUint16)(data, 0); - - if (head === 0xff4f) { - this.parseCodestream(data, 0, data.length); - return; - } - - const length = data.length; - let position = 0; - - while (position < length) { - let headerSize = 8; - let lbox = (0, _core_utils.readUint32)(data, position); - const tbox = (0, _core_utils.readUint32)(data, position + 4); - position += headerSize; - - if (lbox === 1) { - lbox = (0, _core_utils.readUint32)(data, position) * 4294967296 + (0, _core_utils.readUint32)(data, position + 4); - position += 8; - headerSize += 8; - } - - if (lbox === 0) { - lbox = length - position + headerSize; - } - - if (lbox < headerSize) { - throw new JpxError("Invalid box field size"); - } - - const dataLength = lbox - headerSize; - let jumpDataLength = true; - - switch (tbox) { - case 0x6a703268: - jumpDataLength = false; - break; - - case 0x636f6c72: - const method = data[position]; - - if (method === 1) { - const colorspace = (0, _core_utils.readUint32)(data, position + 3); - - switch (colorspace) { - case 16: - case 17: - case 18: - break; - - default: - (0, _util.warn)("Unknown colorspace " + colorspace); - break; - } - } else if (method === 2) { - (0, _util.info)("ICC profile not supported"); - } - - break; - - case 0x6a703263: - this.parseCodestream(data, position, position + dataLength); - break; - - case 0x6a502020: - if ((0, _core_utils.readUint32)(data, position) !== 0x0d0a870a) { - (0, _util.warn)("Invalid JP2 signature"); - } - - break; - - case 0x6a501a1a: - case 0x66747970: - case 0x72726571: - case 0x72657320: - case 0x69686472: - break; - - default: - const headerType = String.fromCharCode(tbox >> 24 & 0xff, tbox >> 16 & 0xff, tbox >> 8 & 0xff, tbox & 0xff); - (0, _util.warn)(`Unsupported header type ${tbox} (${headerType}).`); - break; - } - - if (jumpDataLength) { - position += dataLength; - } - } - } - - parseImageProperties(stream) { - let newByte = stream.getByte(); - - while (newByte >= 0) { - const oldByte = newByte; - newByte = stream.getByte(); - const code = oldByte << 8 | newByte; - - if (code === 0xff51) { - stream.skip(4); - const Xsiz = stream.getInt32() >>> 0; - const Ysiz = stream.getInt32() >>> 0; - const XOsiz = stream.getInt32() >>> 0; - const YOsiz = stream.getInt32() >>> 0; - stream.skip(16); - const Csiz = stream.getUint16(); - this.width = Xsiz - XOsiz; - this.height = Ysiz - YOsiz; - this.componentsCount = Csiz; - this.bitsPerComponent = 8; - return; - } - } - - throw new JpxError("No size marker found in JPX stream"); - } - - parseCodestream(data, start, end) { - const context = {}; - let doNotRecover = false; - - try { - let position = start; - - while (position + 1 < end) { - const code = (0, _core_utils.readUint16)(data, position); - position += 2; - let length = 0, - j, - sqcd, - spqcds, - spqcdSize, - scalarExpounded, - tile; - - switch (code) { - case 0xff4f: - context.mainHeader = true; - break; - - case 0xffd9: - break; - - case 0xff51: - length = (0, _core_utils.readUint16)(data, position); - const siz = {}; - siz.Xsiz = (0, _core_utils.readUint32)(data, position + 4); - siz.Ysiz = (0, _core_utils.readUint32)(data, position + 8); - siz.XOsiz = (0, _core_utils.readUint32)(data, position + 12); - siz.YOsiz = (0, _core_utils.readUint32)(data, position + 16); - siz.XTsiz = (0, _core_utils.readUint32)(data, position + 20); - siz.YTsiz = (0, _core_utils.readUint32)(data, position + 24); - siz.XTOsiz = (0, _core_utils.readUint32)(data, position + 28); - siz.YTOsiz = (0, _core_utils.readUint32)(data, position + 32); - const componentsCount = (0, _core_utils.readUint16)(data, position + 36); - siz.Csiz = componentsCount; - const components = []; - j = position + 38; - - for (let i = 0; i < componentsCount; i++) { - const component = { - precision: (data[j] & 0x7f) + 1, - isSigned: !!(data[j] & 0x80), - XRsiz: data[j + 1], - YRsiz: data[j + 2] - }; - j += 3; - calculateComponentDimensions(component, siz); - components.push(component); - } - - context.SIZ = siz; - context.components = components; - calculateTileGrids(context, components); - context.QCC = []; - context.COC = []; - break; - - case 0xff5c: - length = (0, _core_utils.readUint16)(data, position); - const qcd = {}; - j = position + 2; - sqcd = data[j++]; - - switch (sqcd & 0x1f) { - case 0: - spqcdSize = 8; - scalarExpounded = true; - break; - - case 1: - spqcdSize = 16; - scalarExpounded = false; - break; - - case 2: - spqcdSize = 16; - scalarExpounded = true; - break; - - default: - throw new Error("Invalid SQcd value " + sqcd); - } - - qcd.noQuantization = spqcdSize === 8; - qcd.scalarExpounded = scalarExpounded; - qcd.guardBits = sqcd >> 5; - spqcds = []; - - while (j < length + position) { - const 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: - length = (0, _core_utils.readUint16)(data, position); - const qcc = {}; - j = position + 2; - let cqcc; - - if (context.SIZ.Csiz < 257) { - cqcc = data[j++]; - } else { - cqcc = (0, _core_utils.readUint16)(data, j); - j += 2; - } - - sqcd = data[j++]; - - switch (sqcd & 0x1f) { - case 0: - spqcdSize = 8; - scalarExpounded = true; - break; - - case 1: - spqcdSize = 16; - scalarExpounded = false; - break; - - case 2: - spqcdSize = 16; - scalarExpounded = true; - break; - - default: - throw new Error("Invalid SQcd value " + sqcd); - } - - qcc.noQuantization = spqcdSize === 8; - qcc.scalarExpounded = scalarExpounded; - qcc.guardBits = sqcd >> 5; - spqcds = []; - - while (j < length + position) { - const 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: - length = (0, _core_utils.readUint16)(data, position); - const cod = {}; - j = position + 2; - const scod = data[j++]; - cod.entropyCoderWithCustomPrecincts = !!(scod & 1); - cod.sopMarkerUsed = !!(scod & 2); - cod.ephMarkerUsed = !!(scod & 4); - cod.progressionOrder = data[j++]; - cod.layersCount = (0, _core_utils.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; - const blockStyle = data[j++]; - cod.selectiveArithmeticCodingBypass = !!(blockStyle & 1); - cod.resetContextProbabilities = !!(blockStyle & 2); - cod.terminationOnEachCodingPass = !!(blockStyle & 4); - cod.verticallyStripe = !!(blockStyle & 8); - cod.predictableTermination = !!(blockStyle & 16); - cod.segmentationSymbolUsed = !!(blockStyle & 32); - cod.reversibleTransformation = data[j++]; - - if (cod.entropyCoderWithCustomPrecincts) { - const precinctsSizes = []; - - while (j < length + position) { - const precinctsSize = data[j++]; - precinctsSizes.push({ - PPx: precinctsSize & 0xf, - PPy: precinctsSize >> 4 - }); - } - - cod.precinctsSizes = precinctsSizes; - } - - const unsupported = []; - - if (cod.selectiveArithmeticCodingBypass) { - unsupported.push("selectiveArithmeticCodingBypass"); - } - - if (cod.resetContextProbabilities) { - unsupported.push("resetContextProbabilities"); - } - - if (cod.terminationOnEachCodingPass) { - unsupported.push("terminationOnEachCodingPass"); - } - - if (cod.verticallyStripe) { - unsupported.push("verticallyStripe"); - } - - if (cod.predictableTermination) { - unsupported.push("predictableTermination"); - } - - if (unsupported.length > 0) { - doNotRecover = true; - (0, _util.warn)(`JPX: Unsupported COD options (${unsupported.join(", ")}).`); - } - - if (context.mainHeader) { - context.COD = cod; - } else { - context.currentTile.COD = cod; - context.currentTile.COC = []; - } - - break; - - case 0xff90: - length = (0, _core_utils.readUint16)(data, position); - tile = {}; - tile.index = (0, _core_utils.readUint16)(data, position + 2); - tile.length = (0, _core_utils.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) { - tile.COD = context.COD; - tile.COC = context.COC.slice(0); - tile.QCD = context.QCD; - tile.QCC = context.QCC.slice(0); - } - - context.currentTile = tile; - break; - - case 0xff93: - tile = context.currentTile; - - if (tile.partIndex === 0) { - initializeTile(context, tile.index); - buildPackets(context); - } - - length = tile.dataEnd - position; - parseTilePackets(context, data, position, length); - break; - - case 0xff53: - (0, _util.warn)("JPX: Codestream code 0xFF53 (COC) is not implemented."); - - case 0xff55: - case 0xff57: - case 0xff58: - case 0xff64: - length = (0, _core_utils.readUint16)(data, position); - break; - - default: - throw new Error("Unknown codestream code: " + code.toString(16)); - } - - position += length; - } - } catch (e) { - if (doNotRecover || this.failOnCorruptedImage) { - throw new JpxError(e.message); - } else { - (0, _util.warn)(`JPX: Trying to recover from: "${e.message}".`); - } - } - - this.tiles = transformComponents(context); - this.width = context.SIZ.Xsiz - context.SIZ.XOsiz; - this.height = context.SIZ.Ysiz - context.SIZ.YOsiz; - this.componentsCount = context.SIZ.Csiz; - } - -} - -exports.JpxImage = JpxImage; - -function calculateComponentDimensions(component, siz) { - 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) { - const siz = context.SIZ; - const tiles = []; - let tile; - const numXtiles = Math.ceil((siz.Xsiz - siz.XTOsiz) / siz.XTsiz); - const numYtiles = Math.ceil((siz.Ysiz - siz.YTOsiz) / siz.YTsiz); - - for (let q = 0; q < numYtiles; q++) { - for (let p = 0; p < numXtiles; p++) { - tile = {}; - tile.tx0 = Math.max(siz.XTOsiz + p * siz.XTsiz, siz.XOsiz); - tile.ty0 = Math.max(siz.YTOsiz + q * siz.YTsiz, siz.YOsiz); - tile.tx1 = Math.min(siz.XTOsiz + (p + 1) * siz.XTsiz, siz.Xsiz); - tile.ty1 = Math.min(siz.YTOsiz + (q + 1) * siz.YTsiz, siz.Ysiz); - tile.width = tile.tx1 - tile.tx0; - tile.height = tile.ty1 - tile.ty0; - tile.components = []; - tiles.push(tile); - } - } - - context.tiles = tiles; - const componentsCount = siz.Csiz; - - for (let i = 0, ii = componentsCount; i < ii; i++) { - const component = components[i]; - - for (let j = 0, jj = tiles.length; j < jj; j++) { - const 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) { - const codOrCoc = component.codingStyleParameters; - const result = {}; - - if (!codOrCoc.entropyCoderWithCustomPrecincts) { - result.PPx = 15; - result.PPy = 15; - } else { - result.PPx = codOrCoc.precinctsSizes[r].PPx; - result.PPy = codOrCoc.precinctsSizes[r].PPy; - } - - result.xcb_ = r > 0 ? Math.min(codOrCoc.xcb, result.PPx - 1) : Math.min(codOrCoc.xcb, result.PPx); - result.ycb_ = r > 0 ? Math.min(codOrCoc.ycb, result.PPy - 1) : Math.min(codOrCoc.ycb, result.PPy); - return result; -} - -function buildPrecincts(context, resolution, dimensions) { - const precinctWidth = 1 << dimensions.PPx; - const precinctHeight = 1 << dimensions.PPy; - const isZeroRes = resolution.resLevel === 0; - const precinctWidthInSubband = 1 << dimensions.PPx + (isZeroRes ? 0 : -1); - const precinctHeightInSubband = 1 << dimensions.PPy + (isZeroRes ? 0 : -1); - const numprecinctswide = resolution.trx1 > resolution.trx0 ? Math.ceil(resolution.trx1 / precinctWidth) - Math.floor(resolution.trx0 / precinctWidth) : 0; - const numprecinctshigh = resolution.try1 > resolution.try0 ? Math.ceil(resolution.try1 / precinctHeight) - Math.floor(resolution.try0 / precinctHeight) : 0; - const numprecincts = numprecinctswide * numprecinctshigh; - resolution.precinctParameters = { - precinctWidth, - precinctHeight, - numprecinctswide, - numprecinctshigh, - numprecincts, - precinctWidthInSubband, - precinctHeightInSubband - }; -} - -function buildCodeblocks(context, subband, dimensions) { - const xcb_ = dimensions.xcb_; - const ycb_ = dimensions.ycb_; - const codeblockWidth = 1 << xcb_; - const codeblockHeight = 1 << ycb_; - const cbx0 = subband.tbx0 >> xcb_; - const cby0 = subband.tby0 >> ycb_; - const cbx1 = subband.tbx1 + codeblockWidth - 1 >> xcb_; - const cby1 = subband.tby1 + codeblockHeight - 1 >> ycb_; - const precinctParameters = subband.resolution.precinctParameters; - const codeblocks = []; - const precincts = []; - let i, j, codeblock, precinctNumber; - - for (j = cby0; j < cby1; j++) { - for (i = cbx0; i < cbx1; i++) { - codeblock = { - cbx: i, - cby: j, - tbx0: codeblockWidth * i, - tby0: codeblockHeight * j, - tbx1: codeblockWidth * (i + 1), - tby1: codeblockHeight * (j + 1) - }; - codeblock.tbx0_ = Math.max(subband.tbx0, codeblock.tbx0); - codeblock.tby0_ = Math.max(subband.tby0, codeblock.tby0); - codeblock.tbx1_ = Math.min(subband.tbx1, codeblock.tbx1); - codeblock.tby1_ = Math.min(subband.tby1, codeblock.tby1); - const pi = Math.floor((codeblock.tbx0_ - subband.tbx0) / precinctParameters.precinctWidthInSubband); - const pj = Math.floor((codeblock.tby0_ - subband.tby0) / precinctParameters.precinctHeightInSubband); - precinctNumber = pi + pj * precinctParameters.numprecinctswide; - codeblock.precinctNumber = precinctNumber; - codeblock.subbandType = subband.type; - codeblock.Lblock = 3; - - if (codeblock.tbx1_ <= codeblock.tbx0_ || codeblock.tby1_ <= codeblock.tby0_) { - continue; - } - - codeblocks.push(codeblock); - let precinct = precincts[precinctNumber]; - - if (precinct !== undefined) { - if (i < precinct.cbxMin) { - precinct.cbxMin = i; - } else if (i > precinct.cbxMax) { - precinct.cbxMax = i; - } - - if (j < precinct.cbyMin) { - precinct.cbxMin = j; - } else if (j > precinct.cbyMax) { - precinct.cbyMax = j; - } - } else { - precincts[precinctNumber] = precinct = { - cbxMin: i, - cbyMin: j, - cbxMax: i, - cbyMax: j - }; - } - - codeblock.precinct = precinct; - } - } - - subband.codeblockParameters = { - codeblockWidth: xcb_, - codeblockHeight: ycb_, - numcodeblockwide: cbx1 - cbx0 + 1, - numcodeblockhigh: cby1 - cby0 + 1 - }; - subband.codeblocks = codeblocks; - subband.precincts = precincts; -} - -function createPacket(resolution, precinctNumber, layerNumber) { - const precinctCodeblocks = []; - const subbands = resolution.subbands; - - for (let i = 0, ii = subbands.length; i < ii; i++) { - const subband = subbands[i]; - const codeblocks = subband.codeblocks; - - for (let j = 0, jj = codeblocks.length; j < jj; j++) { - const codeblock = codeblocks[j]; - - if (codeblock.precinctNumber !== precinctNumber) { - continue; - } - - precinctCodeblocks.push(codeblock); - } - } - - return { - layerNumber, - codeblocks: precinctCodeblocks - }; -} - -function LayerResolutionComponentPositionIterator(context) { - const siz = context.SIZ; - const tileIndex = context.currentTile.index; - const tile = context.tiles[tileIndex]; - const layersCount = tile.codingStyleDefaultParameters.layersCount; - const componentsCount = siz.Csiz; - let maxDecompositionLevelsCount = 0; - - for (let q = 0; q < componentsCount; q++) { - maxDecompositionLevelsCount = Math.max(maxDecompositionLevelsCount, tile.components[q].codingStyleParameters.decompositionLevelsCount); - } - - let l = 0, - r = 0, - i = 0, - k = 0; - - this.nextPacket = function JpxImage_nextPacket() { - for (; l < layersCount; l++) { - for (; r <= maxDecompositionLevelsCount; r++) { - for (; i < componentsCount; i++) { - const component = tile.components[i]; - - if (r > component.codingStyleParameters.decompositionLevelsCount) { - continue; - } - - const resolution = component.resolutions[r]; - const numprecincts = resolution.precinctParameters.numprecincts; - - for (; k < numprecincts;) { - const packet = createPacket(resolution, k, l); - k++; - return packet; - } - - k = 0; - } - - i = 0; - } - - r = 0; - } - - throw new JpxError("Out of packets"); - }; -} - -function ResolutionLayerComponentPositionIterator(context) { - const siz = context.SIZ; - const tileIndex = context.currentTile.index; - const tile = context.tiles[tileIndex]; - const layersCount = tile.codingStyleDefaultParameters.layersCount; - const componentsCount = siz.Csiz; - let maxDecompositionLevelsCount = 0; - - for (let q = 0; q < componentsCount; q++) { - maxDecompositionLevelsCount = Math.max(maxDecompositionLevelsCount, tile.components[q].codingStyleParameters.decompositionLevelsCount); - } - - let r = 0, - l = 0, - i = 0, - k = 0; - - this.nextPacket = function JpxImage_nextPacket() { - for (; r <= maxDecompositionLevelsCount; r++) { - for (; l < layersCount; l++) { - for (; i < componentsCount; i++) { - const component = tile.components[i]; - - if (r > component.codingStyleParameters.decompositionLevelsCount) { - continue; - } - - const resolution = component.resolutions[r]; - const numprecincts = resolution.precinctParameters.numprecincts; - - for (; k < numprecincts;) { - const packet = createPacket(resolution, k, l); - k++; - return packet; - } - - k = 0; - } - - i = 0; - } - - l = 0; - } - - throw new JpxError("Out of packets"); - }; -} - -function ResolutionPositionComponentLayerIterator(context) { - const siz = context.SIZ; - const tileIndex = context.currentTile.index; - const tile = context.tiles[tileIndex]; - const layersCount = tile.codingStyleDefaultParameters.layersCount; - const componentsCount = siz.Csiz; - let l, r, c, p; - let maxDecompositionLevelsCount = 0; - - for (c = 0; c < componentsCount; c++) { - const component = tile.components[c]; - maxDecompositionLevelsCount = Math.max(maxDecompositionLevelsCount, component.codingStyleParameters.decompositionLevelsCount); - } - - const maxNumPrecinctsInLevel = new Int32Array(maxDecompositionLevelsCount + 1); - - for (r = 0; r <= maxDecompositionLevelsCount; ++r) { - let maxNumPrecincts = 0; - - for (c = 0; c < componentsCount; ++c) { - const resolutions = tile.components[c].resolutions; - - if (r < resolutions.length) { - maxNumPrecincts = Math.max(maxNumPrecincts, resolutions[r].precinctParameters.numprecincts); - } - } - - maxNumPrecinctsInLevel[r] = maxNumPrecincts; - } - - l = 0; - r = 0; - c = 0; - p = 0; - - this.nextPacket = function JpxImage_nextPacket() { - for (; r <= maxDecompositionLevelsCount; r++) { - for (; p < maxNumPrecinctsInLevel[r]; p++) { - for (; c < componentsCount; c++) { - const component = tile.components[c]; - - if (r > component.codingStyleParameters.decompositionLevelsCount) { - continue; - } - - const resolution = component.resolutions[r]; - const numprecincts = resolution.precinctParameters.numprecincts; - - if (p >= numprecincts) { - continue; - } - - for (; l < layersCount;) { - const packet = createPacket(resolution, p, l); - l++; - return packet; - } - - l = 0; - } - - c = 0; - } - - p = 0; - } - - throw new JpxError("Out of packets"); - }; -} - -function PositionComponentResolutionLayerIterator(context) { - const siz = context.SIZ; - const tileIndex = context.currentTile.index; - const tile = context.tiles[tileIndex]; - const layersCount = tile.codingStyleDefaultParameters.layersCount; - const componentsCount = siz.Csiz; - const precinctsSizes = getPrecinctSizesInImageScale(tile); - const precinctsIterationSizes = precinctsSizes; - let l = 0, - r = 0, - c = 0, - px = 0, - py = 0; - - this.nextPacket = function JpxImage_nextPacket() { - for (; py < precinctsIterationSizes.maxNumHigh; py++) { - for (; px < precinctsIterationSizes.maxNumWide; px++) { - for (; c < componentsCount; c++) { - const component = tile.components[c]; - const decompositionLevelsCount = component.codingStyleParameters.decompositionLevelsCount; - - for (; r <= decompositionLevelsCount; r++) { - const resolution = component.resolutions[r]; - const sizeInImageScale = precinctsSizes.components[c].resolutions[r]; - const k = getPrecinctIndexIfExist(px, py, sizeInImageScale, precinctsIterationSizes, resolution); - - if (k === null) { - continue; - } - - for (; l < layersCount;) { - const packet = createPacket(resolution, k, l); - l++; - return packet; - } - - l = 0; - } - - r = 0; - } - - c = 0; - } - - px = 0; - } - - throw new JpxError("Out of packets"); - }; -} - -function ComponentPositionResolutionLayerIterator(context) { - const siz = context.SIZ; - const tileIndex = context.currentTile.index; - const tile = context.tiles[tileIndex]; - const layersCount = tile.codingStyleDefaultParameters.layersCount; - const componentsCount = siz.Csiz; - const precinctsSizes = getPrecinctSizesInImageScale(tile); - let l = 0, - r = 0, - c = 0, - px = 0, - py = 0; - - this.nextPacket = function JpxImage_nextPacket() { - for (; c < componentsCount; ++c) { - const component = tile.components[c]; - const precinctsIterationSizes = precinctsSizes.components[c]; - const decompositionLevelsCount = component.codingStyleParameters.decompositionLevelsCount; - - for (; py < precinctsIterationSizes.maxNumHigh; py++) { - for (; px < precinctsIterationSizes.maxNumWide; px++) { - for (; r <= decompositionLevelsCount; r++) { - const resolution = component.resolutions[r]; - const sizeInImageScale = precinctsIterationSizes.resolutions[r]; - const k = getPrecinctIndexIfExist(px, py, sizeInImageScale, precinctsIterationSizes, resolution); - - if (k === null) { - continue; - } - - for (; l < layersCount;) { - const packet = createPacket(resolution, k, l); - l++; - return packet; - } - - l = 0; - } - - r = 0; - } - - px = 0; - } - - py = 0; - } - - throw new JpxError("Out of packets"); - }; -} - -function getPrecinctIndexIfExist(pxIndex, pyIndex, sizeInImageScale, precinctIterationSizes, resolution) { - const posX = pxIndex * precinctIterationSizes.minWidth; - const posY = pyIndex * precinctIterationSizes.minHeight; - - if (posX % sizeInImageScale.width !== 0 || posY % sizeInImageScale.height !== 0) { - return null; - } - - const startPrecinctRowIndex = posY / sizeInImageScale.width * resolution.precinctParameters.numprecinctswide; - return posX / sizeInImageScale.height + startPrecinctRowIndex; -} - -function getPrecinctSizesInImageScale(tile) { - const componentsCount = tile.components.length; - let minWidth = Number.MAX_VALUE; - let minHeight = Number.MAX_VALUE; - let maxNumWide = 0; - let maxNumHigh = 0; - const sizePerComponent = new Array(componentsCount); - - for (let c = 0; c < componentsCount; c++) { - const component = tile.components[c]; - const decompositionLevelsCount = component.codingStyleParameters.decompositionLevelsCount; - const sizePerResolution = new Array(decompositionLevelsCount + 1); - let minWidthCurrentComponent = Number.MAX_VALUE; - let minHeightCurrentComponent = Number.MAX_VALUE; - let maxNumWideCurrentComponent = 0; - let maxNumHighCurrentComponent = 0; - let scale = 1; - - for (let r = decompositionLevelsCount; r >= 0; --r) { - const resolution = component.resolutions[r]; - const widthCurrentResolution = scale * resolution.precinctParameters.precinctWidth; - const heightCurrentResolution = scale * resolution.precinctParameters.precinctHeight; - minWidthCurrentComponent = Math.min(minWidthCurrentComponent, widthCurrentResolution); - minHeightCurrentComponent = Math.min(minHeightCurrentComponent, heightCurrentResolution); - maxNumWideCurrentComponent = Math.max(maxNumWideCurrentComponent, resolution.precinctParameters.numprecinctswide); - maxNumHighCurrentComponent = Math.max(maxNumHighCurrentComponent, resolution.precinctParameters.numprecinctshigh); - sizePerResolution[r] = { - width: widthCurrentResolution, - height: heightCurrentResolution - }; - scale <<= 1; - } - - minWidth = Math.min(minWidth, minWidthCurrentComponent); - minHeight = Math.min(minHeight, minHeightCurrentComponent); - maxNumWide = Math.max(maxNumWide, maxNumWideCurrentComponent); - maxNumHigh = Math.max(maxNumHigh, maxNumHighCurrentComponent); - sizePerComponent[c] = { - resolutions: sizePerResolution, - minWidth: minWidthCurrentComponent, - minHeight: minHeightCurrentComponent, - maxNumWide: maxNumWideCurrentComponent, - maxNumHigh: maxNumHighCurrentComponent - }; - } - - return { - components: sizePerComponent, - minWidth, - minHeight, - maxNumWide, - maxNumHigh - }; -} - -function buildPackets(context) { - const siz = context.SIZ; - const tileIndex = context.currentTile.index; - const tile = context.tiles[tileIndex]; - const componentsCount = siz.Csiz; - - for (let c = 0; c < componentsCount; c++) { - const component = tile.components[c]; - const decompositionLevelsCount = component.codingStyleParameters.decompositionLevelsCount; - const resolutions = []; - const subbands = []; - - for (let r = 0; r <= decompositionLevelsCount; r++) { - const blocksDimensions = getBlocksDimensions(context, component, r); - const resolution = {}; - const scale = 1 << decompositionLevelsCount - r; - resolution.trx0 = Math.ceil(component.tcx0 / scale); - resolution.try0 = Math.ceil(component.tcy0 / scale); - resolution.trx1 = Math.ceil(component.tcx1 / scale); - resolution.try1 = Math.ceil(component.tcy1 / scale); - resolution.resLevel = r; - buildPrecincts(context, resolution, blocksDimensions); - resolutions.push(resolution); - let subband; - - if (r === 0) { - 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 { - const bscale = 1 << decompositionLevelsCount - r + 1; - const resolutionSubbands = []; - 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; - } - - const progressionOrder = tile.codingStyleDefaultParameters.progressionOrder; - - switch (progressionOrder) { - case 0: - tile.packetsIterator = new LayerResolutionComponentPositionIterator(context); - break; - - case 1: - tile.packetsIterator = new ResolutionLayerComponentPositionIterator(context); - break; - - case 2: - tile.packetsIterator = new ResolutionPositionComponentLayerIterator(context); - break; - - case 3: - tile.packetsIterator = new PositionComponentResolutionLayerIterator(context); - break; - - case 4: - tile.packetsIterator = new ComponentPositionResolutionLayerIterator(context); - break; - - default: - throw new JpxError(`Unsupported progression order ${progressionOrder}`); - } -} - -function parseTilePackets(context, data, offset, dataLength) { - let position = 0; - let buffer, - bufferSize = 0, - skipNextBit = false; - - function readBits(count) { - while (bufferSize < count) { - const b = data[offset + position]; - position++; - - if (skipNextBit) { - buffer = buffer << 7 | b; - bufferSize += 7; - skipNextBit = false; - } else { - buffer = buffer << 8 | b; - bufferSize += 8; - } - - if (b === 0xff) { - skipNextBit = true; - } - } - - bufferSize -= count; - return buffer >>> bufferSize & (1 << count) - 1; - } - - function skipMarkerIfEqual(value) { - if (data[offset + position - 1] === 0xff && data[offset + position] === value) { - skipBytes(1); - return true; - } else if (data[offset + position] === 0xff && data[offset + position + 1] === value) { - skipBytes(2); - return true; - } - - return false; - } - - function skipBytes(count) { - position += count; - } - - function alignToByte() { - bufferSize = 0; - - if (skipNextBit) { - position++; - skipNextBit = false; - } - } - - function readCodingpasses() { - if (readBits(1) === 0) { - return 1; - } - - if (readBits(1) === 0) { - return 2; - } - - let value = readBits(2); - - if (value < 3) { - return value + 3; - } - - value = readBits(5); - - if (value < 31) { - return value + 6; - } - - value = readBits(7); - return value + 37; - } - - const tileIndex = context.currentTile.index; - const tile = context.tiles[tileIndex]; - const sopMarkerUsed = context.COD.sopMarkerUsed; - const ephMarkerUsed = context.COD.ephMarkerUsed; - const packetsIterator = tile.packetsIterator; - - while (position < dataLength) { - alignToByte(); - - if (sopMarkerUsed && skipMarkerIfEqual(0x91)) { - skipBytes(4); - } - - const packet = packetsIterator.nextPacket(); - - if (!readBits(1)) { - continue; - } - - const layerNumber = packet.layerNumber, - queue = []; - let codeblock; - - for (let i = 0, ii = packet.codeblocks.length; i < ii; i++) { - codeblock = packet.codeblocks[i]; - let precinct = codeblock.precinct; - const codeblockColumn = codeblock.cbx - precinct.cbxMin; - const codeblockRow = codeblock.cby - precinct.cbyMin; - let codeblockIncluded = false; - let firstTimeInclusion = false; - let valueReady, zeroBitPlanesTree; - - if (codeblock.included !== undefined) { - codeblockIncluded = !!readBits(1); - } else { - precinct = codeblock.precinct; - let inclusionTree; - - if (precinct.inclusionTree !== undefined) { - inclusionTree = precinct.inclusionTree; - } else { - const width = precinct.cbxMax - precinct.cbxMin + 1; - const height = precinct.cbyMax - precinct.cbyMin + 1; - inclusionTree = new InclusionTree(width, height, layerNumber); - zeroBitPlanesTree = new TagTree(width, height); - precinct.inclusionTree = inclusionTree; - precinct.zeroBitPlanesTree = zeroBitPlanesTree; - - for (let l = 0; l < layerNumber; l++) { - if (readBits(1) !== 0) { - throw new JpxError("Invalid tag tree"); - } - } - } - - if (inclusionTree.reset(codeblockColumn, codeblockRow, layerNumber)) { - while (true) { - if (readBits(1)) { - valueReady = !inclusionTree.nextLevel(); - - if (valueReady) { - codeblock.included = true; - codeblockIncluded = firstTimeInclusion = true; - break; - } - } else { - inclusionTree.incrementValue(layerNumber); - break; - } - } - } - } - - if (!codeblockIncluded) { - continue; - } - - if (firstTimeInclusion) { - zeroBitPlanesTree = precinct.zeroBitPlanesTree; - zeroBitPlanesTree.reset(codeblockColumn, codeblockRow); - - while (true) { - if (readBits(1)) { - valueReady = !zeroBitPlanesTree.nextLevel(); - - if (valueReady) { - break; - } - } else { - zeroBitPlanesTree.incrementValue(); - } - } - - codeblock.zeroBitPlanes = zeroBitPlanesTree.value; - } - - const codingpasses = readCodingpasses(); - - while (readBits(1)) { - codeblock.Lblock++; - } - - const codingpassesLog2 = (0, _core_utils.log2)(codingpasses); - const bits = (codingpasses < 1 << codingpassesLog2 ? codingpassesLog2 - 1 : codingpassesLog2) + codeblock.Lblock; - const codedDataLength = readBits(bits); - queue.push({ - codeblock, - codingpasses, - dataLength: codedDataLength - }); - } - - alignToByte(); - - if (ephMarkerUsed) { - skipMarkerIfEqual(0x92); - } - - while (queue.length > 0) { - const packetItem = queue.shift(); - codeblock = packetItem.codeblock; - - if (codeblock.data === undefined) { - codeblock.data = []; - } - - codeblock.data.push({ - data, - start: offset + position, - end: offset + position + packetItem.dataLength, - codingpasses: packetItem.codingpasses - }); - position += packetItem.dataLength; - } - } - - return position; -} - -function copyCoefficients(coefficients, levelWidth, levelHeight, subband, delta, mb, reversible, segmentationSymbolUsed) { - const x0 = subband.tbx0; - const y0 = subband.tby0; - const width = subband.tbx1 - subband.tbx0; - const codeblocks = subband.codeblocks; - const right = subband.type.charAt(0) === "H" ? 1 : 0; - const bottom = subband.type.charAt(1) === "H" ? levelWidth : 0; - - for (let i = 0, ii = codeblocks.length; i < ii; ++i) { - const codeblock = codeblocks[i]; - const blockWidth = codeblock.tbx1_ - codeblock.tbx0_; - const blockHeight = codeblock.tby1_ - codeblock.tby0_; - - if (blockWidth === 0 || blockHeight === 0) { - continue; - } - - if (codeblock.data === undefined) { - continue; - } - - const bitModel = new BitModel(blockWidth, blockHeight, codeblock.subbandType, codeblock.zeroBitPlanes, mb); - let currentCodingpassType = 2; - const data = codeblock.data; - let totalLength = 0, - codingpasses = 0; - let j, jj, dataItem; - - for (j = 0, jj = data.length; j < jj; j++) { - dataItem = data[j]; - totalLength += dataItem.end - dataItem.start; - codingpasses += dataItem.codingpasses; - } - - const encodedData = new Uint8Array(totalLength); - let position = 0; - - for (j = 0, jj = data.length; j < jj; j++) { - dataItem = data[j]; - const chunk = dataItem.data.subarray(dataItem.start, dataItem.end); - encodedData.set(chunk, position); - position += chunk.length; - } - - const decoder = new _arithmetic_decoder.ArithmeticDecoder(encodedData, 0, totalLength); - bitModel.setDecoder(decoder); - - for (j = 0; j < codingpasses; j++) { - switch (currentCodingpassType) { - case 0: - bitModel.runSignificancePropagationPass(); - break; - - case 1: - bitModel.runMagnitudeRefinementPass(); - break; - - case 2: - bitModel.runCleanupPass(); - - if (segmentationSymbolUsed) { - bitModel.checkSegmentationSymbol(); - } - - break; - } - - currentCodingpassType = (currentCodingpassType + 1) % 3; - } - - let offset = codeblock.tbx0_ - x0 + (codeblock.tby0_ - y0) * width; - const sign = bitModel.coefficentsSign; - const magnitude = bitModel.coefficentsMagnitude; - const bitsDecoded = bitModel.bitsDecoded; - const magnitudeCorrection = reversible ? 0 : 0.5; - let k, n, nb; - position = 0; - const interleave = subband.type !== "LL"; - - for (j = 0; j < blockHeight; j++) { - const row = offset / width | 0; - const levelOffset = 2 * row * (levelWidth - width) + right + bottom; - - for (k = 0; k < blockWidth; k++) { - n = magnitude[position]; - - if (n !== 0) { - n = (n + magnitudeCorrection) * delta; - - if (sign[position] !== 0) { - n = -n; - } - - nb = bitsDecoded[position]; - const pos = interleave ? levelOffset + (offset << 1) : offset; - - if (reversible && nb >= mb) { - coefficients[pos] = n; - } else { - coefficients[pos] = n * (1 << mb - nb); - } - } - - offset++; - position++; - } - - offset += width - blockWidth; - } - } -} - -function transformTile(context, tile, c) { - const component = tile.components[c]; - const codingStyleParameters = component.codingStyleParameters; - const quantizationParameters = component.quantizationParameters; - const decompositionLevelsCount = codingStyleParameters.decompositionLevelsCount; - const spqcds = quantizationParameters.SPqcds; - const scalarExpounded = quantizationParameters.scalarExpounded; - const guardBits = quantizationParameters.guardBits; - const segmentationSymbolUsed = codingStyleParameters.segmentationSymbolUsed; - const precision = context.components[c].precision; - const reversible = codingStyleParameters.reversibleTransformation; - const transform = reversible ? new ReversibleTransform() : new IrreversibleTransform(); - const subbandCoefficients = []; - let b = 0; - - for (let i = 0; i <= decompositionLevelsCount; i++) { - const resolution = component.resolutions[i]; - const width = resolution.trx1 - resolution.trx0; - const height = resolution.try1 - resolution.try0; - const coefficients = new Float32Array(width * height); - - for (let j = 0, jj = resolution.subbands.length; j < jj; j++) { - let mu, epsilon; - - if (!scalarExpounded) { - mu = spqcds[0].mu; - epsilon = spqcds[0].epsilon + (i > 0 ? 1 - i : 0); - } else { - mu = spqcds[b].mu; - epsilon = spqcds[b].epsilon; - b++; - } - - const subband = resolution.subbands[j]; - const gainLog2 = SubbandsGainLog2[subband.type]; - const delta = reversible ? 1 : 2 ** (precision + gainLog2 - epsilon) * (1 + mu / 2048); - const mb = guardBits + epsilon - 1; - copyCoefficients(coefficients, width, height, subband, delta, mb, reversible, segmentationSymbolUsed); - } - - subbandCoefficients.push({ - width, - height, - items: coefficients - }); - } - - const 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) { - const siz = context.SIZ; - const components = context.components; - const componentsCount = siz.Csiz; - const resultImages = []; - - for (let i = 0, ii = context.tiles.length; i < ii; i++) { - const tile = context.tiles[i]; - const transformedTiles = []; - - for (let c = 0; c < componentsCount; c++) { - transformedTiles[c] = transformTile(context, tile, c); - } - - const tile0 = transformedTiles[0]; - const out = new Uint8ClampedArray(tile0.items.length * componentsCount); - const result = { - left: tile0.left, - top: tile0.top, - width: tile0.width, - height: tile0.height, - items: out - }; - let shift, offset; - let pos = 0, - j, - jj, - y0, - y1, - y2; - - if (tile.codingStyleDefaultParameters.multipleComponentTransform) { - const fourComponents = componentsCount === 4; - const y0items = transformedTiles[0].items; - const y1items = transformedTiles[1].items; - const y2items = transformedTiles[2].items; - const y3items = fourComponents ? transformedTiles[3].items : null; - shift = components[0].precision - 8; - offset = (128 << shift) + 0.5; - const component0 = tile.components[0]; - const alpha01 = componentsCount - 3; - jj = y0items.length; - - if (!component0.codingStyleParameters.reversibleTransformation) { - for (j = 0; j < jj; j++, pos += alpha01) { - y0 = y0items[j] + offset; - y1 = y1items[j]; - y2 = y2items[j]; - out[pos++] = y0 + 1.402 * y2 >> shift; - out[pos++] = y0 - 0.34413 * y1 - 0.71414 * y2 >> shift; - out[pos++] = y0 + 1.772 * y1 >> shift; - } - } else { - for (j = 0; j < jj; j++, pos += alpha01) { - y0 = y0items[j] + offset; - y1 = y1items[j]; - y2 = y2items[j]; - const g = y0 - (y2 + y1 >> 2); - out[pos++] = g + y2 >> shift; - out[pos++] = g >> shift; - out[pos++] = g + y1 >> shift; - } - } - - if (fourComponents) { - for (j = 0, pos = 3; j < jj; j++, pos += 4) { - out[pos] = y3items[j] + offset >> shift; - } - } - } else { - for (let c = 0; c < componentsCount; c++) { - const items = transformedTiles[c].items; - shift = components[c].precision - 8; - offset = (128 << shift) + 0.5; - - for (pos = c, j = 0, jj = items.length; j < jj; j++) { - out[pos] = items[j] + offset >> shift; - pos += componentsCount; - } - } - } - - resultImages.push(result); - } - - return resultImages; -} - -function initializeTile(context, tileIndex) { - const siz = context.SIZ; - const componentsCount = siz.Csiz; - const tile = context.tiles[tileIndex]; - - for (let c = 0; c < componentsCount; c++) { - const component = tile.components[c]; - const qcdOrQcc = context.currentTile.QCC[c] !== undefined ? context.currentTile.QCC[c] : context.currentTile.QCD; - component.quantizationParameters = qcdOrQcc; - const codOrCoc = context.currentTile.COC[c] !== undefined ? context.currentTile.COC[c] : context.currentTile.COD; - component.codingStyleParameters = codOrCoc; - } - - tile.codingStyleDefaultParameters = context.currentTile.COD; -} - -class TagTree { - constructor(width, height) { - const levelsLength = (0, _core_utils.log2)(Math.max(width, height)) + 1; - this.levels = []; - - for (let i = 0; i < levelsLength; i++) { - const level = { - width, - height, - items: [] - }; - this.levels.push(level); - width = Math.ceil(width / 2); - height = Math.ceil(height / 2); - } - } - - reset(i, j) { - let currentLevel = 0, - value = 0, - level; - - while (currentLevel < this.levels.length) { - level = this.levels[currentLevel]; - const index = i + j * level.width; - - if (level.items[index] !== undefined) { - value = level.items[index]; - break; - } - - level.index = index; - i >>= 1; - j >>= 1; - currentLevel++; - } - - currentLevel--; - level = this.levels[currentLevel]; - level.items[level.index] = value; - this.currentLevel = currentLevel; - delete this.value; - } - - incrementValue() { - const level = this.levels[this.currentLevel]; - level.items[level.index]++; - } - - nextLevel() { - let currentLevel = this.currentLevel; - let level = this.levels[currentLevel]; - const value = level.items[level.index]; - currentLevel--; - - if (currentLevel < 0) { - this.value = value; - return false; - } - - this.currentLevel = currentLevel; - level = this.levels[currentLevel]; - level.items[level.index] = value; - return true; - } - -} - -class InclusionTree { - constructor(width, height, defaultValue) { - const levelsLength = (0, _core_utils.log2)(Math.max(width, height)) + 1; - this.levels = []; - - for (let i = 0; i < levelsLength; i++) { - const items = new Uint8Array(width * height); - - for (let j = 0, jj = items.length; j < jj; j++) { - items[j] = defaultValue; - } - - const level = { - width, - height, - items - }; - this.levels.push(level); - width = Math.ceil(width / 2); - height = Math.ceil(height / 2); - } - } - - reset(i, j, stopValue) { - let currentLevel = 0; - - while (currentLevel < this.levels.length) { - const level = this.levels[currentLevel]; - const index = i + j * level.width; - level.index = index; - const value = level.items[index]; - - if (value === 0xff) { - break; - } - - if (value > stopValue) { - this.currentLevel = currentLevel; - this.propagateValues(); - return false; - } - - i >>= 1; - j >>= 1; - currentLevel++; - } - - this.currentLevel = currentLevel - 1; - return true; - } - - incrementValue(stopValue) { - const level = this.levels[this.currentLevel]; - level.items[level.index] = stopValue + 1; - this.propagateValues(); - } - - propagateValues() { - let levelIndex = this.currentLevel; - let level = this.levels[levelIndex]; - const currentValue = level.items[level.index]; - - while (--levelIndex >= 0) { - level = this.levels[levelIndex]; - level.items[level.index] = currentValue; - } - } - - nextLevel() { - let currentLevel = this.currentLevel; - let level = this.levels[currentLevel]; - const value = level.items[level.index]; - level.items[level.index] = 0xff; - currentLevel--; - - if (currentLevel < 0) { - return false; - } - - this.currentLevel = currentLevel; - level = this.levels[currentLevel]; - level.items[level.index] = value; - return true; - } - -} - -const BitModel = function BitModelClosure() { - const UNIFORM_CONTEXT = 17; - const RUNLENGTH_CONTEXT = 18; - const 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]); - const 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]); - const 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]); - - class BitModel { - constructor(width, height, subband, zeroBitPlanes, mb) { - this.width = width; - this.height = height; - let contextLabelTable; - - if (subband === "HH") { - contextLabelTable = HHContextLabel; - } else if (subband === "HL") { - contextLabelTable = HLContextLabel; - } else { - contextLabelTable = LLAndLHContextsLabel; - } - - this.contextLabelTable = contextLabelTable; - const coefficientCount = width * height; - this.neighborsSignificance = new Uint8Array(coefficientCount); - this.coefficentsSign = new Uint8Array(coefficientCount); - let coefficentsMagnitude; - - if (mb > 14) { - coefficentsMagnitude = new Uint32Array(coefficientCount); - } else if (mb > 6) { - coefficentsMagnitude = new Uint16Array(coefficientCount); - } else { - coefficentsMagnitude = new Uint8Array(coefficientCount); - } - - this.coefficentsMagnitude = coefficentsMagnitude; - this.processingFlags = new Uint8Array(coefficientCount); - const bitsDecoded = new Uint8Array(coefficientCount); - - if (zeroBitPlanes !== 0) { - for (let i = 0; i < coefficientCount; i++) { - bitsDecoded[i] = zeroBitPlanes; - } - } - - this.bitsDecoded = bitsDecoded; - this.reset(); - } - - setDecoder(decoder) { - this.decoder = decoder; - } - - reset() { - this.contexts = new Int8Array(19); - this.contexts[0] = 4 << 1 | 0; - this.contexts[UNIFORM_CONTEXT] = 46 << 1 | 0; - this.contexts[RUNLENGTH_CONTEXT] = 3 << 1 | 0; - } - - setNeighborsSignificance(row, column, index) { - const neighborsSignificance = this.neighborsSignificance; - const width = this.width, - height = this.height; - const left = column > 0; - const right = column + 1 < width; - let i; - - if (row > 0) { - i = index - width; - - if (left) { - neighborsSignificance[i - 1] += 0x10; - } - - if (right) { - neighborsSignificance[i + 1] += 0x10; - } - - neighborsSignificance[i] += 0x04; - } - - if (row + 1 < height) { - i = index + width; - - if (left) { - neighborsSignificance[i - 1] += 0x10; - } - - if (right) { - neighborsSignificance[i + 1] += 0x10; - } - - neighborsSignificance[i] += 0x04; - } - - if (left) { - neighborsSignificance[index - 1] += 0x01; - } - - if (right) { - neighborsSignificance[index + 1] += 0x01; - } - - neighborsSignificance[index] |= 0x80; - } - - runSignificancePropagationPass() { - const decoder = this.decoder; - const width = this.width, - height = this.height; - const coefficentsMagnitude = this.coefficentsMagnitude; - const coefficentsSign = this.coefficentsSign; - const neighborsSignificance = this.neighborsSignificance; - const processingFlags = this.processingFlags; - const contexts = this.contexts; - const labels = this.contextLabelTable; - const bitsDecoded = this.bitsDecoded; - const processedInverseMask = ~1; - const processedMask = 1; - const firstMagnitudeBitMask = 2; - - for (let i0 = 0; i0 < height; i0 += 4) { - for (let j = 0; j < width; j++) { - let index = i0 * width + j; - - for (let i1 = 0; i1 < 4; i1++, index += width) { - const i = i0 + i1; - - if (i >= height) { - break; - } - - processingFlags[index] &= processedInverseMask; - - if (coefficentsMagnitude[index] || !neighborsSignificance[index]) { - continue; - } - - const contextLabel = labels[neighborsSignificance[index]]; - const decision = decoder.readBit(contexts, contextLabel); - - if (decision) { - const sign = this.decodeSignBit(i, j, index); - coefficentsSign[index] = sign; - coefficentsMagnitude[index] = 1; - this.setNeighborsSignificance(i, j, index); - processingFlags[index] |= firstMagnitudeBitMask; - } - - bitsDecoded[index]++; - processingFlags[index] |= processedMask; - } - } - } - } - - decodeSignBit(row, column, index) { - const width = this.width, - height = this.height; - const coefficentsMagnitude = this.coefficentsMagnitude; - const coefficentsSign = this.coefficentsSign; - let contribution, sign0, sign1, significance1; - let contextLabel, decoded; - significance1 = column > 0 && coefficentsMagnitude[index - 1] !== 0; - - if (column + 1 < width && coefficentsMagnitude[index + 1] !== 0) { - sign1 = coefficentsSign[index + 1]; - - if (significance1) { - sign0 = coefficentsSign[index - 1]; - contribution = 1 - sign1 - sign0; - } else { - contribution = 1 - sign1 - sign1; - } - } else if (significance1) { - sign0 = coefficentsSign[index - 1]; - contribution = 1 - sign0 - sign0; - } else { - contribution = 0; - } - - const horizontalContribution = 3 * contribution; - significance1 = row > 0 && coefficentsMagnitude[index - width] !== 0; - - if (row + 1 < height && coefficentsMagnitude[index + width] !== 0) { - sign1 = coefficentsSign[index + width]; - - if (significance1) { - sign0 = coefficentsSign[index - width]; - contribution = 1 - sign1 - sign0 + horizontalContribution; - } else { - contribution = 1 - sign1 - sign1 + horizontalContribution; - } - } else if (significance1) { - sign0 = coefficentsSign[index - width]; - contribution = 1 - sign0 - sign0 + horizontalContribution; - } else { - contribution = horizontalContribution; - } - - if (contribution >= 0) { - contextLabel = 9 + contribution; - decoded = this.decoder.readBit(this.contexts, contextLabel); - } else { - contextLabel = 9 - contribution; - decoded = this.decoder.readBit(this.contexts, contextLabel) ^ 1; - } - - return decoded; - } - - runMagnitudeRefinementPass() { - const decoder = this.decoder; - const width = this.width, - height = this.height; - const coefficentsMagnitude = this.coefficentsMagnitude; - const neighborsSignificance = this.neighborsSignificance; - const contexts = this.contexts; - const bitsDecoded = this.bitsDecoded; - const processingFlags = this.processingFlags; - const processedMask = 1; - const firstMagnitudeBitMask = 2; - const length = width * height; - const width4 = width * 4; - - for (let index0 = 0, indexNext; index0 < length; index0 = indexNext) { - indexNext = Math.min(length, index0 + width4); - - for (let j = 0; j < width; j++) { - for (let index = index0 + j; index < indexNext; index += width) { - if (!coefficentsMagnitude[index] || (processingFlags[index] & processedMask) !== 0) { - continue; - } - - let contextLabel = 16; - - if ((processingFlags[index] & firstMagnitudeBitMask) !== 0) { - processingFlags[index] ^= firstMagnitudeBitMask; - const significance = neighborsSignificance[index] & 127; - contextLabel = significance === 0 ? 15 : 14; - } - - const bit = decoder.readBit(contexts, contextLabel); - coefficentsMagnitude[index] = coefficentsMagnitude[index] << 1 | bit; - bitsDecoded[index]++; - processingFlags[index] |= processedMask; - } - } - } - } - - runCleanupPass() { - const decoder = this.decoder; - const width = this.width, - height = this.height; - const neighborsSignificance = this.neighborsSignificance; - const coefficentsMagnitude = this.coefficentsMagnitude; - const coefficentsSign = this.coefficentsSign; - const contexts = this.contexts; - const labels = this.contextLabelTable; - const bitsDecoded = this.bitsDecoded; - const processingFlags = this.processingFlags; - const processedMask = 1; - const firstMagnitudeBitMask = 2; - const oneRowDown = width; - const twoRowsDown = width * 2; - const threeRowsDown = width * 3; - let iNext; - - for (let i0 = 0; i0 < height; i0 = iNext) { - iNext = Math.min(i0 + 4, height); - const indexBase = i0 * width; - const checkAllEmpty = i0 + 3 < height; - - for (let j = 0; j < width; j++) { - const index0 = indexBase + j; - const allEmpty = checkAllEmpty && processingFlags[index0] === 0 && processingFlags[index0 + oneRowDown] === 0 && processingFlags[index0 + twoRowsDown] === 0 && processingFlags[index0 + threeRowsDown] === 0 && neighborsSignificance[index0] === 0 && neighborsSignificance[index0 + oneRowDown] === 0 && neighborsSignificance[index0 + twoRowsDown] === 0 && neighborsSignificance[index0 + threeRowsDown] === 0; - let i1 = 0, - index = index0; - let i = i0, - sign; - - if (allEmpty) { - const hasSignificantCoefficent = decoder.readBit(contexts, RUNLENGTH_CONTEXT); - - if (!hasSignificantCoefficent) { - bitsDecoded[index0]++; - bitsDecoded[index0 + oneRowDown]++; - bitsDecoded[index0 + twoRowsDown]++; - bitsDecoded[index0 + threeRowsDown]++; - continue; - } - - i1 = decoder.readBit(contexts, UNIFORM_CONTEXT) << 1 | decoder.readBit(contexts, UNIFORM_CONTEXT); - - if (i1 !== 0) { - i = i0 + i1; - index += i1 * width; - } - - sign = this.decodeSignBit(i, j, index); - coefficentsSign[index] = sign; - coefficentsMagnitude[index] = 1; - this.setNeighborsSignificance(i, j, index); - processingFlags[index] |= firstMagnitudeBitMask; - index = index0; - - for (let i2 = i0; i2 <= i; i2++, index += width) { - bitsDecoded[index]++; - } - - i1++; - } - - for (i = i0 + i1; i < iNext; i++, index += width) { - if (coefficentsMagnitude[index] || (processingFlags[index] & processedMask) !== 0) { - continue; - } - - const contextLabel = labels[neighborsSignificance[index]]; - const decision = decoder.readBit(contexts, contextLabel); - - if (decision === 1) { - sign = this.decodeSignBit(i, j, index); - coefficentsSign[index] = sign; - coefficentsMagnitude[index] = 1; - this.setNeighborsSignificance(i, j, index); - processingFlags[index] |= firstMagnitudeBitMask; - } - - bitsDecoded[index]++; - } - } - } - } - - checkSegmentationSymbol() { - const decoder = this.decoder; - const contexts = this.contexts; - const symbol = decoder.readBit(contexts, UNIFORM_CONTEXT) << 3 | decoder.readBit(contexts, UNIFORM_CONTEXT) << 2 | decoder.readBit(contexts, UNIFORM_CONTEXT) << 1 | decoder.readBit(contexts, UNIFORM_CONTEXT); - - if (symbol !== 0xa) { - throw new JpxError("Invalid segmentation symbol"); - } - } - - } - - return BitModel; -}(); - -class Transform { - constructor() { - if (this.constructor === Transform) { - (0, _util.unreachable)("Cannot initialize Transform."); - } - } - - calculate(subbands, u0, v0) { - let ll = subbands[0]; - - for (let i = 1, ii = subbands.length; i < ii; i++) { - ll = this.iterate(ll, subbands[i], u0, v0); - } - - return ll; - } - - extend(buffer, offset, size) { - let i1 = offset - 1, - j1 = offset + 1; - let i2 = offset + size - 2, - j2 = offset + size; - buffer[i1--] = buffer[j1++]; - buffer[j2++] = buffer[i2--]; - buffer[i1--] = buffer[j1++]; - buffer[j2++] = buffer[i2--]; - buffer[i1--] = buffer[j1++]; - buffer[j2++] = buffer[i2--]; - buffer[i1] = buffer[j1]; - buffer[j2] = buffer[i2]; - } - - filter(x, offset, length) { - (0, _util.unreachable)("Abstract method `filter` called"); - } - - iterate(ll, hl_lh_hh, u0, v0) { - const llWidth = ll.width, - llHeight = ll.height; - let llItems = ll.items; - const width = hl_lh_hh.width; - const height = hl_lh_hh.height; - const items = hl_lh_hh.items; - let i, j, k, l, u, v; - - for (k = 0, i = 0; i < llHeight; i++) { - l = i * 2 * width; - - for (j = 0; j < llWidth; j++, k++, l += 2) { - items[l] = llItems[k]; - } - } - - llItems = ll.items = null; - const bufferPadding = 4; - const rowBuffer = new Float32Array(width + 2 * bufferPadding); - - if (width === 1) { - if ((u0 & 1) !== 0) { - for (v = 0, k = 0; v < height; v++, k += width) { - items[k] *= 0.5; - } - } - } else { - for (v = 0, k = 0; v < height; v++, k += width) { - rowBuffer.set(items.subarray(k, k + width), bufferPadding); - this.extend(rowBuffer, bufferPadding, width); - this.filter(rowBuffer, bufferPadding, width); - items.set(rowBuffer.subarray(bufferPadding, bufferPadding + width), k); - } - } - - let numBuffers = 16; - const colBuffers = []; - - for (i = 0; i < numBuffers; i++) { - colBuffers.push(new Float32Array(height + 2 * bufferPadding)); - } - - let b, - currentBuffer = 0; - ll = bufferPadding + height; - - if (height === 1) { - if ((v0 & 1) !== 0) { - for (u = 0; u < width; u++) { - items[u] *= 0.5; - } - } - } else { - for (u = 0; u < width; u++) { - if (currentBuffer === 0) { - numBuffers = Math.min(width - u, numBuffers); - - for (k = u, l = bufferPadding; l < ll; k += width, l++) { - for (b = 0; b < numBuffers; b++) { - colBuffers[b][l] = items[k + b]; - } - } - - currentBuffer = numBuffers; - } - - currentBuffer--; - const buffer = colBuffers[currentBuffer]; - this.extend(buffer, bufferPadding, height); - this.filter(buffer, bufferPadding, height); - - if (currentBuffer === 0) { - k = u - numBuffers + 1; - - for (l = bufferPadding; l < ll; k += width, l++) { - for (b = 0; b < numBuffers; b++) { - items[k + b] = colBuffers[b][l]; - } - } - } - } - } - - return { - width, - height, - items - }; - } - -} - -class IrreversibleTransform extends Transform { - filter(x, offset, length) { - const len = length >> 1; - offset |= 0; - let j, n, current, next; - const alpha = -1.586134342059924; - const beta = -0.052980118572961; - const gamma = 0.882911075530934; - const delta = 0.443506852043971; - const K = 1.230174104914001; - const K_ = 1 / K; - j = offset - 3; - - for (n = len + 4; n--; j += 2) { - x[j] *= K_; - } - - j = offset - 2; - current = delta * x[j - 1]; - - for (n = len + 3; n--; j += 2) { - next = delta * x[j + 1]; - x[j] = K * x[j] - current - next; - - if (n--) { - j += 2; - current = delta * x[j + 1]; - x[j] = K * x[j] - current - next; - } else { - break; - } - } - - j = offset - 1; - current = gamma * x[j - 1]; - - for (n = len + 2; n--; j += 2) { - next = gamma * x[j + 1]; - x[j] -= current + next; - - if (n--) { - j += 2; - current = gamma * x[j + 1]; - x[j] -= current + next; - } else { - break; - } - } - - j = offset; - current = beta * x[j - 1]; - - for (n = len + 1; n--; j += 2) { - next = beta * x[j + 1]; - x[j] -= current + next; - - if (n--) { - j += 2; - current = beta * x[j + 1]; - x[j] -= current + next; - } else { - break; - } - } - - if (len !== 0) { - j = offset + 1; - current = alpha * x[j - 1]; - - for (n = len; n--; j += 2) { - next = alpha * x[j + 1]; - x[j] -= current + next; - - if (n--) { - j += 2; - current = alpha * x[j + 1]; - x[j] -= current + next; - } else { - break; - } - } - } - } - -} - -class ReversibleTransform extends Transform { - filter(x, offset, length) { - const len = length >> 1; - offset |= 0; - let j, n; - - for (j = offset, n = len + 1; n--; j += 2) { - x[j] -= x[j - 1] + x[j + 1] + 2 >> 2; - } - - for (j = offset + 1, n = len; n--; j += 2) { - x[j] += x[j - 1] + x[j + 1] >> 1; - } - } - -} - -/***/ }), -/* 41 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.LZWStream = void 0; - -var _decode_stream = __w_pdfjs_require__(29); - -class LZWStream extends _decode_stream.DecodeStream { - constructor(str, maybeLength, earlyChange) { - super(maybeLength); - this.str = str; - this.dict = str.dict; - this.cachedData = 0; - this.bitsCached = 0; - const maxLzwDictionarySize = 4096; - const lzwState = { - earlyChange, - codeLength: 9, - nextCode: 258, - dictionaryValues: new Uint8Array(maxLzwDictionarySize), - dictionaryLengths: new Uint16Array(maxLzwDictionarySize), - dictionaryPrevCodes: new Uint16Array(maxLzwDictionarySize), - currentSequence: new Uint8Array(maxLzwDictionarySize), - currentSequenceLength: 0 - }; - - for (let i = 0; i < 256; ++i) { - lzwState.dictionaryValues[i] = i; - lzwState.dictionaryLengths[i] = 1; - } - - this.lzwState = lzwState; - } - - readBits(n) { - let bitsCached = this.bitsCached; - let cachedData = this.cachedData; - - while (bitsCached < n) { - const 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; - } - - readBlock() { - const blockSize = 512, - decodedSizeDelta = blockSize; - let estimatedDecodedSize = blockSize * 2; - let i, j, q; - const lzwState = this.lzwState; - - if (!lzwState) { - return; - } - - const earlyChange = lzwState.earlyChange; - let nextCode = lzwState.nextCode; - const dictionaryValues = lzwState.dictionaryValues; - const dictionaryLengths = lzwState.dictionaryLengths; - const dictionaryPrevCodes = lzwState.dictionaryPrevCodes; - let codeLength = lzwState.codeLength; - let prevCode = lzwState.prevCode; - const currentSequence = lzwState.currentSequence; - let currentSequenceLength = lzwState.currentSequenceLength; - let decodedLength = 0; - let currentBufferLength = this.bufferLength; - let buffer = this.ensureBuffer(this.bufferLength + estimatedDecodedSize); - - for (i = 0; i < blockSize; i++) { - const code = this.readBits(codeLength); - const 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; - } - -} - -exports.LZWStream = LZWStream; - -/***/ }), -/* 42 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.PredictorStream = void 0; - -var _decode_stream = __w_pdfjs_require__(29); - -var _util = __w_pdfjs_require__(2); - -var _primitives = __w_pdfjs_require__(5); - -class PredictorStream extends _decode_stream.DecodeStream { - constructor(str, maybeLength, params) { - super(maybeLength); - - if (!(0, _primitives.isDict)(params)) { - return str; - } - - const predictor = this.predictor = params.get("Predictor") || 1; - - if (predictor <= 1) { - return str; - } - - if (predictor !== 2 && (predictor < 10 || predictor > 15)) { - throw new _util.FormatError(`Unsupported predictor: ${predictor}`); - } - - if (predictor === 2) { - this.readBlock = this.readBlockTiff; - } else { - this.readBlock = this.readBlockPng; - } - - this.str = str; - this.dict = str.dict; - const colors = this.colors = params.get("Colors") || 1; - const bits = this.bits = params.get("BPC", "BitsPerComponent") || 8; - const columns = this.columns = params.get("Columns") || 1; - this.pixBytes = colors * bits + 7 >> 3; - this.rowBytes = columns * colors * bits + 7 >> 3; - return this; - } - - readBlockTiff() { - const rowBytes = this.rowBytes; - const bufferLength = this.bufferLength; - const buffer = this.ensureBuffer(bufferLength + rowBytes); - const bits = this.bits; - const colors = this.colors; - const rawBytes = this.str.getBytes(rowBytes); - this.eof = !rawBytes.length; - - if (this.eof) { - return; - } - - let inbuf = 0, - outbuf = 0; - let inbits = 0, - outbits = 0; - let pos = bufferLength; - let i; - - if (bits === 1 && colors === 1) { - for (i = 0; i < rowBytes; ++i) { - let c = rawBytes[i] ^ inbuf; - c ^= c >> 1; - c ^= c >> 2; - c ^= c >> 4; - inbuf = (c & 1) << 7; - buffer[pos++] = c; - } - } else if (bits === 8) { - for (i = 0; i < colors; ++i) { - buffer[pos++] = rawBytes[i]; - } - - for (; i < rowBytes; ++i) { - buffer[pos] = buffer[pos - colors] + rawBytes[i]; - pos++; - } - } else if (bits === 16) { - const bytesPerPixel = colors * 2; - - for (i = 0; i < bytesPerPixel; ++i) { - buffer[pos++] = rawBytes[i]; - } - - for (; i < rowBytes; i += 2) { - const sum = ((rawBytes[i] & 0xff) << 8) + (rawBytes[i + 1] & 0xff) + ((buffer[pos - bytesPerPixel] & 0xff) << 8) + (buffer[pos - bytesPerPixel + 1] & 0xff); - buffer[pos++] = sum >> 8 & 0xff; - buffer[pos++] = sum & 0xff; - } - } else { - const compArray = new Uint8Array(colors + 1); - const bitMask = (1 << bits) - 1; - let j = 0, - k = bufferLength; - const columns = this.columns; - - for (i = 0; i < columns; ++i) { - for (let 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; - } - - readBlockPng() { - const rowBytes = this.rowBytes; - const pixBytes = this.pixBytes; - const predictor = this.str.getByte(); - const rawBytes = this.str.getBytes(rowBytes); - this.eof = !rawBytes.length; - - if (this.eof) { - return; - } - - const bufferLength = this.bufferLength; - const buffer = this.ensureBuffer(bufferLength + rowBytes); - let prevRow = buffer.subarray(bufferLength - rowBytes, bufferLength); - - if (prevRow.length === 0) { - prevRow = new Uint8Array(rowBytes); - } - - let i, - j = bufferLength, - up, - c; - - switch (predictor) { - case 0: - for (i = 0; i < rowBytes; ++i) { - buffer[j++] = rawBytes[i]; - } - - break; - - case 1: - for (i = 0; i < pixBytes; ++i) { - buffer[j++] = rawBytes[i]; - } - - for (; i < rowBytes; ++i) { - buffer[j] = buffer[j - pixBytes] + rawBytes[i] & 0xff; - j++; - } - - break; - - case 2: - for (i = 0; i < rowBytes; ++i) { - buffer[j++] = prevRow[i] + rawBytes[i] & 0xff; - } - - break; - - case 3: - for (i = 0; i < pixBytes; ++i) { - buffer[j++] = (prevRow[i] >> 1) + rawBytes[i]; - } - - for (; i < rowBytes; ++i) { - buffer[j] = (prevRow[i] + buffer[j - pixBytes] >> 1) + rawBytes[i] & 0xff; - j++; - } - - break; - - case 4: - for (i = 0; i < pixBytes; ++i) { - up = prevRow[i]; - c = rawBytes[i]; - buffer[j++] = up + c; - } - - for (; i < rowBytes; ++i) { - up = prevRow[i]; - const upLeft = prevRow[i - pixBytes]; - const left = buffer[j - pixBytes]; - const p = left + up - upLeft; - let pa = p - left; - - if (pa < 0) { - pa = -pa; - } - - let pb = p - up; - - if (pb < 0) { - pb = -pb; - } - - let pc = p - upLeft; - - if (pc < 0) { - pc = -pc; - } - - c = rawBytes[i]; - - if (pa <= pb && pa <= pc) { - buffer[j++] = left + c; - } else if (pb <= pc) { - buffer[j++] = up + c; - } else { - buffer[j++] = upLeft + c; - } - } - - break; - - default: - throw new _util.FormatError(`Unsupported predictor: ${predictor}`); - } - - this.bufferLength += rowBytes; - } - -} - -exports.PredictorStream = PredictorStream; - -/***/ }), -/* 43 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.RunLengthStream = void 0; - -var _decode_stream = __w_pdfjs_require__(29); - -class RunLengthStream extends _decode_stream.DecodeStream { - constructor(str, maybeLength) { - super(maybeLength); - this.str = str; - this.dict = str.dict; - } - - readBlock() { - const repeatHeader = this.str.getBytes(2); - - if (!repeatHeader || repeatHeader.length < 2 || repeatHeader[0] === 128) { - this.eof = true; - return; - } - - let buffer; - let bufferLength = this.bufferLength; - let n = repeatHeader[0]; - - if (n < 128) { - buffer = this.ensureBuffer(bufferLength + n + 1); - buffer[bufferLength++] = repeatHeader[1]; - - if (n > 0) { - const source = this.str.getBytes(n); - buffer.set(source, bufferLength); - bufferLength += n; - } - } else { - n = 257 - n; - const b = repeatHeader[1]; - buffer = this.ensureBuffer(bufferLength + n + 1); - - for (let i = 0; i < n; i++) { - buffer[bufferLength++] = b; - } - } - - this.bufferLength = bufferLength; - } - -} - -exports.RunLengthStream = RunLengthStream; - -/***/ }), -/* 44 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.Font = exports.ErrorFont = void 0; - -var _util = __w_pdfjs_require__(2); - -var _cff_parser = __w_pdfjs_require__(45); - -var _fonts_utils = __w_pdfjs_require__(18); - -var _glyphlist = __w_pdfjs_require__(20); - -var _encodings = __w_pdfjs_require__(19); - -var _standard_fonts = __w_pdfjs_require__(47); - -var _unicode = __w_pdfjs_require__(21); - -var _to_unicode_map = __w_pdfjs_require__(48); - -var _cff_font = __w_pdfjs_require__(49); - -var _font_renderer = __w_pdfjs_require__(50); - -var _glyf = __w_pdfjs_require__(51); - -var _cmap = __w_pdfjs_require__(26); - -var _opentype_file_builder = __w_pdfjs_require__(52); - -var _core_utils = __w_pdfjs_require__(9); - -var _stream = __w_pdfjs_require__(10); - -var _type1_font = __w_pdfjs_require__(53); - -const PRIVATE_USE_AREAS = [[0xe000, 0xf8ff], [0x100000, 0x10fffd]]; -const PDF_GLYPH_SPACE_UNITS = 1000; -const EXPORT_DATA_PROPERTIES = ["ascent", "bbox", "black", "bold", "charProcOperatorList", "composite", "cssFontInfo", "data", "defaultVMetrics", "defaultWidth", "descent", "fallbackName", "fontMatrix", "fontType", "isType3Font", "italic", "loadedName", "mimetype", "missingFile", "name", "remeasure", "subtype", "type", "vertical"]; -const EXPORT_DATA_EXTRA_PROPERTIES = ["cMap", "defaultEncoding", "differences", "isMonospace", "isSerifFont", "isSymbolicFont", "seacMap", "toFontChar", "toUnicode", "vmetrics", "widths"]; - -function adjustWidths(properties) { - if (!properties.fontMatrix) { - return; - } - - if (properties.fontMatrix[0] === _util.FONT_IDENTITY_MATRIX[0]) { - return; - } - - const scale = 0.001 / properties.fontMatrix[0]; - const glyphsWidths = properties.widths; - - for (const glyph in glyphsWidths) { - glyphsWidths[glyph] *= scale; - } - - properties.defaultWidth *= scale; -} - -function adjustToUnicode(properties, builtInEncoding) { - if (properties.isInternalFont) { - return; - } - - if (builtInEncoding === properties.defaultEncoding) { - return; - } - - if (properties.toUnicode instanceof _to_unicode_map.IdentityToUnicodeMap) { - return; - } - - const toUnicode = [], - glyphsUnicodeMap = (0, _glyphlist.getGlyphsUnicode)(); - - for (const charCode in builtInEncoding) { - if (properties.hasIncludedToUnicodeMap) { - if (properties.toUnicode.has(charCode)) { - continue; - } - } else if (properties.hasEncoding) { - if (properties.differences.length === 0 || properties.differences[charCode] !== undefined) { - continue; - } - } - - const glyphName = builtInEncoding[charCode]; - const unicode = (0, _unicode.getUnicodeForGlyph)(glyphName, glyphsUnicodeMap); - - if (unicode !== -1) { - toUnicode[charCode] = String.fromCharCode(unicode); - } - } - - if (toUnicode.length > 0) { - properties.toUnicode.amend(toUnicode); - } -} - -function amendFallbackToUnicode(properties) { - if (!properties.fallbackToUnicode) { - return; - } - - if (properties.toUnicode instanceof _to_unicode_map.IdentityToUnicodeMap) { - return; - } - - const toUnicode = []; - - for (const charCode in properties.fallbackToUnicode) { - if (properties.toUnicode.has(charCode)) { - continue; - } - - toUnicode[charCode] = properties.fallbackToUnicode[charCode]; - } - - if (toUnicode.length > 0) { - properties.toUnicode.amend(toUnicode); - } -} - -class Glyph { - constructor(originalCharCode, fontChar, unicode, accent, width, vmetric, operatorListId, isSpace, isInFont) { - this.originalCharCode = originalCharCode; - this.fontChar = fontChar; - this.unicode = unicode; - this.accent = accent; - this.width = width; - this.vmetric = vmetric; - this.operatorListId = operatorListId; - this.isSpace = isSpace; - this.isInFont = isInFont; - } - - matchesForCache(originalCharCode, fontChar, unicode, accent, width, vmetric, operatorListId, isSpace, isInFont) { - return this.originalCharCode === originalCharCode && this.fontChar === fontChar && this.unicode === unicode && this.accent === accent && this.width === width && this.vmetric === vmetric && this.operatorListId === operatorListId && this.isSpace === isSpace && this.isInFont === isInFont; - } - -} - -function int16(b0, b1) { - return (b0 << 8) + b1; -} - -function writeSignedInt16(bytes, index, value) { - bytes[index + 1] = value; - bytes[index] = value >>> 8; -} - -function signedInt16(b0, b1) { - const value = (b0 << 8) + b1; - return value & 1 << 15 ? value - 0x10000 : value; -} - -function int32(b0, b1, b2, b3) { - return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3; -} - -function string16(value) { - return String.fromCharCode(value >> 8 & 0xff, value & 0xff); -} - -function safeString16(value) { - if (value > 0x7fff) { - value = 0x7fff; - } else if (value < -0x8000) { - value = -0x8000; - } - - return String.fromCharCode(value >> 8 & 0xff, value & 0xff); -} - -function isTrueTypeFile(file) { - const header = file.peekBytes(4); - return (0, _core_utils.readUint32)(header, 0) === 0x00010000 || (0, _util.bytesToString)(header) === "true"; -} - -function isTrueTypeCollectionFile(file) { - const header = file.peekBytes(4); - return (0, _util.bytesToString)(header) === "ttcf"; -} - -function isOpenTypeFile(file) { - const header = file.peekBytes(4); - return (0, _util.bytesToString)(header) === "OTTO"; -} - -function isType1File(file) { - const header = file.peekBytes(2); - - if (header[0] === 0x25 && header[1] === 0x21) { - return true; - } - - if (header[0] === 0x80 && header[1] === 0x01) { - return true; - } - - return false; -} - -function isCFFFile(file) { - const header = file.peekBytes(4); - - if (header[0] >= 1 && header[3] >= 1 && header[3] <= 4) { - return true; - } - - return false; -} - -function getFontFileType(file, { - type, - subtype, - composite -}) { - let fileType, fileSubtype; - - if (isTrueTypeFile(file) || isTrueTypeCollectionFile(file)) { - if (composite) { - fileType = "CIDFontType2"; - } else { - fileType = "TrueType"; - } - } else if (isOpenTypeFile(file)) { - if (composite) { - fileType = "CIDFontType2"; - } else { - fileType = "OpenType"; - } - } else if (isType1File(file)) { - if (composite) { - fileType = "CIDFontType0"; - } else { - fileType = type === "MMType1" ? "MMType1" : "Type1"; - } - } else if (isCFFFile(file)) { - if (composite) { - fileType = "CIDFontType0"; - fileSubtype = "CIDFontType0C"; - } else { - fileType = type === "MMType1" ? "MMType1" : "Type1"; - fileSubtype = "Type1C"; - } - } else { - (0, _util.warn)("getFontFileType: Unable to detect correct font file Type/Subtype."); - fileType = type; - fileSubtype = subtype; - } - - return [fileType, fileSubtype]; -} - -function applyStandardFontGlyphMap(map, glyphMap) { - for (const charCode in glyphMap) { - map[+charCode] = glyphMap[charCode]; - } -} - -function buildToFontChar(encoding, glyphsUnicodeMap, differences) { - const toFontChar = []; - let unicode; - - for (let i = 0, ii = encoding.length; i < ii; i++) { - unicode = (0, _unicode.getUnicodeForGlyph)(encoding[i], glyphsUnicodeMap); - - if (unicode !== -1) { - toFontChar[i] = unicode; - } - } - - for (const charCode in differences) { - unicode = (0, _unicode.getUnicodeForGlyph)(differences[charCode], glyphsUnicodeMap); - - if (unicode !== -1) { - toFontChar[+charCode] = unicode; - } - } - - return toFontChar; -} - -function convertCidString(charCode, cid, shouldThrow = false) { - switch (cid.length) { - case 1: - return cid.charCodeAt(0); - - case 2: - return cid.charCodeAt(0) << 8 | cid.charCodeAt(1); - } - - const msg = `Unsupported CID string (charCode ${charCode}): "${cid}".`; - - if (shouldThrow) { - throw new _util.FormatError(msg); - } - - (0, _util.warn)(msg); - return cid; -} - -function adjustMapping(charCodeToGlyphId, hasGlyph, newGlyphZeroId) { - const newMap = Object.create(null); - const toFontChar = []; - let privateUseAreaIndex = 0; - let nextAvailableFontCharCode = PRIVATE_USE_AREAS[privateUseAreaIndex][0]; - let privateUseOffetEnd = PRIVATE_USE_AREAS[privateUseAreaIndex][1]; - - for (let originalCharCode in charCodeToGlyphId) { - originalCharCode |= 0; - let glyphId = charCodeToGlyphId[originalCharCode]; - - if (!hasGlyph(glyphId)) { - continue; - } - - if (nextAvailableFontCharCode > privateUseOffetEnd) { - privateUseAreaIndex++; - - if (privateUseAreaIndex >= PRIVATE_USE_AREAS.length) { - (0, _util.warn)("Ran out of space in font private use area."); - break; - } - - nextAvailableFontCharCode = PRIVATE_USE_AREAS[privateUseAreaIndex][0]; - privateUseOffetEnd = PRIVATE_USE_AREAS[privateUseAreaIndex][1]; - } - - const fontCharCode = nextAvailableFontCharCode++; - - if (glyphId === 0) { - glyphId = newGlyphZeroId; - } - - newMap[fontCharCode] = glyphId; - toFontChar[originalCharCode] = fontCharCode; - } - - return { - toFontChar, - charCodeToGlyphId: newMap, - nextAvailableFontCharCode - }; -} - -function getRanges(glyphs, numGlyphs) { - const codes = []; - - for (const charCode in glyphs) { - if (glyphs[charCode] >= numGlyphs) { - continue; - } - - codes.push({ - fontCharCode: charCode | 0, - glyphId: glyphs[charCode] - }); - } - - if (codes.length === 0) { - codes.push({ - fontCharCode: 0, - glyphId: 0 - }); - } - - codes.sort(function fontGetRangesSort(a, b) { - return a.fontCharCode - b.fontCharCode; - }); - const ranges = []; - const length = codes.length; - - for (let n = 0; n < length;) { - const start = codes[n].fontCharCode; - const codeIndices = [codes[n].glyphId]; - ++n; - let end = start; - - while (n < length && end + 1 === codes[n].fontCharCode) { - codeIndices.push(codes[n].glyphId); - ++end; - ++n; - - if (end === 0xffff) { - break; - } - } - - ranges.push([start, end, codeIndices]); - } - - return ranges; -} - -function createCmapTable(glyphs, numGlyphs) { - const ranges = getRanges(glyphs, numGlyphs); - const numTables = ranges[ranges.length - 1][1] > 0xffff ? 2 : 1; - let cmap = "\x00\x00" + string16(numTables) + "\x00\x03" + "\x00\x01" + (0, _util.string32)(4 + numTables * 8); - let i, ii, j, jj; - - for (i = ranges.length - 1; i >= 0; --i) { - if (ranges[i][0] <= 0xffff) { - break; - } - } - - const bmpLength = i + 1; - - if (ranges[i][0] < 0xffff && ranges[i][1] === 0xffff) { - ranges[i][1] = 0xfffe; - } - - const trailingRangesCount = ranges[i][1] < 0xffff ? 1 : 0; - const segCount = bmpLength + trailingRangesCount; - - const searchParams = _opentype_file_builder.OpenTypeFileBuilder.getSearchParams(segCount, 2); - - let startCount = ""; - let endCount = ""; - let idDeltas = ""; - let idRangeOffsets = ""; - let glyphsIds = ""; - let bias = 0; - let range, start, end, codes; - - for (i = 0, ii = bmpLength; i < ii; i++) { - range = ranges[i]; - start = range[0]; - end = range[1]; - startCount += string16(start); - endCount += string16(end); - codes = range[2]; - let contiguous = true; - - for (j = 1, jj = codes.length; j < jj; ++j) { - if (codes[j] !== codes[j - 1] + 1) { - contiguous = false; - break; - } - } - - if (!contiguous) { - const offset = (segCount - i) * 2 + bias * 2; - bias += end - start + 1; - idDeltas += string16(0); - idRangeOffsets += string16(offset); - - for (j = 0, jj = codes.length; j < jj; ++j) { - glyphsIds += string16(codes[j]); - } - } else { - const 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"; - } - - const format314 = "\x00\x00" + string16(2 * segCount) + string16(searchParams.range) + string16(searchParams.entry) + string16(searchParams.rangeShift) + endCount + "\x00\x00" + startCount + idDeltas + idRangeOffsets + glyphsIds; - let format31012 = ""; - let header31012 = ""; - - if (numTables > 1) { - cmap += "\x00\x03" + "\x00\x0A" + (0, _util.string32)(4 + numTables * 8 + 4 + format314.length); - format31012 = ""; - - for (i = 0, ii = ranges.length; i < ii; i++) { - range = ranges[i]; - start = range[0]; - codes = range[2]; - let code = codes[0]; - - for (j = 1, jj = codes.length; j < jj; ++j) { - if (codes[j] !== codes[j - 1] + 1) { - end = range[0] + j - 1; - format31012 += (0, _util.string32)(start) + (0, _util.string32)(end) + (0, _util.string32)(code); - start = end + 1; - code = codes[j]; - } - } - - format31012 += (0, _util.string32)(start) + (0, _util.string32)(range[1]) + (0, _util.string32)(code); - } - - header31012 = "\x00\x0C" + "\x00\x00" + (0, _util.string32)(format31012.length + 16) + "\x00\x00\x00\x00" + (0, _util.string32)(format31012.length / 12); - } - - return cmap + "\x00\x04" + string16(format314.length + 4) + format314 + header31012 + format31012; -} - -function validateOS2Table(os2, file) { - file.pos = (file.start || 0) + os2.offset; - const version = file.getUint16(); - file.skip(60); - const selection = file.getUint16(); - - if (version < 4 && selection & 0x0300) { - return false; - } - - const firstChar = file.getUint16(); - const lastChar = file.getUint16(); - - if (firstChar > lastChar) { - return false; - } - - file.skip(6); - const usWinAscent = file.getUint16(); - - if (usWinAscent === 0) { - return false; - } - - os2.data[8] = os2.data[9] = 0; - return true; -} - -function createOS2Table(properties, charstrings, override) { - override = override || { - unitsPerEm: 0, - yMax: 0, - yMin: 0, - ascent: 0, - descent: 0 - }; - let ulUnicodeRange1 = 0; - let ulUnicodeRange2 = 0; - let ulUnicodeRange3 = 0; - let ulUnicodeRange4 = 0; - let firstCharIndex = null; - let lastCharIndex = 0; - - if (charstrings) { - for (let code in charstrings) { - code |= 0; - - if (firstCharIndex > code || !firstCharIndex) { - firstCharIndex = code; - } - - if (lastCharIndex < code) { - lastCharIndex = code; - } - - const position = (0, _unicode.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 { - throw new _util.FormatError("Unicode ranges Bits > 123 are reserved for internal usage"); - } - } - - if (lastCharIndex > 0xffff) { - lastCharIndex = 0xffff; - } - } else { - firstCharIndex = 0; - lastCharIndex = 255; - } - - const bbox = properties.bbox || [0, 0, 0, 0]; - const unitsPerEm = override.unitsPerEm || 1 / (properties.fontMatrix || _util.FONT_IDENTITY_MATRIX)[0]; - const scale = properties.ascentScaled ? 1.0 : unitsPerEm / PDF_GLYPH_SPACE_UNITS; - const typoAscent = override.ascent || Math.round(scale * (properties.ascent || bbox[3])); - let typoDescent = override.descent || Math.round(scale * (properties.descent || bbox[1])); - - if (typoDescent > 0 && properties.descent > 0 && bbox[1] < 0) { - typoDescent = -typoDescent; - } - - const winAscent = override.yMax || typoAscent; - const winDescent = -override.yMin || -typoDescent; - return "\x00\x03" + "\x02\x24" + "\x01\xF4" + "\x00\x05" + "\x00\x00" + "\x02\x8A" + "\x02\xBB" + "\x00\x00" + "\x00\x8C" + "\x02\x8A" + "\x02\xBB" + "\x00\x00" + "\x01\xDF" + "\x00\x31" + "\x01\x02" + "\x00\x00" + "\x00\x00\x06" + String.fromCharCode(properties.fixedPitch ? 0x09 : 0x00) + "\x00\x00\x00\x00\x00\x00" + (0, _util.string32)(ulUnicodeRange1) + (0, _util.string32)(ulUnicodeRange2) + (0, _util.string32)(ulUnicodeRange3) + (0, _util.string32)(ulUnicodeRange4) + "\x2A\x32\x31\x2A" + string16(properties.italicAngle ? 1 : 0) + string16(firstCharIndex || properties.firstChar) + string16(lastCharIndex || properties.lastChar) + string16(typoAscent) + string16(typoDescent) + "\x00\x64" + string16(winAscent) + string16(winDescent) + "\x00\x00\x00\x00" + "\x00\x00\x00\x00" + string16(properties.xHeight) + string16(properties.capHeight) + string16(0) + string16(firstCharIndex || properties.firstChar) + "\x00\x03"; -} - -function createPostTable(properties) { - const angle = Math.floor(properties.italicAngle * 2 ** 16); - return "\x00\x03\x00\x00" + (0, _util.string32)(angle) + "\x00\x00" + "\x00\x00" + (0, _util.string32)(properties.fixedPitch ? 1 : 0) + "\x00\x00\x00\x00" + "\x00\x00\x00\x00" + "\x00\x00\x00\x00" + "\x00\x00\x00\x00"; -} - -function createPostscriptName(name) { - return name.replace(/[^\x21-\x7E]|[[\](){}<>/%]/g, "").slice(0, 63); -} - -function createNameTable(name, proto) { - if (!proto) { - proto = [[], []]; - } - - const strings = [proto[0][0] || "Original licence", proto[0][1] || name, proto[0][2] || "Unknown", proto[0][3] || "uniqueID", proto[0][4] || name, proto[0][5] || "Version 0.11", proto[0][6] || createPostscriptName(name), proto[0][7] || "Unknown", proto[0][8] || "Unknown", proto[0][9] || "Unknown"]; - const stringsUnicode = []; - let i, ii, j, jj, str; - - for (i = 0, ii = strings.length; i < ii; i++) { - str = proto[1][i] || strings[i]; - const strBufUnicode = []; - - for (j = 0, jj = str.length; j < jj; j++) { - strBufUnicode.push(string16(str.charCodeAt(j))); - } - - stringsUnicode.push(strBufUnicode.join("")); - } - - const names = [strings, stringsUnicode]; - const platforms = ["\x00\x01", "\x00\x03"]; - const encodings = ["\x00\x00", "\x00\x01"]; - const languages = ["\x00\x00", "\x04\x09"]; - const namesRecordCount = strings.length * platforms.length; - let nameTable = "\x00\x00" + string16(namesRecordCount) + string16(namesRecordCount * 12 + 6); - let strOffset = 0; - - for (i = 0, ii = platforms.length; i < ii; i++) { - const strs = names[i]; - - for (j = 0, jj = strs.length; j < jj; j++) { - str = strs[j]; - const nameRecord = platforms[i] + encodings[i] + languages[i] + string16(j) + string16(str.length) + string16(strOffset); - nameTable += nameRecord; - strOffset += str.length; - } - } - - nameTable += strings.join("") + stringsUnicode.join(""); - return nameTable; -} - -class Font { - constructor(name, file, properties) { - this.name = name; - this.psName = null; - this.mimetype = null; - this.disableFontFace = false; - this.loadedName = properties.loadedName; - this.isType3Font = properties.isType3Font; - this.missingFile = false; - this.cssFontInfo = properties.cssFontInfo; - this._charsCache = Object.create(null); - this._glyphCache = Object.create(null); - let isSerifFont = !!(properties.flags & _fonts_utils.FontFlags.Serif); - - if (!isSerifFont && !properties.isSimulatedFlags) { - const baseName = name.replace(/[,_]/g, "-").split("-")[0], - serifFonts = (0, _standard_fonts.getSerifFonts)(); - - for (const namePart of baseName.split("+")) { - if (serifFonts[namePart]) { - isSerifFont = true; - break; - } - } - } - - this.isSerifFont = isSerifFont; - this.isSymbolicFont = !!(properties.flags & _fonts_utils.FontFlags.Symbolic); - this.isMonospace = !!(properties.flags & _fonts_utils.FontFlags.FixedPitch); - let type = properties.type; - let subtype = properties.subtype; - this.type = type; - this.subtype = subtype; - let fallbackName = "sans-serif"; - - if (this.isMonospace) { - fallbackName = "monospace"; - } else if (this.isSerifFont) { - fallbackName = "serif"; - } - - this.fallbackName = fallbackName; - this.differences = properties.differences; - this.widths = properties.widths; - this.defaultWidth = properties.defaultWidth; - this.composite = properties.composite; - this.cMap = properties.cMap; - this.capHeight = properties.capHeight / PDF_GLYPH_SPACE_UNITS; - this.ascent = properties.ascent / PDF_GLYPH_SPACE_UNITS; - this.descent = properties.descent / PDF_GLYPH_SPACE_UNITS; - this.lineHeight = this.ascent - this.descent; - this.fontMatrix = properties.fontMatrix; - this.bbox = properties.bbox; - this.defaultEncoding = properties.defaultEncoding; - this.toUnicode = properties.toUnicode; - this.toFontChar = []; - - if (properties.type === "Type3") { - for (let charCode = 0; charCode < 256; charCode++) { - this.toFontChar[charCode] = this.differences[charCode] || properties.defaultEncoding[charCode]; - } - - this.fontType = _util.FontType.TYPE3; - return; - } - - this.cidEncoding = properties.cidEncoding || ""; - this.vertical = !!properties.vertical; - - if (this.vertical) { - this.vmetrics = properties.vmetrics; - this.defaultVMetrics = properties.defaultVMetrics; - } - - if (!file || file.isEmpty) { - if (file) { - (0, _util.warn)('Font file is empty in "' + name + '" (' + this.loadedName + ")"); - } - - this.fallbackToSystemFont(properties); - return; - } - - [type, subtype] = getFontFileType(file, properties); - - if (type !== this.type || subtype !== this.subtype) { - (0, _util.info)("Inconsistent font file Type/SubType, expected: " + `${this.type}/${this.subtype} but found: ${type}/${subtype}.`); - } - - let data; - - try { - switch (type) { - case "MMType1": - (0, _util.info)("MMType1 font (" + name + "), falling back to Type1."); - - case "Type1": - case "CIDFontType0": - this.mimetype = "font/opentype"; - const cff = subtype === "Type1C" || subtype === "CIDFontType0C" ? new _cff_font.CFFFont(file, properties) : new _type1_font.Type1Font(name, file, properties); - adjustWidths(properties); - data = this.convert(name, cff, properties); - break; - - case "OpenType": - case "TrueType": - case "CIDFontType2": - this.mimetype = "font/opentype"; - data = this.checkAndRepair(name, file, properties); - - if (this.isOpenType) { - adjustWidths(properties); - type = "OpenType"; - } - - break; - - default: - throw new _util.FormatError(`Font ${type} is not supported`); - } - } catch (e) { - (0, _util.warn)(e); - this.fallbackToSystemFont(properties); - return; - } - - amendFallbackToUnicode(properties); - this.data = data; - this.fontType = (0, _fonts_utils.getFontType)(type, subtype, properties.isStandardFont); - this.fontMatrix = properties.fontMatrix; - this.widths = properties.widths; - this.defaultWidth = properties.defaultWidth; - this.toUnicode = properties.toUnicode; - this.seacMap = properties.seacMap; - } - - get renderer() { - const renderer = _font_renderer.FontRendererFactory.create(this, _fonts_utils.SEAC_ANALYSIS_ENABLED); - - return (0, _util.shadow)(this, "renderer", renderer); - } - - exportData(extraProperties = false) { - const exportDataProperties = extraProperties ? [...EXPORT_DATA_PROPERTIES, ...EXPORT_DATA_EXTRA_PROPERTIES] : EXPORT_DATA_PROPERTIES; - const data = Object.create(null); - let property, value; - - for (property of exportDataProperties) { - value = this[property]; - - if (value !== undefined) { - data[property] = value; - } - } - - return data; - } - - fallbackToSystemFont(properties) { - this.missingFile = true; - const name = this.name; - const type = this.type; - const subtype = this.subtype; - let fontName = (0, _fonts_utils.normalizeFontName)(name); - const stdFontMap = (0, _standard_fonts.getStdFontMap)(), - nonStdFontMap = (0, _standard_fonts.getNonStdFontMap)(); - const isStandardFont = !!stdFontMap[fontName]; - const isMappedToStandardFont = !!(nonStdFontMap[fontName] && stdFontMap[nonStdFontMap[fontName]]); - fontName = stdFontMap[fontName] || nonStdFontMap[fontName] || fontName; - this.bold = fontName.search(/bold/gi) !== -1; - this.italic = fontName.search(/oblique/gi) !== -1 || fontName.search(/italic/gi) !== -1; - this.black = name.search(/Black/g) !== -1; - const isNarrow = name.search(/Narrow/g) !== -1; - this.remeasure = (!isStandardFont || isNarrow) && Object.keys(this.widths).length > 0; - - if ((isStandardFont || isMappedToStandardFont) && type === "CIDFontType2" && this.cidEncoding.startsWith("Identity-")) { - const cidToGidMap = properties.cidToGidMap; - const map = []; - applyStandardFontGlyphMap(map, (0, _standard_fonts.getGlyphMapForStandardFonts)()); - - if (/Arial-?Black/i.test(name)) { - applyStandardFontGlyphMap(map, (0, _standard_fonts.getSupplementalGlyphMapForArialBlack)()); - } else if (/Calibri/i.test(name)) { - applyStandardFontGlyphMap(map, (0, _standard_fonts.getSupplementalGlyphMapForCalibri)()); - } - - if (cidToGidMap) { - for (const charCode in map) { - const cid = map[charCode]; - - if (cidToGidMap[cid] !== undefined) { - map[+charCode] = cidToGidMap[cid]; - } - } - - if (cidToGidMap.length !== this.toUnicode.length && properties.hasIncludedToUnicodeMap && this.toUnicode instanceof _to_unicode_map.IdentityToUnicodeMap) { - this.toUnicode.forEach(function (charCode, unicodeCharCode) { - const cid = map[charCode]; - - if (cidToGidMap[cid] === undefined) { - map[+charCode] = unicodeCharCode; - } - }); - } - } - - if (!(this.toUnicode instanceof _to_unicode_map.IdentityToUnicodeMap)) { - this.toUnicode.forEach(function (charCode, unicodeCharCode) { - map[+charCode] = unicodeCharCode; - }); - } - - this.toFontChar = map; - this.toUnicode = new _to_unicode_map.ToUnicodeMap(map); - } else if (/Symbol/i.test(fontName)) { - this.toFontChar = buildToFontChar(_encodings.SymbolSetEncoding, (0, _glyphlist.getGlyphsUnicode)(), this.differences); - } else if (/Dingbats/i.test(fontName)) { - if (/Wingdings/i.test(name)) { - (0, _util.warn)("Non-embedded Wingdings font, falling back to ZapfDingbats."); - } - - this.toFontChar = buildToFontChar(_encodings.ZapfDingbatsEncoding, (0, _glyphlist.getDingbatsGlyphsUnicode)(), this.differences); - } else if (isStandardFont) { - const map = buildToFontChar(this.defaultEncoding, (0, _glyphlist.getGlyphsUnicode)(), this.differences); - - if (type === "CIDFontType2" && !this.cidEncoding.startsWith("Identity-") && !(this.toUnicode instanceof _to_unicode_map.IdentityToUnicodeMap)) { - this.toUnicode.forEach(function (charCode, unicodeCharCode) { - map[+charCode] = unicodeCharCode; - }); - } - - this.toFontChar = map; - } else { - const glyphsUnicodeMap = (0, _glyphlist.getGlyphsUnicode)(); - const map = []; - this.toUnicode.forEach((charCode, unicodeCharCode) => { - if (!this.composite) { - const glyphName = this.differences[charCode] || this.defaultEncoding[charCode]; - const unicode = (0, _unicode.getUnicodeForGlyph)(glyphName, glyphsUnicodeMap); - - if (unicode !== -1) { - unicodeCharCode = unicode; - } - } - - map[+charCode] = unicodeCharCode; - }); - - if (this.composite && this.toUnicode instanceof _to_unicode_map.IdentityToUnicodeMap) { - if (/Verdana/i.test(name)) { - applyStandardFontGlyphMap(map, (0, _standard_fonts.getGlyphMapForStandardFonts)()); - } - } - - this.toFontChar = map; - } - - amendFallbackToUnicode(properties); - this.loadedName = fontName.split("-")[0]; - this.fontType = (0, _fonts_utils.getFontType)(type, subtype, properties.isStandardFont); - } - - checkAndRepair(name, font, properties) { - const VALID_TABLES = ["OS/2", "cmap", "head", "hhea", "hmtx", "maxp", "name", "post", "loca", "glyf", "fpgm", "prep", "cvt ", "CFF "]; - - function readTables(file, numTables) { - const tables = Object.create(null); - tables["OS/2"] = null; - tables.cmap = null; - tables.head = null; - tables.hhea = null; - tables.hmtx = null; - tables.maxp = null; - tables.name = null; - tables.post = null; - - for (let i = 0; i < numTables; i++) { - const table = readTableEntry(file); - - if (!VALID_TABLES.includes(table.tag)) { - continue; - } - - if (table.length === 0) { - continue; - } - - tables[table.tag] = table; - } - - return tables; - } - - function readTableEntry(file) { - const tag = file.getString(4); - const checksum = file.getInt32() >>> 0; - const offset = file.getInt32() >>> 0; - const length = file.getInt32() >>> 0; - const previousPosition = file.pos; - file.pos = file.start ? file.start : 0; - file.skip(offset); - const data = file.getBytes(length); - file.pos = previousPosition; - - if (tag === "head") { - data[8] = data[9] = data[10] = data[11] = 0; - data[17] |= 0x20; - } - - return { - tag, - checksum, - length, - offset, - data - }; - } - - function readOpenTypeHeader(ttf) { - return { - version: ttf.getString(4), - numTables: ttf.getUint16(), - searchRange: ttf.getUint16(), - entrySelector: ttf.getUint16(), - rangeShift: ttf.getUint16() - }; - } - - function readTrueTypeCollectionHeader(ttc) { - const ttcTag = ttc.getString(4); - (0, _util.assert)(ttcTag === "ttcf", "Must be a TrueType Collection font."); - const majorVersion = ttc.getUint16(); - const minorVersion = ttc.getUint16(); - const numFonts = ttc.getInt32() >>> 0; - const offsetTable = []; - - for (let i = 0; i < numFonts; i++) { - offsetTable.push(ttc.getInt32() >>> 0); - } - - const header = { - ttcTag, - majorVersion, - minorVersion, - numFonts, - offsetTable - }; - - switch (majorVersion) { - case 1: - return header; - - case 2: - header.dsigTag = ttc.getInt32() >>> 0; - header.dsigLength = ttc.getInt32() >>> 0; - header.dsigOffset = ttc.getInt32() >>> 0; - return header; - } - - throw new _util.FormatError(`Invalid TrueType Collection majorVersion: ${majorVersion}.`); - } - - function readTrueTypeCollectionData(ttc, fontName) { - const { - numFonts, - offsetTable - } = readTrueTypeCollectionHeader(ttc); - const fontNameParts = fontName.split("+"); - let fallbackData; - - for (let i = 0; i < numFonts; i++) { - ttc.pos = (ttc.start || 0) + offsetTable[i]; - const potentialHeader = readOpenTypeHeader(ttc); - const potentialTables = readTables(ttc, potentialHeader.numTables); - - if (!potentialTables.name) { - throw new _util.FormatError('TrueType Collection font must contain a "name" table.'); - } - - const nameTable = readNameTable(potentialTables.name); - - for (let j = 0, jj = nameTable.length; j < jj; j++) { - for (let k = 0, kk = nameTable[j].length; k < kk; k++) { - const nameEntry = nameTable[j][k] && nameTable[j][k].replace(/\s/g, ""); - - if (!nameEntry) { - continue; - } - - if (nameEntry === fontName) { - return { - header: potentialHeader, - tables: potentialTables - }; - } - - if (fontNameParts.length < 2) { - continue; - } - - for (const part of fontNameParts) { - if (nameEntry === part) { - fallbackData = { - name: part, - header: potentialHeader, - tables: potentialTables - }; - } - } - } - } - } - - if (fallbackData) { - (0, _util.warn)(`TrueType Collection does not contain "${fontName}" font, ` + `falling back to "${fallbackData.name}" font instead.`); - return { - header: fallbackData.header, - tables: fallbackData.tables - }; - } - - throw new _util.FormatError(`TrueType Collection does not contain "${fontName}" font.`); - } - - function readCmapTable(cmap, file, isSymbolicFont, hasEncoding) { - if (!cmap) { - (0, _util.warn)("No cmap table available."); - return { - platformId: -1, - encodingId: -1, - mappings: [], - hasShortCmap: false - }; - } - - let segment; - let start = (file.start ? file.start : 0) + cmap.offset; - file.pos = start; - file.skip(2); - const numTables = file.getUint16(); - let potentialTable; - let canBreak = false; - - for (let i = 0; i < numTables; i++) { - const platformId = file.getUint16(); - const encodingId = file.getUint16(); - const offset = file.getInt32() >>> 0; - let useTable = false; - - if (potentialTable && potentialTable.platformId === platformId && potentialTable.encodingId === encodingId) { - continue; - } - - if (platformId === 0 && (encodingId === 0 || encodingId === 1 || encodingId === 3)) { - useTable = true; - } else if (platformId === 1 && encodingId === 0) { - useTable = true; - } else if (platformId === 3 && encodingId === 1 && (hasEncoding || !potentialTable)) { - useTable = true; - - if (!isSymbolicFont) { - canBreak = true; - } - } else if (isSymbolicFont && platformId === 3 && encodingId === 0) { - useTable = true; - let correctlySorted = true; - - if (i < numTables - 1) { - const nextBytes = file.peekBytes(2), - nextPlatformId = int16(nextBytes[0], nextBytes[1]); - - if (nextPlatformId < platformId) { - correctlySorted = false; - } - } - - if (correctlySorted) { - canBreak = true; - } - } - - if (useTable) { - potentialTable = { - platformId, - encodingId, - offset - }; - } - - if (canBreak) { - break; - } - } - - if (potentialTable) { - file.pos = start + potentialTable.offset; - } - - if (!potentialTable || file.peekByte() === -1) { - (0, _util.warn)("Could not find a preferred cmap table."); - return { - platformId: -1, - encodingId: -1, - mappings: [], - hasShortCmap: false - }; - } - - const format = file.getUint16(); - file.skip(2 + 2); - let hasShortCmap = false; - const mappings = []; - let j, glyphId; - - if (format === 0) { - for (j = 0; j < 256; j++) { - const index = file.getByte(); - - if (!index) { - continue; - } - - mappings.push({ - charCode: j, - glyphId: index - }); - } - - hasShortCmap = true; - } else if (format === 2) { - const subHeaderKeys = []; - let maxSubHeaderKey = 0; - - for (let i = 0; i < 256; i++) { - const subHeaderKey = file.getUint16() >> 3; - subHeaderKeys.push(subHeaderKey); - maxSubHeaderKey = Math.max(subHeaderKey, maxSubHeaderKey); - } - - const subHeaders = []; - - for (let i = 0; i <= maxSubHeaderKey; i++) { - subHeaders.push({ - firstCode: file.getUint16(), - entryCount: file.getUint16(), - idDelta: signedInt16(file.getByte(), file.getByte()), - idRangePos: file.pos + file.getUint16() - }); - } - - for (let i = 0; i < 256; i++) { - if (subHeaderKeys[i] === 0) { - file.pos = subHeaders[0].idRangePos + 2 * i; - glyphId = file.getUint16(); - mappings.push({ - charCode: i, - glyphId - }); - } else { - const s = subHeaders[subHeaderKeys[i]]; - - for (j = 0; j < s.entryCount; j++) { - const charCode = (i << 8) + j + s.firstCode; - file.pos = s.idRangePos + 2 * j; - glyphId = file.getUint16(); - - if (glyphId !== 0) { - glyphId = (glyphId + s.idDelta) % 65536; - } - - mappings.push({ - charCode, - glyphId - }); - } - } - } - } else if (format === 4) { - const segCount = file.getUint16() >> 1; - file.skip(6); - const segments = []; - let segIndex; - - for (segIndex = 0; segIndex < segCount; segIndex++) { - segments.push({ - end: file.getUint16() - }); - } - - file.skip(2); - - for (segIndex = 0; segIndex < segCount; segIndex++) { - segments[segIndex].start = file.getUint16(); - } - - for (segIndex = 0; segIndex < segCount; segIndex++) { - segments[segIndex].delta = file.getUint16(); - } - - let offsetsCount = 0, - offsetIndex; - - for (segIndex = 0; segIndex < segCount; segIndex++) { - segment = segments[segIndex]; - const rangeOffset = file.getUint16(); - - if (!rangeOffset) { - segment.offsetIndex = -1; - continue; - } - - offsetIndex = (rangeOffset >> 1) - (segCount - segIndex); - segment.offsetIndex = offsetIndex; - offsetsCount = Math.max(offsetsCount, offsetIndex + segment.end - segment.start + 1); - } - - const offsets = []; - - for (j = 0; j < offsetsCount; j++) { - offsets.push(file.getUint16()); - } - - for (segIndex = 0; segIndex < segCount; segIndex++) { - segment = segments[segIndex]; - start = segment.start; - const end = segment.end; - const delta = segment.delta; - offsetIndex = segment.offsetIndex; - - for (j = start; j <= end; j++) { - if (j === 0xffff) { - continue; - } - - glyphId = offsetIndex < 0 ? j : offsets[offsetIndex + j - start]; - glyphId = glyphId + delta & 0xffff; - mappings.push({ - charCode: j, - glyphId - }); - } - } - } else if (format === 6) { - const firstCode = file.getUint16(); - const entryCount = file.getUint16(); - - for (j = 0; j < entryCount; j++) { - glyphId = file.getUint16(); - const charCode = firstCode + j; - mappings.push({ - charCode, - glyphId - }); - } - } else { - (0, _util.warn)("cmap table has unsupported format: " + format); - return { - platformId: -1, - encodingId: -1, - mappings: [], - hasShortCmap: false - }; - } - - mappings.sort(function (a, b) { - return a.charCode - b.charCode; - }); - - for (let i = 1; i < mappings.length; i++) { - if (mappings[i - 1].charCode === mappings[i].charCode) { - mappings.splice(i, 1); - i--; - } - } - - return { - platformId: potentialTable.platformId, - encodingId: potentialTable.encodingId, - mappings, - hasShortCmap - }; - } - - function sanitizeMetrics(file, header, metrics, headTable, numGlyphs, dupFirstEntry) { - if (!header) { - if (metrics) { - metrics.data = null; - } - - return; - } - - file.pos = (file.start ? file.start : 0) + header.offset; - file.pos += 4; - file.pos += 2; - file.pos += 2; - file.pos += 2; - file.pos += 2; - file.pos += 2; - file.pos += 2; - file.pos += 2; - file.pos += 2; - file.pos += 2; - const caretOffset = file.getUint16(); - file.pos += 8; - file.pos += 2; - let numOfMetrics = file.getUint16(); - - if (caretOffset !== 0) { - const macStyle = int16(headTable.data[44], headTable.data[45]); - - if (!(macStyle & 2)) { - header.data[22] = 0; - header.data[23] = 0; - } - } - - if (numOfMetrics > numGlyphs) { - (0, _util.info)(`The numOfMetrics (${numOfMetrics}) should not be ` + `greater than the numGlyphs (${numGlyphs}).`); - numOfMetrics = numGlyphs; - header.data[34] = (numOfMetrics & 0xff00) >> 8; - header.data[35] = numOfMetrics & 0x00ff; - } - - const numOfSidebearings = numGlyphs - numOfMetrics; - const numMissing = numOfSidebearings - (metrics.length - numOfMetrics * 4 >> 1); - - if (numMissing > 0) { - const entries = new Uint8Array(metrics.length + numMissing * 2); - entries.set(metrics.data); - - if (dupFirstEntry) { - entries[metrics.length] = metrics.data[2]; - entries[metrics.length + 1] = metrics.data[3]; - } - - metrics.data = entries; - } - } - - function sanitizeGlyph(source, sourceStart, sourceEnd, dest, destStart, hintsValid) { - const glyphProfile = { - length: 0, - sizeOfInstructions: 0 - }; - - if (sourceEnd - sourceStart <= 12) { - return glyphProfile; - } - - const glyf = source.subarray(sourceStart, sourceEnd); - let contoursCount = signedInt16(glyf[0], glyf[1]); - - if (contoursCount < 0) { - contoursCount = -1; - writeSignedInt16(glyf, 0, contoursCount); - dest.set(glyf, destStart); - glyphProfile.length = glyf.length; - return glyphProfile; - } - - let i, - j = 10, - flagsCount = 0; - - for (i = 0; i < contoursCount; i++) { - const endPoint = glyf[j] << 8 | glyf[j + 1]; - flagsCount = endPoint + 1; - j += 2; - } - - const instructionsStart = j; - const instructionsLength = glyf[j] << 8 | glyf[j + 1]; - glyphProfile.sizeOfInstructions = instructionsLength; - j += 2 + instructionsLength; - const instructionsEnd = j; - let coordinatesLength = 0; - - for (i = 0; i < flagsCount; i++) { - const flag = glyf[j++]; - - if (flag & 0xc0) { - glyf[j - 1] = flag & 0x3f; - } - - let xLength = 2; - - if (flag & 2) { - xLength = 1; - } else if (flag & 16) { - xLength = 0; - } - - let yLength = 2; - - if (flag & 4) { - yLength = 1; - } else if (flag & 32) { - yLength = 0; - } - - const xyLength = xLength + yLength; - coordinatesLength += xyLength; - - if (flag & 8) { - const repeat = glyf[j++]; - i += repeat; - coordinatesLength += repeat * xyLength; - } - } - - if (coordinatesLength === 0) { - return glyphProfile; - } - - let glyphDataLength = j + coordinatesLength; - - if (glyphDataLength > glyf.length) { - return glyphProfile; - } - - 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; - } - - glyphProfile.length = glyphDataLength; - return glyphProfile; - } - - if (glyf.length - glyphDataLength > 3) { - glyphDataLength = glyphDataLength + 3 & ~3; - dest.set(glyf.subarray(0, glyphDataLength), destStart); - glyphProfile.length = glyphDataLength; - return glyphProfile; - } - - dest.set(glyf, destStart); - glyphProfile.length = glyf.length; - return glyphProfile; - } - - function sanitizeHead(head, numGlyphs, locaLength) { - const data = head.data; - const version = int32(data[0], data[1], data[2], data[3]); - - if (version >> 16 !== 1) { - (0, _util.info)("Attempting to fix invalid version in head table: " + version); - data[0] = 0; - data[1] = 1; - data[2] = 0; - data[3] = 0; - } - - const indexToLocFormat = int16(data[50], data[51]); - - if (indexToLocFormat < 0 || indexToLocFormat > 1) { - (0, _util.info)("Attempting to fix invalid indexToLocFormat in head table: " + indexToLocFormat); - const numGlyphsPlusOne = numGlyphs + 1; - - if (locaLength === numGlyphsPlusOne << 1) { - data[50] = 0; - data[51] = 0; - } else if (locaLength === numGlyphsPlusOne << 2) { - data[50] = 0; - data[51] = 1; - } else { - throw new _util.FormatError("Could not fix indexToLocFormat: " + indexToLocFormat); - } - } - } - - function sanitizeGlyphLocations(loca, glyf, numGlyphs, isGlyphLocationsLong, hintsValid, dupFirstEntry, maxSizeOfInstructions) { - let 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; - }; - } - - const numGlyphsOut = dupFirstEntry ? numGlyphs + 1 : numGlyphs; - const locaDataSize = itemSize * (1 + numGlyphsOut); - const locaData = new Uint8Array(locaDataSize); - locaData.set(loca.data.subarray(0, locaDataSize)); - loca.data = locaData; - const oldGlyfData = glyf.data; - const oldGlyfDataLength = oldGlyfData.length; - const newGlyfData = new Uint8Array(oldGlyfDataLength); - let i, j; - const locaEntries = []; - - for (i = 0, j = 0; i < numGlyphs + 1; i++, j += itemSize) { - let offset = itemDecode(locaData, j); - - if (offset > oldGlyfDataLength) { - offset = oldGlyfDataLength; - } - - locaEntries.push({ - index: i, - offset, - endOffset: 0 - }); - } - - locaEntries.sort((a, b) => { - return a.offset - b.offset; - }); - - for (i = 0; i < numGlyphs; i++) { - locaEntries[i].endOffset = locaEntries[i + 1].offset; - } - - locaEntries.sort((a, b) => { - return a.index - b.index; - }); - const missingGlyphs = Object.create(null); - let writeOffset = 0; - itemEncode(locaData, 0, writeOffset); - - for (i = 0, j = itemSize; i < numGlyphs; i++, j += itemSize) { - const glyphProfile = sanitizeGlyph(oldGlyfData, locaEntries[i].offset, locaEntries[i].endOffset, newGlyfData, writeOffset, hintsValid); - const newLength = glyphProfile.length; - - if (newLength === 0) { - missingGlyphs[i] = true; - } - - if (glyphProfile.sizeOfInstructions > maxSizeOfInstructions) { - maxSizeOfInstructions = glyphProfile.sizeOfInstructions; - } - - writeOffset += newLength; - itemEncode(locaData, j, writeOffset); - } - - if (writeOffset === 0) { - const simpleGlyph = new Uint8Array([0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 0]); - - for (i = 0, j = itemSize; i < numGlyphsOut; i++, j += itemSize) { - itemEncode(locaData, j, simpleGlyph.length); - } - - glyf.data = simpleGlyph; - } else if (dupFirstEntry) { - const firstEntryLength = itemDecode(locaData, itemSize); - - if (newGlyfData.length > firstEntryLength + writeOffset) { - glyf.data = newGlyfData.subarray(0, firstEntryLength + writeOffset); - } else { - glyf.data = new Uint8Array(firstEntryLength + writeOffset); - glyf.data.set(newGlyfData.subarray(0, writeOffset)); - } - - glyf.data.set(newGlyfData.subarray(0, firstEntryLength), writeOffset); - itemEncode(loca.data, locaData.length - itemSize, writeOffset + firstEntryLength); - } else { - glyf.data = newGlyfData.subarray(0, writeOffset); - } - - return { - missingGlyphs, - maxSizeOfInstructions - }; - } - - function readPostScriptTable(post, propertiesObj, maxpNumGlyphs) { - const start = (font.start ? font.start : 0) + post.offset; - font.pos = start; - const length = post.length, - end = start + length; - const version = font.getInt32(); - font.skip(28); - let glyphNames; - let valid = true; - let i; - - switch (version) { - case 0x00010000: - glyphNames = _fonts_utils.MacStandardGlyphOrdering; - break; - - case 0x00020000: - const numGlyphs = font.getUint16(); - - if (numGlyphs !== maxpNumGlyphs) { - valid = false; - break; - } - - const glyphNameIndexes = []; - - for (i = 0; i < numGlyphs; ++i) { - const index = font.getUint16(); - - if (index >= 32768) { - valid = false; - break; - } - - glyphNameIndexes.push(index); - } - - if (!valid) { - break; - } - - const customNames = [], - strBuf = []; - - while (font.pos < end) { - const stringLength = font.getByte(); - strBuf.length = stringLength; - - for (i = 0; i < stringLength; ++i) { - strBuf[i] = String.fromCharCode(font.getByte()); - } - - customNames.push(strBuf.join("")); - } - - glyphNames = []; - - for (i = 0; i < numGlyphs; ++i) { - const j = glyphNameIndexes[i]; - - if (j < 258) { - glyphNames.push(_fonts_utils.MacStandardGlyphOrdering[j]); - continue; - } - - glyphNames.push(customNames[j - 258]); - } - - break; - - case 0x00030000: - break; - - default: - (0, _util.warn)("Unknown/unsupported post table version " + version); - valid = false; - - if (propertiesObj.defaultEncoding) { - glyphNames = propertiesObj.defaultEncoding; - } - - break; - } - - propertiesObj.glyphNames = glyphNames; - return valid; - } - - function readNameTable(nameTable) { - const start = (font.start ? font.start : 0) + nameTable.offset; - font.pos = start; - const names = [[], []]; - const length = nameTable.length, - end = start + length; - const format = font.getUint16(); - const FORMAT_0_HEADER_LENGTH = 6; - - if (format !== 0 || length < FORMAT_0_HEADER_LENGTH) { - return names; - } - - const numRecords = font.getUint16(); - const stringsStart = font.getUint16(); - const records = []; - const NAME_RECORD_LENGTH = 12; - let i, ii; - - for (i = 0; i < numRecords && font.pos + NAME_RECORD_LENGTH <= end; i++) { - const r = { - platform: font.getUint16(), - encoding: font.getUint16(), - language: font.getUint16(), - name: font.getUint16(), - length: font.getUint16(), - offset: font.getUint16() - }; - - if (r.platform === 1 && r.encoding === 0 && r.language === 0 || r.platform === 3 && r.encoding === 1 && r.language === 0x409) { - records.push(r); - } - } - - for (i = 0, ii = records.length; i < ii; i++) { - const record = records[i]; - - if (record.length <= 0) { - continue; - } - - const pos = start + stringsStart + record.offset; - - if (pos + record.length > end) { - continue; - } - - font.pos = pos; - const nameIndex = record.name; - - if (record.encoding) { - let str = ""; - - for (let j = 0, jj = record.length; j < jj; j += 2) { - str += String.fromCharCode(font.getUint16()); - } - - names[1][nameIndex] = str; - } else { - names[0][nameIndex] = font.getString(record.length); - } - } - - return names; - } - - const 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]; - - function sanitizeTTProgram(table, ttContext) { - let data = table.data; - let i = 0, - j, - n, - b, - funcId, - pc, - lastEndf = 0, - lastDeff = 0; - const stack = []; - const callstack = []; - const functionsCalled = []; - let tooComplexToFollowFunctions = ttContext.tooComplexToFollowFunctions; - let inFDEF = false, - ifLevel = 0, - inELSE = 0; - - for (let ii = data.length; i < ii;) { - const op = data[i++]; - - if (op === 0x40) { - n = data[i++]; - - if (inFDEF || inELSE) { - i += n; - } else { - for (j = 0; j < n; j++) { - stack.push(data[i++]); - } - } - } else if (op === 0x41) { - n = data[i++]; - - if (inFDEF || inELSE) { - i += n * 2; - } else { - for (j = 0; j < n; j++) { - b = data[i++]; - stack.push(b << 8 | data[i++]); - } - } - } else if ((op & 0xf8) === 0xb0) { - n = op - 0xb0 + 1; - - if (inFDEF || inELSE) { - i += n; - } else { - for (j = 0; j < n; j++) { - stack.push(data[i++]); - } - } - } else if ((op & 0xf8) === 0xb8) { - n = op - 0xb8 + 1; - - if (inFDEF || inELSE) { - i += n * 2; - } else { - for (j = 0; j < n; j++) { - b = data[i++]; - stack.push(b << 8 | data[i++]); - } - } - } else if (op === 0x2b && !tooComplexToFollowFunctions) { - if (!inFDEF && !inELSE) { - funcId = stack[stack.length - 1]; - - if (isNaN(funcId)) { - (0, _util.info)("TT: CALL empty stack (or invalid entry)."); - } else { - ttContext.functionsUsed[funcId] = true; - - if (funcId in ttContext.functionsStackDeltas) { - const newStackLength = stack.length + ttContext.functionsStackDeltas[funcId]; - - if (newStackLength < 0) { - (0, _util.warn)("TT: CALL invalid functions stack delta."); - ttContext.hintsValid = false; - return; - } - - stack.length = newStackLength; - } else if (funcId in ttContext.functionsDefined && !functionsCalled.includes(funcId)) { - callstack.push({ - data, - i, - stackTop: stack.length - 1 - }); - functionsCalled.push(funcId); - pc = ttContext.functionsDefined[funcId]; - - if (!pc) { - (0, _util.warn)("TT: CALL non-existent function"); - ttContext.hintsValid = false; - return; - } - - data = pc.data; - i = pc.i; - } - } - } - } else if (op === 0x2c && !tooComplexToFollowFunctions) { - if (inFDEF || inELSE) { - (0, _util.warn)("TT: nested FDEFs not allowed"); - tooComplexToFollowFunctions = true; - } - - inFDEF = true; - lastDeff = i; - funcId = stack.pop(); - ttContext.functionsDefined[funcId] = { - data, - i - }; - } else if (op === 0x2d) { - if (inFDEF) { - inFDEF = false; - lastEndf = i; - } else { - pc = callstack.pop(); - - if (!pc) { - (0, _util.warn)("TT: ENDF bad stack"); - ttContext.hintsValid = false; - return; - } - - funcId = functionsCalled.pop(); - data = pc.data; - i = pc.i; - ttContext.functionsStackDeltas[funcId] = stack.length - pc.stackTop; - } - } else if (op === 0x89) { - if (inFDEF || inELSE) { - (0, _util.warn)("TT: nested IDEFs not allowed"); - tooComplexToFollowFunctions = true; - } - - inFDEF = true; - lastDeff = i; - } else if (op === 0x58) { - ++ifLevel; - } else if (op === 0x1b) { - inELSE = ifLevel; - } else if (op === 0x59) { - if (inELSE === ifLevel) { - inELSE = 0; - } - - --ifLevel; - } else if (op === 0x1c) { - if (!inFDEF && !inELSE) { - const offset = stack[stack.length - 1]; - - if (offset > 0) { - i += offset - 1; - } - } - } - - if (!inFDEF && !inELSE) { - let stackDelta = 0; - - if (op <= 0x8e) { - stackDelta = TTOpsStackDeltas[op]; - } else if (op >= 0xc0 && op <= 0xdf) { - stackDelta = -1; - } else if (op >= 0xe0) { - stackDelta = -2; - } - - if (op >= 0x71 && op <= 0x75) { - n = stack.pop(); - - if (!isNaN(n)) { - stackDelta = -n * 2; - } - } - - while (stackDelta < 0 && stack.length > 0) { - stack.pop(); - stackDelta++; - } - - while (stackDelta > 0) { - stack.push(NaN); - stackDelta--; - } - } - } - - ttContext.tooComplexToFollowFunctions = tooComplexToFollowFunctions; - const content = [data]; - - if (i > data.length) { - content.push(new Uint8Array(i - data.length)); - } - - if (lastDeff > lastEndf) { - (0, _util.warn)("TT: complementing a missing function tail"); - content.push(new Uint8Array([0x22, 0x2d])); - } - - foldTTTable(table, content); - } - - function checkInvalidFunctions(ttContext, maxFunctionDefs) { - if (ttContext.tooComplexToFollowFunctions) { - return; - } - - if (ttContext.functionsDefined.length > maxFunctionDefs) { - (0, _util.warn)("TT: more functions defined than expected"); - ttContext.hintsValid = false; - return; - } - - for (let j = 0, jj = ttContext.functionsUsed.length; j < jj; j++) { - if (j > maxFunctionDefs) { - (0, _util.warn)("TT: invalid function id: " + j); - ttContext.hintsValid = false; - return; - } - - if (ttContext.functionsUsed[j] && !ttContext.functionsDefined[j]) { - (0, _util.warn)("TT: undefined function: " + j); - ttContext.hintsValid = false; - return; - } - } - } - - function foldTTTable(table, content) { - if (content.length > 1) { - let newLength = 0; - let j, jj; - - for (j = 0, jj = content.length; j < jj; j++) { - newLength += content[j].length; - } - - newLength = newLength + 3 & ~3; - const result = new Uint8Array(newLength); - let pos = 0; - - for (j = 0, jj = content.length; j < jj; j++) { - result.set(content[j], pos); - pos += content[j].length; - } - - table.data = result; - table.length = newLength; - } - } - - function sanitizeTTPrograms(fpgm, prep, cvt, maxFunctionDefs) { - const ttContext = { - functionsDefined: [], - functionsUsed: [], - functionsStackDeltas: [], - tooComplexToFollowFunctions: false, - hintsValid: true - }; - - if (fpgm) { - sanitizeTTProgram(fpgm, ttContext); - } - - if (prep) { - sanitizeTTProgram(prep, ttContext); - } - - if (fpgm) { - checkInvalidFunctions(ttContext, maxFunctionDefs); - } - - if (cvt && cvt.length & 1) { - const cvtData = new Uint8Array(cvt.length + 1); - cvtData.set(cvt.data); - cvt.data = cvtData; - } - - return ttContext.hintsValid; - } - - font = new _stream.Stream(new Uint8Array(font.getBytes())); - let header, tables; - - if (isTrueTypeCollectionFile(font)) { - const ttcData = readTrueTypeCollectionData(font, this.name); - header = ttcData.header; - tables = ttcData.tables; - } else { - header = readOpenTypeHeader(font); - tables = readTables(font, header.numTables); - } - - let cff, cffFile; - const isTrueType = !tables["CFF "]; - - if (!isTrueType) { - const isComposite = properties.composite && ((properties.cidToGidMap || []).length > 0 || !(properties.cMap instanceof _cmap.IdentityCMap)); - - if (header.version === "OTTO" && !isComposite || !tables.head || !tables.hhea || !tables.maxp || !tables.post) { - cffFile = new _stream.Stream(tables["CFF "].data); - cff = new _cff_font.CFFFont(cffFile, properties); - adjustWidths(properties); - return this.convert(name, cff, properties); - } - - delete tables.glyf; - delete tables.loca; - delete tables.fpgm; - delete tables.prep; - delete tables["cvt "]; - this.isOpenType = true; - } else { - if (!tables.loca) { - throw new _util.FormatError('Required "loca" table is not found'); - } - - if (!tables.glyf) { - (0, _util.warn)('Required "glyf" table is not found -- trying to recover.'); - tables.glyf = { - tag: "glyf", - data: new Uint8Array(0) - }; - } - - this.isOpenType = false; - } - - if (!tables.maxp) { - throw new _util.FormatError('Required "maxp" table is not found'); - } - - font.pos = (font.start || 0) + tables.maxp.offset; - const version = font.getInt32(); - const numGlyphs = font.getUint16(); - - if (properties.scaleFactors && properties.scaleFactors.length === numGlyphs && isTrueType) { - const { - scaleFactors - } = properties; - const isGlyphLocationsLong = int16(tables.head.data[50], tables.head.data[51]); - const glyphs = new _glyf.GlyfTable({ - glyfTable: tables.glyf.data, - isGlyphLocationsLong, - locaTable: tables.loca.data, - numGlyphs - }); - glyphs.scale(scaleFactors); - const { - glyf, - loca, - isLocationLong - } = glyphs.write(); - tables.glyf.data = glyf; - tables.loca.data = loca; - - if (isLocationLong !== !!isGlyphLocationsLong) { - tables.head.data[50] = 0; - tables.head.data[51] = isLocationLong ? 1 : 0; - } - - const metrics = tables.hmtx.data; - - for (let i = 0; i < numGlyphs; i++) { - const j = 4 * i; - const advanceWidth = Math.round(scaleFactors[i] * int16(metrics[j], metrics[j + 1])); - metrics[j] = advanceWidth >> 8 & 0xff; - metrics[j + 1] = advanceWidth & 0xff; - const lsb = Math.round(scaleFactors[i] * signedInt16(metrics[j + 2], metrics[j + 3])); - writeSignedInt16(metrics, j + 2, lsb); - } - } - - let numGlyphsOut = numGlyphs + 1; - let dupFirstEntry = true; - - if (numGlyphsOut > 0xffff) { - dupFirstEntry = false; - numGlyphsOut = numGlyphs; - (0, _util.warn)("Not enough space in glyfs to duplicate first glyph."); - } - - let maxFunctionDefs = 0; - let maxSizeOfInstructions = 0; - - if (version >= 0x00010000 && tables.maxp.length >= 22) { - font.pos += 8; - const maxZones = font.getUint16(); - - if (maxZones > 2) { - tables.maxp.data[14] = 0; - tables.maxp.data[15] = 2; - } - - font.pos += 4; - maxFunctionDefs = font.getUint16(); - font.pos += 4; - maxSizeOfInstructions = font.getUint16(); - } - - tables.maxp.data[4] = numGlyphsOut >> 8; - tables.maxp.data[5] = numGlyphsOut & 255; - const hintsValid = sanitizeTTPrograms(tables.fpgm, tables.prep, tables["cvt "], maxFunctionDefs); - - if (!hintsValid) { - delete tables.fpgm; - delete tables.prep; - delete tables["cvt "]; - } - - sanitizeMetrics(font, tables.hhea, tables.hmtx, tables.head, numGlyphsOut, dupFirstEntry); - - if (!tables.head) { - throw new _util.FormatError('Required "head" table is not found'); - } - - sanitizeHead(tables.head, numGlyphs, isTrueType ? tables.loca.length : 0); - let missingGlyphs = Object.create(null); - - if (isTrueType) { - const isGlyphLocationsLong = int16(tables.head.data[50], tables.head.data[51]); - const glyphsInfo = sanitizeGlyphLocations(tables.loca, tables.glyf, numGlyphs, isGlyphLocationsLong, hintsValid, dupFirstEntry, maxSizeOfInstructions); - missingGlyphs = glyphsInfo.missingGlyphs; - - if (version >= 0x00010000 && tables.maxp.length >= 22) { - tables.maxp.data[26] = glyphsInfo.maxSizeOfInstructions >> 8; - tables.maxp.data[27] = glyphsInfo.maxSizeOfInstructions & 255; - } - } - - if (!tables.hhea) { - throw new _util.FormatError('Required "hhea" table is not found'); - } - - if (tables.hhea.data[10] === 0 && tables.hhea.data[11] === 0) { - tables.hhea.data[10] = 0xff; - tables.hhea.data[11] = 0xff; - } - - const metricsOverride = { - unitsPerEm: int16(tables.head.data[18], tables.head.data[19]), - yMax: int16(tables.head.data[42], tables.head.data[43]), - yMin: signedInt16(tables.head.data[38], tables.head.data[39]), - ascent: signedInt16(tables.hhea.data[4], tables.hhea.data[5]), - descent: signedInt16(tables.hhea.data[6], tables.hhea.data[7]), - lineGap: signedInt16(tables.hhea.data[8], tables.hhea.data[9]) - }; - this.ascent = metricsOverride.ascent / metricsOverride.unitsPerEm; - this.descent = metricsOverride.descent / metricsOverride.unitsPerEm; - this.lineGap = metricsOverride.lineGap / metricsOverride.unitsPerEm; - - if (this.cssFontInfo && this.cssFontInfo.lineHeight) { - this.lineHeight = this.cssFontInfo.metrics.lineHeight; - this.lineGap = this.cssFontInfo.metrics.lineGap; - } else { - this.lineHeight = this.ascent - this.descent + this.lineGap; - } - - if (tables.post) { - readPostScriptTable(tables.post, properties, numGlyphs); - } - - tables.post = { - tag: "post", - data: createPostTable(properties) - }; - const charCodeToGlyphId = []; - - function hasGlyph(glyphId) { - return !missingGlyphs[glyphId]; - } - - if (properties.composite) { - const cidToGidMap = properties.cidToGidMap || []; - const isCidToGidMapEmpty = cidToGidMap.length === 0; - properties.cMap.forEach(function (charCode, cid) { - if (typeof cid === "string") { - cid = convertCidString(charCode, cid, true); - } - - if (cid > 0xffff) { - throw new _util.FormatError("Max size of CID is 65,535"); - } - - let glyphId = -1; - - if (isCidToGidMapEmpty) { - glyphId = cid; - } else if (cidToGidMap[cid] !== undefined) { - glyphId = cidToGidMap[cid]; - } - - if (glyphId >= 0 && glyphId < numGlyphs && hasGlyph(glyphId)) { - charCodeToGlyphId[charCode] = glyphId; - } - }); - } else { - const cmapTable = readCmapTable(tables.cmap, font, this.isSymbolicFont, properties.hasEncoding); - const cmapPlatformId = cmapTable.platformId; - const cmapEncodingId = cmapTable.encodingId; - const cmapMappings = cmapTable.mappings; - const cmapMappingsLength = cmapMappings.length; - let baseEncoding = [], - forcePostTable = false; - - if (properties.hasEncoding && (properties.baseEncodingName === "MacRomanEncoding" || properties.baseEncodingName === "WinAnsiEncoding")) { - baseEncoding = (0, _encodings.getEncoding)(properties.baseEncodingName); - } - - if (properties.hasEncoding && !this.isSymbolicFont && (cmapPlatformId === 3 && cmapEncodingId === 1 || cmapPlatformId === 1 && cmapEncodingId === 0)) { - const glyphsUnicodeMap = (0, _glyphlist.getGlyphsUnicode)(); - - for (let charCode = 0; charCode < 256; charCode++) { - let glyphName; - - if (this.differences[charCode] !== undefined) { - glyphName = this.differences[charCode]; - } else if (baseEncoding.length && baseEncoding[charCode] !== "") { - glyphName = baseEncoding[charCode]; - } else { - glyphName = _encodings.StandardEncoding[charCode]; - } - - if (!glyphName) { - continue; - } - - const standardGlyphName = (0, _fonts_utils.recoverGlyphName)(glyphName, glyphsUnicodeMap); - let unicodeOrCharCode; - - if (cmapPlatformId === 3 && cmapEncodingId === 1) { - unicodeOrCharCode = glyphsUnicodeMap[standardGlyphName]; - } else if (cmapPlatformId === 1 && cmapEncodingId === 0) { - unicodeOrCharCode = _encodings.MacRomanEncoding.indexOf(standardGlyphName); - } - - if (unicodeOrCharCode === undefined) { - if (!properties.glyphNames && properties.hasIncludedToUnicodeMap && !(this.toUnicode instanceof _to_unicode_map.IdentityToUnicodeMap)) { - const unicode = this.toUnicode.get(charCode); - - if (unicode) { - unicodeOrCharCode = unicode.codePointAt(0); - } - } - - if (unicodeOrCharCode === undefined) { - continue; - } - } - - for (let i = 0; i < cmapMappingsLength; ++i) { - if (cmapMappings[i].charCode !== unicodeOrCharCode) { - continue; - } - - charCodeToGlyphId[charCode] = cmapMappings[i].glyphId; - break; - } - } - } else if (cmapPlatformId === 0) { - for (let i = 0; i < cmapMappingsLength; ++i) { - charCodeToGlyphId[cmapMappings[i].charCode] = cmapMappings[i].glyphId; - } - - forcePostTable = true; - } else { - for (let i = 0; i < cmapMappingsLength; ++i) { - let charCode = cmapMappings[i].charCode; - - if (cmapPlatformId === 3 && charCode >= 0xf000 && charCode <= 0xf0ff) { - charCode &= 0xff; - } - - charCodeToGlyphId[charCode] = cmapMappings[i].glyphId; - } - } - - if (properties.glyphNames && (baseEncoding.length || this.differences.length)) { - for (let i = 0; i < 256; ++i) { - if (!forcePostTable && charCodeToGlyphId[i] !== undefined) { - continue; - } - - const glyphName = this.differences[i] || baseEncoding[i]; - - if (!glyphName) { - continue; - } - - const glyphId = properties.glyphNames.indexOf(glyphName); - - if (glyphId > 0 && hasGlyph(glyphId)) { - charCodeToGlyphId[i] = glyphId; - } - } - } - } - - if (charCodeToGlyphId.length === 0) { - charCodeToGlyphId[0] = 0; - } - - let glyphZeroId = numGlyphsOut - 1; - - if (!dupFirstEntry) { - glyphZeroId = 0; - } - - if (!properties.cssFontInfo) { - const newMapping = adjustMapping(charCodeToGlyphId, hasGlyph, glyphZeroId); - this.toFontChar = newMapping.toFontChar; - tables.cmap = { - tag: "cmap", - data: createCmapTable(newMapping.charCodeToGlyphId, numGlyphsOut) - }; - - if (!tables["OS/2"] || !validateOS2Table(tables["OS/2"], font)) { - tables["OS/2"] = { - tag: "OS/2", - data: createOS2Table(properties, newMapping.charCodeToGlyphId, metricsOverride) - }; - } - } - - if (!isTrueType) { - try { - cffFile = new _stream.Stream(tables["CFF "].data); - const parser = new _cff_parser.CFFParser(cffFile, properties, _fonts_utils.SEAC_ANALYSIS_ENABLED); - cff = parser.parse(); - cff.duplicateFirstGlyph(); - const compiler = new _cff_parser.CFFCompiler(cff); - tables["CFF "].data = compiler.compile(); - } catch (e) { - (0, _util.warn)("Failed to compile font " + properties.loadedName); - } - } - - if (!tables.name) { - tables.name = { - tag: "name", - data: createNameTable(this.name) - }; - } else { - const namePrototype = readNameTable(tables.name); - tables.name.data = createNameTable(name, namePrototype); - this.psName = namePrototype[0][6] || null; - } - - const builder = new _opentype_file_builder.OpenTypeFileBuilder(header.version); - - for (const tableTag in tables) { - builder.addTable(tableTag, tables[tableTag].data); - } - - return builder.toArray(); - } - - convert(fontName, font, properties) { - properties.fixedPitch = false; - - if (properties.builtInEncoding) { - adjustToUnicode(properties, properties.builtInEncoding); - } - - let glyphZeroId = 1; - - if (font instanceof _cff_font.CFFFont) { - glyphZeroId = font.numGlyphs - 1; - } - - const mapping = font.getGlyphMapping(properties); - let newMapping = null; - let newCharCodeToGlyphId = mapping; - - if (!properties.cssFontInfo) { - newMapping = adjustMapping(mapping, font.hasGlyphId.bind(font), glyphZeroId); - this.toFontChar = newMapping.toFontChar; - newCharCodeToGlyphId = newMapping.charCodeToGlyphId; - } - - const numGlyphs = font.numGlyphs; - - function getCharCodes(charCodeToGlyphId, glyphId) { - let charCodes = null; - - for (const charCode in charCodeToGlyphId) { - if (glyphId === charCodeToGlyphId[charCode]) { - if (!charCodes) { - charCodes = []; - } - - charCodes.push(charCode | 0); - } - } - - return charCodes; - } - - function createCharCode(charCodeToGlyphId, glyphId) { - for (const charCode in charCodeToGlyphId) { - if (glyphId === charCodeToGlyphId[charCode]) { - return charCode | 0; - } - } - - newMapping.charCodeToGlyphId[newMapping.nextAvailableFontCharCode] = glyphId; - return newMapping.nextAvailableFontCharCode++; - } - - const seacs = font.seacs; - - if (newMapping && _fonts_utils.SEAC_ANALYSIS_ENABLED && seacs && seacs.length) { - const matrix = properties.fontMatrix || _util.FONT_IDENTITY_MATRIX; - const charset = font.getCharset(); - const seacMap = Object.create(null); - - for (let glyphId in seacs) { - glyphId |= 0; - const seac = seacs[glyphId]; - const baseGlyphName = _encodings.StandardEncoding[seac[2]]; - const accentGlyphName = _encodings.StandardEncoding[seac[3]]; - const baseGlyphId = charset.indexOf(baseGlyphName); - const accentGlyphId = charset.indexOf(accentGlyphName); - - if (baseGlyphId < 0 || accentGlyphId < 0) { - continue; - } - - const accentOffset = { - x: seac[0] * matrix[0] + seac[1] * matrix[2] + matrix[4], - y: seac[0] * matrix[1] + seac[1] * matrix[3] + matrix[5] - }; - const charCodes = getCharCodes(mapping, glyphId); - - if (!charCodes) { - continue; - } - - for (let i = 0, ii = charCodes.length; i < ii; i++) { - const charCode = charCodes[i]; - const charCodeToGlyphId = newMapping.charCodeToGlyphId; - const baseFontCharCode = createCharCode(charCodeToGlyphId, baseGlyphId); - const accentFontCharCode = createCharCode(charCodeToGlyphId, accentGlyphId); - seacMap[charCode] = { - baseFontCharCode, - accentFontCharCode, - accentOffset - }; - } - } - - properties.seacMap = seacMap; - } - - const unitsPerEm = 1 / (properties.fontMatrix || _util.FONT_IDENTITY_MATRIX)[0]; - const builder = new _opentype_file_builder.OpenTypeFileBuilder("\x4F\x54\x54\x4F"); - builder.addTable("CFF ", font.data); - builder.addTable("OS/2", createOS2Table(properties, newCharCodeToGlyphId)); - builder.addTable("cmap", createCmapTable(newCharCodeToGlyphId, numGlyphs)); - builder.addTable("head", "\x00\x01\x00\x00" + "\x00\x00\x10\x00" + "\x00\x00\x00\x00" + "\x5F\x0F\x3C\xF5" + "\x00\x00" + safeString16(unitsPerEm) + "\x00\x00\x00\x00\x9e\x0b\x7e\x27" + "\x00\x00\x00\x00\x9e\x0b\x7e\x27" + "\x00\x00" + safeString16(properties.descent) + "\x0F\xFF" + safeString16(properties.ascent) + string16(properties.italicAngle ? 2 : 0) + "\x00\x11" + "\x00\x00" + "\x00\x00" + "\x00\x00"); - builder.addTable("hhea", "\x00\x01\x00\x00" + safeString16(properties.ascent) + safeString16(properties.descent) + "\x00\x00" + "\xFF\xFF" + "\x00\x00" + "\x00\x00" + "\x00\x00" + safeString16(properties.capHeight) + safeString16(Math.tan(properties.italicAngle) * properties.xHeight) + "\x00\x00" + "\x00\x00" + "\x00\x00" + "\x00\x00" + "\x00\x00" + "\x00\x00" + string16(numGlyphs)); - builder.addTable("hmtx", function fontFieldsHmtx() { - const charstrings = font.charstrings; - const cffWidths = font.cff ? font.cff.widths : null; - let hmtx = "\x00\x00\x00\x00"; - - for (let i = 1, ii = numGlyphs; i < ii; i++) { - let width = 0; - - if (charstrings) { - const charstring = charstrings[i - 1]; - width = "width" in charstring ? charstring.width : 0; - } else if (cffWidths) { - width = Math.ceil(cffWidths[i] || 0); - } - - hmtx += string16(width) + string16(0); - } - - return hmtx; - }()); - builder.addTable("maxp", "\x00\x00\x50\x00" + string16(numGlyphs)); - builder.addTable("name", createNameTable(fontName)); - builder.addTable("post", createPostTable(properties)); - return builder.toArray(); - } - - get spaceWidth() { - const possibleSpaceReplacements = ["space", "minus", "one", "i", "I"]; - let width; - - for (let i = 0, ii = possibleSpaceReplacements.length; i < ii; i++) { - const glyphName = possibleSpaceReplacements[i]; - - if (glyphName in this.widths) { - width = this.widths[glyphName]; - break; - } - - const glyphsUnicodeMap = (0, _glyphlist.getGlyphsUnicode)(); - const glyphUnicode = glyphsUnicodeMap[glyphName]; - let charcode = 0; - - if (this.composite && this.cMap.contains(glyphUnicode)) { - charcode = this.cMap.lookup(glyphUnicode); - - if (typeof charcode === "string") { - charcode = convertCidString(glyphUnicode, charcode); - } - } - - if (!charcode && this.toUnicode) { - charcode = this.toUnicode.charCodeOf(glyphUnicode); - } - - if (charcode <= 0) { - charcode = glyphUnicode; - } - - width = this.widths[charcode]; - - if (width) { - break; - } - } - - width = width || this.defaultWidth; - return (0, _util.shadow)(this, "spaceWidth", width); - } - - _charToGlyph(charcode, isSpace = false) { - let fontCharCode, width, operatorListId; - let widthCode = charcode; - - if (this.cMap && this.cMap.contains(charcode)) { - widthCode = this.cMap.lookup(charcode); - - if (typeof widthCode === "string") { - widthCode = convertCidString(charcode, widthCode); - } - } - - width = this.widths[widthCode]; - width = (0, _util.isNum)(width) ? width : this.defaultWidth; - const vmetric = this.vmetrics && this.vmetrics[widthCode]; - let unicode = this.toUnicode.get(charcode) || charcode; - - if (typeof unicode === "number") { - unicode = String.fromCharCode(unicode); - } - - let isInFont = this.toFontChar[charcode] !== undefined; - fontCharCode = this.toFontChar[charcode] || charcode; - - if (this.missingFile) { - const glyphName = this.differences[charcode] || this.defaultEncoding[charcode]; - - if ((glyphName === ".notdef" || glyphName === "") && this.type === "Type1") { - fontCharCode = 0x20; - } - - fontCharCode = (0, _unicode.mapSpecialUnicodeValues)(fontCharCode); - } - - if (this.isType3Font) { - operatorListId = fontCharCode; - } - - let accent = null; - - if (this.seacMap && this.seacMap[charcode]) { - isInFont = true; - const seac = this.seacMap[charcode]; - fontCharCode = seac.baseFontCharCode; - accent = { - fontChar: String.fromCodePoint(seac.accentFontCharCode), - offset: seac.accentOffset - }; - } - - let fontChar = ""; - - if (typeof fontCharCode === "number") { - if (fontCharCode <= 0x10ffff) { - fontChar = String.fromCodePoint(fontCharCode); - } else { - (0, _util.warn)(`charToGlyph - invalid fontCharCode: ${fontCharCode}`); - } - } - - let glyph = this._glyphCache[charcode]; - - if (!glyph || !glyph.matchesForCache(charcode, fontChar, unicode, accent, width, vmetric, operatorListId, isSpace, isInFont)) { - glyph = new Glyph(charcode, fontChar, unicode, accent, width, vmetric, operatorListId, isSpace, isInFont); - this._glyphCache[charcode] = glyph; - } - - return glyph; - } - - charsToGlyphs(chars) { - let glyphs = this._charsCache[chars]; - - if (glyphs) { - return glyphs; - } - - glyphs = []; - - if (this.cMap) { - const c = Object.create(null), - ii = chars.length; - let i = 0; - - while (i < ii) { - this.cMap.readCharCode(chars, i, c); - const { - charcode, - length - } = c; - i += length; - - const glyph = this._charToGlyph(charcode, length === 1 && chars.charCodeAt(i - 1) === 0x20); - - glyphs.push(glyph); - } - } else { - for (let i = 0, ii = chars.length; i < ii; ++i) { - const charcode = chars.charCodeAt(i); - - const glyph = this._charToGlyph(charcode, charcode === 0x20); - - glyphs.push(glyph); - } - } - - return this._charsCache[chars] = glyphs; - } - - getCharPositions(chars) { - const positions = []; - - if (this.cMap) { - const c = Object.create(null); - let i = 0; - - while (i < chars.length) { - this.cMap.readCharCode(chars, i, c); - const length = c.length; - positions.push([i, i + length]); - i += length; - } - } else { - for (let i = 0, ii = chars.length; i < ii; ++i) { - positions.push([i, i + 1]); - } - } - - return positions; - } - - get glyphCacheValues() { - return Object.values(this._glyphCache); - } - - encodeString(str) { - const buffers = []; - const currentBuf = []; - - const hasCurrentBufErrors = () => buffers.length % 2 === 1; - - const getCharCode = this.toUnicode instanceof _to_unicode_map.IdentityToUnicodeMap ? unicode => this.toUnicode.charCodeOf(unicode) : unicode => this.toUnicode.charCodeOf(String.fromCodePoint(unicode)); - - for (let i = 0, ii = str.length; i < ii; i++) { - const unicode = str.codePointAt(i); - - if (unicode > 0xd7ff && (unicode < 0xe000 || unicode > 0xfffd)) { - i++; - } - - if (this.toUnicode) { - const charCode = getCharCode(unicode); - - if (charCode !== -1) { - if (hasCurrentBufErrors()) { - buffers.push(currentBuf.join("")); - currentBuf.length = 0; - } - - const charCodeLength = this.cMap ? this.cMap.getCharCodeLength(charCode) : 1; - - for (let j = charCodeLength - 1; j >= 0; j--) { - currentBuf.push(String.fromCharCode(charCode >> 8 * j & 0xff)); - } - - continue; - } - } - - if (!hasCurrentBufErrors()) { - buffers.push(currentBuf.join("")); - currentBuf.length = 0; - } - - currentBuf.push(String.fromCodePoint(unicode)); - } - - buffers.push(currentBuf.join("")); - return buffers; - } - -} - -exports.Font = Font; - -class ErrorFont { - constructor(error) { - this.error = error; - this.loadedName = "g_font_error"; - this.missingFile = true; - } - - charsToGlyphs() { - return []; - } - - encodeString(chars) { - return [chars]; - } - - exportData(extraProperties = false) { - return { - error: this.error - }; - } - -} - -exports.ErrorFont = ErrorFont; - -/***/ }), -/* 45 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.CFFTopDict = exports.CFFStrings = exports.CFFStandardStrings = exports.CFFPrivateDict = exports.CFFParser = exports.CFFIndex = exports.CFFHeader = exports.CFFFDSelect = exports.CFFCompiler = exports.CFFCharset = exports.CFF = void 0; - -var _util = __w_pdfjs_require__(2); - -var _charsets = __w_pdfjs_require__(46); - -var _encodings = __w_pdfjs_require__(19); - -const MAX_SUBR_NESTING = 10; -const CFFStandardStrings = [".notdef", "space", "exclam", "quotedbl", "numbersign", "dollar", "percent", "ampersand", "quoteright", "parenleft", "parenright", "asterisk", "plus", "comma", "hyphen", "period", "slash", "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "colon", "semicolon", "less", "equal", "greater", "question", "at", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "bracketleft", "backslash", "bracketright", "asciicircum", "underscore", "quoteleft", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "braceleft", "bar", "braceright", "asciitilde", "exclamdown", "cent", "sterling", "fraction", "yen", "florin", "section", "currency", "quotesingle", "quotedblleft", "guillemotleft", "guilsinglleft", "guilsinglright", "fi", "fl", "endash", "dagger", "daggerdbl", "periodcentered", "paragraph", "bullet", "quotesinglbase", "quotedblbase", "quotedblright", "guillemotright", "ellipsis", "perthousand", "questiondown", "grave", "acute", "circumflex", "tilde", "macron", "breve", "dotaccent", "dieresis", "ring", "cedilla", "hungarumlaut", "ogonek", "caron", "emdash", "AE", "ordfeminine", "Lslash", "Oslash", "OE", "ordmasculine", "ae", "dotlessi", "lslash", "oslash", "oe", "germandbls", "onesuperior", "logicalnot", "mu", "trademark", "Eth", "onehalf", "plusminus", "Thorn", "onequarter", "divide", "brokenbar", "degree", "thorn", "threequarters", "twosuperior", "registered", "minus", "eth", "multiply", "threesuperior", "copyright", "Aacute", "Acircumflex", "Adieresis", "Agrave", "Aring", "Atilde", "Ccedilla", "Eacute", "Ecircumflex", "Edieresis", "Egrave", "Iacute", "Icircumflex", "Idieresis", "Igrave", "Ntilde", "Oacute", "Ocircumflex", "Odieresis", "Ograve", "Otilde", "Scaron", "Uacute", "Ucircumflex", "Udieresis", "Ugrave", "Yacute", "Ydieresis", "Zcaron", "aacute", "acircumflex", "adieresis", "agrave", "aring", "atilde", "ccedilla", "eacute", "ecircumflex", "edieresis", "egrave", "iacute", "icircumflex", "idieresis", "igrave", "ntilde", "oacute", "ocircumflex", "odieresis", "ograve", "otilde", "scaron", "uacute", "ucircumflex", "udieresis", "ugrave", "yacute", "ydieresis", "zcaron", "exclamsmall", "Hungarumlautsmall", "dollaroldstyle", "dollarsuperior", "ampersandsmall", "Acutesmall", "parenleftsuperior", "parenrightsuperior", "twodotenleader", "onedotenleader", "zerooldstyle", "oneoldstyle", "twooldstyle", "threeoldstyle", "fouroldstyle", "fiveoldstyle", "sixoldstyle", "sevenoldstyle", "eightoldstyle", "nineoldstyle", "commasuperior", "threequartersemdash", "periodsuperior", "questionsmall", "asuperior", "bsuperior", "centsuperior", "dsuperior", "esuperior", "isuperior", "lsuperior", "msuperior", "nsuperior", "osuperior", "rsuperior", "ssuperior", "tsuperior", "ff", "ffi", "ffl", "parenleftinferior", "parenrightinferior", "Circumflexsmall", "hyphensuperior", "Gravesmall", "Asmall", "Bsmall", "Csmall", "Dsmall", "Esmall", "Fsmall", "Gsmall", "Hsmall", "Ismall", "Jsmall", "Ksmall", "Lsmall", "Msmall", "Nsmall", "Osmall", "Psmall", "Qsmall", "Rsmall", "Ssmall", "Tsmall", "Usmall", "Vsmall", "Wsmall", "Xsmall", "Ysmall", "Zsmall", "colonmonetary", "onefitted", "rupiah", "Tildesmall", "exclamdownsmall", "centoldstyle", "Lslashsmall", "Scaronsmall", "Zcaronsmall", "Dieresissmall", "Brevesmall", "Caronsmall", "Dotaccentsmall", "Macronsmall", "figuredash", "hypheninferior", "Ogoneksmall", "Ringsmall", "Cedillasmall", "questiondownsmall", "oneeighth", "threeeighths", "fiveeighths", "seveneighths", "onethird", "twothirds", "zerosuperior", "foursuperior", "fivesuperior", "sixsuperior", "sevensuperior", "eightsuperior", "ninesuperior", "zeroinferior", "oneinferior", "twoinferior", "threeinferior", "fourinferior", "fiveinferior", "sixinferior", "seveninferior", "eightinferior", "nineinferior", "centinferior", "dollarinferior", "periodinferior", "commainferior", "Agravesmall", "Aacutesmall", "Acircumflexsmall", "Atildesmall", "Adieresissmall", "Aringsmall", "AEsmall", "Ccedillasmall", "Egravesmall", "Eacutesmall", "Ecircumflexsmall", "Edieresissmall", "Igravesmall", "Iacutesmall", "Icircumflexsmall", "Idieresissmall", "Ethsmall", "Ntildesmall", "Ogravesmall", "Oacutesmall", "Ocircumflexsmall", "Otildesmall", "Odieresissmall", "OEsmall", "Oslashsmall", "Ugravesmall", "Uacutesmall", "Ucircumflexsmall", "Udieresissmall", "Yacutesmall", "Thornsmall", "Ydieresissmall", "001.000", "001.001", "001.002", "001.003", "Black", "Bold", "Book", "Light", "Medium", "Regular", "Roman", "Semibold"]; -exports.CFFStandardStrings = CFFStandardStrings; -const NUM_STANDARD_CFF_STRINGS = 391; - -const CFFParser = function CFFParserClosure() { - const CharstringValidationData = [null, { - id: "hstem", - min: 2, - stackClearing: true, - stem: true - }, null, { - id: "vstem", - min: 2, - stackClearing: true, - stem: true - }, { - id: "vmoveto", - min: 1, - stackClearing: true - }, { - id: "rlineto", - min: 2, - resetStack: true - }, { - id: "hlineto", - min: 1, - resetStack: true - }, { - id: "vlineto", - min: 1, - resetStack: true - }, { - id: "rrcurveto", - min: 6, - resetStack: true - }, null, { - id: "callsubr", - min: 1, - undefStack: true - }, { - id: "return", - min: 0, - undefStack: true - }, null, null, { - id: "endchar", - min: 0, - stackClearing: true - }, null, null, null, { - id: "hstemhm", - min: 2, - stackClearing: true, - stem: true - }, { - id: "hintmask", - min: 0, - stackClearing: true - }, { - id: "cntrmask", - min: 0, - stackClearing: true - }, { - id: "rmoveto", - min: 2, - stackClearing: true - }, { - id: "hmoveto", - min: 1, - stackClearing: true - }, { - id: "vstemhm", - min: 2, - stackClearing: true, - stem: true - }, { - id: "rcurveline", - min: 8, - resetStack: true - }, { - id: "rlinecurve", - min: 8, - resetStack: true - }, { - id: "vvcurveto", - min: 4, - resetStack: true - }, { - id: "hhcurveto", - min: 4, - resetStack: true - }, null, { - id: "callgsubr", - min: 1, - undefStack: true - }, { - id: "vhcurveto", - min: 4, - resetStack: true - }, { - id: "hvcurveto", - min: 4, - resetStack: true - }]; - const 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 - }]; - - class CFFParser { - constructor(file, properties, seacAnalysisEnabled) { - this.bytes = file.getBytes(); - this.properties = properties; - this.seacAnalysisEnabled = !!seacAnalysisEnabled; - } - - parse() { - const properties = this.properties; - const cff = new CFF(); - this.cff = cff; - const header = this.parseHeader(); - const nameIndex = this.parseIndex(header.endPos); - const topDictIndex = this.parseIndex(nameIndex.endPos); - const stringIndex = this.parseIndex(topDictIndex.endPos); - const globalSubrIndex = this.parseIndex(stringIndex.endPos); - const topDictParsed = this.parseDict(topDictIndex.obj.get(0)); - const 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"); - const charStringOffset = topDict.getByName("CharStrings"); - const charStringIndex = this.parseIndex(charStringOffset).obj; - const fontMatrix = topDict.getByName("FontMatrix"); - - if (fontMatrix) { - properties.fontMatrix = fontMatrix; - } - - const fontBBox = topDict.getByName("FontBBox"); - - if (fontBBox) { - properties.ascent = Math.max(fontBBox[3], fontBBox[1]); - properties.descent = Math.min(fontBBox[1], fontBBox[3]); - properties.ascentScaled = true; - } - - let charset, encoding; - - if (cff.isCIDFont) { - const fdArrayIndex = this.parseIndex(topDict.getByName("FDArray")).obj; - - for (let i = 0, ii = fdArrayIndex.count; i < ii; ++i) { - const dictRaw = fdArrayIndex.get(i); - const fontDict = this.createDict(CFFTopDict, this.parseDict(dictRaw), cff.strings); - this.parsePrivateDict(fontDict); - cff.fdArray.push(fontDict); - } - - encoding = null; - charset = this.parseCharsets(topDict.getByName("charset"), charStringIndex.count, cff.strings, true); - cff.fdSelect = this.parseFDSelect(topDict.getByName("FDSelect"), charStringIndex.count); - } else { - charset = this.parseCharsets(topDict.getByName("charset"), charStringIndex.count, cff.strings, false); - encoding = this.parseEncoding(topDict.getByName("Encoding"), properties, cff.strings, charset.charset); - } - - cff.charset = charset; - cff.encoding = encoding; - const charStringsAndSeacs = this.parseCharStrings({ - charStrings: charStringIndex, - localSubrIndex: topDict.privateDict.subrsIndex, - globalSubrIndex: globalSubrIndex.obj, - fdSelect: cff.fdSelect, - fdArray: cff.fdArray, - privateDict: topDict.privateDict - }); - cff.charStrings = charStringsAndSeacs.charStrings; - cff.seacs = charStringsAndSeacs.seacs; - cff.widths = charStringsAndSeacs.widths; - return cff; - } - - parseHeader() { - let bytes = this.bytes; - const bytesLength = bytes.length; - let offset = 0; - - while (offset < bytesLength && bytes[offset] !== 1) { - ++offset; - } - - if (offset >= bytesLength) { - throw new _util.FormatError("Invalid CFF header"); - } - - if (offset !== 0) { - (0, _util.info)("cff data is shifted"); - bytes = bytes.subarray(offset); - this.bytes = bytes; - } - - const major = bytes[0]; - const minor = bytes[1]; - const hdrSize = bytes[2]; - const offSize = bytes[3]; - const header = new CFFHeader(major, minor, hdrSize, offSize); - return { - obj: header, - endPos: hdrSize - }; - } - - parseDict(dict) { - let pos = 0; - - function parseOperand() { - let value = dict[pos++]; - - if (value === 30) { - return parseFloatOperand(); - } 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; - } - - (0, _util.warn)('CFFParser_parseDict: "' + value + '" is a reserved command.'); - return NaN; - } - - function parseFloatOperand() { - let str = ""; - const eof = 15; - const lookup = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ".", "E", "E-", null, "-"]; - const length = dict.length; - - while (pos < length) { - const b = dict[pos++]; - const b1 = b >> 4; - const b2 = b & 15; - - if (b1 === eof) { - break; - } - - str += lookup[b1]; - - if (b2 === eof) { - break; - } - - str += lookup[b2]; - } - - return parseFloat(str); - } - - let operands = []; - const entries = []; - pos = 0; - const end = dict.length; - - while (pos < end) { - let 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(pos) { - const cffIndex = new CFFIndex(); - const bytes = this.bytes; - const count = bytes[pos++] << 8 | bytes[pos++]; - const offsets = []; - let end = pos; - let i, ii; - - if (count !== 0) { - const offsetSize = bytes[pos++]; - const startPos = pos + (count + 1) * offsetSize - 1; - - for (i = 0, ii = count + 1; i < ii; ++i) { - let offset = 0; - - for (let j = 0; j < offsetSize; ++j) { - offset <<= 8; - offset += bytes[pos++]; - } - - offsets.push(startPos + offset); - } - - end = offsets[count]; - } - - for (i = 0, ii = offsets.length - 1; i < ii; ++i) { - const offsetStart = offsets[i]; - const offsetEnd = offsets[i + 1]; - cffIndex.add(bytes.subarray(offsetStart, offsetEnd)); - } - - return { - obj: cffIndex, - endPos: end - }; - } - - parseNameIndex(index) { - const names = []; - - for (let i = 0, ii = index.count; i < ii; ++i) { - const name = index.get(i); - names.push((0, _util.bytesToString)(name)); - } - - return names; - } - - parseStringIndex(index) { - const strings = new CFFStrings(); - - for (let i = 0, ii = index.count; i < ii; ++i) { - const data = index.get(i); - strings.add((0, _util.bytesToString)(data)); - } - - return strings; - } - - createDict(Type, dict, strings) { - const cffDict = new Type(strings); - - for (let i = 0, ii = dict.length; i < ii; ++i) { - const pair = dict[i]; - const key = pair[0]; - const value = pair[1]; - cffDict.setByKey(key, value); - } - - return cffDict; - } - - parseCharString(state, data, localSubrIndex, globalSubrIndex) { - if (!data || state.callDepth > MAX_SUBR_NESTING) { - return false; - } - - let stackSize = state.stackSize; - const stack = state.stack; - const length = data.length; - - for (let j = 0; j < length;) { - const value = data[j++]; - let validationCommand = null; - - if (value === 12) { - const q = data[j++]; - - if (q === 0) { - data[j - 2] = 139; - data[j - 1] = 22; - stackSize = 0; - } else { - validationCommand = CharstringValidationData12[q]; - } - } else if (value === 28) { - stack[stackSize] = (data[j] << 24 | data[j + 1] << 16) >> 16; - j += 2; - stackSize++; - } else if (value === 14) { - if (stackSize >= 4) { - stackSize -= 4; - - if (this.seacAnalysisEnabled) { - state.seac = stack.slice(stackSize, stackSize + 4); - return false; - } - } - - validationCommand = CharstringValidationData[value]; - } else if (value >= 32 && value <= 246) { - stack[stackSize] = value - 139; - stackSize++; - } else if (value >= 247 && value <= 254) { - stack[stackSize] = value < 251 ? (value - 247 << 8) + data[j] + 108 : -(value - 251 << 8) - data[j] - 108; - j++; - stackSize++; - } else if (value === 255) { - 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) { - state.hints += stackSize >> 1; - j += state.hints + 7 >> 3; - stackSize %= 2; - validationCommand = CharstringValidationData[value]; - } else if (value === 10 || value === 29) { - let subrsIndex; - - if (value === 10) { - subrsIndex = localSubrIndex; - } else { - subrsIndex = globalSubrIndex; - } - - if (!subrsIndex) { - validationCommand = CharstringValidationData[value]; - (0, _util.warn)("Missing subrsIndex for " + validationCommand.id); - return false; - } - - let bias = 32768; - - if (subrsIndex.count < 1240) { - bias = 107; - } else if (subrsIndex.count < 33900) { - bias = 1131; - } - - const subrNumber = stack[--stackSize] + bias; - - if (subrNumber < 0 || subrNumber >= subrsIndex.count || isNaN(subrNumber)) { - validationCommand = CharstringValidationData[value]; - (0, _util.warn)("Out of bounds subrIndex for " + validationCommand.id); - return false; - } - - state.stackSize = stackSize; - state.callDepth++; - const valid = this.parseCharString(state, subrsIndex.get(subrNumber), localSubrIndex, globalSubrIndex); - - if (!valid) { - return false; - } - - state.callDepth--; - stackSize = state.stackSize; - continue; - } else if (value === 11) { - state.stackSize = stackSize; - return true; - } else if (value === 0 && j === data.length) { - data[j - 1] = 14; - validationCommand = CharstringValidationData[14]; - } else { - validationCommand = CharstringValidationData[value]; - } - - if (validationCommand) { - if (validationCommand.stem) { - state.hints += stackSize >> 1; - - if (value === 3 || value === 23) { - state.hasVStems = true; - } else if (state.hasVStems && (value === 1 || value === 18)) { - (0, _util.warn)("CFF stem hints are in wrong order"); - data[j - 1] = value === 1 ? 3 : 23; - } - } - - if ("min" in validationCommand) { - if (!state.undefStack && stackSize < validationCommand.min) { - (0, _util.warn)("Not enough parameters for " + validationCommand.id + "; actual: " + stackSize + ", expected: " + validationCommand.min); - - if (stackSize === 0) { - data[j - 1] = 14; - return true; - } - - return false; - } - } - - if (state.firstStackClearing && validationCommand.stackClearing) { - state.firstStackClearing = false; - stackSize -= validationCommand.min; - - if (stackSize >= 2 && validationCommand.stem) { - stackSize %= 2; - } else if (stackSize > 1) { - (0, _util.warn)("Found too many parameters for stack-clearing command"); - } - - if (stackSize > 0) { - state.width = stack[stackSize - 1]; - } - } - - if ("stackDelta" in validationCommand) { - if ("stackFn" in validationCommand) { - validationCommand.stackFn(stack, stackSize); - } - - stackSize += validationCommand.stackDelta; - } else if (validationCommand.stackClearing) { - stackSize = 0; - } else if (validationCommand.resetStack) { - stackSize = 0; - state.undefStack = false; - } else if (validationCommand.undefStack) { - stackSize = 0; - state.undefStack = true; - state.firstStackClearing = false; - } - } - } - - state.stackSize = stackSize; - return true; - } - - parseCharStrings({ - charStrings, - localSubrIndex, - globalSubrIndex, - fdSelect, - fdArray, - privateDict - }) { - const seacs = []; - const widths = []; - const count = charStrings.count; - - for (let i = 0; i < count; i++) { - const charstring = charStrings.get(i); - const state = { - callDepth: 0, - stackSize: 0, - stack: [], - undefStack: true, - hints: 0, - firstStackClearing: true, - seac: null, - width: null, - hasVStems: false - }; - let valid = true; - let localSubrToUse = null; - let privateDictToUse = privateDict; - - if (fdSelect && fdArray.length) { - const fdIndex = fdSelect.getFDIndex(i); - - if (fdIndex === -1) { - (0, _util.warn)("Glyph index is not in fd select."); - valid = false; - } - - if (fdIndex >= fdArray.length) { - (0, _util.warn)("Invalid fd index for glyph index."); - valid = false; - } - - if (valid) { - privateDictToUse = fdArray[fdIndex].privateDict; - localSubrToUse = privateDictToUse.subrsIndex; - } - } else if (localSubrIndex) { - localSubrToUse = localSubrIndex; - } - - if (valid) { - valid = this.parseCharString(state, charstring, localSubrToUse, globalSubrIndex); - } - - if (state.width !== null) { - const nominalWidth = privateDictToUse.getByName("nominalWidthX"); - widths[i] = nominalWidth + state.width; - } else { - const defaultWidth = privateDictToUse.getByName("defaultWidthX"); - widths[i] = defaultWidth; - } - - if (state.seac !== null) { - seacs[i] = state.seac; - } - - if (!valid) { - charStrings.set(i, new Uint8Array([14])); - } - } - - return { - charStrings, - seacs, - widths - }; - } - - emptyPrivateDictionary(parentDict) { - const privateDict = this.createDict(CFFPrivateDict, [], parentDict.strings); - parentDict.setByKey(18, [0, 0]); - parentDict.privateDict = privateDict; - } - - parsePrivateDict(parentDict) { - if (!parentDict.hasName("Private")) { - this.emptyPrivateDictionary(parentDict); - return; - } - - const privateOffset = parentDict.getByName("Private"); - - if (!Array.isArray(privateOffset) || privateOffset.length !== 2) { - parentDict.removeByName("Private"); - return; - } - - const size = privateOffset[0]; - const offset = privateOffset[1]; - - if (size === 0 || offset >= this.bytes.length) { - this.emptyPrivateDictionary(parentDict); - return; - } - - const privateDictEnd = offset + size; - const dictData = this.bytes.subarray(offset, privateDictEnd); - const dict = this.parseDict(dictData); - const privateDict = this.createDict(CFFPrivateDict, dict, parentDict.strings); - parentDict.privateDict = privateDict; - - if (!privateDict.getByName("Subrs")) { - return; - } - - const subrsOffset = privateDict.getByName("Subrs"); - const relativeOffset = offset + subrsOffset; - - if (subrsOffset === 0 || relativeOffset >= this.bytes.length) { - this.emptyPrivateDictionary(parentDict); - return; - } - - const subrsIndex = this.parseIndex(relativeOffset); - privateDict.subrsIndex = subrsIndex.obj; - } - - parseCharsets(pos, length, strings, cid) { - if (pos === 0) { - return new CFFCharset(true, CFFCharsetPredefinedTypes.ISO_ADOBE, _charsets.ISOAdobeCharset); - } else if (pos === 1) { - return new CFFCharset(true, CFFCharsetPredefinedTypes.EXPERT, _charsets.ExpertCharset); - } else if (pos === 2) { - return new CFFCharset(true, CFFCharsetPredefinedTypes.EXPERT_SUBSET, _charsets.ExpertSubsetCharset); - } - - const bytes = this.bytes; - const start = pos; - const format = bytes[pos++]; - const charset = [cid ? 0 : ".notdef"]; - let id, count, i; - length -= 1; - - switch (format) { - case 0: - for (i = 0; i < length; i++) { - id = bytes[pos++] << 8 | bytes[pos++]; - charset.push(cid ? id : strings.get(id)); - } - - break; - - case 1: - while (charset.length <= length) { - id = bytes[pos++] << 8 | bytes[pos++]; - count = bytes[pos++]; - - for (i = 0; i <= count; i++) { - charset.push(cid ? id++ : strings.get(id++)); - } - } - - break; - - case 2: - while (charset.length <= length) { - id = bytes[pos++] << 8 | bytes[pos++]; - count = bytes[pos++] << 8 | bytes[pos++]; - - for (i = 0; i <= count; i++) { - charset.push(cid ? id++ : strings.get(id++)); - } - } - - break; - - default: - throw new _util.FormatError("Unknown charset format"); - } - - const end = pos; - const raw = bytes.subarray(start, end); - return new CFFCharset(false, format, charset, raw); - } - - parseEncoding(pos, properties, strings, charset) { - const encoding = Object.create(null); - const bytes = this.bytes; - let predefined = false; - let format, i, ii; - let raw = null; - - function readSupplement() { - const supplementsCount = bytes[pos++]; - - for (i = 0; i < supplementsCount; i++) { - const code = bytes[pos++]; - const sid = (bytes[pos++] << 8) + (bytes[pos++] & 0xff); - encoding[code] = charset.indexOf(strings.get(sid)); - } - } - - if (pos === 0 || pos === 1) { - predefined = true; - format = pos; - const baseEncoding = pos ? _encodings.ExpertEncoding : _encodings.StandardEncoding; - - for (i = 0, ii = charset.length; i < ii; i++) { - const index = baseEncoding.indexOf(charset[i]); - - if (index !== -1) { - encoding[index] = i; - } - } - } else { - const dataStart = pos; - format = bytes[pos++]; - - switch (format & 0x7f) { - case 0: - const glyphsCount = bytes[pos++]; - - for (i = 1; i <= glyphsCount; i++) { - encoding[bytes[pos++]] = i; - } - - break; - - case 1: - const rangesCount = bytes[pos++]; - let gid = 1; - - for (i = 0; i < rangesCount; i++) { - const start = bytes[pos++]; - const left = bytes[pos++]; - - for (let j = start; j <= start + left; j++) { - encoding[j] = gid++; - } - } - - break; - - default: - throw new _util.FormatError(`Unknown encoding format: ${format} in CFF`); - } - - const dataEnd = pos; - - if (format & 0x80) { - bytes[dataStart] &= 0x7f; - readSupplement(); - } - - raw = bytes.subarray(dataStart, dataEnd); - } - - format &= 0x7f; - return new CFFEncoding(predefined, format, encoding, raw); - } - - parseFDSelect(pos, length) { - const bytes = this.bytes; - const format = bytes[pos++]; - const fdSelect = []; - let i; - - switch (format) { - case 0: - for (i = 0; i < length; ++i) { - const id = bytes[pos++]; - fdSelect.push(id); - } - - break; - - case 3: - const rangesCount = bytes[pos++] << 8 | bytes[pos++]; - - for (i = 0; i < rangesCount; ++i) { - let first = bytes[pos++] << 8 | bytes[pos++]; - - if (i === 0 && first !== 0) { - (0, _util.warn)("parseFDSelect: The first range must have a first GID of 0" + " -- trying to recover."); - first = 0; - } - - const fdIndex = bytes[pos++]; - const next = bytes[pos] << 8 | bytes[pos + 1]; - - for (let j = first; j < next; ++j) { - fdSelect.push(fdIndex); - } - } - - pos += 2; - break; - - default: - throw new _util.FormatError(`parseFDSelect: Unknown format "${format}".`); - } - - if (fdSelect.length !== length) { - throw new _util.FormatError("parseFDSelect: Invalid font data."); - } - - return new CFFFDSelect(format, fdSelect); - } - - } - - return CFFParser; -}(); - -exports.CFFParser = CFFParser; - -class CFF { - constructor() { - this.header = null; - this.names = []; - this.topDict = null; - this.strings = new CFFStrings(); - this.globalSubrIndex = null; - this.encoding = null; - this.charset = null; - this.charStrings = null; - this.fdArray = []; - this.fdSelect = null; - this.isCIDFont = false; - } - - duplicateFirstGlyph() { - if (this.charStrings.count >= 65535) { - (0, _util.warn)("Not enough space in charstrings to duplicate first glyph."); - return; - } - - const glyphZero = this.charStrings.get(0); - this.charStrings.add(glyphZero); - - if (this.isCIDFont) { - this.fdSelect.fdSelect.push(this.fdSelect.fdSelect[0]); - } - } - - hasGlyphId(id) { - if (id < 0 || id >= this.charStrings.count) { - return false; - } - - const glyph = this.charStrings.get(id); - return glyph.length > 0; - } - -} - -exports.CFF = CFF; - -class CFFHeader { - constructor(major, minor, hdrSize, offSize) { - this.major = major; - this.minor = minor; - this.hdrSize = hdrSize; - this.offSize = offSize; - } - -} - -exports.CFFHeader = CFFHeader; - -class CFFStrings { - constructor() { - this.strings = []; - } - - get(index) { - if (index >= 0 && index <= NUM_STANDARD_CFF_STRINGS - 1) { - return CFFStandardStrings[index]; - } - - if (index - NUM_STANDARD_CFF_STRINGS <= this.strings.length) { - return this.strings[index - NUM_STANDARD_CFF_STRINGS]; - } - - return CFFStandardStrings[0]; - } - - getSID(str) { - let index = CFFStandardStrings.indexOf(str); - - if (index !== -1) { - return index; - } - - index = this.strings.indexOf(str); - - if (index !== -1) { - return index + NUM_STANDARD_CFF_STRINGS; - } - - return -1; - } - - add(value) { - this.strings.push(value); - } - - get count() { - return this.strings.length; - } - -} - -exports.CFFStrings = CFFStrings; - -class CFFIndex { - constructor() { - this.objects = []; - this.length = 0; - } - - add(data) { - this.length += data.length; - this.objects.push(data); - } - - set(index, data) { - this.length += data.length - this.objects[index].length; - this.objects[index] = data; - } - - get(index) { - return this.objects[index]; - } - - get count() { - return this.objects.length; - } - -} - -exports.CFFIndex = CFFIndex; - -class CFFDict { - constructor(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 = Object.create(null); - } - - setByKey(key, value) { - if (!(key in this.keyToNameMap)) { - return false; - } - - const valueLength = value.length; - - if (valueLength === 0) { - return true; - } - - for (let i = 0; i < valueLength; i++) { - if (isNaN(value[i])) { - (0, _util.warn)('Invalid CFFDict value: "' + value + '" for key "' + key + '".'); - return true; - } - } - - const type = this.types[key]; - - if (type === "num" || type === "sid" || type === "offset") { - value = value[0]; - } - - this.values[key] = value; - return true; - } - - setByName(name, value) { - if (!(name in this.nameToKeyMap)) { - throw new _util.FormatError(`Invalid dictionary name "${name}"`); - } - - this.values[this.nameToKeyMap[name]] = value; - } - - hasName(name) { - return this.nameToKeyMap[name] in this.values; - } - - getByName(name) { - if (!(name in this.nameToKeyMap)) { - throw new _util.FormatError(`Invalid dictionary name ${name}"`); - } - - const key = this.nameToKeyMap[name]; - - if (!(key in this.values)) { - return this.defaults[key]; - } - - return this.values[key]; - } - - removeByName(name) { - delete this.values[this.nameToKeyMap[name]]; - } - - static createTables(layout) { - const tables = { - keyToNameMap: {}, - nameToKeyMap: {}, - defaults: {}, - types: {}, - opcodes: {}, - order: [] - }; - - for (let i = 0, ii = layout.length; i < ii; ++i) { - const entry = layout[i]; - const key = Array.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] = Array.isArray(entry[0]) ? entry[0] : [entry[0]]; - tables.order.push(key); - } - - return tables; - } - -} - -const CFFTopDict = function CFFTopDictClosure() { - const 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], [[12, 37], "FDSelect", "offset", null], [[12, 36], "FDArray", "offset", null], [[12, 38], "FontName", "sid", null]]; - let tables = null; - - class CFFTopDict extends CFFDict { - constructor(strings) { - if (tables === null) { - tables = CFFDict.createTables(layout); - } - - super(tables, strings); - this.privateDict = null; - } - - } - - return CFFTopDict; -}(); - -exports.CFFTopDict = CFFTopDict; - -const CFFPrivateDict = function CFFPrivateDictClosure() { - const 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]]; - let tables = null; - - class CFFPrivateDict extends CFFDict { - constructor(strings) { - if (tables === null) { - tables = CFFDict.createTables(layout); - } - - super(tables, strings); - this.subrsIndex = null; - } - - } - - return CFFPrivateDict; -}(); - -exports.CFFPrivateDict = CFFPrivateDict; -const CFFCharsetPredefinedTypes = { - ISO_ADOBE: 0, - EXPERT: 1, - EXPERT_SUBSET: 2 -}; - -class CFFCharset { - constructor(predefined, format, charset, raw) { - this.predefined = predefined; - this.format = format; - this.charset = charset; - this.raw = raw; - } - -} - -exports.CFFCharset = CFFCharset; - -class CFFEncoding { - constructor(predefined, format, encoding, raw) { - this.predefined = predefined; - this.format = format; - this.encoding = encoding; - this.raw = raw; - } - -} - -class CFFFDSelect { - constructor(format, fdSelect) { - this.format = format; - this.fdSelect = fdSelect; - } - - getFDIndex(glyphIndex) { - if (glyphIndex < 0 || glyphIndex >= this.fdSelect.length) { - return -1; - } - - return this.fdSelect[glyphIndex]; - } - -} - -exports.CFFFDSelect = CFFFDSelect; - -class CFFOffsetTracker { - constructor() { - this.offsets = Object.create(null); - } - - isTracking(key) { - return key in this.offsets; - } - - track(key, location) { - if (key in this.offsets) { - throw new _util.FormatError(`Already tracking location of ${key}`); - } - - this.offsets[key] = location; - } - - offset(value) { - for (const key in this.offsets) { - this.offsets[key] += value; - } - } - - setEntryLocation(key, values, output) { - if (!(key in this.offsets)) { - throw new _util.FormatError(`Not tracking location of ${key}`); - } - - const data = output.data; - const dataOffset = this.offsets[key]; - const size = 5; - - for (let i = 0, ii = values.length; i < ii; ++i) { - const offset0 = i * size + dataOffset; - const offset1 = offset0 + 1; - const offset2 = offset0 + 2; - const offset3 = offset0 + 3; - const offset4 = offset0 + 4; - - if (data[offset0] !== 0x1d || data[offset1] !== 0 || data[offset2] !== 0 || data[offset3] !== 0 || data[offset4] !== 0) { - throw new _util.FormatError("writing to an offset that is not empty"); - } - - const 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; - } - } - -} - -class CFFCompiler { - constructor(cff) { - this.cff = cff; - } - - compile() { - const cff = this.cff; - const output = { - data: [], - length: 0, - add: function CFFCompiler_add(data) { - this.data = this.data.concat(data); - this.length = this.data.length; - } - }; - const header = this.compileHeader(cff.header); - output.add(header); - const nameIndex = this.compileNameIndex(cff.names); - output.add(nameIndex); - - if (cff.isCIDFont) { - if (cff.topDict.hasName("FontMatrix")) { - const base = cff.topDict.getByName("FontMatrix"); - cff.topDict.removeByName("FontMatrix"); - - for (let i = 0, ii = cff.fdArray.length; i < ii; i++) { - const subDict = cff.fdArray[i]; - let matrix = base.slice(0); - - if (subDict.hasName("FontMatrix")) { - matrix = _util.Util.transform(matrix, subDict.getByName("FontMatrix")); - } - - subDict.setByName("FontMatrix", matrix); - } - } - } - - const xuid = cff.topDict.getByName("XUID"); - - if (xuid && xuid.length > 16) { - cff.topDict.removeByName("XUID"); - } - - cff.topDict.setByName("charset", 0); - let compiled = this.compileTopDicts([cff.topDict], output.length, cff.isCIDFont); - output.add(compiled.output); - const topDictTracker = compiled.trackers[0]; - const stringIndex = this.compileStringIndex(cff.strings.strings); - output.add(stringIndex); - const globalSubrIndex = this.compileIndex(cff.globalSubrIndex); - output.add(globalSubrIndex); - - if (cff.encoding && cff.topDict.hasName("Encoding")) { - if (cff.encoding.predefined) { - topDictTracker.setEntryLocation("Encoding", [cff.encoding.format], output); - } else { - const encoding = this.compileEncoding(cff.encoding); - topDictTracker.setEntryLocation("Encoding", [output.length], output); - output.add(encoding); - } - } - - const charset = this.compileCharset(cff.charset, cff.charStrings.count, cff.strings, cff.isCIDFont); - topDictTracker.setEntryLocation("charset", [output.length], output); - output.add(charset); - const charStrings = this.compileCharStrings(cff.charStrings); - topDictTracker.setEntryLocation("CharStrings", [output.length], output); - output.add(charStrings); - - if (cff.isCIDFont) { - topDictTracker.setEntryLocation("FDSelect", [output.length], output); - const fdSelect = this.compileFDSelect(cff.fdSelect); - output.add(fdSelect); - compiled = this.compileTopDicts(cff.fdArray, output.length, true); - topDictTracker.setEntryLocation("FDArray", [output.length], output); - output.add(compiled.output); - const fontDictTrackers = compiled.trackers; - this.compilePrivateDicts(cff.fdArray, fontDictTrackers, output); - } - - this.compilePrivateDicts([cff.topDict], [topDictTracker], output); - output.add([0]); - return output.data; - } - - encodeNumber(value) { - if (Number.isInteger(value)) { - return this.encodeInteger(value); - } - - return this.encodeFloat(value); - } - - static get EncodeFloatRegExp() { - return (0, _util.shadow)(this, "EncodeFloatRegExp", /\.(\d*?)(?:9{5,20}|0{5,20})\d{0,2}(?:e(.+)|$)/); - } - - encodeFloat(num) { - let value = num.toString(); - const m = CFFCompiler.EncodeFloatRegExp.exec(value); - - if (m) { - const epsilon = parseFloat("1e" + ((m[2] ? +m[2] : 0) + m[1].length)); - value = (Math.round(num * epsilon) / epsilon).toString(); - } - - let nibbles = ""; - let i, ii; - - for (i = 0, ii = value.length; i < ii; ++i) { - const 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"; - const out = [30]; - - for (i = 0, ii = nibbles.length; i < ii; i += 2) { - out.push(parseInt(nibbles.substring(i, i + 2), 16)); - } - - return out; - } - - encodeInteger(value) { - let code; - - if (value >= -107 && value <= 107) { - code = [value + 139]; - } else if (value >= 108 && value <= 1131) { - 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(header) { - return [header.major, header.minor, 4, header.offSize]; - } - - compileNameIndex(names) { - const nameIndex = new CFFIndex(); - - for (let i = 0, ii = names.length; i < ii; ++i) { - const name = names[i]; - const length = Math.min(name.length, 127); - let sanitizedName = new Array(length); - - for (let j = 0; j < length; j++) { - let char = name[j]; - - if (char < "!" || char > "~" || char === "[" || char === "]" || char === "(" || char === ")" || char === "{" || char === "}" || char === "<" || char === ">" || char === "/" || char === "%") { - char = "_"; - } - - sanitizedName[j] = char; - } - - sanitizedName = sanitizedName.join(""); - - if (sanitizedName === "") { - sanitizedName = "Bad_Font_Name"; - } - - nameIndex.add((0, _util.stringToBytes)(sanitizedName)); - } - - return this.compileIndex(nameIndex); - } - - compileTopDicts(dicts, length, removeCidKeys) { - const fontDictTrackers = []; - let fdArrayIndex = new CFFIndex(); - - for (let i = 0, ii = dicts.length; i < ii; ++i) { - const fontDict = dicts[i]; - - if (removeCidKeys) { - fontDict.removeByName("CIDFontVersion"); - fontDict.removeByName("CIDFontRevision"); - fontDict.removeByName("CIDFontType"); - fontDict.removeByName("CIDCount"); - fontDict.removeByName("UIDBase"); - } - - const fontDictTracker = new CFFOffsetTracker(); - const 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(dicts, trackers, output) { - for (let i = 0, ii = dicts.length; i < ii; ++i) { - const fontDict = dicts[i]; - const privateDict = fontDict.privateDict; - - if (!privateDict || !fontDict.hasName("Private")) { - throw new _util.FormatError("There must be a private dictionary."); - } - - const privateDictTracker = new CFFOffsetTracker(); - const privateDictData = this.compileDict(privateDict, privateDictTracker); - let outputLength = output.length; - privateDictTracker.offset(outputLength); - - if (!privateDictData.length) { - outputLength = 0; - } - - trackers[i].setEntryLocation("Private", [privateDictData.length, outputLength], output); - output.add(privateDictData); - - if (privateDict.subrsIndex && privateDict.hasName("Subrs")) { - const subrs = this.compileIndex(privateDict.subrsIndex); - privateDictTracker.setEntryLocation("Subrs", [privateDictData.length], output); - output.add(subrs); - } - } - } - - compileDict(dict, offsetTracker) { - let out = []; - const order = dict.order; - - for (let i = 0; i < order.length; ++i) { - const key = order[i]; - - if (!(key in dict.values)) { - continue; - } - - let values = dict.values[key]; - let types = dict.types[key]; - - if (!Array.isArray(types)) { - types = [types]; - } - - if (!Array.isArray(values)) { - values = [values]; - } - - if (values.length === 0) { - continue; - } - - for (let j = 0, jj = types.length; j < jj; ++j) { - const type = types[j]; - const value = values[j]; - - switch (type) { - case "num": - case "sid": - out = out.concat(this.encodeNumber(value)); - break; - - case "offset": - const name = dict.keyToNameMap[key]; - - 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 (let k = 1, kk = values.length; k < kk; ++k) { - out = out.concat(this.encodeNumber(values[k])); - } - - break; - - default: - throw new _util.FormatError(`Unknown data type of ${type}`); - } - } - - out = out.concat(dict.opcodes[key]); - } - - return out; - } - - compileStringIndex(strings) { - const stringIndex = new CFFIndex(); - - for (let i = 0, ii = strings.length; i < ii; ++i) { - stringIndex.add((0, _util.stringToBytes)(strings[i])); - } - - return this.compileIndex(stringIndex); - } - - compileGlobalSubrIndex() { - const globalSubrIndex = this.cff.globalSubrIndex; - this.out.writeByteArray(this.compileIndex(globalSubrIndex)); - } - - compileCharStrings(charStrings) { - const charStringsIndex = new CFFIndex(); - - for (let i = 0; i < charStrings.count; i++) { - const glyph = charStrings.get(i); - - if (glyph.length === 0) { - charStringsIndex.add(new Uint8Array([0x8b, 0x0e])); - continue; - } - - charStringsIndex.add(glyph); - } - - return this.compileIndex(charStringsIndex); - } - - compileCharset(charset, numGlyphs, strings, isCIDFont) { - let out; - const numGlyphsLessNotDef = numGlyphs - 1; - - if (isCIDFont) { - out = new Uint8Array([2, 0, 0, numGlyphsLessNotDef >> 8 & 0xff, numGlyphsLessNotDef & 0xff]); - } else { - const length = 1 + numGlyphsLessNotDef * 2; - out = new Uint8Array(length); - out[0] = 0; - let charsetIndex = 0; - const numCharsets = charset.charset.length; - let warned = false; - - for (let i = 1; i < out.length; i += 2) { - let sid = 0; - - if (charsetIndex < numCharsets) { - const name = charset.charset[charsetIndex++]; - sid = strings.getSID(name); - - if (sid === -1) { - sid = 0; - - if (!warned) { - warned = true; - (0, _util.warn)(`Couldn't find ${name} in CFF strings`); - } - } - } - - out[i] = sid >> 8 & 0xff; - out[i + 1] = sid & 0xff; - } - } - - return this.compileTypedArray(out); - } - - compileEncoding(encoding) { - return this.compileTypedArray(encoding.raw); - } - - compileFDSelect(fdSelect) { - const format = fdSelect.format; - let out, i; - - switch (format) { - case 0: - out = new Uint8Array(1 + fdSelect.fdSelect.length); - out[0] = format; - - for (i = 0; i < fdSelect.fdSelect.length; i++) { - out[i + 1] = fdSelect.fdSelect[i]; - } - - break; - - case 3: - const start = 0; - let lastFD = fdSelect.fdSelect[0]; - const ranges = [format, 0, 0, start >> 8 & 0xff, start & 0xff, lastFD]; - - for (i = 1; i < fdSelect.fdSelect.length; i++) { - const currentFD = fdSelect.fdSelect[i]; - - if (currentFD !== lastFD) { - ranges.push(i >> 8 & 0xff, i & 0xff, currentFD); - lastFD = currentFD; - } - } - - const numRanges = (ranges.length - 3) / 3; - ranges[1] = numRanges >> 8 & 0xff; - ranges[2] = numRanges & 0xff; - ranges.push(i >> 8 & 0xff, i & 0xff); - out = new Uint8Array(ranges); - break; - } - - return this.compileTypedArray(out); - } - - compileTypedArray(data) { - const out = []; - - for (let i = 0, ii = data.length; i < ii; ++i) { - out[i] = data[i]; - } - - return out; - } - - compileIndex(index, trackers = []) { - const objects = index.objects; - const count = objects.length; - - if (count === 0) { - return [0, 0, 0]; - } - - const data = [count >> 8 & 0xff, count & 0xff]; - let lastOffset = 1, - i; - - for (i = 0; i < count; ++i) { - lastOffset += objects[i].length; - } - - let offsetSize; - - if (lastOffset < 0x100) { - offsetSize = 1; - } else if (lastOffset < 0x10000) { - offsetSize = 2; - } else if (lastOffset < 0x1000000) { - offsetSize = 3; - } else { - offsetSize = 4; - } - - data.push(offsetSize); - let relativeOffset = 1; - - for (i = 0; i < count + 1; i++) { - if (offsetSize === 1) { - data.push(relativeOffset & 0xff); - } else if (offsetSize === 2) { - data.push(relativeOffset >> 8 & 0xff, relativeOffset & 0xff); - } else if (offsetSize === 3) { - data.push(relativeOffset >> 16 & 0xff, relativeOffset >> 8 & 0xff, relativeOffset & 0xff); - } else { - data.push(relativeOffset >>> 24 & 0xff, relativeOffset >> 16 & 0xff, relativeOffset >> 8 & 0xff, relativeOffset & 0xff); - } - - if (objects[i]) { - relativeOffset += objects[i].length; - } - } - - for (i = 0; i < count; i++) { - if (trackers[i]) { - trackers[i].offset(data.length); - } - - for (let j = 0, jj = objects[i].length; j < jj; j++) { - data.push(objects[i][j]); - } - } - - return data; - } - -} - -exports.CFFCompiler = CFFCompiler; - -/***/ }), -/* 46 */ -/***/ ((__unused_webpack_module, exports) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.ISOAdobeCharset = exports.ExpertSubsetCharset = exports.ExpertCharset = void 0; -const 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"]; -exports.ISOAdobeCharset = ISOAdobeCharset; -const 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"]; -exports.ExpertCharset = ExpertCharset; -const 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"]; -exports.ExpertSubsetCharset = ExpertSubsetCharset; - -/***/ }), -/* 47 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.getSerifFonts = exports.getNonStdFontMap = exports.getGlyphMapForStandardFonts = exports.getFontNameToFileMap = void 0; -exports.getStandardFontName = getStandardFontName; -exports.getSymbolsFonts = exports.getSupplementalGlyphMapForCalibri = exports.getSupplementalGlyphMapForArialBlack = exports.getStdFontMap = void 0; - -var _core_utils = __w_pdfjs_require__(9); - -var _fonts_utils = __w_pdfjs_require__(18); - -const getStdFontMap = (0, _core_utils.getLookupTableFactory)(function (t) { - t["Times-Roman"] = "Times-Roman"; - t.Helvetica = "Helvetica"; - t.Courier = "Courier"; - t.Symbol = "Symbol"; - t["Times-Bold"] = "Times-Bold"; - t["Helvetica-Bold"] = "Helvetica-Bold"; - t["Courier-Bold"] = "Courier-Bold"; - t.ZapfDingbats = "ZapfDingbats"; - t["Times-Italic"] = "Times-Italic"; - t["Helvetica-Oblique"] = "Helvetica-Oblique"; - t["Courier-Oblique"] = "Courier-Oblique"; - t["Times-BoldItalic"] = "Times-BoldItalic"; - t["Helvetica-BoldOblique"] = "Helvetica-BoldOblique"; - t["Courier-BoldOblique"] = "Courier-BoldOblique"; - t.ArialNarrow = "Helvetica"; - t["ArialNarrow-Bold"] = "Helvetica-Bold"; - t["ArialNarrow-BoldItalic"] = "Helvetica-BoldOblique"; - t["ArialNarrow-Italic"] = "Helvetica-Oblique"; - t.ArialBlack = "Helvetica"; - t["ArialBlack-Bold"] = "Helvetica-Bold"; - t["ArialBlack-BoldItalic"] = "Helvetica-BoldOblique"; - t["ArialBlack-Italic"] = "Helvetica-Oblique"; - t["Arial-Black"] = "Helvetica"; - t["Arial-Black-Bold"] = "Helvetica-Bold"; - t["Arial-Black-BoldItalic"] = "Helvetica-BoldOblique"; - t["Arial-Black-Italic"] = "Helvetica-Oblique"; - t.Arial = "Helvetica"; - t["Arial-Bold"] = "Helvetica-Bold"; - t["Arial-BoldItalic"] = "Helvetica-BoldOblique"; - t["Arial-Italic"] = "Helvetica-Oblique"; - t["Arial-BoldItalicMT"] = "Helvetica-BoldOblique"; - t["Arial-BoldMT"] = "Helvetica-Bold"; - t["Arial-ItalicMT"] = "Helvetica-Oblique"; - t.ArialMT = "Helvetica"; - t["Courier-BoldItalic"] = "Courier-BoldOblique"; - t["Courier-Italic"] = "Courier-Oblique"; - t.CourierNew = "Courier"; - t["CourierNew-Bold"] = "Courier-Bold"; - t["CourierNew-BoldItalic"] = "Courier-BoldOblique"; - t["CourierNew-Italic"] = "Courier-Oblique"; - t["CourierNewPS-BoldItalicMT"] = "Courier-BoldOblique"; - t["CourierNewPS-BoldMT"] = "Courier-Bold"; - t["CourierNewPS-ItalicMT"] = "Courier-Oblique"; - t.CourierNewPSMT = "Courier"; - t["Helvetica-BoldItalic"] = "Helvetica-BoldOblique"; - t["Helvetica-Italic"] = "Helvetica-Oblique"; - t["Symbol-Bold"] = "Symbol"; - t["Symbol-BoldItalic"] = "Symbol"; - t["Symbol-Italic"] = "Symbol"; - t.TimesNewRoman = "Times-Roman"; - t["TimesNewRoman-Bold"] = "Times-Bold"; - t["TimesNewRoman-BoldItalic"] = "Times-BoldItalic"; - t["TimesNewRoman-Italic"] = "Times-Italic"; - t.TimesNewRomanPS = "Times-Roman"; - t["TimesNewRomanPS-Bold"] = "Times-Bold"; - t["TimesNewRomanPS-BoldItalic"] = "Times-BoldItalic"; - t["TimesNewRomanPS-BoldItalicMT"] = "Times-BoldItalic"; - t["TimesNewRomanPS-BoldMT"] = "Times-Bold"; - t["TimesNewRomanPS-Italic"] = "Times-Italic"; - t["TimesNewRomanPS-ItalicMT"] = "Times-Italic"; - t.TimesNewRomanPSMT = "Times-Roman"; - t["TimesNewRomanPSMT-Bold"] = "Times-Bold"; - t["TimesNewRomanPSMT-BoldItalic"] = "Times-BoldItalic"; - t["TimesNewRomanPSMT-Italic"] = "Times-Italic"; -}); -exports.getStdFontMap = getStdFontMap; -const getFontNameToFileMap = (0, _core_utils.getLookupTableFactory)(function (t) { - t.Courier = "FoxitFixed.pfb"; - t["Courier-Bold"] = "FoxitFixedBold.pfb"; - t["Courier-BoldOblique"] = "FoxitFixedBoldItalic.pfb"; - t["Courier-Oblique"] = "FoxitFixedItalic.pfb"; - t.Helvetica = "FoxitSans.pfb"; - t["Helvetica-Bold"] = "FoxitSansBold.pfb"; - t["Helvetica-BoldOblique"] = "FoxitSansBoldItalic.pfb"; - t["Helvetica-Oblique"] = "FoxitSansItalic.pfb"; - t["Times-Roman"] = "FoxitSerif.pfb"; - t["Times-Bold"] = "FoxitSerifBold.pfb"; - t["Times-BoldItalic"] = "FoxitSerifBoldItalic.pfb"; - t["Times-Italic"] = "FoxitSerifItalic.pfb"; - t.Symbol = "FoxitSymbol.pfb"; - t.ZapfDingbats = "FoxitDingbats.pfb"; - t["LiberationSans-Regular"] = "LiberationSans-Regular.ttf"; - t["LiberationSans-Bold"] = "LiberationSans-Bold.ttf"; - t["LiberationSans-Italic"] = "LiberationSans-Italic.ttf"; - t["LiberationSans-BoldItalic"] = "LiberationSans-BoldItalic.ttf"; -}); -exports.getFontNameToFileMap = getFontNameToFileMap; -const getNonStdFontMap = (0, _core_utils.getLookupTableFactory)(function (t) { - t.Calibri = "Helvetica"; - t["Calibri-Bold"] = "Helvetica-Bold"; - t["Calibri-BoldItalic"] = "Helvetica-BoldOblique"; - t["Calibri-Italic"] = "Helvetica-Oblique"; - t.CenturyGothic = "Helvetica"; - t["CenturyGothic-Bold"] = "Helvetica-Bold"; - t["CenturyGothic-BoldItalic"] = "Helvetica-BoldOblique"; - t["CenturyGothic-Italic"] = "Helvetica-Oblique"; - t.ComicSansMS = "Comic Sans MS"; - t["ComicSansMS-Bold"] = "Comic Sans MS-Bold"; - t["ComicSansMS-BoldItalic"] = "Comic Sans MS-BoldItalic"; - t["ComicSansMS-Italic"] = "Comic Sans MS-Italic"; - t["ItcSymbol-Bold"] = "Helvetica-Bold"; - t["ItcSymbol-BoldItalic"] = "Helvetica-BoldOblique"; - t["ItcSymbol-Book"] = "Helvetica"; - t["ItcSymbol-BookItalic"] = "Helvetica-Oblique"; - t["ItcSymbol-Medium"] = "Helvetica"; - t["ItcSymbol-MediumItalic"] = "Helvetica-Oblique"; - t.LucidaConsole = "Courier"; - t["LucidaConsole-Bold"] = "Courier-Bold"; - t["LucidaConsole-BoldItalic"] = "Courier-BoldOblique"; - t["LucidaConsole-Italic"] = "Courier-Oblique"; - t["LucidaSans-Demi"] = "Helvetica-Bold"; - t["MS-Gothic"] = "MS Gothic"; - t["MS-Gothic-Bold"] = "MS Gothic-Bold"; - t["MS-Gothic-BoldItalic"] = "MS Gothic-BoldItalic"; - t["MS-Gothic-Italic"] = "MS Gothic-Italic"; - t["MS-Mincho"] = "MS Mincho"; - t["MS-Mincho-Bold"] = "MS Mincho-Bold"; - t["MS-Mincho-BoldItalic"] = "MS Mincho-BoldItalic"; - t["MS-Mincho-Italic"] = "MS Mincho-Italic"; - t["MS-PGothic"] = "MS PGothic"; - t["MS-PGothic-Bold"] = "MS PGothic-Bold"; - t["MS-PGothic-BoldItalic"] = "MS PGothic-BoldItalic"; - t["MS-PGothic-Italic"] = "MS PGothic-Italic"; - t["MS-PMincho"] = "MS PMincho"; - t["MS-PMincho-Bold"] = "MS PMincho-Bold"; - t["MS-PMincho-BoldItalic"] = "MS PMincho-BoldItalic"; - t["MS-PMincho-Italic"] = "MS PMincho-Italic"; - t.NuptialScript = "Times-Italic"; - t.SegoeUISymbol = "Helvetica"; - t.Wingdings = "ZapfDingbats"; - t["Wingdings-Regular"] = "ZapfDingbats"; -}); -exports.getNonStdFontMap = getNonStdFontMap; -const getSerifFonts = (0, _core_utils.getLookupTableFactory)(function (t) { - t["Adobe Jenson"] = true; - t["Adobe Text"] = true; - t.Albertus = true; - t.Aldus = true; - t.Alexandria = true; - t.Algerian = true; - t["American Typewriter"] = true; - t.Antiqua = true; - t.Apex = true; - t.Arno = true; - t.Aster = true; - t.Aurora = true; - t.Baskerville = true; - t.Bell = true; - t.Bembo = true; - t["Bembo Schoolbook"] = true; - t.Benguiat = true; - t["Berkeley Old Style"] = true; - t["Bernhard Modern"] = true; - t["Berthold City"] = true; - t.Bodoni = true; - t["Bauer Bodoni"] = true; - t["Book Antiqua"] = true; - t.Bookman = true; - t["Bordeaux Roman"] = true; - t["Californian FB"] = true; - t.Calisto = true; - t.Calvert = true; - t.Capitals = true; - t.Cambria = true; - t.Cartier = true; - t.Caslon = true; - t.Catull = true; - t.Centaur = true; - t["Century Old Style"] = true; - t["Century Schoolbook"] = true; - t.Chaparral = true; - t["Charis SIL"] = true; - t.Cheltenham = true; - t["Cholla Slab"] = true; - t.Clarendon = true; - t.Clearface = true; - t.Cochin = true; - t.Colonna = true; - t["Computer Modern"] = true; - t["Concrete Roman"] = true; - t.Constantia = true; - t["Cooper Black"] = true; - t.Corona = true; - t.Ecotype = true; - t.Egyptienne = true; - t.Elephant = true; - t.Excelsior = true; - t.Fairfield = true; - t["FF Scala"] = true; - t.Folkard = true; - t.Footlight = true; - t.FreeSerif = true; - t["Friz Quadrata"] = true; - t.Garamond = true; - t.Gentium = true; - t.Georgia = true; - t.Gloucester = true; - t["Goudy Old Style"] = true; - t["Goudy Schoolbook"] = true; - t["Goudy Pro Font"] = true; - t.Granjon = true; - t["Guardian Egyptian"] = true; - t.Heather = true; - t.Hercules = true; - t["High Tower Text"] = true; - t.Hiroshige = true; - t["Hoefler Text"] = true; - t["Humana Serif"] = true; - t.Imprint = true; - t["Ionic No. 5"] = true; - t.Janson = true; - t.Joanna = true; - t.Korinna = true; - t.Lexicon = true; - t.LiberationSerif = true; - t["Liberation Serif"] = true; - t["Linux Libertine"] = true; - t.Literaturnaya = true; - t.Lucida = true; - t["Lucida Bright"] = true; - t.Melior = true; - t.Memphis = true; - t.Miller = true; - t.Minion = true; - t.Modern = true; - t["Mona Lisa"] = true; - t["Mrs Eaves"] = true; - t["MS Serif"] = true; - t["Museo Slab"] = true; - t["New York"] = true; - t["Nimbus Roman"] = true; - t["NPS Rawlinson Roadway"] = true; - t.NuptialScript = true; - t.Palatino = true; - t.Perpetua = true; - t.Plantin = true; - t["Plantin Schoolbook"] = true; - t.Playbill = true; - t["Poor Richard"] = true; - t["Rawlinson Roadway"] = true; - t.Renault = true; - t.Requiem = true; - t.Rockwell = true; - t.Roman = true; - t["Rotis Serif"] = true; - t.Sabon = true; - t.Scala = true; - t.Seagull = true; - t.Sistina = true; - t.Souvenir = true; - t.STIX = true; - t["Stone Informal"] = true; - t["Stone Serif"] = true; - t.Sylfaen = true; - t.Times = true; - t.Trajan = true; - t["Trinité"] = true; - t["Trump Mediaeval"] = true; - t.Utopia = true; - t["Vale Type"] = true; - t["Bitstream Vera"] = true; - t["Vera Serif"] = true; - t.Versailles = true; - t.Wanted = true; - t.Weiss = true; - t["Wide Latin"] = true; - t.Windsor = true; - t.XITS = true; -}); -exports.getSerifFonts = getSerifFonts; -const getSymbolsFonts = (0, _core_utils.getLookupTableFactory)(function (t) { - t.Dingbats = true; - t.Symbol = true; - t.ZapfDingbats = true; -}); -exports.getSymbolsFonts = getSymbolsFonts; -const getGlyphMapForStandardFonts = (0, _core_utils.getLookupTableFactory)(function (t) { - t[2] = 10; - t[3] = 32; - t[4] = 33; - t[5] = 34; - t[6] = 35; - t[7] = 36; - t[8] = 37; - t[9] = 38; - t[10] = 39; - t[11] = 40; - t[12] = 41; - t[13] = 42; - t[14] = 43; - t[15] = 44; - t[16] = 45; - t[17] = 46; - t[18] = 47; - t[19] = 48; - t[20] = 49; - t[21] = 50; - t[22] = 51; - t[23] = 52; - t[24] = 53; - t[25] = 54; - t[26] = 55; - t[27] = 56; - t[28] = 57; - t[29] = 58; - t[30] = 894; - t[31] = 60; - t[32] = 61; - t[33] = 62; - t[34] = 63; - t[35] = 64; - t[36] = 65; - t[37] = 66; - t[38] = 67; - t[39] = 68; - t[40] = 69; - t[41] = 70; - t[42] = 71; - t[43] = 72; - t[44] = 73; - t[45] = 74; - t[46] = 75; - t[47] = 76; - t[48] = 77; - t[49] = 78; - t[50] = 79; - t[51] = 80; - t[52] = 81; - t[53] = 82; - t[54] = 83; - t[55] = 84; - t[56] = 85; - t[57] = 86; - t[58] = 87; - t[59] = 88; - t[60] = 89; - t[61] = 90; - t[62] = 91; - t[63] = 92; - t[64] = 93; - t[65] = 94; - t[66] = 95; - t[67] = 96; - t[68] = 97; - t[69] = 98; - t[70] = 99; - t[71] = 100; - t[72] = 101; - t[73] = 102; - t[74] = 103; - t[75] = 104; - t[76] = 105; - t[77] = 106; - t[78] = 107; - t[79] = 108; - t[80] = 109; - t[81] = 110; - t[82] = 111; - t[83] = 112; - t[84] = 113; - t[85] = 114; - t[86] = 115; - t[87] = 116; - t[88] = 117; - t[89] = 118; - t[90] = 119; - t[91] = 120; - t[92] = 121; - t[93] = 122; - t[94] = 123; - t[95] = 124; - t[96] = 125; - t[97] = 126; - t[98] = 196; - t[99] = 197; - t[100] = 199; - t[101] = 201; - t[102] = 209; - t[103] = 214; - t[104] = 220; - t[105] = 225; - t[106] = 224; - t[107] = 226; - t[108] = 228; - t[109] = 227; - t[110] = 229; - t[111] = 231; - t[112] = 233; - t[113] = 232; - t[114] = 234; - t[115] = 235; - t[116] = 237; - t[117] = 236; - t[118] = 238; - t[119] = 239; - t[120] = 241; - t[121] = 243; - t[122] = 242; - t[123] = 244; - t[124] = 246; - t[125] = 245; - t[126] = 250; - t[127] = 249; - t[128] = 251; - t[129] = 252; - t[130] = 8224; - t[131] = 176; - t[132] = 162; - t[133] = 163; - t[134] = 167; - t[135] = 8226; - t[136] = 182; - t[137] = 223; - t[138] = 174; - t[139] = 169; - t[140] = 8482; - t[141] = 180; - t[142] = 168; - t[143] = 8800; - t[144] = 198; - t[145] = 216; - t[146] = 8734; - t[147] = 177; - t[148] = 8804; - t[149] = 8805; - t[150] = 165; - t[151] = 181; - t[152] = 8706; - t[153] = 8721; - t[154] = 8719; - t[156] = 8747; - t[157] = 170; - t[158] = 186; - t[159] = 8486; - t[160] = 230; - t[161] = 248; - t[162] = 191; - t[163] = 161; - t[164] = 172; - t[165] = 8730; - t[166] = 402; - t[167] = 8776; - t[168] = 8710; - t[169] = 171; - t[170] = 187; - t[171] = 8230; - t[200] = 193; - t[203] = 205; - t[210] = 218; - t[223] = 711; - t[224] = 321; - t[225] = 322; - t[226] = 352; - t[227] = 353; - t[228] = 381; - t[229] = 382; - t[233] = 221; - t[234] = 253; - t[252] = 263; - t[253] = 268; - t[254] = 269; - t[258] = 258; - t[260] = 260; - t[261] = 261; - t[265] = 280; - t[266] = 281; - t[267] = 282; - t[268] = 283; - t[269] = 313; - t[275] = 323; - t[276] = 324; - t[278] = 328; - t[283] = 344; - t[284] = 345; - t[285] = 346; - t[286] = 347; - t[292] = 367; - t[295] = 377; - t[296] = 378; - t[298] = 380; - t[305] = 963; - t[306] = 964; - t[307] = 966; - t[308] = 8215; - t[309] = 8252; - t[310] = 8319; - t[311] = 8359; - t[312] = 8592; - t[313] = 8593; - t[337] = 9552; - t[493] = 1039; - t[494] = 1040; - t[705] = 1524; - t[706] = 8362; - t[710] = 64288; - t[711] = 64298; - t[759] = 1617; - t[761] = 1776; - t[763] = 1778; - t[775] = 1652; - t[777] = 1764; - t[778] = 1780; - t[779] = 1781; - t[780] = 1782; - t[782] = 771; - t[783] = 64726; - t[786] = 8363; - t[788] = 8532; - t[790] = 768; - t[791] = 769; - t[792] = 768; - t[795] = 803; - t[797] = 64336; - t[798] = 64337; - t[799] = 64342; - t[800] = 64343; - t[801] = 64344; - t[802] = 64345; - t[803] = 64362; - t[804] = 64363; - t[805] = 64364; - t[2424] = 7821; - t[2425] = 7822; - t[2426] = 7823; - t[2427] = 7824; - t[2428] = 7825; - t[2429] = 7826; - t[2430] = 7827; - t[2433] = 7682; - t[2678] = 8045; - t[2679] = 8046; - t[2830] = 1552; - t[2838] = 686; - t[2840] = 751; - t[2842] = 753; - t[2843] = 754; - t[2844] = 755; - t[2846] = 757; - t[2856] = 767; - t[2857] = 848; - t[2858] = 849; - t[2862] = 853; - t[2863] = 854; - t[2864] = 855; - t[2865] = 861; - t[2866] = 862; - t[2906] = 7460; - t[2908] = 7462; - t[2909] = 7463; - t[2910] = 7464; - t[2912] = 7466; - t[2913] = 7467; - t[2914] = 7468; - t[2916] = 7470; - t[2917] = 7471; - t[2918] = 7472; - t[2920] = 7474; - t[2921] = 7475; - t[2922] = 7476; - t[2924] = 7478; - t[2925] = 7479; - t[2926] = 7480; - t[2928] = 7482; - t[2929] = 7483; - t[2930] = 7484; - t[2932] = 7486; - t[2933] = 7487; - t[2934] = 7488; - t[2936] = 7490; - t[2937] = 7491; - t[2938] = 7492; - t[2940] = 7494; - t[2941] = 7495; - t[2942] = 7496; - t[2944] = 7498; - t[2946] = 7500; - t[2948] = 7502; - t[2950] = 7504; - t[2951] = 7505; - t[2952] = 7506; - t[2954] = 7508; - t[2955] = 7509; - t[2956] = 7510; - t[2958] = 7512; - t[2959] = 7513; - t[2960] = 7514; - t[2962] = 7516; - t[2963] = 7517; - t[2964] = 7518; - t[2966] = 7520; - t[2967] = 7521; - t[2968] = 7522; - t[2970] = 7524; - t[2971] = 7525; - t[2972] = 7526; - t[2974] = 7528; - t[2975] = 7529; - t[2976] = 7530; - t[2978] = 1537; - t[2979] = 1538; - t[2980] = 1539; - t[2982] = 1549; - t[2983] = 1551; - t[2984] = 1552; - t[2986] = 1554; - t[2987] = 1555; - t[2988] = 1556; - t[2990] = 1623; - t[2991] = 1624; - t[2995] = 1775; - t[2999] = 1791; - t[3002] = 64290; - t[3003] = 64291; - t[3004] = 64292; - t[3006] = 64294; - t[3007] = 64295; - t[3008] = 64296; - t[3011] = 1900; - t[3014] = 8223; - t[3015] = 8244; - t[3017] = 7532; - t[3018] = 7533; - t[3019] = 7534; - t[3075] = 7590; - t[3076] = 7591; - t[3079] = 7594; - t[3080] = 7595; - t[3083] = 7598; - t[3084] = 7599; - t[3087] = 7602; - t[3088] = 7603; - t[3091] = 7606; - t[3092] = 7607; - t[3095] = 7610; - t[3096] = 7611; - t[3099] = 7614; - t[3100] = 7615; - t[3103] = 7618; - t[3104] = 7619; - t[3107] = 8337; - t[3108] = 8338; - t[3116] = 1884; - t[3119] = 1885; - t[3120] = 1885; - t[3123] = 1886; - t[3124] = 1886; - t[3127] = 1887; - t[3128] = 1887; - t[3131] = 1888; - t[3132] = 1888; - t[3135] = 1889; - t[3136] = 1889; - t[3139] = 1890; - t[3140] = 1890; - t[3143] = 1891; - t[3144] = 1891; - t[3147] = 1892; - t[3148] = 1892; - t[3153] = 580; - t[3154] = 581; - t[3157] = 584; - t[3158] = 585; - t[3161] = 588; - t[3162] = 589; - t[3165] = 891; - t[3166] = 892; - t[3169] = 1274; - t[3170] = 1275; - t[3173] = 1278; - t[3174] = 1279; - t[3181] = 7622; - t[3182] = 7623; - t[3282] = 11799; - t[3316] = 578; - t[3379] = 42785; - t[3393] = 1159; - t[3416] = 8377; -}); -exports.getGlyphMapForStandardFonts = getGlyphMapForStandardFonts; -const getSupplementalGlyphMapForArialBlack = (0, _core_utils.getLookupTableFactory)(function (t) { - t[227] = 322; - t[264] = 261; - t[291] = 346; -}); -exports.getSupplementalGlyphMapForArialBlack = getSupplementalGlyphMapForArialBlack; -const getSupplementalGlyphMapForCalibri = (0, _core_utils.getLookupTableFactory)(function (t) { - t[1] = 32; - t[4] = 65; - t[6] = 193; - t[17] = 66; - t[18] = 67; - t[21] = 268; - t[24] = 68; - t[28] = 69; - t[30] = 201; - t[32] = 282; - t[38] = 70; - t[39] = 71; - t[44] = 72; - t[47] = 73; - t[49] = 205; - t[58] = 74; - t[60] = 75; - t[62] = 76; - t[68] = 77; - t[69] = 78; - t[75] = 79; - t[87] = 80; - t[89] = 81; - t[90] = 82; - t[92] = 344; - t[94] = 83; - t[97] = 352; - t[100] = 84; - t[104] = 85; - t[115] = 86; - t[116] = 87; - t[121] = 88; - t[122] = 89; - t[124] = 221; - t[127] = 90; - t[129] = 381; - t[258] = 97; - t[260] = 225; - t[268] = 261; - t[271] = 98; - t[272] = 99; - t[273] = 263; - t[275] = 269; - t[282] = 100; - t[286] = 101; - t[288] = 233; - t[290] = 283; - t[295] = 281; - t[296] = 102; - t[336] = 103; - t[346] = 104; - t[349] = 105; - t[351] = 237; - t[361] = 106; - t[364] = 107; - t[367] = 108; - t[371] = 322; - t[373] = 109; - t[374] = 110; - t[381] = 111; - t[383] = 243; - t[393] = 112; - t[395] = 113; - t[396] = 114; - t[398] = 345; - t[400] = 115; - t[401] = 347; - t[403] = 353; - t[410] = 116; - t[437] = 117; - t[448] = 118; - t[449] = 119; - t[454] = 120; - t[455] = 121; - t[457] = 253; - t[460] = 122; - t[462] = 382; - t[463] = 380; - t[853] = 44; - t[855] = 58; - t[856] = 46; - t[876] = 47; - t[878] = 45; - t[882] = 45; - t[894] = 40; - t[895] = 41; - t[896] = 91; - t[897] = 93; - t[923] = 64; - t[1004] = 48; - t[1005] = 49; - t[1006] = 50; - t[1007] = 51; - t[1008] = 52; - t[1009] = 53; - t[1010] = 54; - t[1011] = 55; - t[1012] = 56; - t[1013] = 57; - t[1081] = 37; - t[1085] = 43; - t[1086] = 45; -}); -exports.getSupplementalGlyphMapForCalibri = getSupplementalGlyphMapForCalibri; - -function getStandardFontName(name) { - const fontName = (0, _fonts_utils.normalizeFontName)(name); - const stdFontMap = getStdFontMap(); - return stdFontMap[fontName]; -} - -/***/ }), -/* 48 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.ToUnicodeMap = exports.IdentityToUnicodeMap = void 0; - -var _util = __w_pdfjs_require__(2); - -class ToUnicodeMap { - constructor(cmap = []) { - this._map = cmap; - } - - get length() { - return this._map.length; - } - - forEach(callback) { - for (const charCode in this._map) { - callback(charCode, this._map[charCode].charCodeAt(0)); - } - } - - has(i) { - return this._map[i] !== undefined; - } - - get(i) { - return this._map[i]; - } - - charCodeOf(value) { - const map = this._map; - - if (map.length <= 0x10000) { - return map.indexOf(value); - } - - for (const charCode in map) { - if (map[charCode] === value) { - return charCode | 0; - } - } - - return -1; - } - - amend(map) { - for (const charCode in map) { - this._map[charCode] = map[charCode]; - } - } - -} - -exports.ToUnicodeMap = ToUnicodeMap; - -class IdentityToUnicodeMap { - constructor(firstChar, lastChar) { - this.firstChar = firstChar; - this.lastChar = lastChar; - } - - get length() { - return this.lastChar + 1 - this.firstChar; - } - - forEach(callback) { - for (let i = this.firstChar, ii = this.lastChar; i <= ii; i++) { - callback(i, i); - } - } - - has(i) { - return this.firstChar <= i && i <= this.lastChar; - } - - get(i) { - if (this.firstChar <= i && i <= this.lastChar) { - return String.fromCharCode(i); - } - - return undefined; - } - - charCodeOf(v) { - return Number.isInteger(v) && v >= this.firstChar && v <= this.lastChar ? v : -1; - } - - amend(map) { - (0, _util.unreachable)("Should not call amend()"); - } - -} - -exports.IdentityToUnicodeMap = IdentityToUnicodeMap; - -/***/ }), -/* 49 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.CFFFont = void 0; - -var _cff_parser = __w_pdfjs_require__(45); - -var _fonts_utils = __w_pdfjs_require__(18); - -var _util = __w_pdfjs_require__(2); - -class CFFFont { - constructor(file, properties) { - this.properties = properties; - const parser = new _cff_parser.CFFParser(file, properties, _fonts_utils.SEAC_ANALYSIS_ENABLED); - this.cff = parser.parse(); - this.cff.duplicateFirstGlyph(); - const compiler = new _cff_parser.CFFCompiler(this.cff); - this.seacs = this.cff.seacs; - - try { - this.data = compiler.compile(); - } catch (e) { - (0, _util.warn)("Failed to compile font " + properties.loadedName); - this.data = file; - } - - this._createBuiltInEncoding(); - } - - get numGlyphs() { - return this.cff.charStrings.count; - } - - getCharset() { - return this.cff.charset.charset; - } - - getGlyphMapping() { - const cff = this.cff; - const properties = this.properties; - const charsets = cff.charset.charset; - let charCodeToGlyphId; - let glyphId; - - if (properties.composite) { - charCodeToGlyphId = Object.create(null); - let charCode; - - if (cff.isCIDFont) { - for (glyphId = 0; glyphId < charsets.length; glyphId++) { - const cid = charsets[glyphId]; - charCode = properties.cMap.charCodeOf(cid); - charCodeToGlyphId[charCode] = glyphId; - } - } else { - for (glyphId = 0; glyphId < cff.charStrings.count; glyphId++) { - charCode = properties.cMap.charCodeOf(glyphId); - charCodeToGlyphId[charCode] = glyphId; - } - } - - return charCodeToGlyphId; - } - - let encoding = cff.encoding ? cff.encoding.encoding : null; - - if (properties.isInternalFont) { - encoding = properties.defaultEncoding; - } - - charCodeToGlyphId = (0, _fonts_utils.type1FontGlyphMapping)(properties, encoding, charsets); - return charCodeToGlyphId; - } - - hasGlyphId(id) { - return this.cff.hasGlyphId(id); - } - - _createBuiltInEncoding() { - const { - charset, - encoding - } = this.cff; - - if (!charset || !encoding) { - return; - } - - const charsets = charset.charset, - encodings = encoding.encoding; - const map = []; - - for (const charCode in encodings) { - const glyphId = encodings[charCode]; - - if (glyphId >= 0) { - const glyphName = charsets[glyphId]; - - if (glyphName) { - map[charCode] = glyphName; - } - } - } - - if (map.length > 0) { - this.properties.builtInEncoding = map; - } - } - -} - -exports.CFFFont = CFFFont; - -/***/ }), -/* 50 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.FontRendererFactory = void 0; - -var _util = __w_pdfjs_require__(2); - -var _cff_parser = __w_pdfjs_require__(45); - -var _glyphlist = __w_pdfjs_require__(20); - -var _encodings = __w_pdfjs_require__(19); - -var _stream = __w_pdfjs_require__(10); - -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 getSubroutineBias(subrs) { - const numSubrs = subrs.length; - let bias = 32768; - - if (numSubrs < 1240) { - bias = 107; - } else if (numSubrs < 33900) { - bias = 1131; - } - - return bias; -} - -function parseCmap(data, start, end) { - const offset = getUshort(data, start + 2) === 1 ? getLong(data, start + 8) : getLong(data, start + 16); - const format = getUshort(data, start + offset); - let ranges, p, i; - - if (format === 4) { - getUshort(data, start + offset + 2); - const segCount = getUshort(data, start + offset + 6) >> 1; - p = start + offset + 14; - ranges = []; - - for (i = 0; i < segCount; i++, p += 2) { - ranges[i] = { - end: getUshort(data, p) - }; - } - - p += 2; - - for (i = 0; i < segCount; i++, p += 2) { - ranges[i].start = getUshort(data, p); - } - - for (i = 0; i < segCount; i++, p += 2) { - ranges[i].idDelta = getUshort(data, p); - } - - for (i = 0; i < segCount; i++, p += 2) { - let idOffset = getUshort(data, p); - - if (idOffset === 0) { - continue; - } - - ranges[i].ids = []; - - for (let 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) { - getLong(data, start + offset + 4); - const groups = getLong(data, start + offset + 12); - p = start + offset + 16; - ranges = []; - - for (i = 0; i < groups; i++) { - ranges.push({ - start: getLong(data, p), - end: getLong(data, p + 4), - idDelta: getLong(data, p + 8) - getLong(data, p) - }); - p += 12; - } - - return ranges; - } - - throw new _util.FormatError(`unsupported cmap: ${format}`); -} - -function parseCff(data, start, end, seacAnalysisEnabled) { - const properties = {}; - const parser = new _cff_parser.CFFParser(new _stream.Stream(data, start, end - start), properties, seacAnalysisEnabled); - const 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, - isCFFCIDFont: cff.isCIDFont, - fdSelect: cff.fdSelect, - fdArray: cff.fdArray - }; -} - -function parseGlyfTable(glyf, loca, isGlyphLocationsLong) { - let 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; - }; - } - - const glyphs = []; - let startOffset = itemDecode(loca, 0); - - for (let j = itemSize; j < loca.length; j += itemSize) { - const endOffset = itemDecode(loca, j); - glyphs.push(glyf.subarray(startOffset, endOffset)); - startOffset = endOffset; - } - - return glyphs; -} - -function lookupCmap(ranges, unicode) { - const code = unicode.codePointAt(0); - let gid = 0, - l = 0, - r = ranges.length - 1; - - while (l < r) { - const 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) { - gid = ranges[l].idDelta + (ranges[l].ids ? ranges[l].ids[code - ranges[l].start] : code) & 0xffff; - } - - return { - charCode: code, - glyphId: gid - }; -} - -function compileGlyf(code, cmds, font) { - function moveTo(x, y) { - cmds.push({ - cmd: "moveTo", - args: [x, y] - }); - } - - function lineTo(x, y) { - cmds.push({ - cmd: "lineTo", - args: [x, y] - }); - } - - function quadraticCurveTo(xa, ya, x, y) { - cmds.push({ - cmd: "quadraticCurveTo", - args: [xa, ya, x, y] - }); - } - - let i = 0; - const numberOfContours = (code[i] << 24 | code[i + 1] << 16) >> 16; - let flags; - let x = 0, - y = 0; - i += 10; - - if (numberOfContours < 0) { - do { - flags = code[i] << 8 | code[i + 1]; - const glyphIndex = code[i + 2] << 8 | code[i + 3]; - i += 4; - let 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; - } - - let 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; - } - - const subglyph = font.glyphs[glyphIndex]; - - if (subglyph) { - cmds.push({ - cmd: "save" - }, { - cmd: "transform", - args: [scaleX, scale01, scale10, scaleY, x, y] - }); - compileGlyf(subglyph, cmds, font); - cmds.push({ - cmd: "restore" - }); - } - } while (flags & 0x20); - } else { - const endPtsOfContours = []; - let j, jj; - - for (j = 0; j < numberOfContours; j++) { - endPtsOfContours.push(code[i] << 8 | code[i + 1]); - i += 2; - } - - const instructionLength = code[i] << 8 | code[i + 1]; - i += 2 + instructionLength; - const numberOfPoints = endPtsOfContours[endPtsOfContours.length - 1] + 1; - const points = []; - - while (points.length < numberOfPoints) { - flags = code[i++]; - let repeat = 1; - - if (flags & 0x08) { - repeat += code[i++]; - } - - while (repeat-- > 0) { - points.push({ - flags - }); - } - } - - for (j = 0; j < numberOfPoints; j++) { - switch (points[j].flags & 0x12) { - case 0x00: - x += (code[i] << 24 | code[i + 1] << 16) >> 16; - i += 2; - break; - - case 0x02: - x -= code[i++]; - break; - - case 0x12: - x += code[i++]; - break; - } - - points[j].x = x; - } - - for (j = 0; j < numberOfPoints; j++) { - switch (points[j].flags & 0x24) { - case 0x00: - y += (code[i] << 24 | code[i + 1] << 16) >> 16; - i += 2; - break; - - case 0x04: - y -= code[i++]; - break; - - case 0x24: - y += code[i++]; - break; - } - - points[j].y = y; - } - - let startPoint = 0; - - for (i = 0; i < numberOfContours; i++) { - const endPoint = endPtsOfContours[i]; - const contour = points.slice(startPoint, endPoint + 1); - - if (contour[0].flags & 1) { - contour.push(contour[0]); - } else if (contour[contour.length - 1].flags & 1) { - contour.unshift(contour[contour.length - 1]); - } else { - const p = { - flags: 1, - x: (contour[0].x + contour[contour.length - 1].x) / 2, - y: (contour[0].y + contour[contour.length - 1].y) / 2 - }; - contour.unshift(p); - contour.push(p); - } - - moveTo(contour[0].x, contour[0].y); - - for (j = 1, jj = contour.length; j < jj; j++) { - if (contour[j].flags & 1) { - lineTo(contour[j].x, contour[j].y); - } else if (contour[j + 1].flags & 1) { - quadraticCurveTo(contour[j].x, contour[j].y, contour[j + 1].x, contour[j + 1].y); - j++; - } else { - quadraticCurveTo(contour[j].x, contour[j].y, (contour[j].x + contour[j + 1].x) / 2, (contour[j].y + contour[j + 1].y) / 2); - } - } - - startPoint = endPoint + 1; - } - } -} - -function compileCharString(charStringCode, cmds, font, glyphId) { - function moveTo(x, y) { - cmds.push({ - cmd: "moveTo", - args: [x, y] - }); - } - - function lineTo(x, y) { - cmds.push({ - cmd: "lineTo", - args: [x, y] - }); - } - - function bezierCurveTo(x1, y1, x2, y2, x, y) { - cmds.push({ - cmd: "bezierCurveTo", - args: [x1, y1, x2, y2, x, y] - }); - } - - const stack = []; - let x = 0, - y = 0; - let stems = 0; - - function parse(code) { - let i = 0; - - while (i < code.length) { - let stackClean = false; - let v = code[i++]; - let xa, xb, ya, yb, y1, y2, y3, n, subrCode; - - switch (v) { - case 1: - stems += stack.length >> 1; - stackClean = true; - break; - - case 3: - stems += stack.length >> 1; - stackClean = true; - break; - - case 4: - y += stack.pop(); - moveTo(x, y); - stackClean = true; - break; - - case 5: - while (stack.length > 0) { - x += stack.shift(); - y += stack.shift(); - lineTo(x, y); - } - - break; - - case 6: - while (stack.length > 0) { - x += stack.shift(); - lineTo(x, y); - - if (stack.length === 0) { - break; - } - - y += stack.shift(); - lineTo(x, y); - } - - break; - - case 7: - while (stack.length > 0) { - y += stack.shift(); - lineTo(x, y); - - if (stack.length === 0) { - break; - } - - x += stack.shift(); - lineTo(x, y); - } - - break; - - case 8: - while (stack.length > 0) { - xa = x + stack.shift(); - ya = y + stack.shift(); - xb = xa + stack.shift(); - yb = ya + stack.shift(); - x = xb + stack.shift(); - y = yb + stack.shift(); - bezierCurveTo(xa, ya, xb, yb, x, y); - } - - break; - - case 10: - n = stack.pop(); - subrCode = null; - - if (font.isCFFCIDFont) { - const fdIndex = font.fdSelect.getFDIndex(glyphId); - - if (fdIndex >= 0 && fdIndex < font.fdArray.length) { - const fontDict = font.fdArray[fdIndex]; - let subrs; - - if (fontDict.privateDict && fontDict.privateDict.subrsIndex) { - subrs = fontDict.privateDict.subrsIndex.objects; - } - - if (subrs) { - n += getSubroutineBias(subrs); - subrCode = subrs[n]; - } - } else { - (0, _util.warn)("Invalid fd index for glyph index."); - } - } else { - subrCode = font.subrs[n + font.subrsBias]; - } - - if (subrCode) { - parse(subrCode); - } - - break; - - case 11: - return; - - case 12: - v = code[i++]; - - switch (v) { - case 34: - xa = x + stack.shift(); - xb = xa + stack.shift(); - y1 = y + stack.shift(); - x = xb + stack.shift(); - bezierCurveTo(xa, y, xb, y1, x, y1); - xa = x + stack.shift(); - xb = xa + stack.shift(); - x = xb + stack.shift(); - bezierCurveTo(xa, y1, xb, y, x, y); - break; - - case 35: - xa = x + stack.shift(); - ya = y + stack.shift(); - xb = xa + stack.shift(); - yb = ya + stack.shift(); - x = xb + stack.shift(); - y = yb + stack.shift(); - bezierCurveTo(xa, ya, xb, yb, x, y); - xa = x + stack.shift(); - ya = y + stack.shift(); - xb = xa + stack.shift(); - yb = ya + stack.shift(); - x = xb + stack.shift(); - y = yb + stack.shift(); - bezierCurveTo(xa, ya, xb, yb, x, y); - stack.pop(); - break; - - case 36: - xa = x + stack.shift(); - y1 = y + stack.shift(); - xb = xa + stack.shift(); - y2 = y1 + stack.shift(); - x = xb + stack.shift(); - bezierCurveTo(xa, y1, xb, y2, x, y2); - xa = x + stack.shift(); - xb = xa + stack.shift(); - y3 = y2 + stack.shift(); - x = xb + stack.shift(); - bezierCurveTo(xa, y2, xb, y3, x, y); - break; - - case 37: - const x0 = x, - y0 = y; - xa = x + stack.shift(); - ya = y + stack.shift(); - xb = xa + stack.shift(); - yb = ya + stack.shift(); - x = xb + stack.shift(); - y = yb + stack.shift(); - bezierCurveTo(xa, ya, xb, yb, x, y); - xa = x + stack.shift(); - ya = y + stack.shift(); - xb = xa + stack.shift(); - yb = ya + stack.shift(); - x = xb; - y = yb; - - if (Math.abs(x - x0) > Math.abs(y - y0)) { - x += stack.shift(); - } else { - y += stack.shift(); - } - - bezierCurveTo(xa, ya, xb, yb, x, y); - break; - - default: - throw new _util.FormatError(`unknown operator: 12 ${v}`); - } - - break; - - case 14: - if (stack.length >= 4) { - const achar = stack.pop(); - const bchar = stack.pop(); - y = stack.pop(); - x = stack.pop(); - cmds.push({ - cmd: "save" - }, { - cmd: "translate", - args: [x, y] - }); - let cmap = lookupCmap(font.cmap, String.fromCharCode(font.glyphNameMap[_encodings.StandardEncoding[achar]])); - compileCharString(font.glyphs[cmap.glyphId], cmds, font, cmap.glyphId); - cmds.push({ - cmd: "restore" - }); - cmap = lookupCmap(font.cmap, String.fromCharCode(font.glyphNameMap[_encodings.StandardEncoding[bchar]])); - compileCharString(font.glyphs[cmap.glyphId], cmds, font, cmap.glyphId); - } - - return; - - case 18: - stems += stack.length >> 1; - stackClean = true; - break; - - case 19: - stems += stack.length >> 1; - i += stems + 7 >> 3; - stackClean = true; - break; - - case 20: - stems += stack.length >> 1; - i += stems + 7 >> 3; - stackClean = true; - break; - - case 21: - y += stack.pop(); - x += stack.pop(); - moveTo(x, y); - stackClean = true; - break; - - case 22: - x += stack.pop(); - moveTo(x, y); - stackClean = true; - break; - - case 23: - stems += stack.length >> 1; - stackClean = true; - break; - - case 24: - while (stack.length > 2) { - xa = x + stack.shift(); - ya = y + stack.shift(); - xb = xa + stack.shift(); - yb = ya + stack.shift(); - x = xb + stack.shift(); - y = yb + stack.shift(); - bezierCurveTo(xa, ya, xb, yb, x, y); - } - - x += stack.shift(); - y += stack.shift(); - lineTo(x, y); - break; - - case 25: - while (stack.length > 6) { - x += stack.shift(); - y += stack.shift(); - lineTo(x, y); - } - - xa = x + stack.shift(); - ya = y + stack.shift(); - xb = xa + stack.shift(); - yb = ya + stack.shift(); - x = xb + stack.shift(); - y = yb + stack.shift(); - bezierCurveTo(xa, ya, xb, yb, x, y); - break; - - case 26: - if (stack.length % 2) { - x += stack.shift(); - } - - while (stack.length > 0) { - xa = x; - ya = y + stack.shift(); - xb = xa + stack.shift(); - yb = ya + stack.shift(); - x = xb; - y = yb + stack.shift(); - bezierCurveTo(xa, ya, xb, yb, x, y); - } - - break; - - case 27: - if (stack.length % 2) { - y += stack.shift(); - } - - while (stack.length > 0) { - xa = x + stack.shift(); - ya = y; - xb = xa + stack.shift(); - yb = ya + stack.shift(); - x = xb + stack.shift(); - y = yb; - bezierCurveTo(xa, ya, xb, yb, x, y); - } - - break; - - case 28: - stack.push((code[i] << 24 | code[i + 1] << 16) >> 16); - i += 2; - break; - - case 29: - n = stack.pop() + font.gsubrsBias; - subrCode = font.gsubrs[n]; - - if (subrCode) { - parse(subrCode); - } - - break; - - case 30: - while (stack.length > 0) { - xa = x; - ya = y + stack.shift(); - xb = xa + stack.shift(); - yb = ya + stack.shift(); - x = xb + stack.shift(); - y = yb + (stack.length === 1 ? stack.shift() : 0); - bezierCurveTo(xa, ya, xb, yb, x, y); - - if (stack.length === 0) { - break; - } - - xa = x + stack.shift(); - ya = y; - xb = xa + stack.shift(); - yb = ya + stack.shift(); - y = yb + stack.shift(); - x = xb + (stack.length === 1 ? stack.shift() : 0); - bezierCurveTo(xa, ya, xb, yb, x, y); - } - - break; - - case 31: - while (stack.length > 0) { - xa = x + stack.shift(); - ya = y; - xb = xa + stack.shift(); - yb = ya + stack.shift(); - y = yb + stack.shift(); - x = xb + (stack.length === 1 ? stack.shift() : 0); - bezierCurveTo(xa, ya, xb, yb, x, y); - - if (stack.length === 0) { - break; - } - - xa = x; - ya = y + stack.shift(); - xb = xa + stack.shift(); - yb = ya + stack.shift(); - x = xb + stack.shift(); - y = yb + (stack.length === 1 ? stack.shift() : 0); - bezierCurveTo(xa, ya, xb, yb, x, y); - } - - break; - - default: - if (v < 32) { - throw new _util.FormatError(`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(charStringCode); -} - -const NOOP = []; - -class CompiledFont { - constructor(fontMatrix) { - if (this.constructor === CompiledFont) { - (0, _util.unreachable)("Cannot initialize CompiledFont."); - } - - this.fontMatrix = fontMatrix; - this.compiledGlyphs = Object.create(null); - this.compiledCharCodeToGlyphId = Object.create(null); - } - - getPathJs(unicode) { - const { - charCode, - glyphId - } = lookupCmap(this.cmap, unicode); - let fn = this.compiledGlyphs[glyphId]; - - if (!fn) { - try { - fn = this.compileGlyph(this.glyphs[glyphId], glyphId); - this.compiledGlyphs[glyphId] = fn; - } catch (ex) { - this.compiledGlyphs[glyphId] = NOOP; - - if (this.compiledCharCodeToGlyphId[charCode] === undefined) { - this.compiledCharCodeToGlyphId[charCode] = glyphId; - } - - throw ex; - } - } - - if (this.compiledCharCodeToGlyphId[charCode] === undefined) { - this.compiledCharCodeToGlyphId[charCode] = glyphId; - } - - return fn; - } - - compileGlyph(code, glyphId) { - if (!code || code.length === 0 || code[0] === 14) { - return NOOP; - } - - let fontMatrix = this.fontMatrix; - - if (this.isCFFCIDFont) { - const fdIndex = this.fdSelect.getFDIndex(glyphId); - - if (fdIndex >= 0 && fdIndex < this.fdArray.length) { - const fontDict = this.fdArray[fdIndex]; - fontMatrix = fontDict.getByName("FontMatrix") || _util.FONT_IDENTITY_MATRIX; - } else { - (0, _util.warn)("Invalid fd index for glyph index."); - } - } - - const cmds = [{ - cmd: "save" - }, { - cmd: "transform", - args: fontMatrix.slice() - }, { - cmd: "scale", - args: ["size", "-size"] - }]; - this.compileGlyphImpl(code, cmds, glyphId); - cmds.push({ - cmd: "restore" - }); - return cmds; - } - - compileGlyphImpl() { - (0, _util.unreachable)("Children classes should implement this."); - } - - hasBuiltPath(unicode) { - const { - charCode, - glyphId - } = lookupCmap(this.cmap, unicode); - return this.compiledGlyphs[glyphId] !== undefined && this.compiledCharCodeToGlyphId[charCode] !== undefined; - } - -} - -class TrueTypeCompiled extends CompiledFont { - constructor(glyphs, cmap, fontMatrix) { - super(fontMatrix || [0.000488, 0, 0, 0.000488, 0, 0]); - this.glyphs = glyphs; - this.cmap = cmap; - } - - compileGlyphImpl(code, cmds) { - compileGlyf(code, cmds, this); - } - -} - -class Type2Compiled extends CompiledFont { - constructor(cffInfo, cmap, fontMatrix, glyphNameMap) { - super(fontMatrix || [0.001, 0, 0, 0.001, 0, 0]); - this.glyphs = cffInfo.glyphs; - this.gsubrs = cffInfo.gsubrs || []; - this.subrs = cffInfo.subrs || []; - this.cmap = cmap; - this.glyphNameMap = glyphNameMap || (0, _glyphlist.getGlyphsUnicode)(); - this.gsubrsBias = getSubroutineBias(this.gsubrs); - this.subrsBias = getSubroutineBias(this.subrs); - this.isCFFCIDFont = cffInfo.isCFFCIDFont; - this.fdSelect = cffInfo.fdSelect; - this.fdArray = cffInfo.fdArray; - } - - compileGlyphImpl(code, cmds, glyphId) { - compileCharString(code, cmds, this, glyphId); - } - -} - -class FontRendererFactory { - static create(font, seacAnalysisEnabled) { - const data = new Uint8Array(font.data); - let cmap, glyf, loca, cff, indexToLocFormat, unitsPerEm; - const numTables = getUshort(data, 4); - - for (let i = 0, p = 12; i < numTables; i++, p += 16) { - const tag = (0, _util.bytesToString)(data.subarray(p, p + 4)); - const offset = getLong(data, p + 8); - const 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, seacAnalysisEnabled); - break; - } - } - - if (glyf) { - const fontMatrix = !unitsPerEm ? font.fontMatrix : [1 / unitsPerEm, 0, 0, 1 / unitsPerEm, 0, 0]; - return new TrueTypeCompiled(parseGlyfTable(glyf, loca, indexToLocFormat), cmap, fontMatrix); - } - - return new Type2Compiled(cff, cmap, font.fontMatrix, font.glyphNameMap); - } - -} - -exports.FontRendererFactory = FontRendererFactory; - -/***/ }), -/* 51 */ -/***/ ((__unused_webpack_module, exports) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.GlyfTable = void 0; -const ON_CURVE_POINT = 1 << 0; -const X_SHORT_VECTOR = 1 << 1; -const Y_SHORT_VECTOR = 1 << 2; -const REPEAT_FLAG = 1 << 3; -const X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR = 1 << 4; -const Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR = 1 << 5; -const OVERLAP_SIMPLE = 1 << 6; -const ARG_1_AND_2_ARE_WORDS = 1 << 0; -const ARGS_ARE_XY_VALUES = 1 << 1; -const WE_HAVE_A_SCALE = 1 << 3; -const MORE_COMPONENTS = 1 << 5; -const WE_HAVE_AN_X_AND_Y_SCALE = 1 << 6; -const WE_HAVE_A_TWO_BY_TWO = 1 << 7; -const WE_HAVE_INSTRUCTIONS = 1 << 8; - -class GlyfTable { - constructor({ - glyfTable, - isGlyphLocationsLong, - locaTable, - numGlyphs - }) { - this.glyphs = []; - const loca = new DataView(locaTable.buffer, locaTable.byteOffset, locaTable.byteLength); - const glyf = new DataView(glyfTable.buffer, glyfTable.byteOffset, glyfTable.byteLength); - const offsetSize = isGlyphLocationsLong ? 4 : 2; - let prev = isGlyphLocationsLong ? loca.getUint32(0) : 2 * loca.getUint16(0); - let pos = 0; - - for (let i = 0; i < numGlyphs; i++) { - pos += offsetSize; - const next = isGlyphLocationsLong ? loca.getUint32(pos) : 2 * loca.getUint16(pos); - - if (next === prev) { - this.glyphs.push(new Glyph({})); - continue; - } - - const glyph = Glyph.parse(prev, glyf); - this.glyphs.push(glyph); - prev = next; - } - } - - getSize() { - return this.glyphs.reduce((a, g) => { - const size = g.getSize(); - return a + (size + 3 & ~3); - }, 0); - } - - write() { - const totalSize = this.getSize(); - const glyfTable = new DataView(new ArrayBuffer(totalSize)); - const isLocationLong = totalSize > 0x1fffe; - const offsetSize = isLocationLong ? 4 : 2; - const locaTable = new DataView(new ArrayBuffer((this.glyphs.length + 1) * offsetSize)); - - if (isLocationLong) { - locaTable.setUint32(0, 0); - } else { - locaTable.setUint16(0, 0); - } - - let pos = 0; - let locaIndex = 0; - - for (const glyph of this.glyphs) { - pos += glyph.write(pos, glyfTable); - pos = pos + 3 & ~3; - locaIndex += offsetSize; - - if (isLocationLong) { - locaTable.setUint32(locaIndex, pos); - } else { - locaTable.setUint16(locaIndex, pos >> 1); - } - } - - return { - isLocationLong, - loca: new Uint8Array(locaTable.buffer), - glyf: new Uint8Array(glyfTable.buffer) - }; - } - - scale(factors) { - for (let i = 0, ii = this.glyphs.length; i < ii; i++) { - this.glyphs[i].scale(factors[i]); - } - } - -} - -exports.GlyfTable = GlyfTable; - -class Glyph { - constructor({ - header = null, - simple = null, - composites = null - }) { - this.header = header; - this.simple = simple; - this.composites = composites; - } - - static parse(pos, glyf) { - const [read, header] = GlyphHeader.parse(pos, glyf); - pos += read; - - if (header.numberOfContours < 0) { - const composites = []; - - while (true) { - const [n, composite] = CompositeGlyph.parse(pos, glyf); - pos += n; - composites.push(composite); - - if (!(composite.flags & MORE_COMPONENTS)) { - break; - } - } - - return new Glyph({ - header, - composites - }); - } - - const simple = SimpleGlyph.parse(pos, glyf, header.numberOfContours); - return new Glyph({ - header, - simple - }); - } - - getSize() { - if (!this.header) { - return 0; - } - - const size = this.simple ? this.simple.getSize() : this.composites.reduce((a, c) => a + c.getSize(), 0); - return this.header.getSize() + size; - } - - write(pos, buf) { - if (!this.header) { - return 0; - } - - const spos = pos; - pos += this.header.write(pos, buf); - - if (this.simple) { - pos += this.simple.write(pos, buf); - } else { - for (const composite of this.composites) { - pos += composite.write(pos, buf); - } - } - - return pos - spos; - } - - scale(factor) { - if (!this.header) { - return; - } - - const xMiddle = (this.header.xMin + this.header.xMax) / 2; - this.header.scale(xMiddle, factor); - - if (this.simple) { - this.simple.scale(xMiddle, factor); - } else { - for (const composite of this.composites) { - composite.scale(xMiddle, factor); - } - } - } - -} - -class GlyphHeader { - constructor({ - numberOfContours, - xMin, - yMin, - xMax, - yMax - }) { - this.numberOfContours = numberOfContours; - this.xMin = xMin; - this.yMin = yMin; - this.xMax = xMax; - this.yMax = yMax; - } - - static parse(pos, glyf) { - return [10, new GlyphHeader({ - numberOfContours: glyf.getInt16(pos), - xMin: glyf.getInt16(pos + 2), - yMin: glyf.getInt16(pos + 4), - xMax: glyf.getInt16(pos + 6), - yMax: glyf.getInt16(pos + 8) - })]; - } - - getSize() { - return 10; - } - - write(pos, buf) { - buf.setInt16(pos, this.numberOfContours); - buf.setInt16(pos + 2, this.xMin); - buf.setInt16(pos + 4, this.yMin); - buf.setInt16(pos + 6, this.xMax); - buf.setInt16(pos + 8, this.yMax); - return 10; - } - - scale(x, factor) { - this.xMin = Math.round(x + (this.xMin - x) * factor); - this.xMax = Math.round(x + (this.xMax - x) * factor); - } - -} - -class Contour { - constructor({ - flags, - xCoordinates, - yCoordinates - }) { - this.xCoordinates = xCoordinates; - this.yCoordinates = yCoordinates; - this.flags = flags; - } - -} - -class SimpleGlyph { - constructor({ - contours, - instructions - }) { - this.contours = contours; - this.instructions = instructions; - } - - static parse(pos, glyf, numberOfContours) { - const endPtsOfContours = []; - - for (let i = 0; i < numberOfContours; i++) { - const endPt = glyf.getUint16(pos); - pos += 2; - endPtsOfContours.push(endPt); - } - - const numberOfPt = endPtsOfContours[numberOfContours - 1] + 1; - const instructionLength = glyf.getUint16(pos); - pos += 2; - const instructions = new Uint8Array(glyf).slice(pos, pos + instructionLength); - pos += instructionLength; - const flags = []; - - for (let i = 0; i < numberOfPt; pos++, i++) { - let flag = glyf.getUint8(pos); - flags.push(flag); - - if (flag & REPEAT_FLAG) { - const count = glyf.getUint8(++pos); - flag ^= REPEAT_FLAG; - - for (let m = 0; m < count; m++) { - flags.push(flag); - } - - i += count; - } - } - - const allXCoordinates = []; - let xCoordinates = []; - let yCoordinates = []; - let pointFlags = []; - const contours = []; - let endPtsOfContoursIndex = 0; - let lastCoordinate = 0; - - for (let i = 0; i < numberOfPt; i++) { - const flag = flags[i]; - - if (flag & X_SHORT_VECTOR) { - const x = glyf.getUint8(pos++); - lastCoordinate += flag & X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR ? x : -x; - xCoordinates.push(lastCoordinate); - } else if (flag & X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR) { - xCoordinates.push(lastCoordinate); - } else { - lastCoordinate += glyf.getInt16(pos); - pos += 2; - xCoordinates.push(lastCoordinate); - } - - if (endPtsOfContours[endPtsOfContoursIndex] === i) { - endPtsOfContoursIndex++; - allXCoordinates.push(xCoordinates); - xCoordinates = []; - } - } - - lastCoordinate = 0; - endPtsOfContoursIndex = 0; - - for (let i = 0; i < numberOfPt; i++) { - const flag = flags[i]; - - if (flag & Y_SHORT_VECTOR) { - const y = glyf.getUint8(pos++); - lastCoordinate += flag & Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR ? y : -y; - yCoordinates.push(lastCoordinate); - } else if (flag & Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR) { - yCoordinates.push(lastCoordinate); - } else { - lastCoordinate += glyf.getInt16(pos); - pos += 2; - yCoordinates.push(lastCoordinate); - } - - pointFlags.push(flag & ON_CURVE_POINT | flag & OVERLAP_SIMPLE); - - if (endPtsOfContours[endPtsOfContoursIndex] === i) { - xCoordinates = allXCoordinates[endPtsOfContoursIndex]; - endPtsOfContoursIndex++; - contours.push(new Contour({ - flags: pointFlags, - xCoordinates, - yCoordinates - })); - yCoordinates = []; - pointFlags = []; - } - } - - return new SimpleGlyph({ - contours, - instructions - }); - } - - getSize() { - let size = this.contours.length * 2 + 2 + this.instructions.length; - let lastX = 0; - let lastY = 0; - - for (const contour of this.contours) { - size += contour.flags.length; - - for (let i = 0, ii = contour.xCoordinates.length; i < ii; i++) { - const x = contour.xCoordinates[i]; - const y = contour.yCoordinates[i]; - let abs = Math.abs(x - lastX); - - if (abs > 255) { - size += 2; - } else if (abs > 0) { - size += 1; - } - - lastX = x; - abs = Math.abs(y - lastY); - - if (abs > 255) { - size += 2; - } else if (abs > 0) { - size += 1; - } - - lastY = y; - } - } - - return size; - } - - write(pos, buf) { - const spos = pos; - const xCoordinates = []; - const yCoordinates = []; - const flags = []; - let lastX = 0; - let lastY = 0; - - for (const contour of this.contours) { - for (let i = 0, ii = contour.xCoordinates.length; i < ii; i++) { - let flag = contour.flags[i]; - const x = contour.xCoordinates[i]; - let delta = x - lastX; - - if (delta === 0) { - flag |= X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR; - xCoordinates.push(0); - } else { - const abs = Math.abs(delta); - - if (abs <= 255) { - flag |= delta >= 0 ? X_SHORT_VECTOR | X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR : X_SHORT_VECTOR; - xCoordinates.push(abs); - } else { - xCoordinates.push(delta); - } - } - - lastX = x; - const y = contour.yCoordinates[i]; - delta = y - lastY; - - if (delta === 0) { - flag |= Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR; - yCoordinates.push(0); - } else { - const abs = Math.abs(delta); - - if (abs <= 255) { - flag |= delta >= 0 ? Y_SHORT_VECTOR | Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR : Y_SHORT_VECTOR; - yCoordinates.push(abs); - } else { - yCoordinates.push(delta); - } - } - - lastY = y; - flags.push(flag); - } - - buf.setUint16(pos, xCoordinates.length - 1); - pos += 2; - } - - buf.setUint16(pos, this.instructions.length); - pos += 2; - - if (this.instructions.length) { - new Uint8Array(buf.buffer, 0, buf.buffer.byteLength).set(this.instructions, pos); - pos += this.instructions.length; - } - - for (const flag of flags) { - buf.setUint8(pos++, flag); - } - - for (let i = 0, ii = xCoordinates.length; i < ii; i++) { - const x = xCoordinates[i]; - const flag = flags[i]; - - if (flag & X_SHORT_VECTOR) { - buf.setUint8(pos++, x); - } else if (!(flag & X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR)) { - buf.setInt16(pos, x); - pos += 2; - } - } - - for (let i = 0, ii = yCoordinates.length; i < ii; i++) { - const y = yCoordinates[i]; - const flag = flags[i]; - - if (flag & Y_SHORT_VECTOR) { - buf.setUint8(pos++, y); - } else if (!(flag & Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR)) { - buf.setInt16(pos, y); - pos += 2; - } - } - - return pos - spos; - } - - scale(x, factor) { - for (const contour of this.contours) { - if (contour.xCoordinates.length === 0) { - continue; - } - - for (let i = 0, ii = contour.xCoordinates.length; i < ii; i++) { - contour.xCoordinates[i] = Math.round(x + (contour.xCoordinates[i] - x) * factor); - } - } - } - -} - -class CompositeGlyph { - constructor({ - flags, - glyphIndex, - argument1, - argument2, - transf, - instructions - }) { - this.flags = flags; - this.glyphIndex = glyphIndex; - this.argument1 = argument1; - this.argument2 = argument2; - this.transf = transf; - this.instructions = instructions; - } - - static parse(pos, glyf) { - const spos = pos; - const transf = []; - let flags = glyf.getUint16(pos); - const glyphIndex = glyf.getUint16(pos + 2); - pos += 4; - let argument1, argument2; - - if (flags & ARG_1_AND_2_ARE_WORDS) { - if (flags & ARGS_ARE_XY_VALUES) { - argument1 = glyf.getInt16(pos); - argument2 = glyf.getInt16(pos + 2); - } else { - argument1 = glyf.getUint16(pos); - argument2 = glyf.getUint16(pos + 2); - } - - pos += 4; - flags ^= ARG_1_AND_2_ARE_WORDS; - } else { - argument1 = glyf.getUint8(pos); - argument2 = glyf.getUint8(pos + 1); - - if (flags & ARGS_ARE_XY_VALUES) { - const abs1 = argument1 & 0x7f; - argument1 = argument1 & 0x80 ? -abs1 : abs1; - const abs2 = argument2 & 0x7f; - argument2 = argument2 & 0x80 ? -abs2 : abs2; - } - - pos += 2; - } - - if (flags & WE_HAVE_A_SCALE) { - transf.push(glyf.getUint16(pos)); - pos += 2; - } else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) { - transf.push(glyf.getUint16(pos), glyf.getUint16(pos + 2)); - pos += 4; - } else if (flags & WE_HAVE_A_TWO_BY_TWO) { - transf.push(glyf.getUint16(pos), glyf.getUint16(pos + 2), glyf.getUint16(pos + 4), glyf.getUint16(pos + 6)); - pos += 8; - } - - let instructions = null; - - if (flags & WE_HAVE_INSTRUCTIONS) { - const instructionLength = glyf.getUint16(pos); - pos += 2; - instructions = new Uint8Array(glyf).slice(pos, pos + instructionLength); - pos += instructionLength; - } - - return [pos - spos, new CompositeGlyph({ - flags, - glyphIndex, - argument1, - argument2, - transf, - instructions - })]; - } - - getSize() { - let size = 2 + 2 + this.transf.length * 2; - - if (this.flags & WE_HAVE_INSTRUCTIONS) { - size += 2 + this.instructions.length; - } - - size += 2; - - if (this.flags & 2) { - if (!(this.argument1 >= -128 && this.argument1 <= 127 && this.argument2 >= -128 && this.argument2 <= 127)) { - size += 2; - } - } else { - if (!(this.argument1 >= 0 && this.argument1 <= 255 && this.argument2 >= 0 && this.argument2 <= 255)) { - size += 2; - } - } - - return size; - } - - write(pos, buf) { - const spos = pos; - - if (this.flags & ARGS_ARE_XY_VALUES) { - if (!(this.argument1 >= -128 && this.argument1 <= 127 && this.argument2 >= -128 && this.argument2 <= 127)) { - this.flags |= ARG_1_AND_2_ARE_WORDS; - } - } else { - if (!(this.argument1 >= 0 && this.argument1 <= 255 && this.argument2 >= 0 && this.argument2 <= 255)) { - this.flags |= ARG_1_AND_2_ARE_WORDS; - } - } - - buf.setUint16(pos, this.flags); - buf.setUint16(pos + 2, this.glyphIndex); - pos += 4; - - if (this.flags & ARG_1_AND_2_ARE_WORDS) { - if (this.flags & ARGS_ARE_XY_VALUES) { - buf.setInt16(pos, this.argument1); - buf.setInt16(pos + 2, this.argument2); - } else { - buf.setUint16(pos, this.argument1); - buf.setUint16(pos + 2, this.argument2); - } - - pos += 4; - } else { - buf.setUint8(pos, this.argument1); - buf.setUint8(pos + 1, this.argument2); - pos += 2; - } - - if (this.flags & WE_HAVE_INSTRUCTIONS) { - buf.setUint16(pos, this.instructions.length); - pos += 2; - - if (this.instructions.length) { - new Uint8Array(buf.buffer, 0, buf.buffer.byteLength).set(this.instructions, pos); - pos += this.instructions.length; - } - } - - return pos - spos; - } - - scale(x, factor) {} - -} - -/***/ }), -/* 52 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.OpenTypeFileBuilder = void 0; - -var _core_utils = __w_pdfjs_require__(9); - -var _util = __w_pdfjs_require__(2); - -function writeInt16(dest, offset, num) { - dest[offset] = num >> 8 & 0xff; - dest[offset + 1] = num & 0xff; -} - -function writeInt32(dest, offset, num) { - dest[offset] = num >> 24 & 0xff; - dest[offset + 1] = num >> 16 & 0xff; - dest[offset + 2] = num >> 8 & 0xff; - dest[offset + 3] = num & 0xff; -} - -function writeData(dest, offset, data) { - if (data instanceof Uint8Array) { - dest.set(data, offset); - } else if (typeof data === "string") { - for (let i = 0, ii = data.length; i < ii; i++) { - dest[offset++] = data.charCodeAt(i) & 0xff; - } - } else { - for (let i = 0, ii = data.length; i < ii; i++) { - dest[offset++] = data[i] & 0xff; - } - } -} - -const OTF_HEADER_SIZE = 12; -const OTF_TABLE_ENTRY_SIZE = 16; - -class OpenTypeFileBuilder { - constructor(sfnt) { - this.sfnt = sfnt; - this.tables = Object.create(null); - } - - static getSearchParams(entriesCount, entrySize) { - let maxPower2 = 1, - log2 = 0; - - while ((maxPower2 ^ entriesCount) > maxPower2) { - maxPower2 <<= 1; - log2++; - } - - const searchRange = maxPower2 * entrySize; - return { - range: searchRange, - entry: log2, - rangeShift: entrySize * entriesCount - searchRange - }; - } - - toArray() { - let sfnt = this.sfnt; - const tables = this.tables; - const tablesNames = Object.keys(tables); - tablesNames.sort(); - const numTables = tablesNames.length; - let i, j, jj, table, tableName; - let offset = OTF_HEADER_SIZE + numTables * OTF_TABLE_ENTRY_SIZE; - const tableOffsets = [offset]; - - for (i = 0; i < numTables; i++) { - table = tables[tablesNames[i]]; - const paddedLength = (table.length + 3 & ~3) >>> 0; - offset += paddedLength; - tableOffsets.push(offset); - } - - const file = new Uint8Array(offset); - - for (i = 0; i < numTables; i++) { - table = tables[tablesNames[i]]; - writeData(file, tableOffsets[i], table); - } - - if (sfnt === "true") { - sfnt = (0, _util.string32)(0x00010000); - } - - file[0] = sfnt.charCodeAt(0) & 0xff; - file[1] = sfnt.charCodeAt(1) & 0xff; - file[2] = sfnt.charCodeAt(2) & 0xff; - file[3] = sfnt.charCodeAt(3) & 0xff; - writeInt16(file, 4, numTables); - const searchParams = OpenTypeFileBuilder.getSearchParams(numTables, 16); - writeInt16(file, 6, searchParams.range); - writeInt16(file, 8, searchParams.entry); - writeInt16(file, 10, searchParams.rangeShift); - offset = OTF_HEADER_SIZE; - - for (i = 0; i < numTables; i++) { - tableName = tablesNames[i]; - file[offset] = tableName.charCodeAt(0) & 0xff; - file[offset + 1] = tableName.charCodeAt(1) & 0xff; - file[offset + 2] = tableName.charCodeAt(2) & 0xff; - file[offset + 3] = tableName.charCodeAt(3) & 0xff; - let checksum = 0; - - for (j = tableOffsets[i], jj = tableOffsets[i + 1]; j < jj; j += 4) { - const quad = (0, _core_utils.readUint32)(file, j); - checksum = checksum + quad >>> 0; - } - - writeInt32(file, offset + 4, checksum); - writeInt32(file, offset + 8, tableOffsets[i]); - writeInt32(file, offset + 12, tables[tableName].length); - offset += OTF_TABLE_ENTRY_SIZE; - } - - return file; - } - - addTable(tag, data) { - if (tag in this.tables) { - throw new Error("Table " + tag + " already exists"); - } - - this.tables[tag] = data; - } - -} - -exports.OpenTypeFileBuilder = OpenTypeFileBuilder; - -/***/ }), -/* 53 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.Type1Font = void 0; - -var _cff_parser = __w_pdfjs_require__(45); - -var _fonts_utils = __w_pdfjs_require__(18); - -var _core_utils = __w_pdfjs_require__(9); - -var _stream = __w_pdfjs_require__(10); - -var _type1_parser = __w_pdfjs_require__(54); - -var _util = __w_pdfjs_require__(2); - -function findBlock(streamBytes, signature, startIndex) { - const streamBytesLength = streamBytes.length; - const signatureLength = signature.length; - const scanLength = streamBytesLength - signatureLength; - let i = startIndex, - found = false; - - while (i < scanLength) { - let j = 0; - - while (j < signatureLength && streamBytes[i + j] === signature[j]) { - j++; - } - - if (j >= signatureLength) { - i += j; - - while (i < streamBytesLength && (0, _core_utils.isWhiteSpace)(streamBytes[i])) { - i++; - } - - found = true; - break; - } - - i++; - } - - return { - found, - length: i - }; -} - -function getHeaderBlock(stream, suggestedLength) { - const EEXEC_SIGNATURE = [0x65, 0x65, 0x78, 0x65, 0x63]; - const streamStartPos = stream.pos; - let headerBytes, headerBytesLength, block; - - try { - headerBytes = stream.getBytes(suggestedLength); - headerBytesLength = headerBytes.length; - } catch (ex) {} - - if (headerBytesLength === suggestedLength) { - block = findBlock(headerBytes, EEXEC_SIGNATURE, suggestedLength - 2 * EEXEC_SIGNATURE.length); - - if (block.found && block.length === suggestedLength) { - return { - stream: new _stream.Stream(headerBytes), - length: suggestedLength - }; - } - } - - (0, _util.warn)('Invalid "Length1" property in Type1 font -- trying to recover.'); - stream.pos = streamStartPos; - const SCAN_BLOCK_LENGTH = 2048; - let actualLength; - - while (true) { - const scanBytes = stream.peekBytes(SCAN_BLOCK_LENGTH); - block = findBlock(scanBytes, EEXEC_SIGNATURE, 0); - - if (block.length === 0) { - break; - } - - stream.pos += block.length; - - if (block.found) { - actualLength = stream.pos - streamStartPos; - break; - } - } - - stream.pos = streamStartPos; - - if (actualLength) { - return { - stream: new _stream.Stream(stream.getBytes(actualLength)), - length: actualLength - }; - } - - (0, _util.warn)('Unable to recover "Length1" property in Type1 font -- using as is.'); - return { - stream: new _stream.Stream(stream.getBytes(suggestedLength)), - length: suggestedLength - }; -} - -function getEexecBlock(stream, suggestedLength) { - const eexecBytes = stream.getBytes(); - return { - stream: new _stream.Stream(eexecBytes), - length: eexecBytes.length - }; -} - -class Type1Font { - constructor(name, file, properties) { - const PFB_HEADER_SIZE = 6; - let headerBlockLength = properties.length1; - let eexecBlockLength = properties.length2; - let pfbHeader = file.peekBytes(PFB_HEADER_SIZE); - const pfbHeaderPresent = pfbHeader[0] === 0x80 && pfbHeader[1] === 0x01; - - if (pfbHeaderPresent) { - file.skip(PFB_HEADER_SIZE); - headerBlockLength = pfbHeader[5] << 24 | pfbHeader[4] << 16 | pfbHeader[3] << 8 | pfbHeader[2]; - } - - const headerBlock = getHeaderBlock(file, headerBlockLength); - const headerBlockParser = new _type1_parser.Type1Parser(headerBlock.stream, false, _fonts_utils.SEAC_ANALYSIS_ENABLED); - headerBlockParser.extractFontHeader(properties); - - if (pfbHeaderPresent) { - pfbHeader = file.getBytes(PFB_HEADER_SIZE); - eexecBlockLength = pfbHeader[5] << 24 | pfbHeader[4] << 16 | pfbHeader[3] << 8 | pfbHeader[2]; - } - - const eexecBlock = getEexecBlock(file, eexecBlockLength); - const eexecBlockParser = new _type1_parser.Type1Parser(eexecBlock.stream, true, _fonts_utils.SEAC_ANALYSIS_ENABLED); - const data = eexecBlockParser.extractFontProgram(properties); - - for (const key in data.properties) { - properties[key] = data.properties[key]; - } - - const charstrings = data.charstrings; - const type2Charstrings = this.getType2Charstrings(charstrings); - const subrs = this.getType2Subrs(data.subrs); - this.charstrings = charstrings; - this.data = this.wrap(name, type2Charstrings, this.charstrings, subrs, properties); - this.seacs = this.getSeacs(data.charstrings); - } - - get numGlyphs() { - return this.charstrings.length + 1; - } - - getCharset() { - const charset = [".notdef"]; - const charstrings = this.charstrings; - - for (let glyphId = 0; glyphId < charstrings.length; glyphId++) { - charset.push(charstrings[glyphId].glyphName); - } - - return charset; - } - - getGlyphMapping(properties) { - const charstrings = this.charstrings; - - if (properties.composite) { - const charCodeToGlyphId = Object.create(null); - - for (let glyphId = 0, charstringsLen = charstrings.length; glyphId < charstringsLen; glyphId++) { - const charCode = properties.cMap.charCodeOf(glyphId); - charCodeToGlyphId[charCode] = glyphId + 1; - } - - return charCodeToGlyphId; - } - - const glyphNames = [".notdef"]; - let builtInEncoding, glyphId; - - for (glyphId = 0; glyphId < charstrings.length; glyphId++) { - glyphNames.push(charstrings[glyphId].glyphName); - } - - const encoding = properties.builtInEncoding; - - if (encoding) { - builtInEncoding = Object.create(null); - - for (const charCode in encoding) { - glyphId = glyphNames.indexOf(encoding[charCode]); - - if (glyphId >= 0) { - builtInEncoding[charCode] = glyphId; - } - } - } - - return (0, _fonts_utils.type1FontGlyphMapping)(properties, builtInEncoding, glyphNames); - } - - hasGlyphId(id) { - if (id < 0 || id >= this.numGlyphs) { - return false; - } - - if (id === 0) { - return true; - } - - const glyph = this.charstrings[id - 1]; - return glyph.charstring.length > 0; - } - - getSeacs(charstrings) { - const seacMap = []; - - for (let i = 0, ii = charstrings.length; i < ii; i++) { - const charstring = charstrings[i]; - - if (charstring.seac) { - seacMap[i + 1] = charstring.seac; - } - } - - return seacMap; - } - - getType2Charstrings(type1Charstrings) { - const type2Charstrings = []; - - for (let i = 0, ii = type1Charstrings.length; i < ii; i++) { - type2Charstrings.push(type1Charstrings[i].charstring); - } - - return type2Charstrings; - } - - getType2Subrs(type1Subrs) { - let bias = 0; - const count = type1Subrs.length; - - if (count < 1133) { - bias = 107; - } else if (count < 33769) { - bias = 1131; - } else { - bias = 32768; - } - - const type2Subrs = []; - let i; - - for (i = 0; i < bias; i++) { - type2Subrs.push([0x0b]); - } - - for (i = 0; i < count; i++) { - type2Subrs.push(type1Subrs[i]); - } - - return type2Subrs; - } - - wrap(name, glyphs, charstrings, subrs, properties) { - const cff = new _cff_parser.CFF(); - cff.header = new _cff_parser.CFFHeader(1, 0, 4, 4); - cff.names = [name]; - const topDict = new _cff_parser.CFFTopDict(); - topDict.setByName("version", 391); - topDict.setByName("Notice", 392); - topDict.setByName("FullName", 393); - topDict.setByName("FamilyName", 394); - topDict.setByName("Weight", 395); - topDict.setByName("Encoding", null); - topDict.setByName("FontMatrix", properties.fontMatrix); - topDict.setByName("FontBBox", properties.bbox); - topDict.setByName("charset", null); - topDict.setByName("CharStrings", null); - topDict.setByName("Private", null); - cff.topDict = topDict; - const strings = new _cff_parser.CFFStrings(); - strings.add("Version 0.11"); - strings.add("See original notice"); - strings.add(name); - strings.add(name); - strings.add("Medium"); - cff.strings = strings; - cff.globalSubrIndex = new _cff_parser.CFFIndex(); - const count = glyphs.length; - const charsetArray = [".notdef"]; - let i, ii; - - for (i = 0; i < count; i++) { - const glyphName = charstrings[i].glyphName; - - const index = _cff_parser.CFFStandardStrings.indexOf(glyphName); - - if (index === -1) { - strings.add(glyphName); - } - - charsetArray.push(glyphName); - } - - cff.charset = new _cff_parser.CFFCharset(false, 0, charsetArray); - const charStringsIndex = new _cff_parser.CFFIndex(); - charStringsIndex.add([0x8b, 0x0e]); - - for (i = 0; i < count; i++) { - charStringsIndex.add(glyphs[i]); - } - - cff.charStrings = charStringsIndex; - const privateDict = new _cff_parser.CFFPrivateDict(); - privateDict.setByName("Subrs", null); - const fields = ["BlueValues", "OtherBlues", "FamilyBlues", "FamilyOtherBlues", "StemSnapH", "StemSnapV", "BlueShift", "BlueFuzz", "BlueScale", "LanguageGroup", "ExpansionFactor", "ForceBold", "StdHW", "StdVW"]; - - for (i = 0, ii = fields.length; i < ii; i++) { - const field = fields[i]; - - if (!(field in properties.privateData)) { - continue; - } - - const value = properties.privateData[field]; - - if (Array.isArray(value)) { - for (let j = value.length - 1; j > 0; j--) { - value[j] -= value[j - 1]; - } - } - - privateDict.setByName(field, value); - } - - cff.topDict.privateDict = privateDict; - const subrIndex = new _cff_parser.CFFIndex(); - - for (i = 0, ii = subrs.length; i < ii; i++) { - subrIndex.add(subrs[i]); - } - - privateDict.subrsIndex = subrIndex; - const compiler = new _cff_parser.CFFCompiler(cff); - return compiler.compile(); - } - -} - -exports.Type1Font = Type1Font; - -/***/ }), -/* 54 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.Type1Parser = void 0; - -var _encodings = __w_pdfjs_require__(19); - -var _core_utils = __w_pdfjs_require__(9); - -var _stream = __w_pdfjs_require__(10); - -var _util = __w_pdfjs_require__(2); - -const HINTING_ENABLED = false; - -const Type1CharString = function Type1CharStringClosure() { - const 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] - }; - - class Type1CharString { - constructor() { - this.width = 0; - this.lsb = 0; - this.flexing = false; - this.output = []; - this.stack = []; - } - - convert(encoded, subrs, seacAnalysisEnabled) { - const count = encoded.length; - let error = false; - let wx, sbx, subrNumber; - - for (let i = 0; i < count; i++) { - let value = encoded[i]; - - if (value < 32) { - if (value === 12) { - value = (value << 8) + encoded[++i]; - } - - switch (value) { - case 1: - if (!HINTING_ENABLED) { - this.stack = []; - break; - } - - error = this.executeCommand(2, COMMAND_MAP.hstem); - break; - - case 3: - if (!HINTING_ENABLED) { - this.stack = []; - break; - } - - error = this.executeCommand(2, COMMAND_MAP.vstem); - break; - - case 4: - if (this.flexing) { - if (this.stack.length < 1) { - error = true; - break; - } - - const dy = this.stack.pop(); - this.stack.push(0, dy); - break; - } - - error = this.executeCommand(1, COMMAND_MAP.vmoveto); - break; - - case 5: - error = this.executeCommand(2, COMMAND_MAP.rlineto); - break; - - case 6: - error = this.executeCommand(1, COMMAND_MAP.hlineto); - break; - - case 7: - error = this.executeCommand(1, COMMAND_MAP.vlineto); - break; - - case 8: - error = this.executeCommand(6, COMMAND_MAP.rrcurveto); - break; - - case 9: - this.stack = []; - break; - - case 10: - if (this.stack.length < 1) { - error = true; - break; - } - - subrNumber = this.stack.pop(); - - if (!subrs[subrNumber]) { - error = true; - break; - } - - error = this.convert(subrs[subrNumber], subrs, seacAnalysisEnabled); - break; - - case 11: - return error; - - case 13: - if (this.stack.length < 2) { - error = true; - break; - } - - wx = this.stack.pop(); - sbx = this.stack.pop(); - this.lsb = sbx; - this.width = wx; - this.stack.push(wx, sbx); - error = this.executeCommand(2, COMMAND_MAP.hmoveto); - break; - - case 14: - this.output.push(COMMAND_MAP.endchar[0]); - break; - - case 21: - if (this.flexing) { - break; - } - - error = this.executeCommand(2, COMMAND_MAP.rmoveto); - break; - - case 22: - if (this.flexing) { - this.stack.push(0); - break; - } - - error = this.executeCommand(1, COMMAND_MAP.hmoveto); - break; - - case 30: - error = this.executeCommand(4, COMMAND_MAP.vhcurveto); - break; - - case 31: - error = this.executeCommand(4, COMMAND_MAP.hvcurveto); - break; - - case (12 << 8) + 0: - this.stack = []; - break; - - case (12 << 8) + 1: - if (!HINTING_ENABLED) { - this.stack = []; - break; - } - - error = this.executeCommand(2, COMMAND_MAP.vstem); - break; - - case (12 << 8) + 2: - if (!HINTING_ENABLED) { - this.stack = []; - break; - } - - error = this.executeCommand(2, COMMAND_MAP.hstem); - break; - - case (12 << 8) + 6: - if (seacAnalysisEnabled) { - const asb = this.stack[this.stack.length - 5]; - this.seac = this.stack.splice(-4, 4); - this.seac[0] += this.lsb - asb; - error = this.executeCommand(0, COMMAND_MAP.endchar); - } else { - error = this.executeCommand(4, COMMAND_MAP.endchar); - } - - break; - - case (12 << 8) + 7: - if (this.stack.length < 4) { - error = true; - break; - } - - this.stack.pop(); - wx = this.stack.pop(); - const sby = this.stack.pop(); - sbx = this.stack.pop(); - this.lsb = sbx; - this.width = wx; - this.stack.push(wx, sbx, sby); - error = this.executeCommand(3, COMMAND_MAP.rmoveto); - break; - - case (12 << 8) + 12: - if (this.stack.length < 2) { - error = true; - break; - } - - const num2 = this.stack.pop(); - const num1 = this.stack.pop(); - this.stack.push(num1 / num2); - break; - - case (12 << 8) + 16: - if (this.stack.length < 2) { - error = true; - break; - } - - subrNumber = this.stack.pop(); - const numArgs = this.stack.pop(); - - if (subrNumber === 0 && numArgs === 3) { - const flexArgs = this.stack.splice(this.stack.length - 17, 17); - this.stack.push(flexArgs[2] + flexArgs[0], flexArgs[3] + flexArgs[1], flexArgs[4], flexArgs[5], flexArgs[6], flexArgs[7], flexArgs[8], flexArgs[9], flexArgs[10], flexArgs[11], flexArgs[12], flexArgs[13], flexArgs[14]); - 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: - break; - - case (12 << 8) + 33: - this.stack = []; - break; - - default: - (0, _util.warn)('Unknown type 1 charstring command of "' + value + '"'); - break; - } - - if (error) { - break; - } - - continue; - } else if (value <= 246) { - 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(howManyArgs, command, keepStack) { - const stackLength = this.stack.length; - - if (howManyArgs > stackLength) { - return true; - } - - const start = stackLength - howManyArgs; - - for (let i = start; i < stackLength; i++) { - let value = this.stack[i]; - - if (Number.isInteger(value)) { - this.output.push(28, value >> 8 & 0xff, value & 0xff); - } else { - value = 65536 * value | 0; - this.output.push(255, value >> 24 & 0xff, value >> 16 & 0xff, value >> 8 & 0xff, value & 0xff); - } - } - - this.output.push.apply(this.output, command); - - if (keepStack) { - this.stack.splice(start, howManyArgs); - } else { - this.stack.length = 0; - } - - return false; - } - - } - - return Type1CharString; -}(); - -const Type1Parser = function Type1ParserClosure() { - const EEXEC_ENCRYPT_KEY = 55665; - const CHAR_STRS_ENCRYPT_KEY = 4330; - - function isHexDigit(code) { - return code >= 48 && code <= 57 || code >= 65 && code <= 70 || code >= 97 && code <= 102; - } - - function decrypt(data, key, discardNumber) { - if (discardNumber >= data.length) { - return new Uint8Array(0); - } - - const c1 = 52845, - c2 = 22719; - let r = key | 0, - i, - j; - - for (i = 0; i < discardNumber; i++) { - r = (data[i] + r) * c1 + c2 & (1 << 16) - 1; - } - - const count = data.length - discardNumber; - const decrypted = new Uint8Array(count); - - for (i = discardNumber, j = 0; j < count; i++, j++) { - const value = data[i]; - decrypted[j] = value ^ r >> 8; - r = (value + r) * c1 + c2 & (1 << 16) - 1; - } - - return decrypted; - } - - function decryptAscii(data, key, discardNumber) { - const c1 = 52845, - c2 = 22719; - let r = key | 0; - const count = data.length, - maybeLength = count >>> 1; - const decrypted = new Uint8Array(maybeLength); - let i, j; - - for (i = 0, j = 0; i < count; i++) { - const digit1 = data[i]; - - if (!isHexDigit(digit1)) { - continue; - } - - i++; - let digit2; - - while (i < count && !isHexDigit(digit2 = data[i])) { - i++; - } - - if (i < count) { - const value = parseInt(String.fromCharCode(digit1, digit2), 16); - decrypted[j++] = value ^ r >> 8; - r = (value + r) * c1 + c2 & (1 << 16) - 1; - } - } - - return decrypted.slice(discardNumber, j); - } - - function isSpecial(c) { - return c === 0x2f || c === 0x5b || c === 0x5d || c === 0x7b || c === 0x7d || c === 0x28 || c === 0x29; - } - - class Type1Parser { - constructor(stream, encrypted, seacAnalysisEnabled) { - if (encrypted) { - const data = stream.getBytes(); - const isBinary = !((isHexDigit(data[0]) || (0, _core_utils.isWhiteSpace)(data[0])) && isHexDigit(data[1]) && isHexDigit(data[2]) && isHexDigit(data[3]) && isHexDigit(data[4]) && isHexDigit(data[5]) && isHexDigit(data[6]) && isHexDigit(data[7])); - stream = new _stream.Stream(isBinary ? decrypt(data, EEXEC_ENCRYPT_KEY, 4) : decryptAscii(data, EEXEC_ENCRYPT_KEY, 4)); - } - - this.seacAnalysisEnabled = !!seacAnalysisEnabled; - this.stream = stream; - this.nextChar(); - } - - readNumberArray() { - this.getToken(); - const array = []; - - while (true) { - const token = this.getToken(); - - if (token === null || token === "]" || token === "}") { - break; - } - - array.push(parseFloat(token || 0)); - } - - return array; - } - - readNumber() { - const token = this.getToken(); - return parseFloat(token || 0); - } - - readInt() { - const token = this.getToken(); - return parseInt(token || 0, 10) | 0; - } - - readBoolean() { - const token = this.getToken(); - return token === "true" ? 1 : 0; - } - - nextChar() { - return this.currentChar = this.stream.getByte(); - } - - getToken() { - let comment = false; - let 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 (!(0, _core_utils.isWhiteSpace)(ch)) { - break; - } - - ch = this.nextChar(); - } - - if (isSpecial(ch)) { - this.nextChar(); - return String.fromCharCode(ch); - } - - let token = ""; - - do { - token += String.fromCharCode(ch); - ch = this.nextChar(); - } while (ch >= 0 && !(0, _core_utils.isWhiteSpace)(ch) && !isSpecial(ch)); - - return token; - } - - readCharStrings(bytes, lenIV) { - if (lenIV === -1) { - return bytes; - } - - return decrypt(bytes, CHAR_STRS_ENCRYPT_KEY, lenIV); - } - - extractFontProgram(properties) { - const stream = this.stream; - const subrs = [], - charstrings = []; - const privateData = Object.create(null); - privateData.lenIV = 4; - const program = { - subrs: [], - charstrings: [], - properties: { - privateData - } - }; - let token, length, data, lenIV, encoded; - - while ((token = this.getToken()) !== null) { - if (token !== "/") { - continue; - } - - token = this.getToken(); - - switch (token) { - case "CharStrings": - this.getToken(); - this.getToken(); - this.getToken(); - this.getToken(); - - while (true) { - token = this.getToken(); - - if (token === null || token === "end") { - break; - } - - if (token !== "/") { - continue; - } - - const glyph = this.getToken(); - length = this.readInt(); - this.getToken(); - data = length > 0 ? stream.getBytes(length) : new Uint8Array(0); - lenIV = program.properties.privateData.lenIV; - encoded = this.readCharStrings(data, lenIV); - this.nextChar(); - token = this.getToken(); - - if (token === "noaccess") { - this.getToken(); - } - - charstrings.push({ - glyph, - encoded - }); - } - - break; - - case "Subrs": - this.readInt(); - this.getToken(); - - while (this.getToken() === "dup") { - const index = this.readInt(); - length = this.readInt(); - this.getToken(); - data = length > 0 ? stream.getBytes(length) : new Uint8Array(0); - lenIV = program.properties.privateData.lenIV; - encoded = this.readCharStrings(data, lenIV); - this.nextChar(); - token = this.getToken(); - - if (token === "noaccess") { - this.getToken(); - } - - subrs[index] = encoded; - } - - break; - - case "BlueValues": - case "OtherBlues": - case "FamilyBlues": - case "FamilyOtherBlues": - const blueArray = this.readNumberArray(); - - 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 (let i = 0; i < charstrings.length; i++) { - const glyph = charstrings[i].glyph; - encoded = charstrings[i].encoded; - const charString = new Type1CharString(); - const error = charString.convert(encoded, subrs, this.seacAnalysisEnabled); - let output = charString.output; - - if (error) { - output = [14]; - } - - const charStringObject = { - glyphName: glyph, - charstring: output, - width: charString.width, - lsb: charString.lsb, - seac: charString.seac - }; - - if (glyph === ".notdef") { - program.charstrings.unshift(charStringObject); - } else { - program.charstrings.push(charStringObject); - } - - if (properties.builtInEncoding) { - const index = properties.builtInEncoding.indexOf(glyph); - - if (index > -1 && properties.widths[index] === undefined && index >= properties.firstChar && index <= properties.lastChar) { - properties.widths[index] = charString.width; - } - } - } - - return program; - } - - extractFontHeader(properties) { - let token; - - while ((token = this.getToken()) !== null) { - if (token !== "/") { - continue; - } - - token = this.getToken(); - - switch (token) { - case "FontMatrix": - const matrix = this.readNumberArray(); - properties.fontMatrix = matrix; - break; - - case "Encoding": - const encodingArg = this.getToken(); - let encoding; - - if (!/^\d+$/.test(encodingArg)) { - encoding = (0, _encodings.getEncoding)(encodingArg); - } else { - encoding = []; - const size = parseInt(encodingArg, 10) | 0; - this.getToken(); - - for (let j = 0; j < size; j++) { - token = this.getToken(); - - while (token !== "dup" && token !== "def") { - token = this.getToken(); - - if (token === null) { - return; - } - } - - if (token === "def") { - break; - } - - const index = this.readInt(); - this.getToken(); - const glyph = this.getToken(); - encoding[index] = glyph; - this.getToken(); - } - } - - properties.builtInEncoding = encoding; - break; - - case "FontBBox": - const fontBBox = this.readNumberArray(); - properties.ascent = Math.max(fontBBox[3], fontBBox[1]); - properties.descent = Math.min(fontBBox[1], fontBBox[3]); - properties.ascentScaled = true; - break; - } - } - } - - } - - return Type1Parser; -}(); - -exports.Type1Parser = Type1Parser; - -/***/ }), -/* 55 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.Pattern = void 0; -exports.getTilingPatternIR = getTilingPatternIR; - -var _util = __w_pdfjs_require__(2); - -var _colorspace = __w_pdfjs_require__(24); - -var _primitives = __w_pdfjs_require__(5); - -var _core_utils = __w_pdfjs_require__(9); - -const ShadingType = { - FUNCTION_BASED: 1, - AXIAL: 2, - RADIAL: 3, - FREE_FORM_MESH: 4, - LATTICE_FORM_MESH: 5, - COONS_PATCH_MESH: 6, - TENSOR_PATCH_MESH: 7 -}; - -class Pattern { - constructor() { - (0, _util.unreachable)("Cannot initialize Pattern."); - } - - static parseShading(shading, xref, res, handler, pdfFunctionFactory, localColorSpaceCache) { - const dict = (0, _primitives.isStream)(shading) ? shading.dict : shading; - const type = dict.get("ShadingType"); - - try { - switch (type) { - case ShadingType.AXIAL: - case ShadingType.RADIAL: - return new RadialAxialShading(dict, xref, res, pdfFunctionFactory, localColorSpaceCache); - - case ShadingType.FREE_FORM_MESH: - case ShadingType.LATTICE_FORM_MESH: - case ShadingType.COONS_PATCH_MESH: - case ShadingType.TENSOR_PATCH_MESH: - return new MeshShading(shading, xref, res, pdfFunctionFactory, localColorSpaceCache); - - default: - throw new _util.FormatError("Unsupported ShadingType: " + type); - } - } catch (ex) { - if (ex instanceof _core_utils.MissingDataException) { - throw ex; - } - - handler.send("UnsupportedFeature", { - featureId: _util.UNSUPPORTED_FEATURES.shadingPattern - }); - (0, _util.warn)(ex); - return new DummyShading(); - } - } - -} - -exports.Pattern = Pattern; - -class BaseShading { - static get SMALL_NUMBER() { - return (0, _util.shadow)(this, "SMALL_NUMBER", 1e-6); - } - - constructor() { - if (this.constructor === BaseShading) { - (0, _util.unreachable)("Cannot initialize BaseShading."); - } - } - - getIR() { - (0, _util.unreachable)("Abstract method `getIR` called."); - } - -} - -class RadialAxialShading extends BaseShading { - constructor(dict, xref, resources, pdfFunctionFactory, localColorSpaceCache) { - super(); - this.coordsArr = dict.getArray("Coords"); - this.shadingType = dict.get("ShadingType"); - - const cs = _colorspace.ColorSpace.parse({ - cs: dict.getRaw("CS") || dict.getRaw("ColorSpace"), - xref, - resources, - pdfFunctionFactory, - localColorSpaceCache - }); - - const bbox = dict.getArray("BBox"); - - if (Array.isArray(bbox) && bbox.length === 4) { - this.bbox = _util.Util.normalizeRect(bbox); - } else { - this.bbox = null; - } - - let t0 = 0.0, - t1 = 1.0; - - if (dict.has("Domain")) { - const domainArr = dict.getArray("Domain"); - t0 = domainArr[0]; - t1 = domainArr[1]; - } - - let extendStart = false, - extendEnd = false; - - if (dict.has("Extend")) { - const extendArr = dict.getArray("Extend"); - extendStart = extendArr[0]; - extendEnd = extendArr[1]; - } - - if (this.shadingType === ShadingType.RADIAL && (!extendStart || !extendEnd)) { - const [x1, y1, r1, x2, y2, r2] = this.coordsArr; - const distance = Math.hypot(x1 - x2, y1 - y2); - - if (r1 <= r2 + distance && r2 <= r1 + distance) { - (0, _util.warn)("Unsupported radial gradient."); - } - } - - this.extendStart = extendStart; - this.extendEnd = extendEnd; - const fnObj = dict.getRaw("Function"); - const fn = pdfFunctionFactory.createFromArray(fnObj); - const NUMBER_OF_SAMPLES = 10; - const step = (t1 - t0) / NUMBER_OF_SAMPLES; - const colorStops = this.colorStops = []; - - if (t0 >= t1 || step <= 0) { - (0, _util.info)("Bad shading domain."); - return; - } - - const color = new Float32Array(cs.numComps), - ratio = new Float32Array(1); - let rgbColor; - - for (let i = 0; i <= NUMBER_OF_SAMPLES; i++) { - ratio[0] = t0 + i * step; - fn(ratio, 0, color, 0); - rgbColor = cs.getRgb(color, 0); - - const cssColor = _util.Util.makeHexColor(rgbColor[0], rgbColor[1], rgbColor[2]); - - colorStops.push([i / NUMBER_OF_SAMPLES, cssColor]); - } - - let background = "transparent"; - - if (dict.has("Background")) { - rgbColor = cs.getRgb(dict.get("Background"), 0); - background = _util.Util.makeHexColor(rgbColor[0], rgbColor[1], rgbColor[2]); - } - - if (!extendStart) { - colorStops.unshift([0, background]); - colorStops[1][0] += BaseShading.SMALL_NUMBER; - } - - if (!extendEnd) { - colorStops[colorStops.length - 1][0] -= BaseShading.SMALL_NUMBER; - colorStops.push([1, background]); - } - - this.colorStops = colorStops; - } - - getIR() { - const coordsArr = this.coordsArr; - const shadingType = this.shadingType; - let type, p0, p1, r0, r1; - - if (shadingType === ShadingType.AXIAL) { - p0 = [coordsArr[0], coordsArr[1]]; - p1 = [coordsArr[2], coordsArr[3]]; - r0 = null; - r1 = null; - type = "axial"; - } else if (shadingType === ShadingType.RADIAL) { - p0 = [coordsArr[0], coordsArr[1]]; - p1 = [coordsArr[3], coordsArr[4]]; - r0 = coordsArr[2]; - r1 = coordsArr[5]; - type = "radial"; - } else { - (0, _util.unreachable)(`getPattern type unknown: ${shadingType}`); - } - - return ["RadialAxial", type, this.bbox, this.colorStops, p0, p1, r0, r1]; - } - -} - -class MeshStreamReader { - constructor(stream, context) { - this.stream = stream; - this.context = context; - this.buffer = 0; - this.bufferLength = 0; - const numComps = context.numComps; - this.tmpCompsBuf = new Float32Array(numComps); - const csNumComps = context.colorSpace.numComps; - this.tmpCsCompsBuf = context.colorFn ? new Float32Array(csNumComps) : this.tmpCompsBuf; - } - - get hasData() { - if (this.stream.end) { - return this.stream.pos < this.stream.end; - } - - if (this.bufferLength > 0) { - return true; - } - - const nextByte = this.stream.getByte(); - - if (nextByte < 0) { - return false; - } - - this.buffer = nextByte; - this.bufferLength = 8; - return true; - } - - readBits(n) { - let buffer = this.buffer; - let bufferLength = this.bufferLength; - - if (n === 32) { - if (bufferLength === 0) { - return (this.stream.getByte() << 24 | this.stream.getByte() << 16 | this.stream.getByte() << 8 | this.stream.getByte()) >>> 0; - } - - buffer = buffer << 24 | this.stream.getByte() << 16 | this.stream.getByte() << 8 | this.stream.getByte(); - const nextByte = this.stream.getByte(); - this.buffer = nextByte & (1 << bufferLength) - 1; - return (buffer << 8 - bufferLength | (nextByte & 0xff) >> bufferLength) >>> 0; - } - - if (n === 8 && bufferLength === 0) { - return this.stream.getByte(); - } - - while (bufferLength < n) { - buffer = buffer << 8 | this.stream.getByte(); - bufferLength += 8; - } - - bufferLength -= n; - this.bufferLength = bufferLength; - this.buffer = buffer & (1 << bufferLength) - 1; - return buffer >> bufferLength; - } - - align() { - this.buffer = 0; - this.bufferLength = 0; - } - - readFlag() { - return this.readBits(this.context.bitsPerFlag); - } - - readCoordinate() { - const bitsPerCoordinate = this.context.bitsPerCoordinate; - const xi = this.readBits(bitsPerCoordinate); - const yi = this.readBits(bitsPerCoordinate); - const decode = this.context.decode; - const scale = bitsPerCoordinate < 32 ? 1 / ((1 << bitsPerCoordinate) - 1) : 2.3283064365386963e-10; - return [xi * scale * (decode[1] - decode[0]) + decode[0], yi * scale * (decode[3] - decode[2]) + decode[2]]; - } - - readComponents() { - const numComps = this.context.numComps; - const bitsPerComponent = this.context.bitsPerComponent; - const scale = bitsPerComponent < 32 ? 1 / ((1 << bitsPerComponent) - 1) : 2.3283064365386963e-10; - const decode = this.context.decode; - const components = this.tmpCompsBuf; - - for (let i = 0, j = 4; i < numComps; i++, j += 2) { - const ci = this.readBits(bitsPerComponent); - components[i] = ci * scale * (decode[j + 1] - decode[j]) + decode[j]; - } - - const color = this.tmpCsCompsBuf; - - if (this.context.colorFn) { - this.context.colorFn(components, 0, color, 0); - } - - return this.context.colorSpace.getRgb(color, 0); - } - -} - -const getB = function getBClosure() { - function buildB(count) { - const lut = []; - - for (let i = 0; i <= count; i++) { - const t = i / count, - t_ = 1 - t; - lut.push(new Float32Array([t_ * t_ * t_, 3 * t * t_ * t_, 3 * t * t * t_, t * t * t])); - } - - return lut; - } - - const cache = []; - return function (count) { - if (!cache[count]) { - cache[count] = buildB(count); - } - - return cache[count]; - }; -}(); - -class MeshShading extends BaseShading { - static get MIN_SPLIT_PATCH_CHUNKS_AMOUNT() { - return (0, _util.shadow)(this, "MIN_SPLIT_PATCH_CHUNKS_AMOUNT", 3); - } - - static get MAX_SPLIT_PATCH_CHUNKS_AMOUNT() { - return (0, _util.shadow)(this, "MAX_SPLIT_PATCH_CHUNKS_AMOUNT", 20); - } - - static get TRIANGLE_DENSITY() { - return (0, _util.shadow)(this, "TRIANGLE_DENSITY", 20); - } - - constructor(stream, xref, resources, pdfFunctionFactory, localColorSpaceCache) { - super(); - - if (!(0, _primitives.isStream)(stream)) { - throw new _util.FormatError("Mesh data is not a stream"); - } - - const dict = stream.dict; - this.shadingType = dict.get("ShadingType"); - const bbox = dict.getArray("BBox"); - - if (Array.isArray(bbox) && bbox.length === 4) { - this.bbox = _util.Util.normalizeRect(bbox); - } else { - this.bbox = null; - } - - const cs = _colorspace.ColorSpace.parse({ - cs: dict.getRaw("CS") || dict.getRaw("ColorSpace"), - xref, - resources, - pdfFunctionFactory, - localColorSpaceCache - }); - - this.background = dict.has("Background") ? cs.getRgb(dict.get("Background"), 0) : null; - const fnObj = dict.getRaw("Function"); - const fn = fnObj ? pdfFunctionFactory.createFromArray(fnObj) : null; - this.coords = []; - this.colors = []; - this.figures = []; - const decodeContext = { - bitsPerCoordinate: dict.get("BitsPerCoordinate"), - bitsPerComponent: dict.get("BitsPerComponent"), - bitsPerFlag: dict.get("BitsPerFlag"), - decode: dict.getArray("Decode"), - colorFn: fn, - colorSpace: cs, - numComps: fn ? 1 : cs.numComps - }; - const reader = new MeshStreamReader(stream, decodeContext); - let patchMesh = false; - - switch (this.shadingType) { - case ShadingType.FREE_FORM_MESH: - this._decodeType4Shading(reader); - - break; - - case ShadingType.LATTICE_FORM_MESH: - const verticesPerRow = dict.get("VerticesPerRow") | 0; - - if (verticesPerRow < 2) { - throw new _util.FormatError("Invalid VerticesPerRow"); - } - - this._decodeType5Shading(reader, verticesPerRow); - - break; - - case ShadingType.COONS_PATCH_MESH: - this._decodeType6Shading(reader); - - patchMesh = true; - break; - - case ShadingType.TENSOR_PATCH_MESH: - this._decodeType7Shading(reader); - - patchMesh = true; - break; - - default: - (0, _util.unreachable)("Unsupported mesh type."); - break; - } - - if (patchMesh) { - this._updateBounds(); - - for (let i = 0, ii = this.figures.length; i < ii; i++) { - this._buildFigureFromPatch(i); - } - } - - this._updateBounds(); - - this._packData(); - } - - _decodeType4Shading(reader) { - const coords = this.coords; - const colors = this.colors; - const operators = []; - const ps = []; - let verticesLeft = 0; - - while (reader.hasData) { - const f = reader.readFlag(); - const coord = reader.readCoordinate(); - const color = reader.readComponents(); - - if (verticesLeft === 0) { - if (!(0 <= f && f <= 2)) { - throw new _util.FormatError("Unknown type4 flag"); - } - - switch (f) { - case 0: - verticesLeft = 3; - break; - - case 1: - ps.push(ps[ps.length - 2], ps[ps.length - 1]); - verticesLeft = 1; - break; - - case 2: - ps.push(ps[ps.length - 3], ps[ps.length - 1]); - verticesLeft = 1; - break; - } - - operators.push(f); - } - - ps.push(coords.length); - coords.push(coord); - colors.push(color); - verticesLeft--; - reader.align(); - } - - this.figures.push({ - type: "triangles", - coords: new Int32Array(ps), - colors: new Int32Array(ps) - }); - } - - _decodeType5Shading(reader, verticesPerRow) { - const coords = this.coords; - const colors = this.colors; - const ps = []; - - while (reader.hasData) { - const coord = reader.readCoordinate(); - const color = reader.readComponents(); - ps.push(coords.length); - coords.push(coord); - colors.push(color); - } - - this.figures.push({ - type: "lattice", - coords: new Int32Array(ps), - colors: new Int32Array(ps), - verticesPerRow - }); - } - - _decodeType6Shading(reader) { - const coords = this.coords; - const colors = this.colors; - const ps = new Int32Array(16); - const cs = new Int32Array(4); - - while (reader.hasData) { - const f = reader.readFlag(); - - if (!(0 <= f && f <= 3)) { - throw new _util.FormatError("Unknown type6 flag"); - } - - const pi = coords.length; - - for (let i = 0, ii = f !== 0 ? 8 : 12; i < ii; i++) { - coords.push(reader.readCoordinate()); - } - - const ci = colors.length; - - for (let i = 0, ii = f !== 0 ? 2 : 4; i < ii; i++) { - colors.push(reader.readComponents()); - } - - let tmp1, tmp2, tmp3, tmp4; - - switch (f) { - case 0: - ps[12] = pi + 3; - ps[13] = pi + 4; - ps[14] = pi + 5; - ps[15] = pi + 6; - ps[8] = pi + 2; - ps[11] = pi + 7; - ps[4] = pi + 1; - ps[7] = pi + 8; - ps[0] = pi; - ps[1] = pi + 11; - ps[2] = pi + 10; - ps[3] = pi + 9; - cs[2] = ci + 1; - cs[3] = ci + 2; - cs[0] = ci; - cs[1] = ci + 3; - break; - - case 1: - tmp1 = ps[12]; - tmp2 = ps[13]; - tmp3 = ps[14]; - tmp4 = ps[15]; - ps[12] = tmp4; - ps[13] = pi + 0; - ps[14] = pi + 1; - ps[15] = pi + 2; - ps[8] = tmp3; - ps[11] = pi + 3; - ps[4] = tmp2; - ps[7] = pi + 4; - ps[0] = tmp1; - ps[1] = pi + 7; - ps[2] = pi + 6; - ps[3] = pi + 5; - tmp1 = cs[2]; - tmp2 = cs[3]; - cs[2] = tmp2; - cs[3] = ci; - cs[0] = tmp1; - cs[1] = ci + 1; - break; - - case 2: - tmp1 = ps[15]; - tmp2 = ps[11]; - ps[12] = ps[3]; - ps[13] = pi + 0; - ps[14] = pi + 1; - ps[15] = pi + 2; - ps[8] = ps[7]; - ps[11] = pi + 3; - ps[4] = tmp2; - ps[7] = pi + 4; - ps[0] = tmp1; - ps[1] = pi + 7; - ps[2] = pi + 6; - ps[3] = pi + 5; - tmp1 = cs[3]; - cs[2] = cs[1]; - cs[3] = ci; - cs[0] = tmp1; - cs[1] = ci + 1; - break; - - case 3: - ps[12] = ps[0]; - ps[13] = pi + 0; - ps[14] = pi + 1; - ps[15] = pi + 2; - ps[8] = ps[1]; - ps[11] = pi + 3; - ps[4] = ps[2]; - ps[7] = pi + 4; - ps[0] = ps[3]; - ps[1] = pi + 7; - ps[2] = pi + 6; - ps[3] = pi + 5; - cs[2] = cs[0]; - cs[3] = ci; - cs[0] = cs[1]; - cs[1] = ci + 1; - break; - } - - ps[5] = coords.length; - coords.push([(-4 * coords[ps[0]][0] - coords[ps[15]][0] + 6 * (coords[ps[4]][0] + coords[ps[1]][0]) - 2 * (coords[ps[12]][0] + coords[ps[3]][0]) + 3 * (coords[ps[13]][0] + coords[ps[7]][0])) / 9, (-4 * coords[ps[0]][1] - coords[ps[15]][1] + 6 * (coords[ps[4]][1] + coords[ps[1]][1]) - 2 * (coords[ps[12]][1] + coords[ps[3]][1]) + 3 * (coords[ps[13]][1] + coords[ps[7]][1])) / 9]); - ps[6] = coords.length; - coords.push([(-4 * coords[ps[3]][0] - coords[ps[12]][0] + 6 * (coords[ps[2]][0] + coords[ps[7]][0]) - 2 * (coords[ps[0]][0] + coords[ps[15]][0]) + 3 * (coords[ps[4]][0] + coords[ps[14]][0])) / 9, (-4 * coords[ps[3]][1] - coords[ps[12]][1] + 6 * (coords[ps[2]][1] + coords[ps[7]][1]) - 2 * (coords[ps[0]][1] + coords[ps[15]][1]) + 3 * (coords[ps[4]][1] + coords[ps[14]][1])) / 9]); - ps[9] = coords.length; - coords.push([(-4 * coords[ps[12]][0] - coords[ps[3]][0] + 6 * (coords[ps[8]][0] + coords[ps[13]][0]) - 2 * (coords[ps[0]][0] + coords[ps[15]][0]) + 3 * (coords[ps[11]][0] + coords[ps[1]][0])) / 9, (-4 * coords[ps[12]][1] - coords[ps[3]][1] + 6 * (coords[ps[8]][1] + coords[ps[13]][1]) - 2 * (coords[ps[0]][1] + coords[ps[15]][1]) + 3 * (coords[ps[11]][1] + coords[ps[1]][1])) / 9]); - ps[10] = coords.length; - coords.push([(-4 * coords[ps[15]][0] - coords[ps[0]][0] + 6 * (coords[ps[11]][0] + coords[ps[14]][0]) - 2 * (coords[ps[12]][0] + coords[ps[3]][0]) + 3 * (coords[ps[2]][0] + coords[ps[8]][0])) / 9, (-4 * coords[ps[15]][1] - coords[ps[0]][1] + 6 * (coords[ps[11]][1] + coords[ps[14]][1]) - 2 * (coords[ps[12]][1] + coords[ps[3]][1]) + 3 * (coords[ps[2]][1] + coords[ps[8]][1])) / 9]); - this.figures.push({ - type: "patch", - coords: new Int32Array(ps), - colors: new Int32Array(cs) - }); - } - } - - _decodeType7Shading(reader) { - const coords = this.coords; - const colors = this.colors; - const ps = new Int32Array(16); - const cs = new Int32Array(4); - - while (reader.hasData) { - const f = reader.readFlag(); - - if (!(0 <= f && f <= 3)) { - throw new _util.FormatError("Unknown type7 flag"); - } - - const pi = coords.length; - - for (let i = 0, ii = f !== 0 ? 12 : 16; i < ii; i++) { - coords.push(reader.readCoordinate()); - } - - const ci = colors.length; - - for (let i = 0, ii = f !== 0 ? 2 : 4; i < ii; i++) { - colors.push(reader.readComponents()); - } - - let tmp1, tmp2, tmp3, tmp4; - - switch (f) { - case 0: - ps[12] = pi + 3; - ps[13] = pi + 4; - ps[14] = pi + 5; - ps[15] = pi + 6; - ps[8] = pi + 2; - ps[9] = pi + 13; - ps[10] = pi + 14; - ps[11] = pi + 7; - ps[4] = pi + 1; - ps[5] = pi + 12; - ps[6] = pi + 15; - ps[7] = pi + 8; - ps[0] = pi; - ps[1] = pi + 11; - ps[2] = pi + 10; - ps[3] = pi + 9; - cs[2] = ci + 1; - cs[3] = ci + 2; - cs[0] = ci; - cs[1] = ci + 3; - break; - - case 1: - tmp1 = ps[12]; - tmp2 = ps[13]; - tmp3 = ps[14]; - tmp4 = ps[15]; - ps[12] = tmp4; - ps[13] = pi + 0; - ps[14] = pi + 1; - ps[15] = pi + 2; - ps[8] = tmp3; - ps[9] = pi + 9; - ps[10] = pi + 10; - ps[11] = pi + 3; - ps[4] = tmp2; - ps[5] = pi + 8; - ps[6] = pi + 11; - ps[7] = pi + 4; - ps[0] = tmp1; - ps[1] = pi + 7; - ps[2] = pi + 6; - ps[3] = pi + 5; - tmp1 = cs[2]; - tmp2 = cs[3]; - cs[2] = tmp2; - cs[3] = ci; - cs[0] = tmp1; - cs[1] = ci + 1; - break; - - case 2: - tmp1 = ps[15]; - tmp2 = ps[11]; - ps[12] = ps[3]; - ps[13] = pi + 0; - ps[14] = pi + 1; - ps[15] = pi + 2; - ps[8] = ps[7]; - ps[9] = pi + 9; - ps[10] = pi + 10; - ps[11] = pi + 3; - ps[4] = tmp2; - ps[5] = pi + 8; - ps[6] = pi + 11; - ps[7] = pi + 4; - ps[0] = tmp1; - ps[1] = pi + 7; - ps[2] = pi + 6; - ps[3] = pi + 5; - tmp1 = cs[3]; - cs[2] = cs[1]; - cs[3] = ci; - cs[0] = tmp1; - cs[1] = ci + 1; - break; - - case 3: - ps[12] = ps[0]; - ps[13] = pi + 0; - ps[14] = pi + 1; - ps[15] = pi + 2; - ps[8] = ps[1]; - ps[9] = pi + 9; - ps[10] = pi + 10; - ps[11] = pi + 3; - ps[4] = ps[2]; - ps[5] = pi + 8; - ps[6] = pi + 11; - ps[7] = pi + 4; - ps[0] = ps[3]; - ps[1] = pi + 7; - ps[2] = pi + 6; - ps[3] = pi + 5; - cs[2] = cs[0]; - cs[3] = ci; - cs[0] = cs[1]; - cs[1] = ci + 1; - break; - } - - this.figures.push({ - type: "patch", - coords: new Int32Array(ps), - colors: new Int32Array(cs) - }); - } - } - - _buildFigureFromPatch(index) { - const figure = this.figures[index]; - (0, _util.assert)(figure.type === "patch", "Unexpected patch mesh figure"); - const coords = this.coords, - colors = this.colors; - const pi = figure.coords; - const ci = figure.colors; - const figureMinX = Math.min(coords[pi[0]][0], coords[pi[3]][0], coords[pi[12]][0], coords[pi[15]][0]); - const figureMinY = Math.min(coords[pi[0]][1], coords[pi[3]][1], coords[pi[12]][1], coords[pi[15]][1]); - const figureMaxX = Math.max(coords[pi[0]][0], coords[pi[3]][0], coords[pi[12]][0], coords[pi[15]][0]); - const figureMaxY = Math.max(coords[pi[0]][1], coords[pi[3]][1], coords[pi[12]][1], coords[pi[15]][1]); - let splitXBy = Math.ceil((figureMaxX - figureMinX) * MeshShading.TRIANGLE_DENSITY / (this.bounds[2] - this.bounds[0])); - splitXBy = Math.max(MeshShading.MIN_SPLIT_PATCH_CHUNKS_AMOUNT, Math.min(MeshShading.MAX_SPLIT_PATCH_CHUNKS_AMOUNT, splitXBy)); - let splitYBy = Math.ceil((figureMaxY - figureMinY) * MeshShading.TRIANGLE_DENSITY / (this.bounds[3] - this.bounds[1])); - splitYBy = Math.max(MeshShading.MIN_SPLIT_PATCH_CHUNKS_AMOUNT, Math.min(MeshShading.MAX_SPLIT_PATCH_CHUNKS_AMOUNT, splitYBy)); - const verticesPerRow = splitXBy + 1; - const figureCoords = new Int32Array((splitYBy + 1) * verticesPerRow); - const figureColors = new Int32Array((splitYBy + 1) * verticesPerRow); - let k = 0; - const cl = new Uint8Array(3), - cr = new Uint8Array(3); - const c0 = colors[ci[0]], - c1 = colors[ci[1]], - c2 = colors[ci[2]], - c3 = colors[ci[3]]; - const bRow = getB(splitYBy), - bCol = getB(splitXBy); - - for (let row = 0; row <= splitYBy; row++) { - cl[0] = (c0[0] * (splitYBy - row) + c2[0] * row) / splitYBy | 0; - cl[1] = (c0[1] * (splitYBy - row) + c2[1] * row) / splitYBy | 0; - cl[2] = (c0[2] * (splitYBy - row) + c2[2] * row) / splitYBy | 0; - cr[0] = (c1[0] * (splitYBy - row) + c3[0] * row) / splitYBy | 0; - cr[1] = (c1[1] * (splitYBy - row) + c3[1] * row) / splitYBy | 0; - cr[2] = (c1[2] * (splitYBy - row) + c3[2] * row) / splitYBy | 0; - - for (let col = 0; col <= splitXBy; col++, k++) { - if ((row === 0 || row === splitYBy) && (col === 0 || col === splitXBy)) { - continue; - } - - let x = 0, - y = 0; - let q = 0; - - for (let i = 0; i <= 3; i++) { - for (let j = 0; j <= 3; j++, q++) { - const m = bRow[row][i] * bCol[col][j]; - x += coords[pi[q]][0] * m; - y += coords[pi[q]][1] * m; - } - } - - figureCoords[k] = coords.length; - coords.push([x, y]); - figureColors[k] = colors.length; - const newColor = new Uint8Array(3); - newColor[0] = (cl[0] * (splitXBy - col) + cr[0] * col) / splitXBy | 0; - newColor[1] = (cl[1] * (splitXBy - col) + cr[1] * col) / splitXBy | 0; - newColor[2] = (cl[2] * (splitXBy - col) + cr[2] * col) / splitXBy | 0; - colors.push(newColor); - } - } - - figureCoords[0] = pi[0]; - figureColors[0] = ci[0]; - figureCoords[splitXBy] = pi[3]; - figureColors[splitXBy] = ci[1]; - figureCoords[verticesPerRow * splitYBy] = pi[12]; - figureColors[verticesPerRow * splitYBy] = ci[2]; - figureCoords[verticesPerRow * splitYBy + splitXBy] = pi[15]; - figureColors[verticesPerRow * splitYBy + splitXBy] = ci[3]; - this.figures[index] = { - type: "lattice", - coords: figureCoords, - colors: figureColors, - verticesPerRow - }; - } - - _updateBounds() { - let minX = this.coords[0][0], - minY = this.coords[0][1], - maxX = minX, - maxY = minY; - - for (let i = 1, ii = this.coords.length; i < ii; i++) { - const x = this.coords[i][0], - y = this.coords[i][1]; - minX = minX > x ? x : minX; - minY = minY > y ? y : minY; - maxX = maxX < x ? x : maxX; - maxY = maxY < y ? y : maxY; - } - - this.bounds = [minX, minY, maxX, maxY]; - } - - _packData() { - let i, ii, j, jj; - const coords = this.coords; - const coordsPacked = new Float32Array(coords.length * 2); - - for (i = 0, j = 0, ii = coords.length; i < ii; i++) { - const xy = coords[i]; - coordsPacked[j++] = xy[0]; - coordsPacked[j++] = xy[1]; - } - - this.coords = coordsPacked; - const colors = this.colors; - const colorsPacked = new Uint8Array(colors.length * 3); - - for (i = 0, j = 0, ii = colors.length; i < ii; i++) { - const c = colors[i]; - colorsPacked[j++] = c[0]; - colorsPacked[j++] = c[1]; - colorsPacked[j++] = c[2]; - } - - this.colors = colorsPacked; - const figures = this.figures; - - for (i = 0, ii = figures.length; i < ii; i++) { - const figure = figures[i], - ps = figure.coords, - cs = figure.colors; - - for (j = 0, jj = ps.length; j < jj; j++) { - ps[j] *= 2; - cs[j] *= 3; - } - } - } - - getIR() { - return ["Mesh", this.shadingType, this.coords, this.colors, this.figures, this.bounds, this.bbox, this.background]; - } - -} - -class DummyShading extends BaseShading { - getIR() { - return ["Dummy"]; - } - -} - -function getTilingPatternIR(operatorList, dict, color) { - const matrix = dict.getArray("Matrix"); - - const bbox = _util.Util.normalizeRect(dict.getArray("BBox")); - - const xstep = dict.get("XStep"); - const ystep = dict.get("YStep"); - const paintType = dict.get("PaintType"); - const tilingType = dict.get("TilingType"); - - if (bbox[2] - bbox[0] === 0 || bbox[3] - bbox[1] === 0) { - throw new _util.FormatError(`Invalid getTilingPatternIR /BBox array: [${bbox}].`); - } - - return ["TilingPattern", color, operatorList, matrix, bbox, xstep, ystep, paintType, tilingType]; -} - -/***/ }), -/* 56 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.PostScriptEvaluator = exports.PostScriptCompiler = exports.PDFFunctionFactory = void 0; -exports.isPDFFunction = isPDFFunction; - -var _primitives = __w_pdfjs_require__(5); - -var _util = __w_pdfjs_require__(2); - -var _ps_parser = __w_pdfjs_require__(57); - -var _image_utils = __w_pdfjs_require__(58); - -class PDFFunctionFactory { - constructor({ - xref, - isEvalSupported = true - }) { - this.xref = xref; - this.isEvalSupported = isEvalSupported !== false; - } - - create(fn) { - const cachedFunction = this.getCached(fn); - - if (cachedFunction) { - return cachedFunction; - } - - const parsedFunction = PDFFunction.parse({ - xref: this.xref, - isEvalSupported: this.isEvalSupported, - fn: fn instanceof _primitives.Ref ? this.xref.fetch(fn) : fn - }); - - this._cache(fn, parsedFunction); - - return parsedFunction; - } - - createFromArray(fnObj) { - const cachedFunction = this.getCached(fnObj); - - if (cachedFunction) { - return cachedFunction; - } - - const parsedFunction = PDFFunction.parseArray({ - xref: this.xref, - isEvalSupported: this.isEvalSupported, - fnObj: fnObj instanceof _primitives.Ref ? this.xref.fetch(fnObj) : fnObj - }); - - this._cache(fnObj, parsedFunction); - - return parsedFunction; - } - - getCached(cacheKey) { - let fnRef; - - if (cacheKey instanceof _primitives.Ref) { - fnRef = cacheKey; - } else if (cacheKey instanceof _primitives.Dict) { - fnRef = cacheKey.objId; - } else if ((0, _primitives.isStream)(cacheKey)) { - fnRef = cacheKey.dict && cacheKey.dict.objId; - } - - if (fnRef) { - const localFunction = this._localFunctionCache.getByRef(fnRef); - - if (localFunction) { - return localFunction; - } - } - - return null; - } - - _cache(cacheKey, parsedFunction) { - if (!parsedFunction) { - throw new Error('PDFFunctionFactory._cache - expected "parsedFunction" argument.'); - } - - let fnRef; - - if (cacheKey instanceof _primitives.Ref) { - fnRef = cacheKey; - } else if (cacheKey instanceof _primitives.Dict) { - fnRef = cacheKey.objId; - } else if ((0, _primitives.isStream)(cacheKey)) { - fnRef = cacheKey.dict && cacheKey.dict.objId; - } - - if (fnRef) { - this._localFunctionCache.set(null, fnRef, parsedFunction); - } - } - - get _localFunctionCache() { - return (0, _util.shadow)(this, "_localFunctionCache", new _image_utils.LocalFunctionCache()); - } - -} - -exports.PDFFunctionFactory = PDFFunctionFactory; - -function toNumberArray(arr) { - if (!Array.isArray(arr)) { - return null; - } - - const length = arr.length; - - for (let i = 0; i < length; i++) { - if (typeof arr[i] !== "number") { - const result = new Array(length); - - for (let j = 0; j < length; j++) { - result[j] = +arr[j]; - } - - return result; - } - } - - return arr; -} - -class PDFFunction { - static getSampleArray(size, outputSize, bps, stream) { - let i, ii; - let length = 1; - - for (i = 0, ii = size.length; i < ii; i++) { - length *= size[i]; - } - - length *= outputSize; - const array = new Array(length); - let codeSize = 0; - let codeBuf = 0; - const sampleMul = 1.0 / (2.0 ** bps - 1); - const strBytes = stream.getBytes((length * bps + 7) / 8); - let strIdx = 0; - - for (i = 0; i < length; i++) { - while (codeSize < bps) { - codeBuf <<= 8; - codeBuf |= strBytes[strIdx++]; - codeSize += 8; - } - - codeSize -= bps; - array[i] = (codeBuf >> codeSize) * sampleMul; - codeBuf &= (1 << codeSize) - 1; - } - - return array; - } - - static parse({ - xref, - isEvalSupported, - fn - }) { - const dict = fn.dict || fn; - const typeNum = dict.get("FunctionType"); - - switch (typeNum) { - case 0: - return this.constructSampled({ - xref, - isEvalSupported, - fn, - dict - }); - - case 1: - break; - - case 2: - return this.constructInterpolated({ - xref, - isEvalSupported, - dict - }); - - case 3: - return this.constructStiched({ - xref, - isEvalSupported, - dict - }); - - case 4: - return this.constructPostScript({ - xref, - isEvalSupported, - fn, - dict - }); - } - - throw new _util.FormatError("Unknown type of function"); - } - - static parseArray({ - xref, - isEvalSupported, - fnObj - }) { - if (!Array.isArray(fnObj)) { - return this.parse({ - xref, - isEvalSupported, - fn: fnObj - }); - } - - const fnArray = []; - - for (let j = 0, jj = fnObj.length; j < jj; j++) { - fnArray.push(this.parse({ - xref, - isEvalSupported, - fn: xref.fetchIfRef(fnObj[j]) - })); - } - - return function (src, srcOffset, dest, destOffset) { - for (let i = 0, ii = fnArray.length; i < ii; i++) { - fnArray[i](src, srcOffset, dest, destOffset + i); - } - }; - } - - static constructSampled({ - xref, - isEvalSupported, - fn, - dict - }) { - function toMultiArray(arr) { - const inputLength = arr.length; - const out = []; - let index = 0; - - for (let i = 0; i < inputLength; i += 2) { - out[index++] = [arr[i], arr[i + 1]]; - } - - return out; - } - - function interpolate(x, xmin, xmax, ymin, ymax) { - return ymin + (x - xmin) * ((ymax - ymin) / (xmax - xmin)); - } - - let domain = toNumberArray(dict.getArray("Domain")); - let range = toNumberArray(dict.getArray("Range")); - - if (!domain || !range) { - throw new _util.FormatError("No domain or range"); - } - - const inputSize = domain.length / 2; - const outputSize = range.length / 2; - domain = toMultiArray(domain); - range = toMultiArray(range); - const size = toNumberArray(dict.getArray("Size")); - const bps = dict.get("BitsPerSample"); - const order = dict.get("Order") || 1; - - if (order !== 1) { - (0, _util.info)("No support for cubic spline interpolation: " + order); - } - - let encode = toNumberArray(dict.getArray("Encode")); - - if (!encode) { - encode = []; - - for (let i = 0; i < inputSize; ++i) { - encode.push([0, size[i] - 1]); - } - } else { - encode = toMultiArray(encode); - } - - let decode = toNumberArray(dict.getArray("Decode")); - - if (!decode) { - decode = range; - } else { - decode = toMultiArray(decode); - } - - const samples = this.getSampleArray(size, outputSize, bps, fn); - return function constructSampledFn(src, srcOffset, dest, destOffset) { - const cubeVertices = 1 << inputSize; - const cubeN = new Float64Array(cubeVertices); - const cubeVertex = new Uint32Array(cubeVertices); - let i, j; - - for (j = 0; j < cubeVertices; j++) { - cubeN[j] = 1; - } - - let k = outputSize, - pos = 1; - - for (i = 0; i < inputSize; ++i) { - const domain_2i = domain[i][0]; - const domain_2i_1 = domain[i][1]; - const xi = Math.min(Math.max(src[srcOffset + i], domain_2i), domain_2i_1); - let e = interpolate(xi, domain_2i, domain_2i_1, encode[i][0], encode[i][1]); - const size_i = size[i]; - e = Math.min(Math.max(e, 0), size_i - 1); - const e0 = e < size_i - 1 ? Math.floor(e) : e - 1; - const n0 = e0 + 1 - e; - const n1 = e - e0; - const offset0 = e0 * k; - const offset1 = offset0 + k; - - for (j = 0; j < cubeVertices; j++) { - if (j & pos) { - cubeN[j] *= n1; - cubeVertex[j] += offset1; - } else { - cubeN[j] *= n0; - cubeVertex[j] += offset0; - } - } - - k *= size_i; - pos <<= 1; - } - - for (j = 0; j < outputSize; ++j) { - let rj = 0; - - for (i = 0; i < cubeVertices; i++) { - rj += samples[cubeVertex[i] + j] * cubeN[i]; - } - - rj = interpolate(rj, 0, 1, decode[j][0], decode[j][1]); - dest[destOffset + j] = Math.min(Math.max(rj, range[j][0]), range[j][1]); - } - }; - } - - static constructInterpolated({ - xref, - isEvalSupported, - dict - }) { - const c0 = toNumberArray(dict.getArray("C0")) || [0]; - const c1 = toNumberArray(dict.getArray("C1")) || [1]; - const n = dict.get("N"); - const diff = []; - - for (let i = 0, ii = c0.length; i < ii; ++i) { - diff.push(c1[i] - c0[i]); - } - - const length = diff.length; - return function constructInterpolatedFn(src, srcOffset, dest, destOffset) { - const x = n === 1 ? src[srcOffset] : src[srcOffset] ** n; - - for (let j = 0; j < length; ++j) { - dest[destOffset + j] = c0[j] + x * diff[j]; - } - }; - } - - static constructStiched({ - xref, - isEvalSupported, - dict - }) { - const domain = toNumberArray(dict.getArray("Domain")); - - if (!domain) { - throw new _util.FormatError("No domain"); - } - - const inputSize = domain.length / 2; - - if (inputSize !== 1) { - throw new _util.FormatError("Bad domain for stiched function"); - } - - const fnRefs = dict.get("Functions"); - const fns = []; - - for (let i = 0, ii = fnRefs.length; i < ii; ++i) { - fns.push(this.parse({ - xref, - isEvalSupported, - fn: xref.fetchIfRef(fnRefs[i]) - })); - } - - const bounds = toNumberArray(dict.getArray("Bounds")); - const encode = toNumberArray(dict.getArray("Encode")); - const tmpBuf = new Float32Array(1); - return function constructStichedFn(src, srcOffset, dest, destOffset) { - const clip = function constructStichedFromIRClip(v, min, max) { - if (v > max) { - v = max; - } else if (v < min) { - v = min; - } - - return v; - }; - - const v = clip(src[srcOffset], domain[0], domain[1]); - const length = bounds.length; - let i; - - for (i = 0; i < length; ++i) { - if (v < bounds[i]) { - break; - } - } - - let dmin = domain[0]; - - if (i > 0) { - dmin = bounds[i - 1]; - } - - let dmax = domain[1]; - - if (i < bounds.length) { - dmax = bounds[i]; - } - - const rmin = encode[2 * i]; - const rmax = encode[2 * i + 1]; - tmpBuf[0] = dmin === dmax ? rmin : rmin + (v - dmin) * (rmax - rmin) / (dmax - dmin); - fns[i](tmpBuf, 0, dest, destOffset); - }; - } - - static constructPostScript({ - xref, - isEvalSupported, - fn, - dict - }) { - const domain = toNumberArray(dict.getArray("Domain")); - const range = toNumberArray(dict.getArray("Range")); - - if (!domain) { - throw new _util.FormatError("No domain."); - } - - if (!range) { - throw new _util.FormatError("No range."); - } - - const lexer = new _ps_parser.PostScriptLexer(fn); - const parser = new _ps_parser.PostScriptParser(lexer); - const code = parser.parse(); - - if (isEvalSupported && _util.IsEvalSupportedCached.value) { - const compiled = new PostScriptCompiler().compile(code, domain, range); - - if (compiled) { - return new Function("src", "srcOffset", "dest", "destOffset", compiled); - } - } - - (0, _util.info)("Unable to compile PS function"); - const numOutputs = range.length >> 1; - const numInputs = domain.length >> 1; - const evaluator = new PostScriptEvaluator(code); - const cache = Object.create(null); - const MAX_CACHE_SIZE = 2048 * 4; - let cache_available = MAX_CACHE_SIZE; - const tmpBuf = new Float32Array(numInputs); - return function constructPostScriptFn(src, srcOffset, dest, destOffset) { - let i, value; - let key = ""; - const input = tmpBuf; - - for (i = 0; i < numInputs; i++) { - value = src[srcOffset + i]; - input[i] = value; - key += value + "_"; - } - - const cachedValue = cache[key]; - - if (cachedValue !== undefined) { - dest.set(cachedValue, destOffset); - return; - } - - const output = new Float32Array(numOutputs); - const stack = evaluator.execute(input); - const stackIndex = stack.length - numOutputs; - - for (i = 0; i < numOutputs; i++) { - value = stack[stackIndex + i]; - let bound = range[i * 2]; - - if (value < bound) { - value = bound; - } else { - bound = range[i * 2 + 1]; - - if (value > bound) { - value = bound; - } - } - - output[i] = value; - } - - if (cache_available > 0) { - cache_available--; - cache[key] = output; - } - - dest.set(output, destOffset); - }; - } - -} - -function isPDFFunction(v) { - let fnDict; - - if (typeof v !== "object") { - return false; - } else if ((0, _primitives.isDict)(v)) { - fnDict = v; - } else if ((0, _primitives.isStream)(v)) { - fnDict = v.dict; - } else { - return false; - } - - return fnDict.has("FunctionType"); -} - -class PostScriptStack { - static get MAX_STACK_SIZE() { - return (0, _util.shadow)(this, "MAX_STACK_SIZE", 100); - } - - constructor(initialStack) { - this.stack = !initialStack ? [] : Array.prototype.slice.call(initialStack, 0); - } - - push(value) { - if (this.stack.length >= PostScriptStack.MAX_STACK_SIZE) { - throw new Error("PostScript function stack overflow."); - } - - this.stack.push(value); - } - - pop() { - if (this.stack.length <= 0) { - throw new Error("PostScript function stack underflow."); - } - - return this.stack.pop(); - } - - copy(n) { - if (this.stack.length + n >= PostScriptStack.MAX_STACK_SIZE) { - throw new Error("PostScript function stack overflow."); - } - - const stack = this.stack; - - for (let i = stack.length - n, j = n - 1; j >= 0; j--, i++) { - stack.push(stack[i]); - } - } - - index(n) { - this.push(this.stack[this.stack.length - n - 1]); - } - - roll(n, p) { - const stack = this.stack; - const l = stack.length - n; - const r = stack.length - 1; - const c = l + (p - Math.floor(p / n) * n); - - for (let i = l, j = r; i < j; i++, j--) { - const t = stack[i]; - stack[i] = stack[j]; - stack[j] = t; - } - - for (let i = l, j = c - 1; i < j; i++, j--) { - const t = stack[i]; - stack[i] = stack[j]; - stack[j] = t; - } - - for (let i = c, j = r; i < j; i++, j--) { - const t = stack[i]; - stack[i] = stack[j]; - stack[j] = t; - } - } - -} - -class PostScriptEvaluator { - constructor(operators) { - this.operators = operators; - } - - execute(initialStack) { - const stack = new PostScriptStack(initialStack); - let counter = 0; - const operators = this.operators; - const length = operators.length; - let operator, a, b; - - while (counter < length) { - operator = operators[counter++]; - - if (typeof operator === "number") { - stack.push(operator); - continue; - } - - switch (operator) { - case "jz": - b = stack.pop(); - a = stack.pop(); - - if (!a) { - counter = b; - } - - break; - - case "j": - a = stack.pop(); - counter = a; - break; - - 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 ((0, _util.isBool)(a) && (0, _util.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": - 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(a ** b); - break; - - case "false": - stack.push(false); - break; - - case "floor": - a = stack.pop(); - stack.push(Math.floor(a)); - break; - - case "ge": - b = stack.pop(); - a = stack.pop(); - stack.push(a >= b); - break; - - case "gt": - b = stack.pop(); - a = stack.pop(); - stack.push(a > b); - break; - - case "idiv": - b = stack.pop(); - a = stack.pop(); - stack.push(a / b | 0); - break; - - case "index": - a = stack.pop(); - stack.index(a); - break; - - case "le": - b = stack.pop(); - a = stack.pop(); - stack.push(a <= b); - break; - - case "ln": - a = stack.pop(); - stack.push(Math.log(a)); - break; - - case "log": - a = stack.pop(); - stack.push(Math.log(a) / Math.LN10); - break; - - case "lt": - b = stack.pop(); - a = stack.pop(); - stack.push(a < b); - break; - - case "mod": - b = stack.pop(); - a = stack.pop(); - stack.push(a % b); - break; - - case "mul": - b = stack.pop(); - a = stack.pop(); - stack.push(a * b); - break; - - case "ne": - b = stack.pop(); - a = stack.pop(); - stack.push(a !== b); - break; - - case "neg": - a = stack.pop(); - stack.push(-a); - break; - - case "not": - a = stack.pop(); - - if ((0, _util.isBool)(a)) { - stack.push(!a); - } else { - stack.push(~a); - } - - break; - - case "or": - b = stack.pop(); - a = stack.pop(); - - if ((0, _util.isBool)(a) && (0, _util.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 ((0, _util.isBool)(a) && (0, _util.isBool)(b)) { - stack.push(a !== b); - } else { - stack.push(a ^ b); - } - - break; - - default: - throw new _util.FormatError(`Unknown operator ${operator}`); - } - } - - return stack.stack; - } - -} - -exports.PostScriptEvaluator = PostScriptEvaluator; - -const PostScriptCompiler = function PostScriptCompilerClosure() { - class AstNode { - constructor(type) { - this.type = type; - } - - visit(visitor) { - (0, _util.unreachable)("abstract method"); - } - - } - - class AstArgument extends AstNode { - constructor(index, min, max) { - super("args"); - this.index = index; - this.min = min; - this.max = max; - } - - visit(visitor) { - visitor.visitArgument(this); - } - - } - - class AstLiteral extends AstNode { - constructor(number) { - super("literal"); - this.number = number; - this.min = number; - this.max = number; - } - - visit(visitor) { - visitor.visitLiteral(this); - } - - } - - class AstBinaryOperation extends AstNode { - constructor(op, arg1, arg2, min, max) { - super("binary"); - this.op = op; - this.arg1 = arg1; - this.arg2 = arg2; - this.min = min; - this.max = max; - } - - visit(visitor) { - visitor.visitBinaryOperation(this); - } - - } - - class AstMin extends AstNode { - constructor(arg, max) { - super("max"); - this.arg = arg; - this.min = arg.min; - this.max = max; - } - - visit(visitor) { - visitor.visitMin(this); - } - - } - - class AstVariable extends AstNode { - constructor(index, min, max) { - super("var"); - this.index = index; - this.min = min; - this.max = max; - } - - visit(visitor) { - visitor.visitVariable(this); - } - - } - - class AstVariableDefinition extends AstNode { - constructor(variable, arg) { - super("definition"); - this.variable = variable; - this.arg = arg; - } - - visit(visitor) { - visitor.visitVariableDefinition(this); - } - - } - - class ExpressionBuilderVisitor { - constructor() { - this.parts = []; - } - - visitArgument(arg) { - this.parts.push("Math.max(", arg.min, ", Math.min(", arg.max, ", src[srcOffset + ", arg.index, "]))"); - } - - visitVariable(variable) { - this.parts.push("v", variable.index); - } - - visitLiteral(literal) { - this.parts.push(literal.number); - } - - visitBinaryOperation(operation) { - this.parts.push("("); - operation.arg1.visit(this); - this.parts.push(" ", operation.op, " "); - operation.arg2.visit(this); - this.parts.push(")"); - } - - visitVariableDefinition(definition) { - this.parts.push("var "); - definition.variable.visit(this); - this.parts.push(" = "); - definition.arg.visit(this); - this.parts.push(";"); - } - - visitMin(max) { - this.parts.push("Math.min("); - max.arg.visit(this); - this.parts.push(", ", max.max, ")"); - } - - toString() { - return this.parts.join(""); - } - - } - - function buildAddOperation(num1, num2) { - if (num2.type === "literal" && num2.number === 0) { - return num1; - } - - if (num1.type === "literal" && num1.number === 0) { - return num2; - } - - if (num2.type === "literal" && num1.type === "literal") { - return new AstLiteral(num1.number + num2.number); - } - - return new AstBinaryOperation("+", num1, num2, num1.min + num2.min, num1.max + num2.max); - } - - function buildMulOperation(num1, num2) { - if (num2.type === "literal") { - if (num2.number === 0) { - return new AstLiteral(0); - } else if (num2.number === 1) { - return num1; - } else if (num1.type === "literal") { - return new AstLiteral(num1.number * num2.number); - } - } - - if (num1.type === "literal") { - if (num1.number === 0) { - return new AstLiteral(0); - } else if (num1.number === 1) { - return num2; - } - } - - const min = Math.min(num1.min * num2.min, num1.min * num2.max, num1.max * num2.min, num1.max * num2.max); - const max = Math.max(num1.min * num2.min, num1.min * num2.max, num1.max * num2.min, num1.max * num2.max); - return new AstBinaryOperation("*", num1, num2, min, max); - } - - function buildSubOperation(num1, num2) { - if (num2.type === "literal") { - if (num2.number === 0) { - return num1; - } else if (num1.type === "literal") { - return new AstLiteral(num1.number - num2.number); - } - } - - if (num2.type === "binary" && num2.op === "-" && num1.type === "literal" && num1.number === 1 && num2.arg1.type === "literal" && num2.arg1.number === 1) { - return num2.arg2; - } - - return new AstBinaryOperation("-", num1, num2, num1.min - num2.max, num1.max - num2.min); - } - - function buildMinOperation(num1, max) { - if (num1.min >= max) { - return new AstLiteral(max); - } else if (num1.max <= max) { - return num1; - } - - return new AstMin(num1, max); - } - - class PostScriptCompiler { - compile(code, domain, range) { - const stack = []; - const instructions = []; - const inputSize = domain.length >> 1, - outputSize = range.length >> 1; - let lastRegister = 0; - let n, j; - let num1, num2, ast1, ast2, tmpVar, item; - - for (let i = 0; i < inputSize; i++) { - stack.push(new AstArgument(i, domain[i * 2], domain[i * 2 + 1])); - } - - for (let i = 0, ii = code.length; i < ii; i++) { - item = code[i]; - - if (typeof item === "number") { - stack.push(new AstLiteral(item)); - continue; - } - - switch (item) { - case "add": - if (stack.length < 2) { - return null; - } - - num2 = stack.pop(); - num1 = stack.pop(); - stack.push(buildAddOperation(num1, num2)); - break; - - case "cvr": - if (stack.length < 1) { - return null; - } - - break; - - case "mul": - if (stack.length < 2) { - return null; - } - - num2 = stack.pop(); - num1 = stack.pop(); - stack.push(buildMulOperation(num1, num2)); - break; - - case "sub": - if (stack.length < 2) { - return null; - } - - num2 = stack.pop(); - num1 = stack.pop(); - stack.push(buildSubOperation(num1, num2)); - break; - - case "exch": - if (stack.length < 2) { - return null; - } - - ast1 = stack.pop(); - ast2 = stack.pop(); - stack.push(ast1, ast2); - break; - - case "pop": - if (stack.length < 1) { - return null; - } - - stack.pop(); - break; - - case "index": - if (stack.length < 1) { - return null; - } - - num1 = stack.pop(); - - if (num1.type !== "literal") { - return null; - } - - n = num1.number; - - if (n < 0 || !Number.isInteger(n) || stack.length < n) { - return null; - } - - ast1 = stack[stack.length - n - 1]; - - if (ast1.type === "literal" || ast1.type === "var") { - stack.push(ast1); - break; - } - - tmpVar = new AstVariable(lastRegister++, ast1.min, ast1.max); - stack[stack.length - n - 1] = tmpVar; - stack.push(tmpVar); - instructions.push(new AstVariableDefinition(tmpVar, ast1)); - break; - - case "dup": - if (stack.length < 1) { - return null; - } - - if (typeof code[i + 1] === "number" && code[i + 2] === "gt" && code[i + 3] === i + 7 && code[i + 4] === "jz" && code[i + 5] === "pop" && code[i + 6] === code[i + 1]) { - num1 = stack.pop(); - stack.push(buildMinOperation(num1, code[i + 1])); - i += 6; - break; - } - - ast1 = stack[stack.length - 1]; - - if (ast1.type === "literal" || ast1.type === "var") { - stack.push(ast1); - break; - } - - tmpVar = new AstVariable(lastRegister++, ast1.min, ast1.max); - stack[stack.length - 1] = tmpVar; - stack.push(tmpVar); - instructions.push(new AstVariableDefinition(tmpVar, ast1)); - break; - - case "roll": - if (stack.length < 2) { - return null; - } - - num2 = stack.pop(); - num1 = stack.pop(); - - if (num2.type !== "literal" || num1.type !== "literal") { - return null; - } - - j = num2.number; - n = num1.number; - - if (n <= 0 || !Number.isInteger(n) || !Number.isInteger(j) || stack.length < n) { - return null; - } - - j = (j % n + n) % n; - - if (j === 0) { - break; - } - - Array.prototype.push.apply(stack, stack.splice(stack.length - n, n - j)); - break; - - default: - return null; - } - } - - if (stack.length !== outputSize) { - return null; - } - - const result = []; - - for (const instruction of instructions) { - const statementBuilder = new ExpressionBuilderVisitor(); - instruction.visit(statementBuilder); - result.push(statementBuilder.toString()); - } - - for (let i = 0, ii = stack.length; i < ii; i++) { - const expr = stack[i], - statementBuilder = new ExpressionBuilderVisitor(); - expr.visit(statementBuilder); - const min = range[i * 2], - max = range[i * 2 + 1]; - const out = [statementBuilder.toString()]; - - if (min > expr.min) { - out.unshift("Math.max(", min, ", "); - out.push(")"); - } - - if (max < expr.max) { - out.unshift("Math.min(", max, ", "); - out.push(")"); - } - - out.unshift("dest[destOffset + ", i, "] = "); - out.push(";"); - result.push(out.join("")); - } - - return result.join("\n"); - } - - } - - return PostScriptCompiler; -}(); - -exports.PostScriptCompiler = PostScriptCompiler; - -/***/ }), -/* 57 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.PostScriptParser = exports.PostScriptLexer = void 0; - -var _util = __w_pdfjs_require__(2); - -var _primitives = __w_pdfjs_require__(5); - -var _core_utils = __w_pdfjs_require__(9); - -class PostScriptParser { - constructor(lexer) { - this.lexer = lexer; - this.operators = []; - this.token = null; - this.prev = null; - } - - nextToken() { - this.prev = this.token; - this.token = this.lexer.getToken(); - } - - accept(type) { - if (this.token.type === type) { - this.nextToken(); - return true; - } - - return false; - } - - expect(type) { - if (this.accept(type)) { - return true; - } - - throw new _util.FormatError(`Unexpected symbol: found ${this.token.type} expected ${type}.`); - } - - parse() { - this.nextToken(); - this.expect(PostScriptTokenTypes.LBRACE); - this.parseBlock(); - this.expect(PostScriptTokenTypes.RBRACE); - return this.operators; - } - - 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() { - const conditionLocation = this.operators.length; - this.operators.push(null, null); - this.parseBlock(); - this.expect(PostScriptTokenTypes.RBRACE); - - if (this.accept(PostScriptTokenTypes.IF)) { - this.operators[conditionLocation] = this.operators.length; - this.operators[conditionLocation + 1] = "jz"; - } else if (this.accept(PostScriptTokenTypes.LBRACE)) { - const jumpLocation = this.operators.length; - this.operators.push(null, null); - const endOfTrue = this.operators.length; - this.parseBlock(); - this.expect(PostScriptTokenTypes.RBRACE); - this.expect(PostScriptTokenTypes.IFELSE); - this.operators[jumpLocation] = this.operators.length; - this.operators[jumpLocation + 1] = "j"; - this.operators[conditionLocation] = endOfTrue; - this.operators[conditionLocation + 1] = "jz"; - } else { - throw new _util.FormatError("PS Function: error parsing conditional."); - } - } - -} - -exports.PostScriptParser = PostScriptParser; -const PostScriptTokenTypes = { - LBRACE: 0, - RBRACE: 1, - NUMBER: 2, - OPERATOR: 3, - IF: 4, - IFELSE: 5 -}; - -class PostScriptToken { - static get opCache() { - return (0, _util.shadow)(this, "opCache", Object.create(null)); - } - - constructor(type, value) { - this.type = type; - this.value = value; - } - - static getOperator(op) { - const opValue = PostScriptToken.opCache[op]; - - if (opValue) { - return opValue; - } - - return PostScriptToken.opCache[op] = new PostScriptToken(PostScriptTokenTypes.OPERATOR, op); - } - - static get LBRACE() { - return (0, _util.shadow)(this, "LBRACE", new PostScriptToken(PostScriptTokenTypes.LBRACE, "{")); - } - - static get RBRACE() { - return (0, _util.shadow)(this, "RBRACE", new PostScriptToken(PostScriptTokenTypes.RBRACE, "}")); - } - - static get IF() { - return (0, _util.shadow)(this, "IF", new PostScriptToken(PostScriptTokenTypes.IF, "IF")); - } - - static get IFELSE() { - return (0, _util.shadow)(this, "IFELSE", new PostScriptToken(PostScriptTokenTypes.IFELSE, "IFELSE")); - } - -} - -class PostScriptLexer { - constructor(stream) { - this.stream = stream; - this.nextChar(); - this.strBuf = []; - } - - nextChar() { - return this.currentChar = this.stream.getByte(); - } - - getToken() { - let comment = false; - let ch = this.currentChar; - - while (true) { - if (ch < 0) { - return _primitives.EOF; - } - - if (comment) { - if (ch === 0x0a || ch === 0x0d) { - comment = false; - } - } else if (ch === 0x25) { - comment = true; - } else if (!(0, _core_utils.isWhiteSpace)(ch)) { - break; - } - - ch = this.nextChar(); - } - - switch (ch | 0) { - case 0x30: - case 0x31: - case 0x32: - case 0x33: - case 0x34: - case 0x35: - case 0x36: - case 0x37: - case 0x38: - case 0x39: - 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; - } - - const strBuf = this.strBuf; - strBuf.length = 0; - strBuf[0] = String.fromCharCode(ch); - - while ((ch = this.nextChar()) >= 0 && (ch >= 0x41 && ch <= 0x5a || ch >= 0x61 && ch <= 0x7a)) { - strBuf.push(String.fromCharCode(ch)); - } - - const str = strBuf.join(""); - - switch (str.toLowerCase()) { - case "if": - return PostScriptToken.IF; - - case "ifelse": - return PostScriptToken.IFELSE; - - default: - return PostScriptToken.getOperator(str); - } - } - - getNumber() { - let ch = this.currentChar; - const strBuf = this.strBuf; - strBuf.length = 0; - strBuf[0] = String.fromCharCode(ch); - - while ((ch = this.nextChar()) >= 0) { - if (ch >= 0x30 && ch <= 0x39 || ch === 0x2d || ch === 0x2e) { - strBuf.push(String.fromCharCode(ch)); - } else { - break; - } - } - - const value = parseFloat(strBuf.join("")); - - if (isNaN(value)) { - throw new _util.FormatError(`Invalid floating point number: ${value}`); - } - - return value; - } - -} - -exports.PostScriptLexer = PostScriptLexer; - -/***/ }), -/* 58 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.LocalTilingPatternCache = exports.LocalImageCache = exports.LocalGStateCache = exports.LocalFunctionCache = exports.LocalColorSpaceCache = exports.GlobalImageCache = void 0; - -var _util = __w_pdfjs_require__(2); - -var _primitives = __w_pdfjs_require__(5); - -class BaseLocalCache { - constructor(options) { - if (this.constructor === BaseLocalCache) { - (0, _util.unreachable)("Cannot initialize BaseLocalCache."); - } - - this._onlyRefs = (options && options.onlyRefs) === true; - - if (!this._onlyRefs) { - this._nameRefMap = new Map(); - this._imageMap = new Map(); - } - - this._imageCache = new _primitives.RefSetCache(); - } - - getByName(name) { - if (this._onlyRefs) { - (0, _util.unreachable)("Should not call `getByName` method."); - } - - const ref = this._nameRefMap.get(name); - - if (ref) { - return this.getByRef(ref); - } - - return this._imageMap.get(name) || null; - } - - getByRef(ref) { - return this._imageCache.get(ref) || null; - } - - set(name, ref, data) { - (0, _util.unreachable)("Abstract method `set` called."); - } - -} - -class LocalImageCache extends BaseLocalCache { - set(name, ref = null, data) { - if (typeof name !== "string") { - throw new Error('LocalImageCache.set - expected "name" argument.'); - } - - if (ref) { - if (this._imageCache.has(ref)) { - return; - } - - this._nameRefMap.set(name, ref); - - this._imageCache.put(ref, data); - - return; - } - - if (this._imageMap.has(name)) { - return; - } - - this._imageMap.set(name, data); - } - -} - -exports.LocalImageCache = LocalImageCache; - -class LocalColorSpaceCache extends BaseLocalCache { - set(name = null, ref = null, data) { - if (typeof name !== "string" && !ref) { - throw new Error('LocalColorSpaceCache.set - expected "name" and/or "ref" argument.'); - } - - if (ref) { - if (this._imageCache.has(ref)) { - return; - } - - if (name !== null) { - this._nameRefMap.set(name, ref); - } - - this._imageCache.put(ref, data); - - return; - } - - if (this._imageMap.has(name)) { - return; - } - - this._imageMap.set(name, data); - } - -} - -exports.LocalColorSpaceCache = LocalColorSpaceCache; - -class LocalFunctionCache extends BaseLocalCache { - constructor(options) { - super({ - onlyRefs: true - }); - } - - set(name = null, ref, data) { - if (!ref) { - throw new Error('LocalFunctionCache.set - expected "ref" argument.'); - } - - if (this._imageCache.has(ref)) { - return; - } - - this._imageCache.put(ref, data); - } - -} - -exports.LocalFunctionCache = LocalFunctionCache; - -class LocalGStateCache extends BaseLocalCache { - set(name, ref = null, data) { - if (typeof name !== "string") { - throw new Error('LocalGStateCache.set - expected "name" argument.'); - } - - if (ref) { - if (this._imageCache.has(ref)) { - return; - } - - this._nameRefMap.set(name, ref); - - this._imageCache.put(ref, data); - - return; - } - - if (this._imageMap.has(name)) { - return; - } - - this._imageMap.set(name, data); - } - -} - -exports.LocalGStateCache = LocalGStateCache; - -class LocalTilingPatternCache extends BaseLocalCache { - constructor(options) { - super({ - onlyRefs: true - }); - } - - set(name = null, ref, data) { - if (!ref) { - throw new Error('LocalTilingPatternCache.set - expected "ref" argument.'); - } - - if (this._imageCache.has(ref)) { - return; - } - - this._imageCache.put(ref, data); - } - -} - -exports.LocalTilingPatternCache = LocalTilingPatternCache; - -class GlobalImageCache { - static get NUM_PAGES_THRESHOLD() { - return (0, _util.shadow)(this, "NUM_PAGES_THRESHOLD", 2); - } - - static get MIN_IMAGES_TO_CACHE() { - return (0, _util.shadow)(this, "MIN_IMAGES_TO_CACHE", 10); - } - - static get MAX_BYTE_SIZE() { - return (0, _util.shadow)(this, "MAX_BYTE_SIZE", 40e6); - } - - constructor() { - this._refCache = new _primitives.RefSetCache(); - this._imageCache = new _primitives.RefSetCache(); - } - - get _byteSize() { - let byteSize = 0; - - this._imageCache.forEach(imageData => { - byteSize += imageData.byteSize; - }); - - return byteSize; - } - - get _cacheLimitReached() { - if (this._imageCache.size < GlobalImageCache.MIN_IMAGES_TO_CACHE) { - return false; - } - - if (this._byteSize < GlobalImageCache.MAX_BYTE_SIZE) { - return false; - } - - return true; - } - - shouldCache(ref, pageIndex) { - const pageIndexSet = this._refCache.get(ref); - - const numPages = pageIndexSet ? pageIndexSet.size + (pageIndexSet.has(pageIndex) ? 0 : 1) : 1; - - if (numPages < GlobalImageCache.NUM_PAGES_THRESHOLD) { - return false; - } - - if (!this._imageCache.has(ref) && this._cacheLimitReached) { - return false; - } - - return true; - } - - addPageIndex(ref, pageIndex) { - let pageIndexSet = this._refCache.get(ref); - - if (!pageIndexSet) { - pageIndexSet = new Set(); - - this._refCache.put(ref, pageIndexSet); - } - - pageIndexSet.add(pageIndex); - } - - addByteSize(ref, byteSize) { - const imageData = this._imageCache.get(ref); - - if (!imageData) { - return; - } - - if (imageData.byteSize) { - return; - } - - imageData.byteSize = byteSize; - } - - getData(ref, pageIndex) { - const pageIndexSet = this._refCache.get(ref); - - if (!pageIndexSet) { - return null; - } - - if (pageIndexSet.size < GlobalImageCache.NUM_PAGES_THRESHOLD) { - return null; - } - - const imageData = this._imageCache.get(ref); - - if (!imageData) { - return null; - } - - pageIndexSet.add(pageIndex); - return imageData; - } - - setData(ref, data) { - if (!this._refCache.has(ref)) { - throw new Error('GlobalImageCache.setData - expected "addPageIndex" to have been called.'); - } - - if (this._imageCache.has(ref)) { - return; - } - - if (this._cacheLimitReached) { - (0, _util.warn)("GlobalImageCache.setData - cache limit reached."); - return; - } - - this._imageCache.put(ref, data); - } - - clear(onlyData = false) { - if (!onlyData) { - this._refCache.clear(); - } - - this._imageCache.clear(); - } - -} - -exports.GlobalImageCache = GlobalImageCache; - -/***/ }), -/* 59 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.bidi = bidi; - -var _util = __w_pdfjs_require__(2); - -const 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", "ES", "CS", "ES", "CS", "CS", "EN", "EN", "EN", "EN", "EN", "EN", "EN", "EN", "EN", "EN", "CS", "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", "BN", "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"]; -const arabicTypes = ["AN", "AN", "AN", "AN", "AN", "AN", "ON", "ON", "AL", "ET", "ET", "AL", "CS", "AL", "ON", "ON", "NSM", "NSM", "NSM", "NSM", "NSM", "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", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "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", "AN", "ON", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "AL", "AL", "NSM", "NSM", "ON", "NSM", "NSM", "NSM", "NSM", "AL", "AL", "EN", "EN", "EN", "EN", "EN", "EN", "EN", "EN", "EN", "EN", "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) { - let j, jj; - - for (j = start, jj = arr.length; j < jj; ++j) { - if (arr[j] !== value) { - return j; - } - } - - return j; -} - -function setValues(arr, start, end, value) { - for (let j = start; j < end; ++j) { - arr[j] = value; - } -} - -function reverseValues(arr, start, end) { - for (let i = start, j = end - 1; i < j; ++i, --j) { - const temp = arr[i]; - arr[i] = arr[j]; - arr[j] = temp; - } -} - -function createBidiText(str, isLTR, vertical = false) { - let dir = "ltr"; - - if (vertical) { - dir = "ttb"; - } else if (!isLTR) { - dir = "rtl"; - } - - return { - str, - dir - }; -} - -const chars = []; -const types = []; - -function bidi(str, startLevel = -1, vertical = false) { - let isLTR = true; - const strLength = str.length; - - if (strLength === 0 || vertical) { - return createBidiText(str, isLTR, vertical); - } - - chars.length = strLength; - types.length = strLength; - let numBidi = 0; - let i, ii; - - for (i = 0; i < strLength; ++i) { - chars[i] = str.charAt(i); - const charCode = str.charCodeAt(i); - let 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]; - - if (!charType) { - (0, _util.warn)("Bidi: invalid Unicode character " + charCode.toString(16)); - } - } else if (0x0700 <= charCode && charCode <= 0x08ac) { - charType = "AL"; - } - - if (charType === "R" || charType === "AL" || charType === "AN") { - numBidi++; - } - - types[i] = charType; - } - - if (numBidi === 0) { - isLTR = true; - return createBidiText(str, isLTR); - } - - if (startLevel === -1) { - if (numBidi / strLength < 0.3 && strLength > 4) { - isLTR = true; - startLevel = 0; - } else { - isLTR = false; - startLevel = 1; - } - } - - const levels = []; - - for (i = 0; i < strLength; ++i) { - levels[i] = startLevel; - } - - const e = isOdd(startLevel) ? "R" : "L"; - const sor = e; - const eor = sor; - let lastType = sor; - - for (i = 0; i < strLength; ++i) { - if (types[i] === "NSM") { - types[i] = lastType; - } else { - lastType = types[i]; - } - } - - lastType = sor; - let t; - - for (i = 0; i < strLength; ++i) { - t = types[i]; - - if (t === "EN") { - types[i] = lastType === "AL" ? "AN" : "EN"; - } else if (t === "R" || t === "L" || t === "AL") { - lastType = t; - } - } - - for (i = 0; i < strLength; ++i) { - t = types[i]; - - if (t === "AL") { - types[i] = "R"; - } - } - - for (i = 1; i < strLength - 1; ++i) { - if (types[i] === "ES" && types[i - 1] === "EN" && types[i + 1] === "EN") { - types[i] = "EN"; - } - - if (types[i] === "CS" && (types[i - 1] === "EN" || types[i - 1] === "AN") && types[i + 1] === types[i - 1]) { - types[i] = types[i - 1]; - } - } - - for (i = 0; i < strLength; ++i) { - if (types[i] === "EN") { - for (let j = i - 1; j >= 0; --j) { - if (types[j] !== "ET") { - break; - } - - types[j] = "EN"; - } - - for (let j = i + 1; j < strLength; ++j) { - if (types[j] !== "ET") { - break; - } - - types[j] = "EN"; - } - } - } - - for (i = 0; i < strLength; ++i) { - t = types[i]; - - if (t === "WS" || t === "ES" || t === "ET" || t === "CS") { - types[i] = "ON"; - } - } - - lastType = sor; - - for (i = 0; i < strLength; ++i) { - t = types[i]; - - if (t === "EN") { - types[i] = lastType === "L" ? "L" : "EN"; - } else if (t === "R" || t === "L") { - lastType = t; - } - } - - for (i = 0; i < strLength; ++i) { - if (types[i] === "ON") { - const end = findUnequal(types, i + 1, "ON"); - let before = sor; - - if (i > 0) { - before = types[i - 1]; - } - - let 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; - } - } - - for (i = 0; i < strLength; ++i) { - if (types[i] === "ON") { - types[i] = e; - } - } - - for (i = 0; i < strLength; ++i) { - t = types[i]; - - if (isEven(levels[i])) { - if (t === "R") { - levels[i] += 1; - } else if (t === "AN" || t === "EN") { - levels[i] += 2; - } - } else { - if (t === "L" || t === "AN" || t === "EN") { - levels[i] += 1; - } - } - } - - let highestLevel = -1; - let lowestOddLevel = 99; - let level; - - for (i = 0, ii = levels.length; i < ii; ++i) { - level = levels[i]; - - if (highestLevel < level) { - highestLevel = level; - } - - if (lowestOddLevel > level && isOdd(level)) { - lowestOddLevel = level; - } - } - - for (level = highestLevel; level >= lowestOddLevel; --level) { - let start = -1; - - for (i = 0, ii = levels.length; i < ii; ++i) { - if (levels[i] < level) { - if (start >= 0) { - reverseValues(chars, start, i); - start = -1; - } - } else if (start < 0) { - start = i; - } - } - - if (start >= 0) { - reverseValues(chars, start, levels.length); - } - } - - for (i = 0, ii = chars.length; i < ii; ++i) { - const ch = chars[i]; - - if (ch === "<" || ch === ">") { - chars[i] = ""; - } - } - - return createBidiText(chars.join(""), isLTR); -} - -/***/ }), -/* 60 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.getMetrics = void 0; - -var _core_utils = __w_pdfjs_require__(9); - -const getMetrics = (0, _core_utils.getLookupTableFactory)(function (t) { - t.Courier = 600; - t["Courier-Bold"] = 600; - t["Courier-BoldOblique"] = 600; - t["Courier-Oblique"] = 600; - t.Helvetica = (0, _core_utils.getLookupTableFactory)(function (t) { - t.space = 278; - t.exclam = 278; - t.quotedbl = 355; - t.numbersign = 556; - t.dollar = 556; - t.percent = 889; - t.ampersand = 667; - t.quoteright = 222; - t.parenleft = 333; - t.parenright = 333; - t.asterisk = 389; - t.plus = 584; - t.comma = 278; - t.hyphen = 333; - t.period = 278; - t.slash = 278; - t.zero = 556; - t.one = 556; - t.two = 556; - t.three = 556; - t.four = 556; - t.five = 556; - t.six = 556; - t.seven = 556; - t.eight = 556; - t.nine = 556; - t.colon = 278; - t.semicolon = 278; - t.less = 584; - t.equal = 584; - t.greater = 584; - t.question = 556; - t.at = 1015; - t.A = 667; - t.B = 667; - t.C = 722; - t.D = 722; - t.E = 667; - t.F = 611; - t.G = 778; - t.H = 722; - t.I = 278; - t.J = 500; - t.K = 667; - t.L = 556; - t.M = 833; - t.N = 722; - t.O = 778; - t.P = 667; - t.Q = 778; - t.R = 722; - t.S = 667; - t.T = 611; - t.U = 722; - t.V = 667; - t.W = 944; - t.X = 667; - t.Y = 667; - t.Z = 611; - t.bracketleft = 278; - t.backslash = 278; - t.bracketright = 278; - t.asciicircum = 469; - t.underscore = 556; - t.quoteleft = 222; - t.a = 556; - t.b = 556; - t.c = 500; - t.d = 556; - t.e = 556; - t.f = 278; - t.g = 556; - t.h = 556; - t.i = 222; - t.j = 222; - t.k = 500; - t.l = 222; - t.m = 833; - t.n = 556; - t.o = 556; - t.p = 556; - t.q = 556; - t.r = 333; - t.s = 500; - t.t = 278; - t.u = 556; - t.v = 500; - t.w = 722; - t.x = 500; - t.y = 500; - t.z = 500; - t.braceleft = 334; - t.bar = 260; - t.braceright = 334; - t.asciitilde = 584; - t.exclamdown = 333; - t.cent = 556; - t.sterling = 556; - t.fraction = 167; - t.yen = 556; - t.florin = 556; - t.section = 556; - t.currency = 556; - t.quotesingle = 191; - t.quotedblleft = 333; - t.guillemotleft = 556; - t.guilsinglleft = 333; - t.guilsinglright = 333; - t.fi = 500; - t.fl = 500; - t.endash = 556; - t.dagger = 556; - t.daggerdbl = 556; - t.periodcentered = 278; - t.paragraph = 537; - t.bullet = 350; - t.quotesinglbase = 222; - t.quotedblbase = 333; - t.quotedblright = 333; - t.guillemotright = 556; - t.ellipsis = 1000; - t.perthousand = 1000; - t.questiondown = 611; - t.grave = 333; - t.acute = 333; - t.circumflex = 333; - t.tilde = 333; - t.macron = 333; - t.breve = 333; - t.dotaccent = 333; - t.dieresis = 333; - t.ring = 333; - t.cedilla = 333; - t.hungarumlaut = 333; - t.ogonek = 333; - t.caron = 333; - t.emdash = 1000; - t.AE = 1000; - t.ordfeminine = 370; - t.Lslash = 556; - t.Oslash = 778; - t.OE = 1000; - t.ordmasculine = 365; - t.ae = 889; - t.dotlessi = 278; - t.lslash = 222; - t.oslash = 611; - t.oe = 944; - t.germandbls = 611; - t.Idieresis = 278; - t.eacute = 556; - t.abreve = 556; - t.uhungarumlaut = 556; - t.ecaron = 556; - t.Ydieresis = 667; - t.divide = 584; - t.Yacute = 667; - t.Acircumflex = 667; - t.aacute = 556; - t.Ucircumflex = 722; - t.yacute = 500; - t.scommaaccent = 500; - t.ecircumflex = 556; - t.Uring = 722; - t.Udieresis = 722; - t.aogonek = 556; - t.Uacute = 722; - t.uogonek = 556; - t.Edieresis = 667; - t.Dcroat = 722; - t.commaaccent = 250; - t.copyright = 737; - t.Emacron = 667; - t.ccaron = 500; - t.aring = 556; - t.Ncommaaccent = 722; - t.lacute = 222; - t.agrave = 556; - t.Tcommaaccent = 611; - t.Cacute = 722; - t.atilde = 556; - t.Edotaccent = 667; - t.scaron = 500; - t.scedilla = 500; - t.iacute = 278; - t.lozenge = 471; - t.Rcaron = 722; - t.Gcommaaccent = 778; - t.ucircumflex = 556; - t.acircumflex = 556; - t.Amacron = 667; - t.rcaron = 333; - t.ccedilla = 500; - t.Zdotaccent = 611; - t.Thorn = 667; - t.Omacron = 778; - t.Racute = 722; - t.Sacute = 667; - t.dcaron = 643; - t.Umacron = 722; - t.uring = 556; - t.threesuperior = 333; - t.Ograve = 778; - t.Agrave = 667; - t.Abreve = 667; - t.multiply = 584; - t.uacute = 556; - t.Tcaron = 611; - t.partialdiff = 476; - t.ydieresis = 500; - t.Nacute = 722; - t.icircumflex = 278; - t.Ecircumflex = 667; - t.adieresis = 556; - t.edieresis = 556; - t.cacute = 500; - t.nacute = 556; - t.umacron = 556; - t.Ncaron = 722; - t.Iacute = 278; - t.plusminus = 584; - t.brokenbar = 260; - t.registered = 737; - t.Gbreve = 778; - t.Idotaccent = 278; - t.summation = 600; - t.Egrave = 667; - t.racute = 333; - t.omacron = 556; - t.Zacute = 611; - t.Zcaron = 611; - t.greaterequal = 549; - t.Eth = 722; - t.Ccedilla = 722; - t.lcommaaccent = 222; - t.tcaron = 317; - t.eogonek = 556; - t.Uogonek = 722; - t.Aacute = 667; - t.Adieresis = 667; - t.egrave = 556; - t.zacute = 500; - t.iogonek = 222; - t.Oacute = 778; - t.oacute = 556; - t.amacron = 556; - t.sacute = 500; - t.idieresis = 278; - t.Ocircumflex = 778; - t.Ugrave = 722; - t.Delta = 612; - t.thorn = 556; - t.twosuperior = 333; - t.Odieresis = 778; - t.mu = 556; - t.igrave = 278; - t.ohungarumlaut = 556; - t.Eogonek = 667; - t.dcroat = 556; - t.threequarters = 834; - t.Scedilla = 667; - t.lcaron = 299; - t.Kcommaaccent = 667; - t.Lacute = 556; - t.trademark = 1000; - t.edotaccent = 556; - t.Igrave = 278; - t.Imacron = 278; - t.Lcaron = 556; - t.onehalf = 834; - t.lessequal = 549; - t.ocircumflex = 556; - t.ntilde = 556; - t.Uhungarumlaut = 722; - t.Eacute = 667; - t.emacron = 556; - t.gbreve = 556; - t.onequarter = 834; - t.Scaron = 667; - t.Scommaaccent = 667; - t.Ohungarumlaut = 778; - t.degree = 400; - t.ograve = 556; - t.Ccaron = 722; - t.ugrave = 556; - t.radical = 453; - t.Dcaron = 722; - t.rcommaaccent = 333; - t.Ntilde = 722; - t.otilde = 556; - t.Rcommaaccent = 722; - t.Lcommaaccent = 556; - t.Atilde = 667; - t.Aogonek = 667; - t.Aring = 667; - t.Otilde = 778; - t.zdotaccent = 500; - t.Ecaron = 667; - t.Iogonek = 278; - t.kcommaaccent = 500; - t.minus = 584; - t.Icircumflex = 278; - t.ncaron = 556; - t.tcommaaccent = 278; - t.logicalnot = 584; - t.odieresis = 556; - t.udieresis = 556; - t.notequal = 549; - t.gcommaaccent = 556; - t.eth = 556; - t.zcaron = 500; - t.ncommaaccent = 556; - t.onesuperior = 333; - t.imacron = 278; - t.Euro = 556; - }); - t["Helvetica-Bold"] = (0, _core_utils.getLookupTableFactory)(function (t) { - t.space = 278; - t.exclam = 333; - t.quotedbl = 474; - t.numbersign = 556; - t.dollar = 556; - t.percent = 889; - t.ampersand = 722; - t.quoteright = 278; - t.parenleft = 333; - t.parenright = 333; - t.asterisk = 389; - t.plus = 584; - t.comma = 278; - t.hyphen = 333; - t.period = 278; - t.slash = 278; - t.zero = 556; - t.one = 556; - t.two = 556; - t.three = 556; - t.four = 556; - t.five = 556; - t.six = 556; - t.seven = 556; - t.eight = 556; - t.nine = 556; - t.colon = 333; - t.semicolon = 333; - t.less = 584; - t.equal = 584; - t.greater = 584; - t.question = 611; - t.at = 975; - t.A = 722; - t.B = 722; - t.C = 722; - t.D = 722; - t.E = 667; - t.F = 611; - t.G = 778; - t.H = 722; - t.I = 278; - t.J = 556; - t.K = 722; - t.L = 611; - t.M = 833; - t.N = 722; - t.O = 778; - t.P = 667; - t.Q = 778; - t.R = 722; - t.S = 667; - t.T = 611; - t.U = 722; - t.V = 667; - t.W = 944; - t.X = 667; - t.Y = 667; - t.Z = 611; - t.bracketleft = 333; - t.backslash = 278; - t.bracketright = 333; - t.asciicircum = 584; - t.underscore = 556; - t.quoteleft = 278; - t.a = 556; - t.b = 611; - t.c = 556; - t.d = 611; - t.e = 556; - t.f = 333; - t.g = 611; - t.h = 611; - t.i = 278; - t.j = 278; - t.k = 556; - t.l = 278; - t.m = 889; - t.n = 611; - t.o = 611; - t.p = 611; - t.q = 611; - t.r = 389; - t.s = 556; - t.t = 333; - t.u = 611; - t.v = 556; - t.w = 778; - t.x = 556; - t.y = 556; - t.z = 500; - t.braceleft = 389; - t.bar = 280; - t.braceright = 389; - t.asciitilde = 584; - t.exclamdown = 333; - t.cent = 556; - t.sterling = 556; - t.fraction = 167; - t.yen = 556; - t.florin = 556; - t.section = 556; - t.currency = 556; - t.quotesingle = 238; - t.quotedblleft = 500; - t.guillemotleft = 556; - t.guilsinglleft = 333; - t.guilsinglright = 333; - t.fi = 611; - t.fl = 611; - t.endash = 556; - t.dagger = 556; - t.daggerdbl = 556; - t.periodcentered = 278; - t.paragraph = 556; - t.bullet = 350; - t.quotesinglbase = 278; - t.quotedblbase = 500; - t.quotedblright = 500; - t.guillemotright = 556; - t.ellipsis = 1000; - t.perthousand = 1000; - t.questiondown = 611; - t.grave = 333; - t.acute = 333; - t.circumflex = 333; - t.tilde = 333; - t.macron = 333; - t.breve = 333; - t.dotaccent = 333; - t.dieresis = 333; - t.ring = 333; - t.cedilla = 333; - t.hungarumlaut = 333; - t.ogonek = 333; - t.caron = 333; - t.emdash = 1000; - t.AE = 1000; - t.ordfeminine = 370; - t.Lslash = 611; - t.Oslash = 778; - t.OE = 1000; - t.ordmasculine = 365; - t.ae = 889; - t.dotlessi = 278; - t.lslash = 278; - t.oslash = 611; - t.oe = 944; - t.germandbls = 611; - t.Idieresis = 278; - t.eacute = 556; - t.abreve = 556; - t.uhungarumlaut = 611; - t.ecaron = 556; - t.Ydieresis = 667; - t.divide = 584; - t.Yacute = 667; - t.Acircumflex = 722; - t.aacute = 556; - t.Ucircumflex = 722; - t.yacute = 556; - t.scommaaccent = 556; - t.ecircumflex = 556; - t.Uring = 722; - t.Udieresis = 722; - t.aogonek = 556; - t.Uacute = 722; - t.uogonek = 611; - t.Edieresis = 667; - t.Dcroat = 722; - t.commaaccent = 250; - t.copyright = 737; - t.Emacron = 667; - t.ccaron = 556; - t.aring = 556; - t.Ncommaaccent = 722; - t.lacute = 278; - t.agrave = 556; - t.Tcommaaccent = 611; - t.Cacute = 722; - t.atilde = 556; - t.Edotaccent = 667; - t.scaron = 556; - t.scedilla = 556; - t.iacute = 278; - t.lozenge = 494; - t.Rcaron = 722; - t.Gcommaaccent = 778; - t.ucircumflex = 611; - t.acircumflex = 556; - t.Amacron = 722; - t.rcaron = 389; - t.ccedilla = 556; - t.Zdotaccent = 611; - t.Thorn = 667; - t.Omacron = 778; - t.Racute = 722; - t.Sacute = 667; - t.dcaron = 743; - t.Umacron = 722; - t.uring = 611; - t.threesuperior = 333; - t.Ograve = 778; - t.Agrave = 722; - t.Abreve = 722; - t.multiply = 584; - t.uacute = 611; - t.Tcaron = 611; - t.partialdiff = 494; - t.ydieresis = 556; - t.Nacute = 722; - t.icircumflex = 278; - t.Ecircumflex = 667; - t.adieresis = 556; - t.edieresis = 556; - t.cacute = 556; - t.nacute = 611; - t.umacron = 611; - t.Ncaron = 722; - t.Iacute = 278; - t.plusminus = 584; - t.brokenbar = 280; - t.registered = 737; - t.Gbreve = 778; - t.Idotaccent = 278; - t.summation = 600; - t.Egrave = 667; - t.racute = 389; - t.omacron = 611; - t.Zacute = 611; - t.Zcaron = 611; - t.greaterequal = 549; - t.Eth = 722; - t.Ccedilla = 722; - t.lcommaaccent = 278; - t.tcaron = 389; - t.eogonek = 556; - t.Uogonek = 722; - t.Aacute = 722; - t.Adieresis = 722; - t.egrave = 556; - t.zacute = 500; - t.iogonek = 278; - t.Oacute = 778; - t.oacute = 611; - t.amacron = 556; - t.sacute = 556; - t.idieresis = 278; - t.Ocircumflex = 778; - t.Ugrave = 722; - t.Delta = 612; - t.thorn = 611; - t.twosuperior = 333; - t.Odieresis = 778; - t.mu = 611; - t.igrave = 278; - t.ohungarumlaut = 611; - t.Eogonek = 667; - t.dcroat = 611; - t.threequarters = 834; - t.Scedilla = 667; - t.lcaron = 400; - t.Kcommaaccent = 722; - t.Lacute = 611; - t.trademark = 1000; - t.edotaccent = 556; - t.Igrave = 278; - t.Imacron = 278; - t.Lcaron = 611; - t.onehalf = 834; - t.lessequal = 549; - t.ocircumflex = 611; - t.ntilde = 611; - t.Uhungarumlaut = 722; - t.Eacute = 667; - t.emacron = 556; - t.gbreve = 611; - t.onequarter = 834; - t.Scaron = 667; - t.Scommaaccent = 667; - t.Ohungarumlaut = 778; - t.degree = 400; - t.ograve = 611; - t.Ccaron = 722; - t.ugrave = 611; - t.radical = 549; - t.Dcaron = 722; - t.rcommaaccent = 389; - t.Ntilde = 722; - t.otilde = 611; - t.Rcommaaccent = 722; - t.Lcommaaccent = 611; - t.Atilde = 722; - t.Aogonek = 722; - t.Aring = 722; - t.Otilde = 778; - t.zdotaccent = 500; - t.Ecaron = 667; - t.Iogonek = 278; - t.kcommaaccent = 556; - t.minus = 584; - t.Icircumflex = 278; - t.ncaron = 611; - t.tcommaaccent = 333; - t.logicalnot = 584; - t.odieresis = 611; - t.udieresis = 611; - t.notequal = 549; - t.gcommaaccent = 611; - t.eth = 611; - t.zcaron = 500; - t.ncommaaccent = 611; - t.onesuperior = 333; - t.imacron = 278; - t.Euro = 556; - }); - t["Helvetica-BoldOblique"] = (0, _core_utils.getLookupTableFactory)(function (t) { - t.space = 278; - t.exclam = 333; - t.quotedbl = 474; - t.numbersign = 556; - t.dollar = 556; - t.percent = 889; - t.ampersand = 722; - t.quoteright = 278; - t.parenleft = 333; - t.parenright = 333; - t.asterisk = 389; - t.plus = 584; - t.comma = 278; - t.hyphen = 333; - t.period = 278; - t.slash = 278; - t.zero = 556; - t.one = 556; - t.two = 556; - t.three = 556; - t.four = 556; - t.five = 556; - t.six = 556; - t.seven = 556; - t.eight = 556; - t.nine = 556; - t.colon = 333; - t.semicolon = 333; - t.less = 584; - t.equal = 584; - t.greater = 584; - t.question = 611; - t.at = 975; - t.A = 722; - t.B = 722; - t.C = 722; - t.D = 722; - t.E = 667; - t.F = 611; - t.G = 778; - t.H = 722; - t.I = 278; - t.J = 556; - t.K = 722; - t.L = 611; - t.M = 833; - t.N = 722; - t.O = 778; - t.P = 667; - t.Q = 778; - t.R = 722; - t.S = 667; - t.T = 611; - t.U = 722; - t.V = 667; - t.W = 944; - t.X = 667; - t.Y = 667; - t.Z = 611; - t.bracketleft = 333; - t.backslash = 278; - t.bracketright = 333; - t.asciicircum = 584; - t.underscore = 556; - t.quoteleft = 278; - t.a = 556; - t.b = 611; - t.c = 556; - t.d = 611; - t.e = 556; - t.f = 333; - t.g = 611; - t.h = 611; - t.i = 278; - t.j = 278; - t.k = 556; - t.l = 278; - t.m = 889; - t.n = 611; - t.o = 611; - t.p = 611; - t.q = 611; - t.r = 389; - t.s = 556; - t.t = 333; - t.u = 611; - t.v = 556; - t.w = 778; - t.x = 556; - t.y = 556; - t.z = 500; - t.braceleft = 389; - t.bar = 280; - t.braceright = 389; - t.asciitilde = 584; - t.exclamdown = 333; - t.cent = 556; - t.sterling = 556; - t.fraction = 167; - t.yen = 556; - t.florin = 556; - t.section = 556; - t.currency = 556; - t.quotesingle = 238; - t.quotedblleft = 500; - t.guillemotleft = 556; - t.guilsinglleft = 333; - t.guilsinglright = 333; - t.fi = 611; - t.fl = 611; - t.endash = 556; - t.dagger = 556; - t.daggerdbl = 556; - t.periodcentered = 278; - t.paragraph = 556; - t.bullet = 350; - t.quotesinglbase = 278; - t.quotedblbase = 500; - t.quotedblright = 500; - t.guillemotright = 556; - t.ellipsis = 1000; - t.perthousand = 1000; - t.questiondown = 611; - t.grave = 333; - t.acute = 333; - t.circumflex = 333; - t.tilde = 333; - t.macron = 333; - t.breve = 333; - t.dotaccent = 333; - t.dieresis = 333; - t.ring = 333; - t.cedilla = 333; - t.hungarumlaut = 333; - t.ogonek = 333; - t.caron = 333; - t.emdash = 1000; - t.AE = 1000; - t.ordfeminine = 370; - t.Lslash = 611; - t.Oslash = 778; - t.OE = 1000; - t.ordmasculine = 365; - t.ae = 889; - t.dotlessi = 278; - t.lslash = 278; - t.oslash = 611; - t.oe = 944; - t.germandbls = 611; - t.Idieresis = 278; - t.eacute = 556; - t.abreve = 556; - t.uhungarumlaut = 611; - t.ecaron = 556; - t.Ydieresis = 667; - t.divide = 584; - t.Yacute = 667; - t.Acircumflex = 722; - t.aacute = 556; - t.Ucircumflex = 722; - t.yacute = 556; - t.scommaaccent = 556; - t.ecircumflex = 556; - t.Uring = 722; - t.Udieresis = 722; - t.aogonek = 556; - t.Uacute = 722; - t.uogonek = 611; - t.Edieresis = 667; - t.Dcroat = 722; - t.commaaccent = 250; - t.copyright = 737; - t.Emacron = 667; - t.ccaron = 556; - t.aring = 556; - t.Ncommaaccent = 722; - t.lacute = 278; - t.agrave = 556; - t.Tcommaaccent = 611; - t.Cacute = 722; - t.atilde = 556; - t.Edotaccent = 667; - t.scaron = 556; - t.scedilla = 556; - t.iacute = 278; - t.lozenge = 494; - t.Rcaron = 722; - t.Gcommaaccent = 778; - t.ucircumflex = 611; - t.acircumflex = 556; - t.Amacron = 722; - t.rcaron = 389; - t.ccedilla = 556; - t.Zdotaccent = 611; - t.Thorn = 667; - t.Omacron = 778; - t.Racute = 722; - t.Sacute = 667; - t.dcaron = 743; - t.Umacron = 722; - t.uring = 611; - t.threesuperior = 333; - t.Ograve = 778; - t.Agrave = 722; - t.Abreve = 722; - t.multiply = 584; - t.uacute = 611; - t.Tcaron = 611; - t.partialdiff = 494; - t.ydieresis = 556; - t.Nacute = 722; - t.icircumflex = 278; - t.Ecircumflex = 667; - t.adieresis = 556; - t.edieresis = 556; - t.cacute = 556; - t.nacute = 611; - t.umacron = 611; - t.Ncaron = 722; - t.Iacute = 278; - t.plusminus = 584; - t.brokenbar = 280; - t.registered = 737; - t.Gbreve = 778; - t.Idotaccent = 278; - t.summation = 600; - t.Egrave = 667; - t.racute = 389; - t.omacron = 611; - t.Zacute = 611; - t.Zcaron = 611; - t.greaterequal = 549; - t.Eth = 722; - t.Ccedilla = 722; - t.lcommaaccent = 278; - t.tcaron = 389; - t.eogonek = 556; - t.Uogonek = 722; - t.Aacute = 722; - t.Adieresis = 722; - t.egrave = 556; - t.zacute = 500; - t.iogonek = 278; - t.Oacute = 778; - t.oacute = 611; - t.amacron = 556; - t.sacute = 556; - t.idieresis = 278; - t.Ocircumflex = 778; - t.Ugrave = 722; - t.Delta = 612; - t.thorn = 611; - t.twosuperior = 333; - t.Odieresis = 778; - t.mu = 611; - t.igrave = 278; - t.ohungarumlaut = 611; - t.Eogonek = 667; - t.dcroat = 611; - t.threequarters = 834; - t.Scedilla = 667; - t.lcaron = 400; - t.Kcommaaccent = 722; - t.Lacute = 611; - t.trademark = 1000; - t.edotaccent = 556; - t.Igrave = 278; - t.Imacron = 278; - t.Lcaron = 611; - t.onehalf = 834; - t.lessequal = 549; - t.ocircumflex = 611; - t.ntilde = 611; - t.Uhungarumlaut = 722; - t.Eacute = 667; - t.emacron = 556; - t.gbreve = 611; - t.onequarter = 834; - t.Scaron = 667; - t.Scommaaccent = 667; - t.Ohungarumlaut = 778; - t.degree = 400; - t.ograve = 611; - t.Ccaron = 722; - t.ugrave = 611; - t.radical = 549; - t.Dcaron = 722; - t.rcommaaccent = 389; - t.Ntilde = 722; - t.otilde = 611; - t.Rcommaaccent = 722; - t.Lcommaaccent = 611; - t.Atilde = 722; - t.Aogonek = 722; - t.Aring = 722; - t.Otilde = 778; - t.zdotaccent = 500; - t.Ecaron = 667; - t.Iogonek = 278; - t.kcommaaccent = 556; - t.minus = 584; - t.Icircumflex = 278; - t.ncaron = 611; - t.tcommaaccent = 333; - t.logicalnot = 584; - t.odieresis = 611; - t.udieresis = 611; - t.notequal = 549; - t.gcommaaccent = 611; - t.eth = 611; - t.zcaron = 500; - t.ncommaaccent = 611; - t.onesuperior = 333; - t.imacron = 278; - t.Euro = 556; - }); - t["Helvetica-Oblique"] = (0, _core_utils.getLookupTableFactory)(function (t) { - t.space = 278; - t.exclam = 278; - t.quotedbl = 355; - t.numbersign = 556; - t.dollar = 556; - t.percent = 889; - t.ampersand = 667; - t.quoteright = 222; - t.parenleft = 333; - t.parenright = 333; - t.asterisk = 389; - t.plus = 584; - t.comma = 278; - t.hyphen = 333; - t.period = 278; - t.slash = 278; - t.zero = 556; - t.one = 556; - t.two = 556; - t.three = 556; - t.four = 556; - t.five = 556; - t.six = 556; - t.seven = 556; - t.eight = 556; - t.nine = 556; - t.colon = 278; - t.semicolon = 278; - t.less = 584; - t.equal = 584; - t.greater = 584; - t.question = 556; - t.at = 1015; - t.A = 667; - t.B = 667; - t.C = 722; - t.D = 722; - t.E = 667; - t.F = 611; - t.G = 778; - t.H = 722; - t.I = 278; - t.J = 500; - t.K = 667; - t.L = 556; - t.M = 833; - t.N = 722; - t.O = 778; - t.P = 667; - t.Q = 778; - t.R = 722; - t.S = 667; - t.T = 611; - t.U = 722; - t.V = 667; - t.W = 944; - t.X = 667; - t.Y = 667; - t.Z = 611; - t.bracketleft = 278; - t.backslash = 278; - t.bracketright = 278; - t.asciicircum = 469; - t.underscore = 556; - t.quoteleft = 222; - t.a = 556; - t.b = 556; - t.c = 500; - t.d = 556; - t.e = 556; - t.f = 278; - t.g = 556; - t.h = 556; - t.i = 222; - t.j = 222; - t.k = 500; - t.l = 222; - t.m = 833; - t.n = 556; - t.o = 556; - t.p = 556; - t.q = 556; - t.r = 333; - t.s = 500; - t.t = 278; - t.u = 556; - t.v = 500; - t.w = 722; - t.x = 500; - t.y = 500; - t.z = 500; - t.braceleft = 334; - t.bar = 260; - t.braceright = 334; - t.asciitilde = 584; - t.exclamdown = 333; - t.cent = 556; - t.sterling = 556; - t.fraction = 167; - t.yen = 556; - t.florin = 556; - t.section = 556; - t.currency = 556; - t.quotesingle = 191; - t.quotedblleft = 333; - t.guillemotleft = 556; - t.guilsinglleft = 333; - t.guilsinglright = 333; - t.fi = 500; - t.fl = 500; - t.endash = 556; - t.dagger = 556; - t.daggerdbl = 556; - t.periodcentered = 278; - t.paragraph = 537; - t.bullet = 350; - t.quotesinglbase = 222; - t.quotedblbase = 333; - t.quotedblright = 333; - t.guillemotright = 556; - t.ellipsis = 1000; - t.perthousand = 1000; - t.questiondown = 611; - t.grave = 333; - t.acute = 333; - t.circumflex = 333; - t.tilde = 333; - t.macron = 333; - t.breve = 333; - t.dotaccent = 333; - t.dieresis = 333; - t.ring = 333; - t.cedilla = 333; - t.hungarumlaut = 333; - t.ogonek = 333; - t.caron = 333; - t.emdash = 1000; - t.AE = 1000; - t.ordfeminine = 370; - t.Lslash = 556; - t.Oslash = 778; - t.OE = 1000; - t.ordmasculine = 365; - t.ae = 889; - t.dotlessi = 278; - t.lslash = 222; - t.oslash = 611; - t.oe = 944; - t.germandbls = 611; - t.Idieresis = 278; - t.eacute = 556; - t.abreve = 556; - t.uhungarumlaut = 556; - t.ecaron = 556; - t.Ydieresis = 667; - t.divide = 584; - t.Yacute = 667; - t.Acircumflex = 667; - t.aacute = 556; - t.Ucircumflex = 722; - t.yacute = 500; - t.scommaaccent = 500; - t.ecircumflex = 556; - t.Uring = 722; - t.Udieresis = 722; - t.aogonek = 556; - t.Uacute = 722; - t.uogonek = 556; - t.Edieresis = 667; - t.Dcroat = 722; - t.commaaccent = 250; - t.copyright = 737; - t.Emacron = 667; - t.ccaron = 500; - t.aring = 556; - t.Ncommaaccent = 722; - t.lacute = 222; - t.agrave = 556; - t.Tcommaaccent = 611; - t.Cacute = 722; - t.atilde = 556; - t.Edotaccent = 667; - t.scaron = 500; - t.scedilla = 500; - t.iacute = 278; - t.lozenge = 471; - t.Rcaron = 722; - t.Gcommaaccent = 778; - t.ucircumflex = 556; - t.acircumflex = 556; - t.Amacron = 667; - t.rcaron = 333; - t.ccedilla = 500; - t.Zdotaccent = 611; - t.Thorn = 667; - t.Omacron = 778; - t.Racute = 722; - t.Sacute = 667; - t.dcaron = 643; - t.Umacron = 722; - t.uring = 556; - t.threesuperior = 333; - t.Ograve = 778; - t.Agrave = 667; - t.Abreve = 667; - t.multiply = 584; - t.uacute = 556; - t.Tcaron = 611; - t.partialdiff = 476; - t.ydieresis = 500; - t.Nacute = 722; - t.icircumflex = 278; - t.Ecircumflex = 667; - t.adieresis = 556; - t.edieresis = 556; - t.cacute = 500; - t.nacute = 556; - t.umacron = 556; - t.Ncaron = 722; - t.Iacute = 278; - t.plusminus = 584; - t.brokenbar = 260; - t.registered = 737; - t.Gbreve = 778; - t.Idotaccent = 278; - t.summation = 600; - t.Egrave = 667; - t.racute = 333; - t.omacron = 556; - t.Zacute = 611; - t.Zcaron = 611; - t.greaterequal = 549; - t.Eth = 722; - t.Ccedilla = 722; - t.lcommaaccent = 222; - t.tcaron = 317; - t.eogonek = 556; - t.Uogonek = 722; - t.Aacute = 667; - t.Adieresis = 667; - t.egrave = 556; - t.zacute = 500; - t.iogonek = 222; - t.Oacute = 778; - t.oacute = 556; - t.amacron = 556; - t.sacute = 500; - t.idieresis = 278; - t.Ocircumflex = 778; - t.Ugrave = 722; - t.Delta = 612; - t.thorn = 556; - t.twosuperior = 333; - t.Odieresis = 778; - t.mu = 556; - t.igrave = 278; - t.ohungarumlaut = 556; - t.Eogonek = 667; - t.dcroat = 556; - t.threequarters = 834; - t.Scedilla = 667; - t.lcaron = 299; - t.Kcommaaccent = 667; - t.Lacute = 556; - t.trademark = 1000; - t.edotaccent = 556; - t.Igrave = 278; - t.Imacron = 278; - t.Lcaron = 556; - t.onehalf = 834; - t.lessequal = 549; - t.ocircumflex = 556; - t.ntilde = 556; - t.Uhungarumlaut = 722; - t.Eacute = 667; - t.emacron = 556; - t.gbreve = 556; - t.onequarter = 834; - t.Scaron = 667; - t.Scommaaccent = 667; - t.Ohungarumlaut = 778; - t.degree = 400; - t.ograve = 556; - t.Ccaron = 722; - t.ugrave = 556; - t.radical = 453; - t.Dcaron = 722; - t.rcommaaccent = 333; - t.Ntilde = 722; - t.otilde = 556; - t.Rcommaaccent = 722; - t.Lcommaaccent = 556; - t.Atilde = 667; - t.Aogonek = 667; - t.Aring = 667; - t.Otilde = 778; - t.zdotaccent = 500; - t.Ecaron = 667; - t.Iogonek = 278; - t.kcommaaccent = 500; - t.minus = 584; - t.Icircumflex = 278; - t.ncaron = 556; - t.tcommaaccent = 278; - t.logicalnot = 584; - t.odieresis = 556; - t.udieresis = 556; - t.notequal = 549; - t.gcommaaccent = 556; - t.eth = 556; - t.zcaron = 500; - t.ncommaaccent = 556; - t.onesuperior = 333; - t.imacron = 278; - t.Euro = 556; - }); - t.Symbol = (0, _core_utils.getLookupTableFactory)(function (t) { - t.space = 250; - t.exclam = 333; - t.universal = 713; - t.numbersign = 500; - t.existential = 549; - t.percent = 833; - t.ampersand = 778; - t.suchthat = 439; - t.parenleft = 333; - t.parenright = 333; - t.asteriskmath = 500; - t.plus = 549; - t.comma = 250; - t.minus = 549; - t.period = 250; - t.slash = 278; - t.zero = 500; - t.one = 500; - t.two = 500; - t.three = 500; - t.four = 500; - t.five = 500; - t.six = 500; - t.seven = 500; - t.eight = 500; - t.nine = 500; - t.colon = 278; - t.semicolon = 278; - t.less = 549; - t.equal = 549; - t.greater = 549; - t.question = 444; - t.congruent = 549; - t.Alpha = 722; - t.Beta = 667; - t.Chi = 722; - t.Delta = 612; - t.Epsilon = 611; - t.Phi = 763; - t.Gamma = 603; - t.Eta = 722; - t.Iota = 333; - t.theta1 = 631; - t.Kappa = 722; - t.Lambda = 686; - t.Mu = 889; - t.Nu = 722; - t.Omicron = 722; - t.Pi = 768; - t.Theta = 741; - t.Rho = 556; - t.Sigma = 592; - t.Tau = 611; - t.Upsilon = 690; - t.sigma1 = 439; - t.Omega = 768; - t.Xi = 645; - t.Psi = 795; - t.Zeta = 611; - t.bracketleft = 333; - t.therefore = 863; - t.bracketright = 333; - t.perpendicular = 658; - t.underscore = 500; - t.radicalex = 500; - t.alpha = 631; - t.beta = 549; - t.chi = 549; - t.delta = 494; - t.epsilon = 439; - t.phi = 521; - t.gamma = 411; - t.eta = 603; - t.iota = 329; - t.phi1 = 603; - t.kappa = 549; - t.lambda = 549; - t.mu = 576; - t.nu = 521; - t.omicron = 549; - t.pi = 549; - t.theta = 521; - t.rho = 549; - t.sigma = 603; - t.tau = 439; - t.upsilon = 576; - t.omega1 = 713; - t.omega = 686; - t.xi = 493; - t.psi = 686; - t.zeta = 494; - t.braceleft = 480; - t.bar = 200; - t.braceright = 480; - t.similar = 549; - t.Euro = 750; - t.Upsilon1 = 620; - t.minute = 247; - t.lessequal = 549; - t.fraction = 167; - t.infinity = 713; - t.florin = 500; - t.club = 753; - t.diamond = 753; - t.heart = 753; - t.spade = 753; - t.arrowboth = 1042; - t.arrowleft = 987; - t.arrowup = 603; - t.arrowright = 987; - t.arrowdown = 603; - t.degree = 400; - t.plusminus = 549; - t.second = 411; - t.greaterequal = 549; - t.multiply = 549; - t.proportional = 713; - t.partialdiff = 494; - t.bullet = 460; - t.divide = 549; - t.notequal = 549; - t.equivalence = 549; - t.approxequal = 549; - t.ellipsis = 1000; - t.arrowvertex = 603; - t.arrowhorizex = 1000; - t.carriagereturn = 658; - t.aleph = 823; - t.Ifraktur = 686; - t.Rfraktur = 795; - t.weierstrass = 987; - t.circlemultiply = 768; - t.circleplus = 768; - t.emptyset = 823; - t.intersection = 768; - t.union = 768; - t.propersuperset = 713; - t.reflexsuperset = 713; - t.notsubset = 713; - t.propersubset = 713; - t.reflexsubset = 713; - t.element = 713; - t.notelement = 713; - t.angle = 768; - t.gradient = 713; - t.registerserif = 790; - t.copyrightserif = 790; - t.trademarkserif = 890; - t.product = 823; - t.radical = 549; - t.dotmath = 250; - t.logicalnot = 713; - t.logicaland = 603; - t.logicalor = 603; - t.arrowdblboth = 1042; - t.arrowdblleft = 987; - t.arrowdblup = 603; - t.arrowdblright = 987; - t.arrowdbldown = 603; - t.lozenge = 494; - t.angleleft = 329; - t.registersans = 790; - t.copyrightsans = 790; - t.trademarksans = 786; - t.summation = 713; - t.parenlefttp = 384; - t.parenleftex = 384; - t.parenleftbt = 384; - t.bracketlefttp = 384; - t.bracketleftex = 384; - t.bracketleftbt = 384; - t.bracelefttp = 494; - t.braceleftmid = 494; - t.braceleftbt = 494; - t.braceex = 494; - t.angleright = 329; - t.integral = 274; - t.integraltp = 686; - t.integralex = 686; - t.integralbt = 686; - t.parenrighttp = 384; - t.parenrightex = 384; - t.parenrightbt = 384; - t.bracketrighttp = 384; - t.bracketrightex = 384; - t.bracketrightbt = 384; - t.bracerighttp = 494; - t.bracerightmid = 494; - t.bracerightbt = 494; - t.apple = 790; - }); - t["Times-Roman"] = (0, _core_utils.getLookupTableFactory)(function (t) { - t.space = 250; - t.exclam = 333; - t.quotedbl = 408; - t.numbersign = 500; - t.dollar = 500; - t.percent = 833; - t.ampersand = 778; - t.quoteright = 333; - t.parenleft = 333; - t.parenright = 333; - t.asterisk = 500; - t.plus = 564; - t.comma = 250; - t.hyphen = 333; - t.period = 250; - t.slash = 278; - t.zero = 500; - t.one = 500; - t.two = 500; - t.three = 500; - t.four = 500; - t.five = 500; - t.six = 500; - t.seven = 500; - t.eight = 500; - t.nine = 500; - t.colon = 278; - t.semicolon = 278; - t.less = 564; - t.equal = 564; - t.greater = 564; - t.question = 444; - t.at = 921; - t.A = 722; - t.B = 667; - t.C = 667; - t.D = 722; - t.E = 611; - t.F = 556; - t.G = 722; - t.H = 722; - t.I = 333; - t.J = 389; - t.K = 722; - t.L = 611; - t.M = 889; - t.N = 722; - t.O = 722; - t.P = 556; - t.Q = 722; - t.R = 667; - t.S = 556; - t.T = 611; - t.U = 722; - t.V = 722; - t.W = 944; - t.X = 722; - t.Y = 722; - t.Z = 611; - t.bracketleft = 333; - t.backslash = 278; - t.bracketright = 333; - t.asciicircum = 469; - t.underscore = 500; - t.quoteleft = 333; - t.a = 444; - t.b = 500; - t.c = 444; - t.d = 500; - t.e = 444; - t.f = 333; - t.g = 500; - t.h = 500; - t.i = 278; - t.j = 278; - t.k = 500; - t.l = 278; - t.m = 778; - t.n = 500; - t.o = 500; - t.p = 500; - t.q = 500; - t.r = 333; - t.s = 389; - t.t = 278; - t.u = 500; - t.v = 500; - t.w = 722; - t.x = 500; - t.y = 500; - t.z = 444; - t.braceleft = 480; - t.bar = 200; - t.braceright = 480; - t.asciitilde = 541; - t.exclamdown = 333; - t.cent = 500; - t.sterling = 500; - t.fraction = 167; - t.yen = 500; - t.florin = 500; - t.section = 500; - t.currency = 500; - t.quotesingle = 180; - t.quotedblleft = 444; - t.guillemotleft = 500; - t.guilsinglleft = 333; - t.guilsinglright = 333; - t.fi = 556; - t.fl = 556; - t.endash = 500; - t.dagger = 500; - t.daggerdbl = 500; - t.periodcentered = 250; - t.paragraph = 453; - t.bullet = 350; - t.quotesinglbase = 333; - t.quotedblbase = 444; - t.quotedblright = 444; - t.guillemotright = 500; - t.ellipsis = 1000; - t.perthousand = 1000; - t.questiondown = 444; - t.grave = 333; - t.acute = 333; - t.circumflex = 333; - t.tilde = 333; - t.macron = 333; - t.breve = 333; - t.dotaccent = 333; - t.dieresis = 333; - t.ring = 333; - t.cedilla = 333; - t.hungarumlaut = 333; - t.ogonek = 333; - t.caron = 333; - t.emdash = 1000; - t.AE = 889; - t.ordfeminine = 276; - t.Lslash = 611; - t.Oslash = 722; - t.OE = 889; - t.ordmasculine = 310; - t.ae = 667; - t.dotlessi = 278; - t.lslash = 278; - t.oslash = 500; - t.oe = 722; - t.germandbls = 500; - t.Idieresis = 333; - t.eacute = 444; - t.abreve = 444; - t.uhungarumlaut = 500; - t.ecaron = 444; - t.Ydieresis = 722; - t.divide = 564; - t.Yacute = 722; - t.Acircumflex = 722; - t.aacute = 444; - t.Ucircumflex = 722; - t.yacute = 500; - t.scommaaccent = 389; - t.ecircumflex = 444; - t.Uring = 722; - t.Udieresis = 722; - t.aogonek = 444; - t.Uacute = 722; - t.uogonek = 500; - t.Edieresis = 611; - t.Dcroat = 722; - t.commaaccent = 250; - t.copyright = 760; - t.Emacron = 611; - t.ccaron = 444; - t.aring = 444; - t.Ncommaaccent = 722; - t.lacute = 278; - t.agrave = 444; - t.Tcommaaccent = 611; - t.Cacute = 667; - t.atilde = 444; - t.Edotaccent = 611; - t.scaron = 389; - t.scedilla = 389; - t.iacute = 278; - t.lozenge = 471; - t.Rcaron = 667; - t.Gcommaaccent = 722; - t.ucircumflex = 500; - t.acircumflex = 444; - t.Amacron = 722; - t.rcaron = 333; - t.ccedilla = 444; - t.Zdotaccent = 611; - t.Thorn = 556; - t.Omacron = 722; - t.Racute = 667; - t.Sacute = 556; - t.dcaron = 588; - t.Umacron = 722; - t.uring = 500; - t.threesuperior = 300; - t.Ograve = 722; - t.Agrave = 722; - t.Abreve = 722; - t.multiply = 564; - t.uacute = 500; - t.Tcaron = 611; - t.partialdiff = 476; - t.ydieresis = 500; - t.Nacute = 722; - t.icircumflex = 278; - t.Ecircumflex = 611; - t.adieresis = 444; - t.edieresis = 444; - t.cacute = 444; - t.nacute = 500; - t.umacron = 500; - t.Ncaron = 722; - t.Iacute = 333; - t.plusminus = 564; - t.brokenbar = 200; - t.registered = 760; - t.Gbreve = 722; - t.Idotaccent = 333; - t.summation = 600; - t.Egrave = 611; - t.racute = 333; - t.omacron = 500; - t.Zacute = 611; - t.Zcaron = 611; - t.greaterequal = 549; - t.Eth = 722; - t.Ccedilla = 667; - t.lcommaaccent = 278; - t.tcaron = 326; - t.eogonek = 444; - t.Uogonek = 722; - t.Aacute = 722; - t.Adieresis = 722; - t.egrave = 444; - t.zacute = 444; - t.iogonek = 278; - t.Oacute = 722; - t.oacute = 500; - t.amacron = 444; - t.sacute = 389; - t.idieresis = 278; - t.Ocircumflex = 722; - t.Ugrave = 722; - t.Delta = 612; - t.thorn = 500; - t.twosuperior = 300; - t.Odieresis = 722; - t.mu = 500; - t.igrave = 278; - t.ohungarumlaut = 500; - t.Eogonek = 611; - t.dcroat = 500; - t.threequarters = 750; - t.Scedilla = 556; - t.lcaron = 344; - t.Kcommaaccent = 722; - t.Lacute = 611; - t.trademark = 980; - t.edotaccent = 444; - t.Igrave = 333; - t.Imacron = 333; - t.Lcaron = 611; - t.onehalf = 750; - t.lessequal = 549; - t.ocircumflex = 500; - t.ntilde = 500; - t.Uhungarumlaut = 722; - t.Eacute = 611; - t.emacron = 444; - t.gbreve = 500; - t.onequarter = 750; - t.Scaron = 556; - t.Scommaaccent = 556; - t.Ohungarumlaut = 722; - t.degree = 400; - t.ograve = 500; - t.Ccaron = 667; - t.ugrave = 500; - t.radical = 453; - t.Dcaron = 722; - t.rcommaaccent = 333; - t.Ntilde = 722; - t.otilde = 500; - t.Rcommaaccent = 667; - t.Lcommaaccent = 611; - t.Atilde = 722; - t.Aogonek = 722; - t.Aring = 722; - t.Otilde = 722; - t.zdotaccent = 444; - t.Ecaron = 611; - t.Iogonek = 333; - t.kcommaaccent = 500; - t.minus = 564; - t.Icircumflex = 333; - t.ncaron = 500; - t.tcommaaccent = 278; - t.logicalnot = 564; - t.odieresis = 500; - t.udieresis = 500; - t.notequal = 549; - t.gcommaaccent = 500; - t.eth = 500; - t.zcaron = 444; - t.ncommaaccent = 500; - t.onesuperior = 300; - t.imacron = 278; - t.Euro = 500; - }); - t["Times-Bold"] = (0, _core_utils.getLookupTableFactory)(function (t) { - t.space = 250; - t.exclam = 333; - t.quotedbl = 555; - t.numbersign = 500; - t.dollar = 500; - t.percent = 1000; - t.ampersand = 833; - t.quoteright = 333; - t.parenleft = 333; - t.parenright = 333; - t.asterisk = 500; - t.plus = 570; - t.comma = 250; - t.hyphen = 333; - t.period = 250; - t.slash = 278; - t.zero = 500; - t.one = 500; - t.two = 500; - t.three = 500; - t.four = 500; - t.five = 500; - t.six = 500; - t.seven = 500; - t.eight = 500; - t.nine = 500; - t.colon = 333; - t.semicolon = 333; - t.less = 570; - t.equal = 570; - t.greater = 570; - t.question = 500; - t.at = 930; - t.A = 722; - t.B = 667; - t.C = 722; - t.D = 722; - t.E = 667; - t.F = 611; - t.G = 778; - t.H = 778; - t.I = 389; - t.J = 500; - t.K = 778; - t.L = 667; - t.M = 944; - t.N = 722; - t.O = 778; - t.P = 611; - t.Q = 778; - t.R = 722; - t.S = 556; - t.T = 667; - t.U = 722; - t.V = 722; - t.W = 1000; - t.X = 722; - t.Y = 722; - t.Z = 667; - t.bracketleft = 333; - t.backslash = 278; - t.bracketright = 333; - t.asciicircum = 581; - t.underscore = 500; - t.quoteleft = 333; - t.a = 500; - t.b = 556; - t.c = 444; - t.d = 556; - t.e = 444; - t.f = 333; - t.g = 500; - t.h = 556; - t.i = 278; - t.j = 333; - t.k = 556; - t.l = 278; - t.m = 833; - t.n = 556; - t.o = 500; - t.p = 556; - t.q = 556; - t.r = 444; - t.s = 389; - t.t = 333; - t.u = 556; - t.v = 500; - t.w = 722; - t.x = 500; - t.y = 500; - t.z = 444; - t.braceleft = 394; - t.bar = 220; - t.braceright = 394; - t.asciitilde = 520; - t.exclamdown = 333; - t.cent = 500; - t.sterling = 500; - t.fraction = 167; - t.yen = 500; - t.florin = 500; - t.section = 500; - t.currency = 500; - t.quotesingle = 278; - t.quotedblleft = 500; - t.guillemotleft = 500; - t.guilsinglleft = 333; - t.guilsinglright = 333; - t.fi = 556; - t.fl = 556; - t.endash = 500; - t.dagger = 500; - t.daggerdbl = 500; - t.periodcentered = 250; - t.paragraph = 540; - t.bullet = 350; - t.quotesinglbase = 333; - t.quotedblbase = 500; - t.quotedblright = 500; - t.guillemotright = 500; - t.ellipsis = 1000; - t.perthousand = 1000; - t.questiondown = 500; - t.grave = 333; - t.acute = 333; - t.circumflex = 333; - t.tilde = 333; - t.macron = 333; - t.breve = 333; - t.dotaccent = 333; - t.dieresis = 333; - t.ring = 333; - t.cedilla = 333; - t.hungarumlaut = 333; - t.ogonek = 333; - t.caron = 333; - t.emdash = 1000; - t.AE = 1000; - t.ordfeminine = 300; - t.Lslash = 667; - t.Oslash = 778; - t.OE = 1000; - t.ordmasculine = 330; - t.ae = 722; - t.dotlessi = 278; - t.lslash = 278; - t.oslash = 500; - t.oe = 722; - t.germandbls = 556; - t.Idieresis = 389; - t.eacute = 444; - t.abreve = 500; - t.uhungarumlaut = 556; - t.ecaron = 444; - t.Ydieresis = 722; - t.divide = 570; - t.Yacute = 722; - t.Acircumflex = 722; - t.aacute = 500; - t.Ucircumflex = 722; - t.yacute = 500; - t.scommaaccent = 389; - t.ecircumflex = 444; - t.Uring = 722; - t.Udieresis = 722; - t.aogonek = 500; - t.Uacute = 722; - t.uogonek = 556; - t.Edieresis = 667; - t.Dcroat = 722; - t.commaaccent = 250; - t.copyright = 747; - t.Emacron = 667; - t.ccaron = 444; - t.aring = 500; - t.Ncommaaccent = 722; - t.lacute = 278; - t.agrave = 500; - t.Tcommaaccent = 667; - t.Cacute = 722; - t.atilde = 500; - t.Edotaccent = 667; - t.scaron = 389; - t.scedilla = 389; - t.iacute = 278; - t.lozenge = 494; - t.Rcaron = 722; - t.Gcommaaccent = 778; - t.ucircumflex = 556; - t.acircumflex = 500; - t.Amacron = 722; - t.rcaron = 444; - t.ccedilla = 444; - t.Zdotaccent = 667; - t.Thorn = 611; - t.Omacron = 778; - t.Racute = 722; - t.Sacute = 556; - t.dcaron = 672; - t.Umacron = 722; - t.uring = 556; - t.threesuperior = 300; - t.Ograve = 778; - t.Agrave = 722; - t.Abreve = 722; - t.multiply = 570; - t.uacute = 556; - t.Tcaron = 667; - t.partialdiff = 494; - t.ydieresis = 500; - t.Nacute = 722; - t.icircumflex = 278; - t.Ecircumflex = 667; - t.adieresis = 500; - t.edieresis = 444; - t.cacute = 444; - t.nacute = 556; - t.umacron = 556; - t.Ncaron = 722; - t.Iacute = 389; - t.plusminus = 570; - t.brokenbar = 220; - t.registered = 747; - t.Gbreve = 778; - t.Idotaccent = 389; - t.summation = 600; - t.Egrave = 667; - t.racute = 444; - t.omacron = 500; - t.Zacute = 667; - t.Zcaron = 667; - t.greaterequal = 549; - t.Eth = 722; - t.Ccedilla = 722; - t.lcommaaccent = 278; - t.tcaron = 416; - t.eogonek = 444; - t.Uogonek = 722; - t.Aacute = 722; - t.Adieresis = 722; - t.egrave = 444; - t.zacute = 444; - t.iogonek = 278; - t.Oacute = 778; - t.oacute = 500; - t.amacron = 500; - t.sacute = 389; - t.idieresis = 278; - t.Ocircumflex = 778; - t.Ugrave = 722; - t.Delta = 612; - t.thorn = 556; - t.twosuperior = 300; - t.Odieresis = 778; - t.mu = 556; - t.igrave = 278; - t.ohungarumlaut = 500; - t.Eogonek = 667; - t.dcroat = 556; - t.threequarters = 750; - t.Scedilla = 556; - t.lcaron = 394; - t.Kcommaaccent = 778; - t.Lacute = 667; - t.trademark = 1000; - t.edotaccent = 444; - t.Igrave = 389; - t.Imacron = 389; - t.Lcaron = 667; - t.onehalf = 750; - t.lessequal = 549; - t.ocircumflex = 500; - t.ntilde = 556; - t.Uhungarumlaut = 722; - t.Eacute = 667; - t.emacron = 444; - t.gbreve = 500; - t.onequarter = 750; - t.Scaron = 556; - t.Scommaaccent = 556; - t.Ohungarumlaut = 778; - t.degree = 400; - t.ograve = 500; - t.Ccaron = 722; - t.ugrave = 556; - t.radical = 549; - t.Dcaron = 722; - t.rcommaaccent = 444; - t.Ntilde = 722; - t.otilde = 500; - t.Rcommaaccent = 722; - t.Lcommaaccent = 667; - t.Atilde = 722; - t.Aogonek = 722; - t.Aring = 722; - t.Otilde = 778; - t.zdotaccent = 444; - t.Ecaron = 667; - t.Iogonek = 389; - t.kcommaaccent = 556; - t.minus = 570; - t.Icircumflex = 389; - t.ncaron = 556; - t.tcommaaccent = 333; - t.logicalnot = 570; - t.odieresis = 500; - t.udieresis = 556; - t.notequal = 549; - t.gcommaaccent = 500; - t.eth = 500; - t.zcaron = 444; - t.ncommaaccent = 556; - t.onesuperior = 300; - t.imacron = 278; - t.Euro = 500; - }); - t["Times-BoldItalic"] = (0, _core_utils.getLookupTableFactory)(function (t) { - t.space = 250; - t.exclam = 389; - t.quotedbl = 555; - t.numbersign = 500; - t.dollar = 500; - t.percent = 833; - t.ampersand = 778; - t.quoteright = 333; - t.parenleft = 333; - t.parenright = 333; - t.asterisk = 500; - t.plus = 570; - t.comma = 250; - t.hyphen = 333; - t.period = 250; - t.slash = 278; - t.zero = 500; - t.one = 500; - t.two = 500; - t.three = 500; - t.four = 500; - t.five = 500; - t.six = 500; - t.seven = 500; - t.eight = 500; - t.nine = 500; - t.colon = 333; - t.semicolon = 333; - t.less = 570; - t.equal = 570; - t.greater = 570; - t.question = 500; - t.at = 832; - t.A = 667; - t.B = 667; - t.C = 667; - t.D = 722; - t.E = 667; - t.F = 667; - t.G = 722; - t.H = 778; - t.I = 389; - t.J = 500; - t.K = 667; - t.L = 611; - t.M = 889; - t.N = 722; - t.O = 722; - t.P = 611; - t.Q = 722; - t.R = 667; - t.S = 556; - t.T = 611; - t.U = 722; - t.V = 667; - t.W = 889; - t.X = 667; - t.Y = 611; - t.Z = 611; - t.bracketleft = 333; - t.backslash = 278; - t.bracketright = 333; - t.asciicircum = 570; - t.underscore = 500; - t.quoteleft = 333; - t.a = 500; - t.b = 500; - t.c = 444; - t.d = 500; - t.e = 444; - t.f = 333; - t.g = 500; - t.h = 556; - t.i = 278; - t.j = 278; - t.k = 500; - t.l = 278; - t.m = 778; - t.n = 556; - t.o = 500; - t.p = 500; - t.q = 500; - t.r = 389; - t.s = 389; - t.t = 278; - t.u = 556; - t.v = 444; - t.w = 667; - t.x = 500; - t.y = 444; - t.z = 389; - t.braceleft = 348; - t.bar = 220; - t.braceright = 348; - t.asciitilde = 570; - t.exclamdown = 389; - t.cent = 500; - t.sterling = 500; - t.fraction = 167; - t.yen = 500; - t.florin = 500; - t.section = 500; - t.currency = 500; - t.quotesingle = 278; - t.quotedblleft = 500; - t.guillemotleft = 500; - t.guilsinglleft = 333; - t.guilsinglright = 333; - t.fi = 556; - t.fl = 556; - t.endash = 500; - t.dagger = 500; - t.daggerdbl = 500; - t.periodcentered = 250; - t.paragraph = 500; - t.bullet = 350; - t.quotesinglbase = 333; - t.quotedblbase = 500; - t.quotedblright = 500; - t.guillemotright = 500; - t.ellipsis = 1000; - t.perthousand = 1000; - t.questiondown = 500; - t.grave = 333; - t.acute = 333; - t.circumflex = 333; - t.tilde = 333; - t.macron = 333; - t.breve = 333; - t.dotaccent = 333; - t.dieresis = 333; - t.ring = 333; - t.cedilla = 333; - t.hungarumlaut = 333; - t.ogonek = 333; - t.caron = 333; - t.emdash = 1000; - t.AE = 944; - t.ordfeminine = 266; - t.Lslash = 611; - t.Oslash = 722; - t.OE = 944; - t.ordmasculine = 300; - t.ae = 722; - t.dotlessi = 278; - t.lslash = 278; - t.oslash = 500; - t.oe = 722; - t.germandbls = 500; - t.Idieresis = 389; - t.eacute = 444; - t.abreve = 500; - t.uhungarumlaut = 556; - t.ecaron = 444; - t.Ydieresis = 611; - t.divide = 570; - t.Yacute = 611; - t.Acircumflex = 667; - t.aacute = 500; - t.Ucircumflex = 722; - t.yacute = 444; - t.scommaaccent = 389; - t.ecircumflex = 444; - t.Uring = 722; - t.Udieresis = 722; - t.aogonek = 500; - t.Uacute = 722; - t.uogonek = 556; - t.Edieresis = 667; - t.Dcroat = 722; - t.commaaccent = 250; - t.copyright = 747; - t.Emacron = 667; - t.ccaron = 444; - t.aring = 500; - t.Ncommaaccent = 722; - t.lacute = 278; - t.agrave = 500; - t.Tcommaaccent = 611; - t.Cacute = 667; - t.atilde = 500; - t.Edotaccent = 667; - t.scaron = 389; - t.scedilla = 389; - t.iacute = 278; - t.lozenge = 494; - t.Rcaron = 667; - t.Gcommaaccent = 722; - t.ucircumflex = 556; - t.acircumflex = 500; - t.Amacron = 667; - t.rcaron = 389; - t.ccedilla = 444; - t.Zdotaccent = 611; - t.Thorn = 611; - t.Omacron = 722; - t.Racute = 667; - t.Sacute = 556; - t.dcaron = 608; - t.Umacron = 722; - t.uring = 556; - t.threesuperior = 300; - t.Ograve = 722; - t.Agrave = 667; - t.Abreve = 667; - t.multiply = 570; - t.uacute = 556; - t.Tcaron = 611; - t.partialdiff = 494; - t.ydieresis = 444; - t.Nacute = 722; - t.icircumflex = 278; - t.Ecircumflex = 667; - t.adieresis = 500; - t.edieresis = 444; - t.cacute = 444; - t.nacute = 556; - t.umacron = 556; - t.Ncaron = 722; - t.Iacute = 389; - t.plusminus = 570; - t.brokenbar = 220; - t.registered = 747; - t.Gbreve = 722; - t.Idotaccent = 389; - t.summation = 600; - t.Egrave = 667; - t.racute = 389; - t.omacron = 500; - t.Zacute = 611; - t.Zcaron = 611; - t.greaterequal = 549; - t.Eth = 722; - t.Ccedilla = 667; - t.lcommaaccent = 278; - t.tcaron = 366; - t.eogonek = 444; - t.Uogonek = 722; - t.Aacute = 667; - t.Adieresis = 667; - t.egrave = 444; - t.zacute = 389; - t.iogonek = 278; - t.Oacute = 722; - t.oacute = 500; - t.amacron = 500; - t.sacute = 389; - t.idieresis = 278; - t.Ocircumflex = 722; - t.Ugrave = 722; - t.Delta = 612; - t.thorn = 500; - t.twosuperior = 300; - t.Odieresis = 722; - t.mu = 576; - t.igrave = 278; - t.ohungarumlaut = 500; - t.Eogonek = 667; - t.dcroat = 500; - t.threequarters = 750; - t.Scedilla = 556; - t.lcaron = 382; - t.Kcommaaccent = 667; - t.Lacute = 611; - t.trademark = 1000; - t.edotaccent = 444; - t.Igrave = 389; - t.Imacron = 389; - t.Lcaron = 611; - t.onehalf = 750; - t.lessequal = 549; - t.ocircumflex = 500; - t.ntilde = 556; - t.Uhungarumlaut = 722; - t.Eacute = 667; - t.emacron = 444; - t.gbreve = 500; - t.onequarter = 750; - t.Scaron = 556; - t.Scommaaccent = 556; - t.Ohungarumlaut = 722; - t.degree = 400; - t.ograve = 500; - t.Ccaron = 667; - t.ugrave = 556; - t.radical = 549; - t.Dcaron = 722; - t.rcommaaccent = 389; - t.Ntilde = 722; - t.otilde = 500; - t.Rcommaaccent = 667; - t.Lcommaaccent = 611; - t.Atilde = 667; - t.Aogonek = 667; - t.Aring = 667; - t.Otilde = 722; - t.zdotaccent = 389; - t.Ecaron = 667; - t.Iogonek = 389; - t.kcommaaccent = 500; - t.minus = 606; - t.Icircumflex = 389; - t.ncaron = 556; - t.tcommaaccent = 278; - t.logicalnot = 606; - t.odieresis = 500; - t.udieresis = 556; - t.notequal = 549; - t.gcommaaccent = 500; - t.eth = 500; - t.zcaron = 389; - t.ncommaaccent = 556; - t.onesuperior = 300; - t.imacron = 278; - t.Euro = 500; - }); - t["Times-Italic"] = (0, _core_utils.getLookupTableFactory)(function (t) { - t.space = 250; - t.exclam = 333; - t.quotedbl = 420; - t.numbersign = 500; - t.dollar = 500; - t.percent = 833; - t.ampersand = 778; - t.quoteright = 333; - t.parenleft = 333; - t.parenright = 333; - t.asterisk = 500; - t.plus = 675; - t.comma = 250; - t.hyphen = 333; - t.period = 250; - t.slash = 278; - t.zero = 500; - t.one = 500; - t.two = 500; - t.three = 500; - t.four = 500; - t.five = 500; - t.six = 500; - t.seven = 500; - t.eight = 500; - t.nine = 500; - t.colon = 333; - t.semicolon = 333; - t.less = 675; - t.equal = 675; - t.greater = 675; - t.question = 500; - t.at = 920; - t.A = 611; - t.B = 611; - t.C = 667; - t.D = 722; - t.E = 611; - t.F = 611; - t.G = 722; - t.H = 722; - t.I = 333; - t.J = 444; - t.K = 667; - t.L = 556; - t.M = 833; - t.N = 667; - t.O = 722; - t.P = 611; - t.Q = 722; - t.R = 611; - t.S = 500; - t.T = 556; - t.U = 722; - t.V = 611; - t.W = 833; - t.X = 611; - t.Y = 556; - t.Z = 556; - t.bracketleft = 389; - t.backslash = 278; - t.bracketright = 389; - t.asciicircum = 422; - t.underscore = 500; - t.quoteleft = 333; - t.a = 500; - t.b = 500; - t.c = 444; - t.d = 500; - t.e = 444; - t.f = 278; - t.g = 500; - t.h = 500; - t.i = 278; - t.j = 278; - t.k = 444; - t.l = 278; - t.m = 722; - t.n = 500; - t.o = 500; - t.p = 500; - t.q = 500; - t.r = 389; - t.s = 389; - t.t = 278; - t.u = 500; - t.v = 444; - t.w = 667; - t.x = 444; - t.y = 444; - t.z = 389; - t.braceleft = 400; - t.bar = 275; - t.braceright = 400; - t.asciitilde = 541; - t.exclamdown = 389; - t.cent = 500; - t.sterling = 500; - t.fraction = 167; - t.yen = 500; - t.florin = 500; - t.section = 500; - t.currency = 500; - t.quotesingle = 214; - t.quotedblleft = 556; - t.guillemotleft = 500; - t.guilsinglleft = 333; - t.guilsinglright = 333; - t.fi = 500; - t.fl = 500; - t.endash = 500; - t.dagger = 500; - t.daggerdbl = 500; - t.periodcentered = 250; - t.paragraph = 523; - t.bullet = 350; - t.quotesinglbase = 333; - t.quotedblbase = 556; - t.quotedblright = 556; - t.guillemotright = 500; - t.ellipsis = 889; - t.perthousand = 1000; - t.questiondown = 500; - t.grave = 333; - t.acute = 333; - t.circumflex = 333; - t.tilde = 333; - t.macron = 333; - t.breve = 333; - t.dotaccent = 333; - t.dieresis = 333; - t.ring = 333; - t.cedilla = 333; - t.hungarumlaut = 333; - t.ogonek = 333; - t.caron = 333; - t.emdash = 889; - t.AE = 889; - t.ordfeminine = 276; - t.Lslash = 556; - t.Oslash = 722; - t.OE = 944; - t.ordmasculine = 310; - t.ae = 667; - t.dotlessi = 278; - t.lslash = 278; - t.oslash = 500; - t.oe = 667; - t.germandbls = 500; - t.Idieresis = 333; - t.eacute = 444; - t.abreve = 500; - t.uhungarumlaut = 500; - t.ecaron = 444; - t.Ydieresis = 556; - t.divide = 675; - t.Yacute = 556; - t.Acircumflex = 611; - t.aacute = 500; - t.Ucircumflex = 722; - t.yacute = 444; - t.scommaaccent = 389; - t.ecircumflex = 444; - t.Uring = 722; - t.Udieresis = 722; - t.aogonek = 500; - t.Uacute = 722; - t.uogonek = 500; - t.Edieresis = 611; - t.Dcroat = 722; - t.commaaccent = 250; - t.copyright = 760; - t.Emacron = 611; - t.ccaron = 444; - t.aring = 500; - t.Ncommaaccent = 667; - t.lacute = 278; - t.agrave = 500; - t.Tcommaaccent = 556; - t.Cacute = 667; - t.atilde = 500; - t.Edotaccent = 611; - t.scaron = 389; - t.scedilla = 389; - t.iacute = 278; - t.lozenge = 471; - t.Rcaron = 611; - t.Gcommaaccent = 722; - t.ucircumflex = 500; - t.acircumflex = 500; - t.Amacron = 611; - t.rcaron = 389; - t.ccedilla = 444; - t.Zdotaccent = 556; - t.Thorn = 611; - t.Omacron = 722; - t.Racute = 611; - t.Sacute = 500; - t.dcaron = 544; - t.Umacron = 722; - t.uring = 500; - t.threesuperior = 300; - t.Ograve = 722; - t.Agrave = 611; - t.Abreve = 611; - t.multiply = 675; - t.uacute = 500; - t.Tcaron = 556; - t.partialdiff = 476; - t.ydieresis = 444; - t.Nacute = 667; - t.icircumflex = 278; - t.Ecircumflex = 611; - t.adieresis = 500; - t.edieresis = 444; - t.cacute = 444; - t.nacute = 500; - t.umacron = 500; - t.Ncaron = 667; - t.Iacute = 333; - t.plusminus = 675; - t.brokenbar = 275; - t.registered = 760; - t.Gbreve = 722; - t.Idotaccent = 333; - t.summation = 600; - t.Egrave = 611; - t.racute = 389; - t.omacron = 500; - t.Zacute = 556; - t.Zcaron = 556; - t.greaterequal = 549; - t.Eth = 722; - t.Ccedilla = 667; - t.lcommaaccent = 278; - t.tcaron = 300; - t.eogonek = 444; - t.Uogonek = 722; - t.Aacute = 611; - t.Adieresis = 611; - t.egrave = 444; - t.zacute = 389; - t.iogonek = 278; - t.Oacute = 722; - t.oacute = 500; - t.amacron = 500; - t.sacute = 389; - t.idieresis = 278; - t.Ocircumflex = 722; - t.Ugrave = 722; - t.Delta = 612; - t.thorn = 500; - t.twosuperior = 300; - t.Odieresis = 722; - t.mu = 500; - t.igrave = 278; - t.ohungarumlaut = 500; - t.Eogonek = 611; - t.dcroat = 500; - t.threequarters = 750; - t.Scedilla = 500; - t.lcaron = 300; - t.Kcommaaccent = 667; - t.Lacute = 556; - t.trademark = 980; - t.edotaccent = 444; - t.Igrave = 333; - t.Imacron = 333; - t.Lcaron = 611; - t.onehalf = 750; - t.lessequal = 549; - t.ocircumflex = 500; - t.ntilde = 500; - t.Uhungarumlaut = 722; - t.Eacute = 611; - t.emacron = 444; - t.gbreve = 500; - t.onequarter = 750; - t.Scaron = 500; - t.Scommaaccent = 500; - t.Ohungarumlaut = 722; - t.degree = 400; - t.ograve = 500; - t.Ccaron = 667; - t.ugrave = 500; - t.radical = 453; - t.Dcaron = 722; - t.rcommaaccent = 389; - t.Ntilde = 667; - t.otilde = 500; - t.Rcommaaccent = 611; - t.Lcommaaccent = 556; - t.Atilde = 611; - t.Aogonek = 611; - t.Aring = 611; - t.Otilde = 722; - t.zdotaccent = 389; - t.Ecaron = 611; - t.Iogonek = 333; - t.kcommaaccent = 444; - t.minus = 675; - t.Icircumflex = 333; - t.ncaron = 500; - t.tcommaaccent = 278; - t.logicalnot = 675; - t.odieresis = 500; - t.udieresis = 500; - t.notequal = 549; - t.gcommaaccent = 500; - t.eth = 500; - t.zcaron = 389; - t.ncommaaccent = 500; - t.onesuperior = 300; - t.imacron = 278; - t.Euro = 500; - }); - t.ZapfDingbats = (0, _core_utils.getLookupTableFactory)(function (t) { - t.space = 278; - t.a1 = 974; - t.a2 = 961; - t.a202 = 974; - t.a3 = 980; - t.a4 = 719; - t.a5 = 789; - t.a119 = 790; - t.a118 = 791; - t.a117 = 690; - t.a11 = 960; - t.a12 = 939; - t.a13 = 549; - t.a14 = 855; - t.a15 = 911; - t.a16 = 933; - t.a105 = 911; - t.a17 = 945; - t.a18 = 974; - t.a19 = 755; - t.a20 = 846; - t.a21 = 762; - t.a22 = 761; - t.a23 = 571; - t.a24 = 677; - t.a25 = 763; - t.a26 = 760; - t.a27 = 759; - t.a28 = 754; - t.a6 = 494; - t.a7 = 552; - t.a8 = 537; - t.a9 = 577; - t.a10 = 692; - t.a29 = 786; - t.a30 = 788; - t.a31 = 788; - t.a32 = 790; - t.a33 = 793; - t.a34 = 794; - t.a35 = 816; - t.a36 = 823; - t.a37 = 789; - t.a38 = 841; - t.a39 = 823; - t.a40 = 833; - t.a41 = 816; - t.a42 = 831; - t.a43 = 923; - t.a44 = 744; - t.a45 = 723; - t.a46 = 749; - t.a47 = 790; - t.a48 = 792; - t.a49 = 695; - t.a50 = 776; - t.a51 = 768; - t.a52 = 792; - t.a53 = 759; - t.a54 = 707; - t.a55 = 708; - t.a56 = 682; - t.a57 = 701; - t.a58 = 826; - t.a59 = 815; - t.a60 = 789; - t.a61 = 789; - t.a62 = 707; - t.a63 = 687; - t.a64 = 696; - t.a65 = 689; - t.a66 = 786; - t.a67 = 787; - t.a68 = 713; - t.a69 = 791; - t.a70 = 785; - t.a71 = 791; - t.a72 = 873; - t.a73 = 761; - t.a74 = 762; - t.a203 = 762; - t.a75 = 759; - t.a204 = 759; - t.a76 = 892; - t.a77 = 892; - t.a78 = 788; - t.a79 = 784; - t.a81 = 438; - t.a82 = 138; - t.a83 = 277; - t.a84 = 415; - t.a97 = 392; - t.a98 = 392; - t.a99 = 668; - t.a100 = 668; - t.a89 = 390; - t.a90 = 390; - t.a93 = 317; - t.a94 = 317; - t.a91 = 276; - t.a92 = 276; - t.a205 = 509; - t.a85 = 509; - t.a206 = 410; - t.a86 = 410; - t.a87 = 234; - t.a88 = 234; - t.a95 = 334; - t.a96 = 334; - t.a101 = 732; - t.a102 = 544; - t.a103 = 544; - t.a104 = 910; - t.a106 = 667; - t.a107 = 760; - t.a108 = 760; - t.a112 = 776; - t.a111 = 595; - t.a110 = 694; - t.a109 = 626; - t.a120 = 788; - t.a121 = 788; - t.a122 = 788; - t.a123 = 788; - t.a124 = 788; - t.a125 = 788; - t.a126 = 788; - t.a127 = 788; - t.a128 = 788; - t.a129 = 788; - t.a130 = 788; - t.a131 = 788; - t.a132 = 788; - t.a133 = 788; - t.a134 = 788; - t.a135 = 788; - t.a136 = 788; - t.a137 = 788; - t.a138 = 788; - t.a139 = 788; - t.a140 = 788; - t.a141 = 788; - t.a142 = 788; - t.a143 = 788; - t.a144 = 788; - t.a145 = 788; - t.a146 = 788; - t.a147 = 788; - t.a148 = 788; - t.a149 = 788; - t.a150 = 788; - t.a151 = 788; - t.a152 = 788; - t.a153 = 788; - t.a154 = 788; - t.a155 = 788; - t.a156 = 788; - t.a157 = 788; - t.a158 = 788; - t.a159 = 788; - t.a160 = 894; - t.a161 = 838; - t.a163 = 1016; - t.a164 = 458; - t.a196 = 748; - t.a165 = 924; - t.a192 = 748; - t.a166 = 918; - t.a167 = 927; - t.a168 = 928; - t.a169 = 928; - t.a170 = 834; - t.a171 = 873; - t.a172 = 828; - t.a173 = 924; - t.a162 = 924; - t.a174 = 917; - t.a175 = 930; - t.a176 = 931; - t.a177 = 463; - t.a178 = 883; - t.a179 = 836; - t.a193 = 836; - t.a180 = 867; - t.a199 = 867; - t.a181 = 696; - t.a200 = 696; - t.a182 = 874; - t.a201 = 874; - t.a183 = 760; - t.a184 = 946; - t.a197 = 771; - t.a185 = 865; - t.a194 = 771; - t.a198 = 888; - t.a186 = 967; - t.a195 = 888; - t.a187 = 831; - t.a188 = 873; - t.a189 = 927; - t.a190 = 970; - t.a191 = 918; - }); -}); -exports.getMetrics = getMetrics; - -/***/ }), -/* 61 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.MurmurHash3_64 = void 0; - -var _util = __w_pdfjs_require__(2); - -const SEED = 0xc3d2e1f0; -const MASK_HIGH = 0xffff0000; -const MASK_LOW = 0xffff; - -class MurmurHash3_64 { - constructor(seed) { - this.h1 = seed ? seed & 0xffffffff : SEED; - this.h2 = seed ? seed & 0xffffffff : SEED; - } - - update(input) { - let data, length; - - if ((0, _util.isString)(input)) { - data = new Uint8Array(input.length * 2); - length = 0; - - for (let i = 0, ii = input.length; i < ii; i++) { - const code = input.charCodeAt(i); - - if (code <= 0xff) { - data[length++] = code; - } else { - data[length++] = code >>> 8; - data[length++] = code & 0xff; - } - } - } else if ((0, _util.isArrayBuffer)(input)) { - data = input.slice(); - length = data.byteLength; - } else { - throw new Error("Wrong data format in MurmurHash3_64_update. " + "Input must be a string or array."); - } - - const blockCounts = length >> 2; - const tailLength = length - blockCounts * 4; - const dataUint32 = new Uint32Array(data.buffer, 0, blockCounts); - let k1 = 0, - k2 = 0; - let h1 = this.h1, - h2 = this.h2; - const C1 = 0xcc9e2d51, - C2 = 0x1b873593; - const C1_LOW = C1 & MASK_LOW, - C2_LOW = C2 & MASK_LOW; - - for (let i = 0; i < blockCounts; i++) { - if (i & 1) { - k1 = dataUint32[i]; - k1 = k1 * C1 & MASK_HIGH | k1 * C1_LOW & MASK_LOW; - k1 = k1 << 15 | k1 >>> 17; - k1 = k1 * C2 & MASK_HIGH | k1 * C2_LOW & MASK_LOW; - h1 ^= k1; - h1 = h1 << 13 | h1 >>> 19; - h1 = h1 * 5 + 0xe6546b64; - } else { - k2 = dataUint32[i]; - k2 = k2 * C1 & MASK_HIGH | k2 * C1_LOW & MASK_LOW; - k2 = k2 << 15 | k2 >>> 17; - k2 = k2 * C2 & MASK_HIGH | k2 * C2_LOW & MASK_LOW; - h2 ^= k2; - h2 = h2 << 13 | h2 >>> 19; - h2 = h2 * 5 + 0xe6546b64; - } - } - - k1 = 0; - - switch (tailLength) { - case 3: - k1 ^= data[blockCounts * 4 + 2] << 16; - - case 2: - k1 ^= data[blockCounts * 4 + 1] << 8; - - case 1: - k1 ^= data[blockCounts * 4]; - k1 = k1 * C1 & MASK_HIGH | k1 * C1_LOW & MASK_LOW; - k1 = k1 << 15 | k1 >>> 17; - k1 = k1 * C2 & MASK_HIGH | k1 * C2_LOW & MASK_LOW; - - if (blockCounts & 1) { - h1 ^= k1; - } else { - h2 ^= k1; - } - - } - - this.h1 = h1; - this.h2 = h2; - } - - hexdigest() { - let h1 = this.h1, - h2 = this.h2; - h1 ^= h2 >>> 1; - h1 = h1 * 0xed558ccd & MASK_HIGH | h1 * 0x8ccd & MASK_LOW; - h2 = h2 * 0xff51afd7 & MASK_HIGH | ((h2 << 16 | h1 >>> 16) * 0xafd7ed55 & MASK_HIGH) >>> 16; - h1 ^= h2 >>> 1; - h1 = h1 * 0x1a85ec53 & MASK_HIGH | h1 * 0xec53 & MASK_LOW; - h2 = h2 * 0xc4ceb9fe & MASK_HIGH | ((h2 << 16 | h1 >>> 16) * 0xb9fe1a85 & MASK_HIGH) >>> 16; - h1 ^= h2 >>> 1; - const hex1 = (h1 >>> 0).toString(16), - hex2 = (h2 >>> 0).toString(16); - return hex1.padStart(8, "0") + hex2.padStart(8, "0"); - } - -} - -exports.MurmurHash3_64 = MurmurHash3_64; - -/***/ }), -/* 62 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.OperatorList = void 0; - -var _util = __w_pdfjs_require__(2); - -function addState(parentState, pattern, checkFn, iterateFn, processFn) { - let state = parentState; - - for (let i = 0, ii = pattern.length - 1; i < ii; i++) { - const item = pattern[i]; - state = state[item] || (state[item] = []); - } - - state[pattern[pattern.length - 1]] = { - checkFn, - iterateFn, - processFn - }; -} - -function handlePaintSolidColorImageMask(iFirstSave, count, fnArray, argsArray) { - const iFirstPIMXO = iFirstSave + 2; - let i; - - for (i = 0; i < count; i++) { - const arg = argsArray[iFirstPIMXO + 4 * i]; - const imageMask = arg.length === 1 && arg[0]; - - if (imageMask && imageMask.width === 1 && imageMask.height === 1 && (!imageMask.data.length || imageMask.data.length === 1 && imageMask.data[0] === 0)) { - fnArray[iFirstPIMXO + 4 * i] = _util.OPS.paintSolidColorImageMask; - continue; - } - - break; - } - - return count - i; -} - -const InitialState = []; -addState(InitialState, [_util.OPS.save, _util.OPS.transform, _util.OPS.paintInlineImageXObject, _util.OPS.restore], null, function iterateInlineImageGroup(context, i) { - const fnArray = context.fnArray; - const iFirstSave = context.iCurr - 3; - const pos = (i - iFirstSave) % 4; - - switch (pos) { - case 0: - return fnArray[i] === _util.OPS.save; - - case 1: - return fnArray[i] === _util.OPS.transform; - - case 2: - return fnArray[i] === _util.OPS.paintInlineImageXObject; - - case 3: - return fnArray[i] === _util.OPS.restore; - } - - throw new Error(`iterateInlineImageGroup - invalid pos: ${pos}`); -}, function foundInlineImageGroup(context, i) { - const MIN_IMAGES_IN_INLINE_IMAGES_BLOCK = 10; - const MAX_IMAGES_IN_INLINE_IMAGES_BLOCK = 200; - const MAX_WIDTH = 1000; - const IMAGE_PADDING = 1; - const fnArray = context.fnArray, - argsArray = context.argsArray; - const curr = context.iCurr; - const iFirstSave = curr - 3; - const iFirstTransform = curr - 2; - const iFirstPIIXO = curr - 1; - const count = Math.min(Math.floor((i - iFirstSave) / 4), MAX_IMAGES_IN_INLINE_IMAGES_BLOCK); - - if (count < MIN_IMAGES_IN_INLINE_IMAGES_BLOCK) { - return i - (i - iFirstSave) % 4; - } - - let maxX = 0; - const map = []; - let maxLineHeight = 0; - let currentX = IMAGE_PADDING, - currentY = IMAGE_PADDING; - - for (let q = 0; q < count; q++) { - const transform = argsArray[iFirstTransform + (q << 2)]; - const img = argsArray[iFirstPIIXO + (q << 2)][0]; - - if (currentX + img.width > MAX_WIDTH) { - maxX = Math.max(maxX, currentX); - currentY += maxLineHeight + 2 * IMAGE_PADDING; - currentX = 0; - maxLineHeight = 0; - } - - map.push({ - transform, - x: currentX, - y: currentY, - w: img.width, - h: img.height - }); - currentX += img.width + 2 * IMAGE_PADDING; - maxLineHeight = Math.max(maxLineHeight, img.height); - } - - const imgWidth = Math.max(maxX, currentX) + IMAGE_PADDING; - const imgHeight = currentY + maxLineHeight + IMAGE_PADDING; - const imgData = new Uint8ClampedArray(imgWidth * imgHeight * 4); - const imgRowSize = imgWidth << 2; - - for (let q = 0; q < count; q++) { - const data = argsArray[iFirstPIIXO + (q << 2)][0].data; - const rowSize = map[q].w << 2; - let dataOffset = 0; - let offset = map[q].x + map[q].y * imgWidth << 2; - imgData.set(data.subarray(0, rowSize), offset - imgRowSize); - - for (let 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; - } - } - - fnArray.splice(iFirstSave, count * 4, _util.OPS.paintInlineImageXObjectGroup); - argsArray.splice(iFirstSave, count * 4, [{ - width: imgWidth, - height: imgHeight, - kind: _util.ImageKind.RGBA_32BPP, - data: imgData - }, map]); - return iFirstSave + 1; -}); -addState(InitialState, [_util.OPS.save, _util.OPS.transform, _util.OPS.paintImageMaskXObject, _util.OPS.restore], null, function iterateImageMaskGroup(context, i) { - const fnArray = context.fnArray; - const iFirstSave = context.iCurr - 3; - const pos = (i - iFirstSave) % 4; - - switch (pos) { - case 0: - return fnArray[i] === _util.OPS.save; - - case 1: - return fnArray[i] === _util.OPS.transform; - - case 2: - return fnArray[i] === _util.OPS.paintImageMaskXObject; - - case 3: - return fnArray[i] === _util.OPS.restore; - } - - throw new Error(`iterateImageMaskGroup - invalid pos: ${pos}`); -}, function foundImageMaskGroup(context, i) { - const MIN_IMAGES_IN_MASKS_BLOCK = 10; - const MAX_IMAGES_IN_MASKS_BLOCK = 100; - const MAX_SAME_IMAGES_IN_MASKS_BLOCK = 1000; - const fnArray = context.fnArray, - argsArray = context.argsArray; - const curr = context.iCurr; - const iFirstSave = curr - 3; - const iFirstTransform = curr - 2; - const iFirstPIMXO = curr - 1; - let count = Math.floor((i - iFirstSave) / 4); - count = handlePaintSolidColorImageMask(iFirstSave, count, fnArray, argsArray); - - if (count < MIN_IMAGES_IN_MASKS_BLOCK) { - return i - (i - iFirstSave) % 4; - } - - let isSameImage = false; - let iTransform, transformArgs; - const firstPIMXOArg0 = argsArray[iFirstPIMXO][0]; - const firstTransformArg0 = argsArray[iFirstTransform][0], - firstTransformArg1 = argsArray[iFirstTransform][1], - firstTransformArg2 = argsArray[iFirstTransform][2], - firstTransformArg3 = argsArray[iFirstTransform][3]; - - if (firstTransformArg1 === firstTransformArg2) { - isSameImage = true; - iTransform = iFirstTransform + 4; - let iPIMXO = iFirstPIMXO + 4; - - for (let q = 1; q < count; q++, iTransform += 4, iPIMXO += 4) { - transformArgs = argsArray[iTransform]; - - if (argsArray[iPIMXO][0] !== firstPIMXOArg0 || transformArgs[0] !== firstTransformArg0 || transformArgs[1] !== firstTransformArg1 || transformArgs[2] !== firstTransformArg2 || transformArgs[3] !== firstTransformArg3) { - if (q < MIN_IMAGES_IN_MASKS_BLOCK) { - isSameImage = false; - } else { - count = q; - } - - break; - } - } - } - - if (isSameImage) { - count = Math.min(count, MAX_SAME_IMAGES_IN_MASKS_BLOCK); - const positions = new Float32Array(count * 2); - iTransform = iFirstTransform; - - for (let q = 0; q < count; q++, iTransform += 4) { - transformArgs = argsArray[iTransform]; - positions[q << 1] = transformArgs[4]; - positions[(q << 1) + 1] = transformArgs[5]; - } - - fnArray.splice(iFirstSave, count * 4, _util.OPS.paintImageMaskXObjectRepeat); - argsArray.splice(iFirstSave, count * 4, [firstPIMXOArg0, firstTransformArg0, firstTransformArg1, firstTransformArg2, firstTransformArg3, positions]); - } else { - count = Math.min(count, MAX_IMAGES_IN_MASKS_BLOCK); - const images = []; - - for (let q = 0; q < count; q++) { - transformArgs = argsArray[iFirstTransform + (q << 2)]; - const maskParams = argsArray[iFirstPIMXO + (q << 2)][0]; - images.push({ - data: maskParams.data, - width: maskParams.width, - height: maskParams.height, - transform: transformArgs - }); - } - - fnArray.splice(iFirstSave, count * 4, _util.OPS.paintImageMaskXObjectGroup); - argsArray.splice(iFirstSave, count * 4, [images]); - } - - return iFirstSave + 1; -}); -addState(InitialState, [_util.OPS.save, _util.OPS.transform, _util.OPS.paintImageXObject, _util.OPS.restore], function (context) { - const argsArray = context.argsArray; - const iFirstTransform = context.iCurr - 2; - return argsArray[iFirstTransform][1] === 0 && argsArray[iFirstTransform][2] === 0; -}, function iterateImageGroup(context, i) { - const fnArray = context.fnArray, - argsArray = context.argsArray; - const iFirstSave = context.iCurr - 3; - const pos = (i - iFirstSave) % 4; - - switch (pos) { - case 0: - return fnArray[i] === _util.OPS.save; - - case 1: - if (fnArray[i] !== _util.OPS.transform) { - return false; - } - - const iFirstTransform = context.iCurr - 2; - const firstTransformArg0 = argsArray[iFirstTransform][0]; - const firstTransformArg3 = argsArray[iFirstTransform][3]; - - if (argsArray[i][0] !== firstTransformArg0 || argsArray[i][1] !== 0 || argsArray[i][2] !== 0 || argsArray[i][3] !== firstTransformArg3) { - return false; - } - - return true; - - case 2: - if (fnArray[i] !== _util.OPS.paintImageXObject) { - return false; - } - - const iFirstPIXO = context.iCurr - 1; - const firstPIXOArg0 = argsArray[iFirstPIXO][0]; - - if (argsArray[i][0] !== firstPIXOArg0) { - return false; - } - - return true; - - case 3: - return fnArray[i] === _util.OPS.restore; - } - - throw new Error(`iterateImageGroup - invalid pos: ${pos}`); -}, function (context, i) { - const MIN_IMAGES_IN_BLOCK = 3; - const MAX_IMAGES_IN_BLOCK = 1000; - const fnArray = context.fnArray, - argsArray = context.argsArray; - const curr = context.iCurr; - const iFirstSave = curr - 3; - const iFirstTransform = curr - 2; - const iFirstPIXO = curr - 1; - const firstPIXOArg0 = argsArray[iFirstPIXO][0]; - const firstTransformArg0 = argsArray[iFirstTransform][0]; - const firstTransformArg3 = argsArray[iFirstTransform][3]; - const count = Math.min(Math.floor((i - iFirstSave) / 4), MAX_IMAGES_IN_BLOCK); - - if (count < MIN_IMAGES_IN_BLOCK) { - return i - (i - iFirstSave) % 4; - } - - const positions = new Float32Array(count * 2); - let iTransform = iFirstTransform; - - for (let q = 0; q < count; q++, iTransform += 4) { - const transformArgs = argsArray[iTransform]; - positions[q << 1] = transformArgs[4]; - positions[(q << 1) + 1] = transformArgs[5]; - } - - const args = [firstPIXOArg0, firstTransformArg0, firstTransformArg3, positions]; - fnArray.splice(iFirstSave, count * 4, _util.OPS.paintImageXObjectRepeat); - argsArray.splice(iFirstSave, count * 4, args); - return iFirstSave + 1; -}); -addState(InitialState, [_util.OPS.beginText, _util.OPS.setFont, _util.OPS.setTextMatrix, _util.OPS.showText, _util.OPS.endText], null, function iterateShowTextGroup(context, i) { - const fnArray = context.fnArray, - argsArray = context.argsArray; - const iFirstSave = context.iCurr - 4; - const pos = (i - iFirstSave) % 5; - - switch (pos) { - case 0: - return fnArray[i] === _util.OPS.beginText; - - case 1: - return fnArray[i] === _util.OPS.setFont; - - case 2: - return fnArray[i] === _util.OPS.setTextMatrix; - - case 3: - if (fnArray[i] !== _util.OPS.showText) { - return false; - } - - const iFirstSetFont = context.iCurr - 3; - const firstSetFontArg0 = argsArray[iFirstSetFont][0]; - const firstSetFontArg1 = argsArray[iFirstSetFont][1]; - - if (argsArray[i][0] !== firstSetFontArg0 || argsArray[i][1] !== firstSetFontArg1) { - return false; - } - - return true; - - case 4: - return fnArray[i] === _util.OPS.endText; - } - - throw new Error(`iterateShowTextGroup - invalid pos: ${pos}`); -}, function (context, i) { - const MIN_CHARS_IN_BLOCK = 3; - const MAX_CHARS_IN_BLOCK = 1000; - const fnArray = context.fnArray, - argsArray = context.argsArray; - const curr = context.iCurr; - const iFirstBeginText = curr - 4; - const iFirstSetFont = curr - 3; - const iFirstSetTextMatrix = curr - 2; - const iFirstShowText = curr - 1; - const iFirstEndText = curr; - const firstSetFontArg0 = argsArray[iFirstSetFont][0]; - const firstSetFontArg1 = argsArray[iFirstSetFont][1]; - let count = Math.min(Math.floor((i - iFirstBeginText) / 5), MAX_CHARS_IN_BLOCK); - - if (count < MIN_CHARS_IN_BLOCK) { - return i - (i - iFirstBeginText) % 5; - } - - let iFirst = iFirstBeginText; - - if (iFirstBeginText >= 4 && fnArray[iFirstBeginText - 4] === fnArray[iFirstSetFont] && fnArray[iFirstBeginText - 3] === fnArray[iFirstSetTextMatrix] && fnArray[iFirstBeginText - 2] === fnArray[iFirstShowText] && fnArray[iFirstBeginText - 1] === fnArray[iFirstEndText] && argsArray[iFirstBeginText - 4][0] === firstSetFontArg0 && argsArray[iFirstBeginText - 4][1] === firstSetFontArg1) { - count++; - iFirst -= 5; - } - - let iEndText = iFirst + 4; - - for (let q = 1; q < count; q++) { - fnArray.splice(iEndText, 3); - argsArray.splice(iEndText, 3); - iEndText += 2; - } - - return iEndText + 1; -}); - -class NullOptimizer { - constructor(queue) { - this.queue = queue; - } - - _optimize() {} - - push(fn, args) { - this.queue.fnArray.push(fn); - this.queue.argsArray.push(args); - - this._optimize(); - } - - flush() {} - - reset() {} - -} - -class QueueOptimizer extends NullOptimizer { - constructor(queue) { - super(queue); - this.state = null; - this.context = { - iCurr: 0, - fnArray: queue.fnArray, - argsArray: queue.argsArray - }; - this.match = null; - this.lastProcessed = 0; - } - - _optimize() { - const fnArray = this.queue.fnArray; - let i = this.lastProcessed, - ii = fnArray.length; - let state = this.state; - let match = this.match; - - if (!state && !match && i + 1 === ii && !InitialState[fnArray[i]]) { - this.lastProcessed = ii; - return; - } - - const context = this.context; - - while (i < ii) { - if (match) { - const iterate = (0, match.iterateFn)(context, i); - - if (iterate) { - i++; - continue; - } - - i = (0, match.processFn)(context, i + 1); - ii = fnArray.length; - match = null; - state = null; - - if (i >= ii) { - break; - } - } - - state = (state || InitialState)[fnArray[i]]; - - if (!state || Array.isArray(state)) { - i++; - continue; - } - - context.iCurr = i; - i++; - - if (state.checkFn && !(0, state.checkFn)(context)) { - state = null; - continue; - } - - match = state; - state = null; - } - - this.state = state; - this.match = match; - this.lastProcessed = i; - } - - flush() { - while (this.match) { - const length = this.queue.fnArray.length; - this.lastProcessed = (0, this.match.processFn)(this.context, length); - this.match = null; - this.state = null; - - this._optimize(); - } - } - - reset() { - this.state = null; - this.match = null; - this.lastProcessed = 0; - } - -} - -class OperatorList { - static get CHUNK_SIZE() { - return (0, _util.shadow)(this, "CHUNK_SIZE", 1000); - } - - static get CHUNK_SIZE_ABOUT() { - return (0, _util.shadow)(this, "CHUNK_SIZE_ABOUT", this.CHUNK_SIZE - 5); - } - - constructor(intent = 0, streamSink) { - this._streamSink = streamSink; - this.fnArray = []; - this.argsArray = []; - - if (streamSink && !(intent & _util.RenderingIntentFlag.OPLIST)) { - this.optimizer = new QueueOptimizer(this); - } else { - this.optimizer = new NullOptimizer(this); - } - - this.dependencies = new Set(); - this._totalLength = 0; - this.weight = 0; - this._resolved = streamSink ? null : Promise.resolve(); - } - - get length() { - return this.argsArray.length; - } - - get ready() { - return this._resolved || this._streamSink.ready; - } - - get totalLength() { - return this._totalLength + this.length; - } - - addOp(fn, args) { - this.optimizer.push(fn, args); - this.weight++; - - if (this._streamSink) { - if (this.weight >= OperatorList.CHUNK_SIZE) { - this.flush(); - } else if (this.weight >= OperatorList.CHUNK_SIZE_ABOUT && (fn === _util.OPS.restore || fn === _util.OPS.endText)) { - this.flush(); - } - } - } - - addDependency(dependency) { - if (this.dependencies.has(dependency)) { - return; - } - - this.dependencies.add(dependency); - this.addOp(_util.OPS.dependency, [dependency]); - } - - addDependencies(dependencies) { - for (const dependency of dependencies) { - this.addDependency(dependency); - } - } - - addOpList(opList) { - if (!(opList instanceof OperatorList)) { - (0, _util.warn)('addOpList - ignoring invalid "opList" parameter.'); - return; - } - - for (const dependency of opList.dependencies) { - this.dependencies.add(dependency); - } - - for (let i = 0, ii = opList.length; i < ii; i++) { - this.addOp(opList.fnArray[i], opList.argsArray[i]); - } - } - - getIR() { - return { - fnArray: this.fnArray, - argsArray: this.argsArray, - length: this.length - }; - } - - get _transfers() { - const transfers = []; - const { - fnArray, - argsArray, - length - } = this; - - for (let i = 0; i < length; i++) { - switch (fnArray[i]) { - case _util.OPS.paintInlineImageXObject: - case _util.OPS.paintInlineImageXObjectGroup: - case _util.OPS.paintImageMaskXObject: - const arg = argsArray[i][0]; - ; - - if (!arg.cached) { - transfers.push(arg.data.buffer); - } - - break; - } - } - - return transfers; - } - - flush(lastChunk = false) { - this.optimizer.flush(); - const length = this.length; - this._totalLength += length; - - this._streamSink.enqueue({ - fnArray: this.fnArray, - argsArray: this.argsArray, - lastChunk, - length - }, 1, this._transfers); - - this.dependencies.clear(); - this.fnArray.length = 0; - this.argsArray.length = 0; - this.weight = 0; - this.optimizer.reset(); - } - -} - -exports.OperatorList = OperatorList; - -/***/ }), -/* 63 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.PDFImage = void 0; - -var _util = __w_pdfjs_require__(2); - -var _primitives = __w_pdfjs_require__(5); - -var _colorspace = __w_pdfjs_require__(24); - -var _decode_stream = __w_pdfjs_require__(29); - -var _jpeg_stream = __w_pdfjs_require__(37); - -var _jpx = __w_pdfjs_require__(40); - -function decodeAndClamp(value, addend, coefficient, max) { - value = addend + value * coefficient; - - if (value < 0) { - value = 0; - } else if (value > max) { - value = max; - } - - return value; -} - -function resizeImageMask(src, bpc, w1, h1, w2, h2) { - const length = w2 * h2; - let dest; - - if (bpc <= 8) { - dest = new Uint8Array(length); - } else if (bpc <= 16) { - dest = new Uint16Array(length); - } else { - dest = new Uint32Array(length); - } - - const xRatio = w1 / w2; - const yRatio = h1 / h2; - let i, - j, - py, - newIndex = 0, - oldIndex; - const xScaled = new Uint16Array(w2); - const w1Scanline = w1; - - for (i = 0; i < w2; i++) { - xScaled[i] = Math.floor(i * xRatio); - } - - for (i = 0; i < h2; i++) { - py = Math.floor(i * yRatio) * w1Scanline; - - for (j = 0; j < w2; j++) { - oldIndex = py + xScaled[j]; - dest[newIndex++] = src[oldIndex]; - } - } - - return dest; -} - -class PDFImage { - constructor({ - xref, - res, - image, - isInline = false, - smask = null, - mask = null, - isMask = false, - pdfFunctionFactory, - localColorSpaceCache - }) { - this.image = image; - const dict = image.dict; - const filter = dict.get("F", "Filter"); - - if ((0, _primitives.isName)(filter)) { - switch (filter.name) { - case "JPXDecode": - const jpxImage = new _jpx.JpxImage(); - jpxImage.parseImageProperties(image.stream); - image.stream.reset(); - image.width = jpxImage.width; - image.height = jpxImage.height; - image.bitsPerComponent = jpxImage.bitsPerComponent; - image.numComps = jpxImage.componentsCount; - break; - - case "JBIG2Decode": - image.bitsPerComponent = 1; - image.numComps = 1; - break; - } - } - - let width = dict.get("W", "Width"); - let height = dict.get("H", "Height"); - - if (Number.isInteger(image.width) && image.width > 0 && Number.isInteger(image.height) && image.height > 0 && (image.width !== width || image.height !== height)) { - (0, _util.warn)("PDFImage - using the Width/Height of the image data, " + "rather than the image dictionary."); - width = image.width; - height = image.height; - } - - if (width < 1 || height < 1) { - throw new _util.FormatError(`Invalid image width: ${width} or height: ${height}`); - } - - this.width = width; - this.height = height; - this.interpolate = dict.get("I", "Interpolate"); - this.imageMask = dict.get("IM", "ImageMask") || false; - this.matte = dict.get("Matte") || false; - let bitsPerComponent = image.bitsPerComponent; - - if (!bitsPerComponent) { - bitsPerComponent = dict.get("BPC", "BitsPerComponent"); - - if (!bitsPerComponent) { - if (this.imageMask) { - bitsPerComponent = 1; - } else { - throw new _util.FormatError(`Bits per component missing in image: ${this.imageMask}`); - } - } - } - - this.bpc = bitsPerComponent; - - if (!this.imageMask) { - let colorSpace = dict.getRaw("CS") || dict.getRaw("ColorSpace"); - - if (!colorSpace) { - (0, _util.info)("JPX images (which do not require color spaces)"); - - switch (image.numComps) { - case 1: - colorSpace = _primitives.Name.get("DeviceGray"); - break; - - case 3: - colorSpace = _primitives.Name.get("DeviceRGB"); - break; - - case 4: - colorSpace = _primitives.Name.get("DeviceCMYK"); - break; - - default: - throw new Error(`JPX images with ${image.numComps} color components not supported.`); - } - } - - this.colorSpace = _colorspace.ColorSpace.parse({ - cs: colorSpace, - xref, - resources: isInline ? res : null, - pdfFunctionFactory, - localColorSpaceCache - }); - this.numComps = this.colorSpace.numComps; - } - - this.decode = dict.getArray("D", "Decode"); - this.needsDecode = false; - - if (this.decode && (this.colorSpace && !this.colorSpace.isDefaultDecode(this.decode, bitsPerComponent) || isMask && !_colorspace.ColorSpace.isDefaultDecode(this.decode, 1))) { - this.needsDecode = true; - const max = (1 << bitsPerComponent) - 1; - this.decodeCoefficients = []; - this.decodeAddends = []; - const isIndexed = this.colorSpace && this.colorSpace.name === "Indexed"; - - for (let i = 0, j = 0; i < this.decode.length; i += 2, ++j) { - const dmin = this.decode[i]; - const dmax = this.decode[i + 1]; - this.decodeCoefficients[j] = isIndexed ? (dmax - dmin) / max : dmax - dmin; - this.decodeAddends[j] = isIndexed ? dmin : max * dmin; - } - } - - if (smask) { - this.smask = new PDFImage({ - xref, - res, - image: smask, - isInline, - pdfFunctionFactory, - localColorSpaceCache - }); - } else if (mask) { - if ((0, _primitives.isStream)(mask)) { - const maskDict = mask.dict, - imageMask = maskDict.get("IM", "ImageMask"); - - if (!imageMask) { - (0, _util.warn)("Ignoring /Mask in image without /ImageMask."); - } else { - this.mask = new PDFImage({ - xref, - res, - image: mask, - isInline, - isMask: true, - pdfFunctionFactory, - localColorSpaceCache - }); - } - } else { - this.mask = mask; - } - } - } - - static async buildImage({ - xref, - res, - image, - isInline = false, - pdfFunctionFactory, - localColorSpaceCache - }) { - const imageData = image; - let smaskData = null; - let maskData = null; - const smask = image.dict.get("SMask"); - const mask = image.dict.get("Mask"); - - if (smask) { - smaskData = smask; - } else if (mask) { - if ((0, _primitives.isStream)(mask) || Array.isArray(mask)) { - maskData = mask; - } else { - (0, _util.warn)("Unsupported mask format."); - } - } - - return new PDFImage({ - xref, - res, - image: imageData, - isInline, - smask: smaskData, - mask: maskData, - pdfFunctionFactory, - localColorSpaceCache - }); - } - - static createMask({ - imgArray, - width, - height, - imageIsFromDecodeStream, - inverseDecode, - interpolate - }) { - const computedLength = (width + 7 >> 3) * height; - const actualLength = imgArray.byteLength; - const haveFullData = computedLength === actualLength; - let data, i; - - if (imageIsFromDecodeStream && (!inverseDecode || haveFullData)) { - data = imgArray; - } else if (!inverseDecode) { - data = new Uint8ClampedArray(actualLength); - data.set(imgArray); - } else { - data = new Uint8ClampedArray(computedLength); - data.set(imgArray); - - for (i = actualLength; i < computedLength; i++) { - data[i] = 0xff; - } - } - - if (inverseDecode) { - for (i = 0; i < actualLength; i++) { - data[i] ^= 0xff; - } - } - - return { - data, - width, - height, - interpolate - }; - } - - get drawWidth() { - return Math.max(this.width, this.smask && this.smask.width || 0, this.mask && this.mask.width || 0); - } - - get drawHeight() { - return Math.max(this.height, this.smask && this.smask.height || 0, this.mask && this.mask.height || 0); - } - - decodeBuffer(buffer) { - const bpc = this.bpc; - const numComps = this.numComps; - const decodeAddends = this.decodeAddends; - const decodeCoefficients = this.decodeCoefficients; - const max = (1 << bpc) - 1; - let i, ii; - - if (bpc === 1) { - for (i = 0, ii = buffer.length; i < ii; i++) { - buffer[i] = +!buffer[i]; - } - - return; - } - - let index = 0; - - for (i = 0, ii = this.width * this.height; i < ii; i++) { - for (let j = 0; j < numComps; j++) { - buffer[index] = decodeAndClamp(buffer[index], decodeAddends[j], decodeCoefficients[j], max); - index++; - } - } - } - - getComponents(buffer) { - const bpc = this.bpc; - - if (bpc === 8) { - return buffer; - } - - const width = this.width; - const height = this.height; - const numComps = this.numComps; - const length = width * height * numComps; - let bufferPos = 0; - let output; - - if (bpc <= 8) { - output = new Uint8Array(length); - } else if (bpc <= 16) { - output = new Uint16Array(length); - } else { - output = new Uint32Array(length); - } - - const rowComps = width * numComps; - const max = (1 << bpc) - 1; - let i = 0, - ii, - buf; - - if (bpc === 1) { - let mask, loop1End, loop2End; - - for (let j = 0; j < height; j++) { - loop1End = i + (rowComps & ~7); - loop2End = i + rowComps; - - while (i < loop1End) { - buf = buffer[bufferPos++]; - output[i] = buf >> 7 & 1; - output[i + 1] = buf >> 6 & 1; - output[i + 2] = buf >> 5 & 1; - output[i + 3] = buf >> 4 & 1; - output[i + 4] = buf >> 3 & 1; - output[i + 5] = buf >> 2 & 1; - output[i + 6] = buf >> 1 & 1; - output[i + 7] = buf & 1; - i += 8; - } - - if (i < loop2End) { - buf = buffer[bufferPos++]; - mask = 128; - - while (i < loop2End) { - output[i++] = +!!(buf & mask); - mask >>= 1; - } - } - } - } else { - let bits = 0; - buf = 0; - - for (i = 0, ii = length; i < ii; ++i) { - if (i % rowComps === 0) { - buf = 0; - bits = 0; - } - - while (bits < bpc) { - buf = buf << 8 | buffer[bufferPos++]; - bits += 8; - } - - const remainingBits = bits - bpc; - let value = buf >> remainingBits; - - if (value < 0) { - value = 0; - } else if (value > max) { - value = max; - } - - output[i] = value; - buf &= (1 << remainingBits) - 1; - bits = remainingBits; - } - } - - return output; - } - - fillOpacity(rgbaBuf, width, height, actualHeight, image) { - const smask = this.smask; - const mask = this.mask; - let alphaBuf, sw, sh, i, ii, j; - - if (smask) { - sw = smask.width; - sh = smask.height; - alphaBuf = new Uint8ClampedArray(sw * sh); - smask.fillGrayBuffer(alphaBuf); - - if (sw !== width || sh !== height) { - alphaBuf = resizeImageMask(alphaBuf, smask.bpc, sw, sh, width, height); - } - } else if (mask) { - if (mask instanceof PDFImage) { - sw = mask.width; - sh = mask.height; - alphaBuf = new Uint8ClampedArray(sw * sh); - mask.numComps = 1; - mask.fillGrayBuffer(alphaBuf); - - for (i = 0, ii = sw * sh; i < ii; ++i) { - alphaBuf[i] = 255 - alphaBuf[i]; - } - - if (sw !== width || sh !== height) { - alphaBuf = resizeImageMask(alphaBuf, mask.bpc, sw, sh, width, height); - } - } else if (Array.isArray(mask)) { - alphaBuf = new Uint8ClampedArray(width * height); - const numComps = this.numComps; - - for (i = 0, ii = width * height; i < ii; ++i) { - let opacity = 0; - const imageOffset = i * numComps; - - for (j = 0; j < numComps; ++j) { - const color = image[imageOffset + j]; - const maskOffset = j * 2; - - if (color < mask[maskOffset] || color > mask[maskOffset + 1]) { - opacity = 255; - break; - } - } - - alphaBuf[i] = opacity; - } - } else { - throw new _util.FormatError("Unknown mask format."); - } - } - - if (alphaBuf) { - for (i = 0, j = 3, ii = width * actualHeight; i < ii; ++i, j += 4) { - rgbaBuf[j] = alphaBuf[i]; - } - } else { - for (i = 0, j = 3, ii = width * actualHeight; i < ii; ++i, j += 4) { - rgbaBuf[j] = 255; - } - } - } - - undoPreblend(buffer, width, height) { - const matte = this.smask && this.smask.matte; - - if (!matte) { - return; - } - - const matteRgb = this.colorSpace.getRgb(matte, 0); - const matteR = matteRgb[0]; - const matteG = matteRgb[1]; - const matteB = matteRgb[2]; - const length = width * height * 4; - - for (let i = 0; i < length; i += 4) { - const alpha = buffer[i + 3]; - - if (alpha === 0) { - buffer[i] = 255; - buffer[i + 1] = 255; - buffer[i + 2] = 255; - continue; - } - - const k = 255 / alpha; - buffer[i] = (buffer[i] - matteR) * k + matteR; - buffer[i + 1] = (buffer[i + 1] - matteG) * k + matteG; - buffer[i + 2] = (buffer[i + 2] - matteB) * k + matteB; - } - } - - createImageData(forceRGBA = false) { - const drawWidth = this.drawWidth; - const drawHeight = this.drawHeight; - const imgData = { - width: drawWidth, - height: drawHeight, - interpolate: this.interpolate, - kind: 0, - data: null - }; - const numComps = this.numComps; - const originalWidth = this.width; - const originalHeight = this.height; - const bpc = this.bpc; - const rowBytes = originalWidth * numComps * bpc + 7 >> 3; - let imgArray; - - if (!forceRGBA) { - let kind; - - if (this.colorSpace.name === "DeviceGray" && bpc === 1) { - kind = _util.ImageKind.GRAYSCALE_1BPP; - } else if (this.colorSpace.name === "DeviceRGB" && bpc === 8 && !this.needsDecode) { - kind = _util.ImageKind.RGB_24BPP; - } - - if (kind && !this.smask && !this.mask && drawWidth === originalWidth && drawHeight === originalHeight) { - imgData.kind = kind; - imgArray = this.getImageBytes(originalHeight * rowBytes); - - if (this.image instanceof _decode_stream.DecodeStream) { - imgData.data = imgArray; - } else { - const newArray = new Uint8ClampedArray(imgArray.length); - newArray.set(imgArray); - imgData.data = newArray; - } - - if (this.needsDecode) { - (0, _util.assert)(kind === _util.ImageKind.GRAYSCALE_1BPP, "PDFImage.createImageData: The image must be grayscale."); - const buffer = imgData.data; - - for (let i = 0, ii = buffer.length; i < ii; i++) { - buffer[i] ^= 0xff; - } - } - - return imgData; - } - - if (this.image instanceof _jpeg_stream.JpegStream && !this.smask && !this.mask) { - let imageLength = originalHeight * rowBytes; - - switch (this.colorSpace.name) { - case "DeviceGray": - imageLength *= 3; - - case "DeviceRGB": - case "DeviceCMYK": - imgData.kind = _util.ImageKind.RGB_24BPP; - imgData.data = this.getImageBytes(imageLength, drawWidth, drawHeight, true); - return imgData; - } - } - } - - imgArray = this.getImageBytes(originalHeight * rowBytes); - const actualHeight = 0 | imgArray.length / rowBytes * drawHeight / originalHeight; - const comps = this.getComponents(imgArray); - let alpha01, maybeUndoPreblend; - - if (!forceRGBA && !this.smask && !this.mask) { - imgData.kind = _util.ImageKind.RGB_24BPP; - imgData.data = new Uint8ClampedArray(drawWidth * drawHeight * 3); - alpha01 = 0; - maybeUndoPreblend = false; - } else { - imgData.kind = _util.ImageKind.RGBA_32BPP; - imgData.data = new Uint8ClampedArray(drawWidth * drawHeight * 4); - alpha01 = 1; - maybeUndoPreblend = true; - this.fillOpacity(imgData.data, drawWidth, drawHeight, actualHeight, comps); - } - - if (this.needsDecode) { - this.decodeBuffer(comps); - } - - this.colorSpace.fillRgb(imgData.data, originalWidth, originalHeight, drawWidth, drawHeight, actualHeight, bpc, comps, alpha01); - - if (maybeUndoPreblend) { - this.undoPreblend(imgData.data, drawWidth, actualHeight); - } - - return imgData; - } - - fillGrayBuffer(buffer) { - const numComps = this.numComps; - - if (numComps !== 1) { - throw new _util.FormatError(`Reading gray scale from a color image: ${numComps}`); - } - - const width = this.width; - const height = this.height; - const bpc = this.bpc; - const rowBytes = width * numComps * bpc + 7 >> 3; - const imgArray = this.getImageBytes(height * rowBytes); - const comps = this.getComponents(imgArray); - let i, length; - - if (bpc === 1) { - length = width * height; - - if (this.needsDecode) { - for (i = 0; i < length; ++i) { - buffer[i] = comps[i] - 1 & 255; - } - } else { - for (i = 0; i < length; ++i) { - buffer[i] = -comps[i] & 255; - } - } - - return; - } - - if (this.needsDecode) { - this.decodeBuffer(comps); - } - - length = width * height; - const scale = 255 / ((1 << bpc) - 1); - - for (i = 0; i < length; ++i) { - buffer[i] = scale * comps[i]; - } - } - - getImageBytes(length, drawWidth, drawHeight, forceRGB = false) { - this.image.reset(); - this.image.drawWidth = drawWidth || this.width; - this.image.drawHeight = drawHeight || this.height; - this.image.forceRGB = !!forceRGB; - return this.image.getBytes(length, true); - } - -} - -exports.PDFImage = PDFImage; - -/***/ }), -/* 64 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.Catalog = void 0; - -var _primitives = __w_pdfjs_require__(5); - -var _core_utils = __w_pdfjs_require__(9); - -var _util = __w_pdfjs_require__(2); - -var _name_number_tree = __w_pdfjs_require__(65); - -var _base_stream = __w_pdfjs_require__(6); - -var _colorspace = __w_pdfjs_require__(24); - -var _file_spec = __w_pdfjs_require__(66); - -var _image_utils = __w_pdfjs_require__(58); - -var _metadata_parser = __w_pdfjs_require__(67); - -var _struct_tree = __w_pdfjs_require__(69); - -function fetchDestination(dest) { - if (dest instanceof _primitives.Dict) { - dest = dest.get("D"); - } - - return Array.isArray(dest) ? dest : null; -} - -class Catalog { - constructor(pdfManager, xref) { - this.pdfManager = pdfManager; - this.xref = xref; - this._catDict = xref.getCatalogObj(); - - if (!(this._catDict instanceof _primitives.Dict)) { - throw new _util.FormatError("Catalog object is not a dictionary."); - } - - this.toplevelPagesDict; - this._actualNumPages = null; - this.fontCache = new _primitives.RefSetCache(); - this.builtInCMapCache = new Map(); - this.standardFontDataCache = new Map(); - this.globalImageCache = new _image_utils.GlobalImageCache(); - this.pageKidsCountCache = new _primitives.RefSetCache(); - this.pageIndexCache = new _primitives.RefSetCache(); - this.nonBlendModesSet = new _primitives.RefSet(); - } - - get version() { - const version = this._catDict.get("Version"); - - return (0, _util.shadow)(this, "version", version instanceof _primitives.Name ? version.name : null); - } - - get lang() { - const lang = this._catDict.get("Lang"); - - return (0, _util.shadow)(this, "lang", typeof lang === "string" ? (0, _util.stringToPDFString)(lang) : null); - } - - get needsRendering() { - const needsRendering = this._catDict.get("NeedsRendering"); - - return (0, _util.shadow)(this, "needsRendering", typeof needsRendering === "boolean" ? needsRendering : false); - } - - get collection() { - let collection = null; - - try { - const obj = this._catDict.get("Collection"); - - if ((0, _primitives.isDict)(obj) && obj.size > 0) { - collection = obj; - } - } catch (ex) { - if (ex instanceof _core_utils.MissingDataException) { - throw ex; - } - - (0, _util.info)("Cannot fetch Collection entry; assuming no collection is present."); - } - - return (0, _util.shadow)(this, "collection", collection); - } - - get acroForm() { - let acroForm = null; - - try { - const obj = this._catDict.get("AcroForm"); - - if ((0, _primitives.isDict)(obj) && obj.size > 0) { - acroForm = obj; - } - } catch (ex) { - if (ex instanceof _core_utils.MissingDataException) { - throw ex; - } - - (0, _util.info)("Cannot fetch AcroForm entry; assuming no forms are present."); - } - - return (0, _util.shadow)(this, "acroForm", acroForm); - } - - get acroFormRef() { - const value = this._catDict.getRaw("AcroForm"); - - return (0, _util.shadow)(this, "acroFormRef", (0, _primitives.isRef)(value) ? value : null); - } - - get metadata() { - const streamRef = this._catDict.getRaw("Metadata"); - - if (!(streamRef instanceof _primitives.Ref)) { - return (0, _util.shadow)(this, "metadata", null); - } - - let metadata = null; - - try { - const suppressEncryption = !(this.xref.encrypt && this.xref.encrypt.encryptMetadata); - const stream = this.xref.fetch(streamRef, suppressEncryption); - - if (stream instanceof _base_stream.BaseStream && stream.dict instanceof _primitives.Dict) { - const type = stream.dict.get("Type"); - const subtype = stream.dict.get("Subtype"); - - if ((0, _primitives.isName)(type, "Metadata") && (0, _primitives.isName)(subtype, "XML")) { - const data = (0, _util.stringToUTF8String)(stream.getString()); - - if (data) { - metadata = new _metadata_parser.MetadataParser(data).serializable; - } - } - } - } catch (ex) { - if (ex instanceof _core_utils.MissingDataException) { - throw ex; - } - - (0, _util.info)(`Skipping invalid Metadata: "${ex}".`); - } - - return (0, _util.shadow)(this, "metadata", metadata); - } - - get markInfo() { - let markInfo = null; - - try { - markInfo = this._readMarkInfo(); - } catch (ex) { - if (ex instanceof _core_utils.MissingDataException) { - throw ex; - } - - (0, _util.warn)("Unable to read mark info."); - } - - return (0, _util.shadow)(this, "markInfo", markInfo); - } - - _readMarkInfo() { - const obj = this._catDict.get("MarkInfo"); - - if (!(0, _primitives.isDict)(obj)) { - return null; - } - - const markInfo = Object.assign(Object.create(null), { - Marked: false, - UserProperties: false, - Suspects: false - }); - - for (const key in markInfo) { - if (!obj.has(key)) { - continue; - } - - const value = obj.get(key); - - if (!(0, _util.isBool)(value)) { - continue; - } - - markInfo[key] = value; - } - - return markInfo; - } - - get structTreeRoot() { - let structTree = null; - - try { - structTree = this._readStructTreeRoot(); - } catch (ex) { - if (ex instanceof _core_utils.MissingDataException) { - throw ex; - } - - (0, _util.warn)("Unable read to structTreeRoot info."); - } - - return (0, _util.shadow)(this, "structTreeRoot", structTree); - } - - _readStructTreeRoot() { - const obj = this._catDict.get("StructTreeRoot"); - - if (!(0, _primitives.isDict)(obj)) { - return null; - } - - const root = new _struct_tree.StructTreeRoot(obj); - root.init(); - return root; - } - - get toplevelPagesDict() { - const pagesObj = this._catDict.get("Pages"); - - if (!(0, _primitives.isDict)(pagesObj)) { - throw new _util.FormatError("Invalid top-level pages dictionary."); - } - - return (0, _util.shadow)(this, "toplevelPagesDict", pagesObj); - } - - get documentOutline() { - let obj = null; - - try { - obj = this._readDocumentOutline(); - } catch (ex) { - if (ex instanceof _core_utils.MissingDataException) { - throw ex; - } - - (0, _util.warn)("Unable to read document outline."); - } - - return (0, _util.shadow)(this, "documentOutline", obj); - } - - _readDocumentOutline() { - let obj = this._catDict.get("Outlines"); - - if (!(0, _primitives.isDict)(obj)) { - return null; - } - - obj = obj.getRaw("First"); - - if (!(0, _primitives.isRef)(obj)) { - return null; - } - - const root = { - items: [] - }; - const queue = [{ - obj, - parent: root - }]; - const processed = new _primitives.RefSet(); - processed.put(obj); - const xref = this.xref, - blackColor = new Uint8ClampedArray(3); - - while (queue.length > 0) { - const i = queue.shift(); - const outlineDict = xref.fetchIfRef(i.obj); - - if (outlineDict === null) { - continue; - } - - if (!outlineDict.has("Title")) { - throw new _util.FormatError("Invalid outline item encountered."); - } - - const data = { - url: null, - dest: null - }; - Catalog.parseDestDictionary({ - destDict: outlineDict, - resultObj: data, - docBaseUrl: this.pdfManager.docBaseUrl - }); - const title = outlineDict.get("Title"); - const flags = outlineDict.get("F") || 0; - const color = outlineDict.getArray("C"); - const count = outlineDict.get("Count"); - let rgbColor = blackColor; - - if (Array.isArray(color) && color.length === 3 && (color[0] !== 0 || color[1] !== 0 || color[2] !== 0)) { - rgbColor = _colorspace.ColorSpace.singletons.rgb.getRgb(color, 0); - } - - const outlineItem = { - dest: data.dest, - url: data.url, - unsafeUrl: data.unsafeUrl, - newWindow: data.newWindow, - title: (0, _util.stringToPDFString)(title), - color: rgbColor, - count: Number.isInteger(count) ? count : undefined, - bold: !!(flags & 2), - italic: !!(flags & 1), - items: [] - }; - i.parent.items.push(outlineItem); - obj = outlineDict.getRaw("First"); - - if ((0, _primitives.isRef)(obj) && !processed.has(obj)) { - queue.push({ - obj, - parent: outlineItem - }); - processed.put(obj); - } - - obj = outlineDict.getRaw("Next"); - - if ((0, _primitives.isRef)(obj) && !processed.has(obj)) { - queue.push({ - obj, - parent: i.parent - }); - processed.put(obj); - } - } - - return root.items.length > 0 ? root.items : null; - } - - get permissions() { - let permissions = null; - - try { - permissions = this._readPermissions(); - } catch (ex) { - if (ex instanceof _core_utils.MissingDataException) { - throw ex; - } - - (0, _util.warn)("Unable to read permissions."); - } - - return (0, _util.shadow)(this, "permissions", permissions); - } - - _readPermissions() { - const encrypt = this.xref.trailer.get("Encrypt"); - - if (!(0, _primitives.isDict)(encrypt)) { - return null; - } - - let flags = encrypt.get("P"); - - if (!(0, _util.isNum)(flags)) { - return null; - } - - flags += 2 ** 32; - const permissions = []; - - for (const key in _util.PermissionFlag) { - const value = _util.PermissionFlag[key]; - - if (flags & value) { - permissions.push(value); - } - } - - return permissions; - } - - get optionalContentConfig() { - let config = null; - - try { - const properties = this._catDict.get("OCProperties"); - - if (!properties) { - return (0, _util.shadow)(this, "optionalContentConfig", null); - } - - const defaultConfig = properties.get("D"); - - if (!defaultConfig) { - return (0, _util.shadow)(this, "optionalContentConfig", null); - } - - const groupsData = properties.get("OCGs"); - - if (!Array.isArray(groupsData)) { - return (0, _util.shadow)(this, "optionalContentConfig", null); - } - - const groups = []; - const groupRefs = []; - - for (const groupRef of groupsData) { - if (!(0, _primitives.isRef)(groupRef)) { - continue; - } - - groupRefs.push(groupRef); - const group = this.xref.fetchIfRef(groupRef); - groups.push({ - id: groupRef.toString(), - name: (0, _util.isString)(group.get("Name")) ? (0, _util.stringToPDFString)(group.get("Name")) : null, - intent: (0, _util.isString)(group.get("Intent")) ? (0, _util.stringToPDFString)(group.get("Intent")) : null - }); - } - - config = this._readOptionalContentConfig(defaultConfig, groupRefs); - config.groups = groups; - } catch (ex) { - if (ex instanceof _core_utils.MissingDataException) { - throw ex; - } - - (0, _util.warn)(`Unable to read optional content config: ${ex}`); - } - - return (0, _util.shadow)(this, "optionalContentConfig", config); - } - - _readOptionalContentConfig(config, contentGroupRefs) { - function parseOnOff(refs) { - const onParsed = []; - - if (Array.isArray(refs)) { - for (const value of refs) { - if (!(0, _primitives.isRef)(value)) { - continue; - } - - if (contentGroupRefs.includes(value)) { - onParsed.push(value.toString()); - } - } - } - - return onParsed; - } - - function parseOrder(refs, nestedLevels = 0) { - if (!Array.isArray(refs)) { - return null; - } - - const order = []; - - for (const value of refs) { - if ((0, _primitives.isRef)(value) && contentGroupRefs.includes(value)) { - parsedOrderRefs.put(value); - order.push(value.toString()); - continue; - } - - const nestedOrder = parseNestedOrder(value, nestedLevels); - - if (nestedOrder) { - order.push(nestedOrder); - } - } - - if (nestedLevels > 0) { - return order; - } - - const hiddenGroups = []; - - for (const groupRef of contentGroupRefs) { - if (parsedOrderRefs.has(groupRef)) { - continue; - } - - hiddenGroups.push(groupRef.toString()); - } - - if (hiddenGroups.length) { - order.push({ - name: null, - order: hiddenGroups - }); - } - - return order; - } - - function parseNestedOrder(ref, nestedLevels) { - if (++nestedLevels > MAX_NESTED_LEVELS) { - (0, _util.warn)("parseNestedOrder - reached MAX_NESTED_LEVELS."); - return null; - } - - const value = xref.fetchIfRef(ref); - - if (!Array.isArray(value)) { - return null; - } - - const nestedName = xref.fetchIfRef(value[0]); - - if (typeof nestedName !== "string") { - return null; - } - - const nestedOrder = parseOrder(value.slice(1), nestedLevels); - - if (!nestedOrder || !nestedOrder.length) { - return null; - } - - return { - name: (0, _util.stringToPDFString)(nestedName), - order: nestedOrder - }; - } - - const xref = this.xref, - parsedOrderRefs = new _primitives.RefSet(), - MAX_NESTED_LEVELS = 10; - return { - name: (0, _util.isString)(config.get("Name")) ? (0, _util.stringToPDFString)(config.get("Name")) : null, - creator: (0, _util.isString)(config.get("Creator")) ? (0, _util.stringToPDFString)(config.get("Creator")) : null, - baseState: (0, _primitives.isName)(config.get("BaseState")) ? config.get("BaseState").name : null, - on: parseOnOff(config.get("ON")), - off: parseOnOff(config.get("OFF")), - order: parseOrder(config.get("Order")), - groups: null - }; - } - - setActualNumPages(num = null) { - this._actualNumPages = num; - } - - get hasActualNumPages() { - return this._actualNumPages !== null; - } - - get _pagesCount() { - const obj = this.toplevelPagesDict.get("Count"); - - if (!Number.isInteger(obj)) { - throw new _util.FormatError("Page count in top-level pages dictionary is not an integer."); - } - - return (0, _util.shadow)(this, "_pagesCount", obj); - } - - get numPages() { - return this.hasActualNumPages ? this._actualNumPages : this._pagesCount; - } - - get destinations() { - const obj = this._readDests(), - dests = Object.create(null); - - if (obj instanceof _name_number_tree.NameTree) { - for (const [key, value] of obj.getAll()) { - const dest = fetchDestination(value); - - if (dest) { - dests[key] = dest; - } - } - } else if (obj instanceof _primitives.Dict) { - obj.forEach(function (key, value) { - const dest = fetchDestination(value); - - if (dest) { - dests[key] = dest; - } - }); - } - - return (0, _util.shadow)(this, "destinations", dests); - } - - getDestination(id) { - const obj = this._readDests(); - - if (obj instanceof _name_number_tree.NameTree) { - const dest = fetchDestination(obj.get(id)); - - if (dest) { - return dest; - } - - const allDest = this.destinations[id]; - - if (allDest) { - (0, _util.warn)(`Found "${id}" at an incorrect position in the NameTree.`); - return allDest; - } - } else if (obj instanceof _primitives.Dict) { - const dest = fetchDestination(obj.get(id)); - - if (dest) { - return dest; - } - } - - return null; - } - - _readDests() { - const obj = this._catDict.get("Names"); - - if (obj && obj.has("Dests")) { - return new _name_number_tree.NameTree(obj.getRaw("Dests"), this.xref); - } else if (this._catDict.has("Dests")) { - return this._catDict.get("Dests"); - } - - return undefined; - } - - get pageLabels() { - let obj = null; - - try { - obj = this._readPageLabels(); - } catch (ex) { - if (ex instanceof _core_utils.MissingDataException) { - throw ex; - } - - (0, _util.warn)("Unable to read page labels."); - } - - return (0, _util.shadow)(this, "pageLabels", obj); - } - - _readPageLabels() { - const obj = this._catDict.getRaw("PageLabels"); - - if (!obj) { - return null; - } - - const pageLabels = new Array(this.numPages); - let style = null, - prefix = ""; - const numberTree = new _name_number_tree.NumberTree(obj, this.xref); - const nums = numberTree.getAll(); - let currentLabel = "", - currentIndex = 1; - - for (let i = 0, ii = this.numPages; i < ii; i++) { - const labelDict = nums.get(i); - - if (labelDict !== undefined) { - if (!(0, _primitives.isDict)(labelDict)) { - throw new _util.FormatError("PageLabel is not a dictionary."); - } - - if (labelDict.has("Type") && !(0, _primitives.isName)(labelDict.get("Type"), "PageLabel")) { - throw new _util.FormatError("Invalid type in PageLabel dictionary."); - } - - if (labelDict.has("S")) { - const s = labelDict.get("S"); - - if (!(0, _primitives.isName)(s)) { - throw new _util.FormatError("Invalid style in PageLabel dictionary."); - } - - style = s.name; - } else { - style = null; - } - - if (labelDict.has("P")) { - const p = labelDict.get("P"); - - if (!(0, _util.isString)(p)) { - throw new _util.FormatError("Invalid prefix in PageLabel dictionary."); - } - - prefix = (0, _util.stringToPDFString)(p); - } else { - prefix = ""; - } - - if (labelDict.has("St")) { - const st = labelDict.get("St"); - - if (!(Number.isInteger(st) && st >= 1)) { - throw new _util.FormatError("Invalid start in PageLabel dictionary."); - } - - currentIndex = st; - } else { - currentIndex = 1; - } - } - - switch (style) { - case "D": - currentLabel = currentIndex; - break; - - case "R": - case "r": - currentLabel = (0, _core_utils.toRomanNumerals)(currentIndex, style === "r"); - break; - - case "A": - case "a": - const LIMIT = 26; - const A_UPPER_CASE = 0x41, - A_LOWER_CASE = 0x61; - const baseCharCode = style === "a" ? A_LOWER_CASE : A_UPPER_CASE; - const letterIndex = currentIndex - 1; - const character = String.fromCharCode(baseCharCode + letterIndex % LIMIT); - const charBuf = []; - - for (let j = 0, jj = letterIndex / LIMIT | 0; j <= jj; j++) { - charBuf.push(character); - } - - currentLabel = charBuf.join(""); - break; - - default: - if (style) { - throw new _util.FormatError(`Invalid style "${style}" in PageLabel dictionary.`); - } - - currentLabel = ""; - } - - pageLabels[i] = prefix + currentLabel; - currentIndex++; - } - - return pageLabels; - } - - get pageLayout() { - const obj = this._catDict.get("PageLayout"); - - let pageLayout = ""; - - if ((0, _primitives.isName)(obj)) { - switch (obj.name) { - case "SinglePage": - case "OneColumn": - case "TwoColumnLeft": - case "TwoColumnRight": - case "TwoPageLeft": - case "TwoPageRight": - pageLayout = obj.name; - } - } - - return (0, _util.shadow)(this, "pageLayout", pageLayout); - } - - get pageMode() { - const obj = this._catDict.get("PageMode"); - - let pageMode = "UseNone"; - - if ((0, _primitives.isName)(obj)) { - switch (obj.name) { - case "UseNone": - case "UseOutlines": - case "UseThumbs": - case "FullScreen": - case "UseOC": - case "UseAttachments": - pageMode = obj.name; - } - } - - return (0, _util.shadow)(this, "pageMode", pageMode); - } - - get viewerPreferences() { - const ViewerPreferencesValidators = { - HideToolbar: _util.isBool, - HideMenubar: _util.isBool, - HideWindowUI: _util.isBool, - FitWindow: _util.isBool, - CenterWindow: _util.isBool, - DisplayDocTitle: _util.isBool, - NonFullScreenPageMode: _primitives.isName, - Direction: _primitives.isName, - ViewArea: _primitives.isName, - ViewClip: _primitives.isName, - PrintArea: _primitives.isName, - PrintClip: _primitives.isName, - PrintScaling: _primitives.isName, - Duplex: _primitives.isName, - PickTrayByPDFSize: _util.isBool, - PrintPageRange: Array.isArray, - NumCopies: Number.isInteger - }; - - const obj = this._catDict.get("ViewerPreferences"); - - let prefs = null; - - if ((0, _primitives.isDict)(obj)) { - for (const key in ViewerPreferencesValidators) { - if (!obj.has(key)) { - continue; - } - - const value = obj.get(key); - - if (!ViewerPreferencesValidators[key](value)) { - (0, _util.info)(`Bad value in ViewerPreferences for "${key}".`); - continue; - } - - let prefValue; - - switch (key) { - case "NonFullScreenPageMode": - switch (value.name) { - case "UseNone": - case "UseOutlines": - case "UseThumbs": - case "UseOC": - prefValue = value.name; - break; - - default: - prefValue = "UseNone"; - } - - break; - - case "Direction": - switch (value.name) { - case "L2R": - case "R2L": - prefValue = value.name; - break; - - default: - prefValue = "L2R"; - } - - break; - - case "ViewArea": - case "ViewClip": - case "PrintArea": - case "PrintClip": - switch (value.name) { - case "MediaBox": - case "CropBox": - case "BleedBox": - case "TrimBox": - case "ArtBox": - prefValue = value.name; - break; - - default: - prefValue = "CropBox"; - } - - break; - - case "PrintScaling": - switch (value.name) { - case "None": - case "AppDefault": - prefValue = value.name; - break; - - default: - prefValue = "AppDefault"; - } - - break; - - case "Duplex": - switch (value.name) { - case "Simplex": - case "DuplexFlipShortEdge": - case "DuplexFlipLongEdge": - prefValue = value.name; - break; - - default: - prefValue = "None"; - } - - break; - - case "PrintPageRange": - const length = value.length; - - if (length % 2 !== 0) { - break; - } - - const isValid = value.every((page, i, arr) => { - return Number.isInteger(page) && page > 0 && (i === 0 || page >= arr[i - 1]) && page <= this.numPages; - }); - - if (isValid) { - prefValue = value; - } - - break; - - case "NumCopies": - if (value > 0) { - prefValue = value; - } - - break; - - default: - if (typeof value !== "boolean") { - throw new _util.FormatError(`viewerPreferences - expected a boolean value for: ${key}`); - } - - prefValue = value; - } - - if (prefValue !== undefined) { - if (!prefs) { - prefs = Object.create(null); - } - - prefs[key] = prefValue; - } else { - (0, _util.info)(`Bad value in ViewerPreferences for "${key}".`); - } - } - } - - return (0, _util.shadow)(this, "viewerPreferences", prefs); - } - - get openAction() { - const obj = this._catDict.get("OpenAction"); - - const openAction = Object.create(null); - - if ((0, _primitives.isDict)(obj)) { - const destDict = new _primitives.Dict(this.xref); - destDict.set("A", obj); - const resultObj = { - url: null, - dest: null, - action: null - }; - Catalog.parseDestDictionary({ - destDict, - resultObj - }); - - if (Array.isArray(resultObj.dest)) { - openAction.dest = resultObj.dest; - } else if (resultObj.action) { - openAction.action = resultObj.action; - } - } else if (Array.isArray(obj)) { - openAction.dest = obj; - } - - return (0, _util.shadow)(this, "openAction", (0, _util.objectSize)(openAction) > 0 ? openAction : null); - } - - get attachments() { - const obj = this._catDict.get("Names"); - - let attachments = null; - - if (obj instanceof _primitives.Dict && obj.has("EmbeddedFiles")) { - const nameTree = new _name_number_tree.NameTree(obj.getRaw("EmbeddedFiles"), this.xref); - - for (const [key, value] of nameTree.getAll()) { - const fs = new _file_spec.FileSpec(value, this.xref); - - if (!attachments) { - attachments = Object.create(null); - } - - attachments[(0, _util.stringToPDFString)(key)] = fs.serializable; - } - } - - return (0, _util.shadow)(this, "attachments", attachments); - } - - get xfaImages() { - const obj = this._catDict.get("Names"); - - let xfaImages = null; - - if (obj instanceof _primitives.Dict && obj.has("XFAImages")) { - const nameTree = new _name_number_tree.NameTree(obj.getRaw("XFAImages"), this.xref); - - for (const [key, value] of nameTree.getAll()) { - if (!xfaImages) { - xfaImages = new _primitives.Dict(this.xref); - } - - xfaImages.set(key, value); - } - } - - return (0, _util.shadow)(this, "xfaImages", xfaImages); - } - - _collectJavaScript() { - const obj = this._catDict.get("Names"); - - let javaScript = null; - - function appendIfJavaScriptDict(name, jsDict) { - if (!(jsDict instanceof _primitives.Dict)) { - return; - } - - if (!(0, _primitives.isName)(jsDict.get("S"), "JavaScript")) { - return; - } - - let js = jsDict.get("JS"); - - if ((0, _primitives.isStream)(js)) { - js = js.getString(); - } else if (typeof js !== "string") { - return; - } - - if (javaScript === null) { - javaScript = new Map(); - } - - javaScript.set(name, (0, _util.stringToPDFString)(js)); - } - - if (obj instanceof _primitives.Dict && obj.has("JavaScript")) { - const nameTree = new _name_number_tree.NameTree(obj.getRaw("JavaScript"), this.xref); - - for (const [key, value] of nameTree.getAll()) { - appendIfJavaScriptDict(key, value); - } - } - - const openAction = this._catDict.get("OpenAction"); - - if (openAction) { - appendIfJavaScriptDict("OpenAction", openAction); - } - - return javaScript; - } - - get javaScript() { - const javaScript = this._collectJavaScript(); - - return (0, _util.shadow)(this, "javaScript", javaScript ? [...javaScript.values()] : null); - } - - get jsActions() { - const javaScript = this._collectJavaScript(); - - let actions = (0, _core_utils.collectActions)(this.xref, this._catDict, _util.DocumentActionEventType); - - if (javaScript) { - if (!actions) { - actions = Object.create(null); - } - - for (const [key, val] of javaScript) { - if (key in actions) { - actions[key].push(val); - } else { - actions[key] = [val]; - } - } - } - - return (0, _util.shadow)(this, "jsActions", actions); - } - - fontFallback(id, handler) { - const promises = []; - this.fontCache.forEach(function (promise) { - promises.push(promise); - }); - return Promise.all(promises).then(translatedFonts => { - for (const translatedFont of translatedFonts) { - if (translatedFont.loadedName === id) { - translatedFont.fallback(handler); - return; - } - } - }); - } - - cleanup(manuallyTriggered = false) { - (0, _primitives.clearPrimitiveCaches)(); - this.globalImageCache.clear(manuallyTriggered); - this.pageKidsCountCache.clear(); - this.pageIndexCache.clear(); - this.nonBlendModesSet.clear(); - const promises = []; - this.fontCache.forEach(function (promise) { - promises.push(promise); - }); - return Promise.all(promises).then(translatedFonts => { - for (const { - dict - } of translatedFonts) { - delete dict.cacheKey; - } - - this.fontCache.clear(); - this.builtInCMapCache.clear(); - this.standardFontDataCache.clear(); - }); - } - - getPageDict(pageIndex) { - const capability = (0, _util.createPromiseCapability)(); - const nodesToVisit = [this.toplevelPagesDict]; - const visitedNodes = new _primitives.RefSet(); - - const pagesRef = this._catDict.getRaw("Pages"); - - if (pagesRef instanceof _primitives.Ref) { - visitedNodes.put(pagesRef); - } - - const xref = this.xref, - pageKidsCountCache = this.pageKidsCountCache; - let currentPageIndex = 0; - - function next() { - while (nodesToVisit.length) { - const currentNode = nodesToVisit.pop(); - - if (currentNode instanceof _primitives.Ref) { - const count = pageKidsCountCache.get(currentNode); - - if (count >= 0 && currentPageIndex + count <= pageIndex) { - currentPageIndex += count; - continue; - } - - if (visitedNodes.has(currentNode)) { - capability.reject(new _util.FormatError("Pages tree contains circular reference.")); - return; - } - - visitedNodes.put(currentNode); - xref.fetchAsync(currentNode).then(function (obj) { - if ((0, _primitives.isDict)(obj, "Page") || (0, _primitives.isDict)(obj) && !obj.has("Kids")) { - if (currentNode && !pageKidsCountCache.has(currentNode)) { - pageKidsCountCache.put(currentNode, 1); - } - - if (pageIndex === currentPageIndex) { - capability.resolve([obj, currentNode]); - } else { - currentPageIndex++; - next(); - } - - return; - } - - nodesToVisit.push(obj); - next(); - }, capability.reject); - return; - } - - if (!(currentNode instanceof _primitives.Dict)) { - capability.reject(new _util.FormatError("Page dictionary kid reference points to wrong type of object.")); - return; - } - - let count; - - try { - count = currentNode.get("Count"); - } catch (ex) { - if (ex instanceof _core_utils.MissingDataException) { - throw ex; - } - } - - if (Number.isInteger(count) && count >= 0) { - const objId = currentNode.objId; - - if (objId && !pageKidsCountCache.has(objId)) { - pageKidsCountCache.put(objId, count); - } - - if (currentPageIndex + count <= pageIndex) { - currentPageIndex += count; - continue; - } - } - - let kids; - - try { - kids = currentNode.get("Kids"); - } catch (ex) { - if (ex instanceof _core_utils.MissingDataException) { - throw ex; - } - } - - if (!Array.isArray(kids)) { - let type; - - try { - type = currentNode.get("Type"); - } catch (ex) { - if (ex instanceof _core_utils.MissingDataException) { - throw ex; - } - } - - if ((0, _primitives.isName)(type, "Page") || !currentNode.has("Type") && currentNode.has("Contents")) { - if (currentPageIndex === pageIndex) { - capability.resolve([currentNode, null]); - return; - } - - currentPageIndex++; - continue; - } - - capability.reject(new _util.FormatError("Page dictionary kids object is not an array.")); - return; - } - - for (let last = kids.length - 1; last >= 0; last--) { - nodesToVisit.push(kids[last]); - } - } - - capability.reject(new Error(`Page index ${pageIndex} not found.`)); - } - - next(); - return capability.promise; - } - - getAllPageDicts(recoveryMode = false) { - const queue = [{ - currentNode: this.toplevelPagesDict, - posInKids: 0 - }]; - const visitedNodes = new _primitives.RefSet(); - - const pagesRef = this._catDict.getRaw("Pages"); - - if (pagesRef instanceof _primitives.Ref) { - visitedNodes.put(pagesRef); - } - - const map = new Map(); - let pageIndex = 0; - - function addPageDict(pageDict, pageRef) { - map.set(pageIndex++, [pageDict, pageRef]); - } - - function addPageError(error) { - map.set(pageIndex++, [error, null]); - } - - while (queue.length > 0) { - const queueItem = queue[queue.length - 1]; - const { - currentNode, - posInKids - } = queueItem; - let kids; - - try { - kids = currentNode.get("Kids"); - } catch (ex) { - if (ex instanceof _core_utils.MissingDataException) { - throw ex; - } - - if (ex instanceof _core_utils.XRefEntryException && !recoveryMode) { - throw ex; - } - - addPageError(ex); - break; - } - - if (!Array.isArray(kids)) { - addPageError(new _util.FormatError("Page dictionary kids object is not an array.")); - break; - } - - if (posInKids >= kids.length) { - queue.pop(); - continue; - } - - const kidObj = kids[posInKids]; - let obj; - - if (kidObj instanceof _primitives.Ref) { - try { - obj = this.xref.fetch(kidObj); - } catch (ex) { - if (ex instanceof _core_utils.MissingDataException) { - throw ex; - } - - if (ex instanceof _core_utils.XRefEntryException && !recoveryMode) { - throw ex; - } - - addPageError(ex); - break; - } - - if (visitedNodes.has(kidObj)) { - addPageError(new _util.FormatError("Pages tree contains circular reference.")); - break; - } - - visitedNodes.put(kidObj); - } else { - obj = kidObj; - } - - if (!(obj instanceof _primitives.Dict)) { - addPageError(new _util.FormatError("Page dictionary kid reference points to wrong type of object.")); - break; - } - - if ((0, _primitives.isDict)(obj, "Page") || !obj.has("Kids")) { - addPageDict(obj, kidObj instanceof _primitives.Ref ? kidObj : null); - } else { - queue.push({ - currentNode: obj, - posInKids: 0 - }); - } - - queueItem.posInKids++; - } - - return map; - } - - getPageIndex(pageRef) { - const cachedPageIndex = this.pageIndexCache.get(pageRef); - - if (cachedPageIndex !== undefined) { - return Promise.resolve(cachedPageIndex); - } - - const xref = this.xref; - - function pagesBeforeRef(kidRef) { - let total = 0, - parentRef; - return xref.fetchAsync(kidRef).then(function (node) { - if ((0, _primitives.isRefsEqual)(kidRef, pageRef) && !(0, _primitives.isDict)(node, "Page") && !((0, _primitives.isDict)(node) && !node.has("Type") && node.has("Contents"))) { - throw new _util.FormatError("The reference does not point to a /Page dictionary."); - } - - if (!node) { - return null; - } - - if (!(0, _primitives.isDict)(node)) { - throw new _util.FormatError("Node must be a dictionary."); - } - - parentRef = node.getRaw("Parent"); - return node.getAsync("Parent"); - }).then(function (parent) { - if (!parent) { - return null; - } - - if (!(0, _primitives.isDict)(parent)) { - throw new _util.FormatError("Parent must be a dictionary."); - } - - return parent.getAsync("Kids"); - }).then(function (kids) { - if (!kids) { - return null; - } - - const kidPromises = []; - let found = false; - - for (let i = 0, ii = kids.length; i < ii; i++) { - const kid = kids[i]; - - if (!(0, _primitives.isRef)(kid)) { - throw new _util.FormatError("Kid must be a reference."); - } - - if ((0, _primitives.isRefsEqual)(kid, kidRef)) { - found = true; - break; - } - - kidPromises.push(xref.fetchAsync(kid).then(function (obj) { - if (!(0, _primitives.isDict)(obj)) { - throw new _util.FormatError("Kid node must be a dictionary."); - } - - if (obj.has("Count")) { - total += obj.get("Count"); - } else { - total++; - } - })); - } - - if (!found) { - throw new _util.FormatError("Kid reference not found in parent's kids."); - } - - return Promise.all(kidPromises).then(function () { - return [total, parentRef]; - }); - }); - } - - let total = 0; - - const next = ref => pagesBeforeRef(ref).then(args => { - if (!args) { - this.pageIndexCache.put(pageRef, total); - return total; - } - - const [count, parentRef] = args; - total += count; - return next(parentRef); - }); - - return next(pageRef); - } - - static parseDestDictionary(params) { - const destDict = params.destDict; - - if (!(0, _primitives.isDict)(destDict)) { - (0, _util.warn)("parseDestDictionary: `destDict` must be a dictionary."); - return; - } - - const resultObj = params.resultObj; - - if (typeof resultObj !== "object") { - (0, _util.warn)("parseDestDictionary: `resultObj` must be an object."); - return; - } - - const docBaseUrl = params.docBaseUrl || null; - let action = destDict.get("A"), - url, - dest; - - if (!(0, _primitives.isDict)(action)) { - if (destDict.has("Dest")) { - action = destDict.get("Dest"); - } else { - action = destDict.get("AA"); - - if ((0, _primitives.isDict)(action)) { - if (action.has("D")) { - action = action.get("D"); - } else if (action.has("U")) { - action = action.get("U"); - } - } - } - } - - if ((0, _primitives.isDict)(action)) { - const actionType = action.get("S"); - - if (!(0, _primitives.isName)(actionType)) { - (0, _util.warn)("parseDestDictionary: Invalid type in Action dictionary."); - return; - } - - const actionName = actionType.name; - - switch (actionName) { - case "ResetForm": - const flags = action.get("Flags"); - const include = (((0, _util.isNum)(flags) ? flags : 0) & 1) === 0; - const fields = []; - const refs = []; - - for (const obj of action.get("Fields") || []) { - if ((0, _primitives.isRef)(obj)) { - refs.push(obj.toString()); - } else if ((0, _util.isString)(obj)) { - fields.push((0, _util.stringToPDFString)(obj)); - } - } - - resultObj.resetForm = { - fields, - refs, - include - }; - break; - - case "URI": - url = action.get("URI"); - - if (url instanceof _primitives.Name) { - url = "/" + url.name; - } - - break; - - case "GoTo": - dest = action.get("D"); - break; - - case "Launch": - case "GoToR": - const urlDict = action.get("F"); - - if ((0, _primitives.isDict)(urlDict)) { - url = urlDict.get("F") || null; - } else if ((0, _util.isString)(urlDict)) { - url = urlDict; - } - - let remoteDest = action.get("D"); - - if (remoteDest) { - if ((0, _primitives.isName)(remoteDest)) { - remoteDest = remoteDest.name; - } - - if ((0, _util.isString)(url)) { - const baseUrl = url.split("#")[0]; - - if ((0, _util.isString)(remoteDest)) { - url = baseUrl + "#" + remoteDest; - } else if (Array.isArray(remoteDest)) { - url = baseUrl + "#" + JSON.stringify(remoteDest); - } - } - } - - const newWindow = action.get("NewWindow"); - - if ((0, _util.isBool)(newWindow)) { - resultObj.newWindow = newWindow; - } - - break; - - case "Named": - const namedAction = action.get("N"); - - if ((0, _primitives.isName)(namedAction)) { - resultObj.action = namedAction.name; - } - - break; - - case "JavaScript": - const jsAction = action.get("JS"); - let js; - - if ((0, _primitives.isStream)(jsAction)) { - js = jsAction.getString(); - } else if ((0, _util.isString)(jsAction)) { - js = jsAction; - } - - const jsURL = js && (0, _core_utils.recoverJsURL)((0, _util.stringToPDFString)(js)); - - if (jsURL) { - url = jsURL.url; - resultObj.newWindow = jsURL.newWindow; - break; - } - - default: - if (actionName === "JavaScript" || actionName === "SubmitForm") { - break; - } - - (0, _util.warn)(`parseDestDictionary - unsupported action: "${actionName}".`); - break; - } - } else if (destDict.has("Dest")) { - dest = destDict.get("Dest"); - } - - if ((0, _util.isString)(url)) { - const absoluteUrl = (0, _util.createValidAbsoluteUrl)(url, docBaseUrl, { - addDefaultProtocol: true, - tryConvertEncoding: true - }); - - if (absoluteUrl) { - resultObj.url = absoluteUrl.href; - } - - resultObj.unsafeUrl = url; - } - - if (dest) { - if ((0, _primitives.isName)(dest)) { - dest = dest.name; - } - - if ((0, _util.isString)(dest) || Array.isArray(dest)) { - resultObj.dest = dest; - } - } - } - -} - -exports.Catalog = Catalog; - -/***/ }), -/* 65 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.NumberTree = exports.NameTree = void 0; - -var _util = __w_pdfjs_require__(2); - -var _primitives = __w_pdfjs_require__(5); - -class NameOrNumberTree { - constructor(root, xref, type) { - if (this.constructor === NameOrNumberTree) { - (0, _util.unreachable)("Cannot initialize NameOrNumberTree."); - } - - this.root = root; - this.xref = xref; - this._type = type; - } - - getAll() { - const map = new Map(); - - if (!this.root) { - return map; - } - - const xref = this.xref; - const processed = new _primitives.RefSet(); - processed.put(this.root); - const queue = [this.root]; - - while (queue.length > 0) { - const obj = xref.fetchIfRef(queue.shift()); - - if (!(0, _primitives.isDict)(obj)) { - continue; - } - - if (obj.has("Kids")) { - const kids = obj.get("Kids"); - - for (let i = 0, ii = kids.length; i < ii; i++) { - const kid = kids[i]; - - if (processed.has(kid)) { - throw new _util.FormatError(`Duplicate entry in "${this._type}" tree.`); - } - - queue.push(kid); - processed.put(kid); - } - - continue; - } - - const entries = obj.get(this._type); - - if (!Array.isArray(entries)) { - continue; - } - - for (let i = 0, ii = entries.length; i < ii; i += 2) { - map.set(xref.fetchIfRef(entries[i]), xref.fetchIfRef(entries[i + 1])); - } - } - - return map; - } - - get(key) { - if (!this.root) { - return null; - } - - const xref = this.xref; - let kidsOrEntries = xref.fetchIfRef(this.root); - let loopCount = 0; - const MAX_LEVELS = 10; - - while (kidsOrEntries.has("Kids")) { - if (++loopCount > MAX_LEVELS) { - (0, _util.warn)(`Search depth limit reached for "${this._type}" tree.`); - return null; - } - - const kids = kidsOrEntries.get("Kids"); - - if (!Array.isArray(kids)) { - return null; - } - - let l = 0, - r = kids.length - 1; - - while (l <= r) { - const m = l + r >> 1; - const kid = xref.fetchIfRef(kids[m]); - const limits = kid.get("Limits"); - - if (key < xref.fetchIfRef(limits[0])) { - r = m - 1; - } else if (key > xref.fetchIfRef(limits[1])) { - l = m + 1; - } else { - kidsOrEntries = xref.fetchIfRef(kids[m]); - break; - } - } - - if (l > r) { - return null; - } - } - - const entries = kidsOrEntries.get(this._type); - - if (Array.isArray(entries)) { - let l = 0, - r = entries.length - 2; - - while (l <= r) { - const tmp = l + r >> 1, - m = tmp + (tmp & 1); - const currentKey = xref.fetchIfRef(entries[m]); - - if (key < currentKey) { - r = m - 2; - } else if (key > currentKey) { - l = m + 2; - } else { - return xref.fetchIfRef(entries[m + 1]); - } - } - } - - return null; - } - -} - -class NameTree extends NameOrNumberTree { - constructor(root, xref) { - super(root, xref, "Names"); - } - -} - -exports.NameTree = NameTree; - -class NumberTree extends NameOrNumberTree { - constructor(root, xref) { - super(root, xref, "Nums"); - } - -} - -exports.NumberTree = NumberTree; - -/***/ }), -/* 66 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.FileSpec = void 0; - -var _primitives = __w_pdfjs_require__(5); - -var _util = __w_pdfjs_require__(2); - -function pickPlatformItem(dict) { - if (dict.has("UF")) { - return dict.get("UF"); - } else if (dict.has("F")) { - return dict.get("F"); - } else if (dict.has("Unix")) { - return dict.get("Unix"); - } else if (dict.has("Mac")) { - return dict.get("Mac"); - } else if (dict.has("DOS")) { - return dict.get("DOS"); - } - - return null; -} - -class FileSpec { - constructor(root, xref) { - if (!root || !(0, _primitives.isDict)(root)) { - return; - } - - this.xref = xref; - this.root = root; - - if (root.has("FS")) { - this.fs = root.get("FS"); - } - - this.description = root.has("Desc") ? (0, _util.stringToPDFString)(root.get("Desc")) : ""; - - if (root.has("RF")) { - (0, _util.warn)("Related file specifications are not supported"); - } - - this.contentAvailable = true; - - if (!root.has("EF")) { - this.contentAvailable = false; - (0, _util.warn)("Non-embedded file specifications are not supported"); - } - } - - get filename() { - if (!this._filename && this.root) { - const filename = pickPlatformItem(this.root) || "unnamed"; - this._filename = (0, _util.stringToPDFString)(filename).replace(/\\\\/g, "\\").replace(/\\\//g, "/").replace(/\\/g, "/"); - } - - return this._filename; - } - - get content() { - if (!this.contentAvailable) { - return null; - } - - if (!this.contentRef && this.root) { - this.contentRef = pickPlatformItem(this.root.get("EF")); - } - - let content = null; - - if (this.contentRef) { - const fileObj = this.xref.fetchIfRef(this.contentRef); - - if (fileObj && (0, _primitives.isStream)(fileObj)) { - content = fileObj.getBytes(); - } else { - (0, _util.warn)("Embedded file specification points to non-existing/invalid content"); - } - } else { - (0, _util.warn)("Embedded file specification does not have a content"); - } - - return content; - } - - get serializable() { - return { - filename: this.filename, - content: this.content - }; - } - -} - -exports.FileSpec = FileSpec; - -/***/ }), -/* 67 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.MetadataParser = void 0; - -var _xml_parser = __w_pdfjs_require__(68); - -class MetadataParser { - constructor(data) { - data = this._repair(data); - const parser = new _xml_parser.SimpleXMLParser({ - lowerCaseName: true - }); - const xmlDocument = parser.parseFromString(data); - this._metadataMap = new Map(); - this._data = data; - - if (xmlDocument) { - this._parse(xmlDocument); - } - } - - _repair(data) { - return data.replace(/^[^<]+/, "").replace(/>\\376\\377([^<]+)/g, function (all, codes) { - const bytes = codes.replace(/\\([0-3])([0-7])([0-7])/g, function (code, d1, d2, d3) { - return String.fromCharCode(d1 * 64 + d2 * 8 + d3 * 1); - }).replace(/&(amp|apos|gt|lt|quot);/g, function (str, name) { - switch (name) { - case "amp": - return "&"; - - case "apos": - return "'"; - - case "gt": - return ">"; - - case "lt": - return "<"; - - case "quot": - return '"'; - } - - throw new Error(`_repair: ${name} isn't defined.`); - }); - const charBuf = []; - - for (let i = 0, ii = bytes.length; i < ii; i += 2) { - const code = bytes.charCodeAt(i) * 256 + bytes.charCodeAt(i + 1); - - if (code >= 32 && code < 127 && code !== 60 && code !== 62 && code !== 38) { - charBuf.push(String.fromCharCode(code)); - } else { - charBuf.push("&#x" + (0x10000 + code).toString(16).substring(1) + ";"); - } - } - - return ">" + charBuf.join(""); - }); - } - - _getSequence(entry) { - const name = entry.nodeName; - - if (name !== "rdf:bag" && name !== "rdf:seq" && name !== "rdf:alt") { - return null; - } - - return entry.childNodes.filter(node => node.nodeName === "rdf:li"); - } - - _parseArray(entry) { - if (!entry.hasChildNodes()) { - return; - } - - const [seqNode] = entry.childNodes; - const sequence = this._getSequence(seqNode) || []; - - this._metadataMap.set(entry.nodeName, sequence.map(node => node.textContent.trim())); - } - - _parse(xmlDocument) { - let rdf = xmlDocument.documentElement; - - if (rdf.nodeName !== "rdf:rdf") { - rdf = rdf.firstChild; - - while (rdf && rdf.nodeName !== "rdf:rdf") { - rdf = rdf.nextSibling; - } - } - - if (!rdf || rdf.nodeName !== "rdf:rdf" || !rdf.hasChildNodes()) { - return; - } - - for (const desc of rdf.childNodes) { - if (desc.nodeName !== "rdf:description") { - continue; - } - - for (const entry of desc.childNodes) { - const name = entry.nodeName; - - switch (name) { - case "#text": - continue; - - case "dc:creator": - case "dc:subject": - this._parseArray(entry); - - continue; - } - - this._metadataMap.set(name, entry.textContent.trim()); - } - } - } - - get serializable() { - return { - parsedData: this._metadataMap, - rawData: this._data - }; - } - -} - -exports.MetadataParser = MetadataParser; - -/***/ }), -/* 68 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.XMLParserErrorCode = exports.XMLParserBase = exports.SimpleXMLParser = exports.SimpleDOMNode = void 0; - -var _core_utils = __w_pdfjs_require__(9); - -const XMLParserErrorCode = { - NoError: 0, - EndOfDocument: -1, - UnterminatedCdat: -2, - UnterminatedXmlDeclaration: -3, - UnterminatedDoctypeDeclaration: -4, - UnterminatedComment: -5, - MalformedElement: -6, - OutOfMemory: -7, - UnterminatedAttributeValue: -8, - UnterminatedElement: -9, - ElementNeverBegun: -10 -}; -exports.XMLParserErrorCode = XMLParserErrorCode; - -function isWhitespace(s, index) { - const ch = s[index]; - return ch === " " || ch === "\n" || ch === "\r" || ch === "\t"; -} - -function isWhitespaceString(s) { - for (let i = 0, ii = s.length; i < ii; i++) { - if (!isWhitespace(s, i)) { - return false; - } - } - - return true; -} - -class XMLParserBase { - _resolveEntities(s) { - return s.replace(/&([^;]+);/g, (all, entity) => { - if (entity.substring(0, 2) === "#x") { - return String.fromCodePoint(parseInt(entity.substring(2), 16)); - } else if (entity.substring(0, 1) === "#") { - return String.fromCodePoint(parseInt(entity.substring(1), 10)); - } - - switch (entity) { - case "lt": - return "<"; - - case "gt": - return ">"; - - case "amp": - return "&"; - - case "quot": - return '"'; - - case "apos": - return "'"; - } - - return this.onResolveEntity(entity); - }); - } - - _parseContent(s, start) { - const attributes = []; - let pos = start; - - function skipWs() { - while (pos < s.length && isWhitespace(s, pos)) { - ++pos; - } - } - - while (pos < s.length && !isWhitespace(s, pos) && s[pos] !== ">" && s[pos] !== "/") { - ++pos; - } - - const name = s.substring(start, pos); - skipWs(); - - while (pos < s.length && s[pos] !== ">" && s[pos] !== "/" && s[pos] !== "?") { - skipWs(); - let attrName = "", - attrValue = ""; - - while (pos < s.length && !isWhitespace(s, pos) && s[pos] !== "=") { - attrName += s[pos]; - ++pos; - } - - skipWs(); - - if (s[pos] !== "=") { - return null; - } - - ++pos; - skipWs(); - const attrEndChar = s[pos]; - - if (attrEndChar !== '"' && attrEndChar !== "'") { - return null; - } - - const attrEndIndex = s.indexOf(attrEndChar, ++pos); - - if (attrEndIndex < 0) { - return null; - } - - attrValue = s.substring(pos, attrEndIndex); - attributes.push({ - name: attrName, - value: this._resolveEntities(attrValue) - }); - pos = attrEndIndex + 1; - skipWs(); - } - - return { - name, - attributes, - parsed: pos - start - }; - } - - _parseProcessingInstruction(s, start) { - let pos = start; - - function skipWs() { - while (pos < s.length && isWhitespace(s, pos)) { - ++pos; - } - } - - while (pos < s.length && !isWhitespace(s, pos) && s[pos] !== ">" && s[pos] !== "?" && s[pos] !== "/") { - ++pos; - } - - const name = s.substring(start, pos); - skipWs(); - const attrStart = pos; - - while (pos < s.length && (s[pos] !== "?" || s[pos + 1] !== ">")) { - ++pos; - } - - const value = s.substring(attrStart, pos); - return { - name, - value, - parsed: pos - start - }; - } - - parseXml(s) { - let i = 0; - - while (i < s.length) { - const ch = s[i]; - let j = i; - - if (ch === "<") { - ++j; - const ch2 = s[j]; - let q; - - switch (ch2) { - case "/": - ++j; - q = s.indexOf(">", j); - - if (q < 0) { - this.onError(XMLParserErrorCode.UnterminatedElement); - return; - } - - this.onEndElement(s.substring(j, q)); - j = q + 1; - break; - - case "?": - ++j; - - const pi = this._parseProcessingInstruction(s, j); - - if (s.substring(j + pi.parsed, j + pi.parsed + 2) !== "?>") { - this.onError(XMLParserErrorCode.UnterminatedXmlDeclaration); - return; - } - - this.onPi(pi.name, pi.value); - j += pi.parsed + 2; - break; - - case "!": - if (s.substring(j + 1, j + 3) === "--") { - q = s.indexOf("-->", j + 3); - - if (q < 0) { - this.onError(XMLParserErrorCode.UnterminatedComment); - return; - } - - this.onComment(s.substring(j + 3, q)); - j = q + 3; - } else if (s.substring(j + 1, j + 8) === "[CDATA[") { - q = s.indexOf("]]>", j + 8); - - if (q < 0) { - this.onError(XMLParserErrorCode.UnterminatedCdat); - return; - } - - this.onCdata(s.substring(j + 8, q)); - j = q + 3; - } else if (s.substring(j + 1, j + 8) === "DOCTYPE") { - const q2 = s.indexOf("[", j + 8); - let complexDoctype = false; - q = s.indexOf(">", j + 8); - - if (q < 0) { - this.onError(XMLParserErrorCode.UnterminatedDoctypeDeclaration); - return; - } - - if (q2 > 0 && q > q2) { - q = s.indexOf("]>", j + 8); - - if (q < 0) { - this.onError(XMLParserErrorCode.UnterminatedDoctypeDeclaration); - return; - } - - complexDoctype = true; - } - - const doctypeContent = s.substring(j + 8, q + (complexDoctype ? 1 : 0)); - this.onDoctype(doctypeContent); - j = q + (complexDoctype ? 2 : 1); - } else { - this.onError(XMLParserErrorCode.MalformedElement); - return; - } - - break; - - default: - const content = this._parseContent(s, j); - - if (content === null) { - this.onError(XMLParserErrorCode.MalformedElement); - return; - } - - let isClosed = false; - - if (s.substring(j + content.parsed, j + content.parsed + 2) === "/>") { - isClosed = true; - } else if (s.substring(j + content.parsed, j + content.parsed + 1) !== ">") { - this.onError(XMLParserErrorCode.UnterminatedElement); - return; - } - - this.onBeginElement(content.name, content.attributes, isClosed); - j += content.parsed + (isClosed ? 2 : 1); - break; - } - } else { - while (j < s.length && s[j] !== "<") { - j++; - } - - const text = s.substring(i, j); - this.onText(this._resolveEntities(text)); - } - - i = j; - } - } - - onResolveEntity(name) { - return `&${name};`; - } - - onPi(name, value) {} - - onComment(text) {} - - onCdata(text) {} - - onDoctype(doctypeContent) {} - - onText(text) {} - - onBeginElement(name, attributes, isEmpty) {} - - onEndElement(name) {} - - onError(code) {} - -} - -exports.XMLParserBase = XMLParserBase; - -class SimpleDOMNode { - constructor(nodeName, nodeValue) { - this.nodeName = nodeName; - this.nodeValue = nodeValue; - Object.defineProperty(this, "parentNode", { - value: null, - writable: true - }); - } - - get firstChild() { - return this.childNodes && this.childNodes[0]; - } - - get nextSibling() { - const childNodes = this.parentNode.childNodes; - - if (!childNodes) { - return undefined; - } - - const index = childNodes.indexOf(this); - - if (index === -1) { - return undefined; - } - - return childNodes[index + 1]; - } - - get textContent() { - if (!this.childNodes) { - return this.nodeValue || ""; - } - - return this.childNodes.map(function (child) { - return child.textContent; - }).join(""); - } - - hasChildNodes() { - return this.childNodes && this.childNodes.length > 0; - } - - searchNode(paths, pos) { - if (pos >= paths.length) { - return this; - } - - const component = paths[pos]; - const stack = []; - let node = this; - - while (true) { - if (component.name === node.nodeName) { - if (component.pos === 0) { - const res = node.searchNode(paths, pos + 1); - - if (res !== null) { - return res; - } - } else if (stack.length === 0) { - return null; - } else { - const [parent] = stack.pop(); - let siblingPos = 0; - - for (const child of parent.childNodes) { - if (component.name === child.nodeName) { - if (siblingPos === component.pos) { - return child.searchNode(paths, pos + 1); - } - - siblingPos++; - } - } - - return node.searchNode(paths, pos + 1); - } - } - - if (node.childNodes && node.childNodes.length !== 0) { - stack.push([node, 0]); - node = node.childNodes[0]; - } else if (stack.length === 0) { - return null; - } else { - while (stack.length !== 0) { - const [parent, currentPos] = stack.pop(); - const newPos = currentPos + 1; - - if (newPos < parent.childNodes.length) { - stack.push([parent, newPos]); - node = parent.childNodes[newPos]; - break; - } - } - - if (stack.length === 0) { - return null; - } - } - } - } - - dump(buffer) { - if (this.nodeName === "#text") { - buffer.push((0, _core_utils.encodeToXmlString)(this.nodeValue)); - return; - } - - buffer.push(`<${this.nodeName}`); - - if (this.attributes) { - for (const attribute of this.attributes) { - buffer.push(` ${attribute.name}="${(0, _core_utils.encodeToXmlString)(attribute.value)}"`); - } - } - - if (this.hasChildNodes()) { - buffer.push(">"); - - for (const child of this.childNodes) { - child.dump(buffer); - } - - buffer.push(``); - } else if (this.nodeValue) { - buffer.push(`>${(0, _core_utils.encodeToXmlString)(this.nodeValue)}`); - } else { - buffer.push("/>"); - } - } - -} - -exports.SimpleDOMNode = SimpleDOMNode; - -class SimpleXMLParser extends XMLParserBase { - constructor({ - hasAttributes = false, - lowerCaseName = false - }) { - super(); - this._currentFragment = null; - this._stack = null; - this._errorCode = XMLParserErrorCode.NoError; - this._hasAttributes = hasAttributes; - this._lowerCaseName = lowerCaseName; - } - - parseFromString(data) { - this._currentFragment = []; - this._stack = []; - this._errorCode = XMLParserErrorCode.NoError; - this.parseXml(data); - - if (this._errorCode !== XMLParserErrorCode.NoError) { - return undefined; - } - - const [documentElement] = this._currentFragment; - - if (!documentElement) { - return undefined; - } - - return { - documentElement - }; - } - - onText(text) { - if (isWhitespaceString(text)) { - return; - } - - const node = new SimpleDOMNode("#text", text); - - this._currentFragment.push(node); - } - - onCdata(text) { - const node = new SimpleDOMNode("#text", text); - - this._currentFragment.push(node); - } - - onBeginElement(name, attributes, isEmpty) { - if (this._lowerCaseName) { - name = name.toLowerCase(); - } - - const node = new SimpleDOMNode(name); - node.childNodes = []; - - if (this._hasAttributes) { - node.attributes = attributes; - } - - this._currentFragment.push(node); - - if (isEmpty) { - return; - } - - this._stack.push(this._currentFragment); - - this._currentFragment = node.childNodes; - } - - onEndElement(name) { - this._currentFragment = this._stack.pop() || []; - const lastElement = this._currentFragment[this._currentFragment.length - 1]; - - if (!lastElement) { - return; - } - - for (let i = 0, ii = lastElement.childNodes.length; i < ii; i++) { - lastElement.childNodes[i].parentNode = lastElement; - } - } - - onError(code) { - this._errorCode = code; - } - -} - -exports.SimpleXMLParser = SimpleXMLParser; - -/***/ }), -/* 69 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.StructTreeRoot = exports.StructTreePage = void 0; - -var _primitives = __w_pdfjs_require__(5); - -var _util = __w_pdfjs_require__(2); - -var _name_number_tree = __w_pdfjs_require__(65); - -const MAX_DEPTH = 40; -const StructElementType = { - PAGE_CONTENT: "PAGE_CONTENT", - STREAM_CONTENT: "STREAM_CONTENT", - OBJECT: "OBJECT", - ELEMENT: "ELEMENT" -}; - -class StructTreeRoot { - constructor(rootDict) { - this.dict = rootDict; - this.roleMap = new Map(); - } - - init() { - this.readRoleMap(); - } - - readRoleMap() { - const roleMapDict = this.dict.get("RoleMap"); - - if (!(0, _primitives.isDict)(roleMapDict)) { - return; - } - - roleMapDict.forEach((key, value) => { - if (!(0, _primitives.isName)(value)) { - return; - } - - this.roleMap.set(key, value.name); - }); - } - -} - -exports.StructTreeRoot = StructTreeRoot; - -class StructElementNode { - constructor(tree, dict) { - this.tree = tree; - this.dict = dict; - this.kids = []; - this.parseKids(); - } - - get role() { - const nameObj = this.dict.get("S"); - const name = (0, _primitives.isName)(nameObj) ? nameObj.name : ""; - const { - root - } = this.tree; - - if (root.roleMap.has(name)) { - return root.roleMap.get(name); - } - - return name; - } - - parseKids() { - let pageObjId = null; - const objRef = this.dict.getRaw("Pg"); - - if ((0, _primitives.isRef)(objRef)) { - pageObjId = objRef.toString(); - } - - const kids = this.dict.get("K"); - - if (Array.isArray(kids)) { - for (const kid of kids) { - const element = this.parseKid(pageObjId, kid); - - if (element) { - this.kids.push(element); - } - } - } else { - const element = this.parseKid(pageObjId, kids); - - if (element) { - this.kids.push(element); - } - } - } - - parseKid(pageObjId, kid) { - if (Number.isInteger(kid)) { - if (this.tree.pageDict.objId !== pageObjId) { - return null; - } - - return new StructElement({ - type: StructElementType.PAGE_CONTENT, - mcid: kid, - pageObjId - }); - } - - let kidDict = null; - - if ((0, _primitives.isRef)(kid)) { - kidDict = this.dict.xref.fetch(kid); - } else if ((0, _primitives.isDict)(kid)) { - kidDict = kid; - } - - if (!kidDict) { - return null; - } - - const pageRef = kidDict.getRaw("Pg"); - - if ((0, _primitives.isRef)(pageRef)) { - pageObjId = pageRef.toString(); - } - - const type = (0, _primitives.isName)(kidDict.get("Type")) ? kidDict.get("Type").name : null; - - if (type === "MCR") { - if (this.tree.pageDict.objId !== pageObjId) { - return null; - } - - return new StructElement({ - type: StructElementType.STREAM_CONTENT, - refObjId: (0, _primitives.isRef)(kidDict.getRaw("Stm")) ? kidDict.getRaw("Stm").toString() : null, - pageObjId, - mcid: kidDict.get("MCID") - }); - } - - if (type === "OBJR") { - if (this.tree.pageDict.objId !== pageObjId) { - return null; - } - - return new StructElement({ - type: StructElementType.OBJECT, - refObjId: (0, _primitives.isRef)(kidDict.getRaw("Obj")) ? kidDict.getRaw("Obj").toString() : null, - pageObjId - }); - } - - return new StructElement({ - type: StructElementType.ELEMENT, - dict: kidDict - }); - } - -} - -class StructElement { - constructor({ - type, - dict = null, - mcid = null, - pageObjId = null, - refObjId = null - }) { - this.type = type; - this.dict = dict; - this.mcid = mcid; - this.pageObjId = pageObjId; - this.refObjId = refObjId; - this.parentNode = null; - } - -} - -class StructTreePage { - constructor(structTreeRoot, pageDict) { - this.root = structTreeRoot; - this.rootDict = structTreeRoot ? structTreeRoot.dict : null; - this.pageDict = pageDict; - this.nodes = []; - } - - parse() { - if (!this.root || !this.rootDict) { - return; - } - - const parentTree = this.rootDict.get("ParentTree"); - - if (!parentTree) { - return; - } - - const id = this.pageDict.get("StructParents"); - - if (!Number.isInteger(id)) { - return; - } - - const numberTree = new _name_number_tree.NumberTree(parentTree, this.rootDict.xref); - const parentArray = numberTree.get(id); - - if (!Array.isArray(parentArray)) { - return; - } - - const map = new Map(); - - for (const ref of parentArray) { - if ((0, _primitives.isRef)(ref)) { - this.addNode(this.rootDict.xref.fetch(ref), map); - } - } - } - - addNode(dict, map, level = 0) { - if (level > MAX_DEPTH) { - (0, _util.warn)("StructTree MAX_DEPTH reached."); - return null; - } - - if (map.has(dict)) { - return map.get(dict); - } - - const element = new StructElementNode(this, dict); - map.set(dict, element); - const parent = dict.get("P"); - - if (!parent || (0, _primitives.isName)(parent.get("Type"), "StructTreeRoot")) { - if (!this.addTopLevelNode(dict, element)) { - map.delete(dict); - } - - return element; - } - - const parentNode = this.addNode(parent, map, level + 1); - - if (!parentNode) { - return element; - } - - let save = false; - - for (const kid of parentNode.kids) { - if (kid.type === StructElementType.ELEMENT && kid.dict === dict) { - kid.parentNode = element; - save = true; - } - } - - if (!save) { - map.delete(dict); - } - - return element; - } - - addTopLevelNode(dict, element) { - const obj = this.rootDict.get("K"); - - if (!obj) { - return false; - } - - if ((0, _primitives.isDict)(obj)) { - if (obj.objId !== dict.objId) { - return false; - } - - this.nodes[0] = element; - return true; - } - - if (!Array.isArray(obj)) { - return true; - } - - let save = false; - - for (let i = 0; i < obj.length; i++) { - const kidRef = obj[i]; - - if (kidRef && kidRef.toString() === dict.objId) { - this.nodes[i] = element; - save = true; - } - } - - return save; - } - - get serializable() { - function nodeToSerializable(node, parent, level = 0) { - if (level > MAX_DEPTH) { - (0, _util.warn)("StructTree too deep to be fully serialized."); - return; - } - - const obj = Object.create(null); - obj.role = node.role; - obj.children = []; - parent.children.push(obj); - const alt = node.dict.get("Alt"); - - if ((0, _util.isString)(alt)) { - obj.alt = (0, _util.stringToPDFString)(alt); - } - - const lang = node.dict.get("Lang"); - - if ((0, _util.isString)(lang)) { - obj.lang = (0, _util.stringToPDFString)(lang); - } - - for (const kid of node.kids) { - const kidElement = kid.type === StructElementType.ELEMENT ? kid.parentNode : null; - - if (kidElement) { - nodeToSerializable(kidElement, obj, level + 1); - continue; - } else if (kid.type === StructElementType.PAGE_CONTENT || kid.type === StructElementType.STREAM_CONTENT) { - obj.children.push({ - type: "content", - id: `page${kid.pageObjId}_mcid${kid.mcid}` - }); - } else if (kid.type === StructElementType.OBJECT) { - obj.children.push({ - type: "object", - id: kid.refObjId - }); - } - } - } - - const root = Object.create(null); - root.children = []; - root.role = "Root"; - - for (const child of this.nodes) { - if (!child) { - continue; - } - - nodeToSerializable(child, root); - } - - return root; - } - -} - -exports.StructTreePage = StructTreePage; - -/***/ }), -/* 70 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.ObjectLoader = void 0; - -var _primitives = __w_pdfjs_require__(5); - -var _core_utils = __w_pdfjs_require__(9); - -var _util = __w_pdfjs_require__(2); - -function mayHaveChildren(value) { - return value instanceof _primitives.Ref || value instanceof _primitives.Dict || Array.isArray(value) || (0, _primitives.isStream)(value); -} - -function addChildren(node, nodesToVisit) { - if (node instanceof _primitives.Dict) { - node = node.getRawValues(); - } else if ((0, _primitives.isStream)(node)) { - node = node.dict.getRawValues(); - } else if (!Array.isArray(node)) { - return; - } - - for (const rawValue of node) { - if (mayHaveChildren(rawValue)) { - nodesToVisit.push(rawValue); - } - } -} - -class ObjectLoader { - constructor(dict, keys, xref) { - this.dict = dict; - this.keys = keys; - this.xref = xref; - this.refSet = null; - } - - async load() { - if (this.xref.stream.isDataLoaded) { - return undefined; - } - - const { - keys, - dict - } = this; - this.refSet = new _primitives.RefSet(); - const nodesToVisit = []; - - for (let i = 0, ii = keys.length; i < ii; i++) { - const rawValue = dict.getRaw(keys[i]); - - if (rawValue !== undefined) { - nodesToVisit.push(rawValue); - } - } - - return this._walk(nodesToVisit); - } - - async _walk(nodesToVisit) { - const nodesToRevisit = []; - const pendingRequests = []; - - while (nodesToVisit.length) { - let currentNode = nodesToVisit.pop(); - - if (currentNode instanceof _primitives.Ref) { - if (this.refSet.has(currentNode)) { - continue; - } - - try { - this.refSet.put(currentNode); - currentNode = this.xref.fetch(currentNode); - } catch (ex) { - if (!(ex instanceof _core_utils.MissingDataException)) { - (0, _util.warn)(`ObjectLoader._walk - requesting all data: "${ex}".`); - this.refSet = null; - const { - manager - } = this.xref.stream; - return manager.requestAllChunks(); - } - - nodesToRevisit.push(currentNode); - pendingRequests.push({ - begin: ex.begin, - end: ex.end - }); - } - } - - if ((0, _primitives.isStream)(currentNode)) { - const baseStreams = currentNode.getBaseStreams(); - - if (baseStreams) { - let foundMissingData = false; - - for (const stream of baseStreams) { - if (stream.isDataLoaded) { - continue; - } - - foundMissingData = true; - pendingRequests.push({ - begin: stream.start, - end: stream.end - }); - } - - if (foundMissingData) { - nodesToRevisit.push(currentNode); - } - } - } - - addChildren(currentNode, nodesToVisit); - } - - if (pendingRequests.length) { - await this.xref.stream.manager.requestRanges(pendingRequests); - - for (const node of nodesToRevisit) { - if (node instanceof _primitives.Ref) { - this.refSet.remove(node); - } - } - - return this._walk(nodesToRevisit); - } - - this.refSet = null; - return undefined; - } - -} - -exports.ObjectLoader = ObjectLoader; - -/***/ }), -/* 71 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.incrementalUpdate = incrementalUpdate; -exports.writeDict = writeDict; - -var _util = __w_pdfjs_require__(2); - -var _primitives = __w_pdfjs_require__(5); - -var _core_utils = __w_pdfjs_require__(9); - -var _xml_parser = __w_pdfjs_require__(68); - -var _crypto = __w_pdfjs_require__(72); - -function writeDict(dict, buffer, transform) { - buffer.push("<<"); - - for (const key of dict.getKeys()) { - buffer.push(` /${(0, _core_utils.escapePDFName)(key)} `); - writeValue(dict.getRaw(key), buffer, transform); - } - - buffer.push(">>"); -} - -function writeStream(stream, buffer, transform) { - writeDict(stream.dict, buffer, transform); - buffer.push(" stream\n"); - let string = stream.getString(); - - if (transform !== null) { - string = transform.encryptString(string); - } - - buffer.push(string, "\nendstream\n"); -} - -function writeArray(array, buffer, transform) { - buffer.push("["); - let first = true; - - for (const val of array) { - if (!first) { - buffer.push(" "); - } else { - first = false; - } - - writeValue(val, buffer, transform); - } - - buffer.push("]"); -} - -function numberToString(value) { - if (Number.isInteger(value)) { - return value.toString(); - } - - const roundedValue = Math.round(value * 100); - - if (roundedValue % 100 === 0) { - return (roundedValue / 100).toString(); - } - - if (roundedValue % 10 === 0) { - return value.toFixed(1); - } - - return value.toFixed(2); -} - -function writeValue(value, buffer, transform) { - if ((0, _primitives.isName)(value)) { - buffer.push(`/${(0, _core_utils.escapePDFName)(value.name)}`); - } else if ((0, _primitives.isRef)(value)) { - buffer.push(`${value.num} ${value.gen} R`); - } else if (Array.isArray(value)) { - writeArray(value, buffer, transform); - } else if (typeof value === "string") { - if (transform !== null) { - value = transform.encryptString(value); - } - - buffer.push(`(${(0, _util.escapeString)(value)})`); - } else if (typeof value === "number") { - buffer.push(numberToString(value)); - } else if (typeof value === "boolean") { - buffer.push(value.toString()); - } else if ((0, _primitives.isDict)(value)) { - writeDict(value, buffer, transform); - } else if ((0, _primitives.isStream)(value)) { - writeStream(value, buffer, transform); - } else if (value === null) { - buffer.push("null"); - } else { - (0, _util.warn)(`Unhandled value in writer: ${typeof value}, please file a bug.`); - } -} - -function writeInt(number, size, offset, buffer) { - for (let i = size + offset - 1; i > offset - 1; i--) { - buffer[i] = number & 0xff; - number >>= 8; - } - - return offset + size; -} - -function writeString(string, offset, buffer) { - for (let i = 0, len = string.length; i < len; i++) { - buffer[offset + i] = string.charCodeAt(i) & 0xff; - } -} - -function computeMD5(filesize, xrefInfo) { - const time = Math.floor(Date.now() / 1000); - const filename = xrefInfo.filename || ""; - const md5Buffer = [time.toString(), filename, filesize.toString()]; - let md5BufferLen = md5Buffer.reduce((a, str) => a + str.length, 0); - - for (const value of Object.values(xrefInfo.info)) { - md5Buffer.push(value); - md5BufferLen += value.length; - } - - const array = new Uint8Array(md5BufferLen); - let offset = 0; - - for (const str of md5Buffer) { - writeString(str, offset, array); - offset += str.length; - } - - return (0, _util.bytesToString)((0, _crypto.calculateMD5)(array)); -} - -function writeXFADataForAcroform(str, newRefs) { - const xml = new _xml_parser.SimpleXMLParser({ - hasAttributes: true - }).parseFromString(str); - - for (const { - xfa - } of newRefs) { - if (!xfa) { - continue; - } - - const { - path, - value - } = xfa; - - if (!path) { - continue; - } - - const node = xml.documentElement.searchNode((0, _core_utils.parseXFAPath)(path), 0); - - if (node) { - node.childNodes = [new _xml_parser.SimpleDOMNode("#text", value)]; - } else { - (0, _util.warn)(`Node not found for path: ${path}`); - } - } - - const buffer = []; - xml.documentElement.dump(buffer); - return buffer.join(""); -} - -function updateXFA({ - xfaData, - xfaDatasetsRef, - hasXfaDatasetsEntry, - acroFormRef, - acroForm, - newRefs, - xref, - xrefInfo -}) { - if (xref === null) { - return; - } - - if (!hasXfaDatasetsEntry) { - if (!acroFormRef) { - (0, _util.warn)("XFA - Cannot save it"); - return; - } - - const oldXfa = acroForm.get("XFA"); - const newXfa = oldXfa.slice(); - newXfa.splice(2, 0, "datasets"); - newXfa.splice(3, 0, xfaDatasetsRef); - acroForm.set("XFA", newXfa); - const encrypt = xref.encrypt; - let transform = null; - - if (encrypt) { - transform = encrypt.createCipherTransform(acroFormRef.num, acroFormRef.gen); - } - - const buffer = [`${acroFormRef.num} ${acroFormRef.gen} obj\n`]; - writeDict(acroForm, buffer, transform); - buffer.push("\n"); - acroForm.set("XFA", oldXfa); - newRefs.push({ - ref: acroFormRef, - data: buffer.join("") - }); - } - - if (xfaData === null) { - const datasets = xref.fetchIfRef(xfaDatasetsRef); - xfaData = writeXFADataForAcroform(datasets.getString(), newRefs); - } - - const encrypt = xref.encrypt; - - if (encrypt) { - const transform = encrypt.createCipherTransform(xfaDatasetsRef.num, xfaDatasetsRef.gen); - xfaData = transform.encryptString(xfaData); - } - - const data = `${xfaDatasetsRef.num} ${xfaDatasetsRef.gen} obj\n` + `<< /Type /EmbeddedFile /Length ${xfaData.length}>>\nstream\n` + xfaData + "\nendstream\nendobj\n"; - newRefs.push({ - ref: xfaDatasetsRef, - data - }); -} - -function incrementalUpdate({ - originalData, - xrefInfo, - newRefs, - xref = null, - hasXfa = false, - xfaDatasetsRef = null, - hasXfaDatasetsEntry = false, - acroFormRef = null, - acroForm = null, - xfaData = null -}) { - if (hasXfa) { - updateXFA({ - xfaData, - xfaDatasetsRef, - hasXfaDatasetsEntry, - acroFormRef, - acroForm, - newRefs, - xref, - xrefInfo - }); - } - - const newXref = new _primitives.Dict(null); - const refForXrefTable = xrefInfo.newRef; - let buffer, baseOffset; - const lastByte = originalData[originalData.length - 1]; - - if (lastByte === 0x0a || lastByte === 0x0d) { - buffer = []; - baseOffset = originalData.length; - } else { - buffer = ["\n"]; - baseOffset = originalData.length + 1; - } - - newXref.set("Size", refForXrefTable.num + 1); - newXref.set("Prev", xrefInfo.startXRef); - newXref.set("Type", _primitives.Name.get("XRef")); - - if (xrefInfo.rootRef !== null) { - newXref.set("Root", xrefInfo.rootRef); - } - - if (xrefInfo.infoRef !== null) { - newXref.set("Info", xrefInfo.infoRef); - } - - if (xrefInfo.encryptRef !== null) { - newXref.set("Encrypt", xrefInfo.encryptRef); - } - - newRefs.push({ - ref: refForXrefTable, - data: "" - }); - newRefs = newRefs.sort((a, b) => { - return a.ref.num - b.ref.num; - }); - const xrefTableData = [[0, 1, 0xffff]]; - const indexes = [0, 1]; - let maxOffset = 0; - - for (const { - ref, - data - } of newRefs) { - maxOffset = Math.max(maxOffset, baseOffset); - xrefTableData.push([1, baseOffset, Math.min(ref.gen, 0xffff)]); - baseOffset += data.length; - indexes.push(ref.num, 1); - buffer.push(data); - } - - newXref.set("Index", indexes); - - if (Array.isArray(xrefInfo.fileIds) && xrefInfo.fileIds.length > 0) { - const md5 = computeMD5(baseOffset, xrefInfo); - newXref.set("ID", [xrefInfo.fileIds[0], md5]); - } - - const offsetSize = Math.ceil(Math.log2(maxOffset) / 8); - const sizes = [1, offsetSize, 2]; - const structSize = sizes[0] + sizes[1] + sizes[2]; - const tableLength = structSize * xrefTableData.length; - newXref.set("W", sizes); - newXref.set("Length", tableLength); - buffer.push(`${refForXrefTable.num} ${refForXrefTable.gen} obj\n`); - writeDict(newXref, buffer, null); - buffer.push(" stream\n"); - const bufferLen = buffer.reduce((a, str) => a + str.length, 0); - const footer = `\nendstream\nendobj\nstartxref\n${baseOffset}\n%%EOF\n`; - const array = new Uint8Array(originalData.length + bufferLen + tableLength + footer.length); - array.set(originalData); - let offset = originalData.length; - - for (const str of buffer) { - writeString(str, offset, array); - offset += str.length; - } - - for (const [type, objOffset, gen] of xrefTableData) { - offset = writeInt(type, sizes[0], offset, array); - offset = writeInt(objOffset, sizes[1], offset, array); - offset = writeInt(gen, sizes[2], offset, array); - } - - writeString(footer, offset, array); - return array; -} - -/***/ }), -/* 72 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.calculateSHA256 = exports.calculateMD5 = exports.PDF20 = exports.PDF17 = exports.CipherTransformFactory = exports.ARCFourCipher = exports.AES256Cipher = exports.AES128Cipher = void 0; -exports.calculateSHA384 = calculateSHA384; -exports.calculateSHA512 = void 0; - -var _util = __w_pdfjs_require__(2); - -var _primitives = __w_pdfjs_require__(5); - -var _decrypt_stream = __w_pdfjs_require__(73); - -class ARCFourCipher { - constructor(key) { - this.a = 0; - this.b = 0; - const s = new Uint8Array(256); - const keyLength = key.length; - - for (let i = 0; i < 256; ++i) { - s[i] = i; - } - - for (let i = 0, j = 0; i < 256; ++i) { - const tmp = s[i]; - j = j + tmp + key[i % keyLength] & 0xff; - s[i] = s[j]; - s[j] = tmp; - } - - this.s = s; - } - - encryptBlock(data) { - let a = this.a, - b = this.b; - const s = this.s; - const n = data.length; - const output = new Uint8Array(n); - - for (let i = 0; i < n; ++i) { - a = a + 1 & 0xff; - const tmp = s[a]; - b = b + tmp & 0xff; - const 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; - } - - decryptBlock(data) { - return this.encryptBlock(data); - } - - encrypt(data) { - return this.encryptBlock(data); - } - -} - -exports.ARCFourCipher = ARCFourCipher; - -const calculateMD5 = function calculateMD5Closure() { - const 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]); - const 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) { - let h0 = 1732584193, - h1 = -271733879, - h2 = -1732584194, - h3 = 271733878; - const paddedLength = length + 72 & ~63; - const padded = new Uint8Array(paddedLength); - let i, j; - - for (i = 0; i < length; ++i) { - padded[i] = data[offset++]; - } - - padded[i++] = 0x80; - const 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; - const 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; - } - - let 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; - } - - const 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; -}(); - -exports.calculateMD5 = calculateMD5; - -class Word64 { - constructor(highInteger, lowInteger) { - this.high = highInteger | 0; - this.low = lowInteger | 0; - } - - and(word) { - this.high &= word.high; - this.low &= word.low; - } - - xor(word) { - this.high ^= word.high; - this.low ^= word.low; - } - - or(word) { - this.high |= word.high; - this.low |= word.low; - } - - shiftRight(places) { - if (places >= 32) { - this.low = this.high >>> places - 32 | 0; - this.high = 0; - } else { - this.low = this.low >>> places | this.high << 32 - places; - this.high = this.high >>> places | 0; - } - } - - shiftLeft(places) { - if (places >= 32) { - this.high = this.low << places - 32; - this.low = 0; - } else { - this.high = this.high << places | this.low >>> 32 - places; - this.low <<= places; - } - } - - rotateRight(places) { - let low, high; - - if (places & 32) { - high = this.low; - low = this.high; - } else { - low = this.low; - high = this.high; - } - - places &= 31; - this.low = low >>> places | high << 32 - places; - this.high = high >>> places | low << 32 - places; - } - - not() { - this.high = ~this.high; - this.low = ~this.low; - } - - add(word) { - const lowAdd = (this.low >>> 0) + (word.low >>> 0); - let highAdd = (this.high >>> 0) + (word.high >>> 0); - - if (lowAdd > 0xffffffff) { - highAdd += 1; - } - - this.low = lowAdd | 0; - this.high = highAdd | 0; - } - - copyTo(bytes, offset) { - bytes[offset] = this.high >>> 24 & 0xff; - bytes[offset + 1] = this.high >> 16 & 0xff; - bytes[offset + 2] = this.high >> 8 & 0xff; - bytes[offset + 3] = this.high & 0xff; - bytes[offset + 4] = this.low >>> 24 & 0xff; - bytes[offset + 5] = this.low >> 16 & 0xff; - bytes[offset + 6] = this.low >> 8 & 0xff; - bytes[offset + 7] = this.low & 0xff; - } - - assign(word) { - this.high = word.high; - this.low = word.low; - } - -} - -const calculateSHA256 = function calculateSHA256Closure() { - function rotr(x, n) { - return x >>> n | x << 32 - n; - } - - function ch(x, y, z) { - return x & y ^ ~x & z; - } - - function maj(x, y, z) { - return x & y ^ x & z ^ y & z; - } - - function sigma(x) { - return rotr(x, 2) ^ rotr(x, 13) ^ rotr(x, 22); - } - - function sigmaPrime(x) { - return rotr(x, 6) ^ rotr(x, 11) ^ rotr(x, 25); - } - - function littleSigma(x) { - return rotr(x, 7) ^ rotr(x, 18) ^ x >>> 3; - } - - function littleSigmaPrime(x) { - return rotr(x, 17) ^ rotr(x, 19) ^ x >>> 10; - } - - const k = [0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2]; - - function hash(data, offset, length) { - let h0 = 0x6a09e667, - h1 = 0xbb67ae85, - h2 = 0x3c6ef372, - h3 = 0xa54ff53a, - h4 = 0x510e527f, - h5 = 0x9b05688c, - h6 = 0x1f83d9ab, - h7 = 0x5be0cd19; - const paddedLength = Math.ceil((length + 9) / 64) * 64; - const padded = new Uint8Array(paddedLength); - let i, j; - - for (i = 0; i < length; ++i) { - padded[i] = data[offset++]; - } - - padded[i++] = 0x80; - const n = paddedLength - 8; - - while (i < n) { - padded[i++] = 0; - } - - padded[i++] = 0; - padded[i++] = 0; - padded[i++] = 0; - padded[i++] = length >>> 29 & 0xff; - padded[i++] = length >> 21 & 0xff; - padded[i++] = length >> 13 & 0xff; - padded[i++] = length >> 5 & 0xff; - padded[i++] = length << 3 & 0xff; - const w = new Uint32Array(64); - - for (i = 0; i < paddedLength;) { - for (j = 0; j < 16; ++j) { - w[j] = padded[i] << 24 | padded[i + 1] << 16 | padded[i + 2] << 8 | padded[i + 3]; - i += 4; - } - - for (j = 16; j < 64; ++j) { - w[j] = littleSigmaPrime(w[j - 2]) + w[j - 7] + littleSigma(w[j - 15]) + w[j - 16] | 0; - } - - let a = h0, - b = h1, - c = h2, - d = h3, - e = h4, - f = h5, - g = h6, - h = h7, - t1, - t2; - - for (j = 0; j < 64; ++j) { - t1 = h + sigmaPrime(e) + ch(e, f, g) + k[j] + w[j]; - t2 = sigma(a) + maj(a, b, c); - h = g; - g = f; - f = e; - e = d + t1 | 0; - d = c; - c = b; - b = a; - a = t1 + t2 | 0; - } - - h0 = h0 + a | 0; - h1 = h1 + b | 0; - h2 = h2 + c | 0; - h3 = h3 + d | 0; - h4 = h4 + e | 0; - h5 = h5 + f | 0; - h6 = h6 + g | 0; - h7 = h7 + h | 0; - } - - return new Uint8Array([h0 >> 24 & 0xFF, h0 >> 16 & 0xFF, h0 >> 8 & 0xFF, h0 & 0xFF, h1 >> 24 & 0xFF, h1 >> 16 & 0xFF, h1 >> 8 & 0xFF, h1 & 0xFF, h2 >> 24 & 0xFF, h2 >> 16 & 0xFF, h2 >> 8 & 0xFF, h2 & 0xFF, h3 >> 24 & 0xFF, h3 >> 16 & 0xFF, h3 >> 8 & 0xFF, h3 & 0xFF, h4 >> 24 & 0xFF, h4 >> 16 & 0xFF, h4 >> 8 & 0xFF, h4 & 0xFF, h5 >> 24 & 0xFF, h5 >> 16 & 0xFF, h5 >> 8 & 0xFF, h5 & 0xFF, h6 >> 24 & 0xFF, h6 >> 16 & 0xFF, h6 >> 8 & 0xFF, h6 & 0xFF, h7 >> 24 & 0xFF, h7 >> 16 & 0xFF, h7 >> 8 & 0xFF, h7 & 0xFF]); - } - - return hash; -}(); - -exports.calculateSHA256 = calculateSHA256; - -const calculateSHA512 = function calculateSHA512Closure() { - function ch(result, x, y, z, tmp) { - result.assign(x); - result.and(y); - tmp.assign(x); - tmp.not(); - tmp.and(z); - result.xor(tmp); - } - - function maj(result, x, y, z, tmp) { - result.assign(x); - result.and(y); - tmp.assign(x); - tmp.and(z); - result.xor(tmp); - tmp.assign(y); - tmp.and(z); - result.xor(tmp); - } - - function sigma(result, x, tmp) { - result.assign(x); - result.rotateRight(28); - tmp.assign(x); - tmp.rotateRight(34); - result.xor(tmp); - tmp.assign(x); - tmp.rotateRight(39); - result.xor(tmp); - } - - function sigmaPrime(result, x, tmp) { - result.assign(x); - result.rotateRight(14); - tmp.assign(x); - tmp.rotateRight(18); - result.xor(tmp); - tmp.assign(x); - tmp.rotateRight(41); - result.xor(tmp); - } - - function littleSigma(result, x, tmp) { - result.assign(x); - result.rotateRight(1); - tmp.assign(x); - tmp.rotateRight(8); - result.xor(tmp); - tmp.assign(x); - tmp.shiftRight(7); - result.xor(tmp); - } - - function littleSigmaPrime(result, x, tmp) { - result.assign(x); - result.rotateRight(19); - tmp.assign(x); - tmp.rotateRight(61); - result.xor(tmp); - tmp.assign(x); - tmp.shiftRight(6); - result.xor(tmp); - } - - const k = [new Word64(0x428a2f98, 0xd728ae22), new Word64(0x71374491, 0x23ef65cd), new Word64(0xb5c0fbcf, 0xec4d3b2f), new Word64(0xe9b5dba5, 0x8189dbbc), new Word64(0x3956c25b, 0xf348b538), new Word64(0x59f111f1, 0xb605d019), new Word64(0x923f82a4, 0xaf194f9b), new Word64(0xab1c5ed5, 0xda6d8118), new Word64(0xd807aa98, 0xa3030242), new Word64(0x12835b01, 0x45706fbe), new Word64(0x243185be, 0x4ee4b28c), new Word64(0x550c7dc3, 0xd5ffb4e2), new Word64(0x72be5d74, 0xf27b896f), new Word64(0x80deb1fe, 0x3b1696b1), new Word64(0x9bdc06a7, 0x25c71235), new Word64(0xc19bf174, 0xcf692694), new Word64(0xe49b69c1, 0x9ef14ad2), new Word64(0xefbe4786, 0x384f25e3), new Word64(0x0fc19dc6, 0x8b8cd5b5), new Word64(0x240ca1cc, 0x77ac9c65), new Word64(0x2de92c6f, 0x592b0275), new Word64(0x4a7484aa, 0x6ea6e483), new Word64(0x5cb0a9dc, 0xbd41fbd4), new Word64(0x76f988da, 0x831153b5), new Word64(0x983e5152, 0xee66dfab), new Word64(0xa831c66d, 0x2db43210), new Word64(0xb00327c8, 0x98fb213f), new Word64(0xbf597fc7, 0xbeef0ee4), new Word64(0xc6e00bf3, 0x3da88fc2), new Word64(0xd5a79147, 0x930aa725), new Word64(0x06ca6351, 0xe003826f), new Word64(0x14292967, 0x0a0e6e70), new Word64(0x27b70a85, 0x46d22ffc), new Word64(0x2e1b2138, 0x5c26c926), new Word64(0x4d2c6dfc, 0x5ac42aed), new Word64(0x53380d13, 0x9d95b3df), new Word64(0x650a7354, 0x8baf63de), new Word64(0x766a0abb, 0x3c77b2a8), new Word64(0x81c2c92e, 0x47edaee6), new Word64(0x92722c85, 0x1482353b), new Word64(0xa2bfe8a1, 0x4cf10364), new Word64(0xa81a664b, 0xbc423001), new Word64(0xc24b8b70, 0xd0f89791), new Word64(0xc76c51a3, 0x0654be30), new Word64(0xd192e819, 0xd6ef5218), new Word64(0xd6990624, 0x5565a910), new Word64(0xf40e3585, 0x5771202a), new Word64(0x106aa070, 0x32bbd1b8), new Word64(0x19a4c116, 0xb8d2d0c8), new Word64(0x1e376c08, 0x5141ab53), new Word64(0x2748774c, 0xdf8eeb99), new Word64(0x34b0bcb5, 0xe19b48a8), new Word64(0x391c0cb3, 0xc5c95a63), new Word64(0x4ed8aa4a, 0xe3418acb), new Word64(0x5b9cca4f, 0x7763e373), new Word64(0x682e6ff3, 0xd6b2b8a3), new Word64(0x748f82ee, 0x5defb2fc), new Word64(0x78a5636f, 0x43172f60), new Word64(0x84c87814, 0xa1f0ab72), new Word64(0x8cc70208, 0x1a6439ec), new Word64(0x90befffa, 0x23631e28), new Word64(0xa4506ceb, 0xde82bde9), new Word64(0xbef9a3f7, 0xb2c67915), new Word64(0xc67178f2, 0xe372532b), new Word64(0xca273ece, 0xea26619c), new Word64(0xd186b8c7, 0x21c0c207), new Word64(0xeada7dd6, 0xcde0eb1e), new Word64(0xf57d4f7f, 0xee6ed178), new Word64(0x06f067aa, 0x72176fba), new Word64(0x0a637dc5, 0xa2c898a6), new Word64(0x113f9804, 0xbef90dae), new Word64(0x1b710b35, 0x131c471b), new Word64(0x28db77f5, 0x23047d84), new Word64(0x32caab7b, 0x40c72493), new Word64(0x3c9ebe0a, 0x15c9bebc), new Word64(0x431d67c4, 0x9c100d4c), new Word64(0x4cc5d4be, 0xcb3e42b6), new Word64(0x597f299c, 0xfc657e2a), new Word64(0x5fcb6fab, 0x3ad6faec), new Word64(0x6c44198c, 0x4a475817)]; - - function hash(data, offset, length, mode384 = false) { - let h0, h1, h2, h3, h4, h5, h6, h7; - - if (!mode384) { - h0 = new Word64(0x6a09e667, 0xf3bcc908); - h1 = new Word64(0xbb67ae85, 0x84caa73b); - h2 = new Word64(0x3c6ef372, 0xfe94f82b); - h3 = new Word64(0xa54ff53a, 0x5f1d36f1); - h4 = new Word64(0x510e527f, 0xade682d1); - h5 = new Word64(0x9b05688c, 0x2b3e6c1f); - h6 = new Word64(0x1f83d9ab, 0xfb41bd6b); - h7 = new Word64(0x5be0cd19, 0x137e2179); - } else { - h0 = new Word64(0xcbbb9d5d, 0xc1059ed8); - h1 = new Word64(0x629a292a, 0x367cd507); - h2 = new Word64(0x9159015a, 0x3070dd17); - h3 = new Word64(0x152fecd8, 0xf70e5939); - h4 = new Word64(0x67332667, 0xffc00b31); - h5 = new Word64(0x8eb44a87, 0x68581511); - h6 = new Word64(0xdb0c2e0d, 0x64f98fa7); - h7 = new Word64(0x47b5481d, 0xbefa4fa4); - } - - const paddedLength = Math.ceil((length + 17) / 128) * 128; - const padded = new Uint8Array(paddedLength); - let i, j; - - for (i = 0; i < length; ++i) { - padded[i] = data[offset++]; - } - - padded[i++] = 0x80; - const n = paddedLength - 16; - - while (i < n) { - padded[i++] = 0; - } - - padded[i++] = 0; - padded[i++] = 0; - padded[i++] = 0; - padded[i++] = 0; - padded[i++] = 0; - padded[i++] = 0; - padded[i++] = 0; - padded[i++] = 0; - padded[i++] = 0; - padded[i++] = 0; - padded[i++] = 0; - padded[i++] = length >>> 29 & 0xff; - padded[i++] = length >> 21 & 0xff; - padded[i++] = length >> 13 & 0xff; - padded[i++] = length >> 5 & 0xff; - padded[i++] = length << 3 & 0xff; - const w = new Array(80); - - for (i = 0; i < 80; i++) { - w[i] = new Word64(0, 0); - } - - let a = new Word64(0, 0), - b = new Word64(0, 0), - c = new Word64(0, 0); - let d = new Word64(0, 0), - e = new Word64(0, 0), - f = new Word64(0, 0); - let g = new Word64(0, 0), - h = new Word64(0, 0); - const t1 = new Word64(0, 0), - t2 = new Word64(0, 0); - const tmp1 = new Word64(0, 0), - tmp2 = new Word64(0, 0); - let tmp3; - - for (i = 0; i < paddedLength;) { - for (j = 0; j < 16; ++j) { - w[j].high = padded[i] << 24 | padded[i + 1] << 16 | padded[i + 2] << 8 | padded[i + 3]; - w[j].low = padded[i + 4] << 24 | padded[i + 5] << 16 | padded[i + 6] << 8 | padded[i + 7]; - i += 8; - } - - for (j = 16; j < 80; ++j) { - tmp3 = w[j]; - littleSigmaPrime(tmp3, w[j - 2], tmp2); - tmp3.add(w[j - 7]); - littleSigma(tmp1, w[j - 15], tmp2); - tmp3.add(tmp1); - tmp3.add(w[j - 16]); - } - - a.assign(h0); - b.assign(h1); - c.assign(h2); - d.assign(h3); - e.assign(h4); - f.assign(h5); - g.assign(h6); - h.assign(h7); - - for (j = 0; j < 80; ++j) { - t1.assign(h); - sigmaPrime(tmp1, e, tmp2); - t1.add(tmp1); - ch(tmp1, e, f, g, tmp2); - t1.add(tmp1); - t1.add(k[j]); - t1.add(w[j]); - sigma(t2, a, tmp2); - maj(tmp1, a, b, c, tmp2); - t2.add(tmp1); - tmp3 = h; - h = g; - g = f; - f = e; - d.add(t1); - e = d; - d = c; - c = b; - b = a; - tmp3.assign(t1); - tmp3.add(t2); - a = tmp3; - } - - h0.add(a); - h1.add(b); - h2.add(c); - h3.add(d); - h4.add(e); - h5.add(f); - h6.add(g); - h7.add(h); - } - - let result; - - if (!mode384) { - result = new Uint8Array(64); - h0.copyTo(result, 0); - h1.copyTo(result, 8); - h2.copyTo(result, 16); - h3.copyTo(result, 24); - h4.copyTo(result, 32); - h5.copyTo(result, 40); - h6.copyTo(result, 48); - h7.copyTo(result, 56); - } else { - result = new Uint8Array(48); - h0.copyTo(result, 0); - h1.copyTo(result, 8); - h2.copyTo(result, 16); - h3.copyTo(result, 24); - h4.copyTo(result, 32); - h5.copyTo(result, 40); - } - - return result; - } - - return hash; -}(); - -exports.calculateSHA512 = calculateSHA512; - -function calculateSHA384(data, offset, length) { - return calculateSHA512(data, offset, length, true); -} - -class NullCipher { - decryptBlock(data) { - return data; - } - - encrypt(data) { - return data; - } - -} - -class AESBaseCipher { - constructor() { - if (this.constructor === AESBaseCipher) { - (0, _util.unreachable)("Cannot initialize AESBaseCipher."); - } - - this._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]); - this._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]); - this._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]); - this._mixCol = new Uint8Array(256); - - for (let i = 0; i < 256; i++) { - if (i < 128) { - this._mixCol[i] = i << 1; - } else { - this._mixCol[i] = i << 1 ^ 0x1b; - } - } - - this.buffer = new Uint8Array(16); - this.bufferPosition = 0; - } - - _expandKey(cipherKey) { - (0, _util.unreachable)("Cannot call `_expandKey` on the base class"); - } - - _decrypt(input, key) { - let t, u, v; - const state = new Uint8Array(16); - state.set(input); - - for (let j = 0, k = this._keySize; j < 16; ++j, ++k) { - state[j] ^= key[k]; - } - - for (let i = this._cyclesOfRepetition - 1; i >= 1; --i) { - 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 (let j = 0; j < 16; ++j) { - state[j] = this._inv_s[state[j]]; - } - - for (let j = 0, k = i * 16; j < 16; ++j, ++k) { - state[j] ^= key[k]; - } - - for (let j = 0; j < 16; j += 4) { - const s0 = this._mix[state[j]]; - const s1 = this._mix[state[j + 1]]; - const s2 = this._mix[state[j + 2]]; - const s3 = this._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; - } - } - - 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 (let j = 0; j < 16; ++j) { - state[j] = this._inv_s[state[j]]; - state[j] ^= key[j]; - } - - return state; - } - - _encrypt(input, key) { - const s = this._s; - let t, u, v; - const state = new Uint8Array(16); - state.set(input); - - for (let j = 0; j < 16; ++j) { - state[j] ^= key[j]; - } - - for (let i = 1; i < this._cyclesOfRepetition; i++) { - for (let j = 0; j < 16; ++j) { - state[j] = s[state[j]]; - } - - v = state[1]; - state[1] = state[5]; - state[5] = state[9]; - state[9] = state[13]; - state[13] = v; - v = state[2]; - u = state[6]; - state[2] = state[10]; - state[6] = state[14]; - state[10] = v; - state[14] = u; - v = state[3]; - u = state[7]; - t = state[11]; - state[3] = state[15]; - state[7] = v; - state[11] = u; - state[15] = t; - - for (let j = 0; j < 16; j += 4) { - const s0 = state[j + 0]; - const s1 = state[j + 1]; - const s2 = state[j + 2]; - const s3 = state[j + 3]; - t = s0 ^ s1 ^ s2 ^ s3; - state[j + 0] ^= t ^ this._mixCol[s0 ^ s1]; - state[j + 1] ^= t ^ this._mixCol[s1 ^ s2]; - state[j + 2] ^= t ^ this._mixCol[s2 ^ s3]; - state[j + 3] ^= t ^ this._mixCol[s3 ^ s0]; - } - - for (let j = 0, k = i * 16; j < 16; ++j, ++k) { - state[j] ^= key[k]; - } - } - - for (let j = 0; j < 16; ++j) { - state[j] = s[state[j]]; - } - - v = state[1]; - state[1] = state[5]; - state[5] = state[9]; - state[9] = state[13]; - state[13] = v; - v = state[2]; - u = state[6]; - state[2] = state[10]; - state[6] = state[14]; - state[10] = v; - state[14] = u; - v = state[3]; - u = state[7]; - t = state[11]; - state[3] = state[15]; - state[7] = v; - state[11] = u; - state[15] = t; - - for (let j = 0, k = this._keySize; j < 16; ++j, ++k) { - state[j] ^= key[k]; - } - - return state; - } - - _decryptBlock2(data, finalize) { - const sourceLength = data.length; - let buffer = this.buffer, - bufferLength = this.bufferPosition; - const result = []; - let iv = this.iv; - - for (let i = 0; i < sourceLength; ++i) { - buffer[bufferLength] = data[i]; - ++bufferLength; - - if (bufferLength < 16) { - continue; - } - - const plain = this._decrypt(buffer, this._key); - - for (let j = 0; j < 16; ++j) { - plain[j] ^= iv[j]; - } - - iv = buffer; - result.push(plain); - buffer = new Uint8Array(16); - bufferLength = 0; - } - - this.buffer = buffer; - this.bufferLength = bufferLength; - this.iv = iv; - - if (result.length === 0) { - return new Uint8Array(0); - } - - let outputLength = 16 * result.length; - - if (finalize) { - const lastBlock = result[result.length - 1]; - let psLen = lastBlock[15]; - - if (psLen <= 16) { - for (let i = 15, ii = 16 - psLen; i >= ii; --i) { - if (lastBlock[i] !== psLen) { - psLen = 0; - break; - } - } - - outputLength -= psLen; - result[result.length - 1] = lastBlock.subarray(0, 16 - psLen); - } - } - - const output = new Uint8Array(outputLength); - - for (let i = 0, j = 0, ii = result.length; i < ii; ++i, j += 16) { - output.set(result[i], j); - } - - return output; - } - - decryptBlock(data, finalize, iv = null) { - const sourceLength = data.length; - const buffer = this.buffer; - let bufferLength = this.bufferPosition; - - if (iv) { - this.iv = iv; - } else { - for (let i = 0; bufferLength < 16 && i < sourceLength; ++i, ++bufferLength) { - buffer[bufferLength] = data[i]; - } - - if (bufferLength < 16) { - this.bufferLength = bufferLength; - return new Uint8Array(0); - } - - this.iv = buffer; - data = data.subarray(16); - } - - this.buffer = new Uint8Array(16); - this.bufferLength = 0; - this.decryptBlock = this._decryptBlock2; - return this.decryptBlock(data, finalize); - } - - encrypt(data, iv) { - const sourceLength = data.length; - let buffer = this.buffer, - bufferLength = this.bufferPosition; - const result = []; - - if (!iv) { - iv = new Uint8Array(16); - } - - for (let i = 0; i < sourceLength; ++i) { - buffer[bufferLength] = data[i]; - ++bufferLength; - - if (bufferLength < 16) { - continue; - } - - for (let j = 0; j < 16; ++j) { - buffer[j] ^= iv[j]; - } - - const cipher = this._encrypt(buffer, this._key); - - iv = cipher; - result.push(cipher); - buffer = new Uint8Array(16); - bufferLength = 0; - } - - this.buffer = buffer; - this.bufferLength = bufferLength; - this.iv = iv; - - if (result.length === 0) { - return new Uint8Array(0); - } - - const outputLength = 16 * result.length; - const output = new Uint8Array(outputLength); - - for (let i = 0, j = 0, ii = result.length; i < ii; ++i, j += 16) { - output.set(result[i], j); - } - - return output; - } - -} - -class AES128Cipher extends AESBaseCipher { - constructor(key) { - super(); - this._cyclesOfRepetition = 10; - this._keySize = 160; - this._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]); - this._key = this._expandKey(key); - } - - _expandKey(cipherKey) { - const b = 176; - const s = this._s; - const rcon = this._rcon; - const result = new Uint8Array(b); - result.set(cipherKey); - - for (let j = 16, i = 1; j < b; ++i) { - let t1 = result[j - 3]; - let t2 = result[j - 2]; - let t3 = result[j - 1]; - let t4 = result[j - 4]; - t1 = s[t1]; - t2 = s[t2]; - t3 = s[t3]; - t4 = s[t4]; - t1 ^= rcon[i]; - - for (let 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; - } - -} - -exports.AES128Cipher = AES128Cipher; - -class AES256Cipher extends AESBaseCipher { - constructor(key) { - super(); - this._cyclesOfRepetition = 14; - this._keySize = 224; - this._key = this._expandKey(key); - } - - _expandKey(cipherKey) { - const b = 240; - const s = this._s; - const result = new Uint8Array(b); - result.set(cipherKey); - let r = 1; - let t1, t2, t3, t4; - - for (let j = 32, i = 1; j < b; ++i) { - if (j % 32 === 16) { - t1 = s[t1]; - t2 = s[t2]; - t3 = s[t3]; - t4 = s[t4]; - } else if (j % 32 === 0) { - t1 = result[j - 3]; - t2 = result[j - 2]; - t3 = result[j - 1]; - t4 = result[j - 4]; - t1 = s[t1]; - t2 = s[t2]; - t3 = s[t3]; - t4 = s[t4]; - t1 ^= r; - - if ((r <<= 1) >= 256) { - r = (r ^ 0x1b) & 0xff; - } - } - - for (let n = 0; n < 4; ++n) { - result[j] = t1 ^= result[j - 32]; - j++; - result[j] = t2 ^= result[j - 32]; - j++; - result[j] = t3 ^= result[j - 32]; - j++; - result[j] = t4 ^= result[j - 32]; - j++; - } - } - - return result; - } - -} - -exports.AES256Cipher = AES256Cipher; - -class PDF17 { - checkOwnerPassword(password, ownerValidationSalt, userBytes, ownerPassword) { - const hashData = new Uint8Array(password.length + 56); - hashData.set(password, 0); - hashData.set(ownerValidationSalt, password.length); - hashData.set(userBytes, password.length + ownerValidationSalt.length); - const result = calculateSHA256(hashData, 0, hashData.length); - return (0, _util.isArrayEqual)(result, ownerPassword); - } - - checkUserPassword(password, userValidationSalt, userPassword) { - const hashData = new Uint8Array(password.length + 8); - hashData.set(password, 0); - hashData.set(userValidationSalt, password.length); - const result = calculateSHA256(hashData, 0, hashData.length); - return (0, _util.isArrayEqual)(result, userPassword); - } - - getOwnerKey(password, ownerKeySalt, userBytes, ownerEncryption) { - const hashData = new Uint8Array(password.length + 56); - hashData.set(password, 0); - hashData.set(ownerKeySalt, password.length); - hashData.set(userBytes, password.length + ownerKeySalt.length); - const key = calculateSHA256(hashData, 0, hashData.length); - const cipher = new AES256Cipher(key); - return cipher.decryptBlock(ownerEncryption, false, new Uint8Array(16)); - } - - getUserKey(password, userKeySalt, userEncryption) { - const hashData = new Uint8Array(password.length + 8); - hashData.set(password, 0); - hashData.set(userKeySalt, password.length); - const key = calculateSHA256(hashData, 0, hashData.length); - const cipher = new AES256Cipher(key); - return cipher.decryptBlock(userEncryption, false, new Uint8Array(16)); - } - -} - -exports.PDF17 = PDF17; - -const PDF20 = function PDF20Closure() { - function calculatePDF20Hash(password, input, userBytes) { - let k = calculateSHA256(input, 0, input.length).subarray(0, 32); - let e = [0]; - let i = 0; - - while (i < 64 || e[e.length - 1] > i - 32) { - const combinedLength = password.length + k.length + userBytes.length, - combinedArray = new Uint8Array(combinedLength); - let writeOffset = 0; - combinedArray.set(password, writeOffset); - writeOffset += password.length; - combinedArray.set(k, writeOffset); - writeOffset += k.length; - combinedArray.set(userBytes, writeOffset); - const k1 = new Uint8Array(combinedLength * 64); - - for (let j = 0, pos = 0; j < 64; j++, pos += combinedLength) { - k1.set(combinedArray, pos); - } - - const cipher = new AES128Cipher(k.subarray(0, 16)); - e = cipher.encrypt(k1, k.subarray(16, 32)); - let remainder = 0; - - for (let z = 0; z < 16; z++) { - remainder *= 256 % 3; - remainder %= 3; - remainder += (e[z] >>> 0) % 3; - remainder %= 3; - } - - if (remainder === 0) { - k = calculateSHA256(e, 0, e.length); - } else if (remainder === 1) { - k = calculateSHA384(e, 0, e.length); - } else if (remainder === 2) { - k = calculateSHA512(e, 0, e.length); - } - - i++; - } - - return k.subarray(0, 32); - } - - class PDF20 { - hash(password, concatBytes, userBytes) { - return calculatePDF20Hash(password, concatBytes, userBytes); - } - - checkOwnerPassword(password, ownerValidationSalt, userBytes, ownerPassword) { - const hashData = new Uint8Array(password.length + 56); - hashData.set(password, 0); - hashData.set(ownerValidationSalt, password.length); - hashData.set(userBytes, password.length + ownerValidationSalt.length); - const result = calculatePDF20Hash(password, hashData, userBytes); - return (0, _util.isArrayEqual)(result, ownerPassword); - } - - checkUserPassword(password, userValidationSalt, userPassword) { - const hashData = new Uint8Array(password.length + 8); - hashData.set(password, 0); - hashData.set(userValidationSalt, password.length); - const result = calculatePDF20Hash(password, hashData, []); - return (0, _util.isArrayEqual)(result, userPassword); - } - - getOwnerKey(password, ownerKeySalt, userBytes, ownerEncryption) { - const hashData = new Uint8Array(password.length + 56); - hashData.set(password, 0); - hashData.set(ownerKeySalt, password.length); - hashData.set(userBytes, password.length + ownerKeySalt.length); - const key = calculatePDF20Hash(password, hashData, userBytes); - const cipher = new AES256Cipher(key); - return cipher.decryptBlock(ownerEncryption, false, new Uint8Array(16)); - } - - getUserKey(password, userKeySalt, userEncryption) { - const hashData = new Uint8Array(password.length + 8); - hashData.set(password, 0); - hashData.set(userKeySalt, password.length); - const key = calculatePDF20Hash(password, hashData, []); - const cipher = new AES256Cipher(key); - return cipher.decryptBlock(userEncryption, false, new Uint8Array(16)); - } - - } - - return PDF20; -}(); - -exports.PDF20 = PDF20; - -class CipherTransform { - constructor(stringCipherConstructor, streamCipherConstructor) { - this.StringCipherConstructor = stringCipherConstructor; - this.StreamCipherConstructor = streamCipherConstructor; - } - - createStream(stream, length) { - const cipher = new this.StreamCipherConstructor(); - return new _decrypt_stream.DecryptStream(stream, length, function cipherTransformDecryptStream(data, finalize) { - return cipher.decryptBlock(data, finalize); - }); - } - - decryptString(s) { - const cipher = new this.StringCipherConstructor(); - let data = (0, _util.stringToBytes)(s); - data = cipher.decryptBlock(data, true); - return (0, _util.bytesToString)(data); - } - - encryptString(s) { - const cipher = new this.StringCipherConstructor(); - - if (cipher instanceof AESBaseCipher) { - const strLen = s.length; - const pad = 16 - strLen % 16; - s += String.fromCharCode(pad).repeat(pad); - const iv = new Uint8Array(16); - - if (typeof crypto !== "undefined") { - crypto.getRandomValues(iv); - } else { - for (let i = 0; i < 16; i++) { - iv[i] = Math.floor(256 * Math.random()); - } - } - - let data = (0, _util.stringToBytes)(s); - data = cipher.encrypt(data, iv); - const buf = new Uint8Array(16 + data.length); - buf.set(iv); - buf.set(data, 16); - return (0, _util.bytesToString)(buf); - } - - let data = (0, _util.stringToBytes)(s); - data = cipher.encrypt(data); - return (0, _util.bytesToString)(data); - } - -} - -const CipherTransformFactory = function CipherTransformFactoryClosure() { - const defaultPasswordBytes = new Uint8Array([0x28, 0xbf, 0x4e, 0x5e, 0x4e, 0x75, 0x8a, 0x41, 0x64, 0x00, 0x4e, 0x56, 0xff, 0xfa, 0x01, 0x08, 0x2e, 0x2e, 0x00, 0xb6, 0xd0, 0x68, 0x3e, 0x80, 0x2f, 0x0c, 0xa9, 0xfe, 0x64, 0x53, 0x69, 0x7a]); - - function createEncryptionKey20(revision, password, ownerPassword, ownerValidationSalt, ownerKeySalt, uBytes, userPassword, userValidationSalt, userKeySalt, ownerEncryption, userEncryption, perms) { - if (password) { - const passwordLength = Math.min(127, password.length); - password = password.subarray(0, passwordLength); - } else { - password = []; - } - - let pdfAlgorithm; - - if (revision === 6) { - pdfAlgorithm = new PDF20(); - } else { - pdfAlgorithm = new PDF17(); - } - - if (pdfAlgorithm.checkUserPassword(password, userValidationSalt, userPassword)) { - return pdfAlgorithm.getUserKey(password, userKeySalt, userEncryption); - } else if (password.length && pdfAlgorithm.checkOwnerPassword(password, ownerValidationSalt, uBytes, ownerPassword)) { - return pdfAlgorithm.getOwnerKey(password, ownerKeySalt, uBytes, ownerEncryption); - } - - return null; - } - - function prepareKeyData(fileId, password, ownerPassword, userPassword, flags, revision, keyLength, encryptMetadata) { - const hashDataSize = 40 + ownerPassword.length + fileId.length; - const hashData = new Uint8Array(hashDataSize); - let 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++]; - } - - 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; - } - - let hash = calculateMD5(hashData, 0, i); - const keyLengthInBytes = keyLength >> 3; - - if (revision >= 3) { - for (j = 0; j < 50; ++j) { - hash = calculateMD5(hash, 0, keyLengthInBytes); - } - } - - const encryptionKey = hash.subarray(0, keyLengthInBytes); - let cipher, checkData; - - if (revision >= 3) { - for (i = 0; i < 32; ++i) { - hashData[i] = defaultPasswordBytes[i]; - } - - for (j = 0, n = fileId.length; j < n; ++j) { - hashData[i++] = fileId[j]; - } - - cipher = new ARCFourCipher(encryptionKey); - checkData = cipher.encryptBlock(calculateMD5(hashData, 0, i)); - n = encryptionKey.length; - const derivedKey = new Uint8Array(n); - - for (j = 1; j <= 19; ++j) { - for (let 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) { - const hashData = new Uint8Array(32); - let i = 0; - const n = Math.min(32, password.length); - - for (; i < n; ++i) { - hashData[i] = password[i]; - } - - let j = 0; - - while (i < 32) { - hashData[i++] = defaultPasswordBytes[j++]; - } - - let hash = calculateMD5(hashData, 0, i); - const keyLengthInBytes = keyLength >> 3; - - if (revision >= 3) { - for (j = 0; j < 50; ++j) { - hash = calculateMD5(hash, 0, hash.length); - } - } - - let cipher, userPassword; - - if (revision >= 3) { - userPassword = ownerPassword; - const derivedKey = new Uint8Array(keyLengthInBytes); - - for (j = 19; j >= 0; j--) { - for (let 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; - } - - const identityName = _primitives.Name.get("Identity"); - - function buildObjectKey(num, gen, encryptionKey, isAes = false) { - const key = new Uint8Array(encryptionKey.length + 9); - const n = encryptionKey.length; - let i; - - for (i = 0; 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; - } - - const hash = calculateMD5(key, 0, i); - return hash.subarray(0, Math.min(encryptionKey.length + 5, 16)); - } - - function buildCipherConstructor(cf, name, num, gen, key) { - if (!(0, _primitives.isName)(name)) { - throw new _util.FormatError("Invalid crypt filter name."); - } - - const cryptFilter = cf.get(name.name); - let cfm; - - if (cryptFilter !== null && cryptFilter !== undefined) { - cfm = cryptFilter.get("CFM"); - } - - if (!cfm || cfm.name === "None") { - return function cipherTransformFactoryBuildCipherConstructorNone() { - return new NullCipher(); - }; - } - - if (cfm.name === "V2") { - return function cipherTransformFactoryBuildCipherConstructorV2() { - return new ARCFourCipher(buildObjectKey(num, gen, key, false)); - }; - } - - if (cfm.name === "AESV2") { - return function cipherTransformFactoryBuildCipherConstructorAESV2() { - return new AES128Cipher(buildObjectKey(num, gen, key, true)); - }; - } - - if (cfm.name === "AESV3") { - return function cipherTransformFactoryBuildCipherConstructorAESV3() { - return new AES256Cipher(key); - }; - } - - throw new _util.FormatError("Unknown crypto method"); - } - - class CipherTransformFactory { - constructor(dict, fileId, password) { - const filter = dict.get("Filter"); - - if (!(0, _primitives.isName)(filter, "Standard")) { - throw new _util.FormatError("unknown encryption method"); - } - - this.filterName = filter.name; - this.dict = dict; - const algorithm = dict.get("V"); - - if (!Number.isInteger(algorithm) || algorithm !== 1 && algorithm !== 2 && algorithm !== 4 && algorithm !== 5) { - throw new _util.FormatError("unsupported encryption algorithm"); - } - - this.algorithm = algorithm; - let keyLength = dict.get("Length"); - - if (!keyLength) { - if (algorithm <= 3) { - keyLength = 40; - } else { - const cfDict = dict.get("CF"); - const streamCryptoName = dict.get("StmF"); - - if ((0, _primitives.isDict)(cfDict) && (0, _primitives.isName)(streamCryptoName)) { - cfDict.suppressEncryption = true; - const handlerDict = cfDict.get(streamCryptoName.name); - keyLength = handlerDict && handlerDict.get("Length") || 128; - - if (keyLength < 40) { - keyLength <<= 3; - } - } - } - } - - if (!Number.isInteger(keyLength) || keyLength < 40 || keyLength % 8 !== 0) { - throw new _util.FormatError("invalid key length"); - } - - const ownerPassword = (0, _util.stringToBytes)(dict.get("O")).subarray(0, 32); - const userPassword = (0, _util.stringToBytes)(dict.get("U")).subarray(0, 32); - const flags = dict.get("P"); - const revision = dict.get("R"); - const encryptMetadata = (algorithm === 4 || algorithm === 5) && dict.get("EncryptMetadata") !== false; - this.encryptMetadata = encryptMetadata; - const fileIdBytes = (0, _util.stringToBytes)(fileId); - let passwordBytes; - - if (password) { - if (revision === 6) { - try { - password = (0, _util.utf8StringToString)(password); - } catch (ex) { - (0, _util.warn)("CipherTransformFactory: " + "Unable to convert UTF8 encoded password."); - } - } - - passwordBytes = (0, _util.stringToBytes)(password); - } - - let encryptionKey; - - if (algorithm !== 5) { - encryptionKey = prepareKeyData(fileIdBytes, passwordBytes, ownerPassword, userPassword, flags, revision, keyLength, encryptMetadata); - } else { - const ownerValidationSalt = (0, _util.stringToBytes)(dict.get("O")).subarray(32, 40); - const ownerKeySalt = (0, _util.stringToBytes)(dict.get("O")).subarray(40, 48); - const uBytes = (0, _util.stringToBytes)(dict.get("U")).subarray(0, 48); - const userValidationSalt = (0, _util.stringToBytes)(dict.get("U")).subarray(32, 40); - const userKeySalt = (0, _util.stringToBytes)(dict.get("U")).subarray(40, 48); - const ownerEncryption = (0, _util.stringToBytes)(dict.get("OE")); - const userEncryption = (0, _util.stringToBytes)(dict.get("UE")); - const perms = (0, _util.stringToBytes)(dict.get("Perms")); - encryptionKey = createEncryptionKey20(revision, passwordBytes, ownerPassword, ownerValidationSalt, ownerKeySalt, uBytes, userPassword, userValidationSalt, userKeySalt, ownerEncryption, userEncryption, perms); - } - - if (!encryptionKey && !password) { - throw new _util.PasswordException("No password given", _util.PasswordResponses.NEED_PASSWORD); - } else if (!encryptionKey && password) { - const decodedPassword = decodeUserPassword(passwordBytes, ownerPassword, revision, keyLength); - encryptionKey = prepareKeyData(fileIdBytes, decodedPassword, ownerPassword, userPassword, flags, revision, keyLength, encryptMetadata); - } - - if (!encryptionKey) { - throw new _util.PasswordException("Incorrect Password", _util.PasswordResponses.INCORRECT_PASSWORD); - } - - this.encryptionKey = encryptionKey; - - if (algorithm >= 4) { - const cf = dict.get("CF"); - - if ((0, _primitives.isDict)(cf)) { - cf.suppressEncryption = true; - } - - this.cf = cf; - this.stmf = dict.get("StmF") || identityName; - this.strf = dict.get("StrF") || identityName; - this.eff = dict.get("EFF") || this.stmf; - } - } - - createCipherTransform(num, gen) { - if (this.algorithm === 4 || this.algorithm === 5) { - return new CipherTransform(buildCipherConstructor(this.cf, this.stmf, num, gen, this.encryptionKey), buildCipherConstructor(this.cf, this.strf, num, gen, this.encryptionKey)); - } - - const key = buildObjectKey(num, gen, this.encryptionKey, false); - - const cipherConstructor = function buildCipherCipherConstructor() { - return new ARCFourCipher(key); - }; - - return new CipherTransform(cipherConstructor, cipherConstructor); - } - - } - - return CipherTransformFactory; -}(); - -exports.CipherTransformFactory = CipherTransformFactory; - -/***/ }), -/* 73 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.DecryptStream = void 0; - -var _decode_stream = __w_pdfjs_require__(29); - -const chunkSize = 512; - -class DecryptStream extends _decode_stream.DecodeStream { - constructor(str, maybeLength, decrypt) { - super(maybeLength); - this.str = str; - this.dict = str.dict; - this.decrypt = decrypt; - this.nextChunk = null; - this.initialized = false; - } - - readBlock() { - let 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); - const hasMoreData = this.nextChunk && this.nextChunk.length > 0; - const decrypt = this.decrypt; - chunk = decrypt(chunk, !hasMoreData); - let bufferLength = this.bufferLength; - const n = chunk.length, - buffer = this.ensureBuffer(bufferLength + n); - - for (let i = 0; i < n; i++) { - buffer[bufferLength++] = chunk[i]; - } - - this.bufferLength = bufferLength; - } - -} - -exports.DecryptStream = DecryptStream; - -/***/ }), -/* 74 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.XFAFactory = void 0; - -var _xfa_object = __w_pdfjs_require__(75); - -var _bind = __w_pdfjs_require__(79); - -var _data = __w_pdfjs_require__(85); - -var _fonts = __w_pdfjs_require__(83); - -var _utils = __w_pdfjs_require__(76); - -var _util = __w_pdfjs_require__(2); - -var _parser = __w_pdfjs_require__(86); - -var _xhtml = __w_pdfjs_require__(96); - -class XFAFactory { - constructor(data) { - try { - this.root = new _parser.XFAParser().parse(XFAFactory._createDocument(data)); - const binder = new _bind.Binder(this.root); - this.form = binder.bind(); - this.dataHandler = new _data.DataHandler(this.root, binder.getData()); - this.form[_xfa_object.$globalData].template = this.form; - } catch (e) { - (0, _util.warn)(`XFA - an error occurred during parsing and binding: ${e}`); - } - } - - isValid() { - return this.root && this.form; - } - - _createPagesHelper() { - const iterator = this.form[_xfa_object.$toPages](); - - return new Promise((resolve, reject) => { - const nextIteration = () => { - try { - const value = iterator.next(); - - if (value.done) { - resolve(value.value); - } else { - setTimeout(nextIteration, 0); - } - } catch (e) { - reject(e); - } - }; - - setTimeout(nextIteration, 0); - }); - } - - async _createPages() { - try { - this.pages = await this._createPagesHelper(); - this.dims = this.pages.children.map(c => { - const { - width, - height - } = c.attributes.style; - return [0, 0, parseInt(width), parseInt(height)]; - }); - } catch (e) { - (0, _util.warn)(`XFA - an error occurred during layout: ${e}`); - } - } - - getBoundingBox(pageIndex) { - return this.dims[pageIndex]; - } - - async getNumPages() { - if (!this.pages) { - await this._createPages(); - } - - return this.dims.length; - } - - setImages(images) { - this.form[_xfa_object.$globalData].images = images; - } - - setFonts(fonts) { - this.form[_xfa_object.$globalData].fontFinder = new _fonts.FontFinder(fonts); - const missingFonts = []; - - for (let typeface of this.form[_xfa_object.$globalData].usedTypefaces) { - typeface = (0, _utils.stripQuotes)(typeface); - - const font = this.form[_xfa_object.$globalData].fontFinder.find(typeface); - - if (!font) { - missingFonts.push(typeface); - } - } - - if (missingFonts.length > 0) { - return missingFonts; - } - - return null; - } - - appendFonts(fonts, reallyMissingFonts) { - this.form[_xfa_object.$globalData].fontFinder.add(fonts, reallyMissingFonts); - } - - async getPages() { - if (!this.pages) { - await this._createPages(); - } - - const pages = this.pages; - this.pages = null; - return pages; - } - - serializeData(storage) { - return this.dataHandler.serialize(storage); - } - - static _createDocument(data) { - if (!data["/xdp:xdp"]) { - return data["xdp:xdp"]; - } - - return Object.values(data).join(""); - } - - static getRichTextAsHtml(rc) { - if (!rc || typeof rc !== "string") { - return null; - } - - try { - let root = new _parser.XFAParser(_xhtml.XhtmlNamespace, true).parse(rc); - - if (!["body", "xhtml"].includes(root[_xfa_object.$nodeName])) { - const newRoot = _xhtml.XhtmlNamespace.body({}); - - newRoot[_xfa_object.$appendChild](root); - - root = newRoot; - } - - const result = root[_xfa_object.$toHTML](); - - if (!result.success) { - return null; - } - - const { - html - } = result; - const { - attributes - } = html; - - if (attributes) { - if (attributes.class) { - attributes.class = attributes.class.filter(attr => !attr.startsWith("xfa")); - } - - attributes.dir = "auto"; - } - - return { - html, - str: root[_xfa_object.$text]() - }; - } catch (e) { - (0, _util.warn)(`XFA - an error occurred during parsing of rich text: ${e}`); - } - - return null; - } - -} - -exports.XFAFactory = XFAFactory; - -/***/ }), -/* 75 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.XmlObject = exports.XFAObjectArray = exports.XFAObject = exports.XFAAttribute = exports.StringObject = exports.OptionObject = exports.Option10 = exports.Option01 = exports.IntegerObject = exports.ContentObject = exports.$uid = exports.$toStyle = exports.$toString = exports.$toPages = exports.$toHTML = exports.$text = exports.$tabIndex = exports.$setValue = exports.$setSetAttributes = exports.$setId = exports.$searchNode = exports.$root = exports.$resolvePrototypes = exports.$removeChild = exports.$pushPara = exports.$pushGlyphs = exports.$popPara = exports.$onText = exports.$onChildCheck = exports.$onChild = exports.$nsAttributes = exports.$nodeName = exports.$namespaceId = exports.$isUsable = exports.$isTransparent = exports.$isThereMoreWidth = exports.$isSplittable = exports.$isNsAgnostic = exports.$isDescendent = exports.$isDataValue = exports.$isCDATAXml = exports.$isBindable = exports.$insertAt = exports.$indexOf = exports.$ids = exports.$hasSettableValue = exports.$globalData = exports.$getTemplateRoot = exports.$getSubformParent = exports.$getRealChildrenByNameIt = exports.$getParent = exports.$getNextPage = exports.$getExtra = exports.$getDataValue = exports.$getContainedChildren = exports.$getChildrenByNameIt = exports.$getChildrenByName = exports.$getChildrenByClass = exports.$getChildren = exports.$getAvailableSpace = exports.$getAttributes = exports.$getAttributeIt = exports.$flushHTML = exports.$finalize = exports.$extra = exports.$dump = exports.$data = exports.$content = exports.$consumed = exports.$clone = exports.$cleanup = exports.$cleanPage = exports.$clean = exports.$childrenToHTML = exports.$appendChild = exports.$addHTML = exports.$acceptWhitespace = void 0; - -var _utils = __w_pdfjs_require__(76); - -var _util = __w_pdfjs_require__(2); - -var _core_utils = __w_pdfjs_require__(9); - -var _namespaces = __w_pdfjs_require__(77); - -var _som = __w_pdfjs_require__(78); - -const $acceptWhitespace = Symbol(); -exports.$acceptWhitespace = $acceptWhitespace; -const $addHTML = Symbol(); -exports.$addHTML = $addHTML; -const $appendChild = Symbol(); -exports.$appendChild = $appendChild; -const $childrenToHTML = Symbol(); -exports.$childrenToHTML = $childrenToHTML; -const $clean = Symbol(); -exports.$clean = $clean; -const $cleanPage = Symbol(); -exports.$cleanPage = $cleanPage; -const $cleanup = Symbol(); -exports.$cleanup = $cleanup; -const $clone = Symbol(); -exports.$clone = $clone; -const $consumed = Symbol(); -exports.$consumed = $consumed; -const $content = Symbol("content"); -exports.$content = $content; -const $data = Symbol("data"); -exports.$data = $data; -const $dump = Symbol(); -exports.$dump = $dump; -const $extra = Symbol("extra"); -exports.$extra = $extra; -const $finalize = Symbol(); -exports.$finalize = $finalize; -const $flushHTML = Symbol(); -exports.$flushHTML = $flushHTML; -const $getAttributeIt = Symbol(); -exports.$getAttributeIt = $getAttributeIt; -const $getAttributes = Symbol(); -exports.$getAttributes = $getAttributes; -const $getAvailableSpace = Symbol(); -exports.$getAvailableSpace = $getAvailableSpace; -const $getChildrenByClass = Symbol(); -exports.$getChildrenByClass = $getChildrenByClass; -const $getChildrenByName = Symbol(); -exports.$getChildrenByName = $getChildrenByName; -const $getChildrenByNameIt = Symbol(); -exports.$getChildrenByNameIt = $getChildrenByNameIt; -const $getDataValue = Symbol(); -exports.$getDataValue = $getDataValue; -const $getExtra = Symbol(); -exports.$getExtra = $getExtra; -const $getRealChildrenByNameIt = Symbol(); -exports.$getRealChildrenByNameIt = $getRealChildrenByNameIt; -const $getChildren = Symbol(); -exports.$getChildren = $getChildren; -const $getContainedChildren = Symbol(); -exports.$getContainedChildren = $getContainedChildren; -const $getNextPage = Symbol(); -exports.$getNextPage = $getNextPage; -const $getSubformParent = Symbol(); -exports.$getSubformParent = $getSubformParent; -const $getParent = Symbol(); -exports.$getParent = $getParent; -const $getTemplateRoot = Symbol(); -exports.$getTemplateRoot = $getTemplateRoot; -const $globalData = Symbol(); -exports.$globalData = $globalData; -const $hasSettableValue = Symbol(); -exports.$hasSettableValue = $hasSettableValue; -const $ids = Symbol(); -exports.$ids = $ids; -const $indexOf = Symbol(); -exports.$indexOf = $indexOf; -const $insertAt = Symbol(); -exports.$insertAt = $insertAt; -const $isCDATAXml = Symbol(); -exports.$isCDATAXml = $isCDATAXml; -const $isBindable = Symbol(); -exports.$isBindable = $isBindable; -const $isDataValue = Symbol(); -exports.$isDataValue = $isDataValue; -const $isDescendent = Symbol(); -exports.$isDescendent = $isDescendent; -const $isNsAgnostic = Symbol(); -exports.$isNsAgnostic = $isNsAgnostic; -const $isSplittable = Symbol(); -exports.$isSplittable = $isSplittable; -const $isThereMoreWidth = Symbol(); -exports.$isThereMoreWidth = $isThereMoreWidth; -const $isTransparent = Symbol(); -exports.$isTransparent = $isTransparent; -const $isUsable = Symbol(); -exports.$isUsable = $isUsable; -const $lastAttribute = Symbol(); -const $namespaceId = Symbol("namespaceId"); -exports.$namespaceId = $namespaceId; -const $nodeName = Symbol("nodeName"); -exports.$nodeName = $nodeName; -const $nsAttributes = Symbol(); -exports.$nsAttributes = $nsAttributes; -const $onChild = Symbol(); -exports.$onChild = $onChild; -const $onChildCheck = Symbol(); -exports.$onChildCheck = $onChildCheck; -const $onText = Symbol(); -exports.$onText = $onText; -const $pushGlyphs = Symbol(); -exports.$pushGlyphs = $pushGlyphs; -const $popPara = Symbol(); -exports.$popPara = $popPara; -const $pushPara = Symbol(); -exports.$pushPara = $pushPara; -const $removeChild = Symbol(); -exports.$removeChild = $removeChild; -const $root = Symbol("root"); -exports.$root = $root; -const $resolvePrototypes = Symbol(); -exports.$resolvePrototypes = $resolvePrototypes; -const $searchNode = Symbol(); -exports.$searchNode = $searchNode; -const $setId = Symbol(); -exports.$setId = $setId; -const $setSetAttributes = Symbol(); -exports.$setSetAttributes = $setSetAttributes; -const $setValue = Symbol(); -exports.$setValue = $setValue; -const $tabIndex = Symbol(); -exports.$tabIndex = $tabIndex; -const $text = Symbol(); -exports.$text = $text; -const $toPages = Symbol(); -exports.$toPages = $toPages; -const $toHTML = Symbol(); -exports.$toHTML = $toHTML; -const $toString = Symbol(); -exports.$toString = $toString; -const $toStyle = Symbol(); -exports.$toStyle = $toStyle; -const $uid = Symbol("uid"); -exports.$uid = $uid; - -const _applyPrototype = Symbol(); - -const _attributes = Symbol(); - -const _attributeNames = Symbol(); - -const _children = Symbol("_children"); - -const _cloneAttribute = Symbol(); - -const _dataValue = Symbol(); - -const _defaultValue = Symbol(); - -const _filteredChildrenGenerator = Symbol(); - -const _getPrototype = Symbol(); - -const _getUnsetAttributes = Symbol(); - -const _hasChildren = Symbol(); - -const _max = Symbol(); - -const _options = Symbol(); - -const _parent = Symbol("parent"); - -const _resolvePrototypesHelper = Symbol(); - -const _setAttributes = Symbol(); - -const _validator = Symbol(); - -let uid = 0; -const NS_DATASETS = _namespaces.NamespaceIds.datasets.id; - -class XFAObject { - constructor(nsId, name, hasChildren = false) { - this[$namespaceId] = nsId; - this[$nodeName] = name; - this[_hasChildren] = hasChildren; - this[_parent] = null; - this[_children] = []; - this[$uid] = `${name}${uid++}`; - this[$globalData] = null; - } - - [$onChild](child) { - if (!this[_hasChildren] || !this[$onChildCheck](child)) { - return false; - } - - const name = child[$nodeName]; - const node = this[name]; - - if (node instanceof XFAObjectArray) { - if (node.push(child)) { - this[$appendChild](child); - return true; - } - } else { - if (node !== null) { - this[$removeChild](node); - } - - this[name] = child; - this[$appendChild](child); - return true; - } - - let id = ""; - - if (this.id) { - id = ` (id: ${this.id})`; - } else if (this.name) { - id = ` (name: ${this.name} ${this.h.value})`; - } - - (0, _util.warn)(`XFA - node "${this[$nodeName]}"${id} has already enough "${name}"!`); - return false; - } - - [$onChildCheck](child) { - return this.hasOwnProperty(child[$nodeName]) && child[$namespaceId] === this[$namespaceId]; - } - - [$isNsAgnostic]() { - return false; - } - - [$acceptWhitespace]() { - return false; - } - - [$isCDATAXml]() { - return false; - } - - [$isBindable]() { - return false; - } - - [$popPara]() { - if (this.para) { - this[$getTemplateRoot]()[$extra].paraStack.pop(); - } - } - - [$pushPara]() { - this[$getTemplateRoot]()[$extra].paraStack.push(this.para); - } - - [$setId](ids) { - if (this.id && this[$namespaceId] === _namespaces.NamespaceIds.template.id) { - ids.set(this.id, this); - } - } - - [$getTemplateRoot]() { - return this[$globalData].template; - } - - [$isSplittable]() { - return false; - } - - [$isThereMoreWidth]() { - return false; - } - - [$appendChild](child) { - child[_parent] = this; - - this[_children].push(child); - - if (!child[$globalData] && this[$globalData]) { - child[$globalData] = this[$globalData]; - } - } - - [$removeChild](child) { - const i = this[_children].indexOf(child); - - this[_children].splice(i, 1); - } - - [$hasSettableValue]() { - return this.hasOwnProperty("value"); - } - - [$setValue](_) {} - - [$onText](_) {} - - [$finalize]() {} - - [$clean](builder) { - delete this[_hasChildren]; - - if (this[$cleanup]) { - builder.clean(this[$cleanup]); - delete this[$cleanup]; - } - } - - [$indexOf](child) { - return this[_children].indexOf(child); - } - - [$insertAt](i, child) { - child[_parent] = this; - - this[_children].splice(i, 0, child); - - if (!child[$globalData] && this[$globalData]) { - child[$globalData] = this[$globalData]; - } - } - - [$isTransparent]() { - return !this.name; - } - - [$lastAttribute]() { - return ""; - } - - [$text]() { - if (this[_children].length === 0) { - return this[$content]; - } - - return this[_children].map(c => c[$text]()).join(""); - } - - get [_attributeNames]() { - const proto = Object.getPrototypeOf(this); - - if (!proto._attributes) { - const attributes = proto._attributes = new Set(); - - for (const name of Object.getOwnPropertyNames(this)) { - if (this[name] === null || this[name] instanceof XFAObject || this[name] instanceof XFAObjectArray) { - break; - } - - attributes.add(name); - } - } - - return (0, _util.shadow)(this, _attributeNames, proto._attributes); - } - - [$isDescendent](parent) { - let node = this; - - while (node) { - if (node === parent) { - return true; - } - - node = node[$getParent](); - } - - return false; - } - - [$getParent]() { - return this[_parent]; - } - - [$getSubformParent]() { - return this[$getParent](); - } - - [$getChildren](name = null) { - if (!name) { - return this[_children]; - } - - return this[name]; - } - - [$dump]() { - const dumped = Object.create(null); - - if (this[$content]) { - dumped.$content = this[$content]; - } - - for (const name of Object.getOwnPropertyNames(this)) { - const value = this[name]; - - if (value === null) { - continue; - } - - if (value instanceof XFAObject) { - dumped[name] = value[$dump](); - } else if (value instanceof XFAObjectArray) { - if (!value.isEmpty()) { - dumped[name] = value.dump(); - } - } else { - dumped[name] = value; - } - } - - return dumped; - } - - [$toStyle]() { - return null; - } - - [$toHTML]() { - return _utils.HTMLResult.EMPTY; - } - - *[$getContainedChildren]() { - for (const node of this[$getChildren]()) { - yield node; - } - } - - *[_filteredChildrenGenerator](filter, include) { - for (const node of this[$getContainedChildren]()) { - if (!filter || include === filter.has(node[$nodeName])) { - const availableSpace = this[$getAvailableSpace](); - const res = node[$toHTML](availableSpace); - - if (!res.success) { - this[$extra].failingNode = node; - } - - yield res; - } - } - } - - [$flushHTML]() { - return null; - } - - [$addHTML](html, bbox) { - this[$extra].children.push(html); - } - - [$getAvailableSpace]() {} - - [$childrenToHTML]({ - filter = null, - include = true - }) { - if (!this[$extra].generator) { - this[$extra].generator = this[_filteredChildrenGenerator](filter, include); - } else { - const availableSpace = this[$getAvailableSpace](); - const res = this[$extra].failingNode[$toHTML](availableSpace); - - if (!res.success) { - return res; - } - - if (res.html) { - this[$addHTML](res.html, res.bbox); - } - - delete this[$extra].failingNode; - } - - while (true) { - const gen = this[$extra].generator.next(); - - if (gen.done) { - break; - } - - const res = gen.value; - - if (!res.success) { - return res; - } - - if (res.html) { - this[$addHTML](res.html, res.bbox); - } - } - - this[$extra].generator = null; - return _utils.HTMLResult.EMPTY; - } - - [$setSetAttributes](attributes) { - this[_setAttributes] = new Set(Object.keys(attributes)); - } - - [_getUnsetAttributes](protoAttributes) { - const allAttr = this[_attributeNames]; - const setAttr = this[_setAttributes]; - return [...protoAttributes].filter(x => allAttr.has(x) && !setAttr.has(x)); - } - - [$resolvePrototypes](ids, ancestors = new Set()) { - for (const child of this[_children]) { - child[_resolvePrototypesHelper](ids, ancestors); - } - } - - [_resolvePrototypesHelper](ids, ancestors) { - const proto = this[_getPrototype](ids, ancestors); - - if (proto) { - this[_applyPrototype](proto, ids, ancestors); - } else { - this[$resolvePrototypes](ids, ancestors); - } - } - - [_getPrototype](ids, ancestors) { - const { - use, - usehref - } = this; - - if (!use && !usehref) { - return null; - } - - let proto = null; - let somExpression = null; - let id = null; - let ref = use; - - if (usehref) { - ref = usehref; - - if (usehref.startsWith("#som(") && usehref.endsWith(")")) { - somExpression = usehref.slice("#som(".length, usehref.length - 1); - } else if (usehref.startsWith(".#som(") && usehref.endsWith(")")) { - somExpression = usehref.slice(".#som(".length, usehref.length - 1); - } else if (usehref.startsWith("#")) { - id = usehref.slice(1); - } else if (usehref.startsWith(".#")) { - id = usehref.slice(2); - } - } else if (use.startsWith("#")) { - id = use.slice(1); - } else { - somExpression = use; - } - - this.use = this.usehref = ""; - - if (id) { - proto = ids.get(id); - } else { - proto = (0, _som.searchNode)(ids.get($root), this, somExpression, true, false); - - if (proto) { - proto = proto[0]; - } - } - - if (!proto) { - (0, _util.warn)(`XFA - Invalid prototype reference: ${ref}.`); - return null; - } - - if (proto[$nodeName] !== this[$nodeName]) { - (0, _util.warn)(`XFA - Incompatible prototype: ${proto[$nodeName]} !== ${this[$nodeName]}.`); - return null; - } - - if (ancestors.has(proto)) { - (0, _util.warn)(`XFA - Cycle detected in prototypes use.`); - return null; - } - - ancestors.add(proto); - - const protoProto = proto[_getPrototype](ids, ancestors); - - if (protoProto) { - proto[_applyPrototype](protoProto, ids, ancestors); - } - - proto[$resolvePrototypes](ids, ancestors); - ancestors.delete(proto); - return proto; - } - - [_applyPrototype](proto, ids, ancestors) { - if (ancestors.has(proto)) { - (0, _util.warn)(`XFA - Cycle detected in prototypes use.`); - return; - } - - if (!this[$content] && proto[$content]) { - this[$content] = proto[$content]; - } - - const newAncestors = new Set(ancestors); - newAncestors.add(proto); - - for (const unsetAttrName of this[_getUnsetAttributes](proto[_setAttributes])) { - this[unsetAttrName] = proto[unsetAttrName]; - - if (this[_setAttributes]) { - this[_setAttributes].add(unsetAttrName); - } - } - - for (const name of Object.getOwnPropertyNames(this)) { - if (this[_attributeNames].has(name)) { - continue; - } - - const value = this[name]; - const protoValue = proto[name]; - - if (value instanceof XFAObjectArray) { - for (const child of value[_children]) { - child[_resolvePrototypesHelper](ids, ancestors); - } - - for (let i = value[_children].length, ii = protoValue[_children].length; i < ii; i++) { - const child = proto[_children][i][$clone](); - - if (value.push(child)) { - child[_parent] = this; - - this[_children].push(child); - - child[_resolvePrototypesHelper](ids, ancestors); - } else { - break; - } - } - - continue; - } - - if (value !== null) { - value[$resolvePrototypes](ids, ancestors); - - if (protoValue) { - value[_applyPrototype](protoValue, ids, ancestors); - } - - continue; - } - - if (protoValue !== null) { - const child = protoValue[$clone](); - child[_parent] = this; - this[name] = child; - - this[_children].push(child); - - child[_resolvePrototypesHelper](ids, ancestors); - } - } - } - - static [_cloneAttribute](obj) { - if (Array.isArray(obj)) { - return obj.map(x => XFAObject[_cloneAttribute](x)); - } - - if (typeof obj === "object" && obj !== null) { - return Object.assign({}, obj); - } - - return obj; - } - - [$clone]() { - const clone = Object.create(Object.getPrototypeOf(this)); - - for (const $symbol of Object.getOwnPropertySymbols(this)) { - try { - clone[$symbol] = this[$symbol]; - } catch (_) { - (0, _util.shadow)(clone, $symbol, this[$symbol]); - } - } - - clone[$uid] = `${clone[$nodeName]}${uid++}`; - clone[_children] = []; - - for (const name of Object.getOwnPropertyNames(this)) { - if (this[_attributeNames].has(name)) { - clone[name] = XFAObject[_cloneAttribute](this[name]); - continue; - } - - const value = this[name]; - - if (value instanceof XFAObjectArray) { - clone[name] = new XFAObjectArray(value[_max]); - } else { - clone[name] = null; - } - } - - for (const child of this[_children]) { - const name = child[$nodeName]; - const clonedChild = child[$clone](); - - clone[_children].push(clonedChild); - - clonedChild[_parent] = clone; - - if (clone[name] === null) { - clone[name] = clonedChild; - } else { - clone[name][_children].push(clonedChild); - } - } - - return clone; - } - - [$getChildren](name = null) { - if (!name) { - return this[_children]; - } - - return this[_children].filter(c => c[$nodeName] === name); - } - - [$getChildrenByClass](name) { - return this[name]; - } - - [$getChildrenByName](name, allTransparent, first = true) { - return Array.from(this[$getChildrenByNameIt](name, allTransparent, first)); - } - - *[$getChildrenByNameIt](name, allTransparent, first = true) { - if (name === "parent") { - yield this[_parent]; - return; - } - - for (const child of this[_children]) { - if (child[$nodeName] === name) { - yield child; - } - - if (child.name === name) { - yield child; - } - - if (allTransparent || child[$isTransparent]()) { - yield* child[$getChildrenByNameIt](name, allTransparent, false); - } - } - - if (first && this[_attributeNames].has(name)) { - yield new XFAAttribute(this, name, this[name]); - } - } - -} - -exports.XFAObject = XFAObject; - -class XFAObjectArray { - constructor(max = Infinity) { - this[_max] = max; - this[_children] = []; - } - - push(child) { - const len = this[_children].length; - - if (len <= this[_max]) { - this[_children].push(child); - - return true; - } - - (0, _util.warn)(`XFA - node "${child[$nodeName]}" accepts no more than ${this[_max]} children`); - return false; - } - - isEmpty() { - return this[_children].length === 0; - } - - dump() { - return this[_children].length === 1 ? this[_children][0][$dump]() : this[_children].map(x => x[$dump]()); - } - - [$clone]() { - const clone = new XFAObjectArray(this[_max]); - clone[_children] = this[_children].map(c => c[$clone]()); - return clone; - } - - get children() { - return this[_children]; - } - - clear() { - this[_children].length = 0; - } - -} - -exports.XFAObjectArray = XFAObjectArray; - -class XFAAttribute { - constructor(node, name, value) { - this[_parent] = node; - this[$nodeName] = name; - this[$content] = value; - this[$consumed] = false; - this[$uid] = `attribute${uid++}`; - } - - [$getParent]() { - return this[_parent]; - } - - [$isDataValue]() { - return true; - } - - [$getDataValue]() { - return this[$content].trim(); - } - - [$setValue](value) { - value = value.value || ""; - this[$content] = value.toString(); - } - - [$text]() { - return this[$content]; - } - - [$isDescendent](parent) { - return this[_parent] === parent || this[_parent][$isDescendent](parent); - } - -} - -exports.XFAAttribute = XFAAttribute; - -class XmlObject extends XFAObject { - constructor(nsId, name, attributes = {}) { - super(nsId, name); - this[$content] = ""; - this[_dataValue] = null; - - if (name !== "#text") { - const map = new Map(); - this[_attributes] = map; - - for (const [attrName, value] of Object.entries(attributes)) { - map.set(attrName, new XFAAttribute(this, attrName, value)); - } - - if (attributes.hasOwnProperty($nsAttributes)) { - const dataNode = attributes[$nsAttributes].xfa.dataNode; - - if (dataNode !== undefined) { - if (dataNode === "dataGroup") { - this[_dataValue] = false; - } else if (dataNode === "dataValue") { - this[_dataValue] = true; - } - } - } - } - - this[$consumed] = false; - } - - [$toString](buf) { - const tagName = this[$nodeName]; - - if (tagName === "#text") { - buf.push((0, _core_utils.encodeToXmlString)(this[$content])); - return; - } - - const utf8TagName = (0, _util.utf8StringToString)(tagName); - const prefix = this[$namespaceId] === NS_DATASETS ? "xfa:" : ""; - buf.push(`<${prefix}${utf8TagName}`); - - for (const [name, value] of this[_attributes].entries()) { - const utf8Name = (0, _util.utf8StringToString)(name); - buf.push(` ${utf8Name}="${(0, _core_utils.encodeToXmlString)(value[$content])}"`); - } - - if (this[_dataValue] !== null) { - if (this[_dataValue]) { - buf.push(` xfa:dataNode="dataValue"`); - } else { - buf.push(` xfa:dataNode="dataGroup"`); - } - } - - if (!this[$content] && this[_children].length === 0) { - buf.push("/>"); - return; - } - - buf.push(">"); - - if (this[$content]) { - if (typeof this[$content] === "string") { - buf.push((0, _core_utils.encodeToXmlString)(this[$content])); - } else { - this[$content][$toString](buf); - } - } else { - for (const child of this[_children]) { - child[$toString](buf); - } - } - - buf.push(``); - } - - [$onChild](child) { - if (this[$content]) { - const node = new XmlObject(this[$namespaceId], "#text"); - this[$appendChild](node); - node[$content] = this[$content]; - this[$content] = ""; - } - - this[$appendChild](child); - return true; - } - - [$onText](str) { - this[$content] += str; - } - - [$finalize]() { - if (this[$content] && this[_children].length > 0) { - const node = new XmlObject(this[$namespaceId], "#text"); - this[$appendChild](node); - node[$content] = this[$content]; - delete this[$content]; - } - } - - [$toHTML]() { - if (this[$nodeName] === "#text") { - return _utils.HTMLResult.success({ - name: "#text", - value: this[$content] - }); - } - - return _utils.HTMLResult.EMPTY; - } - - [$getChildren](name = null) { - if (!name) { - return this[_children]; - } - - return this[_children].filter(c => c[$nodeName] === name); - } - - [$getAttributes]() { - return this[_attributes]; - } - - [$getChildrenByClass](name) { - const value = this[_attributes].get(name); - - if (value !== undefined) { - return value; - } - - return this[$getChildren](name); - } - - *[$getChildrenByNameIt](name, allTransparent) { - const value = this[_attributes].get(name); - - if (value) { - yield value; - } - - for (const child of this[_children]) { - if (child[$nodeName] === name) { - yield child; - } - - if (allTransparent) { - yield* child[$getChildrenByNameIt](name, allTransparent); - } - } - } - - *[$getAttributeIt](name, skipConsumed) { - const value = this[_attributes].get(name); - - if (value && (!skipConsumed || !value[$consumed])) { - yield value; - } - - for (const child of this[_children]) { - yield* child[$getAttributeIt](name, skipConsumed); - } - } - - *[$getRealChildrenByNameIt](name, allTransparent, skipConsumed) { - for (const child of this[_children]) { - if (child[$nodeName] === name && (!skipConsumed || !child[$consumed])) { - yield child; - } - - if (allTransparent) { - yield* child[$getRealChildrenByNameIt](name, allTransparent, skipConsumed); - } - } - } - - [$isDataValue]() { - if (this[_dataValue] === null) { - return this[_children].length === 0 || this[_children][0][$namespaceId] === _namespaces.NamespaceIds.xhtml.id; - } - - return this[_dataValue]; - } - - [$getDataValue]() { - if (this[_dataValue] === null) { - if (this[_children].length === 0) { - return this[$content].trim(); - } - - if (this[_children][0][$namespaceId] === _namespaces.NamespaceIds.xhtml.id) { - return this[_children][0][$text]().trim(); - } - - return null; - } - - return this[$content].trim(); - } - - [$setValue](value) { - value = value.value || ""; - this[$content] = value.toString(); - } - - [$dump](hasNS = false) { - const dumped = Object.create(null); - - if (hasNS) { - dumped.$ns = this[$namespaceId]; - } - - if (this[$content]) { - dumped.$content = this[$content]; - } - - dumped.$name = this[$nodeName]; - dumped.children = []; - - for (const child of this[_children]) { - dumped.children.push(child[$dump](hasNS)); - } - - dumped.attributes = Object.create(null); - - for (const [name, value] of this[_attributes]) { - dumped.attributes[name] = value[$content]; - } - - return dumped; - } - -} - -exports.XmlObject = XmlObject; - -class ContentObject extends XFAObject { - constructor(nsId, name) { - super(nsId, name); - this[$content] = ""; - } - - [$onText](text) { - this[$content] += text; - } - - [$finalize]() {} - -} - -exports.ContentObject = ContentObject; - -class OptionObject extends ContentObject { - constructor(nsId, name, options) { - super(nsId, name); - this[_options] = options; - } - - [$finalize]() { - this[$content] = (0, _utils.getKeyword)({ - data: this[$content], - defaultValue: this[_options][0], - validate: k => this[_options].includes(k) - }); - } - - [$clean](builder) { - super[$clean](builder); - delete this[_options]; - } - -} - -exports.OptionObject = OptionObject; - -class StringObject extends ContentObject { - [$finalize]() { - this[$content] = this[$content].trim(); - } - -} - -exports.StringObject = StringObject; - -class IntegerObject extends ContentObject { - constructor(nsId, name, defaultValue, validator) { - super(nsId, name); - this[_defaultValue] = defaultValue; - this[_validator] = validator; - } - - [$finalize]() { - this[$content] = (0, _utils.getInteger)({ - data: this[$content], - defaultValue: this[_defaultValue], - validate: this[_validator] - }); - } - - [$clean](builder) { - super[$clean](builder); - delete this[_defaultValue]; - delete this[_validator]; - } - -} - -exports.IntegerObject = IntegerObject; - -class Option01 extends IntegerObject { - constructor(nsId, name) { - super(nsId, name, 0, n => n === 1); - } - -} - -exports.Option01 = Option01; - -class Option10 extends IntegerObject { - constructor(nsId, name) { - super(nsId, name, 1, n => n === 0); - } - -} - -exports.Option10 = Option10; - -/***/ }), -/* 76 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.HTMLResult = void 0; -exports.getBBox = getBBox; -exports.getColor = getColor; -exports.getFloat = getFloat; -exports.getInteger = getInteger; -exports.getKeyword = getKeyword; -exports.getMeasurement = getMeasurement; -exports.getRatio = getRatio; -exports.getRelevant = getRelevant; -exports.getStringOption = getStringOption; -exports.stripQuotes = stripQuotes; - -var _util = __w_pdfjs_require__(2); - -const dimConverters = { - pt: x => x, - cm: x => x / 2.54 * 72, - mm: x => x / (10 * 2.54) * 72, - in: x => x * 72, - px: x => x -}; -const measurementPattern = /([+-]?\d+\.?\d*)(.*)/; - -function stripQuotes(str) { - if (str.startsWith("'") || str.startsWith('"')) { - return str.slice(1, str.length - 1); - } - - return str; -} - -function getInteger({ - data, - defaultValue, - validate -}) { - if (!data) { - return defaultValue; - } - - data = data.trim(); - const n = parseInt(data, 10); - - if (!isNaN(n) && validate(n)) { - return n; - } - - return defaultValue; -} - -function getFloat({ - data, - defaultValue, - validate -}) { - if (!data) { - return defaultValue; - } - - data = data.trim(); - const n = parseFloat(data); - - if (!isNaN(n) && validate(n)) { - return n; - } - - return defaultValue; -} - -function getKeyword({ - data, - defaultValue, - validate -}) { - if (!data) { - return defaultValue; - } - - data = data.trim(); - - if (validate(data)) { - return data; - } - - return defaultValue; -} - -function getStringOption(data, options) { - return getKeyword({ - data, - defaultValue: options[0], - validate: k => options.includes(k) - }); -} - -function getMeasurement(str, def = "0") { - def = def || "0"; - - if (!str) { - return getMeasurement(def); - } - - const match = str.trim().match(measurementPattern); - - if (!match) { - return getMeasurement(def); - } - - const [, valueStr, unit] = match; - const value = parseFloat(valueStr); - - if (isNaN(value)) { - return getMeasurement(def); - } - - if (value === 0) { - return 0; - } - - const conv = dimConverters[unit]; - - if (conv) { - return conv(value); - } - - return value; -} - -function getRatio(data) { - if (!data) { - return { - num: 1, - den: 1 - }; - } - - const ratio = data.trim().split(/\s*:\s*/).map(x => parseFloat(x)).filter(x => !isNaN(x)); - - if (ratio.length === 1) { - ratio.push(1); - } - - if (ratio.length === 0) { - return { - num: 1, - den: 1 - }; - } - - const [num, den] = ratio; - return { - num, - den - }; -} - -function getRelevant(data) { - if (!data) { - return []; - } - - return data.trim().split(/\s+/).map(e => { - return { - excluded: e[0] === "-", - viewname: e.substring(1) - }; - }); -} - -function getColor(data, def = [0, 0, 0]) { - let [r, g, b] = def; - - if (!data) { - return { - r, - g, - b - }; - } - - const color = data.trim().split(/\s*,\s*/).map(c => Math.min(Math.max(0, parseInt(c.trim(), 10)), 255)).map(c => isNaN(c) ? 0 : c); - - if (color.length < 3) { - return { - r, - g, - b - }; - } - - [r, g, b] = color; - return { - r, - g, - b - }; -} - -function getBBox(data) { - const def = -1; - - if (!data) { - return { - x: def, - y: def, - width: def, - height: def - }; - } - - const bbox = data.trim().split(/\s*,\s*/).map(m => getMeasurement(m, "-1")); - - if (bbox.length < 4 || bbox[2] < 0 || bbox[3] < 0) { - return { - x: def, - y: def, - width: def, - height: def - }; - } - - const [x, y, width, height] = bbox; - return { - x, - y, - width, - height - }; -} - -class HTMLResult { - static get FAILURE() { - return (0, _util.shadow)(this, "FAILURE", new HTMLResult(false, null, null, null)); - } - - static get EMPTY() { - return (0, _util.shadow)(this, "EMPTY", new HTMLResult(true, null, null, null)); - } - - constructor(success, html, bbox, breakNode) { - this.success = success; - this.html = html; - this.bbox = bbox; - this.breakNode = breakNode; - } - - isBreak() { - return !!this.breakNode; - } - - static breakNode(node) { - return new HTMLResult(false, null, null, node); - } - - static success(html, bbox = null) { - return new HTMLResult(true, html, bbox, null); - } - -} - -exports.HTMLResult = HTMLResult; - -/***/ }), -/* 77 */ -/***/ ((__unused_webpack_module, exports) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.NamespaceIds = exports.$buildXFAObject = void 0; -const $buildXFAObject = Symbol(); -exports.$buildXFAObject = $buildXFAObject; -const NamespaceIds = { - config: { - id: 0, - check: ns => ns.startsWith("http://www.xfa.org/schema/xci/") - }, - connectionSet: { - id: 1, - check: ns => ns.startsWith("http://www.xfa.org/schema/xfa-connection-set/") - }, - datasets: { - id: 2, - check: ns => ns.startsWith("http://www.xfa.org/schema/xfa-data/") - }, - form: { - id: 3, - check: ns => ns.startsWith("http://www.xfa.org/schema/xfa-form/") - }, - localeSet: { - id: 4, - check: ns => ns.startsWith("http://www.xfa.org/schema/xfa-locale-set/") - }, - pdf: { - id: 5, - check: ns => ns === "http://ns.adobe.com/xdp/pdf/" - }, - signature: { - id: 6, - check: ns => ns === "http://www.w3.org/2000/09/xmldsig#" - }, - sourceSet: { - id: 7, - check: ns => ns.startsWith("http://www.xfa.org/schema/xfa-source-set/") - }, - stylesheet: { - id: 8, - check: ns => ns === "http://www.w3.org/1999/XSL/Transform" - }, - template: { - id: 9, - check: ns => ns.startsWith("http://www.xfa.org/schema/xfa-template/") - }, - xdc: { - id: 10, - check: ns => ns.startsWith("http://www.xfa.org/schema/xdc/") - }, - xdp: { - id: 11, - check: ns => ns === "http://ns.adobe.com/xdp/" - }, - xfdf: { - id: 12, - check: ns => ns === "http://ns.adobe.com/xfdf/" - }, - xhtml: { - id: 13, - check: ns => ns === "http://www.w3.org/1999/xhtml" - }, - xmpmeta: { - id: 14, - check: ns => ns === "http://ns.adobe.com/xmpmeta/" - } -}; -exports.NamespaceIds = NamespaceIds; - -/***/ }), -/* 78 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.createDataNode = createDataNode; -exports.searchNode = searchNode; - -var _xfa_object = __w_pdfjs_require__(75); - -var _namespaces = __w_pdfjs_require__(77); - -var _util = __w_pdfjs_require__(2); - -const namePattern = /^[^.[]+/; -const indexPattern = /^[^\]]+/; -const operators = { - dot: 0, - dotDot: 1, - dotHash: 2, - dotBracket: 3, - dotParen: 4 -}; -const shortcuts = new Map([["$data", (root, current) => root.datasets ? root.datasets.data : root], ["$record", (root, current) => (root.datasets ? root.datasets.data : root)[_xfa_object.$getChildren]()[0]], ["$template", (root, current) => root.template], ["$connectionSet", (root, current) => root.connectionSet], ["$form", (root, current) => root.form], ["$layout", (root, current) => root.layout], ["$host", (root, current) => root.host], ["$dataWindow", (root, current) => root.dataWindow], ["$event", (root, current) => root.event], ["!", (root, current) => root.datasets], ["$xfa", (root, current) => root], ["xfa", (root, current) => root], ["$", (root, current) => current]]); -const somCache = new WeakMap(); -const NS_DATASETS = _namespaces.NamespaceIds.datasets.id; - -function parseIndex(index) { - index = index.trim(); - - if (index === "*") { - return Infinity; - } - - return parseInt(index, 10) || 0; -} - -function parseExpression(expr, dotDotAllowed, noExpr = true) { - let match = expr.match(namePattern); - - if (!match) { - return null; - } - - let [name] = match; - const parsed = [{ - name, - cacheName: "." + name, - index: 0, - js: null, - formCalc: null, - operator: operators.dot - }]; - let pos = name.length; - - while (pos < expr.length) { - const spos = pos; - const char = expr.charAt(pos++); - - if (char === "[") { - match = expr.slice(pos).match(indexPattern); - - if (!match) { - (0, _util.warn)("XFA - Invalid index in SOM expression"); - return null; - } - - parsed[parsed.length - 1].index = parseIndex(match[0]); - pos += match[0].length + 1; - continue; - } - - let operator; - - switch (expr.charAt(pos)) { - case ".": - if (!dotDotAllowed) { - return null; - } - - pos++; - operator = operators.dotDot; - break; - - case "#": - pos++; - operator = operators.dotHash; - break; - - case "[": - if (noExpr) { - (0, _util.warn)("XFA - SOM expression contains a FormCalc subexpression which is not supported for now."); - return null; - } - - operator = operators.dotBracket; - break; - - case "(": - if (noExpr) { - (0, _util.warn)("XFA - SOM expression contains a JavaScript subexpression which is not supported for now."); - return null; - } - - operator = operators.dotParen; - break; - - default: - operator = operators.dot; - break; - } - - match = expr.slice(pos).match(namePattern); - - if (!match) { - break; - } - - [name] = match; - pos += name.length; - parsed.push({ - name, - cacheName: expr.slice(spos, pos), - operator, - index: 0, - js: null, - formCalc: null - }); - } - - return parsed; -} - -function searchNode(root, container, expr, dotDotAllowed = true, useCache = true) { - const parsed = parseExpression(expr, dotDotAllowed); - - if (!parsed) { - return null; - } - - const fn = shortcuts.get(parsed[0].name); - let i = 0; - let isQualified; - - if (fn) { - isQualified = true; - root = [fn(root, container)]; - i = 1; - } else { - isQualified = container === null; - root = [container || root]; - } - - for (let ii = parsed.length; i < ii; i++) { - const { - name, - cacheName, - operator, - index - } = parsed[i]; - const nodes = []; - - for (const node of root) { - if (!(node instanceof _xfa_object.XFAObject)) { - continue; - } - - let children, cached; - - if (useCache) { - cached = somCache.get(node); - - if (!cached) { - cached = new Map(); - somCache.set(node, cached); - } - - children = cached.get(cacheName); - } - - if (!children) { - switch (operator) { - case operators.dot: - children = node[_xfa_object.$getChildrenByName](name, false); - break; - - case operators.dotDot: - children = node[_xfa_object.$getChildrenByName](name, true); - break; - - case operators.dotHash: - children = node[_xfa_object.$getChildrenByClass](name); - - if (children instanceof _xfa_object.XFAObjectArray) { - children = children.children; - } else { - children = [children]; - } - - break; - - default: - break; - } - - if (useCache) { - cached.set(cacheName, children); - } - } - - if (children.length > 0) { - nodes.push(children); - } - } - - if (nodes.length === 0 && !isQualified && i === 0) { - const parent = container[_xfa_object.$getParent](); - - container = parent; - - if (!container) { - return null; - } - - i = -1; - root = [container]; - continue; - } - - if (isFinite(index)) { - root = nodes.filter(node => index < node.length).map(node => node[index]); - } else { - root = nodes.reduce((acc, node) => acc.concat(node), []); - } - } - - if (root.length === 0) { - return null; - } - - return root; -} - -function createNodes(root, path) { - let node = null; - - for (const { - name, - index - } of path) { - for (let i = 0, ii = !isFinite(index) ? 0 : index; i <= ii; i++) { - const nsId = root[_xfa_object.$namespaceId] === NS_DATASETS ? -1 : root[_xfa_object.$namespaceId]; - node = new _xfa_object.XmlObject(nsId, name); - - root[_xfa_object.$appendChild](node); - } - - root = node; - } - - return node; -} - -function createDataNode(root, container, expr) { - const parsed = parseExpression(expr); - - if (!parsed) { - return null; - } - - if (parsed.some(x => x.operator === operators.dotDot)) { - return null; - } - - const fn = shortcuts.get(parsed[0].name); - let i = 0; - - if (fn) { - root = fn(root, container); - i = 1; - } else { - root = container || root; - } - - for (let ii = parsed.length; i < ii; i++) { - const { - name, - operator, - index - } = parsed[i]; - - if (!isFinite(index)) { - parsed[i].index = 0; - return createNodes(root, parsed.slice(i)); - } - - let children; - - switch (operator) { - case operators.dot: - children = root[_xfa_object.$getChildrenByName](name, false); - break; - - case operators.dotDot: - children = root[_xfa_object.$getChildrenByName](name, true); - break; - - case operators.dotHash: - children = root[_xfa_object.$getChildrenByClass](name); - - if (children instanceof _xfa_object.XFAObjectArray) { - children = children.children; - } else { - children = [children]; - } - - break; - - default: - break; - } - - if (children.length === 0) { - return createNodes(root, parsed.slice(i)); - } - - if (index < children.length) { - const child = children[index]; - - if (!(child instanceof _xfa_object.XFAObject)) { - (0, _util.warn)(`XFA - Cannot create a node.`); - return null; - } - - root = child; - } else { - parsed[i].index = index - children.length; - return createNodes(root, parsed.slice(i)); - } - } - - return null; -} - -/***/ }), -/* 79 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.Binder = void 0; - -var _xfa_object = __w_pdfjs_require__(75); - -var _template = __w_pdfjs_require__(80); - -var _som = __w_pdfjs_require__(78); - -var _namespaces = __w_pdfjs_require__(77); - -var _util = __w_pdfjs_require__(2); - -const NS_DATASETS = _namespaces.NamespaceIds.datasets.id; - -function createText(content) { - const node = new _template.Text({}); - node[_xfa_object.$content] = content; - return node; -} - -class Binder { - constructor(root) { - this.root = root; - this.datasets = root.datasets; - - if (root.datasets && root.datasets.data) { - this.data = root.datasets.data; - } else { - this.data = new _xfa_object.XmlObject(_namespaces.NamespaceIds.datasets.id, "data"); - } - - this.emptyMerge = this.data[_xfa_object.$getChildren]().length === 0; - this.root.form = this.form = root.template[_xfa_object.$clone](); - } - - _isConsumeData() { - return !this.emptyMerge && this._mergeMode; - } - - _isMatchTemplate() { - return !this._isConsumeData(); - } - - bind() { - this._bindElement(this.form, this.data); - - return this.form; - } - - getData() { - return this.data; - } - - _bindValue(formNode, data, picture) { - formNode[_xfa_object.$data] = data; - - if (formNode[_xfa_object.$hasSettableValue]()) { - if (data[_xfa_object.$isDataValue]()) { - const value = data[_xfa_object.$getDataValue](); - - formNode[_xfa_object.$setValue](createText(value)); - } else if (formNode instanceof _template.Field && formNode.ui && formNode.ui.choiceList && formNode.ui.choiceList.open === "multiSelect") { - const value = data[_xfa_object.$getChildren]().map(child => child[_xfa_object.$content].trim()).join("\n"); - - formNode[_xfa_object.$setValue](createText(value)); - } else if (this._isConsumeData()) { - (0, _util.warn)(`XFA - Nodes haven't the same type.`); - } - } else if (!data[_xfa_object.$isDataValue]() || this._isMatchTemplate()) { - this._bindElement(formNode, data); - } else { - (0, _util.warn)(`XFA - Nodes haven't the same type.`); - } - } - - _findDataByNameToConsume(name, isValue, dataNode, global) { - if (!name) { - return null; - } - - let generator, match; - - for (let i = 0; i < 3; i++) { - generator = dataNode[_xfa_object.$getRealChildrenByNameIt](name, false, true); - - while (true) { - match = generator.next().value; - - if (!match) { - break; - } - - if (isValue === match[_xfa_object.$isDataValue]()) { - return match; - } - } - - if (dataNode[_xfa_object.$namespaceId] === _namespaces.NamespaceIds.datasets.id && dataNode[_xfa_object.$nodeName] === "data") { - break; - } - - dataNode = dataNode[_xfa_object.$getParent](); - } - - if (!global) { - return null; - } - - generator = this.data[_xfa_object.$getRealChildrenByNameIt](name, true, false); - match = generator.next().value; - - if (match) { - return match; - } - - generator = this.data[_xfa_object.$getAttributeIt](name, true); - match = generator.next().value; - - if (match && match[_xfa_object.$isDataValue]()) { - return match; - } - - return null; - } - - _setProperties(formNode, dataNode) { - if (!formNode.hasOwnProperty("setProperty")) { - return; - } - - for (const { - ref, - target, - connection - } of formNode.setProperty.children) { - if (connection) { - continue; - } - - if (!ref) { - continue; - } - - const nodes = (0, _som.searchNode)(this.root, dataNode, ref, false, false); - - if (!nodes) { - (0, _util.warn)(`XFA - Invalid reference: ${ref}.`); - continue; - } - - const [node] = nodes; - - if (!node[_xfa_object.$isDescendent](this.data)) { - (0, _util.warn)(`XFA - Invalid node: must be a data node.`); - continue; - } - - const targetNodes = (0, _som.searchNode)(this.root, formNode, target, false, false); - - if (!targetNodes) { - (0, _util.warn)(`XFA - Invalid target: ${target}.`); - continue; - } - - const [targetNode] = targetNodes; - - if (!targetNode[_xfa_object.$isDescendent](formNode)) { - (0, _util.warn)(`XFA - Invalid target: must be a property or subproperty.`); - continue; - } - - const targetParent = targetNode[_xfa_object.$getParent](); - - if (targetNode instanceof _template.SetProperty || targetParent instanceof _template.SetProperty) { - (0, _util.warn)(`XFA - Invalid target: cannot be a setProperty or one of its properties.`); - continue; - } - - if (targetNode instanceof _template.BindItems || targetParent instanceof _template.BindItems) { - (0, _util.warn)(`XFA - Invalid target: cannot be a bindItems or one of its properties.`); - continue; - } - - const content = node[_xfa_object.$text](); - - const name = targetNode[_xfa_object.$nodeName]; - - if (targetNode instanceof _xfa_object.XFAAttribute) { - const attrs = Object.create(null); - attrs[name] = content; - const obj = Reflect.construct(Object.getPrototypeOf(targetParent).constructor, [attrs]); - targetParent[name] = obj[name]; - continue; - } - - if (!targetNode.hasOwnProperty(_xfa_object.$content)) { - (0, _util.warn)(`XFA - Invalid node to use in setProperty`); - continue; - } - - targetNode[_xfa_object.$data] = node; - targetNode[_xfa_object.$content] = content; - - targetNode[_xfa_object.$finalize](); - } - } - - _bindItems(formNode, dataNode) { - if (!formNode.hasOwnProperty("items") || !formNode.hasOwnProperty("bindItems") || formNode.bindItems.isEmpty()) { - return; - } - - for (const item of formNode.items.children) { - formNode[_xfa_object.$removeChild](item); - } - - formNode.items.clear(); - const labels = new _template.Items({}); - const values = new _template.Items({}); - - formNode[_xfa_object.$appendChild](labels); - - formNode.items.push(labels); - - formNode[_xfa_object.$appendChild](values); - - formNode.items.push(values); - - for (const { - ref, - labelRef, - valueRef, - connection - } of formNode.bindItems.children) { - if (connection) { - continue; - } - - if (!ref) { - continue; - } - - const nodes = (0, _som.searchNode)(this.root, dataNode, ref, false, false); - - if (!nodes) { - (0, _util.warn)(`XFA - Invalid reference: ${ref}.`); - continue; - } - - for (const node of nodes) { - if (!node[_xfa_object.$isDescendent](this.datasets)) { - (0, _util.warn)(`XFA - Invalid ref (${ref}): must be a datasets child.`); - continue; - } - - const labelNodes = (0, _som.searchNode)(this.root, node, labelRef, true, false); - - if (!labelNodes) { - (0, _util.warn)(`XFA - Invalid label: ${labelRef}.`); - continue; - } - - const [labelNode] = labelNodes; - - if (!labelNode[_xfa_object.$isDescendent](this.datasets)) { - (0, _util.warn)(`XFA - Invalid label: must be a datasets child.`); - continue; - } - - const valueNodes = (0, _som.searchNode)(this.root, node, valueRef, true, false); - - if (!valueNodes) { - (0, _util.warn)(`XFA - Invalid value: ${valueRef}.`); - continue; - } - - const [valueNode] = valueNodes; - - if (!valueNode[_xfa_object.$isDescendent](this.datasets)) { - (0, _util.warn)(`XFA - Invalid value: must be a datasets child.`); - continue; - } - - const label = createText(labelNode[_xfa_object.$text]()); - const value = createText(valueNode[_xfa_object.$text]()); - - labels[_xfa_object.$appendChild](label); - - labels.text.push(label); - - values[_xfa_object.$appendChild](value); - - values.text.push(value); - } - } - } - - _bindOccurrences(formNode, matches, picture) { - let baseClone; - - if (matches.length > 1) { - baseClone = formNode[_xfa_object.$clone](); - - baseClone[_xfa_object.$removeChild](baseClone.occur); - - baseClone.occur = null; - } - - this._bindValue(formNode, matches[0], picture); - - this._setProperties(formNode, matches[0]); - - this._bindItems(formNode, matches[0]); - - if (matches.length === 1) { - return; - } - - const parent = formNode[_xfa_object.$getParent](); - - const name = formNode[_xfa_object.$nodeName]; - - const pos = parent[_xfa_object.$indexOf](formNode); - - for (let i = 1, ii = matches.length; i < ii; i++) { - const match = matches[i]; - - const clone = baseClone[_xfa_object.$clone](); - - parent[name].push(clone); - - parent[_xfa_object.$insertAt](pos + i, clone); - - this._bindValue(clone, match, picture); - - this._setProperties(clone, match); - - this._bindItems(clone, match); - } - } - - _createOccurrences(formNode) { - if (!this.emptyMerge) { - return; - } - - const { - occur - } = formNode; - - if (!occur || occur.initial <= 1) { - return; - } - - const parent = formNode[_xfa_object.$getParent](); - - const name = formNode[_xfa_object.$nodeName]; - - if (!(parent[name] instanceof _xfa_object.XFAObjectArray)) { - return; - } - - let currentNumber; - - if (formNode.name) { - currentNumber = parent[name].children.filter(e => e.name === formNode.name).length; - } else { - currentNumber = parent[name].children.length; - } - - const pos = parent[_xfa_object.$indexOf](formNode) + 1; - const ii = occur.initial - currentNumber; - - if (ii) { - const nodeClone = formNode[_xfa_object.$clone](); - - nodeClone[_xfa_object.$removeChild](nodeClone.occur); - - nodeClone.occur = null; - parent[name].push(nodeClone); - - parent[_xfa_object.$insertAt](pos, nodeClone); - - for (let i = 1; i < ii; i++) { - const clone = nodeClone[_xfa_object.$clone](); - - parent[name].push(clone); - - parent[_xfa_object.$insertAt](pos + i, clone); - } - } - } - - _getOccurInfo(formNode) { - const { - name, - occur - } = formNode; - - if (!occur || !name) { - return [1, 1]; - } - - const max = occur.max === -1 ? Infinity : occur.max; - return [occur.min, max]; - } - - _setAndBind(formNode, dataNode) { - this._setProperties(formNode, dataNode); - - this._bindItems(formNode, dataNode); - - this._bindElement(formNode, dataNode); - } - - _bindElement(formNode, dataNode) { - const uselessNodes = []; - - this._createOccurrences(formNode); - - for (const child of formNode[_xfa_object.$getChildren]()) { - if (child[_xfa_object.$data]) { - continue; - } - - if (this._mergeMode === undefined && child[_xfa_object.$nodeName] === "subform") { - this._mergeMode = child.mergeMode === "consumeData"; - - const dataChildren = dataNode[_xfa_object.$getChildren](); - - if (dataChildren.length > 0) { - this._bindOccurrences(child, [dataChildren[0]], null); - } else if (this.emptyMerge) { - const nsId = dataNode[_xfa_object.$namespaceId] === NS_DATASETS ? -1 : dataNode[_xfa_object.$namespaceId]; - const dataChild = child[_xfa_object.$data] = new _xfa_object.XmlObject(nsId, child.name || "root"); - - dataNode[_xfa_object.$appendChild](dataChild); - - this._bindElement(child, dataChild); - } - - continue; - } - - if (!child[_xfa_object.$isBindable]()) { - continue; - } - - let global = false; - let picture = null; - let ref = null; - let match = null; - - if (child.bind) { - switch (child.bind.match) { - case "none": - this._setAndBind(child, dataNode); - - continue; - - case "global": - global = true; - break; - - case "dataRef": - if (!child.bind.ref) { - (0, _util.warn)(`XFA - ref is empty in node ${child[_xfa_object.$nodeName]}.`); - - this._setAndBind(child, dataNode); - - continue; - } - - ref = child.bind.ref; - break; - - default: - break; - } - - if (child.bind.picture) { - picture = child.bind.picture[_xfa_object.$content]; - } - } - - const [min, max] = this._getOccurInfo(child); - - if (ref) { - match = (0, _som.searchNode)(this.root, dataNode, ref, true, false); - - if (match === null) { - match = (0, _som.createDataNode)(this.data, dataNode, ref); - - if (!match) { - continue; - } - - if (this._isConsumeData()) { - match[_xfa_object.$consumed] = true; - } - - this._setAndBind(child, match); - - continue; - } else { - if (this._isConsumeData()) { - match = match.filter(node => !node[_xfa_object.$consumed]); - } - - if (match.length > max) { - match = match.slice(0, max); - } else if (match.length === 0) { - match = null; - } - - if (match && this._isConsumeData()) { - match.forEach(node => { - node[_xfa_object.$consumed] = true; - }); - } - } - } else { - if (!child.name) { - this._setAndBind(child, dataNode); - - continue; - } - - if (this._isConsumeData()) { - const matches = []; - - while (matches.length < max) { - const found = this._findDataByNameToConsume(child.name, child[_xfa_object.$hasSettableValue](), dataNode, global); - - if (!found) { - break; - } - - found[_xfa_object.$consumed] = true; - matches.push(found); - } - - match = matches.length > 0 ? matches : null; - } else { - match = dataNode[_xfa_object.$getRealChildrenByNameIt](child.name, false, this.emptyMerge).next().value; - - if (!match) { - if (min === 0) { - uselessNodes.push(child); - continue; - } - - const nsId = dataNode[_xfa_object.$namespaceId] === NS_DATASETS ? -1 : dataNode[_xfa_object.$namespaceId]; - match = child[_xfa_object.$data] = new _xfa_object.XmlObject(nsId, child.name); - - if (this.emptyMerge) { - match[_xfa_object.$consumed] = true; - } - - dataNode[_xfa_object.$appendChild](match); - - this._setAndBind(child, match); - - continue; - } - - if (this.emptyMerge) { - match[_xfa_object.$consumed] = true; - } - - match = [match]; - } - } - - if (match) { - this._bindOccurrences(child, match, picture); - } else if (min > 0) { - this._setAndBind(child, dataNode); - } else { - uselessNodes.push(child); - } - } - - uselessNodes.forEach(node => node[_xfa_object.$getParent]()[_xfa_object.$removeChild](node)); - } - -} - -exports.Binder = Binder; - -/***/ }), -/* 80 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.Value = exports.Text = exports.TemplateNamespace = exports.Template = exports.SetProperty = exports.Items = exports.Field = exports.BindItems = void 0; - -var _xfa_object = __w_pdfjs_require__(75); - -var _namespaces = __w_pdfjs_require__(77); - -var _layout = __w_pdfjs_require__(81); - -var _html_utils = __w_pdfjs_require__(82); - -var _utils = __w_pdfjs_require__(76); - -var _util = __w_pdfjs_require__(2); - -var _fonts = __w_pdfjs_require__(83); - -var _core_utils = __w_pdfjs_require__(9); - -var _som = __w_pdfjs_require__(78); - -const TEMPLATE_NS_ID = _namespaces.NamespaceIds.template.id; -const SVG_NS = "http://www.w3.org/2000/svg"; -const MAX_ATTEMPTS_FOR_LRTB_LAYOUT = 2; -const MAX_EMPTY_PAGES = 3; -const DEFAULT_TAB_INDEX = 5000; -const HEADING_PATTERN = /^H(\d+)$/; -const MIMES = new Set(["image/gif", "image/jpeg", "image/jpg", "image/pjpeg", "image/png", "image/apng", "image/x-png", "image/bmp", "image/x-ms-bmp", "image/tiff", "image/tif", "application/octet-stream"]); -const IMAGES_HEADERS = [[[0x42, 0x4d], "image/bmp"], [[0xff, 0xd8, 0xff], "image/jpeg"], [[0x49, 0x49, 0x2a, 0x00], "image/tiff"], [[0x4d, 0x4d, 0x00, 0x2a], "image/tiff"], [[0x47, 0x49, 0x46, 0x38, 0x39, 0x61], "image/gif"], [[0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a], "image/png"]]; - -function getBorderDims(node) { - if (!node || !node.border) { - return { - w: 0, - h: 0 - }; - } - - const borderExtra = node.border[_xfa_object.$getExtra](); - - if (!borderExtra) { - return { - w: 0, - h: 0 - }; - } - - return { - w: borderExtra.widths[0] + borderExtra.widths[2] + borderExtra.insets[0] + borderExtra.insets[2], - h: borderExtra.widths[1] + borderExtra.widths[3] + borderExtra.insets[1] + borderExtra.insets[3] - }; -} - -function hasMargin(node) { - return node.margin && (node.margin.topInset || node.margin.rightInset || node.margin.bottomInset || node.margin.leftInset); -} - -function _setValue(templateNode, value) { - if (!templateNode.value) { - const nodeValue = new Value({}); - - templateNode[_xfa_object.$appendChild](nodeValue); - - templateNode.value = nodeValue; - } - - templateNode.value[_xfa_object.$setValue](value); -} - -function* getContainedChildren(node) { - for (const child of node[_xfa_object.$getChildren]()) { - if (child instanceof SubformSet) { - yield* child[_xfa_object.$getContainedChildren](); - continue; - } - - yield child; - } -} - -function setTabIndex(node) { - while (node) { - if (!node.traversal) { - node[_xfa_object.$tabIndex] = node[_xfa_object.$getParent]()[_xfa_object.$tabIndex]; - return; - } - - if (node[_xfa_object.$tabIndex]) { - return; - } - - let next = null; - - for (const child of node.traversal[_xfa_object.$getChildren]()) { - if (child.operation === "next") { - next = child; - break; - } - } - - if (!next || !next.ref) { - node[_xfa_object.$tabIndex] = node[_xfa_object.$getParent]()[_xfa_object.$tabIndex]; - return; - } - - const root = node[_xfa_object.$getTemplateRoot](); - - node[_xfa_object.$tabIndex] = ++root[_xfa_object.$tabIndex]; - - const ref = root[_xfa_object.$searchNode](next.ref, node); - - if (!ref) { - return; - } - - node = ref[0]; - } -} - -function applyAssist(obj, attributes) { - const assist = obj.assist; - - if (assist) { - const assistTitle = assist[_xfa_object.$toHTML](); - - if (assistTitle) { - attributes.title = assistTitle; - } - - const role = assist.role; - const match = role.match(HEADING_PATTERN); - - if (match) { - const ariaRole = "heading"; - const ariaLevel = match[1]; - attributes.role = ariaRole; - attributes["aria-level"] = ariaLevel; - } - } - - if (obj.layout === "table") { - attributes.role = "table"; - } else if (obj.layout === "row") { - attributes.role = "row"; - } else { - const parent = obj[_xfa_object.$getParent](); - - if (parent.layout === "row") { - if (parent.assist && parent.assist.role === "TH") { - attributes.role = "columnheader"; - } else { - attributes.role = "cell"; - } - } - } -} - -function ariaLabel(obj) { - if (!obj.assist) { - return null; - } - - const assist = obj.assist; - - if (assist.speak && assist.speak[_xfa_object.$content] !== "") { - return assist.speak[_xfa_object.$content]; - } - - if (assist.toolTip) { - return assist.toolTip[_xfa_object.$content]; - } - - return null; -} - -function valueToHtml(value) { - return _utils.HTMLResult.success({ - name: "div", - attributes: { - class: ["xfaRich"], - style: Object.create(null) - }, - children: [{ - name: "span", - attributes: { - style: Object.create(null) - }, - value - }] - }); -} - -function setFirstUnsplittable(node) { - const root = node[_xfa_object.$getTemplateRoot](); - - if (root[_xfa_object.$extra].firstUnsplittable === null) { - root[_xfa_object.$extra].firstUnsplittable = node; - root[_xfa_object.$extra].noLayoutFailure = true; - } -} - -function unsetFirstUnsplittable(node) { - const root = node[_xfa_object.$getTemplateRoot](); - - if (root[_xfa_object.$extra].firstUnsplittable === node) { - root[_xfa_object.$extra].noLayoutFailure = false; - } -} - -function handleBreak(node) { - if (node[_xfa_object.$extra]) { - return false; - } - - node[_xfa_object.$extra] = Object.create(null); - - if (node.targetType === "auto") { - return false; - } - - const root = node[_xfa_object.$getTemplateRoot](); - - let target = null; - - if (node.target) { - target = root[_xfa_object.$searchNode](node.target, node[_xfa_object.$getParent]()); - - if (!target) { - return false; - } - - target = target[0]; - } - - const { - currentPageArea, - currentContentArea - } = root[_xfa_object.$extra]; - - if (node.targetType === "pageArea") { - if (!(target instanceof PageArea)) { - target = null; - } - - if (node.startNew) { - node[_xfa_object.$extra].target = target || currentPageArea; - return true; - } else if (target && target !== currentPageArea) { - node[_xfa_object.$extra].target = target; - return true; - } - - return false; - } - - if (!(target instanceof ContentArea)) { - target = null; - } - - const pageArea = target && target[_xfa_object.$getParent](); - - let index; - let nextPageArea = pageArea; - - if (node.startNew) { - if (target) { - const contentAreas = pageArea.contentArea.children; - const indexForCurrent = contentAreas.indexOf(currentContentArea); - const indexForTarget = contentAreas.indexOf(target); - - if (indexForCurrent !== -1 && indexForCurrent < indexForTarget) { - nextPageArea = null; - } - - index = indexForTarget - 1; - } else { - index = currentPageArea.contentArea.children.indexOf(currentContentArea); - } - } else if (target && target !== currentContentArea) { - const contentAreas = pageArea.contentArea.children; - index = contentAreas.indexOf(target) - 1; - nextPageArea = pageArea === currentPageArea ? null : pageArea; - } else { - return false; - } - - node[_xfa_object.$extra].target = nextPageArea; - node[_xfa_object.$extra].index = index; - return true; -} - -function handleOverflow(node, extraNode, space) { - const root = node[_xfa_object.$getTemplateRoot](); - - const saved = root[_xfa_object.$extra].noLayoutFailure; - const savedMethod = extraNode[_xfa_object.$getSubformParent]; - - extraNode[_xfa_object.$getSubformParent] = () => node; - - root[_xfa_object.$extra].noLayoutFailure = true; - - const res = extraNode[_xfa_object.$toHTML](space); - - node[_xfa_object.$addHTML](res.html, res.bbox); - - root[_xfa_object.$extra].noLayoutFailure = saved; - extraNode[_xfa_object.$getSubformParent] = savedMethod; -} - -class AppearanceFilter extends _xfa_object.StringObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "appearanceFilter"); - this.id = attributes.id || ""; - this.type = (0, _utils.getStringOption)(attributes.type, ["optional", "required"]); - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - } - -} - -class Arc extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "arc", true); - this.circular = (0, _utils.getInteger)({ - data: attributes.circular, - defaultValue: 0, - validate: x => x === 1 - }); - this.hand = (0, _utils.getStringOption)(attributes.hand, ["even", "left", "right"]); - this.id = attributes.id || ""; - this.startAngle = (0, _utils.getFloat)({ - data: attributes.startAngle, - defaultValue: 0, - validate: x => true - }); - this.sweepAngle = (0, _utils.getFloat)({ - data: attributes.sweepAngle, - defaultValue: 360, - validate: x => true - }); - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.edge = null; - this.fill = null; - } - - [_xfa_object.$toHTML]() { - const edge = this.edge ? this.edge : new Edge({}); - - const edgeStyle = edge[_xfa_object.$toStyle](); - - const style = Object.create(null); - - if (this.fill && this.fill.presence === "visible") { - Object.assign(style, this.fill[_xfa_object.$toStyle]()); - } else { - style.fill = "transparent"; - } - - style.strokeWidth = (0, _html_utils.measureToString)(edge.presence === "visible" ? edge.thickness : 0); - style.stroke = edgeStyle.color; - let arc; - const attributes = { - xmlns: SVG_NS, - style: { - width: "100%", - height: "100%", - overflow: "visible" - } - }; - - if (this.sweepAngle === 360) { - arc = { - name: "ellipse", - attributes: { - xmlns: SVG_NS, - cx: "50%", - cy: "50%", - rx: "50%", - ry: "50%", - style - } - }; - } else { - const startAngle = this.startAngle * Math.PI / 180; - const sweepAngle = this.sweepAngle * Math.PI / 180; - const largeArc = this.sweepAngle > 180 ? 1 : 0; - const [x1, y1, x2, y2] = [50 * (1 + Math.cos(startAngle)), 50 * (1 - Math.sin(startAngle)), 50 * (1 + Math.cos(startAngle + sweepAngle)), 50 * (1 - Math.sin(startAngle + sweepAngle))]; - arc = { - name: "path", - attributes: { - xmlns: SVG_NS, - d: `M ${x1} ${y1} A 50 50 0 ${largeArc} 0 ${x2} ${y2}`, - vectorEffect: "non-scaling-stroke", - style - } - }; - Object.assign(attributes, { - viewBox: "0 0 100 100", - preserveAspectRatio: "none" - }); - } - - const svg = { - name: "svg", - children: [arc], - attributes - }; - - const parent = this[_xfa_object.$getParent]()[_xfa_object.$getParent](); - - if (hasMargin(parent)) { - return _utils.HTMLResult.success({ - name: "div", - attributes: { - style: { - display: "inline", - width: "100%", - height: "100%" - } - }, - children: [svg] - }); - } - - svg.attributes.style.position = "absolute"; - return _utils.HTMLResult.success(svg); - } - -} - -class Area extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "area", true); - this.colSpan = (0, _utils.getInteger)({ - data: attributes.colSpan, - defaultValue: 1, - validate: n => n >= 1 || n === -1 - }); - this.id = attributes.id || ""; - this.name = attributes.name || ""; - this.relevant = (0, _utils.getRelevant)(attributes.relevant); - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.x = (0, _utils.getMeasurement)(attributes.x, "0pt"); - this.y = (0, _utils.getMeasurement)(attributes.y, "0pt"); - this.desc = null; - this.extras = null; - this.area = new _xfa_object.XFAObjectArray(); - this.draw = new _xfa_object.XFAObjectArray(); - this.exObject = new _xfa_object.XFAObjectArray(); - this.exclGroup = new _xfa_object.XFAObjectArray(); - this.field = new _xfa_object.XFAObjectArray(); - this.subform = new _xfa_object.XFAObjectArray(); - this.subformSet = new _xfa_object.XFAObjectArray(); - } - - *[_xfa_object.$getContainedChildren]() { - yield* getContainedChildren(this); - } - - [_xfa_object.$isTransparent]() { - return true; - } - - [_xfa_object.$isBindable]() { - return true; - } - - [_xfa_object.$addHTML](html, bbox) { - const [x, y, w, h] = bbox; - this[_xfa_object.$extra].width = Math.max(this[_xfa_object.$extra].width, x + w); - this[_xfa_object.$extra].height = Math.max(this[_xfa_object.$extra].height, y + h); - - this[_xfa_object.$extra].children.push(html); - } - - [_xfa_object.$getAvailableSpace]() { - return this[_xfa_object.$extra].availableSpace; - } - - [_xfa_object.$toHTML](availableSpace) { - const style = (0, _html_utils.toStyle)(this, "position"); - const attributes = { - style, - id: this[_xfa_object.$uid], - class: ["xfaArea"] - }; - - if ((0, _html_utils.isPrintOnly)(this)) { - attributes.class.push("xfaPrintOnly"); - } - - if (this.name) { - attributes.xfaName = this.name; - } - - const children = []; - this[_xfa_object.$extra] = { - children, - width: 0, - height: 0, - availableSpace - }; - - const result = this[_xfa_object.$childrenToHTML]({ - filter: new Set(["area", "draw", "field", "exclGroup", "subform", "subformSet"]), - include: true - }); - - if (!result.success) { - if (result.isBreak()) { - return result; - } - - delete this[_xfa_object.$extra]; - return _utils.HTMLResult.FAILURE; - } - - style.width = (0, _html_utils.measureToString)(this[_xfa_object.$extra].width); - style.height = (0, _html_utils.measureToString)(this[_xfa_object.$extra].height); - const html = { - name: "div", - attributes, - children - }; - const bbox = [this.x, this.y, this[_xfa_object.$extra].width, this[_xfa_object.$extra].height]; - delete this[_xfa_object.$extra]; - return _utils.HTMLResult.success(html, bbox); - } - -} - -class Assist extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "assist", true); - this.id = attributes.id || ""; - this.role = attributes.role || ""; - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.speak = null; - this.toolTip = null; - } - - [_xfa_object.$toHTML]() { - return this.toolTip && this.toolTip[_xfa_object.$content] ? this.toolTip[_xfa_object.$content] : null; - } - -} - -class Barcode extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "barcode", true); - this.charEncoding = (0, _utils.getKeyword)({ - data: attributes.charEncoding ? attributes.charEncoding.toLowerCase() : "", - defaultValue: "", - validate: k => ["utf-8", "big-five", "fontspecific", "gbk", "gb-18030", "gb-2312", "ksc-5601", "none", "shift-jis", "ucs-2", "utf-16"].includes(k) || k.match(/iso-8859-\d{2}/) - }); - this.checksum = (0, _utils.getStringOption)(attributes.checksum, ["none", "1mod10", "1mod10_1mod11", "2mod10", "auto"]); - this.dataColumnCount = (0, _utils.getInteger)({ - data: attributes.dataColumnCount, - defaultValue: -1, - validate: x => x >= 0 - }); - this.dataLength = (0, _utils.getInteger)({ - data: attributes.dataLength, - defaultValue: -1, - validate: x => x >= 0 - }); - this.dataPrep = (0, _utils.getStringOption)(attributes.dataPrep, ["none", "flateCompress"]); - this.dataRowCount = (0, _utils.getInteger)({ - data: attributes.dataRowCount, - defaultValue: -1, - validate: x => x >= 0 - }); - this.endChar = attributes.endChar || ""; - this.errorCorrectionLevel = (0, _utils.getInteger)({ - data: attributes.errorCorrectionLevel, - defaultValue: -1, - validate: x => x >= 0 && x <= 8 - }); - this.id = attributes.id || ""; - this.moduleHeight = (0, _utils.getMeasurement)(attributes.moduleHeight, "5mm"); - this.moduleWidth = (0, _utils.getMeasurement)(attributes.moduleWidth, "0.25mm"); - this.printCheckDigit = (0, _utils.getInteger)({ - data: attributes.printCheckDigit, - defaultValue: 0, - validate: x => x === 1 - }); - this.rowColumnRatio = (0, _utils.getRatio)(attributes.rowColumnRatio); - this.startChar = attributes.startChar || ""; - this.textLocation = (0, _utils.getStringOption)(attributes.textLocation, ["below", "above", "aboveEmbedded", "belowEmbedded", "none"]); - this.truncate = (0, _utils.getInteger)({ - data: attributes.truncate, - defaultValue: 0, - validate: x => x === 1 - }); - this.type = (0, _utils.getStringOption)(attributes.type ? attributes.type.toLowerCase() : "", ["aztec", "codabar", "code2of5industrial", "code2of5interleaved", "code2of5matrix", "code2of5standard", "code3of9", "code3of9extended", "code11", "code49", "code93", "code128", "code128a", "code128b", "code128c", "code128sscc", "datamatrix", "ean8", "ean8add2", "ean8add5", "ean13", "ean13add2", "ean13add5", "ean13pwcd", "fim", "logmars", "maxicode", "msi", "pdf417", "pdf417macro", "plessey", "postauscust2", "postauscust3", "postausreplypaid", "postausstandard", "postukrm4scc", "postusdpbc", "postusimb", "postusstandard", "postus5zip", "qrcode", "rfid", "rss14", "rss14expanded", "rss14limited", "rss14stacked", "rss14stackedomni", "rss14truncated", "telepen", "ucc128", "ucc128random", "ucc128sscc", "upca", "upcaadd2", "upcaadd5", "upcapwcd", "upce", "upceadd2", "upceadd5", "upcean2", "upcean5", "upsmaxicode"]); - this.upsMode = (0, _utils.getStringOption)(attributes.upsMode, ["usCarrier", "internationalCarrier", "secureSymbol", "standardSymbol"]); - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.wideNarrowRatio = (0, _utils.getRatio)(attributes.wideNarrowRatio); - this.encrypt = null; - this.extras = null; - } - -} - -class Bind extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "bind", true); - this.match = (0, _utils.getStringOption)(attributes.match, ["once", "dataRef", "global", "none"]); - this.ref = attributes.ref || ""; - this.picture = null; - } - -} - -class BindItems extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "bindItems"); - this.connection = attributes.connection || ""; - this.labelRef = attributes.labelRef || ""; - this.ref = attributes.ref || ""; - this.valueRef = attributes.valueRef || ""; - } - -} - -exports.BindItems = BindItems; - -class Bookend extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "bookend"); - this.id = attributes.id || ""; - this.leader = attributes.leader || ""; - this.trailer = attributes.trailer || ""; - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - } - -} - -class BooleanElement extends _xfa_object.Option01 { - constructor(attributes) { - super(TEMPLATE_NS_ID, "boolean"); - this.id = attributes.id || ""; - this.name = attributes.name || ""; - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - } - - [_xfa_object.$toHTML](availableSpace) { - return valueToHtml(this[_xfa_object.$content] === 1 ? "1" : "0"); - } - -} - -class Border extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "border", true); - this.break = (0, _utils.getStringOption)(attributes.break, ["close", "open"]); - this.hand = (0, _utils.getStringOption)(attributes.hand, ["even", "left", "right"]); - this.id = attributes.id || ""; - this.presence = (0, _utils.getStringOption)(attributes.presence, ["visible", "hidden", "inactive", "invisible"]); - this.relevant = (0, _utils.getRelevant)(attributes.relevant); - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.corner = new _xfa_object.XFAObjectArray(4); - this.edge = new _xfa_object.XFAObjectArray(4); - this.extras = null; - this.fill = null; - this.margin = null; - } - - [_xfa_object.$getExtra]() { - if (!this[_xfa_object.$extra]) { - const edges = this.edge.children.slice(); - - if (edges.length < 4) { - const defaultEdge = edges[edges.length - 1] || new Edge({}); - - for (let i = edges.length; i < 4; i++) { - edges.push(defaultEdge); - } - } - - const widths = edges.map(edge => edge.thickness); - const insets = [0, 0, 0, 0]; - - if (this.margin) { - insets[0] = this.margin.topInset; - insets[1] = this.margin.rightInset; - insets[2] = this.margin.bottomInset; - insets[3] = this.margin.leftInset; - } - - this[_xfa_object.$extra] = { - widths, - insets, - edges - }; - } - - return this[_xfa_object.$extra]; - } - - [_xfa_object.$toStyle]() { - const { - edges - } = this[_xfa_object.$getExtra](); - - const edgeStyles = edges.map(node => { - const style = node[_xfa_object.$toStyle](); - - style.color = style.color || "#000000"; - return style; - }); - const style = Object.create(null); - - if (this.margin) { - Object.assign(style, this.margin[_xfa_object.$toStyle]()); - } - - if (this.fill && this.fill.presence === "visible") { - Object.assign(style, this.fill[_xfa_object.$toStyle]()); - } - - if (this.corner.children.some(node => node.radius !== 0)) { - const cornerStyles = this.corner.children.map(node => node[_xfa_object.$toStyle]()); - - if (cornerStyles.length === 2 || cornerStyles.length === 3) { - const last = cornerStyles[cornerStyles.length - 1]; - - for (let i = cornerStyles.length; i < 4; i++) { - cornerStyles.push(last); - } - } - - style.borderRadius = cornerStyles.map(s => s.radius).join(" "); - } - - switch (this.presence) { - case "invisible": - case "hidden": - style.borderStyle = ""; - break; - - case "inactive": - style.borderStyle = "none"; - break; - - default: - style.borderStyle = edgeStyles.map(s => s.style).join(" "); - break; - } - - style.borderWidth = edgeStyles.map(s => s.width).join(" "); - style.borderColor = edgeStyles.map(s => s.color).join(" "); - return style; - } - -} - -class Break extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "break", true); - this.after = (0, _utils.getStringOption)(attributes.after, ["auto", "contentArea", "pageArea", "pageEven", "pageOdd"]); - this.afterTarget = attributes.afterTarget || ""; - this.before = (0, _utils.getStringOption)(attributes.before, ["auto", "contentArea", "pageArea", "pageEven", "pageOdd"]); - this.beforeTarget = attributes.beforeTarget || ""; - this.bookendLeader = attributes.bookendLeader || ""; - this.bookendTrailer = attributes.bookendTrailer || ""; - this.id = attributes.id || ""; - this.overflowLeader = attributes.overflowLeader || ""; - this.overflowTarget = attributes.overflowTarget || ""; - this.overflowTrailer = attributes.overflowTrailer || ""; - this.startNew = (0, _utils.getInteger)({ - data: attributes.startNew, - defaultValue: 0, - validate: x => x === 1 - }); - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.extras = null; - } - -} - -class BreakAfter extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "breakAfter", true); - this.id = attributes.id || ""; - this.leader = attributes.leader || ""; - this.startNew = (0, _utils.getInteger)({ - data: attributes.startNew, - defaultValue: 0, - validate: x => x === 1 - }); - this.target = attributes.target || ""; - this.targetType = (0, _utils.getStringOption)(attributes.targetType, ["auto", "contentArea", "pageArea"]); - this.trailer = attributes.trailer || ""; - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.script = null; - } - -} - -class BreakBefore extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "breakBefore", true); - this.id = attributes.id || ""; - this.leader = attributes.leader || ""; - this.startNew = (0, _utils.getInteger)({ - data: attributes.startNew, - defaultValue: 0, - validate: x => x === 1 - }); - this.target = attributes.target || ""; - this.targetType = (0, _utils.getStringOption)(attributes.targetType, ["auto", "contentArea", "pageArea"]); - this.trailer = attributes.trailer || ""; - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.script = null; - } - - [_xfa_object.$toHTML](availableSpace) { - this[_xfa_object.$extra] = {}; - return _utils.HTMLResult.FAILURE; - } - -} - -class Button extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "button", true); - this.highlight = (0, _utils.getStringOption)(attributes.highlight, ["inverted", "none", "outline", "push"]); - this.id = attributes.id || ""; - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.extras = null; - } - - [_xfa_object.$toHTML](availableSpace) { - const parent = this[_xfa_object.$getParent](); - - const grandpa = parent[_xfa_object.$getParent](); - - const htmlButton = { - name: "button", - attributes: { - id: this[_xfa_object.$uid], - class: ["xfaButton"], - style: {} - }, - children: [] - }; - - for (const event of grandpa.event.children) { - if (event.activity !== "click" || !event.script) { - continue; - } - - const jsURL = (0, _core_utils.recoverJsURL)(event.script[_xfa_object.$content]); - - if (!jsURL) { - continue; - } - - const href = (0, _html_utils.fixURL)(jsURL.url); - - if (!href) { - continue; - } - - htmlButton.children.push({ - name: "a", - attributes: { - id: "link" + this[_xfa_object.$uid], - href, - newWindow: jsURL.newWindow, - class: ["xfaLink"], - style: {} - }, - children: [] - }); - } - - return _utils.HTMLResult.success(htmlButton); - } - -} - -class Calculate extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "calculate", true); - this.id = attributes.id || ""; - this.override = (0, _utils.getStringOption)(attributes.override, ["disabled", "error", "ignore", "warning"]); - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.extras = null; - this.message = null; - this.script = null; - } - -} - -class Caption extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "caption", true); - this.id = attributes.id || ""; - this.placement = (0, _utils.getStringOption)(attributes.placement, ["left", "bottom", "inline", "right", "top"]); - this.presence = (0, _utils.getStringOption)(attributes.presence, ["visible", "hidden", "inactive", "invisible"]); - this.reserve = Math.ceil((0, _utils.getMeasurement)(attributes.reserve)); - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.extras = null; - this.font = null; - this.margin = null; - this.para = null; - this.value = null; - } - - [_xfa_object.$setValue](value) { - _setValue(this, value); - } - - [_xfa_object.$getExtra](availableSpace) { - if (!this[_xfa_object.$extra]) { - let { - width, - height - } = availableSpace; - - switch (this.placement) { - case "left": - case "right": - case "inline": - width = this.reserve <= 0 ? width : this.reserve; - break; - - case "top": - case "bottom": - height = this.reserve <= 0 ? height : this.reserve; - break; - } - - this[_xfa_object.$extra] = (0, _html_utils.layoutNode)(this, { - width, - height - }); - } - - return this[_xfa_object.$extra]; - } - - [_xfa_object.$toHTML](availableSpace) { - if (!this.value) { - return _utils.HTMLResult.EMPTY; - } - - this[_xfa_object.$pushPara](); - - const value = this.value[_xfa_object.$toHTML](availableSpace).html; - - if (!value) { - this[_xfa_object.$popPara](); - - return _utils.HTMLResult.EMPTY; - } - - const savedReserve = this.reserve; - - if (this.reserve <= 0) { - const { - w, - h - } = this[_xfa_object.$getExtra](availableSpace); - - switch (this.placement) { - case "left": - case "right": - case "inline": - this.reserve = w; - break; - - case "top": - case "bottom": - this.reserve = h; - break; - } - } - - const children = []; - - if (typeof value === "string") { - children.push({ - name: "#text", - value - }); - } else { - children.push(value); - } - - const style = (0, _html_utils.toStyle)(this, "font", "margin", "visibility"); - - switch (this.placement) { - case "left": - case "right": - if (this.reserve > 0) { - style.width = (0, _html_utils.measureToString)(this.reserve); - } - - break; - - case "top": - case "bottom": - if (this.reserve > 0) { - style.height = (0, _html_utils.measureToString)(this.reserve); - } - - break; - } - - (0, _html_utils.setPara)(this, null, value); - - this[_xfa_object.$popPara](); - - this.reserve = savedReserve; - return _utils.HTMLResult.success({ - name: "div", - attributes: { - style, - class: ["xfaCaption"] - }, - children - }); - } - -} - -class Certificate extends _xfa_object.StringObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "certificate"); - this.id = attributes.id || ""; - this.name = attributes.name || ""; - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - } - -} - -class Certificates extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "certificates", true); - this.credentialServerPolicy = (0, _utils.getStringOption)(attributes.credentialServerPolicy, ["optional", "required"]); - this.id = attributes.id || ""; - this.url = attributes.url || ""; - this.urlPolicy = attributes.urlPolicy || ""; - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.encryption = null; - this.issuers = null; - this.keyUsage = null; - this.oids = null; - this.signing = null; - this.subjectDNs = null; - } - -} - -class CheckButton extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "checkButton", true); - this.id = attributes.id || ""; - this.mark = (0, _utils.getStringOption)(attributes.mark, ["default", "check", "circle", "cross", "diamond", "square", "star"]); - this.shape = (0, _utils.getStringOption)(attributes.shape, ["square", "round"]); - this.size = (0, _utils.getMeasurement)(attributes.size, "10pt"); - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.border = null; - this.extras = null; - this.margin = null; - } - - [_xfa_object.$toHTML](availableSpace) { - const style = (0, _html_utils.toStyle)("margin"); - const size = (0, _html_utils.measureToString)(this.size); - style.width = style.height = size; - let type; - let className; - let groupId; - - const field = this[_xfa_object.$getParent]()[_xfa_object.$getParent](); - - const items = field.items.children.length && field.items.children[0][_xfa_object.$toHTML]().html || []; - const exportedValue = { - on: (items[0] !== undefined ? items[0] : "on").toString(), - off: (items[1] !== undefined ? items[1] : "off").toString() - }; - const value = field.value && field.value[_xfa_object.$text]() || "off"; - const checked = value === exportedValue.on || undefined; - - const container = field[_xfa_object.$getSubformParent](); - - const fieldId = field[_xfa_object.$uid]; - let dataId; - - if (container instanceof ExclGroup) { - groupId = container[_xfa_object.$uid]; - type = "radio"; - className = "xfaRadio"; - dataId = container[_xfa_object.$data] && container[_xfa_object.$data][_xfa_object.$uid] || container[_xfa_object.$uid]; - } else { - type = "checkbox"; - className = "xfaCheckbox"; - dataId = field[_xfa_object.$data] && field[_xfa_object.$data][_xfa_object.$uid] || field[_xfa_object.$uid]; - } - - const input = { - name: "input", - attributes: { - class: [className], - style, - fieldId, - dataId, - type, - checked, - xfaOn: exportedValue.on, - xfaOff: exportedValue.off, - "aria-label": ariaLabel(field) - } - }; - - if (groupId) { - input.attributes.name = groupId; - } - - return _utils.HTMLResult.success({ - name: "label", - attributes: { - class: ["xfaLabel"] - }, - children: [input] - }); - } - -} - -class ChoiceList extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "choiceList", true); - this.commitOn = (0, _utils.getStringOption)(attributes.commitOn, ["select", "exit"]); - this.id = attributes.id || ""; - this.open = (0, _utils.getStringOption)(attributes.open, ["userControl", "always", "multiSelect", "onEntry"]); - this.textEntry = (0, _utils.getInteger)({ - data: attributes.textEntry, - defaultValue: 0, - validate: x => x === 1 - }); - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.border = null; - this.extras = null; - this.margin = null; - } - - [_xfa_object.$toHTML](availableSpace) { - const style = (0, _html_utils.toStyle)(this, "border", "margin"); - - const ui = this[_xfa_object.$getParent](); - - const field = ui[_xfa_object.$getParent](); - - const fontSize = field.font && field.font.size || 10; - const optionStyle = { - fontSize: `calc(${fontSize}px * var(--zoom-factor))` - }; - const children = []; - - if (field.items.children.length > 0) { - const items = field.items; - let displayedIndex = 0; - let saveIndex = 0; - - if (items.children.length === 2) { - displayedIndex = items.children[0].save; - saveIndex = 1 - displayedIndex; - } - - const displayed = items.children[displayedIndex][_xfa_object.$toHTML]().html; - - const values = items.children[saveIndex][_xfa_object.$toHTML]().html; - - let selected = false; - const value = field.value && field.value[_xfa_object.$text]() || ""; - - for (let i = 0, ii = displayed.length; i < ii; i++) { - const option = { - name: "option", - attributes: { - value: values[i] || displayed[i], - style: optionStyle - }, - value: displayed[i] - }; - - if (values[i] === value) { - option.attributes.selected = selected = true; - } - - children.push(option); - } - - if (!selected) { - children.splice(0, 0, { - name: "option", - attributes: { - hidden: true, - selected: true - }, - value: " " - }); - } - } - - const selectAttributes = { - class: ["xfaSelect"], - fieldId: field[_xfa_object.$uid], - dataId: field[_xfa_object.$data] && field[_xfa_object.$data][_xfa_object.$uid] || field[_xfa_object.$uid], - style, - "aria-label": ariaLabel(field) - }; - - if (this.open === "multiSelect") { - selectAttributes.multiple = true; - } - - return _utils.HTMLResult.success({ - name: "label", - attributes: { - class: ["xfaLabel"] - }, - children: [{ - name: "select", - children, - attributes: selectAttributes - }] - }); - } - -} - -class Color extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "color", true); - this.cSpace = (0, _utils.getStringOption)(attributes.cSpace, ["SRGB"]); - this.id = attributes.id || ""; - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.value = attributes.value ? (0, _utils.getColor)(attributes.value) : ""; - this.extras = null; - } - - [_xfa_object.$hasSettableValue]() { - return false; - } - - [_xfa_object.$toStyle]() { - return this.value ? _util.Util.makeHexColor(this.value.r, this.value.g, this.value.b) : null; - } - -} - -class Comb extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "comb"); - this.id = attributes.id || ""; - this.numberOfCells = (0, _utils.getInteger)({ - data: attributes.numberOfCells, - defaultValue: 0, - validate: x => x >= 0 - }); - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - } - -} - -class Connect extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "connect", true); - this.connection = attributes.connection || ""; - this.id = attributes.id || ""; - this.ref = attributes.ref || ""; - this.usage = (0, _utils.getStringOption)(attributes.usage, ["exportAndImport", "exportOnly", "importOnly"]); - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.picture = null; - } - -} - -class ContentArea extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "contentArea", true); - this.h = (0, _utils.getMeasurement)(attributes.h); - this.id = attributes.id || ""; - this.name = attributes.name || ""; - this.relevant = (0, _utils.getRelevant)(attributes.relevant); - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.w = (0, _utils.getMeasurement)(attributes.w); - this.x = (0, _utils.getMeasurement)(attributes.x, "0pt"); - this.y = (0, _utils.getMeasurement)(attributes.y, "0pt"); - this.desc = null; - this.extras = null; - } - - [_xfa_object.$toHTML](availableSpace) { - const left = (0, _html_utils.measureToString)(this.x); - const top = (0, _html_utils.measureToString)(this.y); - const style = { - left, - top, - width: (0, _html_utils.measureToString)(this.w), - height: (0, _html_utils.measureToString)(this.h) - }; - const classNames = ["xfaContentarea"]; - - if ((0, _html_utils.isPrintOnly)(this)) { - classNames.push("xfaPrintOnly"); - } - - return _utils.HTMLResult.success({ - name: "div", - children: [], - attributes: { - style, - class: classNames, - id: this[_xfa_object.$uid] - } - }); - } - -} - -class Corner extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "corner", true); - this.id = attributes.id || ""; - this.inverted = (0, _utils.getInteger)({ - data: attributes.inverted, - defaultValue: 0, - validate: x => x === 1 - }); - this.join = (0, _utils.getStringOption)(attributes.join, ["square", "round"]); - this.presence = (0, _utils.getStringOption)(attributes.presence, ["visible", "hidden", "inactive", "invisible"]); - this.radius = (0, _utils.getMeasurement)(attributes.radius); - this.stroke = (0, _utils.getStringOption)(attributes.stroke, ["solid", "dashDot", "dashDotDot", "dashed", "dotted", "embossed", "etched", "lowered", "raised"]); - this.thickness = (0, _utils.getMeasurement)(attributes.thickness, "0.5pt"); - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.color = null; - this.extras = null; - } - - [_xfa_object.$toStyle]() { - const style = (0, _html_utils.toStyle)(this, "visibility"); - style.radius = (0, _html_utils.measureToString)(this.join === "square" ? 0 : this.radius); - return style; - } - -} - -class DateElement extends _xfa_object.ContentObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "date"); - this.id = attributes.id || ""; - this.name = attributes.name || ""; - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - } - - [_xfa_object.$finalize]() { - const date = this[_xfa_object.$content].trim(); - - this[_xfa_object.$content] = date ? new Date(date) : null; - } - - [_xfa_object.$toHTML](availableSpace) { - return valueToHtml(this[_xfa_object.$content] ? this[_xfa_object.$content].toString() : ""); - } - -} - -class DateTime extends _xfa_object.ContentObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "dateTime"); - this.id = attributes.id || ""; - this.name = attributes.name || ""; - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - } - - [_xfa_object.$finalize]() { - const date = this[_xfa_object.$content].trim(); - - this[_xfa_object.$content] = date ? new Date(date) : null; - } - - [_xfa_object.$toHTML](availableSpace) { - return valueToHtml(this[_xfa_object.$content] ? this[_xfa_object.$content].toString() : ""); - } - -} - -class DateTimeEdit extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "dateTimeEdit", true); - this.hScrollPolicy = (0, _utils.getStringOption)(attributes.hScrollPolicy, ["auto", "off", "on"]); - this.id = attributes.id || ""; - this.picker = (0, _utils.getStringOption)(attributes.picker, ["host", "none"]); - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.border = null; - this.comb = null; - this.extras = null; - this.margin = null; - } - - [_xfa_object.$toHTML](availableSpace) { - const style = (0, _html_utils.toStyle)(this, "border", "font", "margin"); - - const field = this[_xfa_object.$getParent]()[_xfa_object.$getParent](); - - const html = { - name: "input", - attributes: { - type: "text", - fieldId: field[_xfa_object.$uid], - dataId: field[_xfa_object.$data] && field[_xfa_object.$data][_xfa_object.$uid] || field[_xfa_object.$uid], - class: ["xfaTextfield"], - style, - "aria-label": ariaLabel(field) - } - }; - return _utils.HTMLResult.success({ - name: "label", - attributes: { - class: ["xfaLabel"] - }, - children: [html] - }); - } - -} - -class Decimal extends _xfa_object.ContentObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "decimal"); - this.fracDigits = (0, _utils.getInteger)({ - data: attributes.fracDigits, - defaultValue: 2, - validate: x => true - }); - this.id = attributes.id || ""; - this.leadDigits = (0, _utils.getInteger)({ - data: attributes.leadDigits, - defaultValue: -1, - validate: x => true - }); - this.name = attributes.name || ""; - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - } - - [_xfa_object.$finalize]() { - const number = parseFloat(this[_xfa_object.$content].trim()); - this[_xfa_object.$content] = isNaN(number) ? null : number; - } - - [_xfa_object.$toHTML](availableSpace) { - return valueToHtml(this[_xfa_object.$content] !== null ? this[_xfa_object.$content].toString() : ""); - } - -} - -class DefaultUi extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "defaultUi", true); - this.id = attributes.id || ""; - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.extras = null; - } - -} - -class Desc extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "desc", true); - this.id = attributes.id || ""; - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.boolean = new _xfa_object.XFAObjectArray(); - this.date = new _xfa_object.XFAObjectArray(); - this.dateTime = new _xfa_object.XFAObjectArray(); - this.decimal = new _xfa_object.XFAObjectArray(); - this.exData = new _xfa_object.XFAObjectArray(); - this.float = new _xfa_object.XFAObjectArray(); - this.image = new _xfa_object.XFAObjectArray(); - this.integer = new _xfa_object.XFAObjectArray(); - this.text = new _xfa_object.XFAObjectArray(); - this.time = new _xfa_object.XFAObjectArray(); - } - -} - -class DigestMethod extends _xfa_object.OptionObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "digestMethod", ["", "SHA1", "SHA256", "SHA512", "RIPEMD160"]); - this.id = attributes.id || ""; - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - } - -} - -class DigestMethods extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "digestMethods", true); - this.id = attributes.id || ""; - this.type = (0, _utils.getStringOption)(attributes.type, ["optional", "required"]); - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.digestMethod = new _xfa_object.XFAObjectArray(); - } - -} - -class Draw extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "draw", true); - this.anchorType = (0, _utils.getStringOption)(attributes.anchorType, ["topLeft", "bottomCenter", "bottomLeft", "bottomRight", "middleCenter", "middleLeft", "middleRight", "topCenter", "topRight"]); - this.colSpan = (0, _utils.getInteger)({ - data: attributes.colSpan, - defaultValue: 1, - validate: n => n >= 1 || n === -1 - }); - this.h = attributes.h ? (0, _utils.getMeasurement)(attributes.h) : ""; - this.hAlign = (0, _utils.getStringOption)(attributes.hAlign, ["left", "center", "justify", "justifyAll", "radix", "right"]); - this.id = attributes.id || ""; - this.locale = attributes.locale || ""; - this.maxH = (0, _utils.getMeasurement)(attributes.maxH, "0pt"); - this.maxW = (0, _utils.getMeasurement)(attributes.maxW, "0pt"); - this.minH = (0, _utils.getMeasurement)(attributes.minH, "0pt"); - this.minW = (0, _utils.getMeasurement)(attributes.minW, "0pt"); - this.name = attributes.name || ""; - this.presence = (0, _utils.getStringOption)(attributes.presence, ["visible", "hidden", "inactive", "invisible"]); - this.relevant = (0, _utils.getRelevant)(attributes.relevant); - this.rotate = (0, _utils.getInteger)({ - data: attributes.rotate, - defaultValue: 0, - validate: x => x % 90 === 0 - }); - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.w = attributes.w ? (0, _utils.getMeasurement)(attributes.w) : ""; - this.x = (0, _utils.getMeasurement)(attributes.x, "0pt"); - this.y = (0, _utils.getMeasurement)(attributes.y, "0pt"); - this.assist = null; - this.border = null; - this.caption = null; - this.desc = null; - this.extras = null; - this.font = null; - this.keep = null; - this.margin = null; - this.para = null; - this.traversal = null; - this.ui = null; - this.value = null; - this.setProperty = new _xfa_object.XFAObjectArray(); - } - - [_xfa_object.$setValue](value) { - _setValue(this, value); - } - - [_xfa_object.$toHTML](availableSpace) { - setTabIndex(this); - - if (this.presence === "hidden" || this.presence === "inactive") { - return _utils.HTMLResult.EMPTY; - } - - (0, _html_utils.fixDimensions)(this); - - this[_xfa_object.$pushPara](); - - const savedW = this.w; - const savedH = this.h; - const { - w, - h, - isBroken - } = (0, _html_utils.layoutNode)(this, availableSpace); - - if (w && this.w === "") { - if (isBroken && this[_xfa_object.$getSubformParent]()[_xfa_object.$isThereMoreWidth]()) { - this[_xfa_object.$popPara](); - - return _utils.HTMLResult.FAILURE; - } - - this.w = w; - } - - if (h && this.h === "") { - this.h = h; - } - - setFirstUnsplittable(this); - - if (!(0, _layout.checkDimensions)(this, availableSpace)) { - this.w = savedW; - this.h = savedH; - - this[_xfa_object.$popPara](); - - return _utils.HTMLResult.FAILURE; - } - - unsetFirstUnsplittable(this); - const style = (0, _html_utils.toStyle)(this, "font", "hAlign", "dimensions", "position", "presence", "rotate", "anchorType", "border", "margin"); - (0, _html_utils.setMinMaxDimensions)(this, style); - - if (style.margin) { - style.padding = style.margin; - delete style.margin; - } - - const classNames = ["xfaDraw"]; - - if (this.font) { - classNames.push("xfaFont"); - } - - if ((0, _html_utils.isPrintOnly)(this)) { - classNames.push("xfaPrintOnly"); - } - - const attributes = { - style, - id: this[_xfa_object.$uid], - class: classNames - }; - - if (this.name) { - attributes.xfaName = this.name; - } - - const html = { - name: "div", - attributes, - children: [] - }; - applyAssist(this, attributes); - const bbox = (0, _html_utils.computeBbox)(this, html, availableSpace); - const value = this.value ? this.value[_xfa_object.$toHTML](availableSpace).html : null; - - if (value === null) { - this.w = savedW; - this.h = savedH; - - this[_xfa_object.$popPara](); - - return _utils.HTMLResult.success((0, _html_utils.createWrapper)(this, html), bbox); - } - - html.children.push(value); - (0, _html_utils.setPara)(this, style, value); - this.w = savedW; - this.h = savedH; - - this[_xfa_object.$popPara](); - - return _utils.HTMLResult.success((0, _html_utils.createWrapper)(this, html), bbox); - } - -} - -class Edge extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "edge", true); - this.cap = (0, _utils.getStringOption)(attributes.cap, ["square", "butt", "round"]); - this.id = attributes.id || ""; - this.presence = (0, _utils.getStringOption)(attributes.presence, ["visible", "hidden", "inactive", "invisible"]); - this.stroke = (0, _utils.getStringOption)(attributes.stroke, ["solid", "dashDot", "dashDotDot", "dashed", "dotted", "embossed", "etched", "lowered", "raised"]); - this.thickness = (0, _utils.getMeasurement)(attributes.thickness, "0.5pt"); - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.color = null; - this.extras = null; - } - - [_xfa_object.$toStyle]() { - const style = (0, _html_utils.toStyle)(this, "visibility"); - Object.assign(style, { - linecap: this.cap, - width: (0, _html_utils.measureToString)(this.thickness), - color: this.color ? this.color[_xfa_object.$toStyle]() : "#000000", - style: "" - }); - - if (this.presence !== "visible") { - style.style = "none"; - } else { - switch (this.stroke) { - case "solid": - style.style = "solid"; - break; - - case "dashDot": - style.style = "dashed"; - break; - - case "dashDotDot": - style.style = "dashed"; - break; - - case "dashed": - style.style = "dashed"; - break; - - case "dotted": - style.style = "dotted"; - break; - - case "embossed": - style.style = "ridge"; - break; - - case "etched": - style.style = "groove"; - break; - - case "lowered": - style.style = "inset"; - break; - - case "raised": - style.style = "outset"; - break; - } - } - - return style; - } - -} - -class Encoding extends _xfa_object.OptionObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "encoding", ["adbe.x509.rsa_sha1", "adbe.pkcs7.detached", "adbe.pkcs7.sha1"]); - this.id = attributes.id || ""; - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - } - -} - -class Encodings extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "encodings", true); - this.id = attributes.id || ""; - this.type = (0, _utils.getStringOption)(attributes.type, ["optional", "required"]); - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.encoding = new _xfa_object.XFAObjectArray(); - } - -} - -class Encrypt extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "encrypt", true); - this.id = attributes.id || ""; - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.certificate = null; - } - -} - -class EncryptData extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "encryptData", true); - this.id = attributes.id || ""; - this.operation = (0, _utils.getStringOption)(attributes.operation, ["encrypt", "decrypt"]); - this.target = attributes.target || ""; - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.filter = null; - this.manifest = null; - } - -} - -class Encryption extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "encryption", true); - this.id = attributes.id || ""; - this.type = (0, _utils.getStringOption)(attributes.type, ["optional", "required"]); - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.certificate = new _xfa_object.XFAObjectArray(); - } - -} - -class EncryptionMethod extends _xfa_object.OptionObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "encryptionMethod", ["", "AES256-CBC", "TRIPLEDES-CBC", "AES128-CBC", "AES192-CBC"]); - this.id = attributes.id || ""; - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - } - -} - -class EncryptionMethods extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "encryptionMethods", true); - this.id = attributes.id || ""; - this.type = (0, _utils.getStringOption)(attributes.type, ["optional", "required"]); - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.encryptionMethod = new _xfa_object.XFAObjectArray(); - } - -} - -class Event extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "event", true); - this.activity = (0, _utils.getStringOption)(attributes.activity, ["click", "change", "docClose", "docReady", "enter", "exit", "full", "indexChange", "initialize", "mouseDown", "mouseEnter", "mouseExit", "mouseUp", "postExecute", "postOpen", "postPrint", "postSave", "postSign", "postSubmit", "preExecute", "preOpen", "prePrint", "preSave", "preSign", "preSubmit", "ready", "validationState"]); - this.id = attributes.id || ""; - this.listen = (0, _utils.getStringOption)(attributes.listen, ["refOnly", "refAndDescendents"]); - this.name = attributes.name || ""; - this.ref = attributes.ref || ""; - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.extras = null; - this.encryptData = null; - this.execute = null; - this.script = null; - this.signData = null; - this.submit = null; - } - -} - -class ExData extends _xfa_object.ContentObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "exData"); - this.contentType = attributes.contentType || ""; - this.href = attributes.href || ""; - this.id = attributes.id || ""; - this.maxLength = (0, _utils.getInteger)({ - data: attributes.maxLength, - defaultValue: -1, - validate: x => x >= -1 - }); - this.name = attributes.name || ""; - this.rid = attributes.rid || ""; - this.transferEncoding = (0, _utils.getStringOption)(attributes.transferEncoding, ["none", "base64", "package"]); - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - } - - [_xfa_object.$isCDATAXml]() { - return this.contentType === "text/html"; - } - - [_xfa_object.$onChild](child) { - if (this.contentType === "text/html" && child[_xfa_object.$namespaceId] === _namespaces.NamespaceIds.xhtml.id) { - this[_xfa_object.$content] = child; - return true; - } - - if (this.contentType === "text/xml") { - this[_xfa_object.$content] = child; - return true; - } - - return false; - } - - [_xfa_object.$toHTML](availableSpace) { - if (this.contentType !== "text/html" || !this[_xfa_object.$content]) { - return _utils.HTMLResult.EMPTY; - } - - return this[_xfa_object.$content][_xfa_object.$toHTML](availableSpace); - } - -} - -class ExObject extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "exObject", true); - this.archive = attributes.archive || ""; - this.classId = attributes.classId || ""; - this.codeBase = attributes.codeBase || ""; - this.codeType = attributes.codeType || ""; - this.id = attributes.id || ""; - this.name = attributes.name || ""; - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.extras = null; - this.boolean = new _xfa_object.XFAObjectArray(); - this.date = new _xfa_object.XFAObjectArray(); - this.dateTime = new _xfa_object.XFAObjectArray(); - this.decimal = new _xfa_object.XFAObjectArray(); - this.exData = new _xfa_object.XFAObjectArray(); - this.exObject = new _xfa_object.XFAObjectArray(); - this.float = new _xfa_object.XFAObjectArray(); - this.image = new _xfa_object.XFAObjectArray(); - this.integer = new _xfa_object.XFAObjectArray(); - this.text = new _xfa_object.XFAObjectArray(); - this.time = new _xfa_object.XFAObjectArray(); - } - -} - -class ExclGroup extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "exclGroup", true); - this.access = (0, _utils.getStringOption)(attributes.access, ["open", "nonInteractive", "protected", "readOnly"]); - this.accessKey = attributes.accessKey || ""; - this.anchorType = (0, _utils.getStringOption)(attributes.anchorType, ["topLeft", "bottomCenter", "bottomLeft", "bottomRight", "middleCenter", "middleLeft", "middleRight", "topCenter", "topRight"]); - this.colSpan = (0, _utils.getInteger)({ - data: attributes.colSpan, - defaultValue: 1, - validate: n => n >= 1 || n === -1 - }); - this.h = attributes.h ? (0, _utils.getMeasurement)(attributes.h) : ""; - this.hAlign = (0, _utils.getStringOption)(attributes.hAlign, ["left", "center", "justify", "justifyAll", "radix", "right"]); - this.id = attributes.id || ""; - this.layout = (0, _utils.getStringOption)(attributes.layout, ["position", "lr-tb", "rl-row", "rl-tb", "row", "table", "tb"]); - this.maxH = (0, _utils.getMeasurement)(attributes.maxH, "0pt"); - this.maxW = (0, _utils.getMeasurement)(attributes.maxW, "0pt"); - this.minH = (0, _utils.getMeasurement)(attributes.minH, "0pt"); - this.minW = (0, _utils.getMeasurement)(attributes.minW, "0pt"); - this.name = attributes.name || ""; - this.presence = (0, _utils.getStringOption)(attributes.presence, ["visible", "hidden", "inactive", "invisible"]); - this.relevant = (0, _utils.getRelevant)(attributes.relevant); - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.w = attributes.w ? (0, _utils.getMeasurement)(attributes.w) : ""; - this.x = (0, _utils.getMeasurement)(attributes.x, "0pt"); - this.y = (0, _utils.getMeasurement)(attributes.y, "0pt"); - this.assist = null; - this.bind = null; - this.border = null; - this.calculate = null; - this.caption = null; - this.desc = null; - this.extras = null; - this.margin = null; - this.para = null; - this.traversal = null; - this.validate = null; - this.connect = new _xfa_object.XFAObjectArray(); - this.event = new _xfa_object.XFAObjectArray(); - this.field = new _xfa_object.XFAObjectArray(); - this.setProperty = new _xfa_object.XFAObjectArray(); - } - - [_xfa_object.$isBindable]() { - return true; - } - - [_xfa_object.$hasSettableValue]() { - return true; - } - - [_xfa_object.$setValue](value) { - for (const field of this.field.children) { - if (!field.value) { - const nodeValue = new Value({}); - - field[_xfa_object.$appendChild](nodeValue); - - field.value = nodeValue; - } - - field.value[_xfa_object.$setValue](value); - } - } - - [_xfa_object.$isThereMoreWidth]() { - return this.layout.endsWith("-tb") && this[_xfa_object.$extra].attempt === 0 && this[_xfa_object.$extra].numberInLine > 0 || this[_xfa_object.$getParent]()[_xfa_object.$isThereMoreWidth](); - } - - [_xfa_object.$isSplittable]() { - const parent = this[_xfa_object.$getSubformParent](); - - if (!parent[_xfa_object.$isSplittable]()) { - return false; - } - - if (this[_xfa_object.$extra]._isSplittable !== undefined) { - return this[_xfa_object.$extra]._isSplittable; - } - - if (this.layout === "position" || this.layout.includes("row")) { - this[_xfa_object.$extra]._isSplittable = false; - return false; - } - - if (parent.layout && parent.layout.endsWith("-tb") && parent[_xfa_object.$extra].numberInLine !== 0) { - return false; - } - - this[_xfa_object.$extra]._isSplittable = true; - return true; - } - - [_xfa_object.$flushHTML]() { - return (0, _layout.flushHTML)(this); - } - - [_xfa_object.$addHTML](html, bbox) { - (0, _layout.addHTML)(this, html, bbox); - } - - [_xfa_object.$getAvailableSpace]() { - return (0, _layout.getAvailableSpace)(this); - } - - [_xfa_object.$toHTML](availableSpace) { - setTabIndex(this); - - if (this.presence === "hidden" || this.presence === "inactive" || this.h === 0 || this.w === 0) { - return _utils.HTMLResult.EMPTY; - } - - (0, _html_utils.fixDimensions)(this); - const children = []; - const attributes = { - id: this[_xfa_object.$uid], - class: [] - }; - (0, _html_utils.setAccess)(this, attributes.class); - - if (!this[_xfa_object.$extra]) { - this[_xfa_object.$extra] = Object.create(null); - } - - Object.assign(this[_xfa_object.$extra], { - children, - attributes, - attempt: 0, - line: null, - numberInLine: 0, - availableSpace: { - width: Math.min(this.w || Infinity, availableSpace.width), - height: Math.min(this.h || Infinity, availableSpace.height) - }, - width: 0, - height: 0, - prevHeight: 0, - currentWidth: 0 - }); - - const isSplittable = this[_xfa_object.$isSplittable](); - - if (!isSplittable) { - setFirstUnsplittable(this); - } - - if (!(0, _layout.checkDimensions)(this, availableSpace)) { - return _utils.HTMLResult.FAILURE; - } - - const filter = new Set(["field"]); - - if (this.layout.includes("row")) { - const columnWidths = this[_xfa_object.$getSubformParent]().columnWidths; - - if (Array.isArray(columnWidths) && columnWidths.length > 0) { - this[_xfa_object.$extra].columnWidths = columnWidths; - this[_xfa_object.$extra].currentColumn = 0; - } - } - - const style = (0, _html_utils.toStyle)(this, "anchorType", "dimensions", "position", "presence", "border", "margin", "hAlign"); - const classNames = ["xfaExclgroup"]; - const cl = (0, _html_utils.layoutClass)(this); - - if (cl) { - classNames.push(cl); - } - - if ((0, _html_utils.isPrintOnly)(this)) { - classNames.push("xfaPrintOnly"); - } - - attributes.style = style; - attributes.class = classNames; - - if (this.name) { - attributes.xfaName = this.name; - } - - this[_xfa_object.$pushPara](); - - const isLrTb = this.layout === "lr-tb" || this.layout === "rl-tb"; - const maxRun = isLrTb ? MAX_ATTEMPTS_FOR_LRTB_LAYOUT : 1; - - for (; this[_xfa_object.$extra].attempt < maxRun; this[_xfa_object.$extra].attempt++) { - if (isLrTb && this[_xfa_object.$extra].attempt === MAX_ATTEMPTS_FOR_LRTB_LAYOUT - 1) { - this[_xfa_object.$extra].numberInLine = 0; - } - - const result = this[_xfa_object.$childrenToHTML]({ - filter, - include: true - }); - - if (result.success) { - break; - } - - if (result.isBreak()) { - this[_xfa_object.$popPara](); - - return result; - } - - if (isLrTb && this[_xfa_object.$extra].attempt === 0 && this[_xfa_object.$extra].numberInLine === 0 && !this[_xfa_object.$getTemplateRoot]()[_xfa_object.$extra].noLayoutFailure) { - this[_xfa_object.$extra].attempt = maxRun; - break; - } - } - - this[_xfa_object.$popPara](); - - if (!isSplittable) { - unsetFirstUnsplittable(this); - } - - if (this[_xfa_object.$extra].attempt === maxRun) { - if (!isSplittable) { - delete this[_xfa_object.$extra]; - } - - return _utils.HTMLResult.FAILURE; - } - - let marginH = 0; - let marginV = 0; - - if (this.margin) { - marginH = this.margin.leftInset + this.margin.rightInset; - marginV = this.margin.topInset + this.margin.bottomInset; - } - - const width = Math.max(this[_xfa_object.$extra].width + marginH, this.w || 0); - const height = Math.max(this[_xfa_object.$extra].height + marginV, this.h || 0); - const bbox = [this.x, this.y, width, height]; - - if (this.w === "") { - style.width = (0, _html_utils.measureToString)(width); - } - - if (this.h === "") { - style.height = (0, _html_utils.measureToString)(height); - } - - const html = { - name: "div", - attributes, - children - }; - applyAssist(this, attributes); - delete this[_xfa_object.$extra]; - return _utils.HTMLResult.success((0, _html_utils.createWrapper)(this, html), bbox); - } - -} - -class Execute extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "execute"); - this.connection = attributes.connection || ""; - this.executeType = (0, _utils.getStringOption)(attributes.executeType, ["import", "remerge"]); - this.id = attributes.id || ""; - this.runAt = (0, _utils.getStringOption)(attributes.runAt, ["client", "both", "server"]); - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - } - -} - -class Extras extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "extras", true); - this.id = attributes.id || ""; - this.name = attributes.name || ""; - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.boolean = new _xfa_object.XFAObjectArray(); - this.date = new _xfa_object.XFAObjectArray(); - this.dateTime = new _xfa_object.XFAObjectArray(); - this.decimal = new _xfa_object.XFAObjectArray(); - this.exData = new _xfa_object.XFAObjectArray(); - this.extras = new _xfa_object.XFAObjectArray(); - this.float = new _xfa_object.XFAObjectArray(); - this.image = new _xfa_object.XFAObjectArray(); - this.integer = new _xfa_object.XFAObjectArray(); - this.text = new _xfa_object.XFAObjectArray(); - this.time = new _xfa_object.XFAObjectArray(); - } - -} - -class Field extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "field", true); - this.access = (0, _utils.getStringOption)(attributes.access, ["open", "nonInteractive", "protected", "readOnly"]); - this.accessKey = attributes.accessKey || ""; - this.anchorType = (0, _utils.getStringOption)(attributes.anchorType, ["topLeft", "bottomCenter", "bottomLeft", "bottomRight", "middleCenter", "middleLeft", "middleRight", "topCenter", "topRight"]); - this.colSpan = (0, _utils.getInteger)({ - data: attributes.colSpan, - defaultValue: 1, - validate: n => n >= 1 || n === -1 - }); - this.h = attributes.h ? (0, _utils.getMeasurement)(attributes.h) : ""; - this.hAlign = (0, _utils.getStringOption)(attributes.hAlign, ["left", "center", "justify", "justifyAll", "radix", "right"]); - this.id = attributes.id || ""; - this.locale = attributes.locale || ""; - this.maxH = (0, _utils.getMeasurement)(attributes.maxH, "0pt"); - this.maxW = (0, _utils.getMeasurement)(attributes.maxW, "0pt"); - this.minH = (0, _utils.getMeasurement)(attributes.minH, "0pt"); - this.minW = (0, _utils.getMeasurement)(attributes.minW, "0pt"); - this.name = attributes.name || ""; - this.presence = (0, _utils.getStringOption)(attributes.presence, ["visible", "hidden", "inactive", "invisible"]); - this.relevant = (0, _utils.getRelevant)(attributes.relevant); - this.rotate = (0, _utils.getInteger)({ - data: attributes.rotate, - defaultValue: 0, - validate: x => x % 90 === 0 - }); - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.w = attributes.w ? (0, _utils.getMeasurement)(attributes.w) : ""; - this.x = (0, _utils.getMeasurement)(attributes.x, "0pt"); - this.y = (0, _utils.getMeasurement)(attributes.y, "0pt"); - this.assist = null; - this.bind = null; - this.border = null; - this.calculate = null; - this.caption = null; - this.desc = null; - this.extras = null; - this.font = null; - this.format = null; - this.items = new _xfa_object.XFAObjectArray(2); - this.keep = null; - this.margin = null; - this.para = null; - this.traversal = null; - this.ui = null; - this.validate = null; - this.value = null; - this.bindItems = new _xfa_object.XFAObjectArray(); - this.connect = new _xfa_object.XFAObjectArray(); - this.event = new _xfa_object.XFAObjectArray(); - this.setProperty = new _xfa_object.XFAObjectArray(); - } - - [_xfa_object.$isBindable]() { - return true; - } - - [_xfa_object.$setValue](value) { - _setValue(this, value); - } - - [_xfa_object.$toHTML](availableSpace) { - setTabIndex(this); - - if (!this.ui) { - this.ui = new Ui({}); - this.ui[_xfa_object.$globalData] = this[_xfa_object.$globalData]; - - this[_xfa_object.$appendChild](this.ui); - - let node; - - switch (this.items.children.length) { - case 0: - node = new TextEdit({}); - this.ui.textEdit = node; - break; - - case 1: - node = new CheckButton({}); - this.ui.checkButton = node; - break; - - case 2: - node = new ChoiceList({}); - this.ui.choiceList = node; - break; - } - - this.ui[_xfa_object.$appendChild](node); - } - - if (!this.ui || this.presence === "hidden" || this.presence === "inactive" || this.h === 0 || this.w === 0) { - return _utils.HTMLResult.EMPTY; - } - - if (this.caption) { - delete this.caption[_xfa_object.$extra]; - } - - this[_xfa_object.$pushPara](); - - const caption = this.caption ? this.caption[_xfa_object.$toHTML](availableSpace).html : null; - const savedW = this.w; - const savedH = this.h; - let marginH = 0; - let marginV = 0; - - if (this.margin) { - marginH = this.margin.leftInset + this.margin.rightInset; - marginV = this.margin.topInset + this.margin.bottomInset; - } - - let borderDims = null; - - if (this.w === "" || this.h === "") { - let width = null; - let height = null; - let uiW = 0; - let uiH = 0; - - if (this.ui.checkButton) { - uiW = uiH = this.ui.checkButton.size; - } else { - const { - w, - h - } = (0, _html_utils.layoutNode)(this, availableSpace); - - if (w !== null) { - uiW = w; - uiH = h; - } else { - uiH = (0, _fonts.getMetrics)(this.font, true).lineNoGap; - } - } - - borderDims = getBorderDims(this.ui[_xfa_object.$getExtra]()); - uiW += borderDims.w; - uiH += borderDims.h; - - if (this.caption) { - const { - w, - h, - isBroken - } = this.caption[_xfa_object.$getExtra](availableSpace); - - if (isBroken && this[_xfa_object.$getSubformParent]()[_xfa_object.$isThereMoreWidth]()) { - this[_xfa_object.$popPara](); - - return _utils.HTMLResult.FAILURE; - } - - width = w; - height = h; - - switch (this.caption.placement) { - case "left": - case "right": - case "inline": - width += uiW; - break; - - case "top": - case "bottom": - height += uiH; - break; - } - } else { - width = uiW; - height = uiH; - } - - if (width && this.w === "") { - width += marginH; - this.w = Math.min(this.maxW <= 0 ? Infinity : this.maxW, this.minW + 1 < width ? width : this.minW); - } - - if (height && this.h === "") { - height += marginV; - this.h = Math.min(this.maxH <= 0 ? Infinity : this.maxH, this.minH + 1 < height ? height : this.minH); - } - } - - this[_xfa_object.$popPara](); - - (0, _html_utils.fixDimensions)(this); - setFirstUnsplittable(this); - - if (!(0, _layout.checkDimensions)(this, availableSpace)) { - this.w = savedW; - this.h = savedH; - - this[_xfa_object.$popPara](); - - return _utils.HTMLResult.FAILURE; - } - - unsetFirstUnsplittable(this); - const style = (0, _html_utils.toStyle)(this, "font", "dimensions", "position", "rotate", "anchorType", "presence", "margin", "hAlign"); - (0, _html_utils.setMinMaxDimensions)(this, style); - const classNames = ["xfaField"]; - - if (this.font) { - classNames.push("xfaFont"); - } - - if ((0, _html_utils.isPrintOnly)(this)) { - classNames.push("xfaPrintOnly"); - } - - const attributes = { - style, - id: this[_xfa_object.$uid], - class: classNames - }; - - if (style.margin) { - style.padding = style.margin; - delete style.margin; - } - - (0, _html_utils.setAccess)(this, classNames); - - if (this.name) { - attributes.xfaName = this.name; - } - - const children = []; - const html = { - name: "div", - attributes, - children - }; - applyAssist(this, attributes); - const borderStyle = this.border ? this.border[_xfa_object.$toStyle]() : null; - const bbox = (0, _html_utils.computeBbox)(this, html, availableSpace); - - const ui = this.ui[_xfa_object.$toHTML]().html; - - if (!ui) { - Object.assign(style, borderStyle); - return _utils.HTMLResult.success((0, _html_utils.createWrapper)(this, html), bbox); - } - - if (this[_xfa_object.$tabIndex]) { - if (ui.children && ui.children[0]) { - ui.children[0].attributes.tabindex = this[_xfa_object.$tabIndex]; - } else { - ui.attributes.tabindex = this[_xfa_object.$tabIndex]; - } - } - - if (!ui.attributes.style) { - ui.attributes.style = Object.create(null); - } - - let aElement = null; - - if (this.ui.button) { - if (ui.children.length === 1) { - [aElement] = ui.children.splice(0, 1); - } - - Object.assign(ui.attributes.style, borderStyle); - } else { - Object.assign(style, borderStyle); - } - - children.push(ui); - - if (this.value) { - if (this.ui.imageEdit) { - ui.children.push(this.value[_xfa_object.$toHTML]().html); - } else if (!this.ui.button) { - let value = ""; - - if (this.value.exData) { - value = this.value.exData[_xfa_object.$text](); - } else if (this.value.text) { - value = this.value.text[_xfa_object.$getExtra](); - } else { - const htmlValue = this.value[_xfa_object.$toHTML]().html; - - if (htmlValue !== null) { - value = htmlValue.children[0].value; - } - } - - if (this.ui.textEdit && this.value.text && this.value.text.maxChars) { - ui.children[0].attributes.maxLength = this.value.text.maxChars; - } - - if (value) { - if (this.ui.numericEdit) { - value = parseFloat(value); - value = isNaN(value) ? "" : value.toString(); - } - - if (ui.children[0].name === "textarea") { - ui.children[0].attributes.textContent = value; - } else { - ui.children[0].attributes.value = value; - } - } - } - } - - if (!this.ui.imageEdit && ui.children && ui.children[0] && this.h) { - borderDims = borderDims || getBorderDims(this.ui[_xfa_object.$getExtra]()); - let captionHeight = 0; - - if (this.caption && ["top", "bottom"].includes(this.caption.placement)) { - captionHeight = this.caption.reserve; - - if (captionHeight <= 0) { - captionHeight = this.caption[_xfa_object.$getExtra](availableSpace).h; - } - - const inputHeight = this.h - captionHeight - marginV - borderDims.h; - ui.children[0].attributes.style.height = (0, _html_utils.measureToString)(inputHeight); - } else { - ui.children[0].attributes.style.height = "100%"; - } - } - - if (aElement) { - ui.children.push(aElement); - } - - if (!caption) { - if (ui.attributes.class) { - ui.attributes.class.push("xfaLeft"); - } - - this.w = savedW; - this.h = savedH; - return _utils.HTMLResult.success((0, _html_utils.createWrapper)(this, html), bbox); - } - - if (this.ui.button) { - if (style.padding) { - delete style.padding; - } - - if (caption.name === "div") { - caption.name = "span"; - } - - ui.children.push(caption); - return _utils.HTMLResult.success(html, bbox); - } else if (this.ui.checkButton) { - caption.attributes.class[0] = "xfaCaptionForCheckButton"; - } - - if (!ui.attributes.class) { - ui.attributes.class = []; - } - - ui.children.splice(0, 0, caption); - - switch (this.caption.placement) { - case "left": - ui.attributes.class.push("xfaLeft"); - break; - - case "right": - ui.attributes.class.push("xfaRight"); - break; - - case "top": - ui.attributes.class.push("xfaTop"); - break; - - case "bottom": - ui.attributes.class.push("xfaBottom"); - break; - - case "inline": - ui.attributes.class.push("xfaLeft"); - break; - } - - this.w = savedW; - this.h = savedH; - return _utils.HTMLResult.success((0, _html_utils.createWrapper)(this, html), bbox); - } - -} - -exports.Field = Field; - -class Fill extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "fill", true); - this.id = attributes.id || ""; - this.presence = (0, _utils.getStringOption)(attributes.presence, ["visible", "hidden", "inactive", "invisible"]); - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.color = null; - this.extras = null; - this.linear = null; - this.pattern = null; - this.radial = null; - this.solid = null; - this.stipple = null; - } - - [_xfa_object.$toStyle]() { - const parent = this[_xfa_object.$getParent](); - - const grandpa = parent[_xfa_object.$getParent](); - - const ggrandpa = grandpa[_xfa_object.$getParent](); - - const style = Object.create(null); - let propName = "color"; - let altPropName = propName; - - if (parent instanceof Border) { - propName = "background-color"; - altPropName = "background"; - - if (ggrandpa instanceof Ui) { - style.backgroundColor = "white"; - } - } - - if (parent instanceof Rectangle || parent instanceof Arc) { - propName = altPropName = "fill"; - style.fill = "white"; - } - - for (const name of Object.getOwnPropertyNames(this)) { - if (name === "extras" || name === "color") { - continue; - } - - const obj = this[name]; - - if (!(obj instanceof _xfa_object.XFAObject)) { - continue; - } - - const color = obj[_xfa_object.$toStyle](this.color); - - if (color) { - style[color.startsWith("#") ? propName : altPropName] = color; - } - - return style; - } - - if (this.color && this.color.value) { - const color = this.color[_xfa_object.$toStyle](); - - style[color.startsWith("#") ? propName : altPropName] = color; - } - - return style; - } - -} - -class Filter extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "filter", true); - this.addRevocationInfo = (0, _utils.getStringOption)(attributes.addRevocationInfo, ["", "required", "optional", "none"]); - this.id = attributes.id || ""; - this.name = attributes.name || ""; - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.version = (0, _utils.getInteger)({ - data: this.version, - defaultValue: 5, - validate: x => x >= 1 && x <= 5 - }); - this.appearanceFilter = null; - this.certificates = null; - this.digestMethods = null; - this.encodings = null; - this.encryptionMethods = null; - this.handler = null; - this.lockDocument = null; - this.mdp = null; - this.reasons = null; - this.timeStamp = null; - } - -} - -class Float extends _xfa_object.ContentObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "float"); - this.id = attributes.id || ""; - this.name = attributes.name || ""; - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - } - - [_xfa_object.$finalize]() { - const number = parseFloat(this[_xfa_object.$content].trim()); - this[_xfa_object.$content] = isNaN(number) ? null : number; - } - - [_xfa_object.$toHTML](availableSpace) { - return valueToHtml(this[_xfa_object.$content] !== null ? this[_xfa_object.$content].toString() : ""); - } - -} - -class Font extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "font", true); - this.baselineShift = (0, _utils.getMeasurement)(attributes.baselineShift); - this.fontHorizontalScale = (0, _utils.getFloat)({ - data: attributes.fontHorizontalScale, - defaultValue: 100, - validate: x => x >= 0 - }); - this.fontVerticalScale = (0, _utils.getFloat)({ - data: attributes.fontVerticalScale, - defaultValue: 100, - validate: x => x >= 0 - }); - this.id = attributes.id || ""; - this.kerningMode = (0, _utils.getStringOption)(attributes.kerningMode, ["none", "pair"]); - this.letterSpacing = (0, _utils.getMeasurement)(attributes.letterSpacing, "0"); - this.lineThrough = (0, _utils.getInteger)({ - data: attributes.lineThrough, - defaultValue: 0, - validate: x => x === 1 || x === 2 - }); - this.lineThroughPeriod = (0, _utils.getStringOption)(attributes.lineThroughPeriod, ["all", "word"]); - this.overline = (0, _utils.getInteger)({ - data: attributes.overline, - defaultValue: 0, - validate: x => x === 1 || x === 2 - }); - this.overlinePeriod = (0, _utils.getStringOption)(attributes.overlinePeriod, ["all", "word"]); - this.posture = (0, _utils.getStringOption)(attributes.posture, ["normal", "italic"]); - this.size = (0, _utils.getMeasurement)(attributes.size, "10pt"); - this.typeface = attributes.typeface || "Courier"; - this.underline = (0, _utils.getInteger)({ - data: attributes.underline, - defaultValue: 0, - validate: x => x === 1 || x === 2 - }); - this.underlinePeriod = (0, _utils.getStringOption)(attributes.underlinePeriod, ["all", "word"]); - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.weight = (0, _utils.getStringOption)(attributes.weight, ["normal", "bold"]); - this.extras = null; - this.fill = null; - } - - [_xfa_object.$clean](builder) { - super[_xfa_object.$clean](builder); - - this[_xfa_object.$globalData].usedTypefaces.add(this.typeface); - } - - [_xfa_object.$toStyle]() { - const style = (0, _html_utils.toStyle)(this, "fill"); - const color = style.color; - - if (color) { - if (color === "#000000") { - delete style.color; - } else if (!color.startsWith("#")) { - style.background = color; - style.backgroundClip = "text"; - style.color = "transparent"; - } - } - - if (this.baselineShift) { - style.verticalAlign = (0, _html_utils.measureToString)(this.baselineShift); - } - - style.fontKerning = this.kerningMode === "none" ? "none" : "normal"; - style.letterSpacing = (0, _html_utils.measureToString)(this.letterSpacing); - - if (this.lineThrough !== 0) { - style.textDecoration = "line-through"; - - if (this.lineThrough === 2) { - style.textDecorationStyle = "double"; - } - } - - if (this.overline !== 0) { - style.textDecoration = "overline"; - - if (this.overline === 2) { - style.textDecorationStyle = "double"; - } - } - - style.fontStyle = this.posture; - style.fontSize = (0, _html_utils.measureToString)(0.99 * this.size); - (0, _html_utils.setFontFamily)(this, this, this[_xfa_object.$globalData].fontFinder, style); - - if (this.underline !== 0) { - style.textDecoration = "underline"; - - if (this.underline === 2) { - style.textDecorationStyle = "double"; - } - } - - style.fontWeight = this.weight; - return style; - } - -} - -class Format extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "format", true); - this.id = attributes.id || ""; - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.extras = null; - this.picture = null; - } - -} - -class Handler extends _xfa_object.StringObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "handler"); - this.id = attributes.id || ""; - this.type = (0, _utils.getStringOption)(attributes.type, ["optional", "required"]); - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - } - -} - -class Hyphenation extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "hyphenation"); - this.excludeAllCaps = (0, _utils.getInteger)({ - data: attributes.excludeAllCaps, - defaultValue: 0, - validate: x => x === 1 - }); - this.excludeInitialCap = (0, _utils.getInteger)({ - data: attributes.excludeInitialCap, - defaultValue: 0, - validate: x => x === 1 - }); - this.hyphenate = (0, _utils.getInteger)({ - data: attributes.hyphenate, - defaultValue: 0, - validate: x => x === 1 - }); - this.id = attributes.id || ""; - this.pushCharacterCount = (0, _utils.getInteger)({ - data: attributes.pushCharacterCount, - defaultValue: 3, - validate: x => x >= 0 - }); - this.remainCharacterCount = (0, _utils.getInteger)({ - data: attributes.remainCharacterCount, - defaultValue: 3, - validate: x => x >= 0 - }); - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.wordCharacterCount = (0, _utils.getInteger)({ - data: attributes.wordCharacterCount, - defaultValue: 7, - validate: x => x >= 0 - }); - } - -} - -class Image extends _xfa_object.StringObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "image"); - this.aspect = (0, _utils.getStringOption)(attributes.aspect, ["fit", "actual", "height", "none", "width"]); - this.contentType = attributes.contentType || ""; - this.href = attributes.href || ""; - this.id = attributes.id || ""; - this.name = attributes.name || ""; - this.transferEncoding = (0, _utils.getStringOption)(attributes.transferEncoding, ["base64", "none", "package"]); - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - } - - [_xfa_object.$toHTML]() { - if (this.contentType && !MIMES.has(this.contentType.toLowerCase())) { - return _utils.HTMLResult.EMPTY; - } - - let buffer = this[_xfa_object.$globalData].images && this[_xfa_object.$globalData].images.get(this.href); - - if (!buffer && (this.href || !this[_xfa_object.$content])) { - return _utils.HTMLResult.EMPTY; - } - - if (!buffer && this.transferEncoding === "base64") { - buffer = (0, _util.stringToBytes)(atob(this[_xfa_object.$content])); - } - - if (!buffer) { - return _utils.HTMLResult.EMPTY; - } - - if (!this.contentType) { - for (const [header, type] of IMAGES_HEADERS) { - if (buffer.length > header.length && header.every((x, i) => x === buffer[i])) { - this.contentType = type; - break; - } - } - - if (!this.contentType) { - return _utils.HTMLResult.EMPTY; - } - } - - const blob = new Blob([buffer], { - type: this.contentType - }); - let style; - - switch (this.aspect) { - case "fit": - case "actual": - break; - - case "height": - style = { - height: "100%", - objectFit: "fill" - }; - break; - - case "none": - style = { - width: "100%", - height: "100%", - objectFit: "fill" - }; - break; - - case "width": - style = { - width: "100%", - objectFit: "fill" - }; - break; - } - - const parent = this[_xfa_object.$getParent](); - - return _utils.HTMLResult.success({ - name: "img", - attributes: { - class: ["xfaImage"], - style, - src: URL.createObjectURL(blob), - alt: parent ? ariaLabel(parent[_xfa_object.$getParent]()) : null - } - }); - } - -} - -class ImageEdit extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "imageEdit", true); - this.data = (0, _utils.getStringOption)(attributes.data, ["link", "embed"]); - this.id = attributes.id || ""; - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.border = null; - this.extras = null; - this.margin = null; - } - - [_xfa_object.$toHTML](availableSpace) { - if (this.data === "embed") { - return _utils.HTMLResult.success({ - name: "div", - children: [], - attributes: {} - }); - } - - return _utils.HTMLResult.EMPTY; - } - -} - -class Integer extends _xfa_object.ContentObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "integer"); - this.id = attributes.id || ""; - this.name = attributes.name || ""; - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - } - - [_xfa_object.$finalize]() { - const number = parseInt(this[_xfa_object.$content].trim(), 10); - this[_xfa_object.$content] = isNaN(number) ? null : number; - } - - [_xfa_object.$toHTML](availableSpace) { - return valueToHtml(this[_xfa_object.$content] !== null ? this[_xfa_object.$content].toString() : ""); - } - -} - -class Issuers extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "issuers", true); - this.id = attributes.id || ""; - this.type = (0, _utils.getStringOption)(attributes.type, ["optional", "required"]); - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.certificate = new _xfa_object.XFAObjectArray(); - } - -} - -class Items extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "items", true); - this.id = attributes.id || ""; - this.name = attributes.name || ""; - this.presence = (0, _utils.getStringOption)(attributes.presence, ["visible", "hidden", "inactive", "invisible"]); - this.ref = attributes.ref || ""; - this.save = (0, _utils.getInteger)({ - data: attributes.save, - defaultValue: 0, - validate: x => x === 1 - }); - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.boolean = new _xfa_object.XFAObjectArray(); - this.date = new _xfa_object.XFAObjectArray(); - this.dateTime = new _xfa_object.XFAObjectArray(); - this.decimal = new _xfa_object.XFAObjectArray(); - this.exData = new _xfa_object.XFAObjectArray(); - this.float = new _xfa_object.XFAObjectArray(); - this.image = new _xfa_object.XFAObjectArray(); - this.integer = new _xfa_object.XFAObjectArray(); - this.text = new _xfa_object.XFAObjectArray(); - this.time = new _xfa_object.XFAObjectArray(); - } - - [_xfa_object.$toHTML]() { - const output = []; - - for (const child of this[_xfa_object.$getChildren]()) { - output.push(child[_xfa_object.$text]()); - } - - return _utils.HTMLResult.success(output); - } - -} - -exports.Items = Items; - -class Keep extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "keep", true); - this.id = attributes.id || ""; - const options = ["none", "contentArea", "pageArea"]; - this.intact = (0, _utils.getStringOption)(attributes.intact, options); - this.next = (0, _utils.getStringOption)(attributes.next, options); - this.previous = (0, _utils.getStringOption)(attributes.previous, options); - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.extras = null; - } - -} - -class KeyUsage extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "keyUsage"); - const options = ["", "yes", "no"]; - this.crlSign = (0, _utils.getStringOption)(attributes.crlSign, options); - this.dataEncipherment = (0, _utils.getStringOption)(attributes.dataEncipherment, options); - this.decipherOnly = (0, _utils.getStringOption)(attributes.decipherOnly, options); - this.digitalSignature = (0, _utils.getStringOption)(attributes.digitalSignature, options); - this.encipherOnly = (0, _utils.getStringOption)(attributes.encipherOnly, options); - this.id = attributes.id || ""; - this.keyAgreement = (0, _utils.getStringOption)(attributes.keyAgreement, options); - this.keyCertSign = (0, _utils.getStringOption)(attributes.keyCertSign, options); - this.keyEncipherment = (0, _utils.getStringOption)(attributes.keyEncipherment, options); - this.nonRepudiation = (0, _utils.getStringOption)(attributes.nonRepudiation, options); - this.type = (0, _utils.getStringOption)(attributes.type, ["optional", "required"]); - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - } - -} - -class Line extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "line", true); - this.hand = (0, _utils.getStringOption)(attributes.hand, ["even", "left", "right"]); - this.id = attributes.id || ""; - this.slope = (0, _utils.getStringOption)(attributes.slope, ["\\", "/"]); - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.edge = null; - } - - [_xfa_object.$toHTML]() { - const parent = this[_xfa_object.$getParent]()[_xfa_object.$getParent](); - - const edge = this.edge ? this.edge : new Edge({}); - - const edgeStyle = edge[_xfa_object.$toStyle](); - - const style = Object.create(null); - const thickness = edge.presence === "visible" ? edge.thickness : 0; - style.strokeWidth = (0, _html_utils.measureToString)(thickness); - style.stroke = edgeStyle.color; - let x1, y1, x2, y2; - let width = "100%"; - let height = "100%"; - - if (parent.w <= thickness) { - [x1, y1, x2, y2] = ["50%", 0, "50%", "100%"]; - width = style.strokeWidth; - } else if (parent.h <= thickness) { - [x1, y1, x2, y2] = [0, "50%", "100%", "50%"]; - height = style.strokeWidth; - } else { - if (this.slope === "\\") { - [x1, y1, x2, y2] = [0, 0, "100%", "100%"]; - } else { - [x1, y1, x2, y2] = [0, "100%", "100%", 0]; - } - } - - const line = { - name: "line", - attributes: { - xmlns: SVG_NS, - x1, - y1, - x2, - y2, - style - } - }; - const svg = { - name: "svg", - children: [line], - attributes: { - xmlns: SVG_NS, - width, - height, - style: { - overflow: "visible" - } - } - }; - - if (hasMargin(parent)) { - return _utils.HTMLResult.success({ - name: "div", - attributes: { - style: { - display: "inline", - width: "100%", - height: "100%" - } - }, - children: [svg] - }); - } - - svg.attributes.style.position = "absolute"; - return _utils.HTMLResult.success(svg); - } - -} - -class Linear extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "linear", true); - this.id = attributes.id || ""; - this.type = (0, _utils.getStringOption)(attributes.type, ["toRight", "toBottom", "toLeft", "toTop"]); - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.color = null; - this.extras = null; - } - - [_xfa_object.$toStyle](startColor) { - startColor = startColor ? startColor[_xfa_object.$toStyle]() : "#FFFFFF"; - const transf = this.type.replace(/([RBLT])/, " $1").toLowerCase(); - const endColor = this.color ? this.color[_xfa_object.$toStyle]() : "#000000"; - return `linear-gradient(${transf}, ${startColor}, ${endColor})`; - } - -} - -class LockDocument extends _xfa_object.ContentObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "lockDocument"); - this.id = attributes.id || ""; - this.type = (0, _utils.getStringOption)(attributes.type, ["optional", "required"]); - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - } - - [_xfa_object.$finalize]() { - this[_xfa_object.$content] = (0, _utils.getStringOption)(this[_xfa_object.$content], ["auto", "0", "1"]); - } - -} - -class Manifest extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "manifest", true); - this.action = (0, _utils.getStringOption)(attributes.action, ["include", "all", "exclude"]); - this.id = attributes.id || ""; - this.name = attributes.name || ""; - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.extras = null; - this.ref = new _xfa_object.XFAObjectArray(); - } - -} - -class Margin extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "margin", true); - this.bottomInset = (0, _utils.getMeasurement)(attributes.bottomInset, "0"); - this.id = attributes.id || ""; - this.leftInset = (0, _utils.getMeasurement)(attributes.leftInset, "0"); - this.rightInset = (0, _utils.getMeasurement)(attributes.rightInset, "0"); - this.topInset = (0, _utils.getMeasurement)(attributes.topInset, "0"); - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.extras = null; - } - - [_xfa_object.$toStyle]() { - return { - margin: (0, _html_utils.measureToString)(this.topInset) + " " + (0, _html_utils.measureToString)(this.rightInset) + " " + (0, _html_utils.measureToString)(this.bottomInset) + " " + (0, _html_utils.measureToString)(this.leftInset) - }; - } - -} - -class Mdp extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "mdp"); - this.id = attributes.id || ""; - this.permissions = (0, _utils.getInteger)({ - data: attributes.permissions, - defaultValue: 2, - validate: x => x === 1 || x === 3 - }); - this.signatureType = (0, _utils.getStringOption)(attributes.signatureType, ["filler", "author"]); - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - } - -} - -class Medium extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "medium"); - this.id = attributes.id || ""; - this.imagingBBox = (0, _utils.getBBox)(attributes.imagingBBox); - this.long = (0, _utils.getMeasurement)(attributes.long); - this.orientation = (0, _utils.getStringOption)(attributes.orientation, ["portrait", "landscape"]); - this.short = (0, _utils.getMeasurement)(attributes.short); - this.stock = attributes.stock || ""; - this.trayIn = (0, _utils.getStringOption)(attributes.trayIn, ["auto", "delegate", "pageFront"]); - this.trayOut = (0, _utils.getStringOption)(attributes.trayOut, ["auto", "delegate"]); - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - } - -} - -class Message extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "message", true); - this.id = attributes.id || ""; - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.text = new _xfa_object.XFAObjectArray(); - } - -} - -class NumericEdit extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "numericEdit", true); - this.hScrollPolicy = (0, _utils.getStringOption)(attributes.hScrollPolicy, ["auto", "off", "on"]); - this.id = attributes.id || ""; - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.border = null; - this.comb = null; - this.extras = null; - this.margin = null; - } - - [_xfa_object.$toHTML](availableSpace) { - const style = (0, _html_utils.toStyle)(this, "border", "font", "margin"); - - const field = this[_xfa_object.$getParent]()[_xfa_object.$getParent](); - - const html = { - name: "input", - attributes: { - type: "text", - fieldId: field[_xfa_object.$uid], - dataId: field[_xfa_object.$data] && field[_xfa_object.$data][_xfa_object.$uid] || field[_xfa_object.$uid], - class: ["xfaTextfield"], - style, - "aria-label": ariaLabel(field) - } - }; - return _utils.HTMLResult.success({ - name: "label", - attributes: { - class: ["xfaLabel"] - }, - children: [html] - }); - } - -} - -class Occur extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "occur", true); - this.id = attributes.id || ""; - this.initial = attributes.initial !== "" ? (0, _utils.getInteger)({ - data: attributes.initial, - defaultValue: "", - validate: x => true - }) : ""; - this.max = attributes.max !== "" ? (0, _utils.getInteger)({ - data: attributes.max, - defaultValue: 1, - validate: x => true - }) : ""; - this.min = attributes.min !== "" ? (0, _utils.getInteger)({ - data: attributes.min, - defaultValue: 1, - validate: x => true - }) : ""; - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.extras = null; - } - - [_xfa_object.$clean]() { - const parent = this[_xfa_object.$getParent](); - - const originalMin = this.min; - - if (this.min === "") { - this.min = parent instanceof PageArea || parent instanceof PageSet ? 0 : 1; - } - - if (this.max === "") { - if (originalMin === "") { - this.max = parent instanceof PageArea || parent instanceof PageSet ? -1 : 1; - } else { - this.max = this.min; - } - } - - if (this.max !== -1 && this.max < this.min) { - this.max = this.min; - } - - if (this.initial === "") { - this.initial = parent instanceof Template ? 1 : this.min; - } - } - -} - -class Oid extends _xfa_object.StringObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "oid"); - this.id = attributes.id || ""; - this.name = attributes.name || ""; - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - } - -} - -class Oids extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "oids", true); - this.id = attributes.id || ""; - this.type = (0, _utils.getStringOption)(attributes.type, ["optional", "required"]); - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.oid = new _xfa_object.XFAObjectArray(); - } - -} - -class Overflow extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "overflow"); - this.id = attributes.id || ""; - this.leader = attributes.leader || ""; - this.target = attributes.target || ""; - this.trailer = attributes.trailer || ""; - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - } - - [_xfa_object.$getExtra]() { - if (!this[_xfa_object.$extra]) { - const parent = this[_xfa_object.$getParent](); - - const root = this[_xfa_object.$getTemplateRoot](); - - const target = root[_xfa_object.$searchNode](this.target, parent); - - const leader = root[_xfa_object.$searchNode](this.leader, parent); - - const trailer = root[_xfa_object.$searchNode](this.trailer, parent); - - this[_xfa_object.$extra] = { - target: target && target[0] || null, - leader: leader && leader[0] || null, - trailer: trailer && trailer[0] || null, - addLeader: false, - addTrailer: false - }; - } - - return this[_xfa_object.$extra]; - } - -} - -class PageArea extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "pageArea", true); - this.blankOrNotBlank = (0, _utils.getStringOption)(attributes.blankOrNotBlank, ["any", "blank", "notBlank"]); - this.id = attributes.id || ""; - this.initialNumber = (0, _utils.getInteger)({ - data: attributes.initialNumber, - defaultValue: 1, - validate: x => true - }); - this.name = attributes.name || ""; - this.numbered = (0, _utils.getInteger)({ - data: attributes.numbered, - defaultValue: 1, - validate: x => true - }); - this.oddOrEven = (0, _utils.getStringOption)(attributes.oddOrEven, ["any", "even", "odd"]); - this.pagePosition = (0, _utils.getStringOption)(attributes.pagePosition, ["any", "first", "last", "only", "rest"]); - this.relevant = (0, _utils.getRelevant)(attributes.relevant); - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.desc = null; - this.extras = null; - this.medium = null; - this.occur = null; - this.area = new _xfa_object.XFAObjectArray(); - this.contentArea = new _xfa_object.XFAObjectArray(); - this.draw = new _xfa_object.XFAObjectArray(); - this.exclGroup = new _xfa_object.XFAObjectArray(); - this.field = new _xfa_object.XFAObjectArray(); - this.subform = new _xfa_object.XFAObjectArray(); - } - - [_xfa_object.$isUsable]() { - if (!this[_xfa_object.$extra]) { - this[_xfa_object.$extra] = { - numberOfUse: 0 - }; - return true; - } - - return !this.occur || this.occur.max === -1 || this[_xfa_object.$extra].numberOfUse < this.occur.max; - } - - [_xfa_object.$cleanPage]() { - delete this[_xfa_object.$extra]; - } - - [_xfa_object.$getNextPage]() { - if (!this[_xfa_object.$extra]) { - this[_xfa_object.$extra] = { - numberOfUse: 0 - }; - } - - const parent = this[_xfa_object.$getParent](); - - if (parent.relation === "orderedOccurrence") { - if (this[_xfa_object.$isUsable]()) { - this[_xfa_object.$extra].numberOfUse += 1; - return this; - } - } - - return parent[_xfa_object.$getNextPage](); - } - - [_xfa_object.$getAvailableSpace]() { - return this[_xfa_object.$extra].space || { - width: 0, - height: 0 - }; - } - - [_xfa_object.$toHTML]() { - if (!this[_xfa_object.$extra]) { - this[_xfa_object.$extra] = { - numberOfUse: 1 - }; - } - - const children = []; - this[_xfa_object.$extra].children = children; - const style = Object.create(null); - - if (this.medium && this.medium.short && this.medium.long) { - style.width = (0, _html_utils.measureToString)(this.medium.short); - style.height = (0, _html_utils.measureToString)(this.medium.long); - this[_xfa_object.$extra].space = { - width: this.medium.short, - height: this.medium.long - }; - - if (this.medium.orientation === "landscape") { - const x = style.width; - style.width = style.height; - style.height = x; - this[_xfa_object.$extra].space = { - width: this.medium.long, - height: this.medium.short - }; - } - } else { - (0, _util.warn)("XFA - No medium specified in pageArea: please file a bug."); - } - - this[_xfa_object.$childrenToHTML]({ - filter: new Set(["area", "draw", "field", "subform"]), - include: true - }); - - this[_xfa_object.$childrenToHTML]({ - filter: new Set(["contentArea"]), - include: true - }); - - return _utils.HTMLResult.success({ - name: "div", - children, - attributes: { - class: ["xfaPage"], - id: this[_xfa_object.$uid], - style, - xfaName: this.name - } - }); - } - -} - -class PageSet extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "pageSet", true); - this.duplexImposition = (0, _utils.getStringOption)(attributes.duplexImposition, ["longEdge", "shortEdge"]); - this.id = attributes.id || ""; - this.name = attributes.name || ""; - this.relation = (0, _utils.getStringOption)(attributes.relation, ["orderedOccurrence", "duplexPaginated", "simplexPaginated"]); - this.relevant = (0, _utils.getRelevant)(attributes.relevant); - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.extras = null; - this.occur = null; - this.pageArea = new _xfa_object.XFAObjectArray(); - this.pageSet = new _xfa_object.XFAObjectArray(); - } - - [_xfa_object.$cleanPage]() { - for (const page of this.pageArea.children) { - page[_xfa_object.$cleanPage](); - } - - for (const page of this.pageSet.children) { - page[_xfa_object.$cleanPage](); - } - } - - [_xfa_object.$isUsable]() { - return !this.occur || this.occur.max === -1 || this[_xfa_object.$extra].numberOfUse < this.occur.max; - } - - [_xfa_object.$getNextPage]() { - if (!this[_xfa_object.$extra]) { - this[_xfa_object.$extra] = { - numberOfUse: 1, - pageIndex: -1, - pageSetIndex: -1 - }; - } - - if (this.relation === "orderedOccurrence") { - if (this[_xfa_object.$extra].pageIndex + 1 < this.pageArea.children.length) { - this[_xfa_object.$extra].pageIndex += 1; - const pageArea = this.pageArea.children[this[_xfa_object.$extra].pageIndex]; - return pageArea[_xfa_object.$getNextPage](); - } - - if (this[_xfa_object.$extra].pageSetIndex + 1 < this.pageSet.children.length) { - this[_xfa_object.$extra].pageSetIndex += 1; - return this.pageSet.children[this[_xfa_object.$extra].pageSetIndex][_xfa_object.$getNextPage](); - } - - if (this[_xfa_object.$isUsable]()) { - this[_xfa_object.$extra].numberOfUse += 1; - this[_xfa_object.$extra].pageIndex = -1; - this[_xfa_object.$extra].pageSetIndex = -1; - return this[_xfa_object.$getNextPage](); - } - - const parent = this[_xfa_object.$getParent](); - - if (parent instanceof PageSet) { - return parent[_xfa_object.$getNextPage](); - } - - this[_xfa_object.$cleanPage](); - - return this[_xfa_object.$getNextPage](); - } - - const pageNumber = this[_xfa_object.$getTemplateRoot]()[_xfa_object.$extra].pageNumber; - - const parity = pageNumber % 2 === 0 ? "even" : "odd"; - const position = pageNumber === 0 ? "first" : "rest"; - let page = this.pageArea.children.find(p => p.oddOrEven === parity && p.pagePosition === position); - - if (page) { - return page; - } - - page = this.pageArea.children.find(p => p.oddOrEven === "any" && p.pagePosition === position); - - if (page) { - return page; - } - - page = this.pageArea.children.find(p => p.oddOrEven === "any" && p.pagePosition === "any"); - - if (page) { - return page; - } - - return this.pageArea.children[0]; - } - -} - -class Para extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "para", true); - this.hAlign = (0, _utils.getStringOption)(attributes.hAlign, ["left", "center", "justify", "justifyAll", "radix", "right"]); - this.id = attributes.id || ""; - this.lineHeight = attributes.lineHeight ? (0, _utils.getMeasurement)(attributes.lineHeight, "0pt") : ""; - this.marginLeft = attributes.marginLeft ? (0, _utils.getMeasurement)(attributes.marginLeft, "0pt") : ""; - this.marginRight = attributes.marginRight ? (0, _utils.getMeasurement)(attributes.marginRight, "0pt") : ""; - this.orphans = (0, _utils.getInteger)({ - data: attributes.orphans, - defaultValue: 0, - validate: x => x >= 0 - }); - this.preserve = attributes.preserve || ""; - this.radixOffset = attributes.radixOffset ? (0, _utils.getMeasurement)(attributes.radixOffset, "0pt") : ""; - this.spaceAbove = attributes.spaceAbove ? (0, _utils.getMeasurement)(attributes.spaceAbove, "0pt") : ""; - this.spaceBelow = attributes.spaceBelow ? (0, _utils.getMeasurement)(attributes.spaceBelow, "0pt") : ""; - this.tabDefault = attributes.tabDefault ? (0, _utils.getMeasurement)(this.tabDefault) : ""; - this.tabStops = (attributes.tabStops || "").trim().split(/\s+/).map((x, i) => i % 2 === 1 ? (0, _utils.getMeasurement)(x) : x); - this.textIndent = attributes.textIndent ? (0, _utils.getMeasurement)(attributes.textIndent, "0pt") : ""; - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.vAlign = (0, _utils.getStringOption)(attributes.vAlign, ["top", "bottom", "middle"]); - this.widows = (0, _utils.getInteger)({ - data: attributes.widows, - defaultValue: 0, - validate: x => x >= 0 - }); - this.hyphenation = null; - } - - [_xfa_object.$toStyle]() { - const style = (0, _html_utils.toStyle)(this, "hAlign"); - - if (this.marginLeft !== "") { - style.paddingLeft = (0, _html_utils.measureToString)(this.marginLeft); - } - - if (this.marginRight !== "") { - style.paddingight = (0, _html_utils.measureToString)(this.marginRight); - } - - if (this.spaceAbove !== "") { - style.paddingTop = (0, _html_utils.measureToString)(this.spaceAbove); - } - - if (this.spaceBelow !== "") { - style.paddingBottom = (0, _html_utils.measureToString)(this.spaceBelow); - } - - if (this.textIndent !== "") { - style.textIndent = (0, _html_utils.measureToString)(this.textIndent); - (0, _html_utils.fixTextIndent)(style); - } - - if (this.lineHeight > 0) { - style.lineHeight = (0, _html_utils.measureToString)(this.lineHeight); - } - - if (this.tabDefault !== "") { - style.tabSize = (0, _html_utils.measureToString)(this.tabDefault); - } - - if (this.tabStops.length > 0) {} - - if (this.hyphenatation) { - Object.assign(style, this.hyphenatation[_xfa_object.$toStyle]()); - } - - return style; - } - -} - -class PasswordEdit extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "passwordEdit", true); - this.hScrollPolicy = (0, _utils.getStringOption)(attributes.hScrollPolicy, ["auto", "off", "on"]); - this.id = attributes.id || ""; - this.passwordChar = attributes.passwordChar || "*"; - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.border = null; - this.extras = null; - this.margin = null; - } - -} - -class Pattern extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "pattern", true); - this.id = attributes.id || ""; - this.type = (0, _utils.getStringOption)(attributes.type, ["crossHatch", "crossDiagonal", "diagonalLeft", "diagonalRight", "horizontal", "vertical"]); - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.color = null; - this.extras = null; - } - - [_xfa_object.$toStyle](startColor) { - startColor = startColor ? startColor[_xfa_object.$toStyle]() : "#FFFFFF"; - const endColor = this.color ? this.color[_xfa_object.$toStyle]() : "#000000"; - const width = 5; - const cmd = "repeating-linear-gradient"; - const colors = `${startColor},${startColor} ${width}px,${endColor} ${width}px,${endColor} ${2 * width}px`; - - switch (this.type) { - case "crossHatch": - return `${cmd}(to top,${colors}) ${cmd}(to right,${colors})`; - - case "crossDiagonal": - return `${cmd}(45deg,${colors}) ${cmd}(-45deg,${colors})`; - - case "diagonalLeft": - return `${cmd}(45deg,${colors})`; - - case "diagonalRight": - return `${cmd}(-45deg,${colors})`; - - case "horizontal": - return `${cmd}(to top,${colors})`; - - case "vertical": - return `${cmd}(to right,${colors})`; - } - - return ""; - } - -} - -class Picture extends _xfa_object.StringObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "picture"); - this.id = attributes.id || ""; - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - } - -} - -class Proto extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "proto", true); - this.appearanceFilter = new _xfa_object.XFAObjectArray(); - this.arc = new _xfa_object.XFAObjectArray(); - this.area = new _xfa_object.XFAObjectArray(); - this.assist = new _xfa_object.XFAObjectArray(); - this.barcode = new _xfa_object.XFAObjectArray(); - this.bindItems = new _xfa_object.XFAObjectArray(); - this.bookend = new _xfa_object.XFAObjectArray(); - this.boolean = new _xfa_object.XFAObjectArray(); - this.border = new _xfa_object.XFAObjectArray(); - this.break = new _xfa_object.XFAObjectArray(); - this.breakAfter = new _xfa_object.XFAObjectArray(); - this.breakBefore = new _xfa_object.XFAObjectArray(); - this.button = new _xfa_object.XFAObjectArray(); - this.calculate = new _xfa_object.XFAObjectArray(); - this.caption = new _xfa_object.XFAObjectArray(); - this.certificate = new _xfa_object.XFAObjectArray(); - this.certificates = new _xfa_object.XFAObjectArray(); - this.checkButton = new _xfa_object.XFAObjectArray(); - this.choiceList = new _xfa_object.XFAObjectArray(); - this.color = new _xfa_object.XFAObjectArray(); - this.comb = new _xfa_object.XFAObjectArray(); - this.connect = new _xfa_object.XFAObjectArray(); - this.contentArea = new _xfa_object.XFAObjectArray(); - this.corner = new _xfa_object.XFAObjectArray(); - this.date = new _xfa_object.XFAObjectArray(); - this.dateTime = new _xfa_object.XFAObjectArray(); - this.dateTimeEdit = new _xfa_object.XFAObjectArray(); - this.decimal = new _xfa_object.XFAObjectArray(); - this.defaultUi = new _xfa_object.XFAObjectArray(); - this.desc = new _xfa_object.XFAObjectArray(); - this.digestMethod = new _xfa_object.XFAObjectArray(); - this.digestMethods = new _xfa_object.XFAObjectArray(); - this.draw = new _xfa_object.XFAObjectArray(); - this.edge = new _xfa_object.XFAObjectArray(); - this.encoding = new _xfa_object.XFAObjectArray(); - this.encodings = new _xfa_object.XFAObjectArray(); - this.encrypt = new _xfa_object.XFAObjectArray(); - this.encryptData = new _xfa_object.XFAObjectArray(); - this.encryption = new _xfa_object.XFAObjectArray(); - this.encryptionMethod = new _xfa_object.XFAObjectArray(); - this.encryptionMethods = new _xfa_object.XFAObjectArray(); - this.event = new _xfa_object.XFAObjectArray(); - this.exData = new _xfa_object.XFAObjectArray(); - this.exObject = new _xfa_object.XFAObjectArray(); - this.exclGroup = new _xfa_object.XFAObjectArray(); - this.execute = new _xfa_object.XFAObjectArray(); - this.extras = new _xfa_object.XFAObjectArray(); - this.field = new _xfa_object.XFAObjectArray(); - this.fill = new _xfa_object.XFAObjectArray(); - this.filter = new _xfa_object.XFAObjectArray(); - this.float = new _xfa_object.XFAObjectArray(); - this.font = new _xfa_object.XFAObjectArray(); - this.format = new _xfa_object.XFAObjectArray(); - this.handler = new _xfa_object.XFAObjectArray(); - this.hyphenation = new _xfa_object.XFAObjectArray(); - this.image = new _xfa_object.XFAObjectArray(); - this.imageEdit = new _xfa_object.XFAObjectArray(); - this.integer = new _xfa_object.XFAObjectArray(); - this.issuers = new _xfa_object.XFAObjectArray(); - this.items = new _xfa_object.XFAObjectArray(); - this.keep = new _xfa_object.XFAObjectArray(); - this.keyUsage = new _xfa_object.XFAObjectArray(); - this.line = new _xfa_object.XFAObjectArray(); - this.linear = new _xfa_object.XFAObjectArray(); - this.lockDocument = new _xfa_object.XFAObjectArray(); - this.manifest = new _xfa_object.XFAObjectArray(); - this.margin = new _xfa_object.XFAObjectArray(); - this.mdp = new _xfa_object.XFAObjectArray(); - this.medium = new _xfa_object.XFAObjectArray(); - this.message = new _xfa_object.XFAObjectArray(); - this.numericEdit = new _xfa_object.XFAObjectArray(); - this.occur = new _xfa_object.XFAObjectArray(); - this.oid = new _xfa_object.XFAObjectArray(); - this.oids = new _xfa_object.XFAObjectArray(); - this.overflow = new _xfa_object.XFAObjectArray(); - this.pageArea = new _xfa_object.XFAObjectArray(); - this.pageSet = new _xfa_object.XFAObjectArray(); - this.para = new _xfa_object.XFAObjectArray(); - this.passwordEdit = new _xfa_object.XFAObjectArray(); - this.pattern = new _xfa_object.XFAObjectArray(); - this.picture = new _xfa_object.XFAObjectArray(); - this.radial = new _xfa_object.XFAObjectArray(); - this.reason = new _xfa_object.XFAObjectArray(); - this.reasons = new _xfa_object.XFAObjectArray(); - this.rectangle = new _xfa_object.XFAObjectArray(); - this.ref = new _xfa_object.XFAObjectArray(); - this.script = new _xfa_object.XFAObjectArray(); - this.setProperty = new _xfa_object.XFAObjectArray(); - this.signData = new _xfa_object.XFAObjectArray(); - this.signature = new _xfa_object.XFAObjectArray(); - this.signing = new _xfa_object.XFAObjectArray(); - this.solid = new _xfa_object.XFAObjectArray(); - this.speak = new _xfa_object.XFAObjectArray(); - this.stipple = new _xfa_object.XFAObjectArray(); - this.subform = new _xfa_object.XFAObjectArray(); - this.subformSet = new _xfa_object.XFAObjectArray(); - this.subjectDN = new _xfa_object.XFAObjectArray(); - this.subjectDNs = new _xfa_object.XFAObjectArray(); - this.submit = new _xfa_object.XFAObjectArray(); - this.text = new _xfa_object.XFAObjectArray(); - this.textEdit = new _xfa_object.XFAObjectArray(); - this.time = new _xfa_object.XFAObjectArray(); - this.timeStamp = new _xfa_object.XFAObjectArray(); - this.toolTip = new _xfa_object.XFAObjectArray(); - this.traversal = new _xfa_object.XFAObjectArray(); - this.traverse = new _xfa_object.XFAObjectArray(); - this.ui = new _xfa_object.XFAObjectArray(); - this.validate = new _xfa_object.XFAObjectArray(); - this.value = new _xfa_object.XFAObjectArray(); - this.variables = new _xfa_object.XFAObjectArray(); - } - -} - -class Radial extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "radial", true); - this.id = attributes.id || ""; - this.type = (0, _utils.getStringOption)(attributes.type, ["toEdge", "toCenter"]); - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.color = null; - this.extras = null; - } - - [_xfa_object.$toStyle](startColor) { - startColor = startColor ? startColor[_xfa_object.$toStyle]() : "#FFFFFF"; - const endColor = this.color ? this.color[_xfa_object.$toStyle]() : "#000000"; - const colors = this.type === "toEdge" ? `${startColor},${endColor}` : `${endColor},${startColor}`; - return `radial-gradient(circle at center, ${colors})`; - } - -} - -class Reason extends _xfa_object.StringObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "reason"); - this.id = attributes.id || ""; - this.name = attributes.name || ""; - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - } - -} - -class Reasons extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "reasons", true); - this.id = attributes.id || ""; - this.type = (0, _utils.getStringOption)(attributes.type, ["optional", "required"]); - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.reason = new _xfa_object.XFAObjectArray(); - } - -} - -class Rectangle extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "rectangle", true); - this.hand = (0, _utils.getStringOption)(attributes.hand, ["even", "left", "right"]); - this.id = attributes.id || ""; - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.corner = new _xfa_object.XFAObjectArray(4); - this.edge = new _xfa_object.XFAObjectArray(4); - this.fill = null; - } - - [_xfa_object.$toHTML]() { - const edge = this.edge.children.length ? this.edge.children[0] : new Edge({}); - - const edgeStyle = edge[_xfa_object.$toStyle](); - - const style = Object.create(null); - - if (this.fill && this.fill.presence === "visible") { - Object.assign(style, this.fill[_xfa_object.$toStyle]()); - } else { - style.fill = "transparent"; - } - - style.strokeWidth = (0, _html_utils.measureToString)(edge.presence === "visible" ? edge.thickness : 0); - style.stroke = edgeStyle.color; - const corner = this.corner.children.length ? this.corner.children[0] : new Corner({}); - - const cornerStyle = corner[_xfa_object.$toStyle](); - - const rect = { - name: "rect", - attributes: { - xmlns: SVG_NS, - width: "100%", - height: "100%", - x: 0, - y: 0, - rx: cornerStyle.radius, - ry: cornerStyle.radius, - style - } - }; - const svg = { - name: "svg", - children: [rect], - attributes: { - xmlns: SVG_NS, - style: { - overflow: "visible" - }, - width: "100%", - height: "100%" - } - }; - - const parent = this[_xfa_object.$getParent]()[_xfa_object.$getParent](); - - if (hasMargin(parent)) { - return _utils.HTMLResult.success({ - name: "div", - attributes: { - style: { - display: "inline", - width: "100%", - height: "100%" - } - }, - children: [svg] - }); - } - - svg.attributes.style.position = "absolute"; - return _utils.HTMLResult.success(svg); - } - -} - -class RefElement extends _xfa_object.StringObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "ref"); - this.id = attributes.id || ""; - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - } - -} - -class Script extends _xfa_object.StringObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "script"); - this.binding = attributes.binding || ""; - this.contentType = attributes.contentType || ""; - this.id = attributes.id || ""; - this.name = attributes.name || ""; - this.runAt = (0, _utils.getStringOption)(attributes.runAt, ["client", "both", "server"]); - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - } - -} - -class SetProperty extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "setProperty"); - this.connection = attributes.connection || ""; - this.ref = attributes.ref || ""; - this.target = attributes.target || ""; - } - -} - -exports.SetProperty = SetProperty; - -class SignData extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "signData", true); - this.id = attributes.id || ""; - this.operation = (0, _utils.getStringOption)(attributes.operation, ["sign", "clear", "verify"]); - this.ref = attributes.ref || ""; - this.target = attributes.target || ""; - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.filter = null; - this.manifest = null; - } - -} - -class Signature extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "signature", true); - this.id = attributes.id || ""; - this.type = (0, _utils.getStringOption)(attributes.type, ["PDF1.3", "PDF1.6"]); - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.border = null; - this.extras = null; - this.filter = null; - this.manifest = null; - this.margin = null; - } - -} - -class Signing extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "signing", true); - this.id = attributes.id || ""; - this.type = (0, _utils.getStringOption)(attributes.type, ["optional", "required"]); - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.certificate = new _xfa_object.XFAObjectArray(); - } - -} - -class Solid extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "solid", true); - this.id = attributes.id || ""; - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.extras = null; - } - - [_xfa_object.$toStyle](startColor) { - return startColor ? startColor[_xfa_object.$toStyle]() : "#FFFFFF"; - } - -} - -class Speak extends _xfa_object.StringObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "speak"); - this.disable = (0, _utils.getInteger)({ - data: attributes.disable, - defaultValue: 0, - validate: x => x === 1 - }); - this.id = attributes.id || ""; - this.priority = (0, _utils.getStringOption)(attributes.priority, ["custom", "caption", "name", "toolTip"]); - this.rid = attributes.rid || ""; - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - } - -} - -class Stipple extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "stipple", true); - this.id = attributes.id || ""; - this.rate = (0, _utils.getInteger)({ - data: attributes.rate, - defaultValue: 50, - validate: x => x >= 0 && x <= 100 - }); - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.color = null; - this.extras = null; - } - - [_xfa_object.$toStyle](bgColor) { - const alpha = this.rate / 100; - return _util.Util.makeHexColor(Math.round(bgColor.value.r * (1 - alpha) + this.value.r * alpha), Math.round(bgColor.value.g * (1 - alpha) + this.value.g * alpha), Math.round(bgColor.value.b * (1 - alpha) + this.value.b * alpha)); - } - -} - -class Subform extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "subform", true); - this.access = (0, _utils.getStringOption)(attributes.access, ["open", "nonInteractive", "protected", "readOnly"]); - this.allowMacro = (0, _utils.getInteger)({ - data: attributes.allowMacro, - defaultValue: 0, - validate: x => x === 1 - }); - this.anchorType = (0, _utils.getStringOption)(attributes.anchorType, ["topLeft", "bottomCenter", "bottomLeft", "bottomRight", "middleCenter", "middleLeft", "middleRight", "topCenter", "topRight"]); - this.colSpan = (0, _utils.getInteger)({ - data: attributes.colSpan, - defaultValue: 1, - validate: n => n >= 1 || n === -1 - }); - this.columnWidths = (attributes.columnWidths || "").trim().split(/\s+/).map(x => x === "-1" ? -1 : (0, _utils.getMeasurement)(x)); - this.h = attributes.h ? (0, _utils.getMeasurement)(attributes.h) : ""; - this.hAlign = (0, _utils.getStringOption)(attributes.hAlign, ["left", "center", "justify", "justifyAll", "radix", "right"]); - this.id = attributes.id || ""; - this.layout = (0, _utils.getStringOption)(attributes.layout, ["position", "lr-tb", "rl-row", "rl-tb", "row", "table", "tb"]); - this.locale = attributes.locale || ""; - this.maxH = (0, _utils.getMeasurement)(attributes.maxH, "0pt"); - this.maxW = (0, _utils.getMeasurement)(attributes.maxW, "0pt"); - this.mergeMode = (0, _utils.getStringOption)(attributes.mergeMode, ["consumeData", "matchTemplate"]); - this.minH = (0, _utils.getMeasurement)(attributes.minH, "0pt"); - this.minW = (0, _utils.getMeasurement)(attributes.minW, "0pt"); - this.name = attributes.name || ""; - this.presence = (0, _utils.getStringOption)(attributes.presence, ["visible", "hidden", "inactive", "invisible"]); - this.relevant = (0, _utils.getRelevant)(attributes.relevant); - this.restoreState = (0, _utils.getStringOption)(attributes.restoreState, ["manual", "auto"]); - this.scope = (0, _utils.getStringOption)(attributes.scope, ["name", "none"]); - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.w = attributes.w ? (0, _utils.getMeasurement)(attributes.w) : ""; - this.x = (0, _utils.getMeasurement)(attributes.x, "0pt"); - this.y = (0, _utils.getMeasurement)(attributes.y, "0pt"); - this.assist = null; - this.bind = null; - this.bookend = null; - this.border = null; - this.break = null; - this.calculate = null; - this.desc = null; - this.extras = null; - this.keep = null; - this.margin = null; - this.occur = null; - this.overflow = null; - this.pageSet = null; - this.para = null; - this.traversal = null; - this.validate = null; - this.variables = null; - this.area = new _xfa_object.XFAObjectArray(); - this.breakAfter = new _xfa_object.XFAObjectArray(); - this.breakBefore = new _xfa_object.XFAObjectArray(); - this.connect = new _xfa_object.XFAObjectArray(); - this.draw = new _xfa_object.XFAObjectArray(); - this.event = new _xfa_object.XFAObjectArray(); - this.exObject = new _xfa_object.XFAObjectArray(); - this.exclGroup = new _xfa_object.XFAObjectArray(); - this.field = new _xfa_object.XFAObjectArray(); - this.proto = new _xfa_object.XFAObjectArray(); - this.setProperty = new _xfa_object.XFAObjectArray(); - this.subform = new _xfa_object.XFAObjectArray(); - this.subformSet = new _xfa_object.XFAObjectArray(); - } - - [_xfa_object.$getSubformParent]() { - const parent = this[_xfa_object.$getParent](); - - if (parent instanceof SubformSet) { - return parent[_xfa_object.$getSubformParent](); - } - - return parent; - } - - [_xfa_object.$isBindable]() { - return true; - } - - [_xfa_object.$isThereMoreWidth]() { - return this.layout.endsWith("-tb") && this[_xfa_object.$extra].attempt === 0 && this[_xfa_object.$extra].numberInLine > 0 || this[_xfa_object.$getParent]()[_xfa_object.$isThereMoreWidth](); - } - - *[_xfa_object.$getContainedChildren]() { - yield* getContainedChildren(this); - } - - [_xfa_object.$flushHTML]() { - return (0, _layout.flushHTML)(this); - } - - [_xfa_object.$addHTML](html, bbox) { - (0, _layout.addHTML)(this, html, bbox); - } - - [_xfa_object.$getAvailableSpace]() { - return (0, _layout.getAvailableSpace)(this); - } - - [_xfa_object.$isSplittable]() { - const parent = this[_xfa_object.$getSubformParent](); - - if (!parent[_xfa_object.$isSplittable]()) { - return false; - } - - if (this[_xfa_object.$extra]._isSplittable !== undefined) { - return this[_xfa_object.$extra]._isSplittable; - } - - if (this.layout === "position" || this.layout.includes("row")) { - this[_xfa_object.$extra]._isSplittable = false; - return false; - } - - if (this.keep && this.keep.intact !== "none") { - this[_xfa_object.$extra]._isSplittable = false; - return false; - } - - if (parent.layout && parent.layout.endsWith("-tb") && parent[_xfa_object.$extra].numberInLine !== 0) { - return false; - } - - this[_xfa_object.$extra]._isSplittable = true; - return true; - } - - [_xfa_object.$toHTML](availableSpace) { - setTabIndex(this); - - if (this.break) { - if (this.break.after !== "auto" || this.break.afterTarget !== "") { - const node = new BreakAfter({ - targetType: this.break.after, - target: this.break.afterTarget, - startNew: this.break.startNew.toString() - }); - node[_xfa_object.$globalData] = this[_xfa_object.$globalData]; - - this[_xfa_object.$appendChild](node); - - this.breakAfter.push(node); - } - - if (this.break.before !== "auto" || this.break.beforeTarget !== "") { - const node = new BreakBefore({ - targetType: this.break.before, - target: this.break.beforeTarget, - startNew: this.break.startNew.toString() - }); - node[_xfa_object.$globalData] = this[_xfa_object.$globalData]; - - this[_xfa_object.$appendChild](node); - - this.breakBefore.push(node); - } - - if (this.break.overflowTarget !== "") { - const node = new Overflow({ - target: this.break.overflowTarget, - leader: this.break.overflowLeader, - trailer: this.break.overflowTrailer - }); - node[_xfa_object.$globalData] = this[_xfa_object.$globalData]; - - this[_xfa_object.$appendChild](node); - - this.overflow.push(node); - } - - this[_xfa_object.$removeChild](this.break); - - this.break = null; - } - - if (this.presence === "hidden" || this.presence === "inactive") { - return _utils.HTMLResult.EMPTY; - } - - if (this.breakBefore.children.length > 1 || this.breakAfter.children.length > 1) { - (0, _util.warn)("XFA - Several breakBefore or breakAfter in subforms: please file a bug."); - } - - if (this.breakBefore.children.length >= 1) { - const breakBefore = this.breakBefore.children[0]; - - if (handleBreak(breakBefore)) { - return _utils.HTMLResult.breakNode(breakBefore); - } - } - - if (this[_xfa_object.$extra] && this[_xfa_object.$extra].afterBreakAfter) { - return _utils.HTMLResult.EMPTY; - } - - (0, _html_utils.fixDimensions)(this); - const children = []; - const attributes = { - id: this[_xfa_object.$uid], - class: [] - }; - (0, _html_utils.setAccess)(this, attributes.class); - - if (!this[_xfa_object.$extra]) { - this[_xfa_object.$extra] = Object.create(null); - } - - Object.assign(this[_xfa_object.$extra], { - children, - line: null, - attributes, - attempt: 0, - numberInLine: 0, - availableSpace: { - width: Math.min(this.w || Infinity, availableSpace.width), - height: Math.min(this.h || Infinity, availableSpace.height) - }, - width: 0, - height: 0, - prevHeight: 0, - currentWidth: 0 - }); - - const root = this[_xfa_object.$getTemplateRoot](); - - const savedNoLayoutFailure = root[_xfa_object.$extra].noLayoutFailure; - - const isSplittable = this[_xfa_object.$isSplittable](); - - if (!isSplittable) { - setFirstUnsplittable(this); - } - - if (!(0, _layout.checkDimensions)(this, availableSpace)) { - return _utils.HTMLResult.FAILURE; - } - - const filter = new Set(["area", "draw", "exclGroup", "field", "subform", "subformSet"]); - - if (this.layout.includes("row")) { - const columnWidths = this[_xfa_object.$getSubformParent]().columnWidths; - - if (Array.isArray(columnWidths) && columnWidths.length > 0) { - this[_xfa_object.$extra].columnWidths = columnWidths; - this[_xfa_object.$extra].currentColumn = 0; - } - } - - const style = (0, _html_utils.toStyle)(this, "anchorType", "dimensions", "position", "presence", "border", "margin", "hAlign"); - const classNames = ["xfaSubform"]; - const cl = (0, _html_utils.layoutClass)(this); - - if (cl) { - classNames.push(cl); - } - - attributes.style = style; - attributes.class = classNames; - - if (this.name) { - attributes.xfaName = this.name; - } - - if (this.overflow) { - const overflowExtra = this.overflow[_xfa_object.$getExtra](); - - if (overflowExtra.addLeader) { - overflowExtra.addLeader = false; - handleOverflow(this, overflowExtra.leader, availableSpace); - } - } - - this[_xfa_object.$pushPara](); - - const isLrTb = this.layout === "lr-tb" || this.layout === "rl-tb"; - const maxRun = isLrTb ? MAX_ATTEMPTS_FOR_LRTB_LAYOUT : 1; - - for (; this[_xfa_object.$extra].attempt < maxRun; this[_xfa_object.$extra].attempt++) { - if (isLrTb && this[_xfa_object.$extra].attempt === MAX_ATTEMPTS_FOR_LRTB_LAYOUT - 1) { - this[_xfa_object.$extra].numberInLine = 0; - } - - const result = this[_xfa_object.$childrenToHTML]({ - filter, - include: true - }); - - if (result.success) { - break; - } - - if (result.isBreak()) { - this[_xfa_object.$popPara](); - - return result; - } - - if (isLrTb && this[_xfa_object.$extra].attempt === 0 && this[_xfa_object.$extra].numberInLine === 0 && !root[_xfa_object.$extra].noLayoutFailure) { - this[_xfa_object.$extra].attempt = maxRun; - break; - } - } - - this[_xfa_object.$popPara](); - - if (!isSplittable) { - unsetFirstUnsplittable(this); - } - - root[_xfa_object.$extra].noLayoutFailure = savedNoLayoutFailure; - - if (this[_xfa_object.$extra].attempt === maxRun) { - if (this.overflow) { - this[_xfa_object.$getTemplateRoot]()[_xfa_object.$extra].overflowNode = this.overflow; - } - - if (!isSplittable) { - delete this[_xfa_object.$extra]; - } - - return _utils.HTMLResult.FAILURE; - } - - if (this.overflow) { - const overflowExtra = this.overflow[_xfa_object.$getExtra](); - - if (overflowExtra.addTrailer) { - overflowExtra.addTrailer = false; - handleOverflow(this, overflowExtra.trailer, availableSpace); - } - } - - let marginH = 0; - let marginV = 0; - - if (this.margin) { - marginH = this.margin.leftInset + this.margin.rightInset; - marginV = this.margin.topInset + this.margin.bottomInset; - } - - const width = Math.max(this[_xfa_object.$extra].width + marginH, this.w || 0); - const height = Math.max(this[_xfa_object.$extra].height + marginV, this.h || 0); - const bbox = [this.x, this.y, width, height]; - - if (this.w === "") { - style.width = (0, _html_utils.measureToString)(width); - } - - if (this.h === "") { - style.height = (0, _html_utils.measureToString)(height); - } - - if ((style.width === "0px" || style.height === "0px") && children.length === 0) { - return _utils.HTMLResult.EMPTY; - } - - const html = { - name: "div", - attributes, - children - }; - applyAssist(this, attributes); - - const result = _utils.HTMLResult.success((0, _html_utils.createWrapper)(this, html), bbox); - - if (this.breakAfter.children.length >= 1) { - const breakAfter = this.breakAfter.children[0]; - - if (handleBreak(breakAfter)) { - this[_xfa_object.$extra].afterBreakAfter = result; - return _utils.HTMLResult.breakNode(breakAfter); - } - } - - delete this[_xfa_object.$extra]; - return result; - } - -} - -class SubformSet extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "subformSet", true); - this.id = attributes.id || ""; - this.name = attributes.name || ""; - this.relation = (0, _utils.getStringOption)(attributes.relation, ["ordered", "choice", "unordered"]); - this.relevant = (0, _utils.getRelevant)(attributes.relevant); - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.bookend = null; - this.break = null; - this.desc = null; - this.extras = null; - this.occur = null; - this.overflow = null; - this.breakAfter = new _xfa_object.XFAObjectArray(); - this.breakBefore = new _xfa_object.XFAObjectArray(); - this.subform = new _xfa_object.XFAObjectArray(); - this.subformSet = new _xfa_object.XFAObjectArray(); - } - - *[_xfa_object.$getContainedChildren]() { - yield* getContainedChildren(this); - } - - [_xfa_object.$getSubformParent]() { - let parent = this[_xfa_object.$getParent](); - - while (!(parent instanceof Subform)) { - parent = parent[_xfa_object.$getParent](); - } - - return parent; - } - - [_xfa_object.$isBindable]() { - return true; - } - -} - -class SubjectDN extends _xfa_object.ContentObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "subjectDN"); - this.delimiter = attributes.delimiter || ","; - this.id = attributes.id || ""; - this.name = attributes.name || ""; - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - } - - [_xfa_object.$finalize]() { - this[_xfa_object.$content] = new Map(this[_xfa_object.$content].split(this.delimiter).map(kv => { - kv = kv.split("=", 2); - kv[0] = kv[0].trim(); - return kv; - })); - } - -} - -class SubjectDNs extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "subjectDNs", true); - this.id = attributes.id || ""; - this.type = (0, _utils.getStringOption)(attributes.type, ["optional", "required"]); - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.subjectDN = new _xfa_object.XFAObjectArray(); - } - -} - -class Submit extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "submit", true); - this.embedPDF = (0, _utils.getInteger)({ - data: attributes.embedPDF, - defaultValue: 0, - validate: x => x === 1 - }); - this.format = (0, _utils.getStringOption)(attributes.format, ["xdp", "formdata", "pdf", "urlencoded", "xfd", "xml"]); - this.id = attributes.id || ""; - this.target = attributes.target || ""; - this.textEncoding = (0, _utils.getKeyword)({ - data: attributes.textEncoding ? attributes.textEncoding.toLowerCase() : "", - defaultValue: "", - validate: k => ["utf-8", "big-five", "fontspecific", "gbk", "gb-18030", "gb-2312", "ksc-5601", "none", "shift-jis", "ucs-2", "utf-16"].includes(k) || k.match(/iso-8859-\d{2}/) - }); - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.xdpContent = attributes.xdpContent || ""; - this.encrypt = null; - this.encryptData = new _xfa_object.XFAObjectArray(); - this.signData = new _xfa_object.XFAObjectArray(); - } - -} - -class Template extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "template", true); - this.baseProfile = (0, _utils.getStringOption)(attributes.baseProfile, ["full", "interactiveForms"]); - this.extras = null; - this.subform = new _xfa_object.XFAObjectArray(); - } - - [_xfa_object.$finalize]() { - if (this.subform.children.length === 0) { - (0, _util.warn)("XFA - No subforms in template node."); - } - - if (this.subform.children.length >= 2) { - (0, _util.warn)("XFA - Several subforms in template node: please file a bug."); - } - - this[_xfa_object.$tabIndex] = DEFAULT_TAB_INDEX; - } - - [_xfa_object.$isSplittable]() { - return true; - } - - [_xfa_object.$searchNode](expr, container) { - if (expr.startsWith("#")) { - return [this[_xfa_object.$ids].get(expr.slice(1))]; - } - - return (0, _som.searchNode)(this, container, expr, true, true); - } - - *[_xfa_object.$toPages]() { - if (!this.subform.children.length) { - return _utils.HTMLResult.success({ - name: "div", - children: [] - }); - } - - this[_xfa_object.$extra] = { - overflowNode: null, - firstUnsplittable: null, - currentContentArea: null, - currentPageArea: null, - noLayoutFailure: false, - pageNumber: 1, - pagePosition: "first", - oddOrEven: "odd", - blankOrNotBlank: "nonBlank", - paraStack: [] - }; - const root = this.subform.children[0]; - - root.pageSet[_xfa_object.$cleanPage](); - - const pageAreas = root.pageSet.pageArea.children; - const mainHtml = { - name: "div", - children: [] - }; - let pageArea = null; - let breakBefore = null; - let breakBeforeTarget = null; - - if (root.breakBefore.children.length >= 1) { - breakBefore = root.breakBefore.children[0]; - breakBeforeTarget = breakBefore.target; - } else if (root.subform.children.length >= 1 && root.subform.children[0].breakBefore.children.length >= 1) { - breakBefore = root.subform.children[0].breakBefore.children[0]; - breakBeforeTarget = breakBefore.target; - } else if (root.break && root.break.beforeTarget) { - breakBefore = root.break; - breakBeforeTarget = breakBefore.beforeTarget; - } else if (root.subform.children.length >= 1 && root.subform.children[0].break && root.subform.children[0].break.beforeTarget) { - breakBefore = root.subform.children[0].break; - breakBeforeTarget = breakBefore.beforeTarget; - } - - if (breakBefore) { - const target = this[_xfa_object.$searchNode](breakBeforeTarget, breakBefore[_xfa_object.$getParent]()); - - if (target instanceof PageArea) { - pageArea = target; - breakBefore[_xfa_object.$extra] = {}; - } - } - - if (!pageArea) { - pageArea = pageAreas[0]; - } - - pageArea[_xfa_object.$extra] = { - numberOfUse: 1 - }; - - const pageAreaParent = pageArea[_xfa_object.$getParent](); - - pageAreaParent[_xfa_object.$extra] = { - numberOfUse: 1, - pageIndex: pageAreaParent.pageArea.children.indexOf(pageArea), - pageSetIndex: 0 - }; - let targetPageArea; - let leader = null; - let trailer = null; - let hasSomething = true; - let hasSomethingCounter = 0; - let startIndex = 0; - - while (true) { - if (!hasSomething) { - mainHtml.children.pop(); - - if (++hasSomethingCounter === MAX_EMPTY_PAGES) { - (0, _util.warn)("XFA - Something goes wrong: please file a bug."); - return mainHtml; - } - } else { - hasSomethingCounter = 0; - } - - targetPageArea = null; - this[_xfa_object.$extra].currentPageArea = pageArea; - - const page = pageArea[_xfa_object.$toHTML]().html; - - mainHtml.children.push(page); - - if (leader) { - this[_xfa_object.$extra].noLayoutFailure = true; - page.children.push(leader[_xfa_object.$toHTML](pageArea[_xfa_object.$extra].space).html); - leader = null; - } - - if (trailer) { - this[_xfa_object.$extra].noLayoutFailure = true; - page.children.push(trailer[_xfa_object.$toHTML](pageArea[_xfa_object.$extra].space).html); - trailer = null; - } - - const contentAreas = pageArea.contentArea.children; - const htmlContentAreas = page.children.filter(node => node.attributes.class.includes("xfaContentarea")); - hasSomething = false; - this[_xfa_object.$extra].firstUnsplittable = null; - this[_xfa_object.$extra].noLayoutFailure = false; - - const flush = index => { - const html = root[_xfa_object.$flushHTML](); - - if (html) { - hasSomething = hasSomething || html.children && html.children.length !== 0; - htmlContentAreas[index].children.push(html); - } - }; - - for (let i = startIndex, ii = contentAreas.length; i < ii; i++) { - const contentArea = this[_xfa_object.$extra].currentContentArea = contentAreas[i]; - const space = { - width: contentArea.w, - height: contentArea.h - }; - startIndex = 0; - - if (leader) { - htmlContentAreas[i].children.push(leader[_xfa_object.$toHTML](space).html); - leader = null; - } - - if (trailer) { - htmlContentAreas[i].children.push(trailer[_xfa_object.$toHTML](space).html); - trailer = null; - } - - const html = root[_xfa_object.$toHTML](space); - - if (html.success) { - if (html.html) { - hasSomething = hasSomething || html.html.children && html.html.children.length !== 0; - htmlContentAreas[i].children.push(html.html); - } else if (!hasSomething && mainHtml.children.length > 1) { - mainHtml.children.pop(); - } - - return mainHtml; - } - - if (html.isBreak()) { - const node = html.breakNode; - flush(i); - - if (node.targetType === "auto") { - continue; - } - - if (node.leader) { - leader = this[_xfa_object.$searchNode](node.leader, node[_xfa_object.$getParent]()); - leader = leader ? leader[0] : null; - } - - if (node.trailer) { - trailer = this[_xfa_object.$searchNode](node.trailer, node[_xfa_object.$getParent]()); - trailer = trailer ? trailer[0] : null; - } - - if (node.targetType === "pageArea") { - targetPageArea = node[_xfa_object.$extra].target; - i = Infinity; - } else if (!node[_xfa_object.$extra].target) { - i = node[_xfa_object.$extra].index; - } else { - targetPageArea = node[_xfa_object.$extra].target; - startIndex = node[_xfa_object.$extra].index + 1; - i = Infinity; - } - - continue; - } - - if (this[_xfa_object.$extra].overflowNode) { - const node = this[_xfa_object.$extra].overflowNode; - this[_xfa_object.$extra].overflowNode = null; - - const overflowExtra = node[_xfa_object.$getExtra](); - - const target = overflowExtra.target; - overflowExtra.addLeader = overflowExtra.leader !== null; - overflowExtra.addTrailer = overflowExtra.trailer !== null; - flush(i); - const currentIndex = i; - i = Infinity; - - if (target instanceof PageArea) { - targetPageArea = target; - } else if (target instanceof ContentArea) { - const index = contentAreas.findIndex(e => e === target); - - if (index !== -1) { - if (index > currentIndex) { - i = index - 1; - } else { - startIndex = index; - } - } else { - targetPageArea = target[_xfa_object.$getParent](); - startIndex = targetPageArea.contentArea.children.findIndex(e => e === target); - } - } - - continue; - } - - flush(i); - } - - this[_xfa_object.$extra].pageNumber += 1; - - if (targetPageArea) { - if (targetPageArea[_xfa_object.$isUsable]()) { - targetPageArea[_xfa_object.$extra].numberOfUse += 1; - } else { - targetPageArea = null; - } - } - - pageArea = targetPageArea || pageArea[_xfa_object.$getNextPage](); - yield null; - } - } - -} - -exports.Template = Template; - -class Text extends _xfa_object.ContentObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "text"); - this.id = attributes.id || ""; - this.maxChars = (0, _utils.getInteger)({ - data: attributes.maxChars, - defaultValue: 0, - validate: x => x >= 0 - }); - this.name = attributes.name || ""; - this.rid = attributes.rid || ""; - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - } - - [_xfa_object.$acceptWhitespace]() { - return true; - } - - [_xfa_object.$onChild](child) { - if (child[_xfa_object.$namespaceId] === _namespaces.NamespaceIds.xhtml.id) { - this[_xfa_object.$content] = child; - return true; - } - - (0, _util.warn)(`XFA - Invalid content in Text: ${child[_xfa_object.$nodeName]}.`); - return false; - } - - [_xfa_object.$onText](str) { - if (this[_xfa_object.$content] instanceof _xfa_object.XFAObject) { - return; - } - - super[_xfa_object.$onText](str); - } - - [_xfa_object.$finalize]() { - if (typeof this[_xfa_object.$content] === "string") { - this[_xfa_object.$content] = this[_xfa_object.$content].replace(/\r\n/g, "\n"); - } - } - - [_xfa_object.$getExtra]() { - if (typeof this[_xfa_object.$content] === "string") { - return this[_xfa_object.$content].split(/[\u2029\u2028\n]/).reduce((acc, line) => { - if (line) { - acc.push(line); - } - - return acc; - }, []).join("\n"); - } - - return this[_xfa_object.$content][_xfa_object.$text](); - } - - [_xfa_object.$toHTML](availableSpace) { - if (typeof this[_xfa_object.$content] === "string") { - const html = valueToHtml(this[_xfa_object.$content]).html; - - if (this[_xfa_object.$content].includes("\u2029")) { - html.name = "div"; - html.children = []; - - this[_xfa_object.$content].split("\u2029").map(para => para.split(/[\u2028\n]/).reduce((acc, line) => { - acc.push({ - name: "span", - value: line - }, { - name: "br" - }); - return acc; - }, [])).forEach(lines => { - html.children.push({ - name: "p", - children: lines - }); - }); - } else if (/[\u2028\n]/.test(this[_xfa_object.$content])) { - html.name = "div"; - html.children = []; - - this[_xfa_object.$content].split(/[\u2028\n]/).forEach(line => { - html.children.push({ - name: "span", - value: line - }, { - name: "br" - }); - }); - } - - return _utils.HTMLResult.success(html); - } - - return this[_xfa_object.$content][_xfa_object.$toHTML](availableSpace); - } - -} - -exports.Text = Text; - -class TextEdit extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "textEdit", true); - this.allowRichText = (0, _utils.getInteger)({ - data: attributes.allowRichText, - defaultValue: 0, - validate: x => x === 1 - }); - this.hScrollPolicy = (0, _utils.getStringOption)(attributes.hScrollPolicy, ["auto", "off", "on"]); - this.id = attributes.id || ""; - this.multiLine = (0, _utils.getInteger)({ - data: attributes.multiLine, - defaultValue: "", - validate: x => x === 0 || x === 1 - }); - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.vScrollPolicy = (0, _utils.getStringOption)(attributes.vScrollPolicy, ["auto", "off", "on"]); - this.border = null; - this.comb = null; - this.extras = null; - this.margin = null; - } - - [_xfa_object.$toHTML](availableSpace) { - const style = (0, _html_utils.toStyle)(this, "border", "font", "margin"); - let html; - - const field = this[_xfa_object.$getParent]()[_xfa_object.$getParent](); - - if (this.multiLine === "") { - this.multiLine = field instanceof Draw ? 1 : 0; - } - - if (this.multiLine === 1) { - html = { - name: "textarea", - attributes: { - dataId: field[_xfa_object.$data] && field[_xfa_object.$data][_xfa_object.$uid] || field[_xfa_object.$uid], - fieldId: field[_xfa_object.$uid], - class: ["xfaTextfield"], - style, - "aria-label": ariaLabel(field) - } - }; - } else { - html = { - name: "input", - attributes: { - type: "text", - dataId: field[_xfa_object.$data] && field[_xfa_object.$data][_xfa_object.$uid] || field[_xfa_object.$uid], - fieldId: field[_xfa_object.$uid], - class: ["xfaTextfield"], - style, - "aria-label": ariaLabel(field) - } - }; - } - - return _utils.HTMLResult.success({ - name: "label", - attributes: { - class: ["xfaLabel"] - }, - children: [html] - }); - } - -} - -class Time extends _xfa_object.StringObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "time"); - this.id = attributes.id || ""; - this.name = attributes.name || ""; - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - } - - [_xfa_object.$finalize]() { - const date = this[_xfa_object.$content].trim(); - - this[_xfa_object.$content] = date ? new Date(date) : null; - } - - [_xfa_object.$toHTML](availableSpace) { - return valueToHtml(this[_xfa_object.$content] ? this[_xfa_object.$content].toString() : ""); - } - -} - -class TimeStamp extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "timeStamp"); - this.id = attributes.id || ""; - this.server = attributes.server || ""; - this.type = (0, _utils.getStringOption)(attributes.type, ["optional", "required"]); - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - } - -} - -class ToolTip extends _xfa_object.StringObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "toolTip"); - this.id = attributes.id || ""; - this.rid = attributes.rid || ""; - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - } - -} - -class Traversal extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "traversal", true); - this.id = attributes.id || ""; - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.extras = null; - this.traverse = new _xfa_object.XFAObjectArray(); - } - -} - -class Traverse extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "traverse", true); - this.id = attributes.id || ""; - this.operation = (0, _utils.getStringOption)(attributes.operation, ["next", "back", "down", "first", "left", "right", "up"]); - this.ref = attributes.ref || ""; - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.extras = null; - this.script = null; - } - - get name() { - return this.operation; - } - - [_xfa_object.$isTransparent]() { - return false; - } - -} - -class Ui extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "ui", true); - this.id = attributes.id || ""; - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.extras = null; - this.picture = null; - this.barcode = null; - this.button = null; - this.checkButton = null; - this.choiceList = null; - this.dateTimeEdit = null; - this.defaultUi = null; - this.imageEdit = null; - this.numericEdit = null; - this.passwordEdit = null; - this.signature = null; - this.textEdit = null; - } - - [_xfa_object.$getExtra]() { - if (this[_xfa_object.$extra] === undefined) { - for (const name of Object.getOwnPropertyNames(this)) { - if (name === "extras" || name === "picture") { - continue; - } - - const obj = this[name]; - - if (!(obj instanceof _xfa_object.XFAObject)) { - continue; - } - - this[_xfa_object.$extra] = obj; - return obj; - } - - this[_xfa_object.$extra] = null; - } - - return this[_xfa_object.$extra]; - } - - [_xfa_object.$toHTML](availableSpace) { - const obj = this[_xfa_object.$getExtra](); - - if (obj) { - return obj[_xfa_object.$toHTML](availableSpace); - } - - return _utils.HTMLResult.EMPTY; - } - -} - -class Validate extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "validate", true); - this.formatTest = (0, _utils.getStringOption)(attributes.formatTest, ["warning", "disabled", "error"]); - this.id = attributes.id || ""; - this.nullTest = (0, _utils.getStringOption)(attributes.nullTest, ["disabled", "error", "warning"]); - this.scriptTest = (0, _utils.getStringOption)(attributes.scriptTest, ["error", "disabled", "warning"]); - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.extras = null; - this.message = null; - this.picture = null; - this.script = null; - } - -} - -class Value extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "value", true); - this.id = attributes.id || ""; - this.override = (0, _utils.getInteger)({ - data: attributes.override, - defaultValue: 0, - validate: x => x === 1 - }); - this.relevant = (0, _utils.getRelevant)(attributes.relevant); - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.arc = null; - this.boolean = null; - this.date = null; - this.dateTime = null; - this.decimal = null; - this.exData = null; - this.float = null; - this.image = null; - this.integer = null; - this.line = null; - this.rectangle = null; - this.text = null; - this.time = null; - } - - [_xfa_object.$setValue](value) { - const parent = this[_xfa_object.$getParent](); - - if (parent instanceof Field) { - if (parent.ui && parent.ui.imageEdit) { - if (!this.image) { - this.image = new Image({}); - - this[_xfa_object.$appendChild](this.image); - } - - this.image[_xfa_object.$content] = value[_xfa_object.$content]; - return; - } - } - - const valueName = value[_xfa_object.$nodeName]; - - if (this[valueName] !== null) { - this[valueName][_xfa_object.$content] = value[_xfa_object.$content]; - return; - } - - for (const name of Object.getOwnPropertyNames(this)) { - const obj = this[name]; - - if (obj instanceof _xfa_object.XFAObject) { - this[name] = null; - - this[_xfa_object.$removeChild](obj); - } - } - - this[value[_xfa_object.$nodeName]] = value; - - this[_xfa_object.$appendChild](value); - } - - [_xfa_object.$text]() { - if (this.exData) { - if (typeof this.exData[_xfa_object.$content] === "string") { - return this.exData[_xfa_object.$content].trim(); - } - - return this.exData[_xfa_object.$content][_xfa_object.$text]().trim(); - } - - for (const name of Object.getOwnPropertyNames(this)) { - if (name === "image") { - continue; - } - - const obj = this[name]; - - if (obj instanceof _xfa_object.XFAObject) { - return (obj[_xfa_object.$content] || "").toString().trim(); - } - } - - return null; - } - - [_xfa_object.$toHTML](availableSpace) { - for (const name of Object.getOwnPropertyNames(this)) { - const obj = this[name]; - - if (!(obj instanceof _xfa_object.XFAObject)) { - continue; - } - - return obj[_xfa_object.$toHTML](availableSpace); - } - - return _utils.HTMLResult.EMPTY; - } - -} - -exports.Value = Value; - -class Variables extends _xfa_object.XFAObject { - constructor(attributes) { - super(TEMPLATE_NS_ID, "variables", true); - this.id = attributes.id || ""; - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - this.boolean = new _xfa_object.XFAObjectArray(); - this.date = new _xfa_object.XFAObjectArray(); - this.dateTime = new _xfa_object.XFAObjectArray(); - this.decimal = new _xfa_object.XFAObjectArray(); - this.exData = new _xfa_object.XFAObjectArray(); - this.float = new _xfa_object.XFAObjectArray(); - this.image = new _xfa_object.XFAObjectArray(); - this.integer = new _xfa_object.XFAObjectArray(); - this.manifest = new _xfa_object.XFAObjectArray(); - this.script = new _xfa_object.XFAObjectArray(); - this.text = new _xfa_object.XFAObjectArray(); - this.time = new _xfa_object.XFAObjectArray(); - } - - [_xfa_object.$isTransparent]() { - return true; - } - -} - -class TemplateNamespace { - static [_namespaces.$buildXFAObject](name, attributes) { - if (TemplateNamespace.hasOwnProperty(name)) { - const node = TemplateNamespace[name](attributes); - - node[_xfa_object.$setSetAttributes](attributes); - - return node; - } - - return undefined; - } - - static appearanceFilter(attrs) { - return new AppearanceFilter(attrs); - } - - static arc(attrs) { - return new Arc(attrs); - } - - static area(attrs) { - return new Area(attrs); - } - - static assist(attrs) { - return new Assist(attrs); - } - - static barcode(attrs) { - return new Barcode(attrs); - } - - static bind(attrs) { - return new Bind(attrs); - } - - static bindItems(attrs) { - return new BindItems(attrs); - } - - static bookend(attrs) { - return new Bookend(attrs); - } - - static boolean(attrs) { - return new BooleanElement(attrs); - } - - static border(attrs) { - return new Border(attrs); - } - - static break(attrs) { - return new Break(attrs); - } - - static breakAfter(attrs) { - return new BreakAfter(attrs); - } - - static breakBefore(attrs) { - return new BreakBefore(attrs); - } - - static button(attrs) { - return new Button(attrs); - } - - static calculate(attrs) { - return new Calculate(attrs); - } - - static caption(attrs) { - return new Caption(attrs); - } - - static certificate(attrs) { - return new Certificate(attrs); - } - - static certificates(attrs) { - return new Certificates(attrs); - } - - static checkButton(attrs) { - return new CheckButton(attrs); - } - - static choiceList(attrs) { - return new ChoiceList(attrs); - } - - static color(attrs) { - return new Color(attrs); - } - - static comb(attrs) { - return new Comb(attrs); - } - - static connect(attrs) { - return new Connect(attrs); - } - - static contentArea(attrs) { - return new ContentArea(attrs); - } - - static corner(attrs) { - return new Corner(attrs); - } - - static date(attrs) { - return new DateElement(attrs); - } - - static dateTime(attrs) { - return new DateTime(attrs); - } - - static dateTimeEdit(attrs) { - return new DateTimeEdit(attrs); - } - - static decimal(attrs) { - return new Decimal(attrs); - } - - static defaultUi(attrs) { - return new DefaultUi(attrs); - } - - static desc(attrs) { - return new Desc(attrs); - } - - static digestMethod(attrs) { - return new DigestMethod(attrs); - } - - static digestMethods(attrs) { - return new DigestMethods(attrs); - } - - static draw(attrs) { - return new Draw(attrs); - } - - static edge(attrs) { - return new Edge(attrs); - } - - static encoding(attrs) { - return new Encoding(attrs); - } - - static encodings(attrs) { - return new Encodings(attrs); - } - - static encrypt(attrs) { - return new Encrypt(attrs); - } - - static encryptData(attrs) { - return new EncryptData(attrs); - } - - static encryption(attrs) { - return new Encryption(attrs); - } - - static encryptionMethod(attrs) { - return new EncryptionMethod(attrs); - } - - static encryptionMethods(attrs) { - return new EncryptionMethods(attrs); - } - - static event(attrs) { - return new Event(attrs); - } - - static exData(attrs) { - return new ExData(attrs); - } - - static exObject(attrs) { - return new ExObject(attrs); - } - - static exclGroup(attrs) { - return new ExclGroup(attrs); - } - - static execute(attrs) { - return new Execute(attrs); - } - - static extras(attrs) { - return new Extras(attrs); - } - - static field(attrs) { - return new Field(attrs); - } - - static fill(attrs) { - return new Fill(attrs); - } - - static filter(attrs) { - return new Filter(attrs); - } - - static float(attrs) { - return new Float(attrs); - } - - static font(attrs) { - return new Font(attrs); - } - - static format(attrs) { - return new Format(attrs); - } - - static handler(attrs) { - return new Handler(attrs); - } - - static hyphenation(attrs) { - return new Hyphenation(attrs); - } - - static image(attrs) { - return new Image(attrs); - } - - static imageEdit(attrs) { - return new ImageEdit(attrs); - } - - static integer(attrs) { - return new Integer(attrs); - } - - static issuers(attrs) { - return new Issuers(attrs); - } - - static items(attrs) { - return new Items(attrs); - } - - static keep(attrs) { - return new Keep(attrs); - } - - static keyUsage(attrs) { - return new KeyUsage(attrs); - } - - static line(attrs) { - return new Line(attrs); - } - - static linear(attrs) { - return new Linear(attrs); - } - - static lockDocument(attrs) { - return new LockDocument(attrs); - } - - static manifest(attrs) { - return new Manifest(attrs); - } - - static margin(attrs) { - return new Margin(attrs); - } - - static mdp(attrs) { - return new Mdp(attrs); - } - - static medium(attrs) { - return new Medium(attrs); - } - - static message(attrs) { - return new Message(attrs); - } - - static numericEdit(attrs) { - return new NumericEdit(attrs); - } - - static occur(attrs) { - return new Occur(attrs); - } - - static oid(attrs) { - return new Oid(attrs); - } - - static oids(attrs) { - return new Oids(attrs); - } - - static overflow(attrs) { - return new Overflow(attrs); - } - - static pageArea(attrs) { - return new PageArea(attrs); - } - - static pageSet(attrs) { - return new PageSet(attrs); - } - - static para(attrs) { - return new Para(attrs); - } - - static passwordEdit(attrs) { - return new PasswordEdit(attrs); - } - - static pattern(attrs) { - return new Pattern(attrs); - } - - static picture(attrs) { - return new Picture(attrs); - } - - static proto(attrs) { - return new Proto(attrs); - } - - static radial(attrs) { - return new Radial(attrs); - } - - static reason(attrs) { - return new Reason(attrs); - } - - static reasons(attrs) { - return new Reasons(attrs); - } - - static rectangle(attrs) { - return new Rectangle(attrs); - } - - static ref(attrs) { - return new RefElement(attrs); - } - - static script(attrs) { - return new Script(attrs); - } - - static setProperty(attrs) { - return new SetProperty(attrs); - } - - static signData(attrs) { - return new SignData(attrs); - } - - static signature(attrs) { - return new Signature(attrs); - } - - static signing(attrs) { - return new Signing(attrs); - } - - static solid(attrs) { - return new Solid(attrs); - } - - static speak(attrs) { - return new Speak(attrs); - } - - static stipple(attrs) { - return new Stipple(attrs); - } - - static subform(attrs) { - return new Subform(attrs); - } - - static subformSet(attrs) { - return new SubformSet(attrs); - } - - static subjectDN(attrs) { - return new SubjectDN(attrs); - } - - static subjectDNs(attrs) { - return new SubjectDNs(attrs); - } - - static submit(attrs) { - return new Submit(attrs); - } - - static template(attrs) { - return new Template(attrs); - } - - static text(attrs) { - return new Text(attrs); - } - - static textEdit(attrs) { - return new TextEdit(attrs); - } - - static time(attrs) { - return new Time(attrs); - } - - static timeStamp(attrs) { - return new TimeStamp(attrs); - } - - static toolTip(attrs) { - return new ToolTip(attrs); - } - - static traversal(attrs) { - return new Traversal(attrs); - } - - static traverse(attrs) { - return new Traverse(attrs); - } - - static ui(attrs) { - return new Ui(attrs); - } - - static validate(attrs) { - return new Validate(attrs); - } - - static value(attrs) { - return new Value(attrs); - } - - static variables(attrs) { - return new Variables(attrs); - } - -} - -exports.TemplateNamespace = TemplateNamespace; - -/***/ }), -/* 81 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.addHTML = addHTML; -exports.checkDimensions = checkDimensions; -exports.flushHTML = flushHTML; -exports.getAvailableSpace = getAvailableSpace; - -var _xfa_object = __w_pdfjs_require__(75); - -var _html_utils = __w_pdfjs_require__(82); - -function createLine(node, children) { - return { - name: "div", - attributes: { - class: [node.layout === "lr-tb" ? "xfaLr" : "xfaRl"] - }, - children - }; -} - -function flushHTML(node) { - if (!node[_xfa_object.$extra]) { - return null; - } - - const attributes = node[_xfa_object.$extra].attributes; - const html = { - name: "div", - attributes, - children: node[_xfa_object.$extra].children - }; - - if (node[_xfa_object.$extra].failingNode) { - const htmlFromFailing = node[_xfa_object.$extra].failingNode[_xfa_object.$flushHTML](); - - if (htmlFromFailing) { - if (node.layout.endsWith("-tb")) { - html.children.push(createLine(node, [htmlFromFailing])); - } else { - html.children.push(htmlFromFailing); - } - } - } - - if (html.children.length === 0) { - return null; - } - - return html; -} - -function addHTML(node, html, bbox) { - const extra = node[_xfa_object.$extra]; - const availableSpace = extra.availableSpace; - const [x, y, w, h] = bbox; - - switch (node.layout) { - case "position": - { - extra.width = Math.max(extra.width, x + w); - extra.height = Math.max(extra.height, y + h); - extra.children.push(html); - break; - } - - case "lr-tb": - case "rl-tb": - if (!extra.line || extra.attempt === 1) { - extra.line = createLine(node, []); - extra.children.push(extra.line); - extra.numberInLine = 0; - } - - extra.numberInLine += 1; - extra.line.children.push(html); - - if (extra.attempt === 0) { - extra.currentWidth += w; - extra.height = Math.max(extra.height, extra.prevHeight + h); - } else { - extra.currentWidth = w; - extra.prevHeight = extra.height; - extra.height += h; - extra.attempt = 0; - } - - extra.width = Math.max(extra.width, extra.currentWidth); - break; - - case "rl-row": - case "row": - { - extra.children.push(html); - extra.width += w; - extra.height = Math.max(extra.height, h); - const height = (0, _html_utils.measureToString)(extra.height); - - for (const child of extra.children) { - child.attributes.style.height = height; - } - - break; - } - - case "table": - { - extra.width = Math.min(availableSpace.width, Math.max(extra.width, w)); - extra.height += h; - extra.children.push(html); - break; - } - - case "tb": - { - extra.width = Math.min(availableSpace.width, Math.max(extra.width, w)); - extra.height += h; - extra.children.push(html); - break; - } - } -} - -function getAvailableSpace(node) { - const availableSpace = node[_xfa_object.$extra].availableSpace; - const marginV = node.margin ? node.margin.topInset + node.margin.bottomInset : 0; - const marginH = node.margin ? node.margin.leftInset + node.margin.rightInset : 0; - - switch (node.layout) { - case "lr-tb": - case "rl-tb": - if (node[_xfa_object.$extra].attempt === 0) { - return { - width: availableSpace.width - marginH - node[_xfa_object.$extra].currentWidth, - height: availableSpace.height - marginV - node[_xfa_object.$extra].prevHeight - }; - } - - return { - width: availableSpace.width - marginH, - height: availableSpace.height - marginV - node[_xfa_object.$extra].height - }; - - case "rl-row": - case "row": - const width = node[_xfa_object.$extra].columnWidths.slice(node[_xfa_object.$extra].currentColumn).reduce((a, x) => a + x); - - return { - width, - height: availableSpace.height - marginH - }; - - case "table": - case "tb": - return { - width: availableSpace.width - marginH, - height: availableSpace.height - marginV - node[_xfa_object.$extra].height - }; - - case "position": - default: - return availableSpace; - } -} - -function getTransformedBBox(node) { - let w = node.w === "" ? NaN : node.w; - let h = node.h === "" ? NaN : node.h; - let [centerX, centerY] = [0, 0]; - - switch (node.anchorType || "") { - case "bottomCenter": - [centerX, centerY] = [w / 2, h]; - break; - - case "bottomLeft": - [centerX, centerY] = [0, h]; - break; - - case "bottomRight": - [centerX, centerY] = [w, h]; - break; - - case "middleCenter": - [centerX, centerY] = [w / 2, h / 2]; - break; - - case "middleLeft": - [centerX, centerY] = [0, h / 2]; - break; - - case "middleRight": - [centerX, centerY] = [w, h / 2]; - break; - - case "topCenter": - [centerX, centerY] = [w / 2, 0]; - break; - - case "topRight": - [centerX, centerY] = [w, 0]; - break; - } - - let x, y; - - switch (node.rotate || 0) { - case 0: - [x, y] = [-centerX, -centerY]; - break; - - case 90: - [x, y] = [-centerY, centerX]; - [w, h] = [h, -w]; - break; - - case 180: - [x, y] = [centerX, centerY]; - [w, h] = [-w, -h]; - break; - - case 270: - [x, y] = [centerY, -centerX]; - [w, h] = [-h, w]; - break; - } - - return [node.x + x + Math.min(0, w), node.y + y + Math.min(0, h), Math.abs(w), Math.abs(h)]; -} - -function checkDimensions(node, space) { - if (node[_xfa_object.$getTemplateRoot]()[_xfa_object.$extra].firstUnsplittable === null) { - return true; - } - - if (node.w === 0 || node.h === 0) { - return true; - } - - const ERROR = 2; - - const parent = node[_xfa_object.$getSubformParent](); - - const attempt = parent[_xfa_object.$extra] && parent[_xfa_object.$extra].attempt || 0; - const [, y, w, h] = getTransformedBBox(node); - - switch (parent.layout) { - case "lr-tb": - case "rl-tb": - if (attempt === 0) { - if (!node[_xfa_object.$getTemplateRoot]()[_xfa_object.$extra].noLayoutFailure) { - if (node.h !== "" && Math.round(h - space.height) > ERROR) { - return false; - } - - if (node.w !== "") { - if (Math.round(w - space.width) <= ERROR) { - return true; - } - - if (parent[_xfa_object.$extra].numberInLine === 0) { - return space.height > ERROR; - } - - return false; - } - - return space.width > ERROR; - } - - if (node.w !== "") { - return Math.round(w - space.width) <= ERROR; - } - - return space.width > ERROR; - } - - if (node[_xfa_object.$getTemplateRoot]()[_xfa_object.$extra].noLayoutFailure) { - return true; - } - - if (node.h !== "" && Math.round(h - space.height) > ERROR) { - return false; - } - - if (node.w === "" || Math.round(w - space.width) <= ERROR) { - return space.height > ERROR; - } - - if (parent[_xfa_object.$isThereMoreWidth]()) { - return false; - } - - return space.height > ERROR; - - case "table": - case "tb": - if (node[_xfa_object.$getTemplateRoot]()[_xfa_object.$extra].noLayoutFailure) { - return true; - } - - if (node.h !== "" && !node[_xfa_object.$isSplittable]()) { - return Math.round(h - space.height) <= ERROR; - } - - if (node.w === "" || Math.round(w - space.width) <= ERROR) { - return space.height > ERROR; - } - - if (parent[_xfa_object.$isThereMoreWidth]()) { - return false; - } - - return space.height > ERROR; - - case "position": - if (node[_xfa_object.$getTemplateRoot]()[_xfa_object.$extra].noLayoutFailure) { - return true; - } - - if (node.h === "" || Math.round(h + y - space.height) <= ERROR) { - return true; - } - - const area = node[_xfa_object.$getTemplateRoot]()[_xfa_object.$extra].currentContentArea; - - return h + y > area.h; - - case "rl-row": - case "row": - if (node[_xfa_object.$getTemplateRoot]()[_xfa_object.$extra].noLayoutFailure) { - return true; - } - - if (node.h !== "") { - return Math.round(h - space.height) <= ERROR; - } - - return true; - - default: - return true; - } -} - -/***/ }), -/* 82 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.computeBbox = computeBbox; -exports.createWrapper = createWrapper; -exports.fixDimensions = fixDimensions; -exports.fixTextIndent = fixTextIndent; -exports.fixURL = fixURL; -exports.isPrintOnly = isPrintOnly; -exports.layoutClass = layoutClass; -exports.layoutNode = layoutNode; -exports.measureToString = measureToString; -exports.setAccess = setAccess; -exports.setFontFamily = setFontFamily; -exports.setMinMaxDimensions = setMinMaxDimensions; -exports.setPara = setPara; -exports.toStyle = toStyle; - -var _xfa_object = __w_pdfjs_require__(75); - -var _util = __w_pdfjs_require__(2); - -var _utils = __w_pdfjs_require__(76); - -var _fonts = __w_pdfjs_require__(83); - -var _text = __w_pdfjs_require__(84); - -function measureToString(m) { - if (typeof m === "string") { - return "0px"; - } - - return Number.isInteger(m) ? `${m}px` : `${m.toFixed(2)}px`; -} - -const converters = { - anchorType(node, style) { - const parent = node[_xfa_object.$getSubformParent](); - - if (!parent || parent.layout && parent.layout !== "position") { - return; - } - - if (!("transform" in style)) { - style.transform = ""; - } - - switch (node.anchorType) { - case "bottomCenter": - style.transform += "translate(-50%, -100%)"; - break; - - case "bottomLeft": - style.transform += "translate(0,-100%)"; - break; - - case "bottomRight": - style.transform += "translate(-100%,-100%)"; - break; - - case "middleCenter": - style.transform += "translate(-50%,-50%)"; - break; - - case "middleLeft": - style.transform += "translate(0,-50%)"; - break; - - case "middleRight": - style.transform += "translate(-100%,-50%)"; - break; - - case "topCenter": - style.transform += "translate(-50%,0)"; - break; - - case "topRight": - style.transform += "translate(-100%,0)"; - break; - } - }, - - dimensions(node, style) { - const parent = node[_xfa_object.$getSubformParent](); - - let width = node.w; - const height = node.h; - - if (parent.layout && parent.layout.includes("row")) { - const extra = parent[_xfa_object.$extra]; - const colSpan = node.colSpan; - let w; - - if (colSpan === -1) { - w = extra.columnWidths.slice(extra.currentColumn).reduce((a, x) => a + x, 0); - extra.currentColumn = 0; - } else { - w = extra.columnWidths.slice(extra.currentColumn, extra.currentColumn + colSpan).reduce((a, x) => a + x, 0); - extra.currentColumn = (extra.currentColumn + node.colSpan) % extra.columnWidths.length; - } - - if (!isNaN(w)) { - width = node.w = w; - } - } - - if (width !== "") { - style.width = measureToString(width); - } else { - style.width = "auto"; - } - - if (height !== "") { - style.height = measureToString(height); - } else { - style.height = "auto"; - } - }, - - position(node, style) { - const parent = node[_xfa_object.$getSubformParent](); - - if (parent && parent.layout && parent.layout !== "position") { - return; - } - - style.position = "absolute"; - style.left = measureToString(node.x); - style.top = measureToString(node.y); - }, - - rotate(node, style) { - if (node.rotate) { - if (!("transform" in style)) { - style.transform = ""; - } - - style.transform += `rotate(-${node.rotate}deg)`; - style.transformOrigin = "top left"; - } - }, - - presence(node, style) { - switch (node.presence) { - case "invisible": - style.visibility = "hidden"; - break; - - case "hidden": - case "inactive": - style.display = "none"; - break; - } - }, - - hAlign(node, style) { - if (node[_xfa_object.$nodeName] === "para") { - switch (node.hAlign) { - case "justifyAll": - style.textAlign = "justify-all"; - break; - - case "radix": - style.textAlign = "left"; - break; - - default: - style.textAlign = node.hAlign; - } - } else { - switch (node.hAlign) { - case "left": - style.alignSelf = "start"; - break; - - case "center": - style.alignSelf = "center"; - break; - - case "right": - style.alignSelf = "end"; - break; - } - } - }, - - margin(node, style) { - if (node.margin) { - style.margin = node.margin[_xfa_object.$toStyle]().margin; - } - } - -}; - -function setMinMaxDimensions(node, style) { - const parent = node[_xfa_object.$getSubformParent](); - - if (parent.layout === "position") { - if (node.minW > 0) { - style.minWidth = measureToString(node.minW); - } - - if (node.maxW > 0) { - style.maxWidth = measureToString(node.maxW); - } - - if (node.minH > 0) { - style.minHeight = measureToString(node.minH); - } - - if (node.maxH > 0) { - style.maxHeight = measureToString(node.maxH); - } - } -} - -function layoutText(text, xfaFont, margin, lineHeight, fontFinder, width) { - const measure = new _text.TextMeasure(xfaFont, margin, lineHeight, fontFinder); - - if (typeof text === "string") { - measure.addString(text); - } else { - text[_xfa_object.$pushGlyphs](measure); - } - - return measure.compute(width); -} - -function layoutNode(node, availableSpace) { - let height = null; - let width = null; - let isBroken = false; - - if ((!node.w || !node.h) && node.value) { - let marginH = 0; - let marginV = 0; - - if (node.margin) { - marginH = node.margin.leftInset + node.margin.rightInset; - marginV = node.margin.topInset + node.margin.bottomInset; - } - - let lineHeight = null; - let margin = null; - - if (node.para) { - margin = Object.create(null); - lineHeight = node.para.lineHeight === "" ? null : node.para.lineHeight; - margin.top = node.para.spaceAbove === "" ? 0 : node.para.spaceAbove; - margin.bottom = node.para.spaceBelow === "" ? 0 : node.para.spaceBelow; - margin.left = node.para.marginLeft === "" ? 0 : node.para.marginLeft; - margin.right = node.para.marginRight === "" ? 0 : node.para.marginRight; - } - - let font = node.font; - - if (!font) { - const root = node[_xfa_object.$getTemplateRoot](); - - let parent = node[_xfa_object.$getParent](); - - while (parent && parent !== root) { - if (parent.font) { - font = parent.font; - break; - } - - parent = parent[_xfa_object.$getParent](); - } - } - - const maxWidth = (!node.w ? availableSpace.width : node.w) - marginH; - const fontFinder = node[_xfa_object.$globalData].fontFinder; - - if (node.value.exData && node.value.exData[_xfa_object.$content] && node.value.exData.contentType === "text/html") { - const res = layoutText(node.value.exData[_xfa_object.$content], font, margin, lineHeight, fontFinder, maxWidth); - width = res.width; - height = res.height; - isBroken = res.isBroken; - } else { - const text = node.value[_xfa_object.$text](); - - if (text) { - const res = layoutText(text, font, margin, lineHeight, fontFinder, maxWidth); - width = res.width; - height = res.height; - isBroken = res.isBroken; - } - } - - if (width !== null && !node.w) { - width += marginH; - } - - if (height !== null && !node.h) { - height += marginV; - } - } - - return { - w: width, - h: height, - isBroken - }; -} - -function computeBbox(node, html, availableSpace) { - let bbox; - - if (node.w !== "" && node.h !== "") { - bbox = [node.x, node.y, node.w, node.h]; - } else { - if (!availableSpace) { - return null; - } - - let width = node.w; - - if (width === "") { - if (node.maxW === 0) { - const parent = node[_xfa_object.$getSubformParent](); - - if (parent.layout === "position" && parent.w !== "") { - width = 0; - } else { - width = node.minW; - } - } else { - width = Math.min(node.maxW, availableSpace.width); - } - - html.attributes.style.width = measureToString(width); - } - - let height = node.h; - - if (height === "") { - if (node.maxH === 0) { - const parent = node[_xfa_object.$getSubformParent](); - - if (parent.layout === "position" && parent.h !== "") { - height = 0; - } else { - height = node.minH; - } - } else { - height = Math.min(node.maxH, availableSpace.height); - } - - html.attributes.style.height = measureToString(height); - } - - bbox = [node.x, node.y, width, height]; - } - - return bbox; -} - -function fixDimensions(node) { - const parent = node[_xfa_object.$getSubformParent](); - - if (parent.layout && parent.layout.includes("row")) { - const extra = parent[_xfa_object.$extra]; - const colSpan = node.colSpan; - let width; - - if (colSpan === -1) { - width = extra.columnWidths.slice(extra.currentColumn).reduce((a, w) => a + w, 0); - } else { - width = extra.columnWidths.slice(extra.currentColumn, extra.currentColumn + colSpan).reduce((a, w) => a + w, 0); - } - - if (!isNaN(width)) { - node.w = width; - } - } - - if (parent.layout && parent.layout !== "position") { - node.x = node.y = 0; - } - - if (node.layout === "table") { - if (node.w === "" && Array.isArray(node.columnWidths)) { - node.w = node.columnWidths.reduce((a, x) => a + x, 0); - } - } -} - -function layoutClass(node) { - switch (node.layout) { - case "position": - return "xfaPosition"; - - case "lr-tb": - return "xfaLrTb"; - - case "rl-row": - return "xfaRlRow"; - - case "rl-tb": - return "xfaRlTb"; - - case "row": - return "xfaRow"; - - case "table": - return "xfaTable"; - - case "tb": - return "xfaTb"; - - default: - return "xfaPosition"; - } -} - -function toStyle(node, ...names) { - const style = Object.create(null); - - for (const name of names) { - const value = node[name]; - - if (value === null) { - continue; - } - - if (converters.hasOwnProperty(name)) { - converters[name](node, style); - continue; - } - - if (value instanceof _xfa_object.XFAObject) { - const newStyle = value[_xfa_object.$toStyle](); - - if (newStyle) { - Object.assign(style, newStyle); - } else { - (0, _util.warn)(`(DEBUG) - XFA - style for ${name} not implemented yet`); - } - } - } - - return style; -} - -function createWrapper(node, html) { - const { - attributes - } = html; - const { - style - } = attributes; - const wrapper = { - name: "div", - attributes: { - class: ["xfaWrapper"], - style: Object.create(null) - }, - children: [] - }; - attributes.class.push("xfaWrapped"); - - if (node.border) { - const { - widths, - insets - } = node.border[_xfa_object.$extra]; - let width, height; - let top = insets[0]; - let left = insets[3]; - const insetsH = insets[0] + insets[2]; - const insetsW = insets[1] + insets[3]; - - switch (node.border.hand) { - case "even": - top -= widths[0] / 2; - left -= widths[3] / 2; - width = `calc(100% + ${(widths[1] + widths[3]) / 2 - insetsW}px)`; - height = `calc(100% + ${(widths[0] + widths[2]) / 2 - insetsH}px)`; - break; - - case "left": - top -= widths[0]; - left -= widths[3]; - width = `calc(100% + ${widths[1] + widths[3] - insetsW}px)`; - height = `calc(100% + ${widths[0] + widths[2] - insetsH}px)`; - break; - - case "right": - width = insetsW ? `calc(100% - ${insetsW}px)` : "100%"; - height = insetsH ? `calc(100% - ${insetsH}px)` : "100%"; - break; - } - - const classNames = ["xfaBorder"]; - - if (isPrintOnly(node.border)) { - classNames.push("xfaPrintOnly"); - } - - const border = { - name: "div", - attributes: { - class: classNames, - style: { - top: `${top}px`, - left: `${left}px`, - width, - height - } - }, - children: [] - }; - - for (const key of ["border", "borderWidth", "borderColor", "borderRadius", "borderStyle"]) { - if (style[key] !== undefined) { - border.attributes.style[key] = style[key]; - delete style[key]; - } - } - - wrapper.children.push(border, html); - } else { - wrapper.children.push(html); - } - - for (const key of ["background", "backgroundClip", "top", "left", "width", "height", "minWidth", "minHeight", "maxWidth", "maxHeight", "transform", "transformOrigin", "visibility"]) { - if (style[key] !== undefined) { - wrapper.attributes.style[key] = style[key]; - delete style[key]; - } - } - - if (style.position === "absolute") { - wrapper.attributes.style.position = "absolute"; - } else { - wrapper.attributes.style.position = "relative"; - } - - delete style.position; - - if (style.alignSelf) { - wrapper.attributes.style.alignSelf = style.alignSelf; - delete style.alignSelf; - } - - return wrapper; -} - -function fixTextIndent(styles) { - const indent = (0, _utils.getMeasurement)(styles.textIndent, "0px"); - - if (indent >= 0) { - return; - } - - const align = styles.textAlign === "right" ? "right" : "left"; - const name = "padding" + (align === "left" ? "Left" : "Right"); - const padding = (0, _utils.getMeasurement)(styles[name], "0px"); - styles[name] = `${padding - indent}px`; -} - -function setAccess(node, classNames) { - switch (node.access) { - case "nonInteractive": - classNames.push("xfaNonInteractive"); - break; - - case "readOnly": - classNames.push("xfaReadOnly"); - break; - - case "protected": - classNames.push("xfaDisabled"); - break; - } -} - -function isPrintOnly(node) { - return node.relevant.length > 0 && !node.relevant[0].excluded && node.relevant[0].viewname === "print"; -} - -function getCurrentPara(node) { - const stack = node[_xfa_object.$getTemplateRoot]()[_xfa_object.$extra].paraStack; - - return stack.length ? stack[stack.length - 1] : null; -} - -function setPara(node, nodeStyle, value) { - if (value.attributes.class && value.attributes.class.includes("xfaRich")) { - if (nodeStyle) { - if (node.h === "") { - nodeStyle.height = "auto"; - } - - if (node.w === "") { - nodeStyle.width = "auto"; - } - } - - const para = getCurrentPara(node); - - if (para) { - const valueStyle = value.attributes.style; - valueStyle.display = "flex"; - valueStyle.flexDirection = "column"; - - switch (para.vAlign) { - case "top": - valueStyle.justifyContent = "start"; - break; - - case "bottom": - valueStyle.justifyContent = "end"; - break; - - case "middle": - valueStyle.justifyContent = "center"; - break; - } - - const paraStyle = para[_xfa_object.$toStyle](); - - for (const [key, val] of Object.entries(paraStyle)) { - if (!(key in valueStyle)) { - valueStyle[key] = val; - } - } - } - } -} - -function setFontFamily(xfaFont, node, fontFinder, style) { - if (!fontFinder) { - delete style.fontFamily; - return; - } - - const name = (0, _utils.stripQuotes)(xfaFont.typeface); - style.fontFamily = `"${name}"`; - const typeface = fontFinder.find(name); - - if (typeface) { - const { - fontFamily - } = typeface.regular.cssFontInfo; - - if (fontFamily !== name) { - style.fontFamily = `"${fontFamily}"`; - } - - const para = getCurrentPara(node); - - if (para && para.lineHeight !== "") { - return; - } - - if (style.lineHeight) { - return; - } - - const pdfFont = (0, _fonts.selectFont)(xfaFont, typeface); - - if (pdfFont) { - style.lineHeight = Math.max(1.2, pdfFont.lineHeight); - } - } -} - -function fixURL(str) { - const absoluteUrl = (0, _util.createValidAbsoluteUrl)(str, null, { - addDefaultProtocol: true, - tryConvertEncoding: true - }); - return absoluteUrl ? absoluteUrl.href : null; -} - -/***/ }), -/* 83 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.FontFinder = void 0; -exports.getMetrics = getMetrics; -exports.selectFont = selectFont; - -var _xfa_object = __w_pdfjs_require__(75); - -var _utils = __w_pdfjs_require__(76); - -var _util = __w_pdfjs_require__(2); - -class FontFinder { - constructor(pdfFonts) { - this.fonts = new Map(); - this.cache = new Map(); - this.warned = new Set(); - this.defaultFont = null; - this.add(pdfFonts); - } - - add(pdfFonts, reallyMissingFonts = null) { - for (const pdfFont of pdfFonts) { - this.addPdfFont(pdfFont); - } - - for (const pdfFont of this.fonts.values()) { - if (!pdfFont.regular) { - pdfFont.regular = pdfFont.italic || pdfFont.bold || pdfFont.bolditalic; - } - } - - if (!reallyMissingFonts || reallyMissingFonts.size === 0) { - return; - } - - const myriad = this.fonts.get("PdfJS-Fallback-PdfJS-XFA"); - - for (const missing of reallyMissingFonts) { - this.fonts.set(missing, myriad); - } - } - - addPdfFont(pdfFont) { - const cssFontInfo = pdfFont.cssFontInfo; - const name = cssFontInfo.fontFamily; - let font = this.fonts.get(name); - - if (!font) { - font = Object.create(null); - this.fonts.set(name, font); - - if (!this.defaultFont) { - this.defaultFont = font; - } - } - - let property = ""; - const fontWeight = parseFloat(cssFontInfo.fontWeight); - - if (parseFloat(cssFontInfo.italicAngle) !== 0) { - property = fontWeight >= 700 ? "bolditalic" : "italic"; - } else if (fontWeight >= 700) { - property = "bold"; - } - - if (!property) { - if (pdfFont.name.includes("Bold") || pdfFont.psName && pdfFont.psName.includes("Bold")) { - property = "bold"; - } - - if (pdfFont.name.includes("Italic") || pdfFont.name.endsWith("It") || pdfFont.psName && (pdfFont.psName.includes("Italic") || pdfFont.psName.endsWith("It"))) { - property += "italic"; - } - } - - if (!property) { - property = "regular"; - } - - font[property] = pdfFont; - } - - getDefault() { - return this.defaultFont; - } - - find(fontName, mustWarn = true) { - let font = this.fonts.get(fontName) || this.cache.get(fontName); - - if (font) { - return font; - } - - const pattern = /,|-|_| |bolditalic|bold|italic|regular|it/gi; - let name = fontName.replace(pattern, ""); - font = this.fonts.get(name); - - if (font) { - this.cache.set(fontName, font); - return font; - } - - name = name.toLowerCase(); - const maybe = []; - - for (const [family, pdfFont] of this.fonts.entries()) { - if (family.replace(pattern, "").toLowerCase().startsWith(name)) { - maybe.push(pdfFont); - } - } - - if (maybe.length === 0) { - for (const [, pdfFont] of this.fonts.entries()) { - if (pdfFont.regular.name && pdfFont.regular.name.replace(pattern, "").toLowerCase().startsWith(name)) { - maybe.push(pdfFont); - } - } - } - - if (maybe.length === 0) { - name = name.replace(/psmt|mt/gi, ""); - - for (const [family, pdfFont] of this.fonts.entries()) { - if (family.replace(pattern, "").toLowerCase().startsWith(name)) { - maybe.push(pdfFont); - } - } - } - - if (maybe.length === 0) { - for (const pdfFont of this.fonts.values()) { - if (pdfFont.regular.name && pdfFont.regular.name.replace(pattern, "").toLowerCase().startsWith(name)) { - maybe.push(pdfFont); - } - } - } - - if (maybe.length >= 1) { - if (maybe.length !== 1 && mustWarn) { - (0, _util.warn)(`XFA - Too many choices to guess the correct font: ${fontName}`); - } - - this.cache.set(fontName, maybe[0]); - return maybe[0]; - } - - if (mustWarn && !this.warned.has(fontName)) { - this.warned.add(fontName); - (0, _util.warn)(`XFA - Cannot find the font: ${fontName}`); - } - - return null; - } - -} - -exports.FontFinder = FontFinder; - -function selectFont(xfaFont, typeface) { - if (xfaFont.posture === "italic") { - if (xfaFont.weight === "bold") { - return typeface.bolditalic; - } - - return typeface.italic; - } else if (xfaFont.weight === "bold") { - return typeface.bold; - } - - return typeface.regular; -} - -function getMetrics(xfaFont, real = false) { - let pdfFont = null; - - if (xfaFont) { - const name = (0, _utils.stripQuotes)(xfaFont.typeface); - - const typeface = xfaFont[_xfa_object.$globalData].fontFinder.find(name); - - pdfFont = selectFont(xfaFont, typeface); - } - - if (!pdfFont) { - return { - lineHeight: 12, - lineGap: 2, - lineNoGap: 10 - }; - } - - const size = xfaFont.size || 10; - const lineHeight = pdfFont.lineHeight ? Math.max(real ? 0 : 1.2, pdfFont.lineHeight) : 1.2; - const lineGap = pdfFont.lineGap === undefined ? 0.2 : pdfFont.lineGap; - return { - lineHeight: lineHeight * size, - lineGap: lineGap * size, - lineNoGap: Math.max(1, lineHeight - lineGap) * size - }; -} - -/***/ }), -/* 84 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.TextMeasure = void 0; - -var _fonts = __w_pdfjs_require__(83); - -const WIDTH_FACTOR = 1.02; - -class FontInfo { - constructor(xfaFont, margin, lineHeight, fontFinder) { - this.lineHeight = lineHeight; - this.paraMargin = margin || { - top: 0, - bottom: 0, - left: 0, - right: 0 - }; - - if (!xfaFont) { - [this.pdfFont, this.xfaFont] = this.defaultFont(fontFinder); - return; - } - - this.xfaFont = { - typeface: xfaFont.typeface, - posture: xfaFont.posture, - weight: xfaFont.weight, - size: xfaFont.size, - letterSpacing: xfaFont.letterSpacing - }; - const typeface = fontFinder.find(xfaFont.typeface); - - if (!typeface) { - [this.pdfFont, this.xfaFont] = this.defaultFont(fontFinder); - return; - } - - this.pdfFont = (0, _fonts.selectFont)(xfaFont, typeface); - - if (!this.pdfFont) { - [this.pdfFont, this.xfaFont] = this.defaultFont(fontFinder); - } - } - - defaultFont(fontFinder) { - const font = fontFinder.find("Helvetica", false) || fontFinder.find("Myriad Pro", false) || fontFinder.find("Arial", false) || fontFinder.getDefault(); - - if (font && font.regular) { - const pdfFont = font.regular; - const info = pdfFont.cssFontInfo; - const xfaFont = { - typeface: info.fontFamily, - posture: "normal", - weight: "normal", - size: 10, - letterSpacing: 0 - }; - return [pdfFont, xfaFont]; - } - - const xfaFont = { - typeface: "Courier", - posture: "normal", - weight: "normal", - size: 10, - letterSpacing: 0 - }; - return [null, xfaFont]; - } - -} - -class FontSelector { - constructor(defaultXfaFont, defaultParaMargin, defaultLineHeight, fontFinder) { - this.fontFinder = fontFinder; - this.stack = [new FontInfo(defaultXfaFont, defaultParaMargin, defaultLineHeight, fontFinder)]; - } - - pushData(xfaFont, margin, lineHeight) { - const lastFont = this.stack[this.stack.length - 1]; - - for (const name of ["typeface", "posture", "weight", "size", "letterSpacing"]) { - if (!xfaFont[name]) { - xfaFont[name] = lastFont.xfaFont[name]; - } - } - - for (const name of ["top", "bottom", "left", "right"]) { - if (isNaN(margin[name])) { - margin[name] = lastFont.paraMargin[name]; - } - } - - const fontInfo = new FontInfo(xfaFont, margin, lineHeight || lastFont.lineHeight, this.fontFinder); - - if (!fontInfo.pdfFont) { - fontInfo.pdfFont = lastFont.pdfFont; - } - - this.stack.push(fontInfo); - } - - popFont() { - this.stack.pop(); - } - - topFont() { - return this.stack[this.stack.length - 1]; - } - -} - -class TextMeasure { - constructor(defaultXfaFont, defaultParaMargin, defaultLineHeight, fonts) { - this.glyphs = []; - this.fontSelector = new FontSelector(defaultXfaFont, defaultParaMargin, defaultLineHeight, fonts); - this.extraHeight = 0; - } - - pushData(xfaFont, margin, lineHeight) { - this.fontSelector.pushData(xfaFont, margin, lineHeight); - } - - popFont(xfaFont) { - return this.fontSelector.popFont(); - } - - addPara() { - const lastFont = this.fontSelector.topFont(); - this.extraHeight += lastFont.paraMargin.top + lastFont.paraMargin.bottom; - } - - addString(str) { - if (!str) { - return; - } - - const lastFont = this.fontSelector.topFont(); - const fontSize = lastFont.xfaFont.size; - - if (lastFont.pdfFont) { - const letterSpacing = lastFont.xfaFont.letterSpacing; - const pdfFont = lastFont.pdfFont; - const fontLineHeight = pdfFont.lineHeight || 1.2; - const lineHeight = lastFont.lineHeight || Math.max(1.2, fontLineHeight) * fontSize; - const lineGap = pdfFont.lineGap === undefined ? 0.2 : pdfFont.lineGap; - const noGap = fontLineHeight - lineGap; - const firstLineHeight = Math.max(1, noGap) * fontSize; - const scale = fontSize / 1000; - const fallbackWidth = pdfFont.defaultWidth || pdfFont.charsToGlyphs(" ")[0].width; - - for (const line of str.split(/[\u2029\n]/)) { - const encodedLine = pdfFont.encodeString(line).join(""); - const glyphs = pdfFont.charsToGlyphs(encodedLine); - - for (const glyph of glyphs) { - const width = glyph.width || fallbackWidth; - this.glyphs.push([width * scale + letterSpacing, lineHeight, firstLineHeight, glyph.unicode, false]); - } - - this.glyphs.push([0, 0, 0, "\n", true]); - } - - this.glyphs.pop(); - return; - } - - for (const line of str.split(/[\u2029\n]/)) { - for (const char of line.split("")) { - this.glyphs.push([fontSize, 1.2 * fontSize, fontSize, char, false]); - } - - this.glyphs.push([0, 0, 0, "\n", true]); - } - - this.glyphs.pop(); - } - - compute(maxWidth) { - let lastSpacePos = -1, - lastSpaceWidth = 0, - width = 0, - height = 0, - currentLineWidth = 0, - currentLineHeight = 0; - let isBroken = false; - let isFirstLine = true; - - for (let i = 0, ii = this.glyphs.length; i < ii; i++) { - const [glyphWidth, lineHeight, firstLineHeight, char, isEOL] = this.glyphs[i]; - const isSpace = char === " "; - const glyphHeight = isFirstLine ? firstLineHeight : lineHeight; - - if (isEOL) { - width = Math.max(width, currentLineWidth); - currentLineWidth = 0; - height += currentLineHeight; - currentLineHeight = glyphHeight; - lastSpacePos = -1; - lastSpaceWidth = 0; - isFirstLine = false; - continue; - } - - if (isSpace) { - if (currentLineWidth + glyphWidth > maxWidth) { - width = Math.max(width, currentLineWidth); - currentLineWidth = 0; - height += currentLineHeight; - currentLineHeight = glyphHeight; - lastSpacePos = -1; - lastSpaceWidth = 0; - isBroken = true; - isFirstLine = false; - } else { - currentLineHeight = Math.max(glyphHeight, currentLineHeight); - lastSpaceWidth = currentLineWidth; - currentLineWidth += glyphWidth; - lastSpacePos = i; - } - - continue; - } - - if (currentLineWidth + glyphWidth > maxWidth) { - height += currentLineHeight; - currentLineHeight = glyphHeight; - - if (lastSpacePos !== -1) { - i = lastSpacePos; - width = Math.max(width, lastSpaceWidth); - currentLineWidth = 0; - lastSpacePos = -1; - lastSpaceWidth = 0; - } else { - width = Math.max(width, currentLineWidth); - currentLineWidth = glyphWidth; - } - - isBroken = true; - isFirstLine = false; - continue; - } - - currentLineWidth += glyphWidth; - currentLineHeight = Math.max(glyphHeight, currentLineHeight); - } - - width = Math.max(width, currentLineWidth); - height += currentLineHeight + this.extraHeight; - return { - width: WIDTH_FACTOR * width, - height, - isBroken - }; - } - -} - -exports.TextMeasure = TextMeasure; - -/***/ }), -/* 85 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.DataHandler = void 0; - -var _xfa_object = __w_pdfjs_require__(75); - -class DataHandler { - constructor(root, data) { - this.data = data; - this.dataset = root.datasets || null; - } - - serialize(storage) { - const stack = [[-1, this.data[_xfa_object.$getChildren]()]]; - - while (stack.length > 0) { - const last = stack[stack.length - 1]; - const [i, children] = last; - - if (i + 1 === children.length) { - stack.pop(); - continue; - } - - const child = children[++last[0]]; - const storageEntry = storage.get(child[_xfa_object.$uid]); - - if (storageEntry) { - child[_xfa_object.$setValue](storageEntry); - } else { - const attributes = child[_xfa_object.$getAttributes](); - - for (const value of attributes.values()) { - const entry = storage.get(value[_xfa_object.$uid]); - - if (entry) { - value[_xfa_object.$setValue](entry); - - break; - } - } - } - - const nodes = child[_xfa_object.$getChildren](); - - if (nodes.length > 0) { - stack.push([-1, nodes]); - } - } - - const buf = [``]; - - if (this.dataset) { - for (const child of this.dataset[_xfa_object.$getChildren]()) { - if (child[_xfa_object.$nodeName] !== "data") { - child[_xfa_object.$toString](buf); - } - } - } - - this.data[_xfa_object.$toString](buf); - - buf.push(""); - return buf.join(""); - } - -} - -exports.DataHandler = DataHandler; - -/***/ }), -/* 86 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.XFAParser = void 0; - -var _xfa_object = __w_pdfjs_require__(75); - -var _xml_parser = __w_pdfjs_require__(68); - -var _builder = __w_pdfjs_require__(87); - -var _util = __w_pdfjs_require__(2); - -class XFAParser extends _xml_parser.XMLParserBase { - constructor(rootNameSpace = null, richText = false) { - super(); - this._builder = new _builder.Builder(rootNameSpace); - this._stack = []; - this._globalData = { - usedTypefaces: new Set() - }; - this._ids = new Map(); - this._current = this._builder.buildRoot(this._ids); - this._errorCode = _xml_parser.XMLParserErrorCode.NoError; - this._whiteRegex = /^\s+$/; - this._nbsps = /\xa0+/g; - this._richText = richText; - } - - parse(data) { - this.parseXml(data); - - if (this._errorCode !== _xml_parser.XMLParserErrorCode.NoError) { - return undefined; - } - - this._current[_xfa_object.$finalize](); - - return this._current.element; - } - - onText(text) { - text = text.replace(this._nbsps, match => match.slice(1) + " "); - - if (this._richText || this._current[_xfa_object.$acceptWhitespace]()) { - this._current[_xfa_object.$onText](text, this._richText); - - return; - } - - if (this._whiteRegex.test(text)) { - return; - } - - this._current[_xfa_object.$onText](text.trim()); - } - - onCdata(text) { - this._current[_xfa_object.$onText](text); - } - - _mkAttributes(attributes, tagName) { - let namespace = null; - let prefixes = null; - const attributeObj = Object.create({}); - - for (const { - name, - value - } of attributes) { - if (name === "xmlns") { - if (!namespace) { - namespace = value; - } else { - (0, _util.warn)(`XFA - multiple namespace definition in <${tagName}>`); - } - } else if (name.startsWith("xmlns:")) { - const prefix = name.substring("xmlns:".length); - - if (!prefixes) { - prefixes = []; - } - - prefixes.push({ - prefix, - value - }); - } else { - const i = name.indexOf(":"); - - if (i === -1) { - attributeObj[name] = value; - } else { - let nsAttrs = attributeObj[_xfa_object.$nsAttributes]; - - if (!nsAttrs) { - nsAttrs = attributeObj[_xfa_object.$nsAttributes] = Object.create(null); - } - - const [ns, attrName] = [name.slice(0, i), name.slice(i + 1)]; - let attrs = nsAttrs[ns]; - - if (!attrs) { - attrs = nsAttrs[ns] = Object.create(null); - } - - attrs[attrName] = value; - } - } - } - - return [namespace, prefixes, attributeObj]; - } - - _getNameAndPrefix(name, nsAgnostic) { - const i = name.indexOf(":"); - - if (i === -1) { - return [name, null]; - } - - return [name.substring(i + 1), nsAgnostic ? "" : name.substring(0, i)]; - } - - onBeginElement(tagName, attributes, isEmpty) { - const [namespace, prefixes, attributesObj] = this._mkAttributes(attributes, tagName); - - const [name, nsPrefix] = this._getNameAndPrefix(tagName, this._builder.isNsAgnostic()); - - const node = this._builder.build({ - nsPrefix, - name, - attributes: attributesObj, - namespace, - prefixes - }); - - node[_xfa_object.$globalData] = this._globalData; - - if (isEmpty) { - node[_xfa_object.$finalize](); - - if (this._current[_xfa_object.$onChild](node)) { - node[_xfa_object.$setId](this._ids); - } - - node[_xfa_object.$clean](this._builder); - - return; - } - - this._stack.push(this._current); - - this._current = node; - } - - onEndElement(name) { - const node = this._current; - - if (node[_xfa_object.$isCDATAXml]() && typeof node[_xfa_object.$content] === "string") { - const parser = new XFAParser(); - parser._globalData = this._globalData; - const root = parser.parse(node[_xfa_object.$content]); - node[_xfa_object.$content] = null; - - node[_xfa_object.$onChild](root); - } - - node[_xfa_object.$finalize](); - - this._current = this._stack.pop(); - - if (this._current[_xfa_object.$onChild](node)) { - node[_xfa_object.$setId](this._ids); - } - - node[_xfa_object.$clean](this._builder); - } - - onError(code) { - this._errorCode = code; - } - -} - -exports.XFAParser = XFAParser; - -/***/ }), -/* 87 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.Builder = void 0; - -var _namespaces = __w_pdfjs_require__(77); - -var _xfa_object = __w_pdfjs_require__(75); - -var _setup = __w_pdfjs_require__(88); - -var _template = __w_pdfjs_require__(80); - -var _unknown = __w_pdfjs_require__(97); - -var _util = __w_pdfjs_require__(2); - -class Root extends _xfa_object.XFAObject { - constructor(ids) { - super(-1, "root", Object.create(null)); - this.element = null; - this[_xfa_object.$ids] = ids; - } - - [_xfa_object.$onChild](child) { - this.element = child; - return true; - } - - [_xfa_object.$finalize]() { - super[_xfa_object.$finalize](); - - if (this.element.template instanceof _template.Template) { - this[_xfa_object.$ids].set(_xfa_object.$root, this.element); - - this.element.template[_xfa_object.$resolvePrototypes](this[_xfa_object.$ids]); - - this.element.template[_xfa_object.$ids] = this[_xfa_object.$ids]; - } - } - -} - -class Empty extends _xfa_object.XFAObject { - constructor() { - super(-1, "", Object.create(null)); - } - - [_xfa_object.$onChild](_) { - return false; - } - -} - -class Builder { - constructor(rootNameSpace = null) { - this._namespaceStack = []; - this._nsAgnosticLevel = 0; - this._namespacePrefixes = new Map(); - this._namespaces = new Map(); - this._nextNsId = Math.max(...Object.values(_namespaces.NamespaceIds).map(({ - id - }) => id)); - this._currentNamespace = rootNameSpace || new _unknown.UnknownNamespace(++this._nextNsId); - } - - buildRoot(ids) { - return new Root(ids); - } - - build({ - nsPrefix, - name, - attributes, - namespace, - prefixes - }) { - const hasNamespaceDef = namespace !== null; - - if (hasNamespaceDef) { - this._namespaceStack.push(this._currentNamespace); - - this._currentNamespace = this._searchNamespace(namespace); - } - - if (prefixes) { - this._addNamespacePrefix(prefixes); - } - - if (attributes.hasOwnProperty(_xfa_object.$nsAttributes)) { - const dataTemplate = _setup.NamespaceSetUp.datasets; - const nsAttrs = attributes[_xfa_object.$nsAttributes]; - let xfaAttrs = null; - - for (const [ns, attrs] of Object.entries(nsAttrs)) { - const nsToUse = this._getNamespaceToUse(ns); - - if (nsToUse === dataTemplate) { - xfaAttrs = { - xfa: attrs - }; - break; - } - } - - if (xfaAttrs) { - attributes[_xfa_object.$nsAttributes] = xfaAttrs; - } else { - delete attributes[_xfa_object.$nsAttributes]; - } - } - - const namespaceToUse = this._getNamespaceToUse(nsPrefix); - - const node = namespaceToUse && namespaceToUse[_namespaces.$buildXFAObject](name, attributes) || new Empty(); - - if (node[_xfa_object.$isNsAgnostic]()) { - this._nsAgnosticLevel++; - } - - if (hasNamespaceDef || prefixes || node[_xfa_object.$isNsAgnostic]()) { - node[_xfa_object.$cleanup] = { - hasNamespace: hasNamespaceDef, - prefixes, - nsAgnostic: node[_xfa_object.$isNsAgnostic]() - }; - } - - return node; - } - - isNsAgnostic() { - return this._nsAgnosticLevel > 0; - } - - _searchNamespace(nsName) { - let ns = this._namespaces.get(nsName); - - if (ns) { - return ns; - } - - for (const [name, { - check - }] of Object.entries(_namespaces.NamespaceIds)) { - if (check(nsName)) { - ns = _setup.NamespaceSetUp[name]; - - if (ns) { - this._namespaces.set(nsName, ns); - - return ns; - } - - break; - } - } - - ns = new _unknown.UnknownNamespace(++this._nextNsId); - - this._namespaces.set(nsName, ns); - - return ns; - } - - _addNamespacePrefix(prefixes) { - for (const { - prefix, - value - } of prefixes) { - const namespace = this._searchNamespace(value); - - let prefixStack = this._namespacePrefixes.get(prefix); - - if (!prefixStack) { - prefixStack = []; - - this._namespacePrefixes.set(prefix, prefixStack); - } - - prefixStack.push(namespace); - } - } - - _getNamespaceToUse(prefix) { - if (!prefix) { - return this._currentNamespace; - } - - const prefixStack = this._namespacePrefixes.get(prefix); - - if (prefixStack && prefixStack.length > 0) { - return prefixStack[prefixStack.length - 1]; - } - - (0, _util.warn)(`Unknown namespace prefix: ${prefix}.`); - return null; - } - - clean(data) { - const { - hasNamespace, - prefixes, - nsAgnostic - } = data; - - if (hasNamespace) { - this._currentNamespace = this._namespaceStack.pop(); - } - - if (prefixes) { - prefixes.forEach(({ - prefix - }) => { - this._namespacePrefixes.get(prefix).pop(); - }); - } - - if (nsAgnostic) { - this._nsAgnosticLevel--; - } - } - -} - -exports.Builder = Builder; - -/***/ }), -/* 88 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.NamespaceSetUp = void 0; - -var _config = __w_pdfjs_require__(89); - -var _connection_set = __w_pdfjs_require__(90); - -var _datasets = __w_pdfjs_require__(91); - -var _locale_set = __w_pdfjs_require__(92); - -var _signature = __w_pdfjs_require__(93); - -var _stylesheet = __w_pdfjs_require__(94); - -var _template = __w_pdfjs_require__(80); - -var _xdp = __w_pdfjs_require__(95); - -var _xhtml = __w_pdfjs_require__(96); - -const NamespaceSetUp = { - config: _config.ConfigNamespace, - connection: _connection_set.ConnectionSetNamespace, - datasets: _datasets.DatasetsNamespace, - localeSet: _locale_set.LocaleSetNamespace, - signature: _signature.SignatureNamespace, - stylesheet: _stylesheet.StylesheetNamespace, - template: _template.TemplateNamespace, - xdp: _xdp.XdpNamespace, - xhtml: _xhtml.XhtmlNamespace -}; -exports.NamespaceSetUp = NamespaceSetUp; - -/***/ }), -/* 89 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.ConfigNamespace = void 0; - -var _namespaces = __w_pdfjs_require__(77); - -var _xfa_object = __w_pdfjs_require__(75); - -var _utils = __w_pdfjs_require__(76); - -var _util = __w_pdfjs_require__(2); - -const CONFIG_NS_ID = _namespaces.NamespaceIds.config.id; - -class Acrobat extends _xfa_object.XFAObject { - constructor(attributes) { - super(CONFIG_NS_ID, "acrobat", true); - this.acrobat7 = null; - this.autoSave = null; - this.common = null; - this.validate = null; - this.validateApprovalSignatures = null; - this.submitUrl = new _xfa_object.XFAObjectArray(); - } - -} - -class Acrobat7 extends _xfa_object.XFAObject { - constructor(attributes) { - super(CONFIG_NS_ID, "acrobat7", true); - this.dynamicRender = null; - } - -} - -class ADBE_JSConsole extends _xfa_object.OptionObject { - constructor(attributes) { - super(CONFIG_NS_ID, "ADBE_JSConsole", ["delegate", "Enable", "Disable"]); - } - -} - -class ADBE_JSDebugger extends _xfa_object.OptionObject { - constructor(attributes) { - super(CONFIG_NS_ID, "ADBE_JSDebugger", ["delegate", "Enable", "Disable"]); - } - -} - -class AddSilentPrint extends _xfa_object.Option01 { - constructor(attributes) { - super(CONFIG_NS_ID, "addSilentPrint"); - } - -} - -class AddViewerPreferences extends _xfa_object.Option01 { - constructor(attributes) { - super(CONFIG_NS_ID, "addViewerPreferences"); - } - -} - -class AdjustData extends _xfa_object.Option10 { - constructor(attributes) { - super(CONFIG_NS_ID, "adjustData"); - } - -} - -class AdobeExtensionLevel extends _xfa_object.IntegerObject { - constructor(attributes) { - super(CONFIG_NS_ID, "adobeExtensionLevel", 0, n => n >= 1 && n <= 8); - } - -} - -class Agent extends _xfa_object.XFAObject { - constructor(attributes) { - super(CONFIG_NS_ID, "agent", true); - this.name = attributes.name ? attributes.name.trim() : ""; - this.common = new _xfa_object.XFAObjectArray(); - } - -} - -class AlwaysEmbed extends _xfa_object.ContentObject { - constructor(attributes) { - super(CONFIG_NS_ID, "alwaysEmbed"); - } - -} - -class Amd extends _xfa_object.StringObject { - constructor(attributes) { - super(CONFIG_NS_ID, "amd"); - } - -} - -class Area extends _xfa_object.XFAObject { - constructor(attributes) { - super(CONFIG_NS_ID, "area"); - this.level = (0, _utils.getInteger)({ - data: attributes.level, - defaultValue: 0, - validate: n => n >= 1 && n <= 3 - }); - this.name = (0, _utils.getStringOption)(attributes.name, ["", "barcode", "coreinit", "deviceDriver", "font", "general", "layout", "merge", "script", "signature", "sourceSet", "templateCache"]); - } - -} - -class Attributes extends _xfa_object.OptionObject { - constructor(attributes) { - super(CONFIG_NS_ID, "attributes", ["preserve", "delegate", "ignore"]); - } - -} - -class AutoSave extends _xfa_object.OptionObject { - constructor(attributes) { - super(CONFIG_NS_ID, "autoSave", ["disabled", "enabled"]); - } - -} - -class Base extends _xfa_object.StringObject { - constructor(attributes) { - super(CONFIG_NS_ID, "base"); - } - -} - -class BatchOutput extends _xfa_object.XFAObject { - constructor(attributes) { - super(CONFIG_NS_ID, "batchOutput"); - this.format = (0, _utils.getStringOption)(attributes.format, ["none", "concat", "zip", "zipCompress"]); - } - -} - -class BehaviorOverride extends _xfa_object.ContentObject { - constructor(attributes) { - super(CONFIG_NS_ID, "behaviorOverride"); - } - - [_xfa_object.$finalize]() { - this[_xfa_object.$content] = new Map(this[_xfa_object.$content].trim().split(/\s+/).filter(x => x.includes(":")).map(x => x.split(":", 2))); - } - -} - -class Cache extends _xfa_object.XFAObject { - constructor(attributes) { - super(CONFIG_NS_ID, "cache", true); - this.templateCache = null; - } - -} - -class Change extends _xfa_object.Option01 { - constructor(attributes) { - super(CONFIG_NS_ID, "change"); - } - -} - -class Common extends _xfa_object.XFAObject { - constructor(attributes) { - super(CONFIG_NS_ID, "common", true); - this.data = null; - this.locale = null; - this.localeSet = null; - this.messaging = null; - this.suppressBanner = null; - this.template = null; - this.validationMessaging = null; - this.versionControl = null; - this.log = new _xfa_object.XFAObjectArray(); - } - -} - -class Compress extends _xfa_object.XFAObject { - constructor(attributes) { - super(CONFIG_NS_ID, "compress"); - this.scope = (0, _utils.getStringOption)(attributes.scope, ["imageOnly", "document"]); - } - -} - -class CompressLogicalStructure extends _xfa_object.Option01 { - constructor(attributes) { - super(CONFIG_NS_ID, "compressLogicalStructure"); - } - -} - -class CompressObjectStream extends _xfa_object.Option10 { - constructor(attributes) { - super(CONFIG_NS_ID, "compressObjectStream"); - } - -} - -class Compression extends _xfa_object.XFAObject { - constructor(attributes) { - super(CONFIG_NS_ID, "compression", true); - this.compressLogicalStructure = null; - this.compressObjectStream = null; - this.level = null; - this.type = null; - } - -} - -class Config extends _xfa_object.XFAObject { - constructor(attributes) { - super(CONFIG_NS_ID, "config", true); - this.acrobat = null; - this.present = null; - this.trace = null; - this.agent = new _xfa_object.XFAObjectArray(); - } - -} - -class Conformance extends _xfa_object.OptionObject { - constructor(attributes) { - super(CONFIG_NS_ID, "conformance", ["A", "B"]); - } - -} - -class ContentCopy extends _xfa_object.Option01 { - constructor(attributes) { - super(CONFIG_NS_ID, "contentCopy"); - } - -} - -class Copies extends _xfa_object.IntegerObject { - constructor(attributes) { - super(CONFIG_NS_ID, "copies", 1, n => n >= 1); - } - -} - -class Creator extends _xfa_object.StringObject { - constructor(attributes) { - super(CONFIG_NS_ID, "creator"); - } - -} - -class CurrentPage extends _xfa_object.IntegerObject { - constructor(attributes) { - super(CONFIG_NS_ID, "currentPage", 0, n => n >= 0); - } - -} - -class Data extends _xfa_object.XFAObject { - constructor(attributes) { - super(CONFIG_NS_ID, "data", true); - this.adjustData = null; - this.attributes = null; - this.incrementalLoad = null; - this.outputXSL = null; - this.range = null; - this.record = null; - this.startNode = null; - this.uri = null; - this.window = null; - this.xsl = null; - this.excludeNS = new _xfa_object.XFAObjectArray(); - this.transform = new _xfa_object.XFAObjectArray(); - } - -} - -class Debug extends _xfa_object.XFAObject { - constructor(attributes) { - super(CONFIG_NS_ID, "debug", true); - this.uri = null; - } - -} - -class DefaultTypeface extends _xfa_object.ContentObject { - constructor(attributes) { - super(CONFIG_NS_ID, "defaultTypeface"); - this.writingScript = (0, _utils.getStringOption)(attributes.writingScript, ["*", "Arabic", "Cyrillic", "EastEuropeanRoman", "Greek", "Hebrew", "Japanese", "Korean", "Roman", "SimplifiedChinese", "Thai", "TraditionalChinese", "Vietnamese"]); - } - -} - -class Destination extends _xfa_object.OptionObject { - constructor(attributes) { - super(CONFIG_NS_ID, "destination", ["pdf", "pcl", "ps", "webClient", "zpl"]); - } - -} - -class DocumentAssembly extends _xfa_object.Option01 { - constructor(attributes) { - super(CONFIG_NS_ID, "documentAssembly"); - } - -} - -class Driver extends _xfa_object.XFAObject { - constructor(attributes) { - super(CONFIG_NS_ID, "driver", true); - this.name = attributes.name ? attributes.name.trim() : ""; - this.fontInfo = null; - this.xdc = null; - } - -} - -class DuplexOption extends _xfa_object.OptionObject { - constructor(attributes) { - super(CONFIG_NS_ID, "duplexOption", ["simplex", "duplexFlipLongEdge", "duplexFlipShortEdge"]); - } - -} - -class DynamicRender extends _xfa_object.OptionObject { - constructor(attributes) { - super(CONFIG_NS_ID, "dynamicRender", ["forbidden", "required"]); - } - -} - -class Embed extends _xfa_object.Option01 { - constructor(attributes) { - super(CONFIG_NS_ID, "embed"); - } - -} - -class Encrypt extends _xfa_object.Option01 { - constructor(attributes) { - super(CONFIG_NS_ID, "encrypt"); - } - -} - -class Encryption extends _xfa_object.XFAObject { - constructor(attributes) { - super(CONFIG_NS_ID, "encryption", true); - this.encrypt = null; - this.encryptionLevel = null; - this.permissions = null; - } - -} - -class EncryptionLevel extends _xfa_object.OptionObject { - constructor(attributes) { - super(CONFIG_NS_ID, "encryptionLevel", ["40bit", "128bit"]); - } - -} - -class Enforce extends _xfa_object.StringObject { - constructor(attributes) { - super(CONFIG_NS_ID, "enforce"); - } - -} - -class Equate extends _xfa_object.XFAObject { - constructor(attributes) { - super(CONFIG_NS_ID, "equate"); - this.force = (0, _utils.getInteger)({ - data: attributes.force, - defaultValue: 1, - validate: n => n === 0 - }); - this.from = attributes.from || ""; - this.to = attributes.to || ""; - } - -} - -class EquateRange extends _xfa_object.XFAObject { - constructor(attributes) { - super(CONFIG_NS_ID, "equateRange"); - this.from = attributes.from || ""; - this.to = attributes.to || ""; - this._unicodeRange = attributes.unicodeRange || ""; - } - - get unicodeRange() { - const ranges = []; - const unicodeRegex = /U\+([0-9a-fA-F]+)/; - const unicodeRange = this._unicodeRange; - - for (let range of unicodeRange.split(",").map(x => x.trim()).filter(x => !!x)) { - range = range.split("-", 2).map(x => { - const found = x.match(unicodeRegex); - - if (!found) { - return 0; - } - - return parseInt(found[1], 16); - }); - - if (range.length === 1) { - range.push(range[0]); - } - - ranges.push(range); - } - - return (0, _util.shadow)(this, "unicodeRange", ranges); - } - -} - -class Exclude extends _xfa_object.ContentObject { - constructor(attributes) { - super(CONFIG_NS_ID, "exclude"); - } - - [_xfa_object.$finalize]() { - this[_xfa_object.$content] = this[_xfa_object.$content].trim().split(/\s+/).filter(x => x && ["calculate", "close", "enter", "exit", "initialize", "ready", "validate"].includes(x)); - } - -} - -class ExcludeNS extends _xfa_object.StringObject { - constructor(attributes) { - super(CONFIG_NS_ID, "excludeNS"); - } - -} - -class FlipLabel extends _xfa_object.OptionObject { - constructor(attributes) { - super(CONFIG_NS_ID, "flipLabel", ["usePrinterSetting", "on", "off"]); - } - -} - -class FontInfo extends _xfa_object.XFAObject { - constructor(attributes) { - super(CONFIG_NS_ID, "fontInfo", true); - this.embed = null; - this.map = null; - this.subsetBelow = null; - this.alwaysEmbed = new _xfa_object.XFAObjectArray(); - this.defaultTypeface = new _xfa_object.XFAObjectArray(); - this.neverEmbed = new _xfa_object.XFAObjectArray(); - } - -} - -class FormFieldFilling extends _xfa_object.Option01 { - constructor(attributes) { - super(CONFIG_NS_ID, "formFieldFilling"); - } - -} - -class GroupParent extends _xfa_object.StringObject { - constructor(attributes) { - super(CONFIG_NS_ID, "groupParent"); - } - -} - -class IfEmpty extends _xfa_object.OptionObject { - constructor(attributes) { - super(CONFIG_NS_ID, "ifEmpty", ["dataValue", "dataGroup", "ignore", "remove"]); - } - -} - -class IncludeXDPContent extends _xfa_object.StringObject { - constructor(attributes) { - super(CONFIG_NS_ID, "includeXDPContent"); - } - -} - -class IncrementalLoad extends _xfa_object.OptionObject { - constructor(attributes) { - super(CONFIG_NS_ID, "incrementalLoad", ["none", "forwardOnly"]); - } - -} - -class IncrementalMerge extends _xfa_object.Option01 { - constructor(attributes) { - super(CONFIG_NS_ID, "incrementalMerge"); - } - -} - -class Interactive extends _xfa_object.Option01 { - constructor(attributes) { - super(CONFIG_NS_ID, "interactive"); - } - -} - -class Jog extends _xfa_object.OptionObject { - constructor(attributes) { - super(CONFIG_NS_ID, "jog", ["usePrinterSetting", "none", "pageSet"]); - } - -} - -class LabelPrinter extends _xfa_object.XFAObject { - constructor(attributes) { - super(CONFIG_NS_ID, "labelPrinter", true); - this.name = (0, _utils.getStringOption)(attributes.name, ["zpl", "dpl", "ipl", "tcpl"]); - this.batchOutput = null; - this.flipLabel = null; - this.fontInfo = null; - this.xdc = null; - } - -} - -class Layout extends _xfa_object.OptionObject { - constructor(attributes) { - super(CONFIG_NS_ID, "layout", ["paginate", "panel"]); - } - -} - -class Level extends _xfa_object.IntegerObject { - constructor(attributes) { - super(CONFIG_NS_ID, "level", 0, n => n > 0); - } - -} - -class Linearized extends _xfa_object.Option01 { - constructor(attributes) { - super(CONFIG_NS_ID, "linearized"); - } - -} - -class Locale extends _xfa_object.StringObject { - constructor(attributes) { - super(CONFIG_NS_ID, "locale"); - } - -} - -class LocaleSet extends _xfa_object.StringObject { - constructor(attributes) { - super(CONFIG_NS_ID, "localeSet"); - } - -} - -class Log extends _xfa_object.XFAObject { - constructor(attributes) { - super(CONFIG_NS_ID, "log", true); - this.mode = null; - this.threshold = null; - this.to = null; - this.uri = null; - } - -} - -class MapElement extends _xfa_object.XFAObject { - constructor(attributes) { - super(CONFIG_NS_ID, "map", true); - this.equate = new _xfa_object.XFAObjectArray(); - this.equateRange = new _xfa_object.XFAObjectArray(); - } - -} - -class MediumInfo extends _xfa_object.XFAObject { - constructor(attributes) { - super(CONFIG_NS_ID, "mediumInfo", true); - this.map = null; - } - -} - -class Message extends _xfa_object.XFAObject { - constructor(attributes) { - super(CONFIG_NS_ID, "message", true); - this.msgId = null; - this.severity = null; - } - -} - -class Messaging extends _xfa_object.XFAObject { - constructor(attributes) { - super(CONFIG_NS_ID, "messaging", true); - this.message = new _xfa_object.XFAObjectArray(); - } - -} - -class Mode extends _xfa_object.OptionObject { - constructor(attributes) { - super(CONFIG_NS_ID, "mode", ["append", "overwrite"]); - } - -} - -class ModifyAnnots extends _xfa_object.Option01 { - constructor(attributes) { - super(CONFIG_NS_ID, "modifyAnnots"); - } - -} - -class MsgId extends _xfa_object.IntegerObject { - constructor(attributes) { - super(CONFIG_NS_ID, "msgId", 1, n => n >= 1); - } - -} - -class NameAttr extends _xfa_object.StringObject { - constructor(attributes) { - super(CONFIG_NS_ID, "nameAttr"); - } - -} - -class NeverEmbed extends _xfa_object.ContentObject { - constructor(attributes) { - super(CONFIG_NS_ID, "neverEmbed"); - } - -} - -class NumberOfCopies extends _xfa_object.IntegerObject { - constructor(attributes) { - super(CONFIG_NS_ID, "numberOfCopies", null, n => n >= 2 && n <= 5); - } - -} - -class OpenAction extends _xfa_object.XFAObject { - constructor(attributes) { - super(CONFIG_NS_ID, "openAction", true); - this.destination = null; - } - -} - -class Output extends _xfa_object.XFAObject { - constructor(attributes) { - super(CONFIG_NS_ID, "output", true); - this.to = null; - this.type = null; - this.uri = null; - } - -} - -class OutputBin extends _xfa_object.StringObject { - constructor(attributes) { - super(CONFIG_NS_ID, "outputBin"); - } - -} - -class OutputXSL extends _xfa_object.XFAObject { - constructor(attributes) { - super(CONFIG_NS_ID, "outputXSL", true); - this.uri = null; - } - -} - -class Overprint extends _xfa_object.OptionObject { - constructor(attributes) { - super(CONFIG_NS_ID, "overprint", ["none", "both", "draw", "field"]); - } - -} - -class Packets extends _xfa_object.StringObject { - constructor(attributes) { - super(CONFIG_NS_ID, "packets"); - } - - [_xfa_object.$finalize]() { - if (this[_xfa_object.$content] === "*") { - return; - } - - this[_xfa_object.$content] = this[_xfa_object.$content].trim().split(/\s+/).filter(x => ["config", "datasets", "template", "xfdf", "xslt"].includes(x)); - } - -} - -class PageOffset extends _xfa_object.XFAObject { - constructor(attributes) { - super(CONFIG_NS_ID, "pageOffset"); - this.x = (0, _utils.getInteger)({ - data: attributes.x, - defaultValue: "useXDCSetting", - validate: n => true - }); - this.y = (0, _utils.getInteger)({ - data: attributes.y, - defaultValue: "useXDCSetting", - validate: n => true - }); - } - -} - -class PageRange extends _xfa_object.StringObject { - constructor(attributes) { - super(CONFIG_NS_ID, "pageRange"); - } - - [_xfa_object.$finalize]() { - const numbers = this[_xfa_object.$content].trim().split(/\s+/).map(x => parseInt(x, 10)); - - const ranges = []; - - for (let i = 0, ii = numbers.length; i < ii; i += 2) { - ranges.push(numbers.slice(i, i + 2)); - } - - this[_xfa_object.$content] = ranges; - } - -} - -class Pagination extends _xfa_object.OptionObject { - constructor(attributes) { - super(CONFIG_NS_ID, "pagination", ["simplex", "duplexShortEdge", "duplexLongEdge"]); - } - -} - -class PaginationOverride extends _xfa_object.OptionObject { - constructor(attributes) { - super(CONFIG_NS_ID, "paginationOverride", ["none", "forceDuplex", "forceDuplexLongEdge", "forceDuplexShortEdge", "forceSimplex"]); - } - -} - -class Part extends _xfa_object.IntegerObject { - constructor(attributes) { - super(CONFIG_NS_ID, "part", 1, n => false); - } - -} - -class Pcl extends _xfa_object.XFAObject { - constructor(attributes) { - super(CONFIG_NS_ID, "pcl", true); - this.name = attributes.name || ""; - this.batchOutput = null; - this.fontInfo = null; - this.jog = null; - this.mediumInfo = null; - this.outputBin = null; - this.pageOffset = null; - this.staple = null; - this.xdc = null; - } - -} - -class Pdf extends _xfa_object.XFAObject { - constructor(attributes) { - super(CONFIG_NS_ID, "pdf", true); - this.name = attributes.name || ""; - this.adobeExtensionLevel = null; - this.batchOutput = null; - this.compression = null; - this.creator = null; - this.encryption = null; - this.fontInfo = null; - this.interactive = null; - this.linearized = null; - this.openAction = null; - this.pdfa = null; - this.producer = null; - this.renderPolicy = null; - this.scriptModel = null; - this.silentPrint = null; - this.submitFormat = null; - this.tagged = null; - this.version = null; - this.viewerPreferences = null; - this.xdc = null; - } - -} - -class Pdfa extends _xfa_object.XFAObject { - constructor(attributes) { - super(CONFIG_NS_ID, "pdfa", true); - this.amd = null; - this.conformance = null; - this.includeXDPContent = null; - this.part = null; - } - -} - -class Permissions extends _xfa_object.XFAObject { - constructor(attributes) { - super(CONFIG_NS_ID, "permissions", true); - this.accessibleContent = null; - this.change = null; - this.contentCopy = null; - this.documentAssembly = null; - this.formFieldFilling = null; - this.modifyAnnots = null; - this.plaintextMetadata = null; - this.print = null; - this.printHighQuality = null; - } - -} - -class PickTrayByPDFSize extends _xfa_object.Option01 { - constructor(attributes) { - super(CONFIG_NS_ID, "pickTrayByPDFSize"); - } - -} - -class Picture extends _xfa_object.StringObject { - constructor(attributes) { - super(CONFIG_NS_ID, "picture"); - } - -} - -class PlaintextMetadata extends _xfa_object.Option01 { - constructor(attributes) { - super(CONFIG_NS_ID, "plaintextMetadata"); - } - -} - -class Presence extends _xfa_object.OptionObject { - constructor(attributes) { - super(CONFIG_NS_ID, "presence", ["preserve", "dissolve", "dissolveStructure", "ignore", "remove"]); - } - -} - -class Present extends _xfa_object.XFAObject { - constructor(attributes) { - super(CONFIG_NS_ID, "present", true); - this.behaviorOverride = null; - this.cache = null; - this.common = null; - this.copies = null; - this.destination = null; - this.incrementalMerge = null; - this.layout = null; - this.output = null; - this.overprint = null; - this.pagination = null; - this.paginationOverride = null; - this.script = null; - this.validate = null; - this.xdp = null; - this.driver = new _xfa_object.XFAObjectArray(); - this.labelPrinter = new _xfa_object.XFAObjectArray(); - this.pcl = new _xfa_object.XFAObjectArray(); - this.pdf = new _xfa_object.XFAObjectArray(); - this.ps = new _xfa_object.XFAObjectArray(); - this.submitUrl = new _xfa_object.XFAObjectArray(); - this.webClient = new _xfa_object.XFAObjectArray(); - this.zpl = new _xfa_object.XFAObjectArray(); - } - -} - -class Print extends _xfa_object.Option01 { - constructor(attributes) { - super(CONFIG_NS_ID, "print"); - } - -} - -class PrintHighQuality extends _xfa_object.Option01 { - constructor(attributes) { - super(CONFIG_NS_ID, "printHighQuality"); - } - -} - -class PrintScaling extends _xfa_object.OptionObject { - constructor(attributes) { - super(CONFIG_NS_ID, "printScaling", ["appdefault", "noScaling"]); - } - -} - -class PrinterName extends _xfa_object.StringObject { - constructor(attributes) { - super(CONFIG_NS_ID, "printerName"); - } - -} - -class Producer extends _xfa_object.StringObject { - constructor(attributes) { - super(CONFIG_NS_ID, "producer"); - } - -} - -class Ps extends _xfa_object.XFAObject { - constructor(attributes) { - super(CONFIG_NS_ID, "ps", true); - this.name = attributes.name || ""; - this.batchOutput = null; - this.fontInfo = null; - this.jog = null; - this.mediumInfo = null; - this.outputBin = null; - this.staple = null; - this.xdc = null; - } - -} - -class Range extends _xfa_object.ContentObject { - constructor(attributes) { - super(CONFIG_NS_ID, "range"); - } - - [_xfa_object.$finalize]() { - this[_xfa_object.$content] = this[_xfa_object.$content].trim().split(/\s*,\s*/, 2).map(range => range.split("-").map(x => parseInt(x.trim(), 10))).filter(range => range.every(x => !isNaN(x))).map(range => { - if (range.length === 1) { - range.push(range[0]); - } - - return range; - }); - } - -} - -class Record extends _xfa_object.ContentObject { - constructor(attributes) { - super(CONFIG_NS_ID, "record"); - } - - [_xfa_object.$finalize]() { - this[_xfa_object.$content] = this[_xfa_object.$content].trim(); - const n = parseInt(this[_xfa_object.$content], 10); - - if (!isNaN(n) && n >= 0) { - this[_xfa_object.$content] = n; - } - } - -} - -class Relevant extends _xfa_object.ContentObject { - constructor(attributes) { - super(CONFIG_NS_ID, "relevant"); - } - - [_xfa_object.$finalize]() { - this[_xfa_object.$content] = this[_xfa_object.$content].trim().split(/\s+/); - } - -} - -class Rename extends _xfa_object.ContentObject { - constructor(attributes) { - super(CONFIG_NS_ID, "rename"); - } - - [_xfa_object.$finalize]() { - this[_xfa_object.$content] = this[_xfa_object.$content].trim(); - - if (this[_xfa_object.$content].toLowerCase().startsWith("xml") || this[_xfa_object.$content].match(new RegExp("[\\p{L}_][\\p{L}\\d._\\p{M}-]*", "u"))) { - (0, _util.warn)("XFA - Rename: invalid XFA name"); - } - } - -} - -class RenderPolicy extends _xfa_object.OptionObject { - constructor(attributes) { - super(CONFIG_NS_ID, "renderPolicy", ["server", "client"]); - } - -} - -class RunScripts extends _xfa_object.OptionObject { - constructor(attributes) { - super(CONFIG_NS_ID, "runScripts", ["both", "client", "none", "server"]); - } - -} - -class Script extends _xfa_object.XFAObject { - constructor(attributes) { - super(CONFIG_NS_ID, "script", true); - this.currentPage = null; - this.exclude = null; - this.runScripts = null; - } - -} - -class ScriptModel extends _xfa_object.OptionObject { - constructor(attributes) { - super(CONFIG_NS_ID, "scriptModel", ["XFA", "none"]); - } - -} - -class Severity extends _xfa_object.OptionObject { - constructor(attributes) { - super(CONFIG_NS_ID, "severity", ["ignore", "error", "information", "trace", "warning"]); - } - -} - -class SilentPrint extends _xfa_object.XFAObject { - constructor(attributes) { - super(CONFIG_NS_ID, "silentPrint", true); - this.addSilentPrint = null; - this.printerName = null; - } - -} - -class Staple extends _xfa_object.XFAObject { - constructor(attributes) { - super(CONFIG_NS_ID, "staple"); - this.mode = (0, _utils.getStringOption)(attributes.mode, ["usePrinterSetting", "on", "off"]); - } - -} - -class StartNode extends _xfa_object.StringObject { - constructor(attributes) { - super(CONFIG_NS_ID, "startNode"); - } - -} - -class StartPage extends _xfa_object.IntegerObject { - constructor(attributes) { - super(CONFIG_NS_ID, "startPage", 0, n => true); - } - -} - -class SubmitFormat extends _xfa_object.OptionObject { - constructor(attributes) { - super(CONFIG_NS_ID, "submitFormat", ["html", "delegate", "fdf", "xml", "pdf"]); - } - -} - -class SubmitUrl extends _xfa_object.StringObject { - constructor(attributes) { - super(CONFIG_NS_ID, "submitUrl"); - } - -} - -class SubsetBelow extends _xfa_object.IntegerObject { - constructor(attributes) { - super(CONFIG_NS_ID, "subsetBelow", 100, n => n >= 0 && n <= 100); - } - -} - -class SuppressBanner extends _xfa_object.Option01 { - constructor(attributes) { - super(CONFIG_NS_ID, "suppressBanner"); - } - -} - -class Tagged extends _xfa_object.Option01 { - constructor(attributes) { - super(CONFIG_NS_ID, "tagged"); - } - -} - -class Template extends _xfa_object.XFAObject { - constructor(attributes) { - super(CONFIG_NS_ID, "template", true); - this.base = null; - this.relevant = null; - this.startPage = null; - this.uri = null; - this.xsl = null; - } - -} - -class Threshold extends _xfa_object.OptionObject { - constructor(attributes) { - super(CONFIG_NS_ID, "threshold", ["trace", "error", "information", "warning"]); - } - -} - -class To extends _xfa_object.OptionObject { - constructor(attributes) { - super(CONFIG_NS_ID, "to", ["null", "memory", "stderr", "stdout", "system", "uri"]); - } - -} - -class TemplateCache extends _xfa_object.XFAObject { - constructor(attributes) { - super(CONFIG_NS_ID, "templateCache"); - this.maxEntries = (0, _utils.getInteger)({ - data: attributes.maxEntries, - defaultValue: 5, - validate: n => n >= 0 - }); - } - -} - -class Trace extends _xfa_object.XFAObject { - constructor(attributes) { - super(CONFIG_NS_ID, "trace", true); - this.area = new _xfa_object.XFAObjectArray(); - } - -} - -class Transform extends _xfa_object.XFAObject { - constructor(attributes) { - super(CONFIG_NS_ID, "transform", true); - this.groupParent = null; - this.ifEmpty = null; - this.nameAttr = null; - this.picture = null; - this.presence = null; - this.rename = null; - this.whitespace = null; - } - -} - -class Type extends _xfa_object.OptionObject { - constructor(attributes) { - super(CONFIG_NS_ID, "type", ["none", "ascii85", "asciiHex", "ccittfax", "flate", "lzw", "runLength", "native", "xdp", "mergedXDP"]); - } - -} - -class Uri extends _xfa_object.StringObject { - constructor(attributes) { - super(CONFIG_NS_ID, "uri"); - } - -} - -class Validate extends _xfa_object.OptionObject { - constructor(attributes) { - super(CONFIG_NS_ID, "validate", ["preSubmit", "prePrint", "preExecute", "preSave"]); - } - -} - -class ValidateApprovalSignatures extends _xfa_object.ContentObject { - constructor(attributes) { - super(CONFIG_NS_ID, "validateApprovalSignatures"); - } - - [_xfa_object.$finalize]() { - this[_xfa_object.$content] = this[_xfa_object.$content].trim().split(/\s+/).filter(x => ["docReady", "postSign"].includes(x)); - } - -} - -class ValidationMessaging extends _xfa_object.OptionObject { - constructor(attributes) { - super(CONFIG_NS_ID, "validationMessaging", ["allMessagesIndividually", "allMessagesTogether", "firstMessageOnly", "noMessages"]); - } - -} - -class Version extends _xfa_object.OptionObject { - constructor(attributes) { - super(CONFIG_NS_ID, "version", ["1.7", "1.6", "1.5", "1.4", "1.3", "1.2"]); - } - -} - -class VersionControl extends _xfa_object.XFAObject { - constructor(attributes) { - super(CONFIG_NS_ID, "VersionControl"); - this.outputBelow = (0, _utils.getStringOption)(attributes.outputBelow, ["warn", "error", "update"]); - this.sourceAbove = (0, _utils.getStringOption)(attributes.sourceAbove, ["warn", "error"]); - this.sourceBelow = (0, _utils.getStringOption)(attributes.sourceBelow, ["update", "maintain"]); - } - -} - -class ViewerPreferences extends _xfa_object.XFAObject { - constructor(attributes) { - super(CONFIG_NS_ID, "viewerPreferences", true); - this.ADBE_JSConsole = null; - this.ADBE_JSDebugger = null; - this.addViewerPreferences = null; - this.duplexOption = null; - this.enforce = null; - this.numberOfCopies = null; - this.pageRange = null; - this.pickTrayByPDFSize = null; - this.printScaling = null; - } - -} - -class WebClient extends _xfa_object.XFAObject { - constructor(attributes) { - super(CONFIG_NS_ID, "webClient", true); - this.name = attributes.name ? attributes.name.trim() : ""; - this.fontInfo = null; - this.xdc = null; - } - -} - -class Whitespace extends _xfa_object.OptionObject { - constructor(attributes) { - super(CONFIG_NS_ID, "whitespace", ["preserve", "ltrim", "normalize", "rtrim", "trim"]); - } - -} - -class Window extends _xfa_object.ContentObject { - constructor(attributes) { - super(CONFIG_NS_ID, "window"); - } - - [_xfa_object.$finalize]() { - const pair = this[_xfa_object.$content].trim().split(/\s*,\s*/, 2).map(x => parseInt(x, 10)); - - if (pair.some(x => isNaN(x))) { - this[_xfa_object.$content] = [0, 0]; - return; - } - - if (pair.length === 1) { - pair.push(pair[0]); - } - - this[_xfa_object.$content] = pair; - } - -} - -class Xdc extends _xfa_object.XFAObject { - constructor(attributes) { - super(CONFIG_NS_ID, "xdc", true); - this.uri = new _xfa_object.XFAObjectArray(); - this.xsl = new _xfa_object.XFAObjectArray(); - } - -} - -class Xdp extends _xfa_object.XFAObject { - constructor(attributes) { - super(CONFIG_NS_ID, "xdp", true); - this.packets = null; - } - -} - -class Xsl extends _xfa_object.XFAObject { - constructor(attributes) { - super(CONFIG_NS_ID, "xsl", true); - this.debug = null; - this.uri = null; - } - -} - -class Zpl extends _xfa_object.XFAObject { - constructor(attributes) { - super(CONFIG_NS_ID, "zpl", true); - this.name = attributes.name ? attributes.name.trim() : ""; - this.batchOutput = null; - this.flipLabel = null; - this.fontInfo = null; - this.xdc = null; - } - -} - -class ConfigNamespace { - static [_namespaces.$buildXFAObject](name, attributes) { - if (ConfigNamespace.hasOwnProperty(name)) { - return ConfigNamespace[name](attributes); - } - - return undefined; - } - - static acrobat(attrs) { - return new Acrobat(attrs); - } - - static acrobat7(attrs) { - return new Acrobat7(attrs); - } - - static ADBE_JSConsole(attrs) { - return new ADBE_JSConsole(attrs); - } - - static ADBE_JSDebugger(attrs) { - return new ADBE_JSDebugger(attrs); - } - - static addSilentPrint(attrs) { - return new AddSilentPrint(attrs); - } - - static addViewerPreferences(attrs) { - return new AddViewerPreferences(attrs); - } - - static adjustData(attrs) { - return new AdjustData(attrs); - } - - static adobeExtensionLevel(attrs) { - return new AdobeExtensionLevel(attrs); - } - - static agent(attrs) { - return new Agent(attrs); - } - - static alwaysEmbed(attrs) { - return new AlwaysEmbed(attrs); - } - - static amd(attrs) { - return new Amd(attrs); - } - - static area(attrs) { - return new Area(attrs); - } - - static attributes(attrs) { - return new Attributes(attrs); - } - - static autoSave(attrs) { - return new AutoSave(attrs); - } - - static base(attrs) { - return new Base(attrs); - } - - static batchOutput(attrs) { - return new BatchOutput(attrs); - } - - static behaviorOverride(attrs) { - return new BehaviorOverride(attrs); - } - - static cache(attrs) { - return new Cache(attrs); - } - - static change(attrs) { - return new Change(attrs); - } - - static common(attrs) { - return new Common(attrs); - } - - static compress(attrs) { - return new Compress(attrs); - } - - static compressLogicalStructure(attrs) { - return new CompressLogicalStructure(attrs); - } - - static compressObjectStream(attrs) { - return new CompressObjectStream(attrs); - } - - static compression(attrs) { - return new Compression(attrs); - } - - static config(attrs) { - return new Config(attrs); - } - - static conformance(attrs) { - return new Conformance(attrs); - } - - static contentCopy(attrs) { - return new ContentCopy(attrs); - } - - static copies(attrs) { - return new Copies(attrs); - } - - static creator(attrs) { - return new Creator(attrs); - } - - static currentPage(attrs) { - return new CurrentPage(attrs); - } - - static data(attrs) { - return new Data(attrs); - } - - static debug(attrs) { - return new Debug(attrs); - } - - static defaultTypeface(attrs) { - return new DefaultTypeface(attrs); - } - - static destination(attrs) { - return new Destination(attrs); - } - - static documentAssembly(attrs) { - return new DocumentAssembly(attrs); - } - - static driver(attrs) { - return new Driver(attrs); - } - - static duplexOption(attrs) { - return new DuplexOption(attrs); - } - - static dynamicRender(attrs) { - return new DynamicRender(attrs); - } - - static embed(attrs) { - return new Embed(attrs); - } - - static encrypt(attrs) { - return new Encrypt(attrs); - } - - static encryption(attrs) { - return new Encryption(attrs); - } - - static encryptionLevel(attrs) { - return new EncryptionLevel(attrs); - } - - static enforce(attrs) { - return new Enforce(attrs); - } - - static equate(attrs) { - return new Equate(attrs); - } - - static equateRange(attrs) { - return new EquateRange(attrs); - } - - static exclude(attrs) { - return new Exclude(attrs); - } - - static excludeNS(attrs) { - return new ExcludeNS(attrs); - } - - static flipLabel(attrs) { - return new FlipLabel(attrs); - } - - static fontInfo(attrs) { - return new FontInfo(attrs); - } - - static formFieldFilling(attrs) { - return new FormFieldFilling(attrs); - } - - static groupParent(attrs) { - return new GroupParent(attrs); - } - - static ifEmpty(attrs) { - return new IfEmpty(attrs); - } - - static includeXDPContent(attrs) { - return new IncludeXDPContent(attrs); - } - - static incrementalLoad(attrs) { - return new IncrementalLoad(attrs); - } - - static incrementalMerge(attrs) { - return new IncrementalMerge(attrs); - } - - static interactive(attrs) { - return new Interactive(attrs); - } - - static jog(attrs) { - return new Jog(attrs); - } - - static labelPrinter(attrs) { - return new LabelPrinter(attrs); - } - - static layout(attrs) { - return new Layout(attrs); - } - - static level(attrs) { - return new Level(attrs); - } - - static linearized(attrs) { - return new Linearized(attrs); - } - - static locale(attrs) { - return new Locale(attrs); - } - - static localeSet(attrs) { - return new LocaleSet(attrs); - } - - static log(attrs) { - return new Log(attrs); - } - - static map(attrs) { - return new MapElement(attrs); - } - - static mediumInfo(attrs) { - return new MediumInfo(attrs); - } - - static message(attrs) { - return new Message(attrs); - } - - static messaging(attrs) { - return new Messaging(attrs); - } - - static mode(attrs) { - return new Mode(attrs); - } - - static modifyAnnots(attrs) { - return new ModifyAnnots(attrs); - } - - static msgId(attrs) { - return new MsgId(attrs); - } - - static nameAttr(attrs) { - return new NameAttr(attrs); - } - - static neverEmbed(attrs) { - return new NeverEmbed(attrs); - } - - static numberOfCopies(attrs) { - return new NumberOfCopies(attrs); - } - - static openAction(attrs) { - return new OpenAction(attrs); - } - - static output(attrs) { - return new Output(attrs); - } - - static outputBin(attrs) { - return new OutputBin(attrs); - } - - static outputXSL(attrs) { - return new OutputXSL(attrs); - } - - static overprint(attrs) { - return new Overprint(attrs); - } - - static packets(attrs) { - return new Packets(attrs); - } - - static pageOffset(attrs) { - return new PageOffset(attrs); - } - - static pageRange(attrs) { - return new PageRange(attrs); - } - - static pagination(attrs) { - return new Pagination(attrs); - } - - static paginationOverride(attrs) { - return new PaginationOverride(attrs); - } - - static part(attrs) { - return new Part(attrs); - } - - static pcl(attrs) { - return new Pcl(attrs); - } - - static pdf(attrs) { - return new Pdf(attrs); - } - - static pdfa(attrs) { - return new Pdfa(attrs); - } - - static permissions(attrs) { - return new Permissions(attrs); - } - - static pickTrayByPDFSize(attrs) { - return new PickTrayByPDFSize(attrs); - } - - static picture(attrs) { - return new Picture(attrs); - } - - static plaintextMetadata(attrs) { - return new PlaintextMetadata(attrs); - } - - static presence(attrs) { - return new Presence(attrs); - } - - static present(attrs) { - return new Present(attrs); - } - - static print(attrs) { - return new Print(attrs); - } - - static printHighQuality(attrs) { - return new PrintHighQuality(attrs); - } - - static printScaling(attrs) { - return new PrintScaling(attrs); - } - - static printerName(attrs) { - return new PrinterName(attrs); - } - - static producer(attrs) { - return new Producer(attrs); - } - - static ps(attrs) { - return new Ps(attrs); - } - - static range(attrs) { - return new Range(attrs); - } - - static record(attrs) { - return new Record(attrs); - } - - static relevant(attrs) { - return new Relevant(attrs); - } - - static rename(attrs) { - return new Rename(attrs); - } - - static renderPolicy(attrs) { - return new RenderPolicy(attrs); - } - - static runScripts(attrs) { - return new RunScripts(attrs); - } - - static script(attrs) { - return new Script(attrs); - } - - static scriptModel(attrs) { - return new ScriptModel(attrs); - } - - static severity(attrs) { - return new Severity(attrs); - } - - static silentPrint(attrs) { - return new SilentPrint(attrs); - } - - static staple(attrs) { - return new Staple(attrs); - } - - static startNode(attrs) { - return new StartNode(attrs); - } - - static startPage(attrs) { - return new StartPage(attrs); - } - - static submitFormat(attrs) { - return new SubmitFormat(attrs); - } - - static submitUrl(attrs) { - return new SubmitUrl(attrs); - } - - static subsetBelow(attrs) { - return new SubsetBelow(attrs); - } - - static suppressBanner(attrs) { - return new SuppressBanner(attrs); - } - - static tagged(attrs) { - return new Tagged(attrs); - } - - static template(attrs) { - return new Template(attrs); - } - - static templateCache(attrs) { - return new TemplateCache(attrs); - } - - static threshold(attrs) { - return new Threshold(attrs); - } - - static to(attrs) { - return new To(attrs); - } - - static trace(attrs) { - return new Trace(attrs); - } - - static transform(attrs) { - return new Transform(attrs); - } - - static type(attrs) { - return new Type(attrs); - } - - static uri(attrs) { - return new Uri(attrs); - } - - static validate(attrs) { - return new Validate(attrs); - } - - static validateApprovalSignatures(attrs) { - return new ValidateApprovalSignatures(attrs); - } - - static validationMessaging(attrs) { - return new ValidationMessaging(attrs); - } - - static version(attrs) { - return new Version(attrs); - } - - static versionControl(attrs) { - return new VersionControl(attrs); - } - - static viewerPreferences(attrs) { - return new ViewerPreferences(attrs); - } - - static webClient(attrs) { - return new WebClient(attrs); - } - - static whitespace(attrs) { - return new Whitespace(attrs); - } - - static window(attrs) { - return new Window(attrs); - } - - static xdc(attrs) { - return new Xdc(attrs); - } - - static xdp(attrs) { - return new Xdp(attrs); - } - - static xsl(attrs) { - return new Xsl(attrs); - } - - static zpl(attrs) { - return new Zpl(attrs); - } - -} - -exports.ConfigNamespace = ConfigNamespace; - -/***/ }), -/* 90 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.ConnectionSetNamespace = void 0; - -var _namespaces = __w_pdfjs_require__(77); - -var _xfa_object = __w_pdfjs_require__(75); - -const CONNECTION_SET_NS_ID = _namespaces.NamespaceIds.connectionSet.id; - -class ConnectionSet extends _xfa_object.XFAObject { - constructor(attributes) { - super(CONNECTION_SET_NS_ID, "connectionSet", true); - this.wsdlConnection = new _xfa_object.XFAObjectArray(); - this.xmlConnection = new _xfa_object.XFAObjectArray(); - this.xsdConnection = new _xfa_object.XFAObjectArray(); - } - -} - -class EffectiveInputPolicy extends _xfa_object.XFAObject { - constructor(attributes) { - super(CONNECTION_SET_NS_ID, "effectiveInputPolicy"); - this.id = attributes.id || ""; - this.name = attributes.name || ""; - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - } - -} - -class EffectiveOutputPolicy extends _xfa_object.XFAObject { - constructor(attributes) { - super(CONNECTION_SET_NS_ID, "effectiveOutputPolicy"); - this.id = attributes.id || ""; - this.name = attributes.name || ""; - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - } - -} - -class Operation extends _xfa_object.StringObject { - constructor(attributes) { - super(CONNECTION_SET_NS_ID, "operation"); - this.id = attributes.id || ""; - this.input = attributes.input || ""; - this.name = attributes.name || ""; - this.output = attributes.output || ""; - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - } - -} - -class RootElement extends _xfa_object.StringObject { - constructor(attributes) { - super(CONNECTION_SET_NS_ID, "rootElement"); - this.id = attributes.id || ""; - this.name = attributes.name || ""; - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - } - -} - -class SoapAction extends _xfa_object.StringObject { - constructor(attributes) { - super(CONNECTION_SET_NS_ID, "soapAction"); - this.id = attributes.id || ""; - this.name = attributes.name || ""; - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - } - -} - -class SoapAddress extends _xfa_object.StringObject { - constructor(attributes) { - super(CONNECTION_SET_NS_ID, "soapAddress"); - this.id = attributes.id || ""; - this.name = attributes.name || ""; - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - } - -} - -class Uri extends _xfa_object.StringObject { - constructor(attributes) { - super(CONNECTION_SET_NS_ID, "uri"); - this.id = attributes.id || ""; - this.name = attributes.name || ""; - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - } - -} - -class WsdlAddress extends _xfa_object.StringObject { - constructor(attributes) { - super(CONNECTION_SET_NS_ID, "wsdlAddress"); - this.id = attributes.id || ""; - this.name = attributes.name || ""; - this.use = attributes.use || ""; - this.usehref = attributes.usehref || ""; - } - -} - -class WsdlConnection extends _xfa_object.XFAObject { - constructor(attributes) { - super(CONNECTION_SET_NS_ID, "wsdlConnection", true); - this.dataDescription = attributes.dataDescription || ""; - this.name = attributes.name || ""; - this.effectiveInputPolicy = null; - this.effectiveOutputPolicy = null; - this.operation = null; - this.soapAction = null; - this.soapAddress = null; - this.wsdlAddress = null; - } - -} - -class XmlConnection extends _xfa_object.XFAObject { - constructor(attributes) { - super(CONNECTION_SET_NS_ID, "xmlConnection", true); - this.dataDescription = attributes.dataDescription || ""; - this.name = attributes.name || ""; - this.uri = null; - } - -} - -class XsdConnection extends _xfa_object.XFAObject { - constructor(attributes) { - super(CONNECTION_SET_NS_ID, "xsdConnection", true); - this.dataDescription = attributes.dataDescription || ""; - this.name = attributes.name || ""; - this.rootElement = null; - this.uri = null; - } - -} - -class ConnectionSetNamespace { - static [_namespaces.$buildXFAObject](name, attributes) { - if (ConnectionSetNamespace.hasOwnProperty(name)) { - return ConnectionSetNamespace[name](attributes); - } - - return undefined; - } - - static connectionSet(attrs) { - return new ConnectionSet(attrs); - } - - static effectiveInputPolicy(attrs) { - return new EffectiveInputPolicy(attrs); - } - - static effectiveOutputPolicy(attrs) { - return new EffectiveOutputPolicy(attrs); - } - - static operation(attrs) { - return new Operation(attrs); - } - - static rootElement(attrs) { - return new RootElement(attrs); - } - - static soapAction(attrs) { - return new SoapAction(attrs); - } - - static soapAddress(attrs) { - return new SoapAddress(attrs); - } - - static uri(attrs) { - return new Uri(attrs); - } - - static wsdlAddress(attrs) { - return new WsdlAddress(attrs); - } - - static wsdlConnection(attrs) { - return new WsdlConnection(attrs); - } - - static xmlConnection(attrs) { - return new XmlConnection(attrs); - } - - static xsdConnection(attrs) { - return new XsdConnection(attrs); - } - -} - -exports.ConnectionSetNamespace = ConnectionSetNamespace; - -/***/ }), -/* 91 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.DatasetsNamespace = void 0; - -var _xfa_object = __w_pdfjs_require__(75); - -var _namespaces = __w_pdfjs_require__(77); - -const DATASETS_NS_ID = _namespaces.NamespaceIds.datasets.id; - -class Data extends _xfa_object.XmlObject { - constructor(attributes) { - super(DATASETS_NS_ID, "data", attributes); - } - - [_xfa_object.$isNsAgnostic]() { - return true; - } - -} - -class Datasets extends _xfa_object.XFAObject { - constructor(attributes) { - super(DATASETS_NS_ID, "datasets", true); - this.data = null; - this.Signature = null; - } - - [_xfa_object.$onChild](child) { - const name = child[_xfa_object.$nodeName]; - - if (name === "data" && child[_xfa_object.$namespaceId] === DATASETS_NS_ID || name === "Signature" && child[_xfa_object.$namespaceId] === _namespaces.NamespaceIds.signature.id) { - this[name] = child; - } - - this[_xfa_object.$appendChild](child); - } - -} - -class DatasetsNamespace { - static [_namespaces.$buildXFAObject](name, attributes) { - if (DatasetsNamespace.hasOwnProperty(name)) { - return DatasetsNamespace[name](attributes); - } - - return undefined; - } - - static datasets(attributes) { - return new Datasets(attributes); - } - - static data(attributes) { - return new Data(attributes); - } - -} - -exports.DatasetsNamespace = DatasetsNamespace; - -/***/ }), -/* 92 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.LocaleSetNamespace = void 0; - -var _namespaces = __w_pdfjs_require__(77); - -var _xfa_object = __w_pdfjs_require__(75); - -var _utils = __w_pdfjs_require__(76); - -const LOCALE_SET_NS_ID = _namespaces.NamespaceIds.localeSet.id; - -class CalendarSymbols extends _xfa_object.XFAObject { - constructor(attributes) { - super(LOCALE_SET_NS_ID, "calendarSymbols", true); - this.name = "gregorian"; - this.dayNames = new _xfa_object.XFAObjectArray(2); - this.eraNames = null; - this.meridiemNames = null; - this.monthNames = new _xfa_object.XFAObjectArray(2); - } - -} - -class CurrencySymbol extends _xfa_object.StringObject { - constructor(attributes) { - super(LOCALE_SET_NS_ID, "currencySymbol"); - this.name = (0, _utils.getStringOption)(attributes.name, ["symbol", "isoname", "decimal"]); - } - -} - -class CurrencySymbols extends _xfa_object.XFAObject { - constructor(attributes) { - super(LOCALE_SET_NS_ID, "currencySymbols", true); - this.currencySymbol = new _xfa_object.XFAObjectArray(3); - } - -} - -class DatePattern extends _xfa_object.StringObject { - constructor(attributes) { - super(LOCALE_SET_NS_ID, "datePattern"); - this.name = (0, _utils.getStringOption)(attributes.name, ["full", "long", "med", "short"]); - } - -} - -class DatePatterns extends _xfa_object.XFAObject { - constructor(attributes) { - super(LOCALE_SET_NS_ID, "datePatterns", true); - this.datePattern = new _xfa_object.XFAObjectArray(4); - } - -} - -class DateTimeSymbols extends _xfa_object.ContentObject { - constructor(attributes) { - super(LOCALE_SET_NS_ID, "dateTimeSymbols"); - } - -} - -class Day extends _xfa_object.StringObject { - constructor(attributes) { - super(LOCALE_SET_NS_ID, "day"); - } - -} - -class DayNames extends _xfa_object.XFAObject { - constructor(attributes) { - super(LOCALE_SET_NS_ID, "dayNames", true); - this.abbr = (0, _utils.getInteger)({ - data: attributes.abbr, - defaultValue: 0, - validate: x => x === 1 - }); - this.day = new _xfa_object.XFAObjectArray(7); - } - -} - -class Era extends _xfa_object.StringObject { - constructor(attributes) { - super(LOCALE_SET_NS_ID, "era"); - } - -} - -class EraNames extends _xfa_object.XFAObject { - constructor(attributes) { - super(LOCALE_SET_NS_ID, "eraNames", true); - this.era = new _xfa_object.XFAObjectArray(2); - } - -} - -class Locale extends _xfa_object.XFAObject { - constructor(attributes) { - super(LOCALE_SET_NS_ID, "locale", true); - this.desc = attributes.desc || ""; - this.name = "isoname"; - this.calendarSymbols = null; - this.currencySymbols = null; - this.datePatterns = null; - this.dateTimeSymbols = null; - this.numberPatterns = null; - this.numberSymbols = null; - this.timePatterns = null; - this.typeFaces = null; - } - -} - -class LocaleSet extends _xfa_object.XFAObject { - constructor(attributes) { - super(LOCALE_SET_NS_ID, "localeSet", true); - this.locale = new _xfa_object.XFAObjectArray(); - } - -} - -class Meridiem extends _xfa_object.StringObject { - constructor(attributes) { - super(LOCALE_SET_NS_ID, "meridiem"); - } - -} - -class MeridiemNames extends _xfa_object.XFAObject { - constructor(attributes) { - super(LOCALE_SET_NS_ID, "meridiemNames", true); - this.meridiem = new _xfa_object.XFAObjectArray(2); - } - -} - -class Month extends _xfa_object.StringObject { - constructor(attributes) { - super(LOCALE_SET_NS_ID, "month"); - } - -} - -class MonthNames extends _xfa_object.XFAObject { - constructor(attributes) { - super(LOCALE_SET_NS_ID, "monthNames", true); - this.abbr = (0, _utils.getInteger)({ - data: attributes.abbr, - defaultValue: 0, - validate: x => x === 1 - }); - this.month = new _xfa_object.XFAObjectArray(12); - } - -} - -class NumberPattern extends _xfa_object.StringObject { - constructor(attributes) { - super(LOCALE_SET_NS_ID, "numberPattern"); - this.name = (0, _utils.getStringOption)(attributes.name, ["full", "long", "med", "short"]); - } - -} - -class NumberPatterns extends _xfa_object.XFAObject { - constructor(attributes) { - super(LOCALE_SET_NS_ID, "numberPatterns", true); - this.numberPattern = new _xfa_object.XFAObjectArray(4); - } - -} - -class NumberSymbol extends _xfa_object.StringObject { - constructor(attributes) { - super(LOCALE_SET_NS_ID, "numberSymbol"); - this.name = (0, _utils.getStringOption)(attributes.name, ["decimal", "grouping", "percent", "minus", "zero"]); - } - -} - -class NumberSymbols extends _xfa_object.XFAObject { - constructor(attributes) { - super(LOCALE_SET_NS_ID, "numberSymbols", true); - this.numberSymbol = new _xfa_object.XFAObjectArray(5); - } - -} - -class TimePattern extends _xfa_object.StringObject { - constructor(attributes) { - super(LOCALE_SET_NS_ID, "timePattern"); - this.name = (0, _utils.getStringOption)(attributes.name, ["full", "long", "med", "short"]); - } - -} - -class TimePatterns extends _xfa_object.XFAObject { - constructor(attributes) { - super(LOCALE_SET_NS_ID, "timePatterns", true); - this.timePattern = new _xfa_object.XFAObjectArray(4); - } - -} - -class TypeFace extends _xfa_object.XFAObject { - constructor(attributes) { - super(LOCALE_SET_NS_ID, "typeFace", true); - this.name = attributes.name | ""; - } - -} - -class TypeFaces extends _xfa_object.XFAObject { - constructor(attributes) { - super(LOCALE_SET_NS_ID, "typeFaces", true); - this.typeFace = new _xfa_object.XFAObjectArray(); - } - -} - -class LocaleSetNamespace { - static [_namespaces.$buildXFAObject](name, attributes) { - if (LocaleSetNamespace.hasOwnProperty(name)) { - return LocaleSetNamespace[name](attributes); - } - - return undefined; - } - - static calendarSymbols(attrs) { - return new CalendarSymbols(attrs); - } - - static currencySymbol(attrs) { - return new CurrencySymbol(attrs); - } - - static currencySymbols(attrs) { - return new CurrencySymbols(attrs); - } - - static datePattern(attrs) { - return new DatePattern(attrs); - } - - static datePatterns(attrs) { - return new DatePatterns(attrs); - } - - static dateTimeSymbols(attrs) { - return new DateTimeSymbols(attrs); - } - - static day(attrs) { - return new Day(attrs); - } - - static dayNames(attrs) { - return new DayNames(attrs); - } - - static era(attrs) { - return new Era(attrs); - } - - static eraNames(attrs) { - return new EraNames(attrs); - } - - static locale(attrs) { - return new Locale(attrs); - } - - static localeSet(attrs) { - return new LocaleSet(attrs); - } - - static meridiem(attrs) { - return new Meridiem(attrs); - } - - static meridiemNames(attrs) { - return new MeridiemNames(attrs); - } - - static month(attrs) { - return new Month(attrs); - } - - static monthNames(attrs) { - return new MonthNames(attrs); - } - - static numberPattern(attrs) { - return new NumberPattern(attrs); - } - - static numberPatterns(attrs) { - return new NumberPatterns(attrs); - } - - static numberSymbol(attrs) { - return new NumberSymbol(attrs); - } - - static numberSymbols(attrs) { - return new NumberSymbols(attrs); - } - - static timePattern(attrs) { - return new TimePattern(attrs); - } - - static timePatterns(attrs) { - return new TimePatterns(attrs); - } - - static typeFace(attrs) { - return new TypeFace(attrs); - } - - static typeFaces(attrs) { - return new TypeFaces(attrs); - } - -} - -exports.LocaleSetNamespace = LocaleSetNamespace; - -/***/ }), -/* 93 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.SignatureNamespace = void 0; - -var _namespaces = __w_pdfjs_require__(77); - -var _xfa_object = __w_pdfjs_require__(75); - -const SIGNATURE_NS_ID = _namespaces.NamespaceIds.signature.id; - -class Signature extends _xfa_object.XFAObject { - constructor(attributes) { - super(SIGNATURE_NS_ID, "signature", true); - } - -} - -class SignatureNamespace { - static [_namespaces.$buildXFAObject](name, attributes) { - if (SignatureNamespace.hasOwnProperty(name)) { - return SignatureNamespace[name](attributes); - } - - return undefined; - } - - static signature(attributes) { - return new Signature(attributes); - } - -} - -exports.SignatureNamespace = SignatureNamespace; - -/***/ }), -/* 94 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.StylesheetNamespace = void 0; - -var _namespaces = __w_pdfjs_require__(77); - -var _xfa_object = __w_pdfjs_require__(75); - -const STYLESHEET_NS_ID = _namespaces.NamespaceIds.stylesheet.id; - -class Stylesheet extends _xfa_object.XFAObject { - constructor(attributes) { - super(STYLESHEET_NS_ID, "stylesheet", true); - } - -} - -class StylesheetNamespace { - static [_namespaces.$buildXFAObject](name, attributes) { - if (StylesheetNamespace.hasOwnProperty(name)) { - return StylesheetNamespace[name](attributes); - } - - return undefined; - } - - static stylesheet(attributes) { - return new Stylesheet(attributes); - } - -} - -exports.StylesheetNamespace = StylesheetNamespace; - -/***/ }), -/* 95 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.XdpNamespace = void 0; - -var _namespaces = __w_pdfjs_require__(77); - -var _xfa_object = __w_pdfjs_require__(75); - -const XDP_NS_ID = _namespaces.NamespaceIds.xdp.id; - -class Xdp extends _xfa_object.XFAObject { - constructor(attributes) { - super(XDP_NS_ID, "xdp", true); - this.uuid = attributes.uuid || ""; - this.timeStamp = attributes.timeStamp || ""; - this.config = null; - this.connectionSet = null; - this.datasets = null; - this.localeSet = null; - this.stylesheet = new _xfa_object.XFAObjectArray(); - this.template = null; - } - - [_xfa_object.$onChildCheck](child) { - const ns = _namespaces.NamespaceIds[child[_xfa_object.$nodeName]]; - return ns && child[_xfa_object.$namespaceId] === ns.id; - } - -} - -class XdpNamespace { - static [_namespaces.$buildXFAObject](name, attributes) { - if (XdpNamespace.hasOwnProperty(name)) { - return XdpNamespace[name](attributes); - } - - return undefined; - } - - static xdp(attributes) { - return new Xdp(attributes); - } - -} - -exports.XdpNamespace = XdpNamespace; - -/***/ }), -/* 96 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.XhtmlNamespace = void 0; - -var _xfa_object = __w_pdfjs_require__(75); - -var _namespaces = __w_pdfjs_require__(77); - -var _html_utils = __w_pdfjs_require__(82); - -var _utils = __w_pdfjs_require__(76); - -const XHTML_NS_ID = _namespaces.NamespaceIds.xhtml.id; -const $richText = Symbol(); -const VALID_STYLES = new Set(["color", "font", "font-family", "font-size", "font-stretch", "font-style", "font-weight", "margin", "margin-bottom", "margin-left", "margin-right", "margin-top", "letter-spacing", "line-height", "orphans", "page-break-after", "page-break-before", "page-break-inside", "tab-interval", "tab-stop", "text-align", "text-decoration", "text-indent", "vertical-align", "widows", "kerning-mode", "xfa-font-horizontal-scale", "xfa-font-vertical-scale", "xfa-spacerun", "xfa-tab-stops"]); -const StyleMapping = new Map([["page-break-after", "breakAfter"], ["page-break-before", "breakBefore"], ["page-break-inside", "breakInside"], ["kerning-mode", value => value === "none" ? "none" : "normal"], ["xfa-font-horizontal-scale", value => `scaleX(${Math.max(0, Math.min(parseInt(value) / 100)).toFixed(2)})`], ["xfa-font-vertical-scale", value => `scaleY(${Math.max(0, Math.min(parseInt(value) / 100)).toFixed(2)})`], ["xfa-spacerun", ""], ["xfa-tab-stops", ""], ["font-size", (value, original) => { - value = original.fontSize = (0, _utils.getMeasurement)(value); - return (0, _html_utils.measureToString)(0.99 * value); -}], ["letter-spacing", value => (0, _html_utils.measureToString)((0, _utils.getMeasurement)(value))], ["line-height", value => (0, _html_utils.measureToString)((0, _utils.getMeasurement)(value))], ["margin", value => (0, _html_utils.measureToString)((0, _utils.getMeasurement)(value))], ["margin-bottom", value => (0, _html_utils.measureToString)((0, _utils.getMeasurement)(value))], ["margin-left", value => (0, _html_utils.measureToString)((0, _utils.getMeasurement)(value))], ["margin-right", value => (0, _html_utils.measureToString)((0, _utils.getMeasurement)(value))], ["margin-top", value => (0, _html_utils.measureToString)((0, _utils.getMeasurement)(value))], ["text-indent", value => (0, _html_utils.measureToString)((0, _utils.getMeasurement)(value))], ["font-family", value => value], ["vertical-align", value => (0, _html_utils.measureToString)((0, _utils.getMeasurement)(value))]]); -const spacesRegExp = /\s+/g; -const crlfRegExp = /[\r\n]+/g; -const crlfForRichTextRegExp = /\r\n?/g; - -function mapStyle(styleStr, node, richText) { - const style = Object.create(null); - - if (!styleStr) { - return style; - } - - const original = Object.create(null); - - for (const [key, value] of styleStr.split(";").map(s => s.split(":", 2))) { - const mapping = StyleMapping.get(key); - - if (mapping === "") { - continue; - } - - let newValue = value; - - if (mapping) { - if (typeof mapping === "string") { - newValue = mapping; - } else { - newValue = mapping(value, original); - } - } - - if (key.endsWith("scale")) { - if (style.transform) { - style.transform = `${style[key]} ${newValue}`; - } else { - style.transform = newValue; - } - } else { - style[key.replaceAll(/-([a-zA-Z])/g, (_, x) => x.toUpperCase())] = newValue; - } - } - - if (style.fontFamily) { - (0, _html_utils.setFontFamily)({ - typeface: style.fontFamily, - weight: style.fontWeight || "normal", - posture: style.fontStyle || "normal", - size: original.fontSize || 0 - }, node, node[_xfa_object.$globalData].fontFinder, style); - } - - if (richText && style.verticalAlign && style.verticalAlign !== "0px" && style.fontSize) { - const SUB_SUPER_SCRIPT_FACTOR = 0.583; - const VERTICAL_FACTOR = 0.333; - const fontSize = (0, _utils.getMeasurement)(style.fontSize); - style.fontSize = (0, _html_utils.measureToString)(fontSize * SUB_SUPER_SCRIPT_FACTOR); - style.verticalAlign = (0, _html_utils.measureToString)(Math.sign((0, _utils.getMeasurement)(style.verticalAlign)) * fontSize * VERTICAL_FACTOR); - } - - (0, _html_utils.fixTextIndent)(style); - return style; -} - -function checkStyle(node) { - if (!node.style) { - return ""; - } - - return node.style.trim().split(/\s*;\s*/).filter(s => !!s).map(s => s.split(/\s*:\s*/, 2)).filter(([key, value]) => { - if (key === "font-family") { - node[_xfa_object.$globalData].usedTypefaces.add(value); - } - - return VALID_STYLES.has(key); - }).map(kv => kv.join(":")).join(";"); -} - -const NoWhites = new Set(["body", "html"]); - -class XhtmlObject extends _xfa_object.XmlObject { - constructor(attributes, name) { - super(XHTML_NS_ID, name); - this[$richText] = false; - this.style = attributes.style || ""; - } - - [_xfa_object.$clean](builder) { - super[_xfa_object.$clean](builder); - - this.style = checkStyle(this); - } - - [_xfa_object.$acceptWhitespace]() { - return !NoWhites.has(this[_xfa_object.$nodeName]); - } - - [_xfa_object.$onText](str, richText = false) { - if (!richText) { - str = str.replace(crlfRegExp, ""); - - if (!this.style.includes("xfa-spacerun:yes")) { - str = str.replace(spacesRegExp, " "); - } - } else { - this[$richText] = true; - } - - if (str) { - this[_xfa_object.$content] += str; - } - } - - [_xfa_object.$pushGlyphs](measure, mustPop = true) { - const xfaFont = Object.create(null); - const margin = { - top: NaN, - bottom: NaN, - left: NaN, - right: NaN - }; - let lineHeight = null; - - for (const [key, value] of this.style.split(";").map(s => s.split(":", 2))) { - switch (key) { - case "font-family": - xfaFont.typeface = (0, _utils.stripQuotes)(value); - break; - - case "font-size": - xfaFont.size = (0, _utils.getMeasurement)(value); - break; - - case "font-weight": - xfaFont.weight = value; - break; - - case "font-style": - xfaFont.posture = value; - break; - - case "letter-spacing": - xfaFont.letterSpacing = (0, _utils.getMeasurement)(value); - break; - - case "margin": - const values = value.split(/ \t/).map(x => (0, _utils.getMeasurement)(x)); - - switch (values.length) { - case 1: - margin.top = margin.bottom = margin.left = margin.right = values[0]; - break; - - case 2: - margin.top = margin.bottom = values[0]; - margin.left = margin.right = values[1]; - break; - - case 3: - margin.top = values[0]; - margin.bottom = values[2]; - margin.left = margin.right = values[1]; - break; - - case 4: - margin.top = values[0]; - margin.left = values[1]; - margin.bottom = values[2]; - margin.right = values[3]; - break; - } - - break; - - case "margin-top": - margin.top = (0, _utils.getMeasurement)(value); - break; - - case "margin-bottom": - margin.bottom = (0, _utils.getMeasurement)(value); - break; - - case "margin-left": - margin.left = (0, _utils.getMeasurement)(value); - break; - - case "margin-right": - margin.right = (0, _utils.getMeasurement)(value); - break; - - case "line-height": - lineHeight = (0, _utils.getMeasurement)(value); - break; - } - } - - measure.pushData(xfaFont, margin, lineHeight); - - if (this[_xfa_object.$content]) { - measure.addString(this[_xfa_object.$content]); - } else { - for (const child of this[_xfa_object.$getChildren]()) { - if (child[_xfa_object.$nodeName] === "#text") { - measure.addString(child[_xfa_object.$content]); - continue; - } - - child[_xfa_object.$pushGlyphs](measure); - } - } - - if (mustPop) { - measure.popFont(); - } - } - - [_xfa_object.$toHTML](availableSpace) { - const children = []; - this[_xfa_object.$extra] = { - children - }; - - this[_xfa_object.$childrenToHTML]({}); - - if (children.length === 0 && !this[_xfa_object.$content]) { - return _utils.HTMLResult.EMPTY; - } - - let value; - - if (this[$richText]) { - value = this[_xfa_object.$content] ? this[_xfa_object.$content].replace(crlfForRichTextRegExp, "\n") : undefined; - } else { - value = this[_xfa_object.$content] || undefined; - } - - return _utils.HTMLResult.success({ - name: this[_xfa_object.$nodeName], - attributes: { - href: this.href, - style: mapStyle(this.style, this, this[$richText]) - }, - children, - value - }); - } - -} - -class A extends XhtmlObject { - constructor(attributes) { - super(attributes, "a"); - this.href = (0, _html_utils.fixURL)(attributes.href) || ""; - } - -} - -class B extends XhtmlObject { - constructor(attributes) { - super(attributes, "b"); - } - - [_xfa_object.$pushGlyphs](measure) { - measure.pushFont({ - weight: "bold" - }); - - super[_xfa_object.$pushGlyphs](measure); - - measure.popFont(); - } - -} - -class Body extends XhtmlObject { - constructor(attributes) { - super(attributes, "body"); - } - - [_xfa_object.$toHTML](availableSpace) { - const res = super[_xfa_object.$toHTML](availableSpace); - - const { - html - } = res; - - if (!html) { - return _utils.HTMLResult.EMPTY; - } - - html.name = "div"; - html.attributes.class = ["xfaRich"]; - return res; - } - -} - -class Br extends XhtmlObject { - constructor(attributes) { - super(attributes, "br"); - } - - [_xfa_object.$text]() { - return "\n"; - } - - [_xfa_object.$pushGlyphs](measure) { - measure.addString("\n"); - } - - [_xfa_object.$toHTML](availableSpace) { - return _utils.HTMLResult.success({ - name: "br" - }); - } - -} - -class Html extends XhtmlObject { - constructor(attributes) { - super(attributes, "html"); - } - - [_xfa_object.$toHTML](availableSpace) { - const children = []; - this[_xfa_object.$extra] = { - children - }; - - this[_xfa_object.$childrenToHTML]({}); - - if (children.length === 0) { - return _utils.HTMLResult.success({ - name: "div", - attributes: { - class: ["xfaRich"], - style: {} - }, - value: this[_xfa_object.$content] || "" - }); - } - - if (children.length === 1) { - const child = children[0]; - - if (child.attributes && child.attributes.class.includes("xfaRich")) { - return _utils.HTMLResult.success(child); - } - } - - return _utils.HTMLResult.success({ - name: "div", - attributes: { - class: ["xfaRich"], - style: {} - }, - children - }); - } - -} - -class I extends XhtmlObject { - constructor(attributes) { - super(attributes, "i"); - } - - [_xfa_object.$pushGlyphs](measure) { - measure.pushFont({ - posture: "italic" - }); - - super[_xfa_object.$pushGlyphs](measure); - - measure.popFont(); - } - -} - -class Li extends XhtmlObject { - constructor(attributes) { - super(attributes, "li"); - } - -} - -class Ol extends XhtmlObject { - constructor(attributes) { - super(attributes, "ol"); - } - -} - -class P extends XhtmlObject { - constructor(attributes) { - super(attributes, "p"); - } - - [_xfa_object.$pushGlyphs](measure) { - super[_xfa_object.$pushGlyphs](measure, false); - - measure.addString("\n"); - measure.addPara(); - measure.popFont(); - } - - [_xfa_object.$text]() { - const siblings = this[_xfa_object.$getParent]()[_xfa_object.$getChildren](); - - if (siblings[siblings.length - 1] === this) { - return super[_xfa_object.$text](); - } - - return super[_xfa_object.$text]() + "\n"; - } - -} - -class Span extends XhtmlObject { - constructor(attributes) { - super(attributes, "span"); - } - -} - -class Sub extends XhtmlObject { - constructor(attributes) { - super(attributes, "sub"); - } - -} - -class Sup extends XhtmlObject { - constructor(attributes) { - super(attributes, "sup"); - } - -} - -class Ul extends XhtmlObject { - constructor(attributes) { - super(attributes, "ul"); - } - -} - -class XhtmlNamespace { - static [_namespaces.$buildXFAObject](name, attributes) { - if (XhtmlNamespace.hasOwnProperty(name)) { - return XhtmlNamespace[name](attributes); - } - - return undefined; - } - - static a(attributes) { - return new A(attributes); - } - - static b(attributes) { - return new B(attributes); - } - - static body(attributes) { - return new Body(attributes); - } - - static br(attributes) { - return new Br(attributes); - } - - static html(attributes) { - return new Html(attributes); - } - - static i(attributes) { - return new I(attributes); - } - - static li(attributes) { - return new Li(attributes); - } - - static ol(attributes) { - return new Ol(attributes); - } - - static p(attributes) { - return new P(attributes); - } - - static span(attributes) { - return new Span(attributes); - } - - static sub(attributes) { - return new Sub(attributes); - } - - static sup(attributes) { - return new Sup(attributes); - } - - static ul(attributes) { - return new Ul(attributes); - } - -} - -exports.XhtmlNamespace = XhtmlNamespace; - -/***/ }), -/* 97 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.UnknownNamespace = void 0; - -var _namespaces = __w_pdfjs_require__(77); - -var _xfa_object = __w_pdfjs_require__(75); - -class UnknownNamespace { - constructor(nsId) { - this.namespaceId = nsId; - } - - [_namespaces.$buildXFAObject](name, attributes) { - return new _xfa_object.XmlObject(this.namespaceId, name, attributes); - } - -} - -exports.UnknownNamespace = UnknownNamespace; - -/***/ }), -/* 98 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.XRef = void 0; - -var _util = __w_pdfjs_require__(2); - -var _primitives = __w_pdfjs_require__(5); - -var _core_utils = __w_pdfjs_require__(9); - -var _parser = __w_pdfjs_require__(27); - -var _base_stream = __w_pdfjs_require__(6); - -var _crypto = __w_pdfjs_require__(72); - -class XRef { - constructor(stream, pdfManager) { - this.stream = stream; - this.pdfManager = pdfManager; - this.entries = []; - this.xrefstms = Object.create(null); - this._cacheMap = new Map(); - this._pendingRefs = new _primitives.RefSet(); - this.stats = new _core_utils.DocStats(pdfManager.msgHandler); - this._newRefNum = null; - } - - getNewRef() { - if (this._newRefNum === null) { - this._newRefNum = this.entries.length; - } - - return _primitives.Ref.get(this._newRefNum++, 0); - } - - resetNewRef() { - this._newRefNum = null; - } - - setStartXRef(startXRef) { - this.startXRefQueue = [startXRef]; - } - - parse(recoveryMode = false) { - let trailerDict; - - if (!recoveryMode) { - trailerDict = this.readXRef(); - } else { - (0, _util.warn)("Indexing all PDF objects"); - trailerDict = this.indexObjects(); - } - - trailerDict.assignXref(this); - this.trailer = trailerDict; - let encrypt; - - try { - encrypt = trailerDict.get("Encrypt"); - } catch (ex) { - if (ex instanceof _core_utils.MissingDataException) { - throw ex; - } - - (0, _util.warn)(`XRef.parse - Invalid "Encrypt" reference: "${ex}".`); - } - - if (encrypt instanceof _primitives.Dict) { - const ids = trailerDict.get("ID"); - const fileId = ids && ids.length ? ids[0] : ""; - encrypt.suppressEncryption = true; - this.encrypt = new _crypto.CipherTransformFactory(encrypt, fileId, this.pdfManager.password); - } - - let root; - - try { - root = trailerDict.get("Root"); - } catch (ex) { - if (ex instanceof _core_utils.MissingDataException) { - throw ex; - } - - (0, _util.warn)(`XRef.parse - Invalid "Root" reference: "${ex}".`); - } - - if (root instanceof _primitives.Dict) { - try { - const pages = root.get("Pages"); - - if (pages instanceof _primitives.Dict) { - this.root = root; - return; - } - } catch (ex) { - if (ex instanceof _core_utils.MissingDataException) { - throw ex; - } - - (0, _util.warn)(`XRef.parse - Invalid "Pages" reference: "${ex}".`); - } - } - - if (!recoveryMode) { - throw new _core_utils.XRefParseException(); - } - - throw new _util.InvalidPDFException("Invalid Root reference."); - } - - processXRefTable(parser) { - if (!("tableState" in this)) { - this.tableState = { - entryNum: 0, - streamPos: parser.lexer.stream.pos, - parserBuf1: parser.buf1, - parserBuf2: parser.buf2 - }; - } - - const obj = this.readXRefTable(parser); - - if (!(0, _primitives.isCmd)(obj, "trailer")) { - throw new _util.FormatError("Invalid XRef table: could not find trailer dictionary"); - } - - let dict = parser.getObj(); - - if (!(dict instanceof _primitives.Dict) && dict.dict) { - dict = dict.dict; - } - - if (!(dict instanceof _primitives.Dict)) { - throw new _util.FormatError("Invalid XRef table: could not parse trailer dictionary"); - } - - delete this.tableState; - return dict; - } - - readXRefTable(parser) { - const stream = parser.lexer.stream; - const tableState = this.tableState; - stream.pos = tableState.streamPos; - parser.buf1 = tableState.parserBuf1; - parser.buf2 = tableState.parserBuf2; - let obj; - - while (true) { - if (!("firstEntryNum" in tableState) || !("entryCount" in tableState)) { - if ((0, _primitives.isCmd)(obj = parser.getObj(), "trailer")) { - break; - } - - tableState.firstEntryNum = obj; - tableState.entryCount = parser.getObj(); - } - - let first = tableState.firstEntryNum; - const count = tableState.entryCount; - - if (!Number.isInteger(first) || !Number.isInteger(count)) { - throw new _util.FormatError("Invalid XRef table: wrong types in subsection header"); - } - - for (let i = tableState.entryNum; i < count; i++) { - tableState.streamPos = stream.pos; - tableState.entryNum = i; - tableState.parserBuf1 = parser.buf1; - tableState.parserBuf2 = parser.buf2; - const entry = {}; - entry.offset = parser.getObj(); - entry.gen = parser.getObj(); - const type = parser.getObj(); - - if (type instanceof _primitives.Cmd) { - switch (type.cmd) { - case "f": - entry.free = true; - break; - - case "n": - entry.uncompressed = true; - break; - } - } - - if (!Number.isInteger(entry.offset) || !Number.isInteger(entry.gen) || !(entry.free || entry.uncompressed)) { - throw new _util.FormatError(`Invalid entry in XRef subsection: ${first}, ${count}`); - } - - if (i === 0 && entry.free && first === 1) { - first = 0; - } - - 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; - } - - if (this.entries[0] && !this.entries[0].free) { - throw new _util.FormatError("Invalid XRef table: unexpected first object"); - } - - return obj; - } - - processXRefStream(stream) { - if (!("streamState" in this)) { - const streamParameters = stream.dict; - const byteWidths = streamParameters.get("W"); - let range = streamParameters.get("Index"); - - if (!range) { - range = [0, streamParameters.get("Size")]; - } - - this.streamState = { - entryRanges: range, - byteWidths, - entryNum: 0, - streamPos: stream.pos - }; - } - - this.readXRefStream(stream); - delete this.streamState; - return stream.dict; - } - - readXRefStream(stream) { - const streamState = this.streamState; - stream.pos = streamState.streamPos; - const [typeFieldWidth, offsetFieldWidth, generationFieldWidth] = streamState.byteWidths; - const entryRanges = streamState.entryRanges; - - while (entryRanges.length > 0) { - const [first, n] = entryRanges; - - if (!Number.isInteger(first) || !Number.isInteger(n)) { - throw new _util.FormatError(`Invalid XRef range fields: ${first}, ${n}`); - } - - if (!Number.isInteger(typeFieldWidth) || !Number.isInteger(offsetFieldWidth) || !Number.isInteger(generationFieldWidth)) { - throw new _util.FormatError(`Invalid XRef entry fields length: ${first}, ${n}`); - } - - for (let i = streamState.entryNum; i < n; ++i) { - streamState.entryNum = i; - streamState.streamPos = stream.pos; - let type = 0, - offset = 0, - generation = 0; - - for (let j = 0; j < typeFieldWidth; ++j) { - const typeByte = stream.getByte(); - - if (typeByte === -1) { - throw new _util.FormatError("Invalid XRef byteWidths 'type'."); - } - - type = type << 8 | typeByte; - } - - if (typeFieldWidth === 0) { - type = 1; - } - - for (let j = 0; j < offsetFieldWidth; ++j) { - const offsetByte = stream.getByte(); - - if (offsetByte === -1) { - throw new _util.FormatError("Invalid XRef byteWidths 'offset'."); - } - - offset = offset << 8 | offsetByte; - } - - for (let j = 0; j < generationFieldWidth; ++j) { - const generationByte = stream.getByte(); - - if (generationByte === -1) { - throw new _util.FormatError("Invalid XRef byteWidths 'generation'."); - } - - generation = generation << 8 | generationByte; - } - - const 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: - throw new _util.FormatError(`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() { - const TAB = 0x9, - LF = 0xa, - CR = 0xd, - SPACE = 0x20; - const PERCENT = 0x25, - LT = 0x3c; - - function readToken(data, offset) { - let token = "", - ch = data[offset]; - - while (ch !== LF && ch !== CR && ch !== LT) { - if (++offset >= data.length) { - break; - } - - token += String.fromCharCode(ch); - ch = data[offset]; - } - - return token; - } - - function skipUntil(data, offset, what) { - const length = what.length, - dataLength = data.length; - let skipped = 0; - - while (offset < dataLength) { - let i = 0; - - while (i < length && data[offset + i] === what[i]) { - ++i; - } - - if (i >= length) { - break; - } - - offset++; - skipped++; - } - - return skipped; - } - - const objRegExp = /^(\d+)\s+(\d+)\s+obj\b/; - const endobjRegExp = /\bendobj[\b\s]$/; - const nestedObjRegExp = /\s+(\d+\s+\d+\s+obj[\b\s<])$/; - const CHECK_CONTENT_LENGTH = 25; - const trailerBytes = new Uint8Array([116, 114, 97, 105, 108, 101, 114]); - const startxrefBytes = new Uint8Array([115, 116, 97, 114, 116, 120, 114, 101, 102]); - const objBytes = new Uint8Array([111, 98, 106]); - const xrefBytes = new Uint8Array([47, 88, 82, 101, 102]); - this.entries.length = 0; - - this._cacheMap.clear(); - - const stream = this.stream; - stream.pos = 0; - const buffer = stream.getBytes(), - length = buffer.length; - let position = stream.start; - const trailers = [], - xrefStms = []; - - while (position < length) { - let ch = buffer[position]; - - if (ch === TAB || ch === LF || ch === CR || ch === SPACE) { - ++position; - continue; - } - - if (ch === PERCENT) { - do { - ++position; - - if (position >= length) { - break; - } - - ch = buffer[position]; - } while (ch !== LF && ch !== CR); - - continue; - } - - const token = readToken(buffer, position); - let m; - - if (token.startsWith("xref") && (token.length === 4 || /\s/.test(token[4]))) { - position += skipUntil(buffer, position, trailerBytes); - trailers.push(position); - position += skipUntil(buffer, position, startxrefBytes); - } else if (m = objRegExp.exec(token)) { - const num = m[1] | 0, - gen = m[2] | 0; - let contentLength, - startPos = position + token.length, - updateEntries = false; - - if (!this.entries[num]) { - updateEntries = true; - } else if (this.entries[num].gen === gen) { - try { - const parser = new _parser.Parser({ - lexer: new _parser.Lexer(stream.makeSubStream(startPos)) - }); - parser.getObj(); - updateEntries = true; - } catch (ex) { - if (ex instanceof _core_utils.ParserEOFException) { - (0, _util.warn)(`indexObjects -- checking object (${token}): "${ex}".`); - } else { - updateEntries = true; - } - } - } - - if (updateEntries) { - this.entries[num] = { - offset: position - stream.start, - gen, - uncompressed: true - }; - } - - while (startPos < buffer.length) { - const endPos = startPos + skipUntil(buffer, startPos, objBytes) + 4; - contentLength = endPos - position; - const checkPos = Math.max(endPos - CHECK_CONTENT_LENGTH, startPos); - const tokenStr = (0, _util.bytesToString)(buffer.subarray(checkPos, endPos)); - - if (endobjRegExp.test(tokenStr)) { - break; - } else { - const objToken = nestedObjRegExp.exec(tokenStr); - - if (objToken && objToken[1]) { - (0, _util.warn)('indexObjects: Found new "obj" inside of another "obj", ' + 'caused by missing "endobj" -- trying to recover.'); - contentLength -= objToken[1].length; - break; - } - } - - startPos = endPos; - } - - const content = buffer.subarray(position, position + contentLength); - const xrefTagOffset = skipUntil(content, 0, xrefBytes); - - if (xrefTagOffset < contentLength && content[xrefTagOffset + 5] < 64) { - xrefStms.push(position - stream.start); - this.xrefstms[position - stream.start] = 1; - } - - position += contentLength; - } else if (token.startsWith("trailer") && (token.length === 7 || /\s/.test(token[7]))) { - trailers.push(position); - position += skipUntil(buffer, position, startxrefBytes); - } else { - position += token.length + 1; - } - } - - for (let i = 0, ii = xrefStms.length; i < ii; ++i) { - this.startXRefQueue.push(xrefStms[i]); - this.readXRef(true); - } - - let trailerDict; - - for (let i = 0, ii = trailers.length; i < ii; ++i) { - stream.pos = trailers[i]; - const parser = new _parser.Parser({ - lexer: new _parser.Lexer(stream), - xref: this, - allowStreams: true, - recoveryMode: true - }); - const obj = parser.getObj(); - - if (!(0, _primitives.isCmd)(obj, "trailer")) { - continue; - } - - const dict = parser.getObj(); - - if (!(dict instanceof _primitives.Dict)) { - continue; - } - - try { - const rootDict = dict.get("Root"); - - if (!(rootDict instanceof _primitives.Dict)) { - continue; - } - - const pagesDict = rootDict.get("Pages"); - - if (!(pagesDict instanceof _primitives.Dict)) { - continue; - } - - const pagesCount = pagesDict.get("Count"); - - if (!Number.isInteger(pagesCount)) { - continue; - } - } catch (ex) { - continue; - } - - if (dict.has("ID")) { - return dict; - } - - trailerDict = dict; - } - - if (trailerDict) { - return trailerDict; - } - - if (this.topDict) { - return this.topDict; - } - - throw new _util.InvalidPDFException("Invalid PDF structure."); - } - - readXRef(recoveryMode = false) { - const stream = this.stream; - const startXRefParsedCache = new Set(); - - try { - while (this.startXRefQueue.length) { - const startXRef = this.startXRefQueue[0]; - - if (startXRefParsedCache.has(startXRef)) { - (0, _util.warn)("readXRef - skipping XRef table since it was already parsed."); - this.startXRefQueue.shift(); - continue; - } - - startXRefParsedCache.add(startXRef); - stream.pos = startXRef + stream.start; - const parser = new _parser.Parser({ - lexer: new _parser.Lexer(stream), - xref: this, - allowStreams: true - }); - let obj = parser.getObj(); - let dict; - - if ((0, _primitives.isCmd)(obj, "xref")) { - dict = this.processXRefTable(parser); - - if (!this.topDict) { - this.topDict = dict; - } - - obj = dict.get("XRefStm"); - - if (Number.isInteger(obj)) { - const pos = obj; - - if (!(pos in this.xrefstms)) { - this.xrefstms[pos] = 1; - this.startXRefQueue.push(pos); - } - } - } else if (Number.isInteger(obj)) { - if (!Number.isInteger(parser.getObj()) || !(0, _primitives.isCmd)(parser.getObj(), "obj") || !((obj = parser.getObj()) instanceof _base_stream.BaseStream)) { - throw new _util.FormatError("Invalid XRef stream"); - } - - dict = this.processXRefStream(obj); - - if (!this.topDict) { - this.topDict = dict; - } - - if (!dict) { - throw new _util.FormatError("Failed to read XRef stream"); - } - } else { - throw new _util.FormatError("Invalid XRef stream header"); - } - - obj = dict.get("Prev"); - - if (Number.isInteger(obj)) { - this.startXRefQueue.push(obj); - } else if (obj instanceof _primitives.Ref) { - this.startXRefQueue.push(obj.num); - } - - this.startXRefQueue.shift(); - } - - return this.topDict; - } catch (e) { - if (e instanceof _core_utils.MissingDataException) { - throw e; - } - - (0, _util.info)("(while reading XRef): " + e); - this.startXRefQueue.shift(); - } - - if (recoveryMode) { - return undefined; - } - - throw new _core_utils.XRefParseException(); - } - - getEntry(i) { - const xrefEntry = this.entries[i]; - - if (xrefEntry && !xrefEntry.free && xrefEntry.offset) { - return xrefEntry; - } - - return null; - } - - fetchIfRef(obj, suppressEncryption = false) { - if (obj instanceof _primitives.Ref) { - return this.fetch(obj, suppressEncryption); - } - - return obj; - } - - fetch(ref, suppressEncryption = false) { - if (!(ref instanceof _primitives.Ref)) { - throw new Error("ref object is not a reference"); - } - - const num = ref.num; - - const cacheEntry = this._cacheMap.get(num); - - if (cacheEntry !== undefined) { - if (cacheEntry instanceof _primitives.Dict && !cacheEntry.objId) { - cacheEntry.objId = ref.toString(); - } - - return cacheEntry; - } - - let xrefEntry = this.getEntry(num); - - if (xrefEntry === null) { - this._cacheMap.set(num, xrefEntry); - - return xrefEntry; - } - - if (this._pendingRefs.has(ref)) { - this._pendingRefs.remove(ref); - - (0, _util.warn)(`Ignoring circular reference: ${ref}.`); - return _primitives.CIRCULAR_REF; - } - - this._pendingRefs.put(ref); - - try { - if (xrefEntry.uncompressed) { - xrefEntry = this.fetchUncompressed(ref, xrefEntry, suppressEncryption); - } else { - xrefEntry = this.fetchCompressed(ref, xrefEntry, suppressEncryption); - } - - this._pendingRefs.remove(ref); - } catch (ex) { - this._pendingRefs.remove(ref); - - throw ex; - } - - if (xrefEntry instanceof _primitives.Dict) { - xrefEntry.objId = ref.toString(); - } else if (xrefEntry instanceof _base_stream.BaseStream) { - xrefEntry.dict.objId = ref.toString(); - } - - return xrefEntry; - } - - fetchUncompressed(ref, xrefEntry, suppressEncryption = false) { - const gen = ref.gen; - let num = ref.num; - - if (xrefEntry.gen !== gen) { - throw new _core_utils.XRefEntryException(`Inconsistent generation in XRef: ${ref}`); - } - - const stream = this.stream.makeSubStream(xrefEntry.offset + this.stream.start); - const parser = new _parser.Parser({ - lexer: new _parser.Lexer(stream), - xref: this, - allowStreams: true - }); - const obj1 = parser.getObj(); - const obj2 = parser.getObj(); - const obj3 = parser.getObj(); - - if (obj1 !== num || obj2 !== gen || !(obj3 instanceof _primitives.Cmd)) { - throw new _core_utils.XRefEntryException(`Bad (uncompressed) XRef entry: ${ref}`); - } - - if (obj3.cmd !== "obj") { - if (obj3.cmd.startsWith("obj")) { - num = parseInt(obj3.cmd.substring(3), 10); - - if (!Number.isNaN(num)) { - return num; - } - } - - throw new _core_utils.XRefEntryException(`Bad (uncompressed) XRef entry: ${ref}`); - } - - if (this.encrypt && !suppressEncryption) { - xrefEntry = parser.getObj(this.encrypt.createCipherTransform(num, gen)); - } else { - xrefEntry = parser.getObj(); - } - - if (!(xrefEntry instanceof _base_stream.BaseStream)) { - this._cacheMap.set(num, xrefEntry); - } - - return xrefEntry; - } - - fetchCompressed(ref, xrefEntry, suppressEncryption = false) { - const tableOffset = xrefEntry.offset; - const stream = this.fetch(_primitives.Ref.get(tableOffset, 0)); - - if (!(stream instanceof _base_stream.BaseStream)) { - throw new _util.FormatError("bad ObjStm stream"); - } - - const first = stream.dict.get("First"); - const n = stream.dict.get("N"); - - if (!Number.isInteger(first) || !Number.isInteger(n)) { - throw new _util.FormatError("invalid first and n parameters for ObjStm stream"); - } - - let parser = new _parser.Parser({ - lexer: new _parser.Lexer(stream), - xref: this, - allowStreams: true - }); - const nums = new Array(n); - const offsets = new Array(n); - - for (let i = 0; i < n; ++i) { - const num = parser.getObj(); - - if (!Number.isInteger(num)) { - throw new _util.FormatError(`invalid object number in the ObjStm stream: ${num}`); - } - - const offset = parser.getObj(); - - if (!Number.isInteger(offset)) { - throw new _util.FormatError(`invalid object offset in the ObjStm stream: ${offset}`); - } - - nums[i] = num; - offsets[i] = offset; - } - - const start = (stream.start || 0) + first; - const entries = new Array(n); - - for (let i = 0; i < n; ++i) { - const length = i < n - 1 ? offsets[i + 1] - offsets[i] : undefined; - - if (length < 0) { - throw new _util.FormatError("Invalid offset in the ObjStm stream."); - } - - parser = new _parser.Parser({ - lexer: new _parser.Lexer(stream.makeSubStream(start + offsets[i], length, stream.dict)), - xref: this, - allowStreams: true - }); - const obj = parser.getObj(); - entries[i] = obj; - - if (obj instanceof _base_stream.BaseStream) { - continue; - } - - const num = nums[i], - entry = this.entries[num]; - - if (entry && entry.offset === tableOffset && entry.gen === i) { - this._cacheMap.set(num, obj); - } - } - - xrefEntry = entries[xrefEntry.gen]; - - if (xrefEntry === undefined) { - throw new _core_utils.XRefEntryException(`Bad (compressed) XRef entry: ${ref}`); - } - - return xrefEntry; - } - - async fetchIfRefAsync(obj, suppressEncryption) { - if (obj instanceof _primitives.Ref) { - return this.fetchAsync(obj, suppressEncryption); - } - - return obj; - } - - async fetchAsync(ref, suppressEncryption) { - try { - return this.fetch(ref, suppressEncryption); - } catch (ex) { - if (!(ex instanceof _core_utils.MissingDataException)) { - throw ex; - } - - await this.pdfManager.requestRange(ex.begin, ex.end); - return this.fetchAsync(ref, suppressEncryption); - } - } - - getCatalogObj() { - return this.root; - } - -} - -exports.XRef = XRef; - -/***/ }), -/* 99 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.MessageHandler = void 0; - -var _util = __w_pdfjs_require__(2); - -const CallbackKind = { - UNKNOWN: 0, - DATA: 1, - ERROR: 2 -}; -const StreamKind = { - UNKNOWN: 0, - CANCEL: 1, - CANCEL_COMPLETE: 2, - CLOSE: 3, - ENQUEUE: 4, - ERROR: 5, - PULL: 6, - PULL_COMPLETE: 7, - START_COMPLETE: 8 -}; - -function wrapReason(reason) { - if (!(reason instanceof Error || typeof reason === "object" && reason !== null)) { - (0, _util.warn)('wrapReason: Expected "reason" to be a (possibly cloned) Error.'); - return reason; - } - - switch (reason.name) { - case "AbortException": - return new _util.AbortException(reason.message); - - case "MissingPDFException": - return new _util.MissingPDFException(reason.message); - - case "PasswordException": - return new _util.PasswordException(reason.message, reason.code); - - case "UnexpectedResponseException": - return new _util.UnexpectedResponseException(reason.message, reason.status); - - case "UnknownErrorException": - return new _util.UnknownErrorException(reason.message, reason.details); - - default: - return new _util.UnknownErrorException(reason.message, reason.toString()); - } -} - -class MessageHandler { - constructor(sourceName, targetName, comObj) { - this.sourceName = sourceName; - this.targetName = targetName; - this.comObj = comObj; - this.callbackId = 1; - this.streamId = 1; - this.streamSinks = Object.create(null); - this.streamControllers = Object.create(null); - this.callbackCapabilities = Object.create(null); - this.actionHandler = Object.create(null); - - this._onComObjOnMessage = event => { - const data = event.data; - - if (data.targetName !== this.sourceName) { - return; - } - - if (data.stream) { - this._processStreamMessage(data); - - return; - } - - if (data.callback) { - const callbackId = data.callbackId; - const capability = this.callbackCapabilities[callbackId]; - - if (!capability) { - throw new Error(`Cannot resolve callback ${callbackId}`); - } - - delete this.callbackCapabilities[callbackId]; - - if (data.callback === CallbackKind.DATA) { - capability.resolve(data.data); - } else if (data.callback === CallbackKind.ERROR) { - capability.reject(wrapReason(data.reason)); - } else { - throw new Error("Unexpected callback case"); - } - - return; - } - - const action = this.actionHandler[data.action]; - - if (!action) { - throw new Error(`Unknown action from worker: ${data.action}`); - } - - if (data.callbackId) { - const cbSourceName = this.sourceName; - const cbTargetName = data.sourceName; - new Promise(function (resolve) { - resolve(action(data.data)); - }).then(function (result) { - comObj.postMessage({ - sourceName: cbSourceName, - targetName: cbTargetName, - callback: CallbackKind.DATA, - callbackId: data.callbackId, - data: result - }); - }, function (reason) { - comObj.postMessage({ - sourceName: cbSourceName, - targetName: cbTargetName, - callback: CallbackKind.ERROR, - callbackId: data.callbackId, - reason: wrapReason(reason) - }); - }); - return; - } - - if (data.streamId) { - this._createStreamSink(data); - - return; - } - - action(data.data); - }; - - comObj.addEventListener("message", this._onComObjOnMessage); - } - - on(actionName, handler) { - const ah = this.actionHandler; - - if (ah[actionName]) { - throw new Error(`There is already an actionName called "${actionName}"`); - } - - ah[actionName] = handler; - } - - send(actionName, data, transfers) { - this.comObj.postMessage({ - sourceName: this.sourceName, - targetName: this.targetName, - action: actionName, - data - }, transfers); - } - - sendWithPromise(actionName, data, transfers) { - const callbackId = this.callbackId++; - const capability = (0, _util.createPromiseCapability)(); - this.callbackCapabilities[callbackId] = capability; - - try { - this.comObj.postMessage({ - sourceName: this.sourceName, - targetName: this.targetName, - action: actionName, - callbackId, - data - }, transfers); - } catch (ex) { - capability.reject(ex); - } - - return capability.promise; - } - - sendWithStream(actionName, data, queueingStrategy, transfers) { - const streamId = this.streamId++, - sourceName = this.sourceName, - targetName = this.targetName, - comObj = this.comObj; - return new ReadableStream({ - start: controller => { - const startCapability = (0, _util.createPromiseCapability)(); - this.streamControllers[streamId] = { - controller, - startCall: startCapability, - pullCall: null, - cancelCall: null, - isClosed: false - }; - comObj.postMessage({ - sourceName, - targetName, - action: actionName, - streamId, - data, - desiredSize: controller.desiredSize - }, transfers); - return startCapability.promise; - }, - pull: controller => { - const pullCapability = (0, _util.createPromiseCapability)(); - this.streamControllers[streamId].pullCall = pullCapability; - comObj.postMessage({ - sourceName, - targetName, - stream: StreamKind.PULL, - streamId, - desiredSize: controller.desiredSize - }); - return pullCapability.promise; - }, - cancel: reason => { - (0, _util.assert)(reason instanceof Error, "cancel must have a valid reason"); - const cancelCapability = (0, _util.createPromiseCapability)(); - this.streamControllers[streamId].cancelCall = cancelCapability; - this.streamControllers[streamId].isClosed = true; - comObj.postMessage({ - sourceName, - targetName, - stream: StreamKind.CANCEL, - streamId, - reason: wrapReason(reason) - }); - return cancelCapability.promise; - } - }, queueingStrategy); - } - - _createStreamSink(data) { - const streamId = data.streamId, - sourceName = this.sourceName, - targetName = data.sourceName, - comObj = this.comObj; - const self = this, - action = this.actionHandler[data.action]; - const streamSink = { - enqueue(chunk, size = 1, transfers) { - if (this.isCancelled) { - return; - } - - const lastDesiredSize = this.desiredSize; - this.desiredSize -= size; - - if (lastDesiredSize > 0 && this.desiredSize <= 0) { - this.sinkCapability = (0, _util.createPromiseCapability)(); - this.ready = this.sinkCapability.promise; - } - - comObj.postMessage({ - sourceName, - targetName, - stream: StreamKind.ENQUEUE, - streamId, - chunk - }, transfers); - }, - - close() { - if (this.isCancelled) { - return; - } - - this.isCancelled = true; - comObj.postMessage({ - sourceName, - targetName, - stream: StreamKind.CLOSE, - streamId - }); - delete self.streamSinks[streamId]; - }, - - error(reason) { - (0, _util.assert)(reason instanceof Error, "error must have a valid reason"); - - if (this.isCancelled) { - return; - } - - this.isCancelled = true; - comObj.postMessage({ - sourceName, - targetName, - stream: StreamKind.ERROR, - streamId, - reason: wrapReason(reason) - }); - }, - - sinkCapability: (0, _util.createPromiseCapability)(), - onPull: null, - onCancel: null, - isCancelled: false, - desiredSize: data.desiredSize, - ready: null - }; - streamSink.sinkCapability.resolve(); - streamSink.ready = streamSink.sinkCapability.promise; - this.streamSinks[streamId] = streamSink; - new Promise(function (resolve) { - resolve(action(data.data, streamSink)); - }).then(function () { - comObj.postMessage({ - sourceName, - targetName, - stream: StreamKind.START_COMPLETE, - streamId, - success: true - }); - }, function (reason) { - comObj.postMessage({ - sourceName, - targetName, - stream: StreamKind.START_COMPLETE, - streamId, - reason: wrapReason(reason) - }); - }); - } - - _processStreamMessage(data) { - const streamId = data.streamId, - sourceName = this.sourceName, - targetName = data.sourceName, - comObj = this.comObj; - const streamController = this.streamControllers[streamId], - streamSink = this.streamSinks[streamId]; - - switch (data.stream) { - case StreamKind.START_COMPLETE: - if (data.success) { - streamController.startCall.resolve(); - } else { - streamController.startCall.reject(wrapReason(data.reason)); - } - - break; - - case StreamKind.PULL_COMPLETE: - if (data.success) { - streamController.pullCall.resolve(); - } else { - streamController.pullCall.reject(wrapReason(data.reason)); - } - - break; - - case StreamKind.PULL: - if (!streamSink) { - comObj.postMessage({ - sourceName, - targetName, - stream: StreamKind.PULL_COMPLETE, - streamId, - success: true - }); - break; - } - - if (streamSink.desiredSize <= 0 && data.desiredSize > 0) { - streamSink.sinkCapability.resolve(); - } - - streamSink.desiredSize = data.desiredSize; - new Promise(function (resolve) { - resolve(streamSink.onPull && streamSink.onPull()); - }).then(function () { - comObj.postMessage({ - sourceName, - targetName, - stream: StreamKind.PULL_COMPLETE, - streamId, - success: true - }); - }, function (reason) { - comObj.postMessage({ - sourceName, - targetName, - stream: StreamKind.PULL_COMPLETE, - streamId, - reason: wrapReason(reason) - }); - }); - break; - - case StreamKind.ENQUEUE: - (0, _util.assert)(streamController, "enqueue should have stream controller"); - - if (streamController.isClosed) { - break; - } - - streamController.controller.enqueue(data.chunk); - break; - - case StreamKind.CLOSE: - (0, _util.assert)(streamController, "close should have stream controller"); - - if (streamController.isClosed) { - break; - } - - streamController.isClosed = true; - streamController.controller.close(); - - this._deleteStreamController(streamController, streamId); - - break; - - case StreamKind.ERROR: - (0, _util.assert)(streamController, "error should have stream controller"); - streamController.controller.error(wrapReason(data.reason)); - - this._deleteStreamController(streamController, streamId); - - break; - - case StreamKind.CANCEL_COMPLETE: - if (data.success) { - streamController.cancelCall.resolve(); - } else { - streamController.cancelCall.reject(wrapReason(data.reason)); - } - - this._deleteStreamController(streamController, streamId); - - break; - - case StreamKind.CANCEL: - if (!streamSink) { - break; - } - - new Promise(function (resolve) { - resolve(streamSink.onCancel && streamSink.onCancel(wrapReason(data.reason))); - }).then(function () { - comObj.postMessage({ - sourceName, - targetName, - stream: StreamKind.CANCEL_COMPLETE, - streamId, - success: true - }); - }, function (reason) { - comObj.postMessage({ - sourceName, - targetName, - stream: StreamKind.CANCEL_COMPLETE, - streamId, - reason: wrapReason(reason) - }); - }); - streamSink.sinkCapability.reject(wrapReason(data.reason)); - streamSink.isCancelled = true; - delete this.streamSinks[streamId]; - break; - - default: - throw new Error("Unexpected stream case"); - } - } - - async _deleteStreamController(streamController, streamId) { - await Promise.allSettled([streamController.startCall && streamController.startCall.promise, streamController.pullCall && streamController.pullCall.promise, streamController.cancelCall && streamController.cancelCall.promise]); - delete this.streamControllers[streamId]; - } - - destroy() { - this.comObj.removeEventListener("message", this._onComObjOnMessage); - } - -} - -exports.MessageHandler = MessageHandler; - -/***/ }), -/* 100 */ -/***/ ((__unused_webpack_module, exports, __w_pdfjs_require__) => { - - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -exports.PDFWorkerStream = void 0; - -var _util = __w_pdfjs_require__(2); - -class PDFWorkerStream { - constructor(msgHandler) { - this._msgHandler = msgHandler; - this._contentLength = null; - this._fullRequestReader = null; - this._rangeRequestReaders = []; - } - - getFullReader() { - (0, _util.assert)(!this._fullRequestReader, "PDFWorkerStream.getFullReader can only be called once."); - this._fullRequestReader = new PDFWorkerStreamReader(this._msgHandler); - return this._fullRequestReader; - } - - getRangeReader(begin, end) { - const reader = new PDFWorkerStreamRangeReader(begin, end, this._msgHandler); - - this._rangeRequestReaders.push(reader); - - return reader; - } - - cancelAllRequests(reason) { - if (this._fullRequestReader) { - this._fullRequestReader.cancel(reason); - } - - for (const reader of this._rangeRequestReaders.slice(0)) { - reader.cancel(reason); - } - } - -} - -exports.PDFWorkerStream = PDFWorkerStream; - -class PDFWorkerStreamReader { - constructor(msgHandler) { - this._msgHandler = msgHandler; - this.onProgress = null; - this._contentLength = null; - this._isRangeSupported = false; - this._isStreamingSupported = false; - - const readableStream = this._msgHandler.sendWithStream("GetReader"); - - this._reader = readableStream.getReader(); - this._headersReady = this._msgHandler.sendWithPromise("ReaderHeadersReady").then(data => { - this._isStreamingSupported = data.isStreamingSupported; - this._isRangeSupported = data.isRangeSupported; - this._contentLength = data.contentLength; - }); - } - - get headersReady() { - return this._headersReady; - } - - get contentLength() { - return this._contentLength; - } - - get isStreamingSupported() { - return this._isStreamingSupported; - } - - get isRangeSupported() { - return this._isRangeSupported; - } - - async read() { - const { - value, - done - } = await this._reader.read(); - - if (done) { - return { - value: undefined, - done: true - }; - } - - return { - value: value.buffer, - done: false - }; - } - - cancel(reason) { - this._reader.cancel(reason); - } - -} - -class PDFWorkerStreamRangeReader { - constructor(begin, end, msgHandler) { - this._msgHandler = msgHandler; - this.onProgress = null; - - const readableStream = this._msgHandler.sendWithStream("GetRangeReader", { - begin, - end - }); - - this._reader = readableStream.getReader(); - } - - get isStreamingSupported() { - return false; - } - - async read() { - const { - value, - done - } = await this._reader.read(); - - if (done) { - return { - value: undefined, - done: true - }; - } - - return { - value: value.buffer, - done: false - }; - } - - cancel(reason) { - this._reader.cancel(reason); - } - -} - -/***/ }) -/******/ ]); -/************************************************************************/ -/******/ // The module cache -/******/ var __webpack_module_cache__ = {}; -/******/ -/******/ // The require function -/******/ function __w_pdfjs_require__(moduleId) { -/******/ // Check if module is in cache -/******/ var cachedModule = __webpack_module_cache__[moduleId]; -/******/ if (cachedModule !== undefined) { -/******/ return cachedModule.exports; -/******/ } -/******/ // Create a new module (and put it into the cache) -/******/ var module = __webpack_module_cache__[moduleId] = { -/******/ // no module.id needed -/******/ // no module.loaded needed -/******/ exports: {} -/******/ }; -/******/ -/******/ // Execute the module function -/******/ __webpack_modules__[moduleId](module, module.exports, __w_pdfjs_require__); -/******/ -/******/ // Return the exports of the module -/******/ return module.exports; -/******/ } -/******/ -/************************************************************************/ -/******/ /* webpack/runtime/define property getters */ -/******/ (() => { -/******/ // define getter functions for harmony exports -/******/ __w_pdfjs_require__.d = (exports, definition) => { -/******/ for(var key in definition) { -/******/ if(__w_pdfjs_require__.o(definition, key) && !__w_pdfjs_require__.o(exports, key)) { -/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); -/******/ } -/******/ } -/******/ }; -/******/ })(); -/******/ -/******/ /* webpack/runtime/hasOwnProperty shorthand */ -/******/ (() => { -/******/ __w_pdfjs_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) -/******/ })(); -/******/ -/******/ /* webpack/runtime/make namespace object */ -/******/ (() => { -/******/ // define __esModule on exports -/******/ __w_pdfjs_require__.r = (exports) => { -/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { -/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); -/******/ } -/******/ Object.defineProperty(exports, '__esModule', { value: true }); -/******/ }; -/******/ })(); -/******/ -/************************************************************************/ -var __webpack_exports__ = {}; -// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk. -(() => { -var exports = __webpack_exports__; - - -Object.defineProperty(exports, "__esModule", ({ - value: true -})); -Object.defineProperty(exports, "WorkerMessageHandler", ({ - enumerable: true, - get: function () { - return _worker.WorkerMessageHandler; - } -})); - -var _worker = __w_pdfjs_require__(1); - -const pdfjsVersion = '2.12.313'; -const pdfjsBuild = 'a2ae56f39'; -})(); - -/******/ return __webpack_exports__; -/******/ })() -; -}); -//# sourceMappingURL=pdf.worker.js.map \ No newline at end of file diff --git a/ui/public/robots.txt b/ui/public/robots.txt deleted file mode 100644 index e9e57dc4..00000000 --- a/ui/public/robots.txt +++ /dev/null @@ -1,3 +0,0 @@ -# https://www.robotstxt.org/robotstxt.html -User-agent: * -Disallow: diff --git a/ui/src/App.jsx b/ui/src/App.jsx deleted file mode 100644 index 57e40ec2..00000000 --- a/ui/src/App.jsx +++ /dev/null @@ -1,67 +0,0 @@ -import {useEffect} from "react"; -import { BrowserRouter as Router, Route, Switch } from "react-router-dom"; -import { ToastContainer } from 'react-toastify'; - -import apiService from "./services/api.service"; -import { AuthProvider } from "./common/useAuthContext"; -import Role from "./common/Role"; -import { PrivateRoute } from "./components/PrivateRoute"; -import Navigationbar from "./components/Navigation"; -import PasscodeResets from "./components/PasscodeResets"; - -import Login from "./pages/Login"; -import Home from "./pages/Home"; -import Connect from "./pages/Connect"; -import Documents from "./pages/Documents"; -import Integrations from "./pages/Integrations"; -import Profile from "./pages/Profile"; -import Admin from "./pages/Admin"; -import ScreenShare from "./pages/ScreenShare"; -import NoMatch from "./pages/404"; - -import "react-toastify/dist/ReactToastify.css"; - -import "./App.scss" - -import { pdfjs } from "react-pdf"; -pdfjs.GlobalWorkerOptions.workerSrc = new URL( - 'pdfjs-dist/build/pdf.worker.min.mjs', - import.meta.url, -).toString(); - -export default function App() { - - useEffect(() => { - apiService.checkLogin() - }, []) - - return ( - <> - - -
    - - -
    - - - - - - - - - - - - - - -
    -
    -
    -
    - - - ); -} diff --git a/ui/src/App.scss b/ui/src/App.scss deleted file mode 100644 index 577534fd..00000000 --- a/ui/src/App.scss +++ /dev/null @@ -1,276 +0,0 @@ -@import "./theme.scss"; - -// TODO: Remove styles which are not meant to be global into module files - -:root { - height:100%; - --bs-code-color: #{$action} !important; - --bs-body-bg: #{$background1} !important; - --bs-border-color: #{$foreground2} !important; - --bs-tertiary-bg: #{$background1} !important; - - .dropdown-item { - --bs-dropdown-link-hover-bg: #{$background2}; - --bs-dropdown-link-active-bg: #{$action}; - } - - .btn-outline-secondary { - --bs-btn-color: #{$foreground2}; - --bs-btn-border-color: #{$foreground2}; - } - - .btn-primary { - --bs-btn-bg: #{$foreground2}; - --bs-btn-color: #{$background1}; - --bs-btn-border-color: #{$foreground2}; - - --bs-btn-hover-bg: #{$action}; - --bs-btn-hover-color: #{$foreground2}; - --bs-btn-hover-border-color: #{$action}; - - --bs-btn-active-bg: #{$action}; - --bs-btn-active-color: #{$background2}; - --bs-btn-active-border-color: #{$action}; - - --bs-btn-active-shadow: none; - --bs-btn-focus-shadow-rgb: none; // #{$action-rgb}; - } - - .btn-danger { - --bs-btn-bg: #{$reject}; - --bs-btn-color: #{$foreground2}; - --bs-btn-border-color: #{$reject}; - - --bs-btn-hover-bg: #{$reject}; - --bs-btn-hover-color: #{$foreground2}; - --bs-btn-hover-border-color: #{$reject}; - - --bs-btn-active-bg: #{$reject}; - --bs-btn-active-color: #{$background2}; - --bs-btn-active-border-color: #{$reject}; - - --bs-btn-active-shadow: none; - --bs-btn-focus-shadow-rgb: none; // #{$action-rgb}; - - &:hover, &:focus { - opacity: 0.7; - } - } -} - -.form-control:focus { - border-color: $action !important; - box-shadow: none !important; // 0 0 0 0.25rem rgba(var(--bs-btn-focus-shadow-rgb), 10%) !important; -} - -.card input { - margin-bottom: 0.5em; -} - -#root > nav { - backdrop-filter: blur(12px); - background-color: $background1; -} - -html, body { - height: 100%; - overflow: hidden; - background-color: $background2; -} - -#root { - height: 100%; -} - -*:disabled { - color: $foreground2 !important; - background-color: $background2 !important; - - opacity: 0.7 !important; -} - -div[role="button"] > p { - margin: 1em; -} - -.vstack { - gap: 2em; -} - -canvas { - margin: auto; - width: auto !important; - height: auto !important; - max-width: 100%; - max-height: calc(100vh - 230px); -} - -code { - padding: 0.5em; - background-color: $background1; -} - -@media (max-width: 768px) { - .documents-tree { - max-height: 25vh !important; - } -} - -.container-fluid { - box-sizing: border-box; - margin: 0 50px; - max-width: none; - width: calc(100vw - 100px) !important; -} - -.documents-tree { - div[role=treeitem] { - outline: none; - - & > div { - display: flex; - align-items: center; - height: 100%; - width: 100%; - overflow: hidden; - } - - &:hover { - background-color: rgba(255, 255, 255, .1); - cursor: pointer; - } - - .treeitem-nodename { - white-space: nowrap; - text-overflow: ellipsis; - overflow: hidden; - &.is-folder { - font-weight: bold; - } - } - - } -} - -.filelist { - gap: 0 !important; - - .filelist-header { - display: flex; - align-items: center; - padding: 0.5em 0.8em; - background-color: $background2; - border-bottom: 2px solid $foreground1; - font-weight: bold; - font-size: 0.9em; - color: $foreground1; - - .filelist-header-cell { - display: flex; - align-items: center; - user-select: none; - - &.sortable { - cursor: pointer; - - &:hover { - color: $action; - } - } - - .sort-indicator { - margin-left: 0.3em; - font-size: 0.9em; - } - } - } - - .filelist-item { - &:hover { - background-color: rgba(255, 255, 255, .1); - border-bottom: 1px solid $background2; - cursor: pointer; - } - - .is-folder { - font-weight: bold; - } - - .filelist-metadata { - color: $foreground2; - font-size: 0.8em; - padding: 0 0.5em; - } - - .filelist-checkbox { - margin-right: 0.8em; - } - } -} - -.filegrid { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); - grid-gap: 1em; - - .filegrid-file-item, - .filegrid-folder-item { - display: inline-grid; - padding: 0.5em; - - &:hover { - background-color: rgba(255, 255, 255, .1); - cursor: pointer; - } - - .filegrid-metadata { - font-weight: normal; - color: $foreground2; - font-size: 0.8em; - } - } - - .filegrid-file-item { - .fileicon { - padding: 0.5rem; - svg { - height: 80px; - width: 100%; - } - } - .filename { - display: block; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - width: 100%; - font-size: 0.8rem; - } - } - - .filegrid-folder-item { - font-weight: bold; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - } - - .filelist-checkbox { - position: absolute; - margin: 0.4em; - } - - .filegrid-checkbox-spacer { - margin-left: 2.4em; - } -} - -main h2 { - padding: 0.5em 0; -} - -@import "bootstrap/scss/bootstrap"; - -.flex-spacer { - flex: 1; -} diff --git a/ui/src/App.test.js b/ui/src/App.test.js deleted file mode 100644 index bd809185..00000000 --- a/ui/src/App.test.js +++ /dev/null @@ -1,6 +0,0 @@ -import React from 'react'; -import { render } from '@testing-library/react'; -import App from './App'; - -test('renders learn react link', () => { -}); diff --git a/ui/src/common/Role.js b/ui/src/common/Role.js deleted file mode 100644 index 96dbb4eb..00000000 --- a/ui/src/common/Role.js +++ /dev/null @@ -1,6 +0,0 @@ -const Role = { - Admin: "Admin", - User: "User", -}; - -export default Role; diff --git a/ui/src/common/actions.js b/ui/src/common/actions.js deleted file mode 100644 index 22e189e2..00000000 --- a/ui/src/common/actions.js +++ /dev/null @@ -1,23 +0,0 @@ -import apiService from "../services/api.service"; - -export async function loginUser(dispatch, loginPayload) { - - try { - dispatch({ type: "REQUEST_LOGIN" }); - - let user = await apiService.login(loginPayload) - dispatch({ - type: "LOGIN_SUCCESS", - payload: { user: user }, - }); - - return; - } catch (error) { - dispatch({ type: "LOGIN_ERROR", error: "Can't login: " + error.message}); - } -} - -export async function logout(dispatch) { - await apiService.logout() - dispatch({ type: "LOGOUT" }); -} diff --git a/ui/src/common/constants.js b/ui/src/common/constants.js deleted file mode 100644 index 2a7d5a98..00000000 --- a/ui/src/common/constants.js +++ /dev/null @@ -1,5 +0,0 @@ -const constants = { - ROOT_URL : "/ui/api" -} - -export default constants \ No newline at end of file diff --git a/ui/src/common/date.js b/ui/src/common/date.js deleted file mode 100644 index 15bf2c14..00000000 --- a/ui/src/common/date.js +++ /dev/null @@ -1,7 +0,0 @@ -export function formatDate(dateString) { - // TODO: support other date formats - // TODO: option for local time instead of utc - - let date = new Date(dateString); - return date.toLocaleString('sv'); -} diff --git a/ui/src/common/useAuthContext.jsx b/ui/src/common/useAuthContext.jsx deleted file mode 100644 index 36c91d4a..00000000 --- a/ui/src/common/useAuthContext.jsx +++ /dev/null @@ -1,62 +0,0 @@ -import React, { useReducer } from "react"; - -let user = localStorage.getItem("currentUser") - ? JSON.parse(localStorage.getItem("currentUser")) - : null; - -export const initialState = { - user: "" || user, - loading: false, - errorMessage: null, -}; -const AuthStateContext = React.createContext(); - -export function useAuthState() { - const context = React.useContext(AuthStateContext); - if (context === undefined) { - throw new Error("useAuthState must be used within a AuthProvider"); - } - - return context; -} - -export const AuthProvider = ({ children }) => { - const [state, dispatch] = useReducer(authReducer, initialState); - - return ( - - {children} - - ); -}; - -function authReducer(initialState, action) { - switch (action.type) { - case "REQUEST_LOGIN": - return { - ...initialState, - loading: true, - }; - case "LOGIN_SUCCESS": - return { - ...initialState, - user: action.payload.user, - loading: false, - }; - case "LOGOUT": - return { - ...initialState, - user: "", - }; - - case "LOGIN_ERROR": - return { - ...initialState, - loading: false, - errorMessage: action.error, - }; - - default: - throw new Error(`Unhandled action type: ${action.type}`); - } -} diff --git a/ui/src/components/ErrorBoundary.jsx b/ui/src/components/ErrorBoundary.jsx deleted file mode 100644 index dd6c8d81..00000000 --- a/ui/src/components/ErrorBoundary.jsx +++ /dev/null @@ -1,28 +0,0 @@ -import React from "react"; - -class ErrorBoundary extends React.Component { - state = { hasError: false, errorMessage: null }; - - // A fake logging service - logErrorToServices = console.log; - - static getDerivedStateFromError(error) { - // Update state so the next render will show the fallback UI. - return { hasError: true, errorMessage: error?.toString() }; - } - - componentDidCatch(error, info) { - this.logErrorToServices(error, info.componentStack); - } - - render() { - if (this.state.hasError) { - // You can render any custom fallback UI - return

    Something went wrong: {this.state.errorMessage}

    ; - } - - return this.props.children; - } -} - -export default ErrorBoundary; diff --git a/ui/src/components/NameTag.jsx b/ui/src/components/NameTag.jsx deleted file mode 100644 index 75ba37ed..00000000 --- a/ui/src/components/NameTag.jsx +++ /dev/null @@ -1,14 +0,0 @@ -import { BsChevronRight } from "react-icons/bs"; -import { Button } from "react-bootstrap"; - -export default function NameTag({ node, onSelect }) { - if (node.parent) { - return (<> - - - - ) - } - // No parent means this is the root - render it - return -} \ No newline at end of file diff --git a/ui/src/components/Navigation.jsx b/ui/src/components/Navigation.jsx deleted file mode 100644 index 9cdc3fcc..00000000 --- a/ui/src/components/Navigation.jsx +++ /dev/null @@ -1,75 +0,0 @@ -import React from "react"; -import { Nav, Navbar, Button, NavDropdown, Container } from "react-bootstrap"; -import { logout } from "../common/actions"; -import { useAuthState } from "../common/useAuthContext"; -import { NavLink } from "react-router-dom"; - -const NavigationBar = () => { - const { state:{user}, dispatch } = useAuthState(); - - function handleLogout(e) { - logout(dispatch); - } - - function isAdmin() { - return user && user.Roles && user.Roles[0] === "Admin"; - } - return ( - - - - - rmfakecloud - - - - {user && ( - <> - - - - - - )} - - - ); -}; - -export default NavigationBar; diff --git a/ui/src/components/PasscodeResets.jsx b/ui/src/components/PasscodeResets.jsx deleted file mode 100644 index eb294490..00000000 --- a/ui/src/components/PasscodeResets.jsx +++ /dev/null @@ -1,86 +0,0 @@ -import { useEffect, useState } from "react"; -import Button from "react-bootstrap/Button"; -import Container from "react-bootstrap/Container"; -import ListGroup from "react-bootstrap/ListGroup"; - -import apiservice from "../services/api.service"; -import { useAuthState } from "../common/useAuthContext"; - -export default function PasscodeResets() { - const { state: { user } } = useAuthState(); - const [resets, setResets] = useState([]); - const [error, setError] = useState(""); - - const load = () => { - apiservice - .listPasscodeResets() - .then((list) => setResets(list || [])) - .catch((e) => setError(e.toString())); - }; - - useEffect(() => { - if (!user) { - setResets([]); - return; - } - load(); - const id = setInterval(load, 5000); - return () => clearInterval(id); - }, [user]); - - const approve = (uuid) => { - apiservice - .approvePasscodeReset(uuid) - .then(load) - .catch((e) => setError(e.toString())); - }; - - const dismiss = (uuid) => { - apiservice - .dismissPasscodeReset(uuid) - .then(load) - .catch((e) => setError(e.toString())); - }; - - if (!user) { - return null; - } - if (error) { - return ( - -
    {error}
    -
    - ); - } - if (resets.length === 0) { - return null; - } - - return ( - - - {resets.map((r) => ( - -
    -
    Passcode reset requested — {r.DeviceName || "device"}
    - - {r.DeviceID} · {new Date(r.Created).toLocaleString()} - -
    -
    - - -
    -
    - ))} -
    -
    - ); -} diff --git a/ui/src/components/PrivateRoute.tsx b/ui/src/components/PrivateRoute.tsx deleted file mode 100644 index 87563bbd..00000000 --- a/ui/src/components/PrivateRoute.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import React from "react"; -import { Route, Redirect } from "react-router-dom"; -import { logout } from "../common/actions"; -import { useAuthState } from "../common/useAuthContext"; - -type RouteProp = { - component: React.FC; - roles?: string[]; - exact?: boolean; - path: string; -}; - -export const PrivateRoute = ({ - component: Component, - roles, - ...rest -}: RouteProp) => { - const { state:{user}, dispatch } = useAuthState(); //read the values of loading and errorMessage from context - return ( - { - if (!user) { - // not logged in so redirect to login page with the return url - return ( - - ); - } - - // check if route is restricted by role - if (roles && user.Roles && roles.indexOf(user.Roles[0]) === -1) { - // role not authorised ==> logout - logout(dispatch); - return ; - } - - // authorised so return component - return ; - }} - /> - ); -}; diff --git a/ui/src/components/Spinner.jsx b/ui/src/components/Spinner.jsx deleted file mode 100644 index 880ffa0c..00000000 --- a/ui/src/components/Spinner.jsx +++ /dev/null @@ -1,22 +0,0 @@ -import React from "react"; -import { Card, Spinner as BSpinner } from "react-bootstrap"; - -export default function Spinner() { - return ( - - - Loading... - - ); -} diff --git a/ui/src/hooks/useFetch.js b/ui/src/hooks/useFetch.js deleted file mode 100644 index d241e8f1..00000000 --- a/ui/src/hooks/useFetch.js +++ /dev/null @@ -1,40 +0,0 @@ -import { useState, useEffect } from "react"; -import constants from "../common/constants" - - -const useFetch = (url, options) => { - const [loading, setLoading] = useState(true); - const [data, setData] = useState(null); - const [error, setError] = useState(null); - - useEffect(() => { - const init = async () => { - try { - const response = await fetch(`${constants.ROOT_URL}/${url}`, { - method: "GET", - }); - - if (response.ok) { - const json = await response.json(); - setData(json); - } else if (response.status === 401) { - // //TODO: fix this hack - localStorage.removeItem("currentUser"); - window.location.replace("/") - } else { - throw response; - } - } catch (e) { - console.error("fetch failed: ", e); - setError(e); - } finally { - setLoading(false); - } - }; - - init(); - }, [url, options]); // rerun when... - - return { data, error, loading }; -}; -export default useFetch diff --git a/ui/src/index.css b/ui/src/index.css deleted file mode 100644 index 664413f1..00000000 --- a/ui/src/index.css +++ /dev/null @@ -1,14 +0,0 @@ -body { - margin: 0; - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", - "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; -} - -canvas { - max-width: 100%; -} - -.transparent-modal .modal-content { - background-color: transparent; -} diff --git a/ui/src/index.jsx b/ui/src/index.jsx deleted file mode 100644 index e13c4694..00000000 --- a/ui/src/index.jsx +++ /dev/null @@ -1,14 +0,0 @@ -import React from "react"; -import { createRoot } from "react-dom/client"; -import App from "./App"; -import ErrorBoundary from "./components/ErrorBoundary"; -import "./index.css"; - -const domNode = document.getElementById('root'); -const root = createRoot(domNode); -root.render( - - - - - ); diff --git a/ui/src/pages/404.jsx b/ui/src/pages/404.jsx deleted file mode 100644 index 0108ebbd..00000000 --- a/ui/src/pages/404.jsx +++ /dev/null @@ -1,7 +0,0 @@ -import React from "react"; - -const NoMatch = () => { - return
    Page Not Found.
    ; -}; - -export default NoMatch; diff --git a/ui/src/pages/Admin/NewUserModal.jsx b/ui/src/pages/Admin/NewUserModal.jsx deleted file mode 100644 index 8ba82d96..00000000 --- a/ui/src/pages/Admin/NewUserModal.jsx +++ /dev/null @@ -1,107 +0,0 @@ -import React, { useState } from "react"; -import Form from "react-bootstrap/Form"; -import { Button, Card, Alert } from "react-bootstrap"; - -import apiService from "../../services/api.service"; - -export default function UserProfileModal(params) { - const { onSave, onClose } = params; - - const [formErrors, setFormErrors] = useState({}); - const [formInfo, setFormInfo] = useState({}); - const [userForm, setUserForm] = useState({ - newPassword: "", - email: "", - userid: "", - }); - - function handleChange({ target }) { - setUserForm({ ...userForm, [target.name]: target.value }); - } - - function formIsValid() { - const _errors = {}; - - if (!userForm.newPassword) _errors.error = "password is required"; - - if (!userForm.email) _errors.error = "email is required"; - - if (!userForm.userid) _errors.error = "userid is required"; - - setFormErrors(_errors); - - return Object.keys(_errors).length === 0; - } - - async function handleSubmit(event) { - event.preventDefault(); - - if (!formIsValid()) return; - - try { - await apiService.createuser(userForm); - setFormInfo({ message: "Created" }); - onSave(); - } catch (e) { - setFormErrors({ error: e.toString() }); - } - } - - return ( -
    - - - New User - - - - - - - UserID - - Email - - - - Password - - - - - - - - -
    - ); -} diff --git a/ui/src/pages/Admin/UserList.jsx b/ui/src/pages/Admin/UserList.jsx deleted file mode 100644 index 080893b1..00000000 --- a/ui/src/pages/Admin/UserList.jsx +++ /dev/null @@ -1,138 +0,0 @@ -import {useState} from "react"; -import { toast } from "react-toastify"; -import { Alert, Button, Modal, Table } from "react-bootstrap"; - -import useFetch from "../../hooks/useFetch"; -import Spinner from "../../components/Spinner"; -import UserProfileModal from "./UserProfileModal"; -import NewUserModal from "./NewUserModal"; -import apiService from "../../services/api.service"; -import { formatDate } from "../../common/date"; - -const userListUrl = "users"; - -const NewUser = 1; -const UpdateUser = 2; - -export default function UserList() { - const [index, setIndex] = useState(false); - const { data: userList, error, loading } = useFetch(`${userListUrl}`, index); - const [ state, setState ] = useState({showModal: 0, modalUser: null}); - const refresh = () =>{ - setIndex(previous => previous+1) - } - - function openModal(index) { - let user = userList[index]; - setState({ - showModal: UpdateUser, - modalUser: user, - }); - } - - function closeModal() { - setState({ - showModal: 0, - modalUser: null, - }); - } - - if (loading) { - return - } - - if (error) { - return ( - - An Error Occurred - {`Error ${error.status}: ${error.statusText}`} - - ); - } - - if (!userList.length) { - return
    No users
    ; - } - const newUser = e => { - setState({ - showModal: NewUser, - }); - } - - const onSave = () => { - closeModal(); - refresh(); - } - - const remove = async (e, id) => { - e.preventDefault() - e.stopPropagation() - if (!window.confirm(`Are you sure you want to delete user: ${id}?`)) - return false - - try{ - await apiService.deleteuser(id) - refresh() - } catch(e){ - toast.error('Error:'+ e) - } - } - // const handleSave = async e => { - // e.preventDefault() - // try { - // await apiService.createuser({ - // userid: profileForm.userid, - // email: profileForm.email, - // newPassword: profileForm.password, - // }); - // hide() - // refresh() - // - // } catch (e) { - // setFormErrors({ error: e.toString()}); - // } - // } - // - // const handleChange = ({ target }) => { - // setProfileForm({ ...profileForm, [target.name]: target.value }); - // } - - return ( - <> -

    Users

    - - - - - - - - - - - - - - {userList.map((x, index) => ( - openModal(index)} style={{ cursor: "pointer" }}> - - - - - - - - - ))} - -
    #UserIdEmailNameRoleCreated At
    {index}{x.userid}{x.email}{x.Name}{x.isAdmin && "admin"}{formatDate(x.CreatedAt)}
    - - - - - - - - - ); -} diff --git a/ui/src/pages/Admin/UserProfileModal.jsx b/ui/src/pages/Admin/UserProfileModal.jsx deleted file mode 100644 index 0244b4f6..00000000 --- a/ui/src/pages/Admin/UserProfileModal.jsx +++ /dev/null @@ -1,102 +0,0 @@ -import React, { useState } from "react"; -import Form from "react-bootstrap/Form"; -import { Button, Card } from "react-bootstrap"; -import apiService from "../../services/api.service"; - -import { Alert } from "react-bootstrap"; - -export default function UserProfileModal(params) { - const { user, onSave, headerText, onClose } = params; - - const [formErrors, setFormErrors] = useState({}); - const [resetPasswordForm, setResetPasswordForm] = useState({ - newPassword: "", - email: user?.email, - }); - - function handleChange({ target }) { - setResetPasswordForm({ ...resetPasswordForm, [target.name]: target.value }); - } - - function formIsValid() { - const _errors = {}; - - // if (!resetPasswordForm.newPassword) - // _errors.error = "newPassword is required"; - // - if (!resetPasswordForm.email) _errors.error = "email is required"; - - setFormErrors(_errors); - - return Object.keys(_errors).length === 0; - } - - async function handleSubmit(event) { - event.preventDefault(); - - if (!formIsValid()) return; - - try { - await apiService.updateuser({ - userid: user.userid, - email: resetPasswordForm.email, - newPassword: resetPasswordForm.newPassword, - }); - onSave(); - } catch (e) { - setFormErrors({ error: e.toString() }); - } - } - - if (!user) return null; - return ( -
    - - - {headerText} - - -
    - UserID - - Email - - - New Password - - - - -
    -
    - - - - -
    -
    - ); -} diff --git a/ui/src/pages/Admin/index.jsx b/ui/src/pages/Admin/index.jsx deleted file mode 100644 index 141fd821..00000000 --- a/ui/src/pages/Admin/index.jsx +++ /dev/null @@ -1,15 +0,0 @@ -import Container from "react-bootstrap/Container"; -import Stack from "react-bootstrap/Stack"; -import UserList from "./UserList"; - -const Home = () => { - return ( - - - - - - ); -}; - -export default Home; diff --git a/ui/src/pages/Connect/index.jsx b/ui/src/pages/Connect/index.jsx deleted file mode 100644 index 329ace4c..00000000 --- a/ui/src/pages/Connect/index.jsx +++ /dev/null @@ -1,43 +0,0 @@ -import React, {useState, useLayoutEffect} from "react"; -import apiservice from "../../services/api.service" -import Stack from 'react-bootstrap/Stack'; -import Button from 'react-bootstrap/Button'; -import { FaRepeat } from "react-icons/fa6"; - -export default function CodeGenerator() { - - const [code, setCode] = useState("") - const [error, setError] = useState("") - - const newCode = async () => { - setCode("") - const code = await apiservice.getCode() - .catch(e => { - setError(e) - }) - setCode(code) - } - - useLayoutEffect(() => { - newCode() - }, []) - - if (error) { - return
    {error.message}
    ; - } - - return ( - <> - -
    - -
    -
    -

    {code}

    -
    -
    - - ); -} diff --git a/ui/src/pages/Documents/Documents.module.scss b/ui/src/pages/Documents/Documents.module.scss deleted file mode 100644 index 51663609..00000000 --- a/ui/src/pages/Documents/Documents.module.scss +++ /dev/null @@ -1,88 +0,0 @@ -@import "../../theme.scss"; - -.treeContainer { - height: 100%; - - // Ensure the inner div also takes full height - > div { - height: 100%; - } - - // Target the react-arborist tree div - div[role="tree"] { - height: 100%; - } -} - -.base { - background-color: $background2; - transition: background 0.3s ease; - - &.accept { - background-color: $accept; - } - - &.reject { - background-color: $reject; - } -} - -.selected { - color: $action; -} - -.stretch { - display: flex; - - flex: 1 1 0; - - &.userid { - font-weight: bold; - } -} - -.filedivider { - border-bottom: 2px solid $foreground1; -} - -.upload { - display: flex; - - flex: 1; - align-items: center; - flex-direction: column; - - margin: 0; - padding: 20px; - border: 2px dashed; - border-top: none; - color: $foreground1; - background-color: $background1; - - outline: none; - transition: border .24s ease-in-out; - - border-color: $foreground1; - - &.uploadActive { - border-color: $action; - } - - &.uploadAccept { - border-color: $accept; - } - - &.uploadReject { - border-color: $reject; - } -} - -.uploadWaiting { - display: flex; - justify-content: center; - align-items: center; - padding-top: 1em; - border: none; - width: 100%; - background-color: transparent; -} \ No newline at end of file diff --git a/ui/src/pages/Documents/File.jsx b/ui/src/pages/Documents/File.jsx deleted file mode 100644 index 24d4602e..00000000 --- a/ui/src/pages/Documents/File.jsx +++ /dev/null @@ -1,133 +0,0 @@ -import { useState, useEffect, useRef, useMemo } from "react"; -import { Button, ButtonGroup, Dropdown } from "react-bootstrap"; -import Navbar from 'react-bootstrap/Navbar'; -import { FaChevronRight, FaChevronLeft, } from "react-icons/fa6"; -import { AiOutlineDownload } from "react-icons/ai"; -import constants from "../../common/constants"; - -import apiservice from "../../services/api.service" -import NameTag from "../../components/NameTag" - -import { pdfjs, Document, Page } from "react-pdf"; -// import 'react-pdf/dist/Page/AnnotationLayer.css'; -// import 'react-pdf/dist/Page/TextLayer.css'; -// import 'react-pdf/dist/Page/TextLayer.css'; -//pdfjs.GlobalWorkerOptions.workerSrc = "/pdf.worker.js" -// pdfjs.GlobalWorkerOptions.workerSrc = new URL( -// 'pdfjs-dist/build/pdf.worker.min.mjs', -// import.meta.url, -// ).toString(); - - -export default function FileViewer({ file, onSelect }) { - const { data } = file; - - const downloadUrl = `${constants.ROOT_URL}/documents/${file.id}`; - - const [page, setPage] = useState(1); - const [pages, setPages] = useState(1); - // const [width, setWidth] = useState(100); - const [height, setHeight] = useState(100); - const onLoadSuccess = (pdf) => { - setPage(1); - setPages(pdf.numPages); - }; - const onPrev = () => { - setPage((p) => { - return Math.max(p - 1, 1); - }); - }; - const onNext = () => { - setPage((p) => { - return Math.min(p + 1, pages); - }); - }; - const parent = useRef(null); - useEffect(() => { - const resizeObserver = new ResizeObserver((event) => { - // Depending on the layout, you may need to swap inlineSize with blockSize - // https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserverEntry/contentBoxSize - // setWidth(event[0].contentBoxSize[0].inlineSize); - setHeight(event[0].contentBoxSize[0].blockSize); - }); - - resizeObserver.observe(parent.current); - }); - - // TODO: add loading and error handling - const triggerDownload = (blob, filename) => { - var url = window.URL.createObjectURL(blob) - var a = document.createElement('a') - a.href = url - a.download = filename - document.body.appendChild(a) - a.click() - a.remove() - } - - const onDownloadPdf = () => { - apiservice.download(data.id) - .then(blob => triggerDownload(blob, data.name + '.pdf')) - .catch(() => {}) - } - - const onDownloadRmdoc = () => { - apiservice.download(data.id, 'rmdoc') - .then(blob => triggerDownload(blob, data.name + '.rmdoc')) - .catch(() => {}) - } - - let options = useMemo(()=> { - return { - worker: new pdfjs.PDFWorker() - } - },[pdfjs]) - - return ( - <> - - { file && (
    ) } -
    - - - {pages > 1 && ( -
    - - - - - - Page: {page} of {pages} - -
    - )} -
    - - - - - - - Download PDF - Download .rmdoc - - - -
    - - - {file && ( -
    - - - -
    - )} - - ); -} diff --git a/ui/src/pages/Documents/FileIcon.jsx b/ui/src/pages/Documents/FileIcon.jsx deleted file mode 100644 index a1902cfd..00000000 --- a/ui/src/pages/Documents/FileIcon.jsx +++ /dev/null @@ -1,39 +0,0 @@ -import { BsFilePdf, BsFolder, BsFileEarmark, BsFileEarmarkText, BsCloud, BsFile, BsTrash } from "react-icons/bs"; - -export default function FileIcon({ file }) { - - const Icon = () => { - if (!!file.icon) { - switch (file.icon) { - case "device": - return - case "trash": - return - case "cloud": - return - default: - return - } - } - - if (file.isFolder) { - return - } - - if (file.type === "pdf") { - return - } - - if (file.type === "notebook") { - return - } - - return - } - - return ( - - - - ); -} diff --git a/ui/src/pages/Documents/FileList.jsx b/ui/src/pages/Documents/FileList.jsx deleted file mode 100644 index 07f3aeb7..00000000 --- a/ui/src/pages/Documents/FileList.jsx +++ /dev/null @@ -1,247 +0,0 @@ -import { useMemo } from "react"; -import { Stack } from "react-bootstrap"; -import { - useReactTable, - getCoreRowModel, - getSortedRowModel, - flexRender, -} from "@tanstack/react-table"; -import FileIcon from "./FileIcon"; -import moment from "moment"; - -// optional: load user-specific locale from config -// moment.locale(locale); // eg. 'de' or 'fr' - -function formatBytes(bytes) { - if(bytes === 0) return '0 Bytes'; - let k = 1024, - sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'], - i = Math.floor(Math.log(bytes) / Math.log(k)); - return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; -} - -export default function FileListViewer({ listStyle, files, onSelect, counter, selectedIds = [], onSelectItem }) { - const onClickItem = (file) => { - onSelect(file); - } - - const isFolderClassName = (item) => { - if (item.isFolder) return "is-folder"; - return ""; - } - - // Define columns for TanStack Table - const columns = useMemo( - () => [ - { - id: 'select', - header: ({ table }) => ( - e.stopPropagation()} - /> - ), - cell: ({ row }) => ( - onSelectItem && onSelectItem(row.original.id)} - onClick={(e) => e.stopPropagation()} - className="filelist-checkbox" - /> - ), - enableSorting: false, - size: 40, - }, - { - id: 'icon', - header: '', - cell: ({ row }) => , - enableSorting: false, - size: 40, - }, - { - accessorKey: 'data.name', - id: 'name', - header: 'Name', - cell: ({ row }) => ( -
    - {row.original.data.name} -
    - ), - sortingFn: (rowA, rowB) => { - return rowA.original.data.name.localeCompare(rowB.original.data.name); - }, - }, - { - id: 'metadata', - header: 'Size', - accessorFn: (row) => row.isLeaf ? row.data.size : row.children?.length || 0, - cell: ({ row }) => ( -
    - {!row.original.isLeaf && {row.original.children?.length || "empty"}} - {row.original.isLeaf && {formatBytes(row.original.data.size)}} -
    - ), - sortingFn: (rowA, rowB) => { - const valA = rowA.original.isLeaf ? rowA.original.data.size : rowA.original.children?.length || 0; - const valB = rowB.original.isLeaf ? rowB.original.data.size : rowB.original.children?.length || 0; - return valA - valB; - }, - }, - { - accessorKey: 'data.lastModified', - id: 'lastModified', - header: 'Last Modified', - cell: ({ row }) => ( -
    - {moment(row.original.data.lastModified).format('L')}{" "} - {moment(row.original.data.lastModified).format('LT')} -
    - ), - sortingFn: (rowA, rowB) => { - const dateA = new Date(rowA.original.data.lastModified); - const dateB = new Date(rowB.original.data.lastModified); - return dateA.getTime() - dateB.getTime(); - }, - sortDescFirst: true, // Default to newest first for this column - }, - ], - [selectedIds, onSelectItem] - ); - - const table = useReactTable({ - data: files, - columns, - getCoreRowModel: getCoreRowModel(), - getSortedRowModel: getSortedRowModel(), - enableSortingRemoval: false, // Always have a sort direction - initialState: { - sorting: [ - { - id: 'lastModified', - desc: true, // Default: newest first - }, - ], - }, - }); - - const gridFolderItems = files.filter(file => !file.isLeaf).map(file => -
    - e.stopPropagation()} - onChange={() => onSelectItem && onSelectItem(file.id)} - className="filelist-checkbox" - /> -
    onClickItem(file)}> - - {file.data.name} -
    -
    - ); - - const gridFileItems = files.filter(file => file.isLeaf).map(file => -
    - e.stopPropagation()} - onChange={() => onSelectItem && onSelectItem(file.id)} - className="filelist-checkbox" - /> -
    onClickItem(file)}> - -
    -
    - {file.data.name} -
    -
    - {formatBytes(file.data.size)} -
    -
    - ); - - return ( - <> - {files && (listStyle === "list") && ( -
    -
    -
    - {/* Table header */} - {table.getHeaderGroups().map(headerGroup => ( -
    - {headerGroup.headers.map(header => ( -
    - {header.isPlaceholder - ? null - : flexRender( - header.column.columnDef.header, - header.getContext() - )} - {header.column.getCanSort() && ( - - {header.column.getIsSorted() === 'asc' ? ' ↑' : header.column.getIsSorted() === 'desc' ? ' ↓' : ' ⇅'} - - )} -
    - ))} -
    - ))} - - {/* Table body */} - - {table.getRowModel().rows.map(row => ( -
    onClickItem(row.original)} - > - - {row.getVisibleCells().map(cell => ( -
    - {flexRender(cell.column.columnDef.cell, cell.getContext())} -
    - ))} -
    -
    - ))} -
    -
    -
    - )} - - {files && (listStyle === "grid") && ( -
    -
    -
    - {gridFolderItems} -
    -
    -
    - {gridFileItems} -
    -
    - )} - - ); -} diff --git a/ui/src/pages/Documents/Folder.jsx b/ui/src/pages/Documents/Folder.jsx deleted file mode 100644 index d6770d3c..00000000 --- a/ui/src/pages/Documents/Folder.jsx +++ /dev/null @@ -1,110 +0,0 @@ -import { useState } from "react"; -import Navbar from 'react-bootstrap/Navbar'; -import { Button, InputGroup, Form } from "react-bootstrap"; -import Modal from 'react-bootstrap/Modal'; -import { BsFillGridFill } from "react-icons/bs"; -import { FaList } from "react-icons/fa"; -import { ToggleButton, ToggleButtonGroup } from "react-bootstrap"; - -import apiservice from "../../services/api.service" -import styles from "./Documents.module.scss" - -import Upload from "./Upload" -import FileList from "./FileList"; -import NameTag from "../../components/NameTag" -import { toast } from "react-toastify"; - -export default function Folder({ selection, onSelect, onUpdate }) { - const [listStyle, setListStyle] = useState("list"); - const [folderName, setFolderName] = useState(""); - const [showCreateFileModal, setShowCreateFolder] = useState(false); - const [selectedIds, setSelectedIds] = useState([]); - - const folder = selection - - const onCreateFolderClick = async () => { - const res = await apiservice.createFolder({ name: folderName, parentId: selection.id }); - console.log("created folder with id", res.ID); - setFolderName(""); - setShowCreateFolder(false); - - onUpdate(); - } - - const onDeleteClick = async () => { - if (selectedIds.length === 0) return; - if (!window.confirm(`Are you sure you want to delete the selected item(s)?`)) return; - for (const id of selectedIds) { - const file = folder.children.find(f => f.id === id); - const name = file?.data?.name || id; - try { - await apiservice.deleteDocument(id); - toast.success(`Deleted ${name}`); - } catch (e) { - toast.error(`Failed to delete ${name}`); - } - } - setSelectedIds([]); - onUpdate(); - } - - const fileUploaded = () => { - onUpdate(); - } - - const handleSelectItem = (id) => { - setSelectedIds((prev) => - prev.includes(id) ? prev.filter((x) => x !== id) : [...prev, id] - ); - }; - - // this should generally not happen, but just in case - if (!folder) { - return "nothing selected" - } - return ( - <> - - { folder && (
    ) } -
    - - - -
    - - setListStyle(v)} name="abc"> - - - - - - - -
    - - - - - setShowCreateFolder(false)}> - - Create a new folder - - - - - setFolderName(e.currentTarget.value)} /> - - - - - - - - ); -} diff --git a/ui/src/pages/Documents/Tree.jsx b/ui/src/pages/Documents/Tree.jsx deleted file mode 100644 index 39e4680b..00000000 --- a/ui/src/pages/Documents/Tree.jsx +++ /dev/null @@ -1,71 +0,0 @@ -import { Tree } from 'react-arborist'; -import FileIcon from './FileIcon'; - -import styles from "./Documents.module.scss" - -const DocumentTree = ({ selection, onSelect, treeRef, term, entries, height = 700 }) => { - const onTreeSelect = (sel) => { - if (sel.length > 0) { - const node = sel[0]; - onSelect(node); - } - } - - function Node({ node, style, dragHandle }) { - return ( -
    -
    - - {node.data.name} -
    -
    - ); - } - - function Cursor({ top, left }) { - return
    ; - } - - const itemClassName = (item) => { - if (item.isFolder) return "treeitem-nodename is-folder"; - return "treeitem-nodename"; - } - - if (entries && !entries.length) { - return
    No documents
    ; - } - return ( -
    - { - if (treeRef.current == null) { - if (arg) treeRef.current = arg - } - - return treeRef.current - }} - data={entries} - selection={selection?.id} - rowHeight={36} - indent={36} - width="100%" - height={height} - renderCursor={Cursor} - searchTerm={term} - onSelect={onTreeSelect} - className="documents-tree" - disableEdit={true} - disableDrag={true} - disableDrop={true} - openByDefault={false} - > - {Node} - -
    - ) -} -export default DocumentTree; diff --git a/ui/src/pages/Documents/Upload.jsx b/ui/src/pages/Documents/Upload.jsx deleted file mode 100644 index f9ae15fc..00000000 --- a/ui/src/pages/Documents/Upload.jsx +++ /dev/null @@ -1,90 +0,0 @@ -import { useMemo, useState } from "react"; -import { useDropzone } from "react-dropzone"; -import Spinner from "react-bootstrap/Spinner"; -import { toast } from "react-toastify"; -import apiservice from "../../services/api.service"; - -import styles from "./Documents.module.scss"; - -async function uploadFilesInBatches(files, uploadFolder, batchSize = 100) { - const totalFiles = files.length; - let uploadedCount = 0; - - while (uploadedCount < totalFiles) { - const batch = files.slice(uploadedCount, uploadedCount + batchSize); - try { - await apiservice.upload(uploadFolder, batch); - uploadedCount += batchSize; - } catch (e) { - if (e.status === 409 && e.docId) { - if (window.confirm(`${e.message}\n\nOverwrite?`)) { - await apiservice.deleteDocument(e.docId); - await apiservice.upload(uploadFolder, batch); - uploadedCount += batchSize; - continue; - } - return; - } - console.error("Batch upload error:", e); - throw e; - } - } -} - -export default function StyledDropzone({filesUploaded, uploadFolder}) { - const [uploading, setUploading] = useState(false); - - var onDrop = async (acceptedFiles) => { - try { - setUploading(true); - // TODO: add loading and error handling - await uploadFilesInBatches(acceptedFiles, uploadFolder); - // await delay(100) - filesUploaded(); - } catch (e) { - toast.error("upload error" + e.toString()); - } finally { - setUploading(false); - } - }; - - const { - getRootProps, - getInputProps, - isDragActive, - isDragAccept, - isDragReject, - } = useDropzone({ - accept: { - "application/pdf":[], - "application/zip":[".zip", ".rmdoc"], - "application/epub+zip":[], - }, - onDropAccepted: onDrop, - maxSize: 1 * 1024 * 1024 * 1024, // 1GB - }); - - const className = useMemo(() => { - return `${styles.upload} - ${isDragActive ? styles.uploadActive : ""} - ${isDragAccept ? styles.uploadAccept : ""} - ${isDragReject ? styles.uploadReject : ""}`; - }, [isDragActive, isDragReject, isDragAccept]); - - const hint = - "Drag 'n' drop some files here, or click to select files to upload"; - if (!uploading) { - return ( -
    - -

    {hint}

    -
    - ); - } else { - return ( -
    - -
    - ); - } -} diff --git a/ui/src/pages/Documents/index.jsx b/ui/src/pages/Documents/index.jsx deleted file mode 100644 index 5a4ec05a..00000000 --- a/ui/src/pages/Documents/index.jsx +++ /dev/null @@ -1,261 +0,0 @@ -import DocumentTree from "./Tree"; -import apiservice from "../../services/api.service" -import { useEffect, useRef, useState } from "react"; -import { useParams, useHistory } from "react-router-dom"; -import { Container, Row, Col } from "react-bootstrap"; -import File from "./File"; -import Folder from "./Folder"; -import Navbar from 'react-bootstrap/Navbar'; -import { BsSearch } from "react-icons/bs"; -import Form from 'react-bootstrap/Form'; -import Button from 'react-bootstrap/Button'; -import InputGroup from 'react-bootstrap/InputGroup'; -import { toast } from "react-toastify"; -import { useAuthState } from "../../common/useAuthContext"; - -import styles from "./Documents.module.scss"; - -export default function DocumentList() { - const [selected, setSelected] = useState(null); - const [term, setTerm] = useState(""); - const [showSearch, setShowSearch] = useState(false); - const [counter, setCounter] = useState(0); - const [entries, setEntries] = useState([]) - const [initialSelectionSet, setInitialSelectionSet] = useState(false); - const [treeHeight, setTreeHeight] = useState(700); - - const { itemId } = useParams(); - const history = useHistory(); - const { state: { user } } = useAuthState(); - - const treeRef = useRef(null); - const treeContainerRef = useRef(null); - const lastSelectedId = useRef(null); - - useEffect(() => { - lastSelectedId.current = selected?.id || null; - }, [selected]); - - useEffect(() => { - if (lastSelectedId.current && treeRef.current && typeof treeRef.current.get === 'function') { - const node = treeRef.current.get(lastSelectedId.current); - if (node && node !== selected) { - setSelected(node); - } - } - }, [entries]); - - const toggleNode = (node) => { - if (node == null) { - return - } - if (typeof node.toggle !== 'function') { - return - } - - node.toggle() - } - - // select from tree. node must extend NodeApi from react-arborist - const onSelect = (node) => { - setSelected(node); - toggleNode(node); - - // Update URL with selected item ID - if (node && node.id) { - // Don't add root and trash to URL, keep as /documents - if (node.id === 'root' || node.id === 'trash') { - history.push('/documents'); - } else { - history.push(`/documents/${node.id}`); - } - } - }; - - const onUpdate = () => { - setCounter(prev => prev+1); - }; - - useEffect(() => { - // Only auto-select first item if there's no itemId in URL - if ( - !initialSelectionSet && - !itemId && - selected === null && - treeRef.current && - treeRef.current.root && - treeRef.current.root.children[0] - ) { - setSelected(treeRef.current.root.children[0]); - setInitialSelectionSet(true); - } - }, [entries, selected, initialSelectionSet, itemId]); - - useEffect(() => { - const resizeObserver = new ResizeObserver((event) => { - setTreeHeight(event[0].contentBoxSize[0].blockSize); - }); - - if (treeContainerRef.current) { - resizeObserver.observe(treeContainerRef.current); - } - - return () => { - resizeObserver.disconnect(); - }; - }, []); - - useEffect(() => { - const loadDocs = async () => { - const { Trash, Entries } = await apiservice.listDocument() - - const root = { - id: "root", - name: "My Files", - isFolder: true, - icon: "device", - children: Entries, - } - const trash = { - id: "trash", - name: "Trash", - isFolder: true, - icon: "trash", - children: Trash, - } - setEntries([root, trash]); - } - - loadDocs().catch(e => toast.error(e)); - },[counter]) - - // Helper function to recursively search for an item by ID in the tree - // Returns both the item and its parent chain - const findItemInEntries = (entries, targetId, parent = null) => { - for (const entry of entries) { - if (entry.id === targetId) { - return { item: entry, parent }; - } - if (entry.children && entry.children.length > 0) { - const found = findItemInEntries(entry.children, targetId, entry); - if (found) return found; - } - } - return null; - }; - - // Helper to build parent chain for breadcrumb - const buildParentChain = (parentItem) => { - if (!parentItem) return null; - - const parentNode = { - id: parentItem.id, - data: parentItem, - isLeaf: !parentItem.isFolder, - isRoot: parentItem.id === 'root' || parentItem.id === 'trash', - // Add a dummy toggle function for compatibility - toggle: () => {}, - }; - - // If this parent is not root/trash, try to find its parent - if (parentItem.id !== 'root' && parentItem.id !== 'trash') { - const grandparentResult = findItemInEntries(entries, parentItem.id); - if (grandparentResult && grandparentResult.parent) { - parentNode.parent = buildParentChain(grandparentResult.parent); - } - } else { - // This is root or trash - add the internal react-arborist root above it - parentNode.parent = { - id: '__REACT_ARBORIST_INTERNAL_ROOT__', - data: { id: '__REACT_ARBORIST_INTERNAL_ROOT__', name: '' }, - isLeaf: false, - parent: null, - }; - } - - return parentNode; - }; - - // Handle URL navigation: restore selection from URL parameter - useEffect(() => { - // Only proceed if we have entries and an itemId - if (!entries.length || !itemId || initialSelectionSet) { - return; - } - - // Find the item in our data - const result = findItemInEntries(entries, itemId); - - if (!result) { - // Item doesn't exist in our data - toast.warning(`Item not found, returning to root`); - history.push('/documents'); - return; - } - - const { item: foundItem, parent: parentItem } = result; - - // Create a pseudo-node object that matches what onSelect expects - // React-arborist wraps the data, so the node has both top-level properties - // and a 'data' property containing the actual item - const pseudoNode = { - id: foundItem.id, - data: foundItem, - isLeaf: !foundItem.isFolder, - children: (foundItem.children || []).map(child => ({ - id: child.id, - data: child, - isLeaf: !child.isFolder, - })), - parent: parentItem ? buildParentChain(parentItem) : null, - isRoot: foundItem.id === 'root' || foundItem.id === 'trash', - }; - - // Set the selection directly - setSelected(pseudoNode); - setInitialSelectionSet(true); - - // Try to open parent folders in the tree if possible - if (treeRef.current && typeof treeRef.current.openParents === 'function') { - // Give tree a moment to render, then open parents - setTimeout(() => { - if (treeRef.current && typeof treeRef.current.openParents === 'function') { - treeRef.current.openParents(itemId); - } - }, 100); - } - }, [entries, itemId, initialSelectionSet]); - - return ( - - - - -
    {user.UserID}
    - -
    - - {showSearch &&
    - - - - - - { setTerm(e.currentTarget.value); }} /> - -
    } - -
    - -
    - - -
    - {selected && selected.isLeaf && } - {selected && !selected.isLeaf && } -
    - -
    -
    - ); -} diff --git a/ui/src/pages/Home/index.jsx b/ui/src/pages/Home/index.jsx deleted file mode 100644 index dd139947..00000000 --- a/ui/src/pages/Home/index.jsx +++ /dev/null @@ -1,76 +0,0 @@ -import Container from "react-bootstrap/Container"; - -const Home = () => { - return ( - -
    -

    Welcome to your own reMarkable Cloud!

    -

    About

    -

    - This software is an unofficial replacement for the proprietary - reMarkable Cloud. In case you want to sync/backup your files - and have full control of the hosting environment, this is the - software for you. -

    -

    - It's is still a work in progress being, actively maintained over - on GitHub. -

    -

    Tips

    -
      -
    • -

      - You can use rmapi for managing files, - just specify the URL of your instance with the RMAPI_HOST variable like - so: RMAPI_HOST=https://rmfakecloud.example.com rmapi -

      -
        -
      • -

        - Do note that the original project is now unmaintained. You should consider - using this fork instead. -

        -
      • -
      -
    • -
    • -

      - Check out the online documentation to - learn more about the configuration options. Also read the README -

      -
    • -
    • -

      - You should also read the README, - to see the current status of the project and notes from the developers. -

      -
    • -
    • -

      - We support the Read on reMarkable Extension. Read more about it in the online documentation. -

      -
    • -
    • -

      - Documents will be uploaded to the selected (highlighted) directory. -

      -
        -
      • -

        - Select directories by clicking on them. -

        -
      • -
      • -

        - Clicking on selected directories again will open or close them respectively. -

        -
      • -
      -
    • -
    -
    -
    - ); -}; - -export default Home; diff --git a/ui/src/pages/Integrations/IntegrationModal.jsx b/ui/src/pages/Integrations/IntegrationModal.jsx deleted file mode 100644 index ae09adcc..00000000 --- a/ui/src/pages/Integrations/IntegrationModal.jsx +++ /dev/null @@ -1,220 +0,0 @@ -import React, { useState } from "react"; -import Form from "react-bootstrap/Form"; -import { Button, Card } from "react-bootstrap"; -import apiService from "../../services/api.service"; - -import { Alert } from "react-bootstrap"; - -export default function IntegrationModal(params) { - const { integration, onSave, headerText, onClose } = params; - - const [formErrors, setFormErrors] = useState({}); - const [integrationForm, setIntegrationForm] = useState({ - name: integration?.Name, - provider: integration?.Provider, - email: integration?.email, - username: integration?.Username, - password: integration?.Password, - address: integration?.Address, - activetransfers: integration?.ActiveTransfers, - insecure: integration?.Insecure, - accesstoken: integration?.Accesstoken, - path: integration?.Path, - endpoint: integration?.Endpoint, - }); - - function handleChange({ target }) { - setIntegrationForm({ ...integrationForm, [target.name]: target.value }); - } - - function formIsValid() { - const _errors = {}; - - if (!integrationForm.name) _errors.error = "name is required"; - - setFormErrors(_errors); - - return Object.keys(_errors).length === 0; - } - - async function handleSubmit(event) { - event.preventDefault(); - - if (!formIsValid()) return; - - try { - await apiService.updateintegration({ - id: integration.ID, - name: integrationForm.name, - provider: integrationForm.provider, - username: integrationForm.username, - password: integrationForm.password, - address: integrationForm.address, - activetransfers: integrationForm?.activetransfers, - insecure: integrationForm.insecure, - accesstoken: integrationForm.accesstoken, - path: integrationForm.path, - endpoint: integrationForm.endpoint, - }); - onSave(); - } catch (e) { - setFormErrors({ error: e.toString() }); - } - } - - if (!integration) return null; - return ( -
    - - - {headerText} - - -
    - - - IntegrationID - - - Provider - - - - - - - - - - Name - - - {(integrationForm.provider === "webdav" || integrationForm.provider === "ftp") && ( - <> - Address - - - )} - {(integrationForm.provider === "webdav" || integrationForm.provider === "ftp") && ( - <> - Username - - - )} - {(integrationForm.provider === "webdav" || integrationForm.provider === "ftp") && ( - <> - Password - - - )} - - {integrationForm.provider === "ftp" && ( - setIntegrationForm({ ...integrationForm, [target.name]: target.checked })} - label="Use actives transfers" - /> - )} - - {integrationForm.provider === "ics" && ( - <> - ICS URL - - setIntegrationForm({ ...integrationForm, [target.name]: target.checked })} - label="Ignore TLS certificate errors" - /> - - )} - - {integrationForm.provider === "localfs" && ( - <> - Path - - - )} - - {integrationForm.provider === "dropbox" && ( - <> - Access Token - - - )} - - {integrationForm.provider === "webhook" && ( - <> - Endpoint - - - )} -
    -
    - - - - -
    -
    - ); -} diff --git a/ui/src/pages/Integrations/NewIntegrationModal.jsx b/ui/src/pages/Integrations/NewIntegrationModal.jsx deleted file mode 100644 index 75f13711..00000000 --- a/ui/src/pages/Integrations/NewIntegrationModal.jsx +++ /dev/null @@ -1,198 +0,0 @@ -import React, { useState } from "react"; -import Form from "react-bootstrap/Form"; -import { Button, Card } from "react-bootstrap"; -import apiService from "../../services/api.service"; - -import { Alert } from "react-bootstrap"; - -export default function IntegrationProfileModal(params) { - const { onSave, onClose } = params; - - const [formErrors, setFormErrors] = useState({}); - const [formInfo, setFormInfo] = useState({}); - const [integrationForm, setIntegrationForm] = useState({ - name: "", - provider: "localfs", - }); - - function handleChange({ target }) { - setIntegrationForm({ ...integrationForm, [target.name]: target.value }); - } - - function formIsValid() { - const _errors = {}; - - if (!integrationForm.name) _errors.error = "name is required"; - - if (!integrationForm.provider) _errors.error = "provider is required"; - - setFormErrors(_errors); - - return Object.keys(_errors).length === 0; - } - - async function handleSubmit(event) { - event.preventDefault(); - - if (!formIsValid()) return; - - console.log(integrationForm) - try { - await apiService.createintegration(integrationForm); - setFormInfo({ message: "Created" }); - onSave(); - } catch (e) { - setFormErrors({ error: e.toString() }); - } - } - - return ( -
    - - - New Integration - - - - - - - Name - - - Provider - - - - - - - - - - {integrationForm.provider === "ics" && ( - <> - ICS URL - - setIntegrationForm({ ...integrationForm, [target.name]: target.checked })} - label="Ignore TLS certificate errors" - /> - - )} - - {(integrationForm.provider === "webdav" || integrationForm.provider === "ftp") && ( - <> - Address - - - )} - {(integrationForm.provider === "webdav" || integrationForm.provider === "ftp") && ( - <> - Username - - - )} - {(integrationForm.provider === "webdav" || integrationForm.provider === "ftp") && ( - <> - Password - - - )} - - {integrationForm.provider === "ftp" && ( - setIntegrationForm({ ...integrationForm, [target.name]: target.checked })} - label="Use actives transfers" - /> - )} - - {integrationForm.provider === "localfs" && ( - <> - Path - - - )} - - {integrationForm.provider === "dropbox" && ( - <> - Access Token - - - )} - - {integrationForm.provider === "webhook" && ( - <> - Endpoint - - - )} - - - - - - -
    - ); -} diff --git a/ui/src/pages/Integrations/index.tsx b/ui/src/pages/Integrations/index.tsx deleted file mode 100644 index 0a757cb8..00000000 --- a/ui/src/pages/Integrations/index.tsx +++ /dev/null @@ -1,117 +0,0 @@ -import React, {useState} from "react"; -import useFetch from "../../hooks/useFetch"; -import Spinner from "../../components/Spinner"; -import {Alert, Button, Card, Container, Modal, Table} from "react-bootstrap"; -import IntegrationModal from "./IntegrationModal"; -import NewIntegrationModal from "./NewIntegrationModal"; -import apiService from "../../services/api.service"; -import { toast } from "react-toastify"; -const integrationListUrl = "integrations"; - -const NewIntegration = 1; -const UpdateIntegration = 2; -const Integrations = () => { - const [index, setIndex] = useState(0); - const { data: integrationList, error, loading } = useFetch(`${integrationListUrl}`, index); - const [ state, setState ] = useState({showModal: 0, modalIntegration: null}); - const refresh = () =>{ - setIndex(previous => previous+1) - } - - function openModal(index: number) { - if (!integrationList) return; - const integration = integrationList[index]; - setState({ - showModal: UpdateIntegration, - modalIntegration: integration, - }); - } - function closeModal() { - setState({ - showModal: 0, - modalIntegration: null, - }); - } - - if (loading) { - return - } - - if (error) { - return ( - - An Error Occurred - {`Error ${error.status}: ${error.statusText}`} - - ); - } - - const newIntegration = e => { - setState({ - showModal: NewIntegration, - modalIntegration: null - }); - } - - const onSave = () => { - closeModal(); - refresh(); - } - - const remove = async (e, id, name) => { - e.preventDefault() - e.stopPropagation() - if (!window.confirm(`Are you sure you want to delete integration: ${name}?`)) - return false - - try{ - await apiService.deleteintegration(id) - refresh() - } catch(e){ - toast.error('Error:'+ e) - } - } - - return ( - -

    Integrations

    - - - - - - - - - - - - - {!integrationList.length && ( - - - - )} - {integrationList.map((i, index) => ( - openModal(index)} style={{ cursor: "pointer" }}> - - - - - - - ))} - -
    #IntegrationIdNameProvider
    No integration
    {index}{i.ID}{i.Name}{i.Provider}
    - - - - - - -
    -
    - ); -}; - -export default Integrations; diff --git a/ui/src/pages/Login/Login.module.scss b/ui/src/pages/Login/Login.module.scss deleted file mode 100644 index 55bfc033..00000000 --- a/ui/src/pages/Login/Login.module.scss +++ /dev/null @@ -1,29 +0,0 @@ -@import "../../theme.scss"; - -.container { - min-height: 85vh; - width: 100%; - display: flex; - justify-content: center; - align-items: center; -} - -.formContainer { - width: 300px; -} - -.error { - font-size: 0.8rem; - color: $reject; -} - -.loginForm { - display: flex; - flex-direction: column; -} - -.loginFormItem { - display: flex; - flex-direction: column; - margin-bottom: 10px; -} diff --git a/ui/src/pages/Login/index.jsx b/ui/src/pages/Login/index.jsx deleted file mode 100644 index 31497ef4..00000000 --- a/ui/src/pages/Login/index.jsx +++ /dev/null @@ -1,72 +0,0 @@ -import React, { useState } from "react"; -import { useHistory } from "react-router-dom"; -import { Button, Form } from "react-bootstrap"; - -import { useAuthState } from "../../common/useAuthContext"; -import { loginUser } from "../../common/actions"; - -import styles from "./Login.module.scss"; - -const Login = () => { - let history = useHistory(); - const [username, setUsername] = useState(""); - const [password, setPassword] = useState(""); - - const { state, dispatch } = useAuthState(); //read the values of loading and errorMessage from context - const { errorMessage, loading } = state; - - const handleLogin = async (e) => { - e.preventDefault(); - - let payload = { email: username, password }; - try { - await loginUser(dispatch, payload); - history.push("/documents"); //TODO: usenavigate or return redirect - } catch (error) { - console.log(error); - } - }; - - return ( -
    -
    - {errorMessage ?

    {errorMessage}

    : null} - -
    - - Username - setUsername(e.target.value)} - disabled={loading} - placeholder="Username" - autoComplete="username" - /> - - - - Password - setPassword(e.target.value)} - disabled={loading} - placeholder="Password" - autoComplete="current-password" - /> - - - -
    - -
    -
    - ); -}; - -export default Login; diff --git a/ui/src/pages/Profile/PasswordField.jsx b/ui/src/pages/Profile/PasswordField.jsx deleted file mode 100644 index f50443ae..00000000 --- a/ui/src/pages/Profile/PasswordField.jsx +++ /dev/null @@ -1,44 +0,0 @@ -import React, { useState, useRef, useEffect } from "react"; -import { Form, InputGroup, Button } from "react-bootstrap"; -import { FaEye } from "react-icons/fa"; - -function PasswordField(props) { - const [inputType, setInputType] = useState("password"); - const [inputCursorPosition, setInputCursorPosition] = useState(0); - const inputEl = useRef(null); - - function showHide(e) { - e.preventDefault(); - e.stopPropagation(); - setInputType(inputType === "text" ? "password" : "text"); - inputEl.current.focus(); - } - - useEffect(() => { - const init = () => { - inputEl.current.selectionStart = inputCursorPosition; - }; - init(); - }, [inputType, inputCursorPosition]); - - function saveCursorPosition(e) { - setInputCursorPosition(e.target.selectionStart); - } - - return ( - - - - - ); -} - -export default PasswordField; diff --git a/ui/src/pages/Profile/ResetPassword.jsx b/ui/src/pages/Profile/ResetPassword.jsx deleted file mode 100644 index 0b08cd1e..00000000 --- a/ui/src/pages/Profile/ResetPassword.jsx +++ /dev/null @@ -1,136 +0,0 @@ -import { useState } from "react"; -import Form from "react-bootstrap/Form"; -import Button from "react-bootstrap/Button"; - -import apiservice from "../../services/api.service"; -import { useAuthState } from "../../common/useAuthContext"; -import PasswordField from "./PasswordField"; -import { logout } from "../../common/actions"; - -export default function OwnUserProfile() { - const { state:{ user }, dispatch } = useAuthState(); - const userId = user.UserID - - const [formErrors, setFormErrors] = useState({}); - const [resetPasswordForm, setResetPasswordForm] = useState({ - userid: userId, - currentPassword: "", - newPassword: "", - confirmNewPassword: "", - }); - - function handleChange({ target }) { - console.log(resetPasswordForm) - setResetPasswordForm({ ...resetPasswordForm, [target.name]: target.value }); - } - - function formIsValid() { - const _errors = {}; - - // if (!resetPasswordForm.email) _errors.email = "email is required"; - if (!resetPasswordForm.currentPassword) - _errors.currentPassword = "currentPassword id is required"; - if (!resetPasswordForm.newPassword) - _errors.newPassword = "newPassword is required"; - if (!resetPasswordForm.confirmNewPassword) - _errors.confirmNewPassword = "confirm new password is required"; - if (resetPasswordForm.confirmNewPassword !== resetPasswordForm.newPassword) - _errors.confirmNewPassword = - "confirm new password must match new password"; - - setFormErrors(_errors); - - return Object.keys(_errors).length === 0; - } - - function handleSubmit(event) { - event.preventDefault(); - - if (!formIsValid()) return; - - apiservice.resetPassword(resetPasswordForm) - .then(r => { - if (r.ok) { - logout(dispatch) - - return - } - if (r.status === 400) { - return r.json() - } - throw new Error("unknown error: " + r.status) - }) - .then(j => { - if (j && j.error){ - setFormErrors(j) - return - } else { - setFormErrors({error:"invalid data"}) - } - }) - .catch(e => { - console.log(e) - setFormErrors({ - error:e.toString() - }) - }) - } - - return ( - <> -

    Reset password

    -
    - - Old Password - - {formErrors.currentPassword && ( -
    {formErrors.currentPassword}
    - )} -
    - - New Password - - {formErrors.newPassword && ( -
    {formErrors.newPassword}
    - )} -
    - - Confirm Password - - {formErrors.confirmNewPassword && ( -
    - {formErrors.confirmNewPassword} -
    - )} -
    - {formErrors.error && ( -
    - {formErrors.error} -
    - )} - - -
    - - ); -} diff --git a/ui/src/pages/Profile/UserProfile.jsx b/ui/src/pages/Profile/UserProfile.jsx deleted file mode 100644 index 50992b66..00000000 --- a/ui/src/pages/Profile/UserProfile.jsx +++ /dev/null @@ -1,122 +0,0 @@ -import React, { useState, useEffect } from "react"; -import { toast } from "react-toastify"; -import { useHistory } from "react-router-dom"; -import { toast } from "react-toastify"; -//import { useParams } from "react-router-dom"; -import Form from "react-bootstrap/Form"; -import Button from "react-bootstrap/Button"; - -import NoMatch from "../404"; -import Spinner from "../../components/Spinner"; -import useFetch from "../../hooks/useFetch"; -import apiService from "../../services/api.service"; - -const userListUrl = "users"; - -export default function UserProfile(userid) { - //const { userid } = useParams(); - - const { data: user, loading, error } = useFetch(`${userListUrl}/${userid}`); - const history = useHistory(); - - const [formErrors, setFormErrors] = useState({}); - const [profileForm, setProfileForm] = useState({ - newPassword: "", - email: "", - }); - - useEffect(() => { - if (!user) return; - - setProfileForm((oldState) => ({ - ...oldState, - email: user.email, - })); - }, [user]); - - function handleChange({ target }) { - setProfileForm({ ...profileForm, [target.name]: target.value }); - } - - function formIsValid() { - const _errors = {}; - - // if (!profileForm.newPassword) - // _errors.error = "newPassword is required"; - - setFormErrors(_errors); - - return Object.keys(_errors).length === 0; - } - - async function handleSubmit(event) { - event.preventDefault(); - - if (!formIsValid()) return; - - try { - await apiService.updateuser({ - userid, - newPassword: profileForm.newPassword, - email: profileForm.email, - }); - toast("updated"); - history.push("/users"); - } catch (e) { - setFormErrors({ error: e.toString() }); - } - } - - if (loading) return ; - if (error) { - return
    {error.message}
    ; - } - if (!user) return ; - - return ( -
    -
    - UserId - - - Email address - - - - New Password - - -
    -

    Integrations

    -
      - {user.integrations && user.integrations.map((x, i) =>
    • {x}
    • )} -
    -
    - {formErrors.error && ( -
    {formErrors.error}
    - )} - - -
    - ); -} diff --git a/ui/src/pages/Profile/index.jsx b/ui/src/pages/Profile/index.jsx deleted file mode 100644 index fcf22948..00000000 --- a/ui/src/pages/Profile/index.jsx +++ /dev/null @@ -1,23 +0,0 @@ -import Container from "react-bootstrap/Container"; -import Stack from "react-bootstrap/Stack"; -import { useAuthState } from "../../common/useAuthContext"; - -import ResetPassword from "./ResetPassword"; - -const Home = () => { - const { state: { user } } = useAuthState(); - return ( - - -
    - {user.scopes === "sync15" && (Using sync 15)} -
    -
    - -
    -
    -
    - ); -}; - -export default Home; diff --git a/ui/src/pages/ScreenShare/index.jsx b/ui/src/pages/ScreenShare/index.jsx deleted file mode 100644 index 32a1235c..00000000 --- a/ui/src/pages/ScreenShare/index.jsx +++ /dev/null @@ -1,685 +0,0 @@ - -import { useState, useEffect, useRef, useCallback } from "react"; -import { Container, Alert, Spinner, Button } from "react-bootstrap"; -import { BsGearFill, BsFullscreenExit, BsArrowCounterclockwise, BsArrowClockwise } from "react-icons/bs"; -import pako from "pako"; -import constants from "../../common/constants"; - -const STATUS = { - WAITING: "waiting", - CONNECTING: "connecting", - STREAMING: "streaming", - ERROR: "error", -}; - -const BACKDROP_PRESETS = { - white: "#FFFFFF", - "off-white": "#F9F6F1", - gray: "#2D2D2D", - black: "#000000", -}; - -function getBackdrop() { - return localStorage.getItem("screenshare-backdrop") || "black"; -} - -function setBackdropPref(val) { - localStorage.setItem("screenshare-backdrop", val); -} - -function getCustomColor() { - return localStorage.getItem("screenshare-custom-color") || "#808080"; -} - -function setCustomColorPref(val) { - localStorage.setItem("screenshare-custom-color", val); -} - -function resolveBackdrop(pref) { - return BACKDROP_PRESETS[pref] || pref; -} - -function isLightColor(hex) { - const c = hex.replace("#", ""); - const r = parseInt(c.substring(0, 2), 16); - const g = parseInt(c.substring(2, 4), 16); - const b = parseInt(c.substring(4, 6), 16); - return (r * 299 + g * 587 + b * 114) / 1000 > 128; -} - -function api(path, opts = {}) { - return fetch(`${constants.ROOT_URL}/screenshare/${path}`, { - headers: { "Content-Type": "application/json" }, - ...opts, - }); -} - -export default function ScreenShare() { - const [status, setStatus] = useState(STATUS.WAITING); - const [errorMsg, setErrorMsg] = useState(""); - const [poppedOut, setPoppedOut] = useState(false); - const [manualRotation, setManualRotation] = useState(0); - const [backdrop, setBackdrop] = useState(getBackdrop); - const [customColor, setCustomColor] = useState(getCustomColor); - const [showControls, setShowControls] = useState(false); - const [pinnedPosition, setPinnedPosition] = useState(null); - const [controlsPosition, setControlsPosition] = useState("right"); - const controlsRef = useRef(null); - const manualRotationRef = useRef(0); - - useEffect(() => { - if (!showControls) return; - const handler = (e) => { - if (controlsRef.current && !controlsRef.current.contains(e.target)) { - setShowControls(false); - } - }; - document.addEventListener("mousedown", handler); - return () => document.removeEventListener("mousedown", handler); - }, [showControls]); - - useEffect(() => { - if (!poppedOut) return; - const check = () => { - const canvas = videoRef.current; - if (!canvas || !canvas.width || !canvas.height) return; - const rot = ((manualRotation % 360) + 360) % 360; - const isRotated = rot % 180 !== 0; - const aspect = isRotated ? canvas.height / canvas.width : canvas.width / canvas.height; - const vpAspect = (window.innerWidth - 50) / window.innerHeight; - setControlsPosition(aspect < vpAspect ? "right" : "top"); - }; - check(); - window.addEventListener("resize", check); - return () => window.removeEventListener("resize", check); - }, [poppedOut, manualRotation]); - const videoRef = useRef(null); - const pcRef = useRef(null); - const dcRef = useRef(null); - const roomIdRef = useRef(null); - const tabletClientIdRef = useRef(null); - - const cleanup = useCallback(() => { - dcRef.current = null; - if (pcRef.current) { - pcRef.current.close(); - pcRef.current = null; - } - roomIdRef.current = null; - }, []); - - const setupPeerConnection = useCallback( - (iceServers) => { - if (pcRef.current) pcRef.current.close(); - - const config = {}; - if (iceServers?.length) { - config.iceServers = iceServers.map((s) => ({ - urls: s.url || s.urls, - username: s.username, - credential: s.credential, - })); - } - - const pc = new RTCPeerConnection(config); - pcRef.current = pc; - - pc.ondatachannel = (event) => { - const dc = event.channel; - dc.binaryType = "arraybuffer"; - dcRef.current = dc; - - let screenWidth = 0; - let screenHeight = 0; - const canvas = videoRef.current; - let ctx = null; - let lastPenX = 0; - let lastPenY = 0; - let rotation = 0; - const frameQueue = []; - let rafPending = false; - let pendingBuffer = null; - let pendingExpected = 0; - let pendingReceived = 0; - - function updateCursor() { - const cursor = document.getElementById("pen-cursor"); - if (!cursor || !canvas) return; - if (lastPenX === 0 && lastPenY === 0) { - cursor.style.display = "none"; - return; - } - const rect = canvas.getBoundingClientRect(); - const cw = canvas.width; - const ch = canvas.height; - const rot = ((manualRotationRef.current % 360) + 360) % 360; - const isLandscape = rot === 90 || rot === 270; - const renderedW = isLandscape ? rect.height : rect.width; - const renderedH = isLandscape ? rect.width : rect.height; - const scaleX = renderedW / cw; - const scaleY = renderedH / ch; - - const cx = (lastPenX - cw / 2) * scaleX; - const cy = (lastPenY - ch / 2) * scaleY; - - const rad = rot * Math.PI / 180; - const rx = cx * Math.cos(rad) - cy * Math.sin(rad); - const ry = cx * Math.sin(rad) + cy * Math.cos(rad); - - const screenX = rect.left + rect.width / 2 + rx; - const screenY = rect.top + rect.height / 2 + ry; - - cursor.style.display = "block"; - cursor.style.left = (screenX - 4) + "px"; - cursor.style.top = (screenY - 4) + "px"; - } - - dc.onopen = () => { - const header = new TextEncoder().encode("reMarkable"); - const buf = new ArrayBuffer(header.length + 2); - new Uint8Array(buf).set(header); - dc.send(buf); - pc.getStats().then(stats => { - stats.forEach(s => { - if (s.type === "candidate-pair" && s.state === "succeeded") { - const local = stats.get(s.localCandidateId); - const remote = stats.get(s.remoteCandidateId); - console.log("[screenshare] peer:", remote?.address, s.nominated ? "(active)" : ""); - } - }); - }); - }; - - dc.onmessage = (e) => { - const data = e.data; - if (!(data instanceof ArrayBuffer)) return; - const bytes = new Uint8Array(data); - if (bytes.length === 0) return; - - if (pendingBuffer && pendingExpected > 0) { - const chunk = new Uint8Array(data); - const remaining = pendingExpected - pendingReceived; - const take = Math.min(chunk.byteLength, remaining); - pendingBuffer.set(chunk.subarray(0, take), pendingReceived); - pendingReceived += take; - if (pendingReceived < pendingExpected) return; - } - - const msgType = pendingBuffer ? 0x00 : bytes[0]; - - // 'h' = header with screen dimensions - if (msgType === 0x68 && bytes.length >= 7) { - const view = new DataView(data); - screenWidth = view.getUint16(3, false); - screenHeight = view.getUint16(5, false); - if (canvas) { - canvas.width = screenWidth; - canvas.height = screenHeight; - ctx = canvas.getContext("2d", {willReadFrequently: true}); - } - setStatus(STATUS.STREAMING); - return; - } - - // 'g' = heartbeat, 'f' = flag - if (msgType === 0x67) return; - - if (msgType === 0x66 && bytes.length >= 5) { - const rv = new DataView(data, 1); - const rawDeg = rv.getUint32(0, false); - const newRotation = (360 - rawDeg) % 360; - if (newRotation !== rotation) { - const prev = rotation; - rotation = newRotation; - setManualRotation(r => { - const target = r + ((newRotation - prev + 540) % 360 - 180); - return target; - }); - } - return; - } - - // 'd' = pen position (5 bytes: [0x64, x_hi, x_lo, y_hi, y_lo]) - if (msgType === 0x64 && bytes.length === 5 && ctx) { - const penX = (bytes[1] << 8) | bytes[2]; - const penY = (bytes[3] << 8) | bytes[4]; - lastPenX = penX; - lastPenY = penY; - updateCursor(); - return; - } - - // frame data: [type(1), rectCount(2), deflatedSize(4), zlib...] - if ((pendingBuffer && pendingReceived >= pendingExpected) || (msgType === 0x00 && bytes.length > 7 && ctx)) { - let frameBytes; - if (pendingBuffer && pendingReceived >= pendingExpected) { - frameBytes = pendingBuffer; - pendingBuffer = null; - pendingExpected = 0; - pendingReceived = 0; - } else { - const declaredSize = new DataView(data, 3, 4).getUint32(0, false); - const expectedLen = 7 + declaredSize; - if (bytes.length < expectedLen) { - pendingBuffer = new Uint8Array(expectedLen); - pendingBuffer.set(new Uint8Array(data), 0); - pendingExpected = expectedLen; - pendingReceived = bytes.length; - return; - } - frameBytes = new Uint8Array(bytes); - } - - frameQueue.push(frameBytes); - if (!rafPending) { - rafPending = true; - requestAnimationFrame(() => { - rafPending = false; - while (frameQueue.length > 0) { - const frame = frameQueue.shift(); - try { - const fv = new DataView(frame.buffer, frame.byteOffset, frame.byteLength); - const rectCount = fv.getUint16(1, false); - const deflatedSize = fv.getUint32(3, false); - if (7 + deflatedSize > frame.byteLength) continue; - const compressed = new Uint8Array(frame.buffer.slice(frame.byteOffset + 7, frame.byteOffset + 7 + deflatedSize)); - const raw = pako.inflate(compressed); - if (!raw || raw.length < 12) continue; - - const rv = new DataView(raw.buffer); - let pos = 0; - for (let ri = 0; ri < rectCount; ri++) { - if (pos + 12 > raw.byteLength) break; - const regionX = rv.getUint16(pos, false); - const regionY = rv.getUint16(pos + 2, false); - const regionW = rv.getUint16(pos + 4, false); - const regionH = rv.getUint16(pos + 6, false); - const pxDataLen = rv.getUint32(pos + 8, false); - if (pos + 12 + pxDataLen > raw.byteLength) break; - - const pxView = new DataView(raw.buffer, pos + 12, pxDataLen); - const imgData = new ImageData(regionW, regionH); - const out = imgData.data; - const pixels = regionW * regionH; - for (let i = 0; i < pixels; i++) { - const val = pxView.getUint16(i * 2, true); - const r5 = (val >> 11) & 0x1f; - const g6 = (val >> 5) & 0x3f; - const b5 = val & 0x1f; - out[i * 4] = (r5 << 3) | (r5 >> 2); - out[i * 4 + 1] = (g6 << 2) | (g6 >> 4); - out[i * 4 + 2] = (b5 << 3) | (b5 >> 2); - out[i * 4 + 3] = 255; - } - pos += 12 + pxDataLen; - - if (regionX === 0 && regionY === 0 && - regionW >= screenWidth * 0.9 && regionH >= screenHeight * 0.9) { - screenWidth = regionW; - screenHeight = regionH; - canvas.width = screenWidth; - canvas.height = screenHeight; - } - ctx.putImageData(imgData, regionX, regionY); - } - - } catch (e) { - console.error("[screenshare] frame error:", e); - pendingBuffer = null; - pendingExpected = 0; - pendingReceived = 0; - } - } - }); - } - } - }; - - dc.onclose = () => { - if (!disconnectedRef.current) { - setStatus(STATUS.WAITING); - } - }; - }; - - // Don't trickle ICE candidates. The tablet crashes on mDNS candidates. - // The SDP answer already contains our ICE info for LAN connectivity. - pc.onicecandidate = () => {}; - - pc.oniceconnectionstatechange = () => - - pc.onconnectionstatechange = () => { - - if ( - pc.connectionState === "failed" || - pc.connectionState === "disconnected" - ) { - cleanup(); - if (!disconnectedRef.current) { - setStatus(STATUS.WAITING); - } - } - }; - - return pc; - }, - [cleanup] - ); - - const joinRoom = useCallback(async () => { - try { - setStatus(STATUS.CONNECTING); - - const offerRes = await api("offer"); - if (!offerRes.ok) throw new Error("Failed to get offer from device"); - - const data = await offerRes.json(); - roomIdRef.current = data.roomId; - - const pc = setupPeerConnection(data.iceServers); - - const msgs = data.messages || []; - const offerMsg = msgs.find(m => { - let p = m.payload; - if (p && p.type === "webtrc" && p.payload) p = p.payload; - return p && p.type === "offer"; - }); - - if (!offerMsg) throw new Error("No offer received from device"); - - if (offerMsg.clientId) tabletClientIdRef.current = offerMsg.clientId; - let offerPayload = offerMsg.payload; - if (offerPayload.type === "webtrc") offerPayload = offerPayload.payload; - - const sdp = offerPayload.description || offerPayload.sdp; - await pc.setRemoteDescription(new RTCSessionDescription({ type: "offer", sdp })); - - for (const msg of msgs) { - let inner = msg.payload; - if (!inner) continue; - if (inner.type === "webtrc" && inner.payload) inner = inner.payload; - if (inner.type === "candidate") { - await pc.addIceCandidate(new RTCIceCandidate({ - candidate: inner.candidate, - sdpMid: inner.mid || "0", - })); - } - } - - const answer = await pc.createAnswer(); - await pc.setLocalDescription(answer); - - // Wait for ICE gathering to complete so relay candidates are in the SDP - if (pc.iceGatheringState !== "complete") { - await new Promise((resolve) => { - const check = () => { - if (pc.iceGatheringState === "complete") { - pc.removeEventListener("icegatheringstatechange", check); - resolve(); - } - }; - pc.addEventListener("icegatheringstatechange", check); - setTimeout(resolve, 5000); - }); - } - - await api(`room/${data.roomId}/answer`, { - method: "POST", - body: JSON.stringify({ - targetClientId: offerMsg.clientId, - payload: { - type: "webtrc", - payload: { type: "answer", description: pc.localDescription.sdp }, - }, - }), - }); - } catch (e) { - setErrorMsg(e.message); - setStatus(STATUS.ERROR); - } - }, [setupPeerConnection]); - - useEffect(() => { - if (status !== STATUS.WAITING) return; - - const check = setInterval(async () => { - const r = await api("room").catch(() => null); - if (r?.ok) { - clearInterval(check); - joinRoom(); - } - }, 2000); - - return () => clearInterval(check); - }, [status, joinRoom]); - - useEffect(() => { manualRotationRef.current = manualRotation; }, [manualRotation]); - useEffect(() => cleanup, [cleanup]); - - const disconnectedRef = useRef(false); - - const disconnect = () => { - if (dcRef.current && dcRef.current.readyState === "open") { - const buf = new ArrayBuffer(4); - new DataView(buf).setInt32(0, 0x65, false); - dcRef.current.send(buf); - } - cleanup(); - setPoppedOut(false); - setShowControls(false); - disconnectedRef.current = true; - setStatus(STATUS.ERROR); - setErrorMsg("Disconnected. Start a new screenshare session from the tablet to reconnect."); - }; - - const reconnect = () => { - disconnectedRef.current = false; - setStatus(STATUS.WAITING); - }; - - - return ( - - {status === STATUS.ERROR && ( - - {errorMsg} - {disconnectedRef.current && ( - - )} - - )} - - {status === STATUS.WAITING && ( - - - Waiting for reMarkable to start screen sharing... - - )} - - {status === STATUS.CONNECTING && ( - - - Connecting to reMarkable... - - )} - -
    - {(() => { - const isRotated = ((manualRotation % 360) + 360) % 360 % 180 !== 0; - const canvasStyle = { - background: "#000", - borderRadius: poppedOut ? 0 : "4px", - transform: `rotate(${manualRotation}deg)`, - transition: "transform 0.3s ease", - }; - if (poppedOut) { - const pad = controlsPosition === "right" ? 56 : 0; - const topPad = controlsPosition === "top" ? 48 : 0; - if (isRotated) { - canvasStyle.maxWidth = `calc(100vh - ${topPad}px)`; - canvasStyle.maxHeight = `calc(100vw - ${pad}px)`; - } else { - canvasStyle.maxWidth = `calc(100vw - ${pad}px)`; - canvasStyle.maxHeight = `calc(100vh - ${topPad}px)`; - } - canvasStyle.width = "auto"; - } else if (isRotated) { - canvasStyle.height = "70vh"; - canvasStyle.width = "auto"; - } else { - canvasStyle.width = "100%"; - canvasStyle.maxWidth = "min(600px, 100%)"; - } - return ; - })()} -
    - {(() => { - const light = poppedOut && isLightColor(resolveBackdrop(backdrop)); - const btnVar = poppedOut ? (light ? "outline-dark" : "outline-light") : "outline-secondary"; - if (poppedOut) { - return ( -
    -
    - {controlsPosition === "right" ? ( - <> - - - - ) : ( - <> - - - - )} -
    - {showControls && ( -
    -
    - - -
    - -
    - {Object.entries(BACKDROP_PRESETS).map(([name, color]) => ( -
    -
    - )} -
    - ); - } - return ( -
    - - - - -
    - ); - })()} -
    - - ); -} diff --git a/ui/src/react-app-env.d.ts b/ui/src/react-app-env.d.ts deleted file mode 100644 index 6431bc5f..00000000 --- a/ui/src/react-app-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/ui/src/services/api.service.js b/ui/src/services/api.service.js deleted file mode 100644 index f763066e..00000000 --- a/ui/src/services/api.service.js +++ /dev/null @@ -1,229 +0,0 @@ -import constants from "../common/constants"; -import { jwtDecode } from "jwt-decode"; - -class ApiServices { - header() { - return { - "Content-Type": "application/json", - }; - } - checkLogin() { - if (localStorage.getItem("currentUser")) { - return fetch(`${constants.ROOT_URL}/`, { - method: "HEAD", - }).then(handleError); - } - } - login(loginData) { - return fetch(`${constants.ROOT_URL}/login`, { - method: "POST", - headers: this.header(), - body: JSON.stringify(loginData), - }) - .then((r) => { - if (!r.ok) { - throw new Error(r.statusText); - } - return r.text(); - }) - .then((text) => { - let user = jwtDecode(text); - localStorage.setItem("currentUser", JSON.stringify(user)); - localStorage.setItem("authToken", text); - return user; - }); - } - logout() { - removeUser(); - fetch(`${constants.ROOT_URL}/logout`); - } - - upload(parent, files) { - const formData = new FormData(); - formData.append("parent", parent); - files.forEach((f) => { - // file extensions which are not lowecase break the upload - - // set the file extension to be lower case - let sub = f.name.split(".") - const ext = sub[sub.length - 1].toLowerCase() - sub.pop() - sub.push(ext) - - // copy file data to new (lowecase) file - const newFile = new File([f], sub.join("."), {type: f.type}); - formData.append("file", newFile); - }); - - return fetch(`${constants.ROOT_URL}/documents/upload`, { - method: "POST", - body: formData, - }).then(async (r) => { - if (r.status === 409) { - const body = await r.json(); - const err = new Error(body.error); - err.status = 409; - err.docId = body.docId; - throw err; - } - if (!r.ok) { - const body = await r.json(); - throw new Error(body.error || r.statusText); - } - return r.json(); - }); - } - - listPasscodeResets() { - return fetch(`${constants.ROOT_URL}/passcode/resets`, { - method: "GET", - headers: this.header(), - }).then((r) => { - handleError(r); - return r.json(); - }); - } - approvePasscodeReset(uuid) { - return fetch(`${constants.ROOT_URL}/passcode/resets/${uuid}/approve`, { - method: "POST", - headers: this.header(), - }).then((r) => handleError(r)); - } - dismissPasscodeReset(uuid) { - return fetch(`${constants.ROOT_URL}/passcode/resets/${uuid}`, { - method: "DELETE", - headers: this.header(), - }).then((r) => handleError(r)); - } - - resetPassword(resetPasswordForm) { - return fetch(`${constants.ROOT_URL}/profile`, { - method: "POST", - headers: this.header(), - body: JSON.stringify({ - ...resetPasswordForm, - }), - }); - } - - listDocument() { - return fetch(`${constants.ROOT_URL}/documents`, { - method: "GET", - headers: this.header(), - }).then((r) => { - handleError(r); - return r.json(); - }); - } - getCode() { - return fetch(`${constants.ROOT_URL}/newcode`, { - method: "GET", - headers: this.header(), - }).then((r) => { - handleError(r); - return r.json(); - }); - } - - deleteDocument(id) { - return fetch(`${constants.ROOT_URL}/documents/${id}`, { - method: "DELETE", - headers: this.header(), - }).then((r) => handleError(r)); - } - download(id, exportType) { - let url = `${constants.ROOT_URL}/documents/${id}`; - if (exportType) url += `?type=${exportType}`; - return fetch(url, { - method: "GET", - }).then((r) => { - handleError(r); - return r.blob(); - }); - } - - createFolder(data) { - return fetch(`${constants.ROOT_URL}/folders`, { - method: "POST", - headers: this.header(), - body: JSON.stringify(data), - }).then((r) => { - handleError(r); - return r.json(); - }); - } - updateuser(usr) { - return fetch(`${constants.ROOT_URL}/users`, { - method: "PUT", - headers: this.header(), - body: JSON.stringify(usr), - }).then((r) => handleError(r)); - } - createuser(usr) { - return fetch(`${constants.ROOT_URL}/users`, { - method: "POST", - headers: this.header(), - body: JSON.stringify(usr), - }).then((r) => handleError(r)); - } - deleteuser(userid) { - return fetch(`${constants.ROOT_URL}/users/${userid}`, { - method: "DELETE", - headers: this.header(), - }).then((r) => handleError(r)); - } - - listintegration() { - return fetch(`${constants.ROOT_URL}/integrations`, { - method: "GET", - headers: this.header(), - }).then((r) => { - handleError(r); - return r.json(); - }); - } - updateintegration(integration) { - return fetch(`${constants.ROOT_URL}/integrations/${integration.id}`, { - method: "PUT", - headers: this.header(), - body: JSON.stringify(integration), - }).then((r) => handleError(r)); - } - createintegration(integration) { - return fetch(`${constants.ROOT_URL}/integrations`, { - method: "POST", - headers: this.header(), - body: JSON.stringify(integration), - }).then((r) => handleError(r)); - } - deleteintegration(integrationid) { - return fetch(`${constants.ROOT_URL}/integrations/${integrationid}`, { - method: "DELETE", - headers: this.header(), - }).then((r) => handleError(r)); - } -} - -function removeUser(){ - localStorage.removeItem("currentUser"); - localStorage.removeItem("authToken"); -} -function handleError(r) { - if (!r.ok) { - if (r.status === 401) { - removeUser(); - window.location.reload(true); - return - } - if (r.headers.get("Content-Type").startsWith("application/json")) { - return r.json().then(d => {throw new Error(d.error)}); - } - if (r.status === 400) { - return r.text().then(text => {throw new Error(text)}) - } - return Promise.reject(r.status) - } -} - -const apiServices = new ApiServices() -export default apiServices diff --git a/ui/src/setupTests.js b/ui/src/setupTests.js deleted file mode 100644 index 74b1a275..00000000 --- a/ui/src/setupTests.js +++ /dev/null @@ -1,5 +0,0 @@ -// jest-dom adds custom jest matchers for asserting on DOM nodes. -// allows you to do things like: -// expect(element).toHaveTextContent(/react/i) -// learn more: https://github.com/testing-library/jest-dom -import '@testing-library/jest-dom/extend-expect'; diff --git a/ui/src/theme.scss b/ui/src/theme.scss deleted file mode 100644 index d02364e9..00000000 --- a/ui/src/theme.scss +++ /dev/null @@ -1,12 +0,0 @@ -//$background1: #211E1C; -$background1: rgb(33,37,41); -$background2: #0f0f0f; - -$foreground1: #f8f7f6; -$foreground2: #e8e3d9; -$foreground3: #e4dbaf; - -$action-rgb: 238, 123, 48; -$action: #EE7B30; -$accept: #00e676; -$reject: #ff1744; diff --git a/ui/tsconfig.app.json b/ui/tsconfig.app.json deleted file mode 100644 index c6eae93c..00000000 --- a/ui/tsconfig.app.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "compilerOptions": { - "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", - "target": "ES2020", - "useDefineForClassFields": true, - "lib": ["ES2020", "DOM", "DOM.Iterable"], - "module": "ESNext", - "skipLibCheck": true, - - /* Bundler mode */ - "moduleResolution": "Bundler", - "allowImportingTsExtensions": true, - "isolatedModules": true, - "moduleDetection": "force", - "noEmit": true, - "jsx": "react-jsx", - - /* Linting */ - "strict": false, - "noUnusedLocals": false, - "noUnusedParameters": false, - "noFallthroughCasesInSwitch": true, - "noUncheckedSideEffectImports": true - }, - "include": ["src"] -} diff --git a/ui/tsconfig.json b/ui/tsconfig.json deleted file mode 100644 index 1ffef600..00000000 --- a/ui/tsconfig.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "files": [], - "references": [ - { "path": "./tsconfig.app.json" }, - { "path": "./tsconfig.node.json" } - ] -} diff --git a/ui/tsconfig.node.json b/ui/tsconfig.node.json deleted file mode 100644 index abcd7f0d..00000000 --- a/ui/tsconfig.node.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "compilerOptions": { - "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", - "target": "ES2022", - "lib": ["ES2023"], - "module": "ESNext", - "skipLibCheck": true, - - /* Bundler mode */ - "moduleResolution": "Bundler", - "allowImportingTsExtensions": true, - "isolatedModules": true, - "moduleDetection": "force", - "noEmit": true, - - /* Linting */ - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "noFallthroughCasesInSwitch": true, - "noUncheckedSideEffectImports": true - }, - "include": ["vite.config.ts"] -} diff --git a/ui/vite.config.ts b/ui/vite.config.ts deleted file mode 100644 index 488b3b32..00000000 --- a/ui/vite.config.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { defineConfig} from 'vite' -import react from '@vitejs/plugin-react-swc' - -// https://vite.dev/config/ -export default defineConfig({ - plugins: [react()], - build: { - rollupOptions: { - // external:["pdfjs-dist"], - output: { - manualChunks: function (id) { - // console.log(id); - if (id.includes("node_modules")) { - if (id.includes("pdf")) return "pdf"; - if (id.includes("react")) return "react"; - return "vendor"; - } - }, - }, - }, - }, - css: { - preprocessorOptions: { - scss: { - api: "modern-compiler", - silenceDeprecations: [ - "mixed-decls", - "color-functions", - "global-builtin", - "import", - ], - }, - }, - }, - server: { - open: true, - port: 3001, - proxy: { - "/ui/api": { - target: "http://localhost:3000", - changeOrigin: true - } - }, - }, -});