fix rendering table measurement

This commit is contained in:
Gavin Nishizawa 2022-12-17 18:56:43 -08:00
parent 6429beb3bb
commit abb57adf48
No known key found for this signature in database
GPG key ID: AE3B177777CE55CD
7 changed files with 22 additions and 18 deletions

View file

@ -1011,14 +1011,14 @@ func (g *Graph) SetDimensions(mtexts []*d2target.MText, ruler *textmeasure.Ruler
} }
if c.Constraint != "" { if c.Constraint != "" {
// covers UNQ constraint with padding // covers UNQ constraint with padding
constraintWidth = 70. constraintWidth = 60.
} }
} }
// The rows get padded a little due to header font being larger than row font // The rows get padded a little due to header font being larger than row font
obj.Height = float64(dims.Height * (len(obj.SQLTable.Columns) + 1)) obj.Height = float64(dims.Height * (len(obj.SQLTable.Columns) + 1))
// Leave room for padding (20 on each side) // Leave room for padding (10 name 20 type 20 = 50)
obj.Width = float64(maxNameWidth + maxTypeWidth + constraintWidth + 40) obj.Width = float64(maxNameWidth + maxTypeWidth + constraintWidth + 50)
case d2target.ShapeText, d2target.ShapeCode: case d2target.ShapeText, d2target.ShapeCode:
} }

View file

@ -589,7 +589,7 @@ func render3dRect(targetShape d2target.Shape) string {
return borderMask + mainRect + renderedSides + renderedBorder return borderMask + mainRect + renderedSides + renderedBorder
} }
func drawShape(writer io.Writer, targetShape d2target.Shape) (labelMask string, err error) { func drawShape(writer io.Writer, targetShape d2target.Shape, ruler *textmeasure.Ruler) (labelMask string, err error) {
fmt.Fprintf(writer, `<g id="%s">`, escapeText(targetShape.ID)) fmt.Fprintf(writer, `<g id="%s">`, escapeText(targetShape.ID))
tl := geo.NewPoint(float64(targetShape.Pos.X), float64(targetShape.Pos.Y)) tl := geo.NewPoint(float64(targetShape.Pos.X), float64(targetShape.Pos.Y))
width := float64(targetShape.Width) width := float64(targetShape.Width)
@ -629,7 +629,7 @@ func drawShape(writer io.Writer, targetShape d2target.Shape) (labelMask string,
fmt.Fprintf(writer, `</g></g>`) fmt.Fprintf(writer, `</g></g>`)
return labelMask, nil return labelMask, nil
case d2target.ShapeSQLTable: case d2target.ShapeSQLTable:
drawTable(writer, targetShape) drawTable(writer, targetShape, ruler)
fmt.Fprintf(writer, `</g></g>`) fmt.Fprintf(writer, `</g></g>`)
return labelMask, nil return labelMask, nil
case d2target.ShapeOval: case d2target.ShapeOval:
@ -963,7 +963,7 @@ func embedFonts(buf *bytes.Buffer) {
} }
// TODO minify output at end // TODO minify output at end
func Render(diagram *d2target.Diagram, pad int) ([]byte, error) { func Render(diagram *d2target.Diagram, ruler *textmeasure.Ruler, pad int) ([]byte, error) {
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
w, h := setViewbox(buf, diagram, pad) w, h := setViewbox(buf, diagram, pad)
@ -1022,7 +1022,7 @@ func Render(diagram *d2target.Diagram, pad int) ([]byte, error) {
labelMasks = append(labelMasks, labelMask) labelMasks = append(labelMasks, labelMask)
} }
} else if s, is := obj.(d2target.Shape); is { } else if s, is := obj.(d2target.Shape); is {
labelMask, err := drawShape(buf, s) labelMask, err := drawShape(buf, s, ruler)
if err != nil { if err != nil {
return nil, err return nil, err
} else if labelMask != "" { } else if labelMask != "" {

View file

@ -6,11 +6,15 @@ import (
"math" "math"
"strings" "strings"
"oss.terrastruct.com/d2/d2renderers/d2fonts"
"oss.terrastruct.com/d2/d2target" "oss.terrastruct.com/d2/d2target"
"oss.terrastruct.com/d2/lib/geo" "oss.terrastruct.com/d2/lib/geo"
"oss.terrastruct.com/d2/lib/label" "oss.terrastruct.com/d2/lib/label"
"oss.terrastruct.com/d2/lib/textmeasure"
) )
const namePadding = 10
func tableHeader(box *geo.Box, text string, textWidth, textHeight, fontSize float64) string { func tableHeader(box *geo.Box, text string, textWidth, textHeight, fontSize float64) string {
str := fmt.Sprintf(`<rect class="class_header" x="%f" y="%f" width="%f" height="%f" fill="%s" />`, str := fmt.Sprintf(`<rect class="class_header" x="%f" y="%f" width="%f" height="%f" fill="%s" />`,
box.TopLeft.X, box.TopLeft.Y, box.Width, box.Height, "#0a0f25") box.TopLeft.X, box.TopLeft.Y, box.Width, box.Height, "#0a0f25")
@ -43,7 +47,7 @@ func tableRow(box *geo.Box, nameText, typeText, constraintText string, fontSize,
// e.g. | diagram int FK | // e.g. | diagram int FK |
nameTL := label.InsideMiddleLeft.GetPointOnBox( nameTL := label.InsideMiddleLeft.GetPointOnBox(
box, box,
prefixPadding, namePadding,
box.Width, box.Width,
fontSize, fontSize,
) )
@ -69,7 +73,7 @@ func tableRow(box *geo.Box, nameText, typeText, constraintText string, fontSize,
// TODO light font // TODO light font
fmt.Sprintf(`<text class="text" x="%f" y="%f" style="%s">%s</text>`, fmt.Sprintf(`<text class="text" x="%f" y="%f" style="%s">%s</text>`,
nameTL.X+longestNameWidth, nameTL.X+longestNameWidth+2*namePadding,
nameTL.Y+fontSize*3/4, nameTL.Y+fontSize*3/4,
fmt.Sprintf("text-anchor:%s;font-size:%vpx;fill:%s", "start", fontSize, neutralColor), fmt.Sprintf("text-anchor:%s;font-size:%vpx;fill:%s", "start", fontSize, neutralColor),
escapeText(typeText), escapeText(typeText),
@ -97,7 +101,7 @@ func constraintAbbr(constraint string) string {
} }
} }
func drawTable(writer io.Writer, targetShape d2target.Shape) { func drawTable(writer io.Writer, targetShape d2target.Shape, ruler *textmeasure.Ruler) {
fmt.Fprintf(writer, `<rect class="shape" x="%d" y="%d" width="%d" height="%d" style="%s"/>`, fmt.Fprintf(writer, `<rect class="shape" x="%d" y="%d" width="%d" height="%d" style="%s"/>`,
targetShape.Pos.X, targetShape.Pos.Y, targetShape.Width, targetShape.Height, shapeStyle(targetShape)) targetShape.Pos.X, targetShape.Pos.Y, targetShape.Width, targetShape.Height, shapeStyle(targetShape))
@ -113,18 +117,18 @@ func drawTable(writer io.Writer, targetShape d2target.Shape) {
tableHeader(headerBox, targetShape.Label, float64(targetShape.LabelWidth), float64(targetShape.LabelHeight), float64(targetShape.FontSize)), tableHeader(headerBox, targetShape.Label, float64(targetShape.LabelWidth), float64(targetShape.LabelHeight), float64(targetShape.FontSize)),
) )
fontSize := float64(targetShape.FontSize) font := d2fonts.SourceSansPro.Font(targetShape.FontSize, d2fonts.FONT_STYLE_REGULAR)
var longestNameWidth float64 var longestNameWidth float64
for _, f := range targetShape.SQLTable.Columns { for _, f := range targetShape.SQLTable.Columns {
// TODO measure text w, _ := ruler.MeasurePrecise(font, f.Name)
longestNameWidth = math.Max(longestNameWidth, float64(len(f.Name))*fontSize*5/9) longestNameWidth = math.Max(longestNameWidth, w)
} }
rowBox := geo.NewBox(box.TopLeft.Copy(), box.Width, rowHeight) rowBox := geo.NewBox(box.TopLeft.Copy(), box.Width, rowHeight)
rowBox.TopLeft.Y += headerBox.Height rowBox.TopLeft.Y += headerBox.Height
for _, f := range targetShape.SQLTable.Columns { for _, f := range targetShape.SQLTable.Columns {
fmt.Fprint(writer, fmt.Fprint(writer,
tableRow(rowBox, f.Name, f.Type, constraintAbbr(f.Constraint), fontSize, longestNameWidth), tableRow(rowBox, f.Name, f.Type, constraintAbbr(f.Constraint), float64(targetShape.FontSize), longestNameWidth),
) )
rowBox.TopLeft.Y += rowHeight rowBox.TopLeft.Y += rowHeight
fmt.Fprintf(writer, `<line x1="%f" y1="%f" x2="%f" y2="%f" style="stroke-width:2;stroke:#0a0f25" />`, fmt.Fprintf(writer, `<line x1="%f" y1="%f" x2="%f" y2="%f" style="stroke-width:2;stroke:#0a0f25" />`,

View file

@ -20,6 +20,6 @@ func main() {
Ruler: ruler, Ruler: ruler,
ThemeID: d2themescatalog.GrapeSoda.ID, ThemeID: d2themescatalog.GrapeSoda.ID,
}) })
out, _ := d2svg.Render(diagram, d2svg.DEFAULT_PADDING) out, _ := d2svg.Render(diagram, ruler, d2svg.DEFAULT_PADDING)
_ = ioutil.WriteFile(filepath.Join("out.svg"), out, 0600) _ = ioutil.WriteFile(filepath.Join("out.svg"), out, 0600)
} }

View file

@ -21,6 +21,6 @@ func main() {
_ = graph.SetDimensions(nil, ruler) _ = graph.SetDimensions(nil, ruler)
_ = d2dagrelayout.Layout(context.Background(), graph) _ = d2dagrelayout.Layout(context.Background(), graph)
diagram, _ := d2exporter.Export(context.Background(), graph, d2themescatalog.NeutralDefault.ID) diagram, _ := d2exporter.Export(context.Background(), graph, d2themescatalog.NeutralDefault.ID)
out, _ := d2svg.Render(diagram, d2svg.DEFAULT_PADDING) out, _ := d2svg.Render(diagram, ruler, d2svg.DEFAULT_PADDING)
_ = ioutil.WriteFile(filepath.Join("out.svg"), out, 0600) _ = ioutil.WriteFile(filepath.Join("out.svg"), out, 0600)
} }

View file

@ -125,7 +125,7 @@ func run(t *testing.T, tc testCase) {
dataPath := filepath.Join("testdata", strings.TrimPrefix(t.Name(), "TestE2E/"), layoutName) dataPath := filepath.Join("testdata", strings.TrimPrefix(t.Name(), "TestE2E/"), layoutName)
pathGotSVG := filepath.Join(dataPath, "sketch.got.svg") pathGotSVG := filepath.Join(dataPath, "sketch.got.svg")
svgBytes, err := d2svg.Render(diagram, d2svg.DEFAULT_PADDING) svgBytes, err := d2svg.Render(diagram, ruler, d2svg.DEFAULT_PADDING)
assert.Success(t, err) assert.Success(t, err)
err = os.MkdirAll(dataPath, 0755) err = os.MkdirAll(dataPath, 0755)
assert.Success(t, err) assert.Success(t, err)

View file

@ -214,7 +214,7 @@ func compile(ctx context.Context, ms *xmain.State, plugin d2plugin.Plugin, pad,
return nil, false, err return nil, false, err
} }
svg, err := d2svg.Render(diagram, int(pad)) svg, err := d2svg.Render(diagram, ruler, int(pad))
if err != nil { if err != nil {
return nil, false, err return nil, false, err
} }