void part_ui::render_background() { #if SDL_VERSION_ATLEAST(2,0,0) sdl::draw_solid_tinted_rectangle( 0, 0, video_.getx(), video_.gety(), 0, 0, 0, 1.0, video_.getSurface() ); sdl_blit(background_, NULL, video_.getSurface(), NULL); #else #ifdef SDL_GPU GPU_Target *target = get_render_target(); GPU_Clear(target); for (size_t i = 0; i<background_images_.size(); i++) { const int x = background_positions_[i].first; const int y = background_positions_[i].second; background_images_[i].draw(video_, x, y); } #else sdl::draw_solid_tinted_rectangle( 0, 0, video_.getx(), video_.gety(), 0, 0, 0, 1.0, video_.getSurface() ); sdl_blit(background_, NULL, video_.getSurface(), NULL); #endif #endif }
void dialog_frame::draw_background() { if(auto_restore_) { clear_background(); restorer_ = new surface_restorer(&video_, dim_.exterior); } if (dialog_style_.blur_radius) { surface surf = ::get_surface_portion(video_.getSurface(), dim_.exterior); surf = blur_surface(surf, dialog_style_.blur_radius, false); sdl_blit(surf, NULL, video_.getSurface(), &dim_.exterior); } if(bg_ == NULL) { ERR_DP << "could not find dialog background '" << dialog_style_.panel << "'\n"; return; } for(int i = 0; i < dim_.interior.w; i += bg_->w) { for(int j = 0; j < dim_.interior.h; j += bg_->h) { SDL_Rect src = {0,0,0,0}; src.w = std::min(dim_.interior.w - i, bg_->w); src.h = std::min(dim_.interior.h - j, bg_->h); SDL_Rect dst = src; dst.x = dim_.interior.x + i; dst.y = dim_.interior.y + j; sdl_blit(bg_, &src, video_.getSurface(), &dst); } } }
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_fill_rect(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 = create_rect(offset, quarter_size, 0, 0); sdl_blit ( image_fg, NULL, image, &rcDestLeft ); // Blit left side image_bg = scale_surface(image_bg, new_size, new_size); SDL_Rect rcDestRight = create_rect(half_size, quarter_size, 0, 0); sdl_blit ( image_bg, NULL, image, &rcDestRight ); //apply mask so the overlay is contained within the mouseover hex image = mask_surface(image, image::get_hexmask()); // 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); }
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); }
void textbox::draw_contents() { SDL_Rect const &loc = inner_location(); surface surf = video().getSurface(); draw_solid_tinted_rectangle(loc.x,loc.y,loc.w,loc.h,0,0,0, focus(NULL) ? alpha_focus_ : alpha_, surf); SDL_Rect src; if(text_image_ == NULL) { update_text_cache(true); } if(text_image_ != NULL) { src.y = yscroll_; src.w = std::min<size_t>(loc.w,text_image_->w); src.h = std::min<size_t>(loc.h,text_image_->h); src.x = text_pos_; SDL_Rect dest = screen_area(); dest.x = loc.x; dest.y = loc.y; // Fills the selected area if(is_selection()) { const int start = std::min<int>(selstart_,selend_); const int end = std::max<int>(selstart_,selend_); int startx = char_x_[start]; int starty = char_y_[start]; const int endx = char_x_[end]; const int endy = char_y_[end]; while(starty <= endy) { const size_t right = starty == endy ? endx : text_image_->w; if(right <= size_t(startx)) { break; } SDL_Rect rect = create_rect(loc.x + startx , loc.y + starty - src.y , right - startx , line_height_); const clip_rect_setter clipper(surf, &loc); Uint32 color = SDL_MapRGB(surf->format, 0, 0, 160); fill_rect_alpha(rect, color, 140, surf); starty += int(line_height_); startx = 0; } } sdl_blit(text_image_, &src, surf, &dest); } draw_cursor((cursor_pos_ == 0 ? 0 : cursor_pos_ - 1), video()); update_rect(loc); }
void help_text_area::draw_contents() { SDL_Rect const &loc = inner_location(); bg_restore(); surface screen = video().getSurface(); clip_rect_setter clip_rect_set(screen, &loc); for(std::list<item>::const_iterator it = items_.begin(), end = items_.end(); it != end; ++it) { SDL_Rect dst = it->rect; dst.y -= get_position(); if (dst.y < static_cast<int>(loc.h) && dst.y + it->rect.h > 0) { dst.x += loc.x; dst.y += loc.y; if (it->box) { for (int i = 0; i < box_width; ++i) { sdl::draw_rectangle(dst.x, dst.y, it->rect.w - i * 2, it->rect.h - i * 2, 0, screen); ++dst.x; ++dst.y; } } sdl_blit(it->surf, NULL, screen, &dst); } } update_rect(loc); }
void halo_impl::effect::unrender() { if (!surf_ || !buffer_) { return; } // Shrouded haloes are never rendered unless shroud has been re-placed; in // that case, unrendering causes the hidden terrain (and previous halo // frame, when dealing with animated halos) to glitch through shroud. We // don't need to unrender them because shroud paints over the underlying // area anyway. if (loc_.x != -1 && loc_.y != -1 && disp->shrouded(loc_)) { return; } surface& screen = disp->get_screen_surface(); SDL_Rect clip_rect = disp->map_outside_area(); const clip_rect_setter clip_setter(screen, &clip_rect); // Due to scrolling, the location of the rendered halo // might have changed; recalculate const int screenx = disp->get_location_x(map_location::ZERO()); const int screeny = disp->get_location_y(map_location::ZERO()); const int xpos = x_ + screenx - surf_->w/2; const int ypos = y_ + screeny - surf_->h/2; SDL_Rect rect = sdl::create_rect(xpos, ypos, surf_->w, surf_->h); sdl_blit(buffer_,nullptr,screen,&rect); update_rect(rect); }
void unit_palette::draw_item(SDL_Rect& dstrect, const unit_type& u, std::stringstream& tooltip_text) { surface screen = gui_.video().getSurface(); const std::string filename = u.image(); surface image(image::get_image(filename)); if(image == NULL) { tooltip_text << "IMAGE NOT FOUND\n"; ERR_ED << "image for terrain: '" << filename << "' not found\n"; image = image::get_image(game_config::images::missing); if (image == NULL) { ERR_ED << "Placeholder image not found\n"; return; } } if(image->w != item_size_ || image->h != item_size_) { image.assign(scale_surface(image, item_size_, item_size_)); } sdl_blit(image, NULL, screen, &dstrect); tooltip_text << u.type_name(); }
bool part_ui::render_floating_images() { events::raise_draw_event(); update_whole_screen(); skip_ = false; last_key_ = true; size_t fi_n = 0; foreach(floating_image::render_input& ri, imgs_) { const floating_image& fi = p_.get_floating_images()[fi_n]; if(!ri.image.null()) { sdl_blit(ri.image, NULL, video_.getSurface(), &ri.rect); update_rect(ri.rect); } if (!skip_) { int delay = fi.display_delay(), delay_step = 20; for (int i = 0; i != (delay + delay_step - 1) / delay_step; ++i) { if (handle_interface()) return false; if (skip_) break; disp_.delay(std::min<int>(delay_step, delay - i * delay_step)); } } ++fi_n; } return true; }
void part_ui::render_background() { draw_solid_tinted_rectangle( 0, 0, video_.getx(), video_.gety(), 0, 0, 0, 1.0, video_.getSurface() ); sdl_blit(background_, NULL, video_.getSurface(), &base_rect_); }
void CVideo::blit_surface(int x, int y, surface surf, SDL_Rect* srcrect, SDL_Rect* clip_rect) { surface target(getSurface()); SDL_Rect dst = create_rect(x, y, 0, 0); const clip_rect_setter clip_setter(target, clip_rect, clip_rect != NULL); sdl_blit(surf,srcrect,target,&dst); }
surface darken_function::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) sdl_blit(tod_dark, NULL, ret, NULL); return ret; }
surface mask_function::operator()(const surface& src) const { if(src->w == mask_->w && src->h == mask_->h && x_ == 0 && y_ == 0) return mask_surface(src, mask_); SDL_Rect r = create_rect(x_, y_, 0, 0); surface new_mask = create_neutral_surface(src->w, src->h); sdl_blit(mask_, NULL, new_mask, &r); return mask_surface(src, new_mask); }
void surface_restorer::restore() const { if(surface_.null()) { return; } SDL_Rect dst = rect_; sdl_blit(surface_, nullptr, target_->getSurface(), &dst); }
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; }
void part_ui::render_background() { sdl::draw_solid_tinted_rectangle( 0, 0, video_.getx(), video_.gety(), 0, 0, 0, 1.0, video_.getSurface() ); sdl_blit(background_, NULL, video_.getSurface(), NULL); // Render the titlebox over the background render_title_box(); }
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); 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_blit(text_image_,NULL,new_surface,NULL); SDL_Rect target = create_rect(0 , text_image_->h , new_text->w , new_text->h); sdl_blit(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_); }
void surface_restorer::restore(const SDL_Rect& dst) const { if(surface_.null()) { return; } SDL_Rect dst2 = sdl::intersect_rects(dst, rect_); if(dst2.w == 0 || dst2.h == 0) { return; } SDL_Rect src = dst2; src.x -= rect_.x; src.y -= rect_.y; sdl_blit(surface_, &src, target_->getSurface(), &dst2); }
void undraw(surface screen) { if(use_color_cursors() == false) { return; } if(cursor_buf == NULL) { return; } SDL_Rect area = create_rect(cursor_x - shift_x[current_cursor] , cursor_y - shift_y[current_cursor] , cursor_buf->w , cursor_buf->h); sdl_blit(cursor_buf,NULL,screen,&area); update_rect(area); }
void ttrack::impl_draw_background(surface& frame_buffer, int x_offset, int y_offset) { tcontrol::impl_draw_background(frame_buffer, x_offset, y_offset); SDL_Rect rc = get_rect(); if (!background_surf_ || background_surf_->w != w_ || background_surf_->h != h_) { background_surf_.assign(get_surface_portion(frame_buffer, rc)); } else { sdl_blit(frame_buffer, &rc, background_surf_, NULL); } frame_buffer_ = frame_buffer; frame_offset_ = tpoint(x_offset + draw_offset_.x, y_offset + draw_offset_.y); if (callback_timer_) { callback_timer_(*this, frame_buffer, frame_offset_, state2_, false); } }
void floating_label::undraw(surface screen) { if(screen == nullptr || 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_blit(buf_,nullptr,screen,&rect); move(xmove_,ymove_); if(lifetime_ > 0) { --lifetime_; if(alpha_change_ != 0 && (xmove_ != 0.0 || ymove_ != 0.0) && surf_ != nullptr) { // fade out moving floating labels surf_.assign(adjust_surface_alpha_add(surf_,alpha_change_)); } } }
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); }
void tminimap::impl_draw_background(surface& frame_buffer) { if(!terrain_) return; assert(terrain_); DBG_GUI_D << LOG_HEADER << " size " << get_rectangle() << ".\n"; if(map_data_.empty()) { return; } SDL_Rect rect = get_rectangle(); assert(rect.w > 0 && rect.h > 0); const ::surface surf = get_image(rect.w, rect.h); if(surf) { sdl_blit(surf, NULL, frame_buffer, &rect); } }
void effect::unrender() { if (!surf_ || !buffer_) { return; } surface screen = disp->get_screen_surface(); SDL_Rect clip_rect = disp->map_outside_area(); const clip_rect_setter clip_setter(screen, &clip_rect); // Due to scrolling, the location of the rendered halo // might have changed; recalculate const map_location zero_loc(0,0); const int screenx = disp->get_location_x(zero_loc); const int screeny = disp->get_location_y(zero_loc); const int xpos = x_ + screenx - surf_->w/2; const int ypos = y_ + screeny - surf_->h/2; SDL_Rect rect = create_rect(xpos, ypos, surf_->w, surf_->h); sdl_blit(buffer_,NULL,screen,&rect); }
void tminimap::impl_draw_background(surface& frame_buffer, int x_offset, int y_offset) { if(!terrain_) return; assert(terrain_); DBG_GUI_D << LOG_HEADER << " size " << calculate_blitting_rectangle(x_offset, y_offset) << ".\n"; if(map_data_.empty()) { return; } SDL_Rect rect = calculate_blitting_rectangle(x_offset, y_offset); assert(rect.w > 0 && rect.h > 0); const ::surface surf = get_image(rect.w, rect.h); if(surf) { sdl_blit(surf, nullptr, frame_buffer, &rect); } }
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); } }
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; }
bool effect::render() { if(disp == NULL) { return false; } if(loc_.x != -1 && loc_.y != -1) { if(disp->shrouded(loc_)) { return false; } else { // The location of a halo is an x,y value and not a map location. // This means when a map is zoomed, the halo's won't move, // This glitch is most visible on [item] haloes. // This workaround always recalculates the location of the halo // (item haloes have a location parameter to hide them under the shroud) // and reapplies that location. // It might be optimized by storing and comparing the zoom value. set_location( disp->get_location_x(loc_) + disp->hex_size() / 2, disp->get_location_y(loc_) + disp->hex_size() / 2); } } images_.update_last_draw_time(); surf_.assign(image::get_image(current_image(),image::SCALED_TO_ZOOM)); if(surf_ == NULL) { return false; } if(orientation_ == HREVERSE || orientation_ == HVREVERSE) { surf_.assign(image::reverse_image(surf_)); } if(orientation_ == VREVERSE || orientation_ == HVREVERSE) { surf_.assign(flop_surface(surf_)); } const map_location zero_loc(0,0); const int screenx = disp->get_location_x(zero_loc); const int screeny = disp->get_location_y(zero_loc); const int xpos = x_ + screenx - surf_->w/2; const int ypos = y_ + screeny - surf_->h/2; SDL_Rect rect = create_rect(xpos, ypos, surf_->w, surf_->h); rect_ = rect; SDL_Rect clip_rect = disp->map_outside_area(); // If rendered the first time, need to determine the area affected. // If a halo changes size, it is not updated. if(overlayed_hexes_.empty()) { rect_of_hexes hexes = disp->hexes_under_rect(rect); rect_of_hexes::iterator i = hexes.begin(), end = hexes.end(); for (;i != end; ++i) { overlayed_hexes_.push_back(*i); } } if(rects_overlap(rect,clip_rect) == false) { buffer_.assign(NULL); return false; } surface screen = disp->get_screen_surface(); const clip_rect_setter clip_setter(screen, &clip_rect); if(buffer_ == NULL || buffer_->w != rect.w || buffer_->h != rect.h) { SDL_Rect rect = rect_; buffer_.assign(get_surface_portion(screen,rect)); } else { SDL_Rect rect = rect_; sdl_blit(screen,&rect,buffer_,NULL); } sdl_blit(surf_,NULL,screen,&rect); return true; }
void loadscreen::draw_screen(const std::string &text) { // Set progress bar parameters: // // RGB-values for finished piece. int fcr = 21, fcg = 53, fcb = 80; // Groove. int lcr = 21, lcg = 22, lcb = 24; // Border color. int bcr = 188, bcg = 176, bcb = 136; // Border width. int bw = 1; // Border inner spacing width. int bispw = 1; bw = 2*(bw+bispw) > screen_.getx() ? 0: 2*(bw+bispw) > screen_.gety() ? 0: bw; // Available width. int scrx = screen_.getx() - 2*(bw+bispw); // Available height. int scry = screen_.gety() - 2*(bw+bispw); // Used width. int pbw = scrx/2; // Used height. int pbh = scry/16; // Height of the lighting line. int lightning_thickness = 2; surface gdis = screen_.getSurface(); SDL_Rect area; // Pump events and make sure to redraw the logo if there's a chance that it's been obscured SDL_Event ev; while(SDL_PollEvent(&ev)) { #if SDL_VERSION_ATLEAST(2, 0, 0) if(ev.type == SDL_WINDOWEVENT && (ev.window.event == SDL_WINDOWEVENT_RESIZED || ev.window.event == SDL_WINDOWEVENT_EXPOSED)) #else if(ev.type == SDL_VIDEORESIZE || ev.type == SDL_VIDEOEXPOSE) #endif { logo_drawn_ = false; } } // Draw logo if it was successfully loaded. #if SDL_VERSION_ATLEAST(2,0,0) static int angle = 0; if (!logo_texture_.null() /*&& !logo_drawn_*/) { int x = (screen_.getx () - logo_texture_.width()) / 2; int y = ((scry - logo_texture_.height()) / 2) - pbh; // Check if we have enough pixels to display it. if (x > 0 && y > 0) { pby_offset_ = (pbh + logo_texture_.height())/2; CVideo::get_window()->draw(logo_texture_, x, y); } else { if (!screen_.faked()) { // Avoid error if --nogui is used. ERR_DP << "loadscreen: Logo image is too big." << std::endl; } } logo_drawn_ = true; logo_texture_.set_rotation(angle+=3); } #else if (logo_surface_ && !logo_drawn_) { area.x = (screen_.getx () - logo_surface_->w) / 2; area.y = ((scry - logo_surface_->h) / 2) - pbh; area.w = logo_surface_->w; area.h = logo_surface_->h; // Check if we have enough pixels to display it. if (area.x > 0 && area.y > 0) { pby_offset_ = (pbh + area.h)/2; sdl_blit(logo_surface_, 0, gdis, &area); } else { if (!screen_.faked()) { // Avoid error if --nogui is used. ERR_DP << "loadscreen: Logo image is too big." << std::endl; } } logo_drawn_ = true; update_rect(area.x, area.y, area.w, area.h); } #endif int pbx = (scrx - pbw)/2; // Horizontal location. int pby = (scry - pbh)/2 + pby_offset_; // Vertical location. // Draw top border. area.x = pbx; area.y = pby; area.w = pbw + 2*(bw+bispw); area.h = bw; sdl::fill_rect(gdis,&area,SDL_MapRGB(gdis->format,bcr,bcg,bcb)); // Draw bottom border. area.x = pbx; area.y = pby + pbh + bw + 2*bispw; area.w = pbw + 2*(bw+bispw); area.h = bw; sdl::fill_rect(gdis,&area,SDL_MapRGB(gdis->format,bcr,bcg,bcb)); // Draw left border. area.x = pbx; area.y = pby + bw; area.w = bw; area.h = pbh + 2*bispw; sdl::fill_rect(gdis,&area,SDL_MapRGB(gdis->format,bcr,bcg,bcb)); // Draw right border. area.x = pbx + pbw + bw + 2*bispw; area.y = pby + bw; area.w = bw; area.h = pbh + 2*bispw; sdl::fill_rect(gdis,&area,SDL_MapRGB(gdis->format,bcr,bcg,bcb)); // Draw the finished bar area. area.x = pbx + bw + bispw; area.y = pby + bw + bispw; area.w = (prcnt_ * pbw) / 100; area.h = pbh; sdl::fill_rect(gdis,&area,SDL_MapRGB(gdis->format,fcr,fcg,fcb)); SDL_Rect lightning = area; lightning.h = lightning_thickness; //we add 25% of white to the color of the bar to simulate a light effect sdl::fill_rect(gdis,&lightning,SDL_MapRGB(gdis->format,(fcr*3+255)/4,(fcg*3+255)/4,(fcb*3+255)/4)); lightning.y = area.y+area.h-lightning.h; //remove 50% of color to simulate a shadow effect sdl::fill_rect(gdis,&lightning,SDL_MapRGB(gdis->format,fcr/2,fcg/2,fcb/2)); // Draw the leftover bar area. area.x = pbx + bw + bispw + (prcnt_ * pbw) / 100; area.y = pby + bw + bispw; area.w = ((100 - prcnt_) * pbw) / 100; area.h = pbh; sdl::fill_rect(gdis,&area,SDL_MapRGB(gdis->format,lcr,lcg,lcb)); // Clear the last text and draw new if text is provided. if (!text.empty()) { SDL_Rect oldarea = textarea_; sdl::fill_rect(gdis,&textarea_,SDL_MapRGB(gdis->format,0,0,0)); textarea_ = font::line_size(text, font::SIZE_NORMAL); textarea_.x = scrx/2 + bw + bispw - textarea_.w / 2; textarea_.y = pby + pbh + 4*(bw + bispw); textarea_ = font::draw_text(&screen_,textarea_,font::SIZE_NORMAL,font::NORMAL_COLOR,text,textarea_.x,textarea_.y); SDL_Rect refresh = sdl::union_rects(oldarea, textarea_); update_rect(refresh.x, refresh.y, refresh.w, refresh.h); } // Update the rectangle. update_rect(pbx, pby, pbw + 2*(bw + bispw), pbh + 2*(bw + bispw)); screen_.flip(); #if SDL_VERSION_ATLEAST(2,0,0) CVideo::get_window()->render(); #endif }
surface floating_label::create_surface() { if(surf_.null()) { font::pango_text text; text.set_foreground_color(color_); text.set_font_size(font_size_); text.set_maximum_width(width_ < 0 ? clip_rect_.w : width_); text.set_maximum_height(height_ < 0 ? clip_rect_.h : height_, true); // ignore last '\n' if(!text_.empty() && *(text_.rbegin()) == '\n') { text.set_text(std::string(text_.begin(), text_.end() - 1), use_markup_); } else { text.set_text(text_, use_markup_); } surface foreground = text.render(); if(foreground == nullptr) { ERR_FT << "could not create floating label's text" << std::endl; return nullptr; } // combine foreground text with its background if(bgalpha_ != 0) { // background is a dark tooltip box surface background = create_neutral_surface(foreground->w + border_ * 2, foreground->h + border_ * 2); if(background == nullptr) { ERR_FT << "could not create tooltip box" << std::endl; return surf_ = foreground; } uint32_t color = SDL_MapRGBA(foreground->format, bgcolor_.r, bgcolor_.g, bgcolor_.b, bgalpha_); sdl::fill_surface_rect(background, nullptr, color); // we make the text less transparent, because the blitting on the // dark background will darken the anti-aliased part. // This 1.13 value seems to restore the brightness of version 1.4 // (where the text was blitted directly on screen) adjust_surface_alpha(foreground, ftofxp(1.13)); SDL_Rect r{border_, border_, 0, 0}; adjust_surface_alpha(foreground, SDL_ALPHA_OPAQUE); sdl_blit(foreground, nullptr, background, &r); surf_ = background; } else { // background is blurred shadow of the text surface background = create_neutral_surface(foreground->w + 4, foreground->h + 4); sdl::fill_surface_rect(background, nullptr, 0); SDL_Rect r{2, 2, 0, 0}; sdl_blit(foreground, nullptr, background, &r); background = shadow_image(background); if(background == nullptr) { ERR_FT << "could not create floating label's shadow" << std::endl; return surf_ = foreground; } sdl_blit(foreground, nullptr, background, &r); surf_ = background; } } return surf_; }