Skip to content

Commit

Permalink
refactor(scan/worker.ts): Improve outline handling and typing
Browse files Browse the repository at this point in the history
  • Loading branch information
aidenybai committed Dec 27, 2024
1 parent 5a630db commit a7ba740
Showing 1 changed file with 57 additions and 37 deletions.
94 changes: 57 additions & 37 deletions src/scan/worker.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,22 @@
import type { CompressedPendingOutline } from "./types.js";
import type { CompressedPendingOutline, ActiveOutline } from "./types.js";

// Use separate functions for keys if we're dealing with both Compressed and Active outlines:
function getCompressedOutlineKey(outline: CompressedPendingOutline): string {
const [name, , x, y, width, height] = outline;
return `${name},${x},${y},${width},${height}`;
}

function getActiveOutlineKey(outline: ActiveOutline): string {
const { name, x, y, width, height } = outline;
return `${name},${x},${y},${width},${height}`;
}

let canvas: OffscreenCanvas | null = null;
let ctx: OffscreenCanvasRenderingContext2D | null = null;
let dpr = 1;

let pendingOutlines: CompressedPendingOutline[] = [];
let activeOutlines: Map<string, CompressedPendingOutline> = new Map();
const activeOutlines: Map<string, ActiveOutline> = new Map();

const color = { r: 115, g: 97, b: 230 };

Expand All @@ -14,11 +25,6 @@ let animationFrameId: number | null = null;
const MONO_FONT =
"Menlo,Consolas,Monaco,Liberation Mono,Lucida Console,monospace";

const getOutlineKey = (outline: CompressedPendingOutline) => {
const [name, _count, x, y, width, height] = outline;
return `${name},${x},${y},${width},${height}`;
};

const getOverlapArea = (rect1: DOMRect, rect2: DOMRect): number => {
if (rect1.right <= rect2.left || rect2.right <= rect1.left) {
return 0;
Expand All @@ -36,17 +42,30 @@ const getOverlapArea = (rect1: DOMRect, rect2: DOMRect): number => {
return xOverlap * yOverlap;
};

const getLabelText = (outlines: CompressedPendingOutline[]): string => {
const getLabelText = (outlines: ActiveOutline[]): string => {
const parts: string[] = [];
for (const outline of outlines) {
const [name, count] = outline;
const { name, count } = outline;
parts.push(count > 1 ? `${name} ×${count}` : name);
}
return parts.join(", ");
};

const TOTAL_FRAMES = 45;

// Convert compressed outline to an ActiveOutline
function toActiveOutline(c: CompressedPendingOutline): ActiveOutline {
return {
name: c[0],
count: c[1],
x: c[2],
y: c[3],
width: c[4],
height: c[5],
frame: 0,
};
}

function draw() {
if (!ctx || !canvas) return;

Expand All @@ -60,10 +79,10 @@ function draw() {
// const alpha = invariantActiveOutline.alpha;
// const fillAlpha = alpha * 0.1;

const labelMap = new Map<string, CompressedPendingOutline[]>();
const labelMap = new Map<string, ActiveOutline[]>();

for (const outline of activeOutlines.values()) {
const [_name, _count, x, y, width, height, frame] = outline;
const { x, y, width, height, frame } = outline;
const alpha = 1 - frame / TOTAL_FRAMES;
const fillAlpha = alpha * 0.1;

Expand All @@ -76,14 +95,14 @@ function draw() {
ctx.rect(x, y, width, height);
ctx.stroke();
ctx.fill();
outline[6]++; // update frame
outline.frame++;

const key = `${x},${y}`;
const label = labelMap.get(key);
if (label) {
label.push(outline);
const labelKey = `${x},${y}`;
const group = labelMap.get(labelKey);
if (group) {
group.push(outline);
} else {
labelMap.set(key, [outline]);
labelMap.set(labelKey, [outline]);
}
// slow?
}
Expand All @@ -95,18 +114,19 @@ function draw() {

// dedupe overlapping outlines
for (const outlines of labelMap.values()) {
const [_name, _count, x, y, _width, _height, frame] = outlines[0];
const first = outlines[0];
const { x, y, frame } = first;
const alpha = 1 - frame / TOTAL_FRAMES;
const text = getLabelText(outlines);

const textMetrics = ctx.measureText(text);
const textWidth = textMetrics.width;
const textHeight = 11;

}

for (const outlines of labelMap.values()) {
const [_name, _count, x, y, _width, _height, frame] = outlines[0];
const first = outlines[0];
const { x, y, frame } = first;
const alpha = 1 - frame / TOTAL_FRAMES;
const text = getLabelText(outlines);

Expand All @@ -124,8 +144,8 @@ function draw() {
ctx.fillText(text, labelX + 2, labelY + textHeight);

if (frame > TOTAL_FRAMES) {
for (const outline of outlines) {
activeOutlines.delete(getOutlineKey(outline));
for (const o of outlines) {
activeOutlines.delete(getActiveOutlineKey(o));
}
}
}
Expand Down Expand Up @@ -172,7 +192,7 @@ self.onmessage = (event) => {
if (type === "draw") {
const { outlinesBuffer, names } = event.data;
const floatView = new Float32Array(outlinesBuffer);
const newOutlines = [];
const newOutlines: CompressedPendingOutline[] = [];

for (let i = 0; i < floatView.length; i += 6) {
newOutlines.push([
Expand All @@ -182,33 +202,33 @@ self.onmessage = (event) => {
floatView[i + 2],
floatView[i + 3],
floatView[i + 4],
floatView[i + 5],
]);
}

pendingOutlines = newOutlines as CompressedPendingOutline[];
pendingOutlines = newOutlines;
if (!animationFrameId) {
animationFrameId = requestAnimationFrame(() => {
for (const outline of pendingOutlines) {
if (activeOutlines.has(getOutlineKey(outline))) {
// biome-ignore lint/style/noNonNullAssertion: <explanation>
activeOutlines.get(getOutlineKey(outline))![1]++; // count
for (const c of pendingOutlines) {
const key = getCompressedOutlineKey(c);
const existingOutline = activeOutlines.get(key);
if (existingOutline) {
existingOutline.count++;
} else {
activeOutlines.set(getOutlineKey(outline), outline);
activeOutlines.set(key, toActiveOutline(c));
}
}
pendingOutlines = [];
draw();
});
} else {
for (const outline of pendingOutlines) {
if (activeOutlines.has(getOutlineKey(outline))) {
// biome-ignore lint/style/noNonNullAssertion: <explanation>
activeOutlines.get(getOutlineKey(outline))![1]++; // count
// biome-ignore lint/style/noNonNullAssertion: <explanation>
activeOutlines.get(getOutlineKey(outline))![6] = 0; // reset frame
for (const c of pendingOutlines) {
const key = getCompressedOutlineKey(c);
const existingOutline = activeOutlines.get(key);
if (existingOutline) {
existingOutline.count++;
existingOutline.frame = 0;
} else {
activeOutlines.set(getOutlineKey(outline), outline);
activeOutlines.set(key, toActiveOutline(c));
}
}
}
Expand Down

0 comments on commit a7ba740

Please sign in to comment.