This commit is contained in:
parent
71ffecc2d5
commit
ff704930c8
7 changed files with 308 additions and 355 deletions
|
@ -9,10 +9,11 @@ import lustre/attribute.{style} as _attribute
|
||||||
import lustre/element.{type Element, fragment, to_readable_string} as _element
|
import lustre/element.{type Element, fragment, to_readable_string} as _element
|
||||||
import lustre/element/html.{svg}
|
import lustre/element/html.{svg}
|
||||||
import simplifile
|
import simplifile
|
||||||
import svg_attribute as attribute
|
import svg/attribute
|
||||||
import svg_element as element
|
import svg/element
|
||||||
import svg_path as path
|
import svg/path
|
||||||
import svg_transform as transform
|
import svg/styles
|
||||||
|
import svg/transform
|
||||||
|
|
||||||
pub fn get_footprint(
|
pub fn get_footprint(
|
||||||
library_location: String,
|
library_location: String,
|
||||||
|
@ -122,71 +123,31 @@ pub fn main() -> Nil {
|
||||||
const bg_col = "#001021"
|
const bg_col = "#001021"
|
||||||
|
|
||||||
fn create_svg(footprint: Footprint) -> String {
|
fn create_svg(footprint: Footprint) -> String {
|
||||||
let fill = None
|
let styles = styles.new()
|
||||||
let stroke = None
|
|
||||||
let stroke_width = None
|
|
||||||
let transform = None
|
let transform = None
|
||||||
svg([attribute.view_box(-4.0, -4.0, 8.0, 8.0), style("background", bg_col)], [
|
svg([attribute.view_box(-4.0, -4.0, 8.0, 8.0), style("background", bg_col)], [
|
||||||
element.group(
|
element.group(
|
||||||
fill:,
|
styles: styles
|
||||||
stroke: Some("#BBBBBB"),
|
|> styles.with_stroke("#BBBBBB")
|
||||||
stroke_width: Some(0.01),
|
|> styles.with_stroke_width(0.01),
|
||||||
transform:,
|
transform:,
|
||||||
children: [
|
children: [
|
||||||
element.line(
|
element.line(styles:, transform:, x1: -4.0, y1: 0.0, x2: 4.0, y2: 0.0),
|
||||||
fill:,
|
element.line(styles:, transform:, x1: 0.0, y1: -4.0, x2: 0.0, y2: 4.0),
|
||||||
stroke:,
|
|
||||||
stroke_width:,
|
|
||||||
transform:,
|
|
||||||
x1: -4.0,
|
|
||||||
y1: 0.0,
|
|
||||||
x2: 4.0,
|
|
||||||
y2: 0.0,
|
|
||||||
),
|
|
||||||
element.line(
|
|
||||||
fill:,
|
|
||||||
stroke:,
|
|
||||||
stroke_width:,
|
|
||||||
transform:,
|
|
||||||
x1: 0.0,
|
|
||||||
y1: -4.0,
|
|
||||||
x2: 0.0,
|
|
||||||
y2: 4.0,
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
element.group(
|
element.group(
|
||||||
fill:,
|
styles: styles
|
||||||
stroke: Some("#FF00FF"),
|
|> styles.with_stroke("#FF00FF")
|
||||||
stroke_width: Some(0.01),
|
|> styles.with_stroke_width(0.01),
|
||||||
transform:,
|
transform:,
|
||||||
children: [
|
children: [
|
||||||
element.line(
|
element.line(styles:, transform:, x1: -0.05, y1: 0.0, x2: 0.05, y2: 0.0),
|
||||||
fill:,
|
element.line(styles:, transform:, x1: 0.0, y1: -0.05, x2: 0.0, y2: 0.05),
|
||||||
stroke:,
|
|
||||||
stroke_width:,
|
|
||||||
transform:,
|
|
||||||
x1: -0.05,
|
|
||||||
y1: 0.0,
|
|
||||||
x2: 0.05,
|
|
||||||
y2: 0.0,
|
|
||||||
),
|
|
||||||
element.line(
|
|
||||||
fill:,
|
|
||||||
stroke:,
|
|
||||||
stroke_width:,
|
|
||||||
transform:,
|
|
||||||
x1: 0.0,
|
|
||||||
y1: -0.05,
|
|
||||||
x2: 0.0,
|
|
||||||
y2: 0.05,
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
element.group(
|
element.group(
|
||||||
fill: Some("#CE3431"),
|
styles: styles |> styles.with_fill("#CE3431"),
|
||||||
stroke:,
|
|
||||||
stroke_width:,
|
|
||||||
transform:,
|
transform:,
|
||||||
children: footprint.pads
|
children: footprint.pads
|
||||||
|> list.filter(fn(pad) {
|
|> list.filter(fn(pad) {
|
||||||
|
@ -206,9 +167,7 @@ fn pad_to_element(pad: Pad) -> Element(a) {
|
||||||
let nh = -1.0 *. h
|
let nh = -1.0 *. h
|
||||||
let hw = w /. 2.0
|
let hw = w /. 2.0
|
||||||
let hh = h /. 2.0
|
let hh = h /. 2.0
|
||||||
let fill = None
|
let styles = styles.new()
|
||||||
let stroke = None
|
|
||||||
let stroke_width = None
|
|
||||||
let transform =
|
let transform =
|
||||||
angle
|
angle
|
||||||
|> option.map(fn(angle) {
|
|> option.map(fn(angle) {
|
||||||
|
@ -227,29 +186,12 @@ fn pad_to_element(pad: Pad) -> Element(a) {
|
||||||
}
|
}
|
||||||
let elem = case pad.shape {
|
let elem = case pad.shape {
|
||||||
token.CirclePadShape ->
|
token.CirclePadShape ->
|
||||||
element.circle(
|
element.circle(styles:, transform:, cx: ox, cy: oy, r: hw)
|
||||||
fill:,
|
|
||||||
stroke:,
|
|
||||||
stroke_width:,
|
|
||||||
transform:,
|
|
||||||
cx: ox,
|
|
||||||
cy: oy,
|
|
||||||
r: hw,
|
|
||||||
)
|
|
||||||
token.OvalPadShape ->
|
token.OvalPadShape ->
|
||||||
case float.compare(w, h) {
|
case float.compare(w, h) {
|
||||||
order.Eq ->
|
order.Eq -> element.circle(styles:, transform:, cx: ox, cy: oy, r: hw)
|
||||||
element.circle(
|
|
||||||
fill:,
|
|
||||||
stroke:,
|
|
||||||
stroke_width:,
|
|
||||||
transform:,
|
|
||||||
cx: ox,
|
|
||||||
cy: oy,
|
|
||||||
r: hw,
|
|
||||||
)
|
|
||||||
order.Lt ->
|
order.Lt ->
|
||||||
element.path(fill:, stroke:, stroke_width:, transform:, path: [
|
element.path(styles:, transform:, path: [
|
||||||
path.MoveAbsolute(x: ox +. hw, y: oy +. hw -. hh),
|
path.MoveAbsolute(x: ox +. hw, y: oy +. hw -. hh),
|
||||||
path.ArcCurveRelative(
|
path.ArcCurveRelative(
|
||||||
rx: hw,
|
rx: hw,
|
||||||
|
@ -273,7 +215,7 @@ fn pad_to_element(pad: Pad) -> Element(a) {
|
||||||
path.ClosePath,
|
path.ClosePath,
|
||||||
])
|
])
|
||||||
order.Gt ->
|
order.Gt ->
|
||||||
element.path(fill:, stroke:, stroke_width:, transform:, path: [
|
element.path(styles:, transform:, path: [
|
||||||
path.MoveAbsolute(x: ox +. hh -. hw, y: oy -. hh),
|
path.MoveAbsolute(x: ox +. hh -. hw, y: oy -. hh),
|
||||||
path.ArcCurveRelative(
|
path.ArcCurveRelative(
|
||||||
rx: hh,
|
rx: hh,
|
||||||
|
@ -317,9 +259,7 @@ fn pad_to_element(pad: Pad) -> Element(a) {
|
||||||
case rounding, pad.chamfer, chamfering {
|
case rounding, pad.chamfer, chamfering {
|
||||||
None, Some([]), _ | None, None, _ | None, _, None ->
|
None, Some([]), _ | None, None, _ | None, _, None ->
|
||||||
element.centered_rect(
|
element.centered_rect(
|
||||||
fill:,
|
styles:,
|
||||||
stroke:,
|
|
||||||
stroke_width:,
|
|
||||||
transform:,
|
transform:,
|
||||||
x: ox,
|
x: ox,
|
||||||
y: oy,
|
y: oy,
|
||||||
|
@ -332,9 +272,7 @@ fn pad_to_element(pad: Pad) -> Element(a) {
|
||||||
-> {
|
-> {
|
||||||
let radius = rounding *. float.min(w, h)
|
let radius = rounding *. float.min(w, h)
|
||||||
element.centered_rounded_rect(
|
element.centered_rounded_rect(
|
||||||
fill:,
|
styles:,
|
||||||
stroke:,
|
|
||||||
stroke_width:,
|
|
||||||
transform:,
|
transform:,
|
||||||
x: ox,
|
x: ox,
|
||||||
y: oy,
|
y: oy,
|
||||||
|
@ -393,7 +331,7 @@ fn pad_to_element(pad: Pad) -> Element(a) {
|
||||||
]
|
]
|
||||||
False -> [path.MoveAbsolute(x: ox -. hw, y: oy -. hh), ..path]
|
False -> [path.MoveAbsolute(x: ox -. hw, y: oy -. hh), ..path]
|
||||||
}
|
}
|
||||||
element.path(fill:, stroke:, stroke_width:, transform:, path:)
|
element.path(styles:, transform:, path:)
|
||||||
}
|
}
|
||||||
Some(rounding), Some(corners), Some(chamfering) -> {
|
Some(rounding), Some(corners), Some(chamfering) -> {
|
||||||
let #(tl, tr, bl, br) = chamfered_corners(corners)
|
let #(tl, tr, bl, br) = chamfered_corners(corners)
|
||||||
|
@ -494,7 +432,7 @@ fn pad_to_element(pad: Pad) -> Element(a) {
|
||||||
..path
|
..path
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
element.path(fill:, stroke:, stroke_width:, transform:, path:)
|
element.path(styles:, transform:, path:)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -510,7 +448,7 @@ fn pad_to_element(pad: Pad) -> Element(a) {
|
||||||
path.LineRelative(dx: no, dy: nh),
|
path.LineRelative(dx: no, dy: nh),
|
||||||
path.ClosePath,
|
path.ClosePath,
|
||||||
]
|
]
|
||||||
element.path(fill:, stroke:, stroke_width:, transform:, path:)
|
element.path(styles:, transform:, path:)
|
||||||
}
|
}
|
||||||
Some(token.XY(x: o, y: 0.0)) -> {
|
Some(token.XY(x: o, y: 0.0)) -> {
|
||||||
let no = -1.0 *. o
|
let no = -1.0 *. o
|
||||||
|
@ -522,13 +460,11 @@ fn pad_to_element(pad: Pad) -> Element(a) {
|
||||||
path.LineRelative(dx: nw, dy: no),
|
path.LineRelative(dx: nw, dy: no),
|
||||||
path.ClosePath,
|
path.ClosePath,
|
||||||
]
|
]
|
||||||
element.path(fill:, stroke:, stroke_width:, transform:, path:)
|
element.path(styles:, transform:, path:)
|
||||||
}
|
}
|
||||||
_ ->
|
_ ->
|
||||||
element.centered_rect(
|
element.centered_rect(
|
||||||
fill:,
|
styles:,
|
||||||
stroke:,
|
|
||||||
stroke_width:,
|
|
||||||
transform:,
|
transform:,
|
||||||
x: ox,
|
x: ox,
|
||||||
y: oy,
|
y: oy,
|
||||||
|
@ -539,21 +475,11 @@ fn pad_to_element(pad: Pad) -> Element(a) {
|
||||||
token.CustomPadShape ->
|
token.CustomPadShape ->
|
||||||
case pad.custom_options {
|
case pad.custom_options {
|
||||||
Some(token.CustomPadOptions(anchor: token.CircleAnchorPadShape, ..)) ->
|
Some(token.CustomPadOptions(anchor: token.CircleAnchorPadShape, ..)) ->
|
||||||
element.circle(
|
element.circle(styles:, transform:, cx: ox, cy: oy, r: hw)
|
||||||
fill:,
|
|
||||||
stroke:,
|
|
||||||
stroke_width:,
|
|
||||||
transform:,
|
|
||||||
cx: ox,
|
|
||||||
cy: oy,
|
|
||||||
r: hw,
|
|
||||||
)
|
|
||||||
Some(token.CustomPadOptions(anchor: token.RectangleAnchorPadShape, ..))
|
Some(token.CustomPadOptions(anchor: token.RectangleAnchorPadShape, ..))
|
||||||
| None ->
|
| None ->
|
||||||
element.centered_rect(
|
element.centered_rect(
|
||||||
fill:,
|
styles:,
|
||||||
stroke:,
|
|
||||||
stroke_width:,
|
|
||||||
transform:,
|
transform:,
|
||||||
x: ox,
|
x: ox,
|
||||||
y: oy,
|
y: oy,
|
||||||
|
@ -562,25 +488,22 @@ fn pad_to_element(pad: Pad) -> Element(a) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let #(fill, stroke, stroke_width) = case pad.type_ {
|
let styles = case pad.type_ {
|
||||||
token.ThroughHolePadType -> #(Some(bg_col), Some("#E7B629"), Some(0.03333))
|
token.ThroughHolePadType ->
|
||||||
token.NpThroughHolePadType -> #(Some("#18C7D6"), None, None)
|
styles.new()
|
||||||
_ -> #(None, None, None)
|
|> styles.with_fill(bg_col)
|
||||||
|
|> styles.with_stroke("#E7B629")
|
||||||
|
|> styles.with_stroke_width(0.06666)
|
||||||
|
|> styles.with_paint_order([styles.StrokeComponent])
|
||||||
|
token.NpThroughHolePadType -> styles.new() |> styles.with_fill("#18C7D6")
|
||||||
|
_ -> styles
|
||||||
}
|
}
|
||||||
case pad.drill {
|
case pad.drill {
|
||||||
Some(token.PadDrillDefinition(False, Some(d), ..))
|
Some(token.PadDrillDefinition(False, Some(d), ..))
|
||||||
| Some(token.PadDrillDefinition(True, Some(d), None, ..)) ->
|
| Some(token.PadDrillDefinition(True, Some(d), None, ..)) ->
|
||||||
fragment([
|
fragment([
|
||||||
elem,
|
elem,
|
||||||
element.circle(
|
element.circle(styles:, transform:, cx: x, cy: y, r: d /. 2.0),
|
||||||
fill:,
|
|
||||||
stroke:,
|
|
||||||
stroke_width:,
|
|
||||||
transform:,
|
|
||||||
cx: x,
|
|
||||||
cy: y,
|
|
||||||
r: d /. 2.0,
|
|
||||||
),
|
|
||||||
])
|
])
|
||||||
Some(token.PadDrillDefinition(True, Some(w), Some(h), ..)) -> {
|
Some(token.PadDrillDefinition(True, Some(w), Some(h), ..)) -> {
|
||||||
let hw = w /. 2.0
|
let hw = w /. 2.0
|
||||||
|
@ -590,18 +513,9 @@ fn pad_to_element(pad: Pad) -> Element(a) {
|
||||||
fragment([
|
fragment([
|
||||||
elem,
|
elem,
|
||||||
case float.compare(w, h) {
|
case float.compare(w, h) {
|
||||||
order.Eq ->
|
order.Eq -> element.circle(styles:, transform:, cx: x, cy: y, r: hw)
|
||||||
element.circle(
|
|
||||||
fill:,
|
|
||||||
stroke:,
|
|
||||||
stroke_width:,
|
|
||||||
transform:,
|
|
||||||
cx: x,
|
|
||||||
cy: y,
|
|
||||||
r: hw,
|
|
||||||
)
|
|
||||||
order.Lt ->
|
order.Lt ->
|
||||||
element.path(fill:, stroke:, stroke_width:, transform:, path: [
|
element.path(styles:, transform:, path: [
|
||||||
path.MoveAbsolute(x: x +. hw, y: y +. hw -. hh),
|
path.MoveAbsolute(x: x +. hw, y: y +. hw -. hh),
|
||||||
path.ArcCurveRelative(
|
path.ArcCurveRelative(
|
||||||
rx: hw,
|
rx: hw,
|
||||||
|
@ -625,7 +539,7 @@ fn pad_to_element(pad: Pad) -> Element(a) {
|
||||||
path.ClosePath,
|
path.ClosePath,
|
||||||
])
|
])
|
||||||
order.Gt ->
|
order.Gt ->
|
||||||
element.path(fill:, stroke:, stroke_width:, transform:, path: [
|
element.path(styles:, transform:, path: [
|
||||||
path.MoveAbsolute(x: x +. hh -. hw, y: y -. hh),
|
path.MoveAbsolute(x: x +. hh -. hw, y: y -. hh),
|
||||||
path.ArcCurveRelative(
|
path.ArcCurveRelative(
|
||||||
rx: hh,
|
rx: hh,
|
||||||
|
|
|
@ -2,8 +2,9 @@ import gleam/float
|
||||||
import gleam/list
|
import gleam/list
|
||||||
import gleam/string
|
import gleam/string
|
||||||
import lustre/attribute.{type Attribute, attribute}
|
import lustre/attribute.{type Attribute, attribute}
|
||||||
import svg_path.{type Path}
|
import svg/path.{type Path}
|
||||||
import svg_transform.{type Transform}
|
import svg/styles.{type PaintOrder}
|
||||||
|
import svg/transform.{type Transform}
|
||||||
|
|
||||||
pub fn view_box(
|
pub fn view_box(
|
||||||
min_x: Float,
|
min_x: Float,
|
||||||
|
@ -35,6 +36,10 @@ pub fn stroke_width(value: Float) -> Attribute(a) {
|
||||||
float_attribute("stroke-width", value)
|
float_attribute("stroke-width", value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn paint_order(value: PaintOrder) -> Attribute(a) {
|
||||||
|
attribute("paint-order", styles.paint_order_to_string(value))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn width(value: Float) -> Attribute(a) {
|
pub fn width(value: Float) -> Attribute(a) {
|
||||||
float_attribute("width", value)
|
float_attribute("width", value)
|
||||||
}
|
}
|
||||||
|
@ -96,9 +101,9 @@ pub fn r(value: Float) -> Attribute(a) {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn d(value: Path) -> Attribute(a) {
|
pub fn d(value: Path) -> Attribute(a) {
|
||||||
attribute("d", svg_path.to_string(value))
|
attribute("d", path.to_string(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn transform(value: Transform) -> Attribute(a) {
|
pub fn transform(value: Transform) -> Attribute(a) {
|
||||||
attribute("transform", svg_transform.to_string(value))
|
attribute("transform", transform.to_string(value))
|
||||||
}
|
}
|
202
src/svg/element.gleam
Normal file
202
src/svg/element.gleam
Normal file
|
@ -0,0 +1,202 @@
|
||||||
|
import gleam/option.{type Option, None, Some}
|
||||||
|
import lustre/attribute.{type Attribute} as _attribute
|
||||||
|
import lustre/element.{type Element, element}
|
||||||
|
import svg/attribute
|
||||||
|
import svg/path.{type Path}
|
||||||
|
import svg/styles.{type Styles}
|
||||||
|
import svg/transform.{type Transform}
|
||||||
|
|
||||||
|
fn styles_transform(
|
||||||
|
styles styles: Styles,
|
||||||
|
transform transform: Option(Transform),
|
||||||
|
) -> List(Attribute(a)) {
|
||||||
|
let attrs = []
|
||||||
|
let attrs = case transform {
|
||||||
|
Some(value) -> [attribute.transform(value), ..attrs]
|
||||||
|
None -> attrs
|
||||||
|
}
|
||||||
|
let attrs = case styles.paint_order {
|
||||||
|
Some(value) -> [attribute.paint_order(value), ..attrs]
|
||||||
|
None -> attrs
|
||||||
|
}
|
||||||
|
let attrs = case styles.stroke_width {
|
||||||
|
Some(value) -> [attribute.stroke_width(value), ..attrs]
|
||||||
|
None -> attrs
|
||||||
|
}
|
||||||
|
let attrs = case styles.stroke {
|
||||||
|
Some(value) -> [attribute.stroke(value), ..attrs]
|
||||||
|
None -> attrs
|
||||||
|
}
|
||||||
|
let attrs = case styles.fill {
|
||||||
|
Some(value) -> [attribute.fill(value), ..attrs]
|
||||||
|
None -> attrs
|
||||||
|
}
|
||||||
|
attrs
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn group(
|
||||||
|
styles styles: Styles,
|
||||||
|
transform transform: Option(Transform),
|
||||||
|
children children: List(Element(a)),
|
||||||
|
) -> Element(a) {
|
||||||
|
element("g", styles_transform(styles:, transform:), children)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn line(
|
||||||
|
styles styles: Styles,
|
||||||
|
transform transform: Option(Transform),
|
||||||
|
x1 x1: Float,
|
||||||
|
y1 y1: Float,
|
||||||
|
x2 x2: Float,
|
||||||
|
y2 y2: Float,
|
||||||
|
) -> Element(a) {
|
||||||
|
element(
|
||||||
|
"line",
|
||||||
|
[
|
||||||
|
attribute.x1(x1),
|
||||||
|
attribute.y1(y1),
|
||||||
|
attribute.x2(x2),
|
||||||
|
attribute.y2(y2),
|
||||||
|
..styles_transform(styles:, transform:)
|
||||||
|
],
|
||||||
|
[],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn circle(
|
||||||
|
styles styles: Styles,
|
||||||
|
transform transform: Option(Transform),
|
||||||
|
cx cx: Float,
|
||||||
|
cy cy: Float,
|
||||||
|
r r: Float,
|
||||||
|
) -> Element(a) {
|
||||||
|
element(
|
||||||
|
"circle",
|
||||||
|
[
|
||||||
|
attribute.cx(cx),
|
||||||
|
attribute.cy(cy),
|
||||||
|
attribute.r(r),
|
||||||
|
..styles_transform(styles:, transform:)
|
||||||
|
],
|
||||||
|
[],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn ellipse(
|
||||||
|
styles styles: Styles,
|
||||||
|
transform transform: Option(Transform),
|
||||||
|
cx cx: Float,
|
||||||
|
cy cy: Float,
|
||||||
|
rx rx: Float,
|
||||||
|
ry ry: Float,
|
||||||
|
) -> Element(a) {
|
||||||
|
element(
|
||||||
|
"ellipse",
|
||||||
|
[
|
||||||
|
attribute.cx(cx),
|
||||||
|
attribute.cy(cy),
|
||||||
|
attribute.rx(rx),
|
||||||
|
attribute.ry(ry),
|
||||||
|
..styles_transform(styles:, transform:)
|
||||||
|
],
|
||||||
|
[],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn rect(
|
||||||
|
styles styles: Styles,
|
||||||
|
transform transform: Option(Transform),
|
||||||
|
x x: Float,
|
||||||
|
y y: Float,
|
||||||
|
width width: Float,
|
||||||
|
height height: Float,
|
||||||
|
) -> Element(a) {
|
||||||
|
element(
|
||||||
|
"rect",
|
||||||
|
[
|
||||||
|
attribute.x(x),
|
||||||
|
attribute.y(y),
|
||||||
|
attribute.width(width),
|
||||||
|
attribute.height(height),
|
||||||
|
..styles_transform(styles:, transform:)
|
||||||
|
],
|
||||||
|
[],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn rounded_rect(
|
||||||
|
styles styles: Styles,
|
||||||
|
transform transform: Option(Transform),
|
||||||
|
x x: Float,
|
||||||
|
y y: Float,
|
||||||
|
rx rx: Float,
|
||||||
|
ry ry: Float,
|
||||||
|
width width: Float,
|
||||||
|
height height: Float,
|
||||||
|
) -> Element(a) {
|
||||||
|
element(
|
||||||
|
"rect",
|
||||||
|
[
|
||||||
|
attribute.x(x),
|
||||||
|
attribute.y(y),
|
||||||
|
attribute.rx(rx),
|
||||||
|
attribute.ry(ry),
|
||||||
|
attribute.width(width),
|
||||||
|
attribute.height(height),
|
||||||
|
..styles_transform(styles:, transform:)
|
||||||
|
],
|
||||||
|
[],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn centered_rect(
|
||||||
|
styles styles: Styles,
|
||||||
|
transform transform: Option(Transform),
|
||||||
|
x x: Float,
|
||||||
|
y y: Float,
|
||||||
|
width width: Float,
|
||||||
|
height height: Float,
|
||||||
|
) -> Element(a) {
|
||||||
|
rect(
|
||||||
|
styles:,
|
||||||
|
transform:,
|
||||||
|
x: x -. width /. 2.0,
|
||||||
|
y: y -. height /. 2.0,
|
||||||
|
width:,
|
||||||
|
height:,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn centered_rounded_rect(
|
||||||
|
styles styles: Styles,
|
||||||
|
transform transform: Option(Transform),
|
||||||
|
x x: Float,
|
||||||
|
y y: Float,
|
||||||
|
rx rx: Float,
|
||||||
|
ry ry: Float,
|
||||||
|
width width: Float,
|
||||||
|
height height: Float,
|
||||||
|
) -> Element(a) {
|
||||||
|
rounded_rect(
|
||||||
|
styles:,
|
||||||
|
transform:,
|
||||||
|
x: x -. width /. 2.0,
|
||||||
|
y: y -. height /. 2.0,
|
||||||
|
rx:,
|
||||||
|
ry:,
|
||||||
|
width:,
|
||||||
|
height:,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn path(
|
||||||
|
styles styles: Styles,
|
||||||
|
transform transform: Option(Transform),
|
||||||
|
path path: Path,
|
||||||
|
) -> Element(a) {
|
||||||
|
element(
|
||||||
|
"path",
|
||||||
|
[attribute.d(path), ..styles_transform(styles:, transform:)],
|
||||||
|
[],
|
||||||
|
)
|
||||||
|
}
|
53
src/svg/styles.gleam
Normal file
53
src/svg/styles.gleam
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
import gleam/list
|
||||||
|
import gleam/option.{type Option, None, Some}
|
||||||
|
import gleam/string
|
||||||
|
|
||||||
|
pub type PaintComponent {
|
||||||
|
FillComponent
|
||||||
|
StrokeComponent
|
||||||
|
MarkerComponent
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type PaintOrder =
|
||||||
|
List(PaintComponent)
|
||||||
|
|
||||||
|
pub fn paint_order_to_string(value: PaintOrder) -> String {
|
||||||
|
value
|
||||||
|
|> list.map(fn(comp) {
|
||||||
|
case comp {
|
||||||
|
FillComponent -> "fill"
|
||||||
|
StrokeComponent -> "stroke"
|
||||||
|
MarkerComponent -> "marker"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|> string.join(" ")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type Styles {
|
||||||
|
Styles(
|
||||||
|
fill: Option(String),
|
||||||
|
stroke: Option(String),
|
||||||
|
stroke_width: Option(Float),
|
||||||
|
paint_order: Option(List(PaintComponent)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new() {
|
||||||
|
Styles(fill: None, stroke: None, stroke_width: None, paint_order: None)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_fill(styles: Styles, fill: String) {
|
||||||
|
Styles(..styles, fill: Some(fill))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_stroke(styles: Styles, stroke: String) {
|
||||||
|
Styles(..styles, stroke: Some(stroke))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_stroke_width(styles: Styles, stroke_width: Float) {
|
||||||
|
Styles(..styles, stroke_width: Some(stroke_width))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_paint_order(styles: Styles, paint_order: PaintOrder) {
|
||||||
|
Styles(..styles, paint_order: Some(paint_order))
|
||||||
|
}
|
|
@ -1,221 +0,0 @@
|
||||||
import gleam/option.{type Option, None, Some}
|
|
||||||
import lustre/attribute.{type Attribute}
|
|
||||||
import lustre/element.{type Element, element}
|
|
||||||
import svg_attribute
|
|
||||||
import svg_path.{type Path}
|
|
||||||
import svg_transform.{type Transform}
|
|
||||||
|
|
||||||
fn styles(
|
|
||||||
fill fill: Option(String),
|
|
||||||
stroke stroke: Option(String),
|
|
||||||
stroke_width stroke_width: Option(Float),
|
|
||||||
transform transform: Option(Transform),
|
|
||||||
) -> List(Attribute(a)) {
|
|
||||||
let attrs = []
|
|
||||||
let attrs = case transform {
|
|
||||||
Some(value) -> [svg_attribute.transform(value), ..attrs]
|
|
||||||
None -> attrs
|
|
||||||
}
|
|
||||||
let attrs = case stroke_width {
|
|
||||||
Some(value) -> [svg_attribute.stroke_width(value), ..attrs]
|
|
||||||
None -> attrs
|
|
||||||
}
|
|
||||||
let attrs = case stroke {
|
|
||||||
Some(value) -> [svg_attribute.stroke(value), ..attrs]
|
|
||||||
None -> attrs
|
|
||||||
}
|
|
||||||
let attrs = case fill {
|
|
||||||
Some(value) -> [svg_attribute.fill(value), ..attrs]
|
|
||||||
None -> attrs
|
|
||||||
}
|
|
||||||
attrs
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn group(
|
|
||||||
fill fill: Option(String),
|
|
||||||
stroke stroke: Option(String),
|
|
||||||
stroke_width stroke_width: Option(Float),
|
|
||||||
transform transform: Option(Transform),
|
|
||||||
children children: List(Element(a)),
|
|
||||||
) -> Element(a) {
|
|
||||||
element("g", styles(fill:, stroke:, stroke_width:, transform:), children)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn line(
|
|
||||||
fill fill: Option(String),
|
|
||||||
stroke stroke: Option(String),
|
|
||||||
stroke_width stroke_width: Option(Float),
|
|
||||||
transform transform: Option(Transform),
|
|
||||||
x1 x1: Float,
|
|
||||||
y1 y1: Float,
|
|
||||||
x2 x2: Float,
|
|
||||||
y2 y2: Float,
|
|
||||||
) -> Element(a) {
|
|
||||||
element(
|
|
||||||
"line",
|
|
||||||
[
|
|
||||||
svg_attribute.x1(x1),
|
|
||||||
svg_attribute.y1(y1),
|
|
||||||
svg_attribute.x2(x2),
|
|
||||||
svg_attribute.y2(y2),
|
|
||||||
..styles(fill:, stroke:, stroke_width:, transform:)
|
|
||||||
],
|
|
||||||
[],
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn circle(
|
|
||||||
fill fill: Option(String),
|
|
||||||
stroke stroke: Option(String),
|
|
||||||
stroke_width stroke_width: Option(Float),
|
|
||||||
transform transform: Option(Transform),
|
|
||||||
cx cx: Float,
|
|
||||||
cy cy: Float,
|
|
||||||
r r: Float,
|
|
||||||
) -> Element(a) {
|
|
||||||
element(
|
|
||||||
"circle",
|
|
||||||
[
|
|
||||||
svg_attribute.cx(cx),
|
|
||||||
svg_attribute.cy(cy),
|
|
||||||
svg_attribute.r(r),
|
|
||||||
..styles(fill:, stroke:, stroke_width:, transform:)
|
|
||||||
],
|
|
||||||
[],
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn ellipse(
|
|
||||||
fill fill: Option(String),
|
|
||||||
stroke stroke: Option(String),
|
|
||||||
stroke_width stroke_width: Option(Float),
|
|
||||||
transform transform: Option(Transform),
|
|
||||||
cx cx: Float,
|
|
||||||
cy cy: Float,
|
|
||||||
rx rx: Float,
|
|
||||||
ry ry: Float,
|
|
||||||
) -> Element(a) {
|
|
||||||
element(
|
|
||||||
"ellipse",
|
|
||||||
[
|
|
||||||
svg_attribute.cx(cx),
|
|
||||||
svg_attribute.cy(cy),
|
|
||||||
svg_attribute.rx(rx),
|
|
||||||
svg_attribute.ry(ry),
|
|
||||||
..styles(fill:, stroke:, stroke_width:, transform:)
|
|
||||||
],
|
|
||||||
[],
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn rect(
|
|
||||||
fill fill: Option(String),
|
|
||||||
stroke stroke: Option(String),
|
|
||||||
stroke_width stroke_width: Option(Float),
|
|
||||||
transform transform: Option(Transform),
|
|
||||||
x x: Float,
|
|
||||||
y y: Float,
|
|
||||||
width width: Float,
|
|
||||||
height height: Float,
|
|
||||||
) -> Element(a) {
|
|
||||||
element(
|
|
||||||
"rect",
|
|
||||||
[
|
|
||||||
svg_attribute.x(x),
|
|
||||||
svg_attribute.y(y),
|
|
||||||
svg_attribute.width(width),
|
|
||||||
svg_attribute.height(height),
|
|
||||||
..styles(fill:, stroke:, stroke_width:, transform:)
|
|
||||||
],
|
|
||||||
[],
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn rounded_rect(
|
|
||||||
fill fill: Option(String),
|
|
||||||
stroke stroke: Option(String),
|
|
||||||
stroke_width stroke_width: Option(Float),
|
|
||||||
transform transform: Option(Transform),
|
|
||||||
x x: Float,
|
|
||||||
y y: Float,
|
|
||||||
rx rx: Float,
|
|
||||||
ry ry: Float,
|
|
||||||
width width: Float,
|
|
||||||
height height: Float,
|
|
||||||
) -> Element(a) {
|
|
||||||
element(
|
|
||||||
"rect",
|
|
||||||
[
|
|
||||||
svg_attribute.x(x),
|
|
||||||
svg_attribute.y(y),
|
|
||||||
svg_attribute.rx(rx),
|
|
||||||
svg_attribute.ry(ry),
|
|
||||||
svg_attribute.width(width),
|
|
||||||
svg_attribute.height(height),
|
|
||||||
..styles(fill:, stroke:, stroke_width:, transform:)
|
|
||||||
],
|
|
||||||
[],
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn centered_rect(
|
|
||||||
fill fill: Option(String),
|
|
||||||
stroke stroke: Option(String),
|
|
||||||
stroke_width stroke_width: Option(Float),
|
|
||||||
transform transform: Option(Transform),
|
|
||||||
x x: Float,
|
|
||||||
y y: Float,
|
|
||||||
width width: Float,
|
|
||||||
height height: Float,
|
|
||||||
) -> Element(a) {
|
|
||||||
rect(
|
|
||||||
fill:,
|
|
||||||
stroke:,
|
|
||||||
stroke_width:,
|
|
||||||
transform:,
|
|
||||||
x: x -. width /. 2.0,
|
|
||||||
y: y -. height /. 2.0,
|
|
||||||
width:,
|
|
||||||
height:,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn centered_rounded_rect(
|
|
||||||
fill fill: Option(String),
|
|
||||||
stroke stroke: Option(String),
|
|
||||||
stroke_width stroke_width: Option(Float),
|
|
||||||
transform transform: Option(Transform),
|
|
||||||
x x: Float,
|
|
||||||
y y: Float,
|
|
||||||
rx rx: Float,
|
|
||||||
ry ry: Float,
|
|
||||||
width width: Float,
|
|
||||||
height height: Float,
|
|
||||||
) -> Element(a) {
|
|
||||||
rounded_rect(
|
|
||||||
fill:,
|
|
||||||
stroke:,
|
|
||||||
stroke_width:,
|
|
||||||
transform:,
|
|
||||||
x: x -. width /. 2.0,
|
|
||||||
y: y -. height /. 2.0,
|
|
||||||
rx:,
|
|
||||||
ry:,
|
|
||||||
width:,
|
|
||||||
height:,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn path(
|
|
||||||
fill fill: Option(String),
|
|
||||||
stroke stroke: Option(String),
|
|
||||||
stroke_width stroke_width: Option(Float),
|
|
||||||
transform transform: Option(Transform),
|
|
||||||
path path: Path,
|
|
||||||
) -> Element(a) {
|
|
||||||
element(
|
|
||||||
"path",
|
|
||||||
[svg_attribute.d(path), ..styles(fill:, stroke:, stroke_width:, transform:)],
|
|
||||||
[],
|
|
||||||
)
|
|
||||||
}
|
|
Loading…
Reference in a new issue