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)
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 ***********************************************************************/
15 #include <fc_config.h>
23 /****************************************************************************
24 Create a canvas of the given size.
25 ****************************************************************************/
26 struct canvas
*canvas_create(int width
, int height
)
28 struct canvas
*result
= fc_malloc(sizeof(*result
));
30 result
->type
= CANVAS_PIXMAP
;
31 result
->v
.pixmap
= gdk_pixmap_new(root_window
, width
, height
, -1);
35 /****************************************************************************
36 Free any resources associated with this canvas and the canvas struct
38 ****************************************************************************/
39 void canvas_free(struct canvas
*store
)
41 if (store
->type
== CANVAS_PIXMAP
) {
42 g_object_unref(store
->v
.pixmap
);
47 /****************************************************************************
48 Set canvas zoom for future drawing operations.
49 ****************************************************************************/
50 void canvas_set_zoom(struct canvas
*store
, float zoom
)
52 /* gtk2-client has no zoom support */
55 /****************************************************************************
56 This gui has zoom support.
57 ****************************************************************************/
58 bool has_zoom_support(void)
63 /****************************************************************************
64 Copies an area from the source canvas to the destination canvas.
65 ****************************************************************************/
66 void canvas_copy(struct canvas
*dest
, struct canvas
*src
,
67 int src_x
, int src_y
, int dest_x
, int dest_y
,
68 int width
, int height
)
70 if (dest
->type
== src
->type
) {
71 if (src
->type
== CANVAS_PIXMAP
) {
72 gdk_draw_drawable(dest
->v
.pixmap
, fill_bg_gc
, src
->v
.pixmap
,
73 src_x
, src_y
, dest_x
, dest_y
, width
, height
);
78 /****************************************************************************
79 Place part of a (possibly masked) sprite on a pixmap.
80 ****************************************************************************/
81 static void pixmap_put_sprite(GdkDrawable
*pixmap
,
82 int pixmap_x
, int pixmap_y
,
83 struct sprite
*ssprite
,
84 int offset_x
, int offset_y
,
85 int width
, int height
)
87 if (ssprite
->pixmap
) {
89 gdk_gc_set_clip_origin(civ_gc
, pixmap_x
, pixmap_y
);
90 gdk_gc_set_clip_mask(civ_gc
, ssprite
->mask
);
93 gdk_draw_drawable(pixmap
, civ_gc
, ssprite
->pixmap
,
95 pixmap_x
+ offset_x
, pixmap_y
+ offset_y
,
96 MIN(width
, MAX(0, ssprite
->width
- offset_x
)),
97 MIN(height
, MAX(0, ssprite
->height
- offset_y
)));
99 gdk_gc_set_clip_mask(civ_gc
, NULL
);
101 gdk_draw_pixbuf(pixmap
, civ_gc
, ssprite
->pixbuf
,
103 pixmap_x
+ offset_x
, pixmap_y
+ offset_y
,
104 MIN(width
, MAX(0, ssprite
->width
- offset_x
)),
105 MIN(height
, MAX(0, ssprite
->height
- offset_y
)),
106 GDK_RGB_DITHER_NONE
, 0, 0);
110 /****************************************************************************
111 Draw some or all of a sprite onto the mapview or citydialog canvas.
112 ****************************************************************************/
113 void canvas_put_sprite(struct canvas
*pcanvas
,
114 int canvas_x
, int canvas_y
,
115 struct sprite
*sprite
,
116 int offset_x
, int offset_y
, int width
, int height
)
118 switch (pcanvas
->type
) {
120 pixmap_put_sprite(pcanvas
->v
.pixmap
, canvas_x
, canvas_y
,
121 sprite
, offset_x
, offset_y
, width
, height
);
124 gtk_pixcomm_copyto(pcanvas
->v
.pixcomm
, sprite
, canvas_x
, canvas_y
);
128 GdkPixbuf
*src
, *dst
;
130 /* FIXME: is this right??? */
132 offset_x
-= canvas_x
;
136 offset_y
-= canvas_y
;
141 src
= sprite_get_pixbuf(sprite
);
142 dst
= pcanvas
->v
.pixbuf
;
143 gdk_pixbuf_composite(src
, dst
, canvas_x
, canvas_y
,
145 MIN(gdk_pixbuf_get_width(dst
), gdk_pixbuf_get_width(src
))),
147 MIN(gdk_pixbuf_get_height(dst
), gdk_pixbuf_get_height(src
))),
148 canvas_x
- offset_x
, canvas_y
- offset_y
,
149 1.0, 1.0, GDK_INTERP_NEAREST
, 255);
157 /****************************************************************************
158 Draw a full sprite onto the mapview or citydialog canvas.
159 ****************************************************************************/
160 void canvas_put_sprite_full(struct canvas
*pcanvas
,
161 int canvas_x
, int canvas_y
,
162 struct sprite
*sprite
)
164 canvas_put_sprite(pcanvas
, canvas_x
, canvas_y
, sprite
,
165 0, 0, sprite
->width
, sprite
->height
);
168 /****************************************************************************
169 Draw a full sprite onto the canvas. If "fog" is specified draw it with
171 ****************************************************************************/
172 void canvas_put_sprite_fogged(struct canvas
*pcanvas
,
173 int canvas_x
, int canvas_y
,
174 struct sprite
*psprite
,
175 bool fog
, int fog_x
, int fog_y
)
177 if (pcanvas
->type
== CANVAS_PIXMAP
) {
178 pixmap_put_overlay_tile_draw(pcanvas
->v
.pixmap
, canvas_x
, canvas_y
,
183 /****************************************************************************
184 Draw a filled-in colored rectangle onto the mapview or citydialog canvas.
185 ****************************************************************************/
186 void canvas_put_rectangle(struct canvas
*pcanvas
,
187 struct color
*pcolor
,
188 int canvas_x
, int canvas_y
, int width
, int height
)
190 GdkColor
*col
= &pcolor
->color
;
192 switch (pcanvas
->type
) {
194 gdk_gc_set_foreground(fill_bg_gc
, col
);
195 gdk_draw_rectangle(pcanvas
->v
.pixmap
, fill_bg_gc
, TRUE
,
196 canvas_x
, canvas_y
, width
, height
);
199 gtk_pixcomm_fill(pcanvas
->v
.pixcomm
, col
);
202 gdk_pixbuf_fill(pcanvas
->v
.pixbuf
,
203 ((guint32
)(col
->red
& 0xff00) << 16)
204 | ((col
->green
& 0xff00) << 8) | (col
->blue
& 0xff00) | 0xff);
211 /****************************************************************************
212 Fill the area covered by the sprite with the given color.
213 ****************************************************************************/
214 void canvas_fill_sprite_area(struct canvas
*pcanvas
,
215 struct sprite
*psprite
,
216 struct color
*pcolor
,
217 int canvas_x
, int canvas_y
)
219 if (pcanvas
->type
== CANVAS_PIXMAP
) {
220 gdk_gc_set_clip_origin(fill_bg_gc
, canvas_x
, canvas_y
);
221 gdk_gc_set_clip_mask(fill_bg_gc
, sprite_get_mask(psprite
));
222 gdk_gc_set_foreground(fill_bg_gc
, &pcolor
->color
);
224 gdk_draw_rectangle(pcanvas
->v
.pixmap
, fill_bg_gc
, TRUE
,
225 canvas_x
, canvas_y
, psprite
->width
, psprite
->height
);
227 gdk_gc_set_clip_mask(fill_bg_gc
, NULL
);
231 /****************************************************************************
232 Draw a colored line onto the mapview or citydialog canvas.
233 ****************************************************************************/
234 void canvas_put_line(struct canvas
*pcanvas
,
235 struct color
*pcolor
,
236 enum line_type ltype
, int start_x
, int start_y
,
239 if (pcanvas
->type
== CANVAS_PIXMAP
) {
249 case LINE_TILE_FRAME
:
257 gdk_gc_set_foreground(gc
, &pcolor
->color
);
258 gdk_draw_line(pcanvas
->v
.pixmap
, gc
,
259 start_x
, start_y
, start_x
+ dx
, start_y
+ dy
);
263 /****************************************************************************
264 Draw a colored curved line for the Technology Tree connectors
265 A curved line is: 1 horizontal line, 2 arcs, 1 horizontal line
266 ****************************************************************************/
267 void canvas_put_curved_line(struct canvas
*pcanvas
,
268 struct color
*pcolor
,
269 enum line_type ltype
, int start_x
, int start_y
,
272 if (pcanvas
->type
== CANVAS_PIXMAP
) {
282 case LINE_TILE_FRAME
:
290 gdk_gc_set_foreground(gc
, &pcolor
->color
);
292 /* To begin, work out the endpoints of the curve */
293 /* and initial horizontal stroke */
294 int line1end_x
= start_x
+ 10;
295 int end_x
= start_x
+ dx
;
296 int end_y
= start_y
+ dy
;
298 int arcwidth
= dx
- 10;
299 /* draw a short horizontal line */
300 gdk_draw_line(pcanvas
->v
.pixmap
, gc
,
301 start_x
, start_y
, line1end_x
, start_y
);
303 if (end_y
< start_y
) {
304 /* if end_y is above start_y then the first curve is rising */
305 int archeight
= -dy
+ 1;
307 /* position the BB of the arc */
308 int arcstart_x
= line1end_x
-arcwidth
/2 -1;
309 int arcstart_y
= end_y
-1;
311 /* Draw arc curving up */
312 gdk_draw_arc(pcanvas
->v
.pixmap
, gc
, FALSE
,
313 arcstart_x
, arcstart_y
,
314 arcwidth
, archeight
, 0, -90*64);
316 /* Shift BB to the right */
317 arcstart_x
= arcstart_x
+ arcwidth
;
319 /* draw arc curving across */
320 gdk_draw_arc(pcanvas
->v
.pixmap
, gc
, FALSE
,
321 arcstart_x
, arcstart_y
,
322 arcwidth
, archeight
, 180*64, -90*64);
324 } else { /* end_y is below start_y */
326 int archeight
= dy
+ 1;
329 int arcstart_x
= line1end_x
- arcwidth
/2 -1;
330 int arcstart_y
= start_y
-1;
332 /* Draw arc curving down */
333 gdk_draw_arc(pcanvas
->v
.pixmap
, gc
, FALSE
,
334 arcstart_x
, arcstart_y
,
335 arcwidth
, archeight
, 0, 90*64);
338 arcstart_x
= arcstart_x
+ arcwidth
;
340 /* Draw arc curving across */
341 gdk_draw_arc(pcanvas
->v
.pixmap
, gc
, FALSE
,
342 arcstart_x
, arcstart_y
,
343 arcwidth
, archeight
, 270*64, -90*64);
346 /* Draw short horizontal line */
347 gdk_draw_line(pcanvas
->v
.pixmap
, gc
,
348 end_x
- 10, start_y
+ dy
, end_x
, end_y
);
352 static PangoLayout
*layout
;
356 } fonts
[FONT_COUNT
] = {
357 {&city_names_style
, TRUE
},
358 {&city_productions_style
, TRUE
},
359 {&reqtree_text_style
, FALSE
}
361 #define FONT(font) ((*fonts[font].styles)->font_desc)
363 /****************************************************************************
364 Return the size of the given text in the given font. This size should
365 include the ascent and descent of the text. Either of width or height
366 may be NULL in which case those values simply shouldn't be filled out.
367 ****************************************************************************/
368 void get_text_size(int *width
, int *height
,
369 enum client_font font
, const char *text
)
374 layout
= pango_layout_new(gdk_pango_context_get());
377 pango_layout_set_font_description(layout
, FONT(font
));
378 pango_layout_set_text(layout
, text
, -1);
380 pango_layout_get_pixel_extents(layout
, &rect
, NULL
);
385 *height
= rect
.height
;
389 /****************************************************************************
390 Draw the text onto the canvas in the given color and font. The canvas
391 position does not account for the ascent of the text; this function must
392 take care of this manually. The text will not be NULL but may be empty.
393 ****************************************************************************/
394 void canvas_put_text(struct canvas
*pcanvas
, int canvas_x
, int canvas_y
,
395 enum client_font font
,
396 struct color
*pcolor
,
401 if (pcanvas
->type
!= CANVAS_PIXMAP
) {
405 layout
= pango_layout_new(gdk_pango_context_get());
408 gdk_gc_set_foreground(civ_gc
, &pcolor
->color
);
409 pango_layout_set_font_description(layout
, FONT(font
));
410 pango_layout_set_text(layout
, text
, -1);
412 pango_layout_get_pixel_extents(layout
, &rect
, NULL
);
414 /* Suppress drop shadow for black text */
415 if (fonts
[font
].shadowed
416 && !gdk_color_equal(&pcolor
->color
, &toplevel
->style
->black
)) {
417 gtk_draw_shadowed_string(pcanvas
->v
.pixmap
,
418 toplevel
->style
->black_gc
, civ_gc
,
420 canvas_y
+ PANGO_ASCENT(rect
), layout
);
422 gdk_draw_layout(pcanvas
->v
.pixmap
, civ_gc
,
423 canvas_x
, canvas_y
+ PANGO_ASCENT(rect
),