1 /* NetHack may be freely redistributed.  See license for details. */
2 
3 #include <stdlib.h>
4 #include <string.h>
5 
6 #include "vulture_sdl.h"
7 #include "vulture_gra.h"
8 
9 
10 Uint32 CLR32_BLACK;
11 Uint32 CLR32_BLACK_A30;
12 Uint32 CLR32_BLACK_A50;
13 Uint32 CLR32_BLACK_A70;
14 Uint32 CLR32_GREEN;
15 Uint32 CLR32_YELLOW;
16 Uint32 CLR32_ORANGE;
17 Uint32 CLR32_RED;
18 Uint32 CLR32_GRAY20;
19 Uint32 CLR32_GRAY70;
20 Uint32 CLR32_GRAY77;
21 Uint32 CLR32_PURPLE44;
22 Uint32 CLR32_LIGHTPINK;
23 Uint32 CLR32_LIGHTGREEN;
24 Uint32 CLR32_BROWN;
25 Uint32 CLR32_WHITE;
26 Uint32 CLR32_BLESS_BLUE;
27 Uint32 CLR32_CURSE_RED;
28 Uint32 CLR32_GOLD_SHADE;
29 
30 
31 SDL_PixelFormat * vulture_px_format = NULL;
32 
33 
34 #define FADESTEPS_PER_SEC 20
35 
dofade(double n_secs,SDL_Surface * blendimg)36 static void dofade(double n_secs, SDL_Surface * blendimg)
37 {
38 	unsigned int cur_clock, end_clock, start_clock, sleeptime, elapsed;
39 
40 	/* calculate how many individual blends we want to do */
41 	int n_steps = FADESTEPS_PER_SEC * n_secs;
42 	SDL_SetAlpha(blendimg, SDL_SRCALPHA, (SDL_ALPHA_OPAQUE / n_steps));
43 
44 	start_clock = cur_clock = SDL_GetTicks();
45 	end_clock = start_clock + (n_secs * 1000);
46 	while (cur_clock < end_clock)
47 	{
48 		/* blitting the image onto the screen repeatedly
49 		* will slowly add up to full brightness, while
50 		* drawing over the screen with semi-transparent
51 		* darkness repeatedly gives us a fade-out effect*/
52 		SDL_BlitSurface(blendimg, NULL, vulture_screen, NULL);
53 		vulture_refresh();
54 
55 		elapsed = SDL_GetTicks() - cur_clock;
56 		sleeptime = ((1000/FADESTEPS_PER_SEC) > elapsed) ? ((1000/FADESTEPS_PER_SEC) - elapsed) : 0;
57 		SDL_Delay(sleeptime);
58 		cur_clock = SDL_GetTicks();
59 	}
60 
61 	/* ensure that the screen is fully faded in */
62 	SDL_SetAlpha(blendimg, 0, 0);
63 	SDL_BlitSurface(blendimg, NULL, vulture_screen, NULL);
64 	vulture_refresh();
65 }
66 
67 
vulture_fade_out(double n_secs)68 void vulture_fade_out(double n_secs)
69 {
70 	/* create a screen sized pure black surface without an alpha channel */
71 	SDL_Surface * img = SDL_CreateRGBSurface(SDL_SWSURFACE, vulture_screen->w, vulture_screen->h,
72 											vulture_px_format->BitsPerPixel,
73 											vulture_px_format->Rmask,
74 											vulture_px_format->Gmask,
75 											vulture_px_format->Bmask, 0);
76 	SDL_FillRect(img, NULL, 0);
77 
78 	/* blend the blackness with the existing image */
79 	dofade(n_secs, img);
80 
81 	SDL_FreeSurface(img);
82 }
83 
84 
vulture_fade_in(double n_secs)85 void vulture_fade_in(double n_secs)
86 {
87 	/* create a copy of the screen without an alpha-channel (ie an alpha mask == 0) */
88 	SDL_Surface * img = SDL_CreateRGBSurface(SDL_SWSURFACE, vulture_screen->w, vulture_screen->h,
89 											vulture_px_format->BitsPerPixel,
90 											vulture_px_format->Rmask,
91 											vulture_px_format->Gmask,
92 											vulture_px_format->Bmask, 0);
93 	SDL_BlitSurface(vulture_screen, NULL, img, NULL);
94 
95 	/* set the screen to all-black and display that */
96 	SDL_FillRect(vulture_screen, NULL, CLR32_BLACK);
97 	vulture_refresh();
98 
99 	dofade(n_secs, img);
100 
101 	SDL_FreeSurface(img);
102 }
103 
104 
105 /*--------------------------------------------------------------------------
106 Basic graphics plotting
107 --------------------------------------------------------------------------*/
vulture_set_draw_region(int _drx1,int _dry1,int _drx2,int _dry2)108 void vulture_set_draw_region
109 (
110 int _drx1, int _dry1,
111 int _drx2, int _dry2
112 )
113 {
114 	SDL_Rect rect;
115 
116 	rect.x = _drx1;
117 	rect.y = _dry1;
118 	rect.w = _drx2+1-_drx1;
119 	rect.h = _dry2+1-_dry1;
120 	SDL_SetClipRect( vulture_screen, &rect );
121 }
122 
123 
124 
125 /* draws an unfilled rectangle onto the given surface;
126 * this function may blow up if given invalid coordinates */
vulture_rect_surface(SDL_Surface * surface,int x1,int y1,int x2,int y2,Uint32 color)127 void vulture_rect_surface
128 (
129 	SDL_Surface *surface,
130 	int x1, int y1,
131 	int x2, int y2,
132 	Uint32 color
133 )
134 {
135 	int i,j;
136 	Uint32 *screen;
137 
138 	if (SDL_MUSTLOCK(surface)) SDL_LockSurface(surface);
139 	screen = (Uint32 *)surface->pixels;
140 
141 	for (i = x1; i <= x2; i++)
142 	{
143 		screen[y1*surface->w+i] = color;
144 		screen[y2*surface->w+i] = color;
145 	}
146 	for (j = y1; j <= y2; j++)
147 	{
148 		screen[j*surface->w+x1] = color;
149 		screen[j*surface->w+x2] = color;
150 	}
151 
152 	if (SDL_MUSTLOCK(surface)) SDL_UnlockSurface(surface);
153 }
154 
155 
156 /* draws a filled rectangle onto the given surface;
157 * this function blows up if given invalid coordinates */
vulture_fill_rect_surface(SDL_Surface * surface,int x1,int y1,int x2,int y2,Uint32 color)158 void vulture_fill_rect_surface
159 (
160 	SDL_Surface *surface,
161 	int x1, int y1,
162 	int x2, int y2,
163 	Uint32 color
164 )
165 {
166 	SDL_Rect dstrect, srcrect;
167 
168 	dstrect.x = x1;
169 	dstrect.y = y1;
170 	dstrect.w = x2+1-x1;
171 	dstrect.h = y2+1-y1;
172 
173 	srcrect.x = 0;
174 	srcrect.y = 0;
175 	srcrect.w = dstrect.w;
176 	srcrect.h = dstrect.h;
177 
178 	/* to get alpha-blending with our rect-filling we create a temp surface, fill that
179 	* and then let SDL_BlitSurface do the blending for us */
180 	SDL_Surface * tmp_surface = SDL_CreateRGBSurface(
181 			SDL_SWSURFACE | SDL_SRCALPHA,
182 			srcrect.w,
183 			srcrect.h,
184 			32, surface->format->Rmask, surface->format->Gmask, surface->format->Bmask, DEF_AMASK);
185 
186 	SDL_FillRect(tmp_surface, &srcrect, color);
187 
188 	SDL_BlitSurface(tmp_surface, &srcrect, surface, &dstrect);
189 	SDL_FreeSurface(tmp_surface);
190 }
191 
192 
vulture_draw_raised_frame(int x1,int y1,int x2,int y2)193 void vulture_draw_raised_frame(int x1, int y1, int x2, int y2)
194 {
195 	/* bottom edge */
196 	vulture_line(x1 + 1, y2, x2,     y2,     CLR32_GRAY70);
197 	/* top edge */
198 	vulture_line(x1,     y1, x2 - 1, y1,     CLR32_GRAY20);
199 	/* right edge */
200 	vulture_line(x2,     y1, x2,     y2,     CLR32_GRAY77);
201 	/* left edge */
202 	vulture_line(x1,     y1, x1,     y2 - 1, CLR32_GRAY20);
203 }
204 
205 
vulture_draw_lowered_frame(int x1,int y1,int x2,int y2)206 void vulture_draw_lowered_frame(int x1, int y1, int x2, int y2)
207 {
208 	/* top edge */
209 	vulture_line(x1,     y1,     x2 - 1, y1,     CLR32_GRAY70);
210 	/* left edge */
211 	vulture_line(x1,     y1 + 1, x1,     y2 - 1, CLR32_GRAY77);
212 	/* bottom edge */
213 	vulture_line(x1 + 1, y2,     x2,     y2,     CLR32_GRAY20);
214 	/* right edge */
215 	vulture_line(x2,     y1 + 1, x2,     y2,     CLR32_GRAY20);
216 }
217 
218 /*--------------------------------------------------------------------------
219 Bitmap handling
220 --------------------------------------------------------------------------*/
vulture_get_img_src(int x1,int y1,int x2,int y2,SDL_Surface * img_source)221 SDL_Surface *vulture_get_img_src
222 (
223 	int x1, int y1,
224 	int x2, int y2,
225 	SDL_Surface *img_source
226 )
227 {
228 	SDL_Surface *toSurface;
229 	int i;
230 	unsigned char * srcpixels = (unsigned char*)img_source->pixels;
231 
232 
233 	toSurface = SDL_CreateRGBSurface(
234 			SDL_SWSURFACE | SDL_SRCALPHA,
235 			x2+1-x1,
236 			y2+1-y1,
237 			img_source->format->BitsPerPixel,
238 			img_source->format->Rmask,
239 			img_source->format->Gmask,
240 			img_source->format->Bmask,
241 			img_source->format->Amask);
242 
243 	/* we might have been passed coordinates that are outside the source which will blow up our memcpy */
244 	int leftoffset = (x1 < 0) ? -x1 : 0;
245 	int rightoffset = (x2 >= img_source->w) ? (x2 - img_source->w + 1) : 0;
246 	int topoffset = (y1 < 0) ? -y1: 0;
247 	int bottomoffset = (y2 >= img_source->h) ? (y2 - img_source->h + 1) : 0;
248 
249 	int destwidth = x2+1-x1-leftoffset-rightoffset;
250 	int destheight = y2+1-y1-topoffset-bottomoffset;
251 	if (destwidth <= 0 || destheight <= 0)
252 		return toSurface;
253 
254 	/* Blitting would be a mistake here, because we need to preserve
255 	* the alpha channel, which blitting does not do */
256 	for (i = topoffset; i < (y2+1-y1-bottomoffset); i++)
257 		memcpy((char*)toSurface->pixels + toSurface->pitch*i + (leftoffset * 4),
258 			&srcpixels[(i+y1)*img_source->pitch + (x1 + leftoffset)*4],
259 			destwidth*4);
260 
261 	return toSurface;
262 }
263 
264 
265 
vulture_put_img(int x,int y,SDL_Surface * a)266 void vulture_put_img
267 (
268 	int x, int y,
269 	SDL_Surface *a
270 )
271 {
272 	if (!a)
273 		return;
274 
275 	SDL_Rect toRect;
276 
277 	toRect.x = x;
278 	toRect.y = y;
279 	toRect.w = a->w;
280 	toRect.h = a->h;
281 
282 	SDL_BlitSurface( a, NULL, vulture_screen, &toRect);
283 }
284 
285