1 //========================================================================
2 //
3 // SplashXPathScanner.h
4 //
5 //========================================================================
6 
7 //========================================================================
8 //
9 // Modified under the Poppler project - http://poppler.freedesktop.org
10 //
11 // All changes made under the Poppler project to this file are licensed
12 // under GPL version 2 or later
13 //
14 // Copyright (C) 2013, 2014, 2021 Thomas Freitag <Thomas.Freitag@alfa.de>
15 // Copyright (C) 2018, 2021 Albert Astals Cid <aacid@kde.org>
16 // Copyright (C) 2018 Stefan Brüns <stefan.bruens@rwth-aachen.de>
17 //
18 // To see a description of the changes please see the Changelog file that
19 // came with your tarball or type make ChangeLog if you are building from git
20 //
21 //========================================================================
22 
23 #ifndef SPLASHXPATHSCANNER_H
24 #define SPLASHXPATHSCANNER_H
25 
26 #include "SplashTypes.h"
27 
28 #include <poppler-config.h>
29 
30 #ifdef USE_BOOST_HEADERS
31 #    include <boost/container/small_vector.hpp>
32 #endif
33 
34 #include <vector>
35 
36 class SplashXPath;
37 class SplashBitmap;
38 
39 struct SplashIntersect
40 {
41     int y;
42     int x0, x1; // intersection of segment with [y, y+1)
43     int count; // EO/NZWN counter increment
44 };
45 
46 //------------------------------------------------------------------------
47 // SplashXPathScanner
48 //------------------------------------------------------------------------
49 
50 class SplashXPathScanner
51 {
52 public:
53     // Create a new SplashXPathScanner object.  <xPathA> must be sorted.
54     SplashXPathScanner(const SplashXPath &xPath, bool eoA, int clipYMin, int clipYMax);
55 
56     ~SplashXPathScanner();
57 
58     SplashXPathScanner(const SplashXPathScanner &) = delete;
59     SplashXPathScanner &operator=(const SplashXPathScanner &) = delete;
60 
61     // Return the path's bounding box.
getBBox(int * xMinA,int * yMinA,int * xMaxA,int * yMaxA)62     void getBBox(int *xMinA, int *yMinA, int *xMaxA, int *yMaxA) const
63     {
64         *xMinA = xMin;
65         *yMinA = yMin;
66         *xMaxA = xMax;
67         *yMaxA = yMax;
68     }
69 
70     // Return the path's bounding box.
71     void getBBoxAA(int *xMinA, int *yMinA, int *xMaxA, int *yMaxA) const;
72 
73     // Returns true if at least part of the path was outside the
74     // clipYMin/clipYMax bounds passed to the constructor.
hasPartialClip()75     bool hasPartialClip() const { return partialClip; }
76 
77     // Return the min/max x values for the span at <y>.
78     void getSpanBounds(int y, int *spanXMin, int *spanXMax) const;
79 
80     // Returns true if (<x>,<y>) is inside the path.
81     bool test(int x, int y) const;
82 
83     // Returns true if the entire span ([<x0>,<x1>], <y>) is inside the
84     // path.
85     bool testSpan(int x0, int x1, int y) const;
86 
87     // Renders one anti-aliased line into <aaBuf>.  Returns the min and
88     // max x coordinates with non-zero pixels in <x0> and <x1>.
89     void renderAALine(SplashBitmap *aaBuf, int *x0, int *x1, int y, bool adjustVertLine = false) const;
90 
91     // Clips an anti-aliased line by setting pixels to zero.  On entry,
92     // all non-zero pixels are between <x0> and <x1>.  This function
93     // will update <x0> and <x1>.
94     void clipAALine(SplashBitmap *aaBuf, int *x0, int *x1, int y) const;
95 
96 private:
97     void computeIntersections(const SplashXPath &xPath);
98     bool addIntersection(double segYMin, double segYMax, int y, int x0, int x1, int count);
99 
100     bool eo;
101     int xMin, yMin, xMax, yMax;
102     bool partialClip;
103 
104 #ifdef USE_BOOST_HEADERS
105     typedef boost::container::small_vector<SplashIntersect, 4> IntersectionLine;
106 #else
107     typedef std::vector<SplashIntersect> IntersectionLine;
108 #endif
109     std::vector<IntersectionLine> allIntersections;
110 
111     friend class SplashXPathScanIterator;
112 };
113 
114 class SplashXPathScanIterator
115 {
116 public:
117     SplashXPathScanIterator(const SplashXPathScanner &scanner, int y);
118 
119     // Returns the next span inside the path at the current y position
120     // Returns false if there are no more spans.
121     bool getNextSpan(int *x0, int *x1);
122 
123 private:
124 #ifdef USE_BOOST_HEADERS
125     typedef boost::container::small_vector<SplashIntersect, 4> IntersectionLine;
126 #else
127     typedef std::vector<SplashIntersect> IntersectionLine;
128 #endif
129     const IntersectionLine &line;
130 
131     size_t interIdx; // current index into <line>
132     int interCount; // current EO/NZWN counter
133     const bool eo;
134 };
135 
136 #endif
137