stk-code_catmod/src/font/font_with_face.hpp
2016-08-12 09:41:08 +08:00

229 lines
8.8 KiB
C++

//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2016 SuperTuxKart-Team
//
// 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 3
// 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; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef HEADER_FONT_WITH_FACE_HPP
#define HEADER_FONT_WITH_FACE_HPP
#include "font/font_manager.hpp"
#include "font/font_settings.hpp"
#include "utils/cpp2011.hpp"
#include <algorithm>
#include <map>
#include <set>
const int BEARING = 64;
class FaceTTF;
class FontWithFace : public NoCopy
{
public:
class FontCharCollector
{
public:
virtual void collectChar(video::ITexture* texture,
const core::rect<float>& destRect,
const core::rect<s32>& sourceRect,
const video::SColor* const colors) = 0;
};
struct FontArea
{
FontArea() : advance_x(0), bearing_x(0) ,offset_y(0), offset_y_bt(0),
spriteno(0) {}
int advance_x;
int bearing_x;
int offset_y;
int offset_y_bt;
int spriteno;
};
protected:
int m_font_max_height;
int m_glyph_max_height;
// ------------------------------------------------------------------------
void insertCharacters(const wchar_t* in_ptr, bool first_load = false)
{
if (!supportLazyLoadChar() && !first_load) return;
for (const wchar_t* p = in_ptr; *p; ++p)
{
if (*p == L'\r' || *p == L'\n' || *p < (wchar_t)32)
continue;
if (!loadedChar(*p))
{
loadGlyphInfo(*p);
if (supportChar(*p))
addLazyLoadChar(*p);
else if (m_fallback_font != NULL)
{
if (!m_fallback_font->loadedChar(*p))
{
m_fallback_font->loadGlyphInfo(*p);
if (m_fallback_font->supportChar(*p))
m_fallback_font->addLazyLoadChar(*p);
}
}
}
}
}
// ------------------------------------------------------------------------
void updateCharactersList();
// ------------------------------------------------------------------------
void setFallbackFont(FontWithFace* face) { m_fallback_font = face; }
// ------------------------------------------------------------------------
void setFallbackFontScale(float scale) { m_fallback_font_scale = scale; }
private:
struct GlyphInfo
{
unsigned int font_number;
unsigned int glyph_index;
GlyphInfo(unsigned int first = 0, unsigned int second = 0)
{
font_number = first;
glyph_index = second;
}
};
FaceTTF* m_face_ttf;
FontWithFace* m_fallback_font;
float m_fallback_font_scale;
/** A temporary holder stored new char to be inserted. */
std::set<wchar_t> m_new_char_holder;
gui::IGUISpriteBank* m_spritebank;
/** A full glyph page for this font. */
video::IImage* m_page;
unsigned int m_temp_height;
unsigned int m_used_width;
unsigned int m_used_height;
unsigned int m_face_dpi;
std::map<wchar_t, FontArea> m_character_area_map;
std::map<wchar_t, GlyphInfo> m_character_glyph_info_map;
// ------------------------------------------------------------------------
float getCharWidth(const FontArea& area, bool fallback, float scale) const
{
if (fallback)
return area.advance_x * m_fallback_font_scale;
else
return area.advance_x * scale;
}
// ------------------------------------------------------------------------
bool loadedChar(wchar_t c) const
{
std::map<wchar_t, GlyphInfo>::const_iterator n =
m_character_glyph_info_map.find(c);
if (n != m_character_glyph_info_map.end())
return true;
return false;
}
// ------------------------------------------------------------------------
const GlyphInfo& getGlyphInfo(wchar_t c) const
{
std::map<wchar_t, GlyphInfo>::const_iterator n =
m_character_glyph_info_map.find(c);
// Make sure we always find GlyphInfo
assert(n != m_character_glyph_info_map.end());
return n->second;
}
// ------------------------------------------------------------------------
bool supportChar(wchar_t c)
{
std::map<wchar_t, GlyphInfo>::const_iterator n =
m_character_glyph_info_map.find(c);
if (n != m_character_glyph_info_map.end())
{
return n->second.glyph_index > 0;
}
return false;
}
// ------------------------------------------------------------------------
void loadGlyphInfo(wchar_t c);
// ------------------------------------------------------------------------
void createNewGlyphPage();
// ------------------------------------------------------------------------
void addLazyLoadChar(wchar_t c) { m_new_char_holder.insert(c); }
// ------------------------------------------------------------------------
void insertGlyph(wchar_t c, const GlyphInfo& gi);
// ------------------------------------------------------------------------
void setDPI();
// ------------------------------------------------------------------------
virtual bool supportLazyLoadChar() const = 0;
// ------------------------------------------------------------------------
virtual unsigned int getGlyphPageSize() const = 0;
// ------------------------------------------------------------------------
virtual float getScalingFactorOne() const = 0;
// ------------------------------------------------------------------------
virtual unsigned int getScalingFactorTwo() const = 0;
public:
LEAK_CHECK();
// ------------------------------------------------------------------------
FontWithFace(const std::string& name, FaceTTF* ttf);
// ------------------------------------------------------------------------
virtual ~FontWithFace();
// ------------------------------------------------------------------------
virtual void init();
// ------------------------------------------------------------------------
virtual void reset();
// ------------------------------------------------------------------------
core::dimension2d<u32> getDimension(const wchar_t* text,
FontSettings* font_settings = NULL);
// ------------------------------------------------------------------------
int getCharacterFromPos(const wchar_t* text, int pixel_x,
FontSettings* font_settings = NULL) const;
// ------------------------------------------------------------------------
void render(const core::stringw& text, const core::rect<s32>& position,
const video::SColor& color, bool hcenter, bool vcenter,
const core::rect<s32>* clip,
FontSettings* font_settings,
FontCharCollector* char_collector = NULL);
// ------------------------------------------------------------------------
/** Write the current glyph page in png inside current running directory.
* Mainly for debug use.
* \param name The file name.
*/
void dumpGlyphPage(const std::string& name);
// ------------------------------------------------------------------------
/** Write the current glyph page in png inside current running directory.
* Useful in gdb without parameter.
*/
void dumpGlyphPage();
// ------------------------------------------------------------------------
gui::IGUISpriteBank* getSpriteBank() const { return m_spritebank; }
// ------------------------------------------------------------------------
const FontArea& getAreaFromCharacter(const wchar_t c,
bool* fallback_font) const;
// ------------------------------------------------------------------------
unsigned int getDPI() const { return m_face_dpi; }
}; // FontWithFace
#endif
/* EOF */