Is there a nice way of drawing an arc without cetz?

Obviously you can call cetz’s arc, but given that the stroke on the built-in typst circle seems to accept any pattern or gradient, I was wondering if someone had thought of a way to do so. I.e., drawing the circle stroke only between an ordered set of bounding angles.

This is particularly driven by a desire to have content in the interior to use for slides.

I guess the follow-up question is what the best method of creating custom parameterised shapes with content is, especially in terms of not breaking the compiler (like I bet one could with curve).

See Add a `curve.arc` function for circular and elliptical arcs · Issue #5915 · typst/typst · GitHub

#circle(radius: 5cm, fill: gradient
  .conic(..color.map.rainbow, angle: 0deg)
  .repeat(4, mirror: true))
#circle(radius: 5cm, fill: gradient
  .conic(..color.map.rainbow.slice(0, -20), angle: 0deg)
  .sharp(7))

I don’t know how you would do this with pattern, might as well just use curve.

I don’t understand.

#let custom-shape(stroke: 1pt, fill: green, parameter3: ...) = {
  curve(
    stroke: stroke,
    fill: fill,
    ...
  )
}

Ah, thanks for the issue link – this clarifies why an arc is something essentially done with Bezier paths.

By custom shape, I meant if I wanted mirror the use of body content inside a circle, but with a custom arc shape based on curve, it’s not clear to me how this should be done. The documentation says it takes content but this appears to only be the curve drawing commands, instead of e.g. [hello!].

I noticed this too. Make it possible to add arbitrary content in `curve`/`polygon` shape · Issue #6397 · typst/typst · GitHub

#let shape(side, fill: none, stroke: 1pt, ..body) = {
  set curve.line(relative: true)
  place(curve(
    stroke: stroke,
    fill: fill,
    curve.line((side, 0pt)),
    curve.line((0pt, side)),
    curve.line((-side, 0pt)),
    curve.line((0pt, -side)),
  ))
  block(width: side, height: side, ..body)
}

#shape(1cm, align(center + horizon)[text])

image