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