Mercurial > fife-parpg
view engine/core/video/fonts/fontbase.cpp @ 150:6e7d228def30
Lazy loading for animations.
Uses a Resource-Pointer class that behaves like
a pointer to an IResource, but only loads the
resource on demand.
There's a slight change of API, which is already
adapted to in the XML loaders. If you use
Animation.addFrame directly, either adapt to the
change or wait a few hours for a backwards compatibility
solution.
author | phoku@33b003aa-7bff-0310-803a-e67f0ece8222 |
---|---|
date | Sat, 11 Oct 2008 12:03:59 +0000 |
parents | 90005975cdbb |
children | 9a05ba6735b1 |
line wrap: on
line source
/*************************************************************************** * Copyright (C) 2005-2008 by the FIFE team * * http://www.fifengine.de * * This file is part of FIFE. * * * * FIFE is free software; you can redistribute it and/or * * modify it under the terms of the GNU Lesser General Public * * License as published by the Free Software Foundation; either * * version 2.1 of the License, or (at your option) any later version. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with this library; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * ***************************************************************************/ // Standard C++ library includes #include <vector> // Platform specific includes // 3rd party library includes #include <boost/filesystem/convenience.hpp> // FIFE includes // These includes are split up in two parts, separated by one empty line // First block: files included from the FIFE root src directory // Second block: files included from the same folder #include "util/structures/rect.h" #include "util/base/exception.h" #include "video/image.h" #include "video/renderbackend.h" #include "fontbase.h" namespace FIFE { FontBase::FontBase(): m_pool(), mColor(), mGlyphSpacing(0), mRowSpacing(0), mFilename(""), m_antiAlias(true) { } void FontBase::setRowSpacing(int spacing) { mRowSpacing = spacing; } int FontBase::getRowSpacing() const { return mRowSpacing; } void FontBase::setGlyphSpacing(int spacing) { mGlyphSpacing = spacing; } int FontBase::getGlyphSpacing() const { return mGlyphSpacing; } void FontBase::setAntiAlias(bool antiAlias) { m_antiAlias = antiAlias; } bool FontBase::isAntiAlias() { return m_antiAlias; } SDL_Color FontBase::getColor() const { return mColor; } int FontBase::getStringIndexAt(const std::string &text, int x) { for (int i = 0; i < static_cast<int>(text.size()); ++i) { if (getWidth(text.substr(0,i)) > x) { return i-1; } } return text.length(); } Image* FontBase::getAsImage(const std::string& text) { Image* image = m_pool.getRenderedText(this, text); if (!image) { SDL_Surface* textSurface = renderString(text); image = RenderBackend::instance()->createImage(textSurface); m_pool.addRenderedText( this, text, image ); } return image; } Image* FontBase::getAsImageMultiline(const std::string& text) { Image* image = m_pool.getRenderedText(this, text); if (!image) { std::vector<SDL_Surface*> lines; // split text as needed std::string::size_type pos, last_pos = 0; int length = 0; int render_width = 0, render_height = 0; do { pos = text.find("\n", last_pos); if (pos != std::string::npos) { length = pos - last_pos; } else { length = text.size() - last_pos; } std::string sub = text.substr(last_pos, length); SDL_Surface* text_surface = renderString(sub); if (text_surface->w > render_width) { render_width = text_surface->w; } lines.push_back(text_surface); last_pos = pos + 1; } while (pos != std::string::npos); render_height = (getRowSpacing() + getHeight()) * lines.size(); SDL_Surface* final_surface = SDL_CreateRGBSurface(SDL_SWSURFACE, render_width,render_height,32, RMASK, GMASK, BMASK ,AMASK); if (!final_surface) { std::cerr << "CreateRGBSurface failed: " << SDL_GetError() << "\n"; exit(0); } SDL_FillRect(final_surface, 0, 0x00000000); int ypos = 0; for (std::vector<SDL_Surface*>::iterator i = lines.begin(); i != lines.end(); ++i) { SDL_Rect dst_rect = { 0, 0, 0, 0 }; dst_rect.y = ypos; SDL_SetAlpha(*i,0,SDL_ALPHA_OPAQUE); SDL_BlitSurface(*i,0,final_surface,&dst_rect); ypos += getRowSpacing() + getHeight(); SDL_FreeSurface(*i); } image = RenderBackend::instance()->createImage(final_surface); m_pool.addRenderedText(this, text, image); } return image; } std::string FontBase::splitTextToWidth (const std::string& text, int render_width) { if (render_width <= 0 || text.empty()) { return text; } std::string output; std::string line; std::string::size_type pos = 0; std::list<std::pair<size_t,size_t> > break_pos; bool firstLine = true; while( pos < text.length() ) { break_pos.clear(); if( !firstLine ) { line = "\n"; } else { firstLine = false; } while( getWidth(line) < render_width && pos < text.length() ) { if (text.at(pos) == ' ' && !line.empty()) break_pos.push_back( std::make_pair(line.length(),pos) ); line.push_back( text.at(pos) ); ++pos; // Special case: Already newlines in string: if( text.at(pos-1) == '\n' ) { if( line[0] == '\n' && line.length() > 1 ) line.erase(0); output.append(line); break; } } if( pos >= text.length() ) break; if( break_pos.empty() ) { // No break position and line length smaller than 2 // means the renderwidth is really screwed. Just continue // appending single character lines. if( line.length() <= 1 ) { output.append(line); continue; } // We can't do hyphenation here, // so we just retreat one character :-( line.erase(line.length() - 1); --pos; } else { line = line.substr(0,break_pos.back().first); pos = break_pos.back().second + 1; } output.append(line); } if( !line.empty() ) { output.append(line); } return output; } }