From 3d9c35d2446709adfcaadc1a4e168d6f8aef194e Mon Sep 17 00:00:00 2001 From: Gavin Nishizawa Date: Wed, 9 Nov 2022 11:10:51 -0800 Subject: [PATCH] add shadow keyword --- d2renderers/d2svg/d2svg.go | 51 ++++++++++++++++++++++++++++---------- 1 file changed, 38 insertions(+), 13 deletions(-) diff --git a/d2renderers/d2svg/d2svg.go b/d2renderers/d2svg/d2svg.go index 042ecc48e..6a76331b3 100644 --- a/d2renderers/d2svg/d2svg.go +++ b/d2renderers/d2svg/d2svg.go @@ -444,16 +444,28 @@ func drawConnection(writer io.Writer, connection d2target.Connection, markers ma } } -func renderOval(tl *geo.Point, width, height float64, style string) string { +func renderOval(tl *geo.Point, width, height float64, style, shadowAttr string) string { rx := width / 2 ry := height / 2 cx := tl.X + rx cy := tl.Y + ry - return fmt.Sprintf(``, - cx, cy, rx, ry, style, + return fmt.Sprintf(``, + cx, cy, rx, ry, style, shadowAttr, ) } +func defineShadowFilter(writer io.Writer) { + fmt.Fprint(writer, ` + + + + + + + +`) +} + func drawShape(writer io.Writer, targetShape d2target.Shape) error { tl := geo.NewPoint(float64(targetShape.Pos.X), float64(targetShape.Pos.Y)) width := float64(targetShape.Width) @@ -468,6 +480,11 @@ func drawShape(writer io.Writer, targetShape d2target.Shape) error { multipleTL = tl.AddVector(multipleOffset) } + var shadowAttr string + if targetShape.Shadow { + shadowAttr = `filter="url(#shadow-filter)" ` + } + switch targetShape.Type { case d2target.ShapeClass: drawClass(writer, targetShape) @@ -477,34 +494,34 @@ func drawShape(writer io.Writer, targetShape d2target.Shape) error { return nil case d2target.ShapeOval: if targetShape.Multiple { - fmt.Fprint(writer, renderOval(multipleTL, width, height, style)) + fmt.Fprint(writer, renderOval(multipleTL, width, height, style, shadowAttr)) } - fmt.Fprint(writer, renderOval(tl, width, height, style)) + fmt.Fprint(writer, renderOval(tl, width, height, style, shadowAttr)) case d2target.ShapeImage: - fmt.Fprintf(writer, ``, + fmt.Fprintf(writer, ``, targetShape.Icon.String(), - targetShape.Pos.X, targetShape.Pos.Y, targetShape.Width, targetShape.Height, style) + targetShape.Pos.X, targetShape.Pos.Y, targetShape.Width, targetShape.Height, style, shadowAttr) case d2target.ShapeText: case d2target.ShapeCode: // TODO should standardize "" to rectangle case d2target.ShapeRectangle, "": if targetShape.Multiple { - fmt.Fprintf(writer, ``, - targetShape.Pos.X+10, targetShape.Pos.Y-10, targetShape.Width, targetShape.Height, style) + fmt.Fprintf(writer, ``, + targetShape.Pos.X+10, targetShape.Pos.Y-10, targetShape.Width, targetShape.Height, style, shadowAttr) } - fmt.Fprintf(writer, ``, - targetShape.Pos.X, targetShape.Pos.Y, targetShape.Width, targetShape.Height, style) + fmt.Fprintf(writer, ``, + targetShape.Pos.X, targetShape.Pos.Y, targetShape.Width, targetShape.Height, style, shadowAttr) default: if targetShape.Multiple { multiplePathData := shape.NewShape(shapeType, geo.NewBox(multipleTL, width, height)).GetSVGPathData() for _, pathData := range multiplePathData { - fmt.Fprintf(writer, ``, pathData, style) + fmt.Fprintf(writer, ``, pathData, style, shadowAttr) } } for _, pathData := range s.GetSVGPathData() { - fmt.Fprintf(writer, ``, pathData, style) + fmt.Fprintf(writer, ``, pathData, style, shadowAttr) } } @@ -796,6 +813,14 @@ func Render(diagram *d2target.Diagram) ([]byte, error) { fmt.Fprintf(buf, ``, mdCSS) } + // only define shadow filter if a shape uses it + for _, s := range diagram.Shapes { + if s.Shadow { + defineShadowFilter(buf) + break + } + } + // SVG has no notion of z-index. The z-index is effectively the order it's drawn. // So draw from the least nested to most nested idToShape := make(map[string]d2target.Shape)