Complete.Org: Mailing Lists: Archives: freeciv-dev: March 2005:
[Freeciv-Dev] (PR#12470) unify show_city_desc
Home

[Freeciv-Dev] (PR#12470) unify show_city_desc

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
Subject: [Freeciv-Dev] (PR#12470) unify show_city_desc
From: "Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx>
Date: Wed, 9 Mar 2005 15:09:51 -0800
Reply-to: bugs@xxxxxxxxxxx

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

This patch unifies show_city_desc by moving it into mapview_common.

* The complicated layout logic is now only in one place.

* Two helper functions, get_text_size and canvas_put_text are added. 
This is quite simplistic but surely just as good as what we have now.

* Behavior should be unchanged EXCEPT that I fixed a "bug" where the 
text was drawn 3 pixels above the tile it was supposed to cover (exact 
placement may be added back later but preferably not in a buggy way).

* I updated and tested gui-gtk-2.0.  I also updated gui-stub and gui-xaw 
but didn't test these.  It's up to the GUI authors to update the other 
clients.

Ultimately this makes it very much easier to make advanced "city bars" 
(like the design in 
http://www.idi.ntnu.no/~haskjold/freeciv/city_info3.png) or just to make 
any changes to the "city bar".  It makes it harder to get exact text 
placement since get_text_size doesn't include the ascent/descent (but as 
I said the current code doesn't do exact text placement anyway).

-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     9 Mar 2005 23:05:40 -0000
@@ -1307,6 +1307,77 @@
   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,
+                          int canvas_x, int canvas_y,
+                          struct city *pcity, int *width, int *height)
+{
+  static char name[512], growth[32], prod[512];
+  enum color_std growth_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 extra_width = 0, total_width, total_height;
+
+  *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, 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);
+      /* HACK: put a character's worth of space between the two strings. */
+      get_text_size(&extra_width, NULL, FONT_CITY_NAME, "M");
+    }
+    total_width = name_rect.w + extra_width + growth_rect.w;
+    total_height = MAX(name_rect.h, growth_rect.h);
+    canvas_put_text(pcanvas,
+                   canvas_x - total_width / 2, canvas_y,
+                   FONT_CITY_NAME, COLOR_STD_WHITE, name);
+    if (growth[0] != '\0') {
+      canvas_put_text(pcanvas,
+                     canvas_x - total_width / 2 + name_rect.w + extra_width,
+                     canvas_y + total_height - growth_rect.h,
+                     FONT_CITY_PROD, growth_color, growth);
+    }
+    canvas_y += total_height + 3;
+
+    *width = MAX(*width, total_width);
+    *height += total_height + 3;
+  }
+  if (draw_city_productions && pcity->owner == game.player_idx) {
+    get_city_mapview_production(pcity, prod, sizeof(prod));
+    get_text_size(&prod_rect.w, &prod_rect.h, FONT_CITY_PROD, prod);
+
+    total_width = prod_rect.w;
+    total_height = prod_rect.h;
+
+    canvas_put_text(pcanvas, canvas_x - total_width / 2, canvas_y,
+                   FONT_CITY_PROD, COLOR_STD_WHITE, prod);
+
+    canvas_y += total_height;
+    *width = MAX(*width, total_width);
+    *height += total_height;
+  }
+}
+
 /**************************************************************************
   Show descriptions for all cities visible on the map canvas.
 **************************************************************************/
@@ -1319,8 +1390,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
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     9 Mar 2005 23:05:40 -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        9 Mar 2005 23:05:40 -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   9 Mar 2005 23:05:40 -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    9 Mar 2005 23:05:40 -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  9 Mar 2005 23:05:40 -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]
  • [Freeciv-Dev] (PR#12470) unify show_city_desc, Jason Short <=