Photo Puzzle - fotojockovic.com/puzzle ====================================== Turns a photo into a puzzle (30 types), lets you play it in the browser, send it to a friend, and download exact cut files (SVG, DXF, PDF) and a print file (PDF with bleed, crop marks and CutContour lines). Everything runs in the browser; no photo leaves the device. Our own work, written for this tool (source: src-rs/, MIT licence), with no third-party code or crates: - pz.wasm: the geometry engine, Rust compiled to WebAssembly and run in worker.js: * jigsaw knob ("tab") curves in 8 styles from Hermite nodes -> cubic Beziers, with size / neck / variety / waviness controls; knobs that would collide with a neighbour, the outline or a whimsy are detected and replaced, and self-crossing curves are rejected * 30 puzzle generators (see PUZZLE-TYPES.txt): square, brick, diamond, hexagon, triangle, rhombille and Penrose (Robinson-triangle deflation) lattices, Voronoi cells with Lloyd relaxation, polar (round) grid, Archimedean spiral, shaped outlines, letters, whimsies, games (sliding, rotating, swap, strips, rings, tangram, pentomino with a randomised exact-cover search) * planar arrangement: all curves flattened for topology only, crossings found with a uniform grid, curves split at exact Bezier parameters and welded to shared vertices, faces traced on a half-edge structure, bridges for holes, merging of slivers; every cut edge keeps its exact lines/cubics for export * self-check of every puzzle (and a re-try with the next seed if it fails): pieces' areas add up to the outline area, no crossings, no loose ends, exact size * signed distance field atlas of all pieces for the WebGL renderer and for picking * cut files: SVG (inner cuts red, outline blue, frame green, numbers as an engrave layer), DXF R12 (layers CUT_INNER, CUT_OUTLINE, CUT_FRAME, ENGRAVE), PDF; shared edges cut once, chained into long paths, inner cuts before the outline; kerf compensation, separate-pieces layout, frame and base board * print PDF: the photo with bleed (edge-extended where needed), crop marks, cut lines as the CutContour Separation spot colour (or thin black), page sizes, a mirrored back side with piece numbers or a second photo for duplex printing * subject outline for silhouette puzzles: OKLab k-means of the border colours, Otsu threshold, morphology, Moore boundary tracing, smoothing (no machine learning) * letter outlines: a small TrueType reader (cmap 4, glyf, composites) used at build time to pack the glyphs we need into font/name.bin - gl.js: WebGL2 renderer (instanced pieces, bevel lighting and soft shadows from the distance field). - app.js, worker.js, i18n.js, lang/*.js, index.html: the page, UI and texts. Published methods the engine builds on (ideas only; no code was copied): - R. Penrose's P3 tiling via Robinson triangle subdivision (as popularised by J. Preshing's description). - S. Lloyd, "Least squares quantization in PCM" (Lloyd relaxation of Voronoi cells). - B. Ottosson, "A perceptual color space for image processing" (OKLab), 2020 - public domain formulas. - N. Otsu, "A threshold selection method from gray-level histograms", 1979. - S. Wang's bound for the subdivision of Bezier curves; de Casteljau splitting; Hermite-to-Bezier conversion. - The TrueType format as documented by Apple and Microsoft (OpenType specification). Sample pictures (img/*.jpg, resized). The Metropolitan Museum of Art, Open Access, CC0 1.0 (isPublicDomain: true in the Met Collection API, checked 2026-10-16): img/wave.jpg - Katsushika Hokusai, Under the Wave off Kanagawa (The Great Wave), ca. 1830-32, object 45434 img/harv.jpg - Pieter Bruegel the Elder, The Harvesters, 1565, object 435809 img/wheat.jpg - Vincent van Gogh, Wheat Field with Cypresses, 1889, object 436535 img/jar.jpg - Jacob Scholl, Covered jar, ca. 1830-40, object 2412 Font for name puzzles (font/name.bin: outlines of Latin, Greek and Cyrillic letters and digits extracted from the font, no font file is shipped as such): Fira Sans Black, Copyright (c) 2012-2015 The Mozilla Foundation and Telefonica S.A., SIL Open Font License 1.1 (full text: font/OFL.txt). The extracted outlines are a Modified Version under the OFL and keep its licence; they are not sold on their own. UI fonts, loaded from Google Fonts, SIL Open Font License 1.1: Inter Tight (Rasmus Andersson et al.), Instrument Serif (Instrument). Shared helpers /static/tools/common/i18n.js, rail.js and sheets.js: our own. Translations of the interface: our own. Used only to build and test, never shipped to the browser: Rust and cargo (MIT/Apache-2.0); binaryen (Apache-2.0) for wasm-opt; puppeteer-core (Apache-2.0) and Google Chrome for screenshots and tests; poppler pdftoppm (GPL, run locally to look at the PDFs only). No GPL code is shipped. No machine-learning model is used. Self-hosted web fonts (2026-10-19): Inter Tight, Instrument Serif. SIL Open Font License 1.1. The woff2 files are the ones Google Fonts serves (latin, latin-ext, cyrillic, greek subsets where the family has them), stored on our own server under /static/tools/common/fonts// with each family's licence text (OFL.txt) next to them; stylesheet /static/tools/common/fonts/ui.css. No font request goes to Google.