Moved ShapeCache in element

This commit is contained in:
Marcel Mraz 2025-03-18 11:54:51 +01:00
parent 875450a0a1
commit 931d03d514
23 changed files with 84 additions and 54 deletions

View file

@ -2,6 +2,9 @@ interface ImportMetaEnv {
MODE: string; MODE: string;
DEV: string; DEV: string;
PROD: string; PROD: string;
// To enable bounding box for text containers
VITE_APP_DEBUG_ENABLE_TEXT_CONTAINER_BOUNDING_BOX: string;
} }
interface ImportMeta { interface ImportMeta {

View file

@ -1,9 +1,10 @@
import { pointFrom, pointDistance, type LocalPoint } from "@excalidraw/math";
import { simplify } from "points-on-curve"; import { simplify } from "points-on-curve";
import { pointFrom, pointDistance, type LocalPoint } from "@excalidraw/math";
import { ROUGHNESS, isTransparent, assertNever } from "@excalidraw/common"; import { ROUGHNESS, isTransparent, assertNever } from "@excalidraw/common";
import { getDiamondPoints, getArrowheadPoints } from "@excalidraw/element"; import { getDiamondPoints, getArrowheadPoints } from "@excalidraw/element";
import { headingForPointIsHorizontal } from "@excalidraw/element/heading"; import { headingForPointIsHorizontal } from "@excalidraw/element/heading";
import { getCornerRadius, isPathALoop } from "@excalidraw/element/shapes";
import { import {
isElbowArrow, isElbowArrow,
isEmbeddableElement, isEmbeddableElement,
@ -12,8 +13,6 @@ import {
isLinearElement, isLinearElement,
} from "@excalidraw/element/typeChecks"; } from "@excalidraw/element/typeChecks";
import { getCornerRadius, isPathALoop } from "@excalidraw/element/shapes";
import type { import type {
ExcalidrawElement, ExcalidrawElement,
NonDeletedExcalidrawElement, NonDeletedExcalidrawElement,
@ -22,12 +21,12 @@ import type {
Arrowhead, Arrowhead,
} from "@excalidraw/element/types"; } from "@excalidraw/element/types";
import { generateFreeDrawShape } from "../renderer/renderElement"; import type { EmbedsValidationStatus } from "@excalidraw/excalidraw/types";
import type { ElementShapes } from "@excalidraw/excalidraw/scene/types";
import { canChangeRoundness } from "./comparisons"; import { canChangeRoundness } from "./comparisons";
import { generateFreeDrawShape } from "./renderElement";
import type { EmbedsValidationStatus } from "../types";
import type { ElementShapes } from "./types";
import type { Drawable, Options } from "roughjs/bin/core"; import type { Drawable, Options } from "roughjs/bin/core";
import type { RoughGenerator } from "roughjs/bin/generator"; import type { RoughGenerator } from "roughjs/bin/generator";
import type { Point as RoughPoint } from "roughjs/bin/geometry"; import type { Point as RoughPoint } from "roughjs/bin/geometry";

View file

@ -7,12 +7,19 @@ import type {
ExcalidrawSelectionElement, ExcalidrawSelectionElement,
} from "@excalidraw/element/types"; } from "@excalidraw/element/types";
import { elementWithCanvasCache } from "../renderer/renderElement"; import type {
AppState,
EmbedsValidationStatus,
} from "@excalidraw/excalidraw/types";
import type {
ElementShape,
ElementShapes,
} from "@excalidraw/excalidraw/scene/types";
import { _generateElementShape } from "./Shape"; import { _generateElementShape } from "./Shape";
import type { AppState, EmbedsValidationStatus } from "../types"; import { elementWithCanvasCache } from "./renderElement";
import type { ElementShape, ElementShapes } from "./types";
import type { Drawable } from "roughjs/bin/core"; import type { Drawable } from "roughjs/bin/core";
export class ShapeCache { export class ShapeCache {

View file

@ -12,8 +12,7 @@ import {
} from "@excalidraw/math"; } from "@excalidraw/math";
import { getCurvePathOps } from "@excalidraw/utils/geometry/shape"; import { getCurvePathOps } from "@excalidraw/utils/geometry/shape";
import { generateRoughOptions } from "@excalidraw/excalidraw/scene/Shape"; import { generateRoughOptions } from "@excalidraw/element/Shape";
import { ShapeCache } from "@excalidraw/excalidraw/scene/ShapeCache";
import type { import type {
Degrees, Degrees,

View file

@ -1,4 +1,4 @@
import type { ElementOrToolType } from "../types"; import type { ElementOrToolType } from "@excalidraw/excalidraw/types";
export const hasBackground = (type: ElementOrToolType) => export const hasBackground = (type: ElementOrToolType) =>
type === "rectangle" || type === "rectangle" ||

View file

@ -19,7 +19,6 @@ import {
invariant, invariant,
tupleToCoors, tupleToCoors,
} from "@excalidraw/common"; } from "@excalidraw/common";
import { ShapeCache } from "@excalidraw/excalidraw/scene/ShapeCache";
import { import {
getBezierCurveLength, getBezierCurveLength,
@ -29,6 +28,8 @@ import {
mapIntervalToBezierT, mapIntervalToBezierT,
} from "@excalidraw/element"; } from "@excalidraw/element";
import type { Store } from "@excalidraw/excalidraw/store";
import type { Radians } from "@excalidraw/math"; import type { Radians } from "@excalidraw/math";
import type Scene from "@excalidraw/excalidraw/scene/Scene"; import type Scene from "@excalidraw/excalidraw/scene/Scene";
@ -59,6 +60,8 @@ import {
isFixedPointBinding, isFixedPointBinding,
} from "./typeChecks"; } from "./typeChecks";
import { ShapeCache } from "./ShapeCache";
import { getElementAbsoluteCoords, getLockedLinearCursorAlignSize } from "./"; import { getElementAbsoluteCoords, getLockedLinearCursorAlignSize } from "./";
import type { Bounds } from "./bounds"; import type { Bounds } from "./bounds";

View file

@ -10,7 +10,8 @@ import type { Radians } from "@excalidraw/math";
import type { Mutable } from "@excalidraw/excalidraw/utility-types"; import type { Mutable } from "@excalidraw/excalidraw/utility-types";
import Scene from "../scene/Scene"; import Scene from "../scene/Scene";
import { ShapeCache } from "../scene/ShapeCache";
import { ShapeCache } from "./ShapeCache";
import { updateElbowArrowPoints } from "./elbowArrow"; import { updateElbowArrowPoints } from "./elbowArrow";
import { isElbowArrow } from "./typeChecks"; import { isElbowArrow } from "./typeChecks";

View file

@ -1,6 +1,7 @@
import { isRightAngleRads } from "@excalidraw/math";
import { getStroke } from "perfect-freehand";
import rough from "roughjs/bin/rough"; import rough from "roughjs/bin/rough";
import { getStroke } from "perfect-freehand";
import { isRightAngleRads } from "@excalidraw/math";
import { import {
BOUND_TEXT_PADDING, BOUND_TEXT_PADDING,
@ -37,6 +38,9 @@ import {
import { getContainingFrame } from "@excalidraw/element/frame"; import { getContainingFrame } from "@excalidraw/element/frame";
import { getCornerRadius } from "@excalidraw/element/shapes"; import { getCornerRadius } from "@excalidraw/element/shapes";
// TODO: consider separating
import { getVerticalOffset } from "@excalidraw/excalidraw/fonts/FontMetadata";
import type { import type {
ExcalidrawElement, ExcalidrawElement,
ExcalidrawTextElement, ExcalidrawTextElement,
@ -49,15 +53,6 @@ import type {
ElementsMap, ElementsMap,
} from "@excalidraw/element/types"; } from "@excalidraw/element/types";
import { getDefaultAppState } from "../appState";
import { getVerticalOffset } from "../fonts/FontMetadata";
import { ShapeCache } from "../scene/ShapeCache";
import type {
StaticCanvasRenderConfig,
RenderableElementsMap,
InteractiveCanvasRenderConfig,
} from "../scene/types";
import type { import type {
AppState, AppState,
StaticCanvasAppState, StaticCanvasAppState,
@ -65,7 +60,17 @@ import type {
InteractiveCanvasAppState, InteractiveCanvasAppState,
ElementsPendingErasure, ElementsPendingErasure,
PendingExcalidrawElements, PendingExcalidrawElements,
} from "../types"; NormalizedZoomValue,
} from "@excalidraw/excalidraw/types";
import type {
StaticCanvasRenderConfig,
RenderableElementsMap,
InteractiveCanvasRenderConfig,
} from "@excalidraw/excalidraw/scene/types";
import { ShapeCache } from "./ShapeCache";
import type { StrokeOptions } from "perfect-freehand"; import type { StrokeOptions } from "perfect-freehand";
import type { RoughCanvas } from "roughjs/bin/canvas"; import type { RoughCanvas } from "roughjs/bin/canvas";
@ -76,8 +81,6 @@ import type { RoughCanvas } from "roughjs/bin/canvas";
export const IMAGE_INVERT_FILTER = export const IMAGE_INVERT_FILTER =
"invert(100%) hue-rotate(180deg) saturate(1.25)"; "invert(100%) hue-rotate(180deg) saturate(1.25)";
const defaultAppState = getDefaultAppState();
const isPendingImageElement = ( const isPendingImageElement = (
element: ExcalidrawElement, element: ExcalidrawElement,
renderConfig: StaticCanvasRenderConfig, renderConfig: StaticCanvasRenderConfig,
@ -537,7 +540,11 @@ const generateElementWithCanvas = (
renderConfig: StaticCanvasRenderConfig, renderConfig: StaticCanvasRenderConfig,
appState: StaticCanvasAppState, appState: StaticCanvasAppState,
) => { ) => {
const zoom: Zoom = renderConfig ? appState.zoom : defaultAppState.zoom; const zoom: Zoom = renderConfig
? appState.zoom
: {
value: 1 as NormalizedZoomValue,
};
const prevElementWithCanvas = elementWithCanvasCache.get(element); const prevElementWithCanvas = elementWithCanvasCache.get(element);
const shouldRegenerateBecauseZoom = const shouldRegenerateBecauseZoom =
prevElementWithCanvas && prevElementWithCanvas &&

View file

@ -30,7 +30,7 @@ import type { NormalizedZoomValue, Zoom } from "@excalidraw/excalidraw/types";
import { shouldTestInside } from "./collision"; import { shouldTestInside } from "./collision";
import { LinearElementEditor } from "./linearElementEditor"; import { LinearElementEditor } from "./linearElementEditor";
import { getBoundTextElement } from "./textElement"; import { getBoundTextElement } from "./textElement";
import { ShapeCache } from "./scene/ShapeCache"; import { ShapeCache } from "./ShapeCache";
import { getElementAbsoluteCoords } from "./"; import { getElementAbsoluteCoords } from "./";

View file

@ -52,6 +52,8 @@ import {
isUsingAdaptiveRadius, isUsingAdaptiveRadius,
} from "@excalidraw/element/typeChecks"; } from "@excalidraw/element/typeChecks";
import { hasStrokeColor } from "@excalidraw/element/comparisons";
import type { LocalPoint } from "@excalidraw/math"; import type { LocalPoint } from "@excalidraw/math";
import type { import type {
@ -128,7 +130,6 @@ import {
getTargetElements, getTargetElements,
isSomeElementSelected, isSomeElementSelected,
} from "../scene"; } from "../scene";
import { hasStrokeColor } from "../scene/comparisons";
import { CaptureUpdateAction } from "../store"; import { CaptureUpdateAction } from "../store";
import { register } from "./register"; import { register } from "./register";

View file

@ -21,6 +21,8 @@ import {
isTextElement, isTextElement,
} from "@excalidraw/element/typeChecks"; } from "@excalidraw/element/typeChecks";
import { hasStrokeColor, toolIsArrow } from "@excalidraw/element/comparisons";
import type { import type {
ExcalidrawElement, ExcalidrawElement,
ExcalidrawElementType, ExcalidrawElementType,
@ -43,7 +45,6 @@ import {
hasStrokeStyle, hasStrokeStyle,
hasStrokeWidth, hasStrokeWidth,
} from "../scene"; } from "../scene";
import { hasStrokeColor, toolIsArrow } from "../scene/comparisons";
import { SHAPES } from "./shapes"; import { SHAPES } from "./shapes";

View file

@ -270,6 +270,10 @@ import {
getMinTextElementWidth, getMinTextElementWidth,
} from "@excalidraw/element/textMeasurements"; } from "@excalidraw/element/textMeasurements";
import { ShapeCache } from "@excalidraw/element/ShapeCache";
import { getRenderOpacity } from "@excalidraw/element/renderElement";
import type { LocalPoint, Radians } from "@excalidraw/math"; import type { LocalPoint, Radians } from "@excalidraw/math";
import type { import type {
@ -428,7 +432,6 @@ import {
} from "../snapping"; } from "../snapping";
import { convertToExcalidrawElements } from "../data/transform"; import { convertToExcalidrawElements } from "../data/transform";
import { Renderer } from "../scene/Renderer"; import { Renderer } from "../scene/Renderer";
import { ShapeCache } from "../scene/ShapeCache";
import { import {
setEraserCursor, setEraserCursor,
setCursor, setCursor,
@ -441,7 +444,6 @@ import { Store, CaptureUpdateAction } from "../store";
import { AnimatedTrail } from "../animated-trail"; import { AnimatedTrail } from "../animated-trail";
import { LaserTrails } from "../laser-trails"; import { LaserTrails } from "../laser-trails";
import { withBatchedUpdates, withBatchedUpdatesThrottled } from "../reactUtils"; import { withBatchedUpdates, withBatchedUpdatesThrottled } from "../reactUtils";
import { getRenderOpacity } from "../renderer/renderElement";
import { textWysiwyg } from "../wysiwyg/textWysiwyg"; import { textWysiwyg } from "../wysiwyg/textWysiwyg";
import { isOverScrollBars } from "../scene/scrollbars"; import { isOverScrollBars } from "../scene/scrollbars";
import { syncInvalidIndices, syncMovedIndices } from "../fractionalIndex"; import { syncInvalidIndices, syncMovedIndices } from "../fractionalIndex";

View file

@ -13,9 +13,10 @@ import { mutateElement } from "@excalidraw/element/mutateElement";
import { showSelectedShapeActions } from "@excalidraw/element"; import { showSelectedShapeActions } from "@excalidraw/element";
import { ShapeCache } from "@excalidraw/element/ShapeCache";
import type { NonDeletedExcalidrawElement } from "@excalidraw/element/types"; import type { NonDeletedExcalidrawElement } from "@excalidraw/element/types";
import { ShapeCache } from "../scene/ShapeCache";
import Scene from "../scene/Scene"; import Scene from "../scene/Scene";
import { actionToggleStats } from "../actions"; import { actionToggleStats } from "../actions";
import { trackEvent } from "../analytics"; import { trackEvent } from "../analytics";

View file

@ -4,6 +4,8 @@ import { MIME_TYPES } from "@excalidraw/common";
import { getElementAbsoluteCoords } from "@excalidraw/element/bounds"; import { getElementAbsoluteCoords } from "@excalidraw/element/bounds";
import { hitElementBoundingBox } from "@excalidraw/element/collision"; import { hitElementBoundingBox } from "@excalidraw/element/collision";
import { DEFAULT_LINK_SIZE } from "@excalidraw/element/renderElement";
import type { GlobalPoint, Radians } from "@excalidraw/math"; import type { GlobalPoint, Radians } from "@excalidraw/math";
import type { Bounds } from "@excalidraw/element/bounds"; import type { Bounds } from "@excalidraw/element/bounds";
@ -12,8 +14,6 @@ import type {
NonDeletedExcalidrawElement, NonDeletedExcalidrawElement,
} from "@excalidraw/element/types"; } from "@excalidraw/element/types";
import { DEFAULT_LINK_SIZE } from "../../renderer/renderElement";
import type { AppState, UIAppState } from "../../types"; import type { AppState, UIAppState } from "../../types";
export const EXTERNAL_LINK_IMG = document.createElement("img"); export const EXTERNAL_LINK_IMG = document.createElement("img");

View file

@ -12,13 +12,13 @@ import { containsCJK } from "@excalidraw/element/textWrapping";
import { getFontString, PromisePool, promiseTry } from "@excalidraw/common"; import { getFontString, PromisePool, promiseTry } from "@excalidraw/common";
import { ShapeCache } from "@excalidraw/element/ShapeCache";
import type { import type {
ExcalidrawElement, ExcalidrawElement,
ExcalidrawTextElement, ExcalidrawTextElement,
} from "@excalidraw/element/types"; } from "@excalidraw/element/types";
import { ShapeCache } from "../scene/ShapeCache";
import { CascadiaFontFaces } from "./Cascadia"; import { CascadiaFontFaces } from "./Cascadia";
import { ComicShannsFontFaces } from "./ComicShanns"; import { ComicShannsFontFaces } from "./ComicShanns";
import { EmojiFontFaces } from "./Emoji"; import { EmojiFontFaces } from "./Emoji";

View file

@ -242,7 +242,7 @@ export {
loadSceneOrLibraryFromBlob, loadSceneOrLibraryFromBlob,
loadLibraryFromBlob, loadLibraryFromBlob,
} from "./data/blob"; } from "./data/blob";
export { getFreeDrawSvgPath } from "./renderer/renderElement"; export { getFreeDrawSvgPath } from "@excalidraw/element/renderElement";
export { mergeLibraryItems, getLibraryItemsHash } from "./data/library"; export { mergeLibraryItems, getLibraryItemsHash } from "./data/library";
export { isLinearElement } from "@excalidraw/element/typeChecks"; export { isLinearElement } from "@excalidraw/element/typeChecks";

View file

@ -40,6 +40,8 @@ import {
import { getCornerRadius } from "@excalidraw/element/shapes"; import { getCornerRadius } from "@excalidraw/element/shapes";
import { renderSelectionElement } from "@excalidraw/element/renderElement";
import type { import type {
SuggestedBinding, SuggestedBinding,
SuggestedPointBinding, SuggestedPointBinding,
@ -68,7 +70,6 @@ import {
getElementsInGroup, getElementsInGroup,
selectGroupsFromGivenElements, selectGroupsFromGivenElements,
} from "../groups"; } from "../groups";
import { renderSelectionElement } from "../renderer/renderElement";
import { renderSnaps } from "../renderer/renderSnaps"; import { renderSnaps } from "../renderer/renderSnaps";
import { roundRect } from "../renderer/roundRect"; import { roundRect } from "../renderer/roundRect";
import { import {

View file

@ -1,7 +1,8 @@
import { throttleRAF } from "@excalidraw/common"; import { throttleRAF } from "@excalidraw/common";
import { renderElement } from "@excalidraw/element/renderElement";
import { bootstrapCanvas, getNormalizedCanvasDimensions } from "./helpers"; import { bootstrapCanvas, getNormalizedCanvasDimensions } from "./helpers";
import { renderElement } from "./renderElement";
import type { NewElementSceneRenderConfig } from "../scene/types"; import type { NewElementSceneRenderConfig } from "../scene/types";

View file

@ -14,6 +14,8 @@ import {
shouldApplyFrameClip, shouldApplyFrameClip,
} from "@excalidraw/element/frame"; } from "@excalidraw/element/frame";
import { renderElement } from "@excalidraw/element/renderElement";
import type { import type {
ElementsMap, ElementsMap,
ExcalidrawFrameLikeElement, ExcalidrawFrameLikeElement,
@ -25,7 +27,6 @@ import {
ELEMENT_LINK_IMG, ELEMENT_LINK_IMG,
getLinkHandleFromCoords, getLinkHandleFromCoords,
} from "../components/hyperlink/helpers"; } from "../components/hyperlink/helpers";
import { renderElement } from "../renderer/renderElement";
import { bootstrapCanvas, getNormalizedCanvasDimensions } from "./helpers"; import { bootstrapCanvas, getNormalizedCanvasDimensions } from "./helpers";

View file

@ -31,6 +31,13 @@ import { getContainingFrame } from "@excalidraw/element/frame";
import { getCornerRadius, isPathALoop } from "@excalidraw/element/shapes"; import { getCornerRadius, isPathALoop } from "@excalidraw/element/shapes";
import { ShapeCache } from "@excalidraw/element/ShapeCache";
import {
getFreeDrawSvgPath,
IMAGE_INVERT_FILTER,
} from "@excalidraw/element/renderElement";
import type { import type {
ExcalidrawElement, ExcalidrawElement,
ExcalidrawTextElementWithContainer, ExcalidrawTextElementWithContainer,
@ -38,9 +45,6 @@ import type {
} from "@excalidraw/element/types"; } from "@excalidraw/element/types";
import { getVerticalOffset } from "../fonts/FontMetadata"; import { getVerticalOffset } from "../fonts/FontMetadata";
import { ShapeCache } from "../scene/ShapeCache";
import { getFreeDrawSvgPath, IMAGE_INVERT_FILTER } from "./renderElement";
import type { RenderableElementsMap, SVGRenderConfig } from "../scene/types"; import type { RenderableElementsMap, SVGRenderConfig } from "../scene/types";
import type { AppState, BinaryFiles } from "../types"; import type { AppState, BinaryFiles } from "../types";

View file

@ -1,13 +1,14 @@
import throttle from "lodash.throttle"; import throttle from "lodash.throttle";
import { ENV } from "@excalidraw/common"; import {
ENV,
randomInteger,
arrayToMap,
toBrandedType,
} from "@excalidraw/common";
import { isNonDeletedElement } from "@excalidraw/element"; import { isNonDeletedElement } from "@excalidraw/element";
import { isFrameLikeElement } from "@excalidraw/element/typeChecks"; import { isFrameLikeElement } from "@excalidraw/element/typeChecks";
import { randomInteger } from "@excalidraw/common";
import { arrayToMap } from "@excalidraw/common";
import { toBrandedType } from "@excalidraw/common";
import type { LinearElementEditor } from "@excalidraw/element/linearElementEditor"; import type { LinearElementEditor } from "@excalidraw/element/linearElementEditor";
import type { import type {
ExcalidrawElement, ExcalidrawElement,

View file

@ -12,7 +12,7 @@ export {
hasStrokeStyle, hasStrokeStyle,
canHaveArrowheads, canHaveArrowheads,
canChangeRoundness, canChangeRoundness,
} from "./comparisons"; } from "@excalidraw/element/comparisons";
export { export {
getNormalizedZoom, getNormalizedZoom,
getNormalizedGridSize, getNormalizedGridSize,

View file

@ -34,8 +34,6 @@ interface ImportMetaEnv {
//Debug flags //Debug flags
// To enable bounding box for text containers
VITE_APP_DEBUG_ENABLE_TEXT_CONTAINER_BOUNDING_BOX: string;
VITE_APP_DISABLE_SENTRY: string; VITE_APP_DISABLE_SENTRY: string;
// Set this flag to false if you want to open the overlay by default // Set this flag to false if you want to open the overlay by default
VITE_APP_COLLAPSE_OVERLAY: string; VITE_APP_COLLAPSE_OVERLAY: string;