diff --git a/d2renderers/d2fonts/d2fonts.go b/d2renderers/d2fonts/d2fonts.go index 85bd8b7f0..a41d1bbfe 100644 --- a/d2renderers/d2fonts/d2fonts.go +++ b/d2renderers/d2fonts/d2fonts.go @@ -13,6 +13,7 @@ import ( "oss.terrastruct.com/d2/lib/font" fontlib "oss.terrastruct.com/d2/lib/font" + "oss.terrastruct.com/d2/lib/syncmap" ) type FontFamily string @@ -44,11 +45,7 @@ func (f Font) GetEncodedSubset(corpus string) string { FontFamiliesMu.Lock() defer FontFamiliesMu.Unlock() - var face []byte - { - ff, _ := FontFaces.Load(f) - face = ff.([]byte) - } + face := FontFaces.Get(f) fontBuf := make([]byte, len(face)) copy(fontBuf, face) fontBuf = font.UTF8CutFont(fontBuf, uniqueChars) @@ -56,8 +53,7 @@ func (f Font) GetEncodedSubset(corpus string) string { fontBuf, err := fontlib.Sfnt2Woff(fontBuf) if err != nil { // If subset fails, return full encoding - fe, _ := FontEncodings.Load(f) - return fe.(string) + return FontEncodings.Get(f) } return fmt.Sprintf("data:application/font-woff;base64,%v", base64.StdEncoding.EncodeToString(fontBuf)) @@ -140,104 +136,105 @@ var fuzzyBubblesBoldBase64 string //go:embed ttf/* var fontFacesFS embed.FS -// FontEncodings map[Font]string -var FontEncodings sync.Map - -// FontFaces map[Font][]byte -var FontFaces sync.Map +var FontEncodings syncmap.SyncMap[Font, string] +var FontFaces syncmap.SyncMap[Font, []byte] func init() { - FontEncodings.Store( + FontEncodings = syncmap.New[Font, string]() + + FontEncodings.Set( Font{ Family: SourceSansPro, Style: FONT_STYLE_REGULAR, }, sourceSansProRegularBase64) - FontEncodings.Store( + FontEncodings.Set( Font{ Family: SourceSansPro, Style: FONT_STYLE_BOLD, }, sourceSansProBoldBase64) - FontEncodings.Store( + FontEncodings.Set( Font{ Family: SourceSansPro, Style: FONT_STYLE_SEMIBOLD, }, sourceSansProSemiboldBase64) - FontEncodings.Store( + FontEncodings.Set( Font{ Family: SourceSansPro, Style: FONT_STYLE_ITALIC, }, sourceSansProItalicBase64) - FontEncodings.Store( + FontEncodings.Set( Font{ Family: SourceCodePro, Style: FONT_STYLE_REGULAR, }, sourceCodeProRegularBase64) - FontEncodings.Store( + FontEncodings.Set( Font{ Family: SourceCodePro, Style: FONT_STYLE_BOLD, }, sourceCodeProBoldBase64) - FontEncodings.Store( + FontEncodings.Set( Font{ Family: SourceCodePro, Style: FONT_STYLE_SEMIBOLD, }, sourceCodeProSemiboldBase64) - FontEncodings.Store( + FontEncodings.Set( Font{ Family: SourceCodePro, Style: FONT_STYLE_ITALIC, }, sourceCodeProItalicBase64) - FontEncodings.Store( + FontEncodings.Set( Font{ Family: HandDrawn, Style: FONT_STYLE_REGULAR, }, fuzzyBubblesRegularBase64) - FontEncodings.Store( + FontEncodings.Set( Font{ Family: HandDrawn, Style: FONT_STYLE_ITALIC, // This font has no italic, so just reuse regular }, fuzzyBubblesRegularBase64) - FontEncodings.Store( + FontEncodings.Set( Font{ Family: HandDrawn, Style: FONT_STYLE_BOLD, }, fuzzyBubblesBoldBase64) - FontEncodings.Store( + FontEncodings.Set( Font{ Family: HandDrawn, Style: FONT_STYLE_SEMIBOLD, // This font has no semibold, so just reuse bold }, fuzzyBubblesBoldBase64) - FontEncodings.Range(func(k, v any) bool { - FontEncodings.Swap(k, strings.TrimSuffix(v.(string), "\n")) + FontEncodings.Range(func(k Font, v string) bool { + FontEncodings.Set(k, strings.TrimSuffix(v, "\n")) return true }) + FontFaces = syncmap.New[Font, []byte]() + b, err := fontFacesFS.ReadFile("ttf/SourceSansPro-Regular.ttf") if err != nil { panic(err) } - FontFaces.Store(Font{ + FontFaces.Set(Font{ Family: SourceSansPro, Style: FONT_STYLE_REGULAR, }, b) @@ -246,7 +243,7 @@ func init() { if err != nil { panic(err) } - FontFaces.Store(Font{ + FontFaces.Set(Font{ Family: SourceCodePro, Style: FONT_STYLE_REGULAR, }, b) @@ -255,7 +252,7 @@ func init() { if err != nil { panic(err) } - FontFaces.Store(Font{ + FontFaces.Set(Font{ Family: SourceCodePro, Style: FONT_STYLE_BOLD, }, b) @@ -264,7 +261,7 @@ func init() { if err != nil { panic(err) } - FontFaces.Store(Font{ + FontFaces.Set(Font{ Family: SourceCodePro, Style: FONT_STYLE_SEMIBOLD, }, b) @@ -273,7 +270,7 @@ func init() { if err != nil { panic(err) } - FontFaces.Store(Font{ + FontFaces.Set(Font{ Family: SourceCodePro, Style: FONT_STYLE_ITALIC, }, b) @@ -282,7 +279,7 @@ func init() { if err != nil { panic(err) } - FontFaces.Store(Font{ + FontFaces.Set(Font{ Family: SourceSansPro, Style: FONT_STYLE_BOLD, }, b) @@ -291,7 +288,7 @@ func init() { if err != nil { panic(err) } - FontFaces.Store(Font{ + FontFaces.Set(Font{ Family: SourceSansPro, Style: FONT_STYLE_SEMIBOLD, }, b) @@ -300,7 +297,7 @@ func init() { if err != nil { panic(err) } - FontFaces.Store(Font{ + FontFaces.Set(Font{ Family: SourceSansPro, Style: FONT_STYLE_ITALIC, }, b) @@ -309,11 +306,11 @@ func init() { if err != nil { panic(err) } - FontFaces.Store(Font{ + FontFaces.Set(Font{ Family: HandDrawn, Style: FONT_STYLE_REGULAR, }, b) - FontFaces.Store(Font{ + FontFaces.Set(Font{ Family: HandDrawn, Style: FONT_STYLE_ITALIC, }, b) @@ -322,11 +319,11 @@ func init() { if err != nil { panic(err) } - FontFaces.Store(Font{ + FontFaces.Set(Font{ Family: HandDrawn, Style: FONT_STYLE_BOLD, }, b) - FontFaces.Store(Font{ + FontFaces.Set(Font{ Family: HandDrawn, Style: FONT_STYLE_SEMIBOLD, }, b) @@ -338,14 +335,14 @@ var D2_FONT_TO_FAMILY = map[string]FontFamily{ } func AddFontStyle(font Font, style FontStyle, ttf []byte) error { - FontFaces.Store(font, ttf) + FontFaces.Set(font, ttf) woff, err := fontlib.Sfnt2Woff(ttf) if err != nil { return fmt.Errorf("failed to encode ttf to woff: %v", err) } encodedWoff := fmt.Sprintf("data:application/font-woff;base64,%v", base64.StdEncoding.EncodeToString(woff)) - FontEncodings.Store(font, encodedWoff) + FontEncodings.Set(font, encodedWoff) return nil } @@ -369,10 +366,8 @@ func AddFontFamily(name string, regularTTF, italicTTF, boldTTF, semiboldTTF []by Family: SourceSansPro, Style: FONT_STYLE_REGULAR, } - f, _ := FontFaces.Load(fallbackFont) - FontFaces.Store(regularFont, f) - e, _ := FontEncodings.Load(fallbackFont) - FontEncodings.Store(regularFont, e) + FontFaces.Set(regularFont, FontFaces.Get(fallbackFont)) + FontEncodings.Set(regularFont, FontEncodings.Get(fallbackFont)) } italicFont := Font{ @@ -389,10 +384,8 @@ func AddFontFamily(name string, regularTTF, italicTTF, boldTTF, semiboldTTF []by Family: SourceSansPro, Style: FONT_STYLE_ITALIC, } - f, _ := FontFaces.Load(fallbackFont) - FontFaces.Store(italicFont, f) - fb, _ := FontEncodings.Load(fallbackFont) - FontEncodings.Store(italicFont, fb) + FontFaces.Set(italicFont, FontFaces.Get(fallbackFont)) + FontEncodings.Set(italicFont, FontEncodings.Get(fallbackFont)) } boldFont := Font{ @@ -409,10 +402,8 @@ func AddFontFamily(name string, regularTTF, italicTTF, boldTTF, semiboldTTF []by Family: SourceSansPro, Style: FONT_STYLE_BOLD, } - f, _ := FontFaces.Load(fallbackFont) - FontFaces.Store(boldFont, f) - fb, _ := FontEncodings.Load(fallbackFont) - FontEncodings.Store(boldFont, fb) + FontFaces.Set(boldFont, FontFaces.Get(fallbackFont)) + FontEncodings.Set(boldFont, FontEncodings.Get(fallbackFont)) } semiboldFont := Font{ @@ -429,10 +420,8 @@ func AddFontFamily(name string, regularTTF, italicTTF, boldTTF, semiboldTTF []by Family: SourceSansPro, Style: FONT_STYLE_SEMIBOLD, } - f, _ := FontFaces.Load(fallbackFont) - FontFaces.Store(semiboldFont, f) - fb, _ := FontEncodings.Load(fallbackFont) - FontEncodings.Store(semiboldFont, fb) + FontFaces.Set(semiboldFont, FontFaces.Get(fallbackFont)) + FontEncodings.Set(semiboldFont, FontEncodings.Get(fallbackFont)) } FontFamilies = append(FontFamilies, customFontFamily) diff --git a/d2renderers/d2fonts/d2fonts_test.go b/d2renderers/d2fonts/d2fonts_test.go index 1fd773241..9c1cf4f00 100644 --- a/d2renderers/d2fonts/d2fonts_test.go +++ b/d2renderers/d2fonts/d2fonts_test.go @@ -14,11 +14,7 @@ func TestCutFont(t *testing.T) { Family: SourceCodePro, Style: FONT_STYLE_BOLD, } - var face []byte - { - ff, _ := FontFaces.Load(f) - face = ff.([]byte) - } + face := FontFaces.Get(f) fontBuf := make([]byte, len(face)) copy(fontBuf, face) fontBuf = font.UTF8CutFont(fontBuf, " 1") diff --git a/d2renderers/d2svg/appendix/appendix.go b/d2renderers/d2svg/appendix/appendix.go index 86c44b9c3..803651f35 100644 --- a/d2renderers/d2svg/appendix/appendix.go +++ b/d2renderers/d2svg/appendix/appendix.go @@ -121,7 +121,6 @@ func Append(diagram *d2target.Diagram, ruler *textmeasure.Ruler, in []byte) []by } if !strings.Contains(svg, `font-family: "font-regular"`) { - font, _ := d2fonts.FontEncodings.Load(d2fonts.SourceSansPro.Font(0, d2fonts.FONT_STYLE_REGULAR)) appendix += fmt.Sprintf(``, font.(string)) +]]>`, d2fonts.FontEncodings.Get(d2fonts.SourceSansPro.Font(0, d2fonts.FONT_STYLE_REGULAR))) } if !strings.Contains(svg, `font-family: "font-bold"`) { - font, _ := d2fonts.FontEncodings.Load(d2fonts.SourceSansPro.Font(0, d2fonts.FONT_STYLE_BOLD)) appendix += fmt.Sprintf(``, font.(string)) +]]>`, d2fonts.FontEncodings.Get(d2fonts.SourceSansPro.Font(0, d2fonts.FONT_STYLE_BOLD))) } closingIndex := strings.LastIndex(svg, "") diff --git a/lib/pdf/pdf.go b/lib/pdf/pdf.go index b1471f70a..85d6b7971 100644 --- a/lib/pdf/pdf.go +++ b/lib/pdf/pdf.go @@ -31,10 +31,8 @@ func Init() *GoFPDF { UnitStr: "pt", }) - reg, _ := d2fonts.FontFaces.Load(d2fonts.SourceSansPro.Font(0, d2fonts.FONT_STYLE_REGULAR)) - bold, _ := d2fonts.FontFaces.Load(d2fonts.SourceSansPro.Font(0, d2fonts.FONT_STYLE_BOLD)) - newGofPDF.AddUTF8FontFromBytes("source", "", reg.([]byte)) - newGofPDF.AddUTF8FontFromBytes("source", "B", bold.([]byte)) + newGofPDF.AddUTF8FontFromBytes("source", "", d2fonts.FontFaces.Get(d2fonts.SourceSansPro.Font(0, d2fonts.FONT_STYLE_REGULAR))) + newGofPDF.AddUTF8FontFromBytes("source", "B", d2fonts.FontFaces.Get(d2fonts.SourceSansPro.Font(0, d2fonts.FONT_STYLE_BOLD))) newGofPDF.SetAutoPageBreak(false, 0) newGofPDF.SetLineWidth(2) newGofPDF.SetMargins(0, 0, 0) diff --git a/lib/textmeasure/textmeasure.go b/lib/textmeasure/textmeasure.go index 004b48a3d..2bd112b7d 100644 --- a/lib/textmeasure/textmeasure.go +++ b/lib/textmeasure/textmeasure.go @@ -126,12 +126,12 @@ func NewRuler() (*Ruler, error) { Style: fontStyle, } // Note: FontFaces lookup is size-agnostic - face, has := d2fonts.FontFaces.Load(font) + face, has := d2fonts.FontFaces.GetWithStatus(font) if !has { continue } if _, loaded := r.ttfs[font]; !loaded { - ttf, err := truetype.Parse(face.([]byte)) + ttf, err := truetype.Parse(face) if err != nil { return nil, err }