mirror of
https://github.com/Nexoniarz/YAPF.git
synced 2026-11-02 20:44:27 +00:00
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>
54 lines
2.2 KiB
JavaScript
54 lines
2.2 KiB
JavaScript
// 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();
|
||
};
|