]> git.donarmstrong.com Git - lilypond.git/blob - mf/feta-macros.mf
font: clean up staffline-display in testing mode
[lilypond.git] / mf / feta-macros.mf
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.
3 %
4 % Copyright (C) 1997--2012 Han-Wen Nienhuys <hanwen@xs4all.nl>
5 %
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.
10 %
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.
15 %
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/>.
18
19
20 %
21 % debugging
22 %
23
24 input debugging-settings.mf
25
26 def print_penpos (suffix $) =
27         message
28           "z" & str$ & "l = (" & decimal x.$.l & ", " &decimal y.$.l & ");"
29           & " z" & str$ & "r = (" & decimal x.$.r & ", " & decimal y.$.r & ");";
30 enddef;
31
32
33 def test_grid =
34         if test > 1:
35                 proofrulethickness 1pt#;
36
37                 makegrid
38                   (0pt, 0pt for i := -5pt step 1pt until 5pt: , i endfor)
39                   (0pt, 0pt for i := -5pt step 1pt until 5pt: , i endfor);
40
41                 proofrulethickness .1pt#;
42
43                 makegrid
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);
46         fi;
47 enddef;
48
49
50 def treq =
51         tracingequations := tracingonline := 1;
52 enddef;
53
54
55 def draw_staff_if_debugging (expr first, last) =
56         if test <> 0:
57                 pickup pencircle scaled stafflinethickness;
58
59                 for i := first step 1 until last:
60                         draw (-staff_space,
61                               (i + stafflines_y_offset) * staff_space_rounded)
62                              -- (4 staff_space,
63                                  (i + stafflines_y_offset) * staff_space_rounded);
64                 endfor;
65         fi;
66 enddef;
67
68
69 %
70 % Draw the outline of the stafflines.  For fine tuning.
71 %
72
73 def draw_staff_outline (expr first, last, offset) =
74         if test <> 0:
75                 save p;
76                 path p;
77
78                 pickup pencircle scaled 2;
79
80                 for i := first step 1 until last:
81                         p := (-staff_space,
82                               (i + offset) * staff_space_rounded)
83                              -- (4 staff_space,
84                                  (i + offset) * staff_space_rounded);
85
86                         draw p shifted (0, .5 stafflinethickness);
87                         draw p shifted (0, -.5 stafflinethickness);
88                 endfor;
89         fi;
90 enddef;
91
92
93 %
94 % Transformations
95 %
96
97 def scaledabout (expr point, scale) =
98         shifted -point scaled scale shifted point
99 enddef;
100
101
102 %
103 % make a local (restored after endgroup) copy of t_var
104 %
105
106 def local_copy (text type, t_var) =
107         save copy_temp;
108         type copy_temp;
109         copy_temp := t_var;
110         save t_var;
111         type t_var;
112         t_var := copy_temp;
113 enddef;
114
115
116 %
117 % Urgh! Want to do parametric types
118 %
119
120 def del_picture_stack =
121         save save_picture_stack, picture_stack_idx;
122 enddef;
123
124
125 %
126 % better versions of Taupin/Egler savepic cmds
127 %
128
129 def make_picture_stack =
130         % override previous stack
131         del_picture_stack;
132         picture save_picture_stack[];
133         numeric picture_stack_idx;
134         picture_stack_idx := 0;
135
136         def push_picture (expr p) =
137                 save_picture_stack[picture_stack_idx] := p;
138                 picture_stack_idx := picture_stack_idx + 1;
139         enddef;
140
141         def pop_picture = save_picture_stack[decr picture_stack_idx] enddef;
142         def top_picture = save_picture_stack[picture_stack_idx] enddef;
143 enddef;
144
145
146 %
147 % save/restore pens
148 % why can't I delete individual pens?
149 %
150
151 def make_pen_stack =
152         del_pen_stack;
153         pen save_pen_stack[];
154         numeric pen_stack_idx;
155         pen_stack_idx := 0;
156         def push_pen (expr p) =
157                 save_pen_stack[pen_stack_idx] := p;
158                 pen_stack_idx := pen_stack_idx + 1;
159         enddef;
160         def pop_pen = save_pen_stack[decr pen_stack_idx] enddef;
161         def top_pen = save_pen_stack[pen_stack_idx] enddef;
162 enddef;
163
164
165 def del_pen_stack =
166         save save_pen_stack, pen_stack_idx;
167 enddef;
168
169
170 %
171 % drawing
172 %
173
174 def soft_penstroke text t =
175         forsuffixes e = l, r:
176                 path_.e := t;
177         endfor;
178
179         if cycle path_.l:
180                 cyclestroke_;
181         else:
182                 fill path_.l
183                 ..tension1.5.. reverse path_.r
184                 ..tension1.5.. cycle;
185         fi;
186 enddef;
187
188
189 def soft_start_penstroke text t =
190         forsuffixes e = l, r:
191                 path_.e := t;
192         endfor;
193
194         if cycle path_.l:
195                 cyclestroke_;
196         else:
197                 fill path_.l
198                 -- reverse path_.r
199                 ..tension1.5.. cycle;
200         fi;
201 enddef;
202
203
204 def soft_end_penstroke text t =
205         forsuffixes e = l, r:
206                 path_.e := t;
207         endfor;
208
209         if cycle path_.l:
210                 cyclestroke_;
211         else:
212                 fill path_.l
213                 ..tension1.5.. reverse path_.r
214                 -- cycle;
215         fi;
216 enddef;
217
218
219 %
220 % Make a round path segment going from P to Q.  2*A is the angle that the
221 % path should take.
222 %
223
224 def simple_serif (expr p, q, a) =
225         p{dir (angle (q - p) - a)}
226         .. q{-dir (angle (p - q) + a)}
227 enddef;
228
229
230 %
231 % Draw an axis aligned block making sure that edges are on pixels.
232 %
233
234 def draw_rounded_block (expr bottom_left, top_right, roundness) =
235 begingroup;
236         save size;
237         save x, y;
238
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));
244
245         z2 + (size / 2, size / 2) = top_right;
246         z4 - (size / 2, size / 2) = bottom_left;
247         y3 = y2;
248         y4 = y1;
249         x2 = x1;
250         x4 = x3;
251
252         pickup pencircle scaled size;
253
254         fill bot z1{right}
255              .. rt z1{up}
256              -- rt z2{up}
257              .. top z2{left}
258              -- top z3{left}
259              .. lft z3{down}
260              -- lft z4{down}
261              .. bot z4{right}
262              -- cycle;
263 endgroup;
264 enddef;
265
266
267 def draw_block (expr bottom_left, top_right) =
268         draw_rounded_block (bottom_left, top_right, blot_diameter);
269 enddef;
270
271
272 def draw_square_block (expr bottom_left, top_right) =
273         save x, y;
274
275         x1 = xpart bottom_left;
276         y1 = ypart bottom_left;
277         x2 = xpart top_right;
278         y2 = ypart top_right;
279
280         fill (x1, y1)
281              -- (x2, y1)
282              -- (x2, y2)
283              -- (x1, y2)
284              -- cycle;
285 enddef;
286
287
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),
291                             thickness);
292 enddef;
293
294
295 def draw_brush (expr a, w, b, v) =
296         save x, y;
297
298         z1 = a;
299         z2 = b;
300         z3 = z4 = z1;
301         z5 = z6 = z2;
302
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));
307
308         fill z3r{z3r - z5l}
309              .. z4l
310              .. {z5r - z3l}z3l
311              .. z5r{z5r - z3l}
312              .. z6l
313              .. {z3r - z5l}z5l
314              .. cycle;
315 enddef;
316
317
318 %
319 % Make a superellipsoid segment going from FROM to TO, with SUPERNESS.
320 % Take superness = sqrt(2)/2 to get a circle segment.
321 %
322 % See Knuth, p. 267 and p.126.
323
324 def super_curvelet (expr from, to, superness, dir) =
325         if dir = 1:
326                 (superness [xpart to, xpart from],
327                  superness [ypart from, ypart to]){to - from}
328         else:
329                 (superness [xpart from, xpart to],
330                  superness [ypart to, ypart from]){to - from}
331         fi
332 enddef;
333
334
335 %
336 % Bulb with smooth inside curve.
337 %
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)
343 %
344 % Note that `currentpen' must be set correctly -- only circular pens
345 % are supported properly.
346
347 def flare_path (expr pos, alpha, beta, line, flare, direction) =
348 begingroup;
349         save thick;
350
351         thick = pen_top + pen_bot;
352
353         clearxy;
354
355         penpos1' (line - thick, 180 + beta + alpha);
356         top z1'r = pos;
357
358         penpos2' (flare - thick, 180 + beta + alpha);
359         z2' = z3';
360
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));
366
367         rt x4' = x2'r - line * xpart dir (alpha);
368         y4' = y2'r - line * ypart dir (alpha);
369
370         penlabels (1', 2', 3', 4');
371
372         save t, p;
373         t = 0.833;
374         path p;
375
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)};
382
383         if direction <> 1:
384                 p := reverse p;
385         fi;
386
387 p
388 endgroup
389 enddef;
390
391
392 def brush (expr a, w, b, v) =
393 begingroup;
394         draw_brush (a, w, b, v);
395         penlabels (3, 4, 5, 6);
396 endgroup;
397 enddef;
398
399
400 %
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.
404 %
405
406 def balled_crook (expr a, w, balldiam, stem) =
407 begingroup;
408         save x, y;
409
410         penpos1 (balldiam / 2, -90);
411         penpos2 (balldiam / 2, 0);
412         penpos3 (balldiam / 2, 90);
413         penpos4 (balldiam / 2, 180);
414
415         x4r = xpart a - w;
416         y3r = ypart a + balldiam / 4;
417         x1l = x2l = x3l = x4l;
418         y1l = y2l = y3l = y4l;
419
420         penpos5 (stem, 250);
421         x5 = x4r + 9/8 balldiam;
422         y5r = y1r;
423
424         penpos6 (stem, 260);
425         x6l = xpart a;
426         y6l = ypart a;
427
428         penstroke z1e
429                   .. z2e
430                   .. z3e
431                   .. z4e
432                   .. z1e
433                   .. z5e{right}
434                   .. z6e;
435
436         penlabels (1, 2, 3, 4, 5, 6);
437 endgroup;
438 enddef;
439
440
441 def y_mirror_char =
442         currentpicture := currentpicture yscaled -1;
443
444         set_char_box (charbp, charwd, charht, chardp);
445 enddef;
446
447
448 def xy_mirror_char =
449         currentpicture := currentpicture scaled -1;
450
451         set_char_box (charwd, charbp, charht, chardp);
452 enddef;
453
454
455 %
456 % center_factor: typically .5; the larger, the larger the radius of the bulb
457 % radius factor: how much the bulb curves inward
458 %
459
460 def draw_bulb (expr turndir, zl, zr, bulb_rad, radius_factor)=
461 begingroup;
462         save rad, ang, pat;
463         path pat;
464
465         clearxy;
466
467         ang = angle (zr - zl);
468
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);
472
473         rad = bulb_rad;
474
475         z1' = z0' + radius_factor * rad * dir (ang + turndir * 100);
476         z2' = z0' + rad * dir (ang + turndir * 300);
477
478         labels (0', 1', 2');
479
480         pat = zr{dir (ang + turndir * 90)}
481                .. z1'
482                .. z2'
483                .. cycle;
484
485         % avoid grazing outlines
486         fill subpath (0, 2.5) of pat
487              -- cycle;
488 endgroup
489 enddef;
490
491
492 pi := 3.14159;
493
494
495 %
496 % To get symmetry at low resolutions we need to shift some points and
497 % paths, but not if mf2pt1 is used.
498 %
499
500 if known miterlimit:
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;
505 else:
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;
510 fi;