Files
Azornes-Comfyui-LayerForge/tests/test_drag_scene_cache_characterization.mjs

111 lines
3.7 KiB
JavaScript

import assert from 'node:assert/strict';
import { readFile } from 'node:fs/promises';
import test from 'node:test';
const canvasLayersSource = await readFile(
new URL('../js/canvas/canvas_layers.js', import.meta.url),
'utf8'
);
const canvasRendererSource = await readFile(
new URL('../js/canvas/canvas_renderer.js', import.meta.url),
'utf8'
);
const canvasInteractionsSource = await readFile(
new URL('../js/canvas/canvas_interactions.js', import.meta.url),
'utf8'
);
function extractMethod(methodName) {
const start = canvasLayersSource.indexOf(` ${methodName}(`);
assert.notEqual(start, -1, `compiled ${methodName} method should exist`);
const bodyStart = canvasLayersSource.indexOf('{', start);
assert.notEqual(bodyStart, -1, `${methodName} should have a body`);
let depth = 0;
let quote = null;
let escaped = false;
for (let index = bodyStart; index < canvasLayersSource.length; index += 1) {
const character = canvasLayersSource[index];
if (quote) {
if (escaped) {
escaped = false;
} else if (character === '\\') {
escaped = true;
} else if (character === quote) {
quote = null;
}
continue;
}
if (character === '"' || character === "'" || character === '`') {
quote = character;
continue;
}
if (character === '{') depth += 1;
if (character === '}') {
depth -= 1;
if (depth === 0) {
return canvasLayersSource.slice(start, index + 1);
}
}
}
throw new Error(`Could not extract ${methodName}`);
}
const methodFactory = new Function(
`return {\n${[
extractMethod('isSourceOverBlendMode'),
extractMethod('getDragCanvasBlendMode'),
extractMethod('createDragStaticSegments'),
].join(',\n')}\n};`,
);
const methods = methodFactory();
test('drag scene cache groups source-over layers and replays non-normal modes', () => {
const context = {
isSourceOverBlendMode: methods.isSourceOverBlendMode,
getDragCanvasBlendMode: methods.getDragCanvasBlendMode,
};
const layers = [
{ id: 'lower', blendMode: 'normal', opacity: 0.8 },
{ id: 'middle', blendMode: 'source-over', opacity: 0.6 },
{ id: 'blend', blendMode: 'multiply', opacity: 0.5 },
{ id: 'upper', blendMode: 'screen', opacity: 0.7 },
{ id: 'top', blendMode: 'normal', opacity: 1 },
];
const segments = methods.createDragStaticSegments.call(context, layers);
assert.equal(segments.length, 4);
assert.deepEqual(segments.map(segment => segment.layers.map(layer => layer.id)), [
['lower', 'middle'],
['blend'],
['upper'],
['top'],
]);
assert.deepEqual(segments.map(({ blendMode, opacity, applyLayerOpacity }) => ({
blendMode,
opacity,
applyLayerOpacity,
})), [
{ blendMode: 'source-over', opacity: 1, applyLayerOpacity: true },
{ blendMode: 'multiply', opacity: 0.5, applyLayerOpacity: false },
{ blendMode: 'screen', opacity: 0.7, applyLayerOpacity: false },
{ blendMode: 'source-over', opacity: 1, applyLayerOpacity: true },
]);
assert.match(canvasRendererSource, /canReuseDragFrame/);
assert.match(canvasRendererSource, /getDragDirtyRects/);
assert.match(canvasRendererSource, /dirtyRects\.forEach/);
assert.match(canvasRendererSource, /this\.canvas\.offscreenCanvas,\s*rect\.x/);
assert.match(canvasRendererSource, /ctx\.clip\(\)/);
assert.match(canvasLayersSource, /getOrCreateDragLayerPreview/);
assert.match(canvasLayersSource, /prepareDragLayerPreviews/);
assert.match(canvasLayersSource, /dragPreview: \{ viewport, width, height \}/);
assert.match(canvasLayersSource, /ctx\.drawImage\(preview, -layer\.width \/ 2/);
assert.match(canvasInteractionsSource, /prepareDragLayerPreviews\(this\.canvas\.canvasSelection\.selectedLayers\)/);
});