YAPF/extensions/figma/code.js
Nexoniarz 2ca726e3af YAPF v1: fast byte-aligned format, SIMD, tools and plugins
Format (version 1, replaces the earlier experimental versions):
- per-tile YCoCg-R or subtract-green colour transform, 8-bit modular
- 12 row filters per 8-row band (Left, Gradient, Up-right, Up-average,
  Up 1-8 rows), none with more than a one-add serial dependency
- residuals in groups of 8 at the group's width (w bits x 8 = w bytes),
  4-bit control codes with repeat-previous-width runs chosen by DP
- constant and stored tiles, independent 64x64 tiles, mips, GPU hints
- all sizes validated before decoding; corrupt input is rejected

Library:
- SIMD on by default: SSSE3 (runtime CPUID check; GCC, Clang, MSVC,
  MinGW) and NEON on ARM64; -DYAPF_NO_SIMD for plain C
- yapf_load_memory, yapf_load_mt, yapf_load_memory_mt
- 6-10x faster decoding than PNG (stb_image) on one core; -O2 and -O3
  builds perform the same
- fixes for macOS (sysconf) and the Windows import library exports

Tools and integrations:
- `yapf` CLI: convert PNG/JPG/TGA/BMP/PSD/GIF <-> YAPF, info, bench,
  thumbnail, mips
- JavaScript and Python bindings (byte-identical to the C encoder)
- GIMP 3 plugin: exports the flattened image, optional mipmaps
- Blender extension: import (also as plane), export, drag and drop
- VS Code preview, Figma plugin, Photoshop scripts, Linux MIME type and
  thumbnailer
- Makefile, updated build.sh / build.bat, tools/build_release.sh
- tests/test_yapf.c (784 checks) and bindings/js/test.js

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 14:17:59 +02:00

54 lines
2.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// YAPF for Figma — plugin main thread (has the document, no DOM).
// Copyright 2026 Nexoniarz — Apache License 2.0.
// Decoding/encoding happens in the UI (ui.html), which has a DOM.
figma.showUI(__html__, { width: 380, height: 330, themeColors: true });
figma.ui.postMessage({ type: 'mode', mode: figma.command || 'import' });
function sendSelection() {
const nodes = figma.currentPage.selection.filter((n) => 'exportAsync' in n);
figma.ui.postMessage({ type: 'selection', names: nodes.map((n) => n.name) });
}
figma.on('selectionchange', sendSelection);
sendSelection();
figma.ui.onmessage = async (msg) => {
if (msg.type === 'import') {
// msg.images: [{ name, width, height, png: Uint8Array }]
const created = [];
const center = figma.viewport.center;
let x = center.x;
for (const im of msg.images) {
try {
const image = figma.createImage(im.png);
const rect = figma.createRectangle();
rect.name = im.name;
rect.resize(im.width, im.height);
rect.fills = [{ type: 'IMAGE', imageHash: image.hash, scaleMode: 'FILL' }];
rect.x = Math.round(x - (created.length ? 0 : im.width / 2));
rect.y = Math.round(center.y - im.height / 2);
x = rect.x + im.width + 40;
figma.currentPage.appendChild(rect);
created.push(rect);
} catch (e) {
figma.notify(im.name + ': ' + (e.message || e) + ' (Figma accepts images up to 4096×4096)', { error: true });
}
}
if (created.length) {
figma.currentPage.selection = created;
figma.viewport.scrollAndZoomIntoView(created);
figma.notify('Imported ' + created.length + ' YAPF image' + (created.length > 1 ? 's' : ''));
}
}
if (msg.type === 'export') {
const nodes = figma.currentPage.selection.filter((n) => 'exportAsync' in n);
if (!nodes.length) { figma.notify('Select one or more layers to export', { error: true }); return; }
for (const node of nodes) {
const png = await node.exportAsync({ format: 'PNG', constraint: { type: 'SCALE', value: msg.scale || 1 } });
figma.ui.postMessage({ type: 'exported', name: node.name, png });
}
}
if (msg.type === 'close') figma.closePlugin();
};