package qslcard import ( "embed" "os" ) //go:embed assets/fonts/*.ttf assets/fonts/OFL-*.txt var fontsFS embed.FS // Font is one face the designer offers. Data is the raw TTF; the frontend // registers it as a base64 @font-face (and inlines it into the SVG before // rasterization so canvas export matches the live preview). type Font struct { Family string `json:"family"` Kind string `json:"kind"` // "display" | "script" | "system" Variable bool `json:"variable"` Data []byte `json:"data"` } // fontFiles lists the embedded faces. All OFL-licensed (license texts ship // alongside in assets/fonts). var fontFiles = []struct { family, kind, file string variable bool }{ {"Archivo Black", "display", "ArchivoBlack-Regular.ttf", false}, {"Lilita One", "display", "LilitaOne-Regular.ttf", false}, {"Baloo 2", "display", "Baloo2-Variable.ttf", true}, {"Oswald", "display", "Oswald-Variable.ttf", true}, {"Great Vibes", "script", "GreatVibes-Regular.ttf", false}, {"Allura", "script", "Allura-Regular.ttf", false}, } // cooperBlackPath is where MS Office installs Cooper Black; offered as a // bonus display face when present (system font, not embedded). const cooperBlackPath = `C:\Windows\Fonts\COOPBL.TTF` // Fonts returns every available face: the embedded OFL set, plus Cooper // Black when the machine has it. func Fonts() ([]Font, error) { out := make([]Font, 0, len(fontFiles)+1) for _, f := range fontFiles { data, err := fontsFS.ReadFile("assets/fonts/" + f.file) if err != nil { return nil, err // embedded read can only fail on a packaging bug } out = append(out, Font{Family: f.family, Kind: f.kind, Variable: f.variable, Data: data}) } if data, err := os.ReadFile(cooperBlackPath); err == nil { out = append(out, Font{Family: "Cooper Black", Kind: "system", Data: data}) } return out, nil }