]> git.donarmstrong.com Git - lilypond.git/blob - mf/feta-klef.mf
*** empty log message ***
[lilypond.git] / mf / feta-klef.mf
1 % feta-klef.mf --  implement Clefs -*-Fundamental-*-
2 %
3 % part of LilyPond's pretty-but-neat music font
4 %
5 % source file of the Feta (not the Font-En-Tja) music font
6 %
7 % (c) 1997--2005 Han-Wen Nienhuys <hanwen@cs.uu.nl>,
8 % Jan Nieuwenhuizen <janneke@gnu.org>,
9 % Juergen Reuter <reuter@ipd.uka.de>
10
11
12 fet_begingroup ("clefs");
13
14 %
15 % [Wanske] says the bulbs should be positioned about 1/4 right of the
16 % `arrow'.
17 %
18 % TODO: The hair-curve at z6r looks a little awkward.
19 %
20
21 def draw_c_clef (expr reduction) =
22         save hair, norm, reduced_ss, right_edge;
23         save xoff;
24
25         reduced_ss# = staff_space# * reduction;
26         norm# := 2/3 reduced_ss#;
27         hair# := 0.06 reduced_ss# + 0.5 linethickness#;
28         right_edge# = 15/4 norm# + 2 hair#;
29         define_pixels (norm, reduced_ss, right_edge);
30         define_whole_vertical_blacker_pixels (hair);
31
32         set_char_box (0, right_edge#, 2 reduced_ss#, 2 reduced_ss#);
33
34         % make unreduced glyph fit exactly into five staff lines
35         if reduction = 1:
36                 h := d := 2 staff_space_rounded;
37         fi;
38
39         % assure that the gap between the left and right stem
40         % has the same number of pixels as the thickness of the right
41         % stem
42         draw_block ((0, -d + feta_shift),
43                     (3/4 norm + 1/2 hair, h));
44         draw_block ((3/4 norm + 1/2 hair + hround (3/2 hair), -d + feta_shift),
45                     (3/4 norm + 1/2 hair + 2 hround (3/2 hair), h));
46
47         % assure symmetry
48         h := h - feta_shift;
49
50         pickup feta_fillpen;
51
52         xoff = 3/4 norm + 1/2 hair + 2 hround (3/2 hair);
53         z5l = (xoff - 3/4 hair, 0);
54         z5r = (x4, 0);
55
56         penpos1 (hair - pen_top - pen_bot, -90);
57         top z1l = (xoff + norm + hair, h);
58
59         penpos2 (hround (norm - 3/2 hair) - pen_lft - pen_rt, 180);
60         rt z2l = (w, h / 2);
61
62         penpos3 (hair - pen_top - pen_bot, 90);
63         bot z3l = ((right_edge - xoff) / 2 + xoff,
64                    vround (.5 norm - 1.5 hair));
65
66         penpos4 (hair - pen_lft - pen_rt, 0);
67         top z4 = (xoff + 1/2 norm + 1/2 hair,
68                   vfloor (reduced_ss - linethickness - .2 hair));
69
70         bot z6 = (xoff + 3/4 norm, vround (.5 norm - .5 hair));
71
72         save t;
73         t = 0.833;
74
75         save pat;
76         path pat;
77
78         pat = z5l{curl 1}
79               .. z4l{up}
80               .. z4r{down}
81               .. z3r{right}
82               ..tension t.. z2r{up}
83               ..tension t.. flare_path (top z1l, 180, 90,
84                                         hair, hfloor (norm - 1/2 hair), -1)
85               ..tension t.. z2l{down}
86               .. z3l{left}
87               .. z6
88               .. z5r{down};
89
90         filldraw pat shifted (0, feta_shift)
91                  -- reverse pat yscaled -1 shifted (0, -feta_eps)
92                  -- cycle;
93
94         penlabels (1, 2, 3, 4, 5, 6);
95
96         % ugh, should be bulb, not flare?
97
98         draw_staff (-2, 2, 0);
99 enddef;
100
101
102 fet_beginchar ("C clef", "C");
103         draw_c_clef (1.0);
104 fet_endchar;
105
106
107 fet_beginchar ("C clef", "C_change");
108         draw_c_clef (.8);
109 fet_endchar;
110
111
112 %
113 % New bulb routine:
114 %
115 % Insert a brushed piece of the path, and draw the rest of the bulb
116 % separately.
117 %
118 % The bulb has circular form.  Neat merging of the bulb and brushed path
119 % is done by playing with tension.
120 %
121
122 def new_bulb (expr start_point, start_angle,
123               outer_tangent_point,
124               end_point, end_angle,
125               big_radius, bulb_radius, flare,
126               direction, turning_dir) =
127 begingroup;
128         save pat, before, after;
129         save center;
130         save u, v;
131         path pat, before, after;
132         pair center;
133
134         clearxy;
135
136         center = outer_tangent_point
137                  + big_radius * dir (0)
138                  + (big_radius - bulb_radius) * dir (-turning_dir * 90);
139
140         z1' = center + bulb_radius * dir (turning_dir * 180);
141         z2' = outer_tangent_point + flare * dir (0);
142         z3' = center + bulb_radius * dir (0);
143         z4' = center + bulb_radius * dir (turning_dir * 90);
144
145         labels (1', 2', 3', 4');
146
147         before := z3'{dir (turning_dir * 90)}
148                   .. z4'
149                   ..tension 1.1.. z1';
150         after := z2'{dir (turning_dir * 90)}
151                  .. end_point{dir (end_angle)};
152         (u, v) = before intersectiontimes after;
153
154         pat := start_point{dir (start_angle)}
155                .. outer_tangent_point{dir (-turning_dir * 90)}
156                ..tension 0.97.. subpath (0, u) of before
157                .. subpath (v, infinity) of after;
158
159         if direction = 0:
160                 pat := reverse pat;
161         fi
162
163 pat
164 endgroup
165 enddef;
166
167
168 %
169 % There is some variation in the shape of bass clefs.
170 %
171 % * In some clefs the size of the swoosh tip almost reaches the
172 %   bottom staff line; in some it crosses the 2nd line from the bottom
173 %   with a small overshoot.
174 %
175 %   The most popular design is where the X part of the tip is aligned
176 %   with the left bulb boundary, and the Y part ends on the 2nd
177 %   staffline exactly.  This is what we do.
178 %
179 % * The diameter of the bulb is the width of the open space.
180 %
181 % * The vertical center of the bulb can be on or slightly above the
182 %   staff line.
183 %
184 % * The vertical position of the dots can be symmetrical around the
185 %   staffline, centered in the staff space.  The Baerenreiter SCS has
186 %   the bottom dot raised by approximately 0.1 staff space.
187 %
188 % * Uncarefully set music may have overshoots at the top.  We have none.
189 %
190 % * It is not exactly clear where the vertical tangent at the right
191 %   of the swoosh should be.
192 %
193
194 def draw_bass_clef (expr exact_center, reduction) =
195         save reduced_ss, swoosh_width;
196         save right_thickness, right_offset, tip_protude;
197         save dot_diam, bulb_y_offset, bulb_flare;
198         pair tip_protude;
199
200         reduced_ss# = staff_space# * reduction;
201         2.2 dot_diam# = reduction * (staff_space# - stafflinethickness#);
202         right_thickness# = 0.37 staff_space# + 1.2 linethickness#;
203         swoosh_width# = 2.1 reduced_ss#;
204         define_pixels (swoosh_width);
205         define_whole_pixels (reduced_ss);
206         define_whole_blacker_pixels (dot_diam, right_thickness);
207
208         right_offset = 0.05 staff_space;
209         bulb_y_offset := 0.15 staff_space;
210         bulb_flare := 2.5 linethickness;
211 %       tip_protude := (-linethickness, -.2 staff_space);
212         tip_protude := (0, 0);
213
214         set_char_box (-xpart exact_center,
215                       xpart exact_center + swoosh_width# + 7/12 reduced_ss#,
216                       -ypart exact_center + 2.5 reduced_ss#,
217                       ypart exact_center + reduced_ss#);
218
219         y1 = bulb_y_offset;
220         x1 = 0;
221
222         x2 = .5 [x1, x3];
223         x2l = x2r = x2;
224
225         y2l := vround_pixels (reduced_ss# + 0.5 linethickness#);
226         y2l - y2r = linethickness;
227
228         x3l - x1 = swoosh_width;
229         x3l - x3r = right_thickness;
230
231         % optical correction: the top dot seems farther away if y3l = 0.
232         y3l = right_offset;
233
234         z4 = -(0, 2.0 reduced_ss) + tip_protude;
235
236         penpos3 (whatever, 185);
237         penpos4 (linethickness, 135);
238
239         fill new_bulb (z2l, 180, z1, z2r, 0,
240                        0.45 reduced_ss, 0.4 reduced_ss,
241                        bulb_flare, 1, 1)
242              .. z3r{down}
243              .. {curl 0}simple_serif (z4r, z4l, 90){curl 0}
244              .. z3l{up}
245              ..tension 0.9.. cycle;
246
247         pickup pencircle scaled dot_diam;
248
249         lft x5 = hround (x3l + 1/3 reduced_ss - dot_diam / 2);
250         bot y5 = vfloor (.5 reduced_ss - dot_diam / 2);
251         z6 = z5 yscaled -1;
252
253         % for symmetry
254         y5 := y5 + feta_shift;
255
256         drawdot z5;
257         drawdot z6;
258
259         penlabels (1, 2, 3, 4, 5, 6);
260
261         draw_staff (-3, 1, 0);
262 enddef;
263
264
265 fet_beginchar ("F clef ", "F");
266         draw_bass_clef ((0, 0), 1.0);
267 fet_endchar;
268
269
270 fet_beginchar ("F clef (reduced)", "F_change");
271         draw_bass_clef ((0, 0), 0.8);
272 fet_endchar;
273
274
275
276 %
277 % Inspired by Baerenreiter
278 %
279 %
280 % Beste lezers, kijk,
281 %
282 % Een bolletje hebben we bij toeval allemaal wel eens getekend, maar begint u
283 % toch eenvoudig.  Eerst een eenvoudig kruis of herstellingsteken
284 % en via de dubbelslag naar een voorzichtig vlaggetje, en heb geduld!
285 % Ikzelf heb bijvoorbeeld over mijn eerste gave G-sleutel
286 % 35 kilobyte metafont, 12 patchlevels, 0 vriendinnen en 45 dagen gedaan
287 %
288 %  -- vrij naar Van Kooten & De Bie
289 %
290
291 def debugfill = fill enddef;
292
293 def draw_gclef (expr reduction) =
294         save reduced_ss, downstroke_dir, downstroke_angle, center;
295         save breapth_factor, inner_thick_end, thinness, thickness, thinnib;
296         save start_angle, inner_start_angle, thinness;
297         save upward_swoosh_angle, bot_angle;
298         save pat;
299         path pat;
300         pair downstroke_dir, center;
301
302         reduced_ss# = staff_space# * reduction;
303         define_pixels (reduced_ss);
304
305         thinness = 0.08 staff_space + 0.7 linethickness;
306         downstroke_dir = unitvector (14, -75);
307         downstroke_angle = angle downstroke_dir;
308         bot_angle = -180;               % downstroke_angle - 87
309
310         upward_swoosh_angle = 132;
311         start_angle = -95;
312
313         breapth_factor = 21.0 /14;
314         inner_thick_end = 45;
315         inner_start_angle = downstroke_angle - 43;
316         thickness = .32 reduced_ss + 1.1 linethickness;
317
318         thinnib = thinness;
319
320         set_char_box (0, 1.71 * breapth_factor * reduced_ss#,
321                       2.6 * reduced_ss#, 5 * reduced_ss#);
322
323         center := (breapth_factor * reduced_ss, 0);
324
325         z1 = center + whatever * dir (inner_start_angle);
326         x1 = xpart center - .28 reduced_ss;
327         penpos1 (thinnib, inner_start_angle);
328
329         x2r = xpart center;
330         y2r = vround_pixels (reduced_ss# + .5 stafflinethickness#);
331         penpos2 (thickness, 90);
332
333         z3 = (z4 - center) rotated inner_thick_end + center;
334         penpos3 (thinnib, -90 + inner_thick_end);
335
336         x4 = xpart center - .1 reduced_ss;
337         y4r = -y2r + feta_shift;
338         penpos4 (thinnib, -90);
339
340         x5r = -breapth_factor * reduced_ss + xpart center;
341         y5r = .37 reduced_ss + ypart center;
342         penpos5 (thickness, upward_swoosh_angle);
343
344         z6 = center + whatever * downstroke_dir;
345         y6 = ypart center + 2 reduced_ss;
346         % penpos6 is computed later
347
348         z7l - z6 = whatever * (z5 - z6) ;
349         y7l = 3.5 reduced_ss;
350         penpos7 (thickness, upward_swoosh_angle);
351
352         x9 = .7 [x10, x7r];
353         top y9l = 5 reduced_ss;
354         penpos9 (1.45 thickness, -70);
355
356         x11 - x13r = 1.5 reduced_ss + 0.5 thinnib;
357         y11 = ypart center - 47/28 reduced_ss;
358         y12 = ypart center - 71/28 reduced_ss;
359         y13 = .48 [y12, y4r];
360         x12r = xpart (.45 [z13r, z11] + .75 reduced_ss * downstroke_dir);
361
362 %       z10 = center + whatever * dir (downstroke_angle - 1.5);
363         x10 = x6 - 2 thinnib;
364         y10 = ypart center + 3.5 reduced_ss;
365         y10l - y10r = 1.2 thickness;
366         z10r - z10l = .7 thinnib * dir (downstroke_angle + 90)
367                       + whatever * downstroke_dir;
368         z10 = .5 [z10l, z10r];
369         z11 = center + whatever * downstroke_dir + (0 reduced_ss, 0);
370
371         penpos11 (thinnib, start_angle + 90);
372         penpos12 (thinnib, bot_angle + 90);
373         penpos13 (thinnib + 0.14 staff_space, 180);
374
375         % this auxiliary point ensures good contour overlapping
376         z8 = .5 [z9l, z9r] + .25 ((z9r - z9l) rotated -90);
377
378         fill z2l{right}
379              .. z3l
380              .. z4l{left}
381              .. z5l{up}
382              .. z7l{up}
383              ..tension 1.2.. z9l
384              -- z8
385              -- z9r                     % {dir (downstroke_angle + 0)}
386              ..tension 0.8.. z7r{down}
387              .. z5r{down}
388              .. z4r{right}
389              .. z3r
390              .. z2r{left}
391              ..tension .95.. z1r
392              -- simple_serif (z1r, z1l, 80)
393              -- z1l
394              ..tension 0.85.. cycle;
395
396         pat := z10{down}
397                .. z6
398                .. z11{dir (start_angle)};
399
400         penpos6 (thinnib, angle (direction 1 of pat) + 90);
401
402         % two auxiliary points to simulate `draw' with `penstroke'
403         z10' = point 0.5 of pat;
404         penpos10' (thinnib, angle (direction 0.5 of pat) + 90);
405         z11' = point 1.5 of pat;
406         penpos11' (thinnib, angle (direction 1.5 of pat) + 90);
407
408         penstroke z9e
409                   .. z10e{down}
410                   .. z10'e
411                   .. z6e
412                   .. z11'e
413                   .. z11e{dir (-95)}
414                   .. z12e{dir (bot_angle)};
415
416         fill new_bulb (z12r, bot_angle, z13r, z12l, bot_angle + 180,
417                        0.45 reduced_ss, 0.38 reduced_ss,
418                        thinnib + .15 staff_space, 1, -1)
419              -- cycle;
420
421         penlabels (range 1 thru 16);
422         penlabels (10', 11');
423
424         draw_staff (-1, 3, 0);
425 enddef;
426
427
428 fet_beginchar ("G clef", "G");
429         draw_gclef (1.0);
430 fet_endchar;
431
432
433 fet_beginchar ("G clef", "G_change");
434         draw_gclef (0.8);
435 fet_endchar;
436
437
438 %%%%
439 %
440 % PERCUSSION
441 %
442
443 %
444 % The percussion clef extent is not coincident with its bbox, since
445 % the percussion clef needs more space in front than a normal clef.
446 %
447
448 def draw_percussion_clef (expr reduction) =
449         save reduced_ss, razt;
450
451         reduced_ss# = staff_space# * reduction;
452         define_pixels (reduced_ss);
453
454         set_char_box (-.67 reduced_ss#, 2.0 reduced_ss#,
455                       reduced_ss#, reduced_ss#);
456
457         razt := hround (0.45 reduced_ss);
458
459         d := d - feta_shift;
460
461         draw_block ((-b, -d), (-b + razt, h));
462         draw_block ((w - razt, -d), (w, h));
463
464         draw_staff (-3, 1, 1);
465 enddef;
466
467
468 fet_beginchar ("percussion clef", "percussion");
469         draw_percussion_clef (1.0);
470 fet_endchar;
471
472
473 fet_beginchar ("percussion clef (reduced)", "percussion_change");
474         draw_percussion_clef (.8);
475 fet_endchar;
476
477
478 def draw_tab_T (expr pos, siz, slant) =
479 begingroup;
480         save vx, vy;
481         pair vx, vy;
482
483         clearxy;
484
485         vx = (xpart siz) * dir 0;
486         vy = (ypart siz) * dir 90;
487
488         penpos1 (.75 penh, 100);
489         z1 = z2 + (1/6 * vx - .15 * vy);
490         penpos2 (hround (.9 penw), 0);
491         x2l = hround xpart (pos + .75 vy);
492         y2l = ypart (pos + .75 vy);
493         penpos3 (penh, -100);
494         z3l = pos + .4 vx + vy;
495         penpos4 (penh, -90);
496         z4 = -.1 vy + .5 [z3, z5];
497         penpos5 (.8 penh, -30);
498         x5r = xpart (pos + siz);
499         y5l = ypart (pos + siz);
500
501         penpos10 (penw, 170);
502         z10 = pos + .55 vx + .9 vy;
503         penpos11 (.75 [penh, penw], 170);
504         z11 = z10 - .5 vy + .025 vx;
505         penpos12 (penh, 100);
506         z12l = (xpart .5 [z13, z11], ypart (pos - .025 * siz));
507         penpos13 (.75 penh, 60);
508         z13 = pos + .2 vx + .15 vy;
509
510         % penlabels (range 1 thru 13);
511
512         soft_penstroke (z1e
513                         ..tension 1.1.. z2e
514                         .. z3e{right}
515                         ..tension 1.5.. z4e
516                         ..z5e)
517           slanted slant shifted (slant * -ypart pos, 0);
518
519         soft_end_penstroke (z10e
520                             ..tension 1.5.. z11e
521                             .. z12e
522                             ..tension 1.1.. z13e{(z13r - z13l) rotated 90})
523           slanted slant shifted (slant * -ypart pos, 0);
524 endgroup;
525 enddef;
526
527         
528 def draw_tab_A (expr pos, siz, slant) =
529 begingroup;
530         save vx, vy, pat;
531         pair vx, vy;
532         path pat;
533
534         clearxy;
535
536         vx = (xpart siz) * dir 0;
537         vy = (ypart siz) * dir 90;
538
539         penpos1 (.75 penh, -110);
540         z1r = pos + .07 vy;
541         penpos2 (penh, -75);
542         z2r = (.5 [x1, x3], ypart pos);
543         penpos3 (.25 [penh, penw], -30);
544         z3 = (.45 [x2, x4], .15 [y2, y4]);
545         penpos4 (1 [penh, penw], 0);
546         z4 = pos + .5 vx + .975 vy;
547
548         penpos5 (1 [penh, penw], -180);
549         z5 = z4;
550         penpos6 (.2 [penh, penw], -150);
551         z6l = (.8 [x5l, x7l], .9 [y5l, y7l]);
552         penpos7 (penh,-90);
553         z7r = (.5 [x6, x8], ypart pos);
554         penpos8 (.75 penh, -70);
555         z8r = (xpart (pos + siz), y7r + .075 ypart (siz));
556
557         pat := z2
558                .. z3
559                .. z4;
560
561         penpos10 (penh, angle (direction 1.2 of pat) - 180);
562         z10 = point 1.2 of pat;
563         penpos11 (.9 penh, -90);
564         z11 = .4 [z10, z6] - 0.05 vy;
565         penpos12 (.75 penh, -75);
566         z12 = .3 [z11, z6] + 0.02 vy;
567
568         % penlabels (range 1 thru 12);
569
570         soft_penstroke (z1e{(z1r - z1l) rotated 90}
571                         .. z2e
572                         .. z3e
573                         .. z4e)
574           slanted slant shifted (slant * -ypart pos, 0);
575
576         soft_end_penstroke (z5e
577                             .. z6e
578                             .. z7e
579                             .. z8e{(z8r - z8l) rotated 90})
580           slanted slant shifted (slant * -ypart pos, 0);
581
582         soft_end_penstroke (z10e
583                             .. z11e
584                             .. z12e)
585           slanted slant shifted (slant * -ypart pos, 0);
586 endgroup;
587 enddef;
588
589
590 def draw_tab_B (expr pos, siz, slant) =
591 begingroup;
592         save vx, vy;
593         pair vx, vy;
594
595         clearxy;
596
597         vx = (xpart siz) * dir 0;
598         vy = (ypart siz) * dir 90;
599
600         penpos1 (.75 penh, 100);
601         z1 = z2 + (.15 * vx - .1 * vy);
602         penpos2 (hround (.9 penw), 0);
603         x2l = hround xpart (pos + .75 vy);
604         y2l = ypart (pos + .75 vy);
605         penpos3 (penh, -100);
606         z3l = pos + .4 vx + 1.05 vy;
607         penpos4 (.8 [penh, penw], -180);
608         z4 = (xpart (pos + .75 siz), .5 [y3, y5]);
609         penpos5 (.8 penh, 90);
610         z5 = (.5 [x10, x4], ypart (pos + .55 siz));
611
612         penpos6 (.8 penh, 270);
613         z6 = z5;
614         penpos7 (penw, 180);
615         z7l = (xpart (pos + siz), .5 [y6, y8]);
616         penpos8 (.8 penh, 45);
617         z8 = .5 [z12l, z11l] + .15 vx - .05 vy;
618
619         penpos10 (.75 [penh, penw], 170);
620         z10 = pos + .375 vx + vy;
621         penpos 11 (.8 [penh, penw], 150);
622         z11 = z10 - .5 vy + .04 vx;
623         penpos12 (penh, 100);
624         z12l = (xpart .5 [z13, z11], ypart pos);
625         penpos13 (.75 penh, 60);
626         z13 = pos + .1 vx + .15 vy;
627
628         % penlabels (range 1 thru 13);
629
630         soft_penstroke (z1e
631                         ..tension 1.1.. z2e
632                         .. z3e
633                         .. z4e
634                         ..z5e {left})
635           slanted slant shifted (slant * -ypart pos, 0);
636
637         soft_end_penstroke (z6e{right}
638                             .. z7e
639                             .. z8e{(z8r - z8l) rotated 90})
640           slanted slant shifted (slant * -ypart pos, 0);
641
642         soft_end_penstroke (z10e
643                             ..tension 1.5.. z11e
644                             .. z12e
645                             ..tension 1.1.. z13e{(z13r - z13l) rotated 90})
646           slanted slant shifted (slant * -ypart pos, 0);
647 endgroup;
648 enddef;
649
650
651 def draw_tab_clef (expr reduction) =
652         save reduced_ss, letterheight, penw, penh;
653
654         reduced_ss# = staff_space# * reduction;
655         letterheight# = 1.8 reduced_ss#;
656         define_pixels (reduced_ss, letterheight);
657
658         set_char_box (-.2 reduced_ss#, 2.8 reduced_ss#,
659                       1.6 letterheight#, 1.6 letterheight#);
660
661         penw = .45 reduced_ss;
662         penh = .2 reduced_ss;
663
664         draw_tab_T ((-b + .15 reduced_ss, h - letterheight),
665                     (2.1 reduced_ss, letterheight), 0.2);
666         draw_tab_A ((-b - .05 reduced_ss, -.5 letterheight +.15 reduced_ss),
667                     (2.2 reduced_ss, letterheight), 0.4);
668         draw_tab_B ((-b + .025 reduced_ss, -d),
669                     (2.1 reduced_ss, letterheight), 0.25);
670
671         draw_staff (-3, 2, 0.5);
672 enddef;
673
674
675 fet_beginchar ("tab clef", "tab");
676         draw_tab_clef (1.0);
677 fet_endchar;
678
679
680 fet_beginchar ("tab clef (reduced)", "tab_change");
681         draw_tab_clef (.8);
682 fet_endchar;
683
684 fet_endgroup ("clefs");