Load all font weight/style variants needed by pasted text nodes

loadFontsForNodes only loaded the Regular style for each family.
Now collects fontWeight and italic from each text node and style
run, converts to style name via weightToStyle, and loads each
variant separately (e.g. Medium, Bold, Bold Italic).
This commit is contained in:
Danila Poyarkov 2026-03-04 00:53:36 +03:00
parent 26ed064b07
commit 8a13c5ffb6

View file

@ -1,3 +1,4 @@
import { weightToStyle } from '@open-pencil/core'
import { shallowReactive, shallowRef, computed, watch } from 'vue' import { shallowReactive, shallowRef, computed, watch } from 'vue'
import { import {
@ -22,13 +23,13 @@ import {
prefetchFigmaSchema prefetchFigmaSchema
} from '@/engine/clipboard' } from '@/engine/clipboard'
import { exportFigFile } from '@/engine/fig-export' import { exportFigFile } from '@/engine/fig-export'
import { loadFont } from '@/engine/fonts'
import { computeLayout, computeAllLayouts, setTextMeasurer } from '@/engine/layout' import { computeLayout, computeAllLayouts, setTextMeasurer } from '@/engine/layout'
import { renderNodesToImage } from '@/engine/render-image' import { renderNodesToImage } from '@/engine/render-image'
import { SceneGraph } from '@/engine/scene-graph' import { SceneGraph } from '@/engine/scene-graph'
import { TextEditor } from '@/engine/text-editor' import { TextEditor } from '@/engine/text-editor'
import { UndoManager } from '@/engine/undo' import { UndoManager } from '@/engine/undo'
import { computeVectorBounds } from '@/engine/vector' import { computeVectorBounds } from '@/engine/vector'
import { loadFont } from '@/engine/fonts'
import { readFigFile } from '@/kiwi/fig-file' import { readFigFile } from '@/kiwi/fig-file'
import type { ExportFormat } from '@/engine/render-image' import type { ExportFormat } from '@/engine/render-image'
@ -1696,22 +1697,30 @@ export function createEditorStore() {
} }
function loadFontsForNodes(nodeIds: string[]) { function loadFontsForNodes(nodeIds: string[]) {
const families = new Set<string>() const fontKeys = new Set<string>()
const collect = (id: string) => { const collect = (id: string) => {
const node = graph.getNode(id) const node = graph.getNode(id)
if (!node) return if (!node) return
if (node.type === 'TEXT') { if (node.type === 'TEXT') {
families.add(node.fontFamily || DEFAULT_FONT_FAMILY) const family = node.fontFamily || DEFAULT_FONT_FAMILY
fontKeys.add(`${family}\0${weightToStyle(node.fontWeight || 400, node.italic)}`)
for (const run of node.styleRuns) { for (const run of node.styleRuns) {
if (run.style.fontFamily) families.add(run.style.fontFamily) const f = run.style.fontFamily ?? family
const w = run.style.fontWeight ?? node.fontWeight ?? 400
const i = run.style.italic ?? node.italic
fontKeys.add(`${f}\0${weightToStyle(w, i)}`)
} }
} }
for (const childId of node.childIds) collect(childId) for (const childId of node.childIds) collect(childId)
} }
for (const id of nodeIds) collect(id) for (const id of nodeIds) collect(id)
families.delete(DEFAULT_FONT_FAMILY)
if (families.size === 0) return const toLoad = [...fontKeys]
const promises = [...families].map((f) => loadFont(f)) .map((k) => k.split('\0') as [string, string])
.filter(([family]) => family !== DEFAULT_FONT_FAMILY)
if (toLoad.length === 0) return
const promises = toLoad.map(([family, style]) => loadFont(family, style))
Promise.all(promises).then(() => { Promise.all(promises).then(() => {
computeAllLayouts(graph) computeAllLayouts(graph)
requestRender() requestRender()