Reuse unchanged projection arrays and limit extra viewport retention
This commit is contained in:
@@ -7,6 +7,8 @@ type Retained<T>={incarnation:number;ownerCanvasId:Id;value:T};
|
||||
/** View-owned rendering cache, never a document store. Keep unchanged React Flow input identities. */
|
||||
export function createProjectionCache(){
|
||||
let scope:object|undefined,projectId:Id|undefined,canvasId:Id|undefined;
|
||||
let nodeArray:Projection['nodes']|undefined,edgeArray:Projection['edges']|undefined;
|
||||
const stable=<T>(previous:T[]|undefined,next:T[])=>previous?.length===next.length&&next.every((value,index)=>value===previous[index])?previous:next;
|
||||
let nodes=new Map<Id,Retained<Projection['nodes'][number]>>(),edges=new Map<Id,Retained<Projection['edges'][number]>>();
|
||||
function retain<T extends{id:Id}>(document:Document,values:T[],previous:Map<Id,Retained<T>>){
|
||||
const next=new Map<Id,Retained<T>>();
|
||||
@@ -19,15 +21,16 @@ export function createProjectionCache(){
|
||||
}
|
||||
return Object.freeze({
|
||||
reuse(owner:object,document:Document,viewCanvasId:Id,projection:Projection):Projection{
|
||||
if(scope!==owner||projectId!==document.projectId||canvasId!==viewCanvasId){nodes.clear();edges.clear();scope=owner;projectId=document.projectId;canvasId=viewCanvasId;}
|
||||
nodes=retain(document,projection.nodes,nodes);edges=retain(document,projection.edges,edges);
|
||||
return projection;
|
||||
if(scope!==owner||projectId!==document.projectId||canvasId!==viewCanvasId){nodes.clear();edges.clear();nodeArray=undefined;edgeArray=undefined;scope=owner;projectId=document.projectId;canvasId=viewCanvasId;}
|
||||
const nextNodes=retain(document,projection.nodes,nodes),nextEdges=retain(document,projection.edges,edges);
|
||||
nodes=nextNodes;edges=nextEdges;nodeArray=stable(nodeArray,projection.nodes);edgeArray=stable(edgeArray,projection.edges);
|
||||
return{...projection,nodes:nodeArray,edges:edgeArray};
|
||||
},
|
||||
getNode(id:Id){return nodes.get(id)?.value;},
|
||||
canRetainMeasurement(owner:object,document:Document,viewCanvasId:Id,value:Projection['nodes'][number]){
|
||||
const old=nodes.get(value.id),record=document.elements.get(value.id);
|
||||
return scope===owner&&projectId===document.projectId&&canvasId===viewCanvasId&&!!old&&!!record&&old.incarnation===record.incarnation&&old.ownerCanvasId===record.ownerCanvasId&&old.value.type===value.type&&old.value.width===value.width&&old.value.height===value.height&&equal(old.value.data,value.data);
|
||||
},
|
||||
clear(){nodes.clear();edges.clear();scope=undefined;projectId=undefined;canvasId=undefined;},
|
||||
clear(){nodes.clear();edges.clear();nodeArray=undefined;edgeArray=undefined;scope=undefined;projectId=undefined;canvasId=undefined;},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
import type {Rect} from '../canvas-core/geometry.ts';
|
||||
/** Positive-area native node visibility. Degenerate nodes are retained for measurement. */
|
||||
export function nativeRectVisible(node:Rect,viewport:Rect){if(node.width<=0||node.height<=0)return true;return Math.min(node.x+node.width,viewport.x+viewport.width)>Math.max(node.x,viewport.x)&&Math.min(node.y+node.height,viewport.y+viewport.height)>Math.max(node.y,viewport.y);}
|
||||
Reference in New Issue
Block a user