Revert tree-restructure attempt: r66583, r66582, r66581, r66578, sauf ntdll changes...
[reactos.git] / reactos / win32ss / drivers / displays / vga / objects / lineto.c
diff --git a/reactos/win32ss/drivers/displays/vga/objects/lineto.c b/reactos/win32ss/drivers/displays/vga/objects/lineto.c
new file mode 100644 (file)
index 0000000..afffdfc
--- /dev/null
@@ -0,0 +1,406 @@
+/*
+ * 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 <vgaddi.h>
+
+/*
+ * 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 */