00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #define GETTEXT_DOMAIN "wesnoth-lib"
00022
00023 #include "global.hpp"
00024
00025 #include "color_range.hpp"
00026 #include "config.hpp"
00027 #include "filesystem.hpp"
00028 #include "foreach.hpp"
00029 #include "game_config.hpp"
00030 #include "image.hpp"
00031 #include "image_modifications.hpp"
00032 #include "log.hpp"
00033 #include "gettext.hpp"
00034 #include "serialization/string_utils.hpp"
00035
00036 #include "SDL_image.h"
00037
00038 #include <boost/functional/hash.hpp>
00039
00040 #include <list>
00041 #include <set>
00042
00043 static lg::log_domain log_display("display");
00044 #define ERR_DP LOG_STREAM(err, log_display)
00045 #define LOG_DP LOG_STREAM(info, log_display)
00046
00047 static lg::log_domain log_config("config");
00048 #define ERR_CFG LOG_STREAM(err , log_config)
00049
00050 template<typename T>
00051 struct cache_item
00052 {
00053 cache_item(): item(), loaded(false)
00054 {}
00055
00056 cache_item(const T &item): item(item), loaded(true)
00057 {}
00058
00059 T item;
00060 bool loaded;
00061 };
00062
00063 namespace image {
00064
00065 template<typename T>
00066 class cache_type
00067 {
00068 public:
00069 cache_type(): content_()
00070 {}
00071
00072 cache_item<T> &get_element(int index) {
00073 if (static_cast<unsigned>(index) >= content_.size())
00074 content_.resize(index + 1);
00075 return content_[index];
00076 }
00077
00078 void flush() { content_.clear(); }
00079
00080 private:
00081 std::vector<cache_item<T> > content_;
00082 };
00083
00084 template <typename T>
00085 bool locator::in_cache(cache_type<T> &cache) const
00086 {
00087 return index_ < 0 ? false : cache.get_element(index_).loaded;
00088 }
00089
00090 template <typename T>
00091 const T &locator::locate_in_cache(cache_type<T> &cache) const
00092 {
00093 static T dummy;
00094 return index_ < 0 ? dummy : cache.get_element(index_).item;
00095 }
00096
00097 template <typename T>
00098 T &locator::access_in_cache(cache_type<T> &cache) const
00099 {
00100 static T dummy;
00101 return index_ < 0 ? dummy : cache.get_element(index_).item;
00102 }
00103
00104 template <typename T>
00105 void locator::add_to_cache(cache_type<T> &cache, const T &data) const
00106 {
00107 if (index_ >= 0)
00108 cache.get_element(index_) = cache_item<T>(data);
00109 }
00110
00111 }
00112
00113 namespace {
00114
00115 image::locator::locator_finder_t locator_finder;
00116
00117
00118 image::image_cache images_,
00119 scaled_to_zoom_,
00120 hexed_images_,
00121 scaled_to_hex_images_,
00122 tod_colored_images_,
00123 brightened_images_;
00124
00125
00126 image::bool_cache in_hex_info_;
00127
00128
00129 image::bool_cache is_empty_hex_;
00130
00131
00132 image::lit_cache lit_images_,
00133 lit_scaled_images_;
00134
00135 image::lit_variants lightmaps_;
00136
00137
00138
00139 std::map<std::string,bool> image_existence_map;
00140
00141
00142 std::set<std::string> precached_dirs;
00143
00144 std::map<surface, surface> reversed_images_;
00145
00146 int red_adjust = 0, green_adjust = 0, blue_adjust = 0;
00147
00148
00149 std::vector<std::string> team_colors;
00150
00151 int zoom = image::tile_size;
00152 int cached_zoom = 0;
00153
00154 }
00155
00156 namespace image {
00157
00158 std::list<int> dummy_list;
00159
00160 mini_terrain_cache_map mini_terrain_cache;
00161 mini_terrain_cache_map mini_fogged_terrain_cache;
00162
00163 static int last_index_ = 0;
00164
00165 void flush_cache()
00166 {
00167 #ifdef _OPENMP
00168 #pragma omp critical(image_cache)
00169 #endif //_OPENMP
00170 {
00171 images_.flush();
00172 hexed_images_.flush();
00173 tod_colored_images_.flush();
00174 scaled_to_zoom_.flush();
00175 scaled_to_hex_images_.flush();
00176 brightened_images_.flush();
00177 lit_images_.flush();
00178 lit_scaled_images_.flush();
00179 in_hex_info_.flush();
00180 is_empty_hex_.flush();
00181 mini_terrain_cache.clear();
00182 mini_fogged_terrain_cache.clear();
00183 reversed_images_.clear();
00184 image_existence_map.clear();
00185 precached_dirs.clear();
00186 }
00187
00188
00189
00190
00191 }
00192
00193 void locator::init_index()
00194 {
00195 std::map<value, int>& finder = locator_finder[hash_value(val_)];
00196 std::map<value, int>::iterator i = finder.find(val_);
00197
00198 if(i == finder.end()) {
00199 index_ = last_index_++;
00200 finder.insert(std::make_pair(val_, index_));
00201 } else {
00202 index_ = i->second;
00203 }
00204 }
00205
00206 void locator::parse_arguments()
00207 {
00208 std::string& fn = val_.filename_;
00209 if(fn.empty()) {
00210 return;
00211 }
00212 size_t markup_field = fn.find('~');
00213
00214 if(markup_field != std::string::npos) {
00215 val_.type_ = SUB_FILE;
00216 val_.modifications_ = fn.substr(markup_field, fn.size() - markup_field);
00217 fn = fn.substr(0,markup_field);
00218 }
00219 }
00220
00221 locator::locator() :
00222 index_(-1),
00223 val_()
00224 {
00225 }
00226
00227 locator::locator(const locator &a, const std::string& mods):
00228 index_(-1),
00229 val_(a.val_)
00230 {
00231 if(!mods.empty()){
00232 val_.modifications_ += mods;
00233 val_.type_=SUB_FILE;
00234 init_index();
00235 }
00236 else index_=a.index_;
00237 }
00238
00239 locator::locator(const char *filename) :
00240 index_(-1),
00241 val_(filename)
00242 {
00243 parse_arguments();
00244 init_index();
00245 }
00246
00247 locator::locator(const std::string &filename) :
00248 index_(-1),
00249 val_(filename)
00250 {
00251 parse_arguments();
00252 init_index();
00253 }
00254
00255 locator::locator(const std::string &filename, const std::string& modifications) :
00256 index_(-1),
00257 val_(filename, modifications)
00258 {
00259 init_index();
00260 }
00261
00262 locator::locator(const std::string &filename, const map_location &loc,
00263 int center_x, int center_y, const std::string& modifications) :
00264 index_(-1),
00265 val_(filename, loc, center_x, center_y, modifications)
00266 {
00267 init_index();
00268 }
00269
00270 locator& locator::operator=(const locator &a)
00271 {
00272 index_ = a.index_;
00273 val_ = a.val_;
00274
00275 return *this;
00276 }
00277
00278 locator::value::value(const locator::value& a) :
00279 type_(a.type_), filename_(a.filename_), loc_(a.loc_),
00280 modifications_(a.modifications_),
00281 center_x_(a.center_x_), center_y_(a.center_y_)
00282 {}
00283
00284 locator::value::value() :
00285 type_(NONE), filename_(), loc_(),
00286 modifications_(),
00287 center_x_(0), center_y_(0)
00288 {}
00289
00290 locator::value::value(const char *filename) :
00291 type_(FILE), filename_(filename), loc_(),
00292 modifications_(),
00293 center_x_(0), center_y_(0)
00294 {}
00295
00296 locator::value::value(const std::string& filename) :
00297 type_(FILE), filename_(filename), loc_(),
00298 modifications_(),
00299 center_x_(0), center_y_(0)
00300 {}
00301
00302 locator::value::value(const std::string& filename, const std::string& modifications) :
00303 type_(SUB_FILE), filename_(filename), loc_(), modifications_(modifications),
00304 center_x_(0), center_y_(0)
00305 {}
00306
00307 locator::value::value(const std::string& filename, const map_location& loc, int center_x, int center_y, const std::string& modifications) :
00308 type_(SUB_FILE), filename_(filename), loc_(loc), modifications_(modifications),
00309 center_x_(center_x), center_y_(center_y)
00310 {}
00311
00312 bool locator::value::operator==(const value& a) const
00313 {
00314 if(a.type_ != type_) {
00315 return false;
00316 } else if(type_ == FILE) {
00317 return filename_ == a.filename_;
00318 } else if(type_ == SUB_FILE) {
00319 return filename_ == a.filename_ && loc_ == a.loc_
00320 && modifications_ == a.modifications_
00321 && center_x_ == a.center_x_ && center_y_ == a.center_y_;
00322 } else {
00323 return false;
00324 }
00325 }
00326
00327 bool locator::value::operator<(const value& a) const
00328 {
00329 if(type_ != a.type_) {
00330 return type_ < a.type_;
00331 } else if(type_ == FILE) {
00332 return filename_ < a.filename_;
00333 } else if(type_ == SUB_FILE) {
00334 if(filename_ != a.filename_)
00335 return filename_ < a.filename_;
00336 if(loc_ != a.loc_)
00337 return loc_ < a.loc_;
00338 if(center_x_ != a.center_x_)
00339 return center_x_ < a.center_x_;
00340 if(center_y_ != a.center_y_)
00341 return center_y_ < a.center_y_;
00342 return (modifications_ < a.modifications_);
00343 } else {
00344 return false;
00345 }
00346 }
00347
00348 size_t hash_value(const locator::value& val) {
00349 using boost::hash_value;
00350 using boost::hash_combine;
00351
00352 size_t hash = hash_value(val.type_);
00353 if (val.type_ == locator::FILE || val.type_ == locator::SUB_FILE) {
00354 hash_combine(hash, val.filename_);
00355 }
00356 if (val.type_ == locator::SUB_FILE) {
00357 hash_combine(hash, val.loc_.x);
00358 hash_combine(hash, val.loc_.y);
00359 hash_combine(hash, val.center_x_);
00360 hash_combine(hash, val.center_y_);
00361 hash_combine(hash, val.modifications_);
00362 }
00363
00364 return hash;
00365 }
00366
00367
00368
00369
00370 static std::set<std::string> fuzzy_localized_files;
00371 static bool localized_file_uptodate (const std::string& loc_file)
00372 {
00373 if (fuzzy_localized_files.empty()) {
00374
00375 std::string fsep = "\xC2\xA6";
00376 std::string trackpath = get_binary_file_location("", "l10n-track");
00377 std::string contents = read_file(trackpath);
00378 std::vector<std::string> lines = utils::split(contents, '\n');
00379 foreach (const std::string &line, lines) {
00380 size_t p1 = line.find(fsep);
00381 if (p1 == std::string::npos)
00382 continue;
00383 std::string state = line.substr(0, p1);
00384 utils::strip(state);
00385 if (state == "fuzzy") {
00386 size_t p2 = line.find(fsep, p1 + fsep.length());
00387 if (p2 == std::string::npos)
00388 continue;
00389 std::string relpath = line.substr(p1 + fsep.length(), p2 - p1 - fsep.length());
00390 fuzzy_localized_files.insert(game_config::path + '/' + relpath);
00391 }
00392 }
00393 fuzzy_localized_files.insert("");
00394 }
00395 return fuzzy_localized_files.count(loc_file) == 0;
00396 }
00397
00398
00399
00400 static std::string get_localized_path (const std::string& file, const std::string& suff = "")
00401 {
00402 std::string dir = directory_name(file);
00403 std::string base = file_name(file);
00404 const size_t pos_ext = base.rfind(".");
00405 std::string loc_base;
00406 if (pos_ext != std::string::npos) {
00407 loc_base = base.substr(0, pos_ext) + suff + base.substr(pos_ext);
00408 } else {
00409 loc_base = base + suff;
00410 }
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421 std::vector<std::string> langs = utils::split(_("language code for localized resources^en_US"));
00422
00423
00424
00425 langs.push_back("en_US");
00426 foreach (const std::string &lang, langs) {
00427 std::string loc_file = dir + "l10n" + "/" + lang + "/" + loc_base;
00428 if (file_exists(loc_file) && localized_file_uptodate(loc_file)) {
00429 return loc_file;
00430 }
00431 }
00432 return "";
00433 }
00434
00435
00436 static void add_localized_overlay (const std::string& ovr_file, surface &orig_surf)
00437 {
00438 surface ovr_surf = IMG_Load(ovr_file.c_str());
00439 if (ovr_surf.null()) {
00440 return;
00441 }
00442 SDL_Rect area;
00443 area.x = 0;
00444 area.y = 0;
00445 area.w = ovr_surf->w;
00446 area.h = ovr_surf->h;
00447 sdl_blit(ovr_surf, 0, orig_surf, &area);
00448 }
00449
00450 surface locator::load_image_file() const
00451 {
00452 surface res;
00453
00454 std::string location = get_binary_file_location("images", val_.filename_);
00455
00456
00457 {
00458 if (!location.empty()) {
00459
00460 const std::string loc_location = get_localized_path(location);
00461 if (!loc_location.empty()) {
00462 location = loc_location;
00463 }
00464 res = IMG_Load(location.c_str());
00465
00466 if (!res.null() && loc_location.empty()) {
00467 const std::string ovr_location = get_localized_path(location, "--overlay");
00468 if (!ovr_location.empty()) {
00469 add_localized_overlay(ovr_location, res);
00470 }
00471 }
00472 }
00473 }
00474
00475 if (res.null() && !val_.filename_.empty()) {
00476 ERR_DP << "could not open image '" << val_.filename_ << "'\n";
00477 if (game_config::debug && val_.filename_ != game_config::images::missing)
00478 return get_image(game_config::images::missing, UNSCALED);
00479 }
00480
00481 return res;
00482 }
00483
00484
00485 static signed char col_to_uchar(int i) {
00486 return static_cast<signed char>(std::min<int>(127, std::max<int>(-128, i/2)));
00487 }
00488
00489 light_string get_light_string(int op, int r, int g, int b){
00490 light_string ls;
00491 ls.reserve(4);
00492 ls.push_back(op);
00493 ls.push_back(col_to_uchar(r));
00494 ls.push_back(col_to_uchar(g));
00495 ls.push_back(col_to_uchar(b));
00496 return ls;
00497 }
00498
00499 static surface apply_light(surface surf, const light_string& ls){
00500
00501 if(ls.size() == 4){
00502
00503
00504 int m = ls[0] == -1 ? 2 : 1;
00505 return adjust_surface_color(surf, ls[1]*m, ls[2]*m, ls[3]*m);
00506 }
00507
00508
00509 surface lightmap = NULL;
00510 lit_variants::iterator i = lightmaps_.find(ls);
00511 if(i != lightmaps_.end()) {
00512 lightmap = i->second;
00513 } else {
00514
00515 static const std::string p = "terrain/light";
00516 static const std::string lm_img[7] = {
00517 p+"-n.png", p+"-ne.png", p+"-se.png",
00518 p+"-s.png", p+"-sw.png", p+"-nw.png",
00519 p+".png"
00520 };
00521
00522
00523 for(size_t c = 0; c+3 < ls.size(); c+=4){
00524 light_string sls = ls.substr(c,4);
00525
00526
00527
00528 surface lts = image::get_lighted_image(lm_img[sls[0]], sls, HEXED);
00529
00530 if(lightmap == NULL) {
00531
00532 lightmap = make_neutral_surface(lts);
00533 } else{
00534 blit_surface(lts, NULL, lightmap, NULL);
00535 }
00536 }
00537
00538 lightmaps_[ls] = lightmap;
00539 }
00540
00541 return light_surface(surf, lightmap);
00542 }
00543
00544 surface locator::load_image_sub_file() const
00545 {
00546 surface surf = get_image(val_.filename_, UNSCALED);
00547 if(surf == NULL)
00548 return NULL;
00549
00550 modification_queue mods = modification::decode(val_.modifications_);
00551
00552 while(!mods.empty()) {
00553 modification* mod = mods.top();
00554 mods.pop();
00555
00556 try {
00557 surf = (*mod)(surf);
00558 } catch(const image::modification::texception& e) {
00559 ERR_CFG << "Failed to apply a modification to an image:\n"
00560 << "Image: " << val_.filename_ << ".\n"
00561 << "Modifications: " << val_.modifications_ << ".\n"
00562 << "Error: " << e.message;
00563 }
00564 delete mod;
00565 }
00566
00567 if(val_.loc_.valid()) {
00568 SDL_Rect srcrect = create_rect(
00569 ((tile_size*3) / 4) * val_.loc_.x
00570 , tile_size * val_.loc_.y + (tile_size / 2) * (val_.loc_.x % 2)
00571 , tile_size
00572 , tile_size);
00573
00574 if(val_.center_x_ >= 0 && val_.center_y_>= 0){
00575 srcrect.x += surf->w/2 - val_.center_x_;
00576 srcrect.y += surf->h/2 - val_.center_y_;
00577 }
00578
00579
00580 surface cut(cut_surface(surf, srcrect));
00581 bool is_empty = false;
00582 surf = mask_surface(cut, get_hexmask(), &is_empty);
00583
00584 if(is_empty) {
00585
00586
00587
00588 surf = NULL;
00589 }
00590 add_to_cache(is_empty_hex_, is_empty);
00591 }
00592
00593 return surf;
00594 }
00595
00596 bool locator::file_exists() const
00597 {
00598 return !get_binary_file_location("images", val_.filename_).empty();
00599 }
00600
00601 surface locator::load_from_disk() const
00602 {
00603 switch(val_.type_) {
00604 case FILE:
00605 return load_image_file();
00606 case SUB_FILE:
00607 return load_image_sub_file();
00608 default:
00609 return surface(NULL);
00610 }
00611 }
00612
00613
00614 manager::manager() {}
00615
00616 manager::~manager()
00617 {
00618 flush_cache();
00619 }
00620
00621 SDL_PixelFormat last_pixel_format;
00622
00623 void set_pixel_format(SDL_PixelFormat* format)
00624 {
00625 assert(format != NULL);
00626
00627 SDL_PixelFormat &f = *format;
00628 SDL_PixelFormat &l = last_pixel_format;
00629
00630
00631
00632 if (format->BitsPerPixel == 8 ||
00633 f.BitsPerPixel != l.BitsPerPixel || f.BytesPerPixel != l.BytesPerPixel ||
00634 f.Rmask != l.Rmask || f.Gmask != l.Gmask || f.Bmask != l.Bmask ||
00635 f.Rloss != l.Rloss || f.Gloss != l.Gloss || f.Bloss != l.Bloss ||
00636 f.Rshift != l.Rshift || f.Gshift != l.Gshift || f.Bshift != l.Bshift ||
00637 f.colorkey != l.colorkey || f.alpha != l.alpha)
00638 {
00639 LOG_DP << "detected a new display format\n";
00640 flush_cache();
00641 }
00642 last_pixel_format = *format;
00643 }
00644
00645 void set_color_adjustment(int r, int g, int b)
00646 {
00647 if(r != red_adjust || g != green_adjust || b != blue_adjust) {
00648 red_adjust = r;
00649 green_adjust = g;
00650 blue_adjust = b;
00651 tod_colored_images_.flush();
00652 brightened_images_.flush();
00653 lit_images_.flush();
00654 lit_scaled_images_.flush();
00655 reversed_images_.clear();
00656 }
00657 }
00658
00659 color_adjustment_resetter::color_adjustment_resetter()
00660 : r_(red_adjust), g_(green_adjust), b_(blue_adjust)
00661 {
00662 }
00663
00664 void color_adjustment_resetter::reset()
00665 {
00666 set_color_adjustment(r_, g_, b_);
00667 }
00668
00669 void set_team_colors(const std::vector<std::string>* colors)
00670 {
00671 if (colors == NULL)
00672 team_colors.clear();
00673 else {
00674 team_colors = *colors;
00675 }
00676 }
00677
00678 const std::vector<std::string>& get_team_colors()
00679 {
00680 return team_colors;
00681 }
00682
00683 void set_zoom(int amount)
00684 {
00685 if(amount != zoom) {
00686 zoom = amount;
00687 tod_colored_images_.flush();
00688 brightened_images_.flush();
00689 reversed_images_.clear();
00690
00691
00692
00693
00694 if (zoom != tile_size && zoom != cached_zoom) {
00695 scaled_to_zoom_.flush();
00696 scaled_to_hex_images_.flush();
00697 lit_scaled_images_.flush();
00698 cached_zoom = zoom;
00699 }
00700 }
00701 }
00702
00703 static surface get_hexed(const locator& i_locator)
00704 {
00705 surface image(get_image(i_locator, UNSCALED));
00706
00707 bool is_empty = false;
00708 surface res = mask_surface(image, get_hexmask(), &is_empty, i_locator.get_filename());
00709 i_locator.add_to_cache(is_empty_hex_, is_empty);
00710 return res;
00711 }
00712
00713 static surface get_scaled_to_hex(const locator& i_locator)
00714 {
00715 surface img = get_image(i_locator, HEXED);
00716 return scale_surface(img, zoom, zoom);
00717 }
00718
00719 static surface get_tod_colored(const locator& i_locator)
00720 {
00721 surface img = get_image(i_locator, SCALED_TO_HEX);
00722 return adjust_surface_color(img, red_adjust, green_adjust, blue_adjust);
00723 }
00724
00725 static surface get_scaled_to_zoom(const locator& i_locator)
00726 {
00727 assert(zoom != tile_size);
00728 assert(tile_size != 0);
00729
00730 surface res(get_image(i_locator, UNSCALED));
00731
00732 if(!res.null()) {
00733 return scale_surface(res, ((res.get()->w * zoom) / tile_size), ((res.get()->h * zoom) / tile_size));
00734 } else {
00735 return surface(NULL);
00736 }
00737 }
00738
00739 static surface get_brightened(const locator& i_locator)
00740 {
00741 surface image(get_image(i_locator, TOD_COLORED));
00742 return surface(brighten_image(image, ftofxp(game_config::hex_brightening)));
00743 }
00744
00745
00746 static TYPE simplify_type(const image::locator& i_locator, TYPE type){
00747 switch(type) {
00748 case SCALED_TO_ZOOM:
00749 if(zoom == tile_size)
00750 type = UNSCALED;
00751 break;
00752 case BRIGHTENED:
00753 if(ftofxp(game_config::hex_brightening) == ftofxp(1.0))
00754 type = TOD_COLORED;
00755 break;
00756 default:
00757 break;
00758 }
00759
00760 if(type == TOD_COLORED) {
00761 if (red_adjust==0 && green_adjust==0 && blue_adjust==0)
00762 type = SCALED_TO_HEX;
00763 }
00764
00765 if(type == SCALED_TO_HEX) {
00766 if(zoom == tile_size)
00767 type = HEXED;
00768 }
00769
00770 if(type == HEXED) {
00771
00772 if(i_locator.get_loc().valid())
00773 type = UNSCALED;
00774 }
00775
00776 return type;
00777 }
00778
00779
00780 surface get_image(const image::locator& i_locator, TYPE type)
00781 {
00782 surface res;
00783
00784 if(i_locator.is_void())
00785 return res;
00786
00787 type = simplify_type(i_locator, type);
00788
00789 image_cache *imap;
00790
00791 switch(type) {
00792 case UNSCALED:
00793 imap = &images_;
00794 break;
00795 case TOD_COLORED:
00796 imap = &tod_colored_images_;
00797 break;
00798 case SCALED_TO_ZOOM:
00799 imap = &scaled_to_zoom_;
00800 break;
00801 case HEXED:
00802 imap = &hexed_images_;
00803 break;
00804 case SCALED_TO_HEX:
00805 imap = &scaled_to_hex_images_;
00806 break;
00807 case BRIGHTENED:
00808 imap = &brightened_images_;
00809 break;
00810 default:
00811 return res;
00812 }
00813
00814
00815 bool tmp;
00816 #ifdef _OPENMP
00817 #pragma omp critical(image_cache)
00818 #endif //_OPENMP
00819 tmp=i_locator.in_cache(*imap);
00820
00821 if(tmp) {
00822 surface result;
00823 #ifdef _OPENMP
00824 #pragma omp critical(image_cache)
00825 #endif //_OPENMP
00826 result = i_locator.locate_in_cache(*imap);
00827 return result;
00828 }
00829
00830
00831 switch(type) {
00832 case UNSCALED:
00833
00834 res = i_locator.load_from_disk();
00835 break;
00836 case TOD_COLORED:
00837 res = get_tod_colored(i_locator);
00838 break;
00839 case SCALED_TO_ZOOM:
00840 res = get_scaled_to_zoom(i_locator);
00841 break;
00842 case HEXED:
00843 res = get_hexed(i_locator);
00844 break;
00845 case SCALED_TO_HEX:
00846 res = get_scaled_to_hex(i_locator);
00847 break;
00848 case BRIGHTENED:
00849 res = get_brightened(i_locator);
00850 break;
00851 default:
00852 return res;
00853 }
00854
00855
00856 if(res)
00857 res = create_optimized_surface(res);
00858
00859 #ifdef _OPENMP
00860 #pragma omp critical(image_cache)
00861 #endif //_OPENMP
00862 i_locator.add_to_cache(*imap, res);
00863
00864 return res;
00865 }
00866
00867 surface get_lighted_image(const image::locator& i_locator, const light_string& ls, TYPE type)
00868 {
00869 surface res;
00870 if(i_locator.is_void())
00871 return res;
00872
00873 if(type == SCALED_TO_HEX && zoom == tile_size){
00874 type = HEXED;
00875 }
00876
00877
00878 lit_cache* imap = &lit_images_;
00879 if(type == SCALED_TO_HEX)
00880 imap = &lit_scaled_images_;
00881
00882
00883 if(!i_locator.in_cache(*imap)){
00884 i_locator.add_to_cache(*imap, lit_variants());
00885 }
00886
00887
00888 {
00889 const lit_variants& lvar = i_locator.locate_in_cache(*imap);
00890 lit_variants::const_iterator lvi = lvar.find(ls);
00891 if(lvi != lvar.end()) {
00892 return lvi->second;
00893 }
00894 }
00895
00896
00897 switch(type) {
00898 case HEXED:
00899 res = get_image(i_locator, HEXED);
00900 res = apply_light(res, ls);
00901 break;
00902 case SCALED_TO_HEX:
00903
00904 res = get_lighted_image(i_locator, ls, HEXED);
00905 res = scale_surface(res, zoom, zoom);;
00906 break;
00907 default:
00908 ;
00909 }
00910
00911
00912 res = create_optimized_surface(res);
00913
00914 i_locator.access_in_cache(*imap)[ls] = res;
00915
00916 return res;
00917 }
00918
00919
00920 surface get_hexmask()
00921 {
00922 static const image::locator terrain_mask(game_config::images::terrain_mask);
00923 return get_image(terrain_mask, UNSCALED);
00924 }
00925
00926 bool is_in_hex(const locator& i_locator)
00927 {
00928 bool result;
00929 #ifdef _OPENMP
00930 #pragma omp critical(in_hex_info_)
00931 #endif //_OPENMP
00932 {
00933 if(i_locator.in_cache(in_hex_info_)) {
00934 result= i_locator.locate_in_cache(in_hex_info_);
00935 } else {
00936 const surface image(get_image(i_locator, UNSCALED));
00937
00938 bool res = in_mask_surface(image, get_hexmask());
00939
00940 i_locator.add_to_cache(in_hex_info_, res);
00941
00942
00943
00944
00945 result= res;
00946 }
00947 }
00948 return result;
00949 }
00950
00951 bool is_empty_hex(const locator& i_locator)
00952 {
00953 if(!i_locator.in_cache(is_empty_hex_)) {
00954 const surface surf = get_image(i_locator, HEXED);
00955
00956
00957 if(!i_locator.in_cache(is_empty_hex_)) {
00958
00959
00960
00961 bool is_empty = false;
00962 mask_surface(surf, get_hexmask(), &is_empty);
00963 i_locator.add_to_cache(is_empty_hex_, is_empty);
00964 }
00965 }
00966 return i_locator.locate_in_cache(is_empty_hex_);
00967 }
00968
00969
00970 surface reverse_image(const surface& surf)
00971 {
00972 if(surf == NULL) {
00973 return surface(NULL);
00974 }
00975
00976 const std::map<surface,surface>::iterator itor = reversed_images_.find(surf);
00977 if(itor != reversed_images_.end()) {
00978
00979 return itor->second;
00980 }
00981
00982 const surface rev(flip_surface(surf));
00983 if(rev == NULL) {
00984 return surface(NULL);
00985 }
00986
00987 reversed_images_.insert(std::pair<surface,surface>(surf,rev));
00988
00989 return rev;
00990 }
00991
00992 bool exists(const image::locator& i_locator)
00993 {
00994 typedef image::locator loc;
00995 loc::type type = i_locator.get_type();
00996 if (type != loc::FILE && type != loc::SUB_FILE)
00997 return false;
00998
00999
01000 std::pair< std::map< std::string, bool >::iterator, bool >
01001 it = image_existence_map.insert(std::make_pair(i_locator.get_filename(), false));
01002 bool &cache = it.first->second;
01003 if (it.second)
01004 cache = !get_binary_file_location("images", i_locator.get_filename()).empty();
01005 return cache;
01006 }
01007
01008 static void precache_file_existence_internal(const std::string& dir, const std::string& subdir)
01009 {
01010 const std::string checked_dir = dir + "/" + subdir;
01011 if (precached_dirs.find(checked_dir) != precached_dirs.end())
01012 return;
01013 precached_dirs.insert(checked_dir);
01014
01015 std::vector<std::string> files_found;
01016 std::vector<std::string> dirs_found;
01017 get_files_in_dir(checked_dir, &files_found, &dirs_found,
01018 FILE_NAME_ONLY, NO_FILTER, DONT_REORDER);
01019
01020 for(std::vector<std::string>::const_iterator f = files_found.begin();
01021 f != files_found.end(); ++f) {
01022 image_existence_map[subdir + *f] = true;
01023 }
01024
01025 for(std::vector<std::string>::const_iterator d = dirs_found.begin();
01026 d != dirs_found.end(); ++d) {
01027 precache_file_existence_internal(dir, subdir + *d + "/");
01028 }
01029 }
01030
01031 void precache_file_existence(const std::string& subdir)
01032 {
01033 const std::vector<std::string>& paths = get_binary_paths("images");
01034
01035 for(std::vector<std::string>::const_iterator p = paths.begin();
01036 p != paths.end(); ++p) {
01037
01038 precache_file_existence_internal(*p, subdir);
01039 }
01040 }
01041
01042 bool precached_file_exists(const std::string& file)
01043 {
01044 std::map<std::string, bool>::const_iterator b = image_existence_map.find(file);
01045 if (b != image_existence_map.end())
01046 return b->second;
01047 else
01048 return false;
01049 }
01050
01051 }
01052