81 lines
2.7 KiB
TypeScript
81 lines
2.7 KiB
TypeScript
export type ReaderSize = {
|
|
width: number;
|
|
height: number;
|
|
};
|
|
|
|
export const READER_ZOOM_MIN = 50;
|
|
export const READER_ZOOM_MAX = 300;
|
|
export const READER_ZOOM_STEP = 25;
|
|
export const READER_ZOOM_DEFAULT = 100;
|
|
|
|
export function clampReaderZoom(zoom: number) {
|
|
const steppedZoom = Math.round(zoom / READER_ZOOM_STEP) * READER_ZOOM_STEP;
|
|
return Math.max(READER_ZOOM_MIN, Math.min(steppedZoom, READER_ZOOM_MAX));
|
|
}
|
|
|
|
export function readerZoomLabel(zoom: number) {
|
|
return `${clampReaderZoom(zoom)} %`;
|
|
}
|
|
|
|
export function readerZoomFactor(zoom: number) {
|
|
return clampReaderZoom(zoom) / 100;
|
|
}
|
|
|
|
export function clampReaderPage(page: number, pageCount: number) {
|
|
const safePageCount = Math.max(1, Math.floor(pageCount));
|
|
return Math.max(1, Math.min(Math.floor(page), safePageCount));
|
|
}
|
|
|
|
export function previousReaderPage(page: number, pageCount: number) {
|
|
return clampReaderPage(page - 1, pageCount);
|
|
}
|
|
|
|
export function nextReaderPage(page: number, pageCount: number) {
|
|
return clampReaderPage(page + 1, pageCount);
|
|
}
|
|
|
|
export function readerPositionLabel(page: number, pageCount: number) {
|
|
return `Page ${clampReaderPage(page, pageCount)} / ${Math.max(1, Math.floor(pageCount))}`;
|
|
}
|
|
|
|
export function containPageSize(viewport: ReaderSize, page: ReaderSize): ReaderSize {
|
|
if (viewport.width <= 0 || viewport.height <= 0 || page.width <= 0 || page.height <= 0) {
|
|
return { width: 0, height: 0 };
|
|
}
|
|
const scale = Math.min(viewport.width / page.width, viewport.height / page.height);
|
|
return {
|
|
width: Math.max(1, Math.floor(page.width * scale)),
|
|
height: Math.max(1, Math.floor(page.height * scale))
|
|
};
|
|
}
|
|
|
|
export function orientedContainPageSize(viewport: ReaderSize, page: ReaderSize): ReaderSize {
|
|
if (viewport.width <= 0 || viewport.height <= 0 || page.width <= 0 || page.height <= 0) {
|
|
return { width: 0, height: 0 };
|
|
}
|
|
const fitByHeight = page.height >= page.width;
|
|
const primaryScale = fitByHeight ? viewport.height / page.height : viewport.width / page.width;
|
|
const crossScale = fitByHeight ? viewport.width / page.width : viewport.height / page.height;
|
|
const scale = Math.min(primaryScale, crossScale);
|
|
return {
|
|
width: Math.max(1, Math.floor(page.width * scale)),
|
|
height: Math.max(1, Math.floor(page.height * scale))
|
|
};
|
|
}
|
|
|
|
export function zoomReaderSize(size: ReaderSize, zoom: number): ReaderSize {
|
|
const factor = readerZoomFactor(zoom);
|
|
return {
|
|
width: Math.max(1, Math.floor(size.width * factor)),
|
|
height: Math.max(1, Math.floor(size.height * factor))
|
|
};
|
|
}
|
|
|
|
export function readableViewportSize(size: ReaderSize): ReaderSize | null {
|
|
if (size.width < 32 || size.height < 32) return null;
|
|
return {
|
|
width: Math.floor(size.width),
|
|
height: Math.floor(size.height)
|
|
};
|
|
}
|