mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-03 04:38:33 +00:00
fix(cli): fold canvas pixel hashes into the frozen-sweep fingerprint
This commit is contained in:
@@ -895,6 +895,31 @@
|
||||
// actually moved anything and the whole audit run is unreliable. Deliberately
|
||||
// a single opaque string (not a structured array) since Node only ever needs
|
||||
// equality, not per-element diffing.
|
||||
// Pixel-only canvas motion (a 2D/WebGL canvas repainting without any element
|
||||
// moving) is invisible to a geometry+opacity fingerprint and false-positived
|
||||
// sweep_static (wild report: 4K WebGL comp needed a transparent moving DOM
|
||||
// sentinel to pass). Downsample each visible canvas to 8x8 and fold its
|
||||
// pixels into the fingerprint. Tainted/zero-sized/unreadable canvases hash
|
||||
// to a constant — no worse than today, never a new false NEGATIVE for
|
||||
// DOM-motion comps.
|
||||
function canvasPixelHash(canvas) {
|
||||
try {
|
||||
if (!canvas.width || !canvas.height) return "x";
|
||||
const off = document.createElement("canvas");
|
||||
off.width = 8;
|
||||
off.height = 8;
|
||||
const ctx = off.getContext("2d");
|
||||
if (!ctx) return "x";
|
||||
ctx.drawImage(canvas, 0, 0, 8, 8);
|
||||
const data = ctx.getImageData(0, 0, 8, 8).data;
|
||||
let hash = 0;
|
||||
for (let i = 0; i < data.length; i++) hash = (hash * 31 + data[i]) >>> 0;
|
||||
return String(hash);
|
||||
} catch {
|
||||
return "x";
|
||||
}
|
||||
}
|
||||
|
||||
window.__hyperframesLayoutGeometry = function collectLayoutGeometry() {
|
||||
const root =
|
||||
document.querySelector("[data-composition-id][data-width][data-height]") ||
|
||||
@@ -903,12 +928,15 @@
|
||||
const elements = Array.from(root.querySelectorAll("*")).filter((element) =>
|
||||
isVisibleElement(element),
|
||||
);
|
||||
return elements
|
||||
.map((element) => {
|
||||
const rect = toRect(element.getBoundingClientRect());
|
||||
const opacity = round(opacityChain(element));
|
||||
return `${rect.left},${rect.top},${rect.width},${rect.height},${opacity}`;
|
||||
})
|
||||
.join("|");
|
||||
const parts = elements.map((element) => {
|
||||
const rect = toRect(element.getBoundingClientRect());
|
||||
const opacity = round(opacityChain(element));
|
||||
return `${rect.left},${rect.top},${rect.width},${rect.height},${opacity}`;
|
||||
});
|
||||
for (const canvas of root.querySelectorAll("canvas")) {
|
||||
if (!isVisibleElement(canvas)) continue;
|
||||
parts.push(`c:${canvasPixelHash(canvas)}`);
|
||||
}
|
||||
return parts.join("|");
|
||||
};
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user