Quake-2

Quake 2 GPL Source Release
Log | Files | Refs

r_draw.c (8137B)


      1 /*
      2 Copyright (C) 1997-2001 Id Software, Inc.
      3 
      4 This program is free software; you can redistribute it and/or
      5 modify it under the terms of the GNU General Public License
      6 as published by the Free Software Foundation; either version 2
      7 of the License, or (at your option) any later version.
      8 
      9 This program is distributed in the hope that it will be useful,
     10 but WITHOUT ANY WARRANTY; without even the implied warranty of
     11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
     12 
     13 See the GNU General Public License for more details.
     14 
     15 You should have received a copy of the GNU General Public License
     16 along with this program; if not, write to the Free Software
     17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
     18 
     19 */
     20 
     21 // draw.c
     22 
     23 #include "r_local.h"
     24 
     25 
     26 image_t		*draw_chars;				// 8*8 graphic characters
     27 
     28 //=============================================================================
     29 
     30 /*
     31 ================
     32 Draw_FindPic
     33 ================
     34 */
     35 image_t *Draw_FindPic (char *name)
     36 {
     37 	image_t	*image;
     38 	char	fullname[MAX_QPATH];
     39 
     40 	if (name[0] != '/' && name[0] != '\\')
     41 	{
     42 		Com_sprintf (fullname, sizeof(fullname), "pics/%s.pcx", name);
     43 		image = R_FindImage (fullname, it_pic);
     44 	}
     45 	else
     46 		image = R_FindImage (name+1, it_pic);
     47 
     48 	return image;
     49 }
     50 
     51 
     52 
     53 /*
     54 ===============
     55 Draw_InitLocal
     56 ===============
     57 */
     58 void Draw_InitLocal (void)
     59 {
     60 	draw_chars = Draw_FindPic ("conchars");
     61 }
     62 
     63 
     64 
     65 /*
     66 ================
     67 Draw_Char
     68 
     69 Draws one 8*8 graphics character
     70 It can be clipped to the top of the screen to allow the console to be
     71 smoothly scrolled off.
     72 ================
     73 */
     74 void Draw_Char (int x, int y, int num)
     75 {
     76 	byte			*dest;
     77 	byte			*source;
     78 	int				drawline;	
     79 	int				row, col;
     80 
     81 	num &= 255;
     82 
     83 	if (num == 32 || num == 32+128)
     84 		return;
     85 
     86 	if (y <= -8)
     87 		return;			// totally off screen
     88 
     89 //	if ( ( y + 8 ) >= vid.height )
     90 	if ( ( y + 8 ) > vid.height )		// PGM - status text was missing in sw...
     91 		return;
     92 
     93 #ifdef PARANOID
     94 	if (y > vid.height - 8 || x < 0 || x > vid.width - 8)
     95 		ri.Sys_Error (ERR_FATAL,"Con_DrawCharacter: (%i, %i)", x, y);
     96 	if (num < 0 || num > 255)
     97 		ri.Sys_Error (ERR_FATAL,"Con_DrawCharacter: char %i", num);
     98 #endif
     99 
    100 	row = num>>4;
    101 	col = num&15;
    102 	source = draw_chars->pixels[0] + (row<<10) + (col<<3);
    103 
    104 	if (y < 0)
    105 	{	// clipped
    106 		drawline = 8 + y;
    107 		source -= 128*y;
    108 		y = 0;
    109 	}
    110 	else
    111 		drawline = 8;
    112 
    113 
    114 	dest = vid.buffer + y*vid.rowbytes + x;
    115 
    116 	while (drawline--)
    117 	{
    118 		if (source[0] != TRANSPARENT_COLOR)
    119 			dest[0] = source[0];
    120 		if (source[1] != TRANSPARENT_COLOR)
    121 			dest[1] = source[1];
    122 		if (source[2] != TRANSPARENT_COLOR)
    123 			dest[2] = source[2];
    124 		if (source[3] != TRANSPARENT_COLOR)
    125 			dest[3] = source[3];
    126 		if (source[4] != TRANSPARENT_COLOR)
    127 			dest[4] = source[4];
    128 		if (source[5] != TRANSPARENT_COLOR)
    129 			dest[5] = source[5];
    130 		if (source[6] != TRANSPARENT_COLOR)
    131 			dest[6] = source[6];
    132 		if (source[7] != TRANSPARENT_COLOR)
    133 			dest[7] = source[7];
    134 		source += 128;
    135 		dest += vid.rowbytes;
    136 	}
    137 }
    138 
    139 /*
    140 =============
    141 Draw_GetPicSize
    142 =============
    143 */
    144 void Draw_GetPicSize (int *w, int *h, char *pic)
    145 {
    146 	image_t *gl;
    147 
    148 	gl = Draw_FindPic (pic);
    149 	if (!gl)
    150 	{
    151 		*w = *h = -1;
    152 		return;
    153 	}
    154 	*w = gl->width;
    155 	*h = gl->height;
    156 }
    157 
    158 /*
    159 =============
    160 Draw_StretchPicImplementation
    161 =============
    162 */
    163 void Draw_StretchPicImplementation (int x, int y, int w, int h, image_t	*pic)
    164 {
    165 	byte			*dest, *source;
    166 	int				v, u, sv;
    167 	int				height;
    168 	int				f, fstep;
    169 	int				skip;
    170 
    171 	if ((x < 0) ||
    172 		(x + w > vid.width) ||
    173 		(y + h > vid.height))
    174 	{
    175 		ri.Sys_Error (ERR_FATAL,"Draw_Pic: bad coordinates");
    176 	}
    177 
    178 	height = h;
    179 	if (y < 0)
    180 	{
    181 		skip = -y;
    182 		height += y;
    183 		y = 0;
    184 	}
    185 	else
    186 		skip = 0;
    187 
    188 	dest = vid.buffer + y * vid.rowbytes + x;
    189 
    190 	for (v=0 ; v<height ; v++, dest += vid.rowbytes)
    191 	{
    192 		sv = (skip + v)*pic->height/h;
    193 		source = pic->pixels[0] + sv*pic->width;
    194 		if (w == pic->width)
    195 			memcpy (dest, source, w);
    196 		else
    197 		{
    198 			f = 0;
    199 			fstep = pic->width*0x10000/w;
    200 			for (u=0 ; u<w ; u+=4)
    201 			{
    202 				dest[u] = source[f>>16];
    203 				f += fstep;
    204 				dest[u+1] = source[f>>16];
    205 				f += fstep;
    206 				dest[u+2] = source[f>>16];
    207 				f += fstep;
    208 				dest[u+3] = source[f>>16];
    209 				f += fstep;
    210 			}
    211 		}
    212 	}
    213 }
    214 
    215 /*
    216 =============
    217 Draw_StretchPic
    218 =============
    219 */
    220 void Draw_StretchPic (int x, int y, int w, int h, char *name)
    221 {
    222 	image_t	*pic;
    223 
    224 	pic = Draw_FindPic (name);
    225 	if (!pic)
    226 	{
    227 		ri.Con_Printf (PRINT_ALL, "Can't find pic: %s\n", name);
    228 		return;
    229 	}
    230 	Draw_StretchPicImplementation (x, y, w, h, pic);
    231 }
    232 
    233 /*
    234 =============
    235 Draw_StretchRaw
    236 =============
    237 */
    238 void Draw_StretchRaw (int x, int y, int w, int h, int cols, int rows, byte *data)
    239 {
    240 	image_t	pic;
    241 
    242 	pic.pixels[0] = data;
    243 	pic.width = cols;
    244 	pic.height = rows;
    245 	Draw_StretchPicImplementation (x, y, w, h, &pic);
    246 }
    247 
    248 /*
    249 =============
    250 Draw_Pic
    251 =============
    252 */
    253 void Draw_Pic (int x, int y, char *name)
    254 {
    255 	image_t			*pic;
    256 	byte			*dest, *source;
    257 	int				v, u;
    258 	int				tbyte;
    259 	int				height;
    260 
    261 	pic = Draw_FindPic (name);
    262 	if (!pic)
    263 	{
    264 		ri.Con_Printf (PRINT_ALL, "Can't find pic: %s\n", name);
    265 		return;
    266 	}
    267 
    268 	if ((x < 0) ||
    269 		(x + pic->width > vid.width) ||
    270 		(y + pic->height > vid.height))
    271 		return;	//	ri.Sys_Error (ERR_FATAL,"Draw_Pic: bad coordinates");
    272 
    273 	height = pic->height;
    274 	source = pic->pixels[0];
    275 	if (y < 0)
    276 	{
    277 		height += y;
    278 		source += pic->width*-y;
    279 		y = 0;
    280 	}
    281 
    282 	dest = vid.buffer + y * vid.rowbytes + x;
    283 
    284 	if (!pic->transparent)
    285 	{
    286 		for (v=0 ; v<height ; v++)
    287 		{
    288 			memcpy (dest, source, pic->width);
    289 			dest += vid.rowbytes;
    290 			source += pic->width;
    291 		}
    292 	}
    293 	else
    294 	{
    295 		if (pic->width & 7)
    296 		{	// general
    297 			for (v=0 ; v<height ; v++)
    298 			{
    299 				for (u=0 ; u<pic->width ; u++)
    300 					if ( (tbyte=source[u]) != TRANSPARENT_COLOR)
    301 						dest[u] = tbyte;
    302 
    303 				dest += vid.rowbytes;
    304 				source += pic->width;
    305 			}
    306 		}
    307 		else
    308 		{	// unwound
    309 			for (v=0 ; v<height ; v++)
    310 			{
    311 				for (u=0 ; u<pic->width ; u+=8)
    312 				{
    313 					if ( (tbyte=source[u]) != TRANSPARENT_COLOR)
    314 						dest[u] = tbyte;
    315 					if ( (tbyte=source[u+1]) != TRANSPARENT_COLOR)
    316 						dest[u+1] = tbyte;
    317 					if ( (tbyte=source[u+2]) != TRANSPARENT_COLOR)
    318 						dest[u+2] = tbyte;
    319 					if ( (tbyte=source[u+3]) != TRANSPARENT_COLOR)
    320 						dest[u+3] = tbyte;
    321 					if ( (tbyte=source[u+4]) != TRANSPARENT_COLOR)
    322 						dest[u+4] = tbyte;
    323 					if ( (tbyte=source[u+5]) != TRANSPARENT_COLOR)
    324 						dest[u+5] = tbyte;
    325 					if ( (tbyte=source[u+6]) != TRANSPARENT_COLOR)
    326 						dest[u+6] = tbyte;
    327 					if ( (tbyte=source[u+7]) != TRANSPARENT_COLOR)
    328 						dest[u+7] = tbyte;
    329 				}
    330 				dest += vid.rowbytes;
    331 				source += pic->width;
    332 			}
    333 		}
    334 	}
    335 }
    336 
    337 /*
    338 =============
    339 Draw_TileClear
    340 
    341 This repeats a 64*64 tile graphic to fill the screen around a sized down
    342 refresh window.
    343 =============
    344 */
    345 void Draw_TileClear (int x, int y, int w, int h, char *name)
    346 {
    347 	int			i, j;
    348 	byte		*psrc;
    349 	byte		*pdest;
    350 	image_t		*pic;
    351 	int			x2;
    352 
    353 	if (x < 0)
    354 	{
    355 		w += x;
    356 		x = 0;
    357 	}
    358 	if (y < 0)
    359 	{
    360 		h += y;
    361 		y = 0;
    362 	}
    363 	if (x + w > vid.width)
    364 		w = vid.width - x;
    365 	if (y + h > vid.height)
    366 		h = vid.height - y;
    367 	if (w <= 0 || h <= 0)
    368 		return;
    369 
    370 	pic = Draw_FindPic (name);
    371 	if (!pic)
    372 	{
    373 		ri.Con_Printf (PRINT_ALL, "Can't find pic: %s\n", name);
    374 		return;
    375 	}
    376 	x2 = x + w;
    377 	pdest = vid.buffer + y*vid.rowbytes;
    378 	for (i=0 ; i<h ; i++, pdest += vid.rowbytes)
    379 	{
    380 		psrc = pic->pixels[0] + pic->width * ((i+y)&63);
    381 		for (j=x ; j<x2 ; j++)
    382 			pdest[j] = psrc[j&63];
    383 	}
    384 }
    385 
    386 
    387 /*
    388 =============
    389 Draw_Fill
    390 
    391 Fills a box of pixels with a single color
    392 =============
    393 */
    394 void Draw_Fill (int x, int y, int w, int h, int c)
    395 {
    396 	byte			*dest;
    397 	int				u, v;
    398 
    399 	if (x+w > vid.width)
    400 		w = vid.width - x;
    401 	if (y+h > vid.height)
    402 		h = vid.height - y;
    403 	if (x < 0)
    404 	{
    405 		w += x;
    406 		x = 0;
    407 	}
    408 	if (y < 0)
    409 	{
    410 		h += y;
    411 		y = 0;
    412 	}
    413 	if (w < 0 || h < 0)
    414 		return;
    415 	dest = vid.buffer + y*vid.rowbytes + x;
    416 	for (v=0 ; v<h ; v++, dest += vid.rowbytes)
    417 		for (u=0 ; u<w ; u++)
    418 			dest[u] = c;
    419 }
    420 //=============================================================================
    421 
    422 /*
    423 ================
    424 Draw_FadeScreen
    425 
    426 ================
    427 */
    428 void Draw_FadeScreen (void)
    429 {
    430 	int			x,y;
    431 	byte		*pbuf;
    432 	int	t;
    433 
    434 	for (y=0 ; y<vid.height ; y++)
    435 	{
    436 		pbuf = (byte *)(vid.buffer + vid.rowbytes*y);
    437 		t = (y & 1) << 1;
    438 
    439 		for (x=0 ; x<vid.width ; x++)
    440 		{
    441 			if ((x & 3) != t)
    442 				pbuf[x] = 0;
    443 		}
    444 	}
    445 }