Add double circle shape

This commit is contained in:
OneRain2333 2022-12-30 17:14:44 +08:00
parent 5abde05b86
commit 8bb86250fb
6 changed files with 74 additions and 7 deletions

View file

@ -804,7 +804,7 @@ func (c *compiler) validateKey(obj *d2graph.Object, m *d2ast.Map, mk *d2ast.Key)
if reserved == "" {
c.errorf(mk.Range.Start, mk.Range.End, "image shapes cannot have children.")
}
case d2target.ShapeCircle, d2target.ShapeSquare:
case d2target.ShapeCircle, d2target.ShapeSquare, d2target.ShapeDoubleCircle:
checkEqual := (reserved == "width" && obj.Attributes.Height != nil) ||
(reserved == "height" && obj.Attributes.Width != nil)

View file

@ -353,7 +353,7 @@ func (obj *Object) GetFill(theme *d2themes.Theme) string {
shape := obj.Attributes.Shape.Value
if shape == "" || strings.EqualFold(shape, d2target.ShapeSquare) || strings.EqualFold(shape, d2target.ShapeCircle) || strings.EqualFold(shape, d2target.ShapeOval) || strings.EqualFold(shape, d2target.ShapeRectangle) {
if shape == "" || strings.EqualFold(shape, d2target.ShapeSquare) || strings.EqualFold(shape, d2target.ShapeCircle) || strings.EqualFold(shape, d2target.ShapeDoubleCircle) || strings.EqualFold(shape, d2target.ShapeOval) || strings.EqualFold(shape, d2target.ShapeRectangle) {
if level == 1 {
if !obj.IsContainer() {
return theme.Colors.B6
@ -1138,7 +1138,7 @@ func (g *Graph) SetDimensions(mtexts []*d2target.MText, ruler *textmeasure.Ruler
paddingX, paddingY := obj.GetPadding()
switch shapeType {
case d2target.ShapeSquare, d2target.ShapeCircle:
case d2target.ShapeSquare, d2target.ShapeCircle, d2target.ShapeDoubleCircle:
if desiredWidth != 0 || desiredHeight != 0 {
paddingX = 0.
paddingY = 0.

View file

@ -589,6 +589,17 @@ func renderOval(tl *geo.Point, width, height float64, style string) string {
return fmt.Sprintf(`<ellipse class="shape" cx="%f" cy="%f" rx="%f" ry="%f" style="%s" />`, cx, cy, rx, ry, style)
}
func renderDoubleCircle(tl *geo.Point, width, height float64, style string) string {
rx := width / 2
ry := height / 2
cx := tl.X + rx
cy := tl.Y + ry
return fmt.Sprintf(`<ellipse class="shape" cx="%f" cy="%f" rx="%f" ry="%f" style="%s" />
<ellipse class="shape" cx="%f" cy="%f" rx="%f" ry="%f" style="%s" />`,
cx, cy, rx-2, ry-2, style,
cx, cy, rx-10, ry-10, style)
}
func defineShadowFilter(writer io.Writer) {
fmt.Fprint(writer, `<defs>
<filter id="shadow-filter" width="200%" height="200%" x="-50%" y="-50%">
@ -772,6 +783,19 @@ func drawShape(writer io.Writer, targetShape d2target.Shape, sketchRunner *d2ske
} else {
fmt.Fprint(writer, renderOval(tl, width, height, style))
}
case d2target.ShapeDoubleCircle:
if targetShape.Multiple {
fmt.Fprint(writer, renderDoubleCircle(multipleTL, width, height, style))
}
if sketchRunner != nil {
out, err := d2sketch.Oval(sketchRunner, targetShape)
if err != nil {
return "", err
}
fmt.Fprintf(writer, out)
} else {
fmt.Fprint(writer, renderDoubleCircle(tl, width, height, style))
}
case d2target.ShapeImage:
fmt.Fprintf(writer, `<image href="%s" x="%d" y="%d" width="%d" height="%d" style="%s" />`,

View file

@ -427,6 +427,7 @@ const (
ShapeSQLTable = "sql_table"
ShapeImage = "image"
ShapeSequenceDiagram = "sequence_diagram"
ShapeDoubleCircle = "double_circle"
)
var Shapes = []string{
@ -453,6 +454,7 @@ var Shapes = []string{
ShapeSQLTable,
ShapeImage,
ShapeSequenceDiagram,
ShapeDoubleCircle,
}
func IsShape(s string) bool {

View file

@ -24,6 +24,7 @@ const (
CIRCLE_TYPE = "Circle"
HEXAGON_TYPE = "Hexagon"
CLOUD_TYPE = "Cloud"
DOUBLE_CIRCLE_TYPE = "DoubleCircle"
TABLE_TYPE = "Table"
CLASS_TYPE = "Class"
@ -108,6 +109,8 @@ func NewShape(shapeType string, box *geo.Box) Shape {
return NewCallout(box)
case CIRCLE_TYPE:
return NewCircle(box)
case DOUBLE_CIRCLE_TYPE:
return NewDoubleCircle(box)
case CLASS_TYPE:
return NewClass(box)
case CLOUD_TYPE:
@ -164,10 +167,11 @@ func NewShape(shapeType string, box *geo.Box) Shape {
// p is the prev point (used to calculate slope)
// s is the point on the actual shape border that'll be returned
//
// p
// │
// │
// ▼
// p
// │
// │
// ▼
//
// ┌────r─────────────────────────┐
// │ │
// │ │ │

View file

@ -0,0 +1,37 @@
package shape
import (
"oss.terrastruct.com/d2/lib/geo"
"oss.terrastruct.com/d2/lib/svg"
)
type shapeDoubleCircle struct {
*baseShape
}
func NewDoubleCircle(box *geo.Box) Shape {
return shapeDoubleCircle{
baseShape: &baseShape{
Type: DOUBLE_CIRCLE_TYPE,
Box: box,
},
}
}
func doubleCirclePath(box *geo.Box) *svg.SvgPathContext {
// halfYFactor := 43.6 / 87.3
pc := svg.NewSVGPathContext(box.TopLeft, box.Width, box.Height)
pc.StartAt(pc.Absolute(0.25, 0))
// pc
return pc
}
func (s shapeDoubleCircle) Perimeter() []geo.Intersectable {
return doubleCirclePath(s.Box).Path
}
func (s shapeDoubleCircle) GetSVGPathData() []string {
return []string{
doubleCirclePath(s.Box).PathData(),
}
}