move class floating_label from font.cpp to its own file

floating_label is essentially a primitive GUI1 widget, consisting
just of a text label and non-interacting. It's also used for the
map labels displayed in-game iiuc.
This commit is contained in:
Chris Beck 2015-03-07 21:22:03 -05:00
parent 1bc7471822
commit ea212b5bc2
18 changed files with 672 additions and 604 deletions

View file

@ -1044,6 +1044,7 @@ set(libwesnoth-game_STAT_SRC
display.cpp
display_context.cpp
events.cpp
floating_label.cpp
font.cpp
format_time_summary.cpp
generators/cave_map_generator.cpp

View file

@ -80,6 +80,7 @@ libwesnoth_sources = Split("""
display.cpp
display_context.cpp
events.cpp
floating_label.cpp
format_time_summary.cpp
generic_event.cpp
hotkey/hotkey_item.cpp

View file

@ -17,7 +17,7 @@
#include "desktop/notifications.hpp"
#include "display.hpp"
#include "font.hpp"
#include "floating_label.hpp"
#include "game_board.hpp" // <-- only needed for is_observer()
#include "game_preferences.hpp"
#include "log.hpp"

509
src/floating_label.cpp Normal file
View file

@ -0,0 +1,509 @@
/*
Copyright (C) 2003 by David White <dave@whitevine.net>
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
#include "floating_label.hpp"
#include "display.hpp"
#include "font.hpp"
#include "log.hpp"
#include "text.hpp"
#include <map>
#include <set>
#include <stack>
static lg::log_domain log_font("font");
#define DBG_FT LOG_STREAM(debug, log_font)
#define LOG_FT LOG_STREAM(info, log_font)
#define WRN_FT LOG_STREAM(warn, log_font)
#define ERR_FT LOG_STREAM(err, log_font)
namespace {
typedef std::map<int, font::floating_label> label_map;
label_map labels;
int label_id = 1;
std::stack<std::set<int> > label_contexts;
}
namespace font {
floating_label::floating_label(const std::string& text, const surface& surf)
#if 0
: img_(),
#else
: surf_(surf), buf_(NULL),
#endif
text_(text),
font_size_(SIZE_NORMAL),
color_(NORMAL_COLOR), bgcolor_(), bgalpha_(0),
xpos_(0), ypos_(0),
xmove_(0), ymove_(0), lifetime_(-1),
width_(-1), height_(-1),
clip_rect_(screen_area()),
alpha_change_(0), visible_(true), align_(CENTER_ALIGN),
border_(0), scroll_(ANCHOR_LABEL_SCREEN), use_markup_(true)
{}
void floating_label::move(double xmove, double ymove)
{
xpos_ += xmove;
ypos_ += ymove;
}
int floating_label::xpos(size_t width) const
{
int xpos = int(xpos_);
if(align_ == font::CENTER_ALIGN) {
xpos -= width/2;
} else if(align_ == font::RIGHT_ALIGN) {
xpos -= width;
}
return xpos;
}
#if 0
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()) {
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 NULL;
}
// 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;
surf_ = create_optimized_surface(foreground);
return surf_;
}
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);
surf_ = create_optimized_surface(background);
// RLE compression seems less efficient for big semi-transparent area
// so, remove it for this case, but keep the optimized display format
SDL_SetAlpha(surf_,SDL_SRCALPHA,SDL_ALPHA_OPAQUE);
}
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;
surf_ = create_optimized_surface(foreground);
return surf_;
}
SDL_SetAlpha(foreground,SDL_SRCALPHA,SDL_ALPHA_OPAQUE);
blit_surface(foreground, NULL, background, &r);
surf_ = create_optimized_surface(background);
}
}
return surf_;
}
#endif
#ifdef SDL_GPU
void floating_label::draw(CVideo &video)
{
if (!visible_) {
return;
}
#if 0
create_image();
if (img_.null()) {
return;
}
video.draw_texture(img_, xpos(img_.width()), int(ypos_));
#else
create_surface();
if (surf_.null()) {
return;
}
video.blit_to_overlay(surf_, xpos(surf_->w), int(ypos_));
#endif
}
#else
void floating_label::draw(surface screen)
{
if(!visible_) {
buf_.assign(NULL);
return;
}
create_surface();
if(surf_ == NULL) {
return;
}
if(buf_ == NULL) {
buf_.assign(create_compatible_surface(screen, surf_->w, surf_->h));
if(buf_ == NULL) {
return;
}
}
if(screen == 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(screen,&rect,buf_,NULL);
sdl_blit(surf_,NULL,screen,&rect);
update_rect(rect);
}
#endif
#ifdef SDL_GPU
void floating_label::undraw(CVideo &video)
{
SDL_Rect r = sdl::create_rect(xpos(surf_->w), ypos_, surf_->w, surf_->h);
video.clear_overlay_area(r);
}
#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);
update_rect(rect);
move(xmove_,ymove_);
if(lifetime_ > 0) {
--lifetime_;
if(alpha_change_ != 0 && (xmove_ != 0.0 || ymove_ != 0.0) && surf_ != NULL) {
// fade out moving floating labels
// note that we don't optimize these surfaces since they will always change
surf_.assign(adjust_surface_alpha_add(surf_,alpha_change_,false));
}
}
}
#endif
int add_floating_label(const floating_label& flabel)
{
if(label_contexts.empty()) {
return 0;
}
++label_id;
labels.insert(std::pair<int, floating_label>(label_id, flabel));
label_contexts.top().insert(label_id);
return label_id;
}
void move_floating_label(int handle, double xmove, double ymove)
{
const label_map::iterator i = labels.find(handle);
if(i != labels.end()) {
i->second.move(xmove,ymove);
}
}
void scroll_floating_labels(double xmove, double ymove)
{
for(label_map::iterator i = labels.begin(); i != labels.end(); ++i) {
if(i->second.scroll() == ANCHOR_LABEL_MAP) {
i->second.move(xmove,ymove);
}
}
}
void remove_floating_label(int handle)
{
const label_map::iterator i = labels.find(handle);
if(i != labels.end()) {
if(label_contexts.empty() == false) {
label_contexts.top().erase(i->first);
}
labels.erase(i);
}
}
void show_floating_label(int handle, bool value)
{
const label_map::iterator i = labels.find(handle);
if(i != labels.end()) {
i->second.show(value);
}
}
SDL_Rect get_floating_label_rect(int handle)
{
const label_map::iterator i = labels.find(handle);
#if 0
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
surface const screen = SDL_GetVideoSurface();
#endif
if(screen != NULL) {
draw_floating_labels(screen);
}
#endif
label_contexts.push(std::set<int>());
}
floating_label_context::~floating_label_context()
{
const std::set<int>& labels = label_contexts.top();
for(std::set<int>::const_iterator i = labels.begin(); i != labels.end(); ) {
remove_floating_label(*i++);
}
label_contexts.pop();
#ifdef SDL_GPU
//TODO
#else
#if SDL_VERSION_ATLEAST(2, 0, 0)
surface const screen = NULL;
#else
surface const screen = SDL_GetVideoSurface();
#endif
if(screen != NULL) {
undraw_floating_labels(screen);
}
#endif
}
#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);
}
}
}
void undraw_floating_labels(CVideo &video)
{
if(label_contexts.empty()) {
return;
}
std::set<int>& context = label_contexts.top();
//remove expired labels
for(label_map::iterator j = labels.begin(); j != labels.end(); ) {
if(context.count(j->first) > 0 && j->second.expired()) {
j->second.undraw(video);
context.erase(j->first);
labels.erase(j++);
} else {
++j;
}
}
}
#else
void draw_floating_labels(surface screen)
{
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(screen);
}
}
}
void undraw_floating_labels(surface screen)
{
if(label_contexts.empty()) {
return;
}
std::set<int>& context = label_contexts.top();
//undraw labels in reverse order, so that a LIFO process occurs, and the screen is restored
//into the exact state it started in.
for(label_map::reverse_iterator i = labels.rbegin(); i != labels.rend(); ++i) {
if(context.count(i->first) > 0) {
i->second.undraw(screen);
}
}
//remove expired labels
for(label_map::iterator j = labels.begin(); j != labels.end(); ) {
if(context.count(j->first) > 0 && j->second.expired()) {
context.erase(j->first);
labels.erase(j++);
} else {
++j;
}
}
}
#endif
}

149
src/floating_label.hpp Normal file
View file

@ -0,0 +1,149 @@
/*
Copyright (C) 2003 by David White <dave@whitevine.net>
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
#pragma once
#include "font.hpp"
#include "sdl/utils.hpp"
#include <string>
namespace font {
/// structure which will hide all current floating labels, and cause floating labels
/// instantiated after it is created to be displayed
struct floating_label_context
{
floating_label_context();
~floating_label_context();
};
enum ALIGN { LEFT_ALIGN, CENTER_ALIGN, RIGHT_ALIGN };
enum LABEL_SCROLL_MODE { ANCHOR_LABEL_SCREEN, ANCHOR_LABEL_MAP };
class floating_label
{
public:
floating_label(const std::string& text, const surface& surface = NULL);
void set_font_size(int font_size) {font_size_ = font_size;}
// set the location on the screen to display the text.
void set_position(double xpos, double ypos){
xpos_ = xpos;
ypos_ = ypos;
}
// set the amount to move the text each frame
void set_move(double xmove, double ymove){
xmove_ = xmove;
ymove_ = ymove;
}
// set the number of frames to display the text for, or -1 to display until removed
void set_lifetime(int lifetime) {
lifetime_ = lifetime;
alpha_change_ = -255 / lifetime_;
}
void set_color(const SDL_Color& color) {color_ = color;}
void set_bg_color(const SDL_Color& bg_color) {
bgcolor_ = bg_color;
#if SDL_VERSION_ATLEAST(2,0,0)
bgalpha_ = bg_color.a;
#else
bgalpha_ = bg_color.unused;
#endif
}
void set_border_size(int border) {border_ = border;}
// set width for word wrapping (use -1 to disable it)
void set_width(int w) {width_ = w;}
void set_height(int h) { height_ = h; }
void set_clip_rect(const SDL_Rect& r) {clip_rect_ = r;}
void set_alignment(ALIGN align) {align_ = align;}
void set_scroll_mode(LABEL_SCROLL_MODE scroll) {scroll_ = scroll;}
void use_markup(bool b) {use_markup_ = b;}
void move(double xmove, double ymove);
#ifdef SDL_GPU
void draw(CVideo &video);
void undraw(CVideo &video);
#else
void draw(surface screen);
void undraw(surface screen);
#endif
#if 0
sdl::timage create_image();
#else
surface create_surface();
#endif
bool expired() const { return lifetime_ == 0; }
void show(const bool value) { visible_ = value; }
LABEL_SCROLL_MODE scroll() const { return scroll_; }
private:
int xpos(size_t width) const;
#if 0
sdl::timage img_;
#else
surface surf_, buf_;
#endif
std::string text_;
int font_size_;
SDL_Color color_, bgcolor_;
int bgalpha_;
double xpos_, ypos_, xmove_, ymove_;
int lifetime_;
int width_, height_;
SDL_Rect clip_rect_;
int alpha_change_;
bool visible_;
font::ALIGN align_;
int border_;
LABEL_SCROLL_MODE scroll_;
bool use_markup_;
};
/// add a label floating on the screen above everything else.
/// @returns a handle to the label which can be used with other label functions
int add_floating_label(const floating_label& flabel);
/// moves the floating label given by 'handle' by (xmove,ymove)
void move_floating_label(int handle, double xmove, double ymove);
/// moves all floating labels that have 'scroll_mode' set to ANCHOR_LABEL_MAP
void scroll_floating_labels(double xmove, double ymove);
/// removes the floating label given by 'handle' from the screen
void remove_floating_label(int handle);
/// hides or shows a floating label
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);
void undraw_floating_labels(CVideo &video);
#else
void draw_floating_labels(surface screen);
void undraw_floating_labels(surface screen);
#endif
} // end namespace font

View file

@ -17,6 +17,7 @@
#include "floating_textbox.hpp"
#include "display_chat_manager.hpp"
#include "floating_label.hpp"
#include "game_display.hpp"
#include "game_preferences.hpp"
#include "log.hpp"

View file

@ -1028,484 +1028,6 @@ std::string make_text_ellipsis(const std::string &text, int font_size,
}
namespace {
typedef std::map<int, font::floating_label> label_map;
label_map labels;
int label_id = 1;
std::stack<std::set<int> > label_contexts;
}
namespace font {
floating_label::floating_label(const std::string& text, const surface& surf)
#if 0
: img_(),
#else
: surf_(surf), buf_(NULL),
#endif
text_(text),
font_size_(SIZE_NORMAL),
color_(NORMAL_COLOR), bgcolor_(), bgalpha_(0),
xpos_(0), ypos_(0),
xmove_(0), ymove_(0), lifetime_(-1),
width_(-1), height_(-1),
clip_rect_(screen_area()),
alpha_change_(0), visible_(true), align_(CENTER_ALIGN),
border_(0), scroll_(ANCHOR_LABEL_SCREEN), use_markup_(true)
{}
void floating_label::move(double xmove, double ymove)
{
xpos_ += xmove;
ypos_ += ymove;
}
int floating_label::xpos(size_t width) const
{
int xpos = int(xpos_);
if(align_ == font::CENTER_ALIGN) {
xpos -= width/2;
} else if(align_ == font::RIGHT_ALIGN) {
xpos -= width;
}
return xpos;
}
#if 0
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()) {
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 NULL;
}
// 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;
surf_ = create_optimized_surface(foreground);
return surf_;
}
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);
surf_ = create_optimized_surface(background);
// RLE compression seems less efficient for big semi-transparent area
// so, remove it for this case, but keep the optimized display format
SDL_SetAlpha(surf_,SDL_SRCALPHA,SDL_ALPHA_OPAQUE);
}
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;
surf_ = create_optimized_surface(foreground);
return surf_;
}
SDL_SetAlpha(foreground,SDL_SRCALPHA,SDL_ALPHA_OPAQUE);
blit_surface(foreground, NULL, background, &r);
surf_ = create_optimized_surface(background);
}
}
return surf_;
}
#endif
#ifdef SDL_GPU
void floating_label::draw(CVideo &video)
{
if (!visible_) {
return;
}
#if 0
create_image();
if (img_.null()) {
return;
}
video.draw_texture(img_, xpos(img_.width()), int(ypos_));
#else
create_surface();
if (surf_.null()) {
return;
}
video.blit_to_overlay(surf_, xpos(surf_->w), int(ypos_));
#endif
}
#else
void floating_label::draw(surface screen)
{
if(!visible_) {
buf_.assign(NULL);
return;
}
create_surface();
if(surf_ == NULL) {
return;
}
if(buf_ == NULL) {
buf_.assign(create_compatible_surface(screen, surf_->w, surf_->h));
if(buf_ == NULL) {
return;
}
}
if(screen == 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(screen,&rect,buf_,NULL);
sdl_blit(surf_,NULL,screen,&rect);
update_rect(rect);
}
#endif
#ifdef SDL_GPU
void floating_label::undraw(CVideo &video)
{
SDL_Rect r = sdl::create_rect(xpos(surf_->w), ypos_, surf_->w, surf_->h);
video.clear_overlay_area(r);
}
#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);
update_rect(rect);
move(xmove_,ymove_);
if(lifetime_ > 0) {
--lifetime_;
if(alpha_change_ != 0 && (xmove_ != 0.0 || ymove_ != 0.0) && surf_ != NULL) {
// fade out moving floating labels
// note that we don't optimize these surfaces since they will always change
surf_.assign(adjust_surface_alpha_add(surf_,alpha_change_,false));
}
}
}
#endif
int add_floating_label(const floating_label& flabel)
{
if(label_contexts.empty()) {
return 0;
}
++label_id;
labels.insert(std::pair<int, floating_label>(label_id, flabel));
label_contexts.top().insert(label_id);
return label_id;
}
void move_floating_label(int handle, double xmove, double ymove)
{
const label_map::iterator i = labels.find(handle);
if(i != labels.end()) {
i->second.move(xmove,ymove);
}
}
void scroll_floating_labels(double xmove, double ymove)
{
for(label_map::iterator i = labels.begin(); i != labels.end(); ++i) {
if(i->second.scroll() == ANCHOR_LABEL_MAP) {
i->second.move(xmove,ymove);
}
}
}
void remove_floating_label(int handle)
{
const label_map::iterator i = labels.find(handle);
if(i != labels.end()) {
if(label_contexts.empty() == false) {
label_contexts.top().erase(i->first);
}
labels.erase(i);
}
}
void show_floating_label(int handle, bool value)
{
const label_map::iterator i = labels.find(handle);
if(i != labels.end()) {
i->second.show(value);
}
}
SDL_Rect get_floating_label_rect(int handle)
{
const label_map::iterator i = labels.find(handle);
#if 0
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
surface const screen = SDL_GetVideoSurface();
#endif
if(screen != NULL) {
draw_floating_labels(screen);
}
#endif
label_contexts.push(std::set<int>());
}
floating_label_context::~floating_label_context()
{
const std::set<int>& labels = label_contexts.top();
for(std::set<int>::const_iterator i = labels.begin(); i != labels.end(); ) {
remove_floating_label(*i++);
}
label_contexts.pop();
#ifdef SDL_GPU
//TODO
#else
#if SDL_VERSION_ATLEAST(2, 0, 0)
surface const screen = NULL;
#else
surface const screen = SDL_GetVideoSurface();
#endif
if(screen != NULL) {
undraw_floating_labels(screen);
}
#endif
}
#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);
}
}
}
void undraw_floating_labels(CVideo &video)
{
if(label_contexts.empty()) {
return;
}
std::set<int>& context = label_contexts.top();
//remove expired labels
for(label_map::iterator j = labels.begin(); j != labels.end(); ) {
if(context.count(j->first) > 0 && j->second.expired()) {
j->second.undraw(video);
context.erase(j->first);
labels.erase(j++);
} else {
++j;
}
}
}
#else
void draw_floating_labels(surface screen)
{
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(screen);
}
}
}
void undraw_floating_labels(surface screen)
{
if(label_contexts.empty()) {
return;
}
std::set<int>& context = label_contexts.top();
//undraw labels in reverse order, so that a LIFO process occurs, and the screen is restored
//into the exact state it started in.
for(label_map::reverse_iterator i = labels.rbegin(); i != labels.rend(); ++i) {
if(context.count(i->first) > 0) {
i->second.undraw(screen);
}
}
//remove expired labels
for(label_map::iterator j = labels.begin(); j != labels.end(); ) {
if(context.count(j->first) > 0 && j->second.expired()) {
context.erase(j->first);
labels.erase(j++);
} else {
++j;
}
}
}
#endif
}
static bool add_font_to_fontlist(const config &fonts_config,
std::vector<font::subset_descriptor>& fontlist, const std::string& name)

View file

@ -103,131 +103,6 @@ std::string make_text_ellipsis(const std::string& text, int font_size, int max_w
int style = TTF_STYLE_NORMAL);
/// structure which will hide all current floating labels, and cause floating labels
/// instantiated after it is created to be displayed
struct floating_label_context
{
floating_label_context();
~floating_label_context();
};
enum ALIGN { LEFT_ALIGN, CENTER_ALIGN, RIGHT_ALIGN };
enum LABEL_SCROLL_MODE { ANCHOR_LABEL_SCREEN, ANCHOR_LABEL_MAP };
class floating_label
{
public:
floating_label(const std::string& text, const surface& surface = NULL);
void set_font_size(int font_size) {font_size_ = font_size;}
// set the location on the screen to display the text.
void set_position(double xpos, double ypos){
xpos_ = xpos;
ypos_ = ypos;
}
// set the amount to move the text each frame
void set_move(double xmove, double ymove){
xmove_ = xmove;
ymove_ = ymove;
}
// set the number of frames to display the text for, or -1 to display until removed
void set_lifetime(int lifetime) {
lifetime_ = lifetime;
alpha_change_ = -255 / lifetime_;
}
void set_color(const SDL_Color& color) {color_ = color;}
void set_bg_color(const SDL_Color& bg_color) {
bgcolor_ = bg_color;
#if SDL_VERSION_ATLEAST(2,0,0)
bgalpha_ = bg_color.a;
#else
bgalpha_ = bg_color.unused;
#endif
}
void set_border_size(int border) {border_ = border;}
// set width for word wrapping (use -1 to disable it)
void set_width(int w) {width_ = w;}
void set_height(int h) { height_ = h; }
void set_clip_rect(const SDL_Rect& r) {clip_rect_ = r;}
void set_alignment(ALIGN align) {align_ = align;}
void set_scroll_mode(LABEL_SCROLL_MODE scroll) {scroll_ = scroll;}
void use_markup(bool b) {use_markup_ = b;}
void move(double xmove, double ymove);
#ifdef SDL_GPU
void draw(CVideo &video);
void undraw(CVideo &video);
#else
void draw(surface screen);
void undraw(surface screen);
#endif
#if 0
sdl::timage create_image();
#else
surface create_surface();
#endif
bool expired() const { return lifetime_ == 0; }
void show(const bool value) { visible_ = value; }
LABEL_SCROLL_MODE scroll() const { return scroll_; }
private:
int xpos(size_t width) const;
#if 0
sdl::timage img_;
#else
surface surf_, buf_;
#endif
std::string text_;
int font_size_;
SDL_Color color_, bgcolor_;
int bgalpha_;
double xpos_, ypos_, xmove_, ymove_;
int lifetime_;
int width_, height_;
SDL_Rect clip_rect_;
int alpha_change_;
bool visible_;
font::ALIGN align_;
int border_;
LABEL_SCROLL_MODE scroll_;
bool use_markup_;
};
/// add a label floating on the screen above everything else.
/// @returns a handle to the label which can be used with other label functions
int add_floating_label(const floating_label& flabel);
/// moves the floating label given by 'handle' by (xmove,ymove)
void move_floating_label(int handle, double xmove, double ymove);
/// moves all floating labels that have 'scroll_mode' set to ANCHOR_LABEL_MAP
void scroll_floating_labels(double xmove, double ymove);
/// removes the floating label given by 'handle' from the screen
void remove_floating_label(int handle);
/// hides or shows a floating label
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);
void undraw_floating_labels(CVideo &video);
#else
void draw_floating_labels(surface screen);
void undraw_floating_labels(surface screen);
#endif
bool load_font_config();
/** Returns the currently defined fonts. */

View file

@ -27,6 +27,7 @@
#include "display_chat_manager.hpp"
#include "fake_unit_manager.hpp"
#include "fake_unit_ptr.hpp"
#include "floating_label.hpp"
#include "game_board.hpp"
#include "game_preferences.hpp"
#include "halo.hpp"

View file

@ -15,6 +15,7 @@
#define MULTIPLAYER_UI_HPP_INCLUDED
#include "chat_events.hpp"
#include "floating_label.hpp"
#include "hotkey/command_executor.hpp"
#include "network.hpp"
#include "preferences_display.hpp"

View file

@ -25,6 +25,7 @@
#include "cursor.hpp"
#include "display.hpp"
#include "events.hpp"
#include "floating_label.hpp"
#include "formula_callable.hpp"
#include "font.hpp"
#include "gettext.hpp"

View file

@ -15,6 +15,7 @@
#include "global.hpp"
#include "display.hpp"
#include "floating_label.hpp"
#include "game_board.hpp"
#include "game_data.hpp"
#include "map_label.hpp"

View file

@ -17,6 +17,7 @@
#define PLAY_CONTROLLER_H_INCLUDED
#include "controller_base.hpp"
#include "floating_label.hpp"
#include "game_end_exceptions.hpp"
#include "game_state.hpp"
#include "help/help.hpp"

View file

@ -20,6 +20,7 @@
#include "construct_dialog.hpp"
#include "display.hpp"
#include "floating_label.hpp"
#include "gettext.hpp"
#include "gui/auxiliary/event/handler.hpp"
#include "help/help.hpp"

View file

@ -20,6 +20,7 @@ class CVideo;
class display;
#include "cursor.hpp"
#include "floating_label.hpp"
#include "font.hpp"
#include "tooltips.hpp"

View file

@ -15,6 +15,7 @@
#include "tooltips.hpp"
#include "floating_label.hpp"
#include "font.hpp"
#include "game_display.hpp"
#include "help/help.hpp"

View file

@ -20,6 +20,7 @@
#include "global.hpp"
#include "font.hpp"
#include "floating_label.hpp"
#include "image.hpp"
#include "log.hpp"
#include "preferences.hpp"

View file

@ -22,6 +22,7 @@
#include "cursor.hpp" // for set, CURSOR_TYPE::NORMAL, etc
#include "editor/editor_main.hpp"
#include "filesystem.hpp" // for filesystem::file_exists, filesystem::io_exception, etc
#include "floating_label.hpp"
#include "font.hpp" // for load_font_config, etc
#include "formula.hpp" // for formula_error
#include "game_config.hpp" // for path, debug, debug_lua, etc