Complete.Org: Mailing Lists: Archives: freeciv-dev: January 2003:
[Freeciv-Dev] (PR#2708) backing rectangle for city descriptions in gtk2
Home

[Freeciv-Dev] (PR#2708) backing rectangle for city descriptions in gtk2

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: undisclosed-recipients:;
Subject: [Freeciv-Dev] (PR#2708) backing rectangle for city descriptions in gtk2 client
From: "Jason Short via RT" <rt@xxxxxxxxxxxxxx>
Date: Thu, 2 Jan 2003 19:35:38 -0800
Reply-to: rt@xxxxxxxxxxxxxx

This patch draws a partially-transparent backing rectangle behind the
city description text for gui-gtk-2.0.  Screenshots are at
http://freeciv.org/~jdorje/citydesc/.

The pixbuf manipulation to do this is a bit expensive.  It increases the
execution time of show_city_desc() by about 75% on my system.  This is
well worth it IMO.

The color and level of transparency are easily adjustable in the code,
but could be made theme values or local options.  It would also be easy
to add a local option to toggle the behavior on and off.

The bulk of the code changes are because show_city_desc had to be
restructured.  It has to first calculate the dimensions of the text,
then draw the background rectangle, then draw the text.  I also fixed a
bug related to PR#2445.

A side change, suggested on IRC, is that the city name is changed color
along with the turns-to-grow.

jason


Index: client/gui-gtk-2.0/mapview.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk-2.0/mapview.c,v
retrieving revision 1.34
diff -u -r1.34 mapview.c
--- client/gui-gtk-2.0/mapview.c        2003/01/01 11:51:33     1.34
+++ client/gui-gtk-2.0/mapview.c        2003/01/03 03:02:00
@@ -1109,87 +1109,191 @@
   update_map_canvas_visible();
 }
 
+#include <string.h>
 /**************************************************************************
 ...
 **************************************************************************/
 void show_city_desc(struct city *pcity, int canvas_x, int canvas_y)
 {
-  static char buffer[512], buffer2[32];
-  PangoRectangle rect, rect2;
+  static char name_buf[512], growth_buf[32], prod_buf[512];
+  PangoRectangle name_rect, growth_rect, prod_rect;
+  int name_x = 0, name_y = 0, growth_x = 0, growth_y = 0;
+  int prod_x = 0, prod_y = 0, bg_w = 0, bg_h = 0;
   enum color_std color;
   int extra_width = 0;
   PangoLayout *layout;
+  bool draw = FALSE;
 
   /* FIXME: layout should be statically declared */
   layout = pango_layout_new(gdk_pango_context_get());
 
+  /* Draw below the city, centered. */
   canvas_x += NORMAL_TILE_WIDTH / 2;
   canvas_y += NORMAL_TILE_HEIGHT;
 
+  /* First position the text. */
   if (draw_city_names) {
-    get_city_mapview_name_and_growth(pcity, buffer, sizeof(buffer),
-                                    buffer2, sizeof(buffer2), &color);
+    int name_h, growth_h;
 
+    draw = TRUE;
+    get_city_mapview_name_and_growth(pcity, name_buf, sizeof(name_buf),
+                                    growth_buf, sizeof(growth_buf), &color);
+
     pango_layout_set_font_description(layout, main_font);
-    if (buffer2[0] != '\0') {
+    if (growth_buf[0] != '\0') {
       /* HACK: put a character's worth of space between the two strings. */
+      PangoRectangle rect;
       pango_layout_set_text(layout, "M", -1);
       pango_layout_get_pixel_extents(layout, &rect, NULL);
       extra_width = rect.width;
     }
-    pango_layout_set_text(layout, buffer, -1);
-    pango_layout_get_pixel_extents(layout, &rect, NULL);
-    rect.width += extra_width;
+    pango_layout_set_text(layout, name_buf, -1);
+    pango_layout_get_pixel_extents(layout, &name_rect, NULL);
+    name_rect.width += extra_width;
+    name_h = name_rect.height;
 
     if (draw_city_growth && pcity->owner == game.player_idx) {
       /* We need to know the size of the growth text before
         drawing anything. */
       pango_layout_set_font_description(layout, city_productions_font);
-      pango_layout_set_text(layout, buffer2, -1);
-      pango_layout_get_pixel_extents(layout, &rect2, NULL);
-
-      /* Now return the layout to its previous state. */
-      pango_layout_set_font_description(layout, main_font);
-      pango_layout_set_text(layout, buffer, -1);
+      pango_layout_set_text(layout, growth_buf, -1);
+      pango_layout_get_pixel_extents(layout, &growth_rect, NULL);
+      growth_h = growth_rect.height - PANGO_ASCENT(growth_rect)
+       + PANGO_ASCENT(name_rect);
     } else {
-      rect2.width = 0;
+      growth_rect.width = 0;
+      growth_rect.height = 0;
+      growth_h = 0;
+    }
+
+    name_x = canvas_x - (name_rect.width + growth_rect.width) / 2;
+    name_y = canvas_y + PANGO_ASCENT(name_rect);
+
+    growth_x = canvas_x - (name_rect.width + growth_rect.width) / 2
+      + name_rect.width;
+    growth_y = canvas_y + PANGO_ASCENT(name_rect);
+
+    /* With some names the growth text may be taller than the name text. */
+    bg_h = MAX(name_h, growth_h);
+    bg_w = name_rect.width + growth_rect.width;
+  }
+
+  if (draw_city_productions && (pcity->owner==game.player_idx)) {
+    if (draw_city_names) {
+      /* Add a 3-pixel separation. */
+      bg_h += 3;
     }
 
+    draw = TRUE;
+    get_city_mapview_production(pcity, prod_buf, sizeof(prod_buf));
+
+    pango_layout_set_font_description(layout, city_productions_font);
+    pango_layout_set_text(layout, prod_buf, -1);
+
+    pango_layout_get_pixel_extents(layout, &prod_rect, NULL);
+
+    prod_x = canvas_x - prod_rect.width / 2;
+    prod_y = canvas_y + bg_h + PANGO_ASCENT(prod_rect);
+    
+    bg_h += prod_rect.height;
+    bg_w = MAX(bg_w, prod_rect.width);
+  }
+
+  if (draw) {
+    GdkPixbuf *buf;
+    int bg_x, bg_y, mapview_width, mapview_height;
+
+    /* Set X and Y positioning, after adding on a 3-pixel border. */
+    bg_w += 6;
+    bg_x = canvas_x - bg_w / 2;
+    bg_h += 6;
+    bg_y = canvas_y - 3;
+
+    /* Make sure the rect is within the screen;
+     * otherwise gdkpixbuf will fail. */
+    gdk_window_get_size(map_canvas->window,
+                       &mapview_width, &mapview_height);
+    if (bg_x < 0) {
+      bg_w += bg_x;
+      bg_x = 0;
+    }
+    if (bg_y < 0) {
+      bg_h += bg_y;
+      bg_y = 0;
+    }
+    if (bg_x + bg_w > mapview_width) {
+      bg_w = mapview_width - bg_x;
+    }
+    if (bg_y + bg_h > mapview_height) {
+      bg_h = mapview_height - bg_y;
+    }
+
+    /* Check to see if we even need to draw anything. */
+    if (bg_w <= 0 || bg_h <= 0) {
+      return;
+    }
+
+    buf = gdk_pixbuf_get_from_drawable(NULL,
+                                      map_canvas_store,
+                                      NULL,
+                                      bg_x, bg_y,
+                                      0, 0,
+                                      bg_w, bg_h);
+    if (buf) {
+      GdkPixbuf *buf2;
+      /* This value is ARGB form; one byte per element. */
+      const guint32 color = 0xFF000000;
+      /* The alpha level.  0 = opaque, 255=transparent */
+      const int alpha = 128;
+
+      buf2 = gdk_pixbuf_composite_color_simple(buf,
+                                              bg_w, bg_h,
+                                              GDK_INTERP_NEAREST,
+                                              alpha, 1024,
+                                              color, color);
+      if (buf2) {
+       gdk_pixbuf_render_to_drawable(buf2,
+                                     map_canvas->window,
+                                     civ_gc,
+                                     0, 0,
+                                     bg_x, bg_y,
+                                     bg_w, bg_h,
+                                     GDK_RGB_DITHER_NONE, 0, 0);
+       gdk_pixbuf_unref(buf2);
+      }
+      gdk_pixbuf_unref(buf);
+    }
+  }
+
+  /* Now draw the text. */
+  if (draw_city_names) {
+    /* Draw city name. */
+    pango_layout_set_font_description(layout, main_font);
+    pango_layout_set_text(layout, name_buf, -1);
+    gdk_gc_set_foreground(civ_gc, colors_standard[color]);
     gtk_draw_shadowed_string(map_canvas->window,
                             toplevel->style->black_gc,
-                            toplevel->style->white_gc,
-                            canvas_x - (rect.width + rect2.width) / 2,
-                            canvas_y + PANGO_ASCENT(rect), layout);
+                            civ_gc,
+                            name_x, name_y, layout);
 
     if (draw_city_growth && pcity->owner == game.player_idx) {
+      /* Draw city growth. */
       pango_layout_set_font_description(layout, city_productions_font);
-      pango_layout_set_text(layout, buffer2, -1);
-      gdk_gc_set_foreground(civ_gc, colors_standard[color]);
+      pango_layout_set_text(layout, growth_buf, -1);
       gtk_draw_shadowed_string(map_canvas->window,
                               toplevel->style->black_gc,
                               civ_gc,
-                              canvas_x - (rect.width + rect2.width) / 2
-                              + rect.width,
-                              canvas_y + PANGO_ASCENT(rect)
-                              + rect.height / 2 - rect2.height / 2,
-                              layout);
+                              growth_x, growth_y, layout);
     }
-
-    canvas_y += rect.height + 3;
   }
 
-  if (draw_city_productions && (pcity->owner==game.player_idx)) {
-    get_city_mapview_production(pcity, buffer, sizeof(buffer));
-
+  if (draw_city_productions && pcity->owner == game.player_idx) {
     pango_layout_set_font_description(layout, city_productions_font);
-    pango_layout_set_text(layout, buffer, -1);
-
-    pango_layout_get_pixel_extents(layout, &rect, NULL);
+    pango_layout_set_text(layout, prod_buf, -1);
     gtk_draw_shadowed_string(map_canvas->window,
                             toplevel->style->black_gc,
                             toplevel->style->white_gc,
-                            canvas_x - rect.width / 2,
-                            canvas_y + PANGO_ASCENT(rect), layout);
+                            prod_x, prod_y, layout);
   }
 
 #if 0

[Prev in Thread] Current Thread [Next in Thread]