1 % Feta (not the Font-En-Tja) music font -- auxiliary macros for both feta and parmesan fonts
2 % This file is part of LilyPond, the GNU music typesetter.
4 % Copyright (C) 1997--2012 Han-Wen Nienhuys <hanwen@xs4all.nl>
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/>.
24 input debugging-settings.mf
26 def print_penpos (suffix $) =
28 "z" & str$ & "l = (" & decimal x.$.l & ", " &decimal y.$.l & ");"
29 & " z" & str$ & "r = (" & decimal x.$.r & ", " & decimal y.$.r & ");";
35 proofrulethickness 1pt#;
38 (0pt, 0pt for i := -5pt step 1pt until 5pt: , i endfor)
39 (0pt, 0pt for i := -5pt step 1pt until 5pt: , i endfor);
41 proofrulethickness .1pt#;
44 (0pt, 0pt for i := -4.8pt step .2pt until 4.8pt: , i endfor)
45 (0pt, 0pt for i := -4.8pt step .2pt until 4.8pt: , i endfor);
51 tracingequations := tracingonline := 1;
55 def draw_staff_if_debugging (expr first, last) =
57 pickup pencircle scaled stafflinethickness;
59 for i := first step 1 until last:
61 (i + stafflines_y_offset) * staff_space_rounded)
63 (i + stafflines_y_offset) * staff_space_rounded);
70 % Draw the outline of the stafflines. For fine tuning.
73 def draw_staff_outline (expr first, last, offset) =
78 pickup pencircle scaled 2;
80 for i := first step 1 until last:
82 (i + offset) * staff_space_rounded)
84 (i + offset) * staff_space_rounded);
86 draw p shifted (0, .5 stafflinethickness);
87 draw p shifted (0, -.5 stafflinethickness);
97 def scaledabout (expr point, scale) =
98 shifted -point scaled scale shifted point
103 % make a local (restored after endgroup) copy of t_var
106 def local_copy (text type, t_var) =
117 % Urgh! Want to do parametric types
120 def del_picture_stack =
121 save save_picture_stack, picture_stack_idx;
126 % better versions of Taupin/Egler savepic cmds
129 def make_picture_stack =
130 % override previous stack
132 picture save_picture_stack[];
133 numeric picture_stack_idx;
134 picture_stack_idx := 0;
136 def push_picture (expr p) =
137 save_picture_stack[picture_stack_idx] := p;
138 picture_stack_idx := picture_stack_idx + 1;
141 def pop_picture = save_picture_stack[decr picture_stack_idx] enddef;
142 def top_picture = save_picture_stack[picture_stack_idx] enddef;
148 % why can't I delete individual pens?
153 pen save_pen_stack[];
154 numeric pen_stack_idx;
156 def push_pen (expr p) =
157 save_pen_stack[pen_stack_idx] := p;
158 pen_stack_idx := pen_stack_idx + 1;
160 def pop_pen = save_pen_stack[decr pen_stack_idx] enddef;
161 def top_pen = save_pen_stack[pen_stack_idx] enddef;
166 save save_pen_stack, pen_stack_idx;
174 def soft_penstroke text t =
175 forsuffixes e = l, r:
183 ..tension1.5.. reverse path_.r
184 ..tension1.5.. cycle;
189 def soft_start_penstroke text t =
190 forsuffixes e = l, r:
199 ..tension1.5.. cycle;
204 def soft_end_penstroke text t =
205 forsuffixes e = l, r:
213 ..tension1.5.. reverse path_.r
220 % Make a round path segment going from P to Q. 2*A is the angle that the
224 def simple_serif (expr p, q, a) =
225 p{dir (angle (q - p) - a)}
226 .. q{-dir (angle (p - q) + a)}
231 % Draw an axis aligned block making sure that edges are on pixels.
234 def draw_rounded_block (expr bottom_left, top_right, roundness) =
239 % Originally, there was `floor' instead of `round', but this is
240 % not correct because pens use `round' also.
241 size = round min (roundness,
242 xpart (top_right - bottom_left),
243 ypart (top_right - bottom_left));
245 z2 + (size / 2, size / 2) = top_right;
246 z4 - (size / 2, size / 2) = bottom_left;
252 pickup pencircle scaled size;
267 def draw_block (expr bottom_left, top_right) =
268 draw_rounded_block (bottom_left, top_right, blot_diameter);
272 def draw_square_block (expr bottom_left, top_right) =
275 x1 = xpart bottom_left;
276 y1 = ypart bottom_left;
277 x2 = xpart top_right;
278 y2 = ypart top_right;
288 def draw_gridline (expr bottom_left, top_right, thickness) =
289 draw_rounded_block (bottom_left - (thickness / 2, thickness / 2),
290 top_right + (thickness / 2, thickness / 2),
295 def draw_brush (expr a, w, b, v) =
303 penpos3 (w, angle (z2 - z1) + 90);
304 penpos4 (w, angle (z2 - z1));
305 penpos5 (v, angle (z1 - z2) + 90);
306 penpos6 (v, angle (z1 - z2));
319 % Make a superellipsoid segment going from FROM to TO, with SUPERNESS.
320 % Take superness = sqrt(2)/2 to get a circle segment.
322 % See Knuth, p. 267 and p.126.
324 def super_curvelet (expr from, to, superness, dir) =
326 (superness [xpart to, xpart from],
327 superness [ypart from, ypart to]){to - from}
329 (superness [xpart from, xpart to],
330 superness [ypart to, ypart from]){to - from}
336 % Bulb with smooth inside curve.
338 % alpha = start direction
339 % beta = which side to turn to
340 % flare = diameter of the bulb
341 % line = diameter of line attachment
342 % direction = is ink on left or right side (1 or -1)
344 % Note that `currentpen' must be set correctly -- only circular pens
345 % are supported properly.
347 def flare_path (expr pos, alpha, beta, line, flare, direction) =
351 thick = pen_top + pen_bot;
355 penpos1' (line - thick, 180 + beta + alpha);
358 penpos2' (flare - thick, 180 + beta + alpha);
361 penpos3' (flare - thick, 0 + alpha);
362 rt x3'l = hround (x1'r
363 + (1/2 + 0.43) * flare * xpart dir (alpha + beta));
364 bot y2'l = vround (y1'r
365 + (1 + 0.43) * flare * ypart dir (alpha + beta));
367 rt x4' = x2'r - line * xpart dir (alpha);
368 y4' = y2'r - line * ypart dir (alpha);
370 penlabels (1', 2', 3', 4');
376 p := z1'r{dir (alpha)}
377 .. z3'r{dir (180 + alpha - beta)}
378 .. z2'l{dir (alpha + 180)}
379 .. z3'l{dir (180 + alpha + beta)}
380 ..tension t.. z4'{dir (180 + alpha + beta)}
381 .. z1'l{dir (alpha + 180)};
392 def brush (expr a, w, b, v) =
394 draw_brush (a, w, b, v);
395 penlabels (3, 4, 5, 6);
401 % Draw a (rest) crook, starting at thickness STEM in point A,
402 % ending a ball W to the left, diameter BALLDIAM.
403 % ypart of the center of the ball is BALLDIAM/4 lower than ypart A.
406 def balled_crook (expr a, w, balldiam, stem) =
410 penpos1 (balldiam / 2, -90);
411 penpos2 (balldiam / 2, 0);
412 penpos3 (balldiam / 2, 90);
413 penpos4 (balldiam / 2, 180);
416 y3r = ypart a + balldiam / 4;
417 x1l = x2l = x3l = x4l;
418 y1l = y2l = y3l = y4l;
421 x5 = x4r + 9/8 balldiam;
436 penlabels (1, 2, 3, 4, 5, 6);
442 currentpicture := currentpicture yscaled -1;
444 set_char_box (charbp, charwd, charht, chardp);
449 currentpicture := currentpicture scaled -1;
451 set_char_box (charwd, charbp, charht, chardp);
456 % center_factor: typically .5; the larger, the larger the radius of the bulb
457 % radius factor: how much the bulb curves inward
460 def draw_bulb (expr turndir, zl, zr, bulb_rad, radius_factor)=
467 ang = angle (zr - zl);
469 % don't get near infinity
470 % z0 = zr + bulb_rad * (zl - zr) / length (zr - zl);
471 z0' = zr + bulb_rad / length (zr - zl) * (zl - zr);
475 z1' = z0' + radius_factor * rad * dir (ang + turndir * 100);
476 z2' = z0' + rad * dir (ang + turndir * 300);
480 pat = zr{dir (ang + turndir * 90)}
485 % avoid grazing outlines
486 fill subpath (0, 2.5) of pat
496 % To get symmetry at low resolutions we need to shift some points and
497 % paths, but not if mf2pt1 is used.
501 vardef hfloor primary x = x enddef;
502 vardef vfloor primary y = y enddef;
503 vardef hceiling primary x = x enddef;
504 vardef vceiling primary y = y enddef;
506 vardef hfloor primary x = floor x enddef;
507 vardef vfloor primary y = (floor y.o_)_o_ enddef;
508 vardef hceiling primary x = ceiling x enddef;
509 vardef vceiling primary y = (ceiling y.o_)_o_ enddef;