Implement clipping of lines

svn path=/trunk/; revision=5111
This commit is contained in:
Gé van Geldorp 2003-07-14 09:43:11 +00:00
parent 98d338a1c4
commit 7e11593f8c
6 changed files with 873 additions and 209 deletions

View file

@ -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 "../vgaddi.h"
#include "../vgavideo/vgavideo.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 BOOL STDCALL
DrvLineTo(SURFOBJ *Surface, DrvLineTo(SURFOBJ *DestObj,
CLIPOBJ *Clip, CLIPOBJ *Clip,
BRUSHOBJ *Brush, BRUSHOBJ *Brush,
LONG x1, LONG x1,
@ -12,16 +300,12 @@ DrvLineTo(SURFOBJ *Surface,
LONG y2, LONG y2,
RECTL *RectBounds, RECTL *RectBounds,
MIX mix) 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; LONG x, y, deltax, deltay, i, xchange, ychange, hx, vy;
ULONG Pixel = Brush->iSolidColor;
iSolidColor = Brush->iSolidColor; // FIXME: Brush Realization... RECTL DestRect;
RECT_ENUM RectEnum;
// FIXME: Implement clipping BOOL EnumMore;
x = x1; x = x1;
y = y1; y = y1;
@ -30,73 +314,100 @@ DrvLineTo(SURFOBJ *Surface,
if (deltax < 0) if (deltax < 0)
{ {
xchange = -1; xchange = -1;
deltax = - deltax; deltax = - deltax;
hx = x2; hx = x2;
x--; x--;
} }
else else
{ {
xchange = 1; xchange = 1;
hx = x1; hx = x1;
} }
if (deltay < 0) if (deltay < 0)
{ {
ychange = -1; ychange = -1;
deltay = - deltay; deltay = - deltay;
vy = y2; vy = y2;
y--; y--;
} }
else else
{ {
ychange = 1; ychange = 1;
vy = y1; vy = y1;
}; }
if (y1 == y2) 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 return TRUE;
// 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;
} }
/* EOF */

View file

@ -15,12 +15,15 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 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 <ddk/winddi.h> #include <ddk/winddi.h>
#include <ddk/ntddmou.h> #include <ddk/ntddmou.h>
#include <include/inteng.h> #include <include/inteng.h>
#include <include/dib.h> #include <include/dib.h>
#include "clip.h"
#include "objects.h" #include "objects.h"
#include "../dib/dib.h" #include "../dib/dib.h"
#include "misc.h" #include "misc.h"
@ -29,6 +32,303 @@
#include <include/object.h> #include <include/object.h>
#include <include/surface.h> #include <include/surface.h>
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 * @unimplemented
*/ */
@ -43,36 +343,38 @@ EngLineTo(SURFOBJ *DestObj,
RECTL *RectBounds, RECTL *RectBounds,
MIX mix) 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; ULONG Pixel = Brush->iSolidColor;
SURFOBJ *OutputObj; SURFOBJ *OutputObj;
SURFGDI *OutputGDI; SURFGDI *OutputGDI;
RECTL DestRect; RECTL DestRect;
POINTL Translate; POINTL Translate;
INTENG_ENTER_LEAVE EnterLeave; INTENG_ENTER_LEAVE EnterLeave;
RECT_ENUM RectEnum;
BOOL EnumMore;
DestRect.left = x1; DestRect.left = x1;
if (x1 != x2) if (x1 != x2)
{ {
DestRect.right = x2; DestRect.right = x2;
} }
else else
{ {
DestRect.right = x2 + 1; DestRect.right = x2 + 1;
} }
DestRect.top = y1; DestRect.top = y1;
if (y1 != y2) if (y1 != y2)
{ {
DestRect.bottom = y2; DestRect.bottom = y2;
} }
else else
{ {
DestRect.bottom = y2 + 1; DestRect.bottom = y2 + 1;
} }
if (! IntEngEnter(&EnterLeave, DestObj, &DestRect, FALSE, &Translate, &OutputObj)) if (! IntEngEnter(&EnterLeave, DestObj, &DestRect, FALSE, &Translate, &OutputObj))
{ {
return FALSE; return FALSE;
} }
x1 += Translate.x; x1 += Translate.x;
@ -82,7 +384,6 @@ EngLineTo(SURFOBJ *DestObj,
OutputGDI = AccessInternalObjectFromUserObject(OutputObj); OutputGDI = AccessInternalObjectFromUserObject(OutputObj);
// FIXME: Implement clipping
x = x1; x = x1;
y = y1; y = y1;
deltax = x2 - x1; deltax = x2 - x1;
@ -90,71 +391,97 @@ EngLineTo(SURFOBJ *DestObj,
if (deltax < 0) if (deltax < 0)
{ {
xchange = -1; xchange = -1;
deltax = - deltax; deltax = - deltax;
hx = x2; hx = x2;
x--; x--;
} }
else else
{ {
xchange = 1; xchange = 1;
hx = x1; hx = x1;
} }
if (deltay < 0) if (deltay < 0)
{ {
ychange = -1; ychange = -1;
deltay = - deltay; deltay = - deltay;
vy = y2; vy = y2;
y--; y--;
} }
else else
{ {
ychange = 1; ychange = 1;
vy = y1; vy = y1;
} }
if (y1 == y2) 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) 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 else
{ {
error = 0; if (0 < xchange)
{
if (deltax < deltay) if (0 < ychange)
{ {
for (i = 0; i < deltay; i++) NWtoSE(OutputObj, OutputGDI, Clip, Brush, x, y, deltax, deltay, &Translate);
{ }
OutputGDI->DIB_PutPixel(OutputObj, x, y, Pixel); else
y = y + ychange; {
error = error + deltax; SWtoNE(OutputObj, OutputGDI, Clip, Brush, x, y, deltax, deltay, &Translate);
}
if (deltay <= error) }
{ else
x = x + xchange; {
error = error - deltay; if (0 < ychange)
} {
} NEtoSW(OutputObj, OutputGDI, Clip, Brush, x, y, deltax, deltay, &Translate);
} }
else else
{ {
for (i = 0; i < deltax; i++) SEtoNW(OutputObj, OutputGDI, Clip, Brush, x, y, deltax, deltay, &Translate);
{ }
OutputGDI->DIB_PutPixel(OutputObj, x, y, Pixel); }
x = x + xchange;
error = error + deltay;
if (deltax <= error)
{
y = y + ychange;
error = error - deltax;
}
}
}
} }
return IntEngLeave(&EnterLeave); return IntEngLeave(&EnterLeave);
@ -180,20 +507,23 @@ IntEngLineTo(SURFOBJ *DestSurf,
MouseSafetyOnDrawStart(DestSurf, SurfGDI, x1, y1, x2, y2); MouseSafetyOnDrawStart(DestSurf, SurfGDI, x1, y1, x2, y2);
if (NULL != SurfGDI->LineTo) { if (NULL != SurfGDI->LineTo)
{
/* Call the driver's DrvLineTo */ /* Call the driver's DrvLineTo */
ret = SurfGDI->LineTo(DestSurf, Clip, Brush, x1, y1, x2, y2, RectBounds, mix); ret = SurfGDI->LineTo(DestSurf, Clip, Brush, x1, y1, x2, y2, RectBounds, mix);
} }
#if 0 #if 0
if (! ret && NULL != SurfGDI->StrokePath) { if (! ret && NULL != SurfGDI->StrokePath)
/* FIXME: Emulate LineTo using drivers DrvStrokePath and set ret on success */ {
} /* FIXME: Emulate LineTo using drivers DrvStrokePath and set ret on success */
}
#endif #endif
if (! ret) { if (! ret)
ret = EngLineTo(DestSurf, Clip, Brush, x1, y1, x2, y2, RectBounds, mix); {
} ret = EngLineTo(DestSurf, Clip, Brush, x1, y1, x2, y2, RectBounds, mix);
}
MouseSafetyOnDrawEnd(DestSurf, SurfGDI); MouseSafetyOnDrawEnd(DestSurf, SurfGDI);
@ -213,25 +543,28 @@ IntEngPolyline(SURFOBJ *DestSurf,
BOOL ret = FALSE; BOOL ret = FALSE;
//Draw the Polyline with a call to IntEngLineTo for each segment. //Draw the Polyline with a call to IntEngLineTo for each segment.
for (i=1; i<dCount; i++) for (i = 1; i < dCount; i++)
{ {
rect.left = MIN(pt[i-1].x, pt[i].x); rect.left = MIN(pt[i-1].x, pt[i].x);
rect.top = MIN(pt[i-1].y, pt[i].y); rect.top = MIN(pt[i-1].y, pt[i].y);
rect.right = MAX(pt[i-1].x, pt[i].x); rect.right = MAX(pt[i-1].x, pt[i].x);
rect.bottom = MAX(pt[i-1].y, pt[i].y); rect.bottom = MAX(pt[i-1].y, pt[i].y);
ret = IntEngLineTo(DestSurf, ret = IntEngLineTo(DestSurf,
Clip, Clip,
Brush, Brush,
pt[i-1].x, pt[i-1].x,
pt[i-1].y, pt[i-1].y,
pt[i].x, pt[i].x,
pt[i].y, pt[i].y,
&rect, &rect,
mix); mix);
if (!ret) if (!ret)
break; {
} break;
}
}
return ret; return ret;
} }
/* EOF */ /* EOF */

View file

@ -2,7 +2,7 @@
#define __WIN32K_PAINT_H #define __WIN32K_PAINT_H
BOOL STDCALL FillSolid (PSURFOBJ Surface, PRECTL Dimensions, ULONG iColor); BOOL STDCALL FillSolid (PSURFOBJ Surface, PRECTL Dimensions, ULONG iColor);
BOOL STDCALL FillPolygon_ALTERNATE (PSURFOBJ SurfObj, PBRUSHOBJ BrushObj, MIX RopMode, CONST PPOINT Points, INT Count, RECTL BoundRect); BOOL STDCALL FillPolygon_ALTERNATE (PDC dc, PSURFOBJ SurfObj, PBRUSHOBJ BrushObj, MIX RopMode, CONST PPOINT Points, INT Count, RECTL BoundRect);
BOOL STDCALL FillPolygon_WINDING (PSURFOBJ SurfObj, PBRUSHOBJ BrushObj, MIX RopMode, CONST PPOINT Points, INT Count, RECTL BoundRect); BOOL STDCALL FillPolygon_WINDING (PSURFOBJ SurfObj, PBRUSHOBJ BrushObj, MIX RopMode, CONST PPOINT Points, INT Count, RECTL BoundRect);
#endif /* __WIN32K_PAINT_H */ #endif /* __WIN32K_PAINT_H */

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
/* $Id: fillshap.c,v 1.20 2003/06/25 16:55:33 gvg Exp $ */ /* $Id: fillshap.c,v 1.21 2003/07/14 09:43:11 gvg Exp $ */
#undef WIN32_LEAN_AND_MEAN #undef WIN32_LEAN_AND_MEAN
#include <windows.h> #include <windows.h>
@ -82,7 +82,8 @@ W32kPie(HDC hDC,
//When the fill mode is ALTERNATE, GDI fills the area between odd-numbered and //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 //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. //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, PBRUSHOBJ BrushObj,
MIX RopMode, MIX RopMode,
CONST PPOINT Points, CONST PPOINT Points,
@ -186,7 +187,7 @@ W32kPolygon(HDC hDC,
} }
else /* default */ 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 // 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 ); DPRINT("Polygon Making line from (%d,%d) to (%d,%d)\n", From.x, From.y, To.x, To.y );
ret = IntEngLineTo(SurfObj, ret = IntEngLineTo(SurfObj,
NULL, /* ClipObj */ dc->CombinedClip,
OutBrushObj, OutBrushObj,
From.x, From.x,
From.y, From.y,
@ -311,28 +312,28 @@ W32kRectangle(HDC hDC,
BottomRect += dc->w.DCOrgY; BottomRect += dc->w.DCOrgY;
ret = IntEngLineTo(SurfObj, ret = IntEngLineTo(SurfObj,
NULL, // ClipObj, dc->CombinedClip,
BrushObj, BrushObj,
LeftRect, TopRect, RightRect, TopRect, LeftRect, TopRect, RightRect, TopRect,
RectBounds, // Bounding rectangle RectBounds, // Bounding rectangle
dc->w.ROPmode); // MIX dc->w.ROPmode); // MIX
ret = IntEngLineTo(SurfObj, ret = IntEngLineTo(SurfObj,
NULL, // ClipObj, dc->CombinedClip,
BrushObj, BrushObj,
RightRect, TopRect, RightRect, BottomRect, RightRect, TopRect, RightRect, BottomRect,
RectBounds, // Bounding rectangle RectBounds, // Bounding rectangle
dc->w.ROPmode); // MIX dc->w.ROPmode); // MIX
ret = IntEngLineTo(SurfObj, ret = IntEngLineTo(SurfObj,
NULL, // ClipObj, dc->CombinedClip,
BrushObj, BrushObj,
LeftRect, BottomRect, RightRect, BottomRect, LeftRect, BottomRect, RightRect, BottomRect,
RectBounds, // Bounding rectangle RectBounds, // Bounding rectangle
dc->w.ROPmode); // MIX dc->w.ROPmode); // MIX
ret = IntEngLineTo(SurfObj, ret = IntEngLineTo(SurfObj,
NULL, // ClipObj, dc->CombinedClip,
BrushObj, BrushObj,
LeftRect, TopRect, LeftRect, BottomRect, LeftRect, TopRect, LeftRect, BottomRect,
RectBounds, // Bounding rectangle RectBounds, // Bounding rectangle

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 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) // Some code from the WINE project source (www.winehq.com)
@ -29,6 +29,7 @@
#include <win32k/path.h> #include <win32k/path.h>
#include <win32k/pen.h> #include <win32k/pen.h>
#include <win32k/region.h> #include <win32k/region.h>
#include <include/error.h>
#include <include/inteng.h> #include <include/inteng.h>
#include <include/object.h> #include <include/object.h>
#include <include/path.h> #include <include/path.h>
@ -128,57 +129,74 @@ W32kGetArcDirection(HDC hDC)
BOOL BOOL
STDCALL STDCALL
W32kLineTo(HDC hDC, W32kLineTo(HDC hDC,
int XEnd, int XEnd,
int YEnd) int YEnd)
{ {
DC *dc = DC_HandleToPtr(hDC); DC *dc = DC_HandleToPtr(hDC);
SURFOBJ *SurfObj = (SURFOBJ*)AccessUserObject(dc->Surface); SURFOBJ *SurfObj = (SURFOBJ*)AccessUserObject(dc->Surface);
BOOL ret; BOOL Ret;
PPENOBJ pen; PPENOBJ Pen;
PROSRGNDATA reg; RECT Bounds;
#ifndef TODO
RECT defaultrect;
#endif
if(!dc) return FALSE; if (NULL == dc)
{
SetLastWin32Error(ERROR_INVALID_HANDLE);
return FALSE;
}
if(PATH_IsPathOpen(dc->w.path)) { if (PATH_IsPathOpen(dc->w.path))
ret = PATH_LineTo(hDC, XEnd, YEnd); {
} else { Ret = PATH_LineTo(hDC, XEnd, YEnd);
pen = (PPENOBJ) GDIOBJ_LockObj(dc->w.hPen, GO_PEN_MAGIC); }
reg = (PROSRGNDATA)GDIOBJ_LockObj(dc->w.hGCClipRgn, GO_REGION_MAGIC); else
{
Pen = (PPENOBJ) GDIOBJ_LockObj(dc->w.hPen, GO_PEN_MAGIC);
ASSERT(NULL != Pen);
ASSERT( pen ); if (dc->w.CursPosX <= XEnd)
// not yet implemented ASSERT( reg ); {
#ifndef TODO Bounds.left = dc->w.CursPosX;
if (NULL == reg) { Bounds.right = XEnd;
defaultrect.left = 0; }
defaultrect.top = 0; else
defaultrect.right = 640; {
defaultrect.bottom = 480; 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; Ret = IntEngLineTo(SurfObj,
} dc->CombinedClip,
#endif 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 */ GDIOBJ_UnlockObj( dc->w.hPen, GO_PEN_MAGIC);
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.hGCClipRgn, GO_REGION_MAGIC ); if (Ret)
GDIOBJ_UnlockObj( dc->w.hPen, GO_PEN_MAGIC); {
} dc->w.CursPosX = XEnd;
if(ret) { dc->w.CursPosY = YEnd;
dc->w.CursPosX = XEnd; }
dc->w.CursPosY = YEnd; DC_ReleasePtr(hDC);
}
DC_ReleasePtr( hDC ); return Ret;
return ret;
} }
BOOL BOOL
@ -336,7 +354,7 @@ W32kPolyline(HDC hDC,
//get IntEngPolyline to do the drawing. //get IntEngPolyline to do the drawing.
ret = IntEngPolyline(SurfObj, ret = IntEngPolyline(SurfObj,
NULL, dc->CombinedClip,
PenToBrushObj(dc, pen), PenToBrushObj(dc, pen),
pts, pts,
Count, Count,

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 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 * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -33,6 +33,7 @@
#include <win32k/fillshap.h> #include <win32k/fillshap.h>
#include <win32k/dc.h> #include <win32k/dc.h>
#include <win32k/pen.h> #include <win32k/pen.h>
#include <include/inteng.h>
#include <include/object.h> #include <include/object.h>
#include <include/paint.h> #include <include/paint.h>
@ -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 ** This method fills the portion of the polygon that intersects with the scanline
** 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; BOOL OnOdd = TRUE;
RECTL BoundRect; RECTL BoundRect;
@ -510,15 +511,15 @@ static void STDCALL POLYGONFILL_FillScanLine(int ScanLine, PFILL_EDGE_LIST Activ
XInterceptEven = pThis->XIntercept; XInterceptEven = pThis->XIntercept;
DPRINT("Fill Line (%d, %d) to (%d, %d)\n",XInterceptOdd - 1, ScanLine, XInterceptEven - 1, ScanLine); DPRINT("Fill Line (%d, %d) to (%d, %d)\n",XInterceptOdd - 1, ScanLine, XInterceptEven - 1, ScanLine);
ret = EngLineTo(SurfObj, ret = IntEngLineTo(SurfObj,
NULL, /* ClipObj */ dc->CombinedClip,
BrushObj, BrushObj,
XInterceptOdd - 1, XInterceptOdd - 1,
ScanLine, ScanLine,
XInterceptEven - 1, XInterceptEven - 1,
ScanLine, ScanLine,
&BoundRect, /* Bounding rectangle */ &BoundRect, /* Bounding rectangle */
RopMode); /* MIX */ RopMode); /* MIX */
OnOdd = TRUE; OnOdd = TRUE;
} }
pThis = pThis->pNext; 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 //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 //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. //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 list = 0;
PFILL_EDGE_LIST ActiveEdges = 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); POLYGONFILL_UpdateActiveEdges(ScanLine, &list, &ActiveEdges);
/* DEBUG_PRINT_EDGELIST(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. */ /* Free Edge List. If any are left. */