update for HEAD-2003091401
[reactos.git] / drivers / dd / vga / display / 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(PCLIPOBJ Clip, PBRUSHOBJ 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, ENUM_RECT_LIMIT);
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(PCLIPOBJ Clip, PBRUSHOBJ 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, ENUM_RECT_LIMIT);
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(PCLIPOBJ Clip, PBRUSHOBJ 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, ENUM_RECT_LIMIT);
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(PCLIPOBJ Clip, PBRUSHOBJ 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, ENUM_RECT_LIMIT);
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   RECTL DestRect;
307   RECT_ENUM RectEnum;
308   BOOL EnumMore;
309
310   x = x1;
311   y = y1;
312   deltax = x2 - x1;
313   deltay = y2 - y1;
314
315   if (deltax < 0)
316     {
317       xchange = -1;
318       deltax = - deltax;
319       hx = x2+1;
320       //x--;
321     }
322   else
323     {
324       xchange = 1;
325       hx = x1;
326     }
327
328   if (deltay < 0)
329     {
330       ychange = -1;
331       deltay = - deltay;
332       vy = y2+1;
333       //y--;
334     }
335   else
336     {
337       ychange = 1;
338       vy = y1;
339     }
340
341   if (y1 == y2)
342     {
343       CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, CD_RIGHTDOWN, ENUM_RECT_LIMIT);
344       do
345         {
346           EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
347           for (i = 0; i < RectEnum.c && RectEnum.arcl[i].top <= y1; i++)
348             {
349               if (y1 < RectEnum.arcl[i].bottom &&
350                   RectEnum.arcl[i].left <= hx + deltax &&
351                   hx < RectEnum.arcl[i].right)
352                 {
353
354                   vgaHLine(max(hx, RectEnum.arcl[i].left), y1,
355                            min(hx + deltax, RectEnum.arcl[i].right)
356                            -max(hx, RectEnum.arcl[i].left), Pixel);
357                 }
358             }
359         }
360       while (EnumMore);
361     }
362   else if (x1 == x2)
363     {
364       CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, CD_RIGHTDOWN, ENUM_RECT_LIMIT);
365       do
366         {
367           EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum);
368           for (i = 0; i < RectEnum.c; i++)
369             {
370               if (RectEnum.arcl[i].left <= x1 &&
371                   x1 < RectEnum.arcl[i].right &&
372                   RectEnum.arcl[i].top <= vy + deltay &&
373                   vy < RectEnum.arcl[i].bottom)
374                 {
375                   vgaVLine(x1,
376                            max(vy, RectEnum.arcl[i].top),
377                            min(vy + deltay, RectEnum.arcl[i].bottom)
378                            - max(vy, RectEnum.arcl[i].top),
379                            Pixel);
380                 }
381             }
382         }
383       while (EnumMore);
384     }
385   else
386     {
387       if (0 < xchange)
388         {
389           if (0 < ychange)
390             {
391               vgaNWtoSE(Clip, Brush, x, y, deltax, deltay);
392             }
393           else
394             {
395               vgaSWtoNE(Clip, Brush, x, y, deltax, deltay);
396             }
397         }
398       else
399         {
400           if (0 < ychange)
401             {
402               vgaNEtoSW(Clip, Brush, x, y, deltax, deltay);
403             }
404           else
405             {
406               vgaSEtoNW(Clip, Brush, x, y, deltax, deltay);
407             }
408         }
409     }
410
411   return TRUE;
412 }
413
414 /* EOF */