1 /***********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12 ***********************************************************************/
14 /***********************************************************************
15 graphics.c - description
17 begin : Mon Jul 1 2002
18 copyright : (C) 2000 by Michael Speck
19 : (C) 2002 by Rafał Bursig
20 email : Michael Speck <kulkanie@gmx.net>
21 : Rafał Bursig <bursig@poczta.fm>
22 ***********************************************************************/
25 #include <fc_config.h>
29 #ifdef SDL2_PLAIN_INCLUDE
30 #include <SDL_image.h>
31 #include <SDL_syswm.h>
33 #else /* SDL2_PLAIN_INCLUDE */
34 #include <SDL2/SDL_image.h>
35 #include <SDL2/SDL_syswm.h>
36 #include <SDL2/SDL_ttf.h>
37 #endif /* SDL2_PLAIN_INCLUDE */
48 #include "gui_tilespec.h"
50 #include "themebackgrounds.h"
51 #include "themespec.h"
55 /* ------------------------------ */
59 static SDL_Surface
*main_surface
;
61 static bool render_dirty
= TRUE
;
63 /**************************************************************************
64 Allocate new gui_layer.
65 **************************************************************************/
66 struct gui_layer
*gui_layer_new(int x
, int y
, SDL_Surface
*surface
)
68 struct gui_layer
*result
;
70 result
= fc_calloc(1, sizeof(struct gui_layer
));
72 result
->dest_rect
= (SDL_Rect
){x
, y
, 0, 0};
73 result
->surface
= surface
;
78 /**************************************************************************
79 Free resources associated with gui_layer.
80 **************************************************************************/
81 void gui_layer_destroy(struct gui_layer
**gui_layer
)
83 FREESURFACE((*gui_layer
)->surface
);
87 /**************************************************************************
88 Get surface gui_layer.
89 **************************************************************************/
90 struct gui_layer
*get_gui_layer(SDL_Surface
*surface
)
94 while ((i
< Main
.guis_count
) && Main
.guis
[i
]) {
95 if (Main
.guis
[i
]->surface
== surface
) {
104 /**************************************************************************
105 Buffer allocation function.
106 This function is call by "create_window(...)" function and allocate
107 buffer layer for this function.
109 Pointer for this buffer is put in buffer array on last position that
110 flush functions will draw this layer last.
111 **************************************************************************/
112 struct gui_layer
*add_gui_layer(int width
, int height
)
114 struct gui_layer
*gui_layer
= NULL
;
115 SDL_Surface
*pBuffer
;
117 pBuffer
= create_surf(width
, height
, SDL_SWSURFACE
);
118 gui_layer
= gui_layer_new(0, 0, pBuffer
);
120 /* add to buffers array */
124 /* find NULL element */
125 for (i
= 0; i
< Main
.guis_count
; i
++) {
127 Main
.guis
[i
] = gui_layer
;
132 Main
.guis
= fc_realloc(Main
.guis
, Main
.guis_count
* sizeof(struct gui_layer
*));
133 Main
.guis
[Main
.guis_count
- 1] = gui_layer
;
135 Main
.guis
= fc_calloc(1, sizeof(struct gui_layer
*));
136 Main
.guis
[0] = gui_layer
;
143 /**************************************************************************
144 Free buffer layer ( call by popdown_window_group_dialog(...) funct )
145 Funct. free buffer layer and cleare buffer array entry.
146 **************************************************************************/
147 void remove_gui_layer(struct gui_layer
*gui_layer
)
151 for (i
= 0; i
< Main
.guis_count
- 1; i
++) {
152 if (Main
.guis
[i
] && (Main
.guis
[i
]== gui_layer
)) {
153 gui_layer_destroy(&Main
.guis
[i
]);
154 Main
.guis
[i
] = Main
.guis
[i
+ 1];
155 Main
.guis
[i
+ 1] = NULL
;
158 Main
.guis
[i
] = Main
.guis
[i
+ 1];
159 Main
.guis
[i
+ 1] = NULL
;
164 if (Main
.guis
[Main
.guis_count
- 1]) {
165 gui_layer_destroy(&Main
.guis
[Main
.guis_count
- 1]);
169 /**************************************************************************
170 Adjust dest_rect according to gui_layer.
171 **************************************************************************/
172 void screen_rect_to_layer_rect(struct gui_layer
*gui_layer
,
176 dest_rect
->x
= dest_rect
->x
- gui_layer
->dest_rect
.x
;
177 dest_rect
->y
= dest_rect
->y
- gui_layer
->dest_rect
.y
;
181 /* ============ Freeciv sdl graphics function =========== */
183 /**************************************************************************
185 **************************************************************************/
186 int alphablit(SDL_Surface
*src
, SDL_Rect
*srcrect
,
187 SDL_Surface
*dst
, SDL_Rect
*dstrect
,
188 unsigned char alpha_mod
)
192 if (src
== NULL
|| dst
== NULL
) {
196 SDL_SetSurfaceAlphaMod(src
, alpha_mod
);
198 ret
= SDL_BlitSurface(src
, srcrect
, dst
, dstrect
);
201 log_error("SDL_BlitSurface() fails: %s", SDL_GetError());
207 /**************************************************************************
208 Execute alphablit to the main surface
209 **************************************************************************/
210 int screen_blit(SDL_Surface
*src
, SDL_Rect
*srcrect
, SDL_Rect
*dstrect
,
211 unsigned char alpha_mod
)
214 return alphablit(src
, srcrect
, main_surface
, dstrect
, alpha_mod
);
217 /**************************************************************************
218 Create new surface (pRect->w x pRect->h size) and copy pRect area of
220 if pRect == NULL then create copy of entire pSource.
221 **************************************************************************/
222 SDL_Surface
*crop_rect_from_surface(SDL_Surface
*pSource
,
225 SDL_Surface
*pNew
= create_surf_with_format(pSource
->format
,
226 pRect
? pRect
->w
: pSource
->w
,
227 pRect
? pRect
->h
: pSource
->h
,
230 if (alphablit(pSource
, pRect
, pNew
, NULL
, 255) != 0) {
239 /**************************************************************************
240 Reduce the alpha of the final surface proportional to the alpha of the mask.
241 Thus if the mask has 50% alpha the final image will be reduced by 50% alpha.
243 mask_offset_x, mask_offset_y is the offset of the mask relative to the
244 origin of the source image. The pixel at (mask_offset_x,mask_offset_y)
245 in the mask image will be used to clip pixel (0,0) in the source image
246 which is pixel (-x,-y) in the new image.
247 **************************************************************************/
248 SDL_Surface
*mask_surface(SDL_Surface
*pSrc
, SDL_Surface
*pMask
,
249 int mask_offset_x
, int mask_offset_y
)
251 SDL_Surface
*pDest
= NULL
;
253 Uint32
*pSrc_Pixel
= NULL
;
254 Uint32
*pDest_Pixel
= NULL
;
255 Uint32
*pMask_Pixel
= NULL
;
256 unsigned char src_alpha
, mask_alpha
;
258 pDest
= copy_surface(pSrc
);
264 pSrc_Pixel
= (Uint32
*)pSrc
->pixels
;
265 pDest_Pixel
= (Uint32
*)pDest
->pixels
;
267 for (row
= 0; row
< pSrc
->h
; row
++) {
268 pMask_Pixel
= (Uint32
*)pMask
->pixels
269 + pMask
->w
* (row
+ mask_offset_y
)
272 for (col
= 0; col
< pSrc
->w
; col
++) {
273 src_alpha
= (*pSrc_Pixel
& pSrc
->format
->Amask
) >> pSrc
->format
->Ashift
;
274 mask_alpha
= (*pMask_Pixel
& pMask
->format
->Amask
) >> pMask
->format
->Ashift
;
276 *pDest_Pixel
= (*pSrc_Pixel
& ~pSrc
->format
->Amask
)
277 | (((src_alpha
* mask_alpha
) / 255) << pDest
->format
->Ashift
);
279 pSrc_Pixel
++; pDest_Pixel
++; pMask_Pixel
++;
290 /**************************************************************************
291 Load a surface from file putting it in software mem.
292 **************************************************************************/
293 SDL_Surface
*load_surf(const char *pFname
)
301 if ((pBuf
= IMG_Load(pFname
)) == NULL
) {
302 log_error(_("load_surf: Failed to load graphic file %s!"), pFname
);
309 SDL_Surface
*pNew_sur
;
311 if ((pNew_sur
= SDL_ConvertSurfaceFormat(pBuf
, SDL_PIXELFORMAT_RGBA4444
, 0)) == NULL
) {
312 log_error(_("load_surf: Unable to convert file %s "
313 "into screen's format!"), pFname
);
325 /**************************************************************************
326 create an surface with format
327 MUST NOT BE USED IF NO SDLSCREEN IS SET
328 **************************************************************************/
329 SDL_Surface
*create_surf_with_format(SDL_PixelFormat
*pf
,
330 int width
, int height
,
333 SDL_Surface
*surf
= SDL_CreateRGBSurface(flags
, width
, height
,
337 pf
->Bmask
, pf
->Amask
);
340 log_error(_("Unable to create Sprite (Surface) of size "
341 "%d x %d %d Bits in format %d"),
342 width
, height
, pf
->BitsPerPixel
, flags
);
349 /**************************************************************************
350 Create surface with the same format as main window
351 **************************************************************************/
352 SDL_Surface
*create_surf(int width
, int height
, Uint32 flags
)
354 return create_surf_with_format(main_surface
->format
, width
, height
, flags
);
357 /**************************************************************************
358 Convert surface to the main window format.
359 **************************************************************************/
360 SDL_Surface
*convert_surf(SDL_Surface
*surf_in
)
362 return SDL_ConvertSurface(surf_in
, main_surface
->format
, 0);
365 /**************************************************************************
366 create an surface with screen format and fill with color.
367 if pColor == NULL surface is filled with transparent white A = 128
368 **************************************************************************/
369 SDL_Surface
*create_filled_surface(Uint16 w
, Uint16 h
, Uint32 iFlags
,
373 SDL_Color color
= {255, 255, 255, 128};
375 pNew
= create_surf(w
, h
, iFlags
);
382 /* pColor->unused == ALPHA */
386 SDL_FillRect(pNew
, NULL
,
387 SDL_MapRGBA(pNew
->format
, pColor
->r
, pColor
->g
, pColor
->b
,
390 if (pColor
->a
!= 255) {
391 SDL_SetSurfaceAlphaMod(pNew
, pColor
->a
);
397 /**************************************************************************
398 fill surface with (0, 0, 0, 0), so the next blitting operation can set
400 **************************************************************************/
401 int clear_surface(SDL_Surface
*pSurf
, SDL_Rect
*dstrect
)
403 /* SDL_FillRect might change the rectangle, so we create a copy */
405 SDL_Rect _dstrect
= *dstrect
;
407 return SDL_FillRect(pSurf
, &_dstrect
, SDL_MapRGBA(pSurf
->format
, 0, 0, 0, 0));
409 return SDL_FillRect(pSurf
, NULL
, SDL_MapRGBA(pSurf
->format
, 0, 0, 0, 0));
413 /**************************************************************************
414 blit entire src [SOURCE] surface to destination [DEST] surface
415 on position : [iDest_x],[iDest_y] using it's actual alpha and
417 **************************************************************************/
418 int blit_entire_src(SDL_Surface
* pSrc
, SDL_Surface
* pDest
,
419 Sint16 iDest_x
, Sint16 iDest_y
)
421 SDL_Rect dest_rect
= { iDest_x
, iDest_y
, 0, 0 };
423 return alphablit(pSrc
, NULL
, pDest
, &dest_rect
, 255);
427 * this is center main application window function
428 * currently it work only for X but problem is that such
429 * functions will be needed by others enviroments.
430 * ( for X it's make by settings "SDL_VIDEO_CENTERED" enviroment )
432 int center_main_window_on_screen(void)
435 SDL_SysWMinfo myinfo
;
437 SDL_VERSION(&myinfo
.version
);
438 if (SDL_GetWMInfo(&myinfo
) > 0)
442 /* Port ME - Write center window code with WinAPI instructions */
445 #else /* WIN32_NATIVE */
448 /* this code is for X and is only example what should be write to other
451 Display
*d
= myinfo
.info
.x11
.display
;
453 myinfo
.info
.x11
.lock_func();
454 defscr
= DefaultScreenOfDisplay(d
);
455 XMoveWindow(d
, myinfo
.info
.x11
.wmwindow
,
456 (defscr
->width
- Main
.screen
->w
) / 2,
457 (defscr
->height
- Main
.screen
->h
) / 2);
458 myinfo
.info
.x11
.unlock_func();
461 #endif /* WIN32_NATIVE */
469 /**************************************************************************
471 Return the pixel value at (x, y)
472 NOTE: The surface must be locked before calling this!
473 **************************************************************************/
474 Uint32
getpixel(SDL_Surface
*pSurface
, Sint16 x
, Sint16 y
)
480 switch (pSurface
->format
->BytesPerPixel
) {
482 return *(Uint8
*) ((Uint8
*) pSurface
->pixels
+ y
* pSurface
->pitch
+ x
);
485 return *((Uint16
*)pSurface
->pixels
+ y
* pSurface
->pitch
/ sizeof(Uint16
) + x
);
489 /* Here ptr is the address to the pixel we want to retrieve */
491 (Uint8
*) pSurface
->pixels
+ y
* pSurface
->pitch
+ x
* 3;
493 if (SDL_BYTEORDER
== SDL_BIG_ENDIAN
) {
494 return ptr
[0] << 16 | ptr
[1] << 8 | ptr
[2];
496 return ptr
[0] | ptr
[1] << 8 | ptr
[2] << 16;
500 return *((Uint32
*)pSurface
->pixels
+ y
* pSurface
->pitch
/ sizeof(Uint32
) + x
);
503 return 0; /* shouldn't happen, but avoids warnings */
507 /**************************************************************************
509 Return the pixel value at (0, 0)
510 NOTE: The surface must be locked before calling this!
511 **************************************************************************/
512 Uint32
get_first_pixel(SDL_Surface
*pSurface
)
518 switch (pSurface
->format
->BytesPerPixel
) {
520 return *((Uint8
*)pSurface
->pixels
);
523 return *((Uint16
*)pSurface
->pixels
);
527 if (SDL_BYTEORDER
== SDL_BIG_ENDIAN
) {
528 return (((Uint8
*)pSurface
->pixels
)[0] << 16)
529 | (((Uint8
*)pSurface
->pixels
)[1] << 8)
530 | ((Uint8
*)pSurface
->pixels
)[2];
532 return ((Uint8
*)pSurface
->pixels
)[0]
533 | (((Uint8
*)pSurface
->pixels
)[1] << 8)
534 | (((Uint8
*)pSurface
->pixels
)[2] << 16);
538 return *((Uint32
*)pSurface
->pixels
);
541 return 0; /* shouldn't happen, but avoids warnings */
545 /* ===================================================================== */
547 /**************************************************************************
548 initialize sdl with Flags
549 **************************************************************************/
550 void init_sdl(int iFlags
)
558 Main
.dummy
= NULL
; /* can't create yet -- hope we don't need it */
559 Main
.rects_count
= 0;
562 if (SDL_WasInit(SDL_INIT_AUDIO
)) {
563 error
= (SDL_InitSubSystem(iFlags
) < 0);
565 error
= (SDL_Init(iFlags
) < 0);
568 log_fatal(_("Unable to initialize SDL2 library: %s"), SDL_GetError());
574 /* Initialize the TTF library */
575 if (TTF_Init() < 0) {
576 log_fatal(_("Unable to initialize SDL2_ttf library: %s"), SDL_GetError());
583 /**************************************************************************
585 **************************************************************************/
589 gui_layer_destroy(&Main
.gui
);
590 FREESURFACE(Main
.map
);
591 FREESURFACE(Main
.dummy
);
594 /**************************************************************************
595 Switch to passed video mode.
596 **************************************************************************/
597 int set_video_mode(int iWidth
, int iHeight
, int iFlags
)
601 Main
.screen
= SDL_CreateWindow(_("SDL2 Client for Freeciv"),
602 SDL_WINDOWPOS_UNDEFINED
,
603 SDL_WINDOWPOS_UNDEFINED
,
607 main_surface
= SDL_CreateRGBSurface(0, iWidth
, iHeight
, 32,
608 #if SDL_BYTEORDER != SDL_LIL_ENDIAN
609 0x0000FF00, 0x00FF0000, 0xFF000000, 0x000000FF
611 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000
615 Main
.map
= SDL_CreateRGBSurface(0, iWidth
, iHeight
, 32,
616 #if SDL_BYTEORDER != SDL_LIL_ENDIAN
617 0x0000FF00, 0x00FF0000, 0xFF000000, 0x000000FF
619 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000
623 if (gui_options
.gui_sdl2_swrenderer
) {
624 flags
= SDL_RENDERER_SOFTWARE
;
629 Main
.renderer
= SDL_CreateRenderer(Main
.screen
, -1, flags
);
631 Main
.maintext
= SDL_CreateTexture(Main
.renderer
,
632 SDL_PIXELFORMAT_ARGB8888
,
633 SDL_TEXTUREACCESS_STREAMING
,
638 int iDepth
= SDL_GetVideoInfo()->vfmt
->BitsPerPixel
;
640 /* if screen does exist check if this is mayby
641 exactly the same resolution then return 1 */
643 if (Main
.screen
->w
== iWidth
&& Main
.screen
->h
== iHeight
) {
644 if ((Main
.screen
->flags
& SDL_FULLSCREEN
)
645 && (iFlags
& SDL_FULLSCREEN
)) {
651 /* Check to see if a particular video mode is supported */
652 if ((iDepth
= SDL_VideoModeOK(iWidth
, iHeight
, iDepth
, iFlags
)) == 0) {
653 log_error(_("No available mode for this resolution : %d x %d %d bpp"),
654 iWidth
, iHeight
, iDepth
);
656 log_debug(_("Setting default resolution to : 640 x 480 16 bpp SW"));
658 Main
.screen
= SDL_SetVideoMode(640, 480, 16, SDL_SWSURFACE
);
659 } else { /* set video mode */
660 if ((Main
.screen
= SDL_SetVideoMode(iWidth
, iHeight
,
661 iDepth
, iFlags
)) == NULL
) {
662 log_error(_("Unable to set this resolution: %d x %d %d bpp %s"),
663 iWidth
, iHeight
, iDepth
, SDL_GetError());
668 log_debug(_("Setting resolution to: %d x %d %d bpp"),
669 iWidth
, iHeight
, iDepth
);
672 /* Create a dummy surface to be used when sprites are missing, etc.
673 * Various things (such as zoomSurfaceRGBA() don't cope well with a
674 * zero-sized surface, so we use a transparent 1x1 surface. */
675 FREESURFACE(Main
.dummy
);
676 Main
.dummy
= create_surf(1, 1, SDL_SWSURFACE
);
678 FREESURFACE(Main
.map
);
679 Main
.map
= SDL_DisplayFormat(Main
.screen
);
684 FREESURFACE(Main
.gui
->surface
);
685 Main
.gui
->surface
= create_surf(iWidth
, iHeight
, SDL_SWSURFACE
);
687 Main
.gui
= add_gui_layer(iWidth
, iHeight
);
690 clear_surface(Main
.gui
->surface
, NULL
);
695 /**************************************************************************
696 Render from main surface with screen renderer.
697 **************************************************************************/
698 void update_main_screen(void)
701 SDL_UpdateTexture(Main
.maintext
, NULL
,
702 main_surface
->pixels
, main_surface
->pitch
);
703 SDL_RenderClear(Main
.renderer
);
704 SDL_RenderCopy(Main
.renderer
, Main
.maintext
, NULL
, NULL
);
705 SDL_RenderPresent(Main
.renderer
);
707 render_dirty
= FALSE
;
711 /**************************************************************************
712 Return width of the main window
713 **************************************************************************/
714 int main_window_width(void)
716 return main_surface
->w
;
719 /**************************************************************************
720 Return height of the main window
721 **************************************************************************/
722 int main_window_height(void)
724 return main_surface
->h
;
727 /**************************************************************************
728 Fill Rect with RGBA color
729 **************************************************************************/
730 #define MASK565 0xf7de
731 #define MASK555 0xfbde
733 /* 50% alpha (128) */
734 #define BLEND16_50( d, s , mask ) \
735 (((( s & mask ) + ( d & mask )) >> 1) + ( s & d & ( ~mask & 0xffff)))
737 #define BLEND2x16_50( d, s , mask ) \
738 (((( s & (mask | mask << 16)) + ( d & ( mask | mask << 16 ))) >> 1) + \
739 ( s & d & ( ~(mask | mask << 16))))
741 /**************************************************************************
742 Fill rectangle for "565" format surface
743 **************************************************************************/
744 static int __FillRectAlpha565(SDL_Surface
*pSurface
, SDL_Rect
*pRect
,
750 register Uint32 D
, S
=
751 SDL_MapRGB(pSurface
->format
, pColor
->r
, pColor
->g
, pColor
->b
);
752 register Uint32 A
= pColor
->a
>> 3;
758 end
= pSurface
->w
* pSurface
->h
;
759 pixel
= pSurface
->pixels
;
760 if (A
== 16) { /* A == 128 >> 3 */
761 /* this code don't work (A == 128) */
762 if (end
& 0x1) { /* end % 2 */
764 *pixel
++ = BLEND16_50(D
, S
, MASK565
);
769 for (y
= 0; y
< end
; y
+= 2) {
770 D
= *(Uint32
*) pixel
;
771 *(Uint32
*) pixel
= BLEND2x16_50(D
, S
, MASK565
);
775 S
= (S
| S
<< 16) & 0x07e0f81f;
779 D
= (D
| D
<< 16) & 0x07e0f81f;
780 D
+= (S
- D
) * A
>> 5;
782 *pixel
++ = (D
| (D
>> 16)) & 0xFFFF;
786 /* correct pRect size */
788 pRect
->w
+= pRect
->x
;
791 if (pRect
->x
>= pSurface
->w
- pRect
->w
) {
792 pRect
->w
= pSurface
->w
- pRect
->x
;
797 pRect
->h
+= pRect
->y
;
800 if (pRect
->y
>= pSurface
->h
- pRect
->h
) {
801 pRect
->h
= pSurface
->h
- pRect
->y
;
805 start
= pixel
= (Uint32
*) pSurface
->pixels
+
806 (pRect
->y
* pSurface
->pitch
) + pRect
->x
/ 2;
808 if (A
== 16) { /* A == 128 >> 3 */
809 /* this code don't work (A == 128) */
811 for (y
= 0; y
< pRect
->h
; y
++) {
814 if (pRect
->w
& 0x1) {
816 *pixel
++ = BLEND16_50(D
, (S
& 0xFFFF), MASK565
);
820 for (; end
< pRect
->w
; end
+= 2) {
821 D
= *(Uint32
*) pixel
;
822 *(Uint32
*) pixel
= BLEND2x16_50(D
, S
, MASK565
);
826 pixel
= start
+ pSurface
->pitch
;
831 S
= (S
| S
<< 16) & 0x07e0f81f;
839 D
= (D
| D
<< 16) & 0x07e0f81f;
840 D
+= (S
- D
) * A
>> 5;
842 *pixel
++ = (D
| (D
>> 16)) & 0xFFFF;
845 pixel
= start
+ pSurface
->pitch
;
852 unlock_surf(pSurface
);
856 /**************************************************************************
857 Fill rectangle for "555" format surface
858 **************************************************************************/
859 static int __FillRectAlpha555(SDL_Surface
*pSurface
, SDL_Rect
*pRect
,
863 Uint32
*start
, *pixel
;
864 register Uint32 D
, S
=
865 SDL_MapRGB(pSurface
->format
, pColor
->r
, pColor
->g
, pColor
->b
);
866 register Uint32 A
= pColor
->a
>> 3;
873 end
= pSurface
->w
* pSurface
->h
;
874 pixel
= pSurface
->pixels
;
875 if (A
== 16) { /* A == 128 >> 3 */
878 *pixel
++ = BLEND16_50(D
, S
, MASK555
);
883 for (y
= 0; y
< end
; y
+= 2) {
885 *pixel
= BLEND2x16_50(D
, S
, MASK555
);
889 S
= (S
| S
<< 16) & 0x03e07c1f;
893 D
= (D
| D
<< 16) & 0x03e07c1f;
894 D
+= (S
- D
) * A
>> 5;
896 *pixel
++ = (D
| (D
>> 16)) & 0xFFFF;
900 /* correct pRect size */
902 pRect
->w
+= pRect
->x
;
905 if (pRect
->x
>= pSurface
->w
- pRect
->w
) {
906 pRect
->w
= pSurface
->w
- pRect
->x
;
911 pRect
->h
+= pRect
->y
;
914 if (pRect
->y
>= pSurface
->h
- pRect
->h
) {
915 pRect
->h
= pSurface
->h
- pRect
->y
;
919 start
= pixel
= (Uint32
*) pSurface
->pixels
+
920 (pRect
->y
* pSurface
->pitch
) + pRect
->x
/ 2;
922 if (A
== 16) { /* A == 128 >> 3 */
924 for (y
= 0; y
< pRect
->h
; y
++) {
927 if (pRect
->w
& 0x1) {
929 *pixel
++ = BLEND16_50(D
, (S
& 0xFFFF), MASK555
);
933 for (; end
< pRect
->w
; end
+= 2) {
934 D
= *(Uint32
*) pixel
;
935 *(Uint32
*) pixel
= BLEND2x16_50(D
, S
, MASK555
);
939 pixel
= start
+ pSurface
->pitch
;
944 S
= (S
| S
<< 16) & 0x03e07c1f;
952 D
= (D
| D
<< 16) & 0x03e07c1f;
953 D
+= (S
- D
) * A
>> 5;
955 *pixel
++ = (D
| (D
>> 16)) & 0xFFFF;
958 pixel
= start
+ pSurface
->pitch
;
964 unlock_surf(pSurface
);
968 /**************************************************************************
969 Fill rectangle for 32bit "8888" format surface
970 **************************************************************************/
971 static int __FillRectAlpha8888_32bit(SDL_Surface
*pSurface
, SDL_Rect
*pRect
,
974 register Uint32 A
= pColor
->a
;
975 register Uint32 dSIMD1
, dSIMD2
;
976 register Uint32 sSIMD1
, sSIMD2
= SDL_MapRGB(pSurface
->format
,
977 pColor
->r
, pColor
->g
,
979 Uint32 y
, end
, A_Dst
, A_Mask
= pSurface
->format
->Amask
;
980 Uint32
*start
, *pixel
;
982 sSIMD1
= sSIMD2
& 0x00FF00FF;
987 end
= pSurface
->w
* pSurface
->h
;
988 pixel
= (Uint32
*) pSurface
->pixels
;
989 if (A
== 128) { /* 50% A */
993 A_Dst
= dSIMD2
& A_Mask
;
994 *pixel
++ = ((((sSIMD2
& 0x00fefefe) + (dSIMD2
& 0x00fefefe)) >> 1)
995 + (sSIMD2
& dSIMD2
& 0x00010101)) | A_Dst
;
999 sSIMD2
= sSIMD2
>> 8 | sSIMD2
<< 8;
1003 A_Dst
= dSIMD2
& A_Mask
;
1004 dSIMD1
= dSIMD2
& 0x00FF00FF;
1005 dSIMD1
+= (sSIMD1
- dSIMD1
) * A
>> 8;
1006 dSIMD1
&= 0x00FF00FF;
1008 dSIMD2
+= (((sSIMD2
<< 8) & 0xFF00) - dSIMD2
) * A
>> 8;
1010 *pixel
++ = dSIMD1
| dSIMD2
| A_Dst
;
1013 A_Dst
= dSIMD1
& A_Mask
;
1014 dSIMD1
&= 0x00FF00FF;
1015 dSIMD1
+= (sSIMD1
- dSIMD1
) * A
>> 8;
1016 dSIMD1
&= 0x00FF00FF;
1018 dSIMD2
= ((*pixel
& 0xFF00) >> 8)| ((pixel
[1] & 0xFF00) << 8);
1019 dSIMD2
+= (sSIMD2
- dSIMD2
) * A
>> 8;
1020 dSIMD2
&= 0x00FF00FF;
1022 *pixel
++ = dSIMD1
| ((dSIMD2
<< 8) & 0xFF00) | A_Dst
;
1025 A_Dst
= dSIMD1
& A_Mask
;
1026 dSIMD1
&= 0x00FF00FF;
1027 dSIMD1
+= (sSIMD1
- dSIMD1
) * A
>> 8;
1028 dSIMD1
&= 0x00FF00FF;
1030 *pixel
++ = dSIMD1
| ((dSIMD2
>> 8) & 0xFF00) | A_Dst
;
1034 /* correct pRect size */
1036 pRect
->w
+= pRect
->x
;
1039 if (pRect
->x
>= pSurface
->w
- pRect
->w
) {
1040 pRect
->w
= pSurface
->w
- pRect
->x
;
1045 pRect
->h
+= pRect
->y
;
1048 if (pRect
->y
>= pSurface
->h
- pRect
->h
) {
1049 pRect
->h
= pSurface
->h
- pRect
->y
;
1053 start
= pixel
= (Uint32
*) pSurface
->pixels
+
1054 (pRect
->y
* (pSurface
->pitch
>> 2)) + pRect
->x
;
1056 if (A
== 128) { /* 50% A */
1063 A_Dst
= dSIMD2
& A_Mask
;
1064 *pixel
++ = ((((sSIMD2
& 0x00fefefe) + (dSIMD2
& 0x00fefefe)) >> 1)
1065 + (sSIMD2
& dSIMD2
& 0x00010101)) | A_Dst
;
1067 pixel
= start
+ (pSurface
->pitch
>> 2);
1075 sSIMD2
= sSIMD2
>> 8 | sSIMD2
<< 8;
1081 A_Dst
= dSIMD2
& A_Mask
;
1082 dSIMD1
= dSIMD2
& 0x00FF00FF;
1083 dSIMD1
+= (sSIMD1
- dSIMD1
) * A
>> 8;
1084 dSIMD1
&= 0x00FF00FF;
1086 dSIMD2
+= (((sSIMD2
<< 8) & 0xFF00) - dSIMD2
) * A
>> 8;
1088 *pixel
++ = dSIMD1
| dSIMD2
| A_Dst
;
1091 A_Dst
= dSIMD1
& A_Mask
;
1092 dSIMD1
&= 0x00FF00FF;
1093 dSIMD1
+= (sSIMD1
- dSIMD1
) * A
>> 8;
1094 dSIMD1
&= 0x00FF00FF;
1096 dSIMD2
= ((*pixel
& 0xFF00) >> 8)| ((pixel
[1] & 0xFF00) << 8);
1097 dSIMD2
+= (sSIMD2
- dSIMD2
) * A
>> 8;
1098 dSIMD2
&= 0x00FF00FF;
1100 *pixel
++ = dSIMD1
| ((dSIMD2
<< 8) & 0xFF00) | A_Dst
;
1103 A_Dst
= dSIMD1
& A_Mask
;
1104 dSIMD1
&= 0x00FF00FF;
1105 dSIMD1
+= (sSIMD1
- dSIMD1
) * A
>> 8;
1106 dSIMD1
&= 0x00FF00FF;
1108 *pixel
++ = dSIMD1
| ((dSIMD2
>> 8) & 0xFF00) | A_Dst
;
1111 pixel
= start
+ (pSurface
->pitch
>> 2);
1117 unlock_surf(pSurface
);
1121 /**************************************************************************
1122 Fill rectangle for 32bit "888" format surface
1123 **************************************************************************/
1124 static int __FillRectAlpha888_32bit(SDL_Surface
*pSurface
, SDL_Rect
*pRect
,
1127 register Uint32 A
= pColor
->a
;
1128 register Uint32 dSIMD1
, dSIMD2
;
1129 register Uint32 sSIMD1
, sSIMD2
= SDL_MapRGB(pSurface
->format
,
1130 pColor
->r
, pColor
->g
,
1133 Uint32
*start
, *pixel
;
1135 sSIMD1
= sSIMD2
& 0x00FF00FF;
1137 lock_surf(pSurface
);
1139 if (pRect
== NULL
) {
1140 end
= pSurface
->w
* pSurface
->h
;
1141 pixel
= (Uint32
*) pSurface
->pixels
;
1142 if (A
== 128) { /* 50% A */
1143 for (y
= 0; y
< end
; y
++) {
1145 *pixel
++ = ((((sSIMD2
& 0x00fefefe) + (dSIMD2
& 0x00fefefe)) >> 1)
1146 + (sSIMD2
& dSIMD2
& 0x00010101)) | 0xFF000000;
1150 sSIMD2
= sSIMD2
>> 8 | sSIMD2
<< 8;
1154 dSIMD1
= dSIMD2
& 0x00FF00FF;
1155 dSIMD1
+= (sSIMD1
- dSIMD1
) * A
>> 8;
1156 dSIMD1
&= 0x00FF00FF;
1158 dSIMD2
+= (((sSIMD2
<< 8) & 0xFF00) - dSIMD2
) * A
>> 8;
1160 *pixel
++ = dSIMD1
| dSIMD2
| 0xFF000000;
1162 dSIMD1
= *pixel
& 0x00FF00FF;
1163 dSIMD1
+= (sSIMD1
- dSIMD1
) * A
>> 8;
1164 dSIMD1
&= 0x00FF00FF;
1166 dSIMD2
= ((*pixel
& 0xFF00) >> 8)| ((pixel
[1] & 0xFF00) << 8);
1167 dSIMD2
+= (sSIMD2
- dSIMD2
) * A
>> 8;
1168 dSIMD2
&= 0x00FF00FF;
1170 *pixel
++ = dSIMD1
| ((dSIMD2
<< 8) & 0xFF00) | 0xFF000000;
1172 dSIMD1
= *pixel
& 0x00FF00FF;
1173 dSIMD1
+= (sSIMD1
- dSIMD1
) * A
>> 8;
1174 dSIMD1
&= 0x00FF00FF;
1176 *pixel
++ = dSIMD1
| ((dSIMD2
>> 8) & 0xFF00) | 0xFF000000;
1180 /* correct pRect size */
1182 pRect
->w
+= pRect
->x
;
1185 if (pRect
->x
>= pSurface
->w
- pRect
->w
) {
1186 pRect
->w
= pSurface
->w
- pRect
->x
;
1191 pRect
->h
+= pRect
->y
;
1194 if (pRect
->y
>= pSurface
->h
- pRect
->h
) {
1195 pRect
->h
= pSurface
->h
- pRect
->y
;
1199 start
= pixel
= (Uint32
*) pSurface
->pixels
+
1200 (pRect
->y
* (pSurface
->pitch
>> 2)) + pRect
->x
;
1202 if (A
== 128) { /* 50% A */
1204 for (y
= 0; y
< pRect
->h
; y
++) {
1206 for (end
= 0; end
< pRect
->w
; end
++) {
1208 *pixel
++ = ((((sSIMD2
& 0x00fefefe) + (dSIMD2
& 0x00fefefe)) >> 1)
1209 + (sSIMD2
& dSIMD2
& 0x00010101)) | 0xFF000000;
1212 pixel
= start
+ (pSurface
->pitch
>> 2);
1220 sSIMD2
= sSIMD2
>> 8 | sSIMD2
<< 8;
1226 dSIMD1
= dSIMD2
& 0x00FF00FF;
1227 dSIMD1
+= (sSIMD1
- dSIMD1
) * A
>> 8;
1228 dSIMD1
&= 0x00FF00FF;
1230 dSIMD2
+= (((sSIMD2
<< 8) & 0xFF00) - dSIMD2
) * A
>> 8;
1232 *pixel
++ = dSIMD1
| dSIMD2
| 0xFF000000;
1234 dSIMD1
= *pixel
& 0x00FF00FF;
1235 dSIMD1
+= (sSIMD1
- dSIMD1
) * A
>> 8;
1236 dSIMD1
&= 0x00FF00FF;
1238 dSIMD2
= ((*pixel
& 0xFF00) >> 8)| ((pixel
[1] & 0xFF00) << 8);
1239 dSIMD2
+= (sSIMD2
- dSIMD2
) * A
>> 8;
1240 dSIMD2
&= 0x00FF00FF;
1242 *pixel
++ = dSIMD1
| ((dSIMD2
<< 8) & 0xFF00) | 0xFF000000;
1244 dSIMD1
= *pixel
& 0x00FF00FF;
1245 dSIMD1
+= (sSIMD1
- dSIMD1
) * A
>> 8;
1246 dSIMD1
&= 0x00FF00FF;
1248 *pixel
++ = dSIMD1
| ((dSIMD2
>> 8) & 0xFF00) | 0xFF000000;
1251 pixel
= start
+ (pSurface
->pitch
>> 2);
1258 unlock_surf(pSurface
);
1262 /**************************************************************************
1263 Fill rectangle for 24bit "888" format surface
1264 **************************************************************************/
1265 static int __FillRectAlpha888_24bit(SDL_Surface
*pSurface
, SDL_Rect
*pRect
,
1269 Uint8
*start
, *pixel
;
1270 register Uint32 P
, D
, S1
, S2
= SDL_MapRGB(pSurface
->format
,
1271 pColor
->r
, pColor
->g
,
1273 register Uint32 A
= pColor
->a
;
1275 S1
= S2
& 0x00FF00FF;
1279 lock_surf(pSurface
);
1281 if (pRect
== NULL
) {
1282 end
= pSurface
->w
* pSurface
->h
;
1283 pixel
= (Uint8
*) pSurface
->pixels
;
1285 for (y
= 0; y
< end
; y
++) {
1286 D
= (pixel
[0] << 16) + (pixel
[1] << 8) + pixel
[2];
1289 P
+= (S1
- P
) * A
>> 8;
1293 D
+= (S2
- D
) * A
>> 8;
1298 /* Fix me to little - big EDIAN */
1300 pixel
[0] = P
& 0xff;
1301 pixel
[1] = (P
>> 8) & 0xff;
1302 pixel
[2] = (P
>> 16) & 0xff;
1308 /* correct pRect size */
1310 pRect
->w
+= pRect
->x
;
1313 if (pRect
->x
>= pSurface
->w
- pRect
->w
) {
1314 pRect
->w
= pSurface
->w
- pRect
->x
;
1319 pRect
->h
+= pRect
->y
;
1322 if (pRect
->y
>= pSurface
->h
- pRect
->h
) {
1323 pRect
->h
= pSurface
->h
- pRect
->y
;
1327 end
= pRect
->w
* pRect
->h
;
1328 start
= pixel
= (Uint8
*) pSurface
->pixels
+
1329 (pRect
->y
* pSurface
->pitch
) + pRect
->x
* 3;
1332 while (y
!= pRect
->h
) {
1333 D
= (pixel
[0] << 16) + (pixel
[1] << 8) + pixel
[2];
1336 P
+= (S1
- P
) * A
>> 8;
1340 D
+= (S2
- D
) * A
>> 8;
1345 /* Fix me to little - big EDIAN */
1347 pixel
[0] = P
& 0xff;
1348 pixel
[1] = (P
>> 8) & 0xff;
1349 pixel
[2] = (P
>> 16) & 0xff;
1351 if ((pixel
- start
) == (pRect
->w
* 3)) {
1352 pixel
= start
+ pSurface
->pitch
;
1361 unlock_surf(pSurface
);
1366 /**************************************************************************
1367 Fill rectangle with color with alpha channel.
1368 **************************************************************************/
1369 int fill_rect_alpha(SDL_Surface
*pSurface
, SDL_Rect
*pRect
,
1372 if (pRect
&& (pRect
->x
< - pRect
->w
|| pRect
->x
>= pSurface
->w
1373 || pRect
->y
< - pRect
->h
|| pRect
->y
>= pSurface
->h
)) {
1377 if (pColor
->a
== 255) {
1378 return SDL_FillRect(pSurface
, pRect
,
1379 SDL_MapRGB(pSurface
->format
, pColor
->r
, pColor
->g
, pColor
->b
));
1386 switch (pSurface
->format
->BytesPerPixel
) {
1392 if (pSurface
->format
->Gmask
== 0x7E0) {
1393 return __FillRectAlpha565(pSurface
, pRect
, pColor
);
1395 if (pSurface
->format
->Gmask
== 0x3E0) {
1396 return __FillRectAlpha555(pSurface
, pRect
, pColor
);
1404 return __FillRectAlpha888_24bit(pSurface
, pRect
, pColor
);
1407 if (pSurface
->format
->Amask
) {
1408 return __FillRectAlpha8888_32bit(pSurface
, pRect
, pColor
);
1410 return __FillRectAlpha888_32bit(pSurface
, pRect
, pColor
);
1417 /**************************************************************************
1418 Make rectangle region sane. Return TRUE if result is sane.
1419 **************************************************************************/
1420 bool correct_rect_region(SDL_Rect
*pRect
)
1422 int ww
= pRect
->w
, hh
= pRect
->h
;
1434 if (pRect
->x
+ ww
> main_window_width()) {
1435 ww
= main_window_width() - pRect
->x
;
1438 if (pRect
->y
+ hh
> main_window_height()) {
1439 hh
= main_window_height() - pRect
->y
;
1442 /* End Correction */
1444 if (ww
<= 0 || hh
<= 0) {
1445 return FALSE
; /* suprise :) */
1454 /**************************************************************************
1455 Return whether coordinates are in rectangle.
1456 **************************************************************************/
1457 bool is_in_rect_area(int x
, int y
, SDL_Rect rect
)
1459 return ((x
>= rect
.x
) && (x
< rect
.x
+ rect
.w
)
1460 && (y
>= rect
.y
) && (y
< rect
.y
+ rect
.h
));
1463 /**************************************************************************
1464 Most black color is coded like {0,0,0,255} but in sdl if alpha is turned
1465 off and colorkey is set to 0 this black color is transparent.
1466 To fix this we change all black {0, 0, 0, 255} to newblack {4, 4, 4, 255}
1467 (first collor != 0 in 16 bit coding).
1468 **************************************************************************/
1469 bool correct_black(SDL_Surface
*pSrc
)
1475 if (pSrc
->format
->BitsPerPixel
== 32 && pSrc
->format
->Amask
) {
1476 register Uint32 alpha
, *pPixels
= (Uint32
*) pSrc
->pixels
;
1477 Uint32 Amask
= pSrc
->format
->Amask
;
1478 Uint32 black
= SDL_MapRGBA(pSrc
->format
, 0, 0, 0, 255);
1479 Uint32 new_black
= SDL_MapRGBA(pSrc
->format
, 4, 4, 4, 255);
1480 int end
= pSrc
->w
* pSrc
->h
;
1482 /* for 32 bit color coding */
1486 for (x
= 0; x
< end
; x
++, pPixels
++) {
1487 if (*pPixels
== black
) {
1488 *pPixels
= new_black
;
1491 alpha
= *pPixels
& Amask
;
1492 if (alpha
&& (alpha
!= Amask
)) {
1501 if (pSrc
->format
->BitsPerPixel
== 8 && pSrc
->format
->palette
) {
1502 for(x
= 0; x
< pSrc
->format
->palette
->ncolors
; x
++) {
1503 if (x
!= pSrc
->format
->colorkey
&&
1504 pSrc
->format
->palette
->colors
[x
].r
< 4 &&
1505 pSrc
->format
->palette
->colors
[x
].g
< 4 &&
1506 pSrc
->format
->palette
->colors
[x
].b
< 4) {
1507 pSrc
->format
->palette
->colors
[x
].r
= 4;
1508 pSrc
->format
->palette
->colors
[x
].g
= 4;
1509 pSrc
->format
->palette
->colors
[x
].b
= 4;
1521 /* ===================================================================== */
1523 /**************************************************************************
1524 Get visible rectangle from surface.
1525 **************************************************************************/
1526 SDL_Rect
get_smaller_surface_rect(SDL_Surface
*pSurface
)
1530 Uint16 minX
, maxX
, minY
, maxY
;
1533 fc_assert(pSurface
!= NULL
);
1539 SDL_GetColorKey(pSurface
, &colorkey
);
1541 lock_surf(pSurface
);
1543 switch(pSurface
->format
->BytesPerPixel
) {
1546 Uint8
*pixel
= (Uint8
*)pSurface
->pixels
;
1547 Uint8
*start
= pixel
;
1554 if (*pixel
!= colorkey
) {
1570 pixel
= start
+ pSurface
->pitch
;
1578 pixel
= (Uint8
*)((Uint8
*)pSurface
->pixels
+ (y
* pSurface
->pitch
) + x
);
1582 if (*pixel
!= colorkey
) {
1598 pixel
= start
- pSurface
->pitch
;
1605 Uint16
*pixel
= (Uint16
*)pSurface
->pixels
;
1606 Uint16
*start
= pixel
;
1614 if (*pixel
!= colorkey
) {
1630 pixel
= start
+ pSurface
->pitch
/ 2;
1638 pixel
= ((Uint16
*)pSurface
->pixels
+ (y
* pSurface
->pitch
/ 2) + x
);
1642 if (*pixel
!= colorkey
) {
1658 pixel
= start
- pSurface
->pitch
/ 2;
1665 Uint8
*pixel
= (Uint8
*)pSurface
->pixels
;
1666 Uint8
*start
= pixel
;
1675 if (SDL_BYTEORDER
== SDL_BIG_ENDIAN
) {
1676 color
= (pixel
[0] << 16 | pixel
[1] << 8 | pixel
[2]);
1678 color
= (pixel
[0] | pixel
[1] << 8 | pixel
[2] << 16);
1680 if (color
!= colorkey
) {
1696 pixel
= start
+ pSurface
->pitch
/ 3;
1704 pixel
= (Uint8
*)((Uint8
*)pSurface
->pixels
+ (y
* pSurface
->pitch
) + x
* 3);
1708 if (SDL_BYTEORDER
== SDL_BIG_ENDIAN
) {
1709 color
= (pixel
[0] << 16 | pixel
[1] << 8 | pixel
[2]);
1711 color
= (pixel
[0] | pixel
[1] << 8 | pixel
[2] << 16);
1713 if (color
!= colorkey
) {
1729 pixel
= start
- pSurface
->pitch
/ 3;
1736 Uint32
*pixel
= (Uint32
*)pSurface
->pixels
;
1737 Uint32
*start
= pixel
;
1745 if (*pixel
!= colorkey
) {
1761 pixel
= start
+ pSurface
->pitch
/ 4;
1769 pixel
= ((Uint32
*)pSurface
->pixels
+ (y
* pSurface
->pitch
/ 4) + x
);
1773 if (*pixel
!= colorkey
) {
1789 pixel
= start
- pSurface
->pitch
/ 4;
1796 unlock_surf(pSurface
);
1799 src
.w
= maxX
- minX
+ 1;
1800 src
.h
= maxY
- minY
+ 1;
1805 /**************************************************************************
1806 Create new surface that is just visible part of source surface.
1807 **************************************************************************/
1808 SDL_Surface
*crop_visible_part_from_surface(SDL_Surface
*pSrc
)
1810 SDL_Rect src
= get_smaller_surface_rect(pSrc
);
1812 return crop_rect_from_surface(pSrc
, &src
);
1815 /**************************************************************************
1817 **************************************************************************/
1818 SDL_Surface
*ResizeSurface(const SDL_Surface
*pSrc
, Uint16 new_width
,
1819 Uint16 new_height
, int smooth
)
1825 return zoomSurface((SDL_Surface
*)pSrc
,
1826 (double)new_width
/ pSrc
->w
,
1827 (double)new_height
/ pSrc
->h
,
1831 /**************************************************************************
1832 Resize a surface to fit into a box with the dimensions 'new_width' and a
1833 'new_height'. If 'scale_up' is FALSE, a surface that already fits into
1834 the box will not be scaled up to the boundaries of the box.
1835 If 'absolute_dimensions' is TRUE, the function returns a surface with the
1836 dimensions of the box and the scaled/original surface centered in it.
1837 **************************************************************************/
1838 SDL_Surface
*ResizeSurfaceBox(const SDL_Surface
*pSrc
,
1839 Uint16 new_width
, Uint16 new_height
, int smooth
,
1840 bool scale_up
, bool absolute_dimensions
)
1842 SDL_Surface
*tmpSurface
, *result
;
1848 if (!((scale_up
== FALSE
) && ((new_width
>= pSrc
->w
) && (new_height
>= pSrc
->h
)))) {
1849 if ((new_width
- pSrc
->w
) <= (new_height
- pSrc
->h
)) {
1850 /* horizontal limit */
1851 tmpSurface
= zoomSurface((SDL_Surface
*)pSrc
,
1852 (double)new_width
/ pSrc
->w
,
1853 (double)new_width
/ pSrc
->w
,
1856 /* vertical limit */
1857 tmpSurface
= zoomSurface((SDL_Surface
*)pSrc
,
1858 (double)new_height
/ pSrc
->h
,
1859 (double)new_height
/ pSrc
->h
,
1863 tmpSurface
= zoomSurface((SDL_Surface
*)pSrc
,
1869 if (absolute_dimensions
) {
1871 (new_width
- tmpSurface
->w
) / 2,
1872 (new_height
- tmpSurface
->h
) / 2,
1876 result
= create_surf(new_width
, new_height
, SDL_SWSURFACE
);
1877 alphablit(tmpSurface
, NULL
, result
, &area
, 255);
1878 FREESURFACE(tmpSurface
);
1880 result
= tmpSurface
;
1886 /**************************************************************************
1887 Return copy of the surface
1888 **************************************************************************/
1889 SDL_Surface
*copy_surface(SDL_Surface
*src
)
1893 dst
= SDL_CreateRGBSurface(0, src
->w
, src
->h
, src
->format
->BitsPerPixel
,
1894 src
->format
->Rmask
, src
->format
->Gmask
,
1895 src
->format
->Bmask
, src
->format
->Amask
);
1897 SDL_BlitSurface(src
, NULL
, dst
, NULL
);
1902 /* ============ Freeciv game graphics function =========== */
1904 /**************************************************************************
1905 Return whether the client supports given view type
1906 **************************************************************************/
1907 bool is_view_supported(enum ts_type type
)
1918 /**************************************************************************
1919 Load intro sprites. Not used in SDL-client.
1920 **************************************************************************/
1921 void load_intro_gfx(void)
1926 /**************************************************************************
1927 Frees the introductory sprites.
1928 **************************************************************************/
1929 void free_intro_radar_sprites(void)
1934 /**************************************************************************
1935 Create colored frame
1936 **************************************************************************/
1937 void create_frame(SDL_Surface
*dest
, Sint16 left
, Sint16 top
,
1938 Sint16 width
, Sint16 height
,
1941 struct color gsdl2_color
= { .color
= pcolor
};
1942 struct sprite
*vertical
= create_sprite(1, height
, &gsdl2_color
);
1943 struct sprite
*horizontal
= create_sprite(width
, 1, &gsdl2_color
);
1944 SDL_Rect tmp
,dst
= { left
, top
, 0, 0 };
1947 alphablit(vertical
->psurface
, NULL
, dest
, &tmp
, 255);
1951 alphablit(vertical
->psurface
, NULL
, dest
, &tmp
, 255);
1955 alphablit(horizontal
->psurface
, NULL
, dest
, &tmp
, 255);
1957 dst
.y
+= height
- 1;
1959 alphablit(horizontal
->psurface
, NULL
, dest
, &tmp
, 255);
1961 free_sprite(horizontal
);
1962 free_sprite(vertical
);
1965 /**************************************************************************
1966 Create single colored line
1967 **************************************************************************/
1968 void create_line(SDL_Surface
*dest
, Sint16 x0
, Sint16 y0
, Sint16 x1
, Sint16 y1
,
1971 int xl
= x0
< x1
? x0
: x1
;
1972 int xr
= x0
< x1
? x1
: x0
;
1973 int yt
= y0
< y1
? y0
: y1
;
1974 int yb
= y0
< y1
? y1
: y0
;
1975 int w
= (xr
- xl
) + 1;
1976 int h
= (yb
- yt
) + 1;
1978 SDL_Rect dst
= { xl
, yt
, w
, h
};
1980 struct color gsdl2_color
;
1981 int l
= MAX((xr
- xl
) + 1, (yb
- yt
) + 1);
1984 pcol
= fc_malloc(sizeof(pcol
));
1985 pcol
->r
= pcolor
->r
;
1986 pcol
->g
= pcolor
->g
;
1987 pcol
->b
= pcolor
->b
;
1988 pcol
->a
= 0; /* Fill with transparency */
1990 gsdl2_color
.color
= pcol
;
1991 spr
= create_sprite(w
, h
, &gsdl2_color
);
1993 lock_surf(spr
->psurface
);
1995 /* Set off transparency from pixels belonging to the line */
1996 if ((x0
<= x1
&& y0
<= y1
)
1997 || (x1
<= x0
&& y1
<= y0
)) {
1998 for (i
= 0; i
< l
; i
++) {
1999 int cx
= (xr
- xl
) * i
/ l
;
2000 int cy
= (yb
- yt
) * i
/ l
;
2002 *((Uint32
*)spr
->psurface
->pixels
+ spr
->psurface
->w
* cy
+ cx
)
2003 |= (pcolor
->a
<< spr
->psurface
->format
->Ashift
);
2006 for (i
= 0; i
< l
; i
++) {
2007 int cx
= (xr
- xl
) * i
/ l
;
2008 int cy
= yb
- (yb
- yt
) * i
/ l
;
2010 *((Uint32
*)spr
->psurface
->pixels
+ spr
->psurface
->w
* cy
+ cx
)
2011 |= (pcolor
->a
<< spr
->psurface
->format
->Ashift
);
2015 unlock_surf(spr
->psurface
);
2017 alphablit(spr
->psurface
, NULL
, dest
, &dst
, 255);