1 % Feta (not the Font-En-Tja) music font -- bold Orator numerals
2 % This file is part of LilyPond, the GNU music typesetter.
4 % Copyright (C) 1997--2012 Jan Nieuwenhuizen <janneke@gnu.org>
6 % The LilyPond font is free software: you can redistribute it and/or modify
7 % it under the terms of the GNU General Public License as published by
8 % the Free Software Foundation, either version 3 of the License, or
9 % (at your option) any later version, or under the SIL Open Font License.
11 % LilyPond is distributed in the hope that it will be useful,
12 % but WITHOUT ANY WARRANTY; without even the implied warranty of
13 % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 % GNU General Public License for more details.
16 % You should have received a copy of the GNU General Public License
17 % along with LilyPond. If not, see <http://www.gnu.org/licenses/>.
20 height# := number_design_size;
21 space# := number_design_size / 2;
23 font_x_height height#;
24 font_normal_space space#;
30 % ugh. b and h are reused.
36 fatten := number_design_size * h + b;
41 widen := number_design_size * h + b;
44 thick# := 7/30 height# * fatten;
45 thin# := thick# / 4 * fatten + max (.1 (height# / 10 - 1), 0);
47 %% sqrt (.8 * blot_diameter# * thin#);
50 flare# := 9/8 thick# + .75 (height# / 10 - 1);
55 kuulleke# := thick# * number_design_size * h + b;
57 foot_width# := 9/4 thick#;
61 % These numbers were taken from a part that the EJE violas played in
62 % 1997 -- Probably Mendelssohn's ouverture `Heimkehr aus der Fremde'.
67 % TODO all the invocation of flare_path are weird --
68 % the horizontal tangents should be more at the center of the
72 define_pixels (height, thick, thick, thin, hair, flare);
73 define_pixels (foot_top, foot_width);
74 define_pixels (kuulleke);
78 % Yet Another Bulb Routine with smooth inside curve.
80 % alpha = start direction.
81 % beta = which side to turn to
82 % flare = diameter of the bulb
83 % line = diameter of line attachment
84 % direction = is ink on left or right side (1 or -1)
87 % move_away_to = amount left (for 2)
88 % turn_to = amount down (for 2)
91 def number_flare_path (expr pos, alpha, beta, line, flare,
92 move_away_to, turn_to, taille, taille_ratio,
100 % z5 = z2 + 0.43 * flare * dir (alpha - 1.5 beta);
102 z4 = (0.75 - taille) [z2r, z2l] + whatever * dir (alpha - beta);
103 z4 = (taille_ratio * taille) [z3l, z3r] + whatever * dir (alpha);
106 z2r = z1r + move_away_to * dir (alpha)
107 + (line + turn_to) * dir (alpha + beta);
108 z3r = 0.5 [z2l, z2r] + 0.5 * flare * dir (alpha + beta);
110 penpos1 (line, 180 + beta + alpha);
111 penpos2 (flare, alpha);
112 penpos3 (flare, alpha + beta);
114 penlabels (1, 2, 3, 4, 5);
116 res := z1r{dir (alpha)}
117 .. z2r{dir (180 + alpha - beta)}
118 .. z3r{dir (alpha + 180)}
119 .. z2l{dir (alpha - beta)}
121 %%% Two versions of the curve: one with z4, the other with z5.
122 % .. z5{dir (alpha - beta / 2)}
124 .. z4{dir (180 + alpha + beta)}
125 .. z1l{dir (alpha + 180)};
139 def calc_kuulleke (expr w, alpha) =
143 beta = (alpha - 90) / 2;
144 gamma = (90 + alpha) / 2;
146 penpos1 (w / cosd (alpha), alpha);
147 penpos2 (hair, 90 + beta);
148 penpos3 (hair, gamma - 90);
150 z2 = z1l + (1/2 hair / tand ((alpha + 90) / 2)) * dir (beta);
151 z3 = z1r - (1/2 hair / tand ((90 - alpha) / 2)) * dir (gamma);
152 z4 = z1 + kuulleke * dir (alpha - 90);
157 % should make generic macro?
159 def draw_foot (expr xpos) =
164 penpos2 (foot_width, 0);
168 z1= (xpos, foot_top);
174 penlabels (1, 2, 3, 4);
192 save before, after, u, v;
195 set_char_box (0, .68 height# * widen, 0, height#);
197 message "w:" & decimal w;
198 message "h:" & decimal h;
201 z2 = (w / 2, h / 2 + thin - hair / 2);
203 penpos3 (15/16 thick, 0);
214 penpos7 (thick, 180);
218 penpos10 (thick, 180);
221 penlabels (range 1 thru 10);
229 .. number_flare_path (z6r, 0, -90, hair, flare,
230 w - x6r - hair / 2, .16 h,
233 (u, v) = before intersectiontimes after;
236 fill subpath (u, infinity) of before
237 ..tension outer_t.. z3r{down}
238 ..tension outer_t.. z4r{left}
239 .. subpath (0, v) of after
243 ..tension t.. z3l{down}
244 ..tension t.. z4l{left}
245 ..tension t.. z10l{up}
251 dot_diam# = 7/8 flare#;
252 define_pixels (dot_diam);
257 fet_beginchar ("Plus", "plus");
258 set_char_box (0, .5 height#, -0.25 height#, 0.75 height#);
260 save hthick, vthick, size, outer_hsize, outer_vsize;
262 hthick# = vthick# = 2 linethickness#;
263 size# = 1.1 staff_space#;
264 define_whole_blacker_pixels (vthick);
265 define_whole_vertical_blacker_pixels (hthick);
267 outer_hsize = hround ((b + w - vthick) / 2);
268 outer_vsize = vround ((h + d - hthick) / 2);
270 centerx := hround (w / 2);
271 centery := vround ((h - d) / 2);
273 z1 = (centerx - hthick / 2, -d);
274 z2 = (centerx + hthick / 2, h);
278 draw_rounded_block (z1, z2, hthick);
279 draw_rounded_block ((0, centery - vthick / 2),
280 (w, (centery + vthick / 2)),
287 fet_beginchar ("Numeral comma", "comma");
291 set_char_box (0, dot_diam#, 3/2 dot_diam#, dot_diam#);
293 pat := (dot_diam / 2, 0)
294 .. (dot_diam, dot_diam / 2)
295 .. (dot_diam / 2, dot_diam)
299 pos = ypart (((w / 3, 0) -- (w / 3, dot_diam / 2))
300 intersectiontimes pat);
301 z0 = point pos of pat;
304 penpos1 (thin, alpha + 90);
306 z1l = (w / 2, -1.5 h + hair);
311 % include z0 to assist removal of overlaps
312 fill subpath (0,3) of pat
315 filldraw z1l{dir (alpha)}
317 -- z0{direction pos of pat}
318 ..tension 0.95.. {dir (180 + alpha)}z1r
326 fet_beginchar ("Numeral dash", "hyphen");
327 set_char_box (0, height# / 3, 0, height#);
329 draw_rounded_block ((-b, h / 3 - thin / 2),
330 (w, h / 3 + thin / 2), thin);
334 fet_beginchar ("Numeral dot", "period");
335 set_char_box (0, dot_diam#, 0, dot_diam#);
337 pickup pencircle scaled dot_diam;
339 drawdot (dot_diam / 2, dot_diam / 2);
347 fet_beginchar ("Numeral 0", "zero");
348 set_char_box (0, 11/15 height# * widen, 0, height#);
350 message "w:" & decimal w;
351 message "h:" & decimal h;
354 penpos2 (thick, 180);
372 penlabels (1, 2, 3, 4);
382 fet_beginchar ("Numeral 1", "one");
383 save alpha, beta, gamma;
385 % set_char_box (0, 19/30 height# * widen, 0, height#);
386 set_char_box (0, 1/2 foot_width# + 3/2 thick# + 1/2 hair#,
389 message "w:" & decimal w;
390 message "h:" & decimal h;
393 calc_kuulleke (thick, alpha);
394 z1 = (3/2 thick, height);
400 beta = angle (z1l - z6);
402 penpos7 (thin, beta - 90);
405 penpos8 (thin / cosd (beta), -90);
408 penpos9 (thin, beta - 90);
409 z9r = z8r + (thin / cosd (beta)) * down;
411 penlabels (range 1 thru 9);
413 gamma = angle (length (z1r - z1), 2 kuulleke);
415 fill z2r{dir (alpha - gamma)}
417 .. {dir (alpha + gamma)}z3l
426 .. {dir (alpha - gamma)}z2r
428 .. {dir (180 + beta)}z9l
429 -- z7r{dir (180 + beta)}
430 .. {dir (beta)}cycle;
436 fet_beginchar ("Numeral 2", "two");
438 save alpha, beta, gamma, theta;
439 save flare_start_distance;
443 set_char_box (0, 22/30 height# * widen, 0, height#);
445 message "w:" & decimal w;
446 message "h:" & decimal h;
455 penpos1 (hair, 90 + beta);
456 z1 = (0, 0) + (1/2 sqrt (2) * hair) * dir (45);
458 penpos3 (hair,90 + gamma);
459 z3 = (w, thick) + (1/2 sqrt (2) * hair) * dir (-135);
461 penpos2 (thick, 90 + alpha - 15);
463 y2 = 10/16 thick / widen;
465 tolerance := epsilon;
467 % Find proper tension to exactly touch the x axis.
468 % Later on we directly use `bow'.
470 bow := z3l{dir (180 + gamma)}
471 ..tension t.. {dir (180 + alpha -5)}z2l;
472 ypart (directionpoint left of bow) < 0
475 % the return value of `solve' is stored in a dummy variable
476 t = solve f (0.8, 1.2);
479 ..tension 0.9.. {dir (alpha + 10)}z2r
482 .. {dir (180 + beta)}z1l
486 z4r = (w - thin / 2, .71 h);
492 penlabels (range 1 thru 6);
496 pat := z1l{dir (beta)}
497 ..tension t.. z4r{up}
498 .. number_flare_path (z5r, 180, 90, hair, 1.05 flare,
499 x5r - 1/2 hair, .21 h, 0.006, 0.4, 1)
501 ..tension t.. {dir (180 + beta)}z1r
504 % pickup pencircle scaled 1;
512 % TODO: should widen a bit. The right edge of the 3 bumps into next glyph in
515 fet_beginchar ("Numeral 3", "three");
516 set_char_box (0, 2/3 height# * widen, 0, height#);
518 message "w:" & decimal w;
519 message "h:" & decimal h;
523 % flare_start = 0.25;
528 % z1l = (17/16 thick, h);
530 penpos2 (7/8 thick, 180);
532 y2l = 3/4 h + thick * 3/32;
535 z3 = (w / 2, h / 2 + 1/8 thick);
538 z4 = (5/8 thick + 1/2 thin, y3);
542 y5r = 17/64 h + thick / 16;
548 penpos7 (3/2 thin, 90);
552 penlabels (range 1 thru 7);
554 save alpha, t, outer_t;
559 % pickup pencircle scaled 1;
561 fill number_flare_path (z1l, 180, 90, hair, 7/8 flare, x1l - .5 hair,
562 .16 h, 0.06, 1.5, -1)
563 ..tension outer_t.. z2l{down}
564 ..tension outer_t.. z7r{dir (180 + alpha)}
566 ..tension outer_t.. z5r{down}
567 ..tension outer_t.. number_flare_path (z6r, 180, -90, hair,
568 flare, x6l, .18 h, 0.06,
571 ..tension t.. z3l{left}
575 ..tension t.. z2r{up}
580 fet_beginchar ("Numeral 4", "four");
581 save alpha, beta, gamma;
583 set_char_box (0, 4/5 height# * widen, 0, height#);
585 message "w:" & decimal w;
586 message "h:" & decimal h;
589 calc_kuulleke (3/2 thick, alpha);
591 z1r = (w - 3/4 thick, height);
592 z5 = (thin, 1/4 height + thin);
594 beta = angle (z3r - z5);
603 penpos8 (thin, -alpha);
606 penlabels (range 1 thru 8);
608 gamma = angle (length (z1r - z1), 2 kuulleke);
610 fill z2r{dir (alpha - gamma)}
612 .. {dir (alpha + gamma)}z3l
613 .. {dir (180 + beta)}z3r
618 ..tension 0.8 and 2.. z8l{dir (beta)}
625 calc_kuulleke (thick, alpha);
627 z1r = (w - 3/4 thick, height - (3/2 thin) / cosd (alpha));
632 gamma := angle (length (z1r - z1), 2 kuulleke);
634 fill z2r{dir (alpha - gamma)}
636 .. {dir (alpha + gamma)}z3l
643 penlabels (1, 2, 3, 4, 5);
649 fet_beginchar ("Numeral 5", "five");
650 save alpha, beta, gamma, delta;
651 save inner_t, outer_t;
655 set_char_box (0, 27/40 height# * widen, 0, height#);
657 message "w:" & decimal w;
658 message "h:" & decimal h;
661 calc_kuulleke (w - thin, alpha);
663 z1 = (w / 2 + 1/8 thick, h);
666 z5l = (x1l, h - 15/16 thick);
668 penpos6 (hair, 90 - 45);
669 z6 = z5r + 1/2 hair * dir (-45);
672 z7l = (x1l, h / 2 + thin - hair);
674 penlabels (range 1 thru 7);
676 gamma = angle (length (z1r - z1), 2 kuulleke);
678 pat := z2r{dir (alpha - gamma)}
680 .. {dir (alpha + gamma)}z3l
690 delta = 180 + beta + 10;
691 z8r = (x7r, y7r - 1/16 thick + thin);
692 z8l = directionpoint dir (delta) of
693 subpath (6, 7) of pat;
695 % include intersection point to improve overlap removal
696 fill subpath (0, 6) of pat
698 .. subpath (7, length (pat)) of pat
703 x9 = .36 [x8r, x10r];
707 y10r = 1/2 [y9r, y11r];
709 penpos11 (hair, -90);
713 penlabels (range 8 thru 12);
718 fill z8r {dir (beta)}
720 ..tension outer_t.. z10r{down}
721 .. number_flare_path (z11r, 180, -90, hair, flare, x11l,
724 ..tension inner_t.. z10l{up}
725 ..tension inner_t.. z9l{left}
731 fet_beginchar ("Numeral 6", "six");
736 fet_beginchar ("Numeral 7", "seven");
738 save alpha, beta, gamma, delta;
744 set_char_box (0, 11/15 height# * widen - thin#, 0, height#);
745 overshoot_x = .75 thin;
747 message "w:" & decimal w;
748 message "h:" & decimal h;
752 penpos1 (3/2 thick, 180 + alpha);
753 penpos2 (hair, 180 + alpha - 45);
754 penpos3 (hair, 180 + alpha + 45);
756 z2 = z1l + (1/4 sqrt (2) * hair) * dir (alpha - 135);
757 z3 = z1r + (1/4 sqrt (2) * hair) * dir (alpha - 45);
758 z4 = z1 + kuulleke * dir (alpha - 90);
763 penpos5 (thin, 90 + beta);
764 z5 = (w, h) + (1/2 sqrt (2) * thin) * dir (-135) + (overshoot_x, 0);
766 gamma = angle (length (z1r - z1), 2 kuulleke);
771 fill z3l{dir (alpha - gamma)}
773 .. {dir (alpha + gamma)}z2r
774 .. z2l{dir (beta + delta)}
776 .. z5l{dir (180 + beta)}
777 .. {dir (delta - 90)}z3r
780 penlabels (1, 2, 3, 4, 5);
782 alpha := -45 * widen;
784 penpos11 (1/2 thick, 90);
785 z11 = (3/2 thin, h - (thick + thin) / 2);
787 penpos13 (thin, 90 + beta);
790 penpos12 (thick, 90 + alpha);
791 x12 = 1/2 [x11, x13] - 1/4 thick;
792 y12 = h - 15/16 thick + thin * widen;
795 z14l = (0, h - thin / 2);
798 z15l = (0, h / 2 + thin / 2);
800 penpos16 (9/8 thick, 90);
801 z16r = (thin, y11r + 2/16 thick);
803 tolerance := epsilon;
805 % Find proper tension to exactly touch the x axis.
806 % Later on we directly use `bow'.
808 bow := z11r{dir (beta)}
809 ..tension t.. {dir (alpha)}z12r;
810 ypart (directionpoint right of bow) > h
813 % the return value of `solve' is stored in a dummy variable
814 t = solve f (0.8, 1.2);
818 -- z13l{dir (180 + beta)}
819 .. {dir (180 + alpha)}z12l
820 .. {dir (180 + beta)}z11l
827 ..tension 1.5.. {dir (beta)}cycle;
829 penlabels (range 11 thru 16);
833 fet_beginchar ("Numeral 8", "eight");
836 set_char_box (0, 11/15 height# * widen, 0, height#);
838 message "w:" & decimal w;
839 message "h:" & decimal h;
844 z1 = (w / 2, h / 2 + thick / 8);
846 penpos2 (14/8 thin, 0);
847 z2 = (w / 3, h / 2 + thin);
849 penpos3 (3/2 thin, 0);
850 z3l = (0, h / 4 + thin / 2);
855 penpos5 (thick, 90 + 90 + alpha);
856 z5 = z1 + w / 4 * dir (alpha - 90);
858 penpos6 (thick, 90 + 90 + alpha);
859 z6 = z1 + (w / 4 - thin / 2) * dir (90 + alpha);
862 z7r = (x1 + .02 w, h);
864 penpos8 (3/2 thin, 0);
865 z8r = (w - thin / 2, 3/4 h + thin / 2);
867 penpos9 (13/8 thin, 0);
870 penlabels (range 1 thru 9);
875 fill z2r{dir (180 + beta)}
878 .. z5r{dir (90 + alpha)}
879 -- z6r{dir (90 + alpha)}
880 ..tension t.. z7r{right}
882 .. {dir (180 + beta)}z9r
886 .. {dir (alpha - 90)}z6l
887 -- z5l{dir (alpha - 90)}
888 ..tension t.. z4l{left}
895 fet_beginchar ("Numeral 9", "nine");
899 currentpicture := currentpicture scaled -1;
900 currentpicture := currentpicture shifted (w, h);
909 "7" kern 0.15 space#;