1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 
40 #ifndef QVECTORPATH_P_H
41 #define QVECTORPATH_P_H
42 
43 //
44 //  W A R N I N G
45 //  -------------
46 //
47 // This file is not part of the Qt API.  It exists purely as an
48 // implementation detail.  This header file may change from version to
49 // version without notice, or even be removed.
50 //
51 // We mean it.
52 //
53 
54 #include <QtGui/private/qtguiglobal_p.h>
55 #include <QtGui/qpaintengine.h>
56 
57 #include <private/qpaintengine_p.h>
58 #include <private/qstroker_p.h>
59 #include <private/qpainter_p.h>
60 
61 
62 QT_BEGIN_NAMESPACE
63 
64 
65 class QPaintEngineEx;
66 
67 typedef void (*qvectorpath_cache_cleanup)(QPaintEngineEx *engine, void *data);
68 
69 struct QRealRect {
70     qreal x1, y1, x2, y2;
71 };
72 
73 class Q_GUI_EXPORT QVectorPath
74 {
75 public:
76     enum Hint {
77         // Shape hints, in 0x000000ff, access using shape()
78         AreaShapeMask           = 0x0001,       // shape covers an area
79         NonConvexShapeMask      = 0x0002,       // shape is not convex
80         CurvedShapeMask         = 0x0004,       // shape contains curves...
81         LinesShapeMask          = 0x0008,
82         RectangleShapeMask      = 0x0010,
83         ShapeMask               = 0x001f,
84 
85         // Shape hints merged into basic shapes..
86         LinesHint               = LinesShapeMask,
87         RectangleHint           = AreaShapeMask | RectangleShapeMask,
88         EllipseHint             = AreaShapeMask | CurvedShapeMask,
89         ConvexPolygonHint       = AreaShapeMask,
90         PolygonHint             = AreaShapeMask | NonConvexShapeMask,
91         RoundedRectHint         = AreaShapeMask | CurvedShapeMask,
92         ArbitraryShapeHint      = AreaShapeMask | NonConvexShapeMask | CurvedShapeMask,
93 
94         // Other hints
95         IsCachedHint            = 0x0100, // Set if the cache hint is set
96         ShouldUseCacheHint      = 0x0200, // Set if the path should be cached when possible..
97         ControlPointRect        = 0x0400, // Set if the control point rect has been calculated...
98 
99         // Shape rendering specifiers...
100         OddEvenFill             = 0x1000,
101         WindingFill             = 0x2000,
102         ImplicitClose           = 0x4000,
103         ExplicitOpen            = 0x8000
104     };
105 
106     // ### Falcon: introduca a struct XY for points so lars is not so confused...
107     QVectorPath(const qreal *points,
108                 int count,
109                 const QPainterPath::ElementType *elements = nullptr,
110                 uint hints = ArbitraryShapeHint)
m_elements(elements)111         : m_elements(elements),
112           m_points(points),
113           m_count(count),
114           m_hints(hints)
115     {
116     }
117 
118     ~QVectorPath();
119 
120     QRectF controlPointRect() const;
121 
shape()122     inline Hint shape() const { return (Hint) (m_hints & ShapeMask); }
isConvex()123     inline bool isConvex() const { return (m_hints & NonConvexShapeMask) == 0; }
isCurved()124     inline bool isCurved() const { return m_hints & CurvedShapeMask; }
125 
isCacheable()126     inline bool isCacheable() const { return m_hints & ShouldUseCacheHint; }
hasImplicitClose()127     inline bool hasImplicitClose() const { return m_hints & ImplicitClose; }
hasExplicitOpen()128     inline bool hasExplicitOpen() const { return m_hints & ExplicitOpen; }
hasWindingFill()129     inline bool hasWindingFill() const { return m_hints & WindingFill; }
130 
makeCacheable()131     inline void makeCacheable() const { m_hints |= ShouldUseCacheHint; m_cache = nullptr; }
hints()132     inline uint hints() const { return m_hints; }
133 
elements()134     inline const QPainterPath::ElementType *elements() const { return m_elements; }
points()135     inline const qreal *points() const { return m_points; }
isEmpty()136     inline bool isEmpty() const { return m_points == nullptr; }
137 
elementCount()138     inline int elementCount() const { return m_count; }
139     inline const QPainterPath convertToPainterPath() const;
140 
polygonFlags(QPaintEngine::PolygonDrawMode mode)141     static inline uint polygonFlags(QPaintEngine::PolygonDrawMode mode)
142     {
143         switch (mode) {
144         case QPaintEngine::ConvexMode: return ConvexPolygonHint | ImplicitClose;
145         case QPaintEngine::OddEvenMode: return PolygonHint | OddEvenFill | ImplicitClose;
146         case QPaintEngine::WindingMode: return PolygonHint | WindingFill | ImplicitClose;
147         case QPaintEngine::PolylineMode: return PolygonHint | ExplicitOpen;
148         default: return 0;
149         }
150     }
151 
152     struct CacheEntry {
153         QPaintEngineEx *engine;
154         void *data;
155         qvectorpath_cache_cleanup cleanup;
156         CacheEntry *next;
157     };
158 
159     CacheEntry *addCacheData(QPaintEngineEx *engine, void *data, qvectorpath_cache_cleanup cleanup) const;
lookupCacheData(QPaintEngineEx * engine)160     inline CacheEntry *lookupCacheData(QPaintEngineEx *engine) const {
161         Q_ASSERT(m_hints & ShouldUseCacheHint);
162         CacheEntry *e = m_cache;
163         while (e) {
164             if (e->engine == engine)
165                 return e;
166             e = e->next;
167         }
168         return nullptr;
169     }
170 
isRect(const T * pts,int elementCount)171     template <typename T> static inline bool isRect(const T *pts, int elementCount) {
172         return (elementCount == 5 // 5-point polygon, check for closed rect
173                 && pts[0] == pts[8] && pts[1] == pts[9] // last point == first point
174                 && pts[0] == pts[6] && pts[2] == pts[4] // x values equal
175                 && pts[1] == pts[3] && pts[5] == pts[7] // y values equal...
176                 && pts[0] < pts[4] && pts[1] < pts[5]
177                 ) ||
178                (elementCount == 4 // 4-point polygon, check for unclosed rect
179                 && pts[0] == pts[6] && pts[2] == pts[4] // x values equal
180                 && pts[1] == pts[3] && pts[5] == pts[7] // y values equal...
181                 && pts[0] < pts[4] && pts[1] < pts[5]
182                 );
183     }
184 
isRect()185     inline bool isRect() const
186     {
187         const QPainterPath::ElementType * const types = elements();
188 
189         return (shape() == QVectorPath::RectangleHint)
190                 || (isRect(points(), elementCount())
191                     && (!types || (types[0] == QPainterPath::MoveToElement
192                                    && types[1] == QPainterPath::LineToElement
193                                    && types[2] == QPainterPath::LineToElement
194                                    && types[3] == QPainterPath::LineToElement)));
195     }
196 
197 
198 private:
199     Q_DISABLE_COPY_MOVE(QVectorPath)
200 
201     const QPainterPath::ElementType *m_elements;
202     const qreal *m_points;
203     const int m_count;
204 
205     mutable uint m_hints;
206     mutable QRealRect m_cp_rect;
207 
208     mutable CacheEntry *m_cache;
209 };
210 
211 Q_GUI_EXPORT const QVectorPath &qtVectorPathForPath(const QPainterPath &path);
212 
213 QT_END_NAMESPACE
214 
215 #endif
216