1 // Copyright (C) 2003, 2004, 2005, 2006, 2007 Ulf Lorenz
2 // Copyright (C) 2004, 2005, 2006 Andrea Paternesi
3 // Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2014, 2015, 2016,
4 // 2020 Ben Asselstine
5 //
6 //  This program is free software; you can redistribute it and/or modify
7 //  it under the terms of the GNU General Public License as published by
8 //  the Free Software Foundation; either version 3 of the License, or
9 //  (at your option) any later version.
10 //
11 //  This program is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 //  GNU Library General Public License for more details.
15 //
16 //  You should have received a copy of the GNU General Public License
17 //  along with this program; if not, write to the Free Software
18 //  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 //  02110-1301, USA.
20 #include <sigc++/functors/mem_fun.h>
21 #include <iostream>
22 #include "ImageCache.h"
23 #include "gui/image-helpers.h"
24 #include "playerlist.h"
25 #include "stack.h"
26 #include "player.h"
27 #include "tilesetlist.h"
28 #include "GameMap.h"
29 #include "armysetlist.h"
30 #include "shield.h"
31 #include "citysetlist.h"
32 #include "shieldsetlist.h"
33 #include "Configuration.h"
34 #include "city.h"
35 #include "Tile.h"
36 #include "ruin.h"
37 #include "temple.h"
38 #include "road.h"
39 #include "bridge.h"
40 #include "FogMap.h"
41 #include "shieldset.h"
42 #include "ScenarioMedia.h"
43 
44 ImageCache* ImageCache::s_instance = 0;
45 
getInstance()46 ImageCache* ImageCache::getInstance()
47 {
48   if (!s_instance)
49     s_instance = new ImageCache();
50 
51   return s_instance;
52 }
53 
deleteInstance()54 void ImageCache::deleteInstance()
55 {
56   if (!s_instance)
57     return;
58 
59   delete s_instance;
60   s_instance = NULL;
61 }
62 
ImageCache()63 ImageCache::ImageCache()
64  : d_cachesize(0),
65     selectorcache((sigc::ptr_fun(&SelectorPixMaskCacheItem::generate))),
66     armycache((sigc::ptr_fun(&ArmyPixMaskCacheItem::generate))),
67     flagcache((sigc::ptr_fun(&FlagPixMaskCacheItem::generate))),
68     circledarmycache((sigc::ptr_fun(&CircledArmyPixMaskCacheItem::generate))),
69     tilecache((sigc::ptr_fun(&TilePixMaskCacheItem::generate))),
70     citycache((sigc::ptr_fun(&CityPixMaskCacheItem::generate))),
71     towercache((sigc::ptr_fun(&TowerPixMaskCacheItem::generate))),
72     templecache((sigc::ptr_fun(&TemplePixMaskCacheItem::generate))),
73     ruincache((sigc::ptr_fun(&RuinPixMaskCacheItem::generate))),
74     diplomacycache((sigc::ptr_fun(&DiplomacyPixMaskCacheItem::generate))),
75     roadcache((sigc::ptr_fun(&RoadPixMaskCacheItem::generate))),
76     fogcache((sigc::ptr_fun(&FogPixMaskCacheItem::generate))),
77     bridgecache((sigc::ptr_fun(&BridgePixMaskCacheItem::generate))),
78     cursorcache((sigc::ptr_fun(&CursorPixMaskCacheItem::generate))),
79     shieldcache((sigc::ptr_fun(&ShieldPixMaskCacheItem::generate))),
80     prodshieldcache((sigc::ptr_fun(&ProdShieldPixMaskCacheItem::generate))),
81     movebonuscache((sigc::ptr_fun(&MoveBonusPixMaskCacheItem::generate))),
82     shipcache((sigc::ptr_fun(&ShipPixMaskCacheItem::generate))),
83     plantedstandardcache((sigc::ptr_fun(&PlantedStandardPixMaskCacheItem::generate))),
84     portcache((sigc::ptr_fun(&PortPixMaskCacheItem::generate))),
85     signpostcache((sigc::ptr_fun(&SignpostPixMaskCacheItem::generate))),
86     bagcache((sigc::ptr_fun(&BagPixMaskCacheItem::generate))),
87     explosioncache((sigc::ptr_fun(&ExplosionPixMaskCacheItem::generate))),
88     newlevelcache((sigc::ptr_fun(&NewLevelPixMaskCacheItem::generate))),
89     defaulttilestylecache((sigc::ptr_fun(&DefaultTileStylePixMaskCacheItem::generate))),
90     tartancache((sigc::ptr_fun(&TartanPixMaskCacheItem::generate))),
91     emptytartancache((sigc::ptr_fun(&EmptyTartanPixMaskCacheItem::generate))),
92     statuscache((sigc::ptr_fun(&StatusPixMaskCacheItem::generate))),
93     gamebuttoncache((sigc::ptr_fun(&GameButtonPixMaskCacheItem::generate))),
94     dialogcache((sigc::ptr_fun(&DialogPixMaskCacheItem::generate))),
95     medalcache((sigc::ptr_fun(&MedalPixMaskCacheItem::generate)))
96 {
97     loadDiplomacyImages();
98     loadCursorImages();
99     loadProdShieldImages();
100     loadMoveBonusImages();
101     loadMedalImages(ScenarioMedia::getDefaultSmallMedalsImageFilename(),
102                     ScenarioMedia::getDefaultBigMedalsImageFilename());
103     d_smallruinedcity = loadMiscImage("smallruinedcity.png");
104     d_smallhero = loadMiscImage("hero.png");
105     d_smallbag = loadMiscImage("bag.png");
106     d_smallinactivehero = loadMiscImage("hero-inactive.png");
107     d_small_ruin_unexplored = loadMiscImage("smallunexploredruin.png");
108     d_small_stronghold_unexplored =
109       loadMiscImage("smallunexploredstronghold.png");
110     d_small_ruin_explored = loadMiscImage("smallexploredruin.png");
111     d_small_temple = loadMiscImage("smalltemple.png");
112     loadNewLevelImages();
113     loadDefaultTileStyleImages();
114     loadWaypointImages(); //only for game.  not for editors.
115     loadGameButtonImages(); //only for game.  not for editors.
116     d_nextturn = NULL;
117     d_citydefeated = NULL;
118     d_winning = NULL;
119     d_malehero = NULL;
120     d_femalehero = NULL;
121     d_ruinsuccess = NULL;
122     d_ruindefeat = NULL;
123     d_parleyoffered = NULL;
124     d_parleyrefused = NULL;
125     d_commentator = NULL;
126 }
127 
loadDiplomacyImages()128 bool ImageCache::loadDiplomacyImages()
129 {
130   bool broken = false;
131   int ts = 30;
132   std::vector<PixMask*> diplomacy;
133   diplomacy = disassemble_row(File::getVariousFile("diplomacy-small.png"),
134                               DIPLOMACY_TYPES, broken);
135   if (broken)
136     return false;
137   for (unsigned int i = 0; i < DIPLOMACY_TYPES ; i++)
138     {
139       if (diplomacy[i]->get_width() != ts)
140 	PixMask::scale(diplomacy[i], ts, ts);
141       d_diplomacy[0][i] = diplomacy[i];
142     }
143 
144   ts = 50;
145   diplomacy = disassemble_row(File::getVariousFile("diplomacy-large.png"),
146                               DIPLOMACY_TYPES, broken);
147   if (broken)
148     return false;
149   for (unsigned int i = 0; i < DIPLOMACY_TYPES ; i++)
150     {
151       if (diplomacy[i]->get_width() != ts)
152 	PixMask::scale(diplomacy[i], ts, ts);
153       d_diplomacy[1][i] = diplomacy[i];
154     }
155   return true;
156 }
157 
loadCursorImages()158 bool ImageCache::loadCursorImages()
159 {
160   bool broken = false;
161   int ts = 16;
162 
163   // load the cursor pictures
164   std::vector<PixMask*> cursor;
165   cursor = disassemble_row(File::getVariousFile("cursors.png"),
166                            CURSOR_TYPES, broken);
167   if (broken)
168     return false;
169   for (unsigned int i = 0; i < CURSOR_TYPES ; i++)
170     {
171       if (cursor[i]->get_width() != ts)
172 	PixMask::scale(cursor[i], ts, ts);
173       d_cursor[i] = cursor[i];
174     }
175   return true;
176 }
177 
loadProdShieldImages()178 bool ImageCache::loadProdShieldImages()
179 {
180   bool broken = false;
181   //load the production shieldset
182   std::vector<PixMask*> prodshield;
183   prodshield = disassemble_row
184     (File::getVariousFile("prodshieldset.png"), PRODUCTION_SHIELD_TYPES,
185      broken);
186   if (broken)
187     return false;
188   for (unsigned int i = 0; i < PRODUCTION_SHIELD_TYPES; i++)
189     d_prodshield[i] = prodshield[i];
190   prodshield.clear();
191   return true;
192 }
193 
loadMoveBonusImages()194 bool ImageCache::loadMoveBonusImages()
195 {
196   bool broken = false;
197   //load the movement bonus icons
198   std::vector<PixMask*> movebonus;
199   movebonus = disassemble_row(File::getVariousFile("movebonus.png"),
200                               MOVE_BONUS_TYPES, broken);
201   if (broken)
202     return false;
203   for (unsigned int i = 0; i < MOVE_BONUS_TYPES; i++)
204     d_movebonus[i] = movebonus[i];
205   return true;
206 }
207 
loadNewLevelImages()208 bool ImageCache::loadNewLevelImages()
209 {
210   bool broken = false;
211   std::vector<PixMask*> half;
212   half = disassemble_row
213     (ScenarioMedia::getDefaultHeroNewLevelMaleImageFilename(), 2, broken);
214   if (broken)
215     return false;
216   d_newlevel_male = half[0];
217   d_newlevelmask_male = half[1];
218   half = disassemble_row
219     (ScenarioMedia::getDefaultHeroNewLevelFemaleImageFilename(), 2, broken);
220   if (broken)
221     return false;
222   d_newlevel_female = half[0];
223   d_newlevelmask_female = half[1];
224   return true;
225 }
226 
loadDefaultTileStyleImages()227 bool ImageCache::loadDefaultTileStyleImages()
228 {
229   bool broken = false;
230   std::vector<PixMask*> images =
231     disassemble_row(File::getVariousFile("tilestyles.png"),
232                     DEFAULT_TILESTYLE_TYPES, broken);
233   if (broken)
234     return false;
235   for (unsigned int i = 0; i < DEFAULT_TILESTYLE_TYPES; i++)
236     d_default_tilestyles[i] = images[i];
237   return true;
238 }
239 
loadMedalImages(Glib::ustring sm,Glib::ustring lg)240 bool ImageCache::loadMedalImages(Glib::ustring sm, Glib::ustring lg)
241 {
242   bool broken = false;
243   //load the medal icons
244   int ts = 40;
245   std::vector<PixMask*> medal;
246   medal = disassemble_row(sm, MEDAL_TYPES, broken);
247   if (broken)
248     return false;
249   for (unsigned int i = 0; i < MEDAL_TYPES; i++)
250     {
251       if (medal[i]->get_width() != ts)
252         PixMask::scale(medal[i], ts, ts);
253       d_medal[0][i] = medal[i];
254     }
255   medal = disassemble_row(lg, MEDAL_TYPES, broken);
256   if (broken)
257     return false;
258   for (unsigned int i = 0; i < MEDAL_TYPES; i++)
259     d_medal[1][i] = medal[i];
260   return true;
261 }
262 
loadWaypointImages()263 bool ImageCache::loadWaypointImages()
264 {
265   bool broken = false;
266   std::vector<PixMask*> images = disassemble_row
267     (File::getVariousFile("waypoints.png"), NUM_WAYPOINTS, broken);
268   if (broken)
269     return false;
270   for (unsigned int i = 0; i < NUM_WAYPOINTS; i++)
271     d_waypoint[i] = images[i];
272   return true;
273 }
274 
loadGameButtonImages()275 bool ImageCache::loadGameButtonImages()
276 {
277   bool broken = false;
278   std::vector<PixMask*> images = disassemble_row
279     (File::getVariousFile("buttons.png"), NUM_GAME_BUTTON_IMAGES, broken);
280   if (broken)
281     return false;
282   int w = 0, h = 0;
283   Gtk::IconSize::lookup(Gtk::IconSize(Gtk::ICON_SIZE_BUTTON), w, h);
284   for (unsigned int i = 0; i < NUM_GAME_BUTTON_IMAGES; i++)
285     PixMask::scale(images[i], w, h);
286   for (unsigned int i = 0; i < NUM_GAME_BUTTON_IMAGES; i++)
287     d_gamebuttons[i] = images[i];
288 
289   images.clear();
290   return true;
291 }
292 
loadMiscImage(Glib::ustring pngfile)293 PixMask* ImageCache::loadMiscImage(Glib::ustring pngfile)
294 {
295   bool broken = false;
296   return PixMask::create(File::getVariousFile(pngfile), broken);
297 }
298 
~ImageCache()299 ImageCache::~ImageCache()
300 {
301 
302   for (unsigned int i = 0; i < DIPLOMACY_TYPES;i++)
303     {
304       delete d_diplomacy[0][i];
305       delete d_diplomacy[1][i];
306     }
307 
308   for (unsigned int i = 0; i < CURSOR_TYPES;i++)
309     delete d_cursor[i];
310 
311   for (unsigned int i = 0; i < PRODUCTION_SHIELD_TYPES; i++)
312     delete d_prodshield[i];
313 
314   for (unsigned int i = 0; i < MOVE_BONUS_TYPES; i++)
315     delete d_movebonus[i];
316 
317   delete d_newlevel_male;
318   delete d_newlevelmask_male;
319   delete d_newlevel_female;
320   delete d_newlevelmask_female;
321 
322   for (unsigned int i = 0; i < DEFAULT_TILESTYLE_TYPES; i++)
323     delete d_default_tilestyles[i];
324 
325   for (unsigned int i = 0; i < MEDAL_TYPES; i++)
326     {
327       delete d_medal[0][i];
328       delete d_medal[1][i];
329     }
330 
331   delete d_smallruinedcity;
332   delete d_smallhero;
333   delete d_smallbag;
334   delete d_smallinactivehero;
335   delete d_small_temple;
336   delete d_small_ruin_unexplored;
337   delete d_small_stronghold_unexplored;
338   delete d_small_ruin_explored;
339 
340   for (unsigned int i = 0; i < NUM_WAYPOINTS; i++)
341     delete d_waypoint[i];
342 
343   for (unsigned int i = 0; i < NUM_GAME_BUTTON_IMAGES; i++)
344     delete d_gamebuttons[i];
345 
346   if (d_nextturn)
347     delete d_nextturn;
348   if (d_citydefeated)
349     delete d_citydefeated;
350   if (d_winning)
351     delete d_winning;
352   if (d_malehero)
353     delete d_malehero;
354   if (d_femalehero)
355     delete d_femalehero;
356   if (d_ruinsuccess)
357     delete d_ruinsuccess;
358   if (d_ruindefeat)
359     delete d_ruindefeat;
360   if (d_parleyoffered)
361     delete d_parleyoffered;
362   if (d_parleyrefused)
363     delete d_parleyrefused;
364   if (d_commentator)
365     delete d_commentator;
366   reset();
367 }
368 
reset()369 void ImageCache::reset()
370 {
371   selectorcache.reset();
372   flagcache.reset();
373   armycache.reset();
374   circledarmycache.reset();
375   tilecache.reset();
376   citycache.reset();
377   towercache.reset();
378   templecache.reset();
379   ruincache.reset();
380   diplomacycache.reset();
381   roadcache.reset();
382   fogcache.reset();
383   bridgecache.reset();
384   cursorcache.reset();
385   shieldcache.reset();
386   prodshieldcache.reset();
387   movebonuscache.reset();
388   shipcache.reset();
389   plantedstandardcache.reset();
390   portcache.reset();
391   signpostcache.reset();
392   bagcache.reset();
393   explosioncache.reset();
394   newlevelcache.reset();
395   defaulttilestylecache.reset();
396   tartancache.reset();
397   emptytartancache.reset();
398   statuscache.reset();
399   gamebuttoncache.reset();
400   dialogcache.reset();
401   medalcache.reset();
402 
403   d_cachesize = 0;
404   return;
405 }
406 
checkPictures()407 void ImageCache::checkPictures()
408 {
409   guint32 maxcache = Configuration::s_cacheSize;
410   if (maxcache < MINIMUM_CACHE_SIZE)
411     maxcache = MINIMUM_CACHE_SIZE;
412 
413   if (d_cachesize < maxcache)
414     return;
415 
416   // Now the cache size has been exceeded. We try to guarantee the values
417   // given above and reduce the number of images. Let us start with the
418   // cities
419 
420   unsigned int num_players = Playerlist::getInstance()->countPlayersAlive();
421   if (armycache.size() >= 15 * num_players)
422     {
423       d_cachesize -= armycache.discardHalf();
424       if (d_cachesize < maxcache)
425         return;
426     }
427 
428   if (circledarmycache.size() >= 15 * num_players)
429     {
430       d_cachesize -= circledarmycache.discardHalf();
431       if (d_cachesize < maxcache)
432         return;
433     }
434 
435   if (flagcache.size() >= num_players * MAX_STACK_SIZE)
436     {
437       d_cachesize -= flagcache.discardHalf();
438       if (d_cachesize < maxcache)
439         return;
440     }
441 
442   if (citycache.size() >= num_players)
443     {
444       d_cachesize -= citycache.discardHalf();
445       if (d_cachesize < maxcache)
446         return;
447     }
448 
449   if (roadcache.size() >= ROAD_TYPES / 2)
450     {
451       d_cachesize -= roadcache.discardHalf();
452       if (d_cachesize < maxcache)
453         return;
454     }
455 
456   if (fogcache.size() >= FOG_TYPES / 2)
457     {
458       d_cachesize -= fogcache.discardHalf();
459       if (d_cachesize < maxcache)
460         return;
461     }
462 
463   if (bridgecache.size() >= BRIDGE_TYPES)
464     {
465       d_cachesize -= bridgecache.discardHalf();
466       if (d_cachesize < maxcache)
467         return;
468     }
469 
470   if (shipcache.size() >= MAX_PLAYERS)
471     {
472       d_cachesize -= shipcache.discardHalf();
473       if (d_cachesize < maxcache)
474         return;
475     }
476 
477   if (plantedstandardcache.size() >= num_players)
478     {
479       d_cachesize -= plantedstandardcache.discardHalf();
480       if (d_cachesize < maxcache)
481         return;
482     }
483 
484   if (portcache.size() > 1)
485     {
486       d_cachesize -= portcache.discardHalf();
487       if (d_cachesize < maxcache)
488         return;
489     }
490 
491   if (towercache.size() >= num_players)
492     {
493       d_cachesize -= towercache.discardHalf();
494       if (d_cachesize < maxcache)
495         return;
496     }
497 
498   if (templecache.size() >= TEMPLE_TYPES)
499     {
500       d_cachesize -= templecache.discardHalf();
501       if (d_cachesize < maxcache)
502         return;
503     }
504 
505   if (ruincache.size() >= RUIN_TYPES)
506     {
507       d_cachesize -= ruincache.discardHalf();
508       if (d_cachesize < maxcache)
509         return;
510     }
511 
512   if (signpostcache.size() > 1)
513     {
514       d_cachesize -= signpostcache.discardHalf();
515       if (d_cachesize < maxcache)
516         return;
517     }
518 
519   if (bagcache.size() > 1)
520     {
521       d_cachesize -= bagcache.discardHalf();
522       if (d_cachesize < maxcache)
523         return;
524     }
525 
526   if (selectorcache.size() >= num_players * MAX_STACK_SIZE)
527     {
528       d_cachesize -= selectorcache.discardHalf();
529       if (d_cachesize < maxcache)
530         return;
531     }
532 
533   if (tilecache.size() >= 15*15)
534     {
535       d_cachesize -= tilecache.discardHalf();
536       if (d_cachesize < maxcache)
537         return;
538     }
539 
540   if (diplomacycache.size() >= DIPLOMACY_TYPES)
541     {
542       d_cachesize -= diplomacycache.discardHalf();
543       if (d_cachesize < maxcache)
544         return;
545     }
546 
547   if (cursorcache.size() >= CURSOR_TYPES)
548     {
549       d_cachesize -= cursorcache.discardHalf();
550       if (d_cachesize < maxcache)
551         return;
552     }
553 
554   if (shieldcache.size() >= num_players * 3)
555     {
556       d_cachesize -= shieldcache.discardHalf();
557       if (d_cachesize < maxcache)
558         return;
559     }
560 
561   if (prodshieldcache.size() >= PRODUCTION_SHIELD_TYPES)
562     {
563       d_cachesize -= prodshieldcache.discardHalf();
564       if (d_cachesize < maxcache)
565         return;
566     }
567 
568   if (movebonuscache.size() >= MOVE_BONUS_TYPES)
569     {
570       d_cachesize -= movebonuscache.discardHalf();
571       if (d_cachesize < maxcache)
572         return;
573     }
574 
575   if (explosioncache.size() > 1)
576     {
577       d_cachesize -= explosioncache.discardHalf();
578       if (d_cachesize < maxcache)
579         return;
580     }
581 
582   if (newlevelcache.size() > 2)
583     {
584       d_cachesize -= newlevelcache.discardHalf();
585       if (d_cachesize < maxcache)
586         return;
587     }
588 
589   if (defaulttilestylecache.size() >= DEFAULT_TILESTYLE_TYPES)
590     {
591       d_cachesize -= defaulttilestylecache.discardHalf();
592       if (d_cachesize < maxcache)
593         return;
594     }
595 
596   if (tartancache.size() >= MAX_PLAYERS + 1)
597     {
598       d_cachesize -= tartancache.discardHalf();
599       if (d_cachesize < maxcache)
600         return;
601     }
602 
603   if (emptytartancache.size() >= MAX_PLAYERS + 1)
604     {
605       d_cachesize -= emptytartancache.discardHalf();
606       if (d_cachesize < maxcache)
607         return;
608     }
609 
610   if (statuscache.size() >= 6)
611     {
612       d_cachesize -= statuscache.discardHalf();
613       if (d_cachesize < maxcache)
614         return;
615     }
616 
617   if (gamebuttoncache.size() >= 12)
618     {
619       d_cachesize -= gamebuttoncache.discardHalf();
620       if (d_cachesize < maxcache)
621         return;
622     }
623 
624   if (dialogcache.size() >= 10)
625     {
626       d_cachesize -= dialogcache.discardHalf();
627       if (d_cachesize < maxcache)
628         return;
629     }
630 
631   if (medalcache.size() >= 6)
632     {
633       d_cachesize -= medalcache.discardHalf();
634       if (d_cachesize < maxcache)
635         return;
636     }
637 }
638 
getSelectorPic(guint32 type,guint32 frame,const Player * p)639 PixMask* ImageCache::getSelectorPic(guint32 type, guint32 frame,
640                                     const Player *p)
641 {
642   return getSelectorPic(type, frame, p,
643                         GameMap::getInstance()->getTilesetId());
644 }
645 
getSelectorPic(guint32 type,guint32 frame,const Player * p,guint32 tileset)646 PixMask* ImageCache::getSelectorPic(guint32 type, guint32 frame,
647                                     const Player *p, guint32 tileset)
648 {
649   guint32 added = 0;
650   SelectorPixMaskCacheItem i;
651   i.tileset = tileset;
652   i.type = type;
653   i.frame = frame;
654   i.player_id = p->getId();
655   PixMask *s = selectorcache.get(i, added);
656   d_cachesize += added;
657   if (added)
658     checkPictures();
659   return s;
660 }
661 
getArmyPic(Army * a,bool greyed)662 PixMask* ImageCache::getArmyPic(Army *a, bool greyed)
663 {
664   return getArmyPic(a->getOwner()->getArmyset(), a->getTypeId(),
665 		    a->getOwner(), NULL, true, 0, greyed);
666 }
667 
getDialogArmyPic(Army * a,guint32 font_size,bool greyed)668 PixMask* ImageCache::getDialogArmyPic(Army *a, guint32 font_size, bool greyed)
669 {
670   return getArmyPic(a->getOwner()->getArmyset(), a->getTypeId(),
671 		    a->getOwner(), NULL, false, font_size, greyed);
672 }
673 
getArmyPic(guint32 armyset,guint32 army_id,const Player * p,const bool * medals,bool map,guint32 font_size,bool greyed)674 PixMask* ImageCache::getArmyPic(guint32 armyset, guint32 army_id,
675                                 const Player* p, const bool *medals,
676                                 bool map, guint32 font_size, bool greyed)
677 {
678   guint added = 0;
679   ArmyPixMaskCacheItem i;
680   i.armyset = armyset;
681   i.army_id = army_id;
682   i.player_id = p->getId();
683   for (guint32 j = 0; j < MEDAL_TYPES; j++)
684     if (medals)
685       i.medals[j] = medals[j];
686     else
687       i.medals[j] = false;
688   i.map = map;
689   i.font_size = font_size;
690   i.greyed = greyed;
691   PixMask *s = armycache.get(i, added);
692   if (!s)
693     {
694       guint32 size = Armysetlist::getInstance()->get(i.armyset)->getTileSize();
695       s = getDefaultTileStylePic(DEFAULT_TILESTYLE_TYPES-1, size);
696     }
697   d_cachesize += added;
698   if (added)
699     checkPictures();
700   return s;
701 }
702 
getFlagPic(guint32 stack_size,const Player * p,guint32 tileset)703 PixMask* ImageCache::getFlagPic(guint32 stack_size, const Player *p, guint32 tileset)
704 {
705   guint32 added = 0;
706   FlagPixMaskCacheItem i;
707   i.tileset = tileset;
708   i.size = stack_size;
709   i.player_id = p->getId();
710   PixMask *s = flagcache.get(i, added);
711   d_cachesize += added;
712   if (added)
713     checkPictures();
714   return s;
715 }
716 
getFlagPic(guint32 stack_size,const Player * p)717 PixMask* ImageCache::getFlagPic(guint32 stack_size, const Player *p)
718 {
719   return getFlagPic(stack_size, p,
720 		    GameMap::getInstance()->getTilesetId());
721 }
722 
getFlagPic(const Stack * s)723 PixMask* ImageCache::getFlagPic(const Stack* s)
724 {
725   return getFlagPic(s, GameMap::getInstance()->getTilesetId());
726 }
727 
getFlagPic(const Stack * s,guint32 tileset)728 PixMask* ImageCache::getFlagPic(const Stack* s, guint32 tileset)
729 {
730   return getFlagPic(s->size(), s->getOwner(), tileset);
731 }
732 
getCircledArmyPic(Army * a,bool greyed,guint32 circle_colour_id,bool show_army,guint32 font_size)733 PixMask* ImageCache::getCircledArmyPic(Army *a, bool greyed,
734                                        guint32 circle_colour_id,
735                                        bool show_army, guint32 font_size)
736 {
737   return getCircledArmyPic(a->getOwner()->getArmyset(), a->getTypeId(),
738 		    a->getOwner(), NULL, greyed, circle_colour_id, show_army,
739                     font_size);
740 }
741 
getCircledArmyPic(guint32 armyset,guint32 army_id,const Player * p,const bool * medals,bool greyed,guint32 circle_colour_id,bool show_army,guint32 font_size)742 PixMask* ImageCache::getCircledArmyPic(guint32 armyset, guint32 army_id,
743                                              const Player* p,
744                                              const bool *medals, bool greyed,
745                                              guint32 circle_colour_id,
746                                              bool show_army, guint32 font_size)
747 {
748   guint added = 0;
749   CircledArmyPixMaskCacheItem i;
750   i.armyset = armyset;
751   i.army_id = army_id;
752   i.player_id = p->getId();
753   for (guint32 j = 0; j < MEDAL_TYPES; j++)
754     if (medals)
755       i.medals[j] = medals[j];
756     else
757       i.medals[j] = false;
758   i.greyed = greyed;
759   i.circle_colour_id = circle_colour_id;
760   i.show_army = show_army;
761   i.font_size = font_size;
762   PixMask *s = circledarmycache.get(i, added);
763   d_cachesize += added;
764   if (added)
765     checkPictures();
766   return s;
767 }
768 
getTilePic(int tile_style_id,int fog_type_id,bool has_bag,bool has_standard,int standard_player_id,int stack_size,int stack_player_id,int army_type_id,bool has_tower,bool has_ship,Maptile::Building building_type,int building_subtype,Vector<int> building_tile,int building_player_id,guint32 tilesize,bool has_grid,int stone_type)769 PixMask* ImageCache::getTilePic(int tile_style_id, int fog_type_id, bool has_bag, bool has_standard, int standard_player_id, int stack_size, int stack_player_id, int army_type_id, bool has_tower, bool has_ship, Maptile::Building building_type, int building_subtype, Vector<int> building_tile, int building_player_id, guint32 tilesize, bool has_grid, int stone_type)
770 {
771   guint32 tileset = GameMap::getInstance()->getTilesetId();
772   guint32 cityset = GameMap::getInstance()->getCitysetId();
773   guint32 shieldset = GameMap::getInstance()->getShieldsetId();
774   return getTilePic(tile_style_id, fog_type_id, has_bag, has_standard, standard_player_id, stack_size, stack_player_id, army_type_id, has_tower, has_ship, building_type, building_subtype, building_tile, building_player_id, tilesize, has_grid, tileset, cityset, shieldset, stone_type);
775 }
776 
getTilePic(int tile_style_id,int fog_type_id,bool has_bag,bool has_standard,int standard_player_id,int stack_size,int stack_player_id,int army_type_id,bool has_tower,bool has_ship,Maptile::Building building_type,int building_subtype,Vector<int> building_tile,int building_player_id,guint32 tilesize,bool has_grid,guint32 tileset,guint32 cityset,guint32 shieldset,int stone_type)777 PixMask* ImageCache::getTilePic(int tile_style_id, int fog_type_id, bool has_bag, bool has_standard, int standard_player_id, int stack_size, int stack_player_id, int army_type_id, bool has_tower, bool has_ship, Maptile::Building building_type, int building_subtype, Vector<int> building_tile, int building_player_id, guint32 tilesize, bool has_grid, guint32 tileset, guint32 cityset, guint32 shieldset, int stone_type)
778 {
779   guint added = 0;
780   TilePixMaskCacheItem i;
781   i.tile_style_id = tile_style_id;
782   i.fog_type_id = fog_type_id;
783   i.has_bag = has_bag;
784   i.has_standard = has_standard;
785   i.standard_player_id = standard_player_id;
786   i.stack_size = stack_size; //flag size
787   i.stack_player_id = stack_player_id;
788   i.army_type_id = army_type_id;
789   i.has_tower = has_tower;
790   i.has_ship = has_ship;
791   i.building_type = building_type;
792   i.building_subtype = building_subtype;
793   i.building_tile = building_tile;
794   i.building_player_id = building_player_id;
795   i.tilesize = tilesize;
796   i.has_grid = has_grid;
797   i.tileset = tileset;
798   i.cityset = cityset;
799   i.shieldset = shieldset;
800   i.stone_type = stone_type;
801   PixMask *s = tilecache.get(i, added);
802   d_cachesize += added;
803   if (added)
804     checkPictures();
805   return s;
806 }
807 
getCityPic(const City * city,guint32 cityset)808 PixMask* ImageCache::getCityPic(const City* city, guint32 cityset)
809 {
810   if (!city)
811     return NULL;
812   int type;
813   if (city->isBurnt() == true)
814     type = -1;
815   else
816     type = 0;
817   return getCityPic(type, city->getOwner(), cityset);
818 }
819 
getCityPic(const City * city)820 PixMask* ImageCache::getCityPic(const City* city)
821 {
822   guint32 cityset = GameMap::getInstance()->getCitysetId();
823   return getCityPic(city, cityset);
824 }
825 
getCityPic(int type,const Player * p,guint32 cityset)826 PixMask* ImageCache::getCityPic(int type, const Player* p, guint32 cityset)
827 {
828   guint added = 0;
829   CityPixMaskCacheItem i;
830   i.cityset = cityset;
831   i.type = type;
832   i.player_id = p->getId();
833   PixMask *s = citycache.get(i, added);
834   d_cachesize += added;
835   if (added)
836     checkPictures();
837   return s;
838 }
839 
getTowerPic(const Player * p)840 PixMask* ImageCache::getTowerPic(const Player* p)
841 {
842   guint32 cityset = GameMap::getInstance()->getCitysetId();
843   return getTowerPic(p, cityset);
844 }
845 
getTowerPic(const Player * p,guint32 cityset)846 PixMask* ImageCache::getTowerPic(const Player* p, guint32 cityset)
847 {
848   guint added = 0;
849   TowerPixMaskCacheItem i;
850   i.cityset = cityset;
851   i.player_id = p->getId();
852   PixMask *s = towercache.get(i, added);
853   d_cachesize += added;
854   if (added)
855     checkPictures();
856   return s;
857 }
858 
getTemplePic(Temple * t)859 PixMask* ImageCache::getTemplePic(Temple *t)
860 {
861   guint32 cityset = GameMap::getInstance()->getCitysetId();
862   return getTemplePic(t->getType(), cityset);
863 }
864 
getTemplePic(int type)865 PixMask* ImageCache::getTemplePic(int type)
866 {
867   guint32 cityset = GameMap::getInstance()->getCitysetId();
868   return getTemplePic(type, cityset);
869 }
870 
getTemplePic(int type,guint32 cityset)871 PixMask* ImageCache::getTemplePic(int type, guint32 cityset)
872 {
873   guint added = 0;
874   TemplePixMaskCacheItem i;
875   i.cityset = cityset;
876   i.type = type;
877   PixMask *s = templecache.get(i, added);
878   d_cachesize += added;
879   if (added)
880     checkPictures();
881   return s;
882 }
883 
getRuinPic(Ruin * ruin)884 PixMask* ImageCache::getRuinPic(Ruin *ruin)
885 {
886   guint32 cityset = GameMap::getInstance()->getCitysetId();
887   return getRuinPic(ruin->getType(), cityset);
888 }
getRuinPic(int type)889 PixMask* ImageCache::getRuinPic(int type)
890 {
891   guint32 cityset = GameMap::getInstance()->getCitysetId();
892   return getRuinPic(type, cityset);
893 }
894 
getRuinPic(int type,guint32 cityset)895 PixMask* ImageCache::getRuinPic(int type, guint32 cityset)
896 {
897   guint added = 0;
898   RuinPixMaskCacheItem i;
899   i.cityset = cityset;
900   i.type = type;
901   PixMask *s = ruincache.get(i, added);
902   d_cachesize += added;
903   if (added)
904     checkPictures();
905   return s;
906 }
907 
getDiplomacyPic(int type,Player::DiplomaticState state,guint32 font_size)908 PixMask* ImageCache::getDiplomacyPic(int type, Player::DiplomaticState state,
909                                      guint32 font_size)
910 {
911   guint added = 0;
912   DiplomacyPixMaskCacheItem i;
913   i.type = type;
914   i.state = state;
915   i.font_size = font_size;
916   PixMask *s = diplomacycache.get(i, added);
917   d_cachesize += added;
918   if (added)
919     checkPictures();
920   return s;
921 }
922 
getRoadPic(Road * r)923 PixMask* ImageCache::getRoadPic(Road *r)
924 {
925   return ImageCache::getRoadPic(r->getType());
926 }
927 
getRoadPic(int type)928 PixMask* ImageCache::getRoadPic(int type)
929 {
930   return getRoadPic(type, GameMap::getInstance()->getTilesetId());
931 }
932 
getRoadPic(int type,guint32 tileset)933 PixMask* ImageCache::getRoadPic(int type, guint32 tileset)
934 {
935   guint added = 0;
936   RoadPixMaskCacheItem i;
937   i.type = type;
938   i.tileset = tileset;
939   PixMask *s = roadcache.get(i, added);
940   d_cachesize += added;
941   if (added)
942     checkPictures();
943   return s;
944 }
945 
getFogPic(int type)946 PixMask* ImageCache::getFogPic(int type)
947 {
948   return getFogPic(type, GameMap::getInstance()->getTilesetId());
949 }
950 
getFogPic(int type,guint32 tileset)951 PixMask* ImageCache::getFogPic(int type, guint32 tileset)
952 {
953   guint added = 0;
954   FogPixMaskCacheItem i;
955   i.type = type;
956   i.tileset = tileset;
957   PixMask *s = fogcache.get(i, added);
958   d_cachesize += added;
959   if (added)
960     checkPictures();
961   return s;
962 }
963 
getBridgePic(Bridge * b)964 PixMask* ImageCache::getBridgePic(Bridge *b)
965 {
966   return getBridgePic(b->getType());
967 }
968 
getBridgePic(int type)969 PixMask* ImageCache::getBridgePic(int type)
970 {
971   return getBridgePic(type, GameMap::getInstance()->getTilesetId());
972 }
973 
getBridgePic(int type,guint32 tileset)974 PixMask* ImageCache::getBridgePic(int type, guint32 tileset)
975 {
976   guint added = 0;
977   BridgePixMaskCacheItem i;
978   i.type = type;
979   i.tileset = tileset;
980   PixMask *s = bridgecache.get(i, added);
981   d_cachesize += added;
982   if (added)
983     checkPictures();
984   return s;
985 }
986 
getCursorPic(int type,guint32 font_size)987 PixMask* ImageCache::getCursorPic(int type, guint32 font_size)
988 {
989   guint added = 0;
990   CursorPixMaskCacheItem i;
991   i.type = type;
992   i.font_size = font_size;
993   PixMask *s = cursorcache.get(i, added);
994   d_cachesize += added;
995   if (added)
996     checkPictures();
997   return s;
998 }
999 
getShieldPic(guint32 type,Player * p,bool map,guint32 font_size)1000 PixMask* ImageCache::getShieldPic(guint32 type, Player *p, bool map,
1001                                   guint32 font_size)
1002 {
1003   guint32 shieldset = GameMap::getInstance()->getShieldsetId();
1004   return getShieldPic(shieldset, type, p->getId(), map, font_size);
1005 }
1006 
getShieldPic(guint32 shieldset,guint32 type,guint32 colour,bool map,guint32 font_size)1007 PixMask* ImageCache::getShieldPic(guint32 shieldset, guint32 type,
1008                                         guint32 colour, bool map,
1009                                         guint32 font_size)
1010 {
1011   guint added = 0;
1012   ShieldPixMaskCacheItem i;
1013   i.type = type;
1014   i.shieldset = shieldset;
1015   i.colour = colour;
1016   i.map = map;
1017   i.font_size = font_size;
1018   PixMask *s = shieldcache.get(i, added);
1019   d_cachesize += added;
1020   if (added)
1021     checkPictures();
1022   return s;
1023 }
1024 
getStatusPic(guint32 type,guint32 font_size)1025 PixMask* ImageCache::getStatusPic(guint32 type, guint32 font_size)
1026 {
1027   guint added = 0;
1028   StatusPixMaskCacheItem i;
1029   i.type = type;
1030   i.font_size = font_size;
1031   PixMask *s = statuscache.get(i, added);
1032   d_cachesize += added;
1033   if (added)
1034     checkPictures();
1035   return s;
1036 }
1037 
getGameButtonPic(guint32 type,guint32 font_size)1038 PixMask* ImageCache::getGameButtonPic(guint32 type, guint32 font_size)
1039 {
1040   guint added = 0;
1041   GameButtonPixMaskCacheItem i;
1042   i.type = type;
1043   i.font_size = font_size;
1044   PixMask *s = gamebuttoncache.get(i, added);
1045   d_cachesize += added;
1046   if (added)
1047     checkPictures();
1048   return s;
1049 }
1050 
getProdShieldPic(guint32 type,bool prod)1051 PixMask* ImageCache::getProdShieldPic(guint32 type, bool prod)
1052 {
1053   guint added = 0;
1054   ProdShieldPixMaskCacheItem i;
1055   i.type = type;
1056   i.prod = prod;
1057   PixMask *s = prodshieldcache.get(i, added);
1058   d_cachesize += added;
1059   if (added)
1060     checkPictures();
1061   return s;
1062 }
1063 
getMoveBonusPic(guint32 bonus,bool has_ship,guint32 font_size)1064 PixMask* ImageCache::getMoveBonusPic(guint32 bonus, bool has_ship,
1065                                      guint32 font_size)
1066 {
1067   guint added = 0;
1068   MoveBonusPixMaskCacheItem i;
1069   if (bonus == Tile::isFlying()) // show fly icon
1070     i.type = 4;
1071   else if (bonus & Tile::FOREST && bonus & Tile::HILLS) // show trees and hills
1072     i.type = 3;
1073   else if (bonus & Tile::HILLS) // show foothills
1074     i.type = 2;
1075   else if (bonus & Tile::FOREST) // show trees
1076     i.type = 1;
1077   else // show blank
1078     i.type = 0;
1079   if (has_ship && bonus != Tile::isFlying()) // (what a) show boat
1080     i.type = 5;
1081   i.font_size = font_size;
1082   PixMask *s = movebonuscache.get(i, added);
1083   d_cachesize += added;
1084   if (added)
1085     checkPictures();
1086   return s;
1087 }
1088 
getShipPic(const Player * p)1089 PixMask* ImageCache::getShipPic(const Player* p)
1090 {
1091   guint added = 0;
1092   ShipPixMaskCacheItem i;
1093   i.player_id = p->getId();
1094   i.armyset = p->getArmyset();
1095   PixMask *s = shipcache.get(i, added);
1096   if (!s)
1097     {
1098       guint32 size = Armysetlist::getInstance()->get(i.armyset)->getTileSize();
1099       s = getDefaultTileStylePic(DEFAULT_TILESTYLE_TYPES-1, size);
1100     }
1101   d_cachesize += added;
1102   if (added)
1103     checkPictures();
1104   return s;
1105 }
1106 
getPlantedStandardPic(const Player * p)1107 PixMask* ImageCache::getPlantedStandardPic(const Player* p)
1108 {
1109   guint added = 0;
1110   PlantedStandardPixMaskCacheItem i;
1111   i.player_id = p->getId();
1112   i.armyset = p->getArmyset();
1113   PixMask *s = plantedstandardcache.get(i, added);
1114   if (!s)
1115     {
1116       guint32 size = Armysetlist::getInstance()->get(i.armyset)->getTileSize();
1117       s = getDefaultTileStylePic(DEFAULT_TILESTYLE_TYPES-1, size);
1118     }
1119   d_cachesize += added;
1120   if (added)
1121     checkPictures();
1122   return s;
1123 }
1124 
getPortPic()1125 PixMask* ImageCache::getPortPic()
1126 {
1127   return getPortPic(GameMap::getInstance()->getCitysetId());
1128 }
1129 
getPortPic(guint32 cityset)1130 PixMask* ImageCache::getPortPic(guint32 cityset)
1131 {
1132   guint added = 0;
1133   PortPixMaskCacheItem i;
1134   i.cityset = cityset;
1135   PixMask *s = portcache.get(i, added);
1136   d_cachesize += added;
1137   if (added)
1138     checkPictures();
1139   return s;
1140 }
1141 
getSignpostPic()1142 PixMask* ImageCache::getSignpostPic()
1143 {
1144   return getSignpostPic(GameMap::getInstance()->getCitysetId());
1145 }
1146 
getSignpostPic(guint32 cityset)1147 PixMask* ImageCache::getSignpostPic(guint32 cityset)
1148 {
1149   guint added = 0;
1150   SignpostPixMaskCacheItem i;
1151   i.cityset = cityset;
1152   PixMask *s = signpostcache.get(i, added);
1153   d_cachesize += added;
1154   if (added)
1155     checkPictures();
1156   return s;
1157 }
1158 
getBagPic()1159 PixMask* ImageCache::getBagPic()
1160 {
1161   guint32 armyset = Playerlist::getActiveplayer()->getArmyset();
1162   return getBagPic(armyset);
1163 }
1164 
getBagPic(guint32 armyset)1165 PixMask* ImageCache::getBagPic(guint32 armyset)
1166 {
1167   guint added = 0;
1168   BagPixMaskCacheItem i;
1169   i.armyset = armyset;
1170   PixMask *s = bagcache.get(i, added);
1171   if (!s)
1172     {
1173       guint32 size = Armysetlist::getInstance()->get(i.armyset)->getTileSize();
1174       s = getDefaultTileStylePic(DEFAULT_TILESTYLE_TYPES-1, size);
1175     }
1176   d_cachesize += added;
1177   if (added)
1178     checkPictures();
1179   return s;
1180 }
1181 
getExplosionPic()1182 PixMask* ImageCache::getExplosionPic()
1183 {
1184   return getExplosionPic(GameMap::getInstance()->getTilesetId());
1185 }
1186 
getExplosionPic(guint32 tileset)1187 PixMask* ImageCache::getExplosionPic(guint32 tileset)
1188 {
1189   guint added = 0;
1190   ExplosionPixMaskCacheItem i;
1191   i.tileset = tileset;
1192   PixMask *s = explosioncache.get(i, added);
1193   d_cachesize += added;
1194   if (added)
1195     checkPictures();
1196   return s;
1197 }
1198 
getNewLevelPic(const Player * p,guint32 gender,guint32 font_size)1199 PixMask* ImageCache::getNewLevelPic(const Player* p, guint32 gender,
1200                                     guint32 font_size)
1201 {
1202   guint added = 0;
1203   NewLevelPixMaskCacheItem i;
1204   i.player_id = p->getId();
1205   i.gender = gender;
1206   i.font_size = font_size;
1207   PixMask *s = newlevelcache.get(i, added);
1208   d_cachesize += added;
1209   if (added)
1210     checkPictures();
1211   return s;
1212 }
1213 
getDefaultTileStylePic(guint32 type,guint32 size)1214 PixMask* ImageCache::getDefaultTileStylePic(guint32 type, guint32 size)
1215 {
1216   guint added = 0;
1217   DefaultTileStylePixMaskCacheItem i;
1218   i.tilestyle_type = type;
1219   i.tilesize = size;
1220   PixMask *s = defaulttilestylecache.get(i, added);
1221   d_cachesize += added;
1222   if (added)
1223     checkPictures();
1224   return s;
1225 }
1226 
getTartanPic(const Player * p,guint32 width,Shieldset * shieldset,guint32 font_size)1227 PixMask* ImageCache::getTartanPic(const Player *p, guint32 width, Shieldset *shieldset, guint32 font_size)
1228 {
1229   guint added = 0;
1230   TartanPixMaskCacheItem i;
1231   i.player_id = p->getId();
1232   i.width = width;
1233   i.shieldset = shieldset->getId();
1234   i.font_size = font_size;
1235   PixMask *s = tartancache.get(i, added);
1236   d_cachesize += added;
1237   if (added)
1238     checkPictures();
1239   return s;
1240 }
1241 
getEmptyTartanPic(const Player * p,guint32 width,Shieldset * shieldset,guint32 font_size)1242 PixMask* ImageCache::getEmptyTartanPic(const Player *p, guint32 width, Shieldset *shieldset, guint32 font_size)
1243 {
1244   guint added = 0;
1245   EmptyTartanPixMaskCacheItem i;
1246   i.player_id = p->getId();
1247   i.width = width;
1248   i.shieldset = shieldset->getId();
1249   i.font_size = font_size;
1250   PixMask *s = emptytartancache.get(i, added);
1251   d_cachesize += added;
1252   if (added)
1253     checkPictures();
1254   return s;
1255 }
1256 
getDialogPic(guint32 type,guint32 font_size)1257 PixMask* ImageCache::getDialogPic(guint32 type, guint32 font_size)
1258 {
1259   guint added = 0;
1260   DialogPixMaskCacheItem i;
1261   i.type = type;
1262   i.font_size = font_size;
1263   PixMask *s = dialogcache.get(i, added);
1264   d_cachesize += added;
1265   if (added)
1266     checkPictures();
1267   return s;
1268 }
1269 
getDiplomacyImage(int type,Player::DiplomaticState state)1270 PixMask* ImageCache::getDiplomacyImage(int type, Player::DiplomaticState state)
1271 {
1272   return d_diplomacy[type][state];
1273 }
1274 
getMoveBonusImage(guint32 type)1275 PixMask* ImageCache::getMoveBonusImage(guint32 type)
1276 {
1277   return d_movebonus[type];
1278 }
1279 
getDefaultTileStyleImage(guint32 type)1280 PixMask* ImageCache::getDefaultTileStyleImage(guint32 type)
1281 {
1282   return d_default_tilestyles[type];
1283 }
1284 
getCursorImage(int type)1285 PixMask* ImageCache::getCursorImage(int type)
1286 {
1287   return d_cursor[type];
1288 }
1289 
getProdShieldImage(guint32 type)1290 PixMask *ImageCache::getProdShieldImage(guint32 type)
1291 {
1292   return d_prodshield[type];
1293 }
1294 
getMedalImage(bool large,int type)1295 PixMask* ImageCache::getMedalImage(bool large, int type)
1296 {
1297   if (large)
1298     {
1299       if (ScenarioMedia::getInstance()->getBigMedalsImageName() != "")
1300         return ScenarioMedia::getInstance()->getBigMedalImage(type);
1301       else
1302         return d_medal[1][type];
1303     }
1304   else
1305     {
1306       if (ScenarioMedia::getInstance()->getSmallMedalsImageName() != "")
1307         return ScenarioMedia::getInstance()->getSmallMedalImage(type);
1308       else
1309         return d_medal[0][type];
1310     }
1311 }
1312 
getNewLevelImage(bool female,bool mask)1313 PixMask *ImageCache::getNewLevelImage(bool female, bool mask)
1314 {
1315   if (female && mask)
1316     {
1317       if (ScenarioMedia::getInstance()->getHeroNewLevelFemaleMask())
1318         return ScenarioMedia::getInstance()->getHeroNewLevelFemaleMask();
1319       else
1320         return d_newlevelmask_female;
1321     }
1322   else if (female && !mask)
1323     {
1324       if (ScenarioMedia::getInstance()->getHeroNewLevelFemaleImage())
1325         return ScenarioMedia::getInstance()->getHeroNewLevelFemaleImage();
1326       else
1327         return d_newlevel_female;
1328     }
1329 
1330   if (!female && mask)
1331     {
1332       if (ScenarioMedia::getInstance()->getHeroNewLevelMaleMask())
1333         return ScenarioMedia::getInstance()->getHeroNewLevelMaleMask();
1334       else
1335         return d_newlevelmask_male;
1336     }
1337   else if (!female && !mask)
1338     {
1339       if (ScenarioMedia::getInstance()->getHeroNewLevelMaleImage())
1340         return ScenarioMedia::getInstance()->getHeroNewLevelMaleImage();
1341       else
1342         return d_newlevel_male;
1343     }
1344   return NULL;
1345 }
1346 
getMedalPic(bool large,guint32 type,guint32 font_size)1347 PixMask* ImageCache::getMedalPic(bool large, guint32 type,
1348                                         guint32 font_size)
1349 {
1350   guint added = 0;
1351   MedalPixMaskCacheItem i;
1352   i.large = large;
1353   i.type = type;
1354   i.font_size = font_size;
1355   PixMask *s = medalcache.get(i, added);
1356   d_cachesize += added;
1357   if (added)
1358     checkPictures();
1359   return s;
1360 }
1361 
getGameButtonImage(guint32 type)1362 PixMask* ImageCache::getGameButtonImage(guint32 type)
1363 {
1364   return d_gamebuttons[type];
1365 }
1366 
getWaypointImage(guint32 type)1367 PixMask* ImageCache::getWaypointImage(guint32 type)
1368 {
1369   return d_waypoint[type];
1370 }
1371 
getSmallRuinedCityImage()1372 PixMask* ImageCache::getSmallRuinedCityImage()
1373 {
1374   return d_smallruinedcity;
1375 }
1376 
getSmallBagImage()1377 PixMask* ImageCache::getSmallBagImage()
1378 {
1379   return d_smallbag;
1380 }
1381 
getSmallHeroImage(bool active)1382 PixMask* ImageCache::getSmallHeroImage(bool active)
1383 {
1384   if (active)
1385     return d_smallhero;
1386   else
1387     return d_smallinactivehero;
1388 }
1389 
getSmallRuinExploredImage()1390 PixMask* ImageCache::getSmallRuinExploredImage()
1391 {
1392   return d_small_ruin_explored;
1393 }
1394 
getSmallRuinUnexploredImage()1395 PixMask* ImageCache::getSmallRuinUnexploredImage()
1396 {
1397   return d_small_ruin_unexplored;
1398 }
1399 
getSmallStrongholdUnexploredImage()1400 PixMask* ImageCache::getSmallStrongholdUnexploredImage()
1401 {
1402   return d_small_stronghold_unexplored;
1403 }
1404 
getSmallTempleImage()1405 PixMask* ImageCache::getSmallTempleImage()
1406 {
1407   return d_small_temple;
1408 }
1409 
applyMask(PixMask * image,PixMask * mask,const Player * p)1410 PixMask* ImageCache::applyMask(PixMask* image, PixMask* mask, const Player* p)
1411 {
1412   return applyMask(image, mask, p->getColor());
1413 }
1414 
applyMask(PixMask * image,PixMask * mask,Gdk::RGBA colour)1415 PixMask* ImageCache::applyMask(PixMask* image, PixMask* mask, Gdk::RGBA colour)
1416 {
1417   int width = image->get_width();
1418   int height = image->get_height();
1419   PixMask* result = PixMask::create(image->get_pixmap(), mask->get_pixmap());
1420   if (!result)
1421     return NULL;
1422   if (mask->get_width() != width || (mask->get_height()) != height)
1423     {
1424       std::cerr <<"Warning: mask and original image do not match\n";
1425       return NULL;
1426     }
1427   Glib::RefPtr<Gdk::Pixbuf> maskbuf = mask->to_pixbuf();
1428 
1429   guint8 *data = maskbuf->get_pixels();
1430   guint8 *copy = (guint8*)  malloc (height * width * 4 * sizeof(guint8));
1431   memcpy(copy, data, height * width * 4 * sizeof(guint8));
1432   for (int i = 0; i < width; i++)
1433     for (int j = 0; j < height; j++)
1434       {
1435 	const int base = (j * 4) + (i * height * 4);
1436 
1437 	if (copy[base+3] != 0)
1438 	  {
1439 	    copy[base+0] = colour.get_red() *copy[base+0];
1440 	    copy[base+1] = colour.get_green() * copy[base+1];
1441 	    copy[base+2] = colour.get_blue() * copy[base+2];
1442 	  }
1443       }
1444   Glib::RefPtr<Gdk::Pixbuf> colouredmask =
1445     Gdk::Pixbuf::create_from_data(copy, Gdk::COLORSPACE_RGB, true, 8,
1446 				  width, height, width * 4);
1447   result->draw_pixbuf(colouredmask, 0, 0, 0, 0, width, height);
1448   free(copy);
1449 
1450   return result;
1451 }
1452 
greyOut(PixMask * image)1453 PixMask* ImageCache::greyOut(PixMask* image)
1454 {
1455   bool broken = false;
1456   int width = image->get_width();
1457   int height = image->get_height();
1458   PixMask* result = PixMask::create(image->to_pixbuf());
1459   if (broken)
1460     return NULL;
1461 
1462   guint8 *data = result->to_pixbuf()->get_pixels();
1463   guint8 *copy = (guint8*)  malloc (height * width * 4 * sizeof(guint8));
1464   memcpy(copy, data, height * width * 4 * sizeof(guint8));
1465   for (int i = 0; i < width; i++)
1466     for (int j = 0; j < height; j++)
1467       {
1468 	const int base = (j * 4) + (i * height * 4);
1469 
1470 	if (data[base+3] != 0)
1471 	  {
1472 	    guint32 max = 0;
1473 	    if (copy[base+0] > max)
1474 	      max = copy[base+0];
1475 	    else if (copy[base+1] > max)
1476 	      max = copy[base+1];
1477 	    else if (copy[base+2] > max)
1478 	      max = copy[base+2];
1479 	    int x =  i % 2;
1480 	    int y = j % 2;
1481 	    if ((x == 0 && y == 0) || (x == 1 && y == 1))
1482 	      max = 88;
1483 	    copy[base+0] = max;
1484 	    copy[base+1] = max;
1485 	    copy[base+2] = max;
1486 	  }
1487       }
1488   Glib::RefPtr<Gdk::Pixbuf> greyed_out =
1489     Gdk::Pixbuf::create_from_data(copy, Gdk::COLORSPACE_RGB, true, 8,
1490 				  width, height, width * 4);
1491 
1492   result->draw_pixbuf(greyed_out, 0, 0, 0, 0, width, height);
1493   free(copy);
1494 
1495   return result;
1496 }
draw_circle(Cairo::RefPtr<Cairo::Context> cr,double width_percent,int width,int height,Gdk::RGBA colour,bool coloured,bool mask)1497 void ImageCache::draw_circle(Cairo::RefPtr<Cairo::Context> cr, double width_percent, int width, int height, Gdk::RGBA colour, bool coloured, bool mask)
1498 {
1499   if (width_percent > 100)
1500     width_percent = 0;
1501   else if (width_percent < 0)
1502     width_percent = 0;
1503   width_percent /= 100.0;
1504   //i want 2 o'clock as a starting point, and 8pm as an ending point.
1505 
1506   double dred = BEVELED_CIRCLE_DARK.get_red();
1507   double dgreen = BEVELED_CIRCLE_DARK.get_green();
1508   double dblue = BEVELED_CIRCLE_DARK.get_blue();
1509   double lred = BEVELED_CIRCLE_LIGHT.get_red();
1510   double lgreen = BEVELED_CIRCLE_LIGHT.get_green();
1511   double lblue = BEVELED_CIRCLE_LIGHT.get_blue();
1512 
1513   double radius = (double)width * width_percent / 2.0;
1514   double line_width = radius * 0.2;
1515 
1516   if (mask)
1517     cr->set_line_width(line_width + 2.0);
1518   else
1519     cr->set_line_width(line_width + 4.0);
1520   cr->set_source_rgb(((lred - dred) / 2.0) + lred,
1521                      ((lgreen -dgreen) / 2.0) + lgreen,
1522                      ((lblue - dblue) / 2.0) + lblue);
1523   cr->arc((double)width/2.0, (double)height/2.0, radius - (line_width / 2.0), 0, 2 *M_PI);
1524   cr->stroke();
1525   if (mask)
1526     return;
1527 
1528   cr->set_line_width(1.0);
1529   cr->set_source_rgb(dred, dgreen, dblue);
1530   cr->arc((double)width/2.0, (double)height/2.0, radius, (2 * M_PI) * (2.0/12.0), (2 *M_PI) * (8.0/12.0));
1531   cr->stroke();
1532   cr->set_source_rgb(lred, lgreen, lblue);
1533   cr->arc((double)width/2.0, (double)height/2.0, radius, (2 * M_PI) * (8.0/12.0), (2 *M_PI) * (2.0/12.0));
1534   cr->stroke();
1535 
1536   radius -= line_width;
1537   cr->set_source_rgb(lred, lgreen, lblue);
1538   cr->arc((double)width/2.0, (double)height/2.0, radius, (2 * M_PI) * (2.0/12.0), (2 *M_PI) * (8.0/12.0));
1539   cr->stroke();
1540 
1541   cr->set_source_rgb(dred, dgreen, dblue);
1542   cr->arc((double)width/2.0, (double)height/2.0, radius, (2 * M_PI) * (8.0/12.0), (2 *M_PI) * (2.0/12.0));
1543   cr->stroke();
1544 
1545   if (coloured)
1546     {
1547       cr->set_line_width(line_width);
1548       double red = colour.get_red();
1549       double green = colour.get_green();
1550       double blue = colour.get_blue();
1551       cr->set_source_rgb(red, green, blue);
1552       cr->arc((double)width/2.0, (double)height/2.0, radius + (line_width / 2.0), 0, 2 *M_PI);
1553       cr->stroke();
1554     }
1555 }
1556 
circled(PixMask * image,Gdk::RGBA colour,bool coloured,double width_percent)1557 PixMask* ImageCache::circled(PixMask* image, Gdk::RGBA colour, bool coloured, double width_percent)
1558 {
1559   PixMask *copy = image->copy();
1560   int width = image->get_width();
1561   int height = image->get_height();
1562   //here we draw a coloured circle on top of the army's image
1563   Cairo::RefPtr<Cairo::Context> cr = Cairo::Context::create(copy->get_pixmap());
1564 
1565   draw_circle(cr, width_percent, width, height, colour, coloured, false);
1566 
1567   //here we draw a white circle on a copy of the image's mask.
1568   Cairo::RefPtr<Cairo::Surface> mask = copy->get_mask();
1569 
1570   cr = Cairo::Context::create(mask);
1571   draw_circle(cr, width_percent, width, height, Gdk::RGBA("white"), coloured, true);
1572   PixMask *result = PixMask::create(copy->get_pixmap(), mask);
1573   //draw the army on top again, to make it look like the circle is behind.
1574   result->draw_pixbuf(image->to_pixbuf(), 0, 0, 0, 0, width, height);
1575   delete copy;
1576   return result;
1577 }
1578 
getNextTurnPic()1579 PixMask* ImageCache::getNextTurnPic ()
1580 {
1581   PixMask *i = ScenarioMedia::getInstance()->getNextTurnImage();
1582   if (i)
1583     return i;
1584   if (!d_nextturn)
1585     {
1586       bool broken = false;
1587       i = PixMask::create(ScenarioMedia::getDefaultNextTurnImageFilename(),
1588                           broken);
1589       if (!broken)
1590         d_nextturn = i;
1591     }
1592   return d_nextturn;
1593 }
1594 
getCityDefeatedPic()1595 PixMask* ImageCache::getCityDefeatedPic ()
1596 {
1597   PixMask *i = ScenarioMedia::getInstance()->getCityDefeatedImage();
1598   if (i)
1599     return i;
1600   if (!d_citydefeated)
1601     {
1602       bool broken = false;
1603       i = PixMask::create(ScenarioMedia::getDefaultCityDefeatedImageFilename(),
1604                           broken);
1605       if (!broken)
1606         d_citydefeated = i;
1607     }
1608   return d_citydefeated;
1609 }
1610 
getWinningPic()1611 PixMask * ImageCache::getWinningPic ()
1612 {
1613   PixMask *i = ScenarioMedia::getInstance()->getWinningImage();
1614   if (i)
1615     return i;
1616   if (!d_winning)
1617     {
1618       bool broken = false;
1619       i = PixMask::create(ScenarioMedia::getDefaultWinningImageFilename(),
1620                           broken);
1621       if (!broken)
1622         d_winning = i;
1623     }
1624   return d_winning;
1625 }
1626 
getHeroPic(Hero::Gender gender)1627 PixMask * ImageCache::getHeroPic (Hero::Gender gender)
1628 {
1629   switch (gender)
1630     {
1631     case Hero::NONE:
1632     case Hero::MALE:
1633         {
1634           PixMask *i = ScenarioMedia::getInstance()->getMaleHeroImage();
1635           if (i)
1636             return i;
1637           if (!d_malehero)
1638             {
1639               bool broken = false;
1640               i = PixMask::create
1641                 (ScenarioMedia::getDefaultMaleHeroImageFilename(), broken);
1642               if (!broken)
1643                 d_malehero = i;
1644             }
1645           return d_malehero;
1646         }
1647       break;
1648     case Hero::FEMALE:
1649         {
1650           PixMask *i = ScenarioMedia::getInstance()->getFemaleHeroImage();
1651           if (i)
1652             return i;
1653           if (!d_femalehero)
1654             {
1655               bool broken = false;
1656               i = PixMask::create
1657                 (ScenarioMedia::getDefaultFemaleHeroImageFilename(), broken);
1658               if (!broken)
1659                 d_femalehero = i;
1660             }
1661           return d_femalehero;
1662         }
1663       break;
1664     }
1665   return NULL;
1666 }
1667 
getRuinSuccessPic()1668 PixMask *ImageCache::getRuinSuccessPic()
1669 {
1670   PixMask *i = ScenarioMedia::getInstance()->getRuinSuccessImage();
1671   if (i)
1672     return i;
1673   if (!d_ruinsuccess)
1674     {
1675       bool broken = false;
1676       i = PixMask::create(ScenarioMedia::getDefaultRuinSuccessImageFilename(),
1677                           broken);
1678       if (!broken)
1679         d_ruinsuccess = i;
1680     }
1681   return d_ruinsuccess;
1682 }
1683 
getRuinDefeatPic()1684 PixMask *ImageCache::getRuinDefeatPic()
1685 {
1686   PixMask *i = ScenarioMedia::getInstance()->getRuinDefeatImage();
1687   if (i)
1688     return i;
1689   if (!d_ruindefeat)
1690     {
1691       bool broken = false;
1692       i = PixMask::create(ScenarioMedia::getDefaultRuinDefeatImageFilename(),
1693                           broken);
1694       if (!broken)
1695         d_ruindefeat = i;
1696     }
1697   return d_ruindefeat;
1698 }
1699 
getParleyOfferedPic()1700 PixMask* ImageCache::getParleyOfferedPic ()
1701 {
1702   PixMask *i = ScenarioMedia::getInstance()->getParleyOfferedImage();
1703   if (i)
1704     return i;
1705   if (!d_parleyoffered)
1706     {
1707       bool broken = false;
1708       i = PixMask::create(ScenarioMedia::getDefaultParleyOfferedImageFilename(),
1709                           broken);
1710       if (!broken)
1711         d_parleyoffered = i;
1712     }
1713   return d_parleyoffered;
1714 }
1715 
getParleyRefusedPic()1716 PixMask* ImageCache::getParleyRefusedPic ()
1717 {
1718   PixMask *i = ScenarioMedia::getInstance()->getParleyRefusedImage();
1719   if (i)
1720     return i;
1721   if (!d_parleyrefused)
1722     {
1723       bool broken = false;
1724       i = PixMask::create(ScenarioMedia::getDefaultParleyRefusedImageFilename(),
1725                           broken);
1726       if (!broken)
1727         d_parleyrefused = i;
1728     }
1729   return d_parleyrefused;
1730 }
1731 
getCommentatorPic()1732 PixMask* ImageCache::getCommentatorPic ()
1733 {
1734   PixMask *i = ScenarioMedia::getInstance()->getCommentatorImage();
1735   if (i)
1736     return i;
1737   if (!d_commentator)
1738     {
1739       bool broken = false;
1740       i = PixMask::create(ScenarioMedia::getDefaultCommentatorImageFilename(),
1741                           broken);
1742       if (!broken)
1743         d_commentator = i;
1744     }
1745   return d_commentator;
1746 }
1747 
add_underline(PixMask ** p,Gdk::RGBA color,guint32 font_size)1748 void ImageCache::add_underline (PixMask **p, Gdk::RGBA color, guint32 font_size)
1749 {
1750   int height = (*p)->get_height () +
1751     (font_size * TURN_INDICATOR_FONT_SIZE_MULTIPLE);
1752   int width = (*p)->get_width ();
1753     Glib::RefPtr<Gdk::Pixbuf> pixbuf
1754     = Gdk::Pixbuf::create(Gdk::COLORSPACE_RGB, true, 8, width, height);
1755   pixbuf->fill(0x00000000);
1756   PixMask *box = PixMask::create (pixbuf);
1757   (*p)->blit (box->get_pixmap(), 0, 0);
1758   Cairo::RefPtr<Cairo::Context> cr = Cairo::Context::create(box->get_pixmap());
1759   cr->set_line_width(1.0);
1760   cr->set_source_rgba(color.get_red (), color.get_green(), color.get_blue (),
1761                       color.get_alpha ());
1762   cr->rectangle(0, (*p)->get_height (), width, height - (*p)->get_height ());
1763   cr->fill ();
1764   //cr->stroke();
1765   delete *p;
1766   *p = box;
1767 }
1768 
calculate_width_from_adjusted_height(PixMask * p,double new_height)1769 int ImageCache::calculate_width_from_adjusted_height (PixMask *p, double new_height)
1770 {
1771   return p->get_width () * (new_height / p->get_height ());
1772 }
1773 
generate(SelectorPixMaskCacheItem i)1774 PixMask *SelectorPixMaskCacheItem::generate(SelectorPixMaskCacheItem i)
1775 {
1776   Tileset *ts = Tilesetlist::getInstance()->get(i.tileset);
1777   Player *p = Playerlist::getInstance()->getPlayer(i.player_id);
1778   if (i.type == 0)
1779     return ImageCache::applyMask(ts->getSelectorImage(i.frame),
1780                                  ts->getSelectorMask(i.frame), p);
1781   else
1782     return ImageCache::applyMask(ts->getSmallSelectorImage(i.frame),
1783                                  ts->getSmallSelectorMask(i.frame), p);
1784 }
1785 
comp(const SelectorPixMaskCacheItem item) const1786 int SelectorPixMaskCacheItem::comp(const SelectorPixMaskCacheItem item) const
1787 {
1788   return
1789     (tileset < item.tileset) ? -1 :
1790     (tileset> item.tileset)?  1 :
1791     (type < item.type) ? -1 :
1792     (type > item.type) ?  1 :
1793     (frame < item.frame) ? -1 :
1794     (frame > item.frame) ?  1 :
1795     (player_id < item.player_id) ? -1 :
1796     (player_id > item.player_id) ?  1 :
1797     0;
1798 }
1799 
loadSelectorImages(Glib::ustring filename,guint32 size,std::vector<PixMask * > & images,std::vector<PixMask * > & masks,bool scale)1800 bool SelectorPixMaskCacheItem::loadSelectorImages(Glib::ustring filename, guint32 size, std::vector<PixMask* > &images, std::vector<PixMask* > &masks, bool scale)
1801 {
1802   bool broken = false;
1803   PixMask *p = PixMask::create (filename, broken);
1804   if (!broken)
1805     {
1806       broken = loadSelectors(p, size, images, masks, scale);
1807       delete p;
1808     }
1809   return broken;
1810 }
1811 
loadSelectors(PixMask * p,guint32 size,std::vector<PixMask * > & images,std::vector<PixMask * > & masks,bool scale)1812 bool SelectorPixMaskCacheItem::loadSelectors(PixMask *p, guint32 size, std::vector<PixMask* > &images, std::vector<PixMask* > &masks, bool scale)
1813 {
1814   bool broken = false;
1815   int num_frames;
1816   guint32 width = p->get_unscaled_width ();
1817   num_frames = width / size;
1818   images = disassemble_row(p->to_pixbuf (), num_frames, true);
1819   if (broken)
1820     return false;
1821   if (scale)
1822     {
1823       for (int i = 0; i < num_frames; i++)
1824         {
1825           if (images[i]->get_width() != (int)size)
1826             PixMask::scale(images[i], size, size);
1827         }
1828     }
1829 
1830   masks = disassemble_row(p->to_pixbuf (), num_frames, false);
1831   if (broken)
1832     return false;
1833   if (scale)
1834     {
1835       for (int i = 0; i < num_frames; i++)
1836         {
1837           if (masks[i]->get_width() != (int)size)
1838             PixMask::scale(masks[i], size, size);
1839         }
1840     }
1841 
1842   return true;
1843 }
1844 
generate(FlagPixMaskCacheItem i)1845 PixMask *FlagPixMaskCacheItem::generate(FlagPixMaskCacheItem i)
1846 {
1847   Tileset *ts = Tilesetlist::getInstance()->get(i.tileset);
1848   Player *p = Playerlist::getInstance()->getPlayer(i.player_id);
1849   // size of stack starts at 1, but we need the index, which starts at 0
1850   return ImageCache::applyMask (ts->getFlagImage(i.size-1),
1851                                 ts->getFlagMask(i.size-1), p);
1852 }
1853 
comp(const FlagPixMaskCacheItem item) const1854 int FlagPixMaskCacheItem::comp(const FlagPixMaskCacheItem item) const
1855 {
1856   return
1857     (tileset < item.tileset) ? -1 :
1858     (tileset > item.tileset)?  1 :
1859     (size < item.size) ? -1 :
1860     (size > item.size) ?  1 :
1861     (player_id < item.player_id) ? -1 :
1862     (player_id > item.player_id) ?  1 :
1863     0;
1864 }
1865 
loadFlagImages(Glib::ustring filename,guint32 size,std::vector<PixMask * > & images,std::vector<PixMask * > & masks,bool scale)1866 bool FlagPixMaskCacheItem::loadFlagImages(Glib::ustring filename, guint32 size, std::vector<PixMask* > &images, std::vector<PixMask* > &masks, bool scale)
1867 {
1868   bool broken = false;
1869   PixMask *p = PixMask::create (filename, broken);
1870   if (!broken)
1871     {
1872       broken = loadFlagImages (p, size, images, masks, scale);
1873       delete p;
1874     }
1875   return broken;
1876 }
1877 
loadFlagImages(PixMask * p,guint32 size,std::vector<PixMask * > & images,std::vector<PixMask * > & masks,bool scale)1878 bool FlagPixMaskCacheItem::loadFlagImages(PixMask *p, guint32 size,
1879                                           std::vector<PixMask* > &images,
1880                                           std::vector<PixMask* > &masks,
1881                                           bool scale)
1882 {
1883   images = disassemble_row(p->to_pixbuf (), FLAG_TYPES, true);
1884   if (scale)
1885     {
1886       for (unsigned int i = 0; i < FLAG_TYPES; i++)
1887         {
1888           if (images[i]->get_width() != (int)size)
1889             PixMask::scale(images[i], size, size);
1890         }
1891     }
1892 
1893   masks = disassemble_row(p->to_pixbuf (), FLAG_TYPES, false);
1894   if (scale)
1895     {
1896       for (unsigned int i = 0; i < FLAG_TYPES; i++)
1897         {
1898           if (masks[i]->get_width() !=(int) size)
1899             PixMask::scale(masks[i], size, size);
1900         }
1901     }
1902   return true;
1903 }
1904 
generate(ArmyPixMaskCacheItem i)1905 PixMask *ArmyPixMaskCacheItem::generate(ArmyPixMaskCacheItem i)
1906 {
1907   PixMask *s;
1908   const ArmyProto * basearmy =
1909     Armysetlist::getInstance()->getArmy(i.armyset, i.army_id);
1910 
1911   // copy the pixmap including player colors
1912   Player *p = Playerlist::getInstance()->getPlayer(i.player_id);
1913   Shield::Colour c = Shield::Colour(i.player_id);
1914   if (basearmy->getImage(c) == NULL || basearmy->getMask(c) == NULL)
1915     return NULL;
1916   PixMask *coloured = ImageCache::applyMask(basearmy->getImage(c),
1917                                             basearmy->getMask(c), p);
1918   if (i.greyed)
1919     {
1920       PixMask *greyed_out = ImageCache::greyOut(coloured);
1921       s = greyed_out;
1922       delete coloured;
1923     }
1924   else
1925     s = coloured;
1926 
1927   for(int j = 0; j < 3; j++)
1928     {
1929       if (i.medals[j])
1930         ImageCache::getInstance()->getMedalImage(false, j)->blit(s->get_pixmap());
1931     }
1932   if (i.map == false)
1933     {
1934       int dialogsize = i.font_size * DIALOG_ARMY_PIC_FONTSIZE_MULTIPLE;
1935       PixMask::scale (s, dialogsize, dialogsize);
1936     }
1937   return s;
1938 }
1939 
comp(const ArmyPixMaskCacheItem item) const1940 int ArmyPixMaskCacheItem::comp(const ArmyPixMaskCacheItem item) const
1941 {
1942   return
1943     (armyset < item.armyset) ? -1 :
1944     (armyset > item.armyset)?  1 :
1945     (army_id < item.army_id) ? -1 :
1946     (army_id > item.army_id) ?  1 :
1947     (player_id < item.player_id) ? -1 :
1948     (player_id > item.player_id) ?  1 :
1949     (memcmp(medals,item.medals,sizeof(medals)) < 0) ? -1 :
1950     (memcmp(medals,item.medals,sizeof(medals)) > 0) ? 1 :
1951     (map < item.map) ? -1 :
1952     (map > item.map) ?  1 :
1953     (font_size < item.font_size) ? -1 :
1954     (font_size > item.font_size) ?  1 :
1955     (greyed < item.greyed) ? -1 :
1956     (greyed > item.greyed) ?  1 :
1957     0;
1958 }
1959 
generate(CircledArmyPixMaskCacheItem i)1960 PixMask *CircledArmyPixMaskCacheItem::generate(CircledArmyPixMaskCacheItem i)
1961 {
1962   PixMask *s;
1963   if (i.show_army)
1964     {
1965       Player *p = Playerlist::getInstance()->getPlayer(i.player_id);
1966       PixMask *pre_circle =
1967         ImageCache::getInstance()->getArmyPic(i.armyset, i.army_id, p,
1968                                               i.medals, false, i.font_size,
1969                                               i.greyed);
1970       s = ImageCache::circled(pre_circle, p->getColor(),
1971                               i.circle_colour_id != Shield::NEUTRAL);
1972     }
1973   else
1974     {
1975       guint32 size = Armysetlist::getInstance()->get(i.armyset)->getTileSize();
1976       Glib::RefPtr<Gdk::Pixbuf> pixbuf
1977         = Gdk::Pixbuf::create(Gdk::COLORSPACE_RGB, true, 8, size, size);
1978       pixbuf->fill(0x00000000);
1979       PixMask *empty = PixMask::create(pixbuf);
1980       s = ImageCache::circled
1981         (empty, Shield::get_default_color_for_no(i.circle_colour_id),
1982          i.circle_colour_id != Shield::NEUTRAL);
1983       delete empty;
1984     }
1985   int dialogsize = i.font_size * DIALOG_ARMY_PIC_FONTSIZE_MULTIPLE;
1986   PixMask::scale (s, dialogsize, dialogsize);
1987   return s;
1988 }
1989 
comp(const CircledArmyPixMaskCacheItem item) const1990 int CircledArmyPixMaskCacheItem::comp(const CircledArmyPixMaskCacheItem item) const
1991 {
1992   return
1993     (armyset < item.armyset) ? -1 :
1994     (armyset > item.armyset)?  1 :
1995     (army_id < item.army_id) ? -1 :
1996     (army_id > item.army_id) ?  1 :
1997     (player_id < item.player_id) ? -1 :
1998     (player_id > item.player_id) ?  1 :
1999     (memcmp(medals,item.medals,sizeof(medals)) < 0) ? -1 :
2000     (memcmp(medals,item.medals,sizeof(medals)) > 0) ? 1 :
2001     (greyed < item.greyed) ?  -1 :
2002     (greyed > item.greyed) ?  1 :
2003     (circle_colour_id < item.circle_colour_id) ?  -1 :
2004     (circle_colour_id > item.circle_colour_id) ?  1 :
2005     (show_army < item.show_army) ?  -1 :
2006     (show_army > item.show_army) ?  1 :
2007     (font_size < item.font_size) ?  -1 :
2008     (font_size > item.font_size) ?  1 :
2009     0;
2010 }
2011 
generate(TilePixMaskCacheItem i)2012 PixMask *TilePixMaskCacheItem::generate(TilePixMaskCacheItem i)
2013 {
2014   PixMask *s;
2015   Tileset *t = Tilesetlist::getInstance()->get(i.tileset);
2016   guint32 uts = t->getUnscaledTileSize();
2017   if (i.fog_type_id == FogMap::ALL)
2018     s = t->getFogImage(i.fog_type_id - 1)->copy();
2019   else
2020     {
2021       TileStyle *tilestyle = t->getTileStyle(i.tile_style_id);
2022       s = tilestyle->getImage()->copy();
2023       const Player *player;
2024       Cairo::RefPtr<Cairo::Surface> pixmap = s->get_pixmap();
2025 
2026       switch (i.building_type)
2027         {
2028         case Maptile::CITY:
2029             {
2030               player = Playerlist::getInstance()->getPlayer(i.building_player_id);
2031               ImageCache::getInstance()->getCityPic(i.building_subtype, player, i.cityset)->blit(i.building_tile, uts, pixmap);
2032             }
2033           break;
2034         case Maptile::RUIN:
2035           ImageCache::getInstance()->getRuinPic(i.building_subtype, i.cityset)->blit(i.building_tile, uts, pixmap);
2036           break;
2037         case Maptile::TEMPLE:
2038           ImageCache::getInstance()->getTemplePic(i.building_subtype, i.cityset)->blit(i.building_tile, uts, pixmap);
2039           break;
2040         case Maptile::SIGNPOST:
2041           ImageCache::getInstance()->getSignpostPic(i.cityset)->blit(i.building_tile, uts, pixmap);
2042           break;
2043         case Maptile::ROAD:
2044           ImageCache::getInstance()->getRoadPic(i.building_subtype)->blit(i.building_tile, uts, pixmap);
2045           if (i.stone_type != -1)
2046             {
2047               Tileset *ts = Tilesetlist::getInstance()->get(i.tileset);
2048               PixMask *p = ts->getStoneImage(i.stone_type);
2049               if (p)
2050                 p->blit(i.building_tile, uts, pixmap);
2051             }
2052           break;
2053         case Maptile::STONE:
2054             {
2055               Tileset *ts = Tilesetlist::getInstance()->get(i.tileset);
2056               PixMask *p = ts->getStoneImage(i.stone_type);
2057               if (p)
2058                 p->blit(i.building_tile, uts, pixmap);
2059             }
2060           break;
2061         case Maptile::PORT:
2062           ImageCache::getInstance()->getPortPic(i.cityset)->blit(i.building_tile, uts, pixmap);
2063           break;
2064         case Maptile::BRIDGE:
2065           ImageCache::getInstance()->getBridgePic(i.building_subtype)->blit(i.building_tile, uts, pixmap);
2066           break;
2067         case Maptile::NONE: default:
2068           break;
2069         }
2070 
2071       if (i.has_standard)
2072         {
2073           player = Playerlist::getInstance()->getPlayer(i.standard_player_id) ;
2074           ImageCache::getInstance()->getPlantedStandardPic(player)->blit(pixmap);
2075         }
2076 
2077       if (i.has_bag)
2078         {
2079           PixMask *pic = ImageCache::getInstance()->getBagPic();
2080           Vector<int>bagsize = Vector<int>(pic->get_width(), pic->get_height());
2081           pic->blit(pixmap, Vector<int>(uts,uts)-bagsize);
2082         }
2083 
2084       if (i.stack_player_id > -1)
2085         {
2086           player = Playerlist::getInstance()->getPlayer(i.stack_player_id);
2087           if (i.has_tower)
2088             ImageCache::getInstance()->getTowerPic(player)->blit(pixmap);
2089           else
2090             {
2091               if (i.stack_size > -1)
2092                 ImageCache::getInstance()->getFlagPic(i.stack_size, player)->blit(pixmap);
2093               if (i.has_ship)
2094                 ImageCache::getInstance()->getShipPic(player)->blit(pixmap);
2095               else
2096                 ImageCache::getInstance()->getArmyPic(player->getArmyset(), i.army_type_id, player, NULL, true, 0)->blit(pixmap);
2097             }
2098         }
2099       if (i.has_grid)
2100         {
2101           Cairo::RefPtr<Cairo::Context> context = s->get_gc();
2102           context->set_source_rgba(GRID_BOX_COLOUR.get_red(), GRID_BOX_COLOUR.get_blue(), GRID_BOX_COLOUR.get_green(), GRID_BOX_COLOUR.get_alpha());
2103           context->move_to(0, 0);
2104           context->rel_line_to(uts, 0);
2105           context->rel_line_to(0, uts);
2106           context->rel_line_to(-uts, 0);
2107           context->rel_line_to(0, -uts);
2108           context->set_line_width(1.0);
2109           context->stroke();
2110         }
2111 
2112       if (i.fog_type_id)
2113         t->getFogImage(i.fog_type_id - 1)->blit(pixmap);
2114     }
2115   int ts = t->getTileSize();
2116   if (s->get_width () != ts)
2117     s->scale (s, ts, ts);
2118   return s;
2119 }
2120 
comp(const TilePixMaskCacheItem item) const2121 int TilePixMaskCacheItem::comp(const TilePixMaskCacheItem item) const
2122 {
2123   return
2124     (tile_style_id < item.tile_style_id) ? -1 :
2125     (tile_style_id > item.tile_style_id) ?  1 :
2126     (fog_type_id < item.fog_type_id) ? -1 :
2127     (fog_type_id > item.fog_type_id) ?  1 :
2128     (has_bag < item.has_bag) ? -1 :
2129     (has_bag > item.has_bag) ?  1 :
2130     (has_standard < item.has_standard) ? -1 :
2131     (has_standard > item.has_standard) ?  1 :
2132     (standard_player_id < item.standard_player_id) ?  -1 :
2133     (standard_player_id > item.standard_player_id) ?  1 :
2134     (stack_size < item.stack_size) ?  -1 :
2135     (stack_size > item.stack_size) ?  1 :
2136     (stack_player_id < item.stack_player_id) ?  -1 :
2137     (stack_player_id > item.stack_player_id) ?  1 :
2138     (army_type_id < item.army_type_id) ?  -1 :
2139     (army_type_id > item.army_type_id) ?  1 :
2140     (has_tower < item.has_tower) ? -1 :
2141     (has_tower > item.has_tower) ?  1 :
2142     (has_ship < item.has_ship) ? -1 :
2143     (has_ship > item.has_ship) ?  1 :
2144     (building_type < item.building_type) ?  -1 :
2145     (building_type > item.building_type) ?  1 :
2146     (building_subtype < item.building_subtype) ?  -1 :
2147     (building_subtype > item.building_subtype) ?  1 :
2148     (building_tile < item.building_tile) ?  -1 :
2149     (building_tile > item.building_tile) ?  1 :
2150     (building_player_id < item.building_player_id) ?  -1 :
2151     (building_player_id > item.building_player_id) ?  1 :
2152     (tilesize < item.tilesize) ?  -1 :
2153     (tilesize > item.tilesize) ?  1 :
2154     (has_grid < item.has_grid) ? -1 :
2155     (has_grid > item.has_grid) ?  1 :
2156     (tileset < item.tileset) ? -1 :
2157     (tileset > item.tileset) ?  1 :
2158     (cityset < item.cityset) ? -1 :
2159     (cityset > item.cityset) ?  1 :
2160     (shieldset < item.shieldset) ? -1 :
2161     (shieldset > item.shieldset) ?  1 :
2162     (stone_type < item.stone_type) ? -1 :
2163     (stone_type > item.stone_type) ?  1 :
2164     0;
2165 }
2166 
generate(CityPixMaskCacheItem i)2167 PixMask *CityPixMaskCacheItem::generate(CityPixMaskCacheItem i)
2168 {
2169   Cityset *cs = Citysetlist::getInstance()->get(i.cityset);
2170   Player *p = Playerlist::getInstance()->getPlayer(i.player_id);
2171   if (i.type == -1)
2172     return cs->getRazedCityImage(p->getId())->copy();
2173   else
2174     return cs->getCityImage(p->getId())->copy();
2175 }
2176 
comp(const CityPixMaskCacheItem item) const2177 int CityPixMaskCacheItem::comp(const CityPixMaskCacheItem item) const
2178 {
2179   return
2180     (cityset < item.cityset) ? -1 :
2181     (cityset > item.cityset)?  1 :
2182     (type < item.type) ? -1 :
2183     (type > item.type) ?  1 :
2184     (player_id < item.player_id) ? -1 :
2185     (player_id > item.player_id) ?  1 :
2186     0;
2187 }
2188 
generate(TowerPixMaskCacheItem i)2189 PixMask *TowerPixMaskCacheItem::generate(TowerPixMaskCacheItem i)
2190 {
2191   Cityset *cs = Citysetlist::getInstance()->get(i.cityset);
2192   return cs->getTowerImage(i.player_id)->copy();
2193 }
2194 
comp(const TowerPixMaskCacheItem item) const2195 int TowerPixMaskCacheItem::comp(const TowerPixMaskCacheItem item) const
2196 {
2197   return
2198     (cityset < item.cityset) ? -1 :
2199     (cityset > item.cityset)?  1 :
2200     (player_id < item.player_id) ? -1 :
2201     (player_id > item.player_id) ?  1 :
2202     0;
2203 }
2204 
generate(TemplePixMaskCacheItem i)2205 PixMask *TemplePixMaskCacheItem::generate(TemplePixMaskCacheItem i)
2206 {
2207   Cityset *cs = Citysetlist::getInstance()->get(i.cityset);
2208   return cs->getTempleImage(i.type)->copy();
2209 }
2210 
comp(const TemplePixMaskCacheItem item) const2211 int TemplePixMaskCacheItem::comp(const TemplePixMaskCacheItem item) const
2212 {
2213   return
2214     (cityset < item.cityset) ? -1 :
2215     (cityset > item.cityset)?  1 :
2216     (type < item.type) ? -1 :
2217     (type > item.type) ?  1 :
2218     0;
2219 }
2220 
generate(RuinPixMaskCacheItem i)2221 PixMask *RuinPixMaskCacheItem::generate(RuinPixMaskCacheItem i)
2222 {
2223   Cityset *cs = Citysetlist::getInstance()->get(i.cityset);
2224   return cs->getRuinImage(i.type)->copy();
2225 }
2226 
comp(const RuinPixMaskCacheItem item) const2227 int RuinPixMaskCacheItem::comp(const RuinPixMaskCacheItem item) const
2228 {
2229   return
2230     (cityset < item.cityset) ? -1 :
2231     (cityset > item.cityset)?  1 :
2232     (type < item.type) ? -1 :
2233     (type > item.type) ?  1 :
2234     0;
2235 }
2236 
generate(DiplomacyPixMaskCacheItem i)2237 PixMask *DiplomacyPixMaskCacheItem::generate(DiplomacyPixMaskCacheItem i)
2238 {
2239   PixMask *p =
2240     ImageCache::getInstance()->getDiplomacyImage
2241     (i.type, Player::DiplomaticState(i.state - Player::AT_PEACE))->copy();
2242   double ratio = 1;
2243   switch (i.type)
2244     {
2245     case 0:
2246       ratio = DIALOG_DIPLOMACY_TYPE_0_PIC_FONTSIZE_MULTIPLE;
2247       break;
2248     case 1:
2249       ratio = DIALOG_DIPLOMACY_TYPE_1_PIC_FONTSIZE_MULTIPLE;
2250       break;
2251     }
2252 
2253   double new_height = i.font_size * ratio;
2254   int new_width =
2255     ImageCache::calculate_width_from_adjusted_height (p, new_height);
2256   PixMask::scale (p, new_width, new_height);
2257   return p;
2258 }
2259 
comp(const DiplomacyPixMaskCacheItem item) const2260 int DiplomacyPixMaskCacheItem::comp(const DiplomacyPixMaskCacheItem item) const
2261 {
2262   return
2263     (type < item.type) ? -1 :
2264     (type > item.type) ?  1 :
2265     (state < item.state) ? -1 :
2266     (state > item.state) ? 1 :
2267     (font_size < item.font_size) ? -1 :
2268     (font_size > item.font_size) ? 1 :
2269     0;
2270 }
2271 
generate(RoadPixMaskCacheItem i)2272 PixMask *RoadPixMaskCacheItem::generate(RoadPixMaskCacheItem i)
2273 {
2274   Tileset *ts = Tilesetlist::getInstance()->get(i.tileset);
2275   return ts->getRoadImage(i.type)->copy();
2276 }
2277 
comp(const RoadPixMaskCacheItem item) const2278 int RoadPixMaskCacheItem::comp(const RoadPixMaskCacheItem item) const
2279 {
2280   return
2281     (tileset < item.tileset) ? -1 :
2282     (tileset > item.tileset)?  1 :
2283     (type < item.type) ? -1 :
2284     (type > item.type) ?  1 :
2285     0;
2286 }
2287 
generate(FogPixMaskCacheItem i)2288 PixMask *FogPixMaskCacheItem::generate(FogPixMaskCacheItem i)
2289 {
2290   Tileset *ts = Tilesetlist::getInstance()->get(i.tileset);
2291   return ts->getFogImage(i.type - 1)->copy();
2292 }
2293 
comp(const FogPixMaskCacheItem item) const2294 int FogPixMaskCacheItem::comp(const FogPixMaskCacheItem item) const
2295 {
2296   return
2297     (tileset < item.tileset) ? -1 :
2298     (tileset > item.tileset)?  1 :
2299     (type < item.type) ? -1 :
2300     (type > item.type) ?  1 :
2301     0;
2302 }
2303 
generate(BridgePixMaskCacheItem i)2304 PixMask *BridgePixMaskCacheItem::generate(BridgePixMaskCacheItem i)
2305 {
2306   Tileset *ts = Tilesetlist::getInstance()->get(i.tileset);
2307   return ts->getBridgeImage(i.type)->copy();
2308 }
2309 
comp(const BridgePixMaskCacheItem item) const2310 int BridgePixMaskCacheItem::comp(const BridgePixMaskCacheItem item) const
2311 {
2312   return
2313     (tileset < item.tileset) ? -1 :
2314     (tileset > item.tileset)?  1 :
2315     (type < item.type) ? -1 :
2316     (type > item.type) ?  1 :
2317     0;
2318 }
2319 
generate(CursorPixMaskCacheItem i)2320 PixMask *CursorPixMaskCacheItem::generate(CursorPixMaskCacheItem i)
2321 {
2322   PixMask *p =
2323     ImageCache::getInstance()->getCursorImage(i.type)->copy();
2324   double ratio = DIALOG_CURSOR_PIC_FONTSIZE_MULTIPLE;
2325   double new_height = i.font_size * ratio;
2326   int new_width =
2327     ImageCache::calculate_width_from_adjusted_height (p, new_height);
2328   PixMask::scale (p, new_width, new_height);
2329   return p;
2330 }
2331 
comp(const CursorPixMaskCacheItem item) const2332 int CursorPixMaskCacheItem::comp(const CursorPixMaskCacheItem item) const
2333 {
2334   return
2335     (type < item.type) ? -1 :
2336     (type > item.type) ?  1 :
2337     (font_size < item.font_size) ? -1 :
2338     (font_size > item.font_size) ?  1 :
2339     0;
2340 }
2341 
generate(ShieldPixMaskCacheItem i)2342 PixMask *ShieldPixMaskCacheItem::generate(ShieldPixMaskCacheItem i)
2343 {
2344   ShieldStyle *sh = Shieldsetlist::getInstance()->getShield(i.shieldset,
2345                                                             i.type, i.colour);
2346   Gdk::RGBA colour =
2347     Shieldsetlist::getInstance()->getColor(i.shieldset, i.colour);
2348   PixMask *p = ImageCache::applyMask(sh->getImage(), sh->getMask(), colour);
2349   if (i.map)
2350     return p;
2351   //okay now we size things accordingly.
2352   double height_ratio = 1.0;
2353   switch (i.type)
2354     {
2355     case 0:
2356       height_ratio = DIALOG_SMALL_SHIELD_PIC_FONTSIZE_MULTIPLE;
2357       break;
2358     case 1:
2359       height_ratio = DIALOG_MEDIUM_SHIELD_PIC_FONTSIZE_MULTIPLE;
2360       break;
2361     case 2:
2362       height_ratio = DIALOG_LARGE_SHIELD_PIC_FONTSIZE_MULTIPLE;
2363       break;
2364     }
2365   int new_height = i.font_size * height_ratio;
2366   int new_width =
2367     ImageCache::calculate_width_from_adjusted_height (p, new_height);
2368   PixMask::scale (p, new_width, new_height);
2369   return p;
2370 }
2371 
comp(const ShieldPixMaskCacheItem item) const2372 int ShieldPixMaskCacheItem::comp(const ShieldPixMaskCacheItem item) const
2373 {
2374   return
2375     (shieldset < item.shieldset) ? -1 :
2376     (shieldset > item.shieldset) ?  1 :
2377     (type < item.type) ? -1 :
2378     (type > item.type) ?  1 :
2379     (colour < item.colour) ? -1 :
2380     (colour > item.colour) ?  1 :
2381     (font_size < item.font_size) ? -1 :
2382     (font_size > item.font_size) ?  1 :
2383     0;
2384 }
2385 
generate(ProdShieldPixMaskCacheItem i)2386 PixMask *ProdShieldPixMaskCacheItem::generate(ProdShieldPixMaskCacheItem i)
2387 {
2388   switch (i.type)
2389     {
2390     case 0: //home city
2391       if (i.prod) //production
2392         return ImageCache::getInstance()->getProdShieldImage(1)->copy();
2393       else //no production
2394         return ImageCache::getInstance()->getProdShieldImage(0)->copy();
2395       break;
2396     case 1: //away city
2397       if (i.prod) //production
2398         return ImageCache::getInstance()->getProdShieldImage(3)->copy();
2399       else //no production
2400         return ImageCache::getInstance()->getProdShieldImage(2)->copy();
2401       break;
2402     case 2: //destination city
2403       if (i.prod) //production
2404         return ImageCache::getInstance()->getProdShieldImage(5)->copy();
2405       else //no production
2406         return ImageCache::getInstance()->getProdShieldImage(4)->copy();
2407       break;
2408     case 3: //source city
2409       return ImageCache::getInstance()->getProdShieldImage(6)->copy();
2410       break;
2411     case 4: //invalid
2412       return ImageCache::getInstance()->getProdShieldImage(7)->copy();
2413       break;
2414     }
2415   return NULL;
2416 }
2417 
comp(const ProdShieldPixMaskCacheItem item) const2418 int ProdShieldPixMaskCacheItem::comp(const ProdShieldPixMaskCacheItem item) const
2419 {
2420   return
2421     (type < item.type) ? -1 :
2422     (type > item.type) ?  1 :
2423     (prod < item.prod) ? -1 :
2424     (prod > item.prod) ?  1 :
2425     0;
2426 }
2427 
generate(MoveBonusPixMaskCacheItem i)2428 PixMask *MoveBonusPixMaskCacheItem::generate(MoveBonusPixMaskCacheItem i)
2429 {
2430   PixMask *p = ImageCache::getInstance()->getMoveBonusImage(i.type)->copy();
2431   double ratio = DIALOG_MOVE_BONUS_PIC_FONTSIZE_MULTIPLE;
2432   double new_height = i.font_size * ratio;
2433   int new_width =
2434     ImageCache::calculate_width_from_adjusted_height (p, new_height);
2435   PixMask::scale (p, new_width, new_height);
2436   return p;
2437 }
2438 
comp(const MoveBonusPixMaskCacheItem item) const2439 int MoveBonusPixMaskCacheItem::comp(const MoveBonusPixMaskCacheItem item) const
2440 {
2441   return
2442     (type < item.type) ? -1 :
2443     (type > item.type) ?  1 :
2444     (font_size < item.font_size) ? -1 :
2445     (font_size > item.font_size) ?  1 :
2446     0;
2447 }
2448 
generate(ShipPixMaskCacheItem i)2449 PixMask *ShipPixMaskCacheItem::generate(ShipPixMaskCacheItem i)
2450 {
2451   // copy the pixmap including player colors
2452   return ImageCache::applyMask
2453     (Armysetlist::getInstance()->getShipPic(i.armyset),
2454      Armysetlist::getInstance()->getShipMask(i.armyset),
2455      Playerlist::getInstance()->getPlayer(i.player_id));
2456 }
2457 
comp(const ShipPixMaskCacheItem item) const2458 int ShipPixMaskCacheItem::comp(const ShipPixMaskCacheItem item) const
2459 {
2460   return
2461     (player_id < item.player_id) ? -1 :
2462     (player_id > item.player_id) ?  1 :
2463     (armyset < item.armyset) ? -1 :
2464     (armyset > item.armyset) ?  1 :
2465     0;
2466 }
2467 
generate(PlantedStandardPixMaskCacheItem i)2468 PixMask *PlantedStandardPixMaskCacheItem::generate(PlantedStandardPixMaskCacheItem i)
2469 {
2470   // copy the pixmap including player colors
2471   return ImageCache::applyMask
2472     (Armysetlist::getInstance()->getStandardPic(i.armyset),
2473      Armysetlist::getInstance()->getStandardMask(i.armyset),
2474      Playerlist::getInstance()->getPlayer(i.player_id));
2475 }
2476 
comp(const PlantedStandardPixMaskCacheItem item) const2477 int PlantedStandardPixMaskCacheItem::comp(const PlantedStandardPixMaskCacheItem item) const
2478 {
2479   return
2480     (player_id < item.player_id) ? -1 :
2481     (player_id > item.player_id) ?  1 :
2482     (armyset < item.armyset) ? -1 :
2483     (armyset > item.armyset) ?  1 :
2484     0;
2485 }
2486 
generate(PortPixMaskCacheItem i)2487 PixMask *PortPixMaskCacheItem::generate(PortPixMaskCacheItem i)
2488 {
2489   return Citysetlist::getInstance()->get(i.cityset)->getPortImage()->copy();
2490 }
2491 
comp(const PortPixMaskCacheItem item) const2492 int PortPixMaskCacheItem::comp(const PortPixMaskCacheItem item) const
2493 {
2494   return
2495     (cityset < item.cityset) ? -1 :
2496     (cityset > item.cityset) ?  1 :
2497     0;
2498 }
2499 
generate(SignpostPixMaskCacheItem i)2500 PixMask *SignpostPixMaskCacheItem::generate(SignpostPixMaskCacheItem i)
2501 {
2502   return Citysetlist::getInstance()->get(i.cityset)->getSignpostImage()->copy();
2503 }
2504 
comp(const SignpostPixMaskCacheItem item) const2505 int SignpostPixMaskCacheItem::comp(const SignpostPixMaskCacheItem item) const
2506 {
2507   return
2508     (cityset < item.cityset) ? -1 :
2509     (cityset > item.cityset) ?  1 :
2510     0;
2511 }
2512 
generate(BagPixMaskCacheItem i)2513 PixMask *BagPixMaskCacheItem::generate(BagPixMaskCacheItem i)
2514 {
2515   return Armysetlist::getInstance()->getBagPic(i.armyset)->copy();
2516 }
2517 
comp(const BagPixMaskCacheItem item) const2518 int BagPixMaskCacheItem::comp(const BagPixMaskCacheItem item) const
2519 {
2520   return
2521     (armyset < item.armyset) ? -1 :
2522     (armyset > item.armyset) ?  1 :
2523     0;
2524 }
2525 
generate(ExplosionPixMaskCacheItem i)2526 PixMask *ExplosionPixMaskCacheItem::generate(ExplosionPixMaskCacheItem i)
2527 {
2528   return Tilesetlist::getInstance()->get(i.tileset)->getExplosionImage()->copy();
2529 }
2530 
comp(const ExplosionPixMaskCacheItem item) const2531 int ExplosionPixMaskCacheItem::comp(const ExplosionPixMaskCacheItem item) const
2532 {
2533   return
2534     (tileset < item.tileset) ? -1 :
2535     (tileset > item.tileset) ?  1 :
2536     0;
2537 }
2538 
generate(NewLevelPixMaskCacheItem i)2539 PixMask *NewLevelPixMaskCacheItem::generate(NewLevelPixMaskCacheItem i)
2540 {
2541   bool female = i.gender == Hero::FEMALE;
2542   PixMask *p = ImageCache::applyMask
2543     (ImageCache::getInstance()->getNewLevelImage(female, false),
2544      ImageCache::getInstance()->getNewLevelImage(female, true),
2545      Playerlist::getInstance()->getPlayer(i.player_id));
2546 
2547   double ratio = DIALOG_NEW_LEVEL_PIC_FONTSIZE_MULTIPLE;
2548   double new_height = i.font_size * ratio;
2549   int new_width =
2550     ImageCache::calculate_width_from_adjusted_height (p, new_height);
2551   PixMask::scale (p, new_width, new_height);
2552   return p;
2553 }
2554 
comp(const NewLevelPixMaskCacheItem item) const2555 int NewLevelPixMaskCacheItem::comp(const NewLevelPixMaskCacheItem item) const
2556 {
2557   return
2558     (player_id < item.player_id) ? -1 :
2559     (player_id > item.player_id) ?  1 :
2560     (gender < item.gender) ? -1 :
2561     (gender > item.gender) ?  1 :
2562     (font_size < item.font_size) ? -1 :
2563     (font_size > item.font_size) ?  1 :
2564     0;
2565 }
2566 
generate(DefaultTileStylePixMaskCacheItem i)2567 PixMask *DefaultTileStylePixMaskCacheItem::generate(DefaultTileStylePixMaskCacheItem i)
2568 {
2569   PixMask *t =
2570     ImageCache::getInstance()->getDefaultTileStyleImage(i.tilestyle_type);
2571   PixMask *s = t->copy();
2572   PixMask::scale(s, i.tilesize, i.tilesize);
2573   return s;
2574 }
2575 
comp(const DefaultTileStylePixMaskCacheItem item) const2576 int DefaultTileStylePixMaskCacheItem::comp(const DefaultTileStylePixMaskCacheItem item) const
2577 {
2578   return
2579     (tilestyle_type < item.tilestyle_type) ? -1 :
2580     (tilestyle_type > item.tilestyle_type) ?  1 :
2581     (tilesize < item.tilesize) ? -1 :
2582     (tilesize > item.tilesize) ?  1 :
2583     0;
2584 }
2585 
calculateWidth(guint32 iwidth,PixMask * left,PixMask * center,PixMask * right,guint32 & width,guint32 & centers,bool & include_right)2586 void TartanPixMaskCacheItem::calculateWidth(guint32 iwidth, PixMask *left, PixMask *center, PixMask *right, guint32 &width, guint32 &centers, bool &include_right)
2587 {
2588   //calculate the width, ugh.
2589   for (width = left->get_width(); width < iwidth - right->get_width();
2590        width += center->get_width())
2591     centers++;
2592   width += right->get_width();
2593   include_right = true;
2594   for (guint32 j = 0; j < centers; j++)
2595     {
2596       if (width > iwidth)
2597         {
2598           width -= center->get_width();
2599           if (centers)
2600             centers--;
2601         }
2602       else
2603         break;
2604     }
2605   if (width > iwidth)
2606     {
2607       width -= right->get_width();
2608       include_right = false;
2609     }
2610 }
2611 
generate(TartanPixMaskCacheItem i)2612 PixMask *TartanPixMaskCacheItem::generate(TartanPixMaskCacheItem i)
2613 {
2614   //okay, here's where we fashion the new image.
2615   //we take the leftmost tartan image for this player
2616   //and then we repeat the center tartan image a bunch of times
2617   //and then finally we cap it off with the rightmost tartan image
2618   //the images are all masked in the player's colour.
2619 
2620   Gdk::RGBA colour =
2621     Shieldsetlist::getInstance()->getColor(i.shieldset, i.player_id);
2622   PixMask *image = NULL, *mask = NULL;
2623   Shieldsetlist::getInstance()->getTartan(i.shieldset, i.player_id,
2624                                           Tartan::LEFT, &image, &mask);
2625   PixMask *left = ImageCache::applyMask(image, mask, colour);
2626   double ratio = DIALOG_TARTAN_PIC_FONTSIZE_MULTIPLE;
2627   double new_height = i.font_size * ratio;
2628   int new_width =
2629     ImageCache::calculate_width_from_adjusted_height (left, new_height);
2630   PixMask::scale (left, new_width, new_height);
2631 
2632   image = NULL;
2633   mask = NULL;
2634   Shieldsetlist::getInstance()->getTartan(i.shieldset, i.player_id,
2635                                           Tartan::CENTER, &image, &mask);
2636   PixMask *center = ImageCache::applyMask(image, mask, colour);
2637   new_width =
2638     ImageCache::calculate_width_from_adjusted_height (center, new_height);
2639   PixMask::scale (center, new_width, new_height);
2640   image = NULL;
2641   mask = NULL;
2642   Shieldsetlist::getInstance()->getTartan(i.shieldset, i.player_id,
2643                                           Tartan::RIGHT, &image, &mask);
2644   PixMask *right = ImageCache::applyMask(image, mask, colour);
2645   new_width =
2646     ImageCache::calculate_width_from_adjusted_height (right, new_height);
2647   PixMask::scale (right, new_width, new_height);
2648   //okay, so we have our left, right and center images, now we need to
2649   //concatenate them together
2650 
2651   guint32 w = 0, num_centers = 0;
2652   bool include_right = false;
2653   calculateWidth(i.width, left, center, right, w, num_centers, include_right);
2654   //okay w is the actual width of the image, which is the same or less than
2655   //the width we asked for.  it has NUM_CENTERS center pieces and it may or may
2656   //not have an ending piece (if we can fit it.)
2657   //we always have the leftmost piece though because we have to show something.
2658   Glib::RefPtr<Gdk::Pixbuf> pixbuf
2659     = Gdk::Pixbuf::create(Gdk::COLORSPACE_RGB, true, 8, w, left->get_height());
2660   pixbuf->fill(0x00000000);
2661   PixMask *tartan = PixMask::create(pixbuf);
2662 
2663   //blit the left image
2664   guint32 l = 0;
2665   left->blit (tartan->get_pixmap(), l, 0);
2666   l += left->get_width();
2667 
2668   //blit the center images
2669   for (guint32 j = 0; j < num_centers; j++)
2670     {
2671       center->blit (tartan->get_pixmap(), l, 0);
2672       l += center->get_width();
2673     }
2674 
2675   //blit the right image
2676   if (include_right)
2677     right->blit (tartan->get_pixmap(), l, 0);
2678   delete left;
2679   delete center;
2680   delete right;
2681   return tartan;
2682 }
2683 
comp(const TartanPixMaskCacheItem item) const2684 int TartanPixMaskCacheItem::comp(const TartanPixMaskCacheItem item) const
2685 {
2686   return
2687     (player_id < item.player_id) ? -1 :
2688     (player_id > item.player_id) ?  1 :
2689     (width < item.width) ? -1 :
2690     (width > item.width) ?  1 :
2691     (shieldset < item.shieldset) ? -1 :
2692     (shieldset > item.shieldset) ?  1 :
2693     (font_size < item.font_size) ? -1 :
2694     (font_size > item.font_size) ?  1 :
2695     0;
2696 }
2697 
generate(EmptyTartanPixMaskCacheItem i)2698 PixMask *EmptyTartanPixMaskCacheItem::generate(EmptyTartanPixMaskCacheItem i)
2699 {
2700   //okay, here's where we fashion the new image.
2701   //we take the leftmost tartan image for this player
2702   //and then we repeat the center tartan image a bunch of times
2703   //and then finally we cap it off with the rightmost tartan image
2704   //the images are all masked in the player's colour.
2705 
2706   //the empty tartan pictures are the same as the regular tartan pictures
2707   //except they're not coloured in the player's colour.
2708 
2709   PixMask *image = NULL, *mask = NULL;
2710   Shieldsetlist::getInstance()->getTartan(i.shieldset, i.player_id,
2711                                           Tartan::LEFT, &image, &mask);
2712   PixMask *left = image->copy();
2713   double ratio = DIALOG_TARTAN_PIC_FONTSIZE_MULTIPLE;
2714   double new_height = i.font_size * ratio;
2715   int new_width =
2716     ImageCache::calculate_width_from_adjusted_height (left, new_height);
2717   PixMask::scale (left, new_width, new_height);
2718 
2719   image = NULL;
2720   mask = NULL;
2721   Shieldsetlist::getInstance()->getTartan(i.shieldset, i.player_id,
2722                                           Tartan::CENTER, &image, &mask);
2723   PixMask *center = image->copy();
2724   new_width =
2725     ImageCache::calculate_width_from_adjusted_height (center, new_height);
2726   PixMask::scale (center, new_width, new_height);
2727 
2728   image = NULL;
2729   mask = NULL;
2730   Shieldsetlist::getInstance()->getTartan(i.shieldset, i.player_id,
2731                                           Tartan::RIGHT, &image, &mask);
2732   PixMask *right = image->copy();
2733   new_width =
2734     ImageCache::calculate_width_from_adjusted_height (right, new_height);
2735   PixMask::scale (right, new_width, new_height);
2736 
2737   //okay, so we have our left, right and center images, now we need to
2738   //concatenate them together
2739 
2740   guint32 w = 0, num_centers = 0;
2741   bool include_right = false;
2742   TartanPixMaskCacheItem::calculateWidth(i.width, left, center, right, w, num_centers, include_right);
2743   //okay w is the actual width of the image, which is the same or less than
2744   //the width we asked for.  it has NUM_CENTERS center pieces and it may or may
2745   //not have an ending piece (if we can fit it.)
2746   //we always have the leftmost piece though because we have to show something.
2747   Glib::RefPtr<Gdk::Pixbuf> pixbuf
2748     = Gdk::Pixbuf::create(Gdk::COLORSPACE_RGB, true, 8, w, left->get_height());
2749   pixbuf->fill(0x00000000);
2750   PixMask *tartan = PixMask::create(pixbuf);
2751 
2752   //blit the left image
2753   guint32 l = 0;
2754   left->blit (tartan->get_pixmap(), l, 0);
2755   l += left->get_width();
2756 
2757   //blit the center images
2758   for (guint32 j = 0; j < num_centers; j++)
2759     {
2760       center->blit (tartan->get_pixmap(), l, 0);
2761       l += center->get_width();
2762     }
2763 
2764   //blit the right image
2765   if (include_right)
2766     right->blit (tartan->get_pixmap(), l, 0);
2767   delete left;
2768   delete center;
2769   delete right;
2770   return tartan;
2771 }
2772 
comp(const EmptyTartanPixMaskCacheItem item) const2773 int EmptyTartanPixMaskCacheItem::comp(const EmptyTartanPixMaskCacheItem item) const
2774 {
2775   return
2776     (player_id < item.player_id) ? -1 :
2777     (player_id > item.player_id) ?  1 :
2778     (width < item.width) ? -1 :
2779     (width > item.width) ?  1 :
2780     (shieldset < item.shieldset) ? -1 :
2781     (shieldset > item.shieldset) ?  1 :
2782     (font_size < item.font_size) ? -1 :
2783     (font_size > item.font_size) ?  1 :
2784     0;
2785 }
2786 
generate(StatusPixMaskCacheItem i)2787 PixMask *StatusPixMaskCacheItem::generate(StatusPixMaskCacheItem i)
2788 {
2789   Glib::ustring file = "";
2790   switch (i.type)
2791     {
2792     case ImageCache::STATUS_CITY:
2793       file = File::getVariousFile ("smallcity.png");
2794       break;
2795     case ImageCache::STATUS_TREASURY:
2796       file = File::getVariousFile ("smalltreasury.png");
2797       break;
2798     case ImageCache::STATUS_INCOME:
2799       file = File::getVariousFile ("smallincome.png");
2800       break;
2801     case ImageCache::STATUS_UPKEEP:
2802       file = File::getVariousFile ("smallupkeep.png");
2803       break;
2804     case ImageCache::STATUS_DEFENSE:
2805       file = File::getVariousFile ("smalldefense.png");
2806       break;
2807     }
2808 
2809   bool broken = false;
2810   PixMask *p = PixMask::create (file, broken);
2811   if (!broken)
2812     {
2813       double ratio = DIALOG_STATUS_PIC_FONTSIZE_MULTIPLE;
2814       if (i.type == ImageCache::STATUS_DEFENSE)
2815         ratio = DIALOG_DEFENSE_PIC_FONTSIZE_MULTIPLE;
2816       double new_height = i.font_size * ratio;
2817       int new_width =
2818         ImageCache::calculate_width_from_adjusted_height (p, new_height);
2819       PixMask::scale (p, new_width, new_height);
2820     }
2821   return p;
2822 }
2823 
comp(const StatusPixMaskCacheItem item) const2824 int StatusPixMaskCacheItem::comp(const StatusPixMaskCacheItem item) const
2825 {
2826   return
2827     (type < item.type) ? -1 :
2828     (type > item.type) ?  1 :
2829     (font_size < item.font_size) ? -1 :
2830     (font_size > item.font_size) ?  1 :
2831     0;
2832 }
2833 
generate(GameButtonPixMaskCacheItem i)2834 PixMask *GameButtonPixMaskCacheItem::generate(GameButtonPixMaskCacheItem i)
2835 {
2836   PixMask *p =
2837     ImageCache::getInstance ()->getGameButtonImage (i.type)->copy ();
2838 
2839   if (p)
2840     {
2841       double ratio = DIALOG_GAME_BUTTON_PIC_FONTSIZE_MULTIPLE;
2842       double new_height = i.font_size * ratio;
2843       int new_width =
2844         ImageCache::calculate_width_from_adjusted_height (p, new_height);
2845       PixMask::scale (p, new_width, new_height);
2846     }
2847   return p;
2848 }
2849 
comp(const GameButtonPixMaskCacheItem item) const2850 int GameButtonPixMaskCacheItem::comp(const GameButtonPixMaskCacheItem item) const
2851 {
2852   return
2853     (type < item.type) ? -1 :
2854     (type > item.type) ?  1 :
2855     (font_size < item.font_size) ? -1 :
2856     (font_size > item.font_size) ?  1 :
2857     0;
2858 }
2859 
generate(DialogPixMaskCacheItem i)2860 PixMask *DialogPixMaskCacheItem::generate(DialogPixMaskCacheItem i)
2861 {
2862   PixMask *p = NULL;
2863   double ratio = 1;
2864   switch (i.type)
2865     {
2866     case ImageCache::DIALOG_NEXT_TURN:
2867       p = ImageCache::getInstance ()->getNextTurnPic ()->copy ();
2868       ratio = DIALOG_NEXT_TURN_PIC_FONT_SIZE_MULTIPLE;
2869       break;
2870     case ImageCache::DIALOG_NEW_HERO_MALE:
2871       p = ImageCache::getInstance ()->getHeroPic (Hero::MALE)->copy ();
2872       ratio = DIALOG_NEW_HERO_PIC_FONT_SIZE_MULTIPLE;
2873       break;
2874     case ImageCache::DIALOG_NEW_HERO_FEMALE:
2875       p = ImageCache::getInstance ()->getHeroPic (Hero::FEMALE)->copy ();
2876       ratio = DIALOG_NEW_HERO_PIC_FONT_SIZE_MULTIPLE;
2877       break;
2878     case ImageCache::DIALOG_CONQUERED_CITY:
2879       p = ImageCache::getInstance ()->getCityDefeatedPic ()->copy ();
2880       ratio = DIALOG_CONQUERED_CITY_PIC_FONT_SIZE_MULTIPLE;
2881       break;
2882     case ImageCache::DIALOG_WINNING:
2883       p = ImageCache::getInstance ()->getWinningPic()->copy ();
2884       ratio = DIALOG_WINNING_PIC_FONT_SIZE_MULTIPLE;
2885       break;
2886     case ImageCache::DIALOG_RUIN_SUCCESS:
2887       p = ImageCache::getInstance ()->getRuinSuccessPic()->copy ();
2888       ratio = DIALOG_RUIN_PIC_FONT_SIZE_MULTIPLE;
2889       break;
2890     case ImageCache::DIALOG_RUIN_DEFEAT:
2891       p = ImageCache::getInstance ()->getRuinDefeatPic()->copy ();
2892       ratio = DIALOG_RUIN_PIC_FONT_SIZE_MULTIPLE;
2893       break;
2894     case ImageCache::DIALOG_PARLEY_OFFERED:
2895       p = ImageCache::getInstance ()->getParleyOfferedPic()->copy ();
2896       ratio = DIALOG_PARLEY_PIC_FONT_SIZE_MULTIPLE;
2897       break;
2898     case ImageCache::DIALOG_PARLEY_REFUSED:
2899       p = ImageCache::getInstance ()->getParleyRefusedPic()->copy ();
2900       ratio = DIALOG_PARLEY_PIC_FONT_SIZE_MULTIPLE;
2901       break;
2902     case ImageCache::DIALOG_COMMENTATOR:
2903       p = ImageCache::getInstance ()->getCommentatorPic()->copy ();
2904       ratio = DIALOG_COMMENTATOR_PIC_FONT_SIZE_MULTIPLE;
2905       break;
2906     }
2907   if (p)
2908     {
2909       double new_height = i.font_size * ratio;
2910       int new_width =
2911         ImageCache::calculate_width_from_adjusted_height (p, new_height);
2912       PixMask::scale (p, new_width, new_height);
2913     }
2914   return p;
2915 }
2916 
comp(const DialogPixMaskCacheItem item) const2917 int DialogPixMaskCacheItem::comp(const DialogPixMaskCacheItem item) const
2918 {
2919   return
2920     (type < item.type) ? -1 :
2921     (type > item.type) ?  1 :
2922     (font_size < item.font_size) ? -1 :
2923     (font_size > item.font_size) ?  1 :
2924     0;
2925 }
2926 
2927 
generate(MedalPixMaskCacheItem i)2928 PixMask *MedalPixMaskCacheItem::generate(MedalPixMaskCacheItem i)
2929 {
2930   PixMask *p =
2931     ImageCache::getInstance ()->getMedalImage (i.large, i.type)->copy ();
2932 
2933   if (i.large == false)
2934     return p;
2935 
2936   if (p)
2937     {
2938       double ratio = DIALOG_MEDAL_PIC_FONTSIZE_MULTIPLE;
2939       double new_height = i.font_size * ratio;
2940       int new_width =
2941         ImageCache::calculate_width_from_adjusted_height (p, new_height);
2942       PixMask::scale (p, new_width, new_height);
2943     }
2944   return p;
2945 }
2946 
comp(const MedalPixMaskCacheItem item) const2947 int MedalPixMaskCacheItem::comp(const MedalPixMaskCacheItem item) const
2948 {
2949   return
2950     (large < item.large) ? -1 :
2951     (large > item.large) ?  1 :
2952     (type < item.type) ? -1 :
2953     (type > item.type) ?  1 :
2954     (font_size < item.font_size) ? -1 :
2955     (font_size > item.font_size) ?  1 :
2956     0;
2957 }
2958