]> git.donarmstrong.com Git - lilypond.git/commitdiff
Issue 2658: Be serious about setstrokeadjust in PostScript primitives
authorDavid Kastrup <dak@gnu.org>
Thu, 11 Apr 2013 15:27:14 +0000 (17:27 +0200)
committerDavid Kastrup <dak@gnu.org>
Sat, 7 Dec 2013 11:48:17 +0000 (12:48 +0100)
This particularly concerns draw_round_box which is used for drawing
lines with a rounded ending.  If the width/height ratio or its inverse
exceeds 2, the box is considered to be a "line".  In this case, first
a clipping path is established representing the whole shape and
extended widely in the area of the "main stroke".  The reason for this
extension is to avoid both clip area and stroke competing for the
outline.  While this is not a problem for the PostScript or PDF
rendering model, the Cairo bitmap rendering library employs
Porter-Duff compositing for antialiasing amounting to "cheap man's
antialiasing" not requiring a higher rendering resolution but relying
on edges affecting a single pixel to be independent.

Porter-Duff requires us not to have multiple parallel strokes or clip
areas if we want to avoid wrong sub-pixel grayness levels (and
consequently lines appearing too thick or thin) in Cairo-based
previewers like Evince.

After establishing the clip area, a stroke is drawn through.  This
stroke may (at the PostScript device's discretion) employ
strokeadjustment further correcting the apparent thickness.
Ghostscript employs stroke adjustment when rendering at a resolution
below 150dpi.  Stroke adjustment does not pass into PDF, however, when
ps2pdf runs.

Ghostscript performs sub-pixel rendering for antialiasing which
reduces the amount of discontinuities possibly caused by joining
stroke-adjusted shapes with full shapes.

It turns out that sharper contours can be achieved by using strokepath
and fill instead of a plain stroke.  However, the resulting crisper
stems tend to combine worse with beams, so this approach has not been
pursued.

ps/music-drawing-routines.ps

index 189310a84ddf8ef4bd54d73c6af5ae3093f58372..121897a0218682dbb339f76beeb6eea6156e596a 100644 (file)
@@ -75,7 +75,8 @@ bind def
 /stroke_and_fill? {
     {
        gsave
-               stroke
+           false setstrokeadjust
+           stroke
        grestore
        fill
     }
@@ -96,30 +97,97 @@ bind def
 
 /draw_round_box % width height x y blot
 {
-        dup
-       0.0 gt {
-               setlinewidth % w h x y
-               rmoveto % w h
-               2 copy 0 ne exch 0 ne and
+    0 max setlinewidth
+    matrix currentmatrix 5 1 roll
+    currentpoint translate newpath translate
+    2 copy 0 min exch 0 min exch translate
+    abs exch abs exch
+    currentlinewidth 0 eq
+    { % straight corners
+       2 copy 2 mul gt
+       { % horizontal
+           0 1 index 2 div moveto
+           setlinewidth
+           0 rlineto
+           0 setlinecap
+           stroke
+       }
+       {
+           2 copy exch 2 mul gt
+           { % vertical
+               1 index 2 div 0 moveto
+               exch setlinewidth
+               0 exch rlineto
+               0 setlinecap
+               stroke
+           }
+           {
+               0 0 4 2 roll rectfill
+           }
+           ifelse
+       }
+       ifelse
+    }
+    { % rounded corners
+       2 copy 0 eq exch 0 eq or
+       { % line shape
+           0 0 moveto
+           rlineto
+           1 setlinecap
+           stroke
+           0 setlinecap
+       }
+       { % full shape
+           currentlinewidth 2 div
+           0 0 2 index 180 270 arc
+           2 index 0 2 index 270 360 arc
+           3 copy 0 90 arc
+           0 2 index 3 -1 roll 90 180 arc
+           closepath
+           2 copy 2 mul gt
+           { % horizontal
+               2 copy add currentlinewidth add 10 add % large enough
+               0 1 index neg moveto
+               2 index 1 index neg lineto
+               2 index 1 index lineto
+               0 exch lineto closepath
+               gsave clip newpath
+               0 1 index 2 div moveto
+               currentlinewidth add setlinewidth
+               0 rlineto
+               2 setlinecap
+               stroke
+               grestore
+           }
+           {
+               2 copy exch 2 mul gt
+               { % vertical
+                   2 copy add currentlinewidth add 10 add % large enough
+                   dup neg 0 moveto
+                   dup 0 lineto
+                   dup 2 index lineto
+                   neg 1 index lineto closepath
+                   gsave clip newpath
+                   1 index 2 div 0 moveto
+                   exch currentlinewidth add setlinewidth
+                   0 exch rlineto
+                   2 setlinecap
+                   stroke
+                   grestore
+               }
                {
-                   0 setlinecap
-                   1 setlinejoin
-                   currentpoint % w h x1 y1
-                   4 2 roll % x1 y1 w h
-                   4 copy
-                   rectfill
-                   rectstroke
-               } {
-                   1 setlinecap
-                   rlineto stroke
-               } ifelse
-       } {
-               pop % w h x y
-               rmoveto % w h
-               currentpoint % w h x1 y1
-               4 2 roll % x1 y1 w h
-               rectfill
-       } ifelse
+                   pop pop
+                   fill
+               }
+               ifelse
+           }
+           ifelse
+           newpath
+       }
+       ifelse
+    }
+    ifelse
+    setmatrix
 } bind def
 
 /draw_polygon % fill? x(n) y(n) x(n-1) y(n-1) ... x(0) y(0) n blot
@@ -206,7 +274,6 @@ bind def
 {
        setlinewidth % dx dy x1 y1
        1 setlinecap
-       1 setlinejoin
        rmoveto % dx dy
        rlineto
        stroke
@@ -215,7 +282,6 @@ bind def
 /draw_dashed_line % dx dy thickness dashpattern offset draw_dashed_line
 {
        1 setlinecap
-       1 setlinejoin
        setdash % dx dy thickness
        setlinewidth %dx dy
        rlineto