diff --git a/d2exporter/export.go b/d2exporter/export.go
index 99e8db2d0..56f4b9146 100644
--- a/d2exporter/export.go
+++ b/d2exporter/export.go
@@ -194,11 +194,8 @@ func applyStyles(shape *d2target.Shape, obj *d2graph.Object) {
if obj.Style.DoubleBorder != nil {
shape.DoubleBorder, _ = strconv.ParseBool(obj.Style.DoubleBorder.Value)
}
- if obj.IconStyle != (d2graph.Style{}) {
- shape.IconStyle = &d2target.ShapeIconStyle{}
- }
if obj.IconStyle.BorderRadius != nil {
- shape.IconStyle.BorderRadius, _ = strconv.Atoi(obj.IconStyle.BorderRadius.Value)
+ shape.IconBorderRadius, _ = strconv.Atoi(obj.IconStyle.BorderRadius.Value)
}
}
diff --git a/d2renderers/d2svg/d2svg.go b/d2renderers/d2svg/d2svg.go
index 0d0bb44fc..a71580121 100644
--- a/d2renderers/d2svg/d2svg.go
+++ b/d2renderers/d2svg/d2svg.go
@@ -853,25 +853,18 @@ func drawConnection(writer io.Writer, diagramHash string, connection d2target.Co
if connection.Icon != nil {
iconPos := connection.GetIconPosition()
if iconPos != nil {
+ connectionIconClipPath := ""
if connection.IconBorderRadius != 0 {
- fmt.Fprintf(writer, ``,
- html.EscapeString(connection.Icon.String()),
- iconPos.X,
- iconPos.Y,
- d2target.DEFAULT_ICON_SIZE,
- d2target.DEFAULT_ICON_SIZE,
- connection.IconBorderRadius,
- )
- } else {
-
- fmt.Fprintf(writer, ``,
- html.EscapeString(connection.Icon.String()),
- iconPos.X,
- iconPos.Y,
- d2target.DEFAULT_ICON_SIZE,
- d2target.DEFAULT_ICON_SIZE,
- )
+ connectionIconClipPath = fmt.Sprintf(` clip-path="inset(0 round %fpx)"`, connection.IconBorderRadius)
}
+ fmt.Fprintf(writer, ``,
+ html.EscapeString(connection.Icon.String()),
+ iconPos.X,
+ iconPos.Y,
+ d2target.DEFAULT_ICON_SIZE,
+ d2target.DEFAULT_ICON_SIZE,
+ connectionIconClipPath,
+ )
}
}
@@ -1447,9 +1440,10 @@ func drawShape(writer, appendixWriter io.Writer, diagramHash string, targetShape
el.Fill = fill
el.Stroke = stroke
el.Style = style
- if targetShape.IconStyle != nil && targetShape.IconStyle.BorderRadius != 0 {
- fmt.Fprint(writer, clipPathForIconBorderRadius(diagramHash, targetShape))
- el.ClipPath = fmt.Sprintf("%v-%v-icon", diagramHash, targetShape.ID)
+ if targetShape.IconBorderRadius != 0 {
+ clipPathId := fmt.Sprintf("%v-%v-icon", diagramHash, svg.SVGID(targetShape.ID))
+ fmt.Fprint(writer, applyIconBorderRadius(clipPathId, targetShape))
+ el.ClipPath = clipPathId
}
fmt.Fprint(writer, el.Render())
@@ -1643,24 +1637,18 @@ func drawShape(writer, appendixWriter io.Writer, diagramHash string, targetShape
tl := iconPosition.GetPointOnBox(box, label.PADDING, float64(iconSize), float64(iconSize))
- if targetShape.IconStyle != nil && targetShape.IconStyle.BorderRadius != 0 {
- fmt.Fprintf(writer, ``,
- html.EscapeString(targetShape.Icon.String()),
- tl.X,
- tl.Y,
- iconSize,
- iconSize,
- targetShape.IconStyle.BorderRadius,
- )
- } else {
- fmt.Fprintf(writer, ``,
- html.EscapeString(targetShape.Icon.String()),
- tl.X,
- tl.Y,
- iconSize,
- iconSize,
- )
+ shapeIconClipPath := ""
+ if targetShape.IconBorderRadius != 0 {
+ shapeIconClipPath = fmt.Sprintf(` clip-path="inset(0 round %dpx)"`, targetShape.IconBorderRadius)
}
+ fmt.Fprintf(writer, ``,
+ html.EscapeString(targetShape.Icon.String()),
+ tl.X,
+ tl.Y,
+ iconSize,
+ iconSize,
+ shapeIconClipPath,
+ )
}
if targetShape.Label != "" && targetShape.Opacity != 0 {
@@ -1889,6 +1877,28 @@ func drawShape(writer, appendixWriter io.Writer, diagramHash string, targetShape
return labelMask, nil
}
+func applyIconBorderRadius(clipPathId string, shape d2target.Shape) string {
+ box := geo.NewBox(
+ geo.NewPoint(float64(shape.Pos.X), float64(shape.Pos.Y)),
+ float64(shape.Width),
+ float64(shape.Height),
+ )
+ topX, topY := box.TopLeft.X+box.Width, box.TopLeft.Y
+
+ out := fmt.Sprintf(``, clipPathId)
+ out += fmt.Sprintf(` `
+}
+
func addAppendixItems(writer io.Writer, diagramHash string, targetShape d2target.Shape, s shape.Shape) {
var p1, p2 *geo.Point
if targetShape.Tooltip != "" || targetShape.Link != "" {
diff --git a/d2renderers/d2svg/table.go b/d2renderers/d2svg/table.go
index 2499836fc..f7b2782db 100644
--- a/d2renderers/d2svg/table.go
+++ b/d2renderers/d2svg/table.go
@@ -41,28 +41,6 @@ func clipPathForBorderRadius(diagramHash string, shape d2target.Shape) string {
return out + `fill="none" /> `
}
-func clipPathForIconBorderRadius(diagramHash string, shape d2target.Shape) string {
- box := geo.NewBox(
- geo.NewPoint(float64(shape.Pos.X), float64(shape.Pos.Y)),
- float64(shape.Width),
- float64(shape.Height),
- )
- topX, topY := box.TopLeft.X+box.Width, box.TopLeft.Y
-
- out := fmt.Sprintf(``, diagramHash, shape.ID)
- out += fmt.Sprintf(` `
-}
-
func tableHeader(diagramHash string, shape d2target.Shape, box *geo.Box, text string, textWidth, textHeight, fontSize float64, inlineTheme *d2themes.Theme) string {
rectEl := d2themes.NewThemableElement("rect", inlineTheme)
rectEl.X, rectEl.Y = box.TopLeft.X, box.TopLeft.Y
diff --git a/d2target/d2target.go b/d2target/d2target.go
index 81518a966..4880c2859 100644
--- a/d2target/d2target.go
+++ b/d2target/d2target.go
@@ -503,12 +503,12 @@ type Shape struct {
Multiple bool `json:"multiple"`
DoubleBorder bool `json:"double-border"`
- Tooltip string `json:"tooltip"`
- Link string `json:"link"`
- PrettyLink string `json:"prettyLink,omitempty"`
- Icon *url.URL `json:"icon"`
- IconStyle *ShapeIconStyle `json:"iconStyle,omitempty"`
- IconPosition string `json:"iconPosition"`
+ Tooltip string `json:"tooltip"`
+ Link string `json:"link"`
+ PrettyLink string `json:"prettyLink,omitempty"`
+ Icon *url.URL `json:"icon"`
+ IconBorderRadius int `json:"iconBorderRadius,omitempty"`
+ IconPosition string `json:"iconPosition"`
// Whether the shape should allow shapes behind it to bleed through
// Currently just used for sequence diagram groups
@@ -532,10 +532,6 @@ type Shape struct {
NeutralAccentColor string `json:"neutralAccentColor,omitempty"`
}
-type ShapeIconStyle struct {
- BorderRadius int `json:"borderRadius"`
-}
-
func (s Shape) GetFontColor() string {
if s.Type == ShapeClass || s.Type == ShapeSQLTable {
if !color.IsThemeColor(s.Color) {
diff --git a/e2etests/testdata/txtar/icon-style/dagre/board.exp.json b/e2etests/testdata/txtar/icon-style/dagre/board.exp.json
index 768640279..ae8607e6d 100644
--- a/e2etests/testdata/txtar/icon-style/dagre/board.exp.json
+++ b/e2etests/testdata/txtar/icon-style/dagre/board.exp.json
@@ -46,9 +46,7 @@
"Fragment": "",
"RawFragment": ""
},
- "iconStyle": {
- "borderRadius": 20
- },
+ "iconBorderRadius": 20,
"iconPosition": "INSIDE_MIDDLE_CENTER",
"blend": false,
"fields": null,
diff --git a/e2etests/testdata/txtar/icon-style/dagre/sketch.exp.svg b/e2etests/testdata/txtar/icon-style/dagre/sketch.exp.svg
index 7e69de058..f8018d37f 100644
--- a/e2etests/testdata/txtar/icon-style/dagre/sketch.exp.svg
+++ b/e2etests/testdata/txtar/icon-style/dagre/sketch.exp.svg
@@ -1,9 +1,9 @@
-
\ No newline at end of file
diff --git a/e2etests/testdata/txtar/icon-style/elk/board.exp.json b/e2etests/testdata/txtar/icon-style/elk/board.exp.json
index 429ca832b..67f46fcbf 100644
--- a/e2etests/testdata/txtar/icon-style/elk/board.exp.json
+++ b/e2etests/testdata/txtar/icon-style/elk/board.exp.json
@@ -46,9 +46,7 @@
"Fragment": "",
"RawFragment": ""
},
- "iconStyle": {
- "borderRadius": 20
- },
+ "iconBorderRadius": 20,
"iconPosition": "INSIDE_MIDDLE_CENTER",
"blend": false,
"fields": null,
diff --git a/e2etests/testdata/txtar/icon-style/elk/sketch.exp.svg b/e2etests/testdata/txtar/icon-style/elk/sketch.exp.svg
index 9c23b0493..223b98b4c 100644
--- a/e2etests/testdata/txtar/icon-style/elk/sketch.exp.svg
+++ b/e2etests/testdata/txtar/icon-style/elk/sketch.exp.svg
@@ -1,9 +1,9 @@
- lambda
+ .d2-2677970358 .fill-N1{fill:#0A0F25;}
+ .d2-2677970358 .fill-N2{fill:#676C7E;}
+ .d2-2677970358 .fill-N3{fill:#9499AB;}
+ .d2-2677970358 .fill-N4{fill:#CFD2DD;}
+ .d2-2677970358 .fill-N5{fill:#DEE1EB;}
+ .d2-2677970358 .fill-N6{fill:#EEF1F8;}
+ .d2-2677970358 .fill-N7{fill:#FFFFFF;}
+ .d2-2677970358 .fill-B1{fill:#0D32B2;}
+ .d2-2677970358 .fill-B2{fill:#0D32B2;}
+ .d2-2677970358 .fill-B3{fill:#E3E9FD;}
+ .d2-2677970358 .fill-B4{fill:#E3E9FD;}
+ .d2-2677970358 .fill-B5{fill:#EDF0FD;}
+ .d2-2677970358 .fill-B6{fill:#F7F8FE;}
+ .d2-2677970358 .fill-AA2{fill:#4A6FF3;}
+ .d2-2677970358 .fill-AA4{fill:#EDF0FD;}
+ .d2-2677970358 .fill-AA5{fill:#F7F8FE;}
+ .d2-2677970358 .fill-AB4{fill:#EDF0FD;}
+ .d2-2677970358 .fill-AB5{fill:#F7F8FE;}
+ .d2-2677970358 .stroke-N1{stroke:#0A0F25;}
+ .d2-2677970358 .stroke-N2{stroke:#676C7E;}
+ .d2-2677970358 .stroke-N3{stroke:#9499AB;}
+ .d2-2677970358 .stroke-N4{stroke:#CFD2DD;}
+ .d2-2677970358 .stroke-N5{stroke:#DEE1EB;}
+ .d2-2677970358 .stroke-N6{stroke:#EEF1F8;}
+ .d2-2677970358 .stroke-N7{stroke:#FFFFFF;}
+ .d2-2677970358 .stroke-B1{stroke:#0D32B2;}
+ .d2-2677970358 .stroke-B2{stroke:#0D32B2;}
+ .d2-2677970358 .stroke-B3{stroke:#E3E9FD;}
+ .d2-2677970358 .stroke-B4{stroke:#E3E9FD;}
+ .d2-2677970358 .stroke-B5{stroke:#EDF0FD;}
+ .d2-2677970358 .stroke-B6{stroke:#F7F8FE;}
+ .d2-2677970358 .stroke-AA2{stroke:#4A6FF3;}
+ .d2-2677970358 .stroke-AA4{stroke:#EDF0FD;}
+ .d2-2677970358 .stroke-AA5{stroke:#F7F8FE;}
+ .d2-2677970358 .stroke-AB4{stroke:#EDF0FD;}
+ .d2-2677970358 .stroke-AB5{stroke:#F7F8FE;}
+ .d2-2677970358 .background-color-N1{background-color:#0A0F25;}
+ .d2-2677970358 .background-color-N2{background-color:#676C7E;}
+ .d2-2677970358 .background-color-N3{background-color:#9499AB;}
+ .d2-2677970358 .background-color-N4{background-color:#CFD2DD;}
+ .d2-2677970358 .background-color-N5{background-color:#DEE1EB;}
+ .d2-2677970358 .background-color-N6{background-color:#EEF1F8;}
+ .d2-2677970358 .background-color-N7{background-color:#FFFFFF;}
+ .d2-2677970358 .background-color-B1{background-color:#0D32B2;}
+ .d2-2677970358 .background-color-B2{background-color:#0D32B2;}
+ .d2-2677970358 .background-color-B3{background-color:#E3E9FD;}
+ .d2-2677970358 .background-color-B4{background-color:#E3E9FD;}
+ .d2-2677970358 .background-color-B5{background-color:#EDF0FD;}
+ .d2-2677970358 .background-color-B6{background-color:#F7F8FE;}
+ .d2-2677970358 .background-color-AA2{background-color:#4A6FF3;}
+ .d2-2677970358 .background-color-AA4{background-color:#EDF0FD;}
+ .d2-2677970358 .background-color-AA5{background-color:#F7F8FE;}
+ .d2-2677970358 .background-color-AB4{background-color:#EDF0FD;}
+ .d2-2677970358 .background-color-AB5{background-color:#F7F8FE;}
+ .d2-2677970358 .color-N1{color:#0A0F25;}
+ .d2-2677970358 .color-N2{color:#676C7E;}
+ .d2-2677970358 .color-N3{color:#9499AB;}
+ .d2-2677970358 .color-N4{color:#CFD2DD;}
+ .d2-2677970358 .color-N5{color:#DEE1EB;}
+ .d2-2677970358 .color-N6{color:#EEF1F8;}
+ .d2-2677970358 .color-N7{color:#FFFFFF;}
+ .d2-2677970358 .color-B1{color:#0D32B2;}
+ .d2-2677970358 .color-B2{color:#0D32B2;}
+ .d2-2677970358 .color-B3{color:#E3E9FD;}
+ .d2-2677970358 .color-B4{color:#E3E9FD;}
+ .d2-2677970358 .color-B5{color:#EDF0FD;}
+ .d2-2677970358 .color-B6{color:#F7F8FE;}
+ .d2-2677970358 .color-AA2{color:#4A6FF3;}
+ .d2-2677970358 .color-AA4{color:#EDF0FD;}
+ .d2-2677970358 .color-AA5{color:#F7F8FE;}
+ .d2-2677970358 .color-AB4{color:#EDF0FD;}
+ .d2-2677970358 .color-AB5{color:#F7F8FE;}.appendix text.text{fill:#0A0F25}.md{--color-fg-default:#0A0F25;--color-fg-muted:#676C7E;--color-fg-subtle:#9499AB;--color-canvas-default:#FFFFFF;--color-canvas-subtle:#EEF1F8;--color-border-default:#0D32B2;--color-border-muted:#0D32B2;--color-neutral-muted:#EEF1F8;--color-accent-fg:#0D32B2;--color-accent-emphasis:#0D32B2;--color-attention-subtle:#676C7E;--color-danger-fg:red;}.sketch-overlay-B1{fill:url(#streaks-darker-d2-2677970358);mix-blend-mode:lighten}.sketch-overlay-B2{fill:url(#streaks-darker-d2-2677970358);mix-blend-mode:lighten}.sketch-overlay-B3{fill:url(#streaks-bright-d2-2677970358);mix-blend-mode:darken}.sketch-overlay-B4{fill:url(#streaks-bright-d2-2677970358);mix-blend-mode:darken}.sketch-overlay-B5{fill:url(#streaks-bright-d2-2677970358);mix-blend-mode:darken}.sketch-overlay-B6{fill:url(#streaks-bright-d2-2677970358);mix-blend-mode:darken}.sketch-overlay-AA2{fill:url(#streaks-dark-d2-2677970358);mix-blend-mode:overlay}.sketch-overlay-AA4{fill:url(#streaks-bright-d2-2677970358);mix-blend-mode:darken}.sketch-overlay-AA5{fill:url(#streaks-bright-d2-2677970358);mix-blend-mode:darken}.sketch-overlay-AB4{fill:url(#streaks-bright-d2-2677970358);mix-blend-mode:darken}.sketch-overlay-AB5{fill:url(#streaks-bright-d2-2677970358);mix-blend-mode:darken}.sketch-overlay-N1{fill:url(#streaks-darker-d2-2677970358);mix-blend-mode:lighten}.sketch-overlay-N2{fill:url(#streaks-dark-d2-2677970358);mix-blend-mode:overlay}.sketch-overlay-N3{fill:url(#streaks-normal-d2-2677970358);mix-blend-mode:color-burn}.sketch-overlay-N4{fill:url(#streaks-normal-d2-2677970358);mix-blend-mode:color-burn}.sketch-overlay-N5{fill:url(#streaks-bright-d2-2677970358);mix-blend-mode:darken}.sketch-overlay-N6{fill:url(#streaks-bright-d2-2677970358);mix-blend-mode:darken}.sketch-overlay-N7{fill:url(#streaks-bright-d2-2677970358);mix-blend-mode:darken}.light-code{display: block}.dark-code{display: none}]]> lambda
\ No newline at end of file