Complete.Org: Mailing Lists: Archives: freeciv-dev: March 2005:
[Freeciv-Dev] Re: (PR#2708) patch: backing rectangle for city descriptio
Home

[Freeciv-Dev] Re: (PR#2708) patch: backing rectangle for city descriptio

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
Subject: [Freeciv-Dev] Re: (PR#2708) patch: backing rectangle for city descriptions in gtk2 client
From: "Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx>
Date: Wed, 9 Mar 2005 18:09:19 -0800
Reply-to: bugs@xxxxxxxxxxx

<URL: http://bugs.freeciv.org/Ticket/Display.html?id=2708 >

Here is an updated an much-improved patch.  See

   http://bugs.freeciv.org/Ticket/Attachment/92195/58696/citybar.png

it includes PR#12470.  There are only two real issues:

1.  It uses sprites.mask.worked to get a 50%-alpha black background. 
This is a hack, of course.  Instead we should add a new sprite for it.

2.  In single-player games the human is always player 0 which has a dark 
maroon color.  This doesn't show up very well against the transparent 
black background.  Bright colors show up better.

-jason


Index: client/mapview_common.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/mapview_common.c,v
retrieving revision 1.208
diff -u -r1.208 mapview_common.c
--- client/mapview_common.c     9 Mar 2005 18:12:33 -0000       1.208
+++ client/mapview_common.c     10 Mar 2005 02:03:31 -0000
@@ -1307,6 +1307,136 @@
   queue_mapview_tile_update(pcity->tile, TILE_UPDATE_CITY_DESC);
 }
 
+/****************************************************************************
+  Draw a description for the given city.  This description may include the
+  name, turns-to-grow, production, and city turns-to-build (depending on
+  client options).
+
+  (canvas_x, canvas_y) gives the location on the given canvas at which to
+  draw the description.  This is the location of the city itself so the
+  text must be drawn underneath it.  pcity gives the city to be drawn,
+  while (*width, *height) should be set by show_ctiy_desc to contain the
+  width and height of the text block (centered directly underneath the
+  city's tile).
+****************************************************************************/
+static void show_city_desc(struct canvas *pcanvas,
+                          const int canvas_xx, const int canvas_yy,
+                          struct city *pcity, int *width, int *height)
+{
+  const bool draw_city_prod = (draw_city_productions
+                              && pcity->owner == game.player_idx);
+  const bool multi = (draw_city_prod && draw_city_names);
+  static char name[512], growth[32], prod[512];
+  enum color_std growth_color, owner_color;
+  struct {
+    int x, y, w, h;
+  } name_rect = {0, 0, 0, 0}, growth_rect = {0, 0, 0, 0},
+                               prod_rect = {0, 0, 0, 0};
+  int width1 = 0, width2 = 0, height1 = 0, height2 = 0;
+  struct Sprite *sprite = sprites.mask.worked_tile; /* FIXME */
+  int sprite_w, sprite_h, x, y;
+  const int canvas_x = canvas_xx + NORMAL_TILE_WIDTH / 2;
+  const int canvas_y = canvas_yy + NORMAL_TILE_HEIGHT;
+  const int border = 6;
+
+  get_sprite_dimensions(sprite, &sprite_w, &sprite_h);
+  *width = *height = 0;
+
+  if (!draw_city_names && !draw_city_prod) {
+    return;
+  }
+
+  /* First: calculate rect dimensions (but not positioning). */
+  if (draw_city_names) {
+    int extra_width = 0;
+
+    get_city_mapview_name_and_growth(pcity, name, sizeof(name),
+                                    growth, sizeof(growth), &growth_color);
+
+    get_text_size(&name_rect.w, &name_rect.h, FONT_CITY_NAME, name);
+
+    if (growth[0] != '\0') {
+      get_text_size(&growth_rect.w, &growth_rect.h, FONT_CITY_PROD, growth);
+      extra_width = border;
+    }
+    width1 = name_rect.w + extra_width + growth_rect.w;
+    height1 = MAX(name_rect.h, growth_rect.h);
+  }
+  if (draw_city_prod) {
+    get_city_mapview_production(pcity, prod, sizeof(prod));
+    get_text_size(&prod_rect.w, &prod_rect.h, FONT_CITY_PROD, prod);
+
+    width2 = prod_rect.w;
+    height2 = prod_rect.h;
+  }
+
+  *width = MAX(width1, width2) + border;
+  *height = border + height1 + height2 + (multi ? border : 0);
+
+  /* Next fill in X and Y locations. */
+  if (draw_city_names) {
+    int growth_w = 0;
+
+    if (growth[0] != '\0') {
+      growth_rect.x
+       = canvas_x + (MAX(width1, width2) + 1) / 2 - growth_rect.w;
+      growth_rect.y = canvas_y + border / 2 + (height1 - growth_rect.h) / 2;
+      growth_w = growth_rect.w + border;
+    }
+
+    name_rect.x = canvas_x - (name_rect.w + growth_w) / 2;
+    name_rect.y = canvas_y + border / 2;
+  }
+  if (draw_city_prod) {
+    prod_rect.x = canvas_x - width2 / 2;
+    prod_rect.y = canvas_y + border / 2
+      + (draw_city_names ? border + height1 : 0);
+  }
+
+  /* Now draw. */
+  for (x = 0; x < *width; x += sprite_w) {
+    for (y = 0; y < *height; y += sprite_h) {
+      canvas_put_sprite(pcanvas, canvas_x - *width / 2 + x,
+                       canvas_y + y,
+                       sprite,
+                       0, 0, *width - x, *height - y);
+    }
+  }
+  owner_color = player_color(city_owner(pcity));
+  canvas_put_line(pcanvas, owner_color, LINE_NORMAL,
+                 canvas_x - *width / 2, canvas_y,
+                 *width, 0);
+  canvas_put_line(pcanvas, owner_color, LINE_NORMAL,
+                 canvas_x - *width / 2, canvas_y,
+                 0, *height);
+  canvas_put_line(pcanvas, owner_color, LINE_NORMAL,
+                 canvas_x - *width / 2, canvas_y + *height,
+                 *width, 0);
+  canvas_put_line(pcanvas, owner_color, LINE_NORMAL,
+                 canvas_x - *width / 2 + *width, canvas_y,
+                 0, *height);
+  if (draw_city_names) {
+    canvas_put_text(pcanvas, name_rect.x, name_rect.y,
+                   FONT_CITY_NAME, COLOR_STD_WHITE, name);
+    if (growth[0] != '\0') {
+      canvas_put_line(pcanvas, owner_color, LINE_NORMAL,
+                     growth_rect.x - border / 2, canvas_y,
+                     0, height1 + border);
+      canvas_put_text(pcanvas, growth_rect.x, growth_rect.y,
+                     FONT_CITY_PROD, growth_color, growth);
+    }
+  }
+  if (draw_city_prod) {
+    if (draw_city_names) {
+      canvas_put_line(pcanvas, owner_color, LINE_NORMAL,
+                     canvas_x - *width / 2, canvas_y + height1 + border,
+                     *width, 0);
+    }
+    canvas_put_text(pcanvas, prod_rect.x, prod_rect.y,
+                   FONT_CITY_PROD, COLOR_STD_WHITE, prod);
+  }
+}
+
 /**************************************************************************
   Show descriptions for all cities visible on the map canvas.
 **************************************************************************/
@@ -1319,8 +1449,6 @@
     return;
   }
 
-  prepare_show_city_descriptions();
-
   /* A city description is shown below the city.  It has a specified
    * maximum width and height (although these are only estimates).  Thus
    * we need to update some tiles above the mapview and some to the left
@@ -1341,7 +1469,7 @@
    */
   gui_rect_iterate(mapview.gui_x0 + canvas_x - dx / 2,
                   mapview.gui_y0 + canvas_y - dy,
-                  width + dx, height + dy - NORMAL_TILE_HEIGHT,
+                  width + dx, height + dy,
                   ptile, pedge, pcorner, gui_x, gui_y) {
     const int canvas_x = gui_x - mapview.gui_x0;
     const int canvas_y = gui_y - mapview.gui_y0;
Index: client/mapview_common.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/mapview_common.h,v
retrieving revision 1.103
diff -u -r1.103 mapview_common.h
--- client/mapview_common.h     5 Mar 2005 02:23:29 -0000       1.103
+++ client/mapview_common.h     10 Mar 2005 02:03:34 -0000
@@ -55,6 +55,12 @@
 extern struct view mapview;
 extern struct overview overview;
 
+enum client_font {
+  FONT_CITY_NAME,
+  FONT_CITY_PROD,
+  FONT_COUNT
+};
+
 /* HACK: Callers can set this to FALSE to disable sliding.  It should be
  * reenabled afterwards. */
 extern bool can_slide;
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.163
diff -u -r1.163 mapview.c
--- client/gui-gtk-2.0/mapview.c        5 Mar 2005 23:43:59 -0000       1.163
+++ client/gui-gtk-2.0/mapview.c        10 Mar 2005 02:03:34 -0000
@@ -461,117 +461,63 @@
   update_map_canvas_visible();
 }
 
-/**************************************************************************
-  If necessary, clear the city descriptions out of the buffer.
-**************************************************************************/
-void prepare_show_city_descriptions(void)
-{
-  /* Nothing to do */
-}
+static PangoLayout *layout;
+static PangoFontDescription **fonts[FONT_COUNT] = {&main_font,
+                                                  &city_productions_font};
 
 /****************************************************************************
-  Draw a description for the given city.  This description may include the
-  name, turns-to-grow, production, and city turns-to-build (depending on
-  client options).
-
-  (canvas_x, canvas_y) gives the location on the given canvas at which to
-  draw the description.  This is the location of the city itself so the
-  text must be drawn underneath it.  pcity gives the city to be drawn,
-  while (*width, *height) should be set by show_ctiy_desc to contain the
-  width and height of the text block (centered directly underneath the
-  city's tile).
+  Return the size of the given text in the given font.  This size should
+  include the ascent and descent of the text.  Either of width or height
+  may be NULL in which case those values simply shouldn't be filled out.
 ****************************************************************************/
-void show_city_desc(struct canvas *pcanvas, int canvas_x, int canvas_y,
-                   struct city *pcity, int *width, int *height)
+void get_text_size(int *width, int *height,
+                  enum client_font font, const char *text)
 {
-  if (pcanvas->type == CANVAS_PIXMAP) {
-  static char buffer[512], buffer2[32];
-  PangoRectangle rect, rect2;
-  enum color_std color;
-  int extra_width = 0;
-  static PangoLayout *layout;
+  PangoRectangle rect;
 
   if (!layout) {
     layout = pango_layout_new(gdk_pango_context_get());
   }
 
-  *width = *height = 0;
-
-  canvas_x += NORMAL_TILE_WIDTH / 2;
-  canvas_y += NORMAL_TILE_HEIGHT;
-
-  if (draw_city_names) {
-    get_city_mapview_name_and_growth(pcity, buffer, sizeof(buffer),
-                                    buffer2, sizeof(buffer2), &color);
-
-    pango_layout_set_font_description(layout, main_font);
-    if (buffer2[0] != '\0') {
-      /* HACK: put a character's worth of space between the two strings. */
-      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;
-
-    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);
-    } else {
-      rect2.width = 0;
-    }
-
-    gtk_draw_shadowed_string(pcanvas->v.pixmap,
-                            toplevel->style->black_gc,
-                            toplevel->style->white_gc,
-                            canvas_x - (rect.width + rect2.width) / 2,
-                            canvas_y + PANGO_ASCENT(rect), layout);
-
-    if (draw_city_growth && pcity->owner == game.player_idx) {
-      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]);
-      gtk_draw_shadowed_string(pcanvas->v.pixmap,
-                              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);
-    }
-
-    canvas_y += rect.height + 3;
+  pango_layout_set_font_description(layout, *fonts[font]);
+  pango_layout_set_text(layout, text, -1);
 
-    *width = rect.width + rect2.width;
-    *height += rect.height + 3;
+  pango_layout_get_pixel_extents(layout, &rect, NULL);
+  if (width) {
+    *width = rect.width;
   }
+  if (height) {
+    *height = rect.height;
+  }
+}
 
-  if (draw_city_productions && (pcity->owner==game.player_idx)) {
-    get_city_mapview_production(pcity, buffer, sizeof(buffer));
-
-    pango_layout_set_font_description(layout, city_productions_font);
-    pango_layout_set_text(layout, buffer, -1);
-
-    pango_layout_get_pixel_extents(layout, &rect, NULL);
-    gtk_draw_shadowed_string(pcanvas->v.pixmap,
-                            toplevel->style->black_gc,
-                            toplevel->style->white_gc,
-                            canvas_x - rect.width / 2,
-                            canvas_y + PANGO_ASCENT(rect), layout);
+/****************************************************************************
+  Draw the text onto the canvas in the given color and font.  The canvas
+  position does not account for the ascent of the text; this function must
+  take care of this manually.  The text will not be NULL but may be empty.
+****************************************************************************/
+void canvas_put_text(struct canvas *pcanvas, int canvas_x, int canvas_y,
+                    enum client_font font, enum color_std color,
+                    const char *text)
+{
+  PangoRectangle rect;
 
-    *width = MAX(*width, rect.width);
-    *height += rect.height;
+  if (pcanvas->type != CANVAS_PIXMAP) {
+    return;
   }
+  if (!layout) {
+    layout = pango_layout_new(gdk_pango_context_get());
   }
+
+  gdk_gc_set_foreground(civ_gc, colors_standard[color]);
+  pango_layout_set_font_description(layout, *fonts[font]);
+  pango_layout_set_text(layout, text, -1);
+
+  pango_layout_get_pixel_extents(layout, &rect, NULL);
+  gtk_draw_shadowed_string(pcanvas->v.pixmap,
+                          toplevel->style->black_gc, civ_gc,
+                          canvas_x,
+                          canvas_y + PANGO_ASCENT(rect), layout);
 }
 
 /**************************************************************************
Index: client/gui-stub/mapview.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-stub/mapview.c,v
retrieving revision 1.50
diff -u -r1.50 mapview.c
--- client/gui-stub/mapview.c   2 Mar 2005 18:22:59 -0000       1.50
+++ client/gui-stub/mapview.c   10 Mar 2005 02:03:34 -0000
@@ -122,19 +122,30 @@
 }
 
 /****************************************************************************
-  Draw a description for the given city.  This description may include the
-  name, turns-to-grow, production, and city turns-to-build (depending on
-  client options).
-
-  (canvas_x, canvas_y) gives the location on the given canvas at which to
-  draw the description.  This is the location of the city itself so the
-  text must be drawn underneath it.  pcity gives the city to be drawn,
-  while (*width, *height) should be set by show_ctiy_desc to contain the
-  width and height of the text block (centered directly underneath the
-  city's tile).
+  Return the size of the given text in the given font.  This size should
+  include the ascent and descent of the text.  Either of width or height
+  may be NULL in which case those values simply shouldn't be filled out.
 ****************************************************************************/
-void show_city_desc(struct canvas *pcanvas, int canvas_x, int canvas_y,
-                   struct city *pcity, int *width, int *height)
+void get_text_size(int *width, int *height,
+                  enum client_font font, const char *text)
+{
+  /* PORTME */
+  if (width) {
+    *width = 0;
+  }
+  if (height) {
+    *height = 0;
+  }
+}
+
+/****************************************************************************
+  Draw the text onto the canvas in the given color and font.  The canvas
+  position does not account for the ascent of the text; this function must
+  take care of this manually.  The text will not be NULL but may be empty.
+****************************************************************************/
+void canvas_put_text(struct canvas *pcanvas, int canvas_x, int canvas_y,
+                    enum client_font font, enum color_std color,
+                    const char *text)
 {
   /* PORTME */
 }
@@ -322,14 +333,6 @@
 }
 
 /****************************************************************************
-  If necessary, clear the city descriptions out of the buffer.
-****************************************************************************/
-void prepare_show_city_descriptions(void)
-{
-  /* PORTME */
-}
-
-/****************************************************************************
   Draw a cross-hair overlay on a tile.
 ****************************************************************************/
 void put_cross_overlay_tile(struct tile *ptile)
Index: client/gui-xaw/mapview.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-xaw/mapview.c,v
retrieving revision 1.193
diff -u -r1.193 mapview.c
--- client/gui-xaw/mapview.c    5 Mar 2005 23:43:59 -0000       1.193
+++ client/gui-xaw/mapview.c    10 Mar 2005 02:03:35 -0000
@@ -641,14 +641,6 @@
 }
 
 /**************************************************************************
-  If necessary, clear the city descriptions out of the buffer.
-**************************************************************************/
-void prepare_show_city_descriptions(void)
-{
-  /* Nothing to do */
-}
-
-/**************************************************************************
 Draw at x = left of string, y = top of string.
 **************************************************************************/
 static void draw_shadowed_string(struct canvas *pcanvas,
@@ -670,69 +662,38 @@
       x, y, string, len);
 }
 
+static XFontSet *fonts[FONT_COUNT] = {&main_font_set, &prod_font_set};
+static GC *font_gcs[FONT_COUNT] = {&font_gc, &prod_font_gc};
+
 /****************************************************************************
-  Draw a description for the given city.  This description may include the
-  name, turns-to-grow, production, and city turns-to-build (depending on
-  client options).
-
-  (canvas_x, canvas_y) gives the location on the given canvas at which to
-  draw the description.  This is the location of the city itself so the
-  text must be drawn underneath it.  pcity gives the city to be drawn,
-  while (*width, *height) should be set by show_ctiy_desc to contain the
-  width and height of the text block (centered directly underneath the
-  city's tile).
+  Return the size of the given text in the given font.  This size should
+  include the ascent and descent of the text.  Either of width or height
+  may be NULL in which case those values simply shouldn't be filled out.
 ****************************************************************************/
-void show_city_desc(struct canvas *pcanvas, int canvas_x, int canvas_y,
-                   struct city *pcity, int *width, int *height)
+void get_text_size(int *width, int *height,
+                  enum client_font font, const char *text)
 {
-  char buffer[512], buffer2[512];
-  enum color_std color;
-  int w, w2;
-  XFontSetExtents *main_exts = XExtentsOfFontSet(main_font_set);
-  XFontSetExtents *prod_exts = XExtentsOfFontSet(prod_font_set);
-
-  canvas_x += NORMAL_TILE_WIDTH / 2;
-  canvas_y += NORMAL_TILE_HEIGHT;
-
-  get_city_mapview_name_and_growth(pcity, buffer, sizeof(buffer),
-                                  buffer2, sizeof(buffer2), &color);
-
-  w = XmbTextEscapement(main_font_set, buffer, strlen(buffer));
-  if (buffer2[0] != '\0') {
-    /* HACK: put a character's worth of space between the two strings. */
-    w += XmbTextEscapement(main_font_set, "M", 1);
-  }
-  w2 = XmbTextEscapement(main_font_set, buffer2, strlen(buffer2));
-
-  draw_shadowed_string(pcanvas, main_font_set, font_gc,
-                      COLOR_STD_WHITE, COLOR_STD_BLACK,
-                      canvas_x - (w + w2) / 2,
-                      canvas_y, buffer);
-
-  draw_shadowed_string(pcanvas, prod_font_set, prod_font_gc, color,
-                      COLOR_STD_BLACK,
-                      canvas_x - (w + w2) / 2 + w,
-                      canvas_y, buffer2);
-
-  *width = w + w2;
-  *height = main_exts->max_logical_extent.height;
-
-  if (draw_city_productions && (pcity->owner == game.player_idx)) {
-    if (draw_city_names) {
-      canvas_y += main_exts->max_logical_extent.height;
-    }
-
-    get_city_mapview_production(pcity, buffer, sizeof(buffer));
-    w = XmbTextEscapement(prod_font_set, buffer, strlen(buffer));
-
-    draw_shadowed_string(pcanvas, prod_font_set, prod_font_gc,
-                        COLOR_STD_WHITE, COLOR_STD_BLACK,
-                        canvas_x - w / 2,
-                        canvas_y, buffer);
-
-    *width = MAX(*width, w);
-    *height += prod_exts->max_logical_extent.height;
+  if (width) {
+    *width = XmbTextEscapement(*fonts[font], text, strlen(text));
   }
+  if (height) {
+    /* ??? */
+    *height = main_exts->max_logical_extent.height;
+  }
+}
+
+/****************************************************************************
+  Draw the text onto the canvas in the given color and font.  The canvas
+  position does not account for the ascent of the text; this function must
+  take care of this manually.  The text will not be NULL but may be empty.
+****************************************************************************/
+void canvas_put_text(struct canvas *pcanvas, int canvas_x, int canvas_y,
+                    enum client_font font, enum color_std color,
+                    const char *text)
+{
+  draw_shadowed_string(pcanvas, fonts[font], font_gcs[font],
+                      color, COLOR_STD_BLACK,
+                      canvas_x, canvas_y, text);
 }
 
 /**************************************************************************
Index: client/include/mapview_g.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/include/mapview_g.h,v
retrieving revision 1.60
diff -u -r1.60 mapview_g.h
--- client/include/mapview_g.h  2 Mar 2005 18:23:00 -0000       1.60
+++ client/include/mapview_g.h  10 Mar 2005 02:03:35 -0000
@@ -34,10 +34,12 @@
 void canvas_free(struct canvas *store);
 struct canvas *get_overview_window(void);
 
-void show_city_desc(struct canvas *pcanvas, int canvas_x, int canvas_y,
-                   struct city *pcity, int *width, int *height);
-void prepare_show_city_descriptions(void);
+void get_text_size(int *width, int *height,
+                  enum client_font font, const char *text);
 
+void canvas_put_text(struct canvas *pcanvas, int canvas_x, int canvas_y,
+                    enum client_font font, enum color_std color,
+                    const char *text);
 void canvas_put_sprite(struct canvas *pcanvas,
                       int canvas_x, int canvas_y, struct Sprite *sprite,
                       int offset_x, int offset_y, int width, int height);

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