Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for devicePixelRatio and more crips images #182

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ui/demo/components/Reader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export const Reader: React.FunctionComponent<RouteComponentProps> = () => {
// ref for the scrollable region where the pages are rendered
const pdfScrollableRef = React.createRef<HTMLDivElement>();

const samplePdfUrl = 'https://arxiv.org/pdf/2112.07873.pdf';
const samplePdfUrl = 'https://arxiv.org/pdf/2111.07945.pdf';
const sampleS2airsUrl =
'http://s2airs.prod.s2.allenai.org/v1/pdf_data?pdf_sha=9b79eb8d21c8a832daedbfc6d8c31bebe0da3ed5';

Expand Down
2 changes: 2 additions & 0 deletions ui/library/dist/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -328,9 +328,11 @@ declare module '@allenai/pdf-components/src/context/TransformContext' {
import * as React from 'react';
import { PageRotation } from '@allenai/pdf-components/src/utils/rotate';
export interface ITransformContext {
pixelRatio: number;
rotation: PageRotation;
scale: number;
zoomMultiplier: number;
setPixelRatio: (devicePixelRatio: number) => void;
setRotation: (rotation: PageRotation) => void;
setScale: (scale: number) => void;
setZoomMultiplier: (zoom: number) => void;
Expand Down
2 changes: 1 addition & 1 deletion ui/library/dist/pdf-components.js

Large diffs are not rendered by default.

3 changes: 1 addition & 2 deletions ui/library/src/context/ContextProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,8 @@ export const ContextProvider: React.FunctionComponent<Props> = ({ children }: Pr
const scrollProps = useScrollContextProps();
const pageRenderProps = usePageRenderContextProps({
pdfDocProxy: documentProps.pdfDocProxy,
pixelRatio: transformProps.pixelRatio,
scale: transformProps.scale,
rotation: transformProps.rotation,
zoomMultiplier: transformProps.zoomMultiplier,
visiblePageRatios: scrollProps.visiblePageRatios,
});

Expand Down
41 changes: 27 additions & 14 deletions ui/library/src/context/PageRenderContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { pdfjs } from 'react-pdf';
import { PageNumber } from '../components/types/page';
import { Nullable } from '../components/types/utils';
import { logProviderWarning } from '../utils/provider';
import { PageRotation } from '../utils/rotate';

export type RenderState = {
promise: Promise<string>;
Expand Down Expand Up @@ -38,15 +37,13 @@ export const PageRenderContext = React.createContext<IPageRenderContext>({

export function usePageRenderContextProps({
pdfDocProxy,
pixelRatio,
scale,
rotation,
zoomMultiplier,
visiblePageRatios,
}: {
pdfDocProxy?: pdfjs.PDFDocumentProxy;
pixelRatio: number;
scale: number;
rotation: PageRotation;
zoomMultiplier: number;
visiblePageRatios: Map<number, number>;
}): IPageRenderContext {
const [pageRenderStates, _setPageRenderStates] = React.useState<PageNumberToRenderStateMap>(
Expand Down Expand Up @@ -119,9 +116,8 @@ export function usePageRenderContextProps({
const promise = buildPageObjectURL({
pageNumber,
pdfDocProxy,
pixelRatio,
scale,
rotation,
zoomMultiplier,
});
const renderState: RenderState = {
promise,
Expand All @@ -139,7 +135,7 @@ export function usePageRenderContextProps({
setPageRenderStates(newPageRenderStates);
return promise;
},
[pageRenderStates, pdfDocProxy, scale, rotation, zoomMultiplier]
[pageRenderStates, pdfDocProxy, scale]
);

React.useEffect(() => {
Expand All @@ -151,6 +147,21 @@ export function usePageRenderContextProps({
}
}, [pageRenderStates, visiblePageRatios]);

// Flush page render states when scale changes
React.useEffect(() => {
// Clean memory of old generated images
for (const [, renderState] of pageRenderStatesRef.current) {
if (renderState.objectURL) {
URL.revokeObjectURL(renderState.objectURL);
}
}

// Clear all page render states, so pages can rebuild images
const newPageRenderStates = new Map();
Object.freeze(newPageRenderStates);
setPageRenderStates(newPageRenderStates);
}, [scale, pixelRatio]);

return {
pageRenderStates,
getObjectURLForPage,
Expand All @@ -159,30 +170,32 @@ export function usePageRenderContextProps({
};
}

// This boost causes the rendered image to be scaled up by this amount
const SCALE_BOOST = 2;

// Generate an object url for a given page, rendered in a shared canvas
async function buildPageObjectURL({
pageNumber,
pdfDocProxy,
pixelRatio = window.devicePixelRatio || 1,
scale = 1,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
rotation = PageRotation.Rotate0,
zoomMultiplier = 1.2,
imageType = 'image/png',
imageQuality = 1.0,
}: {
pageNumber: number;
pdfDocProxy: pdfjs.PDFDocumentProxy;
pixelRatio?: number;
scale?: number;
rotation?: PageRotation;
zoomMultiplier?: number;
imageType?: string;
imageQuality?: number;
}): Promise<string> {
const pageProxy = await pdfDocProxy.getPage(pageNumber);

const blob: Nullable<Blob> = await useRenderCanvas(async canvas => {
// Render page in a canvas
const viewport = pageProxy.getViewport({ scale: scale * zoomMultiplier * devicePixelRatio });
const viewport = pageProxy.getViewport({
scale: scale * pixelRatio * SCALE_BOOST,
});
canvas.height = viewport.height;
canvas.width = viewport.width;
const canvasContext = canvas.getContext('2d');
Expand Down
9 changes: 9 additions & 0 deletions ui/library/src/context/TransformContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,24 @@ import { logProviderWarning } from '../utils/provider';
import { PageRotation } from '../utils/rotate';

export interface ITransformContext {
pixelRatio: number;
rotation: PageRotation;
scale: number;
zoomMultiplier: number;
setPixelRatio: (devicePixelRatio: number) => void;
setRotation: (rotation: PageRotation) => void;
setScale: (scale: number) => void;
setZoomMultiplier: (zoom: number) => void;
}

export const TransformContext = React.createContext<ITransformContext>({
pixelRatio: window.devicePixelRatio || 1,
rotation: PageRotation.Rotate0,
scale: 1,
zoomMultiplier: 1.2,
setPixelRatio: pixelRatio => {
logProviderWarning(`setPixelRatio(${pixelRatio})`, 'TransformContext');
},
setRotation: rotation => {
logProviderWarning(`setRotation(${rotation})`, 'TransformContext');
},
Expand All @@ -28,13 +34,16 @@ export const TransformContext = React.createContext<ITransformContext>({
});

export function useTransformContextProps(): ITransformContext {
const [pixelRatio, setPixelRatio] = React.useState<number>(window.devicePixelRatio || 1);
const [rotation, setRotation] = React.useState<PageRotation>(PageRotation.Rotate0);
const [scale, setScale] = React.useState<number>(1.0);
const [zoomMultiplier, setZoomMultiplier] = React.useState<number>(1.2);

return {
pixelRatio,
rotation,
scale,
setPixelRatio,
setRotation,
setScale,
setZoomMultiplier,
Expand Down