4 * This file is part of BeRTOS.
6 * Bertos is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 * As a special exception, you may use this file as part of a free software
21 * library without restriction. Specifically, if other files instantiate
22 * templates or use macros or inline functions from this file, or you compile
23 * this file and link it with other files to produce an executable, this
24 * file does not by itself cause the resulting executable to be covered by
25 * the GNU General Public License. This exception does not however
26 * invalidate any other reasons why the executable file might be covered by
27 * the GNU General Public License.
29 * Copyright 2005 Develer S.r.l. (http://www.develer.com/)
33 * \author Massimiliano Corsini <chad@develer.com>
36 * \brief Low-level drawing routines.
38 * This file contains the implementation of the low-level drawing routines
39 * to draw fill rectangle, fill triangle and so on.
45 *#* Revision 1.1 2006/07/19 13:00:01 bernie
46 *#* Import into DevLib.
48 *#* Revision 1.10 2005/10/15 15:03:43 rasky
49 *#* Remove per-pixel clipping from line().
50 *#* Use clipLine() also for a-scope.
52 *#* Revision 1.9 2005/10/14 15:21:32 eldes
53 *#* Implement the cohen-sutherland clipping on the buffer
55 *#* Revision 1.8 2005/09/27 13:28:10 rasky
56 *#* Add clipping capabilities to line()
57 *#* Fix off-by-one computation of rectangles of drawing.
59 *#* Revision 1.7 2005/09/27 10:41:35 rasky
60 *#* Import line-drawing routine from Devlib
62 *#* Revision 1.6 2005/09/19 16:36:05 chad
63 *#* Fix doxygen autobrief
65 *#* Revision 1.5 2005/07/06 12:51:47 chad
66 *#* Make the fillRectangle() independent of the order of the points of the rectangle
68 *#* Revision 1.4 2005/06/17 15:06:36 chad
69 *#* Remove conversion warning
71 *#* Revision 1.3 2005/06/17 15:04:47 chad
72 *#* Add line clipping capability
74 *#* Revision 1.2 2005/06/15 14:04:43 chad
77 *#* Revision 1.1 2005/06/15 13:34:34 chad
78 *#* Low-level drawing routines
82 // Qt-specific headers
87 * Low-level routine to draw a line.
89 * This routine is based on the Bresenham Line-Drawing Algorithm.
91 * The \a stride represents the width of the image buffer.
92 * (\a x1, \a y1) are the coordinates of the starting point.
93 * (\a x2, \a y2) are the coordinates of the ending point.
95 * The line has no anti-alias, and clipping is not performed. The line
96 * must be fully contained in the buffer (use clipLine() if you need
99 void line(unsigned char *buf,
100 unsigned long bufw, unsigned long bufh, unsigned long stride,
101 int x1, int y1, int x2, int y2, unsigned char color)
103 int x, y, e, len, adx, ady, signx, signy;
136 /* X-major line (octants 1/4/5/8) */
142 assert(y >= 0 && y < static_cast<int>(bufh) &&
143 x >= 0 && x < static_cast<int>(bufw));
144 buf[y * stride + x] = color;
156 /* Y-major line (octants 2/3/6/7) */
162 assert(y >= 0 && y < static_cast<int>(bufh) &&
163 x >= 0 && x < static_cast<int>(bufw));
164 buf[y * stride + x] = color;
176 /// Helper routine for clipLine().
177 static int region(int x, int y, int w, int h)
195 * Low-level routine to draw a line, clipped to the buffer extents.
197 * This routine executes the clipping, and then invokes line().
198 * Parameters are the same of line(). The clipping is performed
199 * using the Cohen-Sutherland algorithm, which is very fast.
201 void clipLine(unsigned char *buf,
202 unsigned long w, unsigned long h, unsigned long stride,
203 int x1, int y1, int x2, int y2, unsigned char color)
205 int code1 = region(x1, y1, w, h);
206 int code2 = region(x2, y2, w, h);
208 // Loop while there is at least one point outside
209 while (code1 | code2)
211 // Check for line totally outside
215 int c = code1 ? code1 : code2;
220 x = x1 + (x2 - x1) * (h - y1) / (y2 - y1);
223 else if (c & 2) //bottom
225 x = x1 + (x2 - x1) * -y1 / (y2 - y1);
228 else if (c & 4) //right
230 y = y1 + (y2 - y1) * (w - x1) / (x2 - x1);
235 y = y1 + (y2 - y1) * -x1 / (x2 - x1);
239 if (c == code1) // first endpoint was clipped
242 code1 = region(x1, y1, w, h);
244 else //second endpoint was clipped
247 code2 = region(x2, y2, w, h);
251 line(buf, w, h, stride, x1, y1, x2, y2, color);
256 * Low-level routine to draw a filled rectangle.
258 * The triangle is filled with the given color.
260 * The \a stride represents the width of the image buffer.
261 * The points \a p1 and \a p2 are two opposite corners of the
264 void fillRectangle(unsigned char *buf, unsigned long stride,
265 QPoint p1, QPoint p2, unsigned char color)
267 QPoint ul; // upper-left corner
268 QPoint lr; // lower-right corner
292 int width = lr.x() - ul.x();
293 unsigned long offset = ul.x() + ul.y()*stride;
295 for (int h = ul.y(); h < lr.y(); h++)
297 memset(buf+offset, color, width);
303 * Low-level routines to draw a filled triangle.
305 * The triangle is filled with the given \a color.
306 * The \a stride represents the width of the image buffer (\a buf).
308 * The routine use fixed-point arithmetic.
310 void fillTriangle(unsigned char* buf, unsigned long stride,
311 QPoint v1, QPoint v2, QPoint v3, unsigned char color)
315 // Sort by vertical coordinate
323 altezza[0] = v3.y() - v1.y();
330 buf += v1.y() * stride;
332 altezza[1] = v2.y() - v1.y();
333 altezza[2] = v3.y() - v2.y();
335 int sinistra = v1.x();
336 int destra = sinistra;
338 if (v1.y() == v2.y())
349 int stmp1, stmp2, stmp3;
351 stmp1 = (altezza[1] << 16) / altezza[0];
352 int lunghezza = stmp1 * (v3.x() - v1.x()) + ((v1.x() - v2.x()) << 16);
357 int delta_sinistra[2];
360 stmp1 = ((v3.x() - v1.x()) << 16) / altezza[0];
363 stmp2 = ((v2.x() - v1.x()) << 16) / altezza[1];
365 stmp3 = ((v3.x() - v2.x()) << 16) / altezza[2];
367 if (lunghezza < 0) // Il secondo vertice ~J a destra
369 delta_sinistra[0] = stmp1;
370 delta_sinistra[1] = stmp1;
371 delta_destra[0] = stmp2;
372 delta_destra[1] = stmp3;
374 else // Il secondo vertice ~J a sinistra
376 delta_sinistra[0] = stmp2;
377 delta_sinistra[1] = stmp3;
378 delta_destra[0] = stmp1;
379 delta_destra[1] = stmp1;
382 int len2 = lunghezza;
386 while (altezza [sezione])
388 unsigned char* curpos = buf + ((sinistra )>> 16);
389 lunghezza = ((destra ) >> 16) - ((sinistra ) >> 16);
390 assert(lunghezza >= 0);
392 memset(curpos, color, lunghezza);
394 destra += delta_destra[sezione - 1];
395 sinistra += delta_sinistra[sezione - 1];
399 destra = v2.x() << 16;
401 sinistra = v2.x() << 16;