123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101 |
- /*
- * encantar.js
- * GPU-accelerated Augmented Reality for the web
- * Copyright (C) 2022-2024 Alexandre Martins <alemartf(at)gmail.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
- * resolution.ts
- * Resolution utilities
- */
-
- import Speedy from 'speedy-vision';
- import { SpeedySize } from 'speedy-vision/types/core/speedy-size';
- import { IllegalArgumentError } from './errors';
-
- type Digit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9';
- type EvenDigit = '0' | '2' | '4' | '6' | '8';
- type PositiveDigit = '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9';
- type OptionalDigit = Digit | '';
- type CustomResolution = `${PositiveDigit}${OptionalDigit}${Digit}${EvenDigit}p`;
- type ResolutionAlias = 'xs' | 'xs+' | 'sm' | 'sm+' | 'md' | 'md+' | 'lg' | 'lg+' | 'xl' | 'xl+' | 'xxl';
-
- /** Resolution type */
- export type Resolution = ResolutionAlias | CustomResolution;
-
- /** A regex that identifies custom resolutions */
- const CUSTOM_RESOLUTION_REGEX = /^[1-9][0-9]?[0-9][02468]p$/;
-
- /** Reference heights when in landscape mode, measured in pixels, for all aliases */
- const ALIAS_TO_HEIGHT: { readonly [R in ResolutionAlias]: number } = {
- 'xs' : 120,
- 'xs+': 144,
- 'sm' : 240,
- 'sm+': 288,
- 'md' : 320,
- 'md+': 360,
- 'lg' : 480,
- 'lg+': 600,
- 'xl' : 720,
- 'xl+': 900,
- 'xxl': 1080,
- };
-
- /**
- * Convert a resolution type to a (width, height) pair
- * @param resolution resolution type
- * @param aspectRatio desired width / height ratio
- * @returns size in pixels
- */
- export function computeResolution(resolution: Resolution, aspectRatio: number): SpeedySize
- {
- const referenceHeight = parseHeight(resolution);
- let width = 0, height = 0;
-
- if(Number.isNaN(referenceHeight))
- throw new IllegalArgumentError('Invalid resolution: ' + resolution);
- else if(aspectRatio <= 0)
- throw new IllegalArgumentError('Invalid aspect ratio: ' + aspectRatio);
-
- if(aspectRatio >= 1) {
- // landscape
- height = referenceHeight;
- width = Math.floor(height * aspectRatio);
- width += width % 2;
- }
- else {
- // portrait
- width = referenceHeight;
- height = Math.floor(width / aspectRatio);
- height += height % 2;
- }
-
- return Speedy.Size(width, height);
- }
-
- /**
- * Get the height in pixels of a resolution
- * @param resolution resolution type
- * @returns the height in pixels, or NaN on error
- */
- function parseHeight(resolution: Resolution): number
- {
- if(ALIAS_TO_HEIGHT.hasOwnProperty(resolution))
- return ALIAS_TO_HEIGHT[resolution as ResolutionAlias];
-
- if(CUSTOM_RESOLUTION_REGEX.test(resolution))
- return parseInt(resolution);
-
- return Number.NaN;
- }
|