source: trunk/src/qt3support/other/q3polygonscanner.cpp@ 561

Last change on this file since 561 was 561, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.1 sources.

File size: 28.6 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the Qt3Support module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "q3polygonscanner.h"
43#include "q3pointarray.h"
44#include <stdlib.h>
45
46QT_BEGIN_NAMESPACE
47
48// Based on Xserver code miFillGeneralPoly...
49/*
50 *
51 * Written by Brian Kelleher; Oct. 1985
52 *
53 * Routine to fill a polygon. Two fill rules are
54 * supported: frWINDING and frEVENODD.
55 *
56 * See fillpoly.h for a complete description of the algorithm.
57 */
58
59/*
60 * These are the data structures needed to scan
61 * convert regions. Two different scan conversion
62 * methods are available -- the even-odd method, and
63 * the winding number method.
64 * The even-odd rule states that a point is inside
65 * the polygon if a ray drawn from that point in any
66 * direction will pass through an odd number of
67 * path segments.
68 * By the winding number rule, a point is decided
69 * to be inside the polygon if a ray drawn from that
70 * point in any direction passes through a different
71 * number of clockwise and counterclockwise path
72 * segments.
73 *
74 * These data structures are adapted somewhat from
75 * the algorithm in (Foley/Van Dam) for scan converting
76 * polygons.
77 * The basic algorithm is to start at the top (smallest y)
78 * of the polygon, stepping down to the bottom of
79 * the polygon by incrementing the y coordinate. We
80 * keep a list of edges which the current scanline crosses,
81 * sorted by x. This list is called the Active Edge Table (AET)
82 * As we change the y-coordinate, we update each entry in
83 * in the active edge table to reflect the edges new xcoord.
84 * This list must be sorted at each scanline in case
85 * two edges intersect.
86 * We also keep a data structure known as the Edge Table (ET),
87 * which keeps track of all the edges which the current
88 * scanline has not yet reached. The ET is basically a
89 * list of ScanLineList structures containing a list of
90 * edges which are entered at a given scanline. There is one
91 * ScanLineList per scanline at which an edge is entered.
92 * When we enter a new edge, we move it from the ET to the AET.
93 *
94 * From the AET, we can implement the even-odd rule as in
95 * (Foley/Van Dam).
96 * The winding number rule is a little trickier. We also
97 * keep the EdgeTableEntries in the AET linked by the
98 * nextWETE (winding EdgeTableEntry) link. This allows
99 * the edges to be linked just as before for updating
100 * purposes, but only uses the edges linked by the nextWETE
101 * link as edges representing spans of the polygon to
102 * drawn (as with the even-odd rule).
103 */
104
105/* $XConsortium: miscanfill.h,v 1.5 94/04/17 20:27:50 dpw Exp $ */
106/*
107
108Copyright (c) 1987 X Consortium
109
110Permission is hereby granted, free of charge, to any person obtaining
111a copy of this software and associated documentation files (the
112"Software"), to deal in the Software without restriction, including
113without limitation the rights to use, copy, modify, merge, publish,
114distribute, sublicense, and/or sell copies of the Software, and to
115permit persons to whom the Software is furnished to do so, subject to
116the following conditions:
117
118The above copyright notice and this permission notice shall be included
119in all copies or substantial portions of the Software.
120
121THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
122OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
123MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
124IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
125OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
126ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
127OTHER DEALINGS IN THE SOFTWARE.
128
129Except as contained in this notice, the name of the X Consortium shall
130not be used in advertising or otherwise to promote the sale, use or
131other dealings in this Software without prior written authorization
132from the X Consortium.
133
134*/
135
136
137/*
138 * scanfill.h
139 *
140 * Written by Brian Kelleher; Jan 1985
141 *
142 * This file contains a few macros to help track
143 * the edge of a filled object. The object is assumed
144 * to be filled in scanline order, and thus the
145 * algorithm used is an extension of Bresenham's line
146 * drawing algorithm which assumes that y is always the
147 * major axis.
148 * Since these pieces of code are the same for any filled shape,
149 * it is more convenient to gather the library in one
150 * place, but since these pieces of code are also in
151 * the inner loops of output primitives, procedure call
152 * overhead is out of the question.
153 * See the author for a derivation if needed.
154 */
155
156/*
157 * In scan converting polygons, we want to choose those pixels
158 * which are inside the polygon. Thus, we add .5 to the starting
159 * x coordinate for both left and right edges. Now we choose the
160 * first pixel which is inside the pgon for the left edge and the
161 * first pixel which is outside the pgon for the right edge.
162 * Draw the left pixel, but not the right.
163 *
164 * How to add .5 to the starting x coordinate:
165 * If the edge is moving to the right, then subtract dy from the
166 * error term from the general form of the algorithm.
167 * If the edge is moving to the left, then add dy to the error term.
168 *
169 * The reason for the difference between edges moving to the left
170 * and edges moving to the right is simple: If an edge is moving
171 * to the right, then we want the algorithm to flip immediately.
172 * If it is moving to the left, then we don't want it to flip until
173 * we traverse an entire pixel.
174 */
175#define BRESINITPGON(dy, x1, x2, xStart, d, m, m1, incr1, incr2) { \
176 int dx; /* local storage */ \
177\
178 /* \
179 * if the edge is horizontal, then it is ignored \
180 * and assumed not to be processed. Otherwise, do this stuff. \
181 */ \
182 if ((dy) != 0) { \
183 xStart = (x1); \
184 dx = (x2) - xStart; \
185 if (dx < 0) { \
186 m = dx / (dy); \
187 m1 = m - 1; \
188 incr1 = -2 * dx + 2 * (dy) * m1; \
189 incr2 = -2 * dx + 2 * (dy) * m; \
190 d = 2 * m * (dy) - 2 * dx - 2 * (dy); \
191 } else { \
192 m = dx / (dy); \
193 m1 = m + 1; \
194 incr1 = 2 * dx - 2 * (dy) * m1; \
195 incr2 = 2 * dx - 2 * (dy) * m; \
196 d = -2 * m * (dy) + 2 * dx; \
197 } \
198 } \
199}
200
201
202#define BRESINCRPGON(d, minval, m, m1, incr1, incr2) { \
203 if (m1 > 0) { \
204 if (d > 0) { \
205 minval += m1; \
206 d += incr1; \
207 } \
208 else { \
209 minval += m; \
210 d += incr2; \
211 } \
212 } else {\
213 if (d >= 0) { \
214 minval += m1; \
215 d += incr1; \
216 } \
217 else { \
218 minval += m; \
219 d += incr2; \
220 } \
221 } \
222}
223
224
225
226/*
227 * This structure contains all of the information needed
228 * to run the bresenham algorithm.
229 * The variables may be hardcoded into the declarations
230 * instead of using this structure to make use of
231 * register declarations.
232 */
233typedef struct {
234 int minor; /* minor axis */
235 int d; /* decision variable */
236 int m, m1; /* slope and slope+1 */
237 int incr1, incr2; /* error increments */
238} BRESINFO;
239
240
241#define BRESINITPGONSTRUCT(dmaj, min1, min2, bres) \
242 BRESINITPGON(dmaj, min1, min2, bres.minor, bres.d, \
243 bres.m, bres.m1, bres.incr1, bres.incr2)
244
245#define BRESINCRPGONSTRUCT(bres) \
246 BRESINCRPGON(bres.d, bres.minor, bres.m, bres.m1, bres.incr1, bres.incr2)
247
248
249typedef struct _EdgeTableEntry {
250 int ymax; /* ycoord at which we exit this edge. */
251 BRESINFO bres; /* Bresenham info to run the edge */
252 struct _EdgeTableEntry *next; /* next in the list */
253 struct _EdgeTableEntry *back; /* for insertion sort */
254 struct _EdgeTableEntry *nextWETE; /* for winding num rule */
255 int ClockWise; /* flag for winding number rule */
256} EdgeTableEntry;
257
258
259typedef struct _ScanLineList{
260 int scanline; /* the scanline represented */
261 EdgeTableEntry *edgelist; /* header node */
262 struct _ScanLineList *next; /* next in the list */
263} ScanLineList;
264
265
266typedef struct {
267 int ymax; /* ymax for the polygon */
268 int ymin; /* ymin for the polygon */
269 ScanLineList scanlines; /* header node */
270} EdgeTable;
271
272
273/*
274 * Here is a struct to help with storage allocation
275 * so we can allocate a big chunk at a time, and then take
276 * pieces from this heap when we need to.