Merge branch 'master' of https://github.com/supertuxkart/stk-code
@ -16,6 +16,7 @@ if (NOT CMAKE_BUILD_TYPE)
|
||||
endif()
|
||||
|
||||
option(USE_WIIUSE "Support for wiimote input devices" ON)
|
||||
option(USE_FREETYPE "Use Freetype to render text" ON)
|
||||
option(USE_FRIBIDI "Support for right-to-left languages" ON)
|
||||
option(CHECK_ASSETS "Check if assets are installed in ../stk-assets" ON)
|
||||
option(USE_SYSTEM_ANGELSCRIPT "Use system angelscript instead of built-in angelscript. If you enable this option, make sure to use a compatible version." OFF)
|
||||
@ -164,6 +165,17 @@ else()
|
||||
include_directories(${OGGVORBIS_INCLUDE_DIRS})
|
||||
endif()
|
||||
|
||||
# Freetype
|
||||
if(USE_FREETYPE)
|
||||
find_package(Freetype)
|
||||
if(FREETYPE_FOUND)
|
||||
include_directories(${FREETYPE_INCLUDE_DIRS})
|
||||
else()
|
||||
message(FATAL_ERROR "Freetype not found. "
|
||||
"Either install freetype or disable freetype rendering support with -DUSE_FREETYPE=0 ")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Fribidi
|
||||
if(USE_FRIBIDI)
|
||||
find_package(Fribidi)
|
||||
@ -339,6 +351,7 @@ target_link_libraries(supertuxkart
|
||||
${OGGVORBIS_LIBRARIES}
|
||||
${OPENAL_LIBRARY}
|
||||
${OPENGL_LIBRARIES}
|
||||
${FREETPYE_LIBRARIES}
|
||||
)
|
||||
|
||||
if(UNIX AND NOT APPLE)
|
||||
@ -368,6 +381,11 @@ if(USE_FRIBIDI)
|
||||
add_definitions(-DENABLE_BIDI)
|
||||
endif()
|
||||
|
||||
if(USE_FREETYPE)
|
||||
target_link_libraries(supertuxkart ${FREETYPE_LIBRARIES})
|
||||
add_definitions(-DENABLE_FREETYPE)
|
||||
endif()
|
||||
|
||||
# Wiiuse
|
||||
# ------
|
||||
if(USE_WIIUSE)
|
||||
@ -416,9 +434,6 @@ if(MINGW)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Optional tools
|
||||
add_subdirectory(tools/font_tool)
|
||||
|
||||
|
||||
# ==== Checking if data folder exists ====
|
||||
if(NOT IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/data)
|
||||
|
29
cmake/FindFreetype.cmake
Normal file
@ -0,0 +1,29 @@
|
||||
# - Find Freetype
|
||||
# Find the Freetype includes and libraries
|
||||
#
|
||||
# Following variables are provided:
|
||||
# FREETYPE_FOUND
|
||||
# True if Freetype has been found
|
||||
# FREETYPE_INCLUDE_DIRS
|
||||
# The include directories of Freetype
|
||||
# FREETYPE_LIBRARIES
|
||||
# Freetype library list
|
||||
|
||||
if(WIN32)
|
||||
find_path(FREETYPE_INCLUDE_DIRS NAMES freetype/freetype.h PATHS "${PROJECT_SOURCE_DIR}/dependencies/include")
|
||||
find_library(FREETPYE_LIBRARY NAMES freetype PATHS "${PROJECT_SOURCE_DIR}/dependencies/lib")
|
||||
set(FREETYPE_FOUND 1)
|
||||
set(FREETPYE_LIBRARIES ${FREETPYE_LIBRARY})
|
||||
elseif(APPLE)
|
||||
find_path(FREETYPE_INCLUDE_DIRS NAMES freetype/freetype.h PATHS "/Library/Frameworks/FreeType.Framework/Versions/2.4/unix/include")
|
||||
find_library(FREETPYE_LIBRARY NAMES freetype PATHS "/Library/Frameworks/FreeType.Framework/Versions/2.4/")
|
||||
include_directories(/Library/Frameworks/FreeType.Framework/Versions/2.4/unix/include)
|
||||
set(FREETYPE_FOUND 1)
|
||||
set(FREETPYE_LIBRARIES ${FREETPYE_LIBRARY})
|
||||
elseif(UNIX)
|
||||
include(FindPkgConfig)
|
||||
pkg_check_modules(FREETYPE freetype2)
|
||||
else()
|
||||
set(FREETYPE_FOUND 0)
|
||||
endif()
|
||||
|
BIN
data/CREDITS
Before Width: | Height: | Size: 46 KiB |
Before Width: | Height: | Size: 43 KiB |
Before Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 47 KiB |
Before Width: | Height: | Size: 4.3 KiB |
@ -1,22 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<materials>
|
||||
<!-- Fonts -->
|
||||
<material name="title_font.png" shader="unlit" dont-load="Y"/>
|
||||
<material name="title_font_2.png" shader="unlit" dont-load="Y"/>
|
||||
<material name="sigmar0.png" shader="unlit" dont-load="Y"/>
|
||||
<material name="comix.png" shader="unlit" dont-load="Y"/>
|
||||
<material name="LayneHansom0.png" shader="unlit" dont-load="Y"/>
|
||||
<material name="Mplus2p_JP0.png" shader="unlit" dont-load="Y"/>
|
||||
<material name="rasheeq0.png" shader="unlit" dont-load="Y"/>
|
||||
<material name="rasheeq3.png" shader="unlit" dont-load="Y"/>
|
||||
<material name="rasheeq4.png" shader="unlit" dont-load="Y"/>
|
||||
<material name="wqyMicroHei0.png" shader="unlit" dont-load="Y"/>
|
||||
<material name="wqyMicroHei1.png" shader="unlit" dont-load="Y"/>
|
||||
<material name="wqyMicroHei2.png" shader="unlit" dont-load="Y"/>
|
||||
<material name="wqyMicroHei3.png" shader="unlit" dont-load="Y"/>
|
||||
<material name="wqyMicroHei4.png" shader="unlit" dont-load="Y"/>
|
||||
<material name="wqyMicroHei5.png" shader="unlit" dont-load="Y"/>
|
||||
<material name="AR_PL_SungtiL_GB0.png" shader="unlit" dont-load="Y"/>
|
||||
<material name="LayneHansomBigDigits.png" shader="unlit" dont-load="Y"/>
|
||||
|
||||
</materials>
|
Before Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 9.1 KiB |
Before Width: | Height: | Size: 8.0 KiB |
Before Width: | Height: | Size: 9.0 KiB |
Before Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 174 KiB |
Before Width: | Height: | Size: 181 KiB |
Before Width: | Height: | Size: 61 KiB |
Before Width: | Height: | Size: 71 KiB |
Before Width: | Height: | Size: 78 KiB |
Before Width: | Height: | Size: 81 KiB |
Before Width: | Height: | Size: 75 KiB |
Before Width: | Height: | Size: 63 KiB |
Before Width: | Height: | Size: 45 KiB |
BIN
data/ttf/FreeSans.ttf
Normal file
BIN
data/ttf/FreeSansBold.ttf
Normal file
12
data/ttf/LICENSE
Normal file
@ -0,0 +1,12 @@
|
||||
GNU FreeFont (FreeSans, FreeSansBold) is released under the GPLv3
|
||||
|
||||
wqyMicroHei is released under the GPLv3 with font embedding exception and Apache-2.0 licenses
|
||||
By Qianqian Fang and The WenQuanYi Project Contributors
|
||||
Copyright (C) 2008-2009 The WenQuanYi Project Board of Trustees
|
||||
Copyright (C) 2007 Google Corporation
|
||||
|
||||
Noto Naskh Arabic UI is released under Apache-2.0 license
|
||||
|
||||
Ubuntu font is released under the ubuntu font license (http://font.ubuntu.com/licence/)
|
||||
|
||||
SigmarOne is released under the SIL open font license 1.1 ( https://www.google.com/fonts/specimen/Sigmar+One )
|
BIN
data/ttf/NotoNaskhArabicUI-Bold.ttf
Normal file
44
data/ttf/SIL Open Font License.txt
Normal file
@ -0,0 +1,44 @@
|
||||
Copyright (c) 2011, Vernon Adams (vern@newtypography.co.uk),
|
||||
with Reserved Font Name Sigmar One.
|
||||
|
||||
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||
This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL
|
||||
|
||||
-----------------------------------------------------------
|
||||
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||
-----------------------------------------------------------
|
||||
|
||||
PREAMBLE
|
||||
The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others.
|
||||
|
||||
The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives.
|
||||
|
||||
DEFINITIONS
|
||||
"Font Software" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation.
|
||||
|
||||
"Reserved Font Name" refers to any names specified as such after the copyright statement(s).
|
||||
|
||||
"Original Version" refers to the collection of Font Software components as distributed by the Copyright Holder(s).
|
||||
|
||||
"Modified Version" refers to any derivative made by adding to, deleting, or substituting -- in part or in whole -- any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment.
|
||||
|
||||
"Author" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software.
|
||||
|
||||
PERMISSION & CONDITIONS
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions:
|
||||
|
||||
1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself.
|
||||
|
||||
2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user.
|
||||
|
||||
3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users.
|
||||
|
||||
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission.
|
||||
|
||||
5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software.
|
||||
|
||||
TERMINATION
|
||||
This license becomes null and void if any of the above conditions are not met.
|
||||
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE.
|
BIN
data/ttf/SigmarOne.otf
Normal file
BIN
data/ttf/Ubuntu-B.ttf
Normal file
BIN
data/ttf/Ubuntu-R.ttf
Normal file
96
data/ttf/ubuntu-font-licence-1.0.txt
Normal file
@ -0,0 +1,96 @@
|
||||
-------------------------------
|
||||
UBUNTU FONT LICENCE Version 1.0
|
||||
-------------------------------
|
||||
|
||||
PREAMBLE
|
||||
This licence allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely. The fonts, including any derivative works, can be
|
||||
bundled, embedded, and redistributed provided the terms of this licence
|
||||
are met. The fonts and derivatives, however, cannot be released under
|
||||
any other licence. The requirement for fonts to remain under this
|
||||
licence does not require any document created using the fonts or their
|
||||
derivatives to be published under this licence, as long as the primary
|
||||
purpose of the document is not to be a vehicle for the distribution of
|
||||
the fonts.
|
||||
|
||||
DEFINITIONS
|
||||
"Font Software" refers to the set of files released by the Copyright
|
||||
Holder(s) under this licence and clearly marked as such. This may
|
||||
include source files, build scripts and documentation.
|
||||
|
||||
"Original Version" refers to the collection of Font Software components
|
||||
as received under this licence.
|
||||
|
||||
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||
or substituting -- in part or in whole -- any of the components of the
|
||||
Original Version, by changing formats or by porting the Font Software to
|
||||
a new environment.
|
||||
|
||||
"Copyright Holder(s)" refers to all individuals and companies who have a
|
||||
copyright ownership of the Font Software.
|
||||
|
||||
"Substantially Changed" refers to Modified Versions which can be easily
|
||||
identified as dissimilar to the Font Software by users of the Font
|
||||
Software comparing the Original Version with the Modified Version.
|
||||
|
||||
To "Propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification and with or without charging
|
||||
a redistribution fee), making available to the public, and in some
|
||||
countries other activities as well.
|
||||
|
||||
PERMISSION & CONDITIONS
|
||||
This licence does not grant any rights under trademark law and all such
|
||||
rights are reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of the Font Software, to propagate the Font Software, subject to
|
||||
the below conditions:
|
||||
|
||||
1) Each copy of the Font Software must contain the above copyright
|
||||
notice and this licence. These can be included either as stand-alone
|
||||
text files, human-readable headers or in the appropriate machine-
|
||||
readable metadata fields within text or binary files as long as those
|
||||
fields can be easily viewed by the user.
|
||||
|
||||
2) The font name complies with the following:
|
||||
(a) The Original Version must retain its name, unmodified.
|
||||
(b) Modified Versions which are Substantially Changed must be renamed to
|
||||
avoid use of the name of the Original Version or similar names entirely.
|
||||
(c) Modified Versions which are not Substantially Changed must be
|
||||
renamed to both (i) retain the name of the Original Version and (ii) add
|
||||
additional naming elements to distinguish the Modified Version from the
|
||||
Original Version. The name of such Modified Versions must be the name of
|
||||
the Original Version, with "derivative X" where X represents the name of
|
||||
the new work, appended to that name.
|
||||
|
||||
3) The name(s) of the Copyright Holder(s) and any contributor to the
|
||||
Font Software shall not be used to promote, endorse or advertise any
|
||||
Modified Version, except (i) as required by this licence, (ii) to
|
||||
acknowledge the contribution(s) of the Copyright Holder(s) or (iii) with
|
||||
their explicit written permission.
|
||||
|
||||
4) The Font Software, modified or unmodified, in part or in whole, must
|
||||
be distributed entirely under this licence, and must not be distributed
|
||||
under any other licence. The requirement for fonts to remain under this
|
||||
licence does not affect any document created using the Font Software,
|
||||
except any version of the Font Software extracted from a document
|
||||
created using the Font Software may only be distributed under this
|
||||
licence.
|
||||
|
||||
TERMINATION
|
||||
This licence becomes null and void if any of the above conditions are
|
||||
not met.
|
||||
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER
|
||||
DEALINGS IN THE FONT SOFTWARE.
|
BIN
data/ttf/wqy-microhei.ttf
Normal file
@ -501,7 +501,7 @@ if(APPLE)
|
||||
set_source_files_properties(source/Irrlicht/MacOSX/OSXClipboard.mm PROPERTIES LANGUAGE C)
|
||||
endif()
|
||||
|
||||
add_library(stkirrlicht ${IRRLICHT_SOURCES})
|
||||
add_library(stkirrlicht STATIC ${IRRLICHT_SOURCES})
|
||||
target_link_libraries(stkirrlicht ${PNG_LIBRARY} ${JPEG_LIBRARY} ${ZLIB_LIBRARY})
|
||||
|
||||
|
||||
|
@ -377,6 +377,7 @@ public:
|
||||
float getZipperMinSpeed() const { return m_zipper_min_speed; }
|
||||
// ------------------------------------------------------------------------
|
||||
ShaderType getShaderType() const { return m_shader_type; }
|
||||
void setShaderType(ShaderType st) { m_shader_type = st; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** True if this texture should have the U coordinates mirrored. */
|
||||
char getMirrorAxisInReverse() const { return m_mirror_axis_when_reverse; }
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
#include "config/user_config.hpp"
|
||||
#include "graphics/material.hpp"
|
||||
#include "graphics/shaders.hpp"
|
||||
#include "io/file_manager.hpp"
|
||||
#include "io/xml_node.hpp"
|
||||
#include "modes/world.hpp"
|
||||
@ -40,7 +41,6 @@ MaterialManager::MaterialManager()
|
||||
{
|
||||
/* Create list - and default material zero */
|
||||
|
||||
m_default_material = NULL;
|
||||
m_materials.reserve(256);
|
||||
// We can't call init/loadMaterial here, since the global variable
|
||||
// material_manager has not yet been initialised, and
|
||||
@ -67,7 +67,7 @@ Material* MaterialManager::getMaterialFor(video::ITexture* t,
|
||||
scene::IMeshBuffer *mb)
|
||||
{
|
||||
if (t == NULL)
|
||||
return m_default_material;
|
||||
return getDefaultMaterial(mb->getMaterial().MaterialType);
|
||||
|
||||
core::stringc img_path = core::stringc(t->getName());
|
||||
const std::string image = StringUtils::getBasename(img_path.c_str());
|
||||
@ -92,7 +92,8 @@ Material* MaterialManager::getMaterialFor(video::ITexture* t,
|
||||
}
|
||||
} // for i
|
||||
}
|
||||
return m_default_material;
|
||||
|
||||
return getDefaultMaterial(mb->getMaterial().MaterialType);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -111,53 +112,41 @@ void MaterialManager::setAllMaterialFlags(video::ITexture* t,
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_default_material == NULL)
|
||||
m_default_material = new Material("", false, false, false);
|
||||
m_default_material->setMaterialProperties(&(mb->getMaterial()), mb);
|
||||
|
||||
/*
|
||||
// This material does not appear in materials.xml. Set some common flags...
|
||||
if (UserConfigParams::m_anisotropic > 0)
|
||||
{
|
||||
for (u32 i=0; i<video::MATERIAL_MAX_TEXTURES; ++i)
|
||||
{
|
||||
mb->getMaterial().TextureLayer[i].AnisotropicFilter =
|
||||
UserConfigParams::m_anisotropic;
|
||||
}
|
||||
}
|
||||
else if (UserConfigParams::m_trilinear)
|
||||
{
|
||||
mb->getMaterial().setFlag(video::EMF_TRILINEAR_FILTER, true);
|
||||
}
|
||||
|
||||
mb->getMaterial().ColorMaterial = video::ECM_DIFFUSE_AND_AMBIENT;
|
||||
|
||||
if (World::getWorld() != NULL)
|
||||
{
|
||||
mb->getMaterial().FogEnable = World::getWorld()->isFogEnabled();
|
||||
}
|
||||
|
||||
|
||||
// Modify lightmap materials so that vertex colors are taken into account.
|
||||
// But disable lighting because we assume all lighting is already part
|
||||
// of the lightmap
|
||||
if (mb->getMaterial().MaterialType == video::EMT_LIGHTMAP)
|
||||
{
|
||||
mb->getMaterial().MaterialType = video::EMT_LIGHTMAP_LIGHTING;
|
||||
mb->getMaterial().AmbientColor = video::SColor(255, 255, 255, 255);
|
||||
mb->getMaterial().DiffuseColor = video::SColor(255, 255, 255, 255);
|
||||
mb->getMaterial().EmissiveColor = video::SColor(255, 255, 255, 255);
|
||||
mb->getMaterial().SpecularColor = video::SColor(255, 255, 255, 255);
|
||||
}
|
||||
|
||||
|
||||
//if (UserConfigParams::m_fullscreen_antialiasing)
|
||||
// mb->getMaterial().AntiAliasing = video::EAAM_LINE_SMOOTH;
|
||||
*/
|
||||
Material* default_material = getDefaultMaterial(mb->getMaterial().MaterialType);
|
||||
default_material->setMaterialProperties(&(mb->getMaterial()), mb);
|
||||
} // setAllMaterialFlags
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
Material* MaterialManager::getDefaultMaterial(video::E_MATERIAL_TYPE shader_type)
|
||||
{
|
||||
auto it = m_default_materials.find(shader_type);
|
||||
if (it == m_default_materials.end())
|
||||
{
|
||||
Material* default_material = new Material("", false, false, false);
|
||||
|
||||
// TODO: workaround, should not hardcode these material types here?
|
||||
// Try to find a cleaner way
|
||||
if (shader_type == Shaders::getShader(ShaderType::ES_OBJECT_UNLIT))
|
||||
default_material->setShaderType(Material::SHADERTYPE_SOLID_UNLIT);
|
||||
else if (shader_type == Shaders::getShader(ShaderType::ES_OBJECTPASS_REF))
|
||||
default_material->setShaderType(Material::SHADERTYPE_ALPHA_TEST);
|
||||
//else if (shader_type == Shaders::getShader(ShaderType::ES_OBJECTPASS))
|
||||
// default_material->setShaderType(Material::SHADERTYPE_ALPHA_BLEND);
|
||||
else
|
||||
default_material->setShaderType(Material::SHADERTYPE_SOLID);
|
||||
|
||||
m_default_materials[shader_type] = default_material;
|
||||
return default_material;
|
||||
}
|
||||
else
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void MaterialManager::adjustForFog(video::ITexture* t,
|
||||
scene::IMeshBuffer *mb,
|
||||
scene::ISceneNode* parent,
|
||||
@ -191,9 +180,8 @@ void MaterialManager::setAllUntexturedMaterialFlags(scene::IMeshBuffer *mb)
|
||||
material.MaterialType = irr::video::EMT_SOLID;
|
||||
}
|
||||
|
||||
if (m_default_material == NULL)
|
||||
m_default_material = new Material("", false, false, false);
|
||||
m_default_material->setMaterialProperties(&(mb->getMaterial()), mb);
|
||||
Material* default_material = getDefaultMaterial(mb->getMaterial().MaterialType);
|
||||
default_material->setMaterialProperties(&(mb->getMaterial()), mb);
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
int MaterialManager::addEntity(Material *m)
|
||||
|
@ -29,8 +29,10 @@ namespace irr
|
||||
}
|
||||
using namespace irr;
|
||||
|
||||
#include <irrlicht.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
class Material;
|
||||
class XMLReader;
|
||||
@ -48,7 +50,8 @@ private:
|
||||
|
||||
std::vector<Material*> m_materials;
|
||||
|
||||
Material* m_default_material;
|
||||
std::map<video::E_MATERIAL_TYPE, Material*> m_default_materials;
|
||||
Material* getDefaultMaterial(video::E_MATERIAL_TYPE material_type);
|
||||
|
||||
public:
|
||||
MaterialManager();
|
||||
|
@ -67,7 +67,11 @@ scene::IMesh* STKTextBillboard::getTextMesh(core::stringw text, gui::ScalableFon
|
||||
font->doDraw(text, core::rect<s32>(0, 0, size.Width, size.Height), video::SColor(255,255,255,255),
|
||||
false, false, NULL, this);
|
||||
|
||||
#ifdef ENABLE_FREETYPE
|
||||
const float scale = 0.03f; //Larger for ttf font as they are less bold
|
||||
#else
|
||||
const float scale = 0.018f;
|
||||
#endif // ENABLE_FREETYPE
|
||||
|
||||
//scene::SMesh* mesh = new scene::SMesh();
|
||||
std::map<video::ITexture*, scene::SMeshBuffer*> buffers;
|
||||
|
@ -688,6 +688,10 @@ namespace GUIEngine
|
||||
{
|
||||
IGUIEnvironment* g_env;
|
||||
Skin* g_skin = NULL;
|
||||
#ifdef ENABLE_FREETYPE
|
||||
FTEnvironment* g_ft_env = NULL;
|
||||
GlyphPageCreator* g_gp_creator = NULL;
|
||||
#endif // ENABLE_FREETYPE
|
||||
ScalableFont *g_font;
|
||||
ScalableFont *g_outline_font;
|
||||
ScalableFont *g_large_font;
|
||||
@ -952,6 +956,13 @@ namespace GUIEngine
|
||||
//if (g_skin != NULL) delete g_skin;
|
||||
g_skin = NULL;
|
||||
|
||||
#ifdef ENABLE_FREETYPE
|
||||
g_ft_env->~FTEnvironment();
|
||||
g_ft_env = NULL;
|
||||
g_gp_creator->~GlyphPageCreator();
|
||||
g_gp_creator = NULL;
|
||||
#endif // ENABLE_FREETYPE
|
||||
|
||||
for (unsigned int i=0; i<g_loaded_screens.size(); i++)
|
||||
{
|
||||
g_loaded_screens[i].unload();
|
||||
@ -982,6 +993,17 @@ namespace GUIEngine
|
||||
// kill everything along the device
|
||||
} // cleanUp
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
void cleanHollowCopyFont()
|
||||
{
|
||||
g_small_font->drop();
|
||||
g_small_font = NULL;
|
||||
g_large_font->drop();
|
||||
g_large_font = NULL;
|
||||
g_outline_font->drop();
|
||||
g_outline_font = NULL;
|
||||
} // cleanHollowCopyFont
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
@ -1009,6 +1031,11 @@ namespace GUIEngine
|
||||
g_focus_for_player[n] = NULL;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_FREETYPE
|
||||
g_ft_env = new FTEnvironment();
|
||||
g_gp_creator = new GlyphPageCreator();
|
||||
#endif // ENABLE_FREETYPE
|
||||
|
||||
/*
|
||||
To make the g_font a little bit nicer, we load an external g_font
|
||||
and set it as the new default g_font in the g_skin.
|
||||
@ -1042,6 +1069,51 @@ namespace GUIEngine
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ENABLE_FREETYPE
|
||||
float normal_text_scale = 1;
|
||||
float title_text_scale = 1;
|
||||
|
||||
ScalableFont* digit_font =new ScalableFont(g_env,T_DIGIT);
|
||||
digit_font->setMonospaceDigits(true);
|
||||
g_digit_font = digit_font;
|
||||
|
||||
ScalableFont* sfont2 =new ScalableFont(g_env,T_BOLD);
|
||||
sfont2->setKerningWidth(0);
|
||||
// Because the fallback font is much smaller than the title font:
|
||||
sfont2->m_fallback_font_scale = 2.0f;
|
||||
sfont2->m_fallback_kerning_width = 5;
|
||||
|
||||
ScalableFont* sfont =new ScalableFont(g_env,T_NORMAL);
|
||||
sfont->setKerningHeight(0);
|
||||
sfont->setScale(normal_text_scale);
|
||||
g_font = sfont;
|
||||
Private::font_height = g_font->getDimension( L"X" ).Height;
|
||||
|
||||
ScalableFont* sfont_larger = sfont->getHollowCopy();
|
||||
sfont_larger->setScale(normal_text_scale*1.4f);
|
||||
sfont_larger->setKerningHeight(0);
|
||||
g_large_font = sfont_larger;
|
||||
|
||||
g_outline_font = sfont->getHollowCopy();
|
||||
g_outline_font->m_black_border = true;
|
||||
|
||||
Private::large_font_height = g_large_font->getDimension( L"X" ).Height;
|
||||
|
||||
ScalableFont* sfont_smaller = sfont->getHollowCopy();
|
||||
sfont_smaller->setScale(normal_text_scale*0.8f);
|
||||
sfont_smaller->setKerningHeight(0);
|
||||
g_small_font = sfont_smaller;
|
||||
|
||||
Private::small_font_height =
|
||||
g_small_font->getDimension( L"X" ).Height;
|
||||
|
||||
sfont2->m_fallback_font = sfont;
|
||||
sfont2->setScale(title_text_scale);
|
||||
sfont2->m_black_border = true;
|
||||
g_title_font = sfont2;
|
||||
Private::title_font_height =
|
||||
g_title_font->getDimension( L"X" ).Height;
|
||||
#else
|
||||
// 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
|
||||
@ -1112,6 +1184,7 @@ namespace GUIEngine
|
||||
g_title_font = sfont2;
|
||||
Private::title_font_height =
|
||||
g_title_font->getDimension( L"X" ).Height;
|
||||
#endif // ENABLE_FREETYPE
|
||||
|
||||
|
||||
if (g_font != NULL) g_skin->setFont(g_font);
|
||||
@ -1125,6 +1198,34 @@ namespace GUIEngine
|
||||
g_device->getVideoDriver()->endScene();
|
||||
} // init
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
void reloadHollowCopyFont(irr::gui::ScalableFont* sfont)
|
||||
{
|
||||
//Base on the init function above
|
||||
float normal_text_scale = 1;
|
||||
|
||||
sfont->setScale(normal_text_scale);
|
||||
sfont->setKerningHeight(-5);
|
||||
Private::font_height = sfont->getDimension( L"X" ).Height;
|
||||
|
||||
ScalableFont* sfont_larger = sfont->getHollowCopy();
|
||||
sfont_larger->setScale(normal_text_scale*1.4f);
|
||||
sfont_larger->setKerningHeight(-5);
|
||||
g_large_font = sfont_larger;
|
||||
|
||||
g_outline_font = sfont->getHollowCopy();
|
||||
g_outline_font->m_black_border = true;
|
||||
|
||||
Private::large_font_height = g_large_font->getDimension( L"X" ).Height;
|
||||
|
||||
ScalableFont* sfont_smaller = sfont->getHollowCopy();
|
||||
sfont_smaller->setScale(normal_text_scale*0.8f);
|
||||
sfont_smaller->setKerningHeight(-5);
|
||||
g_small_font = sfont_smaller;
|
||||
|
||||
Private::small_font_height = g_small_font->getDimension( L"X" ).Height;
|
||||
} // reloadHollowCopyFont
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
void reloadSkin()
|
||||
{
|
||||
|
@ -39,6 +39,11 @@ namespace irr
|
||||
#include "utils/constants.hpp"
|
||||
#include "utils/ptr_vector.hpp"
|
||||
|
||||
#ifdef ENABLE_FREETYPE
|
||||
#include "guiengine/ft_environment.hpp"
|
||||
#include "guiengine/glyph_page_creator.hpp"
|
||||
#endif // ENABLE_FREETYPE
|
||||
|
||||
/**
|
||||
* \ingroup guiengine
|
||||
* \brief Contains all GUI engine related classes and functions
|
||||
@ -81,6 +86,10 @@ namespace GUIEngine
|
||||
{
|
||||
extern irr::gui::IGUIEnvironment* g_env;
|
||||
extern Skin* g_skin;
|
||||
#ifdef ENABLE_FREETYPE
|
||||
extern FTEnvironment* g_ft_env;
|
||||
extern GlyphPageCreator* g_gp_creator;
|
||||
#endif // ENABLE_FREETYPE
|
||||
extern irr::gui::ScalableFont* g_small_font;
|
||||
extern irr::gui::ScalableFont* g_font;
|
||||
extern irr::gui::ScalableFont* g_outline_font;
|
||||
@ -172,6 +181,20 @@ namespace GUIEngine
|
||||
*/
|
||||
inline Skin* getSkin() { return Private::g_skin; }
|
||||
|
||||
#ifdef ENABLE_FREETYPE
|
||||
/**
|
||||
* \pre GUIEngine::init must have been called first
|
||||
* \return the freetype and library with face
|
||||
*/
|
||||
inline FTEnvironment* getFreetype() { return Private::g_ft_env; }
|
||||
|
||||
/**
|
||||
* \pre GUIEngine::init must have been called first
|
||||
* \return the glyph page creator, useful to create a glyph page from individual char
|
||||
*/
|
||||
inline GlyphPageCreator* getGlyphPageCreator() { return Private::g_gp_creator; }
|
||||
#endif // ENABLE_FREETYPE
|
||||
|
||||
Screen* getScreenNamed(const char* name);
|
||||
|
||||
/** \return the height of the title font in pixels */
|
||||
@ -247,6 +270,14 @@ namespace GUIEngine
|
||||
* \brief call when skin in user config was updated
|
||||
*/
|
||||
void reloadSkin();
|
||||
|
||||
#ifdef ENABLE_FREETYPE
|
||||
/**
|
||||
* \brief call when translation in user config was updated for freetype rendering STK
|
||||
*/
|
||||
void cleanHollowCopyFont();
|
||||
void reloadHollowCopyFont(irr::gui::ScalableFont*);
|
||||
#endif // ENABLE_FREETYPE
|
||||
}
|
||||
|
||||
#endif
|
||||
|
101
src/guiengine/ft_environment.cpp
Normal file
@ -0,0 +1,101 @@
|
||||
// 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.
|
||||
|
||||
#ifdef ENABLE_FREETYPE
|
||||
#include "guiengine/ft_environment.hpp"
|
||||
#include "guiengine/get_font_properties.hpp"
|
||||
#include "io/file_manager.hpp"
|
||||
#include "utils/log.hpp"
|
||||
|
||||
using namespace gui;
|
||||
|
||||
namespace GUIEngine
|
||||
{
|
||||
|
||||
FTEnvironment::FTEnvironment()
|
||||
{
|
||||
FTEnvironment::ft_err += FT_Init_FreeType(&(FTEnvironment::ft_lib));
|
||||
|
||||
loadFont();
|
||||
}
|
||||
|
||||
FTEnvironment::~FTEnvironment()
|
||||
{
|
||||
for (int i = 0; i < F_COUNT; ++i)
|
||||
FTEnvironment::ft_err += FT_Done_Face((FTEnvironment::ft_face[i]));
|
||||
|
||||
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.");
|
||||
}
|
||||
|
||||
void FTEnvironment::loadFont()
|
||||
{
|
||||
FTEnvironment::ft_err += FT_New_Face(FTEnvironment::ft_lib, (file_manager->getAssetChecked
|
||||
(FileManager::TTF, "Ubuntu-R.ttf", true)).c_str(),
|
||||
0, &(FTEnvironment::ft_face[F_DEFAULT]));
|
||||
|
||||
FTEnvironment::ft_err += FT_New_Face(FTEnvironment::ft_lib, (file_manager->getAssetChecked
|
||||
(FileManager::TTF, "FreeSans.ttf",true)).c_str(),
|
||||
0, &(FTEnvironment::ft_face[F_DEFAULT_FALLBACK]));
|
||||
|
||||
FTEnvironment::ft_err += FT_New_Face(FTEnvironment::ft_lib, (file_manager->getAssetChecked
|
||||
(FileManager::TTF, "wqy-microhei.ttf",true)).c_str(),
|
||||
0, &(FTEnvironment::ft_face[F_CJK]));
|
||||
|
||||
FTEnvironment::ft_err += FT_New_Face(FTEnvironment::ft_lib, (file_manager->getAssetChecked
|
||||
(FileManager::TTF, "NotoNaskhArabicUI-Bold.ttf",true)).c_str(),
|
||||
0, &(FTEnvironment::ft_face[F_AR]));
|
||||
|
||||
FTEnvironment::ft_err += FT_New_Face(FTEnvironment::ft_lib, (file_manager->getAssetChecked
|
||||
(FileManager::TTF, "Ubuntu-B.ttf", true)).c_str(),
|
||||
0, &(FTEnvironment::ft_face[F_BOLD]));
|
||||
|
||||
FTEnvironment::ft_err += FT_New_Face(FTEnvironment::ft_lib, (file_manager->getAssetChecked
|
||||
(FileManager::TTF, "FreeSansBold.ttf", true)).c_str(),
|
||||
0, &(FTEnvironment::ft_face[F_BOLD_FALLBACK]));
|
||||
|
||||
FTEnvironment::ft_err += FT_New_Face(FTEnvironment::ft_lib, (file_manager->getAssetChecked
|
||||
(FileManager::TTF, "SigmarOne.otf",true)).c_str(),
|
||||
0, &(FTEnvironment::ft_face[F_DIGIT]));
|
||||
|
||||
//Set charmap
|
||||
for (int h = 0; h < F_COUNT; ++h)
|
||||
{
|
||||
for (int i = 0; i < FTEnvironment::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;
|
||||
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]);
|
||||
}
|
||||
}
|
||||
|
||||
if (FTEnvironment::ft_err > 0)
|
||||
Log::error("Freetype Environment", "Can't load all fonts.");
|
||||
else
|
||||
Log::info("Freetype Environment", "Successfully loaded all fonts.");
|
||||
}
|
||||
|
||||
FT_Library FTEnvironment::ft_lib = NULL;
|
||||
FT_Error FTEnvironment::ft_err = 0;
|
||||
|
||||
} // guiengine
|
||||
#endif // ENABLE_FREETYPE
|
46
src/guiengine/ft_environment.hpp
Normal file
@ -0,0 +1,46 @@
|
||||
// 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 <ft2build.h>
|
||||
#include "guiengine/get_font_properties.hpp"
|
||||
#include FT_FREETYPE_H
|
||||
|
||||
/**
|
||||
* \ingroup guiengine
|
||||
*/
|
||||
namespace GUIEngine
|
||||
{
|
||||
/**
|
||||
* \brief Initialize a freetype environment with a single freetype library.
|
||||
*/
|
||||
class FTEnvironment
|
||||
{
|
||||
public:
|
||||
FTEnvironment();
|
||||
~FTEnvironment();
|
||||
FT_Face ft_face[irr::gui::F_COUNT];
|
||||
|
||||
private:
|
||||
/** Load font face into memory, but don't create glyph yet.
|
||||
*/
|
||||
void loadFont();
|
||||
|
||||
static FT_Library ft_lib;
|
||||
static FT_Error ft_err;
|
||||
};
|
||||
|
||||
} // guiengine
|
127
src/guiengine/get_font_properties.cpp
Normal file
@ -0,0 +1,127 @@
|
||||
// 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
|
76
src/guiengine/get_font_properties.hpp
Normal file
@ -0,0 +1,76 @@
|
||||
// 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
|
159
src/guiengine/glyph_page_creator.cpp
Normal file
@ -0,0 +1,159 @@
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2009-2010 John Norman
|
||||
// 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.
|
||||
//
|
||||
// The image loading function is partially based on CGUITTFont.cpp by John Norman,
|
||||
// original version is located here:
|
||||
//
|
||||
// http://irrlicht.suckerfreegames.com/
|
||||
|
||||
#ifdef ENABLE_FREETYPE
|
||||
#include <irrlicht.h>
|
||||
#include "guiengine/engine.hpp"
|
||||
|
||||
namespace GUIEngine
|
||||
{
|
||||
|
||||
GlyphPageCreator::GlyphPageCreator()
|
||||
{
|
||||
page = GUIEngine::getDriver()->createImage(video::ECF_A8R8G8B8, core::dimension2du(512, 512));
|
||||
image = 0;
|
||||
newchar.clear();
|
||||
}
|
||||
|
||||
GlyphPageCreator::~GlyphPageCreator()
|
||||
{
|
||||
clearGlyphPage();
|
||||
page->drop();
|
||||
page = 0;
|
||||
}
|
||||
|
||||
void GlyphPageCreator::dumpGlyphPage(const core::stringc fn)
|
||||
{
|
||||
GUIEngine::getDriver()->writeImageToFile(page, fn + ".png");
|
||||
}
|
||||
|
||||
bool GlyphPageCreator::checkEnoughSpace(FT_Bitmap bits)
|
||||
{
|
||||
core::dimension2du d(bits.width + 1, bits.rows + 1);
|
||||
core::dimension2du texture_size;
|
||||
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)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void GlyphPageCreator::clearGlyphPage()
|
||||
{
|
||||
used_width = 0;
|
||||
temp_height = 0;
|
||||
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));
|
||||
}
|
||||
|
||||
video::IImage* GlyphPageCreator::getPage()
|
||||
{
|
||||
return page;
|
||||
}
|
||||
|
||||
core::stringw GlyphPageCreator::getNewChar()
|
||||
{
|
||||
core::stringw c;
|
||||
for (std::set<wchar_t>::iterator it = newchar.begin(); it != newchar.end(); ++it)
|
||||
c += *it;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
bool GlyphPageCreator::insertGlyph(FT_Bitmap bits, core::rect<s32>& rect)
|
||||
{
|
||||
core::dimension2du d(bits.width + 1, bits.rows + 1);
|
||||
core::dimension2du texture_size;
|
||||
|
||||
switch (bits.pixel_mode)
|
||||
{
|
||||
case FT_PIXEL_MODE_GRAY:
|
||||
{
|
||||
// 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));
|
||||
|
||||
// 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();
|
||||
u8* glyph_data = bits.buffer;
|
||||
for (u32 y = 0; y < (unsigned)bits.rows; ++y)
|
||||
{
|
||||
u8* row = glyph_data;
|
||||
for (u32 x = 0; x < (unsigned)bits.width; ++x)
|
||||
{
|
||||
image_data[y * image_pitch + x] |= static_cast<u32>(255.0f * (static_cast<float>(*row++) / gray_count)) << 24;
|
||||
//data[y * image_pitch + x] |= ((u32)(*bitsdata++) << 24);
|
||||
}
|
||||
glyph_data += bits.pitch;
|
||||
}
|
||||
image->unlock();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
if (!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)
|
||||
{
|
||||
used_width = 0;
|
||||
used_height += temp_height;
|
||||
temp_height = 0;
|
||||
}
|
||||
|
||||
//Copy now
|
||||
image->copyTo(page, core::position2di(used_width, used_height));
|
||||
|
||||
//Store the rectangle of current glyph
|
||||
rect = core::rect<s32> (used_width, used_height, used_width + bits.width, used_height + bits.rows);
|
||||
|
||||
image->drop();
|
||||
image = 0;
|
||||
|
||||
//Store used area
|
||||
used_width += texture_size.Width;
|
||||
if (temp_height < texture_size.Height)
|
||||
temp_height = texture_size.Height;
|
||||
return true;
|
||||
}
|
||||
|
||||
u32 GlyphPageCreator::used_width = 0;
|
||||
u32 GlyphPageCreator::used_height = 0;
|
||||
u32 GlyphPageCreator::temp_height = 0;
|
||||
|
||||
} // guiengine
|
||||
#endif // ENABLE_FREETYPE
|
95
src/guiengine/glyph_page_creator.hpp
Normal file
@ -0,0 +1,95 @@
|
||||
// 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 <IVideoDriver.h>
|
||||
#include <irrlicht.h>
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
#include <set>
|
||||
|
||||
using namespace irr;
|
||||
|
||||
/**
|
||||
* \ingroup guiengine
|
||||
*/
|
||||
namespace GUIEngine
|
||||
{
|
||||
/**
|
||||
* \brief Create glyph pages for different fonts.
|
||||
*/
|
||||
class GlyphPageCreator
|
||||
{
|
||||
public:
|
||||
GlyphPageCreator();
|
||||
~GlyphPageCreator();
|
||||
|
||||
/** Write the current glyph page into png on current running directory.
|
||||
* Mainly for debug use.
|
||||
* \param fn The file name.
|
||||
*/
|
||||
void dumpGlyphPage(const core::stringc fn);
|
||||
|
||||
/** Check whether it is ok the fit the inputted glyph into the current glyph page.
|
||||
* \param bits The Glyph bitmap inputted.
|
||||
* \return True if there is enough space.
|
||||
*/
|
||||
bool checkEnoughSpace(FT_Bitmap bits);
|
||||
|
||||
/** Reset position of glyph on the current glyph page.
|
||||
*/
|
||||
static void clearGlyphPage();
|
||||
|
||||
/** Clear (fill it with transparent content) the current glyph page.
|
||||
*/
|
||||
void createNewGlyphPage();
|
||||
|
||||
/** Used to get a glyph page which is loaded later for texture
|
||||
* \return Glyph page image.
|
||||
*/
|
||||
video::IImage* getPage();
|
||||
|
||||
/** Used to get the string of new characters inside set newchar. (Mainly for debug)
|
||||
* \return string of wild-character.
|
||||
*/
|
||||
core::stringw getNewChar();
|
||||
|
||||
/** 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.
|
||||
* \return True if a glyph is loaded.
|
||||
*/
|
||||
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;
|
||||
|
||||
/** A full glyph page.
|
||||
*/
|
||||
video::IImage* page;
|
||||
|
||||
static u32 temp_height;
|
||||
static u32 used_width;
|
||||
static u32 used_height;
|
||||
};
|
||||
|
||||
} // guiengine
|
@ -16,12 +16,81 @@
|
||||
#include <IVideoDriver.h>
|
||||
#include <IXMLReader.h>
|
||||
|
||||
#include <clocale>
|
||||
#include <cmath>
|
||||
#include <cwctype>
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
|
||||
//! constructor
|
||||
#ifdef ENABLE_FREETYPE
|
||||
ScalableFont::ScalableFont(IGUIEnvironment *env, TTFLoadingType type)
|
||||
: Driver(0), SpriteBank(0), Environment(env), WrongCharacter(0),
|
||||
MaxHeight(0), GlobalKerningWidth(0), GlobalKerningHeight(0)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("ScalableFont");
|
||||
#endif
|
||||
|
||||
m_fallback_font = NULL;
|
||||
m_fallback_kerning_width = 0;
|
||||
m_fallback_font_scale = 1.0f;
|
||||
m_scale = 1.0f;
|
||||
m_is_hollow_copy = false;
|
||||
m_black_border = false;
|
||||
m_type = type;
|
||||
m_font_use = (FontUse)0;
|
||||
m_dpi = 0;
|
||||
m_shadow = false;
|
||||
m_mono_space_digits = false;
|
||||
m_rtl = translations->isRTLLanguage();
|
||||
|
||||
if (Environment)
|
||||
{
|
||||
// don't grab environment, to avoid circular references
|
||||
Driver = Environment->getVideoDriver();
|
||||
|
||||
SpriteBank = Environment->addEmptySpriteBank((std::to_string(type)).c_str());
|
||||
if (SpriteBank)
|
||||
SpriteBank->grab();
|
||||
}
|
||||
|
||||
if (Driver)
|
||||
Driver->grab();
|
||||
|
||||
setInvisibleCharacters ( L" " );
|
||||
|
||||
if (!loadTTF())
|
||||
{
|
||||
Log::fatal("ScalableFont", "Loading TTF font failed");
|
||||
}
|
||||
|
||||
assert(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");
|
||||
}
|
||||
}
|
||||
#else
|
||||
ScalableFont::ScalableFont(IGUIEnvironment *env, const std::string &filename)
|
||||
: Driver(0), SpriteBank(0), Environment(env), WrongCharacter(0),
|
||||
MaxHeight(0), GlobalKerningWidth(0), GlobalKerningHeight(0)
|
||||
@ -65,6 +134,7 @@ ScalableFont::ScalableFont(IGUIEnvironment *env, const std::string &filename)
|
||||
assert(Areas.size() > 0);
|
||||
}
|
||||
|
||||
#endif // ENABLE_FREETYPE
|
||||
|
||||
//! destructor
|
||||
ScalableFont::~ScalableFont()
|
||||
@ -87,6 +157,7 @@ void ScalableFont::setShadow(const irr::video::SColor &col)
|
||||
m_shadow_color = col;
|
||||
}
|
||||
|
||||
#ifndef ENABLE_FREETYPE
|
||||
void ScalableFont::doReadXmlFile(io::IXMLReader* xml)
|
||||
{
|
||||
int trim_top = 0;
|
||||
@ -281,11 +352,391 @@ bool ScalableFont::load(io::IXMLReader* xml)
|
||||
m_max_digit_area.overhang = 0;m_max_digit_area.underhang=0;
|
||||
return true;
|
||||
}
|
||||
#endif // ENABLE_FREETYPE
|
||||
|
||||
#ifdef ENABLE_FREETYPE
|
||||
//! loads a font from a TTF file
|
||||
bool ScalableFont::loadTTF()
|
||||
{
|
||||
if (!SpriteBank)
|
||||
{
|
||||
Log::error("ScalableFont::loadTTF", "SpriteBank is NULL!!");
|
||||
return false;
|
||||
}
|
||||
|
||||
GUIEngine::GlyphPageCreator* gp_creator = GUIEngine::getGlyphPageCreator();
|
||||
|
||||
//Initialize glyph slot
|
||||
FT_GlyphSlot slot;
|
||||
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> bx;
|
||||
std::vector <s32> advance;
|
||||
std::vector <s32> height;
|
||||
|
||||
std::set<wchar_t>::iterator it;
|
||||
s32 current_maxheight = 0;
|
||||
s32 t;
|
||||
u32 texno = 0;
|
||||
SpriteBank->addTexture(NULL);
|
||||
gp_creator->clearGlyphPage();
|
||||
gp_creator->createNewGlyphPage();
|
||||
|
||||
GUIEngine::FTEnvironment* ft_env = GUIEngine::getFreetype();
|
||||
|
||||
it = cur_prop.usedchar.begin();
|
||||
while (it != cur_prop.usedchar.end())
|
||||
{
|
||||
SGUISpriteFrame f;
|
||||
SGUISprite s;
|
||||
core::rect<s32> rectangle;
|
||||
|
||||
int idx;
|
||||
if (m_type == T_BOLD) //Lite-Fontconfig for stk, this one is specifically for bold title
|
||||
{
|
||||
int count = F_BOLD;
|
||||
while (count < irr::gui::F_COUNT)
|
||||
{
|
||||
m_font_use = (FontUse)count;
|
||||
FT_Face curr_face = ft_env->ft_face[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);
|
||||
if (idx > 0) break;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FT_Face curr_face = ft_env->ft_face[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);
|
||||
}
|
||||
|
||||
FT_Face curr_face = ft_env->ft_face[m_font_use];
|
||||
slot = curr_face->glyph;
|
||||
|
||||
if (idx)
|
||||
{
|
||||
// Load glyph image into the slot (erase previous one)
|
||||
err = FT_Load_Glyph(curr_face, idx,
|
||||
FT_LOAD_DEFAULT | FT_LOAD_RENDER | FT_LOAD_TARGET_NORMAL);
|
||||
if (err)
|
||||
Log::error("ScalableFont::loadTTF", "Can't load a single glyph.");
|
||||
|
||||
// Store vertical offset on line.
|
||||
s32 offset_on_line = (curr_face->glyph->metrics.height >> 6) - curr_face->glyph->bitmap_top;
|
||||
offset.push_back(offset_on_line);
|
||||
|
||||
// This is to be used later.
|
||||
t = curr_face->glyph->metrics.height >> 6;
|
||||
height.push_back(t);
|
||||
if (t > current_maxheight)
|
||||
current_maxheight = t;
|
||||
|
||||
// Store horizontal padding (bearingX).
|
||||
s32 bX = curr_face->glyph->bitmap_left;
|
||||
bx.push_back(bX);
|
||||
|
||||
// Store total width on horizontal line.
|
||||
s32 width = curr_face->glyph->advance.x >> 6;
|
||||
advance.push_back(width);
|
||||
|
||||
// Convert to an anti-aliased bitmap
|
||||
FT_Bitmap bits = slot->bitmap;
|
||||
|
||||
CharacterMap[*it] = SpriteBank->getSprites().size();
|
||||
|
||||
if (!gp_creator->checkEnoughSpace(bits))
|
||||
// Glyph page is full, save current one and reset the current page
|
||||
{
|
||||
#ifdef FONT_DEBUG
|
||||
gp_creator->dumpGlyphPage(((std::to_string(m_type)) + "_" + (std::to_string(texno))).c_str());
|
||||
#endif
|
||||
SpriteBank->setTexture(texno, Driver->addTexture("Glyph_page", gp_creator->getPage()));
|
||||
gp_creator->clearGlyphPage();
|
||||
SpriteBank->addTexture(NULL);
|
||||
gp_creator->createNewGlyphPage();
|
||||
texno++;
|
||||
}
|
||||
|
||||
// Inserting now
|
||||
if (gp_creator->insertGlyph(bits, rectangle))
|
||||
{
|
||||
f.rectNumber = SpriteBank->getPositions().size();
|
||||
f.textureNumber = texno;
|
||||
|
||||
// add frame to sprite
|
||||
s.Frames.push_back(f);
|
||||
s.frameTime = 0;
|
||||
|
||||
SpriteBank->getPositions().push_back(rectangle);
|
||||
SpriteBank->getSprites().push_back(s);
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for glyph page which can fit all characters
|
||||
if (it == --cur_prop.usedchar.end())
|
||||
{
|
||||
#ifdef FONT_DEBUG
|
||||
gp_creator->dumpGlyphPage(((std::to_string(m_type)) + "_" + (std::to_string(texno))).c_str());
|
||||
#endif
|
||||
if (m_type == T_NORMAL)
|
||||
{
|
||||
LastNormalPage = Driver->addTexture("Glyph_page", gp_creator->getPage());
|
||||
SpriteBank->setTexture(texno, LastNormalPage);
|
||||
}
|
||||
else
|
||||
SpriteBank->setTexture(texno, Driver->addTexture("Glyph_page", gp_creator->getPage()));
|
||||
}
|
||||
|
||||
if (*it == (wchar_t)32 && SpriteBank->getPositions().size() == 1)
|
||||
continue; //Preventing getAreaIDFromCharacter of whitespace == 0, which make space disappear
|
||||
else ++it;
|
||||
}
|
||||
|
||||
//Fix unused glyphs....
|
||||
if (m_type == T_NORMAL || T_BOLD)
|
||||
{
|
||||
CharacterMap[(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.
|
||||
//And then it will convert to a "-".
|
||||
|
||||
if (m_type == T_NORMAL)
|
||||
{
|
||||
CharacterMap[(wchar_t)8204] = 0; //They are zero width chars found in Arabic.
|
||||
CharacterMap[(wchar_t)65279] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_type == T_BOLD)
|
||||
{
|
||||
setlocale(LC_ALL, "en_US.UTF8");
|
||||
for (it = cur_prop.usedchar.begin(); it != cur_prop.usedchar.end(); ++it)
|
||||
{
|
||||
if (iswupper((wchar_t)*it) && *it < 640)
|
||||
CharacterMap[towlower((wchar_t)*it)] = getAreaIDFromCharacter(*it, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned int n = 0 ; n < SpriteBank->getSprites().size(); ++n)
|
||||
{
|
||||
//Storing now
|
||||
SFontArea a;
|
||||
a.spriteno = n;
|
||||
a.offsety = current_maxheight - height.at(n)
|
||||
+ offset.at(n); //Compute the correct offset as ttf texture image is cropped against the glyph fully.
|
||||
|
||||
a.offsety_bt = -offset.at(n); //FIXME
|
||||
//Specific offset for billboard text as billboard text seems to be drawn bottom-up,
|
||||
//as the offset in calculated based on the fact that the characters are drawn all
|
||||
//at the bottom line, so no addition is required, but if we can make draw2dimage draw
|
||||
//characters close to the bottom line too, than only one offsety is needed.
|
||||
|
||||
if (!n) //Skip width-less characters
|
||||
a.bearingx = 0;
|
||||
else
|
||||
a.bearingx = bx.at(n);
|
||||
if (!n) //Skip width-less characters
|
||||
a.width = 0;
|
||||
else
|
||||
a.width = advance.at(n);
|
||||
// add character to font
|
||||
Areas.push_back(a);
|
||||
}
|
||||
|
||||
WrongCharacter = getAreaIDFromCharacter(L' ', NULL);
|
||||
|
||||
//Reserve 10 for normal font new characters added, 40 for digit font to display separately
|
||||
//Consider fallback font (bold) too
|
||||
MaxHeight = (int)((current_maxheight + (m_type == T_DIGIT ? 40 : 10) +
|
||||
(m_type == T_BOLD ? 20 : 0))*m_scale);
|
||||
|
||||
GlyphMaxHeight = current_maxheight;
|
||||
|
||||
for(wchar_t c='0'; c<='9'; c++)
|
||||
{
|
||||
SFontArea a = getAreaFromCharacter(c, NULL);
|
||||
m_max_digit_area.width = a.width;
|
||||
m_max_digit_area.offsety = a.offsety;
|
||||
m_max_digit_area.bearingx = a.bearingx;
|
||||
}
|
||||
|
||||
switch (m_type)
|
||||
{
|
||||
case T_NORMAL:
|
||||
Log::info("ScalableFont::loadTTF", "Created %d glyphs "
|
||||
"supporting %d characters for normal font %s at %d dpi using %d glyph page(s)."
|
||||
, Areas.size(), CharacterMap.size(), GUIEngine::getFreetype()->ft_face[m_font_use]->family_name, m_dpi, SpriteBank->getTextureCount());
|
||||
break;
|
||||
case T_DIGIT:
|
||||
Log::info("ScalableFont::loadTTF", "Created %d glyphs "
|
||||
"supporting %d characters for high-res digits font %s at %d dpi using %d glyph page(s)."
|
||||
, Areas.size(), CharacterMap.size(), GUIEngine::getFreetype()->ft_face[m_font_use]->family_name, m_dpi, SpriteBank->getTextureCount());
|
||||
break;
|
||||
case T_BOLD:
|
||||
Log::info("ScalableFont::loadTTF", "Created %d glyphs "
|
||||
"supporting %d characters for bold title font %s at %d dpi using %d glyph page(s)."
|
||||
, Areas.size(), CharacterMap.size(), GUIEngine::getFreetype()->ft_face[m_font_use]->family_name, m_dpi, SpriteBank->getTextureCount());
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//! lazy load new characters discovered in normal font
|
||||
bool ScalableFont::lazyLoadChar()
|
||||
{
|
||||
//Mainly copy from loadTTF(), so removing unnecessary comments
|
||||
if (m_type != T_NORMAL) return false; //Make sure only insert char inside normal font
|
||||
|
||||
FT_GlyphSlot slot;
|
||||
FT_Error err;
|
||||
|
||||
GUIEngine::FTEnvironment* ft_env = GUIEngine::getFreetype();
|
||||
GUIEngine::GlyphPageCreator* gp_creator = GUIEngine::getGlyphPageCreator();
|
||||
|
||||
s32 height;
|
||||
s32 bX;
|
||||
s32 offset_on_line;
|
||||
s32 width;
|
||||
u32 texno = SpriteBank->getTextureCount() - 1;
|
||||
std::set<wchar_t>::iterator it;
|
||||
it = gp_creator->newchar.begin();
|
||||
while (it != gp_creator->newchar.end())
|
||||
{
|
||||
SGUISpriteFrame f;
|
||||
SGUISprite s;
|
||||
core::rect<s32> rectangle;
|
||||
|
||||
//Lite-Fontconfig for stk
|
||||
int idx;
|
||||
int font = irr::gui::F_DEFAULT;
|
||||
while (font <= irr::gui::F_LAST_REGULAR_FONT)
|
||||
{
|
||||
m_font_use = (FontUse)font;
|
||||
|
||||
FT_Face face = ft_env->ft_face[font];
|
||||
|
||||
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;
|
||||
|
||||
font++;
|
||||
}
|
||||
|
||||
FT_Face curr_face = ft_env->ft_face[m_font_use];
|
||||
|
||||
slot = curr_face->glyph;
|
||||
|
||||
if (idx)
|
||||
{
|
||||
err = FT_Load_Glyph(curr_face, idx,
|
||||
FT_LOAD_DEFAULT | FT_LOAD_RENDER | FT_LOAD_TARGET_NORMAL);
|
||||
if (err)
|
||||
Log::error("ScalableFont::loadTTF", "Can't load a single glyph.");
|
||||
|
||||
offset_on_line = (curr_face->glyph->metrics.height >> 6) - curr_face->glyph->bitmap_top;
|
||||
height = curr_face->glyph->metrics.height >> 6;
|
||||
bX = curr_face->glyph->bitmap_left;
|
||||
width = curr_face->glyph->advance.x >> 6;
|
||||
FT_Bitmap bits = slot->bitmap;
|
||||
CharacterMap[*it] = SpriteBank->getSprites().size();
|
||||
|
||||
if (!gp_creator->checkEnoughSpace(bits))
|
||||
{
|
||||
#ifdef FONT_DEBUG
|
||||
gp_creator->dumpGlyphPage(((std::to_string(m_type)) + "_" + (std::to_string(texno))).c_str());
|
||||
#endif
|
||||
SpriteBank->setTexture(texno, Driver->addTexture("Glyph_page", gp_creator->getPage()));
|
||||
gp_creator->clearGlyphPage();
|
||||
SpriteBank->addTexture(NULL);
|
||||
gp_creator->createNewGlyphPage();
|
||||
texno++;
|
||||
}
|
||||
|
||||
if (gp_creator->insertGlyph(bits, rectangle))
|
||||
{
|
||||
f.rectNumber = SpriteBank->getPositions().size();
|
||||
f.textureNumber = texno;
|
||||
s.Frames.push_back(f);
|
||||
s.frameTime = 0;
|
||||
SpriteBank->getPositions().push_back(rectangle);
|
||||
SpriteBank->getSprites().push_back(s);
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
SFontArea a;
|
||||
a.spriteno = SpriteBank->getSprites().size() - 1;
|
||||
a.offsety = GlyphMaxHeight - height + offset_on_line;
|
||||
a.offsety_bt = -offset_on_line;
|
||||
a.bearingx = bX;
|
||||
a.width = width;
|
||||
Areas.push_back(a);
|
||||
}
|
||||
else
|
||||
CharacterMap[*it] = 2; //Set wrong character to !, preventing it from loading again
|
||||
++it;
|
||||
}
|
||||
|
||||
#ifdef FONT_DEBUG
|
||||
gp_creator->dumpGlyphPage(((std::to_string(m_type)) + "_" + (std::to_string(texno))).c_str());
|
||||
#endif
|
||||
gp_creator->newchar.clear(); //Clear the Newly characters in creator after they are loaded
|
||||
Driver->removeTexture(LastNormalPage); //Remove old texture
|
||||
LastNormalPage = Driver->addTexture("Glyph_page", gp_creator->getPage());
|
||||
SpriteBank->setTexture(texno, LastNormalPage);
|
||||
|
||||
if (!m_is_hollow_copy)
|
||||
{
|
||||
GUIEngine::cleanHollowCopyFont();
|
||||
GUIEngine::reloadHollowCopyFont(GUIEngine::getFont());
|
||||
}
|
||||
|
||||
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."
|
||||
, GUIEngine::getFreetype()->ft_face[m_font_use]->family_name, Areas.size(), CharacterMap.size(), m_dpi, SpriteBank->getTextureCount());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//! force create a new texture (glyph) page in a font
|
||||
void ScalableFont::forceNewPage()
|
||||
{
|
||||
GUIEngine::GlyphPageCreator* gp_creator = GUIEngine::getGlyphPageCreator();
|
||||
|
||||
SpriteBank->setTexture(SpriteBank->getTextureCount() - 1, Driver->addTexture("Glyph_page", gp_creator->getPage()));
|
||||
gp_creator->clearGlyphPage();
|
||||
SpriteBank->addTexture(NULL);
|
||||
gp_creator->createNewGlyphPage();
|
||||
}
|
||||
|
||||
#endif // ENABLE_FREETYPE
|
||||
|
||||
void ScalableFont::setScale(const float scale)
|
||||
{
|
||||
m_scale = scale;
|
||||
}
|
||||
|
||||
#ifndef ENABLE_FREETYPE
|
||||
void ScalableFont::setMaxHeight()
|
||||
{
|
||||
MaxHeight = 0;
|
||||
@ -313,6 +764,7 @@ void ScalableFont::setMaxHeight()
|
||||
|
||||
MaxHeight = (int)(MaxHeight*m_scale);
|
||||
}
|
||||
#endif // ENABLE_FREETYPE
|
||||
|
||||
|
||||
|
||||
@ -328,6 +780,7 @@ s32 ScalableFont::getKerningWidth(const wchar_t* thisLetter, const wchar_t* prev
|
||||
{
|
||||
s32 ret = GlobalKerningWidth;
|
||||
|
||||
#ifndef ENABLE_FREETYPE
|
||||
if (thisLetter)
|
||||
{
|
||||
ret += Areas[getAreaIDFromCharacter(*thisLetter, NULL)].overhang;
|
||||
@ -337,6 +790,7 @@ s32 ScalableFont::getKerningWidth(const wchar_t* thisLetter, const wchar_t* prev
|
||||
ret += Areas[getAreaIDFromCharacter(*previousLetter, NULL)].underhang;
|
||||
}
|
||||
}
|
||||
#endif // ENABLE_FREETYPE
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -426,6 +880,29 @@ void ScalableFont::setInvisibleCharacters( const wchar_t *s )
|
||||
//! returns the dimension of text
|
||||
core::dimension2d<u32> ScalableFont::getDimension(const wchar_t* text) const
|
||||
{
|
||||
#ifdef ENABLE_FREETYPE
|
||||
GUIEngine::GlyphPageCreator* gp_creator = GUIEngine::getGlyphPageCreator();
|
||||
|
||||
if (m_type == T_NORMAL || T_BOLD) //lazy load char
|
||||
{
|
||||
for (const wchar_t* p = text; *p; ++p)
|
||||
{
|
||||
if (*p == L'\r' || *p == L'\n' || *p == L' ' || *p < 32) continue;
|
||||
if (GUIEngine::getFont()->getSpriteNoFromChar(p) == WrongCharacter)
|
||||
gp_creator->newchar.insert(*p);
|
||||
}
|
||||
|
||||
if (gp_creator->newchar.size() > 0 && !m_is_hollow_copy && m_scale == 1)
|
||||
{
|
||||
Log::debug("ScalableFont::getDimension", "New character(s) %s discoverd, perform lazy loading",
|
||||
StringUtils::wide_to_utf8(gp_creator->getNewChar().c_str()).c_str());
|
||||
|
||||
if (!GUIEngine::getFont()->lazyLoadChar())
|
||||
Log::error("ScalableFont::lazyLoadChar", "Can't insert new char into glyph pages.");
|
||||
}
|
||||
}
|
||||
#endif // ENABLE_FREETYPE
|
||||
|
||||
assert(Areas.size() > 0);
|
||||
|
||||
core::dimension2d<u32> dim(0, 0);
|
||||
@ -448,7 +925,9 @@ core::dimension2d<u32> ScalableFont::getDimension(const wchar_t* text) const
|
||||
bool fallback = false;
|
||||
const SFontArea &area = getAreaFromCharacter(*p, &fallback);
|
||||
|
||||
#ifndef ENABLE_FREETYPE
|
||||
thisLine.Width += area.underhang;
|
||||
#endif // ENABLE_FREETYPE
|
||||
|
||||
thisLine.Width += getCharWidth(area, fallback);
|
||||
}
|
||||
@ -496,6 +975,8 @@ void ScalableFont::doDraw(const core::stringw& text,
|
||||
{
|
||||
if (!Driver) return;
|
||||
|
||||
GUIEngine::GlyphPageCreator* gp_creator = GUIEngine::getGlyphPageCreator();
|
||||
|
||||
if (m_shadow)
|
||||
{
|
||||
m_shadow = false; // avoid infinite recursion
|
||||
@ -534,6 +1015,37 @@ void ScalableFont::doDraw(const core::stringw& text,
|
||||
core::array<core::position2di> offsets(text_size);
|
||||
std::vector<bool> fallback(text_size);
|
||||
|
||||
#ifdef ENABLE_FREETYPE
|
||||
if (m_type == T_NORMAL || T_BOLD) //lazy load char, have to do this again
|
||||
{ //because some text isn't drawn with getDimension
|
||||
for (u32 i = 0; i<text_size; i++)
|
||||
{
|
||||
wchar_t c = text[i];
|
||||
if (c == L'\r' || c == L'\n' || c == L' ' || c < 32) continue;
|
||||
if (GUIEngine::getFont()->getSpriteNoFromChar(&c) == WrongCharacter)
|
||||
gp_creator->newchar.insert(c);
|
||||
|
||||
if (charCollector != NULL && m_type == T_NORMAL && SpriteBank->getSprites()
|
||||
[GUIEngine::getFont()->getSpriteNoFromChar(&c)].Frames[0].textureNumber
|
||||
== 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."
|
||||
" Create a new glyph page for new characters inserted later to prevent it from being removed.");
|
||||
GUIEngine::getFont()->forceNewPage();
|
||||
}
|
||||
}
|
||||
|
||||
if (gp_creator->newchar.size() > 0 && !m_is_hollow_copy && m_scale == 1)
|
||||
{
|
||||
Log::debug("ScalableFont::doDraw", "New character(s) %s discoverd, perform lazy loading",
|
||||
StringUtils::wide_to_utf8(gp_creator->getNewChar().c_str()).c_str());
|
||||
|
||||
if (!GUIEngine::getFont()->lazyLoadChar())
|
||||
Log::error("ScalableFont::lazyLoadChar", "Can't insert new char into glyph pages.");
|
||||
}
|
||||
}
|
||||
#endif // ENABLE_FREETYPE
|
||||
|
||||
for (u32 i = 0; i<text_size; i++)
|
||||
{
|
||||
wchar_t c = text[i];
|
||||
@ -552,8 +1064,36 @@ void ScalableFont::doDraw(const core::stringw& text,
|
||||
bool use_fallback_font = false;
|
||||
const SFontArea &area = getAreaFromCharacter(c, &use_fallback_font);
|
||||
fallback[i] = use_fallback_font;
|
||||
#ifdef ENABLE_FREETYPE
|
||||
if (charCollector == NULL)
|
||||
{
|
||||
//floor is used to prevent negligible movement when m_scale changes with resolution
|
||||
int Hpadding = floor((float) area.bearingx*
|
||||
(fallback[i] ? m_scale*m_fallback_font_scale : m_scale));
|
||||
int Vpadding = floor((float) area.offsety*
|
||||
(fallback[i] ? m_scale*m_fallback_font_scale : m_scale));
|
||||
offset.X += Hpadding;
|
||||
offset.Y += Vpadding + floor(m_type == T_DIGIT ? 20*m_scale : 0); //Additional offset for digit text
|
||||
offsets.push_back(offset);
|
||||
offset.X -= Hpadding;
|
||||
offset.Y -= Vpadding + floor(m_type == T_DIGIT ? 20*m_scale : 0);
|
||||
}
|
||||
else //Billboard text specific
|
||||
{
|
||||
int Hpadding = floor((float) area.bearingx*
|
||||
(fallback[i] ? m_scale*m_fallback_font_scale : m_scale));
|
||||
int Vpadding = floor((float) area.offsety_bt*
|
||||
(fallback[i] ? m_scale*m_fallback_font_scale : m_scale));
|
||||
offset.X += Hpadding;
|
||||
offset.Y += Vpadding + floor(m_type == T_DIGIT ? 20*m_scale : 0); //Additional offset for digit text
|
||||
offsets.push_back(offset);
|
||||
offset.X -= Hpadding;
|
||||
offset.Y -= Vpadding + floor(m_type == T_DIGIT ? 20*m_scale : 0);
|
||||
}
|
||||
#else
|
||||
offset.X += area.underhang;
|
||||
offsets.push_back(offset);
|
||||
#endif // ENABLE_FREETYPE
|
||||
// Invisible character. add something to the array anyway so that
|
||||
// indices from the various arrays remain in sync
|
||||
indices.push_back( Invisible.findFirst(c) < 0 ? area.spriteno
|
||||
@ -595,11 +1135,15 @@ void ScalableFont::doDraw(const core::stringw& text,
|
||||
(*fallback_positions)[(*fallback_sprites)[spriteID].Frames[0].rectNumber] :
|
||||
positions[sprites[spriteID].Frames[0].rectNumber]);
|
||||
|
||||
#ifdef ENABLE_FREETYPE
|
||||
float char_scale = 1.0f;
|
||||
#else
|
||||
const TextureInfo& info = (fallback[n] ?
|
||||
(*(m_fallback_font->m_texture_files.find(texID))).second :
|
||||
(*(m_texture_files.find(texID))).second
|
||||
);
|
||||
float char_scale = info.m_scale;
|
||||
#endif // ENABLE_FREETYPE
|
||||
|
||||
core::dimension2d<s32> size = source.getSize();
|
||||
|
||||
@ -608,9 +1152,13 @@ void ScalableFont::doDraw(const core::stringw& text,
|
||||
size.Height = (int)(size.Height * scale * char_scale);
|
||||
|
||||
// align vertically if character is smaller
|
||||
#ifndef ENABLE_FREETYPE
|
||||
int y_shift = (size.Height < MaxHeight*m_scale ? (int)((MaxHeight*m_scale - size.Height)/2.0f) : 0);
|
||||
|
||||
core::rect<s32> dest(offsets[n] + core::position2di(0, y_shift), size);
|
||||
#else
|
||||
core::rect<s32> dest(offsets[n], size);
|
||||
#endif // ENABLE_FREETYPE
|
||||
|
||||
video::ITexture* texture = (fallback[n] ?
|
||||
m_fallback_font->SpriteBank->getTexture(texID) :
|
||||
@ -624,7 +1172,11 @@ void ScalableFont::doDraw(const core::stringw& text,
|
||||
source.getWidth(), source.getHeight(), offsets[n].X, offsets[n].Y);
|
||||
}
|
||||
*/
|
||||
#ifdef FONT_DEBUG
|
||||
GL32_draw2DRectangle(video::SColor(255, 255,0,0), dest,clip);
|
||||
#endif
|
||||
|
||||
#ifndef ENABLE_FREETYPE
|
||||
if (texture == NULL)
|
||||
{
|
||||
// perform lazy loading
|
||||
@ -646,6 +1198,7 @@ void ScalableFont::doDraw(const core::stringw& text,
|
||||
continue; // no such character
|
||||
}
|
||||
}
|
||||
#endif // ENABLE_FREETYPE
|
||||
|
||||
if (m_black_border && charCollector == NULL)
|
||||
{
|
||||
@ -666,7 +1219,11 @@ void ScalableFont::doDraw(const core::stringw& text,
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ENABLE_FREETYPE
|
||||
if (fallback[n] || m_type == T_BOLD)
|
||||
#else
|
||||
if (fallback[n])
|
||||
#endif // ENABLE_FREETYPE
|
||||
{
|
||||
// TODO: don't hardcode colors?
|
||||
video::SColor orange(color.getAlpha(), 255, 100, 0);
|
||||
@ -707,26 +1264,12 @@ void ScalableFont::doDraw(const core::stringw& text,
|
||||
clip,
|
||||
color, true);
|
||||
}
|
||||
#ifdef FONT_DEBUG
|
||||
video::IVideoDriver* driver = GUIEngine::getDriver();
|
||||
driver->draw2DLine(core::position2d<s32>(dest.UpperLeftCorner.X, dest.UpperLeftCorner.Y),
|
||||
core::position2d<s32>(dest.UpperLeftCorner.X, dest.LowerRightCorner.Y),
|
||||
video::SColor(255, 255,0,0));
|
||||
driver->draw2DLine(core::position2d<s32>(dest.LowerRightCorner.X, dest.LowerRightCorner.Y),
|
||||
core::position2d<s32>(dest.LowerRightCorner.X, dest.UpperLeftCorner.Y),
|
||||
video::SColor(255, 255,0,0));
|
||||
driver->draw2DLine(core::position2d<s32>(dest.LowerRightCorner.X, dest.LowerRightCorner.Y),
|
||||
core::position2d<s32>(dest.UpperLeftCorner.X, dest.LowerRightCorner.Y),
|
||||
video::SColor(255, 255,0,0));
|
||||
driver->draw2DLine(core::position2d<s32>(dest.UpperLeftCorner.X, dest.UpperLeftCorner.Y),
|
||||
core::position2d<s32>(dest.LowerRightCorner.X, dest.UpperLeftCorner.Y),
|
||||
video::SColor(255, 255,0,0));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifndef ENABLE_FREETYPE
|
||||
void ScalableFont::lazyLoadTexture(int texID)
|
||||
{
|
||||
Driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, true);
|
||||
@ -765,9 +1308,13 @@ void ScalableFont::lazyLoadTexture(int texID)
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // ENABLE_FREETYPE
|
||||
|
||||
int ScalableFont::getCharWidth(const SFontArea& area, const bool fallback) const
|
||||
{
|
||||
#ifdef ENABLE_FREETYPE
|
||||
const float char_scale = 1.0f;
|
||||
#else
|
||||
core::array< SGUISprite >& sprites = SpriteBank->getSprites();
|
||||
core::array< SGUISprite >* fallback_sprites = (m_fallback_font != NULL ?
|
||||
&m_fallback_font->SpriteBank->getSprites() :
|
||||
@ -783,11 +1330,17 @@ int ScalableFont::getCharWidth(const SFontArea& area, const bool fallback) const
|
||||
);
|
||||
assert(info.m_file_name.size() > 0);
|
||||
const float char_scale = info.m_scale;
|
||||
#endif // ENABLE_FREETYPE
|
||||
|
||||
//Log::info("ScalableFont", "area.spriteno = %d, char_scale = %f", area.spriteno, char_scale);
|
||||
|
||||
#ifdef ENABLE_FREETYPE
|
||||
if (fallback) return (int)((area.width*m_fallback_font_scale + m_fallback_kerning_width) * m_scale * char_scale);
|
||||
else return (int)((area.width + GlobalKerningWidth) * m_scale * char_scale);
|
||||
#else
|
||||
if (fallback) return (int)(((area.width + area.overhang)*m_fallback_font_scale + m_fallback_kerning_width) * m_scale * char_scale);
|
||||
else return (int)((area.width + area.overhang + GlobalKerningWidth) * m_scale * char_scale);
|
||||
#endif // ENABLE_FREETYPE
|
||||
}
|
||||
|
||||
|
||||
@ -802,7 +1355,11 @@ s32 ScalableFont::getCharacterFromPos(const wchar_t* text, s32 pixel_x) const
|
||||
bool use_fallback_font = false;
|
||||
const SFontArea &a = getAreaFromCharacter(text[idx], &use_fallback_font);
|
||||
|
||||
#ifdef ENABLE_FREETYPE
|
||||
x += getCharWidth(a, use_fallback_font) + GlobalKerningWidth;
|
||||
#else
|
||||
x += getCharWidth(a, use_fallback_font) + a.overhang + a.underhang + GlobalKerningWidth;
|
||||
#endif // ENABLE_FREETYPE
|
||||
|
||||
if (x >= pixel_x)
|
||||
return idx;
|
||||
|
@ -7,6 +7,10 @@
|
||||
|
||||
#include "utils/leak_check.hpp"
|
||||
|
||||
#ifdef ENABLE_FREETYPE
|
||||
#include "guiengine/get_font_properties.hpp"
|
||||
#endif // ENABLE_FREETYPE
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#include "IGUIFontBitmap.h"
|
||||
#include "irrString.h"
|
||||
@ -51,6 +55,7 @@ class ScalableFont : public IGUIFontBitmap
|
||||
bool m_mono_space_digits;
|
||||
irr::video::SColor m_shadow_color;
|
||||
|
||||
#ifndef ENABLE_FREETYPE
|
||||
struct TextureInfo
|
||||
{
|
||||
irr::core::stringc m_file_name;
|
||||
@ -68,6 +73,7 @@ class ScalableFont : public IGUIFontBitmap
|
||||
std::map<int /* texture file ID */, TextureInfo> m_texture_files;
|
||||
|
||||
void doReadXmlFile(io::IXMLReader* xml);
|
||||
#endif // ENABLE_FREETYPE
|
||||
|
||||
bool m_is_hollow_copy;
|
||||
bool m_rtl;
|
||||
@ -78,12 +84,22 @@ public:
|
||||
|
||||
bool m_black_border;
|
||||
|
||||
#ifdef ENABLE_FREETYPE
|
||||
TTFLoadingType m_type;
|
||||
FontUse m_font_use;
|
||||
u32 m_dpi;
|
||||
#endif // ENABLE_FREETYPE
|
||||
|
||||
ScalableFont* m_fallback_font;
|
||||
float m_fallback_font_scale;
|
||||
int m_fallback_kerning_width;
|
||||
|
||||
//! constructor
|
||||
#ifdef ENABLE_FREETYPE
|
||||
ScalableFont(IGUIEnvironment* env, TTFLoadingType type);
|
||||
#else
|
||||
ScalableFont(IGUIEnvironment* env, const std::string &filename);
|
||||
#endif // ENABLE_FREETYPE
|
||||
|
||||
/** 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
|
||||
@ -104,10 +120,15 @@ public:
|
||||
//! destructor
|
||||
virtual ~ScalableFont();
|
||||
|
||||
#ifdef ENABLE_FREETYPE
|
||||
//! loads a font from a TTF file
|
||||
bool loadTTF();
|
||||
#else
|
||||
//! loads a font from an XML file
|
||||
bool load(io::IXMLReader* xml);
|
||||
|
||||
void lazyLoadTexture(int texID);
|
||||
#endif // ENABLE_FREETYPE
|
||||
|
||||
//! draws an text and clips it to the specified rectangle if wanted
|
||||
virtual void draw(const core::stringw& text, const core::rect<s32>& position,
|
||||
@ -159,8 +180,30 @@ public:
|
||||
|
||||
void updateRTL();
|
||||
|
||||
#ifdef ENABLE_FREETYPE
|
||||
//! 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
|
||||
void forceNewPage();
|
||||
#endif // ENABLE_FREETYPE
|
||||
|
||||
private:
|
||||
|
||||
#ifdef ENABLE_FREETYPE
|
||||
struct SFontArea
|
||||
{
|
||||
SFontArea() : width(0), spriteno(0), offsety(0), offsety_bt(0), bearingx(0) {}
|
||||
s32 width;
|
||||
u32 spriteno;
|
||||
s32 offsety;
|
||||
s32 offsety_bt;
|
||||
s32 bearingx;
|
||||
};
|
||||
#else
|
||||
struct SFontArea
|
||||
{
|
||||
SFontArea() : underhang(0), overhang(0), width(0), spriteno(0) {}
|
||||
@ -169,6 +212,7 @@ private:
|
||||
s32 width;
|
||||
u32 spriteno;
|
||||
};
|
||||
#endif // ENABLE_FREETYPE
|
||||
|
||||
int getCharWidth(const SFontArea& area, const bool fallback) const;
|
||||
s32 getAreaIDFromCharacter(const wchar_t c, bool* fallback_font) const;
|
||||
@ -185,6 +229,10 @@ private:
|
||||
u32 WrongCharacter;
|
||||
s32 MaxHeight;
|
||||
s32 GlobalKerningWidth, GlobalKerningHeight;
|
||||
#ifdef ENABLE_FREETYPE
|
||||
s32 GlyphMaxHeight;
|
||||
video::ITexture* LastNormalPage;
|
||||
#endif // ENABLE_FREETYPE
|
||||
|
||||
core::stringw Invisible;
|
||||
};
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "Keycodes.h"
|
||||
|
||||
#include "graphics/2dutils.hpp"
|
||||
#include "utils/string_utils.hpp"
|
||||
#include "utils/translation.hpp"
|
||||
#include "utils/time.hpp"
|
||||
|
||||
@ -279,9 +280,9 @@ bool CGUIEditBox::processKey(const SEvent& event)
|
||||
const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd;
|
||||
const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin;
|
||||
|
||||
core::stringc s;
|
||||
core::stringw s;
|
||||
s = Text.subString(realmbgn, realmend - realmbgn).c_str();
|
||||
Operator->copyToClipboard(s.c_str());
|
||||
Operator->copyToClipboard(StringUtils::wide_to_utf8(s.c_str()).c_str());
|
||||
}
|
||||
break;
|
||||
case KEY_KEY_X:
|
||||
@ -292,9 +293,9 @@ bool CGUIEditBox::processKey(const SEvent& event)
|
||||
const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin;
|
||||
|
||||
// copy
|
||||
core::stringc sc;
|
||||
core::stringw sc;
|
||||
sc = Text.subString(realmbgn, realmend - realmbgn).c_str();
|
||||
Operator->copyToClipboard(sc.c_str());
|
||||
Operator->copyToClipboard(StringUtils::wide_to_utf8(sc.c_str()).c_str());
|
||||
|
||||
if (isEnabled())
|
||||
{
|
||||
@ -330,13 +331,13 @@ bool CGUIEditBox::processKey(const SEvent& event)
|
||||
{
|
||||
// insert text
|
||||
core::stringw s = Text.subString(0, CursorPos);
|
||||
s.append(p);
|
||||
s.append(StringUtils::utf8_to_wide(p));
|
||||
s.append( Text.subString(CursorPos, Text.size()-CursorPos) );
|
||||
|
||||
if (!Max || s.size()<=Max) // thx to Fish FH for fix
|
||||
{
|
||||
Text = s;
|
||||
s = p;
|
||||
s = StringUtils::utf8_to_wide(p);
|
||||
CursorPos += s.size();
|
||||
}
|
||||
}
|
||||
@ -345,13 +346,13 @@ bool CGUIEditBox::processKey(const SEvent& event)
|
||||
// replace text
|
||||
|
||||
core::stringw s = Text.subString(0, realmbgn);
|
||||
s.append(p);
|
||||
s.append(StringUtils::utf8_to_wide(p));
|
||||
s.append( Text.subString(realmend, Text.size()-realmend) );
|
||||
|
||||
if (!Max || s.size()<=Max) // thx to Fish FH for fix
|
||||
{
|
||||
Text = s;
|
||||
s = p;
|
||||
s = StringUtils::utf8_to_wide(p);
|
||||
CursorPos = realmbgn + s.size();
|
||||
}
|
||||
}
|
||||
|
@ -56,7 +56,6 @@ DynamicRibbonWidget::DynamicRibbonWidget(const bool combo, const bool multi_row)
|
||||
|
||||
m_item_count_hint = 0;
|
||||
|
||||
m_font = GUIEngine::getFont()->getHollowCopy();
|
||||
m_max_label_width = 0;
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
@ -385,6 +384,8 @@ void DynamicRibbonWidget::buildInternalStructure()
|
||||
ribbon->m_properties[PROP_ID] = name.str();
|
||||
ribbon->m_event_handler = this;
|
||||
|
||||
m_font = GUIEngine::getFont()->getHollowCopy();
|
||||
|
||||
// calculate font size
|
||||
if (m_col_amount > 0)
|
||||
{
|
||||
|
@ -145,8 +145,8 @@ void SpinnerWidget::add()
|
||||
else
|
||||
{
|
||||
rect<s32> subsize_label = rect<s32>(m_h, 0, m_w - m_h, m_h);
|
||||
const wchar_t *text = stringw(m_value).c_str();
|
||||
IGUIStaticText* label = GUIEngine::getGUIEnv()->addStaticText(text, subsize_label,
|
||||
stringw text = stringw(m_value);
|
||||
IGUIStaticText* label = GUIEngine::getGUIEnv()->addStaticText(text.c_str(), subsize_label,
|
||||
false /* border */, true /* word wrap */,
|
||||
btn, getNewNoFocusID());
|
||||
m_children[1].m_element = label;
|
||||
|
@ -115,7 +115,6 @@ FileManager::FileManager()
|
||||
{
|
||||
m_subdir_name.resize(ASSET_COUNT);
|
||||
m_subdir_name[CHALLENGE ] = "challenges";
|
||||
m_subdir_name[FONT ] = "fonts";
|
||||
m_subdir_name[GFX ] = "gfx";
|
||||
m_subdir_name[GRANDPRIX ] = "grandprix";
|
||||
m_subdir_name[GUI ] = "gui";
|
||||
@ -127,6 +126,7 @@ FileManager::FileManager()
|
||||
m_subdir_name[SKIN ] = "skins";
|
||||
m_subdir_name[SHADER ] = "shaders";
|
||||
m_subdir_name[TEXTURE ] = "textures";
|
||||
m_subdir_name[TTF ] = "ttf";
|
||||
m_subdir_name[TRANSLATION] = "po";
|
||||
#ifdef __APPLE__
|
||||
// irrLicht's createDevice method has a nasty habit of messing the CWD.
|
||||
|
@ -48,8 +48,8 @@ public:
|
||||
* The last entry ASSET_COUNT specifies the number of entries. */
|
||||
enum AssetType {ASSET_MIN,
|
||||
CHALLENGE=ASSET_MIN,
|
||||
FONT, GFX, GRANDPRIX, GUI, LIBRARY, MODEL, MUSIC,
|
||||
SCRIPT, SFX, SHADER, SKIN, TEXTURE,
|
||||
GFX, GRANDPRIX, GUI, LIBRARY, MODEL, MUSIC,
|
||||
SCRIPT, SFX, SHADER, SKIN, TEXTURE, TTF,
|
||||
TRANSLATION, ASSET_MAX = TRANSLATION,
|
||||
ASSET_COUNT};
|
||||
private:
|
||||
|
@ -1289,14 +1289,6 @@ int main(int argc, char *argv[] )
|
||||
main_loop = new MainLoop();
|
||||
material_manager->loadMaterial();
|
||||
|
||||
// Load the font textures - they are all lazily loaded
|
||||
// so no need to push a texture search path. They will actually
|
||||
// be loaded from ScalableFont.
|
||||
file_manager->pushTextureSearchPath(file_manager->getAsset(FileManager::FONT, ""));
|
||||
material_manager->addSharedMaterial(
|
||||
file_manager->getAsset(FileManager::FONT,"materials.xml"));
|
||||
file_manager->popTextureSearchPath();
|
||||
|
||||
GUIEngine::addLoadingIcon( irr_driver->getTexture(FileManager::GUI,
|
||||
"options_video.png"));
|
||||
kart_properties_manager -> loadAllKarts ();
|
||||
|
@ -192,12 +192,13 @@ void OptionsScreenUI::init()
|
||||
// The names need to be sorted alphabetically. Store the 2-letter
|
||||
// language names in a mapping, to be able to get them from the
|
||||
// user visible full name.
|
||||
std::vector<std::string> nice_lang_list;
|
||||
std::map<std::string, std::string> nice_name_2_id;
|
||||
std::vector<core::stringw> nice_lang_list;
|
||||
std::map<core::stringw, std::string> nice_name_2_id;
|
||||
for (int n=0; n<amount; n++)
|
||||
{
|
||||
std::string code_name = (*lang_list)[n];
|
||||
std::string nice_name = tinygettext::Language::from_name(code_name).get_name();
|
||||
std::string s_name = tinygettext::Language::from_name(code_name).get_name();
|
||||
core::stringw nice_name = StringUtils::utf8_to_wide(s_name.c_str());
|
||||
nice_lang_list.push_back(nice_name);
|
||||
nice_name_2_id[nice_name] = code_name;
|
||||
}
|
||||
@ -205,7 +206,7 @@ void OptionsScreenUI::init()
|
||||
for(unsigned int i=0; i<nice_lang_list.size(); i++)
|
||||
{
|
||||
list_widget->addItem(nice_name_2_id[nice_lang_list[i]],
|
||||
nice_lang_list[i].c_str());
|
||||
nice_lang_list[i]);
|
||||
}
|
||||
|
||||
list_widget->setSelectionID( list_widget->getItemID(UserConfigParams::m_language) );
|
||||
@ -328,6 +329,15 @@ void OptionsScreenUI::eventCallback(Widget* widget, const std::string& name, con
|
||||
}
|
||||
|
||||
translations = new Translations();
|
||||
|
||||
#ifdef ENABLE_FREETYPE
|
||||
//Reload fonts for new translation when using freetype
|
||||
GUIEngine::cleanHollowCopyFont();
|
||||
GUIEngine::getTitleFont()->recreateFromLanguage();
|
||||
GUIEngine::getFont()->recreateFromLanguage();
|
||||
GUIEngine::reloadHollowCopyFont(GUIEngine::getFont());
|
||||
#endif // ENABLE_FREETYPE
|
||||
|
||||
GUIEngine::getStateManager()->hardResetAndGoToScreen<MainMenuScreen>();
|
||||
|
||||
GUIEngine::getFont()->updateRTL();
|
||||
|
@ -19,6 +19,8 @@
|
||||
#include "dictionary.hpp"
|
||||
|
||||
#include "utils/log.hpp"
|
||||
#include "utils/string_utils.hpp"
|
||||
#include "utils/translation.hpp"
|
||||
|
||||
namespace tinygettext {
|
||||
|
||||
@ -211,6 +213,36 @@ Dictionary::add_translation(const std::string& msgctxt, const std::string& msgid
|
||||
}
|
||||
}
|
||||
|
||||
std::set<wchar_t> Dictionary::get_all_used_chars()
|
||||
{
|
||||
std::set<wchar_t> UsedChars;
|
||||
for (Entries::const_iterator i = entries.begin(); i != entries.end(); ++i)
|
||||
{
|
||||
const std::vector<std::string>& msgstrs = i->second;
|
||||
for (unsigned int k = 0; k < msgstrs.size(); k++)
|
||||
{
|
||||
irr::core::stringw ws = translations->fribidize((StringUtils::utf8_to_wide(msgstrs[k].c_str())).c_str());
|
||||
for (unsigned int l = 0; l < ws.size(); ++l)
|
||||
UsedChars.insert(ws[l]);
|
||||
}
|
||||
}
|
||||
|
||||
for (CtxtEntries::const_iterator i = ctxt_entries.begin(); i != ctxt_entries.end(); ++i)
|
||||
{
|
||||
for (Entries::const_iterator j = i->second.begin(); j != i->second.end(); ++j)
|
||||
{
|
||||
const std::vector<std::string>& msgstrs = j->second;
|
||||
for (unsigned int k = 0; k < msgstrs.size(); k++)
|
||||
{
|
||||
irr::core::stringw ws = translations->fribidize((StringUtils::utf8_to_wide(msgstrs[k].c_str())).c_str());
|
||||
for (unsigned int l = 0; l < ws.size(); ++l)
|
||||
UsedChars.insert(ws[l]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return UsedChars;
|
||||
}
|
||||
|
||||
} // namespace tinygettext
|
||||
|
||||
/* EOF */
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <set>
|
||||
#include "plural_forms.hpp"
|
||||
|
||||
namespace tinygettext {
|
||||
@ -91,6 +92,10 @@ public:
|
||||
void add_translation(const std::string& msgid, const std::string& msgstr);
|
||||
void add_translation(const std::string& msgctxt, const std::string& msgid, const std::string& msgstr);
|
||||
|
||||
/** Write all unique character from current dictionary using in a c++ set which is useful for
|
||||
specific character loading. */
|
||||
std::set<wchar_t> get_all_used_chars();
|
||||
|
||||
/** Iterate over all messages, Func is of type:
|
||||
void func(const std::string& msgid, const std::vector<std::string>& msgstrs) */
|
||||
template<class Func>
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "utils/time.hpp"
|
||||
|
||||
#include "graphics/irr_driver.hpp"
|
||||
#include "utils/translation.hpp"
|
||||
|
||||
#include <ctime>
|
||||
|
||||
@ -38,6 +39,22 @@ void StkTime::init()
|
||||
m_timer->grab();
|
||||
} // init
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/** Converts the time in this object to a human readable string. */
|
||||
std::string StkTime::toString(const TimeType &tt)
|
||||
{
|
||||
const struct tm *t = gmtime(&tt);
|
||||
|
||||
//I18N: Format for dates (%d = day, %m = month, %Y = year). See http://www.cplusplus.com/reference/ctime/strftime/ for more info about date formats.
|
||||
core::stringw w_date_format = translations->w_gettext(N_("%d/%m/%Y"));
|
||||
core::stringc c_date_format(w_date_format.c_str());
|
||||
|
||||
char s[64];
|
||||
strftime(s, 64, c_date_format.c_str(), t);
|
||||
return s;
|
||||
} // toString
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Returns a time based on an arbitrary 'epoch' (e.g. could be start
|
||||
* time of the application, 1.1.1970, ...).
|
||||
|
@ -52,13 +52,7 @@ public:
|
||||
static void getDate(int *day=NULL, int *month=NULL, int *year=NULL);
|
||||
|
||||
/** Converts the time in this object to a human readable string. */
|
||||
static std::string toString(const TimeType &tt)
|
||||
{
|
||||
const struct tm *t = gmtime(&tt);
|
||||
char s[16];
|
||||
strftime(s, 16, "%x", t);
|
||||
return s;
|
||||
} // toString
|
||||
static std::string toString(const TimeType &tt);
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the number of seconds since 1.1.1970. This function is used
|
||||
* to compare access times of files, e.g. news, addons data etc.
|
||||
|
@ -298,6 +298,7 @@ Translations::Translations() //: m_dictionary_manager("UTF-16")
|
||||
}
|
||||
|
||||
m_current_language_name = l.get_name();
|
||||
m_current_language_name_code = l.get_language();
|
||||
|
||||
if (!l)
|
||||
{
|
||||
@ -312,11 +313,13 @@ Translations::Translations() //: m_dictionary_manager("UTF-16")
|
||||
Log::warn("Translation", "Unsupported langage '%s'", language.c_str());
|
||||
UserConfigParams::m_language = "system";
|
||||
m_current_language_name = "Default language";
|
||||
m_current_language_name_code = "en";
|
||||
m_dictionary = m_dictionary_manager.get_dictionary();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_current_language_name = tgtLang.get_name();
|
||||
m_current_language_name_code = tgtLang.get_language();
|
||||
Log::verbose("translation", "Language '%s'.", m_current_language_name.c_str());
|
||||
m_dictionary = m_dictionary_manager.get_dictionary(tgtLang);
|
||||
}
|
||||
@ -325,6 +328,7 @@ Translations::Translations() //: m_dictionary_manager("UTF-16")
|
||||
else
|
||||
{
|
||||
m_current_language_name = "Default language";
|
||||
m_current_language_name_code = "en";
|
||||
m_dictionary = m_dictionary_manager.get_dictionary();
|
||||
}
|
||||
|
||||
@ -538,12 +542,22 @@ bool Translations::isRTLLanguage() const
|
||||
return m_rtl;
|
||||
}
|
||||
|
||||
std::set<wchar_t> Translations::getCurrentAllChar()
|
||||
{
|
||||
return m_dictionary.get_all_used_chars();
|
||||
}
|
||||
|
||||
std::string Translations::getCurrentLanguageName()
|
||||
{
|
||||
return m_current_language_name;
|
||||
//return m_dictionary_manager.get_language().get_name();
|
||||
}
|
||||
|
||||
std::string Translations::getCurrentLanguageNameCode()
|
||||
{
|
||||
return m_current_language_name_code;
|
||||
}
|
||||
|
||||
core::stringw Translations::fribidizeLine(const core::stringw &str)
|
||||
{
|
||||
#if ENABLE_BIDI
|
||||
|
@ -54,6 +54,7 @@ private:
|
||||
bool m_rtl;
|
||||
|
||||
std::string m_current_language_name;
|
||||
std::string m_current_language_name_code;
|
||||
|
||||
public:
|
||||
Translations();
|
||||
@ -74,8 +75,12 @@ public:
|
||||
|
||||
const std::vector<std::string>* getLanguageList() const;
|
||||
|
||||
std::set<wchar_t> getCurrentAllChar();
|
||||
|
||||
std::string getCurrentLanguageName();
|
||||
|
||||
std::string getCurrentLanguageNameCode();
|
||||
|
||||
private:
|
||||
irr::core::stringw fribidizeLine(const irr::core::stringw &str);
|
||||
}; // Translations
|
||||
|
@ -1,861 +0,0 @@
|
||||
#include "CFontTool.h"
|
||||
#include "IXMLWriter.h"
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
using namespace irr;
|
||||
|
||||
const int fontsizes[] = {4,6,8,9,10,11,12,14,16,18,20,22,24,26,28,36,48,56,68,72,0};
|
||||
|
||||
char bUsed[0x10000]={0};
|
||||
|
||||
/** True if pot files where given, which indicates that Asian fonts
|
||||
* are to be created, and an offset needs to be used for the index. */
|
||||
bool has_pot_files = false;
|
||||
|
||||
inline u32 getTextureSizeFromSurfaceSize(u32 size)
|
||||
{
|
||||
u32 ts = 0x01;
|
||||
while(ts < size)
|
||||
ts <<= 1;
|
||||
|
||||
return ts;
|
||||
}
|
||||
|
||||
bool LoadPoFiles(const char* sListFileName){
|
||||
has_pot_files = true;
|
||||
char s[1024];
|
||||
std::ifstream fin(sListFileName);
|
||||
if(!fin){
|
||||
std::cout<<"Error: Can't open "<<sListFileName<<std::endl;
|
||||
return false;
|
||||
}
|
||||
std::cout<<"Opened list file "<<sListFileName<<std::endl;
|
||||
for(;;){
|
||||
fin.getline(s,1024);
|
||||
if(fin.eof()) break;
|
||||
std::ifstream fin2(s);
|
||||
if(!fin2){
|
||||
std::cout<<"Error: Can't open "<<s<<std::endl;
|
||||
}else{
|
||||
std::cout<<"Opened "<<s<<std::endl;
|
||||
//buggy code that convert UTF-8 to UCS-2
|
||||
for(;;){
|
||||
unsigned char c1=(unsigned char)fin2.get();
|
||||
unsigned short out=0;
|
||||
if(fin2.eof()) break;
|
||||
if(c1>=0xF0) continue;
|
||||
else if(c1>=0xE0){
|
||||
out=((c1&0xF)<<12)
|
||||
|((((unsigned char)fin2.get())&0x3F)<<6)
|
||||
|(((unsigned char)fin2.get())&0x3F);
|
||||
}else if(c1>=0xC0){
|
||||
out=((c1&0x1F)<<6)
|
||||
|(((unsigned char)fin2.get())&0x3F);
|
||||
}else{
|
||||
out=c1;
|
||||
}
|
||||
bUsed[out]=1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Set all characters in the given character string to be used. */
|
||||
bool setUsedCharacters(const char* characters)
|
||||
{
|
||||
int n = strlen(characters);
|
||||
for(int i=0; i<n; i++)
|
||||
bUsed[short(characters[i])] = true;
|
||||
return true;
|
||||
} // setUsedCharacters
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// windows specific
|
||||
#ifdef _IRR_WINDOWS_
|
||||
|
||||
const DWORD charsets[] = { ANSI_CHARSET, DEFAULT_CHARSET, OEM_CHARSET, BALTIC_CHARSET, GB2312_CHARSET, CHINESEBIG5_CHARSET,
|
||||
EASTEUROPE_CHARSET, GREEK_CHARSET, HANGUL_CHARSET, MAC_CHARSET, RUSSIAN_CHARSET,
|
||||
SHIFTJIS_CHARSET, SYMBOL_CHARSET, TURKISH_CHARSET, VIETNAMESE_CHARSET, JOHAB_CHARSET,
|
||||
ARABIC_CHARSET, HEBREW_CHARSET, THAI_CHARSET, 0};
|
||||
|
||||
const wchar_t *setnames[] = {L"ANSI", L"All Available", L"OEM", L"Baltic", L"Chinese Simplified", L"Chinese Traditional",
|
||||
L"Eastern European", L"Greek", L"Hangul", L"Macintosh", L"Russian",
|
||||
L"Japanese", L"Symbol", L"Turkish", L"Vietnamese", L"Johab",
|
||||
L"Arabic", L"Hebrew", L"Thai", 0};
|
||||
|
||||
// callback for adding font names
|
||||
int CALLBACK EnumFontFamExProc( ENUMLOGFONTEX *lpelfe, NEWTEXTMETRICEX *lpntme,
|
||||
DWORD FontType, LPARAM lParam)
|
||||
{
|
||||
CFontTool* t = (CFontTool*) lParam;
|
||||
t->FontNames.push_back( core::stringw(lpelfe->elfFullName));
|
||||
return 1;
|
||||
}
|
||||
|
||||
//
|
||||
// Constructor
|
||||
//
|
||||
|
||||
CFontTool::CFontTool(IrrlichtDevice* device) : FontSizes(fontsizes),
|
||||
Device(device), UseAlphaChannel(false),
|
||||
// win specific
|
||||
dc(0)
|
||||
{
|
||||
// init display context
|
||||
dc = CreateDC(L"DISPLAY", L"DISPLAY", 0 ,0 );
|
||||
|
||||
// populate list of available character set names
|
||||
for (int i=0; setnames[i] != 0; ++i)
|
||||
CharSets.push_back( core::stringw(setnames[i]));
|
||||
|
||||
selectCharSet(0);
|
||||
}
|
||||
|
||||
void CFontTool::selectCharSet(u32 currentCharSet)
|
||||
{
|
||||
if ( currentCharSet >= CharSets.size() )
|
||||
return;
|
||||
|
||||
LOGFONTW lf;
|
||||
lf.lfFaceName[0] = L'\0';
|
||||
lf.lfCharSet = (BYTE) charsets[currentCharSet];
|
||||
// HRESULT hr; // no error checking(!)
|
||||
|
||||
// clear font list
|
||||
FontNames.clear();
|
||||
|
||||
// create list of available fonts
|
||||
EnumFontFamiliesExW( dc, (LPLOGFONTW) &lf, (FONTENUMPROCW) EnumFontFamExProc, (LPARAM) this, 0);
|
||||
}
|
||||
|
||||
bool CFontTool::makeBitmapFont(u32 fontIndex, u32 charsetIndex, s32 fontSize, u32 textureWidth, u32 textureHeight, bool bold, bool italic, bool aa, bool alpha,bool usedOnly,bool excludeLatin)
|
||||
{
|
||||
if (fontIndex >= FontNames.size() || charsetIndex >= CharSets.size() )
|
||||
return false;
|
||||
|
||||
UseAlphaChannel = alpha;
|
||||
u32 currentImage = 0;
|
||||
|
||||
// create the font
|
||||
HFONT font = CreateFontW(
|
||||
-MulDiv(fontSize, GetDeviceCaps(dc, LOGPIXELSY), 72), 0,
|
||||
0,0,
|
||||
bold ? FW_BOLD : 0,
|
||||
italic, 0,0, charsets[charsetIndex], 0,0,
|
||||
aa ? ANTIALIASED_QUALITY : 0,
|
||||
0, FontNames[fontIndex].c_str() );
|
||||
|
||||
if (!font)
|
||||
return false;
|
||||
|
||||
SelectObject(dc, font);
|
||||
SetTextAlign (dc,TA_LEFT | TA_TOP | TA_NOUPDATECP);
|
||||
|
||||
// get rid of the current textures/images
|
||||
for (u32 i=0; i<currentTextures.size(); ++i)
|
||||
currentTextures[i]->drop();
|
||||
currentTextures.clear();
|
||||
|
||||
for (u32 i=0; i<currentImages.size(); ++i)
|
||||
currentImages[i]->drop();
|
||||
currentImages.clear();
|
||||
|
||||
// clear current image mappings
|
||||
CharMap.clear();
|
||||
// clear array
|
||||
Areas.clear();
|
||||
|
||||
// get information about this font's unicode ranges.
|
||||
s32 size = GetFontUnicodeRanges( dc, 0);
|
||||
c8 *buf = new c8[size];
|
||||
LPGLYPHSET glyphs = (LPGLYPHSET)buf;
|
||||
|
||||
GetFontUnicodeRanges( dc, glyphs);
|
||||
|
||||
// s32 TotalCharCount = glyphs->cGlyphsSupported;
|
||||
|
||||
s32 currentx=0, currenty=0, maxy=0;
|
||||
|
||||
for (u32 range=0; range < glyphs->cRanges; range++)
|
||||
{
|
||||
WCRANGE* current = &glyphs->ranges[range];
|
||||
|
||||
//maxy=0;
|
||||
|
||||
// loop through each glyph and write its size and position
|
||||
for (s32 ch=current->wcLow; ch< current->wcLow + current->cGlyphs; ch++)
|
||||
{
|
||||
wchar_t currentchar = ch;
|
||||
|
||||
/* if ( IsDBCSLeadByte((BYTE) ch))
|
||||
continue; // surragate pairs unsupported */
|
||||
if(excludeLatin && ch>=0 && ch<0x100) continue;
|
||||
if(usedOnly && !bUsed[(unsigned short)ch]) continue;
|
||||
|
||||
// get the dimensions
|
||||
SIZE size;
|
||||
ABC abc;
|
||||
GetTextExtentPoint32W(dc, ¤tchar, 1, &size);
|
||||
SFontArea fa;
|
||||
fa.underhang = 0;
|
||||
fa.overhang = 0;
|
||||
|
||||
if (GetCharABCWidthsW(dc, currentchar, currentchar, &abc)) // for unicode fonts, get overhang, underhang, width
|
||||
{
|
||||
size.cx = abc.abcB;
|
||||
fa.underhang = abc.abcA;
|
||||
fa.overhang = abc.abcC;
|
||||
}
|
||||
if (size.cy < 1)
|
||||
continue;
|
||||
|
||||
//GetGlyphOutline(dc, currentchar, GGO_METRICS, &gm, 0, 0, 0);
|
||||
|
||||
//size.cx++; size.cy++;
|
||||
|
||||
// wrap around?
|
||||
if (currentx + size.cx > (s32) textureWidth)
|
||||
{
|
||||
currenty += maxy;
|
||||
currentx = 0;
|
||||
if ((u32)(currenty + maxy) > textureHeight)
|
||||
{
|
||||
currentImage++; // increase Image count
|
||||
currenty=0;
|
||||
}
|
||||
maxy = 0;
|
||||
}
|
||||
// add this char dimension to the current map
|
||||
|
||||
fa.rectangle = core::rect<s32>(currentx, currenty, currentx + size.cx, currenty + size.cy);
|
||||
fa.sourceimage = currentImage;
|
||||
|
||||
CharMap.insert(currentchar, Areas.size());
|
||||
Areas.push_back( fa );
|
||||
|
||||
currentx += size.cx +1;
|
||||
|
||||
if (size.cy+1 > maxy)
|
||||
maxy = size.cy+1;
|
||||
}
|
||||
}
|
||||
currenty += maxy;
|
||||
|
||||
u32 lastTextureHeight = getTextureSizeFromSurfaceSize(currenty);
|
||||
|
||||
// delete the glyph set
|
||||
delete [] buf;
|
||||
|
||||
currentImages.set_used(currentImage+1);
|
||||
currentTextures.set_used(currentImage+1);
|
||||
|
||||
for (currentImage=0; currentImage < currentImages.size(); ++currentImage)
|
||||
{
|
||||
core::stringc logmsg = "Creating image ";
|
||||
logmsg += (s32) (currentImage+1);
|
||||
logmsg += " of ";
|
||||
logmsg += (s32) currentImages.size();
|
||||
Device->getLogger()->log(logmsg.c_str());
|
||||
// no need for a huge final texture
|
||||
u32 texHeight = textureHeight;
|
||||
if (currentImage == currentImages.size()-1 )
|
||||
texHeight = lastTextureHeight;
|
||||
|
||||
// make a new bitmap
|
||||
HBITMAP bmp = CreateCompatibleBitmap(dc, textureWidth, texHeight);
|
||||
HDC bmpdc = CreateCompatibleDC(dc);
|
||||
|
||||
LOGBRUSH lbrush;
|
||||
lbrush.lbColor = RGB(0,0,0);
|
||||
lbrush.lbHatch = 0;
|
||||
lbrush.lbStyle = BS_SOLID;
|
||||
|
||||
HBRUSH brush = CreateBrushIndirect(&lbrush);
|
||||
HPEN pen = CreatePen(PS_NULL, 0, 0);
|
||||
|
||||
HGDIOBJ oldbmp = SelectObject(bmpdc, bmp);
|
||||
HGDIOBJ oldbmppen = SelectObject(bmpdc, pen);
|
||||
HGDIOBJ oldbmpbrush = SelectObject(bmpdc, brush);
|
||||
HGDIOBJ oldbmpfont = SelectObject(bmpdc, font);
|
||||
|
||||
SetTextColor(bmpdc, RGB(255,255,255));
|
||||
|
||||
Rectangle(bmpdc, 0,0,textureWidth,texHeight);
|
||||
SetBkMode(bmpdc, TRANSPARENT);
|
||||
|
||||
// draw the letters...
|
||||
|
||||
// iterate through the tree
|
||||
core::map<wchar_t, u32>::Iterator it = CharMap.getIterator();
|
||||
while (!it.atEnd())
|
||||
{
|
||||
s32 currentArea = (*it).getValue();
|
||||
wchar_t wch = (*it).getKey();
|
||||
// sloppy but I couldnt be bothered rewriting it
|
||||
if (Areas[currentArea].sourceimage == currentImage)
|
||||
{
|
||||
// draw letter
|
||||
s32 sx = Areas[currentArea].rectangle.UpperLeftCorner.X - Areas[currentArea].underhang;
|
||||
TextOutW(bmpdc, sx, Areas[currentArea].rectangle.UpperLeftCorner.Y, &wch, 1);
|
||||
|
||||
// if ascii font...
|
||||
//SetPixel(bmpdc, Areas[currentArea].rectangle.UpperLeftCorner.X, Areas[currentArea].rectangle.UpperLeftCorner.Y, RGB(255,255,0));// left upper corner mark
|
||||
}
|
||||
it++;
|
||||
}
|
||||
|
||||
// copy the font bitmap into a new irrlicht image
|
||||
BITMAP b;
|
||||
PBITMAPINFO pbmi;
|
||||
WORD cClrBits;
|
||||
u32 cformat;
|
||||
|
||||
// Retrieve the bitmap color format, width, and height.
|
||||
GetObject(bmp, sizeof(BITMAP), (LPSTR)&b);
|
||||
|
||||
// Convert the color format to a count of bits.
|
||||
cClrBits = (WORD)(b.bmPlanes * b.bmBitsPixel);
|
||||
|
||||
if (cClrBits <= 8) // we're not supporting these
|
||||
cformat = -1;
|
||||
else if (cClrBits <= 16)
|
||||
cformat = video::ECF_A1R5G5B5;
|
||||
else if (cClrBits <= 24)
|
||||
cformat = video::ECF_R8G8B8;
|
||||
else
|
||||
cformat = video::ECF_A8R8G8B8;
|
||||
|
||||
pbmi = (PBITMAPINFO) LocalAlloc(LPTR,
|
||||
sizeof(BITMAPINFOHEADER));
|
||||
|
||||
// Initialize the fields in the BITMAPINFO structure.
|
||||
|
||||
pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
pbmi->bmiHeader.biWidth = b.bmWidth;
|
||||
pbmi->bmiHeader.biHeight = b.bmHeight;
|
||||
pbmi->bmiHeader.biPlanes = b.bmPlanes;
|
||||
pbmi->bmiHeader.biBitCount = b.bmBitsPixel;
|
||||
|
||||
// If the bitmap is not compressed, set the BI_RGB flag.
|
||||
pbmi->bmiHeader.biCompression = BI_RGB;
|
||||
|
||||
// Compute the number of bytes in the array of color
|
||||
// indices and store the result in biSizeImage.
|
||||
// For Windows NT, the width must be DWORD aligned unless
|
||||
// the bitmap is RLE compressed. This example shows this.
|
||||
// For Windows 95/98/Me, the width must be WORD aligned unless the
|
||||
// bitmap is RLE compressed.
|
||||
pbmi->bmiHeader.biSizeImage = ((pbmi->bmiHeader.biWidth * cClrBits +31) & ~31) /8
|
||||
* pbmi->bmiHeader.biHeight;
|
||||
// Set biClrImportant to 0, indicating that all of the
|
||||
// device colors are important.
|
||||
pbmi->bmiHeader.biClrImportant = 0;
|
||||
|
||||
LPBYTE lpBits; // memory pointer
|
||||
|
||||
PBITMAPINFOHEADER pbih = (PBITMAPINFOHEADER) pbmi;
|
||||
lpBits = (LPBYTE) GlobalAlloc(GMEM_FIXED, pbih->biSizeImage);
|
||||
|
||||
GetDIBits(dc, bmp, 0, (WORD) pbih->biHeight, lpBits, pbmi, DIB_RGB_COLORS);
|
||||
|
||||
// DEBUG- copy to clipboard
|
||||
//OpenClipboard(hWnd);
|
||||
//EmptyClipboard();
|
||||
//SetClipboardData(CF_BITMAP, bmp);
|
||||
//CloseClipboard();
|
||||
|
||||
// flip bitmap
|
||||
s32 rowsize = ((pbmi->bmiHeader.biWidth * cClrBits +31) & ~31) /8;
|
||||
c8 *row = new c8[rowsize];
|
||||
for (s32 i=0; i < (pbih->biHeight/2); ++i)
|
||||
{
|
||||
// grab a row
|
||||
memcpy(row, lpBits + (rowsize * i), rowsize);
|
||||
// swap row
|
||||
memcpy(lpBits + (rowsize * i), lpBits + ((pbih->biHeight-1 -i) * rowsize ) , rowsize);
|
||||
memcpy(lpBits + ((pbih->biHeight-1 -i) * rowsize ), row , rowsize);
|
||||
}
|
||||
|
||||
bool ret = false;
|
||||
|
||||
if (cformat == video::ECF_A8R8G8B8)
|
||||
{
|
||||
// in this case the font should have an alpha channel, but since windows doesn't draw one
|
||||
// we have to set one manually by going through all the pixels.. *sigh*
|
||||
|
||||
u8* m;
|
||||
for (m = lpBits; m < lpBits + pbih->biSizeImage; m+=4)
|
||||
{
|
||||
if (UseAlphaChannel)
|
||||
{
|
||||
if (m[0] > 0) // pixel has colour
|
||||
{
|
||||
m[3]=m[0]; // set alpha
|
||||
m[0]=m[1]=m[2] = 255; // everything else is full
|
||||
}
|
||||
}
|
||||
else
|
||||
m[3]=255; // all pixels are full alpha
|
||||
}
|
||||
|
||||
}
|
||||
else if (cformat == video::ECF_A1R5G5B5)
|
||||
{
|
||||
u8* m;
|
||||
for (m = lpBits; m < lpBits + pbih->biSizeImage; m+=2)
|
||||
{
|
||||
WORD *p = (WORD*)m;
|
||||
if (m[0] > 0 || !UseAlphaChannel) // alpha should be set
|
||||
*p |= 0x8000; // set alpha bit
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cformat = -1;
|
||||
}
|
||||
|
||||
// make a texture from the image
|
||||
if (cformat != -1)
|
||||
{
|
||||
// turn mip-mapping off
|
||||
bool b = Device->getVideoDriver()->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS);
|
||||
currentImages[currentImage] = Device->getVideoDriver()->createImageFromData((video::ECOLOR_FORMAT)cformat, core::dimension2d<u32>(textureWidth,texHeight), (void*)lpBits);
|
||||
Device->getVideoDriver()->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS,b);
|
||||
}
|
||||
else
|
||||
{
|
||||
Device->getLogger()->log("Couldn't create font, your pixel format is unsupported.");
|
||||
}
|
||||
|
||||
// free memory and windows resources
|
||||
// sloppy I know, but I only intended to create one image at first.
|
||||
delete [] row;
|
||||
LocalFree(pbmi);
|
||||
GlobalFree(lpBits);
|
||||
DeleteDC(bmpdc);
|
||||
DeleteObject(brush);
|
||||
DeleteObject(pen);
|
||||
DeleteObject(bmp);
|
||||
|
||||
if (currentImages[currentImage])
|
||||
{
|
||||
// add texture
|
||||
currentTextures[currentImage] = Device->getVideoDriver()->addTexture("GUIFontImage",currentImages[currentImage]);
|
||||
currentTextures[currentImage]->grab();
|
||||
}
|
||||
else
|
||||
{
|
||||
Device->getLogger()->log("Something went wrong, aborting.");
|
||||
// drop all images
|
||||
DeleteObject(font);
|
||||
return false;
|
||||
}
|
||||
} // looping through each texture
|
||||
DeleteObject(font);
|
||||
return true;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
CFontTool::CFontTool(IrrlichtDevice *device) : FontSizes(fontsizes), Device(device), UseAlphaChannel(false)
|
||||
{
|
||||
if (!XftInitFtLibrary())
|
||||
{
|
||||
core::stringc logmsg = "XFT not found\n";
|
||||
Device->getLogger()->log(logmsg.c_str());
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Get a list of the font foundries, storing them in a set to sort */
|
||||
std::set<core::stringw> foundries;
|
||||
Display* display = (Display*)Device->getVideoDriver()->getExposedVideoData().OpenGLLinux.X11Display;
|
||||
XftFontSet* fonts = XftListFonts(display, DefaultScreen(display), 0, XFT_FOUNDRY, NULL);
|
||||
for (int i = 0; i < fonts->nfont; i++)
|
||||
{
|
||||
char *foundry;
|
||||
XftPatternGetString(fonts->fonts[i], XFT_FOUNDRY, 0, &foundry);
|
||||
core::stringw tmp(foundry);
|
||||
foundries.insert(tmp);
|
||||
}
|
||||
XftFontSetDestroy(fonts);
|
||||
|
||||
/* Copy the sorted list into the array */
|
||||
CharSets.clear();
|
||||
for (std::set<core::stringw>::iterator i = foundries.begin(); i != foundries.end(); i++)
|
||||
CharSets.push_back((*i).c_str());
|
||||
selectCharSet(0);
|
||||
}
|
||||
|
||||
/* Note: There must be some trick for using strings as pattern parameters to XftListFonts because
|
||||
no matter how I specify a string, I end up with an intermittent segfault. Since XftFontList is
|
||||
just calling FcFontList, that's what I'll do too since that works OK */
|
||||
void CFontTool::selectCharSet(u32 currentCharSet)
|
||||
{
|
||||
/* Get a list of the font families, storing them in a set to sort */
|
||||
char foundry[256];
|
||||
sprintf(&foundry[0],"%ls",CharSets[currentCharSet].c_str());
|
||||
std::set<core::stringw> families;
|
||||
XftPattern *pattern = FcPatternCreate();
|
||||
XftPatternAddString(pattern, FC_FOUNDRY, &foundry[0]);
|
||||
XftObjectSet *objectset = FcObjectSetCreate();
|
||||
XftObjectSetAdd(objectset, XFT_FOUNDRY);
|
||||
XftObjectSetAdd(objectset, XFT_FAMILY);
|
||||
FcFontSet *fonts = FcFontList(NULL, pattern, objectset);
|
||||
|
||||
for (int i = 0; i < fonts->nfont; i++)
|
||||
{
|
||||
char* ptr;
|
||||
XftPatternGetString(fonts->fonts[i], XFT_FAMILY, 0, &ptr);
|
||||
core::stringw family(ptr);
|
||||
families.insert(family);
|
||||
}
|
||||
XftPatternDestroy(pattern);
|
||||
FcObjectSetDestroy(objectset);
|
||||
|
||||
/* Copy the sorted list into the array */
|
||||
FontNames.clear();
|
||||
for (std::set<core::stringw>::iterator i = families.begin(); i != families.end(); i++)
|
||||
FontNames.push_back((*i).c_str());
|
||||
}
|
||||
|
||||
bool CFontTool::makeBitmapFont(u32 fontIndex, u32 charsetIndex, s32 fontSize, u32 textureWidth, u32 textureHeight, bool bold, bool italic, bool aa, bool alpha,bool usedOnly,bool excludeLatin)
|
||||
{
|
||||
if (fontIndex >= FontNames.size() || charsetIndex >= CharSets.size() )
|
||||
return false;
|
||||
|
||||
Display *display = (Display*) Device->getVideoDriver()->getExposedVideoData().OpenGLLinux.X11Display;
|
||||
u32 screen = DefaultScreen(display);
|
||||
Window win = RootWindow(display, screen);
|
||||
Visual *visual = DefaultVisual(display, screen);
|
||||
UseAlphaChannel = alpha;
|
||||
u32 currentImage = 0;
|
||||
|
||||
XftResult result;
|
||||
XftPattern *request = XftPatternCreate();
|
||||
char foundry[256], family[256];
|
||||
sprintf(&foundry[0],"%ls",CharSets[charsetIndex].c_str());
|
||||
sprintf(&family[0],"%ls",FontNames[fontIndex].c_str());
|
||||
XftPatternAddString(request, XFT_FOUNDRY, &foundry[0]);
|
||||
XftPatternAddString(request, XFT_FAMILY, &family[0]);
|
||||
XftPatternAddInteger(request, XFT_PIXEL_SIZE, fontSize);
|
||||
XftPatternAddInteger(request, XFT_WEIGHT, bold ? XFT_WEIGHT_BLACK : XFT_WEIGHT_LIGHT);
|
||||
XftPatternAddInteger(request, XFT_SLANT, italic ? XFT_SLANT_ITALIC : XFT_SLANT_ROMAN);
|
||||
XftPatternAddBool(request, XFT_ANTIALIAS, aa);
|
||||
|
||||
/* Find the closest font that matches the user choices and open it and check if the returned
|
||||
font has anti aliasing enabled by default, even if it wasn't requested */
|
||||
FcBool aaEnabled;
|
||||
XftPattern *found = XftFontMatch(display, DefaultScreen(display), request, &result);
|
||||
XftPatternGetBool(found, XFT_ANTIALIAS, 0, &aaEnabled);
|
||||
aa = aaEnabled;
|
||||
XftFont *font = XftFontOpenPattern(display, found);
|
||||
|
||||
// get rid of the current textures/images
|
||||
for (u32 i=0; i<currentTextures.size(); ++i)
|
||||
currentTextures[i]->drop();
|
||||
currentTextures.clear();
|
||||
for (u32 i=0; i<currentImages.size(); ++i)
|
||||
currentImages[i]->drop();
|
||||
currentImages.clear();
|
||||
CharMap.clear();
|
||||
Areas.clear();
|
||||
|
||||
/* Calculate the max height of the font. Annoyingly, it seems that the height property of the font
|
||||
is the maximum height of any single character, but a string of characters, aligned along their
|
||||
baselines, can exceed this figure. Because I don't know any better way of doing it, I'm going to
|
||||
have to use the brute force method.
|
||||
|
||||
Note: There will be a certain number of charters in a font, however they may not be grouped
|
||||
consecutively, and could in fact be spread out with many gaps */
|
||||
u32 maxY = 0;
|
||||
u32 charsFound = 0;
|
||||
for (FT_UInt charCode = 0; charsFound < FcCharSetCount(font->charset); charCode++)
|
||||
{
|
||||
if (!XftCharExists(display, font, charCode))
|
||||
continue;
|
||||
|
||||
charsFound++;
|
||||
|
||||
XGlyphInfo extents;
|
||||
XftTextExtents32(display, font, &charCode, 1, &extents);
|
||||
if ((extents.xOff <= 0) && (extents.height <= 0))
|
||||
continue;
|
||||
|
||||
/* Calculate the width and height, adding 1 extra pixel if anti aliasing is enabled */
|
||||
u32 chWidth = extents.xOff + (aa ? 1 : 0);
|
||||
u32 chHeight = (font->ascent - extents.y + extents.height) + (aa ? 1 : 0);
|
||||
if (chHeight > maxY)
|
||||
maxY = chHeight;
|
||||
|
||||
/* Store the character details here */
|
||||
SFontArea fontArea;
|
||||
fontArea.rectangle = core::rect<s32>(0, 0, chWidth, chHeight);
|
||||
CharMap.insert(charCode, Areas.size());
|
||||
Areas.push_back(fontArea);
|
||||
}
|
||||
core::stringc logmsg = "Found ";
|
||||
logmsg += (s32) (CharMap.size() + 1);
|
||||
logmsg += " characters";
|
||||
Device->getLogger()->log(logmsg.c_str());
|
||||
|
||||
/* Get the size of the chars and allocate them a position on a texture. If the next character that
|
||||
is added would be outside the width or height of the texture, then a new texture is added */
|
||||
u32 currentX = 0, currentY = 0, rowY = 0;
|
||||
for (core::map<wchar_t, u32>::Iterator it = CharMap.getIterator(); !it.atEnd(); it++)
|
||||
{
|
||||
s32 currentArea = (*it).getValue();
|
||||
SFontArea *fontArea = &Areas[currentArea];
|
||||
u32 chWidth = fontArea->rectangle.LowerRightCorner.X;
|
||||
u32 chHeight = fontArea->rectangle.LowerRightCorner.Y;
|
||||
|
||||
/* If the width of this char will exceed the textureWidth then start a new row */
|
||||
if ((currentX + chWidth) > textureWidth)
|
||||
{
|
||||
currentY += rowY;
|
||||
currentX = 0;
|
||||
|
||||
/* If the new row added to the texture exceeds the textureHeight then start a new texture */
|
||||
if ((currentY + rowY) > textureHeight)
|
||||
{
|
||||
currentImage++;
|
||||
currentY = 0;
|
||||
}
|
||||
rowY = 0;
|
||||
}
|
||||
|
||||
/* Update the area with the current x and y and texture */
|
||||
fontArea->rectangle = core::rect<s32>(currentX, currentY, currentX + chWidth, currentY + chHeight);
|
||||
fontArea->sourceimage = currentImage;
|
||||
currentX += chWidth + 1;
|
||||
if (chHeight + 1 > rowY)
|
||||
rowY = chHeight + 1;
|
||||
}
|
||||
|
||||
/* The last row of chars and the last texture weren't accounted for in the loop, so add them here */
|
||||
currentY += rowY;
|
||||
u32 lastTextureHeight = getTextureSizeFromSurfaceSize(currentY);
|
||||
currentImages.set_used(currentImage + 1);
|
||||
currentTextures.set_used(currentImage + 1);
|
||||
|
||||
/* Initialise colours */
|
||||
XftColor colFore, colBack;
|
||||
XRenderColor xFore = {0xffff, 0xffff, 0xffff, 0xffff};
|
||||
XRenderColor xBack = {0x0000, 0x0000, 0x0000, 0xffff};
|
||||
XftColorAllocValue(display, DefaultVisual(display, screen), DefaultColormap(display, screen), &xFore, &colFore);
|
||||
XftColorAllocValue(display, DefaultVisual(display, screen), DefaultColormap(display, screen), &xBack, &colBack);
|
||||
|
||||
/* Create a pixmap that is large enough to hold any character in the font */
|
||||
Pixmap pixmap = XCreatePixmap(display, win, textureWidth, maxY, DefaultDepth(display, screen));
|
||||
XftDraw *draw = XftDrawCreate(display, pixmap, visual, DefaultColormap(display, screen));
|
||||
|
||||
/* Render the chars */
|
||||
for (currentImage = 0; currentImage < currentImages.size(); ++currentImage)
|
||||
{
|
||||
core::stringc logmsg = "Creating image ";
|
||||
logmsg += (s32) (currentImage+1);
|
||||
logmsg += " of ";
|
||||
logmsg += (s32) currentImages.size();
|
||||
Device->getLogger()->log(logmsg.c_str());
|
||||
|
||||
/* The last texture that is saved is vertically shrunk to fit the characters drawn on it */
|
||||
u32 texHeight = textureHeight;
|
||||
if (currentImage == currentImages.size() - 1)
|
||||
texHeight = lastTextureHeight;
|
||||
|
||||
/* The texture that holds this "page" of characters */
|
||||
currentImages[currentImage] = Device->getVideoDriver()->createImage(video::ECF_A8R8G8B8, core::dimension2du(textureWidth, texHeight));
|
||||
currentImages[currentImage]->fill(video::SColor(alpha ? 0 : 255,0,0,0));
|
||||
|
||||
for (core::map<wchar_t, u32>::Iterator it = CharMap.getIterator(); !it.atEnd(); it++)
|
||||
{
|
||||
FcChar32 wch = (*it).getKey();
|
||||
s32 currentArea = (*it).getValue();
|
||||
if (Areas[currentArea].sourceimage == currentImage)
|
||||
{
|
||||
SFontArea *fontArea = &Areas[currentArea];
|
||||
u32 chWidth = fontArea->rectangle.LowerRightCorner.X - fontArea->rectangle.UpperLeftCorner.X;
|
||||
u32 chHeight = fontArea->rectangle.LowerRightCorner.Y - fontArea->rectangle.UpperLeftCorner.Y;
|
||||
|
||||
/* Draw the glyph onto the pixmap */
|
||||
XGlyphInfo extents;
|
||||
XftDrawRect(draw, &colBack, 0, 0, chWidth, chHeight);
|
||||
XftTextExtents32(display, font, &wch, 1, &extents);
|
||||
XftDrawString32(draw, &colFore, font, extents.x, extents.y, &wch, 1);
|
||||
|
||||
/* Convert the pixmap into an image, then copy it onto the Irrlicht texture, pixel by pixel.
|
||||
There's bound to be a faster way, but this is adequate */
|
||||
u32 xDest = fontArea->rectangle.UpperLeftCorner.X;
|
||||
u32 yDest = fontArea->rectangle.UpperLeftCorner.Y + font->ascent - extents.y;
|
||||
XImage *image = XGetImage(display, pixmap, 0, 0, chWidth, chHeight, 0xffffff, XYPixmap);
|
||||
if (image)
|
||||
{
|
||||
for (u32 ySrc = 0; ySrc < chHeight; ySrc++)
|
||||
for (u32 xSrc = 0; xSrc < chWidth; xSrc++)
|
||||
{
|
||||
/* Get the pixel colour and break it down into rgb components */
|
||||
u32 col = XGetPixel(image, xSrc, ySrc);
|
||||
u32 a = 255;
|
||||
u32 r = col & visual->red_mask;
|
||||
u32 g = col & visual->green_mask;
|
||||
u32 b = col & visual->blue_mask;
|
||||
while (r > 0xff) r >>= 8;
|
||||
while (g > 0xff) g >>= 8;
|
||||
while (b > 0xff) b >>= 8;
|
||||
|
||||
/* To make the background transparent, set the colour to 100% white and the alpha to
|
||||
the average of the three rgb colour components to maintain the anti-aliasing */
|
||||
if (alpha)
|
||||
{
|
||||
a = (r + g + b) / 3;
|
||||
r = 255;
|
||||
g = 255;
|
||||
b = 255;
|
||||
}
|
||||
currentImages[currentImage]->setPixel(xDest + xSrc,yDest + ySrc,video::SColor(a,r,g,b));
|
||||
}
|
||||
image->f.destroy_image(image);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Add the texture to the list */
|
||||
currentTextures[currentImage] = Device->getVideoDriver()->addTexture("GUIFontImage",currentImages[currentImage]);
|
||||
currentTextures[currentImage]->grab();
|
||||
}
|
||||
|
||||
XftColorFree (display, visual, DefaultColormap(display, screen), &colFore);
|
||||
XftColorFree (display, visual, DefaultColormap(display, screen), &colBack);
|
||||
XftFontClose(display,font);
|
||||
XftPatternDestroy(request);
|
||||
XftDrawDestroy(draw);
|
||||
XFreePixmap(display, pixmap);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
CFontTool::~CFontTool()
|
||||
{
|
||||
#ifdef _IRR_WINDOWS_
|
||||
// destroy display context
|
||||
if (dc)
|
||||
DeleteDC(dc);
|
||||
#endif
|
||||
|
||||
// drop textures+images
|
||||
for (u32 i=0; i<currentTextures.size(); ++i)
|
||||
currentTextures[i]->drop();
|
||||
currentTextures.clear();
|
||||
|
||||
for (u32 i=0; i<currentImages.size(); ++i)
|
||||
currentImages[i]->drop();
|
||||
currentImages.clear();
|
||||
}
|
||||
|
||||
bool CFontTool::saveBitmapFont(const c8 *filename, const c8* format)
|
||||
{
|
||||
if (currentImages.size() == 0)
|
||||
{
|
||||
Device->getLogger()->log("No image data to write, aborting.");
|
||||
return false;
|
||||
}
|
||||
|
||||
core::stringc fn = filename;
|
||||
core::stringc imagename = filename;
|
||||
fn += ".xml";
|
||||
|
||||
io::IXMLWriter *writer = Device->getFileSystem()->createXMLWriter(fn.c_str());
|
||||
|
||||
// header and line breaks
|
||||
writer->writeXMLHeader();
|
||||
writer->writeLineBreak();
|
||||
|
||||
// write information
|
||||
writer->writeElement(L"font", false, L"type", L"bitmap");
|
||||
writer->writeLineBreak();
|
||||
writer->writeLineBreak();
|
||||
|
||||
// write images and link to them
|
||||
// Only use the offset if Asian fonts are created.
|
||||
u32 offset_for_asian_fonts=has_pot_files ? 100 : 0;
|
||||
for (u32 i=0; i<currentImages.size(); ++i)
|
||||
{
|
||||
imagename = filename;
|
||||
imagename += (s32)i;
|
||||
imagename += ".";
|
||||
imagename += format;
|
||||
Device->getVideoDriver()->writeImageToFile(currentImages[i],imagename.c_str());
|
||||
|
||||
writer->writeElement(L"Texture", true,
|
||||
L"index", core::stringw(i+offset_for_asian_fonts).c_str(),
|
||||
L"filename", core::stringw(imagename.c_str()).c_str(),
|
||||
L"hasAlpha", UseAlphaChannel ? L"true" : L"false");
|
||||
writer->writeLineBreak();
|
||||
}
|
||||
|
||||
writer->writeLineBreak();
|
||||
|
||||
// write each character
|
||||
core::map<wchar_t, u32>::Iterator it = CharMap.getIterator();
|
||||
while (!it.atEnd())
|
||||
{
|
||||
SFontArea &fa = Areas[(*it).getValue()];
|
||||
|
||||
wchar_t c[2];
|
||||
c[0] = (*it).getKey();
|
||||
c[1] = L'\0';
|
||||
core::stringw area, under, over, image;
|
||||
area = core::stringw(fa.rectangle.UpperLeftCorner.X);
|
||||
area += L", ";
|
||||
area += fa.rectangle.UpperLeftCorner.Y;
|
||||
area += L", ";
|
||||
area += fa.rectangle.LowerRightCorner.X;
|
||||
area += L", ";
|
||||
area += fa.rectangle.LowerRightCorner.Y;
|
||||
|
||||
core::array<core::stringw> names;
|
||||
core::array<core::stringw> values;
|
||||
names.clear();
|
||||
values.clear();
|
||||
// char
|
||||
names.push_back(core::stringw(L"c"));
|
||||
values.push_back(core::stringw(c));
|
||||
// image number
|
||||
if (fa.sourceimage+offset_for_asian_fonts != 0)
|
||||
{
|
||||
image = core::stringw(fa.sourceimage+offset_for_asian_fonts);
|
||||
names.push_back(core::stringw(L"i"));
|
||||
values.push_back(image);
|
||||
}
|
||||
// rectangle
|
||||
names.push_back(core::stringw(L"r"));
|
||||
values.push_back(area);
|
||||
|
||||
if (fa.underhang != 0)
|
||||
{
|
||||
under = core::stringw(fa.underhang);
|
||||
names.push_back(core::stringw(L"u"));
|
||||
values.push_back(under);
|
||||
}
|
||||
if (fa.overhang != 0)
|
||||
{
|
||||
over = core::stringw(fa.overhang);
|
||||
names.push_back(core::stringw(L"o"));
|
||||
values.push_back(over);
|
||||
}
|
||||
writer->writeElement(L"c", true, names, values);
|
||||
|
||||
writer->writeLineBreak();
|
||||
it++;
|
||||
}
|
||||
|
||||
writer->writeClosingTag(L"font");
|
||||
|
||||
writer->drop();
|
||||
|
||||
Device->getLogger()->log("Bitmap font saved.");
|
||||
|
||||
return true;
|
||||
}
|
@ -1,79 +0,0 @@
|
||||
#ifndef __IRR_FONT_TOOL_INCLUDED__
|
||||
#define __IRR_FONT_TOOL_INCLUDED__
|
||||
|
||||
|
||||
#include "irrlicht.h"
|
||||
|
||||
#if defined(_IRR_WINDOWS_)
|
||||
#ifdef _MBCS
|
||||
#undef _MBCS
|
||||
#endif
|
||||
|
||||
#define UNICODE
|
||||
#define _WIN32_WINNT 0x0500
|
||||
#include "windows.h"
|
||||
#else
|
||||
#ifdef _IRR_COMPILE_WITH_X11_
|
||||
#include <X11/Xlib.h>
|
||||
#endif
|
||||
#include <X11/Xft/Xft.h>
|
||||
#include <set>
|
||||
#endif
|
||||
|
||||
bool LoadPoFiles(const char* sListFileName);
|
||||
bool setUsedCharacters(const char* characters);
|
||||
|
||||
namespace irr {
|
||||
class CFontTool : public irr::IReferenceCounted
|
||||
{
|
||||
public:
|
||||
CFontTool(irr::IrrlichtDevice* device);
|
||||
~CFontTool();
|
||||
|
||||
virtual bool makeBitmapFont(u32 fontIndex, u32 charsetIndex,
|
||||
s32 fontSize, u32 texturewidth, u32 textureHeight,
|
||||
bool bold, bool italic, bool aa, bool alpha,
|
||||
bool usedOnly=false,bool exclideLatin=false);
|
||||
|
||||
virtual bool saveBitmapFont(const c8* filename, const c8* format);
|
||||
|
||||
virtual void selectCharSet(u32 currentCharSet);
|
||||
|
||||
struct SFontArea
|
||||
{
|
||||
SFontArea() : rectangle(), underhang(0), overhang(0), sourceimage(0) {}
|
||||
core::rect<s32> rectangle;
|
||||
s32 underhang;
|
||||
s32 overhang;
|
||||
u32 sourceimage;
|
||||
};
|
||||
|
||||
/* struct SFontMap
|
||||
{
|
||||
SFontMap() : areas(), start(0), count(0) {}
|
||||
core::array< SFontArea > areas;
|
||||
s32 start;
|
||||
s32 count;
|
||||
};*/
|
||||
|
||||
core::array<core::stringw> FontNames;
|
||||
core::array<core::stringw> CharSets;
|
||||
//core::array<SFontMap> Mappings;
|
||||
core::array<SFontArea> Areas;
|
||||
core::map<wchar_t, u32> CharMap;
|
||||
|
||||
core::array<video::ITexture*> currentTextures;
|
||||
core::array<video::IImage*> currentImages;
|
||||
const int *FontSizes;
|
||||
IrrlichtDevice *Device;
|
||||
|
||||
bool UseAlphaChannel;
|
||||
|
||||
// windows
|
||||
#ifdef _IRR_WINDOWS_
|
||||
HDC dc;
|
||||
#endif
|
||||
|
||||
};
|
||||
}
|
||||
#endif // __IRR_FONT_TOOL_INCLUDED__
|
@ -1,39 +0,0 @@
|
||||
option(FONT_TOOL "Compile font tool (only useful for developers)" OFF)
|
||||
mark_as_advanced(FONT_TOOL)
|
||||
|
||||
if(FONT_TOOL)
|
||||
if(MSVC)
|
||||
add_executable(font_tool CFontTool.cpp main.cpp)
|
||||
target_link_libraries(font_tool stkirrlicht)
|
||||
else()
|
||||
find_package(Freetype)
|
||||
find_library(FONTCONFIG_LIBRARY fontconfig)
|
||||
if(UNIX AND NOT APPLE)
|
||||
find_package(Xrandr REQUIRED)
|
||||
find_package(X11 REQUIRED)
|
||||
include_directories(${X11_INCLUDE_DIR})
|
||||
if(NOT XRANDR_FOUND)
|
||||
message(STATUS "XRANDR not found.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(FREETYPE_FOUND)
|
||||
include_directories(${FREETYPE_INCLUDE_DIRS})
|
||||
add_executable(font_tool CFontTool.cpp main.cpp)
|
||||
|
||||
target_link_libraries(font_tool stkirrlicht)
|
||||
target_link_libraries(font_tool ${FREETYPE_LIBRARIES})
|
||||
target_link_libraries(font_tool ${OPENGL_LIBRARIES})
|
||||
target_link_libraries(font_tool ${FONTCONFIG_LIBRARY})
|
||||
if(UNIX AND NOT APPLE)
|
||||
target_link_libraries(font_tool ${XRANDR_LIBRARIES})
|
||||
target_link_libraries(font_tool ${X11_Xft_LIB} Xxf86vm)
|
||||
target_link_libraries(font_tool ${X11_LIBRARIES})
|
||||
endif()
|
||||
else()
|
||||
message(STATUS "Freetype was not found, the font tool won't be built (only useful for developers)")
|
||||
endif()
|
||||
endif()
|
||||
else()
|
||||
message(STATUS "Font tool deactivated, the font tool won't be built (only useful for developers)")
|
||||
endif()
|
@ -1,20 +0,0 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 10.00
|
||||
# Visual C++ Express 2008
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Font Tool", "irrFontTool_v9.vcproj", "{4D53E40F-37E3-42B1-8848-F4C6F8313A17}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Release|Win32 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{4D53E40F-37E3-42B1-8848-F4C6F8313A17}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{4D53E40F-37E3-42B1-8848-F4C6F8313A17}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{4D53E40F-37E3-42B1-8848-F4C6F8313A17}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{4D53E40F-37E3-42B1-8848-F4C6F8313A17}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
@ -1,204 +0,0 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="9.00"
|
||||
Name="Font Tool"
|
||||
ProjectGUID="{4D53E40F-37E3-42B1-8848-F4C6F8313A17}"
|
||||
Keyword="Win32Proj"
|
||||
TargetFrameworkVersion="131072"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="Debug"
|
||||
IntermediateDirectory="Debug"
|
||||
ConfigurationType="1"
|
||||
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
|
||||
CharacterSet="2"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="../../lib/irrlicht/include"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_IRR_STATIC_LIB_"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="4"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalOptions=" kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib glu32.lib opengl32.lib gdi32.lib"
|
||||
AdditionalDependencies="Irrlicht.lib"
|
||||
OutputFile="../../font_tool.exe"
|
||||
LinkIncremental="2"
|
||||
AdditionalLibraryDirectories="../../lib/irrlicht/lib/Win32-visualstudio"
|
||||
GenerateDebugInformation="true"
|
||||
ProgramDatabaseFile="$(OutDir)/TestProject.pdb"
|
||||
SubSystem="1"
|
||||
RandomizedBaseAddress="1"
|
||||
DataExecutionPrevention="0"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="Release"
|
||||
IntermediateDirectory="Release"
|
||||
ConfigurationType="1"
|
||||
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
|
||||
CharacterSet="2"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
WholeProgramOptimization="false"
|
||||
AdditionalIncludeDirectories="../../lib/irrlicht/include"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_IRR_STATIC_LIB_"
|
||||
MinimalRebuild="true"
|
||||
RuntimeLibrary="0"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalOptions=" kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib glu32.lib opengl32.lib gdi32.lib"
|
||||
AdditionalDependencies="Irrlicht.lib"
|
||||
OutputFile="../../FontTool.exe"
|
||||
LinkIncremental="0"
|
||||
AdditionalLibraryDirectories="../../lib/irrlicht/lib/Win32-visualstudio"
|
||||
GenerateDebugInformation="false"
|
||||
SubSystem="1"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
LinkTimeCodeGeneration="0"
|
||||
RandomizedBaseAddress="1"
|
||||
DataExecutionPrevention="0"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<File
|
||||
RelativePath=".\CFontTool.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\CFontTool.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\CVectorFontTool.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\main.cpp"
|
||||
>
|
||||
</File>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
@ -1,592 +0,0 @@
|
||||
/*
|
||||
Tool for creating Irrlicht bitmap+vector fonts,
|
||||
started by Gaz Davidson in December 2006
|
||||
|
||||
Due to my laziness and Microsoft's unituitive API, surragate pairs and
|
||||
nonspacing diacritical marks are not supported!
|
||||
|
||||
Linux bitmap font support added by Neil Burlock Oct 2008
|
||||
Note: Xft/Freetype2 is used to render the fonts under X11. Anti-aliasing
|
||||
is controlled by the system and cannot be overriden by an application,
|
||||
so fonts that are rendered will be aliased or anti-aliased depending
|
||||
on the system that they are created on.
|
||||
|
||||
acme_pjz modified the original irrlicht font tool to only write the
|
||||
characters needed in a list of .po files - which saves huge amount
|
||||
of space for Asian fonts.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include <irrlicht.h>
|
||||
#include <iostream>
|
||||
|
||||
#include "CFontTool.h"
|
||||
#include "CVectorFontTool.h"
|
||||
#include "ITexture.h"
|
||||
|
||||
using namespace irr;
|
||||
using namespace gui;
|
||||
|
||||
#if DEBUG
|
||||
bool GLContextDebugBit = true;
|
||||
#else
|
||||
bool GLContextDebugBit = false;
|
||||
#endif
|
||||
|
||||
const int WIDTH = 1024;
|
||||
const int HEIGHT = 768;
|
||||
|
||||
const s32 texturesizes[] = {128, 256, 512, 1024, 2048, 4096, 0};
|
||||
|
||||
const wchar_t *fileformats[] = { L"bmp", L"ppm", 0 }; // bitmap font formats
|
||||
const wchar_t *alphafileformats[] = { L"png", L"tga", 0 }; // bitmap font formats which support alpha channels
|
||||
const wchar_t *vectorfileformats[] = { L"xml", L"bin", 0 }; // file formats for vector fonts
|
||||
|
||||
const wchar_t *warntext = L"Legal Notice\n"
|
||||
L"------------\n\n"
|
||||
L"When making bitmap and vector fonts, you should consider the potential legal "
|
||||
L"issues with redistributing the fonts with your software; this tool basically "
|
||||
L"copies font data and some authors might not like this!\n"
|
||||
L"If you purchased fonts or they came with an application or your OS, you'll have"
|
||||
L"to check the license to see what restrictions are placed on making derivative works.\n\n"
|
||||
L"PD and the OFL\n"
|
||||
L"--------------\n\n"
|
||||
L"You'll find lots of fonts on the web listed as Public Domain, you can do what you like "
|
||||
L"with these.\n"
|
||||
L"Many fonts are released under the Open Font License, which is a 'viral' open source "
|
||||
L"license like the GPL. It's worth reading the license here: http://scripts.sil.org/OFL\n"
|
||||
L"The most important restrictions are- you must include the original font's license, you "
|
||||
L"can't stop your users from using or distributing the font, the font must have a "
|
||||
L"different name the original.\n\n"
|
||||
L"Some free fonts can be found here- www.openfontlibrary.org\n"
|
||||
L"http://savannah.nongnu.org/projects/freefont/";
|
||||
|
||||
const wchar_t *helptext = L"This tool creates bitmap fonts for the Irrlicht Engine\n\n"
|
||||
|
||||
L"First select a character encoding from the list, then choose the font, "
|
||||
L"size, and whether you'd like bold, italic, antialiasing and an alpha channel. "
|
||||
L"In Windows, antialiasing will be ignored for small fonts\n\n"
|
||||
|
||||
L"Then select a texture width and height. If the output exceeds this then more than "
|
||||
L"one image will be created. You can use the scrollbar at the top of the screen to "
|
||||
L"preview them. Most modern graphics cards will support up to 2048x2048, "
|
||||
L"keep in mind that more images means worse performance when drawing text!\n\n"
|
||||
|
||||
L"If you want a vector font rather than a bitmap font, check the vector box. "
|
||||
L"Vector fonts are stored in system memory while bitmap fonts are in video ram\n\n"
|
||||
|
||||
L"Click create to preview your font, this may take lots of time and memory "
|
||||
L"when making a font with a lot of characters, please be patient!\n\n"
|
||||
|
||||
L"Now you're ready to give your font a name, select a format and click save.\n\n"
|
||||
L"To load your font in Irrlicht, simply use env->getFont(\"Myfont.xml\");\n\n"
|
||||
|
||||
L"That's all, have fun :-)";
|
||||
|
||||
#ifdef _IRR_WINDOWS
|
||||
const wchar_t *completeText = L"Font created"
|
||||
#else
|
||||
const wchar_t *completeText = L"Font created\n\n"
|
||||
L"Please note that anti-aliasing under X11 is controlled by the system "
|
||||
L"configuration, so if your system is set to use anti-aliasing, then so "
|
||||
L"will any fonts you create with FontTool";
|
||||
#endif
|
||||
|
||||
enum MYGUI
|
||||
{
|
||||
MYGUI_CHARSET = 100,
|
||||
MYGUI_FONTNAME,
|
||||
MYGUI_SIZE,
|
||||
MYGUI_TEXWIDTH,
|
||||
MYGUI_TEXHEIGHT,
|
||||
MYGUI_BOLD,
|
||||
MYGUI_ITALIC,
|
||||
MYGUI_ANTIALIAS,
|
||||
MYGUI_ALPHA,
|
||||
MYGUI_VECTOR,
|
||||
MYGUI_FILENAME,
|
||||
MYGUI_FORMAT,
|
||||
MYGUI_CREATE,
|
||||
MYGUI_SAVE,
|
||||
MYGUI_IMAGE,
|
||||
MYGUI_CURRENTIMAGE,
|
||||
MYGUI_HELPBUTTON
|
||||
};
|
||||
|
||||
|
||||
// event reciever
|
||||
class MyEventReceiver : public IEventReceiver
|
||||
{
|
||||
public:
|
||||
|
||||
MyEventReceiver(IrrlichtDevice* device, CFontTool*& fonttool, CVectorFontTool* &vectool) :
|
||||
Device(device), FontTool(fonttool), VecTool(vectool)
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool OnEvent(const SEvent &event)
|
||||
{
|
||||
if (event.EventType == EET_GUI_EVENT)
|
||||
{
|
||||
s32 id = event.GUIEvent.Caller->getID();
|
||||
IGUIEnvironment* env = Device->getGUIEnvironment();
|
||||
|
||||
switch(event.GUIEvent.EventType)
|
||||
{
|
||||
case EGET_SCROLL_BAR_CHANGED:
|
||||
if (id == MYGUI_CURRENTIMAGE)
|
||||
{
|
||||
IGUIImage* img = (IGUIImage*)env->getRootGUIElement()->getElementFromId(MYGUI_IMAGE,true);
|
||||
s32 i = ((IGUIScrollBar*)event.GUIEvent.Caller)->getPos();
|
||||
img->setImage(FontTool->currentTextures[i]);
|
||||
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case EGET_COMBO_BOX_CHANGED:
|
||||
if (id == MYGUI_CHARSET)
|
||||
{
|
||||
IGUIComboBox* cbo = (IGUIComboBox*)event.GUIEvent.Caller;
|
||||
IGUIComboBox* cbo_1 = (IGUIComboBox*)env->getRootGUIElement()->getElementFromId(MYGUI_FONTNAME,true);
|
||||
core::stringw str=FontTool->FontNames[cbo_1->getSelected()];
|
||||
u32 j=0;
|
||||
FontTool->selectCharSet(cbo->getSelected());
|
||||
// rebuild font list
|
||||
cbo = cbo_1;
|
||||
cbo->clear();
|
||||
for (u32 i=0; i < FontTool->FontNames.size(); ++i){
|
||||
cbo->addItem(FontTool->FontNames[i].c_str());
|
||||
if(FontTool->FontNames[i]==str) j=i;
|
||||
}
|
||||
cbo->setSelected(j);
|
||||
return true;
|
||||
}
|
||||
else if(id==MYGUI_FONTNAME){
|
||||
IGUIComboBox* cbo = (IGUIComboBox*)event.GUIEvent.Caller;
|
||||
std::cout << FontTool->FontNames[cbo->getSelected()].c_str() << std::endl;
|
||||
}
|
||||
break;
|
||||
case EGET_CHECKBOX_CHANGED:
|
||||
if (id == MYGUI_VECTOR)
|
||||
{
|
||||
IGUICheckBox* chk = (IGUICheckBox*)event.GUIEvent.Caller;
|
||||
|
||||
IGUIComboBox *cbo = (IGUIComboBox*)env->getRootGUIElement()->getElementFromId(MYGUI_FORMAT,true);
|
||||
cbo->clear();
|
||||
|
||||
if (chk->isChecked() && VecTool)
|
||||
{
|
||||
// vector formats
|
||||
for (s32 i=0; fileformats[i] != 0; ++i)
|
||||
cbo->addItem( core::stringw(vectorfileformats[i]).c_str());
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// bitmap formats
|
||||
if (!FontTool->UseAlphaChannel)
|
||||
{
|
||||
// add non-alpha formats
|
||||
for (s32 i=0; fileformats[i] != 0; ++i)
|
||||
cbo->addItem( core::stringw(fileformats[i]).c_str());
|
||||
}
|
||||
// add formats which support alpha
|
||||
for (s32 i=0; alphafileformats[i] != 0; ++i)
|
||||
cbo->addItem( core::stringw(alphafileformats[i]).c_str());
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case EGET_BUTTON_CLICKED:
|
||||
|
||||
if (id == MYGUI_CREATE)
|
||||
{
|
||||
// create the font with the params
|
||||
IGUIComboBox* cbo = (IGUIComboBox*)env->getRootGUIElement()->getElementFromId(MYGUI_CHARSET, true);
|
||||
int charset = cbo->getSelected();
|
||||
|
||||
cbo = (IGUIComboBox*)env->getRootGUIElement()->getElementFromId(MYGUI_FONTNAME,true);
|
||||
int fontname = cbo->getSelected();
|
||||
|
||||
/*
|
||||
cbo = (IGUIComboBox*)env->getRootGUIElement()->getElementFromId(MYGUI_SIZE,true);
|
||||
int fontsize = cbo->getSelected();
|
||||
*/
|
||||
|
||||
int fontsize=wcstol(((IGUIEditBox*)env->getRootGUIElement()->getElementFromId(MYGUI_SIZE,true))->getText(),NULL,10);
|
||||
|
||||
cbo = (IGUIComboBox*)env->getRootGUIElement()->getElementFromId(MYGUI_TEXWIDTH,true);
|
||||
int texwidth = cbo->getSelected();
|
||||
|
||||
cbo = (IGUIComboBox*)env->getRootGUIElement()->getElementFromId(MYGUI_TEXHEIGHT,true);
|
||||
int texheight = cbo->getSelected();
|
||||
|
||||
IGUICheckBox* chk = (IGUICheckBox*)env->getRootGUIElement()->getElementFromId(MYGUI_BOLD,true);
|
||||
bool bold = chk->isChecked();
|
||||
chk = (IGUICheckBox*)env->getRootGUIElement()->getElementFromId(MYGUI_ITALIC,true);
|
||||
bool italic = chk->isChecked();
|
||||
|
||||
chk = (IGUICheckBox*)env->getRootGUIElement()->getElementFromId(MYGUI_ALPHA,true);
|
||||
bool alpha = chk->isChecked();
|
||||
|
||||
chk = (IGUICheckBox*)env->getRootGUIElement()->getElementFromId(MYGUI_ANTIALIAS,true);
|
||||
bool aa = chk->isChecked();
|
||||
|
||||
chk = (IGUICheckBox*)env->getRootGUIElement()->getElementFromId(201,true);
|
||||
bool usedOnly = chk->isChecked();
|
||||
|
||||
chk = (IGUICheckBox*)env->getRootGUIElement()->getElementFromId(202,true);
|
||||
bool excludeLatin = chk->isChecked();
|
||||
|
||||
// vector fonts disabled
|
||||
//chk = (IGUICheckBox*)env->getRootGUIElement()->getElementFromId(MYGUI_VECTOR,true);
|
||||
bool vec = false;//chk->isChecked();
|
||||
|
||||
FontTool->makeBitmapFont(fontname, charset, /*FontTool->FontSizes[fontsize]*/ fontsize, texturesizes[texwidth], texturesizes[texheight], bold, italic, aa, alpha, usedOnly, excludeLatin);
|
||||
|
||||
IGUIScrollBar* scrl = (IGUIScrollBar*)env->getRootGUIElement()->getElementFromId(MYGUI_CURRENTIMAGE,true);
|
||||
scrl->setMax(FontTool->currentTextures.size() == 0 ? 0 : FontTool->currentTextures.size()-1);
|
||||
|
||||
if (FontTool->currentTextures.size() > 0)
|
||||
{
|
||||
IGUIImage* img = (IGUIImage*)env->getRootGUIElement()->getElementFromId(MYGUI_IMAGE,true);
|
||||
img->setImage(FontTool->currentTextures[0]);
|
||||
scrl->setPos(0);
|
||||
}
|
||||
|
||||
// make sure users pick a file format that supports alpha channel
|
||||
cbo = (IGUIComboBox*)env->getRootGUIElement()->getElementFromId(MYGUI_FORMAT,true);
|
||||
cbo->clear();
|
||||
|
||||
if (vec)
|
||||
{
|
||||
// add vector formats
|
||||
for (s32 i=0; fileformats[i] != 0; ++i)
|
||||
cbo->addItem( core::stringw(vectorfileformats[i]).c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!alpha)
|
||||
{
|
||||
// add non-alpha formats
|
||||
for (s32 i=0; fileformats[i] != 0; ++i)
|
||||
cbo->addItem( core::stringw(fileformats[i]).c_str());
|
||||
}
|
||||
// add formats which support alpha
|
||||
for (s32 i=0; alphafileformats[i] != 0; ++i)
|
||||
cbo->addItem( core::stringw(alphafileformats[i]).c_str());
|
||||
}
|
||||
if (VecTool)
|
||||
{
|
||||
delete VecTool;
|
||||
VecTool = 0;
|
||||
}
|
||||
if (vec)
|
||||
{
|
||||
VecTool = new CVectorFontTool(FontTool);
|
||||
}
|
||||
|
||||
/* Message box letting the user know the process is complete */
|
||||
env->addMessageBox(L"Create", completeText);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (id == MYGUI_SAVE)
|
||||
{
|
||||
IGUIEditBox *edt = (IGUIEditBox*)env->getRootGUIElement()->getElementFromId(MYGUI_FILENAME,true);
|
||||
core::stringc name = edt->getText();
|
||||
|
||||
IGUIComboBox *fmt = (IGUIComboBox*)env->getRootGUIElement()->getElementFromId(MYGUI_FORMAT,true);
|
||||
core::stringc format = fmt->getItem(fmt->getSelected());
|
||||
|
||||
// vector fonts disabled
|
||||
// IGUICheckBox *chk = (IGUICheckBox*)env->getRootGUIElement()->getElementFromId(MYGUI_VECTOR,true);
|
||||
// bool vec = chk->isChecked();
|
||||
bool vec = false;
|
||||
|
||||
if (vec && VecTool)
|
||||
VecTool->saveVectorFont(name.c_str(), format.c_str());
|
||||
else
|
||||
FontTool->saveBitmapFont(name.c_str(), format.c_str());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (id == MYGUI_HELPBUTTON)
|
||||
{
|
||||
env->addMessageBox(L"Irrlicht Unicode Font Tool", helptext);
|
||||
return true;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
IrrlichtDevice* Device;
|
||||
CFontTool* FontTool;
|
||||
CVectorFontTool* VecTool;
|
||||
|
||||
};
|
||||
|
||||
void createGUI(IrrlichtDevice* device, CFontTool* fc)
|
||||
{
|
||||
// Scaling factor to allow a larger font to be used
|
||||
float scale = 2.0f;
|
||||
io::path previous_cwd = device->getFileSystem()->getWorkingDirectory();
|
||||
|
||||
gui::IGUIEnvironment *env = device->getGUIEnvironment();
|
||||
gui::IGUIFont *font = env->getFont(io::path("../../../data/fonts/StkFont.xml"));
|
||||
device->getGUIEnvironment()->getSkin()->setFont(font);
|
||||
|
||||
//env->getSkin()->setSize((gui::EGUI_DEFAULT_SIZE, 24);
|
||||
// change transparency of skin
|
||||
for (s32 i=0; i<gui::EGDC_COUNT ; ++i)
|
||||
{
|
||||
video::SColor col = env->getSkin()->getColor((gui::EGUI_DEFAULT_COLOR)i);
|
||||
col.setAlpha(255);
|
||||
env->getSkin()->setColor((gui::EGUI_DEFAULT_COLOR)i, col);
|
||||
}
|
||||
|
||||
IGUIWindow *win = env->addWindow( core::rect<s32>(10,HEIGHT/30,int(scale*WIDTH)/4,HEIGHT-100), false, L"Font Creator");
|
||||
win->getCloseButton()->setVisible(false);
|
||||
|
||||
s32 xs=10,xp=xs, yp=HEIGHT/20, h=HEIGHT/20;
|
||||
|
||||
env->addStaticText(L"Charset", core::rect<s32>(int(scale*xp),yp,int(scale*90),yp+h),false,false, win);
|
||||
|
||||
xp+=60;
|
||||
|
||||
// charset combo
|
||||
gui::IGUIComboBox* cbo = env->addComboBox( core::rect<s32>(int(scale*xp),yp,int(scale*180),yp+h),win, MYGUI_CHARSET);
|
||||
for (u32 i=0; i < fc->CharSets.size(); ++i)
|
||||
cbo->addItem(fc->CharSets[i].c_str());
|
||||
|
||||
yp += (s32)(h*1.5f);
|
||||
xp = xs;
|
||||
|
||||
env->addStaticText(L"Font", core::rect<s32>(int(scale*xp),yp,int(scale*50),yp+h),false,false, win);
|
||||
|
||||
xp+=60;
|
||||
|
||||
// font name combo
|
||||
cbo = env->addComboBox( core::rect<s32>(int(scale*xp),yp,int(scale*180),yp+h),win, MYGUI_FONTNAME);
|
||||
for (u32 i=0; i < fc->FontNames.size(); ++i){
|
||||
cbo->addItem(fc->FontNames[i].c_str());
|
||||
if(fc->FontNames[i] == L"\u6587\u6CC9\u9A7F\u5FAE\u7C73\u9ED1") cbo->setSelected(i); //auto select wqy-microhei
|
||||
}
|
||||
|
||||
yp += (s32)(h*1.5f);
|
||||
xp = xs;
|
||||
|
||||
env->addStaticText(L"Size", core::rect<s32>(int(scale*xp),yp,int(scale*(50+xp)),yp+h),false,false, win);
|
||||
|
||||
xp += 60;
|
||||
|
||||
/*
|
||||
// font size combo
|
||||
cbo = env->addComboBox( core::rect<s32>(xp,yp,xp+50,yp+h),win, MYGUI_SIZE);
|
||||
for (s32 i=0; fc->FontSizes[i] != 0; ++i)
|
||||
cbo->addItem( ((core::stringw(fc->FontSizes[i])) + L"pt").c_str()); */
|
||||
|
||||
env->addEditBox(L"24",core::rect<s32>(int(scale*xp),yp,int(scale*(xp+70)),yp+h), true, win, MYGUI_SIZE);
|
||||
xp += int(scale*80);
|
||||
env->addStaticText(L"pt", core::rect<s32>(xp,yp,xp+50,yp+h),false,false,win);
|
||||
|
||||
xp = xs;
|
||||
yp += (s32)(h*1.5f);
|
||||
|
||||
// bold checkbox
|
||||
env->addCheckBox(false, core::rect<s32>(xp,yp,int(scale*(xp+50)),yp+h),win, MYGUI_BOLD, L"Bold");
|
||||
|
||||
xp += int(45*scale);
|
||||
|
||||
// italic checkbox
|
||||
env->addCheckBox(false, core::rect<s32>(xp,yp,int(scale*(xp+50)),yp+h),win, MYGUI_ITALIC, L"Italic");
|
||||
|
||||
xp += int(55*scale);
|
||||
|
||||
// AA checkbox
|
||||
env->addCheckBox(false, core::rect<s32>(xp,yp,int(scale*(xp+50)),yp+h),win, MYGUI_ANTIALIAS, L"AA");
|
||||
|
||||
xp += int(scale * 40);
|
||||
|
||||
// Alpha checkbox
|
||||
env->addCheckBox(false, core::rect<s32>(xp,yp,int(scale*(xp+50)),yp+h),win, MYGUI_ALPHA, L"Alpha");
|
||||
|
||||
xp = xs;
|
||||
yp += (s32)(h*1.5f);
|
||||
|
||||
//new
|
||||
|
||||
env->addCheckBox(false, core::rect<s32>(xp,yp,int(scale*(xp+200)),yp+h),win, 201, L"Only used characters")->setChecked(false);
|
||||
yp += (s32)(h*1.5f);
|
||||
|
||||
env->addCheckBox(false, core::rect<s32>(xp,yp,int(scale*(xp+200)),yp+h),win, 202, L"Exclude basic latin");
|
||||
yp += (s32)(h*1.5f);
|
||||
|
||||
/*
|
||||
// vector fonts can't be loaded yet
|
||||
env->addCheckBox(false, core::rect<s32>(xp,yp,xp+200,yp+h),win, MYGUI_VECTOR, L"Vector Font");
|
||||
|
||||
yp += (s32)(h*1.5f);
|
||||
*/
|
||||
|
||||
env->addStaticText(L"Max Width:", core::rect<s32>(xp,yp,int(scale*100),yp+h),false,false, win);
|
||||
|
||||
xp += int(scale*90);
|
||||
|
||||
// texture widths
|
||||
cbo = env->addComboBox( core::rect<s32>(xp,yp,xp+int(scale*80),yp+h),win, MYGUI_TEXWIDTH);
|
||||
for (s32 i=0; texturesizes[i] != 0; ++i)
|
||||
cbo->addItem( ((core::stringw(texturesizes[i])) + L" wide").c_str());
|
||||
cbo->setSelected(2); // 128, 256, 512 --> make 512 the default
|
||||
xp=xs;
|
||||
yp += (s32)(h*1.5f);
|
||||
|
||||
env->addStaticText(L"Max Height:", core::rect<s32>(xp,yp,int(scale*100),yp+h),false,false, win);
|
||||
|
||||
xp += int(scale*90);
|
||||
|
||||
// texture height
|
||||
cbo = env->addComboBox( core::rect<s32>(xp,yp,xp+int(scale*80),yp+h),win, MYGUI_TEXHEIGHT);
|
||||
for (s32 i=0; texturesizes[i] != 0; ++i)
|
||||
cbo->addItem( ((core::stringw(texturesizes[i])) + L" tall").c_str());
|
||||
cbo->setSelected(2); // 512 as default
|
||||
// file name
|
||||
xp = xs;
|
||||
yp += (s32)(h*1.5f);
|
||||
env->addStaticText(L"Filename", core::rect<s32>(xp,yp,int(scale*100),yp+h),false,false, win);
|
||||
xp += int(scale*90);
|
||||
env->addEditBox(L"wqyMicroHei",core::rect<s32>(xp,yp,xp+int(scale*80),yp+h), true, win, MYGUI_FILENAME);
|
||||
|
||||
// file format
|
||||
xp = xs;
|
||||
yp += (s32)(h*1.5f);
|
||||
env->addStaticText(L"File Format", core::rect<s32>(xp,yp,int(scale*100),yp+h),false,false, win);
|
||||
xp += int(scale*90);
|
||||
|
||||
cbo = env->addComboBox( core::rect<s32>(xp,yp,xp+int(scale*80),yp+h),win, MYGUI_FORMAT);
|
||||
for (s32 i=0; fileformats[i] != 0; ++i)
|
||||
cbo->addItem( core::stringw(fileformats[i]).c_str());
|
||||
for (s32 i=0; alphafileformats[i] != 0; ++i)
|
||||
cbo->addItem( core::stringw(alphafileformats[i]).c_str());
|
||||
cbo->setSelected(2); // bmp, ppm, png, ... --> select pn
|
||||
xp = xs;
|
||||
yp += h*2;
|
||||
|
||||
// create button
|
||||
env->addButton( core::rect<s32>(xp,yp,int(scale*(xp+50)),yp+h),win, MYGUI_CREATE, L"Create");
|
||||
|
||||
xp += int(scale*60);
|
||||
|
||||
// save button
|
||||
env->addButton( core::rect<s32>(xp,yp,xp+int(scale*50),yp+h),win, MYGUI_SAVE, L"Save");
|
||||
|
||||
xp += int(scale*60);
|
||||
|
||||
// help button
|
||||
env->addButton( core::rect<s32>(xp,yp,xp+int(scale*50),yp+h),win, MYGUI_HELPBUTTON, L"Help");
|
||||
|
||||
// font image
|
||||
gui::IGUIImage *img = env->addImage(0, core::position2d<s32>(0,0), true,0, MYGUI_IMAGE);
|
||||
img->setRelativePosition(core::rect<s32>(0,HEIGHT/30,WIDTH,HEIGHT));
|
||||
|
||||
// font scrollbar
|
||||
IGUIScrollBar *scrl= env->addScrollBar(true,core::rect<s32>(0,0,WIDTH,HEIGHT/30),0, MYGUI_CURRENTIMAGE);
|
||||
scrl->setMax(0);
|
||||
scrl->setSmallStep(1);
|
||||
|
||||
yp += h*3;
|
||||
|
||||
env->getRootGUIElement()->bringToFront(win);
|
||||
win->setRelativePosition( core::rect<s32>(0,HEIGHT/30,int(scale*200),yp));
|
||||
}
|
||||
|
||||
int main(int argc,char **argv)
|
||||
{
|
||||
SIrrlichtCreationParameters p;
|
||||
p.DriverType = video::EDT_OPENGL;
|
||||
p.WindowSize = core::dimension2du(WIDTH, HEIGHT);
|
||||
p.Bits = 16;
|
||||
p.Fullscreen = false;
|
||||
p.Stencilbuffer = false;
|
||||
p.Vsync = false;
|
||||
p.EventReceiver = NULL;
|
||||
p.FileSystem = NULL;
|
||||
p.ForceLegacyDevice = true;
|
||||
|
||||
IrrlichtDevice *device = createDeviceEx(p);
|
||||
|
||||
video::IVideoDriver* driver = device->getVideoDriver();
|
||||
scene::ISceneManager* smgr = device->getSceneManager();
|
||||
gui::IGUIEnvironment *env = device->getGUIEnvironment();
|
||||
|
||||
// create font tool
|
||||
CFontTool *fc = new CFontTool(device);
|
||||
CVectorFontTool *vc = 0;
|
||||
|
||||
MyEventReceiver events(device,fc,vc);
|
||||
device->setEventReceiver(&events);
|
||||
|
||||
createGUI(device, fc);
|
||||
|
||||
for(int i=1; i<argc; i++)
|
||||
{
|
||||
if(!strcmp(argv[i],"-c") && i<argc-1)
|
||||
{
|
||||
i++;
|
||||
if(setUsedCharacters(argv[i]))
|
||||
{
|
||||
IGUICheckBox *box =
|
||||
dynamic_cast<IGUICheckBox*>(device->getGUIEnvironment()
|
||||
->getRootGUIElement()
|
||||
->getElementFromId(201, true));
|
||||
box->setChecked(true);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// Old style: just a single parameter, assume it's a file name with pot files in it
|
||||
if(LoadPoFiles(argv[i]))
|
||||
{
|
||||
IGUICheckBox *box =
|
||||
dynamic_cast<IGUICheckBox*>(device->getGUIEnvironment()
|
||||
->getRootGUIElement()
|
||||
->getElementFromId(201, true));
|
||||
box->setChecked(true);
|
||||
}
|
||||
}
|
||||
} // for i <argc
|
||||
|
||||
while(device->run())
|
||||
{
|
||||
device->sleep(50);
|
||||
if (device->isWindowActive())
|
||||
{
|
||||
|
||||
driver->beginScene(true, true, video::SColor(0,200,200,200));
|
||||
smgr->drawAll();
|
||||
env->drawAll();
|
||||
driver->endScene();
|
||||
}
|
||||
}
|
||||
|
||||
// drop the font tool and resources
|
||||
fc->drop();
|
||||
|
||||
device->drop();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,6 +0,0 @@
|
||||
data/po/ko.po
|
||||
data/po/vi.po
|
||||
data/po/zh_CN.po
|
||||
data/po/zh_TW.po
|
||||
data/po/uk.po
|
||||
data/po/ky.po
|