Spaces:
Running
Running
| // Output sizes: any side 128…1024 in steps of 16; these are the presets on the menu. The app | |
| // shows only the ones inside the engine's limits (max side and area budget, App.svelte), so the | |
| // list can run ahead of what a given build accepts. The examples' desktop and mobile sizes | |
| // (examples.js) are all listed here. | |
| export const SIZES = [ | |
| [128, 128], | |
| [256, 256], | |
| [384, 384], | |
| [512, 512], | |
| [640, 640], | |
| [768, 768], | |
| [1024, 1024], | |
| [320, 192], | |
| [192, 320], | |
| [480, 288], | |
| [288, 480], | |
| [384, 256], | |
| [256, 384], | |
| [480, 320], | |
| [320, 480], | |
| [512, 256], | |
| [256, 512], | |
| [448, 256], | |
| [256, 448], | |
| [768, 512], | |
| [512, 768], | |
| [960, 640], | |
| [640, 960], | |
| [1024, 576], | |
| [576, 1024], | |
| [1024, 768], | |
| [768, 1024], | |
| [1024, 512], | |
| [512, 1024], | |
| ] | |
| export const sizeKey = ([w, h]) => `${w}x${h}` | |
| export const parseSize = (k) => k.split('x').map(Number) | |
| // The preset closest to an image's aspect (then closest in area to the current one), within budget. | |
| export function fitToAspect(w0, h0, sizes, current) { | |
| const want = Math.log(w0 / h0), | |
| cur = current[0] * current[1] | |
| let best = null | |
| for (const s of sizes) { | |
| const err = Math.abs(Math.log(s[0] / s[1]) - want), | |
| area = Math.abs(s[0] * s[1] - cur) | |
| if (!best || err < best.err - 1e-9 || (Math.abs(err - best.err) < 1e-9 && area < best.area)) | |
| best = { s, err, area } | |
| } | |
| return best?.s ?? current | |
| } | |
| const gcd = (a, b) => (b ? gcd(b, a % b) : a) | |
| export const ratioLabel = ([w, h]) => { | |
| const g = gcd(w, h) | |
| return `${w / g}:${h / g}` | |
| } | |
| export const orientation = ([w, h]) => (w === h ? 'Square' : w < h ? 'Portrait' : 'Landscape') | |
| // Menu order: tallest first, widest last, smallest before largest within one shape. Listed that | |
| // way the presets read as a fan, so "taller / wider / bigger" is answered by position alone. | |
| export const byShape = (a, b) => a[0] * b[1] - b[0] * a[1] || a[0] * a[1] - b[0] * b[1] | |
| // Longest side among a list of presets — the scale the menu's little rectangles are drawn | |
| // against, so a glyph shows the real proportions *and* the real size next to its neighbours. | |
| export const longestSide = (sizes) => Math.max(...sizes.flat(), 1) | |