88 lines
2.3 KiB
TypeScript
88 lines
2.3 KiB
TypeScript
import { PageInfo } from "../components/page_info";
|
|
import { Display } from "../display/display";
|
|
import { PromiseCapability } from "../utils/promise_capability";
|
|
import { RenderingState } from "./rendering_queue";
|
|
|
|
class ViewPage {
|
|
pageInfo: PageInfo;
|
|
display: Display;
|
|
div: HTMLDivElement;
|
|
canvas?: HTMLCanvasElement;
|
|
renderingState: RenderingState;
|
|
lastScale: number;
|
|
#drawPromise?: PromiseCapability;
|
|
|
|
constructor(
|
|
container: HTMLDivElement,
|
|
pageInfo: PageInfo,
|
|
display: Display
|
|
) {
|
|
this.pageInfo = pageInfo;
|
|
this.display = display;
|
|
this.div = document.createElement('div');
|
|
this.div.classList.add('page');
|
|
this.renderingState = "none";
|
|
this.lastScale = 0;
|
|
this.#drawPromise = undefined;
|
|
|
|
container.append(this.div);
|
|
}
|
|
|
|
reset() {
|
|
if (this.renderingState === "drawing") {
|
|
throw new Error(`ViewPage is currently drawing.`);
|
|
}
|
|
|
|
if (this.canvas) {
|
|
this.canvas.width = 0;
|
|
this.canvas.height = 0;
|
|
this.canvas.remove();
|
|
}
|
|
|
|
this.renderingState = "none";
|
|
}
|
|
|
|
async draw() {
|
|
if (this.renderingState === "drawed" || this.renderingState === "drawing") {
|
|
throw new Error(`Invalid rendering state.`);
|
|
}
|
|
|
|
this.renderingState = "drawing";
|
|
this.#drawPromise = new PromiseCapability();
|
|
try {
|
|
const canvas = this.canvas = document.createElement('canvas');
|
|
const context = canvas.getContext('2d');
|
|
if (context === null) {
|
|
throw new RangeError('Out of memory');
|
|
}
|
|
|
|
const { bitmap } = await this.display.drawPageInfo(this.pageInfo);
|
|
canvas.width = bitmap.width;
|
|
canvas.height = bitmap.height;
|
|
canvas.style.width = `${Math.floor(this.pageInfo.width * this.display.scale)}px`;
|
|
canvas.style.height = `${Math.floor(this.pageInfo.height * this.display.scale)}px`;
|
|
context.drawImage(bitmap, 0, 0);
|
|
|
|
this.div.style.width = `${Math.floor(this.pageInfo.width * this.display.scale)}px`;
|
|
this.div.style.height = `${Math.floor(this.pageInfo.height * this.display.scale)}px`;
|
|
this.div.append(canvas);
|
|
} finally {
|
|
this.renderingState = "drawed";
|
|
this.#drawPromise.resolve(null);
|
|
}
|
|
}
|
|
|
|
async dispose() {
|
|
if (this.renderingState === "drawing") {
|
|
await this.#drawPromise?.promise;
|
|
}
|
|
|
|
this.reset();
|
|
this.div.remove();
|
|
}
|
|
}
|
|
|
|
export {
|
|
ViewPage,
|
|
}
|