Fix floating labels for SDL_gpu.

This commit is contained in:
Boldizsár Lipka 2014-08-08 01:29:50 +02:00
parent 04232d57ca
commit 731e91c0c0
4 changed files with 160 additions and 7 deletions

View file

@ -1392,8 +1392,11 @@ void display::flip()
sdl::fill_rect_alpha(r, color, 1, frameBuffer);
update_rect(r);
}
#ifdef SDL_GPU
font::draw_floating_labels(screen_);
#else
font::draw_floating_labels(frameBuffer);
#endif
events::raise_volatile_draw_event();
cursor::draw(frameBuffer);

View file

@ -918,7 +918,12 @@ std::stack<std::set<int> > label_contexts;
namespace font {
floating_label::floating_label(const std::string& text)
: surf_(NULL), buf_(NULL), text_(text),
#ifdef SDL_GPU
: img_(),
#else
: surf_(NULL), buf_(NULL),
#endif
text_(text),
font_size_(SIZE_NORMAL),
color_(NORMAL_COLOR), bgcolor_(), bgalpha_(0),
xpos_(0), ypos_(0),
@ -947,6 +952,80 @@ int floating_label::xpos(size_t width) const
return xpos;
}
#ifdef SDL_GPU
sdl::timage floating_label::create_image()
{
if (img_.null()) {
font::ttext text;
text.set_foreground_color((color_.r << 24) | (color_.g << 16) | (color_.b << 8) | 255);
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 == NULL) {
ERR_FT << "could not create floating label's text" << std::endl;
return sdl::timage();
}
// 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 == NULL) {
ERR_FT << "could not create tooltip box" << std::endl;
img_ = sdl::timage(foreground);
return img_;
}
Uint32 color = SDL_MapRGBA(foreground->format, bgcolor_.r,bgcolor_.g, bgcolor_.b, bgalpha_);
sdl::fill_rect(background,NULL, 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)
foreground = adjust_surface_alpha(foreground, ftofxp(1.13), false);
SDL_Rect r = sdl::create_rect( border_, border_, 0, 0);
SDL_SetAlpha(foreground,SDL_SRCALPHA,SDL_ALPHA_OPAQUE);
blit_surface(foreground, NULL, background, &r);
img_ = sdl::timage(background);
}
else {
// background is blurred shadow of the text
surface background = create_neutral_surface
(foreground->w + 4, foreground->h + 4);
sdl::fill_rect(background, NULL, 0);
SDL_Rect r = { 2, 2, 0, 0 };
blit_surface(foreground, NULL, background, &r);
background = shadow_image(background, false);
if (background == NULL) {
ERR_FT << "could not create floating label's shadow" << std::endl;
img_ = sdl::timage(foreground);
return img_;
}
SDL_SetAlpha(foreground,SDL_SRCALPHA,SDL_ALPHA_OPAQUE);
blit_surface(foreground, NULL, background, &r);
img_ = sdl::timage(background);
}
}
return img_;
}
#else
surface floating_label::create_surface()
{
if (surf_.null()) {
@ -1021,7 +1100,23 @@ surface floating_label::create_surface()
return surf_;
}
#endif
#ifdef SDL_GPU
void floating_label::draw(CVideo &video)
{
if (!visible_) {
return;
}
create_image();
if (img_.null()) {
return;
}
video.draw_texture(img_, xpos(img_.width()), int(ypos_));
}
#else
void floating_label::draw(surface screen)
{
if(!visible_) {
@ -1052,13 +1147,17 @@ void floating_label::draw(surface screen)
update_rect(rect);
}
#endif
#ifdef SDL_GPU
// No undrawing for SDL_gpu, it won't be necessary once z-order is implemented
void floating_label::undraw(surface) {}
#else
void floating_label::undraw(surface screen)
{
if(screen == NULL || buf_ == NULL) {
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_,NULL,screen,&rect);
@ -1075,6 +1174,7 @@ void floating_label::undraw(surface screen)
}
}
}
#endif
int add_floating_label(const floating_label& flabel)
{
@ -1128,18 +1228,29 @@ void show_floating_label(int handle, bool value)
SDL_Rect get_floating_label_rect(int handle)
{
const label_map::iterator i = labels.find(handle);
#ifdef SDL_GPU
if(i != labels.end()) {
const sdl::timage img = i->second.create_image();
if(!img.null()) {
return sdl::create_rect(0, 0, img.width(), img.height());
}
}
#else
if(i != labels.end()) {
const surface surf = i->second.create_surface();
if(surf != NULL) {
return sdl::create_rect(0, 0, surf->w, surf->h);
}
}
#endif
return sdl::empty_rect;
}
floating_label_context::floating_label_context()
{
#ifdef SDL_GPU
#else
#if SDL_VERSION_ATLEAST(2, 0, 0)
surface const screen = NULL;
#else
@ -1148,6 +1259,7 @@ floating_label_context::floating_label_context()
if(screen != NULL) {
draw_floating_labels(screen);
}
#endif
label_contexts.push(std::set<int>());
}
@ -1171,6 +1283,24 @@ floating_label_context::~floating_label_context()
}
}
#ifdef SDL_GPU
void draw_floating_labels(CVideo &video)
{
if(label_contexts.empty()) {
return;
}
const std::set<int>& context = label_contexts.top();
//draw the labels in the order they were added, so later added labels (likely to be tooltips)
//are displayed over earlier added labels.
for(label_map::iterator i = labels.begin(); i != labels.end(); ++i) {
if(context.count(i->first) > 0) {
i->second.draw(video);
}
}
}
#else
void draw_floating_labels(surface screen)
{
if(label_contexts.empty()) {
@ -1187,6 +1317,7 @@ void draw_floating_labels(surface screen)
}
}
}
#endif
void undraw_floating_labels(surface screen)
{

View file

@ -17,6 +17,7 @@
#include "exceptions.hpp"
#include "sdl/utils.hpp"
#include "sdl/image.hpp"
#include <SDL_ttf.h>
@ -153,11 +154,18 @@ public:
void use_markup(bool b) {use_markup_ = b;}
void move(double xmove, double ymove);
#ifdef SDL_GPU
void draw(CVideo &video);
#else
void draw(surface screen);
#endif
void undraw(surface screen);
#ifdef SDL_GPU
sdl::timage create_image();
#else
surface create_surface();
#endif
bool expired() const { return lifetime_ == 0; }
@ -168,8 +176,11 @@ public:
private:
int xpos(size_t width) const;
#ifdef SDL_GPU
sdl::timage img_;
#else
surface surf_, buf_;
#endif
std::string text_;
int font_size_;
SDL_Color color_, bgcolor_;
@ -206,8 +217,12 @@ void remove_floating_label(int handle);
void show_floating_label(int handle, bool show);
SDL_Rect get_floating_label_rect(int handle);
#ifdef SDL_GPU
void draw_floating_labels(CVideo &video);
#else
void draw_floating_labels(surface screen);
#endif
void undraw_floating_labels(surface screen);
bool load_font_config();

View file

@ -727,7 +727,11 @@ void twindow::draw()
SDL_Rect rect = get_rectangle();
// We want the labels underneath the window so draw them and use them
// as restore point.
#ifdef SDL_GPU
font::draw_floating_labels(video_);
#else
font::draw_floating_labels(frame_buffer);
#endif
restorer_ = get_surface_portion(frame_buffer, rect);
// Need full redraw so only set ourselves dirty.