diff --git a/src/utils/svgDownload.ts b/src/utils/svgDownload.ts
index fe12f34..b8c68bc 100644
--- a/src/utils/svgDownload.ts
+++ b/src/utils/svgDownload.ts
@@ -3,6 +3,55 @@ const SVG_NS = "http://www.w3.org/2000/svg"
const TABLER_DOWNLOAD_ICON = ``
+const stripQuotes = (s: string): string => s.trim().replace(/^["']|["']$/g, "")
+
+const collectFontFamilies = (svg: SVGSVGElement): Set => {
+ const families = new Set()
+ const collect = (raw: string | null) => {
+ if (!raw) return
+ raw.split(",").forEach((part) => {
+ const cleaned = stripQuotes(part)
+ if (cleaned) families.add(cleaned)
+ })
+ }
+ collect(svg.getAttribute("font-family"))
+ svg.querySelectorAll("[font-family]").forEach((el) =>
+ collect(el.getAttribute("font-family"))
+ )
+ return families
+}
+
+const isFontFaceRule = (rule: CSSRule): boolean => {
+ if (typeof CSSFontFaceRule !== "undefined" && rule instanceof CSSFontFaceRule)
+ return true
+ return rule.cssText.trimStart().startsWith("@font-face")
+}
+
+const collectFontFaceCss = (families: Set): string => {
+ if (families.size === 0) return ""
+ const parts: string[] = []
+ for (const sheet of Array.from(document.styleSheets)) {
+ let rules: CSSRuleList | null = null
+ try {
+ rules = sheet.cssRules
+ } catch {
+ continue
+ }
+ if (!rules) continue
+ for (const rule of Array.from(rules)) {
+ if (!isFontFaceRule(rule)) continue
+ const styleRule = rule as CSSFontFaceRule
+ const family = stripQuotes(
+ styleRule.style?.getPropertyValue("font-family") ?? ""
+ )
+ if (family && families.has(family)) {
+ parts.push(rule.cssText)
+ }
+ }
+ }
+ return parts.join("\n")
+}
+
const getSvgPixelSize = (svg: SVGSVGElement): { width: number; height: number } => {
const viewBox = svg.viewBox?.baseVal
if (viewBox && viewBox.width > 0 && viewBox.height > 0) {
@@ -36,6 +85,14 @@ const buildExportableSvgString = (svg: SVGSVGElement): string => {
bg.setAttribute("fill", "#ffffff")
clone.insertBefore(bg, clone.firstChild)
+ const fontFaceCss = collectFontFaceCss(collectFontFamilies(svg))
+ if (fontFaceCss) {
+ const style = document.createElementNS(SVG_NS, "style")
+ style.setAttribute("type", "text/css")
+ style.textContent = fontFaceCss
+ clone.insertBefore(style, clone.firstChild)
+ }
+
return new XMLSerializer().serializeToString(clone)
}
@@ -67,6 +124,9 @@ const downloadAsPng = async (
const svgUrl = URL.createObjectURL(svgBlob)
try {
+ if (document.fonts?.ready) {
+ await document.fonts.ready
+ }
const img = new Image()
img.crossOrigin = "anonymous"
await new Promise((resolve, reject) => {