Do some clipping in the draw routines.

After fixing Maraakate's crash, I thought it would be a good idea to put
the fixes into QF, too.
This commit is contained in:
Bill Currie 2011-12-28 19:17:15 +09:00
parent 59c621e0cf
commit 8ee13ef8c2
2 changed files with 100 additions and 10 deletions

View file

@ -73,6 +73,26 @@ typedef struct cachepic_s {
cachepic_t cachepics[MAX_CACHED_PICS]; cachepic_t cachepics[MAX_CACHED_PICS];
int numcachepics; int numcachepics;
#define CLIP(x,y,w,h,mw,mh) \
do { \
if (y < 0) { \
h += y; \
y = 0; \
} \
if (y + h > mh) \
h = mh - y; \
if (h <= 0) \
return; \
if (x < 0) { \
w += x; \
x = 0; \
} \
if (x + w > mw) \
w = mw - x; \
if (w <= 0) \
return; \
} while (0)
VISIBLE qpic_t * VISIBLE qpic_t *
Draw_PicFromWad (const char *name) Draw_PicFromWad (const char *name)
@ -362,7 +382,9 @@ Draw_Pic (int x, int y, qpic_t *pic)
if (x < 0 || (unsigned int) (x + pic->width) > vid.conwidth || y < 0 || if (x < 0 || (unsigned int) (x + pic->width) > vid.conwidth || y < 0 ||
(unsigned int) (y + pic->height) > vid.conheight) { (unsigned int) (y + pic->height) > vid.conheight) {
Sys_Error ("Draw_Pic: bad coordinates"); Sys_MaskPrintf (SYS_VID, "Draw_Pic: bad coordinates");
Draw_SubPic (x, y, pic, 0, 0, pic->width, pic->height);
return;
} }
source = pic->data; source = pic->data;
@ -414,8 +436,29 @@ Draw_SubPic (int x, int y, qpic_t *pic, int srcx, int srcy, int width,
if ((x < 0) || (x + width > (int) vid.conwidth) if ((x < 0) || (x + width > (int) vid.conwidth)
|| (y < 0) || (y + height > (int) vid.conheight)) { || (y < 0) || (y + height > (int) vid.conheight)) {
Sys_Error ("Draw_SubPic: bad coordinates"); Sys_MaskPrintf (SYS_VID, "Draw_SubPic: bad coordinates");
} }
// first, clip to screen
if (x < 0) {
srcx += x;
width += x;
x = 0;
}
if (x + width > (int) vid.width)
width = vid.width - x;
if (width <= 0)
return;
if (y < 0) {
srcy += y;
height += y;
y = 0;
}
if (y + height > (int) vid.height)
height = vid.height - y;
if (height <= 0)
return;
// next, clip to pic
CLIP (srcx, srcy, width, height, pic->width, pic->height);
source = pic->data + srcy * pic->width + srcx; source = pic->data + srcy * pic->width + srcx;
@ -531,7 +574,6 @@ R_DrawRect (vrect_t *prect, int rowbytes, byte * psrc, int transparent)
} }
} }
/* /*
Draw_TileClear Draw_TileClear
@ -545,6 +587,8 @@ Draw_TileClear (int x, int y, int w, int h)
byte *psrc; byte *psrc;
vrect_t vr; vrect_t vr;
CLIP (x, y, w, h, (int) vid.width, (int) vid.height);
r_rectdesc.rect.x = x; r_rectdesc.rect.x = x;
r_rectdesc.rect.y = y; r_rectdesc.rect.y = y;
r_rectdesc.rect.width = w; r_rectdesc.rect.width = w;
@ -608,9 +652,10 @@ Draw_Fill (int x, int y, int w, int h, int c)
if (x < 0 || x + w > (int) vid.conwidth if (x < 0 || x + w > (int) vid.conwidth
|| y < 0 || y + h > (int) vid.conheight) { || y < 0 || y + h > (int) vid.conheight) {
Sys_Printf ("Bad Draw_Fill(%d, %d, %d, %d, %c)\n", x, y, w, h, c); Sys_MaskPrintf (SYS_VID, "Bad Draw_Fill(%d, %d, %d, %d, %c)\n",
return; x, y, w, h, c);
} }
CLIP (x, y, w, h, (int) vid.width, (int) vid.height);
dest = ((byte*)vid.buffer) + y * vid.rowbytes + x; dest = ((byte*)vid.buffer) + y * vid.rowbytes + x;
for (v = 0; v < h; v++, dest += vid.rowbytes) for (v = 0; v < h; v++, dest += vid.rowbytes)

View file

@ -73,6 +73,26 @@ typedef struct cachepic_s {
cachepic_t cachepics[MAX_CACHED_PICS]; cachepic_t cachepics[MAX_CACHED_PICS];
int numcachepics; int numcachepics;
#define CLIP(x,y,w,h,mw,mh) \
do { \
if (y < 0) { \
h += y; \
y = 0; \
} \
if (y + h > mh) \
h = mh - y; \
if (h <= 0) \
return; \
if (x < 0) { \
w += x; \
x = 0; \
} \
if (x + w > mw) \
w = mw - x; \
if (w <= 0) \
return; \
} while (0)
VISIBLE qpic_t * VISIBLE qpic_t *
Draw_PicFromWad (const char *name) Draw_PicFromWad (const char *name)
@ -435,7 +455,9 @@ Draw_Pic (int x, int y, qpic_t *pic)
if (x < 0 || (unsigned int) (x + pic->width) > vid.conwidth || y < 0 || if (x < 0 || (unsigned int) (x + pic->width) > vid.conwidth || y < 0 ||
(unsigned int) (y + pic->height) > vid.conheight) { (unsigned int) (y + pic->height) > vid.conheight) {
Sys_Error ("Draw_Pic: bad coordinates"); Sys_MaskPrintf (SYS_VID, "Draw_Pic: bad coordinates");
Draw_SubPic (x, y, pic, 0, 0, pic->width, pic->height);
return;
} }
source = pic->data; source = pic->data;
@ -527,8 +549,29 @@ Draw_SubPic (int x, int y, qpic_t *pic, int srcx, int srcy, int width,
if ((x < 0) || (x + width > (int) vid.conwidth) if ((x < 0) || (x + width > (int) vid.conwidth)
|| (y < 0) || (y + height > (int) vid.conheight)) { || (y < 0) || (y + height > (int) vid.conheight)) {
Sys_Error ("Draw_SubPic: bad coordinates"); Sys_MaskPrintf (SYS_VID, "Draw_SubPic: bad coordinates");
} }
// first, clip to screen
if (x < 0) {
srcx += x;
width += x;
x = 0;
}
if (x + width > (int) vid.width)
width = vid.width - x;
if (width <= 0)
return;
if (y < 0) {
srcy += y;
height += y;
y = 0;
}
if (y + height > (int) vid.height)
height = vid.height - y;
if (height <= 0)
return;
// next, clip to pic
CLIP (srcx, srcy, width, height, pic->width, pic->height);
source = pic->data + srcy * pic->width + srcx; source = pic->data + srcy * pic->width + srcx;
@ -944,7 +987,6 @@ R_DrawRect (vrect_t *prect, int rowbytes, byte * psrc, int transparent)
} }
} }
/* /*
Draw_TileClear Draw_TileClear
@ -958,6 +1000,8 @@ Draw_TileClear (int x, int y, int w, int h)
byte *psrc; byte *psrc;
vrect_t vr; vrect_t vr;
CLIP (x, y, w, h, (int) vid.width, (int) vid.height);
r_rectdesc.rect.x = x; r_rectdesc.rect.x = x;
r_rectdesc.rect.y = y; r_rectdesc.rect.y = y;
r_rectdesc.rect.width = w; r_rectdesc.rect.width = w;
@ -1020,9 +1064,10 @@ Draw_Fill (int x, int y, int w, int h, int c)
if (x < 0 || x + w > (int) vid.conwidth if (x < 0 || x + w > (int) vid.conwidth
|| y < 0 || y + h > (int) vid.conheight) { || y < 0 || y + h > (int) vid.conheight) {
Sys_Printf ("Bad Draw_Fill(%d, %d, %d, %d, %c)\n", x, y, w, h, c); Sys_MaskPrintf (SYS_VID, "Bad Draw_Fill(%d, %d, %d, %d, %c)\n",
return; x, y, w, h, c);
} }
CLIP (x, y, w, h, (int) vid.width, (int) vid.height);
switch (r_pixbytes) { switch (r_pixbytes) {
case 1: case 1: