void part_ui::render_story_box_borders(SDL_Rect& update_area) { const part::BLOCK_LOCATION tbl = p_.story_text_location(); if(has_background_) { surface border_top = NULL; surface border_bottom = NULL; if(tbl == part::BLOCK_BOTTOM || tbl == part::BLOCK_MIDDLE) { border_top = image::get_image(storybox_top_border_path); } if(tbl == part::BLOCK_TOP || tbl == part::BLOCK_MIDDLE) { border_bottom = image::get_image(storybox_bottom_border_path); } // // If one of those are null at this point, it means that either we // don't need that border pic, or it is missing (in such case get_image() // would report). // if(border_top.null() != true) { if((border_top = scale_surface_blended(border_top, screen_area().w, border_top->h)).null()) { WARN_NG << "storyscreen got a null top border surface after rescaling\n"; } else { update_area.y -= border_top->h; update_area.h += border_top->h; blur_area(video_, update_area.y, border_top->h); video_.blit_surface(0, update_area.y, border_top); } } if(border_bottom.null() != true) { if((border_bottom = scale_surface_blended(border_bottom, screen_area().w, border_bottom->h)).null()) { WARN_NG << "storyscreen got a null bottom border surface after rescaling\n"; } else { blur_area(video_, update_area.h, border_bottom->h); video_.blit_surface(0, update_area.y+update_area.h, border_bottom); update_area.h += border_bottom->h; } } } }
void part_ui::render_story_box() { #ifdef SDL_GPU LOG_NG << "ENTER part_ui()::render_story_box()\n"; GPU_Target *target = get_render_target(); const std::string& storytxt = p_.text(); if(storytxt.empty()) { video_.flip(); wait_for_input(); return; } const part::BLOCK_LOCATION tbl = p_.story_text_location(); const int max_width = buttons_x_ - storybox_padding - text_x_; const int max_height = screen_area().h - storybox_padding; skip_ = false; last_key_ = true; font::ttext t; if(!t.set_text(p_.text(), true)) { ERR_NG << "Text: Invalid markup in '" << p_.text() << "' rendered as is.\n"; t.set_text(p_.text(), false); } t.set_font_style(font::ttext::STYLE_NORMAL) .set_font_size(storybox_font_size) .set_foreground_color(storybox_font_color) .set_maximum_width(max_width) .set_maximum_height(max_height, true); sdl::timage txttxt = t.render_as_texture(); if(txttxt.null()) { ERR_NG << "storyscreen text area rendering resulted in a null texture" << std::endl; return; } int fix_text_y = text_y_; if(fix_text_y + 2*(storybox_padding+1) + txttxt.height() > screen_area().h && tbl != part::BLOCK_TOP) { fix_text_y = (screen_area().h > txttxt.height() + 1) ? (std::max(0, screen_area().h - txttxt.height() - 2*(storybox_padding+1))) : (0); } int fix_text_h; switch(tbl) { case part::BLOCK_TOP: fix_text_h = std::max(txttxt.height() + 2*storybox_padding, screen_area().h/4); break; case part::BLOCK_MIDDLE: fix_text_h = std::max(txttxt.height() + 2*storybox_padding, screen_area().h/3); break; default: fix_text_h = screen_area().h - fix_text_y; break; } SDL_Rect update_area = sdl::create_rect(0 , fix_text_y , screen_area().w , fix_text_h); /* do */ { // this should kill the tiniest flickering caused // by the buttons being hidden and unhidden in this scope. update_locker locker(video_); next_button_.hide(); back_button_.hide(); play_button_.hide(); //TODO: blurring const SDL_Rect box = sdl::create_rect(0, fix_text_y, screen_area().w, fix_text_h); sdl::fill_rect(*target, box, storyshadow_r, storyshadow_g, storyshadow_b, storyshadow_a); render_story_box_borders(update_area); // no-op if LOW_MEM is defined next_button_.hide(false); back_button_.hide(false); play_button_.hide(false); } // Time to do some f*****g visual effect. const int scan_height = 1, scan_width = txttxt.width(); SDL_Rect scan = sdl::create_rect(0, 0, scan_width, scan_height); SDL_Rect dstrect = sdl::create_rect(text_x_, 0, scan_width, scan_height); bool scan_finished = false; while(true) { scan_finished = scan.y >= txttxt.base_height(); if (!scan_finished) { dstrect.y = fix_text_y + scan.y + storybox_padding; txttxt.set_clip(scan); video_.draw_texture(txttxt, dstrect.x, dstrect.y); video_.flip(); ++scan.y; } else skip_ = true; if (handle_interface()) break; if (!skip_ || scan_finished) { disp_.delay(20); } } const SDL_Rect rect = sdl::create_rect(0, 0, video_.getx(), video_.gety()); sdl::fill_rect(*target, rect, 0, 0, 0, 255); #else LOG_NG << "ENTER part_ui()::render_story_box()\n"; const std::string& storytxt = p_.text(); if(storytxt.empty()) { update_whole_screen(); wait_for_input(); return; } const part::BLOCK_LOCATION tbl = p_.story_text_location(); const int max_width = buttons_x_ - storybox_padding - text_x_; const int max_height = screen_area().h - storybox_padding; skip_ = false; last_key_ = true; font::ttext t; if(!t.set_text(p_.text(), true)) { ERR_NG << "Text: Invalid markup in '" << p_.text() << "' rendered as is.\n"; t.set_text(p_.text(), false); } t.set_font_style(font::ttext::STYLE_NORMAL) .set_font_size(storybox_font_size) .set_foreground_color(storybox_font_color) .set_maximum_width(max_width) .set_maximum_height(max_height, true); surface txtsurf = t.render(); if(txtsurf.null()) { ERR_NG << "storyscreen text area rendering resulted in a null surface" << std::endl; return; } int fix_text_y = text_y_; if(fix_text_y + 2*(storybox_padding+1) + txtsurf->h > screen_area().h && tbl != part::BLOCK_TOP) { fix_text_y = (screen_area().h > txtsurf->h + 1) ? (std::max(0, screen_area().h - txtsurf->h - 2*(storybox_padding+1))) : (0); } int fix_text_h; switch(tbl) { case part::BLOCK_TOP: fix_text_h = std::max(txtsurf->h + 2*storybox_padding, screen_area().h/4); break; case part::BLOCK_MIDDLE: fix_text_h = std::max(txtsurf->h + 2*storybox_padding, screen_area().h/3); break; default: fix_text_h = screen_area().h - fix_text_y; break; } SDL_Rect update_area = sdl::create_rect(0 , fix_text_y , screen_area().w , fix_text_h); /* do */ { // this should kill the tiniest flickering caused // by the buttons being hidden and unhidden in this scope. update_locker locker(video_); next_button_.hide(); back_button_.hide(); play_button_.hide(); #ifndef LOW_MEM blur_area(video_, fix_text_y, fix_text_h); #endif sdl::draw_solid_tinted_rectangle( 0, fix_text_y, screen_area().w, fix_text_h, storyshadow_r, storyshadow_g, storyshadow_b, storyshadow_opacity, video_.getSurface() ); render_story_box_borders(update_area); // no-op if LOW_MEM is defined next_button_.hide(false); back_button_.hide(false); play_button_.hide(false); } if(imgs_.empty()) { update_whole_screen(); } else if(update_area.h > 0) { update_rect(update_area); } // Time to do some f*****g visual effect. const int scan_height = 1, scan_width = txtsurf->w; SDL_Rect scan = sdl::create_rect(0, 0, scan_width, scan_height); SDL_Rect dstrect = sdl::create_rect(text_x_, 0, scan_width, scan_height); surface scan_dst = video_.getSurface(); bool scan_finished = false; while(true) { scan_finished = scan.y >= txtsurf->h; if (!scan_finished) { //dstrect.x = text_x_; dstrect.y = fix_text_y + scan.y + storybox_padding; // NOTE: ::blit_surface() screws up with antialiasing and hinting when // on backgroundless (e.g. black) screens; ttext::draw() // uses it nonetheless, no idea why... // Here we'll use CVideo::blit_surface() instead. video_.blit_surface(dstrect.x, dstrect.y, txtsurf, &scan); update_rect(dstrect); ++scan.y; } else skip_ = true; if (handle_interface()) break; if (!skip_ || scan_finished) { disp_.delay(20); } } sdl::draw_solid_tinted_rectangle( 0, 0, video_.getx(), video_.gety(), 0, 0, 0, 1.0, video_.getSurface() ); #endif }
void part_ui::render_story_box_borders(SDL_Rect& update_area) { #ifdef SDL_GPU const part::BLOCK_LOCATION tbl = p_.story_text_location(); if(has_background_) { sdl::timage border_top; sdl::timage border_bottom; if(tbl == part::BLOCK_BOTTOM || tbl == part::BLOCK_MIDDLE) { border_top = image::get_texture(storybox_top_border_path); } if(tbl == part::BLOCK_TOP || tbl == part::BLOCK_MIDDLE) { border_bottom = image::get_texture(storybox_bottom_border_path); } // // If one of those are null at this point, it means that either we // don't need that border pic, or it is missing (in such case get_image() // would report). // if(border_top.null() != true) { const float xscale = float(screen_area().w) / border_top.base_width(); border_top.set_hscale(xscale); //TODO: blurring video_.draw_texture(border_top, 0, update_area.y - border_top.base_height()); } if(border_bottom.null() != true) { const float xscale = float(screen_area().w) / border_bottom.base_width(); border_bottom.set_hscale(xscale); //TODO: blurring video_.draw_texture(border_bottom, 0, update_area.y - border_top.base_height()); } } #else const part::BLOCK_LOCATION tbl = p_.story_text_location(); if(has_background_) { surface border_top = NULL; surface border_bottom = NULL; if(tbl == part::BLOCK_BOTTOM || tbl == part::BLOCK_MIDDLE) { border_top = image::get_image(storybox_top_border_path); } if(tbl == part::BLOCK_TOP || tbl == part::BLOCK_MIDDLE) { border_bottom = image::get_image(storybox_bottom_border_path); } // // If one of those are null at this point, it means that either we // don't need that border pic, or it is missing (in such case get_image() // would report). // if(border_top.null() != true) { if((border_top = scale_surface(border_top, screen_area().w, border_top->h)).null()) { WARN_NG << "storyscreen got a null top border surface after rescaling" << std::endl; } else { update_area.y -= border_top->h; update_area.h += border_top->h; blur_area(video_, update_area.y, border_top->h); video_.blit_surface(0, update_area.y, border_top); } } if(border_bottom.null() != true) { if((border_bottom = scale_surface(border_bottom, screen_area().w, border_bottom->h)).null()) { WARN_NG << "storyscreen got a null bottom border surface after rescaling" << std::endl; } else { blur_area(video_, update_area.h, border_bottom->h); video_.blit_surface(0, update_area.y+update_area.h, border_bottom); update_area.h += border_bottom->h; } } } #endif }