1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtGui module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #ifndef QPOLYGONCLIPPER_P_H
43 #define QPOLYGONCLIPPER_P_H
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.
56 #include "private/qdatabuffer_p.h"
60 /* based on sutherland-hodgman line-by-line clipping, as described in
61 Computer Graphics and Principles */
62 template <typename InType, typename OutType, typename CastType> class QPolygonClipper
66 buffer1(0), buffer2(0)
68 x1 = y1 = x2 = y2 = 0;
75 void setBoundingRect(const QRect bounds)
78 x2 = bounds.x() + bounds.width();
80 y2 = bounds.y() + bounds.height();
85 return QRect(QPoint(x1, y1), QPoint(x2, y2));
88 inline OutType intersectLeft(const OutType &p1, const OutType &p2)
91 qreal dy = (p1.y - p2.y) / qreal(p1.x - p2.x);
93 t.y = static_cast<CastType>(p2.y + (x1 - p2.x) * dy);
98 inline OutType intersectRight(const OutType &p1, const OutType &p2)
101 qreal dy = (p1.y - p2.y) / qreal(p1.x - p2.x);
103 t.y = static_cast<CastType>(p2.y + (x2 - p2.x) * dy);
108 inline OutType intersectTop(const OutType &p1, const OutType &p2)
111 qreal dx = (p1.x - p2.x) / qreal(p1.y - p2.y);
112 t.x = static_cast<CastType>(p2.x + (y1 - p2.y) * dx);
118 inline OutType intersectBottom(const OutType &p1, const OutType &p2)
121 qreal dx = (p1.x - p2.x) / qreal(p1.y - p2.y);
122 t.x = static_cast<CastType>(p2.x + (y2 - p2.y) * dx);
128 void clipPolygon(const InType *inPoints, int inCount, OutType **outPoints, int *outCount,
129 bool closePolygon = true)
142 QDataBuffer<OutType> *source = &buffer1;
143 QDataBuffer<OutType> *clipped = &buffer2;
145 // Gather some info since we are iterating through the points anyway..
146 bool doLeft = false, doRight = false, doTop = false, doBottom = false;
148 for (int i=0; i<inCount; ++i) {
162 if (doLeft && clipped->size() > 1) {
163 QDataBuffer<OutType> *tmp = source;
169 lastPos = source->size() - 1;
174 if (source->at(0).x >= x1)
175 clipped->add(source->at(0));
177 for (int i=start; i<inCount; ++i) {
178 const OutType &cpt = source->at(i);
179 const OutType &ppt = source->at(lastPos);
185 clipped->add(intersectLeft(cpt, ppt));
188 } else if (ppt.x >= x1) {
189 clipped->add(intersectLeft(cpt, ppt));
195 if (doRight && clipped->size() > 1) {
196 QDataBuffer<OutType> *tmp = source;
202 lastPos = source->size() - 1;
207 if (source->at(0).x <= x2)
208 clipped->add(source->at(0));
210 for (int i=start; i<source->size(); ++i) {
211 const OutType &cpt = source->at(i);
212 const OutType &ppt = source->at(lastPos);
218 clipped->add(intersectRight(cpt, ppt));
221 } else if (ppt.x <= x2) {
222 clipped->add(intersectRight(cpt, ppt));
230 if (doTop && clipped->size() > 1) {
231 QDataBuffer<OutType> *tmp = source;
237 lastPos = source->size() - 1;
242 if (source->at(0).y >= y1)
243 clipped->add(source->at(0));
245 for (int i=start; i<source->size(); ++i) {
246 const OutType &cpt = source->at(i);
247 const OutType &ppt = source->at(lastPos);
253 clipped->add(intersectTop(cpt, ppt));
256 } else if (ppt.y >= y1) {
257 clipped->add(intersectTop(cpt, ppt));
264 if (doBottom && clipped->size() > 1) {
265 QDataBuffer<OutType> *tmp = source;
271 lastPos = source->size() - 1;
276 if (source->at(0).y <= y2)
277 clipped->add(source->at(0));
279 for (int i=start; i<source->size(); ++i) {
280 const OutType &cpt = source->at(i);
281 const OutType &ppt = source->at(lastPos);
287 clipped->add(intersectBottom(cpt, ppt));
290 } else if (ppt.y <= y2) {
291 clipped->add(intersectBottom(cpt, ppt));
297 if (closePolygon && clipped->size() > 0) {
298 // close clipped polygon
299 if (clipped->at(0).x != clipped->at(clipped->size()-1).x ||
300 clipped->at(0).y != clipped->at(clipped->size()-1).y) {
301 OutType ot = clipped->at(0);
305 *outCount = clipped->size();
306 *outPoints = clipped->data();
311 QDataBuffer<OutType> buffer1;
312 QDataBuffer<OutType> buffer2;
317 #endif // QPOLYGONCLIPPER_P_H