From d4c1a1ec2d0f537d4729c388296ba7484183a5da Mon Sep 17 00:00:00 2001 From: ttop32 Date: Sun, 27 Oct 2024 11:36:47 +0900 Subject: [PATCH] update doq library --- doc/description.md | 2 + public/doq/CHANGELOG.md | 93 +++++++++ public/doq/LICENSE.txt | 21 ++ public/doq/README.md | 186 ++++++++++++++++++ public/doq/{ => addon}/app/config.js | 16 +- public/doq/{ => addon}/app/prefs.js | 17 +- public/doq/{ => addon}/app/reader.js | 19 +- public/doq/{ => addon}/app/theme.js | 21 +- public/doq/{ => addon}/app/toolbar.js | 0 public/doq/{ => addon}/doq.css | 5 +- public/doq/{ => addon}/doq.html | 0 public/doq/{ => addon}/doq.js | 4 +- public/doq/{ => addon}/images/checkMark.svg | 2 +- public/doq/addon/images/optionsIcon.svg | 4 + public/doq/addon/images/readerIcon-legacy.svg | 7 + public/doq/addon/images/readerIcon.svg | 9 + public/doq/{ => addon}/lib/annots.js | 0 public/doq/{ => addon}/lib/api.js | 2 +- public/doq/{ => addon}/lib/color.js | 0 public/doq/{ => addon}/lib/colors.json | 24 +++ public/doq/{ => addon}/lib/doq.js | 0 public/doq/{ => addon}/lib/engine.js | 26 ++- public/doq/{ => addon}/lib/utils.js | 0 public/doq/addon/options.json | 30 +++ public/doq/images/optionsIcon.svg | 4 - public/doq/images/readerIcon-legacy.svg | 4 - public/doq/images/readerIcon.svg | 7 - public/doq/package.json | 22 +++ 28 files changed, 478 insertions(+), 47 deletions(-) create mode 100644 public/doq/CHANGELOG.md create mode 100644 public/doq/LICENSE.txt create mode 100644 public/doq/README.md rename public/doq/{ => addon}/app/config.js (77%) rename public/doq/{ => addon}/app/prefs.js (68%) rename public/doq/{ => addon}/app/reader.js (87%) rename public/doq/{ => addon}/app/theme.js (76%) rename public/doq/{ => addon}/app/toolbar.js (100%) rename public/doq/{ => addon}/doq.css (96%) rename public/doq/{ => addon}/doq.html (100%) rename public/doq/{ => addon}/doq.js (96%) rename public/doq/{ => addon}/images/checkMark.svg (56%) create mode 100644 public/doq/addon/images/optionsIcon.svg create mode 100644 public/doq/addon/images/readerIcon-legacy.svg create mode 100644 public/doq/addon/images/readerIcon.svg rename public/doq/{ => addon}/lib/annots.js (100%) rename public/doq/{ => addon}/lib/api.js (98%) rename public/doq/{ => addon}/lib/color.js (100%) rename public/doq/{ => addon}/lib/colors.json (77%) rename public/doq/{ => addon}/lib/doq.js (100%) rename public/doq/{ => addon}/lib/engine.js (90%) rename public/doq/{ => addon}/lib/utils.js (100%) create mode 100644 public/doq/addon/options.json delete mode 100644 public/doq/images/optionsIcon.svg delete mode 100644 public/doq/images/readerIcon-legacy.svg delete mode 100644 public/doq/images/readerIcon.svg create mode 100644 public/doq/package.json diff --git a/doc/description.md b/doc/description.md index b34a6487..fa4d7d70 100644 --- a/doc/description.md +++ b/doc/description.md @@ -19,6 +19,8 @@ Mouseover Translate Any Language At Once English, Russian, Japanese, Chinese and so on # Change Log +- 0.1.155 + - update doq library - 0.1.154 - fix pdf dark mode - 0.1.153 diff --git a/public/doq/CHANGELOG.md b/public/doq/CHANGELOG.md new file mode 100644 index 00000000..bd670a4d --- /dev/null +++ b/public/doq/CHANGELOG.md @@ -0,0 +1,93 @@ +# v2.4 (2024-07-07) + +- Update: target PDF.js v4.1: support Stamps and Highlights +- Feature: enable non-viewer integration and general usage +- Refactor: separate the theme engine, components into modules +- Refactor: make awaiting PDF.js eventBus reusable +- Improvement: wrap setters to proactively calculate styles +- Improvement: drop storing canvas, minimize checking background +- Fix: map colors to gradient if no accents were provided + + +# v2.3 (2023-02-08) + +### Release version 2.3 + +- Update: target PDF.js 3.2, but retain legacy compatibility +- Update: new reader icon to match the revamped PDF.js UI +- Improvement: optimize saving canvas for faster rendering +- Feature: theme support for added text annotations +- Fix: avoid redraw when simply disabling invert mode +- Improvement: refactor method wrapping + + +# v2.2 (2022-10-30) + +### Release version 2.2 + +- Update: target PDF.js version 2.16 +- Improvement: handle transparent canvas styles +- Improvement: color calc based on BG of the text centre +- Feature: support for PDF.js annotation editor +- Fix: separate canvas data for different pages +- Fix: apply invert filter to individual pages + + +# v2.1 (2022-05-21) + +### Release version 2.1 + +- Update: target PDF.js version 2.13 +- Add themes: Nord and Firefox reader view +- Revamp UI: neat, minimal & simplified toolbar +- Feature: separate preferences based on OS theme +- Feature: configurable options to control behaviour +- Improvement: accessibility and color schemes +- Improvement: better performance when reader is off +- Fix: printing, thumbnails & some minor errors + + +# v2.0 (2021-11-05) + +### Release version 2.0 + +Major update, almost a complete rewrite. See c941877, 4b42993. + +#### Changes + +- Name, logo, core functionality: convert to Reader mode +- Stop tweaking the text layer; act directly on the canvas +- Properly apply a color scheme: preserve monotones and accents +- Accurate color transformations based on color science +- Process/leave images instead of show/hiding them +- Move the UI to its own separate (accessible) toolbar +- Remove the PDF.js wrapper; this is now addon-only + + +# v1.2 (2021-01-25) + +### Release version 1.2 + +- Feature: support multiple color schemes +- Feature: gestures for toggling toolbar and scrolling +- Improvement: change font resize buttons to html slider +- Fix: random text inflation in iOS Safari +- Fix: URL encode the path to the PDF file +- Refactor: linking CSS + + +# v1.1 (2020-12-19) + +### Release version 1.1 + +- Fix: make font resize persistent across page loads +- Feature: make Terminal Mode and Lights Off mutually exclusive +- Feature: plugin buttons are now highlighted when toggled On +- Feature: toolbar buttons now disappear only in small views +- Add: all plugin controls can now be accessed using Tab key +- Improvement: minor code refactor + + +# v1.0 (2020-12-17) + +### Release version 1.0 diff --git a/public/doq/LICENSE.txt b/public/doq/LICENSE.txt new file mode 100644 index 00000000..af4168fd --- /dev/null +++ b/public/doq/LICENSE.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020-2024 Shiva Prasad + +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/public/doq/README.md b/public/doq/README.md new file mode 100644 index 00000000..1586c85a --- /dev/null +++ b/public/doq/README.md @@ -0,0 +1,186 @@ +![doq logo](docs/logo/logo.png) + +# doq + +*doq* (pronounced as *doc-HUE*) is an add-on for Mozilla's excellent +[PDF.js][1] PDF viewer. + +It adds a **reader mode** where you can change the *colors* of the rendered PDF +files, to make it more comfortable to the eyes while reading. It works similar +to the reader mode in web browsers and theme options in eBook readers (except +that it cannot change the fonts or reflow text). + +*doq* was inspired by Safari's Reader View, and many terminal color schemes. + +![Screenshot with a light theme applied](docs/screenshots/reader-light.png) + +![Screenshot with a dark theme applied](docs/screenshots/reader-dark.png) + +## Usage + +If you simply want to use *doq* to read PDFs, try [*doqment*][6]. It is a +browser extension that bundles *doq* with PDF.js and opens all your PDF links. +You can skip the rest of this section. + +*doq* is written as a native [ES6 module][2]; there is no bundled version. +Hence it runs only in modern browsers that supports `import` and `export`. + +### Installation + +For your own deployment of the PDF.js viewer: + +1. [Download][3] the latest version (or clone this repo) +2. Copy the `addon/` and `lib/` directories to some directory on your server\ + (e.g. `/pdfjs-dist/addons/doq/`) +3. Include `addon/doq.js` as a module in the `viewer.html` of your deployment: + +```js + +``` +4. The global add-on object can be accessed later as `window.DOQ`. + +Alternatively, to simply import as an ES6 module: +`import doq from "path/to/lib/doq.js"`. + +Please check the exported functions of `lib/api.js` for the API for both the +global add-on object and the module import. + +The add-on targets the default generic viewer of PDF.js. It should also work in +custom viewers built on top of that. Feel free to open an issue if it breaks in +your viewer. + +### Defining colors + +Color schemes are defined in `lib/colors.json`, which you can extend. Only +6-digit RGB hex codes are currently supported. + +Each color scheme can have up to *three* tones. `background` and `foreground` +will replace the white and black colors in the document respectively; they also +define the gradient to which the rest of the greyscale gets interpolated. Other +colors map to their nearest color among `accents`, which can be specified per +tone and/or per scheme. They too get mapped to the gradient if no `accents` are +supplied. + +Included by default are the Firefox, Safari Reader View themes and the +[Solarized][4] color scheme. + +### Reader options + +Deployments can configure the following options by writing key-value pairs +directly to `doq.options` in Local storage (example follows): + +- `autoReader` [Boolean]: Whether to automatically apply the last-used reader + theme at launch. Default `true`. + +- `dynamicTheme` [Boolean]: Whether to save separate last-used preferences for + OS light/dark themes. Default `true`. + +- `softwareRender` [Boolean]: Whether to disable GPU acceleration of the canvas + and force CPU rendering. Default `false`. + +- `filterCSS` [String]: CSS property value to use for the Filter mode. Allowed + filter functions are `brightness`, `contrast`, `grayscale`, `hue-rotate`, + `invert`, `saturate` and `sepia`. Default `"invert(86%) hue-rotate(180deg)"`. + +#### Example: + +```js +/* Options have to be set before loading doq */ +const doqOptions = { dynamicTheme: false }; +localStorage.setItem("doq.options", JSON.stringify(doqOptions)); +``` + +## Features + +![Screenshot of the doq toolbar](docs/screenshots/addon-toolbar.png) + +- **Reader mode**: applies the selected theme to the document's background, + text and (optionally) to lines and other shapes. + +- **Blend images**: make images in the document blend with the new background + (or text color in the case of dark themes). + +- **Filter mode**: simply apply a CSS filter to the PDF if that is all you want + (faster but less pretty, especially with images). + +- **Intelligent application**: *doq* does not blindly change text color, but + tries to ensure the legibility of the text against the background in which it + is rendered. + +- **Color-science aware**: *doq* does color transformations in the + perceptually-uniform [CIELAB color space][5]. + +- **Accessibility**: the add-on toolbar is designed, following WCAG guidelines, + to be well accessible to keyboard/screen-reader users. + +- **Remember preferences**: *doq* loads the last used settings at launch, and + also updates them dynamically, based on the OS theme in use. + +### Performance + +*doq* recalculates the colors when the page is being rendered by PDF.js. This +incurs a small overhead, slightly reducing the renderer's performance (this +does not apply to the Filter mode as no processing is done there). *doq* tries +to minimize this overhead with many optimizations (like caching the calculation +results) so that speed improves after the initial render. + +(I guess this can be avoided altogether by implementing the logic directly +within the PDF.js library by modifying the source. But that requires digging +into PDF.js internals and also building and testing the entire thing, which I +have zero experience with. Hence I chose the add-on route.) + +## Why *doq*? + +Same reason that led Ethan Schoonover in developing the Solarized color scheme: +**ergonomics for eyes**. It is best summarized by this quote from the Solarized +Readme: + +> Black text on white from a computer display is akin to reading a book in +> direct sunlight and tires the eye. + +PDFs are perhaps the single largest source of "black text on white" out there +*that are not amenable to modification*. Designed to look the same everywhere, +the PDF format, unlike EPUB or plain text, does not offer the flexibility of +choosing its appearance while viewing. Yet it is the most popular document +format in existence. Not much talk about ergonomics. + +Another point is **accessibility**. The ability to adjust the colors of +documents can be immensly helpful to people with color vision deficiencies or +other low-vision conditions. Document creators are usually *blind* to such +concerns. + +The Web is heeding the call, with major browsers now having reader modes, and +more and more websites providing dark/night/low-contrast versions on their own. +But I could find scarcely any efforts in that direction in the domain of PDF +viewing. None of the viewers I tried offered any simple way to change the PDF's +appearance. In the end I decided to create a tool on my own. + +### OK, but why *PDF.js*? + +Perhaps a web app is still not the best tool to view a PDF document; but they +seem to be getting there. With modern browsers, PDF.js does a decent job, and +is FireFox's built-in PDF viewer. Being familiar with web and JS, I saw it as +the tool that I could quickly extend and develop my solution for, without +needing to pore over thousands of lines of code of a low-level PDF library. It +requires no additional software and is automatically cross-platform, meaning I +could have my solution immediately available on my smartphone also, without +much additional coding. + +The limitations do bug me sometimes. I would be delighted to see a *doq*-like +feature added to other popular PDF viewers also. I plan to work towards that +goal in future if time permits.\ +*Eye ergonomics matter.* + +Suggestions and contributions are welcome! + +--- + +This project started out slightly differently; versions 1.x are now legacy. If +interested, see v2.0 release notes for an overview of what changed, and why. + +[1]: https://mozilla.github.io/pdf.js/ +[2]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules +[3]: https://github.com/shivaprsd/doq/releases/latest +[4]: https://ethanschoonover.com/solarized/ +[5]: https://en.wikipedia.org/wiki/CIELAB_color_space +[6]: https://github.com/shivaprsd/doqment diff --git a/public/doq/app/config.js b/public/doq/addon/app/config.js similarity index 77% rename from public/doq/app/config.js rename to public/doq/addon/app/config.js index d62b23d4..93ab0431 100644 --- a/public/doq/app/config.js +++ b/public/doq/addon/app/config.js @@ -1,11 +1,21 @@ import { DOQ } from "../lib/engine.js"; + Object.assign(DOQ, { config: {}, preferences: {}, - options: { autoReader: true, dynamicTheme: true } + options: { + autoReader: true, + dynamicTheme: true, + softwareRender: false, + filterCSS: "" + } }); +/* CSS filter syntax: BOL [()]+ EOL */ +const filterRegEx = + /^((brightness|contrast|grayscale|hue-rotate|invert|saturate|sepia)\([^\)]+\)(\s+|$))+$/; + function getDefaultPrefs() { return { scheme: 0, tone: "0", @@ -22,7 +32,7 @@ function initConfig() { /* Legacy PDF.js support */ const pdfjsVer = pdfjsLib.version.split(".").map(Number); if (pdfjsVer[0] < 3) { - if (pdfjsVer[0] < 2 || pdfjsVer[1] < 7) { + if (pdfjsVer[0] < 2 || pdfjsVer[1] < 10) { console.warn("doq: unsupported PDF.js version " + pdfjsLib.version); } config.viewReader.classList.add("pdfjsLegacy"); @@ -47,4 +57,4 @@ function getAddonConfig() { }; } -export { DOQ, initConfig, getDefaultPrefs }; +export { DOQ, initConfig, getDefaultPrefs, filterRegEx }; diff --git a/public/doq/app/prefs.js b/public/doq/addon/app/prefs.js similarity index 68% rename from public/doq/app/prefs.js rename to public/doq/addon/app/prefs.js index 74593fdc..b4d609b2 100644 --- a/public/doq/app/prefs.js +++ b/public/doq/addon/app/prefs.js @@ -35,6 +35,21 @@ function getSysTheme() { return light ? "light" : "dark"; } +/* TEMPORARY: keep user prefs while adding Chromium theme */ +function migratePrefs() { + if (localStorage.getItem("doq.migrated-chromium-theme")) { + return; + } + for (const theme of ["light", "dark"]) { + const store = JSON.parse(localStorage.getItem(`doq.preferences.${theme}`)); + if (store?.scheme !== undefined) { + ++store.scheme; + localStorage.setItem(`doq.preferences.${theme}`, JSON.stringify(store)); + } + } + localStorage.setItem("doq.migrated-chromium-theme", "true"); +} + function readOptions() { const store = JSON.parse(localStorage.getItem("doq.options")); const { options } = DOQ; @@ -47,4 +62,4 @@ function readOptions() { return options; } -export { readOptions, readPreferences, updatePreference }; +export { readOptions, readPreferences, updatePreference, migratePrefs }; diff --git a/public/doq/app/reader.js b/public/doq/addon/app/reader.js similarity index 87% rename from public/doq/app/reader.js rename to public/doq/addon/app/reader.js index 5292e967..63f2680c 100644 --- a/public/doq/app/reader.js +++ b/public/doq/addon/app/reader.js @@ -1,12 +1,13 @@ import { DOQ } from "./config.js"; -import { updatePreference } from "./prefs.js"; +import { updatePreference, readOptions } from "./prefs.js"; import { wrapCanvas, setCanvasTheme } from "../lib/engine.js"; import { redrawAnnotation } from "../lib/annots.js"; function initReader() { - wrapCanvas(); + const options = readOptions(); const ctxp = CanvasRenderingContext2D.prototype; + wrapCanvas(options.softwareRender); const wrappedDrawImage = ctxp.drawImage; ctxp.drawImage = function() { @@ -28,14 +29,14 @@ function updateReaderColors(e) { if (pick == 0) { disableReader(redraw); - disableInvert(); + disableFilter(); } else if (pick == picker.elements.length - 1) { - enableInvert(redraw); + enableFilter(redraw); } else { const readerTone = setCanvasTheme(sel, +pick - 1); const isDarkTone = readerTone.colors.bg.lightness < 50; config.docStyle.setProperty("--reader-bg", readerTone.background); - disableInvert(); + disableFilter(); enableReader(redraw, isDarkTone); } updatePreference("tone", pick); @@ -63,15 +64,15 @@ function disableReader(redraw) { } } -function enableInvert(redraw) { +function enableFilter(redraw) { if (DOQ.flags.engineOn) { disableReader(redraw); } - DOQ.config.viewerClassList.add("invert"); + DOQ.config.viewerClassList.add("filter"); } -function disableInvert() { - DOQ.config.viewerClassList.remove("invert"); +function disableFilter() { + DOQ.config.viewerClassList.remove("filter"); } function toggleFlags(e) { diff --git a/public/doq/app/theme.js b/public/doq/addon/app/theme.js similarity index 76% rename from public/doq/app/theme.js rename to public/doq/addon/app/theme.js index 8c98c91b..c5d95dc4 100644 --- a/public/doq/app/theme.js +++ b/public/doq/addon/app/theme.js @@ -1,19 +1,24 @@ -import { DOQ } from "./config.js"; +import { DOQ, filterRegEx } from "./config.js"; import { updateReaderColors } from "./reader.js"; -import { readOptions, readPreferences, updatePreference } from "./prefs.js"; +import { readPreferences, updatePreference } from "./prefs.js"; function updateReaderState(e) { - const options = readOptions(); + const { config, options } = DOQ; const prefs = readPreferences(); - Object.assign(DOQ.flags, prefs.flags); - const { config } = DOQ; + Object.assign(DOQ.flags, prefs.flags); config.imageToggle.checked = prefs.flags.imagesOn; config.shapeToggle.checked = prefs.flags.shapesOn; config.schemeSelector.selectedIndex = prefs.scheme; - if (!e || options.dynamicTheme) { + const { dynamicTheme, filterCSS } = options; + if (filterRegEx.test(filterCSS) && CSS.supports("filter", filterCSS)) { + config.docStyle.setProperty("--filter-css", filterCSS); + } else if (filterCSS !== "") { + console.warn(`doq: unsupported filter property: "${filterCSS}"`); + } + if (!e || dynamicTheme) { updateColorScheme(e); } } @@ -50,8 +55,8 @@ function refreshTonePicker(picker, scheme) { scheme.tones.slice(0, 3).forEach(tone => { picker.appendChild(cloneWidget(toneWgt, null, null, i++, tone)); }); - picker.appendChild(cloneWidget(toneWgt, "invertTone", "Invert", i)); - picker.lastElementChild.classList.add("invert"); + picker.appendChild(cloneWidget(toneWgt, "filterTone", "Filter", i)); + picker.lastElementChild.classList.add("filter"); } function cloneWidget(template, id, title, value, tone) { diff --git a/public/doq/app/toolbar.js b/public/doq/addon/app/toolbar.js similarity index 100% rename from public/doq/app/toolbar.js rename to public/doq/addon/app/toolbar.js diff --git a/public/doq/doq.css b/public/doq/addon/doq.css similarity index 96% rename from public/doq/doq.css rename to public/doq/addon/doq.css index 0685b6f2..53415381 100644 --- a/public/doq/doq.css +++ b/public/doq/addon/doq.css @@ -1,6 +1,7 @@ /* Viewer customizations */ :root { --reader-bg: #F8F1E3; + --filter-css: invert(86%) hue-rotate(180deg); } .reader .pdfViewer .page, .reader .thumbnailImage { background-color: var(--reader-bg) !important; @@ -12,8 +13,8 @@ .reader.dark .canvasWrapper > .highlight { --blend-mode: overlay; } -.invert :is(.page, .thumbnailImage), .colorSwatch.invert { - filter: invert(86%); +.filter :is(.page, .thumbnailImage), .colorSwatch.filter { + filter: var(--filter-css); } /* Widgets */ diff --git a/public/doq/doq.html b/public/doq/addon/doq.html similarity index 100% rename from public/doq/doq.html rename to public/doq/addon/doq.html diff --git a/public/doq/doq.js b/public/doq/addon/doq.js similarity index 96% rename from public/doq/doq.js rename to public/doq/addon/doq.js index 612d366d..0f67a5b6 100644 --- a/public/doq/doq.js +++ b/public/doq/addon/doq.js @@ -4,6 +4,7 @@ import { addColorScheme } from "./lib/engine.js"; import { monitorAnnotationParams, handleInput } from "./lib/annots.js"; import { DOQ, initConfig } from "./app/config.js"; +import { migratePrefs } from "./app/prefs.js"; import { updateReaderState, updateColorScheme } from "./app/theme.js"; import { initReader, updateReaderColors, toggleFlags } from "./app/reader.js"; import updateToolbarPos, * as Toolbar from "./app/toolbar.js"; @@ -50,8 +51,9 @@ function installUI(html) { function load(colorSchemes) { colorSchemes.forEach(addColorScheme); - initReader() + initReader(); initConfig(); + migratePrefs(); /* TEMPORARY */ updateReaderState(); updateToolbarPos(); bindEvents(); diff --git a/public/doq/images/checkMark.svg b/public/doq/addon/images/checkMark.svg similarity index 56% rename from public/doq/images/checkMark.svg rename to public/doq/addon/images/checkMark.svg index 609ef60c..8eccef68 100644 --- a/public/doq/images/checkMark.svg +++ b/public/doq/addon/images/checkMark.svg @@ -1,4 +1,4 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/public/doq/addon/images/optionsIcon.svg b/public/doq/addon/images/optionsIcon.svg new file mode 100644 index 00000000..0db6c8d9 --- /dev/null +++ b/public/doq/addon/images/optionsIcon.svg @@ -0,0 +1,4 @@ + + \ No newline at end of file diff --git a/public/doq/addon/images/readerIcon-legacy.svg b/public/doq/addon/images/readerIcon-legacy.svg new file mode 100644 index 00000000..8b838cc1 --- /dev/null +++ b/public/doq/addon/images/readerIcon-legacy.svg @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/public/doq/addon/images/readerIcon.svg b/public/doq/addon/images/readerIcon.svg new file mode 100644 index 00000000..28b16367 --- /dev/null +++ b/public/doq/addon/images/readerIcon.svg @@ -0,0 +1,9 @@ + + + + + + + \ No newline at end of file diff --git a/public/doq/lib/annots.js b/public/doq/addon/lib/annots.js similarity index 100% rename from public/doq/lib/annots.js rename to public/doq/addon/lib/annots.js diff --git a/public/doq/lib/api.js b/public/doq/addon/lib/api.js similarity index 98% rename from public/doq/lib/api.js rename to public/doq/addon/lib/api.js index 83d87d53..83a76efe 100644 --- a/public/doq/lib/api.js +++ b/public/doq/addon/lib/api.js @@ -5,7 +5,7 @@ async function init(themes) { if (DOQ.initialized) return; - if (typeof themes === "undefined") { + if (themes === undefined) { themes = await loadThemes("colors.json"); } else if (!Array.isArray(themes)) { throw new Error("doq: argument 'themes' must be an array"); diff --git a/public/doq/lib/color.js b/public/doq/addon/lib/color.js similarity index 100% rename from public/doq/lib/color.js rename to public/doq/addon/lib/color.js diff --git a/public/doq/lib/colors.json b/public/doq/addon/lib/colors.json similarity index 77% rename from public/doq/lib/colors.json rename to public/doq/addon/lib/colors.json index 2023f03e..f2242bd2 100644 --- a/public/doq/lib/colors.json +++ b/public/doq/addon/lib/colors.json @@ -1,4 +1,28 @@ [ + { + "name": "Chrome", + "tones": [ + { + "name": "Yellow", + "background": "#FEEFC3", + "foreground": "#1F1F1F", + "accents": ["#174EA6", "#681DA8"] + }, + { + "name": "Blue", + "background": "#D2E3FC", + "foreground": "#1F1F1F", + "accents": ["#174EA6", "#681DA8"] + }, + { + "name": "Dark", + "background": "#202124", + "foreground": "#E3E3E3", + "accents": ["#8AB4F8", "#D7AEFB"] + } + ] + }, + { "name": "Firefox", "tones": [ diff --git a/public/doq/lib/doq.js b/public/doq/addon/lib/doq.js similarity index 100% rename from public/doq/lib/doq.js rename to public/doq/addon/lib/doq.js diff --git a/public/doq/lib/engine.js b/public/doq/addon/lib/engine.js similarity index 90% rename from public/doq/lib/engine.js rename to public/doq/addon/lib/engine.js index a72b0fd3..b3154e95 100644 --- a/public/doq/lib/engine.js +++ b/public/doq/addon/lib/engine.js @@ -35,11 +35,12 @@ function addColorScheme(scheme) { DOQ.colorSchemes.push(scheme); } -/* Wrap canvas drawing */ -function wrapCanvas() { - const checks = style => checkFlags() && checkStyle(style); +/* Wrap canvas drawing and rendering */ +function wrapCanvas(disableGPU = false) { const ctxp = CanvasRenderingContext2D.prototype; ctxp.origFillRect = ctxp.fillRect; + ctxp.origDrawImage = ctxp.drawImage; + const checks = style => checkFlags() && checkStyle(style); ["fill", "stroke"].forEach(f => { ["", "Rect"].forEach(e => { @@ -48,9 +49,22 @@ function wrapCanvas() { wrapSet(ctxp, f + "Style", getCanvasStyle, checks); }); ctxp.fillText = wrapAPI(ctxp.fillText, updateTextStyle, checks, "fillStyle"); - - ctxp.origDrawImage = ctxp.drawImage; ctxp.drawImage = wrapAPI(ctxp.drawImage, setCanvasCompOp, checkFlags); + wrapContext(disableGPU); +} + +/* Wrap canvas context to disable GPU accelerated rendering; + * can speed up getImageData() operations in some browsers */ +function wrapContext(disable) { + if (!disable) { + return; + } + const cvsp = HTMLCanvasElement.prototype; + const origGetContext = cvsp.getContext; + cvsp.getContext = function(type, attrs) { + attrs = Object.assign(attrs ?? {}, { willReadFrequently: true }); + return origGetContext.call(this, type, attrs); + }; } /* Method and setter wrapper closures */ @@ -97,7 +111,7 @@ function checkStyle(style) { return typeof(style) === "string"; /* is not gradient/pattern */ } - +/* Get style from cache, calculate if not present */ function getCanvasStyle(style, bg) { style = new Color(style); const key = style.hex + (bg?.hex || ""); diff --git a/public/doq/lib/utils.js b/public/doq/addon/lib/utils.js similarity index 100% rename from public/doq/lib/utils.js rename to public/doq/addon/lib/utils.js diff --git a/public/doq/addon/options.json b/public/doq/addon/options.json new file mode 100644 index 00000000..0b16d21e --- /dev/null +++ b/public/doq/addon/options.json @@ -0,0 +1,30 @@ +{ + "type": "schema", + "properties": { + "autoReader": { + "title": "Auto reader mode", + "description": "Whether to automatically apply the last-used reader theme at launch.", + "type": "boolean", + "default": true + }, + "dyanamicTheme": { + "title": "Dynamic theme", + "description": "Whether to save separate last-used preferences for OS light/dark themes.", + "type": "boolean", + "default": true + }, + "softwareRender": { + "title": "Force software rendering", + "description": "Whether to disable GPU acceleration of the canvas and force CPU rendering.", + "type": "boolean", + "default": false + }, + "filterCSS": { + "title": "Filter mode CSS", + "description": "CSS property value to use for the Filter mode. Accepted filters: 'brightness', 'contrast', 'grayscale', 'hue-rotate', 'invert', 'saturate', and 'sepia'.", + "type": "string", + "pattern": "^((brightness|contrast|grayscale|hue-rotate|invert|saturate|sepia)\\([^\\)]+\\)(\\s+|$))+$", + "default": "invert(86%) hue-rotate(180deg)" + } + } +} diff --git a/public/doq/images/optionsIcon.svg b/public/doq/images/optionsIcon.svg deleted file mode 100644 index 1e717f92..00000000 --- a/public/doq/images/optionsIcon.svg +++ /dev/null @@ -1,4 +0,0 @@ - - \ No newline at end of file diff --git a/public/doq/images/readerIcon-legacy.svg b/public/doq/images/readerIcon-legacy.svg deleted file mode 100644 index 462ef7df..00000000 --- a/public/doq/images/readerIcon-legacy.svg +++ /dev/null @@ -1,4 +0,0 @@ - - \ No newline at end of file diff --git a/public/doq/images/readerIcon.svg b/public/doq/images/readerIcon.svg deleted file mode 100644 index c374ec0b..00000000 --- a/public/doq/images/readerIcon.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/public/doq/package.json b/public/doq/package.json new file mode 100644 index 00000000..6554bdfd --- /dev/null +++ b/public/doq/package.json @@ -0,0 +1,22 @@ +{ + "name": "doq", + "description": "The missing reader mode/color schemes tool for PDFs.", + "homepage": "https://github.com/shivaprsd/doq", + "keywords": [ "pdf", "pdf.js", "reader mode", "color schemes" ], + "license": "MIT", + "author": "Shiva Prasad ", + "contributors": [], + "dependencies": {}, + "repository": { + "type": "git", + "url": "https://github.com/shivaprsd/doq.git" + }, + "type": "module", + "target": "@mozilla/pdf.js", + "main": "lib/doq.js", + "version": "2.4", + "pdfjs_version": { + "minimum": "2.10.377", + "target": "4.1.392" + } +}