diff options
Diffstat (limited to 'public/bluebey-studio/src/exporter.js')
| -rw-r--r-- | public/bluebey-studio/src/exporter.js | 92 |
1 files changed, 0 insertions, 92 deletions
diff --git a/public/bluebey-studio/src/exporter.js b/public/bluebey-studio/src/exporter.js index ea9356e..cc9c1ca 100644 --- a/public/bluebey-studio/src/exporter.js +++ b/public/bluebey-studio/src/exporter.js @@ -1,6 +1,5 @@ import { traceAlphaContours, contoursToPathData } from './trace.js'; import { roughenContours } from './handDrawn.js'; -import { EYE_LAYOUT, MOUTH_LAYOUT } from './faceArt.js'; /** * Export helpers. @@ -175,97 +174,6 @@ ${rect}<path fill="${lineColor}"${widthAttr} fill-rule="evenodd" d="${d}"/> }; } -/** Alignment guides: blue on the white paper, light enough to paint over. */ -const FACE_MAP_GUIDE = 'rgba(90, 140, 220, 0.55)'; -/** Half-length of the centre ticks, in artwork-window pixels. */ -const FACE_MAP_TICK = 16; - -/** - * Build the「下地」image an author paints a custom face texture on. - * - * The studio loads a hand-drawn image by drawing it at the artwork window's own - * offset and size (see `Face.loadImage` / `placeInWindow`), so an image the size - * of the *plate canvas*, with its artwork aligned to `offsetX/offsetY`, imports - * 1:1. That is exactly what this hands out: the live drawing as a reference, an - * opaque white window to paint on, and faint guides for the eye centres, the lid - * line or the mouth chord. - * - * The white and the guides go on a **copy**: the plate canvas *is* the live - * texture, and painting it would show up in the view. - * - * @param {import('./face.js').Face} face - * @param {'eyes'|'mouth'} kind - * @returns {HTMLCanvasElement} - */ -export function buildFaceMap(face, kind) { - const eyes = kind === 'eyes'; - const layout = eyes ? face.eyeLayout : face.mouthLayout; - const plate = eyes ? face.eyeCanvas : face.mouthCanvas; - - const canvas = document.createElement('canvas'); - canvas.width = layout.width; - canvas.height = layout.height; - const ctx = canvas.getContext('2d'); - ctx.drawImage(plate, 0, 0); - - const { offsetX, offsetY, window: win } = layout; - // `destination-over` so the white paper lands *under* the copy: filling it - // normally would erase the very drawing the author lines the new art up against. - ctx.globalCompositeOperation = 'destination-over'; - ctx.fillStyle = '#ffffff'; - ctx.fillRect(offsetX, offsetY, win.width, win.height); - ctx.globalCompositeOperation = 'source-over'; - - // The plate canvas keeps the artwork at its original pixel size (only the canvas - // grows around it), so a fixed-width stroke reads the same on both parts. - ctx.strokeStyle = FACE_MAP_GUIDE; - ctx.fillStyle = FACE_MAP_GUIDE; - ctx.lineWidth = 2; - - // Where the drawing has to fit, and where its middle is. The cross uses short - // ticks, not full-width lines, so it cannot be mistaken for artwork. - ctx.strokeRect(offsetX, offsetY, win.width, win.height); - const cx = offsetX + win.width / 2; - const cy = offsetY + win.height / 2; - guideLine(ctx, cx - FACE_MAP_TICK, cy, cx + FACE_MAP_TICK, cy); - guideLine(ctx, cx, cy - FACE_MAP_TICK, cx, cy + FACE_MAP_TICK); - - if (eyes) { - // Both eyeballs (`radius`) and the lid line through their centres, so a - // hand-drawn brow or eye can be placed against the parametric ones. - const [a, b] = EYE_LAYOUT.eyes; - const y = offsetY + a.cy; - guideLine(ctx, offsetX + a.cx, y, offsetX + b.cx, y); - for (const eye of EYE_LAYOUT.eyes) { - const ex = offsetX + eye.cx; - const ey = offsetY + eye.cy; - ctx.beginPath(); - ctx.arc(ex, ey, EYE_LAYOUT.radius, 0, Math.PI * 2); - ctx.stroke(); - // A small dot marks the exact centre, where the eyeball pivots. - ctx.beginPath(); - ctx.arc(ex, ey, ctx.lineWidth * 1.5, 0, Math.PI * 2); - ctx.fill(); - } - } else { - // The lip line the mouth is drawn around: end to end, plus a tick at the centre. - const y = offsetY + MOUTH_LAYOUT.chordY; - const { centreX, halfChord } = MOUTH_LAYOUT; - guideLine(ctx, offsetX + centreX - halfChord, y, offsetX + centreX + halfChord, y); - guideLine(ctx, offsetX + centreX, y - FACE_MAP_TICK, offsetX + centreX, y + FACE_MAP_TICK); - } - - return canvas; -} - -/** One guide segment, kept out of the map builders so the placements stay readable. */ -function guideLine(ctx, x0, y0, x1, y1) { - ctx.beginPath(); - ctx.moveTo(x0, y0); - ctx.lineTo(x1, y1); - ctx.stroke(); -} - export function downloadBlob(blob, filename) { const url = URL.createObjectURL(blob); const link = document.createElement('a'); |
