1 /* 2 * PROJECT: ReactOS VGA display driver 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: win32ss/drivers/displays/vga/objects/lineto.c 5 * PURPOSE: 6 * PROGRAMMERS: Copyright (C) 1998-2003 ReactOS Team 7 */ 8 9 #include <vgaddi.h> 10 11 /* 12 * Draw a line from top-left to bottom-right 13 */ 14 static void FASTCALL 15 vgaNWtoSE( 16 IN CLIPOBJ* Clip, 17 IN BRUSHOBJ* Brush, 18 IN LONG x, 19 IN LONG y, 20 IN LONG deltax, 21 IN LONG deltay) 22 { 23 int i; 24 int error; 25 BOOLEAN EnumMore; 26 PRECTL ClipRect; 27 RECT_ENUM RectEnum; 28 ULONG Pixel = Brush->iSolidColor; 29 LONG delta; 30 31 CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, CD_RIGHTDOWN, 0); 32 EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum); 33 ClipRect = RectEnum.arcl; 34 delta = max(deltax, deltay); 35 i = 0; 36 error = delta / 2; 37 while (i < delta && (ClipRect < RectEnum.arcl + RectEnum.c || EnumMore)) 38 { 39 while ((ClipRect < RectEnum.arcl + RectEnum.c /* there's still a current clip rect */ 40 && (ClipRect->bottom <= y /* but it's above us */ 41 || (ClipRect->top <= y && ClipRect->right <= x))) /* or to the left of us */ 42 || EnumMore) /* no current clip rect, but rects left */ 43 { 44 /* Skip to the next clip rect */ 45 if (RectEnum.arcl + RectEnum.c <= ClipRect) 46 { 47 EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum); 48 ClipRect = RectEnum.arcl; 49 } 50 else 51 { 52 ClipRect++; 53 } 54 } 55 if ( ClipRect < RectEnum.arcl + RectEnum.c ) /* If there's no current clip rect we're done */ 56 { 57 if (ClipRect->left <= x && ClipRect->top <= y) 58 vgaPutPixel ( x, y, Pixel ); 59 if ( deltax < deltay ) 60 { 61 y++; 62 error += deltax; 63 if ( error >= deltay ) 64 { 65 x++; 66 error -= deltay; 67 } 68 } 69 else 70 { 71 x++; 72 error += deltay; 73 if ( error >= deltax ) 74 { 75 y++; 76 error -= deltax; 77 } 78 } 79 i++; 80 } 81 } 82 } 83 84 static void FASTCALL 85 vgaSWtoNE( 86 IN CLIPOBJ* Clip, 87 IN BRUSHOBJ* Brush, 88 IN LONG x, 89 IN LONG y, 90 IN LONG deltax, 91 IN LONG deltay) 92 { 93 int i; 94 int error; 95 BOOLEAN EnumMore; 96 PRECTL ClipRect; 97 RECT_ENUM RectEnum; 98 ULONG Pixel = Brush->iSolidColor; 99 LONG delta; 100 101 CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, CD_RIGHTUP, 0); 102 EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum); 103 ClipRect = RectEnum.arcl; 104 delta = max(deltax, deltay); 105 i = 0; 106 error = delta / 2; 107 while (i < delta && (ClipRect < RectEnum.arcl + RectEnum.c || EnumMore)) 108 { 109 while ((ClipRect < RectEnum.arcl + RectEnum.c 110 && (y < ClipRect->top 111 || (y < ClipRect->bottom && ClipRect->right <= x))) 112 || EnumMore) 113 { 114 if (RectEnum.arcl + RectEnum.c <= ClipRect) 115 { 116 EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum); 117 ClipRect = RectEnum.arcl; 118 } 119 else 120 { 121 ClipRect++; 122 } 123 } 124 if (ClipRect < RectEnum.arcl + RectEnum.c) 125 { 126 if (ClipRect->left <= x && y < ClipRect->bottom) 127 vgaPutPixel(x, y, Pixel); 128 if (deltax < deltay) 129 { 130 y--; 131 error = error + deltax; 132 if (deltay <= error) 133 { 134 x++; 135 error = error - deltay; 136 } 137 } 138 else 139 { 140 x++; 141 error = error + deltay; 142 if (deltax <= error) 143 { 144 y--; 145 error = error - deltax; 146 } 147 } 148 i++; 149 } 150 } 151 } 152 153 static void FASTCALL 154 vgaNEtoSW( 155 IN CLIPOBJ* Clip, 156 IN BRUSHOBJ* Brush, 157 IN LONG x, 158 IN LONG y, 159 IN LONG deltax, 160 IN 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 vgaPutPixel(x, y, Pixel); 197 if (deltax < deltay) 198 { 199 y++; 200 error = error + deltax; 201 if (deltay <= error) 202 { 203 x--; 204 error = error - deltay; 205 } 206 } 207 else 208 { 209 x--; 210 error = error + deltay; 211 if (deltax <= error) 212 { 213 y++; 214 error = error - deltax; 215 } 216 } 217 i++; 218 } 219 } 220 } 221 222 static void FASTCALL 223 vgaSEtoNW( 224 IN CLIPOBJ* Clip, 225 IN BRUSHOBJ* Brush, 226 IN LONG x, 227 IN LONG y, 228 IN LONG deltax, 229 IN LONG deltay) 230 { 231 int i; 232 int error; 233 BOOLEAN EnumMore; 234 PRECTL ClipRect; 235 RECT_ENUM RectEnum; 236 ULONG Pixel = Brush->iSolidColor; 237 LONG delta; 238 239 CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, CD_LEFTUP, 0); 240 EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum); 241 ClipRect = RectEnum.arcl; 242 delta = max(deltax, deltay); 243 i = 0; 244 error = delta / 2; 245 while (i < delta && (ClipRect < RectEnum.arcl + RectEnum.c || EnumMore)) 246 { 247 while ((ClipRect < RectEnum.arcl + RectEnum.c 248 && (y < ClipRect->top 249 || (y < ClipRect->bottom && x < ClipRect->left))) 250 || EnumMore) 251 { 252 if (RectEnum.arcl + RectEnum.c <= ClipRect) 253 { 254 EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum); 255 ClipRect = RectEnum.arcl; 256 } 257 else 258 { 259 ClipRect++; 260 } 261 } 262 if (ClipRect < RectEnum.arcl + RectEnum.c) 263 { 264 if (x < ClipRect->right && y < ClipRect->bottom) 265 vgaPutPixel(x, y, Pixel); 266 if (deltax < deltay) 267 { 268 y--; 269 error = error + deltax; 270 if (deltay <= error) 271 { 272 x--; 273 error = error - deltay; 274 } 275 } 276 else 277 { 278 x--; 279 error = error + deltay; 280 if (deltax <= error) 281 { 282 y--; 283 error = error - deltax; 284 } 285 } 286 i++; 287 } 288 } 289 } 290 291 /* 292 * FIXME: Use Mix to perform ROPs 293 * FIXME: Non-solid Brush 294 */ 295 BOOL APIENTRY 296 DrvLineTo( 297 IN SURFOBJ *DestObj, 298 IN CLIPOBJ *Clip, 299 IN BRUSHOBJ *Brush, 300 IN LONG x1, 301 IN LONG y1, 302 IN LONG x2, 303 IN LONG y2, 304 IN RECTL *RectBounds, 305 IN MIX mix) 306 { 307 LONG x, y, deltax, deltay, xchange, ychange, hx, vy; 308 ULONG i; 309 ULONG Pixel = Brush->iSolidColor; 310 RECT_ENUM RectEnum; 311 BOOL EnumMore; 312 313 x = x1; 314 y = y1; 315 deltax = x2 - x1; 316 deltay = y2 - y1; 317 318 if (deltax < 0) 319 { 320 xchange = -1; 321 deltax = - deltax; 322 hx = x2+1; 323 //x--; 324 } 325 else 326 { 327 xchange = 1; 328 hx = x1; 329 } 330 331 if (deltay < 0) 332 { 333 ychange = -1; 334 deltay = - deltay; 335 vy = y2+1; 336 //y--; 337 } 338 else 339 { 340 ychange = 1; 341 vy = y1; 342 } 343 344 if (y1 == y2) 345 { 346 CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, CD_RIGHTDOWN, 0); 347 do 348 { 349 EnumMore = CLIPOBJ_bEnum(Clip, sizeof(RectEnum), (PVOID) &RectEnum); 350 for (i = 0; i < RectEnum.c && RectEnum.arcl[i].top <= y1; i++) 351 { 352 if (y1 < RectEnum.arcl[i].bottom && 353 RectEnum.arcl[i].left <= hx + deltax && 354 hx < RectEnum.arcl[i].right) 355 { 356 vgaHLine(max(hx, RectEnum.arcl[i].left), y1, 357 min(hx + deltax, RectEnum.arcl[i].right) 358 -max(hx, RectEnum.arcl[i].left), Pixel); 359 } 360 } 361 } while (EnumMore); 362 } 363 else if (x1 == x2) 364 { 365 CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, CD_RIGHTDOWN, 0); 366 do 367 { 368 EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum); 369 for (i = 0; i < RectEnum.c; i++) 370 { 371 if (RectEnum.arcl[i].left <= x1 && 372 x1 < RectEnum.arcl[i].right && 373 RectEnum.arcl[i].top <= vy + deltay && 374 vy < RectEnum.arcl[i].bottom) 375 { 376 vgaVLine(x1, 377 max(vy, RectEnum.arcl[i].top), 378 min(vy + deltay, RectEnum.arcl[i].bottom) 379 - max(vy, RectEnum.arcl[i].top), 380 Pixel); 381 } 382 } 383 } while (EnumMore); 384 } 385 else 386 { 387 if (0 < xchange) 388 { 389 if (0 < ychange) 390 vgaNWtoSE(Clip, Brush, x, y, deltax, deltay); 391 else 392 vgaSWtoNE(Clip, Brush, x, y, deltax, deltay); 393 } 394 else 395 { 396 if (0 < ychange) 397 vgaNEtoSW(Clip, Brush, x, y, deltax, deltay); 398 else 399 vgaSEtoNW(Clip, Brush, x, y, deltax, deltay); 400 } 401 } 402 403 return TRUE; 404 } 405 406 /* EOF */ 407