mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-01-31 05:00:35 +00:00
Split out vrect_t to its own file and add support functions.
The rest is cleanup after removing a wart from one of the field names.
This commit is contained in:
parent
42266cddd5
commit
2ae044effd
14 changed files with 337 additions and 23 deletions
|
@ -8,8 +8,8 @@ nobase_pkginclude_HEADERS = \
|
|||
pakfile.h pcx.h png.h plugin.h pr_comp.h pr_debug.h pr_obj.h progs.h \
|
||||
qargs.h qdefs.h qendian.h qfplist.h qtypes.h quakefs.h quakeio.h render.h \
|
||||
riff.h ruamoko.h screen.h script.h sizebuf.h skin.h sound.h spritegn.h \
|
||||
sys.h teamplay.h tga.h uint32.h va.h ver_check.h vid.h view.h wad.h \
|
||||
wadfile.h winding.h zone.h \
|
||||
sys.h teamplay.h tga.h uint32.h va.h ver_check.h vid.h vrect.h view.h \
|
||||
wad.h wadfile.h winding.h zone.h \
|
||||
\
|
||||
GL/ati.h GL/defines.h GL/extensions.h GL/funcs.h GL/qf_explosions.h \
|
||||
GL/qf_funcs_list.h GL/qf_lightmap.h GL/qf_noisetextures.h \
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#define __vid_h_
|
||||
|
||||
#include "QF/qtypes.h"
|
||||
#include "QF/vrect.h"
|
||||
|
||||
#define VID_CBITS 6
|
||||
#define VID_GRADES (1 << VID_CBITS)
|
||||
|
@ -44,11 +45,6 @@ extern struct cvar_s *vid_width;
|
|||
extern struct cvar_s *vid_height;
|
||||
extern struct cvar_s *vid_bitdepth;
|
||||
|
||||
typedef struct vrect_s {
|
||||
int x,y,width,height;
|
||||
struct vrect_s *pnext;
|
||||
} vrect_t;
|
||||
|
||||
typedef struct {
|
||||
qboolean initialized;
|
||||
void *buffer; // invisible buffer
|
||||
|
|
140
include/QF/vrect.h
Normal file
140
include/QF/vrect.h
Normal file
|
@ -0,0 +1,140 @@
|
|||
/*
|
||||
vrect.h
|
||||
|
||||
Rectangle manipulation
|
||||
|
||||
Copyright (C) 2012 Bill Currie <bill@taniwha.org>
|
||||
|
||||
Author: Bill Currie <bill@taniwha.org>
|
||||
Date: 2012/1/6
|
||||
|
||||
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:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
$Id$
|
||||
*/
|
||||
|
||||
#ifndef __QF_vrect_h
|
||||
#define __QF_vrect_h
|
||||
|
||||
typedef struct vrect_s {
|
||||
int x;
|
||||
int y;
|
||||
int width;
|
||||
int height;
|
||||
struct vrect_s *next;
|
||||
} vrect_t;
|
||||
|
||||
#define VRect_MinX(vr) ((vr)->x)
|
||||
#define VRect_MinY(vr) ((vr)->y)
|
||||
#define VRect_MaxX(vr) ((vr)->x + (vr)->width)
|
||||
#define VRect_MaxY(vr) ((vr)->y + (vr)->height)
|
||||
#define VRect_IsEmpty(vr) ((vr)->width <= 0 || (vr)->height <= 0)
|
||||
|
||||
/** Create a new rectangle of the specified shape.
|
||||
|
||||
Other VRect functions will return a rectangle (or chain of rectangles)
|
||||
created by this function.
|
||||
|
||||
\param x The X coordinate of the top-left corner.
|
||||
\param y The Y coordinate of the top-left corner.
|
||||
\param width The width of the rectangle.
|
||||
\param height The height of the rectangle.
|
||||
\return The newly created rectangle.
|
||||
*/
|
||||
vrect_t *VRect_New (int x, int y, int width, int height);
|
||||
|
||||
/** Free one rectangle.
|
||||
|
||||
This function will not free any other rectangles linked to the specified
|
||||
rectangle.
|
||||
|
||||
\param rect The rectangle to be freed.
|
||||
*/
|
||||
void VRect_Delete (vrect_t *rect);
|
||||
|
||||
/** Return a rectangle representing the intersection of \a r1 and \a r2.
|
||||
|
||||
The returned rectangle may be empty. Use VRect_IsEmpty to check.
|
||||
|
||||
\param r1 The first rectangle.
|
||||
\param r2 The second rectangle.
|
||||
\return The single (possibly empty) rectangle representing the
|
||||
intersection of \a r1 and \a r2.
|
||||
\note It is the caller's responsibility to delete the returned rectangle.
|
||||
*/
|
||||
vrect_t *VRect_Intersect (const vrect_t *r1, const vrect_t *r2);
|
||||
|
||||
/** Return two rectangles representing the portions of \a r above and below
|
||||
\a y.
|
||||
|
||||
One of the returned rectangles may be empty. Use VRect_IsEmpty to check.
|
||||
The first rectangle represents the portion of \a r that is above \a y, and
|
||||
the second rectangle repesents the portion of \a r that is below \a y. The
|
||||
second rectangle is linked to the first via the first's vrect_t::next
|
||||
pointer.
|
||||
|
||||
\param r The rectangle to split.
|
||||
\param y The horizontal line by which \r will be split.
|
||||
\return The two linked rectangles representing the portions above
|
||||
and below \a y. The returned pointer points to the first
|
||||
(above) rectangle, which links to the second (below)
|
||||
rectangle.
|
||||
\note It is the caller's responsibility to delete the returned
|
||||
rectangles.
|
||||
*/
|
||||
vrect_t *VRect_HSplit (const vrect_t *r, int y);
|
||||
|
||||
/** Return two rectangles representing the portions of \a r to the left and
|
||||
right of \a y.
|
||||
|
||||
One of the returned rectangles may be empty. Use VRect_IsEmpty to check.
|
||||
The first rectangle represents the portion of \a r that is to the left of
|
||||
\a y, and the second rectangle repesents the portion of \a r that is to
|
||||
the right of \a y. The second rectangle is linked to the first via the
|
||||
first's vrect_t::next pointer.
|
||||
|
||||
\param r The rectangle to split.
|
||||
\param x The vertical line by which \r will be split.
|
||||
\return The two linked rectangles representing the portions to the
|
||||
left and right of \a y. The returned pointer points to the
|
||||
first (left) rectangle, which links to the second (right)
|
||||
rectangle.
|
||||
\note It is the caller's responsibility to delete the returned
|
||||
rectangles.
|
||||
*/
|
||||
vrect_t *VRect_VSplit (const vrect_t *r, int x);
|
||||
|
||||
/** Return up to four rectangles representing the result of carving rectangle
|
||||
\a s out of rectangle \a r.
|
||||
|
||||
None of the returned rectangles will be empty. If the difference is empty,
|
||||
null will be returned.
|
||||
|
||||
\param r The rectangle to be carved.
|
||||
\param s The rectangle used to carve \a r.
|
||||
\return Up to four linked rectangles representing the portions of
|
||||
\a r after carving out the portion represented by \a s, or
|
||||
null if the result is empty. A new rectangle that is a copy
|
||||
of \a r will be returned if \a r and \a s do not intersect.
|
||||
\note It is the caller's responsibility to delete the returned
|
||||
rectangles.
|
||||
*/
|
||||
vrect_t *VRect_Difference (const vrect_t *r, const vrect_t *s);
|
||||
|
||||
#endif//__QF_vrect_h
|
|
@ -42,6 +42,6 @@ libQFutil_la_SOURCES= \
|
|||
fendian.c hash.c idparse.c info.c link.c llist.c \
|
||||
mathlib.c mdfour.c msg.c pakfile.c plugin.c qargs.c qendian.c \
|
||||
qfplist.c quakefs.c quakeio.c riff.c script.c sizebuf.c string.c sys.c \
|
||||
va.c ver_check.c wad.c wadfile.c zone.c $(fnmatch) $(getopt)
|
||||
va.c ver_check.c vrect.c wad.c wadfile.c zone.c $(fnmatch) $(getopt)
|
||||
|
||||
EXTRA_DIST= $(fnmatch_src) $(getopt_src)
|
||||
|
|
178
libs/util/vrect.c
Normal file
178
libs/util/vrect.c
Normal file
|
@ -0,0 +1,178 @@
|
|||
/*
|
||||
vrect.c
|
||||
|
||||
Rectangle manipulation
|
||||
|
||||
Copyright (C) 2012 Bill Currie <bill@taniwha.org>
|
||||
|
||||
Author: Bill Currie <bill@taniwha.org>
|
||||
Date: 2012/1/6
|
||||
|
||||
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:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
static __attribute__ ((used)) const char rcsid[] = "$Id$";
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "QF/mathlib.h"
|
||||
#include "QF/vrect.h"
|
||||
|
||||
#define RECT_BLOCK 128
|
||||
static vrect_t *free_rects;
|
||||
|
||||
VISIBLE vrect_t *
|
||||
VRect_New (int x, int y, int width, int height)
|
||||
{
|
||||
vrect_t *r;
|
||||
|
||||
if (!free_rects) {
|
||||
int i;
|
||||
|
||||
free_rects = malloc (RECT_BLOCK * sizeof (vrect_t));
|
||||
for (i = 0; i < RECT_BLOCK - 1; i++)
|
||||
free_rects[i].next = &free_rects[i + 1];
|
||||
free_rects[i].next = 0;
|
||||
}
|
||||
r = free_rects;
|
||||
free_rects = free_rects->next;
|
||||
r->next = 0;
|
||||
r->x = x;
|
||||
r->y = y;
|
||||
r->width = width;
|
||||
r->height = height;
|
||||
return r;
|
||||
}
|
||||
|
||||
VISIBLE void
|
||||
VRect_Delete (vrect_t *rect)
|
||||
{
|
||||
rect->next = free_rects;
|
||||
free_rects = rect;
|
||||
}
|
||||
|
||||
VISIBLE vrect_t *
|
||||
VRect_Intersect (const vrect_t *r1, const vrect_t *r2)
|
||||
{
|
||||
int minx = max (VRect_MinX (r1), VRect_MinX (r2));
|
||||
int miny = max (VRect_MinY (r1), VRect_MinY (r2));
|
||||
int maxx = min (VRect_MaxX (r1), VRect_MaxX (r2));
|
||||
int maxy = min (VRect_MaxY (r1), VRect_MaxY (r2));
|
||||
return VRect_New (minx, miny, maxx - minx, maxy - miny);
|
||||
}
|
||||
|
||||
VISIBLE vrect_t *
|
||||
VRect_HSplit (const vrect_t *r, int y)
|
||||
{
|
||||
vrect_t *r1, *r2;
|
||||
int r1miny = VRect_MinY (r);
|
||||
int r1maxy = min (VRect_MaxY (r), y);
|
||||
int r2miny = max (VRect_MinY (r), y);
|
||||
int r2maxy = VRect_MaxY (r);
|
||||
r1 = VRect_New (VRect_MinX (r), r1miny, r->width, r1maxy - r1miny);
|
||||
r2 = VRect_New (VRect_MinX (r), r2miny, r->width, r2maxy - r2miny);
|
||||
r1->next = r2;
|
||||
return r1;
|
||||
}
|
||||
|
||||
VISIBLE vrect_t *
|
||||
VRect_VSplit (const vrect_t *r, int x)
|
||||
{
|
||||
vrect_t *r1, *r2;
|
||||
int r1minx = VRect_MinX (r);
|
||||
int r1maxx = min (VRect_MaxX (r), x);
|
||||
int r2minx = max (VRect_MinX (r), x);
|
||||
int r2maxx = VRect_MaxX (r);
|
||||
r1 = VRect_New (r1minx, VRect_MinY (r), r1maxx - r1minx, r->height);
|
||||
r2 = VRect_New (r2minx, VRect_MinY (r), r2maxx - r2minx, r->height);
|
||||
r1->next = r2;
|
||||
return r1;
|
||||
}
|
||||
|
||||
VISIBLE vrect_t *
|
||||
VRect_Difference (const vrect_t *r, const vrect_t *s)
|
||||
{
|
||||
vrect_t *i, *t, *_r;
|
||||
vrect_t *rects = 0;
|
||||
#define STASH(t) \
|
||||
do { \
|
||||
if (!VRect_IsEmpty (t)) { \
|
||||
t->next = rects; \
|
||||
rects = t; \
|
||||
} else { \
|
||||
VRect_Delete (t); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
// Find the intersection of r (original rect) and s (the rect being
|
||||
// subtracted from r). The intersection rect is used to carve the original
|
||||
// rect. If there is no intersection (the intersection rect is empty),
|
||||
// then there is nothing to subtract and the original rect (actually, a
|
||||
// copy of it) is returned.
|
||||
i = VRect_Intersect (r, s);
|
||||
if (VRect_IsEmpty (i)) {
|
||||
// copy r's shape to i, and return i.
|
||||
i->x = r->x;
|
||||
i->y = r->y;
|
||||
i->width = r->width;
|
||||
i->height = r->height;
|
||||
return i;
|
||||
}
|
||||
|
||||
// Split r along the top of the intersection rect and stash the top
|
||||
// section if it is not empty.
|
||||
t = VRect_HSplit (r, VRect_MinY (i));
|
||||
// can't delete r: we don't own it
|
||||
_r = t->next;
|
||||
STASH (t); // maybe stash the top section
|
||||
// r now represents the portion of the original rect below the top of
|
||||
// the intersection rect.
|
||||
|
||||
// Split r along the bottom of the intersection rect and stash the bottom
|
||||
// section if it is not empty.
|
||||
t = VRect_HSplit (_r, VRect_MaxY (i));
|
||||
VRect_Delete (_r); // finished with that copy of _r
|
||||
_r = t;
|
||||
STASH (t->next); // maybe stash the bottom section
|
||||
// r now represents the horizontal section that is common with the
|
||||
// intersection rect.
|
||||
|
||||
// Split r along the left side of tht intersection rect and stash the
|
||||
// left section if it is not empty.
|
||||
t = VRect_VSplit (_r, VRect_MinX (i));
|
||||
VRect_Delete (_r); // finished with that copy of _r
|
||||
_r = t->next;
|
||||
STASH (t); // maybe stash the left section
|
||||
// r now represets the section of the original rect that is between the
|
||||
// top and bottom, and to the right of the left side of the intersection
|
||||
// rect.
|
||||
|
||||
// Split r along the right side of the intersection rect and stash the
|
||||
// right section if it is not empty. The left section is discarded.
|
||||
t = VRect_VSplit (_r, VRect_MaxX (i));
|
||||
VRect_Delete (_r); // finished with that copy of _r
|
||||
STASH (t->next); // maybe stash the right section
|
||||
VRect_Delete (t); // discard the left section
|
||||
|
||||
return rects;
|
||||
}
|
|
@ -286,7 +286,7 @@ SCR_UpdateScreen (double realtime, SCR_Func *scr_funcs)
|
|||
vrect.y = 0;
|
||||
vrect.width = vid.width;
|
||||
vrect.height = vid.height;
|
||||
vrect.pnext = 0;
|
||||
vrect.next = 0;
|
||||
|
||||
VID_Update (&vrect);
|
||||
} else if (scr_copytop) {
|
||||
|
@ -294,7 +294,7 @@ SCR_UpdateScreen (double realtime, SCR_Func *scr_funcs)
|
|||
vrect.y = 0;
|
||||
vrect.width = vid.width;
|
||||
vrect.height = vid.height - r_lineadj;
|
||||
vrect.pnext = 0;
|
||||
vrect.next = 0;
|
||||
|
||||
VID_Update (&vrect);
|
||||
} else {
|
||||
|
@ -302,7 +302,7 @@ SCR_UpdateScreen (double realtime, SCR_Func *scr_funcs)
|
|||
vrect.y = scr_vrect.y;
|
||||
vrect.width = scr_vrect.width;
|
||||
vrect.height = scr_vrect.height;
|
||||
vrect.pnext = 0;
|
||||
vrect.next = 0;
|
||||
|
||||
VID_Update (&vrect);
|
||||
}
|
||||
|
|
|
@ -75,7 +75,7 @@ R_TimeRefresh_f (void)
|
|||
vr.y = r_refdef.vrect.y;
|
||||
vr.width = r_refdef.vrect.width;
|
||||
vr.height = r_refdef.vrect.height;
|
||||
vr.pnext = NULL;
|
||||
vr.next = NULL;
|
||||
VID_Update (&vr);
|
||||
}
|
||||
stop = Sys_DoubleTime ();
|
||||
|
|
|
@ -307,7 +307,7 @@ SCR_UpdateScreen (double realtime, SCR_Func *scr_funcs)
|
|||
vrect.y = 0;
|
||||
vrect.width = vid.width;
|
||||
vrect.height = vid.height;
|
||||
vrect.pnext = 0;
|
||||
vrect.next = 0;
|
||||
|
||||
VID_Update (&vrect);
|
||||
} else if (scr_copytop) {
|
||||
|
@ -315,7 +315,7 @@ SCR_UpdateScreen (double realtime, SCR_Func *scr_funcs)
|
|||
vrect.y = 0;
|
||||
vrect.width = vid.width;
|
||||
vrect.height = vid.height - r_lineadj;
|
||||
vrect.pnext = 0;
|
||||
vrect.next = 0;
|
||||
|
||||
VID_Update (&vrect);
|
||||
} else {
|
||||
|
@ -323,7 +323,7 @@ SCR_UpdateScreen (double realtime, SCR_Func *scr_funcs)
|
|||
vrect.y = scr_vrect.y;
|
||||
vrect.width = scr_vrect.width;
|
||||
vrect.height = scr_vrect.height;
|
||||
vrect.pnext = 0;
|
||||
vrect.next = 0;
|
||||
|
||||
VID_Update (&vrect);
|
||||
}
|
||||
|
|
|
@ -75,7 +75,7 @@ R_TimeRefresh_f (void)
|
|||
vr.y = r_refdef.vrect.y;
|
||||
vr.width = r_refdef.vrect.width;
|
||||
vr.height = r_refdef.vrect.height;
|
||||
vr.pnext = NULL;
|
||||
vr.next = NULL;
|
||||
VID_Update (&vr);
|
||||
}
|
||||
stop = Sys_DoubleTime ();
|
||||
|
|
|
@ -518,7 +518,7 @@ VID_Update (vrect_t *rects)
|
|||
d += lineskip;
|
||||
s += lineskip;
|
||||
}
|
||||
rects = rects->pnext;
|
||||
rects = rects->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -147,14 +147,14 @@ VID_Update (vrect_t *rects)
|
|||
|
||||
// First, count the number of rectangles
|
||||
n = 0;
|
||||
for (rect = rects; rect; rect = rect->pnext)
|
||||
for (rect = rects; rect; rect = rect->next)
|
||||
++n;
|
||||
|
||||
// Second, copy them to SDL rectangles and update
|
||||
if (!(sdlrects = (SDL_Rect *) calloc (1, n * sizeof (SDL_Rect))))
|
||||
Sys_Error ("Out of memory!");
|
||||
i = 0;
|
||||
for (rect = rects; rect; rect = rect->pnext) {
|
||||
for (rect = rects; rect; rect = rect->next) {
|
||||
sdlrects[i].x = rect->x;
|
||||
sdlrects[i].y = rect->y;
|
||||
sdlrects[i].w = rect->width;
|
||||
|
|
|
@ -197,7 +197,7 @@ VID_Update (vrect_t *rects)
|
|||
// update display
|
||||
SDL_UpdateRect (screen, rects->x, rects->y, rects->width,
|
||||
rects->height);
|
||||
rects = rects->pnext;
|
||||
rects = rects->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -457,7 +457,7 @@ VID_Update (vrect_t *rects)
|
|||
}
|
||||
offset += vid.rowbytes;
|
||||
}
|
||||
rects = rects->pnext;
|
||||
rects = rects->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -615,7 +615,7 @@ VID_Update (vrect_t *rects)
|
|||
oktodraw = false;
|
||||
while (!oktodraw)
|
||||
X11_ProcessEvent ();
|
||||
rects = rects->pnext;
|
||||
rects = rects->next;
|
||||
|
||||
current_framebuffer = !current_framebuffer;
|
||||
} else {
|
||||
|
@ -624,7 +624,7 @@ VID_Update (vrect_t *rects)
|
|||
rects->width, rects->height)) {
|
||||
Sys_Error ("VID_Update: XPutImage failed");
|
||||
}
|
||||
rects = rects->pnext;
|
||||
rects = rects->next;
|
||||
}
|
||||
}
|
||||
XSync (x_disp, False);
|
||||
|
|
Loading…
Reference in a new issue