d2/d2renderers/d2fonts/d2fonts.go

237 lines
4.9 KiB
Go
Raw Normal View History

// d2fonts holds fonts for renderings
// TODO write a script to do this as part of CI
2022-12-21 07:43:45 +00:00
// Currently using an online converter: https://dopiaza.org/tools/datauri/index.php
package d2fonts
import (
"embed"
2023-03-24 22:04:35 +00:00
"encoding/base64"
"fmt"
"strings"
2023-03-24 22:04:35 +00:00
fontlib "oss.terrastruct.com/d2/lib/font"
)
2022-12-21 07:43:45 +00:00
type FontFamily string
type FontStyle string
type Font struct {
Family FontFamily
Style FontStyle
Size int
}
func (f FontFamily) Font(size int, style FontStyle) Font {
return Font{
Family: f,
Style: style,
Size: size,
}
}
2023-03-27 21:46:03 +00:00
func (f Font) GetEncodedSubset(cutset string) string {
// gofpdf subset only accepts .ttf fonts
fontBuf := FontFaces[f]
2023-03-28 02:26:49 +00:00
fontBuf = fontlib.CutFont(fontBuf, cutset)
2023-03-27 21:46:03 +00:00
2023-03-27 22:38:53 +00:00
fontBuf, err := fontlib.Sfnt2Woff(fontBuf)
2023-03-25 02:50:16 +00:00
if err != nil {
// If subset fails, return full encoding
2023-03-27 21:46:03 +00:00
return FontEncodings[f]
2023-03-25 02:50:16 +00:00
}
2023-03-27 21:46:03 +00:00
2023-03-27 22:38:53 +00:00
return fmt.Sprintf("data:application/font-woff;base64,%v", base64.StdEncoding.EncodeToString(fontBuf))
2023-03-25 02:50:16 +00:00
}
const (
FONT_SIZE_XS = 13
FONT_SIZE_S = 14
FONT_SIZE_M = 16
FONT_SIZE_L = 20
FONT_SIZE_XL = 24
FONT_SIZE_XXL = 28
FONT_SIZE_XXXL = 32
FONT_STYLE_REGULAR FontStyle = "regular"
FONT_STYLE_BOLD FontStyle = "bold"
FONT_STYLE_ITALIC FontStyle = "italic"
2022-12-21 07:43:45 +00:00
SourceSansPro FontFamily = "SourceSansPro"
SourceCodePro FontFamily = "SourceCodePro"
HandDrawn FontFamily = "HandDrawn"
)
var FontSizes = []int{
FONT_SIZE_XS,
FONT_SIZE_S,
FONT_SIZE_M,
FONT_SIZE_L,
FONT_SIZE_XL,
FONT_SIZE_XXL,
FONT_SIZE_XXXL,
}
var FontStyles = []FontStyle{
FONT_STYLE_REGULAR,
FONT_STYLE_BOLD,
FONT_STYLE_ITALIC,
}
var FontFamilies = []FontFamily{
SourceSansPro,
SourceCodePro,
2022-12-21 07:43:45 +00:00
HandDrawn,
}
//go:embed encoded/SourceSansPro-Regular.txt
var sourceSansProRegularBase64 string
//go:embed encoded/SourceSansPro-Bold.txt
var sourceSansProBoldBase64 string
//go:embed encoded/SourceSansPro-Italic.txt
var sourceSansProItalicBase64 string
//go:embed encoded/SourceCodePro-Regular.txt
var sourceCodeProRegularBase64 string
d2renderers: d2fonts: add bold + italic styles for Source Code Pro 👋 I've been playing around with changing the entire font of a diagram to something fixed-width, starting by hand-editing `main.go` I noticed that if I switched over the family to Source Code Pro, d2 crashed with the following stack: ``` [23:38:30] info: compiling GetUniqueColumnName-fix.d2... panic: runtime error: invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation code=0x1 addr=0x1c4 pc=0x16b562c] goroutine 43 [running]: github.com/golang/freetype/truetype.(*Font).Bounds(0xc000669670?, 0x0?) /Users/kevin/dev/go/pkg/mod/github.com/golang/freetype@v0.0.0-20170609003504-e2365dfdc4a0/truetype/truetype.go:378 +0xc github.com/golang/freetype/truetype.NewFace(0x0, 0xc0003276c0) /Users/kevin/dev/go/pkg/mod/github.com/golang/freetype@v0.0.0-20170609003504-e2365dfdc4a0/truetype/face.go:199 +0x325 oss.terrastruct.com/d2/lib/textmeasure.(*Ruler).addFontSize(0xc00037c000, {{0x1bb9a34, 0xd}, {0x1b82732, 0x4}, 0x1f}) /Users/kevin/dev/d2/lib/textmeasure/textmeasure.go:141 +0x112 oss.terrastruct.com/d2/lib/textmeasure.(*Ruler).MeasurePrecise(0xc00037c000, {{0x1bb9a34, 0xd}, {0x1b82732, 0x4}, 0x1f}, {0xc000582100, 0x1f}) /Users/kevin/dev/d2/lib/textmeasure/textmeasure.go:157 +0xde oss.terrastruct.com/d2/lib/textmeasure.(*Ruler).Measure(...) /Users/kevin/dev/d2/lib/textmeasure/textmeasure.go:151 oss.terrastruct.com/d2/d2graph.GetTextDimensions({0x0, 0x0, 0xc000657860?}, 0xc00037c000, 0xc000620280, 0xc000092020) ``` Which I tracked down to these missing styles, which appear to matter even if they aren't used. I acquired the `ttf` files from https://fonts.google.com/specimen/Source+Code+Pro I created the encoded fonts on my Mac with: ``` base64 -i SourceCodePro-Italic.ttf -o ../encoded/SourceCodePro-Italic.txt ``` Hopefully this is correct! Open to all feedback, especially since I think this is the first change I've ever made to a go program :) Signed-off-by: Kevin David <kevin-david@github.com>
2023-01-23 05:13:08 +00:00
//go:embed encoded/SourceCodePro-Bold.txt
var sourceCodeProBoldBase64 string
//go:embed encoded/SourceCodePro-Italic.txt
var sourceCodeProItalicBase64 string
2022-12-21 07:43:45 +00:00
//go:embed encoded/ArchitectsDaughter-Regular.txt
var architectsDaughterRegularBase64 string
//go:embed encoded/FuzzyBubbles-Bold.txt
var fuzzyBubblesBoldBase64 string
//go:embed ttf/*
var fontFacesFS embed.FS
var FontEncodings map[Font]string
var FontFaces map[Font][]byte
func init() {
FontEncodings = map[Font]string{
{
Family: SourceSansPro,
Style: FONT_STYLE_REGULAR,
}: sourceSansProRegularBase64,
{
Family: SourceSansPro,
Style: FONT_STYLE_BOLD,
}: sourceSansProBoldBase64,
{
Family: SourceSansPro,
Style: FONT_STYLE_ITALIC,
}: sourceSansProItalicBase64,
{
Family: SourceCodePro,
Style: FONT_STYLE_REGULAR,
}: sourceCodeProRegularBase64,
d2renderers: d2fonts: add bold + italic styles for Source Code Pro 👋 I've been playing around with changing the entire font of a diagram to something fixed-width, starting by hand-editing `main.go` I noticed that if I switched over the family to Source Code Pro, d2 crashed with the following stack: ``` [23:38:30] info: compiling GetUniqueColumnName-fix.d2... panic: runtime error: invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation code=0x1 addr=0x1c4 pc=0x16b562c] goroutine 43 [running]: github.com/golang/freetype/truetype.(*Font).Bounds(0xc000669670?, 0x0?) /Users/kevin/dev/go/pkg/mod/github.com/golang/freetype@v0.0.0-20170609003504-e2365dfdc4a0/truetype/truetype.go:378 +0xc github.com/golang/freetype/truetype.NewFace(0x0, 0xc0003276c0) /Users/kevin/dev/go/pkg/mod/github.com/golang/freetype@v0.0.0-20170609003504-e2365dfdc4a0/truetype/face.go:199 +0x325 oss.terrastruct.com/d2/lib/textmeasure.(*Ruler).addFontSize(0xc00037c000, {{0x1bb9a34, 0xd}, {0x1b82732, 0x4}, 0x1f}) /Users/kevin/dev/d2/lib/textmeasure/textmeasure.go:141 +0x112 oss.terrastruct.com/d2/lib/textmeasure.(*Ruler).MeasurePrecise(0xc00037c000, {{0x1bb9a34, 0xd}, {0x1b82732, 0x4}, 0x1f}, {0xc000582100, 0x1f}) /Users/kevin/dev/d2/lib/textmeasure/textmeasure.go:157 +0xde oss.terrastruct.com/d2/lib/textmeasure.(*Ruler).Measure(...) /Users/kevin/dev/d2/lib/textmeasure/textmeasure.go:151 oss.terrastruct.com/d2/d2graph.GetTextDimensions({0x0, 0x0, 0xc000657860?}, 0xc00037c000, 0xc000620280, 0xc000092020) ``` Which I tracked down to these missing styles, which appear to matter even if they aren't used. I acquired the `ttf` files from https://fonts.google.com/specimen/Source+Code+Pro I created the encoded fonts on my Mac with: ``` base64 -i SourceCodePro-Italic.ttf -o ../encoded/SourceCodePro-Italic.txt ``` Hopefully this is correct! Open to all feedback, especially since I think this is the first change I've ever made to a go program :) Signed-off-by: Kevin David <kevin-david@github.com>
2023-01-23 05:13:08 +00:00
{
Family: SourceCodePro,
Style: FONT_STYLE_BOLD,
}: sourceCodeProBoldBase64,
{
Family: SourceCodePro,
Style: FONT_STYLE_ITALIC,
}: sourceCodeProItalicBase64,
2022-12-21 07:43:45 +00:00
{
Family: HandDrawn,
Style: FONT_STYLE_REGULAR,
}: architectsDaughterRegularBase64,
{
Family: HandDrawn,
Style: FONT_STYLE_ITALIC,
// This font has no italic, so just reuse regular
}: architectsDaughterRegularBase64,
{
Family: HandDrawn,
Style: FONT_STYLE_BOLD,
}: fuzzyBubblesBoldBase64,
}
for k, v := range FontEncodings {
FontEncodings[k] = strings.TrimSuffix(v, "\n")
}
FontFaces = map[Font][]byte{}
b, err := fontFacesFS.ReadFile("ttf/SourceSansPro-Regular.ttf")
if err != nil {
panic(err)
}
FontFaces[Font{
Family: SourceSansPro,
Style: FONT_STYLE_REGULAR,
}] = b
b, err = fontFacesFS.ReadFile("ttf/SourceCodePro-Regular.ttf")
if err != nil {
panic(err)
}
FontFaces[Font{
Family: SourceCodePro,
Style: FONT_STYLE_REGULAR,
}] = b
d2renderers: d2fonts: add bold + italic styles for Source Code Pro 👋 I've been playing around with changing the entire font of a diagram to something fixed-width, starting by hand-editing `main.go` I noticed that if I switched over the family to Source Code Pro, d2 crashed with the following stack: ``` [23:38:30] info: compiling GetUniqueColumnName-fix.d2... panic: runtime error: invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation code=0x1 addr=0x1c4 pc=0x16b562c] goroutine 43 [running]: github.com/golang/freetype/truetype.(*Font).Bounds(0xc000669670?, 0x0?) /Users/kevin/dev/go/pkg/mod/github.com/golang/freetype@v0.0.0-20170609003504-e2365dfdc4a0/truetype/truetype.go:378 +0xc github.com/golang/freetype/truetype.NewFace(0x0, 0xc0003276c0) /Users/kevin/dev/go/pkg/mod/github.com/golang/freetype@v0.0.0-20170609003504-e2365dfdc4a0/truetype/face.go:199 +0x325 oss.terrastruct.com/d2/lib/textmeasure.(*Ruler).addFontSize(0xc00037c000, {{0x1bb9a34, 0xd}, {0x1b82732, 0x4}, 0x1f}) /Users/kevin/dev/d2/lib/textmeasure/textmeasure.go:141 +0x112 oss.terrastruct.com/d2/lib/textmeasure.(*Ruler).MeasurePrecise(0xc00037c000, {{0x1bb9a34, 0xd}, {0x1b82732, 0x4}, 0x1f}, {0xc000582100, 0x1f}) /Users/kevin/dev/d2/lib/textmeasure/textmeasure.go:157 +0xde oss.terrastruct.com/d2/lib/textmeasure.(*Ruler).Measure(...) /Users/kevin/dev/d2/lib/textmeasure/textmeasure.go:151 oss.terrastruct.com/d2/d2graph.GetTextDimensions({0x0, 0x0, 0xc000657860?}, 0xc00037c000, 0xc000620280, 0xc000092020) ``` Which I tracked down to these missing styles, which appear to matter even if they aren't used. I acquired the `ttf` files from https://fonts.google.com/specimen/Source+Code+Pro I created the encoded fonts on my Mac with: ``` base64 -i SourceCodePro-Italic.ttf -o ../encoded/SourceCodePro-Italic.txt ``` Hopefully this is correct! Open to all feedback, especially since I think this is the first change I've ever made to a go program :) Signed-off-by: Kevin David <kevin-david@github.com>
2023-01-23 05:13:08 +00:00
b, err = fontFacesFS.ReadFile("ttf/SourceCodePro-Bold.ttf")
if err != nil {
panic(err)
}
FontFaces[Font{
Family: SourceCodePro,
Style: FONT_STYLE_BOLD,
}] = b
b, err = fontFacesFS.ReadFile("ttf/SourceCodePro-Italic.ttf")
if err != nil {
panic(err)
}
FontFaces[Font{
Family: SourceCodePro,
Style: FONT_STYLE_ITALIC,
}] = b
b, err = fontFacesFS.ReadFile("ttf/SourceSansPro-Bold.ttf")
if err != nil {
panic(err)
}
FontFaces[Font{
Family: SourceSansPro,
Style: FONT_STYLE_BOLD,
}] = b
b, err = fontFacesFS.ReadFile("ttf/SourceSansPro-Italic.ttf")
if err != nil {
panic(err)
}
FontFaces[Font{
Family: SourceSansPro,
Style: FONT_STYLE_ITALIC,
}] = b
2022-12-21 07:43:45 +00:00
b, err = fontFacesFS.ReadFile("ttf/ArchitectsDaughter-Regular.ttf")
if err != nil {
panic(err)
}
FontFaces[Font{
Family: HandDrawn,
Style: FONT_STYLE_REGULAR,
}] = b
FontFaces[Font{
Family: HandDrawn,
Style: FONT_STYLE_ITALIC,
}] = b
b, err = fontFacesFS.ReadFile("ttf/FuzzyBubbles-Bold.ttf")
if err != nil {
panic(err)
}
FontFaces[Font{
Family: HandDrawn,
Style: FONT_STYLE_BOLD,
}] = b
}
2023-03-07 06:21:23 +00:00
var D2_FONT_TO_FAMILY = map[string]FontFamily{
"default": SourceSansPro,
"mono": SourceCodePro,
}