Skip to main content

pedalkernel_layout/
symbols.rs

1//! Component symbol definitions.
2//!
3//! Each component type maps to a vector symbol defined as a series of path
4//! commands (move_to, line_to, arc_to, close). These render at any resolution
5//! with zero texture memory when drawn with Lyon or a similar path rasterizer.
6
7use pedalkernel::compiler::Component;
8use serde::{Deserialize, Serialize};
9
10/// A symbol identifier string used in the layout JSON.
11/// At runtime, the shader/renderer maps this to the actual path commands.
12pub fn symbol_for_kind(kind: &dyn Component) -> String {
13    kind.symbol_name().to_string()
14}
15
16/// Enumeration of all symbol types used in the layout.
17#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
18pub enum SymbolType {
19    Resistor,
20    Capacitor,
21    ElectrolyticCap,
22    Inductor,
23    Diode,
24    Zener,
25    Triode,
26    Pentode,
27    NJfet,
28    PJfet,
29    NpnBjt,
30    PnpBjt,
31    Nmos,
32    Pmos,
33    OpAmp,
34    Pot,
35    Transformer,
36    Photocoupler,
37    IcChip,
38    Ground,
39    Supply,
40    Speaker,
41    Input,
42    Output,
43    Lfo,
44    Neon,
45    Switch,
46}
47
48/// A path command for vector symbol rendering.
49#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
50pub enum PathCmd {
51    /// Move to (x, y) without drawing.
52    MoveTo(f32, f32),
53    /// Draw a line to (x, y).
54    LineTo(f32, f32),
55    /// Draw an arc: center (cx, cy), radius, start_angle, end_angle (radians).
56    ArcTo(f32, f32, f32, f32, f32),
57    /// Close the current sub-path.
58    Close,
59}
60
61/// Get the path commands for a given symbol type.
62///
63/// All symbols are drawn in a normalized coordinate space centered at (0, 0)
64/// with a nominal size of ~30×30 units. The renderer scales and translates
65/// as needed.
66pub fn symbol_paths(sym: SymbolType) -> Vec<PathCmd> {
67    match sym {
68        SymbolType::Resistor => resistor_path(),
69        SymbolType::Capacitor => capacitor_path(),
70        SymbolType::ElectrolyticCap => electrolytic_cap_path(),
71        SymbolType::Inductor => inductor_path(),
72        SymbolType::Diode => diode_path(),
73        SymbolType::Zener => zener_path(),
74        SymbolType::Triode => triode_path(),
75        SymbolType::Pentode => pentode_path(),
76        SymbolType::NJfet => njfet_path(),
77        SymbolType::PJfet => pjfet_path(),
78        SymbolType::NpnBjt => npn_bjt_path(),
79        SymbolType::PnpBjt => pnp_bjt_path(),
80        SymbolType::Nmos => nmos_path(),
81        SymbolType::Pmos => pmos_path(),
82        SymbolType::OpAmp => opamp_path(),
83        SymbolType::Pot => pot_path(),
84        SymbolType::Transformer => transformer_path(),
85        SymbolType::Photocoupler => photocoupler_path(),
86        SymbolType::IcChip => ic_chip_path(),
87        SymbolType::Ground => ground_path(),
88        SymbolType::Supply => supply_path(),
89        SymbolType::Speaker => speaker_path(),
90        SymbolType::Input => input_path(),
91        SymbolType::Output => output_path(),
92        SymbolType::Lfo => lfo_path(),
93        SymbolType::Neon => neon_path(),
94        SymbolType::Switch => switch_path(),
95    }
96}
97
98// ---------------------------------------------------------------------------
99// Symbol path definitions
100// ---------------------------------------------------------------------------
101
102/// American-style zigzag resistor.
103fn resistor_path() -> Vec<PathCmd> {
104    vec![
105        PathCmd::MoveTo(-15.0, 0.0),
106        PathCmd::LineTo(-10.0, 0.0),
107        PathCmd::LineTo(-8.0, -5.0),
108        PathCmd::LineTo(-4.0, 5.0),
109        PathCmd::LineTo(0.0, -5.0),
110        PathCmd::LineTo(4.0, 5.0),
111        PathCmd::LineTo(8.0, -5.0),
112        PathCmd::LineTo(10.0, 0.0),
113        PathCmd::LineTo(15.0, 0.0),
114    ]
115}
116
117/// Non-polarized capacitor: two parallel lines.
118fn capacitor_path() -> Vec<PathCmd> {
119    vec![
120        // Left lead
121        PathCmd::MoveTo(-15.0, 0.0),
122        PathCmd::LineTo(-3.0, 0.0),
123        // Left plate
124        PathCmd::MoveTo(-3.0, -8.0),
125        PathCmd::LineTo(-3.0, 8.0),
126        // Right plate
127        PathCmd::MoveTo(3.0, -8.0),
128        PathCmd::LineTo(3.0, 8.0),
129        // Right lead
130        PathCmd::MoveTo(3.0, 0.0),
131        PathCmd::LineTo(15.0, 0.0),
132    ]
133}
134
135/// Electrolytic capacitor: one straight plate, one curved.
136fn electrolytic_cap_path() -> Vec<PathCmd> {
137    vec![
138        PathCmd::MoveTo(-15.0, 0.0),
139        PathCmd::LineTo(-3.0, 0.0),
140        // Straight plate (positive)
141        PathCmd::MoveTo(-3.0, -8.0),
142        PathCmd::LineTo(-3.0, 8.0),
143        // Curved plate (negative) — approximated with line segments
144        PathCmd::MoveTo(3.0, -8.0),
145        PathCmd::ArcTo(3.0, 0.0, 8.0, -1.0, 1.0),
146        PathCmd::MoveTo(3.0, 0.0),
147        PathCmd::LineTo(15.0, 0.0),
148        // Plus sign near positive plate
149        PathCmd::MoveTo(-8.0, -6.0),
150        PathCmd::LineTo(-8.0, -10.0),
151        PathCmd::MoveTo(-10.0, -8.0),
152        PathCmd::LineTo(-6.0, -8.0),
153    ]
154}
155
156/// Inductor: series of bumps (coil).
157fn inductor_path() -> Vec<PathCmd> {
158    vec![
159        PathCmd::MoveTo(-15.0, 0.0),
160        PathCmd::LineTo(-10.0, 0.0),
161        PathCmd::ArcTo(-7.5, 0.0, 2.5, std::f32::consts::PI, 0.0),
162        PathCmd::ArcTo(-2.5, 0.0, 2.5, std::f32::consts::PI, 0.0),
163        PathCmd::ArcTo(2.5, 0.0, 2.5, std::f32::consts::PI, 0.0),
164        PathCmd::ArcTo(7.5, 0.0, 2.5, std::f32::consts::PI, 0.0),
165        PathCmd::LineTo(15.0, 0.0),
166    ]
167}
168
169/// Diode: triangle + line.
170fn diode_path() -> Vec<PathCmd> {
171    vec![
172        PathCmd::MoveTo(-15.0, 0.0),
173        PathCmd::LineTo(-5.0, 0.0),
174        // Triangle (anode side)
175        PathCmd::MoveTo(-5.0, -7.0),
176        PathCmd::LineTo(-5.0, 7.0),
177        PathCmd::LineTo(5.0, 0.0),
178        PathCmd::Close,
179        // Cathode bar
180        PathCmd::MoveTo(5.0, -7.0),
181        PathCmd::LineTo(5.0, 7.0),
182        // Lead
183        PathCmd::MoveTo(5.0, 0.0),
184        PathCmd::LineTo(15.0, 0.0),
185    ]
186}
187
188/// Zener diode: triangle + bent line.
189fn zener_path() -> Vec<PathCmd> {
190    vec![
191        PathCmd::MoveTo(-15.0, 0.0),
192        PathCmd::LineTo(-5.0, 0.0),
193        PathCmd::MoveTo(-5.0, -7.0),
194        PathCmd::LineTo(-5.0, 7.0),
195        PathCmd::LineTo(5.0, 0.0),
196        PathCmd::Close,
197        // Zener cathode (bent bar)
198        PathCmd::MoveTo(3.0, -9.0),
199        PathCmd::LineTo(5.0, -7.0),
200        PathCmd::LineTo(5.0, 7.0),
201        PathCmd::LineTo(7.0, 9.0),
202        PathCmd::MoveTo(5.0, 0.0),
203        PathCmd::LineTo(15.0, 0.0),
204    ]
205}
206
207/// Triode: circle with grid, plate, cathode.
208fn triode_path() -> Vec<PathCmd> {
209    vec![
210        // Envelope (circle)
211        PathCmd::ArcTo(0.0, 0.0, 12.0, 0.0, std::f32::consts::TAU),
212        // Plate (top)
213        PathCmd::MoveTo(-6.0, -8.0),
214        PathCmd::LineTo(6.0, -8.0),
215        PathCmd::MoveTo(0.0, -8.0),
216        PathCmd::LineTo(0.0, -15.0),
217        // Grid (dashed horizontal line in middle)
218        PathCmd::MoveTo(-8.0, 0.0),
219        PathCmd::LineTo(-5.0, 0.0),
220        PathCmd::MoveTo(-3.0, 0.0),
221        PathCmd::LineTo(0.0, 0.0),
222        PathCmd::MoveTo(2.0, 0.0),
223        PathCmd::LineTo(5.0, 0.0),
224        // Grid lead
225        PathCmd::MoveTo(-8.0, 0.0),
226        PathCmd::LineTo(-15.0, 0.0),
227        // Cathode (bottom arc)
228        PathCmd::ArcTo(0.0, 8.0, 6.0, std::f32::consts::PI, 0.0),
229        PathCmd::MoveTo(0.0, 8.0),
230        PathCmd::LineTo(0.0, 15.0),
231    ]
232}
233
234/// Pentode: circle with grid, screen, plate, cathode.
235fn pentode_path() -> Vec<PathCmd> {
236    vec![
237        // Envelope
238        PathCmd::ArcTo(0.0, 0.0, 14.0, 0.0, std::f32::consts::TAU),
239        // Plate
240        PathCmd::MoveTo(-6.0, -10.0),
241        PathCmd::LineTo(6.0, -10.0),
242        PathCmd::MoveTo(0.0, -10.0),
243        PathCmd::LineTo(0.0, -18.0),
244        // Screen grid (dashed, between plate and control grid)
245        PathCmd::MoveTo(-6.0, -5.0),
246        PathCmd::LineTo(-3.0, -5.0),
247        PathCmd::MoveTo(0.0, -5.0),
248        PathCmd::LineTo(3.0, -5.0),
249        // Screen lead
250        PathCmd::MoveTo(6.0, -5.0),
251        PathCmd::LineTo(18.0, -5.0),
252        // Control grid (dashed)
253        PathCmd::MoveTo(-8.0, 2.0),
254        PathCmd::LineTo(-5.0, 2.0),
255        PathCmd::MoveTo(-3.0, 2.0),
256        PathCmd::LineTo(0.0, 2.0),
257        PathCmd::MoveTo(2.0, 2.0),
258        PathCmd::LineTo(5.0, 2.0),
259        // Grid lead
260        PathCmd::MoveTo(-8.0, 2.0),
261        PathCmd::LineTo(-18.0, 2.0),
262        // Cathode
263        PathCmd::ArcTo(0.0, 10.0, 6.0, std::f32::consts::PI, 0.0),
264        PathCmd::MoveTo(0.0, 10.0),
265        PathCmd::LineTo(0.0, 18.0),
266    ]
267}
268
269/// N-channel JFET.
270fn njfet_path() -> Vec<PathCmd> {
271    vec![
272        // Channel
273        PathCmd::MoveTo(0.0, -10.0),
274        PathCmd::LineTo(0.0, 10.0),
275        // Drain (top)
276        PathCmd::MoveTo(0.0, -6.0),
277        PathCmd::LineTo(8.0, -6.0),
278        PathCmd::LineTo(8.0, -15.0),
279        // Source (bottom)
280        PathCmd::MoveTo(0.0, 6.0),
281        PathCmd::LineTo(8.0, 6.0),
282        PathCmd::LineTo(8.0, 15.0),
283        // Gate (with arrow pointing in)
284        PathCmd::MoveTo(-15.0, 0.0),
285        PathCmd::LineTo(0.0, 0.0),
286        // Arrow
287        PathCmd::MoveTo(-2.0, -3.0),
288        PathCmd::LineTo(0.0, 0.0),
289        PathCmd::LineTo(-2.0, 3.0),
290    ]
291}
292
293/// P-channel JFET.
294fn pjfet_path() -> Vec<PathCmd> {
295    vec![
296        PathCmd::MoveTo(0.0, -10.0),
297        PathCmd::LineTo(0.0, 10.0),
298        PathCmd::MoveTo(0.0, -6.0),
299        PathCmd::LineTo(8.0, -6.0),
300        PathCmd::LineTo(8.0, -15.0),
301        PathCmd::MoveTo(0.0, 6.0),
302        PathCmd::LineTo(8.0, 6.0),
303        PathCmd::LineTo(8.0, 15.0),
304        PathCmd::MoveTo(-15.0, 0.0),
305        PathCmd::LineTo(0.0, 0.0),
306        // Arrow pointing out
307        PathCmd::MoveTo(-4.0, -3.0),
308        PathCmd::LineTo(-2.0, 0.0),
309        PathCmd::LineTo(-4.0, 3.0),
310    ]
311}
312
313/// NPN BJT.
314fn npn_bjt_path() -> Vec<PathCmd> {
315    vec![
316        // Base lead
317        PathCmd::MoveTo(-15.0, 0.0),
318        PathCmd::LineTo(-5.0, 0.0),
319        // Base bar
320        PathCmd::MoveTo(-5.0, -8.0),
321        PathCmd::LineTo(-5.0, 8.0),
322        // Collector
323        PathCmd::MoveTo(-5.0, -5.0),
324        PathCmd::LineTo(5.0, -10.0),
325        PathCmd::LineTo(5.0, -15.0),
326        // Emitter (with arrow out)
327        PathCmd::MoveTo(-5.0, 5.0),
328        PathCmd::LineTo(5.0, 10.0),
329        PathCmd::LineTo(5.0, 15.0),
330        // Arrow on emitter
331        PathCmd::MoveTo(2.0, 7.0),
332        PathCmd::LineTo(5.0, 10.0),
333        PathCmd::LineTo(1.0, 10.0),
334    ]
335}
336
337/// PNP BJT.
338fn pnp_bjt_path() -> Vec<PathCmd> {
339    vec![
340        PathCmd::MoveTo(-15.0, 0.0),
341        PathCmd::LineTo(-5.0, 0.0),
342        PathCmd::MoveTo(-5.0, -8.0),
343        PathCmd::LineTo(-5.0, 8.0),
344        PathCmd::MoveTo(-5.0, -5.0),
345        PathCmd::LineTo(5.0, -10.0),
346        PathCmd::LineTo(5.0, -15.0),
347        PathCmd::MoveTo(-5.0, 5.0),
348        PathCmd::LineTo(5.0, 10.0),
349        PathCmd::LineTo(5.0, 15.0),
350        // Arrow on emitter (pointing in)
351        PathCmd::MoveTo(-2.0, 7.0),
352        PathCmd::LineTo(-5.0, 5.0),
353        PathCmd::LineTo(-2.0, 3.0),
354    ]
355}
356
357/// N-channel MOSFET.
358fn nmos_path() -> Vec<PathCmd> {
359    vec![
360        // Gate
361        PathCmd::MoveTo(-15.0, 0.0),
362        PathCmd::LineTo(-6.0, 0.0),
363        PathCmd::MoveTo(-6.0, -8.0),
364        PathCmd::LineTo(-6.0, 8.0),
365        // Channel (three segments)
366        PathCmd::MoveTo(-3.0, -8.0),
367        PathCmd::LineTo(-3.0, -3.0),
368        PathCmd::MoveTo(-3.0, -1.0),
369        PathCmd::LineTo(-3.0, 1.0),
370        PathCmd::MoveTo(-3.0, 3.0),
371        PathCmd::LineTo(-3.0, 8.0),
372        // Drain
373        PathCmd::MoveTo(-3.0, -6.0),
374        PathCmd::LineTo(5.0, -6.0),
375        PathCmd::LineTo(5.0, -15.0),
376        // Source
377        PathCmd::MoveTo(-3.0, 6.0),
378        PathCmd::LineTo(5.0, 6.0),
379        PathCmd::LineTo(5.0, 15.0),
380        // Body connection
381        PathCmd::MoveTo(-3.0, 0.0),
382        PathCmd::LineTo(5.0, 0.0),
383        // Arrow (enhancement mode, pointing in)
384        PathCmd::MoveTo(2.0, -3.0),
385        PathCmd::LineTo(5.0, 0.0),
386        PathCmd::LineTo(2.0, 3.0),
387    ]
388}
389
390/// P-channel MOSFET.
391fn pmos_path() -> Vec<PathCmd> {
392    vec![
393        PathCmd::MoveTo(-15.0, 0.0),
394        PathCmd::LineTo(-6.0, 0.0),
395        PathCmd::MoveTo(-6.0, -8.0),
396        PathCmd::LineTo(-6.0, 8.0),
397        PathCmd::MoveTo(-3.0, -8.0),
398        PathCmd::LineTo(-3.0, -3.0),
399        PathCmd::MoveTo(-3.0, -1.0),
400        PathCmd::LineTo(-3.0, 1.0),
401        PathCmd::MoveTo(-3.0, 3.0),
402        PathCmd::LineTo(-3.0, 8.0),
403        PathCmd::MoveTo(-3.0, -6.0),
404        PathCmd::LineTo(5.0, -6.0),
405        PathCmd::LineTo(5.0, -15.0),
406        PathCmd::MoveTo(-3.0, 6.0),
407        PathCmd::LineTo(5.0, 6.0),
408        PathCmd::LineTo(5.0, 15.0),
409        PathCmd::MoveTo(-3.0, 0.0),
410        PathCmd::LineTo(5.0, 0.0),
411        // Arrow pointing out
412        PathCmd::MoveTo(1.0, -3.0),
413        PathCmd::LineTo(-2.0, 0.0),
414        PathCmd::LineTo(1.0, 3.0),
415    ]
416}
417
418/// Op-amp: triangle.
419fn opamp_path() -> Vec<PathCmd> {
420    vec![
421        // Triangle body
422        PathCmd::MoveTo(-10.0, -12.0),
423        PathCmd::LineTo(-10.0, 12.0),
424        PathCmd::LineTo(12.0, 0.0),
425        PathCmd::Close,
426        // Non-inverting input (+)
427        PathCmd::MoveTo(-15.0, -6.0),
428        PathCmd::LineTo(-10.0, -6.0),
429        PathCmd::MoveTo(-14.0, -8.0),
430        PathCmd::LineTo(-14.0, -4.0),
431        PathCmd::MoveTo(-16.0, -6.0),
432        PathCmd::LineTo(-12.0, -6.0),
433        // Inverting input (-)
434        PathCmd::MoveTo(-15.0, 6.0),
435        PathCmd::LineTo(-10.0, 6.0),
436        PathCmd::MoveTo(-16.0, 6.0),
437        PathCmd::LineTo(-12.0, 6.0),
438        // Output
439        PathCmd::MoveTo(12.0, 0.0),
440        PathCmd::LineTo(18.0, 0.0),
441    ]
442}
443
444/// Potentiometer: resistor with arrow wiper.
445fn pot_path() -> Vec<PathCmd> {
446    vec![
447        // Resistor body
448        PathCmd::MoveTo(-15.0, 0.0),
449        PathCmd::LineTo(-10.0, 0.0),
450        PathCmd::LineTo(-8.0, -5.0),
451        PathCmd::LineTo(-4.0, 5.0),
452        PathCmd::LineTo(0.0, -5.0),
453        PathCmd::LineTo(4.0, 5.0),
454        PathCmd::LineTo(8.0, -5.0),
455        PathCmd::LineTo(10.0, 0.0),
456        PathCmd::LineTo(15.0, 0.0),
457        // Wiper arrow
458        PathCmd::MoveTo(0.0, -10.0),
459        PathCmd::LineTo(0.0, -5.0),
460        PathCmd::MoveTo(-2.0, -7.0),
461        PathCmd::LineTo(0.0, -5.0),
462        PathCmd::LineTo(2.0, -7.0),
463    ]
464}
465
466/// Transformer: two coupled inductors.
467fn transformer_path() -> Vec<PathCmd> {
468    vec![
469        // Primary (left)
470        PathCmd::MoveTo(-8.0, -15.0),
471        PathCmd::ArcTo(
472            -8.0,
473            -10.0,
474            3.0,
475            std::f32::consts::FRAC_PI_2,
476            -std::f32::consts::FRAC_PI_2,
477        ),
478        PathCmd::ArcTo(
479            -8.0,
480            -5.0,
481            3.0,
482            std::f32::consts::FRAC_PI_2,
483            -std::f32::consts::FRAC_PI_2,
484        ),
485        PathCmd::ArcTo(
486            -8.0,
487            0.0,
488            3.0,
489            std::f32::consts::FRAC_PI_2,
490            -std::f32::consts::FRAC_PI_2,
491        ),
492        PathCmd::ArcTo(
493            -8.0,
494            5.0,
495            3.0,
496            std::f32::consts::FRAC_PI_2,
497            -std::f32::consts::FRAC_PI_2,
498        ),
499        PathCmd::LineTo(-8.0, 15.0),
500        // Core lines
501        PathCmd::MoveTo(-2.0, -15.0),
502        PathCmd::LineTo(-2.0, 15.0),
503        PathCmd::MoveTo(2.0, -15.0),
504        PathCmd::LineTo(2.0, 15.0),
505        // Secondary (right)
506        PathCmd::MoveTo(8.0, -15.0),
507        PathCmd::ArcTo(
508            8.0,
509            -10.0,
510            3.0,
511            -std::f32::consts::FRAC_PI_2,
512            std::f32::consts::FRAC_PI_2,
513        ),
514        PathCmd::ArcTo(
515            8.0,
516            -5.0,
517            3.0,
518            -std::f32::consts::FRAC_PI_2,
519            std::f32::consts::FRAC_PI_2,
520        ),
521        PathCmd::ArcTo(
522            8.0,
523            0.0,
524            3.0,
525            -std::f32::consts::FRAC_PI_2,
526            std::f32::consts::FRAC_PI_2,
527        ),
528        PathCmd::ArcTo(
529            8.0,
530            5.0,
531            3.0,
532            -std::f32::consts::FRAC_PI_2,
533            std::f32::consts::FRAC_PI_2,
534        ),
535        PathCmd::LineTo(8.0, 15.0),
536    ]
537}
538
539/// Photocoupler (LED + LDR in box).
540fn photocoupler_path() -> Vec<PathCmd> {
541    vec![
542        // Box
543        PathCmd::MoveTo(-10.0, -10.0),
544        PathCmd::LineTo(10.0, -10.0),
545        PathCmd::LineTo(10.0, 10.0),
546        PathCmd::LineTo(-10.0, 10.0),
547        PathCmd::Close,
548        // LED symbol (left half)
549        PathCmd::MoveTo(-8.0, -4.0),
550        PathCmd::LineTo(-2.0, 0.0),
551        PathCmd::LineTo(-8.0, 4.0),
552        PathCmd::Close,
553        // Light arrows
554        PathCmd::MoveTo(-1.0, -3.0),
555        PathCmd::LineTo(2.0, -5.0),
556        PathCmd::MoveTo(-1.0, 0.0),
557        PathCmd::LineTo(2.0, -2.0),
558        // LDR symbol (right half) — zigzag
559        PathCmd::MoveTo(4.0, -4.0),
560        PathCmd::LineTo(5.0, -2.0),
561        PathCmd::LineTo(7.0, -3.0),
562        PathCmd::LineTo(5.0, 0.0),
563        PathCmd::LineTo(7.0, 1.0),
564        PathCmd::LineTo(5.0, 2.0),
565        PathCmd::LineTo(4.0, 4.0),
566    ]
567}
568
569/// Generic IC chip (rectangle with pins).
570fn ic_chip_path() -> Vec<PathCmd> {
571    vec![
572        PathCmd::MoveTo(-10.0, -12.0),
573        PathCmd::LineTo(10.0, -12.0),
574        PathCmd::LineTo(10.0, 12.0),
575        PathCmd::LineTo(-10.0, 12.0),
576        PathCmd::Close,
577        // Pin 1 dot
578        PathCmd::ArcTo(-6.0, -8.0, 1.5, 0.0, std::f32::consts::TAU),
579    ]
580}
581
582/// Ground symbol: three horizontal lines.
583fn ground_path() -> Vec<PathCmd> {
584    vec![
585        PathCmd::MoveTo(0.0, -5.0),
586        PathCmd::LineTo(0.0, 0.0),
587        PathCmd::MoveTo(-8.0, 0.0),
588        PathCmd::LineTo(8.0, 0.0),
589        PathCmd::MoveTo(-5.0, 3.0),
590        PathCmd::LineTo(5.0, 3.0),
591        PathCmd::MoveTo(-2.0, 6.0),
592        PathCmd::LineTo(2.0, 6.0),
593    ]
594}
595
596/// Supply symbol: upward arrow.
597fn supply_path() -> Vec<PathCmd> {
598    vec![
599        PathCmd::MoveTo(0.0, 5.0),
600        PathCmd::LineTo(0.0, -5.0),
601        PathCmd::MoveTo(-3.0, -2.0),
602        PathCmd::LineTo(0.0, -5.0),
603        PathCmd::LineTo(3.0, -2.0),
604    ]
605}
606
607/// Speaker symbol.
608fn speaker_path() -> Vec<PathCmd> {
609    vec![
610        // Body
611        PathCmd::MoveTo(-5.0, -5.0),
612        PathCmd::LineTo(-5.0, 5.0),
613        PathCmd::LineTo(0.0, 5.0),
614        PathCmd::LineTo(8.0, 10.0),
615        PathCmd::LineTo(8.0, -10.0),
616        PathCmd::LineTo(0.0, -5.0),
617        PathCmd::Close,
618        // Lead
619        PathCmd::MoveTo(-15.0, 0.0),
620        PathCmd::LineTo(-5.0, 0.0),
621    ]
622}
623
624/// Input arrow.
625fn input_path() -> Vec<PathCmd> {
626    vec![
627        PathCmd::MoveTo(-10.0, 0.0),
628        PathCmd::LineTo(5.0, 0.0),
629        PathCmd::MoveTo(2.0, -4.0),
630        PathCmd::LineTo(5.0, 0.0),
631        PathCmd::LineTo(2.0, 4.0),
632    ]
633}
634
635/// Output arrow (larger).
636fn output_path() -> Vec<PathCmd> {
637    vec![
638        PathCmd::MoveTo(-10.0, 0.0),
639        PathCmd::LineTo(8.0, 0.0),
640        PathCmd::MoveTo(4.0, -5.0),
641        PathCmd::LineTo(8.0, 0.0),
642        PathCmd::LineTo(4.0, 5.0),
643    ]
644}
645
646/// LFO symbol (sine wave in box).
647fn lfo_path() -> Vec<PathCmd> {
648    vec![
649        PathCmd::MoveTo(-10.0, -8.0),
650        PathCmd::LineTo(10.0, -8.0),
651        PathCmd::LineTo(10.0, 8.0),
652        PathCmd::LineTo(-10.0, 8.0),
653        PathCmd::Close,
654        // Sine wave
655        PathCmd::MoveTo(-8.0, 0.0),
656        PathCmd::ArcTo(-4.0, 0.0, 4.0, std::f32::consts::PI, 0.0),
657        PathCmd::ArcTo(4.0, 0.0, 4.0, 0.0, std::f32::consts::PI),
658    ]
659}
660
661/// Neon bulb.
662fn neon_path() -> Vec<PathCmd> {
663    vec![
664        // Circle (envelope)
665        PathCmd::ArcTo(0.0, 0.0, 8.0, 0.0, std::f32::consts::TAU),
666        // Two dots (electrodes)
667        PathCmd::ArcTo(-3.0, 0.0, 1.5, 0.0, std::f32::consts::TAU),
668        PathCmd::ArcTo(3.0, 0.0, 1.5, 0.0, std::f32::consts::TAU),
669        // Leads
670        PathCmd::MoveTo(-8.0, 0.0),
671        PathCmd::LineTo(-15.0, 0.0),
672        PathCmd::MoveTo(8.0, 0.0),
673        PathCmd::LineTo(15.0, 0.0),
674    ]
675}
676
677/// Switch symbol.
678fn switch_path() -> Vec<PathCmd> {
679    vec![
680        // Two terminals
681        PathCmd::ArcTo(-8.0, 0.0, 2.0, 0.0, std::f32::consts::TAU),
682        PathCmd::ArcTo(8.0, 0.0, 2.0, 0.0, std::f32::consts::TAU),
683        // Switch arm
684        PathCmd::MoveTo(-6.0, 0.0),
685        PathCmd::LineTo(6.0, -5.0),
686        // Leads
687        PathCmd::MoveTo(-15.0, 0.0),
688        PathCmd::LineTo(-8.0, 0.0),
689        PathCmd::MoveTo(8.0, 0.0),
690        PathCmd::LineTo(15.0, 0.0),
691    ]
692}