]> git.donarmstrong.com Git - lilypond.git/blob - mf/parmesan-heads.mf
Fix subpath construction.
[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 %
467 % This is the same as `get_subpath', except that the time values
468 % used to construct the resulting subpath are rounded to integers.
469 %
470 def get_subpath_i (expr curve, dir_in, dir_out, offset) =
471         begingroup;
472         save t_in, t_out;
473
474         t_in := directiontime dir_in of curve;
475         t_out := directiontime dir_out of curve;
476
477         if t_in > t_out:
478                 t_out := t_out + length curve;
479         fi;
480
481         (subpath (round t_in, round t_out) of curve) shifted offset
482         endgroup
483 enddef;
484
485
486 def draw_diamond_head (expr head_h, pen_w, pen_h, angle, open) =
487         save head_width, head_height;
488         save ellipse, ellipse_r;
489         path ellipse, ellipse_r, diamond_shape;
490
491         head_height# = head_h;
492         head_width# / head_height# = tand (angle);
493
494         set_char_box (0, head_width#,
495                       head_height# / 2, head_height# / 2);
496
497         charwx := head_width# / 2;
498         charwy := head_height# / 2 - linethickness#;
499
500         define_pixels (head_width, head_height);
501
502         ellipse := reverse fullcircle
503                      xscaled (max (blot_diameter, pen_w * head_width))
504                      yscaled (max (blot_diameter, pen_h * head_width))
505                      rotated -angle;
506
507         z1 = find_tangent_shift (((0, h) -- (0, -h)), ellipse,
508                                  (0, 0), (w / 2, 0));
509         z2 = find_tangent_shift (((0, h) -- (w, h)), ellipse,
510                                  (w / 2, h), (w / 2, 0));
511         z3 = find_tangent_shift (((w, h) -- (w, -h)), ellipse,
512                                  (w, 0), (w / 2, 0));
513         z4 = find_tangent_shift (((0, -h) -- (w, -h)), ellipse,
514                                  (w / 2, -h), (w / 2, 0));
515
516         diamond_shape := get_subpath (ellipse, z1 - z4, z2 - z1, z1)
517                          -- get_subpath (ellipse, z2 - z1, z3 - z2, z2)
518                          -- get_subpath (ellipse, z3 - z2, z4 - z3, z3)
519                          -- get_subpath (ellipse, z4 - z3, z1 - z4, z4)
520                          -- cycle;
521         fill diamond_shape;
522
523         if open:
524                 save l;
525                 path l[];
526
527                 l12 := (directionpoint (z1 - z2) of ellipse) shifted z1
528                         -- (directionpoint (z1 - z2) of ellipse) shifted z2;
529                 l23 := (directionpoint (z2 - z3) of ellipse) shifted z2
530                         -- (directionpoint (z2 - z3) of ellipse) shifted z3;
531                 l34 := (directionpoint (z3 - z4) of ellipse) shifted z3
532                         -- (directionpoint (z3 - z4) of ellipse) shifted z4;
533                 l41 := (directionpoint (z4 - z1) of ellipse) shifted z4
534                         -- (directionpoint (z4 - z1) of ellipse) shifted z1;
535
536                 unfill l12 intersectionpoint l23
537                        -- l23 intersectionpoint l34
538                        -- l34 intersectionpoint l41
539                        -- l41 intersectionpoint l12
540                        -- cycle;
541         fi;
542
543         labels (1, 2, 3, 4);
544 enddef;
545
546
547 fet_beginchar ("Mensural semibrevis head", "s0mensural");
548         draw_diamond_head (staff_space#, 0.15, 0.30, 30, true);
549 fet_endchar;
550
551
552 fet_beginchar ("Mensural minima head", "s1mensural");
553         draw_diamond_head (staff_space#, 0.15, 0.30, 30, true);
554 fet_endchar;
555
556
557 fet_beginchar ("Mensural semiminima head", "s2mensural");
558         draw_diamond_head (staff_space#, 0.15, 0.30, 30, false);
559 fet_endchar;
560
561
562 fet_beginchar ("Petrucci semibrevis head", "s0petrucci");
563 %       draw_diamond_head (1.8 staff_space#, 0.15, 0.40, 30, true);
564         draw_neomensural_open_head (staff_space#, 1.8 staff_space#);
565 fet_endchar;
566
567
568 fet_beginchar ("Petrucci minima head", "s1petrucci");
569 %       draw_diamond_head (1.8 staff_space#, 0.15, 0.40, 30, true);
570         draw_neomensural_open_head (staff_space#, 1.8 staff_space#);
571 fet_endchar;
572
573
574 fet_beginchar ("Petrucci semiminima head", "s2petrucci");
575 %       draw_diamond_head (1.8 staff_space#, 0.15, 0.40, 30, false);
576         draw_neomensural_black_head (staff_space#, 1.8 staff_space#);
577 fet_endchar;
578
579
580 %%%%%%%%
581 %
582 %
583 %
584 % EDITIO VATICANA (including solesmes extensions)
585 %
586 %
587 %
588
589 def punctum_char (expr verbose_name, internal_name,
590                        linea, cavum, straight, auctum,
591                        d_up, up_shift, down_shift, mag) =
592         fet_beginchar (verbose_name, "s" & internal_name);
593                 save a_b, b_h, a_w;
594
595                 a_b := 1.54; % b_h * a_b / a_w = wd / ht
596                 b_h := 0.85;
597                 a_w := 1.09;
598
599                 save a, beta, ht, wd;
600
601                 ht# = noteheight# * mag;
602                 2 beta = ht# * b_h;
603                 a = beta * a_b;
604                 wd# = 2 a / a_w;
605                 black_notehead_width# := wd#;
606
607                 % direction
608                 save d_, d_sign;
609                 pair d_;
610
611                 if d_up:
612                         d_ := up;
613                         d_sign := 1;
614                 else:
615                         d_ := down;
616                         d_sign := -1;
617                 fi;
618
619                 % convexity and eccentricity
620                 save u_convexity, u_eccentricity;
621
622                 if straight:
623                         u_convexity# := -0.01 ht#;
624                         u_eccentricity# := 0.0 ht#; % dummy
625                 elseif auctum:
626                         u_convexity# := -0.03 ht#;
627                         u_eccentricity# := +0.25 ht#;
628                 else:
629                         u_convexity# := -0.05 ht#;
630                         u_eccentricity# := 0.0 ht#; % dummy
631                 fi;
632
633                 save convexity, eccentricity;
634
635                 convexity# := d_sign * u_convexity#;
636                 eccentricity# := d_sign * u_eccentricity#;
637
638                 % y shift offset
639                 save yoffs;
640
641                 if up_shift:
642                         yoffs# := 0.08 ht#;
643                 elseif down_shift:
644                         yoffs# := -0.11 ht#;
645                 else:
646                         yoffs# := 0.00 ht#;
647                 fi;
648
649                 define_pixels (convexity, eccentricity, yoffs, ht, wd);
650
651                 pickup pencircle scaled linethickness;
652
653                 save height, yoffs_bt, p, circle, circle_r;
654                 path p, circle, circle_r;
655
656                 height# = 0.47 ht#;
657                 yoffs_bt# = yoffs# - 0.5 height# - 0.25 convexity#;
658
659                 define_pixels (height, yoffs_bt);
660
661                 circle := fullcircle scaled linethickness;
662
663                 x1 = x6;
664                 x2 = x5;
665                 x3 = x4;
666                 y1 + height = y6;
667                 y2 + height = y5;
668                 y3 + height = y4;
669
670                 save box_top, box_bt;
671
672                 if auctum:
673                         z1 = (0.00 wd + linethickness / 2, yoffs_bt);
674                         z2 = (0.21 wd, yoffs_bt + convexity);
675                         z3 = (0.42 wd - linethickness/ 2,
676                               yoffs_bt + eccentricity);
677                         box_top# = height# + yoffs_bt# +
678                                      max (0, convexity#, eccentricity#);
679                         box_bt# = yoffs_bt# +
680                                      min (0, convexity#, eccentricity#);
681                         p = z1
682                             .. {right}z2
683                             .. {d_}z3
684                             -- z4{-d_}
685                             .. z5{left}
686                             .. z6
687                             -- cycle;
688                 else:
689                         z1 = (0.00 wd + linethickness / 2, yoffs_bt);
690                         z2 = (0.21 wd, yoffs_bt + convexity);
691                         z3 = (0.42 wd - linethickness / 2, yoffs_bt);
692                         box_top# = height# + yoffs_bt# + max (0, convexity#);
693                         box_bt# = yoffs_bt# + min (0, convexity#);
694                         p = z1
695                             .. z2
696                             .. z3
697                             -- z4
698                             .. z5
699                             .. z6
700                             -- cycle;
701                 fi;
702
703                 labels (1, 2, 3, 4, 5, 6);
704
705                 save dirs;
706                 pair dirs[];
707
708                 dirs12 := direction (0 + epsilon) of p;
709                 dirs2 := direction 1 of p;
710                 dirs32 := direction (2 - epsilon) of p;
711                 dirs45 := direction (3 + epsilon) of p;
712                 dirs5 := direction 4 of p;
713                 dirs65 := direction (5 - epsilon) of p;
714
715                 fill get_subpath (circle, down, dirs12, z1)
716                      .. (bot z2){dirs2}
717                      .. get_subpath (circle, dirs32, up, z3)
718                      -- get_subpath (circle, up, dirs45, z4)
719                      .. (top z5){dirs5}
720                      .. get_subpath (circle, dirs65, down, z6)
721                      -- cycle;
722
723                 if cavum:
724                         save pat, t;
725                         path pat[];
726                         numeric t[];
727
728                         pat123 := ((directionpoint -dirs12 of circle)
729                                     shifted z1){dirs12}
730                                   .. (top z2){dirs2}
731                                   .. {dirs32}((directionpoint -dirs32 of circle)
732                                        shifted z3);
733                         pat34 := lft z3
734                                  -- lft z4;
735                         pat456 := ((directionpoint -dirs45 of circle)
736                                     shifted z4){dirs45}
737                                   .. (bot z5){dirs5}
738                                   .. {dirs65}((directionpoint -dirs65 of circle)
739                                        shifted z6);
740                         pat61 := rt z6
741                                  -- rt z1;
742
743                         t61 := ypart (pat61 intersectiontimes pat123);
744                         t12 := xpart (pat123 intersectiontimes pat34);
745                         t34 := ypart (pat34 intersectiontimes pat456);
746                         t45 := xpart (pat456 intersectiontimes pat61);
747
748                         unfill subpath (t61, t12) of pat123
749                                -- subpath (t34, t45) of pat456
750                                -- cycle;
751                 fi;
752
753                 set_char_box (0.00 wd#, 0.42 wd#,
754                               max (0, -box_bt#) + linethickness# / 2,
755                               max (0, box_top#) + linethickness# / 2);
756
757                 if linea:
758                         save linea_width, linea_height;
759
760                         linea_width# = 0.6 linethickness#;
761                         linea_height# = 0.7 ht#;
762
763                         define_pixels (linea_width, linea_height);
764
765                         pickup pencircle scaled 0.6 linethickness;
766
767                         draw_block ((-0.10 wd - linea_width / 2,
768                                      -linea_height / 2),
769                                     (-0.10 wd + linea_width / 2,
770                                      +linea_height / 2));
771                         draw_block ((+0.52 wd - linea_width / 2,
772                                      -linea_height / 2),
773                                     (+0.52 wd + linea_width / 2,
774                                      +linea_height / 2));
775
776                         set_char_box (0, 0.62 wd# + linea_width#,
777                                       linea_height# / 2,
778                                       linea_height# / 2);
779
780                         currentpicture := currentpicture
781                                 shifted (0.10 wd + linea_width / 2, 0);
782                 fi;
783         fet_endchar;
784 enddef;
785
786
787 def plica_char (expr verbose_name, internal_name,
788                      d_up, mag) =
789         fet_beginchar (verbose_name, "s" & internal_name);
790                 save a_b, b_h, a_w;
791
792                 a_b := 1.54; % b_h * a_b / a_w = wd / ht
793                 b_h := 0.85;
794                 a_w := 1.09;
795
796                 save a, beta, ht, wd;
797
798                 ht# = noteheight# * mag;
799                 2 beta = ht# * b_h;
800                 a = beta * a_b;
801                 wd# = 2 a / a_w;
802                 black_notehead_width# := wd#;
803
804                 % direction
805                 save d_, d_sign;
806                 pair d_;
807
808                 if d_up:
809                         d_ := up;
810                         d_sign := 1;
811                 else:
812                         d_ := down;
813                         d_sign := -1;
814                 fi;
815
816                 % convexity and eccentricity
817                 save convexity, eccentricity;
818
819                 convexity# := d_sign * -0.10 ht#;
820                 eccentricity# := d_sign * -0.12 ht#;
821
822                 % y shift offset
823                 save yoffs;
824
825                 yoffs# := -0.11 ht#;
826
827                 define_pixels (convexity, eccentricity, yoffs, ht, wd);
828
829                 pickup pencircle scaled linethickness;
830
831                 save height, yoffs_bt, p, circle, circle_r;
832                 path p, circle, circle_r;
833
834                 height# = 0.47 ht#;
835                 yoffs_bt# = yoffs# - 0.5 height# - 0.25 convexity#;
836
837                 define_pixels (height, yoffs_bt);
838
839                 circle := fullcircle scaled linethickness;
840
841                 x1 = x6;
842                 x2 = x5;
843                 x3 = x4;
844                 y1 + height = y6;
845                 y2 + height = y5;
846                 y3 + height = y4;
847
848                 save box_top, box_bt;
849
850                 z1 = (0.00 wd + linethickness / 2, yoffs_bt);
851                 z2 = (0.21 wd, yoffs_bt + convexity);
852                 z3 = (0.42 wd - linethickness/ 2, yoffs_bt + eccentricity);
853                 box_top# = height# + yoffs_bt# +
854                              max (0, convexity#, eccentricity#);
855                 box_bt# = yoffs_bt# +
856                              min (0, convexity#, eccentricity#);
857                 p = z1
858                     .. z2{right}
859                     .. z3
860                     -- z4
861                     .. z5{left}
862                     .. z6
863                     -- cycle;
864
865                 labels (1, 2, 3, 4, 5, 6);
866
867                 save dirs;
868                 pair dirs[];
869
870                 dirs12 := direction (0 + epsilon) of p;
871                 dirs2 := direction 1 of p;
872                 dirs32 := direction (2 - epsilon) of p;
873                 dirs45 := direction (3 + epsilon) of p;
874                 dirs5 := direction 4 of p;
875                 dirs65 := direction (5 - epsilon) of p;
876
877                 fill get_subpath (circle, down, dirs12, z1)
878                      .. (bot z2){dirs2}
879                      .. get_subpath (circle, dirs32, up, z3)
880                      -- get_subpath (circle, up, dirs45, z4)
881                      .. (top z5){dirs5}
882                      .. get_subpath (circle, dirs65, down, z6)
883                      -- cycle;
884
885                 pickup pencircle scaled 0.6 linethickness;
886
887                 save stem_bt;
888
889                 set_char_box (0.00 wd#, 0.42 wd#,
890                               max (0, -box_bt#) + linethickness# / 2,
891                               max (0, box_top#) + linethickness# / 2);
892
893         fet_endchar;
894 enddef;
895
896
897 def epiphonus_char (expr verbose_name, internal_name,
898                          left_stem, d_up, down_shift, mag) =
899         fet_beginchar (verbose_name, "s" & internal_name);
900                 save a_b, b_h, a_w;
901
902                 a_b := 1.54; % b_h * a_b / a_w = wd / ht
903                 b_h := 0.85;
904                 a_w := 1.09;
905
906                 save a, beta, ht, wd;
907
908                 ht# = noteheight# * mag;
909                 2 beta = ht# * b_h;
910                 a = beta * a_b;
911                 wd# = 2 a / a_w;
912                 black_notehead_width# := wd#;
913
914                 % direction
915                 save d_, d_sign;
916                 pair d_;
917
918                 if d_up:
919                         d_ := up;
920                         d_sign := 1;
921                 else:
922                         d_ := down;
923                         d_sign := -1;
924                 fi;
925
926                 % convexity and eccentricity
927                 save convexity;
928
929                 convexity# := d_sign * -0.05ht#;
930
931                 % y shift offset
932                 save yoffs;
933
934                 if down_shift:
935                         yoffs# := -0.11 ht#;
936                 else:
937                         yoffs# := 0.00 ht#;
938                 fi;
939
940                 define_pixels (convexity, yoffs, ht, wd);
941
942                 pickup pencircle scaled linethickness;
943
944                 save height, yoffs_bt, p, circle, circle_r;
945                 path p, circle, circle_r;
946
947                 height# = 0.47 ht#;
948                 yoffs_bt# = yoffs# - 0.5 height# - 0.25 convexity#;
949
950                 define_pixels (height, yoffs_bt);
951
952                 circle := fullcircle scaled linethickness;
953
954                 x1 = x6;
955                 x2 = x5;
956                 x3 = x4;
957                 y1 + height = y6;
958                 y2 + height = y5;
959                 y3 + height = y4;
960
961                 save box_top, box_bt;
962
963                 z1 = (0.00 wd + linethickness / 2, yoffs_bt - 2.5 convexity);
964                 z2 = (0.06 wd, yoffs_bt + 1.4 convexity);
965                 z3 = (0.42 wd - linethickness / 2, yoffs_bt - 1.0 convexity);
966                 box_top# = height# + yoffs_bt# +
967                              max (-1.0 convexity#, 1.4 convexity#, 0);
968                 box_bt# = yoffs_bt# +
969                              min (-1.0 convexity#, 1.4 convexity#, 0);
970                 p = z1{-d_}
971                     .. {curl 1}z2{right}
972                     .. z3
973                     -- z4
974                     .. {left}z5{curl 1}
975                     .. {d_}z6
976                     -- cycle;
977
978                 labels (1, 2, 3, 4, 5, 6);
979
980                 save dirs;
981                 pair dirs[];
982
983                 dirs12 := direction (0 + epsilon) of p;
984                 dirs21 := direction (1 - epsilon) of p;
985                 dirs23 := direction (1 + epsilon) of p;
986                 dirs32 := direction (2 - epsilon) of p;
987                 dirs45 := direction (3 + epsilon) of p;
988                 dirs54 := direction (4 - epsilon) of p;
989                 dirs56 := direction (4 + epsilon) of p;
990                 dirs65 := direction (5 - epsilon) of p;
991
992                 fill get_subpath (circle, down, dirs12, z1)
993                      .. get_subpath (circle, dirs21, dirs23, z2)
994                      .. get_subpath (circle, dirs32, up, z3)
995                      -- get_subpath (circle, up, dirs45, z4)
996                      .. get_subpath (circle, dirs54, dirs56, z5)
997                      .. get_subpath (circle, dirs65, down, z6)
998                      -- cycle;
999
1000                 pickup pencircle scaled 0.6 linethickness;
1001
1002                 save stem_bt;
1003
1004                 if left_stem:
1005                         z11 = (0.00 wd + 0.6 linethickness / 2, yoffs - 1.1 ht);
1006                         z12 = (0.00 wd + 0.6 linethickness / 2, yoffs);
1007                         draw_block ((0, yoffs - 1.1 ht - linethickness / 2),
1008                                     (0.6 linethickness, yoffs));
1009                         stem_bt# = yoffs# - 1.1 ht#;
1010                 else:
1011                         stem_bt# = 0;
1012                 fi;
1013
1014                 set_char_box (0.00 wd#, 0.42 wd#,
1015                               max (0, -box_bt#, -stem_bt#) + linethickness# / 2,
1016                               max (0, box_top#) + linethickness# / 2);
1017         fet_endchar;
1018 enddef;
1019
1020
1021 def inclinatum_char (expr verbose_name, internal_name,
1022                           small, stropha, auctum) =
1023         fet_beginchar (verbose_name, "s" & internal_name)
1024                 save ht, alpha;
1025
1026                 alpha := 35;
1027
1028                 if small:
1029                         ht# = 0.50 noteheight#;
1030                 else:
1031                         ht# = 0.80 noteheight#;
1032                 fi;
1033
1034                 draw_diamond_head (ht#, 0, 0, alpha, false);
1035
1036                 save off_angle;
1037
1038                 off_angle := alpha + 15;
1039
1040                 save stropha_ellipse, auctum_hook, circle;
1041                 path stropha_ellipse, auctum_hook, circle;
1042
1043                 circle := reverse fullcircle scaled linethickness;
1044
1045                 stropha_ellipse := fullcircle xscaled 0.25 head_height
1046                                               yscaled 0.55 head_height
1047                                               rotated alpha;
1048
1049                 z11 = z12
1050                       + linethickness / 2 * dir (180 - off_angle)
1051                       - directionpoint dir (90 - off_angle)
1052                           of stropha_ellipse;
1053                 z12 = directionpoint -dir (90 - off_angle) of diamond_shape +
1054                         linethickness / 2 * dir (180 - off_angle);
1055                 z13 = (0, -0.5 head_height + linethickness);
1056
1057                 auctum_hook := z12{-dir (90 - off_angle)}
1058                                .. {dir (90 + alpha)}z13;
1059
1060                 labels (12);
1061
1062                 if (stropha and not auctum):
1063                         clearit;
1064
1065                         save t_in, t_out;
1066
1067                         t_in := xpart ((stropha_ellipse shifted z11)
1068                                        intersectiontimes
1069                                        get_subpath (diamond_shape,
1070                                                     left, up,
1071                                                     (0, 0)));
1072                         t_out := xpart ((stropha_ellipse shifted z11)
1073                                         intersectiontimes
1074                                         get_subpath (diamond_shape,
1075                                                      up, right,
1076                                                      (0, 0)));
1077
1078                         % the addition or subtraction of `1' is necessary
1079                         % so that we get the right starting point
1080                         fill get_subpath_i (diamond_shape,
1081                                             dir (angle (z2 - z1) - 1),
1082                                             dir (angle (z1 - z4) + 1),
1083                                             (0, 0))
1084                              -- get_subpath (stropha_ellipse,
1085                                              direction t_in of stropha_ellipse,
1086                                              direction t_out of stropha_ellipse,
1087                                              z11)
1088                              -- cycle;
1089
1090                         labels (11);
1091                 fi;
1092
1093                 if (auctum and not stropha):
1094                         clearit;
1095
1096                         fill get_subpath (diamond_shape,
1097                                           left,
1098                                           -dir (90 - off_angle),
1099                                           (0, 0))
1100                              .. get_subpath (circle,
1101                                              dir (90 + alpha),
1102                                              -dir (90 + alpha),
1103                                              z13)
1104                              .. get_subpath (circle,
1105                                              dir (90 - off_angle),
1106                                              right,
1107                                              z12)
1108                              -- cycle;
1109
1110                         labels (13);
1111                 fi;
1112
1113                 if (auctum and stropha):
1114                         clearit;
1115
1116                         save t;
1117
1118                         t := xpart ((stropha_ellipse shifted z11)
1119                                     intersectiontimes
1120                                     get_subpath (diamond_shape, up, right,
1121                                                  (0, 0)));
1122
1123                         % the addition or subtraction of `1' is necessary
1124                         % so that we get the right starting point
1125                         fill get_subpath_i (diamond_shape,
1126                                             dir (angle (z2 - z1) - 1),
1127                                             -dir (90 - off_angle),
1128                                             (0, 0))
1129                              .. get_subpath (circle,
1130                                              dir (90 + alpha),
1131                                              -dir (90 + alpha),
1132                                              z13)
1133                              .. get_subpath (stropha_ellipse,
1134                                              dir (90 - off_angle),
1135                                              direction t of stropha_ellipse,
1136                                              z11)
1137                              -- cycle;
1138
1139                         labels (11, 13);
1140                 fi;
1141         fet_endchar;
1142 enddef;
1143
1144
1145 % punctum
1146 punctum_char ("Ed. Vat. punctum", "vaticana.punctum",
1147               false, false, false, false,
1148               false, false, false, 1.0);
1149
1150
1151 % punctum cavum (for OpusTeX compatibility)
1152 punctum_char ("Ed. Vat. punctum cavum", "vaticana.punctum.cavum",
1153               false, true, false, false,
1154               false, false, false, 1.0);
1155
1156
1157 % linea punctum (for OpusTeX compatibility)
1158 punctum_char ("Ed. Vat. linea punctum", "vaticana.linea.punctum",
1159               true, false, false, false,
1160               false, false, false, 1.0);
1161
1162
1163 % linea punctum cavum (for OpusTeX compatibility)
1164 punctum_char ("Ed. Vat. linea punctum cavum", "vaticana.linea.punctum.cavum",
1165               true, true, false, false,
1166               false, false, false, 1.0);
1167
1168
1169 % punctum inclinatum
1170 inclinatum_char ("Ed. Vat. inclinatum", "vaticana.inclinatum",
1171                  false, false, false);
1172
1173
1174 % pes lower punctum
1175 punctum_char ("Ed. Vat. pes lower punctum", "vaticana.lpes",
1176               false, false, true, false,
1177               true, false, false, 1.0);
1178
1179
1180 % pes lower punctum
1181 punctum_char ("Ed. Vat. pes var lower punctum", "vaticana.vlpes",
1182               false, false, true, false,
1183               true, false, true, 1.0);
1184
1185
1186 % pes upper punctum
1187 punctum_char ("Ed. Vat. pes upper punctum", "vaticana.upes", 
1188               false, false, true, false,
1189               false, false, false, 1.0);
1190
1191
1192 % pes upper punctum (shifted variation)
1193 %
1194 % This note head is used instead of the regular pes upper punctum to
1195 % avoid collision with the lower punctum note of the pes when the upper
1196 % punctum sits directly on top of the lower punctum.
1197 %
1198 punctum_char ("Ed. Vat. var pes upper punctum", "vaticana.vupes",
1199               false, false, true, false,
1200               false, true, false, 1.0);
1201
1202
1203 % small punctum as used in epiphonus
1204 punctum_char ("Ed. Vat. plica", "vaticana.plica", 
1205               false, false, false, false,
1206               false, false, false, 0.6);
1207
1208
1209 % small punctum as used in epiphonus
1210 plica_char ("Ed. Vat. var plica", "vaticana.vplica", 
1211             false, 0.6);
1212
1213
1214 % eccentric punctum as used in epiphonus
1215 epiphonus_char ("Ed. Vat. epiphonus", "vaticana.epiphonus", 
1216                 false, true, false, 1.0);
1217
1218
1219 % eccentric punctum as used in epiphonus (shifted variation)
1220 %
1221 % This note head is used instead of the regular epiphonus punctum to
1222 % avoid collision with the plica head when the plica sits directly on
1223 % top of the lower head.
1224 %
1225 epiphonus_char ("Ed. Vat. var epiphonus", "vaticana.vepiphonus",
1226                 false, true, true, 1.0);
1227
1228
1229 % small punctum as used in cephalicus
1230 punctum_char ("Ed. Vat. rev. plica", "vaticana.reverse.plica",
1231               false, false, false, false,
1232               true, false, false, 0.6);
1233
1234
1235 % small punctum as used in cephalicus
1236 plica_char ("Ed. Vat. rev. var plica", "vaticana.reverse.vplica",
1237             true, 0.6);
1238
1239
1240 % eccentric punctum as used in cephalicus; without left stem
1241 epiphonus_char ("Ed. Vat. inner cephalicus", "vaticana.inner.cephalicus",
1242                 false, false, false, 1.0);
1243
1244
1245 % eccentric punctum as used in cephalicus; with left stem
1246 epiphonus_char ("Ed. Vat. cephalicus", "vaticana.cephalicus",
1247                 true, false, false, 1.0);
1248
1249
1250 % quilisma
1251 fet_beginchar ("Ed. Vat. quilisma", "svaticana.quilisma")
1252         save a_b, b_h, a_w;
1253
1254         a_b := 1.54; % b_h * a_b / a_w = wd / ht
1255         b_h := 0.85;
1256         a_w := 1.09;
1257
1258         save a, beta, ht, wd;
1259
1260         ht# = noteheight#;
1261         2 beta = ht# * b_h;
1262         a = beta * a_b;
1263         wd# = 2 a / a_w;
1264
1265         set_char_box (0, 0.42 wd#, 0.28 ht#, 0.36 ht#);
1266
1267         black_notehead_width# := wd#;
1268
1269         define_pixels (ht, wd);
1270
1271         pickup pencircle xscaled linethickness
1272                          yscaled 0.44 ht;
1273
1274         save ellipse;
1275         path ellipse;
1276
1277         ellipse := reverse fullcircle xscaled linethickness
1278                                       yscaled 0.44 ht;
1279
1280         z1 = (rt 0.00 wd, top -0.28 ht);
1281         z2 = (0.11 wd, -0.14 ht);
1282         z3 = (0.12 wd, +0.03 ht);
1283         z4 = (0.25 wd, -0.09 ht);
1284         z5 = (0.25 wd, +0.08 ht);
1285         z6 = (lft 0.42 wd, -0.04 ht);
1286         z7 = (lft 0.40 wd, bot +0.36 ht);
1287
1288         fill get_subpath (ellipse, z1 - z2, z2 - z1, z1)
1289              -- get_subpath (ellipse, z2 - z1, z1 - z2, z2)
1290              -- cycle;
1291         fill get_subpath (ellipse, z3 - z4, z4 - z3, z3)
1292              -- get_subpath (ellipse, z4 - z3, z3 - z4, z4)
1293              -- cycle;
1294         fill get_subpath (ellipse, z5 - z6, z6 - z5, z5)
1295              -- point 0 of get_subpath (ellipse, z6 - z5, z5 - z6, z6)
1296              -- get_subpath (ellipse, z7 - z6, z6 - z7, z7)
1297              -- get_subpath (ellipse, z6 - z7, z5 - z6, z6)
1298              -- cycle;
1299
1300         labels (1, 2, 3, 4, 5, 6, 7);
1301 fet_endchar;
1302
1303
1304 % solesmes punctum inclinatum parvum
1305 inclinatum_char ("Solesmes punctum inclinatum parvum", "solesmes.incl.parvum",
1306                  true, false, false);
1307
1308
1309 % solesmes punctum auctum ascendens
1310 punctum_char ("Solesmes punctum auctum ascendens", "solesmes.auct.asc",
1311               false, false, false, true,
1312               true, false, false, 1.0);
1313
1314
1315 % solesmes punctum auctum descendens
1316 punctum_char ("Solesmes punctum auctum descendens", "solesmes.auct.desc",
1317               false, false, false, true,
1318               false, false, false, 1.0);
1319
1320
1321 % solesmes punctum inclinatum auctum
1322 inclinatum_char ("Solesmes punctum incl. auctum", "solesmes.incl.auctum",
1323                  false, false, true);
1324
1325
1326 % solesmes stropha
1327 inclinatum_char ("Solesmes stropha", "solesmes.stropha",
1328                  false, true, false);
1329
1330
1331 % solesmes stropha aucta
1332 inclinatum_char ("Solesmes stropha aucta", "solesmes.stropha.aucta",
1333                  false, true, true);
1334
1335
1336 % solesmes oriscus
1337 fet_beginchar ("Solesmes oriscus", "ssolesmes.oriscus")
1338         save a_b, b_h, a_w;
1339
1340         a_b := 1.54; % b_h * a_b / a_w = wd / ht
1341         b_h := 0.85;
1342         a_w := 1.09;
1343
1344         save a, beta, ht, wd;
1345
1346         ht# = noteheight#;
1347         2 beta = ht# * b_h;
1348         a = beta * a_b;
1349         wd# = 2 a / a_w;
1350         black_notehead_width# := wd#;
1351
1352         save convexity;
1353
1354         convexity# = +0.05 ht#;
1355
1356         define_pixels (ht, wd, convexity);
1357
1358         set_char_box (0.00 wd#, 0.50 wd#,
1359                       0.25 ht# + convexity#, 0.25 ht# + convexity#);
1360
1361         z1 = (0.00 wd + blot_diameter / 2, -convexity);
1362         z2 = (1/6 wd, +convexity);
1363         z3 = (2/6 wd, -convexity);
1364         z4 = (0.50 wd - blot_diameter / 2, +convexity);
1365
1366         save height, ellipse;
1367         path ellipse;
1368
1369         height = 2 ypart (directionpoint right of (z1
1370                                                    .. z2
1371                                                    .. z3
1372                                                    .. z4));
1373
1374         pickup pencircle xscaled blot_diameter
1375                          yscaled (h + d - height);
1376
1377         ellipse := fullcircle xscaled blot_diameter
1378                               yscaled (h + d - height);
1379
1380         % Adjust vertical coordinates to touch bounding box.
1381         y1 := top -d;
1382         y4 := bot h;
1383
1384         save d_;
1385         pair d_;
1386
1387         d_ := direction 0 of (z1
1388                               .. z2
1389                               .. z3
1390                               .. z4);
1391
1392         fill get_subpath (ellipse, -d_, d_, z1)
1393              .. bot z2
1394              .. bot z3
1395              .. get_subpath (ellipse, d_, -d_, z4)
1396              .. top z3
1397              .. top z2
1398              .. cycle;
1399
1400         labels (1, 2, 3, 4);
1401 fet_endchar;
1402
1403
1404 %%%%%%%%
1405 %
1406 %
1407 %
1408 % EDITIO MEDICAEA
1409 %
1410 %
1411 %
1412
1413 % inclinatum
1414 fet_beginchar ("Ed. Med. inclinatum", "smedicaea.inclinatum")
1415         draw_diamond_head (1.2 staff_space#, 0, 0, 35, false);
1416 fet_endchar;
1417
1418
1419 def punctum_char (expr verbose_name, internal_name,
1420                        left_up_stem, left_down_stem) =
1421         fet_beginchar (verbose_name, "s" & internal_name);
1422                 save a, ht, wd;
1423
1424                 ht# = 2 staff_space#;
1425                 wd# = ht#;
1426                 black_notehead_width# := wd#;
1427
1428                 define_pixels (ht, wd);
1429
1430                 save ellipse;
1431                 path ellipse;
1432
1433                 ellipse := fullcircle xscaled blot_diameter
1434                                       yscaled 0.50 ht;
1435
1436                 z1 = (0.00 wd + blot_diameter / 2, 0);
1437                 z2 = (0.4 wd - blot_diameter / 2, 0);
1438
1439                 fill get_subpath (ellipse, left, right, z1)
1440                      -- get_subpath (ellipse, right, left, z2)
1441                      -- cycle;
1442
1443                 labels (1, 2);
1444
1445                 pickup pencircle scaled linethickness;
1446
1447                 if left_down_stem:
1448                         set_char_box (0.0, 0.4 wd#, 1.25 ht#, 0.25 ht#);
1449
1450                         z4 = (0.00 wd + linethickness / 2, blot_diameter / 2);
1451                         z5 = (0.00 wd + linethickness / 2, -1.25 ht);
1452
1453                         draw_block (lft z5, rt z4);
1454                 elseif left_up_stem:
1455                         set_char_box (0.0, 0.4 wd#, 0.25 ht#, 1.25 ht#);
1456
1457                         z4 = (0.00 wd + linethickness / 2, -blot_diameter / 2);
1458                         z5 = (0.00 wd + linethickness / 2, +1.25 ht);
1459
1460                         draw_block (lft z4, rt z5);
1461                 else:
1462                         set_char_box (0.0, 0.4 wd#, 0.25 ht#, 0.25 ht#);
1463                 fi;
1464
1465                 labels (4, 5);
1466         fet_endchar;
1467 enddef;
1468
1469
1470 % punctum
1471 punctum_char ("Ed. Med. punctum", "medicaea.punctum", 
1472               false, false);
1473
1474
1475 % left up-stemmed punctum
1476 punctum_char ("Ed. Med. reverse virga", "medicaea.rvirga",
1477               true, false);
1478
1479
1480 % virga (i.e. left down-stemmed punctum)
1481 punctum_char ("Ed. Med. virga", "medicaea.virga", 
1482               false, true);
1483
1484
1485 %%%%%%%%
1486 %
1487 %
1488 %
1489 % HUFNAGEL
1490 %
1491 %
1492 %
1493
1494 def punctum_char (expr verbose_name, internal_name,
1495                        down_stem) =
1496         fet_beginchar (verbose_name, "s" & internal_name);
1497                 save alpha;
1498
1499                 alpha = 55;
1500
1501                 draw_diamond_head (staff_space#, 0, 0, alpha, false);
1502
1503                 if down_stem:
1504                         set_char_box (0, head_width#,
1505                                       1.5 staff_space#, head_height# / 2);
1506
1507                         save ellipse;
1508                         path ellipse;
1509
1510                         ellipse := reverse fullcircle xscaled blot_diameter
1511                                                       yscaled 0.7 staff_space
1512                                                       rotated -alpha;
1513
1514                         z11 = (head_width / 2, 0);
1515                         z12 = find_tangent_shift (((0, -d) -- (w, -d)), ellipse,
1516                                                   (w / 2, -d), (w / 2, 0));
1517
1518                         fill get_subpath (ellipse, up, down, z11)
1519                              -- get_subpath (ellipse, down, up, z12)
1520                              --cycle;
1521
1522                         labels (11, 12);
1523                 fi;
1524         fet_endchar;
1525 enddef;
1526
1527
1528 % punctum
1529 punctum_char ("Hufnagel punctum", "hufnagel.punctum", false)
1530
1531
1532 % virga
1533 punctum_char ("Hufnagel virga", "hufnagel.virga", true)
1534
1535
1536 % pes lower punctum
1537 fet_beginchar ("Hufnagel pes lower punctum", "shufnagel.lpes")
1538         save width, height, alpha;
1539
1540         width# = 2 * staff_space#;
1541         height# = 0.7 * staff_space#;
1542         alpha = 35;
1543
1544         set_char_box (0, width#, height# / 2, height# / 2);
1545
1546         define_pixels (width, height);
1547
1548         save circle;
1549         path circle;
1550
1551         circle := reverse fullcircle scaled linethickness;
1552
1553         pickup pencircle scaled linethickness;
1554
1555         rt x3 = -lft x1 = width / 2;
1556         y2 = y3 = height / 2;
1557         y1 = y4 = -height / 2;
1558
1559         tand (alpha) * (y2 - y1) = x2 - x1 = x3 - x4;
1560
1561         fill get_subpath (circle, left, z2 - z1, z1)
1562              -- get_subpath (circle, z2 - z1, right, z2)
1563              -- get_subpath (circle, right, z4 - z3, z3)
1564              -- get_subpath (circle, z4 - z3, left, z4)
1565              -- cycle;
1566
1567         currentpicture := currentpicture shifted (width/2, 0);
1568
1569 %       labels (1, 2, 3, 4);
1570 fet_endchar;
1571
1572
1573 fet_endgroup ("noteheads")