]> git.donarmstrong.com Git - lilypond.git/blob - mf/parmesan-heads.mf
Merge branch 'master' of ssh+git://git.sv.gnu.org/srv/git/lilypond
[lilypond.git] / mf / parmesan-heads.mf
1 % -%-Fundamental-%- -*-Metafont-*-
2 % parmesan-heads.mf -- implement ancient note heads
3
4 % source file of LilyPond's pretty-but-neat music font
5
6 % (c) 2001--2006 Juergen Reuter <reuter@ipd.uka.de>
7
8 % Neo-mensural heads originally by
9 % Christian Mondrup and Mats Bengtsson
10
11
12 save black_notehead_width;
13 numeric black_notehead_width;
14
15 fet_begingroup ("noteheads")
16
17 %
18 % character aligment:
19 %
20 %   The head is assumed to be vertically centered around (0, 0).
21 %   The left-most edge of the head should touch the vertical line
22 %   that goes though the point (0, 0).
23 %
24 % set_char_box() conventions:
25 %
26 % * breapth: Ignored (as far as I know).  Should be set to 0.
27 %
28 % * width: Should match the head's width.
29 %
30 % * depth: Should match the bottom edge of the head.  Affects vertical
31 %   collision handling.
32 %
33 % * height: Should match the top edge of the head.  Affects vertical
34 %   collision handling.
35 %
36 % TODO: should depth/height include appendages/stems?
37
38 overdone_heads = 0;
39 noteheight# := staff_space# + (1 + overdone_heads) * stafflinethickness#;
40 define_pixels (noteheight);
41
42
43 %%%%%%%%
44 %
45 %
46 %
47 % MENSURAL NOTATION
48 %
49 %
50 %
51
52 def draw_neomensural_brevis (expr brevwid) =
53         save beamheight, head_width;
54         save holeheight, stem_width;
55         save serif_size, serif_protrude;
56
57         head_width# = brevwid;
58         holeheight = 3 stafflinethickness;
59         stem_width = 1.4 stafflinethickness;
60
61         define_pixels (head_width);
62
63         set_char_box (0, head_width#,
64                       noteheight# / 2, noteheight# / 2);
65         
66         2 beamheight + holeheight = noteheight;
67         serif_size = (holeheight - stafflinethickness) / 2;
68         serif_protrude = 1.5 serif_size;
69
70         z1l = (0, 0);
71         z2l = (0, -stafflinethickness / 2);
72         z3r = z2r + serif_size * (1, -1);
73         y4r = y3r;
74         x4r = head_width / 2;
75         z5l = z3l + (-serif_size, -serif_protrude);
76
77         penpos1 (stem_width, 0);
78         penpos2 (stem_width, 0);
79         penpos3 (beamheight, 90);
80         penpos4 (beamheight, 90);
81         penpos5 (stem_width, 180);
82
83         save pat_in, pat_out;
84         path pat_in, pat_out;
85
86         pat_out := z4l
87                    -- z3l{left}
88                    .. z5l{down}
89                    .. z5r{up}
90                    -- z1l;
91         pat_out := pat_out
92                    -- reverse pat_out yscaled -1;
93         pat_out := pat_out
94                    -- reverse pat_out shifted (-x4r, 0)
95                                       xscaled -1
96                                       shifted (x4l, 0)
97                    -- cycle;
98         fill pat_out;
99
100         pat_in := z4r
101                   -- z3r{left}
102                   .. z2r{up}
103                   -- z1r;
104         pat_in := pat_in
105                   -- reverse pat_in yscaled -1;
106         pat_in := pat_in
107                   -- reverse pat_in shifted (-x4r, 0)
108                                     xscaled -1
109                                     shifted (x4l, 0)
110                   -- cycle;
111         unfill pat_in;
112
113         penlabels (1, 2, 3, 4, 5);
114 enddef;
115
116
117 %%% This head does not seem to be used anywhere.  Junk me?  -- jr
118 def draw_neomensural_left_stemmed_head (expr wid) =
119         draw_neomensural_brevis (wid);
120
121         x6 = x7 = stem_width / 2;
122         y6 = y5;
123         y7 = y5 - 2.25 staff_space;
124
125         z17 = (x7, y7 - stem_width / 2);
126
127         penpos6 (stem_width, 0);
128         penpos7 (stem_width, 0);
129
130         fill z7l
131              -- z6l
132              -- z6r
133              -- z7r
134              .. z17
135              .. cycle;
136
137         penlabels (6, 7);
138         labels (17);
139 enddef;
140
141
142 %%% This head does not seem to be used anywhere.  Junk me?  -- jr
143 fet_beginchar ("Left stemmed notehead", "slneomensural");
144         draw_neomensural_left_stemmed_head (2 staff_space#);
145 fet_endchar;
146
147
148 %
149 % Find point on `curve' which gives the tangent between point `p'
150 % and `curve'.  To guide the search, two auxiliary points must be
151 % specified, `p_in' and `p_out'.  The line between `p' and `p_in'
152 % must intersect `curve', while the line between `p' and `p_out'
153 % must not.
154 %
155 def find_tangent (expr p, curve, p_in, p_out) =
156         begingroup;
157         save mid, t, t_good, in, out;
158         pair mid, in, out;
159
160         in := p_in;
161         out := p_out;
162
163         forever:
164                 mid := 0.5 [in, out];
165                 exitif abs (out - mid) <= eps;
166                 t := xpart (curve intersectiontimes (p -- mid));
167                 if (t > 0):
168                         in := mid;
169                         t_good := t;
170                 else:
171                         out := mid;
172                 fi;
173         endfor;
174
175         point t_good of curve
176         endgroup
177 enddef;
178
179
180 %
181 % Some sources (eg. Musix/OpusTeX) think that the appendage should be on
182 % the left, some say right.  Right wins democratically.
183 %
184 def draw_neomensural_longa (expr wid) =
185         draw_neomensural_brevis (wid);
186
187         save theta;
188
189         x7r = head_width;
190         y7 = y5;
191         z6 - z7 = (stem_width / 2, -staff_space);
192         theta = angle (z6 - z7) + 90;
193
194         penpos7 (stem_width, 0);
195         penpos6 (1.2 stem_width, theta);
196         
197         z7' = find_tangent (z6l, pat_out,
198                             (x7l + 0.5 stem_width, y7l),
199                             (x7l - 0.5 stem_width, y7l));
200
201         fill z7r
202              .. z6r{z6 - z7}
203              .. {z7 - z6}z6l
204              -- z7'
205              -- cycle;
206
207         penlabels (6, 7);
208         labels (7');
209 enddef;
210
211
212 %
213 % En wij presenteren U: de opvolgster van Emily
214 %
215 % (ze is wel breed)
216
217 fet_beginchar ("Neo-mensural maxima notehead", "s-3neomensural");
218         draw_neomensural_longa (2.6 staff_space#);
219 fet_endchar;
220
221
222 fet_beginchar ("Neo-mensural longa notehead", "s-2neomensural");
223         draw_neomensural_longa (2 staff_space#);
224 fet_endchar;
225
226
227 fet_beginchar ("Neo-mensural brevis notehead", "s-1neomensural");
228         draw_neomensural_brevis (2 staff_space#);
229 fet_endchar;
230
231
232 def draw_neomensural_black_head (expr wid, height) =
233         save head_width;
234         save ne, nw, ne_dist, nw_dist;
235         pair ne, nw, ne_dist, nw_dist;
236
237         head_width# = wid;
238
239         set_char_box (0, head_width#,
240                       height / 2, height / 2);
241         
242         charwx := head_width# / 2;
243         charwy := height / 2;
244
245         y3 = y1 = 0;
246         x2 = x4 = (x1 + x3) / 2;
247
248         pickup pencircle scaled blot_diameter;
249
250         top y2 = h;
251         bot y4 = -d;
252         lft x1 = 0;
253         rt x3 = w;
254
255         ne := unitvector (z2 - z1);
256         nw_dist := (ne rotated 90) * 0.5 blot_diameter;
257         nw := unitvector (z2 - z3);
258         ne_dist := (nw rotated -90) * 0.5 blot_diameter;
259
260         fill lft z1{up}
261              .. (z1 + nw_dist){ne}
262              -- (z2 + nw_dist){ne}
263              .. top z2{right}
264              .. (z2 + ne_dist){-nw}
265              -- (z3 + ne_dist){-nw}
266              .. rt z3{down}
267              .. (z3 - nw_dist){-ne}
268              -- (z4 - nw_dist){-ne}
269              .. bot z4{left}
270              .. (z4 - ne_dist){nw}
271              -- (z1 - ne_dist){nw}
272              .. cycle;
273
274         labels (1, 2, 3, 4);
275 enddef;
276
277
278 def draw_neomensural_open_head (expr wid, height)=
279         draw_neomensural_black_head (wid, height);
280
281         save diamNW, diamSW;
282
283         diamNW = length (z2 - z1) + blot_diameter;
284         diamSW = length (z4 - z1) + blot_diameter;
285         
286         save hole_widthNW, hole_widthSW;
287
288         hole_widthNW = 0.34 diamNW ;
289         hole_widthSW + 2.6 linethickness = diamSW;
290
291         (z7 + z5) / 2 = (w / 2, 0);
292         (z8 + z6) / 2 = (w / 2, 0);
293         z6 - z5 = hole_widthNW * unitvector (z2 - z1);
294         z7 - z6 = hole_widthSW * unitvector (z4 - z1);
295
296         unfill z5
297                -- z6
298                -- z7
299                -- z8
300                -- cycle;
301
302         labels (5, 6, 7, 8);
303 enddef;
304
305
306 %
307 % WL says the thin lines should be thinner.
308 %
309 fet_beginchar ("Harmonic notehead (Neo-mensural open)", "s0harmonic");
310         draw_neomensural_open_head (1.3 staff_space#, 1.3 noteheight#);
311         charwx := head_width#;
312         charwy := 0;
313 fet_endchar;
314
315
316 fet_beginchar ("Harmonic notehead (Neo-mensural black)", "s2harmonic");
317         draw_neomensural_black_head (1.3 staff_space#, 1.3 noteheight#);
318         charwx := head_width#;
319         charwy := 0;
320 fet_endchar;
321
322
323 fet_beginchar ("Neo-mensural semibrevis head", "s0neomensural");
324         draw_neomensural_open_head (staff_space#, noteheight#);
325 fet_endchar;
326
327
328 fet_beginchar ("Neo-mensural minima head", "s1neomensural");
329         draw_neomensural_open_head (staff_space#, noteheight#);
330 fet_endchar;
331
332
333 fet_beginchar ("Neo-mensural semiminima head", "s2neomensural");
334         draw_neomensural_black_head (staff_space#, noteheight#);
335 fet_endchar;
336
337
338 def draw_mensural_brevis (expr wid) =
339         % TODO.  For the moment, fall back to draw_neomensural_brevis.
340         draw_neomensural_brevis (wid);
341 enddef;
342
343
344 %%% This head does not seem to be used anywhere.  Junk me?  -- jr
345 def draw_mensural_left_stemmed_head (expr wid) =
346         draw_mensural_brevis (wid);
347
348         x6 = x7 = stem_width / 2;
349         y6 = y5;
350         y7 = y5 - 2.25 staff_space;
351
352         z17 = (x7, y7 - stem_width / 2);
353
354         penpos6 (stem_width, 0);
355         penpos7 (stem_width, 0);
356
357         fill z7l
358              -- z6l
359              -- z6r
360              -- z7r
361              .. z17
362              .. cycle;
363
364         penlabels (6, 7);
365         labels (17);
366 enddef;
367
368
369 def draw_mensural_longa (expr wid) =
370         draw_mensural_brevis (wid);
371
372         x6 = x7 = head_width - stem_width / 2;
373         y6 = y5;
374         y7 = y5 - 2.25 staff_space;
375
376         z17 = (x7, y7 - stem_width / 2);
377
378         penpos6 (stem_width, 0);
379         penpos7 (stem_width, 0);
380
381         fill z7l
382              -- z6l
383              -- z6r
384              -- z7r
385              .. z17
386              .. cycle;
387
388         penlabels (6, 7);
389         labels (17);
390 enddef;
391
392
393 %%% This head does not seem to be used anywhere.  Junk me?  -- jr
394 fet_beginchar ("Mensural left stemmed notehead", "slmensural");
395         draw_mensural_left_stemmed_head (staff_space#);
396 fet_endchar;
397
398
399 fet_beginchar ("Mensural maxima notehead", "s-3mensural");
400         draw_mensural_longa (2.0 staff_space#);
401 fet_endchar;
402
403
404 fet_beginchar ("Mensural longa notehead", "s-2mensural");
405         draw_mensural_longa (staff_space#);
406 fet_endchar;
407
408
409 fet_beginchar ("Mensural brevis notehead", "s-1mensural");
410         draw_mensural_brevis (staff_space#);
411 fet_endchar;
412
413
414 %
415 % Shift `curve' along the line given by the auxiliary points `p_in'
416 % and `p_out' until `line' is a tangent, and return the shift.
417 % If `curve' is shifted to position `p_in', it must intersect
418 % `line', while shifted to `p_out' it must not.
419 %
420 def find_tangent_shift (expr line, curve, p_in, p_out) =
421         begingroup;
422         save mid, t, t_good, in, out;
423         pair mid, in, out;
424
425         in := p_in;
426         out := p_out;
427
428         forever:
429                 mid := 0.5 [in, out];
430                 exitif abs (out - mid) <= eps;
431                 t := xpart ((curve shifted mid) intersectiontimes line);
432                 if (t > 0):
433                         in := mid;
434                         t_good := t;
435                 else:
436                         out := mid;
437                 fi;
438         endfor;
439
440         mid
441         endgroup
442 enddef;
443
444
445 %
446 % Get subpath specified by `dir_in' and `dir_out' of `curve'
447 % which is then shifted by `offset'.  Assure that result has
448 % the same orientation as `curve'.
449 %
450 def get_subpath (expr curve, dir_in, dir_out, offset) =
451         begingroup;
452         save t_in, t_out;
453
454         t_in := directiontime dir_in of curve;
455         t_out := directiontime dir_out of curve;
456
457         if t_in > t_out:
458                 t_out := t_out + length curve;
459         fi;
460
461         (subpath (t_in, t_out) of curve) shifted offset
462         endgroup
463 enddef;
464
465
466 def draw_diamond_head (expr head_h, pen_w, pen_h, angle, open) =
467         save head_width, head_height;
468         save ellipse, ellipse_r;
469         path ellipse, ellipse_r;
470
471         head_height# = head_h;
472         head_width# / head_height# = tand (angle);
473
474         set_char_box (0, head_width#,
475                       head_height# / 2, head_height# / 2);
476
477         charwx := head_width# / 2;
478         charwy := head_height# / 2 - linethickness#;
479
480         define_pixels (head_width, head_height);
481
482         ellipse := reverse fullcircle
483                      xscaled (max (blot_diameter, pen_w * head_width))
484                      yscaled (max (blot_diameter, pen_h * head_width))
485                      rotated -angle;
486
487         z1 = find_tangent_shift (((0, h) -- (0, -h)), ellipse,
488                                  (0, 0), (w / 2, 0));
489         z2 = find_tangent_shift (((0, h) -- (w, h)), ellipse,
490                                  (w / 2, h), (w / 2, 0));
491         z3 = find_tangent_shift (((w, h) -- (w, -h)), ellipse,
492                                  (w, 0), (w / 2, 0));
493         z4 = find_tangent_shift (((0, -h) -- (w, -h)), ellipse,
494                                  (w / 2, -h), (w / 2, 0));
495
496         fill get_subpath (ellipse, z1 - z4, z2 - z1, z1)
497              -- get_subpath (ellipse, z2 - z1, z3 - z2, z2)
498              -- get_subpath (ellipse, z3 - z2, z4 - z3, z3)
499              -- get_subpath (ellipse, z4 - z3, z1 - z4, z4)
500              -- cycle;
501
502         if open:
503                 save l;
504                 path l[];
505
506                 l12 := (directionpoint (z1 - z2) of ellipse) shifted z1
507                         -- (directionpoint (z1 - z2) of ellipse) shifted z2;
508                 l23 := (directionpoint (z2 - z3) of ellipse) shifted z2
509                         -- (directionpoint (z2 - z3) of ellipse) shifted z3;
510                 l34 := (directionpoint (z3 - z4) of ellipse) shifted z3
511                         -- (directionpoint (z3 - z4) of ellipse) shifted z4;
512                 l41 := (directionpoint (z4 - z1) of ellipse) shifted z4
513                         -- (directionpoint (z4 - z1) of ellipse) shifted z1;
514
515                 unfill l12 intersectionpoint l23
516                        -- l23 intersectionpoint l34
517                        -- l34 intersectionpoint l41
518                        -- l41 intersectionpoint l12
519                        -- cycle;
520         fi;
521
522         labels (1, 2, 3, 4);
523 enddef;
524
525
526 fet_beginchar ("Mensural semibrevis head", "s0mensural");
527         draw_diamond_head (staff_space#, 0.15, 0.30, 30, true);
528 fet_endchar;
529
530
531 fet_beginchar ("Mensural minima head", "s1mensural");
532         draw_diamond_head (staff_space#, 0.15, 0.30, 30, true);
533 fet_endchar;
534
535
536 fet_beginchar ("Mensural semiminima head", "s2mensural");
537         draw_diamond_head (staff_space#, 0.15, 0.30, 30, false);
538 fet_endchar;
539
540
541 fet_beginchar ("Petrucci semibrevis head", "s0petrucci");
542 %       draw_diamond_head (1.8 staff_space#, 0.15, 0.40, 30, true);
543         draw_neomensural_open_head (staff_space#, 1.8 staff_space#);
544 fet_endchar;
545
546
547 fet_beginchar ("Petrucci minima head", "s1petrucci");
548 %       draw_diamond_head (1.8 staff_space#, 0.15, 0.40, 30, true);
549         draw_neomensural_open_head (staff_space#, 1.8 staff_space#);
550 fet_endchar;
551
552
553 fet_beginchar ("Petrucci semiminima head", "s2petrucci");
554 %       draw_diamond_head (1.8 staff_space#, 0.15, 0.40, 30, false);
555         draw_neomensural_black_head (staff_space#, 1.8 staff_space#);
556 fet_endchar;
557
558
559 %%%%%%%%
560 %
561 %
562 %
563 % EDITIO VATICANA (including solesmes extensions)
564 %
565 %
566 %
567
568 % parameterized punctum
569 def punctum_char (expr verbose_name, internal_name,
570                        linea, cavum, straight, auctum,
571                        d_up, up_shift, down_shift, mag) =
572         fet_beginchar (verbose_name, "s" & internal_name);
573                 save a_b, b_h, a_w;
574
575                 a_b := 1.54; % b_h * a_b / a_w = wd / ht
576                 b_h := 0.85;
577                 a_w := 1.09;
578
579                 save a, beta, ht, wd;
580
581                 ht# = noteheight# * mag;
582                 2 beta# = ht# * b_h;
583                 a# = beta# * a_b;
584                 wd# = 2 a# / a_w;
585                 black_notehead_width# := wd#;
586
587                 % direction
588                 save d_, d_sign;
589                 pair d_;
590
591                 if d_up:
592                         d_ := up;
593                         d_sign := 1;
594                 else:
595                         d_ := down;
596                         d_sign := -1;
597                 fi;
598
599                 % convexity and eccentricity
600                 save u_convexity, u_eccentricity;
601
602                 if straight:
603                         u_convexity# := -0.01 ht#;
604                         u_eccentricity# := 0.0 ht#; % dummy
605                 elseif auctum:
606                         u_convexity# := -0.03 ht#;
607                         u_eccentricity# := +0.25 ht#;
608                 else:
609                         u_convexity# := -0.05 ht#;
610                         u_eccentricity# := 0.0 ht#; % dummy
611                 fi;
612
613                 save convexity, eccentricity;
614
615                 convexity# := d_sign * u_convexity#;
616                 eccentricity# := d_sign * u_eccentricity#;
617
618                 % y shift offset
619                 save yoffs;
620
621                 if up_shift:
622                         yoffs# := 0.08 ht#;
623                 elseif down_shift:
624                         yoffs# := -0.11 ht#;
625                 else:
626                         yoffs# := 0.00 ht#;
627                 fi;
628
629                 define_pixels (convexity, eccentricity, yoffs, ht, wd);
630
631                 pickup pencircle scaled linethickness;
632
633                 save height, yoffs_bt, p, circle, circle_r;
634                 path p, circle, circle_r;
635
636                 height# = 0.47 ht#;
637                 yoffs_bt# = yoffs# - 0.5 height# - 0.25 convexity#;
638
639                 define_pixels (height, yoffs_bt);
640
641                 circle := fullcircle scaled linethickness;
642
643                 x1 = x6;
644                 x2 = x5;
645                 x3 = x4;
646                 y1 + height = y6;
647                 y2 + height = y5;
648                 y3 + height = y4;
649
650                 save box_top, box_bt;
651
652                 if auctum:
653                         z1 = (0.00 wd + linethickness / 2, yoffs_bt);
654                         z2 = (0.21 wd, yoffs_bt + convexity);
655                         z3 = (0.42 wd - linethickness/ 2,
656                               yoffs_bt + eccentricity);
657                         box_top# = height# + yoffs_bt# +
658                                      max (0, convexity#, eccentricity#);
659                         box_bt# = yoffs_bt# +
660                                      min (0, convexity#, eccentricity#);
661                         p = z1
662                             .. {right}z2
663                             .. {d_}z3
664                             -- z4{-d_}
665                             .. z5{left}
666                             .. z6
667                             -- cycle;
668                 else:
669                         z1 = (0.00 wd + linethickness / 2, yoffs_bt);
670                         z2 = (0.21 wd, yoffs_bt + convexity);
671                         z3 = (0.42 wd - linethickness / 2, yoffs_bt);
672                         box_top# = height# + yoffs_bt# + max (0, convexity#);
673                         box_bt# = yoffs_bt# + min (0, convexity#);
674                         p = z1
675                             .. z2
676                             .. z3
677                             -- z4
678                             .. z5
679                             .. z6
680                             -- cycle;
681                 fi;
682
683                 labels (1, 2, 3, 4, 5, 6);
684
685                 save dirs;
686                 pair dirs[];
687
688                 dirs12 := direction (0 + epsilon) of p;
689                 dirs2 := direction 1 of p;
690                 dirs32 := direction (2 - epsilon) of p;
691                 dirs45 := direction (3 + epsilon) of p;
692                 dirs5 := direction 4 of p;
693                 dirs65 := direction (5 - epsilon) of p;
694
695                 fill get_subpath (circle, down, dirs12, z1)
696                      .. (bot z2){dirs2}
697                      .. get_subpath (circle, dirs32, up, z3)
698                      -- get_subpath (circle, up, dirs45, z4)
699                      .. (top z5){dirs5}
700                      .. get_subpath (circle, dirs65, down, z6)
701                      -- cycle;
702
703                 if cavum:
704                         save pat, t;
705                         path pat[];
706                         numeric t[];
707
708                         pat123 := ((directionpoint -dirs12 of circle)
709                                     shifted z1){dirs12}
710                                   .. (top z2){dirs2}
711                                   .. {dirs32}((directionpoint -dirs32 of circle)
712                                        shifted z3);
713                         pat34 := lft z3
714                                  -- lft z4;
715                         pat456 := ((directionpoint -dirs45 of circle)
716                                     shifted z4){dirs45}
717                                   .. (bot z5){dirs5}
718                                   .. {dirs65}((directionpoint -dirs65 of circle)
719                                        shifted z6);
720                         pat61 := rt z6
721                                  -- rt z1;
722
723                         t61 := ypart (pat61 intersectiontimes pat123);
724                         t12 := xpart (pat123 intersectiontimes pat34);
725                         t34 := ypart (pat34 intersectiontimes pat456);
726                         t45 := xpart (pat456 intersectiontimes pat61);
727
728                         unfill subpath (t61, t12) of pat123
729                                -- subpath (t34, t45) of pat456
730                                -- cycle;
731                 fi;
732
733                 set_char_box (0.00 wd#, 0.42 wd#,
734                               max (0, -box_bt#) + linethickness# / 2,
735                               max (0, box_top#) + linethickness# / 2);
736
737                 if linea:
738                         save linea_width, linea_height;
739
740                         linea_width# = 0.6 linethickness#;
741                         linea_height# = 0.7 ht#;
742
743                         define_pixels (linea_width, linea_height);
744
745                         pickup pencircle scaled 0.6 linethickness;
746
747                         draw_block ((-0.10 wd - linea_width / 2,
748                                      -linea_height / 2),
749                                     (-0.10 wd + linea_width / 2,
750                                      +linea_height / 2));
751                         draw_block ((+0.52 wd - linea_width / 2,
752                                      -linea_height / 2),
753                                     (+0.52 wd + linea_width / 2,
754                                      +linea_height / 2));
755
756                         set_char_box (0, 0.62 wd# + linea_width#,
757                                       linea_height# / 2,
758                                       linea_height# / 2);
759
760                         currentpicture := currentpicture
761                                 shifted (0.10 wd + linea_width / 2, 0);
762                 fi;
763         fet_endchar;
764 enddef;
765
766
767 % parameterized punctum
768 def plica_char (expr verbose_name, internal_name,
769                      d_up, mag) =
770         fet_beginchar (verbose_name, "s" & internal_name);
771                 save a_b, b_h, a_w;
772
773                 a_b := 1.54; % b_h * a_b / a_w = wd / ht
774                 b_h := 0.85;
775                 a_w := 1.09;
776
777                 save a, beta, ht, wd;
778
779                 ht# = noteheight# * mag;
780                 2 beta# = ht# * b_h;
781                 a# = beta# * a_b;
782                 wd# = 2 a# / a_w;
783                 black_notehead_width# := wd#;
784
785                 % direction
786                 save d_, d_sign;
787                 pair d_;
788
789                 if d_up:
790                         d_ := up;
791                         d_sign := 1;
792                 else:
793                         d_ := down;
794                         d_sign := -1;
795                 fi;
796
797                 % convexity and eccentricity
798                 save convexity, eccentricity;
799
800                 convexity# := d_sign * -0.10 ht#;
801                 eccentricity# := d_sign * -0.12 ht#;
802
803                 % y shift offset
804                 save yoffs;
805
806                 yoffs# := -0.11 ht#;
807
808                 define_pixels (convexity, eccentricity, yoffs, ht, wd);
809
810                 pickup pencircle scaled linethickness;
811
812                 save height, yoffs_bt, p, circle, circle_r;
813                 path p, circle, circle_r;
814
815                 height# = 0.47 ht#;
816                 yoffs_bt# = yoffs# - 0.5 height# - 0.25 convexity#;
817
818                 define_pixels (height, yoffs_bt);
819
820                 circle := fullcircle scaled linethickness;
821
822                 x1 = x6;
823                 x2 = x5;
824                 x3 = x4;
825                 y1 + height = y6;
826                 y2 + height = y5;
827                 y3 + height = y4;
828
829                 save box_top, box_bt;
830
831                 z1 = (0.00 wd + linethickness / 2, yoffs_bt);
832                 z2 = (0.21 wd, yoffs_bt + convexity);
833                 z3 = (0.42 wd - linethickness/ 2, yoffs_bt + eccentricity);
834                 box_top# = height# + yoffs_bt# +
835                              max (0, convexity#, eccentricity#);
836                 box_bt# = yoffs_bt# +
837                              min (0, convexity#, eccentricity#);
838                 p = z1
839                     .. z2{right}
840                     .. z3
841                     -- z4
842                     .. z5{left}
843                     .. z6
844                     -- cycle;
845
846                 labels (1, 2, 3, 4, 5, 6);
847
848                 save dirs;
849                 pair dirs[];
850
851                 dirs12 := direction (0 + epsilon) of p;
852                 dirs2 := direction 1 of p;
853                 dirs32 := direction (2 - epsilon) of p;
854                 dirs45 := direction (3 + epsilon) of p;
855                 dirs5 := direction 4 of p;
856                 dirs65 := direction (5 - epsilon) of p;
857
858                 fill get_subpath (circle, down, dirs12, z1)
859                      .. (bot z2){dirs2}
860                      .. get_subpath (circle, dirs32, up, z3)
861                      -- get_subpath (circle, up, dirs45, z4)
862                      .. (top z5){dirs5}
863                      .. get_subpath (circle, dirs65, down, z6)
864                      -- cycle;
865
866                 pickup pencircle scaled 0.6 linethickness;
867
868                 save stem_bt;
869
870                 set_char_box (0.00 wd#, 0.42 wd#,
871                               max (0, -box_bt#) + linethickness# / 2,
872                               max (0, box_top#) + linethickness# / 2);
873
874         fet_endchar;
875 enddef;
876
877
878 % parameterized punctum
879 def epiphonus_char (expr verbose_name, internal_name,
880                          left_stem, d_up, down_shift, mag) =
881         fet_beginchar (verbose_name, "s" & internal_name);
882                 save a_b, b_h, a_w;
883
884                 a_b := 1.54; % b_h * a_b / a_w = wd / ht
885                 b_h := 0.85;
886                 a_w := 1.09;
887
888                 save a, beta, ht, wd;
889
890                 ht# = noteheight# * mag;
891                 2 beta# = ht# * b_h;
892                 a# = beta# * a_b;
893                 wd# = 2 a# / a_w;
894                 black_notehead_width# := wd#;
895
896                 % direction
897                 save d_, d_sign;
898                 pair d_;
899
900                 if d_up:
901                         d_ := up;
902                         d_sign := 1;
903                 else:
904                         d_ := down;
905                         d_sign := -1;
906                 fi;
907
908                 % convexity and eccentricity
909                 save convexity;
910
911                 convexity# := d_sign * -0.05ht#;
912
913                 % y shift offset
914                 save yoffs;
915
916                 if down_shift:
917                         yoffs# := -0.11 ht#;
918                 else:
919                         yoffs# := 0.00 ht#;
920                 fi;
921
922                 define_pixels (convexity, yoffs, ht, wd);
923
924                 pickup pencircle scaled linethickness;
925
926                 save height, yoffs_bt, p, circle, circle_r;
927                 path p, circle, circle_r;
928
929                 height# = 0.47 ht#;
930                 yoffs_bt# = yoffs# - 0.5 height# - 0.25 convexity#;
931
932                 define_pixels (height, yoffs_bt);
933
934                 circle := fullcircle scaled linethickness;
935
936                 x1 = x6;
937                 x2 = x5;
938                 x3 = x4;
939                 y1 + height = y6;
940                 y2 + height = y5;
941                 y3 + height = y4;
942
943                 save box_top, box_bt;
944
945                 z1 = (0.00 wd + linethickness / 2, yoffs_bt - 2.5 convexity);
946                 z2 = (0.06 wd, yoffs_bt + 1.4 convexity);
947                 z3 = (0.42 wd - linethickness / 2, yoffs_bt - 1.0 convexity);
948                 box_top# = height# + yoffs_bt# +
949                              max (-1.0 convexity#, 1.4 convexity#, 0);
950                 box_bt# = yoffs_bt# +
951                              min (-1.0 convexity#, 1.4 convexity#, 0);
952                 p = z1{-d_}
953                     .. {curl 1}z2{right}
954                     .. z3
955                     -- z4
956                     .. {left}z5{curl 1}
957                     .. {d_}z6
958                     -- cycle;
959
960 %               filldraw p;
961
962                 labels (1, 2, 3, 4, 5, 6);
963
964                 save dirs;
965                 pair dirs[];
966
967                 dirs12 := direction (0 + epsilon) of p;
968                 dirs21 := direction (1 - epsilon) of p;
969                 dirs23 := direction (1 + epsilon) of p;
970                 dirs32 := direction (2 - epsilon) of p;
971                 dirs45 := direction (3 + epsilon) of p;
972                 dirs54 := direction (4 - epsilon) of p;
973                 dirs56 := direction (4 + epsilon) of p;
974                 dirs65 := direction (5 - epsilon) of p;
975
976                 fill get_subpath (circle, down, dirs12, z1)
977                      .. get_subpath (circle, dirs21, dirs23, z2)
978                      .. get_subpath (circle, dirs32, up, z3)
979                      -- get_subpath (circle, up, dirs45, z4)
980                      .. get_subpath (circle, dirs54, dirs56, z5)
981                      .. get_subpath (circle, dirs65, down, z6)
982                      -- cycle;
983
984                 pickup pencircle scaled 0.6 linethickness;
985
986                 save stem_bt;
987
988                 if left_stem:
989                         z11 = (0.00 wd + 0.6 linethickness / 2, yoffs - 1.1 ht);
990                         z12 = (0.00 wd + 0.6 linethickness / 2, yoffs);
991                         draw_block ((0, yoffs - 1.1 ht - linethickness / 2),
992                                     (0.6 linethickness, yoffs));
993                         stem_bt# = yoffs# - 1.1 ht#;
994                 else:
995                         stem_bt# = 0;
996                 fi;
997
998                 set_char_box (0.00 wd#, 0.42 wd#,
999                               max (0, -box_bt#, -stem_bt#) + linethickness# / 2,
1000                               max (0, box_top#) + linethickness# / 2);
1001         fet_endchar;
1002 enddef;
1003
1004
1005 % parameterized punctum inclinatum
1006 def inclinatum_char (expr verbose_name, internal_name,
1007                           small, stropha, auctum) =
1008         fet_beginchar (verbose_name, "s" & internal_name)
1009                 save ht, alpha;
1010
1011                 alpha := 35;
1012
1013                 if small:
1014                         ht# = 0.50 noteheight#;
1015                 else:
1016                         ht# = 0.80 noteheight#;
1017                 fi;
1018
1019                 draw_diamond_head (ht#, 0, 0, alpha, false);
1020
1021                 if stropha:
1022                         pickup pencircle xscaled 0.25 head_height
1023                                          yscaled 0.55 head_height
1024                                          rotated alpha;
1025
1026                         save za, off_angle;
1027                         pair za;
1028
1029                         off_angle := 15;
1030
1031                         za = (0, -0.25 head_height)
1032                                rotated -(alpha + off_angle)
1033                                shifted (0.48 head_width, -0.02 head_width);
1034
1035                         undrawdot za;
1036                 fi;
1037
1038                 if auctum:
1039                         pickup pencircle scaled linethickness;
1040
1041                         save za, zb, zc;
1042                         pair za, zb, zc;
1043
1044                         za = (0, -0.5 head_height + linethickness);
1045                         zb = 0.6 (za + zc);
1046                         zc = za + (0.52 head_width, 0);
1047
1048                         draw za{(0, -1) rotated alpha}
1049                              .. {right}zb{right}
1050                              .. {(0, 1) rotated -alpha}zc;
1051                 fi;
1052         fet_endchar;
1053 enddef;
1054
1055
1056 % punctum
1057 punctum_char ("Ed. Vat. punctum", "vaticana.punctum",
1058               false, false, false, false,
1059               false, false, false, 1.0);
1060
1061
1062 % punctum cavum (for OpusTeX compatibility)
1063 punctum_char ("Ed. Vat. punctum cavum", "vaticana.punctum.cavum",
1064               false, true, false, false,
1065               false, false, false, 1.0);
1066
1067
1068 % linea punctum (for OpusTeX compatibility)
1069 punctum_char ("Ed. Vat. linea punctum", "vaticana.linea.punctum",
1070               true, false, false, false,
1071               false, false, false, 1.0);
1072
1073
1074 % linea punctum cavum (for OpusTeX compatibility)
1075 punctum_char ("Ed. Vat. linea punctum cavum", "vaticana.linea.punctum.cavum",
1076               true, true, false, false,
1077               false, false, false, 1.0);
1078
1079
1080 % punctum inclinatum
1081 inclinatum_char ("Ed. Vat. inclinatum", "vaticana.inclinatum",
1082                  false, false, false);
1083
1084
1085 % pes lower punctum
1086 punctum_char ("Ed. Vat. pes lower punctum", "vaticana.lpes",
1087               false, false, true, false,
1088               true, false, false, 1.0);
1089
1090
1091 % pes lower punctum
1092 punctum_char ("Ed. Vat. pes var lower punctum", "vaticana.vlpes",
1093               false, false, true, false,
1094               true, false, true, 1.0);
1095
1096
1097 % pes upper punctum
1098 punctum_char ("Ed. Vat. pes upper punctum", "vaticana.upes", 
1099               false, false, true, false,
1100               false, false, false, 1.0);
1101
1102
1103 % pes upper punctum (shifted variation)
1104 %
1105 % This note head is used instead of the regular pes upper punctum to
1106 % avoid collision with the lower punctum note of the pes when the upper
1107 % punctum sits directly on top of the lower punctum.
1108 %
1109 punctum_char ("Ed. Vat. var pes upper punctum", "vaticana.vupes",
1110               false, false, true, false,
1111               false, true, false, 1.0);
1112
1113
1114 % small punctum as used in epiphonus
1115 punctum_char ("Ed. Vat. plica", "vaticana.plica", 
1116               false, false, false, false,
1117               false, false, false, 0.6);
1118
1119
1120 % small punctum as used in epiphonus
1121 plica_char ("Ed. Vat. var plica", "vaticana.vplica", 
1122             false, 0.6);
1123
1124
1125 % eccentric punctum as used in epiphonus
1126 epiphonus_char ("Ed. Vat. epiphonus", "vaticana.epiphonus", 
1127                 false, true, false, 1.0);
1128
1129
1130 % eccentric punctum as used in epiphonus (shifted variation)
1131 %
1132 % This note head is used instead of the regular epiphonus punctum to
1133 % avoid collision with the plica head when the plica sits directly on
1134 % top of the lower head.
1135 %
1136 epiphonus_char ("Ed. Vat. var epiphonus", "vaticana.vepiphonus",
1137                 false, true, true, 1.0);
1138
1139
1140 % small punctum as used in cephalicus
1141 punctum_char ("Ed. Vat. rev. plica", "vaticana.reverse.plica",
1142               false, false, false, false,
1143               true, false, false, 0.6);
1144
1145
1146 % small punctum as used in cephalicus
1147 plica_char ("Ed. Vat. rev. var plica", "vaticana.reverse.vplica",
1148             true, 0.6);
1149
1150
1151 % eccentric punctum as used in cephalicus; without left stem
1152 epiphonus_char ("Ed. Vat. inner cephalicus", "vaticana.inner.cephalicus",
1153                 false, false, false, 1.0);
1154
1155
1156 % eccentric punctum as used in cephalicus; with left stem
1157 epiphonus_char ("Ed. Vat. cephalicus", "vaticana.cephalicus",
1158                 true, false, false, 1.0);
1159
1160
1161 % quilisma
1162 fet_beginchar ("Ed. Vat. quilisma", "svaticana.quilisma")
1163         save a_b, b_h, a_w;
1164
1165         a_b:=1.54; % b_h*a_b/a_w = wd/ht
1166         b_h:=0.85;
1167         a_w:=1.09;
1168
1169         save a, beta, ht, wd;
1170         ht# = noteheight#;
1171         2 beta# = ht# * b_h;
1172         a# = beta#*a_b;
1173         wd# = 2 a# / a_w;
1174         set_char_box (0, 0.42 wd#, 0.28 ht#, 0.36 ht#);
1175         black_notehead_width# := wd#;
1176
1177         define_pixels (ht, wd);
1178         pickup pencircle xscaled linethickness yscaled 0.44 ht;
1179         lft x1 = 0.00 wd; bot y1 = -0.28 ht;
1180         x2 = 0.11 wd;     y2 = -0.14 ht;
1181         x3 = 0.12 wd;     y3 = +0.03 ht;
1182         x4 = 0.25 wd;     y4 = -0.09 ht;
1183         x5 = 0.26 wd;     y5 = +0.08 ht;
1184         x6 = 0.40 wd;     y6 = -0.04 ht;
1185         rt x7 = 0.42 wd;  top y7 = +0.36 ht;
1186         draw z1 .. z2 -- z3 .. z4 -- z5 .. z6 -- z7;
1187 fet_endchar;
1188
1189
1190 % solesmes punctum inclinatum parvum
1191 inclinatum_char ("Solesmes punctum inclinatum parvum", "solesmes.incl.parvum",
1192                  true, false, false);
1193
1194
1195 % solesmes punctum auctum ascendens
1196 punctum_char ("Solesmes punctum auctum ascendens", "solesmes.auct.asc",
1197               false, false, false, true,
1198               true, false, false, 1.0);
1199
1200
1201 % solesmes punctum auctum descendens
1202 punctum_char ("Solesmes punctum auctum descendens", "solesmes.auct.desc",
1203               false, false, false, true,
1204               false, false, false, 1.0);
1205
1206
1207 % solesmes punctum inclinatum auctum
1208 inclinatum_char ("Solesmes punctum incl. auctum", "solesmes.incl.auctum",
1209                  false, false, true);
1210
1211
1212 % solesmes stropha
1213 inclinatum_char ("Solesmes stropha", "solesmes.stropha",
1214                  false, true, false);
1215
1216
1217 % solesmes stropha aucta
1218 inclinatum_char ("Solesmes stropha aucta", "solesmes.stropha.aucta",
1219                  false, true, true);
1220
1221
1222 % solesmes oriscus
1223 fet_beginchar ("Solesmes oriscus", "ssolesmes.oriscus")
1224         save a_b, b_h, a_w;
1225
1226         a_b := 1.54; % b_h*a_b/a_w = wd/ht
1227         b_h := 0.85;
1228         a_w := 1.09;
1229
1230         save a, beta, ht, wd;
1231         ht# = noteheight#;
1232         2 beta# = ht# * b_h;
1233         a# = beta# * a_b;
1234         wd# = 2 a# / a_w;
1235         black_notehead_width# := wd#;
1236
1237         save convexity;
1238         convexity# = +0.05 ht#;
1239
1240         define_pixels (ht, wd, convexity);
1241         pickup pencircle xscaled blot_diameter yscaled 0.50 ht;
1242         lft x1 = 0.00 wd; y1 = -convexity;
1243         x2 = 0.16 wd;     y2 = +convexity;
1244         x3 = 0.33 wd;     y3 = -convexity;
1245         rt x4 = 0.50 wd;  y4 = +convexity;
1246         draw z1 .. z2 .. z3 .. z4;
1247         set_char_box (0.00 wd#, 0.50 wd#,
1248                       0.25 ht# + convexity#, 0.25 ht# + convexity#);
1249 fet_endchar;
1250
1251
1252 %%%%%%%%
1253 %
1254 %
1255 %
1256 % EDITIO MEDICAEA
1257 %
1258 %
1259 %
1260
1261 % inclinatum
1262 fet_beginchar ("Ed. Med. inclinatum", "smedicaea.inclinatum")
1263         draw_diamond_head (1.2 staff_space#, 0, 0, 35, false);
1264 fet_endchar;
1265
1266
1267 % parametrized punctum
1268 def punctum_char (expr verbose_name, internal_name,
1269                        left_up_stem, left_down_stem) =
1270         fet_beginchar (verbose_name, "s" & internal_name);
1271                 save a, beta, ht, wd;
1272
1273                 ht# = 2 staff_space#;
1274                 wd# = ht#;
1275                 black_notehead_width# := wd#;
1276
1277                 define_pixels (ht, wd);
1278
1279                 pickup pencircle xscaled blot_diameter
1280                                  yscaled 0.50 ht;
1281
1282                 z1 = (0.00 wd + blot_diameter / 2, 0);
1283                 z2 = (0.4 wd - blot_diameter / 2, 0);
1284
1285                 draw z1
1286                      .. z2;
1287
1288                 pickup pencircle xscaled linethickness
1289                                  yscaled blot_diameter;
1290
1291                 if left_down_stem:
1292                         z4 = (0.00 wd + linethickness / 2, blot_diameter / 2);
1293                         z5 = (0.00 wd + linethickness / 2, -1.25 ht);
1294
1295                         draw z4
1296                              .. z5;
1297                         set_char_box (0.0, 0.4 wd#, 1.25 ht#, 0.25 ht#);
1298                 elseif left_up_stem:
1299                         z4 = (0.00 wd + linethickness / 2, blot_diameter / 2);
1300                         z5 = (0.00 wd + linethickness / 2, +1.25 ht);
1301
1302                         draw z4
1303                              .. z5;
1304                         set_char_box (0.0, 0.4 wd#, 0.25 ht#, 1.25 ht#);
1305                 else:
1306                         set_char_box (0.0, 0.4 wd#, 0.25 ht#, 0.25 ht#);
1307                 fi;
1308
1309         fet_endchar;
1310 enddef;
1311
1312
1313 % punctum
1314 punctum_char ("Ed. Med. punctum", "medicaea.punctum", 
1315               false, false);
1316
1317
1318 % left up-stemmed punctum
1319 punctum_char ("Ed. Med. reverse virga", "medicaea.rvirga",
1320               true, false);
1321
1322
1323 % virga (i.e. left down-stemmed punctum)
1324 punctum_char ("Ed. Med. virga", "medicaea.virga", 
1325               false, true);
1326
1327 %%%%%%%%
1328 %
1329 %
1330 %
1331 % HUFNAGEL
1332 %
1333 %
1334 %
1335
1336 % punctum
1337 % parametrized punctum
1338 def punctum_char (expr verbose_name, internal_name,
1339                        down_stem) =
1340         fet_beginchar (verbose_name, "s" & internal_name);
1341                 save alpha;
1342
1343                 alpha# = 55;
1344                 draw_diamond_head (staff_space#, 0, 0, alpha#, false);
1345                 if down_stem:
1346                         pickup pencircle xscaled blot_diameter
1347                                          yscaled 0.7 staff_space
1348                                          rotated -alpha#;
1349
1350                         save za, zb;
1351                         pair za, zb;
1352
1353                         za = (head_width / 2, 0);
1354                         bot zb = (head_width / 2, -1.5 staff_space);
1355
1356                         draw za
1357                              -- zb;
1358                         set_char_box (0, head_width#,
1359                                       1.5 staff_space#, head_height# / 2);
1360                 fi;
1361         fet_endchar;
1362 enddef;
1363
1364 % punctum
1365 punctum_char ("Hufnagel punctum", "hufnagel.punctum", false)
1366
1367 % virga
1368 punctum_char ("Hufnagel virga", "hufnagel.virga",  true)
1369
1370 % pes lower punctum
1371 fet_beginchar ("Hufnagel pes lower punctum", "shufnagel.lpes")
1372         save width, height, alpha;
1373         width# = 2*staff_space#;
1374         height# = 0.7*staff_space#;
1375         alpha# = 35;
1376
1377         set_char_box (0, width#, height#/2, height#/2);
1378
1379         pickup pencircle scaled linethickness;
1380         define_pixels (width, height);
1381
1382         rt x3 = -lft x1 = width/2;
1383         y2 = y3 = height/2;
1384         y1 = y4 = -height/2;
1385         tand (alpha#) * (y2 - y1) = x2 - x1 = x3 - x4;
1386
1387         filldraw z1 -- z2 -- z3 -- z4 -- cycle;
1388
1389         currentpicture := currentpicture shifted (width/2, 0);
1390 fet_endchar;
1391
1392 fet_endgroup ("noteheads")