diff --git a/d2cli/main.go b/d2cli/main.go index 9df893c42..794f2a071 100644 --- a/d2cli/main.go +++ b/d2cli/main.go @@ -284,7 +284,7 @@ func compile(ctx context.Context, ms *xmain.State, plugin d2plugin.Plugin, sketc var svg []byte if filepath.Ext(outputPath) == ".pdf" { - svg, err = renderPDF(ctx, ms, plugin, sketch, pad, outputPath, page, ruler, diagram, nil, nil) + svg, err = renderPDF(ctx, ms, plugin, sketch, pad, themeID, outputPath, page, ruler, diagram, nil, nil) } else { compileDur := time.Since(start) svg, err = render(ctx, ms, compileDur, plugin, sketch, pad, themeID, darkThemeID, inputPath, outputPath, bundle, forceAppendix, page, ruler, diagram) @@ -436,7 +436,7 @@ func _render(ctx context.Context, ms *xmain.State, plugin d2plugin.Plugin, sketc return svg, nil } -func renderPDF(ctx context.Context, ms *xmain.State, plugin d2plugin.Plugin, sketch bool, pad int64, outputPath string, page playwright.Page, ruler *textmeasure.Ruler, diagram *d2target.Diagram, pdf *pdflib.GoFPDF, boardPath []string) (svg []byte, err error) { +func renderPDF(ctx context.Context, ms *xmain.State, plugin d2plugin.Plugin, sketch bool, pad, themeID int64, outputPath string, page playwright.Page, ruler *textmeasure.Ruler, diagram *d2target.Diagram, pdf *pdflib.GoFPDF, boardPath []string) (svg []byte, err error) { var isRoot bool if pdf == nil { pdf = pdflib.Init() @@ -487,26 +487,26 @@ func renderPDF(ctx context.Context, ms *xmain.State, plugin d2plugin.Plugin, ske return svg, err } - err = pdf.AddPDFPage(pngImg, currBoardPath, rootFill) + err = pdf.AddPDFPage(pngImg, currBoardPath, themeID, rootFill) if err != nil { return svg, err } } for _, dl := range diagram.Layers { - _, err := renderPDF(ctx, ms, plugin, sketch, pad, "", page, ruler, dl, pdf, currBoardPath) + _, err := renderPDF(ctx, ms, plugin, sketch, pad, themeID, "", page, ruler, dl, pdf, currBoardPath) if err != nil { return nil, err } } for _, dl := range diagram.Scenarios { - _, err := renderPDF(ctx, ms, plugin, sketch, pad, "", page, ruler, dl, pdf, currBoardPath) + _, err := renderPDF(ctx, ms, plugin, sketch, pad, themeID, "", page, ruler, dl, pdf, currBoardPath) if err != nil { return nil, err } } for _, dl := range diagram.Steps { - _, err := renderPDF(ctx, ms, plugin, sketch, pad, "", page, ruler, dl, pdf, currBoardPath) + _, err := renderPDF(ctx, ms, plugin, sketch, pad, themeID, "", page, ruler, dl, pdf, currBoardPath) if err != nil { return nil, err } diff --git a/d2themes/d2themes.go b/d2themes/d2themes.go index 00df8a4f7..f595ed600 100644 --- a/d2themes/d2themes.go +++ b/d2themes/d2themes.go @@ -2,6 +2,8 @@ // Color codes: darkest (N1) -> lightest (N7) package d2themes +import "oss.terrastruct.com/d2/lib/color" + type Theme struct { ID int64 `json:"id"` Name string `json:"name"` @@ -68,3 +70,49 @@ var DarkNeutral = Neutral{ N6: "#313244", N7: "#1E1E2E", } + +func ResolveThemeColor(theme Theme, code string) string { + if !color.IsThemeColor(code) { + return code + } + switch code { + case "N1": + return theme.Colors.Neutrals.N1 + case "N2": + return theme.Colors.Neutrals.N2 + case "N3": + return theme.Colors.Neutrals.N3 + case "N4": + return theme.Colors.Neutrals.N4 + case "N5": + return theme.Colors.Neutrals.N5 + case "N6": + return theme.Colors.Neutrals.N6 + case "N7": + return theme.Colors.Neutrals.N7 + case "B1": + return theme.Colors.B1 + case "B2": + return theme.Colors.B2 + case "B3": + return theme.Colors.B3 + case "B4": + return theme.Colors.B4 + case "B5": + return theme.Colors.B5 + case "B6": + return theme.Colors.B6 + case "AA2": + return theme.Colors.AA2 + case "AA4": + return theme.Colors.AA4 + case "AA5": + return theme.Colors.AA5 + case "AB4": + return theme.Colors.AB4 + case "AB5": + return theme.Colors.AB5 + default: + return "" + } +} diff --git a/lib/pdf/pdf.go b/lib/pdf/pdf.go index 1a05ac8a3..4ec7eb273 100644 --- a/lib/pdf/pdf.go +++ b/lib/pdf/pdf.go @@ -8,6 +8,8 @@ import ( "github.com/jung-kurt/gofpdf" "oss.terrastruct.com/d2/d2renderers/d2fonts" + "oss.terrastruct.com/d2/d2themes" + "oss.terrastruct.com/d2/d2themes/d2themescatalog" "oss.terrastruct.com/d2/lib/color" ) @@ -33,7 +35,7 @@ func Init() *GoFPDF { return &fpdf } -func (g *GoFPDF) GetFillRGB(fill string) (color.RGB, error) { +func (g *GoFPDF) GetFillRGB(themeID int64, fill string) (color.RGB, error) { if fill == "" || strings.ToLower(fill) == "transparent" { return color.RGB{ Red: 255, @@ -47,10 +49,15 @@ func (g *GoFPDF) GetFillRGB(fill string) (color.RGB, error) { return rgb, nil } + if color.IsThemeColor(fill) { + theme := d2themescatalog.Find(themeID) + fill = d2themes.ResolveThemeColor(theme, fill) + } + return color.Hex2RGB(fill) } -func (g *GoFPDF) AddPDFPage(png []byte, boardPath []string, fill string) error { +func (g *GoFPDF) AddPDFPage(png []byte, boardPath []string, themeID int64, fill string) error { var opt gofpdf.ImageOptions opt.ImageType = "png" imageInfo := g.pdf.RegisterImageOptionsReader(strings.Join(boardPath, "/"), opt, bytes.NewReader(png)) @@ -73,7 +80,7 @@ func (g *GoFPDF) AddPDFPage(png []byte, boardPath []string, fill string) error { pageWidth = math.Max(math.Max(minPageDimension, imageWidth), headerWidth) pageHeight = math.Max(minPageDimension, imageHeight) - fillRGB, err := g.GetFillRGB(fill) + fillRGB, err := g.GetFillRGB(themeID, fill) if err != nil { return err }