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--2015 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/>.
25 def print_penpos (suffix $) =
27 "z" & str$ & "l = (" & decimal x.$.l & ", " &decimal y.$.l & ");"
28 & " z" & str$ & "r = (" & decimal x.$.r & ", " & decimal y.$.r & ");";
34 proofrulethickness 1pt#;
37 (0pt, 0pt for i := -5pt step 1pt until 5pt: , i endfor)
38 (0pt, 0pt for i := -5pt step 1pt until 5pt: , i endfor);
40 proofrulethickness .1pt#;
43 (0pt, 0pt for i := -4.8pt step .2pt until 4.8pt: , i endfor)
44 (0pt, 0pt for i := -4.8pt step .2pt until 4.8pt: , i endfor);
50 tracingequations := tracingonline := 1;
54 def draw_staff_if_debugging (expr first, last) =
56 pickup pencircle scaled stafflinethickness;
58 for i := first step 1 until last:
60 (i + stafflines_y_offset) * staff_space_rounded)
62 (i + stafflines_y_offset) * staff_space_rounded);
69 % Draw the outline of the stafflines. For fine tuning.
72 def draw_staff_outline (expr first, last, offset) =
77 pickup pencircle scaled 2;
79 for i := first step 1 until last:
81 (i + offset) * staff_space_rounded)
83 (i + offset) * staff_space_rounded);
85 draw p shifted (0, .5 stafflinethickness);
86 draw p shifted (0, -.5 stafflinethickness);
96 def scaledabout (expr point, scale) =
97 shifted -point scaled scale shifted point
102 % make a local (restored after endgroup) copy of t_var
105 def local_copy (text type, t_var) =
116 % Urgh! Want to do parametric types
119 def del_picture_stack =
120 save save_picture_stack, picture_stack_idx;
125 % better versions of Taupin/Egler savepic cmds
128 def make_picture_stack =
129 % override previous stack
131 picture save_picture_stack[];
132 numeric picture_stack_idx;
133 picture_stack_idx := 0;
135 def push_picture (expr p) =
136 save_picture_stack[picture_stack_idx] := p;
137 picture_stack_idx := picture_stack_idx + 1;
140 def pop_picture = save_picture_stack[decr picture_stack_idx] enddef;
141 def top_picture = save_picture_stack[picture_stack_idx] enddef;
147 % why can't I delete individual pens?
152 pen save_pen_stack[];
153 numeric pen_stack_idx;
155 def push_pen (expr p) =
156 save_pen_stack[pen_stack_idx] := p;
157 pen_stack_idx := pen_stack_idx + 1;
159 def pop_pen = save_pen_stack[decr pen_stack_idx] enddef;
160 def top_pen = save_pen_stack[pen_stack_idx] enddef;
165 save save_pen_stack, pen_stack_idx;
173 def soft_penstroke text t =
174 forsuffixes e = l, r:
182 ..tension1.5.. reverse path_.r
183 ..tension1.5.. cycle;
188 def soft_start_penstroke text t =
189 forsuffixes e = l, r:
198 ..tension1.5.. cycle;
203 def soft_end_penstroke text t =
204 forsuffixes e = l, r:
212 ..tension1.5.. reverse path_.r
219 % Make a round path segment going from P to Q. 2*A is the angle that the
223 def simple_serif (expr p, q, a) =
224 p{dir (angle (q - p) - a)}
225 .. q{-dir (angle (p - q) + a)}
230 % Draw an axis aligned block making sure that edges are on pixels.
233 def draw_rounded_block (expr bottom_left, top_right, roundness) =
238 % Originally, there was `floor' instead of `round', but this is
239 % not correct because pens use `round' also.
240 size = round min (roundness,
241 xpart (top_right - bottom_left),
242 ypart (top_right - bottom_left));
244 z2 + (size / 2, size / 2) = top_right;
245 z4 - (size / 2, size / 2) = bottom_left;
251 pickup pencircle scaled size;
266 def draw_block (expr bottom_left, top_right) =
267 draw_rounded_block (bottom_left, top_right, blot_diameter);
271 def draw_square_block (expr bottom_left, top_right) =
274 x1 = xpart bottom_left;
275 y1 = ypart bottom_left;
276 x2 = xpart top_right;
277 y2 = ypart top_right;
287 def draw_gridline (expr bottom_left, top_right, thickness) =
288 draw_rounded_block (bottom_left - (thickness / 2, thickness / 2),
289 top_right + (thickness / 2, thickness / 2),
294 def draw_brush (expr a, w, b, v) =
302 penpos3 (w, angle (z2 - z1) + 90);
303 penpos4 (w, angle (z2 - z1));
304 penpos5 (v, angle (z1 - z2) + 90);
305 penpos6 (v, angle (z1 - z2));
318 % Make a superellipsoid segment going from FROM to TO, with SUPERNESS.
319 % Take superness = sqrt(2)/2 to get a circle segment.
321 % See Knuth, p. 267 and p.126.
323 def super_curvelet (expr from, to, superness, dir) =
325 (superness [xpart to, xpart from],
326 superness [ypart from, ypart to]){to - from}
328 (superness [xpart from, xpart to],
329 superness [ypart to, ypart from]){to - from}
335 % Bulb with smooth inside curve.
337 % alpha = start direction
338 % beta = which side to turn to
339 % flare = diameter of the bulb
340 % line = diameter of line attachment
341 % direction = is ink on left or right side (1 or -1)
343 % Note that `currentpen' must be set correctly -- only circular pens
344 % are supported properly.
346 def flare_path (expr pos, alpha, beta, line, flare, direction) =
350 thick = pen_top + pen_bot;
354 penpos1' (line - thick, 180 + beta + alpha);
357 penpos2' (flare - thick, 180 + beta + alpha);
360 penpos3' (flare - thick, 0 + alpha);
361 rt x3'l = hround (x1'r
362 + (1/2 + 0.43) * flare * xpart dir (alpha + beta));
363 bot y2'l = vround (y1'r
364 + (1 + 0.43) * flare * ypart dir (alpha + beta));
366 rt x4' = x2'r - line * xpart dir (alpha);
367 y4' = y2'r - line * ypart dir (alpha);
369 penlabels (1', 2', 3', 4');
375 p := z1'r{dir (alpha)}
376 .. z3'r{dir (180 + alpha - beta)}
377 .. z2'l{dir (alpha + 180)}
378 .. z3'l{dir (180 + alpha + beta)}
379 ..tension t.. z4'{dir (180 + alpha + beta)}
380 .. z1'l{dir (alpha + 180)};
391 def brush (expr a, w, b, v) =
393 draw_brush (a, w, b, v);
394 penlabels (3, 4, 5, 6);
400 % Draw a (rest) crook, starting at thickness STEM in point A,
401 % ending a ball W to the left, diameter BALLDIAM.
402 % ypart of the center of the ball is BALLDIAM/4 lower than ypart A.
405 def balled_crook (expr a, w, balldiam, stem) =
409 penpos1 (balldiam / 2, -90);
410 penpos2 (balldiam / 2, 0);
411 penpos3 (balldiam / 2, 90);
412 penpos4 (balldiam / 2, 180);
415 y3r = ypart a + balldiam / 4;
416 x1l = x2l = x3l = x4l;
417 y1l = y2l = y3l = y4l;
420 x5 = x4r + 9/8 balldiam;
435 penlabels (1, 2, 3, 4, 5, 6);
441 currentpicture := currentpicture yscaled -1;
443 set_char_box (charbp, charwd, charht, chardp);
448 currentpicture := currentpicture scaled -1;
450 set_char_box (charwd, charbp, charht, chardp);
455 % center_factor: typically .5; the larger, the larger the radius of the bulb
456 % radius factor: how much the bulb curves inward
459 def draw_bulb (expr turndir, zl, zr, bulb_rad, radius_factor)=
466 ang = angle (zr - zl);
468 % don't get near infinity
469 % z0 = zr + bulb_rad * (zl - zr) / length (zr - zl);
470 z0' = zr + bulb_rad / length (zr - zl) * (zl - zr);
474 z1' = z0' + radius_factor * rad * dir (ang + turndir * 100);
475 z2' = z0' + rad * dir (ang + turndir * 300);
479 pat = zr{dir (ang + turndir * 90)}
484 % avoid grazing outlines
485 fill subpath (0, 2.5) of pat
495 % To get symmetry at low resolutions we need to shift some points and
496 % paths, but not if mf2pt1 is used.
500 vardef hfloor primary x = x enddef;
501 vardef vfloor primary y = y enddef;
502 vardef hceiling primary x = x enddef;
503 vardef vceiling primary y = y enddef;
505 vardef hfloor primary x = floor x enddef;
506 vardef vfloor primary y = (floor y.o_)_o_ enddef;
507 vardef hceiling primary x = ceiling x enddef;
508 vardef vceiling primary y = (ceiling y.o_)_o_ enddef;