mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-09-08 01:57:02 +02:00
Compare commits
1 Commits
feature/do
...
mrazator/t
Author | SHA1 | Date | |
---|---|---|---|
![]() |
2939b03e78 |
@@ -49,7 +49,7 @@ export const actionUnbindText = register({
|
||||
selectedElements.forEach((element) => {
|
||||
const boundTextElement = getBoundTextElement(element, elementsMap);
|
||||
if (boundTextElement) {
|
||||
const { width, height } = measureText(
|
||||
const { width, height, baseline } = measureText(
|
||||
boundTextElement.originalText,
|
||||
getFontString(boundTextElement),
|
||||
boundTextElement.lineHeight,
|
||||
@@ -63,6 +63,7 @@ export const actionUnbindText = register({
|
||||
containerId: null,
|
||||
width,
|
||||
height,
|
||||
baseline,
|
||||
text: boundTextElement.originalText,
|
||||
x,
|
||||
y,
|
||||
|
@@ -219,6 +219,7 @@ exports[`Test Transform > Test arrow bindings > should bind arrows to existing t
|
||||
{
|
||||
"angle": 0,
|
||||
"backgroundColor": "transparent",
|
||||
"baseline": 0,
|
||||
"boundElements": [
|
||||
{
|
||||
"id": "id48",
|
||||
@@ -262,6 +263,7 @@ exports[`Test Transform > Test arrow bindings > should bind arrows to existing t
|
||||
{
|
||||
"angle": 0,
|
||||
"backgroundColor": "transparent",
|
||||
"baseline": 0,
|
||||
"boundElements": [
|
||||
{
|
||||
"id": "id48",
|
||||
@@ -363,6 +365,7 @@ exports[`Test Transform > Test arrow bindings > should bind arrows to existing t
|
||||
{
|
||||
"angle": 0,
|
||||
"backgroundColor": "transparent",
|
||||
"baseline": 0,
|
||||
"boundElements": null,
|
||||
"containerId": "id48",
|
||||
"fillStyle": "solid",
|
||||
@@ -459,6 +462,7 @@ exports[`Test Transform > Test arrow bindings > should bind arrows to shapes whe
|
||||
{
|
||||
"angle": 0,
|
||||
"backgroundColor": "transparent",
|
||||
"baseline": 0,
|
||||
"boundElements": null,
|
||||
"containerId": "id37",
|
||||
"fillStyle": "solid",
|
||||
@@ -625,6 +629,7 @@ exports[`Test Transform > Test arrow bindings > should bind arrows to text when
|
||||
{
|
||||
"angle": 0,
|
||||
"backgroundColor": "transparent",
|
||||
"baseline": 0,
|
||||
"boundElements": null,
|
||||
"containerId": "id41",
|
||||
"fillStyle": "solid",
|
||||
@@ -663,6 +668,7 @@ exports[`Test Transform > Test arrow bindings > should bind arrows to text when
|
||||
{
|
||||
"angle": 0,
|
||||
"backgroundColor": "transparent",
|
||||
"baseline": 0,
|
||||
"boundElements": [
|
||||
{
|
||||
"id": "id41",
|
||||
@@ -706,6 +712,7 @@ exports[`Test Transform > Test arrow bindings > should bind arrows to text when
|
||||
{
|
||||
"angle": 0,
|
||||
"backgroundColor": "transparent",
|
||||
"baseline": 0,
|
||||
"boundElements": [
|
||||
{
|
||||
"id": "id41",
|
||||
@@ -1139,6 +1146,7 @@ exports[`Test Transform > should transform text element 1`] = `
|
||||
{
|
||||
"angle": 0,
|
||||
"backgroundColor": "transparent",
|
||||
"baseline": 0,
|
||||
"boundElements": null,
|
||||
"containerId": null,
|
||||
"fillStyle": "solid",
|
||||
@@ -1177,6 +1185,7 @@ exports[`Test Transform > should transform text element 2`] = `
|
||||
{
|
||||
"angle": 0,
|
||||
"backgroundColor": "transparent",
|
||||
"baseline": 0,
|
||||
"boundElements": null,
|
||||
"containerId": null,
|
||||
"fillStyle": "solid",
|
||||
@@ -1415,6 +1424,7 @@ exports[`Test Transform > should transform to labelled arrows when label provide
|
||||
{
|
||||
"angle": 0,
|
||||
"backgroundColor": "transparent",
|
||||
"baseline": 0,
|
||||
"boundElements": null,
|
||||
"containerId": "id25",
|
||||
"fillStyle": "solid",
|
||||
@@ -1453,6 +1463,7 @@ exports[`Test Transform > should transform to labelled arrows when label provide
|
||||
{
|
||||
"angle": 0,
|
||||
"backgroundColor": "transparent",
|
||||
"baseline": 0,
|
||||
"boundElements": null,
|
||||
"containerId": "id26",
|
||||
"fillStyle": "solid",
|
||||
@@ -1491,6 +1502,7 @@ exports[`Test Transform > should transform to labelled arrows when label provide
|
||||
{
|
||||
"angle": 0,
|
||||
"backgroundColor": "transparent",
|
||||
"baseline": 0,
|
||||
"boundElements": null,
|
||||
"containerId": "id27",
|
||||
"fillStyle": "solid",
|
||||
@@ -1530,6 +1542,7 @@ exports[`Test Transform > should transform to labelled arrows when label provide
|
||||
{
|
||||
"angle": 0,
|
||||
"backgroundColor": "transparent",
|
||||
"baseline": 0,
|
||||
"boundElements": null,
|
||||
"containerId": "id28",
|
||||
"fillStyle": "solid",
|
||||
@@ -1779,6 +1792,7 @@ exports[`Test Transform > should transform to text containers when label provide
|
||||
{
|
||||
"angle": 0,
|
||||
"backgroundColor": "transparent",
|
||||
"baseline": 0,
|
||||
"boundElements": null,
|
||||
"containerId": "id13",
|
||||
"fillStyle": "solid",
|
||||
@@ -1817,6 +1831,7 @@ exports[`Test Transform > should transform to text containers when label provide
|
||||
{
|
||||
"angle": 0,
|
||||
"backgroundColor": "transparent",
|
||||
"baseline": 0,
|
||||
"boundElements": null,
|
||||
"containerId": "id14",
|
||||
"fillStyle": "solid",
|
||||
@@ -1856,6 +1871,7 @@ exports[`Test Transform > should transform to text containers when label provide
|
||||
{
|
||||
"angle": 0,
|
||||
"backgroundColor": "transparent",
|
||||
"baseline": 0,
|
||||
"boundElements": null,
|
||||
"containerId": "id15",
|
||||
"fillStyle": "solid",
|
||||
@@ -1897,6 +1913,7 @@ exports[`Test Transform > should transform to text containers when label provide
|
||||
{
|
||||
"angle": 0,
|
||||
"backgroundColor": "transparent",
|
||||
"baseline": 0,
|
||||
"boundElements": null,
|
||||
"containerId": "id16",
|
||||
"fillStyle": "solid",
|
||||
@@ -1936,6 +1953,7 @@ exports[`Test Transform > should transform to text containers when label provide
|
||||
{
|
||||
"angle": 0,
|
||||
"backgroundColor": "transparent",
|
||||
"baseline": 0,
|
||||
"boundElements": null,
|
||||
"containerId": "id17",
|
||||
"fillStyle": "solid",
|
||||
@@ -1976,6 +1994,7 @@ exports[`Test Transform > should transform to text containers when label provide
|
||||
{
|
||||
"angle": 0,
|
||||
"backgroundColor": "transparent",
|
||||
"baseline": 0,
|
||||
"boundElements": null,
|
||||
"containerId": "id18",
|
||||
"fillStyle": "solid",
|
||||
|
@@ -35,13 +35,14 @@ import {
|
||||
import { getDefaultAppState } from "../appState";
|
||||
import { LinearElementEditor } from "../element/linearElementEditor";
|
||||
import { bumpVersion } from "../element/mutateElement";
|
||||
import { getUpdatedTimestamp, updateActiveTool } from "../utils";
|
||||
import { getFontString, getUpdatedTimestamp, updateActiveTool } from "../utils";
|
||||
import { arrayToMap } from "../utils";
|
||||
import { MarkOptional, Mutable } from "../utility-types";
|
||||
import {
|
||||
detectLineHeight,
|
||||
getContainerElement,
|
||||
getDefaultLineHeight,
|
||||
measureBaseline,
|
||||
} from "../element/textElement";
|
||||
import { normalizeLink } from "./url";
|
||||
|
||||
@@ -206,6 +207,16 @@ const restoreElement = (
|
||||
: // no element height likely means programmatic use, so default
|
||||
// to a fixed line height
|
||||
getDefaultLineHeight(element.fontFamily));
|
||||
|
||||
const baseline = measureBaseline(
|
||||
element.text,
|
||||
getFontString({
|
||||
fontSize: element.fontSize,
|
||||
fontFamily: element.fontFamily,
|
||||
}),
|
||||
String(lineHeight),
|
||||
);
|
||||
|
||||
element = restoreElementWithProperties(element, {
|
||||
fontSize,
|
||||
fontFamily,
|
||||
@@ -216,6 +227,7 @@ const restoreElement = (
|
||||
originalText: element.originalText || text,
|
||||
|
||||
lineHeight,
|
||||
baseline,
|
||||
});
|
||||
|
||||
// if empty text, mark as deleted. We keep in array
|
||||
|
@@ -246,6 +246,7 @@ export const newTextElement = (
|
||||
y: opts.y - offsets.y,
|
||||
width: metrics.width,
|
||||
height: metrics.height,
|
||||
baseline: metrics.baseline,
|
||||
containerId: opts.containerId || null,
|
||||
originalText: text,
|
||||
lineHeight,
|
||||
@@ -263,12 +264,13 @@ const getAdjustedDimensions = (
|
||||
y: number;
|
||||
width: number;
|
||||
height: number;
|
||||
baseline: number;
|
||||
} => {
|
||||
const { width: nextWidth, height: nextHeight } = measureText(
|
||||
nextText,
|
||||
getFontString(element),
|
||||
element.lineHeight,
|
||||
);
|
||||
const {
|
||||
width: nextWidth,
|
||||
height: nextHeight,
|
||||
baseline: nextBaseline,
|
||||
} = measureText(nextText, getFontString(element), element.lineHeight);
|
||||
const { textAlign, verticalAlign } = element;
|
||||
let x: number;
|
||||
let y: number;
|
||||
@@ -322,6 +324,7 @@ const getAdjustedDimensions = (
|
||||
return {
|
||||
width: nextWidth,
|
||||
height: nextHeight,
|
||||
baseline: nextBaseline,
|
||||
x: Number.isFinite(x) ? x : element.x,
|
||||
y: Number.isFinite(y) ? y : element.y,
|
||||
};
|
||||
|
@@ -52,6 +52,10 @@ import {
|
||||
handleBindTextResize,
|
||||
getBoundTextMaxWidth,
|
||||
getApproxMinLineHeight,
|
||||
measureText,
|
||||
getBoundTextMaxHeight,
|
||||
measureBaselines,
|
||||
BaselineInput,
|
||||
} from "./textElement";
|
||||
import { LinearElementEditor } from "./linearElementEditor";
|
||||
|
||||
@@ -209,7 +213,8 @@ const measureFontSizeFromWidth = (
|
||||
element: NonDeleted<ExcalidrawTextElement>,
|
||||
elementsMap: ElementsMap,
|
||||
nextWidth: number,
|
||||
): { size: number } | null => {
|
||||
nextHeight: number,
|
||||
): { size: number; baseline: number } | null => {
|
||||
// We only use width to scale font on resize
|
||||
let width = element.width;
|
||||
|
||||
@@ -224,9 +229,14 @@ const measureFontSizeFromWidth = (
|
||||
if (nextFontSize < MIN_FONT_SIZE) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const metrics = measureText(
|
||||
element.text,
|
||||
getFontString({ fontSize: nextFontSize, fontFamily: element.fontFamily }),
|
||||
element.lineHeight,
|
||||
);
|
||||
return {
|
||||
size: nextFontSize,
|
||||
baseline: metrics.baseline + (nextHeight - metrics.height),
|
||||
};
|
||||
};
|
||||
|
||||
@@ -299,7 +309,12 @@ const resizeSingleTextElement = (
|
||||
if (scale > 0) {
|
||||
const nextWidth = element.width * scale;
|
||||
const nextHeight = element.height * scale;
|
||||
const metrics = measureFontSizeFromWidth(element, elementsMap, nextWidth);
|
||||
const metrics = measureFontSizeFromWidth(
|
||||
element,
|
||||
elementsMap,
|
||||
nextWidth,
|
||||
nextHeight,
|
||||
);
|
||||
if (metrics === null) {
|
||||
return;
|
||||
}
|
||||
@@ -327,6 +342,7 @@ const resizeSingleTextElement = (
|
||||
fontSize: metrics.size,
|
||||
width: nextWidth,
|
||||
height: nextHeight,
|
||||
baseline: metrics.baseline,
|
||||
x: nextElementX,
|
||||
y: nextElementY,
|
||||
});
|
||||
@@ -380,7 +396,7 @@ export const resizeSingleElement = (
|
||||
let scaleX = atStartBoundsWidth / boundsCurrentWidth;
|
||||
let scaleY = atStartBoundsHeight / boundsCurrentHeight;
|
||||
|
||||
let boundTextFont: { fontSize?: number } = {};
|
||||
let boundTextFont: { fontSize?: number; baseline?: number } = {};
|
||||
const boundTextElement = getBoundTextElement(element, elementsMap);
|
||||
|
||||
if (transformHandleDirection.includes("e")) {
|
||||
@@ -432,6 +448,7 @@ export const resizeSingleElement = (
|
||||
if (stateOfBoundTextElementAtResize) {
|
||||
boundTextFont = {
|
||||
fontSize: stateOfBoundTextElementAtResize.fontSize,
|
||||
baseline: stateOfBoundTextElementAtResize.baseline,
|
||||
};
|
||||
}
|
||||
if (shouldMaintainAspectRatio) {
|
||||
@@ -445,12 +462,14 @@ export const resizeSingleElement = (
|
||||
boundTextElement,
|
||||
elementsMap,
|
||||
getBoundTextMaxWidth(updatedElement, boundTextElement),
|
||||
getBoundTextMaxHeight(updatedElement, boundTextElement),
|
||||
);
|
||||
if (nextFont === null) {
|
||||
return;
|
||||
}
|
||||
boundTextFont = {
|
||||
fontSize: nextFont.size,
|
||||
baseline: nextFont.baseline,
|
||||
};
|
||||
} else {
|
||||
const minWidth = getApproxMinLineWidth(
|
||||
@@ -619,6 +638,7 @@ export const resizeSingleElement = (
|
||||
if (boundTextElement && boundTextFont != null) {
|
||||
mutateElement(boundTextElement, {
|
||||
fontSize: boundTextFont.fontSize,
|
||||
baseline: boundTextFont.baseline,
|
||||
});
|
||||
}
|
||||
handleBindTextResize(
|
||||
@@ -745,11 +765,31 @@ export const resizeMultipleElements = (
|
||||
> & {
|
||||
points?: ExcalidrawLinearElement["points"];
|
||||
fontSize?: ExcalidrawTextElement["fontSize"];
|
||||
baseline?: ExcalidrawTextElement["baseline"];
|
||||
scale?: ExcalidrawImageElement["scale"];
|
||||
boundTextFontSize?: ExcalidrawTextElement["fontSize"];
|
||||
};
|
||||
}[] = [];
|
||||
|
||||
const precomputedBaselines = measureBaselines(
|
||||
targetElements.reduce((inputs, { latest: element }) => {
|
||||
if (!isTextElement(element)) {
|
||||
return inputs;
|
||||
}
|
||||
|
||||
inputs.push({
|
||||
id: element.id,
|
||||
text: element.text,
|
||||
font: getFontString({
|
||||
fontSize: element.fontSize,
|
||||
fontFamily: element.fontFamily,
|
||||
}),
|
||||
lineHeight: String(element.lineHeight),
|
||||
});
|
||||
return inputs;
|
||||
}, [] as BaselineInput[]),
|
||||
);
|
||||
|
||||
for (const { orig, latest } of targetElements) {
|
||||
// bounded text elements are updated along with their container elements
|
||||
if (isTextElement(orig) && isBoundToContainer(orig)) {
|
||||
@@ -819,11 +859,13 @@ export const resizeMultipleElements = (
|
||||
}
|
||||
|
||||
if (isTextElement(orig)) {
|
||||
const metrics = measureFontSizeFromWidth(orig, elementsMap, width);
|
||||
if (!metrics) {
|
||||
const nextFontSize = orig.fontSize * scale;
|
||||
if (nextFontSize < MIN_FONT_SIZE) {
|
||||
return;
|
||||
}
|
||||
update.fontSize = metrics.size;
|
||||
|
||||
update.fontSize = nextFontSize;
|
||||
update.baseline = precomputedBaselines.get(orig.id);
|
||||
}
|
||||
|
||||
const boundTextElement = originalElements.get(
|
||||
|
@@ -18,6 +18,7 @@ import {
|
||||
DEFAULT_FONT_FAMILY,
|
||||
DEFAULT_FONT_SIZE,
|
||||
FONT_FAMILY,
|
||||
isSafari,
|
||||
TEXT_ALIGN,
|
||||
VERTICAL_ALIGN,
|
||||
} from "../constants";
|
||||
@@ -60,6 +61,7 @@ export const redrawTextBoundingBox = (
|
||||
text: textElement.text,
|
||||
width: textElement.width,
|
||||
height: textElement.height,
|
||||
baseline: textElement.baseline,
|
||||
};
|
||||
|
||||
boundTextUpdates.text = textElement.text;
|
||||
@@ -80,6 +82,7 @@ export const redrawTextBoundingBox = (
|
||||
|
||||
boundTextUpdates.width = metrics.width;
|
||||
boundTextUpdates.height = metrics.height;
|
||||
boundTextUpdates.baseline = metrics.baseline;
|
||||
|
||||
if (container) {
|
||||
const maxContainerHeight = getBoundTextMaxHeight(
|
||||
@@ -180,6 +183,7 @@ export const handleBindTextResize = (
|
||||
const maxWidth = getBoundTextMaxWidth(container, textElement);
|
||||
const maxHeight = getBoundTextMaxHeight(container, textElement);
|
||||
let containerHeight = container.height;
|
||||
let nextBaseLine = textElement.baseline;
|
||||
if (
|
||||
shouldMaintainAspectRatio ||
|
||||
(transformHandleType !== "n" && transformHandleType !== "s")
|
||||
@@ -198,6 +202,7 @@ export const handleBindTextResize = (
|
||||
);
|
||||
nextHeight = metrics.height;
|
||||
nextWidth = metrics.width;
|
||||
nextBaseLine = metrics.baseline;
|
||||
}
|
||||
// increase height in case text element height exceeds
|
||||
if (nextHeight > maxHeight) {
|
||||
@@ -225,6 +230,7 @@ export const handleBindTextResize = (
|
||||
text,
|
||||
width: nextWidth,
|
||||
height: nextHeight,
|
||||
baseline: nextBaseLine,
|
||||
});
|
||||
|
||||
if (!isArrowElement(container)) {
|
||||
@@ -288,7 +294,102 @@ export const measureText = (
|
||||
const fontSize = parseFloat(font);
|
||||
const height = getTextHeight(text, fontSize, lineHeight);
|
||||
const width = getTextWidth(text, font);
|
||||
return { width, height };
|
||||
const baseline = measureBaseline(text, font, String(lineHeight));
|
||||
return { width, height, baseline };
|
||||
};
|
||||
|
||||
export type BaselineInput = {
|
||||
id: string;
|
||||
font: FontString;
|
||||
lineHeight: string;
|
||||
text: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Baseline calculation is based on expensive DOM operations, resulting in forced reflow.
|
||||
* Therefore whenever we can, we should always batch the calculation of the baselines upfront for all the elements.
|
||||
*/
|
||||
export const measureBaselines = (inputs: BaselineInput[]) => {
|
||||
const baselines = new Map<string, number>();
|
||||
const containers = new Map<string, [HTMLDivElement, BaselineInput]>();
|
||||
|
||||
// Batch DOM writes (and reads below) to avoid layout trashing
|
||||
for (const input of inputs) {
|
||||
const container = document.createElement("div");
|
||||
const span = document.createElement("span");
|
||||
|
||||
Object.assign(span.style, {
|
||||
display: "inline-block",
|
||||
// overflow: "hidden",
|
||||
});
|
||||
|
||||
Object.assign(container.style, {
|
||||
font: input.font,
|
||||
lineHeight: input.lineHeight,
|
||||
minHeight: "1em",
|
||||
visibility: "hidden",
|
||||
// whitespace: "pre",
|
||||
// overflow: "hidden",
|
||||
// wordBreak: "break-word",
|
||||
// whiteSpace: "pre-wrap",
|
||||
});
|
||||
|
||||
container.innerText = input.text;
|
||||
|
||||
container.appendChild(span);
|
||||
document.body.appendChild(container);
|
||||
|
||||
containers.set(input.id, [container, input]);
|
||||
}
|
||||
|
||||
for (const [id, [container, input]] of containers.entries()) {
|
||||
const span = container.lastChild as HTMLSpanElement;
|
||||
let baseline =
|
||||
span.getBoundingClientRect().y - container.getBoundingClientRect().y;
|
||||
|
||||
if (isSafari) {
|
||||
const height = container.offsetHeight;
|
||||
const fontSize = parseFloat(input.font);
|
||||
const canvasHeight = getTextHeight(
|
||||
input.text,
|
||||
fontSize,
|
||||
Number(input.lineHeight) as any,
|
||||
);
|
||||
// In Safari the font size gets rounded off when rendering hence calculating the safari height and shifting the baseline if it differs
|
||||
// from the actual canvas height
|
||||
const domHeight = getTextHeight(
|
||||
input.text,
|
||||
Math.round(fontSize),
|
||||
Number(input.lineHeight) as any,
|
||||
);
|
||||
if (canvasHeight > height) {
|
||||
baseline += canvasHeight - domHeight;
|
||||
}
|
||||
|
||||
if (height > canvasHeight) {
|
||||
baseline -= domHeight - canvasHeight;
|
||||
}
|
||||
}
|
||||
|
||||
baselines.set(id, baseline);
|
||||
}
|
||||
|
||||
for (const [container] of containers.values()) {
|
||||
document.body.removeChild(container);
|
||||
}
|
||||
|
||||
return baselines;
|
||||
};
|
||||
|
||||
export const measureBaseline = (
|
||||
text: string,
|
||||
font: FontString,
|
||||
lineHeight: string,
|
||||
) => {
|
||||
// In single measurement the element id is irrelevant
|
||||
const fakeId = "fake-id";
|
||||
const baselines = measureBaselines([{ id: fakeId, text, font, lineHeight }]);
|
||||
return baselines.get(fakeId)!;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@@ -176,6 +176,7 @@ export type ExcalidrawTextElement = _ExcalidrawElementBase &
|
||||
fontSize: number;
|
||||
fontFamily: FontFamilyValues;
|
||||
text: string;
|
||||
baseline: number;
|
||||
textAlign: TextAlign;
|
||||
verticalAlign: VerticalAlign;
|
||||
containerId: ExcalidrawGenericElement["id"] | null;
|
||||
|
@@ -395,24 +395,12 @@ const drawElementOnCanvas = (
|
||||
element.fontSize,
|
||||
element.lineHeight,
|
||||
);
|
||||
|
||||
const metrics = context.measureText(element.text);
|
||||
const lineGap =
|
||||
lineHeightPx -
|
||||
(metrics.fontBoundingBoxAscent + metrics.fontBoundingBoxDescent);
|
||||
/**
|
||||
* Set a vertical offset to be aligned with <textarea>.
|
||||
* - `fontBoundingBoxAscent` is here the font bouding box with its default line-height used in textareas
|
||||
* - half of the line gap is the additional padding above and below the bounding box when line-height isn't equal to the default value
|
||||
* - for details check - https://codesandbox.io/p/devbox/v4nsqz?file=%2Fsrc%2Findex.js%3A1%2C1-166%2C1
|
||||
*/
|
||||
context.translate(0, metrics.fontBoundingBoxAscent + lineGap / 2);
|
||||
|
||||
const verticalOffset = element.height - element.baseline;
|
||||
for (let index = 0; index < lines.length; index++) {
|
||||
context.fillText(
|
||||
lines[index],
|
||||
horizontalOffset,
|
||||
index * lineHeightPx,
|
||||
(index + 1) * lineHeightPx - verticalOffset,
|
||||
);
|
||||
}
|
||||
context.restore();
|
||||
|
@@ -289,6 +289,7 @@ exports[`restoreElements > should restore text element correctly passing value f
|
||||
{
|
||||
"angle": 0,
|
||||
"backgroundColor": "transparent",
|
||||
"baseline": 0,
|
||||
"boundElements": [],
|
||||
"containerId": null,
|
||||
"fillStyle": "solid",
|
||||
@@ -329,6 +330,7 @@ exports[`restoreElements > should restore text element correctly with unknown fo
|
||||
{
|
||||
"angle": 0,
|
||||
"backgroundColor": "transparent",
|
||||
"baseline": 0,
|
||||
"boundElements": [],
|
||||
"containerId": null,
|
||||
"fillStyle": "solid",
|
||||
|
Reference in New Issue
Block a user