]> git.donarmstrong.com Git - lilypond.git/blobdiff - mf/feta-macros.mf
Web-ja: update introduction
[lilypond.git] / mf / feta-macros.mf
index ae413e6a516b647fc7ef2cbabee9462c921d47b3..89458e3c3dbb7e69358eed3f70813507bb988e98 100644 (file)
+% Feta (not the Font-En-Tja) music font -- auxiliary macros for both feta and parmesan fonts
+% This file is part of LilyPond, the GNU music typesetter.
+%
+% Copyright (C) 1997--2015 Han-Wen Nienhuys <hanwen@xs4all.nl>
+%
+% The LilyPond font is free software: you can redistribute it and/or modify
+% it under the terms of the GNU General Public License as published by
+% the Free Software Foundation, either version 3 of the License, or
+% (at your option) any later version, or under the SIL Open Font License.
+%
+% LilyPond is distributed in the hope that it will be useful,
+% but WITHOUT ANY WARRANTY; without even the implied warranty of
+% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+% GNU General Public License for more details.
+%
+% You should have received a copy of the GNU General Public License
+% along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
+
+
 %
 % debugging
 %
+
+
+def print_penpos (suffix $) =
+       message
+         "z" & str$ & "l = (" & decimal x.$.l & ", " &decimal y.$.l & ");"
+         & " z" & str$ & "r = (" & decimal x.$.r & ", " & decimal y.$.r & ");";
+enddef;
+
+
 def test_grid =
-if test>1:
-       proofrulethickness 1pt#;
-       makegrid(0pt,0pt for i:=-5pt step 1pt until 5pt: ,i endfor)
-               (0pt,0pt for i:=-5pt step 1pt until 5pt: ,i endfor);
-       proofrulethickness .1pt#;
-       makegrid(0pt,0pt for i:=-4.8pt step .2pt until 4.8pt: ,i endfor)
-               (0pt,0pt for i:=-4.8pt step .2pt until 4.8pt: ,i endfor);
-fi
-       enddef;
+       if test > 1:
+               proofrulethickness 1pt#;
+
+               makegrid
+                 (0pt, 0pt for i := -5pt step 1pt until 5pt: , i endfor)
+                 (0pt, 0pt for i := -5pt step 1pt until 5pt: , i endfor);
+
+               proofrulethickness .1pt#;
+
+               makegrid
+                 (0pt, 0pt for i := -4.8pt step .2pt until 4.8pt: , i endfor)
+                 (0pt, 0pt for i := -4.8pt step .2pt until 4.8pt: , i endfor);
+       fi;
+enddef;
+
 
 def treq =
        tracingequations := tracingonline := 1;
 enddef;
 
 
-def draw_staff(expr first, last, offset)=
-if test <> 0:
-       pickup pencircle scaled stafflinethickness;
-       for i:= first step 1 until last:
-               draw (- staff_space, (i + offset) * staff_space) .. (4 staff_space,( i+ offset)* staff_space);
-       endfor
-fi;
+def draw_staff_if_debugging (expr first, last) =
+       if test <> 0:
+               pickup pencircle scaled stafflinethickness;
+
+               for i := first step 1 until last:
+                       draw (-staff_space,
+                             (i + stafflines_y_offset) * staff_space_rounded)
+                            -- (4 staff_space,
+                                (i + stafflines_y_offset) * staff_space_rounded);
+               endfor;
+       fi;
+enddef;
+
+
+%
+% Draw the outline of the stafflines.  For fine tuning.
+%
+
+def draw_staff_outline (expr first, last, offset) =
+       if test <> 0:
+               save p;
+               path p;
+
+               pickup pencircle scaled 2;
+
+               for i := first step 1 until last:
+                       p := (-staff_space,
+                             (i + offset) * staff_space_rounded)
+                            -- (4 staff_space,
+                                (i + offset) * staff_space_rounded);
 
+                       draw p shifted (0, .5 stafflinethickness);
+                       draw p shifted (0, -.5 stafflinethickness);
+               endfor;
+       fi;
 enddef;
 
 
 %
-% Transforms
+% Transformations
 %
 
-def scaledabout(expr point, scale) =
+def scaledabout (expr point, scale) =
        shifted -point scaled scale shifted point
 enddef;
 
 
 %
-% make a local (restored after endgroup) copy of t_var 
+% make a local (restored after endgroup) copy of t_var
 %
-def local_copy(text type, t_var)=
+
+def local_copy (text type, t_var) =
        save copy_temp;
-       type copy_temp; 
+       type copy_temp;
        copy_temp := t_var;
        save t_var;
        type t_var;
@@ -54,145 +116,217 @@ enddef;
 % Urgh! Want to do parametric types
 %
 
-def del_picture_stack=
+def del_picture_stack =
        save save_picture_stack, picture_stack_idx;
 enddef;
 
-% better versions of Taupin/Egler savepic cmds
+
 %
+% better versions of Taupin/Egler savepic cmds
 %
-def make_picture_stack = 
-       % override previous stack.
+
+def make_picture_stack =
+       % override previous stack
        del_picture_stack;
        picture save_picture_stack[];
        numeric picture_stack_idx;
        picture_stack_idx := 0;
-       def push_picture(expr p) = 
-               save_picture_stack[picture_stack_idx] := p ;
+
+       def push_picture (expr p) =
+               save_picture_stack[picture_stack_idx] := p;
                picture_stack_idx := picture_stack_idx + 1;
        enddef;
-       def pop_picture =  save_picture_stack[decr picture_stack_idx] enddef;
+
+       def pop_picture = save_picture_stack[decr picture_stack_idx] enddef;
        def top_picture = save_picture_stack[picture_stack_idx] enddef;
 enddef;
 
 
+%
 % save/restore pens
 % why can't I delete individual pens?
+%
+
 def make_pen_stack =
        del_pen_stack;
        pen save_pen_stack[];
        numeric pen_stack_idx;
        pen_stack_idx := 0;
-       def push_pen(expr p) = 
-               save_pen_stack[pen_stack_idx] := p ;
-               pen_stack_idx := pen_stack_idx +1;
+       def push_pen (expr p) =
+               save_pen_stack[pen_stack_idx] := p;
+               pen_stack_idx := pen_stack_idx + 1;
        enddef;
-       def pop_pen =  save_pen_stack[decr pen_stack_idx] enddef;
+       def pop_pen = save_pen_stack[decr pen_stack_idx] enddef;
        def top_pen = save_pen_stack[pen_stack_idx] enddef;
 enddef;
-def del_pen_stack=
+
+
+def del_pen_stack =
        save save_pen_stack, pen_stack_idx;
 enddef;
 
+
 %
 % drawing
 %
 
 def soft_penstroke text t =
-       forsuffixes e = l,r: path_.e:=t; endfor
+       forsuffixes e = l, r:
+               path_.e := t;
+       endfor;
+
        if cycle path_.l:
-         cyclestroke_
+               cyclestroke_;
        else:
-         fill path_.l .. tension1.5 .. reverse path_.r .. tension1.5 .. cycle
-       fi
+               fill path_.l
+               ..tension1.5.. reverse path_.r
+               ..tension1.5.. cycle;
+       fi;
+enddef;
+
+
+def soft_start_penstroke text t =
+       forsuffixes e = l, r:
+               path_.e := t;
+       endfor;
+
+       if cycle path_.l:
+               cyclestroke_;
+       else:
+               fill path_.l
+               -- reverse path_.r
+               ..tension1.5.. cycle;
+       fi;
+enddef;
+
+
+def soft_end_penstroke text t =
+       forsuffixes e = l, r:
+               path_.e := t;
+       endfor;
+
+       if cycle path_.l:
+               cyclestroke_;
+       else:
+               fill path_.l
+               ..tension1.5.. reverse path_.r
+               -- cycle;
+       fi;
 enddef;
 
 
 %
-% make a round path segment going from P to Q. 2*A is the angle that the 
+% Make a round path segment going from P to Q.  2*A is the angle that the
 % path should take.
 %
 
-def simple_serif(expr p,q, a)= 
-       p{dir(angle(q-p) -a)} .. q{ - dir(angle(p -q) + a)}
+def simple_serif (expr p, q, a) =
+       p{dir (angle (q - p) - a)}
+       .. q{-dir (angle (p - q) + a)}
 enddef;
-%
+
 
 %
-% draw an axis aligned block making sure that edges are on pixels.
+% Draw an axis aligned block making sure that edges are on pixels.
 %
 
 def draw_rounded_block (expr bottom_left, top_right, roundness) =
-       save round;
-       round = floor min(roundness,xpart (top_right-bottom_left),
-                                   ypart (top_right-bottom_left));
-       pickup pencircle scaled round;
-  
-        begingroup;
-        save x,y;
-       z2+(round/2,round/2) = top_right;
-       z4-(round/2,round/2) = bottom_left;
-        y3 = y2;
-        y4 = y1;
-        x2 = x1;
-        x4 = x3;
-       fill bot z1 .. rt z1 --- rt z2 .. top z2 ---
-            top z3 .. lft z3 --- lft z4 .. bot z4 --- cycle;
-        endgroup;
-        enddef;
-  
-
-
- def draw_block (expr bottom_left, top_right) =
-       draw_rounded_block (bottom_left, top_right, blot_diameter);
-       enddef;
-
- def draw_square_block (expr bottom_left, top_right) =
-       save x,y;
+begingroup;
+       save size;
+       save x, y;
+
+       % Originally, there was `floor' instead of `round', but this is
+       % not correct because pens use `round' also.
+       size = round min (roundness,
+                         xpart (top_right - bottom_left),
+                         ypart (top_right - bottom_left));
+
+       z2 + (size / 2, size / 2) = top_right;
+       z4 - (size / 2, size / 2) = bottom_left;
+       y3 = y2;
+       y4 = y1;
+       x2 = x1;
+       x4 = x3;
+
+       pickup pencircle scaled size;
+
+       fill bot z1{right}
+            .. rt z1{up}
+            -- rt z2{up}
+            .. top z2{left}
+            -- top z3{left}
+            .. lft z3{down}
+            -- lft z4{down}
+            .. bot z4{right}
+            -- cycle;
+endgroup;
+enddef;
+
+
+def draw_block (expr bottom_left, top_right) =
+       draw_rounded_block (bottom_left, top_right, blot_diameter);
+enddef;
+
+
+def draw_square_block (expr bottom_left, top_right) =
+       save x, y;
+
        x1 = xpart bottom_left;
        y1 = ypart bottom_left;
        x2 = xpart top_right;
        y2 = ypart top_right;
 
+       fill (x1, y1)
+            -- (x2, y1)
+            -- (x2, y2)
+            -- (x1, y2)
+            -- cycle;
+enddef;
+
 
-       fill (x1,y1) --- (x2,y1) --- (x2,y2) --- (x1,y2) --- cycle; 
-       enddef;
+def draw_gridline (expr bottom_left, top_right, thickness) =
+       draw_rounded_block (bottom_left - (thickness / 2, thickness / 2),
+                           top_right + (thickness / 2, thickness / 2),
+                           thickness);
+enddef;
 
 
- def draw_gridline (expr bottom_left,top_right,thickness) =
-       draw_rounded_block (bottom_left-(thickness/2,thickness/2),
-                           top_right+(thickness/2,thickness/2),
-                           thickness);
-       enddef;
-       
+def draw_brush (expr a, w, b, v) =
+       save x, y;
 
-def draw_brush(expr a,w,b,v) =
-       save x,y;
-       z1=a; z2=b;
-       penpos3(w,angle(z2-z1)+90);
-       penpos4(w,angle(z2-z1));
-       penpos5(v,angle(z1-z2)+90);
-       penpos6(v,angle(z1-z2));
+       z1 = a;
+       z2 = b;
        z3 = z4 = z1;
        z5 = z6 = z2;
 
-       fill z3r{z3r-z5l}..z4l..{z5r-z3l}z3l..z5r{z5r-z3l}..z6l..{z3r-z5l}z5l..cycle;
+       penpos3 (w, angle (z2 - z1) + 90);
+       penpos4 (w, angle (z2 - z1));
+       penpos5 (v, angle (z1 - z2) + 90);
+       penpos6 (v, angle (z1 - z2));
+
+       fill z3r{z3r - z5l}
+            .. z4l
+            .. {z5r - z3l}z3l
+            .. z5r{z5r - z3l}
+            .. z6l
+            .. {z3r - z5l}z5l
+            .. cycle;
 enddef;
 
 
-
 %
-% make a superellipsoid segment going from FROM to TO, with SUPERNESS.  
-% Take superness = sqrt(2)/2 to get a circle segment 
+% Make a superellipsoid segment going from FROM to TO, with SUPERNESS.
+% Take superness = sqrt(2)/2 to get a circle segment.
 %
-% see Knuth, p. 267 and p.126
-def super_curvelet(expr from, to, superness, dir) =
+% See Knuth, p. 267 and p.126.
+
+def super_curvelet (expr from, to, superness, dir) =
        if dir = 1:
-        (superness [xpart to, xpart from], superness [ypart from,ypart to]){to - from}
+               (superness [xpart to, xpart from],
+                superness [ypart from, ypart to]){to - from}
        else:
-        (superness [xpart from, xpart to], superness [ypart  to,ypart from]){to - from}
+               (superness [xpart from, xpart to],
+                superness [ypart to, ypart from]){to - from}
        fi
 enddef;
 
@@ -200,108 +334,176 @@ enddef;
 %
 % Bulb with smooth inside curve.
 %
-% alpha = start direction.
-% beta = which side to turn to.
+% alpha = start direction
+% beta = which side to turn to
 % flare = diameter of the bulb
 % line = diameter of line attachment
 % direction = is ink on left or right side (1 or -1)
 %
-def flare_path(expr pos,alpha,beta,line,flare, direction) =
-       begingroup;
+% Note that `currentpen' must be set correctly -- only circular pens
+% are supported properly.
+
+def flare_path (expr pos, alpha, beta, line, flare, direction) =
+begingroup;
+       save thick;
+
+       thick = pen_top + pen_bot;
+
        clearxy;
-       penpos1(line,180+beta+alpha);
-       z1r=pos;
-       penpos2(flare,180+beta+alpha);
-       z2=z3;
-       penpos3(flare,0+alpha);
-       z3l=z1r+(1/2+0.43)*flare*dir(alpha+beta) ;
-       save taille;
-       taille = 0.0;
-       z4=z2r-  line * dir(alpha);
-       penlabels(1,2,3,4);
-       pickup pencircle;
-       save t; t=0.833;
-       save p; 
+
+       penpos1' (line - thick, 180 + beta + alpha);
+       top z1'r = pos;
+
+       penpos2' (flare - thick, 180 + beta + alpha);
+       z2' = z3';
+
+       penpos3' (flare - thick, 0 + alpha);
+       rt x3'l = hround (x1'r
+                         + (1/2 + 0.43) * flare * xpart dir (alpha + beta));
+       bot y2'l = vround (y1'r
+                          + (1 + 0.43) * flare * ypart dir (alpha + beta));
+
+       rt x4' = x2'r - line * xpart dir (alpha);
+       y4' = y2'r - line * ypart dir (alpha);
+
+       penlabels (1', 2', 3', 4');
+
+       save t, p;
+       t = 0.833;
        path p;
-       p:=z1r{dir(alpha)}..z3r{dir(180+alpha-beta)}..z2l{dir(alpha+180)}
-               ..z3l{dir(180+alpha+beta)}..tension t
-               ..z4{dir(180+alpha+beta)}..z1l{dir(alpha+180)};
 
-       if direction = 1:
-               p
-       else:
-               reverse p
-       fi
-       endgroup
-       enddef;
+       p := z1'r{dir (alpha)}
+            .. z3'r{dir (180 + alpha - beta)}
+            .. z2'l{dir (alpha + 180)}
+            .. z3'l{dir (180 + alpha + beta)}
+            ..tension t.. z4'{dir (180 + alpha + beta)}
+            .. z1'l{dir (alpha + 180)};
 
+       if direction <> 1:
+               p := reverse p;
+       fi;
+
+p
+endgroup
+enddef;
 
 
-def brush(expr a,w,b,v) =
-       begingroup;
-       draw_brush(a,w,b,v);    
-       penlabels(3,4,5,6);
-       endgroup;
+def brush (expr a, w, b, v) =
+begingroup;
+       draw_brush (a, w, b, v);
+       penlabels (3, 4, 5, 6);
+endgroup;
 enddef;
 
+
 %
 % Draw a (rest) crook, starting at thickness STEM in point A,
-% ending a ball W to the left, diameter BALLDIAM
-% ypart of the center of the ball is BALLDIAM/4 lower than ypart A
+% ending a ball W to the left, diameter BALLDIAM.
+% ypart of the center of the ball is BALLDIAM/4 lower than ypart A.
 %
-def balled_crook(expr a, w, balldiam, stem) =
+
+def balled_crook (expr a, w, balldiam, stem) =
 begingroup;
-       save x,y;
-       penpos1(balldiam/2,-90);
-       penpos2(balldiam/2,0);
-       penpos3(balldiam/2,90);
-       penpos4(balldiam/2,180);
-       x4r=xpart a-w; y3r=ypart a+balldiam/4;
-       x1l=x2l=x3l=x4l;
-       y1l=y2l=y3l=y4l;
-       penpos5(stem,250);
-       x5=x4r+9/8balldiam; y5r=y1r;
-       penpos6(stem,260);
-       x6l=xpart a; y6l=ypart a;
-       penstroke z1e..z2e..z3e..z4e..z1e..z5e{right}..z6e;
-       penlabels(1,2,3,4,5,6);
+       save x, y;
+
+       penpos1 (balldiam / 2, -90);
+       penpos2 (balldiam / 2, 0);
+       penpos3 (balldiam / 2, 90);
+       penpos4 (balldiam / 2, 180);
+
+       x4r = xpart a - w;
+       y3r = ypart a + balldiam / 4;
+       x1l = x2l = x3l = x4l;
+       y1l = y2l = y3l = y4l;
+
+       penpos5 (stem, 250);
+       x5 = x4r + 9/8 balldiam;
+       y5r = y1r;
+
+       penpos6 (stem, 260);
+       x6l = xpart a;
+       y6l = ypart a;
+
+       penstroke z1e
+                 .. z2e
+                 .. z3e
+                 .. z4e
+                 .. z1e
+                 .. z5e{right}
+                 .. z6e;
+
+       penlabels (1, 2, 3, 4, 5, 6);
 endgroup;
 enddef;
 
 
 def y_mirror_char =
        currentpicture := currentpicture yscaled -1;
-       set_char_box(charbp, charwd, charht, chardp);
+
+       set_char_box (charbp, charwd, charht, chardp);
 enddef;
 
 
 def xy_mirror_char =
        currentpicture := currentpicture scaled -1;
-       set_char_box(charwd, charbp, charht, chardp);
+
+       set_char_box (charwd, charbp, charht, chardp);
 enddef;
 
+
 %
-% center_factor: typically .5, the larger, the larger the radius of the bulb
+% center_factor: typically .5; the larger, the larger the radius of the bulb
 % radius factor: how much the bulb curves inward
 %
-def draw_bulb(expr turndir, zl, zr, bulb_rad, radius_factor)=
-       begingroup;
+
+def draw_bulb (expr turndir, zl, zr, bulb_rad, radius_factor)=
+begingroup;
+       save rad, ang, pat;
+       path pat;
+
        clearxy;
-       save rad, ang;
 
-       ang = angle(zr-zl);
+       ang = angle (zr - zl);
 
        % don't get near infinity
-       %z0 = zr + bulb_rad * (zl-zr)/length(zr -zl);
-       z0 = zr + bulb_rad /length(zr -zl) * (zl-zr);
+       % z0 = zr + bulb_rad * (zl - zr) / length (zr - zl);
+       z0' = zr + bulb_rad / length (zr - zl) * (zl - zr);
+
+       rad = bulb_rad;
 
-       rad =  bulb_rad;
+       z1' = z0' + radius_factor * rad * dir (ang + turndir * 100);
+       z2' = z0' + rad * dir (ang + turndir * 300);
 
-       z1 = z0 + radius_factor* rad * dir(ang + turndir* 100);
-       z2 = z0 + rad * dir(ang  + turndir*300);
-       labels(0,1,2);
-       fill zr{dir (ang + turndir* 90)} .. z1 .. z2 -- cycle;
+       labels (0', 1', 2');
 
-       endgroup
+       pat = zr{dir (ang + turndir * 90)}
+              .. z1'
+              .. z2'
+              .. cycle;
+
+       % avoid grazing outlines
+       fill subpath (0, 2.5) of pat
+            -- cycle;
+endgroup
 enddef;
+
+
+pi := 3.14159;
+
+
+%
+% To get symmetry at low resolutions we need to shift some points and
+% paths, but not if mf2pt1 is used.
+%
+
+if known miterlimit:
+       vardef hfloor primary x = x enddef;
+       vardef vfloor primary y = y enddef;
+       vardef hceiling primary x = x enddef;
+       vardef vceiling primary y = y enddef;
+else:
+       vardef hfloor primary x = floor x enddef;
+       vardef vfloor primary y = (floor y.o_)_o_ enddef;
+       vardef hceiling primary x = ceiling x enddef;
+       vardef vceiling primary y = (ceiling y.o_)_o_ enddef;
+fi;