9ef13d68b2651e1cd9494230c13cbaf775efab9f
[reactos.git] / reactos / drivers / video / displays / vga / objects / lineto.c
1 /*
2 * ReactOS VGA driver
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 *
19 * $Id$
20 */
21
22 #include "../vgaddi.h"
23 #include "../vgavideo/vgavideo.h"
24
25 /*
26 * Draw a line from top-left to bottom-right
27 */
28 static void FASTCALL
29 vgaNWtoSE(CLIPOBJ* Clip, BRUSHOBJ* Brush, LONG x, LONG y, LONG deltax, LONG deltay)
30 {
31 int i;
32 int error;
33 BOOLEAN EnumMore;
34 PRECTL ClipRect;
35 RECT_ENUM RectEnum;
36 ULONG Pixel = Brush->iSolidColor;
37 LONG delta;
38
39 CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, CD_RIGHTDOWN, 0);
40 EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
41 ClipRect = RectEnum.arcl;
42 delta = max(deltax, deltay);
43 i = 0;
44 error = delta/2;
45 while (i < delta && (ClipRect < RectEnum.arcl + RectEnum.c || EnumMore))
46 {
47 while ((ClipRect < RectEnum.arcl + RectEnum.c /* there's still a current clip rect */
48 && (ClipRect->bottom <= y /* but it's above us */
49 || (ClipRect->top <= y && ClipRect->right <= x))) /* or to the left of us */
50 || EnumMore) /* no current clip rect, but rects left */
51 {
52 /* Skip to the next clip rect */
53 if (RectEnum.arcl + RectEnum.c <= ClipRect)
54 {
55 EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
56 ClipRect = RectEnum.arcl;
57 }
58 else
59 {
60 ClipRect++;
61 }
62 }
63 if ( ClipRect < RectEnum.arcl + RectEnum.c ) /* If there's no current clip rect we're done */
64 {
65 if (ClipRect->left <= x && ClipRect->top <= y)
66 {
67 vgaPutPixel ( x, y, Pixel );
68 }
69 if ( deltax < deltay )
70 {
71 y++;
72 error += deltax;
73 if ( error >= deltay )
74 {
75 x++;
76 error -= deltay;
77 }
78 }
79 else
80 {
81 x++;
82 error += deltay;
83 if ( error >= deltax )
84 {
85 y++;
86 error -= deltax;
87 }
88 }
89 i++;
90 }
91 }
92 }
93
94 static void FASTCALL
95 vgaSWtoNE(CLIPOBJ* Clip, BRUSHOBJ* Brush, LONG x, LONG y, LONG deltax, LONG deltay)
96 {
97 int i;
98 int error;
99 BOOLEAN EnumMore;
100 PRECTL ClipRect;
101 RECT_ENUM RectEnum;
102 ULONG Pixel = Brush->iSolidColor;
103 LONG delta;
104
105 CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, CD_RIGHTUP, 0);
106 EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
107 ClipRect = RectEnum.arcl;
108 delta = max(deltax, deltay);
109 i = 0;
110 error = delta/2;
111 while (i < delta && (ClipRect < RectEnum.arcl + RectEnum.c || EnumMore))
112 {
113 while ((ClipRect < RectEnum.arcl + RectEnum.c
114 && (y < ClipRect->top
115 || (y < ClipRect->bottom && ClipRect->right <= x)))
116 || EnumMore)
117 {
118 if (RectEnum.arcl + RectEnum.c <= ClipRect)
119 {
120 EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
121 ClipRect = RectEnum.arcl;
122 }
123 else
124 {
125 ClipRect++;
126 }
127 }
128 if (ClipRect < RectEnum.arcl + RectEnum.c)
129 {
130 if (ClipRect->left <= x && y < ClipRect->bottom)
131 {
132 vgaPutPixel(x, y, Pixel);
133 }
134 if (deltax < deltay)
135 {
136 y--;
137 error = error + deltax;
138 if (deltay <= error)
139 {
140 x++;
141 error = error - deltay;
142 }
143 }
144 else
145 {
146 x++;
147 error = error + deltay;
148 if (deltax <= error)
149 {
150 y--;
151 error = error - deltax;
152 }
153 }
154 i++;
155 }
156 }
157 }
158
159 static void FASTCALL
160 vgaNEtoSW(CLIPOBJ* Clip, BRUSHOBJ* Brush, LONG x, LONG y, LONG deltax, LONG deltay)
161 {
162 int i;
163 int error;
164 BOOLEAN EnumMore;
165 PRECTL ClipRect;
166 RECT_ENUM RectEnum;
167 ULONG Pixel = Brush->iSolidColor;
168 LONG delta;
169
170 CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, CD_LEFTDOWN, 0);
171 EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
172 ClipRect = RectEnum.arcl;
173 delta = max(deltax, deltay);
174 i = 0;
175 error = delta/2;
176 while (i < delta && (ClipRect < RectEnum.arcl + RectEnum.c || EnumMore))
177 {
178 while ((ClipRect < RectEnum.arcl + RectEnum.c
179 && (ClipRect->bottom <= y
180 || (ClipRect->top <= y && x < ClipRect->left)))
181 || EnumMore)
182 {
183 if (RectEnum.arcl + RectEnum.c <= ClipRect)
184 {
185 EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
186 ClipRect = RectEnum.arcl;
187 }
188 else
189 {
190 ClipRect++;
191 }
192 }
193 if (ClipRect < RectEnum.arcl + RectEnum.c)
194 {
195 if (x < ClipRect->right && ClipRect->top <= y)
196 {
197 vgaPutPixel(x, y, Pixel);
198 }
199 if (deltax < deltay)
200 {
201 y++;
202 error = error + deltax;
203 if (deltay <= error)
204 {
205 x--;
206 error = error - deltay;
207 }
208 }
209 else
210 {
211 x--;
212 error = error + deltay;
213 if (deltax <= error)
214 {
215 y++;
216 error = error - deltax;
217 }
218 }
219 i++;
220 }
221 }
222 }
223
224 static void FASTCALL
225 vgaSEtoNW(CLIPOBJ* Clip, BRUSHOBJ* Brush, LONG x, LONG y, LONG deltax, LONG deltay)
226 {
227 int i;
228 int error;
229 BOOLEAN EnumMore;
230 PRECTL ClipRect;
231 RECT_ENUM RectEnum;
232 ULONG Pixel = Brush->iSolidColor;
233 LONG delta;
234
235 CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, CD_LEFTUP, 0);
236 EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
237 ClipRect = RectEnum.arcl;
238 delta = max(deltax, deltay);
239 i = 0;
240 error = delta/2;
241 while (i < delta && (ClipRect < RectEnum.arcl + RectEnum.c || EnumMore))
242 {
243 while ((ClipRect < RectEnum.arcl + RectEnum.c
244 && (y < ClipRect->top
245 || (y < ClipRect->bottom && x < ClipRect->left)))
246 || EnumMore)
247 {
248 if (RectEnum.arcl + RectEnum.c <= ClipRect)
249 {
250 EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
251 ClipRect = RectEnum.arcl;
252 }
253 else
254 {
255 ClipRect++;
256 }
257 }
258 if (ClipRect < RectEnum.arcl + RectEnum.c)
259 {
260 if (x < ClipRect->right && y < ClipRect->bottom)
261 {
262 vgaPutPixel(x, y, Pixel);
263 }
264 if (deltax < deltay)
265 {
266 y--;
267 error = error + deltax;
268 if (deltay <= error)
269 {
270 x--;
271 error = error - deltay;
272 }
273 }
274 else
275 {
276 x--;
277 error = error + deltay;
278 if (deltax <= error)
279 {
280 y--;
281 error = error - deltax;
282 }
283 }
284 i++;
285 }
286 }
287 }
288
289 /*
290 * FIXME: Use Mix to perform ROPs
291 * FIXME: Non-solid Brush
292 */
293 BOOL STDCALL
294 DrvLineTo(SURFOBJ *DestObj,
295 CLIPOBJ *Clip,
296 BRUSHOBJ *Brush,
297 LONG x1,
298 LONG y1,
299 LONG x2,
300 LONG y2,
301 RECTL *RectBounds,
302 MIX mix)
303 {
304 LONG x, y, deltax, deltay, i, xchange, ychange, hx, vy;
305 ULONG Pixel = Brush->iSolidColor;
306 RECT_ENUM RectEnum;
307 BOOL EnumMore;
308
309 x = x1;
310 y = y1;
311 deltax = x2 - x1;
312 deltay = y2 - y1;
313
314 if (deltax < 0)
315 {
316 xchange = -1;
317 deltax = - deltax;
318 hx = x2+1;
319 //x--;
320 }
321 else
322 {
323 xchange = 1;
324 hx = x1;
325 }
326
327 if (deltay < 0)
328 {
329 ychange = -1;
330 deltay = - deltay;
331 vy = y2+1;
332 //y--;
333 }
334 else
335 {
336 ychange = 1;
337 vy = y1;
338 }
339
340 if (y1 == y2)
341 {
342 CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, CD_RIGHTDOWN, 0);
343 do
344 {
345 EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
346 for (i = 0; i < RectEnum.c && RectEnum.arcl[i].top <= y1; i++)
347 {
348 if (y1 < RectEnum.arcl[i].bottom &&
349 RectEnum.arcl[i].left <= hx + deltax &&
350 hx < RectEnum.arcl[i].right)
351 {
352
353 vgaHLine(max(hx, RectEnum.arcl[i].left), y1,
354 min(hx + deltax, RectEnum.arcl[i].right)
355 -max(hx, RectEnum.arcl[i].left), Pixel);
356 }
357 }
358 }
359 while (EnumMore);
360 }
361 else if (x1 == x2)
362 {
363 CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, CD_RIGHTDOWN, 0);
364 do
365 {
366 EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
367 for (i = 0; i < RectEnum.c; i++)
368 {
369 if (RectEnum.arcl[i].left <= x1 &&
370 x1 < RectEnum.arcl[i].right &&
371 RectEnum.arcl[i].top <= vy + deltay &&
372 vy < RectEnum.arcl[i].bottom)
373 {
374 vgaVLine(x1,
375 max(vy, RectEnum.arcl[i].top),
376 min(vy + deltay, RectEnum.arcl[i].bottom)
377 - max(vy, RectEnum.arcl[i].top),
378 Pixel);
379 }
380 }
381 }
382 while (EnumMore);
383 }
384 else
385 {
386 if (0 < xchange)
387 {
388 if (0 < ychange)
389 {
390 vgaNWtoSE(Clip, Brush, x, y, deltax, deltay);
391 }
392 else
393 {
394 vgaSWtoNE(Clip, Brush, x, y, deltax, deltay);
395 }
396 }
397 else
398 {
399 if (0 < ychange)
400 {
401 vgaNEtoSW(Clip, Brush, x, y, deltax, deltay);
402 }
403 else
404 {
405 vgaSEtoNW(Clip, Brush, x, y, deltax, deltay);
406 }
407 }
408 }
409
410 return TRUE;
411 }
412
413 /* EOF */