/* * PROJECT: ReactOS VGA display driver * LICENSE: GPL - See COPYING in the top level directory * FILE: drivers/video/displays/vga/objects/lineto.c * PURPOSE: * PROGRAMMERS: Copyright (C) 1998-2003 ReactOS Team */ #include /* * Draw a line from top-left to bottom-right */ static void FASTCALL vgaNWtoSE( IN CLIPOBJ* Clip, IN BRUSHOBJ* Brush, IN LONG x, IN LONG y, IN LONG deltax, IN LONG deltay) { int i; int error; BOOLEAN EnumMore; PRECTL ClipRect; RECT_ENUM RectEnum; ULONG Pixel = Brush->iSolidColor; LONG delta; CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, CD_RIGHTDOWN, 0); EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum); ClipRect = RectEnum.arcl; delta = max(deltax, deltay); i = 0; error = delta / 2; while (i < delta && (ClipRect < RectEnum.arcl + RectEnum.c || EnumMore)) { while ((ClipRect < RectEnum.arcl + RectEnum.c /* there's still a current clip rect */ && (ClipRect->bottom <= y /* but it's above us */ || (ClipRect->top <= y && ClipRect->right <= x))) /* or to the left of us */ || EnumMore) /* no current clip rect, but rects left */ { /* Skip to the next clip rect */ if (RectEnum.arcl + RectEnum.c <= ClipRect) { EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum); ClipRect = RectEnum.arcl; } else { ClipRect++; } } if ( ClipRect < RectEnum.arcl + RectEnum.c ) /* If there's no current clip rect we're done */ { if (ClipRect->left <= x && ClipRect->top <= y) vgaPutPixel ( x, y, Pixel ); if ( deltax < deltay ) { y++; error += deltax; if ( error >= deltay ) { x++; error -= deltay; } } else { x++; error += deltay; if ( error >= deltax ) { y++; error -= deltax; } } i++; } } } static void FASTCALL vgaSWtoNE( IN CLIPOBJ* Clip, IN BRUSHOBJ* Brush, IN LONG x, IN LONG y, IN LONG deltax, IN LONG deltay) { int i; int error; BOOLEAN EnumMore; PRECTL ClipRect; RECT_ENUM RectEnum; ULONG Pixel = Brush->iSolidColor; LONG delta; CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, CD_RIGHTUP, 0); EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum); ClipRect = RectEnum.arcl; delta = max(deltax, deltay); i = 0; error = delta / 2; while (i < delta && (ClipRect < RectEnum.arcl + RectEnum.c || EnumMore)) { while ((ClipRect < RectEnum.arcl + RectEnum.c && (y < ClipRect->top || (y < ClipRect->bottom && ClipRect->right <= x))) || EnumMore) { if (RectEnum.arcl + RectEnum.c <= ClipRect) { EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum); ClipRect = RectEnum.arcl; } else { ClipRect++; } } if (ClipRect < RectEnum.arcl + RectEnum.c) { if (ClipRect->left <= x && y < ClipRect->bottom) vgaPutPixel(x, y, Pixel); if (deltax < deltay) { y--; error = error + deltax; if (deltay <= error) { x++; error = error - deltay; } } else { x++; error = error + deltay; if (deltax <= error) { y--; error = error - deltax; } } i++; } } } static void FASTCALL vgaNEtoSW( IN CLIPOBJ* Clip, IN BRUSHOBJ* Brush, IN LONG x, IN LONG y, IN LONG deltax, IN LONG deltay) { int i; int error; BOOLEAN EnumMore; PRECTL ClipRect; RECT_ENUM RectEnum; ULONG Pixel = Brush->iSolidColor; LONG delta; CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, CD_LEFTDOWN, 0); EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum); ClipRect = RectEnum.arcl; delta = max(deltax, deltay); i = 0; error = delta / 2; while (i < delta && (ClipRect < RectEnum.arcl + RectEnum.c || EnumMore)) { while ((ClipRect < RectEnum.arcl + RectEnum.c && (ClipRect->bottom <= y || (ClipRect->top <= y && x < ClipRect->left))) || EnumMore) { if (RectEnum.arcl + RectEnum.c <= ClipRect) { EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum); ClipRect = RectEnum.arcl; } else { ClipRect++; } } if (ClipRect < RectEnum.arcl + RectEnum.c) { if (x < ClipRect->right && ClipRect->top <= y) vgaPutPixel(x, y, Pixel); if (deltax < deltay) { y++; error = error + deltax; if (deltay <= error) { x--; error = error - deltay; } } else { x--; error = error + deltay; if (deltax <= error) { y++; error = error - deltax; } } i++; } } } static void FASTCALL vgaSEtoNW( IN CLIPOBJ* Clip, IN BRUSHOBJ* Brush, IN LONG x, IN LONG y, IN LONG deltax, IN LONG deltay) { int i; int error; BOOLEAN EnumMore; PRECTL ClipRect; RECT_ENUM RectEnum; ULONG Pixel = Brush->iSolidColor; LONG delta; CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, CD_LEFTUP, 0); EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum); ClipRect = RectEnum.arcl; delta = max(deltax, deltay); i = 0; error = delta / 2; while (i < delta && (ClipRect < RectEnum.arcl + RectEnum.c || EnumMore)) { while ((ClipRect < RectEnum.arcl + RectEnum.c && (y < ClipRect->top || (y < ClipRect->bottom && x < ClipRect->left))) || EnumMore) { if (RectEnum.arcl + RectEnum.c <= ClipRect) { EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum); ClipRect = RectEnum.arcl; } else { ClipRect++; } } if (ClipRect < RectEnum.arcl + RectEnum.c) { if (x < ClipRect->right && y < ClipRect->bottom) vgaPutPixel(x, y, Pixel); if (deltax < deltay) { y--; error = error + deltax; if (deltay <= error) { x--; error = error - deltay; } } else { x--; error = error + deltay; if (deltax <= error) { y--; error = error - deltax; } } i++; } } } /* * FIXME: Use Mix to perform ROPs * FIXME: Non-solid Brush */ BOOL APIENTRY DrvLineTo( IN SURFOBJ *DestObj, IN CLIPOBJ *Clip, IN BRUSHOBJ *Brush, IN LONG x1, IN LONG y1, IN LONG x2, IN LONG y2, IN RECTL *RectBounds, IN MIX mix) { LONG x, y, deltax, deltay, xchange, ychange, hx, vy; ULONG i; ULONG Pixel = Brush->iSolidColor; RECT_ENUM RectEnum; BOOL EnumMore; x = x1; y = y1; deltax = x2 - x1; deltay = y2 - y1; if (deltax < 0) { xchange = -1; deltax = - deltax; hx = x2+1; //x--; } else { xchange = 1; hx = x1; } if (deltay < 0) { ychange = -1; deltay = - deltay; vy = y2+1; //y--; } else { ychange = 1; vy = y1; } if (y1 == y2) { CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, CD_RIGHTDOWN, 0); do { EnumMore = CLIPOBJ_bEnum(Clip, sizeof(RectEnum), (PVOID) &RectEnum); for (i = 0; i < RectEnum.c && RectEnum.arcl[i].top <= y1; i++) { if (y1 < RectEnum.arcl[i].bottom && RectEnum.arcl[i].left <= hx + deltax && hx < RectEnum.arcl[i].right) { vgaHLine(max(hx, RectEnum.arcl[i].left), y1, min(hx + deltax, RectEnum.arcl[i].right) -max(hx, RectEnum.arcl[i].left), Pixel); } } } while (EnumMore); } else if (x1 == x2) { CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, CD_RIGHTDOWN, 0); do { EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum); for (i = 0; i < RectEnum.c; i++) { if (RectEnum.arcl[i].left <= x1 && x1 < RectEnum.arcl[i].right && RectEnum.arcl[i].top <= vy + deltay && vy < RectEnum.arcl[i].bottom) { vgaVLine(x1, max(vy, RectEnum.arcl[i].top), min(vy + deltay, RectEnum.arcl[i].bottom) - max(vy, RectEnum.arcl[i].top), Pixel); } } } while (EnumMore); } else { if (0 < xchange) { if (0 < ychange) vgaNWtoSE(Clip, Brush, x, y, deltax, deltay); else vgaSWtoNE(Clip, Brush, x, y, deltax, deltay); } else { if (0 < ychange) vgaNEtoSW(Clip, Brush, x, y, deltax, deltay); else vgaSEtoNW(Clip, Brush, x, y, deltax, deltay); } } return TRUE; } /* EOF */