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