]> git.donarmstrong.com Git - lilypond.git/blobdiff - mf/mf2pt1.mp
Release: bump Welcome versions.
[lilypond.git] / mf / mf2pt1.mp
index da25edd07de9655949178947c2d5810c8a9600b9..bb6ceda5dc32e7e5b5b26f6f2857b273b01a0690 100644 (file)
@@ -10,7 +10,7 @@
 
 %%%% ==================================================================== %%%%
 %%%% mf2pt1                                                               %%%%
-%%%% Copyright (C) 2007 Scott Pakin                                       %%%%
+%%%% Copyright (C) 2012 Scott Pakin                                       %%%%
 %%%%                                                                      %%%%
 %%%% This program may be distributed and/or modified under the conditions %%%%
 %%%% of the LaTeX Project Public License, either version 1.3c of this     %%%%
@@ -58,7 +58,7 @@ def beginchar(expr c,w_sharp,h_sharp,d_sharp) =
     w:=charwd*pt; h:=charht*pt; d:=chardp*pt;
     charic:=0; clearxy; clearit; clearpen; scantokens extra_beginchar;
 
-    def to_bp (expr num) = decimal (ceiling (num*bp_per_pixel)) enddef;
+    def to_bp (expr num) = decimal (round (num*bp_per_pixel)) enddef;
     special "% MF2PT1: glyph_dimensions 0 " & to_bp (-d) & " " & to_bp(w) & " " & to_bp(h);
     special "% MF2PT1: font_size " & decimal designsize;
     special "% MF2PT1: font_slant " & decimal font_slant_;
@@ -196,7 +196,8 @@ enddef;
 %%   The algorithm used is quite simple:
 %%
 %%   \begin{itemize}
-%%     \item Find a point~$P$ on the path which has a non-zero direction.
+%%     \item Find a point~$P$ on the path which has a non-zero direction,
+%%     and which is on a not-too-short path element.
 %%
 %%     \item Construct a ray of ``infinite'' length, starting in the
 %%     vicinity of~$P$ which intersects the path at this point.
@@ -204,7 +205,7 @@ enddef;
 %%     \item Use \mfcomment
 %      |intersectiontimes| to find the intersection.  If the direction of
 %%     the path at this point is (near) zero, or if we have a grazing
-%%     intersection, get a new ray.
+%%     intersection or even a tangent, get a new ray.
 %%
 %%     \item Shorten the ray so that it starts right after the
 %%     intersection.  Repeat the previous step until no intersection is
@@ -232,29 +233,51 @@ vardef crossproduct (expr u, v) =
 enddef;
 
 vardef makeline primary p =
-  save start, loop, d, n;
+  save start, bad_n, loop, distance, d, i, n;
   pair start, d;
 
   loop := 0;
-  for i = 0.5 step 1 until length p - 0.5:
-    n := uniformdeviate 0.9 - 0.45 + i;    % Add some randomness to get different lines for each function call.
-    start := point n of p;
-    d := direction n of p;
-    if d <> (0, 0):
-      loop := 1;
+  bad_n := -1;
+  for i := 0 step 1 until length p - 1:
+    distance := length (point i of p - point (i + 1) of p);
+    if distance <> 0:
+      if distance < 1:
+        % In case we don't find something better.
+        bad_n := i;
+      else:
+        n := i;
+        loop := 1;
+      fi;
     fi;
     exitif loop = 1;
   endfor;
 
   if loop = 0:
-    errmessage ("Cannot find a starting point on path for orientation test");
+    if bad_n <> -1:
+      n := bad_n;
+      loop = 1;
+    fi;
   fi;
 
-  d := unitvector (d rotated (uniformdeviate 160 + 10));  % Again, some added randomness
+  % Add some randomness to get different lines for each function call.
+  n := n + uniformdeviate 0.8 + 0.1;
+  start := point n of p;
 
-  % Construct a line which intersects the path at least once.
-  start - eps * d
-  -- infinity * d
+  if loop = 0:
+    % Construct a line which misses the degenerated path.
+    start + (1, 0)
+    -- start + (1, 1)
+  else:
+    d := direction n of p;
+
+    % Again, some added randomness.
+    n := uniformdeviate 150 + 15;
+    d := unitvector (d rotated n);
+
+    % Construct a line which intersects the path at least once.
+    start - eps * d
+    -- infinity * d
+  fi
 enddef;
 
 vardef is_clockwise primary p =
@@ -262,8 +285,6 @@ vardef is_clockwise primary p =
   path line;
   pair cut, cut_new, line_dir, tangent_dir;
 
-  res := 1;
-
   line := makeline p;
   line_dir := direction 0 of line;
 
@@ -279,21 +300,31 @@ vardef is_clockwise primary p =
       % The vector is zero or too small.
       line := makeline p;
       line_dir := direction 0 of line;
-    elseif crossproduct (tangent_dir, line_dir) < 0.02:
-      % Grazing intersection
+
+    elseif abs (ypart cut_new - floor (ypart cut_new + 0.5)) < eps:
+      % Avoid possible tangent touching in a corner or cusp.
+      line := makeline p;
+      line_dir := direction 0 of line;
+
+    elseif crossproduct (tangent_dir, line_dir) < 0.2:
+      % Grazing intersection (arcsin 0.2 ~= 11.5 degrees).
       line := makeline p;
       line_dir := direction 0 of line;
+
     else:
-      % Try again.
+      % Go ahead.
       cut := cut_new;
       line := subpath (xpart cut + eps, infinity) of line;
     fi;
   endfor;
 
   tangent_dir := direction (ypart cut) of p;
-  res := (angle tangent_dir - angle line_dir + 180) mod 360 - 180;
-
-  res < 0
+  if tangent_dir <> (0, 0):
+    res := (angle tangent_dir - angle line_dir + 180) mod 360 - 180;
+    res < 0
+  else:
+    false
+  fi
 enddef;