Freeciv-3.2: /fast/freeciv/nightly/S3_2/client/gui-sdl3/graphics.c Source File

Freeciv-3.2

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/* SDL3 */
29#include <SDL3_image/SDL_image.h>
30#include <SDL3_ttf/SDL_ttf.h>
31
32/* utility */
33#include "fcintl.h"
34#include "log.h"
35
36/* client */
37#include "tilespec.h"
38
39/* gui-sdl3 */
40#include "colors.h"
41#include "gui_tilespec.h"
42#include "mapview.h"
43#include "themebackgrounds.h"
44#include "themespec.h"
45
46#include "graphics.h"
47
48/* ------------------------------ */
49
50 struct sdl3_data main_data;
51
52 static SDL_Surface *main_surface = NULL;
53
54 static bool render_dirty = TRUE;
55
56/**********************************************************************/
59 struct gui_layer *gui_layer_new(int x, int y, SDL_Surface *surface)
60{
61 struct gui_layer *result;
62
63 result = fc_calloc(1, sizeof(struct gui_layer));
64
65 result->dest_rect = (SDL_Rect){x, y, 0, 0};
66 result->surface = surface;
67
68 return result;
69}
70
71/**********************************************************************/
74 void gui_layer_destroy(struct gui_layer **gui_layer)
75{
76 FREESURFACE((*gui_layer)->surface);
77 FC_FREE(*gui_layer);
78}
79
80/**********************************************************************/
83 struct gui_layer *get_gui_layer(SDL_Surface *surface)
84{
85 int i = 0;
86
87 while ((i < main_data.guis_count) && main_data.guis[i]) {
88 if (main_data.guis[i]->surface == surface) {
89 return main_data.guis[i];
90 }
91 i++;
92 }
93
94 return NULL;
95}
96
97/**********************************************************************/
105 struct gui_layer *add_gui_layer(int width, int height)
106{
107 struct gui_layer *gui_layer = NULL;
108 SDL_Surface *buffer;
109
110 buffer = create_surf(width, height, SDL_SWSURFACE);
111 gui_layer = gui_layer_new(0, 0, buffer);
112
113 /* add to buffers array */
114 if (main_data.guis) {
115 int i;
116
117 /* find NULL element */
118 for (i = 0; i < main_data.guis_count; i++) {
119 if (!main_data.guis[i]) {
120 main_data.guis[i] = gui_layer;
121 return gui_layer;
122 }
123 }
124 main_data.guis_count++;
125 main_data.guis = fc_realloc(main_data.guis,
126 main_data.guis_count * sizeof(struct gui_layer *));
127 main_data.guis[main_data.guis_count - 1] = gui_layer;
128 } else {
129 main_data.guis = fc_calloc(1, sizeof(struct gui_layer *));
130 main_data.guis[0] = gui_layer;
131 main_data.guis_count = 1;
132 }
133
134 return gui_layer;
135}
136
137/**********************************************************************/
141 void remove_gui_layer(struct gui_layer *gui_layer)
142{
143 int i;
144
145 for (i = 0; i < main_data.guis_count - 1; i++) {
146 if (main_data.guis[i] && (main_data.guis[i] == gui_layer)) {
147 gui_layer_destroy(&main_data.guis[i]);
148 main_data.guis[i] = main_data.guis[i + 1];
149 main_data.guis[i + 1] = NULL;
150 } else {
151 if (!main_data.guis[i]) {
152 main_data.guis[i] = main_data.guis[i + 1];
153 main_data.guis[i + 1] = NULL;
154 }
155 }
156 }
157
158 if (main_data.guis[main_data.guis_count - 1]) {
159 gui_layer_destroy(&main_data.guis[main_data.guis_count - 1]);
160 }
161}
162
163/**********************************************************************/
166 void screen_rect_to_layer_rect(struct gui_layer *gui_layer,
167 SDL_Rect *dest_rect)
168{
169 if (gui_layer) {
170 dest_rect->x = dest_rect->x - gui_layer->dest_rect.x;
171 dest_rect->y = dest_rect->y - gui_layer->dest_rect.y;
172 }
173}
174
175/**********************************************************************/
178 void layer_rect_to_screen_rect(struct gui_layer *gui_layer,
179 SDL_Rect *dest_rect)
180{
181 if (gui_layer) {
182 dest_rect->x = dest_rect->x + gui_layer->dest_rect.x;
183 dest_rect->y = dest_rect->y + gui_layer->dest_rect.y;
184 }
185}
186
187/* ============ Freeciv sdl graphics function =========== */
188
189/**********************************************************************/
192 int alphablit(SDL_Surface *src, SDL_Rect *srcrect,
193 SDL_Surface *dst, SDL_Rect *dstrect,
194 unsigned char alpha_mod)
195{
196 int ret;
197
198 if (src == NULL || dst == NULL) {
199 return 1;
200 }
201
202 SDL_SetSurfaceAlphaMod(src, alpha_mod);
203
204 ret = SDL_BlitSurface(src, srcrect, dst, dstrect);
205
206 if (ret) {
207 log_error("SDL_BlitSurface() fails: %s", SDL_GetError());
208 }
209
210 return ret;
211}
212
213/**********************************************************************/
216 int screen_blit(SDL_Surface *src, SDL_Rect *srcrect, SDL_Rect *dstrect,
217 unsigned char alpha_mod)
218{
219 render_dirty = TRUE;
220
221 return alphablit(src, srcrect, main_surface, dstrect, alpha_mod);
222}
223
224/**********************************************************************/
229 SDL_Surface *crop_rect_from_surface(SDL_Surface *psource,
230 SDL_Rect *prect)
231{
232 SDL_Surface *new_surf = create_surf_with_format(psource->format,
233 prect ? prect->w : psource->w,
234 prect ? prect->h : psource->h);
235
236 if (alphablit(psource, prect, new_surf, NULL, 255) != 0) {
237 FREESURFACE(new_surf);
238
239 return NULL;
240 }
241
242 return new_surf;
243}
244
245/**********************************************************************/
254 SDL_Surface *mask_surface(SDL_Surface *src, SDL_Surface *mask,
255 int mask_offset_x, int mask_offset_y)
256{
257 SDL_Surface *dest = NULL;
258 int row, col;
259 Uint32 *src_pixel = NULL;
260 Uint32 *dest_pixel = NULL;
261 Uint32 *mask_pixel = NULL;
262 unsigned char src_alpha, mask_alpha;
263
264 dest = copy_surface(src);
265
266 lock_surf(src);
267 lock_surf(mask);
268 lock_surf(dest);
269
270 src_pixel = (Uint32 *)src->pixels;
271 dest_pixel = (Uint32 *)dest->pixels;
272
273 for (row = 0; row < src->h; row++) {
274 mask_pixel = (Uint32 *)mask->pixels
275 + mask->w * (row + mask_offset_y)
276 + mask_offset_x;
277
278 for (col = 0; col < src->w; col++) {
279 src_alpha = (*src_pixel & src->format->Amask) >> src->format->Ashift;
280 mask_alpha = (*mask_pixel & mask->format->Amask) >> mask->format->Ashift;
281
282 *dest_pixel = (*src_pixel & ~src->format->Amask)
283 | (((src_alpha * mask_alpha) / 255) << dest->format->Ashift);
284
285 src_pixel++; dest_pixel++; mask_pixel++;
286 }
287 }
288
289 unlock_surf(dest);
290 unlock_surf(mask);
291 unlock_surf(src);
292
293 return dest;
294}
295
296/**********************************************************************/
299 SDL_Surface *load_surf(const char *fname)
300{
301 SDL_Surface *buf;
302
303 if (!fname) {
304 return NULL;
305 }
306
307 if ((buf = IMG_Load(fname)) == NULL) {
308 log_error(_("load_surf: Failed to load graphic file %s!"), fname);
309
310 return NULL;
311 }
312
313 return buf;
314}
315
316/**********************************************************************/
319 SDL_Surface *create_surf_with_format(SDL_PixelFormat *pf,
320 int width, int height)
321{
322 SDL_Surface *surf = SDL_CreateSurface(width, height, pf->format);
323
324 if (surf == NULL) {
325 log_error(_("Unable to create Sprite (Surface) of size "
326 "%d x %d %d Bits"),
327 width, height, pf->bits_per_pixel);
328 return NULL;
329 }
330
331 return surf;
332}
333
334/**********************************************************************/
337 SDL_Surface *create_surf(int width, int height, Uint32 flags)
338{
339 return create_surf_with_format(main_surface->format, width, height);
340}
341
342/**********************************************************************/
345 SDL_Surface *convert_surf(SDL_Surface *surf_in)
346{
347 return SDL_ConvertSurface(surf_in, main_surface->format);
348}
349
350/**********************************************************************/
354 SDL_Surface *create_filled_surface(Uint16 w, Uint16 h, Uint32 flags,
355 SDL_Color *pcolor)
356{
357 SDL_Surface *new_surf;
358 SDL_Color color = {255, 255, 255, 128};
359
360 new_surf = create_surf(w, h, flags);
361
362 if (!new_surf) {
363 return NULL;
364 }
365
366 if (!pcolor) {
367 /* pcolor->unused == ALPHA */
368 pcolor = &color;
369 }
370
371 SDL_FillSurfaceRect(new_surf, NULL,
372 SDL_MapRGBA(new_surf->format,
373 pcolor->r, pcolor->g, pcolor->b,
374 pcolor->a));
375
376 if (pcolor->a != 255) {
377 SDL_SetSurfaceAlphaMod(new_surf, pcolor->a);
378 }
379
380 return new_surf;
381}
382
383/**********************************************************************/
387 int clear_surface(SDL_Surface *surf, SDL_Rect *dstrect)
388{
389 /* SDL_FillSurfaceRect() might change the rectangle, so we create a copy */
390 if (dstrect) {
391 SDL_Rect _dstrect = *dstrect;
392
393 return SDL_FillSurfaceRect(surf, &_dstrect,
394 SDL_MapRGBA(surf->format, 0, 0, 0, 0));
395 } else {
396 return SDL_FillSurfaceRect(surf, NULL,
397 SDL_MapRGBA(surf->format, 0, 0, 0, 0));
398 }
399}
400
401/**********************************************************************/
406 int blit_entire_src(SDL_Surface *psrc, SDL_Surface *pdest,
407 Sint16 dest_x, Sint16 dest_y)
408{
409 SDL_Rect dest_rect = { dest_x, dest_y, 0, 0 };
410
411 return alphablit(psrc, NULL, pdest, &dest_rect, 255);
412}
413
414/**********************************************************************/
419 Uint32 getpixel(SDL_Surface *surf, Sint16 x, Sint16 y)
420{
421 if (!surf) {
422 return 0x0;
423 }
424
425 switch (surf->format->bytes_per_pixel) {
426 case 1:
427 return *(Uint8 *) ((Uint8 *) surf->pixels + y * surf->pitch + x);
428
429 case 2:
430 return *((Uint16 *)surf->pixels + y * surf->pitch / sizeof(Uint16) + x);
431
432 case 3:
433 {
434 /* Here ptr is the address to the pixel we want to retrieve */
435 Uint8 *ptr =
436 (Uint8 *) surf->pixels + y * surf->pitch + x * 3;
437
438 if (is_bigendian()) {
439 return ptr[0] << 16 | ptr[1] << 8 | ptr[2];
440 } else {
441 return ptr[0] | ptr[1] << 8 | ptr[2] << 16;
442 }
443 }
444 case 4:
445 return *((Uint32 *)surf->pixels + y * surf->pitch / sizeof(Uint32) + x);
446
447 default:
448 return 0; /* Shouldn't happen, but avoids warnings */
449 }
450}
451
452/**********************************************************************/
457 Uint32 get_first_pixel(SDL_Surface *surf)
458{
459 if (!surf) {
460 return 0;
461 }
462
463 switch (surf->format->bytes_per_pixel) {
464 case 1:
465 return *((Uint8 *)surf->pixels);
466
467 case 2:
468 return *((Uint16 *)surf->pixels);
469
470 case 3:
471 {
472 if (is_bigendian()) {
473 return (((Uint8 *)surf->pixels)[0] << 16)
474 | (((Uint8 *)surf->pixels)[1] << 8)
475 | ((Uint8 *)surf->pixels)[2];
476 } else {
477 return ((Uint8 *)surf->pixels)[0]
478 | (((Uint8 *)surf->pixels)[1] << 8)
479 | (((Uint8 *)surf->pixels)[2] << 16);
480 }
481 }
482 case 4:
483 return *((Uint32 *)surf->pixels);
484
485 default:
486 return 0; /* shouldn't happen, but avoids warnings */
487 }
488}
489
490/* ===================================================================== */
491
492/**********************************************************************/
495 void init_sdl(int flags)
496{
497 bool error;
498
499 main_data.screen = NULL;
500 main_data.guis = NULL;
501 main_data.gui = NULL;
502 main_data.map = NULL;
503 main_data.dummy = NULL; /* Can't create yet -- hope we don't need it */
504 main_data.renderer = NULL;
505 main_data.rects_count = 0;
506 main_data.guis_count = 0;
507
508 if (SDL_WasInit(SDL_INIT_AUDIO)) {
509 error = (SDL_InitSubSystem(flags) < 0);
510 } else {
511 error = (SDL_Init(flags) < 0);
512 }
513 if (error) {
514 log_fatal(_("Unable to initialize SDL3 library: %s"), SDL_GetError());
515 exit(EXIT_FAILURE);
516 }
517
518 atexit(SDL_Quit);
519
520 /* Initialize the TTF library */
521 if (TTF_Init() < 0) {
522 log_fatal(_("Unable to initialize SDL3_ttf library: %s"), SDL_GetError());
523 exit(EXIT_FAILURE);
524 }
525
526 atexit(TTF_Quit);
527}
528
529/**********************************************************************/
532 static void free_surfaces(void)
533{
534 if (main_data.renderer != NULL) {
535 SDL_DestroyRenderer(main_data.renderer);
536 main_data.renderer = NULL;
537
538 FREESURFACE(main_surface);
539 }
540}
541
542/**********************************************************************/
545 bool create_surfaces(int width, int height)
546{
547 unsigned flags;
548
549 free_surfaces();
550
551 main_surface = SDL_CreateSurface(width, height, SDL_PIXELFORMAT_RGBA8888);
552 main_data.map = SDL_CreateSurface(width, height, SDL_PIXELFORMAT_RGBA8888);
553
554 if (main_surface == NULL || main_data.map == NULL) {
555 log_fatal(_("Failed to create RGB surface: %s"), SDL_GetError());
556 return FALSE;
557 }
558
559 if (GUI_SDL_OPTION(swrenderer)
560 || (sdl3_client_flags & CF_SWRENDERER)) {
561 flags = SDL_RENDERER_SOFTWARE;
562 } else {
563 flags = SDL_RENDERER_ACCELERATED;
564 }
565
566 main_data.renderer = SDL_CreateRenderer(main_data.screen, NULL, flags);
567
568 if (main_data.renderer == NULL) {
569 log_fatal(_("Failed to create renderer: %s"), SDL_GetError());
570 return FALSE;
571 }
572
573 main_data.maintext = SDL_CreateTexture(main_data.renderer,
574 SDL_PIXELFORMAT_RGBA8888,
575 SDL_TEXTUREACCESS_STREAMING,
576 width, height);
577
578 if (main_data.maintext == NULL) {
579 log_fatal(_("Failed to create texture: %s"), SDL_GetError());
580 return FALSE;
581 }
582
583 if (main_data.gui) {
584 FREESURFACE(main_data.gui->surface);
585 main_data.gui->surface = create_surf(width, height, SDL_SWSURFACE);
586 } else {
587 main_data.gui = add_gui_layer(width, height);
588 }
589
590 clear_surface(main_data.gui->surface, NULL);
591
592 return TRUE;
593}
594
595/**********************************************************************/
598 void quit_sdl(void)
599{
600 FC_FREE(main_data.guis);
601 gui_layer_destroy(&main_data.gui);
602 FREESURFACE(main_data.map);
603 FREESURFACE(main_data.dummy);
604 SDL_DestroyTexture(main_data.maintext);
605
606 free_surfaces();
607}
608
609/**********************************************************************/
612 bool set_video_mode(unsigned width, unsigned height, unsigned flags_in)
613{
614 main_data.screen = SDL_CreateWindow(_("SDL3 Client for Freeciv"),
615 width, height, 0);
616
617 if (main_data.screen == NULL) {
618 log_fatal(_("Failed to create main window: %s"), SDL_GetError());
619 return FALSE;
620 }
621
622 if (flags_in & SDL_WINDOW_FULLSCREEN) {
623 const SDL_DisplayMode *mode;
624
625 SDL_SetWindowFullscreen(main_data.screen, SDL_WINDOW_FULLSCREEN);
626 mode = SDL_GetWindowFullscreenMode(main_data.screen);
627 width = mode->w;
628 height = mode->h;
629 }
630
631 if (!create_surfaces(width, height)) {
632 return FALSE;
633 }
634
635 return TRUE;
636}
637
638/**********************************************************************/
641 void update_main_screen(void)
642{
643 if (render_dirty) {
644 SDL_UpdateTexture(main_data.maintext, NULL,
645 main_surface->pixels, main_surface->pitch);
646 SDL_RenderClear(main_data.renderer);
647 SDL_RenderTexture(main_data.renderer, main_data.maintext, NULL, NULL);
648 SDL_RenderPresent(main_data.renderer);
649
650 render_dirty = FALSE;
651 }
652}
653
654/**********************************************************************/
657 int main_window_width(void)
658{
659 return main_surface->w;
660}
661
662/**********************************************************************/
665 int main_window_height(void)
666{
667 return main_surface->h;
668}
669
670/**********************************************************************/
673 int fill_rect_alpha(SDL_Surface *surf, SDL_Rect *prect,
674 SDL_Color *pcolor)
675{
676 SDL_Surface *colorbar;
677
678 if (prect && (prect->x < - prect->w || prect->x >= surf->w
679 || prect->y < - prect->h || prect->y >= surf->h)) {
680 return -2;
681 }
682
683 if (pcolor->a == 255) {
684 return SDL_FillSurfaceRect(surf, prect,
685 SDL_MapRGB(surf->format,
686 pcolor->r, pcolor->g, pcolor->b));
687 }
688
689 if (!pcolor->a) {
690 return -3;
691 }
692
693 colorbar = create_surf(surf->w, surf->h, 0);
694
695 SDL_FillSurfaceRect(colorbar, prect,
696 SDL_MapRGB(surf->format,
697 pcolor->r, pcolor->g, pcolor->b));
698
699 return alphablit(colorbar, NULL, surf, NULL, pcolor->a);
700}
701
702/**********************************************************************/
705 bool correct_rect_region(SDL_Rect *prect)
706{
707 int ww = prect->w, hh = prect->h;
708
709 if (prect->x < 0) {
710 ww += prect->x;
711 prect->x = 0;
712 }
713
714 if (prect->y < 0) {
715 hh += prect->y;
716 prect->y = 0;
717 }
718
719 if (prect->x + ww > main_window_width()) {
720 ww = main_window_width() - prect->x;
721 }
722
723 if (prect->y + hh > main_window_height()) {
724 hh = main_window_height() - prect->y;
725 }
726
727 /* End Correction */
728
729 if (ww <= 0 || hh <= 0) {
730 return FALSE; /* surprise :) */
731 } else {
732 prect->w = ww;
733 prect->h = hh;
734 }
735
736 return TRUE;
737}
738
739/**********************************************************************/
742 bool is_in_rect_area(int x, int y, const SDL_Rect *rect)
743{
744 return ((x >= rect->x) && (x < rect-> x + rect->w)
745 && (y >= rect->y) && (y < rect-> y + rect->h));
746}
747
748/* ===================================================================== */
749
750/**********************************************************************/
753 void get_smaller_surface_rect(SDL_Surface *surf, SDL_Rect *rect)
754{
755 int w, h, x, y;
756 Uint16 minX, maxX, minY, maxY;
757 Uint32 colorkey;
758 Uint32 mask;
759
760 fc_assert(surf != NULL);
761 fc_assert(rect != NULL);
762
763 minX = surf->w;
764 maxX = 0;
765 minY = surf->h;
766 maxY = 0;
767
768 if (SDL_GetSurfaceColorKey(surf, &colorkey) < 0) {
769 /* Use alpha instead of colorkey */
770 mask = surf->format->Amask;
771 colorkey = 0;
772 } else {
773 mask = 0xffffffff;
774 }
775
776 lock_surf(surf);
777
778 switch (surf->format->bytes_per_pixel) {
779 case 1:
780 {
781 Uint8 *pixel = (Uint8 *)surf->pixels;
782 Uint8 *start = pixel;
783
784 x = 0;
785 y = 0;
786 w = surf->w;
787 h = surf->h;
788 while (h--) {
789 do {
790 if (*pixel != colorkey) {
791 if (minY > y) {
792 minY = y;
793 }
794
795 if (minX > x) {
796 minX = x;
797 }
798 break;
799 }
800 pixel++;
801 x++;
802 } while (--w > 0);
803 w = surf->w;
804 x = 0;
805 y++;
806 pixel = start + surf->pitch;
807 start = pixel;
808 }
809
810 w = surf->w;
811 h = surf->h;
812 x = w - 1;
813 y = h - 1;
814 pixel = (Uint8 *)((Uint8 *)surf->pixels + (y * surf->pitch) + x);
815 start = pixel;
816 while (h--) {
817 do {
818 if (*pixel != colorkey) {
819 if (maxY < y) {
820 maxY = y;
821 }
822
823 if (maxX < x) {
824 maxX = x;
825 }
826 break;
827 }
828 pixel--;
829 x--;
830 } while (--w > 0);
831 w = surf->w;
832 x = w - 1;
833 y--;
834 pixel = start - surf->pitch;
835 start = pixel;
836 }
837 break;
838 }
839 case 2:
840 {
841 Uint16 *pixel = (Uint16 *)surf->pixels;
842 Uint16 *start = pixel;
843
844 x = 0;
845 y = 0;
846 w = surf->w;
847 h = surf->h;
848 while (h--) {
849 do {
850 if (*pixel != colorkey) {
851 if (minY > y) {
852 minY = y;
853 }
854
855 if (minX > x) {
856 minX = x;
857 }
858 break;
859 }
860 pixel++;
861 x++;
862 } while (--w > 0);
863 w = surf->w;
864 x = 0;
865 y++;
866 pixel = start + surf->pitch / 2;
867 start = pixel;
868 }
869
870 w = surf->w;
871 h = surf->h;
872 x = w - 1;
873 y = h - 1;
874 pixel = ((Uint16 *)surf->pixels + (y * surf->pitch / 2) + x);
875 start = pixel;
876 while (h--) {
877 do {
878 if (*pixel != colorkey) {
879 if (maxY < y) {
880 maxY = y;
881 }
882
883 if (maxX < x) {
884 maxX = x;
885 }
886 break;
887 }
888 pixel--;
889 x--;
890 } while (--w > 0);
891 w = surf->w;
892 x = w - 1;
893 y--;
894 pixel = start - surf->pitch / 2;
895 start = pixel;
896 }
897 break;
898 }
899 case 3:
900 {
901 Uint8 *pixel = (Uint8 *)surf->pixels;
902 Uint8 *start = pixel;
903 Uint32 color;
904
905 x = 0;
906 y = 0;
907 w = surf->w;
908 h = surf->h;
909 while (h--) {
910 do {
911 if (is_bigendian()) {
912 color = (pixel[0] << 16 | pixel[1] << 8 | pixel[2]);
913 } else {
914 color = (pixel[0] | pixel[1] << 8 | pixel[2] << 16);
915 }
916 if (color != colorkey) {
917 if (minY > y) {
918 minY = y;
919 }
920
921 if (minX > x) {
922 minX = x;
923 }
924 break;
925 }
926 pixel += 3;
927 x++;
928 } while (--w > 0);
929 w = surf->w;
930 x = 0;
931 y++;
932 pixel = start + surf->pitch / 3;
933 start = pixel;
934 }
935
936 w = surf->w;
937 h = surf->h;
938 x = w - 1;
939 y = h - 1;
940 pixel = (Uint8 *)((Uint8 *)surf->pixels + (y * surf->pitch) + x * 3);
941 start = pixel;
942 while (h--) {
943 do {
944 if (is_bigendian()) {
945 color = (pixel[0] << 16 | pixel[1] << 8 | pixel[2]);
946 } else {
947 color = (pixel[0] | pixel[1] << 8 | pixel[2] << 16);
948 }
949 if (color != colorkey) {
950 if (maxY < y) {
951 maxY = y;
952 }
953
954 if (maxX < x) {
955 maxX = x;
956 }
957 break;
958 }
959 pixel -= 3;
960 x--;
961 } while (--w > 0);
962 w = surf->w;
963 x = w - 1;
964 y--;
965 pixel = start - surf->pitch / 3;
966 start = pixel;
967 }
968 break;
969 }
970 case 4:
971 {
972 Uint32 *pixel = (Uint32 *)surf->pixels;
973 Uint32 *start = pixel;
974
975 x = 0;
976 y = 0;
977 w = surf->w;
978 h = surf->h;
979 while (h--) {
980 do {
981 if (((*pixel) & mask) != colorkey) {
982 if (minY > y) {
983 minY = y;
984 }
985
986 if (minX > x) {
987 minX = x;
988 }
989 break;
990 }
991 pixel++;
992 x++;
993 } while (--w > 0);
994 w = surf->w;
995 x = 0;
996 y++;
997 pixel = start + surf->pitch / 4;
998 start = pixel;
999 }
1000
1001 w = surf->w;
1002 h = surf->h;
1003 x = w - 1;
1004 y = h - 1;
1005 pixel = ((Uint32 *)surf->pixels + (y * surf->pitch / 4) + x);
1006 start = pixel;
1007 while (h--) {
1008 do {
1009 if (((*pixel) & mask) != colorkey) {
1010 if (maxY < y) {
1011 maxY = y;
1012 }
1013
1014 if (maxX < x) {
1015 maxX = x;
1016 }
1017 break;
1018 }
1019 pixel--;
1020 x--;
1021 } while (--w > 0);
1022 w = surf->w;
1023 x = w - 1;
1024 y--;
1025 pixel = start - surf->pitch / 4;
1026 start = pixel;
1027 }
1028 break;
1029 }
1030 }
1031
1032 unlock_surf(surf);
1033 rect->x = minX;
1034 rect->y = minY;
1035 rect->w = maxX - minX + 1;
1036 rect->h = maxY - minY + 1;
1037}
1038
1039/**********************************************************************/
1042 SDL_Surface *crop_visible_part_from_surface(SDL_Surface *psrc)
1043{
1044 SDL_Rect src;
1045
1046 get_smaller_surface_rect(psrc, &src);
1047
1048 return crop_rect_from_surface(psrc, &src);
1049}
1050
1051/**********************************************************************/
1054 SDL_Surface *resize_surface(const SDL_Surface *psrc, Uint16 new_width,
1055 Uint16 new_height, int smooth)
1056{
1057 if (psrc == NULL) {
1058 return NULL;
1059 }
1060
1061 return zoomSurface((SDL_Surface*)psrc,
1062 (double)new_width / psrc->w,
1063 (double)new_height / psrc->h,
1064 smooth);
1065}
1066
1067/**********************************************************************/
1074 SDL_Surface *resize_surface_box(const SDL_Surface *psrc,
1075 Uint16 new_width, Uint16 new_height,
1076 int smooth, bool scale_up,
1077 bool absolute_dimensions)
1078{
1079 SDL_Surface *tmp_surface, *result;
1080
1081 if (psrc == NULL) {
1082 return NULL;
1083 }
1084
1085 if (!(!scale_up && ((new_width >= psrc->w) && (new_height >= psrc->h)))) {
1086 if ((new_width - psrc->w) <= (new_height - psrc->h)) {
1087 /* horizontal limit */
1088 tmp_surface = zoomSurface((SDL_Surface*)psrc,
1089 (double)new_width / psrc->w,
1090 (double)new_width / psrc->w,
1091 smooth);
1092 } else {
1093 /* vertical limit */
1094 tmp_surface = zoomSurface((SDL_Surface*)psrc,
1095 (double)new_height / psrc->h,
1096 (double)new_height / psrc->h,
1097 smooth);
1098 }
1099 } else {
1100 tmp_surface = zoomSurface((SDL_Surface*)psrc,
1101 1.0,
1102 1.0,
1103 smooth);
1104 }
1105
1106 if (absolute_dimensions) {
1107 SDL_Rect area = {
1108 (new_width - tmp_surface->w) / 2,
1109 (new_height - tmp_surface->h) / 2,
1110 0, 0
1111 };
1112
1113 result = create_surf(new_width, new_height, SDL_SWSURFACE);
1114 alphablit(tmp_surface, NULL, result, &area, 255);
1115 FREESURFACE(tmp_surface);
1116 } else {
1117 result = tmp_surface;
1118 }
1119
1120 return result;
1121}
1122
1123/**********************************************************************/
1126 SDL_Surface *copy_surface(SDL_Surface *src)
1127{
1128 SDL_Surface *copy = SDL_CreateSurface(src->w, src->h, src->format->format);
1129
1130 alphablit(src, NULL, copy, NULL, 255);
1131
1132 return copy;
1133}
1134
1135/* ============ Freeciv game graphics function =========== */
1136
1137/**********************************************************************/
1140 bool is_view_supported(enum ts_type type)
1141{
1142 switch (type) {
1143 case TS_ISOMETRIC:
1144 case TS_OVERHEAD:
1145 return TRUE;
1146 }
1147
1148 return FALSE;
1149}
1150
1151/**********************************************************************/
1154 void tileset_type_set(enum ts_type type)
1155{
1156}
1157
1158/**********************************************************************/
1161 void create_frame(SDL_Surface *dest, Sint16 left, Sint16 top,
1162 Sint16 width, Sint16 height,
1163 SDL_Color *pcolor)
1164{
1165 struct color gsdl3_color = { .color = pcolor };
1166 struct sprite *vertical = create_sprite(1, height, &gsdl3_color);
1167 struct sprite *horizontal = create_sprite(width, 1, &gsdl3_color);
1168 SDL_Rect tmp, dst = { .x = left, .y = top, .w = 0, .h = 0 };
1169
1170 tmp = dst;
1171 alphablit(vertical->psurface, NULL, dest, &tmp, 255);
1172
1173 dst.x += width - 1;
1174 tmp = dst;
1175 alphablit(vertical->psurface, NULL, dest, &tmp, 255);
1176
1177 dst.x = left;
1178 tmp = dst;
1179 alphablit(horizontal->psurface, NULL, dest, &tmp, 255);
1180
1181 dst.y += height - 1;
1182 tmp = dst;
1183 alphablit(horizontal->psurface, NULL, dest, &tmp, 255);
1184
1185 free_sprite(horizontal);
1186 free_sprite(vertical);
1187}
1188
1189/**********************************************************************/
1192 void create_line(SDL_Surface *dest, Sint16 x0, Sint16 y0, Sint16 x1, Sint16 y1,
1193 SDL_Color *pcolor)
1194{
1195 int xl = x0 < x1 ? x0 : x1;
1196 int xr = x0 < x1 ? x1 : x0;
1197 int yt = y0 < y1 ? y0 : y1;
1198 int yb = y0 < y1 ? y1 : y0;
1199 int w = (xr - xl) + 1;
1200 int h = (yb - yt) + 1;
1201 struct sprite *spr;
1202 SDL_Rect dst = { xl, yt, w, h };
1203 SDL_Color *pcol;
1204 struct color gsdl3_color;
1205 int l = MAX((xr - xl) + 1, (yb - yt) + 1);
1206 int i;
1207
1208 pcol = fc_malloc(sizeof(pcol));
1209 pcol->r = pcolor->r;
1210 pcol->g = pcolor->g;
1211 pcol->b = pcolor->b;
1212 pcol->a = 0; /* Fill with transparency */
1213
1214 gsdl3_color.color = pcol;
1215 spr = create_sprite(w, h, &gsdl3_color);
1216
1217 lock_surf(spr->psurface);
1218
1219 /* Set off transparency from pixels belonging to the line */
1220 if ((x0 <= x1 && y0 <= y1)
1221 || (x1 <= x0 && y1 <= y0)) {
1222 for (i = 0; i < l; i++) {
1223 int cx = (xr - xl) * i / l;
1224 int cy = (yb - yt) * i / l;
1225
1226 *((Uint32 *)spr->psurface->pixels + spr->psurface->w * cy + cx)
1227 |= (pcolor->a << spr->psurface->format->Ashift);
1228 }
1229 } else {
1230 for (i = 0; i < l; i++) {
1231 int cx = (xr - xl) * i / l;
1232 int cy = yb - yt - (yb - yt) * i / l;
1233
1234 *((Uint32 *)spr->psurface->pixels + spr->psurface->w * cy + cx)
1235 |= (pcolor->a << spr->psurface->format->Ashift);
1236 }
1237 }
1238
1239 unlock_surf(spr->psurface);
1240
1241 alphablit(spr->psurface, NULL, dest, &dst, 255);
1242
1243 free_sprite(spr);
1244 free(pcol);
1245}
height
struct canvas int int struct sprite int int int int height
Definition canvas_g.h:44
pcolor
struct canvas int int int int struct sprite *sprite struct canvas struct color * pcolor
Definition canvas_g.h:56
width
struct canvas int int struct sprite int int int width
Definition canvas_g.h:44
incite_cost
char * incite_cost
Definition comments.c:74
fcintl.h
_
#define _(String)
Definition fcintl.h:67
is_view_supported
bool is_view_supported(enum ts_type type)
Definition graphics.c:53
tileset_type_set
void tileset_type_set(enum ts_type type)
Definition graphics.c:67
type
GType type
Definition repodlgs.c:1313
free_sprite
void free_sprite(struct sprite *s)
Definition sprite.c:278
create_sprite
struct sprite * create_sprite(int width, int height, struct color *pcolor)
Definition sprite.c:84
resize_surface
SDL_Surface * resize_surface(const SDL_Surface *psrc, Uint16 new_width, Uint16 new_height, int smooth)
Definition graphics.c:1237
set_video_mode
bool set_video_mode(unsigned width, unsigned height, unsigned flags_in)
Definition graphics.c:636
getpixel
Uint32 getpixel(SDL_Surface *surf, Sint16 x, Sint16 y)
Definition graphics.c:430
main_window_width
int main_window_width(void)
Definition graphics.c:685
layer_rect_to_screen_rect
void layer_rect_to_screen_rect(struct gui_layer *gui_layer, SDL_Rect *dest_rect)
Definition graphics.c:185
load_surf
SDL_Surface * load_surf(const char *fname)
Definition graphics.c:307
create_surf_with_format
SDL_Surface * create_surf_with_format(SDL_PixelFormat *pf, int width, int height, Uint32 flags)
Definition graphics.c:328
init_sdl
void init_sdl(int flags)
Definition graphics.c:506
update_main_screen
void update_main_screen(void)
Definition graphics.c:669
remove_gui_layer
void remove_gui_layer(struct gui_layer *gui_layer)
Definition graphics.c:148
create_filled_surface
SDL_Surface * create_filled_surface(Uint16 w, Uint16 h, Uint32 flags, SDL_Color *pcolor)
Definition graphics.c:368
fill_rect_alpha
int fill_rect_alpha(SDL_Surface *surf, SDL_Rect *prect, SDL_Color *pcolor)
Definition graphics.c:865
gui_layer_destroy
void gui_layer_destroy(struct gui_layer **gui_layer)
Definition graphics.c:81
create_line
void create_line(SDL_Surface *dest, Sint16 x0, Sint16 y0, Sint16 x1, Sint16 y1, SDL_Color *pcolor)
Definition graphics.c:1379
copy_surface
SDL_Surface * copy_surface(SDL_Surface *src)
Definition graphics.c:1309
mask_surface
SDL_Surface * mask_surface(SDL_Surface *src, SDL_Surface *mask, int mask_offset_x, int mask_offset_y)
Definition graphics.c:262
gui_layer_new
struct gui_layer * gui_layer_new(int x, int y, SDL_Surface *surface)
Definition graphics.c:66
quit_sdl
void quit_sdl(void)
Definition graphics.c:622
crop_visible_part_from_surface
SDL_Surface * crop_visible_part_from_surface(SDL_Surface *psrc)
Definition graphics.c:1225
crop_rect_from_surface
SDL_Surface * crop_rect_from_surface(SDL_Surface *psource, SDL_Rect *prect)
Definition graphics.c:236
alphablit
int alphablit(SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *dst, SDL_Rect *dstrect, unsigned char alpha_mod)
Definition graphics.c:199
get_gui_layer
struct gui_layer * get_gui_layer(SDL_Surface *surface)
Definition graphics.c:90
is_in_rect_area
bool is_in_rect_area(int x, int y, const SDL_Rect *rect)
Definition graphics.c:925
screen_blit
int screen_blit(SDL_Surface *src, SDL_Rect *srcrect, SDL_Rect *dstrect, unsigned char alpha_mod)
Definition graphics.c:223
main_data
struct sdl2_data main_data
Definition graphics.c:57
main_surface
static SDL_Surface * main_surface
Definition graphics.c:59
blit_entire_src
int blit_entire_src(SDL_Surface *psrc, SDL_Surface *pdest, Sint16 dest_x, Sint16 dest_y)
Definition graphics.c:417
get_first_pixel
Uint32 get_first_pixel(SDL_Surface *surf)
Definition graphics.c:468
convert_surf
SDL_Surface * convert_surf(SDL_Surface *surf_in)
Definition graphics.c:359
create_surf
SDL_Surface * create_surf(int width, int height, Uint32 flags)
Definition graphics.c:351
get_smaller_surface_rect
void get_smaller_surface_rect(SDL_Surface *surf, SDL_Rect *rect)
Definition graphics.c:936
add_gui_layer
struct gui_layer * add_gui_layer(int width, int height)
Definition graphics.c:112
clear_surface
int clear_surface(SDL_Surface *surf, SDL_Rect *dstrect)
Definition graphics.c:400
correct_rect_region
bool correct_rect_region(SDL_Rect *prect)
Definition graphics.c:888
screen_rect_to_layer_rect
void screen_rect_to_layer_rect(struct gui_layer *gui_layer, SDL_Rect *dest_rect)
Definition graphics.c:173
create_frame
void create_frame(SDL_Surface *dest, Sint16 left, Sint16 top, Sint16 width, Sint16 height, SDL_Color *pcolor)
Definition graphics.c:1348
free_surfaces
static void free_surfaces(void)
Definition graphics.c:543
create_surfaces
bool create_surfaces(int width, int height)
Definition graphics.c:556
main_window_height
int main_window_height(void)
Definition graphics.c:693
render_dirty
static bool render_dirty
Definition graphics.c:61
resize_surface_box
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:1257
FREESURFACE
#define FREESURFACE(ptr)
Definition graphics.h:322
unlock_surf
#define unlock_surf(surf)
Definition graphics.h:344
lock_surf
#define lock_surf(surf)
Definition graphics.h:333
CF_SWRENDERER
#define CF_SWRENDERER
Definition gui_main.h:64
GUI_SDL_OPTION
#define GUI_SDL_OPTION(optname)
Definition gui_main.h:37
sdl3_client_flags
Uint32 sdl3_client_flags
Definition gui_main.c:93
gui_tilespec.h
themebackgrounds.h
themespec.h
colors.h
graphics.h
mapview.h
log.h
fc_assert
#define fc_assert(condition)
Definition log.h:176
log_fatal
#define log_fatal(message,...)
Definition log.h:100
log_error
#define log_error(message,...)
Definition log.h:103
fc_calloc
#define fc_calloc(n, esz)
Definition mem.h:38
FC_FREE
#define FC_FREE(ptr)
Definition mem.h:41
fc_realloc
#define fc_realloc(ptr, sz)
Definition mem.h:36
fc_malloc
#define fc_malloc(sz)
Definition mem.h:34
MAX
#define MAX(x, y)
Definition shared.h:54
mask
struct sprite int int int int struct sprite * mask
Definition sprite_g.h:32
y
struct sprite int int y
Definition sprite_g.h:31
mask_offset_x
struct sprite int int int int struct sprite int mask_offset_x
Definition sprite_g.h:32
x
struct sprite int x
Definition sprite_g.h:31
mask_offset_y
struct sprite int int int int struct sprite int int mask_offset_y
Definition sprite_g.h:32
color
Definition colors.h:21
color::color
GdkRGBA color
Definition colors.h:22
gui_layer
Definition graphics.h:227
gui_layer::surface
SDL_Surface * surface
Definition graphics.h:229
gui_layer::dest_rect
SDL_Rect dest_rect
Definition graphics.h:228
sdl2_data::guis_count
int guis_count
Definition graphics.h:207
sdl2_data::dummy
SDL_Surface * dummy
Definition graphics.h:211
sdl2_data::renderer
SDL_Renderer * renderer
Definition graphics.h:213
sdl2_data::maintext
SDL_Texture * maintext
Definition graphics.h:212
sdl2_data::gui
struct gui_layer * gui
Definition graphics.h:215
sdl2_data::rects_count
int rects_count
Definition graphics.h:206
sdl2_data::guis
struct gui_layer ** guis
Definition graphics.h:216
sdl2_data::screen
SDL_Window * screen
Definition graphics.h:209
sdl2_data::map
SDL_Surface * map
Definition graphics.h:210
sdl3_data
Definition graphics.h:197
sprite
Definition sprite.h:22
is_bigendian
static bool is_bigendian(void)
Definition support.h:229
TRUE
#define TRUE
Definition support.h:46
FALSE
#define FALSE
Definition support.h:47
tilespec.h