瀏覽代碼

introduce baseline in element making it backward compat

Aakansha Doshi 2 年之前
父節點
當前提交
f8b25375a4

+ 2 - 1
src/actions/actionBoundText.tsx

@@ -42,7 +42,7 @@ export const actionUnbindText = register({
     selectedElements.forEach((element) => {
     selectedElements.forEach((element) => {
       const boundTextElement = getBoundTextElement(element);
       const boundTextElement = getBoundTextElement(element);
       if (boundTextElement) {
       if (boundTextElement) {
-        const { width, height } = measureText(
+        const { width, height, baseline } = measureText(
           boundTextElement.originalText,
           boundTextElement.originalText,
           getFontString(boundTextElement),
           getFontString(boundTextElement),
           boundTextElement.lineHeight,
           boundTextElement.lineHeight,
@@ -56,6 +56,7 @@ export const actionUnbindText = register({
           containerId: null,
           containerId: null,
           width,
           width,
           height,
           height,
+          baseline,
           text: boundTextElement.originalText,
           text: boundTextElement.originalText,
         });
         });
         mutateElement(element, {
         mutateElement(element, {

+ 5 - 6
src/components/App.tsx

@@ -1348,14 +1348,13 @@ class App extends React.Component<AppProps, AppState> {
             return false;
             return false;
           }
           }
         }
         }
-        return true;
         // don't render text element that's being currently edited (it's
         // don't render text element that's being currently edited (it's
         // rendered on remote only)
         // rendered on remote only)
-        // return (
-        //   !this.state.editingElement ||
-        //   this.state.editingElement.type !== "text" ||
-        //   element.id !== this.state.editingElement.id
-        // );
+        return (
+          !this.state.editingElement ||
+          this.state.editingElement.type !== "text" ||
+          element.id !== this.state.editingElement.id
+        );
       });
       });
 
 
     const selectionColor = getComputedStyle(
     const selectionColor = getComputedStyle(

+ 26 - 16
src/data/restore.ts

@@ -31,11 +31,15 @@ import {
 import { getDefaultAppState } from "../appState";
 import { getDefaultAppState } from "../appState";
 import { LinearElementEditor } from "../element/linearElementEditor";
 import { LinearElementEditor } from "../element/linearElementEditor";
 import { bumpVersion } from "../element/mutateElement";
 import { bumpVersion } from "../element/mutateElement";
-import { getUpdatedTimestamp, updateActiveTool } from "../utils";
+import { getFontString, getUpdatedTimestamp, updateActiveTool } from "../utils";
 import { arrayToMap } from "../utils";
 import { arrayToMap } from "../utils";
 import oc from "open-color";
 import oc from "open-color";
 import { MarkOptional, Mutable } from "../utility-types";
 import { MarkOptional, Mutable } from "../utility-types";
-import { detectLineHeight, getDefaultLineHeight } from "../element/textElement";
+import {
+  detectLineHeight,
+  getDefaultLineHeight,
+  measureBaseline,
+} from "../element/textElement";
 
 
 type RestoredAppState = Omit<
 type RestoredAppState = Omit<
   AppState,
   AppState,
@@ -170,7 +174,19 @@ const restoreElement = (
         fontFamily = getFontFamilyByName(_fontFamily);
         fontFamily = getFontFamilyByName(_fontFamily);
       }
       }
       const text = element.text ?? "";
       const text = element.text ?? "";
-
+      // line-height might not be specified either when creating elements
+      // programmatically, or when importing old diagrams.
+      // For the latter we want to detect the original line height which
+      // will likely differ from our per-font fixed line height we now use,
+      // to maintain backward compatibility.
+      const lineHeight =
+        element.lineHeight ||
+        (element.height
+          ? // detect line-height from current element height and font-size
+            detectLineHeight(element)
+          : // no element height likely means programmatic use, so default
+            // to a fixed line height
+            getDefaultLineHeight(element.fontFamily));
       element = restoreElementWithProperties(element, {
       element = restoreElementWithProperties(element, {
         fontSize,
         fontSize,
         fontFamily,
         fontFamily,
@@ -179,19 +195,13 @@ const restoreElement = (
         verticalAlign: element.verticalAlign || DEFAULT_VERTICAL_ALIGN,
         verticalAlign: element.verticalAlign || DEFAULT_VERTICAL_ALIGN,
         containerId: element.containerId ?? null,
         containerId: element.containerId ?? null,
         originalText: element.originalText || text,
         originalText: element.originalText || text,
-        // line-height might not be specified either when creating elements
-        // programmatically, or when importing old diagrams.
-        // For the latter we want to detect the original line height which
-        // will likely differ from our per-font fixed line height we now use,
-        // to maintain backward compatibility.
-        lineHeight:
-          element.lineHeight ||
-          (element.height
-            ? // detect line-height from current element height and font-size
-              detectLineHeight(element)
-            : // no element height likely means programmatic use, so default
-              // to a fixed line height
-              getDefaultLineHeight(element.fontFamily)),
+
+        lineHeight,
+        baseline: measureBaseline(
+          element.text,
+          getFontString(element),
+          lineHeight,
+        ),
       });
       });
 
 
       if (refreshDimensions) {
       if (refreshDimensions) {

+ 10 - 5
src/element/newElement.ts

@@ -30,6 +30,7 @@ import {
   wrapText,
   wrapText,
   getMaxContainerWidth,
   getMaxContainerWidth,
   getDefaultLineHeight,
   getDefaultLineHeight,
+  measureBaseline,
 } from "./textElement";
 } from "./textElement";
 import { VERTICAL_ALIGN } from "../constants";
 import { VERTICAL_ALIGN } from "../constants";
 import { isArrowElement } from "./typeChecks";
 import { isArrowElement } from "./typeChecks";
@@ -145,6 +146,7 @@ export const newTextElement = (
   const text = normalizeText(opts.text);
   const text = normalizeText(opts.text);
   const metrics = measureText(text, getFontString(opts), lineHeight);
   const metrics = measureText(text, getFontString(opts), lineHeight);
   const offsets = getTextElementPositionOffsets(opts, metrics);
   const offsets = getTextElementPositionOffsets(opts, metrics);
+
   const textElement = newElementWith(
   const textElement = newElementWith(
     {
     {
       ..._newElementBase<ExcalidrawTextElement>("text", opts),
       ..._newElementBase<ExcalidrawTextElement>("text", opts),
@@ -157,6 +159,7 @@ export const newTextElement = (
       y: opts.y - offsets.y,
       y: opts.y - offsets.y,
       width: metrics.width,
       width: metrics.width,
       height: metrics.height,
       height: metrics.height,
+      baseline: metrics.baseline,
       containerId: opts.containerId || null,
       containerId: opts.containerId || null,
       originalText: text,
       originalText: text,
       lineHeight,
       lineHeight,
@@ -174,14 +177,15 @@ const getAdjustedDimensions = (
   y: number;
   y: number;
   width: number;
   width: number;
   height: number;
   height: number;
+  baseline: number;
 } => {
 } => {
   const container = getContainerElement(element);
   const container = getContainerElement(element);
 
 
-  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;
   const { textAlign, verticalAlign } = element;
   let x: number;
   let x: number;
   let y: number;
   let y: number;
@@ -256,6 +260,7 @@ const getAdjustedDimensions = (
   return {
   return {
     width: nextWidth,
     width: nextWidth,
     height: nextHeight,
     height: nextHeight,
+    baseline: nextBaseline,
     x: Number.isFinite(x) ? x : element.x,
     x: Number.isFinite(x) ? x : element.x,
     y: Number.isFinite(y) ? y : element.y,
     y: Number.isFinite(y) ? y : element.y,
   };
   };

+ 11 - 6
src/element/textElement.ts

@@ -58,6 +58,7 @@ export const redrawTextBoundingBox = (
     text: textElement.text,
     text: textElement.text,
     width: textElement.width,
     width: textElement.width,
     height: textElement.height,
     height: textElement.height,
+    baseline: textElement.baseline,
   };
   };
 
 
   boundTextUpdates.text = textElement.text;
   boundTextUpdates.text = textElement.text;
@@ -78,6 +79,7 @@ export const redrawTextBoundingBox = (
 
 
   boundTextUpdates.width = metrics.width;
   boundTextUpdates.width = metrics.width;
   boundTextUpdates.height = metrics.height;
   boundTextUpdates.height = metrics.height;
+  boundTextUpdates.baseline = metrics.baseline;
 
 
   if (container) {
   if (container) {
     if (isArrowElement(container)) {
     if (isArrowElement(container)) {
@@ -183,6 +185,7 @@ export const handleBindTextResize = (
     const maxWidth = getMaxContainerWidth(container);
     const maxWidth = getMaxContainerWidth(container);
     const maxHeight = getMaxContainerHeight(container);
     const maxHeight = getMaxContainerHeight(container);
     let containerHeight = containerDims.height;
     let containerHeight = containerDims.height;
+    let nextBaseLine = textElement.baseline;
     if (transformHandleType !== "n" && transformHandleType !== "s") {
     if (transformHandleType !== "n" && transformHandleType !== "s") {
       if (text) {
       if (text) {
         text = wrapText(
         text = wrapText(
@@ -191,13 +194,14 @@ export const handleBindTextResize = (
           maxWidth,
           maxWidth,
         );
         );
       }
       }
-      const dimensions = measureText(
+      const metrics = measureText(
         text,
         text,
         getFontString(textElement),
         getFontString(textElement),
         textElement.lineHeight,
         textElement.lineHeight,
       );
       );
-      nextHeight = dimensions.height;
-      nextWidth = dimensions.width;
+      nextHeight = metrics.height;
+      nextWidth = metrics.width;
+      nextBaseLine = metrics.baseline;
     }
     }
     // increase height in case text element height exceeds
     // increase height in case text element height exceeds
     if (nextHeight > maxHeight) {
     if (nextHeight > maxHeight) {
@@ -225,6 +229,7 @@ export const handleBindTextResize = (
       text,
       text,
       width: nextWidth,
       width: nextWidth,
       height: nextHeight,
       height: nextHeight,
+      baseline: nextBaseLine,
     });
     });
 
 
     if (!isArrowElement(container)) {
     if (!isArrowElement(container)) {
@@ -285,8 +290,8 @@ export const measureText = (
   const fontSize = parseFloat(font);
   const fontSize = parseFloat(font);
   const height = getTextHeight(text, fontSize, lineHeight);
   const height = getTextHeight(text, fontSize, lineHeight);
   const width = getTextWidth(text, font);
   const width = getTextWidth(text, font);
-
-  return { width, height };
+  const baseline = measureBaseline(text, font, lineHeight);
+  return { width, height, baseline };
 };
 };
 
 
 export const measureBaseline = (
 export const measureBaseline = (
@@ -300,7 +305,7 @@ export const measureBaseline = (
   container.style.whiteSpace = "pre";
   container.style.whiteSpace = "pre";
   container.style.font = font;
   container.style.font = font;
   container.style.minHeight = "1em";
   container.style.minHeight = "1em";
-
+  console.log("HEYYY you are here!!");
   if (wrapInContainer) {
   if (wrapInContainer) {
     container.style.overflow = "hidden";
     container.style.overflow = "hidden";
     container.style.wordBreak = "break-word";
     container.style.wordBreak = "break-word";

+ 6 - 5
src/element/textWysiwyg.tsx

@@ -34,7 +34,6 @@ import {
   wrapText,
   wrapText,
   getMaxContainerHeight,
   getMaxContainerHeight,
   getMaxContainerWidth,
   getMaxContainerWidth,
-  measureBaseline,
   computeContainerDimensionForBoundText,
   computeContainerDimensionForBoundText,
 } from "./textElement";
 } from "./textElement";
 import {
 import {
@@ -273,7 +272,10 @@ export const textWysiwyg = ({
         textElementWidth += 0.5;
         textElementWidth += 0.5;
       }
       }
 
 
-      const top = viewportY;
+      let verticalOffset = 0;
+      if (element.verticalAlign === VERTICAL_ALIGN.BOTTOM) {
+        //verticalOffset = getBoundTextElementOffset(element);
+      }
       // Make sure text editor height doesn't go beyond viewport
       // Make sure text editor height doesn't go beyond viewport
       const editorMaxHeight =
       const editorMaxHeight =
         (appState.height - viewportY) / appState.zoom.value;
         (appState.height - viewportY) / appState.zoom.value;
@@ -284,7 +286,7 @@ export const textWysiwyg = ({
         width: `${textElementWidth}px`,
         width: `${textElementWidth}px`,
         height: `${textElementHeight}px`,
         height: `${textElementHeight}px`,
         left: `${viewportX}px`,
         left: `${viewportX}px`,
-        top: `${top}px`,
+        top: `${viewportY + verticalOffset}px`,
         transform: getTransform(
         transform: getTransform(
           textElementWidth,
           textElementWidth,
           textElementHeight,
           textElementHeight,
@@ -295,8 +297,7 @@ export const textWysiwyg = ({
         ),
         ),
         textAlign,
         textAlign,
         verticalAlign,
         verticalAlign,
-        // color: updatedTextElement.strokeColor,
-        color: "red",
+        color: updatedTextElement.strokeColor,
         opacity: updatedTextElement.opacity / 100,
         opacity: updatedTextElement.opacity / 100,
         filter: "var(--theme-filter)",
         filter: "var(--theme-filter)",
         maxHeight: `${editorMaxHeight}px`,
         maxHeight: `${editorMaxHeight}px`,

+ 1 - 0
src/element/types.ts

@@ -131,6 +131,7 @@ export type ExcalidrawTextElement = _ExcalidrawElementBase &
     fontSize: number;
     fontSize: number;
     fontFamily: FontFamilyValues;
     fontFamily: FontFamilyValues;
     text: string;
     text: string;
+    baseline: number;
     textAlign: TextAlign;
     textAlign: TextAlign;
     verticalAlign: VerticalAlign;
     verticalAlign: VerticalAlign;
     containerId: ExcalidrawGenericElement["id"] | null;
     containerId: ExcalidrawGenericElement["id"] | null;

+ 1 - 40
src/renderer/renderElement.ts

@@ -46,7 +46,6 @@ import {
   getLineHeightInPx,
   getLineHeightInPx,
   getMaxContainerHeight,
   getMaxContainerHeight,
   getMaxContainerWidth,
   getMaxContainerWidth,
-  measureBaseline,
 } from "../element/textElement";
 } from "../element/textElement";
 import { LinearElementEditor } from "../element/linearElementEditor";
 import { LinearElementEditor } from "../element/linearElementEditor";
 
 
@@ -201,17 +200,6 @@ const drawImagePlaceholder = (
     size,
     size,
   );
   );
 };
 };
-//@ts-ignore
-const drawLine = (x, y, width, height, stroke, context) => {
-  context.lineWidth = "2";
-  context.strokeStyle = stroke;
-  context.beginPath();
-  context.moveTo(x, y);
-  context.lineTo(x + width, y);
-  context.closePath();
-  context.stroke();
-};
-
 const drawElementOnCanvas = (
 const drawElementOnCanvas = (
   element: NonDeletedExcalidrawElement,
   element: NonDeletedExcalidrawElement,
   rc: RoughCanvas,
   rc: RoughCanvas,
@@ -288,33 +276,6 @@ const drawElementOnCanvas = (
         context.save();
         context.save();
         context.font = getFontString(element);
         context.font = getFontString(element);
 
 
-        // drawLine(0, 0, metrics.width, element.height, "green", context);
-
-        // drawLine(
-        //   0,
-        //   -metrics.actualBoundingBoxAscent,
-        //   metrics.width,
-        //   element.height,
-        //   "magenta",
-        //   context,
-        // );
-
-        // drawLine(
-        //   0,
-        //   metrics.actualBoundingBoxDescent,
-        //   metrics.width,
-        //   element.height,
-        //   "magenta",
-        //   context,
-        // );
-        const container = getContainerElement(element);
-        const baseline = measureBaseline(
-          element.text,
-          getFontString(element),
-          element.lineHeight,
-          !!container,
-        );
-
         context.fillStyle = element.strokeColor;
         context.fillStyle = element.strokeColor;
         context.textAlign = element.textAlign as CanvasTextAlign;
         context.textAlign = element.textAlign as CanvasTextAlign;
 
 
@@ -331,7 +292,7 @@ const drawElementOnCanvas = (
           element.fontSize,
           element.fontSize,
           element.lineHeight,
           element.lineHeight,
         );
         );
-        const verticalOffset = element.height - baseline;
+        const verticalOffset = element.height - element.baseline;
 
 
         for (let index = 0; index < lines.length; index++) {
         for (let index = 0; index < lines.length; index++) {
           context.fillText(
           context.fillText(