Make QRegion not need to be friends with QVector
[profile/ivi/qtbase.git] / src / gui / painting / qstroker_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 QSTROKER_P_H
43 #define QSTROKER_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 purely as an
50 // implementation detail.  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 "private/qdatabuffer_p.h"
58 #include "private/qnumeric_p.h"
59
60 QT_BEGIN_NAMESPACE
61
62 // #define QFIXED_IS_26_6
63
64 #if defined QFIXED_IS_26_6
65 typedef int qfixed;
66 #define qt_real_to_fixed(real) qfixed(real * 64)
67 #define qt_int_to_fixed(real) qfixed(int(real) << 6)
68 #define qt_fixed_to_real(fixed) qreal(fixed / qreal(64))
69 #define qt_fixed_to_int(fixed) int(fixed >> 6)
70 struct qfixed2d
71 {
72     qfixed x;
73     qfixed y;
74
75     bool operator==(const qfixed2d &other) const { return x == other.x && y == other.y; }
76 };
77 #elif defined QFIXED_IS_32_32
78 typedef qint64 qfixed;
79 #define qt_real_to_fixed(real) qfixed(real * double(qint64(1) << 32))
80 #define qt_fixed_to_real(fixed) qreal(fixed / double(qint64(1) << 32))
81 struct qfixed2d
82 {
83     qfixed x;
84     qfixed y;
85
86     bool operator==(const qfixed2d &other) const { return x == other.x && y == other.y; }
87 };
88 #elif defined QFIXED_IS_16_16
89 typedef int qfixed;
90 #define qt_real_to_fixed(real) qfixed(real * qreal(1 << 16))
91 #define qt_fixed_to_real(fixed) qreal(fixed / qreal(1 << 16))
92 struct qfixed2d
93 {
94     qfixed x;
95     qfixed y;
96
97     bool operator==(const qfixed2d &other) const { return x == other.x && y == other.y; }
98 };
99 #else
100 typedef qreal qfixed;
101 #define qt_real_to_fixed(real) qfixed(real)
102 #define qt_fixed_to_real(fixed) fixed
103 struct qfixed2d
104 {
105     qfixed x;
106     qfixed y;
107
108     bool operator==(const qfixed2d &other) const { return qFuzzyCompare(x, other.x)
109                                                        && qFuzzyCompare(y, other.y); }
110 };
111 #endif
112
113 #define QT_PATH_KAPPA 0.5522847498
114
115 QPointF qt_curves_for_arc(const QRectF &rect, qreal startAngle, qreal sweepLength,
116                           QPointF *controlPoints, int *point_count);
117
118 qreal qt_t_for_arc_angle(qreal angle);
119
120 typedef void (*qStrokerMoveToHook)(qfixed x, qfixed y, void *data);
121 typedef void (*qStrokerLineToHook)(qfixed x, qfixed y, void *data);
122 typedef void (*qStrokerCubicToHook)(qfixed c1x, qfixed c1y,
123                                     qfixed c2x, qfixed c2y,
124                                     qfixed ex, qfixed ey,
125                                     void *data);
126
127 // qtransform.cpp
128 Q_GUI_EXPORT bool qt_scaleForTransform(const QTransform &transform, qreal *scale);
129
130 class Q_GUI_EXPORT QStrokerOps
131 {
132 public:
133     struct Element {
134         QPainterPath::ElementType type;
135         qfixed x;
136         qfixed y;
137
138         inline bool isMoveTo() const { return type == QPainterPath::MoveToElement; }
139         inline bool isLineTo() const { return type == QPainterPath::LineToElement; }
140         inline bool isCurveTo() const { return type == QPainterPath::CurveToElement; }
141
142         operator qfixed2d () { qfixed2d pt = { x, y }; return pt; }
143     };
144
145     QStrokerOps();
146     virtual ~QStrokerOps();
147
148     void setMoveToHook(qStrokerMoveToHook moveToHook) { m_moveTo = moveToHook; }
149     void setLineToHook(qStrokerLineToHook lineToHook) { m_lineTo = lineToHook; }
150     void setCubicToHook(qStrokerCubicToHook cubicToHook) { m_cubicTo = cubicToHook; }
151
152     virtual void begin(void *customData);
153     virtual void end();
154
155     inline void moveTo(qfixed x, qfixed y);
156     inline void lineTo(qfixed x, qfixed y);
157     inline void cubicTo(qfixed x1, qfixed y1, qfixed x2, qfixed y2, qfixed ex, qfixed ey);
158
159     void strokePath(const QPainterPath &path, void *data, const QTransform &matrix);
160     void strokePolygon(const QPointF *points, int pointCount, bool implicit_close,
161                        void *data, const QTransform &matrix);
162     void strokeEllipse(const QRectF &ellipse, void *data, const QTransform &matrix);
163
164     QRectF clipRect() const { return m_clip_rect; }
165     void setClipRect(const QRectF &clip) { m_clip_rect = clip; }
166
167     void setCurveThresholdFromTransform(const QTransform &transform)
168     {
169         qreal scale;
170         qt_scaleForTransform(transform, &scale);
171         m_dashThreshold = scale == 0 ? qreal(0.5) : (qreal(0.5) / scale);
172     }
173
174     void setCurveThreshold(qfixed threshold) { m_curveThreshold = threshold; }
175     qfixed curveThreshold() const { return m_curveThreshold; }
176
177 protected:
178     inline void emitMoveTo(qfixed x, qfixed y);
179     inline void emitLineTo(qfixed x, qfixed y);
180     inline void emitCubicTo(qfixed c1x, qfixed c1y, qfixed c2x, qfixed c2y, qfixed ex, qfixed ey);
181
182     virtual void processCurrentSubpath() = 0;
183     QDataBuffer<Element> m_elements;
184
185     QRectF m_clip_rect;
186     qfixed m_curveThreshold;
187     qfixed m_dashThreshold;
188
189     void *m_customData;
190     qStrokerMoveToHook m_moveTo;
191     qStrokerLineToHook m_lineTo;
192     qStrokerCubicToHook m_cubicTo;
193
194 };
195
196 class Q_GUI_EXPORT QStroker : public QStrokerOps
197 {
198 public:
199
200     enum LineJoinMode {
201         FlatJoin,
202         SquareJoin,
203         MiterJoin,
204         RoundJoin,
205         RoundCap,
206         SvgMiterJoin
207     };
208
209     QStroker();
210     ~QStroker();
211
212     void setStrokeWidth(qfixed width) { m_strokeWidth = width; }
213     qfixed strokeWidth() const { return m_strokeWidth; }
214
215     void setCapStyle(Qt::PenCapStyle capStyle) { m_capStyle = joinModeForCap(capStyle); }
216     Qt::PenCapStyle capStyle() const { return capForJoinMode(m_capStyle); }
217     LineJoinMode capStyleMode() const { return m_capStyle; }
218
219     void setJoinStyle(Qt::PenJoinStyle style) { m_joinStyle = joinModeForJoin(style); }
220     Qt::PenJoinStyle joinStyle() const { return joinForJoinMode(m_joinStyle); }
221     LineJoinMode joinStyleMode() const { return m_joinStyle; }
222
223     void setMiterLimit(qfixed length) { m_miterLimit = length; }
224     qfixed miterLimit() const { return m_miterLimit; }
225
226     void joinPoints(qfixed x, qfixed y, const QLineF &nextLine, LineJoinMode join);
227     inline void emitMoveTo(qfixed x, qfixed y);
228     inline void emitLineTo(qfixed x, qfixed y);
229     inline void emitCubicTo(qfixed c1x, qfixed c1y, qfixed c2x, qfixed c2y, qfixed ex, qfixed ey);
230
231 protected:
232     static Qt::PenCapStyle capForJoinMode(LineJoinMode mode);
233     static LineJoinMode joinModeForCap(Qt::PenCapStyle);
234
235     static Qt::PenJoinStyle joinForJoinMode(LineJoinMode mode);
236     static LineJoinMode joinModeForJoin(Qt::PenJoinStyle joinStyle);
237
238     virtual void processCurrentSubpath();
239
240     qfixed m_strokeWidth;
241     qfixed m_miterLimit;
242
243     LineJoinMode m_capStyle;
244     LineJoinMode m_joinStyle;
245
246     qfixed m_back1X;
247     qfixed m_back1Y;
248
249     qfixed m_back2X;
250     qfixed m_back2Y;
251 };
252
253 class Q_GUI_EXPORT QDashStroker : public QStrokerOps
254 {
255 public:
256     QDashStroker(QStroker *stroker);
257     ~QDashStroker();
258
259     QStroker *stroker() const { return m_stroker; }
260
261     static QVector<qfixed> patternForStyle(Qt::PenStyle style);
262
263     void setDashPattern(const QVector<qfixed> &dashPattern) { m_dashPattern = dashPattern; }
264     QVector<qfixed> dashPattern() const { return m_dashPattern; }
265
266     void setDashOffset(qreal offset) { m_dashOffset = offset; }
267     qreal dashOffset() const { return m_dashOffset; }
268
269     virtual void begin(void *data);
270     virtual void end();
271
272     inline void setStrokeWidth(qreal width) { m_stroke_width = width; }
273     inline void setMiterLimit(qreal limit) { m_miter_limit = limit; }
274
275 protected:
276     virtual void processCurrentSubpath();
277
278     QStroker *m_stroker;
279     QVector<qfixed> m_dashPattern;
280     qreal m_dashOffset;
281
282     qreal m_stroke_width;
283     qreal m_miter_limit;
284 };
285
286
287 /*******************************************************************************
288  * QStrokerOps inline membmers
289  */
290
291 inline void QStrokerOps::emitMoveTo(qfixed x, qfixed y)
292 {
293     Q_ASSERT(m_moveTo);
294     m_moveTo(x, y, m_customData);
295 }
296
297 inline void QStrokerOps::emitLineTo(qfixed x, qfixed y)
298 {
299     Q_ASSERT(m_lineTo);
300     m_lineTo(x, y, m_customData);
301 }
302
303 inline void QStrokerOps::emitCubicTo(qfixed c1x, qfixed c1y, qfixed c2x, qfixed c2y, qfixed ex, qfixed ey)
304 {
305     Q_ASSERT(m_cubicTo);
306     m_cubicTo(c1x, c1y, c2x, c2y, ex, ey, m_customData);
307 }
308
309 inline void QStrokerOps::moveTo(qfixed x, qfixed y)
310 {
311     if (m_elements.size()>1)
312         processCurrentSubpath();
313     m_elements.reset();
314     Element e = { QPainterPath::MoveToElement, x, y };
315     m_elements.add(e);
316 }
317
318 inline void QStrokerOps::lineTo(qfixed x, qfixed y)
319 {
320     Element e = { QPainterPath::LineToElement, x, y };
321     m_elements.add(e);
322 }
323
324 inline void QStrokerOps::cubicTo(qfixed x1, qfixed y1, qfixed x2, qfixed y2, qfixed ex, qfixed ey)
325 {
326     Element c1 = { QPainterPath::CurveToElement, x1, y1 };
327     Element c2 = { QPainterPath::CurveToDataElement, x2, y2 };
328     Element e = { QPainterPath::CurveToDataElement, ex, ey };
329     m_elements.add(c1);
330     m_elements.add(c2);
331     m_elements.add(e);
332 }
333
334 /*******************************************************************************
335  * QStroker inline members
336  */
337 inline void QStroker::emitMoveTo(qfixed x, qfixed y)
338 {
339     m_back2X = m_back1X;
340     m_back2Y = m_back1Y;
341     m_back1X = x;
342     m_back1Y = y;
343     QStrokerOps::emitMoveTo(x, y);
344 }
345
346 inline void QStroker::emitLineTo(qfixed x, qfixed y)
347 {
348     m_back2X = m_back1X;
349     m_back2Y = m_back1Y;
350     m_back1X = x;
351     m_back1Y = y;
352     QStrokerOps::emitLineTo(x, y);
353 }
354
355 inline void QStroker::emitCubicTo(qfixed c1x, qfixed c1y,
356                                   qfixed c2x, qfixed c2y,
357                                   qfixed ex, qfixed ey)
358 {
359     if (c2x == ex && c2y == ey) {
360         if (c1x == ex && c1y == ey) {
361             m_back2X = m_back1X;
362             m_back2Y = m_back1Y;
363         } else {
364             m_back2X = c1x;
365             m_back2Y = c1y;
366         }
367     } else {
368         m_back2X = c2x;
369         m_back2Y = c2y;
370     }
371     m_back1X = ex;
372     m_back1Y = ey;
373     QStrokerOps::emitCubicTo(c1x, c1y, c2x, c2y, ex, ey);
374 }
375
376 /*******************************************************************************
377  * QDashStroker inline members
378  */
379 inline void QDashStroker::begin(void *data)
380 {
381     if (m_stroker)
382         m_stroker->begin(data);
383     QStrokerOps::begin(data);
384 }
385
386 inline void QDashStroker::end()
387 {
388     QStrokerOps::end();
389     if (m_stroker)
390         m_stroker->end();
391 }
392
393 QT_END_NAMESPACE
394
395 #endif // QSTROKER_P_H