浏览代码

Retrieve first font url when not inlining font

Marcel Mraz 1 年之前
父节点
当前提交
391497916f
共有 2 个文件被更改,包括 24 次插入7 次删除
  1. 1 0
      packages/excalidraw/hooks/useLibraryItemSvg.ts
  2. 23 7
      packages/excalidraw/scene/export.ts

+ 1 - 0
packages/excalidraw/hooks/useLibraryItemSvg.ts

@@ -41,6 +41,7 @@ export const useLibraryItemSvg = (
           // When there is no svg in cache export it and save to cache
           (async () => {
             const exportedSvg = await exportLibraryItemToSvg(elements);
+            // TODO: should likely be removed for custom fonts
             exportedSvg.querySelector(".style-fonts")?.remove();
 
             if (exportedSvg) {

+ 23 - 7
packages/excalidraw/scene/export.ts

@@ -39,6 +39,7 @@ import type { RenderableElementsMap } from "./types";
 import { syncInvalidIndices } from "../fractionalIndex";
 import { renderStaticScene } from "../renderer/staticScene";
 import { Fonts } from "../fonts";
+import type { Font } from "../fonts/ExcalidrawFont";
 
 const SVG_EXPORT_TAG = `<!-- svg-source:excalidraw -->`;
 
@@ -355,7 +356,8 @@ export const exportToSvg = async (
         </clipPath>`;
   }
 
-  const fontFaces = opts?.skipInliningFonts ? [] : await getFontFaces(elements);
+  const shouldInlineFonts = !opts?.skipInliningFonts;
+  const fontFaces = await getFontFaces(elements, shouldInlineFonts);
 
   svgRoot.innerHTML = `
   ${SVG_EXPORT_TAG}
@@ -436,10 +438,13 @@ export const getExportSize = (
 
 const getFontFaces = async (
   elements: readonly ExcalidrawElement[],
+  shouldInlineFonts: boolean,
 ): Promise<string[]> => {
   const fontFamilies = new Set<number>();
   const codePoints = new Set<number>();
 
+  let getSource: (font: Font) => string | Promise<string>;
+
   for (const element of elements) {
     if (!isTextElement(element)) {
       continue;
@@ -447,15 +452,26 @@ const getFontFaces = async (
 
     fontFamilies.add(element.fontFamily);
 
-    for (const codePoint of Array.from(element.originalText, (u) =>
-      u.codePointAt(0),
-    )) {
-      if (codePoint) {
-        codePoints.add(codePoint);
+    // gather unique codepoints only when inlining fonts
+    if (shouldInlineFonts) {
+      for (const codePoint of Array.from(element.originalText, (u) =>
+        u.codePointAt(0),
+      )) {
+        if (codePoint) {
+          codePoints.add(codePoint);
+        }
       }
     }
   }
 
+  if (shouldInlineFonts) {
+    // retrieve font source as dataurl based on the used codepoints
+    getSource = (font: Font) => font.getContent(codePoints);
+  } else {
+    // retrieve font source as a url otherwise
+    getSource = (font: Font) => font.urls[0].toString();
+  }
+
   const fontFaces = await Promise.all(
     Array.from(fontFamilies).map(async (x) => {
       const { fonts, metadata } = Fonts.registered.get(x) ?? {};
@@ -477,7 +493,7 @@ const getFontFaces = async (
         fonts.map(
           async (font) => `@font-face {
         font-family: ${font.fontFace.family};
-        src: url(${await font.getContent(codePoints)});
+        src: url(${await getSource(font)});
           }`,
         ),
       );