From 9cb7e7f396d0c117779fc0f1cec4feb27f9aaec7 Mon Sep 17 00:00:00 2001 From: Alexander Wang Date: Mon, 13 Feb 2023 22:28:32 -0800 Subject: [PATCH 1/4] scale multi-width unicode --- e2etests/e2e_test.go | 1 + .../dagre_special_ids/dagre/board.exp.json | 36 +- .../dagre_special_ids/dagre/sketch.exp.svg | 6 +- .../dagre_special_ids/elk/board.exp.json | 32 +- .../dagre_special_ids/elk/sketch.exp.svg | 6 +- .../unicode/emojis/dagre/board.exp.json | 179 +++++++ .../unicode/emojis/dagre/sketch.exp.svg | 52 ++ .../unicode/emojis/elk/board.exp.json | 170 ++++++ .../unicode/emojis/elk/sketch.exp.svg | 52 ++ .../japanese-basic/dagre/board.exp.json | 48 ++ .../japanese-basic/dagre/sketch.exp.svg | 52 ++ .../unicode/japanese-basic/elk/board.exp.json | 48 ++ .../unicode/japanese-basic/elk/sketch.exp.svg | 52 ++ .../japanese-full/dagre/board.exp.json | 138 +++++ .../japanese-full/dagre/sketch.exp.svg | 59 +++ .../unicode/japanese-full/elk/board.exp.json | 129 +++++ .../unicode/japanese-full/elk/sketch.exp.svg | 59 +++ .../japanese-mixed/dagre/board.exp.json | 494 ++++++++++++++++++ .../japanese-mixed/dagre/sketch.exp.svg | 52 ++ .../unicode/japanese-mixed/elk/board.exp.json | 449 ++++++++++++++++ .../unicode/japanese-mixed/elk/sketch.exp.svg | 52 ++ .../unicode/with-style/dagre/board.exp.json | 48 ++ .../unicode/with-style/dagre/sketch.exp.svg | 52 ++ .../unicode/with-style/elk/board.exp.json | 48 ++ .../unicode/with-style/elk/sketch.exp.svg | 52 ++ e2etests/unicode_test.go | 56 ++ go.mod | 2 + go.sum | 6 + lib/textmeasure/textmeasure.go | 40 ++ 29 files changed, 2430 insertions(+), 40 deletions(-) create mode 100644 e2etests/testdata/unicode/emojis/dagre/board.exp.json create mode 100644 e2etests/testdata/unicode/emojis/dagre/sketch.exp.svg create mode 100644 e2etests/testdata/unicode/emojis/elk/board.exp.json create mode 100644 e2etests/testdata/unicode/emojis/elk/sketch.exp.svg create mode 100644 e2etests/testdata/unicode/japanese-basic/dagre/board.exp.json create mode 100644 e2etests/testdata/unicode/japanese-basic/dagre/sketch.exp.svg create mode 100644 e2etests/testdata/unicode/japanese-basic/elk/board.exp.json create mode 100644 e2etests/testdata/unicode/japanese-basic/elk/sketch.exp.svg create mode 100644 e2etests/testdata/unicode/japanese-full/dagre/board.exp.json create mode 100644 e2etests/testdata/unicode/japanese-full/dagre/sketch.exp.svg create mode 100644 e2etests/testdata/unicode/japanese-full/elk/board.exp.json create mode 100644 e2etests/testdata/unicode/japanese-full/elk/sketch.exp.svg create mode 100644 e2etests/testdata/unicode/japanese-mixed/dagre/board.exp.json create mode 100644 e2etests/testdata/unicode/japanese-mixed/dagre/sketch.exp.svg create mode 100644 e2etests/testdata/unicode/japanese-mixed/elk/board.exp.json create mode 100644 e2etests/testdata/unicode/japanese-mixed/elk/sketch.exp.svg create mode 100644 e2etests/testdata/unicode/with-style/dagre/board.exp.json create mode 100644 e2etests/testdata/unicode/with-style/dagre/sketch.exp.svg create mode 100644 e2etests/testdata/unicode/with-style/elk/board.exp.json create mode 100644 e2etests/testdata/unicode/with-style/elk/sketch.exp.svg create mode 100644 e2etests/unicode_test.go diff --git a/e2etests/e2e_test.go b/e2etests/e2e_test.go index 41ad5498d..5a5b7c57d 100644 --- a/e2etests/e2e_test.go +++ b/e2etests/e2e_test.go @@ -38,6 +38,7 @@ func TestE2E(t *testing.T) { t.Run("regression", testRegression) t.Run("todo", testTodo) t.Run("measured", testMeasured) + t.Run("unicode", testUnicode) } func testSanity(t *testing.T) { diff --git a/e2etests/testdata/regression/dagre_special_ids/dagre/board.exp.json b/e2etests/testdata/regression/dagre_special_ids/dagre/board.exp.json index d7c736755..2cb1ebfab 100644 --- a/e2etests/testdata/regression/dagre_special_ids/dagre/board.exp.json +++ b/e2etests/testdata/regression/dagre_special_ids/dagre/board.exp.json @@ -91,7 +91,7 @@ "x": 302, "y": 0 }, - "width": 102, + "width": 97, "height": 82, "opacity": 1, "strokeDash": 0, @@ -119,7 +119,7 @@ "italic": false, "bold": true, "underline": false, - "labelWidth": 57, + "labelWidth": 52, "labelHeight": 37, "labelPosition": "INSIDE_MIDDLE_CENTER", "zIndex": 0, @@ -129,7 +129,7 @@ "id": "\"a\\\\yode\"", "type": "rectangle", "pos": { - "x": 464, + "x": 459, "y": 8 }, "width": 94, @@ -170,7 +170,7 @@ "id": "there", "type": "rectangle", "pos": { - "x": 624, + "x": 619, "y": 182 }, "width": 83, @@ -211,7 +211,7 @@ "id": "'a\\\"ode'", "type": "rectangle", "pos": { - "x": 618, + "x": 613, "y": 8 }, "width": 94, @@ -252,7 +252,7 @@ "id": "\"a\\\\node\"", "type": "rectangle", "pos": { - "x": 772, + "x": 767, "y": 8 }, "width": 95, @@ -317,19 +317,19 @@ "labelPercentage": 0, "route": [ { - "x": 511, + "x": 506, "y": 74 }, { - "x": 511, + "x": 506, "y": 120.4 }, { - "x": 533.5, + "x": 528.5, "y": 144.12662337662337 }, { - "x": 623.5, + "x": 618.5, "y": 192.63311688311688 } ], @@ -365,19 +365,19 @@ "labelPercentage": 0, "route": [ { - "x": 665, + "x": 660, "y": 74 }, { - "x": 665, + "x": 660, "y": 120.4 }, { - "x": 665, + "x": 660, "y": 142 }, { - "x": 665, + "x": 660, "y": 182 } ], @@ -413,19 +413,19 @@ "labelPercentage": 0, "route": [ { - "x": 819.5, + "x": 814.5, "y": 74 }, { - "x": 819.5, + "x": 814.5, "y": 120.4 }, { - "x": 796.9, + "x": 791.9, "y": 144 }, { - "x": 706.5, + "x": 701.5, "y": 192 } ], diff --git a/e2etests/testdata/regression/dagre_special_ids/dagre/sketch.exp.svg b/e2etests/testdata/regression/dagre_special_ids/dagre/sketch.exp.svg index 35734e017..5b4018056 100644 --- a/e2etests/testdata/regression/dagre_special_ids/dagre/sketch.exp.svg +++ b/e2etests/testdata/regression/dagre_special_ids/dagre/sketch.exp.svg @@ -3,7 +3,7 @@ id="d2-svg" style="background: white;" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" -width="1071" height="452" viewBox="-102 -102 1071 452">🙈🙈🙈🙈🙈🙈🙈🙈✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️ + + + \ No newline at end of file diff --git a/e2etests/testdata/unicode/emojis/elk/board.exp.json b/e2etests/testdata/unicode/emojis/elk/board.exp.json new file mode 100644 index 000000000..2e524b35a --- /dev/null +++ b/e2etests/testdata/unicode/emojis/elk/board.exp.json @@ -0,0 +1,170 @@ +{ + "name": "", + "fontFamily": "SourceSansPro", + "shapes": [ + { + "id": "a", + "type": "rectangle", + "pos": { + "x": 12, + "y": 12 + }, + "width": 205, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "🙈🙈🙈🙈🙈🙈🙈🙈", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 160, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊", + "type": "rectangle", + "pos": { + "x": 237, + "y": 12 + }, + "width": 833, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 788, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️", + "type": "rectangle", + "pos": { + "x": 201, + "y": 148 + }, + "width": 905, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 860, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + } + ], + "connections": [ + { + "id": "(✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊ -> ☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️)[0]", + "src": "✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊", + "srcArrow": "none", + "srcLabel": "", + "dst": "☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 653.5, + "y": 78 + }, + { + "x": 653.5, + "y": 148 + } + ], + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + } + ] +} diff --git a/e2etests/testdata/unicode/emojis/elk/sketch.exp.svg b/e2etests/testdata/unicode/emojis/elk/sketch.exp.svg new file mode 100644 index 000000000..7ccc8cb4f --- /dev/null +++ b/e2etests/testdata/unicode/emojis/elk/sketch.exp.svg @@ -0,0 +1,52 @@ + +🙈🙈🙈🙈🙈🙈🙈🙈✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️ + + + \ No newline at end of file diff --git a/e2etests/testdata/unicode/japanese-basic/dagre/board.exp.json b/e2etests/testdata/unicode/japanese-basic/dagre/board.exp.json new file mode 100644 index 000000000..4bc654165 --- /dev/null +++ b/e2etests/testdata/unicode/japanese-basic/dagre/board.exp.json @@ -0,0 +1,48 @@ +{ + "name": "", + "fontFamily": "SourceSansPro", + "shapes": [ + { + "id": "a", + "type": "rectangle", + "pos": { + "x": 0, + "y": 0 + }, + "width": 246, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "ああああああああああ", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 201, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + } + ], + "connections": [] +} diff --git a/e2etests/testdata/unicode/japanese-basic/dagre/sketch.exp.svg b/e2etests/testdata/unicode/japanese-basic/dagre/sketch.exp.svg new file mode 100644 index 000000000..b30f6e8c4 --- /dev/null +++ b/e2etests/testdata/unicode/japanese-basic/dagre/sketch.exp.svg @@ -0,0 +1,52 @@ + +ああああああああああ + + + \ No newline at end of file diff --git a/e2etests/testdata/unicode/japanese-basic/elk/board.exp.json b/e2etests/testdata/unicode/japanese-basic/elk/board.exp.json new file mode 100644 index 000000000..7b54eaf15 --- /dev/null +++ b/e2etests/testdata/unicode/japanese-basic/elk/board.exp.json @@ -0,0 +1,48 @@ +{ + "name": "", + "fontFamily": "SourceSansPro", + "shapes": [ + { + "id": "a", + "type": "rectangle", + "pos": { + "x": 12, + "y": 12 + }, + "width": 246, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "ああああああああああ", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 201, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + } + ], + "connections": [] +} diff --git a/e2etests/testdata/unicode/japanese-basic/elk/sketch.exp.svg b/e2etests/testdata/unicode/japanese-basic/elk/sketch.exp.svg new file mode 100644 index 000000000..29d9caa5c --- /dev/null +++ b/e2etests/testdata/unicode/japanese-basic/elk/sketch.exp.svg @@ -0,0 +1,52 @@ + +ああああああああああ + + + \ No newline at end of file diff --git a/e2etests/testdata/unicode/japanese-full/dagre/board.exp.json b/e2etests/testdata/unicode/japanese-full/dagre/board.exp.json new file mode 100644 index 000000000..76f3ee1c3 --- /dev/null +++ b/e2etests/testdata/unicode/japanese-full/dagre/board.exp.json @@ -0,0 +1,138 @@ +{ + "name": "", + "fontFamily": "SourceSansPro", + "shapes": [ + { + "id": "a", + "type": "rectangle", + "pos": { + "x": 0, + "y": 0 + }, + "width": 1382, + "height": 98, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "ある日、トマトが道を歩いていたら、道路の向こうからキュウリがやって来ました。\nトマトは驚いて尋ねました。\n「キュウリさん、どうしてあなたはここにいるのですか?」 キュウリは答えました。「あなたと同じ理由でここにいます。サラダになるために。」", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 1337, + "labelHeight": 53, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "b", + "type": "rectangle", + "pos": { + "x": 8, + "y": 219 + }, + "width": 1367, + "height": 115, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "「バナナは皮を剥いて食べるものです。」", + "fontSize": 55, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 1322, + "labelHeight": 70, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + } + ], + "connections": [ + { + "id": "(a -> b)[0]", + "src": "a", + "srcArrow": "none", + "srcLabel": "", + "dst": "b", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "「バカは死ななきゃ治らない。」", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 289, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "labelPercentage": 0, + "route": [ + { + "x": 691, + "y": 98 + }, + { + "x": 691, + "y": 146.4 + }, + { + "x": 691, + "y": 170.7 + }, + { + "x": 691, + "y": 219.5 + } + ], + "isCurve": true, + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + } + ] +} diff --git a/e2etests/testdata/unicode/japanese-full/dagre/sketch.exp.svg b/e2etests/testdata/unicode/japanese-full/dagre/sketch.exp.svg new file mode 100644 index 000000000..e821ce14a --- /dev/null +++ b/e2etests/testdata/unicode/japanese-full/dagre/sketch.exp.svg @@ -0,0 +1,59 @@ + +ある日、トマトが道を歩いていたら、道路の向こうからキュウリがやって来ました。トマトは驚いて尋ねました。「キュウリさん、どうしてあなたはここにいるのですか?」 キュウリは答えました。「あなたと同じ理由でここにいます。サラダになるために。」「バナナは皮を剥いて食べるものです。」 「バカは死ななきゃ治らない。」 + + + \ No newline at end of file diff --git a/e2etests/testdata/unicode/japanese-full/elk/board.exp.json b/e2etests/testdata/unicode/japanese-full/elk/board.exp.json new file mode 100644 index 000000000..08cca5c14 --- /dev/null +++ b/e2etests/testdata/unicode/japanese-full/elk/board.exp.json @@ -0,0 +1,129 @@ +{ + "name": "", + "fontFamily": "SourceSansPro", + "shapes": [ + { + "id": "a", + "type": "rectangle", + "pos": { + "x": 12, + "y": 12 + }, + "width": 1382, + "height": 98, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "ある日、トマトが道を歩いていたら、道路の向こうからキュウリがやって来ました。\nトマトは驚いて尋ねました。\n「キュウリさん、どうしてあなたはここにいるのですか?」 キュウリは答えました。「あなたと同じ理由でここにいます。サラダになるために。」", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 1337, + "labelHeight": 53, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "b", + "type": "rectangle", + "pos": { + "x": 19, + "y": 271 + }, + "width": 1367, + "height": 115, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "「バナナは皮を剥いて食べるものです。」", + "fontSize": 55, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 1322, + "labelHeight": 70, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + } + ], + "connections": [ + { + "id": "(a -> b)[0]", + "src": "a", + "srcArrow": "none", + "srcLabel": "", + "dst": "b", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "「バカは死ななきゃ治らない。」", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 289, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "labelPercentage": 0, + "route": [ + { + "x": 703, + "y": 110 + }, + { + "x": 703, + "y": 271 + } + ], + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + } + ] +} diff --git a/e2etests/testdata/unicode/japanese-full/elk/sketch.exp.svg b/e2etests/testdata/unicode/japanese-full/elk/sketch.exp.svg new file mode 100644 index 000000000..16635fff6 --- /dev/null +++ b/e2etests/testdata/unicode/japanese-full/elk/sketch.exp.svg @@ -0,0 +1,59 @@ + +ある日、トマトが道を歩いていたら、道路の向こうからキュウリがやって来ました。トマトは驚いて尋ねました。「キュウリさん、どうしてあなたはここにいるのですか?」 キュウリは答えました。「あなたと同じ理由でここにいます。サラダになるために。」「バナナは皮を剥いて食べるものです。」 「バカは死ななきゃ治らない。」 + + + \ No newline at end of file diff --git a/e2etests/testdata/unicode/japanese-mixed/dagre/board.exp.json b/e2etests/testdata/unicode/japanese-mixed/dagre/board.exp.json new file mode 100644 index 000000000..506dfab48 --- /dev/null +++ b/e2etests/testdata/unicode/japanese-mixed/dagre/board.exp.json @@ -0,0 +1,494 @@ +{ + "name": "", + "fontFamily": "SourceSansPro", + "shapes": [ + { + "id": "a", + "type": "rectangle", + "pos": { + "x": 1646, + "y": 0 + }, + "width": 668, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "トマトが赤くなったのはなぜですか?Because it saw the salad dressing!👩‍👩‍👧‍👶👩‍👩‍👧‍👶", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 623, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "b", + "type": "rectangle", + "pos": { + "x": 0, + "y": 166 + }, + "width": 3959, + "height": 171, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "トマトが赤くなったのはなぜですか?Because it saw the salad dressing!👩‍👩‍👧‍👶👩‍👩‍👧‍👶", + "fontSize": 100, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 3914, + "labelHeight": 126, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "c", + "type": "rectangle", + "pos": { + "x": 1817, + "y": 437 + }, + "width": 326, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "今日はTokyoでsushiを食べました", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 281, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "d", + "type": "rectangle", + "pos": { + "x": 888, + "y": 603 + }, + "width": 2184, + "height": 100, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "先日、Shibuyaで友達とshoppingを楽😊しんだ後、ramen屋でdelicious😊なラーメンを食べた。", + "fontSize": 43, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 2139, + "labelHeight": 55, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "e", + "type": "rectangle", + "pos": { + "x": 1877, + "y": 803 + }, + "width": 206, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "English English English", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 161, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "f", + "type": "rectangle", + "pos": { + "x": 1897, + "y": 969 + }, + "width": 165, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "先日先日先日", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 120, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + } + ], + "connections": [ + { + "id": "(a -> b)[0]", + "src": "a", + "srcArrow": "none", + "srcLabel": "", + "dst": "b", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 1979.5, + "y": 66 + }, + { + "x": 1979.5, + "y": 106 + }, + { + "x": 1979.5, + "y": 126 + }, + { + "x": 1979.5, + "y": 166 + } + ], + "isCurve": true, + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + }, + { + "id": "(b -> c)[0]", + "src": "b", + "srcArrow": "none", + "srcLabel": "", + "dst": "c", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 1979.5, + "y": 337 + }, + { + "x": 1979.5, + "y": 377 + }, + { + "x": 1979.5, + "y": 397 + }, + { + "x": 1979.5, + "y": 437 + } + ], + "isCurve": true, + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + }, + { + "id": "(c -> d)[0]", + "src": "c", + "srcArrow": "none", + "srcLabel": "", + "dst": "d", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 1979.5, + "y": 503 + }, + { + "x": 1979.5, + "y": 543 + }, + { + "x": 1979.5, + "y": 563 + }, + { + "x": 1979.5, + "y": 603 + } + ], + "isCurve": true, + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + }, + { + "id": "(d -> e)[0]", + "src": "d", + "srcArrow": "none", + "srcLabel": "", + "dst": "e", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 1979.5, + "y": 703 + }, + { + "x": 1979.5, + "y": 743 + }, + { + "x": 1979.5, + "y": 763 + }, + { + "x": 1979.5, + "y": 803 + } + ], + "isCurve": true, + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + }, + { + "id": "(e -> f)[0]", + "src": "e", + "srcArrow": "none", + "srcLabel": "", + "dst": "f", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 1979.5, + "y": 869 + }, + { + "x": 1979.5, + "y": 909 + }, + { + "x": 1979.5, + "y": 929 + }, + { + "x": 1979.5, + "y": 969 + } + ], + "isCurve": true, + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + } + ] +} diff --git a/e2etests/testdata/unicode/japanese-mixed/dagre/sketch.exp.svg b/e2etests/testdata/unicode/japanese-mixed/dagre/sketch.exp.svg new file mode 100644 index 000000000..77274b84b --- /dev/null +++ b/e2etests/testdata/unicode/japanese-mixed/dagre/sketch.exp.svg @@ -0,0 +1,52 @@ + +トマトが赤くなったのはなぜですか?Because it saw the salad dressing!👩‍👩‍👧‍👶👩‍👩‍👧‍👶トマトが赤くなったのはなぜですか?Because it saw the salad dressing!👩‍👩‍👧‍👶👩‍👩‍👧‍👶今日はTokyoでsushiを食べました先日、Shibuyaで友達とshoppingを楽😊しんだ後、ramen屋でdelicious😊なラーメンを食べた。English English English先日先日先日 + + + \ No newline at end of file diff --git a/e2etests/testdata/unicode/japanese-mixed/elk/board.exp.json b/e2etests/testdata/unicode/japanese-mixed/elk/board.exp.json new file mode 100644 index 000000000..622db44fb --- /dev/null +++ b/e2etests/testdata/unicode/japanese-mixed/elk/board.exp.json @@ -0,0 +1,449 @@ +{ + "name": "", + "fontFamily": "SourceSansPro", + "shapes": [ + { + "id": "a", + "type": "rectangle", + "pos": { + "x": 1657, + "y": 12 + }, + "width": 668, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "トマトが赤くなったのはなぜですか?Because it saw the salad dressing!👩‍👩‍👧‍👶👩‍👩‍👧‍👶", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 623, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "b", + "type": "rectangle", + "pos": { + "x": 12, + "y": 148 + }, + "width": 3959, + "height": 171, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "トマトが赤くなったのはなぜですか?Because it saw the salad dressing!👩‍👩‍👧‍👶👩‍👩‍👧‍👶", + "fontSize": 100, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 3914, + "labelHeight": 126, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "c", + "type": "rectangle", + "pos": { + "x": 1828, + "y": 389 + }, + "width": 326, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "今日はTokyoでsushiを食べました", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 281, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "d", + "type": "rectangle", + "pos": { + "x": 899, + "y": 525 + }, + "width": 2184, + "height": 100, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "先日、Shibuyaで友達とshoppingを楽😊しんだ後、ramen屋でdelicious😊なラーメンを食べた。", + "fontSize": 43, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 2139, + "labelHeight": 55, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "e", + "type": "rectangle", + "pos": { + "x": 1888, + "y": 695 + }, + "width": 206, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "English English English", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 161, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "f", + "type": "rectangle", + "pos": { + "x": 1909, + "y": 831 + }, + "width": 165, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "先日先日先日", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 120, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + } + ], + "connections": [ + { + "id": "(a -> b)[0]", + "src": "a", + "srcArrow": "none", + "srcLabel": "", + "dst": "b", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 1991.5, + "y": 78 + }, + { + "x": 1991.5, + "y": 148 + } + ], + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + }, + { + "id": "(b -> c)[0]", + "src": "b", + "srcArrow": "none", + "srcLabel": "", + "dst": "c", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 1991.5, + "y": 319 + }, + { + "x": 1991.5, + "y": 389 + } + ], + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + }, + { + "id": "(c -> d)[0]", + "src": "c", + "srcArrow": "none", + "srcLabel": "", + "dst": "d", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 1991.5, + "y": 455 + }, + { + "x": 1991.5, + "y": 525 + } + ], + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + }, + { + "id": "(d -> e)[0]", + "src": "d", + "srcArrow": "none", + "srcLabel": "", + "dst": "e", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 1991.5, + "y": 625 + }, + { + "x": 1991.5, + "y": 695 + } + ], + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + }, + { + "id": "(e -> f)[0]", + "src": "e", + "srcArrow": "none", + "srcLabel": "", + "dst": "f", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 1991.5, + "y": 761 + }, + { + "x": 1991.5, + "y": 831 + } + ], + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + } + ] +} diff --git a/e2etests/testdata/unicode/japanese-mixed/elk/sketch.exp.svg b/e2etests/testdata/unicode/japanese-mixed/elk/sketch.exp.svg new file mode 100644 index 000000000..6edeb9aa3 --- /dev/null +++ b/e2etests/testdata/unicode/japanese-mixed/elk/sketch.exp.svg @@ -0,0 +1,52 @@ + +トマトが赤くなったのはなぜですか?Because it saw the salad dressing!👩‍👩‍👧‍👶👩‍👩‍👧‍👶トマトが赤くなったのはなぜですか?Because it saw the salad dressing!👩‍👩‍👧‍👶👩‍👩‍👧‍👶今日はTokyoでsushiを食べました先日、Shibuyaで友達とshoppingを楽😊しんだ後、ramen屋でdelicious😊なラーメンを食べた。English English English先日先日先日 + + + \ No newline at end of file diff --git a/e2etests/testdata/unicode/with-style/dagre/board.exp.json b/e2etests/testdata/unicode/with-style/dagre/board.exp.json new file mode 100644 index 000000000..475a72efb --- /dev/null +++ b/e2etests/testdata/unicode/with-style/dagre/board.exp.json @@ -0,0 +1,48 @@ +{ + "name": "", + "fontFamily": "SourceSansPro", + "shapes": [ + { + "id": "おやすみなさい", + "type": "rectangle", + "pos": { + "x": 0, + "y": 0 + }, + "width": 185, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 15, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": true, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "おやすみなさい", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 140, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + } + ], + "connections": [] +} diff --git a/e2etests/testdata/unicode/with-style/dagre/sketch.exp.svg b/e2etests/testdata/unicode/with-style/dagre/sketch.exp.svg new file mode 100644 index 000000000..64a18001c --- /dev/null +++ b/e2etests/testdata/unicode/with-style/dagre/sketch.exp.svg @@ -0,0 +1,52 @@ + +おやすみなさい + + + \ No newline at end of file diff --git a/e2etests/testdata/unicode/with-style/elk/board.exp.json b/e2etests/testdata/unicode/with-style/elk/board.exp.json new file mode 100644 index 000000000..201320c67 --- /dev/null +++ b/e2etests/testdata/unicode/with-style/elk/board.exp.json @@ -0,0 +1,48 @@ +{ + "name": "", + "fontFamily": "SourceSansPro", + "shapes": [ + { + "id": "おやすみなさい", + "type": "rectangle", + "pos": { + "x": 12, + "y": 12 + }, + "width": 185, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 15, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": true, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "おやすみなさい", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 140, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + } + ], + "connections": [] +} diff --git a/e2etests/testdata/unicode/with-style/elk/sketch.exp.svg b/e2etests/testdata/unicode/with-style/elk/sketch.exp.svg new file mode 100644 index 000000000..fa4d7d8a1 --- /dev/null +++ b/e2etests/testdata/unicode/with-style/elk/sketch.exp.svg @@ -0,0 +1,52 @@ + +おやすみなさい + + + \ No newline at end of file diff --git a/e2etests/unicode_test.go b/e2etests/unicode_test.go new file mode 100644 index 000000000..0629cdf09 --- /dev/null +++ b/e2etests/unicode_test.go @@ -0,0 +1,56 @@ +package e2etests + +import ( + _ "embed" + "testing" +) + +func testUnicode(t *testing.T) { + tcs := []testCase{ + { + name: "japanese-basic", + script: `a: ああああああああああ +`, + }, + { + name: "japanese-full", + script: `a: "ある日、トマトが道を歩いていたら、道路の向こうからキュウリがやって来ました。\nトマトは驚いて尋ねました。\n「キュウリさん、どうしてあなたはここにいるのですか?」 キュウリは答えました。「あなたと同じ理由でここにいます。サラダになるために。」" + +b: "「バナナは皮を剥いて食べるものです。」" { + style.font-size: 55 +} + +a -> b: 「バカは死ななきゃ治らない。」 +`, + }, + { + name: "emojis", + script: `a: 🙈🙈🙈🙈🙈🙈🙈🙈 +✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊ -> ☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️ +`, + }, + { + name: "with-style", + script: `おやすみなさい: {style.stroke-width: 15; style.double-border: true} +`, + }, + { + name: "japanese-mixed", + script: `a: "トマトが赤くなったのはなぜですか?Because it saw the salad dressing!👩‍👩‍👧‍👶👩‍👩‍👧‍👶" +b: "トマトが赤くなったのはなぜですか?Because it saw the salad dressing!👩‍👩‍👧‍👶👩‍👩‍👧‍👶" { + style.font-size: 100 +} +c: 今日はTokyoでsushiを食べました +d: 先日、Shibuyaで友達とshoppingを楽😊しんだ後、ramen屋でdelicious😊なラーメンを食べた。{ + style.font-size: 43 +} +e: English English English +f: 先日先日先日 +a -> b -> c -> d -> e -> f + +`, + }, + } + + runa(t, tcs) +} diff --git a/go.mod b/go.mod index feec9b43c..c8986bd2f 100644 --- a/go.mod +++ b/go.mod @@ -10,8 +10,10 @@ require ( github.com/fsnotify/fsnotify v1.6.0 github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 github.com/lucasb-eyer/go-colorful v1.2.0 + github.com/mattn/go-runewidth v0.0.14 github.com/mazznoer/csscolorparser v0.1.3 github.com/playwright-community/playwright-go v0.2000.1 + github.com/rivo/uniseg v0.4.3 github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.8.1 github.com/yuin/goldmark v1.5.3 diff --git a/go.sum b/go.sum index 1f31c5679..9b83338c3 100644 --- a/go.sum +++ b/go.sum @@ -115,6 +115,8 @@ github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= +github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mazznoer/csscolorparser v0.1.3 h1:vug4zh6loQxAUxfU1DZEu70gTPufDPspamZlHAkKcxE= github.com/mazznoer/csscolorparser v0.1.3/go.mod h1:Aj22+L/rYN/Y6bj3bYqO3N6g1dtdHtGfQ32xZ5PJQic= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= @@ -128,6 +130,10 @@ github.com/playwright-community/playwright-go v0.2000.1/go.mod h1:1y9cM9b9dVHnuR github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rivo/uniseg v0.4.3 h1:utMvzDsuh3suAEnhH0RdHmoPbU648o6CvXxTx4SBMOw= +github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= diff --git a/lib/textmeasure/textmeasure.go b/lib/textmeasure/textmeasure.go index b46cc1711..cdf9c811c 100644 --- a/lib/textmeasure/textmeasure.go +++ b/lib/textmeasure/textmeasure.go @@ -5,10 +5,12 @@ package textmeasure import ( "math" + "strings" "unicode" "unicode/utf8" "github.com/golang/freetype/truetype" + "github.com/rivo/uniseg" "oss.terrastruct.com/d2/d2renderers/d2fonts" "oss.terrastruct.com/d2/lib/geo" @@ -166,6 +168,44 @@ func (r *Ruler) addFontSize(font d2fonts.Font) { func (t *Ruler) Measure(font d2fonts.Font, s string) (width, height int) { w, h := t.MeasurePrecise(font, s) + // Weird unicode stuff is going on when this is true + // See https://github.com/rivo/uniseg#grapheme-clusters + // This method is a good-enough approximation. It overshoots, but not by much. + // I suspect we need to import a font with the right glyphs to get the precise measurements + // but Hans fonts are heavy. + if uniseg.GraphemeClusterCount(s) != len(s) { + for _, line := range strings.Split(s, "\n") { + lineW, _ := t.MeasurePrecise(font, line) + gr := uniseg.NewGraphemes(line) + + mono := d2fonts.SourceCodePro.Font(font.Size, font.Style) + for gr.Next() { + if gr.Width() == 1 { + continue + } + // For each grapheme which doesn't have width=1, the ruler measured wrongly. + // So, replace the measured width with a scaled measurement of a monospace version + var prevRune rune + dot := t.Orig.Copy() + b := newRect() + for _, r := range gr.Runes() { + var control bool + dot, control = t.controlRune(r, dot, font) + if control { + continue + } + + var bounds *rect + _, _, bounds, dot = t.atlases[font].DrawRune(prevRune, r, dot) + b = b.union(bounds) + prevRune = r + } + lineW -= b.w() + lineW += t.spaceWidth(mono) * float64(gr.Width()) + } + w = math.Max(w, lineW) + } + } return int(math.Ceil(w)), int(math.Ceil(h)) } From 156c9742411207981766a4f67aaee52b932d4855 Mon Sep 17 00:00:00 2001 From: Alexander Wang Date: Tue, 14 Feb 2023 10:13:23 -0800 Subject: [PATCH 2/4] unicode tests --- .../dagre_special_ids/dagre/board.exp.json | 36 +- .../dagre_special_ids/dagre/sketch.exp.svg | 6 +- .../dagre_special_ids/elk/board.exp.json | 32 +- .../dagre_special_ids/elk/sketch.exp.svg | 6 +- .../unicode/chinese/dagre/board.exp.json | 137 +++ .../unicode/chinese/dagre/sketch.exp.svg | 820 ++++++++++++++++ .../unicode/chinese/elk/board.exp.json | 128 +++ .../unicode/chinese/elk/sketch.exp.svg | 820 ++++++++++++++++ .../unicode/korean/dagre/board.exp.json | 48 + .../unicode/korean/dagre/sketch.exp.svg | 52 + .../unicode/korean/elk/board.exp.json | 48 + .../unicode/korean/elk/sketch.exp.svg | 52 + .../mixed-language-2/dagre/board.exp.json | 909 ++++++++++++++++++ .../mixed-language-2/dagre/sketch.exp.svg | 52 + .../mixed-language-2/elk/board.exp.json | 909 ++++++++++++++++++ .../mixed-language-2/elk/sketch.exp.svg | 52 + .../mixed-language/dagre/board.exp.json | 226 +++++ .../mixed-language/dagre/sketch.exp.svg | 818 ++++++++++++++++ .../unicode/mixed-language/elk/board.exp.json | 216 +++++ .../unicode/mixed-language/elk/sketch.exp.svg | 818 ++++++++++++++++ e2etests/unicode_test.go | 78 ++ go.mod | 1 - go.sum | 4 - lib/textmeasure/markdown.go | 2 + lib/textmeasure/textmeasure.go | 10 +- 25 files changed, 6233 insertions(+), 47 deletions(-) create mode 100644 e2etests/testdata/unicode/chinese/dagre/board.exp.json create mode 100644 e2etests/testdata/unicode/chinese/dagre/sketch.exp.svg create mode 100644 e2etests/testdata/unicode/chinese/elk/board.exp.json create mode 100644 e2etests/testdata/unicode/chinese/elk/sketch.exp.svg create mode 100644 e2etests/testdata/unicode/korean/dagre/board.exp.json create mode 100644 e2etests/testdata/unicode/korean/dagre/sketch.exp.svg create mode 100644 e2etests/testdata/unicode/korean/elk/board.exp.json create mode 100644 e2etests/testdata/unicode/korean/elk/sketch.exp.svg create mode 100644 e2etests/testdata/unicode/mixed-language-2/dagre/board.exp.json create mode 100644 e2etests/testdata/unicode/mixed-language-2/dagre/sketch.exp.svg create mode 100644 e2etests/testdata/unicode/mixed-language-2/elk/board.exp.json create mode 100644 e2etests/testdata/unicode/mixed-language-2/elk/sketch.exp.svg create mode 100644 e2etests/testdata/unicode/mixed-language/dagre/board.exp.json create mode 100644 e2etests/testdata/unicode/mixed-language/dagre/sketch.exp.svg create mode 100644 e2etests/testdata/unicode/mixed-language/elk/board.exp.json create mode 100644 e2etests/testdata/unicode/mixed-language/elk/sketch.exp.svg diff --git a/e2etests/testdata/regression/dagre_special_ids/dagre/board.exp.json b/e2etests/testdata/regression/dagre_special_ids/dagre/board.exp.json index 2cb1ebfab..d7c736755 100644 --- a/e2etests/testdata/regression/dagre_special_ids/dagre/board.exp.json +++ b/e2etests/testdata/regression/dagre_special_ids/dagre/board.exp.json @@ -91,7 +91,7 @@ "x": 302, "y": 0 }, - "width": 97, + "width": 102, "height": 82, "opacity": 1, "strokeDash": 0, @@ -119,7 +119,7 @@ "italic": false, "bold": true, "underline": false, - "labelWidth": 52, + "labelWidth": 57, "labelHeight": 37, "labelPosition": "INSIDE_MIDDLE_CENTER", "zIndex": 0, @@ -129,7 +129,7 @@ "id": "\"a\\\\yode\"", "type": "rectangle", "pos": { - "x": 459, + "x": 464, "y": 8 }, "width": 94, @@ -170,7 +170,7 @@ "id": "there", "type": "rectangle", "pos": { - "x": 619, + "x": 624, "y": 182 }, "width": 83, @@ -211,7 +211,7 @@ "id": "'a\\\"ode'", "type": "rectangle", "pos": { - "x": 613, + "x": 618, "y": 8 }, "width": 94, @@ -252,7 +252,7 @@ "id": "\"a\\\\node\"", "type": "rectangle", "pos": { - "x": 767, + "x": 772, "y": 8 }, "width": 95, @@ -317,19 +317,19 @@ "labelPercentage": 0, "route": [ { - "x": 506, + "x": 511, "y": 74 }, { - "x": 506, + "x": 511, "y": 120.4 }, { - "x": 528.5, + "x": 533.5, "y": 144.12662337662337 }, { - "x": 618.5, + "x": 623.5, "y": 192.63311688311688 } ], @@ -365,19 +365,19 @@ "labelPercentage": 0, "route": [ { - "x": 660, + "x": 665, "y": 74 }, { - "x": 660, + "x": 665, "y": 120.4 }, { - "x": 660, + "x": 665, "y": 142 }, { - "x": 660, + "x": 665, "y": 182 } ], @@ -413,19 +413,19 @@ "labelPercentage": 0, "route": [ { - "x": 814.5, + "x": 819.5, "y": 74 }, { - "x": 814.5, + "x": 819.5, "y": 120.4 }, { - "x": 791.9, + "x": 796.9, "y": 144 }, { - "x": 701.5, + "x": 706.5, "y": 192 } ], diff --git a/e2etests/testdata/regression/dagre_special_ids/dagre/sketch.exp.svg b/e2etests/testdata/regression/dagre_special_ids/dagre/sketch.exp.svg index 5b4018056..35734e017 100644 --- a/e2etests/testdata/regression/dagre_special_ids/dagre/sketch.exp.svg +++ b/e2etests/testdata/regression/dagre_special_ids/dagre/sketch.exp.svg @@ -3,7 +3,7 @@ id="d2-svg" style="background: white;" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" -width="1066" height="452" viewBox="-102 -102 1066 452">

床前明月光,

+

疑是地上霜。

+

举头望明月,

+

低头思故乡。

+
所以,即使夏天很热 + + + \ No newline at end of file diff --git a/e2etests/testdata/unicode/chinese/elk/board.exp.json b/e2etests/testdata/unicode/chinese/elk/board.exp.json new file mode 100644 index 000000000..a6fe84f83 --- /dev/null +++ b/e2etests/testdata/unicode/chinese/elk/board.exp.json @@ -0,0 +1,128 @@ +{ + "name": "", + "fontFamily": "SourceSansPro", + "shapes": [ + { + "id": "poem", + "type": "text", + "pos": { + "x": 66, + "y": 12 + }, + "width": 118, + "height": 144, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "transparent", + "stroke": "#0A0F25", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "床前明月光,\n\n疑是地上霜。\n\n举头望明月,\n\n低头思故乡。", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "markdown", + "color": "#0A0F25", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 118, + "labelHeight": 144, + "zIndex": 0, + "level": 1 + }, + { + "id": "a", + "type": "rectangle", + "pos": { + "x": 12, + "y": 226 + }, + "width": 226, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "所以,即使夏天很热", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 181, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + } + ], + "connections": [ + { + "id": "(poem -> a)[0]", + "src": "poem", + "srcArrow": "none", + "srcLabel": "", + "dst": "a", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 125, + "y": 156 + }, + { + "x": 125, + "y": 226 + } + ], + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + } + ] +} diff --git a/e2etests/testdata/unicode/chinese/elk/sketch.exp.svg b/e2etests/testdata/unicode/chinese/elk/sketch.exp.svg new file mode 100644 index 000000000..a2ddcd832 --- /dev/null +++ b/e2etests/testdata/unicode/chinese/elk/sketch.exp.svg @@ -0,0 +1,820 @@ + +

床前明月光,

+

疑是地上霜。

+

举头望明月,

+

低头思故乡。

+
所以,即使夏天很热 + + +
\ No newline at end of file diff --git a/e2etests/testdata/unicode/korean/dagre/board.exp.json b/e2etests/testdata/unicode/korean/dagre/board.exp.json new file mode 100644 index 000000000..57d6026fc --- /dev/null +++ b/e2etests/testdata/unicode/korean/dagre/board.exp.json @@ -0,0 +1,48 @@ +{ + "name": "", + "fontFamily": "SourceSansPro", + "shapes": [ + { + "id": "a", + "type": "rectangle", + "pos": { + "x": 0, + "y": 0 + }, + "width": 205, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "고생끝에낙이온다", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 160, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + } + ], + "connections": [] +} diff --git a/e2etests/testdata/unicode/korean/dagre/sketch.exp.svg b/e2etests/testdata/unicode/korean/dagre/sketch.exp.svg new file mode 100644 index 000000000..0f7567734 --- /dev/null +++ b/e2etests/testdata/unicode/korean/dagre/sketch.exp.svg @@ -0,0 +1,52 @@ + +고생끝에낙이온다 + + + \ No newline at end of file diff --git a/e2etests/testdata/unicode/korean/elk/board.exp.json b/e2etests/testdata/unicode/korean/elk/board.exp.json new file mode 100644 index 000000000..bf70b2118 --- /dev/null +++ b/e2etests/testdata/unicode/korean/elk/board.exp.json @@ -0,0 +1,48 @@ +{ + "name": "", + "fontFamily": "SourceSansPro", + "shapes": [ + { + "id": "a", + "type": "rectangle", + "pos": { + "x": 12, + "y": 12 + }, + "width": 205, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "고생끝에낙이온다", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 160, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + } + ], + "connections": [] +} diff --git a/e2etests/testdata/unicode/korean/elk/sketch.exp.svg b/e2etests/testdata/unicode/korean/elk/sketch.exp.svg new file mode 100644 index 000000000..b61a68b53 --- /dev/null +++ b/e2etests/testdata/unicode/korean/elk/sketch.exp.svg @@ -0,0 +1,52 @@ + +고생끝에낙이온다 + + + \ No newline at end of file diff --git a/e2etests/testdata/unicode/mixed-language-2/dagre/board.exp.json b/e2etests/testdata/unicode/mixed-language-2/dagre/board.exp.json new file mode 100644 index 000000000..bb5c666f8 --- /dev/null +++ b/e2etests/testdata/unicode/mixed-language-2/dagre/board.exp.json @@ -0,0 +1,909 @@ +{ + "name": "", + "fontFamily": "SourceSansPro", + "shapes": [ + { + "id": "a", + "type": "rectangle", + "pos": { + "x": 0, + "y": 0 + }, + "width": 240, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "我 (wǒ) - Mandarin Chinese", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 195, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "b", + "type": "rectangle", + "pos": { + "x": 300, + "y": 0 + }, + "width": 241, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "ສະບາຍດີ (sabaai dii) - Lao", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 196, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "c", + "type": "rectangle", + "pos": { + "x": 601, + "y": 0 + }, + "width": 301, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "ជំរាបសួរ (jomreab suor) - Khmer", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 256, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "\"สวัสดี (sà-wàt-dii) - Thai\"", + "type": "rectangle", + "pos": { + "x": 962, + "y": 0 + }, + "width": 244, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "สวัสดี (sà-wàt-dii) - Thai", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 199, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "\"ສະບາຍດີ (sabaidee) - Lao\"", + "type": "rectangle", + "pos": { + "x": 1266, + "y": 0 + }, + "width": 237, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "ສະບາຍດີ (sabaidee) - Lao", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 192, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "\"ဟယ်လို (helaou) - Burmese\"", + "type": "rectangle", + "pos": { + "x": 1563, + "y": 0 + }, + "width": 247, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "ဟယ်လို (helaou) - Burmese", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 202, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "\"mari (まり) - Ainu\"", + "type": "rectangle", + "pos": { + "x": 1870, + "y": 0 + }, + "width": 176, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "mari (まり) - Ainu", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 131, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "\"cào (草) - Zhuang\"", + "type": "rectangle", + "pos": { + "x": 2106, + "y": 0 + }, + "width": 173, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "cào (草) - Zhuang", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 128, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "\"күнтізбе (kúntízbe) - Kazakh\"", + "type": "rectangle", + "pos": { + "x": 2339, + "y": 0 + }, + "width": 282, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "күнтізбе (kúntízbe) - Kazakh", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 237, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "\"բարև (barev) - Armenian\"", + "type": "rectangle", + "pos": { + "x": 2681, + "y": 0 + }, + "width": 224, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "բարև (barev) - Armenian", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 179, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "\"монгол (mongol) - Mongolian\"", + "type": "rectangle", + "pos": { + "x": 2965, + "y": 0 + }, + "width": 265, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "монгол (mongol) - Mongolian", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 220, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "\"mila (میلا) - Uyghur\"", + "type": "rectangle", + "pos": { + "x": 3290, + "y": 0 + }, + "width": 199, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "mila (میلا) - Uyghur", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 154, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "\"નમસ્તે (namaste) - Gujarati\"", + "type": "rectangle", + "pos": { + "x": 3549, + "y": 0 + }, + "width": 255, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "નમસ્તે (namaste) - Gujarati", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 210, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "\"漢字 (kanji) - Japanese\"", + "type": "rectangle", + "pos": { + "x": 3864, + "y": 0 + }, + "width": 213, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "漢字 (kanji) - Japanese", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 168, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "\"위 (wi) - Korean\"", + "type": "rectangle", + "pos": { + "x": 4137, + "y": 0 + }, + "width": 158, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "위 (wi) - Korean", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 113, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "\"吾哥 (ngǔgāi) - Cantonese\"", + "type": "rectangle", + "pos": { + "x": 4355, + "y": 0 + }, + "width": 238, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "吾哥 (ngǔgāi) - Cantonese", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 193, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "\"မင်္ဂလာပါ (mingalaba) - Burmese\"", + "type": "rectangle", + "pos": { + "x": 4653, + "y": 0 + }, + "width": 307, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "မင်္ဂလာပါ (mingalaba) - Burmese", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 262, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "\"сайн уу (sain uu) - Mongolian\"", + "type": "rectangle", + "pos": { + "x": 5020, + "y": 0 + }, + "width": 264, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "сайн уу (sain uu) - Mongolian", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 219, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "\"ਸਤਿ ਸ੍ਰੀ ਅਕਾਲ (sat sri akal) - Punjabi\"", + "type": "rectangle", + "pos": { + "x": 5344, + "y": 0 + }, + "width": 328, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "ਸਤਿ ਸ੍ਰੀ ਅਕਾਲ (sat sri akal) - Punjabi", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 283, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "\"你吃了吗 (ní chī le ma) - Mandarin Chinese\"", + "type": "rectangle", + "pos": { + "x": 5732, + "y": 0 + }, + "width": 370, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "你吃了吗 (ní chī le ma) - Mandarin Chinese", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 325, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "\"饭 (fan) - Zhuang\"", + "type": "rectangle", + "pos": { + "x": 6162, + "y": 0 + }, + "width": 167, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "饭 (fan) - Zhuang", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 122, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "مەن سىزنى ياخشى ئۈمىد ق", + "type": "rectangle", + "pos": { + "x": 6389, + "y": 0 + }, + "width": 266, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "مەن سىزنى ياخشى ئۈمىد ق", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 221, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + } + ], + "connections": [] +} diff --git a/e2etests/testdata/unicode/mixed-language-2/dagre/sketch.exp.svg b/e2etests/testdata/unicode/mixed-language-2/dagre/sketch.exp.svg new file mode 100644 index 000000000..2947dbba3 --- /dev/null +++ b/e2etests/testdata/unicode/mixed-language-2/dagre/sketch.exp.svg @@ -0,0 +1,52 @@ + +我 (wǒ) - Mandarin Chineseສະບາຍດີ (sabaai dii) - Laoជំរាបសួរ (jomreab suor) - Khmerสวัสดี (sà-wàt-dii) - Thaiສະບາຍດີ (sabaidee) - Laoဟယ်လို (helaou) - Burmesemari (まり) - Ainucào (草) - Zhuangкүнтізбе (kúntízbe) - Kazakhբարև (barev) - Armenianмонгол (mongol) - Mongolianmila (میلا) - Uyghurનમસ્તે (namaste) - Gujarati漢字 (kanji) - Japanese위 (wi) - Korean吾哥 (ngǔgāi) - Cantoneseမင်္ဂလာပါ (mingalaba) - Burmeseсайн уу (sain uu) - Mongolianਸਤਿ ਸ੍ਰੀ ਅਕਾਲ (sat sri akal) - Punjabi你吃了吗 (ní chī le ma) - Mandarin Chinese饭 (fan) - Zhuangمەن سىزنى ياخشى ئۈمىد ق + + + \ No newline at end of file diff --git a/e2etests/testdata/unicode/mixed-language-2/elk/board.exp.json b/e2etests/testdata/unicode/mixed-language-2/elk/board.exp.json new file mode 100644 index 000000000..6f5f1cbd9 --- /dev/null +++ b/e2etests/testdata/unicode/mixed-language-2/elk/board.exp.json @@ -0,0 +1,909 @@ +{ + "name": "", + "fontFamily": "SourceSansPro", + "shapes": [ + { + "id": "a", + "type": "rectangle", + "pos": { + "x": 12, + "y": 12 + }, + "width": 240, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "我 (wǒ) - Mandarin Chinese", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 195, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "b", + "type": "rectangle", + "pos": { + "x": 272, + "y": 12 + }, + "width": 241, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "ສະບາຍດີ (sabaai dii) - Lao", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 196, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "c", + "type": "rectangle", + "pos": { + "x": 533, + "y": 12 + }, + "width": 301, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "ជំរាបសួរ (jomreab suor) - Khmer", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 256, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "\"สวัสดี (sà-wàt-dii) - Thai\"", + "type": "rectangle", + "pos": { + "x": 854, + "y": 12 + }, + "width": 244, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "สวัสดี (sà-wàt-dii) - Thai", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 199, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "\"ສະບາຍດີ (sabaidee) - Lao\"", + "type": "rectangle", + "pos": { + "x": 1118, + "y": 12 + }, + "width": 237, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "ສະບາຍດີ (sabaidee) - Lao", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 192, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "\"ဟယ်လို (helaou) - Burmese\"", + "type": "rectangle", + "pos": { + "x": 1375, + "y": 12 + }, + "width": 247, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "ဟယ်လို (helaou) - Burmese", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 202, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "\"mari (まり) - Ainu\"", + "type": "rectangle", + "pos": { + "x": 1642, + "y": 12 + }, + "width": 176, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "mari (まり) - Ainu", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 131, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "\"cào (草) - Zhuang\"", + "type": "rectangle", + "pos": { + "x": 1838, + "y": 12 + }, + "width": 173, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "cào (草) - Zhuang", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 128, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "\"күнтізбе (kúntízbe) - Kazakh\"", + "type": "rectangle", + "pos": { + "x": 2031, + "y": 12 + }, + "width": 282, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "күнтізбе (kúntízbe) - Kazakh", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 237, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "\"բարև (barev) - Armenian\"", + "type": "rectangle", + "pos": { + "x": 2333, + "y": 12 + }, + "width": 224, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "բարև (barev) - Armenian", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 179, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "\"монгол (mongol) - Mongolian\"", + "type": "rectangle", + "pos": { + "x": 2577, + "y": 12 + }, + "width": 265, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "монгол (mongol) - Mongolian", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 220, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "\"mila (میلا) - Uyghur\"", + "type": "rectangle", + "pos": { + "x": 2862, + "y": 12 + }, + "width": 199, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "mila (میلا) - Uyghur", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 154, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "\"નમસ્તે (namaste) - Gujarati\"", + "type": "rectangle", + "pos": { + "x": 3081, + "y": 12 + }, + "width": 255, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "નમસ્તે (namaste) - Gujarati", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 210, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "\"漢字 (kanji) - Japanese\"", + "type": "rectangle", + "pos": { + "x": 3356, + "y": 12 + }, + "width": 213, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "漢字 (kanji) - Japanese", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 168, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "\"위 (wi) - Korean\"", + "type": "rectangle", + "pos": { + "x": 3589, + "y": 12 + }, + "width": 158, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "위 (wi) - Korean", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 113, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "\"吾哥 (ngǔgāi) - Cantonese\"", + "type": "rectangle", + "pos": { + "x": 3767, + "y": 12 + }, + "width": 238, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "吾哥 (ngǔgāi) - Cantonese", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 193, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "\"မင်္ဂလာပါ (mingalaba) - Burmese\"", + "type": "rectangle", + "pos": { + "x": 4025, + "y": 12 + }, + "width": 307, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "မင်္ဂလာပါ (mingalaba) - Burmese", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 262, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "\"сайн уу (sain uu) - Mongolian\"", + "type": "rectangle", + "pos": { + "x": 4352, + "y": 12 + }, + "width": 264, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "сайн уу (sain uu) - Mongolian", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 219, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "\"ਸਤਿ ਸ੍ਰੀ ਅਕਾਲ (sat sri akal) - Punjabi\"", + "type": "rectangle", + "pos": { + "x": 4636, + "y": 12 + }, + "width": 328, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "ਸਤਿ ਸ੍ਰੀ ਅਕਾਲ (sat sri akal) - Punjabi", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 283, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "\"你吃了吗 (ní chī le ma) - Mandarin Chinese\"", + "type": "rectangle", + "pos": { + "x": 4984, + "y": 12 + }, + "width": 370, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "你吃了吗 (ní chī le ma) - Mandarin Chinese", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 325, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "\"饭 (fan) - Zhuang\"", + "type": "rectangle", + "pos": { + "x": 5374, + "y": 12 + }, + "width": 167, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "饭 (fan) - Zhuang", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 122, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "مەن سىزنى ياخشى ئۈمىد ق", + "type": "rectangle", + "pos": { + "x": 5561, + "y": 12 + }, + "width": 266, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "مەن سىزنى ياخشى ئۈمىد ق", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 221, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + } + ], + "connections": [] +} diff --git a/e2etests/testdata/unicode/mixed-language-2/elk/sketch.exp.svg b/e2etests/testdata/unicode/mixed-language-2/elk/sketch.exp.svg new file mode 100644 index 000000000..1e19459bf --- /dev/null +++ b/e2etests/testdata/unicode/mixed-language-2/elk/sketch.exp.svg @@ -0,0 +1,52 @@ + +我 (wǒ) - Mandarin Chineseສະບາຍດີ (sabaai dii) - Laoជំរាបសួរ (jomreab suor) - Khmerสวัสดี (sà-wàt-dii) - Thaiສະບາຍດີ (sabaidee) - Laoဟယ်လို (helaou) - Burmesemari (まり) - Ainucào (草) - Zhuangкүнтізбе (kúntízbe) - Kazakhբարև (barev) - Armenianмонгол (mongol) - Mongolianmila (میلا) - Uyghurનમસ્તે (namaste) - Gujarati漢字 (kanji) - Japanese위 (wi) - Korean吾哥 (ngǔgāi) - Cantoneseမင်္ဂလာပါ (mingalaba) - Burmeseсайн уу (sain uu) - Mongolianਸਤਿ ਸ੍ਰੀ ਅਕਾਲ (sat sri akal) - Punjabi你吃了吗 (ní chī le ma) - Mandarin Chinese饭 (fan) - Zhuangمەن سىزنى ياخشى ئۈمىد ق + + + \ No newline at end of file diff --git a/e2etests/testdata/unicode/mixed-language/dagre/board.exp.json b/e2etests/testdata/unicode/mixed-language/dagre/board.exp.json new file mode 100644 index 000000000..310f55112 --- /dev/null +++ b/e2etests/testdata/unicode/mixed-language/dagre/board.exp.json @@ -0,0 +1,226 @@ +{ + "name": "", + "fontFamily": "SourceSansPro", + "shapes": [ + { + "id": "a", + "type": "rectangle", + "pos": { + "x": 275, + "y": 0 + }, + "width": 428, + "height": 98, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "有一个叫做夏天的季节。\n ある季節、夏という名前がついています。\n한 계절, 여름이란 이름이 있습니다.", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 383, + "labelHeight": 53, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "b", + "type": "rectangle", + "pos": { + "x": 0, + "y": 198 + }, + "width": 448, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "夏天的时候,天气非常热,人们总是流着汗。", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 403, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "c", + "type": "text", + "pos": { + "x": 508, + "y": 199 + }, + "width": 492, + "height": 64, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "transparent", + "stroke": "#0A0F25", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "夏になると、とても暑くて、人々は汗を流しています。\n\n여름에는 매우 더워서 사람들은 땀을 흘립니다.", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "markdown", + "color": "#0A0F25", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 492, + "labelHeight": 64, + "zIndex": 0, + "level": 1 + } + ], + "connections": [ + { + "id": "(a -> b)[0]", + "src": "a", + "srcArrow": "none", + "srcLabel": "", + "dst": "b", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 357.83838383838383, + "y": 98 + }, + { + "x": 250.76767676767676, + "y": 138 + }, + { + "x": 224, + "y": 158 + }, + { + "x": 224, + "y": 198 + } + ], + "isCurve": true, + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + }, + { + "id": "(a -> c)[0]", + "src": "a", + "srcArrow": "none", + "srcLabel": "", + "dst": "c", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 620.1616161616162, + "y": 98 + }, + { + "x": 727.2323232323232, + "y": 138 + }, + { + "x": 754, + "y": 158.2 + }, + { + "x": 754, + "y": 199 + } + ], + "isCurve": true, + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + } + ] +} diff --git a/e2etests/testdata/unicode/mixed-language/dagre/sketch.exp.svg b/e2etests/testdata/unicode/mixed-language/dagre/sketch.exp.svg new file mode 100644 index 000000000..a3682641a --- /dev/null +++ b/e2etests/testdata/unicode/mixed-language/dagre/sketch.exp.svg @@ -0,0 +1,818 @@ + +有一个叫做夏天的季节。 ある季節、夏という名前がついています。한 계절, 여름이란 이름이 있습니다.夏天的时候,天气非常热,人们总是流着汗。

夏になると、とても暑くて、人々は汗を流しています。

+

여름에는 매우 더워서 사람들은 땀을 흘립니다.

+
+ + +
\ No newline at end of file diff --git a/e2etests/testdata/unicode/mixed-language/elk/board.exp.json b/e2etests/testdata/unicode/mixed-language/elk/board.exp.json new file mode 100644 index 000000000..cdd2c0da3 --- /dev/null +++ b/e2etests/testdata/unicode/mixed-language/elk/board.exp.json @@ -0,0 +1,216 @@ +{ + "name": "", + "fontFamily": "SourceSansPro", + "shapes": [ + { + "id": "a", + "type": "rectangle", + "pos": { + "x": 93, + "y": 12 + }, + "width": 428, + "height": 98, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "有一个叫做夏天的季节。\n ある季節、夏という名前がついています。\n한 계절, 여름이란 이름이 있습니다.", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 383, + "labelHeight": 53, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "b", + "type": "rectangle", + "pos": { + "x": 12, + "y": 190 + }, + "width": 448, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#F7F8FE", + "stroke": "#0D32B2", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "夏天的时候,天气非常热,人们总是流着汗。", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 403, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "c", + "type": "text", + "pos": { + "x": 480, + "y": 190 + }, + "width": 492, + "height": 64, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "transparent", + "stroke": "#0A0F25", + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "夏になると、とても暑くて、人々は汗を流しています。\n\n여름에는 매우 더워서 사람들은 땀을 흘립니다.", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "markdown", + "color": "#0A0F25", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 492, + "labelHeight": 64, + "zIndex": 0, + "level": 1 + } + ], + "connections": [ + { + "id": "(a -> b)[0]", + "src": "a", + "srcArrow": "none", + "srcLabel": "", + "dst": "b", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 236, + "y": 110 + }, + { + "x": 236, + "y": 190 + } + ], + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + }, + { + "id": "(a -> c)[0]", + "src": "a", + "srcArrow": "none", + "srcLabel": "", + "dst": "c", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 378.66666666666663, + "y": 110 + }, + { + "x": 378.66666666666663, + "y": 150 + }, + { + "x": 726, + "y": 150 + }, + { + "x": 726, + "y": 190 + } + ], + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + } + ] +} diff --git a/e2etests/testdata/unicode/mixed-language/elk/sketch.exp.svg b/e2etests/testdata/unicode/mixed-language/elk/sketch.exp.svg new file mode 100644 index 000000000..d013202bf --- /dev/null +++ b/e2etests/testdata/unicode/mixed-language/elk/sketch.exp.svg @@ -0,0 +1,818 @@ + +有一个叫做夏天的季节。 ある季節、夏という名前がついています。한 계절, 여름이란 이름이 있습니다.夏天的时候,天气非常热,人们总是流着汗。

夏になると、とても暑くて、人々は汗を流しています。

+

여름에는 매우 더워서 사람들은 땀을 흘립니다.

+
+ + +
\ No newline at end of file diff --git a/e2etests/unicode_test.go b/e2etests/unicode_test.go index 0629cdf09..d6131857f 100644 --- a/e2etests/unicode_test.go +++ b/e2etests/unicode_test.go @@ -48,6 +48,84 @@ e: English English English f: 先日先日先日 a -> b -> c -> d -> e -> f +`, + }, + { + name: "chinese", + script: `poem: |md + 床前明月光, + + 疑是地上霜。 + + 举头望明月, + + 低头思故乡。 +| +a: 所以,即使夏天很热 +poem -> a +`, + }, + { + name: "korean", + script: `a: 고생끝에낙이온다 +`, + }, + { + name: "mixed-language", + script: `a: 有一个叫做夏天的季节。\n ある季節、夏という名前がついています。\n한 계절, 여름이란 이름이 있습니다. +b: 夏天的时候,天气非常热,人们总是流着汗。 +c: |md + 夏になると、とても暑くて、人々は汗を流しています。 + + 여름에는 매우 더워서 사람들은 땀을 흘립니다. +| +a -> b +a -> c +`, + }, + { + name: "mixed-language-2", + script: `a: 我 (wǒ) - Mandarin Chinese +b: ສະບາຍດີ (sabaai dii) - Lao +c: ជំរាបសួរ (jomreab suor) - Khmer + +สวัสดี (sà-wàt-dii) - Thai + +ສະບາຍດີ (sabaidee) - Lao + +ဟယ်လို (helaou) - Burmese + +mari (まり) - Ainu + +cào (草) - Zhuang + +күнтізбе (kúntízbe) - Kazakh + +բարև (barev) - Armenian + +монгол (mongol) - Mongolian + +mila (میلا) - Uyghur + +નમસ્તે (namaste) - Gujarati + +漢字 (kanji) - Japanese + +위 (wi) - Korean + +吾哥 (ngǔgāi) - Cantonese + +မင်္ဂလာပါ (mingalaba) - Burmese + +сайн уу (sain uu) - Mongolian + +ਸਤਿ ਸ੍ਰੀ ਅਕਾਲ (sat sri akal) - Punjabi + +你吃了吗 (ní chī le ma) - Mandarin Chinese + +饭 (fan) - Zhuang + +مەن سىزنى ياخشى ئۈمىد ق `, }, } diff --git a/go.mod b/go.mod index c8986bd2f..d586076c6 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,6 @@ require ( github.com/fsnotify/fsnotify v1.6.0 github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 github.com/lucasb-eyer/go-colorful v1.2.0 - github.com/mattn/go-runewidth v0.0.14 github.com/mazznoer/csscolorparser v0.1.3 github.com/playwright-community/playwright-go v0.2000.1 github.com/rivo/uniseg v0.4.3 diff --git a/go.sum b/go.sum index 9b83338c3..b98f3d151 100644 --- a/go.sum +++ b/go.sum @@ -115,8 +115,6 @@ github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= -github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mazznoer/csscolorparser v0.1.3 h1:vug4zh6loQxAUxfU1DZEu70gTPufDPspamZlHAkKcxE= github.com/mazznoer/csscolorparser v0.1.3/go.mod h1:Aj22+L/rYN/Y6bj3bYqO3N6g1dtdHtGfQ32xZ5PJQic= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= @@ -130,8 +128,6 @@ github.com/playwright-community/playwright-go v0.2000.1/go.mod h1:1y9cM9b9dVHnuR github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= -github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.3 h1:utMvzDsuh3suAEnhH0RdHmoPbU648o6CvXxTx4SBMOw= github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= diff --git a/lib/textmeasure/markdown.go b/lib/textmeasure/markdown.go index 4a30afbbb..bb9cdaa46 100644 --- a/lib/textmeasure/markdown.go +++ b/lib/textmeasure/markdown.go @@ -257,6 +257,8 @@ func (ruler *Ruler) measureNode(depth int, n *html.Node, fontFamily *d2fonts.Fon if isCode { w *= FontSize_pre_code_em h *= FontSize_pre_code_em + } else { + w = ruler.scaleUnicode(w, font, str) } if debugMeasure { fmt.Printf("%stext(%v,%v)\n", depthStr, w, h) diff --git a/lib/textmeasure/textmeasure.go b/lib/textmeasure/textmeasure.go index cdf9c811c..2e539e86d 100644 --- a/lib/textmeasure/textmeasure.go +++ b/lib/textmeasure/textmeasure.go @@ -166,8 +166,7 @@ func (r *Ruler) addFontSize(font d2fonts.Font) { r.tabWidths[font] = atlas.glyph(' ').advance * TAB_SIZE } -func (t *Ruler) Measure(font d2fonts.Font, s string) (width, height int) { - w, h := t.MeasurePrecise(font, s) +func (t *Ruler) scaleUnicode(w float64, font d2fonts.Font, s string) float64 { // Weird unicode stuff is going on when this is true // See https://github.com/rivo/uniseg#grapheme-clusters // This method is a good-enough approximation. It overshoots, but not by much. @@ -198,6 +197,7 @@ func (t *Ruler) Measure(font d2fonts.Font, s string) (width, height int) { var bounds *rect _, _, bounds, dot = t.atlases[font].DrawRune(prevRune, r, dot) b = b.union(bounds) + prevRune = r } lineW -= b.w() @@ -206,6 +206,12 @@ func (t *Ruler) Measure(font d2fonts.Font, s string) (width, height int) { w = math.Max(w, lineW) } } + return w +} + +func (t *Ruler) Measure(font d2fonts.Font, s string) (width, height int) { + w, h := t.MeasurePrecise(font, s) + w = t.scaleUnicode(w, font, s) return int(math.Ceil(w)), int(math.Ceil(h)) } From cbfa02825849ba844bab659a503fa35ac93085b6 Mon Sep 17 00:00:00 2001 From: Alexander Wang Date: Tue, 14 Feb 2023 10:39:15 -0800 Subject: [PATCH 3/4] regenerate tests --- .../mixed-language-2/dagre/board.exp.json | 673 ++++++++++++++++-- .../mixed-language-2/dagre/sketch.exp.svg | 6 +- .../mixed-language-2/elk/board.exp.json | 565 +++++++++++++-- .../mixed-language-2/elk/sketch.exp.svg | 6 +- e2etests/unicode_test.go | 31 +- 5 files changed, 1166 insertions(+), 115 deletions(-) diff --git a/e2etests/testdata/unicode/mixed-language-2/dagre/board.exp.json b/e2etests/testdata/unicode/mixed-language-2/dagre/board.exp.json index bb5c666f8..de3b3e2bf 100644 --- a/e2etests/testdata/unicode/mixed-language-2/dagre/board.exp.json +++ b/e2etests/testdata/unicode/mixed-language-2/dagre/board.exp.json @@ -6,7 +6,7 @@ "id": "a", "type": "rectangle", "pos": { - "x": 0, + "x": 31, "y": 0 }, "width": 240, @@ -47,8 +47,8 @@ "id": "b", "type": "rectangle", "pos": { - "x": 300, - "y": 0 + "x": 30, + "y": 166 }, "width": 241, "height": 66, @@ -88,8 +88,8 @@ "id": "c", "type": "rectangle", "pos": { - "x": 601, - "y": 0 + "x": 0, + "y": 332 }, "width": 301, "height": 66, @@ -126,11 +126,11 @@ "level": 1 }, { - "id": "\"สวัสดี (sà-wàt-dii) - Thai\"", + "id": "d", "type": "rectangle", "pos": { - "x": 962, - "y": 0 + "x": 29, + "y": 498 }, "width": 244, "height": 66, @@ -167,10 +167,10 @@ "level": 1 }, { - "id": "\"ສະບາຍດີ (sabaidee) - Lao\"", + "id": "e", "type": "rectangle", "pos": { - "x": 1266, + "x": 336, "y": 0 }, "width": 237, @@ -208,11 +208,11 @@ "level": 1 }, { - "id": "\"ဟယ်လို (helaou) - Burmese\"", + "id": "f", "type": "rectangle", "pos": { - "x": 1563, - "y": 0 + "x": 331, + "y": 166 }, "width": 247, "height": 66, @@ -249,11 +249,11 @@ "level": 1 }, { - "id": "\"mari (まり) - Ainu\"", + "id": "g", "type": "rectangle", "pos": { - "x": 1870, - "y": 0 + "x": 367, + "y": 332 }, "width": 176, "height": 66, @@ -290,11 +290,11 @@ "level": 1 }, { - "id": "\"cào (草) - Zhuang\"", + "id": "h", "type": "rectangle", "pos": { - "x": 2106, - "y": 0 + "x": 368, + "y": 498 }, "width": 173, "height": 66, @@ -331,10 +331,10 @@ "level": 1 }, { - "id": "\"күнтізбе (kúntízbe) - Kazakh\"", + "id": "i", "type": "rectangle", "pos": { - "x": 2339, + "x": 633, "y": 0 }, "width": 282, @@ -372,11 +372,11 @@ "level": 1 }, { - "id": "\"բարև (barev) - Armenian\"", + "id": "j", "type": "rectangle", "pos": { - "x": 2681, - "y": 0 + "x": 662, + "y": 166 }, "width": 224, "height": 66, @@ -413,11 +413,11 @@ "level": 1 }, { - "id": "\"монгол (mongol) - Mongolian\"", + "id": "k", "type": "rectangle", "pos": { - "x": 2965, - "y": 0 + "x": 642, + "y": 332 }, "width": 265, "height": 66, @@ -454,11 +454,11 @@ "level": 1 }, { - "id": "\"mila (میلا) - Uyghur\"", + "id": "l", "type": "rectangle", "pos": { - "x": 3290, - "y": 0 + "x": 675, + "y": 498 }, "width": 199, "height": 66, @@ -495,10 +495,10 @@ "level": 1 }, { - "id": "\"નમસ્તે (namaste) - Gujarati\"", + "id": "m", "type": "rectangle", "pos": { - "x": 3549, + "x": 975, "y": 0 }, "width": 255, @@ -536,11 +536,11 @@ "level": 1 }, { - "id": "\"漢字 (kanji) - Japanese\"", + "id": "n", "type": "rectangle", "pos": { - "x": 3864, - "y": 0 + "x": 996, + "y": 166 }, "width": 213, "height": 66, @@ -577,11 +577,11 @@ "level": 1 }, { - "id": "\"위 (wi) - Korean\"", + "id": "o", "type": "rectangle", "pos": { - "x": 4137, - "y": 0 + "x": 1024, + "y": 332 }, "width": 158, "height": 66, @@ -618,11 +618,11 @@ "level": 1 }, { - "id": "\"吾哥 (ngǔgāi) - Cantonese\"", + "id": "p", "type": "rectangle", "pos": { - "x": 4355, - "y": 0 + "x": 984, + "y": 498 }, "width": 238, "height": 66, @@ -662,7 +662,7 @@ "id": "\"မင်္ဂလာပါ (mingalaba) - Burmese\"", "type": "rectangle", "pos": { - "x": 4653, + "x": 1290, "y": 0 }, "width": 307, @@ -703,7 +703,7 @@ "id": "\"сайн уу (sain uu) - Mongolian\"", "type": "rectangle", "pos": { - "x": 5020, + "x": 1657, "y": 0 }, "width": 264, @@ -744,7 +744,7 @@ "id": "\"ਸਤਿ ਸ੍ਰੀ ਅਕਾਲ (sat sri akal) - Punjabi\"", "type": "rectangle", "pos": { - "x": 5344, + "x": 1981, "y": 0 }, "width": 328, @@ -785,7 +785,7 @@ "id": "\"你吃了吗 (ní chī le ma) - Mandarin Chinese\"", "type": "rectangle", "pos": { - "x": 5732, + "x": 2369, "y": 0 }, "width": 370, @@ -826,7 +826,7 @@ "id": "\"饭 (fan) - Zhuang\"", "type": "rectangle", "pos": { - "x": 6162, + "x": 2799, "y": 0 }, "width": 167, @@ -867,7 +867,7 @@ "id": "مەن سىزنى ياخشى ئۈمىد ق", "type": "rectangle", "pos": { - "x": 6389, + "x": 3026, "y": 0 }, "width": 266, @@ -905,5 +905,582 @@ "level": 1 } ], - "connections": [] + "connections": [ + { + "id": "(a -> b)[0]", + "src": "a", + "srcArrow": "none", + "srcLabel": "", + "dst": "b", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 150.5, + "y": 66 + }, + { + "x": 150.5, + "y": 106 + }, + { + "x": 150.5, + "y": 126 + }, + { + "x": 150.5, + "y": 166 + } + ], + "isCurve": true, + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + }, + { + "id": "(b -> c)[0]", + "src": "b", + "srcArrow": "none", + "srcLabel": "", + "dst": "c", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 150.5, + "y": 232 + }, + { + "x": 150.5, + "y": 272 + }, + { + "x": 150.5, + "y": 292 + }, + { + "x": 150.5, + "y": 332 + } + ], + "isCurve": true, + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + }, + { + "id": "(c -> d)[0]", + "src": "c", + "srcArrow": "none", + "srcLabel": "", + "dst": "d", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 150.5, + "y": 398 + }, + { + "x": 150.5, + "y": 438 + }, + { + "x": 150.5, + "y": 458 + }, + { + "x": 150.5, + "y": 498 + } + ], + "isCurve": true, + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + }, + { + "id": "(e -> f)[0]", + "src": "e", + "srcArrow": "none", + "srcLabel": "", + "dst": "f", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 454.5, + "y": 66 + }, + { + "x": 454.5, + "y": 106 + }, + { + "x": 454.5, + "y": 126 + }, + { + "x": 454.5, + "y": 166 + } + ], + "isCurve": true, + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + }, + { + "id": "(f -> g)[0]", + "src": "f", + "srcArrow": "none", + "srcLabel": "", + "dst": "g", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 454.5, + "y": 232 + }, + { + "x": 454.5, + "y": 272 + }, + { + "x": 454.5, + "y": 292 + }, + { + "x": 454.5, + "y": 332 + } + ], + "isCurve": true, + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + }, + { + "id": "(g -> h)[0]", + "src": "g", + "srcArrow": "none", + "srcLabel": "", + "dst": "h", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 454.5, + "y": 398 + }, + { + "x": 454.5, + "y": 438 + }, + { + "x": 454.5, + "y": 458 + }, + { + "x": 454.5, + "y": 498 + } + ], + "isCurve": true, + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + }, + { + "id": "(i -> j)[0]", + "src": "i", + "srcArrow": "none", + "srcLabel": "", + "dst": "j", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 774, + "y": 66 + }, + { + "x": 774, + "y": 106 + }, + { + "x": 774, + "y": 126 + }, + { + "x": 774, + "y": 166 + } + ], + "isCurve": true, + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + }, + { + "id": "(j -> k)[0]", + "src": "j", + "srcArrow": "none", + "srcLabel": "", + "dst": "k", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 774, + "y": 232 + }, + { + "x": 774, + "y": 272 + }, + { + "x": 774, + "y": 292 + }, + { + "x": 774, + "y": 332 + } + ], + "isCurve": true, + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + }, + { + "id": "(k -> l)[0]", + "src": "k", + "srcArrow": "none", + "srcLabel": "", + "dst": "l", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 774, + "y": 398 + }, + { + "x": 774, + "y": 438 + }, + { + "x": 774, + "y": 458 + }, + { + "x": 774, + "y": 498 + } + ], + "isCurve": true, + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + }, + { + "id": "(m -> n)[0]", + "src": "m", + "srcArrow": "none", + "srcLabel": "", + "dst": "n", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 1102.5, + "y": 66 + }, + { + "x": 1102.5, + "y": 106 + }, + { + "x": 1102.5, + "y": 126 + }, + { + "x": 1102.5, + "y": 166 + } + ], + "isCurve": true, + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + }, + { + "id": "(n -> o)[0]", + "src": "n", + "srcArrow": "none", + "srcLabel": "", + "dst": "o", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 1102.5, + "y": 232 + }, + { + "x": 1102.5, + "y": 272 + }, + { + "x": 1102.5, + "y": 292 + }, + { + "x": 1102.5, + "y": 332 + } + ], + "isCurve": true, + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + }, + { + "id": "(o -> p)[0]", + "src": "o", + "srcArrow": "none", + "srcLabel": "", + "dst": "p", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 1102.5, + "y": 398 + }, + { + "x": 1102.5, + "y": 438 + }, + { + "x": 1102.5, + "y": 458 + }, + { + "x": 1102.5, + "y": 498 + } + ], + "isCurve": true, + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + } + ] } diff --git a/e2etests/testdata/unicode/mixed-language-2/dagre/sketch.exp.svg b/e2etests/testdata/unicode/mixed-language-2/dagre/sketch.exp.svg index 2947dbba3..b3c441a46 100644 --- a/e2etests/testdata/unicode/mixed-language-2/dagre/sketch.exp.svg +++ b/e2etests/testdata/unicode/mixed-language-2/dagre/sketch.exp.svg @@ -3,7 +3,7 @@ id="d2-svg" style="background: white;" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" -width="6859" height="270" viewBox="-102 -102 6859 270">