[poppler] poppler/poppler-config.h.cmake README-XPDF splash/Splash.cc

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Sun Feb 27 23:48:02 UTC 2022


 README-XPDF                    |    2 
 poppler/poppler-config.h.cmake |    4 -
 splash/Splash.cc               |  100 +++++++++++++++++++++++++++++++++++++----
 3 files changed, 94 insertions(+), 12 deletions(-)

New commits:
commit 1dbb74f24bb5d6d1f000993c62f3916dfa67d15e
Author: Oliver Sander <oliver.sander at tu-dresden.de>
Date:   Sat Feb 26 17:54:32 2022 +0100

    Import improved line join handling from xpdf 4.02
    
    The imported code from the makeStrokePath method seems much more
    sophisticated than what is currently in poppler.  In particular,
    it fixes
    
      https://gitlab.freedesktop.org/poppler/poppler/-/issues/1212
    
    Also, at least for the test file from that bug, the makeStrokePath
    implementation from xpdf constructs a path with only a bit more
    than half the number of points than the current poppler implementation.
    Therefore, importing the xpdf code may improve rendering efficiency.

diff --git a/README-XPDF b/README-XPDF
index d43bb60f..bad23bef 100644
--- a/README-XPDF
+++ b/README-XPDF
@@ -5,7 +5,7 @@ version 3.03
 2011-aug-15
 
 The Xpdf software and documentation are
-copyright 1996-2011 Glyph & Cog, LLC.
+copyright 1996-2011, 2022 Glyph & Cog, LLC.
 
 Email: derekn at foolabs.com
 WWW: http://www.foolabs.com/xpdf/
diff --git a/poppler/poppler-config.h.cmake b/poppler/poppler-config.h.cmake
index 488ff9c7..733c427c 100644
--- a/poppler/poppler-config.h.cmake
+++ b/poppler/poppler-config.h.cmake
@@ -2,7 +2,7 @@
 //
 // poppler-config.h
 //
-// Copyright 1996-2011 Glyph & Cog, LLC
+// Copyright 1996-2011, 2022 Glyph & Cog, LLC
 //
 //========================================================================
 
@@ -123,7 +123,7 @@
 
 // copyright notice
 #define popplerCopyright "Copyright 2005-2022 The Poppler Developers - http://poppler.freedesktop.org"
-#define xpdfCopyright "Copyright 1996-2011 Glyph & Cog, LLC"
+#define xpdfCopyright "Copyright 1996-2011, 2022 Glyph & Cog, LLC"
 
 //------------------------------------------------------------------------
 // Win32 stuff
diff --git a/splash/Splash.cc b/splash/Splash.cc
index 0119cfe0..e5b7cad1 100644
--- a/splash/Splash.cc
+++ b/splash/Splash.cc
@@ -55,6 +55,11 @@
 #include "Splash.h"
 #include <algorithm>
 
+// the MSVC math.h doesn't define this
+#ifndef M_PI
+#    define M_PI 3.14159265358979323846
+#endif
+
 //------------------------------------------------------------------------
 
 #define splashAAGamma 1.5
@@ -5962,17 +5967,94 @@ SplashPath *Splash::makeStrokePath(SplashPath *path, SplashCoord w, bool flatten
                 m = splashSqrt(miter - 1);
             }
 
+            // hasangle == false means that the current and and the next segment
+            // are parallel.  In that case no join needs to be drawn.
             // round join
             if (hasangle && state->lineJoin == splashLineJoinRound) {
-                pathOut->moveTo(pathIn->pts[j0].x + (SplashCoord)0.5 * w, pathIn->pts[j0].y);
-                pathOut->curveTo(pathIn->pts[j0].x + (SplashCoord)0.5 * w, pathIn->pts[j0].y + bezierCircle2 * w, pathIn->pts[j0].x + bezierCircle2 * w, pathIn->pts[j0].y + (SplashCoord)0.5 * w, pathIn->pts[j0].x,
-                                 pathIn->pts[j0].y + (SplashCoord)0.5 * w);
-                pathOut->curveTo(pathIn->pts[j0].x - bezierCircle2 * w, pathIn->pts[j0].y + (SplashCoord)0.5 * w, pathIn->pts[j0].x - (SplashCoord)0.5 * w, pathIn->pts[j0].y + bezierCircle2 * w, pathIn->pts[j0].x - (SplashCoord)0.5 * w,
-                                 pathIn->pts[j0].y);
-                pathOut->curveTo(pathIn->pts[j0].x - (SplashCoord)0.5 * w, pathIn->pts[j0].y - bezierCircle2 * w, pathIn->pts[j0].x - bezierCircle2 * w, pathIn->pts[j0].y - (SplashCoord)0.5 * w, pathIn->pts[j0].x,
-                                 pathIn->pts[j0].y - (SplashCoord)0.5 * w);
-                pathOut->curveTo(pathIn->pts[j0].x + bezierCircle2 * w, pathIn->pts[j0].y - (SplashCoord)0.5 * w, pathIn->pts[j0].x + (SplashCoord)0.5 * w, pathIn->pts[j0].y - bezierCircle2 * w, pathIn->pts[j0].x + (SplashCoord)0.5 * w,
-                                 pathIn->pts[j0].y);
+                // join angle < 180
+                if (crossprod < 0) {
+                    SplashCoord angle = atan2((double)dx, (double)-dy);
+                    SplashCoord angleNext = atan2((double)dxNext, (double)-dyNext);
+                    if (angle < angleNext) {
+                        angle += 2 * M_PI;
+                    }
+                    SplashCoord dAngle = (angle - angleNext) / M_PI;
+                    if (dAngle < 0.501) {
+                        // span angle is <= 90 degrees -> draw a single arc
+                        SplashCoord kappa = dAngle * bezierCircle * w;
+                        SplashCoord cx1 = pathIn->pts[j0].x - wdy + kappa * dx;
+                        SplashCoord cy1 = pathIn->pts[j0].y + wdx + kappa * dy;
+                        SplashCoord cx2 = pathIn->pts[j0].x - wdyNext - kappa * dxNext;
+                        SplashCoord cy2 = pathIn->pts[j0].y + wdxNext - kappa * dyNext;
+                        pathOut->moveTo(pathIn->pts[j0].x, pathIn->pts[j0].y);
+                        pathOut->lineTo(pathIn->pts[j0].x - wdyNext, pathIn->pts[j0].y + wdxNext);
+                        pathOut->curveTo(cx2, cy2, cx1, cy1, pathIn->pts[j0].x - wdy, pathIn->pts[j0].y + wdx);
+                    } else {
+                        // span angle is > 90 degrees -> split into two arcs
+                        SplashCoord dJoin = splashDist(-wdy, wdx, -wdyNext, wdxNext);
+                        if (dJoin > 0) {
+                            SplashCoord dxJoin = (-wdyNext + wdy) / dJoin;
+                            SplashCoord dyJoin = (wdxNext - wdx) / dJoin;
+                            SplashCoord xc = pathIn->pts[j0].x + (SplashCoord)0.5 * w * cos((double)((SplashCoord)0.5 * (angle + angleNext)));
+                            SplashCoord yc = pathIn->pts[j0].y + (SplashCoord)0.5 * w * sin((double)((SplashCoord)0.5 * (angle + angleNext)));
+                            SplashCoord kappa = dAngle * bezierCircle2 * w;
+                            SplashCoord cx1 = pathIn->pts[j0].x - wdy + kappa * dx;
+                            SplashCoord cy1 = pathIn->pts[j0].y + wdx + kappa * dy;
+                            SplashCoord cx2 = xc - kappa * dxJoin;
+                            SplashCoord cy2 = yc - kappa * dyJoin;
+                            SplashCoord cx3 = xc + kappa * dxJoin;
+                            SplashCoord cy3 = yc + kappa * dyJoin;
+                            SplashCoord cx4 = pathIn->pts[j0].x - wdyNext - kappa * dxNext;
+                            SplashCoord cy4 = pathIn->pts[j0].y + wdxNext - kappa * dyNext;
+                            pathOut->moveTo(pathIn->pts[j0].x, pathIn->pts[j0].y);
+                            pathOut->lineTo(pathIn->pts[j0].x - wdyNext, pathIn->pts[j0].y + wdxNext);
+                            pathOut->curveTo(cx4, cy4, cx3, cy3, xc, yc);
+                            pathOut->curveTo(cx2, cy2, cx1, cy1, pathIn->pts[j0].x - wdy, pathIn->pts[j0].y + wdx);
+                        }
+                    }
+
+                    // join angle >= 180
+                } else {
+                    SplashCoord angle = atan2((double)-dx, (double)dy);
+                    SplashCoord angleNext = atan2((double)-dxNext, (double)dyNext);
+                    if (angleNext < angle) {
+                        angleNext += 2 * M_PI;
+                    }
+                    SplashCoord dAngle = (angleNext - angle) / M_PI;
+                    if (dAngle < 0.501) {
+                        // span angle is <= 90 degrees -> draw a single arc
+                        SplashCoord kappa = dAngle * bezierCircle * w;
+                        SplashCoord cx1 = pathIn->pts[j0].x + wdy + kappa * dx;
+                        SplashCoord cy1 = pathIn->pts[j0].y - wdx + kappa * dy;
+                        SplashCoord cx2 = pathIn->pts[j0].x + wdyNext - kappa * dxNext;
+                        SplashCoord cy2 = pathIn->pts[j0].y - wdxNext - kappa * dyNext;
+                        pathOut->moveTo(pathIn->pts[j0].x, pathIn->pts[j0].y);
+                        pathOut->lineTo(pathIn->pts[j0].x + wdy, pathIn->pts[j0].y - wdx);
+                        pathOut->curveTo(cx1, cy1, cx2, cy2, pathIn->pts[j0].x + wdyNext, pathIn->pts[j0].y - wdxNext);
+                    } else {
+                        // span angle is > 90 degrees -> split into two arcs
+                        SplashCoord dJoin = splashDist(wdy, -wdx, wdyNext, -wdxNext);
+                        if (dJoin > 0) {
+                            SplashCoord dxJoin = (wdyNext - wdy) / dJoin;
+                            SplashCoord dyJoin = (-wdxNext + wdx) / dJoin;
+                            SplashCoord xc = pathIn->pts[j0].x + (SplashCoord)0.5 * w * cos((double)((SplashCoord)0.5 * (angle + angleNext)));
+                            SplashCoord yc = pathIn->pts[j0].y + (SplashCoord)0.5 * w * sin((double)((SplashCoord)0.5 * (angle + angleNext)));
+                            SplashCoord kappa = dAngle * bezierCircle2 * w;
+                            SplashCoord cx1 = pathIn->pts[j0].x + wdy + kappa * dx;
+                            SplashCoord cy1 = pathIn->pts[j0].y - wdx + kappa * dy;
+                            SplashCoord cx2 = xc - kappa * dxJoin;
+                            SplashCoord cy2 = yc - kappa * dyJoin;
+                            SplashCoord cx3 = xc + kappa * dxJoin;
+                            SplashCoord cy3 = yc + kappa * dyJoin;
+                            SplashCoord cx4 = pathIn->pts[j0].x + wdyNext - kappa * dxNext;
+                            SplashCoord cy4 = pathIn->pts[j0].y - wdxNext - kappa * dyNext;
+                            pathOut->moveTo(pathIn->pts[j0].x, pathIn->pts[j0].y);
+                            pathOut->lineTo(pathIn->pts[j0].x + wdy, pathIn->pts[j0].y - wdx);
+                            pathOut->curveTo(cx1, cy1, cx2, cy2, xc, yc);
+                            pathOut->curveTo(cx3, cy3, cx4, cy4, pathIn->pts[j0].x + wdyNext, pathIn->pts[j0].y - wdxNext);
+                        }
+                    }
+                }
 
             } else if (hasangle) {
                 pathOut->moveTo(pathIn->pts[j0].x, pathIn->pts[j0].y);


More information about the poppler mailing list