diff --git a/d2graph/d2graph.go b/d2graph/d2graph.go index 409e59cf0..e39ec27ca 100644 --- a/d2graph/d2graph.go +++ b/d2graph/d2graph.go @@ -903,16 +903,21 @@ func (obj *Object) GetLabelSize(mtexts []*d2target.MText, ruler *textmeasure.Rul func (obj *Object) GetDefaultSize(mtexts []*d2target.MText, ruler *textmeasure.Ruler, fontFamily *d2fonts.FontFamily, labelDims d2target.TextDimensions, withLabelPadding bool) (*d2target.TextDimensions, error) { dims := d2target.TextDimensions{} + dslShape := strings.ToLower(obj.Shape.Value) - if withLabelPadding { + if dslShape == d2target.ShapeCode { + fontSize := obj.Text().FontSize + // 0.5em padding on each side + labelDims.Width += fontSize + labelDims.Height += fontSize + } else if withLabelPadding { labelDims.Width += INNER_LABEL_PADDING labelDims.Height += INNER_LABEL_PADDING } - switch strings.ToLower(obj.Shape.Value) { + switch dslShape { default: return d2target.NewTextDimensions(labelDims.Width, labelDims.Height), nil - case d2target.ShapeText: w := labelDims.Width if w < MIN_SHAPE_SIZE { @@ -1308,7 +1313,10 @@ func GetTextDimensions(mtexts []*d2target.MText, ruler *textmeasure.Ruler, t *d2 var w int var h int if t.Language != "" { - w, h = ruler.Measure(d2fonts.SourceCodePro.Font(t.FontSize, d2fonts.FONT_STYLE_REGULAR), t.Text) + originalLineHeight := ruler.LineHeightFactor + ruler.LineHeightFactor = 1.3 + w, h = ruler.MeasureMono(d2fonts.SourceCodePro.Font(t.FontSize, d2fonts.FONT_STYLE_REGULAR), t.Text) + ruler.LineHeightFactor = originalLineHeight // count empty leading and trailing lines since ruler will not be able to measure it lines := strings.Split(t.Text, "\n") @@ -1329,10 +1337,6 @@ func GetTextDimensions(mtexts []*d2target.MText, ruler *textmeasure.Ruler, t *d2 } } h += t.FontSize * (leadingLines + trailingLines) - - // padding - w += 12 - h += 12 } else { style := d2fonts.FONT_STYLE_REGULAR if t.IsBold { diff --git a/d2renderers/d2fonts/d2fonts.go b/d2renderers/d2fonts/d2fonts.go index 2c692ab35..2e1cad31d 100644 --- a/d2renderers/d2fonts/d2fonts.go +++ b/d2renderers/d2fonts/d2fonts.go @@ -199,6 +199,7 @@ func init() { Family: SourceSansPro, Style: FONT_STYLE_REGULAR, }] = b + b, err = fontFacesFS.ReadFile("ttf/SourceCodePro-Regular.ttf") if err != nil { panic(err) @@ -207,6 +208,7 @@ func init() { Family: SourceCodePro, Style: FONT_STYLE_REGULAR, }] = b + b, err = fontFacesFS.ReadFile("ttf/SourceCodePro-Bold.ttf") if err != nil { panic(err) @@ -215,6 +217,7 @@ func init() { Family: SourceCodePro, Style: FONT_STYLE_BOLD, }] = b + b, err = fontFacesFS.ReadFile("ttf/SourceCodePro-Semibold.ttf") if err != nil { panic(err) @@ -223,6 +226,7 @@ func init() { Family: SourceCodePro, Style: FONT_STYLE_SEMIBOLD, }] = b + b, err = fontFacesFS.ReadFile("ttf/SourceCodePro-Italic.ttf") if err != nil { panic(err) @@ -231,6 +235,7 @@ func init() { Family: SourceCodePro, Style: FONT_STYLE_ITALIC, }] = b + b, err = fontFacesFS.ReadFile("ttf/SourceSansPro-Bold.ttf") if err != nil { panic(err) @@ -239,6 +244,7 @@ func init() { Family: SourceSansPro, Style: FONT_STYLE_BOLD, }] = b + b, err = fontFacesFS.ReadFile("ttf/SourceSansPro-Semibold.ttf") if err != nil { panic(err) @@ -247,6 +253,7 @@ func init() { Family: SourceSansPro, Style: FONT_STYLE_SEMIBOLD, }] = b + b, err = fontFacesFS.ReadFile("ttf/SourceSansPro-Italic.ttf") if err != nil { panic(err) @@ -255,6 +262,7 @@ func init() { Family: SourceSansPro, Style: FONT_STYLE_ITALIC, }] = b + b, err = fontFacesFS.ReadFile("ttf/ArchitectsDaughter-Regular.ttf") if err != nil { panic(err) @@ -267,6 +275,7 @@ func init() { Family: HandDrawn, Style: FONT_STYLE_ITALIC, }] = b + b, err = fontFacesFS.ReadFile("ttf/FuzzyBubbles-Bold.ttf") if err != nil { panic(err) diff --git a/d2renderers/d2svg/d2svg.go b/d2renderers/d2svg/d2svg.go index 0c9c44943..3b4f0650e 100644 --- a/d2renderers/d2svg/d2svg.go +++ b/d2renderers/d2svg/d2svg.go @@ -1263,14 +1263,18 @@ func drawShape(writer io.Writer, diagramHash string, targetShape d2target.Shape, rectEl.Height = float64(targetShape.Height) rectEl.Stroke = targetShape.Stroke rectEl.ClassName = "shape" - rectEl.Style = fmt.Sprintf(`fill:%s`, style.Get(chroma.Background).Background.String()) + rectEl.Style = fmt.Sprintf(`fill:%s;stroke-width:%d;`, + style.Get(chroma.Background).Background.String(), + targetShape.StrokeWidth, + ) fmt.Fprint(writer, rectEl.Render()) - // Padding - fmt.Fprint(writer, ``) + // Padding = 0.5em + padding := float64(targetShape.FontSize) / 2. + fmt.Fprintf(writer, ``, padding, padding) + lineHeight := 1.3 for index, tokens := range chroma.SplitTokensIntoLines(iterator.Tokens()) { - // TODO mono font looks better with 1.2 em (use px equivalent), but textmeasure needs to account for it. Not obvious how that should be done - fmt.Fprintf(writer, "", 1*float64(index+1)) + fmt.Fprintf(writer, "", 1+lineHeight*float64(index)) for _, token := range tokens { text := svgEscaper.Replace(token.String()) attr := styleAttr(svgStyles, token.Type) diff --git a/lib/textmeasure/textmeasure.go b/lib/textmeasure/textmeasure.go index ea104e18a..8602a0bed 100644 --- a/lib/textmeasure/textmeasure.go +++ b/lib/textmeasure/textmeasure.go @@ -214,6 +214,14 @@ func (t *Ruler) scaleUnicode(w float64, font d2fonts.Font, s string) float64 { return w } +func (t *Ruler) MeasureMono(font d2fonts.Font, s string) (width, height int) { + originalBoundsWithDot := t.boundsWithDot + t.boundsWithDot = true + width, height = t.Measure(font, s) + t.boundsWithDot = originalBoundsWithDot + return width, height +} + func (t *Ruler) Measure(font d2fonts.Font, s string) (width, height int) { w, h := t.MeasurePrecise(font, s) w = t.scaleUnicode(w, font, s)