You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
render CircularWaveformRenderer .ring as a true annulus across all styles
The ring path is now built as two subpaths (outer envelope + inner circle),
and both the CGContext and SwiftUI rendering paths fill / clip it with the
even-odd rule so the inner disk is correctly excluded for filled and
gradient styles. The envelope also stays at least 1 device pixel thick at
silence, mirroring LinearWaveformRenderer's minimum-amplitude behavior, so
the ring remains visible regardless of input. Drops the "experimental"
label on .ring now that all styles render correctly.
Copy file name to clipboardExpand all lines: Sources/DSWaveformImage/Renderers/CircularWaveformRenderer.swift
+87-28Lines changed: 87 additions & 28 deletions
Original file line number
Diff line number
Diff line change
@@ -5,7 +5,6 @@ import CoreGraphics
5
5
Draws a circular 2D amplitude envelope of the samples provided.
6
6
7
7
Draws either a filled circle, or a hollow ring, depending on the provided `Kind`. Defaults to drawing a `.circle`.
8
-
`Kind.ring` is currently experimental.
9
8
Can be customized further via the configuration `Waveform.Style`.
10
9
*/
11
10
@@ -14,17 +13,28 @@ public struct CircularWaveformRenderer: WaveformRenderer {
14
13
/// Draws waveform as a circular amplitude envelope.
15
14
case circle
16
15
17
-
/// **Experimental!** (Will) draw waveform as a ring-shaped amplitude envelope.
18
-
/// Associated value will define the percentage of desired "hollowness" inside, or in other words the ring's thickness / diameter in relation to the overall diameter.
16
+
/// Draws waveform as a ring-shaped amplitude envelope, where the modulated outer envelope
17
+
/// extends from a fixed inner circle outward toward the maximum radius.
18
+
/// The associated value sets the inner circle's radius as a fraction of the overall radius
19
+
/// (e.g. `0.5` = inner radius is half of the maximum). Clamped to `(0...1)` is the caller's
20
+
/// responsibility — `0` collapses to `.circle`, `1` collapses to a zero-thickness ring.
19
21
case ring(CGFloat)
20
22
}
21
23
22
-
privateletkind:Kind
24
+
publicletkind:Kind
23
25
24
26
publicinit(kind:Kind=.circle){
25
27
self.kind = kind
26
28
}
27
29
30
+
/// Whether `fill` / `clip` over this renderer's path needs the even-odd rule to produce the
31
+
/// intended region. `true` for `.ring`, because the path consists of an outer envelope and an
32
+
/// inner circle subpath whose subtraction can't be guaranteed by winding direction alone.
33
+
publicvarprefersEvenOddFillRule:Bool{
34
+
if case .ring = kind {returntrue}
35
+
returnfalse
36
+
}
37
+
28
38
publicfunc path(samples:[Float], with configuration:Waveform.Configuration, lastOffset:Int, position:Waveform.Position=.middle)->CGPath{
0 commit comments