コード例 #1
0
void floating_label::draw(surface screen)
{
	if(!visible_) {
		buf_.assign(nullptr);
		return;
	}

	if(screen == nullptr) {
		return;
	}

	create_surface();
	if(surf_ == nullptr) {
		return;
	}

	if(buf_ == nullptr) {
		buf_.assign(create_compatible_surface(screen, surf_->w, surf_->h));
		if(buf_ == nullptr) {
			return;
		}
	}

	SDL_Rect rect = sdl::create_rect(xpos(surf_->w), ypos_, surf_->w, surf_->h);
	const clip_rect_setter clip_setter(screen, &clip_rect_);
	sdl_copy_portion(screen,&rect,buf_,nullptr);
	sdl_blit(surf_,nullptr,screen,&rect);
}
コード例 #2
0
void textbox::append_text(const std::string& text, bool auto_scroll, const SDL_Color& color)
{
	if(text_image_.get() == NULL) {
		set_text(text, color);
		return;
	}

	//disallow adding multi-line text to a single-line text box
	if(wrap_ == false && std::find_if(text.begin(),text.end(),utils::isnewline) != text.end()) {
		return;
	}
	const bool is_at_bottom = get_position() == get_max_position();
	const wide_string& wtext = utils::string_to_wstring(text);

	const surface new_text = add_text_line(wtext, color);
	const surface new_surface = create_compatible_surface(text_image_,std::max<size_t>(text_image_->w,new_text->w),text_image_->h+new_text->h);

	SDL_SetAlpha(new_text.get(),0,0);
	SDL_SetAlpha(text_image_.get(),0,0);

	SDL_BlitSurface(text_image_,NULL,new_surface,NULL);

	SDL_Rect target = {0,text_image_->h,new_text->w,new_text->h};
	SDL_BlitSurface(new_text,NULL,new_surface,&target);
	text_image_.assign(new_surface);

	text_.resize(text_.size() + wtext.size());
	std::copy(wtext.begin(),wtext.end(),text_.end()-wtext.size());

	set_dirty(true);
	update_text_cache(false);
	if(auto_scroll && is_at_bottom) scroll_to_bottom();
	handle_text_changed(text_);
}
コード例 #3
0
void mouse_action::set_terrain_mouse_overlay(editor_display& disp, t_translation::t_terrain fg,
		t_translation::t_terrain bg)
{
	surface image_fg(image::get_image("terrain/"
		+ disp.get_map().get_terrain_info(fg).editor_image() + ".png"));
	surface image_bg(image::get_image("terrain/"
		+ disp.get_map().get_terrain_info(bg).editor_image() + ".png"));

	if (image_fg == NULL || image_bg == NULL) {
		ERR_ED << "Missing terrain icon\n";
		disp.set_mouseover_hex_overlay(NULL);
		return;
	}

	// Create a transparent surface of the right size.
	surface image = create_compatible_surface(image_fg, image_fg->w, image_fg->h);
	SDL_FillRect(image,NULL,SDL_MapRGBA(image->format,0,0,0, 0));

	// For efficiency the size of the tile is cached.
	// We assume all tiles are of the same size.
	// The zoom factor can change, so it's not cached.
	// NOTE: when zooming and not moving the mouse, there are glitches.
	// Since the optimal alpha factor is unknown, it has to be calculated
	// on the fly, and caching the surfaces makes no sense yet.
	static const Uint8 alpha = 196;
	static const int size = image_fg->w;
	static const int half_size = size / 2;
	static const int quarter_size = size / 4;
	static const int offset = 2;
	static const int new_size = half_size - 2;
	const int zoom = static_cast<int>(size * disp.get_zoom_factor());

	// Blit left side
	image_fg = scale_surface(image_fg, new_size, new_size);
	SDL_Rect rcDestLeft = { offset, quarter_size, 0, 0 };
	SDL_BlitSurface ( image_fg, NULL, image, &rcDestLeft );

	// Blit left side
	image_bg = scale_surface(image_bg, new_size, new_size);
	SDL_Rect rcDestRight = { half_size, quarter_size, 0, 0 };
	SDL_BlitSurface ( image_bg, NULL, image, &rcDestRight );

	//apply mask so the overlay is contained within the mouseover hex
	surface mask(image::get_image("terrain/alphamask.png"));
	image = mask_surface(image, mask);

	// Add the alpha factor and scale the image
	image = scale_surface(adjust_surface_alpha(image, alpha), zoom, zoom);

	// Set as mouseover
	disp.set_mouseover_hex_overlay(image);
}
コード例 #4
0
void fill_rect_alpha(SDL_Rect &rect, Uint32 color, Uint8 alpha, surface target)
{
	if(alpha == SDL_ALPHA_OPAQUE) {
		sdl::fill_rect(target,&rect,color);
		return;
	} else if(alpha == SDL_ALPHA_TRANSPARENT) {
		return;
	}

	surface tmp(create_compatible_surface(target,rect.w,rect.h));
	if(tmp == NULL) {
		return;
	}

	SDL_Rect r = {0,0,rect.w,rect.h};
	sdl::fill_rect(tmp,&r,color);
	SDL_SetAlpha(tmp,SDL_SRCALPHA,alpha);
	sdl_blit(tmp,NULL,target,&rect);
}
コード例 #5
0
void draw(surface screen)
{
	if(use_color_cursors() == false) {
		return;
	}

	if(current_cursor == NUM_CURSORS) {
		current_cursor = NORMAL;
	}

	if(have_focus == false) {
		cursor_buf = NULL;
		return;
	}

	if (!color_ready) {
		// Display start to draw cursor
		// so it can now display color cursor
		color_ready = true;
		// Reset the cursor to be sure that we hide the b&w
		set();
	}

	/** @todo FIXME: don't parse the file path every time */
	const surface surf(image::get_image("cursors/" + color_images[current_cursor]));
	if(surf == NULL) {
		// Fall back to b&w cursors
		std::cerr << "could not load color cursors. Falling back to hardware cursors\n";
		preferences::set_color_cursors(false);
		return;
	}

	if(cursor_buf != NULL && (cursor_buf->w != surf->w || cursor_buf->h != surf->h)) {
		cursor_buf = NULL;
	}

	if(cursor_buf == NULL) {
		cursor_buf = create_compatible_surface(surf);
		if(cursor_buf == NULL) {
			std::cerr << "Could not allocate surface for mouse cursor\n";
			return;
		}
	}

	int new_cursor_x, new_cursor_y;
	SDL_GetMouseState(&new_cursor_x,&new_cursor_y);
	const bool must_update = new_cursor_x != cursor_x || new_cursor_y != cursor_y;
	cursor_x = new_cursor_x;
	cursor_y = new_cursor_y;

	// Save the screen area where the cursor is being drawn onto the back buffer
	SDL_Rect area = create_rect(cursor_x - shift_x[current_cursor]
			, cursor_y - shift_y[current_cursor]
			, surf->w
			, surf->h);
	sdl_blit(screen,&area,cursor_buf,NULL);

	// Blit the surface
	sdl_blit(surf,NULL,screen,&area);

	if(must_update) {
		update_rect(area);
	}
}
コード例 #6
0
ファイル: font.cpp プロジェクト: oys0317/opensanguo
static surface render_text(const std::string& text, int fontsize, const SDL_Color& colour, int style, bool use_markup)
{
	// we keep blank lines and spaces (may be wanted for indentation)
	const std::vector<std::string> lines = utils::split(text, '\n', 0);
	std::vector<std::vector<surface> > surfaces;
	surfaces.reserve(lines.size());
	size_t width = 0, height = 0;

	for(std::vector< std::string >::const_iterator ln = lines.begin(), ln_end = lines.end(); ln != ln_end; ++ln) {

		int sz = fontsize;
		int text_style = style;

		std::string::const_iterator after_markup = use_markup ?
			parse_markup(ln->begin(), ln->end(), &sz, NULL, &text_style) : ln->begin();
		text_surface txt_surf(sz, colour, text_style);

		if (after_markup == ln->end() && (ln+1 != ln_end || lines.begin()+1 == ln_end)) {
			// we replace empty line by a space (to have a line height)
			// except for the last line if we have several
			txt_surf.set_text(" ");
		} else if (after_markup == ln->begin()) {
		 	// simple case, no markup to skip
			txt_surf.set_text(*ln);
		} else  {
			const std::string line(after_markup,ln->end());
			txt_surf.set_text(line);
		}

		const text_surface& cached_surf = text_cache::find(txt_surf);
		const std::vector<surface>&res = cached_surf.get_surfaces();

		if (!res.empty()) {
			surfaces.push_back(res);
			width = std::max<size_t>(cached_surf.width(), width);
			height += cached_surf.height();
		}
	}

	if (surfaces.empty()) {
		return surface();
	} else if (surfaces.size() == 1 && surfaces.front().size() == 1) {
		surface surf = surfaces.front().front();
		SDL_SetAlpha(surf, SDL_SRCALPHA | SDL_RLEACCEL, SDL_ALPHA_OPAQUE);
		return surf;
	} else {

		surface res(create_compatible_surface(surfaces.front().front(),width,height));
		if (res.null())
			return res;

		size_t ypos = 0;
		for(std::vector< std::vector<surface> >::const_iterator i = surfaces.begin(),
		    i_end = surfaces.end(); i != i_end; ++i) {
			size_t xpos = 0;
			size_t height = 0;

			for(std::vector<surface>::const_iterator j = i->begin(),
					j_end = i->end(); j != j_end; ++j) {
				SDL_SetAlpha(*j, 0, 0); // direct blit without alpha blending
				SDL_Rect dstrect = {xpos, ypos, 0, 0};
				SDL_BlitSurface(*j, NULL, res, &dstrect);
				xpos += (*j)->w;
				height = std::max<size_t>((*j)->h, height);
			}
			ypos += height;
		}

		return res;
	}
}
コード例 #7
0
ファイル: drawer.cpp プロジェクト: ArtBears/wesnoth
//TODO: proper SDL_gpu implementation
void unit_drawer::draw_bar(const std::string& image, int xpos, int ypos,
		const map_location& loc, size_t height, double filled,
		const SDL_Color& col, fixed_t alpha) const
{

	filled = std::min<double>(std::max<double>(filled,0.0),1.0);
	height = static_cast<size_t>(height*zoom_factor);

	surface surf(image::get_image(image,image::SCALED_TO_HEX));

	// We use UNSCALED because scaling (and bilinear interpolation)
	// is bad for calculate_energy_bar.
	// But we will do a geometric scaling later.
	surface bar_surf(image::get_image(image));
	if(surf == nullptr || bar_surf == nullptr) {
		return;
	}

	// calculate_energy_bar returns incorrect results if the surface colors
	// have changed (for example, due to bilinear interpolation)
	const SDL_Rect& unscaled_bar_loc = calculate_energy_bar(bar_surf);

	SDL_Rect bar_loc;
	if (surf->w == bar_surf->w && surf->h == bar_surf->h)
		bar_loc = unscaled_bar_loc;
	else {
		const fixed_t xratio = fxpdiv(surf->w,bar_surf->w);
		const fixed_t yratio = fxpdiv(surf->h,bar_surf->h);
		const SDL_Rect scaled_bar_loc = sdl::create_rect(
			    fxptoi(unscaled_bar_loc. x * xratio)
			  , fxptoi(unscaled_bar_loc. y * yratio + 127)
			  , fxptoi(unscaled_bar_loc. w * xratio + 255)
			  , fxptoi(unscaled_bar_loc. h * yratio + 255));
		bar_loc = scaled_bar_loc;
	}

	if(height > static_cast<size_t>(bar_loc.h)) {
		height = bar_loc.h;
	}

	//if(alpha != ftofxp(1.0)) {
	//	surf.assign(adjust_surface_alpha(surf,alpha));
	//	if(surf == nullptr) {
	//		return;
	//	}
	//}

	const size_t skip_rows = bar_loc.h - height;

	SDL_Rect top = sdl::create_rect(0, 0, surf->w, bar_loc.y);
	SDL_Rect bot = sdl::create_rect(0, bar_loc.y + skip_rows, surf->w, 0);
	bot.h = surf->w - bot.y;

#ifdef SDL_GPU
	sdl::timage img(surf);
	img.set_clip(top);
	disp.drawing_buffer_add(display::LAYER_UNIT_BAR, loc, xpos, ypos, surf);
	img.set_clip(bot);
	disp.drawing_buffer_add(display::LAYER_UNIT_BAR, loc, xpos, ypos + top.h, surf);
#else
	disp.drawing_buffer_add(display::LAYER_UNIT_BAR, loc, xpos, ypos, surf, top);
	disp.drawing_buffer_add(display::LAYER_UNIT_BAR, loc, xpos, ypos + top.h, surf, bot);
#endif

	size_t unfilled = static_cast<size_t>(height * (1.0 - filled));

	if(unfilled < height && alpha >= ftofxp(0.3)) {
		const Uint8 r_alpha = std::min<unsigned>(unsigned(fxpmult(alpha,255)),255);
		surface filled_surf = create_compatible_surface(bar_surf, bar_loc.w, height - unfilled);
		SDL_Rect filled_area = sdl::create_rect(0, 0, bar_loc.w, height-unfilled);
		sdl::fill_rect(filled_surf,&filled_area,SDL_MapRGBA(bar_surf->format,col.r,col.g,col.b, r_alpha));
#ifdef SDL_GPU
		disp.drawing_buffer_add(display::LAYER_UNIT_BAR, loc, xpos + bar_loc.x, ypos + bar_loc.y + unfilled, sdl::timage(filled_surf));
#else
		disp.drawing_buffer_add(display::LAYER_UNIT_BAR, loc, xpos + bar_loc.x, ypos + bar_loc.y + unfilled, filled_surf);
#endif
	}
}
コード例 #8
0
ファイル: cutter.cpp プロジェクト: Heark/wesnoth
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;
}
コード例 #9
0
ファイル: minimap.cpp プロジェクト: hyrio/War-Of-Kingdom
surface getMinimap(int w, int h, const gamemap &map, const display* disp)
{
	const size_t map_width = map.w() * scale_ratio_w;
	const size_t map_height = map.h() * scale_ratio_h;
	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;

	SDL_Rect tilerect = empty_rect;
	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)) {

				bool shrouded = false;
				bool fogged = false;
				if (disp) {
					disp->shrouded_and_fogged(loc, shrouded, fogged);
				}
				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 =
						image::terrain_prefix + terrain_info.minimap_image() + ".png";
					// surface tile = get_image(base_file,image::HEXED);
					surface tile = get_hexed(base_file);
					
					//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 =
								image::terrain_prefix + terrain_info.minimap_image_overlay() + ".png";
						// surface overlay = get_image(overlay_file,image::HEXED);
						surface overlay = get_hexed(overlay_file);

						if(overlay != NULL && overlay != tile) {
							surface combined = create_compatible_surface(tile, 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_blended(tile, scale_ratio, scale_ratio);

					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
				tilerect.x = x;
				tilerect.y = y;
				minimap_tile_dst(tilerect.x, tilerect.y);

				if (surf != NULL) {
					sdl_blit(surf, NULL, minimap, &tilerect);
				}
			}
		}
	}

	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;
}
コード例 #10
0
ファイル: about.cpp プロジェクト: ArtBears/wesnoth
/**
 * Show credits with list of contributors.
 *
 * Names of people are shown scrolling up like in movie-credits.\n
 * Uses map from wesnoth or campaign as background.
 */
void show_about(CVideo &video, const std::string &campaign)
{
	boost::scoped_ptr<cursor::setter> cur(new cursor::setter(cursor::WAIT));
	surface& screen = video.getSurface();
	if (screen == nullptr) return;

	// If the title is multi-line, we need to split it accordingly or we
	// get slight scrolling glitches in the credits screen.
	std::vector<std::string> text = about::get_text(campaign, true);

	SDL_Rect screen_rect = sdl::create_rect(0, 0, screen->w, screen->h);

	const surface_restorer restorer(&video, screen_rect);

	cur.reset();

	std::vector<std::string> image_list;
	if(campaign.size() && !images[campaign].empty()){
		image_list = utils::parenthetical_split(images[campaign], ',');
	} else{
		image_list = utils::parenthetical_split(images_default, ',');
	}

	surface map_image, map_image_scaled;

	if(!image_list.empty()) {
		map_image = image::get_image(image_list[0]);
	} else {
		image_list.push_back("");
	}

	if(!map_image){
        image_list[0]=game_config::images::game_title_background;
		map_image=image::get_image(image_list[0]);
	}

	gui::button close(video,_("Close"));
	close.set_location((screen->w/2)-(close.width()/2), screen->h - 30);

	const int def_size = font::SIZE_XLARGE;
	const SDL_Color def_color = font::NORMAL_COLOR;

	//substitute in the correct control characters for '+' and '-'
	std::string before_header(2, ' ');
	before_header[0] = font::LARGE_TEXT;
	for(unsigned i = 0; i < text.size(); ++i) {
		std::string &s = text[i];
		if (s.empty()) continue;
		char &first = s[0];
		if (first == '-')
			first = font::SMALL_TEXT;
		else if (first == '+') {
			first = font::LARGE_TEXT;
			text.insert(text.begin() + i, before_header);
			++i;
		}
	}
	text.insert(text.begin(), 10, before_header);

	int startline = 0;

	//TODO: use values proportional to screen ?
	// distance from top of map image to top of scrolling text
	const int top_margin = 60;
	// distance from bottom of scrolling text to bottom of map image
	const int bottom_margin = 40;
	// distance from left of scrolling text to the frame border
	const int text_left_padding = screen->w/32;

	int offset = 0;
	bool is_new_line = true;

	int first_line_height = 0;

	SDL_Rect frame_area;

	// we use a dialog to contains the text. Strange idea but at least the style
	// will be consistent with the titlescreen
	gui::dialog_frame f(video, "", gui::dialog_frame::titlescreen_style, false);

	// the text area's dimensions
	SDL_Rect text_rect = { 0, 0, 0, 0 };
	// we'll retain a copy to prevent SDL_blit to change its w and h
	SDL_Rect text_rect_blit;

	surface text_surf;

	CKey key;
	bool last_escape;

	int image_count = 0;
	int scroll_speed = 4;	// scroll_speed*50 = speed of scroll in pixel per second

	// Initially redraw all
	bool redraw_mapimage = true;
	bool update_dimensions = true;
	int max_text_width = 0;

	do {
		last_escape = key[SDLK_ESCAPE] != 0;

		// check to see if background image has changed
		if(text.size() && (image_count <
				((startline * static_cast<int>(image_list.size())) /
				static_cast<int>(text.size())))){

			image_count++;
			surface temp=image::get_image(image_list[image_count]);
			map_image=temp?temp:map_image;
			redraw_mapimage = true;
		}

		if (update_dimensions) {
			// rescale the background
			map_image_scaled = scale_surface(map_image, screen->w, screen->h);
			screen_rect = sdl::create_rect(0, 0, screen->w, screen->h);
			redraw_mapimage = true;

			// update the frame
			frame_area = sdl::create_rect(
						  screen->w * 3 / 32
						, top_margin
						, screen->w * 13 / 16
						, screen->h - top_margin - bottom_margin);

			text_rect = f.layout(frame_area).interior;

			// update the text area
			text_rect.x += text_left_padding;
			text_rect.w -= text_left_padding;
			text_rect_blit = text_rect;

			text_surf = create_compatible_surface(screen, text_rect.w, text_rect.h);
			SDL_SetAlpha(text_surf, SDL_RLEACCEL, SDL_ALPHA_OPAQUE);

			// relocate the close button
			close.set_location((screen->w/2)-(close.width()/2), screen->h - 30);

			update_dimensions = false;
		}

		if (redraw_mapimage) {
			// draw map to screen, thus erasing all text
			sdl_blit(map_image_scaled, nullptr, screen, nullptr);
			update_rect(screen_rect);

			// redraw the dialog
			f.draw_background();
			f.draw_border();
			// cache the dialog background (alpha blending + blurred map)
			sdl_blit(screen, &text_rect, text_surf, nullptr);
			redraw_mapimage = false;
		} else {
			// redraw the saved part of the dialog where text scrolled
			// thus erasing all text
			SDL_Rect modified = sdl::create_rect(0, 0, max_text_width, text_rect.h);
			sdl_blit(text_surf, &modified, screen, &text_rect_blit);
			update_rect(text_rect);
		}

		int y = text_rect.y - offset;
		int line = startline;
		max_text_width = 0;

		{
			// clip to keep text into the frame (thus the new code block)
			clip_rect_setter set_clip_rect(screen, &text_rect);

			const int line_spacing = 5;
			do {
				// draw the text (with ellipsis if needed)
				// update the max_text_width for future cleaning
				int w = font::draw_text(&video, text_rect, def_size, def_color,
										text[line], text_rect.x, y).w;
				max_text_width = std::max<int>(max_text_width, w);
				// since the real drawing on screen is clipped,
				// we do a dummy one to get the height of the not clipped line.
				// (each time because special format characters may change it)
				const int line_height = font::draw_text(nullptr, text_rect, def_size, def_color,
										text[line], 0,0).h;

				if(is_new_line) {
					is_new_line = false;
					first_line_height = line_height + line_spacing;
				}
				line++;
				if(size_t(line) > text.size()-1)
					line = 0;
				y += line_height + line_spacing;
			} while(y < text_rect.y + text_rect.h);
		}

		// performs the actual scrolling
		offset += scroll_speed;
		if (offset>=first_line_height) {
			offset -= first_line_height;
			is_new_line = true;
			startline++;
			if(size_t(startline) == text.size()){
				startline = 0;
				image_count = -1;
			}
		}

		// handle events
		if (key[SDLK_UP] && scroll_speed < 20) {
			++scroll_speed;
		}
		if (key[SDLK_DOWN] && scroll_speed > 0) {
			--scroll_speed;
		}
		if (screen->w != screen_rect.w || screen->h != screen_rect.h) {
			update_dimensions = true;
		}

		events::pump();
		events::raise_process_event();
		events::raise_draw_event();

		// flip screen and wait, so the text does not scroll too fast
		video.flip();
		CVideo::delay(20);

	} while(!close.pressed() && (last_escape || !key[SDLK_ESCAPE]));
}
コード例 #11
0
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;
}