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