1 % feta-nummer-code.mf -- implement bold Orator numerals
3 % part of LilyPond's pretty-but-neat music font
5 % source file of the Feta (not the Font-En-Tja) music font
7 % (c) 1997--2005 Jan Nieuwenhuizen <janneke@gnu.org>
10 height# := number_design_size;
11 space# := number_design_size / 2;
13 font_x_height height#;
14 font_normal_space space#;
20 % ugh. b and h are reused.
26 fatten := number_design_size * h + b;
31 widen := number_design_size * h + b;
34 thick# := 7/30 height# * fatten;
35 thin# := thick# / 4 * fatten + max (.1 (height# / 10 - 1), 0);
37 %% sqrt (.8 * blot_diameter# * thin#);
40 flare# := 9/8 thick# + .75 (height# / 10 - 1);
45 kuulleke# := thick# * number_design_size * h + b;
47 foot_width# := 9/4 thick#;
51 % These numbers were taken from a part that that the EJE violas played
52 % 1997 -- Probably Mendelssohn's ouverture `Heimkehr aus der Fremde'.
57 % TODO all the invocation of flare_path are weird --
58 % the horizontal tangents should be more at the center of the
62 define_pixels (height, thick, thick, thin, hair, flare);
63 define_pixels (foot_top, foot_width);
64 define_pixels (kuulleke);
68 % Yet Another Bulb Routine with smooth inside curve.
70 % alpha = start direction.
71 % beta = which side to turn to
72 % flare = diameter of the bulb
73 % line = diameter of line attachment
74 % direction = is ink on left or right side (1 or -1)
77 % move_away_to = amount left (for 2)
78 % turn_to = amount down (for 2 )
81 def number_flare_path (expr pos, alpha, beta, line, flare,
82 move_away_to, turn_to, taille, taille_ratio,
90 % z5 = z2 + 0.43 * flare * dir (alpha - 1.5 beta);
92 z4 = (0.75 - taille) [z2r, z2l] + whatever * dir (alpha - beta);
93 z4 = (taille_ratio * taille) [z3l, z3r] + whatever * dir (alpha);
96 z2r = z1r + move_away_to * dir (alpha)
97 + (line + turn_to) * dir (alpha + beta);
98 z3r = 0.5 [z2l, z2r] + 0.5 * flare * dir (alpha + beta);
100 penpos1 (line, 180 + beta + alpha);
101 penpos2 (flare, alpha );
102 penpos3 (flare, alpha + beta);
104 penlabels (1, 2, 3, 4, 5);
106 res := z1r{dir (alpha)}
107 .. z2r{dir (180 + alpha - beta)}
108 .. z3r{dir (alpha + 180)}
109 .. z2l{dir (alpha - beta)}
111 %%% Two versions of the curve: one with z4, the other with z5.
112 % .. z5{dir (alpha - beta / 2)}
114 .. z4{dir (180 + alpha + beta)}
115 .. z1l{dir (alpha + 180)};
129 def calc_kuulleke (expr w, alpha) =
133 beta = (alpha - 90) / 2;
134 gamma = (90 + alpha) / 2;
136 penpos1 (w / cosd (alpha), alpha);
137 penpos2 (hair, 90 + beta);
138 penpos3 (hair, gamma - 90);
140 z2 = z1l + (1/2 hair / tand ((alpha + 90) / 2)) * dir (beta);
141 z3 = z1r - (1/2 hair / tand ((90 - alpha) / 2)) * dir (gamma);
142 z4 = z1 + kuulleke * dir (alpha - 90);
147 % should make generic macro?
149 def draw_foot(expr xpos) =
154 penpos2 (foot_width, 0);
158 z1= (xpos, foot_top);
164 penlabels (1, 2, 3, 4);
182 save before, after, u, v;
185 set_char_box (0, .68 height# * widen, 0, height#);
187 message "w:" & decimal w;
188 message "h:" & decimal h;
191 z2 = (w / 2, h / 2 + thin - hair / 2);
193 penpos3 (15/16 thick, 0);
204 penpos7 (thick, 180);
208 penpos10 (thick, 180);
211 penlabels (range 1 thru 10);
219 .. number_flare_path (z6r, 0, -90, hair, flare,
220 w - x6r - hair / 2, .16 h,
223 (u, v) = before intersectiontimes after;
226 fill subpath (u, infinity) of before
227 ..tension outer_t.. z3r{down}
228 ..tension outer_t.. z4r{left}
229 .. subpath (0, v) of after
233 ..tension t.. z3l{down}
234 ..tension t.. z4l{left}
235 ..tension t.. z10l{up}
241 dot_diam# = 7/8 flare#;
242 define_pixels (dot_diam);
247 fet_beginchar ("Space", "space");
248 set_char_box (0, space#, 0, height#);
254 fet_beginchar ("Plus", "plus");
255 set_char_box (0, .5 height#, -0.25 height#, 0.75 height#);
257 save hthick, vthick, size, outer_hsize, outer_vsize;
259 hthick# = vthick# = 2 linethickness#;
260 size# = 1.1 staff_space#;
261 define_whole_blacker_pixels (vthick);
262 define_whole_vertical_blacker_pixels (hthick);
264 outer_hsize = hround ((b + w - vthick) / 2);
265 outer_vsize = vround ((h + d - hthick) / 2);
267 centerx := hround (w / 2);
268 centery := vround ((h - d) / 2);
270 z1 = (centerx - hthick/2, -d);
271 z2 = (centerx + hthick/2, h);
275 draw_rounded_block (z1, z2, hthick);
276 draw_rounded_block ((0, centery - vthick/2),
277 (w, (centery + vthick/2)),
284 fet_beginchar ("Numeral comma", "comma");
288 set_char_box (0, dot_diam#, 3/2 dot_diam#, dot_diam#);
290 pat := (dot_diam / 2, 0)
291 .. (dot_diam, dot_diam / 2)
292 .. (dot_diam / 2, dot_diam)
296 pos = ypart (((w / 3, 0) -- (w / 3, dot_diam / 2))
297 intersectiontimes pat);
298 z0 = point pos of pat;
301 penpos1 (thin, alpha + 90);
303 z1l = (w / 2, -1.5 h + hair);
308 % include z0 to assist removal of overlaps
309 fill subpath (0,3) of pat
312 filldraw z1l{dir(alpha)}
314 -- z0{direction pos of pat}
315 ..tension 0.95.. {dir (180 + alpha)}z1r
323 fet_beginchar ("Numeral dash", "hyphen");
324 set_char_box (0, height# / 3, 0, height#);
326 draw_rounded_block ((-b, h / 3 - thin / 2),
327 (w, h / 3 + thin / 2), thin);
331 fet_beginchar ("Numeral dot", "period");
332 set_char_box (0, dot_diam#, 0, dot_diam#);
334 pickup pencircle scaled dot_diam;
336 drawdot (dot_diam / 2, dot_diam / 2);
344 fet_beginchar("Numeral 0", "zero");
345 set_char_box (0, 11/15 height# * widen, 0, height#);
347 message "w:" & decimal w;
348 message "h:" & decimal h;
351 penpos2 (thick, 180);
369 penlabels (1, 2, 3, 4);
379 fet_beginchar ("Numeral 1", "one");
380 save alpha, beta, gamma;
382 % set_char_box (0, 19/30 height# * widen, 0, height#);
383 set_char_box (0, 1/2 foot_width# + 3/2 thick# + 1/2 hair#,
386 message "w:" & decimal w;
387 message "h:" & decimal h;
390 calc_kuulleke (thick, alpha);
391 z1 = (3/2 thick, height);
397 beta = angle (z1l - z6);
399 penpos7 (thin, beta - 90);
402 penpos8 (thin / cosd (beta), -90);
405 penpos9 (thin, beta - 90);
406 z9r = z8r + (thin / cosd (beta)) * down;
408 penlabels (range 1 thru 9);
410 gamma = angle (length (z1r - z1), 2 kuulleke);
412 fill z2r{dir (alpha - gamma)}
414 .. {dir (alpha + gamma)}z3l
423 .. {dir (alpha - gamma)}z2r
425 .. {dir (180 + beta)}z9l
426 -- z7r{dir (180 + beta)}
427 .. {dir (beta)}cycle;
433 fet_beginchar ("Numeral 2", "two");
435 save alpha, beta, gamma, theta;
436 save flare_start_distance;
440 set_char_box (0, 22/30 height# * widen, 0, height#);
442 message "w:" & decimal w;
443 message "h:" & decimal h;
452 penpos1 (hair, 90 + beta);
453 z1 = (0, 0) + (1/2 sqrt (2) * hair) * dir (45);
455 penpos3 (hair,90 + gamma);
456 z3 = (w, thick) + (1/2 sqrt (2) * hair) * dir (-135);
458 penpos2 (thick, 90 + alpha - 15);
460 y2 = 10/16 thick / widen;
462 tolerance := epsilon;
464 % Find proper tension to exactly touch the x axis.
465 % Later on we directly use `bow'.
467 bow := z3l{dir (180 + gamma)}
468 ..tension t.. {dir (180 + alpha -5)}z2l;
469 ypart (directionpoint left of bow) < 0
472 % the return value of `solve' is stored in a dummy variable
473 t = solve f (0.8, 1.2);
476 ..tension 0.9.. {dir (alpha + 10)}z2r
479 .. {dir (180 + beta)}z1l
483 z4r = (w - thin / 2, .71 h);
489 penlabels (range 1 thru 6);
493 pat := z1l{dir (beta)}
494 ..tension t.. z4r{up}
495 .. number_flare_path (z5r, 180, 90, hair, 1.05 flare,
496 x5r - 1/2 hair, .21 h, 0.006, 0.4, 1)
498 ..tension t.. {dir (180 + beta)}z1r
501 % pickup pencircle scaled 1;
509 % TODO: should widen a bit. The right edge of the 3 bumps into next glyph in
512 fet_beginchar ("Numeral 3", "three");
513 set_char_box (0, 2/3 height# * widen, 0, height#);
515 message "w:" & decimal w;
516 message "h:" & decimal h;
520 % flare_start = 0.25;
525 % z1l = (17/16 thick, h);
527 penpos2 (7/8 thick, 180);
529 y2l = 3/4 h + thick * 3/32;
532 z3 = (w / 2, h / 2 + 1/8 thick);
535 z4 = (5/8 thick + 1/2 thin, y3);
539 y5r = 17/64 h + thick / 16;
545 penpos7 (3/2 thin, 90);
549 penlabels (range 1 thru 7);
551 save alpha, t, outer_t;
556 % pickup pencircle scaled 1;
558 fill number_flare_path (z1l, 180, 90, hair, 7/8 flare, x1l - .5 hair,
559 .16 h, 0.06, 1.5, -1)
560 ..tension outer_t.. z2l{down}
561 ..tension outer_t.. z7r{dir (180 + alpha)}
563 ..tension outer_t.. z5r{down}
564 ..tension outer_t.. number_flare_path (z6r, 180, -90, hair,
565 flare, x6l, .18 h, 0.06,
568 ..tension t.. z3l{left}
572 ..tension t.. z2r{up}
577 fet_beginchar ("Numeral 4", "four");
578 save alpha, beta, gamma;
580 set_char_box (0, 4/5 height# * widen, 0, height#);
582 message "w:" & decimal w;
583 message "h:" & decimal h;
586 calc_kuulleke (3/2 thick, alpha);
588 z1r = (w - 3/4 thick, height);
589 z5 = (thin, 1/4 height + thin);
591 beta = angle (z3r - z5);
600 penpos8 (thin, -alpha);
603 penlabels (range 1 thru 8);
605 gamma = angle (length (z1r - z1), 2 kuulleke);
607 fill z2r{dir (alpha - gamma)}
609 .. {dir (alpha + gamma)}z3l
610 .. {dir (180 + beta)}z3r
615 ..tension 0.8 and 2.. z8l{dir (beta)}
622 calc_kuulleke (thick, alpha);
624 z1r = (w - 3/4 thick, height - (3/2 thin) / cosd (alpha));
629 gamma := angle (length (z1r - z1), 2 kuulleke);
631 fill z2r{dir (alpha - gamma)}
633 .. {dir (alpha + gamma)}z3l
640 penlabels (1, 2, 3, 4, 5);
646 fet_beginchar ("Numeral 5", "five");
647 save alpha, beta, gamma, delta;
648 save inner_t, outer_t;
652 set_char_box (0, 27/40 height# * widen, 0, height#);
654 message "w:" & decimal w;
655 message "h:" & decimal h;
658 calc_kuulleke (w - thin, alpha);
660 z1 = (w / 2 + 1/8 thick, h);
663 z5l = (x1l, h - 15/16 thick);
665 penpos6 (hair, 90 - 45);
666 z6 = z5r + 1/2 hair * dir (-45);
669 z7l = (x1l, h / 2 + thin - hair);
671 penlabels (range 1 thru 7);
673 gamma = angle (length (z1r - z1), 2 kuulleke);
675 pat := z2r{dir (alpha - gamma)}
677 .. {dir (alpha + gamma)}z3l
687 delta = 180 + beta + 10;
688 z8r = (x7r, y7r - 1/16 thick + thin);
689 z8l = directionpoint dir (delta) of
690 subpath (6, 7) of pat;
692 % include intersection point to improve overlap removal
693 fill subpath (0, 6) of pat
695 .. subpath (7, length (pat)) of pat
700 x9 = .36 [x8r, x10r];
704 y10r = 1/2 [y9r, y11r];
706 penpos11 (hair, -90);
710 penlabels (range 8 thru 12);
715 fill z8r {dir (beta)}
717 ..tension outer_t.. z10r{down}
718 .. number_flare_path (z11r, 180, -90, hair, flare, x11l,
721 ..tension inner_t.. z10l{up}
722 ..tension inner_t.. z9l{left}
728 fet_beginchar ("Numeral 6", "six");
733 fet_beginchar ("Numeral 7", "seven");
735 save alpha, beta, gamma, delta;
739 set_char_box (0, 11/15 height# * widen, 0, height#);
741 message "w:" & decimal w;
742 message "h:" & decimal h;
747 penpos1 (3/2 thick, 180 + alpha);
748 penpos2 (hair, 180 + alpha - 45);
749 penpos3 (hair, 180 + alpha + 45);
751 z2 = z1l + (1/4 sqrt (2) * hair) * dir (alpha - 135);
752 z3 = z1r + (1/4 sqrt (2) * hair) * dir (alpha - 45);
753 z4 = z1 + kuulleke * dir (alpha - 90);
756 calc_kuulleke (3/2 thick, -alpha);
762 penpos5 (thin, 90 + beta);
763 z5 = (w, h) + (1/2 sqrt (2) * thin) * dir (-135);
765 gamma = angle (length (z1r - z1), 2 kuulleke);
770 fill z3l{dir (alpha - gamma)}
772 .. {dir (alpha + gamma)}z2r
773 .. z2l{dir (beta + delta)}
775 .. z5l{dir (180 + beta)}
776 .. {dir (delta - 90)}z3r
779 penlabels (1, 2, 3, 4, 5);
781 alpha := -45 * widen;
783 penpos11 (1/2 thick, 90);
784 z11 = (3/2 thin, h - (thick + thin) / 2);
786 penpos13 (thin, 90 + beta);
789 penpos12 (thick, 90 + alpha);
790 x12 = 1/2 [x11, x13] - 1/4 thick;
791 y12 = h - 15/16 thick + thin * widen;
794 z14l = (0, h - thin / 2);
797 z15l = (0, h / 2 + thin / 2);
799 penpos16 (9/8 thick, 90);
800 z16r = (thin, y11r + 2/16 thick);
802 tolerance := epsilon;
804 % Find proper tension to exactly touch the x axis.
805 % Later on we directly use `bow'.
807 bow := z11r{dir (beta)}
808 ..tension t.. {dir (alpha)}z12r;
809 ypart (directionpoint right of bow) > h
812 % the return value of `solve' is stored in a dummy variable
813 t = solve f (0.8, 1.2);
817 -- z13l{dir (180 + beta)}
818 .. {dir (180 + alpha)}z12l
819 .. {dir (180 + beta)}z11l
826 ..tension 1.5.. {dir (beta)}cycle;
828 penlabels (range 11 thru 16);
832 fet_beginchar ("Numeral 8", "eight");
835 set_char_box (0, 11/15 height# * widen, 0, height#);
837 message "w:" & decimal w;
838 message "h:" & decimal h;
843 z1 = (w / 2, h / 2 + thick / 8);
845 penpos2 (14/8 thin, 0);
846 z2 = (w / 3, h / 2 + thin);
848 penpos3 (3/2 thin, 0);
849 z3l = (0, h / 4 + thin / 2);
854 penpos5 (thick, 90 + 90 + alpha);
855 z5 = z1 + w / 4 * dir (alpha - 90);
857 penpos6 (thick, 90 + 90 + alpha);
858 z6 = z1 + (w / 4 - thin / 2) * dir (90 + alpha);
861 z7r = (x1 + .02 w, h);
863 penpos8 (3/2 thin, 0);
864 z8r = (w - thin / 2, 3/4 h + thin / 2);
866 penpos9 (13/8 thin, 0);
869 penlabels (range 1 thru 9);
874 fill z2r{dir (180 + beta)}
877 .. z5r{dir (90 + alpha)}
878 -- z6r{dir (90 + alpha)}
879 ..tension t.. z7r{right}
881 .. {dir (180 + beta)}z9r
885 .. {dir (alpha - 90)}z6l
886 -- z5l{dir (alpha - 90)}
887 ..tension t.. z4l{left}
894 fet_beginchar ("Numeral 9", "nine");
898 currentpicture := currentpicture scaled -1;
899 currentpicture := currentpicture shifted (w, h);
908 "7" kern 0.15 space#;