1 //       _________ __                 __
2 //      /   _____//  |_____________ _/  |______     ____  __ __  ______
3 //      \_____  \\   __\_  __ \__  \\   __\__  \   / ___\|  |  \/  ___/
4 //      /        \|  |  |  | \// __ \|  |  / __ \_/ /_/  >  |  /\___ |
5 //     /_______  /|__|  |__|  (____  /__| (____  /\___  /|____//____  >
6 //             \/                  \/          \//_____/            \/
7 //  ______________________                           ______________________
8 //                        T H E   W A R   B E G I N S
9 //         Stratagus - A free fantasy real time strategy game engine
10 //
11 /**@name video.h - The video headerfile. */
12 //
13 //      (c) Copyright 1999-2011 by Lutz Sammer, Nehal Mistry, Jimmy Salmon and
14 //                                 Pali Rohár
15 //
16 //      This program is free software; you can redistribute it and/or modify
17 //      it under the terms of the GNU General Public License as published by
18 //      the Free Software Foundation; only version 2 of the License.
19 //
20 //      This program is distributed in the hope that it will be useful,
21 //      but WITHOUT ANY WARRANTY; without even the implied warranty of
22 //      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23 //      GNU General Public License for more details.
24 //
25 //      You should have received a copy of the GNU General Public License
26 //      along with this program; if not, write to the Free Software
27 //      Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
28 //      02111-1307, USA.
29 //
30 
31 #ifndef __VIDEO_H__
32 #define __VIDEO_H__
33 
34 //@{
35 
36 #include "SDL.h"
37 #include "shaders.h"
38 #include "guichan.h"
39 
40 #include "color.h"
41 #include "vec2i.h"
42 
43 class CFont;
44 
45 /// The SDL screen
46 extern SDL_Window *TheWindow;
47 extern SDL_Renderer *TheRenderer;
48 extern SDL_Surface *TheScreen;
49 extern SDL_Texture *TheTexture;
50 
51 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
52 #define RSHIFT  16
53 #define GSHIFT  8
54 #define BSHIFT  0
55 #define ASHIFT  24
56 #define RMASK   0x00ff0000
57 #define GMASK   0x0000ff00
58 #define BMASK   0x000000ff
59 #define AMASK   0xff000000
60 #else
61 #define RSHIFT  8
62 #define GSHIFT  16
63 #define BSHIFT  24
64 #define ASHIFT  0
65 #define RMASK   0x0000ff00
66 #define GMASK   0x00ff0000
67 #define BMASK   0xff000000
68 #define AMASK   0x000000ff
69 #endif
70 
71 using pixelModifier = uint32_t(*)(const uint32_t, const uint32_t, const uint32_t); // type alias
72 
73 /// Class for modifiers for custom pixel manipulations
74 class PixelModifier
75 {
76 public:
77 	/// This one returns srcRGB+A(modulated) only if srcA is present. Otherwise returns dstRGBA.
78 	/// Used to copy (without alpha modulating) those pixels which has alpha chanel values
CopyWithSrcAlphaKey(const uint32_t srcPixel,const uint32_t dstPixel,const uint32_t reqAlpha)79 	static uint32_t CopyWithSrcAlphaKey(const uint32_t srcPixel, const uint32_t dstPixel, const uint32_t reqAlpha)
80 	{
81 		uint32_t srcAlpha = (srcPixel >> ASHIFT) & 0xFF;
82 		if (srcAlpha) {
83 			srcAlpha = (srcAlpha * reqAlpha) >> 8;
84 			return (srcPixel - (srcPixel & AMASK)) + (srcAlpha << ASHIFT);
85 		}
86 		return dstPixel;
87 	}
88 	/// Add more modifiers here
89 };
90 
91 class CGraphic : public gcn::Image
92 {
93 
94 	struct frame_pos_t {
95 		short int x;
96 		short int y;
97 	};
98 
99 protected:
CGraphic()100 	CGraphic() : Surface(NULL), SurfaceFlip(NULL), frame_map(NULL),
101 		Width(0), Height(0), NumFrames(1), GraphicWidth(0), GraphicHeight(0),
102 		Refs(1), Resized(false)
103 	{
104 		frameFlip_map = NULL;
105 	}
~CGraphic()106 	~CGraphic() {}
107 
108 public:
109 	// Draw
110 	void DrawClip(int x, int y,
111 				  SDL_Surface *surface = TheScreen) const;
112 	void DrawSub(int gx, int gy, int w, int h, int x, int y,
113 				 SDL_Surface *surface = TheScreen) const;
114 
115 	void DrawSubCustomMod(int gx, int gy, int w, int h, int x, int y,
116 					      pixelModifier modifier,
117 						  const uint32_t param,
118 						  SDL_Surface *surface = TheScreen) const;
119 
120 	void DrawSubClip(int gx, int gy, int w, int h, int x, int y,
121 					 SDL_Surface *surface = TheScreen) const;
122 	void DrawSubTrans(int gx, int gy, int w, int h, int x, int y,
123 					  unsigned char alpha,
124 					  SDL_Surface *surface = TheScreen) const;
125 	void DrawSubClipTrans(int gx, int gy, int w, int h, int x, int y,
126 						  unsigned char alpha,
127 						  SDL_Surface *surface = TheScreen) const;
128 
129 	void DrawSubClipCustomMod(int gx, int gy, int w, int h, int x, int y,
130 							  pixelModifier modifier,
131 							  const uint32_t param,
132 							  SDL_Surface *surface = TheScreen) const;
133 
134 	// Draw frame
135 	void DrawFrame(unsigned frame, int x, int y,
136 				   SDL_Surface *surface = TheScreen) const;
137 	void DrawFrameClip(unsigned frame, int x, int y,
138 					   SDL_Surface *surface = TheScreen) const;
139 	void DrawFrameTrans(unsigned frame, int x, int y, int alpha,
140 						SDL_Surface *surface = TheScreen) const;
141 	void DrawFrameClipTrans(unsigned frame, int x, int y, int alpha,
142 							SDL_Surface *surface = TheScreen) const;
143 
144 	void DrawFrameClipCustomMod(unsigned frame, int x, int y,
145 								pixelModifier modifier,
146 								const uint32_t param,
147 								SDL_Surface *surface = TheScreen) const;
148 
149 	// Draw frame flipped horizontally
150 	void DrawFrameX(unsigned frame, int x, int y,
151 					SDL_Surface *surface = TheScreen) const;
152 	void DrawFrameClipX(unsigned frame, int x, int y,
153 						SDL_Surface *surface = TheScreen) const;
154 	void DrawFrameTransX(unsigned frame, int x, int y, int alpha,
155 						 SDL_Surface *surface = TheScreen) const;
156 	void DrawFrameClipTransX(unsigned frame, int x, int y, int alpha,
157 							 SDL_Surface *surface = TheScreen) const;
158 
159 
160 	static CGraphic *New(const std::string &file, int w = 0, int h = 0);
161 	static CGraphic *ForceNew(const std::string &file, int w = 0, int h = 0);
162 	static CGraphic *Get(const std::string &file);
163 
164 	static void Free(CGraphic *g);
165 
166 	void Load(bool grayscale = false);
167 	void Flip();
168 	void Resize(int w, int h);
169 	void SetOriginalSize();
170 	bool TransparentPixel(int x, int y);
171 	void SetPaletteColor(int idx, int r, int g, int b);
172 	void MakeShadow();
173 
IsLoaded()174 	inline bool IsLoaded() const { return Surface != NULL; }
175 
176 	//guichan
_getData()177 	virtual void *_getData() const { return Surface; }
getWidth()178 	virtual int getWidth() const { return Width; }
getHeight()179 	virtual int getHeight() const { return Height; }
180 
181 	std::string File;          /// Filename
182 	std::string HashFile;      /// Filename used in hash
183 	SDL_Surface *Surface;      /// Surface
184 	SDL_Surface *SurfaceFlip;  /// Flipped surface
185 	frame_pos_t *frame_map;
186 	frame_pos_t *frameFlip_map;
187 	void GenFramesMap();
188 	int Width;                 /// Width of a frame
189 	int Height;                /// Height of a frame
190 	int NumFrames;             /// Number of frames
191 	int GraphicWidth;          /// Original graphic width
192 	int GraphicHeight;         /// Original graphic height
193 	int Refs;                  /// Uses of this graphic
194 	bool Resized;              /// Image has been resized
195 
196 	friend class CFont;
197 };
198 
199 class CPlayerColorGraphic : public CGraphic
200 {
201 protected:
CPlayerColorGraphic()202 	CPlayerColorGraphic()
203 	{
204 	}
205 
206 public:
207 	void DrawPlayerColorFrameClipX(int player, unsigned frame, int x, int y,
208 								   SDL_Surface *surface = TheScreen);
209 	void DrawPlayerColorFrameClip(int player, unsigned frame, int x, int y,
210 								  SDL_Surface *surface = TheScreen);
211 
212 	static CPlayerColorGraphic *New(const std::string &file, int w = 0, int h = 0);
213 	static CPlayerColorGraphic *ForceNew(const std::string &file, int w = 0, int h = 0);
214 	static CPlayerColorGraphic *Get(const std::string &file);
215 
216 	CPlayerColorGraphic *Clone(bool grayscale = false) const;
217 };
218 
219 #ifdef USE_MNG
220 #ifdef WIN32
221 #ifdef HAVE_STDDEF_H
222 #undef HAVE_STDDEF_H
223 #endif
224 #endif
225 #include <libmng.h>
226 #ifdef WIN32
227 #ifndef HAVE_STDDEF_H
228 #undef HAVE_STDDEF_H
229 #endif
230 #endif
231 
232 class Mng : public gcn::Image
233 {
234 public:
235 	Mng();
236 	~Mng();
237 	bool Load(const std::string &name);
238 	void Reset();
239 	void Draw(int x, int y);
240 
241 	//guichan
242 	virtual void *_getData() const;
getWidth()243 	virtual int getWidth() const { return surface->h; }
getHeight()244 	virtual int getHeight() const { return surface->w; }
isDirty()245 	virtual bool isDirty() const { return is_dirty; }
246 
247 	mutable bool is_dirty;
248 	std::string name;
249 	FILE *fd;
250 	mng_handle handle;
251 	SDL_Surface *surface;
252 	unsigned char *buffer;
253 	unsigned long ticks;
254 	int iteration;
255 };
256 #else
257 /// empty class for lua scripts
258 class Mng : public gcn::Image
259 {
260 public:
Mng()261 	Mng() {};
~Mng()262 	~Mng() {};
Load(const std::string & name)263 	bool Load(const std::string &name) { return false; };
Reset()264 	void Reset() {};
Draw(int x,int y)265 	void Draw(int x, int y) {};
266 
267 	//guichan
_getData()268 	virtual void *_getData() const { return NULL; };
getWidth()269 	virtual int getWidth() const { return 0; };
getHeight()270 	virtual int getHeight() const { return 0; };
isDirty()271 	virtual bool isDirty() const { return false; };
272 };
273 #endif
274 
275 /**
276 **  Event call back.
277 **
278 **  This is placed in the video part, because it depends on the video
279 **  hardware driver.
280 */
281 struct EventCallback {
282 
283 	/// Callback for mouse button press
284 	void (*ButtonPressed)(unsigned buttons);
285 	/// Callback for mouse button release
286 	void (*ButtonReleased)(unsigned buttons);
287 	/// Callback for mouse move
288 	void (*MouseMoved)(const PixelPos &screenPos);
289 	/// Callback for mouse exit of game window
290 	void (*MouseExit)();
291 
292 	/// Callback for key press
293 	void (*KeyPressed)(unsigned keycode, unsigned keychar);
294 	/// Callback for key release
295 	void (*KeyReleased)(unsigned keycode, unsigned keychar);
296 	/// Callback for key repeated
297 	void (*KeyRepeated)(unsigned keycode, unsigned keychar);
298 
299 	/// Callback for network event
300 	void (*NetworkEvent)();
301 
302 };
303 
304 
305 class CVideo
306 {
307 public:
CVideo()308 	CVideo() : Width(0), Height(0), WindowWidth(0), WindowHeight(0), VerticalPixelSize(1), Depth(0), FullScreen(false) {}
309 
310 	void LockScreen();
311 	void UnlockScreen();
312 
313 	void ClearScreen();
314 	bool ResizeScreen(int width, int height);
315 
316 	void DrawPixelClip(Uint32 color, int x, int y);
317 	void DrawTransPixelClip(Uint32 color, int x, int y, unsigned char alpha);
318 
319 	void DrawVLine(Uint32 color, int x, int y, int height);
320 	void DrawTransVLine(Uint32 color, int x, int y, int height, unsigned char alpha);
321 	void DrawVLineClip(Uint32 color, int x, int y, int height);
322 	void DrawTransVLineClip(Uint32 color, int x, int y, int height, unsigned char alpha);
323 
324 	void DrawHLine(Uint32 color, int x, int y, int width);
325 	void DrawTransHLine(Uint32 color, int x, int y, int width, unsigned char alpha);
326 	void DrawHLineClip(Uint32 color, int x, int y, int width);
327 	void DrawTransHLineClip(Uint32 color, int x, int y, int width, unsigned char alpha);
328 
329 	void DrawLine(Uint32 color, int sx, int sy, int dx, int dy);
330 	void DrawTransLine(Uint32 color, int sx, int sy, int dx, int dy, unsigned char alpha);
331 	void DrawLineClip(Uint32 color, const PixelPos &pos1, const PixelPos &pos2);
332 	void DrawTransLineClip(Uint32 color, int sx, int sy, int dx, int dy, unsigned char alpha);
333 
334 	void DrawRectangle(Uint32 color, int x, int y, int w, int h);
335 	void DrawTransRectangle(Uint32 color, int x, int y, int w, int h, unsigned char alpha);
336 	void DrawRectangleClip(Uint32 color, int x, int y, int w, int h);
337 	void DrawTransRectangleClip(Uint32 color, int x, int y, int w, int h, unsigned char alpha);
338 
339 	void FillRectangle(Uint32 color, int x, int y, int w, int h);
340 	void FillTransRectangle(Uint32 color, int x, int y, int w, int h, unsigned char alpha);
341 	void FillRectangleClip(Uint32 color, int x, int y, int w, int h);
342 	void FillTransRectangleClip(Uint32 color, int x, int y, int w, int h, unsigned char alpha);
343 
344 	void DrawCircle(Uint32 color, int x, int y, int r);
345 	void DrawTransCircle(Uint32 color, int x, int y, int r, unsigned char alpha);
346 	void DrawCircleClip(Uint32 color, int x, int y, int r);
347 	void DrawTransCircleClip(Uint32 color, int x, int y, int r, unsigned char alpha);
348 
349 	void FillCircle(Uint32 color, int x, int y, int radius);
350 	void FillTransCircle(Uint32 color, int x, int y, int radius, unsigned char alpha);
351 	void FillCircleClip(Uint32 color, const PixelPos &screenPos, int radius);
352 	void FillTransCircleClip(Uint32 color, int x, int y, int radius, unsigned char alpha);
353 
MapRGB(SDL_PixelFormat * f,Uint8 r,Uint8 g,Uint8 b)354 	inline Uint32 MapRGB(SDL_PixelFormat *f, Uint8 r, Uint8 g, Uint8 b)
355 	{
356 		return SDL_MapRGB(f, r, g, b);
357 	}
MapRGB(SDL_PixelFormat * f,const CColor & color)358 	inline Uint32 MapRGB(SDL_PixelFormat *f, const CColor &color)
359 	{
360 		return MapRGB(f, color.R, color.G, color.B);
361 	}
MapRGBA(SDL_PixelFormat * f,Uint8 r,Uint8 g,Uint8 b,Uint8 a)362 	inline Uint32 MapRGBA(SDL_PixelFormat *f, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
363 	{
364 		return SDL_MapRGBA(f, r, g, b, a);
365 	}
MapRGBA(SDL_PixelFormat * f,const CColor & color)366 	inline Uint32 MapRGBA(SDL_PixelFormat *f, const CColor &color)
367 	{
368 		return MapRGBA(f, color.R, color.G, color.B, color.A);
369 	}
GetRGB(Uint32 c,SDL_PixelFormat * f,Uint8 * r,Uint8 * g,Uint8 * b)370 	inline void GetRGB(Uint32 c, SDL_PixelFormat *f, Uint8 *r, Uint8 *g, Uint8 *b)
371 	{
372 		SDL_GetRGB(c, f, r, g, b);
373 	}
GetRGBA(Uint32 c,SDL_PixelFormat * f,Uint8 * r,Uint8 * g,Uint8 * b,Uint8 * a)374 	inline void GetRGBA(Uint32 c, SDL_PixelFormat *f, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a)
375 	{
376 		SDL_GetRGBA(c, f, r, g, b, a);
377 	}
378 
379 	int Width;
380 	int Height;
381 	int WindowWidth;
382 	int WindowHeight;
383 	double VerticalPixelSize;
384 	SDL_Cursor *blankCursor;
385 	int Depth;
386 	bool FullScreen;
387 };
388 
389 extern CVideo Video;
390 
391 /**
392 **  Video synchronization speed. Synchronization time in percent.
393 **  If =0, video framerate is not synchronized. 100 is exact
394 **  CYCLES_PER_SECOND (30). Game will try to redraw screen within
395 **  intervals of VideoSyncSpeed, not more, not less.
396 **  @see CYCLES_PER_SECOND
397 */
398 extern int VideoSyncSpeed;
399 
400 extern int SkipFrames;
401 
402 /// Fullscreen or windowed set from commandline.
403 extern char VideoForceFullScreen;
404 
405 /// Next frame ticks
406 extern double NextFrameTicks;
407 
408 /// Counts frames
409 extern unsigned long FrameCounter;
410 
411 /// Counts quantity of slow frames
412 extern unsigned long SlowFrameCounter;
413 
414 /// Initialize Pixels[] for all players.
415 /// (bring Players[] in sync with Pixels[])
416 extern void SetPlayersPalette();
417 
418 /// register lua function
419 extern void VideoCclRegister();
420 
421 /// initialize the image loaders part
422 extern void InitImageLoaders();
423 
424 /// deinitialize the image loaders
425 extern void DeInitImageLoaders();
426 
427 /// initialize the video part
428 extern void InitVideo();
429 
430 /// deinitliaize the video part
431 void DeInitVideo();
432 
433 /// Check if a resolution is valid
434 extern int VideoValidResolution(int w, int h);
435 
436 /// Initializes video synchronization.
437 extern void SetVideoSync();
438 
439 /// Init line draw
440 extern void InitLineDraw();
441 
442 /// Simply invalidates whole window or screen.
443 extern void Invalidate();
444 
445 /// Invalidates selected area on window or screen. Use for accurate
446 /// redrawing. in so
447 extern void InvalidateArea(int x, int y, int w, int h);
448 
449 /// Set clipping for nearly all vector primitives. Functions which support
450 /// clipping will be marked Clip. Set the system-wide clipping rectangle.
451 extern void SetClipping(int left, int top, int right, int bottom);
452 
453 /// Realize video memory.
454 extern void RealizeVideoMemory();
455 
456 /// Save a screenshot to a PNG file
457 extern void SaveScreenshotPNG(const char *name);
458 
459 /// Save a screenshot to a PNG file
460 extern void SaveMapPNG(const char *name);
461 
462 /// Set the current callbacks
463 extern void SetCallbacks(const EventCallback *callbacks);
464 /// Get the current callbacks
465 extern const EventCallback *GetCallbacks();
466 
467 /// Process all system events. Returns if the time for a frame is over
468 extern void WaitEventsOneFrame();
469 
470 /// Toggle full screen mode
471 extern void ToggleFullScreen();
472 
473 /// Push current clipping.
474 extern void PushClipping();
475 
476 /// Pop current clipping.
477 extern void PopClipping();
478 
479 /// Returns the ticks in ms since start
480 extern unsigned long GetTicks();
481 
482 /// Convert a SDLKey to a string
483 extern const char *SdlKey2Str(int key);
484 
485 /// Check if the mouse is grabbed
486 extern bool SdlGetGrabMouse();
487 /// Toggle mouse grab mode
488 extern void ToggleGrabMouse(int mode);
489 
490 extern EventCallback GameCallbacks;   /// Game callbacks
491 extern EventCallback EditorCallbacks; /// Editor callbacks
492 
493 extern Uint32 ColorBlack;
494 extern Uint32 ColorDarkGreen;
495 extern Uint32 ColorLightBlue;
496 extern Uint32 ColorBlue;
497 extern Uint32 ColorOrange;
498 extern Uint32 ColorWhite;
499 extern Uint32 ColorLightGray;
500 extern Uint32 ColorGray;
501 extern Uint32 ColorDarkGray;
502 extern Uint32 ColorRed;
503 extern Uint32 ColorGreen;
504 extern Uint32 ColorYellow;
505 
IndexToColor(unsigned int index)506 inline Uint32 IndexToColor(unsigned int index) {
507     // FIXME: this only works after video was initialized, so we do it dynamically
508     static const Uint32 ColorValues[] = {ColorRed, ColorYellow, ColorGreen, ColorLightGray,
509                                          ColorGray, ColorDarkGray, ColorWhite, ColorOrange,
510                                          ColorLightBlue, ColorBlue, ColorDarkGreen, ColorBlack};
511     return ColorValues[index];
512 }
513 
514 static const char *ColorNames[] = {"red", "yellow", "green", "light-gray",
515                                    "gray", "dark-gray", "white", "orange",
516                                    "light-blue", "blue", "dark-green", "black", NULL};
517 
GetColorIndexByName(const char * colorName)518 inline int GetColorIndexByName(const char *colorName) {
519     int i = 0;
520     while (ColorNames[i] != NULL) {
521         if (!strcmp(colorName, ColorNames[i])) {
522             return i;
523         }
524         i++;
525     }
526     return -1;
527 }
528 
529 extern void FreeGraphics();
530 
531 //
532 //  Color Cycling stuff
533 //
534 
535 extern void VideoPaletteListAdd(SDL_Surface *surface);
536 extern void VideoPaletteListRemove(SDL_Surface *surface);
537 extern void ClearAllColorCyclingRange();
538 extern void AddColorCyclingRange(unsigned int begin, unsigned int end);
539 extern void SetColorCycleAll(bool value);
540 extern void RestoreColorCyclingSurface();
541 
542 /// Does ColorCycling..
543 extern void ColorCycle();
544 
545 /// Blit a surface into another with alpha blending
546 extern void BlitSurfaceAlphaBlending_32bpp(const SDL_Surface *srcSurface, const SDL_Rect *srcRect,
547 												 SDL_Surface *dstSurface, const SDL_Rect *dstRect, const bool enableMT = true);
548 
549 //@}
550 
551 #endif // !__VIDEO_H__
552