Merge pull request #1413 from gavin-ts/scale-flag

use scale flag for no-fit and customizing zoom
This commit is contained in:
gavin-ts 2023-06-26 13:54:57 -07:00 committed by GitHub
commit 5829f26082
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 84 additions and 34 deletions

View file

@ -1,6 +1,7 @@
#### Features 🚀 #### Features 🚀
- Configure timeout value with D2_TIMEOUT env var. [#1392](https://github.com/terrastruct/d2/pull/1392) - Configure timeout value with D2_TIMEOUT env var. [#1392](https://github.com/terrastruct/d2/pull/1392)
- Scale renders and disable fit to screen with `--scale` flag. [#1413](https://github.com/terrastruct/d2/pull/1413)
#### Improvements 🧹 #### Improvements 🧹

View file

@ -80,6 +80,9 @@ Renders the diagram to look like it was sketched by hand
.It Fl -center Ar flag .It Fl -center Ar flag
Center the SVG in the containing viewbox, such as your browser screen Center the SVG in the containing viewbox, such as your browser screen
.Ns . .Ns .
.It Fl -scale Ar -1
Scale the output. E.g., 0.5 to halve the default size. Default -1 means that SVG's will fit to screen and all others will use their default render size. Setting to 1 turns off SVG fitting to screen
.Ns .
.It Fl -font-regular .It Fl -font-regular
Path to .ttf file to use for the regular font. If none provided, Source Sans Pro Regular is used Path to .ttf file to use for the regular font. If none provided, Source Sans Pro Regular is used
.Ns . .Ns .

View file

@ -107,6 +107,10 @@ func Run(ctx context.Context, ms *xmain.State) (err error) {
if err != nil { if err != nil {
return err return err
} }
scaleFlag, err := ms.Opts.Float64("SCALE", "scale", "", -1, "scale the output. E.g., 0.5 to halve the default size. Default -1 means that SVG's will fit to screen and all others will use their default render size. Setting to 1 turns off SVG fitting to screen.")
if err != nil {
return err
}
fontRegularFlag := ms.Opts.String("D2_FONT_REGULAR", "font-regular", "", "", "path to .ttf file to use for the regular font. If none provided, Source Sans Pro Regular is used.") fontRegularFlag := ms.Opts.String("D2_FONT_REGULAR", "font-regular", "", "", "path to .ttf file to use for the regular font. If none provided, Source Sans Pro Regular is used.")
fontItalicFlag := ms.Opts.String("D2_FONT_ITALIC", "font-italic", "", "", "path to .ttf file to use for the italic font. If none provided, Source Sans Pro Regular-Italic is used.") fontItalicFlag := ms.Opts.String("D2_FONT_ITALIC", "font-italic", "", "", "path to .ttf file to use for the italic font. If none provided, Source Sans Pro Regular-Italic is used.")
@ -232,6 +236,10 @@ func Run(ctx context.Context, ms *xmain.State) (err error) {
} }
ms.Log.Debug.Printf("using dark theme %s (ID: %d)", match.Name, *darkThemeFlag) ms.Log.Debug.Printf("using dark theme %s (ID: %d)", match.Name, *darkThemeFlag)
} }
var scale *float64
if scaleFlag != nil && *scaleFlag > 0. {
scale = scaleFlag
}
plugin, err := d2plugin.FindPlugin(ctx, ps, *layoutFlag) plugin, err := d2plugin.FindPlugin(ctx, ps, *layoutFlag)
if err != nil { if err != nil {
@ -282,6 +290,7 @@ func Run(ctx context.Context, ms *xmain.State) (err error) {
Center: *centerFlag, Center: *centerFlag,
ThemeID: *themeFlag, ThemeID: *themeFlag,
DarkThemeID: darkThemeFlag, DarkThemeID: darkThemeFlag,
Scale: scale,
} }
if *watchFlag { if *watchFlag {
@ -665,6 +674,12 @@ func render(ctx context.Context, ms *xmain.State, compileDur time.Duration, plug
func _render(ctx context.Context, ms *xmain.State, plugin d2plugin.Plugin, opts d2svg.RenderOpts, outputPath string, bundle, forceAppendix bool, page playwright.Page, ruler *textmeasure.Ruler, diagram *d2target.Diagram) ([]byte, error) { func _render(ctx context.Context, ms *xmain.State, plugin d2plugin.Plugin, opts d2svg.RenderOpts, outputPath string, bundle, forceAppendix bool, page playwright.Page, ruler *textmeasure.Ruler, diagram *d2target.Diagram) ([]byte, error) {
toPNG := getExportExtension(outputPath) == PNG toPNG := getExportExtension(outputPath) == PNG
var scale *float64
if opts.Scale != nil {
scale = opts.Scale
} else if toPNG {
scale = go2.Pointer(1.)
}
svg, err := d2svg.Render(diagram, &d2svg.RenderOpts{ svg, err := d2svg.Render(diagram, &d2svg.RenderOpts{
Pad: opts.Pad, Pad: opts.Pad,
Sketch: opts.Sketch, Sketch: opts.Sketch,
@ -672,7 +687,7 @@ func _render(ctx context.Context, ms *xmain.State, plugin d2plugin.Plugin, opts
ThemeID: opts.ThemeID, ThemeID: opts.ThemeID,
DarkThemeID: opts.DarkThemeID, DarkThemeID: opts.DarkThemeID,
MasterID: opts.MasterID, MasterID: opts.MasterID,
SetDimensions: toPNG, Scale: scale,
}) })
if err != nil { if err != nil {
return nil, err return nil, err
@ -746,11 +761,18 @@ func renderPDF(ctx context.Context, ms *xmain.State, plugin d2plugin.Plugin, opt
// make the bg fill within the png transparent so that the pdf bg fill is the only bg color present // make the bg fill within the png transparent so that the pdf bg fill is the only bg color present
diagram.Root.Fill = "transparent" diagram.Root.Fill = "transparent"
var scale *float64
if opts.Scale != nil {
scale = opts.Scale
} else {
scale = go2.Pointer(1.)
}
svg, err = d2svg.Render(diagram, &d2svg.RenderOpts{ svg, err = d2svg.Render(diagram, &d2svg.RenderOpts{
Pad: opts.Pad, Pad: opts.Pad,
Sketch: opts.Sketch, Sketch: opts.Sketch,
Center: opts.Center, Center: opts.Center,
SetDimensions: true, Scale: scale,
}) })
if err != nil { if err != nil {
return nil, err return nil, err
@ -837,12 +859,20 @@ func renderPPTX(ctx context.Context, ms *xmain.State, presentation *pptx.Present
// make the bg fill within the png transparent so that the pdf bg fill is the only bg color present // make the bg fill within the png transparent so that the pdf bg fill is the only bg color present
diagram.Root.Fill = "transparent" diagram.Root.Fill = "transparent"
var scale *float64
if opts.Scale != nil {
scale = opts.Scale
} else {
scale = go2.Pointer(1.)
}
var err error var err error
svg, err = d2svg.Render(diagram, &d2svg.RenderOpts{ svg, err = d2svg.Render(diagram, &d2svg.RenderOpts{
Pad: opts.Pad, Pad: opts.Pad,
Sketch: opts.Sketch, Sketch: opts.Sketch,
Center: opts.Center, Center: opts.Center,
SetDimensions: true, Scale: scale,
}) })
if err != nil { if err != nil {
return nil, err return nil, err
@ -1076,11 +1106,18 @@ func buildBoardIDToIndex(diagram *d2target.Diagram, dictionary map[string]int, p
func renderPNGsForGIF(ctx context.Context, ms *xmain.State, plugin d2plugin.Plugin, opts d2svg.RenderOpts, ruler *textmeasure.Ruler, page playwright.Page, diagram *d2target.Diagram) (svg []byte, pngs [][]byte, err error) { func renderPNGsForGIF(ctx context.Context, ms *xmain.State, plugin d2plugin.Plugin, opts d2svg.RenderOpts, ruler *textmeasure.Ruler, page playwright.Page, diagram *d2target.Diagram) (svg []byte, pngs [][]byte, err error) {
if !diagram.IsFolderOnly { if !diagram.IsFolderOnly {
var scale *float64
if opts.Scale != nil {
scale = opts.Scale
} else {
scale = go2.Pointer(1.)
}
svg, err = d2svg.Render(diagram, &d2svg.RenderOpts{ svg, err = d2svg.Render(diagram, &d2svg.RenderOpts{
Pad: opts.Pad, Pad: opts.Pad,
Sketch: opts.Sketch, Sketch: opts.Sketch,
Center: opts.Center, Center: opts.Center,
SetDimensions: true, Scale: scale,
}) })
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err

View file

@ -35,6 +35,9 @@ function init(reconnectDelay) {
let width = parseInt(svgEl.getAttribute("width"), 10); let width = parseInt(svgEl.getAttribute("width"), 10);
let height = parseInt(svgEl.getAttribute("height"), 10); let height = parseInt(svgEl.getAttribute("height"), 10);
if (isInit) { if (isInit) {
if (msg.scale) {
ratio = msg.scale;
} else {
if (width > height) { if (width > height) {
if (width > window.innerWidth) { if (width > window.innerWidth) {
ratio = window.innerWidth / width; ratio = window.innerWidth / width;
@ -42,6 +45,7 @@ function init(reconnectDelay) {
} else if (height > window.innerHeight) { } else if (height > window.innerHeight) {
ratio = window.innerHeight / height; ratio = window.innerHeight / height;
} }
}
// Scale svg fit to zoom // Scale svg fit to zoom
isInit = false; isInit = false;
} }

View file

@ -84,6 +84,7 @@ type watcher struct {
type compileResult struct { type compileResult struct {
SVG string `json:"svg"` SVG string `json:"svg"`
Scale *float64 `json:"scale,omitEmpty"`
Err string `json:"err"` Err string `json:"err"`
} }
@ -373,6 +374,7 @@ func (w *watcher) compileLoop(ctx context.Context) error {
} }
w.broadcast(&compileResult{ w.broadcast(&compileResult{
SVG: string(svg), SVG: string(svg),
Scale: w.renderOpts.Scale,
Err: errs, Err: errs,
}) })

View file

@ -75,8 +75,8 @@ type RenderOpts struct {
ThemeID int64 ThemeID int64
DarkThemeID *int64 DarkThemeID *int64
Font string Font string
// disables the fit to screen behavior and ensures the exported svg has the exact dimensions // the svg will be scaled by this factor, if unset the svg will fit to screen
SetDimensions bool Scale *float64
// MasterID is passed when the diagram should use something other than its own hash for unique targeting // MasterID is passed when the diagram should use something other than its own hash for unique targeting
// Currently, that's when multi-boards are collapsed // Currently, that's when multi-boards are collapsed
@ -1654,7 +1654,7 @@ func Render(diagram *d2target.Diagram, opts *RenderOpts) ([]byte, error) {
pad := DEFAULT_PADDING pad := DEFAULT_PADDING
themeID := DEFAULT_THEME themeID := DEFAULT_THEME
darkThemeID := DEFAULT_DARK_THEME darkThemeID := DEFAULT_DARK_THEME
setDimensions := false var scale *float64
if opts != nil { if opts != nil {
pad = opts.Pad pad = opts.Pad
if opts.Sketch { if opts.Sketch {
@ -1666,7 +1666,7 @@ func Render(diagram *d2target.Diagram, opts *RenderOpts) ([]byte, error) {
} }
themeID = opts.ThemeID themeID = opts.ThemeID
darkThemeID = opts.DarkThemeID darkThemeID = opts.DarkThemeID
setDimensions = opts.SetDimensions scale = opts.Scale
} }
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
@ -1857,8 +1857,11 @@ func Render(diagram *d2target.Diagram, opts *RenderOpts) ([]byte, error) {
} }
var dimensions string var dimensions string
if setDimensions { if scale != nil {
dimensions = fmt.Sprintf(` width="%d" height="%d"`, w, h) dimensions = fmt.Sprintf(` width="%d" height="%d"`,
int(math.Ceil((*scale)*float64(w))),
int(math.Ceil((*scale)*float64(h))),
)
} }
alignment := "xMinYMin" alignment := "xMinYMin"