More clean up freetype-related code
1. Remove useless get font properties class 2. Pre-set the face dpi 3. Make all freetype related code to have a better coding style
This commit is contained in:
parent
c2d863888b
commit
09101e923c
@ -15,85 +15,130 @@
|
|||||||
// along with this program; if not, write to the Free Software
|
// along with this program; if not, write to the Free Software
|
||||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
#include "graphics/irr_driver.hpp"
|
||||||
#include "guiengine/ft_environment.hpp"
|
#include "guiengine/ft_environment.hpp"
|
||||||
#include "guiengine/get_font_properties.hpp"
|
|
||||||
#include "io/file_manager.hpp"
|
#include "io/file_manager.hpp"
|
||||||
#include "utils/log.hpp"
|
#include "utils/log.hpp"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
using namespace gui;
|
using namespace gui;
|
||||||
|
|
||||||
namespace GUIEngine
|
namespace GUIEngine
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
FTEnvironment::FTEnvironment()
|
FTEnvironment::FTEnvironment()
|
||||||
{
|
{
|
||||||
FTEnvironment::ft_err += FT_Init_FreeType(&(FTEnvironment::ft_lib));
|
m_ft_err += FT_Init_FreeType(&(m_ft_lib));
|
||||||
|
|
||||||
loadFont();
|
loadFont();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
FTEnvironment::~FTEnvironment()
|
FTEnvironment::~FTEnvironment()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < F_COUNT; ++i)
|
for (int i = 0; i < F_COUNT; ++i)
|
||||||
FTEnvironment::ft_err += FT_Done_Face((FTEnvironment::ft_face[i]));
|
m_ft_err += FT_Done_Face(m_ft_face[i]);
|
||||||
|
|
||||||
FTEnvironment::ft_err += FT_Done_FreeType(FTEnvironment::ft_lib);
|
m_ft_err += FT_Done_FreeType(m_ft_lib);
|
||||||
|
|
||||||
if (FTEnvironment::ft_err > 0)
|
if (m_ft_err > 0)
|
||||||
Log::error("Freetype Environment", "Can't destroy all fonts.");
|
Log::error("Freetype Environment", "Can't destroy all fonts.");
|
||||||
else
|
else
|
||||||
Log::info("Freetype Environment", "Successfully destroy all fonts.");
|
Log::info("Freetype Environment", "Successfully destroy all fonts.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
FT_Face FTEnvironment::getFace(const FontUse font)
|
||||||
|
{
|
||||||
|
return m_ft_face[font];
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
void FTEnvironment::loadFont()
|
void FTEnvironment::loadFont()
|
||||||
{
|
{
|
||||||
FTEnvironment::ft_err += FT_New_Face(FTEnvironment::ft_lib, (file_manager->getAssetChecked
|
m_ft_err += FT_New_Face(m_ft_lib, (file_manager->getAssetChecked
|
||||||
(FileManager::TTF, "Ubuntu-R.ttf", true)).c_str(),
|
(FileManager::TTF, "Ubuntu-R.ttf", true)).c_str(),
|
||||||
0, &(FTEnvironment::ft_face[F_DEFAULT]));
|
0, &m_ft_face[F_DEFAULT]);
|
||||||
|
|
||||||
FTEnvironment::ft_err += FT_New_Face(FTEnvironment::ft_lib, (file_manager->getAssetChecked
|
m_ft_err += FT_New_Face(m_ft_lib, (file_manager->getAssetChecked
|
||||||
(FileManager::TTF, "FreeSans.ttf",true)).c_str(),
|
(FileManager::TTF, "FreeSans.ttf",true)).c_str(),
|
||||||
0, &(FTEnvironment::ft_face[F_DEFAULT_FALLBACK]));
|
0, &m_ft_face[F_DEFAULT_FALLBACK]);
|
||||||
|
|
||||||
FTEnvironment::ft_err += FT_New_Face(FTEnvironment::ft_lib, (file_manager->getAssetChecked
|
m_ft_err += FT_New_Face(m_ft_lib, (file_manager->getAssetChecked
|
||||||
(FileManager::TTF, "wqy-microhei.ttf",true)).c_str(),
|
(FileManager::TTF, "wqy-microhei.ttf",true)).c_str(),
|
||||||
0, &(FTEnvironment::ft_face[F_CJK]));
|
0, &m_ft_face[F_CJK]);
|
||||||
|
|
||||||
FTEnvironment::ft_err += FT_New_Face(FTEnvironment::ft_lib, (file_manager->getAssetChecked
|
m_ft_err += FT_New_Face(m_ft_lib, (file_manager->getAssetChecked
|
||||||
(FileManager::TTF, "NotoNaskhArabicUI-Bold.ttf",true)).c_str(),
|
(FileManager::TTF, "NotoNaskhArabicUI-Bold.ttf",true)).c_str(),
|
||||||
0, &(FTEnvironment::ft_face[F_AR]));
|
0, &m_ft_face[F_AR]);
|
||||||
|
|
||||||
FTEnvironment::ft_err += FT_New_Face(FTEnvironment::ft_lib, (file_manager->getAssetChecked
|
m_ft_err += FT_New_Face(m_ft_lib, (file_manager->getAssetChecked
|
||||||
(FileManager::TTF, "Ubuntu-B.ttf", true)).c_str(),
|
(FileManager::TTF, "Ubuntu-B.ttf", true)).c_str(),
|
||||||
0, &(FTEnvironment::ft_face[F_BOLD]));
|
0, &m_ft_face[F_BOLD]);
|
||||||
|
|
||||||
FTEnvironment::ft_err += FT_New_Face(FTEnvironment::ft_lib, (file_manager->getAssetChecked
|
m_ft_err += FT_New_Face(m_ft_lib, (file_manager->getAssetChecked
|
||||||
(FileManager::TTF, "FreeSansBold.ttf", true)).c_str(),
|
(FileManager::TTF, "FreeSansBold.ttf", true)).c_str(),
|
||||||
0, &(FTEnvironment::ft_face[F_BOLD_FALLBACK]));
|
0, &m_ft_face[F_BOLD_FALLBACK]);
|
||||||
|
|
||||||
FTEnvironment::ft_err += FT_New_Face(FTEnvironment::ft_lib, (file_manager->getAssetChecked
|
m_ft_err += FT_New_Face(m_ft_lib, (file_manager->getAssetChecked
|
||||||
(FileManager::TTF, "SigmarOne.otf",true)).c_str(),
|
(FileManager::TTF, "SigmarOne.otf",true)).c_str(),
|
||||||
0, &(FTEnvironment::ft_face[F_DIGIT]));
|
0, &m_ft_face[F_DIGIT]);
|
||||||
|
|
||||||
//Set charmap
|
//Set charmap
|
||||||
for (int h = 0; h < F_COUNT; ++h)
|
for (int h = 0; h < F_COUNT; ++h)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < FTEnvironment::ft_face[h]->num_charmaps; ++i)
|
for (int i = 0; i < m_ft_face[h]->num_charmaps; ++i)
|
||||||
{
|
{
|
||||||
FT_UShort pid = FTEnvironment::ft_face[h]->charmaps[i]->platform_id;
|
FT_UShort pid = m_ft_face[h]->charmaps[i]->platform_id;
|
||||||
FT_UShort eid = FTEnvironment::ft_face[h]->charmaps[i]->encoding_id;
|
FT_UShort eid = m_ft_face[h]->charmaps[i]->encoding_id;
|
||||||
if (((pid == 0) && (eid == 3)) || ((pid == 3) && (eid == 1)))
|
if (((pid == 0) && (eid == 3)) || ((pid == 3) && (eid == 1)))
|
||||||
FTEnvironment::ft_err += FT_Set_Charmap(FTEnvironment::ft_face[h], FTEnvironment::ft_face[h]->charmaps[i]);
|
m_ft_err += FT_Set_Charmap(m_ft_face[h], m_ft_face[h]->charmaps[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FTEnvironment::ft_err > 0)
|
// Set face dpi
|
||||||
|
// font size is resolution-dependent.
|
||||||
|
// normal text will range from 0.8, in 640x* resolutions (won't scale
|
||||||
|
// below that) to 1.0, in 1024x* resolutions, and linearly up
|
||||||
|
// normal text will range from 0.2, in 640x* resolutions (won't scale
|
||||||
|
// below that) to 0.4, in 1024x* resolutions, and linearly up
|
||||||
|
const s32 screen_width = irr_driver->getFrameSize().Width;
|
||||||
|
const s32 screen_height = irr_driver->getFrameSize().Height;
|
||||||
|
float scale = std::max(0, screen_width - 640)/564.0f;
|
||||||
|
|
||||||
|
// attempt to compensate for small screens
|
||||||
|
if (screen_width < 1200) scale = std::max(0, screen_width - 640) / 750.0f;
|
||||||
|
if (screen_width < 900 || screen_height < 700) scale = std::min(scale, 0.05f);
|
||||||
|
|
||||||
|
const u32 normal_dpi = ((0.7f + 0.2f*scale)*27);
|
||||||
|
const u32 title_dpi = ((0.2f + 0.2f*scale)*120);
|
||||||
|
const u32 digit_dpi = ((0.7f + 0.2f*scale)*40);
|
||||||
|
|
||||||
|
Log::info("Freetype Environment", "DPI for Normal Font is %d.", normal_dpi);
|
||||||
|
Log::info("Freetype Environment", "DPI for Title Font is %d.", title_dpi);
|
||||||
|
Log::info("Freetype Environment", "DPI for Digit Font is %d.", digit_dpi);
|
||||||
|
|
||||||
|
m_ft_err += FT_Set_Pixel_Sizes(m_ft_face[F_DEFAULT], 0, normal_dpi);
|
||||||
|
m_ft_err += FT_Set_Pixel_Sizes(m_ft_face[F_DEFAULT_FALLBACK], 0, normal_dpi);
|
||||||
|
m_ft_err += FT_Set_Pixel_Sizes(m_ft_face[F_CJK], 0, normal_dpi);
|
||||||
|
m_ft_err += FT_Set_Pixel_Sizes(m_ft_face[F_AR], 0, normal_dpi);
|
||||||
|
m_ft_err += FT_Set_Pixel_Sizes(m_ft_face[F_BOLD], 0, title_dpi);
|
||||||
|
m_ft_err += FT_Set_Pixel_Sizes(m_ft_face[F_BOLD_FALLBACK], 0, title_dpi);
|
||||||
|
m_ft_err += FT_Set_Pixel_Sizes(m_ft_face[F_DIGIT], 0, digit_dpi);
|
||||||
|
|
||||||
|
if (m_ft_err > 0)
|
||||||
Log::error("Freetype Environment", "Can't load all fonts.");
|
Log::error("Freetype Environment", "Can't load all fonts.");
|
||||||
else
|
else
|
||||||
Log::info("Freetype Environment", "Successfully loaded all fonts.");
|
Log::info("Freetype Environment", "Successfully loaded all fonts.");
|
||||||
}
|
}
|
||||||
|
|
||||||
FT_Library FTEnvironment::ft_lib = NULL;
|
FT_Library FTEnvironment::m_ft_lib = NULL;
|
||||||
FT_Error FTEnvironment::ft_err = 0;
|
FT_Error FTEnvironment::m_ft_err = 0;
|
||||||
|
|
||||||
} // guiengine
|
} // guiengine
|
||||||
|
@ -15,8 +15,10 @@
|
|||||||
// along with this program; if not, write to the Free Software
|
// along with this program; if not, write to the Free Software
|
||||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
#ifndef HEADER_FT_ENVIRONMENT_HPP
|
||||||
|
#define HEADER_FT_ENVIRONMENT_HPP
|
||||||
|
|
||||||
#include <ft2build.h>
|
#include <ft2build.h>
|
||||||
#include "guiengine/get_font_properties.hpp"
|
|
||||||
#include FT_FREETYPE_H
|
#include FT_FREETYPE_H
|
||||||
|
|
||||||
#include "utils/leak_check.hpp"
|
#include "utils/leak_check.hpp"
|
||||||
@ -26,6 +28,23 @@
|
|||||||
*/
|
*/
|
||||||
namespace GUIEngine
|
namespace GUIEngine
|
||||||
{
|
{
|
||||||
|
|
||||||
|
enum FontUse
|
||||||
|
{
|
||||||
|
F_DEFAULT = 0,
|
||||||
|
F_DEFAULT_FALLBACK = 1,
|
||||||
|
F_CJK = 2,
|
||||||
|
F_AR = 3,
|
||||||
|
F_LAST_REGULAR_FONT = F_AR,
|
||||||
|
|
||||||
|
F_BOLD = 4,
|
||||||
|
F_BOLD_FALLBACK = 5,
|
||||||
|
F_DIGIT = 6,
|
||||||
|
F_COUNT = 7
|
||||||
|
};
|
||||||
|
|
||||||
|
enum TTFLoadingType {T_NORMAL, T_DIGIT, T_BOLD};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Initialize a freetype environment with a single freetype library.
|
* \brief Initialize a freetype environment with a single freetype library.
|
||||||
*/
|
*/
|
||||||
@ -37,15 +56,20 @@ namespace GUIEngine
|
|||||||
|
|
||||||
FTEnvironment();
|
FTEnvironment();
|
||||||
~FTEnvironment();
|
~FTEnvironment();
|
||||||
FT_Face ft_face[irr::gui::F_COUNT];
|
|
||||||
|
/** Get a face with a suitable font type.
|
||||||
|
*/
|
||||||
|
FT_Face getFace(const FontUse font);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/** Load font face into memory, but don't create glyph yet.
|
/** Load font face into memory, but don't create glyph yet.
|
||||||
*/
|
*/
|
||||||
void loadFont();
|
void loadFont();
|
||||||
|
|
||||||
static FT_Library ft_lib;
|
FT_Face m_ft_face[F_COUNT];
|
||||||
static FT_Error ft_err;
|
static FT_Library m_ft_lib;
|
||||||
|
static FT_Error m_ft_err;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // guiengine
|
} // guiengine
|
||||||
|
#endif // HEADER_FT_ENVIRONMENT_HPP
|
||||||
|
@ -1,127 +0,0 @@
|
|||||||
// SuperTuxKart - a fun racing game with go-kart
|
|
||||||
// Copyright (C) 2015 Ben Au
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
|
|
||||||
#include "graphics/irr_driver.hpp"
|
|
||||||
#include "guiengine/get_font_properties.hpp"
|
|
||||||
#include "utils/translation.hpp"
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <clocale>
|
|
||||||
#include <cwctype>
|
|
||||||
|
|
||||||
namespace irr
|
|
||||||
{
|
|
||||||
namespace gui
|
|
||||||
{
|
|
||||||
|
|
||||||
getFontProperties::getFontProperties (const core::stringc &langname, TTFLoadingType type, FontUse &fu)
|
|
||||||
{
|
|
||||||
findScale();
|
|
||||||
|
|
||||||
switch(type)
|
|
||||||
{
|
|
||||||
case T_NORMAL:
|
|
||||||
loadChar(langname, fu, normal_text_scale);
|
|
||||||
break;
|
|
||||||
case T_DIGIT:
|
|
||||||
fu = F_DIGIT;
|
|
||||||
loadNumber(normal_text_scale);
|
|
||||||
break;
|
|
||||||
case T_BOLD:
|
|
||||||
fu = F_BOLD;
|
|
||||||
loadBoldChar(title_text_scale);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void getFontProperties::findScale()
|
|
||||||
{
|
|
||||||
//Borrowed from engine.cpp:
|
|
||||||
// font size is resolution-dependent.
|
|
||||||
// normal text will range from 0.8, in 640x* resolutions (won't scale
|
|
||||||
// below that) to 1.0, in 1024x* resolutions, and linearly up
|
|
||||||
// normal text will range from 0.2, in 640x* resolutions (won't scale
|
|
||||||
// below that) to 0.4, in 1024x* resolutions, and linearly up
|
|
||||||
const int screen_width = irr_driver->getFrameSize().Width;
|
|
||||||
const int screen_height = irr_driver->getFrameSize().Height;
|
|
||||||
float scale = std::max(0, screen_width - 640)/564.0f;
|
|
||||||
|
|
||||||
// attempt to compensate for small screens
|
|
||||||
if (screen_width < 1200) scale = std::max(0, screen_width - 640) / 750.0f;
|
|
||||||
if (screen_width < 900 || screen_height < 700) scale = std::min(scale, 0.05f);
|
|
||||||
|
|
||||||
normal_text_scale = 0.7f + 0.2f*scale;
|
|
||||||
title_text_scale = 0.2f + 0.2f*scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
void getFontProperties::loadChar(const core::stringc langname, FontUse& fu, float scale)
|
|
||||||
{
|
|
||||||
fu = F_DEFAULT; //Default font file
|
|
||||||
|
|
||||||
for (int i = 32; i < 128; ++i)
|
|
||||||
usedchar.insert((wchar_t)i); //Include basic Latin too
|
|
||||||
usedchar.insert((wchar_t)160); //Non-breaking space
|
|
||||||
usedchar.insert((wchar_t)215); //Used on resolution selection screen (X).
|
|
||||||
|
|
||||||
//There's specific handling for some language, we may need more after more translation are added or problems found out.
|
|
||||||
//if (langname == "el" || langname == "fr" || langname == "gd")
|
|
||||||
size = (int)(27*scale); //Lower scale for them as they're space-consuming.
|
|
||||||
//else
|
|
||||||
// size = (int)(29*scale); //Set to default size
|
|
||||||
}
|
|
||||||
|
|
||||||
void getFontProperties::loadNumber(float scale)
|
|
||||||
{
|
|
||||||
size = (int)(40*scale); //Set default size for Big Digit Text
|
|
||||||
for (int i = 46; i < 59; ++i) //Include chars used by timer and laps count only
|
|
||||||
usedchar.insert((wchar_t)i); //FIXME have to load 46 " . " to make 47 " / " display correctly, why?
|
|
||||||
}
|
|
||||||
|
|
||||||
void getFontProperties::loadBoldChar(float scale)
|
|
||||||
{
|
|
||||||
size = (int)(120*scale); //Set default size for Bold Text
|
|
||||||
|
|
||||||
usedchar = translations->getCurrentAllChar(); //Loading unique characters
|
|
||||||
for (int i = 65; i < 256; ++i)
|
|
||||||
usedchar.insert((wchar_t)i); //Include basic Latin too, starting from A (char code 65)
|
|
||||||
|
|
||||||
setlocale(LC_ALL, "en_US.UTF8");
|
|
||||||
std::set<wchar_t>::iterator it = usedchar.begin();
|
|
||||||
while (it != usedchar.end())
|
|
||||||
{
|
|
||||||
//Only use all capital letter for bold char with latin (<640 of char code).
|
|
||||||
//Remove all characters (>char code 8191) not used by the title
|
|
||||||
if (((iswlower((wchar_t)*it) || !iswalpha((wchar_t)*it)) && *it < 640) || *it > 8191)
|
|
||||||
it = usedchar.erase(it);
|
|
||||||
else
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Final hack to make stk display title properly
|
|
||||||
for (int i = 32; i < 65; ++i)
|
|
||||||
usedchar.insert((wchar_t)i); //Include basic symbol (from space (char code 32) to @(char code 64))
|
|
||||||
usedchar.insert((wchar_t)160); //Non-breaking space
|
|
||||||
|
|
||||||
//Remove Ordinal indicator (char code 170 and 186)
|
|
||||||
usedchar.erase((wchar_t)170);
|
|
||||||
usedchar.erase((wchar_t)186);
|
|
||||||
|
|
||||||
usedchar.erase((wchar_t)304); //Remove Capital I-dotted (char code 304) with using "I" altogether.
|
|
||||||
}
|
|
||||||
|
|
||||||
} // end namespace gui
|
|
||||||
} // end namespace irr
|
|
@ -1,76 +0,0 @@
|
|||||||
// SuperTuxKart - a fun racing game with go-kart
|
|
||||||
// Copyright (C) 2015 Ben Au
|
|
||||||
//
|
|
||||||
// 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_GET_FONT_PROPERTIES_HPP
|
|
||||||
#define HEADER_GET_FONT_PROPERTIES_HPP
|
|
||||||
|
|
||||||
#include <irrlicht.h>
|
|
||||||
#include <set>
|
|
||||||
|
|
||||||
namespace irr
|
|
||||||
{
|
|
||||||
namespace gui
|
|
||||||
{
|
|
||||||
|
|
||||||
enum FontUse
|
|
||||||
{
|
|
||||||
F_DEFAULT = 0,
|
|
||||||
F_DEFAULT_FALLBACK = 1,
|
|
||||||
F_CJK = 2,
|
|
||||||
F_AR = 3,
|
|
||||||
F_LAST_REGULAR_FONT = F_AR,
|
|
||||||
|
|
||||||
F_BOLD = 4,
|
|
||||||
F_BOLD_FALLBACK = 5,
|
|
||||||
F_DIGIT = 6,
|
|
||||||
F_COUNT = 7
|
|
||||||
};
|
|
||||||
|
|
||||||
enum TTFLoadingType {T_NORMAL, T_DIGIT, T_BOLD};
|
|
||||||
|
|
||||||
class getFontProperties
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
/** Get properties used for load characters with ttf.
|
|
||||||
* \param langname The current gui language.
|
|
||||||
* \param type Current loaded font type (normal, bold or digit font).
|
|
||||||
* \param fu Give a suitable font file.
|
|
||||||
* \return Font dpi and characters required to preload for current gui language.
|
|
||||||
*/
|
|
||||||
getFontProperties (const core::stringc &langname, TTFLoadingType type, FontUse &fu);
|
|
||||||
|
|
||||||
unsigned short size;
|
|
||||||
std::set<wchar_t> usedchar;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void loadChar(core::stringc, FontUse&, float);
|
|
||||||
void loadNumber(float);
|
|
||||||
void loadBoldChar(float);
|
|
||||||
|
|
||||||
/** Find a suitable font scale base on current resolution
|
|
||||||
*/
|
|
||||||
void findScale();
|
|
||||||
|
|
||||||
float normal_text_scale;
|
|
||||||
float title_text_scale;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // end namespace gui
|
|
||||||
} // end namespace irr
|
|
||||||
|
|
||||||
#endif
|
|
@ -27,25 +27,33 @@
|
|||||||
namespace GUIEngine
|
namespace GUIEngine
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
GlyphPageCreator::GlyphPageCreator()
|
GlyphPageCreator::GlyphPageCreator()
|
||||||
{
|
{
|
||||||
page = GUIEngine::getDriver()->createImage(video::ECF_A8R8G8B8, core::dimension2du(512, 512));
|
m_page = GUIEngine::getDriver()->createImage(video::ECF_A8R8G8B8, core::dimension2du(512, 512));
|
||||||
image = 0;
|
m_image = 0;
|
||||||
newchar.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
GlyphPageCreator::~GlyphPageCreator()
|
GlyphPageCreator::~GlyphPageCreator()
|
||||||
{
|
{
|
||||||
clearGlyphPage();
|
clearGlyphPage();
|
||||||
page->drop();
|
clearNewCharHolder();
|
||||||
page = 0;
|
m_page->drop();
|
||||||
|
m_page = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
void GlyphPageCreator::dumpGlyphPage(const core::stringc fn)
|
void GlyphPageCreator::dumpGlyphPage(const core::stringc fn)
|
||||||
{
|
{
|
||||||
GUIEngine::getDriver()->writeImageToFile(page, fn + ".png");
|
GUIEngine::getDriver()->writeImageToFile(m_page, fn + ".png");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
bool GlyphPageCreator::checkEnoughSpace(FT_Bitmap bits)
|
bool GlyphPageCreator::checkEnoughSpace(FT_Bitmap bits)
|
||||||
{
|
{
|
||||||
core::dimension2du d(bits.width + 1, bits.rows + 1);
|
core::dimension2du d(bits.width + 1, bits.rows + 1);
|
||||||
@ -53,39 +61,63 @@ bool GlyphPageCreator::checkEnoughSpace(FT_Bitmap bits)
|
|||||||
texture_size = d.getOptimalSize(!(GUIEngine::getDriver()->queryFeature(video::EVDF_TEXTURE_NPOT)),
|
texture_size = d.getOptimalSize(!(GUIEngine::getDriver()->queryFeature(video::EVDF_TEXTURE_NPOT)),
|
||||||
!(GUIEngine::getDriver()->queryFeature(video::EVDF_TEXTURE_NSQUARE)), true, 0);
|
!(GUIEngine::getDriver()->queryFeature(video::EVDF_TEXTURE_NSQUARE)), true, 0);
|
||||||
|
|
||||||
if ((used_width + texture_size.Width > 512 && used_height + temp_height + texture_size.Height > 512)
|
if ((m_used_width + texture_size.Width > 512 && m_used_height + m_temp_height + texture_size.Height > 512)
|
||||||
|| used_height + texture_size.Height > 512)
|
|| m_used_height + texture_size.Height > 512)
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void GlyphPageCreator::clearNewCharHolder()
|
||||||
|
{
|
||||||
|
m_new_char_holder.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
void GlyphPageCreator::clearGlyphPage()
|
void GlyphPageCreator::clearGlyphPage()
|
||||||
{
|
{
|
||||||
used_width = 0;
|
m_used_width = 0;
|
||||||
temp_height = 0;
|
m_temp_height = 0;
|
||||||
used_height = 0;
|
m_used_height = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
void GlyphPageCreator::createNewGlyphPage()
|
void GlyphPageCreator::createNewGlyphPage()
|
||||||
{
|
{
|
||||||
//Clean the current glyph page by filling it with transparent content
|
//Clean the current glyph page by filling it with transparent content
|
||||||
page->fill(video::SColor(0, 255, 255, 255));
|
m_page->fill(video::SColor(0, 255, 255, 255));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
video::IImage* GlyphPageCreator::getPage()
|
video::IImage* GlyphPageCreator::getPage()
|
||||||
{
|
{
|
||||||
return page;
|
return m_page;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
core::stringw GlyphPageCreator::getNewChar()
|
core::stringw GlyphPageCreator::getNewChar()
|
||||||
{
|
{
|
||||||
core::stringw c;
|
core::stringw c;
|
||||||
for (std::set<wchar_t>::iterator it = newchar.begin(); it != newchar.end(); ++it)
|
for (std::set<wchar_t>::iterator it = m_new_char_holder.begin(); it != m_new_char_holder.end(); ++it)
|
||||||
c += *it;
|
c += *it;
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void GlyphPageCreator::insertChar(const wchar_t c)
|
||||||
|
{
|
||||||
|
m_new_char_holder.insert(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
bool GlyphPageCreator::insertGlyph(FT_Bitmap bits, core::rect<s32>& rect)
|
bool GlyphPageCreator::insertGlyph(FT_Bitmap bits, core::rect<s32>& rect)
|
||||||
{
|
{
|
||||||
core::dimension2du d(bits.width + 1, bits.rows + 1);
|
core::dimension2du d(bits.width + 1, bits.rows + 1);
|
||||||
@ -98,13 +130,13 @@ bool GlyphPageCreator::insertGlyph(FT_Bitmap bits, core::rect<s32>& rect)
|
|||||||
// Create our blank image.
|
// Create our blank image.
|
||||||
texture_size = d.getOptimalSize(!(GUIEngine::getDriver()->queryFeature(video::EVDF_TEXTURE_NPOT)),
|
texture_size = d.getOptimalSize(!(GUIEngine::getDriver()->queryFeature(video::EVDF_TEXTURE_NPOT)),
|
||||||
!(GUIEngine::getDriver()->queryFeature(video::EVDF_TEXTURE_NSQUARE)), true, 0);
|
!(GUIEngine::getDriver()->queryFeature(video::EVDF_TEXTURE_NSQUARE)), true, 0);
|
||||||
image = GUIEngine::getDriver()->createImage(video::ECF_A8R8G8B8, texture_size);
|
m_image = GUIEngine::getDriver()->createImage(video::ECF_A8R8G8B8, texture_size);
|
||||||
image->fill(video::SColor(0, 255, 255, 255));
|
m_image->fill(video::SColor(0, 255, 255, 255));
|
||||||
|
|
||||||
// Load the grayscale data in.
|
// Load the grayscale data in.
|
||||||
const float gray_count = static_cast<float>(bits.num_grays);
|
const float gray_count = static_cast<float>(bits.num_grays);
|
||||||
const u32 image_pitch = image->getPitch() / sizeof(u32);
|
const u32 image_pitch = m_image->getPitch() / sizeof(u32);
|
||||||
u32* image_data = (u32*)image->lock();
|
u32* image_data = (u32*)m_image->lock();
|
||||||
u8* glyph_data = bits.buffer;
|
u8* glyph_data = bits.buffer;
|
||||||
for (u32 y = 0; y < (unsigned)bits.rows; ++y)
|
for (u32 y = 0; y < (unsigned)bits.rows; ++y)
|
||||||
{
|
{
|
||||||
@ -116,37 +148,37 @@ bool GlyphPageCreator::insertGlyph(FT_Bitmap bits, core::rect<s32>& rect)
|
|||||||
}
|
}
|
||||||
glyph_data += bits.pitch;
|
glyph_data += bits.pitch;
|
||||||
}
|
}
|
||||||
image->unlock();
|
m_image->unlock();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!image)
|
if (!m_image)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
//Done creating a single glyph, now copy to the glyph page...
|
//Done creating a single glyph, now copy to the glyph page...
|
||||||
//Determine the linebreak location
|
//Determine the linebreak location
|
||||||
if (used_width + texture_size.Width > 512)
|
if (m_used_width + texture_size.Width > 512)
|
||||||
{
|
{
|
||||||
used_width = 0;
|
m_used_width = 0;
|
||||||
used_height += temp_height;
|
m_used_height += m_temp_height;
|
||||||
temp_height = 0;
|
m_temp_height = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Copy now
|
//Copy now
|
||||||
image->copyTo(page, core::position2di(used_width, used_height));
|
m_image->copyTo(m_page, core::position2di(m_used_width, m_used_height));
|
||||||
|
|
||||||
//Store the rectangle of current glyph
|
//Store the rectangle of current glyph
|
||||||
rect = core::rect<s32> (used_width, used_height, used_width + bits.width, used_height + bits.rows);
|
rect = core::rect<s32> (m_used_width, m_used_height, m_used_width + bits.width, m_used_height + bits.rows);
|
||||||
|
|
||||||
image->drop();
|
m_image->drop();
|
||||||
image = 0;
|
m_image = 0;
|
||||||
|
|
||||||
//Store used area
|
//Store used area
|
||||||
used_width += texture_size.Width;
|
m_used_width += texture_size.Width;
|
||||||
if (temp_height < texture_size.Height)
|
if (m_temp_height < texture_size.Height)
|
||||||
temp_height = texture_size.Height;
|
m_temp_height = texture_size.Height;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,6 +58,10 @@ namespace GUIEngine
|
|||||||
*/
|
*/
|
||||||
void clearGlyphPage();
|
void clearGlyphPage();
|
||||||
|
|
||||||
|
/** Reset characters holder for lazy loading char.
|
||||||
|
*/
|
||||||
|
void clearNewCharHolder();
|
||||||
|
|
||||||
/** Clear (fill it with transparent content) the current glyph page.
|
/** Clear (fill it with transparent content) the current glyph page.
|
||||||
*/
|
*/
|
||||||
void createNewGlyphPage();
|
void createNewGlyphPage();
|
||||||
@ -67,11 +71,16 @@ namespace GUIEngine
|
|||||||
*/
|
*/
|
||||||
video::IImage* getPage();
|
video::IImage* getPage();
|
||||||
|
|
||||||
/** Used to get the string of new characters inside set newchar. (Mainly for debug)
|
/** Used to get the string of new characters inside set m_new_char_holder for lazy char loading.
|
||||||
* \return string of wild-character.
|
* \return string of wild-character.
|
||||||
*/
|
*/
|
||||||
core::stringw getNewChar();
|
core::stringw getNewChar();
|
||||||
|
|
||||||
|
/** Used to insert a single new character into glyph page used for lazy char loading.
|
||||||
|
* \param c A new character.
|
||||||
|
*/
|
||||||
|
void insertChar(const wchar_t c);
|
||||||
|
|
||||||
/** Used to insert a single glyph bitmap into the glyph page
|
/** Used to insert a single glyph bitmap into the glyph page
|
||||||
* \param bits The Glyph bitmap inputted.
|
* \param bits The Glyph bitmap inputted.
|
||||||
* \param rect Give the rectangle of the glyph on the page.
|
* \param rect Give the rectangle of the glyph on the page.
|
||||||
@ -79,22 +88,22 @@ namespace GUIEngine
|
|||||||
*/
|
*/
|
||||||
bool insertGlyph(FT_Bitmap bits, core::rect<s32>& rect);
|
bool insertGlyph(FT_Bitmap bits, core::rect<s32>& rect);
|
||||||
|
|
||||||
/** A temporary holder stored new char to be inserted.
|
|
||||||
*/
|
|
||||||
std::set<wchar_t> newchar;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/** A temporary storage for a single glyph.
|
/** A temporary storage for a single glyph.
|
||||||
*/
|
*/
|
||||||
video::IImage* image;
|
video::IImage* m_image;
|
||||||
|
|
||||||
|
/** A temporary holder stored new char to be inserted.
|
||||||
|
*/
|
||||||
|
std::set<wchar_t> m_new_char_holder;
|
||||||
|
|
||||||
/** A full glyph page.
|
/** A full glyph page.
|
||||||
*/
|
*/
|
||||||
video::IImage* page;
|
video::IImage* m_page;
|
||||||
|
|
||||||
u32 temp_height;
|
u32 m_temp_height;
|
||||||
u32 used_width;
|
u32 m_used_width;
|
||||||
u32 used_height;
|
u32 m_used_height;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // guiengine
|
} // guiengine
|
||||||
|
@ -1,6 +1,20 @@
|
|||||||
// Copyright (C) 2002-2015 Nikolaus Gebhardt
|
// SuperTuxKart - a fun racing game with go-kart
|
||||||
// This file is part of the "Irrlicht Engine".
|
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
// Copyright (C) 2015 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.
|
||||||
|
|
||||||
#include "guiengine/scalable_font.hpp"
|
#include "guiengine/scalable_font.hpp"
|
||||||
|
|
||||||
@ -20,15 +34,18 @@
|
|||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cwctype>
|
#include <cwctype>
|
||||||
|
|
||||||
|
using namespace GUIEngine;
|
||||||
|
|
||||||
namespace irr
|
namespace irr
|
||||||
{
|
{
|
||||||
namespace gui
|
namespace gui
|
||||||
{
|
{
|
||||||
|
|
||||||
//! constructor
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
ScalableFont::ScalableFont(IGUIEnvironment *env, TTFLoadingType type)
|
ScalableFont::ScalableFont(IGUIEnvironment *env, TTFLoadingType type)
|
||||||
: Driver(0), SpriteBank(0), Environment(env), WrongCharacter(0),
|
: m_video_driver(0), m_spritebank(0), m_gui_env(env),
|
||||||
MaxHeight(0), GlobalKerningWidth(0), GlobalKerningHeight(0)
|
m_max_height(0), m_global_kerning_width(0), m_global_kerning_height(0)
|
||||||
{
|
{
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
setDebugName("ScalableFont");
|
setDebugName("ScalableFont");
|
||||||
@ -42,95 +59,73 @@ ScalableFont::ScalableFont(IGUIEnvironment *env, TTFLoadingType type)
|
|||||||
m_black_border = false;
|
m_black_border = false;
|
||||||
m_type = type;
|
m_type = type;
|
||||||
m_font_use = (FontUse)0;
|
m_font_use = (FontUse)0;
|
||||||
m_dpi = 0;
|
|
||||||
m_shadow = false;
|
m_shadow = false;
|
||||||
m_mono_space_digits = false;
|
m_mono_space_digits = false;
|
||||||
m_rtl = translations->isRTLLanguage();
|
m_rtl = translations->isRTLLanguage();
|
||||||
|
|
||||||
if (Environment)
|
if (m_gui_env)
|
||||||
{
|
{
|
||||||
// don't grab environment, to avoid circular references
|
// don't grab environment, to avoid circular references
|
||||||
Driver = Environment->getVideoDriver();
|
m_video_driver = m_gui_env->getVideoDriver();
|
||||||
|
|
||||||
SpriteBank = Environment->addEmptySpriteBank((std::to_string(type)).c_str());
|
m_spritebank = m_gui_env->addEmptySpriteBank((std::to_string(type)).c_str());
|
||||||
if (SpriteBank)
|
if (m_spritebank)
|
||||||
SpriteBank->grab();
|
m_spritebank->grab();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Driver)
|
if (m_video_driver)
|
||||||
Driver->grab();
|
m_video_driver->grab();
|
||||||
|
|
||||||
setInvisibleCharacters ( L" " );
|
setInvisibleCharacters(L" ");
|
||||||
|
|
||||||
if (!loadTTF())
|
if (!loadTTF())
|
||||||
{
|
{
|
||||||
Log::fatal("ScalableFont", "Loading TTF font failed");
|
Log::fatal("ScalableFont", "Loading TTF font failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(Areas.size() > 0);
|
assert(m_areas.size() > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScalableFont::recreateFromLanguage()
|
// ----------------------------------------------------------------------------
|
||||||
{
|
|
||||||
//Clean previous font data
|
|
||||||
SpriteBank->clear();
|
|
||||||
Areas.clear();
|
|
||||||
CharacterMap.clear();
|
|
||||||
WrongCharacter = 0;
|
|
||||||
MaxHeight = 0;
|
|
||||||
GlobalKerningWidth = 0;
|
|
||||||
GlobalKerningHeight = 0;
|
|
||||||
|
|
||||||
//Set to default scale to reload font
|
|
||||||
m_scale = 1;
|
|
||||||
//Reload
|
|
||||||
if (!loadTTF())
|
|
||||||
{
|
|
||||||
Log::fatal("ScalableFont", "Recreation of TTF font failed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//! destructor
|
|
||||||
ScalableFont::~ScalableFont()
|
ScalableFont::~ScalableFont()
|
||||||
{
|
{
|
||||||
if (!m_is_hollow_copy)
|
if (!m_is_hollow_copy)
|
||||||
{
|
{
|
||||||
if (Driver) Driver->drop();
|
if (m_video_driver) m_video_driver->drop();
|
||||||
if (SpriteBank) SpriteBank->drop();
|
if (m_spritebank) m_spritebank->drop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScalableFont::updateRTL()
|
// ----------------------------------------------------------------------------
|
||||||
{
|
|
||||||
m_rtl = translations->isRTLLanguage();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScalableFont::setShadow(const irr::video::SColor &col)
|
|
||||||
{
|
|
||||||
m_shadow = true;
|
|
||||||
m_shadow_color = col;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! loads a font from a TTF file
|
|
||||||
bool ScalableFont::loadTTF()
|
bool ScalableFont::loadTTF()
|
||||||
{
|
{
|
||||||
if (!SpriteBank)
|
if (!m_spritebank)
|
||||||
{
|
{
|
||||||
Log::error("ScalableFont::loadTTF", "SpriteBank is NULL!!");
|
Log::error("ScalableFont::loadTTF", "SpriteBank is NULL!!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch(m_type)
|
||||||
|
{
|
||||||
|
case T_NORMAL:
|
||||||
|
m_font_use = F_DEFAULT;
|
||||||
|
break;
|
||||||
|
case T_DIGIT:
|
||||||
|
m_font_use = F_DIGIT;
|
||||||
|
break;
|
||||||
|
case T_BOLD:
|
||||||
|
m_font_use = F_BOLD;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
GUIEngine::GlyphPageCreator* gp_creator = GUIEngine::getGlyphPageCreator();
|
GUIEngine::GlyphPageCreator* gp_creator = GUIEngine::getGlyphPageCreator();
|
||||||
|
|
||||||
//Initialize glyph slot
|
//Initialize glyph slot
|
||||||
FT_GlyphSlot slot;
|
FT_GlyphSlot slot;
|
||||||
FT_Error err;
|
FT_Error err;
|
||||||
|
|
||||||
//Determine which font(face) and size to load,
|
|
||||||
//also get all used char base on current language settings
|
|
||||||
getFontProperties cur_prop(translations->getCurrentLanguageNameCode().c_str(), m_type, m_font_use);
|
|
||||||
m_dpi = cur_prop.size;
|
|
||||||
|
|
||||||
std::vector <s32> offset;
|
std::vector <s32> offset;
|
||||||
std::vector <s32> bearingx;
|
std::vector <s32> bearingx;
|
||||||
std::vector <s32> advance;
|
std::vector <s32> advance;
|
||||||
@ -140,14 +135,15 @@ bool ScalableFont::loadTTF()
|
|||||||
s32 curr_maxheight = 0;
|
s32 curr_maxheight = 0;
|
||||||
s32 t;
|
s32 t;
|
||||||
u32 texno = 0;
|
u32 texno = 0;
|
||||||
SpriteBank->addTexture(NULL);
|
m_spritebank->addTexture(NULL);
|
||||||
gp_creator->clearGlyphPage();
|
gp_creator->clearGlyphPage();
|
||||||
gp_creator->createNewGlyphPage();
|
gp_creator->createNewGlyphPage();
|
||||||
|
|
||||||
GUIEngine::FTEnvironment* ft_env = GUIEngine::getFreetype();
|
GUIEngine::FTEnvironment* ft_env = GUIEngine::getFreetype();
|
||||||
|
std::set<wchar_t> preload_char = getPreloadCharacters(m_type);
|
||||||
|
|
||||||
it = cur_prop.usedchar.begin();
|
it = preload_char.begin();
|
||||||
while (it != cur_prop.usedchar.end())
|
while (it != preload_char.end())
|
||||||
{
|
{
|
||||||
SGUISpriteFrame f;
|
SGUISpriteFrame f;
|
||||||
SGUISprite s;
|
SGUISprite s;
|
||||||
@ -157,14 +153,10 @@ bool ScalableFont::loadTTF()
|
|||||||
if (m_type == T_BOLD) //Lite-Fontconfig for stk, this one is specifically for bold title
|
if (m_type == T_BOLD) //Lite-Fontconfig for stk, this one is specifically for bold title
|
||||||
{
|
{
|
||||||
int count = F_BOLD;
|
int count = F_BOLD;
|
||||||
while (count < irr::gui::F_COUNT)
|
while (count < GUIEngine::F_COUNT)
|
||||||
{
|
{
|
||||||
m_font_use = (FontUse)count;
|
m_font_use = (FontUse)count;
|
||||||
FT_Face curr_face = ft_env->ft_face[m_font_use];
|
FT_Face curr_face = ft_env->getFace(m_font_use);
|
||||||
|
|
||||||
err = FT_Set_Pixel_Sizes(curr_face, 0, m_dpi);
|
|
||||||
if (err)
|
|
||||||
Log::error("ScalableFont::loadTTF", "Can't set font size.");
|
|
||||||
|
|
||||||
idx = FT_Get_Char_Index(curr_face, *it);
|
idx = FT_Get_Char_Index(curr_face, *it);
|
||||||
if (idx > 0) break;
|
if (idx > 0) break;
|
||||||
@ -173,15 +165,11 @@ bool ScalableFont::loadTTF()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FT_Face curr_face = ft_env->ft_face[m_font_use];
|
FT_Face curr_face = ft_env->getFace(m_font_use);
|
||||||
err = FT_Set_Pixel_Sizes(curr_face, 0, m_dpi);
|
|
||||||
if (err)
|
|
||||||
Log::error("ScalableFont::loadTTF", "Can't set font size.");
|
|
||||||
|
|
||||||
idx = FT_Get_Char_Index(curr_face, *it);
|
idx = FT_Get_Char_Index(curr_face, *it);
|
||||||
}
|
}
|
||||||
|
|
||||||
FT_Face curr_face = ft_env->ft_face[m_font_use];
|
FT_Face curr_face = ft_env->getFace(m_font_use);
|
||||||
slot = curr_face->glyph;
|
slot = curr_face->glyph;
|
||||||
|
|
||||||
if (idx)
|
if (idx)
|
||||||
@ -193,7 +181,7 @@ bool ScalableFont::loadTTF()
|
|||||||
Log::error("ScalableFont::loadTTF", "Can't load a single glyph.");
|
Log::error("ScalableFont::loadTTF", "Can't load a single glyph.");
|
||||||
|
|
||||||
// Store vertical offset on line.
|
// Store vertical offset on line.
|
||||||
s32 curr_offset = (curr_face->glyph->metrics.height >> 6) - curr_face->glyph->bitmap_top;
|
s32 curr_offset = (curr_face->glyph->metrics.height >> 6) - (curr_face->glyph->metrics.horiBearingY >> 6);
|
||||||
offset.push_back(curr_offset);
|
offset.push_back(curr_offset);
|
||||||
|
|
||||||
// This is to be used later.
|
// This is to be used later.
|
||||||
@ -203,7 +191,7 @@ bool ScalableFont::loadTTF()
|
|||||||
curr_maxheight = t;
|
curr_maxheight = t;
|
||||||
|
|
||||||
// Store horizontal padding (bearingX).
|
// Store horizontal padding (bearingX).
|
||||||
s32 curr_bearingx = curr_face->glyph->bitmap_left;
|
s32 curr_bearingx = curr_face->glyph->metrics.horiBearingX >> 6;
|
||||||
bearingx.push_back(curr_bearingx);
|
bearingx.push_back(curr_bearingx);
|
||||||
|
|
||||||
// Store total width on horizontal line.
|
// Store total width on horizontal line.
|
||||||
@ -213,7 +201,7 @@ bool ScalableFont::loadTTF()
|
|||||||
// Convert to an anti-aliased bitmap
|
// Convert to an anti-aliased bitmap
|
||||||
FT_Bitmap bits = slot->bitmap;
|
FT_Bitmap bits = slot->bitmap;
|
||||||
|
|
||||||
CharacterMap[*it] = SpriteBank->getSprites().size();
|
m_character_map[*it] = m_spritebank->getSprites().size();
|
||||||
|
|
||||||
if (!gp_creator->checkEnoughSpace(bits))
|
if (!gp_creator->checkEnoughSpace(bits))
|
||||||
// Glyph page is full, save current one and reset the current page
|
// Glyph page is full, save current one and reset the current page
|
||||||
@ -221,9 +209,9 @@ bool ScalableFont::loadTTF()
|
|||||||
#ifdef FONT_DEBUG
|
#ifdef FONT_DEBUG
|
||||||
gp_creator->dumpGlyphPage(((std::to_string(m_type)) + "_" + (std::to_string(texno))).c_str());
|
gp_creator->dumpGlyphPage(((std::to_string(m_type)) + "_" + (std::to_string(texno))).c_str());
|
||||||
#endif
|
#endif
|
||||||
SpriteBank->setTexture(texno, Driver->addTexture("Glyph_page", gp_creator->getPage()));
|
m_spritebank->setTexture(texno, m_video_driver->addTexture("Glyph_page", gp_creator->getPage()));
|
||||||
gp_creator->clearGlyphPage();
|
gp_creator->clearGlyphPage();
|
||||||
SpriteBank->addTexture(NULL);
|
m_spritebank->addTexture(NULL);
|
||||||
gp_creator->createNewGlyphPage();
|
gp_creator->createNewGlyphPage();
|
||||||
texno++;
|
texno++;
|
||||||
}
|
}
|
||||||
@ -231,36 +219,36 @@ bool ScalableFont::loadTTF()
|
|||||||
// Inserting now
|
// Inserting now
|
||||||
if (gp_creator->insertGlyph(bits, rectangle))
|
if (gp_creator->insertGlyph(bits, rectangle))
|
||||||
{
|
{
|
||||||
f.rectNumber = SpriteBank->getPositions().size();
|
f.rectNumber = m_spritebank->getPositions().size();
|
||||||
f.textureNumber = texno;
|
f.textureNumber = texno;
|
||||||
|
|
||||||
// add frame to sprite
|
// add frame to sprite
|
||||||
s.Frames.push_back(f);
|
s.Frames.push_back(f);
|
||||||
s.frameTime = 0;
|
s.frameTime = 0;
|
||||||
|
|
||||||
SpriteBank->getPositions().push_back(rectangle);
|
m_spritebank->getPositions().push_back(rectangle);
|
||||||
SpriteBank->getSprites().push_back(s);
|
m_spritebank->getSprites().push_back(s);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for glyph page which can fit all characters
|
// Check for glyph page which can fit all characters
|
||||||
if (it == --cur_prop.usedchar.end())
|
if (it == --preload_char.end())
|
||||||
{
|
{
|
||||||
#ifdef FONT_DEBUG
|
#ifdef FONT_DEBUG
|
||||||
gp_creator->dumpGlyphPage(((std::to_string(m_type)) + "_" + (std::to_string(texno))).c_str());
|
gp_creator->dumpGlyphPage(((std::to_string(m_type)) + "_" + (std::to_string(texno))).c_str());
|
||||||
#endif
|
#endif
|
||||||
if (m_type == T_NORMAL)
|
if (m_type == T_NORMAL)
|
||||||
{
|
{
|
||||||
LastNormalPage = Driver->addTexture("Glyph_page", gp_creator->getPage());
|
m_last_normal_page = m_video_driver->addTexture("Glyph_page", gp_creator->getPage());
|
||||||
SpriteBank->setTexture(texno, LastNormalPage);
|
m_spritebank->setTexture(texno, m_last_normal_page);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
SpriteBank->setTexture(texno, Driver->addTexture("Glyph_page", gp_creator->getPage()));
|
m_spritebank->setTexture(texno, m_video_driver->addTexture("Glyph_page", gp_creator->getPage()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*it == (wchar_t)32 && SpriteBank->getPositions().size() == 1)
|
if (*it == (wchar_t)32 && m_spritebank->getPositions().size() == 1)
|
||||||
continue; //Preventing getAreaIDFromCharacter of whitespace == 0, which make space disappear
|
continue; //Preventing getAreaIDFromCharacter of whitespace == 0, which make space disappear
|
||||||
else ++it;
|
else ++it;
|
||||||
}
|
}
|
||||||
@ -268,28 +256,28 @@ bool ScalableFont::loadTTF()
|
|||||||
//Fix unused glyphs....
|
//Fix unused glyphs....
|
||||||
if (m_type == T_NORMAL || T_BOLD)
|
if (m_type == T_NORMAL || T_BOLD)
|
||||||
{
|
{
|
||||||
CharacterMap[(wchar_t)9] = getAreaIDFromCharacter((wchar_t)160, NULL); //Use non-breaking space glyph to tab.
|
m_character_map[(wchar_t)9] = getAreaIDFromCharacter((wchar_t)160, NULL); //Use non-breaking space glyph to tab.
|
||||||
CharacterMap[(wchar_t)173] = 0; //Don't need a glyph for the soft hypen, as it only print when not having enough space.
|
m_character_map[(wchar_t)173] = 0; //Don't need a glyph for the soft hypen, as it only print when not having enough space.
|
||||||
//And then it will convert to a "-".
|
//And then it will convert to a "-".
|
||||||
|
|
||||||
if (m_type == T_NORMAL)
|
if (m_type == T_NORMAL)
|
||||||
{
|
{
|
||||||
CharacterMap[(wchar_t)8204] = 0; //They are zero width chars found in Arabic.
|
m_character_map[(wchar_t)8204] = 0; //They are zero width chars found in Arabic.
|
||||||
CharacterMap[(wchar_t)65279] = 0;
|
m_character_map[(wchar_t)65279] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_type == T_BOLD)
|
if (m_type == T_BOLD)
|
||||||
{
|
{
|
||||||
setlocale(LC_ALL, "en_US.UTF8");
|
setlocale(LC_ALL, "en_US.UTF8");
|
||||||
for (it = cur_prop.usedchar.begin(); it != cur_prop.usedchar.end(); ++it)
|
for (it = preload_char.begin(); it != preload_char.end(); ++it)
|
||||||
{
|
{
|
||||||
if (iswupper((wchar_t)*it) && *it < 640)
|
if (iswupper((wchar_t)*it) && *it < 640)
|
||||||
CharacterMap[towlower((wchar_t)*it)] = getAreaIDFromCharacter(*it, NULL);
|
m_character_map[towlower((wchar_t)*it)] = getAreaIDFromCharacter(*it, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned int n = 0 ; n < SpriteBank->getSprites().size(); ++n)
|
for (unsigned int n = 0 ; n < m_spritebank->getSprites().size(); ++n)
|
||||||
{
|
{
|
||||||
//Storing now
|
//Storing now
|
||||||
SFontArea a;
|
SFontArea a;
|
||||||
@ -312,17 +300,15 @@ bool ScalableFont::loadTTF()
|
|||||||
else
|
else
|
||||||
a.width = advance.at(n);
|
a.width = advance.at(n);
|
||||||
// add character to font
|
// add character to font
|
||||||
Areas.push_back(a);
|
m_areas.push_back(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
WrongCharacter = getAreaIDFromCharacter(L' ', NULL);
|
|
||||||
|
|
||||||
//Reserve 10 for normal font new characters added, 40 for digit font to display separately
|
//Reserve 10 for normal font new characters added, 40 for digit font to display separately
|
||||||
//Consider fallback font (bold) too
|
//Consider fallback font (bold) too
|
||||||
MaxHeight = (int)((curr_maxheight + (m_type == T_DIGIT ? 40 : 10) +
|
m_max_height = (int)((curr_maxheight + (m_type == T_DIGIT ? 40 : 10) +
|
||||||
(m_type == T_BOLD ? 20 : 0))*m_scale);
|
(m_type == T_BOLD ? 20 : 0))*m_scale);
|
||||||
|
|
||||||
GlyphMaxHeight = curr_maxheight;
|
m_glyph_max_height = curr_maxheight;
|
||||||
|
|
||||||
for(wchar_t c='0'; c<='9'; c++)
|
for(wchar_t c='0'; c<='9'; c++)
|
||||||
{
|
{
|
||||||
@ -336,25 +322,26 @@ bool ScalableFont::loadTTF()
|
|||||||
{
|
{
|
||||||
case T_NORMAL:
|
case T_NORMAL:
|
||||||
Log::info("ScalableFont::loadTTF", "Created %d glyphs "
|
Log::info("ScalableFont::loadTTF", "Created %d glyphs "
|
||||||
"supporting %d characters for normal font %s at %d dpi using %d glyph page(s)."
|
"supporting %d characters for normal font %s using %d glyph page(s)."
|
||||||
, Areas.size(), CharacterMap.size(), GUIEngine::getFreetype()->ft_face[m_font_use]->family_name, m_dpi, SpriteBank->getTextureCount());
|
, m_areas.size(), m_character_map.size(), ft_env->getFace(m_font_use)->family_name, m_spritebank->getTextureCount());
|
||||||
break;
|
break;
|
||||||
case T_DIGIT:
|
case T_DIGIT:
|
||||||
Log::info("ScalableFont::loadTTF", "Created %d glyphs "
|
Log::info("ScalableFont::loadTTF", "Created %d glyphs "
|
||||||
"supporting %d characters for high-res digits font %s at %d dpi using %d glyph page(s)."
|
"supporting %d characters for high-res digits font %s using %d glyph page(s)."
|
||||||
, Areas.size(), CharacterMap.size(), GUIEngine::getFreetype()->ft_face[m_font_use]->family_name, m_dpi, SpriteBank->getTextureCount());
|
, m_areas.size(), m_character_map.size(), ft_env->getFace(m_font_use)->family_name, m_spritebank->getTextureCount());
|
||||||
break;
|
break;
|
||||||
case T_BOLD:
|
case T_BOLD:
|
||||||
Log::info("ScalableFont::loadTTF", "Created %d glyphs "
|
Log::info("ScalableFont::loadTTF", "Created %d glyphs "
|
||||||
"supporting %d characters for bold title font %s at %d dpi using %d glyph page(s)."
|
"supporting %d characters for bold title font %s using %d glyph page(s)."
|
||||||
, Areas.size(), CharacterMap.size(), GUIEngine::getFreetype()->ft_face[m_font_use]->family_name, m_dpi, SpriteBank->getTextureCount());
|
, m_areas.size(), m_character_map.size(), ft_env->getFace(m_font_use)->family_name, m_spritebank->getTextureCount());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! lazy load new characters discovered in normal font
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
bool ScalableFont::lazyLoadChar()
|
bool ScalableFont::lazyLoadChar()
|
||||||
{
|
{
|
||||||
//Mainly copy from loadTTF(), so removing unnecessary comments
|
//Mainly copy from loadTTF(), so removing unnecessary comments
|
||||||
@ -370,10 +357,9 @@ bool ScalableFont::lazyLoadChar()
|
|||||||
s32 bearingx;
|
s32 bearingx;
|
||||||
s32 curr_offset;
|
s32 curr_offset;
|
||||||
s32 width;
|
s32 width;
|
||||||
u32 texno = SpriteBank->getTextureCount() - 1;
|
u32 texno = m_spritebank->getTextureCount() - 1;
|
||||||
std::set<wchar_t>::iterator it;
|
core::stringw lazy_load = gp_creator->getNewChar();
|
||||||
it = gp_creator->newchar.begin();
|
for (u32 i = 0; i < lazy_load.size(); ++i)
|
||||||
while (it != gp_creator->newchar.end())
|
|
||||||
{
|
{
|
||||||
SGUISpriteFrame f;
|
SGUISpriteFrame f;
|
||||||
SGUISprite s;
|
SGUISprite s;
|
||||||
@ -381,24 +367,18 @@ bool ScalableFont::lazyLoadChar()
|
|||||||
|
|
||||||
//Lite-Fontconfig for stk
|
//Lite-Fontconfig for stk
|
||||||
int idx;
|
int idx;
|
||||||
int font = irr::gui::F_DEFAULT;
|
int font = F_DEFAULT;
|
||||||
while (font <= irr::gui::F_LAST_REGULAR_FONT)
|
while (font <= F_LAST_REGULAR_FONT)
|
||||||
{
|
{
|
||||||
m_font_use = (FontUse)font;
|
m_font_use = (FontUse)font;
|
||||||
|
|
||||||
FT_Face face = ft_env->ft_face[font];
|
idx = FT_Get_Char_Index(ft_env->getFace(m_font_use), lazy_load[i]);
|
||||||
|
|
||||||
err = FT_Set_Pixel_Sizes(face, 0, m_dpi);
|
|
||||||
if (err)
|
|
||||||
Log::error("ScalableFont::loadTTF", "Can't set font size.");
|
|
||||||
|
|
||||||
idx = FT_Get_Char_Index(face, *it);
|
|
||||||
if (idx > 0) break;
|
if (idx > 0) break;
|
||||||
|
|
||||||
font++;
|
font++;
|
||||||
}
|
}
|
||||||
|
|
||||||
FT_Face curr_face = ft_env->ft_face[m_font_use];
|
FT_Face curr_face = ft_env->getFace(m_font_use);
|
||||||
|
|
||||||
slot = curr_face->glyph;
|
slot = curr_face->glyph;
|
||||||
|
|
||||||
@ -409,57 +389,56 @@ bool ScalableFont::lazyLoadChar()
|
|||||||
if (err)
|
if (err)
|
||||||
Log::error("ScalableFont::loadTTF", "Can't load a single glyph.");
|
Log::error("ScalableFont::loadTTF", "Can't load a single glyph.");
|
||||||
|
|
||||||
curr_offset = (curr_face->glyph->metrics.height >> 6) - curr_face->glyph->bitmap_top;
|
curr_offset = (curr_face->glyph->metrics.height >> 6) - (curr_face->glyph->metrics.horiBearingY >> 6);
|
||||||
height = curr_face->glyph->metrics.height >> 6;
|
height = curr_face->glyph->metrics.height >> 6;
|
||||||
bearingx = curr_face->glyph->bitmap_left;
|
bearingx = curr_face->glyph->metrics.horiBearingX >> 6;
|
||||||
width = curr_face->glyph->advance.x >> 6;
|
width = curr_face->glyph->advance.x >> 6;
|
||||||
FT_Bitmap bits = slot->bitmap;
|
FT_Bitmap bits = slot->bitmap;
|
||||||
CharacterMap[*it] = SpriteBank->getSprites().size();
|
m_character_map[lazy_load[i]] = m_spritebank->getSprites().size();
|
||||||
|
|
||||||
if (!gp_creator->checkEnoughSpace(bits))
|
if (!gp_creator->checkEnoughSpace(bits))
|
||||||
{
|
{
|
||||||
#ifdef FONT_DEBUG
|
#ifdef FONT_DEBUG
|
||||||
gp_creator->dumpGlyphPage(((std::to_string(m_type)) + "_" + (std::to_string(texno))).c_str());
|
gp_creator->dumpGlyphPage(((std::to_string(m_type)) + "_" + (std::to_string(texno))).c_str());
|
||||||
#endif
|
#endif
|
||||||
SpriteBank->setTexture(texno, Driver->addTexture("Glyph_page", gp_creator->getPage()));
|
m_spritebank->setTexture(texno, m_video_driver->addTexture("Glyph_page", gp_creator->getPage()));
|
||||||
gp_creator->clearGlyphPage();
|
gp_creator->clearGlyphPage();
|
||||||
SpriteBank->addTexture(NULL);
|
m_spritebank->addTexture(NULL);
|
||||||
gp_creator->createNewGlyphPage();
|
gp_creator->createNewGlyphPage();
|
||||||
texno++;
|
texno++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gp_creator->insertGlyph(bits, rectangle))
|
if (gp_creator->insertGlyph(bits, rectangle))
|
||||||
{
|
{
|
||||||
f.rectNumber = SpriteBank->getPositions().size();
|
f.rectNumber = m_spritebank->getPositions().size();
|
||||||
f.textureNumber = texno;
|
f.textureNumber = texno;
|
||||||
s.Frames.push_back(f);
|
s.Frames.push_back(f);
|
||||||
s.frameTime = 0;
|
s.frameTime = 0;
|
||||||
SpriteBank->getPositions().push_back(rectangle);
|
m_spritebank->getPositions().push_back(rectangle);
|
||||||
SpriteBank->getSprites().push_back(s);
|
m_spritebank->getSprites().push_back(s);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
SFontArea a;
|
SFontArea a;
|
||||||
a.spriteno = SpriteBank->getSprites().size() - 1;
|
a.spriteno = m_spritebank->getSprites().size() - 1;
|
||||||
a.offsety = GlyphMaxHeight - height + curr_offset;
|
a.offsety = m_glyph_max_height - height + curr_offset;
|
||||||
a.offsety_bt = -curr_offset;
|
a.offsety_bt = -curr_offset;
|
||||||
a.bearingx = bearingx;
|
a.bearingx = bearingx;
|
||||||
a.width = width;
|
a.width = width;
|
||||||
Areas.push_back(a);
|
m_areas.push_back(a);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
CharacterMap[*it] = 2; //Set wrong character to !, preventing it from loading again
|
m_character_map[lazy_load[i]] = 1; //Set any wrong characters to 1 (space), preventing it from loading again
|
||||||
++it;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef FONT_DEBUG
|
#ifdef FONT_DEBUG
|
||||||
gp_creator->dumpGlyphPage(((std::to_string(m_type)) + "_" + (std::to_string(texno))).c_str());
|
gp_creator->dumpGlyphPage(((std::to_string(m_type)) + "_" + (std::to_string(texno))).c_str());
|
||||||
#endif
|
#endif
|
||||||
gp_creator->newchar.clear(); //Clear the Newly characters in creator after they are loaded
|
gp_creator->clearNewCharHolder(); //Clear the Newly characters in creator after they are loaded
|
||||||
Driver->removeTexture(LastNormalPage); //Remove old texture
|
m_video_driver->removeTexture(m_last_normal_page); //Remove old texture
|
||||||
LastNormalPage = Driver->addTexture("Glyph_page", gp_creator->getPage());
|
m_last_normal_page = m_video_driver->addTexture("Glyph_page", gp_creator->getPage());
|
||||||
SpriteBank->setTexture(texno, LastNormalPage);
|
m_spritebank->setTexture(texno, m_last_normal_page);
|
||||||
|
|
||||||
if (!m_is_hollow_copy)
|
if (!m_is_hollow_copy)
|
||||||
{
|
{
|
||||||
@ -468,73 +447,167 @@ bool ScalableFont::lazyLoadChar()
|
|||||||
}
|
}
|
||||||
|
|
||||||
Log::debug("ScalableFont::lazyLoadChar", "New characters drawn by %s inserted, there are %d glyphs "
|
Log::debug("ScalableFont::lazyLoadChar", "New characters drawn by %s inserted, there are %d glyphs "
|
||||||
"supporting %d characters for normal font at %d dpi using %d glyph page(s) now."
|
"supporting %d characters for normal font using %d glyph page(s) now."
|
||||||
, GUIEngine::getFreetype()->ft_face[m_font_use]->family_name, Areas.size(), CharacterMap.size(), m_dpi, SpriteBank->getTextureCount());
|
, ft_env->getFace(m_font_use)->family_name, m_areas.size(), m_character_map.size(), m_spritebank->getTextureCount());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! force create a new texture (glyph) page in a font
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
void ScalableFont::forceNewPage()
|
void ScalableFont::forceNewPage()
|
||||||
{
|
{
|
||||||
GUIEngine::GlyphPageCreator* gp_creator = GUIEngine::getGlyphPageCreator();
|
GUIEngine::GlyphPageCreator* gp_creator = GUIEngine::getGlyphPageCreator();
|
||||||
|
|
||||||
SpriteBank->setTexture(SpriteBank->getTextureCount() - 1, Driver->addTexture("Glyph_page", gp_creator->getPage()));
|
m_spritebank->setTexture(m_spritebank->getTextureCount() - 1, m_video_driver->addTexture("Glyph_page", gp_creator->getPage()));
|
||||||
gp_creator->clearGlyphPage();
|
gp_creator->clearGlyphPage();
|
||||||
SpriteBank->addTexture(NULL);
|
m_spritebank->addTexture(NULL);
|
||||||
gp_creator->createNewGlyphPage();
|
gp_creator->createNewGlyphPage();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
std::set<wchar_t> ScalableFont::getPreloadCharacters(const GUIEngine::TTFLoadingType type)
|
||||||
|
{
|
||||||
|
std::set<wchar_t> preload_char;
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case T_NORMAL:
|
||||||
|
for (u32 i = 32; i < 128; ++i)
|
||||||
|
preload_char.insert((wchar_t)i); //Include basic Latin
|
||||||
|
|
||||||
|
preload_char.insert((wchar_t)160); //Non-breaking space
|
||||||
|
preload_char.insert((wchar_t)215); //Used on resolution selection screen (X).
|
||||||
|
break;
|
||||||
|
case T_DIGIT:
|
||||||
|
preload_char.insert((wchar_t)32); //Space
|
||||||
|
|
||||||
|
for (u32 i = 47; i < 59; ++i)
|
||||||
|
preload_char.insert((wchar_t)i); //Include chars used by timer and laps count only
|
||||||
|
break;
|
||||||
|
case T_BOLD:
|
||||||
|
preload_char = translations->getCurrentAllChar(); //Loading unique characters
|
||||||
|
|
||||||
|
for (u32 i = 65; i < 256; ++i)
|
||||||
|
preload_char.insert((wchar_t)i); //Include basic Latin too, starting from A (char code 65)
|
||||||
|
|
||||||
|
setlocale(LC_ALL, "en_US.UTF8");
|
||||||
|
std::set<wchar_t>::iterator it = preload_char.begin();
|
||||||
|
|
||||||
|
while (it != preload_char.end())
|
||||||
|
{
|
||||||
|
//Only use all capital letter for bold char with latin (<640 of char code).
|
||||||
|
//Remove all characters (>char code 8191) not used by the title
|
||||||
|
if (((iswlower((wchar_t)*it) || !iswalpha((wchar_t)*it)) && *it < 640) || *it > 8191)
|
||||||
|
it = preload_char.erase(it);
|
||||||
|
else
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Final hack to make stk display title properly
|
||||||
|
for (u32 i = 32; i < 65; ++i)
|
||||||
|
preload_char.insert((wchar_t)i); //Include basic symbol (from space (char code 32) to @(char code 64))
|
||||||
|
|
||||||
|
preload_char.insert((wchar_t)160); //Non-breaking space
|
||||||
|
|
||||||
|
//Remove Ordinal indicator (char code 170 and 186)
|
||||||
|
preload_char.erase((wchar_t)170);
|
||||||
|
preload_char.erase((wchar_t)186);
|
||||||
|
|
||||||
|
preload_char.erase((wchar_t)304); //Remove Capital I-dotted (char code 304) with using "I" altogether.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return preload_char;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void ScalableFont::recreateFromLanguage()
|
||||||
|
{
|
||||||
|
//Clean previous font data
|
||||||
|
m_spritebank->clear();
|
||||||
|
m_areas.clear();
|
||||||
|
m_character_map.clear();
|
||||||
|
m_max_height = 0;
|
||||||
|
m_global_kerning_width = 0;
|
||||||
|
m_global_kerning_height = 0;
|
||||||
|
|
||||||
|
//Set to default scale to reload font
|
||||||
|
m_scale = 1;
|
||||||
|
//Reload
|
||||||
|
if (!loadTTF())
|
||||||
|
{
|
||||||
|
Log::fatal("ScalableFont", "Recreation of TTF font failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void ScalableFont::updateRTL()
|
||||||
|
{
|
||||||
|
m_rtl = translations->isRTLLanguage();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void ScalableFont::setShadow(const irr::video::SColor &col)
|
||||||
|
{
|
||||||
|
m_shadow = true;
|
||||||
|
m_shadow_color = col;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
void ScalableFont::setScale(const float scale)
|
void ScalableFont::setScale(const float scale)
|
||||||
{
|
{
|
||||||
m_scale = scale;
|
m_scale = scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//! set an Pixel Offset on Drawing ( scale position on width )
|
|
||||||
void ScalableFont::setKerningWidth(s32 kerning)
|
void ScalableFont::setKerningWidth(s32 kerning)
|
||||||
{
|
{
|
||||||
GlobalKerningWidth = kerning;
|
m_global_kerning_width = kerning;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
//! set an Pixel Offset on Drawing ( scale position on width )
|
|
||||||
s32 ScalableFont::getKerningWidth(const wchar_t* thisLetter, const wchar_t* previousLetter) const
|
s32 ScalableFont::getKerningWidth(const wchar_t* thisLetter, const wchar_t* previousLetter) const
|
||||||
{
|
{
|
||||||
s32 ret = GlobalKerningWidth;
|
s32 ret = m_global_kerning_width;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
//! set an Pixel Offset on Drawing ( scale position on height )
|
|
||||||
void ScalableFont::setKerningHeight(s32 kerning)
|
void ScalableFont::setKerningHeight(s32 kerning)
|
||||||
{
|
{
|
||||||
GlobalKerningHeight = kerning;
|
m_global_kerning_height = kerning;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
//! set an Pixel Offset on Drawing ( scale position on height )
|
|
||||||
s32 ScalableFont::getKerningHeight () const
|
s32 ScalableFont::getKerningHeight () const
|
||||||
{
|
{
|
||||||
return GlobalKerningHeight;
|
return m_global_kerning_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
//! returns the sprite number from a given character
|
|
||||||
u32 ScalableFont::getSpriteNoFromChar(const wchar_t *c) const
|
u32 ScalableFont::getSpriteNoFromChar(const wchar_t *c) const
|
||||||
{
|
{
|
||||||
return Areas[getAreaIDFromCharacter(*c, NULL)].spriteno;
|
return m_areas[getAreaIDFromCharacter(*c, NULL)].spriteno;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
s32 ScalableFont::getAreaIDFromCharacter(const wchar_t c, bool* fallback_font) const
|
s32 ScalableFont::getAreaIDFromCharacter(const wchar_t c, bool* fallback_font) const
|
||||||
{
|
{
|
||||||
std::map<wchar_t, s32>::const_iterator n = CharacterMap.find(c);
|
std::map<wchar_t, s32>::const_iterator n = m_character_map.find(c);
|
||||||
if (n != CharacterMap.end())
|
if (n != m_character_map.end())
|
||||||
{
|
{
|
||||||
if (fallback_font != NULL) *fallback_font = false;
|
if (fallback_font != NULL) *fallback_font = false;
|
||||||
//Log::info("ScalableFont", "Character %d found in font", (int)c);
|
//Log::info("ScalableFont", "Character %d found in font", (int)c);
|
||||||
@ -550,10 +623,12 @@ s32 ScalableFont::getAreaIDFromCharacter(const wchar_t c, bool* fallback_font) c
|
|||||||
{
|
{
|
||||||
//Log::warn("ScalableFont", "The font does not have this character: <%d>", (int)c);
|
//Log::warn("ScalableFont", "The font does not have this character: <%d>", (int)c);
|
||||||
if (fallback_font != NULL) *fallback_font = false;
|
if (fallback_font != NULL) *fallback_font = false;
|
||||||
return WrongCharacter;
|
return 1; //The first preload character in all type of fonts is space, which is 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
const ScalableFont::SFontArea &ScalableFont::getAreaFromCharacter(const wchar_t c,
|
const ScalableFont::SFontArea &ScalableFont::getAreaFromCharacter(const wchar_t c,
|
||||||
bool* fallback_font) const
|
bool* fallback_font) const
|
||||||
{
|
{
|
||||||
@ -563,8 +638,8 @@ const ScalableFont::SFontArea &ScalableFont::getAreaFromCharacter(const wchar_t
|
|||||||
if(m_mono_space_digits && ( (c>=L'0' && c<=L'9') || c==L' ' ) )
|
if(m_mono_space_digits && ( (c>=L'0' && c<=L'9') || c==L' ' ) )
|
||||||
{
|
{
|
||||||
const SFontArea &area = (fallback_font && *fallback_font)
|
const SFontArea &area = (fallback_font && *fallback_font)
|
||||||
? m_fallback_font->Areas[area_id]
|
? m_fallback_font->m_areas[area_id]
|
||||||
: Areas[area_id];
|
: m_areas[area_id];
|
||||||
m_max_digit_area.spriteno = area.spriteno;
|
m_max_digit_area.spriteno = area.spriteno;
|
||||||
return m_max_digit_area;
|
return m_max_digit_area;
|
||||||
}
|
}
|
||||||
@ -573,25 +648,36 @@ const ScalableFont::SFontArea &ScalableFont::getAreaFromCharacter(const wchar_t
|
|||||||
|
|
||||||
if (use_fallback_font)
|
if (use_fallback_font)
|
||||||
{
|
{
|
||||||
assert(area_id < (int)m_fallback_font->Areas.size());
|
assert(area_id < (int)m_fallback_font->m_areas.size());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
assert(area_id < (int)Areas.size());
|
assert(area_id < (int)m_areas.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: fallback_font can be NULL
|
// Note: fallback_font can be NULL
|
||||||
return ( use_fallback_font ? m_fallback_font->Areas[area_id] : Areas[area_id]);
|
return ( use_fallback_font ? m_fallback_font->m_areas[area_id] : m_areas[area_id]);
|
||||||
} // getAreaFromCharacter
|
} // getAreaFromCharacter
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
bool ScalableFont::hasThisChar(const wchar_t c) const
|
||||||
|
{
|
||||||
|
std::map<wchar_t, s32>::const_iterator n = m_character_map.find(c);
|
||||||
|
if (n != m_character_map.end())
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
void ScalableFont::setInvisibleCharacters( const wchar_t *s )
|
void ScalableFont::setInvisibleCharacters( const wchar_t *s )
|
||||||
{
|
{
|
||||||
Invisible = s;
|
m_invisible = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
//! returns the dimension of text
|
|
||||||
core::dimension2d<u32> ScalableFont::getDimension(const wchar_t* text) const
|
core::dimension2d<u32> ScalableFont::getDimension(const wchar_t* text) const
|
||||||
{
|
{
|
||||||
GUIEngine::GlyphPageCreator* gp_creator = GUIEngine::getGlyphPageCreator();
|
GUIEngine::GlyphPageCreator* gp_creator = GUIEngine::getGlyphPageCreator();
|
||||||
@ -601,11 +687,11 @@ core::dimension2d<u32> ScalableFont::getDimension(const wchar_t* text) const
|
|||||||
for (const wchar_t* p = text; *p; ++p)
|
for (const wchar_t* p = text; *p; ++p)
|
||||||
{
|
{
|
||||||
if (*p == L'\r' || *p == L'\n' || *p == L' ' || *p < 32) continue;
|
if (*p == L'\r' || *p == L'\n' || *p == L' ' || *p < 32) continue;
|
||||||
if (GUIEngine::getFont()->getSpriteNoFromChar(p) == WrongCharacter)
|
if (!GUIEngine::getFont()->hasThisChar(*p))
|
||||||
gp_creator->newchar.insert(*p);
|
gp_creator->insertChar(*p);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gp_creator->newchar.size() > 0 && !m_is_hollow_copy && m_scale == 1)
|
if (gp_creator->getNewChar().size() > 0 && !m_is_hollow_copy && m_scale == 1)
|
||||||
{
|
{
|
||||||
Log::debug("ScalableFont::getDimension", "New character(s) %s discoverd, perform lazy loading",
|
Log::debug("ScalableFont::getDimension", "New character(s) %s discoverd, perform lazy loading",
|
||||||
StringUtils::wide_to_utf8(gp_creator->getNewChar().c_str()).c_str());
|
StringUtils::wide_to_utf8(gp_creator->getNewChar().c_str()).c_str());
|
||||||
@ -615,10 +701,10 @@ core::dimension2d<u32> ScalableFont::getDimension(const wchar_t* text) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(Areas.size() > 0);
|
assert(m_areas.size() > 0);
|
||||||
|
|
||||||
core::dimension2d<u32> dim(0, 0);
|
core::dimension2d<u32> dim(0, 0);
|
||||||
core::dimension2d<u32> thisLine(0, (int)(MaxHeight*m_scale));
|
core::dimension2d<u32> thisLine(0, (int)(m_max_height*m_scale));
|
||||||
|
|
||||||
for (const wchar_t* p = text; *p; ++p)
|
for (const wchar_t* p = text; *p; ++p)
|
||||||
{
|
{
|
||||||
@ -653,6 +739,8 @@ core::dimension2d<u32> ScalableFont::getDimension(const wchar_t* text) const
|
|||||||
return dim;
|
return dim;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
void ScalableFont::draw(const core::stringw& text,
|
void ScalableFont::draw(const core::stringw& text,
|
||||||
const core::rect<s32>& position, video::SColor color,
|
const core::rect<s32>& position, video::SColor color,
|
||||||
bool hcenter, bool vcenter,
|
bool hcenter, bool vcenter,
|
||||||
@ -661,6 +749,8 @@ void ScalableFont::draw(const core::stringw& text,
|
|||||||
doDraw(text, position, color, hcenter, vcenter, clip, NULL);
|
doDraw(text, position, color, hcenter, vcenter, clip, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
void ScalableFont::draw(const core::stringw& text,
|
void ScalableFont::draw(const core::stringw& text,
|
||||||
const core::rect<s32>& position, video::SColor color,
|
const core::rect<s32>& position, video::SColor color,
|
||||||
bool hcenter, bool vcenter,
|
bool hcenter, bool vcenter,
|
||||||
@ -674,14 +764,15 @@ void ScalableFont::draw(const core::stringw& text,
|
|||||||
if (ignoreRTL) m_rtl = previousRTL;
|
if (ignoreRTL) m_rtl = previousRTL;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! draws some text and clips it to the specified rectangle if wanted
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
void ScalableFont::doDraw(const core::stringw& text,
|
void ScalableFont::doDraw(const core::stringw& text,
|
||||||
const core::rect<s32>& position, video::SColor color,
|
const core::rect<s32>& position, video::SColor color,
|
||||||
bool hcenter, bool vcenter,
|
bool hcenter, bool vcenter,
|
||||||
const core::rect<s32>* clip,
|
const core::rect<s32>* clip,
|
||||||
FontCharCollector* charCollector)
|
FontCharCollector* charCollector)
|
||||||
{
|
{
|
||||||
if (!Driver) return;
|
if (!m_video_driver) return;
|
||||||
|
|
||||||
GUIEngine::GlyphPageCreator* gp_creator = GUIEngine::getGlyphPageCreator();
|
GUIEngine::GlyphPageCreator* gp_creator = GUIEngine::getGlyphPageCreator();
|
||||||
|
|
||||||
@ -729,12 +820,12 @@ void ScalableFont::doDraw(const core::stringw& text,
|
|||||||
{
|
{
|
||||||
wchar_t c = text[i];
|
wchar_t c = text[i];
|
||||||
if (c == L'\r' || c == L'\n' || c == L' ' || c < 32) continue;
|
if (c == L'\r' || c == L'\n' || c == L' ' || c < 32) continue;
|
||||||
if (GUIEngine::getFont()->getSpriteNoFromChar(&c) == WrongCharacter)
|
if (!GUIEngine::getFont()->hasThisChar(c))
|
||||||
gp_creator->newchar.insert(c);
|
gp_creator->insertChar(c);
|
||||||
|
|
||||||
if (charCollector != NULL && m_type == T_NORMAL && SpriteBank->getSprites()
|
if (charCollector != NULL && m_type == T_NORMAL && m_spritebank->getSprites()
|
||||||
[GUIEngine::getFont()->getSpriteNoFromChar(&c)].Frames[0].textureNumber
|
[GUIEngine::getFont()->getSpriteNoFromChar(&c)].Frames[0].textureNumber
|
||||||
== SpriteBank->getTextureCount() - 1) //Prevent overwriting texture used by billboard text
|
== m_spritebank->getTextureCount() - 1) //Prevent overwriting texture used by billboard text
|
||||||
{
|
{
|
||||||
Log::debug("ScalableFont::doDraw", "Character used by billboard text is in the last glyph page of normal font."
|
Log::debug("ScalableFont::doDraw", "Character used by billboard text is in the last glyph page of normal font."
|
||||||
" Create a new glyph page for new characters inserted later to prevent it from being removed.");
|
" Create a new glyph page for new characters inserted later to prevent it from being removed.");
|
||||||
@ -742,7 +833,7 @@ void ScalableFont::doDraw(const core::stringw& text,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gp_creator->newchar.size() > 0 && !m_is_hollow_copy && m_scale == 1)
|
if (gp_creator->getNewChar().size() > 0 && !m_is_hollow_copy && m_scale == 1)
|
||||||
{
|
{
|
||||||
Log::debug("ScalableFont::doDraw", "New character(s) %s discoverd, perform lazy loading",
|
Log::debug("ScalableFont::doDraw", "New character(s) %s discoverd, perform lazy loading",
|
||||||
StringUtils::wide_to_utf8(gp_creator->getNewChar().c_str()).c_str());
|
StringUtils::wide_to_utf8(gp_creator->getNewChar().c_str()).c_str());
|
||||||
@ -760,7 +851,7 @@ void ScalableFont::doDraw(const core::stringw& text,
|
|||||||
c == L'\n' ) // Unix breaks
|
c == L'\n' ) // Unix breaks
|
||||||
{
|
{
|
||||||
if(c==L'\r' && text[i+1]==L'\n') c = text[++i];
|
if(c==L'\r' && text[i+1]==L'\n') c = text[++i];
|
||||||
offset.Y += (int)(MaxHeight*m_scale);
|
offset.Y += (int)(m_max_height*m_scale);
|
||||||
offset.X = position.UpperLeftCorner.X;
|
offset.X = position.UpperLeftCorner.X;
|
||||||
if (hcenter)
|
if (hcenter)
|
||||||
offset.X += (position.getWidth() - text_dimension.Width) >> 1;
|
offset.X += (position.getWidth() - text_dimension.Width) >> 1;
|
||||||
@ -772,46 +863,45 @@ void ScalableFont::doDraw(const core::stringw& text,
|
|||||||
fallback[i] = use_fallback_font;
|
fallback[i] = use_fallback_font;
|
||||||
if (charCollector == NULL)
|
if (charCollector == NULL)
|
||||||
{
|
{
|
||||||
//floor is used to prevent negligible movement when m_scale changes with resolution
|
//Try to use ceil to make offset calculate correctly when m_scale is smaller than 1
|
||||||
int Hpadding = floor((float) area.bearingx*
|
s32 glyph_offset_x = ceil((float) area.bearingx*
|
||||||
(fallback[i] ? m_scale*m_fallback_font_scale : m_scale));
|
(fallback[i] ? m_scale*m_fallback_font_scale : m_scale));
|
||||||
int Vpadding = floor((float) area.offsety*
|
s32 glyph_offset_y = ceil((float) area.offsety*
|
||||||
(fallback[i] ? m_scale*m_fallback_font_scale : m_scale));
|
(fallback[i] ? m_scale*m_fallback_font_scale : m_scale));
|
||||||
offset.X += Hpadding;
|
offset.X += glyph_offset_x;
|
||||||
offset.Y += Vpadding + floor(m_type == T_DIGIT ? 20*m_scale : 0); //Additional offset for digit text
|
offset.Y += glyph_offset_y + floor(m_type == T_DIGIT ? 20*m_scale : 0); //Additional offset for digit text
|
||||||
offsets.push_back(offset);
|
offsets.push_back(offset);
|
||||||
offset.X -= Hpadding;
|
offset.X -= glyph_offset_x;
|
||||||
offset.Y -= Vpadding + floor(m_type == T_DIGIT ? 20*m_scale : 0);
|
offset.Y -= glyph_offset_y + floor(m_type == T_DIGIT ? 20*m_scale : 0);
|
||||||
}
|
}
|
||||||
else //Billboard text specific
|
else //Billboard text specific
|
||||||
{
|
{
|
||||||
int Hpadding = floor((float) area.bearingx*
|
s32 glyph_offset_x = ceil((float) area.bearingx*
|
||||||
(fallback[i] ? m_scale*m_fallback_font_scale : m_scale));
|
(fallback[i] ? m_scale*m_fallback_font_scale : m_scale));
|
||||||
int Vpadding = floor((float) area.offsety_bt*
|
s32 glyph_offset_y = ceil((float) area.offsety_bt*
|
||||||
(fallback[i] ? m_scale*m_fallback_font_scale : m_scale));
|
(fallback[i] ? m_scale*m_fallback_font_scale : m_scale));
|
||||||
offset.X += Hpadding;
|
offset.X += glyph_offset_x;
|
||||||
offset.Y += Vpadding + floor(m_type == T_DIGIT ? 20*m_scale : 0); //Additional offset for digit text
|
offset.Y += glyph_offset_y + floor(m_type == T_DIGIT ? 20*m_scale : 0); //Additional offset for digit text
|
||||||
offsets.push_back(offset);
|
offsets.push_back(offset);
|
||||||
offset.X -= Hpadding;
|
offset.X -= glyph_offset_x;
|
||||||
offset.Y -= Vpadding + floor(m_type == T_DIGIT ? 20*m_scale : 0);
|
offset.Y -= glyph_offset_y + floor(m_type == T_DIGIT ? 20*m_scale : 0);
|
||||||
}
|
}
|
||||||
// Invisible character. add something to the array anyway so that
|
// Invisible character. add something to the array anyway so that
|
||||||
// indices from the various arrays remain in sync
|
// indices from the various arrays remain in sync
|
||||||
indices.push_back( Invisible.findFirst(c) < 0 ? area.spriteno
|
indices.push_back(m_invisible.findFirst(c) < 0 ? area.spriteno : -1);
|
||||||
: -1 );
|
|
||||||
offset.X += getCharWidth(area, fallback[i]);
|
offset.X += getCharWidth(area, fallback[i]);
|
||||||
} // for i<text_size
|
} // for i<text_size
|
||||||
|
|
||||||
// ---- do the actual rendering
|
// ---- do the actual rendering
|
||||||
const int indiceAmount = indices.size();
|
const int indiceAmount = indices.size();
|
||||||
core::array< SGUISprite >& sprites = SpriteBank->getSprites();
|
core::array< SGUISprite >& sprites = m_spritebank->getSprites();
|
||||||
core::array< core::rect<s32> >& positions = SpriteBank->getPositions();
|
core::array< core::rect<s32> >& positions = m_spritebank->getPositions();
|
||||||
core::array< SGUISprite >* fallback_sprites;
|
core::array< SGUISprite >* fallback_sprites;
|
||||||
core::array< core::rect<s32> >* fallback_positions;
|
core::array< core::rect<s32> >* fallback_positions;
|
||||||
if(m_fallback_font!=NULL)
|
if (m_fallback_font != NULL)
|
||||||
{
|
{
|
||||||
fallback_sprites = &m_fallback_font->SpriteBank->getSprites();
|
fallback_sprites = &m_fallback_font->m_spritebank->getSprites();
|
||||||
fallback_positions = &m_fallback_font->SpriteBank->getPositions();
|
fallback_positions = &m_fallback_font->m_spritebank->getPositions();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -825,7 +915,7 @@ void ScalableFont::doDraw(const core::stringw& text,
|
|||||||
{ //Draw black border first, to make it behind the real character
|
{ //Draw black border first, to make it behind the real character
|
||||||
//which make script language display better
|
//which make script language display better
|
||||||
video::SColor black(color.getAlpha(),0,0,0);
|
video::SColor black(color.getAlpha(),0,0,0);
|
||||||
for (int n=0; n<indiceAmount; n++)
|
for (int n = 0; n < indiceAmount; n++)
|
||||||
{
|
{
|
||||||
const int spriteID = indices[n];
|
const int spriteID = indices[n];
|
||||||
if (!fallback[n] && (spriteID < 0 || spriteID >= spriteAmount)) continue;
|
if (!fallback[n] && (spriteID < 0 || spriteID >= spriteAmount)) continue;
|
||||||
@ -848,12 +938,12 @@ void ScalableFont::doDraw(const core::stringw& text,
|
|||||||
core::rect<s32> dest(offsets[n], size);
|
core::rect<s32> dest(offsets[n], size);
|
||||||
|
|
||||||
video::ITexture* texture = (fallback[n] ?
|
video::ITexture* texture = (fallback[n] ?
|
||||||
m_fallback_font->SpriteBank->getTexture(texID) :
|
m_fallback_font->m_spritebank->getTexture(texID) :
|
||||||
SpriteBank->getTexture(texID) );
|
m_spritebank->getTexture(texID) );
|
||||||
|
|
||||||
for (int x_delta=-2; x_delta<=2; x_delta++)
|
for (int x_delta = -2; x_delta <= 2; x_delta++)
|
||||||
{
|
{
|
||||||
for (int y_delta=-2; y_delta<=2; y_delta++)
|
for (int y_delta = -2; y_delta <= 2; y_delta++)
|
||||||
{
|
{
|
||||||
if (x_delta == 0 || y_delta == 0) continue;
|
if (x_delta == 0 || y_delta == 0) continue;
|
||||||
draw2DImage(texture,
|
draw2DImage(texture,
|
||||||
@ -866,7 +956,7 @@ void ScalableFont::doDraw(const core::stringw& text,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int n=0; n<indiceAmount; n++)
|
for (int n = 0; n < indiceAmount; n++)
|
||||||
{
|
{
|
||||||
const int spriteID = indices[n];
|
const int spriteID = indices[n];
|
||||||
if (!fallback[n] && (spriteID < 0 || spriteID >= spriteAmount)) continue;
|
if (!fallback[n] && (spriteID < 0 || spriteID >= spriteAmount)) continue;
|
||||||
@ -891,8 +981,8 @@ void ScalableFont::doDraw(const core::stringw& text,
|
|||||||
core::rect<s32> dest(offsets[n], size);
|
core::rect<s32> dest(offsets[n], size);
|
||||||
|
|
||||||
video::ITexture* texture = (fallback[n] ?
|
video::ITexture* texture = (fallback[n] ?
|
||||||
m_fallback_font->SpriteBank->getTexture(texID) :
|
m_fallback_font->m_spritebank->getTexture(texID) :
|
||||||
SpriteBank->getTexture(texID) );
|
m_spritebank->getTexture(texID) );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if (fallback[n])
|
if (fallback[n])
|
||||||
@ -951,15 +1041,16 @@ void ScalableFont::doDraw(const core::stringw& text,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
int ScalableFont::getCharWidth(const SFontArea& area, const bool fallback) const
|
s32 ScalableFont::getCharWidth(const SFontArea& area, const bool fallback) const
|
||||||
{
|
{
|
||||||
if (fallback) return (int)((area.width*m_fallback_font_scale + m_fallback_kerning_width) * m_scale);
|
if (fallback) return (int)((area.width*m_fallback_font_scale + m_fallback_kerning_width) * m_scale);
|
||||||
else return (int)((area.width + GlobalKerningWidth) * m_scale);
|
else return (int)((area.width + m_global_kerning_width) * m_scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
//! Calculates the index of the character in the text which is on a specific position.
|
|
||||||
s32 ScalableFont::getCharacterFromPos(const wchar_t* text, s32 pixel_x) const
|
s32 ScalableFont::getCharacterFromPos(const wchar_t* text, s32 pixel_x) const
|
||||||
{
|
{
|
||||||
s32 x = 0;
|
s32 x = 0;
|
||||||
@ -970,7 +1061,7 @@ s32 ScalableFont::getCharacterFromPos(const wchar_t* text, s32 pixel_x) const
|
|||||||
bool use_fallback_font = false;
|
bool use_fallback_font = false;
|
||||||
const SFontArea &a = getAreaFromCharacter(text[idx], &use_fallback_font);
|
const SFontArea &a = getAreaFromCharacter(text[idx], &use_fallback_font);
|
||||||
|
|
||||||
x += getCharWidth(a, use_fallback_font) + GlobalKerningWidth;
|
x += getCharWidth(a, use_fallback_font) + m_global_kerning_width;
|
||||||
|
|
||||||
if (x >= pixel_x)
|
if (x >= pixel_x)
|
||||||
return idx;
|
return idx;
|
||||||
@ -981,13 +1072,12 @@ s32 ScalableFont::getCharacterFromPos(const wchar_t* text, s32 pixel_x) const
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
IGUISpriteBank* ScalableFont::getSpriteBank() const
|
IGUISpriteBank* ScalableFont::getSpriteBank() const
|
||||||
{
|
{
|
||||||
return SpriteBank;
|
return m_spritebank;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end namespace gui
|
} // end namespace gui
|
||||||
} // end namespace irr
|
} // end namespace irr
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,14 +1,27 @@
|
|||||||
// Copyright (C) 2002-2015 Nikolaus Gebhardt
|
// SuperTuxKart - a fun racing game with go-kart
|
||||||
// This file is part of the "Irrlicht Engine".
|
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
// Copyright (C) 2015 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 __C_GUI_FONT_H_INCLUDED__
|
#ifndef HEADER_SCALABLE_FONT_HPP
|
||||||
#define __C_GUI_FONT_H_INCLUDED__
|
#define HEADER_SCALABLE_FONT_HPP
|
||||||
|
|
||||||
|
#include "guiengine/ft_environment.hpp"
|
||||||
#include "utils/leak_check.hpp"
|
#include "utils/leak_check.hpp"
|
||||||
|
|
||||||
#include "guiengine/get_font_properties.hpp"
|
|
||||||
|
|
||||||
#include "IrrCompileConfig.h"
|
#include "IrrCompileConfig.h"
|
||||||
#include "IGUIFontBitmap.h"
|
#include "IGUIFontBitmap.h"
|
||||||
#include "irrString.h"
|
#include "irrString.h"
|
||||||
@ -20,6 +33,7 @@
|
|||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
namespace irr
|
namespace irr
|
||||||
{
|
{
|
||||||
@ -62,16 +76,12 @@ public:
|
|||||||
|
|
||||||
bool m_black_border;
|
bool m_black_border;
|
||||||
|
|
||||||
TTFLoadingType m_type;
|
|
||||||
FontUse m_font_use;
|
|
||||||
u32 m_dpi;
|
|
||||||
|
|
||||||
ScalableFont* m_fallback_font;
|
ScalableFont* m_fallback_font;
|
||||||
float m_fallback_font_scale;
|
float m_fallback_font_scale;
|
||||||
int m_fallback_kerning_width;
|
int m_fallback_kerning_width;
|
||||||
|
|
||||||
//! constructor
|
ScalableFont(IGUIEnvironment* env, GUIEngine::TTFLoadingType type);
|
||||||
ScalableFont(IGUIEnvironment* env, TTFLoadingType type);
|
virtual ~ScalableFont();
|
||||||
|
|
||||||
/** Creates a hollow copy of this font; i.e. the underlying font data is the *same* for
|
/** Creates a hollow copy of this font; i.e. the underlying font data is the *same* for
|
||||||
* both fonts. The advantage of doing this is that you can change "view" parameters
|
* both fonts. The advantage of doing this is that you can change "view" parameters
|
||||||
@ -89,13 +99,13 @@ public:
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! destructor
|
/** loads a font from a TTF file */
|
||||||
virtual ~ScalableFont();
|
|
||||||
|
|
||||||
//! loads a font from a TTF file
|
|
||||||
bool loadTTF();
|
bool loadTTF();
|
||||||
|
|
||||||
//! draws an text and clips it to the specified rectangle if wanted
|
/** lazy load new characters discovered in normal font */
|
||||||
|
bool lazyLoadChar();
|
||||||
|
|
||||||
|
/** draws an text and clips it to the specified rectangle if wanted */
|
||||||
virtual void draw(const core::stringw& text, const core::rect<s32>& position,
|
virtual void draw(const core::stringw& text, const core::rect<s32>& position,
|
||||||
video::SColor color, bool hcenter = false,
|
video::SColor color, bool hcenter = false,
|
||||||
bool vcenter = false, const core::rect<s32>* clip = 0);
|
bool vcenter = false, const core::rect<s32>* clip = 0);
|
||||||
@ -109,20 +119,20 @@ public:
|
|||||||
bool vcenter, const core::rect<s32>* clip,
|
bool vcenter, const core::rect<s32>* clip,
|
||||||
FontCharCollector* charCollector = NULL);
|
FontCharCollector* charCollector = NULL);
|
||||||
|
|
||||||
//! returns the dimension of a text
|
/** returns the dimension of a text */
|
||||||
virtual core::dimension2d<u32> getDimension(const wchar_t* text) const;
|
virtual core::dimension2d<u32> getDimension(const wchar_t* text) const;
|
||||||
|
|
||||||
//! Calculates the index of the character in the text which is on a specific position.
|
/** Calculates the index of the character in the text which is on a specific position. */
|
||||||
virtual s32 getCharacterFromPos(const wchar_t* text, s32 pixel_x) const;
|
virtual s32 getCharacterFromPos(const wchar_t* text, s32 pixel_x) const;
|
||||||
|
|
||||||
//! Returns the type of this font
|
/** Returns the type of this font */
|
||||||
virtual EGUI_FONT_TYPE getType() const { return EGFT_BITMAP; }
|
virtual EGUI_FONT_TYPE getType() const { return EGFT_BITMAP; }
|
||||||
|
|
||||||
//! set an Pixel Offset on Drawing ( scale position on width )
|
/** set an Pixel Offset on Drawing ( scale position on width ) */
|
||||||
virtual void setKerningWidth (s32 kerning);
|
virtual void setKerningWidth (s32 kerning);
|
||||||
virtual void setKerningHeight (s32 kerning);
|
virtual void setKerningHeight (s32 kerning);
|
||||||
|
|
||||||
//! set an Pixel Offset on Drawing ( scale position on width )
|
/** set an Pixel Offset on Drawing ( scale position on width ) */
|
||||||
virtual s32 getKerningWidth(const wchar_t* thisLetter=0, const wchar_t* previousLetter=0) const;
|
virtual s32 getKerningWidth(const wchar_t* thisLetter=0, const wchar_t* previousLetter=0) const;
|
||||||
virtual s32 getKerningHeight() const;
|
virtual s32 getKerningHeight() const;
|
||||||
|
|
||||||
@ -132,26 +142,26 @@ public:
|
|||||||
void setShadow(const irr::video::SColor &col);
|
void setShadow(const irr::video::SColor &col);
|
||||||
void disableShadow() {m_shadow = false;}
|
void disableShadow() {m_shadow = false;}
|
||||||
|
|
||||||
//! gets the sprite bank
|
/** gets the sprite bank */
|
||||||
virtual IGUISpriteBank* getSpriteBank() const;
|
virtual IGUISpriteBank* getSpriteBank() const;
|
||||||
|
|
||||||
//! returns the sprite number from a given character
|
/** returns the sprite number from a given character */
|
||||||
virtual u32 getSpriteNoFromChar(const wchar_t *c) const;
|
virtual u32 getSpriteNoFromChar(const wchar_t *c) const;
|
||||||
|
|
||||||
virtual void setInvisibleCharacters( const wchar_t *s );
|
virtual void setInvisibleCharacters( const wchar_t *s );
|
||||||
|
|
||||||
|
/** test whether current font has this character regardless of fallback font */
|
||||||
|
virtual bool hasThisChar(const wchar_t c) const;
|
||||||
|
|
||||||
void setScale(const float scale);
|
void setScale(const float scale);
|
||||||
float getScale() const { return m_scale; }
|
float getScale() const { return m_scale; }
|
||||||
|
|
||||||
void updateRTL();
|
void updateRTL();
|
||||||
|
|
||||||
//! re-create fonts when language is changed
|
/** re-create fonts when language is changed */
|
||||||
void recreateFromLanguage();
|
void recreateFromLanguage();
|
||||||
|
|
||||||
//! lazy load new characters discovered in normal font
|
/** force create a new texture (glyph) page in a font */
|
||||||
bool lazyLoadChar();
|
|
||||||
|
|
||||||
//! force create a new texture (glyph) page in a font
|
|
||||||
void forceNewPage();
|
void forceNewPage();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -166,30 +176,35 @@ private:
|
|||||||
s32 bearingx;
|
s32 bearingx;
|
||||||
};
|
};
|
||||||
|
|
||||||
int getCharWidth(const SFontArea& area, const bool fallback) const;
|
s32 getCharWidth(const SFontArea& area, const bool fallback) const;
|
||||||
s32 getAreaIDFromCharacter(const wchar_t c, bool* fallback_font) const;
|
s32 getAreaIDFromCharacter(const wchar_t c, bool* fallback_font) const;
|
||||||
const SFontArea &getAreaFromCharacter(const wchar_t c, bool* fallback_font) const;
|
const SFontArea &getAreaFromCharacter(const wchar_t c, bool* fallback_font) const;
|
||||||
void setMaxHeight();
|
/** get characters to be pre-loaded base on font type */
|
||||||
|
std::set<wchar_t> getPreloadCharacters(const GUIEngine::TTFLoadingType);
|
||||||
|
|
||||||
core::array<SFontArea> Areas;
|
GUIEngine::TTFLoadingType m_type;
|
||||||
|
GUIEngine::FontUse m_font_use;
|
||||||
|
video::IVideoDriver *m_video_driver;
|
||||||
|
IGUISpriteBank *m_spritebank;
|
||||||
|
IGUIEnvironment *m_gui_env;
|
||||||
|
video::ITexture *m_last_normal_page;
|
||||||
|
|
||||||
|
core::array<SFontArea> m_areas;
|
||||||
/** The maximum values of all digits, used in monospace_digits. */
|
/** The maximum values of all digits, used in monospace_digits. */
|
||||||
mutable SFontArea m_max_digit_area;
|
mutable SFontArea m_max_digit_area;
|
||||||
std::map<wchar_t, s32> CharacterMap;
|
std::map<wchar_t, s32> m_character_map;
|
||||||
video::IVideoDriver* Driver;
|
|
||||||
IGUISpriteBank* SpriteBank;
|
|
||||||
IGUIEnvironment* Environment;
|
|
||||||
u32 WrongCharacter;
|
|
||||||
s32 MaxHeight;
|
|
||||||
s32 GlobalKerningWidth, GlobalKerningHeight;
|
|
||||||
s32 GlyphMaxHeight;
|
|
||||||
video::ITexture* LastNormalPage;
|
|
||||||
|
|
||||||
core::stringw Invisible;
|
s32 m_max_height;
|
||||||
|
s32 m_global_kerning_width;
|
||||||
|
s32 m_global_kerning_height;
|
||||||
|
s32 m_glyph_max_height;
|
||||||
|
|
||||||
|
core::stringw m_invisible;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace gui
|
} // end namespace gui
|
||||||
} // end namespace irr
|
} // end namespace irr
|
||||||
|
|
||||||
|
|
||||||
#endif // __C_GUI_FONT_H_INCLUDED__
|
#endif // HEADER_SCALABLE_FONT_HPP
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user