From 7e11593f8c75f69205c24311c301e4937c0609a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9=20van=20Geldorp?= Date: Mon, 14 Jul 2003 09:43:11 +0000 Subject: [PATCH] Implement clipping of lines svn path=/trunk/; revision=5111 --- .../drivers/dd/vga/display/objects/lineto.c | 435 +++++++++++++--- reactos/subsys/win32k/eng/lineto.c | 491 +++++++++++++++--- reactos/subsys/win32k/include/paint.h | 2 +- reactos/subsys/win32k/objects/fillshap.c | 17 +- reactos/subsys/win32k/objects/line.c | 110 ++-- reactos/subsys/win32k/objects/polyfill.c | 27 +- 6 files changed, 873 insertions(+), 209 deletions(-) diff --git a/reactos/drivers/dd/vga/display/objects/lineto.c b/reactos/drivers/dd/vga/display/objects/lineto.c index 6fceab6f661..dc2b24be2fa 100644 --- a/reactos/drivers/dd/vga/display/objects/lineto.c +++ b/reactos/drivers/dd/vga/display/objects/lineto.c @@ -1,9 +1,297 @@ +/* + * ReactOS VGA driver + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * $Id: lineto.c,v 1.12 2003/07/14 09:43:11 gvg Exp $ + */ + #include "../vgaddi.h" #include "../vgavideo/vgavideo.h" +/* + * Draw a line from top-left to bottom-right + */ +static void FASTCALL +vgaNWtoSE(PCLIPOBJ Clip, PBRUSHOBJ Brush, LONG x, LONG y, LONG deltax, 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, ENUM_RECT_LIMIT); + EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum); + ClipRect = RectEnum.arcl; + delta = max(deltax, deltay); + i = 0; + error = 0; + 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 = 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 +vgaSWtoNE(PCLIPOBJ Clip, PBRUSHOBJ Brush, LONG x, LONG y, LONG deltax, 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, ENUM_RECT_LIMIT); + EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum); + ClipRect = RectEnum.arcl; + delta = max(deltax, deltay); + i = 0; + error = 0; + 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(PCLIPOBJ Clip, PBRUSHOBJ Brush, LONG x, LONG y, LONG deltax, 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, ENUM_RECT_LIMIT); + EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum); + ClipRect = RectEnum.arcl; + delta = max(deltax, deltay); + i = 0; + error = 0; + 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(PCLIPOBJ Clip, PBRUSHOBJ Brush, LONG x, LONG y, LONG deltax, 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, ENUM_RECT_LIMIT); + EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum); + ClipRect = RectEnum.arcl; + delta = max(deltax, deltay); + i = 0; + error = 0; + 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 STDCALL -DrvLineTo(SURFOBJ *Surface, +DrvLineTo(SURFOBJ *DestObj, CLIPOBJ *Clip, BRUSHOBJ *Brush, LONG x1, @@ -12,16 +300,12 @@ DrvLineTo(SURFOBJ *Surface, LONG y2, RECTL *RectBounds, MIX mix) - -// FIXME: Use ClipObj and RectBounds to clip the line where required -// FIXME: Use Mix to perform ROPs - { - LONG deltax, deltay, x, y, d, i, xchange, ychange, error, iSolidColor, hx, vy; - - iSolidColor = Brush->iSolidColor; // FIXME: Brush Realization... - - // FIXME: Implement clipping + LONG x, y, deltax, deltay, i, xchange, ychange, hx, vy; + ULONG Pixel = Brush->iSolidColor; + RECTL DestRect; + RECT_ENUM RectEnum; + BOOL EnumMore; x = x1; y = y1; @@ -30,73 +314,100 @@ DrvLineTo(SURFOBJ *Surface, if (deltax < 0) { - xchange = -1; - deltax = - deltax; - hx = x2; - x--; + xchange = -1; + deltax = - deltax; + hx = x2; + x--; } else { - xchange = 1; - hx = x1; + xchange = 1; + hx = x1; } if (deltay < 0) { - ychange = -1; - deltay = - deltay; - vy = y2; - y--; + ychange = -1; + deltay = - deltay; + vy = y2; + y--; } else { - ychange = 1; - vy = y1; - }; + ychange = 1; + vy = y1; + } if (y1 == y2) { - return vgaHLine(hx, y1, deltax, iSolidColor); + CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, CD_RIGHTDOWN, ENUM_RECT_LIMIT); + do + { + EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) 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); } - if (x1 == x2) + else if (x1 == x2) { - return vgaVLine(x1, vy, deltay, iSolidColor); + CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, CD_RIGHTDOWN, ENUM_RECT_LIMIT); + 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); + } + } } - // Using individual pixels to draw a line neither horizontal or vertical - // Set up the VGA masking for individual pixels - - error = 0; - - if (deltax < deltay) - { - for (i = 0; i < deltay; i++) - { - vgaPutPixel(x, y, iSolidColor); - y = y + ychange; - error = error + deltax; - - if (deltay <= error) - { - x = x + xchange; - error = error - deltay; - } - } - } - else - { - for (i = 0; i < deltax; i++) - { - vgaPutPixel(x, y, iSolidColor); - x = x + xchange; - error = error + deltay; - if (deltax <= error) - { - y = y + ychange; - error = error - deltax; - } - } - } - - return TRUE; + return TRUE; } + +/* EOF */ diff --git a/reactos/subsys/win32k/eng/lineto.c b/reactos/subsys/win32k/eng/lineto.c index fe0780a5d4f..3eb284e561a 100644 --- a/reactos/subsys/win32k/eng/lineto.c +++ b/reactos/subsys/win32k/eng/lineto.c @@ -15,12 +15,15 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * $Id: lineto.c,v 1.20 2003/07/14 09:43:11 gvg Exp $ */ -/* $Id: lineto.c,v 1.19 2003/07/11 15:59:37 royce Exp $ */ + #include #include #include #include +#include "clip.h" #include "objects.h" #include "../dib/dib.h" #include "misc.h" @@ -29,6 +32,303 @@ #include #include +static void FASTCALL +TranslateRects(RECT_ENUM *RectEnum, PPOINTL Translate) +{ + PRECTL CurrentRect; + + if (0 != Translate->x || 0 != Translate->y) + { + for (CurrentRect = RectEnum->arcl; CurrentRect < RectEnum->arcl + RectEnum->c; CurrentRect++) + { + CurrentRect->left += Translate->x; + CurrentRect->right += Translate->x; + CurrentRect->top += Translate->y; + CurrentRect->bottom += Translate->y; + } + } +} + +/* + * Draw a line from top-left to bottom-right + */ +static void FASTCALL +NWtoSE(PSURFOBJ OutputObj, PSURFGDI OutputGDI, PCLIPOBJ Clip, + PBRUSHOBJ Brush, LONG x, LONG y, LONG deltax, LONG deltay, + PPOINTL Translate) +{ + 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, ENUM_RECT_LIMIT); + EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum); + TranslateRects(&RectEnum, Translate); + ClipRect = RectEnum.arcl; + delta = max(deltax, deltay); + i = 0; + error = 0; + 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); + TranslateRects(&RectEnum, Translate); + 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) + { + OutputGDI->DIB_PutPixel(OutputObj, 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 +SWtoNE(PSURFOBJ OutputObj, PSURFGDI OutputGDI, PCLIPOBJ Clip, + PBRUSHOBJ Brush, LONG x, LONG y, LONG deltax, LONG deltay, + PPOINTL Translate) +{ + 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, ENUM_RECT_LIMIT); + EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum); + TranslateRects(&RectEnum, Translate); + ClipRect = RectEnum.arcl; + delta = max(deltax, deltay); + i = 0; + error = 0; + 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); + TranslateRects(&RectEnum, Translate); + ClipRect = RectEnum.arcl; + } + else + { + ClipRect++; + } + } + if (ClipRect < RectEnum.arcl + RectEnum.c) + { + if (ClipRect->left <= x && y < ClipRect->bottom) + { + OutputGDI->DIB_PutPixel(OutputObj, 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 +NEtoSW(PSURFOBJ OutputObj, PSURFGDI OutputGDI, PCLIPOBJ Clip, + PBRUSHOBJ Brush, LONG x, LONG y, LONG deltax, LONG deltay, + PPOINTL Translate) +{ + 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, ENUM_RECT_LIMIT); + EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum); + TranslateRects(&RectEnum, Translate); + ClipRect = RectEnum.arcl; + delta = max(deltax, deltay); + i = 0; + error = 0; + 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); + TranslateRects(&RectEnum, Translate); + ClipRect = RectEnum.arcl; + } + else + { + ClipRect++; + } + } + if (ClipRect < RectEnum.arcl + RectEnum.c) + { + if (x < ClipRect->right && ClipRect->top <= y) + { + OutputGDI->DIB_PutPixel(OutputObj, 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 +SEtoNW(PSURFOBJ OutputObj, PSURFGDI OutputGDI, PCLIPOBJ Clip, + PBRUSHOBJ Brush, LONG x, LONG y, LONG deltax, LONG deltay, + PPOINTL Translate) +{ + 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, ENUM_RECT_LIMIT); + EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum); + TranslateRects(&RectEnum, Translate); + ClipRect = RectEnum.arcl; + delta = max(deltax, deltay); + i = 0; + error = 0; + 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); + TranslateRects(&RectEnum, Translate); + ClipRect = RectEnum.arcl; + } + else + { + ClipRect++; + } + } + if (ClipRect < RectEnum.arcl + RectEnum.c) + { + if (x < ClipRect->right && y < ClipRect->bottom) + { + OutputGDI->DIB_PutPixel(OutputObj, 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++; + } + } +} + /* * @unimplemented */ @@ -43,36 +343,38 @@ EngLineTo(SURFOBJ *DestObj, RECTL *RectBounds, MIX mix) { - LONG x, y, deltax, deltay, i, xchange, ychange, error, hx, vy; + LONG x, y, deltax, deltay, i, xchange, ychange, hx, vy; ULONG Pixel = Brush->iSolidColor; SURFOBJ *OutputObj; SURFGDI *OutputGDI; RECTL DestRect; POINTL Translate; INTENG_ENTER_LEAVE EnterLeave; + RECT_ENUM RectEnum; + BOOL EnumMore; DestRect.left = x1; if (x1 != x2) { - DestRect.right = x2; + DestRect.right = x2; } else { - DestRect.right = x2 + 1; + DestRect.right = x2 + 1; } DestRect.top = y1; if (y1 != y2) { - DestRect.bottom = y2; + DestRect.bottom = y2; } else { - DestRect.bottom = y2 + 1; + DestRect.bottom = y2 + 1; } if (! IntEngEnter(&EnterLeave, DestObj, &DestRect, FALSE, &Translate, &OutputObj)) { - return FALSE; + return FALSE; } x1 += Translate.x; @@ -82,7 +384,6 @@ EngLineTo(SURFOBJ *DestObj, OutputGDI = AccessInternalObjectFromUserObject(OutputObj); - // FIXME: Implement clipping x = x1; y = y1; deltax = x2 - x1; @@ -90,71 +391,97 @@ EngLineTo(SURFOBJ *DestObj, if (deltax < 0) { - xchange = -1; - deltax = - deltax; - hx = x2; - x--; + xchange = -1; + deltax = - deltax; + hx = x2; + x--; } else { - xchange = 1; - hx = x1; + xchange = 1; + hx = x1; } if (deltay < 0) { - ychange = -1; - deltay = - deltay; - vy = y2; - y--; + ychange = -1; + deltay = - deltay; + vy = y2; + y--; } else { - ychange = 1; - vy = y1; + ychange = 1; + vy = y1; } if (y1 == y2) { - OutputGDI->DIB_HLine(OutputObj, hx, hx + deltax, y1, Pixel); + CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, CD_RIGHTDOWN, ENUM_RECT_LIMIT); + do + { + EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum); + for (i = 0; i < RectEnum.c && RectEnum.arcl[i].top + Translate.y <= y1; i++) + { + if (y1 < RectEnum.arcl[i].bottom + Translate.y && + RectEnum.arcl[i].left + Translate.x <= hx + deltax && + hx < RectEnum.arcl[i].right + Translate.x) + { + OutputGDI->DIB_HLine(OutputObj, + max(hx, RectEnum.arcl[i].left + Translate.x), + min(hx + deltax, RectEnum.arcl[i].right + Translate.x), + y1, Pixel); + } + } + } + while (EnumMore); } else if (x1 == x2) { - OutputGDI->DIB_VLine(OutputObj, x1, vy, vy + deltay, Pixel); + CLIPOBJ_cEnumStart(Clip, FALSE, CT_RECTANGLES, CD_RIGHTDOWN, ENUM_RECT_LIMIT); + do + { + EnumMore = CLIPOBJ_bEnum(Clip, (ULONG) sizeof(RectEnum), (PVOID) &RectEnum); + for (i = 0; i < RectEnum.c; i++) + { + if (RectEnum.arcl[i].left + Translate.x <= x1 && + x1 < RectEnum.arcl[i].right + Translate.x && + RectEnum.arcl[i].top + Translate.y <= vy + deltay && + vy < RectEnum.arcl[i].bottom + Translate.y) + { + OutputGDI->DIB_VLine(OutputObj, x1, + max(vy, RectEnum.arcl[i].top + Translate.y), + min(vy + deltay, RectEnum.arcl[i].bottom + Translate.y), + Pixel); + } + } + } + while (EnumMore); } else { - error = 0; - - if (deltax < deltay) - { - for (i = 0; i < deltay; i++) - { - OutputGDI->DIB_PutPixel(OutputObj, x, y, Pixel); - y = y + ychange; - error = error + deltax; - - if (deltay <= error) - { - x = x + xchange; - error = error - deltay; - } - } - } - else - { - for (i = 0; i < deltax; i++) - { - OutputGDI->DIB_PutPixel(OutputObj, x, y, Pixel); - x = x + xchange; - error = error + deltay; - if (deltax <= error) - { - y = y + ychange; - error = error - deltax; - } - } - } + if (0 < xchange) + { + if (0 < ychange) + { + NWtoSE(OutputObj, OutputGDI, Clip, Brush, x, y, deltax, deltay, &Translate); + } + else + { + SWtoNE(OutputObj, OutputGDI, Clip, Brush, x, y, deltax, deltay, &Translate); + } + } + else + { + if (0 < ychange) + { + NEtoSW(OutputObj, OutputGDI, Clip, Brush, x, y, deltax, deltay, &Translate); + } + else + { + SEtoNW(OutputObj, OutputGDI, Clip, Brush, x, y, deltax, deltay, &Translate); + } + } } return IntEngLeave(&EnterLeave); @@ -180,20 +507,23 @@ IntEngLineTo(SURFOBJ *DestSurf, MouseSafetyOnDrawStart(DestSurf, SurfGDI, x1, y1, x2, y2); - if (NULL != SurfGDI->LineTo) { + if (NULL != SurfGDI->LineTo) + { /* Call the driver's DrvLineTo */ ret = SurfGDI->LineTo(DestSurf, Clip, Brush, x1, y1, x2, y2, RectBounds, mix); - } + } #if 0 - if (! ret && NULL != SurfGDI->StrokePath) { - /* FIXME: Emulate LineTo using drivers DrvStrokePath and set ret on success */ - } + if (! ret && NULL != SurfGDI->StrokePath) + { + /* FIXME: Emulate LineTo using drivers DrvStrokePath and set ret on success */ + } #endif - if (! ret) { - ret = EngLineTo(DestSurf, Clip, Brush, x1, y1, x2, y2, RectBounds, mix); - } + if (! ret) + { + ret = EngLineTo(DestSurf, Clip, Brush, x1, y1, x2, y2, RectBounds, mix); + } MouseSafetyOnDrawEnd(DestSurf, SurfGDI); @@ -213,25 +543,28 @@ IntEngPolyline(SURFOBJ *DestSurf, BOOL ret = FALSE; //Draw the Polyline with a call to IntEngLineTo for each segment. - for (i=1; i @@ -82,7 +82,8 @@ W32kPie(HDC hDC, //When the fill mode is ALTERNATE, GDI fills the area between odd-numbered and //even-numbered polygon sides on each scan line. That is, GDI fills the area between the //first and second side, between the third and fourth side, and so on. -extern BOOL FillPolygon_ALTERNATE(SURFOBJ *SurfObj, +extern BOOL FillPolygon_ALTERNATE(PDC dc, + SURFOBJ *SurfObj, PBRUSHOBJ BrushObj, MIX RopMode, CONST PPOINT Points, @@ -186,7 +187,7 @@ W32kPolygon(HDC hDC, } else /* default */ { - ret = FillPolygon_ALTERNATE(SurfObj, FillBrushObj, dc->w.ROPmode, Points, Count, DestRect); + ret = FillPolygon_ALTERNATE(dc, SurfObj, FillBrushObj, dc->w.ROPmode, Points, Count, DestRect); } // Draw the Polygon Edges with the current pen @@ -243,7 +244,7 @@ W32kPolygon(HDC hDC, } DPRINT("Polygon Making line from (%d,%d) to (%d,%d)\n", From.x, From.y, To.x, To.y ); ret = IntEngLineTo(SurfObj, - NULL, /* ClipObj */ + dc->CombinedClip, OutBrushObj, From.x, From.y, @@ -311,28 +312,28 @@ W32kRectangle(HDC hDC, BottomRect += dc->w.DCOrgY; ret = IntEngLineTo(SurfObj, - NULL, // ClipObj, + dc->CombinedClip, BrushObj, LeftRect, TopRect, RightRect, TopRect, RectBounds, // Bounding rectangle dc->w.ROPmode); // MIX ret = IntEngLineTo(SurfObj, - NULL, // ClipObj, + dc->CombinedClip, BrushObj, RightRect, TopRect, RightRect, BottomRect, RectBounds, // Bounding rectangle dc->w.ROPmode); // MIX ret = IntEngLineTo(SurfObj, - NULL, // ClipObj, + dc->CombinedClip, BrushObj, LeftRect, BottomRect, RightRect, BottomRect, RectBounds, // Bounding rectangle dc->w.ROPmode); // MIX ret = IntEngLineTo(SurfObj, - NULL, // ClipObj, + dc->CombinedClip, BrushObj, LeftRect, TopRect, LeftRect, BottomRect, RectBounds, // Bounding rectangle diff --git a/reactos/subsys/win32k/objects/line.c b/reactos/subsys/win32k/objects/line.c index a501261aacc..3cc4f834b18 100644 --- a/reactos/subsys/win32k/objects/line.c +++ b/reactos/subsys/win32k/objects/line.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: line.c,v 1.16 2003/05/18 17:16:18 ea Exp $ */ +/* $Id: line.c,v 1.17 2003/07/14 09:43:11 gvg Exp $ */ // Some code from the WINE project source (www.winehq.com) @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -128,57 +129,74 @@ W32kGetArcDirection(HDC hDC) BOOL STDCALL W32kLineTo(HDC hDC, - int XEnd, - int YEnd) + int XEnd, + int YEnd) { - DC *dc = DC_HandleToPtr(hDC); - SURFOBJ *SurfObj = (SURFOBJ*)AccessUserObject(dc->Surface); - BOOL ret; - PPENOBJ pen; - PROSRGNDATA reg; -#ifndef TODO - RECT defaultrect; -#endif + DC *dc = DC_HandleToPtr(hDC); + SURFOBJ *SurfObj = (SURFOBJ*)AccessUserObject(dc->Surface); + BOOL Ret; + PPENOBJ Pen; + RECT Bounds; - if(!dc) return FALSE; + if (NULL == dc) + { + SetLastWin32Error(ERROR_INVALID_HANDLE); + return FALSE; + } - if(PATH_IsPathOpen(dc->w.path)) { - ret = PATH_LineTo(hDC, XEnd, YEnd); - } else { - pen = (PPENOBJ) GDIOBJ_LockObj(dc->w.hPen, GO_PEN_MAGIC); - reg = (PROSRGNDATA)GDIOBJ_LockObj(dc->w.hGCClipRgn, GO_REGION_MAGIC); + if (PATH_IsPathOpen(dc->w.path)) + { + Ret = PATH_LineTo(hDC, XEnd, YEnd); + } + else + { + Pen = (PPENOBJ) GDIOBJ_LockObj(dc->w.hPen, GO_PEN_MAGIC); + ASSERT(NULL != Pen); - ASSERT( pen ); - // not yet implemented ASSERT( reg ); -#ifndef TODO - if (NULL == reg) { - defaultrect.left = 0; - defaultrect.top = 0; - defaultrect.right = 640; - defaultrect.bottom = 480; + if (dc->w.CursPosX <= XEnd) + { + Bounds.left = dc->w.CursPosX; + Bounds.right = XEnd; + } + else + { + Bounds.left = XEnd; + Bounds.right = dc->w.CursPosX; + } + Bounds.left += dc->w.DCOrgX; + Bounds.right += dc->w.DCOrgX; + if (dc->w.CursPosY <= YEnd) + { + Bounds.top = dc->w.CursPosY; + Bounds.bottom = YEnd; + } + else + { + Bounds.top = YEnd; + Bounds.bottom = dc->w.CursPosY; + } + Bounds.top += dc->w.DCOrgY; + Bounds.bottom += dc->w.DCOrgY; - reg = &defaultrect; - } -#endif + Ret = IntEngLineTo(SurfObj, + dc->CombinedClip, + PenToBrushObj(dc, Pen), + dc->w.DCOrgX + dc->w.CursPosX, dc->w.DCOrgY + dc->w.CursPosY, + dc->w.DCOrgX + XEnd, dc->w.DCOrgY + YEnd, + &Bounds, + dc->w.ROPmode); - /* Draw the line according to the DC origin */ - ret = IntEngLineTo(SurfObj, - NULL, // ClipObj - PenToBrushObj(dc, pen), - dc->w.DCOrgX + dc->w.CursPosX, dc->w.DCOrgY + dc->w.CursPosY, - dc->w.DCOrgX + XEnd, dc->w.DCOrgY + YEnd, - reg, // Bounding rectangle - dc->w.ROPmode); // MIX + GDIOBJ_UnlockObj( dc->w.hPen, GO_PEN_MAGIC); + } - GDIOBJ_UnlockObj( dc->w.hGCClipRgn, GO_REGION_MAGIC ); - GDIOBJ_UnlockObj( dc->w.hPen, GO_PEN_MAGIC); - } - if(ret) { - dc->w.CursPosX = XEnd; - dc->w.CursPosY = YEnd; - } - DC_ReleasePtr( hDC ); - return ret; + if (Ret) + { + dc->w.CursPosX = XEnd; + dc->w.CursPosY = YEnd; + } + DC_ReleasePtr(hDC); + + return Ret; } BOOL @@ -336,7 +354,7 @@ W32kPolyline(HDC hDC, //get IntEngPolyline to do the drawing. ret = IntEngPolyline(SurfObj, - NULL, + dc->CombinedClip, PenToBrushObj(dc, pen), pts, Count, diff --git a/reactos/subsys/win32k/objects/polyfill.c b/reactos/subsys/win32k/objects/polyfill.c index 4fbece0e1b1..1ef590e32f4 100644 --- a/reactos/subsys/win32k/objects/polyfill.c +++ b/reactos/subsys/win32k/objects/polyfill.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: polyfill.c,v 1.4 2003/06/25 16:55:33 gvg Exp $ +/* $Id: polyfill.c,v 1.5 2003/07/14 09:43:11 gvg Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -487,7 +488,7 @@ static void STDCALL POLYGONFILL_UpdateActiveEdges(int Scanline, PFILL_EDGE_LIST ** This method fills the portion of the polygon that intersects with the scanline ** Scanline. */ -static void STDCALL POLYGONFILL_FillScanLine(int ScanLine, PFILL_EDGE_LIST ActiveEdges, SURFOBJ *SurfObj, PBRUSHOBJ BrushObj, MIX RopMode) +static void STDCALL POLYGONFILL_FillScanLine(PDC dc, int ScanLine, PFILL_EDGE_LIST ActiveEdges, SURFOBJ *SurfObj, PBRUSHOBJ BrushObj, MIX RopMode) { BOOL OnOdd = TRUE; RECTL BoundRect; @@ -510,15 +511,15 @@ static void STDCALL POLYGONFILL_FillScanLine(int ScanLine, PFILL_EDGE_LIST Activ XInterceptEven = pThis->XIntercept; DPRINT("Fill Line (%d, %d) to (%d, %d)\n",XInterceptOdd - 1, ScanLine, XInterceptEven - 1, ScanLine); - ret = EngLineTo(SurfObj, - NULL, /* ClipObj */ - BrushObj, - XInterceptOdd - 1, - ScanLine, - XInterceptEven - 1, - ScanLine, - &BoundRect, /* Bounding rectangle */ - RopMode); /* MIX */ + ret = IntEngLineTo(SurfObj, + dc->CombinedClip, + BrushObj, + XInterceptOdd - 1, + ScanLine, + XInterceptEven - 1, + ScanLine, + &BoundRect, /* Bounding rectangle */ + RopMode); /* MIX */ OnOdd = TRUE; } pThis = pThis->pNext; @@ -530,7 +531,7 @@ static void STDCALL POLYGONFILL_FillScanLine(int ScanLine, PFILL_EDGE_LIST Activ //When the fill mode is ALTERNATE, GDI fills the area between odd-numbered and //even-numbered polygon sides on each scan line. That is, GDI fills the area between the //first and second side, between the third and fourth side, and so on. -BOOL STDCALL FillPolygon_ALTERNATE(SURFOBJ *SurfObj, PBRUSHOBJ BrushObj, MIX RopMode, CONST PPOINT Points, int Count, RECTL BoundRect) +BOOL STDCALL FillPolygon_ALTERNATE(PDC dc, SURFOBJ *SurfObj, PBRUSHOBJ BrushObj, MIX RopMode, CONST PPOINT Points, int Count, RECTL BoundRect) { PFILL_EDGE_LIST list = 0; PFILL_EDGE_LIST ActiveEdges = 0; @@ -553,7 +554,7 @@ BOOL STDCALL FillPolygon_ALTERNATE(SURFOBJ *SurfObj, PBRUSHOBJ BrushObj, MIX Rop { POLYGONFILL_UpdateActiveEdges(ScanLine, &list, &ActiveEdges); /* DEBUG_PRINT_EDGELIST(ActiveEdges); */ - POLYGONFILL_FillScanLine(ScanLine, ActiveEdges, SurfObj, BrushObj, RopMode); + POLYGONFILL_FillScanLine(dc, ScanLine, ActiveEdges, SurfObj, BrushObj, RopMode); } /* Free Edge List. If any are left. */