Write in the pango render engine for the new widget library.

Also enabled it for scons, cmake still needs to be done.
This commit is contained in:
Mark de Wever 2008-07-11 16:53:20 +00:00
parent 536917b304
commit e63e00dad2
8 changed files with 284 additions and 6 deletions

View file

@ -191,8 +191,8 @@ if env["prereqs"]:
conf.CheckCHeader("libintl.h", "<>") and \
conf.CheckSDL(require_version = '1.2.7') or Die("Base prerequisites are not met.")
# conf.CheckPango("cairo") and \
have_client_prereqs = \
conf.CheckPango("cairo") and \
conf.CheckBoost("regex") and \
conf.CheckSDL("SDL_ttf", require_version = "2.0.8") and \
conf.CheckSDL("SDL_mixer", require_version = '1.2.0') and \

View file

@ -39,6 +39,7 @@ src/minimap.cpp
src/preferences.cpp
src/preferences_display.cpp
src/show_dialog.cpp
src/text.cpp
src/terrain_filter.cpp
src/terrain_translation.cpp
src/widgets/button.cpp

View file

@ -164,6 +164,7 @@ SET(libwesnoth-game_STAT_SRC
soundsource.cpp
terrain.cpp
terrain_translation.cpp
text.cpp
time_of_day.cpp
video.cpp
theme.cpp

View file

@ -127,6 +127,7 @@ wesnoth_source = \
statistics_dialog.cpp \
team.cpp \
terrain_filter.cpp \
text.cpp \
time_of_day.cpp \
titlescreen.cpp \
tooltips.cpp \

View file

@ -83,6 +83,7 @@ libwesnoth_sources = Split("""
soundsource.cpp
terrain.cpp
terrain_translation.cpp
text.cpp
time_of_day.cpp
tooltips.cpp
video.cpp

View file

@ -20,13 +20,13 @@
#include "gui/widgets/canvas.hpp"
#include "config.hpp"
#include "font.hpp"
#include "image.hpp"
#include "gettext.hpp"
#include "gui/widgets/formula.hpp"
#include "gui/widgets/helper.hpp"
#include "log.hpp"
#include "serialization/parser.hpp"
#include "../../text.hpp"
#include "variant.hpp"
#include "wml_exception.hpp"
@ -766,18 +766,21 @@ void ttext::draw(surface& canvas,
return;
}
SDL_Color col = { (colour_ >> 24), (colour_ >> 16), (colour_ >> 8), colour_ };
surface surf(font::get_rendered_text(text, font_size_, col, font_style_));
assert(surf);
static font::ttext text_renderer;
text_renderer.set_text(text, false).
set_font_size(font_size_).
set_foreground_colour(colour_);
surface surf = text_renderer.render();
game_logic::map_formula_callable local_variables(variables);
local_variables.add("text_width", variant(surf->w));
local_variables.add("text_height", variant(surf->h));
//@todo formulas are now recalculated every draw cycle which is a
// bit silly unless there has been a resize. So to optimize we should
// use an extra flag or do the calculation in a separate routine.
const unsigned x = x_(local_variables);
const unsigned y = y_(local_variables);
const unsigned w = w_(local_variables);

162
src/text.cpp Normal file
View file

@ -0,0 +1,162 @@
/* $Id$ */
/*
Copyright (C) 2003 - 2008 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 version 2
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 "text.hpp"
#include "font.hpp"
#include "language.hpp"
#include <cassert>
#include <cairo/cairo.h>
namespace font {
ttext::ttext() :
font_map_(reinterpret_cast<PangoCairoFontMap*>(pango_cairo_font_map_new())),
context_(pango_cairo_font_map_create_context(font_map_)),
layout_(pango_layout_new(context_)),
surface_(),
text_(),
markedup_text_(false),
font_size_(14),
foreground_colour_(0xFFFFFFFF), // solid white
dirty_(true),
surface_buffer_(NULL)
{
// With 72 dpi the sizes are the same as with SDL_TTF so hardcoded.
pango_cairo_context_set_resolution(context_, 72.0);
}
ttext::~ttext()
{
if(font_map_) {
g_object_unref(font_map_);
}
if(context_) {
g_object_unref(context_);
}
if(layout_) {
g_object_unref(layout_);
}
if(surface_buffer_) {
surface_.assign(NULL);
delete[] surface_buffer_;
}
}
surface ttext::render()
{
if(dirty_) {
dirty_ = false;
/**
* @todo FIXME the font needs to be an object.
*/
PangoFontDescription *font = pango_font_description_new();
pango_font_description_set_family(font, get_fonts().c_str());
pango_font_description_set_size(font, font_size_ * PANGO_SCALE);
pango_layout_set_font_description(layout_, font);
pango_font_description_free(font);
if(markedup_text_) {
pango_layout_set_markup(layout_, text_.c_str(), text_.size());
} else {
pango_layout_set_text(layout_, text_.c_str(), text_.size());
}
PangoRectangle rect;
pango_layout_get_pixel_extents(layout_, NULL, &rect);
const unsigned stride = rect.width * 4;
create_surface_buffer(stride * rect.height);
cairo_surface_t *cairo_surface =
cairo_image_surface_create_for_data(surface_buffer_,
CAIRO_FORMAT_ARGB32, rect.width, rect.height, stride);
cairo_t *cr = cairo_create(cairo_surface);
pango_cairo_update_context (cr, context_); // Needed?
/* paint background */
// cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
// cairo_paint(cr);
/* set colour (used for foreground). */
cairo_set_source_rgba(cr,
(foreground_colour_ >> 24) / 256.0,
((foreground_colour_ >> 16) & 0xFF) / 256.0,
((foreground_colour_ >> 8) & 0xFF) / 256.0,
(foreground_colour_ & 0xFF) / 256.0);
pango_cairo_show_layout(cr, layout_);
// Draw twice otherwise we have some problems due to transparency
// we overcome the problem with drawing twice which is a kind of hack.
pango_cairo_show_layout(cr, layout_);
surface_.assign(SDL_CreateRGBSurfaceFrom(
surface_buffer_, rect.width, rect.height, 32, stride,
0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000));
}
return surface_;
}
ttext& ttext::set_text(const t_string& text, const bool markedup)
{
if(markedup != markedup_text_ || text != text_) {
text_ = text;
markedup_text_ = markedup;
dirty_ = true;
}
return *this;
}
ttext& ttext::set_font_size(const unsigned font_size)
{
if(font_size != font_size_) {
font_size_ = font_size;
dirty_ = true;
}
return *this;
}
ttext& ttext::set_foreground_colour(const Uint32 colour)
{
if(colour != foreground_colour_) {
foreground_colour_ = colour;
dirty_ = true;
}
return *this;
}
void ttext::create_surface_buffer(const size_t size)
{
// clear old buffer
if(surface_buffer_) {
surface_.assign(NULL);
delete[] surface_buffer_;
}
surface_buffer_ = new unsigned char [size];
memset(surface_buffer_, 0, size);
}
} // namespace font

109
src/text.hpp Normal file
View file

@ -0,0 +1,109 @@
/* $Id$ */
/*
Copyright (C) 2003 - 2008 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 version 2
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.
*/
#ifndef TEXT_HPP_INCLUDED
#define TEXT_HPP_INCLUDED
#include "sdl_utils.hpp"
#include "tstring.hpp"
#include <pango/pango.h>
#include <pango/pangocairo.h>
class language_def;
namespace font {
// add background colour and also font markup.
/**
* Text class .
*
* This class stores the text to draw and uses pango with the cairo backend to
* render the text. See http://pango.org for more info.
*/
class ttext {
public:
ttext();
~ttext();
/**
* Returns the rendered text.
*
* Before rendering it tests whether a redraw is needed and if so it first
* redraws the surface before returning it.
*/
surface render();
/***** ***** ***** ***** Setters ***** ***** ***** *****/
ttext& set_text(const t_string& text, const bool markedup);
ttext& set_font_size(const unsigned font_size);
ttext& set_foreground_colour(const Uint32 colour);
private:
/***** ***** ***** ***** Pango variables ***** ***** ***** *****/
PangoCairoFontMap* font_map_;
PangoContext* context_;
PangoLayout* layout_;
/** The surface to render upon used as a cache. */
mutable surface surface_;
/** The text to draw. */
t_string text_;
/** Is the text markedup if so the markedup render routines need to be used. */
bool markedup_text_;
/** The font size to draw. */
unsigned font_size_;
/** The foreground colour. */
Uint32 foreground_colour_;
/**
* When the text is rendered it's cached so we need to know the dirty
* status of the surface.
*/
bool dirty_;
/**
* Buffer to store the image on.
*
* We use a cairo surface to draw on this buffer and then use the buffer as
* data source for the SDL_Surface. This means the buffer needs to be stored
* in the object.
*/
unsigned char* surface_buffer_;
/**
* Creates a new buffer.
*
* If needed frees the other surface and then creates a new buffer and
* initializes the entire buffer with values 0.
*
* @param size The required size of the buffer.
*/
void create_surface_buffer(const size_t size);
};
} // namespace font
#endif