mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-05-03 10:00:07 -04:00
feat: introduce font picker (#8012)
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
This commit is contained in:
parent
4c5408263c
commit
62228e0bbb
120 changed files with 3390 additions and 1106 deletions
|
@ -13,8 +13,8 @@ import { arrayToMap, distance, getFontString, toBrandedType } from "../utils";
|
|||
import type { AppState, BinaryFiles } from "../types";
|
||||
import {
|
||||
DEFAULT_EXPORT_PADDING,
|
||||
FONT_FAMILY,
|
||||
FRAME_STYLE,
|
||||
FONT_FAMILY,
|
||||
SVG_NS,
|
||||
THEME,
|
||||
THEME_FILTER,
|
||||
|
@ -32,12 +32,18 @@ import {
|
|||
getRootElements,
|
||||
} from "../frame";
|
||||
import { newTextElement } from "../element";
|
||||
import type { Mutable } from "../utility-types";
|
||||
import { type Mutable } from "../utility-types";
|
||||
import { newElementWith } from "../element/mutateElement";
|
||||
import { isFrameElement, isFrameLikeElement } from "../element/typeChecks";
|
||||
import {
|
||||
isFrameElement,
|
||||
isFrameLikeElement,
|
||||
isTextElement,
|
||||
} from "../element/typeChecks";
|
||||
import type { RenderableElementsMap } from "./types";
|
||||
import { syncInvalidIndices } from "../fractionalIndex";
|
||||
import { renderStaticScene } from "../renderer/staticScene";
|
||||
import { Fonts } from "../fonts";
|
||||
import { LOCAL_FONT_PROTOCOL } from "../fonts/metadata";
|
||||
|
||||
const SVG_EXPORT_TAG = `<!-- svg-source:excalidraw -->`;
|
||||
|
||||
|
@ -95,7 +101,7 @@ const addFrameLabelsAsTextElements = (
|
|||
let textElement: Mutable<ExcalidrawTextElement> = newTextElement({
|
||||
x: element.x,
|
||||
y: element.y - FRAME_STYLE.nameOffsetY,
|
||||
fontFamily: FONT_FAMILY.Assistant,
|
||||
fontFamily: FONT_FAMILY.Helvetica,
|
||||
fontSize: FRAME_STYLE.nameFontSize,
|
||||
lineHeight:
|
||||
FRAME_STYLE.nameLineHeight as ExcalidrawTextElement["lineHeight"],
|
||||
|
@ -269,6 +275,7 @@ export const exportToSvg = async (
|
|||
*/
|
||||
renderEmbeddables?: boolean;
|
||||
exportingFrame?: ExcalidrawFrameLikeElement | null;
|
||||
skipInliningFonts?: true;
|
||||
},
|
||||
): Promise<SVGSVGElement> => {
|
||||
const frameRendering = getFrameRenderingConfig(
|
||||
|
@ -333,21 +340,6 @@ export const exportToSvg = async (
|
|||
svgRoot.setAttribute("filter", THEME_FILTER);
|
||||
}
|
||||
|
||||
let assetPath = "https://excalidraw.com/";
|
||||
// Asset path needs to be determined only when using package
|
||||
if (import.meta.env.VITE_IS_EXCALIDRAW_NPM_PACKAGE) {
|
||||
assetPath =
|
||||
window.EXCALIDRAW_ASSET_PATH ||
|
||||
`https://unpkg.com/${import.meta.env.VITE_PKG_NAME}@${
|
||||
import.meta.env.VITE_PKG_VERSION
|
||||
}`;
|
||||
|
||||
if (assetPath?.startsWith("/")) {
|
||||
assetPath = assetPath.replace("/", `${window.location.origin}/`);
|
||||
}
|
||||
assetPath = `${assetPath}/dist/excalidraw-assets/`;
|
||||
}
|
||||
|
||||
const offsetX = -minX + exportPadding;
|
||||
const offsetY = -minY + exportPadding;
|
||||
|
||||
|
@ -371,23 +363,57 @@ export const exportToSvg = async (
|
|||
</clipPath>`;
|
||||
}
|
||||
|
||||
const fontFamilies = elements.reduce((acc, element) => {
|
||||
if (isTextElement(element)) {
|
||||
acc.add(element.fontFamily);
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, new Set<number>());
|
||||
|
||||
const fontFaces = opts?.skipInliningFonts
|
||||
? []
|
||||
: await Promise.all(
|
||||
Array.from(fontFamilies).map(async (x) => {
|
||||
const { fontFaces } = Fonts.registered.get(x) ?? {};
|
||||
|
||||
if (!Array.isArray(fontFaces)) {
|
||||
console.error(
|
||||
`Couldn't find registered font-faces for font-family "${x}"`,
|
||||
Fonts.registered,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
return Promise.all(
|
||||
fontFaces
|
||||
.filter((font) => font.url.protocol !== LOCAL_FONT_PROTOCOL)
|
||||
.map(async (font) => {
|
||||
try {
|
||||
const content = await font.getContent();
|
||||
|
||||
return `@font-face {
|
||||
font-family: ${font.fontFace.family};
|
||||
src: url(${content});
|
||||
}`;
|
||||
} catch (e) {
|
||||
console.error(
|
||||
`Skipped inlining font with URL "${font.url.toString()}"`,
|
||||
e,
|
||||
);
|
||||
return "";
|
||||
}
|
||||
}),
|
||||
);
|
||||
}),
|
||||
);
|
||||
|
||||
svgRoot.innerHTML = `
|
||||
${SVG_EXPORT_TAG}
|
||||
${metadata}
|
||||
<defs>
|
||||
<style class="style-fonts">
|
||||
@font-face {
|
||||
font-family: "Virgil";
|
||||
src: url("${assetPath}Virgil.woff2");
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Cascadia";
|
||||
src: url("${assetPath}Cascadia.woff2");
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Assistant";
|
||||
src: url("${assetPath}Assistant-Regular.woff2");
|
||||
}
|
||||
${fontFaces.flat().filter(Boolean).join("\n")}
|
||||
</style>
|
||||
${exportingFrameClipPath}
|
||||
</defs>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue