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/)
34 * \author Massimiliano Corsini <chad@develer.com>
37 * \brief Low-level drawing routines.
39 * This file contains the implementation of the low-level drawing routines
40 * to draw fill rectangle, fill triangle and so on.
46 *#* Revision 1.1 2006/07/19 13:00:01 bernie
47 *#* Import into DevLib.
49 *#* Revision 1.10 2005/10/15 15:03:43 rasky
50 *#* Remove per-pixel clipping from line().
51 *#* Use clipLine() also for a-scope.
53 *#* Revision 1.9 2005/10/14 15:21:32 eldes
54 *#* Implement the cohen-sutherland clipping on the buffer
56 *#* Revision 1.8 2005/09/27 13:28:10 rasky
57 *#* Add clipping capabilities to line()
58 *#* Fix off-by-one computation of rectangles of drawing.
60 *#* Revision 1.7 2005/09/27 10:41:35 rasky
61 *#* Import line-drawing routine from Devlib
63 *#* Revision 1.6 2005/09/19 16:36:05 chad
64 *#* Fix doxygen autobrief
66 *#* Revision 1.5 2005/07/06 12:51:47 chad
67 *#* Make the fillRectangle() independent of the order of the points of the rectangle
69 *#* Revision 1.4 2005/06/17 15:06:36 chad
70 *#* Remove conversion warning
72 *#* Revision 1.3 2005/06/17 15:04:47 chad
73 *#* Add line clipping capability
75 *#* Revision 1.2 2005/06/15 14:04:43 chad
78 *#* Revision 1.1 2005/06/15 13:34:34 chad
79 *#* Low-level drawing routines
83 // Qt-specific headers
88 * Low-level routine to draw a line.
90 * This routine is based on the Bresenham Line-Drawing Algorithm.
92 * The \a stride represents the width of the image buffer.
93 * (\a x1, \a y1) are the coordinates of the starting point.
94 * (\a x2, \a y2) are the coordinates of the ending point.
96 * The line has no anti-alias, and clipping is not performed. The line
97 * must be fully contained in the buffer (use clipLine() if you need
100 void line(unsigned char *buf,
101 unsigned long bufw, unsigned long bufh, unsigned long stride,
102 int x1, int y1, int x2, int y2, unsigned char color)
104 int x, y, e, len, adx, ady, signx, signy;
137 /* X-major line (octants 1/4/5/8) */
143 assert(y >= 0 && y < static_cast<int>(bufh) &&
144 x >= 0 && x < static_cast<int>(bufw));
145 buf[y * stride + x] = color;
157 /* Y-major line (octants 2/3/6/7) */
163 assert(y >= 0 && y < static_cast<int>(bufh) &&
164 x >= 0 && x < static_cast<int>(bufw));
165 buf[y * stride + x] = color;
177 /// Helper routine for clipLine().
178 static int region(int x, int y, int w, int h)
196 * Low-level routine to draw a line, clipped to the buffer extents.
198 * This routine executes the clipping, and then invokes line().
199 * Parameters are the same of line(). The clipping is performed
200 * using the Cohen-Sutherland algorithm, which is very fast.
202 void clipLine(unsigned char *buf,
203 unsigned long w, unsigned long h, unsigned long stride,
204 int x1, int y1, int x2, int y2, unsigned char color)
206 int code1 = region(x1, y1, w, h);
207 int code2 = region(x2, y2, w, h);
209 // Loop while there is at least one point outside
210 while (code1 | code2)
212 // Check for line totally outside
216 int c = code1 ? code1 : code2;
221 x = x1 + (x2 - x1) * (h - y1) / (y2 - y1);
224 else if (c & 2) //bottom
226 x = x1 + (x2 - x1) * -y1 / (y2 - y1);
229 else if (c & 4) //right
231 y = y1 + (y2 - y1) * (w - x1) / (x2 - x1);
236 y = y1 + (y2 - y1) * -x1 / (x2 - x1);
240 if (c == code1) // first endpoint was clipped
243 code1 = region(x1, y1, w, h);
245 else //second endpoint was clipped
248 code2 = region(x2, y2, w, h);
252 line(buf, w, h, stride, x1, y1, x2, y2, color);
257 * Low-level routine to draw a filled rectangle.
259 * The triangle is filled with the given color.
261 * The \a stride represents the width of the image buffer.
262 * The points \a p1 and \a p2 are two opposite corners of the
265 void fillRectangle(unsigned char *buf, unsigned long stride,
266 QPoint p1, QPoint p2, unsigned char color)
268 QPoint ul; // upper-left corner
269 QPoint lr; // lower-right corner
293 int width = lr.x() - ul.x();
294 unsigned long offset = ul.x() + ul.y()*stride;
296 for (int h = ul.y(); h < lr.y(); h++)
298 memset(buf+offset, color, width);
304 * Low-level routines to draw a filled triangle.
306 * The triangle is filled with the given \a color.
307 * The \a stride represents the width of the image buffer (\a buf).
309 * The routine use fixed-point arithmetic.
311 void fillTriangle(unsigned char* buf, unsigned long stride,
312 QPoint v1, QPoint v2, QPoint v3, unsigned char color)
316 // Sort by vertical coordinate
324 altezza[0] = v3.y() - v1.y();
331 buf += v1.y() * stride;
333 altezza[1] = v2.y() - v1.y();
334 altezza[2] = v3.y() - v2.y();
336 int sinistra = v1.x();
337 int destra = sinistra;
339 if (v1.y() == v2.y())
350 int stmp1, stmp2, stmp3;
352 stmp1 = (altezza[1] << 16) / altezza[0];
353 int lunghezza = stmp1 * (v3.x() - v1.x()) + ((v1.x() - v2.x()) << 16);
358 int delta_sinistra[2];
361 stmp1 = ((v3.x() - v1.x()) << 16) / altezza[0];
364 stmp2 = ((v2.x() - v1.x()) << 16) / altezza[1];
366 stmp3 = ((v3.x() - v2.x()) << 16) / altezza[2];
368 if (lunghezza < 0) // Il secondo vertice ~J a destra
370 delta_sinistra[0] = stmp1;
371 delta_sinistra[1] = stmp1;
372 delta_destra[0] = stmp2;
373 delta_destra[1] = stmp3;
375 else // Il secondo vertice ~J a sinistra
377 delta_sinistra[0] = stmp2;
378 delta_sinistra[1] = stmp3;
379 delta_destra[0] = stmp1;
380 delta_destra[1] = stmp1;
383 int len2 = lunghezza;
387 while (altezza [sezione])
389 unsigned char* curpos = buf + ((sinistra )>> 16);
390 lunghezza = ((destra ) >> 16) - ((sinistra ) >> 16);
391 assert(lunghezza >= 0);
393 memset(curpos, color, lunghezza);
395 destra += delta_destra[sezione - 1];
396 sinistra += delta_sinistra[sezione - 1];
400 destra = v2.x() << 16;
402 sinistra = v2.x() << 16;