]> git.donarmstrong.com Git - lilypond.git/blob - mf/feta-bolletjes.mf
48eb3649c3693334805d8bca3d6ac375d6c5d29a
[lilypond.git] / mf / feta-bolletjes.mf
1 %  -*-Fundamental-*-
2 % feta-bolletjes.mf --  implement noteheads
3 %
4 % source file of LilyPond's pretty-but-neat music font
5 %
6 % (c) 1997--2006 Jan Nieuwenhuizen <janneke@gnu.org>
7 % & Han-Wen Nienhuys <hanwen@xs4all.nl>
8 % & Juergen Reuter <reuter@ipd.uka.de>
9 %
10
11 test_outlines := 0;
12
13
14 save remember_pic;
15 picture remember_pic;
16
17
18 % Most beautiful noteheads are pronounced, not circular,
19 % and not even symmetric.
20 % These examples are inspired by [Wanske]; see literature list.
21
22
23
24 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
25 % NOTE HEAD VARIABLES
26 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
27
28 save black_notehead_width, noteheight;
29 save half_notehead_width, whole_notehead_width, slash_thick;
30 save slash_slope, overdone_heads, solfa_noteheight;
31
32 numeric noteheight;
33 numeric slash_thick;
34 numeric black_notehead_width;
35 numeric whole_notehead_width;
36 numeric half_notehead_width;
37
38
39 fet_begingroup ("noteheads");
40
41
42 % Slope of slash.  From scm/grob-description.scm.  How to auto-copy?
43 slash_slope := 1.7;
44
45 % Thickness of slash lines.  Quarter notes get 1.5slt width.
46 slash_thick# := 2/3 * 0.48 staff_space#;
47
48
49 %
50 % Hand-engraved music often has balls extending above and below
51 % the lines.  If you like that, modify overdone heads (unit:
52 % stafflinethickness).
53 %
54 overdone_heads = 0.0;
55 noteheight# := staff_space# + (1 + overdone_heads) * stafflinethickness#;
56
57
58 %
59 % solfa heads should not overlap on chords.
60 %
61 solfa_noteheight# := staff_space# - stafflinethickness#;
62
63 define_pixels (slash_thick);
64 define_whole_vertical_pixels (noteheight);
65
66
67 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
68 %
69 % SLANT moves both extrema on the long axis (by SLANT * ELLIPTICITY,
70 % so SLANT = -1, puts the extreme on the long axis next to the short
71 % axis one).
72 %
73
74 def draw_outside_ellipse (expr ellipticity, tilt, superness, slant) =
75         save attachment_y;
76         save pat;
77         path pat;
78
79         pat := superellipse ((ellipticity, 0), (-slant * ellipticity, 1.0),
80                              (-ellipticity, 0), (slant * ellipticity, -1.0),
81                              superness);
82         pat := pat rotated tilt;
83
84         save top_point, right_point;
85         pair top_point, right_point;
86
87         top_point := directionpoint left of pat;
88         right_point := directionpoint up of pat;
89
90         save scaling, width;
91
92         scaling# = noteheight# / (2 ypart (top_point));
93         width# := 2 xpart (right_point) * scaling#;
94         define_pixels (scaling, width);
95
96         set_char_box (0, width#, noteheight# / 2, noteheight# / 2);
97
98         d := d - feta_space_shift;
99
100         % attachment Y
101         charwy := ypart (right_point) * scaling#;
102         charwx := width#;
103
104         pat := pat scaled scaling shifted (w / 2, .5 (h - d));
105
106         width := hround width;
107
108         if test_outlines = 1:
109                 draw pat;
110         else:
111                 fill pat;
112         fi;
113 enddef;
114
115
116 def undraw_inside_ellipse (expr ellipticity, tilt, superness, clearance) =
117 begingroup
118         save pat;
119         path pat;
120
121         pat := superellipse ((ellipticity, 0), (0, 1.0),
122                              (-ellipticity, 0), (0, -1.0),
123                              superness);
124         pat := pat rotated tilt;
125
126         save top_point, right_point;
127         pair top_point, right_point;
128
129         top_point := directionpoint left of pat;
130         right_point := directionpoint up of pat;
131
132         save height, scaling;
133
134         height# = staff_space# + stafflinethickness# - clearance;
135         scaling# = height# / (2 ypart (top_point));
136         define_pixels (scaling);
137         pat := pat scaled scaling shifted (w / 2, .5 (h - d));
138
139         if test_outlines = 1:
140                 draw pat;
141         else:
142                 unfill pat;
143         fi
144 endgroup;
145 enddef;
146
147
148 %
149 % dimensions aren't entirely right.
150 %
151 def draw_brevis =
152         save stemthick, fudge;
153
154         stemthick# = 2 stafflinethickness#;
155         define_whole_blacker_pixels (stemthick);
156
157         fudge = hround (blot_diameter / 2);
158
159         draw_outside_ellipse (1.80, 0, 0.707, 0);
160         undraw_inside_ellipse (1.30, 125, 0.68, 2 stafflinethickness#);
161
162         pickup pencircle scaled stemthick;
163
164         bot y1 = -d;
165         top y2 = h;
166         rt x1 - fudge = 0;
167         x1 = x2;
168
169         fudge + lft x3 = w;
170         x4 = x3;
171         y4 = y2;
172         y3 = y1;
173
174         draw_gridline (z1, z2, stemthick);
175         draw_gridline (z3, z4, stemthick);
176 enddef;
177
178
179 fet_beginchar ("Brevis notehead", "s-1");
180         draw_brevis;
181
182         draw_staff (-2, 2, 0);
183 fet_endchar;
184
185
186 if test > 0:
187         fet_beginchar ("Brevis notehead", "s-1");
188                 draw_brevis;
189
190                 draw_staff (-2, 2, 0.5);
191         fet_endchar;
192 fi;
193
194
195 fet_beginchar ("Whole notehead", "s0");
196         draw_outside_ellipse (1.80 - puff_up_factor / 3.0, 0, 0.707, 0);
197         undraw_inside_ellipse (1.30, 125 - puff_up_factor * 10,
198                                0.68, 2 stafflinethickness#);
199
200         whole_notehead_width# := charwd;
201
202         draw_staff (-2, 2, 0);
203 fet_endchar;
204
205
206 if test > 0:
207         fet_beginchar ("Whole notehead", "s0");
208                 draw_outside_ellipse (1.80 - puff_up_factor / 3.0, 0,
209                                       0.707, 0);
210                 undraw_inside_ellipse (1.30, 125 - puff_up_factor * 10,
211                                        0.68, 2 stafflinethickness#);
212
213                 draw_staff (-2, 2, 0.5);
214         fet_endchar;
215 fi;
216
217
218
219
220 fet_beginchar ("Half notehead", "s1");
221         draw_outside_ellipse (1.53 - puff_up_factor / 3.0, 34, 0.66, 0.17);
222         undraw_inside_ellipse (3.25, 33, 0.81, 2.5 stafflinethickness#);
223
224         half_notehead_width# := charwd;
225
226         draw_staff (-2, 2, 0);
227 fet_endchar;
228
229
230 if test > 0:
231         fet_beginchar ("Half notehead", "s1");
232                 draw_outside_ellipse (1.53 - puff_up_factor / 3.0, 34,
233                                       0.66, 0.17);
234                 undraw_inside_ellipse (3.25, 33, 0.81,
235                                        2.5 stafflinethickness#);
236
237                 draw_staff (-2, 2, 0.5);
238         fet_endchar;
239 fi;
240
241
242 fet_beginchar ("Quart notehead", "s2");
243         % used to have 32. With 31, they are slightly bolder.
244         draw_outside_ellipse (1.49 - puff_up_factor / 3.0, 31, 0.707, 0);
245         black_notehead_width# := charwd;
246
247         draw_staff (-2, 2, 0);
248 fet_endchar;
249
250 if test > 0:
251         fet_beginchar ("Quart notehead", "s2");
252                 draw_outside_ellipse (1.49 - puff_up_factor / 3.0, 31,
253                                       0.707, 0);
254
255                 draw_staff (-2, 2, 0.5);
256         fet_endchar;
257 fi;
258
259
260 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
261
262
263 fet_beginchar ("Whole diamondhead", "s0diamond");
264         draw_outside_ellipse (1.80, 0, 0.495, 0);
265         undraw_inside_ellipse (1.30, 125, 0.6,
266                                .4 staff_space# + stafflinethickness#);
267
268         draw_staff (-2, 2, 0);
269 fet_endchar;
270
271
272 if test > 0:
273         fet_beginchar ("Whole diamondhead", "s0diamond");
274                 draw_outside_ellipse (1.80, 0, 0.495, 0);
275                 undraw_inside_ellipse (1.30, 125, 0.6,
276                                        .4 staff_space# + stafflinethickness#);
277
278                 draw_staff (-2, 2, 0.5);
279         fet_endchar;
280 fi;
281
282
283 fet_beginchar ("Half diamondhead", "s1diamond");
284         draw_outside_ellipse (1.50, 34, 0.49, 0.17);
285         undraw_inside_ellipse (3.5, 33, 0.80,
286                                .3 staff_space# + 1.5 stafflinethickness#);
287
288         draw_staff (-2, 2, 0);
289 fet_endchar;
290
291
292 if test > 0:
293         fet_beginchar ("Half diamondhead", "s1diamond");
294                 draw_outside_ellipse (1.50, 34, 0.49, 0.17);
295                 undraw_inside_ellipse (3.5, 33, 0.80,
296                                        .3 staff_space#
297                                        + 1.5 stafflinethickness#);
298
299                 draw_staff (-2, 2, 0.5);
300         fet_endchar;
301 fi;
302
303
304 fet_beginchar ("Quart diamondhead", "s2diamond");
305         draw_outside_ellipse (1.80, 35, 0.495, -0.25);
306
307         draw_staff (-2, 2, 0);
308 fet_endchar;
309
310
311 if test > 0:
312         fet_beginchar ("Quart diamondhead", "s2diamond");
313                 draw_outside_ellipse (1.80, 35, 0.495, -0.25);
314
315                 draw_staff (-2, 2, 0.5);
316         fet_endchar;
317 fi;
318
319
320 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
321
322
323 vardef penposx@# (expr d) = 
324 begingroup;
325         save pat;
326         path pat;
327
328         pat = top z@#
329               .. lft z@#
330               .. bot z@#
331               .. rt z@#
332               .. cycle;
333         z@#l = pat intersectionpoint (z@# -- infinity * dir (d + 180));
334         z@#r = pat intersectionpoint (z@# -- infinity * dir (d));
335 endgroup
336 enddef;
337
338
339 %
340 %
341 % UGH : xs not declared as argument.
342 %
343 def define_triangle_shape (expr stemdir) =
344         save triangle_a, triangle_b, triangle_c;
345         save triangle_out_a, triangle_out_b, triangle_out_c;
346         save triangle_in, triangle_out;
347         save width, depth, height;
348         save origin, left_up_dir;
349         save exact_left_point, exact_right_point, exact_down_point;
350
351         path triangle_a, triangle_b, triangle_c;
352         path triangle_out_a, triangle_out_b, triangle_out_c;
353         path triangle_in, triangle_out;
354         pair origin, left_up_dir;
355         pair exact_down_point, exact_left_point, exact_right_point;
356
357         save pen_thick;
358         pen_thick# = stafflinethickness# + .1 staff_space#;
359         define_pixels (llap);
360         define_blacker_pixels (pen_thick);
361
362         left_up_dir = llap# * dir (90 + tilt);
363
364         xpart (left_up_dir) * xs - (pen_thick# * xs) / 2 + xpart origin = 0;
365         ypart origin = 0;
366
367         exact_left_point := origin + (left_up_dir xscaled xs);
368         exact_down_point := origin + (left_up_dir rotated 120 xscaled xs);
369         exact_right_point := origin + (left_up_dir rotated 240 xscaled xs);
370
371         height# = ypart (exact_left_point + origin) + pen_thick# / 2;
372         depth# = -ypart (exact_down_point + origin) + pen_thick# / 2;
373         width# = xpart (exact_right_point - exact_left_point)
374                  + pen_thick# * xs;
375
376         set_char_box (0, width#, depth#, height#);
377
378         % Formerly, the shape has simply been drawn with an elliptical pen
379         % (`scaled pen_thick xsaled xs'), but the envelope of such a curve
380         % is of 6th degree.  For the sake of mf2pt1, we approximate it.
381
382         pickup pencircle scaled pen_thick xscaled xs;
383
384         z0 = (hround_pixels (xpart origin), 0);
385
386         z1 = z1' = z0 + llap * dir (90 + tilt) xscaled xs;
387         z2 = z2' = z0 + llap * dir (90 + tilt + 120) xscaled xs;
388         z3 = z3' = z0 + llap * dir (90 + tilt + 240) xscaled xs;
389
390         z12 = caveness [.5[z1, z2], z3];
391         z23 = caveness [.5[z2, z3], z1];
392         z31 = caveness [.5[z3, z1], z2];
393
394         triangle_a = z1 .. z12 .. z2;
395         triangle_b = z2 .. z23 .. z3;
396         triangle_c = z3 .. z31 .. z1;
397
398         penposx1 (angle (direction 0 of triangle_a) - 90);
399         penposx2 (angle (direction 0 of triangle_b) - 90);
400         penposx3 (angle (direction 0 of triangle_c) - 90);
401
402         penposx1' (angle (direction infinity of triangle_c) + 90);
403         penposx2' (angle (direction infinity of triangle_a) + 90);
404         penposx3' (angle (direction infinity of triangle_b) + 90);
405
406         penposx12 (angle (z12 - z0));
407         penposx23 (angle (z23 - z0));
408         penposx31 (angle (z31 - z0));
409
410         z10 = (z0 -- z1) intersectionpoint (z1l .. z12l .. z2'r);
411         z20 = (z0 -- z2) intersectionpoint (z2l .. z23l .. z3'r);
412         z30 = (z0 -- z3) intersectionpoint (z3l .. z31l .. z1'r);
413
414         triangle_in = z10
415                       .. z12l
416                       .. z20
417                       & z20
418                       .. z23l
419                       .. z30
420                       & z30
421                       .. z31l
422                       .. z10
423                       & cycle;
424
425         triangle_out_a = z1r .. z12r .. z2'l;
426         triangle_out_b = z2r .. z23r .. z3'l;
427         triangle_out_c = z3r .. z31r .. z1'l;
428
429         triangle_out = top z1
430                        .. lft z1
431                        .. z1r{direction 0 of triangle_out_a}
432                        & triangle_out_a
433                        & {direction infinity of triangle_out_a}z2'l
434                        .. lft z2
435                        .. bot z2
436                        .. z2r{direction 0 of triangle_out_b}
437                        & triangle_out_b
438                        & {direction infinity of triangle_out_b}z3'l
439                        .. rt z3
440                        .. top z3
441                        .. z3r{direction 0 of triangle_out_c}
442                        & triangle_out_c
443                        & {direction infinity of triangle_out_c}z1'l
444                        .. cycle;
445
446
447         labels (0, 10, 20, 30);
448         penlabels (1, 1', 2, 2', 3, 3', 12, 23, 31);
449
450         % attachment Y
451         if stemdir = 1:
452                 charwy := ypart exact_right_point;
453                 charwx := xpart exact_right_point + .5 pen_thick# * xs;
454         else:
455                 charwy := -ypart exact_down_point;
456                 charwx := (width# - (xpart exact_down_point - 0.5 * xs * pen_thick#));
457         fi
458 enddef;
459
460
461 def draw_whole_triangle_head =
462         save hei, xs;
463         save llap;
464         save tilt;
465
466         tilt = 40;
467         llap# = 3/4 noteheight#;
468
469         xs = 1.5;
470         caveness := 0.1;
471         define_triangle_shape (1);
472         fill triangle_out;
473         unfill triangle_in;
474 enddef;
475
476
477 fet_beginchar ("Whole trianglehead", "s0triangle");
478         draw_whole_triangle_head;
479
480         draw_staff (-2, 2, 0);
481 fet_endchar;
482
483
484 if test > 0:
485         fet_beginchar ("Whole trianglehead", "s0triangle");
486                 draw_whole_triangle_head;
487
488                 draw_staff (-2, 2, 0.5);
489         fet_endchar;
490 fi;
491
492
493 def draw_small_triangle_head (expr dir) =
494         save hei, xs;
495         save llap;
496         save tilt;
497
498         tilt = 40;
499         llap# = 2/3 noteheight#;
500         xs = 1.2;
501         caveness := 0.1;
502         define_triangle_shape (dir);
503
504         pickup feta_fillpen;
505
506         filldraw triangle_out;
507         unfilldraw triangle_in;
508 enddef;
509
510
511 fet_beginchar ("Half trianglehead (downstem)", "d1triangle");
512         draw_small_triangle_head (-1);
513
514         draw_staff (-2, 2, 0);
515 fet_endchar;
516
517
518 fet_beginchar ("Half trianglehead (upstem)", "u1triangle");
519         draw_small_triangle_head (1);
520
521         draw_staff (-2, 2, 0.5);
522 fet_endchar;
523
524
525 def draw_closed_triangle_head (expr dir) =
526         save hei, xs;
527         save llap;
528         save tilt;
529
530         tilt = 40;
531         llap# = 2/3 noteheight#;
532         xs = 1.0;
533         caveness := 0.1;
534         define_triangle_shape (dir);
535         fill triangle_out;
536 enddef;
537
538
539 fet_beginchar ("Quart trianglehead (upstem)", "u2triangle");
540         draw_closed_triangle_head (1);
541
542         draw_staff (-2, 2, 0);
543 fet_endchar;
544
545
546 fet_beginchar ("Quart trianglehead (downstem)", "d2triangle");
547         draw_closed_triangle_head (-1);
548
549         draw_staff (-2, 2, 0.5);
550 fet_endchar;
551
552
553 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
554 %
555 % Slash heads are for indicating improvisation.  They are
556 % twice as high as normal heads.
557 %
558 def draw_slash (expr hwid_hash) =
559         save exact_height;
560         save ne, nw_dist;
561         pair ne, nw_dist;
562         exact_height = staff_space# + stafflinethickness# / 2;
563
564         set_char_box (0, 2 exact_height / slash_slope + hwid_hash,
565                       exact_height, exact_height);
566
567         charwx := charwd;
568         charwy := charht;
569
570         clearxy;
571
572         d := d - feta_shift;
573
574         pickup pencircle scaled blot_diameter;
575
576         bot y1 = -d;
577         top y2 = h;
578         lft x1 = 0;
579         lft x2 = 2 h / slash_slope;
580
581         rt x3 = w;
582         y3 = y2;
583         y4 = y1;
584         x3 - x2 = x4 - x1;
585
586         ne = unitvector (z3 - z4);
587         nw_dist = (ne rotated 90) * 0.5 blot_diameter;
588
589         fill bot z1{left}
590              .. (z1 + nw_dist){ne}
591              -- (z2 + nw_dist){ne}
592              .. top z2{right}
593              -- top z3{right}
594              .. (z3 - nw_dist){-ne}
595              -- (z4 - nw_dist){-ne}
596              .. bot z4{left}
597              -- cycle;
598
599         if hwid_hash > 2 slash_thick#:
600                 save th;
601
602                 th = slash_thick - blot_diameter;
603                 y6 = y7;
604                 y5 = y8;
605                 y3 - y7 = th;
606                 y5 - y1 = th;
607                 z6 - z5 = whatever * ne;
608                 z8 - z7 = whatever * ne;
609
610                 z5 = z1 + whatever * ne + th * (ne rotated -90);
611                 z8 = z4 + whatever * ne + th * (ne rotated 90);
612
613                 unfill z5
614                        -- z6
615                        -- z7
616                        -- z8
617                        -- cycle;
618         fi
619         labels (range 1 thru 10);
620 enddef;
621
622
623 fet_beginchar ("Whole slashhead", "s0slash");
624         draw_slash (4 slash_thick# + 0.5 staff_space#);
625
626         draw_staff (-2, 2, 0);
627 fet_endchar;
628
629
630 fet_beginchar ("Half slashhead", "s1slash");
631         draw_slash (3.0 slash_thick# + 0.15 staff_space#);
632
633         draw_staff (-2, 2, 0);
634 fet_endchar;
635
636
637 fet_beginchar ("Quart slashhead", "s2slash");
638         draw_slash (1.5 slash_thick#);
639
640         draw_staff (-2, 2, 0);
641 fet_endchar;
642
643
644 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
645 %
646 % `thick' is the distance between the NE/SW parallel lines in the cross
647 % (distance between centres of lines) in multiples of stafflinethickness
648 %
649 def draw_cross (expr thick) =
650         save ne, nw;
651         save ne_dist, nw_dist, rt_dist, up_dist;
652         save crz_in, crz_out;
653         save thickness;
654         pair ne, nw;
655         pair ne_dist, nw_dist, rt_dist, up_dist;
656         path crz_in, crz_out;
657
658         pen_thick# := 1.2 stafflinethickness#;
659         thickness# := thick * stafflinethickness#;
660         define_pixels (thickness);
661         define_blacker_pixels (pen_thick);
662
663         pickup pencircle scaled pen_thick;
664
665         h := h - feta_shift;
666
667         top y3 = h;
668         ne = unitvector ((1, (2 h - pen_thick) / (w - pen_thick)));
669         rt x4 = w / 2;
670         y5 = 0;
671         z4 - z5 = whatever * ne;
672         x6 = 0;
673         z6 - z3 = whatever * ne;
674         z3 - z4 = whatever * (ne yscaled -1);
675
676         z4 - z3 = whatever * (ne) + (ne rotated -90) * thickness;
677
678
679         x1 = charwd / 2 - .5 pen_thick#;
680         z1 = whatever * ne
681              + thick / 2 * stafflinethickness# * (ne rotated -90);
682
683         % labels (1, 2, 3, 4, 5, 6);
684
685         nw = unitvector (z3 - z4);
686
687         up_dist = up * 0.5 pen_thick / cosd (angle (ne));
688         rt_dist = right * 0.5 pen_thick / sind (angle (ne));
689         nw_dist = (ne rotated 90) * 0.5 pen_thick;
690         ne_dist = (nw rotated -90) * 0.5 pen_thick;
691
692         x4' := x4;
693         x5' := x5;
694         y6' := y6;
695
696         x4 := hround (x4' + .5 pen_thick) - .5 pen_thick;
697         x5 := hfloor (x5' + xpart rt_dist) - xpart rt_dist;
698         y6 := vfloor (y6' + ypart up_dist) - ypart up_dist;
699
700         crz_out = (z6 + up_dist)
701                   -- (z3 + nw_dist){ne}
702                   .. (top z3)
703                   .. (z3 + ne_dist){-nw}
704                   -- (z4 + ne_dist){-nw}
705                   .. (rt z4)
706                   .. (z4 - nw_dist){-ne}
707                   -- (z5 + rt_dist);
708         crz_out := crz_out shifted (0, feta_shift)
709                    -- reverse crz_out yscaled -1 shifted (0, -feta_eps);
710         fill crz_out
711              -- reverse crz_out xscaled -1 shifted (-feta_eps, 0)
712              -- cycle;
713
714         if (thick > 1):
715                 x4 := hround (x4' - xpart rt_dist) + xpart rt_dist;
716                 x5 := hceiling (x5' - .5 pen_thick) + .5 pen_thick;
717                 y6 := vfloor (y6' - .5 pen_thick) + .5 pen_thick;
718
719                 crz_in = (bot z6){right}
720                          .. (z6 - nw_dist){ne}
721                          -- (z3 - up_dist)
722                          -- (z4 - rt_dist)
723                          -- (z5 + nw_dist){-ne}
724                          .. {down}(lft z5);
725                 crz_in := crz_in shifted (0, feta_shift)
726                           -- reverse crz_in yscaled -1 shifted (0, -feta_eps);
727                 unfill crz_in
728                        -- reverse crz_in xscaled -1 shifted (-feta_eps, 0)
729                        -- cycle;
730         fi
731
732         % ugh
733         currentpicture := currentpicture shifted (hround (w / 2), 0);
734
735         charwx := charwd;
736         charwy := y1 + feta_shift;
737
738         z12 = (charwx * hppp, y1 * vppp);
739
740         labels (12);
741 enddef;
742
743
744 fet_beginchar ("Whole Crossed notehead", "s0cross");
745         save wid, hei;
746
747         wid# := black_notehead_width# + 4 stafflinethickness#;
748         hei# := noteheight# + stafflinethickness#;
749
750         set_char_box (0, wid#, hei# / 2, hei# / 2);
751
752         draw_cross (3.75);
753
754         remember_pic := currentpicture;
755
756         draw_staff (-2, 2, 0);
757 fet_endchar;
758
759
760 if test > 0:
761         fet_beginchar ("Whole Crossed notehead", "s0cross");
762                 save wid, hei;
763
764                 wid# := black_notehead_width# + 4 stafflinethickness#;
765                 hei# := noteheight# + stafflinethickness#;
766
767                 set_char_box (0, wid#, hei# / 2, hei# / 2);
768
769                 currentpicture := remember_pic;
770
771                 draw_staff (-2, 2, 0.5);
772         fet_endchar;
773 fi;
774
775
776 fet_beginchar ("Half Crossed notehead", "s1cross");
777         save wid, hei;
778
779         wid# := black_notehead_width# + 2 stafflinethickness#;
780         hei# := noteheight# + stafflinethickness# / 2;
781
782         set_char_box (0, wid#, hei# / 2, hei# / 2);
783
784         draw_cross (3.0);
785
786         remember_pic := currentpicture;
787
788         draw_staff (-2, 2, 0);
789 fet_endchar;
790
791
792 if test > 0:
793         fet_beginchar ("Half Crossed notehead", "s1cross");
794                 save wid, hei;
795
796                 wid# := black_notehead_width# + 2 stafflinethickness#;
797                 hei# := noteheight# + stafflinethickness# / 2;
798
799                 set_char_box (0, wid#, hei# / 2, hei# / 2);
800
801                 currentpicture := remember_pic;
802
803                 draw_staff (-2, 2, 0.5);
804         fet_endchar;
805 fi;
806
807
808 fet_beginchar ("Crossed notehead", "s2cross");
809         wid# := black_notehead_width#;
810         hei# := noteheight#;
811         set_char_box (0, wid#, hei# / 2, hei# / 2);
812
813         draw_cross (1.0);
814
815         remember_pic := currentpicture;
816
817         draw_staff (-2, 2, 0);
818 fet_endchar;
819
820
821 if test > 0:
822         fet_beginchar ("Crossed notehead", "s2cross");
823                 wid# := black_notehead_width#;
824                 hei# := noteheight#;
825                 set_char_box (0, wid#, hei# / 2, hei# / 2);
826
827                 currentpicture := remember_pic;
828
829                 draw_staff (-2, 2, 0.5);
830         fet_endchar;
831 fi;
832
833
834 fet_beginchar ("X-Circled notehead", "s2xcircle");
835         save wid, hei;
836         save cthick, cxd, cyd, dy;
837
838         wid# := black_notehead_width# * sqrt (sqrt2);
839         hei# := noteheight# * sqrt (sqrt2);
840
841         set_char_box (0, wid#, hei# / 2, hei# / 2);
842
843         d := d - feta_space_shift;
844
845         cthick# := (1.2 + 1/4) * stafflinethickness#;
846         define_blacker_pixels (cthick);
847
848         cxd := w - cthick;
849         cyd := h + d - cthick / 2;
850
851         dy = .5 (h - d);
852
853         pickup pencircle scaled cthick;
854
855         fill fullcircle xscaled (cxd + cthick)
856                         yscaled (cyd + cthick)
857                         shifted (w / 2, dy);
858         unfill fullcircle xscaled (cxd - cthick)
859                           yscaled (cyd - cthick)
860                           shifted (w / 2, dy);
861
862         xpos := .5 cxd / sqrt2;
863         ypos := .5 cyd / sqrt2;
864
865         pickup penrazor scaled cthick rotated (angle (xpos, ypos) + 90);
866         draw (-xpos + w / 2, -ypos + dy) -- (xpos + w / 2, ypos + dy);
867
868         pickup penrazor scaled cthick rotated (angle (xpos, -ypos) + 90);
869         draw (-xpos + w / 2, ypos + dy) -- (xpos + w / 2, -ypos + dy);
870
871         charwx := charwd;
872         charwy := 0;
873
874         z12 = (charwx * hppp, charwy * vppp);
875         labels (12);
876
877         remember_pic := currentpicture;
878
879         draw_staff (-2, 2, 0);
880 fet_endchar;
881
882
883 if test > 0:
884         fet_beginchar ("X-Circled notehead", "s2xcircle");
885                 save wid, hei;
886                 save cthick, cxr, cyr;
887
888                 wid# := black_notehead_width# * sqrt (sqrt2);
889                 hei# := noteheight# * sqrt (sqrt2);
890
891                 set_char_box (0, wid#, hei# / 2, hei# / 2);
892
893                 currentpicture := remember_pic;
894
895                 draw_staff (-2, 2, 0.5);
896         fet_endchar;
897 fi;
898
899
900 %%%%%%%%
901 %
902 % SOLFA SHAPED NOTES
903 %
904
905 save solfa_pen_thick;
906 solfa_pen_thick# = 1.75 stafflinethickness#;
907 define_blacker_pixels (solfa_pen_thick);
908
909
910 save solfa_base_notewidth;
911 solfa_base_notewidth# := black_notehead_width#;
912
913 solfa_whole_width := whole_notehead_width# / black_notehead_width#;
914 solfa_half_width := half_notehead_width# / black_notehead_width#;
915 solfa_quarter_width := 1.0;
916
917 def draw_do_head (expr width_factor, dir) =
918         save p_in, p_out;
919         save left_dist, right_dist;
920         path p_in, p_out;
921         pair left_dist, right_dist;
922
923         set_char_box (0, width_factor * solfa_base_notewidth#,
924                       0.5 solfa_noteheight#, 0.5 solfa_noteheight#);
925
926         pickup pencircle scaled solfa_pen_thick;
927
928         bot y1 = -d;
929         y1 = y2;
930         lft x1 = 0;
931         rt x2 = w;
932         top y3 = h;
933         x3 =.5 [x1, x2];
934
935         left_dist = (unitvector (z3 - z1) rotated 90) * 0.5 solfa_pen_thick;
936         right_dist = (unitvector (z2 - z3) rotated 90) * 0.5 solfa_pen_thick;
937
938         p_in := (((z1 - left_dist) -- (z3 - left_dist)) intersectionpoint
939                   (top z1 -- top z2))
940                 -- ((top z1 -- top z2) intersectionpoint
941                     ((z2 - right_dist) -- (z3 - right_dist)))
942                 -- (((z2 - right_dist) -- (z3 - right_dist)) intersectionpoint
943                     ((z1 - left_dist) -- (z3 - left_dist)))
944                 -- cycle;
945
946         p_out := bot z1
947                  -- bot z2{right}
948                  .. rt z2{up}
949                  .. (z2 + right_dist){z3 - z2}
950                  -- (z3 + right_dist){z3 - z2}
951                  .. top z3{left}
952                  .. (z3 + left_dist){z1 - z3}
953                  -- (z1 + left_dist){z1 - z3}
954                  .. lft z1{down}
955                  .. {right}cycle;
956                  
957
958         labels (1, 2, 3);
959
960         charwx := charwd;
961         charwy := -chardp + 0.5 stafflinethickness#;
962         if dir = -1:
963                 charwy := -charwy;
964         fi;
965 enddef;
966
967
968 fet_beginchar ("Whole dohead", "s0do");
969         draw_do_head (solfa_whole_width, 1);
970         fill p_out;
971         unfill p_in;
972 fet_endchar;
973
974
975 fet_beginchar ("Half dohead", "d1do");
976         draw_do_head (solfa_half_width, -1);
977         fill p_out;
978         unfill p_in;
979 fet_endchar;
980
981
982 fet_beginchar ("Half dohead", "u1do");
983         draw_do_head (solfa_half_width, 1);
984         fill p_out;
985         unfill p_in;
986 fet_endchar;
987
988
989 fet_beginchar ("Quart dohead", "d2do");
990         draw_do_head (solfa_quarter_width, -1);
991         fill p_out;
992 fet_endchar;
993
994
995 fet_beginchar ("Quart dohead", "u2do");
996         draw_do_head (solfa_quarter_width, 1);
997         fill p_out;
998 fet_endchar;
999
1000
1001 %
1002 % re - flat top, curved bottom:
1003 %                (0,h/2) {dir -90} .. (w/2,-h/2) .. {dir 90} (w,h/2) -- cycle;
1004 % (broader along the base and with more vertical sides for half and
1005 % whole notes)
1006 % stem attachment: h/2
1007 %
1008
1009 def draw_re_head (expr width_factor, dir) =
1010         save p_in, p_out;
1011         path p_in, p_out;
1012
1013         set_char_box (0, width_factor * solfa_base_notewidth#,
1014                       0.5 solfa_noteheight#, 0.5 solfa_noteheight#);
1015
1016         pickup pencircle scaled solfa_pen_thick;
1017
1018         save curve_start;
1019         curve_start = 0.7;
1020         lft x1 = 0;
1021         y1 = y5;
1022         x1 = x2;
1023         y2 = curve_start [y3, y1];
1024         bot y3 = -d;
1025         x3 = .5 [x2, x4];
1026         rt x4 = w;
1027         y4 = y2;
1028         top y5 = h;
1029         x5 = x4;
1030
1031         labels (range 1 thru 5);
1032
1033         p_in := (z1 + 0.5 solfa_pen_thick * (1, -1))
1034                 -- rt z2{down}
1035                 .. top z3
1036                 .. lft z4{up}
1037                 -- (z5 + 0.5 solfa_pen_thick * (-1, -1))
1038                 -- cycle;
1039
1040         p_out := lft z1
1041                  -- lft z2{down}
1042                  .. bot z3
1043                  .. rt z4{up}
1044                  -- rt z5{up}
1045                  .. top z5{left}
1046                  -- top z1{left}
1047                  .. {down}cycle;
1048
1049         charwx := charwd;
1050         charwy := curve_start [-chardp, charht];
1051
1052         if dir = -1:
1053                 charwy := -charwy;
1054         fi;
1055 enddef;
1056
1057
1058 fet_beginchar ("Whole rehead", "s0re");
1059         draw_re_head (solfa_whole_width, 1);
1060         fill p_out;
1061         unfill p_in;
1062 fet_endchar;
1063
1064
1065 fet_beginchar ("Half up rehead", "u1re");
1066         draw_re_head (solfa_half_width, 1);
1067         fill p_out;
1068         unfill p_in;
1069 fet_endchar;
1070
1071
1072 fet_beginchar ("Half down rehead", "d1re");
1073         draw_re_head (solfa_half_width, -1);
1074         fill p_out;
1075         unfill p_in;
1076 fet_endchar;
1077
1078
1079 fet_beginchar ("Quart rehead", "u2re");
1080         draw_re_head (solfa_quarter_width, 1);
1081         fill p_out;
1082 fet_endchar;
1083
1084
1085 fet_beginchar ("Quart rehead", "d2re");
1086         draw_re_head (solfa_quarter_width, -1);
1087         fill p_out;
1088 fet_endchar;
1089
1090
1091 def draw_mi_head (expr width_factor) =
1092         save path_out, path_in;
1093         save ne_dist, se_dist, ne, se;
1094         path path_out, path_in;
1095         pair ne_dist, se_dist, ne, se;
1096
1097         set_char_box (0, width_factor * solfa_base_notewidth#,
1098                       0.5 solfa_noteheight#, 0.5 solfa_noteheight#);
1099
1100         pickup pencircle scaled solfa_pen_thick;
1101
1102         lft x1 = 0;
1103         y1 = 0;
1104         bot y2 = -d;
1105         x2 = .5 [x1, x3];
1106         rt x3 = w;
1107         x4 = x2;
1108         y3 = y1;
1109         top y4 = h;
1110
1111         z6 - z5 = whatever * (z2 - z1);
1112         z8 - z7 = whatever * (z2 - z1);
1113         z8 - z5 = whatever * (z4 - z1);
1114         z6 - z7 = whatever * (z4 - z1);
1115
1116         ne = unitvector (z4 - z1);
1117         se = unitvector (z1 - z2);
1118
1119         ne_dist = (ne rotated 90) * 0.5 solfa_pen_thick;
1120         se_dist = (se rotated 90) * 0.5 solfa_pen_thick;
1121
1122         z5 = whatever [z1, z4] - ne_dist;
1123         z5 = whatever [z1, z2] - 1.5 se_dist;
1124
1125         z5 - z1 = -(z7 - z3);
1126
1127         labels (range 1 thru 8);
1128
1129         path_in := z5
1130                    -- z6
1131                    -- z7
1132                    -- z8
1133                    -- cycle;
1134
1135         path_out := lft z1
1136                     .. (z1 + se_dist){-se}
1137                     -- (z2 + se_dist){-se}
1138                     .. bot z2
1139                     .. (z2 - ne_dist){ne}
1140                     -- (z3 - ne_dist){ne}
1141                     .. rt z3
1142                     .. (z3 - se_dist){se}
1143                     -- (z4 - se_dist){se}
1144                     .. top z4
1145                     .. (z4 + ne_dist){-ne}
1146                     -- (z1 + ne_dist){-ne}
1147                     .. cycle;
1148 enddef;
1149
1150
1151 fet_beginchar ("Whole mihead", "s0mi");
1152         draw_mi_head (solfa_whole_width);
1153         fill path_out;
1154         unfill path_in;
1155 fet_endchar;
1156
1157
1158 fet_beginchar ("Half mihead", "s1mi");
1159         draw_mi_head (solfa_quarter_width);
1160         fill path_out;
1161         unfill path_in;
1162 fet_endchar;
1163
1164
1165 fet_beginchar ("Quart mihead", "s2mi");
1166         draw_mi_head (solfa_quarter_width);
1167         fill path_out;
1168 fet_endchar;
1169
1170
1171 def draw_fa_head (expr width_factor) =
1172         set_char_box (0, width_factor * solfa_base_notewidth#,
1173                       0.5 solfa_noteheight#, 0.5 solfa_noteheight#);
1174
1175         save p_down_in, p_down_out, p_up_in, p_up_out, nw_dist, nw;
1176         path p_down_in, p_down_out, p_up_in, p_up_out;
1177         pair nw_dist, nw;
1178
1179         pickup pencircle scaled solfa_pen_thick;
1180
1181         lft x1 = 0;
1182         top y1 = h;
1183
1184         rt x2 = w;
1185         y2 = y1;
1186         bot y3 = -d;
1187         x3 = x2;
1188
1189         y4 = y3;
1190         x4 = x1;
1191
1192         labels (1, 2, 3, 4);
1193
1194         nw = unitvector (z1 - z3);
1195         nw_dist = (nw rotated 90) * 0.5 solfa_pen_thick;
1196
1197         p_up_in := (((z1 - nw_dist) -- (z3 - nw_dist)) intersectionpoint
1198                      (bot z1 -- bot z2))
1199                    -- (((z1 - nw_dist) -- (z3 - nw_dist)) intersectionpoint
1200                         (lft z3 -- lft z2))
1201                    -- (z2 + 0.5 solfa_pen_thick * (-1, -1))
1202                    -- cycle;
1203
1204         p_up_out := lft z1{down}
1205                     .. (z1 + nw_dist){-nw}
1206                     -- (z3 + nw_dist){-nw}
1207                     .. bot z3{right}
1208                     .. rt z3{up}
1209                     -- rt z2{up}
1210                     .. top z2{left}
1211                     -- top z1{left}
1212                     .. {down}cycle;
1213
1214         p_down_in := p_up_in rotated 180 shifted (w, 0);
1215         p_down_out := p_up_out rotated 180 shifted (w, 0);
1216
1217         charwy := 0.0;
1218         charwx := charwd;
1219 enddef;
1220
1221
1222 fet_beginchar ("Whole fa up head", "u0fa");
1223         draw_fa_head (solfa_whole_width);
1224         fill p_up_out;
1225         unfill p_up_in;
1226 fet_endchar;
1227
1228
1229 fet_beginchar ("Whole fa down head", "d0fa");
1230         draw_fa_head (solfa_whole_width);
1231         fill p_down_out;
1232         unfill p_down_in;
1233 fet_endchar;
1234
1235
1236 fet_beginchar ("half fa up head", "u1fa");
1237         draw_fa_head (solfa_half_width);
1238         fill p_up_out;
1239         unfill p_up_in;
1240 fet_endchar;
1241
1242
1243 fet_beginchar ("Half fa down head", "d1fa");
1244         draw_fa_head (solfa_half_width);
1245         fill p_down_out;
1246         unfill p_down_in;
1247 fet_endchar;
1248
1249
1250 fet_beginchar ("Quarter fa up head", "u2fa");
1251         draw_fa_head (solfa_quarter_width);
1252         fill p_up_out;
1253 fet_endchar;
1254
1255
1256 fet_beginchar ("Quarter fa down head", "d2fa");
1257         draw_fa_head (solfa_quarter_width);
1258         fill p_down_out;
1259 fet_endchar;
1260
1261
1262 def draw_la_head (expr width_factor) =
1263         set_char_box (0, width_factor * solfa_base_notewidth#,
1264                       0.5 solfa_noteheight#, 0.5 solfa_noteheight#);
1265         save p_in, p_out;
1266         path p_in, p_out;
1267
1268         pickup pencircle scaled solfa_pen_thick;
1269
1270         lft x1 = 0;
1271         top y1 = h;
1272
1273         rt x2 = w;
1274         y2 = y1;
1275         bot y3 = -d;
1276         x3 = x2;
1277
1278         y4 = y3;
1279         x4 = x1;
1280
1281         labels (range 1 thru 4);
1282
1283         p_in := (z1 + 0.5 solfa_pen_thick * (1, -1))
1284                 -- (z2 + 0.5 solfa_pen_thick * (-1, -1))
1285                 -- (z3 + 0.5 solfa_pen_thick * (-1, 1))
1286                 -- (z4 + 0.5 solfa_pen_thick * (1, 1))
1287                 -- cycle;
1288
1289         p_out := top z1
1290                  -- top z2{right}
1291                  .. rt z2{down}
1292                  -- rt z3{down}
1293                  .. bot z3{left}
1294                  -- bot z4{left}
1295                  .. lft z4{up}
1296                  -- lft z1{up}
1297                  .. cycle;
1298 enddef;
1299
1300
1301 fet_beginchar ("Whole lahead", "s0la");
1302         draw_la_head (solfa_whole_width);
1303         fill p_out;
1304         unfill p_in;
1305 fet_endchar;
1306
1307
1308 fet_beginchar ("Half lahead", "s1la");
1309         draw_la_head (solfa_half_width);
1310         fill p_out;
1311         unfill p_in;
1312 fet_endchar;
1313
1314
1315 fet_beginchar ("Quart lahead", "s2la");
1316         draw_la_head (solfa_quarter_width);
1317         fill p_out;
1318 fet_endchar;
1319
1320
1321 def draw_ti_head (expr width_factor, dir) =
1322         set_char_box (0, width_factor * solfa_base_notewidth#,
1323                       0.5 solfa_noteheight#, 0.5 solfa_noteheight#);
1324         save p_in, p_out, p_top;
1325         save nw_dist, sw_dist, nw, sw;
1326         path p_in, p_out, p_top;
1327         pair nw_dist, sw_dist, nw, sw;
1328         save cone_height;
1329         cone_height = 0.64;
1330
1331         pickup pencircle scaled solfa_pen_thick;
1332
1333         x1 = .5 [x2, x4];
1334         bot y1 = -d;
1335         lft x2 = 0;
1336         y2 = cone_height [y1, y3];
1337         rt x4 = w;
1338         y4 = y2;
1339         x3 = x1;
1340         top y3 = h;
1341
1342         labels (range 1 thru 4);
1343
1344         nw = unitvector (z2 - z1);
1345         sw = unitvector (z1 - z4);
1346
1347         nw_dist = (nw rotated 90) * 0.5 solfa_pen_thick;
1348         sw_dist = (sw rotated 90) * 0.5 solfa_pen_thick;
1349
1350         p_top := (z2 - sw_dist)
1351                  .. (top z3){right}
1352                  .. (z4 - nw_dist);
1353
1354         p_in := (((z1 - nw_dist) -- (z2 - nw_dist)) intersectionpoint
1355                   ((z1 - sw_dist) -- (z4 - sw_dist)))
1356                 -- (((z1 - nw_dist) -- (z2 - nw_dist)) intersectionpoint
1357                      ((z2 + sw_dist) .. {right}(bot z3)))
1358                 .. bot z3
1359                 .. (((bot z3){right} .. (z4 + nw_dist)) intersectionpoint
1360                      ((z1 - sw_dist) -- (z4 - sw_dist)))
1361                 -- cycle;
1362
1363         p_out := bot z1
1364                  .. (z1 + nw_dist)
1365                  -- (z2 + nw_dist)
1366                  .. lft z2
1367                  .. (z2 - sw_dist){direction 0 of p_top}
1368                  & p_top
1369                  & {direction infinity of p_top}(z4 - nw_dist)
1370                  .. rt z4
1371                  .. (z4 + sw_dist)
1372                  -- (z1 + sw_dist)
1373                  .. cycle;
1374
1375         charwx := charwd;
1376         charwy := cone_height [-chardp, charht];
1377         if dir = -1:
1378                 charwy := -charwy;
1379         fi;
1380 enddef;
1381
1382
1383 fet_beginchar ("Whole up tihead", "s0ti");
1384         draw_ti_head (solfa_whole_width, 1);
1385         fill p_out;
1386         unfill p_in;
1387 fet_endchar;
1388
1389
1390 fet_beginchar ("Half up tihead", "u1ti");
1391         draw_ti_head (solfa_half_width, 1);
1392         fill p_out;
1393         unfill p_in;
1394 fet_endchar;
1395
1396
1397 fet_beginchar ("Half down tihead", "d1ti");
1398         draw_ti_head (solfa_half_width, -1);
1399         fill p_out;
1400         unfill p_in;
1401 fet_endchar;
1402
1403
1404 fet_beginchar ("Quart up tihead", "u2ti");
1405         draw_ti_head (solfa_quarter_width, 1);
1406         fill p_out;
1407 fet_endchar;
1408
1409
1410 fet_beginchar ("Quart down tihead", "d2ti");
1411         draw_ti_head (solfa_quarter_width, -1);
1412         fill p_out;
1413 fet_endchar;
1414
1415
1416 fet_endgroup ("noteheads");
1417
1418
1419 %
1420 % we derive black_notehead_width# from the quarter head,
1421 % so we have to define black_notehead_width (pixel qty)
1422 % after the black_notehead_width# itself.
1423 %
1424 % Let's keep it outside the group as well.
1425 %
1426
1427 define_pixels (black_notehead_width);