diff --git a/ci/release/changelogs/next.md b/ci/release/changelogs/next.md
index 55bafe4af..a8d27e47b 100644
--- a/ci/release/changelogs/next.md
+++ b/ci/release/changelogs/next.md
@@ -2,6 +2,8 @@
#### Improvements 🧹
+- Improved label placements for shapes with images to avoid overlapping container labels. [#474](https://github.com/terrastruct/d2/pull/474)
+
#### Bugfixes ⛑️
- `d2 fmt` only rewrites if it has changes, instead of always rewriting. [#470](https://github.com/terrastruct/d2/pull/470)
diff --git a/d2layouts/d2dagrelayout/layout.go b/d2layouts/d2dagrelayout/layout.go
index ec72a91c6..3ae70e35a 100644
--- a/d2layouts/d2dagrelayout/layout.go
+++ b/d2layouts/d2dagrelayout/layout.go
@@ -90,7 +90,14 @@ func Layout(ctx context.Context, g *d2graph.Graph) (err error) {
for _, obj := range g.Objects {
id := obj.AbsID()
idToObj[id] = obj
- loadScript += generateAddNodeLine(id, int(obj.Width), int(obj.Height))
+
+ height := obj.Height
+ if obj.LabelWidth != nil && obj.LabelHeight != nil {
+ if obj.Attributes.Shape.Value == d2target.ShapeImage || obj.Attributes.Icon != nil {
+ height += float64(*obj.LabelHeight) + label.PADDING
+ }
+ }
+ loadScript += generateAddNodeLine(id, int(obj.Width), int(height))
if obj.Parent != g.Root {
loadScript += generateAddParentLine(id, obj.Parent.AbsID())
}
@@ -151,8 +158,12 @@ func Layout(ctx context.Context, g *d2graph.Graph) (err error) {
if obj.LabelWidth != nil && obj.LabelHeight != nil {
if len(obj.ChildrenArray) > 0 {
obj.LabelPosition = go2.Pointer(string(label.InsideTopCenter))
- } else if obj.Attributes.Shape.Value == d2target.ShapeImage || obj.Attributes.Icon != nil {
- obj.LabelPosition = go2.Pointer(string(label.OutsideTopCenter))
+ } else if obj.Attributes.Shape.Value == d2target.ShapeImage {
+ obj.LabelPosition = go2.Pointer(string(label.OutsideBottomCenter))
+ // remove the extra height we added to the node when passing to dagre
+ obj.Height -= float64(*obj.LabelHeight) + label.PADDING
+ } else if obj.Attributes.Icon != nil {
+ obj.LabelPosition = go2.Pointer(string(label.InsideTopCenter))
} else {
obj.LabelPosition = go2.Pointer(string(label.InsideMiddleCenter))
}
diff --git a/d2layouts/d2elklayout/layout.go b/d2layouts/d2elklayout/layout.go
index dce31bc8a..fb364ceba 100644
--- a/d2layouts/d2elklayout/layout.go
+++ b/d2layouts/d2elklayout/layout.go
@@ -142,10 +142,15 @@ func Layout(ctx context.Context, g *d2graph.Graph) (err error) {
}
walk(g.Root, nil, func(obj, parent *d2graph.Object) {
+ height := obj.Height
+ if obj.Attributes.Shape.Value == d2target.ShapeImage || obj.Attributes.Icon != nil {
+ height += float64(*obj.LabelHeight) + label.PADDING
+ }
+
n := &ELKNode{
ID: obj.AbsID(),
Width: obj.Width,
- Height: obj.Height,
+ Height: height,
}
if len(obj.ChildrenArray) > 0 {
@@ -250,8 +255,11 @@ func Layout(ctx context.Context, g *d2graph.Graph) (err error) {
if obj.LabelWidth != nil && obj.LabelHeight != nil {
if len(obj.ChildrenArray) > 0 {
obj.LabelPosition = go2.Pointer(string(label.InsideTopCenter))
- } else if obj.Attributes.Shape.Value == d2target.ShapeImage || obj.Attributes.Icon != nil {
- obj.LabelPosition = go2.Pointer(string(label.OutsideTopCenter))
+ } else if obj.Attributes.Shape.Value == d2target.ShapeImage {
+ obj.LabelPosition = go2.Pointer(string(label.OutsideBottomCenter))
+ obj.Height -= float64(*obj.LabelHeight) + label.PADDING
+ } else if obj.Attributes.Icon != nil {
+ obj.LabelPosition = go2.Pointer(string(label.InsideTopCenter))
} else {
obj.LabelPosition = go2.Pointer(string(label.InsideMiddleCenter))
}
diff --git a/e2etests/stable_test.go b/e2etests/stable_test.go
index 76f4cf12a..848d0028a 100644
--- a/e2etests/stable_test.go
+++ b/e2etests/stable_test.go
@@ -1513,6 +1513,78 @@ no container.style: {
stroke: red
fill: "#CEEDEE"
}
+`,
+ },
+ {
+ name: "overlapping_image_container_labels",
+ script: `
+root: {
+ shape: image
+ icon: https://icons.terrastruct.com/essentials/004-picture.svg
+}
+
+root -> container.root
+
+container: {
+ root: {
+ shape: image
+ icon: https://icons.terrastruct.com/essentials/004-picture.svg
+ }
+
+ left: {
+ root: {
+ shape: image
+ icon: https://icons.terrastruct.com/essentials/004-picture.svg
+ }
+ inner: {
+ left: {
+ shape: image
+ icon: https://icons.terrastruct.com/essentials/004-picture.svg
+ }
+ right: {
+ shape: image
+ icon: https://icons.terrastruct.com/essentials/004-picture.svg
+ }
+ }
+ root -> inner.left: {
+ label: to inner left
+ }
+ root -> inner.right: {
+ label: to inner right
+ }
+ }
+
+ right: {
+ root: {
+ shape: image
+ icon: https://icons.terrastruct.com/essentials/004-picture.svg
+ }
+ inner: {
+ left: {
+ shape: image
+ icon: https://icons.terrastruct.com/essentials/004-picture.svg
+ }
+ right: {
+ shape: image
+ icon: https://icons.terrastruct.com/essentials/004-picture.svg
+ }
+ }
+ root -> inner.left: {
+ label: to inner left
+ }
+ root -> inner.right: {
+ label: to inner right
+ }
+ }
+
+ root -> left.root: {
+ label: to left container root
+ }
+
+ root -> right.root: {
+ label: to right container root
+ }
+}
`,
},
}
diff --git a/e2etests/testdata/stable/icon-label/dagre/board.exp.json b/e2etests/testdata/stable/icon-label/dagre/board.exp.json
index d399b9275..d8830f909 100644
--- a/e2etests/testdata/stable/icon-label/dagre/board.exp.json
+++ b/e2etests/testdata/stable/icon-label/dagre/board.exp.json
@@ -9,7 +9,7 @@
"y": 0
},
"width": 140,
- "height": 126,
+ "height": 152,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@@ -48,7 +48,7 @@
"underline": false,
"labelWidth": 40,
"labelHeight": 26,
- "labelPosition": "OUTSIDE_TOP_CENTER",
+ "labelPosition": "INSIDE_TOP_CENTER",
"zIndex": 0,
"level": 1
}
diff --git a/e2etests/testdata/stable/icon-label/dagre/sketch.exp.svg b/e2etests/testdata/stable/icon-label/dagre/sketch.exp.svg
index f9f6c8d1b..0de642053 100644
--- a/e2etests/testdata/stable/icon-label/dagre/sketch.exp.svg
+++ b/e2etests/testdata/stable/icon-label/dagre/sketch.exp.svg
@@ -2,7 +2,7 @@
\ No newline at end of file
diff --git a/e2etests/testdata/stable/overlapping_image_container_labels/elk/board.exp.json b/e2etests/testdata/stable/overlapping_image_container_labels/elk/board.exp.json
new file mode 100644
index 000000000..754dfe0fb
--- /dev/null
+++ b/e2etests/testdata/stable/overlapping_image_container_labels/elk/board.exp.json
@@ -0,0 +1,912 @@
+{
+ "name": "",
+ "shapes": [
+ {
+ "id": "root",
+ "type": "image",
+ "pos": {
+ "x": 280,
+ "y": 12
+ },
+ "width": 128,
+ "height": 128,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "#FFFFFF",
+ "stroke": "#0D32B2",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "tooltip": "",
+ "link": "",
+ "icon": {
+ "Scheme": "https",
+ "Opaque": "",
+ "User": null,
+ "Host": "icons.terrastruct.com",
+ "Path": "/essentials/004-picture.svg",
+ "RawPath": "",
+ "ForceQuery": false,
+ "RawQuery": "",
+ "Fragment": "",
+ "RawFragment": ""
+ },
+ "iconPosition": "INSIDE_MIDDLE_CENTER",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "root",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "#0A0F25",
+ "italic": false,
+ "bold": true,
+ "underline": false,
+ "labelWidth": 35,
+ "labelHeight": 26,
+ "labelPosition": "OUTSIDE_BOTTOM_CENTER",
+ "zIndex": 0,
+ "level": 1
+ },
+ {
+ "id": "container",
+ "type": "",
+ "pos": {
+ "x": 12,
+ "y": 271
+ },
+ "width": 1322,
+ "height": 1044,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "#E3E9FD",
+ "stroke": "#0D32B2",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "container",
+ "fontSize": 28,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "#0A0F25",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 117,
+ "labelHeight": 41,
+ "labelPosition": "INSIDE_TOP_CENTER",
+ "zIndex": 0,
+ "level": 1
+ },
+ {
+ "id": "container.root",
+ "type": "image",
+ "pos": {
+ "x": 280,
+ "y": 346
+ },
+ "width": 128,
+ "height": 128,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "#FFFFFF",
+ "stroke": "#0D32B2",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "tooltip": "",
+ "link": "",
+ "icon": {
+ "Scheme": "https",
+ "Opaque": "",
+ "User": null,
+ "Host": "icons.terrastruct.com",
+ "Path": "/essentials/004-picture.svg",
+ "RawPath": "",
+ "ForceQuery": false,
+ "RawQuery": "",
+ "Fragment": "",
+ "RawFragment": ""
+ },
+ "iconPosition": "INSIDE_MIDDLE_CENTER",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "root",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "#0A0F25",
+ "italic": false,
+ "bold": true,
+ "underline": false,
+ "labelWidth": 35,
+ "labelHeight": 26,
+ "labelPosition": "OUTSIDE_BOTTOM_CENTER",
+ "zIndex": 0,
+ "level": 2
+ },
+ {
+ "id": "container.left",
+ "type": "",
+ "pos": {
+ "x": 87,
+ "y": 566
+ },
+ "width": 576,
+ "height": 674,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "#EDF0FD",
+ "stroke": "#0D32B2",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "left",
+ "fontSize": 24,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "#0A0F25",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 38,
+ "labelHeight": 36,
+ "labelPosition": "INSIDE_TOP_CENTER",
+ "zIndex": 0,
+ "level": 2
+ },
+ {
+ "id": "container.left.root",
+ "type": "image",
+ "pos": {
+ "x": 258,
+ "y": 641
+ },
+ "width": 128,
+ "height": 128,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "#FFFFFF",
+ "stroke": "#0D32B2",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "tooltip": "",
+ "link": "",
+ "icon": {
+ "Scheme": "https",
+ "Opaque": "",
+ "User": null,
+ "Host": "icons.terrastruct.com",
+ "Path": "/essentials/004-picture.svg",
+ "RawPath": "",
+ "ForceQuery": false,
+ "RawQuery": "",
+ "Fragment": "",
+ "RawFragment": ""
+ },
+ "iconPosition": "INSIDE_MIDDLE_CENTER",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "root",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "#0A0F25",
+ "italic": false,
+ "bold": true,
+ "underline": false,
+ "labelWidth": 35,
+ "labelHeight": 26,
+ "labelPosition": "OUTSIDE_BOTTOM_CENTER",
+ "zIndex": 0,
+ "level": 3
+ },
+ {
+ "id": "container.left.inner",
+ "type": "",
+ "pos": {
+ "x": 162,
+ "y": 861
+ },
+ "width": 426,
+ "height": 304,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "#F7F8FE",
+ "stroke": "#0D32B2",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "inner",
+ "fontSize": 20,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "#0A0F25",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 49,
+ "labelHeight": 31,
+ "labelPosition": "INSIDE_TOP_CENTER",
+ "zIndex": 0,
+ "level": 3
+ },
+ {
+ "id": "container.left.inner.left",
+ "type": "image",
+ "pos": {
+ "x": 237,
+ "y": 936
+ },
+ "width": 128,
+ "height": 128,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "#FFFFFF",
+ "stroke": "#0D32B2",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "tooltip": "",
+ "link": "",
+ "icon": {
+ "Scheme": "https",
+ "Opaque": "",
+ "User": null,
+ "Host": "icons.terrastruct.com",
+ "Path": "/essentials/004-picture.svg",
+ "RawPath": "",
+ "ForceQuery": false,
+ "RawQuery": "",
+ "Fragment": "",
+ "RawFragment": ""
+ },
+ "iconPosition": "INSIDE_MIDDLE_CENTER",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "left",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "#0A0F25",
+ "italic": false,
+ "bold": true,
+ "underline": false,
+ "labelWidth": 29,
+ "labelHeight": 26,
+ "labelPosition": "OUTSIDE_BOTTOM_CENTER",
+ "zIndex": 0,
+ "level": 4
+ },
+ {
+ "id": "container.left.inner.right",
+ "type": "image",
+ "pos": {
+ "x": 385,
+ "y": 936
+ },
+ "width": 128,
+ "height": 128,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "#FFFFFF",
+ "stroke": "#0D32B2",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "tooltip": "",
+ "link": "",
+ "icon": {
+ "Scheme": "https",
+ "Opaque": "",
+ "User": null,
+ "Host": "icons.terrastruct.com",
+ "Path": "/essentials/004-picture.svg",
+ "RawPath": "",
+ "ForceQuery": false,
+ "RawQuery": "",
+ "Fragment": "",
+ "RawFragment": ""
+ },
+ "iconPosition": "INSIDE_MIDDLE_CENTER",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "right",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "#0A0F25",
+ "italic": false,
+ "bold": true,
+ "underline": false,
+ "labelWidth": 39,
+ "labelHeight": 26,
+ "labelPosition": "OUTSIDE_BOTTOM_CENTER",
+ "zIndex": 0,
+ "level": 4
+ },
+ {
+ "id": "container.right",
+ "type": "",
+ "pos": {
+ "x": 683,
+ "y": 566
+ },
+ "width": 576,
+ "height": 674,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "#EDF0FD",
+ "stroke": "#0D32B2",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "right",
+ "fontSize": 24,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "#0A0F25",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 52,
+ "labelHeight": 36,
+ "labelPosition": "INSIDE_TOP_CENTER",
+ "zIndex": 0,
+ "level": 2
+ },
+ {
+ "id": "container.right.root",
+ "type": "image",
+ "pos": {
+ "x": 854,
+ "y": 641
+ },
+ "width": 128,
+ "height": 128,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "#FFFFFF",
+ "stroke": "#0D32B2",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "tooltip": "",
+ "link": "",
+ "icon": {
+ "Scheme": "https",
+ "Opaque": "",
+ "User": null,
+ "Host": "icons.terrastruct.com",
+ "Path": "/essentials/004-picture.svg",
+ "RawPath": "",
+ "ForceQuery": false,
+ "RawQuery": "",
+ "Fragment": "",
+ "RawFragment": ""
+ },
+ "iconPosition": "INSIDE_MIDDLE_CENTER",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "root",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "#0A0F25",
+ "italic": false,
+ "bold": true,
+ "underline": false,
+ "labelWidth": 35,
+ "labelHeight": 26,
+ "labelPosition": "OUTSIDE_BOTTOM_CENTER",
+ "zIndex": 0,
+ "level": 3
+ },
+ {
+ "id": "container.right.inner",
+ "type": "",
+ "pos": {
+ "x": 758,
+ "y": 861
+ },
+ "width": 426,
+ "height": 304,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "#F7F8FE",
+ "stroke": "#0D32B2",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "inner",
+ "fontSize": 20,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "#0A0F25",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 49,
+ "labelHeight": 31,
+ "labelPosition": "INSIDE_TOP_CENTER",
+ "zIndex": 0,
+ "level": 3
+ },
+ {
+ "id": "container.right.inner.left",
+ "type": "image",
+ "pos": {
+ "x": 833,
+ "y": 936
+ },
+ "width": 128,
+ "height": 128,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "#FFFFFF",
+ "stroke": "#0D32B2",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "tooltip": "",
+ "link": "",
+ "icon": {
+ "Scheme": "https",
+ "Opaque": "",
+ "User": null,
+ "Host": "icons.terrastruct.com",
+ "Path": "/essentials/004-picture.svg",
+ "RawPath": "",
+ "ForceQuery": false,
+ "RawQuery": "",
+ "Fragment": "",
+ "RawFragment": ""
+ },
+ "iconPosition": "INSIDE_MIDDLE_CENTER",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "left",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "#0A0F25",
+ "italic": false,
+ "bold": true,
+ "underline": false,
+ "labelWidth": 29,
+ "labelHeight": 26,
+ "labelPosition": "OUTSIDE_BOTTOM_CENTER",
+ "zIndex": 0,
+ "level": 4
+ },
+ {
+ "id": "container.right.inner.right",
+ "type": "image",
+ "pos": {
+ "x": 981,
+ "y": 936
+ },
+ "width": 128,
+ "height": 128,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "#FFFFFF",
+ "stroke": "#0D32B2",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "tooltip": "",
+ "link": "",
+ "icon": {
+ "Scheme": "https",
+ "Opaque": "",
+ "User": null,
+ "Host": "icons.terrastruct.com",
+ "Path": "/essentials/004-picture.svg",
+ "RawPath": "",
+ "ForceQuery": false,
+ "RawQuery": "",
+ "Fragment": "",
+ "RawFragment": ""
+ },
+ "iconPosition": "INSIDE_MIDDLE_CENTER",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "right",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "#0A0F25",
+ "italic": false,
+ "bold": true,
+ "underline": false,
+ "labelWidth": 39,
+ "labelHeight": 26,
+ "labelPosition": "OUTSIDE_BOTTOM_CENTER",
+ "zIndex": 0,
+ "level": 4
+ }
+ ],
+ "connections": [
+ {
+ "id": "(root -> container.root)[0]",
+ "src": "root",
+ "srcArrow": "none",
+ "srcLabel": "",
+ "dst": "container.root",
+ "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": 343.6666666666667,
+ "y": 166
+ },
+ {
+ "x": 343.6666666666667,
+ "y": 346
+ }
+ ],
+ "animated": false,
+ "tooltip": "",
+ "icon": null,
+ "zIndex": 0
+ },
+ {
+ "id": "container.left.(root -> inner.left)[0]",
+ "src": "container.left.root",
+ "srcArrow": "none",
+ "srcLabel": "",
+ "dst": "container.left.inner.left",
+ "dstArrow": "triangle",
+ "dstLabel": "",
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "stroke": "#0D32B2",
+ "label": "to inner left",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "#676C7E",
+ "italic": true,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 76,
+ "labelHeight": 21,
+ "labelPosition": "INSIDE_MIDDLE_CENTER",
+ "labelPercentage": 0,
+ "route": [
+ {
+ "x": 301,
+ "y": 795
+ },
+ {
+ "x": 301,
+ "y": 936
+ }
+ ],
+ "animated": false,
+ "tooltip": "",
+ "icon": null,
+ "zIndex": 0
+ },
+ {
+ "id": "container.left.(root -> inner.right)[0]",
+ "src": "container.left.root",
+ "srcArrow": "none",
+ "srcLabel": "",
+ "dst": "container.left.inner.right",
+ "dstArrow": "triangle",
+ "dstLabel": "",
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "stroke": "#0D32B2",
+ "label": "to inner right",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "#676C7E",
+ "italic": true,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 86,
+ "labelHeight": 21,
+ "labelPosition": "INSIDE_MIDDLE_CENTER",
+ "labelPercentage": 0,
+ "route": [
+ {
+ "x": 343.6666666666667,
+ "y": 795
+ },
+ {
+ "x": 343.6666666666667,
+ "y": 846
+ },
+ {
+ "x": 449,
+ "y": 846
+ },
+ {
+ "x": 449,
+ "y": 936
+ }
+ ],
+ "animated": false,
+ "tooltip": "",
+ "icon": null,
+ "zIndex": 0
+ },
+ {
+ "id": "container.right.(root -> inner.left)[0]",
+ "src": "container.right.root",
+ "srcArrow": "none",
+ "srcLabel": "",
+ "dst": "container.right.inner.left",
+ "dstArrow": "triangle",
+ "dstLabel": "",
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "stroke": "#0D32B2",
+ "label": "to inner left",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "#676C7E",
+ "italic": true,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 76,
+ "labelHeight": 21,
+ "labelPosition": "INSIDE_MIDDLE_CENTER",
+ "labelPercentage": 0,
+ "route": [
+ {
+ "x": 897,
+ "y": 795
+ },
+ {
+ "x": 897,
+ "y": 936
+ }
+ ],
+ "animated": false,
+ "tooltip": "",
+ "icon": null,
+ "zIndex": 0
+ },
+ {
+ "id": "container.right.(root -> inner.right)[0]",
+ "src": "container.right.root",
+ "srcArrow": "none",
+ "srcLabel": "",
+ "dst": "container.right.inner.right",
+ "dstArrow": "triangle",
+ "dstLabel": "",
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "stroke": "#0D32B2",
+ "label": "to inner right",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "#676C7E",
+ "italic": true,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 86,
+ "labelHeight": 21,
+ "labelPosition": "INSIDE_MIDDLE_CENTER",
+ "labelPercentage": 0,
+ "route": [
+ {
+ "x": 939.6666666666667,
+ "y": 795
+ },
+ {
+ "x": 939.6666666666667,
+ "y": 846
+ },
+ {
+ "x": 1045,
+ "y": 846
+ },
+ {
+ "x": 1045,
+ "y": 936
+ }
+ ],
+ "animated": false,
+ "tooltip": "",
+ "icon": null,
+ "zIndex": 0
+ },
+ {
+ "id": "container.(root -> left.root)[0]",
+ "src": "container.root",
+ "srcArrow": "none",
+ "srcLabel": "",
+ "dst": "container.left.root",
+ "dstArrow": "triangle",
+ "dstLabel": "",
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "stroke": "#0D32B2",
+ "label": "to left container root",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "#676C7E",
+ "italic": true,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 136,
+ "labelHeight": 21,
+ "labelPosition": "INSIDE_MIDDLE_CENTER",
+ "labelPercentage": 0,
+ "route": [
+ {
+ "x": 322.33333333333337,
+ "y": 500
+ },
+ {
+ "x": 322.33333333333337,
+ "y": 641
+ }
+ ],
+ "animated": false,
+ "tooltip": "",
+ "icon": null,
+ "zIndex": 0
+ },
+ {
+ "id": "container.(root -> right.root)[0]",
+ "src": "container.root",
+ "srcArrow": "none",
+ "srcLabel": "",
+ "dst": "container.right.root",
+ "dstArrow": "triangle",
+ "dstLabel": "",
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "stroke": "#0D32B2",
+ "label": "to right container root",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "#676C7E",
+ "italic": true,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 146,
+ "labelHeight": 21,
+ "labelPosition": "INSIDE_MIDDLE_CENTER",
+ "labelPercentage": 0,
+ "route": [
+ {
+ "x": 365,
+ "y": 500
+ },
+ {
+ "x": 365,
+ "y": 510
+ },
+ {
+ "x": 918.3333333333334,
+ "y": 510
+ },
+ {
+ "x": 918.3333333333334,
+ "y": 641
+ }
+ ],
+ "animated": false,
+ "tooltip": "",
+ "icon": null,
+ "zIndex": 0
+ }
+ ]
+}
diff --git a/e2etests/testdata/stable/overlapping_image_container_labels/elk/sketch.exp.svg b/e2etests/testdata/stable/overlapping_image_container_labels/elk/sketch.exp.svg
new file mode 100644
index 000000000..c25a9441f
--- /dev/null
+++ b/e2etests/testdata/stable/overlapping_image_container_labels/elk/sketch.exp.svg
@@ -0,0 +1,50 @@
+
+
\ No newline at end of file