Merge branch 'master' of github.com:supertuxkart/stk-code

This commit is contained in:
hiker 2015-11-09 09:04:43 +11:00
commit ce219f2fd4
11 changed files with 681 additions and 623 deletions

View File

@ -66,10 +66,6 @@ GLuint ShaderBase::loadShader(const std::string &file, unsigned type)
std::ostringstream code;
code << "#version " << CVS->getGLSLVersion()<<"\n";
//shader compilation fails with some drivers if there is no precision qualifier
if (type == GL_FRAGMENT_SHADER)
code << "precision mediump float;\n";
if (CVS->isAMDVertexShaderLayerUsable())
code << "#extension GL_AMD_vertex_shader_layer : enable\n";
if (CVS->isAZDOEnabled())
@ -84,6 +80,11 @@ GLuint ShaderBase::loadShader(const std::string &file, unsigned type)
code << "#define VSLayer\n";
if (CVS->needsRGBBindlessWorkaround())
code << "#define SRGBBindlessFix\n";
//shader compilation fails with some drivers if there is no precision qualifier
if (type == GL_FRAGMENT_SHADER)
code << "precision mediump float;\n";
code << getHeader();
std::ifstream stream(file_manager->getShader(file), std::ios::in);

View File

@ -15,85 +15,132 @@
// 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/ft_environment.hpp"
#include "guiengine/get_font_properties.hpp"
#include "io/file_manager.hpp"
#include "utils/log.hpp"
#include <algorithm>
using namespace gui;
namespace GUIEngine
{
// ----------------------------------------------------------------------------
FTEnvironment::FTEnvironment()
{
FTEnvironment::ft_err += FT_Init_FreeType(&(FTEnvironment::ft_lib));
Log::info("Freetype Environment", "Loading fonts...");
checkError(FT_Init_FreeType(&m_ft_lib), "loading freetype library");
loadFont();
}
// ----------------------------------------------------------------------------
FTEnvironment::~FTEnvironment()
{
for (int i = 0; i < F_COUNT; ++i)
FTEnvironment::ft_err += FT_Done_Face((FTEnvironment::ft_face[i]));
checkError(FT_Done_Face(m_ft_face[i]), "removing freetype face");
FTEnvironment::ft_err += FT_Done_FreeType(FTEnvironment::ft_lib);
if (FTEnvironment::ft_err > 0)
Log::error("Freetype Environment", "Can't destroy all fonts.");
else
Log::info("Freetype Environment", "Successfully destroy all fonts.");
checkError(FT_Done_FreeType(m_ft_lib), "removing freetype library");
}
// ----------------------------------------------------------------------------
FT_Face FTEnvironment::getFace(const FontUse font)
{
return m_ft_face[font];
}
// ----------------------------------------------------------------------------
void FTEnvironment::checkError(FT_Error err, const irr::core::stringc desc)
{
if (err)
{
Log::error("Freetype Environment", "Something wrong when %s!", desc.c_str());
}
}
// ----------------------------------------------------------------------------
void FTEnvironment::loadFont()
{
FTEnvironment::ft_err += FT_New_Face(FTEnvironment::ft_lib, (file_manager->getAssetChecked
checkError(FT_New_Face(m_ft_lib, (file_manager->getAssetChecked
(FileManager::TTF, "Ubuntu-R.ttf", true)).c_str(),
0, &(FTEnvironment::ft_face[F_DEFAULT]));
0, &m_ft_face[F_DEFAULT]), "loading F_DEFAULT");
FTEnvironment::ft_err += FT_New_Face(FTEnvironment::ft_lib, (file_manager->getAssetChecked
checkError(FT_New_Face(m_ft_lib, (file_manager->getAssetChecked
(FileManager::TTF, "FreeSans.ttf",true)).c_str(),
0, &(FTEnvironment::ft_face[F_DEFAULT_FALLBACK]));
0, &m_ft_face[F_DEFAULT_FALLBACK]), "loading F_DEFAULT_FALLBACK");
FTEnvironment::ft_err += FT_New_Face(FTEnvironment::ft_lib, (file_manager->getAssetChecked
checkError(FT_New_Face(m_ft_lib, (file_manager->getAssetChecked
(FileManager::TTF, "wqy-microhei.ttf",true)).c_str(),
0, &(FTEnvironment::ft_face[F_CJK]));
0, &m_ft_face[F_CJK]), "loading F_CJK");
FTEnvironment::ft_err += FT_New_Face(FTEnvironment::ft_lib, (file_manager->getAssetChecked
checkError(FT_New_Face(m_ft_lib, (file_manager->getAssetChecked
(FileManager::TTF, "NotoNaskhArabicUI-Bold.ttf",true)).c_str(),
0, &(FTEnvironment::ft_face[F_AR]));
0, &m_ft_face[F_AR]), "loading F_AR");
FTEnvironment::ft_err += FT_New_Face(FTEnvironment::ft_lib, (file_manager->getAssetChecked
checkError(FT_New_Face(m_ft_lib, (file_manager->getAssetChecked
(FileManager::TTF, "Ubuntu-B.ttf", true)).c_str(),
0, &(FTEnvironment::ft_face[F_BOLD]));
0, &m_ft_face[F_BOLD]), "loading F_BOLD");
FTEnvironment::ft_err += FT_New_Face(FTEnvironment::ft_lib, (file_manager->getAssetChecked
checkError(FT_New_Face(m_ft_lib, (file_manager->getAssetChecked
(FileManager::TTF, "FreeSansBold.ttf", true)).c_str(),
0, &(FTEnvironment::ft_face[F_BOLD_FALLBACK]));
0, &m_ft_face[F_BOLD_FALLBACK]), "loading F_BOLD_FALLBACK");
FTEnvironment::ft_err += FT_New_Face(FTEnvironment::ft_lib, (file_manager->getAssetChecked
checkError(FT_New_Face(m_ft_lib, (file_manager->getAssetChecked
(FileManager::TTF, "SigmarOne.otf",true)).c_str(),
0, &(FTEnvironment::ft_face[F_DIGIT]));
0, &m_ft_face[F_DIGIT]), "loading F_DIGIT");
//Set charmap
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 eid = FTEnvironment::ft_face[h]->charmaps[i]->encoding_id;
FT_UShort pid = m_ft_face[h]->charmaps[i]->platform_id;
FT_UShort eid = m_ft_face[h]->charmaps[i]->encoding_id;
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]);
checkError(FT_Set_Charmap(m_ft_face[h], m_ft_face[h]->charmaps[i]), "setting charmaps");
}
}
if (FTEnvironment::ft_err > 0)
Log::error("Freetype Environment", "Can't load all fonts.");
else
Log::info("Freetype Environment", "Successfully loaded all fonts.");
// 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);
checkError(FT_Set_Pixel_Sizes(m_ft_face[F_DEFAULT], 0, normal_dpi), "setting F_DEFAULT size");
checkError(FT_Set_Pixel_Sizes(m_ft_face[F_DEFAULT_FALLBACK], 0, normal_dpi), "setting F_DEFAULT_FALLBACK size");
checkError(FT_Set_Pixel_Sizes(m_ft_face[F_CJK], 0, normal_dpi), "setting F_CJK size");
checkError(FT_Set_Pixel_Sizes(m_ft_face[F_AR], 0, normal_dpi), "setting F_AR size");
checkError(FT_Set_Pixel_Sizes(m_ft_face[F_BOLD], 0, title_dpi), "setting F_BOLD size");
checkError(FT_Set_Pixel_Sizes(m_ft_face[F_BOLD_FALLBACK], 0, title_dpi), "setting F_BOLD_FALLBACK size");
checkError(FT_Set_Pixel_Sizes(m_ft_face[F_DIGIT], 0, digit_dpi), "setting F_DIGIT size");
}
FT_Library FTEnvironment::ft_lib = NULL;
FT_Error FTEnvironment::ft_err = 0;
FT_Library FTEnvironment::m_ft_lib = NULL;
} // guiengine

View File

@ -15,9 +15,12 @@
// 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_FT_ENVIRONMENT_HPP
#define HEADER_FT_ENVIRONMENT_HPP
#include <ft2build.h>
#include "guiengine/get_font_properties.hpp"
#include FT_FREETYPE_H
#include <irrlicht.h>
#include "utils/leak_check.hpp"
@ -26,6 +29,23 @@
*/
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.
*/
@ -37,15 +57,25 @@ namespace GUIEngine
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:
/** Check for any error discovered in a freetype function that will return a FT_Error value.
* \param err The Freetype function.
* \param desc The description of what is the function doing.
*/
void checkError(FT_Error err, const irr::core::stringc desc);
/** Load font face into memory, but don't create glyph yet.
*/
void loadFont();
static FT_Library ft_lib;
static FT_Error ft_err;
FT_Face m_ft_face[F_COUNT];
static FT_Library m_ft_lib;
};
} // guiengine
#endif // HEADER_FT_ENVIRONMENT_HPP

View File

@ -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

View File

@ -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

View File

@ -27,25 +27,33 @@
namespace GUIEngine
{
// ----------------------------------------------------------------------------
GlyphPageCreator::GlyphPageCreator()
{
page = GUIEngine::getDriver()->createImage(video::ECF_A8R8G8B8, core::dimension2du(512, 512));
image = 0;
newchar.clear();
m_page = GUIEngine::getDriver()->createImage(video::ECF_A8R8G8B8, core::dimension2du(512, 512));
m_image = 0;
}
// ----------------------------------------------------------------------------
GlyphPageCreator::~GlyphPageCreator()
{
clearGlyphPage();
page->drop();
page = 0;
clearNewCharHolder();
m_page->drop();
m_page = 0;
}
// ----------------------------------------------------------------------------
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)
{
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)),
!(GUIEngine::getDriver()->queryFeature(video::EVDF_TEXTURE_NSQUARE)), true, 0);
if ((used_width + texture_size.Width > 512 && used_height + temp_height + texture_size.Height > 512)
|| used_height + texture_size.Height > 512)
if ((m_used_width + texture_size.Width > 512 && m_used_height + m_temp_height + texture_size.Height > 512)
|| m_used_height + texture_size.Height > 512)
return false;
return true;
}
// ----------------------------------------------------------------------------
void GlyphPageCreator::clearNewCharHolder()
{
m_new_char_holder.clear();
}
// ----------------------------------------------------------------------------
void GlyphPageCreator::clearGlyphPage()
{
used_width = 0;
temp_height = 0;
used_height = 0;
m_used_width = 0;
m_temp_height = 0;
m_used_height = 0;
}
// ----------------------------------------------------------------------------
void GlyphPageCreator::createNewGlyphPage()
{
//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()
{
return page;
return m_page;
}
// ----------------------------------------------------------------------------
core::stringw GlyphPageCreator::getNewChar()
{
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;
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)
{
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.
texture_size = d.getOptimalSize(!(GUIEngine::getDriver()->queryFeature(video::EVDF_TEXTURE_NPOT)),
!(GUIEngine::getDriver()->queryFeature(video::EVDF_TEXTURE_NSQUARE)), true, 0);
image = GUIEngine::getDriver()->createImage(video::ECF_A8R8G8B8, texture_size);
image->fill(video::SColor(0, 255, 255, 255));
m_image = GUIEngine::getDriver()->createImage(video::ECF_A8R8G8B8, texture_size);
m_image->fill(video::SColor(0, 255, 255, 255));
// Load the grayscale data in.
const float gray_count = static_cast<float>(bits.num_grays);
const u32 image_pitch = image->getPitch() / sizeof(u32);
u32* image_data = (u32*)image->lock();
const u32 image_pitch = m_image->getPitch() / sizeof(u32);
u32* image_data = (u32*)m_image->lock();
u8* glyph_data = bits.buffer;
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;
}
image->unlock();
m_image->unlock();
break;
}
default:
return false;
}
if (!image)
if (!m_image)
return false;
//Done creating a single glyph, now copy to the glyph page...
//Determine the linebreak location
if (used_width + texture_size.Width > 512)
if (m_used_width + texture_size.Width > 512)
{
used_width = 0;
used_height += temp_height;
temp_height = 0;
m_used_width = 0;
m_used_height += m_temp_height;
m_temp_height = 0;
}
//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
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();
image = 0;
m_image->drop();
m_image = 0;
//Store used area
used_width += texture_size.Width;
if (temp_height < texture_size.Height)
temp_height = texture_size.Height;
m_used_width += texture_size.Width;
if (m_temp_height < texture_size.Height)
m_temp_height = texture_size.Height;
return true;
}

View File

@ -58,6 +58,10 @@ namespace GUIEngine
*/
void clearGlyphPage();
/** Reset characters holder for lazy loading char.
*/
void clearNewCharHolder();
/** Clear (fill it with transparent content) the current glyph page.
*/
void createNewGlyphPage();
@ -67,11 +71,16 @@ namespace GUIEngine
*/
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.
*/
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
* \param bits The Glyph bitmap inputted.
* \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);
/** A temporary holder stored new char to be inserted.
*/
std::set<wchar_t> newchar;
private:
/** 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.
*/
video::IImage* page;
video::IImage* m_page;
u32 temp_height;
u32 used_width;
u32 used_height;
u32 m_temp_height;
u32 m_used_width;
u32 m_used_height;
};
} // guiengine

File diff suppressed because it is too large Load Diff

View File

@ -1,14 +1,27 @@
// Copyright (C) 2002-2015 Nikolaus Gebhardt
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2002-2012 Nikolaus Gebhardt
// 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__
#define __C_GUI_FONT_H_INCLUDED__
#ifndef HEADER_SCALABLE_FONT_HPP
#define HEADER_SCALABLE_FONT_HPP
#include "guiengine/ft_environment.hpp"
#include "utils/leak_check.hpp"
#include "guiengine/get_font_properties.hpp"
#include "IrrCompileConfig.h"
#include "IGUIFontBitmap.h"
#include "irrString.h"
@ -20,6 +33,7 @@
#include <map>
#include <string>
#include <set>
namespace irr
{
@ -62,16 +76,12 @@ public:
bool m_black_border;
TTFLoadingType m_type;
FontUse m_font_use;
u32 m_dpi;
ScalableFont* m_fallback_font;
float m_fallback_font_scale;
int m_fallback_kerning_width;
//! constructor
ScalableFont(IGUIEnvironment* env, TTFLoadingType type);
ScalableFont(IGUIEnvironment* env, GUIEngine::TTFLoadingType type);
virtual ~ScalableFont();
/** 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
@ -89,13 +99,13 @@ public:
return out;
}
//! destructor
virtual ~ScalableFont();
//! loads a font from a TTF file
/** loads a font from a TTF file */
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,
video::SColor color, bool hcenter = false,
bool vcenter = false, const core::rect<s32>* clip = 0);
@ -109,20 +119,20 @@ public:
bool vcenter, const core::rect<s32>* clip,
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;
//! 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;
//! Returns the type of this font
/** Returns the type of this font */
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 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 getKerningHeight() const;
@ -132,26 +142,26 @@ public:
void setShadow(const irr::video::SColor &col);
void disableShadow() {m_shadow = false;}
//! gets the sprite bank
/** gets the sprite bank */
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 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);
float getScale() const { return m_scale; }
void updateRTL();
//! re-create fonts when language is changed
/** re-create fonts when language is changed */
void recreateFromLanguage();
//! lazy load new characters discovered in normal font
bool lazyLoadChar();
//! force create a new texture (glyph) page in a font
/** force create a new texture (glyph) page in a font */
void forceNewPage();
private:
@ -166,30 +176,35 @@ private:
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;
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. */
mutable SFontArea m_max_digit_area;
std::map<wchar_t, s32> CharacterMap;
video::IVideoDriver* Driver;
IGUISpriteBank* SpriteBank;
IGUIEnvironment* Environment;
u32 WrongCharacter;
s32 MaxHeight;
s32 GlobalKerningWidth, GlobalKerningHeight;
s32 GlyphMaxHeight;
video::ITexture* LastNormalPage;
mutable SFontArea m_max_digit_area;
std::map<wchar_t, s32> m_character_map;
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 irr
#endif // __C_GUI_FONT_H_INCLUDED__
#endif // HEADER_SCALABLE_FONT_HPP

112
tools/remove-whitespaces.py Executable file
View File

@ -0,0 +1,112 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# 2014, By konstin (http://github/konstin)
# 2015, Modified by leyyin
#
# Removes all trailing whitespaces and replaces all tabs with four spaces, the
# files with a given extension in a recursively searched directory.
# It can also count the number of code lines excluding comments and blank
# lines.
#
# Tested with python 2.7 and python 3
import os
import argparse
import sys
def main(directory, is_statistics, is_dry_run, extensions, comments_start):
lines_total = 0
lines_comments = 0
file_counter = 0
files_affected = 0
for dir_path, _, file_names in os.walk(directory):
if is_statistics:
file_counter += len(file_names)
for file_name in file_names:
_, file_extension = os.path.splitext(file_name)
# File does not have an extension
if not file_extension:
continue
# Not a valid extension. Note: extensions have in the 0 position a dot, eg: '.hpp', '.cpp'
if file_extension[1:] not in extensions:
continue
if is_statistics:
files_affected += 1
# Read whole file
path_file = os.path.join(dir_path, file_name)
with open(path_file, 'r') as f:
lines = f.readlines()
if is_statistics:
lines_total += len(lines)
# Scan lines
is_modified = False
for i, line in enumerate(lines):
original_line = line
# Replace tabs with four spaces
line = line.replace('\t', ' ')
line_rstrip = line.rstrip()
if line_rstrip: # Don't de-indent empty lines
line = line_rstrip + '\n'
# Count the number of comments
if is_statistics:
line_lstrip = line.lstrip()
if any([line_lstrip.startswith(c) for c in comments_start]):
lines_comments += 1
# Indicate that we want to write to the current file
if original_line != line:
lines[i] = line # Replace original line
if not is_modified:
is_modified = True
# Write back modified lines
if not is_dry_run and is_modified:
with open(path_file, 'w') as f:
f.writelines(lines)
if is_statistics:
print('Total number of files in {0}: {1}'.format(directory, file_counter))
print('Total number of files affected in {0}: {1}'.format(directory, files_affected))
print('Lines in total: {0}'.format(lines_total))
print(' empty/comments: {0}'.format(lines_comments))
print('↳ excluding comments and blank lines: {0}'.format(lines_total - lines_comments), end='\n' * 2)
print('Finished.')
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Remove whitespace from C/C++ files.')
parser.add_argument('directory', default='../src', nargs='?',
help='the directory where all the source files are located. (default: %(default)s)')
parser.add_argument('--dry-run', dest='dry_run', action='store_true',
help='do a dry run. Do not modify/write any files. (default: %(default)s)')
parser.add_argument('--statistics', dest='statistics', action='store_true',
help='display statistics (count files and lines if enabled). On by default.')
parser.add_argument('--no-statistics', dest='statistics', action='store_false', help='do not display statistics.')
parser.add_argument('--extensions', default=["cpp", "hpp", "c", "h"], nargs='+',
help='set file extensions. Eg: --extensions cpp hpp (default: %(default)s).')
parser.add_argument('--comments-start', default=['//', '/*', '*'], nargs='+',
help='set how line comments start. Eg: --comments-start // \'*\'. (default: %(default)s).')
parser.set_defaults(statistics=True)
parser.set_defaults(dry_run=False)
args = parser.parse_args()
if not os.path.exists(args.directory):
print('ERROR: The directory {0} does not exist'.format(args.directory))
sys.exit(1)
print(args)
main(args.directory, args.statistics, args.dry_run, args.extensions, args.comments_start)

View File

@ -1,74 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# 2014, By konstin (http://github/konstin)
#
# Removes all trailing whitespaces and replaces all tabs with four spacesin the
# files with a given extension in a recursivly searched directory.
# It can also count the number of code lines excluding comments and blank
# lines.
#
# Tested with python 2.7 and python 3
import os
def main():
# -------------- config --------------
extensions = ["cpp", "hpp", "c" , "h"]
directory = "../src"
# Counts files and lines if enabled
statistics = True
# ------------------------------------
if statistics:
lines_total = 0
lines_code = 0
file_counter = 0
for dirpath, dirnames, filenames in os.walk(directory):
for filename in filenames:
if statistics:
file_counter += 1
if (filename.rfind(".") != -1 and
filename[ filename.rfind(".")+1 : ] in extensions):
# reading
src_file = open(dirpath + "/" + filename, "r")
lines = src_file.readlines()
if statistics:
lines_total += len(lines)
modified = False
for i in range(len(lines)):
oldLine = lines[i]
# replacing tabs with four spaces
lines[i] = lines[i].replace("\t", " ")
if lines[i].rstrip() != "": # don't de-indent empty lines
lines[i] = lines[i].rstrip() + "\n"
if statistics:
if lines[i].lstrip().startswith("//"):
lines_code += 1
if not modified and oldLine != lines[i]:
modified = True
src_file.close()
# writing back
if modified:
src_file = open(dirpath + "/" + filename, "w")
src_file.write("".join(lines))
src_file.close()
if statistics:
print("Total number of files in " + directory + ": "
+ str(file_counter))
print("Lines in total in: " + str(lines_total))
print("↳ excluding comments and blank lines: " + str(lines_code)+ "\n")
print("Finished.")
if __name__ == '__main__':
main()