Rationalize string number handling for notes and chords
[lilypond/mpolesky.git] / mf / parmesan-noteheads.mf
blob1d5e1950032cb92f84c03882fa3b9356ead00379
1 % Feta (not the Font-En-Tja) music font --  ancient note heads
2 % This file is part of LilyPond, the GNU music typesetter.
4 % Copyright (C) 2001--2010 Juergen Reuter <reuter@ipd.uka.de>
6 % Neo-mensural heads originally by
7 % Christian Mondrup and Mats Bengtsson
10 % LilyPond is free software: you can redistribute it and/or modify
11 % it under the terms of the GNU General Public License as published by
12 % the Free Software Foundation, either version 3 of the License, or
13 % (at your option) any later version.
15 % LilyPond is distributed in the hope that it will be useful,
16 % but WITHOUT ANY WARRANTY; without even the implied warranty of
17 % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 % GNU General Public License for more details.
20 % You should have received a copy of the GNU General Public License
21 % along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
23 save black_notehead_width;
24 numeric black_notehead_width;
26 fet_begingroup ("noteheads");
29 % character aligment:
31 %   The head is assumed to be vertically centered around (0, 0).
32 %   The left-most edge of the head should touch the vertical line
33 %   that goes though the point (0, 0).
35 % set_char_box() conventions:
37 % * breapth: Ignored (as far as I know).  Should be set to 0.
39 % * width: Should match the head's width.
41 % * depth: Should match the bottom edge of the head.  Affects vertical
42 %   collision handling.
44 % * height: Should match the top edge of the head.  Affects vertical
45 %   collision handling.
47 % TODO: should depth/height include appendages/stems?
49 overdone_heads = 0;
50 noteheight# := staff_space# + (1 + overdone_heads) * stafflinethickness#;
51 define_pixels (noteheight);
54 %%%%%%%%
58 % MENSURAL NOTATION
63 def draw_neomensural_brevis (expr brevwid) =
64         save beamheight, head_width;
65         save holeheight, stem_width;
66         save serif_size, serif_protrude;
68         head_width# = brevwid;
69         holeheight = 3 stafflinethickness;
70         stem_width = 1.4 stafflinethickness;
72         define_pixels (head_width);
74         set_char_box (0, head_width#,
75                       noteheight# / 2, noteheight# / 2);
77         2 beamheight + holeheight = noteheight;
78         serif_size = (holeheight - stafflinethickness) / 2;
79         serif_protrude = 1.5 serif_size;
81         z1l = (0, 0);
82         z2l = (0, -stafflinethickness / 2);
83         z3r = z2r + serif_size * (1, -1);
84         y4r = y3r;
85         x4r = head_width / 2;
86         z5l = z3l + (-serif_size, -serif_protrude);
88         penpos1 (stem_width, 0);
89         penpos2 (stem_width, 0);
90         penpos3 (beamheight, 90);
91         penpos4 (beamheight, 90);
92         penpos5 (stem_width, 180);
94         save pat_in, pat_out;
95         path pat_in, pat_out;
97         pat_out := z4l
98                    -- z3l{left}
99                    .. z5l{down}
100                    .. z5r{up}
101                    -- z1l;
102         pat_out := pat_out
103                    -- reverse pat_out yscaled -1;
104         pat_out := pat_out
105                    -- reverse pat_out shifted (-x4r, 0)
106                                       xscaled -1
107                                       shifted (x4l, 0)
108                    -- cycle;
109         fill pat_out;
111         pat_in := z4r
112                   -- z3r{left}
113                   .. z2r{up}
114                   -- z1r;
115         pat_in := pat_in
116                   -- reverse pat_in yscaled -1;
117         pat_in := pat_in
118                   -- reverse pat_in shifted (-x4r, 0)
119                                     xscaled -1
120                                     shifted (x4l, 0)
121                   -- cycle;
122         unfill pat_in;
124         penlabels (1, 2, 3, 4, 5);
125 enddef;
128 %%% This head does not seem to be used anywhere.  Junk me?  -- jr
129 def draw_neomensural_left_stemmed_head (expr wid) =
130         draw_neomensural_brevis (wid);
132         x6 = x7 = stem_width / 2;
133         y6 = y5;
134         y7 = y5 - 2.25 staff_space;
136         z17 = (x7, y7 - stem_width / 2);
138         penpos6 (stem_width, 0);
139         penpos7 (stem_width, 0);
141         fill z7l
142              -- z6l
143              -- z6r
144              -- z7r
145              .. z17
146              .. cycle;
148         penlabels (6, 7);
149         labels (17);
150 enddef;
153 %%% This head does not seem to be used anywhere.  Junk me?  -- jr
154 fet_beginchar ("Left stemmed notehead", "slneomensural");
155         draw_neomensural_left_stemmed_head (2 staff_space#);
156 fet_endchar;
160 % Some sources (eg. Musix/OpusTeX) think that the appendage should be on
161 % the left, some say right.  Right wins democratically.
163 def draw_neomensural_longa (expr wid) =
164         draw_neomensural_brevis (wid);
166         save theta;
168         x7r = head_width;
169         y7 = y5;
170         z6 - z7 = (stem_width / 2, -staff_space);
171         theta = angle (z6 - z7) + 90;
173         penpos7 (stem_width, 0);
174         penpos6 (1.2 stem_width, theta);
176         z7' = find_tangent (z6l, pat_out,
177                             (x7l + 0.5 stem_width, y7l),
178                             (x7l - 0.5 stem_width, y7l));
180         fill z7r
181              .. z6r{z6 - z7}
182              .. {z7 - z6}z6l
183              -- z7'
184              -- cycle;
186         penlabels (6, 7);
187         labels (7');
188 enddef;
192 % En wij presenteren U: de opvolgster van Emily
194 % (ze is wel breed)
196 fet_beginchar ("Neo-mensural maxima notehead", "sM3neomensural");
197         draw_neomensural_longa (2.6 staff_space#);
198 fet_endchar;
201 fet_beginchar ("Neo-mensural longa notehead", "sM2neomensural");
202         draw_neomensural_longa (2 staff_space#);
203 fet_endchar;
206 fet_beginchar ("Neo-mensural brevis notehead", "sM1neomensural");
207         draw_neomensural_brevis (2 staff_space#);
208 fet_endchar;
211 def draw_neomensural_black_head (expr wid, height) =
212         save head_width;
213         save ne, nw, ne_dist, nw_dist;
214         pair ne, nw, ne_dist, nw_dist;
216         head_width# = wid;
218         set_char_box (0, head_width#,
219                       height / 2, height / 2);
221         charwx := head_width# / 2;
222         charwy := height / 2;
224         y3 = y1 = 0;
225         x2 = x4 = (x1 + x3) / 2;
227         pickup pencircle scaled blot_diameter;
229         top y2 = h;
230         bot y4 = -d;
231         lft x1 = 0;
232         rt x3 = w;
234         ne := unitvector (z2 - z1);
235         nw_dist := (ne rotated 90) * 0.5 blot_diameter;
236         nw := unitvector (z2 - z3);
237         ne_dist := (nw rotated -90) * 0.5 blot_diameter;
239         fill lft z1{up}
240              .. (z1 + nw_dist){ne}
241              -- (z2 + nw_dist){ne}
242              .. top z2{right}
243              .. (z2 + ne_dist){-nw}
244              -- (z3 + ne_dist){-nw}
245              .. rt z3{down}
246              .. (z3 - nw_dist){-ne}
247              -- (z4 - nw_dist){-ne}
248              .. bot z4{left}
249              .. (z4 - ne_dist){nw}
250              -- (z1 - ne_dist){nw}
251              .. cycle;
253         labels (1, 2, 3, 4);
254 enddef;
257 def draw_neomensural_open_head (expr wid, height)=
258         draw_neomensural_black_head (wid, height);
260         save diamNW, diamSW;
262         diamNW = length (z2 - z1) + blot_diameter;
263         diamSW = length (z4 - z1) + blot_diameter;
265         save hole_widthNW, hole_widthSW;
267         hole_widthNW = 0.34 diamNW ;
268         hole_widthSW + 2.6 linethickness = diamSW;
270         (z7 + z5) / 2 = (w / 2, 0);
271         (z8 + z6) / 2 = (w / 2, 0);
272         z6 - z5 = hole_widthNW * unitvector (z2 - z1);
273         z7 - z6 = hole_widthSW * unitvector (z4 - z1);
275         unfill z5
276                -- z6
277                -- z7
278                -- z8
279                -- cycle;
281         labels (5, 6, 7, 8);
282 enddef;
286 % WL says the thin lines should be thinner.
288 fet_beginchar ("Harmonic notehead (Neo-mensural open)", "s0harmonic");
289         draw_neomensural_open_head (1.3 staff_space#, 1.3 noteheight#);
290         charwx := head_width#;
291         charwy := 0;
292 fet_endchar;
295 fet_beginchar ("Harmonic notehead (Neo-mensural black)", "s2harmonic");
296         draw_neomensural_black_head (1.3 staff_space#, 1.3 noteheight#);
297         charwx := head_width#;
298         charwy := 0;
299 fet_endchar;
302 fet_beginchar ("Neo-mensural semibrevis head", "s0neomensural");
303         draw_neomensural_open_head (staff_space#, noteheight#);
304 fet_endchar;
307 fet_beginchar ("Neo-mensural minima head", "s1neomensural");
308         draw_neomensural_open_head (staff_space#, noteheight#);
309 fet_endchar;
312 fet_beginchar ("Neo-mensural semiminima head", "s2neomensural");
313         draw_neomensural_black_head (staff_space#, noteheight#);
314 fet_endchar;
317 def draw_mensural_brevis (expr wid) =
318         % TODO.  For the moment, fall back to draw_neomensural_brevis.
319         draw_neomensural_brevis (wid);
320 enddef;
323 %%% This head does not seem to be used anywhere.  Junk me?  -- jr
324 def draw_mensural_left_stemmed_head (expr wid) =
325         draw_mensural_brevis (wid);
327         x6 = x7 = stem_width / 2;
328         y6 = y5;
329         y7 = y5 - 2.25 staff_space;
331         z17 = (x7, y7 - stem_width / 2);
333         penpos6 (stem_width, 0);
334         penpos7 (stem_width, 0);
336         fill z7l
337              -- z6l
338              -- z6r
339              -- z7r
340              .. z17
341              .. cycle;
343         penlabels (6, 7);
344         labels (17);
345 enddef;
348 def draw_mensural_longa (expr wid) =
349         draw_mensural_brevis (wid);
351         x6 = x7 = head_width - stem_width / 2;
352         y6 = y5;
353         y7 = y5 - 2.25 staff_space;
355         z17 = (x7, y7 - stem_width / 2);
357         penpos6 (stem_width, 0);
358         penpos7 (stem_width, 0);
360         fill z7l
361              -- z6l
362              -- z6r
363              -- z7r
364              .. z17
365              .. cycle;
367         penlabels (6, 7);
368         labels (17);
369 enddef;
372 %%% This head does not seem to be used anywhere.  Junk me?  -- jr
373 fet_beginchar ("Mensural left stemmed notehead", "slmensural");
374         draw_mensural_left_stemmed_head (staff_space#);
375 fet_endchar;
378 fet_beginchar ("Mensural maxima notehead", "sM3mensural");
379         draw_mensural_longa (2.0 staff_space#);
380 fet_endchar;
383 fet_beginchar ("Mensural longa notehead", "sM2mensural");
384         draw_mensural_longa (staff_space#);
385 fet_endchar;
388 fet_beginchar ("Mensural brevis notehead", "sM1mensural");
389         draw_mensural_brevis (staff_space#);
390 fet_endchar;
393 def draw_diamond_head (expr head_h, pen_w, pen_h, angle, open) =
394         save head_width, head_height;
395         save ellipse, ellipse_r;
396         path ellipse, ellipse_r, diamond_shape;
398         head_height# = head_h;
399         head_width# / head_height# = tand (angle);
401         set_char_box (0, head_width#,
402                       head_height# / 2, head_height# / 2);
404         charwx := head_width# / 2;
405         charwy := head_height# / 2 - linethickness#;
407         define_pixels (head_width, head_height);
409         ellipse := reverse fullcircle
410                      xscaled (max (blot_diameter, pen_w * head_width))
411                      yscaled (max (blot_diameter, pen_h * head_width))
412                      rotated -angle;
414         z1 = find_tangent_shift (((0, h) -- (0, -h)), ellipse,
415                                  (0, 0), (w / 2, 0));
416         z2 = find_tangent_shift (((0, h) -- (w, h)), ellipse,
417                                  (w / 2, h), (w / 2, 0));
418         z3 = find_tangent_shift (((w, h) -- (w, -h)), ellipse,
419                                  (w, 0), (w / 2, 0));
420         z4 = find_tangent_shift (((0, -h) -- (w, -h)), ellipse,
421                                  (w / 2, -h), (w / 2, 0));
423         diamond_shape := get_subpath (ellipse, z1 - z4, z2 - z1, z1)
424                          -- get_subpath (ellipse, z2 - z1, z3 - z2, z2)
425                          -- get_subpath (ellipse, z3 - z2, z4 - z3, z3)
426                          -- get_subpath (ellipse, z4 - z3, z1 - z4, z4)
427                          -- cycle;
428         fill diamond_shape;
430         if open:
431                 save l;
432                 path l[];
434                 l12 := (directionpoint (z1 - z2) of ellipse) shifted z1
435                         -- (directionpoint (z1 - z2) of ellipse) shifted z2;
436                 l23 := (directionpoint (z2 - z3) of ellipse) shifted z2
437                         -- (directionpoint (z2 - z3) of ellipse) shifted z3;
438                 l34 := (directionpoint (z3 - z4) of ellipse) shifted z3
439                         -- (directionpoint (z3 - z4) of ellipse) shifted z4;
440                 l41 := (directionpoint (z4 - z1) of ellipse) shifted z4
441                         -- (directionpoint (z4 - z1) of ellipse) shifted z1;
443                 unfill l12 intersectionpoint l23
444                        -- l23 intersectionpoint l34
445                        -- l34 intersectionpoint l41
446                        -- l41 intersectionpoint l12
447                        -- cycle;
448         fi;
450         labels (1, 2, 3, 4);
451 enddef;
454 fet_beginchar ("Mensural semibrevis head", "s0mensural");
455         draw_diamond_head (staff_space#, 0.15, 0.30, 30, true);
456 fet_endchar;
459 fet_beginchar ("Mensural minima head", "s1mensural");
460         draw_diamond_head (staff_space#, 0.15, 0.30, 30, true);
461 fet_endchar;
464 fet_beginchar ("Mensural semiminima head", "s2mensural");
465         draw_diamond_head (staff_space#, 0.15, 0.30, 30, false);
466 fet_endchar;
469 fet_beginchar ("Petrucci semibrevis head", "s0petrucci");
470 %       draw_diamond_head (1.8 staff_space#, 0.15, 0.40, 30, true);
471         draw_neomensural_open_head (staff_space#, 1.8 staff_space#);
472 fet_endchar;
475 fet_beginchar ("Petrucci minima head", "s1petrucci");
476 %       draw_diamond_head (1.8 staff_space#, 0.15, 0.40, 30, true);
477         draw_neomensural_open_head (staff_space#, 1.8 staff_space#);
478 fet_endchar;
481 fet_beginchar ("Petrucci semiminima head", "s2petrucci");
482 %       draw_diamond_head (1.8 staff_space#, 0.15, 0.40, 30, false);
483         draw_neomensural_black_head (staff_space#, 1.8 staff_space#);
484 fet_endchar;
487 %%%%%%%%
491 % EDITIO VATICANA (including solesmes extensions)
496 def vat_punctum_char (expr verbose_name, internal_name,
497                            linea, cavum, straight, auctum,
498                            d_up, up_shift, down_shift, mag) =
499         fet_beginchar (verbose_name, "s" & internal_name);
500                 save a_b, b_h, a_w;
502                 a_b := 1.54; % b_h * a_b / a_w = wd / ht
503                 b_h := 0.85;
504                 a_w := 1.09;
506                 save a, beta, ht, wd;
508                 ht# = noteheight# * mag;
509                 2 beta = ht# * b_h;
510                 a = beta * a_b;
511                 wd# = 2 a / a_w;
512                 black_notehead_width# := wd#;
514                 % direction
515                 save d_, d_sign;
516                 pair d_;
518                 if d_up:
519                         d_ := up;
520                         d_sign := 1;
521                 else:
522                         d_ := down;
523                         d_sign := -1;
524                 fi;
526                 % convexity and eccentricity
527                 save u_convexity, u_eccentricity;
529                 if straight:
530                         u_convexity# := -0.01 ht#;
531                         u_eccentricity# := 0.0 ht#; % dummy
532                 elseif auctum:
533                         u_convexity# := -0.03 ht#;
534                         u_eccentricity# := +0.25 ht#;
535                 else:
536                         u_convexity# := -0.05 ht#;
537                         u_eccentricity# := 0.0 ht#; % dummy
538                 fi;
540                 save convexity, eccentricity;
542                 convexity# := d_sign * u_convexity#;
543                 eccentricity# := d_sign * u_eccentricity#;
545                 % y shift offset
546                 save yoffs;
548                 if up_shift:
549                         yoffs# := 0.08 ht#;
550                 elseif down_shift:
551                         yoffs# := -0.11 ht#;
552                 else:
553                         yoffs# := 0.00 ht#;
554                 fi;
556                 define_pixels (convexity, eccentricity, yoffs, ht, wd);
558                 pickup pencircle scaled linethickness;
560                 save height, yoffs_bt, p, circle, circle_r;
561                 path p, circle, circle_r;
563                 height# = 0.47 ht#;
564                 yoffs_bt# = yoffs# - 0.5 height# - 0.25 convexity#;
566                 define_pixels (height, yoffs_bt);
568                 circle := fullcircle scaled linethickness;
570                 x1 = x6;
571                 x2 = x5;
572                 x3 = x4;
573                 y1 + height = y6;
574                 y2 + height = y5;
575                 y3 + height = y4;
577                 save box_top, box_bt;
579                 if auctum:
580                         z1 = (0.00 wd + linethickness / 2, yoffs_bt);
581                         z2 = (0.21 wd, yoffs_bt + convexity);
582                         z3 = (0.42 wd - linethickness/ 2,
583                               yoffs_bt + eccentricity);
584                         box_top# = height# + yoffs_bt# +
585                                      max (0, convexity#, eccentricity#);
586                         box_bt# = yoffs_bt# +
587                                      min (0, convexity#, eccentricity#);
588                         p = z1
589                             .. {right}z2
590                             .. {d_}z3
591                             -- z4{-d_}
592                             .. z5{left}
593                             .. z6
594                             -- cycle;
595                 else:
596                         z1 = (0.00 wd + linethickness / 2, yoffs_bt);
597                         z2 = (0.21 wd, yoffs_bt + convexity);
598                         z3 = (0.42 wd - linethickness / 2, yoffs_bt);
599                         box_top# = height# + yoffs_bt# + max (0, convexity#);
600                         box_bt# = yoffs_bt# + min (0, convexity#);
601                         p = z1
602                             .. z2
603                             .. z3
604                             -- z4
605                             .. z5
606                             .. z6
607                             -- cycle;
608                 fi;
610                 labels (1, 2, 3, 4, 5, 6);
612                 save dirs;
613                 pair dirs[];
615                 dirs12 := direction (0 + epsilon) of p;
616                 dirs2 := direction 1 of p;
617                 dirs32 := direction (2 - epsilon) of p;
618                 dirs45 := direction (3 + epsilon) of p;
619                 dirs5 := direction 4 of p;
620                 dirs65 := direction (5 - epsilon) of p;
622                 fill get_subpath (circle, down, dirs12, z1)
623                      .. (bot z2){dirs2}
624                      .. get_subpath (circle, dirs32, up, z3)
625                      -- get_subpath (circle, up, dirs45, z4)
626                      .. (top z5){dirs5}
627                      .. get_subpath (circle, dirs65, down, z6)
628                      -- cycle;
630                 if cavum:
631                         save pat, t;
632                         path pat[];
633                         numeric t[];
635                         pat123 := ((directionpoint -dirs12 of circle)
636                                     shifted z1){dirs12}
637                                   .. (top z2){dirs2}
638                                   .. {dirs32}((directionpoint -dirs32 of circle)
639                                        shifted z3);
640                         pat34 := lft z3
641                                  -- lft z4;
642                         pat456 := ((directionpoint -dirs45 of circle)
643                                     shifted z4){dirs45}
644                                   .. (bot z5){dirs5}
645                                   .. {dirs65}((directionpoint -dirs65 of circle)
646                                        shifted z6);
647                         pat61 := rt z6
648                                  -- rt z1;
650                         t61 := ypart (pat61 intersectiontimes pat123);
651                         t12 := xpart (pat123 intersectiontimes pat34);
652                         t34 := ypart (pat34 intersectiontimes pat456);
653                         t45 := xpart (pat456 intersectiontimes pat61);
655                         unfill subpath (t61, t12) of pat123
656                                -- subpath (t34, t45) of pat456
657                                -- cycle;
658                 fi;
660                 set_char_box (0.00 wd#, 0.42 wd#,
661                               max (0, -box_bt#) + linethickness# / 2,
662                               max (0, box_top#) + linethickness# / 2);
664                 if linea:
665                         save linea_width, linea_height;
667                         linea_width# = 0.6 linethickness#;
668                         linea_height# = 0.7 ht#;
670                         define_pixels (linea_width, linea_height);
672                         pickup pencircle scaled 0.6 linethickness;
674                         draw_rounded_block ((-0.10 wd - linea_width / 2,
675                                              -linea_height / 2),
676                                             (-0.10 wd + linea_width / 2,
677                                              +linea_height / 2),
678                                             0.6 linethickness);
679                         draw_rounded_block ((+0.52 wd - linea_width / 2,
680                                              -linea_height / 2),
681                                             (+0.52 wd + linea_width / 2,
682                                              +linea_height / 2),
683                                             0.6 linethickness);
685                         set_char_box (0, 0.62 wd# + linea_width#,
686                                       linea_height# / 2,
687                                       linea_height# / 2);
689                         currentpicture := currentpicture
690                                 shifted (0.10 wd + linea_width / 2, 0);
691                 fi;
692         fet_endchar;
693 enddef;
696 def plica_char (expr verbose_name, internal_name,
697                      d_up, mag) =
698         fet_beginchar (verbose_name, "s" & internal_name);
699                 save a_b, b_h, a_w;
701                 a_b := 1.54; % b_h * a_b / a_w = wd / ht
702                 b_h := 0.85;
703                 a_w := 1.09;
705                 save a, beta, ht, wd;
707                 ht# = noteheight# * mag;
708                 2 beta = ht# * b_h;
709                 a = beta * a_b;
710                 wd# = 2 a / a_w;
711                 black_notehead_width# := wd#;
713                 % direction
714                 save d_, d_sign;
715                 pair d_;
717                 if d_up:
718                         d_ := up;
719                         d_sign := 1;
720                 else:
721                         d_ := down;
722                         d_sign := -1;
723                 fi;
725                 % convexity and eccentricity
726                 save convexity, eccentricity;
728                 convexity# := d_sign * -0.10 ht#;
729                 eccentricity# := d_sign * -0.12 ht#;
731                 % y shift offset
732                 save yoffs;
734                 yoffs# := -0.11 ht#;
736                 define_pixels (convexity, eccentricity, yoffs, ht, wd);
738                 pickup pencircle scaled linethickness;
740                 save height, yoffs_bt, p, circle, circle_r;
741                 path p, circle, circle_r;
743                 height# = 0.47 ht#;
744                 yoffs_bt# = yoffs# - 0.5 height# - 0.25 convexity#;
746                 define_pixels (height, yoffs_bt);
748                 circle := fullcircle scaled linethickness;
750                 x1 = x6;
751                 x2 = x5;
752                 x3 = x4;
753                 y1 + height = y6;
754                 y2 + height = y5;
755                 y3 + height = y4;
757                 save box_top, box_bt;
759                 z1 = (0.00 wd + linethickness / 2, yoffs_bt);
760                 z2 = (0.21 wd, yoffs_bt + convexity);
761                 z3 = (0.42 wd - linethickness/ 2, yoffs_bt + eccentricity);
762                 box_top# = height# + yoffs_bt# +
763                              max (0, convexity#, eccentricity#);
764                 box_bt# = yoffs_bt# +
765                              min (0, convexity#, eccentricity#);
766                 p = z1
767                     .. z2{right}
768                     .. z3
769                     -- z4
770                     .. z5{left}
771                     .. z6
772                     -- cycle;
774                 labels (1, 2, 3, 4, 5, 6);
776                 save dirs;
777                 pair dirs[];
779                 dirs12 := direction (0 + epsilon) of p;
780                 dirs2 := direction 1 of p;
781                 dirs32 := direction (2 - epsilon) of p;
782                 dirs45 := direction (3 + epsilon) of p;
783                 dirs5 := direction 4 of p;
784                 dirs65 := direction (5 - epsilon) of p;
786                 fill get_subpath (circle, down, dirs12, z1)
787                      .. (bot z2){dirs2}
788                      .. get_subpath (circle, dirs32, up, z3)
789                      -- get_subpath (circle, up, dirs45, z4)
790                      .. (top z5){dirs5}
791                      .. get_subpath (circle, dirs65, down, z6)
792                      -- cycle;
794                 pickup pencircle scaled 0.6 linethickness;
796                 save stem_bt;
798                 set_char_box (0.00 wd#, 0.42 wd#,
799                               max (0, -box_bt#) + linethickness# / 2,
800                               max (0, box_top#) + linethickness# / 2);
802         fet_endchar;
803 enddef;
806 def epiphonus_char (expr verbose_name, internal_name,
807                          left_stem, d_up, down_shift, mag) =
808         fet_beginchar (verbose_name, "s" & internal_name);
809                 save a_b, b_h, a_w;
811                 a_b := 1.54; % b_h * a_b / a_w = wd / ht
812                 b_h := 0.85;
813                 a_w := 1.09;
815                 save a, beta, ht, wd;
817                 ht# = noteheight# * mag;
818                 2 beta = ht# * b_h;
819                 a = beta * a_b;
820                 wd# = 2 a / a_w;
821                 black_notehead_width# := wd#;
823                 % direction
824                 save d_, d_sign;
825                 pair d_;
827                 if d_up:
828                         d_ := up;
829                         d_sign := 1;
830                 else:
831                         d_ := down;
832                         d_sign := -1;
833                 fi;
835                 % convexity and eccentricity
836                 save convexity;
838                 convexity# := d_sign * -0.05ht#;
840                 % y shift offset
841                 save yoffs;
843                 if down_shift:
844                         yoffs# := -0.11 ht#;
845                 else:
846                         yoffs# := 0.00 ht#;
847                 fi;
849                 define_pixels (convexity, yoffs, ht, wd);
851                 pickup pencircle scaled linethickness;
853                 save height, yoffs_bt, p, circle, circle_r;
854                 path p, circle, circle_r;
856                 height# = 0.47 ht#;
857                 yoffs_bt# = yoffs# - 0.5 height# - 0.25 convexity#;
859                 define_pixels (height, yoffs_bt);
861                 circle := fullcircle scaled linethickness;
863                 x1 = x6;
864                 x2 = x5;
865                 x3 = x4;
866                 y1 + height = y6;
867                 y2 + height = y5;
868                 y3 + height = y4;
870                 save box_top, box_bt;
872                 z1 = (0.00 wd + linethickness / 2, yoffs_bt - 2.5 convexity);
873                 z2 = (0.06 wd, yoffs_bt + 1.4 convexity);
874                 z3 = (0.42 wd - linethickness / 2, yoffs_bt - 1.0 convexity);
875                 box_top# = height# + yoffs_bt# +
876                              max (-1.0 convexity#, 1.4 convexity#, 0);
877                 box_bt# = yoffs_bt# +
878                              min (-1.0 convexity#, 1.4 convexity#, 0);
879                 p = z1{-d_}
880                     .. {curl 1}z2{right}
881                     .. z3
882                     -- z4
883                     .. {left}z5{curl 1}
884                     .. {d_}z6
885                     -- cycle;
887                 labels (1, 2, 3, 4, 5, 6);
889                 save dirs;
890                 pair dirs[];
892                 dirs12 := direction (0 + epsilon) of p;
893                 dirs21 := direction (1 - epsilon) of p;
894                 dirs23 := direction (1 + epsilon) of p;
895                 dirs32 := direction (2 - epsilon) of p;
896                 dirs45 := direction (3 + epsilon) of p;
897                 dirs54 := direction (4 - epsilon) of p;
898                 dirs56 := direction (4 + epsilon) of p;
899                 dirs65 := direction (5 - epsilon) of p;
901                 fill get_subpath (circle, down, dirs12, z1)
902                      .. get_subpath (circle, dirs21, dirs23, z2)
903                      .. get_subpath (circle, dirs32, up, z3)
904                      -- get_subpath (circle, up, dirs45, z4)
905                      .. get_subpath (circle, dirs54, dirs56, z5)
906                      .. get_subpath (circle, dirs65, down, z6)
907                      -- cycle;
909                 save stem_bt;
911                 if left_stem:
912                         pickup pencircle scaled 0.6 linethickness;
914                         lft x11 = x1 - linethickness / 2;
915                         bot y11 = yoffs - 1.1 ht - linethickness / 2;
916                         x12 = x11;
917                         y12 = y1;
919                         draw_rounded_block (bot lft z11, top rt z12,
920                                             0.6 linethickness);
921                         stem_bt# = yoffs# - 1.1 ht#;
923                         labels (11, 12);
924                 else:
925                         stem_bt# = 0;
926                 fi;
928                 set_char_box (0.00 wd#, 0.42 wd#,
929                               max (0, -box_bt#, -stem_bt#) + linethickness# / 2,
930                               max (0, box_top#) + linethickness# / 2);
931         fet_endchar;
932 enddef;
935 def inclinatum_char (expr verbose_name, internal_name,
936                           small, stropha, auctum) =
937         fet_beginchar (verbose_name, "s" & internal_name);
938                 save ht, alpha;
940                 alpha := 35;
942                 if small:
943                         ht# = 0.50 noteheight#;
944                 else:
945                         ht# = 0.80 noteheight#;
946                 fi;
948                 draw_diamond_head (ht#, 0, 0, alpha, false);
950                 save off_angle;
952                 off_angle := alpha + 15;
954                 save stropha_ellipse, auctum_hook, circle;
955                 path stropha_ellipse, auctum_hook, circle;
957                 circle := reverse fullcircle scaled linethickness;
959                 stropha_ellipse := fullcircle xscaled 0.25 head_height
960                                               yscaled 0.55 head_height
961                                               rotated alpha;
963                 z11 = z12
964                       + linethickness / 2 * dir (180 - off_angle)
965                       - directionpoint dir (90 - off_angle)
966                           of stropha_ellipse;
967                 z12 = directionpoint -dir (90 - off_angle) of diamond_shape +
968                         linethickness / 2 * dir (180 - off_angle);
969                 z13 = (0, -0.5 head_height + linethickness);
971                 auctum_hook := z12{-dir (90 - off_angle)}
972                                .. {dir (90 + alpha)}z13;
974                 labels (12);
976                 if (stropha and not auctum):
977                         clearit;
979                         save t_in, t_out;
981                         t_in := xpart ((stropha_ellipse shifted z11)
982                                        intersectiontimes
983                                        get_subpath (diamond_shape,
984                                                     left, up,
985                                                     (0, 0)));
986                         t_out := xpart ((stropha_ellipse shifted z11)
987                                         intersectiontimes
988                                         get_subpath (diamond_shape,
989                                                      up, right,
990                                                      (0, 0)));
992                         % the addition or subtraction of `1' is necessary
993                         % so that we get the right starting point
994                         fill get_subpath_i (diamond_shape,
995                                             dir (angle (z2 - z1) - 1),
996                                             dir (angle (z1 - z4) + 1),
997                                             (0, 0))
998                              -- get_subpath (stropha_ellipse,
999                                              direction t_in of stropha_ellipse,
1000                                              direction t_out of stropha_ellipse,
1001                                              z11)
1002                              -- cycle;
1004                         labels (11);
1005                 fi;
1007                 if (auctum and not stropha):
1008                         clearit;
1010                         fill get_subpath (diamond_shape,
1011                                           left,
1012                                           -dir (90 - off_angle),
1013                                           (0, 0))
1014                              .. get_subpath (circle,
1015                                              dir (90 + alpha),
1016                                              -dir (90 + alpha),
1017                                              z13)
1018                              .. get_subpath (circle,
1019                                              dir (90 - off_angle),
1020                                              right,
1021                                              z12)
1022                              -- cycle;
1024                         labels (13);
1025                 fi;
1027                 if (auctum and stropha):
1028                         clearit;
1030                         save t;
1032                         t := xpart ((stropha_ellipse shifted z11)
1033                                     intersectiontimes
1034                                     get_subpath (diamond_shape, up, right,
1035                                                  (0, 0)));
1037                         % the addition or subtraction of `1' is necessary
1038                         % so that we get the right starting point
1039                         fill get_subpath_i (diamond_shape,
1040                                             dir (angle (z2 - z1) - 1),
1041                                             -dir (90 - off_angle),
1042                                             (0, 0))
1043                              .. get_subpath (circle,
1044                                              dir (90 + alpha),
1045                                              -dir (90 + alpha),
1046                                              z13)
1047                              .. get_subpath (stropha_ellipse,
1048                                              dir (90 - off_angle),
1049                                              direction t of stropha_ellipse,
1050                                              z11)
1051                              -- cycle;
1053                         labels (11, 13);
1054                 fi;
1055         fet_endchar;
1056 enddef;
1059 % punctum
1060 vat_punctum_char ("Ed. Vat. punctum", "vaticana.punctum",
1061                   false, false, false, false,
1062                   false, false, false, 1.0);
1065 % punctum cavum (for OpusTeX compatibility)
1066 vat_punctum_char ("Ed. Vat. punctum cavum", "vaticana.punctum.cavum",
1067                   false, true, false, false,
1068                   false, false, false, 1.0);
1071 % linea punctum (for OpusTeX compatibility)
1072 vat_punctum_char ("Ed. Vat. linea punctum", "vaticana.linea.punctum",
1073                   true, false, false, false,
1074                   false, false, false, 1.0);
1077 % linea punctum cavum (for OpusTeX compatibility)
1078 vat_punctum_char ("Ed. Vat. linea punctum cavum", "vaticana.linea.punctum.cavum",
1079                   true, true, false, false,
1080                   false, false, false, 1.0);
1083 % punctum inclinatum
1084 inclinatum_char ("Ed. Vat. inclinatum", "vaticana.inclinatum",
1085                  false, false, false);
1088 % pes lower punctum
1089 vat_punctum_char ("Ed. Vat. pes lower punctum", "vaticana.lpes",
1090                   false, false, true, false,
1091                   true, false, false, 1.0);
1094 % pes lower punctum
1095 vat_punctum_char ("Ed. Vat. pes var lower punctum", "vaticana.vlpes",
1096                   false, false, true, false,
1097                   true, false, true, 1.0);
1100 % pes upper punctum
1101 vat_punctum_char ("Ed. Vat. pes upper punctum", "vaticana.upes",
1102                   false, false, true, false,
1103                   false, false, false, 1.0);
1106 % pes upper punctum (shifted variation)
1108 % This note head is used instead of the regular pes upper punctum to
1109 % avoid collision with the lower punctum note of the pes when the upper
1110 % punctum sits directly on top of the lower punctum.
1112 vat_punctum_char ("Ed. Vat. var pes upper punctum", "vaticana.vupes",
1113                   false, false, true, false,
1114                   false, true, false, 1.0);
1117 % small punctum as used in epiphonus
1118 vat_punctum_char ("Ed. Vat. plica", "vaticana.plica",
1119                   false, false, false, false,
1120                   false, false, false, 0.6);
1123 % small punctum as used in epiphonus
1124 plica_char ("Ed. Vat. var plica", "vaticana.vplica",
1125             false, 0.6);
1128 % eccentric punctum as used in epiphonus
1129 epiphonus_char ("Ed. Vat. epiphonus", "vaticana.epiphonus",
1130                 false, true, false, 1.0);
1133 % eccentric punctum as used in epiphonus (shifted variation)
1135 % This note head is used instead of the regular epiphonus punctum to
1136 % avoid collision with the plica head when the plica sits directly on
1137 % top of the lower head.
1139 epiphonus_char ("Ed. Vat. var epiphonus", "vaticana.vepiphonus",
1140                 false, true, true, 1.0);
1143 % small punctum as used in cephalicus
1144 vat_punctum_char ("Ed. Vat. rev. plica", "vaticana.reverse.plica",
1145                   false, false, false, false,
1146                   true, false, false, 0.6);
1149 % small punctum as used in cephalicus
1150 plica_char ("Ed. Vat. rev. var plica", "vaticana.reverse.vplica",
1151             true, 0.6);
1154 % eccentric punctum as used in cephalicus; without left stem
1155 epiphonus_char ("Ed. Vat. inner cephalicus", "vaticana.inner.cephalicus",
1156                 false, false, false, 1.0);
1159 % eccentric punctum as used in cephalicus; with left stem
1160 epiphonus_char ("Ed. Vat. cephalicus", "vaticana.cephalicus",
1161                 true, false, false, 1.0);
1164 % quilisma
1165 fet_beginchar ("Ed. Vat. quilisma", "svaticana.quilisma");
1166         save a_b, b_h, a_w;
1168         a_b := 1.54; % b_h * a_b / a_w = wd / ht
1169         b_h := 0.85;
1170         a_w := 1.09;
1172         save a, beta, ht, wd;
1174         ht# = noteheight#;
1175         2 beta = ht# * b_h;
1176         a = beta * a_b;
1177         wd# = 2 a / a_w;
1179         set_char_box (0, 0.42 wd#, 0.28 ht#, 0.36 ht#);
1181         black_notehead_width# := wd#;
1183         define_pixels (ht, wd);
1185         save ellipse, T;
1186         path ellipse;
1187         transform T;
1189         T := identity xscaled linethickness
1190                       yscaled 0.44 ht;
1191         pickup pencircle transformed T;
1192         ellipse := reverse fullcircle transformed T;
1194         z1 = (rt 0.00 wd, top -0.28 ht);
1195         z2 = (0.11 wd, -0.14 ht);
1196         z3 = (0.12 wd, +0.03 ht);
1197         z4 = (0.25 wd, -0.09 ht);
1198         z5 = (0.25 wd, +0.08 ht);
1199         z6 = (lft 0.42 wd, -0.04 ht);
1200         z7 = (lft 0.40 wd, bot +0.36 ht);
1202         fill get_subpath (ellipse, z1 - z2, z2 - z1, z1)
1203              -- get_subpath (ellipse, z2 - z1, z1 - z2, z2)
1204              -- cycle;
1205         fill get_subpath (ellipse, z3 - z4, z4 - z3, z3)
1206              -- get_subpath (ellipse, z4 - z3, z3 - z4, z4)
1207              -- cycle;
1208         fill get_subpath (ellipse, z5 - z6, z6 - z5, z5)
1209              -- point 0 of get_subpath (ellipse, z6 - z5, z5 - z6, z6)
1210              -- get_subpath (ellipse, z7 - z6, z6 - z7, z7)
1211              -- get_subpath (ellipse, z6 - z7, z5 - z6, z6)
1212              -- cycle;
1214         labels (1, 2, 3, 4, 5, 6, 7);
1215 fet_endchar;
1218 % solesmes punctum inclinatum parvum
1219 inclinatum_char ("Solesmes punctum inclinatum parvum", "solesmes.incl.parvum",
1220                  true, false, false);
1223 % solesmes punctum auctum ascendens
1224 vat_punctum_char ("Solesmes punctum auctum ascendens", "solesmes.auct.asc",
1225                   false, false, false, true,
1226                   true, false, false, 1.0);
1229 % solesmes punctum auctum descendens
1230 vat_punctum_char ("Solesmes punctum auctum descendens", "solesmes.auct.desc",
1231                   false, false, false, true,
1232                   false, false, false, 1.0);
1235 % solesmes punctum inclinatum auctum
1236 inclinatum_char ("Solesmes punctum incl. auctum", "solesmes.incl.auctum",
1237                  false, false, true);
1240 % solesmes stropha
1241 inclinatum_char ("Solesmes stropha", "solesmes.stropha",
1242                  false, true, false);
1245 % solesmes stropha aucta
1246 inclinatum_char ("Solesmes stropha aucta", "solesmes.stropha.aucta",
1247                  false, true, true);
1250 % solesmes oriscus
1251 fet_beginchar ("Solesmes oriscus", "ssolesmes.oriscus");
1252         save a_b, b_h, a_w;
1254         a_b := 1.54; % b_h * a_b / a_w = wd / ht
1255         b_h := 0.85;
1256         a_w := 1.09;
1258         save a, beta, ht, wd;
1260         ht# = noteheight#;
1261         2 beta = ht# * b_h;
1262         a = beta * a_b;
1263         wd# = 2 a / a_w;
1264         black_notehead_width# := wd#;
1266         save convexity;
1268         convexity# = +0.05 ht#;
1270         define_pixels (ht, wd, convexity);
1272         set_char_box (0.00 wd#, 0.50 wd#,
1273                       0.25 ht# + convexity#, 0.25 ht# + convexity#);
1275         z1 = (0.00 wd + blot_diameter / 2, -convexity);
1276         z2 = (1/6 wd, +convexity);
1277         z3 = (2/6 wd, -convexity);
1278         z4 = (0.50 wd - blot_diameter / 2, +convexity);
1281         save height;
1283         height = 2 ypart (directionpoint right of (z1
1284                                                    .. z2
1285                                                    .. z3
1286                                                    .. z4));
1288         save ellipse, T;
1289         path ellipse;
1290         transform T;
1292         T := identity xscaled blot_diameter
1293                       yscaled (h + d - height);
1294         pickup pencircle transformed T;
1295         ellipse := fullcircle transformed T;
1297         % Adjust vertical coordinates to touch bounding box.
1298         y1 := top -d;
1299         y4 := bot h;
1301         save d_;
1302         pair d_;
1304         d_ := direction 0 of (z1
1305                               .. z2
1306                               .. z3
1307                               .. z4);
1309         fill get_subpath (ellipse, -d_, d_, z1)
1310              .. bot z2
1311              .. bot z3
1312              .. get_subpath (ellipse, d_, -d_, z4)
1313              .. top z3
1314              .. top z2
1315              .. cycle;
1317         labels (1, 2, 3, 4);
1318 fet_endchar;
1321 %%%%%%%%
1325 % EDITIO MEDICAEA
1330 % inclinatum
1331 fet_beginchar ("Ed. Med. inclinatum", "smedicaea.inclinatum");
1332         draw_diamond_head (1.2 staff_space#, 0, 0, 35, false);
1333 fet_endchar;
1336 def med_punctum_char (expr verbose_name, internal_name,
1337                            left_up_stem, left_down_stem) =
1338         fet_beginchar (verbose_name, "s" & internal_name);
1339                 save a, ht, wd;
1341                 ht# = 2 staff_space#;
1342                 wd# = ht#;
1343                 black_notehead_width# := wd#;
1345                 define_pixels (ht, wd);
1347                 save ellipse;
1348                 path ellipse;
1350                 ellipse := fullcircle xscaled blot_diameter
1351                                       yscaled 0.50 ht;
1353                 z1 = (0.00 wd + blot_diameter / 2, 0);
1354                 z2 = (0.4 wd - blot_diameter / 2, 0);
1356                 labels (1, 2);
1358                 pickup pencircle scaled linethickness;
1360                 if left_down_stem:
1361                         z4 = (0.00 wd + linethickness / 2, -1.25 ht);
1363                         fill get_subpath (ellipse, left, down, z1)
1364                              -- top lft z4{down}
1365                              .. z4{right}
1366                              .. top rt z4{up}
1367                              -- (rt x4, -.5 ht / 2)
1368                              -- get_subpath (ellipse, right, left, z2)
1369                              -- cycle;
1371                         labels (4);
1373                         set_char_box (0.0, 0.4 wd#, 1.25 ht#, 0.25 ht#);
1374                 elseif left_up_stem:
1375                         z4 = (0.00 wd + linethickness / 2, +1.25 ht);
1377                         fill get_subpath (ellipse, down, right, z1)
1378                              -- get_subpath (ellipse, right, left, z2)
1379                              -- (rt x4, .5 ht / 2)
1380                              -- bot rt z4{up}
1381                              .. z4{left}
1382                              .. bot lft z4{down}
1383                              -- cycle;
1385                         labels (4);
1387                         set_char_box (0.0, 0.4 wd#, 0.25 ht#, 1.25 ht#);
1388                 else:
1389                         fill get_subpath (ellipse, left, right, z1)
1390                              -- get_subpath (ellipse, right, left, z2)
1391                              -- cycle;
1393                         set_char_box (0.0, 0.4 wd#, 0.25 ht#, 0.25 ht#);
1394                 fi;
1396         fet_endchar;
1397 enddef;
1400 % punctum
1401 med_punctum_char ("Ed. Med. punctum", "medicaea.punctum",
1402                   false, false);
1405 % left up-stemmed punctum
1406 med_punctum_char ("Ed. Med. reverse virga", "medicaea.rvirga",
1407                   true, false);
1410 % virga (i.e. left down-stemmed punctum)
1411 med_punctum_char ("Ed. Med. virga", "medicaea.virga",
1412                   false, true);
1415 %%%%%%%%
1419 % HUFNAGEL
1424 def huf_punctum_char (expr verbose_name, internal_name,
1425                            down_stem) =
1426         fet_beginchar (verbose_name, "s" & internal_name);
1427                 save alpha;
1429                 alpha = 55;
1431                 draw_diamond_head (staff_space#, 0, 0, alpha, false);
1433                 if down_stem:
1434                         set_char_box (0, head_width#,
1435                                       1.5 staff_space#, head_height# / 2);
1437                         save ellipse;
1438                         path ellipse;
1440                         ellipse := reverse fullcircle xscaled blot_diameter
1441                                                       yscaled 0.7 staff_space
1442                                                       rotated -alpha;
1444                         z11 = (head_width / 2, 0);
1445                         z12 = find_tangent_shift (((0, -d) -- (w, -d)), ellipse,
1446                                                   (w / 2, -d), (w / 2, 0));
1448                         fill get_subpath (ellipse, up, down, z11)
1449                              -- get_subpath (ellipse, down, up, z12)
1450                              -- cycle;
1452                         labels (11, 12);
1453                 fi;
1454         fet_endchar;
1455 enddef;
1458 % punctum
1459 huf_punctum_char ("Hufnagel punctum", "hufnagel.punctum", false)
1462 % virga
1463 huf_punctum_char ("Hufnagel virga", "hufnagel.virga", true)
1466 % pes lower punctum
1467 fet_beginchar ("Hufnagel pes lower punctum", "shufnagel.lpes")
1468         save width, height, alpha;
1470         width# = 2 * staff_space#;
1471         height# = 0.7 * staff_space#;
1472         alpha = 35;
1474         set_char_box (0, width#, height# / 2, height# / 2);
1476         define_pixels (width, height);
1478         save circle;
1479         path circle;
1481         circle := reverse fullcircle scaled linethickness;
1483         pickup pencircle scaled linethickness;
1485         rt x3 = -lft x1 = width / 2;
1486         y2 = y3 = height / 2;
1487         y1 = y4 = -height / 2;
1489         tand (alpha) * (y2 - y1) = x2 - x1 = x3 - x4;
1491         fill get_subpath (circle, left, z2 - z1, z1)
1492              -- get_subpath (circle, z2 - z1, right, z2)
1493              -- get_subpath (circle, right, z4 - z3, z3)
1494              -- get_subpath (circle, z4 - z3, left, z4)
1495              -- cycle;
1497         currentpicture := currentpicture shifted (width/2, 0);
1499 %       labels (1, 2, 3, 4);
1500 fet_endchar;
1503 fet_endgroup ("noteheads");