From b18512a560fec1be9a9b27af34860ee1a9f2e139 Mon Sep 17 00:00:00 2001 From: Alina Lenk Date: Thu, 10 Feb 2022 23:04:45 +0100 Subject: [PATCH 2/2] Fix GTK+ clients not drawing citizens correctly above city size 30 Reported by ddeanbrown See osdn #43823 --- client/gui-gtk-3.22/citydlg.c | 36 +++++++++++++++++++++++++---------- client/gui-gtk-4.0/citydlg.c | 36 +++++++++++++++++++++++++---------- 2 files changed, 52 insertions(+), 20 deletions(-) diff --git a/client/gui-gtk-3.22/citydlg.c b/client/gui-gtk-3.22/citydlg.c index 7cccb3d4eb..8d16fc570f 100644 --- a/client/gui-gtk-3.22/citydlg.c +++ b/client/gui-gtk-3.22/citydlg.c @@ -1759,8 +1759,8 @@ static void city_dialog_update_title(struct city_dialog *pdialog) static void city_dialog_update_citizens(struct city_dialog *pdialog) { enum citizen_category categories[MAX_CITY_SIZE]; - int i, width; - int citizen_bar_height; + int i, width, full_width, total_used_width; + int citizen_bar_width, citizen_bar_height; struct city *pcity = pdialog->pcity; int num_citizens = get_city_citizen_types(pcity, FEELING_FINAL, categories); cairo_t *cr; @@ -1770,16 +1770,18 @@ static void city_dialog_update_citizens(struct city_dialog *pdialog) /* last icon is always drawn in full, and so has reserved */ /* tileset_small_sprite_width(tileset) pixels. */ + full_width = tileset_small_sprite_width(tileset); if (num_citizens > 1) { - width = MIN(tileset_small_sprite_width(tileset), - ((NUM_CITIZENS_SHOWN - 1) * tileset_small_sprite_width(tileset)) / - (num_citizens - 1)); + width = MIN(full_width, ((NUM_CITIZENS_SHOWN - 1) * full_width) + / (num_citizens - 1)); } else { - width = tileset_small_sprite_width(tileset); + width = full_width; } pdialog->cwidth = width; /* overview page */ + /* keep these values in sync with create_city_dialog */ + citizen_bar_width = full_width * NUM_CITIZENS_SHOWN; citizen_bar_height = tileset_small_sprite_height(tileset); cr = cairo_create(pdialog->citizen_surface); @@ -1788,12 +1790,26 @@ static void city_dialog_update_citizens(struct city_dialog *pdialog) cairo_set_source_surface(cr, get_citizen_sprite(tileset, categories[i], i, pcity)->surface, i * width, 0); - cairo_rectangle(cr, i * width, 0, width, citizen_bar_height); + cairo_rectangle(cr, i * width, 0, + /* Always draw last citizen in full */ + i + 1 < num_citizens ? width : full_width, + citizen_bar_height); + cairo_fill(cr); + } + + total_used_width = (i - 1) * width + full_width; + + if (total_used_width < citizen_bar_width) { + /* Clear the rest of the area. + * Note that this might still be necessary even in cases where + * num_citizens > NUM_CITIZENS_SHOWN, if the available width cannot be + * divided perfectly. */ + cairo_rectangle(cr, total_used_width, 0, + citizen_bar_width - total_used_width, + citizen_bar_height); + cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR); cairo_fill(cr); } - cairo_rectangle(cr, i * width, 0, width * (NUM_CITIZENS_SHOWN - i), citizen_bar_height); - cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR); - cairo_fill(cr); cairo_destroy(cr); diff --git a/client/gui-gtk-4.0/citydlg.c b/client/gui-gtk-4.0/citydlg.c index 83ad85023b..54ed523261 100644 --- a/client/gui-gtk-4.0/citydlg.c +++ b/client/gui-gtk-4.0/citydlg.c @@ -1752,8 +1752,8 @@ static void city_dialog_update_title(struct city_dialog *pdialog) static void city_dialog_update_citizens(struct city_dialog *pdialog) { enum citizen_category categories[MAX_CITY_SIZE]; - int i, width; - int citizen_bar_height; + int i, width, full_width, total_used_width; + int citizen_bar_width, citizen_bar_height; struct city *pcity = pdialog->pcity; int num_citizens = get_city_citizen_types(pcity, FEELING_FINAL, categories); cairo_t *cr; @@ -1763,16 +1763,18 @@ static void city_dialog_update_citizens(struct city_dialog *pdialog) /* last icon is always drawn in full, and so has reserved */ /* tileset_small_sprite_width(tileset) pixels. */ + full_width = tileset_small_sprite_width(tileset); if (num_citizens > 1) { - width = MIN(tileset_small_sprite_width(tileset), - ((NUM_CITIZENS_SHOWN - 1) * tileset_small_sprite_width(tileset)) / - (num_citizens - 1)); + width = MIN(full_width, ((NUM_CITIZENS_SHOWN - 1) * full_width) + / (num_citizens - 1)); } else { - width = tileset_small_sprite_width(tileset); + width = full_width; } pdialog->cwidth = width; /* overview page */ + /* keep these values in sync with create_city_dialog */ + citizen_bar_width = full_width * NUM_CITIZENS_SHOWN; citizen_bar_height = tileset_small_sprite_height(tileset); cr = cairo_create(pdialog->citizen_surface); @@ -1781,12 +1783,26 @@ static void city_dialog_update_citizens(struct city_dialog *pdialog) cairo_set_source_surface(cr, get_citizen_sprite(tileset, categories[i], i, pcity)->surface, i * width, 0); - cairo_rectangle(cr, i * width, 0, width, citizen_bar_height); + cairo_rectangle(cr, i * width, 0, + /* Always draw last citizen in full */ + i + 1 < num_citizens ? width : full_width, + citizen_bar_height); + cairo_fill(cr); + } + + total_used_width = (i - 1) * width + full_width; + + if (total_used_width < citizen_bar_width) { + /* Clear the rest of the area. + * Note that this might still be necessary even in cases where + * num_citizens > NUM_CITIZENS_SHOWN, if the available width cannot be + * divided perfectly. */ + cairo_rectangle(cr, total_used_width, 0, + citizen_bar_width - total_used_width, + citizen_bar_height); + cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR); cairo_fill(cr); } - cairo_rectangle(cr, i * width, 0, width * (NUM_CITIZENS_SHOWN - i), citizen_bar_height); - cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR); - cairo_fill(cr); cairo_destroy(cr); -- 2.17.1