From 6bf9a5a3dbcabff297d5bcdb3cf1dffd0885cbbc Mon Sep 17 00:00:00 2001 From: David Kastrup Date: Thu, 11 Apr 2013 17:27:14 +0200 Subject: [PATCH] Issue 2658: Be serious about setstrokeadjust in PostScript primitives 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 | 118 +++++++++++++++++++++++++++-------- 1 file changed, 92 insertions(+), 26 deletions(-) diff --git a/ps/music-drawing-routines.ps b/ps/music-drawing-routines.ps index 189310a84d..121897a021 100644 --- a/ps/music-drawing-routines.ps +++ b/ps/music-drawing-routines.ps @@ -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 -- 2.39.2