Freeciv-3.3
Loading...
Searching...
No Matches
sprite.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996-2005 - Freeciv Development Team
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#ifdef HAVE_CONFIG_H
15#include <fc_config.h>
16#endif
17
18/* utility */
19#include "log.h"
20#include "mem.h"
21#include "shared.h"
22
23/* client/gui-gtk-3.22 */
24#include "colors.h"
25#include "mapview.h"
26
27#include "sprite.h"
28
29#define MAX_FILE_EXTENSIONS 50
30
31/************************************************************************/
53 int x, int y,
54 int width, int height,
55 struct sprite *mask, int mask_offset_x, int mask_offset_y,
56 float scale, bool smooth)
57{
58 struct sprite *new = fc_malloc(sizeof(*new));
59 cairo_t *cr;
60
62
63 new->surface = cairo_surface_create_similar(source->surface,
65 cr = cairo_create(new->surface);
66 cairo_rectangle(cr, 0, 0, width, height);
67 cairo_clip(cr);
68
69 cairo_set_source_surface(cr, source->surface, -x, -y);
70 cairo_paint(cr);
71 if (mask) {
74 cairo_paint(cr);
75 }
76 cairo_destroy(cr);
77
78 return new;
79}
80
81/************************************************************************/
84struct sprite *create_sprite(int width, int height, struct color *pcolor)
85{
86 struct sprite *sprite = fc_malloc(sizeof(*sprite));
87 cairo_t *cr;
88
92
94 width, height);
95
98 cairo_paint(cr);
99 cairo_destroy(cr);
100
101 return sprite;
102}
103
104/************************************************************************/
112
113/************************************************************************/
117const char **gfx_fileextensions(void)
118{
119 /* Includes space for hardcoded 'png' and termination NULL */
120 static const char *ext[MAX_FILE_EXTENSIONS + 2] =
121 {
122 NULL
123 };
124
125 if (ext[0] == NULL) {
126 int count = 0;
127 GSList *formats = gdk_pixbuf_get_formats();
128 GSList *next = formats;
129
130 while ((next = g_slist_next(next)) != NULL && count < MAX_FILE_EXTENSIONS) {
131 GdkPixbufFormat *format = g_slist_nth_data(next, 0);
133 int i;
134
135 /* Consider .png to be supported even when there's no mime-type called "png" */
136 ext[count++] = fc_strdup("png");
137
138 for (i = 0; mimes[i] != NULL && count < MAX_FILE_EXTENSIONS; i++) {
139 char *end = strstr(mimes[i], "/");
140
141 if (end != NULL) {
142 ext[count++] = fc_strdup(end + 1);
143 }
144 }
145
147 }
148
149 g_slist_free(formats);
150
151 ext[count] = NULL;
152 }
153
154 return ext;
155}
156
157/************************************************************************/
160static void surf_destroy_callback(void *data)
161{
162 free(data);
163}
164
165/************************************************************************/
170struct sprite *load_gfxfile(const char *filename, bool svgflag)
171{
172 struct sprite *spr;
173 GError *err = NULL;
175 int width;
176 int height;
177 unsigned char *pbdata;
178 int rs;
179 unsigned char *cairo_data;
180 unsigned char *data;
181 int i, j;
182 int cairo_stride;
183 bool has_alpha;
184 int channels;
185
186 if (pb == NULL) {
187 log_error(_("Can't load %s: %s"), filename, err->message);
188 return NULL;
189 }
190
191 spr = fc_malloc(sizeof(*spr));
192 spr->surface = NULL;
193
200
202 if (cairo_stride <= 0) {
203 log_error("Cairo does not give stride for width %d", width);
205
206 return NULL;
207 }
208
210 data = cairo_data;
211
212 for (i = 0; i < height; i++) {
213 for (j = 0; j < width; j++) {
214 if (has_alpha) {
215 unsigned char tmp;
216
217#define MULTI_UNc(a,b) ((a * b - (b / 2)) / 0xFF)
218
219 if (is_bigendian()) {
220 tmp = pbdata[j * channels + 3];
221 data[j * 4 + 3] = MULTI_UNc(pbdata[j * channels + 2], tmp);
222 data[j * 4 + 2] = MULTI_UNc(pbdata[j * channels + 1], tmp);
223 data[j * 4 + 1] = MULTI_UNc(pbdata[j * channels + 0], tmp);
224 data[j * 4 + 0] = tmp;
225 } else {
226 tmp = MULTI_UNc(pbdata[j * channels + 2], pbdata[j * channels + 3]);
227 data[j * 4 + 1] = MULTI_UNc(pbdata[j * channels + 1],
228 pbdata[j * channels + 3]);
229 data[j * 4 + 2] = MULTI_UNc(pbdata[j * channels + 0],
230 pbdata[j * channels + 3]);
231 data[j * 4 + 0] = tmp;
232 data[j * 4 + 3] = pbdata[j * channels + 3];
233 }
234
235#undef MULTI_UNc
236
237 } else {
238 data[j * 4 + 3] = 255;
239 data[j * 4 + 0] = pbdata[j * channels + 2];
240 data[j * 4 + 1] = pbdata[j * channels + 1];
241 data[j * 4 + 2] = pbdata[j * channels + 0];
242 }
243 }
244
245 data += cairo_stride;
246 pbdata += rs;
247 }
248
250
253 if (spr->surface == NULL
255 log_error("Cairo image surface creation error");
258
259 return NULL;
260 }
261
263
265
267 log_fatal("Failed reading graphics file: \"%s\"", filename);
268
270 }
271
272 return spr;
273}
274
275/************************************************************************/
278void free_sprite(struct sprite * s)
279{
280 if (s->surface != NULL) {
282 }
283
284 free(s);
285}
286
287/************************************************************************/
291struct sprite *sprite_scale(struct sprite *src, int new_w, int new_h)
292{
293 cairo_t *cr;
294 struct sprite *new = fc_malloc(sizeof(*new));
295 int width, height;
296
298
299 new->surface = cairo_surface_create_similar(src->surface,
301
302 cr = cairo_create(new->surface);
303 cairo_save(cr);
305 cairo_paint(cr);
306 cairo_restore(cr);
307 cairo_scale(cr, (double) new_w / (double) width, (double) new_h / (double) height);
308 cairo_set_source_surface(cr, src->surface, 0, 0);
309 cairo_paint(cr);
310
311 cairo_destroy(cr);
312
313 return new;
314}
315
316/************************************************************************/
321void sprite_get_bounding_box(struct sprite * sprite, int *start_x,
322 int *start_y, int *end_x, int *end_y)
323{
324 unsigned char *data = cairo_image_surface_get_data(sprite->surface);
327 int i, j;
328 int endian;
329
330 if (is_bigendian()) {
331 endian = 0;
332 } else {
333 endian = 3;
334 }
335
337
338 /* parses mask image for the first column that contains a visible pixel */
339 *start_x = -1;
340 for (i = 0; i < width && *start_x == -1; i++) {
341 for (j = 0; j < height; j++) {
342 if (data[(j * width + i) * 4 + endian]) {
343 *start_x = i;
344 break;
345 }
346 }
347 }
348
349 /* parses mask image for the last column that contains a visible pixel */
350 *end_x = -1;
351 for (i = width - 1; i >= *start_x && *end_x == -1; i--) {
352 for (j = 0; j < height; j++) {
353 if (data[(j * width + i) * 4 + endian]) {
354 *end_x = i;
355 break;
356 }
357 }
358 }
359
360 /* parses mask image for the first row that contains a visible pixel */
361 *start_y = -1;
362 for (i = 0; i < height && *start_y == -1; i++) {
363 for (j = *start_x; j <= *end_x; j++) {
364 if (data[(i * width + j) * 4 + endian]) {
365 *start_y = i;
366 break;
367 }
368 }
369 }
370
371 /* parses mask image for the last row that contains a visible pixel */
372 *end_y = -1;
373 for (i = height - 1; i >= *end_y && *end_y == -1; i--) {
374 for (j = *start_x; j <= *end_x; j++) {
375 if (data[(i * width + j) * 4 + endian]) {
376 *end_y = i;
377 break;
378 }
379 }
380 }
381}
382
383/************************************************************************/
386struct sprite *crop_blankspace(struct sprite *s)
387{
388 int x1, y1, x2, y2;
389
390 sprite_get_bounding_box(s, &x1, &y1, &x2, &y2);
391
392 return crop_sprite(s, x1, y1, x2 - x1 + 1, y2 - y1 + 1, NULL, -1, -1,
393 1.0, FALSE);
394}
395
396/************************************************************************/
403{
404 int width, height;
405
406 if (!sprite) {
407 return NULL;
408 }
409
411
413}
414
415/************************************************************************/
419{
420 cairo_t *cr;
422 GdkPixbuf *pb;
423 unsigned char *pixels;
424 int rowstride;
425 int i;
426
430
433
434 cr = cairo_create(tmpsurf);
435 cairo_save(cr);
437 cairo_paint(cr);
438 cairo_restore(cr);
439 cairo_set_source_surface(cr, surf, 0, 0);
440 cairo_paint(cr);
441 cairo_destroy(cr);
442
443 for (i = height; i > 0; i--) {
444 unsigned char *p = pixels;
445 unsigned char *end = p + 4 * width;
446 unsigned char tmp;
447
448#define DIV_UNc(a,b) (((guint16) (a) * 0xFF + ((b) / 2)) / (b))
449
450 while (p < end) {
451 tmp = p[0];
452
453 if (is_bigendian()) {
454 if (tmp != 0) {
455 p[0] = DIV_UNc(p[1], tmp);
456 p[1] = DIV_UNc(p[2], tmp);
457 p[2] = DIV_UNc(p[3], tmp);
458 p[3] = tmp;
459 } else {
460 p[1] = p[2] = p[3] = 0;
461 }
462 } else {
463 if (p[3] != 0) {
464 p[0] = DIV_UNc(p[2], p[3]);
465 p[1] = DIV_UNc(p[1], p[3]);
466 p[2] = DIV_UNc(tmp, p[3]);
467 } else {
468 p[0] = p[1] = p[2] = 0;
469 }
470 }
471
472 p += 4;
473 }
474
475#undef DIV_UNc
476
477 pixels += rowstride;
478 }
479
481
482 return pb;
483}
484
485/************************************************************************/
495{
496 struct drawn_sprite sprs[80];
497 int count, w, h, canvas_x, canvas_y;
500 cairo_t *cr;
501
504
506 canvas_x = 0;
507 canvas_y = 0;
508
511 cairo_paint(cr);
512 cairo_destroy(cr);
513
516
519
520 return pixbuf;
521}
522
523/************************************************************************/
526struct sprite *load_gfxnumber(int num)
527{
528 int width, height;
529 char buf[10];
530 struct sprite *spr;
531 struct color *sprcolor = color_alloc(0xff, 0xff, 0x00);
532 struct color *textcolor = color_alloc(0x00, 0x00, 0x00);
533 cairo_t *cr;
534 int border = 2;
535
536 fc_snprintf(buf, sizeof(buf), "%d", num);
538
540
541 cr = cairo_create(spr->surface);
542
544
545 cairo_destroy(cr);
546
549
550 return spr;
551}
struct canvas int int struct sprite int int int int height
Definition canvas_g.h:44
struct canvas int int int int struct sprite *sprite struct canvas struct color * pcolor
Definition canvas_g.h:56
struct canvas int int canvas_y
Definition canvas_g.h:43
struct canvas int canvas_x
Definition canvas_g.h:43
struct canvas int int struct sprite int int int width
Definition canvas_g.h:44
char * incite_cost
Definition comments.c:76
#define _(String)
Definition fcintl.h:67
void get_text_size(int *width, int *height, enum client_font font, const char *text)
Definition canvas.c:341
void surface_put_text(cairo_t *cr, int x, int y, float zoom, enum client_font font, struct color *pcolor, const char *text)
Definition canvas.c:396
#define FC_STATIC_CANVAS_INIT
Definition canvas.h:28
struct color * color_alloc(int r, int g, int b)
Definition colors.c:38
void color_free(struct color *color)
Definition colors.c:53
static GtkWidget * source
Definition gotodlg.c:58
#define MULTI_UNc(a, b)
static void surf_destroy_callback(void *data)
Definition sprite.c:160
void free_sprite(struct sprite *s)
Definition sprite.c:278
struct sprite * create_sprite(int width, int height, struct color *pcolor)
Definition sprite.c:84
struct sprite * sprite_scale(struct sprite *src, int new_w, int new_h)
Definition sprite.c:291
struct sprite * load_gfxnumber(int num)
Definition sprite.c:526
GdkPixbuf * surface_get_pixbuf(cairo_surface_t *surf, int width, int height)
Definition sprite.c:418
#define DIV_UNc(a, b)
GdkPixbuf * sprite_get_pixbuf(struct sprite *sprite)
Definition sprite.c:402
GdkPixbuf * create_extra_pixbuf(const struct extra_type *pextra)
Definition sprite.c:494
struct sprite * load_gfxfile(const char *filename, bool svgflag)
Definition sprite.c:170
#define MAX_FILE_EXTENSIONS
Definition sprite.c:29
void sprite_get_bounding_box(struct sprite *sprite, int *start_x, int *start_y, int *end_x, int *end_y)
Definition sprite.c:321
struct sprite * crop_blankspace(struct sprite *s)
Definition sprite.c:386
const char ** gfx_fileextensions(void)
Definition sprite.c:117
#define fc_assert(condition)
Definition log.h:177
#define fc_assert_ret_val(condition, val)
Definition log.h:195
#define log_fatal(message,...)
Definition log.h:101
#define log_error(message,...)
Definition log.h:104
void put_drawn_sprites(struct canvas *pcanvas, float zoom, int canvas_x, int canvas_y, int count, struct drawn_sprite *pdrawn, bool fog)
#define fc_strdup(str)
Definition mem.h:43
#define fc_malloc(sz)
Definition mem.h:34
struct sprite int int int int struct sprite * mask
Definition sprite_g.h:32
struct sprite int int y
Definition sprite_g.h:31
struct sprite int int int int struct sprite int int float scale
Definition sprite_g.h:33
struct sprite int int int int struct sprite int mask_offset_x
Definition sprite_g.h:32
struct sprite int x
Definition sprite_g.h:31
crop_sprite
Definition sprite_g.h:30
struct sprite int int int int struct sprite int int float bool smooth get_sprite_dimensions
Definition sprite_g.h:36
struct sprite int int int int struct sprite int int mask_offset_y
Definition sprite_g.h:32
cairo_surface_t * surface
Definition canvas.h:23
Definition colors.h:21
cairo_surface_t * surface
Definition sprite.h:23
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:960
static bool is_bigendian(void)
Definition support.h:235
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
int fill_basic_extra_sprite_array(const struct tileset *t, struct drawn_sprite *sprs, const struct extra_type *pextra)
Definition tilespec.c:7428
int tileset_tile_height(const struct tileset *t)
Definition tilespec.c:791
int tileset_tile_width(const struct tileset *t)
Definition tilespec.c:779