Freeciv-3.1
Loading...
Searching...
No Matches
graphics.c
Go to the documentation of this file.
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)
6 any later version.
7
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***********************************************************************/
13
14/***********************************************************************
15 graphics.c - description
16 -------------------
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***********************************************************************/
23
24#ifdef HAVE_CONFIG_H
25#include <fc_config.h>
26#endif
27
28/* SDL2 */
29#ifdef SDL2_PLAIN_INCLUDE
30#include <SDL_image.h>
31#include <SDL_ttf.h>
32#else /* SDL2_PLAIN_INCLUDE */
33#include <SDL2/SDL_image.h>
34#include <SDL2/SDL_ttf.h>
35#endif /* SDL2_PLAIN_INCLUDE */
36
37/* utility */
38#include "fcintl.h"
39#include "log.h"
40
41/* client */
42#include "tilespec.h"
43
44/* gui-sdl2 */
45#include "colors.h"
46#include "gui_tilespec.h"
47#include "mapview.h"
48#include "themebackgrounds.h"
49#include "themespec.h"
50
51#include "graphics.h"
52
53/* ------------------------------ */
54
56
57static SDL_Surface *main_surface = NULL;
58
59static bool render_dirty = TRUE;
60
61/**********************************************************************/
64struct gui_layer *gui_layer_new(int x, int y, SDL_Surface *surface)
65{
66 struct gui_layer *result;
67
68 result = fc_calloc(1, sizeof(struct gui_layer));
69
70 result->dest_rect = (SDL_Rect){x, y, 0, 0};
71 result->surface = surface;
72
73 return result;
74}
75
76/**********************************************************************/
80{
81 FREESURFACE((*gui_layer)->surface);
83}
84
85/**********************************************************************/
88struct gui_layer *get_gui_layer(SDL_Surface *surface)
89{
90 int i = 0;
91
92 while ((i < main_data.guis_count) && main_data.guis[i]) {
93 if (main_data.guis[i]->surface == surface) {
94 return main_data.guis[i];
95 }
96 i++;
97 }
98
99 return NULL;
100}
101
102/**********************************************************************/
111{
112 struct gui_layer *gui_layer = NULL;
113 SDL_Surface *buffer;
114
115 buffer = create_surf(width, height, SDL_SWSURFACE);
116 gui_layer = gui_layer_new(0, 0, buffer);
117
118 /* add to buffers array */
119 if (main_data.guis) {
120 int i;
121
122 /* find NULL element */
123 for (i = 0; i < main_data.guis_count; i++) {
124 if (!main_data.guis[i]) {
126 return gui_layer;
127 }
128 }
131 main_data.guis_count * sizeof(struct gui_layer *));
133 } else {
134 main_data.guis = fc_calloc(1, sizeof(struct gui_layer *));
137 }
138
139 return gui_layer;
140}
141
142/**********************************************************************/
147{
148 int i;
149
150 for (i = 0; i < main_data.guis_count - 1; i++) {
151 if (main_data.guis[i] && (main_data.guis[i] == gui_layer)) {
153 main_data.guis[i] = main_data.guis[i + 1];
154 main_data.guis[i + 1] = NULL;
155 } else {
156 if (!main_data.guis[i]) {
157 main_data.guis[i] = main_data.guis[i + 1];
158 main_data.guis[i + 1] = NULL;
159 }
160 }
161 }
162
165 }
166}
167
168/**********************************************************************/
172 SDL_Rect *dest_rect)
173{
174 if (gui_layer) {
177 }
178}
179
180/**********************************************************************/
184 SDL_Rect *dest_rect)
185{
186 if (gui_layer) {
189 }
190}
191
192/* ============ Freeciv sdl graphics function =========== */
193
194/**********************************************************************/
197int alphablit(SDL_Surface *src, SDL_Rect *srcrect,
198 SDL_Surface *dst, SDL_Rect *dstrect,
199 unsigned char alpha_mod)
200{
201 int ret;
202
203 if (src == NULL || dst == NULL) {
204 return 1;
205 }
206
207 SDL_SetSurfaceAlphaMod(src, alpha_mod);
208
209 ret = SDL_BlitSurface(src, srcrect, dst, dstrect);
210
211 if (ret) {
212 log_error("SDL_BlitSurface() fails: %s", SDL_GetError());
213 }
214
215 return ret;
216}
217
218/**********************************************************************/
221int screen_blit(SDL_Surface *src, SDL_Rect *srcrect, SDL_Rect *dstrect,
222 unsigned char alpha_mod)
223{
225
226 return alphablit(src, srcrect, main_surface, dstrect, alpha_mod);
227}
228
229/**********************************************************************/
234SDL_Surface *crop_rect_from_surface(SDL_Surface *psource,
235 SDL_Rect *prect)
236{
237 SDL_Surface *new_surf = create_surf_with_format(psource->format,
238 prect ? prect->w : psource->w,
239 prect ? prect->h : psource->h,
240 SDL_SWSURFACE);
241
242 if (alphablit(psource, prect, new_surf, NULL, 255) != 0) {
243 FREESURFACE(new_surf);
244
245 return NULL;
246 }
247
248 return new_surf;
249}
250
251/**********************************************************************/
260SDL_Surface *mask_surface(SDL_Surface *src, SDL_Surface *mask,
261 int mask_offset_x, int mask_offset_y)
262{
263 SDL_Surface *dest = NULL;
264 int row, col;
265 Uint32 *src_pixel = NULL;
266 Uint32 *dest_pixel = NULL;
267 Uint32 *mask_pixel = NULL;
268 unsigned char src_alpha, mask_alpha;
269
270 dest = copy_surface(src);
271
272 lock_surf(src);
273 lock_surf(mask);
274 lock_surf(dest);
275
276 src_pixel = (Uint32 *)src->pixels;
277 dest_pixel = (Uint32 *)dest->pixels;
278
279 for (row = 0; row < src->h; row++) {
280 mask_pixel = (Uint32 *)mask->pixels
281 + mask->w * (row + mask_offset_y)
282 + mask_offset_x;
283
284 for (col = 0; col < src->w; col++) {
285 src_alpha = (*src_pixel & src->format->Amask) >> src->format->Ashift;
286 mask_alpha = (*mask_pixel & mask->format->Amask) >> mask->format->Ashift;
287
288 *dest_pixel = (*src_pixel & ~src->format->Amask)
289 | (((src_alpha * mask_alpha) / 255) << dest->format->Ashift);
290
291 src_pixel++; dest_pixel++; mask_pixel++;
292 }
293 }
294
295 unlock_surf(dest);
296 unlock_surf(mask);
297 unlock_surf(src);
298
299 return dest;
300}
301
302/**********************************************************************/
305SDL_Surface *load_surf(const char *fname)
306{
307 SDL_Surface *buf;
308
309 if (!fname) {
310 return NULL;
311 }
312
313 if ((buf = IMG_Load(fname)) == NULL) {
314 log_error(_("load_surf: Failed to load graphic file %s!"), fname);
315
316 return NULL;
317 }
318
319 return buf;
320}
321
322/**********************************************************************/
326SDL_Surface *create_surf_with_format(SDL_PixelFormat *pf,
327 int width, int height,
328 Uint32 flags)
329{
330 SDL_Surface *surf = SDL_CreateRGBSurface(flags, width, height,
331 pf->BitsPerPixel,
332 pf->Rmask,
333 pf->Gmask,
334 pf->Bmask, pf->Amask);
335
336 if (surf == NULL) {
337 log_error(_("Unable to create Sprite (Surface) of size "
338 "%d x %d %d Bits in format %d"),
339 width, height, pf->BitsPerPixel, flags);
340 return NULL;
341 }
342
343 return surf;
344}
345
346/**********************************************************************/
349SDL_Surface *create_surf(int width, int height, Uint32 flags)
350{
351 return create_surf_with_format(main_surface->format, width, height, flags);
352}
353
354/**********************************************************************/
357SDL_Surface *convert_surf(SDL_Surface *surf_in)
358{
359 return SDL_ConvertSurface(surf_in, main_surface->format, 0);
360}
361
362/**********************************************************************/
366SDL_Surface *create_filled_surface(Uint16 w, Uint16 h, Uint32 flags,
367 SDL_Color *pcolor)
368{
369 SDL_Surface *new_surf;
370 SDL_Color color = {255, 255, 255, 128};
371
372 new_surf = create_surf(w, h, flags);
373
374 if (!new_surf) {
375 return NULL;
376 }
377
378 if (!pcolor) {
379 /* pcolor->unused == ALPHA */
380 pcolor = &color;
381 }
382
383 SDL_FillRect(new_surf, NULL,
384 SDL_MapRGBA(new_surf->format, pcolor->r, pcolor->g, pcolor->b,
385 pcolor->a));
386
387 if (pcolor->a != 255) {
388 SDL_SetSurfaceAlphaMod(new_surf, pcolor->a);
389 }
390
391 return new_surf;
392}
393
394/**********************************************************************/
398int clear_surface(SDL_Surface *surf, SDL_Rect *dstrect)
399{
400 /* SDL_FillRect might change the rectangle, so we create a copy */
401 if (dstrect) {
402 SDL_Rect _dstrect = *dstrect;
403
404 return SDL_FillRect(surf, &_dstrect, SDL_MapRGBA(surf->format, 0, 0, 0, 0));
405 } else {
406 return SDL_FillRect(surf, NULL, SDL_MapRGBA(surf->format, 0, 0, 0, 0));
407 }
408}
409
410/**********************************************************************/
415int blit_entire_src(SDL_Surface *psrc, SDL_Surface *pdest,
416 Sint16 dest_x, Sint16 dest_y)
417{
418 SDL_Rect dest_rect = { dest_x, dest_y, 0, 0 };
419
420 return alphablit(psrc, NULL, pdest, &dest_rect, 255);
421}
422
423/**********************************************************************/
428Uint32 getpixel(SDL_Surface *surf, int x, int y)
429{
430 if (!surf) {
431 return 0x0;
432 }
433
434 switch (surf->format->BytesPerPixel) {
435 case 1:
436 return *(Uint8 *) ((Uint8 *) surf->pixels + y * surf->pitch + x);
437
438 case 2:
439 return *((Uint16 *)surf->pixels + y * surf->pitch / sizeof(Uint16) + x);
440
441 case 3:
442 {
443 /* Here ptr is the address to the pixel we want to retrieve */
444 Uint8 *ptr =
445 (Uint8 *) surf->pixels + y * surf->pitch + x * 3;
446
447 if (is_bigendian()) {
448 return ptr[0] << 16 | ptr[1] << 8 | ptr[2];
449 } else {
450 return ptr[0] | ptr[1] << 8 | ptr[2] << 16;
451 }
452 }
453 case 4:
454 return *((Uint32 *)surf->pixels + y * surf->pitch / sizeof(Uint32) + x);
455
456 default:
457 return 0; /* shouldn't happen, but avoids warnings */
458 }
459}
460
461/**********************************************************************/
466Uint32 get_first_pixel(SDL_Surface *surf)
467{
468 if (!surf) {
469 return 0;
470 }
471
472 switch (surf->format->BytesPerPixel) {
473 case 1:
474 return *((Uint8 *)surf->pixels);
475
476 case 2:
477 return *((Uint16 *)surf->pixels);
478
479 case 3:
480 {
481 if (is_bigendian()) {
482 return (((Uint8 *)surf->pixels)[0] << 16)
483 | (((Uint8 *)surf->pixels)[1] << 8)
484 | ((Uint8 *)surf->pixels)[2];
485 } else {
486 return ((Uint8 *)surf->pixels)[0]
487 | (((Uint8 *)surf->pixels)[1] << 8)
488 | (((Uint8 *)surf->pixels)[2] << 16);
489 }
490 }
491 case 4:
492 return *((Uint32 *)surf->pixels);
493
494 default:
495 return 0; /* shouldn't happen, but avoids warnings */
496 }
497}
498
499/* ===================================================================== */
500
501/**********************************************************************/
504void init_sdl(int flags)
505{
506 bool error;
507
508 main_data.screen = NULL;
509 main_data.guis = NULL;
510 main_data.gui = NULL;
511 main_data.map = NULL;
512 main_data.dummy = NULL; /* Can't create yet -- hope we don't need it */
513 main_data.renderer = NULL;
516
517 if (SDL_WasInit(SDL_INIT_AUDIO)) {
518 error = (SDL_InitSubSystem(flags) < 0);
519 } else {
520 error = (SDL_Init(flags) < 0);
521 }
522 if (error) {
523 log_fatal(_("Unable to initialize SDL2 library: %s"), SDL_GetError());
524 exit(EXIT_FAILURE);
525 }
526
527 atexit(SDL_Quit);
528
529 /* Initialize the TTF library */
530 if (TTF_Init() < 0) {
531 log_fatal(_("Unable to initialize SDL2_ttf library: %s"), SDL_GetError());
532 exit(EXIT_FAILURE);
533 }
534
535 atexit(TTF_Quit);
536}
537
538/**********************************************************************/
541static void free_surfaces(void)
542{
543 if (main_data.renderer != NULL) {
544 SDL_DestroyRenderer(main_data.renderer);
545 main_data.renderer = NULL;
546
548 }
549}
550
551/**********************************************************************/
555{
556 unsigned flags;
557
559
560 if (is_bigendian()) {
561 main_surface = SDL_CreateRGBSurface(0, width, height, 32,
562 0x0000FF00, 0x00FF0000,
563 0xFF000000, 0x000000FF);
564 main_data.map = SDL_CreateRGBSurface(0, width, height, 32,
565 0x0000FF00, 0x00FF0000,
566 0xFF000000, 0x000000FF);
567 } else {
568 main_surface = SDL_CreateRGBSurface(0, width, height, 32,
569 0x00FF0000, 0x0000FF00,
570 0x000000FF, 0xFF000000);
571 main_data.map = SDL_CreateRGBSurface(0, width, height, 32,
572 0x00FF0000, 0x0000FF00,
573 0x000000FF, 0xFF000000);
574 }
575
576 if (main_surface == NULL || main_data.map == NULL) {
577 log_fatal(_("Failed to create RGB surface: %s"), SDL_GetError());
578 return FALSE;
579 }
580
583 flags = SDL_RENDERER_SOFTWARE;
584 } else {
585 flags = 0;
586 }
587
588 main_data.renderer = SDL_CreateRenderer(main_data.screen, -1, flags);
589
590 if (main_data.renderer == NULL) {
591 log_fatal(_("Failed to create renderer: %s"), SDL_GetError());
592 return FALSE;
593 }
594
595 main_data.maintext = SDL_CreateTexture(main_data.renderer,
596 SDL_PIXELFORMAT_ARGB8888,
597 SDL_TEXTUREACCESS_STREAMING,
598 width, height);
599
600 if (main_data.maintext == NULL) {
601 log_fatal(_("Failed to create texture: %s"), SDL_GetError());
602 return FALSE;
603 }
604
605 if (main_data.gui) {
607 main_data.gui->surface = create_surf(width, height, SDL_SWSURFACE);
608 } else {
610 }
611
613
614 return TRUE;
615}
616
617/**********************************************************************/
620void quit_sdl(void)
621{
626 SDL_DestroyTexture(main_data.maintext);
627
629}
630
631/**********************************************************************/
634bool set_video_mode(unsigned width, unsigned height, unsigned flags_in)
635{
636 main_data.screen = SDL_CreateWindow(_("SDL2 Client for Freeciv"),
637 SDL_WINDOWPOS_UNDEFINED,
638 SDL_WINDOWPOS_UNDEFINED,
639 width, height,
640 0);
641
642 if (main_data.screen == NULL) {
643 log_fatal(_("Failed to create main window: %s"), SDL_GetError());
644 return FALSE;
645 }
646
647 if (flags_in & SDL_WINDOW_FULLSCREEN) {
648 SDL_DisplayMode mode;
649
650 /* Use SDL_WINDOW_FULLSCREEN_DESKTOP instead of real SDL_WINDOW_FULLSCREEN */
651 SDL_SetWindowFullscreen(main_data.screen, SDL_WINDOW_FULLSCREEN_DESKTOP);
652 SDL_GetWindowDisplayMode(main_data.screen, &mode);
653 width = mode.w;
654 height = mode.h;
655 }
656
658 return FALSE;
659 }
660
661 return TRUE;
662}
663
664/**********************************************************************/
668{
669 if (render_dirty) {
670 SDL_UpdateTexture(main_data.maintext, NULL,
671 main_surface->pixels, main_surface->pitch);
672 SDL_RenderClear(main_data.renderer);
673 SDL_RenderCopy(main_data.renderer, main_data.maintext, NULL, NULL);
674 SDL_RenderPresent(main_data.renderer);
675
677 }
678}
679
680/**********************************************************************/
684{
685 return main_surface->w;
686}
687
688/**********************************************************************/
692{
693 return main_surface->h;
694}
695
696/**************************************************************************
697 Fill Rect with RGBA color
698**************************************************************************/
699#define MASK565 0xf7de
700#define MASK555 0xfbde
701
702/* 50% alpha (128) */
703#define BLEND16_50( d, s , mask ) \
704 (((( s & mask ) + ( d & mask )) >> 1) + ( s & d & ( ~mask & 0xffff)))
705
706#define BLEND2x16_50( d, s , mask ) \
707 (((( s & (mask | mask << 16)) + ( d & ( mask | mask << 16 ))) >> 1) + \
708 ( s & d & ( ~(mask | mask << 16))))
709
710/**********************************************************************/
713static int __FillRectAlpha8888_32bit(SDL_Surface *surf, SDL_Rect *prect,
714 SDL_Color *pcolor)
715{
716 register Uint32 A = pcolor->a;
717 register Uint32 dSIMD1, dSIMD2;
718 register Uint32 sSIMD1, sSIMD2 = SDL_MapRGB(surf->format,
719 pcolor->r, pcolor->g,
720 pcolor->b);
721 Uint32 y, end, A_Dst, A_Mask = surf->format->Amask;
722 Uint32 *start, *pixel;
723
724 sSIMD1 = sSIMD2 & 0x00FF00FF;
725
726 lock_surf(surf);
727
728 if (prect == NULL) {
729 end = surf->w * surf->h;
730 pixel = (Uint32 *) surf->pixels;
731 if (A == 128) { /* 50% A */
733 {
734 dSIMD2 = *pixel;
735 A_Dst = dSIMD2 & A_Mask;
736 *pixel++ = ((((sSIMD2 & 0x00fefefe) + (dSIMD2 & 0x00fefefe)) >> 1)
737 + (sSIMD2 & dSIMD2 & 0x00010101)) | A_Dst;
738 }, end);
739 } else {
740 sSIMD2 &= 0xFF00;
741 sSIMD2 = sSIMD2 >> 8 | sSIMD2 << 8;
743 {
744 dSIMD2 = *pixel;
745 A_Dst = dSIMD2 & A_Mask;
746 dSIMD1 = dSIMD2 & 0x00FF00FF;
747 dSIMD1 += (sSIMD1 - dSIMD1) * A >> 8;
748 dSIMD1 &= 0x00FF00FF;
749 dSIMD2 &= 0xFF00;
750 dSIMD2 += (((sSIMD2 << 8) & 0xFF00) - dSIMD2) * A >> 8;
751 dSIMD2 &= 0xFF00;
752 *pixel++ = dSIMD1 | dSIMD2 | A_Dst;
753 }, {
754 dSIMD1 = *pixel;
755 A_Dst = dSIMD1 & A_Mask;
756 dSIMD1 &= 0x00FF00FF;
757 dSIMD1 += (sSIMD1 - dSIMD1) * A >> 8;
758 dSIMD1 &= 0x00FF00FF;
759
760 dSIMD2 = ((*pixel & 0xFF00) >> 8)| ((pixel[1] & 0xFF00) << 8);
761 dSIMD2 += (sSIMD2 - dSIMD2) * A >> 8;
762 dSIMD2 &= 0x00FF00FF;
763
764 *pixel++ = dSIMD1 | ((dSIMD2 << 8) & 0xFF00) | A_Dst;
765
766 dSIMD1 = *pixel;
767 A_Dst = dSIMD1 & A_Mask;
768 dSIMD1 &= 0x00FF00FF;
769 dSIMD1 += (sSIMD1 - dSIMD1) * A >> 8;
770 dSIMD1 &= 0x00FF00FF;
771
772 *pixel++ = dSIMD1 | ((dSIMD2 >> 8) & 0xFF00) | A_Dst;
773 }, end);
774 }
775 } else {
776 /* Correct prect size */
777 if (prect->x < 0) {
778 prect->w += prect->x;
779 prect->x = 0;
780 } else if (prect->x >= surf->w - prect->w) {
781 prect->w = surf->w - prect->x;
782 }
783
784 if (prect->y < 0) {
785 prect->h += prect->y;
786 prect->y = 0;
787 } else if (prect->y >= surf->h - prect->h) {
788 prect->h = surf->h - prect->y;
789 }
790
791 start = pixel = (Uint32 *) surf->pixels +
792 (prect->y * (surf->pitch >> 2)) + prect->x;
793
794 if (A == 128) { /* 50% A */
795 y = prect->h;
796 end = prect->w;
797 while (y--) {
799 {
800 dSIMD2 = *pixel;
801 A_Dst = dSIMD2 & A_Mask;
802 *pixel++ = ((((sSIMD2 & 0x00fefefe) + (dSIMD2 & 0x00fefefe)) >> 1)
803 + (sSIMD2 & dSIMD2 & 0x00010101)) | A_Dst;
804 }, end);
805 pixel = start + (surf->pitch >> 2);
806 start = pixel;
807 }
808 } else {
809 y = prect->h;
810 end = prect->w;
811
812 sSIMD2 &= 0xFF00;
813 sSIMD2 = sSIMD2 >> 8 | sSIMD2 << 8;
814
815 while (y--) {
817 {
818 dSIMD2 = *pixel;
819 A_Dst = dSIMD2 & A_Mask;
820 dSIMD1 = dSIMD2 & 0x00FF00FF;
821 dSIMD1 += (sSIMD1 - dSIMD1) * A >> 8;
822 dSIMD1 &= 0x00FF00FF;
823 dSIMD2 &= 0xFF00;
824 dSIMD2 += (((sSIMD2 << 8) & 0xFF00) - dSIMD2) * A >> 8;
825 dSIMD2 &= 0xFF00;
826 *pixel++ = dSIMD1 | dSIMD2 | A_Dst;
827 }, {
828 dSIMD1 = *pixel;
829 A_Dst = dSIMD1 & A_Mask;
830 dSIMD1 &= 0x00FF00FF;
831 dSIMD1 += (sSIMD1 - dSIMD1) * A >> 8;
832 dSIMD1 &= 0x00FF00FF;
833
834 dSIMD2 = ((*pixel & 0xFF00) >> 8)| ((pixel[1] & 0xFF00) << 8);
835 dSIMD2 += (sSIMD2 - dSIMD2) * A >> 8;
836 dSIMD2 &= 0x00FF00FF;
837
838 *pixel++ = dSIMD1 | ((dSIMD2 << 8) & 0xFF00) | A_Dst;
839
840 dSIMD1 = *pixel;
841 A_Dst = dSIMD1 & A_Mask;
842 dSIMD1 &= 0x00FF00FF;
843 dSIMD1 += (sSIMD1 - dSIMD1) * A >> 8;
844 dSIMD1 &= 0x00FF00FF;
845
846 *pixel++ = dSIMD1 | ((dSIMD2 >> 8) & 0xFF00) | A_Dst;
847 }, end);
848
849 pixel = start + (surf->pitch >> 2);
850 start = pixel;
851 } /* while */
852 }
853 }
854
855 unlock_surf(surf);
856
857 return 0;
858}
859
860/**********************************************************************/
863int fill_rect_alpha(SDL_Surface *surf, SDL_Rect *prect,
864 SDL_Color *pcolor)
865{
866 if (prect && (prect->x < - prect->w || prect->x >= surf->w
867 || prect->y < - prect->h || prect->y >= surf->h)) {
868 return -2;
869 }
870
871 if (pcolor->a == 255) {
872 return SDL_FillRect(surf, prect,
873 SDL_MapRGB(surf->format, pcolor->r, pcolor->g, pcolor->b));
874 }
875
876 if (!pcolor->a) {
877 return -3;
878 }
879
880 return __FillRectAlpha8888_32bit(surf, prect, pcolor);
881}
882
883/**********************************************************************/
886bool correct_rect_region(SDL_Rect *prect)
887{
888 int ww = prect->w, hh = prect->h;
889
890 if (prect->x < 0) {
891 ww += prect->x;
892 prect->x = 0;
893 }
894
895 if (prect->y < 0) {
896 hh += prect->y;
897 prect->y = 0;
898 }
899
900 if (prect->x + ww > main_window_width()) {
901 ww = main_window_width() - prect->x;
902 }
903
904 if (prect->y + hh > main_window_height()) {
905 hh = main_window_height() - prect->y;
906 }
907
908 /* End Correction */
909
910 if (ww <= 0 || hh <= 0) {
911 return FALSE; /* surprise :) */
912 } else {
913 prect->w = ww;
914 prect->h = hh;
915 }
916
917 return TRUE;
918}
919
920/**********************************************************************/
923bool is_in_rect_area(int x, int y, SDL_Rect rect)
924{
925 return ((x >= rect.x) && (x < rect.x + rect.w)
926 && (y >= rect.y) && (y < rect.y + rect.h));
927}
928
929/* ===================================================================== */
930
931/**********************************************************************/
934SDL_Rect get_smaller_surface_rect(SDL_Surface *surf)
935{
936 SDL_Rect src;
937 int w, h, x, y;
938 Uint16 minX, maxX, minY, maxY;
939 Uint32 colorkey;
940 Uint32 mask;
941
942 fc_assert(surf != NULL);
943
944 minX = surf->w;
945 maxX = 0;
946 minY = surf->h;
947 maxY = 0;
948
949 if (SDL_GetColorKey(surf, &colorkey) < 0) {
950 /* Use alpha instead of colorkey */
951 mask = surf->format->Amask;
952 colorkey = 0;
953 } else {
954 mask = 0xffffffff;
955 }
956
957 lock_surf(surf);
958
959 switch (surf->format->BytesPerPixel) {
960 case 1:
961 {
962 Uint8 *pixel = (Uint8 *)surf->pixels;
963 Uint8 *start = pixel;
964 x = 0;
965 y = 0;
966 w = surf->w;
967 h = surf->h;
968 while (h--) {
969 do {
970 if (*pixel != colorkey) {
971 if (minY > y) {
972 minY = y;
973 }
974
975 if (minX > x) {
976 minX = x;
977 }
978 break;
979 }
980 pixel++;
981 x++;
982 } while (--w > 0);
983 w = surf->w;
984 x = 0;
985 y++;
986 pixel = start + surf->pitch;
987 start = pixel;
988 }
989
990 w = surf->w;
991 h = surf->h;
992 x = w - 1;
993 y = h - 1;
994 pixel = (Uint8 *)((Uint8 *)surf->pixels + (y * surf->pitch) + x);
995 start = pixel;
996 while (h--) {
997 do {
998 if (*pixel != colorkey) {
999 if (maxY < y) {
1000 maxY = y;
1001 }
1002
1003 if (maxX < x) {
1004 maxX = x;
1005 }
1006 break;
1007 }
1008 pixel--;
1009 x--;
1010 } while (--w > 0);
1011 w = surf->w;
1012 x = w - 1;
1013 y--;
1014 pixel = start - surf->pitch;
1015 start = pixel;
1016 }
1017 break;
1018 }
1019 case 2:
1020 {
1021 Uint16 *pixel = (Uint16 *)surf->pixels;
1022 Uint16 *start = pixel;
1023
1024 x = 0;
1025 y = 0;
1026 w = surf->w;
1027 h = surf->h;
1028 while (h--) {
1029 do {
1030 if (*pixel != colorkey) {
1031 if (minY > y) {
1032 minY = y;
1033 }
1034
1035 if (minX > x) {
1036 minX = x;
1037 }
1038 break;
1039 }
1040 pixel++;
1041 x++;
1042 } while (--w > 0);
1043 w = surf->w;
1044 x = 0;
1045 y++;
1046 pixel = start + surf->pitch / 2;
1047 start = pixel;
1048 }
1049
1050 w = surf->w;
1051 h = surf->h;
1052 x = w - 1;
1053 y = h - 1;
1054 pixel = ((Uint16 *)surf->pixels + (y * surf->pitch / 2) + x);
1055 start = pixel;
1056 while (h--) {
1057 do {
1058 if (*pixel != colorkey) {
1059 if (maxY < y) {
1060 maxY = y;
1061 }
1062
1063 if (maxX < x) {
1064 maxX = x;
1065 }
1066 break;
1067 }
1068 pixel--;
1069 x--;
1070 } while (--w > 0);
1071 w = surf->w;
1072 x = w - 1;
1073 y--;
1074 pixel = start - surf->pitch / 2;
1075 start = pixel;
1076 }
1077 break;
1078 }
1079 case 3:
1080 {
1081 Uint8 *pixel = (Uint8 *)surf->pixels;
1082 Uint8 *start = pixel;
1083 Uint32 color;
1084
1085 x = 0;
1086 y = 0;
1087 w = surf->w;
1088 h = surf->h;
1089 while (h--) {
1090 do {
1091 if (is_bigendian()) {
1092 color = (pixel[0] << 16 | pixel[1] << 8 | pixel[2]);
1093 } else {
1094 color = (pixel[0] | pixel[1] << 8 | pixel[2] << 16);
1095 }
1096 if (color != colorkey) {
1097 if (minY > y) {
1098 minY = y;
1099 }
1100
1101 if (minX > x) {
1102 minX = x;
1103 }
1104 break;
1105 }
1106 pixel += 3;
1107 x++;
1108 } while (--w > 0);
1109 w = surf->w;
1110 x = 0;
1111 y++;
1112 pixel = start + surf->pitch / 3;
1113 start = pixel;
1114 }
1115
1116 w = surf->w;
1117 h = surf->h;
1118 x = w - 1;
1119 y = h - 1;
1120 pixel = (Uint8 *)((Uint8 *)surf->pixels + (y * surf->pitch) + x * 3);
1121 start = pixel;
1122 while (h--) {
1123 do {
1124 if (is_bigendian()) {
1125 color = (pixel[0] << 16 | pixel[1] << 8 | pixel[2]);
1126 } else {
1127 color = (pixel[0] | pixel[1] << 8 | pixel[2] << 16);
1128 }
1129 if (color != colorkey) {
1130 if (maxY < y) {
1131 maxY = y;
1132 }
1133
1134 if (maxX < x) {
1135 maxX = x;
1136 }
1137 break;
1138 }
1139 pixel -= 3;
1140 x--;
1141 } while (--w > 0);
1142 w = surf->w;
1143 x = w - 1;
1144 y--;
1145 pixel = start - surf->pitch / 3;
1146 start = pixel;
1147 }
1148 break;
1149 }
1150 case 4:
1151 {
1152 Uint32 *pixel = (Uint32 *)surf->pixels;
1153 Uint32 *start = pixel;
1154
1155 x = 0;
1156 y = 0;
1157 w = surf->w;
1158 h = surf->h;
1159 while (h--) {
1160 do {
1161 if (((*pixel) & mask) != colorkey) {
1162 if (minY > y) {
1163 minY = y;
1164 }
1165
1166 if (minX > x) {
1167 minX = x;
1168 }
1169 break;
1170 }
1171 pixel++;
1172 x++;
1173 } while (--w > 0);
1174 w = surf->w;
1175 x = 0;
1176 y++;
1177 pixel = start + surf->pitch / 4;
1178 start = pixel;
1179 }
1180
1181 w = surf->w;
1182 h = surf->h;
1183 x = w - 1;
1184 y = h - 1;
1185 pixel = ((Uint32 *)surf->pixels + (y * surf->pitch / 4) + x);
1186 start = pixel;
1187 while (h--) {
1188 do {
1189 if (((*pixel) & mask) != colorkey) {
1190 if (maxY < y) {
1191 maxY = y;
1192 }
1193
1194 if (maxX < x) {
1195 maxX = x;
1196 }
1197 break;
1198 }
1199 pixel--;
1200 x--;
1201 } while (--w > 0);
1202 w = surf->w;
1203 x = w - 1;
1204 y--;
1205 pixel = start - surf->pitch / 4;
1206 start = pixel;
1207 }
1208 break;
1209 }
1210 }
1211
1212 unlock_surf(surf);
1213 src.x = minX;
1214 src.y = minY;
1215 src.w = maxX - minX + 1;
1216 src.h = maxY - minY + 1;
1217
1218 return src;
1219}
1220
1221/**********************************************************************/
1224SDL_Surface *crop_visible_part_from_surface(SDL_Surface *psrc)
1225{
1226 SDL_Rect src = get_smaller_surface_rect(psrc);
1227
1228 return crop_rect_from_surface(psrc, &src);
1229}
1230
1231/**********************************************************************/
1234SDL_Surface *resize_surface(const SDL_Surface *psrc, Uint16 new_width,
1235 Uint16 new_height, int smooth)
1236{
1237 if (psrc == NULL) {
1238 return NULL;
1239 }
1240
1241 return zoomSurface((SDL_Surface*)psrc,
1242 (double)new_width / psrc->w,
1243 (double)new_height / psrc->h,
1244 smooth);
1245}
1246
1247/**********************************************************************/
1254SDL_Surface *resize_surface_box(const SDL_Surface *psrc,
1255 Uint16 new_width, Uint16 new_height,
1256 int smooth, bool scale_up,
1257 bool absolute_dimensions)
1258{
1259 SDL_Surface *tmp_surface, *result;
1260
1261 if (psrc == NULL) {
1262 return NULL;
1263 }
1264
1265 if (!(!scale_up && ((new_width >= psrc->w) && (new_height >= psrc->h)))) {
1266 if ((new_width - psrc->w) <= (new_height - psrc->h)) {
1267 /* horizontal limit */
1268 tmp_surface = zoomSurface((SDL_Surface*)psrc,
1269 (double)new_width / psrc->w,
1270 (double)new_width / psrc->w,
1271 smooth);
1272 } else {
1273 /* vertical limit */
1274 tmp_surface = zoomSurface((SDL_Surface*)psrc,
1275 (double)new_height / psrc->h,
1276 (double)new_height / psrc->h,
1277 smooth);
1278 }
1279 } else {
1280 tmp_surface = zoomSurface((SDL_Surface*)psrc,
1281 1.0,
1282 1.0,
1283 smooth);
1284 }
1285
1286 if (absolute_dimensions) {
1287 SDL_Rect area = {
1288 (new_width - tmp_surface->w) / 2,
1289 (new_height - tmp_surface->h) / 2,
1290 0, 0
1291 };
1292
1293 result = create_surf(new_width, new_height, SDL_SWSURFACE);
1294 alphablit(tmp_surface, NULL, result, &area, 255);
1295 FREESURFACE(tmp_surface);
1296 } else {
1297 result = tmp_surface;
1298 }
1299
1300 return result;
1301}
1302
1303/**********************************************************************/
1306SDL_Surface *copy_surface(SDL_Surface *src)
1307{
1308 SDL_Surface *dst;
1309
1310 dst = SDL_CreateRGBSurface(0, src->w, src->h, src->format->BitsPerPixel,
1311 src->format->Rmask, src->format->Gmask,
1312 src->format->Bmask, src->format->Amask);
1313
1314 SDL_BlitSurface(src, NULL, dst, NULL);
1315
1316 return dst;
1317}
1318
1319/* ============ Freeciv game graphics function =========== */
1320
1321/**********************************************************************/
1324bool is_view_supported(enum ts_type type)
1325{
1326 switch (type) {
1327 case TS_ISOMETRIC:
1328 case TS_OVERHEAD:
1329 return TRUE;
1330 }
1331
1332 return FALSE;
1333}
1334
1335/**********************************************************************/
1338void tileset_type_set(enum ts_type type)
1339{
1340}
1341
1342/**********************************************************************/
1345void create_frame(SDL_Surface *dest, Sint16 left, Sint16 top,
1346 Sint16 width, Sint16 height,
1347 SDL_Color *pcolor)
1348{
1349 struct color gsdl2_color = { .color = pcolor };
1350 struct sprite *vertical = create_sprite(1, height, &gsdl2_color);
1351 struct sprite *horizontal = create_sprite(width, 1, &gsdl2_color);
1352 SDL_Rect tmp,dst = { left, top, 0, 0 };
1353
1354 tmp = dst;
1355 alphablit(vertical->psurface, NULL, dest, &tmp, 255);
1356
1357 dst.x += width - 1;
1358 tmp = dst;
1359 alphablit(vertical->psurface, NULL, dest, &tmp, 255);
1360
1361 dst.x = left;
1362 tmp = dst;
1363 alphablit(horizontal->psurface, NULL, dest, &tmp, 255);
1364
1365 dst.y += height - 1;
1366 tmp = dst;
1367 alphablit(horizontal->psurface, NULL, dest, &tmp, 255);
1368
1369 free_sprite(horizontal);
1370 free_sprite(vertical);
1371}
1372
1373/**********************************************************************/
1376void create_line(SDL_Surface *dest, Sint16 x0, Sint16 y0, Sint16 x1, Sint16 y1,
1377 SDL_Color *pcolor)
1378{
1379 int xl = x0 < x1 ? x0 : x1;
1380 int xr = x0 < x1 ? x1 : x0;
1381 int yt = y0 < y1 ? y0 : y1;
1382 int yb = y0 < y1 ? y1 : y0;
1383 int w = (xr - xl) + 1;
1384 int h = (yb - yt) + 1;
1385 struct sprite *spr;
1386 SDL_Rect dst = { xl, yt, w, h };
1387 SDL_Color *pcol;
1388 struct color gsdl2_color;
1389 int l = MAX((xr - xl) + 1, (yb - yt) + 1);
1390 int i;
1391
1392 pcol = fc_malloc(sizeof(pcol));
1393 pcol->r = pcolor->r;
1394 pcol->g = pcolor->g;
1395 pcol->b = pcolor->b;
1396 pcol->a = 0; /* Fill with transparency */
1397
1398 gsdl2_color.color = pcol;
1399 spr = create_sprite(w, h, &gsdl2_color);
1400
1401 lock_surf(spr->psurface);
1402
1403 /* Set off transparency from pixels belonging to the line */
1404 if ((x0 <= x1 && y0 <= y1)
1405 || (x1 <= x0 && y1 <= y0)) {
1406 for (i = 0; i < l; i++) {
1407 int cx = (xr - xl) * i / l;
1408 int cy = (yb - yt) * i / l;
1409
1410 *((Uint32 *)spr->psurface->pixels + spr->psurface->w * cy + cx)
1411 |= (pcolor->a << spr->psurface->format->Ashift);
1412 }
1413 } else {
1414 for (i = 0; i < l; i++) {
1415 int cx = (xr - xl) * i / l;
1416 int cy = yb - yt - (yb - yt) * i / l;
1417
1418 *((Uint32 *)spr->psurface->pixels + spr->psurface->w * cy + cx)
1419 |= (pcolor->a << spr->psurface->format->Ashift);
1420 }
1421 }
1422
1423 unlock_surf(spr->psurface);
1424
1425 alphablit(spr->psurface, NULL, dest, &dst, 255);
1426
1427 free_sprite(spr);
1428 free(pcol);
1429}
struct canvas int int struct sprite int int int int height
Definition canvas_g.h:44
struct canvas int int struct sprite bool int int fog_y struct canvas struct sprite struct color * pcolor
Definition canvas_g.h:57
struct canvas int int struct sprite int int int width
Definition canvas_g.h:44
#define _(String)
Definition fcintl.h:67
bool is_view_supported(enum ts_type type)
Definition graphics.c:53
void tileset_type_set(enum ts_type type)
Definition graphics.c:67
GType type
Definition repodlgs.c:1312
void free_sprite(struct sprite *s)
Definition sprite.c:278
SDL_Surface * resize_surface(const SDL_Surface *psrc, Uint16 new_width, Uint16 new_height, int smooth)
Definition graphics.c:1234
Uint32 getpixel(SDL_Surface *surf, int x, int y)
Definition graphics.c:428
bool set_video_mode(unsigned width, unsigned height, unsigned flags_in)
Definition graphics.c:634
SDL_Rect get_smaller_surface_rect(SDL_Surface *surf)
Definition graphics.c:934
bool is_in_rect_area(int x, int y, SDL_Rect rect)
Definition graphics.c:923
int main_window_width(void)
Definition graphics.c:683
void layer_rect_to_screen_rect(struct gui_layer *gui_layer, SDL_Rect *dest_rect)
Definition graphics.c:183
SDL_Surface * load_surf(const char *fname)
Definition graphics.c:305
SDL_Surface * create_surf_with_format(SDL_PixelFormat *pf, int width, int height, Uint32 flags)
Definition graphics.c:326
void init_sdl(int flags)
Definition graphics.c:504
void update_main_screen(void)
Definition graphics.c:667
void remove_gui_layer(struct gui_layer *gui_layer)
Definition graphics.c:146
SDL_Surface * create_filled_surface(Uint16 w, Uint16 h, Uint32 flags, SDL_Color *pcolor)
Definition graphics.c:366
int fill_rect_alpha(SDL_Surface *surf, SDL_Rect *prect, SDL_Color *pcolor)
Definition graphics.c:863
void gui_layer_destroy(struct gui_layer **gui_layer)
Definition graphics.c:79
void create_line(SDL_Surface *dest, Sint16 x0, Sint16 y0, Sint16 x1, Sint16 y1, SDL_Color *pcolor)
Definition graphics.c:1376
SDL_Surface * copy_surface(SDL_Surface *src)
Definition graphics.c:1306
SDL_Surface * mask_surface(SDL_Surface *src, SDL_Surface *mask, int mask_offset_x, int mask_offset_y)
Definition graphics.c:260
struct gui_layer * gui_layer_new(int x, int y, SDL_Surface *surface)
Definition graphics.c:64
void quit_sdl(void)
Definition graphics.c:620
SDL_Surface * crop_visible_part_from_surface(SDL_Surface *psrc)
Definition graphics.c:1224
SDL_Surface * crop_rect_from_surface(SDL_Surface *psource, SDL_Rect *prect)
Definition graphics.c:234
int alphablit(SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *dst, SDL_Rect *dstrect, unsigned char alpha_mod)
Definition graphics.c:197
struct gui_layer * get_gui_layer(SDL_Surface *surface)
Definition graphics.c:88
int screen_blit(SDL_Surface *src, SDL_Rect *srcrect, SDL_Rect *dstrect, unsigned char alpha_mod)
Definition graphics.c:221
struct sdl2_data main_data
Definition graphics.c:55
static SDL_Surface * main_surface
Definition graphics.c:57
int blit_entire_src(SDL_Surface *psrc, SDL_Surface *pdest, Sint16 dest_x, Sint16 dest_y)
Definition graphics.c:415
Uint32 get_first_pixel(SDL_Surface *surf)
Definition graphics.c:466
SDL_Surface * convert_surf(SDL_Surface *surf_in)
Definition graphics.c:357
SDL_Surface * create_surf(int width, int height, Uint32 flags)
Definition graphics.c:349
struct gui_layer * add_gui_layer(int width, int height)
Definition graphics.c:110
int clear_surface(SDL_Surface *surf, SDL_Rect *dstrect)
Definition graphics.c:398
bool correct_rect_region(SDL_Rect *prect)
Definition graphics.c:886
void screen_rect_to_layer_rect(struct gui_layer *gui_layer, SDL_Rect *dest_rect)
Definition graphics.c:171
static int __FillRectAlpha8888_32bit(SDL_Surface *surf, SDL_Rect *prect, SDL_Color *pcolor)
Definition graphics.c:713
void create_frame(SDL_Surface *dest, Sint16 left, Sint16 top, Sint16 width, Sint16 height, SDL_Color *pcolor)
Definition graphics.c:1345
static void free_surfaces(void)
Definition graphics.c:541
bool create_surfaces(int width, int height)
Definition graphics.c:554
int main_window_height(void)
Definition graphics.c:691
static bool render_dirty
Definition graphics.c:59
SDL_Surface * resize_surface_box(const SDL_Surface *psrc, Uint16 new_width, Uint16 new_height, int smooth, bool scale_up, bool absolute_dimensions)
Definition graphics.c:1254
#define FREESURFACE(ptr)
Definition graphics.h:322
#define unlock_surf(surf)
Definition graphics.h:344
#define lock_surf(surf)
Definition graphics.h:333
#define DUFFS_LOOP_DOUBLE2(pixel_copy_increment, double_pixel_copy_increment, width)
Definition graphics.h:98
#define DUFFS_LOOP8(pixel_copy_increment, width)
Definition graphics.h:60
#define DUFFS_LOOP4(pixel_copy_increment, width)
Definition graphics.h:83
Uint32 sdl2_client_flags
Definition gui_main.c:97
#define CF_SWRENDERER
Definition gui_main.h:61
#define fc_assert(condition)
Definition log.h:176
#define log_fatal(message,...)
Definition log.h:100
#define log_error(message,...)
Definition log.h:103
#define fc_calloc(n, esz)
Definition mem.h:38
#define FC_FREE(ptr)
Definition mem.h:41
#define fc_realloc(ptr, sz)
Definition mem.h:36
#define fc_malloc(sz)
Definition mem.h:34
struct client_options gui_options
Definition options.c:71
#define MAX(x, y)
Definition shared.h:54
create_sprite
Definition sprite_g.h:30
bool gui_sdl2_swrenderer
Definition options.h:378
Definition colors.h:20
GdkRGBA color
Definition colors.h:21
SDL_Surface * surface
Definition graphics.h:229
SDL_Rect dest_rect
Definition graphics.h:228
int guis_count
Definition graphics.h:207
SDL_Surface * dummy
Definition graphics.h:211
SDL_Renderer * renderer
Definition graphics.h:213
SDL_Texture * maintext
Definition graphics.h:212
struct gui_layer * gui
Definition graphics.h:215
int rects_count
Definition graphics.h:206
struct gui_layer ** guis
Definition graphics.h:216
SDL_Window * screen
Definition graphics.h:209
SDL_Surface * map
Definition graphics.h:210
struct SDL_Surface * psurface
Definition sprite.h:21
static bool is_bigendian(void)
Definition support.h:207
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47