Make QRegion not need to be friends with QVector
[profile/ivi/qtbase.git] / src / gui / painting / qpainterpath_p.h
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #ifndef QPAINTERPATH_P_H
43 #define QPAINTERPATH_P_H
44
45 //
46 //  W A R N I N G
47 //  -------------
48 //
49 // This file is not part of the Qt API.  It exists for the convenience
50 // of other Qt classes.  This header file may change from version to
51 // version without notice, or even be removed.
52 //
53 // We mean it.
54 //
55
56 #include "QtGui/qpainterpath.h"
57 #include "QtGui/qregion.h"
58 #include "QtCore/qlist.h"
59 #include "QtCore/qvarlengtharray.h"
60
61 #include <qdebug.h>
62
63 #include <private/qvectorpath_p.h>
64 #include <private/qstroker_p.h>
65
66 QT_BEGIN_NAMESPACE
67
68 class QPainterPathPrivate
69 {
70 public:
71     friend class QPainterPath;
72     friend class QPainterPathData;
73     friend class QPainterPathStroker;
74     friend class QPainterPathStrokerPrivate;
75     friend class QMatrix;
76     friend class QTransform;
77     friend class QVectorPath;
78     friend struct QPainterPathPrivateDeleter;
79 #ifndef QT_NO_DATASTREAM
80     friend Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QPainterPath &);
81     friend Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QPainterPath &);
82 #endif
83
84     QPainterPathPrivate() : ref(1) {}
85
86 private:
87     QAtomicInt ref;
88     QVector<QPainterPath::Element> elements;
89 };
90
91 class QPainterPathStrokerPrivate
92 {
93 public:
94     QPainterPathStrokerPrivate();
95
96     QStroker stroker;
97     QVector<qfixed> dashPattern;
98     qreal dashOffset;
99 };
100
101 class QPolygonF;
102 class QVectorPathConverter;
103
104 class QVectorPathConverter
105 {
106 public:
107     QVectorPathConverter(const QVector<QPainterPath::Element> &path, uint fillRule, bool convex)
108         : pathData(path, fillRule, convex),
109           path(pathData.points.data(), path.size(),
110                pathData.elements.data(), pathData.flags) {}
111
112     const QVectorPath &vectorPath() {
113         return path;
114     }
115
116     struct QVectorPathData {
117         QVectorPathData(const QVector<QPainterPath::Element> &path, uint fillRule, bool convex)
118             : elements(path.size()),
119               points(path.size() * 2),
120               flags(0)
121         {
122             int ptsPos = 0;
123             bool isLines = true;
124             for (int i=0; i<path.size(); ++i) {
125                 const QPainterPath::Element &e = path.at(i);
126                 elements[i] = e.type;
127                 points[ptsPos++] = e.x;
128                 points[ptsPos++] = e.y;
129                 if (e.type == QPainterPath::CurveToElement)
130                     flags |= QVectorPath::CurvedShapeMask;
131
132                 // This is to check if the path contains only alternating lineTo/moveTo,
133                 // in which case we can set the LinesHint in the path. MoveTo is 0 and
134                 // LineTo is 1 so the i%2 gets us what we want cheaply.
135                 isLines = isLines && e.type == (QPainterPath::ElementType) (i%2);
136             }
137
138             if (fillRule == Qt::WindingFill)
139                 flags |= QVectorPath::WindingFill;
140             else
141                 flags |= QVectorPath::OddEvenFill;
142
143             if (isLines)
144                 flags |= QVectorPath::LinesShapeMask;
145             else {
146                 flags |= QVectorPath::AreaShapeMask;
147                 if (!convex)
148                     flags |= QVectorPath::NonConvexShapeMask;
149             }
150
151         }
152         QVarLengthArray<QPainterPath::ElementType> elements;
153         QVarLengthArray<qreal> points;
154         uint flags;
155     };
156
157     QVectorPathData pathData;
158     QVectorPath path;
159
160 private:
161     Q_DISABLE_COPY(QVectorPathConverter)
162 };
163
164 class QPainterPathData : public QPainterPathPrivate
165 {
166 public:
167     QPainterPathData() :
168         cStart(0),
169         fillRule(Qt::OddEvenFill),
170         dirtyBounds(false),
171         dirtyControlBounds(false),
172         pathConverter(0)
173     {
174         require_moveTo = false;
175         convex = false;
176     }
177
178     QPainterPathData(const QPainterPathData &other) :
179         QPainterPathPrivate(), cStart(other.cStart), fillRule(other.fillRule),
180         bounds(other.bounds),
181         controlBounds(other.controlBounds),
182         dirtyBounds(other.dirtyBounds),
183         dirtyControlBounds(other.dirtyControlBounds),
184         convex(other.convex),
185         pathConverter(0)
186     {
187         require_moveTo = false;
188         elements = other.elements;
189     }
190
191     ~QPainterPathData() {
192         delete pathConverter;
193     }
194
195     inline bool isClosed() const;
196     inline void close();
197     inline void maybeMoveTo();
198
199     const QVectorPath &vectorPath() {
200         if (!pathConverter)
201             pathConverter = new QVectorPathConverter(elements, fillRule, convex);
202         return pathConverter->path;
203     }
204
205     int cStart;
206     Qt::FillRule fillRule;
207
208     QRectF bounds;
209     QRectF controlBounds;
210
211     uint require_moveTo : 1;
212     uint dirtyBounds : 1;
213     uint dirtyControlBounds : 1;
214     uint convex : 1;
215
216     QVectorPathConverter *pathConverter;
217 };
218
219
220 inline const QPainterPath QVectorPath::convertToPainterPath() const
221 {
222         QPainterPath path;
223         path.ensureData();
224         QPainterPathData *data = path.d_func();
225         data->elements.reserve(m_count);
226         int index = 0;
227         data->elements[0].x = m_points[index++];
228         data->elements[0].y = m_points[index++];
229
230         if (m_elements) {
231             data->elements[0].type = m_elements[0];
232             for (int i=1; i<m_count; ++i) {
233                 QPainterPath::Element element;
234                 element.x = m_points[index++];
235                 element.y = m_points[index++];
236                 element.type = m_elements[i];
237                 data->elements << element;
238             }
239         } else {
240             data->elements[0].type = QPainterPath::MoveToElement;
241             for (int i=1; i<m_count; ++i) {
242                 QPainterPath::Element element;
243                 element.x = m_points[index++];
244                 element.y = m_points[index++];
245                 element.type = QPainterPath::LineToElement;
246                 data->elements << element;
247             }
248         }
249
250         if (m_hints & OddEvenFill)
251             data->fillRule = Qt::OddEvenFill;
252         else
253             data->fillRule = Qt::WindingFill;
254         return path;
255 }
256
257 void Q_GUI_EXPORT qt_find_ellipse_coords(const QRectF &r, qreal angle, qreal length,
258                                          QPointF* startPoint, QPointF *endPoint);
259
260 inline bool QPainterPathData::isClosed() const
261 {
262     const QPainterPath::Element &first = elements.at(cStart);
263     const QPainterPath::Element &last = elements.last();
264     return first.x == last.x && first.y == last.y;
265 }
266
267 inline void QPainterPathData::close()
268 {
269     Q_ASSERT(ref.load() == 1);
270     require_moveTo = true;
271     const QPainterPath::Element &first = elements.at(cStart);
272     QPainterPath::Element &last = elements.last();
273     if (first.x != last.x || first.y != last.y) {
274         if (qFuzzyCompare(first.x, last.x) && qFuzzyCompare(first.y, last.y)) {
275             last.x = first.x;
276             last.y = first.y;
277         } else {
278             QPainterPath::Element e = { first.x, first.y, QPainterPath::LineToElement };
279             elements << e;
280         }
281     }
282 }
283
284 inline void QPainterPathData::maybeMoveTo()
285 {
286     if (require_moveTo) {
287         QPainterPath::Element e = elements.last();
288         e.type = QPainterPath::MoveToElement;
289         elements.append(e);
290         require_moveTo = false;
291     }
292 }
293
294 #define KAPPA qreal(0.5522847498)
295
296
297 QT_END_NAMESPACE
298
299 #endif // QPAINTERPATH_P_H