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