surface blit_function::operator()(const surface& src) const { //blit_surface want neutral surfaces surface nsrc = make_neutral_surface(src); surface nsurf = make_neutral_surface(surf_); SDL_Rect r = create_rect(x_, y_, 0, 0); sdl_blit(nsurf, NULL, nsrc, &r); return nsrc; }
int main(int argc, char* argv[]) { try { const toptions& options = toptions::parse(argc, argv); surface surf(make_neutral_surface( IMG_Load(options.input_filename.c_str()))); if(!surf) { std::cerr << "Error: Failed to load input file »" << options.input_filename << "«.\n"; return EXIT_FAILURE; } std::vector<surface> surfaces; if(options.count != 1) { for(int i = 1; i < options.count; ++i) { // make_neutral_surface make a deep-copy of the image. surfaces.push_back(make_neutral_surface(surf)); } } surfaces.push_back(surf); const clock_t begin = options.time ? get_begin_time() : 0; for(int i = 0; i < options.count; ++i) { BOOST_FOREACH(const std::string& filter, options.filters) { filter_apply(surfaces[i], filter); } } if(options.time) { const clock_t end = std::clock(); std::cout << "Applying the filters took " << end - begin << " ticks, " << static_cast<double>(end - begin) / CLOCKS_PER_SEC << " seconds.\n"; } if(!options.output_filename.empty()) { save_image(surfaces[0], options.output_filename); } } catch(const texit& exit) { return exit.status; } catch(exploder_failure& err) { std::cerr << "Error: Failed with error »" << err.message << "«.\n"; return EXIT_FAILURE; } return EXIT_SUCCESS; }
surface crop_modification::operator()(const surface& src) const { SDL_Rect area = slice_; if(area.w == 0) { area.w = src->w; } if(area.h == 0) { area.h = src->h; } if(area.x < 0) { ERR_DP << "start X coordinate of CROP modification is negative - truncating to zero\n"; area.x = 0; } if(area.y < 0) { ERR_DP << "start Y coordinate of CROP modification is negative - truncating to zero\n"; area.y = 0; } /* * Unlike other image functions cut_surface does not convert the input * surface to a neutral surface, nor does it convert its return surface * to an optimised surface. * * Since it seems to work for most cases, rather change this caller instead * of the function signature. (The issue was discovered in bug #20876). */ return create_optimized_surface( cut_surface(make_neutral_surface(src), area)); }
surface darken_modification::operator()(const surface &src) const { surface ret = make_neutral_surface(src); surface tod_dark(image::get_image(game_config::images::tod_dark)); if (tod_dark) blit_surface(tod_dark, NULL, ret, NULL); return ret; }
surface brighten_function::operator()(const surface &src) const { surface ret = make_neutral_surface(src); surface tod_bright(image::get_image(game_config::images:: tod_bright)); if (tod_bright) sdl_blit(tod_bright, NULL, ret, NULL); return ret; }
surface blit_modification::operator()(const surface& src) const { if(x_ >= src->w) { std::stringstream sstr; sstr << "~BLIT(): x-coordinate '" << x_ << "' larger than destination image's width '" << src->w << "' no blitting performed.\n"; throw texception(sstr); } if(y_ >= src->h) { std::stringstream sstr; sstr << "~BLIT(): y-coordinate '" << y_ << "' larger than destination image's height '" << src->h << "' no blitting performed.\n"; throw texception(sstr); } if(surf_->w + x_ > src->w) { std::stringstream sstr; sstr << "~BLIT(): offset and width '" << x_ + surf_->w << "' larger than destination image's width '" << src->w << "' no blitting performed.\n"; throw texception(sstr); } if(surf_->h + y_ > src->h) { std::stringstream sstr; sstr << "~BLIT(): offset and height '" << y_ + surf_->h << "' larger than destination image's height '" << src->h << "' no blitting performed.\n"; throw texception(sstr); } //blit_surface want neutral surfaces surface nsrc = make_neutral_surface(src); surface nsurf = make_neutral_surface(surf_); SDL_Rect r = create_rect(x_, y_, 0, 0); blit_surface(nsurf, NULL, nsrc, &r); return nsrc; }
surface background_modification::operator()(const surface &src) const { surface ret = make_neutral_surface(src); SDL_FillRect(ret, NULL, SDL_MapRGBA(ret->format, color_.r, color_.g, color_.b, color_.unused)); SDL_SetAlpha(src, SDL_SRCALPHA, SDL_ALPHA_OPAQUE); SDL_BlitSurface(src, NULL, ret, NULL); return ret; }
surface light_modification::operator()(const surface& src) const { if(src == NULL) { return NULL; } //light_surface wants a neutral surface having same dimensions surface nsurf; if(surf_->w != src->w || surf_->h != src->h) nsurf = scale_surface(surf_, src->w, src->h, false); else nsurf = make_neutral_surface(surf_); return light_surface(src, nsurf);; }
surface background_modification::operator()(const surface &src) const { surface ret = make_neutral_surface(src); #if SDL_VERSION_ATLEAST(2,0,0) SDL_FillRect(ret, NULL, SDL_MapRGBA(ret->format, color_.r, color_.g, color_.b, color_.a)); #else SDL_FillRect(ret, NULL, SDL_MapRGBA(ret->format, color_.r, color_.g, color_.b, color_.unused)); #endif SDL_SetAlpha(src, SDL_SRCALPHA, SDL_ALPHA_OPAQUE); blit_surface(src, NULL, ret, NULL); return ret; }
void cutter::load_masks(const config& conf) { const config::child_list& masks = conf.get_children("mask"); for(config::child_list::const_iterator itor = masks.begin(); itor != masks.end(); ++itor) { const std::string name = (**itor)["name"]; const std::string image = get_mask_dir() + "/" + (**itor)["image"]; if(verbose_) { std::cerr << "Adding mask " << name << "\n"; } if(image.empty()) throw exploder_failure("Missing image for mask " + name); const exploder_point shift((**itor)["shift"]); const exploder_rect cut((**itor)["cut"]); if(masks_.find(name) != masks_.end() && masks_[name].filename != image) { throw exploder_failure("Mask " + name + " correspond to two different files: " + name + " and " + masks_.find(name)->second.filename); } if(masks_.find(name) == masks_.end()) { mask& cur_mask = masks_[name]; cur_mask.name = name; cur_mask.shift = shift; cur_mask.cut = cut; cur_mask.filename = image; surface tmp(IMG_Load(image.c_str())); if(tmp == NULL) throw exploder_failure("Unable to load mask image " + image); cur_mask.image = surface(make_neutral_surface(tmp)); } if(masks_[name].image == NULL) throw exploder_failure("Unable to load mask image " + image); } }
void cutter::load_masks(const config& conf) { BOOST_FOREACH(const config &m, conf.child_range("mask")) { const std::string name = m["name"]; const std::string image = get_mask_dir() + "/" + std::string(m["image"]); if(verbose_) { std::cerr << "Adding mask " << name << "\n"; } if(image.empty()) throw exploder_failure("Missing image for mask " + name); const exploder_point shift(m["shift"]); const exploder_rect cut(m["cut"]); if(masks_.find(name) != masks_.end() && masks_[name].filename != image) { throw exploder_failure("Mask " + name + " correspond to two different files: " + name + " and " + masks_.find(name)->second.filename); } if(masks_.find(name) == masks_.end()) { mask& cur_mask = masks_[name]; cur_mask.name = name; cur_mask.shift = shift; cur_mask.cut = cut; cur_mask.filename = image; surface tmp(IMG_Load(image.c_str())); if(tmp == NULL) throw exploder_failure("Unable to load mask image " + image); cur_mask.image = surface(make_neutral_surface(tmp)); } if(masks_[name].image == NULL) throw exploder_failure("Unable to load mask image " + image); } }
const SDL_Rect& unit_drawer::calculate_energy_bar(surface surf) const { const std::map<surface,SDL_Rect>::const_iterator i = energy_bar_rects_.find(surf); if(i != energy_bar_rects_.end()) { return i->second; } int first_row = -1, last_row = -1, first_col = -1, last_col = -1; surface image(make_neutral_surface(surf)); const_surface_lock image_lock(image); const Uint32* const begin = image_lock.pixels(); for(int y = 0; y != image->h; ++y) { const Uint32* const i1 = begin + image->w*y; const Uint32* const i2 = i1 + image->w; const Uint32* const itor = std::find_if(i1,i2,is_energy_color()); const int count = std::count_if(itor,i2,is_energy_color()); if(itor != i2) { if(first_row == -1) { first_row = y; } first_col = itor - i1; last_col = first_col + count; last_row = y; } } const SDL_Rect res = sdl::create_rect(first_col , first_row , last_col-first_col , last_row+1-first_row); energy_bar_rects_.insert(std::pair<surface,SDL_Rect>(surf,res)); return calculate_energy_bar(surf); }
void button::draw_contents() { surface image = image_; const int image_w = image_->w; int offset = 0; switch(state_) { case ACTIVE: image = activeImage_; break; case PRESSED: image = pressedImage_; if (type_ == TYPE_PRESS) offset = 1; break; case PRESSED_ACTIVE: image = pressedActiveImage_; break; case TOUCHED_NORMAL: case TOUCHED_PRESSED: image = touchedImage_; break; default: break; } SDL_Rect const &loc = location(); SDL_Rect clipArea = loc; const int texty = loc.y + loc.h / 2 - textRect_.h / 2 + offset; int textx; if (type_ != TYPE_CHECK && type_ != TYPE_RADIO && type_ != TYPE_IMAGE) textx = loc.x + image->w / 2 - textRect_.w / 2 + offset; else { clipArea.w += image_w + checkbox_horizontal_padding; textx = loc.x + image_w + checkbox_horizontal_padding / 2; } SDL_Color button_color = font::BUTTON_COLOR; if (!enabled()) { if (state_ == PRESSED || state_ == PRESSED_ACTIVE) image = pressedDisabledImage_; else image = disabledImage_; button_color = font::GRAY_COLOR; } if (!overlayImage_.null()) { surface noverlay = make_neutral_surface( enabled() ? overlayImage_ : overlayDisabledImage_); if (!overlayPressedImage_.null()) { switch (state_) { case ACTIVE: if (!overlayActiveImage_.null()) noverlay = make_neutral_surface(overlayActiveImage_); break; case PRESSED: case PRESSED_ACTIVE: case TOUCHED_NORMAL: case TOUCHED_PRESSED: noverlay = make_neutral_surface( enabled() ? overlayPressedImage_ : overlayPressedDisabledImage_); break; default: break; } } surface nimage = make_neutral_surface(image); blit_surface(noverlay, NULL, nimage, NULL); image = nimage; } video().blit_surface(loc.x, loc.y, image); if (type_ != TYPE_IMAGE){ clipArea.x += offset; clipArea.y += offset; clipArea.w -= 2*offset; clipArea.h -= 2*offset; font::draw_text(&video(), clipArea, font_size, button_color, label_, textx, texty); } update_rect(loc); }
void timage::draw(surface& canvas , const game_logic::map_formula_callable& variables) { DBG_GUI_D << "Image: draw.\n"; /** * @todo formulas are now recalculated every draw cycle which is a bit * silly unless there has been a resize. So to optimize we should use an * extra flag or do the calculation in a separate routine. */ const std::string& name = image_name_(variables); if(name.empty()) { DBG_GUI_D << "Image: formula returned no value, will not be drawn.\n"; return; } /* * The locator might return a different surface for every call so we can't * cache the output, also not if no formula is used. */ surface tmp(image::get_image(image::locator(name))); if(!tmp) { ERR_GUI_D << "Image: '" << name << "' not found and won't be drawn.\n"; return; } image_.assign(make_neutral_surface(tmp)); assert(image_); src_clip_ = ::create_rect(0, 0, image_->w, image_->h); game_logic::map_formula_callable local_variables(variables); local_variables.add("image_original_width", variant(image_->w)); local_variables.add("image_original_height", variant(image_->h)); unsigned w = w_(local_variables); VALIDATE_WITH_DEV_MESSAGE( static_cast<int>(w) >= 0 , _("Image doesn't fit on canvas.") , (formatter() << "Image '" << name << "', w = " << static_cast<int>(w) << ".").str()); unsigned h = h_(local_variables); VALIDATE_WITH_DEV_MESSAGE( static_cast<int>(h) >= 0 , _("Image doesn't fit on canvas.") , (formatter() << "Image '" << name << "', h = " << static_cast<int>(h) << ".").str()); local_variables.add("image_width", variant(w ? w : image_->w)); local_variables.add("image_height", variant(h ? h : image_->h)); const unsigned x = x_(local_variables); VALIDATE_WITH_DEV_MESSAGE( static_cast<int>(x) >= 0 , _("Image doesn't fit on canvas.") , (formatter() << "Image '" << name << "', x = " << static_cast<int>(x) << ".").str()); const unsigned y = y_(local_variables); VALIDATE_WITH_DEV_MESSAGE( static_cast<int>(y) >= 0 , _("Image doesn't fit on canvas.") , (formatter() << "Image '" << name << "', y = " << static_cast<int>(y) << ".").str()); // Copy the data to local variables to avoid overwriting the originals. SDL_Rect src_clip = src_clip_; SDL_Rect dst_clip = ::create_rect(x, y, 0, 0); surface surf; // Test whether we need to scale and do the scaling if needed. if(w || h) { bool done = false; bool stretch_image = (resize_mode_ == stretch) && (!!w ^ !!h); if(!w) { if(stretch_image) { DBG_GUI_D << "Image: vertical stretch from " << image_->w << ',' << image_->h << " to a height of " << h << ".\n"; surf = stretch_surface_vertical(image_, h, false); done = true; } w = image_->w; } if(!h) { if(stretch_image) { DBG_GUI_D << "Image: horizontal stretch from " << image_->w << ',' << image_->h << " to a width of " << w << ".\n"; surf = stretch_surface_horizontal(image_, w, false); done = true; } h = image_->h; } if(!done) { if(resize_mode_ == tile) { DBG_GUI_D << "Image: tiling from " << image_->w << ',' << image_->h << " to " << w << ',' << h << ".\n"; const int columns = (w + image_->w - 1) / image_->w; const int rows = (h + image_->h - 1) / image_->h; surf = create_neutral_surface(w, h); for(int x = 0; x < columns; ++x) { for(int y = 0; y < rows; ++y) { const SDL_Rect dest = ::create_rect( x * image_->w , y * image_->h , 0 , 0); blit_surface(image_, NULL, surf, &dest); } } } else { if(resize_mode_ == stretch) { ERR_GUI_D << "Image: failed to stretch image, " "fall back to scaling.\n"; } DBG_GUI_D << "Image: scaling from " << image_->w << ',' << image_->h << " to " << w << ',' << h << ".\n"; surf = scale_surface(image_, w, h, false); } } src_clip.w = w; src_clip.h = h; } else { surf = image_; } if(vertical_mirror_(local_variables)) { surf = flip_surface(surf, false); } blit_surface(surf, &src_clip, canvas, &dst_clip); }
void tristate_button::draw_contents() { surface image(nullptr); surface overlay(nullptr); surface base = baseImage_; int offset = 0; switch (state_) { case UNINIT: return; case NORMAL: break; case TOUCHED_LEFT: overlay = touchedUpImage_; base = touchedBaseImage_; break; case TOUCHED_RIGHT: overlay = touchedDownImage_; base = touchedBaseImage_; break; case TOUCHED_BOTH_LEFT: case TOUCHED_BOTH_RIGHT: overlay = touchedBothImage_; base = touchedBaseImage_; break; case ACTIVE: // overlay = activeImage_; base = activeBaseImage_; break; case PRESSED_LEFT: base = activeBaseImage_; overlay = pressedUpImage_; break; case PRESSED_RIGHT: base = activeBaseImage_; overlay = pressedDownImage_; break; case PRESSED_BOTH: base = activeBaseImage_; overlay = pressedBothImage_; break; case PRESSED_ACTIVE_LEFT: overlay = pressedUpActiveImage_; base = activeBaseImage_; break; case PRESSED_ACTIVE_BOTH: overlay = pressedBothActiveImage_; base = activeBaseImage_; break; case PRESSED_ACTIVE_RIGHT: overlay = pressedDownActiveImage_; base = activeBaseImage_; break; } image = base; const int image_w = image->w; const SDL_Rect& loc = location(); SDL_Rect clipArea = loc; const int texty = loc.y + loc.h / 2 - textRect_.h / 2 + offset; int textx; clipArea.w += image_w + checkbox_horizontal_padding; textx = loc.x + image_w + checkbox_horizontal_padding / 2; color_t button_color = font::BUTTON_COLOR; surface scalled_item; scalled_item.assign(scale_surface(itemImage_, 36, 36)); surface nitem = make_neutral_surface(scalled_item); surface nbase = make_neutral_surface(base); //TODO avoid magic numbers SDL_Rect r {1, 1, 0, 0}; sdl_blit(nitem, nullptr, nbase, &r); if (!overlay.null()) { surface noverlay = make_neutral_surface(overlay); sdl_blit(noverlay, nullptr, nbase, nullptr); } bg_restore(); image = nbase; video().blit_surface(loc.x, loc.y, image); clipArea.x += offset; clipArea.y += offset; clipArea.w -= 2 * offset; clipArea.h -= 2 * offset; font::draw_text(&video(), clipArea, font_size, button_color, label_, textx, texty); }
surface composer::compose(const std::string &src, const std::string &dest) { cutter cut; cut.set_verbose(verbose_); const config src_conf = cut.load_config(src); const config dest_conf = cut.load_config(dest); if(verbose_) { std::cerr << "Loading masks...\n"; } cut.load_masks(src_conf); cut.load_masks(dest_conf); if(verbose_) { std::cerr << "Loading images...\n"; } const surface src_surface(make_neutral_surface(IMG_Load(src.c_str()))); if(src_surface == NULL) throw exploder_failure("Unable to load the source image " + src); const surface dest_surface(make_neutral_surface(IMG_Load(dest.c_str()))); if(dest_surface == NULL) throw exploder_failure("Unable to load the destination image " + dest); if(verbose_) { std::cerr << "Cutting images...\n"; } const cutter::surface_map src_surfaces = cut.cut_surface(src_surface, src_conf); const cutter::surface_map dest_surfaces = cut.cut_surface(dest_surface, dest_conf); for(cutter::surface_map::const_iterator itor = dest_surfaces.begin(); itor != dest_surfaces.end(); ++itor) { const std::string& name = itor->second.name; if(src_surfaces.find(name) == src_surfaces.end()) continue; const cutter::positioned_surface& src_ps = src_surfaces.find(name)->second; const cutter::positioned_surface& dest_ps = itor->second; if(!image_empty(dest_ps.image)) { if(interactive_) { //TODO: make "interactive" mode work } else { std::cerr << "Warning: element " << name << " not empty on destination image\n"; } } if(verbose_) { std::cerr << "Inserting image " << name << " on position (" << dest_ps.pos.x << ", " << dest_ps.pos.y << ")\n"; } masked_overwrite_surface(dest_surface, src_ps.image, src_ps.mask.image, dest_ps.pos.x, dest_ps.pos.y); } return dest_surface; }
surface getMinimap(int w, int h, const gamemap &map, const team *vw) { const int scale = 8; DBG_DP << "creating minimap " << int(map.w()*scale*0.75) << "," << int(map.h()*scale) << "\n"; const size_t map_width = map.w()*scale*3/4; const size_t map_height = map.h()*scale; if(map_width == 0 || map_height == 0) { return surface(NULL); } surface minimap(create_neutral_surface(map_width, map_height)); if(minimap == NULL) return surface(NULL); typedef mini_terrain_cache_map cache_map; cache_map *normal_cache = &mini_terrain_cache; cache_map *fog_cache = &mini_fogged_terrain_cache; for(int y = 0; y != map.total_height(); ++y) { for(int x = 0; x != map.total_width(); ++x) { surface surf(NULL); const map_location loc(x,y); if(map.on_board(loc)) { const bool shrouded = vw != NULL && vw->shrouded(loc); // shrouded hex are not considered fogged (no need to fog a black image) const bool fogged = vw != NULL && !shrouded && vw->fogged(loc); const t_translation::t_terrain terrain = shrouded ? t_translation::VOID_TERRAIN : map[loc]; bool need_fogging = false; cache_map* cache = fogged ? fog_cache : normal_cache; cache_map::iterator i = cache->find(terrain); if (fogged && i == cache->end()) { // we don't have the fogged version in cache // try the normal cache and ask fogging the image cache = normal_cache; i = cache->find(terrain); need_fogging = true; } if(i == cache->end()) { surface tile(get_image("terrain/" + map.get_terrain_info(terrain).minimap_image() + ".png",image::HEXED)); if(tile == 0) { utils::string_map symbols; symbols["terrain"] = t_translation::write_terrain_code(terrain); const std::string msg = vgettext("Could not get image for terrain: $terrain.", symbols); VALIDATE(false, msg); } //Compose images of base and overlay if neccessary if(map.get_terrain_info(terrain).is_combined()) { surface overlay(get_image("terrain/" + map.get_terrain_info(terrain).minimap_image_overlay() + ".png", image::HEXED)); if(overlay != 0 && overlay != tile) { surface combined = create_compatible_surface(tile, tile->w, tile->h); SDL_Rect r; r.x = 0; r.y = 0; SDL_BlitSurface(tile, NULL, combined, &r); r.x = std::max(0, (tile->w - overlay->w)/2); r.y = std::max(0, (tile->h - overlay->h)/2); if ((overlay->flags & SDL_RLEACCEL) == 0) { blit_surface(overlay, NULL, combined, &r); } else { WRN_DP << map.get_terrain_info(terrain).minimap_image_overlay() << ".png overlay is RLE-encoded, creating a neutral surface\n"; surface overlay_neutral = make_neutral_surface(overlay); blit_surface(overlay_neutral, NULL, combined, &r); } tile = combined; } } surf = surface(scale_surface_blended(tile,scale,scale)); VALIDATE(surf != NULL, _("Error creating or aquiring an image.")); i = normal_cache->insert(cache_map::value_type(terrain,surf)).first; } surf = i->second; if (need_fogging) { surf = surface(adjust_surface_colour(surf,-50,-50,-50)); fog_cache->insert(cache_map::value_type(terrain,surf)); } VALIDATE(surf != NULL, _("Error creating or aquiring an image.")); // we need a balanced shift up and down of the hexes. // if not, only the bottom half-hexes are clipped // and it looks asymmetrical. // also do 1-pixel shift because the scaling // function seems to do it with its rounding SDL_Rect maprect = {x * scale*3/4 - 1, y*scale + scale/4 * (is_odd(x) ? 1 : -1) - 1, 0, 0}; SDL_BlitSurface(surf, NULL, minimap, &maprect); } } } double wratio = w*1.0 / minimap->w; double hratio = h*1.0 / minimap->h; double ratio = std::min<double>(wratio, hratio); minimap = scale_surface(minimap, static_cast<int>(minimap->w * ratio), static_cast<int>(minimap->h * ratio)); DBG_DP << "done generating minimap\n"; return minimap; }
void part_ui::prepare_background() { #ifdef SDL_GPU base_rect_.w = video_.getx(); base_rect_.h = video_.gety(); has_background_ = false; bool no_base_yet = true; BOOST_FOREACH(const background_layer& bl, p_.get_background_layers()) { sdl::timage layer; if (!bl.file().empty()) { layer = image::get_texture(bl.file()); } has_background_ = has_background_ || !layer.null(); if(layer.null() || layer.width() * layer.height() == 0) { continue; } const double xscale = 1.0 * video_.getx() / layer.base_width(); const double yscale = 1.0 * video_.gety() / layer.base_height(); const bool scalev = bl.scale_vertically(); const bool scaleh = bl.scale_horizontally(); const bool keep_ratio = bl.keep_aspect_ratio(); const bool tileh = bl.tile_horizontally(); const bool tilev = bl.tile_vertically(); double x_scale_factor = scaleh ? xscale : 1.0; double y_scale_factor = scalev ? yscale : 1.0; if (scalev && scaleh && keep_ratio) { x_scale_factor = y_scale_factor = std::min<double>(xscale, yscale); } else if (keep_ratio && scaleh) { x_scale_factor = y_scale_factor = xscale; } else if (keep_ratio && scalev) { x_scale_factor = y_scale_factor = yscale; } layer.set_smooth_scaling(true); SDL_Rect clip = sdl::create_rect(0, 0, layer.base_width(), layer.base_height()); if (tileh) { clip.x = (layer.base_width() - video_.getx())/2; clip.w = video_.getx(); layer.set_hwrap(GPU_WRAP_REPEAT); } if (tilev) { clip.y = (layer.base_height() - video_.gety())/2; clip.h = video_.gety(); layer.set_vwrap(GPU_WRAP_REPEAT); } layer.set_clip(clip); layer.set_scale(x_scale_factor, y_scale_factor); SDL_Rect base_rect = sdl::create_rect( (video_.getx() - layer.width()) / 2 , (video_.gety() - layer.height()) / 2 , layer.width() , layer.height()); background_images_.push_back(layer); background_positions_.push_back(std::pair<int, int>(base_rect.x, base_rect.y)); if (bl.is_base_layer() || no_base_yet) { x_scale_factor_ = x_scale_factor; y_scale_factor_ = y_scale_factor; base_rect_ = base_rect; no_base_yet = false; } } #else background_.assign( create_neutral_surface(video_.getx(), video_.gety()) ); base_rect_.w = video_.getx(); base_rect_.h = video_.gety(); has_background_ = false; bool no_base_yet = true; // Build background surface BOOST_FOREACH(const background_layer& bl, p_.get_background_layers()) { surface layer; if(bl.file().empty() != true) { layer.assign( image::get_image(bl.file()) ); } has_background_ = has_background_ || !layer.null(); if(layer.null() || layer->w * layer->h == 0) { continue; } layer = make_neutral_surface(layer); const double xscale = 1.0 * video_.getx() / layer->w; const double yscale = 1.0 * video_.gety() / layer->h; const bool scalev = bl.scale_vertically(); const bool scaleh = bl.scale_horizontally(); const bool keep_ratio = bl.keep_aspect_ratio(); double x_scale_factor = scaleh ? xscale : 1.0; double y_scale_factor = scalev ? yscale : 1.0; if (scalev && scaleh && keep_ratio) { x_scale_factor = y_scale_factor = std::min<double>(xscale, yscale); } else if (keep_ratio && scaleh) { x_scale_factor = y_scale_factor = xscale; } else if (keep_ratio && scalev) { x_scale_factor = y_scale_factor = yscale; } layer = scale_surface(layer, static_cast<int>(layer->w*x_scale_factor), static_cast<int>(layer->h*y_scale_factor), false); const int tilew = bl.tile_horizontally() ? video_.getx() : layer->w; const int tileh = bl.tile_vertically() ? video_.gety() : layer->h; layer = tile_surface(layer, tilew, tileh, false); SDL_Rect drect = sdl::create_rect( (background_->w - layer->w) / 2 , (background_->h - layer->h) / 2 , layer->w , layer->h); SDL_Rect srect = sdl::create_rect( 0 , 0 , layer->w , layer->h); SDL_Rect base_rect = drect; // If we can't see the whole image anyways, we'll want to display the // top-middle area. if (drect.y < 0) { drect.y = 0; base_rect.y = 0; } if (drect.x < 0) { srect.x -= drect.x; drect.x = 0; } blit_surface(layer, &srect, background_, &drect); ASSERT_LOG(layer.null() == false, "Oops: a storyscreen part background layer got NULL"); if (bl.is_base_layer() || no_base_yet) { x_scale_factor_ = x_scale_factor; y_scale_factor_ = y_scale_factor; base_rect_ = base_rect; no_base_yet = false; } } #endif }
void tristate_button::draw_contents() { surface image(NULL); surface overlay(NULL); surface base = baseImage_; int offset = 0; switch (state_) { case UNINIT: return; case NORMAL: break; case TOUCHED_LEFT: overlay = touchedUpImage_; base = touchedBaseImage_; break; case TOUCHED_RIGHT: overlay = touchedDownImage_; base = touchedBaseImage_; break; case TOUCHED_BOTH_LEFT: case TOUCHED_BOTH_RIGHT: overlay = touchedBothImage_; base = touchedBaseImage_; break; case ACTIVE: // overlay = activeImage_; base = activeBaseImage_; break; case PRESSED_LEFT: base = activeBaseImage_; overlay = pressedUpImage_; break; case PRESSED_RIGHT: base = activeBaseImage_; overlay = pressedDownImage_; break; case PRESSED_BOTH: base = activeBaseImage_; overlay = pressedBothImage_; break; case PRESSED_ACTIVE_LEFT: overlay = pressedUpActiveImage_; base = activeBaseImage_; break; case PRESSED_ACTIVE_BOTH: overlay = pressedBothActiveImage_; base = activeBaseImage_; break; case PRESSED_ACTIVE_RIGHT: overlay = pressedDownActiveImage_; base = activeBaseImage_; break; } image = base; const int image_w = image->w; SDL_Rect const &loc = location(); SDL_Rect clipArea = loc; const int texty = loc.y + loc.h / 2 - textRect_.h / 2 + offset; int textx; clipArea.w += image_w + checkbox_horizontal_padding; textx = loc.x + image_w + checkbox_horizontal_padding / 2; SDL_Color button_color = font::BUTTON_COLOR; surface scalled_item; scalled_item.assign(scale_surface(itemImage_, 36, 36)); // blit_surface want neutral surfaces surface nitem = make_neutral_surface(scalled_item); surface nbase = make_neutral_surface(base); //TODO avoid magic numbers SDL_Rect r = sdl::create_rect(1, 1, 0, 0); blit_surface(nitem, NULL, nbase, &r); if (!overlay.null()) { surface noverlay = make_neutral_surface(overlay); blit_surface(noverlay, NULL, nbase, NULL); } // TODO for later reference // SDL_SetAlpha(nbase, SDL_SRCALPHA, SDL_ALPHA_OPAQUE); // SDL_SetAlpha(image, 0, 0); // // TODO might be needed. bg_restore(); image = nbase; video().blit_surface(loc.x, loc.y, image); clipArea.x += offset; clipArea.y += offset; clipArea.w -= 2 * offset; clipArea.h -= 2 * offset; font::draw_text(&video(), clipArea, font_size, button_color, label_, textx, texty); update_rect(loc); }
surface getMinimap(int w, int h, const gamemap &map, const team *vw) { const int scale = 8; DBG_DP << "creating minimap " << int(map.w()*scale*0.75) << "," << map.h()*scale << "\n"; const size_t map_width = map.w()*scale*3/4; const size_t map_height = map.h()*scale; if(map_width == 0 || map_height == 0) { return surface(NULL); } surface minimap(create_neutral_surface(map_width, map_height)); if(minimap == NULL) return surface(NULL); typedef mini_terrain_cache_map cache_map; cache_map *normal_cache = &mini_terrain_cache; cache_map *fog_cache = &mini_fogged_terrain_cache; for(int y = 0; y != map.total_height(); ++y) { for(int x = 0; x != map.total_width(); ++x) { surface surf(NULL); const map_location loc(x,y); if(map.on_board(loc)) { const bool shrouded = (vw != NULL && vw->shrouded(loc)); // shrouded hex are not considered fogged (no need to fog a black image) const bool fogged = (vw != NULL && !shrouded && vw->fogged(loc)); const t_translation::t_terrain terrain = shrouded ? t_translation::VOID_TERRAIN : map[loc]; const terrain_type& terrain_info = map.get_terrain_info(terrain); bool need_fogging = false; cache_map* cache = fogged ? fog_cache : normal_cache; cache_map::iterator i = cache->find(terrain); if (fogged && i == cache->end()) { // we don't have the fogged version in cache // try the normal cache and ask fogging the image cache = normal_cache; i = cache->find(terrain); need_fogging = true; } if(i == cache->end()) { std::string base_file = "terrain/" + terrain_info.minimap_image() + ".png"; surface tile = get_image(base_file,image::HEXED); //Compose images of base and overlay if necessary // NOTE we also skip overlay when base is missing (to avoid hiding the error) if(tile != NULL && map.get_terrain_info(terrain).is_combined()) { std::string overlay_file = "terrain/" + terrain_info.minimap_image_overlay() + ".png"; surface overlay = get_image(overlay_file,image::HEXED); if(overlay != NULL && overlay != tile) { surface combined = create_neutral_surface(tile->w, tile->h); SDL_Rect r = create_rect(0,0,0,0); sdl_blit(tile, NULL, combined, &r); r.x = std::max(0, (tile->w - overlay->w)/2); r.y = std::max(0, (tile->h - overlay->h)/2); //blit_surface needs neutral surface surface overlay_neutral = make_neutral_surface(overlay); blit_surface(overlay_neutral, NULL, combined, &r); tile = combined; } } surf = scale_surface_sharp(tile, scale, scale); i = normal_cache->insert(cache_map::value_type(terrain,surf)).first; } surf = i->second; if (need_fogging) { surf = adjust_surface_color(surf,-50,-50,-50); fog_cache->insert(cache_map::value_type(terrain,surf)); } // we need a balanced shift up and down of the hexes. // if not, only the bottom half-hexes are clipped // and it looks asymmetrical. // also do 1-pixel shift because the scaling // function seems to do it with its rounding SDL_Rect maprect = create_rect( x * scale * 3 / 4 - 1 , y * scale + scale / 4 * (is_odd(x) ? 1 : -1) - 1 , 0 , 0); if(surf != NULL) sdl_blit(surf, NULL, minimap, &maprect); } } } double wratio = w*1.0 / minimap->w; double hratio = h*1.0 / minimap->h; double ratio = std::min<double>(wratio, hratio); minimap = scale_surface_sharp(minimap, static_cast<int>(minimap->w * ratio), static_cast<int>(minimap->h * ratio)); DBG_DP << "done generating minimap\n"; return minimap; }
int main(int argc, char* argv[]) { std::string src; std::string dest_dir; cutter cut; // Parse arguments that shouldn't require a display device int arg; for(arg = 1; arg != argc; ++arg) { const std::string val(argv[arg]); if(val.empty()) { continue; } if(val == "--help" || val == "-h") { print_usage(argv[0]); return 0; } else if(val == "--verbose" || val == "-v") { cut.set_verbose(true); } else if(val == "--directory" || val == "-d" ) { game_config::path = argv[++arg]; } else { if(src.empty()) { src = val; } else if(dest_dir.empty()) { dest_dir = val; } else { print_usage(argv[0]); return 1; } } } if(src.empty() || dest_dir.empty()) { print_usage(argv[0]); return 1; } try { const config conf = cut.load_config(src); cut.load_masks(conf); const surface src_surface(make_neutral_surface(IMG_Load(src.c_str()))); if(src_surface == NULL) throw exploder_failure("Unable to load the source image " + src); const cutter::surface_map surfaces = cut.cut_surface(src_surface, conf); for(cutter::surface_map::const_iterator itor = surfaces.begin(); itor != surfaces.end(); ++itor) { const cutter::mask &mask = itor->second.mask; surface surf = create_compatible_surface( itor->second.image , mask.cut.w , mask.cut.h); masked_overwrite_surface(surf, itor->second.image, mask.image, mask.cut.x - mask.shift.x, mask.cut.y - mask.shift.y); save_image(surf, dest_dir + "/" + mask.name + ".png"); } } catch(exploder_failure& err) { std::cerr << "Failed: " << err.message << "\n"; return 1; } return 0; }