]> 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, diamond_shape;
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         diamond_shape := 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         fill diamond_shape;
502
503         if open:
504                 save l;
505                 path l[];
506
507                 l12 := (directionpoint (z1 - z2) of ellipse) shifted z1
508                         -- (directionpoint (z1 - z2) of ellipse) shifted z2;
509                 l23 := (directionpoint (z2 - z3) of ellipse) shifted z2
510                         -- (directionpoint (z2 - z3) of ellipse) shifted z3;
511                 l34 := (directionpoint (z3 - z4) of ellipse) shifted z3
512                         -- (directionpoint (z3 - z4) of ellipse) shifted z4;
513                 l41 := (directionpoint (z4 - z1) of ellipse) shifted z4
514                         -- (directionpoint (z4 - z1) of ellipse) shifted z1;
515
516                 unfill l12 intersectionpoint l23
517                        -- l23 intersectionpoint l34
518                        -- l34 intersectionpoint l41
519                        -- l41 intersectionpoint l12
520                        -- cycle;
521         fi;
522
523         labels (1, 2, 3, 4);
524 enddef;
525
526
527 fet_beginchar ("Mensural semibrevis head", "s0mensural");
528         draw_diamond_head (staff_space#, 0.15, 0.30, 30, true);
529 fet_endchar;
530
531
532 fet_beginchar ("Mensural minima head", "s1mensural");
533         draw_diamond_head (staff_space#, 0.15, 0.30, 30, true);
534 fet_endchar;
535
536
537 fet_beginchar ("Mensural semiminima head", "s2mensural");
538         draw_diamond_head (staff_space#, 0.15, 0.30, 30, false);
539 fet_endchar;
540
541
542 fet_beginchar ("Petrucci semibrevis head", "s0petrucci");
543 %       draw_diamond_head (1.8 staff_space#, 0.15, 0.40, 30, true);
544         draw_neomensural_open_head (staff_space#, 1.8 staff_space#);
545 fet_endchar;
546
547
548 fet_beginchar ("Petrucci minima head", "s1petrucci");
549 %       draw_diamond_head (1.8 staff_space#, 0.15, 0.40, 30, true);
550         draw_neomensural_open_head (staff_space#, 1.8 staff_space#);
551 fet_endchar;
552
553
554 fet_beginchar ("Petrucci semiminima head", "s2petrucci");
555 %       draw_diamond_head (1.8 staff_space#, 0.15, 0.40, 30, false);
556         draw_neomensural_black_head (staff_space#, 1.8 staff_space#);
557 fet_endchar;
558
559
560 %%%%%%%%
561 %
562 %
563 %
564 % EDITIO VATICANA (including solesmes extensions)
565 %
566 %
567 %
568
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 def plica_char (expr verbose_name, internal_name,
768                      d_up, mag) =
769         fet_beginchar (verbose_name, "s" & internal_name);
770                 save a_b, b_h, a_w;
771
772                 a_b := 1.54; % b_h * a_b / a_w = wd / ht
773                 b_h := 0.85;
774                 a_w := 1.09;
775
776                 save a, beta, ht, wd;
777
778                 ht# = noteheight# * mag;
779                 2 beta = ht# * b_h;
780                 a = beta * a_b;
781                 wd# = 2 a / a_w;
782                 black_notehead_width# := wd#;
783
784                 % direction
785                 save d_, d_sign;
786                 pair d_;
787
788                 if d_up:
789                         d_ := up;
790                         d_sign := 1;
791                 else:
792                         d_ := down;
793                         d_sign := -1;
794                 fi;
795
796                 % convexity and eccentricity
797                 save convexity, eccentricity;
798
799                 convexity# := d_sign * -0.10 ht#;
800                 eccentricity# := d_sign * -0.12 ht#;
801
802                 % y shift offset
803                 save yoffs;
804
805                 yoffs# := -0.11 ht#;
806
807                 define_pixels (convexity, eccentricity, yoffs, ht, wd);
808
809                 pickup pencircle scaled linethickness;
810
811                 save height, yoffs_bt, p, circle, circle_r;
812                 path p, circle, circle_r;
813
814                 height# = 0.47 ht#;
815                 yoffs_bt# = yoffs# - 0.5 height# - 0.25 convexity#;
816
817                 define_pixels (height, yoffs_bt);
818
819                 circle := fullcircle scaled linethickness;
820
821                 x1 = x6;
822                 x2 = x5;
823                 x3 = x4;
824                 y1 + height = y6;
825                 y2 + height = y5;
826                 y3 + height = y4;
827
828                 save box_top, box_bt;
829
830                 z1 = (0.00 wd + linethickness / 2, yoffs_bt);
831                 z2 = (0.21 wd, yoffs_bt + convexity);
832                 z3 = (0.42 wd - linethickness/ 2, yoffs_bt + eccentricity);
833                 box_top# = height# + yoffs_bt# +
834                              max (0, convexity#, eccentricity#);
835                 box_bt# = yoffs_bt# +
836                              min (0, convexity#, eccentricity#);
837                 p = z1
838                     .. z2{right}
839                     .. z3
840                     -- z4
841                     .. z5{left}
842                     .. z6
843                     -- cycle;
844
845                 labels (1, 2, 3, 4, 5, 6);
846
847                 save dirs;
848                 pair dirs[];
849
850                 dirs12 := direction (0 + epsilon) of p;
851                 dirs2 := direction 1 of p;
852                 dirs32 := direction (2 - epsilon) of p;
853                 dirs45 := direction (3 + epsilon) of p;
854                 dirs5 := direction 4 of p;
855                 dirs65 := direction (5 - epsilon) of p;
856
857                 fill get_subpath (circle, down, dirs12, z1)
858                      .. (bot z2){dirs2}
859                      .. get_subpath (circle, dirs32, up, z3)
860                      -- get_subpath (circle, up, dirs45, z4)
861                      .. (top z5){dirs5}
862                      .. get_subpath (circle, dirs65, down, z6)
863                      -- cycle;
864
865                 pickup pencircle scaled 0.6 linethickness;
866
867                 save stem_bt;
868
869                 set_char_box (0.00 wd#, 0.42 wd#,
870                               max (0, -box_bt#) + linethickness# / 2,
871                               max (0, box_top#) + linethickness# / 2);
872
873         fet_endchar;
874 enddef;
875
876
877 def epiphonus_char (expr verbose_name, internal_name,
878                          left_stem, d_up, down_shift, mag) =
879         fet_beginchar (verbose_name, "s" & internal_name);
880                 save a_b, b_h, a_w;
881
882                 a_b := 1.54; % b_h * a_b / a_w = wd / ht
883                 b_h := 0.85;
884                 a_w := 1.09;
885
886                 save a, beta, ht, wd;
887
888                 ht# = noteheight# * mag;
889                 2 beta = ht# * b_h;
890                 a = beta * a_b;
891                 wd# = 2 a / a_w;
892                 black_notehead_width# := wd#;
893
894                 % direction
895                 save d_, d_sign;
896                 pair d_;
897
898                 if d_up:
899                         d_ := up;
900                         d_sign := 1;
901                 else:
902                         d_ := down;
903                         d_sign := -1;
904                 fi;
905
906                 % convexity and eccentricity
907                 save convexity;
908
909                 convexity# := d_sign * -0.05ht#;
910
911                 % y shift offset
912                 save yoffs;
913
914                 if down_shift:
915                         yoffs# := -0.11 ht#;
916                 else:
917                         yoffs# := 0.00 ht#;
918                 fi;
919
920                 define_pixels (convexity, yoffs, ht, wd);
921
922                 pickup pencircle scaled linethickness;
923
924                 save height, yoffs_bt, p, circle, circle_r;
925                 path p, circle, circle_r;
926
927                 height# = 0.47 ht#;
928                 yoffs_bt# = yoffs# - 0.5 height# - 0.25 convexity#;
929
930                 define_pixels (height, yoffs_bt);
931
932                 circle := fullcircle scaled linethickness;
933
934                 x1 = x6;
935                 x2 = x5;
936                 x3 = x4;
937                 y1 + height = y6;
938                 y2 + height = y5;
939                 y3 + height = y4;
940
941                 save box_top, box_bt;
942
943                 z1 = (0.00 wd + linethickness / 2, yoffs_bt - 2.5 convexity);
944                 z2 = (0.06 wd, yoffs_bt + 1.4 convexity);
945                 z3 = (0.42 wd - linethickness / 2, yoffs_bt - 1.0 convexity);
946                 box_top# = height# + yoffs_bt# +
947                              max (-1.0 convexity#, 1.4 convexity#, 0);
948                 box_bt# = yoffs_bt# +
949                              min (-1.0 convexity#, 1.4 convexity#, 0);
950                 p = z1{-d_}
951                     .. {curl 1}z2{right}
952                     .. z3
953                     -- z4
954                     .. {left}z5{curl 1}
955                     .. {d_}z6
956                     -- cycle;
957
958                 labels (1, 2, 3, 4, 5, 6);
959
960                 save dirs;
961                 pair dirs[];
962
963                 dirs12 := direction (0 + epsilon) of p;
964                 dirs21 := direction (1 - epsilon) of p;
965                 dirs23 := direction (1 + epsilon) of p;
966                 dirs32 := direction (2 - epsilon) of p;
967                 dirs45 := direction (3 + epsilon) of p;
968                 dirs54 := direction (4 - epsilon) of p;
969                 dirs56 := direction (4 + epsilon) of p;
970                 dirs65 := direction (5 - epsilon) of p;
971
972                 fill get_subpath (circle, down, dirs12, z1)
973                      .. get_subpath (circle, dirs21, dirs23, z2)
974                      .. get_subpath (circle, dirs32, up, z3)
975                      -- get_subpath (circle, up, dirs45, z4)
976                      .. get_subpath (circle, dirs54, dirs56, z5)
977                      .. get_subpath (circle, dirs65, down, z6)
978                      -- cycle;
979
980                 pickup pencircle scaled 0.6 linethickness;
981
982                 save stem_bt;
983
984                 if left_stem:
985                         z11 = (0.00 wd + 0.6 linethickness / 2, yoffs - 1.1 ht);
986                         z12 = (0.00 wd + 0.6 linethickness / 2, yoffs);
987                         draw_block ((0, yoffs - 1.1 ht - linethickness / 2),
988                                     (0.6 linethickness, yoffs));
989                         stem_bt# = yoffs# - 1.1 ht#;
990                 else:
991                         stem_bt# = 0;
992                 fi;
993
994                 set_char_box (0.00 wd#, 0.42 wd#,
995                               max (0, -box_bt#, -stem_bt#) + linethickness# / 2,
996                               max (0, box_top#) + linethickness# / 2);
997         fet_endchar;
998 enddef;
999
1000
1001 def inclinatum_char (expr verbose_name, internal_name,
1002                           small, stropha, auctum) =
1003         fet_beginchar (verbose_name, "s" & internal_name)
1004                 save ht, alpha;
1005
1006                 alpha := 35;
1007
1008                 if small:
1009                         ht# = 0.50 noteheight#;
1010                 else:
1011                         ht# = 0.80 noteheight#;
1012                 fi;
1013
1014                 draw_diamond_head (ht#, 0, 0, alpha, false);
1015
1016                 save off_angle;
1017
1018                 off_angle := alpha + 15;
1019
1020                 save stropha_ellipse, auctum_hook, circle;
1021                 path stropha_ellipse, auctum_hook, circle;
1022
1023                 circle := reverse fullcircle scaled linethickness;
1024
1025                 stropha_ellipse := fullcircle xscaled 0.25 head_height
1026                                               yscaled 0.55 head_height
1027                                               rotated alpha;
1028
1029                 z11 = z12
1030                       + linethickness / 2 * dir (180 - off_angle)
1031                       - directionpoint dir (90 - off_angle)
1032                           of stropha_ellipse;
1033                 z12 = directionpoint -dir (90 - off_angle) of diamond_shape +
1034                         linethickness / 2 * dir (180 - off_angle);
1035                 z13 = (0, -0.5 head_height + linethickness);
1036
1037                 auctum_hook := z12{-dir (90 - off_angle)}
1038                                .. {dir (90 + alpha)}z13;
1039
1040                 labels (12);
1041
1042                 if (stropha and not auctum):
1043                         clearit;
1044
1045                         save t_in, t_out;
1046
1047                         t_in := xpart ((stropha_ellipse shifted z11)
1048                                        intersectiontimes
1049                                        get_subpath (diamond_shape,
1050                                                     left, up,
1051                                                     (0, 0)));
1052                         t_out := xpart ((stropha_ellipse shifted z11)
1053                                         intersectiontimes
1054                                         get_subpath (diamond_shape,
1055                                                      up, right,
1056                                                      (0, 0)));
1057
1058                         % the `eps' is necessary so that we don't get the
1059                         % start of a straight line in the diamond shape
1060                         fill get_subpath (diamond_shape,
1061                                           dir (angle (z2 - z1) - eps),
1062                                           dir (angle (z1 - z4) + eps),
1063                                           (0, 0))
1064                              -- get_subpath (stropha_ellipse,
1065                                              direction t_in of stropha_ellipse,
1066                                              direction t_out of stropha_ellipse,
1067                                              z11)
1068                              -- cycle;
1069
1070                         labels (11);
1071                 fi;
1072
1073                 if (auctum and not stropha):
1074                         clearit;
1075
1076                         fill get_subpath (diamond_shape,
1077                                           left,
1078                                           -dir (90 - off_angle),
1079                                           (0, 0))
1080                              .. get_subpath (circle,
1081                                              dir (90 + alpha),
1082                                              -dir (90 + alpha),
1083                                              z13)
1084                              .. get_subpath (circle,
1085                                              dir (90 - off_angle),
1086                                              right,
1087                                              z12)
1088                              -- cycle;
1089
1090                         labels (13);
1091                 fi;
1092
1093                 if (auctum and stropha):
1094                         clearit;
1095
1096                         save t;
1097
1098                         t := xpart ((stropha_ellipse shifted z11)
1099                                     intersectiontimes
1100                                     get_subpath (diamond_shape, up, right,
1101                                                  (0, 0)));
1102
1103                         % the `eps' is necessary so that we don't get the
1104                         % start of a straight line in the diamond shape
1105                         fill get_subpath (diamond_shape,
1106                                           dir (angle (z2 - z1) - eps),
1107                                           -dir (90 - off_angle),
1108                                           (0, 0))
1109                              .. get_subpath (circle,
1110                                              dir (90 + alpha),
1111                                              -dir (90 + alpha),
1112                                              z13)
1113                              .. get_subpath (stropha_ellipse,
1114                                              dir (90 - off_angle),
1115                                              direction t of stropha_ellipse,
1116                                              z11)
1117                              -- cycle;
1118
1119                         labels (11, 13);
1120                 fi;
1121         fet_endchar;
1122 enddef;
1123
1124
1125 % punctum
1126 punctum_char ("Ed. Vat. punctum", "vaticana.punctum",
1127               false, false, false, false,
1128               false, false, false, 1.0);
1129
1130
1131 % punctum cavum (for OpusTeX compatibility)
1132 punctum_char ("Ed. Vat. punctum cavum", "vaticana.punctum.cavum",
1133               false, true, false, false,
1134               false, false, false, 1.0);
1135
1136
1137 % linea punctum (for OpusTeX compatibility)
1138 punctum_char ("Ed. Vat. linea punctum", "vaticana.linea.punctum",
1139               true, false, false, false,
1140               false, false, false, 1.0);
1141
1142
1143 % linea punctum cavum (for OpusTeX compatibility)
1144 punctum_char ("Ed. Vat. linea punctum cavum", "vaticana.linea.punctum.cavum",
1145               true, true, false, false,
1146               false, false, false, 1.0);
1147
1148
1149 % punctum inclinatum
1150 inclinatum_char ("Ed. Vat. inclinatum", "vaticana.inclinatum",
1151                  false, false, false);
1152
1153
1154 % pes lower punctum
1155 punctum_char ("Ed. Vat. pes lower punctum", "vaticana.lpes",
1156               false, false, true, false,
1157               true, false, false, 1.0);
1158
1159
1160 % pes lower punctum
1161 punctum_char ("Ed. Vat. pes var lower punctum", "vaticana.vlpes",
1162               false, false, true, false,
1163               true, false, true, 1.0);
1164
1165
1166 % pes upper punctum
1167 punctum_char ("Ed. Vat. pes upper punctum", "vaticana.upes", 
1168               false, false, true, false,
1169               false, false, false, 1.0);
1170
1171
1172 % pes upper punctum (shifted variation)
1173 %
1174 % This note head is used instead of the regular pes upper punctum to
1175 % avoid collision with the lower punctum note of the pes when the upper
1176 % punctum sits directly on top of the lower punctum.
1177 %
1178 punctum_char ("Ed. Vat. var pes upper punctum", "vaticana.vupes",
1179               false, false, true, false,
1180               false, true, false, 1.0);
1181
1182
1183 % small punctum as used in epiphonus
1184 punctum_char ("Ed. Vat. plica", "vaticana.plica", 
1185               false, false, false, false,
1186               false, false, false, 0.6);
1187
1188
1189 % small punctum as used in epiphonus
1190 plica_char ("Ed. Vat. var plica", "vaticana.vplica", 
1191             false, 0.6);
1192
1193
1194 % eccentric punctum as used in epiphonus
1195 epiphonus_char ("Ed. Vat. epiphonus", "vaticana.epiphonus", 
1196                 false, true, false, 1.0);
1197
1198
1199 % eccentric punctum as used in epiphonus (shifted variation)
1200 %
1201 % This note head is used instead of the regular epiphonus punctum to
1202 % avoid collision with the plica head when the plica sits directly on
1203 % top of the lower head.
1204 %
1205 epiphonus_char ("Ed. Vat. var epiphonus", "vaticana.vepiphonus",
1206                 false, true, true, 1.0);
1207
1208
1209 % small punctum as used in cephalicus
1210 punctum_char ("Ed. Vat. rev. plica", "vaticana.reverse.plica",
1211               false, false, false, false,
1212               true, false, false, 0.6);
1213
1214
1215 % small punctum as used in cephalicus
1216 plica_char ("Ed. Vat. rev. var plica", "vaticana.reverse.vplica",
1217             true, 0.6);
1218
1219
1220 % eccentric punctum as used in cephalicus; without left stem
1221 epiphonus_char ("Ed. Vat. inner cephalicus", "vaticana.inner.cephalicus",
1222                 false, false, false, 1.0);
1223
1224
1225 % eccentric punctum as used in cephalicus; with left stem
1226 epiphonus_char ("Ed. Vat. cephalicus", "vaticana.cephalicus",
1227                 true, false, false, 1.0);
1228
1229
1230 % quilisma
1231 fet_beginchar ("Ed. Vat. quilisma", "svaticana.quilisma")
1232         save a_b, b_h, a_w;
1233
1234         a_b := 1.54; % b_h * a_b / a_w = wd / ht
1235         b_h := 0.85;
1236         a_w := 1.09;
1237
1238         save a, beta, ht, wd;
1239
1240         ht# = noteheight#;
1241         2 beta = ht# * b_h;
1242         a = beta * a_b;
1243         wd# = 2 a / a_w;
1244
1245         set_char_box (0, 0.42 wd#, 0.28 ht#, 0.36 ht#);
1246
1247         black_notehead_width# := wd#;
1248
1249         define_pixels (ht, wd);
1250
1251         pickup pencircle xscaled linethickness
1252                          yscaled 0.44 ht;
1253
1254         save ellipse;
1255         path ellipse;
1256
1257         ellipse := reverse fullcircle xscaled linethickness
1258                                       yscaled 0.44 ht;
1259
1260         z1 = (rt 0.00 wd, top -0.28 ht);
1261         z2 = (0.11 wd, -0.14 ht);
1262         z3 = (0.12 wd, +0.03 ht);
1263         z4 = (0.25 wd, -0.09 ht);
1264         z5 = (0.25 wd, +0.08 ht);
1265         z6 = (lft 0.42 wd, -0.04 ht);
1266         z7 = (lft 0.40 wd, bot +0.36 ht);
1267
1268         fill get_subpath (ellipse, z1 - z2, z2 - z1, z1)
1269              -- get_subpath (ellipse, z2 - z1, z1 - z2, z2)
1270              -- cycle;
1271         fill get_subpath (ellipse, z3 - z4, z4 - z3, z3)
1272              -- get_subpath (ellipse, z4 - z3, z3 - z4, z4)
1273              -- cycle;
1274         fill get_subpath (ellipse, z5 - z6, z6 - z5, z5)
1275              -- point 0 of get_subpath (ellipse, z6 - z5, z5 - z6, z6)
1276              -- get_subpath (ellipse, z7 - z6, z6 - z7, z7)
1277              -- get_subpath (ellipse, z6 - z7, z5 - z6, z6)
1278              -- cycle;
1279
1280         labels (1, 2, 3, 4, 5, 6, 7);
1281 fet_endchar;
1282
1283
1284 % solesmes punctum inclinatum parvum
1285 inclinatum_char ("Solesmes punctum inclinatum parvum", "solesmes.incl.parvum",
1286                  true, false, false);
1287
1288
1289 % solesmes punctum auctum ascendens
1290 punctum_char ("Solesmes punctum auctum ascendens", "solesmes.auct.asc",
1291               false, false, false, true,
1292               true, false, false, 1.0);
1293
1294
1295 % solesmes punctum auctum descendens
1296 punctum_char ("Solesmes punctum auctum descendens", "solesmes.auct.desc",
1297               false, false, false, true,
1298               false, false, false, 1.0);
1299
1300
1301 % solesmes punctum inclinatum auctum
1302 inclinatum_char ("Solesmes punctum incl. auctum", "solesmes.incl.auctum",
1303                  false, false, true);
1304
1305
1306 % solesmes stropha
1307 inclinatum_char ("Solesmes stropha", "solesmes.stropha",
1308                  false, true, false);
1309
1310
1311 % solesmes stropha aucta
1312 inclinatum_char ("Solesmes stropha aucta", "solesmes.stropha.aucta",
1313                  false, true, true);
1314
1315
1316 % solesmes oriscus
1317 fet_beginchar ("Solesmes oriscus", "ssolesmes.oriscus")
1318         save a_b, b_h, a_w;
1319
1320         a_b := 1.54; % b_h * a_b / a_w = wd / ht
1321         b_h := 0.85;
1322         a_w := 1.09;
1323
1324         save a, beta, ht, wd;
1325
1326         ht# = noteheight#;
1327         2 beta = ht# * b_h;
1328         a = beta * a_b;
1329         wd# = 2 a / a_w;
1330         black_notehead_width# := wd#;
1331
1332         save convexity;
1333
1334         convexity# = +0.05 ht#;
1335
1336         define_pixels (ht, wd, convexity);
1337
1338         set_char_box (0.00 wd#, 0.50 wd#,
1339                       0.25 ht# + convexity#, 0.25 ht# + convexity#);
1340
1341         z1 = (0.00 wd + blot_diameter / 2, -convexity);
1342         z2 = (1/6 wd, +convexity);
1343         z3 = (2/6 wd, -convexity);
1344         z4 = (0.50 wd - blot_diameter / 2, +convexity);
1345
1346         save height, ellipse;
1347         path ellipse;
1348
1349         height = 2 ypart (directionpoint right of (z1
1350                                                    .. z2
1351                                                    .. z3
1352                                                    .. z4));
1353
1354         pickup pencircle xscaled blot_diameter
1355                          yscaled (h + d - height);
1356
1357         ellipse := fullcircle xscaled blot_diameter
1358                               yscaled (h + d - height);
1359
1360         % Adjust vertical coordinates to touch bounding box.
1361         y1 := top -d;
1362         y4 := bot h;
1363
1364         save d_;
1365         pair d_;
1366
1367         d_ := direction 0 of (z1
1368                               .. z2
1369                               .. z3
1370                               .. z4);
1371
1372         fill get_subpath (ellipse, -d_, d_, z1)
1373              .. bot z2
1374              .. bot z3
1375              .. get_subpath (ellipse, d_, -d_, z4)
1376              .. top z3
1377              .. top z2
1378              .. cycle;
1379
1380         labels (1, 2, 3, 4);
1381 fet_endchar;
1382
1383
1384 %%%%%%%%
1385 %
1386 %
1387 %
1388 % EDITIO MEDICAEA
1389 %
1390 %
1391 %
1392
1393 % inclinatum
1394 fet_beginchar ("Ed. Med. inclinatum", "smedicaea.inclinatum")
1395         draw_diamond_head (1.2 staff_space#, 0, 0, 35, false);
1396 fet_endchar;
1397
1398
1399 def punctum_char (expr verbose_name, internal_name,
1400                        left_up_stem, left_down_stem) =
1401         fet_beginchar (verbose_name, "s" & internal_name);
1402                 save a, ht, wd;
1403
1404                 ht# = 2 staff_space#;
1405                 wd# = ht#;
1406                 black_notehead_width# := wd#;
1407
1408                 define_pixels (ht, wd);
1409
1410                 save ellipse;
1411                 path ellipse;
1412
1413                 ellipse := fullcircle xscaled blot_diameter
1414                                       yscaled 0.50 ht;
1415
1416                 z1 = (0.00 wd + blot_diameter / 2, 0);
1417                 z2 = (0.4 wd - blot_diameter / 2, 0);
1418
1419                 fill get_subpath (ellipse, left, right, z1)
1420                      -- get_subpath (ellipse, right, left, z2)
1421                      -- cycle;
1422
1423                 labels (1, 2);
1424
1425                 pickup pencircle scaled linethickness;
1426
1427                 if left_down_stem:
1428                         set_char_box (0.0, 0.4 wd#, 1.25 ht#, 0.25 ht#);
1429
1430                         z4 = (0.00 wd + linethickness / 2, blot_diameter / 2);
1431                         z5 = (0.00 wd + linethickness / 2, -1.25 ht);
1432
1433                         draw_block (lft z5, rt z4);
1434                 elseif left_up_stem:
1435                         set_char_box (0.0, 0.4 wd#, 0.25 ht#, 1.25 ht#);
1436
1437                         z4 = (0.00 wd + linethickness / 2, blot_diameter / 2);
1438                         z5 = (0.00 wd + linethickness / 2, +1.25 ht);
1439
1440                         draw_block (lft z4, rt z5);
1441                 else:
1442                         set_char_box (0.0, 0.4 wd#, 0.25 ht#, 0.25 ht#);
1443                 fi;
1444
1445                 labels (4, 5);
1446         fet_endchar;
1447 enddef;
1448
1449
1450 % punctum
1451 punctum_char ("Ed. Med. punctum", "medicaea.punctum", 
1452               false, false);
1453
1454
1455 % left up-stemmed punctum
1456 punctum_char ("Ed. Med. reverse virga", "medicaea.rvirga",
1457               true, false);
1458
1459
1460 % virga (i.e. left down-stemmed punctum)
1461 punctum_char ("Ed. Med. virga", "medicaea.virga", 
1462               false, true);
1463
1464
1465 %%%%%%%%
1466 %
1467 %
1468 %
1469 % HUFNAGEL
1470 %
1471 %
1472 %
1473
1474 def punctum_char (expr verbose_name, internal_name,
1475                        down_stem) =
1476         fet_beginchar (verbose_name, "s" & internal_name);
1477                 save alpha;
1478
1479                 alpha = 55;
1480
1481                 draw_diamond_head (staff_space#, 0, 0, alpha, false);
1482
1483                 if down_stem:
1484                         set_char_box (0, head_width#,
1485                                       1.5 staff_space#, head_height# / 2);
1486
1487                         save ellipse;
1488                         path ellipse;
1489
1490                         ellipse := reverse fullcircle xscaled blot_diameter
1491                                                       yscaled 0.7 staff_space
1492                                                       rotated -alpha;
1493
1494                         z11 = (head_width / 2, 0);
1495                         z12 = find_tangent_shift (((0, -d) -- (w, -d)), ellipse,
1496                                                   (w / 2, -d), (w / 2, 0));
1497
1498                         fill get_subpath (ellipse, up, down, z11)
1499                              -- get_subpath (ellipse, down, up, z12)
1500                              --cycle;
1501
1502                         labels (11, 12);
1503                 fi;
1504         fet_endchar;
1505 enddef;
1506
1507
1508 % punctum
1509 punctum_char ("Hufnagel punctum", "hufnagel.punctum", false)
1510
1511
1512 % virga
1513 punctum_char ("Hufnagel virga", "hufnagel.virga", true)
1514
1515
1516 % pes lower punctum
1517 fet_beginchar ("Hufnagel pes lower punctum", "shufnagel.lpes")
1518         save width, height, alpha;
1519
1520         width# = 2 * staff_space#;
1521         height# = 0.7 * staff_space#;
1522         alpha = 35;
1523
1524         set_char_box (0, width#, height# / 2, height# / 2);
1525
1526         define_pixels (width, height);
1527
1528         save circle;
1529         path circle;
1530
1531         circle := reverse fullcircle scaled linethickness;
1532
1533         pickup pencircle scaled linethickness;
1534
1535         rt x3 = -lft x1 = width / 2;
1536         y2 = y3 = height / 2;
1537         y1 = y4 = -height / 2;
1538
1539         tand (alpha) * (y2 - y1) = x2 - x1 = x3 - x4;
1540
1541         fill get_subpath (circle, left, z2 - z1, z1)
1542              -- get_subpath (circle, z2 - z1, right, z2)
1543              -- get_subpath (circle, right, z4 - z3, z3)
1544              -- get_subpath (circle, z4 - z3, left, z4)
1545              -- cycle;
1546
1547         currentpicture := currentpicture shifted (width/2, 0);
1548
1549 %       labels (1, 2, 3, 4);
1550 fet_endchar;
1551
1552
1553 fet_endgroup ("noteheads")