From 88bc8fec843bc910fe26cd7f8b68500b198e9802 Mon Sep 17 00:00:00 2001 From: Gavin Nishizawa Date: Wed, 23 Nov 2022 19:47:05 -0800 Subject: [PATCH 1/5] Add arrowhead label test case from #169 --- e2etests/report/main.go | 5 +- e2etests/stable_test.go | 11 ++ .../arrowhead_labels/dagre/board.exp.json | 130 ++++++++++++++++++ .../arrowhead_labels/dagre/sketch.exp.svg | 34 +++++ .../arrowhead_labels/elk/board.exp.json | 121 ++++++++++++++++ .../arrowhead_labels/elk/sketch.exp.svg | 34 +++++ out/.gitignore | 0 7 files changed, 333 insertions(+), 2 deletions(-) create mode 100644 e2etests/testdata/stable/arrowhead_labels/dagre/board.exp.json create mode 100644 e2etests/testdata/stable/arrowhead_labels/dagre/sketch.exp.svg create mode 100644 e2etests/testdata/stable/arrowhead_labels/elk/board.exp.json create mode 100644 e2etests/testdata/stable/arrowhead_labels/elk/sketch.exp.svg create mode 100644 out/.gitignore diff --git a/e2etests/report/main.go b/e2etests/report/main.go index 81ae168d3..652807d0a 100644 --- a/e2etests/report/main.go +++ b/e2etests/report/main.go @@ -85,13 +85,14 @@ func main() { } if testFile != nil { + testCaseRoot := filepath.Dir(path) matchTestCase := true if testCaseFlag != "" { - matchTestCase, _ = regexp.MatchString(testCaseFlag, filepath.Base(path)) + matchTestCase, _ = regexp.MatchString(testCaseFlag, filepath.Base(testCaseRoot)) } matchTestSet := true if testSetFlag != "" { - matchTestSet, _ = regexp.MatchString(testSetFlag, filepath.Base(filepath.Dir(path))) + matchTestSet, _ = regexp.MatchString(testSetFlag, filepath.Base(filepath.Dir(testCaseRoot))) } if matchTestSet && matchTestCase { diff --git a/e2etests/stable_test.go b/e2etests/stable_test.go index b48e2b20e..6f03c9570 100644 --- a/e2etests/stable_test.go +++ b/e2etests/stable_test.go @@ -881,6 +881,17 @@ b: { icon: https://icons.terrastruct.com/essentials/004-picture.svg } a -> b +`, + }, + { + name: "arrowhead_labels", + script: ` +a -> b: To err is human, to moo bovine { + source-arrowhead: 1 + target-arrowhead: * { + shape: diamond + } +} `, }, } diff --git a/e2etests/testdata/stable/arrowhead_labels/dagre/board.exp.json b/e2etests/testdata/stable/arrowhead_labels/dagre/board.exp.json new file mode 100644 index 000000000..60b8d8edd --- /dev/null +++ b/e2etests/testdata/stable/arrowhead_labels/dagre/board.exp.json @@ -0,0 +1,130 @@ +{ + "name": "", + "shapes": [ + { + "id": "a", + "type": "", + "pos": { + "x": 0, + "y": 0 + }, + "width": 113, + "height": 126, + "level": 1, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "fields": null, + "methods": null, + "columns": null, + "label": "a", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 13, + "labelHeight": 26, + "labelPosition": "INSIDE_MIDDLE_CENTER" + }, + { + "id": "b", + "type": "", + "pos": { + "x": 0, + "y": 226 + }, + "width": 113, + "height": 126, + "level": 1, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "fields": null, + "methods": null, + "columns": null, + "label": "b", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 13, + "labelHeight": 26, + "labelPosition": "INSIDE_MIDDLE_CENTER" + } + ], + "connections": [ + { + "id": "(a -> b)[0]", + "src": "a", + "srcArrow": "none", + "srcLabel": "1", + "dst": "b", + "dstArrow": "diamond", + "dstLabel": "*", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "To err is human, to moo bovine", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 201, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "labelPercentage": 0, + "route": [ + { + "x": 56.5, + "y": 126 + }, + { + "x": 56.5, + "y": 166 + }, + { + "x": 56.5, + "y": 186 + }, + { + "x": 56.5, + "y": 226 + } + ], + "isCurve": true, + "animated": false, + "tooltip": "", + "icon": null + } + ] +} diff --git a/e2etests/testdata/stable/arrowhead_labels/dagre/sketch.exp.svg b/e2etests/testdata/stable/arrowhead_labels/dagre/sketch.exp.svg new file mode 100644 index 000000000..916fade4d --- /dev/null +++ b/e2etests/testdata/stable/arrowhead_labels/dagre/sketch.exp.svg @@ -0,0 +1,34 @@ + +ab + + +To err is human, to moo bovine \ No newline at end of file diff --git a/e2etests/testdata/stable/arrowhead_labels/elk/board.exp.json b/e2etests/testdata/stable/arrowhead_labels/elk/board.exp.json new file mode 100644 index 000000000..a0458a9db --- /dev/null +++ b/e2etests/testdata/stable/arrowhead_labels/elk/board.exp.json @@ -0,0 +1,121 @@ +{ + "name": "", + "shapes": [ + { + "id": "a", + "type": "", + "pos": { + "x": 12, + "y": 12 + }, + "width": 113, + "height": 126, + "level": 1, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "fields": null, + "methods": null, + "columns": null, + "label": "a", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 13, + "labelHeight": 26, + "labelPosition": "INSIDE_MIDDLE_CENTER" + }, + { + "id": "b", + "type": "", + "pos": { + "x": 526, + "y": 12 + }, + "width": 113, + "height": 126, + "level": 1, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "fields": null, + "methods": null, + "columns": null, + "label": "b", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 13, + "labelHeight": 26, + "labelPosition": "INSIDE_MIDDLE_CENTER" + } + ], + "connections": [ + { + "id": "(a -> b)[0]", + "src": "a", + "srcArrow": "none", + "srcLabel": "1", + "dst": "b", + "dstArrow": "diamond", + "dstLabel": "*", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "To err is human, to moo bovine", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 201, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "labelPercentage": 0, + "route": [ + { + "x": 125, + "y": 75 + }, + { + "x": 526, + "y": 75 + } + ], + "animated": false, + "tooltip": "", + "icon": null + } + ] +} diff --git a/e2etests/testdata/stable/arrowhead_labels/elk/sketch.exp.svg b/e2etests/testdata/stable/arrowhead_labels/elk/sketch.exp.svg new file mode 100644 index 000000000..0b67ee9dc --- /dev/null +++ b/e2etests/testdata/stable/arrowhead_labels/elk/sketch.exp.svg @@ -0,0 +1,34 @@ + +ab + + +To err is human, to moo bovine \ No newline at end of file diff --git a/out/.gitignore b/out/.gitignore new file mode 100644 index 000000000..e69de29bb From 79c1b9d2850cccc10ec13798b6b917b9e0f40953 Mon Sep 17 00:00:00 2001 From: Gavin Nishizawa Date: Wed, 23 Nov 2022 20:14:46 -0800 Subject: [PATCH 2/5] render arrowhead labels --- d2renderers/d2svg/d2svg.go | 38 +++++++++++++++++++ .../arrowhead_adjustment/dagre/sketch.exp.svg | 9 ++++- .../arrowhead_adjustment/elk/sketch.exp.svg | 9 ++++- .../arrowhead_labels/dagre/sketch.exp.svg | 2 +- .../arrowhead_labels/elk/sketch.exp.svg | 2 +- 5 files changed, 56 insertions(+), 4 deletions(-) diff --git a/d2renderers/d2svg/d2svg.go b/d2renderers/d2svg/d2svg.go index ec8e33d55..6ff8738a3 100644 --- a/d2renderers/d2svg/d2svg.go +++ b/d2renderers/d2svg/d2svg.go @@ -447,6 +447,44 @@ func drawConnection(writer io.Writer, connection d2target.Connection, markers ma renderText(connection.Label, x, float64(connection.LabelHeight)), ) } + + length := geo.Route(connection.Route).Length() + if connection.SrcLabel != "" { + // TODO use arrowhead label dimensions + size := float64(connection.FontSize) + position := 0. + if length > 0 { + position = size / length + } + srcLabelTL := label.UnlockedTop.GetPointOnRoute(connection.Route, float64(connection.StrokeWidth), position, size, size) + + textStyle := fmt.Sprintf("text-anchor:%s;font-size:%vpx;fill:%s", "middle", connection.FontSize, "black") + x := srcLabelTL.X + size/2 + y := srcLabelTL.Y + float64(connection.FontSize) + fmt.Fprintf(writer, `%s`, + x, y, + textStyle, + renderText(connection.SrcLabel, x, size), + ) + } + if connection.DstLabel != "" { + // TODO use arrowhead label dimensions + size := float64(connection.FontSize) + position := 1. + if length > 0 { + position -= size / length + } + dstLabelTL := label.UnlockedTop.GetPointOnRoute(connection.Route, float64(connection.StrokeWidth), position, size, size) + + textStyle := fmt.Sprintf("text-anchor:%s;font-size:%vpx;fill:%s", "middle", connection.FontSize, "black") + x := dstLabelTL.X + size/2 + y := dstLabelTL.Y + float64(connection.FontSize) + fmt.Fprintf(writer, `%s`, + x, y, + textStyle, + renderText(connection.DstLabel, x, size), + ) + } } func renderOval(tl *geo.Point, width, height float64, style string) string { diff --git a/e2etests/testdata/stable/arrowhead_adjustment/dagre/sketch.exp.svg b/e2etests/testdata/stable/arrowhead_adjustment/dagre/sketch.exp.svg index 83d10d7a0..0009a91a5 100644 --- a/e2etests/testdata/stable/arrowhead_adjustment/dagre/sketch.exp.svg +++ b/e2etests/testdata/stable/arrowhead_adjustment/dagre/sketch.exp.svg @@ -14,11 +14,18 @@ width="480" height="778" viewBox="-100 -100 480 778">cba cba * \ No newline at end of file diff --git a/e2etests/testdata/stable/arrowhead_adjustment/elk/sketch.exp.svg b/e2etests/testdata/stable/arrowhead_adjustment/elk/sketch.exp.svg index e0d6183d7..d537b4b4b 100644 --- a/e2etests/testdata/stable/arrowhead_adjustment/elk/sketch.exp.svg +++ b/e2etests/testdata/stable/arrowhead_adjustment/elk/sketch.exp.svg @@ -14,11 +14,18 @@ width="749" height="446" viewBox="-88 -88 749 446">cba cba * \ No newline at end of file diff --git a/e2etests/testdata/stable/arrowhead_labels/dagre/sketch.exp.svg b/e2etests/testdata/stable/arrowhead_labels/dagre/sketch.exp.svg index 916fade4d..65b651774 100644 --- a/e2etests/testdata/stable/arrowhead_labels/dagre/sketch.exp.svg +++ b/e2etests/testdata/stable/arrowhead_labels/dagre/sketch.exp.svg @@ -17,7 +17,7 @@ width="401" height="552" viewBox="-144 -100 401 552">ab -To err is human, to moo bovineab -To err is human, to moo bovine